ref: f4960326869f9bc63b8f7286ee5a85f951d02cdb
parent: 18b54ef468dd76028175dd2082673739263bcc9d
parent: 1aa46abbdfc31e02e139eb0fa8b73b9527006e04
author: Yunqing Wang <[email protected]>
date: Fri Apr 7 12:46:22 EDT 2017
Merge "VP9 motion vector unit test"
--- a/test/test-data.mk
+++ b/test/test-data.mk
@@ -23,6 +23,7 @@
LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += noisy_clip_640_360.y4m
LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += rush_hour_444.y4m
LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += screendata.y4m
+LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += niklas_640_480_30.yuv
# Test vectors
LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-001.ivf
@@ -814,7 +815,6 @@
LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += macmarcomoving_640_480_30.yuv
LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += macmarcostationary_640_480_30.yuv
LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += niklas_1280_720_30.yuv
-LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += niklas_640_480_30.yuv
LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += tacomanarrows_640_480_30.yuv
LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += tacomasmallcameramovement_640_480_30.yuv
LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += thaloundeskmtg_640_480_30.yuv
--- a/test/test.mk
+++ b/test/test.mk
@@ -48,6 +48,7 @@
LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += vp9_lossless_test.cc
LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += vp9_end_to_end_test.cc
LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += vp9_ethread_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += vp9_motion_vector_test.cc
LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += level_test.cc
LIBVPX_TEST_SRCS-yes += decode_test_driver.cc
--- /dev/null
+++ b/test/vp9_motion_vector_test.cc
@@ -1,0 +1,97 @@
+/*
+ * Copyright (c) 2017 The WebM project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "test/codec_factory.h"
+#include "test/encode_test_driver.h"
+#include "test/util.h"
+#include "test/yuv_video_source.h"
+
+namespace {
+#define MAX_EXTREME_MV 1
+#define MIN_EXTREME_MV 2
+
+// Encoding modes
+const libvpx_test::TestMode kEncodingModeVectors[] = {
+ ::libvpx_test::kTwoPassGood, ::libvpx_test::kOnePassGood,
+ ::libvpx_test::kRealTime,
+};
+
+// Encoding speeds
+const int kCpuUsedVectors[] = { 0, 1, 2, 3, 4, 5, 6 };
+
+// MV test modes: 1 - always use maximum MV; 2 - always use minimum MV.
+const int kMVTestModes[] = { MAX_EXTREME_MV, MIN_EXTREME_MV };
+
+class MotionVectorTestLarge
+ : public ::libvpx_test::EncoderTest,
+ public ::libvpx_test::CodecTestWith3Params<libvpx_test::TestMode, int,
+ int> {
+ protected:
+ MotionVectorTestLarge()
+ : EncoderTest(GET_PARAM(0)), encoding_mode_(GET_PARAM(1)),
+ cpu_used_(GET_PARAM(2)), mv_test_mode_(GET_PARAM(3)) {}
+
+ virtual ~MotionVectorTestLarge() {}
+
+ virtual void SetUp() {
+ InitializeConfig();
+ SetMode(encoding_mode_);
+ if (encoding_mode_ != ::libvpx_test::kRealTime) {
+ cfg_.g_lag_in_frames = 3;
+ cfg_.rc_end_usage = VPX_VBR;
+ } else {
+ cfg_.g_lag_in_frames = 0;
+ cfg_.rc_end_usage = VPX_CBR;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 600;
+ }
+ }
+
+ virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
+ ::libvpx_test::Encoder *encoder) {
+ if (video->frame() == 1) {
+ encoder->Control(VP8E_SET_CPUUSED, cpu_used_);
+ encoder->Control(VP9E_ENABLE_MOTION_VECTOR_UNIT_TEST, mv_test_mode_);
+ if (encoding_mode_ != ::libvpx_test::kRealTime) {
+ encoder->Control(VP8E_SET_ENABLEAUTOALTREF, 1);
+ encoder->Control(VP8E_SET_ARNR_MAXFRAMES, 7);
+ encoder->Control(VP8E_SET_ARNR_STRENGTH, 5);
+ encoder->Control(VP8E_SET_ARNR_TYPE, 3);
+ }
+ }
+ }
+
+ libvpx_test::TestMode encoding_mode_;
+ int cpu_used_;
+ int mv_test_mode_;
+};
+
+TEST_P(MotionVectorTestLarge, OverallTest) {
+ cfg_.rc_target_bitrate = 24000;
+ cfg_.g_profile = 0;
+ init_flags_ = VPX_CODEC_USE_PSNR;
+
+ testing::internal::scoped_ptr<libvpx_test::VideoSource> video;
+ video.reset(new libvpx_test::YUVVideoSource(
+ "niklas_640_480_30.yuv", VPX_IMG_FMT_I420, 3840, 2160, // 2048, 1080,
+ 30, 1, 0, 5));
+
+ ASSERT_TRUE(video.get() != NULL);
+ ASSERT_NO_FATAL_FAILURE(RunLoop(video.get()));
+}
+
+VP9_INSTANTIATE_TEST_CASE(MotionVectorTestLarge,
+ ::testing::ValuesIn(kEncodingModeVectors),
+ ::testing::ValuesIn(kCpuUsedVectors),
+ ::testing::ValuesIn(kMVTestModes));
+} // namespace
--- a/vp9/common/vp9_debugmodes.c
+++ b/vp9/common/vp9_debugmodes.c
@@ -34,7 +34,7 @@
for (mi_row = 0; mi_row < rows; mi_row++) {
fprintf(file, "%c ", prefix);
for (mi_col = 0; mi_col < cols; mi_col++) {
- fprintf(file, "%2d ", *((int *)((char *)(mi[0]) + member_offset)));
+ fprintf(file, "%2d ", *((char *)((char *)(mi[0]) + member_offset)));
mi++;
}
fprintf(file, "\n");
--- a/vp9/encoder/vp9_encoder.h
+++ b/vp9/encoder/vp9_encoder.h
@@ -269,6 +269,7 @@
int row_mt;
unsigned int row_mt_bit_exact;
+ unsigned int motion_vector_unit_test;
} VP9EncoderConfig;
static INLINE int is_lossless_requested(const VP9EncoderConfig *cfg) {
--- a/vp9/encoder/vp9_mcomp.c
+++ b/vp9/encoder/vp9_mcomp.c
@@ -21,6 +21,7 @@
#include "vpx_ports/mem.h"
#include "vp9/common/vp9_common.h"
+#include "vp9/common/vp9_mvref_common.h"
#include "vp9/common/vp9_reconinter.h"
#include "vp9/encoder/vp9_encoder.h"
@@ -2476,4 +2477,86 @@
var = vp9_get_mvpred_var(x, tmp_mv, ref_mv, fn_ptr, 1);
return var;
+}
+
+// Note(yunqingwang): The following 2 functions are only used in the motion
+// vector unit test, which return extreme motion vectors allowed by the MV
+// limits.
+#define COMMON_MV_TEST \
+ SETUP_SUBPEL_SEARCH; \
+ \
+ (void)error_per_bit; \
+ (void)vfp; \
+ (void)z; \
+ (void)src_stride; \
+ (void)y; \
+ (void)y_stride; \
+ (void)second_pred; \
+ (void)w; \
+ (void)h; \
+ (void)offset; \
+ (void)mvjcost; \
+ (void)mvcost; \
+ (void)sse1; \
+ (void)distortion; \
+ \
+ (void)halfiters; \
+ (void)quarteriters; \
+ (void)eighthiters; \
+ (void)whichdir; \
+ (void)allow_hp; \
+ (void)forced_stop; \
+ (void)hstep; \
+ (void)rr; \
+ (void)rc; \
+ \
+ (void)tr; \
+ (void)tc; \
+ (void)sse; \
+ (void)thismse; \
+ (void)cost_list;
+
+// Return the maximum MV.
+uint32_t vp9_return_max_sub_pixel_mv(
+ const MACROBLOCK *x, MV *bestmv, const MV *ref_mv, int allow_hp,
+ int error_per_bit, const vp9_variance_fn_ptr_t *vfp, int forced_stop,
+ int iters_per_step, int *cost_list, int *mvjcost, int *mvcost[2],
+ uint32_t *distortion, uint32_t *sse1, const uint8_t *second_pred, int w,
+ int h) {
+ COMMON_MV_TEST;
+
+ (void)minr;
+ (void)minc;
+
+ bestmv->row = maxr;
+ bestmv->col = maxc;
+ besterr = 0;
+
+ // In the sub-pel motion search, if hp is not used, then the last bit of mv
+ // has to be 0.
+ lower_mv_precision(bestmv, allow_hp && use_mv_hp(ref_mv));
+
+ return besterr;
+}
+// Return the minimum MV.
+uint32_t vp9_return_min_sub_pixel_mv(
+ const MACROBLOCK *x, MV *bestmv, const MV *ref_mv, int allow_hp,
+ int error_per_bit, const vp9_variance_fn_ptr_t *vfp, int forced_stop,
+ int iters_per_step, int *cost_list, int *mvjcost, int *mvcost[2],
+ uint32_t *distortion, uint32_t *sse1, const uint8_t *second_pred, int w,
+ int h) {
+ COMMON_MV_TEST;
+
+ (void)maxr;
+ (void)maxc;
+
+ bestmv->row = minr;
+ bestmv->col = minc;
+ besterr = 0;
+
+ // In the sub-pel motion search, if hp is not used, then the last bit of mv
+ // has to be 0.
+ lower_mv_precision(bestmv, allow_hp && use_mv_hp(ref_mv));
+
+ return besterr;
}
--- a/vp9/encoder/vp9_mcomp.h
+++ b/vp9/encoder/vp9_mcomp.h
@@ -81,6 +81,8 @@
extern fractional_mv_step_fp vp9_find_best_sub_pixel_tree_pruned_more;
extern fractional_mv_step_fp vp9_find_best_sub_pixel_tree_pruned_evenmore;
extern fractional_mv_step_fp vp9_skip_sub_pixel_tree;
+extern fractional_mv_step_fp vp9_return_max_sub_pixel_mv;
+extern fractional_mv_step_fp vp9_return_min_sub_pixel_mv;
typedef int (*vp9_full_search_fn_t)(const MACROBLOCK *x, const MV *ref_mv,
int sad_per_bit, int distance,
--- a/vp9/encoder/vp9_rdopt.c
+++ b/vp9/encoder/vp9_rdopt.c
@@ -3241,6 +3241,9 @@
if (best_rd < mode_threshold[mode_index]) continue;
+ // This is only used in motion vector unit test.
+ if (cpi->oxcf.motion_vector_unit_test && ref_frame == INTRA_FRAME) continue;
+
if (sf->motion_field_mode_search) {
const int mi_width = VPXMIN(num_8x8_blocks_wide_lookup[bsize],
tile_info->mi_col_end - mi_col);
@@ -3923,6 +3926,9 @@
#endif
&rd_thresh_freq_fact[ref_index]))
continue;
+
+ // This is only used in motion vector unit test.
+ if (cpi->oxcf.motion_vector_unit_test && ref_frame == INTRA_FRAME) continue;
comp_pred = second_ref_frame > INTRA_FRAME;
if (comp_pred) {
--- a/vp9/encoder/vp9_speed_features.c
+++ b/vp9/encoder/vp9_speed_features.c
@@ -609,6 +609,12 @@
sf->allow_exhaustive_searches = 0;
sf->adaptive_pred_interp_filter = 0;
}
+
+ // This is only used in motion vector unit test.
+ if (cpi->oxcf.motion_vector_unit_test == 1)
+ cpi->find_fractional_mv_step = vp9_return_max_sub_pixel_mv;
+ else if (cpi->oxcf.motion_vector_unit_test == 2)
+ cpi->find_fractional_mv_step = vp9_return_min_sub_pixel_mv;
}
void vp9_set_speed_features_framesize_independent(VP9_COMP *cpi) {
@@ -779,4 +785,10 @@
sf->allow_exhaustive_searches = 0;
sf->adaptive_pred_interp_filter = 0;
}
+
+ // This is only used in motion vector unit test.
+ if (cpi->oxcf.motion_vector_unit_test == 1)
+ cpi->find_fractional_mv_step = vp9_return_max_sub_pixel_mv;
+ else if (cpi->oxcf.motion_vector_unit_test == 2)
+ cpi->find_fractional_mv_step = vp9_return_min_sub_pixel_mv;
}
--- a/vp9/vp9_cx_iface.c
+++ b/vp9/vp9_cx_iface.c
@@ -53,6 +53,7 @@
int render_height;
unsigned int row_mt;
unsigned int row_mt_bit_exact;
+ unsigned int motion_vector_unit_test;
};
static struct vp9_extracfg default_extra_cfg = {
@@ -86,6 +87,7 @@
0, // render height
0, // row_mt
0, // row_mt_bit_exact
+ 0, // motion_vector_unit_test
};
struct vpx_codec_alg_priv {
@@ -251,6 +253,7 @@
RANGE_CHECK(extra_cfg, row_mt, 0, 1);
RANGE_CHECK(extra_cfg, row_mt_bit_exact, 0, 1);
+ RANGE_CHECK(extra_cfg, motion_vector_unit_test, 0, 2);
RANGE_CHECK(extra_cfg, enable_auto_alt_ref, 0, 2);
RANGE_CHECK(extra_cfg, cpu_used, -8, 8);
RANGE_CHECK_HI(extra_cfg, noise_sensitivity, 6);
@@ -562,6 +565,7 @@
oxcf->row_mt = extra_cfg->row_mt;
oxcf->row_mt_bit_exact = extra_cfg->row_mt_bit_exact;
+ oxcf->motion_vector_unit_test = extra_cfg->motion_vector_unit_test;
for (sl = 0; sl < oxcf->ss_number_layers; ++sl) {
#if CONFIG_SPATIAL_SVC
@@ -865,6 +869,14 @@
return update_extra_cfg(ctx, &extra_cfg);
}
+static vpx_codec_err_t ctrl_enable_motion_vector_unit_test(
+ vpx_codec_alg_priv_t *ctx, va_list args) {
+ struct vp9_extracfg extra_cfg = ctx->extra_cfg;
+ extra_cfg.motion_vector_unit_test =
+ CAST(VP9E_ENABLE_MOTION_VECTOR_UNIT_TEST, args);
+ return update_extra_cfg(ctx, &extra_cfg);
+}
+
static vpx_codec_err_t ctrl_get_level(vpx_codec_alg_priv_t *ctx, va_list args) {
int *const arg = va_arg(args, int *);
if (arg == NULL) return VPX_CODEC_INVALID_PARAM;
@@ -1622,6 +1634,7 @@
{ VP9E_SET_TARGET_LEVEL, ctrl_set_target_level },
{ VP9E_SET_ROW_MT, ctrl_set_row_mt },
{ VP9E_ENABLE_ROW_MT_BIT_EXACT, ctrl_enable_row_mt_bit_exact },
+ { VP9E_ENABLE_MOTION_VECTOR_UNIT_TEST, ctrl_enable_motion_vector_unit_test },
// Getters
{ VP8E_GET_LAST_QUANTIZER, ctrl_get_quantizer },
--- a/vpx/vp8cx.h
+++ b/vpx/vp8cx.h
@@ -594,6 +594,15 @@
* Supported in codecs: VP8
*/
VP8E_SET_GF_CBR_BOOST_PCT,
+
+ /*!\brief Codec control function to enable the extreme motion vector unit test
+ * in VP9. Please note that this is only used in motion vector unit test.
+ *
+ * 0 : off, 1 : MAX_EXTREME_MV, 2 : MIN_EXTREME_MV
+ *
+ * Supported in codecs: VP9
+ */
+ VP9E_ENABLE_MOTION_VECTOR_UNIT_TEST,
};
/*!\brief vpx 1-D scaling mode
@@ -863,6 +872,9 @@
VPX_CTRL_USE_TYPE(VP9E_GET_LEVEL, int *)
#define VPX_CTRL_VP9E_GET_LEVEL
+
+VPX_CTRL_USE_TYPE(VP9E_ENABLE_MOTION_VECTOR_UNIT_TEST, unsigned int)
+#define VPX_CTRL_VP9E_ENABLE_MOTION_VECTOR_UNIT_TEST
/*!\endcond */
/*! @} - end defgroup vp8_encoder */