Commit ff4fa068 authored by Yunqing Wang's avatar Yunqing Wang

Add the motion vector unit test

This unit test was ported from VP9. To prevent the motion vector out of
range bug, added a motion vector unit test. In the 4k video encoding,
always forced to use extreme motion vectors and also encouraged to use
INTER modes. In the decoding, checked if the motion vector was valid,
and also checked the encoder/decoder mismatch.

Change-Id: I1c72ea7c32a3cec9c67f1bbdc168e60507e57516
parent c1b17f3b
......@@ -523,6 +523,13 @@ enum aome_enc_control_id {
* Experiment: EXT_TILE
*/
AV1E_SET_TILE_ENCODING_MODE,
/*!\brief Codec control function to enable the extreme motion vector unit test
* in AV1. Please note that this is only used in motion vector unit test.
*
* 0 : off, 1 : MAX_EXTREME_MV, 2 : MIN_EXTREME_MV
*/
AV1E_ENABLE_MOTION_VECTOR_UNIT_TEST,
};
/*!\brief aom 1-D scaling mode
......@@ -730,6 +737,10 @@ AOM_CTRL_USE_TYPE(AV1E_SET_ANS_WINDOW_SIZE_LOG2, unsigned int)
AOM_CTRL_USE_TYPE(AV1E_SET_TILE_ENCODING_MODE, unsigned int)
#define AOM_CTRL_AV1E_SET_TILE_ENCODING_MODE
AOM_CTRL_USE_TYPE(AV1E_ENABLE_MOTION_VECTOR_UNIT_TEST, unsigned int)
#define AOM_CTRL_AV1E_ENABLE_MOTION_VECTOR_UNIT_TEST
/*!\endcond */
/*! @} - end defgroup aom_encoder */
#ifdef __cplusplus
......
......@@ -81,6 +81,8 @@ struct av1_extracfg {
#if CONFIG_EXT_TILE
unsigned int tile_encoding_mode;
#endif // CONFIG_EXT_TILE
unsigned int motion_vector_unit_test;
};
static struct av1_extracfg default_extra_cfg = {
......@@ -146,6 +148,8 @@ static struct av1_extracfg default_extra_cfg = {
#if CONFIG_EXT_TILE
0, // Tile encoding mode is TILE_NORMAL by default.
#endif // CONFIG_EXT_TILE
0, // motion_vector_unit_test
};
struct aom_codec_alg_priv {
......@@ -259,6 +263,7 @@ static aom_codec_err_t validate_config(aom_codec_alg_priv_t *ctx,
"kf_min_dist not supported in auto mode, use 0 "
"or kf_max_dist instead.");
RANGE_CHECK_HI(extra_cfg, motion_vector_unit_test, 2);
RANGE_CHECK_HI(extra_cfg, enable_auto_alt_ref, 2);
#if CONFIG_EXT_REFS
RANGE_CHECK_HI(extra_cfg, enable_auto_bwd_ref, 2);
......@@ -559,6 +564,7 @@ static aom_codec_err_t set_encoder_config(
oxcf->frame_periodic_boost = extra_cfg->frame_periodic_boost;
oxcf->motion_vector_unit_test = extra_cfg->motion_vector_unit_test;
/*
printf("Current AV1 Settings: \n");
printf("target_bandwidth: %d\n", oxcf->target_bandwidth);
......@@ -887,6 +893,14 @@ static aom_codec_err_t ctrl_set_frame_periodic_boost(aom_codec_alg_priv_t *ctx,
return update_extra_cfg(ctx, &extra_cfg);
}
static aom_codec_err_t ctrl_enable_motion_vector_unit_test(
aom_codec_alg_priv_t *ctx, va_list args) {
struct av1_extracfg extra_cfg = ctx->extra_cfg;
extra_cfg.motion_vector_unit_test =
CAST(AV1E_ENABLE_MOTION_VECTOR_UNIT_TEST, args);
return update_extra_cfg(ctx, &extra_cfg);
}
static aom_codec_err_t encoder_init(aom_codec_ctx_t *ctx,
aom_codec_priv_enc_mr_cfg_t *data) {
aom_codec_err_t res = AOM_CODEC_OK;
......@@ -1492,6 +1506,7 @@ static aom_codec_ctrl_fn_map_t encoder_ctrl_maps[] = {
#if CONFIG_EXT_TILE
{ AV1E_SET_TILE_ENCODING_MODE, ctrl_set_tile_encoding_mode },
#endif // CONFIG_EXT_TILE
{ AV1E_ENABLE_MOTION_VECTOR_UNIT_TEST, ctrl_enable_motion_vector_unit_test },
// Getters
{ AOME_GET_LAST_QUANTIZER, ctrl_get_quantizer },
......
......@@ -280,6 +280,8 @@ typedef struct AV1EncoderConfig {
#if CONFIG_EXT_TILE
unsigned int tile_encoding_mode;
#endif // CONFIG_EXT_TILE
unsigned int motion_vector_unit_test;
} AV1EncoderConfig;
static INLINE int is_lossless_requested(const AV1EncoderConfig *cfg) {
......
......@@ -21,6 +21,7 @@
#include "aom_ports/mem.h"
#include "av1/common/common.h"
#include "av1/common/mvref_common.h"
#include "av1/common/reconinter.h"
#include "av1/encoder/encoder.h"
......@@ -3413,3 +3414,78 @@ int av1_obmc_full_pixel_diamond(const AV1_COMP *cpi, MACROBLOCK *x,
return bestsme;
}
#endif // CONFIG_MOTION_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)src_address; \
(void)src_stride; \
(void)y; \
(void)y_stride; \
(void)second_pred; \
(void)w; \
(void)h; \
(void)use_upsampled_ref; \
(void)offset; \
(void)mvjcost; \
(void)mvcost; \
(void)sse1; \
(void)distortion; \
\
(void)halfiters; \
(void)quarteriters; \
(void)eighthiters; \
(void)whichdir; \
(void)forced_stop; \
(void)hstep; \
\
(void)tr; \
(void)tc; \
(void)sse; \
(void)thismse; \
(void)cost_list;
// Return the maximum MV.
int av1_return_max_sub_pixel_mv(MACROBLOCK *x, const MV *ref_mv, int allow_hp,
int error_per_bit,
const aom_variance_fn_ptr_t *vfp,
int forced_stop, int iters_per_step,
int *cost_list, int *mvjcost, int *mvcost[2],
int *distortion, unsigned int *sse1,
const uint8_t *second_pred, int w, int h,
int use_upsampled_ref) {
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);
return besterr;
}
// Return the minimum MV.
int av1_return_min_sub_pixel_mv(MACROBLOCK *x, const MV *ref_mv, int allow_hp,
int error_per_bit,
const aom_variance_fn_ptr_t *vfp,
int forced_stop, int iters_per_step,
int *cost_list, int *mvjcost, int *mvcost[2],
int *distortion, unsigned int *sse1,
const uint8_t *second_pred, int w, int h,
int use_upsampled_ref) {
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);
return besterr;
}
......@@ -98,6 +98,8 @@ extern fractional_mv_step_fp av1_find_best_sub_pixel_tree;
extern fractional_mv_step_fp av1_find_best_sub_pixel_tree_pruned;
extern fractional_mv_step_fp av1_find_best_sub_pixel_tree_pruned_more;
extern fractional_mv_step_fp av1_find_best_sub_pixel_tree_pruned_evenmore;
extern fractional_mv_step_fp av1_return_max_sub_pixel_mv;
extern fractional_mv_step_fp av1_return_min_sub_pixel_mv;
typedef int (*av1_full_search_fn_t)(const MACROBLOCK *x, const MV *ref_mv,
int sad_per_bit, int distance,
......
......@@ -10019,6 +10019,9 @@ void av1_rd_pick_inter_mode_sb(const AV1_COMP *cpi, TileDataEnc *tile_data,
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;
comp_pred = second_ref_frame > INTRA_FRAME;
if (comp_pred) {
if (!cpi->allow_comp_inter_inter) continue;
......@@ -11742,6 +11745,9 @@ void av1_rd_pick_inter_mode_sub8x8(const struct AV1_COMP *cpi,
tile_data->thresh_freq_fact[bsize][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) {
if (!cpi->allow_comp_inter_inter) continue;
......
......@@ -322,6 +322,12 @@ void av1_set_speed_features_framesize_dependent(AV1_COMP *cpi) {
rd->thresh_mult_sub8x8[i] = INT_MAX;
}
}
// This is only used in motion vector unit test.
if (cpi->oxcf.motion_vector_unit_test == 1)
cpi->find_fractional_mv_step = av1_return_max_sub_pixel_mv;
else if (cpi->oxcf.motion_vector_unit_test == 2)
cpi->find_fractional_mv_step = av1_return_min_sub_pixel_mv;
}
void av1_set_speed_features_framesize_independent(AV1_COMP *cpi) {
......@@ -472,4 +478,10 @@ void av1_set_speed_features_framesize_independent(AV1_COMP *cpi) {
if (!cpi->oxcf.frame_periodic_boost) {
sf->max_delta_qindex = 0;
}
// This is only used in motion vector unit test.
if (cpi->oxcf.motion_vector_unit_test == 1)
cpi->find_fractional_mv_step = av1_return_max_sub_pixel_mv;
else if (cpi->oxcf.motion_vector_unit_test == 2)
cpi->find_fractional_mv_step = av1_return_min_sub_pixel_mv;
}
/*
* Copyright (c) 2017, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#include "third_party/googletest/src/googletest/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 libaom_test::TestMode kEncodingModeVectors[] = {
::libaom_test::kTwoPassGood, ::libaom_test::kOnePassGood,
};
// Encoding speeds
const int kCpuUsedVectors[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
// 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 ::libaom_test::EncoderTest,
public ::libaom_test::CodecTestWith3Params<libaom_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_ != ::libaom_test::kRealTime) {
cfg_.g_lag_in_frames = 3;
cfg_.rc_end_usage = AOM_VBR;
} else {
cfg_.g_lag_in_frames = 0;
cfg_.rc_end_usage = AOM_CBR;
cfg_.rc_buf_sz = 1000;
cfg_.rc_buf_initial_sz = 500;
cfg_.rc_buf_optimal_sz = 600;
}
}
virtual void PreEncodeFrameHook(::libaom_test::VideoSource *video,
::libaom_test::Encoder *encoder) {
if (video->frame() == 1) {
encoder->Control(AOME_SET_CPUUSED, cpu_used_);
encoder->Control(AV1E_ENABLE_MOTION_VECTOR_UNIT_TEST, mv_test_mode_);
if (encoding_mode_ != ::libaom_test::kRealTime) {
encoder->Control(AOME_SET_ENABLEAUTOALTREF, 1);
encoder->Control(AOME_SET_ARNR_MAXFRAMES, 7);
encoder->Control(AOME_SET_ARNR_STRENGTH, 5);
}
}
}
libaom_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_ = AOM_CODEC_USE_PSNR;
testing::internal::scoped_ptr<libaom_test::VideoSource> video;
video.reset(new libaom_test::YUVVideoSource(
"niklas_640_480_30.yuv", AOM_IMG_FMT_I420, 3840, 2160, // 2048, 1080,
30, 1, 0, 5));
ASSERT_TRUE(video.get() != NULL);
ASSERT_NO_FATAL_FAILURE(RunLoop(video.get()));
}
AV1_INSTANTIATE_TEST_CASE(MotionVectorTestLarge,
::testing::ValuesIn(kEncodingModeVectors),
::testing::ValuesIn(kCpuUsedVectors),
::testing::ValuesIn(kMVTestModes));
} // namespace
......@@ -22,6 +22,7 @@ LIBAOM_TEST_DATA-$(CONFIG_AV1_ENCODER) += desktop_credits.y4m
LIBAOM_TEST_DATA-$(CONFIG_AV1_ENCODER) += niklas_1280_720_30.y4m
LIBAOM_TEST_DATA-$(CONFIG_AV1_ENCODER) += rush_hour_444.y4m
LIBAOM_TEST_DATA-$(CONFIG_AV1_ENCODER) += screendata.y4m
LIBAOM_TEST_DATA-$(CONFIG_AV1_ENCODER) += niklas_640_480_30.yuv
ifeq ($(CONFIG_DECODE_PERF_TESTS),yes)
# Encode / Decode test
......@@ -33,7 +34,6 @@ LIBAOM_TEST_DATA-$(CONFIG_AV1_ENCODER) += desktop_640_360_30.yuv
LIBAOM_TEST_DATA-$(CONFIG_AV1_ENCODER) += kirland_640_480_30.yuv
LIBAOM_TEST_DATA-$(CONFIG_AV1_ENCODER) += macmarcomoving_640_480_30.yuv
LIBAOM_TEST_DATA-$(CONFIG_AV1_ENCODER) += macmarcostationary_640_480_30.yuv
LIBAOM_TEST_DATA-$(CONFIG_AV1_ENCODER) += niklas_640_480_30.yuv
LIBAOM_TEST_DATA-$(CONFIG_AV1_ENCODER) += niklas_1280_720_30.yuv
LIBAOM_TEST_DATA-$(CONFIG_AV1_ENCODER) += tacomanarrows_640_480_30.yuv
LIBAOM_TEST_DATA-$(CONFIG_AV1_ENCODER) += tacomasmallcameramovement_640_480_30.yuv
......
......@@ -113,6 +113,7 @@ LIBAOM_TEST_SRCS-yes += partial_idct_test.cc
LIBAOM_TEST_SRCS-yes += superframe_test.cc
LIBAOM_TEST_SRCS-yes += tile_independence_test.cc
LIBAOM_TEST_SRCS-yes += ethread_test.cc
LIBAOM_TEST_SRCS-yes += motion_vector_test.cc
ifneq ($(CONFIG_ANS),yes)
LIBAOM_TEST_SRCS-yes += binary_codes_test.cc
endif
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment