2016-08-09 13:01:51 +00:00
/*****************************************************************************
2021-11-23 06:46:06 +00:00
* This file is part of uvg266 VVC encoder .
2016-08-09 13:01:51 +00:00
*
2021-10-07 08:32:59 +00:00
* Copyright ( c ) 2021 , Tampere University , ITU / ISO / IEC , project contributors
* All rights reserved .
*
* Redistribution and use in source and binary forms , with or without modification ,
* are permitted provided that the following conditions are met :
*
* * Redistributions of source code must retain the above copyright notice , this
* list of conditions and the following disclaimer .
*
* * Redistributions in binary form must reproduce the above copyright notice , this
* list of conditions and the following disclaimer in the documentation and / or
* other materials provided with the distribution .
*
* * Neither the name of the Tampere University or ITU / ISO / IEC nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission .
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS " AS IS " AND
* ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED . IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT , INDIRECT , INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES
* INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ;
* LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
* SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
* INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
2016-08-09 13:01:51 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# include "encode_coding_tree.h"
# include "cabac.h"
# include "context.h"
# include "cu.h"
2021-11-30 20:07:01 +00:00
# include "debug.h"
2016-08-09 13:01:51 +00:00
# include "encoder.h"
2020-09-29 11:46:27 +00:00
# include "global.h"
2016-08-09 13:01:51 +00:00
# include "imagelist.h"
# include "inter.h"
# include "intra.h"
2022-04-28 11:26:05 +00:00
# include "uvg266.h"
2022-04-28 11:18:09 +00:00
# include "uvg_math.h"
2018-11-29 14:52:06 +00:00
# include "strategyselector.h"
2016-08-09 13:01:51 +00:00
# include "tables.h"
# include "videoframe.h"
2022-09-08 12:10:54 +00:00
bool uvg_is_mts_allowed ( const encoder_state_t * const state , cu_info_t * const pred_cu , const cu_loc_t *
const cu_loc )
2021-01-18 18:44:36 +00:00
{
2022-05-13 12:04:03 +00:00
uint32_t ts_max_size = 1 < < state - > encoder_control - > cfg . trskip_max_size ;
2022-06-17 08:27:19 +00:00
const uint32_t max_size = 32 ; // CU::isIntra(cu) ? MTS_INTRA_MAX_CU_SIZE : MTS_INTER_MAX_CU_SIZE;
2022-09-08 12:10:54 +00:00
const uint32_t cu_width = cu_loc - > width ;
const uint32_t cu_height = cu_loc - > height ;
2021-01-18 18:44:36 +00:00
//bool mts_allowed = cu.chType == CHANNEL_TYPE_LUMA && compID == COMPONENT_Y;
uint8_t mts_type = state - > encoder_control - > cfg . mts ;
2022-04-28 11:18:09 +00:00
bool mts_allowed = mts_type = = UVG_MTS_BOTH | | ( pred_cu - > type = = CU_INTRA ? mts_type = = UVG_MTS_INTRA : pred_cu - > type = = CU_INTER & & mts_type = = UVG_MTS_INTER ) ;
2021-01-18 18:44:36 +00:00
mts_allowed & = cu_width < = max_size & & cu_height < = max_size ;
2022-08-19 12:05:22 +00:00
mts_allowed & = pred_cu - > type = = CU_INTRA ? ! pred_cu - > intra . isp_mode : true ;
2021-01-18 18:44:36 +00:00
//mts_allowed &= !cu.sbtInfo;
mts_allowed & = ! ( pred_cu - > bdpcmMode & & cu_width < = ts_max_size & & cu_height < = ts_max_size ) ;
2022-06-13 11:48:09 +00:00
mts_allowed & = pred_cu - > tr_idx ! = MTS_SKIP & & ! pred_cu - > violates_mts_coeff_constraint & & pred_cu - > mts_last_scan_pos ;
mts_allowed & = pred_cu - > lfnst_idx = = 0 ;
2021-01-18 18:44:36 +00:00
return mts_allowed ;
}
2022-09-08 12:10:54 +00:00
static void encode_mts_idx (
encoder_state_t * const state ,
2021-01-18 18:44:36 +00:00
cabac_data_t * const cabac ,
2022-09-08 12:10:54 +00:00
const cu_info_t * const pred_cu ,
const cu_loc_t * const cu_loc )
2021-01-18 18:44:36 +00:00
{
//TransformUnit &tu = *cu.firstTU;
2021-02-02 09:09:43 +00:00
int mts_idx = pred_cu - > tr_idx ;
2021-01-18 18:44:36 +00:00
2022-09-08 12:10:54 +00:00
if ( uvg_is_mts_allowed ( state , ( cu_info_t * const ) pred_cu , cu_loc ) & & mts_idx ! = MTS_SKIP
2021-01-18 18:44:36 +00:00
& & ! pred_cu - > violates_mts_coeff_constraint
2022-06-13 11:48:09 +00:00
& & pred_cu - > mts_last_scan_pos
2021-01-18 18:44:36 +00:00
)
{
int symbol = mts_idx ! = MTS_DCT2_DCT2 ? 1 : 0 ;
int ctx_idx = 0 ;
cabac - > cur_ctx = & ( cabac - > ctx . mts_idx_model [ ctx_idx ] ) ;
CABAC_BIN ( cabac , symbol , " mts_idx " ) ;
if ( symbol )
{
ctx_idx = 1 ;
for ( int i = 0 ; i < 3 ; i + + , ctx_idx + + )
{
symbol = mts_idx > i + MTS_DST7_DST7 ? 1 : 0 ;
cabac - > cur_ctx = & ( cabac - > ctx . mts_idx_model [ ctx_idx ] ) ;
CABAC_BIN ( cabac , symbol , " mts_idx " ) ;
if ( ! symbol )
{
break ;
}
}
}
}
}
2022-03-16 10:52:18 +00:00
2022-08-17 12:23:35 +00:00
bool uvg_is_lfnst_allowed (
2022-06-28 12:30:28 +00:00
const encoder_state_t * const state ,
2022-06-13 11:48:09 +00:00
const cu_info_t * const pred_cu ,
2022-06-28 10:45:51 +00:00
enum uvg_tree_type tree_type ,
2022-07-07 14:04:16 +00:00
const color_t color ,
2022-12-06 09:23:30 +00:00
const cu_loc_t * const cu_loc , const lcu_t * const lcu )
2022-03-16 10:52:18 +00:00
{
2022-09-13 11:38:19 +00:00
if ( state - > encoder_control - > cfg . lfnst & & pred_cu - > type = = CU_INTRA & & PU_IS_TU ( pred_cu ) ) {
2022-08-17 12:23:35 +00:00
const int isp_mode = pred_cu - > intra . isp_mode ;
2022-09-13 11:38:19 +00:00
const int cu_width = tree_type ! = UVG_CHROMA_T ? cu_loc - > width : cu_loc - > chroma_width ;
const int cu_height = tree_type ! = UVG_CHROMA_T ? cu_loc - > height : cu_loc - > chroma_height ;
bool can_use_lfnst_with_mip = ( cu_width > = 16 & & cu_height > = 16 ) ;
bool is_sep_tree = tree_type ! = UVG_BOTH_T ;
2022-06-29 12:09:34 +00:00
bool mip_flag = pred_cu - > type = = CU_INTRA & & color = = COLOR_Y ? pred_cu - > intra . mip_flag : false ;
2022-03-29 11:06:39 +00:00
2022-12-06 09:23:30 +00:00
if ( ( isp_mode & & ! uvg_can_use_isp_with_lfnst ( cu_width , cu_height , isp_mode , tree_type ) & & color = = COLOR_Y ) | |
( pred_cu - > type = = CU_INTRA & & mip_flag & & ! can_use_lfnst_with_mip & & color = = COLOR_Y ) | |
2022-06-23 11:58:40 +00:00
( is_sep_tree & & MIN ( cu_width , cu_height ) < 4 ) | |
2022-11-30 11:26:48 +00:00
( cu_width > ( TR_MAX_WIDTH > > ( tree_type = = UVG_CHROMA_T ) ) | | cu_height > ( TR_MAX_WIDTH > > ( tree_type = = UVG_CHROMA_T ) ) ) ) {
2022-03-29 11:06:39 +00:00
return false ;
}
2022-09-13 11:38:19 +00:00
bool luma_flag = tree_type ! = UVG_CHROMA_T ;
bool chroma_flag = tree_type ! = UVG_LUMA_T ;
2022-12-06 09:23:30 +00:00
bool non_zero_coeff_non_ts_corner_8x8 = false ;
bool last_scan_pos = false ;
2022-03-29 11:06:39 +00:00
bool is_tr_skip = false ;
2022-09-23 12:41:50 +00:00
2022-12-06 09:23:30 +00:00
int split_num = color = = COLOR_Y & & isp_mode ? uvg_get_isp_split_num ( cu_width , cu_height , isp_mode , false ) : 0 ;
const videoframe_t * const frame = state - > tile - > frame ;
if ( split_num ) {
// Constraints for ISP split blocks
for ( int i = 0 ; i < split_num ; + + i ) {
cu_loc_t split_loc ;
uvg_get_isp_split_loc ( & split_loc , cu_loc - > x , cu_loc - > y , cu_width , cu_height , i , isp_mode , false ) ;
int local_split_x = split_loc . x ;
int local_split_y = split_loc . y ;
uvg_get_isp_cu_arr_coords ( & local_split_x , & local_split_y ) ;
const cu_info_t * split_cu = lcu ? LCU_GET_CU_AT_PX ( lcu , local_split_x , local_split_y ) :
uvg_cu_array_at_const ( frame - > cu_array , local_split_x , local_split_y ) ;
//if (cbf_is_set(split_cu->cbf, depth, COLOR_Y)) {
// ISP_TODO: remove this if clause altogether if it seems it is not needed
if ( true ) {
non_zero_coeff_non_ts_corner_8x8 | = ( luma_flag & & split_cu - > violates_lfnst_constrained_luma ) | | ( chroma_flag & & split_cu - > violates_lfnst_constrained_chroma ) ;
//last_scan_pos |= split_cu->lfnst_last_scan_pos;
last_scan_pos | = true ;
}
}
}
else {
non_zero_coeff_non_ts_corner_8x8 | = ( luma_flag & & pred_cu - > violates_lfnst_constrained_luma ) | | ( chroma_flag & & pred_cu - > violates_lfnst_constrained_chroma ) ;
last_scan_pos | = pred_cu - > lfnst_last_scan_pos ;
}
2022-09-13 11:38:19 +00:00
if ( color = = COLOR_Y & & pred_cu - > tr_idx = = MTS_SKIP ) {
is_tr_skip = true ;
2022-03-29 11:06:39 +00:00
}
2022-06-13 11:48:09 +00:00
2022-12-06 09:23:30 +00:00
if ( ( ! last_scan_pos ) | | non_zero_coeff_non_ts_corner_8x8 | | is_tr_skip ) {
2022-04-19 15:16:32 +00:00
return false ;
2022-03-16 10:52:18 +00:00
}
2022-06-13 11:48:09 +00:00
return true ;
}
else {
return false ;
}
}
static bool encode_lfnst_idx (
const encoder_state_t * const state ,
cabac_data_t * const cabac ,
const cu_info_t * const pred_cu ,
2022-06-28 10:45:51 +00:00
enum uvg_tree_type tree_type ,
2022-09-13 11:38:19 +00:00
const color_t color ,
const cu_loc_t * const cu_loc )
2022-06-13 11:48:09 +00:00
{
2022-12-06 09:23:30 +00:00
if ( uvg_is_lfnst_allowed ( state , pred_cu , tree_type , color , cu_loc , NULL ) ) {
2022-06-13 11:48:09 +00:00
// Getting separate tree bool from block size is a temporary fix until a proper dual tree check is possible (there is no dual tree structure at time of writing this).
// VTM seems to force explicit dual tree structure for small 4x4 blocks
2022-09-13 11:38:19 +00:00
bool is_separate_tree = tree_type ! = UVG_BOTH_T ;
2022-03-16 10:52:18 +00:00
2022-06-29 13:25:25 +00:00
const int lfnst_index = ! is_separate_tree | | color = = COLOR_Y ? pred_cu - > lfnst_idx : pred_cu - > cr_lfnst_idx ;
2022-04-10 11:49:29 +00:00
assert ( ( lfnst_index > = 0 & & lfnst_index < 3 ) & & " Invalid LFNST index. " ) ;
2022-03-16 10:52:18 +00:00
uint16_t ctx_idx = 0 ;
if ( is_separate_tree ) ctx_idx + + ;
cabac - > cur_ctx = & ( cabac - > ctx . lfnst_idx_model [ ctx_idx ] ) ;
CABAC_BIN ( cabac , lfnst_index ? 1 : 0 , " lfnst_idx " ) ;
if ( lfnst_index ) {
cabac - > cur_ctx = & ( cabac - > ctx . lfnst_idx_model [ 2 ] ) ;
CABAC_BIN ( cabac , ( lfnst_index - 1 ) ? 1 : 0 , " lfnst_idx " ) ;
}
2022-04-19 15:16:32 +00:00
return true ;
}
else {
2022-11-24 07:47:36 +00:00
if ( color = = COLOR_Y ) {
2022-09-26 11:44:51 +00:00
assert ( pred_cu - > lfnst_idx = = 0 ) ;
}
2022-11-24 07:47:36 +00:00
if ( tree_type = = UVG_CHROMA_T & & color ! = COLOR_Y ) {
2022-09-26 11:44:51 +00:00
assert ( pred_cu - > cr_lfnst_idx = = 0 ) ;
}
2022-04-19 15:16:32 +00:00
return false ;
2022-03-16 10:52:18 +00:00
}
}
2022-04-28 11:18:09 +00:00
void uvg_encode_ts_residual ( encoder_state_t * const state ,
2021-04-27 11:13:44 +00:00
cabac_data_t * const cabac ,
const coeff_t * coeff ,
2021-06-07 10:06:03 +00:00
uint32_t width ,
2022-08-18 12:07:22 +00:00
uint32_t height ,
2021-04-27 11:13:44 +00:00
uint8_t type ,
2022-04-01 07:46:51 +00:00
int8_t scan_mode ,
2022-08-09 11:02:30 +00:00
double * bits_out )
{
2021-04-27 11:13:44 +00:00
//const encoder_control_t * const encoder = state->encoder_control;
//int c1 = 1;
2022-06-17 08:27:19 +00:00
uint32_t i ;
2021-04-27 11:13:44 +00:00
int32_t blk_pos ;
// ToDo: large block support in VVC?
uint32_t sig_coeffgroup_flag [ 32 * 32 ] = { 0 } ;
// CONSTANTS
2022-08-18 12:07:22 +00:00
const uint32_t log2_block_width = uvg_g_convert_to_log2 [ width ] ;
const uint32_t log2_block_height = uvg_g_convert_to_log2 [ height ] ;
// TODO: log2_cg_size is wrong if width != height
2022-08-10 16:35:15 +00:00
const uint32_t log2_cg_size = uvg_g_log2_sbb_size [ log2_block_width ] [ log2_block_width ] [ 0 ] + uvg_g_log2_sbb_size [ log2_block_width ] [ log2_block_width ] [ 1 ] ;
2022-08-18 12:37:18 +00:00
2022-08-19 12:05:22 +00:00
const uint32_t * const scan = uvg_get_scan_order_table ( SCAN_GROUP_4X4 , scan_mode , log2_block_width , log2_block_height ) ;
const uint32_t * const scan_cg = uvg_get_scan_order_table ( SCAN_GROUP_UNGROUPED , scan_mode , log2_block_width , log2_block_height ) ;
2022-08-09 11:02:30 +00:00
2022-04-01 07:46:51 +00:00
double bits = 0 ;
2021-04-27 11:13:44 +00:00
// Init base contexts according to block type
2021-12-03 15:17:06 +00:00
cabac_ctx_t * base_coeff_group_ctx = & ( cabac - > ctx . transform_skip_sig_coeff_group [ 0 ] ) ;
2021-04-27 11:13:44 +00:00
cabac - > cur_ctx = base_coeff_group_ctx ;
2022-08-18 12:07:22 +00:00
int maxCtxBins = ( width * height * 7 ) > > 2 ;
2021-07-27 06:23:29 +00:00
unsigned scan_cg_last = ( unsigned ) - 1 ;
2021-12-03 15:19:19 +00:00
//unsigned scan_pos_last = (unsigned )-1;
2021-04-27 11:13:44 +00:00
2022-08-18 12:07:22 +00:00
for ( i = 0 ; i < width * height ; i + + ) {
2021-04-27 11:13:44 +00:00
if ( coeff [ scan [ i ] ] ) {
sig_coeffgroup_flag [ scan_cg [ i > > log2_cg_size ] ] = 1 ;
}
}
2022-08-18 12:07:22 +00:00
// TODO: this won't work with non-square blocks
scan_cg_last = ( width * height - 1 ) > > log2_cg_size ;
2021-12-03 15:17:06 +00:00
const uint32_t cg_width = ( MIN ( ( uint8_t ) 32 , width ) > > ( log2_cg_size / 2 ) ) ;
bool no_sig_group_before_last = true ;
for ( i = 0 ; i < = scan_cg_last ; i + + ) {
if ( ! ( width = = 4 | | ( i = = scan_cg_last & & no_sig_group_before_last ) ) ) {
uint32_t cg_blkpos = scan_cg [ i ] ;
uint32_t cg_pos_y = cg_blkpos / cg_width ;
uint32_t cg_pos_x = cg_blkpos - ( cg_pos_y * cg_width ) ;
2022-04-28 11:18:09 +00:00
uint32_t ctx_sig = uvg_context_get_sig_coeff_group_ts ( sig_coeffgroup_flag , cg_pos_x , cg_pos_y , cg_width ) ;
2021-12-03 15:17:06 +00:00
cabac - > cur_ctx = & base_coeff_group_ctx [ ctx_sig ] ;
2021-04-27 11:13:44 +00:00
if ( ! sig_coeffgroup_flag [ scan_cg [ i ] ] ) {
2022-04-01 07:46:51 +00:00
CABAC_FBITS_UPDATE ( cabac , & base_coeff_group_ctx [ ctx_sig ] , 0 , bits , " ts_sigGroup " ) ;
2021-04-27 11:13:44 +00:00
continue ;
}
2022-04-01 07:46:51 +00:00
CABAC_FBITS_UPDATE ( cabac , & base_coeff_group_ctx [ ctx_sig ] , 1 , bits , " ts_sigGroup " ) ;
2021-12-03 15:17:06 +00:00
no_sig_group_before_last = false ;
2021-04-27 11:13:44 +00:00
}
int firstSigPos = i < < log2_cg_size ;
int min_sub_pos = firstSigPos + ( 1 < < log2_cg_size ) - 1 ;
int nextSigPos = firstSigPos ;
//===== encode absolute values =====
const int inferSigPos = min_sub_pos ;
int remAbsLevel = - 1 ;
int numNonZero = 0 ;
int rightPixel , belowPixel , modAbsCoeff ;
int lastScanPosPass1 = - 1 ;
int lastScanPosPass2 = - 1 ;
for ( ; nextSigPos < = min_sub_pos & & maxCtxBins > = 4 ; nextSigPos + + )
{
blk_pos = scan [ nextSigPos ] ;
int pos_x = blk_pos % width ;
int pos_y = blk_pos / width ;
coeff_t curr_coeff = coeff [ blk_pos ] ;
unsigned sigFlag = ( curr_coeff ! = 0 ) ;
if ( numNonZero | | nextSigPos ! = inferSigPos )
{
2022-04-01 07:46:51 +00:00
CABAC_FBITS_UPDATE ( cabac , & cabac - > ctx . transform_skip_sig [
2022-04-28 11:18:09 +00:00
uvg_context_get_sig_ctx_idx_abs_ts ( coeff , pos_x , pos_y , width )
2022-04-01 07:46:51 +00:00
] , sigFlag , bits , " sig_coeff_flag " ) ;
2021-04-27 11:13:44 +00:00
maxCtxBins - - ;
}
if ( sigFlag )
{
//===== encode sign's =====
int sign = curr_coeff < 0 ;
2022-05-18 06:34:31 +00:00
CABAC_FBITS_UPDATE ( cabac , & cabac - > ctx . transform_skip_res_sign [
2022-04-01 07:46:51 +00:00
uvg_sign_ctx_id_abs_ts ( coeff , pos_x , pos_y , width , 0 )
] , sign , bits , " coeff_sign_flag " ) ;
2021-04-27 11:13:44 +00:00
maxCtxBins - - ;
numNonZero + + ;
rightPixel = pos_x > 0 ? coeff [ pos_x + pos_y * width - 1 ] : 0 ;
belowPixel = pos_y > 0 ? coeff [ pos_x + ( pos_y - 1 ) * width ] : 0 ;
2022-04-28 11:18:09 +00:00
modAbsCoeff = uvg_derive_mod_coeff ( rightPixel , belowPixel , abs ( curr_coeff ) , 0 ) ;
2021-04-27 11:13:44 +00:00
remAbsLevel = modAbsCoeff - 1 ;
unsigned gt1 = ! ! remAbsLevel ;
2022-05-18 06:34:31 +00:00
CABAC_FBITS_UPDATE ( cabac , & cabac - > ctx . transform_skip_gt1 [
2022-04-28 11:18:09 +00:00
uvg_lrg1_ctx_id_abs_ts ( coeff , pos_x , pos_y , width , 0 )
2022-05-18 06:34:31 +00:00
] , gt1 , bits , " abs_level_gtx_flag " ) ;
2021-04-27 11:13:44 +00:00
maxCtxBins - - ;
if ( gt1 )
{
remAbsLevel - = 1 ;
2022-05-18 06:34:31 +00:00
CABAC_FBITS_UPDATE ( cabac , & cabac - > ctx . transform_skip_par , remAbsLevel & 1 , bits , " par_level_flag " ) ;
2021-04-27 11:13:44 +00:00
maxCtxBins - - ;
}
}
lastScanPosPass1 = nextSigPos ;
}
2022-06-17 08:27:19 +00:00
uint32_t cutoffVal = 2 ;
uint32_t numGtBins = 4 ;
2021-04-27 11:13:44 +00:00
for ( int scanPos = firstSigPos ; scanPos < = min_sub_pos & & maxCtxBins > = 4 ; scanPos + + )
{
blk_pos = scan [ scanPos ] ;
int pos_x = blk_pos % width ;
int pos_y = blk_pos / width ;
unsigned absLevel ;
rightPixel = pos_x > 0 ? coeff [ pos_x + pos_y * width - 1 ] : 0 ;
belowPixel = pos_y > 0 ? coeff [ pos_x + ( pos_y - 1 ) * width ] : 0 ;
2022-04-28 11:18:09 +00:00
absLevel = uvg_derive_mod_coeff ( rightPixel , belowPixel , abs ( coeff [ blk_pos ] ) , 0 ) ;
2021-04-27 11:13:44 +00:00
cutoffVal = 2 ;
2022-07-06 07:51:01 +00:00
for ( int j = 0 ; j < numGtBins ; j + + )
2021-04-27 11:13:44 +00:00
{
if ( absLevel > = cutoffVal )
{
unsigned gt2 = ( absLevel > = ( cutoffVal + 2 ) ) ;
2022-05-18 06:34:31 +00:00
CABAC_FBITS_UPDATE ( cabac , & cabac - > ctx . transform_skip_gt2 [ cutoffVal > > 1 ] , gt2 , bits , " abs_level_gtx_flag " ) ;
2021-04-27 11:13:44 +00:00
maxCtxBins - - ;
}
cutoffVal + = 2 ;
}
lastScanPosPass2 = scanPos ;
}
//===== coeff bypass ====
for ( int scanPos = firstSigPos ; scanPos < = min_sub_pos ; scanPos + + )
{
blk_pos = scan [ scanPos ] ;
int pos_x = blk_pos % width ;
int pos_y = blk_pos / width ;
unsigned absLevel ;
rightPixel = pos_x > 0 ? coeff [ pos_x + pos_y * width - 1 ] : 0 ;
belowPixel = pos_y > 0 ? coeff [ pos_x + ( pos_y - 1 ) * width ] : 0 ;
cutoffVal = ( scanPos < = lastScanPosPass2 ? 10 : ( scanPos < = lastScanPosPass1 ? 2 : 0 ) ) ;
2022-04-28 11:18:09 +00:00
absLevel = uvg_derive_mod_coeff ( rightPixel , belowPixel , abs ( coeff [ blk_pos ] ) , 0 | | ! cutoffVal ) ;
2021-04-27 11:13:44 +00:00
if ( absLevel > = cutoffVal )
{
int rice = 1 ;
unsigned rem = scanPos < = lastScanPosPass1 ? ( absLevel - cutoffVal ) > > 1 : absLevel ;
2022-04-01 07:46:51 +00:00
bits + = uvg_cabac_write_coeff_remain ( cabac , rem , rice , 5 ) ;
2021-04-27 11:13:44 +00:00
if ( absLevel & & scanPos > lastScanPosPass1 )
{
int sign = coeff [ blk_pos ] < 0 ;
CABAC_BIN_EP ( cabac , sign , " coeff_sign_flag " ) ;
2022-04-01 07:46:51 +00:00
bits + = 1 ;
2021-04-27 11:13:44 +00:00
}
}
}
}
2022-04-01 07:46:51 +00:00
if ( bits_out & & cabac - > only_count ) * bits_out + = bits ;
2021-04-27 11:13:44 +00:00
}
2016-08-09 13:01:51 +00:00
/**
* \ brief Encode ( X , Y ) position of the last significant coefficient
*
* \ param lastpos_x X component of last coefficient
* \ param lastpos_y Y component of last coefficient
* \ param width Block width
* \ param height Block height
* \ param type plane type / luminance or chrominance
2018-08-30 08:09:42 +00:00
* \ param scan scan type ( diag , hor , ver ) DEPRECATED ?
2016-08-09 13:01:51 +00:00
*
* This method encodes the X and Y component within a block of the last
* significant coefficient .
*/
2022-04-28 11:18:09 +00:00
void uvg_encode_last_significant_xy ( cabac_data_t * const cabac ,
2022-04-01 07:46:51 +00:00
uint8_t lastpos_x , uint8_t lastpos_y ,
uint8_t width , uint8_t height ,
uint8_t type , uint8_t scan , double * bits_out )
2016-08-09 13:01:51 +00:00
{
2022-04-28 11:18:09 +00:00
const int index_x = uvg_math_floor_log2 ( width ) ;
2022-08-31 09:28:57 +00:00
const int index_y = uvg_math_floor_log2 ( height ) ;
2019-05-07 12:01:02 +00:00
const int prefix_ctx [ 8 ] = { 0 , 0 , 0 , 3 , 6 , 10 , 15 , 21 } ;
2019-07-03 12:44:35 +00:00
//ToDo: own ctx_offset and shift for X and Y
2020-04-29 05:52:38 +00:00
uint8_t ctx_offset_x = type ? 0 : prefix_ctx [ index_x ] ;
uint8_t ctx_offset_y = type ? 0 : prefix_ctx [ index_y ] ;
2022-08-25 11:54:42 +00:00
uint8_t shift_x = type ? CLIP ( 0 , 2 , width > > 3 ) : ( index_x + 1 ) > > 2 ;
2022-08-31 09:28:57 +00:00
uint8_t shift_y = type ? CLIP ( 0 , 2 , height > > 3 ) : ( index_y + 1 ) > > 2 ;
2022-04-01 07:46:51 +00:00
double bits = 0 ;
2016-08-09 13:01:51 +00:00
cabac_ctx_t * base_ctx_x = ( type ? cabac - > ctx . cu_ctx_last_x_chroma : cabac - > ctx . cu_ctx_last_x_luma ) ;
cabac_ctx_t * base_ctx_y = ( type ? cabac - > ctx . cu_ctx_last_y_chroma : cabac - > ctx . cu_ctx_last_y_luma ) ;
2019-06-05 12:57:18 +00:00
const int group_idx_x = g_group_idx [ lastpos_x ] ;
const int group_idx_y = g_group_idx [ lastpos_y ] ;
2016-08-09 13:01:51 +00:00
// x prefix
2019-06-07 10:37:45 +00:00
int last_x = 0 ;
2022-04-01 07:46:51 +00:00
for ( ; last_x < group_idx_x ; last_x + + ) {
CABAC_FBITS_UPDATE ( cabac , & base_ctx_x [ ctx_offset_x + ( last_x > > shift_x ) ] , 1 , bits , " last_sig_coeff_x_prefix " ) ;
2016-08-09 13:01:51 +00:00
}
2019-06-07 10:37:45 +00:00
if ( group_idx_x < ( /*width == 32 ? g_group_idx[15] : */ g_group_idx [ MIN ( 32 , ( int32_t ) width ) - 1 ] ) ) {
2022-04-01 07:46:51 +00:00
CABAC_FBITS_UPDATE ( cabac , & base_ctx_x [ ctx_offset_x + ( last_x > > shift_x ) ] , 0 , bits , " last_sig_coeff_x_prefix " ) ;
2016-08-09 13:01:51 +00:00
}
// y prefix
2019-06-07 10:37:45 +00:00
int last_y = 0 ;
2022-04-01 07:46:51 +00:00
for ( ; last_y < group_idx_y ; last_y + + ) {
CABAC_FBITS_UPDATE ( cabac , & base_ctx_y [ ctx_offset_y + ( last_y > > shift_y ) ] , 1 , bits , " last_sig_coeff_y_prefix " ) ;
2016-08-09 13:01:51 +00:00
}
2019-06-07 10:37:45 +00:00
if ( group_idx_y < ( /* height == 32 ? g_group_idx[15] : */ g_group_idx [ MIN ( 32 , ( int32_t ) height ) - 1 ] ) ) {
2022-04-01 07:46:51 +00:00
CABAC_FBITS_UPDATE ( cabac , & base_ctx_y [ ctx_offset_y + ( last_y > > shift_y ) ] , 0 , bits , " last_sig_coeff_y_prefix " ) ;
2016-08-09 13:01:51 +00:00
}
// last_sig_coeff_x_suffix
if ( group_idx_x > 3 ) {
const int suffix = lastpos_x - g_min_in_group [ group_idx_x ] ;
2022-04-01 07:46:51 +00:00
const int write_bits = ( group_idx_x - 2 ) / 2 ;
CABAC_BINS_EP ( cabac , suffix , write_bits , " last_sig_coeff_x_suffix " ) ;
if ( cabac - > only_count ) bits + = write_bits ;
2016-08-09 13:01:51 +00:00
}
// last_sig_coeff_y_suffix
if ( group_idx_y > 3 ) {
const int suffix = lastpos_y - g_min_in_group [ group_idx_y ] ;
2022-04-01 07:46:51 +00:00
const int write_bits = ( group_idx_y - 2 ) / 2 ;
CABAC_BINS_EP ( cabac , suffix , write_bits , " last_sig_coeff_y_suffix " ) ;
if ( cabac - > only_count ) bits + = write_bits ;
2016-08-09 13:01:51 +00:00
}
2022-04-01 07:46:51 +00:00
if ( cabac - > only_count & & bits_out ) * bits_out + = bits ;
2016-08-09 13:01:51 +00:00
}
2022-06-08 10:22:29 +00:00
static void encode_chroma_tu (
encoder_state_t * const state ,
2022-09-08 12:10:54 +00:00
const cu_loc_t * const cu_loc ,
2022-06-28 13:02:22 +00:00
cu_info_t * cur_pu ,
2022-06-08 10:22:29 +00:00
int8_t * scan_idx ,
lcu_coeff_t * coeff ,
uint8_t joint_chroma ,
enum
2022-06-21 09:39:12 +00:00
uvg_tree_type tree_type )
2022-06-08 10:22:29 +00:00
{
2022-08-24 13:15:03 +00:00
int width_c = cu_loc - > chroma_width ;
2022-09-15 12:13:48 +00:00
int height_c = cu_loc - > chroma_height ;
2022-11-24 13:04:57 +00:00
int x_local = ( cu_loc - > x > > ( tree_type ! = UVG_CHROMA_T ) ) % LCU_WIDTH_C ;
int y_local = ( cu_loc - > y > > ( tree_type ! = UVG_CHROMA_T ) ) % LCU_WIDTH_C ;
2021-04-27 11:13:44 +00:00
cabac_data_t * const cabac = & state - > cabac ;
2022-09-15 12:13:48 +00:00
* scan_idx = SCAN_DIAG ;
2021-08-13 12:37:23 +00:00
if ( ! joint_chroma ) {
2022-08-25 11:54:42 +00:00
// const coeff_t *coeff_u = &coeff->u[xy_to_zorder(LCU_WIDTH_C, x_local, y_local)];
// const coeff_t *coeff_v = &coeff->v[xy_to_zorder(LCU_WIDTH_C, x_local, y_local)];
coeff_t coeff_u [ TR_MAX_WIDTH * TR_MAX_WIDTH ] ;
coeff_t coeff_v [ TR_MAX_WIDTH * TR_MAX_WIDTH ] ;
uvg_get_sub_coeff ( coeff_u , coeff - > u , x_local , y_local , cu_loc - > chroma_width , cu_loc - > chroma_height , LCU_WIDTH_C ) ;
uvg_get_sub_coeff ( coeff_v , coeff - > v , x_local , y_local , cu_loc - > chroma_width , cu_loc - > chroma_height , LCU_WIDTH_C ) ;
2021-08-13 12:37:23 +00:00
2022-09-14 08:47:26 +00:00
if ( cbf_is_set ( cur_pu - > cbf , COLOR_U ) ) {
2022-09-15 12:13:48 +00:00
if ( state - > encoder_control - > cfg . trskip_enable
& & width_c < = ( 1 < < state - > encoder_control - > cfg . trskip_max_size )
& & height_c < = ( 1 < < state - > encoder_control - > cfg . trskip_max_size ) ) {
2021-08-13 12:37:23 +00:00
cabac - > cur_ctx = & cabac - > ctx . transform_skip_model_chroma ;
// HEVC only supports transform_skip for Luma
// TODO: transform skip for chroma blocks
2022-05-25 10:47:02 +00:00
CABAC_BIN ( cabac , ( cur_pu - > tr_skip > > COLOR_U ) & 1 , " transform_skip_flag " ) ;
2021-08-13 12:37:23 +00:00
}
2022-08-24 13:15:03 +00:00
uvg_encode_coeff_nxn ( state , & state - > cabac , coeff_u , cu_loc , COLOR_U , * scan_idx , cur_pu , NULL ) ;
2021-08-13 12:37:23 +00:00
}
2021-04-14 11:19:31 +00:00
2022-09-14 08:47:26 +00:00
if ( cbf_is_set ( cur_pu - > cbf , COLOR_V ) ) {
2022-09-15 12:13:48 +00:00
if ( state - > encoder_control - > cfg . trskip_enable
& & width_c < = ( 1 < < state - > encoder_control - > cfg . trskip_max_size )
& & height_c < = ( 1 < < state - > encoder_control - > cfg . trskip_max_size ) ) {
2021-08-13 12:37:23 +00:00
cabac - > cur_ctx = & cabac - > ctx . transform_skip_model_chroma ;
2022-05-25 10:47:02 +00:00
CABAC_BIN ( cabac , ( cur_pu - > tr_skip > > COLOR_V ) & 1 , " transform_skip_flag " ) ;
2021-08-13 12:37:23 +00:00
}
2022-08-24 13:15:03 +00:00
uvg_encode_coeff_nxn ( state , & state - > cabac , coeff_v , cu_loc , COLOR_V , * scan_idx , cur_pu , NULL ) ;
2021-04-27 11:13:44 +00:00
}
2021-04-14 11:19:31 +00:00
}
2021-08-13 12:37:23 +00:00
else {
2022-09-08 12:10:54 +00:00
coeff_t coeff_uv [ TR_MAX_WIDTH * TR_MAX_WIDTH ] ;
2022-08-25 11:54:42 +00:00
uvg_get_sub_coeff ( coeff_uv , coeff - > joint_uv , x_local , y_local , cu_loc - > chroma_width , cu_loc - > chroma_height , LCU_WIDTH_C ) ;
2022-09-15 12:13:48 +00:00
if ( state - > encoder_control - > cfg . trskip_enable
& & width_c < = ( 1 < < state - > encoder_control - > cfg . trskip_max_size )
& & height_c < = ( 1 < < state - > encoder_control - > cfg . trskip_max_size ) ) {
2021-04-27 11:13:44 +00:00
cabac - > cur_ctx = & cabac - > ctx . transform_skip_model_chroma ;
2021-04-29 10:47:31 +00:00
CABAC_BIN ( cabac , 0 , " transform_skip_flag " ) ;
2021-04-27 11:13:44 +00:00
}
2022-08-24 13:15:03 +00:00
uvg_encode_coeff_nxn ( state , & state - > cabac , coeff_uv , cu_loc , COLOR_V , * scan_idx , cur_pu , NULL ) ;
2021-08-13 12:37:23 +00:00
2021-04-14 11:19:31 +00:00
}
}
2022-06-08 07:26:56 +00:00
static void encode_transform_unit (
encoder_state_t * const state ,
2022-08-21 09:46:07 +00:00
const cu_loc_t * cu_loc ,
2022-11-24 07:04:42 +00:00
const cu_info_t * cur_pu ,
2022-06-08 07:26:56 +00:00
lcu_coeff_t * coeff ,
2022-11-24 07:04:42 +00:00
bool only_chroma ,
2022-08-17 13:42:22 +00:00
enum uvg_tree_type tree_type ,
2022-08-31 11:54:30 +00:00
bool last_split ,
2022-11-25 11:50:22 +00:00
const cu_loc_t * original_loc ,
const cu_loc_t * const chroma_loc ) // Original cu dimensions, before CU split
2016-08-09 13:01:51 +00:00
{
const videoframe_t * const frame = state - > tile - > frame ;
2021-04-27 11:13:44 +00:00
cabac_data_t * const cabac = & state - > cabac ;
2022-08-21 09:46:07 +00:00
const int x = cu_loc - > x ;
const int y = cu_loc - > y ;
const uint8_t width = cu_loc - > width ;
const uint8_t height = cu_loc - > height ;
const uint8_t width_c = cu_loc - > chroma_width ;
const uint8_t height_c = cu_loc - > chroma_height ;
2016-08-09 13:01:51 +00:00
2022-06-21 09:39:12 +00:00
cu_array_t * used_cu_array = tree_type ! = UVG_CHROMA_T ? frame - > cu_array : frame - > chroma_cu_array ;
2022-09-16 08:10:26 +00:00
int isp_x = x ;
int isp_y = y ;
uvg_get_isp_cu_arr_coords ( & isp_x , & isp_y ) ;
2022-11-24 07:04:42 +00:00
if ( cur_pu = = NULL ) {
cur_pu = uvg_cu_array_at_const ( used_cu_array , isp_x , isp_y ) ;
}
2016-08-09 13:01:51 +00:00
2022-09-15 12:13:48 +00:00
int8_t scan_idx = SCAN_DIAG ;
2016-08-09 13:01:51 +00:00
2022-09-14 08:47:26 +00:00
int cbf_y = cbf_is_set ( cur_pu - > cbf , COLOR_Y ) ;
2016-08-09 13:01:51 +00:00
2021-04-14 11:19:31 +00:00
if ( cbf_y & & ! only_chroma ) {
2017-05-23 10:31:30 +00:00
int x_local = x % LCU_WIDTH ;
int y_local = y % LCU_WIDTH ;
2022-08-25 11:54:42 +00:00
// const coeff_t *coeff_y = &coeff->y[xy_to_zorder(LCU_WIDTH, x_local, y_local)];
coeff_t coeff_y [ TR_MAX_WIDTH * TR_MAX_WIDTH ] ;
uvg_get_sub_coeff ( coeff_y , coeff - > y , x_local , y_local , width , height , LCU_WIDTH ) ;
2016-08-09 13:01:51 +00:00
2017-05-12 13:03:23 +00:00
// CoeffNxN
// Residual Coding
2021-01-18 18:44:36 +00:00
2022-11-24 07:04:42 +00:00
if ( state - > encoder_control - > cfg . trskip_enable
& & width < = ( 1 < < state - > encoder_control - > cfg . trskip_max_size )
& & height < = ( 1 < < state - > encoder_control - > cfg . trskip_max_size )
& & ! ( cur_pu - > type = = CU_INTRA & & cur_pu - > intra . isp_mode ! = ISP_MODE_NO_ISP ) ) {
2021-04-27 11:13:44 +00:00
cabac - > cur_ctx = & cabac - > ctx . transform_skip_model_luma ;
2021-04-29 10:47:31 +00:00
CABAC_BIN ( cabac , cur_pu - > tr_idx = = MTS_SKIP , " transform_skip_flag " ) ;
2022-11-15 13:31:44 +00:00
DBG_YUVIEW_VALUE ( state - > frame - > poc , DBG_YUVIEW_TR_SKIP , x , y , width , height , ( cur_pu - > tr_idx = = MTS_SKIP ) ? 1 : 0 ) ;
2021-04-29 10:47:31 +00:00
}
if ( cur_pu - > tr_idx = = MTS_SKIP ) {
2022-08-18 12:07:22 +00:00
uvg_encode_ts_residual ( state , cabac , coeff_y , width , height , 0 , scan_idx , NULL ) ;
2021-04-27 11:13:44 +00:00
}
else {
2022-04-28 11:18:09 +00:00
uvg_encode_coeff_nxn ( state ,
2021-04-27 11:13:44 +00:00
cabac ,
coeff_y ,
2022-08-24 13:15:03 +00:00
cu_loc ,
2021-04-27 11:13:44 +00:00
0 ,
scan_idx ,
2022-04-01 07:46:51 +00:00
( cu_info_t * ) cur_pu ,
NULL ) ;
2021-04-27 11:13:44 +00:00
}
2022-11-30 08:43:12 +00:00
if ( tree_type = = UVG_LUMA_T ) return ;
2016-08-09 13:01:51 +00:00
}
2021-08-17 06:31:01 +00:00
bool joint_chroma = cur_pu - > joint_cb_cr ! = 0 ;
2022-11-24 07:04:42 +00:00
if ( cur_pu - > log2_height + cur_pu - > log2_width < 6 & & tree_type ! = UVG_CHROMA_T & & ! only_chroma ) {
2016-08-09 13:01:51 +00:00
// For size 4x4 luma transform the corresponding chroma transforms are
2017-05-23 10:31:30 +00:00
// also of size 4x4 covering 8x8 luma pixels. The residual is coded in
// the last transform unit.
2021-04-14 11:19:31 +00:00
if ( ( x % 8 = = 0 | | y % 8 = = 0 ) | | ! only_chroma ) {
2017-05-23 10:31:30 +00:00
// Not the last luma transform block so there is nothing more to do.
return ;
} else {
// Time to to code the chroma transform blocks. Move to the top-left
// corner of the block.
2022-06-08 07:26:56 +00:00
cur_pu = uvg_cu_array_at_const ( ( const cu_array_t * ) used_cu_array , x , y ) ;
2017-05-23 10:31:30 +00:00
}
2016-08-09 13:01:51 +00:00
}
2022-09-14 08:47:26 +00:00
bool chroma_cbf_set = cbf_is_set ( cur_pu - > cbf , COLOR_U ) | |
cbf_is_set ( cur_pu - > cbf , COLOR_V ) ;
2022-11-25 11:50:22 +00:00
if ( ( chroma_cbf_set | | joint_chroma ) & & last_split & & chroma_loc ) {
2022-06-28 13:02:22 +00:00
//Need to drop const to get lfnst constraints
2022-08-31 11:54:30 +00:00
// Use original dimensions instead of ISP split dimensions
2022-11-25 11:50:22 +00:00
encode_chroma_tu ( state , chroma_loc , ( cu_info_t * ) cur_pu , & scan_idx , coeff , joint_chroma , tree_type ) ;
2016-08-09 13:01:51 +00:00
}
}
/**
* \ param encoder
* \ param x_pu Prediction units ' x coordinate .
* \ param y_pu Prediction units ' y coordinate .
* \ param depth Depth from LCU .
* \ param parent_coeff_u What was signaled at previous level for cbf_cb .
* \ param parent_coeff_v What was signlaed at previous level for cbf_cr .
*/
2022-06-06 11:49:52 +00:00
static void encode_transform_coeff (
encoder_state_t * const state ,
2022-08-21 09:46:07 +00:00
const cu_loc_t * cu_loc ,
2022-06-06 11:49:52 +00:00
bool only_chroma ,
lcu_coeff_t * coeff ,
2022-11-24 07:04:42 +00:00
const cu_info_t * cur_tu ,
2022-08-17 13:42:22 +00:00
enum uvg_tree_type tree_type ,
2022-08-31 09:28:57 +00:00
bool last_split ,
2022-09-13 10:27:16 +00:00
bool can_skip_last_cbf ,
2022-11-25 11:50:22 +00:00
int * luma_cbf_ctx ,
// Always true except when writing sub partition coeffs (ISP)
const cu_loc_t * const original_loc ,
const cu_loc_t * const chroma_loc ) // Original dimensions before ISP split
2016-08-09 13:01:51 +00:00
{
cabac_data_t * const cabac = & state - > cabac ;
2022-08-21 09:46:07 +00:00
2022-09-13 10:27:16 +00:00
bool isp_split = cu_loc - > x ! = original_loc - > x | | cu_loc - > y ! = original_loc - > y ;
2022-11-24 07:47:36 +00:00
int x = cu_loc - > x ;
int y = cu_loc - > y ;
2022-09-16 08:10:26 +00:00
if ( isp_split ) {
uvg_get_isp_cu_arr_coords ( & x , & y ) ;
}
2018-10-17 06:06:35 +00:00
//const encoder_control_t *const ctrl = state->encoder_control;
2016-08-09 13:01:51 +00:00
const videoframe_t * const frame = state - > tile - > frame ;
2022-06-21 09:39:12 +00:00
const cu_array_t * used_array = tree_type ! = UVG_CHROMA_T ? frame - > cu_array : frame - > chroma_cu_array ;
2022-11-24 07:04:42 +00:00
if ( cur_tu = = NULL ) {
2022-11-24 07:47:36 +00:00
cur_tu = uvg_cu_array_at_const ( used_array , x , y ) ;
2022-11-24 07:04:42 +00:00
}
2022-11-21 11:45:36 +00:00
2022-11-30 08:43:12 +00:00
const int tr_limit = ( TR_MAX_WIDTH > > ( tree_type = = UVG_CHROMA_T ) ) ;
const bool ver_split = cu_loc - > height > tr_limit ;
const bool hor_split = cu_loc - > width > tr_limit ;
2019-07-01 10:00:43 +00:00
2022-11-24 07:04:42 +00:00
const int cb_flag_y = tree_type ! = UVG_CHROMA_T ? cbf_is_set ( cur_tu - > cbf , COLOR_Y ) : 0 ;
const int cb_flag_u = tree_type ! = UVG_LUMA_T ? ( cur_tu - > joint_cb_cr ? ( cur_tu - > joint_cb_cr > > 1 ) & 1 : cbf_is_set ( cur_tu - > cbf , COLOR_U ) ) : 0 ;
const int cb_flag_v = tree_type ! = UVG_LUMA_T ? ( cur_tu - > joint_cb_cr ? cur_tu - > joint_cb_cr & 1 : cbf_is_set ( cur_tu - > cbf , COLOR_V ) ) : 0 ;
2016-08-09 13:01:51 +00:00
2022-11-21 11:45:36 +00:00
if ( hor_split | | ver_split ) {
enum split_type split ;
2022-11-30 08:43:12 +00:00
if ( cu_loc - > width > tr_limit & & cu_loc - > height > tr_limit ) {
2022-11-21 11:45:36 +00:00
split = QT_SPLIT ;
}
2022-11-30 08:43:12 +00:00
else if ( cu_loc - > width > tr_limit ) {
2022-11-21 11:45:36 +00:00
split = BT_VER_SPLIT ;
}
else {
split = BT_HOR_SPLIT ;
}
2022-09-13 08:20:25 +00:00
2022-11-21 11:45:36 +00:00
cu_loc_t split_cu_loc [ 4 ] ;
2022-11-24 07:04:42 +00:00
const int split_count = uvg_get_split_locs ( cu_loc , split , split_cu_loc , NULL ) ;
2022-11-21 11:45:36 +00:00
for ( int i = 0 ; i < split_count ; + + i ) {
2022-11-30 08:43:12 +00:00
if ( tree_type = = UVG_CHROMA_T ) {
split_cu_loc [ i ] . chroma_width = split_cu_loc [ i ] . width ;
split_cu_loc [ i ] . chroma_height = split_cu_loc [ i ] . height ;
}
2022-11-25 11:50:22 +00:00
encode_transform_coeff ( state , & split_cu_loc [ i ] , only_chroma ,
2022-12-02 11:56:38 +00:00
coeff , NULL , tree_type , true , false , luma_cbf_ctx , & split_cu_loc [ i ] , chroma_loc ? & split_cu_loc [ i ] : NULL ) ;
2022-09-13 08:20:25 +00:00
}
return ;
}
2022-11-24 07:47:36 +00:00
2016-08-09 13:01:51 +00:00
// Chroma cb flags are not signaled when one of the following:
2022-09-15 11:00:08 +00:00
// No chroma.
// Not the last CU for area of 64 pixels cowered by more than one luma CU.
// Not the last ISP Split
2022-11-24 07:47:36 +00:00
if ( state - > encoder_control - > chroma_format ! = UVG_CSP_400
2022-11-25 11:50:22 +00:00
& & ( chroma_loc | | only_chroma )
2022-11-24 07:47:36 +00:00
& & tree_type ! = UVG_LUMA_T
2022-09-15 12:13:48 +00:00
& & last_split ) {
2022-09-15 11:00:08 +00:00
cabac - > cur_ctx = & ( cabac - > ctx . qt_cbf_model_cb [ 0 ] ) ;
CABAC_BIN ( cabac , cb_flag_u , " cbf_cb " ) ;
cabac - > cur_ctx = & ( cabac - > ctx . qt_cbf_model_cr [ cb_flag_u ? 1 : 0 ] ) ;
2022-11-24 07:47:36 +00:00
CABAC_BIN ( cabac , cb_flag_v , " cbf_cr " ) ;
2016-08-09 13:01:51 +00:00
}
// Luma coded block flag is signaled when one of the following:
// - prediction mode is intra
// - transform depth > 0
// - we have chroma coefficients at this level
// When it is not present, it is inferred to be 1.
2022-11-24 07:04:42 +00:00
if ( ( cur_tu - > type = = CU_INTRA | | ! PU_IS_TU ( cur_tu ) | | cb_flag_u | | cb_flag_v ) & & ! only_chroma & & tree_type ! = UVG_CHROMA_T ) {
2022-09-13 10:27:16 +00:00
if ( can_skip_last_cbf & & isp_split & & last_split ) {
// Do not write luma cbf if first three isp splits have luma cbf 0
} else {
2022-08-31 09:28:57 +00:00
cabac - > cur_ctx = & ( cabac - > ctx . qt_cbf_model_luma [ * luma_cbf_ctx ] ) ;
2016-08-09 13:01:51 +00:00
CABAC_BIN ( cabac , cb_flag_y , " cbf_luma " ) ;
2022-11-24 07:04:42 +00:00
if ( PU_IS_TU ( cur_tu ) ) {
2022-09-05 08:10:55 +00:00
* luma_cbf_ctx = 2 + cb_flag_y ;
}
2022-09-13 10:27:16 +00:00
}
2016-08-09 13:01:51 +00:00
}
if ( cb_flag_y | cb_flag_u | cb_flag_v ) {
2022-11-25 11:50:22 +00:00
if ( state - > must_code_qp_delta & & ( only_chroma | | cb_flag_y | | chroma_loc ) ) {
2022-11-24 07:04:42 +00:00
const int qp_pred = uvg_get_cu_ref_qp ( state , cu_loc - > x , cu_loc - > y , state - > last_qp ) ;
const int qp_delta = cur_tu - > qp - qp_pred ;
2020-09-22 10:41:22 +00:00
// Possible deltaQP range depends on bit depth as stated in HEVC specification.
2022-04-28 11:18:09 +00:00
assert ( qp_delta > = UVG_QP_DELTA_MIN & & qp_delta < = UVG_QP_DELTA_MAX & & " QP delta not in valid range. " ) ;
2020-09-22 10:41:22 +00:00
2017-05-08 07:54:06 +00:00
const int qp_delta_abs = ABS ( qp_delta ) ;
cabac_data_t * cabac = & state - > cabac ;
2016-08-21 04:36:13 +00:00
// cu_qp_delta_abs prefix
2022-05-30 09:11:48 +00:00
uvg_cabac_write_unary_max_symbol ( cabac , cabac - > ctx . cu_qp_delta_abs , MIN ( qp_delta_abs , 5 ) , 1 , 5 , NULL ) ;
2016-08-21 04:36:13 +00:00
if ( qp_delta_abs > = 5 ) {
// cu_qp_delta_abs suffix
2022-04-28 11:18:09 +00:00
uvg_cabac_write_ep_ex_golomb ( state , cabac , qp_delta_abs - 5 , 0 ) ;
2016-08-21 04:36:13 +00:00
}
if ( qp_delta ! = 0 ) {
CABAC_BIN_EP ( cabac , ( qp_delta > = 0 ? 0 : 1 ) , " qp_delta_sign_flag " ) ;
}
state - > must_code_qp_delta = false ;
}
2022-03-31 08:45:49 +00:00
if ( (
( ( cb_flag_u | | cb_flag_v )
2022-11-24 07:04:42 +00:00
& & cur_tu - > type = = CU_INTRA )
2022-03-31 08:45:49 +00:00
| | ( cb_flag_u & & cb_flag_v ) )
2022-11-25 11:50:22 +00:00
& & ( chroma_loc | | only_chroma | | tree_type = = UVG_CHROMA_T )
2022-03-31 08:45:49 +00:00
& & state - > encoder_control - > cfg . jccr
2022-08-17 13:42:22 +00:00
& & last_split
2022-03-31 08:45:49 +00:00
) {
2022-11-24 07:04:42 +00:00
assert ( cur_tu - > joint_cb_cr < 4 & & " JointCbCr is in search state. " ) ;
2021-08-13 12:37:23 +00:00
cabac - > cur_ctx = & cabac - > ctx . joint_cb_cr [ cb_flag_u * 2 + cb_flag_v - 1 ] ;
2022-11-24 07:04:42 +00:00
CABAC_BIN ( cabac , cur_tu - > joint_cb_cr ! = 0 , " tu_joint_cbcr_residual_flag " ) ;
2021-08-13 12:37:23 +00:00
}
2022-08-21 09:46:07 +00:00
2022-11-25 11:50:22 +00:00
encode_transform_unit ( state , cu_loc , only_chroma ? cur_tu : NULL , coeff , only_chroma , tree_type , last_split , original_loc , chroma_loc ) ;
2016-08-09 13:01:51 +00:00
}
}
2021-11-16 15:18:29 +00:00
/**
* \ brief Writes inter block parameters to the bitstream
* \ param state Encoder state in use
* \ param x Slice x coordinate .
* \ param y Slice y coordinate .
* \ param depth Depth from LCU .
* \ return if non - zero mvd is coded
*/
2022-09-06 10:45:08 +00:00
int uvg_encode_inter_prediction_unit (
encoder_state_t * const state ,
cabac_data_t * const cabac ,
const cu_info_t * const cur_cu ,
lcu_t * lcu ,
double * bits_out ,
const cu_loc_t * const cu_loc )
2016-08-09 13:01:51 +00:00
{
// Mergeflag
int16_t num_cand = 0 ;
2021-11-16 15:18:29 +00:00
bool non_zero_mvd = false ;
2021-12-16 06:40:23 +00:00
double bits = 0 ;
CABAC_FBITS_UPDATE ( cabac , & ( cabac - > ctx . cu_merge_flag_ext_model ) , cur_cu - > merged , bits , " MergeFlag " ) ;
2021-10-25 08:25:23 +00:00
num_cand = state - > encoder_control - > cfg . max_merge ;
2016-08-09 13:01:51 +00:00
if ( cur_cu - > merged ) { //merge
if ( num_cand > 1 ) {
int32_t ui ;
for ( ui = 0 ; ui < num_cand - 1 ; ui + + ) {
int32_t symbol = ( ui ! = cur_cu - > merge_idx ) ;
if ( ui = = 0 ) {
2021-12-16 06:40:23 +00:00
CABAC_FBITS_UPDATE ( cabac , & ( cabac - > ctx . cu_merge_idx_ext_model ) , symbol , bits , " MergeIndex " ) ;
2016-08-09 13:01:51 +00:00
} else {
CABAC_BIN_EP ( cabac , symbol , " MergeIndex " ) ;
2021-12-16 06:40:23 +00:00
if ( cabac - > only_count ) bits + = 1 ;
2016-08-09 13:01:51 +00:00
}
if ( symbol = = 0 ) break ;
}
}
2022-04-28 11:18:09 +00:00
# ifdef UVG_DEBUG_PRINT_YUVIEW_CSV
2021-12-01 13:36:29 +00:00
int abs_x = x + state - > tile - > offset_x ;
int abs_y = y + state - > tile - > offset_y ;
if ( cur_cu - > inter . mv_dir & 1 ) DBG_YUVIEW_MV ( state - > frame - > poc , DBG_YUVIEW_MVMERGE_L0 , abs_x , abs_y , width , height , cur_cu - > inter . mv [ 0 ] [ 0 ] , cur_cu - > inter . mv [ 0 ] [ 1 ] ) ;
if ( cur_cu - > inter . mv_dir & 2 ) DBG_YUVIEW_MV ( state - > frame - > poc , DBG_YUVIEW_MVMERGE_L1 , abs_x , abs_y , width , height , cur_cu - > inter . mv [ 1 ] [ 0 ] , cur_cu - > inter . mv [ 1 ] [ 1 ] ) ;
2021-11-30 20:07:01 +00:00
# endif
2016-08-09 13:01:51 +00:00
} else {
2022-04-28 11:18:09 +00:00
if ( state - > frame - > slicetype = = UVG_SLICE_B ) {
2016-08-09 13:01:51 +00:00
// Code Inter Dir
2021-11-10 10:54:33 +00:00
uint8_t inter_dir = cur_cu - > inter . mv_dir ;
2016-08-09 13:01:51 +00:00
2022-09-07 13:11:36 +00:00
if ( cu_loc - > width + cu_loc - > height > 12 ) { // ToDo: limit on 4x8/8x4
2022-09-06 10:45:08 +00:00
uint32_t inter_dir_ctx = ( 7 - ( ( uvg_math_floor_log2 ( cu_loc - > width ) + uvg_math_floor_log2 ( cu_loc - > height ) + 1 ) > > 1 ) ) ;
2021-11-10 10:54:33 +00:00
2022-03-21 06:42:41 +00:00
CABAC_FBITS_UPDATE ( cabac , & ( cabac - > ctx . inter_dir [ inter_dir_ctx ] ) , ( inter_dir = = 3 ) , bits , " inter_pred_idc " ) ;
2016-08-09 13:01:51 +00:00
}
2021-11-10 10:54:33 +00:00
if ( inter_dir < 3 ) {
2022-03-21 06:42:41 +00:00
CABAC_FBITS_UPDATE ( cabac , & ( cabac - > ctx . inter_dir [ 5 ] ) , ( inter_dir = = 2 ) , bits , " inter_pred_idc " ) ;
2016-08-09 13:01:51 +00:00
}
2021-11-30 20:07:01 +00:00
}
2016-08-09 13:01:51 +00:00
2018-01-18 10:47:27 +00:00
for ( uint32_t ref_list_idx = 0 ; ref_list_idx < 2 ; ref_list_idx + + ) {
if ( ! ( cur_cu - > inter . mv_dir & ( 1 < < ref_list_idx ) ) ) {
continue ;
}
2022-04-28 11:18:09 +00:00
# ifdef UVG_DEBUG_PRINT_YUVIEW_CSV
2021-12-01 13:36:29 +00:00
int abs_x = x + state - > tile - > offset_x ;
int abs_y = y + state - > tile - > offset_y ;
DBG_YUVIEW_MV ( state - > frame - > poc , ref_list_idx ? DBG_YUVIEW_MVINTER_L1 : DBG_YUVIEW_MVINTER_L0 , abs_x , abs_y , width , height , cur_cu - > inter . mv [ ref_list_idx ] [ 0 ] , cur_cu - > inter . mv [ ref_list_idx ] [ 1 ] ) ;
2021-12-01 13:48:17 +00:00
# endif
2018-01-18 10:47:27 +00:00
// size of the current reference index list (L0/L1)
uint8_t ref_LX_size = state - > frame - > ref_LX_size [ ref_list_idx ] ;
2017-06-26 12:31:57 +00:00
2018-01-18 10:47:27 +00:00
if ( ref_LX_size > 1 ) {
// parseRefFrmIdx
int32_t ref_frame = cur_cu - > inter . mv_ref [ ref_list_idx ] ;
2021-12-16 06:40:23 +00:00
CABAC_FBITS_UPDATE ( cabac , & ( cabac - > ctx . cu_ref_pic_model [ 0 ] ) , ( ref_frame ! = 0 ) , bits , " ref_idx_lX " ) ;
2021-11-09 07:05:45 +00:00
if ( ref_frame > 0 & & ref_LX_size > 2 ) {
cabac - > cur_ctx = & ( cabac - > ctx . cu_ref_pic_model [ 1 ] ) ;
2022-03-21 06:42:41 +00:00
CABAC_FBITS_UPDATE ( cabac , & ( cabac - > ctx . cu_ref_pic_model [ 1 ] ) , ( ref_frame > 1 ) , bits , " ref_idx_lX " ) ;
2021-11-09 07:05:45 +00:00
if ( ref_frame > 1 & & ref_LX_size > 3 ) {
for ( int idx = 3 ; idx < ref_LX_size ; idx + + )
{
uint8_t val = ( ref_frame > idx - 1 ) ? 1 : 0 ;
CABAC_BIN_EP ( cabac , val , " ref_idx_lX " ) ;
2021-12-16 06:40:23 +00:00
if ( cabac - > only_count ) bits + = 1 ;
2021-11-09 07:05:45 +00:00
if ( ! val ) break ;
2022-03-21 06:42:41 +00:00
2016-08-09 13:01:51 +00:00
}
}
}
2021-11-09 07:05:45 +00:00
2018-01-18 10:47:27 +00:00
}
2016-08-09 13:01:51 +00:00
2018-01-18 10:47:27 +00:00
if ( state - > frame - > ref_list ! = REF_PIC_LIST_1 | | cur_cu - > inter . mv_dir ! = 3 ) {
2016-08-09 13:01:51 +00:00
2021-11-19 14:20:49 +00:00
mv_t mv_cand [ 2 ] [ 2 ] ;
2021-12-13 08:43:19 +00:00
if ( lcu ) {
2022-05-30 09:11:48 +00:00
uvg_inter_get_mv_cand (
2021-12-13 08:43:19 +00:00
state ,
2022-09-06 10:45:08 +00:00
mv_cand , cur_cu , lcu , ref_list_idx ,
cu_loc ) ;
2021-12-13 08:43:19 +00:00
}
else {
2022-05-30 09:11:48 +00:00
uvg_inter_get_mv_cand_cua (
2018-01-18 10:47:27 +00:00
state ,
2022-09-06 10:45:08 +00:00
mv_cand , cur_cu , ref_list_idx , cu_loc
) ;
2021-12-13 08:43:19 +00:00
}
2016-08-09 13:01:51 +00:00
2018-01-18 10:47:27 +00:00
uint8_t cu_mv_cand = CU_GET_MV_CAND ( cur_cu , ref_list_idx ) ;
2021-11-29 12:20:09 +00:00
mv_t mvd_hor = cur_cu - > inter . mv [ ref_list_idx ] [ 0 ] - mv_cand [ cu_mv_cand ] [ 0 ] ;
mv_t mvd_ver = cur_cu - > inter . mv [ ref_list_idx ] [ 1 ] - mv_cand [ cu_mv_cand ] [ 1 ] ;
2016-08-09 13:01:51 +00:00
2022-04-28 11:18:09 +00:00
uvg_change_precision ( INTERNAL_MV_PREC , uvg_g_imv_to_prec [ UVG_IMV_OFF ] , & mvd_hor , & mvd_ver ) ;
2022-05-30 09:11:48 +00:00
uvg_encode_mvd ( state , cabac , mvd_hor , mvd_ver , bits_out ) ;
2021-11-16 15:18:29 +00:00
non_zero_mvd | = ( mvd_hor ! = 0 ) | | ( mvd_ver ! = 0 ) ;
2018-01-18 10:47:27 +00:00
}
2016-08-09 13:01:51 +00:00
2018-01-18 10:47:27 +00:00
// Signal which candidate MV to use
2022-03-21 06:42:41 +00:00
CABAC_FBITS_UPDATE ( cabac , & ( cabac - > ctx . mvp_idx_model ) , CU_GET_MV_CAND ( cur_cu , ref_list_idx ) , bits , " mvp_flag " ) ;
2016-08-09 13:01:51 +00:00
} // for ref_list
} // if !merge
2021-12-16 06:40:23 +00:00
if ( bits_out ) * bits_out + = bits ;
2021-11-16 15:18:29 +00:00
return non_zero_mvd ;
2016-08-09 13:01:51 +00:00
}
2022-05-11 12:18:59 +00:00
static void encode_chroma_intra_cu (
2022-11-25 11:50:22 +00:00
cabac_data_t * const cabac ,
const cu_info_t * const cur_cu ,
const int cclm_enabled ,
int8_t luma_intra_dir ,
2022-05-11 12:18:59 +00:00
double * bits_out ) {
2021-04-14 11:19:31 +00:00
unsigned pred_mode = 0 ;
2021-05-27 05:38:32 +00:00
unsigned chroma_pred_modes [ 8 ] = { 0 , 50 , 18 , 1 , 67 , 81 , 82 , 83 } ;
2022-03-31 08:30:27 +00:00
int8_t chroma_intra_dir = cur_cu - > intra . mode_chroma ;
2022-04-27 09:05:32 +00:00
for ( int i = 0 ; i < 4 ; i + + ) {
if ( chroma_pred_modes [ i ] = = luma_intra_dir ) {
chroma_pred_modes [ i ] = 66 ;
}
}
2021-04-14 11:19:31 +00:00
2022-05-11 12:18:59 +00:00
double bits = 0 ;
2021-05-27 05:38:32 +00:00
bool derived_mode = chroma_intra_dir = = luma_intra_dir ;
2021-11-17 10:41:42 +00:00
bool cclm_mode = chroma_intra_dir > 67 ;
if ( cclm_enabled ) {
2022-05-10 10:45:18 +00:00
CABAC_FBITS_UPDATE ( cabac , & cabac - > ctx . cclm_flag , cclm_mode , bits , " cclm_flag " ) ;
2021-11-17 10:41:42 +00:00
if ( cclm_mode ) {
2022-05-10 10:45:18 +00:00
CABAC_FBITS_UPDATE ( cabac , & cabac - > ctx . cclm_model , chroma_intra_dir ! = 81 , bits , " cclm_model_1 " ) ;
2021-11-17 10:41:42 +00:00
if ( chroma_intra_dir ! = 81 ) {
2021-11-18 04:55:42 +00:00
CABAC_BIN_EP ( cabac , chroma_intra_dir = = 83 , " cclm_model_2 " ) ;
2022-05-19 06:09:08 +00:00
bits + = 1 ;
2021-11-17 10:41:42 +00:00
}
2022-05-19 06:09:08 +00:00
if ( cabac - > only_count & & bits_out ) * bits_out + = bits ;
2021-11-17 10:41:42 +00:00
return ;
}
}
2022-05-10 10:45:18 +00:00
CABAC_FBITS_UPDATE ( cabac , & cabac - > ctx . chroma_pred_model , derived_mode ? 0 : 1 , bits , " intra_chroma_pred_mode " ) ;
2021-04-14 11:19:31 +00:00
2021-05-27 05:38:32 +00:00
if ( ! derived_mode ) {
2021-04-14 11:19:31 +00:00
/*for (int i = 0; i < 4; i++) {
if ( luma_intra_dir = = chroma_pred_modes [ i ] ) {
chroma_pred_modes [ i ] = 66 ;
break ;
}
} */
2021-11-17 10:41:42 +00:00
for ( ; pred_mode < 5 ; pred_mode + + ) {
2021-04-14 11:19:31 +00:00
if ( chroma_intra_dir = = chroma_pred_modes [ pred_mode ] ) {
break ;
}
}
2022-06-08 13:33:14 +00:00
assert ( pred_mode ! = 5 & & " Invalid chroma prediction mode " ) ;
2021-04-14 11:19:31 +00:00
/*else if (intra_pred_mode_chroma == 66) {
// Angular 66 mode is possible only if intra pred mode is one of the
// possible chroma pred modes, in which case it is signaled with that
// duplicate mode.
for ( int i = 0 ; i < 4 ; + + i ) {
if ( intra_pred_mode_actual [ 0 ] = = chroma_pred_modes [ i ] ) pred_mode = i ;
}
}
else {
for ( int i = 0 ; i < 4 ; + + i ) {
if ( intra_pred_mode_chroma = = chroma_pred_modes [ i ] ) pred_mode = i ;
}
}
// pred_mode == 67 mean intra_pred_mode_chroma is something that can't
// be coded.
assert ( pred_mode ! = 67 ) ;
*/
/**
* Table 9 - 35 - Binarization for intra_chroma_pred_mode
* intra_chroma_pred_mode bin_string
* 4 0
* 0 100
* 1 101
* 2 110
* 3 111
* Table 9 - 37 - Assignment of ctxInc to syntax elements with context coded bins
* intra_chroma_pred_mode [ ] [ ] = 0 , bypass , bypass
*/
/*cabac->cur_ctx = &(cabac->ctx.chroma_pred_model[0]);
if ( pred_mode = = 68 ) {
CABAC_BIN ( cabac , 0 , " intra_chroma_pred_mode " ) ;
}
else {
CABAC_BIN ( cabac , 1 , " intra_chroma_pred_mode " ) ; */
2021-05-27 05:38:32 +00:00
CABAC_BINS_EP ( cabac , pred_mode , 2 , " intra_chroma_pred_mode " ) ;
2022-05-10 10:45:18 +00:00
if ( cabac - > only_count & & bits_out ) * bits_out + = 2 + bits ;
2021-04-14 11:19:31 +00:00
//}
}
2022-05-11 12:18:59 +00:00
else if ( cabac - > only_count & & bits_out ) * bits_out + = bits ;
2021-04-14 11:19:31 +00:00
}
2022-09-07 13:11:36 +00:00
void uvg_encode_intra_luma_coding_unit (
const encoder_state_t * const state ,
cabac_data_t * const cabac ,
const cu_info_t * const cur_cu ,
const cu_loc_t * const cu_loc ,
const lcu_t * lcu ,
double * bits_out )
2017-03-06 16:27:39 +00:00
{
const videoframe_t * const frame = state - > tile - > frame ;
2022-03-24 11:34:26 +00:00
uint8_t intra_pred_mode_actual ;
uint8_t * intra_pred_mode = & intra_pred_mode_actual ;
2017-03-06 16:27:39 +00:00
2021-11-29 12:20:09 +00:00
//uint8_t intra_pred_mode_chroma = cur_cu->intra.mode_chroma;
2022-03-24 11:34:26 +00:00
int8_t intra_preds [ INTRA_MPM_COUNT ] = { - 1 , - 1 , - 1 , - 1 , - 1 , - 1 } ;
int8_t mpm_preds = - 1 ;
uint32_t flag ;
double bits = 0 ;
2016-08-09 13:01:51 +00:00
2022-09-07 13:11:36 +00:00
const int x = cu_loc - > x ;
const int y = cu_loc - > y ;
2019-05-29 10:00:19 +00:00
/*
if ( ( cur_cu - > type = = CU_INTRA & & ( LCU_WIDTH > > cur_cu - > depth < = 32 ) ) ) {
cabac - > cur_ctx = & ( cabac - > ctx . bdpcm_mode [ 0 ] ) ;
CABAC_BIN ( cabac , cur_cu - > bdpcmMode > 0 ? 1 : 0 , " bdpcm_mode " ) ;
if ( cur_cu - > bdpcmMode ) {
cabac - > cur_ctx = & ( cabac - > ctx . bdpcm_mode [ 1 ] ) ;
CABAC_BIN ( cabac , cur_cu - > bdpcmMode > 1 ? 1 : 0 , " bdpcm_mode > 1 " ) ;
}
}
*/
2016-08-09 13:01:51 +00:00
# if ENABLE_PCM == 1
// Code must start after variable initialization
2022-04-28 11:18:09 +00:00
uvg_cabac_encode_bin_trm ( cabac , 0 ) ; // IPCMFlag == 0
2016-08-09 13:01:51 +00:00
# endif
2019-08-22 11:33:42 +00:00
/*
2019-07-01 10:00:43 +00:00
if ( cur_cu - > type = = 1 & & ( LCU_WIDTH > > depth < = 32 ) ) {
cabac - > cur_ctx = & ( cabac - > ctx . bdpcm_mode [ 0 ] ) ;
CABAC_BIN ( cabac , 0 , " bdpcm_mode " ) ;
}
2019-08-22 11:33:42 +00:00
*/
2021-08-23 21:15:09 +00:00
2022-09-07 13:11:36 +00:00
uint32_t width = cu_loc - > width ;
uint32_t height = cu_loc - > height ; // TODO: height for non-square blocks
2019-05-21 09:28:05 +00:00
2022-01-21 00:17:07 +00:00
// Code MIP related bits
bool enable_mip = state - > encoder_control - > cfg . mip ;
2022-01-26 11:33:51 +00:00
int8_t mip_flag = enable_mip ? cur_cu - > intra . mip_flag : false ;
2022-01-21 00:17:07 +00:00
bool mip_transpose = enable_mip ? cur_cu - > intra . mip_is_transposed : false ;
int8_t mip_mode = enable_mip ? cur_cu - > intra . mode : 0 ;
uint8_t num_mip_modes ;
// Number of MIP modes for this block
if ( width = = 4 & & height = = 4 ) {
num_mip_modes = 16 ;
}
else if ( width = = 4 | | height = = 4 | | ( width = = 8 & & height = = 8 ) ) {
num_mip_modes = 8 ;
}
else {
num_mip_modes = 6 ;
}
if ( mip_flag ) {
2022-02-01 19:09:36 +00:00
assert ( mip_mode > = 0 & & mip_mode < num_mip_modes & & " Invalid MIP mode. " ) ;
2022-01-21 00:17:07 +00:00
}
if ( cur_cu - > type = = CU_INTRA & & ! cur_cu - > bdpcmMode & & enable_mip ) {
2022-09-07 13:11:36 +00:00
uint8_t ctx_id = uvg_get_mip_flag_context ( cu_loc , lcu , lcu ? NULL : frame - > cu_array ) ;
2022-01-26 11:33:51 +00:00
2022-01-21 00:17:07 +00:00
// Write MIP flag
2022-03-24 11:34:26 +00:00
CABAC_FBITS_UPDATE ( cabac , & ( cabac - > ctx . mip_flag [ ctx_id ] ) , mip_flag , bits , " mip_flag " ) ;
2022-01-21 00:17:07 +00:00
if ( mip_flag ) {
// Write MIP transpose flag & mode
2022-01-21 11:32:41 +00:00
CABAC_BIN_EP ( cabac , mip_transpose , " mip_transposed " ) ;
2022-03-24 11:34:26 +00:00
if ( cabac - > only_count ) bits + = 1 ;
2022-05-30 09:11:48 +00:00
uvg_cabac_encode_trunc_bin ( cabac , mip_mode , num_mip_modes , bits_out ) ;
2022-04-15 08:38:31 +00:00
if ( cabac - > only_count & & bits_out ) * bits_out + = bits ;
2022-03-24 11:34:26 +00:00
return ;
2022-01-21 00:17:07 +00:00
}
}
2021-08-23 21:15:09 +00:00
// Code MRL related bits
bool enable_mrl = state - > encoder_control - > cfg . mrl ;
2021-12-08 09:39:20 +00:00
int multi_ref_idx = enable_mrl ? cur_cu - > intra . multi_ref_idx : 0 ;
2022-04-28 11:18:09 +00:00
# ifdef UVG_DEBUG_PRINT_YUVIEW_CSV
2022-11-15 13:31:44 +00:00
if ( multi_ref_idx ) DBG_YUVIEW_VALUE ( state - > frame - > poc , DBG_YUVIEW_MRL , x , y , width , height , multi_ref_idx ) ;
2021-12-13 14:01:52 +00:00
# endif
2021-08-23 21:15:09 +00:00
2022-01-21 00:17:07 +00:00
if ( cur_cu - > type = = CU_INTRA & & ( y % LCU_WIDTH ) ! = 0 & & ! cur_cu - > bdpcmMode & & enable_mrl & & ! mip_flag ) {
2021-08-23 21:15:09 +00:00
if ( MAX_REF_LINE_IDX > 1 ) {
2022-03-24 11:34:26 +00:00
CABAC_FBITS_UPDATE ( cabac , & ( cabac - > ctx . multi_ref_line [ 0 ] ) , multi_ref_idx ! = 0 , bits , " multi_ref_line " ) ;
2021-08-23 21:15:09 +00:00
if ( MAX_REF_LINE_IDX > 2 & & multi_ref_idx ! = 0 ) {
2022-03-24 11:34:26 +00:00
CABAC_FBITS_UPDATE ( cabac , & ( cabac - > ctx . multi_ref_line [ 1 ] ) , multi_ref_idx ! = 1 , bits , " multi_ref_line " ) ;
2021-08-23 21:15:09 +00:00
}
}
2019-06-07 10:37:45 +00:00
}
2022-08-17 12:23:35 +00:00
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)
2022-09-21 13:04:52 +00:00
bool allow_isp = enable_isp ? uvg_can_use_isp ( width , height ) : false ;
2022-08-17 12:23:35 +00:00
uint8_t isp_mode = allow_isp ? cur_cu - > intra . isp_mode : 0 ;
2019-06-07 10:37:45 +00:00
2022-08-17 12:23:35 +00:00
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
2019-05-21 09:28:05 +00:00
}
2019-03-20 07:07:58 +00:00
}
2022-09-07 13:11:36 +00:00
2022-01-21 00:17:07 +00:00
// PREDINFO CODING
// If intra prediction mode is found from the predictors,
// it can be signaled with two EP's. Otherwise we can send
// 5 EP bins with the full predmode
// ToDo: fix comments for VVC
2022-05-30 09:11:48 +00:00
const cu_info_t * cur_pu = cur_cu ; // uvg_cu_array_at_const(frame->cu_array, pu_x, pu_y);
2019-03-20 07:07:58 +00:00
2022-03-24 11:34:26 +00:00
const cu_info_t * left_pu = NULL ;
const cu_info_t * above_pu = NULL ;
2019-03-20 07:07:58 +00:00
2022-03-24 11:34:26 +00:00
if ( x > 0 ) {
assert ( x > > 2 > 0 ) ;
2022-04-27 09:05:32 +00:00
const int x_scu = SUB_SCU ( x ) - 1 ;
2022-09-07 13:11:36 +00:00
const int y_scu = SUB_SCU ( y + height - 1 ) ;
2022-03-24 11:34:26 +00:00
left_pu = lcu ?
LCU_GET_CU_AT_PX (
lcu ,
2022-04-27 09:05:32 +00:00
x_scu ,
y_scu ) :
2022-05-30 09:11:48 +00:00
uvg_cu_array_at_const (
2022-03-24 11:34:26 +00:00
frame - > cu_array ,
x - 1 ,
2022-09-07 13:11:36 +00:00
y + height - 1 ) ;
2022-03-24 11:34:26 +00:00
}
// Don't take the above PU across the LCU boundary.
if ( y % LCU_WIDTH > 0 & & y > 0 ) {
assert ( y > > 2 > 0 ) ;
above_pu = lcu ?
LCU_GET_CU_AT_PX (
lcu ,
2022-09-07 13:11:36 +00:00
SUB_SCU ( x + width - 1 ) ,
2022-04-27 09:05:32 +00:00
SUB_SCU ( y ) - 1 ) :
2022-05-30 09:11:48 +00:00
uvg_cu_array_at_const (
2022-03-24 11:34:26 +00:00
frame - > cu_array ,
2022-09-07 13:11:36 +00:00
x + width - 1 ,
2022-03-24 11:34:26 +00:00
y - 1 ) ;
}
2022-05-30 09:11:48 +00:00
uvg_intra_get_dir_luma_predictor ( x , y ,
2022-03-24 11:34:26 +00:00
intra_preds ,
cur_pu ,
left_pu , above_pu ) ;
2016-08-09 13:01:51 +00:00
2022-03-24 11:34:26 +00:00
intra_pred_mode_actual = cur_pu - > intra . mode ;
2016-08-09 13:01:51 +00:00
2022-03-24 11:34:26 +00:00
for ( int i = 0 ; i < INTRA_MPM_COUNT ; i + + ) {
if ( intra_preds [ i ] = = * intra_pred_mode ) {
mpm_preds = ( int8_t ) i ;
break ;
}
}
// Is the mode in the MPM array or not
flag = ( mpm_preds = = - 1 ) ? 0 : 1 ;
2022-08-23 10:20:57 +00:00
if ( cur_pu - > intra . multi_ref_idx = = 0 ) {
CABAC_FBITS_UPDATE ( cabac , & ( cabac - > ctx . intra_luma_mpm_flag_model ) , flag , bits , " intra_luma_mpm_flag " ) ;
2022-03-24 11:34:26 +00:00
}
// Signal index of the prediction mode in the prediction list, if it is there
if ( flag ) {
const cu_info_t * cur_pu = cur_cu ;
if ( cur_pu - > intra . multi_ref_idx = = 0 ) {
CABAC_FBITS_UPDATE ( cabac , & ( cabac - > ctx . luma_planar_model [ ( isp_mode ? 0 : 1 ) ] ) , ( mpm_preds > 0 ? 1 : 0 ) , bits , " mpm_idx_luma_planar " ) ;
2016-08-09 13:01:51 +00:00
}
2022-03-24 11:34:26 +00:00
if ( mpm_preds > 0 ) {
CABAC_BIN_EP ( cabac , ( mpm_preds > 1 ? 1 : 0 ) , " mpm_idx " ) ;
if ( cabac - > only_count ) bits + = 1 ;
}
if ( mpm_preds > 1 ) {
CABAC_BIN_EP ( cabac , ( mpm_preds > 2 ? 1 : 0 ) , " mpm_idx " ) ;
if ( cabac - > only_count ) bits + = 1 ;
}
if ( mpm_preds > 2 ) {
CABAC_BIN_EP ( cabac , ( mpm_preds > 3 ? 1 : 0 ) , " mpm_idx " ) ;
if ( cabac - > only_count ) bits + = 1 ;
}
if ( mpm_preds > 3 ) {
CABAC_BIN_EP ( cabac , ( mpm_preds > 4 ? 1 : 0 ) , " mpm_idx " ) ;
if ( cabac - > only_count ) bits + = 1 ;
}
}
else {
// Signal the actual prediction mode.
int32_t tmp_pred = * intra_pred_mode ;
uint8_t intra_preds_temp [ INTRA_MPM_COUNT + 2 ] ;
memcpy ( intra_preds_temp , intra_preds , sizeof ( int8_t ) * 3 ) ;
memcpy ( intra_preds_temp + 4 , & intra_preds [ 3 ] , sizeof ( int8_t ) * 3 ) ;
intra_preds_temp [ 3 ] = 255 ;
intra_preds_temp [ 7 ] = 255 ;
// Improvised merge sort
// Sort prediction list from lowest to highest.
if ( intra_preds_temp [ 0 ] > intra_preds_temp [ 1 ] ) SWAP ( intra_preds_temp [ 0 ] , intra_preds_temp [ 1 ] , uint8_t ) ;
if ( intra_preds_temp [ 0 ] > intra_preds_temp [ 2 ] ) SWAP ( intra_preds_temp [ 0 ] , intra_preds_temp [ 2 ] , uint8_t ) ;
if ( intra_preds_temp [ 1 ] > intra_preds_temp [ 2 ] ) SWAP ( intra_preds_temp [ 1 ] , intra_preds_temp [ 2 ] , uint8_t ) ;
if ( intra_preds_temp [ 4 ] > intra_preds_temp [ 5 ] ) SWAP ( intra_preds_temp [ 4 ] , intra_preds_temp [ 5 ] , uint8_t ) ;
if ( intra_preds_temp [ 4 ] > intra_preds_temp [ 6 ] ) SWAP ( intra_preds_temp [ 4 ] , intra_preds_temp [ 6 ] , uint8_t ) ;
if ( intra_preds_temp [ 5 ] > intra_preds_temp [ 6 ] ) SWAP ( intra_preds_temp [ 5 ] , intra_preds_temp [ 6 ] , uint8_t ) ;
// Merge two subarrays
int32_t array1 = 0 ;
int32_t array2 = 4 ;
for ( int item = 0 ; item < INTRA_MPM_COUNT ; item + + ) {
if ( intra_preds_temp [ array1 ] < intra_preds_temp [ array2 ] ) {
intra_preds [ item ] = intra_preds_temp [ array1 ] ;
array1 + + ;
2019-03-20 13:20:31 +00:00
}
2022-01-21 00:17:07 +00:00
else {
2022-03-24 11:34:26 +00:00
intra_preds [ item ] = intra_preds_temp [ array2 ] ;
array2 + + ;
2016-08-09 13:01:51 +00:00
}
}
2019-05-21 09:28:05 +00:00
2022-03-24 11:34:26 +00:00
// Reduce the index of the signaled prediction mode according to the
// prediction list, as it has been already signaled that it's not one
// of the prediction modes.
for ( int i = INTRA_MPM_COUNT - 1 ; i > = 0 ; i - - ) {
if ( tmp_pred > intra_preds [ i ] ) {
tmp_pred - - ;
2016-08-09 13:01:51 +00:00
}
}
2022-06-13 07:00:46 +00:00
uvg_cabac_encode_trunc_bin ( cabac , tmp_pred , 67 - INTRA_MPM_COUNT , bits_out ) ;
2022-03-16 10:52:18 +00:00
}
2022-04-21 11:43:27 +00:00
if ( cabac - > only_count & & bits_out ) * bits_out + = bits ;
2016-08-09 13:01:51 +00:00
}
2022-03-25 11:00:59 +00:00
2022-11-16 10:27:28 +00:00
uint8_t uvg_write_split_flag (
const encoder_state_t * const state ,
2022-06-08 07:26:56 +00:00
cabac_data_t * cabac ,
2022-11-16 10:27:28 +00:00
const cu_info_t * left_cu ,
const cu_info_t * above_cu ,
2022-09-08 12:10:54 +00:00
const cu_loc_t * const cu_loc ,
2022-11-16 10:27:28 +00:00
split_tree_t split_tree ,
2022-06-21 09:39:12 +00:00
enum uvg_tree_type tree_type ,
2022-12-06 12:23:31 +00:00
bool * is_implicit_out ,
2022-06-08 07:26:56 +00:00
double * bits_out )
2022-03-25 11:00:59 +00:00
{
double bits = 0 ;
// Implisit split flag when on border
// Exception made in VVC with flag not being implicit if the BT can be used for
// horizontal or vertical split, then this flag tells if QT or BT is used
2022-09-08 12:10:54 +00:00
const int cu_width = tree_type ! = UVG_CHROMA_T ? cu_loc - > width : cu_loc - > chroma_width ;
const int cu_height = tree_type ! = UVG_CHROMA_T ? cu_loc - > height : cu_loc - > chroma_height ;
2022-03-25 11:00:59 +00:00
2022-11-29 10:51:34 +00:00
bool can_split [ 6 ] ;
const bool is_implicit = uvg_get_possible_splits ( state , cu_loc , split_tree , tree_type , can_split ) ;
2022-03-25 11:00:59 +00:00
2022-11-29 10:51:34 +00:00
bool allow_split = can_split [ 1 ] | | can_split [ 2 ] | | can_split [ 3 ] | | can_split [ 4 ] | | can_split [ 5 ] ;
2022-03-25 11:00:59 +00:00
2022-11-18 12:00:01 +00:00
enum split_type split_flag = ( split_tree . split_tree > > ( split_tree . current_depth * 3 ) ) & 7 ;
2022-09-14 05:45:09 +00:00
2022-12-06 12:23:31 +00:00
assert ( can_split [ split_flag ] & & " Trying to write an illegal split " ) ;
// split_flag = is_implicit ? (can_split[QT_SPLIT] ? QT_SPLIT : (can_split[BT_HOR_SPLIT] ? BT_HOR_SPLIT : BT_VER_SPLIT)) : split_flag;
* is_implicit_out = is_implicit ;
2022-03-25 11:00:59 +00:00
int split_model = 0 ;
2022-11-29 10:51:34 +00:00
if ( can_split [ NO_SPLIT ] & & allow_split ) {
2022-03-25 11:00:59 +00:00
// Get left and top block split_flags and if they are present and true, increase model number
2022-09-14 05:45:09 +00:00
if ( left_cu & & ( 1 < < left_cu - > log2_height ) < cu_height ) {
2022-03-25 11:00:59 +00:00
split_model + + ;
}
2022-09-14 05:45:09 +00:00
if ( above_cu & & ( 1 < < above_cu - > log2_width ) < cu_width ) {
2022-03-25 11:00:59 +00:00
split_model + + ;
}
uint32_t split_num = 0 ;
2022-11-29 10:51:34 +00:00
if ( can_split [ QT_SPLIT ] ) split_num + = 2 ;
if ( can_split [ BT_HOR_SPLIT ] ) split_num + + ;
if ( can_split [ BT_VER_SPLIT ] ) split_num + + ;
if ( can_split [ TT_HOR_SPLIT ] ) split_num + + ;
if ( can_split [ TT_VER_SPLIT ] ) split_num + + ;
2022-03-25 11:00:59 +00:00
if ( split_num > 0 ) split_num - - ;
split_model + = 3 * ( split_num > > 1 ) ;
cabac - > cur_ctx = & ( cabac - > ctx . split_flag_model [ split_model ] ) ;
2022-05-18 06:34:31 +00:00
2022-11-16 10:27:28 +00:00
CABAC_FBITS_UPDATE ( cabac , & ( cabac - > ctx . split_flag_model [ split_model ] ) , split_flag ! = NO_SPLIT , bits , " split_cu_flag " ) ;
2022-03-25 11:00:59 +00:00
}
2022-12-06 12:23:31 +00:00
if ( ( ! is_implicit | | ( can_split [ QT_SPLIT ] & & ( can_split [ BT_HOR_SPLIT ] | | can_split [ BT_VER_SPLIT ] ) ) )
& & ( can_split [ BT_HOR_SPLIT ] | | can_split [ BT_VER_SPLIT ] | | can_split [ TT_HOR_SPLIT ] | | can_split [ TT_VER_SPLIT ] )
& & split_flag ! = NO_SPLIT ) {
2022-11-16 10:27:28 +00:00
bool qt_split = split_flag = = QT_SPLIT ;
2022-11-29 10:51:34 +00:00
if ( ( can_split [ BT_VER_SPLIT ] | | can_split [ BT_HOR_SPLIT ] | | can_split [ TT_VER_SPLIT ] | | can_split [ TT_HOR_SPLIT ] ) & & can_split [ QT_SPLIT ] ) {
2022-11-18 12:00:01 +00:00
unsigned left_qt_depth = 0 ;
unsigned top_qt_depth = 0 ;
if ( left_cu ) {
2022-11-24 07:04:42 +00:00
while ( ( ( left_cu - > split_tree > > ( left_qt_depth * 3 ) ) & 7u ) = = QT_SPLIT ) {
2022-11-18 12:00:01 +00:00
left_qt_depth + + ;
}
}
if ( above_cu ) {
2022-11-24 07:04:42 +00:00
while ( ( ( above_cu - > split_tree > > ( top_qt_depth * 3 ) ) & 7u ) = = QT_SPLIT ) {
2022-11-18 12:00:01 +00:00
top_qt_depth + + ;
}
}
split_model = ( left_cu & & ( left_qt_depth > split_tree . current_depth ) ) + ( above_cu & & ( top_qt_depth > split_tree . current_depth ) ) + ( split_tree . current_depth < 2 ? 0 : 3 ) ;
2022-11-16 10:27:28 +00:00
CABAC_FBITS_UPDATE ( cabac , & ( cabac - > ctx . qt_split_flag_model [ split_model ] ) , qt_split , bits , " qt_split_flag " ) ;
2022-03-25 11:00:59 +00:00
}
2022-11-16 10:27:28 +00:00
if ( ! qt_split ) {
const bool is_vertical = split_flag = = BT_VER_SPLIT | | split_flag = = TT_VER_SPLIT ;
2022-11-29 10:51:34 +00:00
if ( ( can_split [ BT_HOR_SPLIT ] | | can_split [ TT_HOR_SPLIT ] ) & & ( can_split [ BT_VER_SPLIT ] | | can_split [ TT_VER_SPLIT ] ) ) {
2022-11-16 10:27:28 +00:00
split_model = 0 ;
2022-11-29 10:51:34 +00:00
if ( can_split [ BT_VER_SPLIT ] + can_split [ TT_VER_SPLIT ] > can_split [ BT_HOR_SPLIT ] + can_split [ TT_HOR_SPLIT ] ) {
2022-11-16 10:27:28 +00:00
split_model = 4 ;
2022-11-29 10:51:34 +00:00
} else if ( can_split [ BT_VER_SPLIT ] + can_split [ TT_VER_SPLIT ] < can_split [ BT_HOR_SPLIT ] + can_split [ TT_HOR_SPLIT ] ) {
2022-11-16 10:27:28 +00:00
split_model = 3 ;
} else {
const int d_a = cu_width / ( above_cu ? ( 1 < < above_cu - > log2_width ) : 1 ) ;
const int d_l = cu_height / ( left_cu ? ( 1 < < left_cu - > log2_height ) : 1 ) ;
if ( d_a ! = d_l & & above_cu & & left_cu ) {
split_model = d_a < d_l ? 1 : 2 ;
}
}
CABAC_FBITS_UPDATE ( cabac , & ( cabac - > ctx . mtt_vertical_model [ split_model ] ) , is_vertical , bits , " mtt_vertical_flag " ) ;
}
2022-11-29 10:51:34 +00:00
if ( ( can_split [ BT_VER_SPLIT ] & & can_split [ TT_VER_SPLIT ] & & is_vertical ) | | ( can_split [ BT_HOR_SPLIT ] & & can_split [ TT_HOR_SPLIT ] & & ! is_vertical ) ) {
2022-11-18 12:00:01 +00:00
split_model = ( 2 * is_vertical ) + ( split_tree . mtt_depth < = 1 ) ;
2022-11-16 10:27:28 +00:00
CABAC_FBITS_UPDATE ( cabac , & ( cabac - > ctx . mtt_binary_model [ split_model ] ) ,
split_flag = = BT_VER_SPLIT | | split_flag = = BT_HOR_SPLIT , bits , " mtt_binary_flag " ) ;
}
2022-03-25 11:00:59 +00:00
}
}
2022-11-16 10:27:28 +00:00
2022-03-25 11:00:59 +00:00
if ( bits_out ) * bits_out + = bits ;
return split_flag ;
}
2022-06-06 11:49:52 +00:00
void uvg_encode_coding_tree (
encoder_state_t * const state ,
lcu_coeff_t * coeff ,
2022-09-07 13:11:36 +00:00
enum uvg_tree_type tree_type ,
const cu_loc_t * const cu_loc ,
2022-11-24 07:04:42 +00:00
const cu_loc_t * const chroma_loc ,
split_tree_t split_tree ,
bool has_chroma )
2016-08-09 13:01:51 +00:00
{
cabac_data_t * const cabac = & state - > cabac ;
2017-05-23 11:59:42 +00:00
const encoder_control_t * const ctrl = state - > encoder_control ;
2016-08-09 13:01:51 +00:00
const videoframe_t * const frame = state - > tile - > frame ;
2022-06-21 09:39:12 +00:00
const cu_array_t * used_array = tree_type ! = UVG_CHROMA_T ? frame - > cu_array : frame - > chroma_cu_array ;
2022-09-07 13:11:36 +00:00
const int cu_width = tree_type ! = UVG_CHROMA_T ? cu_loc - > width : cu_loc - > chroma_width ;
const int cu_height = tree_type ! = UVG_CHROMA_T ? cu_loc - > height : cu_loc - > chroma_height ;
2022-11-16 10:27:28 +00:00
2022-11-29 10:14:58 +00:00
const int x = tree_type ! = UVG_CHROMA_T ? cu_loc - > x : chroma_loc - > x ;
const int y = tree_type ! = UVG_CHROMA_T ? cu_loc - > y : chroma_loc - > y ;
const cu_info_t * cur_cu = uvg_cu_array_at_const ( used_array , x , y ) ;
2022-09-07 13:11:36 +00:00
const int depth = split_tree . current_depth ;
2022-08-21 09:46:07 +00:00
2017-05-23 11:59:42 +00:00
const cu_info_t * left_cu = NULL ;
if ( x > 0 ) {
2022-06-06 11:49:52 +00:00
left_cu = uvg_cu_array_at_const ( used_array , x - 1 , y ) ;
2017-05-23 11:59:42 +00:00
}
const cu_info_t * above_cu = NULL ;
if ( y > 0 ) {
2022-06-06 11:49:52 +00:00
above_cu = uvg_cu_array_at_const ( used_array , x , y - 1 ) ;
2017-05-23 11:59:42 +00:00
}
2018-08-14 07:57:32 +00:00
2016-08-21 04:36:13 +00:00
2017-05-23 11:59:42 +00:00
// Absolute coordinates
2022-06-21 09:39:12 +00:00
uint16_t abs_x = x + ( state - > tile - > offset_x > > ( tree_type = = UVG_CHROMA_T ) ) ;
uint16_t abs_y = y + ( state - > tile - > offset_y > > ( tree_type = = UVG_CHROMA_T ) ) ;
2016-08-09 13:01:51 +00:00
2022-06-21 09:39:12 +00:00
int32_t frame_width = tree_type ! = UVG_CHROMA_T ? ctrl - > in . width : ctrl - > in . width / 2 ;
int32_t frame_height = tree_type ! = UVG_CHROMA_T ? ctrl - > in . height : ctrl - > in . height / 2 ;
2022-12-06 12:23:31 +00:00
// Stop if we are outside of the frame
if ( abs_x > = frame_width | | abs_y > = frame_height ) return ;
2016-08-09 13:01:51 +00:00
2022-02-06 18:08:28 +00:00
if ( depth < = state - > frame - > max_qp_delta_depth ) {
2017-05-08 07:54:06 +00:00
state - > must_code_qp_delta = true ;
}
2016-08-09 13:01:51 +00:00
// When not in MAX_DEPTH, insert split flag and split the blocks if needed
2022-09-15 12:13:48 +00:00
if ( cu_width + cu_height > 8 ) {
2022-11-16 10:27:28 +00:00
split_tree . split_tree = cur_cu - > split_tree ;
2022-12-06 12:23:31 +00:00
bool is_implicit ;
2022-09-08 12:10:54 +00:00
const int split_flag = uvg_write_split_flag (
state ,
cabac ,
left_cu ,
2022-09-14 05:45:09 +00:00
above_cu ,
2022-11-29 10:14:58 +00:00
tree_type ! = UVG_CHROMA_T ? cu_loc : chroma_loc ,
2022-11-16 10:27:28 +00:00
split_tree ,
2022-09-08 12:10:54 +00:00
tree_type ,
2022-12-06 12:23:31 +00:00
& is_implicit ,
NULL
) ;
2019-03-20 07:07:58 +00:00
2022-12-06 12:23:31 +00:00
if ( split_flag ! = NO_SPLIT ) {
split_tree_t new_split_tree = { cur_cu - > split_tree ,
split_tree . current_depth + 1 ,
split_tree . mtt_depth + ( split_flag ! = QT_SPLIT ) ,
split_tree . implicit_mtt_depth + ( split_flag ! = QT_SPLIT & & is_implicit ) ,
0 } ;
2022-09-07 13:11:36 +00:00
2022-11-15 13:31:44 +00:00
cu_loc_t new_cu_loc [ 4 ] ;
2022-11-29 10:14:58 +00:00
cu_loc_t chroma_tree_loc ;
2022-11-24 07:04:42 +00:00
uint8_t separate_chroma = 0 ;
const int splits = uvg_get_split_locs ( cu_loc , split_flag , new_cu_loc , & separate_chroma ) ;
2022-12-08 12:52:01 +00:00
separate_chroma | = ! has_chroma ;
2022-11-15 13:31:44 +00:00
for ( int split = 0 ; split < splits ; + + split ) {
2022-11-25 11:50:22 +00:00
new_split_tree . part_index = split ;
2022-11-29 10:14:58 +00:00
if ( tree_type = = UVG_CHROMA_T ) {
chroma_tree_loc = new_cu_loc [ split ] ;
chroma_tree_loc . x > > = 1 ;
chroma_tree_loc . y > > = 1 ;
chroma_tree_loc . local_x = chroma_tree_loc . x & LCU_WIDTH_C ;
chroma_tree_loc . local_y = chroma_tree_loc . y & LCU_WIDTH_C ;
chroma_tree_loc . width > > = 1 ;
chroma_tree_loc . height > > = 1 ;
assert ( ! separate_chroma ) ;
}
2022-11-24 07:04:42 +00:00
uvg_encode_coding_tree ( state , coeff , tree_type ,
2022-11-29 10:14:58 +00:00
& new_cu_loc [ split ] ,
separate_chroma ? chroma_loc : ( tree_type = = UVG_CHROMA_T ? & chroma_tree_loc : & new_cu_loc [ split ] ) ,
2022-12-01 12:38:35 +00:00
new_split_tree , ! separate_chroma | | ( split = = splits - 1 & & has_chroma ) ) ;
2016-08-09 13:01:51 +00:00
}
return ;
}
}
2022-09-07 13:11:36 +00:00
2022-11-29 10:14:58 +00:00
DBG_YUVIEW_VALUE ( state - > frame - > poc , DBG_YUVIEW_CU_TYPE , abs_x , abs_y , cu_width , cu_height , ( cur_cu - > type = = CU_INTRA ) ? 0 : 1 ) ;
2022-12-01 12:38:35 +00:00
2022-12-08 12:52:01 +00:00
fprintf ( stderr , " %4d %4d %2d %2d %d %d \n " , x , y , cu_width , cu_height , has_chroma , cur_cu - > split_tree ) ;
2022-12-01 12:38:35 +00:00
2017-05-08 07:54:06 +00:00
if ( ctrl - > cfg . lossless ) {
2016-08-09 13:01:51 +00:00
cabac - > cur_ctx = & cabac - > ctx . cu_transquant_bypass ;
CABAC_BIN ( cabac , 1 , " cu_transquant_bypass_flag " ) ;
}
2017-05-23 11:59:42 +00:00
// Encode skip flag
2022-04-28 11:18:09 +00:00
if ( state - > frame - > slicetype ! = UVG_SLICE_I & & cu_width ! = 4 ) {
2018-09-26 09:00:18 +00:00
2017-05-23 11:59:42 +00:00
int8_t ctx_skip = 0 ;
if ( left_cu & & left_cu - > skipped ) {
2016-08-09 13:01:51 +00:00
ctx_skip + + ;
}
2017-05-23 11:59:42 +00:00
if ( above_cu & & above_cu - > skipped ) {
2016-08-09 13:01:51 +00:00
ctx_skip + + ;
}
cabac - > cur_ctx = & ( cabac - > ctx . cu_skip_flag_model [ ctx_skip ] ) ;
CABAC_BIN ( cabac , cur_cu - > skipped , " SkipFlag " ) ;
if ( cur_cu - > skipped ) {
2022-09-07 13:11:36 +00:00
DBG_PRINT_MV ( state , x , y , ( uint32_t ) cu_width , ( uint32_t ) cu_height , cur_cu ) ;
uvg_hmvp_add_mv ( state , x , y , cu_width , cu_height , cur_cu ) ;
2021-10-25 08:25:23 +00:00
int16_t num_cand = state - > encoder_control - > cfg . max_merge ;
2016-08-09 13:01:51 +00:00
if ( num_cand > 1 ) {
2017-05-23 11:59:42 +00:00
for ( int ui = 0 ; ui < num_cand - 1 ; ui + + ) {
2016-08-09 13:01:51 +00:00
int32_t symbol = ( ui ! = cur_cu - > merge_idx ) ;
if ( ui = = 0 ) {
cabac - > cur_ctx = & ( cabac - > ctx . cu_merge_idx_ext_model ) ;
CABAC_BIN ( cabac , symbol , " MergeIndex " ) ;
} else {
CABAC_BIN_EP ( cabac , symbol , " MergeIndex " ) ;
}
if ( symbol = = 0 ) {
break ;
}
}
}
2022-04-28 11:18:09 +00:00
# ifdef UVG_DEBUG_PRINT_YUVIEW_CSV
2022-11-15 13:31:44 +00:00
if ( cur_cu - > inter . mv_dir & 1 ) DBG_YUVIEW_MV ( state - > frame - > poc , DBG_YUVIEW_MVSKIP_L0 , abs_x , abs_y , cu_width , cu_height , cur_cu - > inter . mv [ 0 ] [ 0 ] , cur_cu - > inter . mv [ 0 ] [ 1 ] ) ;
if ( cur_cu - > inter . mv_dir & 2 ) DBG_YUVIEW_MV ( state - > frame - > poc , DBG_YUVIEW_MVSKIP_L1 , abs_x , abs_y , cu_width , cu_height , cur_cu - > inter . mv [ 1 ] [ 0 ] , cur_cu - > inter . mv [ 1 ] [ 1 ] ) ;
2021-11-30 20:07:01 +00:00
# endif
2017-05-08 07:54:06 +00:00
goto end ;
2016-08-09 13:01:51 +00:00
}
}
// Prediction mode
2022-09-07 13:11:36 +00:00
if ( state - > frame - > slicetype ! = UVG_SLICE_I & & cu_width ! = 4 & & cu_height ! = 4 ) {
2020-10-13 09:04:31 +00:00
int8_t ctx_predmode = 0 ;
if ( ( left_cu & & left_cu - > type = = CU_INTRA ) | | ( above_cu & & above_cu - > type = = CU_INTRA ) ) {
ctx_predmode = 1 ;
}
cabac - > cur_ctx = & ( cabac - > ctx . cu_pred_mode_model [ ctx_predmode ] ) ;
2016-08-09 13:01:51 +00:00
CABAC_BIN ( cabac , ( cur_cu - > type = = CU_INTRA ) , " PredMode " ) ;
}
2022-09-15 12:13:48 +00:00
2016-08-09 13:01:51 +00:00
2017-05-23 11:59:42 +00:00
# if ENABLE_PCM
2016-08-09 13:01:51 +00:00
// Code IPCM block
2018-07-26 08:05:31 +00:00
if ( FORCE_PCM | | cur_cu - > type = = CU_PCM ) {
2022-04-28 11:18:09 +00:00
uvg_cabac_encode_bin_trm ( cabac , 1 ) ; // IPCMFlag == 1
uvg_cabac_finish ( cabac ) ;
uvg_bitstream_add_rbsp_trailing_bits ( cabac - > stream ) ;
2018-07-26 08:05:31 +00:00
2017-05-23 11:59:42 +00:00
// PCM sample
2022-04-28 11:18:09 +00:00
uvg_pixel * base_y = & frame - > source - > y [ x + y * ctrl - > in . width ] ;
uvg_pixel * base_u = & frame - > source - > u [ x / 2 + y / 2 * ctrl - > in . width / 2 ] ;
uvg_pixel * base_v = & frame - > source - > v [ x / 2 + y / 2 * ctrl - > in . width / 2 ] ;
2017-05-23 11:59:42 +00:00
2022-04-28 11:18:09 +00:00
uvg_pixel * rec_base_y = & frame - > rec - > y [ x + y * ctrl - > in . width ] ;
uvg_pixel * rec_base_u = & frame - > rec - > u [ x / 2 + y / 2 * ctrl - > in . width / 2 ] ;
uvg_pixel * rec_base_v = & frame - > rec - > v [ x / 2 + y / 2 * ctrl - > in . width / 2 ] ;
2018-07-27 11:38:05 +00:00
2017-05-23 11:59:42 +00:00
// Luma
2022-09-08 12:10:54 +00:00
for ( unsigned y_px = 0 ; y_px < cu_height ; y_px + + ) {
for ( unsigned x_px = 0 ; x_px < cu_width ; x_px + + ) {
2022-04-28 11:18:09 +00:00
uvg_bitstream_put ( cabac - > stream , base_y [ x_px + y_px * ctrl - > in . width ] , 8 ) ;
2018-07-27 11:38:05 +00:00
rec_base_y [ x_px + y_px * ctrl - > in . width ] = base_y [ x_px + y_px * ctrl - > in . width ] ;
2017-05-23 11:59:42 +00:00
}
}
2016-08-09 13:01:51 +00:00
2017-05-23 11:59:42 +00:00
// Chroma
2022-04-28 11:18:09 +00:00
if ( ctrl - > chroma_format ! = UVG_CSP_400 ) {
2022-09-08 12:10:54 +00:00
for ( unsigned y_px = 0 ; y_px < cu_loc - > chroma_height ; y_px + + ) {
for ( unsigned x_px = 0 ; x_px < cu_loc - > chroma_width ; x_px + + ) {
2022-04-28 11:18:09 +00:00
uvg_bitstream_put ( cabac - > stream , base_u [ x_px + y_px * ( ctrl - > in . width > > 1 ) ] , 8 ) ;
2018-07-27 11:38:05 +00:00
rec_base_u [ x_px + y_px * ( ctrl - > in . width > > 1 ) ] = base_u [ x_px + y_px * ( ctrl - > in . width > > 1 ) ] ;
2016-08-09 13:01:51 +00:00
}
2017-05-23 11:59:42 +00:00
}
2022-09-08 12:10:54 +00:00
for ( unsigned y_px = 0 ; y_px < cu_loc - > chroma_height ; y_px + + ) {
for ( unsigned x_px = 0 ; x_px < cu_loc - > chroma_width ; x_px + + ) {
2022-04-28 11:18:09 +00:00
uvg_bitstream_put ( cabac - > stream , base_v [ x_px + y_px * ( ctrl - > in . width > > 1 ) ] , 8 ) ;
2018-07-27 11:38:05 +00:00
rec_base_v [ x_px + y_px * ( ctrl - > in . width > > 1 ) ] = base_v [ x_px + y_px * ( ctrl - > in . width > > 1 ) ] ;
2016-08-09 13:01:51 +00:00
}
}
}
2022-04-28 11:18:09 +00:00
uvg_cabac_start ( cabac ) ;
2018-07-26 07:33:27 +00:00
} else
2017-05-23 11:59:42 +00:00
# endif
2018-07-26 07:33:27 +00:00
if ( cur_cu - > type = = CU_INTER ) {
2022-04-28 11:18:09 +00:00
uint8_t imv_mode = UVG_IMV_OFF ;
2021-11-16 15:18:29 +00:00
bool non_zero_mvd = false ;
2022-09-06 10:45:08 +00:00
// TODO: height for non-square blocks
2022-09-07 13:11:36 +00:00
const cu_info_t * cur_pu = uvg_cu_array_at_const ( used_array , cu_loc - > x , cu_loc - > y ) ;
2018-07-26 07:33:27 +00:00
2022-09-07 13:11:36 +00:00
non_zero_mvd | = uvg_encode_inter_prediction_unit ( state , cabac , cur_pu , NULL , NULL , cu_loc ) ;
DBG_PRINT_MV ( state , x , y , cu_width , cu_height , cur_pu ) ;
uvg_hmvp_add_mv ( state , x , y , cu_width , cu_height , cur_pu ) ;
2022-09-06 10:45:08 +00:00
2018-07-26 07:33:27 +00:00
2021-11-16 15:38:38 +00:00
// imv mode, select between fullpel, half-pel and quarter-pel resolutions
2021-11-17 12:14:27 +00:00
// 0 = off, 1 = fullpel, 2 = 4-pel, 3 = half-pel
2021-11-16 15:38:38 +00:00
if ( ctrl - > cfg . amvr & & non_zero_mvd ) {
2021-11-16 15:18:29 +00:00
cabac - > cur_ctx = & ( cabac - > ctx . imv_flag [ 0 ] ) ;
2022-04-28 11:18:09 +00:00
CABAC_BIN ( cabac , ( imv_mode > UVG_IMV_OFF ) , " imv_flag " ) ;
if ( imv_mode > UVG_IMV_OFF ) {
2021-11-16 15:18:29 +00:00
cabac - > cur_ctx = & ( cabac - > ctx . imv_flag [ 4 ] ) ;
2022-04-28 11:18:09 +00:00
CABAC_BIN ( cabac , ( imv_mode < UVG_IMV_HPEL ) , " imv_flag " ) ;
if ( imv_mode < UVG_IMV_HPEL ) {
2021-11-16 15:18:29 +00:00
cabac - > cur_ctx = & ( cabac - > ctx . imv_flag [ 1 ] ) ;
2022-04-28 11:18:09 +00:00
CABAC_BIN ( cabac , ( imv_mode > UVG_IMV_FPEL ) , " imv_flag " ) ; // 1 indicates 4PEL, 0 FPEL
2021-11-16 15:18:29 +00:00
}
}
}
2018-07-26 07:33:27 +00:00
{
// Only need to signal coded block flag if not skipped or merged
// skip = no coded residual, merge = coded residual
2022-09-14 08:47:26 +00:00
const bool has_coeffs = cur_pu - > root_cbf | | cur_pu - > cbf ;
2022-09-06 10:45:08 +00:00
if ( ! cur_cu - > merged ) {
2018-07-26 07:33:27 +00:00
cabac - > cur_ctx = & ( cabac - > ctx . cu_qt_root_cbf_model ) ;
2022-09-14 08:47:26 +00:00
CABAC_BIN ( cabac , has_coeffs , " rqt_root_cbf " ) ;
2018-07-26 07:33:27 +00:00
}
// Code (possible) coeffs to bitstream
2022-09-14 08:47:26 +00:00
if ( has_coeffs ) {
2022-08-31 09:28:57 +00:00
int luma_cbf_ctx = 0 ;
2022-11-25 11:50:22 +00:00
encode_transform_coeff ( state , cu_loc , 0 , coeff , cur_cu , tree_type , true , false , & luma_cbf_ctx , cu_loc , cu_loc ) ;
2018-07-26 07:33:27 +00:00
}
2021-12-03 09:00:07 +00:00
2022-09-08 12:10:54 +00:00
encode_mts_idx ( state , cabac , cur_cu , cu_loc ) ;
2021-12-03 09:00:07 +00:00
2018-07-26 07:33:27 +00:00
}
} else if ( cur_cu - > type = = CU_INTRA ) {
2022-06-21 09:39:12 +00:00
if ( tree_type ! = UVG_CHROMA_T ) {
2022-09-07 13:11:36 +00:00
uvg_encode_intra_luma_coding_unit ( state , cabac , cur_cu , cu_loc , NULL , NULL ) ;
2022-06-06 11:49:52 +00:00
}
2022-11-25 11:50:22 +00:00
const bool is_local_dual_tree = ( chroma_loc - > width ! = cu_loc - > width | | chroma_loc - > height ! = cu_loc - > height ) ;
2022-09-13 11:38:19 +00:00
2022-03-24 10:09:14 +00:00
// Code chroma prediction mode.
2022-11-25 11:50:22 +00:00
if ( state - > encoder_control - > chroma_format ! = UVG_CSP_400
& & ( chroma_loc - > width = = cu_loc - > width & & chroma_loc - > height = = cu_loc - > height )
& & tree_type = = UVG_BOTH_T ) {
encode_chroma_intra_cu ( cabac , cur_cu , state - > encoder_control - > cfg . cclm , ! cur_cu - > intra . mip_flag ? cur_cu - > intra . mode : 0 , NULL ) ;
2022-03-24 10:09:14 +00:00
}
2022-08-31 09:28:57 +00:00
int luma_cbf_ctx = 0 ;
2022-03-24 10:09:14 +00:00
2022-06-21 09:39:12 +00:00
if ( tree_type ! = UVG_CHROMA_T ) {
2022-08-17 13:42:22 +00:00
// Cycle through sub partitions if ISP enabled.
// 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 = cur_cu - > intra . isp_mode ;
2022-09-20 09:35:16 +00:00
int split_limit = split_type = = ISP_MODE_NO_ISP ? 1 : uvg_get_isp_split_num ( cu_width , cu_height , split_type , true ) ;
2022-08-31 09:28:57 +00:00
luma_cbf_ctx = split_limit ! = 1 ? 2 : 0 ;
2022-09-13 10:27:16 +00:00
// If all first three splits have luma cbf 0, the last one must be one. Since the value ca be derived, no need to write it
bool can_skip_last_cbf = true ;
2022-08-23 14:27:57 +00:00
for ( int i = 0 ; i < split_limit ; + + i ) {
2022-08-24 13:15:03 +00:00
cu_loc_t split_loc ;
2022-09-20 09:35:16 +00:00
uvg_get_isp_split_loc ( & split_loc , x , y , cu_width , cu_height , i , split_type , true ) ;
2022-08-21 09:46:07 +00:00
2022-08-17 13:42:22 +00:00
// Check if last split to write chroma
2022-08-23 14:27:57 +00:00
bool last_split = ( i + 1 ) = = split_limit ;
2022-11-25 11:50:22 +00:00
encode_transform_coeff ( state , & split_loc ,
0 , coeff , NULL , tree_type , last_split , can_skip_last_cbf , & luma_cbf_ctx ,
cu_loc , is_local_dual_tree ? NULL : chroma_loc ) ;
2022-12-06 09:23:30 +00:00
can_skip_last_cbf & = luma_cbf_ctx = = 2 ;
2022-08-17 13:42:22 +00:00
}
2022-06-06 11:49:52 +00:00
}
2022-03-24 10:09:14 +00:00
2022-06-29 12:09:34 +00:00
if ( tree_type ! = UVG_CHROMA_T ) {
2022-11-24 07:04:42 +00:00
encode_lfnst_idx ( state , cabac , cur_cu , is_local_dual_tree & & state - > encoder_control - > chroma_format ! = UVG_CSP_400 ? UVG_LUMA_T : tree_type , COLOR_Y , cu_loc ) ;
2022-12-02 11:56:38 +00:00
encode_mts_idx ( state , cabac , cur_cu , cu_loc ) ;
2022-06-29 12:09:34 +00:00
}
2022-03-24 10:09:14 +00:00
// For 4x4 the chroma PU/TU is coded after the last
2022-11-24 07:47:36 +00:00
if ( state - > encoder_control - > chroma_format ! = UVG_CSP_400 & &
2022-11-25 11:50:22 +00:00
( ( is_local_dual_tree & &
2022-11-24 07:47:36 +00:00
has_chroma ) | | tree_type = = UVG_CHROMA_T ) & &
2022-06-21 09:39:12 +00:00
tree_type ! = UVG_LUMA_T ) {
2022-11-29 10:14:58 +00:00
int8_t luma_dir = uvg_get_co_located_luma_mode ( tree_type ! = UVG_CHROMA_T ? chroma_loc : cu_loc , cu_loc , cur_cu , NULL , frame - > cu_array , UVG_CHROMA_T ) ;
2022-11-30 08:43:12 +00:00
encode_chroma_intra_cu ( cabac , cur_cu , state - > encoder_control - > cfg . cclm & & uvg_cclm_is_allowed ( state , cu_loc , cur_cu , tree_type ) , luma_dir , NULL ) ;
2022-04-19 15:16:32 +00:00
// LFNST constraints must be reset here. Otherwise the left over values will interfere when calculating new constraints
2022-12-07 12:56:40 +00:00
cu_info_t * tmp = uvg_cu_array_at ( ( cu_array_t * ) used_array , chroma_loc - > x , chroma_loc - > y ) ;
2022-06-14 07:41:58 +00:00
tmp - > violates_lfnst_constrained_luma = false ;
tmp - > violates_lfnst_constrained_chroma = false ;
2022-04-19 15:16:32 +00:00
tmp - > lfnst_last_scan_pos = false ;
2022-12-07 12:56:40 +00:00
encode_transform_coeff ( state , chroma_loc , 1 , coeff , NULL , tree_type , true , false , & luma_cbf_ctx , chroma_loc , chroma_loc ) ;
2022-04-19 15:16:32 +00:00
// Write LFNST only once for single tree structure
2022-11-24 07:04:42 +00:00
encode_lfnst_idx ( state , cabac , tmp , is_local_dual_tree ? UVG_CHROMA_T : tree_type , COLOR_UV , chroma_loc ) ;
2022-03-24 10:09:14 +00:00
}
2018-07-26 07:33:27 +00:00
}
2017-05-23 11:59:42 +00:00
else {
// CU type not set. Should not happen.
2016-08-09 13:01:51 +00:00
assert ( 0 ) ;
exit ( 1 ) ;
}
2022-06-03 10:28:40 +00:00
if ( state - > encoder_control - > cabac_debug_file ) {
2022-06-21 12:44:00 +00:00
fprintf ( state - > encoder_control - > cabac_debug_file , " E %4d %4d %d %d " , x < < ( tree_type = = UVG_CHROMA_T ) , y < < ( tree_type = = UVG_CHROMA_T ) , depth , tree_type ) ;
2022-06-03 10:28:40 +00:00
fwrite ( & cabac - > ctx , 1 , sizeof ( cabac - > ctx ) , state - > encoder_control - > cabac_debug_file ) ;
}
2017-05-08 07:54:06 +00:00
end :
2022-09-08 12:10:54 +00:00
if ( is_last_cu_in_qg ( state , cu_loc ) ) {
2017-05-08 07:54:06 +00:00
state - > last_qp = cur_cu - > qp ;
}
2018-07-27 08:04:21 +00:00
2016-08-09 13:01:51 +00:00
}
2018-01-18 10:47:27 +00:00
2022-05-30 09:11:48 +00:00
double uvg_mock_encode_coding_unit (
2021-12-16 06:40:23 +00:00
encoder_state_t * const state ,
cabac_data_t * cabac ,
2022-09-06 10:45:08 +00:00
const cu_loc_t * const cu_loc ,
2022-11-24 13:04:57 +00:00
const cu_loc_t * const chroma_loc ,
2022-06-07 12:32:55 +00:00
lcu_t * lcu ,
cu_info_t * cur_cu ,
2022-11-16 10:27:28 +00:00
enum uvg_tree_type tree_type ,
const split_tree_t split_tree ) {
2021-12-16 06:40:23 +00:00
double bits = 0 ;
2022-03-25 11:27:34 +00:00
const encoder_control_t * const ctrl = state - > encoder_control ;
2021-12-16 06:40:23 +00:00
2022-09-06 10:45:08 +00:00
const int x = cu_loc - > x ;
const int y = cu_loc - > y ;
const uint8_t depth = 6 - uvg_g_convert_to_log2 [ cu_loc - > width ] ;
2022-09-08 12:10:54 +00:00
int x_local = cu_loc - > local_x > > ( tree_type = = UVG_CHROMA_T ) ;
int y_local = cu_loc - > local_y > > ( tree_type = = UVG_CHROMA_T ) ;
2022-11-25 11:50:22 +00:00
const bool is_separate_tree = chroma_loc = = NULL | | cu_loc - > height ! = chroma_loc - > height | | cu_loc - > width ! = chroma_loc - > width ;
2022-09-08 12:10:54 +00:00
2021-12-16 06:40:23 +00:00
const cu_info_t * left_cu = NULL , * above_cu = NULL ;
if ( x ) {
2022-06-23 05:28:20 +00:00
if ( x_local | | tree_type ! = UVG_CHROMA_T ) {
left_cu = LCU_GET_CU_AT_PX ( lcu , x_local - 1 , y_local ) ;
}
else {
2022-09-14 05:45:09 +00:00
left_cu = uvg_cu_array_at_const ( state - > tile - > frame - > chroma_cu_array , x - 1 , y ) ;
2022-06-23 05:28:20 +00:00
}
2021-12-16 06:40:23 +00:00
}
if ( y ) {
2022-06-23 05:28:20 +00:00
if ( y_local | | tree_type ! = UVG_CHROMA_T ) {
above_cu = LCU_GET_CU_AT_PX ( lcu , x_local , y_local - 1 ) ;
}
else {
2022-09-14 05:45:09 +00:00
above_cu = uvg_cu_array_at_const ( state - > tile - > frame - > chroma_cu_array , x , y - 1 ) ;
2022-06-23 05:28:20 +00:00
}
2021-12-16 06:40:23 +00:00
}
2022-03-25 11:00:59 +00:00
2021-12-16 06:40:23 +00:00
if ( depth < = state - > frame - > max_qp_delta_depth ) {
state - > must_code_qp_delta = true ;
}
// When not in MAX_DEPTH, insert split flag and split the blocks if needed
2022-09-15 12:13:48 +00:00
if ( cur_cu - > log2_height + cur_cu - > log2_width > 4 ) {
2022-12-06 12:23:31 +00:00
// We do not care about whether the split is implicit or not since there is never split here
bool is_implicit ;
2022-06-23 05:28:20 +00:00
uvg_write_split_flag (
state ,
cabac ,
left_cu ,
above_cu ,
2022-09-08 12:10:54 +00:00
cu_loc ,
2022-11-16 10:27:28 +00:00
split_tree ,
2022-12-06 12:23:31 +00:00
tree_type , & is_implicit ,
& bits
) ;
2021-12-16 06:40:23 +00:00
}
// Encode skip flag
2022-09-08 12:10:54 +00:00
if ( state - > frame - > slicetype ! = UVG_SLICE_I & & ( cu_loc - > width ! = 4 | | cu_loc - > height ! = 4 ) ) {
2021-12-16 06:40:23 +00:00
int8_t ctx_skip = 0 ;
if ( left_cu & & left_cu - > skipped ) {
ctx_skip + + ;
}
if ( above_cu & & above_cu - > skipped ) {
ctx_skip + + ;
}
CABAC_FBITS_UPDATE ( cabac , & ( cabac - > ctx . cu_skip_flag_model [ ctx_skip ] ) , cur_cu - > skipped , bits , " SkipFlag " ) ;
if ( cur_cu - > skipped ) {
int16_t num_cand = state - > encoder_control - > cfg . max_merge ;
if ( num_cand > 1 ) {
for ( int ui = 0 ; ui < num_cand - 1 ; ui + + ) {
int32_t symbol = ( ui ! = cur_cu - > merge_idx ) ;
if ( ui = = 0 ) {
CABAC_FBITS_UPDATE ( cabac , & ( cabac - > ctx . cu_merge_idx_ext_model ) , symbol , bits , " MergeIndex " ) ;
}
else {
CABAC_BIN_EP ( cabac , symbol , " MergeIndex " ) ;
if ( cabac - > only_count ) bits + = 1 ;
}
if ( symbol = = 0 ) {
break ;
}
}
}
2021-12-16 09:26:45 +00:00
return bits ;
2021-12-16 06:40:23 +00:00
}
}
// Prediction mode
2022-09-08 12:10:54 +00:00
if ( state - > frame - > slicetype ! = UVG_SLICE_I & & ( cu_loc - > width ! = 4 | | cu_loc - > height ! = 4 ) ) {
2021-12-16 06:40:23 +00:00
2022-03-21 06:42:41 +00:00
int8_t ctx_predmode = 0 ;
2021-12-16 06:40:23 +00:00
2022-03-21 06:42:41 +00:00
if ( ( left_cu & & left_cu - > type = = CU_INTRA ) | | ( above_cu & & above_cu - > type = = CU_INTRA ) ) {
ctx_predmode = 1 ;
}
CABAC_FBITS_UPDATE ( cabac , & ( cabac - > ctx . cu_pred_mode_model [ ctx_predmode ] ) , ( cur_cu - > type = = CU_INTRA ) , bits , " PredMode " ) ;
}
2021-12-16 06:40:23 +00:00
if ( cur_cu - > type = = CU_INTER ) {
2022-05-30 09:11:48 +00:00
const uint8_t imv_mode = UVG_IMV_OFF ;
2022-09-07 13:11:36 +00:00
const int non_zero_mvd = uvg_encode_inter_prediction_unit ( state , cabac , cur_cu , lcu , & bits , cu_loc ) ;
2022-03-25 11:27:34 +00:00
if ( ctrl - > cfg . amvr & & non_zero_mvd ) {
CABAC_FBITS_UPDATE ( cabac , & ( cabac - > ctx . imv_flag [ 0 ] ) , imv_mode , bits , " imv_flag " ) ;
2022-05-30 09:11:48 +00:00
if ( imv_mode > UVG_IMV_OFF ) {
2022-03-25 11:27:34 +00:00
CABAC_FBITS_UPDATE ( cabac , & ( cabac - > ctx . imv_flag [ 4 ] ) , imv_mode , bits , " imv_flag " ) ;
2022-05-30 09:11:48 +00:00
if ( imv_mode < UVG_IMV_HPEL ) {
2022-03-25 11:27:34 +00:00
CABAC_FBITS_UPDATE ( cabac , & ( cabac - > ctx . imv_flag [ 1 ] ) , imv_mode , bits , " imv_flag " ) ; // 1 indicates 4PEL, 0 FPEL
}
}
2021-12-16 06:40:23 +00:00
}
}
else if ( cur_cu - > type = = CU_INTRA ) {
2022-06-21 09:39:12 +00:00
if ( tree_type ! = UVG_CHROMA_T ) {
2022-09-07 13:11:36 +00:00
uvg_encode_intra_luma_coding_unit ( state , cabac , cur_cu , cu_loc , lcu , & bits ) ;
2022-06-07 12:32:55 +00:00
}
2022-11-24 13:04:57 +00:00
if ( ( chroma_loc | | tree_type = = UVG_CHROMA_T ) & & state - > encoder_control - > chroma_format ! = UVG_CSP_400 & & tree_type ! = UVG_LUMA_T ) {
2022-11-28 09:24:55 +00:00
int8_t luma_dir = uvg_get_co_located_luma_mode ( chroma_loc , cu_loc , cur_cu , tree_type ! = UVG_CHROMA_T ? lcu : NULL ,
tree_type = = UVG_CHROMA_T ? state - > tile - > frame - > cu_array : NULL ,
is_separate_tree ? UVG_CHROMA_T : tree_type ) ;
2022-12-02 11:56:38 +00:00
encode_chroma_intra_cu ( cabac , cur_cu , state - > encoder_control - > cfg . cclm & & uvg_cclm_is_allowed ( state , chroma_loc , cur_cu , tree_type ) , luma_dir , & bits ) ;
2022-03-31 08:30:27 +00:00
}
2021-12-16 06:40:23 +00:00
}
2022-03-25 11:27:34 +00:00
else {
assert ( 0 & & " Unset cu type " ) ;
}
2021-12-16 09:26:45 +00:00
return bits ;
2021-12-16 06:40:23 +00:00
}
2018-01-18 10:47:27 +00:00
2022-04-28 11:18:09 +00:00
void uvg_encode_mvd ( encoder_state_t * const state ,
2018-01-18 10:47:27 +00:00
cabac_data_t * cabac ,
int32_t mvd_hor ,
2021-12-16 06:40:23 +00:00
int32_t mvd_ver , double * bits_out )
2018-01-18 10:47:27 +00:00
{
const int8_t hor_abs_gr0 = mvd_hor ! = 0 ;
const int8_t ver_abs_gr0 = mvd_ver ! = 0 ;
const uint32_t mvd_hor_abs = abs ( mvd_hor ) ;
const uint32_t mvd_ver_abs = abs ( mvd_ver ) ;
cabac - > cur_ctx = & cabac - > ctx . cu_mvd_model [ 0 ] ;
2021-12-16 06:40:23 +00:00
CABAC_FBITS_UPDATE ( cabac , & cabac - > ctx . cu_mvd_model [ 0 ] , ( mvd_hor ! = 0 ) , * bits_out , " abs_mvd_greater0_flag_hor " ) ;
CABAC_FBITS_UPDATE ( cabac , & cabac - > ctx . cu_mvd_model [ 0 ] , ( mvd_ver ! = 0 ) , * bits_out , " abs_mvd_greater0_flag_ver " ) ;
2018-01-18 10:47:27 +00:00
cabac - > cur_ctx = & cabac - > ctx . cu_mvd_model [ 1 ] ;
if ( hor_abs_gr0 ) {
2021-12-16 06:40:23 +00:00
CABAC_FBITS_UPDATE ( cabac , & cabac - > ctx . cu_mvd_model [ 1 ] , ( mvd_hor_abs > 1 ) , * bits_out , " abs_mvd_greater1_flag_hor " ) ;
2018-01-18 10:47:27 +00:00
}
if ( ver_abs_gr0 ) {
2021-12-16 06:40:23 +00:00
CABAC_FBITS_UPDATE ( cabac , & cabac - > ctx . cu_mvd_model [ 1 ] , ( mvd_ver_abs > 1 ) , * bits_out , " abs_mvd_greater1_flag_ver " ) ;
2018-01-18 10:47:27 +00:00
}
if ( hor_abs_gr0 ) {
if ( mvd_hor_abs > 1 ) {
2022-05-30 09:11:48 +00:00
uint32_t bits = uvg_cabac_write_ep_ex_golomb ( state , cabac , mvd_hor_abs - 2 , 1 ) ;
2021-12-16 06:40:23 +00:00
if ( cabac - > only_count ) * bits_out + = bits ;
2018-01-18 10:47:27 +00:00
}
uint32_t mvd_hor_sign = ( mvd_hor > 0 ) ? 0 : 1 ;
CABAC_BIN_EP ( cabac , mvd_hor_sign , " mvd_sign_flag_hor " ) ;
2021-12-16 06:40:23 +00:00
if ( cabac - > only_count ) * bits_out + = 1 ;
2018-01-18 10:47:27 +00:00
}
if ( ver_abs_gr0 ) {
if ( mvd_ver_abs > 1 ) {
2022-05-30 09:11:48 +00:00
uint32_t bits = uvg_cabac_write_ep_ex_golomb ( state , cabac , mvd_ver_abs - 2 , 1 ) ;
2021-12-16 06:40:23 +00:00
if ( cabac - > only_count ) * bits_out + = bits ;
2018-01-18 10:47:27 +00:00
}
uint32_t mvd_ver_sign = mvd_ver > 0 ? 0 : 1 ;
CABAC_BIN_EP ( cabac , mvd_ver_sign , " mvd_sign_flag_ver " ) ;
2021-12-16 06:40:23 +00:00
if ( cabac - > only_count ) * bits_out + = 1 ;
2018-01-18 10:47:27 +00:00
}
}
2022-08-25 11:54:42 +00:00
/**
* \ brief Get a subset of LCU coeff array .
*
* \ param dst Destination array . Should be coeff_t [ 32 * 32 ] .
* \ param src Coeff LCU array .
* \ param lcu_x Local LCU x coordinate .
* \ param lcu_y Local LCU y coordinate .
* \ param width Block width .
* \ param height Block height .
* \ param lcu_width LCU_WIDTH for luma , LCU_WIDTH_C for chroma .
*
*/
2022-09-12 11:59:08 +00:00
void uvg_get_sub_coeff ( const coeff_t * dst , const coeff_t * const src , const int lcu_x , const int lcu_y , const int block_w , const int block_h , const int lcu_width )
2022-08-25 11:54:42 +00:00
{
// Take subset of coeff array
2022-10-03 10:13:56 +00:00
coeff_t * dst_ptr = ( coeff_t * ) dst ;
2022-08-25 11:54:42 +00:00
const coeff_t * coeff_ptr = & src [ lcu_x + lcu_y * lcu_width ] ;
for ( int j = 0 ; j < block_h ; + + j ) {
//memcpy(dst_coeff + (j * lcu_width), &coeff[j * tr_width], tr_width * sizeof(coeff_t));
2022-09-12 11:59:08 +00:00
memcpy ( & dst_ptr [ j * block_w ] , & coeff_ptr [ j * lcu_width ] , block_w * sizeof ( coeff_t ) ) ;
2022-08-25 11:54:42 +00:00
}
}