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.
Unified · Split
| @@ -3810,6 +3810,60 @@ static int get_rdmult_delta(VP9_COMP *cpi, BLOCK_SIZE bsize, int mi_row, · 3809 unmodified lines | |||
| 3810 | } | 3810 | } |
| 3811 | #endif // !CONFIG_REALTIME_ONLY | 3811 | #endif // !CONFIG_REALTIME_ONLY |
| 3812 | 3812 | ||
| 3813 | #if CONFIG_RATE_CTRL | ||
| 3814 | static void store_superblock_partition_info( | ||
| 3815 | const PC_TREE *const pc_tree, PARTITION_INFO *partition_info, | ||
| 3816 | const int square_size_4x4, const int num_unit_rows, const int num_unit_cols, | ||
| 3817 | const int row_start_4x4, const int col_start_4x4) { | ||
| 3818 | const int subblock_square_size_4x4 = square_size_4x4 >> 1; | ||
| 3819 | if (row_start_4x4 >= num_unit_rows || col_start_4x4 >= num_unit_cols) return; | ||
| 3820 | assert(pc_tree->partitioning != PARTITION_INVALID); | ||
| 3821 | // End node, no split. | ||
| 3822 | if (pc_tree->partitioning == PARTITION_NONE || | ||
| 3823 | pc_tree->partitioning == PARTITION_HORZ || | ||
| 3824 | pc_tree->partitioning == PARTITION_VERT || square_size_4x4 == 1) { | ||
| 3825 | const int block_width_4x4 = (pc_tree->partitioning == PARTITION_VERT) | ||
| 3826 | ? square_size_4x4 >> 1 | ||
| 3827 | : square_size_4x4; | ||
| 3828 | const int block_height_4x4 = (pc_tree->partitioning == PARTITION_HORZ) | ||
| 3829 | ? square_size_4x4 >> 1 | ||
| 3830 | : square_size_4x4; | ||
| 3831 | int i, j; | ||
| 3832 | for (i = 0; i < block_height_4x4; ++i) { | ||
| 3833 | for (j = 0; j < block_width_4x4; ++j) { | ||
| 3834 | const int row_4x4 = row_start_4x4 + i; | ||
| 3835 | const int col_4x4 = col_start_4x4 + j; | ||
| 3836 | const int unit_index = row_4x4 * num_unit_cols + col_4x4; | ||
| 3837 | partition_info[unit_index].row = row_4x4 << 2; | ||
| 3838 | partition_info[unit_index].column = col_4x4 << 2; | ||
| 3839 | partition_info[unit_index].row_start = row_start_4x4 << 2; | ||
| 3840 | partition_info[unit_index].column_start = col_start_4x4 << 2; | ||
| 3841 | partition_info[unit_index].width = block_width_4x4 << 2; | ||
| 3842 | partition_info[unit_index].height = block_height_4x4 << 2; | ||
| 3843 | } | ||
| 3844 | } | ||
| 3845 | return; | ||
| 3846 | } | ||
| 3847 | // recursively traverse partition tree when partition is split. | ||
| 3848 | assert(pc_tree->partitioning == PARTITION_SPLIT); | ||
| 3849 | store_superblock_partition_info(pc_tree->split[0], partition_info, | ||
| 3850 | subblock_square_size_4x4, num_unit_rows, | ||
| 3851 | num_unit_cols, row_start_4x4, col_start_4x4); | ||
| 3852 | store_superblock_partition_info(pc_tree->split[1], partition_info, | ||
| 3853 | subblock_square_size_4x4, num_unit_rows, | ||
| 3854 | num_unit_cols, row_start_4x4, | ||
| 3855 | col_start_4x4 + subblock_square_size_4x4); | ||
| 3856 | store_superblock_partition_info( | ||
| 3857 | pc_tree->split[2], partition_info, subblock_square_size_4x4, | ||
| 3858 | num_unit_rows, num_unit_cols, row_start_4x4 + subblock_square_size_4x4, | ||
| 3859 | col_start_4x4); | ||
| 3860 | store_superblock_partition_info( | ||
| 3861 | pc_tree->split[3], partition_info, subblock_square_size_4x4, | ||
| 3862 | num_unit_rows, num_unit_cols, row_start_4x4 + subblock_square_size_4x4, | ||
| 3863 | col_start_4x4 + subblock_square_size_4x4); | ||
| 3864 | } | ||
| 3865 | #endif // CONFIG_RATE_CTRL | ||
| 3866 | |||
| 3813 | #if !CONFIG_REALTIME_ONLY | 3867 | #if !CONFIG_REALTIME_ONLY |
| 3814 | // TODO(jingning,jimbankoski,rbultje): properly skip partition types that are | 3868 | // TODO(jingning,jimbankoski,rbultje): properly skip partition types that are |
| 3815 | // unlikely to be selected depending on previous rate-distortion optimization | 3869 | // unlikely to be selected depending on previous rate-distortion optimization |
| @@ -4384,6 +4438,16 @@ static int rd_pick_partition(VP9_COMP *cpi, ThreadData *td, · 568 unmodified lines | |||
| 4384 | int output_enabled = (bsize == BLOCK_64X64); | 4438 | int output_enabled = (bsize == BLOCK_64X64); |
| 4385 | encode_sb(cpi, td, tile_info, tp, mi_row, mi_col, output_enabled, bsize, | 4439 | encode_sb(cpi, td, tile_info, tp, mi_row, mi_col, output_enabled, bsize, |
| 4386 | pc_tree); | 4440 | pc_tree); |
| 4441 | #if CONFIG_RATE_CTRL | ||
| 4442 | // Store partition info. | ||
| 4443 | if (output_enabled) { | ||
| 4444 | const int num_unit_rows = get_num_unit_4x4(cpi->frame_info.frame_height); | ||
| 4445 | const int num_unit_cols = get_num_unit_4x4(cpi->frame_info.frame_width); | ||
| 4446 | store_superblock_partition_info( | ||
| 4447 | pc_tree, cpi->partition_info, num_4x4_blocks_wide_lookup[BLOCK_64X64], | ||
| 4448 | num_unit_rows, num_unit_cols, mi_row << 1, mi_col << 1); | ||
| 4449 | } | ||
| 4450 | #endif // CONFIG_RATE_CTRL | ||
| 4387 | } | 4451 | } |
| 4388 | 4452 | ||
| 4389 | if (bsize == BLOCK_64X64) { | 4453 | if (bsize == BLOCK_64X64) { |
| @@ -1021,6 +1021,10 @@ static void dealloc_compressor_data(VP9_COMP *cpi) { · 1020 unmodified lines | |||
| 1021 | vpx_free(cpi->mi_ssim_rdmult_scaling_factors); | 1021 | vpx_free(cpi->mi_ssim_rdmult_scaling_factors); |
| 1022 | cpi->mi_ssim_rdmult_scaling_factors = NULL; | 1022 | cpi->mi_ssim_rdmult_scaling_factors = NULL; |
| 1023 | 1023 | ||
| 1024 | #if CONFIG_RATE_CTRL | ||
| 1025 | free_partition_info(cpi); | ||
| 1026 | #endif | ||
| 1027 | |||
| 1024 | vp9_free_ref_frame_buffers(cm->buffer_pool); | 1028 | vp9_free_ref_frame_buffers(cm->buffer_pool); |
| 1025 | #if CONFIG_VP9_POSTPROC | 1029 | #if CONFIG_VP9_POSTPROC |
| 1026 | vp9_free_postproc_buffers(cm); | 1030 | vp9_free_postproc_buffers(cm); |
| @@ -2649,6 +2653,7 @@ VP9_COMP *vp9_create_compressor(const VP9EncoderConfig *oxcf, · 1622 unmodified lines | |||
| 2649 | 2653 | ||
| 2650 | #if CONFIG_RATE_CTRL | 2654 | #if CONFIG_RATE_CTRL |
| 2651 | encode_command_init(&cpi->encode_command); | 2655 | encode_command_init(&cpi->encode_command); |
| 2656 | partition_info_init(cpi); | ||
| 2652 | #endif | 2657 | #endif |
| 2653 | 2658 | ||
| 2654 | return cpi; | 2659 | return cpi; |
| @@ -523,6 +523,15 @@ typedef struct ENCODE_COMMAND { · 522 unmodified lines | |||
| 523 | int external_quantize_index; | 523 | int external_quantize_index; |
| 524 | } ENCODE_COMMAND; | 524 | } ENCODE_COMMAND; |
| 525 | 525 | ||
| 526 | typedef struct PARTITION_INFO { | ||
| 527 | int row; // row pixel offset of current 4x4 block | ||
| 528 | int column; // column pixel offset of current 4x4 block | ||
| 529 | int row_start; // row pixel offset of the start of the prediction block | ||
| 530 | int column_start; // column pixel offset of the start of the prediction block | ||
| 531 | int width; // prediction block width | ||
| 532 | int height; // prediction block height | ||
| 533 | } PARTITION_INFO; | ||
| 534 | |||
| 526 | static INLINE void encode_command_init(ENCODE_COMMAND *encode_command) { | 535 | static INLINE void encode_command_init(ENCODE_COMMAND *encode_command) { |
| 527 | vp9_zero(*encode_command); | 536 | vp9_zero(*encode_command); |
| 528 | encode_command->use_external_quantize_index = 0; | 537 | encode_command->use_external_quantize_index = 0; |
| @@ -540,6 +549,10 @@ static INLINE void encode_command_reset_external_quantize_index( · 11 unmodified lines | |||
| 540 | encode_command->use_external_quantize_index = 0; | 549 | encode_command->use_external_quantize_index = 0; |
| 541 | encode_command->external_quantize_index = -1; | 550 | encode_command->external_quantize_index = -1; |
| 542 | } | 551 | } |
| 552 | |||
| 553 | // Returns number of units in size of 4, if not multiple not a multiple of 4, | ||
| 554 | // round it up. For example, size is 7, return 3. | ||
| 555 | static INLINE int get_num_unit_4x4(int size) { return (size + 3) >> 2; } | ||
| 543 | #endif // CONFIG_RATE_CTRL | 556 | #endif // CONFIG_RATE_CTRL |
| 544 | 557 | ||
| 545 | typedef struct VP9_COMP { | 558 | typedef struct VP9_COMP { |
| @@ -848,9 +861,33 @@ typedef struct VP9_COMP { · 302 unmodified lines | |||
| 848 | vpx_roi_map_t roi; | 861 | vpx_roi_map_t roi; |
| 849 | #if CONFIG_RATE_CTRL | 862 | #if CONFIG_RATE_CTRL |
| 850 | ENCODE_COMMAND encode_command; | 863 | ENCODE_COMMAND encode_command; |
| 864 | PARTITION_INFO *partition_info; | ||
| 851 | #endif | 865 | #endif |
| 852 | } VP9_COMP; | 866 | } VP9_COMP; |
| 853 | 867 | ||
| 868 | #if CONFIG_RATE_CTRL | ||
| 869 | // Allocates memory for the partition information. | ||
| 870 | // The unit size is each 4x4 block. | ||
| 871 | // Only called once in vp9_create_compressor(). | ||
| 872 | static INLINE void partition_info_init(struct VP9_COMP *cpi) { | ||
| 873 | VP9_COMMON *const cm = &cpi->common; | ||
| 874 | const int unit_width = get_num_unit_4x4(cpi->frame_info.frame_width); | ||
| 875 | const int unit_height = get_num_unit_4x4(cpi->frame_info.frame_height); | ||
| 876 | CHECK_MEM_ERROR(cm, cpi->partition_info, | ||
| 877 | (PARTITION_INFO *)vpx_calloc(unit_width * unit_height, | ||
| 878 | sizeof(PARTITION_INFO))); | ||
| 879 | memset(cpi->partition_info, 0, | ||
| 880 | unit_width * unit_height * sizeof(PARTITION_INFO)); | ||
| 881 | } | ||
| 882 | |||
| 883 | // Frees memory of the partition information. | ||
| 884 | // Only called once in dealloc_compressor_data(). | ||
| 885 | static INLINE void free_partition_info(struct VP9_COMP *cpi) { | ||
| 886 | vpx_free(cpi->partition_info); | ||
| 887 | cpi->partition_info = NULL; | ||
| 888 | } | ||
| 889 | #endif // CONFIG_RATE_CTRL | ||
| 890 | |||
| 854 | typedef struct ENCODE_FRAME_RESULT { | 891 | typedef struct ENCODE_FRAME_RESULT { |
| 855 | int show_idx; | 892 | int show_idx; |
| 856 | FRAME_UPDATE_TYPE update_type; | 893 | FRAME_UPDATE_TYPE update_type; |
| @@ -616,7 +616,7 @@ int SimpleEncode::GetCodingFrameNum() const { · 615 unmodified lines | |||
| 616 | 616 | ||
| 617 | uint64_t SimpleEncode::GetFramePixelCount() const { | 617 | uint64_t SimpleEncode::GetFramePixelCount() const { |
| 618 | assert(frame_width_ % 2 == 0); | 618 | assert(frame_width_ % 2 == 0); |
| 619 | assert(frame_heigh_ % 2 == 0); | 619 | assert(frame_height_ % 2 == 0); |
| 620 | switch (impl_ptr_->img_fmt) { | 620 | switch (impl_ptr_->img_fmt) { |
| 621 | case VPX_IMG_FMT_I420: return frame_width_ * frame_height_ * 3 / 2; | 621 | case VPX_IMG_FMT_I420: return frame_width_ * frame_height_ * 3 / 2; |
| 622 | case VPX_IMG_FMT_I422: return frame_width_ * frame_height_ * 2; | 622 | case VPX_IMG_FMT_I422: return frame_width_ * frame_height_ * 2; |