From: Jingning Han Date: Thu, 9 Oct 2014 19:32:56 +0000 (-0700) Subject: Refactor rate distortion cost structure X-Git-Tag: v1.4.0~619^2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=811cef97c979d10d08a82c580cfbfb82484bc55d;p=libvpx Refactor rate distortion cost structure This commit makes a struct that contains rate value, distortion value, and the rate-distortion cost. The goal is to provide a better interface for rate-distortion related operation. It is first used in rd_pick_partition and saves a few RDCOST calculations. Change-Id: I1a6ab7b35282d3c80195af59b6810e577544691f --- diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c index 79946ca92..b43ff9747 100644 --- a/vp9/encoder/vp9_encodeframe.c +++ b/vp9/encoder/vp9_encodeframe.c @@ -770,8 +770,7 @@ static void set_mode_info_seg_skip(MACROBLOCK *x, TX_MODE tx_mode, int *rate, } static void rd_pick_sb_modes(VP9_COMP *cpi, const TileInfo *const tile, - int mi_row, int mi_col, - int *totalrate, int64_t *totaldist, + int mi_row, int mi_col, RD_COST *rd_cost, BLOCK_SIZE bsize, PICK_MODE_CONTEXT *ctx, int64_t best_rd) { VP9_COMMON *const cm = &cpi->common; @@ -857,28 +856,33 @@ static void rd_pick_sb_modes(VP9_COMP *cpi, const TileInfo *const tile, // Find best coding mode & reconstruct the MB so it is available // as a predictor for MBs that follow in the SB if (frame_is_intra_only(cm)) { - vp9_rd_pick_intra_mode_sb(cpi, x, totalrate, totaldist, bsize, ctx, - best_rd); + vp9_rd_pick_intra_mode_sb(cpi, x, rd_cost, bsize, ctx, best_rd); } else { if (bsize >= BLOCK_8X8) { if (vp9_segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP)) - vp9_rd_pick_inter_mode_sb_seg_skip(cpi, x, totalrate, totaldist, bsize, + vp9_rd_pick_inter_mode_sb_seg_skip(cpi, x, rd_cost, bsize, ctx, best_rd); else vp9_rd_pick_inter_mode_sb(cpi, x, tile, mi_row, mi_col, - totalrate, totaldist, bsize, ctx, best_rd); + rd_cost, bsize, ctx, best_rd); } else { - vp9_rd_pick_inter_mode_sub8x8(cpi, x, tile, mi_row, mi_col, totalrate, - totaldist, bsize, ctx, best_rd); + vp9_rd_pick_inter_mode_sub8x8(cpi, x, tile, mi_row, mi_col, rd_cost, + bsize, ctx, best_rd); } } - x->rdmult = orig_rdmult; - - if (aq_mode == VARIANCE_AQ && *totalrate != INT_MAX) { + if (aq_mode == VARIANCE_AQ && rd_cost->rate != INT_MAX) { vp9_clear_system_state(); - *totalrate = (int)round(*totalrate * rdmult_ratio); + rd_cost->rate = (int)round(rd_cost->rate * rdmult_ratio); + rd_cost->rdcost = RDCOST(x->rdmult, x->rddiv, rd_cost->rate, rd_cost->dist); } + + x->rdmult = orig_rdmult; + + // TODO(jingning) The rate-distortion optimization flow needs to be + // refactored to provide proper exit/return handle. + if (rd_cost->rate == INT_MAX) + rd_cost->rdcost = INT64_MAX; } static void update_stats(VP9_COMMON *cm, const MACROBLOCK *x) { @@ -1500,10 +1504,9 @@ static void encode_sb_rt(VP9_COMP *cpi, const TileInfo *const tile, update_partition_context(xd, mi_row, mi_col, subsize, bsize); } -static void rd_use_partition(VP9_COMP *cpi, - const TileInfo *const tile, - MODE_INFO *mi_8x8, - TOKENEXTRA **tp, int mi_row, int mi_col, +static void rd_use_partition(VP9_COMP *cpi, const TileInfo *const tile, + MODE_INFO *mi_8x8, TOKENEXTRA **tp, + int mi_row, int mi_col, BLOCK_SIZE bsize, int *rate, int64_t *dist, int do_recon, PC_TREE *pc_tree) { VP9_COMMON *const cm = &cpi->common; @@ -1518,15 +1521,9 @@ static void rd_use_partition(VP9_COMP *cpi, BLOCK_SIZE subsize; ENTROPY_CONTEXT l[16 * MAX_MB_PLANE], a[16 * MAX_MB_PLANE]; PARTITION_CONTEXT sl[8], sa[8]; - int last_part_rate = INT_MAX; - int64_t last_part_dist = INT64_MAX; - int64_t last_part_rd = INT64_MAX; - int none_rate = INT_MAX; - int64_t none_dist = INT64_MAX; - int64_t none_rd = INT64_MAX; - int chosen_rate = INT_MAX; - int64_t chosen_dist = INT64_MAX; - int64_t chosen_rd = INT64_MAX; + RD_COST last_part_rdc = {INT_MAX, INT64_MAX, INT64_MAX}; + RD_COST none_rdc = {INT_MAX, INT64_MAX, INT64_MAX}; + RD_COST chosen_rdc = {INT_MAX, INT64_MAX, INT64_MAX}; BLOCK_SIZE sub_subsize = BLOCK_4X4; int splits_below = 0; BLOCK_SIZE bs_type = mi_8x8[0].src_mi->mbmi.sb_type; @@ -1572,14 +1569,15 @@ static void rd_use_partition(VP9_COMP *cpi, mi_row + (mi_step >> 1) < cm->mi_rows && mi_col + (mi_step >> 1) < cm->mi_cols) { pc_tree->partitioning = PARTITION_NONE; - rd_pick_sb_modes(cpi, tile, mi_row, mi_col, &none_rate, &none_dist, bsize, + rd_pick_sb_modes(cpi, tile, mi_row, mi_col, &none_rdc, bsize, ctx, INT64_MAX); pl = partition_plane_context(xd, mi_row, mi_col, bsize); - if (none_rate < INT_MAX) { - none_rate += cpi->partition_cost[pl][PARTITION_NONE]; - none_rd = RDCOST(x->rdmult, x->rddiv, none_rate, none_dist); + if (none_rdc.rate < INT_MAX) { + none_rdc.rate += cpi->partition_cost[pl][PARTITION_NONE]; + none_rdc.rdcost = RDCOST(x->rdmult, x->rddiv, none_rdc.rate, + none_rdc.dist); } restore_context(cpi, mi_row, mi_col, a, l, sa, sl, bsize); @@ -1590,84 +1588,85 @@ static void rd_use_partition(VP9_COMP *cpi, switch (partition) { case PARTITION_NONE: - rd_pick_sb_modes(cpi, tile, mi_row, mi_col, &last_part_rate, - &last_part_dist, bsize, ctx, INT64_MAX); + rd_pick_sb_modes(cpi, tile, mi_row, mi_col, &last_part_rdc, + bsize, ctx, INT64_MAX); break; case PARTITION_HORZ: - rd_pick_sb_modes(cpi, tile, mi_row, mi_col, &last_part_rate, - &last_part_dist, subsize, &pc_tree->horizontal[0], + rd_pick_sb_modes(cpi, tile, mi_row, mi_col, &last_part_rdc, + subsize, &pc_tree->horizontal[0], INT64_MAX); - if (last_part_rate != INT_MAX && + if (last_part_rdc.rate != INT_MAX && bsize >= BLOCK_8X8 && mi_row + (mi_step >> 1) < cm->mi_rows) { - int rt = 0; - int64_t dt = 0; + RD_COST tmp_rdc = {0, 0, 0}; PICK_MODE_CONTEXT *ctx = &pc_tree->horizontal[0]; update_state(cpi, ctx, mi_row, mi_col, subsize, 0); encode_superblock(cpi, tp, 0, mi_row, mi_col, subsize, ctx); - rd_pick_sb_modes(cpi, tile, mi_row + (mi_step >> 1), mi_col, &rt, &dt, + rd_pick_sb_modes(cpi, tile, mi_row + (mi_step >> 1), mi_col, &tmp_rdc, subsize, &pc_tree->horizontal[1], INT64_MAX); - if (rt == INT_MAX || dt == INT64_MAX) { - last_part_rate = INT_MAX; - last_part_dist = INT64_MAX; + if (tmp_rdc.rate == INT_MAX || tmp_rdc.dist == INT64_MAX) { + last_part_rdc.rate = INT_MAX; + last_part_rdc.dist = INT64_MAX; + last_part_rdc.rdcost = INT64_MAX; break; } - - last_part_rate += rt; - last_part_dist += dt; + last_part_rdc.rate += tmp_rdc.rate; + last_part_rdc.dist += tmp_rdc.dist; + last_part_rdc.rdcost += tmp_rdc.rdcost; } break; case PARTITION_VERT: - rd_pick_sb_modes(cpi, tile, mi_row, mi_col, &last_part_rate, - &last_part_dist, subsize, &pc_tree->vertical[0], - INT64_MAX); - if (last_part_rate != INT_MAX && + rd_pick_sb_modes(cpi, tile, mi_row, mi_col, &last_part_rdc, + subsize, &pc_tree->vertical[0], INT64_MAX); + if (last_part_rdc.rate != INT_MAX && bsize >= BLOCK_8X8 && mi_col + (mi_step >> 1) < cm->mi_cols) { - int rt = 0; - int64_t dt = 0; + RD_COST tmp_rdc = {0, 0, 0}; PICK_MODE_CONTEXT *ctx = &pc_tree->vertical[0]; update_state(cpi, ctx, mi_row, mi_col, subsize, 0); encode_superblock(cpi, tp, 0, mi_row, mi_col, subsize, ctx); - rd_pick_sb_modes(cpi, tile, mi_row, mi_col + (mi_step >> 1), &rt, &dt, + rd_pick_sb_modes(cpi, tile, mi_row, mi_col + (mi_step >> 1), &tmp_rdc, subsize, &pc_tree->vertical[bsize > BLOCK_8X8], INT64_MAX); - if (rt == INT_MAX || dt == INT64_MAX) { - last_part_rate = INT_MAX; - last_part_dist = INT64_MAX; + if (tmp_rdc.rate == INT_MAX || tmp_rdc.dist == INT64_MAX) { + last_part_rdc.rate = INT_MAX; + last_part_rdc.dist = INT64_MAX; + last_part_rdc.rdcost = INT64_MAX; break; } - last_part_rate += rt; - last_part_dist += dt; + last_part_rdc.rate += tmp_rdc.rate; + last_part_rdc.dist += tmp_rdc.dist; + last_part_rdc.rdcost += tmp_rdc.rdcost; } break; case PARTITION_SPLIT: if (bsize == BLOCK_8X8) { - rd_pick_sb_modes(cpi, tile, mi_row, mi_col, &last_part_rate, - &last_part_dist, subsize, pc_tree->leaf_split[0], - INT64_MAX); + rd_pick_sb_modes(cpi, tile, mi_row, mi_col, &last_part_rdc, + subsize, pc_tree->leaf_split[0], INT64_MAX); break; } - last_part_rate = 0; - last_part_dist = 0; + last_part_rdc.rate = 0; + last_part_rdc.dist = 0; + last_part_rdc.rdcost = 0; for (i = 0; i < 4; i++) { int x_idx = (i & 1) * (mi_step >> 1); int y_idx = (i >> 1) * (mi_step >> 1); int jj = i >> 1, ii = i & 0x01; - int rt; - int64_t dt; + RD_COST tmp_rdc = {0, 0, 0}; if ((mi_row + y_idx >= cm->mi_rows) || (mi_col + x_idx >= cm->mi_cols)) continue; rd_use_partition(cpi, tile, mi_8x8 + jj * bss * mis + ii * bss, tp, - mi_row + y_idx, mi_col + x_idx, subsize, &rt, &dt, + mi_row + y_idx, mi_col + x_idx, subsize, + &tmp_rdc.rate, &tmp_rdc.dist, i != 3, pc_tree->split[i]); - if (rt == INT_MAX || dt == INT64_MAX) { - last_part_rate = INT_MAX; - last_part_dist = INT64_MAX; + if (tmp_rdc.rate == INT_MAX || tmp_rdc.dist == INT64_MAX) { + last_part_rdc.rate = INT_MAX; + last_part_rdc.dist = INT64_MAX; + last_part_rdc.rdcost = INT64_MAX; break; } - last_part_rate += rt; - last_part_dist += dt; + last_part_rdc.rate += tmp_rdc.rate; + last_part_rdc.dist += tmp_rdc.dist; } break; default: @@ -1676,9 +1675,10 @@ static void rd_use_partition(VP9_COMP *cpi, } pl = partition_plane_context(xd, mi_row, mi_col, bsize); - if (last_part_rate < INT_MAX) { - last_part_rate += cpi->partition_cost[pl][partition]; - last_part_rd = RDCOST(x->rdmult, x->rddiv, last_part_rate, last_part_dist); + if (last_part_rdc.rate < INT_MAX) { + last_part_rdc.rate += cpi->partition_cost[pl][partition]; + last_part_rdc.rdcost = RDCOST(x->rdmult, x->rddiv, + last_part_rdc.rate, last_part_rdc.dist); } if (do_partition_search @@ -1690,8 +1690,8 @@ static void rd_use_partition(VP9_COMP *cpi, && (mi_col + mi_step < cm->mi_cols || mi_col + (mi_step >> 1) == cm->mi_cols)) { BLOCK_SIZE split_subsize = get_subsize(bsize, PARTITION_SPLIT); - chosen_rate = 0; - chosen_dist = 0; + chosen_rdc.rate = 0; + chosen_rdc.dist = 0; restore_context(cpi, mi_row, mi_col, a, l, sa, sl, bsize); pc_tree->partitioning = PARTITION_SPLIT; @@ -1699,8 +1699,7 @@ static void rd_use_partition(VP9_COMP *cpi, for (i = 0; i < 4; i++) { int x_idx = (i & 1) * (mi_step >> 1); int y_idx = (i >> 1) * (mi_step >> 1); - int rt = 0; - int64_t dt = 0; + RD_COST tmp_rdc; ENTROPY_CONTEXT l[16 * MAX_MB_PLANE], a[16 * MAX_MB_PLANE]; PARTITION_CONTEXT sl[8], sa[8]; @@ -1709,20 +1708,21 @@ static void rd_use_partition(VP9_COMP *cpi, save_context(cpi, mi_row, mi_col, a, l, sa, sl, bsize); pc_tree->split[i]->partitioning = PARTITION_NONE; - rd_pick_sb_modes(cpi, tile, mi_row + y_idx, mi_col + x_idx, &rt, &dt, + rd_pick_sb_modes(cpi, tile, mi_row + y_idx, mi_col + x_idx, &tmp_rdc, split_subsize, &pc_tree->split[i]->none, INT64_MAX); restore_context(cpi, mi_row, mi_col, a, l, sa, sl, bsize); - if (rt == INT_MAX || dt == INT64_MAX) { - chosen_rate = INT_MAX; - chosen_dist = INT64_MAX; + if (tmp_rdc.rate == INT_MAX || tmp_rdc.dist == INT64_MAX) { + chosen_rdc.rate = INT_MAX; + chosen_rdc.dist = INT64_MAX; + chosen_rdc.rdcost = INT64_MAX; break; } - chosen_rate += rt; - chosen_dist += dt; + chosen_rdc.rate += tmp_rdc.rate; + chosen_rdc.dist += tmp_rdc.dist; if (i != 3) encode_sb(cpi, tile, tp, mi_row + y_idx, mi_col + x_idx, 0, @@ -1730,30 +1730,28 @@ static void rd_use_partition(VP9_COMP *cpi, pl = partition_plane_context(xd, mi_row + y_idx, mi_col + x_idx, split_subsize); - chosen_rate += cpi->partition_cost[pl][PARTITION_NONE]; + chosen_rdc.rate += cpi->partition_cost[pl][PARTITION_NONE]; } pl = partition_plane_context(xd, mi_row, mi_col, bsize); - if (chosen_rate < INT_MAX) { - chosen_rate += cpi->partition_cost[pl][PARTITION_SPLIT]; - chosen_rd = RDCOST(x->rdmult, x->rddiv, chosen_rate, chosen_dist); + if (chosen_rdc.rate < INT_MAX) { + chosen_rdc.rate += cpi->partition_cost[pl][PARTITION_SPLIT]; + chosen_rdc.rdcost = RDCOST(x->rdmult, x->rddiv, + chosen_rdc.rate, chosen_rdc.dist); } } // If last_part is better set the partitioning to that. - if (last_part_rd < chosen_rd) { + if (last_part_rdc.rdcost < chosen_rdc.rdcost) { mi_8x8[0].src_mi->mbmi.sb_type = bsize; if (bsize >= BLOCK_8X8) pc_tree->partitioning = partition; - chosen_rate = last_part_rate; - chosen_dist = last_part_dist; - chosen_rd = last_part_rd; + chosen_rdc = last_part_rdc; } // If none was better set the partitioning to that. - if (none_rd < chosen_rd) { + if (none_rdc.rdcost < chosen_rdc.rdcost) { if (bsize >= BLOCK_8X8) pc_tree->partitioning = PARTITION_NONE; - chosen_rate = none_rate; - chosen_dist = none_dist; + chosen_rdc = none_rdc; } restore_context(cpi, mi_row, mi_col, a, l, sa, sl, bsize); @@ -1761,7 +1759,7 @@ static void rd_use_partition(VP9_COMP *cpi, // We must have chosen a partitioning and encoding or we'll fail later on. // No other opportunities for success. if (bsize == BLOCK_64X64) - assert(chosen_rate < INT_MAX && chosen_dist < INT64_MAX); + assert(chosen_rdc.rate < INT_MAX && chosen_rdc.dist < INT64_MAX); if (do_recon) { int output_enabled = (bsize == BLOCK_64X64); @@ -1771,18 +1769,18 @@ static void rd_use_partition(VP9_COMP *cpi, // closer to the target. if ((cpi->oxcf.aq_mode == COMPLEXITY_AQ) && cm->seg.update_map) { vp9_select_in_frame_q_segment(cpi, mi_row, mi_col, - output_enabled, chosen_rate); + output_enabled, chosen_rdc.rate); } if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ) vp9_cyclic_refresh_set_rate_and_dist_sb(cpi->cyclic_refresh, - chosen_rate, chosen_dist); + chosen_rdc.rate, chosen_rdc.dist); encode_sb(cpi, tile, tp, mi_row, mi_col, output_enabled, bsize, pc_tree); } - *rate = chosen_rate; - *dist = chosen_dist; + *rate = chosen_rdc.rate; + *dist = chosen_rdc.dist; } static const BLOCK_SIZE min_partition_size[BLOCK_SIZES] = { @@ -2111,10 +2109,9 @@ static INLINE int get_motion_inconsistency(MOTION_DIRECTION this_mv, // unlikely to be selected depending on previous rate-distortion optimization // results, for encoding speed-up. static void rd_pick_partition(VP9_COMP *cpi, const TileInfo *const tile, - TOKENEXTRA **tp, int mi_row, - int mi_col, BLOCK_SIZE bsize, int *rate, - int64_t *dist, int64_t best_rd, - PC_TREE *pc_tree) { + TOKENEXTRA **tp, int mi_row, int mi_col, + BLOCK_SIZE bsize, RD_COST *rd_cost, + int64_t best_rd, PC_TREE *pc_tree) { VP9_COMMON *const cm = &cpi->common; MACROBLOCK *const x = &cpi->mb; MACROBLOCKD *const xd = &x->e_mbd; @@ -2125,9 +2122,9 @@ static void rd_pick_partition(VP9_COMP *cpi, const TileInfo *const tile, PICK_MODE_CONTEXT *ctx = &pc_tree->none; int i, pl; BLOCK_SIZE subsize; - int this_rate, sum_rate = 0, best_rate = INT_MAX; - int64_t this_dist, sum_dist = 0, best_dist = INT64_MAX; - int64_t sum_rd = 0; + RD_COST this_rdc = {0, 0, 0}; + RD_COST sum_rdc = {0, 0, 0}; + RD_COST best_rdc = {INT_MAX, INT64_MAX, best_rd}; int do_split = bsize >= BLOCK_8X8; int do_rect = 1; @@ -2246,22 +2243,21 @@ static void rd_pick_partition(VP9_COMP *cpi, const TileInfo *const tile, // PARTITION_NONE if (partition_none_allowed) { - rd_pick_sb_modes(cpi, tile, mi_row, mi_col, &this_rate, &this_dist, bsize, - ctx, best_rd); - if (this_rate != INT_MAX) { + rd_pick_sb_modes(cpi, tile, mi_row, mi_col, &this_rdc, bsize, ctx, + best_rdc.rdcost); + if (this_rdc.rate != INT_MAX) { if (bsize >= BLOCK_8X8) { pl = partition_plane_context(xd, mi_row, mi_col, bsize); - this_rate += cpi->partition_cost[pl][PARTITION_NONE]; + this_rdc.rate += cpi->partition_cost[pl][PARTITION_NONE]; + this_rdc.rdcost = RDCOST(x->rdmult, x->rddiv, + this_rdc.rate, this_rdc.dist); } - sum_rd = RDCOST(x->rdmult, x->rddiv, this_rate, this_dist); - if (sum_rd < best_rd) { + if (this_rdc.rdcost < best_rdc.rdcost) { int64_t dist_breakout_thr = cpi->sf.partition_search_breakout_dist_thr; int rate_breakout_thr = cpi->sf.partition_search_breakout_rate_thr; - best_rate = this_rate; - best_dist = this_dist; - best_rd = sum_rd; + best_rdc = this_rdc; if (bsize >= BLOCK_8X8) pc_tree->partitioning = PARTITION_NONE; @@ -2277,8 +2273,8 @@ static void rd_pick_partition(VP9_COMP *cpi, const TileInfo *const tile, // The dist & rate thresholds are set to 0 at speed 0 to disable the // early termination at that speed. if (!x->e_mbd.lossless && - (ctx->skippable && best_dist < dist_breakout_thr && - best_rate < rate_breakout_thr)) { + (ctx->skippable && best_rdc.dist < dist_breakout_thr && + best_rdc.rate < rate_breakout_thr)) { do_split = 0; do_rect = 0; } @@ -2338,7 +2334,6 @@ static void rd_pick_partition(VP9_COMP *cpi, const TileInfo *const tile, store_pred_mv(x, ctx); // PARTITION_SPLIT - sum_rd = 0; // TODO(jingning): use the motion vectors given by the above search as // the starting point of motion search in the following partition type check. if (do_split) { @@ -2348,14 +2343,12 @@ static void rd_pick_partition(VP9_COMP *cpi, const TileInfo *const tile, if (cpi->sf.adaptive_pred_interp_filter && partition_none_allowed) pc_tree->leaf_split[0]->pred_interp_filter = ctx->mic.mbmi.interp_filter; - rd_pick_sb_modes(cpi, tile, mi_row, mi_col, &sum_rate, &sum_dist, subsize, - pc_tree->leaf_split[0], best_rd); - if (sum_rate == INT_MAX) - sum_rd = INT64_MAX; - else - sum_rd = RDCOST(x->rdmult, x->rddiv, sum_rate, sum_dist); + rd_pick_sb_modes(cpi, tile, mi_row, mi_col, &sum_rdc, subsize, + pc_tree->leaf_split[0], best_rdc.rdcost); + if (sum_rdc.rate == INT_MAX) + sum_rdc.rdcost = INT64_MAX; } else { - for (i = 0; i < 4 && sum_rd < best_rd; ++i) { + for (i = 0; i < 4 && sum_rdc.rdcost < best_rdc.rdcost; ++i) { const int x_idx = (i & 1) * mi_step; const int y_idx = (i >> 1) * mi_step; @@ -2367,28 +2360,28 @@ static void rd_pick_partition(VP9_COMP *cpi, const TileInfo *const tile, pc_tree->split[i]->index = i; rd_pick_partition(cpi, tile, tp, mi_row + y_idx, mi_col + x_idx, - subsize, &this_rate, &this_dist, - best_rd - sum_rd, pc_tree->split[i]); + subsize, &this_rdc, + best_rdc.rdcost - sum_rdc.rdcost, pc_tree->split[i]); - if (this_rate == INT_MAX) { - sum_rd = INT64_MAX; + if (this_rdc.rate == INT_MAX) { + sum_rdc.rdcost = INT64_MAX; + break; } else { - sum_rate += this_rate; - sum_dist += this_dist; - sum_rd = RDCOST(x->rdmult, x->rddiv, sum_rate, sum_dist); + sum_rdc.rate += this_rdc.rate; + sum_rdc.dist += this_rdc.dist; + sum_rdc.rdcost += this_rdc.rdcost; } } } - if (sum_rd < best_rd && i == 4) { + if (sum_rdc.rdcost < best_rdc.rdcost && i == 4) { pl = partition_plane_context(xd, mi_row, mi_col, bsize); - sum_rate += cpi->partition_cost[pl][PARTITION_SPLIT]; - sum_rd = RDCOST(x->rdmult, x->rddiv, sum_rate, sum_dist); + sum_rdc.rate += cpi->partition_cost[pl][PARTITION_SPLIT]; + sum_rdc.rdcost = RDCOST(x->rdmult, x->rddiv, + sum_rdc.rate, sum_rdc.dist); - if (sum_rd < best_rd) { - best_rate = sum_rate; - best_dist = sum_dist; - best_rd = sum_rd; + if (sum_rdc.rdcost < best_rdc.rdcost) { + best_rdc = sum_rdc; pc_tree->partitioning = PARTITION_SPLIT; } } else { @@ -2409,11 +2402,10 @@ static void rd_pick_partition(VP9_COMP *cpi, const TileInfo *const tile, partition_none_allowed) pc_tree->horizontal[0].pred_interp_filter = ctx->mic.mbmi.interp_filter; - rd_pick_sb_modes(cpi, tile, mi_row, mi_col, &sum_rate, &sum_dist, subsize, - &pc_tree->horizontal[0], best_rd); - sum_rd = RDCOST(x->rdmult, x->rddiv, sum_rate, sum_dist); + rd_pick_sb_modes(cpi, tile, mi_row, mi_col, &sum_rdc, subsize, + &pc_tree->horizontal[0], best_rdc.rdcost); - if (sum_rd < best_rd && mi_row + mi_step < cm->mi_rows && + if (sum_rdc.rdcost < best_rdc.rdcost && mi_row + mi_step < cm->mi_rows && bsize > BLOCK_8X8) { PICK_MODE_CONTEXT *ctx = &pc_tree->horizontal[0]; update_state(cpi, ctx, mi_row, mi_col, subsize, 0); @@ -2425,25 +2417,24 @@ static void rd_pick_partition(VP9_COMP *cpi, const TileInfo *const tile, partition_none_allowed) pc_tree->horizontal[1].pred_interp_filter = ctx->mic.mbmi.interp_filter; - rd_pick_sb_modes(cpi, tile, mi_row + mi_step, mi_col, &this_rate, - &this_dist, subsize, &pc_tree->horizontal[1], - best_rd - sum_rd); - if (this_rate == INT_MAX) { - sum_rd = INT64_MAX; + rd_pick_sb_modes(cpi, tile, mi_row + mi_step, mi_col, &this_rdc, + subsize, &pc_tree->horizontal[1], + best_rdc.rdcost - sum_rdc.rdcost); + if (this_rdc.rate == INT_MAX) { + sum_rdc.rdcost = INT64_MAX; } else { - sum_rate += this_rate; - sum_dist += this_dist; - sum_rd = RDCOST(x->rdmult, x->rddiv, sum_rate, sum_dist); + sum_rdc.rate += this_rdc.rate; + sum_rdc.dist += this_rdc.dist; + sum_rdc.rdcost += this_rdc.rdcost; } } - if (sum_rd < best_rd) { + + if (sum_rdc.rdcost < best_rdc.rdcost) { pl = partition_plane_context(xd, mi_row, mi_col, bsize); - sum_rate += cpi->partition_cost[pl][PARTITION_HORZ]; - sum_rd = RDCOST(x->rdmult, x->rddiv, sum_rate, sum_dist); - if (sum_rd < best_rd) { - best_rd = sum_rd; - best_rate = sum_rate; - best_dist = sum_dist; + sum_rdc.rate += cpi->partition_cost[pl][PARTITION_HORZ]; + sum_rdc.rdcost = RDCOST(x->rdmult, x->rddiv, sum_rdc.rate, sum_rdc.dist); + if (sum_rdc.rdcost < best_rdc.rdcost) { + best_rdc = sum_rdc; pc_tree->partitioning = PARTITION_HORZ; } } @@ -2459,10 +2450,9 @@ static void rd_pick_partition(VP9_COMP *cpi, const TileInfo *const tile, partition_none_allowed) pc_tree->vertical[0].pred_interp_filter = ctx->mic.mbmi.interp_filter; - rd_pick_sb_modes(cpi, tile, mi_row, mi_col, &sum_rate, &sum_dist, subsize, - &pc_tree->vertical[0], best_rd); - sum_rd = RDCOST(x->rdmult, x->rddiv, sum_rate, sum_dist); - if (sum_rd < best_rd && mi_col + mi_step < cm->mi_cols && + rd_pick_sb_modes(cpi, tile, mi_row, mi_col, &sum_rdc, subsize, + &pc_tree->vertical[0], best_rdc.rdcost); + if (sum_rdc.rdcost < best_rdc.rdcost && mi_col + mi_step < cm->mi_cols && bsize > BLOCK_8X8) { update_state(cpi, &pc_tree->vertical[0], mi_row, mi_col, subsize, 0); encode_superblock(cpi, tp, 0, mi_row, mi_col, subsize, @@ -2474,25 +2464,24 @@ static void rd_pick_partition(VP9_COMP *cpi, const TileInfo *const tile, partition_none_allowed) pc_tree->vertical[1].pred_interp_filter = ctx->mic.mbmi.interp_filter; - rd_pick_sb_modes(cpi, tile, mi_row, mi_col + mi_step, &this_rate, - &this_dist, subsize, - &pc_tree->vertical[1], best_rd - sum_rd); - if (this_rate == INT_MAX) { - sum_rd = INT64_MAX; + rd_pick_sb_modes(cpi, tile, mi_row, mi_col + mi_step, &this_rdc, subsize, + &pc_tree->vertical[1], best_rdc.rdcost - sum_rdc.rdcost); + if (this_rdc.rate == INT_MAX) { + sum_rdc.rdcost = INT64_MAX; } else { - sum_rate += this_rate; - sum_dist += this_dist; - sum_rd = RDCOST(x->rdmult, x->rddiv, sum_rate, sum_dist); + sum_rdc.rate += this_rdc.rate; + sum_rdc.dist += this_rdc.dist; + sum_rdc.rdcost += this_rdc.rdcost; } } - if (sum_rd < best_rd) { + + if (sum_rdc.rdcost < best_rdc.rdcost) { pl = partition_plane_context(xd, mi_row, mi_col, bsize); - sum_rate += cpi->partition_cost[pl][PARTITION_VERT]; - sum_rd = RDCOST(x->rdmult, x->rddiv, sum_rate, sum_dist); - if (sum_rd < best_rd) { - best_rate = sum_rate; - best_dist = sum_dist; - best_rd = sum_rd; + sum_rdc.rate += cpi->partition_cost[pl][PARTITION_VERT]; + sum_rdc.rdcost = RDCOST(x->rdmult, x->rddiv, + sum_rdc.rate, sum_rdc.dist); + if (sum_rdc.rdcost < best_rdc.rdcost) { + best_rdc = sum_rdc; pc_tree->partitioning = PARTITION_VERT; } } @@ -2504,10 +2493,11 @@ static void rd_pick_partition(VP9_COMP *cpi, const TileInfo *const tile, // point. This code should be refactored so that the duplicate // checks occur in some sub function and thus are used... (void) best_rd; - *rate = best_rate; - *dist = best_dist; + *rd_cost = best_rdc; + - if (best_rate < INT_MAX && best_dist < INT64_MAX && pc_tree->index != 3) { + 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 @@ -2515,18 +2505,18 @@ static void rd_pick_partition(VP9_COMP *cpi, const TileInfo *const tile, // closer to the target. if ((cpi->oxcf.aq_mode == COMPLEXITY_AQ) && cm->seg.update_map) vp9_select_in_frame_q_segment(cpi, mi_row, mi_col, output_enabled, - best_rate); + best_rdc.rate); if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ) vp9_cyclic_refresh_set_rate_and_dist_sb(cpi->cyclic_refresh, - best_rate, best_dist); + best_rdc.rate, best_rdc.dist); encode_sb(cpi, tile, tp, mi_row, mi_col, output_enabled, bsize, pc_tree); } if (bsize == BLOCK_64X64) { assert(tp_orig < *tp); - assert(best_rate < INT_MAX); - assert(best_dist < INT64_MAX); + assert(best_rdc.rate < INT_MAX); + assert(best_rdc.dist < INT64_MAX); } else { assert(tp_orig == *tp); } @@ -2548,6 +2538,7 @@ static void encode_rd_sb_row(VP9_COMP *cpi, const TileInfo *const tile, mi_col += MI_BLOCK_SIZE) { int dummy_rate; int64_t dummy_dist; + RD_COST dummy_rdc; int i; const int idx_str = cm->mi_stride * mi_row + mi_col; @@ -2623,8 +2614,7 @@ static void encode_rd_sb_row(VP9_COMP *cpi, const TileInfo *const tile, &sf->max_partition_size); } rd_pick_partition(cpi, tile, tp, mi_row, mi_col, BLOCK_64X64, - &dummy_rate, &dummy_dist, INT64_MAX, - cpi->pc_root); + &dummy_rdc, INT64_MAX, cpi->pc_root); } } } diff --git a/vp9/encoder/vp9_rd.h b/vp9/encoder/vp9_rd.h index 214f6965b..33fb4ac94 100644 --- a/vp9/encoder/vp9_rd.h +++ b/vp9/encoder/vp9_rd.h @@ -117,6 +117,12 @@ typedef struct RD_OPT { int RDDIV; } RD_OPT; +typedef struct RD_COST { + int rate; + int64_t dist; + int64_t rdcost; +} RD_COST; + struct TileInfo; struct VP9_COMP; struct macroblock; diff --git a/vp9/encoder/vp9_rdopt.c b/vp9/encoder/vp9_rdopt.c index 462bdeb19..1c58941ad 100644 --- a/vp9/encoder/vp9_rdopt.c +++ b/vp9/encoder/vp9_rdopt.c @@ -2702,8 +2702,7 @@ static int64_t handle_inter_mode(VP9_COMP *cpi, MACROBLOCK *x, } void vp9_rd_pick_intra_mode_sb(VP9_COMP *cpi, MACROBLOCK *x, - int *returnrate, int64_t *returndist, - BLOCK_SIZE bsize, + RD_COST *rd_cost, BLOCK_SIZE bsize, PICK_MODE_CONTEXT *ctx, int64_t best_rd) { VP9_COMMON *const cm = &cpi->common; MACROBLOCKD *const xd = &x->e_mbd; @@ -2720,14 +2719,14 @@ void vp9_rd_pick_intra_mode_sb(VP9_COMP *cpi, MACROBLOCK *x, if (rd_pick_intra_sby_mode(cpi, x, &rate_y, &rate_y_tokenonly, &dist_y, &y_skip, bsize, tx_cache, best_rd) >= best_rd) { - *returnrate = INT_MAX; + rd_cost->rate = INT_MAX; return; } } else { y_skip = 0; if (rd_pick_intra_sub_8x8_y_mode(cpi, x, &rate_y, &rate_y_tokenonly, &dist_y, best_rd) >= best_rd) { - *returnrate = INT_MAX; + rd_cost->rate = INT_MAX; return; } } @@ -2739,14 +2738,15 @@ void vp9_rd_pick_intra_mode_sb(VP9_COMP *cpi, MACROBLOCK *x, max_uv_tx_size); if (y_skip && uv_skip) { - *returnrate = rate_y + rate_uv - rate_y_tokenonly - rate_uv_tokenonly + - vp9_cost_bit(vp9_get_skip_prob(cm, xd), 1); - *returndist = dist_y + dist_uv; + rd_cost->rate = rate_y + rate_uv - rate_y_tokenonly - rate_uv_tokenonly + + vp9_cost_bit(vp9_get_skip_prob(cm, xd), 1); + rd_cost->dist = dist_y + dist_uv; vp9_zero(ctx->tx_rd_diff); } else { int i; - *returnrate = rate_y + rate_uv + vp9_cost_bit(vp9_get_skip_prob(cm, xd), 0); - *returndist = dist_y + dist_uv; + rd_cost->rate = rate_y + rate_uv + + vp9_cost_bit(vp9_get_skip_prob(cm, xd), 0); + rd_cost->dist = dist_y + dist_uv; if (cpi->sf.tx_size_search_method == USE_FULL_RD) for (i = 0; i < TX_MODES; i++) { if (tx_cache[i] < INT64_MAX && tx_cache[cm->tx_mode] < INT64_MAX) @@ -2757,6 +2757,7 @@ void vp9_rd_pick_intra_mode_sb(VP9_COMP *cpi, MACROBLOCK *x, } ctx->mic = *xd->mi[0].src_mi; + 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, @@ -2784,9 +2785,7 @@ static void update_rd_thresh_fact(VP9_COMP *cpi, int bsize, int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x, const TileInfo *const tile, int mi_row, int mi_col, - int *returnrate, - int64_t *returndistortion, - BLOCK_SIZE bsize, + RD_COST *rd_cost, BLOCK_SIZE bsize, PICK_MODE_CONTEXT *ctx, int64_t best_rd_so_far) { VP9_COMMON *const cm = &cpi->common; @@ -2859,7 +2858,7 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x, } } - *returnrate = INT_MAX; + rd_cost->rate = INT_MAX; for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) { x->pred_mv_sad[ref_frame] = INT_MAX; @@ -3256,8 +3255,9 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x, best_pred_sse = x->pred_sse[ref_frame]; } - *returnrate = rate2; - *returndistortion = distortion2; + rd_cost->rate = rate2; + rd_cost->dist = distortion2; + rd_cost->rdcost = this_rd; best_rd = this_rd; best_mbmode = *mbmi; best_skip2 = this_skip2; @@ -3473,8 +3473,7 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x, } int64_t vp9_rd_pick_inter_mode_sb_seg_skip(VP9_COMP *cpi, MACROBLOCK *x, - int *returnrate, - int64_t *returndistortion, + RD_COST *rd_cost, BLOCK_SIZE bsize, PICK_MODE_CONTEXT *ctx, int64_t best_rd_so_far) { @@ -3505,7 +3504,7 @@ int64_t vp9_rd_pick_inter_mode_sb_seg_skip(VP9_COMP *cpi, MACROBLOCK *x, for (i = LAST_FRAME; i < MAX_REF_FRAMES; ++i) x->pred_mv_sad[i] = INT_MAX; - *returnrate = INT_MAX; + rd_cost->rate = INT_MAX; assert(vp9_segfeature_active(&cm->seg, segment_id, SEG_LVL_SKIP)); @@ -3554,11 +3553,14 @@ int64_t vp9_rd_pick_inter_mode_sb_seg_skip(VP9_COMP *cpi, MACROBLOCK *x, rate2 += ref_costs_single[LAST_FRAME]; this_rd = RDCOST(x->rdmult, x->rddiv, rate2, distortion2); - *returnrate = rate2; - *returndistortion = distortion2; + rd_cost->rate = rate2; + rd_cost->dist = distortion2; + rd_cost->rdcost = this_rd; - if (this_rd >= best_rd_so_far) + if (this_rd >= best_rd_so_far) { + rd_cost->rdcost = INT64_MAX; return INT64_MAX; + } assert((cm->interp_filter == SWITCHABLE) || (cm->interp_filter == mbmi->interp_filter)); @@ -3580,8 +3582,7 @@ int64_t vp9_rd_pick_inter_mode_sb_seg_skip(VP9_COMP *cpi, MACROBLOCK *x, int64_t vp9_rd_pick_inter_mode_sub8x8(VP9_COMP *cpi, MACROBLOCK *x, const TileInfo *const tile, int mi_row, int mi_col, - int *returnrate, - int64_t *returndistortion, + RD_COST *rd_cost, BLOCK_SIZE bsize, PICK_MODE_CONTEXT *ctx, int64_t best_rd_so_far) { @@ -3639,7 +3640,7 @@ int64_t vp9_rd_pick_inter_mode_sub8x8(VP9_COMP *cpi, MACROBLOCK *x, best_filter_rd[i] = INT64_MAX; rate_uv_intra = INT_MAX; - *returnrate = INT_MAX; + rd_cost->rate = INT_MAX; for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ref_frame++) { if (cpi->ref_frame_flags & flag_list[ref_frame]) { @@ -4014,8 +4015,9 @@ int64_t vp9_rd_pick_inter_mode_sub8x8(VP9_COMP *cpi, MACROBLOCK *x, max_plane = 1; } - *returnrate = rate2; - *returndistortion = distortion2; + rd_cost->rate = rate2; + rd_cost->dist = distortion2; + rd_cost->rdcost = this_rd; best_rd = this_rd; best_yrd = best_rd - RDCOST(x->rdmult, x->rddiv, rate_uv, distortion_uv); @@ -4124,8 +4126,9 @@ int64_t vp9_rd_pick_inter_mode_sub8x8(VP9_COMP *cpi, MACROBLOCK *x, } if (best_rd == INT64_MAX) { - *returnrate = INT_MAX; - *returndistortion = INT64_MAX; + rd_cost->rate = INT_MAX; + rd_cost->dist = INT64_MAX; + rd_cost->rdcost = INT64_MAX; return best_rd; } diff --git a/vp9/encoder/vp9_rdopt.h b/vp9/encoder/vp9_rdopt.h index 50cb108dd..535c03df6 100644 --- a/vp9/encoder/vp9_rdopt.h +++ b/vp9/encoder/vp9_rdopt.h @@ -23,24 +23,22 @@ extern "C" { struct TileInfo; struct VP9_COMP; struct macroblock; +struct RD_COST; void vp9_rd_pick_intra_mode_sb(struct VP9_COMP *cpi, struct macroblock *x, - int *r, int64_t *d, BLOCK_SIZE bsize, + struct RD_COST *rd_cost, BLOCK_SIZE bsize, PICK_MODE_CONTEXT *ctx, int64_t best_rd); int64_t vp9_rd_pick_inter_mode_sb(struct VP9_COMP *cpi, struct macroblock *x, const struct TileInfo *const tile, int mi_row, int mi_col, - int *returnrate, - int64_t *returndistortion, - BLOCK_SIZE bsize, - PICK_MODE_CONTEXT *ctx, + struct RD_COST *rd_cost, + BLOCK_SIZE bsize, PICK_MODE_CONTEXT *ctx, int64_t best_rd_so_far); int64_t vp9_rd_pick_inter_mode_sb_seg_skip(struct VP9_COMP *cpi, struct macroblock *x, - int *returnrate, - int64_t *returndistortion, + struct RD_COST *rd_cost, BLOCK_SIZE bsize, PICK_MODE_CONTEXT *ctx, int64_t best_rd_so_far); @@ -49,10 +47,8 @@ int64_t vp9_rd_pick_inter_mode_sub8x8(struct VP9_COMP *cpi, struct macroblock *x, const struct TileInfo *const tile, int mi_row, int mi_col, - int *returnrate, - int64_t *returndistortion, - BLOCK_SIZE bsize, - PICK_MODE_CONTEXT *ctx, + struct RD_COST *rd_cost, + BLOCK_SIZE bsize, PICK_MODE_CONTEXT *ctx, int64_t best_rd_so_far); #ifdef __cplusplus } // extern "C"