Commit bed59eb8 authored by John Koleszar's avatar John Koleszar Committed by Gerrit Code Review

Merge changes Ia82cef79,I7324a75a,I7b66daad,I73344451,I91dc210f,I5945b5ce into experimental

* changes:
  Use alt-ref frame context for keyframes
  Preserve the previous golden frame on golden updates
  Generalize and increase frame coding contexts
  Start to anonymize reference frames
  Update encoder to use fb_idx_ref_cnt
  Remove buffer-to-buffer copy logic
parents b95ed688 2f24ad9e
...@@ -80,7 +80,6 @@ int vp9_alloc_frame_buffers(VP9_COMMON *oci, int width, int height) { ...@@ -80,7 +80,6 @@ int vp9_alloc_frame_buffers(VP9_COMMON *oci, int width, int height) {
for (i = 0; i < NUM_YV12_BUFFERS; i++) { for (i = 0; i < NUM_YV12_BUFFERS; i++) {
oci->fb_idx_ref_cnt[i] = 0; oci->fb_idx_ref_cnt[i] = 0;
oci->yv12_fb[i].flags = 0;
if (vp8_yv12_alloc_frame_buffer(&oci->yv12_fb[i], width, height, if (vp8_yv12_alloc_frame_buffer(&oci->yv12_fb[i], width, height,
VP9BORDERINPIXELS) < 0) { VP9BORDERINPIXELS) < 0) {
vp9_de_alloc_frame_buffers(oci); vp9_de_alloc_frame_buffers(oci);
...@@ -88,15 +87,16 @@ int vp9_alloc_frame_buffers(VP9_COMMON *oci, int width, int height) { ...@@ -88,15 +87,16 @@ int vp9_alloc_frame_buffers(VP9_COMMON *oci, int width, int height) {
} }
} }
oci->new_fb_idx = 0; oci->new_fb_idx = NUM_YV12_BUFFERS - 1;
oci->lst_fb_idx = 1; oci->fb_idx_ref_cnt[oci->new_fb_idx] = 1;
oci->gld_fb_idx = 2;
oci->alt_fb_idx = 3;
oci->fb_idx_ref_cnt[0] = 1; for (i = 0; i < 3; i++)
oci->fb_idx_ref_cnt[1] = 1; oci->active_ref_idx[i] = i;
oci->fb_idx_ref_cnt[2] = 1;
oci->fb_idx_ref_cnt[3] = 1; 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, if (vp8_yv12_alloc_frame_buffer(&oci->temp_scale_frame, width, 16,
VP9BORDERINPIXELS) < 0) { VP9BORDERINPIXELS) < 0) {
...@@ -204,9 +204,6 @@ void vp9_create_common(VP9_COMMON *oci) { ...@@ -204,9 +204,6 @@ void vp9_create_common(VP9_COMMON *oci) {
/* Initialise reference frame sign bias structure to defaults */ /* Initialise reference frame sign bias structure to defaults */
vpx_memset(oci->ref_frame_sign_bias, 0, sizeof(oci->ref_frame_sign_bias)); vpx_memset(oci->ref_frame_sign_bias, 0, sizeof(oci->ref_frame_sign_bias));
/* Default disable buffer to buffer copying */
oci->copy_buffer_to_gf = 0;
oci->copy_buffer_to_arf = 0;
oci->kf_ymode_probs_update = 0; oci->kf_ymode_probs_update = 0;
} }
......
...@@ -37,7 +37,12 @@ void vp9_initialize_common(void); ...@@ -37,7 +37,12 @@ void vp9_initialize_common(void);
#define QINDEX_RANGE (MAXQ + 1) #define QINDEX_RANGE (MAXQ + 1)
#define NUM_YV12_BUFFERS 4 #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
#define NUM_FRAME_CONTEXTS (1 << NUM_FRAME_CONTEXTS_LG2)
#define COMP_PRED_CONTEXTS 2 #define COMP_PRED_CONTEXTS 2
...@@ -142,8 +147,14 @@ typedef struct VP9Common { ...@@ -142,8 +147,14 @@ typedef struct VP9Common {
YV12_BUFFER_CONFIG *frame_to_show; YV12_BUFFER_CONFIG *frame_to_show;
YV12_BUFFER_CONFIG yv12_fb[NUM_YV12_BUFFERS]; YV12_BUFFER_CONFIG yv12_fb[NUM_YV12_BUFFERS];
int fb_idx_ref_cnt[NUM_YV12_BUFFERS]; int fb_idx_ref_cnt[NUM_YV12_BUFFERS]; /* reference counts */
int new_fb_idx, lst_fb_idx, gld_fb_idx, alt_fb_idx; 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;
YV12_BUFFER_CONFIG post_proc_buffer; YV12_BUFFER_CONFIG post_proc_buffer;
YV12_BUFFER_CONFIG temp_scale_frame; YV12_BUFFER_CONFIG temp_scale_frame;
...@@ -202,13 +213,6 @@ typedef struct VP9Common { ...@@ -202,13 +213,6 @@ typedef struct VP9Common {
int last_sharpness_level; int last_sharpness_level;
int sharpness_level; int sharpness_level;
int refresh_last_frame; /* Two state 0 = NO, 1 = YES */
int refresh_golden_frame; /* Two state 0 = NO, 1 = YES */
int refresh_alt_ref_frame; /* Two state 0 = NO, 1 = YES */
int copy_buffer_to_gf; /* 0 none, 1 Last to GF, 2 ARF to GF */
int copy_buffer_to_arf; /* 0 none, 1 Last to ARF, 2 GF to ARF */
int refresh_entropy_probs; /* Two state 0 = NO, 1 = YES */ int refresh_entropy_probs; /* Two state 0 = NO, 1 = YES */
int ref_frame_sign_bias[MAX_REF_FRAMES]; /* Two state 0, 1 */ int ref_frame_sign_bias[MAX_REF_FRAMES]; /* Two state 0, 1 */
...@@ -250,9 +254,9 @@ typedef struct VP9Common { ...@@ -250,9 +254,9 @@ typedef struct VP9Common {
vp9_prob mbskip_pred_probs[MBSKIP_CONTEXTS]; vp9_prob mbskip_pred_probs[MBSKIP_CONTEXTS];
FRAME_CONTEXT lfc_a; /* last alt ref entropy */
FRAME_CONTEXT lfc; /* last frame entropy */
FRAME_CONTEXT fc; /* this frame entropy */ FRAME_CONTEXT fc; /* this frame entropy */
FRAME_CONTEXT frame_contexts[NUM_FRAME_CONTEXTS];
unsigned int frame_context_idx; /* Context to use/update */
unsigned int current_video_frame; unsigned int current_video_frame;
int near_boffset[3]; int near_boffset[3];
...@@ -274,4 +278,24 @@ typedef struct VP9Common { ...@@ -274,4 +278,24 @@ typedef struct VP9Common {
} VP9_COMMON; } VP9_COMMON;
static int get_free_fb(VP9_COMMON *cm) {
int i;
for (i = 0; i < NUM_YV12_BUFFERS; i++)
if (cm->fb_idx_ref_cnt[i] == 0)
break;
assert(i < NUM_YV12_BUFFERS);
cm->fb_idx_ref_cnt[i] = 1;
return i;
}
static void ref_cnt_fb(int *buf, int *idx, int new_idx) {
if (buf[*idx] > 0)
buf[*idx]--;
*idx = new_idx;
buf[new_idx]++;
}
#endif // VP9_COMMON_VP9_ONYXC_INT_H_ #endif // VP9_COMMON_VP9_ONYXC_INT_H_
...@@ -730,12 +730,7 @@ static void read_mb_modes_mv(VP9D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi, ...@@ -730,12 +730,7 @@ static void read_mb_modes_mv(VP9D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi,
int ref_fb_idx; int ref_fb_idx;
/* Select the appropriate reference frame for this MB */ /* Select the appropriate reference frame for this MB */
if (ref_frame == LAST_FRAME) ref_fb_idx = cm->active_ref_idx[ref_frame - 1];
ref_fb_idx = cm->lst_fb_idx;
else if (ref_frame == GOLDEN_FRAME)
ref_fb_idx = cm->gld_fb_idx;
else
ref_fb_idx = cm->alt_fb_idx;
recon_y_stride = cm->yv12_fb[ref_fb_idx].y_stride ; recon_y_stride = cm->yv12_fb[ref_fb_idx].y_stride ;
recon_uv_stride = cm->yv12_fb[ref_fb_idx].uv_stride; recon_uv_stride = cm->yv12_fb[ref_fb_idx].uv_stride;
...@@ -818,13 +813,7 @@ static void read_mb_modes_mv(VP9D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi, ...@@ -818,13 +813,7 @@ static void read_mb_modes_mv(VP9D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi,
if (mbmi->second_ref_frame > 0) { if (mbmi->second_ref_frame > 0) {
int second_ref_fb_idx; int second_ref_fb_idx;
/* Select the appropriate reference frame for this MB */ /* Select the appropriate reference frame for this MB */
if (mbmi->second_ref_frame == LAST_FRAME) second_ref_fb_idx = cm->active_ref_idx[mbmi->second_ref_frame - 1];
second_ref_fb_idx = cm->lst_fb_idx;
else if (mbmi->second_ref_frame ==
GOLDEN_FRAME)
second_ref_fb_idx = cm->gld_fb_idx;
else
second_ref_fb_idx = cm->alt_fb_idx;
xd->second_pre.y_buffer = xd->second_pre.y_buffer =
cm->yv12_fb[second_ref_fb_idx].y_buffer + recon_yoffset; cm->yv12_fb[second_ref_fb_idx].y_buffer + recon_yoffset;
......
...@@ -1091,12 +1091,7 @@ static void set_refs(VP9D_COMP *pbi, int block_size, ...@@ -1091,12 +1091,7 @@ static void set_refs(VP9D_COMP *pbi, int block_size,
int ref_fb_idx, ref_yoffset, ref_uvoffset, ref_y_stride, ref_uv_stride; int ref_fb_idx, ref_yoffset, ref_uvoffset, ref_y_stride, ref_uv_stride;
/* Select the appropriate reference frame for this MB */ /* Select the appropriate reference frame for this MB */
if (mbmi->ref_frame == LAST_FRAME) ref_fb_idx = cm->active_ref_idx[mbmi->ref_frame - 1];
ref_fb_idx = cm->lst_fb_idx;
else if (mbmi->ref_frame == GOLDEN_FRAME)
ref_fb_idx = cm->gld_fb_idx;
else
ref_fb_idx = cm->alt_fb_idx;
ref_y_stride = cm->yv12_fb[ref_fb_idx].y_stride; ref_y_stride = cm->yv12_fb[ref_fb_idx].y_stride;
ref_yoffset = mb_row * 16 * ref_y_stride + 16 * mb_col; ref_yoffset = mb_row * 16 * ref_y_stride + 16 * mb_col;
...@@ -1113,12 +1108,7 @@ static void set_refs(VP9D_COMP *pbi, int block_size, ...@@ -1113,12 +1108,7 @@ static void set_refs(VP9D_COMP *pbi, int block_size,
int second_ref_fb_idx; int second_ref_fb_idx;
/* Select the appropriate reference frame for this MB */ /* Select the appropriate reference frame for this MB */
if (mbmi->second_ref_frame == LAST_FRAME) second_ref_fb_idx = cm->active_ref_idx[mbmi->second_ref_frame - 1];
second_ref_fb_idx = cm->lst_fb_idx;
else if (mbmi->second_ref_frame == GOLDEN_FRAME)
second_ref_fb_idx = cm->gld_fb_idx;
else
second_ref_fb_idx = cm->alt_fb_idx;
xd->second_pre.y_buffer = xd->second_pre.y_buffer =
cm->yv12_fb[second_ref_fb_idx].y_buffer + ref_yoffset; cm->yv12_fb[second_ref_fb_idx].y_buffer + ref_yoffset;
...@@ -1265,6 +1255,7 @@ static void init_frame(VP9D_COMP *pbi) { ...@@ -1265,6 +1255,7 @@ static void init_frame(VP9D_COMP *pbi) {
MACROBLOCKD *const xd = &pbi->mb; MACROBLOCKD *const xd = &pbi->mb;
if (pc->frame_type == KEY_FRAME) { if (pc->frame_type == KEY_FRAME) {
int i;
if (pc->last_frame_seg_map) if (pc->last_frame_seg_map)
vpx_memset(pc->last_frame_seg_map, 0, (pc->mb_rows * pc->mb_cols)); vpx_memset(pc->last_frame_seg_map, 0, (pc->mb_rows * pc->mb_cols));
...@@ -1288,10 +1279,7 @@ static void init_frame(VP9D_COMP *pbi) { ...@@ -1288,10 +1279,7 @@ static void init_frame(VP9D_COMP *pbi) {
vpx_memset(xd->mode_lf_deltas, 0, sizeof(xd->mode_lf_deltas)); vpx_memset(xd->mode_lf_deltas, 0, sizeof(xd->mode_lf_deltas));
/* All buffers are implicitly updated on key frames. */ /* All buffers are implicitly updated on key frames. */
pc->refresh_golden_frame = 1; pbi->refresh_frame_flags = (1 << NUM_REF_FRAMES) - 1;
pc->refresh_alt_ref_frame = 1;
pc->copy_buffer_to_gf = 0;
pc->copy_buffer_to_arf = 0;
/* Note that Golden and Altref modes cannot be used on a key frame so /* Note that Golden and Altref modes cannot be used on a key frame so
* ref_frame_sign_bias[] is undefined and meaningless * ref_frame_sign_bias[] is undefined and meaningless
...@@ -1300,8 +1288,9 @@ static void init_frame(VP9D_COMP *pbi) { ...@@ -1300,8 +1288,9 @@ static void init_frame(VP9D_COMP *pbi) {
pc->ref_frame_sign_bias[ALTREF_FRAME] = 0; pc->ref_frame_sign_bias[ALTREF_FRAME] = 0;
vp9_init_mode_contexts(&pbi->common); vp9_init_mode_contexts(&pbi->common);
vpx_memcpy(&pc->lfc, &pc->fc, sizeof(pc->fc));
vpx_memcpy(&pc->lfc_a, &pc->fc, sizeof(pc->fc)); for (i = 0; i < NUM_FRAME_CONTEXTS; i++)
vpx_memcpy(&pc->frame_contexts[i], &pc->fc, sizeof(pc->fc));
vpx_memset(pc->prev_mip, 0, vpx_memset(pc->prev_mip, 0,
(pc->mb_cols + 1) * (pc->mb_rows + 1)* sizeof(MODE_INFO)); (pc->mb_cols + 1) * (pc->mb_rows + 1)* sizeof(MODE_INFO));
...@@ -1645,27 +1634,20 @@ int vp9_decode_frame(VP9D_COMP *pbi, const unsigned char **p_data_end) { ...@@ -1645,27 +1634,20 @@ 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 * For all non key frames the GF and ARF refresh flags and sign bias
* flags must be set explicitly. * 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 */ /* Should the GF or ARF be updated from the current frame */
pc->refresh_golden_frame = vp9_read_bit(&header_bc); pbi->refresh_frame_flags = vp9_read_literal(&header_bc, NUM_REF_FRAMES);
pc->refresh_alt_ref_frame = vp9_read_bit(&header_bc);
if (pc->refresh_alt_ref_frame) {
vpx_memcpy(&pc->fc, &pc->lfc_a, sizeof(pc->fc));
} else {
vpx_memcpy(&pc->fc, &pc->lfc, sizeof(pc->fc));
}
/* Buffer to buffer copy flags. */
pc->copy_buffer_to_gf = 0;
if (!pc->refresh_golden_frame) /* Select active reference frames */
pc->copy_buffer_to_gf = vp9_read_literal(&header_bc, 2); for (i = 0; i < 3; i++) {
int ref_frame_num = vp9_read_literal(&header_bc, NUM_REF_FRAMES_LG2);
pc->copy_buffer_to_arf = 0; pc->active_ref_idx[i] = pc->ref_frame_map[ref_frame_num];
}
if (!pc->refresh_alt_ref_frame)
pc->copy_buffer_to_arf = vp9_read_literal(&header_bc, 2);
pc->ref_frame_sign_bias[GOLDEN_FRAME] = vp9_read_bit(&header_bc); pc->ref_frame_sign_bias[GOLDEN_FRAME] = vp9_read_bit(&header_bc);
pc->ref_frame_sign_bias[ALTREF_FRAME] = vp9_read_bit(&header_bc); pc->ref_frame_sign_bias[ALTREF_FRAME] = vp9_read_bit(&header_bc);
...@@ -1686,12 +1668,9 @@ int vp9_decode_frame(VP9D_COMP *pbi, const unsigned char **p_data_end) { ...@@ -1686,12 +1668,9 @@ int vp9_decode_frame(VP9D_COMP *pbi, const unsigned char **p_data_end) {
} }
pc->refresh_entropy_probs = vp9_read_bit(&header_bc); pc->refresh_entropy_probs = vp9_read_bit(&header_bc);
if (pc->refresh_entropy_probs == 0) { pc->frame_context_idx = vp9_read_literal(&header_bc, NUM_FRAME_CONTEXTS_LG2);
vpx_memcpy(&pc->lfc, &pc->fc, sizeof(pc->fc)); vpx_memcpy(&pc->fc, &pc->frame_contexts[pc->frame_context_idx],
} sizeof(pc->fc));
pc->refresh_last_frame = (pc->frame_type == KEY_FRAME)
|| vp9_read_bit(&header_bc);
// Read inter mode probability context updates // Read inter mode probability context updates
if (pc->frame_type != KEY_FRAME) { if (pc->frame_type != KEY_FRAME) {
...@@ -1735,12 +1714,10 @@ int vp9_decode_frame(VP9D_COMP *pbi, const unsigned char **p_data_end) { ...@@ -1735,12 +1714,10 @@ int vp9_decode_frame(VP9D_COMP *pbi, const unsigned char **p_data_end) {
if (0) { if (0) {
FILE *z = fopen("decodestats.stt", "a"); FILE *z = fopen("decodestats.stt", "a");
fprintf(z, "%6d F:%d,G:%d,A:%d,L:%d,Q:%d\n", fprintf(z, "%6d F:%d,R:%d,Q:%d\n",
pc->current_video_frame, pc->current_video_frame,
pc->frame_type, pc->frame_type,
pc->refresh_golden_frame, pbi->refresh_frame_flags,
pc->refresh_alt_ref_frame,
pc->refresh_last_frame,
pc->base_qindex); pc->base_qindex);
fclose(z); fclose(z);
} }
...@@ -1792,8 +1769,11 @@ int vp9_decode_frame(VP9D_COMP *pbi, const unsigned char **p_data_end) { ...@@ -1792,8 +1769,11 @@ int vp9_decode_frame(VP9D_COMP *pbi, const unsigned char **p_data_end) {
read_coef_probs(pbi, &header_bc); read_coef_probs(pbi, &header_bc);
vpx_memcpy(&xd->pre, &pc->yv12_fb[pc->lst_fb_idx], sizeof(YV12_BUFFER_CONFIG)); /* Initialize xd pointers. Any reference should do for xd->pre, so use 0. */
vpx_memcpy(&xd->dst, &pc->yv12_fb[pc->new_fb_idx], sizeof(YV12_BUFFER_CONFIG)); vpx_memcpy(&xd->pre, &pc->yv12_fb[pc->active_ref_idx[0]],
sizeof(YV12_BUFFER_CONFIG));
vpx_memcpy(&xd->dst, &pc->yv12_fb[pc->new_fb_idx],
sizeof(YV12_BUFFER_CONFIG));
// Create the segmentation map structure and set to 0 // Create the segmentation map structure and set to 0
if (!pc->last_frame_seg_map) if (!pc->last_frame_seg_map)
...@@ -1845,16 +1825,9 @@ int vp9_decode_frame(VP9D_COMP *pbi, const unsigned char **p_data_end) { ...@@ -1845,16 +1825,9 @@ int vp9_decode_frame(VP9D_COMP *pbi, const unsigned char **p_data_end) {
vp9_update_mode_context(&pbi->common); vp9_update_mode_context(&pbi->common);
} }
/* If this was a kf or Gf note the Q used */
if ((pc->frame_type == KEY_FRAME) ||
pc->refresh_golden_frame || pc->refresh_alt_ref_frame) {
pc->last_kf_gf_q = pc->base_qindex;
}
if (pc->refresh_entropy_probs) { if (pc->refresh_entropy_probs) {
if (pc->refresh_alt_ref_frame) vpx_memcpy(&pc->frame_contexts[pc->frame_context_idx], &pc->fc,
vpx_memcpy(&pc->lfc_a, &pc->fc, sizeof(pc->fc)); sizeof(pc->fc));
else
vpx_memcpy(&pc->lfc, &pc->fc, sizeof(pc->fc));
} }
#ifdef PACKET_TESTING #ifdef PACKET_TESTING
......
...@@ -30,9 +30,6 @@ ...@@ -30,9 +30,6 @@
#include "vp9/decoder/vp9_detokenize.h" #include "vp9/decoder/vp9_detokenize.h"
#include "./vpx_scale_rtcd.h" #include "./vpx_scale_rtcd.h"
static int get_free_fb(VP9_COMMON *cm);
static void ref_cnt_fb(int *buf, int *idx, int new_idx);
#define WRITE_RECON_BUFFER 0 #define WRITE_RECON_BUFFER 0
#if WRITE_RECON_BUFFER == 1 #if WRITE_RECON_BUFFER == 1
static void recon_write_yuv_frame(char *name, YV12_BUFFER_CONFIG *s) { static void recon_write_yuv_frame(char *name, YV12_BUFFER_CONFIG *s) {
...@@ -168,12 +165,13 @@ vpx_codec_err_t vp9_get_reference_dec(VP9D_PTR ptr, VP9_REFFRAME ref_frame_flag, ...@@ -168,12 +165,13 @@ vpx_codec_err_t vp9_get_reference_dec(VP9D_PTR ptr, VP9_REFFRAME ref_frame_flag,
VP9_COMMON *cm = &pbi->common; VP9_COMMON *cm = &pbi->common;
int ref_fb_idx; int ref_fb_idx;
/* TODO(jkoleszar): The decoder doesn't have any real knowledge of what the
* encoder is using the frame buffers for. This is just a stub to keep the
* vpxenc --test-decode functionality working, and will be replaced in a
* later commit that adds VP9-specific controls for this functionality.
*/
if (ref_frame_flag == VP9_LAST_FLAG) if (ref_frame_flag == VP9_LAST_FLAG)
ref_fb_idx = cm->lst_fb_idx; ref_fb_idx = pbi->common.new_fb_idx;
else if (ref_frame_flag == VP9_GOLD_FLAG)
ref_fb_idx = cm->gld_fb_idx;
else if (ref_frame_flag == VP9_ALT_FLAG)
ref_fb_idx = cm->alt_fb_idx;
else { else {
vpx_internal_error(&pbi->common.error, VPX_CODEC_ERROR, vpx_internal_error(&pbi->common.error, VPX_CODEC_ERROR,
"Invalid reference frame"); "Invalid reference frame");
...@@ -200,12 +198,17 @@ vpx_codec_err_t vp9_set_reference_dec(VP9D_PTR ptr, VP9_REFFRAME ref_frame_flag, ...@@ -200,12 +198,17 @@ vpx_codec_err_t vp9_set_reference_dec(VP9D_PTR ptr, VP9_REFFRAME ref_frame_flag,
int *ref_fb_ptr = NULL; int *ref_fb_ptr = NULL;
int free_fb; int free_fb;
/* TODO(jkoleszar): The decoder doesn't have any real knowledge of what the
* encoder is using the frame buffers for. This is just a stub to keep the
* vpxenc --test-decode functionality working, and will be replaced in a
* later commit that adds VP9-specific controls for this functionality.
*/
if (ref_frame_flag == VP9_LAST_FLAG) if (ref_frame_flag == VP9_LAST_FLAG)
ref_fb_ptr = &cm->lst_fb_idx; ref_fb_ptr = &pbi->common.active_ref_idx[0];
else if (ref_frame_flag == VP9_GOLD_FLAG) else if (ref_frame_flag == VP9_GOLD_FLAG)
ref_fb_ptr = &cm->gld_fb_idx; ref_fb_ptr = &pbi->common.active_ref_idx[1];
else if (ref_frame_flag == VP9_ALT_FLAG) else if (ref_frame_flag == VP9_ALT_FLAG)
ref_fb_ptr = &cm->alt_fb_idx; ref_fb_ptr = &pbi->common.active_ref_idx[2];
else { else {
vpx_internal_error(&pbi->common.error, VPX_CODEC_ERROR, vpx_internal_error(&pbi->common.error, VPX_CODEC_ERROR,
"Invalid reference frame"); "Invalid reference frame");
...@@ -234,77 +237,25 @@ vpx_codec_err_t vp9_set_reference_dec(VP9D_PTR ptr, VP9_REFFRAME ref_frame_flag, ...@@ -234,77 +237,25 @@ vpx_codec_err_t vp9_set_reference_dec(VP9D_PTR ptr, VP9_REFFRAME ref_frame_flag,
} }
static int get_free_fb(VP9_COMMON *cm) { /* If any buffer updating is signalled it should be done here. */
int i; static void swap_frame_buffers(VP9D_COMP *pbi) {
for (i = 0; i < NUM_YV12_BUFFERS; i++) int ref_index = 0, mask;
if (cm->fb_idx_ref_cnt[i] == 0)
break;
assert(i < NUM_YV12_BUFFERS);
cm->fb_idx_ref_cnt[i] = 1;
return i;
}
static void ref_cnt_fb(int *buf, int *idx, int new_idx) {
if (buf[*idx] > 0)
buf[*idx]--;
*idx = new_idx;
buf[new_idx]++;
}
/* If any buffer copy / swapping is signalled it should be done here. */
static int swap_frame_buffers(VP9_COMMON *cm) {
int err = 0;
/* The alternate reference frame or golden frame can be updated
* using the new, last, or golden/alt ref frame. If it
* is updated using the newly decoded frame it is a refresh.
* An update using the last or golden/alt ref frame is a copy.
*/
if (cm->copy_buffer_to_arf) {
int new_fb = 0;
if (cm->copy_buffer_to_arf == 1) for (mask = pbi->refresh_frame_flags; mask; mask >>= 1) {
new_fb = cm->lst_fb_idx; if (mask & 1) {
else if (cm->copy_buffer_to_arf == 2) ref_cnt_fb(pbi->common.fb_idx_ref_cnt,
new_fb = cm->gld_fb_idx; &pbi->common.ref_frame_map[ref_index],
else pbi->common.new_fb_idx);
err = -1; }
++ref_index;
ref_cnt_fb(cm->fb_idx_ref_cnt, &cm->alt_fb_idx, new_fb);
}
if (cm->copy_buffer_to_gf) {
int new_fb = 0;
if (cm->copy_buffer_to_gf == 1)
new_fb = cm->lst_fb_idx;
else if (cm->copy_buffer_to_gf == 2)
new_fb = cm->alt_fb_idx;
else
err = -1;
ref_cnt_fb(cm->fb_idx_ref_cnt, &cm->gld_fb_idx, new_fb);
} }
if (cm->refresh_golden_frame) pbi->common.frame_to_show = &pbi->common.yv12_fb[pbi->common.new_fb_idx];
ref_cnt_fb(cm->fb_idx_ref_cnt, &cm->gld_fb_idx, cm->new_fb_idx); pbi->common.fb_idx_ref_cnt[pbi->common.new_fb_idx]--;
if (cm->refresh_alt_ref_frame)
ref_cnt_fb(cm->fb_idx_ref_cnt, &cm->alt_fb_idx, cm->new_fb_idx);
if (cm->refresh_last_frame) { /* Invalidate these references until the next frame starts. */
ref_cnt_fb(cm->fb_idx_ref_cnt, &cm->lst_fb_idx, cm->new_fb_idx); for (ref_index = 0; ref_index < 3; ref_index++)
pbi->common.active_ref_idx[ref_index] = INT_MAX;
cm->frame_to_show = &cm->yv12_fb[cm->lst_fb_idx];
} else
cm->frame_to_show = &cm->yv12_fb[cm->new_fb_idx];
cm->fb_idx_ref_cnt[cm->new_fb_idx]--;
return err;
} }
int vp9_receive_compressed_data(VP9D_PTR ptr, unsigned long size, int vp9_receive_compressed_data(VP9D_PTR ptr, unsigned long size,
...@@ -332,8 +283,12 @@ int vp9_receive_compressed_data(VP9D_PTR ptr, unsigned long size, ...@@ -332,8 +283,12 @@ int vp9_receive_compressed_data(VP9D_PTR ptr, unsigned long size,
* We do not know if the missing frame(s) was supposed to update * We do not know if the missing frame(s) was supposed to update
* any of the reference buffers, but we act conservative and * any of the reference buffers, but we act conservative and
* mark only the last buffer as corrupted. * mark only the last buffer as corrupted.
*
* TODO(jkoleszar): Error concealment is undefined and non-normative
* at this point, but if it becomes so, [0] may not always be the correct
* thing to do here.
*/ */
cm->yv12_fb[cm->lst_fb_idx].corrupted = 1; cm->yv12_fb[cm->active_ref_idx[0]].corrupted = 1;
} }
cm->new_fb_idx = get_free_fb(cm); cm->new_fb_idx = get_free_fb(cm);
...@@ -344,8 +299,12 @@ int vp9_receive_compressed_data(VP9D_PTR ptr, unsigned long size, ...@@ -344,8 +299,12 @@ int vp9_receive_compressed_data(VP9D_PTR ptr, unsigned long size,
/* We do not know if the missing frame(s) was supposed to update /* We do not know if the missing frame(s) was supposed to update
* any of the reference buffers, but we act conservative and * any of the reference buffers, but we act conservative and
* mark only the last buffer as corrupted. * mark only the last buffer as corrupted.
*
* TODO(jkoleszar): Error concealment is undefined and non-normative
* at this point, but if it becomes so, [0] may not always be the correct
* thing to do here.
*/ */
cm->yv12_fb[cm->lst_fb_idx].corrupted = 1; cm->yv12_fb[cm->active_ref_idx[0]].corrupted = 1;
if (cm->fb_idx_ref_cnt[cm->new_fb_idx] > 0) if (cm->fb_idx_ref_cnt[cm->new_fb_idx] > 0)
cm->fb_idx_ref_cnt[cm->new_fb_idx]--; cm->fb_idx_ref_cnt[cm->new_fb_idx]--;
...@@ -365,11 +324,7 @@ int vp9_receive_compressed_data(VP9D_PTR ptr, unsigned long size, ...@@ -365,11 +324,7 @@ int vp9_receive_compressed_data(VP9D_PTR ptr, unsigned long size,
} }
{ {
if (swap_frame_buffers(cm)) { swap_frame_buffers(pbi);
pbi->common.error.error_code = VPX_CODEC_ERROR;
pbi->common.error.setjmp = 0;
return -1;
}
#if WRITE_RECON_BUFFER == 2 #if WRITE_RECON_BUFFER == 2
if (cm->show_frame) if (cm->show_frame)
......
...@@ -76,6 +76,7 @@ typedef struct VP9Decompressor { ...@@ -76,6 +76,7 @@ typedef struct VP9Decompressor {
vp9_dequant_idct_add_y_block_fn_t idct_add_y_block; vp9_dequant_idct_add_y_block_fn_t idct_add_y_block;
vp9_dequant_idct_add_uv_block_fn_t idct_add_uv_block;