From: angiebird Date: Tue, 4 Aug 2020 02:49:43 +0000 (-0700) Subject: Add rq_history to encode_frame_result X-Git-Tag: v1.10.0-rc1~84 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3ec043a795cdf4dfa4cf31a9a0c82cbeef52c866;p=libvpx Add rq_history to encode_frame_result Change-Id: Ic2a52dcf5e5a6d57b80d390a2c48ee498e89e7b2 --- diff --git a/test/simple_encode_test.cc b/test/simple_encode_test.cc index 1790b56ac..c5674466d 100644 --- a/test/simple_encode_test.cc +++ b/test/simple_encode_test.cc @@ -163,6 +163,40 @@ TEST_F(SimpleEncodeTest, ObserveKeyFrameMap) { simple_encode.EndEncode(); } +TEST_F(SimpleEncodeTest, EncodeFrameWithTargetFrameBits) { + SimpleEncode simple_encode(width_, height_, frame_rate_num_, frame_rate_den_, + target_bitrate_, num_frames_, + in_file_path_str_.c_str()); + simple_encode.ComputeFirstPassStats(); + const int num_coding_frames = simple_encode.GetCodingFrameNum(); + simple_encode.StartEncode(); + for (int i = 0; i < num_coding_frames; ++i) { + EncodeFrameInfo encode_frame_info = simple_encode.GetNextEncodeFrameInfo(); + int target_frame_bits = 20000; + if (encode_frame_info.frame_type == kFrameTypeKey || + encode_frame_info.frame_type == kFrameTypeAltRef || + encode_frame_info.frame_type == kFrameTypeGolden) { + target_frame_bits = 100000; + } + if (encode_frame_info.frame_type == kFrameTypeOverlay) { + target_frame_bits = 2000; + } + + EncodeFrameResult encode_frame_result; + simple_encode.EncodeFrameWithTargetFrameBits(&encode_frame_result, + target_frame_bits); + const int recode_count = encode_frame_result.recode_count; + // TODO(angiebird): Replace 7 by RATE_CTRL_MAX_RECODE_NUM + EXPECT_LE(recode_count, 7); + EXPECT_GE(recode_count, 1); + + double diff = fabs((double)encode_frame_result.coding_data_bit_size - + target_frame_bits); + EXPECT_LE(diff * 100 / target_frame_bits, 15); + } + simple_encode.EndEncode(); +} + TEST_F(SimpleEncodeTest, EncodeFrameWithQuantizeIndex) { SimpleEncode simple_encode(width_, height_, frame_rate_num_, frame_rate_den_, target_bitrate_, num_frames_, diff --git a/vp9/encoder/vp9_encoder.c b/vp9/encoder/vp9_encoder.c index 169cd190e..4820b2529 100644 --- a/vp9/encoder/vp9_encoder.c +++ b/vp9/encoder/vp9_encoder.c @@ -4204,16 +4204,6 @@ static int get_qstep_adj(int rate_excess, int rate_limit) { } #if CONFIG_RATE_CTRL -#define RATE_CTRL_MAX_RECODE_NUM 7 - -typedef struct RATE_QINDEX_HISTORY { - int recode_count; - int q_index_history[RATE_CTRL_MAX_RECODE_NUM]; - int rate_history[RATE_CTRL_MAX_RECODE_NUM]; - int q_index_high; - int q_index_low; -} RATE_QINDEX_HISTORY; - static void init_rq_history(RATE_QINDEX_HISTORY *rq_history) { rq_history->recode_count = 0; rq_history->q_index_high = 255; @@ -4330,8 +4320,12 @@ static void rq_model_update(const RATE_QINDEX_HISTORY *rq_history, } #endif // CONFIG_RATE_CTRL -static void encode_with_recode_loop(VP9_COMP *cpi, size_t *size, - uint8_t *dest) { +static void encode_with_recode_loop(VP9_COMP *cpi, size_t *size, uint8_t *dest +#if CONFIG_RATE_CTRL + , + RATE_QINDEX_HISTORY *rq_history +#endif // CONFIG_RATE_CTRL +) { const VP9EncoderConfig *const oxcf = &cpi->oxcf; VP9_COMMON *const cm = &cpi->common; RATE_CONTROL *const rc = &cpi->rc; @@ -4354,8 +4348,7 @@ static void encode_with_recode_loop(VP9_COMP *cpi, size_t *size, cpi->twopass.gf_group.update_type[cpi->twopass.gf_group.index]; const ENCODE_FRAME_TYPE frame_type = get_encode_frame_type(update_type); RATE_QSTEP_MODEL *rq_model = &cpi->rq_model[frame_type]; - RATE_QINDEX_HISTORY rq_history; - init_rq_history(&rq_history); + init_rq_history(rq_history); #endif // CONFIG_RATE_CTRL if (cm->show_existing_frame) { @@ -4406,8 +4399,7 @@ static void encode_with_recode_loop(VP9_COMP *cpi, size_t *size, #if CONFIG_RATE_CTRL if (cpi->encode_command.use_external_target_frame_bits) { - q = rq_model_predict_q_index(rq_model, &rq_history, - rc->this_frame_target); + q = rq_model_predict_q_index(rq_model, rq_history, rc->this_frame_target); } #endif // CONFIG_RATE_CTRL // Decide frame size bounds first time through. @@ -4507,16 +4499,16 @@ static void encode_with_recode_loop(VP9_COMP *cpi, size_t *size, if (cpi->encode_command.use_external_target_frame_bits) { const double percent_diff = get_bits_percent_diff( rc->this_frame_target, rc->projected_frame_size); - update_rq_history(&rq_history, rc->this_frame_target, + update_rq_history(rq_history, rc->this_frame_target, rc->projected_frame_size, q); loop_count += 1; - rq_model_update(&rq_history, rc->this_frame_target, rq_model); + rq_model_update(rq_history, rc->this_frame_target, rq_model); // Check if we hit the target bitrate. if (percent_diff <= 15 || - rq_history.recode_count >= RATE_CTRL_MAX_RECODE_NUM || - rq_history.q_index_low >= rq_history.q_index_high) { + rq_history->recode_count >= RATE_CTRL_MAX_RECODE_NUM || + rq_history->q_index_low >= rq_history->q_index_high) { break; } @@ -5374,8 +5366,12 @@ static void encode_frame_to_data_rate( if (!encode_without_recode_loop(cpi, size, dest)) return; } else { #if !CONFIG_REALTIME_ONLY +#if CONFIG_RATE_CTRL + encode_with_recode_loop(cpi, size, dest, &encode_frame_result->rq_history); +#else // CONFIG_RATE_CTRL encode_with_recode_loop(cpi, size, dest); -#endif +#endif // CONFIG_RATE_CTRL +#endif // !CONFIG_REALTIME_ONLY } // TODO(jingning): When using show existing frame mode, we assume that the @@ -7561,6 +7557,7 @@ void vp9_init_encode_frame_result(ENCODE_FRAME_RESULT *encode_frame_result) { encode_frame_result->frame_coding_index = -1; vp9_zero(encode_frame_result->coded_frame); encode_frame_result->coded_frame.allocated = 0; + init_rq_history(&encode_frame_result->rq_history); #endif // CONFIG_RATE_CTRL } diff --git a/vp9/encoder/vp9_encoder.h b/vp9/encoder/vp9_encoder.h index 3758ea3ae..0d537ca97 100644 --- a/vp9/encoder/vp9_encoder.h +++ b/vp9/encoder/vp9_encoder.h @@ -1041,6 +1041,17 @@ typedef struct IMAGE_BUFFER { int plane_height[3]; uint8_t *plane_buffer[3]; } IMAGE_BUFFER; + +#define RATE_CTRL_MAX_RECODE_NUM 7 + +typedef struct RATE_QINDEX_HISTORY { + int recode_count; + int q_index_history[RATE_CTRL_MAX_RECODE_NUM]; + int rate_history[RATE_CTRL_MAX_RECODE_NUM]; + int q_index_high; + int q_index_low; +} RATE_QINDEX_HISTORY; + #endif // CONFIG_RATE_CTRL typedef struct ENCODE_FRAME_RESULT { @@ -1056,6 +1067,7 @@ typedef struct ENCODE_FRAME_RESULT { const PARTITION_INFO *partition_info; const MOTION_VECTOR_INFO *motion_vector_info; IMAGE_BUFFER coded_frame; + RATE_QINDEX_HISTORY rq_history; #endif // CONFIG_RATE_CTRL int quantize_index; } ENCODE_FRAME_RESULT; diff --git a/vp9/simple_encode.cc b/vp9/simple_encode.cc index 4ee0bd2e8..da9c4e10a 100644 --- a/vp9/simple_encode.cc +++ b/vp9/simple_encode.cc @@ -485,6 +485,18 @@ static bool init_encode_frame_result(EncodeFrameResult *encode_frame_result, frame_height, img_fmt); } +static void encode_frame_result_update_rq_history( + const RATE_QINDEX_HISTORY *rq_history, + EncodeFrameResult *encode_frame_result) { + encode_frame_result->recode_count = rq_history->recode_count; + for (int i = 0; i < encode_frame_result->recode_count; ++i) { + const int q_index = rq_history->q_index_history[i]; + const int rate = rq_history->rate_history[i]; + encode_frame_result->q_index_history.push_back(q_index); + encode_frame_result->rate_history.push_back(rate); + } +} + static void update_encode_frame_result( EncodeFrameResult *encode_frame_result, const ENCODE_FRAME_RESULT *encode_frame_info) { @@ -514,6 +526,8 @@ static void update_encode_frame_result( &encode_frame_result->motion_vector_info[0]); update_frame_counts(&encode_frame_info->frame_counts, &encode_frame_result->frame_counts); + encode_frame_result_update_rq_history(&encode_frame_info->rq_history, + encode_frame_result); } static void IncreaseGroupOfPictureIndex(GroupOfPicture *group_of_picture) { diff --git a/vp9/simple_encode.h b/vp9/simple_encode.h index 6c66aafda..702895e05 100644 --- a/vp9/simple_encode.h +++ b/vp9/simple_encode.h @@ -256,6 +256,12 @@ struct EncodeFrameResult { // share the same motion vector information. std::vector motion_vector_info; ImageBuffer coded_frame; + + // recode_count, q_index_history and rate_history are only available when + // EncodeFrameWithTargetFrameBits() is used. + int recode_count; + std::vector q_index_history; + std::vector rate_history; }; struct GroupOfPicture {