Commit 254d3e17 authored by Jingning Han's avatar Jingning Han

Analyze motion field to produce reference motion vectors

This commit allows the codec to analyze the motion field in the
avaiable above and left neighboring area to produce a set of
reference motion vectors for each reference frame. These reference
motion vectors are ranked according to the likelihood that it will
be picked.

Change-Id: I82e6cd990a7716848bb7b6f5f2b1829966ff2483
parent c335bfeb
......@@ -200,6 +200,9 @@ typedef uint8_t PREDICTION_MODE;
/* Segment Feature Masks */
#define MAX_MV_REF_CANDIDATES 2
#if CONFIG_REF_MV
#define MAX_REF_MV_STACK_SIZE 16
#endif
#define INTRA_INTER_CONTEXTS 4
#define COMP_INTER_CONTEXTS 5
......
......@@ -11,6 +11,232 @@
#include "vp10/common/mvref_common.h"
#if CONFIG_REF_MV
static void scan_row_mbmi(const VP10_COMMON *cm, const MACROBLOCKD *xd,
const int mi_row, const int mi_col, int block,
const MV_REFERENCE_FRAME ref_frame,
int row_offset,
CANDIDATE_MV *ref_mv_stack,
int *refmv_count) {
const TileInfo *const tile = &xd->tile;
int i;
for (i = 0; i < xd->n8_w && *refmv_count < MAX_REF_MV_STACK_SIZE;) {
POSITION mi_pos;
mi_pos.row = row_offset;
mi_pos.col = i;
if (is_inside(tile, mi_col, mi_row, cm->mi_rows, &mi_pos)) {
const MODE_INFO *const candidate_mi =
xd->mi[mi_pos.row * xd->mi_stride + mi_pos.col];
const MB_MODE_INFO *const candidate = &candidate_mi->mbmi;
const int len = VPXMIN(xd->n8_w,
num_8x8_blocks_wide_lookup[candidate->sb_type]);
const int weight = len;
int index = 0, ref;
for (ref = 0; ref < 2; ++ref) {
if (candidate->ref_frame[ref] == ref_frame) {
int_mv this_refmv =
get_sub_block_mv(candidate_mi, ref, mi_pos.col, block);
for (index = 0; index < *refmv_count; ++index)
if (ref_mv_stack[index].this_mv.as_int == this_refmv.as_int)
break;
if (index < *refmv_count)
ref_mv_stack[index].weight += weight;
// Add a new item to the list.
if (index == *refmv_count) {
ref_mv_stack[index].this_mv = this_refmv;
ref_mv_stack[index].weight = weight;
++(*refmv_count);
}
}
}
i += len;
} else {
++i;
}
}
}
static void scan_col_mbmi(const VP10_COMMON *cm, const MACROBLOCKD *xd,
const int mi_row, const int mi_col, int block,
const MV_REFERENCE_FRAME ref_frame,
int col_offset,
CANDIDATE_MV *ref_mv_stack,
int *refmv_count) {
const TileInfo *const tile = &xd->tile;
int i;
for (i = 0; i < xd->n8_h && *refmv_count < MAX_REF_MV_STACK_SIZE;) {
POSITION mi_pos;
mi_pos.row = i;
mi_pos.col = col_offset;
if (is_inside(tile, mi_col, mi_row, cm->mi_rows, &mi_pos)) {
const MODE_INFO *const candidate_mi =
xd->mi[mi_pos.row * xd->mi_stride + mi_pos.col];
const MB_MODE_INFO *const candidate = &candidate_mi->mbmi;
const int len = VPXMIN(xd->n8_h,
num_8x8_blocks_high_lookup[candidate->sb_type]);
const int weight = len;
int index = 0, ref;
for (ref = 0; ref < 2; ++ref) {
if (candidate->ref_frame[ref] == ref_frame) {
int_mv this_refmv =
get_sub_block_mv(candidate_mi, ref, mi_pos.col, block);
for (index = 0; index < *refmv_count; ++index)
if (ref_mv_stack[index].this_mv.as_int == this_refmv.as_int)
break;
if (index < *refmv_count)
ref_mv_stack[index].weight += weight;
if (index == *refmv_count) {
ref_mv_stack[index].this_mv = this_refmv;
ref_mv_stack[index].weight = weight;
++(*refmv_count);
}
}
}
i += len;
} else {
++i;
}
}
}
static void scan_blk_mbmi(const VP10_COMMON *cm, const MACROBLOCKD *xd,
const int mi_row, const int mi_col, int block,
const MV_REFERENCE_FRAME ref_frame,
int row_offset, int col_offset,
CANDIDATE_MV *ref_mv_stack,
int *refmv_count) {
const TileInfo *const tile = &xd->tile;
POSITION mi_pos;
mi_pos.row = row_offset;
mi_pos.col = col_offset;
if (is_inside(tile, mi_col, mi_row, cm->mi_rows, &mi_pos) &&
*refmv_count < MAX_REF_MV_STACK_SIZE) {
const MODE_INFO *const candidate_mi =
xd->mi[mi_pos.row * xd->mi_stride + mi_pos.col];
const MB_MODE_INFO *const candidate = &candidate_mi->mbmi;
const int len = 1;
const int weight = len;
int index = 0, ref;
for (ref = 0; ref < 2; ++ref) {
if (candidate->ref_frame[ref] == ref_frame) {
int_mv this_refmv =
get_sub_block_mv(candidate_mi, ref, mi_pos.col, block);
for (index = 0; index < *refmv_count; ++index)
if (ref_mv_stack[index].this_mv.as_int == this_refmv.as_int)
break;
if (index < *refmv_count)
ref_mv_stack[index].weight += weight;
if (index == *refmv_count) {
ref_mv_stack[index].this_mv = this_refmv;
ref_mv_stack[index].weight = weight;
++(*refmv_count);
}
}
}
} // Analyze a single 8x8 block motion information.
}
static void setup_ref_mv_list(const VP10_COMMON *cm, const MACROBLOCKD *xd,
MODE_INFO *mi, MV_REFERENCE_FRAME ref_frame,
int_mv *mv_ref_list,
int block, int mi_row, int mi_col,
uint8_t *mode_context) {
int idx, refmv_count = 0, nearest_refmv_count = 0;
const int bw = num_8x8_blocks_wide_lookup[mi->mbmi.sb_type] << 3;
const int bh = num_8x8_blocks_high_lookup[mi->mbmi.sb_type] << 3;
CANDIDATE_MV ref_mv_stack[MAX_REF_MV_STACK_SIZE];
CANDIDATE_MV tmp_mv;
int len, nr_len;
(void) mode_context;
memset(ref_mv_stack, 0, sizeof(ref_mv_stack));
// Scan the first above row mode info.
scan_row_mbmi(cm, xd, mi_row, mi_col, block, ref_frame,
-1, ref_mv_stack, &refmv_count);
// Scan the first left column mode info.
scan_col_mbmi(cm, xd, mi_row, mi_col, block, ref_frame,
-1, ref_mv_stack, &refmv_count);
nearest_refmv_count = refmv_count;
// Analyze the top-left corner block mode info.
// scan_blk_mbmi(cm, xd, mi_row, mi_col, block, ref_frame,
// -1, -1, ref_mv_stack, &refmv_count);
// Scan the second outer area.
scan_row_mbmi(cm, xd, mi_row, mi_col, block, ref_frame,
-2, ref_mv_stack, &refmv_count);
scan_col_mbmi(cm, xd, mi_row, mi_col, block, ref_frame,
-2, ref_mv_stack, &refmv_count);
// Scan the third outer area.
scan_row_mbmi(cm, xd, mi_row, mi_col, block, ref_frame,
-3, ref_mv_stack, &refmv_count);
scan_col_mbmi(cm, xd, mi_row, mi_col, block, ref_frame,
-3, ref_mv_stack, &refmv_count);
// Scan the fourth outer area.
scan_row_mbmi(cm, xd, mi_row, mi_col, block, ref_frame,
-4, ref_mv_stack, &refmv_count);
// Scan the third left row mode info.
scan_col_mbmi(cm, xd, mi_row, mi_col, block, ref_frame,
-4, ref_mv_stack, &refmv_count);
// Rank the likelihood and assign nearest and near mvs.
len = nearest_refmv_count;
while (len > 0) {
nr_len = 0;
for (idx = 1; idx < len; ++idx) {
if (ref_mv_stack[idx - 1].weight < ref_mv_stack[idx].weight) {
tmp_mv = ref_mv_stack[idx - 1];
ref_mv_stack[idx - 1] = ref_mv_stack[idx];
ref_mv_stack[idx] = tmp_mv;
nr_len = idx;
}
}
len = nr_len;
}
len = refmv_count;
while (len > nearest_refmv_count) {
nr_len = nearest_refmv_count;
for (idx = nearest_refmv_count + 1; idx < len; ++idx) {
if (ref_mv_stack[idx - 1].weight < ref_mv_stack[idx].weight) {
tmp_mv = ref_mv_stack[idx - 1];
ref_mv_stack[idx - 1] = ref_mv_stack[idx];
ref_mv_stack[idx] = tmp_mv;
nr_len = idx;
}
}
len = nr_len;
}
for (idx = 0; idx < VPXMIN(MAX_MV_REF_CANDIDATES, refmv_count); ++idx) {
mv_ref_list[idx].as_int = ref_mv_stack[idx].this_mv.as_int;
clamp_mv_ref(&mv_ref_list[idx].as_mv, bw, bh, xd);
}
}
#endif
// This function searches the neighbourhood of a given MB/SB
// to try and find candidate reference vectors.
static void find_mv_refs_idx(const VP10_COMMON *cm, const MACROBLOCKD *xd,
......@@ -153,6 +379,11 @@ void vp10_find_mv_refs(const VP10_COMMON *cm, const MACROBLOCKD *xd,
uint8_t *mode_context) {
find_mv_refs_idx(cm, xd, mi, ref_frame, mv_ref_list, -1,
mi_row, mi_col, sync, data, mode_context);
#if CONFIG_REF_MV
setup_ref_mv_list(cm, xd, mi, ref_frame, mv_ref_list, -1,
mi_row, mi_col, mode_context);
#endif
}
static void lower_mv_precision(MV *mv, int allow_hp) {
......
......@@ -24,6 +24,13 @@ typedef struct position {
int col;
} POSITION;
#if CONFIG_REF_MV
typedef struct candidate_mv {
int_mv this_mv;
int weight;
} CANDIDATE_MV;
#endif
typedef enum {
BOTH_ZERO = 0,
ZERO_PLUS_PREDICTED = 1,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment