summaryrefslogtreecommitdiff
path: root/vp9/encoder/vp9_encoder.c
diff options
context:
space:
mode:
Diffstat (limited to 'vp9/encoder/vp9_encoder.c')
-rw-r--r--vp9/encoder/vp9_encoder.c35
1 files changed, 32 insertions, 3 deletions
diff --git a/vp9/encoder/vp9_encoder.c b/vp9/encoder/vp9_encoder.c
index 6a21a1c18..2757bc428 100644
--- a/vp9/encoder/vp9_encoder.c
+++ b/vp9/encoder/vp9_encoder.c
@@ -4402,6 +4402,17 @@ static void encode_with_recode_loop(VP9_COMP *cpi, size_t *size, uint8_t *dest
int qrange_adj = 1;
#endif
+ // A flag which indicates whether we are recoding the current frame
+ // when the current frame size is larger than the max frame size in the
+ // external rate control model.
+ // This flag doesn't have any impact when external rate control is not used.
+ int ext_rc_recode = 0;
+ // Maximal frame size allowed by the external rate control.
+ // case: 0, we ignore the max frame size limit, and encode with the qindex
+ // passed in by the external rate control model.
+ // case: -1, we take VP9's decision for the max frame size.
+ int ext_rc_max_frame_size = 0;
+
#if CONFIG_RATE_CTRL
const FRAME_UPDATE_TYPE update_type =
cpi->twopass.gf_group.update_type[cpi->twopass.gf_group.index];
@@ -4507,7 +4518,7 @@ static void encode_with_recode_loop(VP9_COMP *cpi, size_t *size, uint8_t *dest
q = cpi->encode_command.external_quantize_index;
}
#endif
- if (cpi->ext_ratectrl.ready) {
+ if (cpi->ext_ratectrl.ready && !ext_rc_recode) {
vpx_codec_err_t codec_status;
const GF_GROUP *gf_group = &cpi->twopass.gf_group;
vpx_rc_encodeframe_decision_t encode_frame_decision;
@@ -4526,6 +4537,7 @@ static void encode_with_recode_loop(VP9_COMP *cpi, size_t *size, uint8_t *dest
"vp9_extrc_get_encodeframe_decision() failed");
}
q = encode_frame_decision.q_index;
+ ext_rc_max_frame_size = encode_frame_decision.max_frame_size;
}
vp9_set_quantizer(cpi, q);
@@ -4567,7 +4579,24 @@ static void encode_with_recode_loop(VP9_COMP *cpi, size_t *size, uint8_t *dest
}
if (cpi->ext_ratectrl.ready) {
- break;
+ // In general, for the external rate control, we take the qindex provided
+ // as input and encode the frame with this qindex faithfully. However,
+ // in some extreme scenarios, the provided qindex leads to a massive
+ // overshoot of frame size. In this case, we fall back to VP9's decision
+ // to pick a new qindex and recode the frame. We return the new qindex
+ // through the API to the external model.
+ if (ext_rc_max_frame_size == 0) {
+ break;
+ } else if (ext_rc_max_frame_size == -1) {
+ if (rc->projected_frame_size < rc->max_frame_bandwidth) {
+ break;
+ }
+ } else {
+ if (rc->projected_frame_size < ext_rc_max_frame_size) {
+ break;
+ }
+ }
+ ext_rc_recode = 1;
}
#if CONFIG_RATE_CTRL
// This part needs to be after save_coding_context() because
@@ -5501,7 +5530,7 @@ static void encode_frame_to_data_rate(
get_ref_cnt_buffer(cm, cm->new_fb_idx);
vpx_codec_err_t codec_status = vp9_extrc_update_encodeframe_result(
&cpi->ext_ratectrl, (*size) << 3, cpi->Source, &coded_frame_buf->buf,
- cm->bit_depth, cpi->oxcf.input_bit_depth);
+ cm->bit_depth, cpi->oxcf.input_bit_depth, cm->base_qindex);
if (codec_status != VPX_CODEC_OK) {
vpx_internal_error(&cm->error, codec_status,
"vp9_extrc_update_encodeframe_result() failed");