Commit f40a9577 authored by Zoe Liu's avatar Zoe Liu

Add motion selection to ext_skip

A new block mode, referred to as skip_mode is added. If a block is
coded as skip_mode, it will be inter-coded, with its references and
motion vectors derived from its neighboring blocks with zero-residue.
Otherwise, the block can be coded in the current intra or inter mode.

The computational load on skip_mode evaluation at the encoder should
be kept minimum. No transform size / type evaluations are needed.

Change-Id: I5aef0159c7d5ecd64258510835903375d6c536d6
parent d915e4ee
......@@ -1415,62 +1415,9 @@ void av1_setup_frame_sign_bias(AV1_COMMON *cm) {
}
}
#endif // CONFIG_FRAME_SIGN_BIAS
#if CONFIG_EXT_SKIP
void av1_setup_skip_mode_allowed(AV1_COMMON *const cm) {
cm->is_skip_mode_allowed = 0;
cm->ref_frame_idx_0 = cm->ref_frame_idx_1 = INVALID_IDX;
if (cm->frame_type == KEY_FRAME || cm->intra_only) return;
BufferPool *const pool = cm->buffer_pool;
RefCntBuffer *const frame_bufs = pool->frame_bufs;
int ref_frame_offset_0 = -1;
int ref_frame_offset_1 = INT_MAX;
int ref_idx_0 = INVALID_IDX;
int ref_idx_1 = INVALID_IDX;
// Identify the nearest forward and backward references
for (int i = 0; i < INTER_REFS_PER_FRAME; ++i) {
RefBuffer *const ref_frame = &cm->frame_refs[i];
const int buf_idx = ref_frame->idx;
// Invalid reference frame buffer
if (buf_idx == INVALID_IDX) continue;
const int ref_offset = frame_bufs[buf_idx].cur_frame_offset;
if (ref_offset < (int)cm->frame_offset) {
// Forward reference
if (ref_offset > ref_frame_offset_0) {
ref_frame_offset_0 = ref_offset;
ref_idx_0 = i;
}
} else if (ref_offset > (int)cm->frame_offset) {
// Backward reference
if (ref_offset < ref_frame_offset_1) {
ref_frame_offset_1 = ref_offset;
ref_idx_1 = i;
}
}
}
// Flag is set when and only when both forward and backward references
// are available and their distance is no greater than 3, i.e. as
// opposed to the current frame position, the reference distance pair are
// either: (1, 1), (1, 2), or (2, 1).
if (ref_idx_0 != INVALID_IDX && ref_idx_1 != INVALID_IDX) {
if ((ref_frame_offset_1 - ref_frame_offset_0) <= 3) {
cm->is_skip_mode_allowed = 1;
cm->ref_frame_idx_0 = ref_idx_0;
cm->ref_frame_idx_1 = ref_idx_1;
}
}
}
#endif // CONFIG_EXT_SKIP
#endif // CONFIG_FRAME_MARKER
#if CONFIG_MFMV
#if CONFIG_MFMV || CONFIG_EXT_SKIP
// Although we assign 32 bit integers, all the values are strictly under 14
// bits.
static int div_mult[32] = {
......@@ -1487,7 +1434,9 @@ static void get_mv_projection(MV *output, MV ref, int num, int den) {
output->col =
(int16_t)(ROUND_POWER_OF_TWO_SIGNED(ref.col * num * div_mult[den], 14));
}
#endif // CONFIG_MFMV || CONFIG_EXT_SKIP
#if CONFIG_MFMV
#define MAX_OFFSET_WIDTH 64
#define MAX_OFFSET_HEIGHT 0
......@@ -2240,3 +2189,271 @@ int findSamples(const AV1_COMMON *cm, MACROBLOCKD *xd, int mi_row, int mi_col,
return np;
}
#endif // CONFIG_EXT_WARPED_MOTION
#if CONFIG_EXT_SKIP
void av1_setup_skip_mode_allowed(AV1_COMMON *const cm) {
cm->is_skip_mode_allowed = 0;
cm->ref_frame_idx_0 = cm->ref_frame_idx_1 = INVALID_IDX;
if (cm->frame_type == KEY_FRAME || cm->intra_only) return;
RefCntBuffer *const frame_bufs = cm->buffer_pool->frame_bufs;
const int cur_frame_offset = cm->frame_offset;
int ref_frame_offset[2] = { -1, INT_MAX };
int ref_idx[2] = { INVALID_IDX, INVALID_IDX };
int ref_buf_idx[2] = { INVALID_IDX, INVALID_IDX };
// Identify the nearest forward and backward references
for (int i = 0; i < INTER_REFS_PER_FRAME; ++i) {
const int buf_idx = cm->frame_refs[i].idx;
if (buf_idx == INVALID_IDX) continue;
const int ref_offset = frame_bufs[buf_idx].cur_frame_offset;
if (ref_offset < cur_frame_offset) {
// Forward reference
if (ref_offset > ref_frame_offset[0]) {
ref_frame_offset[0] = ref_offset;
ref_idx[0] = i;
ref_buf_idx[0] = buf_idx;
}
} else if (ref_offset > cur_frame_offset) {
// Backward reference
if (ref_offset < ref_frame_offset[1]) {
ref_frame_offset[1] = ref_offset;
ref_idx[1] = i;
ref_buf_idx[1] = buf_idx;
}
}
}
// Flag is set when and only when both forward and backward references
// are available and their distance is no greater than 3, i.e. as
// opposed to the current frame position, the reference distance pair are
// either: (1, 1), (1, 2), or (2, 1).
if (ref_idx[0] != INVALID_IDX && ref_idx[1] != INVALID_IDX) {
const int cur_to_fwd = cm->frame_offset - ref_frame_offset[0];
const int cur_to_bwd = ref_frame_offset[1] - cm->frame_offset;
#if 0
if ((ref_frame_offset[1] - ref_frame_offset[0]) <= 3)
#endif // 0
if (abs(cur_to_fwd - cur_to_bwd) <= 1) {
cm->is_skip_mode_allowed = 1;
cm->ref_frame_idx_0 = ref_idx[0];
cm->ref_frame_idx_1 = ref_idx[1];
}
}
// Set up the temporal mv candidates for skip mode.
cm->tpl_frame_ref0_idx = INVALID_IDX;
if (cm->is_skip_mode_allowed && cm->use_ref_frame_mvs) {
const int tpl_ref1_buf_idx = ref_buf_idx[1];
const int tpl_ref1_ref_offsets[INTER_REFS_PER_FRAME] = {
frame_bufs[tpl_ref1_buf_idx].lst_frame_offset,
frame_bufs[tpl_ref1_buf_idx].lst2_frame_offset,
frame_bufs[tpl_ref1_buf_idx].lst3_frame_offset,
frame_bufs[tpl_ref1_buf_idx].gld_frame_offset,
frame_bufs[tpl_ref1_buf_idx].bwd_frame_offset,
frame_bufs[tpl_ref1_buf_idx].alt2_frame_offset,
frame_bufs[tpl_ref1_buf_idx].alt_frame_offset
};
for (int i = 0; i < INTER_REFS_PER_FRAME; ++i) {
if (tpl_ref1_ref_offsets[i] == ref_frame_offset[0]) {
cm->tpl_frame_ref0_idx = i;
break;
}
}
}
}
// Identify mvs for skip mode in the following order:
// (1) Search the spatial two neighboring blocks (left/top);
// (2) Search the temporal neighboring blocks;
// (3) Consider NEAREST_NEARESTMV.
#define SKIP_MODE_MV_LISTS 3
#define SPATIAL_CANDIDATES 2
#define TEMPORAL_CANDIDATES 2
#define TOTAL_CANDIDATES (SPATIAL_CANDIDATES + TEMPORAL_CANDIDATES)
void av1_setup_skip_mode_mvs(const AV1_COMMON *cm, const MACROBLOCKD *xd,
MB_MODE_INFO *mbmi, int mi_row, int mi_col,
const int_mv nearest_mv[2], find_mv_refs_sync sync,
void *const data) {
#if 0
const int sb_mi_size = mi_size_wide[cm->sb_size];
#endif // 0
const TileInfo *const tile = &xd->tile;
int i;
const MV_REFERENCE_FRAME skip_mode_refs[2] = {
LAST_FRAME + cm->ref_frame_idx_0, LAST_FRAME + cm->ref_frame_idx_1
};
const int8_t ref_frame_types[SKIP_MODE_MV_LISTS] = {
skip_mode_refs[0], skip_mode_refs[1], av1_ref_frame_type(skip_mode_refs)
};
int_mv mv_list[SKIP_MODE_MV_LISTS][TOTAL_CANDIDATES][2];
int mv_list_count[SKIP_MODE_MV_LISTS] = { 0 };
const BLOCK_SIZE bsize = mbmi->sb_type;
const int bw = block_size_wide[AOMMAX(bsize, BLOCK_8X8)];
const int bh = block_size_high[AOMMAX(bsize, BLOCK_8X8)];
const int num_8x8_blocks_wide = num_8x8_blocks_wide_lookup[bsize];
const int num_8x8_blocks_high = num_8x8_blocks_high_lookup[bsize];
// === Search mv candidate(s) over spatial neighboring blocks.
POSITION mv_search_pos_cur[SPATIAL_CANDIDATES];
mv_search_pos_cur[0].row = num_8x8_blocks_high - 1; // LEFT
mv_search_pos_cur[0].col = -1;
mv_search_pos_cur[1].row = -1; // TOP
mv_search_pos_cur[1].col = num_8x8_blocks_wide - 1;
MB_MODE_INFO *candidate_mbmi[SPATIAL_CANDIDATES] = { NULL };
for (i = 0; i < SPATIAL_CANDIDATES; ++i) {
const POSITION *const mv_pos = &mv_search_pos_cur[i];
if (is_inside(tile, mi_col, mi_row, cm->mi_rows, cm, mv_pos)) {
candidate_mbmi[i] =
!xd->mi[mv_pos->col + mv_pos->row * xd->mi_stride]
? NULL
: &(xd->mi[mv_pos->col + mv_pos->row * xd->mi_stride]->mbmi);
#if 0
if (candidate_mbmi[i] == NULL) continue;
// TODO(zoeliu): To investigate whether following sanity check is needed.
if ((mi_row & (sb_mi_size - 1)) + mv_pos->row >= sb_mi_size ||
(mi_col & (sb_mi_size - 1)) + mv_pos->col >= sb_mi_size)
continue;
#endif // 0
}
}
// First scan on the spatial neighbors, considering both reference frames
// matched for compound mode.
for (i = 0; i < SPATIAL_CANDIDATES; ++i) {
if (candidate_mbmi[i]) {
if (has_second_ref(candidate_mbmi[i])) { // comp
if (av1_ref_frame_type(candidate_mbmi[i]->ref_frame) ==
ref_frame_types[2])
SKIP_MODE_MV_LIST_ADD(candidate_mbmi[i]->mv, mv_list, mv_list_count,
2, bw, bh, xd);
} else { // single
if (candidate_mbmi[i]->ref_frame[0] == ref_frame_types[0])
SKIP_MODE_MV_LIST_ADD(candidate_mbmi[i]->mv, mv_list, mv_list_count,
0, bw, bh, xd);
else if (candidate_mbmi[i]->ref_frame[0] == ref_frame_types[1])
SKIP_MODE_MV_LIST_ADD(candidate_mbmi[i]->mv, mv_list, mv_list_count,
1, bw, bh, xd);
}
}
}
// Re-scan mv candidate(s) over spatial neighboring blocks of compound mode,
// with only one reference frame matching the skip mode.
for (i = 0; i < SPATIAL_CANDIDATES; ++i) {
if (candidate_mbmi[i] && has_second_ref(candidate_mbmi[i])) { // comp
if (candidate_mbmi[i]->ref_frame[0] == ref_frame_types[0] ||
candidate_mbmi[i]->ref_frame[1] == ref_frame_types[1]) {
const int rf_idx =
(candidate_mbmi[i]->ref_frame[1] == ref_frame_types[1]);
const int_mv rf_mv[2] = { candidate_mbmi[i]->mv[rf_idx],
candidate_mbmi[i]->mv[1 - rf_idx] };
SKIP_MODE_MV_LIST_ADD(rf_mv, mv_list, mv_list_count, rf_idx, bw, bh,
xd);
}
}
}
// TODO(hkuang): Remove this sync after fixing pthread_cond_broadcast
// on windows platform. The sync here is unncessary if use_perv_frame_mvs
// is 0. But after removing it, there will be hang in the unit test on windows
// due to several threads waiting for a thread's signal.
#if defined(_WIN32) && !HAVE_PTHREAD_H
if (cm->frame_parallel_decode && sync != NULL) sync(data, mi_row);
#endif
// === Search mv candidate(s) over temporal neighboring blocks.
if (cm->tpl_frame_ref0_idx != INVALID_IDX) {
// Synchronize here for frame parallel decode if sync function is provided.
if (cm->frame_parallel_decode && sync != NULL) {
sync(data, mi_row);
}
POSITION mv_search_pos_tpl[TEMPORAL_CANDIDATES];
mv_search_pos_tpl[0].row = num_8x8_blocks_high - 1; // current
mv_search_pos_tpl[0].col = num_8x8_blocks_wide - 1;
mv_search_pos_tpl[1].row = num_8x8_blocks_high; // bottom-right
mv_search_pos_tpl[1].col = num_8x8_blocks_wide;
const int mvs_rows = (cm->mi_rows + 1) >> 1;
const int mvs_cols = (cm->mi_cols + 1) >> 1;
RefCntBuffer *const frame_bufs = cm->buffer_pool->frame_bufs;
const int tpl_ref0_buf_idx = cm->frame_refs[cm->ref_frame_idx_0].idx;
const int tpl_ref0_offset = frame_bufs[tpl_ref0_buf_idx].cur_frame_offset;
const int tpl_ref1_buf_idx = cm->frame_refs[cm->ref_frame_idx_1].idx;
const int tpl_ref1_offset = frame_bufs[tpl_ref1_buf_idx].cur_frame_offset;
MV_REF *const tpl_mvs_base = frame_bufs[tpl_ref1_buf_idx].mvs;
for (i = 0; i < TEMPORAL_CANDIDATES; ++i) {
const POSITION *const mv_pos = &mv_search_pos_tpl[i];
const int tpl_mvs_row = (mi_row + mv_pos->row + 1) >> 1;
const int tpl_mvs_col = (mi_col + mv_pos->col + 1) >> 1;
if (tpl_mvs_row >= 0 && tpl_mvs_row < mvs_rows && tpl_mvs_col >= 0 &&
tpl_mvs_col < mvs_cols) {
MV_REF *mv_ref = &tpl_mvs_base[tpl_mvs_row * mvs_cols + tpl_mvs_col];
MV_REFERENCE_FRAME tpl_frame_rf[2] = { mv_ref->ref_frame[0],
mv_ref->ref_frame[1] };
// Check whether the temporal candidate block has its reference frame 0
// point to the same forward reference most recent to the current frame.
if (tpl_frame_rf[0] <= INTRA_FRAME ||
FWD_RF_OFFSET(tpl_frame_rf[0]) != cm->tpl_frame_ref0_idx)
continue;
// Scale the temporal candiate mv of the same forward reference frame
// for the current frame.
const int cur_to_ref0 = AOMMAX(1, cm->frame_offset - tpl_ref0_offset);
const int ref1_to_ref0 = AOMMAX(1, tpl_ref1_offset - tpl_ref0_offset);
MV tpl_frame_mv[2] = { mv_ref->mv[0].as_mv, mv_ref->mv[1].as_mv };
int_mv candidate_mv;
get_mv_projection(&candidate_mv.as_mv, tpl_frame_mv[0], cur_to_ref0,
ref1_to_ref0);
const int_mv tpl_mv[2] = { candidate_mv, mv_ref->mv[1] };
SKIP_MODE_MV_LIST_ADD(tpl_mv, mv_list, mv_list_count, 0, bw, bh, xd);
}
}
}
// === Finalize the mv/ref selection for the current block of skip mode.
// TODO(zoeliu): Several items to consider for possibly improving the coding
// performance further:
// (1) Consider more spatial / temporal neighboring blocks;
// (2) Signal the selection to differentiate between single or compoud mode;
// (3) May allow the use of the most recent forward reference of the temporal
// neighboring block.
if (mv_list_count[2] > 0) { // comp
mbmi->ref_frame[0] = cm->ref_frame_idx_0 + LAST_FRAME;
mbmi->ref_frame[1] = cm->ref_frame_idx_1 + LAST_FRAME;
mbmi->mv[0].as_int = mv_list[2][0][0].as_int;
mbmi->mv[1].as_int = mv_list[2][0][1].as_int;
} else if (mv_list_count[0] > 0) { // single - forward
mbmi->ref_frame[0] = cm->ref_frame_idx_0 + LAST_FRAME;
mbmi->ref_frame[1] = -1;
mbmi->mv[0].as_int = mv_list[0][0][0].as_int;
} else if (mv_list_count[1] > 0) { // single - backward
mbmi->ref_frame[0] = cm->ref_frame_idx_1 + LAST_FRAME;
mbmi->ref_frame[1] = -1;
mbmi->mv[0].as_int = mv_list[1][0][0].as_int;
} else {
mbmi->ref_frame[0] = cm->ref_frame_idx_0 + LAST_FRAME;
mbmi->ref_frame[1] = cm->ref_frame_idx_1 + LAST_FRAME;
mbmi->mv[0].as_int = nearest_mv[0].as_int;
mbmi->mv[1].as_int = nearest_mv[1].as_int;
}
}
#endif // CONFIG_EXT_SKIP
......@@ -174,6 +174,22 @@ static INLINE int_mv scale_mv(const MB_MODE_INFO *mbmi, int ref,
} \
} while (0)
#if CONFIG_EXT_SKIP
// This macro is used to add a motion vector pair to the skip mode mv list.
#define SKIP_MODE_MV_LIST_ADD(mv, mv_list, mv_list_count, mv_list_idx, bw, bh, \
xd) \
do { \
const int mv_idx = (mv_list_count)[mv_list_idx]; \
(mv_list)[mv_list_idx][mv_idx][0] = (mv)[0]; \
CLIP_IN_ADD(&(mv_list)[mv_list_idx][mv_idx][0].as_mv, (bw), (bh), (xd)); \
if (mv_list_idx == 2) { \
(mv_list)[mv_list_idx][mv_idx][1] = (mv)[1]; \
CLIP_IN_ADD(&(mv_list)[mv_list_idx][mv_idx][1].as_mv, (bw), (bh), (xd)); \
} \
(mv_list_count)[mv_list_idx]++; \
} while (0)
#endif // CONFIG_EXT_SKIP
// Checks that the given mi_row, mi_col and search point
// are inside the borders of the tile.
static INLINE int is_inside(const TileInfo *const tile, int mi_col, int mi_row,
......@@ -389,6 +405,12 @@ void av1_find_mv_refs(const AV1_COMMON *cm, const MACROBLOCKD *xd,
int16_t *compound_mode_context, int_mv *mv_ref_list,
int mi_row, int mi_col, find_mv_refs_sync sync,
void *const data, int16_t *mode_context);
#if CONFIG_EXT_SKIP
void av1_setup_skip_mode_mvs(const AV1_COMMON *cm, const MACROBLOCKD *xd,
MB_MODE_INFO *mbmi, int mi_row, int mi_col,
const int_mv nearest_mv[2], find_mv_refs_sync sync,
void *const data);
#endif // CONFIG_EXT_SKIP
// 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
......
......@@ -271,8 +271,10 @@ typedef struct AV1Common {
RefBuffer frame_refs[INTER_REFS_PER_FRAME];
#if CONFIG_EXT_SKIP
int is_skip_mode_allowed;
int skip_mode_flag;
int ref_frame_idx_0;
int ref_frame_idx_1;
int tpl_frame_ref0_idx;
#endif // CONFIG_EXT_SKIP
int new_fb_idx;
......
......@@ -448,10 +448,10 @@ static INLINE void set_default_interp_filters(
static INLINE int av1_is_interp_needed(const MACROBLOCKD *const xd) {
(void)xd;
const MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
if (mbmi->motion_mode == WARPED_CAUSAL) return 0;
#if CONFIG_EXT_SKIP
if (mbmi->skip_mode) return 0;
#endif // CONFIG_EXT_SKIP
if (mbmi->motion_mode == WARPED_CAUSAL) return 0;
if (is_nontrans_global_motion(xd)) return 0;
return 1;
}
......
......@@ -3008,6 +3008,22 @@ static size_t read_uncompressed_header(AV1Decoder *pbi,
}
av1_setup_frame_buf_refs(cm);
#if CONFIG_EXT_SKIP
av1_setup_skip_mode_allowed(cm);
cm->skip_mode_flag = cm->is_skip_mode_allowed ? aom_rb_read_bit(rb) : 0;
#if 0
printf(
"DECODER: Frame=%d, frame_offset=%d, show_frame=%d, "
"show_existing_frame=%d, is_skip_mode_allowed=%d, "
"ref_frame_idx=(%d,%d), frame_reference_mode=%d, "
"tpl_frame_ref0_idx=%d, skip_mode_flag=%d\n\n",
cm->current_video_frame, cm->frame_offset, cm->show_frame,
cm->show_existing_frame, cm->is_skip_mode_allowed, cm->ref_frame_idx_0,
cm->ref_frame_idx_1, cm->reference_mode, cm->tpl_frame_ref0_idx,
cm->skip_mode_flag);
#endif // 0
#endif // CONFIG_EXT_SKIP
#if CONFIG_FRAME_SIGN_BIAS
#if CONFIG_OBU
if (cm->frame_type != S_FRAME)
......@@ -3516,16 +3532,6 @@ size_t av1_decode_frame_headers_and_setup(AV1Decoder *pbi, const uint8_t *data,
(cm->last_frame_type != KEY_FRAME);
#endif // CONFIG_TEMPMV_SIGNALING
#if CONFIG_EXT_SKIP
av1_setup_skip_mode_allowed(cm);
#if 0
printf("\nDECODER: Frame=%d, frame_offset=%d, show_frame=%d, "
"is_skip_mode_allowed=%d, ref_frame_idx=(%d,%d)\n",
cm->current_video_frame, cm->frame_offset, cm->show_frame,
cm->is_skip_mode_allowed, cm->ref_frame_idx_0, cm->ref_frame_idx_1);
#endif // 0
#endif // CONFIG_EXT_SKIP
#if CONFIG_MFMV
av1_setup_motion_field(cm);
#endif // CONFIG_MFMV
......
......@@ -254,6 +254,10 @@ static MOTION_MODE read_motion_mode(AV1_COMMON *cm, MACROBLOCKD *xd,
MB_MODE_INFO *mbmi = &mi->mbmi;
(void)cm;
#if CONFIG_EXT_SKIP
if (mbmi->skip_mode) return SIMPLE_TRANSLATION;
#endif // CONFIG_EXT_SKIP
const MOTION_MODE last_motion_mode_allowed =
motion_mode_allowed(0, xd->global_motion, xd, mi);
int motion_mode;
......@@ -278,22 +282,9 @@ static MOTION_MODE read_motion_mode(AV1_COMMON *cm, MACROBLOCKD *xd,
static PREDICTION_MODE read_inter_compound_mode(AV1_COMMON *cm, MACROBLOCKD *xd,
aom_reader *r, int16_t ctx) {
(void)cm;
#if CONFIG_EXT_SKIP
FRAME_CONTEXT *const ec_ctx = xd->tile_ctx;
const int mode =
xd->mi[0]->mbmi.skip_mode
? (NEAREST_NEARESTMV - NEAREST_NEARESTMV)
: aom_read_symbol(r, ec_ctx->inter_compound_mode_cdf[ctx],
INTER_COMPOUND_MODES, ACCT_STR);
if (xd->mi[0]->mbmi.skip_mode && r->allow_update_cdf)
update_cdf(ec_ctx->inter_compound_mode_cdf[ctx], mode,
INTER_COMPOUND_MODES);
#else
const int mode =
aom_read_symbol(r, xd->tile_ctx->inter_compound_mode_cdf[ctx],
INTER_COMPOUND_MODES, ACCT_STR);
#endif // CONFIG_EXT_SKIP
FRAME_COUNTS *counts = xd->counts;
if (counts) ++counts->inter_compound_mode[ctx][mode];
assert(is_inter_compound_mode(NEAREST_NEARESTMV + mode));
......@@ -602,23 +593,23 @@ static int read_inter_segment_id(AV1_COMMON *const cm, MACROBLOCKD *const xd,
#if CONFIG_EXT_SKIP
static int read_skip_mode(AV1_COMMON *cm, const MACROBLOCKD *xd, int segment_id,
aom_reader *r) {
if (!cm->is_skip_mode_allowed) return 0;
if (!cm->skip_mode_flag) return 0;
if (segfeature_active(&cm->seg, segment_id, SEG_LVL_SKIP)) {
// TODO(zoeliu): To revisit the handling of this scenario.
return 0;
} else {
const int ctx = av1_get_skip_mode_context(xd);
FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
const int skip_mode =
aom_read_symbol(r, ec_ctx->skip_mode_cdfs[ctx], 2, ACCT_STR);
FRAME_COUNTS *counts = xd->counts;
if (counts) ++counts->skip_mode[ctx][skip_mode];
// TODO(zoeliu): To handle:
// if (!is_comp_ref_allowed(xd->mi[0]->mbmi.sb_type))
return skip_mode;
}
if (!is_comp_ref_allowed(xd->mi[0]->mbmi.sb_type)) return 0;
const int ctx = av1_get_skip_mode_context(xd);
FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
const int skip_mode =
aom_read_symbol(r, ec_ctx->skip_mode_cdfs[ctx], 2, ACCT_STR);
FRAME_COUNTS *counts = xd->counts;
if (counts) ++counts->skip_mode[ctx][skip_mode];
return skip_mode;
}
#endif // CONFIG_EXT_SKIP
......@@ -1258,21 +1249,6 @@ static REFERENCE_MODE read_block_reference_mode(AV1_COMMON *cm,
}
}
#if CONFIG_EXT_SKIP
static void update_block_reference_mode(AV1_COMMON *cm, const MACROBLOCKD *xd,
REFERENCE_MODE mode,
uint8_t allow_update_cdf) {
if (cm->reference_mode == REFERENCE_MODE_SELECT) {
assert(mode == SINGLE_REFERENCE || mode == COMPOUND_REFERENCE);
const int ctx = av1_get_reference_mode_context(cm, xd);
if (allow_update_cdf)
update_cdf(xd->tile_ctx->comp_inter_cdf[ctx], mode, 2);
FRAME_COUNTS *counts = xd->counts;
if (counts) ++counts->comp_inter[ctx][mode];
}
}
#endif // CONFIG_EXT_SKIP
#define READ_REF_BIT(pname) \
aom_read_symbol(r, av1_get_pred_cdf_##pname(cm, xd), 2, ACCT_STR)
#define READ_REF_BIT2(pname) \
......@@ -1294,60 +1270,10 @@ static COMP_REFERENCE_TYPE read_comp_reference_type(AV1_COMMON *cm,
#endif // CONFIG_EXT_COMP_REFS
#if CONFIG_EXT_SKIP
#if CONFIG_EXT_COMP_REFS
static void update_comp_reference_type(AV1_COMMON *cm, const MACROBLOCKD *xd,
COMP_REFERENCE_TYPE comp_ref_type,
uint8_t allow_update_cdf) {
assert(comp_ref_type == UNIDIR_COMP_REFERENCE ||
comp_ref_type == BIDIR_COMP_REFERENCE);
(void)cm;
const int ctx = av1_get_comp_reference_type_context(xd);
if (allow_update_cdf)
update_cdf(xd->tile_ctx->comp_ref_type_cdf[ctx], comp_ref_type, 2);
FRAME_COUNTS *counts = xd->counts;
if (counts) ++counts->comp_ref_type[ctx][comp_ref_type];
}
#endif // CONFIG_EXT_COMP_REFS
static void set_ref_frames_for_skip_mode(AV1_COMMON *const cm,
MACROBLOCKD *const xd,
MV_REFERENCE_FRAME ref_frame[2],
uint8_t allow_update_cdf) {
assert(xd->mi[0]->mbmi.skip_mode);
MV_REFERENCE_FRAME ref_frame[2]) {
ref_frame[0] = LAST_FRAME + cm->ref_frame_idx_0;
ref_frame[1] = LAST_FRAME + cm->ref_frame_idx_1;
const REFERENCE_MODE mode = COMPOUND_REFERENCE;
update_block_reference_mode(cm, xd, mode, allow_update_cdf);
#if CONFIG_EXT_COMP_REFS
const COMP_REFERENCE_TYPE comp_ref_type = BIDIR_COMP_REFERENCE;
update_comp_reference_type(cm, xd, comp_ref_type, allow_update_cdf);
#endif // CONFIG_EXT_COMP_REFS
// Update stats for both forward and backward references
#define UPDATE_REF_BIT(bname, pname, cname, iname) \
if (allow_update_cdf) \
update_cdf(av1_get_pred_cdf_##pname(cm, xd), bname, 2); \
if (counts) \
++counts->comp_##cname[av1_get_pred_context_##pname(cm, xd)][iname][bname];
FRAME_COUNTS *counts = xd->counts;
const int bit = (ref_frame[0] == GOLDEN_FRAME || ref_frame[0] == LAST3_FRAME);
UPDATE_REF_BIT(bit, comp_ref_p, ref, 0)
if (!bit) {
UPDATE_REF_BIT(ref_frame[0] == LAST_FRAME, comp_ref_p1, ref, 1)
} else {
UPDATE_REF_BIT(ref_frame[0] == GOLDEN_FRAME, comp_ref_p2, ref, 2)
}
const int bit_bwd = ref_frame[1] == ALTREF_FRAME;
UPDATE_REF_BIT(bit_bwd, comp_bwdref_p, bwdref, 0)
if (!bit_bwd) {
UPDATE_REF_BIT(ref_frame[1] == ALTREF2_FRAME, comp_bwdref_p1, bwdref, 1)
}
}
#endif // CONFIG_EXT_SKIP
......@@ -1374,7 +1300,7 @@ static void read_ref_frames(AV1_COMMON *const cm, MACROBLOCKD *const xd,