| @@ -3831,10 +3831,37 @@ static void assign_partition_info( · 3830 unmodified lines |
| 3831 | 3831 | } |
| 3832 | 3832 | } |
| 3833 | 3833 | } |
| 3834 | | −static void store_superblock_partition_info( |
| 3835 | | − const PC_TREE *const pc_tree, PARTITION_INFO *partition_info, |
| 3836 | | − const int square_size_4x4, const int num_unit_rows, const int num_unit_cols, |
| 3837 | | − const int row_start_4x4, const int col_start_4x4) { |
| 3834 | + |
| 3835 | +static void assign_motion_vector_info(const int block_width_4x4, |
| 3836 | + const int block_height_4x4, |
| 3837 | + const int row_start_4x4, |
| 3838 | + const int col_start_4x4, |
| 3839 | + const int num_unit_rows, |
| 3840 | + const int num_unit_cols, MV *source_mv[2], |
| 3841 | + MV_REFERENCE_FRAME source_ref_frame[2], |
| 3842 | + MOTION_VECTOR_INFO *motion_vector_info) { |
| 3843 | + int i, j; |
| 3844 | + for (i = 0; i < block_height_4x4; ++i) { |
| 3845 | + for (j = 0; j < block_width_4x4; ++j) { |
| 3846 | + const int row_4x4 = row_start_4x4 + i; |
| 3847 | + const int col_4x4 = col_start_4x4 + j; |
| 3848 | + const int unit_index = row_4x4 * num_unit_cols + col_4x4; |
| 3849 | + if (row_4x4 >= num_unit_rows || col_4x4 >= num_unit_cols) continue; |
| 3850 | + motion_vector_info[unit_index].ref_frame[0] = source_ref_frame[0]; |
| 3851 | + motion_vector_info[unit_index].ref_frame[1] = source_ref_frame[1]; |
| 3852 | + motion_vector_info[unit_index].mv[0].as_mv.row = source_mv[0]->row; |
| 3853 | + motion_vector_info[unit_index].mv[0].as_mv.col = source_mv[0]->col; |
| 3854 | + motion_vector_info[unit_index].mv[1].as_mv.row = source_mv[1]->row; |
| 3855 | + motion_vector_info[unit_index].mv[1].as_mv.col = source_mv[1]->col; |
| 3856 | + } |
| 3857 | + } |
| 3858 | +} |
| 3859 | + |
| 3860 | +static void store_superblock_info( |
| 3861 | + const PC_TREE *const pc_tree, MODE_INFO **mi_grid_visible, |
| 3862 | + const int mi_stride, const int square_size_4x4, const int num_unit_rows, |
| 3863 | + const int num_unit_cols, const int row_start_4x4, const int col_start_4x4, |
| 3864 | + PARTITION_INFO *partition_info, MOTION_VECTOR_INFO *motion_vector_info) { |
| 3838 | 3865 | const int subblock_square_size_4x4 = square_size_4x4 >> 1; |
| 3839 | 3866 | if (row_start_4x4 >= num_unit_rows || col_start_4x4 >= num_unit_cols) return; |
| 3840 | 3867 | assert(pc_tree->partitioning != PARTITION_INVALID); |
| @@ -3842,6 +3869,14 @@ static void store_superblock_partition_info( · 1 unmodified line |
| 3842 | 3869 | if (pc_tree->partitioning == PARTITION_NONE || |
| 3843 | 3870 | pc_tree->partitioning == PARTITION_HORZ || |
| 3844 | 3871 | pc_tree->partitioning == PARTITION_VERT || square_size_4x4 == 1) { |
| 3872 | + const int mi_row = row_start_4x4 >> 1; |
| 3873 | + const int mi_col = col_start_4x4 >> 1; |
| 3874 | + const int mi_idx = mi_stride * mi_row + mi_col; |
| 3875 | + MODE_INFO **mi = mi_grid_visible + mi_idx; |
| 3876 | + MV *source_mv[2]; |
| 3877 | + MV_REFERENCE_FRAME source_ref_frame[2]; |
| 3878 | + |
| 3879 | + // partition info |
| 3845 | 3880 | const int block_width_4x4 = (pc_tree->partitioning == PARTITION_VERT) |
| 3846 | 3881 | ? square_size_4x4 >> 1 |
| 3847 | 3882 | : square_size_4x4; |
| @@ -3861,25 +3896,124 @@ static void store_superblock_partition_info( · 13 unmodified lines |
| 3861 | 3896 | num_unit_cols, partition_info); |
| 3862 | 3897 | } |
| 3863 | 3898 | |
| 3899 | + // motion vector info |
| 3900 | + if (pc_tree->partitioning == PARTITION_HORZ) { |
| 3901 | + int is_valid_second_rectangle = 0; |
| 3902 | + assert(square_size_4x4 > 1); |
| 3903 | + // First rectangle. |
| 3904 | + source_ref_frame[0] = mi[0]->ref_frame[0]; |
| 3905 | + source_ref_frame[1] = mi[0]->ref_frame[1]; |
| 3906 | + source_mv[0] = &mi[0]->mv[0].as_mv; |
| 3907 | + source_mv[1] = &mi[0]->mv[1].as_mv; |
| 3908 | + assign_motion_vector_info(block_width_4x4, block_height_4x4, |
| 3909 | + row_start_4x4, col_start_4x4, num_unit_rows, |
| 3910 | + num_unit_cols, source_mv, source_ref_frame, |
| 3911 | + motion_vector_info); |
| 3912 | + // Second rectangle. |
| 3913 | + if (square_size_4x4 == 2) { |
| 3914 | + is_valid_second_rectangle = 1; |
| 3915 | + source_ref_frame[0] = mi[0]->ref_frame[0]; |
| 3916 | + source_ref_frame[1] = mi[0]->ref_frame[1]; |
| 3917 | + source_mv[0] = &mi[0]->bmi[2].as_mv[0].as_mv; |
| 3918 | + source_mv[1] = &mi[0]->bmi[2].as_mv[1].as_mv; |
| 3919 | + } else { |
| 3920 | + const int mi_row_2 = mi_row + (block_height_4x4 >> 1); |
| 3921 | + const int mi_col_2 = mi_col; |
| 3922 | + if (mi_row_2 * 2 < num_unit_rows && mi_col_2 * 2 < num_unit_cols) { |
| 3923 | + const int mi_idx_2 = mi_stride * mi_row_2 + mi_col_2; |
| 3924 | + is_valid_second_rectangle = 1; |
| 3925 | + mi = mi_grid_visible + mi_idx_2; |
| 3926 | + source_ref_frame[0] = mi[0]->ref_frame[0]; |
| 3927 | + source_ref_frame[1] = mi[0]->ref_frame[1]; |
| 3928 | + source_mv[0] = &mi[0]->mv[0].as_mv; |
| 3929 | + source_mv[1] = &mi[0]->mv[1].as_mv; |
| 3930 | + } |
| 3931 | + } |
| 3932 | + if (is_valid_second_rectangle) { |
| 3933 | + assign_motion_vector_info( |
| 3934 | + block_width_4x4, block_height_4x4, row_start_4x4 + block_height_4x4, |
| 3935 | + col_start_4x4, num_unit_rows, num_unit_cols, source_mv, |
| 3936 | + source_ref_frame, motion_vector_info); |
| 3937 | + } |
| 3938 | + } else if (pc_tree->partitioning == PARTITION_VERT) { |
| 3939 | + int is_valid_second_rectangle = 0; |
| 3940 | + assert(square_size_4x4 > 1); |
| 3941 | + // First rectangle. |
| 3942 | + source_ref_frame[0] = mi[0]->ref_frame[0]; |
| 3943 | + source_ref_frame[1] = mi[0]->ref_frame[1]; |
| 3944 | + source_mv[0] = &mi[0]->mv[0].as_mv; |
| 3945 | + source_mv[1] = &mi[0]->mv[1].as_mv; |
| 3946 | + assign_motion_vector_info(block_width_4x4, block_height_4x4, |
| 3947 | + row_start_4x4, col_start_4x4, num_unit_rows, |
| 3948 | + num_unit_cols, source_mv, source_ref_frame, |
| 3949 | + motion_vector_info); |
| 3950 | + // Second rectangle. |
| 3951 | + if (square_size_4x4 == 2) { |
| 3952 | + is_valid_second_rectangle = 1; |
| 3953 | + source_ref_frame[0] = mi[0]->ref_frame[0]; |
| 3954 | + source_ref_frame[1] = mi[0]->ref_frame[1]; |
| 3955 | + source_mv[0] = &mi[0]->bmi[1].as_mv[0].as_mv; |
| 3956 | + source_mv[1] = &mi[0]->bmi[1].as_mv[1].as_mv; |
| 3957 | + } else { |
| 3958 | + const int mi_row_2 = mi_row; |
| 3959 | + const int mi_col_2 = mi_col + (block_width_4x4 >> 1); |
| 3960 | + if (mi_row_2 * 2 < num_unit_rows && mi_col_2 * 2 < num_unit_cols) { |
| 3961 | + const int mi_idx_2 = mi_stride * mi_row_2 + mi_col_2; |
| 3962 | + is_valid_second_rectangle = 1; |
| 3963 | + mi = mi_grid_visible + mi_idx_2; |
| 3964 | + source_ref_frame[0] = mi[0]->ref_frame[0]; |
| 3965 | + source_ref_frame[1] = mi[0]->ref_frame[1]; |
| 3966 | + source_mv[0] = &mi[0]->mv[0].as_mv; |
| 3967 | + source_mv[1] = &mi[0]->mv[1].as_mv; |
| 3968 | + } |
| 3969 | + } |
| 3970 | + if (is_valid_second_rectangle) { |
| 3971 | + assign_motion_vector_info( |
| 3972 | + block_width_4x4, block_height_4x4, row_start_4x4, |
| 3973 | + col_start_4x4 + block_width_4x4, num_unit_rows, num_unit_cols, |
| 3974 | + source_mv, source_ref_frame, motion_vector_info); |
| 3975 | + } |
| 3976 | + } else { |
| 3977 | + assert(pc_tree->partitioning == PARTITION_NONE || square_size_4x4 == 1); |
| 3978 | + source_ref_frame[0] = mi[0]->ref_frame[0]; |
| 3979 | + source_ref_frame[1] = mi[0]->ref_frame[1]; |
| 3980 | + if (square_size_4x4 == 1) { |
| 3981 | + const int sub8x8_row = row_start_4x4 % 2; |
| 3982 | + const int sub8x8_col = col_start_4x4 % 2; |
| 3983 | + const int sub8x8_idx = sub8x8_row * 2 + sub8x8_col; |
| 3984 | + source_mv[0] = &mi[0]->bmi[sub8x8_idx].as_mv[0].as_mv; |
| 3985 | + source_mv[1] = &mi[0]->bmi[sub8x8_idx].as_mv[1].as_mv; |
| 3986 | + } else { |
| 3987 | + source_mv[0] = &mi[0]->mv[0].as_mv; |
| 3988 | + source_mv[1] = &mi[0]->mv[1].as_mv; |
| 3989 | + } |
| 3990 | + assign_motion_vector_info(block_width_4x4, block_height_4x4, |
| 3991 | + row_start_4x4, col_start_4x4, num_unit_rows, |
| 3992 | + num_unit_cols, source_mv, source_ref_frame, |
| 3993 | + motion_vector_info); |
| 3994 | + } |
| 3995 | + |
| 3864 | 3996 | return; |
| 3865 | 3997 | } |
| 3866 | 3998 | // recursively traverse partition tree when partition is split. |
| 3867 | 3999 | assert(pc_tree->partitioning == PARTITION_SPLIT); |
| 3868 | | − store_superblock_partition_info(pc_tree->split[0], partition_info, |
| 3869 | | − subblock_square_size_4x4, num_unit_rows, |
| 3870 | | − num_unit_cols, row_start_4x4, col_start_4x4); |
| 3871 | | − store_superblock_partition_info(pc_tree->split[1], partition_info, |
| 3872 | | − subblock_square_size_4x4, num_unit_rows, |
| 3873 | | − num_unit_cols, row_start_4x4, |
| 3874 | | − col_start_4x4 + subblock_square_size_4x4); |
| 3875 | | − store_superblock_partition_info( |
| 3876 | | − pc_tree->split[2], partition_info, subblock_square_size_4x4, |
| 3877 | | − num_unit_rows, num_unit_cols, row_start_4x4 + subblock_square_size_4x4, |
| 3878 | | − col_start_4x4); |
| 3879 | | − store_superblock_partition_info( |
| 3880 | | − pc_tree->split[3], partition_info, subblock_square_size_4x4, |
| 3881 | | − num_unit_rows, num_unit_cols, row_start_4x4 + subblock_square_size_4x4, |
| 3882 | | − col_start_4x4 + subblock_square_size_4x4); |
| 4000 | + store_superblock_info(pc_tree->split[0], mi_grid_visible, mi_stride, |
| 4001 | + subblock_square_size_4x4, num_unit_rows, num_unit_cols, |
| 4002 | + row_start_4x4, col_start_4x4, partition_info, |
| 4003 | + motion_vector_info); |
| 4004 | + store_superblock_info(pc_tree->split[1], mi_grid_visible, mi_stride, |
| 4005 | + subblock_square_size_4x4, num_unit_rows, num_unit_cols, |
| 4006 | + row_start_4x4, col_start_4x4 + subblock_square_size_4x4, |
| 4007 | + partition_info, motion_vector_info); |
| 4008 | + store_superblock_info(pc_tree->split[2], mi_grid_visible, mi_stride, |
| 4009 | + subblock_square_size_4x4, num_unit_rows, num_unit_cols, |
| 4010 | + row_start_4x4 + subblock_square_size_4x4, col_start_4x4, |
| 4011 | + partition_info, motion_vector_info); |
| 4012 | + store_superblock_info(pc_tree->split[3], mi_grid_visible, mi_stride, |
| 4013 | + subblock_square_size_4x4, num_unit_rows, num_unit_cols, |
| 4014 | + row_start_4x4 + subblock_square_size_4x4, |
| 4015 | + col_start_4x4 + subblock_square_size_4x4, |
| 4016 | + partition_info, motion_vector_info); |
| 3883 | 4017 | } |
| 3884 | 4018 | #endif // CONFIG_RATE_CTRL |
| 3885 | 4019 | |
| @@ -4458,13 +4592,15 @@ static int rd_pick_partition(VP9_COMP *cpi, ThreadData *td, · 572 unmodified lines |
| 4458 | 4592 | encode_sb(cpi, td, tile_info, tp, mi_row, mi_col, output_enabled, bsize, |
| 4459 | 4593 | pc_tree); |
| 4460 | 4594 | #if CONFIG_RATE_CTRL |
| 4461 | | − // Store partition info. |
| 4595 | + // Store partition, motion vector of the superblock. |
| 4462 | 4596 | if (output_enabled) { |
| 4463 | 4597 | const int num_unit_rows = get_num_unit_4x4(cpi->frame_info.frame_height); |
| 4464 | 4598 | const int num_unit_cols = get_num_unit_4x4(cpi->frame_info.frame_width); |
| 4465 | | − store_superblock_partition_info( |
| 4466 | | − pc_tree, cpi->partition_info, num_4x4_blocks_wide_lookup[BLOCK_64X64], |
| 4467 | | − num_unit_rows, num_unit_cols, mi_row << 1, mi_col << 1); |
| 4599 | + store_superblock_info(pc_tree, cm->mi_grid_visible, cm->mi_stride, |
| 4600 | + num_4x4_blocks_wide_lookup[BLOCK_64X64], |
| 4601 | + num_unit_rows, num_unit_cols, mi_row << 1, |
| 4602 | + mi_col << 1, cpi->partition_info, |
| 4603 | + cpi->motion_vector_info); |
| 4468 | 4604 | } |
| 4469 | 4605 | #endif // CONFIG_RATE_CTRL |
| 4470 | 4606 | } |