Commit 387a10e3 authored by Jingning Han's avatar Jingning Han

Enable context analyzer for inter mode entropy coding

It allows the codec to account for certain corner cases when
processing inter prediction mode entropy coding.

Change-Id: Ied451f4fff26ba579f6556554b8381ff2ccd0003
parent c557efaf
......@@ -181,7 +181,7 @@ static const vpx_prob default_zeromv_prob[ZEROMV_MODE_CONTEXTS] = {
};
static const vpx_prob default_refmv_prob[REFMV_MODE_CONTEXTS] = {
220, 220, 200, 200, 180, 128, 1, 250,
220, 220, 200, 200, 180, 128, 30, 220, 30,
};
#endif
......
......@@ -207,7 +207,7 @@ typedef enum {
#if CONFIG_REF_MV
#define NEWMV_MODE_CONTEXTS 7
#define ZEROMV_MODE_CONTEXTS 2
#define REFMV_MODE_CONTEXTS 8
#define REFMV_MODE_CONTEXTS 9
#define ZEROMV_OFFSET 3
#define REFMV_OFFSET 4
......@@ -219,6 +219,7 @@ typedef enum {
#define ALL_ZERO_FLAG_OFFSET 8
#define SKIP_NEARESTMV_OFFSET 9
#define SKIP_NEARMV_OFFSET 10
#define SKIP_NEARESTMV_SUB8X8_OFFSET 11
#endif
#define INTER_MODE_CONTEXTS 7
......
......@@ -216,7 +216,7 @@ static int has_top_right(const MACROBLOCKD *xd,
}
static void handle_sec_rect_block(const MB_MODE_INFO * const candidate,
uint8_t *refmv_count,
uint8_t refmv_count,
CANDIDATE_MV *ref_mv_stack,
MV_REFERENCE_FRAME ref_frame,
int16_t *mode_context) {
......@@ -224,7 +224,7 @@ static void handle_sec_rect_block(const MB_MODE_INFO * const candidate,
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 list_range = VPXMIN(refmv_count, MAX_MV_REF_CANDIDATES);
const int_mv pred_mv = candidate->mv[rf];
for (idx = 0; idx < list_range; ++idx)
......@@ -232,15 +232,10 @@ static void handle_sec_rect_block(const MB_MODE_INFO * const candidate,
break;
if (idx < list_range) {
mode_context[ref_frame] &= ~(0x0f << REFMV_OFFSET);
if (idx == 0) {
if (idx == 0)
mode_context[ref_frame] |= (1 << SKIP_NEARESTMV_OFFSET);
mode_context[ref_frame] |= (6 << REFMV_OFFSET);
} else if (idx == 1) {
else if (idx == 1)
mode_context[ref_frame] |= (1 << SKIP_NEARMV_OFFSET);
mode_context[ref_frame] |= (7 << REFMV_OFFSET);
}
}
}
}
......@@ -417,14 +412,14 @@ static void setup_ref_mv_list(const VP10_COMMON *cm, const MACROBLOCKD *xd,
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,
handle_sec_rect_block(candidate, nearest_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,
handle_sec_rect_block(candidate, nearest_refmv_count, ref_mv_stack,
ref_frame, mode_context);
}
}
......
......@@ -195,6 +195,29 @@ static INLINE int is_inside(const TileInfo *const tile,
mi_col + mi_pos->col >= tile->mi_col_end);
}
#if CONFIG_REF_MV
static int16_t vp10_mode_context_analyzer(const int16_t *const mode_context,
const MV_REFERENCE_FRAME *const rf,
BLOCK_SIZE bsize, int block) {
int16_t mode_ctx = 0;
if (block >= 0) {
mode_ctx = mode_context[rf[0]] & 0x00ff;
if (block > 0 && bsize < BLOCK_8X8 && bsize > BLOCK_4X4)
mode_ctx |= (1 << SKIP_NEARESTMV_SUB8X8_OFFSET);
return mode_ctx;
}
if (rf[1] > INTRA_FRAME)
return mode_context[rf[0]] & (mode_context[rf[1]] | 0x00ff);
else if (rf[0] != ALTREF_FRAME)
return mode_context[rf[0]] & ~(mode_context[ALTREF_FRAME] & 0xfe00);
else
return mode_context[rf[0]];
}
#endif
typedef void (*find_mv_refs_sync)(void *const data, int mi_row);
void vp10_find_mv_refs(const VP10_COMMON *cm, const MACROBLOCKD *xd,
MODE_INFO *mi, MV_REFERENCE_FRAME ref_frame,
......
......@@ -92,6 +92,14 @@ static PREDICTION_MODE read_inter_mode(VP10_COMMON *cm, MACROBLOCKD *xd,
++counts->zeromv_mode[mode_ctx][1];
mode_ctx = (ctx >> REFMV_OFFSET) & REFMV_CTX_MASK;
if (ctx & (1 << SKIP_NEARESTMV_OFFSET))
mode_ctx = 6;
if (ctx & (1 << SKIP_NEARMV_OFFSET))
mode_ctx = 7;
if (ctx & (1 << SKIP_NEARESTMV_SUB8X8_OFFSET))
mode_ctx = 8;
mode_prob = cm->fc->refmv_prob[mode_ctx];
if (vpx_read(r, mode_prob) == 0) {
......@@ -820,12 +828,13 @@ static void read_inter_block_mode_info(VP10Decoder *const pbi,
int ref, is_compound;
int16_t inter_mode_ctx[MAX_REF_FRAMES];
int16_t mode_ctx = 0;
MV_REFERENCE_FRAME ref_frame;
read_ref_frames(cm, xd, r, mbmi->segment_id, mbmi->ref_frame);
is_compound = has_second_ref(mbmi);
for (ref = 0; ref < 1 + is_compound; ++ref) {
const MV_REFERENCE_FRAME frame = mbmi->ref_frame[ref];
MV_REFERENCE_FRAME frame = mbmi->ref_frame[ref];
RefBuffer *ref_buf = &cm->frame_refs[frame - LAST_FRAME];
xd->block_refs[ref] = ref_buf;
......@@ -834,22 +843,23 @@ static void read_inter_block_mode_info(VP10Decoder *const pbi,
"Reference frame has invalid dimensions");
vp10_setup_pre_planes(xd, ref, ref_buf->buf, mi_row, mi_col,
&ref_buf->sf);
vp10_find_mv_refs(cm, xd, mi, frame,
}
for (ref_frame = LAST_FRAME; ref_frame < MAX_REF_FRAMES; ++ref_frame) {
vp10_find_mv_refs(cm, xd, mi, ref_frame,
#if CONFIG_REF_MV
&xd->ref_mv_count[frame],
xd->ref_mv_stack[frame],
&xd->ref_mv_count[ref_frame],
xd->ref_mv_stack[ref_frame],
#endif
ref_mvs[frame],
ref_mvs[ref_frame],
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;
mode_ctx = vp10_mode_context_analyzer(inter_mode_ctx,
mbmi->ref_frame, bsize, -1);
#endif
if (segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP)) {
......@@ -887,6 +897,10 @@ static void read_inter_block_mode_info(VP10Decoder *const pbi,
for (idx = 0; idx < 2; idx += num_4x4_w) {
int_mv block[2];
const int j = idy * 2 + idx;
#if CONFIG_REF_MV
mode_ctx = vp10_mode_context_analyzer(inter_mode_ctx, mbmi->ref_frame,
bsize, j);
#endif
b_mode = read_inter_mode(cm, xd, r, mode_ctx);
if (b_mode == NEARESTMV || b_mode == NEARMV) {
......
......@@ -131,8 +131,17 @@ static void write_inter_mode(VP10_COMMON *cm,
vpx_write(w, mode != ZEROMV, zeromv_prob);
if (mode != ZEROMV) {
const int16_t refmv_ctx = (mode_ctx >> REFMV_OFFSET) & REFMV_CTX_MASK;
const vpx_prob refmv_prob = cm->fc->refmv_prob[refmv_ctx];
int16_t refmv_ctx = (mode_ctx >> REFMV_OFFSET) & REFMV_CTX_MASK;
vpx_prob refmv_prob;
if (mode_ctx & (1 << SKIP_NEARESTMV_OFFSET))
refmv_ctx = 6;
if (mode_ctx & (1 << SKIP_NEARMV_OFFSET))
refmv_ctx = 7;
if (mode_ctx & (1 << SKIP_NEARESTMV_SUB8X8_OFFSET))
refmv_ctx = 8;
refmv_prob = cm->fc->refmv_prob[refmv_ctx];
vpx_write(w, mode != NEARESTMV, refmv_prob);
}
}
......@@ -776,10 +785,8 @@ static void pack_inter_mode_mvs(VP10_COMP *cpi, const MODE_INFO *mi,
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;
mode_ctx = vp10_mode_context_analyzer(mbmi_ext->mode_context,
mbmi->ref_frame, bsize, -1);
#endif
// If segment skip is not enabled code the mode.
......@@ -801,6 +808,10 @@ static void pack_inter_mode_mvs(VP10_COMP *cpi, const MODE_INFO *mi,
for (idx = 0; idx < 2; idx += num_4x4_w) {
const int j = idy * 2 + idx;
const PREDICTION_MODE b_mode = mi->bmi[j].as_mode;
#if CONFIG_REF_MV
mode_ctx = vp10_mode_context_analyzer(mbmi_ext->mode_context,
mbmi->ref_frame, bsize, j);
#endif
write_inter_mode(cm, w, b_mode, mode_ctx);
if (b_mode == NEWMV) {
for (ref = 0; ref < 1 + is_compound; ++ref)
......
......@@ -1687,6 +1687,14 @@ static void update_inter_mode_stats(FRAME_COUNTS *counts,
} else {
++counts->zeromv_mode[mode_ctx][1];
mode_ctx = (mode_context >> REFMV_OFFSET) & REFMV_CTX_MASK;
if (mode_context & (1 << SKIP_NEARESTMV_OFFSET))
mode_ctx = 6;
if (mode_context & (1 << SKIP_NEARMV_OFFSET))
mode_ctx = 7;
if (mode_context & (1 << SKIP_NEARESTMV_SUB8X8_OFFSET))
mode_ctx = 8;
++counts->refmv_mode[mode_ctx][mode != NEARESTMV];
}
}
......@@ -1779,8 +1787,8 @@ static void update_stats(VP10_COMMON *cm, ThreadData *td
if (bsize >= BLOCK_8X8) {
const PREDICTION_MODE mode = mbmi->mode;
#if CONFIG_REF_MV
if (mbmi->ref_frame[1] > NONE)
mode_ctx &= (mbmi_ext->mode_context[mbmi->ref_frame[1]] | 0x00ff);
mode_ctx = vp10_mode_context_analyzer(mbmi_ext->mode_context,
mbmi->ref_frame, bsize, -1);
update_inter_mode_stats(counts, mode, mode_ctx);
#else
++counts->inter_mode[mode_ctx][INTER_OFFSET(mode)];
......@@ -1794,7 +1802,8 @@ static void update_stats(VP10_COMMON *cm, ThreadData *td
const int j = idy * 2 + idx;
const PREDICTION_MODE b_mode = mi->bmi[j].as_mode;
#if CONFIG_REF_MV
mode_ctx &= 0x00ff;
mode_ctx = vp10_mode_context_analyzer(mbmi_ext->mode_context,
mbmi->ref_frame, bsize, j);
update_inter_mode_stats(counts, b_mode, mode_ctx);
#else
++counts->inter_mode[mode_ctx][INTER_OFFSET(b_mode)];
......
......@@ -3340,7 +3340,6 @@ static void encode_with_recode_loop(VP10_COMP *cpi,
// update_base_skip_probs(cpi);
vpx_clear_system_state();
// Dummy pack of the bitstream using up to date stats to get an
// accurate estimate of output frame size to determine if we need
// to recode.
......
......@@ -3099,6 +3099,14 @@ static int cost_mv_ref(const VP10_COMP *cpi, PREDICTION_MODE mode,
} else {
mode_cost += cpi->zeromv_mode_cost[mode_ctx][1];
mode_ctx = (mode_context >> REFMV_OFFSET) & REFMV_CTX_MASK;
if (mode_context & (1 << SKIP_NEARESTMV_OFFSET))
mode_ctx = 6;
if (mode_context & (1 << SKIP_NEARMV_OFFSET))
mode_ctx = 7;
if (mode_context & (1 << SKIP_NEARESTMV_SUB8X8_OFFSET))
mode_ctx = 8;
mode_cost += cpi->refmv_mode_cost[mode_ctx][mode != NEARESTMV];
return mode_cost;
}
......@@ -3163,7 +3171,8 @@ static int set_and_cost_bmi_mvs(VP10_COMP *cpi, MACROBLOCK *x, MACROBLOCKD *xd,
memmove(&mic->bmi[i + idy * 2 + idx], &mic->bmi[i], sizeof(mic->bmi[i]));
#if CONFIG_REF_MV
mode_ctx &= 0x00ff;
mode_ctx = vp10_mode_context_analyzer(mbmi_ext->mode_context,
mbmi->ref_frame, mbmi->sb_type, i);
#endif
return cost_mv_ref(cpi, mode, mode_ctx) + thismvcost;
}
......@@ -3348,14 +3357,15 @@ static INLINE void mi_buf_restore(MACROBLOCK *x, struct buf_2d orig_src,
static int check_best_zero_mv(
const VP10_COMP *cpi, const int16_t mode_context[MAX_REF_FRAMES],
int_mv frame_mv[MB_MODE_COUNT][MAX_REF_FRAMES], int this_mode,
const MV_REFERENCE_FRAME ref_frames[2]) {
const MV_REFERENCE_FRAME ref_frames[2],
const BLOCK_SIZE bsize, int block) {
if ((this_mode == NEARMV || this_mode == NEARESTMV || this_mode == ZEROMV) &&
frame_mv[this_mode][ref_frames[0]].as_int == 0 &&
(ref_frames[1] == NONE ||
frame_mv[this_mode][ref_frames[1]].as_int == 0)) {
#if CONFIG_REF_MV
int16_t rfc = (ref_frames[1] == NONE) ? mode_context[ref_frames[0]] :
mode_context[ref_frames[0]] & (mode_context[ref_frames[1]] | 0x00ff);
int16_t rfc = vp10_mode_context_analyzer(mode_context,
ref_frames, bsize, block);
#else
int16_t rfc = mode_context[ref_frames[0]];
#endif
......@@ -3363,6 +3373,11 @@ static int check_best_zero_mv(
int c2 = cost_mv_ref(cpi, NEARESTMV, rfc);
int c3 = cost_mv_ref(cpi, ZEROMV, rfc);
#if !CONFIG_REF_MV
(void)bsize;
(void)block;
#endif
if (this_mode == NEARMV) {
if (c1 > c3) return 0;
} else if (this_mode == NEARESTMV) {
......@@ -3656,7 +3671,7 @@ static int64_t rd_pick_best_sub8x8_mode(VP10_COMP *cpi, MACROBLOCK *x,
continue;
if (!check_best_zero_mv(cpi, mbmi_ext->mode_context, frame_mv,
this_mode, mbmi->ref_frame))
this_mode, mbmi->ref_frame, bsize, i))
continue;
memcpy(orig_pre, pd->pre, sizeof(orig_pre));
......@@ -4261,8 +4276,6 @@ static void single_motion_search(VP10_COMP *cpi, MACROBLOCK *x,
}
}
static INLINE void restore_dst_buf(MACROBLOCKD *xd,
uint8_t *orig_dst[MAX_MB_PLANE],
int orig_dst_stride[MAX_MB_PLANE]) {
......@@ -4360,8 +4373,8 @@ static int64_t handle_inter_mode(VP10_COMP *cpi, MACROBLOCK *x,
int16_t mode_ctx = mbmi_ext->mode_context[refs[0]];
#if CONFIG_REF_MV
if (refs[1] > NONE)
mode_ctx &= (mbmi_ext->mode_context[refs[1]] | 0x00ff);
mode_ctx = vp10_mode_context_analyzer(mbmi_ext->mode_context,
mbmi->ref_frame, bsize, -1);
#endif
#if CONFIG_VP9_HIGHBITDEPTH
......@@ -5012,6 +5025,7 @@ void vp10_rd_pick_inter_mode_sb(VP10_COMP *cpi,
for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
x->pred_mv_sad[ref_frame] = INT_MAX;
x->mbmi_ext->mode_context[ref_frame] = 0;
if (cpi->ref_frame_flags & flag_list[ref_frame]) {
assert(get_ref_frame_buffer(cpi, ref_frame) != NULL);
setup_buffer_inter(cpi, x, ref_frame, bsize, mi_row, mi_col,
......@@ -5243,7 +5257,7 @@ void vp10_rd_pick_inter_mode_sb(VP10_COMP *cpi,
} else {
const MV_REFERENCE_FRAME ref_frames[2] = {ref_frame, second_ref_frame};
if (!check_best_zero_mv(cpi, mbmi_ext->mode_context, frame_mv,
this_mode, ref_frames))
this_mode, ref_frames, bsize, -1))
continue;
}
......@@ -5923,6 +5937,7 @@ void vp10_rd_pick_inter_mode_sub8x8(struct VP10_COMP *cpi,
#endif
for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ref_frame++) {
x->mbmi_ext->mode_context[ref_frame] = 0;
if (cpi->ref_frame_flags & flag_list[ref_frame]) {
setup_buffer_inter(cpi, x, ref_frame, bsize, mi_row, mi_col,
frame_mv[NEARESTMV], frame_mv[NEARMV],
......
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