: 1000;
cpi->vbp_bsize_min = BLOCK_16X16;
}
+ cpi->vbp_threshold_copy = cpi->vbp_thresholds[0] << 16;
cpi->vbp_threshold_minmax = 15 + (q >> 3);
}
}
}
}
+static void copy_prev_partition(VP9_COMP *cpi, BLOCK_SIZE bsize, int mi_row,
+ int mi_col) {
+ VP9_COMMON *const cm = &cpi->common;
+ BLOCK_SIZE *prev_part = cpi->prev_partition;
+ int start_pos = mi_row * cm->mi_stride + mi_col;
+
+ const int bsl = b_width_log2_lookup[bsize];
+ const int bs = (1 << bsl) / 4;
+ BLOCK_SIZE subsize;
+ PARTITION_TYPE partition;
+ MODE_INFO *mi = NULL;
+
+ if (mi_row >= cm->mi_rows || mi_col >= cm->mi_cols) return;
+
+ partition = partition_lookup[bsl][prev_part[start_pos]];
+ subsize = get_subsize(bsize, partition);
+ mi = cm->mi_grid_visible[mi_row * cm->mi_stride + mi_col];
+
+ if (subsize < BLOCK_8X8) {
+ mi->sb_type = bsize;
+ } else {
+ switch (partition) {
+ case PARTITION_NONE: mi->sb_type = bsize; break;
+ case PARTITION_HORZ:
+ mi->sb_type = subsize;
+ if (mi_row + bs < cm->mi_rows)
+ cm->mi_grid_visible[(mi_row + bs) * cm->mi_stride + mi_col]->sb_type =
+ subsize;
+ break;
+ case PARTITION_VERT:
+ mi->sb_type = subsize;
+ if (mi_col + bs < cm->mi_cols)
+ cm->mi_grid_visible[mi_row * cm->mi_stride + mi_col + bs]->sb_type =
+ subsize;
+ break;
+ case PARTITION_SPLIT:
+ copy_prev_partition(cpi, subsize, mi_row, mi_col);
+ copy_prev_partition(cpi, subsize, mi_row + bs, mi_col);
+ copy_prev_partition(cpi, subsize, mi_row, mi_col + bs);
+ copy_prev_partition(cpi, subsize, mi_row + bs, mi_col + bs);
+ break;
+ default: assert(0);
+ }
+ }
+}
+
+static void update_prev_partition(VP9_COMP *cpi, BLOCK_SIZE bsize, int mi_row,
+ int mi_col) {
+ VP9_COMMON *const cm = &cpi->common;
+ BLOCK_SIZE *prev_part = cpi->prev_partition;
+ int start_pos = mi_row * cm->mi_stride + mi_col;
+ const int bsl = b_width_log2_lookup[bsize];
+ const int bs = (1 << bsl) / 4;
+ BLOCK_SIZE subsize;
+ PARTITION_TYPE partition;
+ const MODE_INFO *mi = NULL;
+
+ if (mi_row >= cm->mi_rows || mi_col >= cm->mi_cols) return;
+
+ mi = cm->mi_grid_visible[start_pos];
+ partition = partition_lookup[bsl][mi->sb_type];
+ subsize = get_subsize(bsize, partition);
+ if (subsize < BLOCK_8X8) {
+ prev_part[start_pos] = bsize;
+ } else {
+ switch (partition) {
+ case PARTITION_NONE: prev_part[start_pos] = bsize; break;
+ case PARTITION_HORZ:
+ prev_part[start_pos] = subsize;
+ if (mi_row + bs < cm->mi_rows)
+ prev_part[start_pos + bs * cm->mi_stride] = subsize;
+ break;
+ case PARTITION_VERT:
+ prev_part[start_pos] = subsize;
+ if (mi_col + bs < cm->mi_cols) prev_part[start_pos + bs] = subsize;
+ break;
+ case PARTITION_SPLIT:
+ update_prev_partition(cpi, subsize, mi_row, mi_col);
+ update_prev_partition(cpi, subsize, mi_row + bs, mi_col);
+ update_prev_partition(cpi, subsize, mi_row, mi_col + bs);
+ update_prev_partition(cpi, subsize, mi_row + bs, mi_col + bs);
+ break;
+ default: assert(0);
+ }
+ }
+}
+
static void chroma_check(VP9_COMP *cpi, MACROBLOCK *x, int bsize,
unsigned int y_sad, int is_key_frame) {
int i;
const int low_res = (cm->width <= 352 && cm->height <= 288);
int variance4x4downsample[16];
int segment_id;
+ int offset = cm->mi_stride * mi_row + mi_col;
set_offsets(cpi, tile, x, mi_row, mi_col, BLOCK_64X64);
segment_id = xd->mi[0]->segment_id;
YV12_BUFFER_CONFIG *yv12 = get_ref_frame_buffer(cpi, LAST_FRAME);
const YV12_BUFFER_CONFIG *yv12_g = NULL;
- unsigned int y_sad_g, y_sad_thr;
+ unsigned int y_sad_g, y_sad_thr, y_sad_last;
bsize = BLOCK_32X32 + (mi_col + 4 < cm->mi_cols) * 2 +
(mi_row + 4 < cm->mi_rows);
mi->interp_filter = BILINEAR;
y_sad = vp9_int_pro_motion_estimation(cpi, x, bsize, mi_row, mi_col);
+ y_sad_last = y_sad;
// Pick ref frame for partitioning, bias last frame when y_sad_g and y_sad
// are close if short_circuit_low_temp_var is on.
y_sad_thr = cpi->sf.short_circuit_low_temp_var ? (y_sad * 7) >> 3 : y_sad;
return 0;
}
}
+
+ // If the y_sad is small enough, copy the partition of the superblock in the
+ // last frame to current frame only if the last frame is not a keyframe.
+ // TODO(jianj) : tune the threshold.
+ if (cpi->sf.copy_partition_flag && cpi->rc.frames_since_key > 1 &&
+ segment_id == CR_SEGMENT_ID_BASE &&
+ cpi->prev_segment_id[offset] == CR_SEGMENT_ID_BASE &&
+ y_sad_last < cpi->vbp_threshold_copy) {
+ if (cpi->prev_partition != NULL) {
+ copy_prev_partition(cpi, BLOCK_64X64, mi_row, mi_col);
+ chroma_check(cpi, x, bsize, y_sad, is_key_frame);
+ return 0;
+ }
+ }
} else {
d = VP9_VAR_OFFS;
dp = 0;
}
}
+ if (cm->frame_type != KEY_FRAME && cpi->sf.copy_partition_flag) {
+ update_prev_partition(cpi, BLOCK_64X64, mi_row, mi_col);
+ cpi->prev_segment_id[offset] = segment_id;
+ }
+
if (cpi->sf.short_circuit_low_temp_var) {
set_low_temp_var_flag(cpi, x, xd, &vt, thresholds, ref_frame_partition,
mi_col, mi_row);