Experiment to copy motion and mode from block neighbors.
Results:
--------
--enable-experimental --enable-copy-mode:
derflr: +0.727%
With other expts:
--enable-experimental --enable-copy-mode --enable-supertx
--enable-ext-tx --enable-filterintra --enable-tx-skip --enable-tx64x64
derflr: +3.43%
Change-Id: Iae74b9a855a1a690bf76131b42d247bbc54dec17
ext_tx
tx_skip
supertx
+ copy_mode
"
CONFIG_LIST="
external_build
#define SKIP_CONTEXTS 3
#define INTER_MODE_CONTEXTS 7
+#if CONFIG_COPY_MODE
+#define COPY_MODE_CONTEXTS 5
+#endif // CONFIG_COPY_MODE
+
/* Segment Feature Masks */
#define MAX_MV_REF_CANDIDATES 2
MB_MODE_COUNT
} PREDICTION_MODE;
+#if CONFIG_COPY_MODE
+typedef enum {
+ NOREF,
+ REF0,
+ REF1,
+ REF2,
+ COPY_MODE_COUNT
+} COPY_MODE;
+#endif // CONFIG_COPY_MODE
+
static INLINE int is_inter_mode(PREDICTION_MODE mode) {
return mode >= NEARESTMV && mode <= NEWMV;
}
int tx_skip[PLANE_TYPES];
int tx_skip_shift;
#endif
+#if CONFIG_COPY_MODE
+ COPY_MODE copy_mode;
+ int inter_ref_count;
+#endif // CONFIG_COPY_MODE
} MB_MODE_INFO;
typedef struct MODE_INFO {
};
static const vp9_prob default_intra_inter_p[INTRA_INTER_CONTEXTS] = {
+#if CONFIG_COPY_MODE
+ 35, 112, 187, 225
+#else
9, 102, 187, 225
+#endif
};
static const vp9_prob default_comp_inter_p[COMP_INTER_CONTEXTS] = {
};
#endif // CONFIG_SUPERTX
+#if CONFIG_COPY_MODE
+static const vp9_prob default_copy_noref_prob[COPY_MODE_CONTEXTS]
+ [BLOCK_SIZES] = {
+ {255, 255, 255, 82, 148, 182, 65, 193, 158, 70, 138, 101, 23},
+ {255, 255, 255, 118, 153, 161, 123, 169, 157, 82, 101, 123, 88},
+ {255, 255, 255, 130, 178, 226, 194, 196, 174, 173, 135, 144, 141},
+ {255, 255, 255, 178, 218, 225, 197, 230, 222, 215, 220, 220, 220},
+ {255, 255, 255, 243, 248, 241, 233, 249, 249, 249, 249, 249, 249}
+};
+
+static const vp9_prob default_copy_mode_probs_l2[COPY_MODE_CONTEXTS][1] = {
+ {207},
+ {135},
+ {141},
+ {189},
+ {209}
+};
+
+const vp9_tree_index vp9_copy_mode_tree_l2[TREE_SIZE(2)] = {
+ -(REF0 - REF0), -(REF1 - REF0)
+};
+
+static const vp9_prob default_copy_mode_probs[COPY_MODE_CONTEXTS]
+ [COPY_MODE_COUNT - 2] = {
+ {130, 159},
+ {126, 176},
+ {120, 150},
+ {158, 183},
+ {149, 125}
+};
+
+const vp9_tree_index vp9_copy_mode_tree[TREE_SIZE(COPY_MODE_COUNT - 1)] = {
+ -(REF0 - REF0), 2,
+ -(REF1 - REF0), -(REF2 - REF0)
+};
+#endif // CONFIG_COPY_MODE
+
#if CONFIG_TX64X64
void tx_counts_to_branch_counts_64x64(const unsigned int *tx_count_64x64p,
unsigned int (*ct_64x64p)[2]) {
vp9_copy(fc->inter_mode_probs, default_inter_mode_probs);
#if CONFIG_FILTERINTRA
vp9_copy(fc->filterintra_prob, default_filterintra_prob);
-#endif
+#endif // CONFIG_FILTERINTRA
#if CONFIG_EXT_TX
vp9_copy(fc->ext_tx_prob, default_ext_tx_prob);
-#endif
+#endif // CONFIG_EXT_TX
#if CONFIG_SUPERTX
vp9_copy(fc->supertx_prob, default_supertx_prob);
-#endif
+#endif // CONFIG_SUPERTX
#if CONFIG_TX_SKIP
vp9_copy(fc->y_tx_skip_prob, default_y_tx_skip_prob);
vp9_copy(fc->uv_tx_skip_prob, default_uv_tx_skip_prob);
-#endif
+#endif // CONFIG_TX_SKIP
+#if CONFIG_COPY_MODE
+ vp9_copy(fc->copy_noref_prob, default_copy_noref_prob);
+ vp9_copy(fc->copy_mode_probs_l2, default_copy_mode_probs_l2);
+ vp9_copy(fc->copy_mode_probs, default_copy_mode_probs);
+#endif // CONFIG_COPY_MODE
}
const vp9_tree_index vp9_switchable_interp_tree
fc->uv_tx_skip_prob[i] = adapt_prob(pre_fc->uv_tx_skip_prob[i],
counts->uv_tx_skip[i]);
#endif // CONFIG_TX_SKIP
+#if CONFIG_COPY_MODE
+ for (i = 0; i < COPY_MODE_CONTEXTS; i++) {
+ for (j = BLOCK_8X8; j < BLOCK_SIZES; j++) {
+ fc->copy_noref_prob[i][j] =
+ adapt_prob(pre_fc->copy_noref_prob[i][j], counts->copy_noref[i][j]);
+ }
+ adapt_probs(vp9_copy_mode_tree_l2, pre_fc->copy_mode_probs_l2[i],
+ counts->copy_mode_l2[i], fc->copy_mode_probs_l2[i]);
+ adapt_probs(vp9_copy_mode_tree, pre_fc->copy_mode_probs[i],
+ counts->copy_mode[i], fc->copy_mode_probs[i]);
+ }
+#endif // CONFIG_COPY_MODE
}
static void set_default_lf_deltas(struct loopfilter *lf) {
nmv_context nmvc;
#if CONFIG_FILTERINTRA
vp9_prob filterintra_prob[TX_SIZES][INTRA_MODES];
-#endif
+#endif // CONFIG_FILTERINTRA
#if CONFIG_EXT_TX
vp9_prob ext_tx_prob[3][EXT_TX_TYPES - 1];
-#endif
+#endif // CONFIG_EXT_TX
#if CONFIG_SUPERTX
vp9_prob supertx_prob[PARTITION_SUPERTX_CONTEXTS][TX_SIZES];
-#endif
+#endif // CONFIG_SUPERTX
#if CONFIG_TX_SKIP
vp9_prob y_tx_skip_prob[2];
vp9_prob uv_tx_skip_prob[2];
-#endif
+#endif // CONFIG_TX_SKIP
+#if CONFIG_COPY_MODE
+ vp9_prob copy_noref_prob[COPY_MODE_CONTEXTS][BLOCK_SIZES];
+ vp9_prob copy_mode_probs_l2[COPY_MODE_CONTEXTS][1];
+ vp9_prob copy_mode_probs[COPY_MODE_CONTEXTS][COPY_MODE_COUNT - 2];
+#endif // CONFIG_COPY_MODE
} FRAME_CONTEXT;
typedef struct {
unsigned int y_tx_skip[2][2];
unsigned int uv_tx_skip[2][2];
#endif
+#if CONFIG_COPY_MODE
+ unsigned int copy_noref[COPY_MODE_CONTEXTS][BLOCK_SIZES][2];
+ unsigned int copy_mode_l2[COPY_MODE_CONTEXTS][2];
+ unsigned int copy_mode[COPY_MODE_CONTEXTS][COPY_MODE_COUNT - 1];
+#endif // CONFIG_COPY_MODE
} FRAME_COUNTS;
extern const vp9_prob vp9_kf_uv_mode_prob[INTRA_MODES][INTRA_MODES - 1];
#if CONFIG_EXT_TX
extern const vp9_tree_index vp9_ext_tx_tree[TREE_SIZE(EXT_TX_TYPES)];
#endif
+#if CONFIG_COPY_MODE
+extern const vp9_tree_index vp9_copy_mode_tree_l2[TREE_SIZE(2)];
+extern const vp9_tree_index vp9_copy_mode_tree[TREE_SIZE(COPY_MODE_COUNT - 1)];
+#endif // CONFIG_COPY_MODE
void vp9_setup_past_independence(struct VP9Common *cm);
assert("Invalid block index.");
}
}
+
+#if CONFIG_COPY_MODE
+static int compare_interinfo(MB_MODE_INFO *mbmi, MB_MODE_INFO *ref_mbmi) {
+ if (mbmi == ref_mbmi) {
+ return 1;
+ } else {
+ int is_same;
+ if (mbmi->ref_frame[0] == ref_mbmi->ref_frame[0] &&
+ mbmi->ref_frame[1] == ref_mbmi->ref_frame[1]) {
+ if (mbmi->ref_frame[1] > INTRA_FRAME)
+ is_same = mbmi->mv[0].as_int == ref_mbmi->mv[0].as_int &&
+ mbmi->mv[1].as_int == ref_mbmi->mv[1].as_int &&
+ mbmi->interp_filter == ref_mbmi->interp_filter;
+ else
+ is_same = mbmi->mv[0].as_int == ref_mbmi->mv[0].as_int &&
+ mbmi->interp_filter == ref_mbmi->interp_filter;
+ } else {
+ is_same = 0;
+ }
+
+ return is_same;
+ }
+}
+
+static int check_inside(VP9_COMMON *cm, int mi_row, int mi_col) {
+ return mi_row >= 0 && mi_col >= 0 &&
+ mi_row < cm->mi_rows && mi_col < cm->mi_cols;
+}
+
+static int is_right_available(BLOCK_SIZE bsize, int mi_row, int mi_col) {
+ int depth, max_depth = 4 - MIN(b_width_log2_lookup[bsize],
+ b_height_log2_lookup[bsize]);
+ int block[4] = {0};
+
+ if (bsize == BLOCK_64X64)
+ return 1;
+ mi_row = mi_row % 8;
+ mi_col = mi_col % 8;
+ for (depth = 1; depth <= max_depth; depth++) {
+ block[depth] = (mi_row >> (3 - depth)) * 2 + (mi_col >> (3 - depth));
+ mi_row = mi_row % (8 >> depth);
+ mi_col = mi_col % (8 >> depth);
+ }
+
+ if (b_width_log2_lookup[bsize] < b_height_log2_lookup[bsize]) {
+ if (block[max_depth] == 0)
+ return 1;
+ } else if (b_width_log2_lookup[bsize] > b_height_log2_lookup[bsize]) {
+ if (block[max_depth] > 0)
+ return 0;
+ } else {
+ if (block[max_depth] == 0 || block[max_depth] == 2)
+ return 1;
+ else if (block[max_depth] == 3)
+ return 0;
+ }
+
+ for (depth = max_depth - 1; depth > 0; depth--) {
+ if (block[depth] == 0 || block[depth] == 2)
+ return 1;
+ else if (block[depth] == 3)
+ return 0;
+ }
+ return 1;
+}
+
+static int is_second_rec(int mi_row, int mi_col, BLOCK_SIZE bsize) {
+ int bw = 4 << b_width_log2_lookup[bsize];
+ int bh = 4 << b_height_log2_lookup[bsize];
+
+ if (bw < bh)
+ return (mi_col << 3) % (bw << 1) == 0 ? 0 : 1;
+ else if (bh < bw)
+ return (mi_row << 3) % (bh << 1) == 0 ? 0 : 2;
+ else
+ return 0;
+}
+
+int vp9_construct_ref_inter_list(VP9_COMMON *cm, MACROBLOCKD *xd,
+ BLOCK_SIZE bsize, int mi_row, int mi_col,
+ MB_MODE_INFO *ref_list[18]) {
+ int bw = 4 << b_width_log2_lookup[bsize];
+ int bh = 4 << b_height_log2_lookup[bsize];
+ int row_offset, col_offset;
+ int mi_offset;
+ MB_MODE_INFO *ref_mbmi;
+ int ref_index, ref_num = 0;
+ int row_offset_cand[18], col_offset_cand[18];
+ int offset_num = 0, i, switchflag;
+ int is_sec_rec = is_second_rec(mi_row, mi_col, bsize);
+
+ if (is_sec_rec != 2) {
+ row_offset_cand[offset_num] = -1; col_offset_cand[offset_num] = 0;
+ offset_num++;
+ }
+ if (is_sec_rec != 1) {
+ row_offset_cand[offset_num] = bh / 16; col_offset_cand[offset_num] = -1;
+ offset_num++;
+ }
+
+ row_offset = bh / 8 - 1;
+ col_offset = 1;
+ if (is_sec_rec < 2)
+ switchflag = 1;
+ else
+ switchflag = 0;
+ while ((is_sec_rec == 0 && ((row_offset >=0) || col_offset < (bw / 8 + 1))) ||
+ (is_sec_rec == 1 && col_offset < (bw / 8 + 1)) ||
+ (is_sec_rec == 2 && row_offset >=0)) {
+ switch (switchflag) {
+ case 0:
+ if (row_offset >= 0) {
+ if (row_offset != bh / 16) {
+ row_offset_cand[offset_num] = row_offset;
+ col_offset_cand[offset_num] = -1;
+ offset_num++;
+ }
+ row_offset--;
+ }
+ break;
+ case 1:
+ if (col_offset < (bw / 8 + 1)) {
+ row_offset_cand[offset_num] = -1;
+ col_offset_cand[offset_num] = col_offset;
+ offset_num++;
+ col_offset++;
+ }
+ break;
+ default:
+ assert(0);
+ }
+ if (is_sec_rec == 0)
+ switchflag = 1 - switchflag;
+ }
+ row_offset_cand[offset_num] = -1;
+ col_offset_cand[offset_num] = -1;
+ offset_num++;
+
+ for (i = 0; i < offset_num; i++) {
+ row_offset = row_offset_cand[i];
+ col_offset = col_offset_cand[i];
+ if ((col_offset < (bw / 8) ||
+ (col_offset == (bw / 8) && is_right_available(bsize, mi_row, mi_col)))
+ && check_inside(cm, mi_row + row_offset, mi_col + col_offset)) {
+ mi_offset = row_offset * cm->mi_stride + col_offset;
+ ref_mbmi = &xd->mi[mi_offset].src_mi->mbmi;
+ if (is_inter_block(ref_mbmi)) {
+ for (ref_index = 0; ref_index < ref_num; ref_index++) {
+ if (compare_interinfo(ref_mbmi, ref_list[ref_index]))
+ break;
+ }
+ if (ref_index == ref_num) {
+ ref_list[ref_num] = ref_mbmi;
+ ref_num++;
+ }
+ }
+ }
+ }
+ return ref_num;
+}
+#endif // CONFIG_COPY_MODE
int block, int ref, int mi_row, int mi_col,
int_mv *nearest, int_mv *near);
+#if CONFIG_COPY_MODE
+int vp9_construct_ref_inter_list(VP9_COMMON *cm, MACROBLOCKD *xd,
+ BLOCK_SIZE bsize, int mi_row, int mi_col,
+ MB_MODE_INFO *ref_list[18]);
+#endif // CONFIG_COPY_MODE
+
#ifdef __cplusplus
} // extern "C"
#endif
assert(segment_id >= 0 && segment_id < MAX_SEGMENTS);
return segment_id;
}
+
+#if CONFIG_COPY_MODE
+int vp9_get_copy_mode_context(const MACROBLOCKD *xd) {
+ const MB_MODE_INFO *const above_mbmi = get_mbmi(get_above_mi(xd));
+ const MB_MODE_INFO *const left_mbmi = get_mbmi(get_left_mi(xd));
+ const int has_above = above_mbmi != NULL;
+ const int has_left = left_mbmi != NULL;
+
+ if (has_above && has_left) {
+ const int above_intra = !is_inter_block(above_mbmi);
+ const int left_intra = !is_inter_block(left_mbmi);
+
+ if (above_intra && left_intra) {
+ return 4;
+ } else if (above_intra || left_intra) {
+ return 3;
+ } else {
+ const int above_predict = above_mbmi->copy_mode != NOREF;
+ const int left_predict = left_mbmi->copy_mode != NOREF;
+ if (above_predict && left_predict)
+ return 0;
+ else if (above_predict || left_predict)
+ return 1;
+ else
+ return 2;
+ }
+ } else if (has_above || has_left) {
+ const MB_MODE_INFO *const ref_mbmi = has_above ? above_mbmi : left_mbmi;
+ const int ref_intra = !is_inter_block(ref_mbmi);
+
+ if (ref_intra) {
+ return 3;
+ } else {
+ const int ref_predict = ref_mbmi != NOREF;
+ if (ref_predict)
+ return 0;
+ else
+ return 1;
+ }
+ } else {
+ return 0;
+ }
+}
+#endif // CONFIG_COPY_MODE
}
}
+#if CONFIG_COPY_MODE
+int vp9_get_copy_mode_context(const MACROBLOCKD *xd);
+#endif // CONFIG_COPY_MODE
+
#ifdef __cplusplus
} // extern "C"
#endif
vp9_diff_update_prob(&r, &fc->y_tx_skip_prob[i]);
for (i = 0; i < 2; i++)
vp9_diff_update_prob(&r, &fc->uv_tx_skip_prob[i]);
+#endif
+#if CONFIG_COPY_MODE
+ for (j = 0; j < COPY_MODE_CONTEXTS; j++) {
+ for (i = 0; i < 1; i++)
+ vp9_diff_update_prob(&r, &fc->copy_mode_probs_l2[j][i]);
+ for (i = 0; i < COPY_MODE_COUNT - 2; i++)
+ vp9_diff_update_prob(&r, &fc->copy_mode_probs[j][i]);
+ }
#endif
}
return NEARESTMV + mode;
}
+#if CONFIG_COPY_MODE
+static COPY_MODE read_copy_mode(VP9_COMMON *cm, vp9_reader *r,
+ int num_candidate, int ctx) {
+ COPY_MODE mode;
+
+ switch (num_candidate) {
+ case 0:
+ assert(0);
+ break;
+ case 1:
+ mode = REF0;
+ break;
+ case 2:
+ mode = REF0 + vp9_read_tree(r, vp9_copy_mode_tree_l2,
+ cm->fc.copy_mode_probs_l2[ctx]);
+ if (!cm->frame_parallel_decoding_mode)
+ ++cm->counts.copy_mode_l2[ctx][mode - REF0];
+ break;
+ default:
+ mode = REF0 + vp9_read_tree(r, vp9_copy_mode_tree,
+ cm->fc.copy_mode_probs[ctx]);
+ if (!cm->frame_parallel_decoding_mode)
+ ++cm->counts.copy_mode[ctx][mode - REF0];
+ break;
+ }
+
+ return mode;
+}
+#endif // CONFIG_COPY_MODE
+
static int read_segment_id(vp9_reader *r, const struct segmentation *seg) {
return vp9_read_tree(r, vp9_segment_tree, seg->tree_probs);
}
int_mv nearestmv[2], nearmv[2];
int inter_mode_ctx, ref, is_compound;
- read_ref_frames(cm, xd, r, mbmi->segment_id, mbmi->ref_frame);
+#if CONFIG_COPY_MODE
+ if (mbmi->copy_mode == NOREF)
+#endif
+ 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) {
"Block reference is corrupt");
vp9_setup_pre_planes(xd, ref, ref_buf->buf, mi_row, mi_col,
&ref_buf->sf);
- vp9_find_mv_refs(cm, xd, tile, mi, frame, mbmi->ref_mvs[frame],
- mi_row, mi_col);
+#if CONFIG_COPY_MODE
+ if (mbmi->copy_mode == NOREF)
+#endif
+ vp9_find_mv_refs(cm, xd, tile, mi, frame, mbmi->ref_mvs[frame],
+ mi_row, mi_col);
}
+#if CONFIG_COPY_MODE
+ if (mbmi->copy_mode != NOREF)
+ return;
+#endif
inter_mode_ctx = mbmi->mode_context[mbmi->ref_frame[0]];
MODE_INFO *const mi = xd->mi[0].src_mi;
MB_MODE_INFO *const mbmi = &mi->mbmi;
int inter_block;
+#if CONFIG_COPY_MODE
+ int num_candidate = 0;
+ MB_MODE_INFO *inter_ref_list[18] = {NULL};
+#endif
mbmi->mv[0].as_int = 0;
mbmi->mv[1].as_int = 0;
+#if CONFIG_COPY_MODE
+ if (mbmi->sb_type >= BLOCK_8X8)
+ num_candidate = vp9_construct_ref_inter_list(
+ cm, xd, mbmi->sb_type, mi_row, mi_col, inter_ref_list);
+ if (mbmi->sb_type >= BLOCK_8X8 && num_candidate > 0) {
+ int ctx = vp9_get_copy_mode_context(xd);
+ int is_copy = vp9_read(r, cm->fc.copy_noref_prob[ctx][mbmi->sb_type]);
+
+ ++cm->counts.copy_noref[ctx][mbmi->sb_type][is_copy];
+ if (!is_copy) {
+ mbmi->copy_mode = NOREF;
+ } else {
+ mbmi->copy_mode = read_copy_mode(cm, r, num_candidate, ctx);
+ }
+ } else {
+ mbmi->copy_mode = NOREF;
+ }
+ if (mbmi->copy_mode != NOREF) {
+ BLOCK_SIZE bsize_backup = mbmi->sb_type;
+ int skip_backup = mbmi->skip;
+ COPY_MODE copy_mode_backup = mbmi->copy_mode;
+#if CONFIG_SUPERTX
+ TX_SIZE tx_size_backup = mbmi->tx_size;
+#endif
+#if CONFIG_EXT_TX
+ EXT_TX_TYPE ext_txfrm_backup = mbmi->ext_txfrm;
+#endif
+
+ inter_block = 1;
+ *mbmi = *inter_ref_list[mbmi->copy_mode - REF0];
+#if CONFIG_SUPERTX
+ mbmi->tx_size = tx_size_backup;
+#endif
+#if CONFIG_EXT_TX
+ mbmi->ext_txfrm = ext_txfrm_backup;
+#endif
+ mbmi->sb_type = bsize_backup;
+ mbmi->mode = NEARESTMV;
+ mbmi->skip = skip_backup;
+ mbmi->copy_mode = copy_mode_backup;
+ }
+#endif // CONFIG_COPY_MODE
+
#if CONFIG_SUPERTX
if (!supertx_enabled) {
#endif
mbmi->segment_id = read_inter_segment_id(cm, xd, mi_row, mi_col, r);
mbmi->skip = read_skip(cm, xd, mbmi->segment_id, r);
- inter_block = read_is_inter_block(cm, xd, mbmi->segment_id, r);
+#if CONFIG_COPY_MODE
+ if (mbmi->copy_mode == NOREF)
+#endif
+ inter_block = read_is_inter_block(cm, xd, mbmi->segment_id, r);
mbmi->tx_size = read_tx_size(cm, xd, cm->tx_mode, mbmi->sb_type,
!mbmi->skip || !inter_block, r);
#if CONFIG_EXT_TX
mbmi->segment_id = 0;
inter_block = 1;
if (!cm->frame_parallel_decoding_mode)
- ++cm->counts.intra_inter[ctx][1];
+#if CONFIG_COPY_MODE
+ if (mbmi->copy_mode == NOREF)
+#endif
+ ++cm->counts.intra_inter[ctx][1];
}
#endif // CONFIG_SUPERTX
#if CONFIG_EXT_TX
static struct vp9_token ext_tx_encodings[EXT_TX_TYPES];
#endif
+#if CONFIG_COPY_MODE
+static struct vp9_token copy_mode_encodings_l2[2];
+static struct vp9_token copy_mode_encodings[COPY_MODE_COUNT - 1];
+#endif
#if CONFIG_SUPERTX
static int vp9_check_supertx(VP9_COMMON *cm, int mi_row, int mi_col,
#if CONFIG_EXT_TX
vp9_tokens_from_tree(ext_tx_encodings, vp9_ext_tx_tree);
#endif
+#if CONFIG_COPY_MODE
+ vp9_tokens_from_tree(copy_mode_encodings_l2, vp9_copy_mode_tree_l2);
+ vp9_tokens_from_tree(copy_mode_encodings, vp9_copy_mode_tree);
+#endif // CONFIG_COPY_MODE
}
static void write_intra_mode(vp9_writer *w, PREDICTION_MODE mode,
&inter_mode_encodings[INTER_OFFSET(mode)]);
}
+#if CONFIG_COPY_MODE
+static void write_copy_mode(VP9_COMMON *cm, vp9_writer *w, COPY_MODE mode,
+ int inter_ref_count, int copy_mode_context) {
+ if (inter_ref_count == 2) {
+ vp9_write_token(w, vp9_copy_mode_tree_l2,
+ cm->fc.copy_mode_probs_l2[copy_mode_context],
+ ©_mode_encodings_l2[mode - REF0]);
+ } else if (inter_ref_count > 2) {
+ vp9_write_token(w, vp9_copy_mode_tree,
+ cm->fc.copy_mode_probs[copy_mode_context],
+ ©_mode_encodings[mode - REF0]);
+ }
+}
+#endif // CONFIG_COPY_MODE
+
static void encode_unsigned_max(struct vp9_write_bit_buffer *wb,
int data, int max) {
vp9_wb_write_literal(wb, data, get_unsigned_bits(max));
const int is_inter = is_inter_block(mbmi);
const int is_compound = has_second_ref(mbmi);
int skip, ref;
+#if CONFIG_COPY_MODE
+ int copy_mode_context = vp9_get_copy_mode_context(xd);
+ if (bsize >= BLOCK_8X8 && mbmi->inter_ref_count > 0) {
+ vp9_write(w, mbmi->copy_mode != NOREF,
+ cm->fc.copy_noref_prob[copy_mode_context][bsize]);
+ if (mbmi->copy_mode != NOREF)
+ write_copy_mode(cm, w, mbmi->copy_mode, mbmi->inter_ref_count,
+ copy_mode_context);
+ }
+#endif
if (seg->update_map) {
if (seg->temporal_update) {
#if CONFIG_SUPERTX
if (!supertx_enabled) {
#endif
- if (!vp9_segfeature_active(seg, segment_id, SEG_LVL_REF_FRAME))
- vp9_write(w, is_inter, vp9_get_intra_inter_prob(cm, xd));
+#if CONFIG_COPY_MODE
+ if (mbmi->copy_mode == NOREF)
+#endif
+ if (!vp9_segfeature_active(seg, segment_id, SEG_LVL_REF_FRAME))
+ vp9_write(w, is_inter, vp9_get_intra_inter_prob(cm, xd));
#if CONFIG_SUPERTX
}
#endif
vp9_write(w, mbmi->tx_skip[1], cm->fc.uv_tx_skip_prob[mbmi->tx_skip[0]]);
}
}
-#endif
+#endif // CONFIG_TX_SKIP
if (!is_inter) {
if (bsize >= BLOCK_8X8) {
cm->fc.filterintra_prob[get_uv_tx_size(mbmi, &xd->plane[1])][mbmi->uv_mode]);
}
#endif
+#if CONFIG_COPY_MODE
+ } else if (mbmi->copy_mode == NOREF) {
+#else
} else {
+#endif
const int mode_ctx = mbmi->mode_context[mbmi->ref_frame[0]];
const vp9_prob *const inter_probs = cm->fc.inter_mode_probs[mode_ctx];
write_ref_frames(cm, xd, w);
for (i = 0; i < 2; i++)
vp9_cond_prob_diff_update(&header_bc, &fc->uv_tx_skip_prob[i],
cm->counts.uv_tx_skip[i]);
+#endif
+#if CONFIG_COPY_MODE
+ for (i = 0; i < COPY_MODE_CONTEXTS; i++) {
+ prob_diff_update(vp9_copy_mode_tree_l2, cm->fc.copy_mode_probs_l2[i],
+ cm->counts.copy_mode_l2[i], 2, &header_bc);
+ prob_diff_update(vp9_copy_mode_tree, cm->fc.copy_mode_probs[i],
+ cm->counts.copy_mode[i], COPY_MODE_COUNT - 1,
+ &header_bc);
+ }
#endif
}
}
#endif
if (!frame_is_intra_only(cm)) {
+#if CONFIG_COPY_MODE
+ COPY_MODE copy_mode = mbmi->copy_mode;
+ if (mbmi->sb_type >= BLOCK_8X8) {
+ int copy_mode_context = vp9_get_copy_mode_context(xd);
+ if (mbmi->inter_ref_count > 0) {
+ ++cm->counts.copy_noref[copy_mode_context][mbmi->sb_type]
+ [copy_mode != NOREF];
+ if (copy_mode != NOREF) {
+ if (mbmi->inter_ref_count == 2)
+ ++cm->counts.copy_mode_l2[copy_mode_context][copy_mode - REF0];
+ else if (mbmi->inter_ref_count > 2)
+ ++cm->counts.copy_mode[copy_mode_context][copy_mode - REF0];
+ }
+ }
+ }
+ if (is_inter_block(mbmi) && copy_mode == NOREF) {
+#else
if (is_inter_block(mbmi)) {
+#endif // CONFIG_COPY_MODE
vp9_update_mv_count(cm, xd);
if (cm->interp_filter == SWITCHABLE) {
return;
if (!frame_is_intra_only(cm)) {
+#if CONFIG_COPY_MODE
+ COPY_MODE copy_mode = mbmi->copy_mode;
+ if (mbmi->sb_type >= BLOCK_8X8) {
+ int copy_mode_context = vp9_get_copy_mode_context(xd);
+ if (mbmi->inter_ref_count > 0) {
+ ++cm->counts.copy_noref[copy_mode_context][mbmi->sb_type]
+ [copy_mode != NOREF];
+ if (copy_mode != NOREF) {
+ if (mbmi->inter_ref_count == 2)
+ ++cm->counts.copy_mode_l2[copy_mode_context][copy_mode - REF0];
+ else if (mbmi->inter_ref_count > 2)
+ ++cm->counts.copy_mode[copy_mode_context][copy_mode - REF0];
+ }
+ }
+ }
+ if (is_inter_block(mbmi) && copy_mode == NOREF) {
+#else
if (is_inter_block(mbmi)) {
+#endif // CONFIG_COPY_MODE
vp9_update_mv_count(cm, xd);
if (cm->interp_filter == SWITCHABLE) {
const MODE_INFO *const mi = xd->mi[0].src_mi;
const MB_MODE_INFO *const mbmi = &mi->mbmi;
+#if CONFIG_COPY_MODE
+ if (!frame_is_intra_only(cm) && mbmi->copy_mode == NOREF) {
+#else
if (!frame_is_intra_only(cm)) {
+#endif
const int seg_ref_active = vp9_segfeature_active(&cm->seg, mbmi->segment_id,
SEG_LVL_REF_FRAME);
if (!seg_ref_active) {
#if CONFIG_EXT_TX
int ext_tx_costs[3][EXT_TX_TYPES];
#endif
+#if CONFIG_COPY_MODE
+ int copy_mode_cost_l2[COPY_MODE_CONTEXTS][2];
+ int copy_mode_cost[COPY_MODE_CONTEXTS][COPY_MODE_COUNT - 1];
+#endif
PICK_MODE_CONTEXT *leaf_tree;
PC_TREE *pc_tree;
cm->fc.inter_mode_probs[i], vp9_inter_mode_tree);
}
}
+
+#if CONFIG_COPY_MODE
+ for (i = 0; i < COPY_MODE_CONTEXTS; ++i) {
+ vp9_cost_tokens((int *)cpi->copy_mode_cost_l2[i],
+ cm->fc.copy_mode_probs_l2[i], vp9_copy_mode_tree_l2);
+ vp9_cost_tokens((int *)cpi->copy_mode_cost[i],
+ cm->fc.copy_mode_probs[i], vp9_copy_mode_tree);
+ }
+#endif // CONFIG_COPY_MODE
}
static void model_rd_norm(int xsq_q10, int *r_q10, int *d_q10) {
#define MIN_EARLY_TERM_INDEX 3
+#if CONFIG_EXT_TX
+const double ext_tx_th = 0.99;
+#endif
+
typedef struct {
PREDICTION_MODE mode;
MV_REFERENCE_FRAME ref_frame[2];
int dummy;
int64_t best_rdcost_tx = INT64_MAX;
int best_ext_tx = NORM;
- double th = 0.99;
for (i = 0; i < EXT_TX_TYPES; i++) {
mbmi->ext_txfrm = i;
rdcost_tx = RDCOST(x->rdmult, x->rddiv, rate_y_tx, distortion_y_tx);
rdcost_tx = MIN(rdcost_tx, RDCOST(x->rdmult, x->rddiv, 0, *psse));
assert(rdcost_tx >= 0);
- if (rdcost_tx < best_rdcost_tx * th) {
+ if (rdcost_tx < best_rdcost_tx * ext_tx_th) {
best_ext_tx = i;
best_rdcost_tx = rdcost_tx;
}
int q_idx = vp9_get_qindex(seg, segment_id, cm->base_qindex);
int try_tx_skip = q_idx <= TX_SKIP_Q_THRESH_INTRA;
#endif
+#if CONFIG_COPY_MODE
+ COPY_MODE copy_mode;
+ int inter_ref_count;
+ MB_MODE_INFO *inter_ref_list[18];
+ int copy_mode_context = vp9_get_copy_mode_context(xd);
+#endif // CONFIG_COPY_MODE
vp9_zero(best_mbmode);
x->skip_encode = sf->skip_encode_frame && x->q_index < QIDX_SKIP_THRESH;
estimate_ref_frame_costs(cm, xd, segment_id, ref_costs_single, ref_costs_comp,
&comp_mode_p);
+#if CONFIG_COPY_MODE
+ inter_ref_count =
+ vp9_construct_ref_inter_list(cm, xd, bsize, mi_row, mi_col, inter_ref_list);
+ mbmi->inter_ref_count = inter_ref_count;
+#endif // CONFIG_COPY_MODE
for (i = 0; i < REFERENCE_MODES; ++i)
best_pred_rd[i] = INT64_MAX;
#if CONFIG_TX_SKIP
mbmi->tx_skip[0] = 0;
mbmi->tx_skip[1] = 0;
+#endif
+#if CONFIG_COPY_MODE
+ mbmi->copy_mode = NOREF;
#endif
// Evaluate all sub-pel filters irrespective of whether we can use
// them for this frame.
} else {
rate2 += ref_costs_single[ref_frame];
}
+#if CONFIG_COPY_MODE
+ if (inter_ref_count > 0)
+ rate2 += vp9_cost_bit(cm->fc.copy_noref_prob[copy_mode_context][bsize],
+ 0);
+#endif
if (!disable_skip) {
if (skippable) {
}
if (best_mode_index < 0 || best_rd >= best_rd_so_far) {
+#if !CONFIG_COPY_MODE
rd_cost->rate = INT_MAX;
rd_cost->rdcost = INT64_MAX;
return;
- }
+#endif
+ } else {
+ // If we used an estimate for the uv intra rd in the loop above...
+ if (sf->use_uv_intra_rd_estimate) {
+ // Do Intra UV best rd mode selection if best mode choice above was intra.
+ if (best_mbmode.ref_frame[0] == INTRA_FRAME) {
+ TX_SIZE uv_tx_size;
+ *mbmi = best_mbmode;
+ uv_tx_size = get_uv_tx_size(mbmi, &xd->plane[1]);
+ rd_pick_intra_sbuv_mode(cpi, x, ctx, &rate_uv_intra[uv_tx_size],
+ &rate_uv_tokenonly[uv_tx_size],
+ &dist_uv[uv_tx_size],
+ &skip_uv[uv_tx_size],
+ bsize < BLOCK_8X8 ? BLOCK_8X8 : bsize,
+ uv_tx_size);
+ }
+ }
- // If we used an estimate for the uv intra rd in the loop above...
- if (sf->use_uv_intra_rd_estimate) {
- // Do Intra UV best rd mode selection if best mode choice above was intra.
- if (best_mbmode.ref_frame[0] == INTRA_FRAME) {
- TX_SIZE uv_tx_size;
- *mbmi = best_mbmode;
- uv_tx_size = get_uv_tx_size(mbmi, &xd->plane[1]);
- rd_pick_intra_sbuv_mode(cpi, x, ctx, &rate_uv_intra[uv_tx_size],
- &rate_uv_tokenonly[uv_tx_size],
- &dist_uv[uv_tx_size],
- &skip_uv[uv_tx_size],
- bsize < BLOCK_8X8 ? BLOCK_8X8 : bsize,
- uv_tx_size);
+ assert((cm->interp_filter == SWITCHABLE) ||
+ (cm->interp_filter == best_mbmode.interp_filter) ||
+ !is_inter_block(&best_mbmode));
+
+ if (!cpi->rc.is_src_frame_alt_ref)
+ update_rd_thresh_fact(cpi, bsize, best_mode_index);
+
+ // macroblock modes
+ *mbmi = best_mbmode;
+ x->skip |= best_skip2;
+
+ for (i = 0; i < REFERENCE_MODES; ++i) {
+ if (best_pred_rd[i] == INT64_MAX)
+ best_pred_diff[i] = INT_MIN;
+ else
+ best_pred_diff[i] = best_rd - best_pred_rd[i];
+ }
+
+ if (!x->skip) {
+ for (i = 0; i < SWITCHABLE_FILTER_CONTEXTS; i++) {
+ if (best_filter_rd[i] == INT64_MAX)
+ best_filter_diff[i] = 0;
+ else
+ best_filter_diff[i] = best_rd - best_filter_rd[i];
+ }
+ if (cm->interp_filter == SWITCHABLE)
+ assert(best_filter_diff[SWITCHABLE_FILTERS] == 0);
+ for (i = 0; i < TX_MODES; i++) {
+ if (best_tx_rd[i] == INT64_MAX)
+ best_tx_diff[i] = 0;
+ else
+ best_tx_diff[i] = best_rd - best_tx_rd[i];
+ }
+ } else {
+ vp9_zero(best_filter_diff);
+ vp9_zero(best_tx_diff);
+ }
+
+ // TODO(yunqingwang): Moving this line in front of the above
+ // best_filter_diff updating code causes PSNR loss. Need to
+ // figure out the confliction.
+ x->skip |= best_mode_skippable;
+
+ if (!x->skip && !x->select_tx_size) {
+ int has_high_freq_coeff = 0;
+ int plane;
+ int max_plane = is_inter_block(&xd->mi[0].src_mi->mbmi)
+ ? MAX_MB_PLANE : 1;
+ for (plane = 0; plane < max_plane; ++plane) {
+ x->plane[plane].eobs = ctx->eobs_pbuf[plane][1];
+ has_high_freq_coeff |= vp9_has_high_freq_in_plane(x, bsize, plane);
+ }
+
+ for (plane = max_plane; plane < MAX_MB_PLANE; ++plane) {
+ x->plane[plane].eobs = ctx->eobs_pbuf[plane][2];
+ has_high_freq_coeff |= vp9_has_high_freq_in_plane(x, bsize, plane);
+ }
+
+ best_mode_skippable |= !has_high_freq_coeff;
}
+
+ store_coding_context(x, ctx, best_mode_index, best_pred_diff,
+ best_tx_diff, best_filter_diff, best_mode_skippable);
}
+#if CONFIG_COPY_MODE
+ for (copy_mode = REF0;
+ copy_mode < (COPY_MODE)(MIN(REF0 + inter_ref_count, COPY_MODE_COUNT));
+ copy_mode++) {
+ int i, rate2, rate_y, rate_uv, rate_copy_mode, this_skip2,
+ skippable, skippable_y, skippable_uv;
+ int64_t distortion2, distortion_y, distortion_uv, this_rd,
+ ssey, sseuv, total_sse, tx_cache[TX_MODES];
+#if CONFIG_EXT_TX
+ EXT_TX_TYPE tx_type, best_tx_type;
+ TX_SIZE best_tx_size;
+ int rate2_tx, this_skip2_tx;
+ int64_t distortion2_tx, bestrd_tx = INT64_MAX;
+ uint8_t tmp_zcoeff_blk[256];
+#endif
- assert((cm->interp_filter == SWITCHABLE) ||
- (cm->interp_filter == best_mbmode.interp_filter) ||
- !is_inter_block(&best_mbmode));
+ *mbmi = *inter_ref_list[copy_mode - REF0];
+ mbmi->sb_type = bsize;
+ mbmi->inter_ref_count = inter_ref_count;
+ mbmi->copy_mode = copy_mode;
+ mbmi->mode = NEARESTMV;
+ x->skip = 0;
+ set_ref_ptrs(cm, xd, mbmi->ref_frame[0], mbmi->ref_frame[1]);
+ for (i = 0; i < MAX_MB_PLANE; i++) {
+ xd->plane[i].pre[0] = yv12_mb[mbmi->ref_frame[0]][i];
+ if (mbmi->ref_frame[1] > INTRA_FRAME)
+ xd->plane[i].pre[1] = yv12_mb[mbmi->ref_frame[1]][i];
+ }
+ vp9_build_inter_predictors_sb(xd, mi_row, mi_col, bsize);
+ vp9_subtract_plane(x, bsize, 0);
- if (!cpi->rc.is_src_frame_alt_ref)
- update_rd_thresh_fact(cpi, bsize, best_mode_index);
+ for (i = 0; i < TX_MODES; ++i)
+ tx_cache[i] = INT64_MAX;
+#if CONFIG_EXT_TX
+ for (tx_type = NORM; tx_type < EXT_TX_TYPES; tx_type++) {
+ mbmi->ext_txfrm = tx_type;
+#endif
+ super_block_yrd(cpi, x, &rate_y, &distortion_y, &skippable_y, &ssey,
+ bsize, tx_cache, INT64_MAX);
+ super_block_uvrd(cpi, x, &rate_uv, &distortion_uv, &skippable_uv, &sseuv,
+ bsize, INT64_MAX);
- // macroblock modes
- *mbmi = best_mbmode;
- x->skip |= best_skip2;
+ rate2 = rate_y + rate_uv;
+ distortion2 = distortion_y + distortion_uv;
+ skippable = skippable_y && skippable_uv;
+ total_sse = ssey + sseuv;
- for (i = 0; i < REFERENCE_MODES; ++i) {
- if (best_pred_rd[i] == INT64_MAX)
- best_pred_diff[i] = INT_MIN;
+ if (skippable) {
+ rate2 -= (rate_y + rate_uv);
+ rate_y = 0;
+ rate_uv = 0;
+ rate2 += vp9_cost_bit(vp9_get_skip_prob(cm, xd), 1);
+ this_skip2 = 1;
+ } else if (!xd->lossless) {
+#if CONFIG_EXT_TX
+ if (mbmi->tx_size < TX_32X32)
+ rate2 += cpi->ext_tx_costs[mbmi->tx_size][mbmi->ext_txfrm];
+#endif // CONFIG_EXT_TX
+ if (RDCOST(x->rdmult, x->rddiv, rate2, distortion2) <
+ RDCOST(x->rdmult, x->rddiv, 0, total_sse)) {
+ rate2 += vp9_cost_bit(vp9_get_skip_prob(cm, xd), 0);
+ this_skip2 = 0;
+ } else {
+ rate2 = vp9_cost_bit(vp9_get_skip_prob(cm, xd), 1);
+ distortion2 = total_sse;
+ rate_y = 0;
+ rate_uv = 0;
+ this_skip2 = 1;
+ }
+ } else {
+ rate2 += vp9_cost_bit(vp9_get_skip_prob(cm, xd), 0);
+ this_skip2 = 0;
+ }
+#if CONFIG_EXT_TX
+ this_rd = RDCOST(x->rdmult, x->rddiv, rate2, distortion2);
+ if (tx_type == NORM || this_rd < (bestrd_tx * ext_tx_th)) {
+ bestrd_tx = this_rd;
+ best_tx_type = tx_type;
+ best_tx_size = mbmi->tx_size;
+ rate2_tx = rate2;
+ distortion2_tx = distortion2;
+ this_skip2_tx = this_skip2;
+ vpx_memcpy(tmp_zcoeff_blk, x->zcoeff_blk[mbmi->tx_size],
+ sizeof(uint8_t) * ctx->num_4x4_blk);
+ }
+ }
+ if (best_tx_size < TX_32X32)
+ mbmi->ext_txfrm = best_tx_type;
else
- best_pred_diff[i] = best_rd - best_pred_rd[i];
+ mbmi->ext_txfrm = NORM;
+ mbmi->tx_size = best_tx_size;
+ vpx_memcpy(x->zcoeff_blk[mbmi->tx_size], tmp_zcoeff_blk,
+ sizeof(uint8_t) * ctx->num_4x4_blk);
+
+ rate2 = rate2_tx;
+ distortion2 = distortion2_tx;
+ this_skip2 = this_skip2_tx;
+#endif // CONFIG_EXT_TX
+
+ rate_copy_mode =
+ vp9_cost_bit(cm->fc.copy_noref_prob[copy_mode_context][bsize], 1);
+ if (inter_ref_count == 2)
+ rate_copy_mode +=
+ cpi->copy_mode_cost_l2[copy_mode_context][copy_mode - REF0];
+ else if (inter_ref_count > 2)
+ rate_copy_mode +=
+ cpi->copy_mode_cost[copy_mode_context][copy_mode - REF0];
+ rate2 += rate_copy_mode;
+ this_rd = RDCOST(x->rdmult, x->rddiv, rate2, distortion2);
+
+ if (this_rd < best_rd) {
+ rd_cost->rate = rate2;
+ rd_cost->dist = distortion2;
+ rd_cost->rdcost = this_rd;
+#if CONFIG_SUPERTX
+ *returnrate_nocoef = rate_copy_mode;
+#endif
+ best_rd = this_rd;
+ best_mbmode = *mbmi;
+ best_skip2 = this_skip2;
+ best_mode_skippable = skippable;
+ // if (!x->select_tx_size) swap_block_ptr(x, ctx, 1, 0, 0, MAX_MB_PLANE);
+ vpx_memcpy(ctx->zcoeff_blk, x->zcoeff_blk[mbmi->tx_size],
+ sizeof(uint8_t) * ctx->num_4x4_blk);
+ }
+
+ if (bsize < BLOCK_32X32) {
+ if (bsize < BLOCK_16X16)
+ tx_cache[ALLOW_16X16] = tx_cache[ALLOW_8X8];
+ tx_cache[ALLOW_32X32] = tx_cache[ALLOW_16X16];
+ }
+ if (this_rd != INT64_MAX) {
+ for (i = 0; i < TX_MODES && tx_cache[i] < INT64_MAX; i++) {
+ int64_t adj_rd = INT64_MAX;
+ adj_rd = this_rd + tx_cache[i] - tx_cache[cm->tx_mode];
+
+ if (adj_rd < best_tx_rd[i])
+ best_tx_rd[i] = adj_rd;
+ }
+ }
+ }
+ if ((best_mode_index < 0 && best_mbmode.copy_mode == NOREF)
+ || best_rd >= best_rd_so_far) {
+ rd_cost->rate = INT_MAX;
+ rd_cost->rdcost = INT64_MAX;
+ return;
+ }
+
+ *mbmi = best_mbmode;
+ if (mbmi->copy_mode != NOREF) {
+ x->skip = best_skip2;
+ ctx->skip = x->skip;
+ ctx->skippable = best_mode_skippable;
+ ctx->mic = *xd->mi[0].src_mi;
}
+ set_ref_ptrs(cm, xd, mbmi->ref_frame[0], mbmi->ref_frame[1]);
if (!x->skip) {
- for (i = 0; i < SWITCHABLE_FILTER_CONTEXTS; i++) {
- if (best_filter_rd[i] == INT64_MAX)
- best_filter_diff[i] = 0;
- else
- best_filter_diff[i] = best_rd - best_filter_rd[i];
- }
- if (cm->interp_filter == SWITCHABLE)
- assert(best_filter_diff[SWITCHABLE_FILTERS] == 0);
for (i = 0; i < TX_MODES; i++) {
if (best_tx_rd[i] == INT64_MAX)
best_tx_diff[i] = 0;
else
best_tx_diff[i] = best_rd - best_tx_rd[i];
}
+ vpx_memcpy(ctx->tx_rd_diff, best_tx_diff, sizeof(ctx->tx_rd_diff));
} else {
vp9_zero(best_filter_diff);
vp9_zero(best_tx_diff);
}
-
- // TODO(yunqingwang): Moving this line in front of the above best_filter_diff
- // updating code causes PSNR loss. Need to figure out the confliction.
- x->skip |= best_mode_skippable;
-
- if (!x->skip && !x->select_tx_size) {
- int has_high_freq_coeff = 0;
- int plane;
- int max_plane = is_inter_block(&xd->mi[0].src_mi->mbmi)
- ? MAX_MB_PLANE : 1;
- for (plane = 0; plane < max_plane; ++plane) {
- x->plane[plane].eobs = ctx->eobs_pbuf[plane][1];
- has_high_freq_coeff |= vp9_has_high_freq_in_plane(x, bsize, plane);
- }
-
- for (plane = max_plane; plane < MAX_MB_PLANE; ++plane) {
- x->plane[plane].eobs = ctx->eobs_pbuf[plane][2];
- has_high_freq_coeff |= vp9_has_high_freq_in_plane(x, bsize, plane);
- }
-
- best_mode_skippable |= !has_high_freq_coeff;
- }
-
- store_coding_context(x, ctx, best_mode_index, best_pred_diff,
- best_tx_diff, best_filter_diff, best_mode_skippable);
+#endif
}
void vp9_rd_pick_inter_mode_sb_seg_skip(VP9_COMP *cpi, MACROBLOCK *x,
best_rd = best_rd_so_far;
best_yrd = best_rd_so_far;
#endif
+#if CONFIG_COPY_MODE
+ mbmi->copy_mode = NOREF;
+#endif
x->skip_encode = sf->skip_encode_frame && x->q_index < QIDX_SKIP_THRESH;
vpx_memset(x->zcoeff_blk[TX_4X4], 0, 4);