primary_ref_frame order_offset to EncodeFrameParams
primary_ref_frame was set in setup_frame() called by
encode_with_recode_loop(). The determination was made using
fb_of_context_type[] which was setup in setup_frame() and
finalize_encoded_frame(). This patch moves the determination to
choose_primary_ref_frame() called by av1_encode_strategy().
fb_of_context_type[] is now updated by update_fb_of_context_type(), also
called by av1_encode_strategy. primary_ref_frame is passed to the low
level encoder as part of EncodeFrameParams (and copied to its previous
location in av1_encode()).
Remove cm->force_primary_ref_none and just directly access
cpi->ext_use_primary_ref_none
Add order_offset to EncodeFrameParams, used by av1_encode() to calculate
the order_hint for this frame. order_offset is now calculated in
encode_strategy.c
Move the resetting of frame_number to 0 upon shown-keyframe to
av1_encode() so it happens before order_hint is calculated.
This forms part of wider restructuring and refactoring in order to
achieve a clean API separation at the entry to the low-level encoder.
BUG=aomedia:2244
Change-Id: I04c786a7d4389dcc8173c3a6ba3d58e217be3035
diff --git a/av1/common/onyxc_int.h b/av1/common/onyxc_int.h
index 9e9158b..56f823e 100644
--- a/av1/common/onyxc_int.h
+++ b/av1/common/onyxc_int.h
@@ -501,7 +501,6 @@
int primary_ref_frame;
int error_resilient_mode;
- int force_primary_ref_none;
int tile_cols, tile_rows;
diff --git a/av1/encoder/encode_strategy.c b/av1/encoder/encode_strategy.c
index 46ae166..92afca6 100644
--- a/av1/encoder/encode_strategy.c
+++ b/av1/encoder/encode_strategy.c
@@ -138,7 +138,6 @@
if (cpi->ext_use_s_frame) {
frame_params->frame_type = S_FRAME;
}
- cm->force_primary_ref_none = cpi->ext_use_primary_ref_none;
if (cpi->ext_refresh_frame_context_pending) {
cm->refresh_frame_context = cpi->ext_refresh_frame_context;
@@ -237,6 +236,109 @@
return flags;
}
+static int get_current_frame_ref_type(
+ const AV1_COMP *const cpi, const EncodeFrameParams *const frame_params) {
+ const GF_GROUP *const gf_group = &cpi->twopass.gf_group;
+ // We choose the reference "type" of this frame from the flags which indicate
+ // which reference frames will be refreshed by it. More than one of these
+ // flags may be set, so the order here implies an order of precedence.
+
+ const int intra_only = frame_params->frame_type == KEY_FRAME ||
+ frame_params->frame_type == INTRA_ONLY_FRAME;
+ if (intra_only || frame_params->error_resilient_mode ||
+ cpi->ext_use_primary_ref_none)
+ return REGULAR_FRAME;
+ else if (gf_group->update_type[gf_group->index] == INTNL_ARF_UPDATE)
+ return EXT_ARF_FRAME;
+ else if (cpi->refresh_alt_ref_frame)
+ return ARF_FRAME;
+ else if (cpi->rc.is_src_frame_alt_ref)
+ return OVERLAY_FRAME;
+ else if (cpi->refresh_golden_frame)
+ return GLD_FRAME;
+ else if (cpi->refresh_bwd_ref_frame)
+ return BRF_FRAME;
+ else
+ return REGULAR_FRAME;
+}
+
+static int choose_primary_ref_frame(
+ const AV1_COMP *const cpi, const EncodeFrameParams *const frame_params) {
+ const AV1_COMMON *const cm = &cpi->common;
+
+ const int intra_only = frame_params->frame_type == KEY_FRAME ||
+ frame_params->frame_type == INTRA_ONLY_FRAME;
+ if (intra_only || frame_params->error_resilient_mode ||
+ cpi->ext_use_primary_ref_none) {
+ return PRIMARY_REF_NONE;
+ }
+
+ // Find the most recent reference frame with the same reference type as the
+ // current frame
+ const FRAME_CONTEXT_INDEX current_ref_type =
+ get_current_frame_ref_type(cpi, frame_params);
+ int wanted_fb = cpi->fb_of_context_type[current_ref_type];
+
+ int primary_ref_frame = PRIMARY_REF_NONE;
+ for (int ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ref_frame++) {
+ if (get_ref_frame_map_idx(cm, ref_frame) == wanted_fb) {
+ primary_ref_frame = ref_frame - LAST_FRAME;
+ }
+ }
+ return primary_ref_frame;
+}
+
+static void update_fb_of_context_type(
+ const AV1_COMP *const cpi, const EncodeFrameParams *const frame_params,
+ int *const fb_of_context_type) {
+ const AV1_COMMON *const cm = &cpi->common;
+
+ if (frame_is_intra_only(cm) || cm->error_resilient_mode ||
+ cpi->ext_use_primary_ref_none) {
+ for (int i = 0; i < REF_FRAMES; i++) {
+ fb_of_context_type[i] = -1;
+ }
+ fb_of_context_type[REGULAR_FRAME] =
+ cm->show_frame ? get_ref_frame_map_idx(cm, GOLDEN_FRAME)
+ : get_ref_frame_map_idx(cm, ALTREF_FRAME);
+ }
+
+ if (!encode_show_existing_frame(cm)) {
+ // Refresh fb_of_context_type[]: see encoder.h for explanation
+ // Note that we want the value of refresh_frame_flags for the frame that
+ // just happened. If we call get_refresh_frame_flags now we will get a
+ // different answer, because update_reference_frames() has happened.
+ if (cm->current_frame.frame_type == KEY_FRAME) {
+ // All ref frames are refreshed, pick one that will live long enough
+ fb_of_context_type[REGULAR_FRAME] = 0;
+ } else {
+ // If more than one frame is refreshed, it doesn't matter which one we
+ // pick so pick the first. LST sometimes doesn't refresh any: this is ok
+ const int current_frame_ref_type =
+ get_current_frame_ref_type(cpi, frame_params);
+ for (int i = 0; i < REF_FRAMES; i++) {
+ if (cm->current_frame.refresh_frame_flags & (1 << i)) {
+ fb_of_context_type[current_frame_ref_type] = i;
+ break;
+ }
+ }
+ }
+ }
+}
+
+static int get_order_offset(const AV1_COMP *const cpi) {
+ // shown frame by definition has order offset 0
+ // show_existing_frame ignores order_offset and simply takes the order_hint
+ // from the reference frame being shown.
+ if (cpi->common.show_frame || cpi->common.show_existing_frame) return 0;
+
+ const GF_GROUP *const gf_group = &cpi->twopass.gf_group;
+ const int arf_offset =
+ AOMMIN((MAX_GF_INTERVAL - 1), gf_group->arf_src_offset[gf_group->index]);
+ const int brf_offset = gf_group->brf_src_offset[gf_group->index];
+ return AOMMIN((MAX_GF_INTERVAL - 1), arf_offset + brf_offset);
+}
+
int av1_encode_strategy(AV1_COMP *const cpi, size_t *const size,
uint8_t *const dest, unsigned int *frame_flags,
const EncodeFrameInput *const frame_input) {
@@ -314,6 +416,12 @@
frame_params.ref_frame_flags = get_ref_frame_flags(cpi);
}
+ if (oxcf->pass == 0 || oxcf->pass == 2) {
+ frame_params.primary_ref_frame =
+ choose_primary_ref_frame(cpi, &frame_params);
+ frame_params.order_offset = get_order_offset(cpi);
+ }
+
if (av1_encode(cpi, dest, frame_input, &frame_params, &frame_results) !=
AOM_CODEC_OK) {
return AOM_CODEC_ERROR;
@@ -332,6 +440,7 @@
}
if (oxcf->pass == 0 || oxcf->pass == 2) {
+ update_fb_of_context_type(cpi, &frame_params, cpi->fb_of_context_type);
set_additional_frame_flags(cm, frame_params.frame_flags);
update_rc_counts(cpi);
check_show_existing_frame(cpi); // Is next frame a show_existing frame?
diff --git a/av1/encoder/encodeframe.c b/av1/encoder/encodeframe.c
index f06cf25..7271c37 100644
--- a/av1/encoder/encodeframe.c
+++ b/av1/encoder/encodeframe.c
@@ -6418,20 +6418,6 @@
// rather than the potential full set of 16 transforms
cm->reduced_tx_set_used = cpi->oxcf.reduced_tx_type_set;
- if (cm->show_frame == 0) {
- int arf_offset = AOMMIN(
- (MAX_GF_INTERVAL - 1),
- cpi->twopass.gf_group.arf_src_offset[cpi->twopass.gf_group.index]);
- int brf_offset =
- cpi->twopass.gf_group.brf_src_offset[cpi->twopass.gf_group.index];
- arf_offset = AOMMIN((MAX_GF_INTERVAL - 1), arf_offset + brf_offset);
- current_frame->order_hint = current_frame->frame_number + arf_offset;
- } else {
- current_frame->order_hint = current_frame->frame_number;
- }
- current_frame->order_hint %=
- (1 << (cm->seq_params.order_hint_info.order_hint_bits_minus_1 + 1));
-
// Make sure segment_id is no larger than last_active_segid.
if (cm->seg.enabled && cm->seg.update_map) {
const int mi_rows = cm->mi_rows;
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c
index 1037318..c3418c6 100644
--- a/av1/encoder/encoder.c
+++ b/av1/encoder/encoder.c
@@ -370,30 +370,6 @@
return BLOCK_128X128;
}
-static int get_current_frame_ref_type(const AV1_COMP *const cpi) {
- const AV1_COMMON *const cm = &cpi->common;
- const GF_GROUP *const gf_group = &cpi->twopass.gf_group;
- // We choose the reference "type" of this frame from the flags which indicate
- // which reference frames will be refreshed by it. More than one of these
- // flags may be set, so the order here implies an order of precedence.
-
- if (frame_is_intra_only(cm) || cm->error_resilient_mode ||
- cm->force_primary_ref_none)
- return REGULAR_FRAME;
- else if (gf_group->update_type[gf_group->index] == INTNL_ARF_UPDATE)
- return EXT_ARF_FRAME;
- else if (cpi->refresh_alt_ref_frame)
- return ARF_FRAME;
- else if (cpi->rc.is_src_frame_alt_ref)
- return OVERLAY_FRAME;
- else if (cpi->refresh_golden_frame)
- return GLD_FRAME;
- else if (cpi->refresh_bwd_ref_frame)
- return BRF_FRAME;
- else
- return REGULAR_FRAME;
-}
-
static void setup_frame(AV1_COMP *cpi) {
AV1_COMMON *const cm = &cpi->common;
// Set up entropy context depending on frame type. The decoder mandates
@@ -402,24 +378,9 @@
// other inter-frames the encoder currently uses only two contexts;
// context 1 for ALTREF frames and context 0 for the others.
- cm->primary_ref_frame = PRIMARY_REF_NONE;
if (frame_is_intra_only(cm) || cm->error_resilient_mode ||
- cm->force_primary_ref_none) {
+ cpi->ext_use_primary_ref_none) {
av1_setup_past_independence(cm);
- for (int i = 0; i < REF_FRAMES; i++) {
- cpi->fb_of_context_type[i] = -1;
- }
- cpi->fb_of_context_type[REGULAR_FRAME] =
- cm->show_frame ? get_ref_frame_map_idx(cm, GOLDEN_FRAME)
- : get_ref_frame_map_idx(cm, ALTREF_FRAME);
- } else {
- int wanted_fb = cpi->fb_of_context_type[get_current_frame_ref_type(cpi)];
- for (int ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ref_frame++) {
- int fb = get_ref_frame_map_idx(cm, ref_frame);
- if (fb == wanted_fb) {
- cm->primary_ref_frame = ref_frame - LAST_FRAME;
- }
- }
}
if (cm->current_frame.frame_type == KEY_FRAME && cm->show_frame) {
@@ -4519,24 +4480,6 @@
// the current frame
current_frame->refresh_frame_flags = get_refresh_frame_flags(cpi);
- if (!encode_show_existing_frame(cm)) {
- // Refresh fb_of_context_type[]: see encoder.h for explanation
- if (current_frame->frame_type == KEY_FRAME) {
- // All ref frames are refreshed, pick one that will live long enough
- cpi->fb_of_context_type[REGULAR_FRAME] = 0;
- } else {
- // If more than one frame is refreshed, it doesn't matter which one we
- // pick so pick the first. LST sometimes doesn't refresh any: this is ok
- const int current_frame_ref_type = get_current_frame_ref_type(cpi);
- for (int i = 0; i < REF_FRAMES; i++) {
- if (current_frame->refresh_frame_flags & (1 << i)) {
- cpi->fb_of_context_type[current_frame_ref_type] = i;
- break;
- }
- }
- }
- }
-
if (!cm->seq_params.reduced_still_picture_hdr &&
encode_show_existing_frame(cm)) {
RefCntBuffer *const frame_to_show =
@@ -5149,10 +5092,6 @@
cm->allow_warped_motion =
cpi->oxcf.allow_warped_motion && frame_might_allow_warped_motion(cm);
- // Reset the frame packet stamp index.
- if (current_frame->frame_type == KEY_FRAME && cm->show_frame)
- current_frame->frame_number = 0;
-
cm->last_frame_type = current_frame->frame_type;
if (cpi->oxcf.pass == 2 && cpi->sf.adaptive_interp_filter_search)
cpi->sf.interp_filter_search_mask = setup_interp_filter_search_mask(cpi);
@@ -5181,9 +5120,6 @@
cpi->seq_params_locked = 1;
- // Update current frame offset.
- current_frame->order_hint = cm->cur_frame->order_hint;
-
#if DUMP_RECON_FRAMES == 1
// NOTE(zoeliu): For debug - Output the filtered reconstructed video.
dump_filtered_recon_frames(cpi);
@@ -5516,16 +5452,30 @@
const EncodeFrameParams *const frame_params,
EncodeFrameResults *const frame_results) {
AV1_COMMON *const cm = &cpi->common;
+ CurrentFrame *const current_frame = &cm->current_frame;
cpi->unscaled_source = frame_input->source;
cpi->source = frame_input->source;
cpi->unscaled_last_source = frame_input->last_source;
cm->error_resilient_mode = frame_params->error_resilient_mode;
+ cm->primary_ref_frame = frame_params->primary_ref_frame;
cm->current_frame.frame_type = frame_params->frame_type;
cpi->ref_frame_flags = frame_params->ref_frame_flags;
cpi->speed = frame_params->speed;
+ if (current_frame->frame_type == KEY_FRAME && cm->show_frame)
+ current_frame->frame_number = 0;
+
+ if (cm->show_existing_frame) {
+ current_frame->order_hint = cm->cur_frame->order_hint;
+ } else {
+ current_frame->order_hint =
+ current_frame->frame_number + frame_params->order_offset;
+ current_frame->order_hint %=
+ (1 << (cm->seq_params.order_hint_info.order_hint_bits_minus_1 + 1));
+ }
+
if (cpi->oxcf.pass == 1) {
av1_first_pass(cpi, frame_input->ts_duration);
} else if (cpi->oxcf.pass == 0 || cpi->oxcf.pass == 2) {
diff --git a/av1/encoder/encoder.h b/av1/encoder/encoder.h
index 2b4ef11..251a917 100644
--- a/av1/encoder/encoder.h
+++ b/av1/encoder/encoder.h
@@ -883,6 +883,8 @@
struct EncodeFrameParams {
int error_resilient_mode;
FRAME_TYPE frame_type;
+ int primary_ref_frame;
+ int order_offset;
// This is a bitmask of which reference slots can be used in this frame
int ref_frame_flags;