summaryrefslogtreecommitdiff
path: root/vp9/encoder
diff options
context:
space:
mode:
Diffstat (limited to 'vp9/encoder')
-rw-r--r--vp9/encoder/vp9_encoder.c8
-rw-r--r--vp9/encoder/vp9_ext_ratectrl.c33
-rw-r--r--vp9/encoder/vp9_ext_ratectrl.h4
-rw-r--r--vp9/encoder/vp9_firstpass.c32
-rw-r--r--vp9/encoder/vp9_ratectrl.h4
5 files changed, 77 insertions, 4 deletions
diff --git a/vp9/encoder/vp9_encoder.c b/vp9/encoder/vp9_encoder.c
index 89b7c8e24..6d807b8ab 100644
--- a/vp9/encoder/vp9_encoder.c
+++ b/vp9/encoder/vp9_encoder.c
@@ -4488,7 +4488,8 @@ static void encode_with_recode_loop(VP9_COMP *cpi, size_t *size, uint8_t *dest
}
}
#endif // CONFIG_RATE_CTRL
- if (cpi->ext_ratectrl.ready && !ext_rc_recode) {
+ if (cpi->ext_ratectrl.ready && !ext_rc_recode &&
+ cpi->ext_ratectrl.funcs.rc_type == VPX_RC_QP) {
vpx_codec_err_t codec_status;
const GF_GROUP *gf_group = &cpi->twopass.gf_group;
vpx_rc_encodeframe_decision_t encode_frame_decision;
@@ -4548,7 +4549,8 @@ static void encode_with_recode_loop(VP9_COMP *cpi, size_t *size, uint8_t *dest
if (frame_over_shoot_limit == 0) frame_over_shoot_limit = 1;
}
- if (cpi->ext_ratectrl.ready) {
+ if (cpi->ext_ratectrl.ready &&
+ cpi->ext_ratectrl.funcs.rc_type == VPX_RC_QP) {
last_q_attempt = q;
// In general, for the external rate control, we take the qindex provided
// as input and encode the frame with this qindex faithfully. However,
@@ -5590,7 +5592,7 @@ static void encode_frame_to_data_rate(
// build the bitstream
vp9_pack_bitstream(cpi, dest, size);
- {
+ if (cpi->ext_ratectrl.ready) {
const RefCntBuffer *coded_frame_buf =
get_ref_cnt_buffer(cm, cm->new_fb_idx);
vpx_codec_err_t codec_status = vp9_extrc_update_encodeframe_result(
diff --git a/vp9/encoder/vp9_ext_ratectrl.c b/vp9/encoder/vp9_ext_ratectrl.c
index 67f58329c..48c90913e 100644
--- a/vp9/encoder/vp9_ext_ratectrl.c
+++ b/vp9/encoder/vp9_ext_ratectrl.c
@@ -172,7 +172,7 @@ vpx_codec_err_t vp9_extrc_update_encodeframe_result(
if (ext_ratectrl == NULL) {
return VPX_CODEC_INVALID_PARAM;
}
- if (ext_ratectrl->ready && ext_ratectrl->funcs.rc_type == VPX_RC_QP) {
+ if (ext_ratectrl->ready) {
PSNR_STATS psnr;
vpx_rc_status_t rc_status;
vpx_rc_encodeframe_result_t encode_frame_result;
@@ -198,3 +198,34 @@ vpx_codec_err_t vp9_extrc_update_encodeframe_result(
}
return VPX_CODEC_OK;
}
+
+vpx_codec_err_t vp9_extrc_get_gop_decision(
+ EXT_RATECTRL *ext_ratectrl, const vpx_rc_gop_info_t *const gop_info,
+ vpx_rc_gop_decision_t *gop_decision) {
+ if (ext_ratectrl == NULL) {
+ return VPX_CODEC_INVALID_PARAM;
+ }
+ if (ext_ratectrl->ready && ext_ratectrl->funcs.rc_type == VPX_RC_GOP) {
+ vpx_rc_status_t rc_status;
+ rc_status = ext_ratectrl->funcs.get_gop_decision(ext_ratectrl->model,
+ gop_info, gop_decision);
+ if (gop_decision->use_alt_ref) {
+ const int arf_constraint =
+ gop_decision->gop_coding_frames >= gop_info->min_gf_interval &&
+ gop_decision->gop_coding_frames < gop_info->lag_in_frames;
+ if (!arf_constraint || !gop_info->allow_alt_ref) return VPX_CODEC_ERROR;
+ }
+ // TODO(chengchen): Take min and max gf interval from the model
+ // and overwrite libvpx's decision so that we can get rid
+ // of one of the checks here.
+ if (gop_decision->gop_coding_frames > gop_info->frames_to_key ||
+ gop_decision->gop_coding_frames - gop_decision->use_alt_ref >
+ gop_info->max_gf_interval) {
+ return VPX_CODEC_ERROR;
+ }
+ if (rc_status == VPX_RC_ERROR) {
+ return VPX_CODEC_ERROR;
+ }
+ }
+ return VPX_CODEC_OK;
+}
diff --git a/vp9/encoder/vp9_ext_ratectrl.h b/vp9/encoder/vp9_ext_ratectrl.h
index 74fd68b96..b46b776b9 100644
--- a/vp9/encoder/vp9_ext_ratectrl.h
+++ b/vp9/encoder/vp9_ext_ratectrl.h
@@ -45,4 +45,8 @@ vpx_codec_err_t vp9_extrc_update_encodeframe_result(
const YV12_BUFFER_CONFIG *coded_frame, uint32_t bit_depth,
uint32_t input_bit_depth, const int actual_encoding_qindex);
+vpx_codec_err_t vp9_extrc_get_gop_decision(
+ EXT_RATECTRL *ext_ratectrl, const vpx_rc_gop_info_t *const gop_info,
+ vpx_rc_gop_decision_t *gop_decision);
+
#endif // VPX_VP9_ENCODER_VP9_EXT_RATECTRL_H_
diff --git a/vp9/encoder/vp9_firstpass.c b/vp9/encoder/vp9_firstpass.c
index 67302ed03..6e1f797f4 100644
--- a/vp9/encoder/vp9_firstpass.c
+++ b/vp9/encoder/vp9_firstpass.c
@@ -2714,6 +2714,9 @@ static void define_gf_group(VP9_COMP *cpi, int gf_start_show_idx) {
// frame in which case it will already have been done.
if (is_key_frame == 0) {
vp9_zero(twopass->gf_group);
+ ++rc->gop_id;
+ } else {
+ rc->gop_id = 0;
}
vpx_clear_system_state();
@@ -2751,6 +2754,35 @@ static void define_gf_group(VP9_COMP *cpi, int gf_start_show_idx) {
}
}
#endif
+ // If the external rate control model for GOP is used, the gop decisions
+ // are overwritten. Specifically, |gop_coding_frames| and |use_alt_ref|
+ // will be overwritten.
+ if (cpi->ext_ratectrl.ready &&
+ cpi->ext_ratectrl.funcs.rc_type == VPX_RC_GOP) {
+ vpx_codec_err_t codec_status;
+ vpx_rc_gop_decision_t gop_decision;
+ vpx_rc_gop_info_t gop_info;
+ gop_info.min_gf_interval = active_gf_interval.min;
+ gop_info.max_gf_interval = active_gf_interval.max;
+ gop_info.allow_alt_ref = allow_alt_ref;
+ gop_info.is_key_frame = is_key_frame;
+ gop_info.last_gop_use_alt_ref = rc->source_alt_ref_active;
+ gop_info.frames_since_key = rc->frames_since_key;
+ gop_info.frames_to_key = rc->frames_to_key;
+ gop_info.lag_in_frames = cpi->oxcf.lag_in_frames;
+ gop_info.show_index = cm->current_video_frame;
+ gop_info.coding_index = cm->current_frame_coding_index;
+ gop_info.gop_id = rc->gop_id;
+
+ codec_status = vp9_extrc_get_gop_decision(&cpi->ext_ratectrl, &gop_info,
+ &gop_decision);
+ if (codec_status != VPX_CODEC_OK) {
+ vpx_internal_error(&cm->error, codec_status,
+ "vp9_extrc_get_gop_decision() failed");
+ }
+ gop_coding_frames = gop_decision.gop_coding_frames;
+ use_alt_ref = gop_decision.use_alt_ref;
+ }
// Was the group length constrained by the requirement for a new KF?
rc->constrained_gf_group = (gop_coding_frames >= rc->frames_to_key) ? 1 : 0;
diff --git a/vp9/encoder/vp9_ratectrl.h b/vp9/encoder/vp9_ratectrl.h
index 83a12cde7..42547d1a6 100644
--- a/vp9/encoder/vp9_ratectrl.h
+++ b/vp9/encoder/vp9_ratectrl.h
@@ -211,6 +211,10 @@ typedef struct {
// Flag to constrain golden frame interval on key frame frequency for 1 pass
// VBR.
int constrain_gf_key_freq_onepass_vbr;
+
+ // The id of the current GOP. Start from zero.
+ // When a key frame is inserted, it resets to zero.
+ int gop_id;
} RATE_CONTROL;
struct VP9_COMP;