summaryrefslogtreecommitdiff
path: root/vp9/encoder
diff options
context:
space:
mode:
Diffstat (limited to 'vp9/encoder')
-rw-r--r--vp9/encoder/vp9_bitstream.c26
-rw-r--r--vp9/encoder/vp9_onyx_if.c21
2 files changed, 42 insertions, 5 deletions
diff --git a/vp9/encoder/vp9_bitstream.c b/vp9/encoder/vp9_bitstream.c
index c02ae1b65..1a9d33dae 100644
--- a/vp9/encoder/vp9_bitstream.c
+++ b/vp9/encoder/vp9_bitstream.c
@@ -1772,10 +1772,30 @@ void vp9_pack_bitstream(VP9_COMP *cpi, unsigned char *dest,
// When there is a key frame all reference buffers are updated using the new key frame
if (pc->frame_type != KEY_FRAME) {
+ int refresh_mask;
+
// Should the GF or ARF be updated using the transmitted frame or buffer
- vp9_write_bit(&header_bc, cpi->refresh_alt_ref_frame);
- vp9_write_bit(&header_bc, cpi->refresh_golden_frame);
- vp9_write_bit(&header_bc, cpi->refresh_last_frame);
+ if (cpi->refresh_golden_frame && !cpi->refresh_alt_ref_frame) {
+ /* Preserve the previously existing golden frame and update the frame in
+ * the alt ref slot instead. This is highly specific to the use of
+ * alt-ref as a forward reference, and this needs to be generalized as
+ * other uses are implemented (like RTC/temporal scaling)
+ *
+ * gld_fb_idx and alt_fb_idx need to be swapped for future frames, but
+ * that happens in vp9_onyx_if.c:update_reference_frames() so that it can
+ * be done outside of the recode loop.
+ */
+ refresh_mask = (cpi->refresh_last_frame << cpi->lst_fb_idx) |
+ (cpi->refresh_golden_frame << cpi->alt_fb_idx);
+ } else {
+ refresh_mask = (cpi->refresh_last_frame << cpi->lst_fb_idx) |
+ (cpi->refresh_golden_frame << cpi->gld_fb_idx) |
+ (cpi->refresh_alt_ref_frame << cpi->alt_fb_idx);
+ }
+ vp9_write_literal(&header_bc, refresh_mask, NUM_REF_FRAMES);
+ vp9_write_literal(&header_bc, cpi->lst_fb_idx, NUM_REF_FRAMES_LG2);
+ vp9_write_literal(&header_bc, cpi->gld_fb_idx, NUM_REF_FRAMES_LG2);
+ vp9_write_literal(&header_bc, cpi->alt_fb_idx, NUM_REF_FRAMES_LG2);
// Indicate reference frame sign bias for Golden and ARF frames (always 0 for last frame buffer)
vp9_write_bit(&header_bc, pc->ref_frame_sign_bias[GOLDEN_FRAME]);
diff --git a/vp9/encoder/vp9_onyx_if.c b/vp9/encoder/vp9_onyx_if.c
index 0f087df1e..c288f93ef 100644
--- a/vp9/encoder/vp9_onyx_if.c
+++ b/vp9/encoder/vp9_onyx_if.c
@@ -2573,13 +2573,30 @@ static void update_reference_frames(VP9_COMP * const cpi) {
// At this point the new frame has been encoded.
// If any buffer copy / swapping is signaled it should be done here.
-
if (cm->frame_type == KEY_FRAME) {
ref_cnt_fb(cm->fb_idx_ref_cnt,
&cm->active_ref_idx[cpi->gld_fb_idx], cm->new_fb_idx);
ref_cnt_fb(cm->fb_idx_ref_cnt,
&cm->active_ref_idx[cpi->alt_fb_idx], cm->new_fb_idx);
- } else { /* For non key frames */
+ } else if (cpi->refresh_golden_frame && !cpi->refresh_alt_ref_frame) {
+ /* Preserve the previously existing golden frame and update the frame in
+ * the alt ref slot instead. This is highly specific to the current use of
+ * alt-ref as a forward reference, and this needs to be generalized as
+ * other uses are implemented (like RTC/temporal scaling)
+ *
+ * The update to the buffer in the alt ref slot was signalled in
+ * vp9_pack_bitstream(), now swap the buffer pointers so that it's treated
+ * as the golden frame next time.
+ */
+ int tmp;
+
+ ref_cnt_fb(cm->fb_idx_ref_cnt,
+ &cm->active_ref_idx[cpi->alt_fb_idx], cm->new_fb_idx);
+
+ tmp = cpi->alt_fb_idx;
+ cpi->alt_fb_idx = cpi->gld_fb_idx;
+ cpi->gld_fb_idx = tmp;
+ } else { /* For non key/golden frames */
if (cpi->refresh_alt_ref_frame) {
ref_cnt_fb(cm->fb_idx_ref_cnt,
&cm->active_ref_idx[cpi->alt_fb_idx], cm->new_fb_idx);