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 | 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 | 3867 | #if !CONFIG_REALTIME_ONLY |
| 3814 | 3868 | // TODO(jingning,jimbankoski,rbultje): properly skip partition types that are |
| 3815 | 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 | 4438 | int output_enabled = (bsize == BLOCK_64X64); |
| 4385 | 4439 | encode_sb(cpi, td, tile_info, tp, mi_row, mi_col, output_enabled, bsize, |
| 4386 | 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 | 4453 | if (bsize == BLOCK_64X64) { |
| @@ -1021,6 +1021,10 @@ static void dealloc_compressor_data(VP9_COMP *cpi) { · 1020 unmodified lines | ||
| 1021 | 1021 | vpx_free(cpi->mi_ssim_rdmult_scaling_factors); |
| 1022 | 1022 | cpi->mi_ssim_rdmult_scaling_factors = NULL; |
| 1023 | 1023 | |
| 1024 | +#if CONFIG_RATE_CTRL | |
| 1025 | + free_partition_info(cpi); | |
| 1026 | +#endif | |
| 1027 | + | |
| 1024 | 1028 | vp9_free_ref_frame_buffers(cm->buffer_pool); |
| 1025 | 1029 | #if CONFIG_VP9_POSTPROC |
| 1026 | 1030 | vp9_free_postproc_buffers(cm); |
| @@ -2649,6 +2653,7 @@ VP9_COMP *vp9_create_compressor(const VP9EncoderConfig *oxcf, · 1622 unmodified lines | ||
| 2649 | 2653 | |
| 2650 | 2654 | #if CONFIG_RATE_CTRL |
| 2651 | 2655 | encode_command_init(&cpi->encode_command); |
| 2656 | + partition_info_init(cpi); | |
| 2652 | 2657 | #endif |
| 2653 | 2658 | |
| 2654 | 2659 | return cpi; |
| @@ -523,6 +523,15 @@ typedef struct ENCODE_COMMAND { · 522 unmodified lines | ||
| 523 | 523 | int external_quantize_index; |
| 524 | 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 | 535 | static INLINE void encode_command_init(ENCODE_COMMAND *encode_command) { |
| 527 | 536 | vp9_zero(*encode_command); |
| 528 | 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 | 549 | encode_command->use_external_quantize_index = 0; |
| 541 | 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 | 556 | #endif // CONFIG_RATE_CTRL |
| 544 | 557 | |
| 545 | 558 | typedef struct VP9_COMP { |
| @@ -848,9 +861,33 @@ typedef struct VP9_COMP { · 302 unmodified lines | ||
| 848 | 861 | vpx_roi_map_t roi; |
| 849 | 862 | #if CONFIG_RATE_CTRL |
| 850 | 863 | ENCODE_COMMAND encode_command; |
| 864 | + PARTITION_INFO *partition_info; | |
| 851 | 865 | #endif |
| 852 | 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 | 891 | typedef struct ENCODE_FRAME_RESULT { |
| 855 | 892 | int show_idx; |
| 856 | 893 | FRAME_UPDATE_TYPE update_type; |
| @@ -616,7 +616,7 @@ int SimpleEncode::GetCodingFrameNum() const { · 615 unmodified lines | ||
| 616 | 616 | |
| 617 | 617 | uint64_t SimpleEncode::GetFramePixelCount() const { |
| 618 | 618 | assert(frame_width_ % 2 == 0); |
| 619 | − assert(frame_heigh_ % 2 == 0); | |
| 619 | + assert(frame_height_ % 2 == 0); | |
| 620 | 620 | switch (impl_ptr_->img_fmt) { |
| 621 | 621 | case VPX_IMG_FMT_I420: return frame_width_ * frame_height_ * 3 / 2; |
| 622 | 622 | case VPX_IMG_FMT_I422: return frame_width_ * frame_height_ * 2; |