Preserve the previous golden frame on golden updates
This commit restores the quality lost when the buffer-to-buffer copy logic was removed. Note that this is specific to the current use of golden frames and will need rework when RTC functionality is added. Change-Id: I7324a75acd96eafd9e0f9b8633d782e390d5dc21
This commit is contained in:
parent
4b65837bc6
commit
26bd81b955
@ -87,14 +87,16 @@ int vp9_alloc_frame_buffers(VP9_COMMON *oci, int width, int height) {
|
||||
}
|
||||
}
|
||||
|
||||
oci->new_fb_idx = 0;
|
||||
for (i = 0; i < 3; i++)
|
||||
oci->active_ref_idx[i] = i + 1;
|
||||
oci->new_fb_idx = NUM_YV12_BUFFERS - 1;
|
||||
oci->fb_idx_ref_cnt[oci->new_fb_idx] = 1;
|
||||
|
||||
oci->fb_idx_ref_cnt[0] = 1;
|
||||
oci->fb_idx_ref_cnt[1] = 1;
|
||||
oci->fb_idx_ref_cnt[2] = 1;
|
||||
oci->fb_idx_ref_cnt[3] = 1;
|
||||
for (i = 0; i < 3; i++)
|
||||
oci->active_ref_idx[i] = i;
|
||||
|
||||
for (i = 0; i < NUM_REF_FRAMES; i++) {
|
||||
oci->ref_frame_map[i] = i;
|
||||
oci->fb_idx_ref_cnt[i] = 1;
|
||||
}
|
||||
|
||||
if (vp8_yv12_alloc_frame_buffer(&oci->temp_scale_frame, width, 16,
|
||||
VP9BORDERINPIXELS) < 0) {
|
||||
|
@ -38,6 +38,7 @@ void vp9_initialize_common(void);
|
||||
#define QINDEX_RANGE (MAXQ + 1)
|
||||
|
||||
#define NUM_REF_FRAMES 3
|
||||
#define NUM_REF_FRAMES_LG2 2
|
||||
#define NUM_YV12_BUFFERS (NUM_REF_FRAMES + 1)
|
||||
|
||||
#define NUM_FRAME_CONTEXTS_LG2 2
|
||||
@ -147,6 +148,11 @@ typedef struct VP9Common {
|
||||
|
||||
YV12_BUFFER_CONFIG yv12_fb[NUM_YV12_BUFFERS];
|
||||
int fb_idx_ref_cnt[NUM_YV12_BUFFERS]; /* reference counts */
|
||||
int ref_frame_map[NUM_REF_FRAMES]; /* maps fb_idx to reference slot */
|
||||
|
||||
/* TODO(jkoleszar): could expand active_ref_idx to 4, with 0 as intra, and
|
||||
* roll new_fb_idx into it.
|
||||
*/
|
||||
int active_ref_idx[3]; /* each frame can reference 3 buffers */
|
||||
int new_fb_idx;
|
||||
|
||||
|
@ -1634,10 +1634,21 @@ int vp9_decode_frame(VP9D_COMP *pbi, const unsigned char **p_data_end) {
|
||||
* For all non key frames the GF and ARF refresh flags and sign bias
|
||||
* flags must be set explicitly.
|
||||
*/
|
||||
if (pc->frame_type != KEY_FRAME) {
|
||||
if (pc->frame_type == KEY_FRAME) {
|
||||
pc->active_ref_idx[0] = pc->new_fb_idx;
|
||||
pc->active_ref_idx[1] = pc->new_fb_idx;
|
||||
pc->active_ref_idx[2] = pc->new_fb_idx;
|
||||
} else {
|
||||
/* Should the GF or ARF be updated from the current frame */
|
||||
pbi->refresh_frame_flags = vp9_read_literal(&header_bc, NUM_REF_FRAMES);
|
||||
|
||||
/* Select active reference frames */
|
||||
for (i = 0; i < 3; i++) {
|
||||
int ref_frame_num = vp9_read_literal(&header_bc, NUM_REF_FRAMES_LG2);
|
||||
|
||||
pc->active_ref_idx[i] = pc->ref_frame_map[ref_frame_num];
|
||||
}
|
||||
|
||||
pc->ref_frame_sign_bias[GOLDEN_FRAME] = vp9_read_bit(&header_bc);
|
||||
pc->ref_frame_sign_bias[ALTREF_FRAME] = vp9_read_bit(&header_bc);
|
||||
|
||||
|
@ -171,11 +171,7 @@ vpx_codec_err_t vp9_get_reference_dec(VP9D_PTR ptr, VP9_REFFRAME ref_frame_flag,
|
||||
* later commit that adds VP9-specific controls for this functionality.
|
||||
*/
|
||||
if (ref_frame_flag == VP9_LAST_FLAG)
|
||||
ref_fb_idx = pbi->common.active_ref_idx[0];
|
||||
else if (ref_frame_flag == VP9_GOLD_FLAG)
|
||||
ref_fb_idx = pbi->common.active_ref_idx[1];
|
||||
else if (ref_frame_flag == VP9_ALT_FLAG)
|
||||
ref_fb_idx = pbi->common.active_ref_idx[2];
|
||||
ref_fb_idx = pbi->common.new_fb_idx;
|
||||
else {
|
||||
vpx_internal_error(&pbi->common.error, VPX_CODEC_ERROR,
|
||||
"Invalid reference frame");
|
||||
@ -248,7 +244,7 @@ static void swap_frame_buffers(VP9D_COMP *pbi) {
|
||||
for (mask = pbi->refresh_frame_flags; mask; mask >>= 1) {
|
||||
if (mask & 1) {
|
||||
ref_cnt_fb(pbi->common.fb_idx_ref_cnt,
|
||||
&pbi->common.active_ref_idx[ref_index],
|
||||
&pbi->common.ref_frame_map[ref_index],
|
||||
pbi->common.new_fb_idx);
|
||||
}
|
||||
++ref_index;
|
||||
@ -256,6 +252,10 @@ static void swap_frame_buffers(VP9D_COMP *pbi) {
|
||||
|
||||
pbi->common.frame_to_show = &pbi->common.yv12_fb[pbi->common.new_fb_idx];
|
||||
pbi->common.fb_idx_ref_cnt[pbi->common.new_fb_idx]--;
|
||||
|
||||
/* Invalidate these references until the next frame starts. */
|
||||
for (ref_index = 0; ref_index < 3; ref_index++)
|
||||
pbi->common.active_ref_idx[ref_index] = INT_MAX;
|
||||
}
|
||||
|
||||
int vp9_receive_compressed_data(VP9D_PTR ptr, unsigned long size,
|
||||
|
@ -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]);
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user