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
This diff is collapsed.
......@@ -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
......
This diff is collapsed.
......@@ -282,6 +282,24 @@ static int write_skip(const AV1_COMMON *cm, const MACROBLOCKD *xd,
}
}
#if CONFIG_EXT_SKIP
static int write_skip_mode(const AV1_COMMON *cm, const MACROBLOCKD *xd,
int segment_id, const MODE_INFO *mi, aom_writer *w) {
if (!cm->skip_mode_flag) return 0;
if (segfeature_active(&cm->seg, segment_id, SEG_LVL_SKIP)) {
return 0;
}
const int skip_mode = mi->mbmi.skip_mode;
if (!is_comp_ref_allowed(mi->mbmi.sb_type)) {
assert(!skip_mode);
return 0;
}
const int ctx = av1_get_skip_mode_context(xd);
aom_write_symbol(w, skip_mode, xd->tile_ctx->skip_mode_cdfs[ctx], 2);
return skip_mode;
}
#endif // CONFIG_EXT_SKIP
static void write_is_inter(const AV1_COMMON *cm, const MACROBLOCKD *xd,
int segment_id, aom_writer *w, const int is_inter) {
if (!segfeature_active(&cm->seg, segment_id, SEG_LVL_REF_FRAME)) {
......@@ -1207,10 +1225,23 @@ static void pack_inter_mode_mvs(AV1_COMP *cpi, const int mi_row,
}
}
skip = write_skip(cm, xd, segment_id, mi, w);
#if CONFIG_EXT_SKIP
write_skip_mode(cm, xd, segment_id, mi, w);
if (mbmi->skip_mode) {
skip = mbmi->skip;
assert(skip);
} else {
#endif // CONFIG_EXT_SKIP
skip = write_skip(cm, xd, segment_id, mi, w);
#if CONFIG_EXT_SKIP
}
#endif // CONFIG_EXT_SKIP
#if CONFIG_Q_SEGMENTATION
write_q_segment_id(cm, skip, mbmi, w, seg, segp, bsize, mi_row, mi_col);
#endif
#endif // CONFIG_Q_SEGMENTATION
if (cm->delta_q_present_flag) {
int super_block_upper_left = ((mi_row & (cm->mib_size - 1)) == 0) &&
((mi_col & (cm->mib_size - 1)) == 0);
......@@ -1252,7 +1283,10 @@ static void pack_inter_mode_mvs(AV1_COMP *cpi, const int mi_row,
}
}
write_is_inter(cm, xd, mbmi->segment_id, w, is_inter);
#if CONFIG_EXT_SKIP
if (!mbmi->skip_mode)
#endif // CONFIG_EXT_SKIP
write_is_inter(cm, xd, mbmi->segment_id, w, is_inter);
if (cm->tx_mode == TX_MODE_SELECT && block_signals_txsize(bsize) &&
!(is_inter && skip) && !xd->lossless[segment_id]) {
......@@ -1274,6 +1308,10 @@ static void pack_inter_mode_mvs(AV1_COMP *cpi, const int mi_row,
set_txfm_ctxs(mbmi->tx_size, xd->n8_w, xd->n8_h, skip, xd);
}
#if CONFIG_EXT_SKIP
if (mbmi->skip_mode) return;
#endif // CONFIG_EXT_SKIP
if (!is_inter) {
write_intra_mode(ec_ctx, bsize, mode, w);
if (is_chroma_reference(mi_row, mi_col, bsize, xd->plane[1].subsampling_x,
......@@ -1310,7 +1348,6 @@ static void pack_inter_mode_mvs(AV1_COMP *cpi, const int mi_row,
if (is_compound)
mode_ctx = mbmi_ext->compound_mode_context[mbmi->ref_frame[0]];
else
mode_ctx = av1_mode_context_analyzer(mbmi_ext->mode_context,
mbmi->ref_frame, bsize, -1);
......@@ -1607,7 +1644,7 @@ static void enc_dump_logs(AV1_COMP *cpi, int mi_row, int mi_col) {
xd->mi = cm->mi_grid_visible + (mi_row * cm->mi_stride + mi_col);
m = xd->mi[0];
if (is_inter_block(&m->mbmi)) {
#define FRAME_TO_CHECK 1
#define FRAME_TO_CHECK 11
if (cm->current_video_frame == FRAME_TO_CHECK && cm->show_frame == 1) {
const MB_MODE_INFO *const mbmi = &m->mbmi;
const BLOCK_SIZE bsize = mbmi->sb_type;
......@@ -1625,11 +1662,15 @@ static void enc_dump_logs(AV1_COMP *cpi, int mi_row, int mi_col) {
MACROBLOCK *const x = &cpi->td.mb;
const MB_MODE_INFO_EXT *const mbmi_ext = x->mbmi_ext;
const int16_t mode_ctx = av1_mode_context_analyzer(
mbmi_ext->mode_context, mbmi->ref_frame, bsize, -1);
const int16_t mode_ctx =
is_comp_ref ? mbmi_ext->compound_mode_context[mbmi->ref_frame[0]]
: av1_mode_context_analyzer(mbmi_ext->mode_context,
mbmi->ref_frame, bsize, -1);
const int16_t newmv_ctx = mode_ctx & NEWMV_CTX_MASK;
int16_t zeromv_ctx = -1;
int16_t refmv_ctx = -1;
if (mbmi->mode != NEWMV) {
zeromv_ctx = (mode_ctx >> GLOBALMV_OFFSET) & GLOBALMV_CTX_MASK;
if (mode_ctx & (1 << ALL_ZERO_FLAG_OFFSET)) {
......@@ -1643,18 +1684,31 @@ static void enc_dump_logs(AV1_COMP *cpi, int mi_row, int mi_col) {
}
}
int8_t ref_frame_type = av1_ref_frame_type(mbmi->ref_frame);
#if CONFIG_EXT_SKIP
printf(
"=== ENCODER ===: "
"Frame=%d, (mi_row,mi_col)=(%d,%d), skip_mode=%d, mode=%d, bsize=%d, "
"show_frame=%d, mv[0]=(%d,%d), mv[1]=(%d,%d), ref[0]=%d, "
"ref[1]=%d, motion_mode=%d, mode_ctx=%d, "
"newmv_ctx=%d, zeromv_ctx=%d, refmv_ctx=%d, tx_size=%d\n",
cm->current_video_frame, mi_row, mi_col, mbmi->skip_mode, mbmi->mode,
bsize, cm->show_frame, mv[0].as_mv.row, mv[0].as_mv.col,
mv[1].as_mv.row, mv[1].as_mv.col, mbmi->ref_frame[0],
mbmi->ref_frame[1], mbmi->motion_mode, mode_ctx, newmv_ctx,
zeromv_ctx, refmv_ctx, mbmi->tx_size);
#else
printf(
"=== ENCODER ===: "
"Frame=%d, (mi_row,mi_col)=(%d,%d), mode=%d, bsize=%d, "
"show_frame=%d, mv[0]=(%d,%d), mv[1]=(%d,%d), ref[0]=%d, "
"ref[1]=%d, motion_mode=%d, inter_mode_ctx=%d, mode_ctx=%d, "
"newmv_ctx=%d, zeromv_ctx=%d, refmv_ctx=%d\n",
"ref[1]=%d, motion_mode=%d, mode_ctx=%d, "
"newmv_ctx=%d, zeromv_ctx=%d, refmv_ctx=%d, tx_size=%d\n",
cm->current_video_frame, mi_row, mi_col, mbmi->mode, bsize,
cm->show_frame, mv[0].as_mv.row, mv[0].as_mv.col, mv[1].as_mv.row,
mv[1].as_mv.col, mbmi->ref_frame[0], mbmi->ref_frame[1],
mbmi->motion_mode, mbmi_ext->mode_context[ref_frame_type], mode_ctx,
newmv_ctx, zeromv_ctx, refmv_ctx);
mbmi->motion_mode, mode_ctx, newmv_ctx, zeromv_ctx, refmv_ctx,
mbmi->tx_size);
#endif // CONFIG_EXT_SKIP
}
}
}
......@@ -1750,6 +1804,9 @@ static void write_tokens_b(AV1_COMP *cpi, const TileInfo *const tile,
for (plane = 0; plane < AOMMIN(2, num_planes); ++plane) {
const uint8_t palette_size_plane =
mbmi->palette_mode_info.palette_size[plane];
#if CONFIG_EXT_SKIP
assert(!mbmi->skip_mode || !palette_size_plane);
#endif // CONFIG_EXT_SKIP
if (palette_size_plane > 0) {
#if CONFIG_INTRABC
assert(mbmi->use_intrabc == 0);
......@@ -3669,8 +3726,6 @@ static void write_uncompressed_header_frame(AV1_COMP *cpi,
aom_wb_write_literal(wb, cpi->common.ans_window_size_log2 - 8, 4);
#endif // CONFIG_ANS && ANS_MAX_SYMBOLS
} else {
MV_REFERENCE_FRAME ref_frame;
aom_wb_write_literal(wb, cpi->refresh_frame_mask, REF_FRAMES);
if (!cpi->refresh_frame_mask) {
......@@ -3679,7 +3734,8 @@ static void write_uncompressed_header_frame(AV1_COMP *cpi,
cm->is_reference_frame = 0;
}
for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
for (MV_REFERENCE_FRAME ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME;
++ref_frame) {
assert(get_ref_frame_map_idx(cpi, ref_frame) != INVALID_IDX);
aom_wb_write_literal(wb, get_ref_frame_map_idx(cpi, ref_frame),
REF_FRAMES_LOG2);
......@@ -3750,7 +3806,11 @@ static void write_uncompressed_header_frame(AV1_COMP *cpi,
arf_offset = AOMMIN((MAX_GF_INTERVAL - 1), arf_offset + brf_offset);
aom_wb_write_literal(wb, arf_offset, 4);
}
#endif
#if CONFIG_EXT_SKIP
if (cm->is_skip_mode_allowed) aom_wb_write_bit(wb, cm->skip_mode_flag);
#endif // CONFIG_EXT_SKIP
#endif // CONFIG_FRAME_MARKER
#if CONFIG_REFERENCE_BUFFER
if (cm->seq_params.frame_id_numbers_present_flag) {
......
......@@ -207,6 +207,20 @@ struct macroblock {
int skip_chroma_rd;
int skip_cost[SKIP_CONTEXTS][2];
#if CONFIG_EXT_SKIP
int skip_mode; // 0: off; 1: on
int skip_mode_cost[SKIP_CONTEXTS][2];
int64_t skip_mode_rdcost; // -1: Not set
int skip_mode_rate;
int64_t skip_mode_sse;
int64_t skip_mode_dist;
MV_REFERENCE_FRAME skip_mode_ref_frame[2];
int_mv skip_mode_mv[2];
int skip_mode_index_candidate;
int skip_mode_index;
#endif // CONFIG_EXT_SKIP
#if CONFIG_LV_MAP
LV_MAP_COEFF_COST coeff_costs[TX_SIZES][PLANE_TYPES];
uint16_t cb_offset;
......
......@@ -1020,11 +1020,24 @@ static void update_stats(const AV1_COMMON *const cm, TileDataEnc *tile_data,
const int seg_ref_active =
segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_REF_FRAME);
if (!seg_ref_active) {
const int skip_ctx = av1_get_skip_context(xd);
td->counts->skip[skip_ctx][mbmi->skip]++;
if (allow_update_cdf) update_cdf(fc->skip_cdfs[skip_ctx], mbmi->skip, 2);
#if CONFIG_EXT_SKIP
if (cm->skip_mode_flag && !seg_ref_active && is_comp_ref_allowed(bsize)) {
const int skip_mode_ctx = av1_get_skip_mode_context(xd);
td->counts->skip_mode[skip_mode_ctx][mbmi->skip_mode]++;
if (allow_update_cdf)
update_cdf(fc->skip_mode_cdfs[skip_mode_ctx], mbmi->skip_mode, 2);
}
if (!mbmi->skip_mode) {
#endif // CONFIG_EXT_SKIP
if (!seg_ref_active) {
const int skip_ctx = av1_get_skip_context(xd);
td->counts->skip[skip_ctx][mbmi->skip]++;
if (allow_update_cdf) update_cdf(fc->skip_cdfs[skip_ctx], mbmi->skip, 2);
}
#if CONFIG_EXT_SKIP
}
#endif // CONFIG_EXT_SKIP
if (cm->delta_q_present_flag && (bsize != cm->sb_size || !mbmi->skip) &&
super_block_upper_left) {
......@@ -1080,10 +1093,24 @@ static void update_stats(const AV1_COMMON *const cm, TileDataEnc *tile_data,
#endif // CONFIG_LOOPFILTER_LEVEL
#endif
}
if (!frame_is_intra_only(cm)) {
FRAME_COUNTS *const counts = td->counts;
RD_COUNTS *rdc = &td->rd_counts;
#if CONFIG_EXT_SKIP
if (mbmi->skip_mode) {
if (cm->reference_mode == REFERENCE_MODE_SELECT) {
assert(has_second_ref(mbmi));
rdc->compound_ref_used_flag = 1;
}
set_ref_ptrs(cm, xd, mbmi->ref_frame[0], mbmi->ref_frame[1]);
return;
}
#endif // CONFIG_EXT_SKIP
FRAME_COUNTS *const counts = td->counts;
const int inter_block = is_inter_block(mbmi);
if (!seg_ref_active) {
counts->intra_inter[av1_get_intra_inter_context(xd)][inter_block]++;
if (allow_update_cdf)
......@@ -4194,6 +4221,41 @@ static void encode_frame_internal(AV1_COMP *cpi) {
av1_setup_motion_field(cm);
#endif // CONFIG_MFMV
#if CONFIG_EXT_SKIP
av1_setup_skip_mode_allowed(cm);
cm->skip_mode_flag = cm->is_skip_mode_allowed;
if (cm->skip_mode_flag) {
if (cm->reference_mode == SINGLE_REFERENCE) {
cm->skip_mode_flag = 0;
} else {
static const int flag_list[TOTAL_REFS_PER_FRAME] = { 0,
AOM_LAST_FLAG,
AOM_LAST2_FLAG,
AOM_LAST3_FLAG,
AOM_GOLD_FLAG,
AOM_BWD_FLAG,
AOM_ALT2_FLAG,
AOM_ALT_FLAG };
const int ref_frame[2] = { cm->ref_frame_idx_0 + LAST_FRAME,
cm->ref_frame_idx_1 + LAST_FRAME };
if (!(cpi->ref_frame_flags & flag_list[ref_frame[0]]) ||
!(cpi->ref_frame_flags & flag_list[ref_frame[1]]))
cm->skip_mode_flag = 0;
}
}
#if 0
printf(
"\nENCODER: 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",
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_MARKER
cpi->all_one_sided_refs = refs_are_one_sided(cm);
#endif // CONFIG_FRAME_MARKER
......
......@@ -5273,16 +5273,31 @@ static void dump_filtered_recon_frames(AV1_COMP *cpi) {
return;
}
}
#if CONFIG_FRAME_MARKER
printf(
"\nFrame=%5d, encode_update_type[%5d]=%1d, frame_offset=%d, "
"show_frame=%d, show_existing_frame=%d, source_alt_ref_active=%d, "
"refresh_alt_ref_frame=%d, rf_level=%d, "
"y_stride=%4d, uv_stride=%4d, cm->width=%4d, cm->height=%4d\n\n",
cm->current_video_frame, cpi->twopass.gf_group.index,
cpi->twopass.gf_group.update_type[cpi->twopass.gf_group.index],
cm->frame_offset, cm->show_frame, cm->show_existing_frame,
cpi->rc.source_alt_ref_active, cpi->refresh_alt_ref_frame,
cpi->twopass.gf_group.rf_level[cpi->twopass.gf_group.index],
recon_buf->y_stride, recon_buf->uv_stride, cm->width, cm->height);
#else
printf(
"\nFrame=%5d, encode_update_type[%5d]=%1d, show_existing_frame=%d, "
"source_alt_ref_active=%d, refresh_alt_ref_frame=%d, rf_level=%d, "
"y_stride=%4d, uv_stride=%4d, cm->width=%4d, cm->height=%4d\n",
"\nFrame=%5d, encode_update_type[%5d]=%1d, "
"show_frame=%d, show_existing_frame=%d, source_alt_ref_active=%d, "
"refresh_alt_ref_frame=%d, rf_level=%d, "
"y_stride=%4d, uv_stride=%4d, cm->width=%4d, cm->height=%4d\n\n",
cm->current_video_frame, cpi->twopass.gf_group.index,
cpi->twopass.gf_group.update_type[cpi->twopass.gf_group.index],
cm->show_existing_frame, cpi->rc.source_alt_ref_active,
cm->show_frame, cm->show_existing_frame, cpi->rc.source_alt_ref_active,
cpi->refresh_alt_ref_frame,
cpi->twopass.gf_group.rf_level[cpi->twopass.gf_group.index],
recon_buf->y_stride, recon_buf->uv_stride, cm->width, cm->height);
#endif // CONFIG_FRAME_MARKER
#if 0
int ref_frame;
printf("get_ref_frame_map_idx: [");
......
......@@ -93,6 +93,15 @@ void av1_fill_mode_rates(AV1_COMMON *const cm, MACROBLOCK *x,
NULL);
}
#if CONFIG_EXT_SKIP
if (cm->skip_mode_flag) {
for (i = 0; i < SKIP_CONTEXTS; ++i) {
av1_cost_tokens_from_cdf(x->skip_mode_cost[i], fc->skip_mode_cdfs[i],
NULL);
}
}
#endif // CONFIG_EXT_SKIP
for (i = 0; i < SKIP_CONTEXTS; ++i) {
av1_cost_tokens_from_cdf(x->skip_cost[i], fc->skip_cdfs[i], NULL);
}
......
This diff is collapsed.
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