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 {