Commit eee201c2 authored by Jingning Han's avatar Jingning Han
Browse files

Tile based adaptive mode search in RD loop

Make the spatially adaptive mode search in rate-distortion
optimization loop inter tile independent. Experiments suggest that
this does not significantly change the coding staticstics.

Single tile, speed 3:
pedestrian_area 1080p 1500 kbps
59192 b/f, 40.611 dB, 101689 ms

blue_sky 1080p 1500 kbps
58505 b/f, 36.347 dB, 62458 ms

mobile_cal 720p 1000 kbps
13335 b/f, 35.646 dB, 45655 ms

as compared to 4 column tiles, speed 3:
pedestrian_area 1080p 1500 kbps
59329 b/f, 40.597 dB, 101917 ms

blue_sky 1080p 1500 kbps
58712 b/f, 36.320 dB, 62693 ms

mobile_cal 720p 1000 kbps
13191 b/f, 35.485 dB, 45319 ms

Change-Id: I35c6e1e0a859fece8f4145dec28623cbc6a12325
parent 9363425d
...@@ -781,6 +781,7 @@ static void set_mode_info_seg_skip(MACROBLOCK *x, TX_MODE tx_mode, ...@@ -781,6 +781,7 @@ static void set_mode_info_seg_skip(MACROBLOCK *x, TX_MODE tx_mode,
} }
static void rd_pick_sb_modes(VP9_COMP *cpi, const TileInfo *const tile, static void rd_pick_sb_modes(VP9_COMP *cpi, const TileInfo *const tile,
TileDataEnc *tile_data,
int mi_row, int mi_col, RD_COST *rd_cost, int mi_row, int mi_col, RD_COST *rd_cost,
BLOCK_SIZE bsize, PICK_MODE_CONTEXT *ctx, BLOCK_SIZE bsize, PICK_MODE_CONTEXT *ctx,
int64_t best_rd) { int64_t best_rd) {
...@@ -872,14 +873,14 @@ static void rd_pick_sb_modes(VP9_COMP *cpi, const TileInfo *const tile, ...@@ -872,14 +873,14 @@ static void rd_pick_sb_modes(VP9_COMP *cpi, const TileInfo *const tile,
} else { } else {
if (bsize >= BLOCK_8X8) { if (bsize >= BLOCK_8X8) {
if (vp9_segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP)) if (vp9_segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP))
vp9_rd_pick_inter_mode_sb_seg_skip(cpi, x, rd_cost, bsize, vp9_rd_pick_inter_mode_sb_seg_skip(cpi, tile_data, x, rd_cost, bsize,
ctx, best_rd); ctx, best_rd);
else else
vp9_rd_pick_inter_mode_sb(cpi, x, tile, mi_row, mi_col, vp9_rd_pick_inter_mode_sb(cpi, tile_data, x, tile, mi_row, mi_col,
rd_cost, bsize, ctx, best_rd); rd_cost, bsize, ctx, best_rd);
} else { } else {
vp9_rd_pick_inter_mode_sub8x8(cpi, x, tile, mi_row, mi_col, rd_cost, vp9_rd_pick_inter_mode_sub8x8(cpi, tile_data, x, tile, mi_row, mi_col,
bsize, ctx, best_rd); rd_cost, bsize, ctx, best_rd);
} }
} }
...@@ -1423,6 +1424,7 @@ static void encode_sb_rt(VP9_COMP *cpi, const TileInfo *const tile, ...@@ -1423,6 +1424,7 @@ static void encode_sb_rt(VP9_COMP *cpi, const TileInfo *const tile,
} }
static void rd_use_partition(VP9_COMP *cpi, const TileInfo *const tile, static void rd_use_partition(VP9_COMP *cpi, const TileInfo *const tile,
TileDataEnc *tile_data,
MODE_INFO *mi_8x8, TOKENEXTRA **tp, MODE_INFO *mi_8x8, TOKENEXTRA **tp,
int mi_row, int mi_col, int mi_row, int mi_col,
BLOCK_SIZE bsize, int *rate, int64_t *dist, BLOCK_SIZE bsize, int *rate, int64_t *dist,
...@@ -1489,7 +1491,7 @@ static void rd_use_partition(VP9_COMP *cpi, const TileInfo *const tile, ...@@ -1489,7 +1491,7 @@ static void rd_use_partition(VP9_COMP *cpi, const TileInfo *const tile,
mi_row + (mi_step >> 1) < cm->mi_rows && mi_row + (mi_step >> 1) < cm->mi_rows &&
mi_col + (mi_step >> 1) < cm->mi_cols) { mi_col + (mi_step >> 1) < cm->mi_cols) {
pc_tree->partitioning = PARTITION_NONE; pc_tree->partitioning = PARTITION_NONE;
rd_pick_sb_modes(cpi, tile, mi_row, mi_col, &none_rdc, bsize, rd_pick_sb_modes(cpi, tile, tile_data, mi_row, mi_col, &none_rdc, bsize,
ctx, INT64_MAX); ctx, INT64_MAX);
pl = partition_plane_context(xd, mi_row, mi_col, bsize); pl = partition_plane_context(xd, mi_row, mi_col, bsize);
...@@ -1508,11 +1510,11 @@ static void rd_use_partition(VP9_COMP *cpi, const TileInfo *const tile, ...@@ -1508,11 +1510,11 @@ static void rd_use_partition(VP9_COMP *cpi, const TileInfo *const tile,
switch (partition) { switch (partition) {
case PARTITION_NONE: case PARTITION_NONE:
rd_pick_sb_modes(cpi, tile, mi_row, mi_col, &last_part_rdc, rd_pick_sb_modes(cpi, tile, tile_data, mi_row, mi_col, &last_part_rdc,
bsize, ctx, INT64_MAX); bsize, ctx, INT64_MAX);
break; break;
case PARTITION_HORZ: case PARTITION_HORZ:
rd_pick_sb_modes(cpi, tile, mi_row, mi_col, &last_part_rdc, rd_pick_sb_modes(cpi, tile, tile_data, mi_row, mi_col, &last_part_rdc,
subsize, &pc_tree->horizontal[0], subsize, &pc_tree->horizontal[0],
INT64_MAX); INT64_MAX);
if (last_part_rdc.rate != INT_MAX && if (last_part_rdc.rate != INT_MAX &&
...@@ -1522,7 +1524,8 @@ static void rd_use_partition(VP9_COMP *cpi, const TileInfo *const tile, ...@@ -1522,7 +1524,8 @@ static void rd_use_partition(VP9_COMP *cpi, const TileInfo *const tile,
vp9_rd_cost_init(&tmp_rdc); vp9_rd_cost_init(&tmp_rdc);
update_state(cpi, ctx, mi_row, mi_col, subsize, 0); update_state(cpi, ctx, mi_row, mi_col, subsize, 0);
encode_superblock(cpi, tp, 0, mi_row, mi_col, subsize, ctx); encode_superblock(cpi, tp, 0, mi_row, mi_col, subsize, ctx);
rd_pick_sb_modes(cpi, tile, mi_row + (mi_step >> 1), mi_col, &tmp_rdc, rd_pick_sb_modes(cpi, tile, tile_data,
mi_row + (mi_step >> 1), mi_col, &tmp_rdc,
subsize, &pc_tree->horizontal[1], INT64_MAX); subsize, &pc_tree->horizontal[1], INT64_MAX);
if (tmp_rdc.rate == INT_MAX || tmp_rdc.dist == INT64_MAX) { if (tmp_rdc.rate == INT_MAX || tmp_rdc.dist == INT64_MAX) {
vp9_rd_cost_reset(&last_part_rdc); vp9_rd_cost_reset(&last_part_rdc);
...@@ -1534,7 +1537,7 @@ static void rd_use_partition(VP9_COMP *cpi, const TileInfo *const tile, ...@@ -1534,7 +1537,7 @@ static void rd_use_partition(VP9_COMP *cpi, const TileInfo *const tile,
} }
break; break;
case PARTITION_VERT: case PARTITION_VERT:
rd_pick_sb_modes(cpi, tile, mi_row, mi_col, &last_part_rdc, rd_pick_sb_modes(cpi, tile, tile_data, mi_row, mi_col, &last_part_rdc,
subsize, &pc_tree->vertical[0], INT64_MAX); subsize, &pc_tree->vertical[0], INT64_MAX);
if (last_part_rdc.rate != INT_MAX && if (last_part_rdc.rate != INT_MAX &&
bsize >= BLOCK_8X8 && mi_col + (mi_step >> 1) < cm->mi_cols) { bsize >= BLOCK_8X8 && mi_col + (mi_step >> 1) < cm->mi_cols) {
...@@ -1543,7 +1546,8 @@ static void rd_use_partition(VP9_COMP *cpi, const TileInfo *const tile, ...@@ -1543,7 +1546,8 @@ static void rd_use_partition(VP9_COMP *cpi, const TileInfo *const tile,
vp9_rd_cost_init(&tmp_rdc); vp9_rd_cost_init(&tmp_rdc);
update_state(cpi, ctx, mi_row, mi_col, subsize, 0); update_state(cpi, ctx, mi_row, mi_col, subsize, 0);
encode_superblock(cpi, tp, 0, mi_row, mi_col, subsize, ctx); encode_superblock(cpi, tp, 0, mi_row, mi_col, subsize, ctx);
rd_pick_sb_modes(cpi, tile, mi_row, mi_col + (mi_step >> 1), &tmp_rdc, rd_pick_sb_modes(cpi, tile, tile_data,
mi_row, mi_col + (mi_step >> 1), &tmp_rdc,
subsize, &pc_tree->vertical[bsize > BLOCK_8X8], subsize, &pc_tree->vertical[bsize > BLOCK_8X8],
INT64_MAX); INT64_MAX);
if (tmp_rdc.rate == INT_MAX || tmp_rdc.dist == INT64_MAX) { if (tmp_rdc.rate == INT_MAX || tmp_rdc.dist == INT64_MAX) {
...@@ -1557,7 +1561,7 @@ static void rd_use_partition(VP9_COMP *cpi, const TileInfo *const tile, ...@@ -1557,7 +1561,7 @@ static void rd_use_partition(VP9_COMP *cpi, const TileInfo *const tile,
break; break;
case PARTITION_SPLIT: case PARTITION_SPLIT:
if (bsize == BLOCK_8X8) { if (bsize == BLOCK_8X8) {
rd_pick_sb_modes(cpi, tile, mi_row, mi_col, &last_part_rdc, rd_pick_sb_modes(cpi, tile, tile_data, mi_row, mi_col, &last_part_rdc,
subsize, pc_tree->leaf_split[0], INT64_MAX); subsize, pc_tree->leaf_split[0], INT64_MAX);
break; break;
} }
...@@ -1573,7 +1577,8 @@ static void rd_use_partition(VP9_COMP *cpi, const TileInfo *const tile, ...@@ -1573,7 +1577,8 @@ static void rd_use_partition(VP9_COMP *cpi, const TileInfo *const tile,
continue; continue;
vp9_rd_cost_init(&tmp_rdc); vp9_rd_cost_init(&tmp_rdc);
rd_use_partition(cpi, tile, mi_8x8 + jj * bss * mis + ii * bss, tp, rd_use_partition(cpi, tile, tile_data,
mi_8x8 + jj * bss * mis + ii * bss, tp,
mi_row + y_idx, mi_col + x_idx, subsize, mi_row + y_idx, mi_col + x_idx, subsize,
&tmp_rdc.rate, &tmp_rdc.dist, &tmp_rdc.rate, &tmp_rdc.dist,
i != 3, pc_tree->split[i]); i != 3, pc_tree->split[i]);
...@@ -1624,7 +1629,8 @@ static void rd_use_partition(VP9_COMP *cpi, const TileInfo *const tile, ...@@ -1624,7 +1629,8 @@ static void rd_use_partition(VP9_COMP *cpi, const TileInfo *const tile,
save_context(cpi, mi_row, mi_col, a, l, sa, sl, bsize); save_context(cpi, mi_row, mi_col, a, l, sa, sl, bsize);
pc_tree->split[i]->partitioning = PARTITION_NONE; pc_tree->split[i]->partitioning = PARTITION_NONE;
rd_pick_sb_modes(cpi, tile, mi_row + y_idx, mi_col + x_idx, &tmp_rdc, rd_pick_sb_modes(cpi, tile, tile_data,
mi_row + y_idx, mi_col + x_idx, &tmp_rdc,
split_subsize, &pc_tree->split[i]->none, INT64_MAX); split_subsize, &pc_tree->split[i]->none, INT64_MAX);
restore_context(cpi, mi_row, mi_col, a, l, sa, sl, bsize); restore_context(cpi, mi_row, mi_col, a, l, sa, sl, bsize);
...@@ -2022,6 +2028,7 @@ static INLINE int get_motion_inconsistency(MOTION_DIRECTION this_mv, ...@@ -2022,6 +2028,7 @@ static INLINE int get_motion_inconsistency(MOTION_DIRECTION this_mv,
// unlikely to be selected depending on previous rate-distortion optimization // unlikely to be selected depending on previous rate-distortion optimization
// results, for encoding speed-up. // results, for encoding speed-up.
static void rd_pick_partition(VP9_COMP *cpi, const TileInfo *const tile, static void rd_pick_partition(VP9_COMP *cpi, const TileInfo *const tile,
TileDataEnc *tile_data,
TOKENEXTRA **tp, int mi_row, int mi_col, TOKENEXTRA **tp, int mi_row, int mi_col,
BLOCK_SIZE bsize, RD_COST *rd_cost, BLOCK_SIZE bsize, RD_COST *rd_cost,
int64_t best_rd, PC_TREE *pc_tree) { int64_t best_rd, PC_TREE *pc_tree) {
...@@ -2159,8 +2166,8 @@ static void rd_pick_partition(VP9_COMP *cpi, const TileInfo *const tile, ...@@ -2159,8 +2166,8 @@ static void rd_pick_partition(VP9_COMP *cpi, const TileInfo *const tile,
// PARTITION_NONE // PARTITION_NONE
if (partition_none_allowed) { if (partition_none_allowed) {
rd_pick_sb_modes(cpi, tile, mi_row, mi_col, &this_rdc, bsize, ctx, rd_pick_sb_modes(cpi, tile, tile_data, mi_row, mi_col,
best_rdc.rdcost); &this_rdc, bsize, ctx, best_rdc.rdcost);
if (this_rdc.rate != INT_MAX) { if (this_rdc.rate != INT_MAX) {
if (bsize >= BLOCK_8X8) { if (bsize >= BLOCK_8X8) {
pl = partition_plane_context(xd, mi_row, mi_col, bsize); pl = partition_plane_context(xd, mi_row, mi_col, bsize);
...@@ -2259,7 +2266,7 @@ static void rd_pick_partition(VP9_COMP *cpi, const TileInfo *const tile, ...@@ -2259,7 +2266,7 @@ static void rd_pick_partition(VP9_COMP *cpi, const TileInfo *const tile,
if (cpi->sf.adaptive_pred_interp_filter && partition_none_allowed) if (cpi->sf.adaptive_pred_interp_filter && partition_none_allowed)
pc_tree->leaf_split[0]->pred_interp_filter = pc_tree->leaf_split[0]->pred_interp_filter =
ctx->mic.mbmi.interp_filter; ctx->mic.mbmi.interp_filter;
rd_pick_sb_modes(cpi, tile, mi_row, mi_col, &sum_rdc, subsize, rd_pick_sb_modes(cpi, tile, tile_data, mi_row, mi_col, &sum_rdc, subsize,
pc_tree->leaf_split[0], best_rdc.rdcost); pc_tree->leaf_split[0], best_rdc.rdcost);
if (sum_rdc.rate == INT_MAX) if (sum_rdc.rate == INT_MAX)
sum_rdc.rdcost = INT64_MAX; sum_rdc.rdcost = INT64_MAX;
...@@ -2275,7 +2282,8 @@ static void rd_pick_partition(VP9_COMP *cpi, const TileInfo *const tile, ...@@ -2275,7 +2282,8 @@ static void rd_pick_partition(VP9_COMP *cpi, const TileInfo *const tile,
load_pred_mv(x, ctx); load_pred_mv(x, ctx);
pc_tree->split[i]->index = i; pc_tree->split[i]->index = i;
rd_pick_partition(cpi, tile, tp, mi_row + y_idx, mi_col + x_idx, rd_pick_partition(cpi, tile, tile_data, tp,
mi_row + y_idx, mi_col + x_idx,
subsize, &this_rdc, subsize, &this_rdc,
best_rdc.rdcost - sum_rdc.rdcost, pc_tree->split[i]); best_rdc.rdcost - sum_rdc.rdcost, pc_tree->split[i]);
...@@ -2318,7 +2326,7 @@ static void rd_pick_partition(VP9_COMP *cpi, const TileInfo *const tile, ...@@ -2318,7 +2326,7 @@ static void rd_pick_partition(VP9_COMP *cpi, const TileInfo *const tile,
partition_none_allowed) partition_none_allowed)
pc_tree->horizontal[0].pred_interp_filter = pc_tree->horizontal[0].pred_interp_filter =
ctx->mic.mbmi.interp_filter; ctx->mic.mbmi.interp_filter;
rd_pick_sb_modes(cpi, tile, mi_row, mi_col, &sum_rdc, subsize, rd_pick_sb_modes(cpi, tile, tile_data, mi_row, mi_col, &sum_rdc, subsize,
&pc_tree->horizontal[0], best_rdc.rdcost); &pc_tree->horizontal[0], best_rdc.rdcost);
if (sum_rdc.rdcost < best_rdc.rdcost && mi_row + mi_step < cm->mi_rows && if (sum_rdc.rdcost < best_rdc.rdcost && mi_row + mi_step < cm->mi_rows &&
...@@ -2333,8 +2341,8 @@ static void rd_pick_partition(VP9_COMP *cpi, const TileInfo *const tile, ...@@ -2333,8 +2341,8 @@ static void rd_pick_partition(VP9_COMP *cpi, const TileInfo *const tile,
partition_none_allowed) partition_none_allowed)
pc_tree->horizontal[1].pred_interp_filter = pc_tree->horizontal[1].pred_interp_filter =
ctx->mic.mbmi.interp_filter; ctx->mic.mbmi.interp_filter;
rd_pick_sb_modes(cpi, tile, mi_row + mi_step, mi_col, &this_rdc, rd_pick_sb_modes(cpi, tile, tile_data, mi_row + mi_step, mi_col,
subsize, &pc_tree->horizontal[1], &this_rdc, subsize, &pc_tree->horizontal[1],
best_rdc.rdcost - sum_rdc.rdcost); best_rdc.rdcost - sum_rdc.rdcost);
if (this_rdc.rate == INT_MAX) { if (this_rdc.rate == INT_MAX) {
sum_rdc.rdcost = INT64_MAX; sum_rdc.rdcost = INT64_MAX;
...@@ -2366,7 +2374,7 @@ static void rd_pick_partition(VP9_COMP *cpi, const TileInfo *const tile, ...@@ -2366,7 +2374,7 @@ static void rd_pick_partition(VP9_COMP *cpi, const TileInfo *const tile,
partition_none_allowed) partition_none_allowed)
pc_tree->vertical[0].pred_interp_filter = pc_tree->vertical[0].pred_interp_filter =
ctx->mic.mbmi.interp_filter; ctx->mic.mbmi.interp_filter;
rd_pick_sb_modes(cpi, tile, mi_row, mi_col, &sum_rdc, subsize, rd_pick_sb_modes(cpi, tile, tile_data, mi_row, mi_col, &sum_rdc, subsize,
&pc_tree->vertical[0], best_rdc.rdcost); &pc_tree->vertical[0], best_rdc.rdcost);
if (sum_rdc.rdcost < best_rdc.rdcost && mi_col + mi_step < cm->mi_cols && if (sum_rdc.rdcost < best_rdc.rdcost && mi_col + mi_step < cm->mi_cols &&
bsize > BLOCK_8X8) { bsize > BLOCK_8X8) {
...@@ -2380,7 +2388,8 @@ static void rd_pick_partition(VP9_COMP *cpi, const TileInfo *const tile, ...@@ -2380,7 +2388,8 @@ static void rd_pick_partition(VP9_COMP *cpi, const TileInfo *const tile,
partition_none_allowed) partition_none_allowed)
pc_tree->vertical[1].pred_interp_filter = pc_tree->vertical[1].pred_interp_filter =
ctx->mic.mbmi.interp_filter; ctx->mic.mbmi.interp_filter;
rd_pick_sb_modes(cpi, tile, mi_row, mi_col + mi_step, &this_rdc, subsize, rd_pick_sb_modes(cpi, tile, tile_data, mi_row, mi_col + mi_step,
&this_rdc, subsize,
&pc_tree->vertical[1], best_rdc.rdcost - sum_rdc.rdcost); &pc_tree->vertical[1], best_rdc.rdcost - sum_rdc.rdcost);
if (this_rdc.rate == INT_MAX) { if (this_rdc.rate == INT_MAX) {
sum_rdc.rdcost = INT64_MAX; sum_rdc.rdcost = INT64_MAX;
...@@ -2439,6 +2448,7 @@ static void rd_pick_partition(VP9_COMP *cpi, const TileInfo *const tile, ...@@ -2439,6 +2448,7 @@ static void rd_pick_partition(VP9_COMP *cpi, const TileInfo *const tile,
} }
static void encode_rd_sb_row(VP9_COMP *cpi, const TileInfo *const tile, static void encode_rd_sb_row(VP9_COMP *cpi, const TileInfo *const tile,
TileDataEnc *tile_data,
int mi_row, TOKENEXTRA **tp) { int mi_row, TOKENEXTRA **tp) {
VP9_COMMON *const cm = &cpi->common; VP9_COMMON *const cm = &cpi->common;
MACROBLOCKD *const xd = &cpi->mb.e_mbd; MACROBLOCKD *const xd = &cpi->mb.e_mbd;
...@@ -2480,20 +2490,20 @@ static void encode_rd_sb_row(VP9_COMP *cpi, const TileInfo *const tile, ...@@ -2480,20 +2490,20 @@ static void encode_rd_sb_row(VP9_COMP *cpi, const TileInfo *const tile,
set_offsets(cpi, tile, mi_row, mi_col, BLOCK_64X64); set_offsets(cpi, tile, mi_row, mi_col, BLOCK_64X64);
set_fixed_partitioning(cpi, tile, mi, mi_row, mi_col, set_fixed_partitioning(cpi, tile, mi, mi_row, mi_col,
sf->always_this_block_size); sf->always_this_block_size);
rd_use_partition(cpi, tile, mi, tp, mi_row, mi_col, BLOCK_64X64, rd_use_partition(cpi, tile, tile_data, mi, tp, mi_row, mi_col,
&dummy_rate, &dummy_dist, 1, cpi->pc_root); BLOCK_64X64, &dummy_rate, &dummy_dist, 1, cpi->pc_root);
} else if (cpi->partition_search_skippable_frame) { } else if (cpi->partition_search_skippable_frame) {
BLOCK_SIZE bsize; BLOCK_SIZE bsize;
set_offsets(cpi, tile, mi_row, mi_col, BLOCK_64X64); set_offsets(cpi, tile, mi_row, mi_col, BLOCK_64X64);
bsize = get_rd_var_based_fixed_partition(cpi, mi_row, mi_col); bsize = get_rd_var_based_fixed_partition(cpi, mi_row, mi_col);
set_fixed_partitioning(cpi, tile, mi, mi_row, mi_col, bsize); set_fixed_partitioning(cpi, tile, mi, mi_row, mi_col, bsize);
rd_use_partition(cpi, tile, mi, tp, mi_row, mi_col, BLOCK_64X64, rd_use_partition(cpi, tile, tile_data, mi, tp, mi_row, mi_col,
&dummy_rate, &dummy_dist, 1, cpi->pc_root); BLOCK_64X64, &dummy_rate, &dummy_dist, 1, cpi->pc_root);
} else if (sf->partition_search_type == VAR_BASED_PARTITION && } else if (sf->partition_search_type == VAR_BASED_PARTITION &&
cm->frame_type != KEY_FRAME ) { cm->frame_type != KEY_FRAME ) {
choose_partitioning(cpi, tile, mi_row, mi_col); choose_partitioning(cpi, tile, mi_row, mi_col);
rd_use_partition(cpi, tile, mi, tp, mi_row, mi_col, BLOCK_64X64, rd_use_partition(cpi, tile, tile_data, mi, tp, mi_row, mi_col,
&dummy_rate, &dummy_dist, 1, cpi->pc_root); BLOCK_64X64, &dummy_rate, &dummy_dist, 1, cpi->pc_root);
} else { } else {
// If required set upper and lower partition size limits // If required set upper and lower partition size limits
if (sf->auto_min_max_partition_size) { if (sf->auto_min_max_partition_size) {
...@@ -2502,7 +2512,7 @@ static void encode_rd_sb_row(VP9_COMP *cpi, const TileInfo *const tile, ...@@ -2502,7 +2512,7 @@ static void encode_rd_sb_row(VP9_COMP *cpi, const TileInfo *const tile,
&sf->min_partition_size, &sf->min_partition_size,
&sf->max_partition_size); &sf->max_partition_size);
} }
rd_pick_partition(cpi, tile, tp, mi_row, mi_col, BLOCK_64X64, rd_pick_partition(cpi, tile, tile_data, tp, mi_row, mi_col, BLOCK_64X64,
&dummy_rdc, INT64_MAX, cpi->pc_root); &dummy_rdc, INT64_MAX, cpi->pc_root);
} }
} }
...@@ -3353,8 +3363,18 @@ static int get_skip_encode_frame(const VP9_COMMON *cm) { ...@@ -3353,8 +3363,18 @@ static int get_skip_encode_frame(const VP9_COMMON *cm) {
cm->show_frame; cm->show_frame;
} }
static void tile_data_init(TileDataEnc *tile_data) {
int i, j;
for (i = 0; i < BLOCK_SIZES; ++i) {
for (j = 0; j < MAX_MODES; ++j) {
tile_data->thresh_freq_fact[i][j] = 32;
tile_data->mode_map[i][j] = j;
}
}
}
static void encode_tiles(VP9_COMP *cpi) { static void encode_tiles(VP9_COMP *cpi) {
const VP9_COMMON *const cm = &cpi->common; VP9_COMMON *const cm = &cpi->common;
const int tile_cols = 1 << cm->log2_tile_cols; const int tile_cols = 1 << cm->log2_tile_cols;
const int tile_rows = 1 << cm->log2_tile_rows; const int tile_rows = 1 << cm->log2_tile_rows;
...@@ -3364,6 +3384,14 @@ static void encode_tiles(VP9_COMP *cpi) { ...@@ -3364,6 +3384,14 @@ static void encode_tiles(VP9_COMP *cpi) {
TOKENEXTRA *pre_tok = cpi->tok; TOKENEXTRA *pre_tok = cpi->tok;
int tile_tok = 0; int tile_tok = 0;
if (cpi->tile_data == NULL) {
CHECK_MEM_ERROR(cm, cpi->tile_data,
vpx_malloc(tile_cols * tile_rows * sizeof(*cpi->tile_data)));
for (tile_row = 0; tile_row < tile_rows; ++tile_row)
for (tile_col = 0; tile_col < tile_cols; ++tile_col)
tile_data_init(&cpi->tile_data[tile_row * tile_cols + tile_col]);
}
for (tile_row = 0; tile_row < tile_rows; ++tile_row) { for (tile_row = 0; tile_row < tile_rows; ++tile_row) {
for (tile_col = 0; tile_col < tile_cols; ++tile_col) { for (tile_col = 0; tile_col < tile_cols; ++tile_col) {
vp9_tile_init(&tile[tile_row][tile_col], cm, tile_row, tile_col); vp9_tile_init(&tile[tile_row][tile_col], cm, tile_row, tile_col);
...@@ -3379,13 +3407,15 @@ static void encode_tiles(VP9_COMP *cpi) { ...@@ -3379,13 +3407,15 @@ static void encode_tiles(VP9_COMP *cpi) {
const TileInfo * const ptile = &tile[tile_row][tile_col]; const TileInfo * const ptile = &tile[tile_row][tile_col];
TOKENEXTRA * const old_tok = tok[tile_row][tile_col]; TOKENEXTRA * const old_tok = tok[tile_row][tile_col];
int mi_row; int mi_row;
TileDataEnc *this_tile = &cpi->tile_data[tile_row * tile_cols + tile_col];
for (mi_row = ptile->mi_row_start; mi_row < ptile->mi_row_end; for (mi_row = ptile->mi_row_start; mi_row < ptile->mi_row_end;
mi_row += MI_BLOCK_SIZE) { mi_row += MI_BLOCK_SIZE) {
if (cpi->sf.use_nonrd_pick_mode && !frame_is_intra_only(cm)) if (cpi->sf.use_nonrd_pick_mode && !frame_is_intra_only(cm))
encode_nonrd_sb_row(cpi, ptile, mi_row, &tok[tile_row][tile_col]); encode_nonrd_sb_row(cpi, ptile, mi_row, &tok[tile_row][tile_col]);
else else
encode_rd_sb_row(cpi, ptile, mi_row, &tok[tile_row][tile_col]); encode_rd_sb_row(cpi, ptile, this_tile,
mi_row, &tok[tile_row][tile_col]);
} }
cpi->tok_count[tile_row][tile_col] = cpi->tok_count[tile_row][tile_col] =
(unsigned int)(tok[tile_row][tile_col] - old_tok); (unsigned int)(tok[tile_row][tile_col] - old_tok);
......
...@@ -164,6 +164,8 @@ static void dealloc_compressor_data(VP9_COMP *cpi) { ...@@ -164,6 +164,8 @@ static void dealloc_compressor_data(VP9_COMP *cpi) {
cm->fc = NULL; cm->fc = NULL;
vpx_free(cm->frame_contexts); vpx_free(cm->frame_contexts);
cm->frame_contexts = NULL; cm->frame_contexts = NULL;
vpx_free(cpi->tile_data);
cpi->tile_data = NULL;
// Delete sementation map // Delete sementation map
vpx_free(cpi->segmentation_map); vpx_free(cpi->segmentation_map);
...@@ -1392,6 +1394,7 @@ VP9_COMP *vp9_create_compressor(VP9EncoderConfig *oxcf) { ...@@ -1392,6 +1394,7 @@ VP9_COMP *vp9_create_compressor(VP9EncoderConfig *oxcf) {
cm->current_video_frame = 0; cm->current_video_frame = 0;
cpi->partition_search_skippable_frame = 0; cpi->partition_search_skippable_frame = 0;
cpi->tile_data = NULL;
// Create the encoder segmentation map and set all entries to 0 // Create the encoder segmentation map and set all entries to 0
CHECK_MEM_ERROR(cm, cpi->segmentation_map, CHECK_MEM_ERROR(cm, cpi->segmentation_map,
......
...@@ -223,6 +223,12 @@ static INLINE int is_lossless_requested(const VP9EncoderConfig *cfg) { ...@@ -223,6 +223,12 @@ static INLINE int is_lossless_requested(const VP9EncoderConfig *cfg) {
return cfg->best_allowed_q == 0 && cfg->worst_allowed_q == 0; return cfg->best_allowed_q == 0 && cfg->worst_allowed_q == 0;
} }
// TODO(jingning) All spatially adaptive variables should go to TileDataEnc.
typedef struct TileDataEnc {
int thresh_freq_fact[BLOCK_SIZES][MAX_MODES];
int mode_map[BLOCK_SIZES][MAX_MODES];
} TileDataEnc;
typedef struct VP9_COMP { typedef struct VP9_COMP {
QUANTS quants; QUANTS quants;
MACROBLOCK mb; MACROBLOCK mb;
...@@ -238,6 +244,8 @@ typedef struct VP9_COMP { ...@@ -238,6 +244,8 @@ typedef struct VP9_COMP {
YV12_BUFFER_CONFIG *unscaled_last_source; YV12_BUFFER_CONFIG *unscaled_last_source;
YV12_BUFFER_CONFIG scaled_last_source; YV12_BUFFER_CONFIG scaled_last_source;
TileDataEnc *tile_data;
// For a still frame, this flag is set to 1 to skip partition search. // For a still frame, this flag is set to 1 to skip partition search.
int partition_search_skippable_frame; int partition_search_skippable_frame;
......
...@@ -2765,8 +2765,9 @@ void vp9_rd_pick_intra_mode_sb(VP9_COMP *cpi, MACROBLOCK *x, ...@@ -2765,8 +2765,9 @@ void vp9_rd_pick_intra_mode_sb(VP9_COMP *cpi, MACROBLOCK *x,
rd_cost->rdcost = RDCOST(x->rdmult, x->rddiv, rd_cost->rate, rd_cost->dist); rd_cost->rdcost = RDCOST(x->rdmult, x->rddiv, rd_cost->rate, rd_cost->dist);
} }
static void update_rd_thresh_fact(VP9_COMP *cpi, int bsize, // TODO(jingning) Refactor this function. Use targeted smaller struct as inputs.
int best_mode_index) { static void update_rd_thresh_fact(VP9_COMP *cpi, TileDataEnc *tile_data,
int bsize, int best_mode_index) {
if (cpi->sf.adaptive_rd_thresh > 0) { if (cpi->sf.adaptive_rd_thresh > 0) {
const int top_mode = bsize < BLOCK_8X8 ? MAX_REFS : MAX_MODES; const int top_mode = bsize < BLOCK_8X8 ? MAX_REFS : MAX_MODES;
int mode; int mode;
...@@ -2775,7 +2776,7 @@ static void update_rd_thresh_fact(VP9_COMP *cpi, int bsize, ...@@ -2775,7 +2776,7 @@ static void update_rd_thresh_fact(VP9_COMP *cpi, int bsize,
const BLOCK_SIZE max_size = MIN(bsize + 2, BLOCK_64X64); const BLOCK_SIZE max_size = MIN(bsize + 2, BLOCK_64X64);
BLOCK_SIZE bs; BLOCK_SIZE bs;
for (bs = min_size; bs <= max_size; ++bs) { for (bs = min_size; bs <= max_size; ++bs) {
int *const fact = &cpi->rd.thresh_freq_fact[bs][mode]; int *const fact = &tile_data->thresh_freq_fact[bs][mode];
if (mode == best_mode_index) { if (mode == best_mode_index) {
*fact -= (*fact >> 4); *fact -= (*fact >> 4);
} else { } else {
...@@ -2787,7 +2788,9 @@ static void update_rd_thresh_fact(VP9_COMP *cpi, int bsize, ...@@ -2787,7 +2788,9 @@ static void update_rd_thresh_fact(VP9_COMP *cpi, int bsize,
} }
} }
void vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x, void vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi,
TileDataEnc *tile_data,
MACROBLOCK *x,
const TileInfo *const tile, const TileInfo *const tile,
int mi_row, int mi_col, int mi_row, int mi_col,
RD_COST *rd_cost, BLOCK_SIZE bsize, RD_COST *rd_cost, BLOCK_SIZE bsize,
...@@ -2836,9 +2839,9 @@ void vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x, ...@@ -2836,9 +2839,9 @@ void vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x,
uint16_t mode_skip_mask[MAX_REF_FRAMES] = { 0 }; uint16_t mode_skip_mask[MAX_REF_FRAMES] = { 0 };
int mode_skip_start = sf->mode_skip_start + 1; int mode_skip_start = sf->mode_skip_start + 1;
const int *const rd_threshes = rd_opt->threshes[segment_id][bsize]; const int *const rd_threshes = rd_opt->threshes[segment_id][bsize];
const int *const rd_thresh_freq_fact = rd_opt->thresh_freq_fact[bsize]; const int *const rd_thresh_freq_fact = tile_data->thresh_freq_fact[bsize];
int64_t mode_threshold[MAX_MODES]; int64_t mode_threshold[MAX_MODES];
int *mode_map = rd_opt->mode_map[bsize]; int *mode_map = tile_data->mode_map[bsize];
const int mode_search_skip_flags = sf->mode_search_skip_flags; const int mode_search_skip_flags = sf->mode_search_skip_flags;
vp9_zero(best_mbmode); vp9_zero(best_mbmode);
...@@ -3420,7 +3423,7 @@ void vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x, ...@@ -3420,7 +3423,7 @@ void vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x,
!is_inter_block(&best_mbmode)); !is_inter_block(&best_mbmode));
if (!cpi->rc.is_src_frame_alt_ref) if (!cpi->rc.is_src_frame_alt_ref)
update_rd_thresh_fact(cpi, bsize, best_mode_index); update_rd_thresh_fact(cpi, tile_data, bsize, best_mode_index);
// macroblock modes // macroblock modes
*mbmi = best_mbmode; *mbmi = best_mbmode;
...@@ -3479,7 +3482,9 @@ void vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x, ...@@ -3479,7 +3482,9 @@ void vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x,
best_tx_diff, best_filter_diff, best_mode_skippable); best_tx_diff, best_filter_diff, best_mode_skippable);
} }
void vp9_rd_pick_inter_mode_sb_seg_skip(VP9_COMP *cpi, MACROBLOCK *x, void vp9_rd_pick_inter_mode_sb_seg_skip(VP9_COMP *cpi,
TileDataEnc *tile_data,
MACROBLOCK *x,
RD_COST *rd_cost, RD_COST *rd_cost,
BLOCK_SIZE bsize, BLOCK_SIZE bsize,
PICK_MODE_CONTEXT *ctx, PICK_MODE_CONTEXT *ctx,
...@@ -3573,7 +3578,7 @@ void vp9_rd_pick_inter_mode_sb_seg_skip(VP9_COMP *cpi, MACROBLOCK *x, ...@@ -3573,7 +3578,7 @@ void vp9_rd_pick_inter_mode_sb_seg_skip(VP9_COMP *cpi, MACROBLOCK *x,
assert((cm->interp_filter == SWITCHABLE) || assert((cm->interp_filter == SWITCHABLE) ||
(cm->interp_filter == mbmi->interp_filter)); (cm->interp_filter == mbmi->interp_filter));
update_rd_thresh_fact(cpi, bsize, THR_ZEROMV); update_rd_thresh_fact(cpi, tile_data, bsize, THR_ZEROMV);
vp9_zero(best_pred_diff); vp9_zero(best_pred_diff);
vp9_zero(best_filter_diff); vp9_zero(best_filter_diff);
...@@ -3585,7 +3590,9 @@ void vp9_rd_pick_inter_mode_sb_seg_skip(VP9_COMP *cpi, MACROBLOCK *x, ...@@ -3585,7 +3590,9 @@ void vp9_rd_pick_inter_mode_sb_seg_skip(VP9_COMP *cpi, MACROBLOCK *x,
best_pred_diff, best_tx_diff, best_filter_diff, 0); best_pred_diff, best_tx_diff, best_filter_diff, 0);
} }