Add unit test to check validity of gf interval configs Added a unit test which checks if the min-gf-interval and max-gf-interval configured by the user are respected in the encoder. Change-Id: If91a0de4d8702c739c634e864470158f5e1c0b78
diff --git a/aom/aomcx.h b/aom/aomcx.h index a76ec3a..ac69d46 100644 --- a/aom/aomcx.h +++ b/aom/aomcx.h
@@ -1269,6 +1269,10 @@ * single pass vbr based on LAP, unsigned int parameter */ AV1E_SET_VBR_CORPUS_COMPLEXITY_LAP = 157, + + /*!\brief Control to get baseline gf interval + */ + AV1E_GET_BASELINE_GF_INTERVAL = 158, }; /*!\brief aom 1-D scaling mode @@ -1691,6 +1695,9 @@ AOM_CTRL_USE_TYPE(AV1E_GET_SEQ_LEVEL_IDX, int *) #define AOM_CTRL_AV1E_GET_SEQ_LEVEL_IDX +AOM_CTRL_USE_TYPE(AV1E_GET_BASELINE_GF_INTERVAL, int *) +#define AOM_CTRL_AV1E_GET_BASELINE_GF_INTERVAL + AOM_CTRL_USE_TYPE(AV1E_SET_SINGLE_TILE_DECODING, unsigned int) #define AOM_CTRL_AV1E_SET_SINGLE_TILE_DECODING
diff --git a/av1/av1_cx_iface.c b/av1/av1_cx_iface.c index b7e0dd1..43c2704 100644 --- a/av1/av1_cx_iface.c +++ b/av1/av1_cx_iface.c
@@ -1158,6 +1158,14 @@ return AOM_CODEC_OK; } +static aom_codec_err_t ctrl_get_baseline_gf_interval(aom_codec_alg_priv_t *ctx, + va_list args) { + int *const arg = va_arg(args, int *); + if (arg == NULL) return AOM_CODEC_INVALID_PARAM; + *arg = ctx->cpi->rc.baseline_gf_interval; + return AOM_CODEC_OK; +} + static aom_codec_err_t update_extra_cfg(aom_codec_alg_priv_t *ctx, struct av1_extracfg *extra_cfg) { const aom_codec_err_t res = validate_config(ctx, &ctx->cfg, extra_cfg); @@ -2877,6 +2885,7 @@ { AV1E_SET_CHROMA_SUBSAMPLING_X, ctrl_set_chroma_subsampling_x }, { AV1E_SET_CHROMA_SUBSAMPLING_Y, ctrl_set_chroma_subsampling_y }, { AV1E_GET_SEQ_LEVEL_IDX, ctrl_get_seq_level_idx }, + { AV1E_GET_BASELINE_GF_INTERVAL, ctrl_get_baseline_gf_interval }, CTRL_MAP_END, };
diff --git a/test/altref_test.cc b/test/altref_test.cc index 58f4446..742358e 100644 --- a/test/altref_test.cc +++ b/test/altref_test.cc
@@ -114,4 +114,105 @@ ::testing::ValuesIn(TestParams), ::testing::Values(AOM_Q, AOM_VBR, AOM_CBR, AOM_CQ)); +typedef struct { + const ::libaom_test::TestMode encoding_mode; + const unsigned int min_gf_interval; + const unsigned int max_gf_interval; +} gfIntervalParam; + +const gfIntervalParam gfTestParams[] = { + // single pass + { ::libaom_test::kOnePassGood, 0, 6 }, + { ::libaom_test::kOnePassGood, 0, 8 }, + { ::libaom_test::kOnePassGood, 5, 10 }, + { ::libaom_test::kOnePassGood, 8, 16 }, + { ::libaom_test::kOnePassGood, 16, 16 }, + + // two pass + { ::libaom_test::kTwoPassGood, 0, 6 }, + { ::libaom_test::kTwoPassGood, 0, 8 }, + { ::libaom_test::kTwoPassGood, 5, 10 }, + { ::libaom_test::kTwoPassGood, 8, 16 }, + { ::libaom_test::kTwoPassGood, 16, 32 }, + // disabled below test case because it causes failure + // TODO(anyone): enable below test case once issue is fixed. + // { ::libaom_test::kTwoPassGood, 20, 32 }, +}; + +// This class is used to test if the gf interval bounds configured by the user +// are respected by the encoder. +class GoldenFrameIntervalTestLarge + : public ::libaom_test::CodecTestWith2Params<gfIntervalParam, aom_rc_mode>, + public ::libaom_test::EncoderTest { + protected: + GoldenFrameIntervalTestLarge() + : EncoderTest(GET_PARAM(0)), gf_interval_param_(GET_PARAM(1)), + rc_end_usage_(GET_PARAM(2)) { + baseline_gf_interval_ = -1; + limit_ = 60; + frame_num_ = 0; + } + virtual ~GoldenFrameIntervalTestLarge() {} + + virtual void SetUp() { + InitializeConfig(); + SetMode(gf_interval_param_.encoding_mode); + const aom_rational timebase = { 1, 30 }; + cfg_.g_timebase = timebase; + cfg_.rc_end_usage = rc_end_usage_; + cfg_.g_threads = 1; + // kf_min_dist is equal to kf_max_dist to make sure that there are no scene + // cuts due to which the min_gf_interval may not be respected. + cfg_.kf_min_dist = limit_; + cfg_.kf_max_dist = limit_; + cfg_.g_limit = limit_; + cfg_.g_lag_in_frames = 35; + cfg_.rc_target_bitrate = 1000; + } + + virtual bool DoDecode() const { return 1; } + + virtual void PreEncodeFrameHook(::libaom_test::VideoSource *video, + ::libaom_test::Encoder *encoder) { + if (video->frame() == 0) { + encoder->Control(AOME_SET_CPUUSED, 5); + encoder->Control(AOME_SET_ENABLEAUTOALTREF, 1); + encoder->Control(AV1E_SET_MIN_GF_INTERVAL, + gf_interval_param_.min_gf_interval); + encoder->Control(AV1E_SET_MAX_GF_INTERVAL, + gf_interval_param_.max_gf_interval); + } + if (frame_num_ > 0) { + encoder->Control(AV1E_GET_BASELINE_GF_INTERVAL, &baseline_gf_interval_); + ASSERT_LE(baseline_gf_interval_, (int)gf_interval_param_.max_gf_interval); + if ((frame_num_ + (int)gf_interval_param_.min_gf_interval) <= limit_) { + ASSERT_GE(baseline_gf_interval_, + (int)gf_interval_param_.min_gf_interval); + } + } + } + + virtual void FramePktHook(const aom_codec_cx_pkt_t *pkt) { + (void)pkt; + ++frame_num_; + } + + const gfIntervalParam gf_interval_param_; + int baseline_gf_interval_; + int limit_; + int frame_num_; + aom_rc_mode rc_end_usage_; +}; + +TEST_P(GoldenFrameIntervalTestLarge, GoldenFrameIntervalTest) { + libaom_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, + cfg_.g_timebase.den, cfg_.g_timebase.num, + 0, limit_); + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); +} + +AV1_INSTANTIATE_TEST_SUITE(GoldenFrameIntervalTestLarge, + ::testing::ValuesIn(gfTestParams), + ::testing::Values(AOM_Q, AOM_VBR, AOM_CQ, AOM_CBR)); + } // namespace