RC: implement updating encodeframe result
Bug: aomedia:450252793
Change-Id: I1316d8d3f2ce5f670876c0204f568563621a0cf5
diff --git a/av1/encoder/av1_ext_ratectrl.c b/av1/encoder/av1_ext_ratectrl.c
index 417c87e..f7187a4 100644
--- a/av1/encoder/av1_ext_ratectrl.c
+++ b/av1/encoder/av1_ext_ratectrl.c
@@ -149,6 +149,24 @@
return AOM_CODEC_OK;
}
+aom_codec_err_t av1_extrc_update_encodeframe_result(
+ AOM_EXT_RATECTRL *ext_ratectrl, int64_t bit_count,
+ int actual_encoding_qindex) {
+ assert(ext_ratectrl != NULL);
+ if (ext_ratectrl->ready) {
+ aom_rc_status_t rc_status;
+ aom_rc_encodeframe_result_t encode_frame_result;
+ encode_frame_result.bit_count = bit_count;
+ encode_frame_result.actual_encoding_qindex = actual_encoding_qindex;
+ rc_status = ext_ratectrl->funcs.update_encodeframe_result(
+ ext_ratectrl->model, &encode_frame_result);
+ if (rc_status == AOM_RC_ERROR) {
+ return AOM_CODEC_ERROR;
+ }
+ }
+ return AOM_CODEC_OK;
+}
+
aom_codec_err_t av1_extrc_delete(AOM_EXT_RATECTRL *ext_ratectrl) {
if (ext_ratectrl == NULL) {
return AOM_CODEC_INVALID_PARAM;
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c
index f6b4fbe..54e4214 100644
--- a/av1/encoder/encoder.c
+++ b/av1/encoder/encoder.c
@@ -4603,6 +4603,16 @@
return AOM_CODEC_ERROR;
}
+ if (cpi->ext_ratectrl.ready &&
+ cpi->ext_ratectrl.funcs.update_encodeframe_result != NULL) {
+ aom_codec_err_t codec_status = av1_extrc_update_encodeframe_result(
+ &cpi->ext_ratectrl, (*frame_size) << 3, cm->quant_params.base_qindex);
+ if (codec_status != AOM_CODEC_OK) {
+ aom_internal_error(cm->error, codec_status,
+ "av1_extrc_update_encodeframe_result() failed");
+ }
+ }
+
return AOM_CODEC_OK;
}
diff --git a/test/ext_ratectrl_test.cc b/test/ext_ratectrl_test.cc
index c031f4a..269de04 100644
--- a/test/ext_ratectrl_test.cc
+++ b/test/ext_ratectrl_test.cc
@@ -42,6 +42,13 @@
// A flag to indicate if get_gop_decision() is called.
bool is_get_gop_decision_called = false;
+// A flag to indicate if update_encodeframe_result() is called.
+bool is_update_encodeframe_result_called = false;
+
+// Variables to store the parameters passed to update_encodeframe_result().
+int64_t bit_count = 0;
+int actual_encoding_qindex = 0;
+
// Construct a single ALTREF GOP.
const int kGopFrameCount = kFrameNum + 1;
aom_rc_gop_frame_t gop_frame_list[kGopFrameCount];
@@ -123,6 +130,16 @@
return AOM_RC_OK;
}
+aom_rc_status_t mock_update_encodeframe_result(
+ aom_rc_model_t /* ratectrl_model */,
+ const aom_rc_encodeframe_result_t *encode_frame_result) {
+ EXPECT_NE(encode_frame_result, nullptr);
+ bit_count = encode_frame_result->bit_count;
+ actual_encoding_qindex = encode_frame_result->actual_encoding_qindex;
+ is_update_encodeframe_result_called = true;
+ return AOM_RC_OK;
+}
+
class ExtRateCtrlTest : public ::libaom_test::EncoderTest,
public ::libaom_test::CodecTestWith2Params<int, int> {
protected:
@@ -149,6 +166,7 @@
is_send_firstpass_stats_called = false;
is_send_extrc_tpl_gop_stats_called = false;
is_get_gop_decision_called = false;
+ is_update_encodeframe_result_called = false;
}
void PreEncodeFrameHook(::libaom_test::VideoSource *video,
@@ -182,10 +200,8 @@
const int kFrameQindex = 172;
aom_rc_status_t mock_get_encodeframe_decision_const_q(
- aom_rc_model_t ratectrl_model, int frame_gop_index,
+ aom_rc_model_t /*ratectrl_model*/, int /*frame_gop_index*/,
aom_rc_encodeframe_decision_t *frame_decision) {
- (void)ratectrl_model;
- (void)frame_gop_index;
// Set constant QP.
frame_decision->q_index = kFrameQindex;
frame_decision->sb_params_list = NULL; // Initialize to NULL
@@ -211,7 +227,6 @@
if (pkt->kind != AOM_CODEC_CX_FRAME_PKT) return;
int q_index = -1;
current_encoder_->Control(AOME_GET_LAST_QUANTIZER, &q_index);
- std::cout << q_index << std::endl;
EXPECT_EQ(q_index, kFrameQindex);
}
};
@@ -227,6 +242,56 @@
::testing::Values(::libaom_test::kTwoPassGood),
::testing::Values(3));
+class ExtRateCtrlUpdateEncodeFrameResultTest : public ExtRateCtrlTest {
+ protected:
+ ExtRateCtrlUpdateEncodeFrameResultTest() {
+ rc_funcs_.rc_type = AOM_RC_QP;
+ rc_funcs_.get_encodeframe_decision = mock_get_encodeframe_decision_const_q;
+ rc_funcs_.update_encodeframe_result = mock_update_encodeframe_result;
+ }
+ ~ExtRateCtrlUpdateEncodeFrameResultTest() override = default;
+
+ void SetUp() override {
+ ExtRateCtrlTest::SetUp();
+ is_update_encodeframe_result_called = false;
+ bit_count = 0;
+ actual_encoding_qindex = 0;
+ }
+
+ void FramePktHook(const aom_codec_cx_pkt_t *pkt) override {
+ if (pkt->kind != AOM_CODEC_CX_FRAME_PKT) return;
+ int q_index = -1;
+ current_encoder_->Control(AOME_GET_LAST_QUANTIZER, &q_index);
+ EXPECT_EQ(q_index, kFrameQindex);
+ EXPECT_EQ(actual_encoding_qindex, kFrameQindex);
+ // The second packet includes both invisible and visible frames. To verify
+ // frame size, there's no move_offset (obu_header_size + obu_payload_size)
+ // for vis_frame_size.
+ const int pkt_size_padding = pkt_count_ == 1 ? 0 : 2;
+ // Due to av1 packing invisible and visible frames together, we can only
+ // verify the size of the visible frame in the packet using vis_frame_size.
+ EXPECT_EQ((bit_count >> 3) + pkt_size_padding,
+ pkt->data.frame.vis_frame_size);
+ pkt_count_++;
+ }
+
+ private:
+ int pkt_count_ = 0;
+};
+
+TEST_P(ExtRateCtrlUpdateEncodeFrameResultTest,
+ TestExternalRateCtrlUpdateEncodeFrameResult) {
+ ::libaom_test::Y4mVideoSource video("screendata.y4m", 0, kFrameNum);
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ EXPECT_TRUE(is_create_model_called);
+ EXPECT_TRUE(is_delete_model_called);
+ EXPECT_TRUE(is_update_encodeframe_result_called);
+}
+
+AV1_INSTANTIATE_TEST_SUITE(ExtRateCtrlUpdateEncodeFrameResultTest,
+ ::testing::Values(::libaom_test::kTwoPassGood),
+ ::testing::Values(3));
+
class ExtRateCtrlGopTest : public ExtRateCtrlTest {
protected:
ExtRateCtrlGopTest() {