From eea06db1782b078aacfc8e5dc06e8e29710ec0ef Mon Sep 17 00:00:00 2001 From: Cheng Chen Date: Fri, 17 Jan 2020 11:25:56 -0800 Subject: 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 --- vp9/encoder/vp9_encodeframe.c | 64 +++++++++++++++++++++++++++++++++++++++++++ vp9/encoder/vp9_encoder.c | 5 ++++ vp9/encoder/vp9_encoder.h | 37 +++++++++++++++++++++++++ vp9/simple_encode.cc | 2 +- 4 files changed, 107 insertions(+), 1 deletion(-) diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c index 2d1914cee..b89b890b3 100644 --- a/vp9/encoder/vp9_encodeframe.c +++ b/vp9/encoder/vp9_encodeframe.c @@ -3810,6 +3810,60 @@ static int get_rdmult_delta(VP9_COMP *cpi, BLOCK_SIZE bsize, int mi_row, } #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 @@ static int rd_pick_partition(VP9_COMP *cpi, ThreadData *td, 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) { diff --git a/vp9/encoder/vp9_encoder.c b/vp9/encoder/vp9_encoder.c index 182064c48..d849a2511 100644 --- a/vp9/encoder/vp9_encoder.c +++ b/vp9/encoder/vp9_encoder.c @@ -1021,6 +1021,10 @@ static void dealloc_compressor_data(VP9_COMP *cpi) { 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 @@ VP9_COMP *vp9_create_compressor(const VP9EncoderConfig *oxcf, #if CONFIG_RATE_CTRL encode_command_init(&cpi->encode_command); + partition_info_init(cpi); #endif return cpi; diff --git a/vp9/encoder/vp9_encoder.h b/vp9/encoder/vp9_encoder.h index 388653ddc..731687549 100644 --- a/vp9/encoder/vp9_encoder.h +++ b/vp9/encoder/vp9_encoder.h @@ -523,6 +523,15 @@ typedef struct ENCODE_COMMAND { 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 @@ static INLINE void encode_command_reset_external_quantize_index( 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,9 +861,33 @@ typedef struct VP9_COMP { 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; FRAME_UPDATE_TYPE update_type; diff --git a/vp9/simple_encode.cc b/vp9/simple_encode.cc index a290704d5..560465567 100644 --- a/vp9/simple_encode.cc +++ b/vp9/simple_encode.cc @@ -616,7 +616,7 @@ int SimpleEncode::GetCodingFrameNum() const { 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; -- cgit v1.2.3