Cross chroma transform-add contexts and optimize CDFs Introduce top and left cctx_type as contexts, optimization of CDFs, and misc cleanups.
diff --git a/av1/common/av1_common_int.h b/av1/common/av1_common_int.h index 06123ba..cfded4d 100644 --- a/av1/common/av1_common_int.h +++ b/av1/common/av1_common_int.h
@@ -2230,10 +2230,12 @@ // 'xd->tx_type_map' should point to an offset in 'mi_params->tx_type_map'. if (xd->tree_type != CHROMA_PART) { xd->tx_type_map = mi_params->tx_type_map + mi_grid_idx; -#if CONFIG_CROSS_CHROMA_TX - xd->cctx_type_map = mi_params->cctx_type_map + mi_grid_idx; -#endif // CONFIG_CROSS_CHROMA_TX } +#if CONFIG_CROSS_CHROMA_TX + if (xd->tree_type != LUMA_PART) { + xd->cctx_type_map = mi_params->cctx_type_map + mi_grid_idx; + } +#endif // CONFIG_CROSS_CHROMA_TX xd->tx_type_map_stride = mi_params->mi_stride; }
diff --git a/av1/common/av1_txfm.c b/av1/common/av1_txfm.c index 267c59e..6c2e2c9 100644 --- a/av1/common/av1_txfm.c +++ b/av1/common/av1_txfm.c
@@ -202,54 +202,34 @@ // stores two values: cos(t) and sin(t) for each rotation angle. const int32_t cctx_mtx[CCTX_TYPES - 1][2] = { #if CCTX_ANGLE_CONFIG == 0 -#if CCTX_POS_ANGLES - { 181, 181 }, // t = 45 degrees - { 222, 128 }, // t = 30 degrees - { 128, 222 }, // t = 60 degrees -#endif // CCTX_POS_ANGLES -#if CCTX_NEG_ANGLES + { 181, 181 }, // t = 45 degrees + { 222, 128 }, // t = 30 degrees + { 128, 222 }, // t = 60 degrees { 181, -181 }, // t = -45 degrees { 222, -128 }, // t = -30 degrees { 128, -222 }, // t = -60 degrees -#endif // CCTX_NEG_ANGLES #elif CCTX_ANGLE_CONFIG == 1 -#if CCTX_POS_ANGLES { 181, 181 }, // t = 45 degrees { 236, 98 }, // t = 22.5 degrees { 98, 236 }, // t = 67.5 degrees -#endif // CCTX_POS_ANGLES -#if CCTX_NEG_ANGLES { 181, -181 }, // t = -45 degrees { 236, -98 }, // t = -22.5 degrees { 98, -236 }, // t = -67.5 degrees -#endif // CCTX_NEG_ANGLES #elif CCTX_ANGLE_CONFIG == 2 -#if CCTX_POS_ANGLES { 181, 181 }, // t = 45 degrees { 232, 108 }, // t = 25 degrees { 108, 232 }, // t = 65 degrees -#endif // CCTX_POS_ANGLES -#if CCTX_NEG_ANGLES { 181, -181 }, // t = -45 degrees { 232, -108 }, // t = -25 degrees { 108, -232 }, // t = -65 degrees -#endif // CCTX_NEG_ANGLES #elif CCTX_ANGLE_CONFIG == 3 -#if CCTX_POS_ANGLES { 222, 128 }, // t = 30 degrees { 128, 222 }, // t = 60 degrees -#endif // CCTX_POS_ANGLES -#if CCTX_NEG_ANGLES { 222, -128 }, // t = -30 degrees { 128, -222 }, // t = -60 degrees -#endif // CCTX_NEG_ANGLES #elif CCTX_ANGLE_CONFIG == 4 -#if CCTX_POS_ANGLES { 181, 181 }, // t = 45 degrees -#endif // CCTX_POS_ANGLES -#if CCTX_NEG_ANGLES { 181, -181 }, // t = -45 degrees -#endif // CCTX_NEG_ANGLES #endif }; #endif // CONFIG_CROSS_CHROMA_TX
diff --git a/av1/common/blockd.h b/av1/common/blockd.h index aee81be..9f22162 100644 --- a/av1/common/blockd.h +++ b/av1/common/blockd.h
@@ -1564,38 +1564,56 @@ #if CONFIG_CROSS_CHROMA_TX #if CCTX_C2_DROPPED static INLINE int keep_chroma_c2(CctxType cctx_type) { - return -#if CCTX_NEG_ANGLES - cctx_type == CCTX_M30 || cctx_type == CCTX_M60 || -#endif -#if CCTX_POS_ANGLES - cctx_type == CCTX_30 || cctx_type == CCTX_60 || -#endif - cctx_type == CCTX_NONE; + return cctx_type == CCTX_M30 || cctx_type == CCTX_M60 || + cctx_type == CCTX_30 || cctx_type == CCTX_60 || cctx_type == CCTX_NONE; } #endif +// When the current block is sub 8x8, obtain amounts of offset to its parent +// 8x8 block. Otherwise set the offsets to 0. +static INLINE void get_offsets_to_8x8(MACROBLOCKD *const xd, TX_SIZE tx_size, + int *row_offset, int *col_offset) { + const struct macroblockd_plane *const pd = &xd->plane[AOM_PLANE_U]; + const int ss_x = pd->subsampling_x; + const int ss_y = pd->subsampling_y; + *row_offset = + (xd->mi_row & 0x01) && (tx_size_high_unit[tx_size] & 0x01) && ss_y; + *col_offset = + (xd->mi_col & 0x01) && (tx_size_wide_unit[tx_size] & 0x01) && ss_x; +} + static INLINE void update_cctx_array(MACROBLOCKD *const xd, int blk_row, - int blk_col, TX_SIZE tx_size, + int blk_col, int blk_row_offset, + int blk_col_offset, TX_SIZE tx_size, CctxType cctx_type) { const int stride = xd->tx_type_map_stride; - xd->cctx_type_map[blk_row * stride + blk_col] = cctx_type; + const struct macroblockd_plane *const pd = &xd->plane[AOM_PLANE_U]; + const int ss_x = pd->subsampling_x; + const int ss_y = pd->subsampling_y; + assert(xd->is_chroma_ref); - const int txw = tx_size_wide_unit[tx_size]; - const int txh = tx_size_high_unit[tx_size]; - // The 16x16 unit is due to the constraint from tx_64x64 which sets the - // maximum tx size for chroma as 32x32. Coupled with 4x1 transform block - // size, the constraint takes effect in 32x16 / 16x32 size too. To solve - // the intricacy, cover all the 16x16 units inside a 64 level transform. - if (txw == tx_size_wide_unit[TX_64X64] || - txh == tx_size_high_unit[TX_64X64]) { - const int tx_unit = tx_size_wide_unit[TX_16X16]; - for (int idy = 0; idy < txh; idy += tx_unit) { - for (int idx = 0; idx < txw; idx += tx_unit) { - xd->cctx_type_map[(blk_row + idy) * stride + blk_col + idx] = cctx_type; - } - } - } + // For sub 8x8 block, offsets will be applied to reach the mi_row and mi_col + // of the >= 8x8 block area. Transform block size is upscaled to match the + // luma block size. + const int br = (blk_row << ss_y) - blk_row_offset; + const int bc = (blk_col << ss_x) - blk_col_offset; + const int txw = tx_size_wide_unit[tx_size] << ss_x; + const int txh = tx_size_high_unit[tx_size] << ss_y; + + // To make cctx_type available for its right and bottom neighbors, cover + // all elements in cctx_type_map within the transform block range with the + // current cctx type + for (int idy = 0; idy < txh; idy++) + memset(&xd->cctx_type_map[(br + idy) * stride + bc], cctx_type, + txw * sizeof(xd->cctx_type_map[0])); +} + +static INLINE CctxType av1_get_cctx_type(const MACROBLOCKD *xd, int blk_row, + int blk_col) { + const struct macroblockd_plane *const pd = &xd->plane[AOM_PLANE_U]; + const int br = blk_row << pd->subsampling_y; + const int bc = blk_col << pd->subsampling_x; + return xd->cctx_type_map[br * xd->tx_type_map_stride + bc]; } #endif // CONFIG_CROSS_CHROMA_TX @@ -1777,13 +1795,6 @@ return tx_type; } -#if CONFIG_CROSS_CHROMA_TX -static INLINE CctxType av1_get_cctx_type(const MACROBLOCKD *xd, int blk_row, - int blk_col) { - return xd->cctx_type_map[blk_row * xd->tx_type_map_stride + blk_col]; -} -#endif // CONFIG_CROSS_CHROMA_TX - void av1_setup_block_planes(MACROBLOCKD *xd, int ss_x, int ss_y, const int num_planes);
diff --git a/av1/common/entropy.c b/av1/common/entropy.c index 86b6465..b6933d5 100644 --- a/av1/common/entropy.c +++ b/av1/common/entropy.c
@@ -296,6 +296,6 @@ RESET_CDF_COUNTER_STRIDE(fc->stx_cdf, STX_TYPES, CDF_SIZE(STX_TYPES)); #endif #if CONFIG_CROSS_CHROMA_TX - RESET_CDF_COUNTER(fc->cctx_type_cdf, CCTX_TYPES); + RESET_CDF_COUNTER(fc->cctx_type_cdf, CCTX_TYPES_ALLOWED); #endif // CONFIG_CROSS_CHROMA_TX }
diff --git a/av1/common/entropymode.c b/av1/common/entropymode.c index e48fea4..f00070d 100644 --- a/av1/common/entropymode.c +++ b/av1/common/entropymode.c
@@ -684,62 +684,77 @@ #endif // CONFIG_DDT_INTER #if CONFIG_CROSS_CHROMA_TX -static const aom_cdf_prob default_cctx_type_cdf[EXT_TX_SIZES] - [CDF_SIZE(CCTX_TYPES)] = { +static const aom_cdf_prob + default_cctx_type_cdf[EXT_TX_SIZES][CCTX_CONTEXTS] + [CDF_SIZE(CCTX_TYPES_ALLOWED)] = { #if CCTX_ANGLE_CONFIG == 4 -#if CCTX_POS_ANGLES && CCTX_NEG_ANGLES - { AOM_CDF3(10923, 21845) }, - { AOM_CDF3(10923, 21845) }, - { AOM_CDF3(10923, 21845) }, - { AOM_CDF3(10923, 21845) }, -#else - { AOM_CDF2(16384) }, - { AOM_CDF2(16384) }, - { AOM_CDF2(16384) }, - { AOM_CDF2(16384) }, -#endif // CCTX_POS_ANGLES && CCTX_NEG_ANGLES + { { AOM_CDF3(10923, 21845) }, + { AOM_CDF3(10923, 21845) }, + { AOM_CDF3(10923, 21845) } }, + { { AOM_CDF3(10923, 21845) }, + { AOM_CDF3(10923, 21845) }, + { AOM_CDF3(10923, 21845) } }, + { { AOM_CDF3(10923, 21845) }, + { AOM_CDF3(10923, 21845) }, + { AOM_CDF3(10923, 21845) } }, + { { AOM_CDF3(10923, 21845) }, + { AOM_CDF3(10923, 21845) }, + { AOM_CDF3(10923, 21845) } }, #elif CCTX_ANGLE_CONFIG == 3 -#if CCTX_POS_ANGLES && CCTX_NEG_ANGLES - { AOM_CDF5(6554, 13107, 19661, - 26214) }, - { AOM_CDF5(6554, 13107, 19661, - 26214) }, - { AOM_CDF5(6554, 13107, 19661, - 26214) }, - { AOM_CDF5(6554, 13107, 19661, - 26214) }, + { { AOM_CDF5(6554, 13107, 19661, 26214) }, + { AOM_CDF5(6554, 13107, 19661, 26214) }, + { AOM_CDF5(6554, 13107, 19661, 26214) } }, + { { AOM_CDF5(6554, 13107, 19661, 26214) }, + { AOM_CDF5(6554, 13107, 19661, 26214) }, + { AOM_CDF5(6554, 13107, 19661, 26214) } }, + { { AOM_CDF5(6554, 13107, 19661, 26214) }, + { AOM_CDF5(6554, 13107, 19661, 26214) }, + { AOM_CDF5(6554, 13107, 19661, 26214) } }, + { { AOM_CDF5(6554, 13107, 19661, 26214) }, + { AOM_CDF5(6554, 13107, 19661, 26214) }, + { AOM_CDF5(6554, 13107, 19661, 26214) } }, #else - { AOM_CDF3(10923, 21845) }, - { AOM_CDF3(10923, 21845) }, - { AOM_CDF3(10923, 21845) }, - { AOM_CDF3(10923, 21845) }, -#endif // CCTX_POS_ANGLES && CCTX_NEG_ANGLES +#if CCTX_ADAPT_REDUCED_SET + { { AOM_CDF3(21092, 22824) }, + { AOM_CDF3(23150, 29387) }, + { AOM_CDF3(12029, 25649) } }, + { { AOM_CDF3(17069, 19010) }, + { AOM_CDF3(22591, 27810) }, + { AOM_CDF3(10803, 24548) } }, + { { AOM_CDF3(16209, 18900) }, + { AOM_CDF3(21703, 27555) }, + { AOM_CDF3(8605, 23810) } }, + { { AOM_CDF3(15354, 17963) }, + { AOM_CDF3(22686, 27727) }, + { AOM_CDF3(9173, 22932) } } #else -#if CCTX_POS_ANGLES && CCTX_NEG_ANGLES - { AOM_CDF7(4681, 9362, 14043, - 18725, 23406, - 28087) }, - { AOM_CDF7(4681, 9362, 14043, - 18725, 23406, - 28087) }, - { AOM_CDF7(4681, 9362, 14043, - 18725, 23406, - 28087) }, - { AOM_CDF7(4681, 9362, 14043, - 18725, 23406, - 28087) }, -#else - { AOM_CDF4(8192, 16384, - 24576) }, - { AOM_CDF4(8192, 16384, - 24576) }, - { AOM_CDF4(8192, 16384, - 24576) }, - { AOM_CDF4(8192, 16384, - 24576) }, -#endif // CCTX_POS_ANGLES && CCTX_NEG_ANGLES + { { AOM_CDF7(19143, 19642, 20876, 21362, 23684, + 30645) }, + { AOM_CDF7(15852, 17519, 22430, 24276, 26473, + 30362) }, + { AOM_CDF7(9981, 10351, 11021, 11340, 16893, + 28901) } }, + { { AOM_CDF7(13312, 14068, 15345, 16249, 20082, + 29648) }, + { AOM_CDF7(11802, 14635, 17918, 20493, 23927, + 29206) }, + { AOM_CDF7(8348, 8915, 9727, 10347, 16584, + 27923) } }, + { { AOM_CDF7(10604, 11887, 13486, 14485, 19798, + 28529) }, + { AOM_CDF7(10790, 13346, 16867, 18854, 23398, + 29133) }, + { AOM_CDF7(6538, 7104, 7997, 8723, 15658, + 26864) } }, + { { AOM_CDF7(13226, 13959, 14918, 15707, 21009, + 29328) }, + { AOM_CDF7(10336, 13195, 15614, 17813, 21992, + 29469) }, + { AOM_CDF7(7769, 8772, 9617, 10150, 16729, + 28132) } } #endif - }; +#endif + }; #endif // CONFIG_CROSS_CHROMA_TX static const aom_cdf_prob default_cfl_sign_cdf[CDF_SIZE(CFL_JOINT_SIGNS)] = {
diff --git a/av1/common/entropymode.h b/av1/common/entropymode.h index c2267a0..af9a7f2 100644 --- a/av1/common/entropymode.h +++ b/av1/common/entropymode.h
@@ -273,7 +273,8 @@ aom_cdf_prob stx_cdf[TX_SIZES][CDF_SIZE(STX_TYPES)]; #endif #if CONFIG_CROSS_CHROMA_TX - aom_cdf_prob cctx_type_cdf[EXT_TX_SIZES][CDF_SIZE(CCTX_TYPES)]; + aom_cdf_prob cctx_type_cdf[EXT_TX_SIZES][CCTX_CONTEXTS] + [CDF_SIZE(CCTX_TYPES_ALLOWED)]; #endif // CONFIG_CROSS_CHROMA_TX int initialized; } FRAME_CONTEXT;
diff --git a/av1/common/enums.h b/av1/common/enums.h index 9f33c0c..aef609b 100644 --- a/av1/common/enums.h +++ b/av1/common/enums.h
@@ -404,14 +404,9 @@ } UENUM1BYTE(TX_TYPE); #if CONFIG_CROSS_CHROMA_TX -#define CCTX_NEG_ANGLES 1 -#define CCTX_POS_ANGLES 1 -// Always signal C1 coefficients for some cctx (i.e., both C1 and C2 nonzero -// or C1 nonzero and C2 zero). This requires CCTX_NEG_ANGLES to be on. -#define CCTX_C1_NONZERO 1 -// Drop C2 channel for some cctx_types. This macro requires CCTX_C1_NONZERO to -// be on. +#define CCTX_CONTEXTS 3 #define CCTX_C2_DROPPED 0 +#define CCTX_ADAPT_REDUCED_SET 0 // Configuration for the set of rotation angles // 0: { 45, 30, 60 } // 1: { 45, 22.5, 67.5 } @@ -421,7 +416,6 @@ #define CCTX_ANGLE_CONFIG 0 enum { CCTX_NONE, // No cross chroma transform -#if CCTX_POS_ANGLES #if CCTX_ANGLE_CONFIG != 3 CCTX_45, // 45 degrees rotation (Haar transform) #endif @@ -429,8 +423,6 @@ CCTX_30, // 30 degrees rotation CCTX_60, // 60 degrees rotation #endif -#endif // CCTX_POS_ANGLES -#if CCTX_NEG_ANGLES #if CCTX_ANGLE_CONFIG != 3 CCTX_M45, // -45 degrees rotation #endif @@ -438,10 +430,16 @@ CCTX_M30, // -30 degrees rotation CCTX_M60, // -60 degrees rotation #endif -#endif // CCTX_NEG_ANGLES CCTX_TYPES, CCTX_START = CCTX_NONE + 1, } UENUM1BYTE(CctxType); + +#if CCTX_ADAPT_REDUCED_SET +#define CCTX_TYPES_ALLOWED 3 +#else +#define CCTX_TYPES_ALLOWED CCTX_TYPES +#endif + #endif // CONFIG_CROSS_CHROMA_TX enum {
diff --git a/av1/common/pred_common.h b/av1/common/pred_common.h index 3491536..b614df3 100644 --- a/av1/common/pred_common.h +++ b/av1/common/pred_common.h
@@ -357,6 +357,145 @@ #endif // CONFIG_SKIP_MODE_ENHANCEMENT } +#if CONFIG_CROSS_CHROMA_TX +#if CCTX_ADAPT_REDUCED_SET +// The closest nonzero neighboring cctx type of the current cctx type +static const CctxType closest_nonzero_cctx[CCTX_TYPES] = { +#if 1 + CCTX_30, CCTX_30, CCTX_45, CCTX_30, CCTX_M30, CCTX_M45, CCTX_M30 +#else + CCTX_30, CCTX_30, CCTX_45, CCTX_45, CCTX_M30, CCTX_M45, CCTX_M45 +#endif +}; + +// Return the set of 3 allowed cctx types given the above and left cctx types. +// Since CCTX_NONE will always be allowed, so we add the above and left +// to the allowed list only when they are valid (not -1) and not CCTX_NONE. +// Then we add their closest cctx types if there is any available slot. +static INLINE uint8_t get_allowed_cctx_mask(int above, int left) { + if (above <= CCTX_NONE && left <= CCTX_NONE) + return (1 << CCTX_NONE) + (1 << CCTX_30) + (1 << CCTX_M30); + else if (above <= CCTX_NONE) + return (1 << CCTX_NONE) + (1 << left) + (1 << closest_nonzero_cctx[left]); + else if (left <= CCTX_NONE || above == left) + return (1 << CCTX_NONE) + (1 << above) + (1 << closest_nonzero_cctx[above]); + else + return (1 << CCTX_NONE) + (1 << above) + (1 << left); +} + +static INLINE void get_allowed_cctx_arr(const int above, const int left, + CctxType *cctxarr) { + cctxarr[0] = CCTX_NONE; + if (above <= CCTX_NONE && left <= CCTX_NONE) { + cctxarr[1] = CCTX_30; + cctxarr[2] = CCTX_M30; + } else if (above <= CCTX_NONE) { + cctxarr[1] = left; + cctxarr[2] = closest_nonzero_cctx[left]; + } else if (left <= CCTX_NONE || above == left) { + cctxarr[1] = above; + cctxarr[2] = closest_nonzero_cctx[above]; + } else { + cctxarr[1] = above; + cctxarr[2] = left; + } +} + +static INLINE CctxType cctx_idx_to_type(const int cctx_idx, const int above, + const int left) { + CctxType cctx_arr[CCTX_TYPES_ALLOWED] = { 0 }; + get_allowed_cctx_arr(above, left, cctx_arr); + return cctx_arr[cctx_idx]; +} + +static INLINE uint8_t cctx_type_to_idx(const CctxType ctype, const int above, + const int left) { + CctxType cctx_arr[CCTX_TYPES_ALLOWED] = { 0 }; + get_allowed_cctx_arr(above, left, cctx_arr); + if (ctype == cctx_arr[0]) return 0; + if (ctype == cctx_arr[1]) return 1; + if (ctype == cctx_arr[2]) return 2; + assert(0); + return 0; +} +#endif +// TODO(kslu) remove it +// static INLINE void get_above_and_left_cctx_type(const MACROBLOCKD *xd, +// int blk_row, int blk_col, +// TX_SIZE tx_size, +// int *above_cctx, +// int *left_cctx) { +// const int ss_x = xd->plane[AOM_PLANE_U].subsampling_x; +// const int ss_y = xd->plane[AOM_PLANE_U].subsampling_y; +// const int txh = tx_size_high_unit[tx_size]; +// const int txw = tx_size_wide_unit[tx_size]; +// +// // Offsets are needed for sub 8x8 blocks to reach the top left corner of the +// // current block where the current cctx_type is applied +// const int mi_row_offset = (xd->mi_row & 0x01) && (txh & 0x01) && ss_y; +// const int mi_col_offset = (xd->mi_col & 0x01) && (txw & 0x01) && ss_x; +// const int stride = xd->tx_type_map_stride; +// CctxType *cur_cctx_ptr = +// &xd->cctx_type_map[((blk_row << ss_y) - mi_row_offset) * stride + +// (blk_col << ss_x) - mi_col_offset]; +// +// *above_cctx = xd->chroma_up_available ? (int)cur_cctx_ptr[-stride] : -1; +// *left_cctx = xd->chroma_left_available ? (int)cur_cctx_ptr[-1] : -1; +// assert(*above_cctx >= -1 && *above_cctx < CCTX_TYPES); +// assert(*left_cctx >= -1 && *left_cctx < CCTX_TYPES); +//} + +static INLINE void get_above_and_left_cctx_type( + const AV1_COMMON *cm, const MACROBLOCKD *xd, int blk_row, int blk_col, + TX_SIZE tx_size, int *above_cctx, int *left_cctx) { + const int ss_x = xd->plane[AOM_PLANE_U].subsampling_x; + const int ss_y = xd->plane[AOM_PLANE_U].subsampling_y; + const int txh = tx_size_high_unit[tx_size]; + const int txw = tx_size_wide_unit[tx_size]; + + const CommonModeInfoParams *const mi_params = &cm->mi_params; + const int stride = mi_params->mi_stride; + + // Offsets are needed for sub 8x8 blocks to reach the top left corner of the + // current block where the current cctx_type is applied + const int mi_row_offset = (xd->mi_row & 0x01) && (txh & 0x01) && ss_y; + const int mi_col_offset = (xd->mi_col & 0x01) && (txw & 0x01) && ss_x; + const int mi_grid_idx = get_mi_grid_idx(mi_params, xd->mi_row - mi_row_offset, + xd->mi_col - mi_col_offset); + CctxType *const cur_cctx_ptr = mi_params->cctx_type_map + mi_grid_idx; + + // TODO(kslu) change this workaround for shifts + const int cctx_stride = xd->tx_type_map_stride; + const int br = (txw == (cctx_stride >> ss_x)) ? blk_row : (blk_row << ss_y); + const int bc = (txw == (cctx_stride >> ss_x)) ? blk_col : (blk_col << ss_x); + if (blk_row) + *above_cctx = (int)xd->cctx_type_map[(br - 1) * cctx_stride + bc]; + else + *above_cctx = xd->chroma_up_available ? (int)cur_cctx_ptr[-stride] : -1; + + if (blk_col) + *left_cctx = (int)xd->cctx_type_map[br * stride + bc - 1]; + else + *left_cctx = xd->chroma_left_available ? (int)cur_cctx_ptr[-1] : -1; + + assert(*above_cctx >= -1 && *above_cctx < CCTX_TYPES); + assert(*left_cctx >= -1 && *left_cctx < CCTX_TYPES); +} + +// 0: CCTX_NONE, unequal top and left context, or unavailable context +// 1: positive angle cctx +// 2: negative angle cctx +static INLINE int get_cctx_context(const MACROBLOCKD *xd, const int above, + const int left) { + int above_ctx = + xd->chroma_up_available ? ((above > CCTX_60) + (above > CCTX_NONE)) : 0; + int left_ctx = + xd->chroma_left_available ? ((left > CCTX_60) + (left > CCTX_NONE)) : 0; + if (above_ctx == 0 || left_ctx == 0) return AOMMAX(above_ctx, left_ctx); + return (above_ctx == left_ctx) ? above_ctx : 0; +} +#endif // CONFIG_CROSS_CHROMA_TX + int av1_get_pred_context_switchable_interp(const MACROBLOCKD *xd, int dir); // Get a list of palette base colors that are used in the above and left blocks,
diff --git a/av1/decoder/decodeframe.c b/av1/decoder/decodeframe.c index ba3490a..a1190be 100644 --- a/av1/decoder/decodeframe.c +++ b/av1/decoder/decodeframe.c
@@ -251,14 +251,8 @@ #if CONFIG_CROSS_CHROMA_TX && CCTX_INTRA eob_info *eob_data_u = dcb->eob_data[AOM_PLANE_U] + dcb->txb_offset[AOM_PLANE_U]; -#if CCTX_C1_NONZERO - if (eob_data->eob || (av1_get_cctx_type(xd, row, col) > CCTX_NONE && - plane == AOM_PLANE_V && eob_data_u->eob)) { -#else - eob_info *eob_data_v = - dcb->eob_data[AOM_PLANE_V] + dcb->txb_offset[AOM_PLANE_V]; - if (eob_data->eob || (plane && (eob_data_u->eob || eob_data_v->eob))) { -#endif + if (eob_data->eob || (plane == AOM_PLANE_V && eob_data_u->eob && + av1_get_cctx_type(xd, row, col) > CCTX_NONE)) { #else if (eob_data->eob) { #endif // CONFIG_CROSS_CHROMA_TX @@ -1319,6 +1313,15 @@ blk_row, blk_col, block, max_tx_size, &eobtotal); block += stepr * stepc; +#if CONFIG_CROSS_CHROMA_TX + } else if (plane == AOM_PLANE_U) { + // fill cctx_type_map with CCTX_NONE for skip blocks so their + // neighbors can derive cctx contexts + int row_offset, col_offset; + get_offsets_to_8x8(xd, max_tx_size, &row_offset, &col_offset); + update_cctx_array(xd, blk_row, blk_col, row_offset, col_offset, + max_tx_size, CCTX_NONE); +#endif } } }
diff --git a/av1/decoder/decodemv.c b/av1/decoder/decodemv.c index 5181fcd..d6b9e07 100644 --- a/av1/decoder/decodemv.c +++ b/av1/decoder/decodemv.c
@@ -874,9 +874,13 @@ int blk_row, int blk_col, TX_SIZE tx_size, aom_reader *r) { MB_MODE_INFO *mbmi = xd->mi[0]; - CctxType *cctx_type = - &xd->cctx_type_map[blk_row * xd->tx_type_map_stride + blk_col]; - *cctx_type = CCTX_NONE; + // If it is a sub 8x8 chroma block, derive the mi_row and mi_col of the + // parent block area. Then apply cctx type update to this area w.r.t the + // offsets derived + int row_offset, col_offset; + get_offsets_to_8x8(xd, tx_size, &row_offset, &col_offset); + update_cctx_array(xd, blk_row, blk_col, row_offset, col_offset, tx_size, + CCTX_NONE); // No need to read transform type if block is skipped. if (mbmi->skip_txfm[xd->tree_type == CHROMA_PART] || @@ -888,11 +892,26 @@ if (qindex == 0) return; const int is_inter = is_inter_block(mbmi, xd->tree_type); + CctxType cctx_type = CCTX_NONE; if ((is_inter && CCTX_INTER) || (!is_inter && CCTX_INTRA)) { FRAME_CONTEXT *ec_ctx = xd->tile_ctx; const TX_SIZE square_tx_size = txsize_sqr_map[tx_size]; - *cctx_type = aom_read_symbol(r, ec_ctx->cctx_type_cdf[square_tx_size], - CCTX_TYPES, ACCT_STR); + int above_cctx, left_cctx; + get_above_and_left_cctx_type(cm, xd, blk_row, blk_col, tx_size, &above_cctx, + &left_cctx); + const int cctx_ctx = get_cctx_context(xd, above_cctx, left_cctx); +#if CCTX_ADAPT_REDUCED_SET + const int cctx_idx = + aom_read_symbol(r, ec_ctx->cctx_type_cdf[square_tx_size][cctx_ctx], + CCTX_TYPES_ALLOWED, ACCT_STR); + cctx_type = cctx_idx_to_type(cctx_idx, above_cctx, left_cctx); +#else + cctx_type = + aom_read_symbol(r, ec_ctx->cctx_type_cdf[square_tx_size][cctx_ctx], + CCTX_TYPES_ALLOWED, ACCT_STR); +#endif + update_cctx_array(xd, blk_row, blk_col, row_offset, col_offset, tx_size, + cctx_type); } } #endif // CONFIG_CROSS_CHROMA_TX
diff --git a/av1/decoder/decoder.c b/av1/decoder/decoder.c index 0558a17..a77ba3e 100644 --- a/av1/decoder/decoder.c +++ b/av1/decoder/decoder.c
@@ -103,6 +103,10 @@ mi_params->mi_stride * calc_mi_size(mi_params->mi_rows); memset(mi_params->mi_grid_base, 0, mi_grid_size * sizeof(*mi_params->mi_grid_base)); +#if CONFIG_CROSS_CHROMA_TX + memset(mi_params->cctx_type_map, 0, + mi_grid_size * sizeof(*mi_params->cctx_type_map)); +#endif // CONFIG_CROSS_CHROMA_TX } static void dec_free_mi(CommonModeInfoParams *mi_params) {
diff --git a/av1/decoder/decodetxb.c b/av1/decoder/decodetxb.c index 779408f..cc178c7 100644 --- a/av1/decoder/decodetxb.c +++ b/av1/decoder/decodetxb.c
@@ -14,6 +14,7 @@ #include "aom_ports/mem.h" #include "av1/common/idct.h" +#include "av1/common/pred_common.h" #include "av1/common/scan.h" #include "av1/common/txb_common.h" #if CONFIG_FORWARDSKIP @@ -192,23 +193,16 @@ #endif // CONFIG_CONTEXT_DERIVATION #if CONFIG_CROSS_CHROMA_TX -#if CCTX_C1_NONZERO if (plane == AOM_PLANE_U) { - if (!all_zero) + if (!all_zero) { av1_read_cctx_type(cm, xd, blk_row, blk_col, tx_size, r); - else - xd->cctx_type_map[blk_row * xd->tx_type_map_stride + blk_col] = CCTX_NONE; + } else { + int row_offset, col_offset; + get_offsets_to_8x8(xd, tx_size, &row_offset, &col_offset); + update_cctx_array(xd, blk_row, blk_col, row_offset, col_offset, tx_size, + CCTX_NONE); + } } -#else - if (plane == AOM_PLANE_V) { - // cctx_type will be read either eob_v > 0 or eob_u > 0 - eob_info *eob_data_u = - dcb->eob_data[AOM_PLANE_U] + dcb->txb_offset[AOM_PLANE_U]; - const uint16_t eob_u = eob_data_u->eob; - if (!all_zero || eob_u > 0) - av1_read_cctx_type(cm, xd, blk_row, blk_col, tx_size, r); - } -#endif // CCTX_C1_NONZERO #endif // CONFIG_CROSS_CHROMA_TX if (all_zero) { @@ -363,19 +357,16 @@ #endif // CONFIG_CONTEXT_DERIVATION #if CONFIG_CROSS_CHROMA_TX -#if CCTX_C1_NONZERO - if (plane == AOM_PLANE_U && !all_zero) { - av1_read_cctx_type(cm, xd, blk_row, blk_col, tx_size, r); - } -#else - if (plane == AOM_PLANE_V) { - eob_info *eob_data_u = - dcb->eob_data[AOM_PLANE_U] + dcb->txb_offset[AOM_PLANE_U]; - uint16_t eob_u = eob_data_u->eob; - if (!all_zero || eob_u > 0) + if (plane == AOM_PLANE_U) { + if (!all_zero) { av1_read_cctx_type(cm, xd, blk_row, blk_col, tx_size, r); + } else { + int row_offset, col_offset; + get_offsets_to_8x8(xd, tx_size, &row_offset, &col_offset); + update_cctx_array(xd, blk_row, blk_col, row_offset, col_offset, tx_size, + CCTX_NONE); + } } -#endif // CCTX_C1_NONZERO #endif // CONFIG_CROSS_CHROMA_TX #endif // CONFIG_FORWARDSKIP eob_info *eob_data = dcb->eob_data[plane] + dcb->txb_offset[plane]; @@ -722,9 +713,6 @@ for (int idy = 0; idy < txh; idy += tx_unit) { for (int idx = 0; idx < txw; idx += tx_unit) { xd->tx_type_map[(row + idy) * stride + col + idx] = tx_type; -#if CONFIG_CROSS_CHROMA_TX - xd->cctx_type_map[(row + idy) * stride + col + idx] = CCTX_NONE; -#endif // CONFIG_CROSS_CHROMA_TX } } }
diff --git a/av1/encoder/bitstream.c b/av1/encoder/bitstream.c index c062195..6653955 100644 --- a/av1/encoder/bitstream.c +++ b/av1/encoder/bitstream.c
@@ -1160,7 +1160,8 @@ #if CONFIG_CROSS_CHROMA_TX void av1_write_cctx_type(const AV1_COMMON *const cm, const MACROBLOCKD *xd, - CctxType cctx_type, TX_SIZE tx_size, aom_writer *w) { + int blk_row, int blk_col, CctxType cctx_type, + TX_SIZE tx_size, aom_writer *w) { MB_MODE_INFO *mbmi = xd->mi[0]; assert(xd->is_chroma_ref); const int is_inter = is_inter_block(mbmi, xd->tree_type); @@ -1171,8 +1172,19 @@ !segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP)) { FRAME_CONTEXT *ec_ctx = xd->tile_ctx; const TX_SIZE square_tx_size = txsize_sqr_map[tx_size]; - aom_write_symbol(w, cctx_type, ec_ctx->cctx_type_cdf[square_tx_size], - CCTX_TYPES); + int above_cctx, left_cctx; + get_above_and_left_cctx_type(cm, xd, blk_row, blk_col, tx_size, &above_cctx, + &left_cctx); + const int cctx_ctx = get_cctx_context(xd, above_cctx, left_cctx); +#if CCTX_ADAPT_REDUCED_SET + aom_write_symbol(w, cctx_type_to_idx(cctx_type, above_cctx, left_cctx), + ec_ctx->cctx_type_cdf[square_tx_size][cctx_ctx], + CCTX_TYPES_ALLOWED); +#else + aom_write_symbol(w, cctx_type, + ec_ctx->cctx_type_cdf[square_tx_size][cctx_ctx], + CCTX_TYPES_ALLOWED); +#endif } } #endif // CONFIG_CROSS_CHROMA_TX @@ -2186,6 +2198,23 @@ set_mi_row_col(xd, tile, mi_row, bh, mi_col, bw, mi_params->mi_rows, mi_params->mi_cols); +#if CONFIG_CROSS_CHROMA_TX + // For skip blocks, reset the corresponding area in cctx_type_map to + // CCTX_NONE, which will be used as contexts for later blocks. No need to use + // av1_get_adjusted_tx_size because uv_txsize is intended to cover the entire + // prediction block area + if (mbmi->skip_txfm[xd->tree_type == CHROMA_PART] && + xd->tree_type != LUMA_PART && xd->is_chroma_ref) { + struct macroblockd_plane *const pd = &xd->plane[AOM_PLANE_U]; + const BLOCK_SIZE uv_bsize = + get_plane_block_size(bsize, pd->subsampling_x, pd->subsampling_y); + const TX_SIZE uv_txsize = max_txsize_rect_lookup[uv_bsize]; + int row_offset, col_offset; + get_offsets_to_8x8(xd, uv_txsize, &row_offset, &col_offset); + update_cctx_array(xd, 0, 0, row_offset, col_offset, uv_txsize, CCTX_NONE); + } +#endif // CONFIG_CROSS_CHROMA_TX + xd->above_txfm_context = cm->above_contexts.txfm[tile->tile_row] + mi_col; xd->left_txfm_context = xd->left_txfm_context_buffer + (mi_row & MAX_MIB_MASK);
diff --git a/av1/encoder/bitstream.h b/av1/encoder/bitstream.h index 8a7cd65..e788253 100644 --- a/av1/encoder/bitstream.h +++ b/av1/encoder/bitstream.h
@@ -55,7 +55,8 @@ #if CONFIG_CROSS_CHROMA_TX void av1_write_cctx_type(const AV1_COMMON *const cm, const MACROBLOCKD *xd, - CctxType cctx_type, TX_SIZE tx_size, aom_writer *w); + int blk_row, int blk_col, CctxType cctx_type, + TX_SIZE tx_size, aom_writer *w); #endif // CONFIG_CROSS_CHROMA_TX #ifdef __cplusplus
diff --git a/av1/encoder/block.h b/av1/encoder/block.h index 01f70d5..3abd50e 100644 --- a/av1/encoder/block.h +++ b/av1/encoder/block.h
@@ -279,7 +279,7 @@ TX_TYPE tx_type_map[MAX_MIB_SIZE * MAX_MIB_SIZE]; #if CONFIG_CROSS_CHROMA_TX //! Map showing the cctx types for each block. - TX_TYPE cctx_type_map[MAX_MIB_SIZE * MAX_MIB_SIZE]; + CctxType cctx_type_map[MAX_MIB_SIZE * MAX_MIB_SIZE]; #endif // CONFIG_CROSS_CHROMA_TX //! Rd_stats for the whole partition block. RD_STATS rd_stats; @@ -855,7 +855,7 @@ #endif // CONFIG_DDT_INTER #if CONFIG_CROSS_CHROMA_TX //! cctx_type_cost - int cctx_type_cost[EXT_TX_SIZES][CCTX_TYPES]; + int cctx_type_cost[EXT_TX_SIZES][CCTX_CONTEXTS][CCTX_TYPES_ALLOWED]; #endif // CONFIG_CROSS_CHROMA_TX /**@}*/
diff --git a/av1/encoder/encodeframe_utils.c b/av1/encoder/encodeframe_utils.c index dcb753e..91a7073 100644 --- a/av1/encoder/encodeframe_utils.c +++ b/av1/encoder/encodeframe_utils.c
@@ -247,18 +247,32 @@ } #if CONFIG_CROSS_CHROMA_TX - if (xd->tree_type != LUMA_PART) { + if (xd->tree_type != LUMA_PART && xd->is_chroma_ref) { xd->cctx_type_map = ctx->cctx_type_map; xd->tx_type_map_stride = mi_size_wide[bsize]; + // If this block is sub 8x8 in luma, derive the parent >= 8x8 block area, + // then update its corresponding chroma area in cctx_type_map to the + // current cctx type + const int ss_x = pd[AOM_PLANE_U].subsampling_x; + const int ss_y = pd[AOM_PLANE_U].subsampling_y; + const int mi_row_offset = (mi_row & 0x01) && (bh & 0x01) && ss_y; + const int mi_col_offset = (mi_col & 0x01) && (bw & 0x01) && ss_x; + const int grid_idx = get_mi_grid_idx(mi_params, mi_row - mi_row_offset, + mi_col - mi_col_offset); + CctxType *const cctx_type_map = mi_params->cctx_type_map + grid_idx; + const int mi_stride = mi_params->mi_stride; + const int is_inter = is_inter_block(mi_addr, xd->tree_type); + const int allow_cctx = + (is_inter && CCTX_INTER) || (!is_inter && CCTX_INTRA); + // Set cctx_type to CCTX_NONE when not allowed or for skip blocks + CctxType cur_cctx_type = (txfm_info->skip_txfm || !allow_cctx) + ? CCTX_NONE + : xd->cctx_type_map[0]; + for (int blk_row = 0; blk_row < (mi_row_offset ? 2 : bh); ++blk_row) { + memset(&cctx_type_map[blk_row * mi_stride], cur_cctx_type, + (mi_col_offset ? 2 : bw) * sizeof(cctx_type_map[0])); + } if (!dry_run) { - const int grid_idx = get_mi_grid_idx(mi_params, mi_row, mi_col); - CctxType *const cctx_type_map = mi_params->cctx_type_map + grid_idx; - const int mi_stride = mi_params->mi_stride; - for (int blk_row = 0; blk_row < bh; ++blk_row) { - av1_copy_array(cctx_type_map + blk_row * mi_stride, - xd->cctx_type_map + blk_row * xd->tx_type_map_stride, - bw); - } xd->cctx_type_map = cctx_type_map; xd->tx_type_map_stride = mi_stride; } @@ -1359,8 +1373,8 @@ CDF_SIZE(STX_TYPES)); #endif #if CONFIG_CROSS_CHROMA_TX - AVG_CDF_STRIDE(ctx_left->cctx_type_cdf, ctx_tr->cctx_type_cdf, CCTX_TYPES, - CDF_SIZE(CCTX_TYPES)); + AVERAGE_CDF(ctx_left->cctx_type_cdf, ctx_tr->cctx_type_cdf, + CCTX_TYPES_ALLOWED); #endif // CONFIG_CROSS_CHROMA_TX }
diff --git a/av1/encoder/encodemb.c b/av1/encoder/encodemb.c index a2453b5..f3e4d49 100644 --- a/av1/encoder/encodemb.c +++ b/av1/encoder/encodemb.c
@@ -78,7 +78,7 @@ int av1_optimize_b(const struct AV1_COMP *cpi, MACROBLOCK *x, int plane, int block, TX_SIZE tx_size, TX_TYPE tx_type, #if CONFIG_CROSS_CHROMA_TX - CctxType cctx_type, + CctxType cctx_type, int blk_row, int blk_col, #endif // CONFIG_CROSS_CHROMA_TX const TXB_CTX *const txb_ctx, int *rate_cost) { MACROBLOCKD *const xd = &x->e_mbd; @@ -95,14 +95,15 @@ #endif // CONFIG_CONTEXT_DERIVATION ); #if CONFIG_CROSS_CHROMA_TX - *rate_cost += get_cctx_type_cost(x, xd, plane, tx_size, block, cctx_type); + *rate_cost += get_cctx_type_cost(&cpi->common, x, xd, plane, tx_size, + blk_row, blk_col, block, cctx_type); #endif // CONFIG_CROSS_CHROMA_TX return eob; } return av1_optimize_txb_new(cpi, x, plane, block, tx_size, tx_type, #if CONFIG_CROSS_CHROMA_TX - cctx_type, + cctx_type, blk_row, blk_col, #endif // CONFIG_CROSS_CHROMA_TX txb_ctx, rate_cost, cpi->oxcf.algo_cfg.sharpness); } @@ -560,11 +561,26 @@ tx_size, cm->features.reduced_tx_set_used); #if CONFIG_CROSS_CHROMA_TX CctxType cctx_type = av1_get_cctx_type(xd, blk_row, blk_col); +#if CCTX_ADAPT_REDUCED_SET + if (plane) { + // TODO(kslu) change this workaround + // Since contexts can be changed during the dry run tx search, check if the + // cctx type is valid here. If not, just use CCTX_NONE. + int above_cctx, left_cctx; + get_above_and_left_cctx_type(cm, xd, blk_row, blk_col, tx_size, &above_cctx, + &left_cctx); + uint8_t allowed_cctx_mask = get_allowed_cctx_mask(above_cctx, left_cctx); + if (!(allowed_cctx_mask & (1 << cctx_type))) { + cctx_type = CCTX_NONE; + update_cctx_array(xd, blk_row, blk_col, 0, 0, tx_size, CCTX_NONE); + } + } +#endif #endif // CONFIG_CROSS_CHROMA_TX if (!is_blk_skip(x->txfm_search_info.blk_skip, plane, blk_row * bw + blk_col) && -#if CONFIG_CROSS_CHROMA_TX && CCTX_INTER && CCTX_C1_NONZERO +#if CONFIG_CROSS_CHROMA_TX && CCTX_INTER #if CCTX_C2_DROPPED (plane < AOM_PLANE_V || ((cctx_type == CCTX_NONE || x->plane[AOM_PLANE_U].eobs[block]) && @@ -573,7 +589,7 @@ (plane < AOM_PLANE_V || cctx_type == CCTX_NONE || x->plane[AOM_PLANE_U].eobs[block]) && #endif -#endif // CONFIG_CROSS_CHROMA_TX && CCTX_INTER && CCTX_C1_NONZERO +#endif // CONFIG_CROSS_CHROMA_TX && CCTX_INTER #if CONFIG_SKIP_MODE_ENHANCEMENT !(mbmi->skip_mode == 1)) { #else @@ -635,7 +651,7 @@ ); av1_optimize_b(args->cpi, x, plane, block, tx_size, tx_type, #if CONFIG_CROSS_CHROMA_TX - cctx_type, + cctx_type, blk_row, blk_col, #endif // CONFIG_CROSS_CHROMA_TX &txb_ctx, &dummy_rate_cost); } @@ -647,13 +663,12 @@ av1_dropout_qcoeff(x, plane, block, tx_size, tx_type, cm->quant_params.base_qindex); } -#if CONFIG_CROSS_CHROMA_TX && CCTX_C1_NONZERO +#if CONFIG_CROSS_CHROMA_TX // Since eob can be updated here, make sure cctx_type is always CCTX_NONE // when eob of U is 0. - // TODO(kslu) why cctx_type can be > CCTX_NONE when eob_u is 0? if (plane == AOM_PLANE_U && p->eobs[block] == 0) - update_cctx_array(xd, blk_row, blk_col, tx_size, CCTX_NONE); -#endif // CONFIG_CROSS_CHROMA_TX && CCTX_C1_NONZERO + update_cctx_array(xd, blk_row, blk_col, 0, 0, tx_size, CCTX_NONE); +#endif // CONFIG_CROSS_CHROMA_TX } else { #if CONFIG_CROSS_CHROMA_TX && CCTX_C2_DROPPED // Reset coeffs and dqcoeffs @@ -1146,7 +1161,7 @@ ); av1_optimize_b(args->cpi, x, plane, block, tx_size, tx_type, #if CONFIG_CROSS_CHROMA_TX - CCTX_NONE, + CCTX_NONE, blk_row, blk_col, #endif // CONFIG_CROSS_CHROMA_TX &txb_ctx, &dummy_rate_cost); } @@ -1246,6 +1261,19 @@ TX_TYPE tx_type = av1_get_tx_type(xd, PLANE_TYPE_UV, blk_row, blk_col, tx_size, cm->features.reduced_tx_set_used); CctxType cctx_type = av1_get_cctx_type(xd, blk_row, blk_col); +#if CCTX_ADAPT_REDUCED_SET + // TODO(kslu) change this workaround + // Since contexts can be changed during the dry run tx search, check if the + // cctx type is valid here. If not, just use CCTX_NONE. + int above_cctx, left_cctx; + get_above_and_left_cctx_type(cm, xd, blk_row, blk_col, tx_size, &above_cctx, + &left_cctx); + uint8_t allowed_cctx_mask = get_allowed_cctx_mask(above_cctx, left_cctx); + if (!(allowed_cctx_mask & (1 << cctx_type))) { + cctx_type = CCTX_NONE; + update_cctx_array(xd, blk_row, blk_col, 0, 0, tx_size, CCTX_NONE); + } +#endif av1_subtract_txb(x, AOM_PLANE_U, plane_bsize, blk_col, blk_row, tx_size); av1_subtract_txb(x, AOM_PLANE_V, plane_bsize, blk_col, blk_row, tx_size); @@ -1283,22 +1311,20 @@ INTRA_BLOCK_OPT_TYPE == TRELLIS_DROPOUT_OPT)); for (int plane = AOM_PLANE_U; plane <= AOM_PLANE_V; plane++) { -#if CCTX_C1_NONZERO + // Since eob can be updated here, make sure cctx_type is always CCTX_NONE + // when eob of U is 0. + if (plane == AOM_PLANE_V && *eob_u == 0) + update_cctx_array(xd, blk_row, blk_col, 0, 0, tx_size, CCTX_NONE); #if CCTX_C2_DROPPED if (plane == AOM_PLANE_V && (!keep_chroma_c2(cctx_type) || (*eob_u == 0 && cctx_type > CCTX_NONE))) { #else if (plane == AOM_PLANE_V && *eob_u == 0 && cctx_type > CCTX_NONE) { #endif - // Since eob can be updated here, make sure cctx_type is always CCTX_NONE - // when eob of U is 0. - if (*eob_u == 0 && cctx_type > CCTX_NONE) - update_cctx_array(xd, blk_row, blk_col, tx_size, CCTX_NONE); av1_quantize_skip(av1_get_max_eob(tx_size), p_v->coeff + BLOCK_OFFSET(block), dqcoeff_v, eob_v); break; } -#endif av1_setup_qmatrix(&cm->quant_params, xd, plane, tx_size, tx_type, &quant_param); av1_xform_quant( @@ -1320,7 +1346,7 @@ #endif // CONFIG_FORWARDSKIP ); av1_optimize_b(args->cpi, x, plane, block, tx_size, tx_type, cctx_type, - &txb_ctx, &dummy_rate_cost); + blk_row, blk_col, &txb_ctx, &dummy_rate_cost); } if (do_dropout) { av1_dropout_qcoeff(x, plane, block, tx_size, tx_type,
diff --git a/av1/encoder/encodemb.h b/av1/encoder/encodemb.h index ade30ee..68dd9cc 100644 --- a/av1/encoder/encodemb.h +++ b/av1/encoder/encodemb.h
@@ -124,7 +124,7 @@ int av1_optimize_b(const struct AV1_COMP *cpi, MACROBLOCK *mb, int plane, int block, TX_SIZE tx_size, TX_TYPE tx_type, #if CONFIG_CROSS_CHROMA_TX - CctxType cctx_type, + CctxType cctx_type, int blk_row, int blk_col, #endif // CONFIG_CROSS_CHROMA_TX const TXB_CTX *const txb_ctx, int *rate_cost);
diff --git a/av1/encoder/encoder.h b/av1/encoder/encoder.h index 6d8cd79..0e1f301 100644 --- a/av1/encoder/encoder.h +++ b/av1/encoder/encoder.h
@@ -1298,7 +1298,7 @@ [TX_TYPES]; #endif // CONFIG_DDT_INTER #if CONFIG_CROSS_CHROMA_TX - unsigned int cctx_type[EXT_TX_SIZES][CCTX_TYPES]; + unsigned int cctx_type[EXT_TX_SIZES][CCTX_CONTEXTS][CCTX_TYPES_ALLOWED]; #endif // CONFIG_CROSS_CHROMA_TX unsigned int filter_intra_mode[FILTER_INTRA_MODES]; unsigned int filter_intra[BLOCK_SIZES_ALL][2];
diff --git a/av1/encoder/encodetxb.c b/av1/encoder/encodetxb.c index 4ca8a19..1157ad1 100644 --- a/av1/encoder/encodetxb.c +++ b/av1/encoder/encodetxb.c
@@ -457,23 +457,11 @@ #endif // CONFIG_CONTEXT_DERIVATION #if CONFIG_CROSS_CHROMA_TX -#if CCTX_C1_NONZERO - if (plane == AOM_PLANE_U && eob > 0) { + if (plane == AOM_PLANE_U) { CctxType cctx_type = av1_get_cctx_type(xd, blk_row, blk_col); - av1_write_cctx_type(cm, xd, cctx_type, tx_size, w); + if (eob > 0) + av1_write_cctx_type(cm, xd, blk_row, blk_col, cctx_type, tx_size, w); } -#else - // tx_type is signaled with Y plane if eob > 0. cctx_type is signaled with V - // plane if either of eob_u and eob_v is > 0. - if (plane == AOM_PLANE_V) { - const uint16_t *eob_txb_u = cb_coef_buff->eobs[AOM_PLANE_U] + txb_offset; - const uint16_t eob_u = eob_txb_u[block]; - if (eob > 0 || eob_u > 0) { - const CctxType cctx_type = av1_get_cctx_type(xd, blk_row, blk_col); - av1_write_cctx_type(cm, xd, cctx_type, tx_size, w); - } - } -#endif // CCTX_C1_NONZERO #endif // CONFIG_CROSS_CHROMA_TX if (eob == 0) return 0; @@ -600,22 +588,10 @@ #endif // CONFIG_CONTEXT_DERIVATION #if CONFIG_CROSS_CHROMA_TX -#if CCTX_C1_NONZERO if (plane == AOM_PLANE_U && eob > 0) { CctxType cctx_type = av1_get_cctx_type(xd, blk_row, blk_col); - av1_write_cctx_type(cm, xd, cctx_type, tx_size, w); + av1_write_cctx_type(cm, xd, blk_row, blk_col, cctx_type, tx_size, w); } -#else - // CCTX type is transmitted with V plane - if (plane == AOM_PLANE_V) { - const uint16_t *eob_txb_u = cb_coef_buff->eobs[AOM_PLANE_U] + txb_offset; - const uint16_t eob_u = eob_txb_u[block]; - if (eob > 0 || eob_u > 0) { - const CctxType cctx_type = av1_get_cctx_type(xd, blk_row, blk_col); - av1_write_cctx_type(cm, xd, cctx_type, tx_size, w); - } - } -#endif // CCTX_C1_NONZERO #endif // CONFIG_CROSS_CHROMA_TX #endif // CONFIG_FORWARDSKIP @@ -879,22 +855,27 @@ } #if CONFIG_CROSS_CHROMA_TX -int get_cctx_type_cost(const MACROBLOCK *x, const MACROBLOCKD *xd, int plane, - TX_SIZE tx_size, int block, CctxType cctx_type) { +int get_cctx_type_cost(const AV1_COMMON *cm, const MACROBLOCK *x, + const MACROBLOCKD *xd, int plane, TX_SIZE tx_size, + int blk_row, int blk_col, int block, + CctxType cctx_type) { const int is_inter = is_inter_block(xd->mi[0], xd->tree_type); - const TX_SIZE square_tx_size = txsize_sqr_map[tx_size]; -#if CCTX_C1_NONZERO - (void)block; if (plane == AOM_PLANE_U && x->plane[plane].eobs[block] && + ((is_inter && CCTX_INTER) || (!is_inter && CCTX_INTRA))) { + const TX_SIZE square_tx_size = txsize_sqr_map[tx_size]; + int above_cctx, left_cctx; + get_above_and_left_cctx_type(cm, xd, blk_row, blk_col, tx_size, &above_cctx, + &left_cctx); + const int cctx_ctx = get_cctx_context(xd, above_cctx, left_cctx); +#if CCTX_ADAPT_REDUCED_SET + const int cctx_idx = cctx_type_to_idx(cctx_type, above_cctx, left_cctx); + return x->mode_costs.cctx_type_cost[square_tx_size][cctx_ctx][cctx_idx]; #else - if (plane == AOM_PLANE_V && - (x->plane[AOM_PLANE_U].eobs[block] || - x->plane[AOM_PLANE_V].eobs[block]) && -#endif // CCTX_C1_NONZERO - ((is_inter && CCTX_INTER) || (!is_inter && CCTX_INTRA))) - return x->mode_costs.cctx_type_cost[square_tx_size][cctx_type]; - else + return x->mode_costs.cctx_type_cost[square_tx_size][cctx_ctx][cctx_type]; +#endif + } else { return 0; + } } #endif // CONFIG_CROSS_CHROMA_TX @@ -1024,13 +1005,16 @@ #if CONFIG_FORWARDSKIP static AOM_FORCE_INLINE int warehouse_efficients_txb_skip( +#if CONFIG_CROSS_CHROMA_TX + const AV1_COMMON *cm, +#endif // CONFIG_CROSS_CHROMA_TX const MACROBLOCK *x, const int plane, const int block, const TX_SIZE tx_size, const TXB_CTX *const txb_ctx, const struct macroblock_plane *p, const int eob, const LV_MAP_COEFF_COST *const coeff_costs, const MACROBLOCKD *const xd, const TX_TYPE tx_type, #if CONFIG_CROSS_CHROMA_TX - const CctxType cctx_type, + const CctxType cctx_type, int blk_row, int blk_col, #endif // CONFIG_CROSS_CHROMA_TX int reduced_tx_set_used) { const tran_low_t *const qcoeff = p->qcoeff + BLOCK_OFFSET(block); @@ -1053,7 +1037,8 @@ #endif // CONFIG_IST ); #if CONFIG_CROSS_CHROMA_TX - cost += get_cctx_type_cost(x, xd, plane, tx_size, block, cctx_type); + cost += get_cctx_type_cost(cm, x, xd, plane, tx_size, blk_row, blk_col, block, + cctx_type); #endif // CONFIG_CROSS_CHROMA_TX DECLARE_ALIGNED(16, int8_t, coeff_contexts[MAX_TX_SQUARE]); av1_get_nz_map_contexts_skip(levels, scan, eob, tx_size, coeff_contexts); @@ -1088,13 +1073,16 @@ #endif // CONFIG_FORWARDSKIP static AOM_FORCE_INLINE int warehouse_efficients_txb( +#if CONFIG_CROSS_CHROMA_TX + const AV1_COMMON *cm, +#endif // CONFIG_CROSS_CHROMA_TX const MACROBLOCK *x, const int plane, const int block, const TX_SIZE tx_size, const TXB_CTX *const txb_ctx, const struct macroblock_plane *p, const int eob, const PLANE_TYPE plane_type, const LV_MAP_COEFF_COST *const coeff_costs, const MACROBLOCKD *const xd, const TX_TYPE tx_type, #if CONFIG_CROSS_CHROMA_TX - const CctxType cctx_type, + const CctxType cctx_type, int blk_row, int blk_col, #endif // CONFIG_CROSS_CHROMA_TX const TX_CLASS tx_class, int reduced_tx_set_used) { const tran_low_t *const qcoeff = p->qcoeff + BLOCK_OFFSET(block); @@ -1138,7 +1126,8 @@ #endif ); #if CONFIG_CROSS_CHROMA_TX - cost += get_cctx_type_cost(x, xd, plane, tx_size, block, cctx_type); + cost += get_cctx_type_cost(cm, x, xd, plane, tx_size, blk_row, blk_col, block, + cctx_type); #endif // CONFIG_CROSS_CHROMA_TX cost += get_eob_cost(eob, eob_costs, coeff_costs, tx_class); @@ -1249,15 +1238,15 @@ } static AOM_FORCE_INLINE int warehouse_efficients_txb_laplacian( -#if CONFIG_FORWARDSKIP +#if CONFIG_FORWARDSKIP || CONFIG_CROSS_CHROMA_TX const AV1_COMMON *cm, -#endif // CONFIG_FORWARDSKIP +#endif // CONFIG_FORWARDSKIP || CONFIG_CROSS_CHROMA_TX const MACROBLOCK *x, const int plane, const int block, const TX_SIZE tx_size, const TXB_CTX *const txb_ctx, const int eob, const PLANE_TYPE plane_type, const LV_MAP_COEFF_COST *const coeff_costs, const MACROBLOCKD *const xd, const TX_TYPE tx_type, #if CONFIG_CROSS_CHROMA_TX - const CctxType cctx_type, + const CctxType cctx_type, int blk_row, int blk_col, #endif // CONFIG_CROSS_CHROMA_TX const TX_CLASS tx_class, int reduced_tx_set_used) { #if CONFIG_CONTEXT_DERIVATION @@ -1291,7 +1280,8 @@ #endif // CONFIG_IST ); #if CONFIG_CROSS_CHROMA_TX - cost += get_cctx_type_cost(x, xd, plane, tx_size, block, cctx_type); + cost += get_cctx_type_cost(cm, x, xd, plane, tx_size, blk_row, blk_col, block, + cctx_type); #endif // CONFIG_CROSS_CHROMA_TX #if !CONFIG_FORWARDSKIP @@ -1387,7 +1377,7 @@ } #endif // CONFIG_FORWARDSKIP -#if CONFIG_FORWARDSKIP +#if CONFIG_FORWARDSKIP || CONFIG_CROSS_CHROMA_TX int av1_cost_coeffs_txb(const AV1_COMMON *cm, const MACROBLOCK *x, const int plane, const int block, #else @@ -1395,7 +1385,7 @@ #endif // CONFIG_FORWARDSKIP const TX_SIZE tx_size, const TX_TYPE tx_type, #if CONFIG_CROSS_CHROMA_TX - const CctxType cctx_type, + const CctxType cctx_type, int blk_row, int blk_col, #endif // CONFIG_CROSS_CHROMA_TX const TXB_CTX *const txb_ctx, int reduced_tx_set_used) { const struct macroblock_plane *p = &x->plane[plane]; @@ -1423,7 +1413,8 @@ skip_cost += coeff_costs->txb_skip_cost[txb_ctx->txb_skip_ctx][1]; #endif // CONFIG_CONTEXT_DERIVATION #if CONFIG_CROSS_CHROMA_TX - skip_cost += get_cctx_type_cost(x, xd, plane, tx_size, block, cctx_type); + skip_cost += get_cctx_type_cost(cm, x, xd, plane, tx_size, blk_row, blk_col, + block, cctx_type); #endif // CONFIG_CROSS_CHROMA_TX return skip_cost; } @@ -1443,38 +1434,49 @@ tx_type == IDTX && plane == PLANE_TYPE_Y) || #endif // CONFIG_IST use_inter_fsc(cm, plane, tx_type, is_inter_block(mbmi, xd->tree_type))) { - return warehouse_efficients_txb_skip(x, plane, block, tx_size, txb_ctx, p, - eob, coeff_costs, xd, tx_type, + return warehouse_efficients_txb_skip( #if CONFIG_CROSS_CHROMA_TX - cctx_type, + cm, #endif // CONFIG_CROSS_CHROMA_TX - reduced_tx_set_used); + x, plane, block, tx_size, txb_ctx, p, eob, coeff_costs, xd, tx_type, +#if CONFIG_CROSS_CHROMA_TX + cctx_type, blk_row, blk_col, +#endif // CONFIG_CROSS_CHROMA_TX + reduced_tx_set_used); } else { - return warehouse_efficients_txb(x, plane, block, tx_size, txb_ctx, p, eob, - plane_type, coeff_costs, xd, tx_type, + return warehouse_efficients_txb( #if CONFIG_CROSS_CHROMA_TX - cctx_type, + cm, #endif // CONFIG_CROSS_CHROMA_TX - tx_class, reduced_tx_set_used); + x, plane, block, tx_size, txb_ctx, p, eob, plane_type, coeff_costs, xd, + tx_type, +#if CONFIG_CROSS_CHROMA_TX + cctx_type, blk_row, blk_col, +#endif // CONFIG_CROSS_CHROMA_TX + tx_class, reduced_tx_set_used); } #else - return warehouse_efficients_txb(x, plane, block, tx_size, txb_ctx, p, eob, - plane_type, coeff_costs, xd, tx_type, + return warehouse_efficients_txb( #if CONFIG_CROSS_CHROMA_TX - cctx_type, + cm, #endif // CONFIG_CROSS_CHROMA_TX - tx_class, reduced_tx_set_used); + x, plane, block, tx_size, txb_ctx, p, eob, plane_type, coeff_costs, xd, + tx_type, +#if CONFIG_CROSS_CHROMA_TX + cctx_type, blk_row, blk_col, +#endif // CONFIG_CROSS_CHROMA_TX + tx_class, reduced_tx_set_used); #endif // CONFIG_FORWARDSKIP } int av1_cost_coeffs_txb_laplacian( -#if CONFIG_FORWARDSKIP +#if CONFIG_FORWARDSKIP || CONFIG_CROSS_CHROMA_TX const AV1_COMMON *cm, #endif // CONFIG_FORWARDSKIP const MACROBLOCK *x, const int plane, const int block, const TX_SIZE tx_size, const TX_TYPE tx_type, #if CONFIG_CROSS_CHROMA_TX - const CctxType cctx_type, + const CctxType cctx_type, int blk_row, int blk_col, #endif // CONFIG_CROSS_CHROMA_TX const TXB_CTX *const txb_ctx, const int reduced_tx_set_used, const int adjust_eob) { @@ -1512,7 +1514,8 @@ skip_cost += coeff_costs->txb_skip_cost[txb_ctx->txb_skip_ctx][1]; #endif // CONFIG_CONTEXT_DERIVATION #if CONFIG_CROSS_CHROMA_TX - skip_cost += get_cctx_type_cost(x, xd, plane, tx_size, block, cctx_type); + skip_cost += get_cctx_type_cost(cm, x, xd, plane, tx_size, blk_row, blk_col, + block, cctx_type); #endif // CONFIG_CROSS_CHROMA_TX return skip_cost; } @@ -1524,13 +1527,13 @@ #endif return warehouse_efficients_txb_laplacian( -#if CONFIG_FORWARDSKIP +#if CONFIG_FORWARDSKIP || CONFIG_CROSS_CHROMA_TX cm, -#endif // CONFIG_FORWARDSKIP +#endif // CONFIG_FORWARDSKIP || CONFIG_CROSS_CHROMA_TX x, plane, block, tx_size, txb_ctx, eob, plane_type, coeff_costs, xd, tx_type, #if CONFIG_CROSS_CHROMA_TX - cctx_type, + cctx_type, blk_row, blk_col, #endif // CONFIG_CROSS_CHROMA_TX tx_class, reduced_tx_set_used); } @@ -1951,7 +1954,7 @@ int av1_optimize_txb_new(const struct AV1_COMP *cpi, MACROBLOCK *x, int plane, int block, TX_SIZE tx_size, TX_TYPE tx_type, #if CONFIG_CROSS_CHROMA_TX - CctxType cctx_type, + CctxType cctx_type, int blk_row, int blk_col, #endif // CONFIG_CROSS_CHROMA_TX const TXB_CTX *const txb_ctx, int *rate_cost, int sharpness) { @@ -2164,7 +2167,8 @@ av1_get_txb_entropy_context(qcoeff, scan_order, p->eobs[block]); #if CONFIG_CROSS_CHROMA_TX - accu_rate += get_cctx_type_cost(x, xd, plane, tx_size, block, cctx_type); + accu_rate += get_cctx_type_cost(cm, x, xd, plane, tx_size, blk_row, blk_col, + block, cctx_type); #endif // CONFIG_CROSS_CHROMA_TX *rate_cost = accu_rate; @@ -2205,11 +2209,26 @@ !mbmi->skip_txfm[xd->tree_type == CHROMA_PART] && !segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP)) { const CctxType cctx_type = av1_get_cctx_type(xd, blk_row, blk_col); + int above_cctx, left_cctx; + get_above_and_left_cctx_type(cm, xd, blk_row, blk_col, tx_size, &above_cctx, + &left_cctx); + const int cctx_ctx = get_cctx_context(xd, above_cctx, left_cctx); if (allow_update_cdf) - update_cdf(fc->cctx_type_cdf[txsize_sqr_map[tx_size]], cctx_type, - CCTX_TYPES); +#if CCTX_ADAPT_REDUCED_SET + update_cdf(fc->cctx_type_cdf[txsize_sqr_map[tx_size]][cctx_ctx], + cctx_type_to_idx(cctx_type, above_cctx, left_cctx), + CCTX_TYPES_ALLOWED); +#else + update_cdf(fc->cctx_type_cdf[txsize_sqr_map[tx_size]][cctx_ctx], + cctx_type, CCTX_TYPES_ALLOWED); +#endif #if CONFIG_ENTROPY_STATS - ++counts->cctx_type[txsize_sqr_map[tx_size]][cctx_type]; +#if CCTX_ADAPT_REDUCED_SET + ++counts->cctx_type[txsize_sqr_map[tx_size]][cctx_ctx] + [cctx_type_to_idx(cctx_type, above_cctx, left_cctx)]; +#else + ++counts->cctx_type[txsize_sqr_map[tx_size]][cctx_ctx][cctx_type]; +#endif #endif // CONFIG_ENTROPY_STATS } } @@ -2659,17 +2678,9 @@ eob_txb[block] = eob; #if CONFIG_CROSS_CHROMA_TX -#if CCTX_C1_NONZERO if (plane == AOM_PLANE_U && eob > 0) update_cctx_type_count(cm, xd, blk_row, blk_col, tx_size, td->counts, allow_update_cdf); -#else - if (plane == AOM_PLANE_V && - (eob > 0 || x->plane[AOM_PLANE_U].eobs[block] > 0)) { - update_cctx_type_count(cm, xd, blk_row, blk_col, tx_size, td->counts, - allow_update_cdf); - } -#endif // CCTX_C1_NONZERO #endif // CONFIG_CROSS_CHROMA_TX if (eob == 0) { av1_set_entropy_contexts(xd, pd, plane, plane_bsize, tx_size, 0, blk_col,
diff --git a/av1/encoder/encodetxb.h b/av1/encoder/encodetxb.h index 7e1be18..3f2bdcc 100644 --- a/av1/encoder/encodetxb.h +++ b/av1/encoder/encodetxb.h
@@ -98,7 +98,11 @@ * \param[in] tx_type The transform type.*/ #if CONFIG_CROSS_CHROMA_TX /* \param[in] cctx_type The cross chroma component transform - * type*/ + * type + * \param[in] blk_row The row index of the current transform block + * in the macroblock. Each unit has 4 pixels in y plane. + * \param[in] blk_col The col index of the current transform block + * in the macroblock. Each unit has 4 pixels in y plane.*/ #endif // CONFIG_CROSS_CHROMA_TX /* \param[in] txb_ctx Context info for entropy coding transform block @@ -113,7 +117,7 @@ const MACROBLOCK *x, const int plane, const int block, const TX_SIZE tx_size, const TX_TYPE tx_type, #if CONFIG_CROSS_CHROMA_TX - const CctxType cctx_type, + const CctxType cctx_type, int blk_row, int blk_col, #endif // CONFIG_CROSS_CHROMA_TX const TXB_CTX *const txb_ctx, int reduced_tx_set_used); @@ -147,7 +151,11 @@ * \param[in] tx_size The transform size * \param[in] tx_type The transform type*/ #if CONFIG_CROSS_CHROMA_TX -/* \param[in] cctx_type The cross chroma component transform type*/ +/* \param[in] cctx_type The cross chroma component transform type + * \param[in] blk_row The row index of the current transform block + * in the macroblock. Each unit has 4 pixels in y plane. + * \param[in] blk_col The col index of the current transform block + * in the macroblock. Each unit has 4 pixels in y plane.*/ #endif // CONFIG_CROSS_CHROMA_TX /* \param[in] txb_ctx Context info for entropy coding transform block * skip flag (tx_skip) and the sign of DC coefficient (dc_sign). @@ -166,7 +174,7 @@ const MACROBLOCK *x, const int plane, const int block, const TX_SIZE tx_size, const TX_TYPE tx_type, #if CONFIG_CROSS_CHROMA_TX - const CctxType cctx_type, + const CctxType cctx_type, int blk_row, int blk_col, #endif // CONFIG_CROSS_CHROMA_TX const TXB_CTX *const txb_ctx, const int reduced_tx_set_used, const int adjust_eob); @@ -506,6 +514,10 @@ * \param[in] tx_size The transform size * \param[in] tx_type The transform type * \param[in] cctx_type The cross chroma component transform type + * \param[in] blk_row The row index of the current transform block + * in the macroblock. Each unit has 4 pixels in y plane. + * \param[in] blk_col The col index of the current transform block + * in the macroblock. Each unit has 4 pixels in y plane. * \param[in] txb_ctx Context info for entropy coding transform block * skip flag (tx_skip) and the sign of DC coefficient (dc_sign). * \param[out] rate_cost The entropy cost of coding the transform block @@ -551,7 +563,7 @@ int av1_optimize_txb_new(const struct AV1_COMP *cpi, MACROBLOCK *x, int plane, int block, TX_SIZE tx_size, TX_TYPE tx_type, #if CONFIG_CROSS_CHROMA_TX - CctxType cctx_type, + CctxType cctx_type, int blk_row, int blk_col, #endif // CONFIG_CROSS_CHROMA_TX const TXB_CTX *const txb_ctx, int *rate_cost, int sharpness); @@ -575,9 +587,32 @@ */ CB_COEFF_BUFFER *av1_get_cb_coeff_buffer(const struct AV1_COMP *cpi, int mi_row, int mi_col); + #if CONFIG_CROSS_CHROMA_TX -int get_cctx_type_cost(const MACROBLOCK *x, const MACROBLOCKD *xd, int plane, - TX_SIZE tx_size, int block, CctxType cctx_type); +/*!\brief Return the entropy cost associated with the cross chroma transform + * + * \ingroup coefficient_coding + * + * \param[in] cm Top-level structure shared by encoder and + decoder + * \param[in] x Pointer to structure holding the data for the + current encoding macroblock + * \param[in] xd Pointer to structure holding the data for the + current macroblockd + * \param[in] plane The index of the current plane + * \param[in] tx_size The transform size + * \param[in] blk_row The row index of the current transform block + * in the macroblock. Each unit has 4 pixels in y plane. + * \param[in] blk_col The col index of the current transform block + * in the macroblock. Each unit has 4 pixels in y plane. + * \param[in] block The index of the current transform block + * \param[in] cctx_type The cross chroma transform type + * + * \return int Entropy cost for cctx type + */ +int get_cctx_type_cost(const AV1_COMMON *cm, const MACROBLOCK *x, + const MACROBLOCKD *xd, int plane, TX_SIZE tx_size, + int blk_row, int blk_col, int block, CctxType cctx_type); #endif // CONFIG_CROSS_CHROMA_TX #if CONFIG_CONTEXT_DERIVATION
diff --git a/av1/encoder/rd.c b/av1/encoder/rd.c index 9eaec85..fd15af0 100644 --- a/av1/encoder/rd.c +++ b/av1/encoder/rd.c
@@ -322,8 +322,10 @@ #if CONFIG_CROSS_CHROMA_TX for (i = 0; i < EXT_TX_SIZES; ++i) { - av1_cost_tokens_from_cdf(mode_costs->cctx_type_cost[i], - fc->cctx_type_cdf[i], NULL); + for (j = 0; j < CCTX_CONTEXTS; ++j) { + av1_cost_tokens_from_cdf(mode_costs->cctx_type_cost[i][j], + fc->cctx_type_cdf[i][j], NULL); + } } #endif // CONFIG_CROSS_CHROMA_TX
diff --git a/av1/encoder/rdopt.c b/av1/encoder/rdopt.c index 7baa75e..471743c 100644 --- a/av1/encoder/rdopt.c +++ b/av1/encoder/rdopt.c
@@ -1626,7 +1626,7 @@ uint8_t best_blk_skip[MAX_MIB_SIZE * MAX_MIB_SIZE]; TX_TYPE best_tx_type_map[MAX_MIB_SIZE * MAX_MIB_SIZE]; #if CONFIG_CROSS_CHROMA_TX - TX_TYPE best_cctx_type_map[MAX_MIB_SIZE * MAX_MIB_SIZE]; + CctxType best_cctx_type_map[MAX_MIB_SIZE * MAX_MIB_SIZE]; #endif // CONFIG_CROSS_CHROMA_TX const int rate_mv0 = *rate_mv; const int interintra_allowed = @@ -3569,7 +3569,7 @@ TX_TYPE best_tx_type_map[MAX_MIB_SIZE * MAX_MIB_SIZE]; av1_copy_array(best_tx_type_map, xd->tx_type_map, ctx->num_4x4_blk); #if CONFIG_CROSS_CHROMA_TX - TX_TYPE best_cctx_type_map[MAX_MIB_SIZE * MAX_MIB_SIZE]; + CctxType best_cctx_type_map[MAX_MIB_SIZE * MAX_MIB_SIZE]; av1_copy_array(best_cctx_type_map, xd->cctx_type_map, ctx->num_4x4_blk); #endif // CONFIG_CROSS_CHROMA_TX
diff --git a/av1/encoder/tx_search.c b/av1/encoder/tx_search.c index 4e33bbb..a09bd53 100644 --- a/av1/encoder/tx_search.c +++ b/av1/encoder/tx_search.c
@@ -1152,7 +1152,7 @@ if (quant_param_intra.use_optimize_b) { av1_optimize_b(cpi, x, plane, block, tx_size, best_tx_type, #if CONFIG_CROSS_CHROMA_TX - cctx_type, + cctx_type, blk_row, blk_col, #endif // CONFIG_CROSS_CHROMA_TX txb_ctx, rate_cost); } @@ -1315,9 +1315,7 @@ memcpy(tmp_dqcoeff_v, p_v->dqcoeff + BLOCK_OFFSET(block), sizeof(tran_low_t) * eob_max); -#if CCTX_C1_NONZERO assert(p_u->eobs[block] > 0); -#endif assert(cpi != NULL); assert(tx_size_wide_log2[0] == tx_size_high_log2[0]); @@ -1551,7 +1549,7 @@ #endif // CONFIG_FORWARDSKIP x, plane, block, tx_size, tx_type, #if CONFIG_CROSS_CHROMA_TX - CCTX_NONE, + CCTX_NONE, blk_row, blk_col, #endif // CONFIG_CROSS_CHROMA_TX txb_ctx, reduced_tx_set_used, 0); @@ -1592,7 +1590,7 @@ #endif // CONFIG_FORWARDSKIP x, plane, block, tx_size, tx_type, #if CONFIG_CROSS_CHROMA_TX - CCTX_NONE, + CCTX_NONE, blk_row, blk_col, #endif // CONFIG_CROSS_CHROMA_TX txb_ctx, reduced_tx_set_used, 0); @@ -1712,7 +1710,7 @@ #endif // CONFIG_FORWARDSKIP x, plane, block, tx_size, tx_type, #if CONFIG_CROSS_CHROMA_TX - CCTX_NONE, + CCTX_NONE, blk_row, blk_col, #endif // CONFIG_CROSS_CHROMA_TX txb_ctx, reduced_tx_set_used, 0); // tx domain dist @@ -2339,7 +2337,7 @@ #endif // CONFIG_FORWARDSKIP MACROBLOCK *x, int plane, int block, TX_SIZE tx_size, const TX_TYPE tx_type, #if CONFIG_CROSS_CHROMA_TX - const CctxType cctx_type, + const CctxType cctx_type, int blk_row, int blk_col, #endif // CONFIG_CROSS_CHROMA_TX const TXB_CTX *const txb_ctx, int reduced_tx_set_used) { #if TXCOEFF_COST_TIMER @@ -2352,7 +2350,7 @@ #endif // CONFIG_FORWARDSKIP x, plane, block, tx_size, tx_type, #if CONFIG_CROSS_CHROMA_TX - cctx_type, + cctx_type, blk_row, blk_col, #endif // CONFIG_CROSS_CHROMA_TX txb_ctx, reduced_tx_set_used); #if TXCOEFF_COST_TIMER @@ -2800,7 +2798,7 @@ if (quant_param.use_optimize_b) { av1_optimize_b(cpi, x, plane, block, tx_size, tx_type, #if CONFIG_CROSS_CHROMA_TX - CCTX_NONE, + CCTX_NONE, blk_row, blk_col, #endif // CONFIG_CROSS_CHROMA_TX txb_ctx, &rate_cost); } else { @@ -2810,7 +2808,7 @@ #endif // CONFIG_FORWARDSKIP x, plane, block, tx_size, tx_type, #if CONFIG_CROSS_CHROMA_TX - CCTX_NONE, + CCTX_NONE, blk_row, blk_col, #endif // CONFIG_CROSS_CHROMA_TX txb_ctx, cm->features.reduced_tx_set_used); } @@ -3055,12 +3053,23 @@ memcpy(orig_coeff_v, p_v->coeff + BLOCK_OFFSET(block), sizeof(tran_low_t) * max_eob); +#if CCTX_ADAPT_REDUCED_SET + int above_cctx, left_cctx; + get_above_and_left_cctx_type(cm, xd, blk_row, blk_col, tx_size, &above_cctx, + &left_cctx); + uint8_t cctx_mask = get_allowed_cctx_mask(above_cctx, left_cctx); +#endif + // Iterate through all transform type candidates. for (CctxType cctx_type = CCTX_START; cctx_type < CCTX_TYPES; ++cctx_type) { +#if CCTX_ADAPT_REDUCED_SET + if (!(cctx_mask & (1 << cctx_type))) continue; +#endif + RD_STATS this_rd_stats; av1_invalid_rd_stats(&this_rd_stats); - update_cctx_array(xd, blk_row, blk_col, tx_size, cctx_type); + update_cctx_array(xd, blk_row, blk_col, 0, 0, tx_size, cctx_type); forward_cross_chroma_transform(x, block, tx_size, cctx_type); for (int plane = AOM_PLANE_U; plane <= AOM_PLANE_V; plane++) { @@ -3092,18 +3101,17 @@ // Calculate rate cost of quantized coefficients. if (quant_param.use_optimize_b) { av1_optimize_b(cpi, x, plane, block, tx_size, tx_type, cctx_type, - &txb_ctx_uv[plane - AOM_PLANE_U], + blk_row, blk_col, &txb_ctx_uv[plane - AOM_PLANE_U], &rate_cost[plane - AOM_PLANE_U]); } else { rate_cost[plane - AOM_PLANE_U] = cost_coeffs( #if CONFIG_FORWARDSKIP cm, #endif // CONFIG_FORWARDSKIP - x, plane, block, tx_size, tx_type, cctx_type, + x, plane, block, tx_size, tx_type, cctx_type, blk_row, blk_col, &txb_ctx_uv[plane - AOM_PLANE_U], cm->features.reduced_tx_set_used); } } -#if CCTX_C1_NONZERO // TODO(kslu) for negative angles, skip av1_xform_quant and reuse previous // dqcoeffs uint64_t sse_dqcoeff_u = @@ -3121,7 +3129,6 @@ } continue; } -#endif // If rd cost based on coeff rate alone is already more than best_rd, // terminate early. @@ -3171,15 +3178,13 @@ assert(best_rd != INT64_MAX); best_rd_stats->skip_txfm = (best_eob_u == 0 && best_eob_v == 0); - update_cctx_array(xd, blk_row, blk_col, tx_size, best_cctx_type); + update_cctx_array(xd, blk_row, blk_col, 0, 0, tx_size, best_cctx_type); p_u->txb_entropy_ctx[block] = best_txb_ctx_u; p_v->txb_entropy_ctx[block] = best_txb_ctx_v; p_u->eobs[block] = best_eob_u; p_v->eobs[block] = best_eob_v; -#if CCTX_C1_NONZERO assert(IMPLIES(best_cctx_type > CCTX_NONE, best_eob_u > 0)); -#endif #if CCTX_C2_DROPPED assert(IMPLIES(!keep_chroma_c2(best_cctx_type), best_eob_v == 0)); #endif @@ -4284,7 +4289,7 @@ const AV1_COMMON *cm = &cpi->common; RD_STATS rd_stats_joint_uv; av1_init_rd_stats(&rd_stats_joint_uv); - update_cctx_array(xd, blk_row, blk_col, tx_size, CCTX_NONE); + update_cctx_array(xd, blk_row, blk_col, 0, 0, tx_size, CCTX_NONE); // Obtain RD cost for CCTX_NONE RD_STATS rd_stats_uv[2];
diff --git a/tools/aom_entropy_optimizer.c b/tools/aom_entropy_optimizer.c index a72a843..c98d648 100644 --- a/tools/aom_entropy_optimizer.c +++ b/tools/aom_entropy_optimizer.c
@@ -375,10 +375,11 @@ #if CONFIG_CROSS_CHROMA_TX /* cctx type */ cts_each_dim[0] = EXT_TX_SIZES; - cts_each_dim[1] = CCTX_TYPES; - optimize_cdf_table(&fc.cctx_type[0][0], probsfile, 2, cts_each_dim, + cts_each_dim[1] = CCTX_CONTEXTS; + cts_each_dim[2] = CCTX_TYPES_ALLOWED; + optimize_cdf_table(&fc.cctx_type[0][0][0], probsfile, 3, cts_each_dim, "static const aom_cdf_prob default_cctx_type[EXT_TX_SIZES]" - "[CDF_SIZE(CCTX_TYPES)]"); + "[CCTX_CONTEXTS][CDF_SIZE(CCTX_TYPES_ALLOWED)]"); #endif // CONFIG_CROSS_CHROMA_TX /* tx type */