ref: 55577431ae364273dbaf2aa1e74f51b0cb893464
parent: 1c84e73ebda82f0089f6ae71acfe1710f5bed2c2
author: hkuang <[email protected]>
date: Mon Oct 27 12:19:04 EDT 2014
Bind motion vectors with frame buffer structure. This will save a lot of memory for decoder due to removing of prev_mi, but prev_mi is still needed in encoder. So this will increase a little bit memory for encoder. Change-Id: I24b2f1a423ebffa55a9bd2fcee1077dac995b2ed
--- a/vp9/common/vp9_alloccommon.c
+++ b/vp9/common/vp9_alloccommon.c
@@ -92,6 +92,7 @@
if (cm->frame_bufs[i].ref_count > 0 &&
cm->frame_bufs[i].raw_frame_buffer.data != NULL) {
cm->release_fb_cb(cm->cb_priv, &cm->frame_bufs[i].raw_frame_buffer);
+ vpx_free(cm->frame_bufs[i].mvs);
cm->frame_bufs[i].ref_count = 0;
}
}
@@ -166,6 +167,16 @@
#endif
VP9_ENC_BORDER_IN_PIXELS) < 0)
goto fail;
+ if (cm->frame_bufs[i].mvs == NULL) {
+ cm->frame_bufs[i].mvs =
+ (MV_REF *)vpx_calloc(cm->mi_rows * cm->mi_cols,
+ sizeof(*cm->frame_bufs[i].mvs));
+ if (cm->frame_bufs[i].mvs == NULL)
+ goto fail;
+
+ cm->frame_bufs[i].mi_rows = cm->mi_rows;
+ cm->frame_bufs[i].mi_cols = cm->mi_cols;
+ }
}
init_frame_bufs(cm);
--- a/vp9/common/vp9_mvref_common.c
+++ b/vp9/common/vp9_mvref_common.c
@@ -20,13 +20,11 @@
int block, int mi_row, int mi_col) {
const int *ref_sign_bias = cm->ref_frame_sign_bias;
int i, refmv_count = 0;
- const MODE_INFO *prev_mi = !cm->error_resilient_mode && cm->prev_mi
- ? cm->prev_mi[mi_row * xd->mi_stride + mi_col].src_mi
- : NULL;
- const MB_MODE_INFO *const prev_mbmi = prev_mi ? &prev_mi->src_mi->mbmi : NULL;
const POSITION *const mv_ref_search = mv_ref_blocks[mi->mbmi.sb_type];
int different_ref_found = 0;
int context_counter = 0;
+ const MV_REF *const prev_frame_mvs = cm->use_prev_frame_mvs ?
+ cm->prev_frame->mvs + mi_row * cm->mi_cols + mi_col : NULL;
// Blank the reference vector list
vpx_memset(mv_ref_list, 0, sizeof(*mv_ref_list) * MAX_MV_REF_CANDIDATES);
@@ -71,11 +69,12 @@
}
// Check the last frame's mode and mv info.
- if (prev_mbmi) {
- if (prev_mbmi->ref_frame[0] == ref_frame)
- ADD_MV_REF_LIST(prev_mbmi->mv[0], refmv_count, mv_ref_list, Done);
- else if (prev_mbmi->ref_frame[1] == ref_frame)
- ADD_MV_REF_LIST(prev_mbmi->mv[1], refmv_count, mv_ref_list, Done);
+ if (cm->use_prev_frame_mvs) {
+ if (prev_frame_mvs->ref_frame[0] == ref_frame) {
+ ADD_MV_REF_LIST(prev_frame_mvs->mv[0], refmv_count, mv_ref_list, Done);
+ } else if (prev_frame_mvs->ref_frame[1] == ref_frame) {
+ ADD_MV_REF_LIST(prev_frame_mvs->mv[1], refmv_count, mv_ref_list, Done);
+ }
}
// Since we couldn't find 2 mvs from the same reference frame
@@ -96,9 +95,30 @@
}
// Since we still don't have a candidate we'll try the last frame.
- if (prev_mbmi)
- IF_DIFF_REF_FRAME_ADD_MV(prev_mbmi, ref_frame, ref_sign_bias, refmv_count,
- mv_ref_list, Done);
+ if (cm->use_prev_frame_mvs) {
+ if (prev_frame_mvs->ref_frame[0] != ref_frame &&
+ prev_frame_mvs->ref_frame[0] > INTRA_FRAME) {
+ int_mv mv = prev_frame_mvs->mv[0];
+ if (ref_sign_bias[prev_frame_mvs->ref_frame[0]] !=
+ ref_sign_bias[ref_frame]) {
+ mv.as_mv.row *= -1;
+ mv.as_mv.col *= -1;
+ }
+ ADD_MV_REF_LIST(mv, refmv_count, mv_ref_list, Done);
+ }
+
+ if (prev_frame_mvs->ref_frame[1] > INTRA_FRAME &&
+ prev_frame_mvs->ref_frame[1] != ref_frame &&
+ prev_frame_mvs->mv[1].as_int != prev_frame_mvs->mv[0].as_int) {
+ int_mv mv = prev_frame_mvs->mv[1];
+ if (ref_sign_bias[prev_frame_mvs->ref_frame[1]] !=
+ ref_sign_bias[ref_frame]) {
+ mv.as_mv.row *= -1;
+ mv.as_mv.col *= -1;
+ }
+ ADD_MV_REF_LIST(mv, refmv_count, mv_ref_list, Done);
+ }
+ }
Done:
--- a/vp9/common/vp9_onyxc_int.h
+++ b/vp9/common/vp9_onyxc_int.h
@@ -56,9 +56,16 @@
REFERENCE_MODES = 3,
} REFERENCE_MODE;
+typedef struct {
+ int_mv mv[2];
+ MV_REFERENCE_FRAME ref_frame[2];
+} MV_REF;
typedef struct {
int ref_count;
+ MV_REF *mvs;
+ int mi_rows;
+ int mi_cols;
vpx_codec_frame_buffer_t raw_frame_buffer;
YV12_BUFFER_CONFIG buf;
} RefCntBuffer;
@@ -91,7 +98,11 @@
YV12_BUFFER_CONFIG *frame_to_show;
RefCntBuffer frame_bufs[FRAME_BUFFERS];
+ RefCntBuffer *prev_frame;
+ // TODO(hkuang): Combine this with cur_buf in macroblockd.
+ RefCntBuffer *cur_frame;
+
int ref_frame_map[REF_FRAMES]; /* maps fb_idx to reference slot */
// TODO(jkoleszar): could expand active_ref_idx to 4, with 0 as intra, and
@@ -148,6 +159,10 @@
MODE_INFO *mi; /* Corresponds to upper left visible macroblock */
MODE_INFO *prev_mip; /* MODE_INFO array 'mip' from last decoded frame */
MODE_INFO *prev_mi; /* 'mi' from last frame (points into prev_mip) */
+
+
+ // Whether to use previous frame's motion vectors for prediction.
+ int use_prev_frame_mvs;
// Persistent mb segment id map used in prediction.
unsigned char *last_frame_seg_map;
--- a/vp9/decoder/vp9_decodeframe.c
+++ b/vp9/decoder/vp9_decodeframe.c
@@ -667,6 +667,14 @@
vp9_read_frame_size(rb, &cm->display_width, &cm->display_height);
}
+static void resize_mv_buffer(VP9_COMMON *cm) {
+ vpx_free(cm->cur_frame->mvs);
+ cm->cur_frame->mi_rows = cm->mi_rows;
+ cm->cur_frame->mi_cols = cm->mi_cols;
+ cm->cur_frame->mvs = (MV_REF *)vpx_calloc(cm->mi_rows * cm->mi_cols,
+ sizeof(*cm->cur_frame->mvs));
+}
+
static void resize_context_buffers(VP9_COMMON *cm, int width, int height) {
#if CONFIG_SIZE_LIMIT
if (width > DECODE_WIDTH_LIMIT || height > DECODE_HEIGHT_LIMIT)
@@ -692,6 +700,10 @@
cm->width = width;
cm->height = height;
}
+ if (cm->cur_frame->mvs == NULL || cm->mi_rows > cm->cur_frame->mi_rows ||
+ cm->mi_cols > cm->cur_frame->mi_cols) {
+ resize_mv_buffer(cm);
+ }
}
static void setup_frame_size(VP9_COMMON *cm, struct vp9_read_bit_buffer *rb) {
@@ -1537,10 +1549,11 @@
init_macroblockd(cm, &pbi->mb);
- if (!cm->error_resilient_mode)
- set_prev_mi(cm);
- else
- cm->prev_mi = NULL;
+ cm->use_prev_frame_mvs = !cm->error_resilient_mode &&
+ cm->width == cm->last_width &&
+ cm->height == cm->last_height &&
+ !cm->intra_only &&
+ cm->last_show_frame;
setup_plane_dequants(cm, xd, cm->base_qindex);
vp9_setup_block_planes(xd, cm->subsampling_x, cm->subsampling_y);
--- a/vp9/decoder/vp9_decodemv.c
+++ b/vp9/decoder/vp9_decodemv.c
@@ -425,7 +425,6 @@
MB_MODE_INFO *const mbmi = &mi->mbmi;
const BLOCK_SIZE bsize = mbmi->sb_type;
const int allow_hp = cm->allow_high_precision_mv;
-
int_mv nearestmv[2], nearmv[2];
int inter_mode_ctx, ref, is_compound;
@@ -544,8 +543,27 @@
void vp9_read_mode_info(VP9_COMMON *cm, MACROBLOCKD *xd,
const TileInfo *const tile,
int mi_row, int mi_col, vp9_reader *r) {
+ MODE_INFO *const mi = xd->mi[0].src_mi;
+ const int bw = num_8x8_blocks_wide_lookup[mi->mbmi.sb_type];
+ const int bh = num_8x8_blocks_high_lookup[mi->mbmi.sb_type];
+ const int x_mis = MIN(bw, cm->mi_cols - mi_col);
+ const int y_mis = MIN(bh, cm->mi_rows - mi_row);
+ MV_REF* frame_mvs = cm->cur_frame->mvs + mi_row * cm->mi_cols + mi_col;
+ int w, h;
+
if (frame_is_intra_only(cm))
read_intra_frame_mode_info(cm, xd, mi_row, mi_col, r);
else
read_inter_frame_mode_info(cm, xd, tile, mi_row, mi_col, r);
+
+ for (h = 0; h < y_mis; ++h) {
+ MV_REF *const frame_mv = frame_mvs + h * cm->mi_cols;
+ for (w = 0; w < x_mis; ++w) {
+ MV_REF *const mv = frame_mv + w;
+ mv->ref_frame[0] = mi->src_mi->mbmi.ref_frame[0];
+ mv->ref_frame[1] = mi->src_mi->mbmi.ref_frame[1];
+ mv->mv[0].as_int = mi->src_mi->mbmi.mv[0].as_int;
+ mv->mv[1].as_int = mi->src_mi->mbmi.mv[1].as_int;
+ }
+ }
}
--- a/vp9/decoder/vp9_decoder.c
+++ b/vp9/decoder/vp9_decoder.c
@@ -252,6 +252,9 @@
&cm->frame_bufs[cm->new_fb_idx].raw_frame_buffer);
cm->new_fb_idx = get_free_fb(cm);
+ // Assign a MV array to the frame buffer.
+ cm->cur_frame = &cm->frame_bufs[cm->new_fb_idx];
+
if (setjmp(cm->error.jmp)) {
pbi->need_resync = 1;
cm->error.setjmp = 0;
@@ -284,14 +287,13 @@
cm->last_width = cm->width;
cm->last_height = cm->height;
- if (!cm->show_existing_frame)
+ if (!cm->show_existing_frame) {
cm->last_show_frame = cm->show_frame;
- if (cm->show_frame) {
- if (!cm->show_existing_frame)
- vp9_swap_mi_and_prev_mi(cm);
+ cm->prev_frame = cm->cur_frame;
+ }
+ if (cm->show_frame)
cm->current_video_frame++;
- }
cm->error.setjmp = 0;
return retcode;
--- a/vp9/encoder/vp9_encodeframe.c
+++ b/vp9/encoder/vp9_encodeframe.c
@@ -611,6 +611,13 @@
MB_MODE_INFO *const mbmi = &xd->mi[0].src_mi->mbmi;
MODE_INFO *mi_addr = &xd->mi[0];
const struct segmentation *const seg = &cm->seg;
+ const int bw = num_8x8_blocks_wide_lookup[mi->mbmi.sb_type];
+ const int bh = num_8x8_blocks_high_lookup[mi->mbmi.sb_type];
+ const int x_mis = MIN(bw, cm->mi_cols - mi_col);
+ const int y_mis = MIN(bh, cm->mi_rows - mi_row);
+ MV_REF *const frame_mvs =
+ cm->cur_frame->mvs + mi_row * cm->mi_cols + mi_col;
+ int w, h;
const int mis = cm->mi_stride;
const int mi_width = num_8x8_blocks_wide_lookup[bsize];
@@ -728,6 +735,17 @@
for (i = 0; i < SWITCHABLE_FILTER_CONTEXTS; ++i)
rd_opt->filter_diff[i] += ctx->best_filter_diff[i];
}
+
+ for (h = 0; h < y_mis; ++h) {
+ MV_REF *const frame_mv = frame_mvs + h * cm->mi_cols;
+ for (w = 0; w < x_mis; ++w) {
+ MV_REF *const mv = frame_mv + w;
+ mv->ref_frame[0] = mi->src_mi->mbmi.ref_frame[0];
+ mv->ref_frame[1] = mi->src_mi->mbmi.ref_frame[1];
+ mv->mv[0].as_int = mi->src_mi->mbmi.mv[0].as_int;
+ mv->mv[1].as_int = mi->src_mi->mbmi.mv[1].as_int;
+ }
+ }
}
void vp9_setup_src_planes(MACROBLOCK *x, const YV12_BUFFER_CONFIG *src,
@@ -1293,8 +1311,16 @@
VP9_COMMON *const cm = &cpi->common;
MACROBLOCK *const x = &cpi->mb;
MACROBLOCKD *const xd = &x->e_mbd;
+ MODE_INFO *const mi = xd->mi[0].src_mi;
MB_MODE_INFO *const mbmi = &xd->mi[0].src_mi->mbmi;
const struct segmentation *const seg = &cm->seg;
+ const int bw = num_8x8_blocks_wide_lookup[mi->mbmi.sb_type];
+ const int bh = num_8x8_blocks_high_lookup[mi->mbmi.sb_type];
+ const int x_mis = MIN(bw, cm->mi_cols - mi_col);
+ const int y_mis = MIN(bh, cm->mi_rows - mi_row);
+ MV_REF *const frame_mvs =
+ cm->cur_frame->mvs + mi_row * cm->mi_cols + mi_col;
+ int w, h;
*(xd->mi[0].src_mi) = ctx->mic;
xd->mi[0].src_mi = &xd->mi[0];
@@ -1323,6 +1349,17 @@
}
}
+ for (h = 0; h < y_mis; ++h) {
+ MV_REF *const frame_mv = frame_mvs + h * cm->mi_cols;
+ for (w = 0; w < x_mis; ++w) {
+ MV_REF *const mv = frame_mv + w;
+ mv->ref_frame[0] = mi->src_mi->mbmi.ref_frame[0];
+ mv->ref_frame[1] = mi->src_mi->mbmi.ref_frame[1];
+ mv->mv[0].as_int = mi->src_mi->mbmi.mv[0].as_int;
+ mv->mv[1].as_int = mi->src_mi->mbmi.mv[1].as_int;
+ }
+ }
+
x->skip = ctx->skip;
x->skip_txfm[0] = mbmi->segment_id ? 0 : ctx->skip_txfm[0];
}
@@ -3529,6 +3566,11 @@
vp9_initialize_me_consts(cpi, cm->base_qindex);
init_encode_frame_mb_context(cpi);
set_prev_mi(cm);
+ cm->use_prev_frame_mvs = !cm->error_resilient_mode &&
+ cm->width == cm->last_width &&
+ cm->height == cm->last_height &&
+ !cm->intra_only &&
+ cm->last_show_frame;
x->quant_fp = cpi->sf.use_quant_fp;
vp9_zero(x->skip_txfm);
--- a/vp9/encoder/vp9_encoder.c
+++ b/vp9/encoder/vp9_encoder.c
@@ -2420,6 +2420,7 @@
#if CONFIG_VP9_HIGHBITDEPTH
if (ref->y_crop_width != cm->width || ref->y_crop_height != cm->height) {
const int new_fb = get_free_fb(cm);
+ cm->cur_frame = &cm->frame_bufs[new_fb];
vp9_realloc_frame_buffer(&cm->frame_bufs[new_fb].buf,
cm->width, cm->height,
cm->subsampling_x, cm->subsampling_y,
@@ -2437,6 +2438,15 @@
scale_and_extend_frame(ref, &cm->frame_bufs[new_fb].buf);
#endif // CONFIG_VP9_HIGHBITDEPTH
cpi->scaled_ref_idx[ref_frame - 1] = new_fb;
+ if (cm->frame_bufs[new_fb].mvs == NULL ||
+ cm->frame_bufs[new_fb].mi_rows < cm->mi_rows ||
+ cm->frame_bufs[new_fb].mi_cols < cm->mi_cols) {
+ cm->frame_bufs[new_fb].mvs =
+ (MV_REF *)vpx_calloc(cm->mi_rows * cm->mi_cols,
+ sizeof(*cm->frame_bufs[new_fb].mvs));
+ cm->frame_bufs[new_fb].mi_rows = cm->mi_rows;
+ cm->frame_bufs[new_fb].mi_cols = cm->mi_cols;
+ }
} else {
cpi->scaled_ref_idx[ref_frame - 1] = idx;
++cm->frame_bufs[idx].ref_count;
@@ -3279,7 +3289,6 @@
if (cm->show_frame) {
vp9_swap_mi_and_prev_mi(cm);
-
// Don't increment frame counters if this was an altref buffer
// update not a real frame
++cm->current_video_frame;
@@ -3286,6 +3295,7 @@
if (cpi->use_svc)
vp9_inc_frame_in_layer(cpi);
}
+ cm->prev_frame = cm->cur_frame;
if (is_two_pass_svc(cpi))
cpi->svc.layer_context[cpi->svc.spatial_layer_id].last_frame_type =
@@ -3630,6 +3640,7 @@
// held.
cm->frame_bufs[cm->new_fb_idx].ref_count--;
cm->new_fb_idx = get_free_fb(cm);
+ cm->cur_frame = &cm->frame_bufs[cm->new_fb_idx];
if (!cpi->use_svc && cpi->multi_arf_allowed) {
if (cm->frame_type == KEY_FRAME) {