Fix ref_mv for int_pro_motion_estimation() in nonrd_pickmode For nonrd_pickmode (speed >= 7): fix the ref_mv input to the int_pro_motion_estimation(), used for newmv search on non-last reference. The ref_mv used there should be set via av1_get_ref_mv(), which gets the ref_mv properly (i.e., gets the mv from mbmi_ext->ref_mv_stack[] or mbmi_ext->global_mvs[] depending on ref_mv_idx). In this assert case it was taking ref_mv directly from ref_mv_stack[], when it should be taking global_mvs (which is zeromv). No changes in stats for all rtc sets, speed >= 7. Added a test that triggers the issue without the fix. Since it was only triggered on high resolution, the test upsamples a QVGA clip, using libyuv. Bug: b:396169342 Change-Id: Ic93dc733017ab0c80db0e1d8a30cc03e3b625139 (cherry picked from commit 127be6a600e56735c6b73a2f23c7bd0577a9d3f3)
diff --git a/av1/encoder/nonrd_pickmode.c b/av1/encoder/nonrd_pickmode.c index 96070ab..fd01565 100644 --- a/av1/encoder/nonrd_pickmode.c +++ b/av1/encoder/nonrd_pickmode.c
@@ -322,10 +322,10 @@ int me_search_size_col = block_size_wide[bsize] >> 1; int me_search_size_row = block_size_high[bsize] >> 1; + MV ref_mv = av1_get_ref_mv(x, 0).as_mv; tmp_sad = av1_int_pro_motion_estimation( - cpi, x, bsize, mi_row, mi_col, - &x->mbmi_ext.ref_mv_stack[ref_frame][0].this_mv.as_mv, &y_sad_zero, - me_search_size_col, me_search_size_row); + cpi, x, bsize, mi_row, mi_col, &ref_mv, &y_sad_zero, me_search_size_col, + me_search_size_row); if (tmp_sad > x->pred_mv_sad[LAST_FRAME]) return -1; @@ -333,7 +333,6 @@ int_mv best_mv = mi->mv[0]; best_mv.as_mv.row >>= 3; best_mv.as_mv.col >>= 3; - MV ref_mv = av1_get_ref_mv(x, 0).as_mv; this_ref_frm_newmv->as_mv.row >>= 3; this_ref_frm_newmv->as_mv.col >>= 3;
diff --git a/test/datarate_test.cc b/test/datarate_test.cc index e1d6a1d..97fa32a 100644 --- a/test/datarate_test.cc +++ b/test/datarate_test.cc
@@ -21,9 +21,59 @@ #include "test/y4m_video_source.h" #include "aom/aom_codec.h" +#if CONFIG_LIBYUV +#include "third_party/libyuv/include/libyuv/scale.h" +#endif + namespace datarate_test { namespace { +#if CONFIG_LIBYUV +class ResizingVideoSource : public ::libaom_test::DummyVideoSource { + public: + ResizingVideoSource(const int width, const int height, const int input_width, + const int input_height, const std::string file_name, + int limit) + : width_(width), height_(height), input_width_(input_width), + input_height_(input_height), limit_(limit) { + SetSize(width_, height_); + img_input_ = aom_img_alloc(nullptr, AOM_IMG_FMT_I420, input_width_, + input_height_, 32); + raw_size_ = input_width_ * input_height_ * 3 / 2; + input_file_ = ::libaom_test::OpenTestDataFile(file_name); + } + + ~ResizingVideoSource() override { + aom_img_free(img_input_); + fclose(input_file_); + } + + protected: + void FillFrame() override { + // Read frame from input_file and scale up. + ASSERT_NE(input_file_, nullptr); + fread(img_input_->img_data, raw_size_, 1, input_file_); + libyuv::I420Scale( + img_input_->planes[AOM_PLANE_Y], img_input_->stride[AOM_PLANE_Y], + img_input_->planes[AOM_PLANE_U], img_input_->stride[AOM_PLANE_U], + img_input_->planes[AOM_PLANE_V], img_input_->stride[AOM_PLANE_V], + input_width_, input_height_, img_->planes[AOM_PLANE_Y], + img_->stride[AOM_PLANE_Y], img_->planes[AOM_PLANE_U], + img_->stride[AOM_PLANE_U], img_->planes[AOM_PLANE_V], + img_->stride[AOM_PLANE_V], width_, height_, libyuv::kFilterBox); + } + + const int width_; + const int height_; + const int input_width_; + const int input_height_; + const int limit_; + aom_image_t *img_input_; + size_t raw_size_; + FILE *input_file_; +}; +#endif // CONFIG_LIBYUV + // Params: test mode, speed, aq mode and index for bitrate array. class DatarateTestLarge : public ::libaom_test::CodecTestWith4Params<libaom_test::TestMode, int, @@ -86,6 +136,27 @@ << " The datarate for the file is greater than target by too much!"; } +#if CONFIG_LIBYUV + // Test for an encoding mode that triggers an assert in nonrd_pickmode + // (in av1_is_subpelmv_in_range), issue b:396169342. + // The assert is triggered on a 2456x2054 resolution with settings defined + // with the flag avif_mode_. This test upsamples a QVGA clip to the target + // resolution, using libyuv for the scaling. + virtual void BasicRateTargetingCBRAssertAvifModeTest() { + cfg_.rc_min_quantizer = 0; + cfg_.rc_max_quantizer = 63; + cfg_.rc_end_usage = AOM_CBR; + cfg_.g_lag_in_frames = 0; + ResizingVideoSource video(2456, 2054, 320, 240, + "pixel_capture_w320h240.yuv", 100); + const int bitrate_array[2] = { 1000, 2000 }; + cfg_.rc_target_bitrate = bitrate_array[GET_PARAM(4)]; + ResetModel(); + avif_mode_ = 1; + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + } +#endif // CONFIG_LIBYUV + virtual void BasicRateTargetingCBRSpikeTest() { cfg_.rc_buf_initial_sz = 500; cfg_.rc_buf_optimal_sz = 500; @@ -555,6 +626,13 @@ BasicRateTargetingCBRTest(); } +#if CONFIG_LIBYUV +// Check basic rate targeting for CBR, special case. +TEST_P(DatarateTestRealtime, BasicRateTargetingCBRAssertAvifMode) { + BasicRateTargetingCBRAssertAvifModeTest(); +} +#endif + // Check basic rate targeting for CBR. Use a longer clip, // and verify #encode size spikes above threshold. TEST_P(DatarateTestRealtime, BasicRateTargetingCBRSpike) {
diff --git a/test/datarate_test.h b/test/datarate_test.h index 9c88ef5..a83a386 100644 --- a/test/datarate_test.h +++ b/test/datarate_test.h
@@ -57,6 +57,7 @@ bits_total_dynamic_[i] = 0; effective_datarate_dynamic_[i] = 0.0; } + avif_mode_ = 0; } void PreEncodeFrameHook(::libaom_test::VideoSource *video, @@ -90,6 +91,17 @@ encoder->Control(AV1E_SET_ENABLE_PALETTE, 1); encoder->Control(AV1E_SET_ENABLE_INTRABC, 0); } + if (avif_mode_) { + encoder->Control(AV1E_SET_COEFF_COST_UPD_FREQ, 0); + encoder->Control(AV1E_SET_MODE_COST_UPD_FREQ, 0); + encoder->Control(AV1E_SET_MV_COST_UPD_FREQ, 0); + encoder->Control(AV1E_SET_DELTAQ_MODE, 3); + encoder->Control(AV1E_SET_ENABLE_QM, 1); + encoder->Control(AOME_SET_SHARPNESS, 1); + encoder->Control(AV1E_SET_ENABLE_CHROMA_DELTAQ, 1); + encoder->Control(AOME_SET_CQ_LEVEL, 0); + encoder->Control(AV1E_SET_AQ_MODE, (aq_mode_ > 0) ? 1 : 0); + } } if (speed_change_test_) { @@ -227,6 +239,7 @@ double effective_datarate_dynamic_[3]; int64_t bits_total_dynamic_[3]; int frame_number_dynamic_[3]; + int avif_mode_; }; } // namespace
diff --git a/test/test.cmake b/test/test.cmake index b3227b8..55fcc14 100644 --- a/test/test.cmake +++ b/test/test.cmake
@@ -501,7 +501,13 @@ endif() endif() - target_link_libraries(test_libaom ${AOM_LIB_LINK_TYPE} aom aom_gtest) + if(CONFIG_LIBYUV) + # link test_libaom with yuv + target_link_libraries(test_libaom ${AOM_LIB_LINK_TYPE} aom aom_gtest yuv) + else() + # do not link test_libaom with yuv + target_link_libraries(test_libaom ${AOM_LIB_LINK_TYPE} aom aom_gtest) + endif() if(CONFIG_WEBM_IO) target_sources(test_libaom PRIVATE $<TARGET_OBJECTS:webm>)