Newer
Older

Karsten Suehring
committed
if( imv == 2 )//IMV_4PEL
{
CHECK( (horMvd % 4) != 0 && (verMvd % 4) != 0, "IMV: MVD is not a multiple of 16" );

Karsten Suehring
committed
horMvd >>= 2;
verMvd >>= 2;
}

Karsten Suehring
committed
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
}
unsigned horAbs = unsigned( horMvd < 0 ? -horMvd : horMvd );
unsigned verAbs = unsigned( verMvd < 0 ? -verMvd : verMvd );
// abs_mvd_greater0_flag[ 0 | 1 ]
m_BinEncoder.encodeBin( (horAbs > 0), Ctx::Mvd() );
m_BinEncoder.encodeBin( (verAbs > 0), Ctx::Mvd() );
// abs_mvd_greater1_flag[ 0 | 1 ]
if( horAbs > 0 )
{
m_BinEncoder.encodeBin( (horAbs > 1), Ctx::Mvd(1) );
}
if( verAbs > 0 )
{
m_BinEncoder.encodeBin( (verAbs > 1), Ctx::Mvd(1) );
}
// abs_mvd_minus2[ 0 | 1 ] and mvd_sign_flag[ 0 | 1 ]
if( horAbs > 0 )
{
if( horAbs > 1 )
{
exp_golomb_eqprob( horAbs - 2, 1 );
}
m_BinEncoder.encodeBinEP( (horMvd < 0) );
}
if( verAbs > 0 )
{
if( verAbs > 1 )
{
exp_golomb_eqprob( verAbs - 2, 1 );
}
m_BinEncoder.encodeBinEP( (verMvd < 0) );
}
}
//================================================================================
// clause 7.3.8.10
//--------------------------------------------------------------------------------
// void transform_unit ( tu, cuCtx, chromaCbfs )
// void cu_qp_delta ( cu )
// void cu_chroma_qp_offset ( cu )
//================================================================================
#if JVET_O0596_CBF_SIG_ALIGN_TO_SPEC
void CABACWriter::transform_unit( const TransformUnit& tu, CUCtx& cuCtx, Partitioner& partitioner, const int subTuCounter)
#else

Karsten Suehring
committed
void CABACWriter::transform_unit( const TransformUnit& tu, CUCtx& cuCtx, ChromaCbfs& chromaCbfs )
#endif

