ref: eea06db1782b078aacfc8e5dc06e8e29710ec0ef
parent: 7a63240c485cd702bead191f36f9bf03d193e7c5
author: Cheng Chen <chengchen@google.com>
date: Fri Jan 17 06:25:56 EST 2020
Store frame partition info Allocate partition information for the frame, and update it when a superblock (64x64) is encoded. The unit size of the smallest block is 4x4. For each 4x4 block, store the current positition (row, column), the start positition (row_start, column_start) of the partition, and the block width and height of the partition. Change-Id: I11c16bbca7e89a088715a1200abd23fe2f9ca1d6
--- a/vp9/encoder/vp9_encodeframe.c
+++ b/vp9/encoder/vp9_encodeframe.c
@@ -3810,6 +3810,60 @@
}
#endif // !CONFIG_REALTIME_ONLY
+#if CONFIG_RATE_CTRL
+static void store_superblock_partition_info(
+ const PC_TREE *const pc_tree, PARTITION_INFO *partition_info,
+ const int square_size_4x4, const int num_unit_rows, const int num_unit_cols,
+ const int row_start_4x4, const int col_start_4x4) {
+ const int subblock_square_size_4x4 = square_size_4x4 >> 1;
+ if (row_start_4x4 >= num_unit_rows || col_start_4x4 >= num_unit_cols) return;
+ assert(pc_tree->partitioning != PARTITION_INVALID);
+ // End node, no split.
+ if (pc_tree->partitioning == PARTITION_NONE ||
+ pc_tree->partitioning == PARTITION_HORZ ||
+ pc_tree->partitioning == PARTITION_VERT || square_size_4x4 == 1) {
+ const int block_width_4x4 = (pc_tree->partitioning == PARTITION_VERT)
+ ? square_size_4x4 >> 1
+ : square_size_4x4;
+ const int block_height_4x4 = (pc_tree->partitioning == PARTITION_HORZ)
+ ? square_size_4x4 >> 1
+ : square_size_4x4;
+ int i, j;
+ for (i = 0; i < block_height_4x4; ++i) {
+ for (j = 0; j < block_width_4x4; ++j) {
+ const int row_4x4 = row_start_4x4 + i;
+ const int col_4x4 = col_start_4x4 + j;
+ const int unit_index = row_4x4 * num_unit_cols + col_4x4;
+ partition_info[unit_index].row = row_4x4 << 2;
+ partition_info[unit_index].column = col_4x4 << 2;
+ partition_info[unit_index].row_start = row_start_4x4 << 2;
+ partition_info[unit_index].column_start = col_start_4x4 << 2;
+ partition_info[unit_index].width = block_width_4x4 << 2;
+ partition_info[unit_index].height = block_height_4x4 << 2;
+ }
+ }
+ return;
+ }
+ // recursively traverse partition tree when partition is split.
+ assert(pc_tree->partitioning == PARTITION_SPLIT);
+ store_superblock_partition_info(pc_tree->split[0], partition_info,
+ subblock_square_size_4x4, num_unit_rows,
+ num_unit_cols, row_start_4x4, col_start_4x4);
+ store_superblock_partition_info(pc_tree->split[1], partition_info,
+ subblock_square_size_4x4, num_unit_rows,
+ num_unit_cols, row_start_4x4,
+ col_start_4x4 + subblock_square_size_4x4);
+ store_superblock_partition_info(
+ pc_tree->split[2], partition_info, subblock_square_size_4x4,
+ num_unit_rows, num_unit_cols, row_start_4x4 + subblock_square_size_4x4,
+ col_start_4x4);
+ store_superblock_partition_info(
+ pc_tree->split[3], partition_info, subblock_square_size_4x4,
+ num_unit_rows, num_unit_cols, row_start_4x4 + subblock_square_size_4x4,
+ col_start_4x4 + subblock_square_size_4x4);
+}
+#endif // CONFIG_RATE_CTRL
+
#if !CONFIG_REALTIME_ONLY
// TODO(jingning,jimbankoski,rbultje): properly skip partition types that are
// unlikely to be selected depending on previous rate-distortion optimization
@@ -4384,6 +4438,16 @@
int output_enabled = (bsize == BLOCK_64X64);
encode_sb(cpi, td, tile_info, tp, mi_row, mi_col, output_enabled, bsize,
pc_tree);
+#if CONFIG_RATE_CTRL
+ // Store partition info.
+ if (output_enabled) {
+ const int num_unit_rows = get_num_unit_4x4(cpi->frame_info.frame_height);
+ const int num_unit_cols = get_num_unit_4x4(cpi->frame_info.frame_width);
+ store_superblock_partition_info(
+ pc_tree, cpi->partition_info, num_4x4_blocks_wide_lookup[BLOCK_64X64],
+ num_unit_rows, num_unit_cols, mi_row << 1, mi_col << 1);
+ }
+#endif // CONFIG_RATE_CTRL
}
if (bsize == BLOCK_64X64) {
--- a/vp9/encoder/vp9_encoder.c
+++ b/vp9/encoder/vp9_encoder.c
@@ -1021,6 +1021,10 @@
vpx_free(cpi->mi_ssim_rdmult_scaling_factors);
cpi->mi_ssim_rdmult_scaling_factors = NULL;
+#if CONFIG_RATE_CTRL
+ free_partition_info(cpi);
+#endif
+
vp9_free_ref_frame_buffers(cm->buffer_pool);
#if CONFIG_VP9_POSTPROC
vp9_free_postproc_buffers(cm);
@@ -2649,6 +2653,7 @@
#if CONFIG_RATE_CTRL
encode_command_init(&cpi->encode_command);
+ partition_info_init(cpi);
#endif
return cpi;
--- a/vp9/encoder/vp9_encoder.h
+++ b/vp9/encoder/vp9_encoder.h
@@ -523,6 +523,15 @@
int external_quantize_index;
} ENCODE_COMMAND;
+typedef struct PARTITION_INFO {
+ int row; // row pixel offset of current 4x4 block
+ int column; // column pixel offset of current 4x4 block
+ int row_start; // row pixel offset of the start of the prediction block
+ int column_start; // column pixel offset of the start of the prediction block
+ int width; // prediction block width
+ int height; // prediction block height
+} PARTITION_INFO;
+
static INLINE void encode_command_init(ENCODE_COMMAND *encode_command) {
vp9_zero(*encode_command);
encode_command->use_external_quantize_index = 0;
@@ -540,6 +549,10 @@
encode_command->use_external_quantize_index = 0;
encode_command->external_quantize_index = -1;
}
+
+// Returns number of units in size of 4, if not multiple not a multiple of 4,
+// round it up. For example, size is 7, return 3.
+static INLINE int get_num_unit_4x4(int size) { return (size + 3) >> 2; }
#endif // CONFIG_RATE_CTRL
typedef struct VP9_COMP {
@@ -848,8 +861,32 @@
vpx_roi_map_t roi;
#if CONFIG_RATE_CTRL
ENCODE_COMMAND encode_command;
+ PARTITION_INFO *partition_info;
#endif
} VP9_COMP;
+
+#if CONFIG_RATE_CTRL
+// Allocates memory for the partition information.
+// The unit size is each 4x4 block.
+// Only called once in vp9_create_compressor().
+static INLINE void partition_info_init(struct VP9_COMP *cpi) {
+ VP9_COMMON *const cm = &cpi->common;
+ const int unit_width = get_num_unit_4x4(cpi->frame_info.frame_width);
+ const int unit_height = get_num_unit_4x4(cpi->frame_info.frame_height);
+ CHECK_MEM_ERROR(cm, cpi->partition_info,
+ (PARTITION_INFO *)vpx_calloc(unit_width * unit_height,
+ sizeof(PARTITION_INFO)));
+ memset(cpi->partition_info, 0,
+ unit_width * unit_height * sizeof(PARTITION_INFO));
+}
+
+// Frees memory of the partition information.
+// Only called once in dealloc_compressor_data().
+static INLINE void free_partition_info(struct VP9_COMP *cpi) {
+ vpx_free(cpi->partition_info);
+ cpi->partition_info = NULL;
+}
+#endif // CONFIG_RATE_CTRL
typedef struct ENCODE_FRAME_RESULT {
int show_idx;
--- a/vp9/simple_encode.cc
+++ b/vp9/simple_encode.cc
@@ -616,7 +616,7 @@
uint64_t SimpleEncode::GetFramePixelCount() const {
assert(frame_width_ % 2 == 0);
- assert(frame_heigh_ % 2 == 0);
+ assert(frame_height_ % 2 == 0);
switch (impl_ptr_->img_fmt) {
case VPX_IMG_FMT_I420: return frame_width_ * frame_height_ * 3 / 2;
case VPX_IMG_FMT_I422: return frame_width_ * frame_height_ * 2;