| Index: source/libvpx/vp9/encoder/vp9_encodeframe.c
|
| ===================================================================
|
| --- source/libvpx/vp9/encoder/vp9_encodeframe.c (revision 293588)
|
| +++ source/libvpx/vp9/encoder/vp9_encodeframe.c (working copy)
|
| @@ -36,6 +36,7 @@
|
| #include "vp9/encoder/vp9_encodeframe.h"
|
| #include "vp9/encoder/vp9_encodemb.h"
|
| #include "vp9/encoder/vp9_encodemv.h"
|
| +#include "vp9/encoder/vp9_ethread.h"
|
| #include "vp9/encoder/vp9_extend.h"
|
| #include "vp9/encoder/vp9_pickmode.h"
|
| #include "vp9/encoder/vp9_rd.h"
|
| @@ -54,9 +55,6 @@
|
| int mi_row, int mi_col, BLOCK_SIZE bsize,
|
| PICK_MODE_CONTEXT *ctx);
|
|
|
| -// Motion vector component magnitude threshold for defining fast motion.
|
| -#define FAST_MOTION_MV_THRESH 24
|
| -
|
| // This is used as a reference when computing the source variance for the
|
| // purposes of activity masking.
|
| // Eventually this should be replaced by custom no-reference routines,
|
| @@ -188,10 +186,10 @@
|
|
|
| // Lighter version of set_offsets that only sets the mode info
|
| // pointers.
|
| -static INLINE void set_modeinfo_offsets(VP9_COMMON *const cm,
|
| - MACROBLOCKD *const xd,
|
| - int mi_row,
|
| - int mi_col) {
|
| +static INLINE void set_mode_info_offsets(VP9_COMMON *const cm,
|
| + MACROBLOCKD *const xd,
|
| + int mi_row,
|
| + int mi_col) {
|
| const int idx_str = xd->mi_stride * mi_row + mi_col;
|
| xd->mi = cm->mi + idx_str;
|
| xd->mi[0].src_mi = &xd->mi[0];
|
| @@ -209,7 +207,7 @@
|
|
|
| set_skip_context(xd, mi_row, mi_col);
|
|
|
| - set_modeinfo_offsets(cm, xd, mi_row, mi_col);
|
| + set_mode_info_offsets(cm, xd, mi_row, mi_col);
|
|
|
| mbmi = &xd->mi[0].src_mi->mbmi;
|
|
|
| @@ -269,9 +267,8 @@
|
| int mi_row, int mi_col,
|
| BLOCK_SIZE bsize) {
|
| if (cpi->common.mi_cols > mi_col && cpi->common.mi_rows > mi_row) {
|
| - set_modeinfo_offsets(&cpi->common, xd, mi_row, mi_col);
|
| + set_mode_info_offsets(&cpi->common, xd, mi_row, mi_col);
|
| xd->mi[0].src_mi->mbmi.sb_type = bsize;
|
| - duplicate_mode_info_in_sb(&cpi->common, xd, mi_row, mi_col, bsize);
|
| }
|
| }
|
|
|
| @@ -278,7 +275,7 @@
|
| typedef struct {
|
| int64_t sum_square_error;
|
| int64_t sum_error;
|
| - int count;
|
| + int log2_count;
|
| int variance;
|
| } var;
|
|
|
| @@ -327,7 +324,6 @@
|
| static void tree_to_node(void *data, BLOCK_SIZE bsize, variance_node *node) {
|
| int i;
|
| node->part_variances = NULL;
|
| - vpx_memset(node->split, 0, sizeof(node->split));
|
| switch (bsize) {
|
| case BLOCK_64X64: {
|
| v64x64 *vt = (v64x64 *) data;
|
| @@ -375,18 +371,18 @@
|
| static void fill_variance(int64_t s2, int64_t s, int c, var *v) {
|
| v->sum_square_error = s2;
|
| v->sum_error = s;
|
| - v->count = c;
|
| - if (c > 0)
|
| - v->variance = (int)(256 *
|
| - (v->sum_square_error - v->sum_error * v->sum_error /
|
| - v->count) / v->count);
|
| - else
|
| - v->variance = 0;
|
| + v->log2_count = c;
|
| }
|
|
|
| +static void get_variance(var *v) {
|
| + v->variance = (int)(256 * (v->sum_square_error -
|
| + ((v->sum_error * v->sum_error) >> v->log2_count)) >> v->log2_count);
|
| +}
|
| +
|
| void sum_2_variances(const var *a, const var *b, var *r) {
|
| + assert(a->log2_count == b->log2_count);
|
| fill_variance(a->sum_square_error + b->sum_square_error,
|
| - a->sum_error + b->sum_error, a->count + b->count, r);
|
| + a->sum_error + b->sum_error, a->log2_count + 1, r);
|
| }
|
|
|
| static void fill_variance_tree(void *data, BLOCK_SIZE bsize) {
|
| @@ -424,8 +420,9 @@
|
|
|
| if (cm->frame_type == KEY_FRAME) {
|
| bsize_ref = BLOCK_8X8;
|
| - // Choose lower thresholds for key frame variance to favor split.
|
| - threshold_bsize_ref = threshold >> 1;
|
| + // Choose lower thresholds for key frame variance to favor split, but keep
|
| + // threshold for splitting to 4x4 block still fairly high for now.
|
| + threshold_bsize_ref = threshold << 2;
|
| threshold_low = threshold >> 2;
|
| }
|
|
|
| @@ -433,6 +430,7 @@
|
| // variance is below threshold, otherwise split will be selected.
|
| // No check for vert/horiz split as too few samples for variance.
|
| if (bsize == bsize_ref) {
|
| + get_variance(&vt.part_variances->none);
|
| if (mi_col + block_width / 2 < cm->mi_cols &&
|
| mi_row + block_height / 2 < cm->mi_rows &&
|
| vt.part_variances->none.variance < threshold_bsize_ref) {
|
| @@ -441,6 +439,7 @@
|
| }
|
| return 0;
|
| } else if (bsize > bsize_ref) {
|
| + get_variance(&vt.part_variances->none);
|
| // For key frame, for bsize above 32X32, or very high variance, take split.
|
| if (cm->frame_type == KEY_FRAME &&
|
| (bsize > BLOCK_32X32 ||
|
| @@ -454,24 +453,32 @@
|
| set_block_size(cpi, xd, mi_row, mi_col, bsize);
|
| return 1;
|
| }
|
| +
|
| // Check vertical split.
|
| - if (mi_row + block_height / 2 < cm->mi_rows &&
|
| - vt.part_variances->vert[0].variance < threshold_low &&
|
| - vt.part_variances->vert[1].variance < threshold_low) {
|
| - BLOCK_SIZE subsize = get_subsize(bsize, PARTITION_VERT);
|
| - set_block_size(cpi, xd, mi_row, mi_col, subsize);
|
| - set_block_size(cpi, xd, mi_row, mi_col + block_width / 2, subsize);
|
| - return 1;
|
| + if (mi_row + block_height / 2 < cm->mi_rows) {
|
| + get_variance(&vt.part_variances->vert[0]);
|
| + get_variance(&vt.part_variances->vert[1]);
|
| + if (vt.part_variances->vert[0].variance < threshold_low &&
|
| + vt.part_variances->vert[1].variance < threshold_low) {
|
| + BLOCK_SIZE subsize = get_subsize(bsize, PARTITION_VERT);
|
| + set_block_size(cpi, xd, mi_row, mi_col, subsize);
|
| + set_block_size(cpi, xd, mi_row, mi_col + block_width / 2, subsize);
|
| + return 1;
|
| + }
|
| }
|
| // Check horizontal split.
|
| - if (mi_col + block_width / 2 < cm->mi_cols &&
|
| - vt.part_variances->horz[0].variance < threshold_low &&
|
| - vt.part_variances->horz[1].variance < threshold_low) {
|
| - BLOCK_SIZE subsize = get_subsize(bsize, PARTITION_HORZ);
|
| - set_block_size(cpi, xd, mi_row, mi_col, subsize);
|
| - set_block_size(cpi, xd, mi_row + block_height / 2, mi_col, subsize);
|
| - return 1;
|
| + if (mi_col + block_width / 2 < cm->mi_cols) {
|
| + get_variance(&vt.part_variances->horz[0]);
|
| + get_variance(&vt.part_variances->horz[1]);
|
| + if (vt.part_variances->horz[0].variance < threshold_low &&
|
| + vt.part_variances->horz[1].variance < threshold_low) {
|
| + BLOCK_SIZE subsize = get_subsize(bsize, PARTITION_HORZ);
|
| + set_block_size(cpi, xd, mi_row, mi_col, subsize);
|
| + set_block_size(cpi, xd, mi_row + block_height / 2, mi_col, subsize);
|
| + return 1;
|
| + }
|
| }
|
| +
|
| return 0;
|
| }
|
| return 0;
|
| @@ -498,7 +505,6 @@
|
| const struct scale_factors *const sf = &cm->frame_refs[LAST_FRAME - 1].sf;
|
|
|
| vp9_clear_system_state();
|
| - vp9_zero(vt);
|
| set_offsets(cpi, tile, x, mi_row, mi_col, BLOCK_64X64);
|
|
|
| if (xd->mb_to_right_edge < 0)
|
| @@ -574,7 +580,7 @@
|
| // If variance is based on 8x8 downsampling, we stop here and have
|
| // one sample for 8x8 block (so use 1 for count in fill_variance),
|
| // which of course means variance = 0 for 8x8 block.
|
| - fill_variance(sse, sum, 1, &vst->split[k].part_variances.none);
|
| + fill_variance(sse, sum, 0, &vst->split[k].part_variances.none);
|
| } else {
|
| // For key frame, go down to 4x4.
|
| v8x8 *vst2 = &vst->split[k];
|
| @@ -584,7 +590,16 @@
|
| unsigned int sse = 0;
|
| int sum = 0;
|
| if (x4_idx < pixels_wide && y4_idx < pixels_high) {
|
| +#if CONFIG_VP9_HIGHBITDEPTH
|
| + int s_avg;
|
| + if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
|
| + s_avg = vp9_highbd_avg_4x4(s + y4_idx * sp + x4_idx, sp);
|
| + } else {
|
| + s_avg = vp9_avg_4x4(s + y4_idx * sp + x4_idx, sp);
|
| + }
|
| +#else
|
| int s_avg = vp9_avg_4x4(s + y4_idx * sp + x4_idx, sp);
|
| +#endif
|
| // For key frame, reference is set to 128.
|
| sum = s_avg - 128;
|
| sse = sum * sum;
|
| @@ -592,7 +607,7 @@
|
| // If variance is based on 4x4 downsampling, we stop here and have
|
| // one sample for 4x4 block (so use 1 for count in fill_variance),
|
| // which of course means variance = 0 for 4x4 block.
|
| - fill_variance(sse, sum, 1, &vst2->split[m].part_variances.none);
|
| + fill_variance(sse, sum, 0, &vst2->split[m].part_variances.none);
|
| }
|
| }
|
| }
|
| @@ -638,8 +653,6 @@
|
| for (k = 0; k < 4; ++k) {
|
| const int x8_idx = (k & 1);
|
| const int y8_idx = (k >> 1);
|
| - // TODO(marpan): Allow for setting 4x4 partition on key frame.
|
| - /*
|
| if (cm->frame_type == KEY_FRAME) {
|
| if (!set_vt_partitioning(cpi, xd,
|
| &vt.split[i].split[j].split[k],
|
| @@ -652,12 +665,11 @@
|
| BLOCK_4X4);
|
| }
|
| } else {
|
| - */
|
| set_block_size(cpi, xd,
|
| (mi_row + y32_idx + y16_idx + y8_idx),
|
| (mi_col + x32_idx + x16_idx + x8_idx),
|
| BLOCK_8X8);
|
| - // }
|
| + }
|
| }
|
| }
|
| }
|
| @@ -700,7 +712,7 @@
|
| mi_addr->src_mi = mi_addr;
|
|
|
| // If segmentation in use
|
| - if (seg->enabled && output_enabled) {
|
| + if (seg->enabled) {
|
| // For in frame complexity AQ copy the segment id from the segment map.
|
| if (cpi->oxcf.aq_mode == COMPLEXITY_AQ) {
|
| const uint8_t *const map = seg->update_map ? cpi->segmentation_map
|
| @@ -863,6 +875,18 @@
|
| vp9_rd_cost_init(rd_cost);
|
| }
|
|
|
| +static int set_segment_rdmult(VP9_COMP *const cpi,
|
| + MACROBLOCK *const x,
|
| + int8_t segment_id) {
|
| + int segment_qindex;
|
| + VP9_COMMON *const cm = &cpi->common;
|
| + vp9_init_plane_quantizers(cpi, x);
|
| + vp9_clear_system_state();
|
| + segment_qindex = vp9_get_qindex(&cm->seg, segment_id,
|
| + cm->base_qindex);
|
| + return vp9_compute_rd_mult(cpi, segment_qindex + cm->y_dc_delta_q);
|
| +}
|
| +
|
| static void rd_pick_sb_modes(VP9_COMP *cpi,
|
| TileDataEnc *tile_data,
|
| MACROBLOCK *const x,
|
| @@ -919,7 +943,6 @@
|
| if (aq_mode == VARIANCE_AQ) {
|
| const int energy = bsize <= BLOCK_16X16 ? x->mb_energy
|
| : vp9_block_energy(cpi, x, bsize);
|
| - int segment_qindex;
|
| if (cm->frame_type == KEY_FRAME ||
|
| cpi->refresh_alt_ref_frame ||
|
| (cpi->refresh_golden_frame && !cpi->rc.is_src_frame_alt_ref)) {
|
| @@ -929,18 +952,9 @@
|
| : cm->last_frame_seg_map;
|
| mbmi->segment_id = vp9_get_segment_id(cm, map, bsize, mi_row, mi_col);
|
| }
|
| - vp9_init_plane_quantizers(cpi, x);
|
| - vp9_clear_system_state();
|
| - segment_qindex = vp9_get_qindex(&cm->seg, mbmi->segment_id,
|
| - cm->base_qindex);
|
| - x->rdmult = vp9_compute_rd_mult(cpi, segment_qindex + cm->y_dc_delta_q);
|
| + x->rdmult = set_segment_rdmult(cpi, x, mbmi->segment_id);
|
| } else if (aq_mode == COMPLEXITY_AQ) {
|
| - const int mi_offset = mi_row * cm->mi_cols + mi_col;
|
| - unsigned char complexity = cpi->complexity_map[mi_offset];
|
| - const int is_edge = (mi_row <= 1) || (mi_row >= (cm->mi_rows - 2)) ||
|
| - (mi_col <= 1) || (mi_col >= (cm->mi_cols - 2));
|
| - if (!is_edge && (complexity > 128))
|
| - x->rdmult += ((x->rdmult * (complexity - 128)) / 256);
|
| + x->rdmult = set_segment_rdmult(cpi, x, mbmi->segment_id);
|
| } else if (aq_mode == CYCLIC_REFRESH_AQ) {
|
| const uint8_t *const map = cm->seg.update_map ? cpi->segmentation_map
|
| : cm->last_frame_seg_map;
|
| @@ -967,6 +981,16 @@
|
| }
|
| }
|
|
|
| +
|
| + // Examine the resulting rate and for AQ mode 2 make a segment choice.
|
| + if ((rd_cost->rate != INT_MAX) &&
|
| + (aq_mode == COMPLEXITY_AQ) && (bsize >= BLOCK_16X16) &&
|
| + (cm->frame_type == KEY_FRAME ||
|
| + cpi->refresh_alt_ref_frame ||
|
| + (cpi->refresh_golden_frame && !cpi->rc.is_src_frame_alt_ref))) {
|
| + vp9_caq_select_segment(cpi, x, bsize, mi_row, mi_col, rd_cost->rate);
|
| + }
|
| +
|
| x->rdmult = orig_rdmult;
|
|
|
| // TODO(jingning) The rate-distortion optimization flow needs to be
|
| @@ -983,22 +1007,20 @@
|
| const MACROBLOCKD *const xd = &x->e_mbd;
|
| const MODE_INFO *const mi = xd->mi[0].src_mi;
|
| const MB_MODE_INFO *const mbmi = &mi->mbmi;
|
| + const BLOCK_SIZE bsize = mbmi->sb_type;
|
|
|
| if (!frame_is_intra_only(cm)) {
|
| + FRAME_COUNTS *const counts = td->counts;
|
| + const int inter_block = is_inter_block(mbmi);
|
| const int seg_ref_active = vp9_segfeature_active(&cm->seg, mbmi->segment_id,
|
| SEG_LVL_REF_FRAME);
|
| if (!seg_ref_active) {
|
| - FRAME_COUNTS *const counts = td->counts;
|
| - const int inter_block = is_inter_block(mbmi);
|
| -
|
| counts->intra_inter[vp9_get_intra_inter_context(xd)][inter_block]++;
|
| -
|
| // If the segment reference feature is enabled we have only a single
|
| // reference frame allowed for the segment so exclude it from
|
| // the reference frame counts used to work out probabilities.
|
| if (inter_block) {
|
| const MV_REFERENCE_FRAME ref0 = mbmi->ref_frame[0];
|
| -
|
| if (cm->reference_mode == REFERENCE_MODE_SELECT)
|
| counts->comp_inter[vp9_get_reference_mode_context(cm, xd)]
|
| [has_second_ref(mbmi)]++;
|
| @@ -1015,6 +1037,25 @@
|
| }
|
| }
|
| }
|
| + if (inter_block &&
|
| + !vp9_segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP)) {
|
| + const int mode_ctx = mbmi->mode_context[mbmi->ref_frame[0]];
|
| + if (bsize >= BLOCK_8X8) {
|
| + const PREDICTION_MODE mode = mbmi->mode;
|
| + ++counts->inter_mode[mode_ctx][INTER_OFFSET(mode)];
|
| + } else {
|
| + const int num_4x4_w = num_4x4_blocks_wide_lookup[bsize];
|
| + const int num_4x4_h = num_4x4_blocks_high_lookup[bsize];
|
| + int idx, idy;
|
| + for (idy = 0; idy < 2; idy += num_4x4_h) {
|
| + 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;
|
| + ++counts->inter_mode[mode_ctx][INTER_OFFSET(b_mode)];
|
| + }
|
| + }
|
| + }
|
| + }
|
| }
|
| }
|
|
|
| @@ -1164,7 +1205,7 @@
|
| }
|
| break;
|
| default:
|
| - assert("Invalid partition type.");
|
| + assert(0 && "Invalid partition type.");
|
| break;
|
| }
|
|
|
| @@ -1357,11 +1398,8 @@
|
| const int bh = num_8x8_blocks_high_lookup[mi->mbmi.sb_type];
|
| const int x_mis = MIN(bw, cm->mi_cols - mi_col);
|
| const int y_mis = MIN(bh, cm->mi_rows - mi_row);
|
| - MV_REF *const frame_mvs =
|
| - cm->cur_frame->mvs + mi_row * cm->mi_cols + mi_col;
|
| - int w, h;
|
|
|
| - *(xd->mi[0].src_mi) = ctx->mic;
|
| + xd->mi[0] = ctx->mic;
|
| xd->mi[0].src_mi = &xd->mi[0];
|
|
|
| if (seg->enabled && cpi->oxcf.aq_mode) {
|
| @@ -1382,21 +1420,31 @@
|
|
|
| if (is_inter_block(mbmi)) {
|
| vp9_update_mv_count(td);
|
| -
|
| if (cm->interp_filter == SWITCHABLE) {
|
| const int pred_ctx = vp9_get_pred_context_switchable_interp(xd);
|
| ++td->counts->switchable_interp[pred_ctx][mbmi->interp_filter];
|
| }
|
| +
|
| + if (mbmi->sb_type < BLOCK_8X8) {
|
| + mbmi->mv[0].as_int = mi->bmi[3].as_mv[0].as_int;
|
| + mbmi->mv[1].as_int = mi->bmi[3].as_mv[1].as_int;
|
| + }
|
| }
|
|
|
| - for (h = 0; h < y_mis; ++h) {
|
| - MV_REF *const frame_mv = frame_mvs + h * cm->mi_cols;
|
| - for (w = 0; w < x_mis; ++w) {
|
| - MV_REF *const mv = frame_mv + w;
|
| - mv->ref_frame[0] = mi->src_mi->mbmi.ref_frame[0];
|
| - mv->ref_frame[1] = mi->src_mi->mbmi.ref_frame[1];
|
| - mv->mv[0].as_int = mi->src_mi->mbmi.mv[0].as_int;
|
| - mv->mv[1].as_int = mi->src_mi->mbmi.mv[1].as_int;
|
| + if (cm->use_prev_frame_mvs) {
|
| + MV_REF *const frame_mvs =
|
| + cm->cur_frame->mvs + mi_row * cm->mi_cols + mi_col;
|
| + int w, h;
|
| +
|
| + for (h = 0; h < y_mis; ++h) {
|
| + MV_REF *const frame_mv = frame_mvs + h * cm->mi_cols;
|
| + for (w = 0; w < x_mis; ++w) {
|
| + MV_REF *const mv = frame_mv + w;
|
| + mv->ref_frame[0] = mi->src_mi->mbmi.ref_frame[0];
|
| + mv->ref_frame[1] = mi->src_mi->mbmi.ref_frame[1];
|
| + mv->mv[0].as_int = mi->src_mi->mbmi.mv[0].as_int;
|
| + mv->mv[1].as_int = mi->src_mi->mbmi.mv[1].as_int;
|
| + }
|
| }
|
| }
|
|
|
| @@ -1491,7 +1539,7 @@
|
| output_enabled, subsize, pc_tree->split[3]);
|
| break;
|
| default:
|
| - assert("Invalid partition type.");
|
| + assert(0 && "Invalid partition type.");
|
| break;
|
| }
|
|
|
| @@ -1761,14 +1809,6 @@
|
|
|
| if (do_recon) {
|
| int output_enabled = (bsize == BLOCK_64X64);
|
| -
|
| - // Check the projected output rate for this SB against it's target
|
| - // and and if necessary apply a Q delta using segmentation to get
|
| - // closer to the target.
|
| - if ((cpi->oxcf.aq_mode == COMPLEXITY_AQ) && cm->seg.update_map) {
|
| - vp9_select_in_frame_q_segment(cpi, x, bsize, mi_row, mi_col,
|
| - output_enabled, chosen_rdc.rate);
|
| - }
|
| encode_sb(cpi, td, tile_info, tp, mi_row, mi_col, output_enabled, bsize,
|
| pc_tree);
|
| }
|
| @@ -2500,13 +2540,6 @@
|
| if (best_rdc.rate < INT_MAX && best_rdc.dist < INT64_MAX &&
|
| pc_tree->index != 3) {
|
| int output_enabled = (bsize == BLOCK_64X64);
|
| -
|
| - // Check the projected output rate for this SB against it's target
|
| - // and and if necessary apply a Q delta using segmentation to get
|
| - // closer to the target.
|
| - if ((cpi->oxcf.aq_mode == COMPLEXITY_AQ) && cm->seg.update_map)
|
| - vp9_select_in_frame_q_segment(cpi, x, bsize, mi_row, mi_col,
|
| - output_enabled, best_rdc.rate);
|
| encode_sb(cpi, td, tile_info, tp, mi_row, mi_col, output_enabled,
|
| bsize, pc_tree);
|
| }
|
| @@ -2662,6 +2695,15 @@
|
| return cpi->common.tx_mode;
|
| }
|
|
|
| +static void hybrid_intra_mode_search(VP9_COMP *cpi, MACROBLOCK *const x,
|
| + RD_COST *rd_cost, BLOCK_SIZE bsize,
|
| + PICK_MODE_CONTEXT *ctx) {
|
| + if (bsize < BLOCK_16X16)
|
| + vp9_rd_pick_intra_mode_sb(cpi, x, rd_cost, bsize, ctx, INT64_MAX);
|
| + else
|
| + vp9_pick_intra_mode(cpi, x, rd_cost, bsize, ctx);
|
| +}
|
| +
|
| static void nonrd_pick_sb_modes(VP9_COMP *cpi,
|
| TileDataEnc *tile_data, MACROBLOCK *const x,
|
| int mi_row, int mi_col, RD_COST *rd_cost,
|
| @@ -2679,12 +2721,15 @@
|
| x->rdmult = vp9_cyclic_refresh_get_rdmult(cpi->cyclic_refresh);
|
|
|
| if (cm->frame_type == KEY_FRAME)
|
| - vp9_pick_intra_mode(cpi, x, rd_cost, bsize, ctx);
|
| + hybrid_intra_mode_search(cpi, x, rd_cost, bsize, ctx);
|
| else if (vp9_segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP))
|
| set_mode_info_seg_skip(x, cm->tx_mode, rd_cost, bsize);
|
| - else
|
| + else if (bsize >= BLOCK_8X8)
|
| vp9_pick_inter_mode(cpi, x, tile_data, mi_row, mi_col,
|
| rd_cost, bsize, ctx);
|
| + else
|
| + vp9_pick_inter_mode_sub8x8(cpi, x, tile_data, mi_row, mi_col,
|
| + rd_cost, bsize, ctx);
|
|
|
| duplicate_mode_info_in_sb(cm, xd, mi_row, mi_col, bsize);
|
|
|
| @@ -2710,27 +2755,27 @@
|
|
|
| switch (partition) {
|
| case PARTITION_NONE:
|
| - set_modeinfo_offsets(cm, xd, mi_row, mi_col);
|
| + set_mode_info_offsets(cm, xd, mi_row, mi_col);
|
| *(xd->mi[0].src_mi) = pc_tree->none.mic;
|
| duplicate_mode_info_in_sb(cm, xd, mi_row, mi_col, bsize);
|
| break;
|
| case PARTITION_VERT:
|
| - set_modeinfo_offsets(cm, xd, mi_row, mi_col);
|
| + set_mode_info_offsets(cm, xd, mi_row, mi_col);
|
| *(xd->mi[0].src_mi) = pc_tree->vertical[0].mic;
|
| duplicate_mode_info_in_sb(cm, xd, mi_row, mi_col, bsize);
|
|
|
| if (mi_col + hbs < cm->mi_cols) {
|
| - set_modeinfo_offsets(cm, xd, mi_row, mi_col + hbs);
|
| + set_mode_info_offsets(cm, xd, mi_row, mi_col + hbs);
|
| *(xd->mi[0].src_mi) = pc_tree->vertical[1].mic;
|
| duplicate_mode_info_in_sb(cm, xd, mi_row, mi_col + hbs, bsize);
|
| }
|
| break;
|
| case PARTITION_HORZ:
|
| - set_modeinfo_offsets(cm, xd, mi_row, mi_col);
|
| + set_mode_info_offsets(cm, xd, mi_row, mi_col);
|
| *(xd->mi[0].src_mi) = pc_tree->horizontal[0].mic;
|
| duplicate_mode_info_in_sb(cm, xd, mi_row, mi_col, bsize);
|
| if (mi_row + hbs < cm->mi_rows) {
|
| - set_modeinfo_offsets(cm, xd, mi_row + hbs, mi_col);
|
| + set_mode_info_offsets(cm, xd, mi_row + hbs, mi_col);
|
| *(xd->mi[0].src_mi) = pc_tree->horizontal[1].mic;
|
| duplicate_mode_info_in_sb(cm, xd, mi_row + hbs, mi_col, bsize);
|
| }
|
| @@ -2775,7 +2820,6 @@
|
| int do_recon, int64_t best_rd,
|
| PC_TREE *pc_tree) {
|
| const SPEED_FEATURES *const sf = &cpi->sf;
|
| - const VP9EncoderConfig *const oxcf = &cpi->oxcf;
|
| VP9_COMMON *const cm = &cpi->common;
|
| TileInfo *const tile_info = &tile_data->tile_info;
|
| MACROBLOCK *const x = &td->mb;
|
| @@ -3007,14 +3051,6 @@
|
|
|
| if (best_rdc.rate < INT_MAX && best_rdc.dist < INT64_MAX && do_recon) {
|
| int output_enabled = (bsize == BLOCK_64X64);
|
| -
|
| - // Check the projected output rate for this SB against it's target
|
| - // and and if necessary apply a Q delta using segmentation to get
|
| - // closer to the target.
|
| - if ((oxcf->aq_mode == COMPLEXITY_AQ) && cm->seg.update_map) {
|
| - vp9_select_in_frame_q_segment(cpi, x, bsize, mi_row, mi_col,
|
| - output_enabled, best_rdc.rate);
|
| - }
|
| encode_sb_rt(cpi, td, tile_info, tp, mi_row, mi_col, output_enabled,
|
| bsize, pc_tree);
|
| }
|
| @@ -3105,7 +3141,7 @@
|
| if (mi_row + hbs < cm->mi_rows) {
|
| pc_tree->horizontal[1].pred_pixel_ready = 1;
|
| nonrd_pick_sb_modes(cpi, tile_data, x, mi_row + hbs, mi_col,
|
| - &this_rdc, subsize, &pc_tree->horizontal[0]);
|
| + &this_rdc, subsize, &pc_tree->horizontal[1]);
|
| pc_tree->horizontal[1].mic.mbmi = xd->mi[0].src_mi->mbmi;
|
| pc_tree->horizontal[1].skip_txfm[0] = x->skip_txfm[0];
|
| pc_tree->horizontal[1].skip = x->skip;
|
| @@ -3147,7 +3183,7 @@
|
| }
|
| break;
|
| default:
|
| - assert("Invalid partition type.");
|
| + assert(0 && "Invalid partition type.");
|
| break;
|
| }
|
| }
|
| @@ -3164,7 +3200,7 @@
|
| TOKENEXTRA **tp,
|
| int mi_row, int mi_col,
|
| BLOCK_SIZE bsize, int output_enabled,
|
| - RD_COST *rd_cost, PC_TREE *pc_tree) {
|
| + RD_COST *dummy_cost, PC_TREE *pc_tree) {
|
| VP9_COMMON *const cm = &cpi->common;
|
| TileInfo *tile_info = &tile_data->tile_info;
|
| MACROBLOCK *const x = &td->mb;
|
| @@ -3173,9 +3209,7 @@
|
| const int mis = cm->mi_stride;
|
| PARTITION_TYPE partition;
|
| BLOCK_SIZE subsize;
|
| - RD_COST this_rdc;
|
|
|
| - vp9_rd_cost_reset(&this_rdc);
|
| if (mi_row >= cm->mi_rows || mi_col >= cm->mi_cols)
|
| return;
|
|
|
| @@ -3190,7 +3224,7 @@
|
| switch (partition) {
|
| case PARTITION_NONE:
|
| pc_tree->none.pred_pixel_ready = 1;
|
| - nonrd_pick_sb_modes(cpi, tile_data, x, mi_row, mi_col, rd_cost,
|
| + nonrd_pick_sb_modes(cpi, tile_data, x, mi_row, mi_col, dummy_cost,
|
| subsize, &pc_tree->none);
|
| pc_tree->none.mic.mbmi = xd->mi[0].src_mi->mbmi;
|
| pc_tree->none.skip_txfm[0] = x->skip_txfm[0];
|
| @@ -3200,7 +3234,7 @@
|
| break;
|
| case PARTITION_VERT:
|
| pc_tree->vertical[0].pred_pixel_ready = 1;
|
| - nonrd_pick_sb_modes(cpi, tile_data, x, mi_row, mi_col, rd_cost,
|
| + nonrd_pick_sb_modes(cpi, tile_data, x, mi_row, mi_col, dummy_cost,
|
| subsize, &pc_tree->vertical[0]);
|
| pc_tree->vertical[0].mic.mbmi = xd->mi[0].src_mi->mbmi;
|
| pc_tree->vertical[0].skip_txfm[0] = x->skip_txfm[0];
|
| @@ -3207,26 +3241,20 @@
|
| pc_tree->vertical[0].skip = x->skip;
|
| encode_b_rt(cpi, td, tile_info, tp, mi_row, mi_col, output_enabled,
|
| subsize, &pc_tree->vertical[0]);
|
| - if (mi_col + hbs < cm->mi_cols) {
|
| + if (mi_col + hbs < cm->mi_cols && bsize > BLOCK_8X8) {
|
| pc_tree->vertical[1].pred_pixel_ready = 1;
|
| nonrd_pick_sb_modes(cpi, tile_data, x, mi_row, mi_col + hbs,
|
| - &this_rdc, subsize, &pc_tree->vertical[1]);
|
| + dummy_cost, subsize, &pc_tree->vertical[1]);
|
| pc_tree->vertical[1].mic.mbmi = xd->mi[0].src_mi->mbmi;
|
| pc_tree->vertical[1].skip_txfm[0] = x->skip_txfm[0];
|
| pc_tree->vertical[1].skip = x->skip;
|
| encode_b_rt(cpi, td, tile_info, tp, mi_row, mi_col + hbs,
|
| output_enabled, subsize, &pc_tree->vertical[1]);
|
| -
|
| - if (this_rdc.rate != INT_MAX && this_rdc.dist != INT64_MAX &&
|
| - rd_cost->rate != INT_MAX && rd_cost->dist != INT64_MAX) {
|
| - rd_cost->rate += this_rdc.rate;
|
| - rd_cost->dist += this_rdc.dist;
|
| - }
|
| }
|
| break;
|
| case PARTITION_HORZ:
|
| pc_tree->horizontal[0].pred_pixel_ready = 1;
|
| - nonrd_pick_sb_modes(cpi, tile_data, x, mi_row, mi_col, rd_cost,
|
| + nonrd_pick_sb_modes(cpi, tile_data, x, mi_row, mi_col, dummy_cost,
|
| subsize, &pc_tree->horizontal[0]);
|
| pc_tree->horizontal[0].mic.mbmi = xd->mi[0].src_mi->mbmi;
|
| pc_tree->horizontal[0].skip_txfm[0] = x->skip_txfm[0];
|
| @@ -3234,55 +3262,41 @@
|
| encode_b_rt(cpi, td, tile_info, tp, mi_row, mi_col, output_enabled,
|
| subsize, &pc_tree->horizontal[0]);
|
|
|
| - if (mi_row + hbs < cm->mi_rows) {
|
| + if (mi_row + hbs < cm->mi_rows && bsize > BLOCK_8X8) {
|
| pc_tree->horizontal[1].pred_pixel_ready = 1;
|
| nonrd_pick_sb_modes(cpi, tile_data, x, mi_row + hbs, mi_col,
|
| - &this_rdc, subsize, &pc_tree->horizontal[0]);
|
| + dummy_cost, subsize, &pc_tree->horizontal[1]);
|
| pc_tree->horizontal[1].mic.mbmi = xd->mi[0].src_mi->mbmi;
|
| pc_tree->horizontal[1].skip_txfm[0] = x->skip_txfm[0];
|
| pc_tree->horizontal[1].skip = x->skip;
|
| encode_b_rt(cpi, td, tile_info, tp, mi_row + hbs, mi_col,
|
| output_enabled, subsize, &pc_tree->horizontal[1]);
|
| -
|
| - if (this_rdc.rate != INT_MAX && this_rdc.dist != INT64_MAX &&
|
| - rd_cost->rate != INT_MAX && rd_cost->dist != INT64_MAX) {
|
| - rd_cost->rate += this_rdc.rate;
|
| - rd_cost->dist += this_rdc.dist;
|
| - }
|
| }
|
| break;
|
| case PARTITION_SPLIT:
|
| subsize = get_subsize(bsize, PARTITION_SPLIT);
|
| - nonrd_use_partition(cpi, td, tile_data, mi, tp, mi_row, mi_col,
|
| - subsize, output_enabled, rd_cost,
|
| - pc_tree->split[0]);
|
| - nonrd_use_partition(cpi, td, tile_data, mi + hbs, tp,
|
| - mi_row, mi_col + hbs, subsize, output_enabled,
|
| - &this_rdc, pc_tree->split[1]);
|
| - if (this_rdc.rate != INT_MAX && this_rdc.dist != INT64_MAX &&
|
| - rd_cost->rate != INT_MAX && rd_cost->dist != INT64_MAX) {
|
| - rd_cost->rate += this_rdc.rate;
|
| - rd_cost->dist += this_rdc.dist;
|
| + if (bsize == BLOCK_8X8) {
|
| + nonrd_pick_sb_modes(cpi, tile_data, x, mi_row, mi_col, dummy_cost,
|
| + subsize, pc_tree->leaf_split[0]);
|
| + encode_b_rt(cpi, td, tile_info, tp, mi_row, mi_col,
|
| + output_enabled, subsize, pc_tree->leaf_split[0]);
|
| + } else {
|
| + nonrd_use_partition(cpi, td, tile_data, mi, tp, mi_row, mi_col,
|
| + subsize, output_enabled, dummy_cost,
|
| + pc_tree->split[0]);
|
| + nonrd_use_partition(cpi, td, tile_data, mi + hbs, tp,
|
| + mi_row, mi_col + hbs, subsize, output_enabled,
|
| + dummy_cost, pc_tree->split[1]);
|
| + nonrd_use_partition(cpi, td, tile_data, mi + hbs * mis, tp,
|
| + mi_row + hbs, mi_col, subsize, output_enabled,
|
| + dummy_cost, pc_tree->split[2]);
|
| + nonrd_use_partition(cpi, td, tile_data, mi + hbs * mis + hbs, tp,
|
| + mi_row + hbs, mi_col + hbs, subsize, output_enabled,
|
| + dummy_cost, pc_tree->split[3]);
|
| }
|
| - nonrd_use_partition(cpi, td, tile_data, mi + hbs * mis, tp,
|
| - mi_row + hbs, mi_col, subsize, output_enabled,
|
| - &this_rdc, pc_tree->split[2]);
|
| - if (this_rdc.rate != INT_MAX && this_rdc.dist != INT64_MAX &&
|
| - rd_cost->rate != INT_MAX && rd_cost->dist != INT64_MAX) {
|
| - rd_cost->rate += this_rdc.rate;
|
| - rd_cost->dist += this_rdc.dist;
|
| - }
|
| - nonrd_use_partition(cpi, td, tile_data, mi + hbs * mis + hbs, tp,
|
| - mi_row + hbs, mi_col + hbs, subsize, output_enabled,
|
| - &this_rdc, pc_tree->split[3]);
|
| - if (this_rdc.rate != INT_MAX && this_rdc.dist != INT64_MAX &&
|
| - rd_cost->rate != INT_MAX && rd_cost->dist != INT64_MAX) {
|
| - rd_cost->rate += this_rdc.rate;
|
| - rd_cost->dist += this_rdc.dist;
|
| - }
|
| break;
|
| default:
|
| - assert("Invalid partition type.");
|
| + assert(0 && "Invalid partition type.");
|
| break;
|
| }
|
|
|
| @@ -3320,6 +3334,10 @@
|
| // Set the partition type of the 64X64 block
|
| switch (sf->partition_search_type) {
|
| case VAR_BASED_PARTITION:
|
| + // TODO(jingning, marpan): The mode decision and encoding process
|
| + // support both intra and inter sub8x8 block coding for RTC mode.
|
| + // Tune the thresholds accordingly to use sub8x8 block coding for
|
| + // coding performance improvement.
|
| choose_partitioning(cpi, tile_info, x, mi_row, mi_col);
|
| nonrd_use_partition(cpi, td, tile_data, mi, tp, mi_row, mi_col,
|
| BLOCK_64X64, 1, &dummy_rdc, td->pc_root);
|
| @@ -3488,7 +3506,7 @@
|
| cm->show_frame;
|
| }
|
|
|
| -static void init_tile_data(VP9_COMP *cpi) {
|
| +void vp9_init_tile_data(VP9_COMP *cpi) {
|
| VP9_COMMON *const cm = &cpi->common;
|
| const int tile_cols = 1 << cm->log2_tile_cols;
|
| const int tile_rows = 1 << cm->log2_tile_rows;
|
| @@ -3526,6 +3544,29 @@
|
| }
|
| }
|
|
|
| +void vp9_encode_tile(VP9_COMP *cpi, ThreadData *td,
|
| + int tile_row, int tile_col) {
|
| + VP9_COMMON *const cm = &cpi->common;
|
| + const int tile_cols = 1 << cm->log2_tile_cols;
|
| + TileDataEnc *this_tile =
|
| + &cpi->tile_data[tile_row * tile_cols + tile_col];
|
| + const TileInfo * const tile_info = &this_tile->tile_info;
|
| + TOKENEXTRA *tok = cpi->tile_tok[tile_row][tile_col];
|
| + int mi_row;
|
| +
|
| + for (mi_row = tile_info->mi_row_start; mi_row < tile_info->mi_row_end;
|
| + mi_row += MI_BLOCK_SIZE) {
|
| + if (cpi->sf.use_nonrd_pick_mode)
|
| + encode_nonrd_sb_row(cpi, td, this_tile, mi_row, &tok);
|
| + else
|
| + encode_rd_sb_row(cpi, td, this_tile, mi_row, &tok);
|
| + }
|
| + cpi->tok_count[tile_row][tile_col] =
|
| + (unsigned int)(tok - cpi->tile_tok[tile_row][tile_col]);
|
| + assert(tok - cpi->tile_tok[tile_row][tile_col] <=
|
| + allocated_tokens(*tile_info));
|
| +}
|
| +
|
| static void encode_tiles(VP9_COMP *cpi) {
|
| VP9_COMMON *const cm = &cpi->common;
|
| const int tile_cols = 1 << cm->log2_tile_cols;
|
| @@ -3532,30 +3573,11 @@
|
| const int tile_rows = 1 << cm->log2_tile_rows;
|
| int tile_col, tile_row;
|
|
|
| - init_tile_data(cpi);
|
| + vp9_init_tile_data(cpi);
|
|
|
| - for (tile_row = 0; tile_row < tile_rows; ++tile_row) {
|
| - for (tile_col = 0; tile_col < tile_cols; ++tile_col) {
|
| - const TileInfo * const tile_info =
|
| - &cpi->tile_data[tile_row * tile_cols + tile_col].tile_info;
|
| - TOKENEXTRA *tok = cpi->tile_tok[tile_row][tile_col];
|
| - int mi_row;
|
| - TileDataEnc *this_tile =
|
| - &cpi->tile_data[tile_row * tile_cols + tile_col];
|
| -
|
| - for (mi_row = tile_info->mi_row_start; mi_row < tile_info->mi_row_end;
|
| - mi_row += MI_BLOCK_SIZE) {
|
| - if (cpi->sf.use_nonrd_pick_mode)
|
| - encode_nonrd_sb_row(cpi, &cpi->td, this_tile, mi_row, &tok);
|
| - else
|
| - encode_rd_sb_row(cpi, &cpi->td, this_tile, mi_row, &tok);
|
| - }
|
| - cpi->tok_count[tile_row][tile_col] =
|
| - (unsigned int)(tok - cpi->tile_tok[tile_row][tile_col]);
|
| - assert(tok - cpi->tile_tok[tile_row][tile_col] <=
|
| - allocated_tokens(*tile_info));
|
| - }
|
| - }
|
| + for (tile_row = 0; tile_row < tile_rows; ++tile_row)
|
| + for (tile_col = 0; tile_col < tile_cols; ++tile_col)
|
| + vp9_encode_tile(cpi, &cpi->td, tile_row, tile_col);
|
| }
|
|
|
| #if CONFIG_FP_MB_STATS
|
| @@ -3604,6 +3626,7 @@
|
| cm->tx_mode = ALLOW_16X16;
|
| }
|
|
|
| +
|
| #if CONFIG_VP9_HIGHBITDEPTH
|
| if (cm->use_highbitdepth)
|
| x->fwd_txm4x4 = xd->lossless ? vp9_highbd_fwht4x4 : vp9_highbd_fdct4x4;
|
| @@ -3619,7 +3642,6 @@
|
| if (xd->lossless) {
|
| x->optimize = 0;
|
| cm->lf.filter_level = 0;
|
| - cpi->zbin_mode_boost_enabled = 0;
|
| }
|
|
|
| vp9_frame_init_quantizer(cpi);
|
| @@ -3627,12 +3649,15 @@
|
| vp9_initialize_rd_consts(cpi);
|
| vp9_initialize_me_consts(cpi, cm->base_qindex);
|
| init_encode_frame_mb_context(cpi);
|
| - set_prev_mi(cm);
|
| cm->use_prev_frame_mvs = !cm->error_resilient_mode &&
|
| cm->width == cm->last_width &&
|
| cm->height == cm->last_height &&
|
| !cm->intra_only &&
|
| cm->last_show_frame;
|
| + // Special case: set prev_mi to NULL when the previous mode info
|
| + // context cannot be used.
|
| + cm->prev_mi = cm->use_prev_frame_mvs ?
|
| + cm->prev_mip + cm->mi_stride + 1 : NULL;
|
|
|
| x->quant_fp = cpi->sf.use_quant_fp;
|
| vp9_zero(x->skip_txfm);
|
| @@ -3667,7 +3692,11 @@
|
| }
|
| #endif
|
|
|
| - encode_tiles(cpi);
|
| + // If allowed, encoding tiles in parallel with one thread handling one tile.
|
| + if (MIN(cpi->oxcf.max_threads, 1 << cm->log2_tile_cols) > 1)
|
| + vp9_encode_tiles_mt(cpi);
|
| + else
|
| + encode_tiles(cpi);
|
|
|
| vpx_usec_timer_mark(&emr_timer);
|
| cpi->time_encode_sb_row += vpx_usec_timer_elapsed(&emr_timer);
|
| @@ -3716,9 +3745,9 @@
|
| cm->ref_frame_sign_bias[GOLDEN_FRAME]) ||
|
| (cm->ref_frame_sign_bias[ALTREF_FRAME] ==
|
| cm->ref_frame_sign_bias[LAST_FRAME])) {
|
| - cm->allow_comp_inter_inter = 0;
|
| + cpi->allow_comp_inter_inter = 0;
|
| } else {
|
| - cm->allow_comp_inter_inter = 1;
|
| + cpi->allow_comp_inter_inter = 1;
|
| cm->comp_fixed_ref = ALTREF_FRAME;
|
| cm->comp_var_ref[0] = LAST_FRAME;
|
| cm->comp_var_ref[1] = GOLDEN_FRAME;
|
| @@ -3742,7 +3771,7 @@
|
| const int is_alt_ref = frame_type == ALTREF_FRAME;
|
|
|
| /* prediction (compound, single or hybrid) mode selection */
|
| - if (is_alt_ref || !cm->allow_comp_inter_inter)
|
| + if (is_alt_ref || !cpi->allow_comp_inter_inter)
|
| cm->reference_mode = SINGLE_REFERENCE;
|
| else if (mode_thrs[COMPOUND_REFERENCE] > mode_thrs[SINGLE_REFERENCE] &&
|
| mode_thrs[COMPOUND_REFERENCE] >
|
| @@ -3852,24 +3881,6 @@
|
| ++counts->uv_mode[y_mode][uv_mode];
|
| }
|
|
|
| -static int get_zbin_mode_boost(const MB_MODE_INFO *mbmi, int enabled) {
|
| - if (enabled) {
|
| - if (is_inter_block(mbmi)) {
|
| - if (mbmi->mode == ZEROMV) {
|
| - return mbmi->ref_frame[0] != LAST_FRAME ? GF_ZEROMV_ZBIN_BOOST
|
| - : LF_ZEROMV_ZBIN_BOOST;
|
| - } else {
|
| - return mbmi->sb_type < BLOCK_8X8 ? SPLIT_MV_ZBIN_BOOST
|
| - : MV_ZBIN_BOOST;
|
| - }
|
| - } else {
|
| - return INTRA_ZBIN_BOOST;
|
| - }
|
| - } else {
|
| - return 0;
|
| - }
|
| -}
|
| -
|
| static void encode_superblock(VP9_COMP *cpi, ThreadData *td,
|
| TOKENEXTRA **t, int output_enabled,
|
| int mi_row, int mi_col, BLOCK_SIZE bsize,
|
| @@ -3905,12 +3916,6 @@
|
|
|
| set_ref_ptrs(cm, xd, mbmi->ref_frame[0], mbmi->ref_frame[1]);
|
|
|
| - // Experimental code. Special case for gf and arf zeromv modes.
|
| - // Increase zbin size to suppress noise
|
| - cpi->zbin_mode_boost = get_zbin_mode_boost(mbmi,
|
| - cpi->zbin_mode_boost_enabled);
|
| - vp9_update_zbin_extra(cpi, x);
|
| -
|
| if (!is_inter_block(mbmi)) {
|
| int plane;
|
| mbmi->skip = 1;
|
|
|