Karsten Suehring
committed
{
#if JVET_O0596_CBF_SIG_ALIGN_TO_SPEC
const CodingStructure& cs = *tu.cs;
const CodingUnit& cu = *tu.cu;
const UnitArea& area = partitioner.currArea();
const unsigned trDepth = partitioner.currTrDepth;
const bool chromaCbfISP = area.blocks[COMPONENT_Cb].valid() && cu.ispMode;
ChromaCbfs chromaCbfs;
CHECK(tu.depth != trDepth, " transform unit should be not be futher partitioned");
// cbf_cb & cbf_cr
#if JVET_O0050_LOCAL_DUAL_TREE
if (area.chromaFormat != CHROMA_400 && area.blocks[COMPONENT_Cb].valid() && (!cu.isSepTree() || partitioner.chType == CHANNEL_TYPE_CHROMA) && (!cu.ispMode || chromaCbfISP))
#else
if (area.chromaFormat != CHROMA_400 && area.blocks[COMPONENT_Cb].valid() && (!CS::isDualITree(cs) || partitioner.chType == CHANNEL_TYPE_CHROMA) && (!cu.ispMode || chromaCbfISP))
{
{
unsigned cbfDepth = chromaCbfISP ? trDepth - 1 : trDepth;
{
chromaCbfs.Cb = TU::getCbfAtDepth(tu, COMPONENT_Cb, trDepth);
//if (!(cu.sbtInfo && trDepth == 1))
if (!(cu.sbtInfo && tu.noResidual))
cbf_comp(cs, chromaCbfs.Cb, area.blocks[COMPONENT_Cb], cbfDepth);
}
{
chromaCbfs.Cr = TU::getCbfAtDepth(tu, COMPONENT_Cr, trDepth);
//if (!(cu.sbtInfo && trDepth == 1))
if (!(cu.sbtInfo && tu.noResidual))
cbf_comp(cs, chromaCbfs.Cr, area.blocks[COMPONENT_Cr], cbfDepth, chromaCbfs.Cb);
}
}
}
#if JVET_O0050_LOCAL_DUAL_TREE
else if (cu.isSepTree())
#else
else if (CS::isDualITree(cs))
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
{
chromaCbfs = ChromaCbfs(false);
}
if (!isChroma(partitioner.chType))
{
if (!CU::isIntra(cu) && trDepth == 0 && !chromaCbfs.sigChroma(area.chromaFormat))
{
CHECK(!TU::getCbfAtDepth(tu, COMPONENT_Y, trDepth), "Luma cbf must be true for inter units with no chroma coeffs");
}
else if (cu.sbtInfo && tu.noResidual)
{
CHECK(TU::getCbfAtDepth(tu, COMPONENT_Y, trDepth), "Luma cbf must be false for inter sbt no-residual tu");
}
else if (cu.sbtInfo && !chromaCbfs.sigChroma(area.chromaFormat))
{
assert(!tu.noResidual);
CHECK(!TU::getCbfAtDepth(tu, COMPONENT_Y, trDepth), "Luma cbf must be true for inter sbt residual tu");
}
else
{
bool previousCbf = false;
bool rootCbfSoFar = false;
bool lastCbfIsInferred = false;
if (cu.ispMode)
{
uint32_t nTus = cu.ispMode == HOR_INTRA_SUBPARTITIONS ? cu.lheight() >> g_aucLog2[tu.lheight()] : cu.lwidth() >> g_aucLog2[tu.lwidth()];
if (subTuCounter == nTus - 1)
{
TransformUnit* tuPointer = cu.firstTU;
for (int tuIdx = 0; tuIdx < subTuCounter; tuIdx++)
{
rootCbfSoFar |= TU::getCbfAtDepth(*tuPointer, COMPONENT_Y, trDepth);
tuPointer = tuPointer->next;
}
if (!rootCbfSoFar)
{
lastCbfIsInferred = true;
}
}
if (!lastCbfIsInferred)
{
previousCbf = TU::getPrevTuCbfAtDepth(tu, COMPONENT_Y, partitioner.currTrDepth);
}
}
if (!lastCbfIsInferred)
{
cbf_comp(cs, TU::getCbfAtDepth(tu, COMPONENT_Y, trDepth), tu.Y(), trDepth, previousCbf, cu.ispMode);
}
}
}
#else

Karsten Suehring
committed
CodingUnit& cu = *tu.cu;
#endif

Karsten Suehring
committed
bool lumaOnly = ( cu.chromaFormat == CHROMA_400 || !tu.blocks[COMPONENT_Cb].valid() );
bool cbf[3] = { TU::getCbf( tu, COMPONENT_Y ), chromaCbfs.Cb, chromaCbfs.Cr };
bool cbfLuma = ( cbf[ COMPONENT_Y ] != 0 );
bool cbfChroma = false;
Santiago de Luxán Hernández
committed
if( !lumaOnly )

Karsten Suehring
committed
{
if( tu.blocks[COMPONENT_Cb].valid() )
{
cbf [ COMPONENT_Cb ] = TU::getCbf( tu, COMPONENT_Cb );
cbf [ COMPONENT_Cr ] = TU::getCbf( tu, COMPONENT_Cr );
}
cbfChroma = ( cbf[ COMPONENT_Cb ] || cbf[ COMPONENT_Cr ] );
}
Brian Heng
committed
#if JVET_O0046_DQ_SIGNALLING
if( ( cu.lwidth() > 64 || cu.lheight() > 64 || cbfLuma || cbfChroma ) &&
if( ( cbfLuma || cbfChroma ) &&
Brian Heng
committed
#endif
#if JVET_O0050_LOCAL_DUAL_TREE
(!CS::isDualITree(*tu.cs) || isLuma(tu.chType)) )

Karsten Suehring
committed
{
if( cu.cs->pps->getUseDQP() && !cuCtx.isDQPCoded )
{
cu_qp_delta(cu, cuCtx.qp, cu.qp);
cuCtx.qp = cu.qp;
cuCtx.isDQPCoded = true;

Karsten Suehring
committed
}
#if JVET_O1168_CU_CHROMA_QP_OFFSET
if (cu.cs->slice->getUseChromaQpAdj() && cbfChroma && !cuCtx.isChromaQpAdjCoded)
#else

Karsten Suehring
committed
if( cu.cs->slice->getUseChromaQpAdj() && cbfChroma && !cu.transQuantBypass && !cuCtx.isChromaQpAdjCoded )

Karsten Suehring
committed
{
cu_chroma_qp_offset( cu );
cuCtx.isChromaQpAdjCoded = true;
}
#if JVET_O0105_ICT
if( !lumaOnly )
{
joint_cb_cr( tu, ( cbf[COMPONENT_Cb] ? 2 : 0 ) + ( cbf[COMPONENT_Cr] ? 1 : 0 ) );
}
#endif

Karsten Suehring
committed
if( cbfLuma )
{
#if JVET_O0094_LFNST_ZERO_PRIM_COEFFS || JVET_O0472_LFNST_SIGNALLING_LAST_SCAN_POS
residual_coding( tu, COMPONENT_Y, &cuCtx );
#else

Karsten Suehring
committed
residual_coding( tu, COMPONENT_Y );

Karsten Suehring
committed
}
if( !lumaOnly )
{
for( ComponentID compID = COMPONENT_Cb; compID <= COMPONENT_Cr; compID = ComponentID( compID + 1 ) )
{
if( TU::hasCrossCompPredInfo( tu, compID ) )
{
cross_comp_pred( tu, compID );
}
if( cbf[ compID ] )
{
#if JVET_O0094_LFNST_ZERO_PRIM_COEFFS || JVET_O0472_LFNST_SIGNALLING_LAST_SCAN_POS
residual_coding( tu, compID, &cuCtx );
#else

Karsten Suehring
committed
residual_coding( tu, compID );

Karsten Suehring
committed
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
}
}
}
}
void CABACWriter::cu_qp_delta( const CodingUnit& cu, int predQP, const int8_t qp )
{
CHECK(!( predQP != std::numeric_limits<int>::max()), "Unspecified error");
int DQp = qp - predQP;
int qpBdOffsetY = cu.cs->sps->getQpBDOffset( CHANNEL_TYPE_LUMA );
DQp = ( DQp + (MAX_QP + 1) + (MAX_QP + 1) / 2 + qpBdOffsetY + (qpBdOffsetY / 2)) % ((MAX_QP + 1) + qpBdOffsetY) - (MAX_QP + 1) / 2 - (qpBdOffsetY / 2);
unsigned absDQP = unsigned( DQp < 0 ? -DQp : DQp );
unsigned unaryDQP = std::min<unsigned>( absDQP, CU_DQP_TU_CMAX );
unary_max_symbol( unaryDQP, Ctx::DeltaQP(), Ctx::DeltaQP(1), CU_DQP_TU_CMAX );
if( absDQP >= CU_DQP_TU_CMAX )
{
exp_golomb_eqprob( absDQP - CU_DQP_TU_CMAX, CU_DQP_EG_k );
}
if( absDQP > 0 )
{
m_BinEncoder.encodeBinEP( DQp < 0 );
}
DTRACE_COND( ( isEncoding() ), g_trace_ctx, D_DQP, "x=%d, y=%d, d=%d, pred_qp=%d, DQp=%d, qp=%d\n", cu.blocks[cu.chType].lumaPos().x, cu.blocks[cu.chType].lumaPos().y, cu.qtDepth, predQP, DQp, qp );
}
void CABACWriter::cu_chroma_qp_offset( const CodingUnit& cu )
{
// cu_chroma_qp_offset_flag
unsigned qpAdj = cu.chromaQpAdj;
if( qpAdj == 0 )
{
m_BinEncoder.encodeBin( 0, Ctx::ChromaQpAdjFlag() );
}
else
{
m_BinEncoder.encodeBin( 1, Ctx::ChromaQpAdjFlag() );
int length = cu.cs->pps->getPpsRangeExtension().getChromaQpOffsetListLen();
if( length > 1 )
{
unary_max_symbol( qpAdj-1, Ctx::ChromaQpAdjIdc(), Ctx::ChromaQpAdjIdc(), length-1 );
}
}
}
//================================================================================
// clause 7.3.8.11
//--------------------------------------------------------------------------------
// void residual_coding ( tu, compID )
// void transform_skip_flag ( tu, compID )
// void explicit_rdpcm_mode ( tu, compID )
// void last_sig_coeff ( coeffCtx )
// void residual_coding_subblock( coeffCtx )
//================================================================================
#if JVET_O0105_ICT
void CABACWriter::joint_cb_cr( const TransformUnit& tu, const int cbfMask )
{
#if JVET_O0376_SPS_JOINTCBCR_FLAG
if ( !tu.cu->slice->getSPS()->getJointCbCrEnabledFlag() )
CHECK( tu.jointCbCr && tu.jointCbCr != cbfMask, "wrong value of jointCbCr (" << (int)tu.jointCbCr << " vs " << (int)cbfMask << ")" );
#if JVET_O0543_ICT_ICU_ONLY
if( ( CU::isIntra( *tu.cu ) && cbfMask ) || ( cbfMask == 3 ) )
#else
if( cbfMask )
#endif
{
m_BinEncoder.encodeBin( tu.jointCbCr ? 1 : 0, Ctx::JointCbCrFlag( cbfMask - 1 ) );
}
}
#else
void CABACWriter::joint_cb_cr( const TransformUnit& tu )
{
m_BinEncoder.encodeBin( tu.jointCbCr ? 1 : 0, Ctx::JointCbCrFlag( 0 ) );
}
#if JVET_O0094_LFNST_ZERO_PRIM_COEFFS || JVET_O0472_LFNST_SIGNALLING_LAST_SCAN_POS
void CABACWriter::residual_coding( const TransformUnit& tu, ComponentID compID, CUCtx* cuCtx )
#else
void CABACWriter::residual_coding( const TransformUnit& tu, ComponentID compID)
#endif

Karsten Suehring
committed
{
const CodingUnit& cu = *tu.cu;
DTRACE( g_trace_ctx, D_SYNTAX, "residual_coding() etype=%d pos=(%d,%d) size=%dx%d predMode=%d\n", tu.blocks[compID].compID, tu.blocks[compID].x, tu.blocks[compID].y, tu.blocks[compID].width, tu.blocks[compID].height, cu.predMode );
#if JVET_O0105_ICT
if( compID == COMPONENT_Cr && tu.jointCbCr == 3 )
return;
#else
// Joint Cb-Cr residual mode is signalled if both Cb and Cr cbfs are true
if ( compID == COMPONENT_Cr && TU::getCbf( tu, COMPONENT_Cb ) )
{
joint_cb_cr( tu );
// No Cr residual in bitstream in joint Cb-Cr residual mode
if ( tu.jointCbCr )
return;
}

Karsten Suehring
committed
// code transform skip and explicit rdpcm mode

Karsten Suehring
committed
explicit_rdpcm_mode( tu, compID );
if( isLuma( compID ) && ( tu.mtsIdx == MTS_SKIP || tu.cu->bdpcmMode ) )
{
residual_codingTS( tu, compID );
return;
}

Karsten Suehring
committed
// determine sign hiding
bool signHiding = ( cu.cs->slice->getSignDataHidingEnabledFlag() && !cu.transQuantBypass && tu.rdpcm[compID] == RDPCM_OFF );
if( signHiding && CU::isIntra(cu) && CU::isRDPCMEnabled(cu) && tu.mtsIdx==MTS_SKIP )

Karsten Suehring
committed
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
{
const ChannelType chType = toChannelType( compID );
const unsigned intraMode = PU::getFinalIntraMode( *cu.cs->getPU( tu.blocks[compID].pos(), chType ), chType );
if( intraMode == HOR_IDX || intraMode == VER_IDX )
{
signHiding = false;
}
}
// init coeff coding context
CoeffCodingContext cctx ( tu, compID, signHiding );
const TCoeff* coeff = tu.getCoeffs( compID ).buf;
// determine and set last coeff position and sig group flags
int scanPosLast = -1;
std::bitset<MLS_GRP_NUM> sigGroupFlags;
for( int scanPos = 0; scanPos < cctx.maxNumCoeff(); scanPos++)
{
unsigned blkPos = cctx.blockPos( scanPos );
if( coeff[blkPos] )
{
scanPosLast = scanPos;
sigGroupFlags.set( scanPos >> cctx.log2CGSize() );
}
}
CHECK( scanPosLast < 0, "Coefficient coding called for empty TU" );
cctx.setScanPosLast(scanPosLast);
if( cuCtx && tu.mtsIdx != MTS_SKIP && tu.blocks[ compID ].height >= 4 && tu.blocks[ compID ].width >= 4 )
{
const int maxLfnstPos = ((tu.blocks[compID].height == 4 && tu.blocks[compID].width == 4) || (tu.blocks[compID].height == 8 && tu.blocks[compID].width == 8)) ? 7 : 15;
cuCtx->violatesLfnstConstrained[ toChannelType(compID) ] |= cctx.scanPosLast() > maxLfnstPos;
}
#endif
#if JVET_O0472_LFNST_SIGNALLING_LAST_SCAN_POS
if( cuCtx && tu.mtsIdx != MTS_SKIP && tu.blocks[ compID ].height >= 4 && tu.blocks[ compID ].width >= 4 )
{
const int lfnstLastScanPosTh = isLuma( compID ) ? LFNST_LAST_SIG_LUMA : LFNST_LAST_SIG_CHROMA;
cuCtx->lfnstLastScanPos |= cctx.scanPosLast() >= lfnstLastScanPosTh;

Karsten Suehring
committed
// code last coeff position

Karsten Suehring
committed
// code subblocks
const int stateTab = ( tu.cs->slice->getDepQuantEnabledFlag() ? 32040 : 0 );
int state = 0;
#if JVET_O0052_TU_LEVEL_CTX_CODED_BIN_CONSTRAINT
int ctxBinSampleRatio = (compID == COMPONENT_Y) ? MAX_TU_LEVEL_CTX_CODED_BIN_CONSTRAINT_LUMA : MAX_TU_LEVEL_CTX_CODED_BIN_CONSTRAINT_CHROMA;
cctx.regBinLimit = (tu.getTbAreaAfterCoefZeroOut(compID) * ctxBinSampleRatio) >> 4;
#endif

Karsten Suehring
committed
for( int subSetId = ( cctx.scanPosLast() >> cctx.log2CGSize() ); subSetId >= 0; subSetId--)
{
cctx.initSubblock ( subSetId, sigGroupFlags[subSetId] );
if( ( tu.mtsIdx > MTS_SKIP || ( tu.cu->sbtInfo != 0 && tu.blocks[ compID ].height <= 32 && tu.blocks[ compID ].width <= 32 ) ) && !tu.cu->transQuantBypass && compID == COMPONENT_Y )
{
if( ( tu.blocks[ compID ].height == 32 && cctx.cgPosY() >= ( 16 >> cctx.log2CGHeight() ) )
|| ( tu.blocks[ compID ].width == 32 && cctx.cgPosX() >= ( 16 >> cctx.log2CGWidth() ) ) )
{
continue;
}
}
residual_coding_subblock( cctx, coeff, stateTab, state );

Karsten Suehring
committed
}
}
void CABACWriter::mts_coding( const TransformUnit& tu, ComponentID compID )
{
const bool tsAllowed = TU::isTSAllowed ( tu, compID );
const bool mtsAllowed = TU::isMTSAllowed( tu, compID );
if( !mtsAllowed && !tsAllowed ) return;
int symbol = 0;
int ctxIdx = 0;
if( tsAllowed )
{
#if JVET_O0294_TRANSFORM_CLEANUP
symbol = (tu.mtsIdx == MTS_SKIP) ? 1 : 0;
#else
symbol = (tu.mtsIdx == MTS_SKIP) ? 0 : 1;
ctxIdx = 6;
m_BinEncoder.encodeBin( symbol, Ctx::MTSIndex( ctxIdx ) );
}
symbol = tu.mtsIdx != MTS_DCT2_DCT2 ? 1 : 0;
#if JVET_O0294_TRANSFORM_CLEANUP
ctxIdx = 0;
#else

Karsten Suehring
committed
if( symbol )
{
ctxIdx = 7;
for( int i = 0; i < 3; i++, ctxIdx++ )
{
symbol = tu.mtsIdx > i + MTS_DST7_DST7 ? 1 : 0;
m_BinEncoder.encodeBin( symbol, Ctx::MTSIndex( ctxIdx ) );
if( !symbol )
{
break;
}
}
}
}
}
#if JVET_O0294_TRANSFORM_CLEANUP
DTRACE( g_trace_ctx, D_SYNTAX, "mts_coding() etype=%d pos=(%d,%d) mtsIdx=%d\n", COMPONENT_Y, tu.cu->lx(), tu.cu->ly(), tu.mtsIdx);
#else
DTRACE( g_trace_ctx, D_SYNTAX, "mts_coding() etype=%d pos=(%d,%d) mtsIdx=%d\n", COMPONENT_Y, cu.lx(), cu.ly(), tu.mtsIdx );

Karsten Suehring
committed
void CABACWriter::isp_mode( const CodingUnit& cu )
{
Santiago de Luxán Hernández
committed
if( !CU::isIntra( cu ) || !isLuma( cu.chType ) || cu.firstPU->multiRefIdx || cu.ipcm || !cu.cs->sps->getUseISP() || cu.bdpcmMode || !CU::canUseISP( cu, getFirstComponentOfChannel( cu.chType ) ) )
Santiago de Luxán Hernández
committed
CHECK( cu.ispMode != NOT_INTRA_SUBPARTITIONS, "cu.ispMode != 0" );
return;
}
Santiago de Luxán Hernández
committed
if ( cu.ispMode == NOT_INTRA_SUBPARTITIONS )
{
m_BinEncoder.encodeBin( 0, Ctx::ISPMode( 0 ) );
}
else
{
m_BinEncoder.encodeBin( 1, Ctx::ISPMode( 0 ) );
Santiago de Luxán Hernández
committed
m_BinEncoder.encodeBin( cu.ispMode - 1, Ctx::ISPMode( 1 ) );
}
DTRACE( g_trace_ctx, D_SYNTAX, "intra_subPartitions() etype=%d pos=(%d,%d) ispIdx=%d\n", cu.chType, cu.blocks[cu.chType].x, cu.blocks[cu.chType].y, (int)cu.ispMode );
}

Karsten Suehring
committed
void CABACWriter::explicit_rdpcm_mode( const TransformUnit& tu, ComponentID compID )
{
const CodingUnit& cu = *tu.cu;
if( !CU::isIntra(cu) && CU::isRDPCMEnabled(cu) && ( tu.mtsIdx==MTS_SKIP || cu.transQuantBypass ) )

Karsten Suehring
committed
{
ChannelType chType = toChannelType( compID );
switch( tu.rdpcm[compID] )
{
case RDPCM_VER:
m_BinEncoder.encodeBin( 1, Ctx::RdpcmFlag(chType) );
m_BinEncoder.encodeBin( 1, Ctx::RdpcmDir (chType) );
break;
case RDPCM_HOR:
m_BinEncoder.encodeBin( 1, Ctx::RdpcmFlag(chType) );
m_BinEncoder.encodeBin( 0, Ctx::RdpcmDir (chType) );
break;
default: // RDPCM_OFF
m_BinEncoder.encodeBin( 0, Ctx::RdpcmFlag(chType) );
}
}
}
void CABACWriter::residual_lfnst_mode( const CodingUnit& cu, CUCtx& cuCtx )
{
Remy Foray
committed
#if JVET_O0213_RESTRICT_LFNST_TO_MAX_TB_SIZE
int chIdx = CS::isDualITree( *cu.cs ) && cu.chType == CHANNEL_TYPE_CHROMA ? 1 : 0;
#endif
if( cu.ispMode != NOT_INTRA_SUBPARTITIONS ||
#if JVET_O0925_MIP_SIMPLIFICATIONS
(cu.cs->sps->getUseLFNST() && CU::isIntra(cu) && cu.mipFlag && !allowLfnstWithMip(cu.firstPU->lumaSize())) ||
#else
cu.mipFlag == true ||
#endif
#if JVET_O0050_LOCAL_DUAL_TREE
( cu.isSepTree() && cu.chType == CHANNEL_TYPE_CHROMA && std::min( cu.blocks[ 1 ].width, cu.blocks[ 1 ].height ) < 4 )
( CS::isDualITree( *cu.cs ) && cu.chType == CHANNEL_TYPE_CHROMA && std::min( cu.blocks[ 1 ].width, cu.blocks[ 1 ].height ) < 4 )
#if JVET_O0213_RESTRICT_LFNST_TO_MAX_TB_SIZE
Moonmo Koo
committed
#if JVET_O0545_MAX_TB_SIGNALLING
Remy Foray
committed
|| ( cu.blocks[ chIdx ].lumaSize().width > cu.cs->sps->getMaxTbSize() || cu.blocks[ chIdx ].lumaSize().height > cu.cs->sps->getMaxTbSize() )
Moonmo Koo
committed
#else
Remy Foray
committed
|| ( cu.blocks[ chIdx ].lumaSize().width > MAX_TB_SIZEY || cu.blocks[ chIdx ].lumaSize().height > MAX_TB_SIZEY )
Moonmo Koo
committed
#endif
{
return;
}
if( cu.cs->sps->getUseLFNST() && CU::isIntra( cu ) && !CU::isLosslessCoded( cu ) )
{
#if JVET_O0050_LOCAL_DUAL_TREE
const bool lumaFlag = cu.isSepTree() ? ( isLuma( cu.chType ) ? true : false ) : true;
const bool chromaFlag = cu.isSepTree() ? ( isChroma( cu.chType ) ? true : false ) : true;
#else
const bool lumaFlag = CS::isDualITree( *cu.cs ) ? ( isLuma( cu.chType ) ? true : false ) : true;
const bool chromaFlag = CS::isDualITree( *cu.cs ) ? ( isChroma( cu.chType ) ? true : false ) : true;
#if !JVET_O0472_LFNST_SIGNALLING_LAST_SCAN_POS
bool nonZeroCoeffNonTs;
bool nonZeroCoeffNonTsCorner8x8 = ( lumaFlag && cuCtx.violatesLfnstConstrained[CHANNEL_TYPE_LUMA] ) || (chromaFlag && cuCtx.violatesLfnstConstrained[CHANNEL_TYPE_CHROMA] );
#else
bool nonZeroCoeffNonTsCorner8x8 = CU::getNumNonZeroCoeffNonTsCorner8x8( cu, lumaFlag, chromaFlag ) > 0;
#if JVET_O0050_LOCAL_DUAL_TREE
const int nonZeroCoeffThr = cu.isSepTree() ? ( isLuma( cu.chType ) ? LFNST_SIG_NZ_LUMA : LFNST_SIG_NZ_CHROMA ) : LFNST_SIG_NZ_LUMA + LFNST_SIG_NZ_CHROMA;
#else
const int nonZeroCoeffThr = CS::isDualITree( *cu.cs ) ? ( isLuma( cu.chType ) ? LFNST_SIG_NZ_LUMA : LFNST_SIG_NZ_CHROMA ) : LFNST_SIG_NZ_LUMA + LFNST_SIG_NZ_CHROMA;
cuCtx.numNonZeroCoeffNonTs = CU::getNumNonZeroCoeffNonTs( cu, lumaFlag, chromaFlag );
nonZeroCoeffNonTs = cuCtx.numNonZeroCoeffNonTs > nonZeroCoeffThr;
Hilmi Egilmez
committed
#if JVET_O0368_LFNST_WITH_DCT2_ONLY
const bool isNonDCT2 = (TU::getCbf(*cu.firstTU, ComponentID(COMPONENT_Y)) && cu.firstTU->mtsIdx != MTS_DCT2_DCT2);
#if JVET_O0472_LFNST_SIGNALLING_LAST_SCAN_POS
if( !cuCtx.lfnstLastScanPos || nonZeroCoeffNonTsCorner8x8 || isNonDCT2 )
Hilmi Egilmez
committed
if (!nonZeroCoeffNonTs || nonZeroCoeffNonTsCorner8x8 || isNonDCT2 )
#endif
#else
#if JVET_O0472_LFNST_SIGNALLING_LAST_SCAN_POS
if( !cuCtx.lfnstLastScanPos || nonZeroCoeffNonTsCorner8x8 )
Hilmi Egilmez
committed
#else
if( !nonZeroCoeffNonTs || nonZeroCoeffNonTsCorner8x8 )
Hilmi Egilmez
committed
#endif
{
return;
}
}
else
{
return;
}
unsigned cctx = 0;
Hilmi Egilmez
committed
#if JVET_O0368_LFNST_WITH_DCT2_ONLY
#if JVET_O0050_LOCAL_DUAL_TREE
if ( cu.isSepTree() ) cctx++;
#else
Hilmi Egilmez
committed
if ( CS::isDualITree(*cu.cs) ) cctx++;
#if JVET_O0545_MAX_TB_SIGNALLING
#if JVET_O0050_LOCAL_DUAL_TREE
if( ( cu.firstTU->mtsIdx < MTS_DST7_DST7 || !TU::getCbf(*cu.firstTU, COMPONENT_Y) ) && cu.isSepTree() ) cctx++;
#else
if( ( cu.firstTU->mtsIdx < MTS_DST7_DST7 || !TU::getCbf(*cu.firstTU, COMPONENT_Y) ) && CS::isDualITree( *cu.cs ) ) cctx++;
#if JVET_O0050_LOCAL_DUAL_TREE
if( cu.firstTU->mtsIdx < MTS_DST7_DST7 && cu.isSepTree() ) cctx++;
Hilmi Egilmez
committed
#else
if( cu.firstTU->mtsIdx < MTS_DST7_DST7 && CS::isDualITree( *cu.cs ) ) cctx++;
Hilmi Egilmez
committed
#endif
const uint32_t idxLFNST = cu.lfnstIdx;
assert( idxLFNST < 3 );
m_BinEncoder.encodeBin( idxLFNST ? 1 : 0, Ctx::LFNSTIdx( cctx ) );
if( idxLFNST )
{
m_BinEncoder.encodeBinEP( ( idxLFNST - 1 ) ? 1 : 0 );
}
DTRACE( g_trace_ctx, D_SYNTAX, "residual_lfnst_mode() etype=%d pos=(%d,%d) mode=%d\n", COMPONENT_Y, cu.lx(), cu.ly(), ( int ) cu.lfnstIdx );
}

Karsten Suehring
committed
void CABACWriter::last_sig_coeff( CoeffCodingContext& cctx, const TransformUnit& tu, ComponentID compID )

Karsten Suehring
committed
{
unsigned blkPos = cctx.blockPos( cctx.scanPosLast() );
unsigned posX, posY;
{
posY = blkPos / cctx.width();
posX = blkPos - ( posY * cctx.width() );
}
unsigned CtxLast;
unsigned GroupIdxX = g_uiGroupIdx[ posX ];
unsigned GroupIdxY = g_uiGroupIdx[ posY ];
unsigned maxLastPosX = cctx.maxLastPosX();
unsigned maxLastPosY = cctx.maxLastPosY();
if( ( tu.mtsIdx > MTS_SKIP || ( tu.cu->sbtInfo != 0 && tu.blocks[ compID ].width <= 32 && tu.blocks[ compID ].height <= 32 ) ) && !tu.cu->transQuantBypass && compID == COMPONENT_Y )
maxLastPosX = ( tu.blocks[compID].width == 32 ) ? g_uiGroupIdx[ 15 ] : maxLastPosX;
maxLastPosY = ( tu.blocks[compID].height == 32 ) ? g_uiGroupIdx[ 15 ] : maxLastPosY;

Karsten Suehring
committed
for( CtxLast = 0; CtxLast < GroupIdxX; CtxLast++ )
{
m_BinEncoder.encodeBin( 1, cctx.lastXCtxId( CtxLast ) );
}

Karsten Suehring
committed
{
m_BinEncoder.encodeBin( 0, cctx.lastXCtxId( CtxLast ) );
}
for( CtxLast = 0; CtxLast < GroupIdxY; CtxLast++ )
{
m_BinEncoder.encodeBin( 1, cctx.lastYCtxId( CtxLast ) );
}

Karsten Suehring
committed
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
{
m_BinEncoder.encodeBin( 0, cctx.lastYCtxId( CtxLast ) );
}
if( GroupIdxX > 3 )
{
posX -= g_uiMinInGroup[ GroupIdxX ];
for (int i = ( ( GroupIdxX - 2 ) >> 1 ) - 1 ; i >= 0; i-- )
{
m_BinEncoder.encodeBinEP( ( posX >> i ) & 1 );
}
}
if( GroupIdxY > 3 )
{
posY -= g_uiMinInGroup[ GroupIdxY ];
for ( int i = ( ( GroupIdxY - 2 ) >> 1 ) - 1 ; i >= 0; i-- )
{
m_BinEncoder.encodeBinEP( ( posY >> i ) & 1 );
}
}
}
void CABACWriter::residual_coding_subblock( CoeffCodingContext& cctx, const TCoeff* coeff, const int stateTransTable, int& state )
{
//===== init =====
const int minSubPos = cctx.minSubPos();
const bool isLast = cctx.isLast();
int firstSigPos = ( isLast ? cctx.scanPosLast() : cctx.maxSubPos() );
int nextSigPos = firstSigPos;
//===== encode significant_coeffgroup_flag =====
if( !isLast && cctx.isNotFirst() )
{
if( cctx.isSigGroup() )
{
m_BinEncoder.encodeBin( 1, cctx.sigGroupCtxId() );
}
else
{
m_BinEncoder.encodeBin( 0, cctx.sigGroupCtxId() );
return;
}
}
uint8_t ctxOffset[16];
//===== encode absolute values =====
const int inferSigPos = nextSigPos != cctx.scanPosLast() ? ( cctx.isNotFirst() ? minSubPos : -1 ) : nextSigPos;
int firstNZPos = nextSigPos;
int lastNZPos = -1;
int remAbsLevel = -1;
int numNonZero = 0;
unsigned signPattern = 0;
#if JVET_O0052_TU_LEVEL_CTX_CODED_BIN_CONSTRAINT
int remRegBins = cctx.regBinLimit;
#else
bool is2x2subblock = ( cctx.log2CGSize() == 2 );
int remRegBins = ( is2x2subblock ? MAX_NUM_REG_BINS_2x2SUBBLOCK : MAX_NUM_REG_BINS_4x4SUBBLOCK );
int firstPosMode2 = minSubPos - 1;

Karsten Suehring
committed
for( ; nextSigPos >= minSubPos && remRegBins >= 4; nextSigPos-- )

Karsten Suehring
committed
{
TCoeff Coeff = coeff[ cctx.blockPos( nextSigPos ) ];
unsigned sigFlag = ( Coeff != 0 );
if( numNonZero || nextSigPos != inferSigPos )
{
const unsigned sigCtxId = cctx.sigCtxIdAbs( nextSigPos, coeff, state );
m_BinEncoder.encodeBin( sigFlag, sigCtxId );
DTRACE( g_trace_ctx, D_SYNTAX_RESI, "sig_bin() bin=%d ctx=%d\n", sigFlag, sigCtxId );
remRegBins--;

Karsten Suehring
committed
}
else if( nextSigPos != cctx.scanPosLast() )
{
cctx.sigCtxIdAbs( nextSigPos, coeff, state ); // required for setting variables that are needed for gtx/par context selection
}

Karsten Suehring
committed
if( sigFlag )
{
uint8_t& ctxOff = ctxOffset[ nextSigPos - minSubPos ];
ctxOff = cctx.ctxOffsetAbs();
numNonZero++;
firstNZPos = nextSigPos;
lastNZPos = std::max<int>( lastNZPos, nextSigPos );
remAbsLevel = abs( Coeff ) - 1;
if( nextSigPos != cctx.scanPosLast() ) signPattern <<= 1;
if( Coeff < 0 ) signPattern++;
unsigned gt1 = !!remAbsLevel;
m_BinEncoder.encodeBin( gt1, cctx.greater1CtxIdAbs(ctxOff) );
DTRACE( g_trace_ctx, D_SYNTAX_RESI, "gt1_flag() bin=%d ctx=%d\n", gt1, cctx.greater1CtxIdAbs(ctxOff) );
remRegBins--;
if( gt1 )
{
remAbsLevel -= 1;
m_BinEncoder.encodeBin( remAbsLevel&1, cctx.parityCtxIdAbs( ctxOff ) );
DTRACE( g_trace_ctx, D_SYNTAX_RESI, "par_flag() bin=%d ctx=%d\n", remAbsLevel&1, cctx.parityCtxIdAbs( ctxOff ) );
remAbsLevel >>= 1;
remRegBins--;
unsigned gt2 = !!remAbsLevel;
m_BinEncoder.encodeBin(gt2, cctx.greater2CtxIdAbs(ctxOff));
DTRACE(g_trace_ctx, D_SYNTAX_RESI, "gt2_flag() bin=%d ctx=%d\n", gt2, cctx.greater2CtxIdAbs(ctxOff));
remRegBins--;

Karsten Suehring
committed
}
state = ( stateTransTable >> ((state<<2)+((Coeff&1)<<1)) ) & 3;
}
firstPosMode2 = nextSigPos;
#if JVET_O0052_TU_LEVEL_CTX_CODED_BIN_CONSTRAINT
cctx.regBinLimit = remRegBins;
#endif

Karsten Suehring
committed
//===== 2nd PASS: Go-rice codes =====
unsigned ricePar = 0;
for( int scanPos = firstSigPos; scanPos > firstPosMode2; scanPos-- )
int sumAll = cctx.templateAbsSum(scanPos, coeff, 4);
ricePar = g_auiGoRiceParsCoeff[sumAll];
unsigned absLevel = abs( coeff[ cctx.blockPos( scanPos ) ] );
if( absLevel >= 4 )
{
unsigned rem = ( absLevel - 4 ) >> 1;
m_BinEncoder.encodeRemAbsEP( rem, ricePar, cctx.extPrec(), cctx.maxLog2TrDRange() );
DTRACE( g_trace_ctx, D_SYNTAX_RESI, "rem_val() bin=%d ctx=%d\n", rem, ricePar );
}
}
//===== coeff bypass ====
for( int scanPos = firstPosMode2; scanPos >= minSubPos; scanPos-- )
{
TCoeff Coeff = coeff[ cctx.blockPos( scanPos ) ];
unsigned absLevel = abs( Coeff );
int sumAll = cctx.templateAbsSum(scanPos, coeff, 0);
int rice = g_auiGoRiceParsCoeff [sumAll];
int pos0 = g_auiGoRicePosCoeff0[std::max(0, state - 1)][sumAll];
unsigned rem = ( absLevel == 0 ? pos0 : absLevel <= pos0 ? absLevel-1 : absLevel );
m_BinEncoder.encodeRemAbsEP( rem, rice, cctx.extPrec(), cctx.maxLog2TrDRange() );
DTRACE( g_trace_ctx, D_SYNTAX_RESI, "rem_val() bin=%d ctx=%d\n", rem, rice );
state = ( stateTransTable >> ((state<<2)+((absLevel&1)<<1)) ) & 3;
if( absLevel )
{
numNonZero++;
firstNZPos = scanPos;
lastNZPos = std::max<int>( lastNZPos, scanPos );
signPattern <<= 1;
if( Coeff < 0 ) signPattern++;
}
}

Karsten Suehring
committed
//===== encode sign's =====
unsigned numSigns = numNonZero;
if( cctx.hideSign( firstNZPos, lastNZPos ) )
{
numSigns --;
signPattern >>= 1;
}
m_BinEncoder.encodeBinsEP( signPattern, numSigns );
}
void CABACWriter::residual_codingTS( const TransformUnit& tu, ComponentID compID )
{
DTRACE( g_trace_ctx, D_SYNTAX, "residual_codingTS() etype=%d pos=(%d,%d) size=%dx%d\n", tu.blocks[compID].compID, tu.blocks[compID].x, tu.blocks[compID].y, tu.blocks[compID].width, tu.blocks[compID].height );
// init coeff coding context
CoeffCodingContext cctx ( tu, compID, false, tu.cu->bdpcmMode );
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
const TCoeff* coeff = tu.getCoeffs( compID ).buf;
cctx.setNumCtxBins( 2 * tu.lwidth()*tu.lheight() );
// determine and set last coeff position and sig group flags
std::bitset<MLS_GRP_NUM> sigGroupFlags;
for( int scanPos = 0; scanPos < cctx.maxNumCoeff(); scanPos++)
{
unsigned blkPos = cctx.blockPos( scanPos );
if( coeff[blkPos] )
{
sigGroupFlags.set( scanPos >> cctx.log2CGSize() );
}
}
// code subblocks
for( int subSetId = 0; subSetId <= ( cctx.maxNumCoeff() - 1 ) >> cctx.log2CGSize(); subSetId++ )
{
cctx.initSubblock ( subSetId, sigGroupFlags[subSetId] );
residual_coding_subblockTS( cctx, coeff );
}
}
void CABACWriter::residual_coding_subblockTS( CoeffCodingContext& cctx, const TCoeff* coeff )
{
//===== init =====
const int minSubPos = cctx.maxSubPos();
int firstSigPos = cctx.minSubPos();
int nextSigPos = firstSigPos;
//===== encode significant_coeffgroup_flag =====
if( !cctx.isLastSubSet() || !cctx.only1stSigGroup() )
{
if( cctx.isSigGroup() )
{
Kato Yusuke
committed
#if !JVET_O0409_EXCLUDE_CODED_SUB_BLK_FLAG_FROM_COUNT
if( cctx.isContextCoded() )
{
Kato Yusuke
committed
#endif
m_BinEncoder.encodeBin( 1, cctx.sigGroupCtxId( true ) );
DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_sigGroup() bin=%d ctx=%d\n", 1, cctx.sigGroupCtxId() );
Kato Yusuke
committed
#if !JVET_O0409_EXCLUDE_CODED_SUB_BLK_FLAG_FROM_COUNT
}
else
{
m_BinEncoder.encodeBinEP( 1 );
DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_sigGroup() EPbin=%d\n", 1 );
}
Kato Yusuke
committed
#endif
}
else
{
Kato Yusuke
committed
#if !JVET_O0409_EXCLUDE_CODED_SUB_BLK_FLAG_FROM_COUNT
if( cctx.isContextCoded() )
{
Kato Yusuke
committed
#endif
m_BinEncoder.encodeBin( 0, cctx.sigGroupCtxId( true ) );
DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_sigGroup() bin=%d ctx=%d\n", 0, cctx.sigGroupCtxId() );
Kato Yusuke
committed
#if !JVET_O0409_EXCLUDE_CODED_SUB_BLK_FLAG_FROM_COUNT
}
else
{
m_BinEncoder.encodeBinEP( 0 );
DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_sigGroup() EPbin=%d\n", 0 );
}
Kato Yusuke
committed
#endif
return;
}
}
//===== encode absolute values =====
const int inferSigPos = minSubPos;
int remAbsLevel = -1;
int numNonZero = 0;
#if JVET_O0122_TS_SIGN_LEVEL
int rightPixel, belowPixel, modAbsCoeff;
#endif
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
for( ; nextSigPos <= minSubPos; nextSigPos++ )
{
TCoeff Coeff = coeff[ cctx.blockPos( nextSigPos ) ];
unsigned sigFlag = ( Coeff != 0 );
if( numNonZero || nextSigPos != inferSigPos )
{
if( cctx.isContextCoded() )
{
const unsigned sigCtxId = cctx.sigCtxIdAbsTS( nextSigPos, coeff );
m_BinEncoder.encodeBin( sigFlag, sigCtxId );
DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_sig_bin() bin=%d ctx=%d\n", sigFlag, sigCtxId );
}
else
{
m_BinEncoder.encodeBinEP( sigFlag );
DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_sig_bin() EPbin=%d\n", sigFlag );
}
}
if( sigFlag )
{
//===== encode sign's =====
int sign = Coeff < 0;
if( cctx.isContextCoded() )
{
#if JVET_O0122_TS_SIGN_LEVEL
const unsigned signCtxId = cctx.signCtxIdAbsTS(nextSigPos, coeff, cctx.bdpcm());
m_BinEncoder.encodeBin(sign, signCtxId);
#else
m_BinEncoder.encodeBin( sign, Ctx::TsResidualSign( cctx.bdpcm() ? 1 : 0 ) );
#endif
}
else
{
m_BinEncoder.encodeBinEP( sign );
}
numNonZero++;
#if JVET_O0122_TS_SIGN_LEVEL
cctx.neighTS(rightPixel, belowPixel, nextSigPos, coeff);
modAbsCoeff = cctx.deriveModCoeff(rightPixel, belowPixel, abs(Coeff), cctx.bdpcm());
remAbsLevel = modAbsCoeff - 1;
#else
remAbsLevel = abs( Coeff ) - 1;
#endif
unsigned gt1 = !!remAbsLevel;
#if JVET_O0122_TS_SIGN_LEVEL
const unsigned gt1CtxId = cctx.lrg1CtxIdAbsTS(nextSigPos, coeff, cctx.bdpcm());
if (cctx.isContextCoded())
{
m_BinEncoder.encodeBin(gt1, gt1CtxId);
DTRACE(g_trace_ctx, D_SYNTAX_RESI, "ts_gt1_flag() bin=%d ctx=%d\n", gt1, gt1CtxId);
}
else
{
m_BinEncoder.encodeBinEP(gt1);
DTRACE(g_trace_ctx, D_SYNTAX_RESI, "ts_gt1_flag() EPbin=%d\n", gt1);
}
#else
if( cctx.isContextCoded() )
{
m_BinEncoder.encodeBin( gt1, cctx.greaterXCtxIdAbsTS(0) );
DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_gt1_flag() bin=%d ctx=%d\n", gt1, cctx.greaterXCtxIdAbsTS(0) );
}
else
{
m_BinEncoder.encodeBinEP( gt1 );
DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_gt1_flag() EPbin=%d\n", gt1 );
}
#endif
if( gt1 )
{
remAbsLevel -= 1;
if( cctx.isContextCoded() )
{
m_BinEncoder.encodeBin( remAbsLevel&1, cctx.parityCtxIdAbsTS() );
DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_par_flag() bin=%d ctx=%d\n", remAbsLevel&1, cctx.parityCtxIdAbsTS() );
}