RTC RC: Support cdef level Bug: b/283122279 Change-Id: I8f2e97b93503f468eba38210433b1f2f1e4bbe69
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c index 24e8a0d..4f0d087 100644 --- a/av1/encoder/encoder.c +++ b/av1/encoder/encoder.c
@@ -2316,7 +2316,8 @@ cpi->sf.lpf_sf.cdef_pick_method, cpi->td.mb.rdmult, cpi->sf.rt_sf.skip_cdef_sb, cpi->oxcf.tool_cfg.cdef_control, use_screen_content_model, - cpi->ppi->rtc_ref.non_reference_frame); + cpi->ppi->rtc_ref.non_reference_frame, + cpi->rc.rtc_external_ratectrl); // Apply the filter if ((skip_apply_postproc_filters & SKIP_APPLY_CDEF) == 0) {
diff --git a/av1/encoder/pickcdef.c b/av1/encoder/pickcdef.c index 22a4557..83d1517 100644 --- a/av1/encoder/pickcdef.c +++ b/av1/encoder/pickcdef.c
@@ -728,8 +728,8 @@ #endif } -static void pick_cdef_from_qp(AV1_COMMON *const cm, int skip_cdef, - int is_screen_content) { +void av1_pick_cdef_from_qp(AV1_COMMON *const cm, int skip_cdef, + int is_screen_content) { const int bd = cm->seq_params->bit_depth; const int q = av1_ac_quant_QTX(cm->quant_params.base_qindex, 0, bd) >> (bd - 8); @@ -807,6 +807,8 @@ const int nvfb = (mi_params->mi_rows + MI_SIZE_64X64 - 1) / MI_SIZE_64X64; const int nhfb = (mi_params->mi_cols + MI_SIZE_64X64 - 1) / MI_SIZE_64X64; MB_MODE_INFO **mbmi = mi_params->mi_grid_base; + // mbmi is NULL when real-time rate control library is used. + if (!mbmi) return; for (int r = 0; r < nvfb; ++r) { for (int c = 0; c < nhfb; ++c) { MB_MODE_INFO *current_mbmi = mbmi[MI_SIZE_64X64 * c]; @@ -820,7 +822,8 @@ const YV12_BUFFER_CONFIG *ref, AV1_COMMON *cm, MACROBLOCKD *xd, CDEF_PICK_METHOD pick_method, int rdmult, int skip_cdef_feature, CDEF_CONTROL cdef_control, - const int is_screen_content, int non_reference_frame) { + const int is_screen_content, int non_reference_frame, + int rtc_ext_rc) { assert(cdef_control != CDEF_NONE); if (cdef_control == CDEF_REFERENCE && non_reference_frame) { CdefInfo *const cdef_info = &cm->cdef_info; @@ -831,8 +834,12 @@ return; } + if (rtc_ext_rc) { + av1_pick_cdef_from_qp(cm, 0, 0); + return; + } if (pick_method == CDEF_PICK_FROM_Q) { - pick_cdef_from_qp(cm, skip_cdef_feature, is_screen_content); + av1_pick_cdef_from_qp(cm, skip_cdef_feature, is_screen_content); return; } const CommonModeInfoParams *const mi_params = &cm->mi_params;
diff --git a/av1/encoder/pickcdef.h b/av1/encoder/pickcdef.h index 548a740..bdd8233 100644 --- a/av1/encoder/pickcdef.h +++ b/av1/encoder/pickcdef.h
@@ -235,6 +235,7 @@ * \param[in] is_screen_content Whether it is screen content type * \param[in] non_reference_frame Indicates if current frame is * non-reference + * \param[in] rtc_ext_rc Indicate if external RC is used for testing * * \remark Nothing is returned. Instead, optimal CDEF parameters are stored * in the \c cdef_info structure of type \ref CdefInfo inside \c cm: @@ -252,7 +253,22 @@ const YV12_BUFFER_CONFIG *ref, AV1_COMMON *cm, MACROBLOCKD *xd, CDEF_PICK_METHOD pick_method, int rdmult, int skip_cdef_feature, CDEF_CONTROL cdef_control, - const int is_screen_content, int non_reference_frame); + const int is_screen_content, int non_reference_frame, + int rtc_ext_rc); + +/*!\brief AV1 CDEF level from QP + * + * \ingroup in_loop_cdef + * + * Calculates CDEF levels from frame QP. Only used for speed 7+ with RT mode. + * + * \param[in,out] cm Pointer to top level common structure + * \param[in] skip_cdef Flag to skip CDEF filtering + * \param[in] is_screen_content Flag indicating screen content + * + */ +void av1_pick_cdef_from_qp(AV1_COMMON *const cm, int skip_cdef, + int is_screen_content); #ifdef __cplusplus } // extern "C"
diff --git a/av1/ratectrl_rtc.cc b/av1/ratectrl_rtc.cc index e1470e6..a3ec6f6 100644 --- a/av1/ratectrl_rtc.cc +++ b/av1/ratectrl_rtc.cc
@@ -19,6 +19,7 @@ #include "aom_mem/aom_mem.h" #include "av1/encoder/encoder.h" #include "av1/encoder/encoder_utils.h" +#include "av1/encoder/pickcdef.h" #include "av1/encoder/picklpf.h" #include "av1/encoder/ratectrl.h" #include "av1/encoder/rc_utils.h" @@ -316,6 +317,16 @@ return lpf_level; } +AV1CdefInfo AV1RateControlRTC::GetCdefInfo() const { + av1_pick_cdef_from_qp(&cpi_->common, 0, 0); + AV1CdefInfo cdef_level; + cdef_level.cdef_strength_y = cpi_->common.cdef_info.cdef_strengths[0]; + cdef_level.cdef_strength_uv = cpi_->common.cdef_info.cdef_uv_strengths[0]; + cdef_level.damping = cpi_->common.cdef_info.cdef_damping; + + return cdef_level; +} + signed char *AV1RateControlRTC::GetCyclicRefreshMap() const { return cpi_->cyclic_refresh->map; }
diff --git a/av1/ratectrl_rtc.h b/av1/ratectrl_rtc.h index 6c223a7..e96e210 100644 --- a/av1/ratectrl_rtc.h +++ b/av1/ratectrl_rtc.h
@@ -71,6 +71,12 @@ int filter_level_v; }; +struct AV1CdefInfo { + int cdef_strength_y; + int cdef_strength_uv; + int damping; +}; + class AV1RateControlRTC { public: static std::unique_ptr<AV1RateControlRTC> Create( @@ -82,6 +88,8 @@ int GetQP() const; // GetLoopfilterLevel() needs to be called after ComputeQP() AV1LoopfilterLevel GetLoopfilterLevel() const; + // GetCdefInfo() needs to be called after ComputeQP() + AV1CdefInfo GetCdefInfo() const; signed char *GetCyclicRefreshMap() const; int *GetDeltaQ() const; void ComputeQP(const AV1FrameParamsRTC &frame_params);
diff --git a/test/ratectrl_rtc_test.cc b/test/ratectrl_rtc_test.cc index 1357983..0d8d48f 100644 --- a/test/ratectrl_rtc_test.cc +++ b/test/ratectrl_rtc_test.cc
@@ -150,6 +150,10 @@ encoder->Control(AOME_GET_LOOPFILTER_LEVEL, &encoder_lpf_level); aom::AV1LoopfilterLevel loopfilter_level = rc_api_->GetLoopfilterLevel(); ASSERT_EQ(loopfilter_level.filter_level[0], encoder_lpf_level); + aom::AV1CdefInfo cdef_level = rc_api_->GetCdefInfo(); + int cdef_y_strengths[16]; + encoder->Control(AV1E_GET_LUMA_CDEF_STRENGTH, cdef_y_strengths); + ASSERT_EQ(cdef_level.cdef_strength_y, cdef_y_strengths[0]); } void FramePktHook(const aom_codec_cx_pkt_t *pkt) override {