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"
2021-01-18 18:44:36 +00:00
static bool is_mts_allowed ( encoder_state_t * const state , cu_info_t * const pred_cu )
{
uint32_t ts_max_size = 1 < < 2 ; //cu.cs->sps->getLog2MaxTransformSkipBlockSize();
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;
const uint32_t cu_width = LCU_WIDTH > > pred_cu - > depth ;
const uint32_t cu_height = LCU_WIDTH > > pred_cu - > depth ;
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-05-30 18:18:39 +00:00
//mts_allowed &= !cu.ispMode; // ISP_TODO: Uncomment this when ISP is implemented.
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 ) ;
return mts_allowed ;
}
static void encode_mts_idx ( encoder_state_t * const state ,
cabac_data_t * const cabac ,
2021-07-27 06:23:29 +00:00
const cu_info_t * const pred_cu )
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
2021-11-29 12:20:09 +00:00
if ( is_mts_allowed ( state , ( cu_info_t * const ) pred_cu ) & & mts_idx ! = MTS_SKIP
2021-01-18 18:44:36 +00:00
& & ! pred_cu - > violates_mts_coeff_constraint
& & pred_cu - > mts_last_scan_pos
2022-03-16 10:52:18 +00:00
& & pred_cu - > lfnst_idx = = 0
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-05-25 10:19:32 +00:00
// ISP_TODO: move these defines to a proper place when ISP is implemented
2022-04-04 16:44:09 +00:00
// As of now, these are only needed in lfnst checks
2022-03-16 10:52:18 +00:00
# define NOT_INTRA_SUBPARTITIONS 0
# define HOR_INTRA_SUBPARTITIONS 1
# define VER_INTRA_SUBPARTITIONS 2
# define NUM_INTRA_SUBPARTITIONS_MODES 3
# define INTRA_SUBPARTITIONS_RESERVED 4
2022-04-04 16:44:09 +00:00
# define TU_1D_HOR_SPLIT 8
# define TU_1D_VER_SPLIT 9
# define MIN_TB_SIZE_X 4
# define MIN_TB_SIZE_Y 4
static int get_isp_split_dim ( const int width , const int height , const int isp_split_type )
{
bool divide_tu_in_rows = isp_split_type = = TU_1D_HOR_SPLIT ;
uint32_t split_dim_size , non_split_dim_size , partition_size , div_shift = 2 ;
if ( divide_tu_in_rows )
{
split_dim_size = height ;
non_split_dim_size = width ;
}
else
{
split_dim_size = width ;
non_split_dim_size = height ;
}
const int min_num_samples_cu = 1 < < ( ( kvz_math_floor_log2 ( MIN_TB_SIZE_Y ) < < 1 ) ) ;
const int factor_to_min_samples = non_split_dim_size < min_num_samples_cu ? min_num_samples_cu > > kvz_math_floor_log2 ( non_split_dim_size ) : 1 ;
partition_size = ( split_dim_size > > div_shift ) < factor_to_min_samples ? factor_to_min_samples : ( split_dim_size > > div_shift ) ;
assert ( ! ( kvz_math_floor_log2 ( partition_size ) + kvz_math_floor_log2 ( non_split_dim_size ) < kvz_math_floor_log2 ( min_num_samples_cu ) ) & & " Partition has less than minimum amount of samples. " ) ;
return partition_size ;
}
static bool can_use_lfnst_with_isp ( const int width , const int height , const int isp_split_type , const int color )
{
if ( color ! = COLOR_Y ) {
return false ;
}
if ( isp_split_type = = NOT_INTRA_SUBPARTITIONS ) {
return false ;
}
const int tu_width = ( isp_split_type = = HOR_INTRA_SUBPARTITIONS ) ? width : get_isp_split_dim ( width , height , TU_1D_VER_SPLIT ) ;
const int tu_height = ( isp_split_type = = HOR_INTRA_SUBPARTITIONS ) ? get_isp_split_dim ( width , height , TU_1D_HOR_SPLIT ) : height ;
if ( ! ( tu_width > = MIN_TB_SIZE_Y & & tu_height > = MIN_TB_SIZE_Y ) )
{
return false ;
}
return true ;
}
2022-03-16 10:52:18 +00:00
static bool is_lfnst_allowed ( encoder_state_t * const state , const cu_info_t * const pred_cu , const int color ,
const int width , const int height )
{
2022-03-29 11:06:39 +00:00
if ( state - > encoder_control - > cfg . lfnst & & pred_cu - > type = = CU_INTRA ) {
2022-05-25 10:19:32 +00:00
const int isp_mode = 0 ; // ISP_TODO: assign proper ISP mode when ISP is implemented
2022-04-04 16:44:09 +00:00
const int isp_split_type = 0 ;
2022-05-30 18:18:39 +00:00
const int depth = pred_cu - > depth ;
2022-03-29 11:06:39 +00:00
const int chroma_width = width > > 1 ;
const int chroma_height = height > > 1 ;
2022-05-30 18:18:39 +00:00
const int cu_width = color = = COLOR_Y | | depth = = 4 ? width : chroma_width ;
const int cu_height = color = = COLOR_Y | | depth = = 4 ? height : chroma_height ;
2022-03-29 11:06:39 +00:00
bool can_use_lfnst_with_mip = ( width > = 16 & & height > = 16 ) ;
2022-05-25 10:19:32 +00:00
bool is_sep_tree = depth = = 4 ; // TODO: if/when separate tree structure is implemented, add proper boolean here
2022-04-28 09:10:10 +00:00
bool mip_flag = pred_cu - > type = = CU_INTRA ? pred_cu - > intra . mip_flag : false ;
2022-03-29 11:06:39 +00:00
2022-04-04 16:44:09 +00:00
if ( ( isp_mode & & ! can_use_lfnst_with_isp ( width , height , isp_split_type , color ) ) | |
( pred_cu - > type = = CU_INTRA & & mip_flag & & ! can_use_lfnst_with_mip ) | |
2022-05-30 18:18:39 +00:00
( is_sep_tree & & color ! = COLOR_Y & & MIN ( cu_width , cu_height ) < 4 ) | |
2022-05-25 10:19:32 +00:00
( cu_width > TR_MAX_WIDTH | | cu_height > TR_MAX_WIDTH ) ) {
2022-03-29 11:06:39 +00:00
return false ;
}
return true ;
}
else {
2022-03-16 10:52:18 +00:00
return false ;
}
}
2022-04-19 15:16:32 +00:00
static bool encode_lfnst_idx ( encoder_state_t * const state , cabac_data_t * const cabac ,
2022-03-29 11:06:39 +00:00
const cu_info_t * const pred_cu , const int x , const int y ,
const int depth , const int color , const int width , const int height )
2022-03-16 10:52:18 +00:00
{
if ( is_lfnst_allowed ( state , pred_cu , color , width , height ) ) {
2022-04-19 15:16:32 +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-05-25 10:19:32 +00:00
bool is_separate_tree = depth = = 4 ; // TODO: if/when separate/dual tree structure is implemented, get proper value for this
2022-03-16 10:52:18 +00:00
bool luma_flag = is_separate_tree ? ( color = = COLOR_Y ? true : false ) : true ;
bool chroma_flag = is_separate_tree ? ( color ! = COLOR_Y ? true : false ) : true ;
bool non_zero_coeff_non_ts_corner_8x8 = ( luma_flag & & pred_cu - > violates_lfnst_constrained [ 0 ] ) | | ( chroma_flag & & pred_cu - > violates_lfnst_constrained [ 1 ] ) ;
2022-03-29 11:06:39 +00:00
bool is_tr_skip = false ;
const videoframe_t * const frame = state - > tile - > frame ;
//const int num_pred_units = kvz_part_mode_num_parts[pred_cu->part_size];
const int cu_width = LCU_WIDTH > > depth ;
const int tr_depth = pred_cu - > tr_depth ;
assert ( depth < = tr_depth & & " Depth greater than transform depth. This should never trigger. " ) ;
const int num_transform_units = 1 < < ( 2 * ( tr_depth - depth ) ) ;
const int tu_row_length = 1 < < ( tr_depth - depth ) ;
const int tu_width = cu_width > > ( tr_depth - depth ) ;
const int tu_height = tu_width ; // TODO: height for non-square blocks
2022-05-25 10:19:32 +00:00
const int isp_mode = 0 ; // ISP_TODO:get isp_mode from cu when ISP is implemented
2022-03-29 11:06:39 +00:00
2022-04-19 15:16:32 +00:00
// TODO: chroma transform skip
2022-05-23 11:47:25 +00:00
if ( color = = COLOR_Y ) {
2022-04-19 15:16:32 +00:00
for ( int i = 0 ; i < num_transform_units ; i + + ) {
// TODO: this works only for square blocks
const int pu_x = x + ( ( i % tu_row_length ) * tu_width ) ;
const int pu_y = y + ( ( i / tu_row_length ) * tu_height ) ;
const cu_info_t * cur_tu = kvz_cu_array_at_const ( frame - > cu_array , pu_x , pu_y ) ;
assert ( cur_tu ! = NULL & & " NULL transform unit. " ) ;
bool cbf_set = cbf_is_set_any ( cur_tu - > cbf , tr_depth ) ;
if ( cur_tu ! = NULL & & cbf_set & & cur_tu - > tr_idx = = MTS_SKIP ) {
is_tr_skip = true ;
}
2022-03-29 11:06:39 +00:00
}
}
2022-03-16 10:52:18 +00:00
2022-04-10 11:49:29 +00:00
if ( ( ! pred_cu - > lfnst_last_scan_pos & & ! isp_mode ) | | 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
}
const int lfnst_index = pred_cu - > 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 {
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 ,
2021-04-27 11:13:44 +00:00
uint8_t type ,
int8_t scan_mode ) {
//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-04-28 11:18:09 +00:00
const uint32_t log2_block_size = uvg_g_convert_to_bit [ width ] + 2 ;
const uint32_t log2_cg_size = uvg_g_log2_sbb_size [ log2_block_size ] [ log2_block_size ] [ 0 ] + uvg_g_log2_sbb_size [ log2_block_size ] [ log2_block_size ] [ 1 ] ;
const uint32_t * scan = uvg_g_sig_last_scan [ scan_mode ] [ log2_block_size - 1 ] ;
2021-04-27 11:13:44 +00:00
const uint32_t * scan_cg = g_sig_last_scan_cg [ log2_block_size - 1 ] [ scan_mode ] ;
// 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 ;
int maxCtxBins = ( width * width * 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-06-17 08:27:19 +00:00
for ( i = 0 ; i < width * width ; i + + ) {
2021-04-27 11:13:44 +00:00
if ( coeff [ scan [ i ] ] ) {
2021-12-03 15:19:19 +00:00
//scan_pos_last = i;
2021-04-27 11:13:44 +00:00
sig_coeffgroup_flag [ scan_cg [ i > > log2_cg_size ] ] = 1 ;
}
}
2021-12-03 15:17:06 +00:00
scan_cg_last = ( width * width - 1 ) > > log2_cg_size ;
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 ] ] ) {
2021-12-03 15:17:06 +00:00
CABAC_BIN ( cabac , 0 , " ts_sigGroup " ) ;
2021-04-27 11:13:44 +00:00
continue ;
}
2021-12-03 15:17:06 +00:00
CABAC_BIN ( cabac , 1 , " ts_sigGroup " ) ;
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 )
{
cabac - > cur_ctx = & 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 )
2021-04-27 11:13:44 +00:00
] ;
CABAC_BIN ( cabac , sigFlag , " sig_coeff_flag " ) ;
maxCtxBins - - ;
}
if ( sigFlag )
{
//===== encode sign's =====
int sign = curr_coeff < 0 ;
cabac - > cur_ctx = & cabac - > ctx . transform_skip_res_sign [
2022-04-28 11:18:09 +00:00
uvg_sign_ctx_id_abs_ts ( coeff , pos_x , pos_y , width , 0 )
2021-04-27 11:13:44 +00:00
] ;
CABAC_BIN ( cabac , sign , " coeff_sign_flag " ) ;
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 ;
cabac - > cur_ctx = & 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 )
2021-04-27 11:13:44 +00:00
] ;
CABAC_BIN ( cabac , gt1 , " abs_level_gtx_flag " ) ;
maxCtxBins - - ;
if ( gt1 )
{
remAbsLevel - = 1 ;
cabac - > cur_ctx = & cabac - > ctx . transform_skip_par ;
CABAC_BIN ( cabac , remAbsLevel & 1 , " par_level_flag " ) ;
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-06-17 08:27:19 +00:00
for ( i = 0 ; i < numGtBins ; i + + )
2021-04-27 11:13:44 +00:00
{
if ( absLevel > = cutoffVal )
{
unsigned gt2 = ( absLevel > = ( cutoffVal + 2 ) ) ;
cabac - > cur_ctx = & cabac - > ctx . transform_skip_gt2 [ cutoffVal > > 1 ] ;
CABAC_BIN ( cabac , gt2 , " abs_level_gtx_flag " ) ;
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-28 11:18:09 +00:00
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 " ) ;
}
}
}
}
}
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 ,
2016-08-09 13:01:51 +00:00
uint8_t lastpos_x , uint8_t lastpos_y ,
uint8_t width , uint8_t height ,
uint8_t type , uint8_t scan )
{
2022-04-28 11:18:09 +00:00
const int index_x = uvg_math_floor_log2 ( width ) ;
const int index_y = uvg_math_floor_log2 ( width ) ;
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 ] ;
uint8_t shift_x = type ? CLIP ( 0 , 2 , width > > 3 ) : ( index_x + 1 ) > > 2 ;
uint8_t shift_y = type ? CLIP ( 0 , 2 , width > > 3 ) : ( index_y + 1 ) > > 2 ;
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 ;
for ( last_x = 0 ; last_x < group_idx_x ; last_x + + ) {
2020-04-29 05:52:38 +00:00
cabac - > cur_ctx = & base_ctx_x [ ctx_offset_x + ( last_x > > shift_x ) ] ;
2016-08-09 13:01:51 +00:00
CABAC_BIN ( cabac , 1 , " last_sig_coeff_x_prefix " ) ;
}
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 ] ) ) {
2020-04-29 05:52:38 +00:00
cabac - > cur_ctx = & base_ctx_x [ ctx_offset_x + ( last_x > > shift_x ) ] ;
2016-08-09 13:01:51 +00:00
CABAC_BIN ( cabac , 0 , " last_sig_coeff_x_prefix " ) ;
}
// y prefix
2019-06-07 10:37:45 +00:00
int last_y = 0 ;
for ( last_y = 0 ; last_y < group_idx_y ; last_y + + ) {
2020-04-29 05:52:38 +00:00
cabac - > cur_ctx = & base_ctx_y [ ctx_offset_y + ( last_y > > shift_y ) ] ;
2016-08-09 13:01:51 +00:00
CABAC_BIN ( cabac , 1 , " last_sig_coeff_y_prefix " ) ;
}
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 ] ) ) {
2020-04-29 05:52:38 +00:00
cabac - > cur_ctx = & base_ctx_y [ ctx_offset_y + ( last_y > > shift_y ) ] ;
2016-08-09 13:01:51 +00:00
CABAC_BIN ( cabac , 0 , " last_sig_coeff_y_prefix " ) ;
}
// last_sig_coeff_x_suffix
if ( group_idx_x > 3 ) {
const int suffix = lastpos_x - g_min_in_group [ group_idx_x ] ;
const int bits = ( group_idx_x - 2 ) / 2 ;
CABAC_BINS_EP ( cabac , suffix , bits , " last_sig_coeff_x_suffix " ) ;
}
// last_sig_coeff_y_suffix
if ( group_idx_y > 3 ) {
const int suffix = lastpos_y - g_min_in_group [ group_idx_y ] ;
const int bits = ( group_idx_y - 2 ) / 2 ;
CABAC_BINS_EP ( cabac , suffix , bits , " last_sig_coeff_y_suffix " ) ;
}
}
2022-04-11 09:55:48 +00:00
static void encode_chroma_tu ( encoder_state_t * const state , int x , int y , int depth , const uint8_t width_c , cu_info_t * cur_pu , int8_t * scan_idx , lcu_coeff_t * coeff , uint8_t joint_chroma ) {
2022-04-21 06:46:54 +00:00
int x_local = ( ( x & ~ 7 ) > > 1 ) % LCU_WIDTH_C ;
int y_local = ( ( y & ~ 7 ) > > 1 ) % LCU_WIDTH_C ;
2021-04-27 11:13:44 +00:00
cabac_data_t * const cabac = & state - > cabac ;
2022-04-28 11:18:09 +00:00
* scan_idx = uvg_get_scan_order ( cur_pu - > type , cur_pu - > intra . mode_chroma , depth ) ;
2021-08-13 12:37:23 +00:00
if ( ! joint_chroma ) {
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 ) ] ;
if ( cbf_is_set ( cur_pu - > cbf , depth , COLOR_U ) ) {
2021-12-02 20:04:09 +00:00
if ( state - > encoder_control - > cfg . trskip_enable & & width_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
CABAC_BIN ( cabac , 0 , " transform_skip_flag " ) ;
}
2022-04-10 11:49:29 +00:00
uvg_encode_coeff_nxn ( state , & state - > cabac , coeff_u , width_c , COLOR_U , * scan_idx , cur_pu ) ;
2021-08-13 12:37:23 +00:00
}
2021-04-14 11:19:31 +00:00
2021-08-13 12:37:23 +00:00
if ( cbf_is_set ( cur_pu - > cbf , depth , COLOR_V ) ) {
2021-12-02 20:04:09 +00:00
if ( state - > encoder_control - > cfg . trskip_enable & & width_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 ;
CABAC_BIN ( cabac , 0 , " transform_skip_flag " ) ;
}
2022-04-10 11:49:29 +00:00
uvg_encode_coeff_nxn ( state , & state - > cabac , coeff_v , width_c , COLOR_V , * scan_idx , cur_pu ) ;
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 {
const coeff_t * coeff_uv = & coeff - > joint_uv [ xy_to_zorder ( LCU_WIDTH_C , x_local , y_local ) ] ;
2021-12-02 20:04:09 +00:00
if ( state - > encoder_control - > cfg . trskip_enable & & width_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-04-10 11:49:29 +00:00
uvg_encode_coeff_nxn ( state , & state - > cabac , coeff_uv , width_c , COLOR_V , * scan_idx , cur_pu ) ;
2021-08-13 12:37:23 +00:00
2021-04-14 11:19:31 +00:00
}
}
2016-08-09 13:01:51 +00:00
static void encode_transform_unit ( encoder_state_t * const state ,
2021-07-23 07:40:19 +00:00
int x , int y , int depth , bool only_chroma , lcu_coeff_t * coeff )
2016-08-09 13:01:51 +00:00
{
assert ( depth > = 1 & & depth < = MAX_PU_DEPTH ) ;
const videoframe_t * const frame = state - > tile - > frame ;
2021-04-27 11:13:44 +00:00
cabac_data_t * const cabac = & state - > cabac ;
2016-08-09 13:01:51 +00:00
const uint8_t width = LCU_WIDTH > > depth ;
const uint8_t width_c = ( depth = = MAX_PU_DEPTH ? width : width / 2 ) ;
2022-04-11 09:55:48 +00:00
cu_info_t * cur_pu = uvg_cu_array_at ( frame - > cu_array , x , y ) ;
2016-08-09 13:01:51 +00:00
2022-04-28 11:18:09 +00:00
int8_t scan_idx = uvg_get_scan_order ( cur_pu - > type , cur_pu - > intra . mode , depth ) ;
2016-08-09 13:01:51 +00:00
int cbf_y = cbf_is_set ( cur_pu - > cbf , depth , COLOR_Y ) ;
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 ;
2021-07-23 07:40:19 +00:00
const coeff_t * coeff_y = & coeff - > y [ xy_to_zorder ( LCU_WIDTH , x_local , y_local ) ] ;
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
2021-12-02 20:04:09 +00:00
if ( state - > encoder_control - > cfg . trskip_enable & & width < = ( 1 < < state - > encoder_control - > cfg . trskip_max_size ) ) {
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 " ) ;
2021-12-03 17:38:50 +00:00
DBG_YUVIEW_VALUE ( state - > frame - > poc , DBG_YUVIEW_TR_SKIP , x , y , width , width , ( cur_pu - > tr_idx = = MTS_SKIP ) ? 1 : 0 ) ;
2021-04-29 10:47:31 +00:00
}
if ( cur_pu - > tr_idx = = MTS_SKIP ) {
2022-04-28 11:18:09 +00:00
uvg_encode_ts_residual ( state , cabac , coeff_y , width , 0 , scan_idx ) ;
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 ,
width ,
0 ,
scan_idx ,
2022-04-10 11:49:29 +00:00
( cu_info_t * ) cur_pu ) ;
2021-04-27 11:13:44 +00:00
}
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 ;
2021-04-14 11:19:31 +00:00
if ( depth = = MAX_DEPTH ) {
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-04-11 09:55:48 +00:00
cur_pu = uvg_cu_array_at ( frame - > cu_array , x , y ) ;
2017-05-23 10:31:30 +00:00
}
2016-08-09 13:01:51 +00:00
}
2017-05-23 10:31:30 +00:00
bool chroma_cbf_set = cbf_is_set ( cur_pu - > cbf , depth , COLOR_U ) | |
cbf_is_set ( cur_pu - > cbf , depth , COLOR_V ) ;
2021-08-19 11:27:55 +00:00
if ( chroma_cbf_set | | joint_chroma ) {
2021-08-17 06:31:01 +00:00
encode_chroma_tu ( state , x , y , depth , width_c , cur_pu , & scan_idx , coeff , joint_chroma ) ;
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 tr_depth Depth from last CU .
* \ 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 .
*/
static void encode_transform_coeff ( encoder_state_t * const state ,
2017-05-23 10:31:30 +00:00
int32_t x ,
int32_t y ,
2016-08-09 13:01:51 +00:00
int8_t depth ,
int8_t tr_depth ,
uint8_t parent_coeff_u ,
2021-04-14 11:19:31 +00:00
uint8_t parent_coeff_v ,
2021-07-23 07:40:19 +00:00
bool only_chroma ,
lcu_coeff_t * coeff )
2016-08-09 13:01:51 +00:00
{
cabac_data_t * const cabac = & state - > cabac ;
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-04-28 11:18:09 +00:00
const cu_info_t * cur_pu = uvg_cu_array_at_const ( frame - > cu_array , x , y ) ;
2017-05-23 10:31:30 +00:00
// Round coordinates down to a multiple of 8 to get the location of the
// containing CU.
2017-05-08 07:54:06 +00:00
const int x_cu = 8 * ( x / 8 ) ;
const int y_cu = 8 * ( y / 8 ) ;
2022-05-30 09:11:48 +00:00
const cu_info_t * cur_cu = uvg_cu_array_at_const ( frame - > cu_array , x , y ) ;
2016-08-09 13:01:51 +00:00
// NxN signifies implicit transform split at the first transform level.
// There is a similar implicit split for inter, but it is only used when
// transform hierarchy is not in use.
2018-10-17 06:06:35 +00:00
//int intra_split_flag = (cur_cu->type == CU_INTRA && cur_cu->part_size == SIZE_NxN);
2016-08-09 13:01:51 +00:00
// The implicit split by intra NxN is not counted towards max_tr_depth.
2018-10-17 06:06:35 +00:00
/*
2017-06-07 09:52:16 +00:00
int max_tr_depth ;
if ( cur_cu - > type = = CU_INTRA ) {
max_tr_depth = ctrl - > cfg . tr_depth_intra + intra_split_flag ;
} else {
max_tr_depth = ctrl - > tr_depth_inter ;
}
2018-10-17 06:06:35 +00:00
*/
2016-08-09 13:01:51 +00:00
2019-07-01 10:00:43 +00:00
int8_t split = ( LCU_WIDTH > > depth > TR_MAX_WIDTH ) ;
2016-08-09 13:01:51 +00:00
const int cb_flag_y = cbf_is_set ( cur_pu - > cbf , depth , COLOR_Y ) ;
2022-04-20 05:12:42 +00:00
const int cb_flag_u = cur_pu - > joint_cb_cr ? ( cur_pu - > joint_cb_cr > > 1 ) & 1 : cbf_is_set ( cur_cu - > cbf , depth , COLOR_U ) ;
const int cb_flag_v = cur_pu - > joint_cb_cr ? cur_pu - > joint_cb_cr & 1 : cbf_is_set ( cur_cu - > cbf , depth , COLOR_V ) ;
2016-08-09 13:01:51 +00:00
// The split_transform_flag is not signaled when:
// - transform size is greater than 32 (depth == 0)
// - transform size is 4 (depth == MAX_PU_DEPTH)
// - transform depth is max
// - cu is intra NxN and it's the first split
2018-07-26 07:33:27 +00:00
//ToDo: check BMS transform split in QTBT
/*
2016-08-09 13:01:51 +00:00
if ( depth > 0 & &
depth < MAX_PU_DEPTH & &
tr_depth < max_tr_depth & &
! ( intra_split_flag & & tr_depth = = 0 ) )
{
2022-04-28 11:18:09 +00:00
cabac - > cur_ctx = & ( cabac - > ctx . trans_subdiv_model [ 5 - ( ( uvg_g_convert_to_bit [ LCU_WIDTH ] + 2 ) - depth ) ] ) ;
2016-08-09 13:01:51 +00:00
CABAC_BIN ( cabac , split , " split_transform_flag " ) ;
}
2018-07-26 07:33:27 +00:00
*/
2016-08-09 13:01:51 +00:00
// Chroma cb flags are not signaled when one of the following:
// - transform size is 4 (2x2 chroma transform doesn't exist)
// - they have already been signaled to 0 previously
// When they are not present they are inferred to be 0, except for size 4
// when the flags from previous level are used.
2022-04-28 11:18:09 +00:00
if ( state - > encoder_control - > chroma_format ! = UVG_CSP_400 & & ( depth ! = 4 | | only_chroma ) ) {
2018-08-29 07:12:07 +00:00
2019-07-01 10:00:43 +00:00
if ( ! split ) {
if ( true ) {
assert ( tr_depth < 5 ) ;
2019-08-22 07:44:47 +00:00
cabac - > cur_ctx = & ( cabac - > ctx . qt_cbf_model_cb [ 0 ] ) ;
2019-07-01 10:00:43 +00:00
CABAC_BIN ( cabac , cb_flag_u , " cbf_cb " ) ;
}
if ( true ) {
cabac - > cur_ctx = & ( cabac - > ctx . qt_cbf_model_cr [ cb_flag_u ? 1 : 0 ] ) ;
2021-08-13 12:37:23 +00:00
CABAC_BIN ( cabac , cb_flag_v , " cbf_cr " ) ;
2019-07-01 10:00:43 +00:00
}
2016-08-09 13:01:51 +00:00
}
}
if ( split ) {
2017-05-23 10:31:30 +00:00
uint8_t offset = LCU_WIDTH > > ( depth + 1 ) ;
int x2 = x + offset ;
int y2 = y + offset ;
2021-07-23 07:40:19 +00:00
encode_transform_coeff ( state , x , y , depth + 1 , tr_depth + 1 , cb_flag_u , cb_flag_v , only_chroma , coeff ) ;
encode_transform_coeff ( state , x2 , y , depth + 1 , tr_depth + 1 , cb_flag_u , cb_flag_v , only_chroma , coeff ) ;
encode_transform_coeff ( state , x , y2 , depth + 1 , tr_depth + 1 , cb_flag_u , cb_flag_v , only_chroma , coeff ) ;
encode_transform_coeff ( state , x2 , y2 , depth + 1 , tr_depth + 1 , cb_flag_u , cb_flag_v , only_chroma , coeff ) ;
2016-08-09 13:01:51 +00:00
return ;
}
// 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.
2021-04-14 11:19:31 +00:00
if ( ( cur_cu - > type = = CU_INTRA | | tr_depth > 0 | | cb_flag_u | | cb_flag_v ) & & ! only_chroma ) {
2019-08-22 07:44:47 +00:00
cabac - > cur_ctx = & ( cabac - > ctx . qt_cbf_model_luma [ 0 ] ) ;
2016-08-09 13:01:51 +00:00
CABAC_BIN ( cabac , cb_flag_y , " cbf_luma " ) ;
}
if ( cb_flag_y | cb_flag_u | cb_flag_v ) {
2022-05-05 11:28:50 +00:00
if ( state - > must_code_qp_delta & & ( only_chroma | | cb_flag_y | | depth ! = 4 ) ) {
2022-04-28 11:18:09 +00:00
const int qp_pred = uvg_get_cu_ref_qp ( state , x_cu , y_cu , state - > last_qp ) ;
2017-05-08 07:54:06 +00:00
const int qp_delta = cur_cu - > 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 )
& & cur_cu - > type = = CU_INTRA )
| | ( cb_flag_u & & cb_flag_v ) )
& & ( depth ! = 4 | | only_chroma )
& & state - > encoder_control - > cfg . jccr
) {
2021-08-13 12:37:23 +00:00
cabac - > cur_ctx = & cabac - > ctx . joint_cb_cr [ cb_flag_u * 2 + cb_flag_v - 1 ] ;
CABAC_BIN ( cabac , cur_pu - > joint_cb_cr ! = 0 , " tu_joint_cbcr_residual_flag " ) ;
}
2021-07-23 07:40:19 +00:00
encode_transform_unit ( state , x , y , depth , only_chroma , coeff ) ;
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-05-30 09:11:48 +00:00
int uvg_encode_inter_prediction_unit ( encoder_state_t * const state ,
2021-12-16 06:40:23 +00:00
cabac_data_t * const cabac ,
const cu_info_t * const cur_cu ,
int x , int y , int width , int height ,
int depth , lcu_t * lcu , double * bits_out )
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
2021-11-10 10:54:33 +00:00
if ( cur_cu - > part_size = = SIZE_2Nx2N | | ( LCU_WIDTH > > depth ) ! = 4 ) { // ToDo: limit on 4x8/8x4
2022-04-28 11:18:09 +00:00
uint32_t inter_dir_ctx = ( 7 - ( ( uvg_math_floor_log2 ( width ) + uvg_math_floor_log2 ( 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 ,
x , y , width , height ,
mv_cand , cur_cu ,
lcu , ref_list_idx ) ;
}
else {
2022-05-30 09:11:48 +00:00
uvg_inter_get_mv_cand_cua (
2018-01-18 10:47:27 +00:00
state ,
x , y , width , height ,
2021-12-13 08:43:19 +00:00
mv_cand , cur_cu , ref_list_idx
) ;
}
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-03-31 08:30:27 +00:00
static void encode_chroma_intra_cu ( cabac_data_t * const cabac , const cu_info_t * const cur_cu , const int cclm_enabled ) {
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 ;
int8_t luma_intra_dir = cur_cu - > intra . mode ;
2021-04-14 11:19:31 +00:00
2021-11-17 10:41:42 +00:00
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 ) {
cabac - > cur_ctx = & cabac - > ctx . cclm_flag ;
CABAC_BIN ( cabac , cclm_mode , " cclm_flag " ) ;
if ( cclm_mode ) {
cabac - > cur_ctx = & cabac - > ctx . cclm_model ;
CABAC_BIN ( cabac , chroma_intra_dir ! = 81 , " cclm_model_1 " ) ;
if ( chroma_intra_dir ! = 81 ) {
2021-11-18 04:55:42 +00:00
CABAC_BIN_EP ( cabac , chroma_intra_dir = = 83 , " cclm_model_2 " ) ;
2021-11-17 10:41:42 +00:00
}
return ;
}
}
2021-04-14 11:19:31 +00:00
cabac - > cur_ctx = & ( cabac - > ctx . chroma_pred_model ) ;
CABAC_BIN ( cabac , derived_mode ? 0 : 1 , " intra_chroma_pred_mode " ) ;
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 ;
}
}
/*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 " ) ;
2021-04-14 11:19:31 +00:00
//}
}
}
2022-05-30 09:11:48 +00:00
void uvg_encode_intra_luma_coding_unit ( const encoder_state_t * const state ,
2017-03-06 16:27:39 +00:00
cabac_data_t * const cabac ,
const cu_info_t * const cur_cu ,
2022-03-24 12:49:05 +00:00
int x , int y , int depth , 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
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
2019-03-20 07:07:58 +00:00
// Intra Subpartition mode
2019-05-21 09:28:05 +00:00
uint32_t width = ( LCU_WIDTH > > depth ) ;
uint32_t height = ( LCU_WIDTH > > depth ) ;
2022-04-28 11:18:09 +00:00
bool enough_samples = uvg_g_convert_to_bit [ width ] + uvg_g_convert_to_bit [ height ] > ( uvg_g_convert_to_bit [ 4 /* MIN_TB_SIZEY*/ ] < < 1 ) ;
2019-05-21 09:28:05 +00:00
uint8_t isp_mode = 0 ;
// ToDo: add height comparison
2019-07-01 10:00:43 +00:00
//isp_mode += ((width > TR_MAX_WIDTH) || !enough_samples) ? 1 : 0;
//isp_mode += ((height > TR_MAX_WIDTH) || !enough_samples) ? 2 : 0;
2019-03-20 07:07:58 +00:00
bool allow_isp = enough_samples ;
2019-06-07 10:37:45 +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-01-26 11:33:51 +00:00
const int cu_width = LCU_WIDTH > > depth ;
const int cu_height = cu_width ; // TODO: height for non-square blocks
2022-05-30 09:11:48 +00:00
uint8_t ctx_id = uvg_get_mip_flag_context ( x , y , cu_width , cu_height , 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
2021-12-13 14:01:52 +00:00
if ( multi_ref_idx ) DBG_YUVIEW_VALUE ( state - > frame - > poc , DBG_YUVIEW_MRL , x , y , width , width , multi_ref_idx ) ;
# 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
}
// ToDo: update real usage, these if clauses as such don't make any sense
2022-03-24 11:34:26 +00:00
if ( isp_mode ! = 0 & & multi_ref_idx = = 0 ) {
2019-05-21 09:28:05 +00:00
if ( isp_mode ) {
2022-03-24 11:34:26 +00:00
CABAC_FBITS_UPDATE ( cabac , & ( cabac - > ctx . intra_subpart_model [ 0 ] ) , 0 , bits , " intra_subPartitions " ) ;
2019-05-21 09:28:05 +00:00
} else {
2022-03-24 11:34:26 +00:00
CABAC_FBITS_UPDATE ( cabac , & ( cabac - > ctx . intra_subpart_model [ 0 ] ) , 1 , bits , " intra_subPartitions " ) ;
2019-05-21 09:28:05 +00:00
// ToDo: complete this if-clause
if ( isp_mode = = 3 ) {
2022-03-24 11:34:26 +00:00
CABAC_FBITS_UPDATE ( cabac , & ( cabac - > ctx . intra_subpart_model [ 0 ] ) , allow_isp - 1 , bits , " intra_subPart_ver_hor " ) ;
2019-05-21 09:28:05 +00:00
}
}
2019-03-20 07:07:58 +00:00
}
2016-08-09 13:01:51 +00:00
const int cu_width = LCU_WIDTH > > depth ;
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 ) ;
left_pu = lcu ?
LCU_GET_CU_AT_PX (
lcu ,
SUB_SCU ( x - 1 ) ,
SUB_SCU ( y + cu_width - 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 ,
x - 1 ,
y + cu_width - 1 ) ;
}
// 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 ,
SUB_SCU ( x + cu_width - 1 ) ,
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 ,
x + cu_width - 1 ,
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 ;
if ( ! ( cur_pu - > intra . multi_ref_idx | | ( isp_mode ) ) ) {
CABAC_FBITS_UPDATE ( cabac , & ( cabac - > ctx . intra_luma_mpm_flag_model ) , flag , bits , " prev_intra_luma_pred_flag " ) ;
}
// 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-04-21 11:43:27 +00:00
kvz_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
}
2018-08-27 06:18:15 +00:00
/**
2016-08-09 13:01:51 +00:00
static void encode_part_mode ( encoder_state_t * const state ,
cabac_data_t * const cabac ,
const cu_info_t * const cur_cu ,
int depth )
{
// Binarization from Table 9-34 of the HEVC spec:
//
// | log2CbSize > | log2CbSize ==
// | MinCbLog2SizeY | MinCbLog2SizeY
// -------+-------+----------+---------+-----------+----------
// pred | part | AMP | AMP | |
// mode | mode | disabled | enabled | size == 8 | size > 8
// -------+-------+----------+---------+-----------+----------
// intra | 2Nx2N | - - | 1 1
// | NxN | - - | 0 0
// -------+-------+--------------------+----------------------
// inter | 2Nx2N | 1 1 | 1 1
// | 2NxN | 01 011 | 01 01
// | Nx2N | 00 001 | 00 001
// | NxN | - - | - 000
// | 2NxnU | - 0100 | - -
// | 2NxnD | - 0101 | - -
// | nLx2N | - 0000 | - -
// | nRx2N | - 0001 | - -
// -------+-------+--------------------+----------------------
//
//
// Context indices from Table 9-37 of the HEVC spec:
//
// binIdx
// | 0 1 2 3
// ------------------------------+------------------
// log2CbSize == MinCbLog2SizeY | 0 1 2 bypass
// log2CbSize > MinCbLog2SizeY | 0 1 3 bypass
// ------------------------------+------------------
2021-12-16 06:40:23 +00:00
double bits = 0 ;
2016-08-09 13:01:51 +00:00
if ( cur_cu - > type = = CU_INTRA ) {
if ( depth = = MAX_DEPTH ) {
cabac - > cur_ctx = & ( cabac - > ctx . part_size_model [ 0 ] ) ;
if ( cur_cu - > part_size = = SIZE_2Nx2N ) {
2021-12-16 06:40:23 +00:00
CABAC_FBITS_UPDATE ( cabac , & ( cabac - > ctx . part_size_model [ 0 ] ) , 1 , bits , " part_mode 2Nx2N " ) ;
2016-08-09 13:01:51 +00:00
} else {
2021-12-16 06:40:23 +00:00
CABAC_FBITS_UPDATE ( cabac , & ( cabac - > ctx . part_size_model [ 0 ] ) , 0 , bits , " part_mode NxN " ) ;
2016-08-09 13:01:51 +00:00
}
}
} else {
cabac - > cur_ctx = & ( cabac - > ctx . part_size_model [ 0 ] ) ;
if ( cur_cu - > part_size = = SIZE_2Nx2N ) {
2021-12-16 06:40:23 +00:00
CABAC_FBITS_UPDATE ( cabac , & ( cabac - > ctx . part_size_model [ 0 ] ) , 1 , bits , " part_mode 2Nx2N " ) ;
return bits ;
2016-08-09 13:01:51 +00:00
}
2021-12-16 06:40:23 +00:00
CABAC_FBITS_UPDATE ( cabac , & ( cabac - > ctx . part_size_model [ 0 ] ) , 0 , bits , " part_mode split " ) ;
2016-08-09 13:01:51 +00:00
cabac - > cur_ctx = & ( cabac - > ctx . part_size_model [ 1 ] ) ;
if ( cur_cu - > part_size = = SIZE_2NxN | |
cur_cu - > part_size = = SIZE_2NxnU | |
cur_cu - > part_size = = SIZE_2NxnD ) {
2021-12-16 06:40:23 +00:00
CABAC_FBITS_UPDATE ( cabac , & ( cabac - > ctx . part_size_model [ 1 ] ) , 1 , bits , " part_mode vertical " ) ;
2016-08-09 13:01:51 +00:00
} else {
2021-12-16 06:40:23 +00:00
CABAC_FBITS_UPDATE ( cabac , & ( cabac - > ctx . part_size_model [ 1 ] ) , 0 , bits , " part_mode horizontal " ) ;
2016-08-09 13:01:51 +00:00
}
2017-02-05 09:59:21 +00:00
if ( state - > encoder_control - > cfg . amp_enable & & depth < MAX_DEPTH ) {
2016-08-09 13:01:51 +00:00
cabac - > cur_ctx = & ( cabac - > ctx . part_size_model [ 3 ] ) ;
if ( cur_cu - > part_size = = SIZE_2NxN | |
cur_cu - > part_size = = SIZE_Nx2N ) {
2021-12-16 06:40:23 +00:00
CABAC_FBITS_UPDATE ( cabac , & ( cabac - > ctx . part_size_model [ 3 ] ) , 1 , bits , " part_mode SMP " ) ;
return bits ;
2016-08-09 13:01:51 +00:00
}
2021-12-16 06:40:23 +00:00
CABAC_FBITS_UPDATE ( cabac , & ( cabac - > ctx . part_size_model [ 3 ] ) , 0 , bits , " part_mode AMP " ) ;
2016-08-09 13:01:51 +00:00
if ( cur_cu - > part_size = = SIZE_2NxnU | |
cur_cu - > part_size = = SIZE_nLx2N ) {
CABAC_BINS_EP ( cabac , 0 , 1 , " part_mode AMP " ) ;
2021-12-16 06:40:23 +00:00
if ( cabac - > only_count ) bits + = 1 ;
2016-08-09 13:01:51 +00:00
} else {
CABAC_BINS_EP ( cabac , 1 , 1 , " part_mode AMP " ) ;
2021-12-16 06:40:23 +00:00
if ( cabac - > only_count ) bits + = 1 ;
2016-08-09 13:01:51 +00:00
}
}
}
2021-12-16 06:40:23 +00:00
return bits ;
2016-08-09 13:01:51 +00:00
}
2018-08-27 06:18:15 +00:00
* */
2016-08-09 13:01:51 +00:00
2022-03-25 11:00:59 +00:00
2022-05-30 09:11:48 +00:00
bool uvg_write_split_flag ( const encoder_state_t * const state , cabac_data_t * cabac ,
2022-03-25 11:00:59 +00:00
const cu_info_t * left_cu , const cu_info_t * above_cu ,
uint8_t split_flag ,
int depth , int cu_width , int x , int y , double * bits_out )
{
uint16_t abs_x = x + state - > tile - > offset_x ;
uint16_t abs_y = y + state - > tile - > offset_y ;
double bits = 0 ;
const encoder_control_t * const ctrl = state - > encoder_control ;
// 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
bool no_split , allow_qt , bh_split , bv_split , th_split , tv_split ;
no_split = allow_qt = bh_split = bv_split = th_split = tv_split = true ;
if ( depth > MAX_DEPTH ) allow_qt = false ;
// ToDo: update this when btt is actually used
bool allow_btt = false ; // when mt_depth < MAX_BT_DEPTH
2022-05-30 09:11:48 +00:00
uint8_t implicit_split_mode = UVG_NO_SPLIT ;
2022-03-25 11:00:59 +00:00
//bool implicit_split = border;
bool bottom_left_available = ( ( abs_y + cu_width - 1 ) < ctrl - > in . height ) ;
bool top_right_available = ( ( abs_x + cu_width - 1 ) < ctrl - > in . width ) ;
if ( ! bottom_left_available & & ! top_right_available & & allow_qt ) {
2022-05-30 09:11:48 +00:00
implicit_split_mode = UVG_QUAD_SPLIT ;
2022-03-25 11:00:59 +00:00
}
else if ( ! bottom_left_available & & allow_btt ) {
2022-05-30 09:11:48 +00:00
implicit_split_mode = UVG_HORZ_SPLIT ;
2022-03-25 11:00:59 +00:00
}
else if ( ! top_right_available & & allow_btt ) {
2022-05-30 09:11:48 +00:00
implicit_split_mode = UVG_VERT_SPLIT ;
2022-03-25 11:00:59 +00:00
}
else if ( ! bottom_left_available | | ! top_right_available ) {
2022-05-30 09:11:48 +00:00
implicit_split_mode = UVG_QUAD_SPLIT ;
2022-03-25 11:00:59 +00:00
}
// Check split conditions
2022-05-30 09:11:48 +00:00
if ( implicit_split_mode ! = UVG_NO_SPLIT ) {
2022-03-25 11:00:59 +00:00
no_split = th_split = tv_split = false ;
2022-05-30 09:11:48 +00:00
bh_split = ( implicit_split_mode = = UVG_HORZ_SPLIT ) ;
bv_split = ( implicit_split_mode = = UVG_VERT_SPLIT ) ;
2022-03-25 11:00:59 +00:00
}
if ( ! allow_btt ) {
bh_split = bv_split = th_split = tv_split = false ;
}
bool allow_split = allow_qt | bh_split | bv_split | th_split | tv_split ;
2022-05-30 09:11:48 +00:00
split_flag | = implicit_split_mode ! = UVG_NO_SPLIT ;
2022-03-25 11:00:59 +00:00
int split_model = 0 ;
if ( no_split & & allow_split ) {
// Get left and top block split_flags and if they are present and true, increase model number
// ToDo: should use height and width to increase model, PU_GET_W() ?
if ( left_cu & & PU_GET_H ( left_cu - > part_size , LCU_WIDTH > > left_cu - > depth , 0 ) < LCU_WIDTH > > depth ) {
split_model + + ;
}
if ( above_cu & & PU_GET_W ( above_cu - > part_size , LCU_WIDTH > > above_cu - > depth , 0 ) < LCU_WIDTH > > depth ) {
split_model + + ;
}
uint32_t split_num = 0 ;
if ( allow_qt ) split_num + = 2 ;
if ( bh_split ) split_num + + ;
if ( bv_split ) split_num + + ;
if ( th_split ) split_num + + ;
if ( tv_split ) split_num + + ;
if ( split_num > 0 ) split_num - - ;
split_model + = 3 * ( split_num > > 1 ) ;
cabac - > cur_ctx = & ( cabac - > ctx . split_flag_model [ split_model ] ) ;
CABAC_FBITS_UPDATE ( cabac , & ( cabac - > ctx . split_flag_model [ split_model ] ) , split_flag , bits , " split_flag " ) ;
}
2022-05-30 09:11:48 +00:00
bool qt_split = split_flag | | implicit_split_mode = = UVG_QUAD_SPLIT ;
2022-03-25 11:00:59 +00:00
2022-05-30 09:11:48 +00:00
if ( ! ( implicit_split_mode = = UVG_NO_SPLIT ) & & ( allow_qt & & allow_btt ) ) {
2022-03-25 11:00:59 +00:00
split_model = ( left_cu & & GET_SPLITDATA ( left_cu , depth ) ) + ( above_cu & & GET_SPLITDATA ( above_cu , depth ) ) + ( depth < 2 ? 0 : 3 ) ;
CABAC_FBITS_UPDATE ( cabac , & ( cabac - > ctx . qt_split_flag_model [ split_model ] ) , qt_split , bits , " QT_split_flag " ) ;
}
// Only signal split when it is not implicit, currently only Qt split supported
2022-05-30 09:11:48 +00:00
if ( ! ( implicit_split_mode = = UVG_NO_SPLIT ) & & ! qt_split & & ( bh_split | bv_split | th_split | tv_split ) ) {
2022-03-25 11:00:59 +00:00
split_model = 0 ;
// Get left and top block split_flags and if they are present and true, increase model number
if ( left_cu & & GET_SPLITDATA ( left_cu , depth ) = = 1 ) {
split_model + + ;
}
if ( above_cu & & GET_SPLITDATA ( above_cu , depth ) = = 1 ) {
split_model + + ;
}
split_model + = ( depth > 2 ? 0 : 3 ) ;
CABAC_FBITS_UPDATE ( cabac , & ( cabac - > ctx . qt_split_flag_model [ split_model ] ) , split_flag , bits , " split_cu_mode " ) ;
}
if ( bits_out ) * bits_out + = bits ;
return split_flag ;
}
2022-04-28 11:18:09 +00:00
void uvg_encode_coding_tree ( encoder_state_t * const state ,
2017-05-23 11:59:42 +00:00
uint16_t x ,
uint16_t y ,
2021-07-23 07:40:19 +00:00
uint8_t depth ,
lcu_coeff_t * coeff )
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-04-28 11:18:09 +00:00
const cu_info_t * cur_cu = uvg_cu_array_at_const ( ( const cu_array_t * ) frame - > cu_array , x , y ) ;
2017-05-23 11:59:42 +00:00
2017-05-08 07:54:06 +00:00
const int cu_width = LCU_WIDTH > > depth ;
2022-04-21 11:43:27 +00:00
const int cu_height = cu_width ; // TODO: height for non-square blocks
2017-05-08 07:54:06 +00:00
const int half_cu = cu_width > > 1 ;
2017-05-23 11:59:42 +00:00
const cu_info_t * left_cu = NULL ;
if ( x > 0 ) {
2022-04-28 11:18:09 +00:00
left_cu = uvg_cu_array_at_const ( ( const cu_array_t * ) frame - > cu_array , x - 1 , y ) ;
2017-05-23 11:59:42 +00:00
}
const cu_info_t * above_cu = NULL ;
if ( y > 0 ) {
2022-04-28 11:18:09 +00:00
above_cu = uvg_cu_array_at_const ( ( const cu_array_t * ) frame - > cu_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
2017-05-31 10:17:59 +00:00
uint16_t abs_x = x + state - > tile - > offset_x ;
uint16_t abs_y = y + state - > tile - > offset_y ;
2016-08-09 13:01:51 +00:00
2017-05-08 07:54:06 +00:00
// Check for slice border
bool border_x = ctrl - > in . width < abs_x + cu_width ;
bool border_y = ctrl - > in . height < abs_y + cu_width ;
bool border_split_x = ctrl - > in . width > = abs_x + ( LCU_WIDTH > > MAX_DEPTH ) + half_cu ;
bool border_split_y = ctrl - > in . height > = abs_y + ( LCU_WIDTH > > MAX_DEPTH ) + half_cu ;
2017-05-23 11:59:42 +00:00
bool border = border_x | | border_y ; /*!< are we in any border CU */
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
if ( depth ! = MAX_DEPTH ) {
2018-08-29 05:23:41 +00:00
2022-05-30 09:11:48 +00:00
const int split_flag = uvg_write_split_flag ( state , cabac , left_cu , above_cu , GET_SPLITDATA ( cur_cu , depth ) , depth , cu_width , x , y , NULL ) ;
2019-03-20 07:07:58 +00:00
2016-08-09 13:01:51 +00:00
if ( split_flag | | border ) {
// Split blocks and remember to change x and y block positions
2022-04-28 11:18:09 +00:00
uvg_encode_coding_tree ( state , x , y , depth + 1 , coeff ) ;
2016-08-09 13:01:51 +00:00
if ( ! border_x | | border_split_x ) {
2022-04-28 11:18:09 +00:00
uvg_encode_coding_tree ( state , x + half_cu , y , depth + 1 , coeff ) ;
2016-08-09 13:01:51 +00:00
}
if ( ! border_y | | border_split_y ) {
2022-04-28 11:18:09 +00:00
uvg_encode_coding_tree ( state , x , y + half_cu , depth + 1 , coeff ) ;
2016-08-09 13:01:51 +00:00
}
if ( ! border | | ( border_split_x & & border_split_y ) ) {
2022-04-28 11:18:09 +00:00
uvg_encode_coding_tree ( state , x + half_cu , y + half_cu , depth + 1 , coeff ) ;
2016-08-09 13:01:51 +00:00
}
return ;
}
}
2018-07-26 13:12:11 +00:00
//ToDo: check if we can actually split
//ToDo: Implement MT split
if ( depth < MAX_PU_DEPTH )
{
2022-04-28 11:18:09 +00:00
// cabac->cur_ctx = &(cabac->ctx.trans_subdiv_model[5 - ((uvg_g_convert_to_bit[LCU_WIDTH] + 2) - depth)]);
2018-07-26 13:12:11 +00:00
// CABAC_BIN(cabac, 0, "split_transform_flag");
}
2021-12-01 12:43:34 +00:00
DBG_YUVIEW_VALUE ( state - > frame - > poc , DBG_YUVIEW_CU_TYPE , abs_x , abs_y , cu_width , cu_width , ( cur_cu - > type = = CU_INTRA ) ? 0 : 1 ) ;
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 ) {
2021-12-01 13:48:17 +00:00
DBG_PRINT_MV ( state , x , y , ( uint32_t ) cu_width , ( uint32_t ) cu_width , cur_cu ) ;
2022-04-28 11:18:09 +00:00
uvg_hmvp_add_mv ( state , x , y , ( uint32_t ) cu_width , ( uint32_t ) cu_width , 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
2021-11-30 21:24:20 +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_width , 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_width , 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-04-28 11:18:09 +00:00
if ( state - > frame - > slicetype ! = UVG_SLICE_I & & cu_width ! = 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 " ) ;
}
// part_mode
2018-07-26 07:33:27 +00:00
//encode_part_mode(state, cabac, cur_cu, depth);
2016-08-09 13:01:51 +00:00
2018-07-26 08:05:31 +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
for ( unsigned y_px = 0 ; y_px < LCU_WIDTH > > depth ; y_px + + ) {
2018-07-26 07:33:27 +00:00
for ( unsigned x_px = 0 ; x_px < LCU_WIDTH > > depth ; 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 ) {
2017-05-23 11:59:42 +00:00
for ( unsigned y_px = 0 ; y_px < LCU_WIDTH > > ( depth + 1 ) ; y_px + + ) {
for ( unsigned x_px = 0 ; x_px < LCU_WIDTH > > ( depth + 1 ) ; 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
}
for ( unsigned y_px = 0 ; y_px < LCU_WIDTH > > ( depth + 1 ) ; y_px + + ) {
for ( unsigned x_px = 0 ; x_px < LCU_WIDTH > > ( depth + 1 ) ; 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-17 12:14:27 +00:00
2022-04-28 11:18:09 +00:00
const int num_pu = uvg_part_mode_num_parts [ cur_cu - > part_size ] ;
2021-11-16 15:18:29 +00:00
bool non_zero_mvd = false ;
2018-07-26 07:33:27 +00:00
for ( int i = 0 ; i < num_pu ; + + i ) {
const int pu_x = PU_GET_X ( cur_cu - > part_size , cu_width , x , i ) ;
const int pu_y = PU_GET_Y ( cur_cu - > part_size , cu_width , y , i ) ;
const int pu_w = PU_GET_W ( cur_cu - > part_size , cu_width , i ) ;
const int pu_h = PU_GET_H ( cur_cu - > part_size , cu_width , i ) ;
2022-04-28 11:18:09 +00:00
const cu_info_t * cur_pu = uvg_cu_array_at_const ( frame - > cu_array , pu_x , pu_y ) ;
2018-07-26 07:33:27 +00:00
2022-05-30 09:11:48 +00:00
non_zero_mvd | = uvg_encode_inter_prediction_unit ( state , cabac , cur_pu , pu_x , pu_y , pu_w , pu_h , depth , NULL , NULL ) ;
2021-12-01 13:48:17 +00:00
DBG_PRINT_MV ( state , pu_x , pu_y , pu_w , pu_h , cur_pu ) ;
2022-04-28 11:18:09 +00:00
uvg_hmvp_add_mv ( state , x , y , pu_w , pu_h , cur_pu ) ;
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
{
int cbf = cbf_is_set_any ( cur_cu - > cbf , depth ) ;
// Only need to signal coded block flag if not skipped or merged
// skip = no coded residual, merge = coded residual
if ( cur_cu - > part_size ! = SIZE_2Nx2N | | ! cur_cu - > merged ) {
cabac - > cur_ctx = & ( cabac - > ctx . cu_qt_root_cbf_model ) ;
CABAC_BIN ( cabac , cbf , " rqt_root_cbf " ) ;
}
// Code (possible) coeffs to bitstream
if ( cbf ) {
2021-07-23 07:40:19 +00:00
encode_transform_coeff ( state , x , y , depth , 0 , 0 , 0 , 0 , coeff ) ;
2018-07-26 07:33:27 +00:00
}
2021-12-03 09:00:07 +00:00
encode_mts_idx ( state , cabac , cur_cu ) ;
2018-07-26 07:33:27 +00:00
}
} else if ( cur_cu - > type = = CU_INTRA ) {
2022-05-30 09:11:48 +00:00
uvg_encode_intra_luma_coding_unit ( state , cabac , cur_cu , x , y , depth , NULL , NULL ) ;
2022-03-24 10:09:14 +00:00
// Code chroma prediction mode.
2022-05-30 09:11:48 +00:00
if ( state - > encoder_control - > chroma_format ! = UVG_CSP_400 & & depth ! = 4 ) {
2022-03-31 08:30:27 +00:00
encode_chroma_intra_cu ( cabac , cur_cu , state - > encoder_control - > cfg . cclm ) ;
2022-03-24 10:09:14 +00:00
}
encode_transform_coeff ( state , x , y , depth , 0 , 0 , 0 , 0 , coeff ) ;
2022-04-21 11:43:27 +00:00
bool lfnst_written = encode_lfnst_idx ( state , cabac , cur_cu , x , y , depth , COLOR_Y , cu_width , cu_height ) ;
2022-05-20 11:24:51 +00:00
bool is_separate_tree = depth = = 4 ; // TODO: proper value for dual tree when dual tree structure is implemented
2022-03-16 10:52:18 +00:00
2022-03-24 10:09:14 +00:00
encode_mts_idx ( state , cabac , cur_cu ) ;
// For 4x4 the chroma PU/TU is coded after the last
2022-05-30 09:11:48 +00:00
if ( state - > encoder_control - > chroma_format ! = UVG_CSP_400 & & depth = = 4 & & x % 8 & & y % 8 ) {
2022-03-31 08:30:27 +00:00
encode_chroma_intra_cu ( cabac , cur_cu , state - > encoder_control - > cfg . cclm ) ;
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-04-22 10:47:09 +00:00
cu_info_t * tmp = kvz_cu_array_at ( frame - > cu_array , x , y ) ;
2022-04-19 15:16:32 +00:00
tmp - > violates_lfnst_constrained [ 0 ] = false ;
tmp - > violates_lfnst_constrained [ 1 ] = false ;
tmp - > lfnst_last_scan_pos = false ;
encode_transform_coeff ( state , x , y , depth , 0 , 0 , 0 , 1 , coeff ) ;
// Write LFNST only once for single tree structure
2022-05-20 11:24:51 +00:00
if ( ! lfnst_written | | is_separate_tree ) {
2022-04-22 10:47:09 +00:00
encode_lfnst_idx ( state , cabac , tmp , x , y , depth , COLOR_UV , cu_width , cu_height ) ;
2022-04-19 15:16:32 +00:00
}
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 ) ;
}
2017-05-08 07:54:06 +00:00
end :
if ( is_last_cu_in_qg ( state , x , y , depth ) ) {
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 ,
int x , int y , int depth ,
2021-12-16 09:26:45 +00:00
lcu_t * lcu , cu_info_t * cur_cu ) {
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
int x_local = SUB_SCU ( x ) ;
int y_local = SUB_SCU ( y ) ;
const int cu_width = LCU_WIDTH > > depth ;
2021-12-16 09:26:45 +00:00
2021-12-16 06:40:23 +00:00
const cu_info_t * left_cu = NULL , * above_cu = NULL ;
if ( x ) {
left_cu = LCU_GET_CU_AT_PX ( lcu , x_local - 1 , y_local ) ;
}
if ( y ) {
above_cu = LCU_GET_CU_AT_PX ( lcu , x_local , y_local - 1 ) ;
}
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
if ( depth ! = MAX_DEPTH ) {
2022-05-30 09:11:48 +00:00
uvg_write_split_flag ( state , cabac , left_cu , above_cu , 0 , depth , cu_width , x , y , & bits ) ;
2021-12-16 06:40:23 +00:00
}
// Encode skip flag
2022-05-30 09:11:48 +00:00
if ( state - > frame - > slicetype ! = UVG_SLICE_I & & cu_width ! = 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-05-30 09:11:48 +00:00
if ( state - > frame - > slicetype ! = UVG_SLICE_I & & cu_width ! = 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 ;
const int non_zero_mvd = uvg_encode_inter_prediction_unit ( state , cabac , cur_cu , x , y , cu_width , cu_width , depth , lcu , & bits ) ;
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-05-30 09:11:48 +00:00
uvg_encode_intra_luma_coding_unit ( state , cabac , cur_cu , x , y , depth , lcu , & bits ) ;
if ( ( depth ! = 4 | | ( x % 8 ! = 0 & & y % 8 ! = 0 ) ) & & state - > encoder_control - > chroma_format ! = UVG_CSP_400 ) {
2022-03-31 08:30:27 +00:00
encode_chroma_intra_cu ( cabac , cur_cu , state - > encoder_control - > cfg . cclm ) ;
}
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
}
}