summaryrefslogtreecommitdiff
path: root/vp9/decoder
diff options
context:
space:
mode:
Diffstat (limited to 'vp9/decoder')
-rw-r--r--vp9/decoder/vp9_decodemv.c15
-rw-r--r--vp9/decoder/vp9_decodframe.c87
-rw-r--r--vp9/decoder/vp9_onyxd_if.c125
-rw-r--r--vp9/decoder/vp9_onyxd_int.h1
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;