From d4158283e79fbdf684ec4f2f983509b793c59090 Mon Sep 17 00:00:00 2001 From: Jim Bankoski Date: Mon, 1 Jul 2013 18:18:50 -0700 Subject: [PATCH] use partitioning from last frame This cl converts use partition from last frame to do the following: if part is none,horz, vert -> try split if part != none and one of the children is not split - try none Change-Id: I5b6c659e35f3ac9f11c051b92ba98af6d7e8aa87 Signed-off-by: Jim Bankoski --- vp9/encoder/vp9_encodeframe.c | 193 +++++++++++++++++++++++++++------- vp9/encoder/vp9_onyx_if.c | 86 +++++++-------- vp9/encoder/vp9_onyx_int.h | 2 + 3 files changed, 204 insertions(+), 77 deletions(-) diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c index a8fb4539c..e4c000495 100644 --- a/vp9/encoder/vp9_encodeframe.c +++ b/vp9/encoder/vp9_encodeframe.c @@ -322,6 +322,7 @@ static void update_state(VP9_COMP *cpi, PICK_MODE_CONTEXT *ctx, MACROBLOCKD * const xd = &x->e_mbd; MODE_INFO *mi = &ctx->mic; MB_MODE_INFO * const mbmi = &xd->mode_info_context->mbmi; + int mb_mode_index = ctx->best_mode_index; const int mis = cpi->common.mode_info_stride; const int bh = 1 << mi_height_log2(bsize), bw = 1 << mi_width_log2(bsize); @@ -690,8 +691,8 @@ static void restore_context(VP9_COMP *cpi, int mi_row, int mi_col, vpx_memcpy(cm->above_seg_context + mi_col, sa, sizeof(PARTITION_CONTEXT) * mw); vpx_memcpy(cm->left_seg_context + (mi_row & MI_MASK), sl, - sizeof(PARTITION_CONTEXT) * mh) - ;} + sizeof(PARTITION_CONTEXT) * mh); +} static void save_context(VP9_COMP *cpi, int mi_row, int mi_col, ENTROPY_CONTEXT a[16 * MAX_MB_PLANE], ENTROPY_CONTEXT l[16 * MAX_MB_PLANE], @@ -1158,16 +1159,27 @@ static void rd_use_partition(VP9_COMP *cpi, MODE_INFO *m, TOKENEXTRA **tp, int bwl = b_width_log2(m->mbmi.sb_type); int bhl = b_height_log2(m->mbmi.sb_type); int bsl = b_width_log2(bsize); - int bh = (1 << bhl); int bs = (1 << bsl); + int bh = (1 << bhl); + int ms = bs / 2; + int mh = bh / 2; int bss = (1 << bsl) / 4; int i, pl; PARTITION_TYPE partition; BLOCK_SIZE_TYPE subsize; ENTROPY_CONTEXT l[16 * MAX_MB_PLANE], a[16 * MAX_MB_PLANE]; PARTITION_CONTEXT sl[8], sa[8]; - int r = 0; - int64_t d = 0; + int last_part_rate = INT_MAX; + int64_t last_part_dist = INT_MAX; + int split_rate = INT_MAX; + int64_t split_dist = INT_MAX; + int none_rate = INT_MAX; + int64_t none_dist = INT_MAX; + int chosen_rate = INT_MAX; + int64_t chosen_dist = INT_MAX; + BLOCK_SIZE_TYPE sub_subsize = BLOCK_SIZE_AB4X4; + int splits_below = 0; + BLOCK_SIZE_TYPE bs_type = m->mbmi.sb_type; if (mi_row >= cm->mi_rows || mi_col >= cm->mi_cols) return; @@ -1195,60 +1207,96 @@ static void rd_use_partition(VP9_COMP *cpi, MODE_INFO *m, TOKENEXTRA **tp, } else { *(get_sb_partitioning(x, bsize)) = subsize; } - pl = partition_plane_context(xd, bsize); save_context(cpi, mi_row, mi_col, a, l, sa, sl, bsize); + + if (cpi->sf.adjust_partitioning_from_last_frame) { + // Check if any of the sub blocks are further split. + if (partition == PARTITION_SPLIT && subsize > BLOCK_SIZE_SB8X8) { + sub_subsize = get_subsize(subsize, PARTITION_SPLIT); + splits_below = 1; + for (i = 0; i < 4; i++) { + int jj = i >> 1, ii = i & 0x01; + if (m[jj * bss * mis + ii * bss].mbmi.sb_type >= sub_subsize) { + splits_below = 0; + } + } + } + + // If partition is not none try none unless each of the 4 splits are split + // even further.. + if (partition != PARTITION_NONE && !splits_below && + mi_row + (ms >> 1) < cm->mi_rows && + mi_col + (ms >> 1) < cm->mi_cols) { + *(get_sb_partitioning(x, bsize)) = bsize; + pick_sb_modes(cpi, mi_row, mi_col, tp, &none_rate, &none_dist, bsize, + get_block_context(x, bsize)); + + set_partition_seg_context(cm, xd, mi_row, mi_col); + pl = partition_plane_context(xd, bsize); + none_rate += x->partition_cost[pl][PARTITION_NONE]; + + restore_context(cpi, mi_row, mi_col, a, l, sa, sl, bsize); + m->mbmi.sb_type = bs_type; + *(get_sb_partitioning(x, bsize)) = subsize; + } + } + switch (partition) { case PARTITION_NONE: - pick_sb_modes(cpi, mi_row, mi_col, tp, &r, &d, bsize, - get_block_context(x, bsize)); - r += x->partition_cost[pl][PARTITION_NONE]; + pick_sb_modes(cpi, mi_row, mi_col, tp, &last_part_rate, &last_part_dist, + bsize, get_block_context(x, bsize)); + set_partition_seg_context(cm, xd, mi_row, mi_col); + pl = partition_plane_context(xd, bsize); + last_part_rate += x->partition_cost[pl][PARTITION_NONE]; break; case PARTITION_HORZ: *(get_sb_index(xd, subsize)) = 0; - pick_sb_modes(cpi, mi_row, mi_col, tp, &r, &d, subsize, - get_block_context(x, subsize)); - if (mi_row + (bh >> 1) <= cm->mi_rows) { + pick_sb_modes(cpi, mi_row, mi_col, tp, &last_part_rate, &last_part_dist, + subsize, get_block_context(x, subsize)); + if (bsize >= BLOCK_SIZE_SB8X8 && mi_row + (mh >> 1) < cm->mi_rows) { int rt = 0; int64_t dt = 0; update_state(cpi, get_block_context(x, subsize), subsize, 0); encode_superblock(cpi, tp, 0, mi_row, mi_col, subsize); *(get_sb_index(xd, subsize)) = 1; - pick_sb_modes(cpi, mi_row + (bs >> 2), mi_col, tp, &rt, &dt, subsize, + pick_sb_modes(cpi, mi_row + (ms >> 1), mi_col, tp, &rt, &dt, subsize, get_block_context(x, subsize)); - r += rt; - d += dt; + last_part_rate += rt; + last_part_dist += dt; } set_partition_seg_context(cm, xd, mi_row, mi_col); pl = partition_plane_context(xd, bsize); - r += x->partition_cost[pl][PARTITION_HORZ]; + last_part_rate += x->partition_cost[pl][PARTITION_HORZ]; break; case PARTITION_VERT: *(get_sb_index(xd, subsize)) = 0; - pick_sb_modes(cpi, mi_row, mi_col, tp, &r, &d, subsize, - get_block_context(x, subsize)); - if (mi_col + (bs >> 1) <= cm->mi_cols) { + pick_sb_modes(cpi, mi_row, mi_col, tp, &last_part_rate, &last_part_dist, + subsize, get_block_context(x, subsize)); + if (bsize >= BLOCK_SIZE_SB8X8 && mi_col + (ms >> 1) < cm->mi_cols) { int rt = 0; int64_t dt = 0; update_state(cpi, get_block_context(x, subsize), subsize, 0); encode_superblock(cpi, tp, 0, mi_row, mi_col, subsize); *(get_sb_index(xd, subsize)) = 1; - pick_sb_modes(cpi, mi_row, mi_col + (bs >> 2), tp, &rt, &dt, subsize, + pick_sb_modes(cpi, mi_row, mi_col + (ms >> 1), tp, &rt, &dt, subsize, get_block_context(x, subsize)); - r += rt; - d += dt; + last_part_rate += rt; + last_part_dist += dt; } set_partition_seg_context(cm, xd, mi_row, mi_col); pl = partition_plane_context(xd, bsize); - r += x->partition_cost[pl][PARTITION_VERT]; - restore_context(cpi, mi_row, mi_col, a, l, sa, sl, bsize); + last_part_rate += x->partition_cost[pl][PARTITION_VERT]; break; case PARTITION_SPLIT: + // Split partition. + last_part_rate = 0; + last_part_dist = 0; for (i = 0; i < 4; i++) { - int x_idx = (i & 1) * (bs >> 2); - int y_idx = (i >> 1) * (bs >> 2); + int x_idx = (i & 1) * (ms >> 1); + int y_idx = (i >> 1) * (ms >> 1); int jj = i >> 1, ii = i & 0x01; - int rt = 0; - int64_t dt = 0; + int rt; + int64_t dt; if ((mi_row + y_idx >= cm->mi_rows) || (mi_col + x_idx >= cm->mi_cols)) continue; @@ -1257,23 +1305,94 @@ static void rd_use_partition(VP9_COMP *cpi, MODE_INFO *m, TOKENEXTRA **tp, rd_use_partition(cpi, m + jj * bss * mis + ii * bss, tp, mi_row + y_idx, mi_col + x_idx, subsize, &rt, &dt); - r += rt; - d += dt; + last_part_rate += rt; + last_part_dist += dt; } set_partition_seg_context(cm, xd, mi_row, mi_col); pl = partition_plane_context(xd, bsize); - r += x->partition_cost[pl][PARTITION_SPLIT]; + last_part_rate += x->partition_cost[pl][PARTITION_SPLIT]; break; default: assert(0); } + if (cpi->sf.adjust_partitioning_from_last_frame + && partition != PARTITION_SPLIT && bsize > BLOCK_SIZE_SB8X8 + && (mi_row + ms < cm->mi_rows || mi_row + (ms >> 1) == cm->mi_rows) + && (mi_col + ms < cm->mi_cols || mi_col + (ms >> 1) == cm->mi_cols)) { + BLOCK_SIZE_TYPE split_subsize = get_subsize(bsize, PARTITION_SPLIT); + split_rate = 0; + split_dist = 0; + restore_context(cpi, mi_row, mi_col, a, l, sa, sl, bsize); + + // Split partition. + for (i = 0; i < 4; i++) { + int x_idx = (i & 1) * (bs >> 2); + int y_idx = (i >> 1) * (bs >> 2); + int rt = 0; + int64_t dt = 0; + ENTROPY_CONTEXT l[16 * MAX_MB_PLANE], a[16 * MAX_MB_PLANE]; + PARTITION_CONTEXT sl[8], sa[8]; + + if ((mi_row + y_idx >= cm->mi_rows) + || (mi_col + x_idx >= cm->mi_cols)) + continue; + + *(get_sb_index(xd, split_subsize)) = i; + *(get_sb_partitioning(x, bsize)) = split_subsize; + *(get_sb_partitioning(x, split_subsize)) = split_subsize; + + save_context(cpi, mi_row, mi_col, a, l, sa, sl, bsize); + + pick_sb_modes(cpi, mi_row + y_idx, mi_col + x_idx, tp, &rt, &dt, + split_subsize, get_block_context(x, split_subsize)); + + restore_context(cpi, mi_row, mi_col, a, l, sa, sl, bsize); + + if (rt < INT_MAX && dt < INT_MAX) + encode_sb(cpi, tp, mi_row + y_idx, mi_col + x_idx, 0, + split_subsize); + + split_rate += rt; + split_dist += dt; + set_partition_seg_context(cm, xd, mi_row + y_idx, mi_col + x_idx); + pl = partition_plane_context(xd, bsize); + split_rate += x->partition_cost[pl][PARTITION_NONE]; + } + set_partition_seg_context(cm, xd, mi_row, mi_col); + pl = partition_plane_context(xd, bsize); + split_rate += x->partition_cost[pl][PARTITION_SPLIT]; + + chosen_rate = split_rate; + chosen_dist = split_dist; + } + + // If last_part is better set the partitioning to that... + if (RDCOST(x->rdmult, x->rddiv, last_part_rate, last_part_dist) + < RDCOST(x->rdmult, x->rddiv, chosen_rate, chosen_dist)) { + m->mbmi.sb_type = bsize; + if (bsize >= BLOCK_SIZE_SB8X8) + *(get_sb_partitioning(x, bsize)) = subsize; + chosen_rate = last_part_rate; + chosen_dist = last_part_dist; + } + // If none was better set the partitioning to that... + if (RDCOST(x->rdmult, x->rddiv, chosen_rate, chosen_dist) + > RDCOST(x->rdmult, x->rddiv, none_rate, none_dist)) { + if (bsize >= BLOCK_SIZE_SB8X8) + *(get_sb_partitioning(x, bsize)) = bsize; + chosen_rate = none_rate; + chosen_dist = none_dist; + } restore_context(cpi, mi_row, mi_col, a, l, sa, sl, bsize); - if (r < INT_MAX && d < INT_MAX) - encode_sb(cpi, tp, mi_row, mi_col, bsize == BLOCK_SIZE_SB64X64, bsize); - *rate = r; - *dist = d; + // We must have chosen a partitioning and encoding or we'll fail later on. + // No other opportunities for success. + assert(chosen_rate < INT_MAX && chosen_dist < INT_MAX); + + encode_sb(cpi, tp, mi_row, mi_col, bsize == BLOCK_SIZE_SB64X64, bsize); + *rate = chosen_rate; + *dist = chosen_dist; } @@ -1483,7 +1602,9 @@ static void encode_sb_row(VP9_COMP *cpi, int mi_row, TOKENEXTRA **tp, rd_use_partition(cpi, m, tp, mi_row, mi_col, BLOCK_SIZE_SB64X64, &dummy_rate, &dummy_dist); } else { - if ((cpi->common.current_video_frame & 1) == 0 || cm->prev_mi == 0 + if ((cpi->common.current_video_frame + % cpi->sf.last_partitioning_redo_frequency) == 0 + || cm->prev_mi == 0 || cpi->common.show_frame == 0 || cpi->common.frame_type == KEY_FRAME || cpi->is_src_frame_alt_ref) { diff --git a/vp9/encoder/vp9_onyx_if.c b/vp9/encoder/vp9_onyx_if.c index e1fb7e0b7..bb4bbd87c 100644 --- a/vp9/encoder/vp9_onyx_if.c +++ b/vp9/encoder/vp9_onyx_if.c @@ -545,52 +545,49 @@ static void set_rd_speed_thresholds(VP9_COMP *cpi, int mode, int speed) { for (i = 0; i < MAX_MODES; ++i) sf->thresh_mult[i] = mode == 0 ? -500 : 0; - sf->thresh_mult[THR_ZEROMV ] = 0; - sf->thresh_mult[THR_ZEROG ] = 0; - sf->thresh_mult[THR_ZEROA ] = 0; + sf->thresh_mult[THR_ZEROMV] = 0; + sf->thresh_mult[THR_ZEROG] = 0; + sf->thresh_mult[THR_ZEROA] = 0; sf->thresh_mult[THR_NEARESTMV] = 0; - sf->thresh_mult[THR_NEARESTG ] = 0; - sf->thresh_mult[THR_NEARESTA ] = 0; + sf->thresh_mult[THR_NEARESTG] = 0; + sf->thresh_mult[THR_NEARESTA] = 0; - sf->thresh_mult[THR_NEARMV ] += speed_multiplier * 1000; - sf->thresh_mult[THR_NEARG ] += speed_multiplier * 1000; - sf->thresh_mult[THR_NEARA ] += speed_multiplier * 1000; + sf->thresh_mult[THR_NEARMV] += speed_multiplier * 1000; + sf->thresh_mult[THR_NEARG] += speed_multiplier * 1000; + sf->thresh_mult[THR_NEARA] += speed_multiplier * 1000; - sf->thresh_mult[THR_DC ] += speed_multiplier * 1000; - sf->thresh_mult[THR_TM ] += speed_multiplier * 1000; - sf->thresh_mult[THR_V_PRED ] += speed_multiplier * 1500; - sf->thresh_mult[THR_H_PRED ] += speed_multiplier * 1500; - sf->thresh_mult[THR_D45_PRED ] += speed_multiplier * 2000; + sf->thresh_mult[THR_DC] += speed_multiplier * 1000; + sf->thresh_mult[THR_TM] += speed_multiplier * 1000; + sf->thresh_mult[THR_V_PRED] += speed_multiplier * 1500; + sf->thresh_mult[THR_H_PRED] += speed_multiplier * 1500; + sf->thresh_mult[THR_D45_PRED] += speed_multiplier * 2000; sf->thresh_mult[THR_D135_PRED] += speed_multiplier * 2000; sf->thresh_mult[THR_D117_PRED] += speed_multiplier * 2000; sf->thresh_mult[THR_D153_PRED] += speed_multiplier * 2000; - sf->thresh_mult[THR_D27_PRED ] += speed_multiplier * 2000; - sf->thresh_mult[THR_D63_PRED ] += speed_multiplier * 2000; + sf->thresh_mult[THR_D27_PRED] += speed_multiplier * 2000; + sf->thresh_mult[THR_D63_PRED] += speed_multiplier * 2000; - sf->thresh_mult[THR_NEWMV ] += new_motion_multiplier * 1000; - sf->thresh_mult[THR_NEWG ] += new_motion_multiplier * 1000; - sf->thresh_mult[THR_NEWA ] += new_motion_multiplier * 1000; + sf->thresh_mult[THR_NEWMV] += new_motion_multiplier * 1000; + sf->thresh_mult[THR_NEWG] += new_motion_multiplier * 1000; + sf->thresh_mult[THR_NEWA] += new_motion_multiplier * 1000; - sf->thresh_mult[THR_COMP_ZEROLA ] += speed_multiplier * 1500; - sf->thresh_mult[THR_COMP_ZEROGA ] += speed_multiplier * 1500; + sf->thresh_mult[THR_COMP_ZEROLA] += speed_multiplier * 1500; + sf->thresh_mult[THR_COMP_ZEROGA] += speed_multiplier * 1500; sf->thresh_mult[THR_COMP_NEARESTLA] += speed_multiplier * 1500; sf->thresh_mult[THR_COMP_NEARESTGA] += speed_multiplier * 1500; - sf->thresh_mult[THR_COMP_NEARLA ] += speed_multiplier * 1500; - sf->thresh_mult[THR_COMP_NEARGA ] += speed_multiplier * 1500; + sf->thresh_mult[THR_COMP_NEARLA] += speed_multiplier * 1500; + sf->thresh_mult[THR_COMP_NEARGA] += speed_multiplier * 1500; - sf->thresh_mult[THR_COMP_NEWLA ] += new_motion_multiplier * 2000; - sf->thresh_mult[THR_COMP_NEWGA ] += new_motion_multiplier * 2000; + sf->thresh_mult[THR_COMP_NEWLA] += new_motion_multiplier * 2000; + sf->thresh_mult[THR_COMP_NEWGA] += new_motion_multiplier * 2000; - sf->thresh_mult[THR_B_PRED ] += speed_multiplier * 2500; + sf->thresh_mult[THR_B_PRED] += speed_multiplier * 2500; - sf->thresh_mult[THR_SPLITMV ] += new_motion_multiplier * 2500; - sf->thresh_mult[THR_SPLITG ] += new_motion_multiplier * 2500; - sf->thresh_mult[THR_SPLITA ] += new_motion_multiplier * 2500; - sf->thresh_mult[THR_COMP_SPLITLA ] += new_motion_multiplier * 4500; - sf->thresh_mult[THR_COMP_SPLITGA ] += new_motion_multiplier * 4500; + sf->thresh_mult[THR_SPLITMV] += new_motion_multiplier * 2500; + sf->thresh_mult[THR_SPLITG] += new_motion_multiplier * 2500; if (cpi->sf.skip_lots_of_modes) { for (i = 0; i < MAX_MODES; ++i) @@ -660,6 +657,7 @@ void vp9_set_speed_features(VP9_COMP *cpi) { int mode = cpi->compressor_speed; int speed = cpi->speed; int i; + // Only modes 0 and 1 supported for now in experimental code basae if (mode > 1) mode = 1; @@ -698,6 +696,7 @@ void vp9_set_speed_features(VP9_COMP *cpi) { sf->use_8tap_always = 0; sf->use_avoid_tested_higherror = 0; sf->skip_lots_of_modes = 0; + sf->adjust_thresholds_by_speed = 0; sf->partition_by_variance = 0; sf->use_one_partition_size_always = 0; sf->less_rectangular_check = 0; @@ -705,6 +704,8 @@ void vp9_set_speed_features(VP9_COMP *cpi) { sf->less_than_block_size = BLOCK_SIZE_MB16X16; sf->use_partitions_greater_than = 0; sf->greater_than_block_size = BLOCK_SIZE_SB8X8; + sf->adjust_partitioning_from_last_frame = 0; + sf->last_partitioning_redo_frequency = 4; #if CONFIG_MULTIPLE_ARF // Switch segmentation off. @@ -737,46 +738,49 @@ void vp9_set_speed_features(VP9_COMP *cpi) { cpi->common.show_frame == 0); } if (speed == 2) { - sf->use_largest_txform = !(cpi->common.frame_type == KEY_FRAME || - cpi->common.intra_only || - cpi->common.show_frame == 0); + sf->use_largest_txform = 1; sf->adjust_thresholds_by_speed = 1; sf->less_rectangular_check = 1; sf->comp_inter_joint_search_thresh = BLOCK_SIZE_TYPES; sf->reduce_first_step_size = 1; sf->optimize_coefficients = 0; sf->use_lastframe_partitioning = 1; + sf->adjust_partitioning_from_last_frame = 1; + sf->last_partitioning_redo_frequency = 3; } if (speed == 3) { sf->comp_inter_joint_search_thresh = BLOCK_SIZE_TYPES; sf->partition_by_variance = 1; - sf->reduce_first_step_size = 1; } if (speed == 4) { - sf->reduce_first_step_size = 1; sf->comp_inter_joint_search_thresh = BLOCK_SIZE_TYPES; sf->use_one_partition_size_always = 1; sf->always_this_block_size = BLOCK_SIZE_MB16X16; } -/* if (speed == 2) { - sf->reduce_first_step_size = 0; + /* + if (speed == 2) { + sf->first_step = 0; sf->comp_inter_joint_search_thresh = BLOCK_SIZE_SB8X8; sf->use_partitions_less_than = 1; sf->less_than_block_size = BLOCK_SIZE_MB16X16; } if (speed == 3) { - sf->reduce_first_step_size = 0; + sf->first_step = 0; sf->comp_inter_joint_search_thresh = BLOCK_SIZE_SB8X8; sf->use_partitions_greater_than = 1; sf->greater_than_block_size = BLOCK_SIZE_SB8X8; - }*/ + } + */ break; }; /* switch */ // Set rd thresholds based on mode and speed setting - set_rd_speed_thresholds(cpi, mode, speed); + if (cpi->sf.adjust_thresholds_by_speed) + set_rd_speed_thresholds(cpi, mode, speed); + else + set_rd_speed_thresholds(cpi, mode, 0); // Slow quant, dct and trellis not worthwhile for first pass // so make sure they are always turned off. @@ -3430,7 +3434,7 @@ static void Pass2Encode(VP9_COMP *cpi, unsigned long *size, vp9_second_pass(cpi); encode_frame_to_data_rate(cpi, size, dest, frame_flags); - //vp9_print_modes_and_motion_vectors(&cpi->common, "encode.stt"); + // vp9_print_modes_and_motion_vectors(&cpi->common, "encode.stt"); #ifdef DISABLE_RC_LONG_TERM_MEM cpi->twopass.bits_left -= cpi->this_frame_target; #else diff --git a/vp9/encoder/vp9_onyx_int.h b/vp9/encoder/vp9_onyx_int.h index 0912dcefc..5aa0947bd 100644 --- a/vp9/encoder/vp9_onyx_int.h +++ b/vp9/encoder/vp9_onyx_int.h @@ -233,6 +233,8 @@ typedef struct { BLOCK_SIZE_TYPE greater_than_block_size; int use_partitions_less_than; BLOCK_SIZE_TYPE less_than_block_size; + int adjust_partitioning_from_last_frame; + int last_partitioning_redo_frequency; } SPEED_FEATURES; enum BlockSize {