Commit 3b4479eb authored by Jingning Han's avatar Jingning Han
Browse files

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: I51a1adda0d9e27bd1e18d912fd56ca4422b607b4
parent de6741bf
......@@ -241,7 +241,7 @@ static const aom_prob default_zeromv_prob[ZEROMV_MODE_CONTEXTS] = {
};
static const aom_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
......
......@@ -134,7 +134,7 @@ typedef uint8_t PREDICTION_MODE;
#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
......@@ -146,6 +146,7 @@ typedef uint8_t PREDICTION_MODE;
#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
......
......@@ -214,7 +214,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) {
......@@ -222,22 +222,17 @@ 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 = AOMMIN(*refmv_count, MAX_MV_REF_CANDIDATES);
const int list_range = AOMMIN(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) {
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);
}
}
}
}
......@@ -384,14 +379,14 @@ static void setup_ref_mv_list(const AV1_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_mbmi = &candidate_mi->mbmi;
handle_sec_rect_block(candidate_mbmi, refmv_count, ref_mv_stack,
handle_sec_rect_block(candidate_mbmi, 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_mbmi = &candidate_mi->mbmi;
handle_sec_rect_block(candidate_mbmi, refmv_count, ref_mv_stack,
handle_sec_rect_block(candidate_mbmi, nearest_refmv_count, ref_mv_stack,
ref_frame, mode_context);
}
}
......
......@@ -302,6 +302,29 @@ static INLINE int is_inside(const TileInfo *const tile, int mi_col, int mi_row,
mi_col + mi_pos->col >= tile->mi_col_end);
}
#if CONFIG_REF_MV
static int16_t av1_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 av1_find_mv_refs(const AV1_COMMON *cm, const MACROBLOCKD *xd,
MODE_INFO *mi, MV_REFERENCE_FRAME ref_frame,
......
......@@ -78,6 +78,14 @@ static PREDICTION_MODE read_inter_mode(AV1_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 (aom_read(r, mode_prob) == 0) {
if (counts)
......@@ -560,6 +568,7 @@ static void read_inter_block_mode_info(AV1Decoder *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);
......@@ -573,22 +582,23 @@ static void read_inter_block_mode_info(AV1Decoder *const pbi,
aom_internal_error(xd->error_info, AOM_CODEC_UNSUP_BITSTREAM,
"Reference frame has invalid dimensions");
av1_setup_pre_planes(xd, ref, ref_buf->buf, mi_row, mi_col, &ref_buf->sf);
av1_find_mv_refs(cm, xd, mi, frame,
}
for (ref_frame = LAST_FRAME; ref_frame < MAX_REF_FRAMES; ++ref_frame) {
av1_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], mi_row, mi_col,
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 = av1_mode_context_analyzer(inter_mode_ctx,
mbmi->ref_frame, bsize, -1);
#endif
if (segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP)) {
......@@ -625,6 +635,11 @@ static void read_inter_block_mode_info(AV1Decoder *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 = av1_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) {
......
......@@ -87,8 +87,17 @@ static void write_inter_mode(AV1_COMMON *cm,
aom_write(w, mode != ZEROMV, zeromv_prob);
if (mode != ZEROMV) {
const int16_t refmv_ctx = (mode_ctx >> REFMV_OFFSET) & REFMV_CTX_MASK;
const aom_prob refmv_prob = cm->fc->refmv_prob[refmv_ctx];
int16_t refmv_ctx = (mode_ctx >> REFMV_OFFSET) & REFMV_CTX_MASK;
aom_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];
aom_write(w, mode != NEARESTMV, refmv_prob);
}
}
......@@ -426,10 +435,8 @@ static void pack_inter_mode_mvs(AV1_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 = av1_mode_context_analyzer(mbmi_ext->mode_context,
mbmi->ref_frame, bsize, -1);
#endif
// If segment skip is not enabled code the mode.
......@@ -457,6 +464,10 @@ static void pack_inter_mode_mvs(AV1_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 = av1_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)
......
......@@ -1182,6 +1182,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];
}
}
......@@ -1230,8 +1238,8 @@ static void update_stats(AV1_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 = av1_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)];
......@@ -1245,7 +1253,8 @@ static void update_stats(AV1_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 = av1_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)];
......
......@@ -1266,6 +1266,14 @@ static int cost_mv_ref(const AV1_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;
}
......@@ -1327,7 +1335,8 @@ static int set_and_cost_bmi_mvs(AV1_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 = av1_mode_context_analyzer(mbmi_ext->mode_context,
mbmi->ref_frame, mbmi->sb_type, i);
#endif
return cost_mv_ref(cpi, mode, mode_ctx) + thismvcost;
}
......@@ -1494,14 +1503,15 @@ static int check_best_zero_mv(const AV1_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 = av1_mode_context_analyzer(mode_context,
ref_frames, bsize, block);
#else
int16_t rfc = mode_context[ref_frames[0]];
#endif
......@@ -1509,6 +1519,11 @@ static int check_best_zero_mv(const AV1_COMP *cpi,
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) {
......@@ -1773,7 +1788,7 @@ static int64_t rd_pick_best_sub8x8_mode(
if (!(inter_mode_mask & (1 << this_mode))) 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));
......@@ -2363,8 +2378,8 @@ static int64_t handle_inter_mode(
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 = av1_mode_context_analyzer(mbmi_ext->mode_context,
mbmi->ref_frame, bsize, -1);
#endif
#if CONFIG_AOM_HIGHBITDEPTH
......@@ -2925,6 +2940,7 @@ void av1_rd_pick_inter_mode_sb(AV1_COMP *cpi, TileDataEnc *tile_data,
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,
......@@ -3120,7 +3136,7 @@ void av1_rd_pick_inter_mode_sb(AV1_COMP *cpi, TileDataEnc *tile_data,
} 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))
ref_frames, bsize, -1))
continue;
}
......@@ -3617,6 +3633,7 @@ void av1_rd_pick_inter_mode_sub8x8(AV1_COMP *cpi, TileDataEnc *tile_data,
rd_cost->rate = INT_MAX;
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], yv12_mb);
......
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