diff options
Diffstat (limited to 'vp9/decoder')
-rw-r--r-- | vp9/decoder/vp9_decodemv.c | 15 | ||||
-rw-r--r-- | vp9/decoder/vp9_decodframe.c | 87 | ||||
-rw-r--r-- | vp9/decoder/vp9_onyxd_if.c | 125 | ||||
-rw-r--r-- | vp9/decoder/vp9_onyxd_int.h | 1 |
4 files changed, 73 insertions, 155 deletions
diff --git a/vp9/decoder/vp9_decodemv.c b/vp9/decoder/vp9_decodemv.c index c6c3d1576..eef9e6e60 100644 --- a/vp9/decoder/vp9_decodemv.c +++ b/vp9/decoder/vp9_decodemv.c @@ -730,12 +730,7 @@ static void read_mb_modes_mv(VP9D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi, int ref_fb_idx; /* Select the appropriate reference frame for this MB */ - if (ref_frame == LAST_FRAME) - 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; + ref_fb_idx = cm->active_ref_idx[ref_frame - 1]; recon_y_stride = cm->yv12_fb[ref_fb_idx].y_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, if (mbmi->second_ref_frame > 0) { int second_ref_fb_idx; /* Select the appropriate reference frame for this MB */ - if (mbmi->second_ref_frame == LAST_FRAME) - 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; + second_ref_fb_idx = cm->active_ref_idx[mbmi->second_ref_frame - 1]; xd->second_pre.y_buffer = cm->yv12_fb[second_ref_fb_idx].y_buffer + recon_yoffset; diff --git a/vp9/decoder/vp9_decodframe.c b/vp9/decoder/vp9_decodframe.c index 361de33b9..18e09e4c4 100644 --- a/vp9/decoder/vp9_decodframe.c +++ b/vp9/decoder/vp9_decodframe.c @@ -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; /* Select the appropriate reference frame for this MB */ - if (mbmi->ref_frame == LAST_FRAME) - 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_fb_idx = cm->active_ref_idx[mbmi->ref_frame - 1]; ref_y_stride = cm->yv12_fb[ref_fb_idx].y_stride; 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, int second_ref_fb_idx; /* Select the appropriate reference frame for this MB */ - if (mbmi->second_ref_frame == LAST_FRAME) - 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; + second_ref_fb_idx = cm->active_ref_idx[mbmi->second_ref_frame - 1]; xd->second_pre.y_buffer = cm->yv12_fb[second_ref_fb_idx].y_buffer + ref_yoffset; @@ -1265,6 +1255,7 @@ static void init_frame(VP9D_COMP *pbi) { MACROBLOCKD *const xd = &pbi->mb; if (pc->frame_type == KEY_FRAME) { + int i; if (pc->last_frame_seg_map) 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) { vpx_memset(xd->mode_lf_deltas, 0, sizeof(xd->mode_lf_deltas)); /* All buffers are implicitly updated on key frames. */ - pc->refresh_golden_frame = 1; - pc->refresh_alt_ref_frame = 1; - pc->copy_buffer_to_gf = 0; - pc->copy_buffer_to_arf = 0; + pbi->refresh_frame_flags = (1 << NUM_REF_FRAMES) - 1; /* Note that Golden and Altref modes cannot be used on a key frame so * ref_frame_sign_bias[] is undefined and meaningless @@ -1300,8 +1288,9 @@ static void init_frame(VP9D_COMP *pbi) { pc->ref_frame_sign_bias[ALTREF_FRAME] = 0; 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, (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) { * 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 */ - pc->refresh_golden_frame = vp9_read_bit(&header_bc); - 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; + pbi->refresh_frame_flags = vp9_read_literal(&header_bc, NUM_REF_FRAMES); - if (!pc->refresh_golden_frame) - pc->copy_buffer_to_gf = vp9_read_literal(&header_bc, 2); + /* Select active reference frames */ + 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; - - if (!pc->refresh_alt_ref_frame) - pc->copy_buffer_to_arf = vp9_read_literal(&header_bc, 2); + 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); @@ -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); - if (pc->refresh_entropy_probs == 0) { - vpx_memcpy(&pc->lfc, &pc->fc, sizeof(pc->fc)); - } - - pc->refresh_last_frame = (pc->frame_type == KEY_FRAME) - || vp9_read_bit(&header_bc); + pc->frame_context_idx = vp9_read_literal(&header_bc, NUM_FRAME_CONTEXTS_LG2); + vpx_memcpy(&pc->fc, &pc->frame_contexts[pc->frame_context_idx], + sizeof(pc->fc)); // Read inter mode probability context updates if (pc->frame_type != KEY_FRAME) { @@ -1735,12 +1714,10 @@ int vp9_decode_frame(VP9D_COMP *pbi, const unsigned char **p_data_end) { if (0) { 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->frame_type, - pc->refresh_golden_frame, - pc->refresh_alt_ref_frame, - pc->refresh_last_frame, + pbi->refresh_frame_flags, pc->base_qindex); fclose(z); } @@ -1792,8 +1769,11 @@ int vp9_decode_frame(VP9D_COMP *pbi, const unsigned char **p_data_end) { read_coef_probs(pbi, &header_bc); - vpx_memcpy(&xd->pre, &pc->yv12_fb[pc->lst_fb_idx], sizeof(YV12_BUFFER_CONFIG)); - vpx_memcpy(&xd->dst, &pc->yv12_fb[pc->new_fb_idx], sizeof(YV12_BUFFER_CONFIG)); + /* Initialize xd pointers. Any reference should do for xd->pre, so use 0. */ + 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 if (!pc->last_frame_seg_map) @@ -1845,16 +1825,9 @@ int vp9_decode_frame(VP9D_COMP *pbi, const unsigned char **p_data_end) { 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_alt_ref_frame) - vpx_memcpy(&pc->lfc_a, &pc->fc, sizeof(pc->fc)); - else - vpx_memcpy(&pc->lfc, &pc->fc, sizeof(pc->fc)); + vpx_memcpy(&pc->frame_contexts[pc->frame_context_idx], &pc->fc, + sizeof(pc->fc)); } #ifdef PACKET_TESTING diff --git a/vp9/decoder/vp9_onyxd_if.c b/vp9/decoder/vp9_onyxd_if.c index b3b75af70..4fb610498 100644 --- a/vp9/decoder/vp9_onyxd_if.c +++ b/vp9/decoder/vp9_onyxd_if.c @@ -30,9 +30,6 @@ #include "vp9/decoder/vp9_detokenize.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 #if WRITE_RECON_BUFFER == 1 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, VP9_COMMON *cm = &pbi->common; 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) - ref_fb_idx = cm->lst_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; + ref_fb_idx = pbi->common.new_fb_idx; else { vpx_internal_error(&pbi->common.error, VPX_CODEC_ERROR, "Invalid reference frame"); @@ -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 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) - ref_fb_ptr = &cm->lst_fb_idx; + ref_fb_ptr = &pbi->common.active_ref_idx[0]; 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) - ref_fb_ptr = &cm->alt_fb_idx; + ref_fb_ptr = &pbi->common.active_ref_idx[2]; else { vpx_internal_error(&pbi->common.error, VPX_CODEC_ERROR, "Invalid reference frame"); @@ -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) { - 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]++; -} - -/* 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 any buffer updating is signalled it should be done here. */ +static void swap_frame_buffers(VP9D_COMP *pbi) { + int ref_index = 0, mask; - if (cm->copy_buffer_to_arf == 1) - new_fb = cm->lst_fb_idx; - else if (cm->copy_buffer_to_arf == 2) - new_fb = cm->gld_fb_idx; - else - err = -1; - - 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); + for (mask = pbi->refresh_frame_flags; mask; mask >>= 1) { + if (mask & 1) { + ref_cnt_fb(pbi->common.fb_idx_ref_cnt, + &pbi->common.ref_frame_map[ref_index], + pbi->common.new_fb_idx); + } + ++ref_index; } - if (cm->refresh_golden_frame) - ref_cnt_fb(cm->fb_idx_ref_cnt, &cm->gld_fb_idx, cm->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); + 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]--; - if (cm->refresh_last_frame) { - ref_cnt_fb(cm->fb_idx_ref_cnt, &cm->lst_fb_idx, cm->new_fb_idx); - - 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; + /* 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, @@ -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 * any of the reference buffers, but we act conservative and * 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); @@ -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 * any of the reference buffers, but we act conservative and * 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) cm->fb_idx_ref_cnt[cm->new_fb_idx]--; @@ -365,11 +324,7 @@ int vp9_receive_compressed_data(VP9D_PTR ptr, unsigned long size, } { - if (swap_frame_buffers(cm)) { - pbi->common.error.error_code = VPX_CODEC_ERROR; - pbi->common.error.setjmp = 0; - return -1; - } + swap_frame_buffers(pbi); #if WRITE_RECON_BUFFER == 2 if (cm->show_frame) diff --git a/vp9/decoder/vp9_onyxd_int.h b/vp9/decoder/vp9_onyxd_int.h index 64975468d..e04b9f5e4 100644 --- a/vp9/decoder/vp9_onyxd_int.h +++ b/vp9/decoder/vp9_onyxd_int.h @@ -76,6 +76,7 @@ typedef struct VP9Decompressor { vp9_dequant_idct_add_y_block_fn_t idct_add_y_block; vp9_dequant_idct_add_uv_block_fn_t idct_add_uv_block; + int refresh_frame_flags; vp9_prob prob_skip_false; int decoded_key_frame; |