Fix key frames forced by application.
(Cherry picked from b436ce7d60aa8114a59fcabf3e45a69194ecca98)
Change-Id: If1922e77550d1730af7cc8dc55f002ff2a794890
diff --git a/av1/encoder/encode_strategy.c b/av1/encoder/encode_strategy.c
index 1631bab..36eaa55 100644
--- a/av1/encoder/encode_strategy.c
+++ b/av1/encoder/encode_strategy.c
@@ -419,23 +419,23 @@
}
// Determine whether there is a forced keyframe pending in the lookahead buffer
-static int is_forced_keyframe_pending(struct lookahead_ctx *lookahead,
- const int up_to_index,
- const COMPRESSOR_STAGE compressor_stage) {
+int is_forced_keyframe_pending(struct lookahead_ctx *lookahead,
+ const int up_to_index,
+ const COMPRESSOR_STAGE compressor_stage) {
for (int i = 0; i <= up_to_index; i++) {
const struct lookahead_entry *e =
av1_lookahead_peek(lookahead, i, compressor_stage);
if (e == NULL) {
// We have reached the end of the lookahead buffer and not early-returned
// so there isn't a forced key-frame pending.
- return 0;
+ return -1;
} else if (e->flags == AOM_EFLAG_FORCE_KF) {
- return 1;
+ return (i + 1);
} else {
continue;
}
}
- return 0; // Never reached
+ return -1; // Never reached
}
// Check if we should encode an ARF or internal ARF. If not, try a LAST
@@ -452,8 +452,11 @@
// Should we encode an alt-ref frame.
int arf_src_index = get_arf_src_index(&cpi->gf_group, cpi->oxcf.pass);
- if (arf_src_index && is_forced_keyframe_pending(cpi->lookahead, arf_src_index,
- cpi->compressor_stage)) {
+ // TODO(Aasaipriya): Forced key frames need to be fixed when rc_mode != AOM_Q
+ if (arf_src_index &&
+ (is_forced_keyframe_pending(cpi->lookahead, arf_src_index,
+ cpi->compressor_stage) != -1) &&
+ cpi->oxcf.rc_mode != AOM_Q) {
arf_src_index = 0;
*flush = 1;
}
diff --git a/av1/encoder/encode_strategy.h b/av1/encoder/encode_strategy.h
index 552b7e4..b05224b 100644
--- a/av1/encoder/encode_strategy.h
+++ b/av1/encoder/encode_strategy.h
@@ -54,6 +54,9 @@
void av1_get_ref_frames(AV1_COMP *const cpi, RefBufferStack *ref_buffer_stack);
+int is_forced_keyframe_pending(struct lookahead_ctx *lookahead,
+ const int up_to_index,
+ const COMPRESSOR_STAGE compressor_stage);
#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/av1/encoder/pass2_strategy.c b/av1/encoder/pass2_strategy.c
index 99be5aa..149de63 100644
--- a/av1/encoder/pass2_strategy.c
+++ b/av1/encoder/pass2_strategy.c
@@ -28,6 +28,7 @@
#include "av1/encoder/ratectrl.h"
#include "av1/encoder/tpl_model.h"
#include "av1/encoder/use_flat_gop_model_params.h"
+#include "av1/encoder/encode_strategy.h"
#define DEFAULT_KF_BOOST 2300
#define DEFAULT_GF_BOOST 2000
@@ -1607,7 +1608,8 @@
// MIN_FWD_KF_INTERVAL.
if (cpi->oxcf.fwd_kf_enabled && use_alt_ref &&
((twopass->stats_in - i + rc->frames_to_key) <
- twopass->stats_buf_ctx->stats_in_end)) {
+ twopass->stats_buf_ctx->stats_in_end) &&
+ cpi->rc.next_is_fwd_key) {
if (i == rc->frames_to_key) {
rc->baseline_gf_interval = i;
// if the last gf group will be smaller than MIN_FWD_KF_INTERVAL
@@ -1870,6 +1872,14 @@
#define MIN_KF_BOOST 600 // Minimum boost for non-static KF interval
#define MIN_STATIC_KF_BOOST 5400 // Minimum boost for static KF interval
+static int detect_app_forced_key(AV1_COMP *cpi) {
+ if (cpi->oxcf.fwd_kf_enabled) cpi->rc.next_is_fwd_key = 1;
+ int num_frames_to_app_forced_key = is_forced_keyframe_pending(
+ cpi->lookahead, cpi->lookahead->max_sz, cpi->compressor_stage);
+ if (num_frames_to_app_forced_key != -1) cpi->rc.next_is_fwd_key = 0;
+ return num_frames_to_app_forced_key;
+}
+
static void find_next_key_frame(AV1_COMP *cpi, FIRSTPASS_STATS *this_frame) {
RATE_CONTROL *const rc = &cpi->rc;
TWO_PASS *const twopass = &cpi->twopass;
@@ -1898,10 +1908,15 @@
rc->frames_to_key = 1;
+ int num_frames_to_app_forced_key = detect_app_forced_key(cpi);
+
if (has_no_stats_stage(cpi)) {
rc->this_key_frame_forced =
current_frame->frame_number != 0 && rc->frames_to_key == 0;
- rc->frames_to_key = cpi->oxcf.key_freq;
+ if (num_frames_to_app_forced_key != -1)
+ rc->frames_to_key = num_frames_to_app_forced_key;
+ else
+ rc->frames_to_key = AOMMAX(1, cpi->oxcf.key_freq);
rc->kf_boost = DEFAULT_KF_BOOST;
rc->source_alt_ref_active = 0;
gf_group->update_type[0] = KF_UPDATE;
@@ -1918,6 +1933,7 @@
double kf_group_err = 0.0;
double recent_loop_decay[FRAMES_TO_CHECK_DECAY];
double sr_accumulator = 0.0;
+ int num_frames_to_check = cpi->oxcf.key_freq;
rc->num_stats_used_for_kf_boost = 1;
// Is this a forced key frame by interval.
@@ -1932,10 +1948,12 @@
// Initialize the decay rates for the recent frames to check
for (j = 0; j < FRAMES_TO_CHECK_DECAY; ++j) recent_loop_decay[j] = 1.0;
+ if (num_frames_to_app_forced_key != -1)
+ num_frames_to_check = num_frames_to_app_forced_key;
// Find the next keyframe.
i = 0;
while (twopass->stats_in < twopass->stats_buf_ctx->stats_in_end &&
- rc->frames_to_key < cpi->oxcf.key_freq) {
+ rc->frames_to_key < num_frames_to_check) {
// Accumulate total number of stats available till next key frame
rc->num_stats_used_for_kf_boost++;
@@ -1991,8 +2009,12 @@
* When lap_enabled forcing frames_to_key as key_freq,
* since all frame stats are not available.
*/
- if (cpi->lap_enabled) rc->frames_to_key = cpi->oxcf.key_freq;
-
+ if (cpi->lap_enabled) {
+ if (num_frames_to_app_forced_key != -1)
+ rc->frames_to_key = num_frames_to_app_forced_key;
+ else
+ rc->frames_to_key = AOMMAX(1, cpi->oxcf.key_freq);
+ }
// If there is a max kf interval set by the user we must obey it.
// We already breakout of the loop above at 2x max.
// This code centers the extra kf if the actual natural interval
@@ -2339,6 +2361,10 @@
if (rc->frames_till_gf_update_due == 0) {
assert(cpi->common.current_frame.frame_number == 0 ||
gf_group->index == gf_group->size);
+ int num_frames_to_app_forced_key = detect_app_forced_key(cpi);
+ if (num_frames_to_app_forced_key != -1)
+ rc->frames_to_key = num_frames_to_app_forced_key;
+
int max_gop_length = (cpi->oxcf.lag_in_frames >= 32) ? MAX_GF_INTERVAL : 16;
if (rc->intervals_till_gf_calculate_due == 0) {
calculate_gf_length(cpi, max_gop_length, MAX_NUM_GF_INTERVALS);
diff --git a/av1/encoder/ratectrl.h b/av1/encoder/ratectrl.h
index 05f11fb..fca49ca 100644
--- a/av1/encoder/ratectrl.h
+++ b/av1/encoder/ratectrl.h
@@ -179,6 +179,7 @@
int num_stats_used_for_gfu_boost;
// Total number of stats required by gfu_boost calculation.
int num_stats_required_for_gfu_boost;
+ int next_is_fwd_key;
} RATE_CONTROL;
struct AV1_COMP;