mirror of
https://github.com/ultravideo/uvg266.git
synced 2024-11-23 18:14:06 +00:00
[isp] Move can_use_lfnst_with_isp to intra.c. Remove duplicate functions. Move isp related functions from search to intra. Make isp_split_dim static. Move isp related defines from search to intra.
This commit is contained in:
parent
bcbd952dfd
commit
573ecf80e3
|
@ -102,63 +102,8 @@ static void encode_mts_idx(encoder_state_t * const state,
|
|||
}
|
||||
}
|
||||
|
||||
// ISP_TODO: move these defines to a proper place when ISP is implemented
|
||||
// As of now, these are only needed in lfnst checks
|
||||
#define NOT_INTRA_SUBPARTITIONS 0
|
||||
#define HOR_INTRA_SUBPARTITIONS 1
|
||||
#define VER_INTRA_SUBPARTITIONS 2
|
||||
#define NUM_INTRA_SUBPARTITIONS_MODES 3
|
||||
#define INTRA_SUBPARTITIONS_RESERVED 4
|
||||
#define TU_1D_HOR_SPLIT 8
|
||||
#define TU_1D_VER_SPLIT 9
|
||||
|
||||
#define MIN_TB_SIZE_X 4
|
||||
#define MIN_TB_SIZE_Y 4
|
||||
|
||||
static int get_isp_split_dim(const int width, const int height, const int isp_split_type)
|
||||
{
|
||||
bool divide_tu_in_rows = isp_split_type == TU_1D_HOR_SPLIT;
|
||||
uint32_t split_dim_size, non_split_dim_size, partition_size, div_shift = 2;
|
||||
|
||||
if (divide_tu_in_rows)
|
||||
{
|
||||
split_dim_size = height;
|
||||
non_split_dim_size = width;
|
||||
}
|
||||
else
|
||||
{
|
||||
split_dim_size = width;
|
||||
non_split_dim_size = height;
|
||||
}
|
||||
|
||||
const unsigned min_num_samples_cu = 1 << ((uvg_math_floor_log2(MIN_TB_SIZE_Y) << 1));
|
||||
const unsigned factor_to_min_samples = non_split_dim_size < min_num_samples_cu ? min_num_samples_cu >> uvg_math_floor_log2(non_split_dim_size) : 1;
|
||||
partition_size = (split_dim_size >> div_shift) < factor_to_min_samples ? factor_to_min_samples : (split_dim_size >> div_shift);
|
||||
|
||||
assert(!(uvg_math_floor_log2(partition_size) + uvg_math_floor_log2(non_split_dim_size) < uvg_math_floor_log2(min_num_samples_cu)) && "Partition has less than minimum amount of samples.");
|
||||
return partition_size;
|
||||
}
|
||||
|
||||
static bool can_use_lfnst_with_isp(const int width, const int height, const int isp_split_type, const enum uvg_tree_type tree_type)
|
||||
{
|
||||
if (tree_type == UVG_CHROMA_T) {
|
||||
return false;
|
||||
}
|
||||
if (isp_split_type == NOT_INTRA_SUBPARTITIONS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const int tu_width = (isp_split_type == HOR_INTRA_SUBPARTITIONS) ? width : get_isp_split_dim(width, height, TU_1D_VER_SPLIT);
|
||||
const int tu_height = (isp_split_type == HOR_INTRA_SUBPARTITIONS) ? get_isp_split_dim(width, height, TU_1D_HOR_SPLIT) : height;
|
||||
|
||||
if (!(tu_width >= MIN_TB_SIZE_Y && tu_height >= MIN_TB_SIZE_Y))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool uvg_is_lfnst_allowed(
|
||||
bool uvg_is_lfnst_allowed(
|
||||
const encoder_state_t* const state,
|
||||
const cu_info_t* const pred_cu,
|
||||
const int width,
|
||||
|
@ -170,8 +115,7 @@ static bool can_use_lfnst_with_isp(const int width, const int height, const int
|
|||
const lcu_t* lcu)
|
||||
{
|
||||
if (state->encoder_control->cfg.lfnst && pred_cu->type == CU_INTRA) {
|
||||
const int isp_mode = 0; // ISP_TODO: assign proper ISP mode when ISP is implemented
|
||||
const int isp_split_type = 0;
|
||||
const int isp_mode = pred_cu->intra.isp_mode;
|
||||
const int depth = pred_cu->depth;
|
||||
const int chroma_width = width >> 1;
|
||||
const int chroma_height = height >> 1;
|
||||
|
@ -181,7 +125,7 @@ static bool can_use_lfnst_with_isp(const int width, const int height, const int
|
|||
bool is_sep_tree = depth == 4 || tree_type != UVG_BOTH_T;
|
||||
bool mip_flag = pred_cu->type == CU_INTRA && color == COLOR_Y ? pred_cu->intra.mip_flag : false;
|
||||
|
||||
if ((isp_mode && !can_use_lfnst_with_isp(width, height, isp_split_type, tree_type)) ||
|
||||
if ((isp_mode && !uvg_can_use_isp_with_lfnst(width, height, isp_mode, tree_type)) ||
|
||||
(pred_cu->type == CU_INTRA && mip_flag && !can_use_lfnst_with_mip) ||
|
||||
(is_sep_tree && MIN(cu_width, cu_height) < 4) ||
|
||||
(cu_width > TR_MAX_WIDTH || cu_height > TR_MAX_WIDTH)) {
|
||||
|
@ -1064,13 +1008,6 @@ void uvg_encode_intra_luma_coding_unit(const encoder_state_t * const state,
|
|||
uint32_t width = (LCU_WIDTH >> depth);
|
||||
uint32_t height = (LCU_WIDTH >> depth);
|
||||
|
||||
// Need at least 16 samples in sub blocks to use isp. If both dimensions are 4, not enough samples. Size cannot be 2 at this point.
|
||||
bool allow_isp = !(width == 4 && height == 4);
|
||||
uint8_t isp_mode = 0;
|
||||
// ToDo: add height comparison
|
||||
//isp_mode += ((width > TR_MAX_WIDTH) || !enough_samples) ? 1 : 0;
|
||||
//isp_mode += ((height > TR_MAX_WIDTH) || !enough_samples) ? 2 : 0;
|
||||
|
||||
// Code MIP related bits
|
||||
bool enable_mip = state->encoder_control->cfg.mip;
|
||||
int8_t mip_flag = enable_mip ? cur_cu->intra.mip_flag : false;
|
||||
|
@ -1127,20 +1064,42 @@ void uvg_encode_intra_luma_coding_unit(const encoder_state_t * const state,
|
|||
}
|
||||
}
|
||||
|
||||
bool enable_isp = state->encoder_control->cfg.isp;
|
||||
// Need at least 16 samples in sub blocks to use isp. If both dimensions are 4, not enough samples. Blocks of size 2 do not exist yet (not for luma at least)
|
||||
bool allow_isp = enable_isp ? uvg_can_use_isp(width, height, 64 /*MAX_TR_SIZE*/) : false;
|
||||
uint8_t isp_mode = allow_isp ? cur_cu->intra.isp_mode : 0;
|
||||
|
||||
// ToDo: update real usage, these if clauses as such don't make any sense
|
||||
if (isp_mode != 0 && multi_ref_idx == 0) {
|
||||
if (isp_mode) {
|
||||
CABAC_FBITS_UPDATE(cabac, &(cabac->ctx.intra_subpart_model[0]), 0, bits, "intra_subPartitions");
|
||||
} else {
|
||||
CABAC_FBITS_UPDATE(cabac, &(cabac->ctx.intra_subpart_model[0]), 1, bits, "intra_subPartitions");
|
||||
// ToDo: complete this if-clause
|
||||
if (isp_mode == 3) {
|
||||
CABAC_FBITS_UPDATE(cabac, &(cabac->ctx.intra_subpart_model[0]), allow_isp - 1, bits, "intra_subPart_ver_hor");
|
||||
}
|
||||
// ToDo: add height comparison
|
||||
//isp_mode += ((width > TR_MAX_WIDTH) || !enough_samples) ? 1 : 0;
|
||||
//isp_mode += ((height > TR_MAX_WIDTH) || !enough_samples) ? 2 : 0;
|
||||
|
||||
if (allow_isp && !multi_ref_idx /*&& !bdpcm && !color_transform*/) {
|
||||
if (isp_mode == ISP_MODE_NO_ISP) {
|
||||
CABAC_FBITS_UPDATE(cabac, &(cabac->ctx.intra_subpart_model[0]), 0, bits, "intra_subpartitions_mode");
|
||||
}
|
||||
else {
|
||||
CABAC_FBITS_UPDATE(cabac, &(cabac->ctx.intra_subpart_model[0]), 1, bits, "intra_subpartitions_mode");
|
||||
CABAC_FBITS_UPDATE(cabac, &(cabac->ctx.intra_subpart_model[1]), isp_mode - 1, bits, "intra_subpartitions_split_type"); // Vertical or horizontal split
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//if (allow_isp && !multi_ref_idx /*&& !bdpcm && !color_transform*/) {
|
||||
// if (isp_mode == ISP_MODE_NO_ISP) {
|
||||
// if (isp_mode) {
|
||||
// CABAC_FBITS_UPDATE(cabac, &(cabac->ctx.intra_subpart_model[0]), 0, bits, "intra_subPartitions");
|
||||
// }
|
||||
// else {
|
||||
// CABAC_FBITS_UPDATE(cabac, &(cabac->ctx.intra_subpart_model[0]), 1, bits, "intra_subPartitions");
|
||||
// // ToDo: complete this if-clause
|
||||
// if (isp_mode == 3) {
|
||||
// CABAC_FBITS_UPDATE(cabac, &(cabac->ctx.intra_subpart_model[0]), allow_isp - 1, bits, "intra_subPart_ver_hor");
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
|
||||
const int cu_width = LCU_WIDTH >> depth;
|
||||
// PREDINFO CODING
|
||||
// If intra prediction mode is found from the predictors,
|
||||
|
|
92
src/intra.c
92
src/intra.c
|
@ -1471,6 +1471,41 @@ const cu_info_t* uvg_get_co_located_luma_cu(
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Returns ISP split partition size based on block dimensions and split type.
|
||||
*
|
||||
* Returns ISP split partition size based on block dimensions and split type.
|
||||
* Will fail if resulting partition size has less than 16 samples.
|
||||
*
|
||||
* \param width Block width.
|
||||
* \param height Block height.
|
||||
* \param split_type Horizontal or vertical split.
|
||||
*/
|
||||
static int get_isp_split_dim(const int width, const int height, const int split_type)
|
||||
{
|
||||
bool divide_in_rows = split_type == SPLIT_TYPE_HOR;
|
||||
int split_dim_size, non_split_dim_size, partition_size, div_shift = 2;
|
||||
|
||||
if (divide_in_rows) {
|
||||
split_dim_size = height;
|
||||
non_split_dim_size = width;
|
||||
}
|
||||
else {
|
||||
split_dim_size = width;
|
||||
non_split_dim_size = height;
|
||||
}
|
||||
|
||||
// ISP_TODO: make a define for this. Depends on minimum transform block log2 side length
|
||||
const int min_num_samples = 16; // Minimum allowed number of samples for split block
|
||||
const int factor_to_min_samples = non_split_dim_size < min_num_samples ? min_num_samples >> uvg_math_floor_log2(non_split_dim_size) : 1;
|
||||
partition_size = (split_dim_size >> div_shift) < factor_to_min_samples ? factor_to_min_samples : (split_dim_size >> div_shift);
|
||||
|
||||
assert((uvg_math_floor_log2(partition_size) + uvg_math_floor_log2(non_split_dim_size) < uvg_math_floor_log2(min_num_samples)) &&
|
||||
"Partition has less than allowed minimum number of samples.");
|
||||
return partition_size;
|
||||
}
|
||||
|
||||
|
||||
static void intra_recon_tb_leaf(
|
||||
encoder_state_t* const state,
|
||||
const cu_loc_t* cu_loc,
|
||||
|
@ -1631,7 +1666,7 @@ void uvg_intra_recon_cu(
|
|||
// ISP split is done horizontally or vertically depending on ISP mode, 2 or 4 times depending on block dimensions.
|
||||
// Small blocks are split only twice.
|
||||
int split_type = search_data->pred_cu.intra.isp_mode;
|
||||
int part_dim = uvg_get_isp_split_dim(width, height, split_type);
|
||||
int part_dim = get_isp_split_dim(width, height, split_type);
|
||||
int limit = split_type == ISP_MODE_HOR ? height : width;
|
||||
for (int part = 0; part < limit; part + part_dim) {
|
||||
const int part_x = split_type == ISP_MODE_HOR ? x : x + part;
|
||||
|
@ -1668,3 +1703,58 @@ void uvg_intra_recon_cu(
|
|||
&loc, depth, cur_cu, lcu,
|
||||
false, tree_type);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Check if ISP can be used for block size.
|
||||
*
|
||||
* \return True if isp can be used.
|
||||
* \param width Block width.
|
||||
* \param height Block height.
|
||||
* \param max_tr_size Maximum supported transform block size (64).
|
||||
*/
|
||||
bool uvg_can_use_isp(const int width, const int height, const int max_tr_size)
|
||||
{
|
||||
assert(!(width > LCU_WIDTH || height > LCU_WIDTH) && "Block size larger than max LCU size.");
|
||||
assert(!(width < TR_MIN_WIDTH || height < TR_MIN_WIDTH) && "Block size smaller than min TR_WIDTH.");
|
||||
|
||||
const int log2_width = uvg_g_convert_to_log2[width];
|
||||
const int log2_height = uvg_g_convert_to_log2[height];
|
||||
|
||||
// Each split block must have at least 16 samples.
|
||||
bool not_enough_samples = (log2_width + log2_height <= 4);
|
||||
bool cu_size_larger_than_max_tr_size = width > max_tr_size || height > max_tr_size;
|
||||
if (not_enough_samples || cu_size_larger_than_max_tr_size) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Check if given ISP mode can be used with LFNST.
|
||||
*
|
||||
* \return True if isp can be used.
|
||||
* \param width Block width.
|
||||
* \param height Block height.
|
||||
* \param isp_mode ISP mode.
|
||||
* \param tree_type Tree type. Dual, luma or chroma tree.
|
||||
*/
|
||||
bool uvg_can_use_isp_with_lfnst(const int width, const int height, const int isp_split_type, const enum uvg_tree_type tree_type)
|
||||
{
|
||||
if (tree_type == UVG_CHROMA_T) {
|
||||
return false;
|
||||
}
|
||||
if (isp_split_type == ISP_MODE_NO_ISP) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const int tu_width = (isp_split_type == ISP_MODE_HOR) ? width : get_isp_split_dim(width, height, SPLIT_TYPE_VER);
|
||||
const int tu_height = (isp_split_type == ISP_MODE_HOR) ? get_isp_split_dim(width, height, SPLIT_TYPE_HOR) : height;
|
||||
|
||||
if (!(tu_width >= TR_MIN_WIDTH && tu_height >= TR_MIN_WIDTH))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
11
src/intra.h
11
src/intra.h
|
@ -159,3 +159,14 @@ const cu_info_t* uvg_get_co_located_luma_cu(
|
|||
enum uvg_tree_type tree_type);
|
||||
|
||||
int uvg_get_mip_flag_context(int x, int y, int width, int height, const lcu_t* lcu, cu_array_t* const cu_a);
|
||||
|
||||
// ISP related defines
|
||||
#define NUM_ISP_MODES 3
|
||||
#define ISP_MODE_NO_ISP 0
|
||||
#define ISP_MODE_HOR 1
|
||||
#define ISP_MODE_VER 2
|
||||
#define SPLIT_TYPE_HOR 1
|
||||
#define SPLIT_TYPE_VER 2
|
||||
|
||||
bool uvg_can_use_isp(const int width, const int height, const int max_tr_size);
|
||||
bool uvg_can_use_isp_with_lfnst(const int width, const int height, const int isp_mode, const enum uvg_tree_type tree_type);
|
||||
|
|
|
@ -77,14 +77,6 @@ typedef struct unit_stats_map_t {
|
|||
#define NUM_MIP_MODES_FULL(width, height) (((width) == 4 && (height) == 4) ? 32 : ((width) == 4 || (height) == 4 || ((width) == 8 && (height) == 8) ? 16 : 12))
|
||||
#define NUM_MIP_MODES_HALF(width, height) (NUM_MIP_MODES_FULL((width), (height)) >> 1)
|
||||
|
||||
// ISP related defines
|
||||
#define NUM_ISP_MODES 3
|
||||
#define ISP_MODE_NO_ISP 0
|
||||
#define ISP_MODE_HOR 1
|
||||
#define ISP_MODE_VER 2
|
||||
#define SPLIT_TYPE_HOR 1
|
||||
#define SPLIT_TYPE_VER 2
|
||||
|
||||
void uvg_sort_modes(int8_t *__restrict modes, double *__restrict costs, uint8_t length);
|
||||
void uvg_sort_modes_intra_luma(int8_t *__restrict modes, int8_t *__restrict trafo, double *__restrict costs, uint8_t length);
|
||||
|
||||
|
|
|
@ -257,77 +257,6 @@ static void derive_mts_constraints(cu_info_t *const pred_cu,
|
|||
}
|
||||
|
||||
|
||||
// ISP_TODO: move this function if it is used elsewhere
|
||||
static INLINE bool can_use_isp(const int width, const int height, const int max_tr_size)
|
||||
{
|
||||
assert(!(width > LCU_WIDTH || height > LCU_WIDTH) && "Block size larger than max LCU size.");
|
||||
assert(!(width < TR_MIN_WIDTH || height < TR_MIN_WIDTH) && "Block size smaller than min TR_WIDTH.");
|
||||
|
||||
const int log2_width = uvg_g_convert_to_log2[width];
|
||||
const int log2_height = uvg_g_convert_to_log2[height];
|
||||
|
||||
// Each split block must have at least 16 samples.
|
||||
bool not_enough_samples = (log2_width + log2_height <= 4);
|
||||
bool cu_size_larger_than_max_tr_size = width > max_tr_size || height > max_tr_size;
|
||||
if (not_enough_samples || cu_size_larger_than_max_tr_size) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Returns ISP split partition size based on block dimensions and split type.
|
||||
*
|
||||
* Returns ISP split partition size based on block dimensions and split type.
|
||||
* Will fail if resulting partition size has less than 16 samples.
|
||||
*
|
||||
* \param width Block width.
|
||||
* \param height Block height.
|
||||
* \param split_type Horizontal or vertical split.
|
||||
*/
|
||||
int uvg_get_isp_split_dim(const int width, const int height, const int split_type)
|
||||
{
|
||||
bool divide_in_rows = split_type == SPLIT_TYPE_HOR;
|
||||
int split_dim_size, non_split_dim_size, partition_size, div_shift = 2;
|
||||
|
||||
if (divide_in_rows) {
|
||||
split_dim_size = height;
|
||||
non_split_dim_size = width;
|
||||
}
|
||||
else {
|
||||
split_dim_size = width;
|
||||
non_split_dim_size = height;
|
||||
}
|
||||
|
||||
// ISP_TODO: make a define for this. Depends on minimum transform block log2 side length
|
||||
const int min_num_samples = 16; // Minimum allowed number of samples for split block
|
||||
const int factor_to_min_samples = non_split_dim_size < min_num_samples ? min_num_samples >> uvg_math_floor_log2(non_split_dim_size) : 1;
|
||||
partition_size = (split_dim_size >> div_shift) < factor_to_min_samples ? factor_to_min_samples : (split_dim_size >> div_shift);
|
||||
|
||||
assert((uvg_math_floor_log2(partition_size) + uvg_math_floor_log2(non_split_dim_size) < uvg_math_floor_log2(min_num_samples)) &&
|
||||
"Partition has less than allowed minimum number of samples.");
|
||||
return partition_size;
|
||||
}
|
||||
|
||||
|
||||
// ISP_TODO: move this function if it is used elsewhere
|
||||
static INLINE bool can_use_isp_with_lfnst(const int width, const int height, const int isp_mode)
|
||||
{
|
||||
if (isp_mode == ISP_MODE_NO_ISP) {
|
||||
return false;
|
||||
}
|
||||
const int tu_width = isp_mode == ISP_MODE_HOR ? width : uvg_get_isp_split_dim(width, height, SPLIT_TYPE_VER);
|
||||
const int tu_height = isp_mode == ISP_MODE_HOR ? uvg_get_isp_split_dim(width, height, SPLIT_TYPE_HOR) : height;
|
||||
const int min_tb_size = TR_MIN_WIDTH;
|
||||
|
||||
if (!(tu_width >= min_tb_size && tu_height >= min_tb_size)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Perform search for best intra transform split configuration.
|
||||
*
|
||||
|
@ -445,7 +374,7 @@ static double search_intra_trdepth(
|
|||
|
||||
if (pred_cu->lfnst_idx != 0) {
|
||||
// Cannot use ISP with LFNST for small blocks
|
||||
pred_cu->intra.isp_mode = can_use_isp_with_lfnst(width, height, pred_cu->intra.isp_mode) ? pred_cu->intra.isp_mode : ISP_MODE_NO_ISP;
|
||||
pred_cu->intra.isp_mode = uvg_can_use_isp_with_lfnst(width, height, pred_cu->intra.isp_mode, tree_type) ? pred_cu->intra.isp_mode : ISP_MODE_NO_ISP;
|
||||
}
|
||||
|
||||
for (trafo = mts_start; trafo < num_transforms; trafo++) {
|
||||
|
@ -1465,7 +1394,7 @@ static int8_t search_intra_rdo(
|
|||
for (int mode = 0; mode < modes_to_check; mode++) {
|
||||
bool can_do_isp_search = search_data[mode].pred_cu.intra.mip_flag ? false: true; // Cannot use ISP with MIP
|
||||
can_do_isp_search = search_data[mode].pred_cu.intra.multi_ref_idx == 0 ? can_do_isp_search : false; // Cannot use ISP with MRL
|
||||
int max_isp_modes = can_do_isp_search && can_use_isp(width, height, 64 /*MAX_TR_SIZE*/) && state->encoder_control->cfg.isp ? NUM_ISP_MODES : 1;
|
||||
int max_isp_modes = can_do_isp_search && uvg_can_use_isp(width, height, 64 /*MAX_TR_SIZE*/) && state->encoder_control->cfg.isp ? NUM_ISP_MODES : 1;
|
||||
|
||||
for (int isp_mode = 0; isp_mode < max_isp_modes; ++isp_mode) {
|
||||
search_data[mode].pred_cu.intra.isp_mode = isp_mode;
|
||||
|
|
Loading…
Reference in a new issue