Commit aa5d53eb authored by Jingning Han's avatar Jingning Han

Enable adaptive prediction mode coding

This commit allows the codec to analyze the reference motion vector
candidate list and adaptively reduce the size of inter prediction
mode set.

Change-Id: Ied6a403843b860d66f26ed485c1825c05c71bdfc
parent 8edbe4d6
...@@ -257,6 +257,7 @@ typedef struct macroblockd { ...@@ -257,6 +257,7 @@ typedef struct macroblockd {
#if CONFIG_REF_MV #if CONFIG_REF_MV
uint8_t ref_mv_count[MAX_REF_FRAMES]; uint8_t ref_mv_count[MAX_REF_FRAMES];
CANDIDATE_MV ref_mv_stack[MAX_REF_FRAMES][MAX_REF_MV_STACK_SIZE]; CANDIDATE_MV ref_mv_stack[MAX_REF_FRAMES][MAX_REF_MV_STACK_SIZE];
uint8_t is_sec_rect;
#endif #endif
#if CONFIG_VP9_HIGHBITDEPTH #if CONFIG_VP9_HIGHBITDEPTH
......
...@@ -181,7 +181,7 @@ static const vpx_prob default_zeromv_prob[ZEROMV_MODE_CONTEXTS] = { ...@@ -181,7 +181,7 @@ static const vpx_prob default_zeromv_prob[ZEROMV_MODE_CONTEXTS] = {
}; };
static const vpx_prob default_refmv_prob[REFMV_MODE_CONTEXTS] = { static const vpx_prob default_refmv_prob[REFMV_MODE_CONTEXTS] = {
220, 220, 200, 200, 180, 128, 220, 220, 200, 200, 180, 128, 1, 250,
}; };
#endif #endif
......
...@@ -206,13 +206,18 @@ typedef enum { ...@@ -206,13 +206,18 @@ typedef enum {
#if CONFIG_REF_MV #if CONFIG_REF_MV
#define NEWMV_MODE_CONTEXTS 7 #define NEWMV_MODE_CONTEXTS 7
#define ZEROMV_MODE_CONTEXTS 2 #define ZEROMV_MODE_CONTEXTS 2
#define REFMV_MODE_CONTEXTS 6 #define REFMV_MODE_CONTEXTS 8
#define ZEROMV_OFFSET 3 #define ZEROMV_OFFSET 3
#define REFMV_OFFSET 4 #define REFMV_OFFSET 4
#define NEWMV_CTX_MASK ((1 << ZEROMV_OFFSET) - 1) #define NEWMV_CTX_MASK ((1 << ZEROMV_OFFSET) - 1)
#define ZEROMV_CTX_MASK ((1 << (REFMV_OFFSET - ZEROMV_OFFSET)) - 1) #define ZEROMV_CTX_MASK ((1 << (REFMV_OFFSET - ZEROMV_OFFSET)) - 1)
#define REFMV_CTX_MASK ((1 << (8 - REFMV_OFFSET)) - 1)
#define ALL_ZERO_FLAG_OFFSET 8
#define SKIP_NEARESTMV_OFFSET 9
#define SKIP_NEARMV_OFFSET 10
#endif #endif
#define INTER_MODE_CONTEXTS 7 #define INTER_MODE_CONTEXTS 7
......
...@@ -189,7 +189,6 @@ static uint8_t scan_blk_mbmi(const VP10_COMMON *cm, const MACROBLOCKD *xd, ...@@ -189,7 +189,6 @@ static uint8_t scan_blk_mbmi(const VP10_COMMON *cm, const MACROBLOCKD *xd,
static int has_top_right(const MACROBLOCKD *xd, static int has_top_right(const MACROBLOCKD *xd,
int mi_row, int mi_col, int bs) { int mi_row, int mi_col, int bs) {
int is_second_rect = 0;
int has_tr = !((mi_row & bs) & (bs * 2 - 1)) || int has_tr = !((mi_row & bs) & (bs * 2 - 1)) ||
!((mi_col & bs) & (bs * 2 - 1)); !((mi_col & bs) & (bs * 2 - 1));
...@@ -205,31 +204,55 @@ static int has_top_right(const MACROBLOCKD *xd, ...@@ -205,31 +204,55 @@ static int has_top_right(const MACROBLOCKD *xd,
if ((mi_row & 0x07) > 0) if ((mi_row & 0x07) > 0)
has_tr = 0; has_tr = 0;
if (xd->n8_w < xd->n8_h) { if (xd->n8_w < xd->n8_h)
if (mi_col & (xd->n8_h - 1)) if (!xd->is_sec_rect)
is_second_rect = 1;
if (!is_second_rect)
has_tr = 1; has_tr = 1;
}
if (xd->n8_w > xd->n8_h) { if (xd->n8_w > xd->n8_h)
if (mi_row & (xd->n8_w - 1)) if (xd->is_sec_rect)
is_second_rect = 1;
if (is_second_rect)
has_tr = 0; has_tr = 0;
}
return has_tr; return has_tr;
} }
static void handle_sec_rect_block(const MB_MODE_INFO * const candidate,
uint8_t *refmv_count,
CANDIDATE_MV *ref_mv_stack,
MV_REFERENCE_FRAME ref_frame,
int16_t *mode_context) {
int rf, idx;
for (rf = 0; rf < 2; ++rf) {
if (candidate->ref_frame[rf] == ref_frame) {
const int list_range = VPXMIN(*refmv_count, MAX_MV_REF_CANDIDATES);
const int_mv pred_mv = candidate->mv[rf];
for (idx = 0; idx < list_range; ++idx)
if (pred_mv.as_int == ref_mv_stack[idx].this_mv.as_int)
break;
if (idx < list_range) {
mode_context[ref_frame] &= ~(0x0f << REFMV_OFFSET);
if (idx == 0) {
mode_context[ref_frame] |= (1 << SKIP_NEARESTMV_OFFSET);
mode_context[ref_frame] |= (6 << REFMV_OFFSET);
} else if (idx == 1) {
mode_context[ref_frame] |= (1 << SKIP_NEARMV_OFFSET);
mode_context[ref_frame] |= (7 << REFMV_OFFSET);
}
}
}
}
}
static void setup_ref_mv_list(const VP10_COMMON *cm, const MACROBLOCKD *xd, static void setup_ref_mv_list(const VP10_COMMON *cm, const MACROBLOCKD *xd,
MV_REFERENCE_FRAME ref_frame, MV_REFERENCE_FRAME ref_frame,
uint8_t *refmv_count, uint8_t *refmv_count,
CANDIDATE_MV *ref_mv_stack, CANDIDATE_MV *ref_mv_stack,
int_mv *mv_ref_list, int_mv *mv_ref_list,
int block, int mi_row, int mi_col, int block, int mi_row, int mi_col,
uint8_t *mode_context) { int16_t *mode_context) {
int idx, nearest_refmv_count = 0; int idx, nearest_refmv_count = 0;
uint8_t newmv_count = 0; uint8_t newmv_count = 0;
...@@ -389,6 +412,23 @@ static void setup_ref_mv_list(const VP10_COMMON *cm, const MACROBLOCKD *xd, ...@@ -389,6 +412,23 @@ static void setup_ref_mv_list(const VP10_COMMON *cm, const MACROBLOCKD *xd,
len = nr_len; len = nr_len;
} }
// TODO(jingning): Clean-up needed.
if (xd->is_sec_rect) {
if (xd->n8_w < xd->n8_h) {
const MODE_INFO *const candidate_mi = xd->mi[-1];
const MB_MODE_INFO *const candidate = &candidate_mi->mbmi;
handle_sec_rect_block(candidate, refmv_count, ref_mv_stack,
ref_frame, mode_context);
}
if (xd->n8_w > xd->n8_h) {
const MODE_INFO *const candidate_mi = xd->mi[-xd->mi_stride];
const MB_MODE_INFO *const candidate = &candidate_mi->mbmi;
handle_sec_rect_block(candidate, refmv_count, ref_mv_stack,
ref_frame, mode_context);
}
}
for (idx = 0; idx < VPXMIN(MAX_MV_REF_CANDIDATES, *refmv_count); ++idx) { 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; mv_ref_list[idx].as_int = ref_mv_stack[idx].this_mv.as_int;
clamp_mv_ref(&mv_ref_list[idx].as_mv, clamp_mv_ref(&mv_ref_list[idx].as_mv,
...@@ -404,7 +444,7 @@ static void find_mv_refs_idx(const VP10_COMMON *cm, const MACROBLOCKD *xd, ...@@ -404,7 +444,7 @@ static void find_mv_refs_idx(const VP10_COMMON *cm, const MACROBLOCKD *xd,
int_mv *mv_ref_list, int_mv *mv_ref_list,
int block, int mi_row, int mi_col, int block, int mi_row, int mi_col,
find_mv_refs_sync sync, void *const data, find_mv_refs_sync sync, void *const data,
uint8_t *mode_context) { int16_t *mode_context) {
const int *ref_sign_bias = cm->ref_frame_sign_bias; const int *ref_sign_bias = cm->ref_frame_sign_bias;
int i, refmv_count = 0; int i, refmv_count = 0;
const POSITION *const mv_ref_search = mv_ref_blocks[mi->mbmi.sb_type]; const POSITION *const mv_ref_search = mv_ref_blocks[mi->mbmi.sb_type];
...@@ -541,13 +581,23 @@ void vp10_find_mv_refs(const VP10_COMMON *cm, const MACROBLOCKD *xd, ...@@ -541,13 +581,23 @@ void vp10_find_mv_refs(const VP10_COMMON *cm, const MACROBLOCKD *xd,
int_mv *mv_ref_list, int_mv *mv_ref_list,
int mi_row, int mi_col, int mi_row, int mi_col,
find_mv_refs_sync sync, void *const data, find_mv_refs_sync sync, void *const data,
uint8_t *mode_context) { int16_t *mode_context) {
#if CONFIG_REF_MV
int idx, all_zero = 1;
#endif
find_mv_refs_idx(cm, xd, mi, ref_frame, mv_ref_list, -1, find_mv_refs_idx(cm, xd, mi, ref_frame, mv_ref_list, -1,
mi_row, mi_col, sync, data, mode_context); mi_row, mi_col, sync, data, mode_context);
#if CONFIG_REF_MV #if CONFIG_REF_MV
setup_ref_mv_list(cm, xd, ref_frame, ref_mv_count, ref_mv_stack, setup_ref_mv_list(cm, xd, ref_frame, ref_mv_count, ref_mv_stack,
mv_ref_list, -1, mi_row, mi_col, mode_context); mv_ref_list, -1, mi_row, mi_col, mode_context);
for (idx = 0; idx < MAX_MV_REF_CANDIDATES; ++idx)
if (mv_ref_list[idx].as_int != 0)
all_zero = 0;
if (all_zero)
mode_context[ref_frame] |= (1 << ALL_ZERO_FLAG_OFFSET);
#endif #endif
} }
......
...@@ -204,7 +204,7 @@ void vp10_find_mv_refs(const VP10_COMMON *cm, const MACROBLOCKD *xd, ...@@ -204,7 +204,7 @@ void vp10_find_mv_refs(const VP10_COMMON *cm, const MACROBLOCKD *xd,
#endif #endif
int_mv *mv_ref_list, int mi_row, int mi_col, int_mv *mv_ref_list, int mi_row, int mi_col,
find_mv_refs_sync sync, void *const data, find_mv_refs_sync sync, void *const data,
uint8_t *mode_context); int16_t *mode_context);
// check a list of motion vectors by sad score using a number rows of pixels // check a list of motion vectors by sad score using a number rows of pixels
// above and a number cols of pixels in the left to select the one with best // above and a number cols of pixels in the left to select the one with best
......
...@@ -460,6 +460,16 @@ static INLINE void set_mi_row_col(MACROBLOCKD *xd, const TileInfo *const tile, ...@@ -460,6 +460,16 @@ static INLINE void set_mi_row_col(MACROBLOCKD *xd, const TileInfo *const tile,
xd->n8_h = bh; xd->n8_h = bh;
xd->n8_w = bw; xd->n8_w = bw;
#if CONFIG_REF_MV
xd->is_sec_rect = 0;
if (xd->n8_w < xd->n8_h)
if (mi_col & (xd->n8_h - 1))
xd->is_sec_rect = 1;
if (xd->n8_w > xd->n8_h)
if (mi_row & (xd->n8_w - 1))
xd->is_sec_rect = 1;
#endif
} }
static INLINE const vpx_prob *get_y_mode_probs(const VP10_COMMON *cm, static INLINE const vpx_prob *get_y_mode_probs(const VP10_COMMON *cm,
......
...@@ -63,10 +63,10 @@ static PREDICTION_MODE read_intra_mode_uv(VP10_COMMON *cm, MACROBLOCKD *xd, ...@@ -63,10 +63,10 @@ static PREDICTION_MODE read_intra_mode_uv(VP10_COMMON *cm, MACROBLOCKD *xd,
} }
static PREDICTION_MODE read_inter_mode(VP10_COMMON *cm, MACROBLOCKD *xd, static PREDICTION_MODE read_inter_mode(VP10_COMMON *cm, MACROBLOCKD *xd,
vpx_reader *r, uint8_t ctx) { vpx_reader *r, int16_t ctx) {
#if CONFIG_REF_MV #if CONFIG_REF_MV
FRAME_COUNTS *counts = xd->counts; FRAME_COUNTS *counts = xd->counts;
uint8_t mode_ctx = ctx & NEWMV_CTX_MASK; int16_t mode_ctx = ctx & NEWMV_CTX_MASK;
vpx_prob mode_prob = cm->fc->newmv_prob[mode_ctx]; vpx_prob mode_prob = cm->fc->newmv_prob[mode_ctx];
if (vpx_read(r, mode_prob) == 0) { if (vpx_read(r, mode_prob) == 0) {
...@@ -77,10 +77,10 @@ static PREDICTION_MODE read_inter_mode(VP10_COMMON *cm, MACROBLOCKD *xd, ...@@ -77,10 +77,10 @@ static PREDICTION_MODE read_inter_mode(VP10_COMMON *cm, MACROBLOCKD *xd,
if (counts) if (counts)
++counts->newmv_mode[mode_ctx][1]; ++counts->newmv_mode[mode_ctx][1];
mode_ctx = (ctx >> ZEROMV_OFFSET) & ZEROMV_CTX_MASK; if (ctx & (1 << ALL_ZERO_FLAG_OFFSET))
return ZEROMV;
if (mode_ctx > 1) mode_ctx = (ctx >> ZEROMV_OFFSET) & ZEROMV_CTX_MASK;
assert(0);
mode_prob = cm->fc->zeromv_prob[mode_ctx]; mode_prob = cm->fc->zeromv_prob[mode_ctx];
if (vpx_read(r, mode_prob) == 0) { if (vpx_read(r, mode_prob) == 0) {
...@@ -91,11 +91,13 @@ static PREDICTION_MODE read_inter_mode(VP10_COMMON *cm, MACROBLOCKD *xd, ...@@ -91,11 +91,13 @@ static PREDICTION_MODE read_inter_mode(VP10_COMMON *cm, MACROBLOCKD *xd,
if (counts) if (counts)
++counts->zeromv_mode[mode_ctx][1]; ++counts->zeromv_mode[mode_ctx][1];
mode_ctx = (ctx >> REFMV_OFFSET); mode_ctx = (ctx >> REFMV_OFFSET) & REFMV_CTX_MASK;
mode_prob = cm->fc->refmv_prob[mode_ctx]; mode_prob = cm->fc->refmv_prob[mode_ctx];
if (vpx_read(r, mode_prob) == 0) { if (vpx_read(r, mode_prob) == 0) {
if (counts) if (counts)
++counts->refmv_mode[mode_ctx][0]; ++counts->refmv_mode[mode_ctx][0];
return NEARESTMV; return NEARESTMV;
} else { } else {
if (counts) if (counts)
...@@ -814,7 +816,8 @@ static void read_inter_block_mode_info(VP10Decoder *const pbi, ...@@ -814,7 +816,8 @@ static void read_inter_block_mode_info(VP10Decoder *const pbi,
int_mv nearestmv[2], nearmv[2]; int_mv nearestmv[2], nearmv[2];
int_mv ref_mvs[MAX_REF_FRAMES][MAX_MV_REF_CANDIDATES]; int_mv ref_mvs[MAX_REF_FRAMES][MAX_MV_REF_CANDIDATES];
int ref, is_compound; int ref, is_compound;
uint8_t inter_mode_ctx[MAX_REF_FRAMES]; int16_t inter_mode_ctx[MAX_REF_FRAMES];
int16_t mode_ctx = 0;
read_ref_frames(cm, xd, r, mbmi->segment_id, mbmi->ref_frame); read_ref_frames(cm, xd, r, mbmi->segment_id, mbmi->ref_frame);
is_compound = has_second_ref(mbmi); is_compound = has_second_ref(mbmi);
...@@ -838,6 +841,15 @@ static void read_inter_block_mode_info(VP10Decoder *const pbi, ...@@ -838,6 +841,15 @@ static void read_inter_block_mode_info(VP10Decoder *const pbi,
mi_row, mi_col, fpm_sync, (void *)pbi, inter_mode_ctx); mi_row, mi_col, fpm_sync, (void *)pbi, inter_mode_ctx);
} }
mode_ctx = inter_mode_ctx[mbmi->ref_frame[0]];
#if CONFIG_REF_MV
if (mbmi->ref_frame[1] > NONE)
mode_ctx &= (inter_mode_ctx[mbmi->ref_frame[1]] | 0x00ff);
if (bsize < BLOCK_8X8)
mode_ctx &= 0x00ff;
#endif
if (segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP)) { if (segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP)) {
mbmi->mode = ZEROMV; mbmi->mode = ZEROMV;
if (bsize < BLOCK_8X8) { if (bsize < BLOCK_8X8) {
...@@ -847,8 +859,7 @@ static void read_inter_block_mode_info(VP10Decoder *const pbi, ...@@ -847,8 +859,7 @@ static void read_inter_block_mode_info(VP10Decoder *const pbi,
} }
} else { } else {
if (bsize >= BLOCK_8X8) if (bsize >= BLOCK_8X8)
mbmi->mode = read_inter_mode(cm, xd, r, mbmi->mode = read_inter_mode(cm, xd, r, mode_ctx);
inter_mode_ctx[mbmi->ref_frame[0]]);
} }
if (bsize < BLOCK_8X8 || mbmi->mode != ZEROMV) { if (bsize < BLOCK_8X8 || mbmi->mode != ZEROMV) {
...@@ -874,7 +885,7 @@ static void read_inter_block_mode_info(VP10Decoder *const pbi, ...@@ -874,7 +885,7 @@ static void read_inter_block_mode_info(VP10Decoder *const pbi,
for (idx = 0; idx < 2; idx += num_4x4_w) { for (idx = 0; idx < 2; idx += num_4x4_w) {
int_mv block[2]; int_mv block[2];
const int j = idy * 2 + idx; const int j = idy * 2 + idx;
b_mode = read_inter_mode(cm, xd, r, inter_mode_ctx[mbmi->ref_frame[0]]); b_mode = read_inter_mode(cm, xd, r, mode_ctx);
if (b_mode == NEARESTMV || b_mode == NEARMV) { if (b_mode == NEARESTMV || b_mode == NEARMV) {
for (ref = 0; ref < 1 + is_compound; ++ref) for (ref = 0; ref < 1 + is_compound; ++ref)
......
...@@ -103,19 +103,25 @@ static void write_intra_mode(vpx_writer *w, PREDICTION_MODE mode, ...@@ -103,19 +103,25 @@ static void write_intra_mode(vpx_writer *w, PREDICTION_MODE mode,
static void write_inter_mode(VP10_COMMON *cm, static void write_inter_mode(VP10_COMMON *cm,
vpx_writer *w, PREDICTION_MODE mode, vpx_writer *w, PREDICTION_MODE mode,
const uint8_t mode_ctx) { const int16_t mode_ctx) {
#if CONFIG_REF_MV #if CONFIG_REF_MV
const uint8_t newmv_ctx = mode_ctx & NEWMV_CTX_MASK; const int16_t newmv_ctx = mode_ctx & NEWMV_CTX_MASK;
const vpx_prob newmv_prob = cm->fc->newmv_prob[newmv_ctx]; const vpx_prob newmv_prob = cm->fc->newmv_prob[newmv_ctx];
vpx_write(w, mode != NEWMV, newmv_prob); vpx_write(w, mode != NEWMV, newmv_prob);
if (mode != NEWMV) { if (mode != NEWMV) {
const uint8_t zeromv_ctx = (mode_ctx >> ZEROMV_OFFSET) & ZEROMV_CTX_MASK; const int16_t zeromv_ctx = (mode_ctx >> ZEROMV_OFFSET) & ZEROMV_CTX_MASK;
const vpx_prob zeromv_prob = cm->fc->zeromv_prob[zeromv_ctx]; const vpx_prob zeromv_prob = cm->fc->zeromv_prob[zeromv_ctx];
if (mode_ctx & (1 << ALL_ZERO_FLAG_OFFSET)) {
assert(mode == ZEROMV);
return;
}
vpx_write(w, mode != ZEROMV, zeromv_prob); vpx_write(w, mode != ZEROMV, zeromv_prob);
if (mode != ZEROMV) { if (mode != ZEROMV) {
const uint8_t refmv_ctx = (mode_ctx >> REFMV_OFFSET); const int16_t refmv_ctx = (mode_ctx >> REFMV_OFFSET) & REFMV_CTX_MASK;
const vpx_prob refmv_prob = cm->fc->refmv_prob[refmv_ctx]; const vpx_prob refmv_prob = cm->fc->refmv_prob[refmv_ctx];
vpx_write(w, mode != NEARESTMV, refmv_prob); vpx_write(w, mode != NEARESTMV, refmv_prob);
} }
...@@ -714,9 +720,16 @@ static void pack_inter_mode_mvs(VP10_COMP *cpi, const MODE_INFO *mi, ...@@ -714,9 +720,16 @@ static void pack_inter_mode_mvs(VP10_COMP *cpi, const MODE_INFO *mi,
write_ext_intra_mode_info(cm, mbmi, w); write_ext_intra_mode_info(cm, mbmi, w);
#endif // CONFIG_EXT_INTRA #endif // CONFIG_EXT_INTRA
} else { } else {
const int mode_ctx = mbmi_ext->mode_context[mbmi->ref_frame[0]]; int16_t mode_ctx = mbmi_ext->mode_context[mbmi->ref_frame[0]];
write_ref_frames(cm, xd, w); write_ref_frames(cm, xd, w);
#if CONFIG_REF_MV
if (mbmi->ref_frame[1] > NONE)
mode_ctx &= (mbmi_ext->mode_context[mbmi->ref_frame[1]] | 0x00ff);
if (bsize < BLOCK_8X8)
mode_ctx &= 0x00ff;
#endif
// If segment skip is not enabled code the mode. // If segment skip is not enabled code the mode.
if (!segfeature_active(seg, segment_id, SEG_LVL_SKIP)) { if (!segfeature_active(seg, segment_id, SEG_LVL_SKIP)) {
if (bsize >= BLOCK_8X8) { if (bsize >= BLOCK_8X8) {
......
...@@ -52,7 +52,7 @@ typedef unsigned int vp10_coeff_cost[PLANE_TYPES][REF_TYPES][COEF_BANDS][2] ...@@ -52,7 +52,7 @@ typedef unsigned int vp10_coeff_cost[PLANE_TYPES][REF_TYPES][COEF_BANDS][2]
typedef struct { typedef struct {
int_mv ref_mvs[MAX_REF_FRAMES][MAX_MV_REF_CANDIDATES]; int_mv ref_mvs[MAX_REF_FRAMES][MAX_MV_REF_CANDIDATES];
uint8_t mode_context[MAX_REF_FRAMES]; int16_t mode_context[MAX_REF_FRAMES];
#if CONFIG_REF_MV #if CONFIG_REF_MV
uint8_t ref_mv_count[MAX_REF_FRAMES]; uint8_t ref_mv_count[MAX_REF_FRAMES];
CANDIDATE_MV ref_mv_stack[MAX_REF_FRAMES][MAX_REF_MV_STACK_SIZE]; CANDIDATE_MV ref_mv_stack[MAX_REF_FRAMES][MAX_REF_MV_STACK_SIZE];
......
...@@ -1260,20 +1260,25 @@ static void rd_pick_sb_modes(VP10_COMP *cpi, ...@@ -1260,20 +1260,25 @@ static void rd_pick_sb_modes(VP10_COMP *cpi,
#if CONFIG_REF_MV #if CONFIG_REF_MV
static void update_inter_mode_stats(FRAME_COUNTS *counts, static void update_inter_mode_stats(FRAME_COUNTS *counts,
PREDICTION_MODE mode, PREDICTION_MODE mode,
uint8_t mode_context) { int16_t mode_context) {
uint8_t mode_ctx = mode_context & NEWMV_CTX_MASK; int16_t mode_ctx = mode_context & NEWMV_CTX_MASK;
if (mode == NEWMV) { if (mode == NEWMV) {
++counts->newmv_mode[mode_ctx][0]; ++counts->newmv_mode[mode_ctx][0];
return; return;
} else { } else {
++counts->newmv_mode[mode_ctx][1]; ++counts->newmv_mode[mode_ctx][1];
if (mode_context & (1 << ALL_ZERO_FLAG_OFFSET)) {
return;
}
mode_ctx = (mode_context >> ZEROMV_OFFSET) & ZEROMV_CTX_MASK; mode_ctx = (mode_context >> ZEROMV_OFFSET) & ZEROMV_CTX_MASK;
if (mode == ZEROMV) { if (mode == ZEROMV) {
++counts->zeromv_mode[mode_ctx][0]; ++counts->zeromv_mode[mode_ctx][0];
return; return;
} else { } else {
++counts->zeromv_mode[mode_ctx][1]; ++counts->zeromv_mode[mode_ctx][1];
mode_ctx = (mode_context >> REFMV_OFFSET); mode_ctx = (mode_context >> REFMV_OFFSET) & REFMV_CTX_MASK;
++counts->refmv_mode[mode_ctx][mode != NEARESTMV]; ++counts->refmv_mode[mode_ctx][mode != NEARESTMV];
} }
} }
...@@ -1355,10 +1360,12 @@ static void update_stats(VP10_COMMON *cm, ThreadData *td) { ...@@ -1355,10 +1360,12 @@ static void update_stats(VP10_COMMON *cm, ThreadData *td) {
} }
if (inter_block && if (inter_block &&
!segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP)) { !segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP)) {
const int mode_ctx = mbmi_ext->mode_context[mbmi->ref_frame[0]]; int16_t mode_ctx = mbmi_ext->mode_context[mbmi->ref_frame[0]];
if (bsize >= BLOCK_8X8) { if (bsize >= BLOCK_8X8) {
const PREDICTION_MODE mode = mbmi->mode; const PREDICTION_MODE mode = mbmi->mode;
#if CONFIG_REF_MV #if CONFIG_REF_MV
if (mbmi->ref_frame[1] > NONE)
mode_ctx &= (mbmi_ext->mode_context[mbmi->ref_frame[1]] | 0x00ff);
update_inter_mode_stats(counts, mode, mode_ctx); update_inter_mode_stats(counts, mode, mode_ctx);
#else #else
++counts->inter_mode[mode_ctx][INTER_OFFSET(mode)]; ++counts->inter_mode[mode_ctx][INTER_OFFSET(mode)];
...@@ -1372,6 +1379,7 @@ static void update_stats(VP10_COMMON *cm, ThreadData *td) { ...@@ -1372,6 +1379,7 @@ static void update_stats(VP10_COMMON *cm, ThreadData *td) {
const int j = idy * 2 + idx; const int j = idy * 2 + idx;
const PREDICTION_MODE b_mode = mi->bmi[j].as_mode; const PREDICTION_MODE b_mode = mi->bmi[j].as_mode;
#if CONFIG_REF_MV #if CONFIG_REF_MV
mode_ctx &= 0x00ff;
update_inter_mode_stats(counts, b_mode, mode_ctx); update_inter_mode_stats(counts, b_mode, mode_ctx);
#else #else
++counts->inter_mode[mode_ctx][INTER_OFFSET(b_mode)]; ++counts->inter_mode[mode_ctx][INTER_OFFSET(b_mode)];
......
...@@ -3025,10 +3025,11 @@ static void choose_intra_uv_mode(VP10_COMP *cpi, MACROBLOCK *const x, ...@@ -3025,10 +3025,11 @@ static void choose_intra_uv_mode(VP10_COMP *cpi, MACROBLOCK *const x,
} }
static int cost_mv_ref(const VP10_COMP *cpi, PREDICTION_MODE mode, static int cost_mv_ref(const VP10_COMP *cpi, PREDICTION_MODE mode,
uint8_t mode_context) { int16_t mode_context) {
#if CONFIG_REF_MV #if CONFIG_REF_MV
int mode_cost = 0; int mode_cost = 0;
uint8_t mode_ctx = mode_context & NEWMV_CTX_MASK; int16_t mode_ctx = mode_context & NEWMV_CTX_MASK;
int16_t is_all_zero_mv = mode_context & (1 << ALL_ZERO_FLAG_OFFSET);
assert(is_inter_mode(mode)); assert(is_inter_mode(mode));
...@@ -3038,12 +3039,16 @@ static int cost_mv_ref(const VP10_COMP *cpi, PREDICTION_MODE mode, ...@@ -3038,12 +3039,16 @@ static int cost_mv_ref(const VP10_COMP *cpi, PREDICTION_MODE mode,
} else { } else {
mode_cost = cpi->newmv_mode_cost[mode_ctx][1]; mode_cost = cpi->newmv_mode_cost[mode_ctx][1];
mode_ctx = (mode_context >> ZEROMV_OFFSET) & ZEROMV_CTX_MASK; mode_ctx = (mode_context >> ZEROMV_OFFSET) & ZEROMV_CTX_MASK;
if (is_all_zero_mv)
return mode_cost;
if (mode == ZEROMV) { if (mode == ZEROMV) {
mode_cost += cpi->zeromv_mode_cost[mode_ctx][0]; mode_cost += cpi->zeromv_mode_cost[mode_ctx][0];
return mode_cost; return mode_cost;
} else { } else {
mode_cost += cpi->zeromv_mode_cost[mode_ctx][1]; mode_cost += cpi->zeromv_mode_cost[mode_ctx][1];
mode_ctx = (mode_context >> REFMV_OFFSET); mode_ctx = (mode_context >> REFMV_OFFSET) & REFMV_CTX_MASK;
mode_cost += cpi->refmv_mode_cost[mode_ctx][mode != NEARESTMV]; mode_cost += cpi->refmv_mode_cost[mode_ctx][mode != NEARESTMV];
return mode_cost; return mode_cost;
} }
...@@ -3069,6 +3074,7 @@ static int set_and_cost_bmi_mvs(VP10_COMP *cpi, MACROBLOCK *x, MACROBLOCKD *xd, ...@@ -3069,6 +3074,7 @@ static int set_and_cost_bmi_mvs(VP10_COMP *cpi, MACROBLOCK *x, MACROBLOCKD *xd,
const int num_4x4_blocks_wide = num_4x4_blocks_wide_lookup[mbmi->sb_type]; const int num_4x4_blocks_wide = num_4x4_blocks_wide_lookup[mbmi->sb_type];
const int num_4x4_blocks_high = num_4x4_blocks_high_lookup[mbmi->sb_type]; const int num_4x4_blocks_high = num_4x4_blocks_high_lookup[mbmi->sb_type];
const int is_compound = has_second_ref(mbmi); const int is_compound = has_second_ref(mbmi);
int mode_ctx = mbmi_ext->mode_context[mbmi->ref_frame[0]];
switch (mode) { switch (mode) {
case NEWMV: case NEWMV:
...@@ -3106,8 +3112,10 @@ static int set_and_cost_bmi_mvs(VP10_COMP *cpi, MACROBLOCK *x, MACROBLOCKD *xd, ...@@ -3106,8 +3112,10 @@ static int set_and_cost_bmi_mvs(VP10_COMP *cpi, MACROBLOCK *x, MACROBLOCKD *xd,
for (idx = 0; idx < num_4x4_blocks_wide; ++idx) for (idx = 0; idx < num_4x4_blocks_wide; ++idx)
memmove(&mic->bmi[i + idy * 2 + idx], &mic->bmi[i], sizeof(mic->bmi[i])); memmove(&mic->bmi[i + idy * 2 + idx], &mic->bmi[i], sizeof(mic->bmi[i]));
return cost_mv_ref(cpi, mode, mbmi_ext->mode_context[mbmi->ref_frame[0]]) + #if CONFIG_REF_MV
thismvcost; mode_ctx &= 0x00ff;
#endif
return cost_mv_ref(cpi, mode, mode_ctx) + thismvcost;
} }
static int64_t encode_inter_mb_segment(VP10_COMP *cpi, static int64_t encode_inter_mb_segment(VP10_COMP *cpi,
...@@ -3288,14 +3296,19 @@ static INLINE void mi_buf_restore(MACROBLOCK *x, struct buf_2d orig_src, ...@@ -3288,14 +3296,19 @@ static INLINE void mi_buf_restore(MACROBLOCK *x, struct buf_2d orig_src,
// Check if NEARESTMV/NEARMV/ZEROMV is the cheapest way encode zero motion. // Check if NEARESTMV/NEARMV/ZEROMV is the cheapest way encode zero motion.
// TODO(aconverse): Find out if this is still productive then clean up or remove // TODO(aconvers