-
Fabrice Le Léannec authoredFabrice Le Léannec authored
CABACWriter.cpp 323.95 KiB
/* The copyright in this software is being made available under the BSD
* License, included below. This software may be subject to other third party
* and contributor rights, including patent rights, and no such rights are
* granted under this license.
*
* Copyright (c) 2010-2023, ITU/ISO/IEC
* 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 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 (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
/** \file CABACWriter.cpp
* \brief Writer for low level syntax
*/
#include "CommonLib/Contexts.h"
#include "CABACWriter.h"
#include "EncLib.h"
#include "CommonLib/UnitTools.h"
#include "CommonLib/dtrace_buffer.h"
#include <map>
#include <algorithm>
#include <limits>
#if JVET_AI0136_ADAPTIVE_DUAL_TREE
static Partitioner *g_encPartitionerSST=nullptr;
#endif
//! \ingroup EncoderLib
//! \{
#if JVET_AG0196_CABAC_RETRAIN
void CABACWriter::initCtxModels( Slice& slice )
#else
void CABACWriter::initCtxModels( const Slice& slice )
#endif
{
int qp = slice.getSliceQp();
SliceType sliceType = slice.getSliceType();
SliceType encCABACTableIdx = slice.getEncCABACTableIdx();
if( !slice.isIntra() && (encCABACTableIdx==B_SLICE || encCABACTableIdx==P_SLICE) && slice.getPPS()->getCabacInitPresentFlag() )
{
sliceType = encCABACTableIdx;
}
#if JVET_AH0176_LOW_DELAY_B_CTX
if (sliceType == B_SLICE && slice.getCheckLDC())
{
sliceType = L_SLICE;
}
#endif
#if JVET_AG0196_CABAC_RETRAIN
slice.setCabacInitSliceType( sliceType );
#endif
m_BinEncoder.reset(qp, (int)sliceType);
#if JVET_Z0135_TEMP_CABAC_WIN_WEIGHT
if( slice.getSPS()->getTempCabacInitMode() )
{
m_CABACDataStore->loadCtxStates( &slice, getCtx() );
}
#endif
}
template <class BinProbModel>
SliceType xGetCtxInitId( const Slice& slice, const BinEncIf& binEncoder, Ctx& ctxTest )
{
const CtxStore<BinProbModel>& ctxStoreTest = static_cast<const CtxStore<BinProbModel>&>( ctxTest );
const CtxStore<BinProbModel>& ctxStoreRef = static_cast<const CtxStore<BinProbModel>&>( binEncoder.getCtx() );
int qp = slice.getSliceQp();
if( !slice.isIntra() )
{
SliceType aSliceTypeChoices[] = { B_SLICE, P_SLICE };
uint64_t bestCost = std::numeric_limits<uint64_t>::max();
SliceType bestSliceType = aSliceTypeChoices[0];
for (uint32_t idx=0; idx<2; idx++)
{
uint64_t curCost = 0;
SliceType curSliceType = aSliceTypeChoices[idx];
#if JVET_AH0176_LOW_DELAY_B_CTX
if (curSliceType == B_SLICE && slice.getCheckLDC())
{
ctxTest.init(qp, (int)L_SLICE);
}
else
{
ctxTest.init(qp, (int)curSliceType);
}
#else
ctxTest.init(qp, (int)curSliceType);
#endif
for( int k = 0; k < Ctx::NumberOfContexts; k++ )
{
if( binEncoder.getNumBins(k) > 0 )
{
curCost += uint64_t( binEncoder.getNumBins(k) ) * ctxStoreRef[k].estFracExcessBits( ctxStoreTest[k] );
}
}
if (curCost < bestCost)
{
bestSliceType = curSliceType;
bestCost = curCost;
}
}
return bestSliceType;
}
else
{
return I_SLICE;
}
}
#if JVET_AI0087_BTCUS_RESTRICTION
bool CABACWriter::isLumaNonBoundaryCu(const Partitioner& partitioner, SizeType picWidth, SizeType picHeight)
{
bool validCU = false;
if (isLuma(partitioner.chType))
{
int maxWidthHeight = std::max(partitioner.currArea().lwidth(), partitioner.currArea().lheight()) - 1;
if ((partitioner.currArea().Y().x + maxWidthHeight < picWidth)
&& (partitioner.currArea().Y().y + maxWidthHeight < picHeight))
{
validCU = true;
}
}
return validCU;
}
void CABACWriter::setBtFirstPart(Partitioner& partitioner, SizeType blockSize, PartSplit setValue)
{
if (blockSize == 128)
{
partitioner.btFirstPartDecs[0] = setValue;
}
else if (blockSize == 64)
{
partitioner.btFirstPartDecs[1] = setValue;
}
else if (blockSize == 32)
{
partitioner.btFirstPartDecs[2] = setValue;
}
else if (blockSize == 16)
{
partitioner.btFirstPartDecs[3] = setValue;
}
}
#endif
SliceType CABACWriter::getCtxInitId( const Slice& slice )
{
switch( m_TestCtx.getBPMType() )
{
case BPM_Std: return xGetCtxInitId<BinProbModel_Std> ( slice, m_BinEncoder, m_TestCtx );
default: return NUMBER_OF_SLICE_TYPES;
}
}
unsigned estBits( BinEncIf& binEnc, const std::vector<bool>& bins, const Ctx& ctx, const int ctxId, const uint8_t winSize )
{
binEnc.initCtxAndWinSize( ctxId, ctx, winSize );
binEnc.start();
const std::size_t numBins = bins.size();
unsigned startBits = binEnc.getNumWrittenBits();
for( std::size_t binId = 0; binId < numBins; binId++ )
{
unsigned bin = ( bins[binId] ? 1 : 0 );
binEnc.encodeBin( bin, ctxId );
}
unsigned endBits = binEnc.getNumWrittenBits();
unsigned codedBits = endBits - startBits;
return codedBits;
}
//================================================================================
// clause 7.3.8.1
//--------------------------------------------------------------------------------
// void end_of_slice()
//================================================================================
void CABACWriter::end_of_slice()
{
m_BinEncoder.encodeBinTrm ( 1 );
m_BinEncoder.finish ();
}
#if JVET_V0094_BILATERAL_FILTER
void CABACWriter::bif( const ComponentID compID, const Slice& slice, const BifParams& bifParams )
{
for (int i = 0; i < bifParams.numBlocks; ++i)
{
bif(compID, slice, bifParams, i);
}
}
void CABACWriter::bif( const ComponentID compID, const Slice& slice, const BifParams& bifParams, unsigned ctuRsAddr)
{
const PPS& pps = *slice.getPPS();
if( isLuma( compID ) && !pps.getUseBIF() )
{
return;
}
#if JVET_X0071_CHROMA_BILATERAL_FILTER
if( isChroma( compID ) && !pps.getUseChromaBIF() )
{
return;
}
#endif
if( ctuRsAddr == 0 )
{
m_BinEncoder.encodeBinEP( bifParams.allCtuOn );
if( bifParams.allCtuOn == 0 )
{
m_BinEncoder.encodeBinEP( bifParams.frmOn );
}
}
if( bifParams.allCtuOn == 0 && bifParams.frmOn )
{
m_BinEncoder.encodeBin( bifParams.ctuOn[ctuRsAddr], Ctx::BifCtrlFlags[compID]() );
}
}
#endif
//================================================================================
// clause 7.3.8.2
//--------------------------------------------------------------------------------
// bool coding_tree_unit( cs, area, qp, ctuRsAddr, skipSao, skipAlf )
//================================================================================
void CABACWriter::coding_tree_unit( CodingStructure& cs, const UnitArea& area, int (&qps)[2], unsigned ctuRsAddr, bool skipSao /* = false */, bool skipAlf /* = false */ )
{
DTRACE(g_trace_ctx, D_SYNTAX, "coding_tree_unit() pos=(%d,%d)\n", area.lx(), area.ly());
CUCtx cuCtx( qps[CH_L] );
QTBTPartitioner partitioner;
#if JVET_AI0136_ADAPTIVE_DUAL_TREE
if (g_encPartitionerSST == nullptr)
{
g_encPartitionerSST = new QTBTPartitioner;
}
#endif
partitioner.initCtu(area, CH_L, *cs.slice);
if( !skipSao )
{
sao( *cs.slice, ctuRsAddr );
}
#if JVET_W0066_CCSAO
if ( !skipSao )
{
for ( int compIdx = 0; compIdx < getNumberValidComponents( cs.pcv->chrFormat ); compIdx++ )
{
if (cs.slice->m_ccSaoComParam.enabled[compIdx])
{
const int setNum = cs.slice->m_ccSaoComParam.setNum[compIdx];
const int ry = ctuRsAddr / cs.pcv->widthInCtus;
const int rx = ctuRsAddr % cs.pcv->widthInCtus;
const Position lumaPos(rx * cs.pcv->maxCUWidth, ry * cs.pcv->maxCUHeight);
codeCcSaoControlIdc(cs.slice->m_ccSaoControl[compIdx][ctuRsAddr], cs, ComponentID(compIdx),
ctuRsAddr, cs.slice->m_ccSaoControl[compIdx], lumaPos, setNum);
}
}
}
#endif
if (!skipAlf)
{
for (int compIdx = 0; compIdx < MAX_NUM_COMPONENT; compIdx++)
{
if (!cs.slice->getTileGroupAlfEnabledFlag((ComponentID)compIdx))
{
continue;
}
codeAlfCtuEnableFlag(cs, ctuRsAddr, compIdx, NULL);
if (isLuma(ComponentID(compIdx)))
{
codeAlfCtuFilterIndex(cs, ctuRsAddr, cs.slice->getTileGroupAlfEnabledFlag(COMPONENT_Y));
#if ALF_IMPROVEMENT
if (cs.slice->getPic()->getAlfCtuEnableFlag(compIdx)[ctuRsAddr] && cs.slice->getPic()->getAlfCtbFilterIndex()[ctuRsAddr] >= NUM_FIXED_FILTER_SETS)
{
int apsIdx = cs.slice->getTileGroupApsIdLuma()[cs.slice->getPic()->getAlfCtbFilterIndex()[ctuRsAddr] - NUM_FIXED_FILTER_SETS];
codeAlfCtuAlternative(cs, ctuRsAddr, 0, NULL, cs.slice->getAlfAPSs()[apsIdx]->getAlfAPSParam().numAlternativesLuma);
}
#endif
}
if (isChroma(ComponentID(compIdx)))
{
uint8_t* ctbAlfFlag = cs.slice->getTileGroupAlfEnabledFlag((ComponentID)compIdx) ? cs.slice->getPic()->getAlfCtuEnableFlag( compIdx ) : nullptr;
if( ctbAlfFlag && ctbAlfFlag[ctuRsAddr] )
{
codeAlfCtuAlternative( cs, ctuRsAddr, compIdx );
}
}
}
}
if ( !skipAlf )
{
for ( int compIdx = 1; compIdx < getNumberValidComponents( cs.pcv->chrFormat ); compIdx++ )
{
if (cs.slice->m_ccAlfFilterParam.ccAlfFilterEnabled[compIdx - 1])
{
const int filterCount = cs.slice->m_ccAlfFilterParam.ccAlfFilterCount[compIdx - 1];
const int ry = ctuRsAddr / cs.pcv->widthInCtus;
const int rx = ctuRsAddr % cs.pcv->widthInCtus;
const Position lumaPos(rx * cs.pcv->maxCUWidth, ry * cs.pcv->maxCUHeight);
codeCcAlfFilterControlIdc(cs.slice->m_ccAlfFilterControl[compIdx - 1][ctuRsAddr], cs, ComponentID(compIdx),
ctuRsAddr, cs.slice->m_ccAlfFilterControl[compIdx - 1], lumaPos, filterCount);
}
}
}
#if JVET_AI0136_ADAPTIVE_DUAL_TREE
coding_tree( cs, partitioner, cuCtx, qps );
qps[CH_L] = cuCtx.qp;
#else
#if TU_256
if( CS::isDualITree( cs ) && cs.pcv->chrFormat != CHROMA_400 && cs.pcv->maxCUWidth > std::min<int>( MAX_TB_SIZEY, MAX_INTRA_SIZE ) )
#else
if ( CS::isDualITree(cs) && cs.pcv->chrFormat != CHROMA_400 && cs.pcv->maxCUWidth > 64 )
#endif
{
CUCtx chromaCuCtx(qps[CH_C]);
QTBTPartitioner chromaPartitioner;
chromaPartitioner.initCtu(area, CH_C, *cs.slice);
coding_tree(cs, partitioner, cuCtx, &chromaPartitioner, &chromaCuCtx);
qps[CH_L] = cuCtx.qp;
qps[CH_C] = chromaCuCtx.qp;
}
else
{
coding_tree(cs, partitioner, cuCtx);
qps[CH_L] = cuCtx.qp;
if( CS::isDualITree( cs ) && cs.pcv->chrFormat != CHROMA_400 )
{
CUCtx cuCtxChroma( qps[CH_C] );
partitioner.initCtu(area, CH_C, *cs.slice);
coding_tree(cs, partitioner, cuCtxChroma);
qps[CH_C] = cuCtxChroma.qp;
}
}
#endif
}
//================================================================================
// clause 7.3.8.3
//--------------------------------------------------------------------------------
// void sao ( slice, ctuRsAddr )
// void sao_block_pars ( saoPars, bitDepths, sliceEnabled, leftMergeAvail, aboveMergeAvail, onlyEstMergeInfo )
// void sao_offset_pars ( ctbPars, compID, sliceEnabled, bitDepth )
//================================================================================
void CABACWriter::sao( const Slice& slice, unsigned ctuRsAddr )
{
const SPS& sps = *slice.getSPS();
if( !sps.getSAOEnabledFlag() )
{
return;
}
CodingStructure& cs = *slice.getPic()->cs;
const PreCalcValues& pcv = *cs.pcv;
const SAOBlkParam& sao_ctu_pars = cs.picture->getSAO()[ctuRsAddr];
bool slice_sao_luma_flag = ( slice.getSaoEnabledFlag( CHANNEL_TYPE_LUMA ) );
bool slice_sao_chroma_flag = ( slice.getSaoEnabledFlag( CHANNEL_TYPE_CHROMA ) && sps.getChromaFormatIdc() != CHROMA_400 );
if( !slice_sao_luma_flag && !slice_sao_chroma_flag )
{
return;
}
bool sliceEnabled[3] = { slice_sao_luma_flag, slice_sao_chroma_flag, slice_sao_chroma_flag };
int frame_width_in_ctus = pcv.widthInCtus;
int ry = ctuRsAddr / frame_width_in_ctus;
int rx = ctuRsAddr - ry * frame_width_in_ctus;
const Position pos ( rx * cs.pcv->maxCUWidth, ry * cs.pcv->maxCUHeight );
const unsigned curSliceIdx = slice.getIndependentSliceIdx();
const unsigned curTileIdx = cs.pps->getTileIdx( pos );
bool leftMergeAvail = cs.getCURestricted( pos.offset( -(int)pcv.maxCUWidth, 0 ), pos, curSliceIdx, curTileIdx, CH_L ) ? true : false;
bool aboveMergeAvail = cs.getCURestricted( pos.offset( 0, -(int)pcv.maxCUHeight ), pos, curSliceIdx, curTileIdx, CH_L ) ? true : false;
sao_block_pars( sao_ctu_pars, sps.getBitDepths(), sliceEnabled, leftMergeAvail, aboveMergeAvail, false );
}
void CABACWriter::sao_block_pars( const SAOBlkParam& saoPars, const BitDepths& bitDepths, bool* sliceEnabled, bool leftMergeAvail, bool aboveMergeAvail, bool onlyEstMergeInfo )
{
bool isLeftMerge = false;
bool isAboveMerge = false;
if( leftMergeAvail )
{
// sao_merge_left_flag
isLeftMerge = ( saoPars[COMPONENT_Y].modeIdc == SAO_MODE_MERGE && saoPars[COMPONENT_Y].typeIdc == SAO_MERGE_LEFT );
m_BinEncoder.encodeBin( (isLeftMerge), Ctx::SaoMergeFlag() );
}
if( aboveMergeAvail && !isLeftMerge )
{
// sao_merge_above_flag
isAboveMerge = ( saoPars[COMPONENT_Y].modeIdc == SAO_MODE_MERGE && saoPars[COMPONENT_Y].typeIdc == SAO_MERGE_ABOVE );
m_BinEncoder.encodeBin( (isAboveMerge), Ctx::SaoMergeFlag() );
}
if( onlyEstMergeInfo )
{
return; //only for RDO
}
if( !isLeftMerge && !isAboveMerge )
{
// explicit parameters
for( int compIdx=0; compIdx < MAX_NUM_COMPONENT; compIdx++ )
{
sao_offset_pars( saoPars[compIdx], ComponentID(compIdx), sliceEnabled[compIdx], bitDepths.recon[ toChannelType(ComponentID(compIdx)) ] );
}
}
}
void CABACWriter::sao_offset_pars( const SAOOffset& ctbPars, ComponentID compID, bool sliceEnabled, int bitDepth )
{
if( !sliceEnabled )
{
CHECK( ctbPars.modeIdc != SAO_MODE_OFF, "Sao must be off, if it is disabled on slice level" );
return;
}
const bool isFirstCompOfChType = ( getFirstComponentOfChannel( toChannelType(compID) ) == compID );
if( isFirstCompOfChType )
{
// sao_type_idx_luma / sao_type_idx_chroma
if( ctbPars.modeIdc == SAO_MODE_OFF )
{
m_BinEncoder.encodeBin ( 0, Ctx::SaoTypeIdx() );
}
else if( ctbPars.typeIdc == SAO_TYPE_BO )
{
m_BinEncoder.encodeBin ( 1, Ctx::SaoTypeIdx() );
m_BinEncoder.encodeBinEP( 0 );
}
else
{
CHECK(!( ctbPars.typeIdc < SAO_TYPE_START_BO ), "Unspecified error");
m_BinEncoder.encodeBin ( 1, Ctx::SaoTypeIdx() );
m_BinEncoder.encodeBinEP( 1 );
}
}
if( ctbPars.modeIdc == SAO_MODE_NEW )
{
const int maxOffsetQVal = SampleAdaptiveOffset::getMaxOffsetQVal( bitDepth );
int numClasses = ( ctbPars.typeIdc == SAO_TYPE_BO ? 4 : NUM_SAO_EO_CLASSES );
int k = 0;
int offset[4];
for( int i = 0; i < numClasses; i++ )
{
if( ctbPars.typeIdc != SAO_TYPE_BO && i == SAO_CLASS_EO_PLAIN )
{
continue;
}
int classIdx = ( ctbPars.typeIdc == SAO_TYPE_BO ? ( ctbPars.typeAuxInfo + i ) % NUM_SAO_BO_CLASSES : i );
offset[k++] = ctbPars.offset[classIdx];
}
// sao_offset_abs
for( int i = 0; i < 4; i++ )
{
unsigned absOffset = ( offset[i] < 0 ? -offset[i] : offset[i] );
unary_max_eqprob( absOffset, maxOffsetQVal );
}
// band offset mode
if( ctbPars.typeIdc == SAO_TYPE_BO )
{
// sao_offset_sign
for( int i = 0; i < 4; i++ )
{
if( offset[i] )
{
m_BinEncoder.encodeBinEP( (offset[i] < 0) );
}
}
// sao_band_position
m_BinEncoder.encodeBinsEP( ctbPars.typeAuxInfo, NUM_SAO_BO_CLASSES_LOG2 );
}
// edge offset mode
else
{
if( isFirstCompOfChType )
{
// sao_eo_class_luma / sao_eo_class_chroma
CHECK( ctbPars.typeIdc - SAO_TYPE_START_EO < 0, "sao edge offset class is outside valid range" );
m_BinEncoder.encodeBinsEP( ctbPars.typeIdc - SAO_TYPE_START_EO, NUM_SAO_EO_TYPES_LOG2 );
}
}
}
}
#if JVET_W0066_CCSAO
void CABACWriter::codeCcSaoControlIdc(uint8_t idcVal, CodingStructure &cs, const ComponentID compID,
const int curIdx, const uint8_t *controlIdc, Position lumaPos,
const int setNum)
{
CHECK(idcVal > setNum, "Set index is too large");
const uint32_t curSliceIdx = cs.slice->getIndependentSliceIdx();
const uint32_t curTileIdx = cs.pps->getTileIdx( lumaPos );
Position leftLumaPos = lumaPos.offset(-(int)cs.pcv->maxCUWidth, 0);
Position aboveLumaPos = lumaPos.offset(0, -(int)cs.pcv->maxCUWidth);
bool leftAvail = cs.getCURestricted( leftLumaPos, lumaPos, curSliceIdx, curTileIdx, CH_L ) ? true : false;
bool aboveAvail = cs.getCURestricted( aboveLumaPos, lumaPos, curSliceIdx, curTileIdx, CH_L ) ? true : false;
int ctxt = 0;
if (leftAvail)
{
ctxt += ( controlIdc[curIdx - 1]) ? 1 : 0;
}
if (aboveAvail)
{
ctxt += (controlIdc[curIdx - cs.pcv->widthInCtus]) ? 1 : 0;
}
ctxt += ( compID == COMPONENT_Y ) ? 0
: ( compID == COMPONENT_Cb ) ? 3 : 6;
m_BinEncoder.encodeBin( ( idcVal == 0 ) ? 0 : 1, Ctx::CcSaoControlIdc( ctxt ) ); // ON/OFF flag is context coded
if ( idcVal > 0 )
{
int val = (idcVal - 1);
while ( val )
{
m_BinEncoder.encodeBinEP( 1 );
val--;
}
if ( idcVal < setNum )
{
m_BinEncoder.encodeBinEP( 0 );
}
}
DTRACE( g_trace_ctx, D_SYNTAX, "cc_sao_control_idc() compID=%d pos=(%d,%d) ctxt=%d, setNum=%d, idcVal=%d\n", compID, lumaPos.x, lumaPos.y, ctxt, setNum, idcVal );
}
#endif
//================================================================================
// clause 7.3.8.4
//--------------------------------------------------------------------------------
// void coding_tree ( cs, partitioner, cuCtx )
// void split_cu_flag ( split, cs, partitioner )
// void split_cu_mode_mt ( split, cs, partitioner )
//================================================================================
#if JVET_AI0136_ADAPTIVE_DUAL_TREE
//void CABACWriter::coding_tree( const CodingStructure& cs, Partitioner& partitioner, CUCtx& cuCtx, int (&qps)[2] )
void CABACWriter::coding_tree(const CodingStructure& cs, Partitioner& partitioner, CUCtx& cuCtx, int (&qps)[2], Partitioner* pPartitionerChroma, CUCtx* pCuCtxChroma)
#else
void CABACWriter::coding_tree(const CodingStructure& cs, Partitioner& partitioner, CUCtx& cuCtx, Partitioner* pPartitionerChroma, CUCtx* pCuCtxChroma)
#endif
{
const PPS &pps = *cs.pps;
const UnitArea &currArea = partitioner.currArea();
const CodingUnit &cu = *cs.getCU( currArea.blocks[partitioner.chType], partitioner.chType );
// Reset delta QP coding flag and ChromaQPAdjustemt coding flag
#if INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS
if (pps.getUseDQP() && partitioner.currQgEnable())
#else
//Note: do not reset qg at chroma CU
if( pps.getUseDQP() && partitioner.currQgEnable() && !isChroma( partitioner.chType ) )
#endif
{
cuCtx.qgStart = true;
cuCtx.isDQPCoded = false;
}
if( cs.slice->getUseChromaQpAdj() && partitioner.currQgChromaEnable() )
{
cuCtx.isChromaQpAdjCoded = false;
}
// Reset delta QP coding flag and ChromaQPAdjustemt coding flag
#if !JVET_AI0136_ADAPTIVE_DUAL_TREE
if (CS::isDualITree(cs) && pPartitionerChroma != nullptr)
{
if (pps.getUseDQP() && pPartitionerChroma->currQgEnable())
{
pCuCtxChroma->qgStart = true;
pCuCtxChroma->isDQPCoded = false;
}
if (cs.slice->getUseChromaQpAdj() && pPartitionerChroma->currQgChromaEnable())
{
pCuCtxChroma->isChromaQpAdjCoded = false;
}
}
#endif
const PartSplit splitMode = CU::getSplitAtDepth( cu, partitioner.currDepth );
split_cu_mode(splitMode, cs, partitioner
#if JVET_AI0136_ADAPTIVE_DUAL_TREE
, & cu
#endif
#if JVET_AI0087_BTCUS_RESTRICTION
, true
#endif
);
#if JVET_AI0087_BTCUS_RESTRICTION
CHECK(!partitioner.canSplit(splitMode, cs, false, false), "The chosen split mode is invalid!");
#else
CHECK(!partitioner.canSplit(splitMode, cs), "The chosen split mode is invalid!");
#endif
#if JVET_AI0136_ADAPTIVE_DUAL_TREE
if( splitMode != CU_DONT_SPLIT && ( cs.slice->getProcessingIntraRegion() || !CU::isIntraRegionRoot( cu, partitioner ) ) )
#else
if( splitMode != CU_DONT_SPLIT )
#endif
{
#if !JVET_AI0136_ADAPTIVE_DUAL_TREE
#if TU_256
const int maxSize = std::min<int>( MAX_TB_SIZEY, MAX_INTRA_SIZE );
if( CS::isDualITree( cs ) && pPartitionerChroma != nullptr && ( partitioner.currArea().lwidth() >= maxSize || partitioner.currArea().lheight() >= maxSize ) )
#else
if (CS::isDualITree(cs) && pPartitionerChroma != nullptr && (partitioner.currArea().lwidth() >= 64 || partitioner.currArea().lheight() >= 64))
#endif
{
partitioner.splitCurrArea(CU_QUAD_SPLIT, cs);
pPartitionerChroma->splitCurrArea(CU_QUAD_SPLIT, cs);
bool beContinue = true;
bool lumaContinue = true;
bool chromaContinue = true;
while (beContinue)
{
#if TU_256
if( partitioner.currArea().lwidth() > maxSize || partitioner.currArea().lheight() > maxSize )
#else
if (partitioner.currArea().lwidth() > 64 || partitioner.currArea().lheight() > 64)
#endif
{
if (cs.picture->blocks[partitioner.chType].contains(partitioner.currArea().blocks[partitioner.chType].pos()))
{
coding_tree(cs, partitioner, cuCtx, pPartitionerChroma, pCuCtxChroma);
}
lumaContinue = partitioner.nextPart(cs);
chromaContinue = pPartitionerChroma->nextPart(cs);
CHECK(lumaContinue != chromaContinue, "luma chroma partition should be matched");
beContinue = lumaContinue;
}
else
{
//dual tree coding under 64x64 block
if (cs.picture->blocks[partitioner.chType].contains(partitioner.currArea().blocks[partitioner.chType].pos()))
{
coding_tree(cs, partitioner, cuCtx);
}
lumaContinue = partitioner.nextPart(cs);
if (cs.picture->blocks[pPartitionerChroma->chType].contains(pPartitionerChroma->currArea().blocks[pPartitionerChroma->chType].pos()))
{
coding_tree(cs, *pPartitionerChroma, *pCuCtxChroma);
}
chromaContinue = pPartitionerChroma->nextPart(cs);
CHECK(lumaContinue != chromaContinue, "luma chroma partition should be matched");
beContinue = lumaContinue;
}
}
partitioner.exitCurrSplit();
pPartitionerChroma->exitCurrSplit();
}
else
{
#endif //!JVET_AI0136_ADAPTIVE_DUAL_TREE
#if !INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS
const ModeType modeTypeParent = partitioner.modeType;
const ModeType modeTypeChild = CU::getModeTypeAtDepth( cu, partitioner.currDepth );
mode_constraint( splitMode, cs, partitioner, modeTypeChild );
partitioner.modeType = modeTypeChild;
bool chromaNotSplit = modeTypeParent == MODE_TYPE_ALL && modeTypeChild == MODE_TYPE_INTRA ? true : false;
CHECK( chromaNotSplit && partitioner.chType != CHANNEL_TYPE_LUMA, "chType must be luma" );
if( partitioner.treeType == TREE_D )
{
partitioner.treeType = chromaNotSplit ? TREE_L : TREE_D;
}
#endif
partitioner.splitCurrArea( splitMode, cs );
do
{
if( cs.picture->blocks[partitioner.chType].contains( partitioner.currArea().blocks[partitioner.chType].pos() ) )
{
#if JVET_AI0136_ADAPTIVE_DUAL_TREE
coding_tree( cs, partitioner, cuCtx, qps );
#else
coding_tree( cs, partitioner, cuCtx );
#endif
}
} while( partitioner.nextPart( cs ) );
partitioner.exitCurrSplit();
#if !INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS
if( chromaNotSplit )
{
if (isChromaEnabled(cs.pcv->chrFormat))
{
CHECK( partitioner.chType != CHANNEL_TYPE_LUMA, "must be luma status" );
partitioner.chType = CHANNEL_TYPE_CHROMA;
partitioner.treeType = TREE_C;
if( cs.picture->blocks[partitioner.chType].contains( partitioner.currArea().blocks[partitioner.chType].pos() ) )
{
coding_tree( cs, partitioner, cuCtx );
}
}
//recover
partitioner.chType = CHANNEL_TYPE_LUMA;
partitioner.treeType = TREE_D;
}
partitioner.modeType = modeTypeParent;
#endif
#if !JVET_AI0136_ADAPTIVE_DUAL_TREE
}
#endif
return;
}
// Predict QP on start of quantization group
if( cuCtx.qgStart )
{
cuCtx.qgStart = false;
cuCtx.qp = CU::predictQP( cu, cuCtx.qp );
}
#if !INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS
CHECK( cu.treeType != partitioner.treeType, "treeType mismatch" );
#endif
#if JVET_AG0117_CABAC_SPATIAL_TUNING
// If context data collection is active and if on bottom of the CTU, start the counters
if ( m_BinEncoder.getBinBuffer() )
{
m_BinEncoder.setBinBufferActive( CU::isOnCtuBottom( cu ) );
}
#endif
// coding unit
#if !JVET_AI0136_ADAPTIVE_DUAL_TREE
DTRACE(g_trace_ctx, D_SYNTAX, "coding_unit() pos=(%d,%d) size=%dx%d chType=%d depth=%d\n", cu.blocks[cu.chType].x, cu.blocks[cu.chType].y, cu.blocks[cu.chType].width, cu.blocks[cu.chType].height, cu.chType, cu.depth);
#endif
coding_unit( cu, partitioner, cuCtx );
#if JVET_AG0117_CABAC_SPATIAL_TUNING
// Done with the data collection for this CU
if ( m_BinEncoder.getBinBuffer() )
{
m_BinEncoder.setBinBufferActive( false );
}
#endif
#if JVET_AI0136_ADAPTIVE_DUAL_TREE
if ( cs.slice->getSeparateTreeEnabled() && (CU::isIntra( cu ) || cu.slice->isIntra()) && !cs.slice->getProcessingIntraRegion() && cu.isSST && cu.separateTree)
{
Partitioner *partitionerSST = g_encPartitionerSST;
partitionerSST->copyState( partitioner );
partitionerSST->chType = CH_L;
cs.slice->setProcessingIntraRegion ( true );
cs.slice->setProcessingSeparateTrees ( cu.separateTree );
cs.slice->setIntraRegionRoot ( &partitioner );
cs.slice->setProcessingChannelType ( CH_L );
coding_tree( cs, *partitionerSST, cuCtx, qps );
qps[CH_L] = cuCtx.qp;
if ( cu.separateTree )
{
CUCtx cuCtxChroma( qps[CH_C] );
cs.slice->setProcessingChannelType ( CH_C );
partitionerSST->copyState ( partitioner );
partitionerSST->chType = CH_C;
coding_tree( cs, *partitionerSST, cuCtx, qps );
qps[CH_C] = cuCtxChroma.qp;
}
cs.slice->setProcessingIntraRegion( false );
}
#endif
#if !INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS
if( cu.chType == CHANNEL_TYPE_CHROMA )
{
DTRACE_COND( (isEncoding()), g_trace_ctx, D_QP, "[chroma CU]x=%d, y=%d, w=%d, h=%d, qp=%d\n", cu.Cb().x, cu.Cb().y, cu.Cb().width, cu.Cb().height, cu.qp );
}
else
{
#endif
DTRACE_COND( ( isEncoding() ), g_trace_ctx, D_QP, "x=%d, y=%d, w=%d, h=%d, qp=%d\n", cu.Y().x, cu.Y().y, cu.Y().width, cu.Y().height, cu.qp );
#if !INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS
}
#endif
DTRACE_BLOCK_REC_COND( ( !isEncoding() ), cs.picture->getRecoBuf( cu ), cu, cu.predMode );
if (CU::isInter(cu))
{
DTRACE_MOT_FIELD(g_trace_ctx, *cu.firstPU);
}
}
#if !INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS
void CABACWriter::mode_constraint( const PartSplit split, const CodingStructure& cs, Partitioner& partitioner, const ModeType modeType )
{
CHECK( split == CU_DONT_SPLIT, "splitMode shall not be no split" );
int val = cs.signalModeCons( split, partitioner, partitioner.modeType );
if( val == LDT_MODE_TYPE_SIGNAL )
{
CHECK( modeType == MODE_TYPE_ALL, "shall not be no constraint case" );
bool flag = modeType == MODE_TYPE_INTRA;
int ctxIdx = DeriveCtx::CtxModeConsFlag( cs, partitioner );
m_BinEncoder.encodeBin( flag, Ctx::ModeConsFlag( ctxIdx ) );
DTRACE( g_trace_ctx, D_SYNTAX, "mode_cons_flag() flag=%d\n", flag );
}
else if( val == LDT_MODE_TYPE_INFER )
{
assert( modeType == MODE_TYPE_INTRA );
}
else
{
assert( modeType == partitioner.modeType );
}
}
#endif
void CABACWriter::split_cu_mode( const PartSplit split, const CodingStructure& cs, Partitioner& partitioner
#if JVET_AI0136_ADAPTIVE_DUAL_TREE
, const CodingUnit* cu
#endif
#if JVET_AI0087_BTCUS_RESTRICTION
, bool updatePartInfo
#endif
)
{
#if JVET_AI0087_BTCUS_RESTRICTION
bool disableBTV = false;
bool disableBTH = false;
if (CABACWriter::isLumaNonBoundaryCu(partitioner, cs.picture->lwidth(), cs.picture->lheight())
#if JVET_AI0136_ADAPTIVE_DUAL_TREE
&& (!(cs.slice->getProcessingIntraRegion() && cs.slice->getProcessingSeparateTrees()) || cs.slice->isIntra())
#endif
)
{
if ((partitioner.currBtDepth == 0) && (partitioner.currArea().lwidth() == partitioner.currArea().lheight()))
{
if (updatePartInfo)
{
CABACWriter::setBtFirstPart(partitioner, partitioner.currArea().lwidth(), CTU_LEVEL);
}
}
if ((partitioner.currBtDepth == 1) && (partitioner.currPartIdx() == 1))
{
if (partitioner.currPartLevel().split == CU_HORZ_SPLIT) // BTH Case
{
if (updatePartInfo)
{
if (partitioner.currArea().lwidth() == 128 && partitioner.btFirstPartDecs[0] == CU_VERT_SPLIT)
{
disableBTV = true;
}
else if (partitioner.currArea().lwidth() == 64 && partitioner.btFirstPartDecs[1] == CU_VERT_SPLIT)
{
disableBTV = true;
}
else if (partitioner.currArea().lwidth() == 32 && partitioner.btFirstPartDecs[2] == CU_VERT_SPLIT)
{
disableBTV = true;
}
else if (partitioner.currArea().lwidth() == 16 && partitioner.btFirstPartDecs[3] == CU_VERT_SPLIT)
{
disableBTV = true;
}
}
else
{
if (partitioner.currArea().lwidth() == 128 && cs.btFirstPartDecs[0] == CU_VERT_SPLIT)
{
disableBTV = true;
}
else if (partitioner.currArea().lwidth() == 64 && cs.btFirstPartDecs[1] == CU_VERT_SPLIT)
{
disableBTV = true;
}
else if (partitioner.currArea().lwidth() == 32 && cs.btFirstPartDecs[2] == CU_VERT_SPLIT)
{
disableBTV = true;
}
else if (partitioner.currArea().lwidth() == 16 && cs.btFirstPartDecs[3] == CU_VERT_SPLIT)
{
disableBTV = true;
}
}
}
else if (partitioner.currPartLevel().split == CU_VERT_SPLIT) // BTV Case
{
if (updatePartInfo)
{
if (partitioner.currArea().lheight() == 128 && partitioner.btFirstPartDecs[0] == CU_HORZ_SPLIT)
{
disableBTH = true;
}
else if (partitioner.currArea().lheight() == 64 && partitioner.btFirstPartDecs[1] == CU_HORZ_SPLIT)
{
disableBTH = true;
}
else if (partitioner.currArea().lheight() == 32 && partitioner.btFirstPartDecs[2] == CU_HORZ_SPLIT)
{
disableBTH = true;
}
else if (partitioner.currArea().lheight() == 16 && partitioner.btFirstPartDecs[3] == CU_HORZ_SPLIT)
{
disableBTH = true;
}
}
else
{
if (partitioner.currArea().lheight() == 128 && cs.btFirstPartDecs[0] == CU_HORZ_SPLIT)
{
disableBTH = true;
}
else if (partitioner.currArea().lheight() == 64 && cs.btFirstPartDecs[1] == CU_HORZ_SPLIT)
{
disableBTH = true;
}
else if (partitioner.currArea().lheight() == 32 && cs.btFirstPartDecs[2] == CU_HORZ_SPLIT)
{
disableBTH = true;
}
else if (partitioner.currArea().lheight() == 16 && cs.btFirstPartDecs[3] == CU_HORZ_SPLIT)
{
disableBTH = true;
}
}
}
}
}
#endif
bool canNo, canQt, canBh, canBv, canTh, canTv;
#if JVET_AH0135_TEMPORAL_PARTITIONING
unsigned maxMtt;
partitioner.canSplit( cs, canNo, canQt, canBh, canBv, canTh, canTv, maxMtt
#if JVET_AI0087_BTCUS_RESTRICTION
, disableBTV, disableBTH
#endif
);
#else
partitioner.canSplit( cs, canNo, canQt, canBh, canBv, canTh, canTv
#if JVET_AI0087_BTCUS_RESTRICTION
, disableBTV, disableBTH
#endif
);
#endif
bool canSpl[6] = { canNo, canQt, canBh, canBv, canTh, canTv };
unsigned ctxSplit = 0, ctxQtSplit = 0, ctxBttHV = 0, ctxBttH12 = 0, ctxBttV12;
DeriveCtx::CtxSplit( cs, partitioner, ctxSplit, ctxQtSplit, ctxBttHV, ctxBttH12, ctxBttV12, canSpl
#if JVET_AI0087_BTCUS_RESTRICTION
, disableBTV, disableBTH
#endif
);
const bool canSplit = canBh || canBv || canTh || canTv || canQt;
#if JVET_AI0136_ADAPTIVE_DUAL_TREE
bool isNo = split == CU_DONT_SPLIT;
#else
const bool isNo = split == CU_DONT_SPLIT;
#endif
#if JVET_AI0136_ADAPTIVE_DUAL_TREE
if ( cu != nullptr && cs.slice->getSeparateTreeEnabled() && !cs.slice->getProcessingIntraRegion() && (CU::isIntra( *cu ) || cu->cs->slice->isIntra()) && CU::isIntraRegionRoot(*cu, partitioner))
{
//split = false;
isNo=true;
#if JVET_AI0136_ADAPTIVE_DUAL_TREE
if ( cs.slice->isIntra() && cs.slice->getSeparateTreeEnabled() && !cs.slice->getProcessingIntraRegion() && ( partitioner.currArea().lwidth() <= 256 && partitioner.currArea().lheight() <= 256 ) )
{
#if ENABLE_TRACING
const CompArea& block = partitioner.currArea().blocks[partitioner.chType];
#endif
DTRACE( g_trace_ctx, D_SYNTAX, "split_cu_mode() pos=(%d,%d) size=%dx%d chType=%d ctx=%d split=%d\n", block.x, block.y, block.width, block.height, partitioner.chType, ctxSplit, !isNo);
return;
}
#endif
}
#endif
#if JVET_AH0135_TEMPORAL_PARTITIONING
bool canBtt = canBh || canBv || canTh || canTv;
#if JVET_AI0136_ADAPTIVE_DUAL_TREE
const bool isQt = split == CU_QUAD_SPLIT && !isNo;
#else
const bool isQt = split == CU_QUAD_SPLIT;
#endif
#endif
if( canNo && canSplit )
{
#if JVET_AH0135_TEMPORAL_PARTITIONING
bool colSplitPredExist = false;
SplitPred currentSplitPred;
Picture* pColPic = cs.slice->getRefPic(RefPicList(cs.slice->isInterB() ? 1 - cs.slice->getColFromL0Flag() : 0), cs.slice->getColRefIdx());
if (!cs.slice->isIntra() && pColPic != NULL && pColPic->cs->slice != NULL
&& (pColPic->cs->area.Y().contains(partitioner.currArea().blocks[partitioner.chType].pos().offset((partitioner.currArea().blocks[partitioner.chType].lumaSize().width) >> 1,
((partitioner.currArea().blocks[partitioner.chType].lumaSize().height) >> 1)))))
{
currentSplitPred = pColPic->cs->getQtDepthInfo(partitioner.currArea().blocks[partitioner.chType].pos().offset((partitioner.currArea().blocks[partitioner.chType].lumaSize().width) >> 1,
((partitioner.currArea().blocks[partitioner.chType].lumaSize().height) >> 1)));
colSplitPredExist = true;
}
if (colSplitPredExist && (partitioner.currQtDepth < currentSplitPred.qtDetphCol))
{
if (canQt && canBtt)
{
m_BinEncoder.encodeBin(isQt, Ctx::SplitQtFlag(ctxQtSplit));
canBtt = false;
if (isQt)
{
return;
}
else
{
m_BinEncoder.encodeBin(!isNo, Ctx::SplitFlag(ctxSplit));
}
}
else
{
m_BinEncoder.encodeBin(!isNo, Ctx::SplitFlag(ctxSplit));
}
}
else
{
#endif
m_BinEncoder.encodeBin(!isNo, Ctx::SplitFlag(ctxSplit));
#if JVET_AH0135_TEMPORAL_PARTITIONING
}
#endif
#if JVET_AI0136_ADAPTIVE_DUAL_TREE
DTRACE( g_trace_ctx, D_SYNTAX, "split_cu_mode() ctx=%d split=%d\n", ctxSplit, !isNo );
#endif
}
#if JVET_AI0136_ADAPTIVE_DUAL_TREE // FLL to check later
if ( cu != nullptr && cs.slice->getSeparateTreeEnabled() && !cs.slice->getProcessingIntraRegion() && CU::isIntra( *cu ) && CU::isIntraRegionRoot( *cu, partitioner ) )
{
canBh = canBv = canTh = canTv = false;
}
#endif
#if ENABLE_TRACING
const CompArea& block = partitioner.currArea().blocks[partitioner.chType];
#endif
DTRACE( g_trace_ctx, D_SYNTAX, "split_cu_mode() pos=(%d,%d) size=%dx%d chType=%d ctx=%d split=%d\n", block.x, block.y, block.width, block.height, partitioner.chType, ctxSplit, !isNo);
if( isNo )
{
return;
}
#if !JVET_AH0135_TEMPORAL_PARTITIONING
const bool canBtt = canBh || canBv || canTh || canTv;
const bool isQt = split == CU_QUAD_SPLIT;
#endif
if( canQt && canBtt )
{
m_BinEncoder.encodeBin( isQt, Ctx::SplitQtFlag( ctxQtSplit ) );
}
DTRACE( g_trace_ctx, D_SYNTAX, "split_cu_mode() pos=(%d,%d) size=%dx%d chType=%d ctx=%d qt=%d\n", block.x, block.y, block.width, block.height, partitioner.chType, ctxQtSplit, isQt );
if( isQt )
{
return;
}
const bool canHor = canBh || canTh;
const bool canVer = canBv || canTv;
const bool isVer = split == CU_VERT_SPLIT || split == CU_TRIV_SPLIT;
if( canVer && canHor )
{
m_BinEncoder.encodeBin( isVer, Ctx::SplitHvFlag( ctxBttHV ) );
}
const bool can14 = isVer ? canTv : canTh;
const bool can12 = isVer ? canBv : canBh;
const bool is12 = isVer ? ( split == CU_VERT_SPLIT ) : ( split == CU_HORZ_SPLIT );
if( can12 && can14 )
{
m_BinEncoder.encodeBin( is12, Ctx::Split12Flag( isVer ? ctxBttV12 : ctxBttH12 ) );
}
#if JVET_AI0087_BTCUS_RESTRICTION
if (CABACWriter::isLumaNonBoundaryCu(partitioner, cs.picture->lwidth(), cs.picture->lheight())
#if JVET_AI0136_ADAPTIVE_DUAL_TREE
&& (!(cs.slice->getProcessingIntraRegion() && cs.slice->getProcessingSeparateTrees()) || cs.slice->isIntra())
#endif
)
{
if (updatePartInfo && (partitioner.currBtDepth == 1) && (partitioner.currPartIdx() == 0))
{
if (partitioner.currPartLevel().split == CU_HORZ_SPLIT) // BTH Case
{
if (split == CU_VERT_SPLIT)
{
CABACWriter::setBtFirstPart(partitioner, partitioner.currArea().lwidth(), CU_VERT_SPLIT);
}
else
{
CABACWriter::setBtFirstPart(partitioner, partitioner.currArea().lwidth(), CTU_LEVEL);
}
}
else if (partitioner.currPartLevel().split == CU_VERT_SPLIT) // BTV Case
{
if (split == CU_HORZ_SPLIT)
{
CABACWriter::setBtFirstPart(partitioner, partitioner.currArea().lheight(), CU_HORZ_SPLIT);
}
else
{
CABACWriter::setBtFirstPart(partitioner, partitioner.currArea().lheight(), CTU_LEVEL);
}
}
}
}
#endif
DTRACE( g_trace_ctx, D_SYNTAX, "split_cu_mode() pos=(%d,%d) size=%dx%d chType=%d ctxHv=%d ctx12=%d mode=%d\n", block.x, block.y, block.width, block.height, partitioner.chType, ctxBttHV, isVer ? ctxBttV12 : ctxBttH12, split);
}
//================================================================================
// clause 7.3.8.5
//--------------------------------------------------------------------------------
// void coding_unit ( cu, partitioner, cuCtx )
// void cu_skip_flag ( cu )
// void pred_mode ( cu )
// void part_mode ( cu )
// void cu_pred_data ( pus )
// void cu_lic_flag ( cu )
// void intra_luma_pred_modes ( pus )
// void intra_chroma_pred_mode ( pu )
// void cu_residual ( cu, partitioner, cuCtx )
// void rqt_root_cbf ( cu )
// void end_of_ctu ( cu, cuCtx )
//================================================================================
void CABACWriter::coding_unit( const CodingUnit& cu, Partitioner& partitioner, CUCtx& cuCtx )
{
#if !INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS
DTRACE( g_trace_ctx, D_SYNTAX, "coding_unit() treeType=%d modeType=%d\n", cu.treeType, cu.modeType );
#endif
CodingStructure& cs = *cu.cs;
// skip flag
#if JVET_AI0136_ADAPTIVE_DUAL_TREE
if ( !cu.slice->getSeparateTreeEnabled() || !cu.slice->getProcessingIntraRegion() || (cu.slice->isIntra() && cu.slice->getUseIBC()) )
{
#endif
#if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
if ((!cs.slice->isIntra() || cs.slice->getUseIBC()) && cu.Y().valid())
#else
if ((!cs.slice->isIntra() || cs.slice->getSPS()->getIBCFlag()) && cu.Y().valid())
#endif
{
#if JVET_AG0117_CABAC_SPATIAL_TUNING && JVET_AI0136_ADAPTIVE_DUAL_TREE
// If context data collection is active and if on bottom of the CTU, start the counters
if ( m_BinEncoder.getBinBuffer() )
{
m_BinEncoder.setBinBufferActive( CU::isPartitionerOnCtuBottom( cu, partitioner ) );
}
#endif
#if JVET_AI0136_ADAPTIVE_DUAL_TREE
cu_skip_flag(cu, partitioner);
#else
cu_skip_flag( cu );
#endif
#if JVET_AG0117_CABAC_SPATIAL_TUNING && JVET_AI0136_ADAPTIVE_DUAL_TREE
// If context data collection is active and if on bottom of the CTU, start the counters
if ( /*CU::isPartitionerOnCtuBottom( cu, partitioner ) &&*/ !CU::isOnCtuBottom(cu))
{
m_BinEncoder.setBinBufferActive( false );
}
#endif
}
// skip data
#if JVET_AI0136_ADAPTIVE_DUAL_TREE
if ( !cu.slice->isIntra() ||
(cu.slice->isIntra() && cu.cs->slice->getUseIBC() && cu.slice->getSPS()->getUseIbcMerge()
&& partitioner.currArea().lwidth() < 128 && partitioner.currArea().lheight() < 128 && cu.lwidth() < 128 && cu.lheight() < 128) // disable IBC mode larger than 64x64
)
#endif
if( cu.skip )
{
#if JVET_AI0136_ADAPTIVE_DUAL_TREE
DTRACE(g_trace_ctx, D_SYNTAX, "coding_unit() pos=(%d,%d) size=%dx%d chType=%d depth=%d\n", cu.blocks[cu.chType].x, cu.blocks[cu.chType].y, cu.blocks[cu.chType].width, cu.blocks[cu.chType].height, cu.chType, cu.depth);
#endif
CHECK( !cu.firstPU->mergeFlag, "Merge flag has to be on!" );
CHECK(cu.colorTransform, "ACT should not be enabled for skip mode");
PredictionUnit& pu = *cu.firstPU;
prediction_unit ( pu );
#if INTER_LIC
cu_lic_flag(cu);
#endif
end_of_ctu ( cu, cuCtx );
return;
}
// prediction mode and partitioning data
#if JVET_AI0136_ADAPTIVE_DUAL_TREE
#if JVET_AG0117_CABAC_SPATIAL_TUNING
// If context data collection is active and if on bottom of the CTU, start the counters
if ( m_BinEncoder.getBinBuffer() )
{
m_BinEncoder.setBinBufferActive( CU::isPartitionerOnCtuBottom( cu, partitioner ) );
}
#endif
pred_mode( cu , partitioner);
#if JVET_AG0117_CABAC_SPATIAL_TUNING
// If context data collection is active and if on bottom of the CTU, start the counters
if ( /*CU::isPartitionerOnCtuBottom( cu, partitioner ) &&*/ !CU::isOnCtuBottom(cu))
{
m_BinEncoder.setBinBufferActive( false );
}
#endif
if (!cu.slice->getSeparateTreeEnabled() || !cu.slice->getProcessingIntraRegion())
{
#if JVET_AG0117_CABAC_SPATIAL_TUNING
// If context data collection is active and if on bottom of the CTU, start the counters
if ( m_BinEncoder.getBinBuffer() )
{
m_BinEncoder.setBinBufferActive( CU::isPartitionerOnCtuBottom( cu, partitioner ) );
}
#endif
separate_tree_cu_flag(cu, partitioner);
#if JVET_AG0117_CABAC_SPATIAL_TUNING
// If context data collection is active and if on bottom of the CTU, start the counters
if ( /*CU::isPartitionerOnCtuBottom( cu, partitioner ) &&*/ !CU::isOnCtuBottom(cu))
{
m_BinEncoder.setBinBufferActive( false );
}
#endif
if (cu.slice->getSeparateTreeEnabled() && (CU::isIntra(cu) || cu.slice->isIntra()) && cu.isSST && !cu.slice->getProcessingIntraRegion() && cu.separateTree)
{
return;
}
}
}
#else
pred_mode ( cu );
#endif
#if JVET_AI0136_ADAPTIVE_DUAL_TREE
DTRACE(g_trace_ctx, D_SYNTAX, "coding_unit() pos=(%d,%d) size=%dx%d chType=%d depth=%d\n", cu.blocks[cu.chType].x, cu.blocks[cu.chType].y, cu.blocks[cu.chType].width, cu.blocks[cu.chType].height, cu.chType, cu.depth);
#endif
#if ENABLE_DIMD
cu_dimd_flag( cu );
#endif
if (CU::isIntra(cu))
{
adaptive_color_transform(cu);
}
if (CU::isPLT(cu))
{
CHECK(cu.colorTransform, "ACT should not be enabled for PLT mode");
#if INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS
if (CS::isDualITree(*cu.cs))
#else
if (cu.isSepTree())
#endif
{
if (isLuma(partitioner.chType))
{
cu_palette_info(cu, COMPONENT_Y, 1, cuCtx);
}
if (cu.chromaFormat != CHROMA_400 && (partitioner.chType == CHANNEL_TYPE_CHROMA))
{
cu_palette_info(cu, COMPONENT_Cb, 2, cuCtx);
}
}
else
{
if( cu.chromaFormat != CHROMA_400 )
{
cu_palette_info(cu, COMPONENT_Y, 3, cuCtx);
}
else
{
cu_palette_info(cu, COMPONENT_Y, 1, cuCtx);
}
}
end_of_ctu(cu, cuCtx);
return;
}
// prediction data ( intra prediction modes / reference indexes + motion vectors )
cu_pred_data( cu );
// residual data ( coded block flags + transform coefficient levels )
cu_residual( cu, partitioner, cuCtx );
// end of cu
end_of_ctu( cu, cuCtx );
}
#if JVET_AI0136_ADAPTIVE_DUAL_TREE
void CABACWriter::cu_skip_flag( const CodingUnit& cu , Partitioner& partitioner)
#else
void CABACWriter::cu_skip_flag( const CodingUnit& cu )
#endif
{
#if JVET_AI0136_ADAPTIVE_DUAL_TREE
if ( cu.slice->getSeparateTreeEnabled() && cu.slice->getProcessingIntraRegion() && !cu.slice->getSPS()->getUseIbcMerge() )
{
return;
}
#endif
#if MULTI_HYP_PRED
CHECK(cu.skip && cu.firstPU->numMergedAddHyps != cu.firstPU->addHypData.size(), "Multi Hyp: cu.skip && cu.firstPU->numMergedAddHyps != cu.firstPU->addHypData.size()");
CHECK(cu.skip && !cu.firstPU->mergeFlag, "merge_flag has to be true for skipped CUs");
#endif
unsigned ctxId = DeriveCtx::CtxSkipFlag( cu );
#if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
#if INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS
if (cu.slice->isIntra() && cu.cs->slice->getUseIBC())
#else
if ((cu.slice->isIntra() || cu.isConsIntra()) && cu.cs->slice->getUseIBC())
#endif
#else
#if INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS
if (cu.slice->isIntra() && cu.cs->slice->getSPS()->getIBCFlag())
#else
if ((cu.slice->isIntra() || cu.isConsIntra()) && cu.cs->slice->getSPS()->getIBCFlag())
#endif
#endif
{
#if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
if( !cu.slice->getSPS()->getUseIbcMerge() )
{
return;
}
#endif
#if JVET_AI0136_ADAPTIVE_DUAL_TREE
if (partitioner.currArea().lwidth() < 128 && partitioner.currArea().lheight() < 128 && cu.lwidth() < 128 && cu.lheight() < 128) // disable IBC mode larger than 64x64
#else
if (cu.lwidth() < 128 && cu.lheight() < 128) // disable IBC mode larger than 64x64
#endif
{
m_BinEncoder.encodeBin((cu.skip), Ctx::SkipFlag(ctxId));
DTRACE(g_trace_ctx, D_SYNTAX, "cu_skip_flag() ctx=%d skip=%d\n", ctxId, cu.skip ? 1 : 0);
}
return;
}
#if !INTER_RM_SIZE_CONSTRAINTS
#if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
if ( !cu.cs->slice->getUseIBC() && cu.lwidth() == 4 && cu.lheight() == 4 )
#else
if ( !cu.cs->slice->getSPS()->getIBCFlag() && cu.lwidth() == 4 && cu.lheight() == 4 )
#endif
{
return;
}
#endif
#if !INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS
#if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
if( !cu.cs->slice->getUseIBC() && cu.isConsIntra() )
#else
if( !cu.cs->slice->getSPS()->getIBCFlag() && cu.isConsIntra() )
#endif
{
return;
}
#endif
m_BinEncoder.encodeBin( ( cu.skip ), Ctx::SkipFlag( ctxId ) );
DTRACE( g_trace_ctx, D_SYNTAX, "cu_skip_flag() ctx=%d skip=%d\n", ctxId, cu.skip ? 1 : 0 );
#if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
if (cu.skip && cu.cs->slice->getUseIBC())
#else
if (cu.skip && cu.cs->slice->getSPS()->getIBCFlag())
#endif
{
#if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
if( !cu.slice->getSPS()->getUseIbcMerge() )
{
CHECK( CU::isIBC( cu ), "IBC skip shall not be used with IBC merge disabled" );
}
else
#endif
#if INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS
if (cu.lwidth() < 128 && cu.lheight() < 128 ) // disable IBC mode larger than 64x64 and disable IBC when only allowing inter mode
#else
if (cu.lwidth() < 128 && cu.lheight() < 128 && !cu.isConsInter()) // disable IBC mode larger than 64x64 and disable IBC when only allowing inter mode
#endif
{
#if !INTER_RM_SIZE_CONSTRAINTS
if ( cu.lwidth() == 4 && cu.lheight() == 4 )
{
return;
}
#endif
unsigned ctxidx = DeriveCtx::CtxIBCFlag(cu);
m_BinEncoder.encodeBin(CU::isIBC(cu) ? 1 : 0, Ctx::IBCFlag(ctxidx));
DTRACE(g_trace_ctx, D_SYNTAX, "ibc() ctx=%d cu.predMode=%d\n", ctxidx, cu.predMode);
}
}
#if JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0
if (cu.skip && CU::interCcpMergeZeroRootCbfAllowed(cu))
{
inter_ccp_merge_root_cbf_zero(cu);
}
#endif
}
#if JVET_AI0136_ADAPTIVE_DUAL_TREE
void CABACWriter::separate_tree_cu_flag( const CodingUnit& cu, Partitioner& partitioner )
{
unsigned ctxId = 0;
bool inferredSeparateTreeFlag = false;
#if JVET_AI0136_ADAPTIVE_DUAL_TREE
if ( cu.slice->getSeparateTreeEnabled() && !cu.slice->getProcessingIntraRegion() && (CU::isIntra( cu ) || cu.slice->isIntra()) && CU::isIntraRegionRoot(cu, partitioner))
#else
if ( cu.slice->getSeparateTreeEnabled() && !cu.slice->getProcessingIntraRegion() && CU::isIntra( cu ) && CU::isIntraRegionRoot( cu, partitioner ) )
#endif
{
bool canSplit = partitioner.canSplit( CU_QUAD_SPLIT, *cu.cs
#if JVET_AI0087_BTCUS_RESTRICTION
, false, false
#endif
);
canSplit = canSplit || partitioner.canSplit( CU_MT_SPLIT, *cu.cs
#if JVET_AI0087_BTCUS_RESTRICTION
, false, false
#endif
);
cu.cs->determineIfSeparateTreeFlagInferred( inferredSeparateTreeFlag, partitioner.currArea().lumaSize().width, partitioner.currArea().lumaSize().height, canSplit );
if ( !inferredSeparateTreeFlag )
{
ctxId = DeriveCtx::CtxCUSeparateTree( *cu.cs, partitioner );
m_BinEncoder.encodeBin( cu.separateTree, Ctx::SeparateTree( ctxId ) );
}
DTRACE( g_trace_ctx, D_SYNTAX, "separate_tree_cu_flag() pred_mode=%d, separateTree=%d, ctxId=%d, inferredSeparateTreeFlag=%d, processingIntraRegion=%d, (x=%d, y=%d, w=%d, h=%d)\n", cu.predMode ? 1 : 0, cu.separateTree, ctxId, inferredSeparateTreeFlag ? 1 : 0, cu.cs->slice->getProcessingIntraRegion() ? 1: 0, cu.lumaPos().x, cu.lumaPos().y, partitioner.currArea().lumaSize().width, partitioner.currArea().lumaSize().height );
//DTRACE( g_trace_ctx, D_SYNTAX, "separate_tree_cu_flag() pred_mode=%d, separateTree=%d, ctxId=%d, inferredSeparateTreeFlag=%d, processingSST=%d, (x=%d, y=%d, w=%d, h=%d)\n", cu.predMode ? 1 : 0, cu.separateTree, ctxId, inferredSeparateTreeFlag ? 1 : 0, cu.cs->slice->getProcessingIntraRegion() ? 1: 0, cu.lumaPos().x, cu.lumaPos().y, partitioner.currArea().lumaSize().width, partitioner.currArea().lumaSize().height );
}
}
#endif
#if JVET_AI0136_ADAPTIVE_DUAL_TREE
void CABACWriter::pred_mode( const CodingUnit& cu , Partitioner& partitioner )
#else
void CABACWriter::pred_mode( const CodingUnit& cu )
#endif
{
#if JVET_AI0136_ADAPTIVE_DUAL_TREE
if ( cu.slice->getSeparateTreeEnabled() && cu.slice->getProcessingIntraRegion() && !(cu.cs->slice->getUseIBC() && cu.chType != CHANNEL_TYPE_CHROMA)
&& !(cu.cs->slice->getSPS()->getPLTMode())
)
{
DTRACE(g_trace_ctx, D_SYNTAX, "pred_mode() pred_mode=%d\n", cu.predMode);
return;
}
#endif
#if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
if (cu.cs->slice->getUseIBC() && cu.chType != CHANNEL_TYPE_CHROMA)
#else
if (cu.cs->slice->getSPS()->getIBCFlag() && cu.chType != CHANNEL_TYPE_CHROMA)
#endif
{
#if !INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS
if( cu.isConsInter() )
{
assert( CU::isInter( cu ) );
return;
}
#endif
#if INTER_RM_SIZE_CONSTRAINTS
#if INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS
if (cu.cs->slice->isIntra())
#else
if ( cu.cs->slice->isIntra() || cu.isConsIntra() )
#endif
#else
#if INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS
if (cu.cs->slice->isIntra() || (cu.lwidth() == 4 && cu.lheight() == 4))
#else
if ( cu.cs->slice->isIntra() || ( cu.lwidth() == 4 && cu.lheight() == 4 ) || cu.isConsIntra() )
#endif
#endif
{
#if JVET_AI0136_ADAPTIVE_DUAL_TREE
if (partitioner.currArea().lwidth() < 128 && partitioner.currArea().lheight() < 128 &&
cu.lwidth() < 128 && cu.lheight() < 128) // disable IBC mode larger than 64x64
#else
if (cu.lwidth() < 128 && cu.lheight() < 128) // disable IBC mode larger than 64x64
#endif
{
unsigned ctxidx = DeriveCtx::CtxIBCFlag(cu);
m_BinEncoder.encodeBin(CU::isIBC(cu), Ctx::IBCFlag(ctxidx));
}
#if JVET_AI0136_ADAPTIVE_DUAL_TREE
if (!CU::isIBC(cu) && cu.cs->slice->getSPS()->getPLTMode()
&& partitioner.currArea().lwidth() < 128 && partitioner.currArea().lheight() < 128
&& cu.lwidth() <= 64 && cu.lheight() <= 64 && (cu.lumaSize().width * cu.lumaSize().height > 16) )
#else
if (!CU::isIBC(cu) && cu.cs->slice->getSPS()->getPLTMode() && cu.lwidth() <= 64 && cu.lheight() <= 64 && (cu.lumaSize().width * cu.lumaSize().height > 16) )
#endif
{
m_BinEncoder.encodeBin(CU::isPLT(cu), Ctx::PLTFlag(0));
}
}
else
{
#if !INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS
if( cu.isConsInter() )
{
return;
}
#endif
m_BinEncoder.encodeBin((CU::isIntra(cu) || CU::isPLT(cu)), Ctx::PredMode(DeriveCtx::CtxPredModeFlag(cu)));
if (CU::isIntra(cu) || CU::isPLT(cu))
{
if (cu.cs->slice->getSPS()->getPLTMode() && cu.lwidth() <= 64 && cu.lheight() <= 64 && (cu.lumaSize().width * cu.lumaSize().height > 16) )
m_BinEncoder.encodeBin(CU::isPLT(cu), Ctx::PLTFlag(0));
}
else
{
if (cu.lwidth() < 128 && cu.lheight() < 128) // disable IBC mode larger than 64x64
{
unsigned ctxidx = DeriveCtx::CtxIBCFlag(cu);
m_BinEncoder.encodeBin(CU::isIBC(cu), Ctx::IBCFlag(ctxidx));
}
}
}
}
else
{
#if !INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS
if( cu.isConsInter() )
{
assert( CU::isInter( cu ) );
return;
}
#endif
#if INTER_RM_SIZE_CONSTRAINTS
#if INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS
if (cu.cs->slice->isIntra())
#else
if ( cu.cs->slice->isIntra() || cu.isConsIntra() )
#endif
#else
#if INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS
if (cu.cs->slice->isIntra() || (cu.lwidth() == 4 && cu.lheight() == 4))
#else
if ( cu.cs->slice->isIntra() || ( cu.lwidth() == 4 && cu.lheight() == 4 ) || cu.isConsIntra() )
#endif
#endif
{
#if INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS
if (cu.cs->slice->getSPS()->getPLTMode() && cu.lwidth() <= 64 && cu.lheight() <= 64 && (((!isLuma(cu.chType)) && (cu.chromaSize().width * cu.chromaSize().height > 16)) || ((isLuma(cu.chType)) && ((cu.lumaSize().width * cu.lumaSize().height) > 16))) && (CS::isDualITree(*cu.cs) || isLuma(cu.chType)))
#else
if (cu.cs->slice->getSPS()->getPLTMode() && cu.lwidth() <= 64 && cu.lheight() <= 64 && ( ( (!isLuma(cu.chType)) && (cu.chromaSize().width * cu.chromaSize().height > 16) ) || ((isLuma(cu.chType)) && ((cu.lumaSize().width * cu.lumaSize().height) > 16 ) ) ) && (!cu.isLocalSepTree() || isLuma(cu.chType) ) )
#endif
m_BinEncoder.encodeBin((CU::isPLT(cu)), Ctx::PLTFlag(0));
}
else
{
m_BinEncoder.encodeBin((CU::isIntra(cu) || CU::isPLT(cu)), Ctx::PredMode(DeriveCtx::CtxPredModeFlag(cu)));
#if INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS
if ((CU::isIntra(cu) || CU::isPLT(cu)) && cu.cs->slice->getSPS()->getPLTMode() && cu.lwidth() <= 64 && cu.lheight() <= 64 && (((!isLuma(cu.chType)) && (cu.chromaSize().width * cu.chromaSize().height > 16)) || ((isLuma(cu.chType)) && ((cu.lumaSize().width * cu.lumaSize().height) > 16))) && (CS::isDualITree(*cu.cs) || isLuma(cu.chType)))
#else
if ((CU::isIntra(cu) || CU::isPLT(cu)) && cu.cs->slice->getSPS()->getPLTMode() && cu.lwidth() <= 64 && cu.lheight() <= 64 && (((!isLuma(cu.chType)) && (cu.chromaSize().width * cu.chromaSize().height > 16)) || ((isLuma(cu.chType)) && ((cu.lumaSize().width * cu.lumaSize().height) > 16))) && (!cu.isLocalSepTree() || isLuma(cu.chType)))
#endif
{
m_BinEncoder.encodeBin((CU::isPLT(cu)), Ctx::PLTFlag(0));
}
}
}
DTRACE(g_trace_ctx, D_SYNTAX, "pred_mode() pred_mode=%d\n", cu.predMode);
}
void CABACWriter::bdpcm_mode( const CodingUnit& cu, const ComponentID compID )
{
if( !cu.cs->sps->getBDPCMEnabledFlag() ) return;
if( !CU::bdpcmAllowed( cu, compID ) ) return;
int bdpcmMode = isLuma(compID) ? cu.bdpcmMode : cu.bdpcmModeChroma;
unsigned ctxId = isLuma(compID) ? 0 : 2;
m_BinEncoder.encodeBin(bdpcmMode > 0 ? 1 : 0, Ctx::BDPCMMode(ctxId));
if (bdpcmMode)
{
m_BinEncoder.encodeBin(bdpcmMode > 1 ? 1 : 0, Ctx::BDPCMMode(ctxId+1));
}
if (isLuma(compID))
{
DTRACE(g_trace_ctx, D_SYNTAX, "bdpcm_mode(%d) x=%d, y=%d, w=%d, h=%d, bdpcm=%d\n", CHANNEL_TYPE_LUMA, cu.lumaPos().x, cu.lumaPos().y, cu.lwidth(), cu.lheight(), cu.bdpcmMode);
}
else
{
DTRACE(g_trace_ctx, D_SYNTAX, "bdpcm_mode(%d) x=%d, y=%d, w=%d, h=%d, bdpcm=%d\n", CHANNEL_TYPE_CHROMA, cu.chromaPos().x, cu.chromaPos().y, cu.chromaSize().width, cu.chromaSize().height, cu.bdpcmModeChroma);
}
}
void CABACWriter::cu_pred_data( const CodingUnit& cu )
{
if( CU::isIntra( cu ) )
{
if( cu.Y().valid() )
{
bdpcm_mode( cu, COMPONENT_Y );
}
intra_luma_pred_modes ( cu );
#if INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS
if ((!cu.Y().valid() || (!CS::isDualITree(*cu.cs) && cu.Y().valid())) && isChromaEnabled(cu.chromaFormat))
#else
if( ( !cu.Y().valid() || ( !cu.isSepTree() && cu.Y().valid() ) ) && isChromaEnabled(cu.chromaFormat) )
#endif
{
bdpcm_mode( cu, ComponentID(CHANNEL_TYPE_CHROMA) );
}
intra_chroma_pred_modes( cu );
return;
}
if (!cu.Y().valid()) // dual tree chroma CU
{
return;
}
for( auto &pu : CU::traversePUs( cu ) )
{
prediction_unit( pu );
}
imv_mode ( cu );
affine_amvr_mode( cu );
#if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED || JVET_AC0104_IBC_BVD_PREDICTION
for (auto &pu : CU::traversePUs(cu))
{
mvsd_data(pu);
}
#endif
#if INTER_LIC
cu_lic_flag(cu);
#endif
#if !(JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED || JVET_AD0140_MVD_PREDICTION) || (JVET_AA0132_CONFIGURABLE_TM_TOOLS && (JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED || JVET_AD0140_MVD_PREDICTION))
#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && (JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED || JVET_AD0140_MVD_PREDICTION)
if (!cu.cs->sps->getUseMvdPred())
{
#endif
cu_bcw_flag(cu);
#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && (JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED || JVET_AD0140_MVD_PREDICTION)
}
#endif
#endif
#if ENABLE_OBMC
obmc_flag( cu );
#endif
}
void CABACWriter::cu_bcw_flag(const CodingUnit& cu)
{
if(!CU::isBcwIdxCoded(cu))
{
return;
}
#if JVET_X0083_BM_AMVP_MERGE_MODE
auto &pu = *cu.firstPU;
if (pu.amvpMergeModeFlag[REF_PIC_LIST_0] || pu.amvpMergeModeFlag[REF_PIC_LIST_1])
{
return;
}
#endif
CHECK(!(BCW_NUM > 1 && (BCW_NUM == 2 || (BCW_NUM & 0x01) == 1)), " !( BCW_NUM > 1 && ( BCW_NUM == 2 || ( BCW_NUM & 0x01 ) == 1 ) ) ");
const uint8_t bcwCodingIdx = (uint8_t)g_bcwCodingOrder[CU::getValidBcwIdx(cu)];
const int32_t numBcw = (cu.slice->getCheckLDC()) ? 5 : 3;
m_BinEncoder.encodeBin((bcwCodingIdx == 0 ? 0 : 1), Ctx::BcwIdx(0));
if(numBcw > 2 && bcwCodingIdx != 0)
{
const uint32_t prefixNumBits = numBcw - 2;
const uint32_t step = 1;
uint8_t idx = 1;
for(int ui = 0; ui < prefixNumBits; ++ui)
{
if (bcwCodingIdx == idx)
{
m_BinEncoder.encodeBinEP(0);
break;
}
else
{
m_BinEncoder.encodeBinEP(1);
idx += step;
}
}
}
DTRACE(g_trace_ctx, D_SYNTAX, "cu_bcw_flag() bcw_idx=%d\n", cu.bcwIdx ? 1 : 0);
#if MULTI_HYP_PRED
mh_pred_data(*cu.firstPU);
#endif
}
#if ENABLE_OBMC
void CABACWriter::obmc_flag(const CodingUnit& cu)
{
//obmc is false
if (!cu.cs->sps->getUseOBMC() || CU::isIBC(cu) || cu.predMode == MODE_INTRA
#if INTER_LIC && !JVET_AD0213_LIC_IMP
|| cu.licFlag
#endif
|| cu.lwidth() * cu.lheight() < 32
)
{
return;
}
//obmc is true
if (cu.firstPU->mergeFlag)
{
return;
}
#if JVET_AG0098_AMVP_WITH_SBTMVP
if (cu.firstPU->amvpSbTmvpFlag)
{
CHECK(!cu.obmcFlag, "obmc flag should be true for AMVP with SbTMVP mode");
return;
}
#endif
#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL
bool ctxCond = cu.affine == false || cu.firstPU->addHypData.size() > 0;
m_BinEncoder.encodeBin(cu.obmcFlag ? 1 : 0, ctxCond ? Ctx::ObmcFlag(0) : Ctx::ObmcFlag(1));
DTRACE(g_trace_ctx, D_SYNTAX, "obmc_flag() pos=(%d,%d) ctx=%d obmc_flag=%d\n", cu.lx(), cu.ly(), ctxCond ? 0 : 1, cu.obmcFlag);
#else
m_BinEncoder.encodeBin(cu.obmcFlag ? 1 : 0, Ctx::ObmcFlag());
DTRACE(g_trace_ctx, D_SYNTAX, "obmc_flag() pos=(%d,%d) obmc_flag=%d\n", cu.lx(), cu.ly(), cu.obmcFlag);
#endif
}
#endif
void CABACWriter::xWriteTruncBinCode(uint32_t symbol, uint32_t maxSymbol)
{
int thresh;
if (maxSymbol > 256)
{
int threshVal = 1 << 8;
thresh = 8;
while (threshVal <= maxSymbol)
{
thresh++;
threshVal <<= 1;
}
thresh--;
}
else
{
thresh = g_tbMax[maxSymbol];
}
int val = 1 << thresh;
assert(val <= maxSymbol);
assert((val << 1) > maxSymbol);
assert(symbol < maxSymbol);
int b = maxSymbol - val;
assert(b < val);
if (symbol < val - b)
{
m_BinEncoder.encodeBinsEP(symbol, thresh);
}
else
{
symbol += val - b;
assert(symbol < (val << 1));
assert((symbol >> 1) >= val - b);
m_BinEncoder.encodeBinsEP(symbol, thresh + 1);
}
}
void CABACWriter::extend_ref_line(const PredictionUnit& pu)
{
const CodingUnit& cu = *pu.cu;
if( !cu.Y().valid() || cu.predMode != MODE_INTRA || !isLuma( cu.chType ) || cu.bdpcmMode
#if ENABLE_DIMD
|| cu.dimd
#endif
#if JVET_AB0155_SGPM
|| cu.sgpm
#endif
)
{
return;
}
if( !cu.cs->sps->getUseMRL() )
{
return;
}
#if JVET_AH0065_RELAX_LINE_BUFFER
bool isFirstLineOfCtu = cu.block(COMPONENT_Y).y == 0;
#else
bool isFirstLineOfCtu = (((cu.block(COMPONENT_Y).y)&((cu.cs->sps)->getMaxCUWidth() - 1)) == 0);
#endif
if (isFirstLineOfCtu)
{
return;
}
int multiRefIdx = pu.multiRefIdx;
#if JVET_Y0116_EXTENDED_MRL_LIST
if (MRL_NUM_REF_LINES > 1)
{
#if JVET_W0123_TIMD_FUSION
m_BinEncoder.encodeBin(multiRefIdx != MULTI_REF_LINE_IDX[0], cu.timd ? Ctx::MultiRefLineIdx(5) : Ctx::MultiRefLineIdx(0));
#else
m_BinEncoder.encodeBin(multiRefIdx != MULTI_REF_LINE_IDX[0], Ctx::MultiRefLineIdx(0));
#endif
if (MRL_NUM_REF_LINES > 2 && multiRefIdx != MULTI_REF_LINE_IDX[0])
{
#if JVET_W0123_TIMD_FUSION
m_BinEncoder.encodeBin(multiRefIdx != MULTI_REF_LINE_IDX[1], cu.timd ? Ctx::MultiRefLineIdx(6) : Ctx::MultiRefLineIdx(1));
#else
m_BinEncoder.encodeBin(multiRefIdx != MULTI_REF_LINE_IDX[1], Ctx::MultiRefLineIdx(1));
#endif
if (MRL_NUM_REF_LINES > 3 && multiRefIdx != MULTI_REF_LINE_IDX[1]
#if JVET_W0123_TIMD_FUSION
&& !cu.timd
#endif
)
{
m_BinEncoder.encodeBin(multiRefIdx != MULTI_REF_LINE_IDX[2], Ctx::MultiRefLineIdx(2));
if (MRL_NUM_REF_LINES > 4 && multiRefIdx != MULTI_REF_LINE_IDX[2])
{
m_BinEncoder.encodeBin(multiRefIdx != MULTI_REF_LINE_IDX[3], Ctx::MultiRefLineIdx(3));
if (MRL_NUM_REF_LINES > 5 && multiRefIdx != MULTI_REF_LINE_IDX[3])
{
m_BinEncoder.encodeBin(multiRefIdx != MULTI_REF_LINE_IDX[4], Ctx::MultiRefLineIdx(4));
}
}
}
}
}
#else
if (MRL_NUM_REF_LINES > 1)
{
#if JVET_W0123_TIMD_FUSION
m_BinEncoder.encodeBin(multiRefIdx != MULTI_REF_LINE_IDX[0], cu.timd ? Ctx::MultiRefLineIdx(2) : Ctx::MultiRefLineIdx(0));
#else
m_BinEncoder.encodeBin(multiRefIdx != MULTI_REF_LINE_IDX[0], Ctx::MultiRefLineIdx(0));
#endif
if (MRL_NUM_REF_LINES > 2 && multiRefIdx != MULTI_REF_LINE_IDX[0])
{
#if JVET_W0123_TIMD_FUSION
m_BinEncoder.encodeBin(multiRefIdx != MULTI_REF_LINE_IDX[1], cu.timd ? Ctx::MultiRefLineIdx(3) : Ctx::MultiRefLineIdx(1));
#else
m_BinEncoder.encodeBin(multiRefIdx != MULTI_REF_LINE_IDX[1], Ctx::MultiRefLineIdx(1));
#endif
}
}
#endif
}
void CABACWriter::extend_ref_line(const CodingUnit& cu)
{
if ( !cu.Y().valid() || cu.predMode != MODE_INTRA || !isLuma(cu.chType) || cu.bdpcmMode
#if ENABLE_DIMD
|| cu.dimd
#endif
#if JVET_AB0155_SGPM
|| cu.sgpm
#endif
)
{
return;
}
if( !cu.cs->sps->getUseMRL() )
{
return;
}
const int numBlocks = CU::getNumPUs(cu);
const PredictionUnit* pu = cu.firstPU;
for (int k = 0; k < numBlocks; k++)
{
#if JVET_AH0065_RELAX_LINE_BUFFER
bool isFirstLineOfCtu = cu.block(COMPONENT_Y).y == 0;
#else
bool isFirstLineOfCtu = (((cu.block(COMPONENT_Y).y)&((cu.cs->sps)->getMaxCUWidth() - 1)) == 0);
#endif
if (isFirstLineOfCtu)
{
return;
}
int multiRefIdx = pu->multiRefIdx;
#if JVET_Y0116_EXTENDED_MRL_LIST
if (MRL_NUM_REF_LINES > 1)
{
#if JVET_W0123_TIMD_FUSION
m_BinEncoder.encodeBin(multiRefIdx != MULTI_REF_LINE_IDX[0], cu.timd ? Ctx::MultiRefLineIdx(5) : Ctx::MultiRefLineIdx(0));
#else
m_BinEncoder.encodeBin(multiRefIdx != MULTI_REF_LINE_IDX[0], Ctx::MultiRefLineIdx(0));
#endif
if (MRL_NUM_REF_LINES > 2 && multiRefIdx != MULTI_REF_LINE_IDX[0])
{
#if JVET_W0123_TIMD_FUSION
m_BinEncoder.encodeBin(multiRefIdx != MULTI_REF_LINE_IDX[1], cu.timd ? Ctx::MultiRefLineIdx(6) : Ctx::MultiRefLineIdx(1));
#else
m_BinEncoder.encodeBin(multiRefIdx != MULTI_REF_LINE_IDX[1], Ctx::MultiRefLineIdx(1));
#endif
if (MRL_NUM_REF_LINES > 3 && multiRefIdx != MULTI_REF_LINE_IDX[1]
#if JVET_W0123_TIMD_FUSION
&& !cu.timd
#endif
)
{
m_BinEncoder.encodeBin(multiRefIdx != MULTI_REF_LINE_IDX[2], Ctx::MultiRefLineIdx(2));
if (MRL_NUM_REF_LINES > 4 && multiRefIdx != MULTI_REF_LINE_IDX[2])
{
m_BinEncoder.encodeBin(multiRefIdx != MULTI_REF_LINE_IDX[3], Ctx::MultiRefLineIdx(3));
if (MRL_NUM_REF_LINES > 5 && multiRefIdx != MULTI_REF_LINE_IDX[3])
{
m_BinEncoder.encodeBin(multiRefIdx != MULTI_REF_LINE_IDX[4], Ctx::MultiRefLineIdx(4));
}
}
}
}
}
#else
if (MRL_NUM_REF_LINES > 1)
{
#if JVET_W0123_TIMD_FUSION
m_BinEncoder.encodeBin(multiRefIdx != MULTI_REF_LINE_IDX[0], cu.timd ? Ctx::MultiRefLineIdx(2) : Ctx::MultiRefLineIdx(0));
#else
m_BinEncoder.encodeBin(multiRefIdx != MULTI_REF_LINE_IDX[0], Ctx::MultiRefLineIdx(0));
#endif
if (MRL_NUM_REF_LINES > 2 && multiRefIdx != MULTI_REF_LINE_IDX[0])
{
#if JVET_W0123_TIMD_FUSION
m_BinEncoder.encodeBin(multiRefIdx != MULTI_REF_LINE_IDX[1], cu.timd ? Ctx::MultiRefLineIdx(3) : Ctx::MultiRefLineIdx(1));
#else
m_BinEncoder.encodeBin(multiRefIdx != MULTI_REF_LINE_IDX[1], Ctx::MultiRefLineIdx(1));
#endif
}
}
#endif
DTRACE(g_trace_ctx, D_SYNTAX, "extend_ref_line() idx=%d pos=(%d,%d) ref_idx=%d\n", k, pu->lumaPos().x, pu->lumaPos().y, pu->multiRefIdx);
pu = pu->next;
}
}
void CABACWriter::intra_luma_pred_modes( const CodingUnit& cu )
{
if( !cu.Y().valid() )
{
return;
}
#if JVET_AH0076_OBIC
if (cu.obicFlag)
{
return;
}
#endif
if( cu.bdpcmMode )
{
cu.firstPU->intraDir[0] = cu.bdpcmMode == 2? VER_IDX : HOR_IDX;
return;
}
#if JVET_V0130_INTRA_TMP
int tmpMaxSize = cu.cs->sps->getIntraTMPMaxSize();
if( cu.lwidth() <= tmpMaxSize && cu.lheight() <= tmpMaxSize )
{
tmp_flag(cu);
if( cu.tmpFlag )
{
return;
}
}
#endif
mip_flag(cu);
if (cu.mipFlag)
{
mip_pred_modes(cu);
return;
}
#if JVET_W0123_TIMD_FUSION
cu_timd_flag(cu);
#endif
#if JVET_AG0058_EIP
cu_eip_flag(cu);
if (cu.eipFlag)
{
return;
}
#endif
#if JVET_AB0155_SGPM
sgpm_flag(cu);
if (cu.sgpm)
{
return;
}
#endif
#if JVET_AD0082_TMRL_CONFIG
if (CU::allowTmrl(cu))
{
cuTmrlFlag(cu);
if (cu.tmrlFlag)
{
return;
}
}
else
{
extend_ref_line(cu);
}
#else
#if JVET_AB0157_TMRL
cuTmrlFlag(cu);
if (cu.tmrlFlag)
{
return;
}
#else
extend_ref_line( cu );
#endif
#endif
isp_mode( cu );
#if ENABLE_DIMD
if (cu.dimd)
{
return;
}
#endif
#if JVET_W0123_TIMD_FUSION
if (cu.timd)
{
return;
}
#endif
const int numBlocks = CU::getNumPUs( cu );
#if !SECONDARY_MPM
unsigned mpmPreds [4][numMPMs];
#endif
const PredictionUnit* pu = cu.firstPU;
// prev_intra_luma_pred_flag
for( int k = 0; k < numBlocks; k++ )
{
if ( pu->multiRefIdx )
{
CHECK(!pu->mpmFlag, "use of non-MPM");
}
else
{
m_BinEncoder.encodeBin(pu->mpmFlag, Ctx::IntraLumaMpmFlag());
}
pu = pu->next;
}
pu = cu.firstPU;
// mpm_idx / rem_intra_luma_pred_mode
for( int k = 0; k < numBlocks; k++ )
{
if(pu->mpmFlag)
{
const unsigned mpm_idx = pu->ipredIdx;
{
unsigned ctx = (pu->cu->ispMode == NOT_INTRA_SUBPARTITIONS ? 1 : 0);
#if SECONDARY_MPM
unsigned ctx2 = (ctx ? (pu->multiRefIdx == 0 ? 2 : 1) : 0);
#endif
if( pu->multiRefIdx == 0 )
{
m_BinEncoder.encodeBin( mpm_idx > 0, Ctx::IntraLumaPlanarFlag( ctx ) );
}
if( mpm_idx )
{
#if SECONDARY_MPM
m_BinEncoder.encodeBin(mpm_idx > 1, Ctx::IntraLumaMPMIdx(0 + ctx2));
#else
m_BinEncoder.encodeBinEP( mpm_idx > 1 );
#endif
}
if (mpm_idx > 1)
{
m_BinEncoder.encodeBinEP(mpm_idx > 2);
}
if (mpm_idx > 2)
{
m_BinEncoder.encodeBinEP(mpm_idx > 3);
}
if (mpm_idx > 3)
{
m_BinEncoder.encodeBinEP(mpm_idx > 4);
}
}
}
else
{
{
#if SECONDARY_MPM
if( pu->secondMpmFlag)
{
uint8_t secondaryMPMIdx = pu->ipredIdx - NUM_PRIMARY_MOST_PROBABLE_MODES;
m_BinEncoder.encodeBin(1, Ctx::IntraLumaSecondMpmFlag());
#if JVET_AD0085_MPM_SORTING
if (cu.cs->sps->getUseMpmSorting())
{
int ctxId = 0;
const int maxNumCtxBins = (NUM_SECONDARY_MOST_PROBABLE_MODES / 4) - 1;
int prefixIdx = secondaryMPMIdx / 4;
for (int val = 0; val < maxNumCtxBins; val++)
{
unsigned int bin = (val == prefixIdx ? 0 : 1);
m_BinEncoder.encodeBin(bin, Ctx::IntraLumaSecondMpmIdx(ctxId++));
if (!bin)
{
break;
}
}
m_BinEncoder.encodeBinsEP(secondaryMPMIdx - prefixIdx * 4, 2);
}
else
{
#endif
m_BinEncoder.encodeBinsEP( secondaryMPMIdx, 4);
#if JVET_AD0085_MPM_SORTING
}
#endif
}
else
{
m_BinEncoder.encodeBin(0, Ctx::IntraLumaSecondMpmFlag());
unsigned nonMPMIdx = pu->ipredIdx;
xWriteTruncBinCode( nonMPMIdx, NUM_LUMA_MODE - NUM_MOST_PROBABLE_MODES); // Remaining mode is truncated binary coded
}
#else
std::sort(mpmPred, mpmPred + numMPMs);
for (int idx = numMPMs - 1; idx >= 0; idx--)
{
if (ipredMode > mpmPred[idx])
{
ipredMode--;
}
}
CHECK(ipredMode >= 64, "Incorrect mode");
xWriteTruncBinCode(ipredMode, NUM_LUMA_MODE - NUM_MOST_PROBABLE_MODES); // Remaining mode is truncated binary coded
#endif
}
}
#if JVET_AC0105_DIRECTIONAL_PLANAR
if (CU::isDirectionalPlanarAvailable(cu) && pu->mpmFlag && pu->ipredIdx == 0)
{
m_BinEncoder.encodeBin(cu.plIdx > 0, Ctx::IntraLumaPlanarFlag(2));
if (cu.plIdx)
{
m_BinEncoder.encodeBin(cu.plIdx > 1, Ctx::IntraLumaPlanarFlag(3));
}
DTRACE(g_trace_ctx, D_SYNTAX, "intra_luma_pred_modes() idx=%d pos=(%d,%d) pl_idx=%d\n", k, pu->lumaPos().x, pu->lumaPos().y, cu.plIdx);
}
#endif
#if ENABLE_DIMD || JVET_W0123_TIMD_FUSION
DTRACE(g_trace_ctx, D_SYNTAX, "intra_luma_pred_modes() idx=%d pos=(%d,%d) predIdx=%d mpm=%d secondmpm=%d\n", k, pu->lumaPos().x, pu->lumaPos().y, pu->ipredIdx, pu->mpmFlag, pu->secondMpmFlag);
#else
DTRACE( g_trace_ctx, D_SYNTAX, "intra_luma_pred_modes() idx=%d pos=(%d,%d) mode=%d\n", k, pu->lumaPos().x, pu->lumaPos().y, pu->intraDir[0] );
#endif
pu = pu->next;
}
}
void CABACWriter::intra_luma_pred_mode( const PredictionUnit& pu )
{
#if JVET_AH0076_OBIC
if (pu.cu->obicFlag)
{
return;
}
#endif
if( pu.cu->bdpcmMode ) return;
#if JVET_V0130_INTRA_TMP
// check if sufficient search range is available
//bool bCheck = pu.cu->
int tmpMaxSize = pu.cu->cs->sps->getIntraTMPMaxSize();
if( pu.cu->lwidth() <= tmpMaxSize && pu.cu->lheight() <= tmpMaxSize )
{
tmp_flag(*pu.cu);
if( pu.cu->tmpFlag )
{
return;
}
}
#endif
mip_flag(*pu.cu);
if (pu.cu->mipFlag)
{
mip_pred_mode(pu);
return;
}
#if JVET_W0123_TIMD_FUSION
cu_timd_flag(*pu.cu);
#endif
#if JVET_AG0058_EIP
cu_eip_flag(*pu.cu);
if (pu.cu->eipFlag)
{
return;
}
#endif
#if JVET_AB0155_SGPM
sgpm_flag(*pu.cu);
if (pu.cu->sgpm)
{
return;
}
#endif
#if JVET_AD0082_TMRL_CONFIG
if (CU::allowTmrl(*pu.cu))
{
cuTmrlFlag(*pu.cu);
if (pu.cu->tmrlFlag)
{
return;
}
}
else
{
extend_ref_line(pu);
}
#else
#if JVET_AB0157_TMRL
cuTmrlFlag(*pu.cu);
if (pu.cu->tmrlFlag)
{
return;
}
#else
extend_ref_line( pu );
#endif
#endif
isp_mode( *pu.cu );
#if ENABLE_DIMD
if (pu.cu->dimd)
{
return;
}
#endif
#if JVET_W0123_TIMD_FUSION
if (pu.cu->timd)
{
return;
}
#endif
// prev_intra_luma_pred_flag
if ( pu.multiRefIdx )
{
CHECK(!pu.mpmFlag, "use of non-MPM");
}
else
{
m_BinEncoder.encodeBin(pu.mpmFlag, Ctx::IntraLumaMpmFlag());
}
// mpm_idx / rem_intra_luma_pred_mode
if (pu.mpmFlag)
{
unsigned mpm_idx = pu.ipredIdx;
{
unsigned ctx = (pu.cu->ispMode == NOT_INTRA_SUBPARTITIONS ? 1 : 0);
#if SECONDARY_MPM
unsigned ctx2 = (ctx ? (pu.multiRefIdx == 0 ? 2 : 1) : 0);
#endif
if (pu.multiRefIdx == 0)
m_BinEncoder.encodeBin( mpm_idx > 0, Ctx::IntraLumaPlanarFlag(ctx) );
if( mpm_idx )
{
#if SECONDARY_MPM
m_BinEncoder.encodeBin(mpm_idx > 1, Ctx::IntraLumaMPMIdx(0 + ctx2));
#else
m_BinEncoder.encodeBinEP( mpm_idx > 1 );
#endif
}
if (mpm_idx > 1)
{
m_BinEncoder.encodeBinEP(mpm_idx > 2);
}
if (mpm_idx > 2)
{
m_BinEncoder.encodeBinEP(mpm_idx > 3);
}
if (mpm_idx > 3)
{
m_BinEncoder.encodeBinEP(mpm_idx > 4);
}
}
}
else
{
#if !SECONDARY_MPM
std::sort( mpmPred, mpmPred + numMPMs );
#endif
{
#if SECONDARY_MPM
if (pu.secondMpmFlag)
{
unsigned secondMpmIdx = pu.ipredIdx - NUM_PRIMARY_MOST_PROBABLE_MODES;
m_BinEncoder.encodeBin(1, Ctx::IntraLumaSecondMpmFlag());
#if JVET_AD0085_MPM_SORTING
if (pu.cs->sps->getUseMpmSorting())
{
int ctxId = 0;
const int maxNumCtxBins = (NUM_SECONDARY_MOST_PROBABLE_MODES / 4) - 1;
int prefixIdx = secondMpmIdx / 4;
for (int val = 0; val < maxNumCtxBins; val++)
{
unsigned int bin = (val == prefixIdx ? 0 : 1);
m_BinEncoder.encodeBin(bin, Ctx::IntraLumaSecondMpmIdx(ctxId++));
if (!bin)
{
break;
}
}
m_BinEncoder.encodeBinsEP(secondMpmIdx - prefixIdx * 4, 2);
}
else
{
#endif
m_BinEncoder.encodeBinsEP(secondMpmIdx, 4);
#if JVET_AD0085_MPM_SORTING
}
#endif
}
else
{
m_BinEncoder.encodeBin(0, Ctx::IntraLumaSecondMpmFlag());
unsigned non_mpm_idx = pu.ipredIdx;
xWriteTruncBinCode(non_mpm_idx, NUM_LUMA_MODE - NUM_MOST_PROBABLE_MODES); // Remaining mode is truncated binary coded
}
#else
unsigned ipredMode = pu.intraDir[0];
xWriteTruncBinCode(ipredMode, NUM_LUMA_MODE - NUM_MOST_PROBABLE_MODES); // Remaining mode is truncated binary coded
#endif
}
}
#if JVET_AC0105_DIRECTIONAL_PLANAR
if (CU::isDirectionalPlanarAvailable(*pu.cu) && pu.mpmFlag && pu.ipredIdx == 0)
{
m_BinEncoder.encodeBin(pu.cu->plIdx > 0, Ctx::IntraLumaPlanarFlag(2));
if (pu.cu->plIdx)
{
m_BinEncoder.encodeBin(pu.cu->plIdx > 1, Ctx::IntraLumaPlanarFlag(3));
}
}
#endif
}
#if JVET_AG0058_EIP
void CABACWriter::cu_eip_flag(const CodingUnit& cu)
{
if (cu.timd || cu.dimd || !cu.Y().valid() || !isLuma(cu.chType))
{
return;
}
const bool bCanUseEip = getAllowedEip(cu, COMPONENT_Y) || getAllowedEipMerge(cu, COMPONENT_Y);
if (bCanUseEip)
{
m_BinEncoder.encodeBin(cu.eipFlag, Ctx::EipFlag(0));
if (cu.eipFlag)
{
if (getAllowedEip(cu, COMPONENT_Y) && getAllowedEipMerge(cu, COMPONENT_Y))
{
m_BinEncoder.encodeBin(cu.eipMerge, Ctx::EipFlag(1));
}
if(cu.eipMerge)
{
CHECK(cu.firstPU->intraDir[0] >= NUM_EIP_MERGE_SIGNAL, "cu.firstPU->intraDir[0] >= NUM_EIP_MERGE_SIGNAL");
unary_max_eqprob(cu.firstPU->intraDir[0], NUM_EIP_MERGE_SIGNAL - 1);
}
else
{
CHECK(cu.firstPU->intraDir[0] >= NUM_DERIVED_EIP, "cu.firstPU->intraDir[0] >= NUM_DERIVED_EIP");
static_vector<EIPInfo, NUM_DERIVED_EIP> eipInfoList;
xWriteTruncBinCode(cu.firstPU->intraDir[0], getAllowedCurEip(cu, COMPONENT_Y, eipInfoList));
}
}
}
DTRACE(g_trace_ctx, D_SYNTAX, "eip_flag() pos=(%d,%d) mode=%d\n", cu.lumaPos().x, cu.lumaPos().y, cu.eipFlag ? 1 : 0);
}
#endif
#if JVET_W0123_TIMD_FUSION
void CABACWriter::cu_timd_flag( const CodingUnit& cu )
{
if (!cu.cs->sps->getUseTimd())
{
return;
}
if (cu.lwidth() * cu.lheight() > 1024 && cu.slice->getSliceType() == I_SLICE)
{
return;
}
#if ENABLE_DIMD
if (cu.dimd)
{
return;
}
#endif
if (!cu.Y().valid() || cu.predMode != MODE_INTRA || !isLuma(cu.chType))
{
return;
}
unsigned ctxId = DeriveCtx::CtxTimdFlag(cu);
m_BinEncoder.encodeBin(cu.timd, Ctx::TimdFlag(ctxId));
DTRACE(g_trace_ctx, D_SYNTAX, "cu_timd_flag() ctx=%d pos=(%d,%d) timd=%d\n", ctxId, cu.lumaPos().x, cu.lumaPos().y, cu.timd);
}
#endif
#if JVET_AB0155_SGPM
void CABACWriter::sgpm_flag(const CodingUnit &cu)
{
if (!cu.cs->sps->getUseSgpm())
{
return;
}
if (!(cu.lwidth() >= GEO_MIN_CU_SIZE_EX && cu.lheight() >= GEO_MIN_CU_SIZE_EX && cu.lwidth() <= GEO_MAX_CU_SIZE_EX
&& cu.lheight() <= GEO_MAX_CU_SIZE_EX && cu.lwidth() < 8 * cu.lheight() && cu.lheight() < 8 * cu.lwidth()
&& cu.lwidth() * cu.lheight() >= SGPM_MIN_PIX))
{
return;
}
if( cu.mipFlag
#if ENABLE_DIMD
|| cu.dimd
#endif
#if JVET_W0123_TIMD_FUSION
|| cu.timd
#endif
#if JVET_V0130_INTRA_TMP
|| cu.tmpFlag
#endif
)
{
return;
}
if (!cu.Y().valid() || cu.predMode != MODE_INTRA || !isLuma(cu.chType))
{
return;
}
if (!(cu.lx() && cu.ly()))
{
return;
}
unsigned ctxId = DeriveCtx::CtxSgpmFlag(cu);
m_BinEncoder.encodeBin(cu.sgpm, Ctx::SgpmFlag(ctxId));
DTRACE(g_trace_ctx, D_SYNTAX, "sgpm_flag() pos=(%d,%d) ctx=%d sgpm_flag=%d\n", cu.lumaPos().x, cu.lumaPos().y, ctxId, cu.sgpm);
if (cu.sgpm)
{
xWriteTruncBinCode(cu.sgpmIdx, SGPM_NUM);
DTRACE(g_trace_ctx, D_SYNTAX, "sgpm_flag() pos=(%d,%d) sgpm_idx=%d\n", cu.lumaPos().x, cu.lumaPos().y, cu.sgpmIdx);
}
}
#endif
#if ENABLE_DIMD
void CABACWriter::cu_dimd_flag(const CodingUnit& cu)
{
if (!cu.Y().valid() || cu.predMode != MODE_INTRA || !isLuma(cu.chType) || !cu.slice->getSPS()->getUseDimd())
{
return;
}
unsigned ctxId = DeriveCtx::CtxDIMDFlag(cu);
m_BinEncoder.encodeBin(cu.dimd, Ctx::DimdFlag(ctxId));
#if JVET_AH0076_OBIC
cu_obic_flag(cu);
#endif
DTRACE(g_trace_ctx, D_SYNTAX, "cu_dimd_flag() ctx=%d pos=(%d,%d) dimd=%d\n", ctxId, cu.lumaPos().x, cu.lumaPos().y, cu.dimd);
}
#endif
#if JVET_AH0076_OBIC
void CABACWriter::cu_obic_flag(const CodingUnit& cu )
{
if (!cu.dimd || !cu.Y().valid() || cu.predMode != MODE_INTRA || !isLuma(cu.chType))
{
return;
}
if (!PU::isObicAvail(*cu.firstPU))
{
return;
}
m_BinEncoder.encodeBin(cu.obicFlag ? 1 : 0, Ctx::obicFlag(0));
}
#endif
void CABACWriter::intra_chroma_pred_modes( const CodingUnit& cu )
{
#if INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS
if (cu.chromaFormat == CHROMA_400 || (CS::isDualITree(*cu.cs) && cu.chType == CHANNEL_TYPE_LUMA))
#else
if (cu.chromaFormat == CHROMA_400 || (cu.isSepTree() && cu.chType == CHANNEL_TYPE_LUMA))
#endif
{
return;
}
if( cu.bdpcmModeChroma )
{
PredictionUnit* pu = cu.firstPU;
pu->intraDir[1] = cu.bdpcmModeChroma == 2 ? VER_IDX : HOR_IDX;
DTRACE(g_trace_ctx, D_SYNTAX, "intra_chroma_pred_modes() pos=(%d,%d) dir=%d\n",
pu->blocks[CHANNEL_TYPE_CHROMA].x, pu->blocks[CHANNEL_TYPE_CHROMA].y, pu->intraDir[CHANNEL_TYPE_CHROMA]);
return;
}
const PredictionUnit* pu = cu.firstPU;
intra_chroma_pred_mode( *pu );
DTRACE(g_trace_ctx, D_SYNTAX, "intra_chroma_pred_modes() pos=(%d,%d) fusion_mode=%d cccm_mode=%d\n",
pu->blocks[CHANNEL_TYPE_CHROMA].x, pu->blocks[CHANNEL_TYPE_CHROMA].y, pu->isChromaFusion, pu->cccmFlag);
}
#if JVET_Z0050_CCLM_SLOPE
void CABACWriter::cclmDelta(const PredictionUnit& pu, int8_t delta)
{
if ( delta )
{
int deltaAbs = abs( delta );
if ( deltaAbs == 1 )
{
m_BinEncoder.encodeBinsEP( 0, 1 );
}
else if ( deltaAbs == 2 )
{
m_BinEncoder.encodeBinsEP( 2, 2 );
}
else if ( deltaAbs == 3 )
{
m_BinEncoder.encodeBinsEP( 6, 3 );
}
else
{
m_BinEncoder.encodeBinsEP( 7, 3 );
}
m_BinEncoder.encodeBin( delta < 0 ? 1 : 0, Ctx::CclmDeltaFlags(4) );
}
}
void CABACWriter::cclmDeltaSlope(const PredictionUnit& pu)
{
#if JVET_AA0057_CCCM
if ( pu.cccmFlag )
{
return;
}
#endif
if ( PU::hasCclmDeltaFlag( pu ) )
{
bool deltaActive = pu.cclmOffsets.isActive();
m_BinEncoder.encodeBin( deltaActive ? 1 : 0, Ctx::CclmDeltaFlags(0) );
if ( deltaActive )
{
bool bothActive = pu.cclmOffsets.cb0 && pu.cclmOffsets.cr0;
m_BinEncoder.encodeBin( bothActive ? 1 : 0, Ctx::CclmDeltaFlags(3) );
if ( !bothActive )
{
m_BinEncoder.encodeBin( pu.cclmOffsets.cb0 ? 1 : 0, Ctx::CclmDeltaFlags(1) );
#if MMLM
if ( PU::isMultiModeLM( pu.intraDir[1] ) && !pu.cclmOffsets.cb0 )
{
m_BinEncoder.encodeBin( pu.cclmOffsets.cr0 ? 1 : 0, Ctx::CclmDeltaFlags(2) );
}
#endif
}
cclmDelta( pu, pu.cclmOffsets.cb0 );
cclmDelta( pu, pu.cclmOffsets.cr0 );
#if MMLM
// Now the same for the second model (if applicable)
if ( PU::isMultiModeLM( pu.intraDir[1] ) )
{
bool bothActive = pu.cclmOffsets.cb1 && pu.cclmOffsets.cr1;
m_BinEncoder.encodeBin( bothActive ? 1 : 0, Ctx::CclmDeltaFlags(3) );
if ( !bothActive )
{
m_BinEncoder.encodeBin( pu.cclmOffsets.cb1 ? 1 : 0, Ctx::CclmDeltaFlags(1) );
if ( !pu.cclmOffsets.cb1 )
{
if ( pu.cclmOffsets.cb0 || pu.cclmOffsets.cr0 || pu.cclmOffsets.cb1 )
{
m_BinEncoder.encodeBin( pu.cclmOffsets.cr1 ? 1 : 0, Ctx::CclmDeltaFlags(2) );
}
}
}
cclmDelta( pu, pu.cclmOffsets.cb1 );
cclmDelta( pu, pu.cclmOffsets.cr1 );
}
#endif
}
}
}
#endif
#if JVET_AA0126_GLM
void CABACWriter::glmIdc(const PredictionUnit& pu)
{
if ( PU::hasGlmFlag( pu ) )
{
bool glmActive = pu.glmIdc.isActive();
m_BinEncoder.encodeBin( glmActive ? 1 : 0, Ctx::GlmFlags(0) );
if ( glmActive )
{
#if JVET_AB0092_GLM_WITH_LUMA
int glmIdx = pu.glmIdc.cb0 - 1;
#if NUM_GLM_WEIGHT
m_BinEncoder.encodeBin(glmIdx >= NUM_GLM_PATTERN ? 1 : 0, Ctx::GlmFlags(1));
glmIdx -= glmIdx >= NUM_GLM_PATTERN ? NUM_GLM_PATTERN : 0;
#endif
CHECK(pu.glmIdc.cb0 != pu.glmIdc.cr0, "wrong glm idx");
#if JVET_AA0057_CCCM
m_BinEncoder.encodeBin(glmIdx > 0, Ctx::GlmFlags(2));
if (glmIdx > 0)
{
m_BinEncoder.encodeBin(glmIdx > 1, Ctx::GlmFlags(3));
if (glmIdx > 1)
{
m_BinEncoder.encodeBin(glmIdx > 2, Ctx::GlmFlags(4));
}
}
#else
m_BinEncoder.encodeBinsEP(glmIdx, NUM_GLM_PATTERN_BITS);
#endif
#else
bool bothActive = pu.glmIdc.cb0 && pu.glmIdc.cr0;
m_BinEncoder.encodeBin( bothActive ? 1 : 0, Ctx::GlmFlags(3) );
if ( !bothActive )
{
m_BinEncoder.encodeBin( pu.glmIdc.cb0 ? 1 : 0, Ctx::GlmFlags(1) );
}
if ( pu.glmIdc.cb0 )
{
int glmIdx = pu.glmIdc.cb0 - 1;
#if NUM_GLM_WEIGHT
m_BinEncoder.encodeBin( glmIdx >= NUM_GLM_PATTERN ? 1 : 0, Ctx::GlmFlags(2) );
glmIdx -= glmIdx >= NUM_GLM_PATTERN ? NUM_GLM_PATTERN : 0;
#endif
m_BinEncoder.encodeBinsEP( glmIdx, NUM_GLM_PATTERN_BITS );
}
if ( pu.glmIdc.cr0 )
{
int glmIdx = pu.glmIdc.cr0 - 1;
#if NUM_GLM_WEIGHT
m_BinEncoder.encodeBin( glmIdx >= NUM_GLM_PATTERN ? 1 : 0, Ctx::GlmFlags(4) );
glmIdx -= glmIdx >= NUM_GLM_PATTERN ? NUM_GLM_PATTERN : 0;
#endif
m_BinEncoder.encodeBinsEP( glmIdx, NUM_GLM_PATTERN_BITS );
}
#endif
#if MMLM
if ( PU::isMultiModeLM( pu.intraDir[1] ) )
{
CHECK(pu.glmIdc.cb0 != pu.glmIdc.cb1
|| pu.glmIdc.cr0 != pu.glmIdc.cr1, "GLM cb0 != cb1 || cr0 != cr1")
}
#endif
}
}
}
#endif
void CABACWriter::intra_chroma_lmc_mode(const PredictionUnit& pu)
{
#if JVET_AG0154_DECODER_DERIVED_CCP_FUSION
decoderDerivedCcpModes(pu);
if (pu.decoderDerivedCcpMode)
{
return;
}
#endif
#if JVET_AD0188_CCP_MERGE || JVET_AG0154_DECODER_DERIVED_CCP_FUSION
nonLocalCCPIndex(pu);
if (pu.idxNonLocalCCP)
{
return;
}
#endif
const unsigned intraDir = pu.intraDir[1];
#if MMLM
int lmModeList[NUM_CHROMA_MODE];
#else
int lmModeList[10];
#endif
PU::getLMSymbolList(pu, lmModeList);
int symbol = -1;
for (int k = 0; k < LM_SYMBOL_NUM; k++)
{
if (lmModeList[k] == intraDir)
{
symbol = k;
break;
}
}
CHECK(symbol < 0, "invalid symbol found");
m_BinEncoder.encodeBin(symbol == 0 ? 0 : 1, Ctx::CclmModeIdx(0));
if (symbol > 0)
{
#if MMLM
CHECK(symbol > 5, "invalid symbol for MMLM");
m_BinEncoder.encodeBin(symbol == 1 ? 0 : 1, Ctx::MMLMFlag(0));
if (symbol > 1)
{
m_BinEncoder.encodeBinEP(symbol > 2);
}
if (symbol > 2)
{
m_BinEncoder.encodeBinEP(symbol > 3);
}
if (symbol > 3)
{
m_BinEncoder.encodeBinEP(symbol > 4);
}
#else
CHECK(symbol > 2, "invalid symbol for MMLM");
unsigned int symbol_minus_1 = symbol - 1;
m_BinEncoder.encodeBinEP(symbol_minus_1);
#endif
}
#if JVET_AA0057_CCCM
cccmFlag( pu );
#endif
#if JVET_AA0126_GLM
glmIdc( pu );
#endif
#if JVET_Z0050_CCLM_SLOPE
cclmDeltaSlope( pu );
#endif
#if JVET_AD0120_LBCCP
ccInsideFilterFlag(pu);
#endif
}
#if JVET_AG0154_DECODER_DERIVED_CCP_FUSION
void CABACWriter::decoderDerivedCcpModes(const PredictionUnit &pu)
{
if (PU::hasDecoderDerivedCCP(pu))
{
m_BinEncoder.encodeBin(pu.decoderDerivedCcpMode > 0 ? 1 : 0, Ctx::decoderDerivedCCP(0));
}
}
#endif
#if JVET_AD0188_CCP_MERGE || JVET_AG0154_DECODER_DERIVED_CCP_FUSION
void CABACWriter::nonLocalCCPIndex(const PredictionUnit &pu)
{
if (PU::hasNonLocalCCP(pu))
{
CHECK(pu.idxNonLocalCCP < 0 || pu.idxNonLocalCCP > MAX_CCP_CAND_LIST_SIZE, "Invalid idxNonLocalCCP");
{
m_BinEncoder.encodeBin(pu.idxNonLocalCCP ? 1 : 0, Ctx::nonLocalCCP(0));
if (pu.idxNonLocalCCP)
{
#if JVET_AG0154_DECODER_DERIVED_CCP_FUSION
if (pu.cu->slice->getSPS()->getUseDdCcpFusion())
{
m_BinEncoder.encodeBin(pu.ddNonLocalCCPFusion > 0 ? 1 : 0, Ctx::ddNonLocalCCP(0));
}
if (pu.ddNonLocalCCPFusion > 0)
{
unary_max_eqprob(pu.ddNonLocalCCPFusion - 1, MAX_CCP_FUSION_NUM - 1);
}
else
{
#endif
unary_max_eqprob(pu.idxNonLocalCCP - 1, MAX_CCP_CAND_LIST_SIZE - 1);
#if JVET_AG0059_CCP_MERGE_ENHANCEMENT
if (PU::hasCCPMergeFusionFlag(pu))
{
m_BinEncoder.encodeBin(pu.ccpMergeFusionFlag ? 1 : 0, Ctx::CCPMergeFusionFlag(0));
if (pu.ccpMergeFusionFlag)
{
m_BinEncoder.encodeBin(pu.ccpMergeFusionType ? 1 : 0, Ctx::CCPMergeFusionType(0));
}
}
#endif
#if JVET_AG0154_DECODER_DERIVED_CCP_FUSION
}
#endif
}
#if JVET_AI0136_ADAPTIVE_DUAL_TREE
DTRACE(g_trace_ctx, D_SYNTAX, "nonLocalCCPIndex() pos=(%d, %d) idxNonLocalCCP=%d\n", pu.blocks[pu.chType].pos().x, pu.blocks[pu.chType].pos().y, pu.idxNonLocalCCP);
#endif
}
}
}
#endif
#if JVET_AA0057_CCCM
void CABACWriter::cccmFlag(const PredictionUnit& pu)
{
#if JVET_AC0147_CCCM_NO_SUBSAMPLING
if ( pu.cs->sps->getUseCccm() == 0 )
{
return;
}
#endif
const unsigned intraDir = pu.intraDir[1];
#if JVET_AE0100_BVGCCCM
if ((intraDir == LM_CHROMA_IDX || intraDir == MMLM_CHROMA_IDX) && PU::hasBvgCccmFlag(pu) && PU::cccmSingleModeAvail(pu, LM_CHROMA_IDX) && PU::bvgCccmMultiModeAvail(pu, intraDir))
{
m_BinEncoder.encodeBin( pu.bvgCccmFlag ? 1 : 0, Ctx::BvgCccmFlag( 0 ) );
if (pu.bvgCccmFlag)
{
return;
}
}
#endif
#if JVET_AB0143_CCCM_TS
bool isCCCMEnabled = false;
if (intraDir == LM_CHROMA_IDX)
{
isCCCMEnabled = PU::cccmSingleModeAvail(pu, LM_CHROMA_IDX);
}
else if (intraDir == MDLM_L_IDX)
{
isCCCMEnabled = PU::isLeftCccmMode(pu, MDLM_L_IDX);
}
else if (intraDir == MDLM_T_IDX)
{
isCCCMEnabled = PU::isTopCccmMode(pu, MDLM_T_IDX);
}
#if MMLM
else if (intraDir == MMLM_CHROMA_IDX)
{
isCCCMEnabled = PU::cccmMultiModeAvail(pu, MMLM_CHROMA_IDX);
}
else if (intraDir == MMLM_L_IDX)
{
isCCCMEnabled = PU::cccmMultiModeAvail(pu, MMLM_L_IDX);
}
else if (intraDir == MMLM_T_IDX)
{
isCCCMEnabled = PU::cccmMultiModeAvail(pu, MMLM_T_IDX);
}
#endif
if (isCCCMEnabled)
#else
if ( PU::cccmSingleModeAvail(pu, intraDir) || PU::cccmMultiModeAvail(pu, intraDir) )
#endif
{
m_BinEncoder.encodeBin( pu.cccmFlag ? 1 : 0, Ctx::CccmFlag( 0 ) );
#if JVET_AD0202_CCCM_MDF
if (pu.cccmFlag)
{
bool isCccmWithMdfEnabled = true;
if (intraDir == MMLM_CHROMA_IDX)
{
isCccmWithMdfEnabled = PU::isMultiCccmWithMdf(pu, MMLM_CHROMA_IDX);
}
else if (intraDir == MMLM_L_IDX)
{
isCccmWithMdfEnabled = PU::isMultiCccmWithMdf(pu, MMLM_L_IDX);
}
else if (intraDir == MMLM_T_IDX)
{
isCccmWithMdfEnabled = PU::isMultiCccmWithMdf(pu, MMLM_T_IDX);
}
if (isCccmWithMdfEnabled)
{
m_BinEncoder.encodeBin(pu.cccmMultiFilterIdx > 0 ? 1 : 0, Ctx::CccmMpfFlag(0));
if (pu.cccmMultiFilterIdx > 0)
{
m_BinEncoder.encodeBin(pu.cccmMultiFilterIdx > 1 ? 1 : 0, Ctx::CccmMpfFlag(1));
if (pu.cccmMultiFilterIdx > 1)
{
m_BinEncoder.encodeBin(pu.cccmMultiFilterIdx > 2 ? 1 : 0, Ctx::CccmMpfFlag(2));
}
}
}
}
if (!pu.cccmMultiFilterIdx)
{
#endif
#if JVET_AC0147_CCCM_NO_SUBSAMPLING
if ( pu.cccmFlag && ( pu.cs->sps->getUseCccm() == 2 ) )
{
m_BinEncoder.encodeBin( pu.cccmNoSubFlag ? 1 : 0, Ctx::CccmFlag( 1 ) );
}
#endif
#if JVET_AC0054_GLCCCM
#if !JVET_AC0147_CCCM_NO_SUBSAMPLING
unsigned ctxId = 1;
if (pu.cccmFlag)
#else
unsigned ctxId = 2;
if (pu.cccmFlag && !pu.cccmNoSubFlag)
#endif
{
m_BinEncoder.encodeBin( pu.glCccmFlag ? 1 : 0, Ctx::CccmFlag( ctxId ) );
}
#endif
#if JVET_AD0202_CCCM_MDF
}
#endif
}
}
#endif
#if JVET_AC0119_LM_CHROMA_FUSION
void CABACWriter::intraChromaFusionMode(const PredictionUnit& pu)
{
int symbol = pu.isChromaFusion;
m_BinEncoder.encodeBin(symbol > 0 ? 1 : 0, Ctx::ChromaFusionMode());
if (symbol > 0)
{
m_BinEncoder.encodeBin(symbol > 1 ? 1 : 0, Ctx::ChromaFusionType()); // Default=1
#if MMLM
if (symbol > 1)
{
m_BinEncoder.encodeBin(symbol > 2 ? 1 : 0, Ctx::ChromaFusionCclm()); // LM=2
}
#endif
}
}
#endif
#if JVET_AD0120_LBCCP
void CABACWriter::ccInsideFilterFlag(const PredictionUnit &pu)
{
#if JVET_AE0100_BVGCCCM
if (pu.bvgCccmFlag)
{
return;
}
#endif
const unsigned intraDir = pu.intraDir[1];
if (PU::hasCcInsideFilterFlag(pu, intraDir))
{
m_BinEncoder.encodeBin(pu.ccInsideFilter, Ctx::CcInsideFilterFlag(0));
}
}
#endif
void CABACWriter::intra_chroma_pred_mode(const PredictionUnit& pu)
{
const unsigned intraDir = pu.intraDir[1];
if (pu.cu->colorTransform)
{
CHECK(pu.intraDir[CHANNEL_TYPE_CHROMA] != DM_CHROMA_IDX, "chroma should use DM for adaptive color transform");
return;
}
#if CCLM_LATENCY_RESTRICTION_RMV
if (pu.cs->sps->getUseLMChroma() )
#else
if (pu.cs->sps->getUseLMChroma() && pu.cu->checkCCLMAllowed())
#endif
{
m_BinEncoder.encodeBin(PU::isLMCMode(intraDir) ? 1 : 0, Ctx::CclmModeFlag(0));
if (PU::isLMCMode(intraDir))
{
intra_chroma_lmc_mode(pu);
DTRACE(g_trace_ctx, D_SYNTAX, "intra_chroma_pred_modes() pos=(%d,%d) dir=%d\n",
pu.blocks[CHANNEL_TYPE_CHROMA].x, pu.blocks[CHANNEL_TYPE_CHROMA].y, pu.intraDir[CHANNEL_TYPE_CHROMA]);
return;
}
}
#if JVET_AC0071_DBV
#if JVET_AH0136_CHROMA_REORDERING
bool hasDBV = false;
#endif
if (PU::hasChromaBvFlag(pu))
{
#if JVET_AH0136_CHROMA_REORDERING
hasDBV = true;
bool isDbvChromaMode = intraDir == DBV_CHROMA_IDX;
#if JVET_AI0136_ADAPTIVE_DUAL_TREE
if (( CS::isDualITree(*pu.cs) || (pu.cu->isSST && pu.cu->separateTree) ) && pu.cs->sps->getUseChromaReordering() && pu.cs->slice->isIntra())
#else
if (CS::isDualITree(*pu.cs) && pu.cs->sps->getUseChromaReordering())
#endif
{
int mode = PU::isDbvMode(pu.intraDir[1]) ? pu.intraDir[1] : PU::getFinalIntraMode(pu, CHANNEL_TYPE_CHROMA);
isDbvChromaMode = mode == pu.cu->chromaList[0];
}
#else
const bool isDbvChromaMode = intraDir == DBV_CHROMA_IDX;
#endif
m_BinEncoder.encodeBin(isDbvChromaMode ? 0 : 1, Ctx::DbvChromaMode());
if (isDbvChromaMode)
{
if (PU::hasChromaFusionFlag(pu, pu.intraDir[1]))
{
#if JVET_AH0136_CHROMA_REORDERING
intraChromaFusionMode(pu);
#else
const bool isFusion = pu.isChromaFusion;
m_BinEncoder.encodeBin(isFusion ? 1 : 0, Ctx::ChromaFusionMode());
#endif
}
#if JVET_AH0136_CHROMA_REORDERING
DTRACE(g_trace_ctx, D_SYNTAX, "intra_chroma_pred_modes() pos=(%d,%d) dir=%d\n", pu.blocks[CHANNEL_TYPE_CHROMA].x,
pu.blocks[CHANNEL_TYPE_CHROMA].y, isDbvChromaMode ? DBV_CHROMA_IDX : pu.intraDir[CHANNEL_TYPE_CHROMA]);
#else
DTRACE(g_trace_ctx, D_SYNTAX, "intra_chroma_pred_modes() pos=(%d,%d) dir=%d\n",
pu.blocks[CHANNEL_TYPE_CHROMA].x, pu.blocks[CHANNEL_TYPE_CHROMA].y, pu.intraDir[CHANNEL_TYPE_CHROMA]);
#endif
return;
}
}
#endif
#if JVET_AH0136_CHROMA_REORDERING
#if JVET_AI0136_ADAPTIVE_DUAL_TREE
if ( (CS::isDualITree(*pu.cs) || (pu.cu->isSST && pu.cu->separateTree) ) && pu.cs->sps->getUseChromaReordering() && pu.cs->slice->isIntra())
#else
if (CS::isDualITree(*pu.cs) && pu.cs->sps->getUseChromaReordering())
#endif
{
int chromaIdx = 0;
bool hasMode = false;
int mode = PU::isDbvMode(pu.intraDir[1]) ? pu.intraDir[1] : PU::getFinalIntraMode(pu, CHANNEL_TYPE_CHROMA);
int start = 0;
int end = 6;
#if JVET_AC0071_DBV
if (hasDBV)
{
start++;
end++;
}
#endif
#if ENABLE_DIMD && JVET_Z0050_DIMD_CHROMA_FUSION
if (!pu.cu->slice->getSPS()->getUseDimd())
{
end--;
}
#endif
for (int i = start; i < end; i++)
{
if (mode == pu.cu->chromaList[i])
{
chromaIdx = i;
hasMode = true;
break;
}
}
if (hasDBV)
{
chromaIdx--;
}
CHECK(!hasMode, "wrong mode");
const bool isDerivedMode = chromaIdx == 0;
m_BinEncoder.encodeBin(isDerivedMode ? 0 : 1, Ctx::IntraChromaPredMode(0));
if (isDerivedMode)
{
#if JVET_Z0050_DIMD_CHROMA_FUSION
if (PU::hasChromaFusionFlag(pu, pu.intraDir[1]))
{
#if JVET_AC0119_LM_CHROMA_FUSION
intraChromaFusionMode(pu);
#else
const bool isFusion = pu.isChromaFusion;
m_BinEncoder.encodeBin(isFusion ? 1 : 0, Ctx::ChromaFusionMode());
#endif
}
#endif
DTRACE(g_trace_ctx, D_SYNTAX, "intra_chroma_pred_modes() pos=(%d,%d) dir=%d\n",
pu.blocks[CHANNEL_TYPE_CHROMA].x, pu.blocks[CHANNEL_TYPE_CHROMA].y, pu.intraDir[CHANNEL_TYPE_CHROMA]);
return;
}
#if JVET_Z0050_DIMD_CHROMA_FUSION && ENABLE_DIMD
if (pu.cu->slice->getSPS()->getUseDimd())
{
const bool isDimdChromaMode = chromaIdx == 1;
m_BinEncoder.encodeBin(isDimdChromaMode ? 0 : 1, Ctx::DimdChromaMode());
if (isDimdChromaMode)
{
if (PU::hasChromaFusionFlag(pu, pu.intraDir[1]))
{
#if JVET_AC0119_LM_CHROMA_FUSION
intraChromaFusionMode(pu);
#else
const bool isFusion = pu.isChromaFusion;
m_BinEncoder.encodeBin(isFusion ? 1 : 0, Ctx::ChromaFusionMode());
#endif
}
DTRACE(g_trace_ctx, D_SYNTAX, "intra_chroma_pred_modes() pos=(%d,%d) dir=%d\n",
pu.blocks[CHANNEL_TYPE_CHROMA].x, pu.blocks[CHANNEL_TYPE_CHROMA].y, pu.intraDir[CHANNEL_TYPE_CHROMA]);
return;
}
}
else
{
chromaIdx++;
}
#endif
// chroma candidate index
{
m_BinEncoder.encodeBinsEP(chromaIdx - 2, 2);
DTRACE(g_trace_ctx, D_SYNTAX, "intra_chroma_pred_modes() pos=(%d,%d) cand_idx=%d\n", pu.blocks[CHANNEL_TYPE_CHROMA].x, pu.blocks[CHANNEL_TYPE_CHROMA].y, chromaIdx - 2);
#if JVET_Z0050_DIMD_CHROMA_FUSION
if (PU::hasChromaFusionFlag(pu, pu.intraDir[1]))
{
#if JVET_AC0119_LM_CHROMA_FUSION
intraChromaFusionMode(pu);
#else
const bool isFusion = pu.isChromaFusion;
m_BinEncoder.encodeBin(isFusion ? 1 : 0, Ctx::ChromaFusionMode());
#endif
}
#endif
}
return;
}
#endif
const bool isDerivedMode = intraDir == DM_CHROMA_IDX;
m_BinEncoder.encodeBin(isDerivedMode ? 0 : 1, Ctx::IntraChromaPredMode(0));
if (isDerivedMode)
{
#if JVET_Z0050_DIMD_CHROMA_FUSION
if (PU::hasChromaFusionFlag(pu, pu.intraDir[1]))
{
#if JVET_AC0119_LM_CHROMA_FUSION
intraChromaFusionMode(pu);
#else
const bool isFusion = pu.isChromaFusion;
m_BinEncoder.encodeBin(isFusion ? 1 : 0, Ctx::ChromaFusionMode());
#endif
}
#endif
DTRACE(g_trace_ctx, D_SYNTAX, "intra_chroma_pred_modes() pos=(%d,%d) dir=%d\n",
pu.blocks[CHANNEL_TYPE_CHROMA].x, pu.blocks[CHANNEL_TYPE_CHROMA].y, pu.intraDir[CHANNEL_TYPE_CHROMA]);
return;
}
#if JVET_Z0050_DIMD_CHROMA_FUSION && ENABLE_DIMD
if (pu.cu->slice->getSPS()->getUseDimd())
{
const bool isDimdChromaMode = intraDir == DIMD_CHROMA_IDX;
m_BinEncoder.encodeBin(isDimdChromaMode ? 0 : 1, Ctx::DimdChromaMode());
if (isDimdChromaMode)
{
if (PU::hasChromaFusionFlag(pu, pu.intraDir[1]))
{
#if JVET_AC0119_LM_CHROMA_FUSION
intraChromaFusionMode(pu);
#else
const bool isFusion = pu.isChromaFusion;
m_BinEncoder.encodeBin(isFusion ? 1 : 0, Ctx::ChromaFusionMode());
#endif
}
DTRACE(g_trace_ctx, D_SYNTAX, "intra_chroma_pred_modes() pos=(%d,%d) dir=%d\n",
pu.blocks[CHANNEL_TYPE_CHROMA].x, pu.blocks[CHANNEL_TYPE_CHROMA].y, pu.intraDir[CHANNEL_TYPE_CHROMA]);
return;
}
}
#endif
// chroma candidate index
unsigned chromaCandModes[NUM_CHROMA_MODE];
PU::getIntraChromaCandModes(pu, chromaCandModes);
int candId = 0;
for (; candId < NUM_CHROMA_MODE; candId++)
{
if (intraDir == chromaCandModes[candId])
{
break;
}
}
CHECK(candId >= NUM_CHROMA_MODE, "Chroma prediction mode index out of bounds");
CHECK(chromaCandModes[candId] == DM_CHROMA_IDX, "The intra dir cannot be DM_CHROMA for this path");
{
m_BinEncoder.encodeBinsEP(candId, 2);
DTRACE(g_trace_ctx, D_SYNTAX, "intra_chroma_pred_modes() pos=(%d,%d) cand_idx=%d\n", pu.blocks[CHANNEL_TYPE_CHROMA].x, pu.blocks[CHANNEL_TYPE_CHROMA].y, candId);
#if JVET_Z0050_DIMD_CHROMA_FUSION
if (PU::hasChromaFusionFlag(pu, pu.intraDir[1]))
{
#if JVET_AC0119_LM_CHROMA_FUSION
intraChromaFusionMode(pu);
#else
const bool isFusion = pu.isChromaFusion;
m_BinEncoder.encodeBin(isFusion ? 1 : 0, Ctx::ChromaFusionMode());
#endif
}
#endif
}
}
void CABACWriter::cu_residual( const CodingUnit& cu, Partitioner& partitioner, CUCtx& cuCtx )
{
if (!CU::isIntra(cu))
{
PredictionUnit& pu = *cu.firstPU;
#if MULTI_HYP_PRED
if (!(pu.mergeFlag && pu.numMergedAddHyps == pu.addHypData.size()))
#else
if (!pu.mergeFlag)
#endif
{
rqt_root_cbf( cu );
}
if( cu.rootCbf )
{
sbt_mode( cu );
}
if( !cu.rootCbf )
{
#if JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0
if (CU::interCcpMergeZeroRootCbfAllowed(cu))
{
inter_ccp_merge_root_cbf_zero(cu);
}
#endif
CHECK(cu.colorTransform, "ACT should not be enabled for root_cbf = 0");
return;
}
}
if (CU::isInter(cu) || CU::isIBC(cu))
{
adaptive_color_transform(cu);
}
cuCtx.violatesLfnstConstrained[CHANNEL_TYPE_LUMA] = false;
cuCtx.violatesLfnstConstrained[CHANNEL_TYPE_CHROMA] = false;
cuCtx.lfnstLastScanPos = false;
cuCtx.violatesMtsCoeffConstraint = false;
cuCtx.mtsLastScanPos = false;
#if JVET_Y0142_ADAPT_INTRA_MTS
cuCtx.mtsCoeffAbsSum = 0;
#endif
if( cu.ispMode && isLuma( partitioner.chType ) )
{
TUIntraSubPartitioner subTuPartitioner( partitioner );
transform_tree( *cu.cs, subTuPartitioner, cuCtx, CU::getISPType( cu, getFirstComponentOfChannel( partitioner.chType) ), 0 );
}
else
{
transform_tree( *cu.cs, partitioner, cuCtx );
}
residual_lfnst_mode( cu, cuCtx );
#if JVET_AE0102_LFNST_CTX
// call coeff coding, check the ordering of tus
if ( isEncoding() )
{
for (auto &currTU : CU::traverseTUs(cu))
{
transform_unit(currTU, cuCtx, partitioner, -1, true);
}
}
#endif
mts_idx ( cu, &cuCtx );
#if SIGN_PREDICTION
if(typeid(m_BinEncoder) == typeid(BinEncoder_Std))
{
// In the final coding stage, predicted signs are signaled here.
for( auto &currTU : CU::traverseTUs( cu ) )
{
for( int compIdx = COMPONENT_Y; compIdx < MAX_NUM_COMPONENT; ++compIdx)
{
ComponentID compID = (ComponentID)compIdx;
if(compIdx >= currTU.blocks.size())
{
continue;
}
if(currTU.jointCbCr)
{
if( !( currTU.jointCbCr >> 1 ) && compID == COMPONENT_Cb )
{
continue;
}
if( ( currTU.jointCbCr >> 1 ) && compID == COMPONENT_Cr )
{
continue;
}
}
if(currTU.blocks[compID].valid() && TU::getCbf( currTU, compID ) && TU::getDelayedSignCoding(currTU, compID))
{
codePredictedSigns(const_cast<TransformUnit &>(currTU), compID);
}
}
}
}
#endif
}
void CABACWriter::rqt_root_cbf( const CodingUnit& cu )
{
m_BinEncoder.encodeBin( cu.rootCbf, Ctx::QtRootCbf() ) ;
DTRACE( g_trace_ctx, D_SYNTAX, "rqt_root_cbf() ctx=0 root_cbf=%d pos=(%d,%d)\n", cu.rootCbf ? 1 : 0, cu.lumaPos().x, cu.lumaPos().y );
}
#if JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0
void CABACWriter::inter_ccp_merge_root_cbf_zero(const CodingUnit &cu)
{
unary_max_symbol(cu.interCcpMergeZeroRootCbfIdc, Ctx::InterCcpMergeZeroRootCbfIdc(0),
Ctx::InterCcpMergeZeroRootCbfIdc(1), MAX_CCP_MERGE_WEIGHT_IDX);
DTRACE(g_trace_ctx, D_SYNTAX, "inter_ccp_merge_root_cbf_zero() pos=(%d,%d) inter_ccp_merge_root_cbf_zero_flag=%d\n", cu.blocks[cu.chType].x, cu.blocks[cu.chType].y, cu.interCcpMergeZeroRootCbfIdc > 0 ? 1 : 0);
}
#endif
void CABACWriter::adaptive_color_transform(const CodingUnit& cu)
{
if (!cu.slice->getSPS()->getUseColorTrans())
{
return;
}
#if INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS
if (CS::isDualITree(*cu.cs))
#else
if (cu.isSepTree())
#endif
{
CHECK(cu.colorTransform, "adaptive color transform should be disabled when dualtree and localtree are enabled");
return;
}
if (CU::isInter(cu) || CU::isIBC(cu) || CU::isIntra(cu))
{
m_BinEncoder.encodeBin(cu.colorTransform, Ctx::ACTFlag());
DTRACE(g_trace_ctx, D_SYNTAX, "adaptive_color_transform() act_flag=(%d,%d)\n", cu.lumaPos().x, cu.lumaPos().y, cu.colorTransform);
}
}
void CABACWriter::sbt_mode( const CodingUnit& cu )
{
uint8_t sbtAllowed = cu.checkAllowedSbt();
if( !sbtAllowed )
{
return;
}
SizeType cuWidth = cu.lwidth();
SizeType cuHeight = cu.lheight();
uint8_t sbtIdx = cu.getSbtIdx();
uint8_t sbtPos = cu.getSbtPos();
//bin - flag
bool sbtFlag = cu.sbtInfo != 0;
uint8_t ctxIdx = ( cuWidth * cuHeight <= 256 ) ? 1 : 0;
m_BinEncoder.encodeBin( sbtFlag, Ctx::SbtFlag( ctxIdx ) );
if( !sbtFlag )
{
return;
}
bool sbtQuadFlag = sbtIdx == SBT_HOR_QUAD || sbtIdx == SBT_VER_QUAD;
bool sbtHorFlag = sbtIdx == SBT_HOR_HALF || sbtIdx == SBT_HOR_QUAD;
bool sbtPosFlag = sbtPos == SBT_POS1;
uint8_t sbtVerHalfAllow = CU::targetSbtAllowed( SBT_VER_HALF, sbtAllowed );
uint8_t sbtHorHalfAllow = CU::targetSbtAllowed( SBT_HOR_HALF, sbtAllowed );
uint8_t sbtVerQuadAllow = CU::targetSbtAllowed( SBT_VER_QUAD, sbtAllowed );
uint8_t sbtHorQuadAllow = CU::targetSbtAllowed( SBT_HOR_QUAD, sbtAllowed );
//bin - type
if( ( sbtHorHalfAllow || sbtVerHalfAllow ) && ( sbtHorQuadAllow || sbtVerQuadAllow ) )
{
m_BinEncoder.encodeBin( sbtQuadFlag, Ctx::SbtQuadFlag( 0 ) );
}
else
{
assert( sbtQuadFlag == 0 );
}
//bin - dir
if( ( sbtQuadFlag && sbtVerQuadAllow && sbtHorQuadAllow ) || ( !sbtQuadFlag && sbtVerHalfAllow && sbtHorHalfAllow ) ) //both direction allowed
{
uint8_t ctxIdx = ( cuWidth == cuHeight ) ? 0 : ( cuWidth < cuHeight ? 1 : 2 );
m_BinEncoder.encodeBin( sbtHorFlag, Ctx::SbtHorFlag( ctxIdx ) );
}
else
{
assert( sbtHorFlag == ( ( sbtQuadFlag && sbtHorQuadAllow ) || ( !sbtQuadFlag && sbtHorHalfAllow ) ) );
}
//bin - pos
m_BinEncoder.encodeBin( sbtPosFlag, Ctx::SbtPosFlag( 0 ) );
DTRACE( g_trace_ctx, D_SYNTAX, "sbt_mode() pos=(%d,%d) sbt_info=%d\n", cu.lx(), cu.ly(), (int)cu.sbtInfo );
}
void CABACWriter::end_of_ctu( const CodingUnit& cu, CUCtx& cuCtx )
{
const bool isLastSubCUOfCtu = CU::isLastSubCUOfCtu( cu );
if ( isLastSubCUOfCtu
#if INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS
&& (!CS::isDualITree(*cu.cs) || cu.chromaFormat == CHROMA_400 || isChroma(cu.chType))
#else
&& (!cu.isSepTree() || cu.chromaFormat == CHROMA_400 || isChroma(cu.chType))
#endif
)
{
cuCtx.isDQPCoded = ( cu.cs->pps->getUseDQP() && !cuCtx.isDQPCoded );
}
}
void CABACWriter::cu_palette_info(const CodingUnit& cu, ComponentID compBegin, uint32_t numComp, CUCtx& cuCtx)
{
const SPS& sps = *(cu.cs->sps);
TransformUnit& tu = *cu.firstTU;
uint32_t indexMaxSize = cu.useEscape[compBegin] ? (cu.curPLTSize[compBegin] + 1) : cu.curPLTSize[compBegin];
#if INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS
int maxPltSize = CS::isDualITree(*cu.cs) ? MAXPLTSIZE_DUALTREE : MAXPLTSIZE;
#else
int maxPltSize = cu.isSepTree() ? MAXPLTSIZE_DUALTREE : MAXPLTSIZE;
#endif
if (cu.lastPLTSize[compBegin])
{
xEncodePLTPredIndicator(cu, maxPltSize, compBegin);
}
uint32_t reusedPLTnum = 0;
for (int idx = 0; idx < cu.lastPLTSize[compBegin]; idx++)
{
if( cu.reuseflag[compBegin][idx] )
{
reusedPLTnum++;
}
}
if (reusedPLTnum < maxPltSize)
{
exp_golomb_eqprob(cu.curPLTSize[compBegin] - reusedPLTnum, 0);
}
DTRACE(g_trace_ctx, D_SYNTAX, "cu_palette_info() recieved_plt_num=%d\n", cu.curPLTSize[compBegin] - reusedPLTnum);
for (int comp = compBegin; comp < (compBegin + numComp); comp++)
{
for (int idx = cu.reusePLTSize[compBegin]; idx < cu.curPLTSize[compBegin]; idx++)
{
ComponentID compID = (ComponentID)comp;
const int channelBitDepth = sps.getBitDepth(toChannelType(compID));
m_BinEncoder.encodeBinsEP(cu.curPLT[comp][idx], channelBitDepth);
DTRACE(g_trace_ctx, D_SYNTAX, "cu_palette_info() comp=%d idx=%d cur_plt=%d\n", comp, idx, cu.curPLT[compID][idx]);
}
}
uint32_t signalEscape = (cu.useEscape[compBegin]) ? 1 : 0;
if (cu.curPLTSize[compBegin] > 0)
{
m_BinEncoder.encodeBinEP(signalEscape);
DTRACE(g_trace_ctx, D_SYNTAX, "cu_palette_info() esc_code=%d\n", signalEscape);
}
//encode index map
uint32_t height = cu.block(compBegin).height;
uint32_t width = cu.block(compBegin).width;
m_scanOrder = g_scanOrder[SCAN_UNGROUPED][(cu.useRotation[compBegin]) ? SCAN_TRAV_VER : SCAN_TRAV_HOR][gp_sizeIdxInfo->idxFrom(width)][gp_sizeIdxInfo->idxFrom(height)];
uint32_t total = height * width;
if( indexMaxSize > 1 )
{
codeScanRotationModeFlag( cu, compBegin );
}
else
{
assert( !cu.useRotation[compBegin] );
}
if (cu.useEscape[compBegin] && cu.cs->pps->getUseDQP() && !cuCtx.isDQPCoded)
{
#if INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS
if (!CS::isDualITree(*tu.cs) || isLuma(tu.chType))
#else
if (!cu.isSepTree() || isLuma(tu.chType))
#endif
{
cu_qp_delta(cu, cuCtx.qp, cu.qp);
cuCtx.qp = cu.qp;
cuCtx.isDQPCoded = true;
}
}
if (cu.useEscape[compBegin] && cu.cs->slice->getUseChromaQpAdj() && !cuCtx.isChromaQpAdjCoded)
{
if (!CS::isDualITree(*tu.cs) || isChroma(tu.chType))
{
cu_chroma_qp_offset(cu);
cuCtx.isChromaQpAdjCoded = true;
}
}
uint32_t prevRunPos = 0;
unsigned prevRunType = 0;
for (int subSetId = 0; subSetId <= (total - 1) >> LOG2_PALETTE_CG_SIZE; subSetId++)
{
cuPaletteSubblockInfo(cu, compBegin, numComp, subSetId, prevRunPos, prevRunType);
}
CHECK(cu.curPLTSize[compBegin] > maxPltSize, " Current palette size is larger than maximum palette size");
}
void CABACWriter::cuPaletteSubblockInfo(const CodingUnit& cu, ComponentID compBegin, uint32_t numComp, int subSetId, uint32_t& prevRunPos, unsigned& prevRunType)
{
const SPS& sps = *(cu.cs->sps);
TransformUnit& tu = *cu.firstTU;
PLTtypeBuf runType = tu.getrunType(compBegin);
PelBuf curPLTIdx = tu.getcurPLTIdx(compBegin);
uint32_t indexMaxSize = cu.useEscape[compBegin] ? (cu.curPLTSize[compBegin] + 1) : cu.curPLTSize[compBegin];
uint32_t totalPel = cu.block(compBegin).height*cu.block(compBegin).width;
int minSubPos = subSetId << LOG2_PALETTE_CG_SIZE;
int maxSubPos = minSubPos + (1 << LOG2_PALETTE_CG_SIZE);
maxSubPos = (maxSubPos > totalPel) ? totalPel : maxSubPos; // if last position is out of the current CU size
unsigned runCopyFlag[(1 << LOG2_PALETTE_CG_SIZE)];
for( int i = 0; i < (1 << LOG2_PALETTE_CG_SIZE); i++ )
{
runCopyFlag[i] = MAX_INT;
}
if( minSubPos == 0 )
{
runCopyFlag[0] = 0;
}
// PLT runCopy flag and runType - context coded
int curPos = minSubPos;
for (; curPos < maxSubPos && indexMaxSize > 1; curPos++)
{
uint32_t posy = m_scanOrder[curPos].y;
uint32_t posx = m_scanOrder[curPos].x;
uint32_t posyprev = (curPos == 0) ? 0 : m_scanOrder[curPos - 1].y;
uint32_t posxprev = (curPos == 0) ? 0 : m_scanOrder[curPos - 1].x;
// encode runCopyFlag
bool identityFlag = !((runType.at(posx, posy) != runType.at(posxprev, posyprev))
|| ((runType.at(posx, posy) == PLT_RUN_INDEX) && (curPLTIdx.at(posx, posy) != curPLTIdx.at(posxprev, posyprev))));
const CtxSet& ctxSet = (prevRunType == PLT_RUN_INDEX)? Ctx::IdxRunModel: Ctx::CopyRunModel;
if ( curPos > 0 )
{
int dist = curPos - prevRunPos - 1;
const unsigned ctxId = DeriveCtx::CtxPltCopyFlag(prevRunType, dist);
runCopyFlag[curPos - minSubPos] = identityFlag;
m_BinEncoder.encodeBin( identityFlag, ctxSet( ctxId ) );
DTRACE(g_trace_ctx, D_SYNTAX, "plt_copy_flag() bin=%d ctx=%d\n", identityFlag, ctxId);
}
// encode run_type
if ( !identityFlag || curPos == 0 )
{
prevRunPos = curPos;
prevRunType = runType.at(posx, posy);
if (((posy == 0) && !cu.useRotation[compBegin]) || ((posx == 0) && cu.useRotation[compBegin]))
{
assert(runType.at(posx, posy) == PLT_RUN_INDEX);
}
else if (curPos != 0 && runType.at(posxprev, posyprev) == PLT_RUN_COPY)
{
assert(runType.at(posx, posy) == PLT_RUN_INDEX);
}
else
{
m_BinEncoder.encodeBin(runType.at(posx, posy), Ctx::RunTypeFlag());
}
DTRACE(g_trace_ctx, D_SYNTAX, "plt_type_flag() bin=%d sp=%d\n", runType.at(posx, posy), curPos);
}
}
// PLT index values - bypass coded
if (indexMaxSize > 1)
{
curPos = minSubPos;
for (; curPos < maxSubPos; curPos++)
{
uint32_t posy = m_scanOrder[curPos].y;
uint32_t posx = m_scanOrder[curPos].x;
if ( runCopyFlag[curPos - minSubPos] == 0 && runType.at(posx, posy) == PLT_RUN_INDEX)
{
writePLTIndex(cu, curPos, curPLTIdx, runType, indexMaxSize, compBegin);
DTRACE(g_trace_ctx, D_SYNTAX, "plt_idx_idc() value=%d sp=%d\n", curPLTIdx.at(posx, posy), curPos);
}
}
}
// Quantized escape colors - bypass coded
uint32_t scaleX = getComponentScaleX(COMPONENT_Cb, sps.getChromaFormatIdc());
uint32_t scaleY = getComponentScaleY(COMPONENT_Cb, sps.getChromaFormatIdc());
for (int comp = compBegin; comp < (compBegin + numComp); comp++)
{
ComponentID compID = (ComponentID)comp;
for (curPos = minSubPos; curPos < maxSubPos; curPos++)
{
uint32_t posy = m_scanOrder[curPos].y;
uint32_t posx = m_scanOrder[curPos].x;
if (curPLTIdx.at(posx, posy) == cu.curPLTSize[compBegin])
{
PLTescapeBuf escapeValue = tu.getescapeValue((ComponentID)comp);
if (compID == COMPONENT_Y || compBegin != COMPONENT_Y)
{
exp_golomb_eqprob((unsigned)escapeValue.at(posx, posy), 5);
DTRACE(g_trace_ctx, D_SYNTAX, "plt_escape_val() value=%d etype=%d sp=%d\n", escapeValue.at(posx, posy), comp, curPos);
}
if (compBegin == COMPONENT_Y && compID != COMPONENT_Y && posy % (1 << scaleY) == 0 && posx % (1 << scaleX) == 0)
{
uint32_t posxC = posx >> scaleX;
uint32_t posyC = posy >> scaleY;
exp_golomb_eqprob((unsigned)escapeValue.at(posxC, posyC), 5);
DTRACE(g_trace_ctx, D_SYNTAX, "plt_escape_val() value=%d etype=%d sp=%d\n", escapeValue.at(posx, posy), comp, curPos);
}
}
}
}
}
void CABACWriter::codeScanRotationModeFlag(const CodingUnit& cu, ComponentID compBegin)
{
m_BinEncoder.encodeBin((cu.useRotation[compBegin]), Ctx::RotationFlag());
DTRACE(g_trace_ctx, D_SYNTAX, "cu_palette_info() use_rotation=%d\n", cu.useRotation[compBegin]);
}
void CABACWriter::xEncodePLTPredIndicator(const CodingUnit& cu, uint32_t maxPLTSize, ComponentID compBegin)
{
int lastPredIdx = -1;
uint32_t run = 0;
uint32_t numPLTPredicted = 0;
for (uint32_t idx = 0; idx < cu.lastPLTSize[compBegin]; idx++)
{
if (cu.reuseflag[compBegin][idx])
{
numPLTPredicted++;
lastPredIdx = idx;
}
}
int idx = 0;
while (idx <= lastPredIdx)
{
if (cu.reuseflag[compBegin][idx])
{
exp_golomb_eqprob(run ? run + 1 : run, 0);
run = 0;
}
else
{
run++;
}
idx++;
}
if ((numPLTPredicted < maxPLTSize && lastPredIdx + 1 < cu.lastPLTSize[compBegin]) || !numPLTPredicted)
{
exp_golomb_eqprob(1, 0);
}
}
Pel CABACWriter::writePLTIndex(const CodingUnit& cu, uint32_t idx, PelBuf& paletteIdx, PLTtypeBuf& paletteRunType, int maxSymbol, ComponentID compBegin)
{
uint32_t posy = m_scanOrder[idx].y;
uint32_t posx = m_scanOrder[idx].x;
Pel curLevel = (paletteIdx.at(posx, posy) == cu.curPLTSize[compBegin]) ? (maxSymbol - 1) : paletteIdx.at(posx, posy);
if (idx) // R0348: remove index redundancy
{
uint32_t prevposy = m_scanOrder[idx - 1].y;
uint32_t prevposx = m_scanOrder[idx - 1].x;
if (paletteRunType.at(prevposx, prevposy) == PLT_RUN_INDEX)
{
Pel leftLevel = paletteIdx.at(prevposx, prevposy); // left index
if (leftLevel == cu.curPLTSize[compBegin]) // escape mode
{
leftLevel = maxSymbol - 1;
}
assert(leftLevel != curLevel);
if (curLevel > leftLevel)
{
curLevel--;
}
}
else
{
Pel aboveLevel;
if (cu.useRotation[compBegin])
{
assert(prevposx > 0);
aboveLevel = paletteIdx.at(posx - 1, posy);
if (paletteIdx.at(posx - 1, posy) == cu.curPLTSize[compBegin]) // escape mode
{
aboveLevel = maxSymbol - 1;
}
}
else
{
assert(prevposy > 0);
aboveLevel = paletteIdx.at(posx, posy - 1);
if (paletteIdx.at(posx, posy - 1) == cu.curPLTSize[compBegin]) // escape mode
{
aboveLevel = maxSymbol - 1;
}
}
assert(curLevel != aboveLevel);
if (curLevel > aboveLevel)
{
curLevel--;
}
}
maxSymbol--;
}
assert(maxSymbol > 0);
assert(curLevel >= 0);
assert(maxSymbol > curLevel);
if (maxSymbol > 1)
{
xWriteTruncBinCode(curLevel, maxSymbol);
}
return curLevel;
}
//================================================================================
// clause 7.3.8.6
//--------------------------------------------------------------------------------
// void prediction_unit ( pu );
// void merge_flag ( pu );
// void merge_idx ( pu );
// void inter_pred_idc ( pu );
// void ref_idx ( pu, refList );
// void mvp_flag ( pu, refList );
//================================================================================
void CABACWriter::prediction_unit( const PredictionUnit& pu )
{
#if !INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS
CHECK( pu.cu->treeType == TREE_C, "cannot be chroma CU" );
#endif
#if ENABLE_SPLIT_PARALLELISM
CHECK( pu.cacheUsed, "Processing a PU that should be in cache!" );
CHECK( pu.cu->cacheUsed, "Processing a CU that should be in cache!" );
#endif
if( pu.cu->skip )
{
CHECK( !pu.mergeFlag, "merge_flag must be true for skipped CUs" );
}
else
{
merge_flag( pu );
}
#if !JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
#if JVET_AA0070_RRIBC
rribcData(*pu.cu);
#endif
#else
if (pu.isBvpClusterApplicable())
{
bvOneZeroComp(*pu.cu);
}
#if JVET_AA0070_RRIBC
else
{
rribcData(*pu.cu);
}
#endif
#endif
#if JVET_AC0112_IBC_LIC
cuIbcLicFlag(*pu.cu);
#endif
if( pu.mergeFlag )
{
merge_data(pu);
#if MULTI_HYP_PRED
if( !pu.cu->skip && !CU::isIBC( *pu.cu ) )
{
CHECK(pu.numMergedAddHyps > pu.addHypData.size(), "wrong number of additional hypotheseis in mergemode");
mh_pred_data(pu);
}
else
{
CHECK(pu.numMergedAddHyps != pu.addHypData.size(), "wrong number of additional hypotheseis in merge mode");
}
#endif
}
else if (CU::isIBC(*pu.cu))
{
#if JVET_AE0169_BIPREDICTIVE_IBC
ibcBiPredictionFlag(pu);
#endif
#if JVET_AC0112_IBC_CIIP
ibcCiipFlag(pu);
if (pu.ibcCiipFlag)
{
ibcCiipIntraIdx(pu);
}
#endif
ref_idx(pu, REF_PIC_LIST_0);
Mv mvd = pu.mvd[REF_PIC_LIST_0];
mvd.changeIbcPrecInternal2Amvr(pu.cu->imv);
#if JVET_AA0070_RRIBC
#if JVET_Z0131_IBC_BVD_BINARIZATION
#if JVET_AC0104_IBC_BVD_PREDICTION
#if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
bvdCoding(mvd, pu.isBvdPredApplicable(), pu.isBvpClusterApplicable(), pu.cu->bvOneZeroComp, pu.cu->bvZeroCompDir,
pu.cu->rribcFlipType); // already changed to signaling precision
#else
bvdCoding(mvd, pu.isBvdPredApplicable(), pu.cu->rribcFlipType); // already changed to signaling precision
#endif
#else
#if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
bvdCoding(mvd, pu.isBvpClusterApplicable(), pu.cu->bvOneZeroComp, pu.cu->bvZeroCompDir,
pu.cu->rribcFlipType); // already changed to signaling precision
#else
bvdCoding(mvd, pu.cu->rribcFlipType); // already changed to signaling precision
#endif
#endif
#else
mvd_coding(mvd, 0, true, pu.cu->rribcFlipType); // already changed to signaling precision
#endif
#else
#if JVET_Z0131_IBC_BVD_BINARIZATION
#if JVET_AC0104_IBC_BVD_PREDICTION
#if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
bvdCoding(mvd, pu.isBvdPredApplicable(), pu.isBvpClusterApplicable(), pu.cu->bvOneZeroComp,
pu.cu->bvZeroCompDir); // already changed to signaling precision
#else
bvdCoding(mvd, pu.isBvdPredApplicable()); // already changed to signaling precision
#endif
#else
#if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
bvdCoding(mvd, pu.isBvpClusterApplicable(), pu.cu->bvOneZeroComp,
pu.cu->bvZeroCompDir); // already changed to signaling precision
#else
bvdCoding(mvd); // already changed to signaling precision
#endif
#endif
#else
mvd_coding(mvd, 0); // already changed to signaling precision
#endif
#endif
if (pu.cs->sps->getMaxNumIBCMergeCand() == 1)
{
CHECK( pu.mvpIdx[REF_PIC_LIST_0], "mvpIdx for IBC mode should be 0" );
}
else
mvp_flag(pu, REF_PIC_LIST_0);
#if JVET_AE0169_BIPREDICTIVE_IBC
if (pu.amvpMergeModeFlag[REF_PIC_LIST_1])
{
merge_idx(pu);
}
#endif
}
else
{
#if JVET_X0083_BM_AMVP_MERGE_MODE
amvpMerge_mode( pu );
if (!(pu.amvpMergeModeFlag[0] || pu.amvpMergeModeFlag[1]))
{
#endif
inter_pred_idc( pu );
affine_flag ( *pu.cu );
#if JVET_AG0098_AMVP_WITH_SBTMVP
amvpSbTmvpFlag(pu);
if (!pu.amvpSbTmvpFlag)
{
#endif
smvd_mode( pu );
#if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED || JVET_AD0140_MVD_PREDICTION
#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
if(pu.cs->sps->getUseMvdPred())
{
#endif
cu_bcw_flag(*pu.cu);
#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
}
#endif
#endif
#if JVET_Z0054_BLK_REF_PIC_REORDER
refPairIdx(pu);
#endif
#if JVET_AG0098_AMVP_WITH_SBTMVP
}
#endif
#if JVET_X0083_BM_AMVP_MERGE_MODE
}
#endif
#if JVET_Z0054_BLK_REF_PIC_REORDER
refIdxLC(pu);
#endif
if( pu.interDir != 2 /* PRED_L1 */ )
{
#if JVET_X0083_BM_AMVP_MERGE_MODE
if (!pu.amvpMergeModeFlag[REF_PIC_LIST_0])
{
#endif
ref_idx ( pu, REF_PIC_LIST_0 );
#if JVET_Y0129_MVD_SIGNAL_AMVP_MERGE_MODE
mvp_flag ( pu, REF_PIC_LIST_0 );
#endif
if ( pu.cu->affine )
{
Mv mvd = pu.mvdAffi[REF_PIC_LIST_0][0];
mvd.changeAffinePrecInternal2Amvr(pu.cu->imv);
#if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
#if JVET_AD0140_MVD_PREDICTION
{
const auto& si = pu.mvdSuffixInfo.mvBins[REF_PIC_LIST_0][0];
mvd_coding(mvd, pu.cu->imv, &si, !pu.isMvdPredApplicable());
}
#else
mvd_coding(mvd, 0, !pu.isMvdPredApplicable());
#endif
#else
mvd_coding(mvd, 0); // already changed to signaling precision
#endif
mvd = pu.mvdAffi[REF_PIC_LIST_0][1];
mvd.changeAffinePrecInternal2Amvr(pu.cu->imv);
#if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
#if JVET_AD0140_MVD_PREDICTION
{
const auto& si = pu.mvdSuffixInfo.mvBins[REF_PIC_LIST_0][1];
mvd_coding(mvd, pu.cu->imv, &si, !pu.isMvdPredApplicable());
}
#else
mvd_coding(mvd, 0, !pu.isMvdPredApplicable());
#endif
#else
mvd_coding(mvd, 0); // already changed to signaling precision
#endif
if ( pu.cu->affineType == AFFINEMODEL_6PARAM )
{
mvd = pu.mvdAffi[REF_PIC_LIST_0][2];
mvd.changeAffinePrecInternal2Amvr(pu.cu->imv);
#if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
#if JVET_AD0140_MVD_PREDICTION
const auto& si = pu.mvdSuffixInfo.mvBins[REF_PIC_LIST_0][2];
mvd_coding(mvd, pu.cu->imv, &si, !pu.isMvdPredApplicable());
#else
mvd_coding(mvd, 0, !pu.isMvdPredApplicable());
#endif
#else
mvd_coding(mvd, 0); // already changed to signaling precision
#endif
}
}
#if JVET_AG0098_AMVP_WITH_SBTMVP
else if (pu.amvpSbTmvpFlag)
{
amvpSbTmvpMvdCoding(pu);
}
#endif
else
{
Mv mvd = pu.mvd[REF_PIC_LIST_0];
#if JVET_Y0129_MVD_SIGNAL_AMVP_MERGE_MODE
if (pu.amvpMergeModeFlag[REF_PIC_LIST_1] == true && pu.mvpIdx[REF_PIC_LIST_0] < 2)
{
CHECK(mvd.hor != 0, "this is not possible");
CHECK(mvd.ver != 0, "this is not possible");
}
else
{
#endif
mvd.changeTransPrecInternal2Amvr(pu.cu->imv);
#if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
#if JVET_AD0140_MVD_PREDICTION
const auto& si = pu.mvdSuffixInfo.mvBins[REF_PIC_LIST_0][0];
mvd_coding(mvd, pu.cu->imv, &si, !pu.isMvdPredApplicable());
#else
mvd_coding(mvd, 0, !pu.isMvdPredApplicable());
#endif
#else
mvd_coding(mvd, 0); // already changed to signaling precision
#endif
#if JVET_Y0129_MVD_SIGNAL_AMVP_MERGE_MODE
}
#endif
}
#if JVET_X0083_BM_AMVP_MERGE_MODE
}
#endif
#if !JVET_Y0129_MVD_SIGNAL_AMVP_MERGE_MODE
mvp_flag ( pu, REF_PIC_LIST_0 );
#endif
}
if( pu.interDir != 1 /* PRED_L0 */ )
{
if ( pu.cu->smvdMode != 1 )
{
#if JVET_X0083_BM_AMVP_MERGE_MODE
if (!pu.amvpMergeModeFlag[REF_PIC_LIST_1])
{
#endif
ref_idx ( pu, REF_PIC_LIST_1 );
#if JVET_Y0129_MVD_SIGNAL_AMVP_MERGE_MODE
mvp_flag ( pu, REF_PIC_LIST_1 );
#endif
if( !pu.cs->picHeader->getMvdL1ZeroFlag() || pu.interDir != 3 /* PRED_BI */ )
{
if ( pu.cu->affine )
{
Mv mvd = pu.mvdAffi[REF_PIC_LIST_1][0];
mvd.changeAffinePrecInternal2Amvr(pu.cu->imv);
#if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
#if JVET_AD0140_MVD_PREDICTION
const auto& si = pu.mvdSuffixInfo.mvBins[REF_PIC_LIST_1][0];
mvd_coding(mvd, pu.cu->imv, &si, !pu.isMvdPredApplicable());
#else
mvd_coding(mvd, 0, !pu.isMvdPredApplicable());
#endif
#else
mvd_coding(mvd, 0); // already changed to signaling precision
#endif
mvd = pu.mvdAffi[REF_PIC_LIST_1][1];
mvd.changeAffinePrecInternal2Amvr(pu.cu->imv);
#if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
#if JVET_AD0140_MVD_PREDICTION
const auto& si1 = pu.mvdSuffixInfo.mvBins[REF_PIC_LIST_1][1];
mvd_coding(mvd, pu.cu->imv, &si1, !pu.isMvdPredApplicable());
#else
mvd_coding(mvd, 0, !pu.isMvdPredApplicable());
#endif
#else
mvd_coding(mvd, 0); // already changed to signaling precision
#endif
if ( pu.cu->affineType == AFFINEMODEL_6PARAM )
{
mvd = pu.mvdAffi[REF_PIC_LIST_1][2];
mvd.changeAffinePrecInternal2Amvr(pu.cu->imv);
#if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
#if JVET_AD0140_MVD_PREDICTION
const auto& si2 = pu.mvdSuffixInfo.mvBins[REF_PIC_LIST_1][2];
mvd_coding(mvd, pu.cu->imv, &si2, !pu.isMvdPredApplicable());
#else
mvd_coding(mvd, 0, !pu.isMvdPredApplicable());
#endif
#else
mvd_coding(mvd, 0); // already changed to signaling precision
#endif
}
}
#if JVET_AG0098_AMVP_WITH_SBTMVP
else if (pu.amvpSbTmvpFlag)
{
amvpSbTmvpMvdCoding(pu);
}
#endif
else
{
Mv mvd = pu.mvd[REF_PIC_LIST_1];
#if JVET_Y0129_MVD_SIGNAL_AMVP_MERGE_MODE
if (pu.amvpMergeModeFlag[REF_PIC_LIST_0] == true && pu.mvpIdx[REF_PIC_LIST_1] < 2)
{
CHECK(mvd.hor != 0, "this is not possible");
CHECK(mvd.ver != 0, "this is not possible");
}
else
{
#endif
mvd.changeTransPrecInternal2Amvr(pu.cu->imv);
#if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
#if JVET_AD0140_MVD_PREDICTION
const auto& si = pu.mvdSuffixInfo.mvBins[REF_PIC_LIST_1][0];
mvd_coding(mvd, pu.cu->imv, &si, !pu.isMvdPredApplicable());
#else
mvd_coding(mvd, 0, !pu.isMvdPredApplicable());
#endif
#else
mvd_coding(mvd, 0); // already changed to signaling precision
#endif
#if JVET_Y0129_MVD_SIGNAL_AMVP_MERGE_MODE
}
#endif
}
}
#if JVET_X0083_BM_AMVP_MERGE_MODE
}
#endif
}
#if JVET_Y0129_MVD_SIGNAL_AMVP_MERGE_MODE
else
{
CHECK( pu.refIdx[REF_PIC_LIST_1] != pu.cs->slice->getSymRefIdx(REF_PIC_LIST_1), "Wrong L1 reference index" );
mvp_flag ( pu, REF_PIC_LIST_1 );
}
#endif
#if !JVET_Y0129_MVD_SIGNAL_AMVP_MERGE_MODE
mvp_flag ( pu, REF_PIC_LIST_1 );
#endif
}
}
}
#if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED || JVET_AC0104_IBC_BVD_PREDICTION
void CABACWriter::mvsd_data(const PredictionUnit& pu)
{
CHECK(pu.cu->slice->getSliceType() == I_SLICE && !CU::isIBC(*pu.cu), "cannot be I Slice");
#if !JVET_AC0104_IBC_BVD_PREDICTION
if (CU::isIBC(*pu.cu))
{
return;
}
#endif
if (pu.cu->skip || pu.mergeFlag
#if !JVET_AC0104_IBC_BVD_PREDICTION
|| CU::isIBC(*pu.cu)
#endif
#if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
|| !pu.isMvdPredApplicable()
#endif
)
{
return;
}
#if JVET_AG0098_AMVP_WITH_SBTMVP
if (pu.amvpSbTmvpFlag)
{
return;
}
#endif
if (pu.interDir != 2 /* PRED_L1 */)
{
#if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
if (pu.cu->affine)
{
mvsdAffineIdxFunc(pu, REF_PIC_LIST_0);
}
else
#endif
{
mvsdIdxFunc(pu, REF_PIC_LIST_0);
}
}
#if JVET_AC0104_IBC_BVD_PREDICTION
if (CU::isIBC(*pu.cu))
{
return;
}
#endif
#if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
if (pu.interDir != 1 /* PRED_L0 */ && pu.cu->smvdMode != 1)
{
if (pu.cu->affine)
{
mvsdAffineIdxFunc(pu, REF_PIC_LIST_1);
}
else
{
mvsdIdxFunc(pu, REF_PIC_LIST_1);
}
}
#endif
}
#endif
void CABACWriter::smvd_mode( const PredictionUnit& pu )
{
if ( pu.interDir != 3 || pu.cu->affine )
{
return;
}
if ( pu.cs->slice->getBiDirPred() == false )
{
return;
}
m_BinEncoder.encodeBin( pu.cu->smvdMode ? 1 : 0, Ctx::SmvdFlag() );
DTRACE( g_trace_ctx, D_SYNTAX, "symmvd_flag() symmvd=%d pos=(%d,%d) size=%dx%d\n", pu.cu->smvdMode ? 1 : 0, pu.lumaPos().x, pu.lumaPos().y, pu.lumaSize().width, pu.lumaSize().height );
}
#if JVET_AG0098_AMVP_WITH_SBTMVP
void CABACWriter::amvpSbTmvpFlag(const PredictionUnit& pu)
{
if (!pu.cs->sps->getSbTMVPEnabledFlag())
{
return;
}
if (!pu.cs->slice->getAmvpSbTmvpEnabledFlag())
{
return;
}
if (pu.cu->affine)
{
return;
}
if (pu.interDir == 3)
{
return;
}
m_BinEncoder.encodeBin(pu.amvpSbTmvpFlag ? 1 : 0, Ctx::amvpSbTmvpFlag(0));
DTRACE(g_trace_ctx, D_SYNTAX, "amvpSbTmvpFlag() amvpSbTmvpFlag=%d colIdx:%d pos=(%d,%d) size=%dx%d\n", pu.amvpSbTmvpFlag ? 1 : 0, pu.colIdx ? 1 : 0, pu.lumaPos().x, pu.lumaPos().y, pu.lumaSize().width, pu.lumaSize().height);
if (pu.amvpSbTmvpFlag)
{
if (pu.cs->slice->getAmvpSbTmvpNumColPic() > 1)
{
m_BinEncoder.encodeBin((pu.interDir == 2), Ctx::amvpSbTmvpFlag(1));
}
if (isEncoding())
{
g_picAmvpSbTmvpEnabledArea += pu.lwidth() * pu.lheight();
}
}
}
void CABACWriter::amvpSbTmvpMvdCoding(const PredictionUnit &pu)
{
if (pu.amvpSbTmvpMvdIdx < 0)
{
m_BinEncoder.encodeBin(1, Ctx::amvpSbTmvpMvdIdx(0));
DTRACE(g_trace_ctx, D_SYNTAX, "amvpSbTmvpMvdCoding() pos=(%d,%d) size=(%d,%d) amvpSbTmvpMvdIdx:%d\n", pu.lx(), pu.ly(), pu.lwidth(), pu.lheight(), -1);
}
else
{
m_BinEncoder.encodeBin(0, Ctx::amvpSbTmvpMvdIdx(0));
int numStepCandMinus1 = pu.cs->slice->getAmvpSbTmvpNumOffset() - 1;
unsigned int amvpSbTmvpMvdIdx = (unsigned int)pu.amvpSbTmvpMvdIdx;
m_BinEncoder.encodeBinsEP(amvpSbTmvpMvdIdx % (1 << 2), 2);
amvpSbTmvpMvdIdx >>= 2;
for (unsigned int uiUnaryIdx = 0; uiUnaryIdx < numStepCandMinus1; ++uiUnaryIdx)
{
unsigned int uiSymbol = amvpSbTmvpMvdIdx == uiUnaryIdx ? 0 : 1;
m_BinEncoder.encodeBin(uiSymbol, Ctx::amvpSbTmvpMvdIdx(uiUnaryIdx + 1));
if (uiSymbol == 0)
{
break;
}
}
DTRACE(g_trace_ctx, D_SYNTAX, "amvpSbTmvpMvdCoding() pos=(%d,%d) size=(%d,%d) amvpSbTmvpMvdIdx:%d numStepCandMinus1:%d\n", pu.lx(), pu.ly(), pu.lwidth(), pu.lheight(), pu.amvpSbTmvpMvdIdx, numStepCandMinus1);
}
}
#endif
void CABACWriter::subblock_merge_flag( const CodingUnit& cu )
{
if ( !cu.cs->slice->isIntra() && (cu.slice->getPicHeader()->getMaxNumAffineMergeCand() > 0) && cu.lumaSize().width >= 8 && cu.lumaSize().height >= 8 )
{
unsigned ctxId = DeriveCtx::CtxAffineFlag( cu );
m_BinEncoder.encodeBin( cu.affine, Ctx::SubblockMergeFlag( ctxId ) );
DTRACE( g_trace_ctx, D_SYNTAX, "subblock_merge_flag() subblock_merge_flag=%d ctx=%d pos=(%d,%d)\n", cu.affine ? 1 : 0, ctxId, cu.Y().x, cu.Y().y );
}
}
void CABACWriter::affine_flag( const CodingUnit& cu )
{
#if INTER_RM_SIZE_CONSTRAINTS
if (!cu.cs->slice->isIntra() && cu.cs->sps->getUseAffine() && cu.lumaSize().width >= 8 && cu.lumaSize().height >= 8)
#else
if ( !cu.cs->slice->isIntra() && cu.cs->sps->getUseAffine() && cu.lumaSize().width > 8 && cu.lumaSize().height > 8 )
#endif
{
unsigned ctxId = DeriveCtx::CtxAffineFlag( cu );
m_BinEncoder.encodeBin( cu.affine, Ctx::AffineFlag( ctxId ) );
DTRACE( g_trace_ctx, D_SYNTAX, "affine_flag() affine=%d ctx=%d pos=(%d,%d)\n", cu.affine ? 1 : 0, ctxId, cu.Y().x, cu.Y().y );
if ( cu.affine && cu.cs->sps->getUseAffineType() )
{
unsigned ctxId = 0;
m_BinEncoder.encodeBin( cu.affineType, Ctx::AffineType( ctxId ) );
DTRACE( g_trace_ctx, D_SYNTAX, "affine_type() affine_type=%d ctx=%d pos=(%d,%d)\n", cu.affineType ? 1 : 0, ctxId, cu.Y().x, cu.Y().y );
}
}
}
#if AFFINE_MMVD
void CABACWriter::affine_mmvd_data(const PredictionUnit& pu)
{
if (!pu.cs->sps->getUseAffineMmvdMode() || !pu.mergeFlag || !pu.cu->affine)
{
return;
}
m_BinEncoder.encodeBin(pu.afMmvdFlag, Ctx::AfMmvdFlag());
DTRACE(g_trace_ctx, D_SYNTAX, "affine_mmvd_flag() af_mmvd_merge=%d pos=(%d,%d) size=%dx%d\n", pu.afMmvdFlag ? 1 : 0, pu.lumaPos().x, pu.lumaPos().y, pu.lumaSize().width, pu.lumaSize().height);
if (!pu.afMmvdFlag)
{
return;
}
// Base affine merge candidate idx
uint8_t afMmvdBaseIdx = pu.afMmvdBaseIdx;
int numCandMinus1Base = AF_MMVD_BASE_NUM - 1;
#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
unsigned ctxId = 0;
#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
static_assert(ECM3_AF_MMVD_BASE_NUM == 1, "The value of ECM3_AF_MMVD_BASE_NUM must be 1");
if (pu.cs->sps->getUseTMMMVD())
#endif
{
const CodingStructure *cs = pu.cu->cs;
const CodingUnit *cuLeft = cs->getCURestricted(pu.cu->lumaPos().offset(-1, 0), *pu.cu, CH_L);
ctxId = (cuLeft && cuLeft->affine) ? 1 : 0;
const CodingUnit *cuAbove = cs->getCURestricted(pu.cu->lumaPos().offset(0, -1), *pu.cu, CH_L);
ctxId += (cuAbove && cuAbove->affine) ? 1 : 0;
}
numCandMinus1Base = (ctxId == 0) ? 0 : ((ctxId == 1) ? 1 : AF_MMVD_BASE_NUM-1);
#endif
if (numCandMinus1Base > 0)
{
// to support more base candidates
#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
int ctx2 = (numCandMinus1Base == 1) ? 1 : 0;
m_BinEncoder.encodeBin((afMmvdBaseIdx == 0 ? 0 : 1), Ctx::AfMmvdIdx(ctx2));
#else
m_BinEncoder.encodeBin((afMmvdBaseIdx == 0 ? 0 : 1), Ctx::AfMmvdIdx());
#endif
if (afMmvdBaseIdx > 0)
{
for (unsigned idx = 1; idx < numCandMinus1Base; idx++)
{
#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
m_BinEncoder.encodeBin(afMmvdBaseIdx == idx ? 0 : 1, Ctx::AfMmvdIdx(idx + 1));
#else
m_BinEncoder.encodeBinEP(afMmvdBaseIdx == idx ? 0 : 1);
#endif
if (afMmvdBaseIdx == idx)
{
break;
}
}
}
}
DTRACE(g_trace_ctx, D_SYNTAX, "affine_mmvd_base_idx() af_mmvd_base_idx=%d\n", afMmvdBaseIdx);
#if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
if(pu.cs->sps->getUseTMMMVD())
{
#endif
#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
uint16_t sym = pu.afMmvdMergeIdx;
#else
uint8_t sym = pu.afMmvdMergeIdx;
#endif
#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
sym -= afMmvdBaseIdx * AF_MMVD_MAX_REFINE_NUM;
#endif
unsigned int ricePar = 1;
#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
int numStepCandMinus1 = ((AF_MMVD_MAX_REFINE_NUM >> ricePar) >> AFFINE_MMVD_SIZE_SHIFT) / AFFINE_BI_DIR - 1;
#else
int numStepCandMinus1 = ((AF_MMVD_MAX_REFINE_NUM >> ricePar) >> AFFINE_MMVD_SIZE_SHIFT) - 1;
#endif
if(ricePar > 0)
{
#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
m_BinEncoder.encodeBin( sym % (1 << ricePar), Ctx::AfMmvdOffsetStep(5));
#else
m_BinEncoder.encodeBinsEP( sym % (1 << ricePar), ricePar);
#endif
}
sym >>= ricePar;
for (unsigned int uiUnaryIdx = 0; uiUnaryIdx < numStepCandMinus1; ++uiUnaryIdx)
{
unsigned int uiSymbol = sym == uiUnaryIdx ? 0 : 1;
m_BinEncoder.encodeBin(uiSymbol, Ctx::AfMmvdOffsetStep((uiUnaryIdx > LAST_MERGE_MMVD_IDX_CABAC - 1 ? LAST_MERGE_MMVD_IDX_CABAC - 1 : uiUnaryIdx)));
if (uiSymbol == 0)
{
break;
}
}
#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
return;
}
#endif
#endif
#if !JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED || (JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED)
{
// Code Step Value
uint8_t step = pu.afMmvdStep;
#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
int numCandMinus1Base = ECM3_AF_MMVD_STEP_NUM - 1;
#else
int numCandMinus1Base = AF_MMVD_STEP_NUM - 1;
#endif
if (numCandMinus1Base > 0)
{
#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
m_BinEncoder.encodeBin((step == 0 ? 0 : 1), Ctx::AfMmvdOffsetStepECM3());
#else
m_BinEncoder.encodeBin((step == 0 ? 0 : 1), Ctx::AfMmvdOffsetStep());
#endif
if (step > 0)
{
for (unsigned idx = 1; idx < numCandMinus1Base; idx++)
{
m_BinEncoder.encodeBinEP(step == idx ? 0 : 1);
if (step == idx)
{
break;
}
}
}
}
DTRACE(g_trace_ctx, D_SYNTAX, "affine_mmvd_offset_step() af_mmvd_offset_step=%d\n", pu.afMmvdStep);
}
{
// Code Dir Value
uint8_t offsetDir = pu.afMmvdDir;
uint8_t b0 = offsetDir & 0x1;
uint8_t b1 = (offsetDir >> 1) & 0x1;
m_BinEncoder.encodeBinEP(b0);
m_BinEncoder.encodeBinEP(b1);
DTRACE(g_trace_ctx, D_SYNTAX, "affine_mmvd_offset_dir() af_mmvd_offset_dir=%d\n", pu.afMmvdDir);
}
#endif
}
#endif
#if JVET_AE0169_BIPREDICTIVE_IBC
void CABACWriter::ibcBiPredictionFlag( const PredictionUnit& pu )
{
if (!pu.cs->slice->getBiPredictionIBCFlag())
{
return;
}
if (!pu.mergeFlag && (pu.cu->ibcLicFlag || pu.cu->rribcFlipType))
{
return;
}
m_BinEncoder.encodeBin(pu.interDir == 3 ? 1 : 0, Ctx::BiPredIbcFlag(pu.mergeFlag ? 0 : 1));
DTRACE( g_trace_ctx, D_SYNTAX, "ibc_bi_prediction_flag() inter_dir=%d\n", pu.interDir );
}
void CABACWriter::ibcMergeIdx1( const PredictionUnit& pu )
{
if (pu.interDir != 3)
{
return;
}
int numCandminus2 = int(pu.cs->sps->getMaxNumIBCMergeCand()) - pu.mergeIdx - 2;
if( numCandminus2 > 0 )
{
CHECK(pu.ibcMergeIdx1 <= pu.mergeIdx, "pu.ibcMergeIdx1 <= pu.mergeIdx");
int idx1 = pu.ibcMergeIdx1 - pu.mergeIdx - 1;
#if TM_MRG || (JVET_Z0084_IBC_TM && IBC_TM_MRG)
const CtxSet mrgIdxCtxSet = pu.tmMergeFlag ? Ctx::TmMergeIdx : Ctx::MergeIdx;
#endif
unsigned int uiUnaryIdx = 0;
for (; uiUnaryIdx < numCandminus2; ++uiUnaryIdx)
{
unsigned int uiSymbol = idx1 == uiUnaryIdx ? 0 : 1;
#if TM_MRG || (JVET_Z0084_IBC_TM && IBC_TM_MRG)
m_BinEncoder.encodeBin(uiSymbol, mrgIdxCtxSet((uiUnaryIdx > LAST_MERGE_IDX_CABAC - 1 ? LAST_MERGE_IDX_CABAC - 1 : uiUnaryIdx)));
#else
m_BinEncoder.encodeBin(uiSymbol, Ctx::MergeIdx((uiUnaryIdx > LAST_MERGE_IDX_CABAC - 1 ? LAST_MERGE_IDX_CABAC - 1 : uiUnaryIdx)));
#endif
if (uiSymbol == 0)
{
break;
}
}
}
DTRACE( g_trace_ctx, D_SYNTAX, "ibc_merge_idx1() ibc_merge_idx1=%d\n", pu.ibcMergeIdx1 );
}
#endif
#if JVET_AA0061_IBC_MBVD
void CABACWriter::ibcMbvdData(const PredictionUnit& pu)
{
if (!pu.cs->sps->getUseIbcMbvd() || !pu.mergeFlag || !CU::isIBC(*pu.cu))
{
return;
}
m_BinEncoder.encodeBin(pu.ibcMbvdMergeFlag, Ctx::IbcMbvdFlag());
DTRACE(g_trace_ctx, D_SYNTAX, "ibc_mbvd_data() ibc_mbvd_flag=%d pos=(%d,%d) size=%dx%d\n", pu.ibcMbvdMergeFlag ? 1 : 0, pu.lumaPos().x, pu.lumaPos().y, pu.lumaSize().width, pu.lumaSize().height);
if (!pu.ibcMbvdMergeFlag)
{
return;
}
#if JVET_AE0169_IBC_MBVD_LIST_DERIVATION
const int mbvdsPerBase = pu.cu->slice->getSPS()->getUseIbcMbvdAdSearch() ? IBC_MBVD_SIZE_ENC : IBC_MBVD_MAX_REFINE_NUM;
#else
const int mbvdsPerBase = IBC_MBVD_MAX_REFINE_NUM;
#endif
#if JVET_AE0169_BIPREDICTIVE_IBC
if (pu.interDir == 3)
{
m_BinEncoder.encodeBin(pu.ibcMergeIdx1 < IBC_MRG_MAX_NUM_CANDS ? 0 : 1, Ctx::IbcMbvdFlag(1));
DTRACE(g_trace_ctx, D_SYNTAX, "ibc_mbvd_data() bi_mbvd_mode=%d\n", pu.ibcMergeIdx1 < IBC_MRG_MAX_NUM_CANDS ? 1 : 2);
}
#endif
int mvpIdx = pu.ibcMbvdMergeIdx;
uint8_t var0;
var0 = mvpIdx / mbvdsPerBase;
mvpIdx -= var0 * mbvdsPerBase;
// Base affine merge candidate idx
#if JVET_AE0169_BIPREDICTIVE_IBC
int numBaseCandMinus1 = std::min(int(pu.cs->sps->getMaxNumIBCMergeCand()) - 1, IBC_MBVD_BASE_NUM - 1);
#else
int numBaseCandMinus1 = IBC_MBVD_BASE_NUM - 1;
#endif
if (numBaseCandMinus1 > 0)
{
// to support more base candidates
m_BinEncoder.encodeBin((var0 == 0 ? 0 : 1), Ctx::IbcMbvdMergeIdx());
if (var0 > 0)
{
for (unsigned idx = 1; idx < numBaseCandMinus1; idx++)
{
m_BinEncoder.encodeBinEP(var0 == idx ? 0 : 1);
if (var0 == idx)
{
break;
}
}
}
}
DTRACE(g_trace_ctx, D_SYNTAX, "ibc_mbvd_data() base_idx=%d\n", var0);
#if JVET_AE0169_BIPREDICTIVE_IBC
int ibcMbvdSizeEnc = IBC_MBVD_SIZE_ENC;
uint8_t var1 = 0;
int mvpIdx1 = 0;
if (pu.interDir == 3 && pu.ibcMergeIdx1 >= IBC_MRG_MAX_NUM_CANDS)
{
mvpIdx1 = pu.ibcMergeIdx1 - IBC_MRG_MAX_NUM_CANDS;
var1 = mvpIdx1 / mbvdsPerBase;
mvpIdx1 -= var1 * mbvdsPerBase;
CHECK(var1 < var0, "var1 < var0");
if (numBaseCandMinus1 > 0 && var0 < numBaseCandMinus1)
{
// to support more base candidates
m_BinEncoder.encodeBinEP(var0 == var1 ? 0 : 1);
if (var1 > var0)
{
for (unsigned idx = var0+1; idx < numBaseCandMinus1; idx++)
{
if (idx == var0+1)
{
m_BinEncoder.encodeBin(var1 == idx ? 0 : 1, Ctx::IbcMbvdMergeIdx());
}
else
{
m_BinEncoder.encodeBinEP(var1 == idx ? 0 : 1);
}
if (var1 == idx)
{
break;
}
}
}
}
if (var1 == var0)
{
ibcMbvdSizeEnc--;
}
DTRACE(g_trace_ctx, D_SYNTAX, "ibc_mbvd_data() base_idx1=%d\n", var1);
}
unsigned int ricePar = 1;
unsigned int riceParVal = 1<<ricePar;
int mvpIdxby2 = mvpIdx >> ricePar;
int remain = ibcMbvdSizeEnc;
for (unsigned int uiUnaryIdx = 0; remain > riceParVal; ++uiUnaryIdx, remain-=riceParVal)
{
unsigned int uiSymbol = mvpIdxby2 == uiUnaryIdx ? 0 : 1;
m_BinEncoder.encodeBin(uiSymbol, Ctx::IbcMbvdStepMvpIdx((uiUnaryIdx > LAST_MERGE_MMVD_IDX_CABAC - 1 ? LAST_MERGE_MMVD_IDX_CABAC - 1 : uiUnaryIdx)));
if (uiSymbol == 0)
{
break;
}
}
int length = remain >= riceParVal ? ricePar : ceilLog2(remain);
if (length > 0)
{
m_BinEncoder.encodeBinsEP( mvpIdx % riceParVal, length);
}
DTRACE(g_trace_ctx, D_SYNTAX, "ibc_mbvd_data() ibc_merge_idx=%d\n", pu.ibcMbvdMergeIdx);
if (pu.interDir == 3 && pu.ibcMergeIdx1 >= IBC_MRG_MAX_NUM_CANDS)
{
if (var0 == var1)
{
CHECK(mvpIdx1 <= mvpIdx, "mvpIdx1 <= mvpIdx");
ibcMbvdSizeEnc = IBC_MBVD_SIZE_ENC - (mvpIdx+1);
mvpIdx1 -= (mvpIdx+1);
}
int mvpIdx1by2 = mvpIdx1 >> ricePar;
int remain1 = ibcMbvdSizeEnc;
for (unsigned int uiUnaryIdx = 0; remain1 > riceParVal; ++uiUnaryIdx, remain1-=riceParVal)
{
unsigned int uiSymbol = mvpIdx1by2 == uiUnaryIdx ? 0 : 1;
m_BinEncoder.encodeBin(uiSymbol, Ctx::IbcMbvdStepMvpIdx((uiUnaryIdx > LAST_MERGE_MMVD_IDX_CABAC - 1 ? LAST_MERGE_MMVD_IDX_CABAC - 1 : uiUnaryIdx)));
if (uiSymbol == 0)
{
break;
}
}
int length1 = remain1 >= riceParVal ? ricePar : ceilLog2(remain1);
if (length1 > 0)
{
m_BinEncoder.encodeBinsEP( mvpIdx1 % riceParVal, length1);
}
DTRACE(g_trace_ctx, D_SYNTAX, "ibc_mbvd_data() ibc_merge_idx1=%d\n", pu.ibcMergeIdx1 - IBC_MRG_MAX_NUM_CANDS);
}
#else
unsigned int ricePar = 1;
int numCandStepMinus1 = (IBC_MBVD_SIZE_ENC >> ricePar) - 1;
if(ricePar > 0)
{
m_BinEncoder.encodeBinsEP( mvpIdx % (1 << ricePar), ricePar);
}
mvpIdx >>= ricePar;
for (unsigned int uiUnaryIdx = 0; uiUnaryIdx < numCandStepMinus1; ++uiUnaryIdx)
{
unsigned int uiSymbol = mvpIdx == uiUnaryIdx ? 0 : 1;
m_BinEncoder.encodeBin(uiSymbol, Ctx::IbcMbvdStepMvpIdx((uiUnaryIdx > LAST_MERGE_MMVD_IDX_CABAC - 1 ? LAST_MERGE_MMVD_IDX_CABAC - 1 : uiUnaryIdx)));
if (uiSymbol == 0)
{
break;
}
}
DTRACE(g_trace_ctx, D_SYNTAX, "ibc_mbvd_data() merge_idx=%d\n", pu.ibcMbvdMergeIdx);
#endif
}
#endif
#if TM_MRG || (JVET_Z0084_IBC_TM && IBC_TM_MRG)
void CABACWriter::tm_merge_flag(const PredictionUnit& pu)
{
#if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
if (CU::isIBC(*pu.cu) && !pu.cs->sps->getUseTMIbc())
{
return;
}
#endif
#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_X0141_CIIP_TIMD_TM && TM_MRG
if (pu.ciipFlag)
{
if (pu.cs->slice->getSPS()->getUseCiipTmMrg())
{
m_BinEncoder.encodeBin(pu.tmMergeFlag, Ctx::CiipTMMergeFlag());
DTRACE(g_trace_ctx, D_SYNTAX, "tm_merge_flag() ciip_tm_merge_flag=%d\n", pu.tmMergeFlag);
}
return;
}
#endif
#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_W0097_GPM_MMVD_TM && TM_MRG
if (pu.cu->geoFlag)
{
if (!pu.cs->slice->getSPS()->getUseGPMTMMode())
{
return;
}
}
else
#endif
#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && TM_MRG
if (pu.regularMergeFlag
#if JVET_Z0084_IBC_TM && IBC_TM_MRG
&& !CU::isIBC(*pu.cu)
#endif
)
{
if (!pu.cs->slice->getSPS()->getUseTMMrgMode())
{
return;
}
}
else
#endif
if (!pu.cs->slice->getSPS()->getUseDMVDMode())
{
#if (JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_X0141_CIIP_TIMD_TM && TM_MRG) && (JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_W0097_GPM_MMVD_TM && TM_MRG) && (JVET_AA0132_CONFIGURABLE_TM_TOOLS && TM_MRG)
#if !(JVET_Z0084_IBC_TM && IBC_TM_MRG)
CHECK(true, "Unknown mode to code tm_merge_flag");
#endif
#endif
return;
}
#if JVET_Z0084_IBC_TM && IBC_TM_MRG
#if JVET_X0049_ADAPT_DMVR
m_BinEncoder.encodeBin(pu.tmMergeFlag || pu.bmMergeFlag, Ctx::TMMergeFlag(CU::isIBC(*pu.cu) ? 1 : 0));
#else
m_BinEncoder.encodeBin(pu.tmMergeFlag, Ctx::TMMergeFlag(CU::isIBC(*pu.cu) ? 1 : 0));
#endif
#else
#if JVET_X0049_ADAPT_DMVR
m_BinEncoder.encodeBin(pu.tmMergeFlag || pu.bmMergeFlag, Ctx::TMMergeFlag());
#else
m_BinEncoder.encodeBin(pu.tmMergeFlag, Ctx::TMMergeFlag());
#endif
#endif
#if JVET_X0049_ADAPT_DMVR
DTRACE(g_trace_ctx, D_SYNTAX, "tm_merge_flag() tm_merge_flag || bm_merge_flag=%d\n", pu.tmMergeFlag || pu.bmMergeFlag);
#else
DTRACE(g_trace_ctx, D_SYNTAX, "tm_merge_flag() tm_merge_flag=%d\n", pu.tmMergeFlag ? 1 : 0);
#endif
}
#endif
#if JVET_AC0112_IBC_CIIP
void CABACWriter::ibcCiipFlag(const PredictionUnit& pu)
{
if (!pu.cs->sps->getUseIbcCiip() || (pu.lx() == 0 && pu.ly() == 0))
{
return;
}
if (pu.lwidth() * pu.lheight() < 32 || pu.lwidth() > 32 || pu.lheight() > 32)
{
return;
}
#if JVET_AE0169_BIPREDICTIVE_IBC
if (pu.interDir == 3)
{
return;
}
#endif
if (pu.mergeFlag)
{
if (pu.cu->skip)
{
return;
}
m_BinEncoder.encodeBin(pu.ibcCiipFlag, Ctx::IbcCiipFlag(0));
}
else
{
#if JVET_AA0070_RRIBC
if (pu.cu->rribcFlipType)
{
return;
}
#endif
#if JVET_AC0112_IBC_LIC
if (pu.cu->ibcLicFlag)
{
return;
}
#endif
if (pu.cs->slice->getSliceType() != I_SLICE)
{
return;
}
m_BinEncoder.encodeBin(pu.ibcCiipFlag, Ctx::IbcCiipFlag(1));
}
DTRACE(g_trace_ctx, D_SYNTAX, "ibc_ciip_flag() ibc_ciip_flag=%d\n", pu.ibcCiipFlag);
}
void CABACWriter::ibcCiipIntraIdx(const PredictionUnit& pu)
{
m_BinEncoder.encodeBin( pu.ibcCiipIntraIdx > 0, Ctx::IbcCiipIntraIdx() );
DTRACE(g_trace_ctx, D_SYNTAX, "ibc_ciip_intra_idx() ibc_ciip_intra_idx=%d\n", pu.ibcCiipIntraIdx);
}
#endif
#if JVET_AC0112_IBC_GPM
void CABACWriter::ibcGpmFlag(const PredictionUnit& pu)
{
if (!pu.cs->sps->getUseIbcGpm() || (pu.lx() == 0 && pu.ly() == 0))
{
return;
}
if (pu.lwidth() < 8 || pu.lheight() < 8 || pu.lwidth() > 32 || pu.lheight() > 32)
{
return;
}
m_BinEncoder.encodeBin(pu.ibcGpmFlag, Ctx::IbcGpmFlag());
DTRACE(g_trace_ctx, D_SYNTAX, "ibc_gpm_flag() ibc_gpm_flag=%d\n", pu.ibcGpmFlag);
}
void CABACWriter::ibcGpmMergeIdx(const PredictionUnit& pu)
{
uint8_t splitDir = pu.ibcGpmSplitDir;
uint8_t candIdx0 = pu.ibcGpmMergeIdx0;
uint8_t candIdx1 = pu.ibcGpmMergeIdx1;
uint8_t splitDirIdx = 0;
if (g_geoParams[splitDir][0] % 8 == 0)
{
m_BinEncoder.encodeBin( 1, Ctx::IbcGpmSplitDirSetFlag() );
splitDirIdx = g_ibcGpmFirstSetSplitDirToIdx[splitDir];
m_BinEncoder.encodeBinsEP(splitDirIdx, 3);
}
else
{
m_BinEncoder.encodeBin( 0, Ctx::IbcGpmSplitDirSetFlag() );
uint8_t prefix = 0;
for (uint8_t i = 0; i < splitDir; i++)
{
if (!g_ibcGpmSecondSetSplitDir[i])
{
prefix++;
}
}
splitDirIdx = splitDir - prefix;
xWriteTruncBinCode(splitDirIdx, IBC_GPM_MAX_SPLIT_DIR_SECOND_SET_NUM);
}
bool isIntra0 = (pu.ibcGpmMergeIdx0 >= IBC_GPM_MAX_NUM_UNI_CANDS);
bool isIntra1 = (pu.ibcGpmMergeIdx1 >= IBC_GPM_MAX_NUM_UNI_CANDS);
m_BinEncoder.encodeBin( isIntra0 ? 1 : 0, Ctx::IbcGpmIntraFlag() );
#if JVET_AE0169_GPM_IBC_IBC
if (!isIntra0 && pu.cs->sps->getMaxNumIBCMergeCand() > 1)
{
m_BinEncoder.encodeBin(isIntra1 ? 1 : 0, Ctx::IbcGpmIntraFlag(1));
}
#endif
const int maxNumIbcGpmCand = pu.cs->sps->getMaxNumIBCMergeCand();
int numCandminus2 = maxNumIbcGpmCand - 2;
if (isIntra0)
{
unary_max_eqprob(candIdx0 - IBC_GPM_MAX_NUM_UNI_CANDS, IBC_GPM_MAX_NUM_INTRA_CANDS-1);
}
else if (numCandminus2 >= 0)
{
m_BinEncoder.encodeBin(candIdx0 == 0 ? 0 : 1, Ctx::MergeIdx());
if (candIdx0 > 0)
{
unary_max_eqprob(candIdx0 - 1, numCandminus2);
}
}
if (isIntra1)
{
unary_max_eqprob(candIdx1 - IBC_GPM_MAX_NUM_UNI_CANDS, IBC_GPM_MAX_NUM_INTRA_CANDS-1);
}
#if JVET_AE0169_GPM_IBC_IBC
else
{
if (isIntra0)
{
if (numCandminus2 >= 0)
{
m_BinEncoder.encodeBin(candIdx1 == 0 ? 0 : 1, Ctx::MergeIdx());
if (candIdx1 > 0)
{
unary_max_eqprob(candIdx1 - 1, numCandminus2);
}
}
}
else
{
candIdx1 -= candIdx1 < candIdx0 ? 0 : 1;
if (numCandminus2 > 0)
{
m_BinEncoder.encodeBin(candIdx1 == 0 ? 0 : 1, Ctx::MergeIdx());
if (candIdx1 > 0)
{
unary_max_eqprob(candIdx1 - 1, numCandminus2 - 1);
}
}
}
}
#else
else if (numCandminus2 >= 0)
{
m_BinEncoder.encodeBin(candIdx1 == 0 ? 0 : 1, Ctx::MergeIdx());
if (candIdx1 > 0)
{
unary_max_eqprob(candIdx1 - 1, numCandminus2);
}
}
#endif
DTRACE(g_trace_ctx, D_SYNTAX, "ibc_gpm_merge_idx() ibc_gpm_splt_dir=%d merge_idx0=%d merge_idx1=%d\n", pu.ibcGpmSplitDir, pu.ibcGpmMergeIdx0, pu.ibcGpmMergeIdx1);
}
void CABACWriter::ibcGpmAdaptBlendIdx(const int idx)
{
if (IBC_GPM_NUM_BLENDING == 1)
{
return;
}
if (idx == 0)
{
m_BinEncoder.encodeBin(1, Ctx::IbcGpmBldIdx(0));
}
else
{
m_BinEncoder.encodeBin(0, Ctx::IbcGpmBldIdx(0));
if (idx == 2 || idx == 1)
{
m_BinEncoder.encodeBin(1, Ctx::IbcGpmBldIdx(1));
m_BinEncoder.encodeBin(idx == 2, Ctx::IbcGpmBldIdx(2));
}
else
{
m_BinEncoder.encodeBin(0, Ctx::IbcGpmBldIdx(1));
m_BinEncoder.encodeBin(idx == 3, Ctx::IbcGpmBldIdx(3));
}
}
DTRACE(g_trace_ctx, D_SYNTAX, "ibc_gpm_adapt_blend_idx() ibc_gpm_bld_idx=%d\n", idx);
}
#endif
#if JVET_AC0112_IBC_LIC
void CABACWriter::cuIbcLicFlag(const CodingUnit& cu)
{
#if JVET_AE0159_FIBC
if (!(cu.cs->sps->getUseIbcLic() || cu.cs->sps->getUseIbcFilter() ) || !CU::isIBC(cu) || cu.firstPU->mergeFlag)
#else
if (!cu.cs->sps->getUseIbcLic() || !CU::isIBC(cu) || cu.firstPU->mergeFlag)
#endif
{
return;
}
#if JVET_AA0070_RRIBC
if (cu.rribcFlipType > 0)
{
return;
}
#endif
#if JVET_AE0159_FIBC || JVET_AE0078_IBC_LIC_EXTENSION
if (cu.lwidth() * cu.lheight() < 32 )
#else
if (cu.lwidth() * cu.lheight() < 32 || cu.lwidth() * cu.lheight() > 256)
#endif
{
return;
}
#if JVET_AE0159_FIBC
if (cu.ibcFilterFlag)
{
CHECK(!cu.ibcLicFlag, "LIC flag has to be 1 when FIBC is 1");
}
if (cu.lx() < FIBC_TEMPLATE_SIZE && cu.ly() < FIBC_TEMPLATE_SIZE)
{
CHECK(cu.ibcFilterFlag, "FIBC has to be 0 when not enough template");
}
if ((cu.lx() >= FIBC_TEMPLATE_SIZE || cu.ly() >= FIBC_TEMPLATE_SIZE) && (cu.cs->slice->getSliceType() == I_SLICE) && cu.cs->sps->getUseIbcFilter() )
{
unsigned ctxIdx = 1 + DeriveCtx::ctxIbcFilterFlag(cu);
m_BinEncoder.encodeBin(cu.ibcFilterFlag ? 1 : 0, Ctx::IbcLicFlag(ctxIdx));
DTRACE(g_trace_ctx, D_SYNTAX, "cu_ibc_lic_flag() filter_flag=%d\n", cu.ibcFilterFlag);
}
#if JVET_AE0078_IBC_LIC_EXTENSION
if (!cu.ibcFilterFlag && cu.cs->sps->getUseIbcLic())
#else
if (!cu.ibcFilterFlag && cu.cs->sps->getUseIbcLic() && (cu.lwidth() * cu.lheight() <= 256))
#endif
{
m_BinEncoder.encodeBin(cu.ibcLicFlag ? 1 : 0, Ctx::IbcLicFlag(0));
DTRACE(g_trace_ctx, D_SYNTAX, "cu_ibc_lic_flag() lic_flag=%d\n", cu.ibcLicFlag);
#if JVET_AE0078_IBC_LIC_EXTENSION
if (cu.ibcLicFlag)
{
const int bin1 = (cu.ibcLicIdx == IBC_LIC_IDX) || (cu.ibcLicIdx == IBC_LIC_IDX_M) ? 0 : 1;
const int bin2 = (cu.ibcLicIdx == IBC_LIC_IDX) || (cu.ibcLicIdx == IBC_LIC_IDX_T) ? 0 : 1;
m_BinEncoder.encodeBin(bin1, Ctx::IbcLicIndex(0));
m_BinEncoder.encodeBin(bin2, Ctx::IbcLicIndex(1));
DTRACE(g_trace_ctx, D_SYNTAX, "cu_ibc_lic_flag() lic_idx=%d\n", cu.ibcLicIdx);
}
#endif
}
#else
m_BinEncoder.encodeBin(cu.ibcLicFlag ? 1 : 0, Ctx::IbcLicFlag());
DTRACE(g_trace_ctx, D_SYNTAX, "cu_ibc_lic_flag() lic_flag=%d\n", cu.ibcLicFlag);
#if JVET_AE0078_IBC_LIC_EXTENSION
if (cu.ibcLicFlag)
{
const int bin1 = (cu.ibcLicIdx == IBC_LIC_IDX) || (cu.ibcLicIdx == IBC_LIC_IDX_M) ? 0 : 1;
const int bin2 = (cu.ibcLicIdx == IBC_LIC_IDX) || (cu.ibcLicIdx == IBC_LIC_IDX_T) ? 0 : 1;
m_BinEncoder.encodeBin(bin1, Ctx::IbcLicIndex(0));
m_BinEncoder.encodeBin(bin2, Ctx::IbcLicIndex(1));
DTRACE(g_trace_ctx, D_SYNTAX, "cu_ibc_lic_flag() lic_idx=%d\n", cu.ibcLicIdx);
}
#endif
#endif
}
#endif
#if JVET_X0049_ADAPT_DMVR
void CABACWriter::bm_merge_flag(const PredictionUnit& pu)
{
if (!PU::isBMMergeFlagCoded(pu))
{
return;
}
unsigned ctxId = DeriveCtx::CtxBMMrgFlag(*pu.cu);
m_BinEncoder.encodeBin(pu.bmMergeFlag, Ctx::BMMergeFlag(ctxId));
if (pu.bmMergeFlag)
{
CHECK(pu.bmDir != 1 && pu.bmDir != 2, "pu.bmDir != 1 && pu.bmDir != 2");
m_BinEncoder.encodeBin(pu.bmDir >> 1, Ctx::BMMergeFlag(3));
}
DTRACE(g_trace_ctx, D_SYNTAX, "bm_merge_flag() bm_merge_flag=%d, bmDir = %d\n", pu.bmMergeFlag ? 1 : 0, pu.bmDir);
}
#endif
#if JVET_AD0182_AFFINE_DMVR_PLUS_EXTENSIONS
void CABACWriter::affBmFlag(const PredictionUnit& pu)
{
if (!PU::isAffBMMergeFlagCoded(pu))
{
CHECK(pu.affBMMergeFlag != false, "");
return;
}
m_BinEncoder.encodeBin(pu.affBMMergeFlag, Ctx::affBMFlag(0));
DTRACE(g_trace_ctx, D_SYNTAX, "aff_bm_flag() aff_bm_flag=%d\n", pu.affBMMergeFlag);
if (pu.affBMMergeFlag)
{
CHECK(pu.affBMDir != 1 && pu.affBMDir != 2, "pu.affBMDir != 1 && pu.affBMDir != 2");
m_BinEncoder.encodeBin(pu.affBMDir >> 1, Ctx::affBMFlag(1));
DTRACE(g_trace_ctx, D_SYNTAX, "aff_bm_flag() aff_bm_dir=%d\n", pu.affBMDir);
}
}
#endif
void CABACWriter::merge_flag( const PredictionUnit& pu )
{
#if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
if( CU::isIBC( *pu.cu ) && !pu.cu->slice->getSPS()->getUseIbcMerge() )
{
CHECK( pu.mergeFlag, "IBC merge flag shall be disabled" );
return;
}
#endif
m_BinEncoder.encodeBin( pu.mergeFlag, Ctx::MergeFlag() );
DTRACE( g_trace_ctx, D_SYNTAX, "merge_flag() merge=%d pos=(%d,%d) size=%dx%d\n", pu.mergeFlag ? 1 : 0, pu.lumaPos().x, pu.lumaPos().y, pu.lumaSize().width, pu.lumaSize().height );
}
void CABACWriter::merge_data(const PredictionUnit& pu)
{
if (CU::isIBC(*pu.cu))
{
#if JVET_AE0169_BIPREDICTIVE_IBC
ibcBiPredictionFlag(pu);
#endif
#if JVET_AA0061_IBC_MBVD
ibcMbvdData(pu);
#endif
#if JVET_Z0084_IBC_TM && IBC_TM_MRG
#if JVET_AA0061_IBC_MBVD
if (!pu.ibcMbvdMergeFlag)
{
#endif
tm_merge_flag(pu);
#if JVET_AA0061_IBC_MBVD
}
#endif
#endif
#if JVET_AC0112_IBC_CIIP
#if JVET_AE0169_BIPREDICTIVE_IBC
if (pu.interDir != 3)
#endif
ibcCiipFlag(pu);
if (pu.ibcCiipFlag)
{
ibcCiipIntraIdx(pu);
}
#endif
#if JVET_AC0112_IBC_GPM
#if JVET_AC0112_IBC_CIIP && JVET_AA0061_IBC_MBVD
#if JVET_AE0169_BIPREDICTIVE_IBC
if (!pu.ibcMbvdMergeFlag && !pu.ibcCiipFlag && pu.interDir != 3)
#else
if (!pu.ibcMbvdMergeFlag && !pu.ibcCiipFlag)
#endif
#else
#if JVET_AA0061_IBC_MBVD
if (!pu.ibcMbvdMergeFlag)
#else
#if JVET_AC0112_IBC_CIIP
if (!pu.ibcCiipFlag)
#endif
#endif
#endif
{
ibcGpmFlag(pu);
if (pu.ibcGpmFlag)
{
ibcGpmMergeIdx(pu);
#if JVET_AE0169_GPM_IBC_IBC
if (pu.cs->slice->getSliceType() == I_SLICE)
{
ibcGpmAdaptBlendIdx(pu.ibcGpmBldIdx);
}
#else
ibcGpmAdaptBlendIdx(pu.ibcGpmBldIdx);
#endif
}
}
#endif
merge_idx(pu);
#if JVET_AE0169_BIPREDICTIVE_IBC
if (pu.interDir == 3 && !pu.ibcMbvdMergeFlag)
{
ibcMergeIdx1(pu);
}
#endif
return;
}
#if JVET_AG0135_AFFINE_CIIP
if (pu.ciipAffine)
{
pu.cu->affine = false;
}
#endif
subblock_merge_flag(*pu.cu);
if (pu.cu->affine)
{
#if AFFINE_MMVD
affine_mmvd_data(pu);
#endif
#if JVET_AD0182_AFFINE_DMVR_PLUS_EXTENSIONS
if (!pu.afMmvdFlag)
{
affBmFlag(pu);
}
#endif
#if JVET_AG0276_LIC_FLAG_SIGNALING
if (PU::hasOppositeLICFlag(pu) && !pu.afMmvdFlag && !pu.affBMMergeFlag && pu.cs->sps->getUseAffMergeOppositeLic())
{
m_BinEncoder.encodeBin(pu.affineOppositeLic, Ctx::AffineFlagOppositeLic(0));
}
#endif
merge_idx(pu);
return;
}
#if JVET_AG0135_AFFINE_CIIP
if (pu.ciipAffine)
{
pu.cu->affine = true;
}
#endif
#if CIIP_RM_BLOCK_SIZE_CONSTRAINTS
#if CTU_256
const int maxSize = std::min<int>( MAX_TB_SIZEY, MAX_INTRA_SIZE );
const bool ciipAvailable = pu.cs->sps->getUseCiip() && !pu.cu->skip && pu.cu->lwidth() * pu.cu->lheight() >= 32 && pu.cu->lwidth() <= maxSize && pu.cu->lheight() <= maxSize;
#else
const bool ciipAvailable = pu.cs->sps->getUseCiip() && !pu.cu->skip && pu.cu->lwidth() * pu.cu->lheight() >= 32;
#endif
#else
const bool ciipAvailable = pu.cs->sps->getUseCiip() && !pu.cu->skip && pu.cu->lwidth() < MAX_CU_SIZE && pu.cu->lheight() < MAX_CU_SIZE && pu.cu->lwidth() * pu.cu->lheight() >= 64;
#endif
#if JVET_Y0065_GPM_INTRA
const bool geoAvailable = pu.cu->cs->slice->getSPS()->getUseGeo() && !pu.cu->cs->slice->isIntra() &&
pu.cs->sps->getMaxNumGeoCand() > 0
#else
const bool geoAvailable = pu.cu->cs->slice->getSPS()->getUseGeo() && pu.cu->cs->slice->isInterB() &&
pu.cs->sps->getMaxNumGeoCand() > 1
#endif
&& pu.cu->lwidth() >= GEO_MIN_CU_SIZE && pu.cu->lheight() >= GEO_MIN_CU_SIZE
&& pu.cu->lwidth() <= GEO_MAX_CU_SIZE && pu.cu->lheight() <= GEO_MAX_CU_SIZE
&& pu.cu->lwidth() < 8 * pu.cu->lheight() && pu.cu->lheight() < 8 * pu.cu->lwidth();
if (geoAvailable || ciipAvailable)
{
m_BinEncoder.encodeBin(pu.regularMergeFlag, Ctx::RegularMergeFlag(pu.cu->skip ? 0 : 1));
DTRACE(g_trace_ctx, D_SYNTAX, "merge_data() regular_merge=%d pos=(%d,%d) size=%dx%d\n", pu.regularMergeFlag ? 1 : 0, pu.lumaPos().x, pu.lumaPos().y, pu.lumaSize().width, pu.lumaSize().height);
}
if (pu.regularMergeFlag)
{
#if TM_MRG
tm_merge_flag(pu);
#endif
#if JVET_X0049_ADAPT_DMVR
#if TM_MRG
if ((pu.tmMergeFlag || pu.bmMergeFlag)
#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
|| !pu.cs->slice->getSPS()->getUseTMMrgMode()
#endif
)
#endif
{
bm_merge_flag(pu);
}
#endif
if (pu.cs->sps->getUseMMVD()
#if TM_MRG
&& !pu.tmMergeFlag
#endif
#if JVET_X0049_ADAPT_DMVR
&& !pu.bmMergeFlag
#endif
)
{
#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
unsigned ctxId =
#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
!pu.cs->sps->getUseTMMMVD() ||
#endif
pu.cu->skip ? 0 : 1;
m_BinEncoder.encodeBin(pu.mmvdMergeFlag, Ctx::MmvdFlag(ctxId));
#else
m_BinEncoder.encodeBin(pu.mmvdMergeFlag, Ctx::MmvdFlag(0));
#endif
DTRACE(g_trace_ctx, D_SYNTAX, "merge_data() mmvd_merge=%d pos=(%d,%d) size=%dx%d\n", pu.mmvdMergeFlag ? 1 : 0, pu.lumaPos().x, pu.lumaPos().y, pu.lumaSize().width, pu.lumaSize().height);
}
if (pu.mmvdMergeFlag || pu.cu->mmvdSkip)
{
mmvd_merge_idx(pu);
}
else
{
#if JVET_AG0276_LIC_FLAG_SIGNALING
if (pu.regularMergeFlag && PU::hasOppositeLICFlag(pu) && !pu.bmMergeFlag)
{
if (pu.tmMergeFlag && pu.cs->sps->getUseTMMergeOppositeLic())
{
m_BinEncoder.encodeBin(pu.tmMergeFlagOppositeLic, Ctx::TmMergeFlagOppositeLic(0));
}
else if (pu.cs->sps->getUseMergeOppositeLic())
{
m_BinEncoder.encodeBin(pu.mergeOppositeLic, Ctx::MergeFlagOppositeLic(0));
}
}
#endif
merge_idx(pu);
}
}
else
{
if (geoAvailable && ciipAvailable)
{
Ciip_flag(pu);
}
#if CIIP_PDPC
if (pu.ciipFlag && !geoAvailable && ciipAvailable)
{
#if JVET_X0141_CIIP_TIMD_TM && TM_MRG
#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
#if JVET_AG0135_AFFINE_CIIP
ciipAffineFlag(pu);
if (!pu.ciipAffine)
{
#endif
tm_merge_flag(pu);
#if JVET_AG0135_AFFINE_CIIP
}
#endif
#else
if (pu.cs->slice->getSPS()->getUseCiipTmMrg())
{
m_BinEncoder.encodeBin(pu.tmMergeFlag, Ctx::CiipTMMergeFlag());
DTRACE(g_trace_ctx, D_SYNTAX, "merge_data() ciip_tm_merge_flag=%d\n", pu.tmMergeFlag);
}
#endif
#endif
#if JVET_AG0135_AFFINE_CIIP
if (!pu.ciipAffine)
{
#endif
m_BinEncoder.encodeBin(pu.ciipPDPC, Ctx::CiipFlag(1));
#if JVET_AG0135_AFFINE_CIIP
}
#endif
DTRACE(g_trace_ctx, D_SYNTAX, "merge_data() ciip_pdpc_flag=%d\n", pu.ciipPDPC);
}
#else
#if JVET_X0141_CIIP_TIMD_TM && TM_MRG
if (pu.ciipFlag && !geoAvailable && ciipAvailable && pu.cs->slice->getSPS()->getUseCiipTmMrg())
{
#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
tm_merge_flag(pu);
#else
m_BinEncoder.encodeBin(pu.tmMergeFlag, Ctx::CiipTMMergeFlag());
#endif
}
#endif
#endif
merge_idx(pu);
}
}
void CABACWriter::imv_mode( const CodingUnit& cu )
{
const SPS *sps = cu.cs->sps;
if( !sps->getAMVREnabledFlag() )
{
#if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
if (CU::isIBC(cu) && !cu.firstPU->mergeFlag)
{
CHECK(cu.imv != 1, "Error on default IMV flag of IBC AMVP mode")
}
#endif
return;
}
if ( cu.affine )
{
return;
}
#if JVET_AG0098_AMVP_WITH_SBTMVP
if (cu.firstPU->amvpSbTmvpFlag && !cu.cs->slice->getAmvpSbTmvpAmvrEnabledFlag())
{
return;
}
#endif
#if JVET_X0083_BM_AMVP_MERGE_MODE
auto &pu = *cu.firstPU;
#if JVET_AE0169_BIPREDICTIVE_IBC
if (!CU::isIBC(cu) && (pu.amvpMergeModeFlag[0] || pu.amvpMergeModeFlag[1]))
#else
if (pu.amvpMergeModeFlag[0] || pu.amvpMergeModeFlag[1])
#endif
{
return;
}
#endif
#if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
bool useIBCFrac = CU::isIBC(cu) && !cu.firstPU->mergeFlag && cu.cs->sps->getIBCFracFlag()
#if JVET_AA0070_RRIBC
&& (cu.rribcFlipType == 0)
#endif
#if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
&& (cu.bvOneZeroComp == 0)
#endif
;
#endif
bool bNonZeroMvd = CU::hasSubCUNonZeroMVd( cu );
if( !bNonZeroMvd )
{
#if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
if (CU::isIBC(cu) && !cu.firstPU->mergeFlag)
{
CHECK(cu.imv != (useIBCFrac ? IBC_SUBPEL_AMVR_MODE_FOR_ZERO_MVD : 1), "Error on default IMV flag of IBC AMVP mode")
}
#endif
return;
}
#if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
const CtxSet& imvCtx = CU::isIBC(cu) && pu.cs->sps->getIBCFracFlag() ? Ctx::ImvFlagIBC : Ctx::ImvFlag;
if (CU::isIBC(cu) && pu.cs->sps->getIBCFracFlag())
{
CHECK(cu.imv == IMV_HPEL, "IBC does not support IMV_HPEL");
}
#endif
if (CU::isIBC(cu) == false
#if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
|| useIBCFrac
#endif
)
m_BinEncoder.encodeBin( (cu.imv > 0)
#if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
, imvCtx( 0 )
#else
, Ctx::ImvFlag( 0 )
#endif
);
DTRACE( g_trace_ctx, D_SYNTAX, "imv_mode() value=%d ctx=%d\n", (cu.imv > 0), 0 );
#if JVET_AG0098_AMVP_WITH_SBTMVP
if (cu.firstPU->amvpSbTmvpFlag)
{
return;
}
#endif
if( sps->getAMVREnabledFlag() && cu.imv > 0 )
{
if (!CU::isIBC(cu))
{
m_BinEncoder.encodeBin(cu.imv < IMV_HPEL
#if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
, imvCtx(4)
#else
, Ctx::ImvFlag(4)
#endif
);
DTRACE(g_trace_ctx, D_SYNTAX, "imv_mode() value=%d ctx=%d\n", cu.imv < 3, 4);
}
if (cu.imv < IMV_HPEL)
{
m_BinEncoder.encodeBin( (cu.imv > 1)
#if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
, imvCtx( 1 )
#else
, Ctx::ImvFlag( 1 )
#endif
);
DTRACE( g_trace_ctx, D_SYNTAX, "imv_mode() value=%d ctx=%d\n", (cu.imv > 1), 1 );
}
}
#if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
if (CU::isIBC(cu))
{
CHECK(pu.cs->sps->getIBCFracFlag() && cu.imv == IMV_HPEL, "IBC does not support IMV_HPEL");
CHECK(!useIBCFrac && (cu.imv == IMV_OFF || cu.imv == IMV_HPEL), "Fractiona IBC is not enabled to support fractional BVD coding");
}
#endif
DTRACE( g_trace_ctx, D_SYNTAX, "imv_mode() IMVFlag=%d\n", cu.imv );
}
void CABACWriter::affine_amvr_mode( const CodingUnit& cu )
{
const SPS* sps = cu.slice->getSPS();
if( !sps->getAffineAmvrEnabledFlag() || !cu.affine )
{
return;
}
if ( !CU::hasSubCUNonZeroAffineMVd( cu ) )
{
return;
}
m_BinEncoder.encodeBin( (cu.imv > 0), Ctx::ImvFlag( 2 ) );
DTRACE( g_trace_ctx, D_SYNTAX, "affine_amvr_mode() value=%d ctx=%d\n", (cu.imv > 0), 2 );
if( cu.imv > 0 )
{
m_BinEncoder.encodeBin( (cu.imv > 1), Ctx::ImvFlag( 3 ) );
DTRACE( g_trace_ctx, D_SYNTAX, "affine_amvr_mode() value=%d ctx=%d\n", (cu.imv > 1), 3 );
}
DTRACE( g_trace_ctx, D_SYNTAX, "affine_amvr_mode() IMVFlag=%d\n", cu.imv );
}
void CABACWriter::merge_idx( const PredictionUnit& pu )
{
if ( pu.cu->affine )
{
#if AFFINE_MMVD
if (pu.afMmvdFlag)
{
return;
}
#endif
#if JVET_AD0182_AFFINE_DMVR_PLUS_EXTENSIONS
if (pu.affBMMergeFlag)
{
return;
}
#endif
int numCandminus1 = int( pu.cs->picHeader->getMaxNumAffineMergeCand() ) - 1;
#if JVET_AG0276_LIC_FLAG_SIGNALING
if (pu.affineOppositeLic)
{
numCandminus1 = int(pu.cs->picHeader->getMaxNumAffineOppositeLicMergeCand()) - 1;
}
#endif
if ( numCandminus1 > 0 )
{
#if JVET_AA0128_AFFINE_MERGE_CTX_INC
unsigned int unaryIdx = 0;
for (; unaryIdx < numCandminus1; ++unaryIdx)
{
unsigned int symbol = pu.mergeIdx == unaryIdx ? 0 : 1;
m_BinEncoder.encodeBin(symbol, Ctx::AffMergeIdx((unaryIdx > 2 ? 2 : unaryIdx)));
if (symbol == 0)
{
break;
}
}
#else
if ( pu.mergeIdx == 0 )
{
m_BinEncoder.encodeBin( 0, Ctx::AffMergeIdx() );
DTRACE( g_trace_ctx, D_SYNTAX, "aff_merge_idx() aff_merge_idx=%d\n", pu.mergeIdx );
return;
}
else
{
m_BinEncoder.encodeBin( 1, Ctx::AffMergeIdx() );
for ( unsigned idx = 1; idx < numCandminus1; idx++ )
{
m_BinEncoder.encodeBinEP( pu.mergeIdx == idx ? 0 : 1 );
if ( pu.mergeIdx == idx )
{
break;
}
}
}
#endif
}
DTRACE( g_trace_ctx, D_SYNTAX, "aff_merge_idx() aff_merge_idx=%d\n", pu.mergeIdx );
}
else
{
if( pu.cu->geoFlag )
{
#if JVET_AG0112_REGRESSION_BASED_GPM_BLENDING
bool bUseOnlyOneVector1 = pu.cs->slice->isInterP() || pu.cs->sps->getMaxNumGeoCand() == 1;
CHECK(bUseOnlyOneVector1, "CABACWriter::merge_idx( bUseOnlyOneVector=1 ) failed.");
if ( CU::isGeoBlendAvailable(*pu.cu) )
{
m_BinEncoder.encodeBin( pu.cu->geoBlendFlag, Ctx::GeoBlendFlag() );
DTRACE( g_trace_ctx, D_SYNTAX, "geoBlendFlag() geoBlendFlag=%d\n", pu.cu->geoBlendFlag ? 1 : 0 );
}
else
{
CHECK(pu.cu->geoBlendFlag, "CABACWriter::merge_idx()\tgeoBlendFlag not available failed.")
}
if ( pu.cu->geoBlendFlag )
{
int candIdx0 = pu.geoMergeIdx0;
CHECK( candIdx0 >= pu.cs->sps->getMaxNumGeoBlendCand() , "geoBlend idx should be < sps->getMaxNumGeoCand()");
const int maxNumGeoCand = pu.cs->sps->getMaxNumGeoBlendCand() - 2;
m_BinEncoder.encodeBin( candIdx0 == 0 ? 0 : 1, Ctx::MergeIdx() );
if ( candIdx0 > 0 )
{
unary_max_eqprob( candIdx0 - 1, maxNumGeoCand );
}
DTRACE( g_trace_ctx, D_SYNTAX, "merge_idx() merge_idx=%d\n", pu.geoMergeIdx0 );
return;
}
#endif
#if JVET_AA0058_GPM_ADAPTIVE_BLENDING
#if JVET_AH0314_ADAPTIVE_GPM_BLENDING_IMPROV
int blkSizeSmall = pu.lwidth() < pu.lheight() ? pu.lwidth() : pu.lheight();
if (blkSizeSmall < GPM_BLENDING_SIZE_THRESHOLD)
{
geoAdaptiveBlendingIdx(pu, pu.geoBldIdx);
}
else
{
geoAdaptiveBlendingIdx(pu, pu.geoBldIdx - 1);
}
#else
geoAdaptiveBlendingIdx(pu.geoBldIdx);
#endif
#endif
#if JVET_W0097_GPM_MMVD_TM
#if JVET_Y0065_GPM_INTRA
#if JVET_AG0164_AFFINE_GPM
bool isIntra0 = (pu.geoMergeIdx0 >= GEO_MAX_ALL_INTER_UNI_CANDS);
bool isIntra1 = (pu.geoMergeIdx1 >= GEO_MAX_ALL_INTER_UNI_CANDS);
bool isAffGPMValid = PU::isAffineGPMValid(pu);
int affGPMFlagCtxOffset = 0;
affGPMFlagCtxOffset = PU::getAffGPMCtxOffset(pu);
#else
bool isIntra0 = (pu.geoMergeIdx0 >= GEO_MAX_NUM_UNI_CANDS);
bool isIntra1 = (pu.geoMergeIdx1 >= GEO_MAX_NUM_UNI_CANDS);
#endif
bool bUseOnlyOneVector = pu.cs->slice->isInterP() || pu.cs->sps->getMaxNumGeoCand() == 1;
#endif
#if JVET_AI0082_GPM_WITH_INTER_IBC
#if JVET_AG0164_AFFINE_GPM
bool isIbc0 = (pu.geoMergeIdx0 >= GEO_MAX_ALL_INTER_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS);
bool isIbc1 = (pu.geoMergeIdx1 >= GEO_MAX_ALL_INTER_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS);
#else
bool isIbc0 = (pu.geoMergeIdx0 >= GEO_MAX_NUM_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS);
bool isIbc1 = (pu.geoMergeIdx1 >= GEO_MAX_NUM_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS);
#endif
bool isGpmInterIbcEnabled = pu.cs->sps->getUseGeoInterIbc();
#endif
m_BinEncoder.encodeBin(pu.geoMMVDFlag0, Ctx::GeoMmvdFlag());
if (pu.geoMMVDFlag0)
{
geo_mmvd_idx(pu, REF_PIC_LIST_0);
}
#if JVET_AG0164_AFFINE_GPM
else
if (isAffGPMValid)
{
m_BinEncoder.encodeBin(pu.affineGPM[0], Ctx::AffineFlag(affGPMFlagCtxOffset));
}
CHECK(pu.geoMMVDFlag0 && pu.affineGPM[0], "Aff GPM does not support MMVD");
if (pu.affineGPM[0] || pu.geoMMVDFlag0)
{
CHECK(isIntra0, "Invalid isIntra0");
}
#endif
#if JVET_Y0065_GPM_INTRA
else
{
m_BinEncoder.encodeBin( isIntra0 ? 1 : 0, Ctx::GPMIntraFlag() );
#if JVET_AI0082_GPM_WITH_INTER_IBC
if (isIntra0 && isGpmInterIbcEnabled)
{
m_BinEncoder.encodeBin( isIbc0 ? 1 : 0, Ctx::GpmInterIbcFlag() );
}
#endif
}
if (!bUseOnlyOneVector || isIntra0)
{
#endif
m_BinEncoder.encodeBin(pu.geoMMVDFlag1, Ctx::GeoMmvdFlag());
if (pu.geoMMVDFlag1)
{
geo_mmvd_idx(pu, REF_PIC_LIST_1);
}
#if JVET_AG0164_AFFINE_GPM
else
if (isAffGPMValid)
{
m_BinEncoder.encodeBin(pu.affineGPM[1], Ctx::AffineFlag(affGPMFlagCtxOffset));
}
CHECK(pu.geoMMVDFlag1&& pu.affineGPM[1], "Aff GPM does not support MMVD");
if (pu.affineGPM[1] || pu.geoMMVDFlag1)
{
CHECK(isIntra1, "Invalid isIntra0");
}
#endif
#if JVET_Y0065_GPM_INTRA
else if (!isIntra0)
{
m_BinEncoder.encodeBin( isIntra1 ? 1 : 0, Ctx::GPMIntraFlag() );
#if JVET_AI0082_GPM_WITH_INTER_IBC
if (isIntra1 && isGpmInterIbcEnabled)
{
m_BinEncoder.encodeBin( isIbc1 ? 1 : 0, Ctx::GpmInterIbcFlag() );
}
#endif
}
}
else
{
CHECK( !isIntra1, "isIntra1 shall be true" );
}
CHECK( pu.gpmIntraFlag != (isIntra0 || isIntra1), "gpmIntraFlag shall be equal to (isIntra0 || isIntra1)" );
#if JVET_AI0082_GPM_WITH_INTER_IBC
CHECK( pu.gpmInterIbcFlag != (isIbc0 || isIbc1), "gpmInterIbcFlag shall be equal to (isIbc0 || isIbc1)" );
#endif
#endif
#if TM_MRG
if (!pu.geoMMVDFlag0 && !pu.geoMMVDFlag1)
{
#if JVET_Y0065_GPM_INTRA
if (!isIntra0 && !isIntra1)
#endif
#if JVET_AG0164_AFFINE_GPM
if( !pu.affineGPM[0] && !pu.affineGPM[1])
#endif
tm_merge_flag(pu);
if (pu.tmMergeFlag)
{
#if JVET_AG0164_AFFINE_GPM
CHECK(pu.affineGPM[0] || pu.affineGPM[1], "Affine GPM cannot be used with TM");
#endif
CHECK(!pu.geoTmFlag0 || !pu.geoTmFlag1, "both must be true");
CHECK(pu.geoMergeIdx0 == pu.geoMergeIdx1, "Incorrect geoMergeIdx0 and geoMergeIdx1");
geo_merge_idx(pu);
}
else
{
CHECK(pu.geoTmFlag0 || pu.geoTmFlag1, "both must be false");
#if JVET_Y0065_GPM_INTRA
if (isIntra0 || isIntra1)
{
geo_merge_idx1(pu);
}
else
#endif
geo_merge_idx(pu);
}
}
#else
if (!pu.geoMMVDFlag0 && !pu.geoMMVDFlag1)
{
#if JVET_Y0065_GPM_INTRA
if( isIntra0 || isIntra1 )
{
geo_merge_idx1( pu );
}
else
#endif
geo_merge_idx(pu);
}
#endif
else if (pu.geoMMVDFlag0 && pu.geoMMVDFlag1)
{
if (pu.geoMMVDIdx0 == pu.geoMMVDIdx1)
{
geo_merge_idx(pu);
}
else
{
geo_merge_idx1(pu);
}
}
else
{
geo_merge_idx1(pu);
}
#else
#if !JVET_Z0056_GPM_SPLIT_MODE_REORDERING
uint8_t splitDir = pu.geoSplitDir;
#endif
uint8_t candIdx0 = pu.geoMergeIdx0;
uint8_t candIdx1 = pu.geoMergeIdx1;
#if !JVET_Z0056_GPM_SPLIT_MODE_REORDERING
DTRACE( g_trace_ctx, D_SYNTAX, "merge_idx() geo_split_dir=%d\n", splitDir );
#endif
DTRACE( g_trace_ctx, D_SYNTAX, "merge_idx() geo_idx0=%d\n", candIdx0 );
DTRACE( g_trace_ctx, D_SYNTAX, "merge_idx() geo_idx1=%d\n", candIdx1 );
#if JVET_Z0056_GPM_SPLIT_MODE_REORDERING
geoModeIdx(pu);
#else
xWriteTruncBinCode(splitDir, GEO_NUM_PARTITION_MODE);
#endif
candIdx1 -= candIdx1 < candIdx0 ? 0 : 1;
const int maxNumGeoCand = pu.cs->sps->getMaxNumGeoCand();
CHECK(maxNumGeoCand < 2, "Incorrect max number of geo candidates");
CHECK(candIdx0 >= maxNumGeoCand, "Incorrect candIdx0");
CHECK(candIdx1 >= maxNumGeoCand, "Incorrect candIdx1");
int numCandminus2 = maxNumGeoCand - 2;
m_BinEncoder.encodeBin( candIdx0 == 0 ? 0 : 1, Ctx::MergeIdx() );
if( candIdx0 > 0 )
{
unary_max_eqprob(candIdx0 - 1, numCandminus2);
}
if (numCandminus2 > 0)
{
m_BinEncoder.encodeBin(candIdx1 == 0 ? 0 : 1, Ctx::MergeIdx());
if (candIdx1 > 0)
{
unary_max_eqprob(candIdx1 - 1, numCandminus2 - 1);
}
}
#endif
return;
}
int numCandminus1;
#if JVET_X0049_ADAPT_DMVR
#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
uint16_t mergeIdx = pu.mergeIdx;
#else
uint8_t mergeIdx = pu.mergeIdx;
#endif
#endif
if (pu.cu->predMode == MODE_IBC)
{
#if JVET_AA0061_IBC_MBVD
#if JVET_AE0169_BIPREDICTIVE_IBC
if (pu.ibcMbvdMergeFlag && (pu.interDir == 1 || pu.ibcMergeIdx1 >= IBC_MRG_MAX_NUM_CANDS))
#else
if (pu.ibcMbvdMergeFlag)
#endif
{
return;
}
#endif
#if JVET_AC0112_IBC_GPM
if (pu.ibcGpmFlag)
{
return;
}
#endif
numCandminus1 = int(pu.cs->sps->getMaxNumIBCMergeCand()) - 1;
#if JVET_AE0169_BIPREDICTIVE_IBC
if (pu.interDir == 3 && pu.mergeFlag)
{
if (pu.ibcMbvdMergeFlag)
{
numCandminus1 = std::min(numCandminus1, IBC_MBVD_BASE_NUM - 1);
mergeIdx = pu.ibcMergeIdx1;
}
else
{
numCandminus1--;
}
}
#endif
}
#if TM_MRG
else if (pu.tmMergeFlag)
#if JVET_X0141_CIIP_TIMD_TM
{
if (pu.ciipFlag)
{
numCandminus1 = int(pu.cs->sps->getMaxNumCiipTMMergeCand()) - 1;
}
else
{
numCandminus1 = int(pu.cs->sps->getMaxNumTMMergeCand()) - 1;
}
}
#else
numCandminus1 = int(pu.cs->sps->getMaxNumTMMergeCand()) - 1;
#endif
#endif
#if JVET_X0049_ADAPT_DMVR
else if (pu.bmMergeFlag)
{
numCandminus1 = int(pu.cs->sps->getMaxNumBMMergeCand()) - 1;
if (pu.bmDir == 2)
{
mergeIdx -= BM_MRG_MAX_NUM_CANDS;
}
}
#endif
else
numCandminus1 = int(pu.cs->sps->getMaxNumMergeCand()) - 1;
#if JVET_AG0276_LIC_FLAG_SIGNALING
if (pu.mergeOppositeLic)
{
numCandminus1 = int(pu.cs->sps->getMaxNumOppositeLicMergeCand()) - 1;
}
else if (pu.tmMergeFlagOppositeLic)
{
numCandminus1 = int(pu.cs->sps->getMaxNumTMOppositeLicMergeCand()) - 1;
}
#endif
if( numCandminus1 > 0 )
{
#if TM_MRG || (JVET_Z0084_IBC_TM && IBC_TM_MRG)
const CtxSet mrgIdxCtxSet = pu.tmMergeFlag ? Ctx::TmMergeIdx : Ctx::MergeIdx;
#endif
#if NON_ADJACENT_MRG_CAND
unsigned int uiUnaryIdx = 0;
for (; uiUnaryIdx < numCandminus1; ++uiUnaryIdx)
{
#if JVET_X0049_ADAPT_DMVR
unsigned int uiSymbol = mergeIdx == uiUnaryIdx ? 0 : 1;
#else
unsigned int uiSymbol = pu.mergeIdx == uiUnaryIdx ? 0 : 1;
#endif
#if TM_MRG || (JVET_Z0084_IBC_TM && IBC_TM_MRG)
m_BinEncoder.encodeBin(uiSymbol, mrgIdxCtxSet((uiUnaryIdx > LAST_MERGE_IDX_CABAC - 1 ? LAST_MERGE_IDX_CABAC - 1 : uiUnaryIdx)));
#else
m_BinEncoder.encodeBin(uiSymbol, Ctx::MergeIdx((uiUnaryIdx > LAST_MERGE_IDX_CABAC - 1 ? LAST_MERGE_IDX_CABAC - 1 : uiUnaryIdx)));
#endif
if (uiSymbol == 0)
{
break;
}
}
#else
#if JVET_X0049_ADAPT_DMVR
if (mergeIdx == 0)
#else
if (pu.mergeIdx == 0)
#endif
{
#if TM_MRG || (JVET_Z0084_IBC_TM && IBC_TM_MRG)
m_BinEncoder.encodeBin( 0, mrgIdxCtxSet() );
#else
m_BinEncoder.encodeBin( 0, Ctx::MergeIdx() );
#endif
DTRACE( g_trace_ctx, D_SYNTAX, "merge_idx() merge_idx=%d\n", pu.mergeIdx );
return;
}
else
{
#if TM_MRG || (JVET_Z0084_IBC_TM && IBC_TM_MRG)
m_BinEncoder.encodeBin( 1, mrgIdxCtxSet() );
#else
m_BinEncoder.encodeBin( 1, Ctx::MergeIdx() );
#endif
for( unsigned idx = 1; idx < numCandminus1; idx++ )
{
#if JVET_X0049_ADAPT_DMVR
m_BinEncoder.encodeBinEP(mergeIdx == idx ? 0 : 1);
if (mergeIdx == idx)
#else
m_BinEncoder.encodeBinEP( pu.mergeIdx == idx ? 0 : 1 );
if( pu.mergeIdx == idx )
#endif
{
break;
}
}
}
#endif
}
#if JVET_X0049_ADAPT_DMVR
#if JVET_AE0169_BIPREDICTIVE_IBC
if (pu.ibcMbvdMergeFlag)
DTRACE( g_trace_ctx, D_SYNTAX, "merge_idx() ibc_merge_idx1=%d\n", mergeIdx );
else
#endif
DTRACE( g_trace_ctx, D_SYNTAX, "merge_idx() merge_idx=%d\n", mergeIdx );
#else
DTRACE( g_trace_ctx, D_SYNTAX, "merge_idx() merge_idx=%d\n", pu.mergeIdx );
#endif
}
}
void CABACWriter::mmvd_merge_idx(const PredictionUnit& pu)
{
#if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
if(pu.cs->sps->getUseTMMMVD())
{
#endif
int mvpIdx = pu.mmvdMergeIdx;
int var0;
var0 = mvpIdx / MMVD_MAX_REFINE_NUM;
mvpIdx -= var0 * MMVD_MAX_REFINE_NUM;
#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
int numCandMinus1Base = std::min<int>(MMVD_BASE_MV_NUM, pu.cs->sps->getMaxNumMergeCand()) - 1;
if (numCandMinus1Base > 0)
{
// to support more base candidates
m_BinEncoder.encodeBin((var0 == 0 ? 0 : 1), Ctx::MmvdMergeIdx(0));
if (var0 > 0)
{
for (unsigned idx = 1; idx < numCandMinus1Base; idx++)
{
m_BinEncoder.encodeBin((var0 == idx ? 0 : 1), Ctx::MmvdMergeIdx(idx));
if (var0 == idx)
{
break;
}
}
}
}
#else
if (pu.cs->sps->getMaxNumMergeCand() > 1)
{
static_assert(MMVD_BASE_MV_NUM == 2, "");
assert(var0 < 2);
m_BinEncoder.encodeBin(var0, Ctx::MmvdMergeIdx());
}
#endif
DTRACE(g_trace_ctx, D_SYNTAX, "mmvd_merge_idx() base_mvp_idx=%d\n", var0);
unsigned int ricePar = 1;
#if JVET_AA0093_ENHANCED_MMVD_EXTENSION
int numStepCandMinus1 = ((MMVD_MAX_REFINE_NUM >> ricePar) >> MMVD_SIZE_SHIFT)/MMVD_BI_DIR - 1;
#else
int numStepCandMinus1 = ((MMVD_MAX_REFINE_NUM >> ricePar) >> MMVD_SIZE_SHIFT) - 1;
#endif
if(ricePar > 0)
{
m_BinEncoder.encodeBinsEP(mvpIdx % (1 << ricePar), ricePar);
}
mvpIdx >>= ricePar;
for (unsigned int uiUnaryIdx = 0; uiUnaryIdx < numStepCandMinus1; ++uiUnaryIdx)
{
unsigned int uiSymbol = mvpIdx == uiUnaryIdx ? 0 : 1;
m_BinEncoder.encodeBin(uiSymbol, Ctx::MmvdStepMvpIdx((uiUnaryIdx > LAST_MERGE_MMVD_IDX_CABAC - 1 ? LAST_MERGE_MMVD_IDX_CABAC - 1 : uiUnaryIdx)));
if (uiSymbol == 0)
{
break;
}
}
DTRACE(g_trace_ctx, D_SYNTAX, "mmvd_merge_idx() mmvd_merge_idx=%d\n", pu.mmvdMergeIdx);
#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
return;
}
#endif
#endif
#if !JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED || (JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED)
int var0, var1, var2;
int mvpIdx = pu.mmvdMergeIdx;
#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
var0 = mvpIdx / VVC_MMVD_MAX_REFINE_NUM;
var1 = (mvpIdx - (var0 * VVC_MMVD_MAX_REFINE_NUM)) / 4;
var2 = mvpIdx - (var0 * VVC_MMVD_MAX_REFINE_NUM) - var1 * 4;
#else
var0 = mvpIdx / MMVD_MAX_REFINE_NUM;
var1 = (mvpIdx - (var0 * MMVD_MAX_REFINE_NUM)) / 4;
var2 = mvpIdx - (var0 * MMVD_MAX_REFINE_NUM) - var1 * 4;
#endif
if (pu.cs->sps->getMaxNumMergeCand() > 1)
{
#if !JVET_AA0093_ENHANCED_MMVD_EXTENSION
static_assert(MMVD_BASE_MV_NUM == 2, "");
#endif
assert(var0 < 2);
m_BinEncoder.encodeBin(var0, Ctx::MmvdMergeIdx());
}
DTRACE(g_trace_ctx, D_SYNTAX, "base_mvp_idx() base_mvp_idx=%d\n", var0);
int numStepCandMinus1 =
#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
VVC_MMVD_REFINE_STEP - 1;
#else
MMVD_REFINE_STEP - 1;
#endif
if (numStepCandMinus1 > 0)
{
if (var1 == 0)
{
#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
m_BinEncoder.encodeBin(0, Ctx::MmvdStepMvpIdxECM3());
#else
m_BinEncoder.encodeBin(0, Ctx::MmvdStepMvpIdx());
#endif
}
else
{
#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
m_BinEncoder.encodeBin(1, Ctx::MmvdStepMvpIdxECM3());
#else
m_BinEncoder.encodeBin(1, Ctx::MmvdStepMvpIdx());
#endif
for (unsigned idx = 1; idx < numStepCandMinus1; idx++)
{
m_BinEncoder.encodeBinEP(var1 == idx ? 0 : 1);
if (var1 == idx)
{
break;
}
}
}
}
DTRACE(g_trace_ctx, D_SYNTAX, "mmvd_step_mvp_idx() mmvd_step_mvp_idx=%d\n", var1);
m_BinEncoder.encodeBinsEP(var2, 2);
DTRACE(g_trace_ctx, D_SYNTAX, "pos() pos=%d\n", var2);
DTRACE(g_trace_ctx, D_SYNTAX, "mmvd_merge_idx() mmvd_merge_idx=%d\n", pu.mmvdMergeIdx);
#endif
}
#if JVET_Z0056_GPM_SPLIT_MODE_REORDERING
void CABACWriter::geoModeIdx(const uint8_t geoMode, const uint8_t altCodeIdx)
{
if (altCodeIdx == 0)
{
xWriteTruncBinCode(geoMode, GEO_NUM_PARTITION_MODE);
DTRACE( g_trace_ctx, D_SYNTAX, "merge_idx() geo_split_dir=%u\n", geoMode );
return;
}
const int maxNumBins = (GEO_NUM_SIG_PARTMODE / GEO_SPLIT_MODE_RICE_CODE_DIVISOR) - 1;
const int maxNumCtxBins = 5;
int geoModePrefix = ((int)geoMode) / GEO_SPLIT_MODE_RICE_CODE_DIVISOR;
for (int binIdx = 0; binIdx < maxNumBins; ++binIdx)
{
unsigned binVal = (binIdx == geoModePrefix ? 0 : 1);
if (binIdx < maxNumCtxBins)
{
m_BinEncoder.encodeBin(binVal, Ctx::GeoSubModeIdx(binIdx));
if (binVal == 0)
{
break;
}
}
else
{
m_BinEncoder.encodeBinEP(binVal);
if (binVal == 0)
{
break;
}
}
}
if (GEO_SPLIT_MODE_RICE_CODE_DIVISOR > 1)
{
uint8_t geoModeSuffix = geoMode & (uint8_t)(GEO_SPLIT_MODE_RICE_CODE_DIVISOR - 1);
xWriteTruncBinCode(geoModeSuffix, GEO_SPLIT_MODE_RICE_CODE_DIVISOR);
DTRACE( g_trace_ctx, D_SYNTAX, "merge_idx() geo_split_dir=%d(prefix=%d suffix=%u)\n", geoMode, geoModePrefix, geoModeSuffix );
}
else
{
DTRACE( g_trace_ctx, D_SYNTAX, "merge_idx() geo_split_dir=%d\n", geoMode );
}
}
void CABACWriter::geoModeIdx(const PredictionUnit& pu)
{
if (!pu.cs->slice->getSPS()->getUseAltGPMSplitModeCode())
{
geoModeIdx(pu.geoSplitDir, 0);
return;
}
geoModeIdx(pu.geoSyntaxMode, 1);
}
#endif
#if JVET_W0097_GPM_MMVD_TM
void CABACWriter::geo_mmvd_idx(const PredictionUnit& pu, RefPicList eRefPicList)
{
int geoMMVDIdx = (eRefPicList == REF_PIC_LIST_0) ? pu.geoMMVDIdx0 : pu.geoMMVDIdx1;
bool extMMVD = pu.cs->picHeader->getGPMMMVDTableFlag();
CHECK(geoMMVDIdx >= (extMMVD ? GPM_EXT_MMVD_MAX_REFINE_NUM : GPM_MMVD_MAX_REFINE_NUM), "invalid GPM MMVD index exist");
int step = (extMMVD ? (geoMMVDIdx >> 3) : (geoMMVDIdx >> 2));
int direction = (extMMVD ? (geoMMVDIdx - (step << 3)) : (geoMMVDIdx - (step << 2)));
int mmvdStepToIdx[GPM_EXT_MMVD_REFINE_STEP] = { 5, 0, 1, 2, 3, 4, 6, 7, 8 };
step = mmvdStepToIdx[step];
int numStepCandMinus1 = (extMMVD ? GPM_EXT_MMVD_REFINE_STEP : GPM_MMVD_REFINE_STEP) - 1;
if (numStepCandMinus1 > 0)
{
if (step == 0)
{
m_BinEncoder.encodeBin(0, Ctx::GeoMmvdStepMvpIdx());
}
else
{
m_BinEncoder.encodeBin(1, Ctx::GeoMmvdStepMvpIdx());
for (unsigned idx = 1; idx < numStepCandMinus1; idx++)
{
m_BinEncoder.encodeBinEP(step == idx ? 0 : 1);
if (step == idx)
{
break;
}
}
}
}
int maxMMVDDir = (extMMVD ? GPM_EXT_MMVD_REFINE_DIRECTION : GPM_MMVD_REFINE_DIRECTION);
m_BinEncoder.encodeBinsEP(direction, maxMMVDDir > 4 ? 3 : 2);
DTRACE(g_trace_ctx, D_SYNTAX, "geo_mmvd_idx() geo_mmvd_idx%d=%d\n", eRefPicList, geoMMVDIdx);
}
void CABACWriter::geo_merge_idx(const PredictionUnit& pu)
{
#if !JVET_Z0056_GPM_SPLIT_MODE_REORDERING
uint8_t splitDir = pu.geoSplitDir;
#endif
uint8_t candIdx0 = pu.geoMergeIdx0;
uint8_t candIdx1 = pu.geoMergeIdx1;
#if JVET_Z0056_GPM_SPLIT_MODE_REORDERING
geoModeIdx(pu);
#else
xWriteTruncBinCode(splitDir, GEO_NUM_PARTITION_MODE);
#endif
#if JVET_AG0164_AFFINE_GPM
candIdx1 -= candIdx1 < candIdx0 || (pu.affineGPM[0] != pu.affineGPM[1] )? 0 : 1;
#else
candIdx1 -= candIdx1 < candIdx0 ? 0 : 1;
#endif
#if JVET_AG0164_AFFINE_GPM
int maxNumGeoCand = pu.affineGPM[0] ? pu.cs->sps->getMaxNumGpmAffCand() : pu.cs->sps->getMaxNumGeoCand();
#else
const int maxNumGeoCand = pu.cs->sps->getMaxNumGeoCand();
#endif
int numCandminus2 = maxNumGeoCand - 2;
#if JVET_AG0164_AFFINE_GPM
CtxSet mrgIdxCtxSet = Ctx::MergeIdx;
mrgIdxCtxSet = pu.affineGPM[0] ? Ctx::GpmAffMergeIdx : Ctx::GpmMergeIdx;
unsigned int uiUnaryIdx = 0;
for (; uiUnaryIdx < numCandminus2 + 1; ++uiUnaryIdx)
{
unsigned int uiSymbol = candIdx0 == uiUnaryIdx ? 0 : 1;
m_BinEncoder.encodeBin(uiSymbol, mrgIdxCtxSet((uiUnaryIdx > LAST_MERGE_IDX_CABAC - 1 ? LAST_MERGE_IDX_CABAC - 1 : uiUnaryIdx)));
if (uiSymbol == 0)
{
break;
}
}
#else
m_BinEncoder.encodeBin(candIdx0 == 0 ? 0 : 1, Ctx::MergeIdx());
if (candIdx0 > 0)
{
unary_max_eqprob(candIdx0 - 1, numCandminus2);
}
#endif
#if JVET_AG0164_AFFINE_GPM
maxNumGeoCand = pu.affineGPM[1] ? pu.cs->sps->getMaxNumGpmAffCand() : pu.cs->sps->getMaxNumGeoCand();
numCandminus2 = maxNumGeoCand - 2;
#endif
if (numCandminus2 > 0
#if JVET_AG0164_AFFINE_GPM
|| (pu.affineGPM[0] != pu.affineGPM[1])
#endif
)
{
#if JVET_AG0164_AFFINE_GPM
CtxSet mrgIdxCtxSet = Ctx::MergeIdx;
mrgIdxCtxSet = pu.affineGPM[1] ? Ctx::GpmAffMergeIdx : Ctx::GpmMergeIdx;
unsigned int uiUnaryIdx = 0;
for (; uiUnaryIdx < numCandminus2 + ((pu.affineGPM[0] != pu.affineGPM[1]) ? 1 : 0); ++uiUnaryIdx)
{
unsigned int uiSymbol = candIdx1 == uiUnaryIdx ? 0 : 1;
m_BinEncoder.encodeBin(uiSymbol, mrgIdxCtxSet((uiUnaryIdx > LAST_MERGE_IDX_CABAC - 1 ? LAST_MERGE_IDX_CABAC - 1 : uiUnaryIdx)));
if (uiSymbol == 0)
{
break;
}
}
#else
m_BinEncoder.encodeBin(candIdx1 == 0 ? 0 : 1, Ctx::MergeIdx());
if (candIdx1 > 0)
{
#if JVET_AG0164_AFFINE_GPM
unary_max_eqprob(candIdx1 - 1, numCandminus2 - ((pu.affineGPM[0] != pu.affineGPM[1]) ? 0 : 1));
#else
unary_max_eqprob(candIdx1 - 1, numCandminus2 - 1);
#endif
}
#endif
}
DTRACE(g_trace_ctx, D_SYNTAX, "geo_merge_idx() geo_merge_idx0=%d geo_merge_idx1=%d\n", pu.geoMergeIdx0, pu.geoMergeIdx1);
}
void CABACWriter::geo_merge_idx1(const PredictionUnit& pu)
{
#if !JVET_Z0056_GPM_SPLIT_MODE_REORDERING
uint8_t splitDir = pu.geoSplitDir;
#endif
uint8_t candIdx0 = pu.geoMergeIdx0;
uint8_t candIdx1 = pu.geoMergeIdx1;
#if JVET_Y0065_GPM_INTRA
#if JVET_AG0164_AFFINE_GPM
bool isIntra0 = (pu.geoMergeIdx0 >= GEO_MAX_ALL_INTER_UNI_CANDS);
bool isIntra1 = (pu.geoMergeIdx1 >= GEO_MAX_ALL_INTER_UNI_CANDS);
#else
bool isIntra0 = (candIdx0 >= GEO_MAX_NUM_UNI_CANDS);
bool isIntra1 = (candIdx1 >= GEO_MAX_NUM_UNI_CANDS);
#endif
#endif
#if JVET_AI0082_GPM_WITH_INTER_IBC
#if JVET_AG0164_AFFINE_GPM
bool isIbc0 = (candIdx0 >= GEO_MAX_ALL_INTER_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS);
bool isIbc1 = (candIdx1 >= GEO_MAX_ALL_INTER_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS);
#else
bool isIbc0 = (candIdx0 >= GEO_MAX_NUM_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS);
bool isIbc1 = (candIdx1 >= GEO_MAX_NUM_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS);
#endif
#endif
#if JVET_Z0056_GPM_SPLIT_MODE_REORDERING
geoModeIdx(pu);
#else
xWriteTruncBinCode(splitDir, GEO_NUM_PARTITION_MODE);
#endif
#if JVET_AG0164_AFFINE_GPM
int maxNumGeoCand = pu.affineGPM[0] ? pu.cs->sps->getMaxNumGpmAffCand(): pu.cs->sps->getMaxNumGeoCand();
#else
const int maxNumGeoCand = pu.cs->sps->getMaxNumGeoCand();
#endif
int numCandminus2 = maxNumGeoCand - 2;
#if JVET_Y0065_GPM_INTRA
if (isIntra0)
{
#if JVET_AI0082_GPM_WITH_INTER_IBC
if (isIbc0)
{
#if JVET_AG0164_AFFINE_GPM
int mergeIdx = candIdx0 - GEO_MAX_ALL_INTER_UNI_CANDS - GEO_MAX_NUM_INTRA_CANDS;
#else
int mergeIdx = candIdx0 - GEO_MAX_NUM_UNI_CANDS - GEO_MAX_NUM_INTRA_CANDS;
#endif
int numCandminus1 = GEO_MAX_NUM_IBC_CANDS - 1;
unsigned int uiUnaryIdx = 0;
for (; uiUnaryIdx < numCandminus1; ++uiUnaryIdx)
{
unsigned int uiSymbol = mergeIdx == uiUnaryIdx ? 0 : 1;
m_BinEncoder.encodeBin(uiSymbol, Ctx::GpmInterIbcIdx((uiUnaryIdx > LAST_MERGE_IDX_CABAC - 1 ? LAST_MERGE_IDX_CABAC - 1 : uiUnaryIdx)));
if (uiSymbol == 0)
{
break;
}
}
}
else
{
#if JVET_AG0164_AFFINE_GPM
unary_max_eqprob(candIdx0 - GEO_MAX_ALL_INTER_UNI_CANDS, GEO_MAX_NUM_INTRA_CANDS-1);
#else
unary_max_eqprob(candIdx0 - GEO_MAX_NUM_UNI_CANDS, GEO_MAX_NUM_INTRA_CANDS - 1);
#endif
}
#else
#if JVET_AG0164_AFFINE_GPM
unary_max_eqprob(candIdx0 - GEO_MAX_ALL_INTER_UNI_CANDS, GEO_MAX_NUM_INTRA_CANDS-1);
#else
unary_max_eqprob(candIdx0 - GEO_MAX_NUM_UNI_CANDS, GEO_MAX_NUM_INTRA_CANDS-1);
#endif
#endif
}
else if (numCandminus2 >= 0)
{
#endif
#if JVET_AG0164_AFFINE_GPM
CtxSet mrgIdxCtxSet = Ctx::MergeIdx;
mrgIdxCtxSet = pu.affineGPM[0] ? Ctx::GpmAffMergeIdx : Ctx::GpmMergeIdx;
unsigned int uiUnaryIdx = 0;
for (; uiUnaryIdx < numCandminus2 + 1; ++uiUnaryIdx)
{
unsigned int uiSymbol = candIdx0 == uiUnaryIdx ? 0 : 1;
m_BinEncoder.encodeBin(uiSymbol, mrgIdxCtxSet((uiUnaryIdx > LAST_MERGE_IDX_CABAC - 1 ? LAST_MERGE_IDX_CABAC - 1 : uiUnaryIdx)));
if (uiSymbol == 0)
{
break;
}
}
#else
m_BinEncoder.encodeBin(candIdx0 == 0 ? 0 : 1, Ctx::MergeIdx());
if (candIdx0 > 0)
{
unary_max_eqprob(candIdx0 - 1, numCandminus2);
}
#endif
#if JVET_Y0065_GPM_INTRA
}
#if JVET_AG0164_AFFINE_GPM
maxNumGeoCand = pu.affineGPM[1] ? pu.cs->sps->getMaxNumGpmAffCand() : pu.cs->sps->getMaxNumGeoCand();
numCandminus2 = maxNumGeoCand - 2;
#endif
if (isIntra1)
{
#if JVET_AI0082_GPM_WITH_INTER_IBC
if (isIbc1)
{
#if JVET_AG0164_AFFINE_GPM
int mergeIdx = candIdx1 - GEO_MAX_ALL_INTER_UNI_CANDS - GEO_MAX_NUM_INTRA_CANDS;
#else
int mergeIdx = candIdx1 - GEO_MAX_NUM_UNI_CANDS - GEO_MAX_NUM_INTRA_CANDS;
#endif
int numCandminus1 = GEO_MAX_NUM_IBC_CANDS - 1;
unsigned int uiUnaryIdx = 0;
for (; uiUnaryIdx < numCandminus1; ++uiUnaryIdx)
{
unsigned int uiSymbol = mergeIdx == uiUnaryIdx ? 0 : 1;
m_BinEncoder.encodeBin(uiSymbol, Ctx::GpmInterIbcIdx((uiUnaryIdx > LAST_MERGE_IDX_CABAC - 1 ? LAST_MERGE_IDX_CABAC - 1 : uiUnaryIdx)));
if (uiSymbol == 0)
{
break;
}
}
}
else
{
#if JVET_AG0164_AFFINE_GPM
unary_max_eqprob(candIdx1 - GEO_MAX_ALL_INTER_UNI_CANDS, GEO_MAX_NUM_INTRA_CANDS - 1);
#else
unary_max_eqprob(candIdx1 - GEO_MAX_NUM_UNI_CANDS, GEO_MAX_NUM_INTRA_CANDS - 1);
#endif
}
#else
#if JVET_AG0164_AFFINE_GPM
unary_max_eqprob(candIdx1 - GEO_MAX_ALL_INTER_UNI_CANDS, GEO_MAX_NUM_INTRA_CANDS - 1);
#else
unary_max_eqprob(candIdx1 - GEO_MAX_NUM_UNI_CANDS, GEO_MAX_NUM_INTRA_CANDS-1);
#endif
#endif
}
else if (numCandminus2 >= 0)
{
#endif
#if JVET_AG0164_AFFINE_GPM
CtxSet mrgIdxCtxSet = Ctx::MergeIdx;
mrgIdxCtxSet = pu.affineGPM[1] ? Ctx::GpmAffMergeIdx : Ctx::GpmMergeIdx;
unsigned int uiUnaryIdx = 0;
for (; uiUnaryIdx < numCandminus2 + 1; ++uiUnaryIdx)
{
unsigned int uiSymbol = candIdx1 == uiUnaryIdx ? 0 : 1;
m_BinEncoder.encodeBin(uiSymbol, mrgIdxCtxSet((uiUnaryIdx > LAST_MERGE_IDX_CABAC - 1 ? LAST_MERGE_IDX_CABAC - 1 : uiUnaryIdx)));
if (uiSymbol == 0)
{
break;
}
}
#else
m_BinEncoder.encodeBin(candIdx1 == 0 ? 0 : 1, Ctx::MergeIdx());
if (candIdx1 > 0)
{
unary_max_eqprob(candIdx1 - 1, numCandminus2);
}
#endif
#if JVET_Y0065_GPM_INTRA
}
#endif
DTRACE(g_trace_ctx, D_SYNTAX, "geo_merge_idx1() geo_merge_idx0=%d geo_merge_idx1=%d\n", pu.geoMergeIdx0, pu.geoMergeIdx1);
}
#if JVET_AG0112_REGRESSION_BASED_GPM_BLENDING
uint64_t CABACWriter::geo_blend_est( const TempCtx& ctxStart, const int flag )
{
getCtx() = ctxStart;
resetBits();
m_BinEncoder.encodeBin( flag, Ctx::GeoBlendFlag() );
return getEstFracBits();
}
#endif
uint64_t CABACWriter::geo_mode_est(const TempCtx& ctxStart, const int geoMode
#if JVET_Z0056_GPM_SPLIT_MODE_REORDERING
, const uint8_t altCodeIdx
#endif
)
{
getCtx() = SubCtx(Ctx::GeoSubModeIdx, ctxStart);
resetBits();
#if JVET_Z0056_GPM_SPLIT_MODE_REORDERING
geoModeIdx((uint8_t)geoMode, altCodeIdx);
#else
xWriteTruncBinCode(geoMode, GEO_NUM_PARTITION_MODE);
#endif
return getEstFracBits();
}
uint64_t CABACWriter::geo_mergeIdx_est(const TempCtx& ctxStart, const int candIdx, const int maxNumGeoCand
#if JVET_AG0164_AFFINE_GPM
, int isAffine
#endif
)
{
getCtx() = SubCtx(Ctx::MergeIdx, ctxStart);
resetBits();
int numCandminus2 = maxNumGeoCand - 2;
#if JVET_Y0065_GPM_INTRA
if (numCandminus2 < 0)
{
return 0;
}
#endif
#if JVET_AG0164_AFFINE_GPM
CtxSet mrgIdxCtxSet = Ctx::MergeIdx;
mrgIdxCtxSet = isAffine? Ctx::GpmAffMergeIdx: Ctx::GpmMergeIdx;
unsigned int uiUnaryIdx = 0;
for (; uiUnaryIdx < numCandminus2 + 1; ++uiUnaryIdx)
{
unsigned int uiSymbol = candIdx == uiUnaryIdx ? 0 : 1;
m_BinEncoder.encodeBin(uiSymbol, mrgIdxCtxSet((uiUnaryIdx > LAST_MERGE_IDX_CABAC - 1 ? LAST_MERGE_IDX_CABAC - 1 : uiUnaryIdx)));
if (uiSymbol == 0)
{
break;
}
}
#else
m_BinEncoder.encodeBin(candIdx == 0 ? 0 : 1, Ctx::MergeIdx());
if (candIdx > 0)
{
unary_max_eqprob(candIdx - 1, numCandminus2);
}
#endif
return getEstFracBits();
}
#if JVET_Y0065_GPM_INTRA
uint64_t CABACWriter::geo_intraFlag_est( const TempCtx& ctxStart, const int flag)
{
getCtx() = SubCtx(Ctx::GPMIntraFlag, ctxStart);
resetBits();
m_BinEncoder.encodeBin(flag, Ctx::GPMIntraFlag());
return getEstFracBits();
}
#if JVET_AI0082_GPM_WITH_INTER_IBC
uint64_t CABACWriter::geo_intraIdx_est( const int intraIdx, const bool isGeoIbc)
#else
uint64_t CABACWriter::geo_intraIdx_est( const int intraIdx)
#endif
{
resetBits();
#if JVET_AI0082_GPM_WITH_INTER_IBC
unary_max_eqprob(intraIdx, GEO_MAX_NUM_INTRA_CANDS + (isGeoIbc ? GEO_MAX_NUM_IBC_CANDS : 0) - 1);
#else
unary_max_eqprob(intraIdx, GEO_MAX_NUM_INTRA_CANDS-1);
#endif
return getEstFracBits();
}
#endif
uint64_t CABACWriter::geo_mmvdFlag_est(const TempCtx& ctxStart, const int flag)
{
getCtx() = SubCtx(Ctx::GeoMmvdFlag, ctxStart);
resetBits();
m_BinEncoder.encodeBin(flag, Ctx::GeoMmvdFlag());
return getEstFracBits();
}
#if TM_MRG
uint64_t CABACWriter::geo_tmFlag_est(const TempCtx& ctxStart, const int flag)
{
getCtx() = SubCtx(Ctx::TMMergeFlag, ctxStart);
resetBits();
m_BinEncoder.encodeBin(flag, Ctx::TMMergeFlag());
return getEstFracBits();
}
#endif
uint64_t CABACWriter::geo_mmvdIdx_est(const TempCtx& ctxStart, const int geoMMVDIdx, const bool extMMVD)
{
getCtx() = SubCtx(Ctx::GeoMmvdStepMvpIdx, ctxStart);
resetBits();
CHECK(geoMMVDIdx >= (extMMVD ? GPM_EXT_MMVD_MAX_REFINE_NUM : GPM_MMVD_MAX_REFINE_NUM), "invalid GPM MMVD index exist");
int step = (extMMVD ? (geoMMVDIdx >> 3) : (geoMMVDIdx >> 2));
int direction = (extMMVD ? (geoMMVDIdx - (step << 3)) : (geoMMVDIdx - (step << 2)));
int mmvdStepToIdx[GPM_EXT_MMVD_REFINE_STEP] = { 5, 0, 1, 2, 3, 4, 6, 7, 8 };
step = mmvdStepToIdx[step];
int numStepCandMinus1 = (extMMVD ? GPM_EXT_MMVD_REFINE_STEP : GPM_MMVD_REFINE_STEP) - 1;
if (numStepCandMinus1 > 0)
{
if (step == 0)
{
m_BinEncoder.encodeBin(0, Ctx::GeoMmvdStepMvpIdx());
}
else
{
m_BinEncoder.encodeBin(1, Ctx::GeoMmvdStepMvpIdx());
for (unsigned idx = 1; idx < numStepCandMinus1; idx++)
{
m_BinEncoder.encodeBinEP(step == idx ? 0 : 1);
if (step == idx)
{
break;
}
}
}
}
int maxMMVDDir = (extMMVD ? GPM_EXT_MMVD_REFINE_DIRECTION : GPM_MMVD_REFINE_DIRECTION);
m_BinEncoder.encodeBinsEP(direction, maxMMVDDir > 4 ? 3 : 2);
return getEstFracBits();
}
#endif
#if JVET_AG0164_AFFINE_GPM
uint64_t CABACWriter::geo_affFlag_est(const TempCtx& ctxStart, const int flag, int ctxOffset)
{
getCtx() = ctxStart;
resetBits();
m_BinEncoder.encodeBin(flag, Ctx::AffineFlag(ctxOffset));
return getEstFracBits();
}
#endif
#if JVET_AA0058_GPM_ADAPTIVE_BLENDING
#if JVET_AH0314_ADAPTIVE_GPM_BLENDING_IMPROV
uint64_t CABACWriter::geoBldFlagEst(const PredictionUnit& pu, const TempCtx& ctxStart, const int flag)
#else
uint64_t CABACWriter::geoBldFlagEst(const TempCtx& ctxStart, const int flag)
#endif
{
getCtx() = ctxStart;
resetBits();
#if JVET_AH0314_ADAPTIVE_GPM_BLENDING_IMPROV
int blkSizeSmall = pu.lwidth() < pu.lheight() ? pu.lwidth() : pu.lheight();
if (blkSizeSmall < GPM_BLENDING_SIZE_THRESHOLD)
{
geoAdaptiveBlendingIdx(pu, flag);
}
else
geoAdaptiveBlendingIdx(pu, flag - 1);
#else
geoAdaptiveBlendingIdx(flag);
#endif
return getEstFracBits();
}
#if JVET_AH0314_ADAPTIVE_GPM_BLENDING_IMPROV
void CABACWriter::geoAdaptiveBlendingIdx(const PredictionUnit& pu, const int idx)
#else
void CABACWriter::geoAdaptiveBlendingIdx(const int idx)
#endif
{
#if JVET_AH0314_ADAPTIVE_GPM_BLENDING_IMPROV
int blkSizeSmall = pu.lwidth() < pu.lheight() ? pu.lwidth() : pu.lheight();
int offset = (blkSizeSmall < GPM_BLENDING_SIZE_THRESHOLD) ? 0 : 4;
if (idx == 2)
{
m_BinEncoder.encodeBin(1, Ctx::GeoBldFlag(0 + offset));
}
else
{
m_BinEncoder.encodeBin(0, Ctx::GeoBldFlag(0 + offset));
if (idx == 0 || idx == 1)
{
m_BinEncoder.encodeBin(1, Ctx::GeoBldFlag(1 + offset));
m_BinEncoder.encodeBin(idx == 0, Ctx::GeoBldFlag(2 + offset));
}
else
{
m_BinEncoder.encodeBin(0, Ctx::GeoBldFlag(1 + offset));
m_BinEncoder.encodeBin(idx == 3, Ctx::GeoBldFlag(3 + offset));
}
}
#else
if (idx == 2)
{
m_BinEncoder.encodeBin(1, Ctx::GeoBldFlag(0));
}
else
{
m_BinEncoder.encodeBin(0, Ctx::GeoBldFlag(0));
if (idx == 0 || idx == 1)
{
m_BinEncoder.encodeBin(1, Ctx::GeoBldFlag(1));
m_BinEncoder.encodeBin(idx == 0, Ctx::GeoBldFlag(2));
}
else
{
m_BinEncoder.encodeBin(0, Ctx::GeoBldFlag(1));
m_BinEncoder.encodeBin(idx == 3, Ctx::GeoBldFlag(3));
}
}
#endif
DTRACE(g_trace_ctx, D_SYNTAX, "geo_adaptive_blending_idx() geo_bld_idx=%d\n", idx);
}
#endif
void CABACWriter::inter_pred_idc( const PredictionUnit& pu )
{
if( !pu.cs->slice->isInterB() )
{
return;
}
if( !(PU::isBipredRestriction(pu)) )
{
unsigned ctxId = DeriveCtx::CtxInterDir(pu);
if( pu.interDir == 3 )
{
m_BinEncoder.encodeBin( 1, Ctx::InterDir(ctxId) );
DTRACE( g_trace_ctx, D_SYNTAX, "inter_pred_idc() ctx=%d value=%d pos=(%d,%d)\n", ctxId, pu.interDir, pu.lumaPos().x, pu.lumaPos().y );
return;
}
else
{
m_BinEncoder.encodeBin( 0, Ctx::InterDir(ctxId) );
}
}
#if JVET_Z0054_BLK_REF_PIC_REORDER
if (pu.cs->sps->getUseARL())
{
return;
}
#endif
#if CTU_256
m_BinEncoder.encodeBin( ( pu.interDir == 2 ), Ctx::InterDir( 7 ) );
#else
m_BinEncoder.encodeBin( ( pu.interDir == 2 ), Ctx::InterDir( 6 ) );
#endif
DTRACE( g_trace_ctx, D_SYNTAX, "inter_pred_idc() ctx=7 value=%d pos=(%d,%d)\n", pu.interDir, pu.lumaPos().x, pu.lumaPos().y );
}
#if JVET_Z0054_BLK_REF_PIC_REORDER
void CABACWriter::refIdxLC(const PredictionUnit& pu)
{
if (!PU::useRefCombList(pu))
{
return;
}
int numRefMinus1 = (int)pu.cs->slice->getRefPicCombinedList().size() - 1;
int refIdxLC = pu.refIdxLC;
#if JVET_X0083_BM_AMVP_MERGE_MODE
if (pu.amvpMergeModeFlag[0] || pu.amvpMergeModeFlag[1])
{
numRefMinus1 = (int)pu.cs->slice->getRefPicCombinedListAmvpMerge().size() - 1;
}
#endif
if (numRefMinus1 > 0)
{
if (refIdxLC == 0)
{
m_BinEncoder.encodeBin(0, Ctx::RefPicLC(0));
DTRACE(g_trace_ctx, D_SYNTAX, "refIdxLC() value=%d pos=(%d,%d)\n", refIdxLC, pu.lumaPos().x, pu.lumaPos().y);
return;
}
else
{
m_BinEncoder.encodeBin(1, Ctx::RefPicLC(0));
for (unsigned idx = 1; idx < numRefMinus1; idx++)
{
m_BinEncoder.encodeBin(refIdxLC == idx ? 0 : 1, Ctx::RefPicLC(std::min((int)idx, 2)));
if (refIdxLC == idx)
{
break;
}
}
}
}
DTRACE(g_trace_ctx, D_SYNTAX, "refIdxLC() value=%d pos=(%d,%d)\n", refIdxLC, pu.lumaPos().x, pu.lumaPos().y);
}
void CABACWriter::refPairIdx(const PredictionUnit& pu)
{
if (!PU::useRefPairList(pu))
{
return;
}
int numRefMinus1 = (int)pu.cs->slice->getRefPicPairList().size() - 1;
int refPairIdx = pu.refPairIdx;
if (numRefMinus1 > 0)
{
if (refPairIdx == 0)
{
m_BinEncoder.encodeBin(0, Ctx::RefPicLC(0));
DTRACE(g_trace_ctx, D_SYNTAX, "refPairIdx() value=%d pos=(%d,%d)\n", refPairIdx, pu.lumaPos().x, pu.lumaPos().y);
return;
}
else
{
m_BinEncoder.encodeBin(1, Ctx::RefPicLC(0));
for (unsigned idx = 1; idx < numRefMinus1; idx++)
{
m_BinEncoder.encodeBin(refPairIdx == idx ? 0 : 1, Ctx::RefPicLC(std::min((int)idx, 2)));
if (refPairIdx == idx)
{
break;
}
}
}
}
DTRACE(g_trace_ctx, D_SYNTAX, "refPairIdx() value=%d pos=(%d,%d)\n", refPairIdx, pu.lumaPos().x, pu.lumaPos().y);
}
#endif
#if JVET_Z0054_BLK_REF_PIC_REORDER && JVET_AD0213_LIC_IMP
void CABACWriter::ref_idx(const PredictionUnit& pu, RefPicList eRefList, bool forceRefIdx)
#else
void CABACWriter::ref_idx( const PredictionUnit& pu, RefPicList eRefList )
#endif
{
if ( pu.cu->smvdMode )
{
CHECK( pu.refIdx[eRefList] != pu.cs->slice->getSymRefIdx( eRefList ), "Invalid reference index!\n" );
return;
}
#if JVET_Z0054_BLK_REF_PIC_REORDER
#if JVET_AD0213_LIC_IMP
if (!forceRefIdx)
#endif
if (PU::useRefCombList(pu) || PU::useRefPairList(pu))
{
return;
}
#endif
#if JVET_AG0098_AMVP_WITH_SBTMVP
if (pu.amvpSbTmvpFlag)
{
return;
}
#endif
#if JVET_X0083_BM_AMVP_MERGE_MODE
if (pu.amvpMergeModeFlag[1 - eRefList])
{
#if JVET_Y0128_NON_CTC
if (pu.cu->slice->getAmvpMergeModeOnlyOneValidRefIdx(eRefList) >= 0)
{
return;
}
#else
const RefPicList refListAmvp = eRefList;
const RefPicList refListMerge = RefPicList(1 - eRefList);
const int curPoc = pu.cs->slice->getPOC();
const int numRefAmvp = pu.cs->slice->getNumRefIdx(refListAmvp);
const int numRefMerge = pu.cs->slice->getNumRefIdx(refListMerge);
int candidateRefIdxCount = 0;
for (int refIdxAmvp = 0; refIdxAmvp < numRefAmvp; refIdxAmvp++)
{
const int amvpPoc = pu.cs->slice->getRefPOC(refListAmvp, refIdxAmvp);
bool validCandidate = false;
for (int refIdxMerge = 0; refIdxMerge < numRefMerge; refIdxMerge++)
{
const int mergePoc = pu.cs->slice->getRefPOC(refListMerge, refIdxMerge);
if ((amvpPoc - curPoc) * (mergePoc - curPoc) < 0)
{
validCandidate = true;
}
}
if (validCandidate)
{
candidateRefIdxCount++;
}
}
CHECK(candidateRefIdxCount == 0, "this is not possible");
if (candidateRefIdxCount == 1)
{
return;
}
#endif
}
#endif
int numRef = pu.cs->slice->getNumRefIdx(eRefList);
#if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
if (eRefList == REF_PIC_LIST_0 && pu.cs->slice->getUseIBC())
#else
if (eRefList == REF_PIC_LIST_0 && pu.cs->sps->getIBCFlag())
#endif
{
if (CU::isIBC(*pu.cu))
return;
}
if( numRef <= 1 )
{
return;
}
int refIdx = pu.refIdx[eRefList];
m_BinEncoder.encodeBin( (refIdx > 0), Ctx::RefPic() );
if( numRef <= 2 || refIdx == 0 )
{
DTRACE( g_trace_ctx, D_SYNTAX, "ref_idx() value=%d pos=(%d,%d)\n", refIdx, pu.lumaPos().x, pu.lumaPos().y );
return;
}
m_BinEncoder.encodeBin( (refIdx > 1), Ctx::RefPic(1) );
if( numRef <= 3 || refIdx == 1 )
{
DTRACE( g_trace_ctx, D_SYNTAX, "ref_idx() value=%d pos=(%d,%d)\n", refIdx, pu.lumaPos().x, pu.lumaPos().y );
return;
}
for( int idx = 3; idx < numRef; idx++ )
{
if( refIdx > idx - 1 )
{
m_BinEncoder.encodeBinEP( 1 );
}
else
{
m_BinEncoder.encodeBinEP( 0 );
break;
}
}
DTRACE( g_trace_ctx, D_SYNTAX, "ref_idx() value=%d pos=(%d,%d)\n", refIdx, pu.lumaPos().x, pu.lumaPos().y );
}
#if MULTI_HYP_PRED
void CABACWriter::mh_pred_data(const PredictionUnit& pu)
{
if (!pu.cs->sps->getUseInterMultiHyp() || !pu.cs->slice->isInterB())
{
CHECK(!pu.addHypData.empty(), "Multi Hyp: !pu.addHypData.empty()");
return;
}
if (pu.ciipFlag)
{
CHECK(!pu.addHypData.empty(), "Multi Hyp: !pu.addHypData.empty()");
return;
}
if (pu.cu->geoFlag)
{
CHECK(!pu.addHypData.empty(), "Multi Hyp: !pu.addHypData.empty()");
return;
}
#if TM_MRG || (JVET_Z0084_IBC_TM && IBC_TM_MRG)
if (pu.tmMergeFlag)
{
CHECK(!pu.addHypData.empty(), "Multi Hyp: !pu.addHypData.empty()");
return;
}
#endif
#if JVET_X0049_ADAPT_DMVR
if (pu.bmMergeFlag)
{
CHECK(!pu.addHypData.empty(), "Multi Hyp: !pu.addHypData.empty()");
return;
}
#endif
#if !JVET_Z0083_PARSINGERROR_FIX
if (!pu.mergeFlag && pu.cu->affine && pu.cu->imv)
{
return;
}
#endif
if( !pu.mergeFlag && pu.cu->bcwIdx == BCW_DEFAULT )
{
return;
}
if( CU::isIBC( *pu.cu ) )
{
return;
}
#if JVET_AG0098_AMVP_WITH_SBTMVP
if (pu.amvpSbTmvpFlag)
{
return;
}
#endif
if (pu.Y().area() <= MULTI_HYP_PRED_RESTRICT_BLOCK_SIZE || std::min(pu.Y().width, pu.Y().height) < MULTI_HYP_PRED_RESTRICT_MIN_WH)
{
CHECK(!pu.addHypData.empty(), "Multi Hyp: !pu.addHypData.empty()");
return;
}
const int numMHRef = pu.cs->slice->getNumMultiHypRefPics();
CHECK(numMHRef <= 0, "Multi Hyp: numMHRef <= 0");
const size_t maxNumAddHyps = pu.cs->sps->getMaxNumAddHyps();
CHECK(pu.addHypData.size() > maxNumAddHyps, "Multi Hyp: pu.addHypData.size() > maxNumAddHyps");
int hypIdx = 0;
for (int i = pu.numMergedAddHyps; i < pu.addHypData.size(); i++)
{
m_BinEncoder.encodeBin(1, Ctx::MultiHypothesisFlag(hypIdx));
if( hypIdx < 1 )
{
hypIdx++;
}
const MultiHypPredictionData &mhData = pu.addHypData[i];
#if MULTI_HYP_PRED
#if JVET_Z0127_SPS_MHP_MAX_MRG_CAND
const int maxNumMHPCand = pu.cs->sps->getMaxNumMHPCand();
if (maxNumMHPCand > 0)
{
m_BinEncoder.encodeBin(mhData.isMrg, Ctx::MultiHypothesisFlag(2));
}
else
{
CHECK(mhData.isMrg, "mhData.isMrg is true while maxNumMHPCand is 0")
}
if (mhData.isMrg)
{
CHECK(mhData.mrgIdx >= maxNumMHPCand, "Incorrect mhData.mrgIdx");
int numCandminus2 = maxNumMHPCand - 2;
#else
m_BinEncoder.encodeBin(mhData.isMrg, Ctx::MultiHypothesisFlag(2));
if (mhData.isMrg)
{
const int maxNumGeoCand = pu.cs->sps->getMaxNumGeoCand();
CHECK(maxNumGeoCand < 2, "Incorrect max number of geo candidates");
CHECK(mhData.mrgIdx >= maxNumGeoCand, "Incorrect mhData.mrgIdx");
int numCandminus2 = maxNumGeoCand - 2;
#endif
m_BinEncoder.encodeBin(mhData.mrgIdx == 0 ? 0 : 1, Ctx::MergeIdx());
if (mhData.mrgIdx > 0)
{
unary_max_eqprob(mhData.mrgIdx - 1, numCandminus2);
}
unary_max_symbol(mhData.weightIdx, Ctx::MHWeight(), Ctx::MHWeight(1), pu.cs->sps->getNumAddHypWeights() - 1);
continue;
}
#endif
CHECK(mhData.refIdx < 0, "Multi Hyp: mhData.refIdx < 0");
CHECK(mhData.refIdx >= numMHRef, "Multi Hyp: mhData.refIdx >= numMHRef");
ref_idx_mh(numMHRef, mhData.refIdx);
Mv mhMvd = mhData.mvd;
if (pu.cu->affine)
{
mhMvd.changeAffinePrecInternal2Amvr(pu.cu->imv);
}
else
{
mhMvd.changeTransPrecInternal2Amvr(pu.cu->imv);
}
#if JVET_AD0140_MVD_PREDICTION
mvd_coding(mhMvd, 0, nullptr, true);
#else
mvd_coding(mhMvd, 0);
#endif
m_BinEncoder.encodeBin(mhData.mvpIdx, Ctx::MVPIdx());
CHECK(mhData.weightIdx < 0, "Multi Hyp: mhData.weightIdx < 0");
CHECK(mhData.weightIdx >= pu.cs->sps->getNumAddHypWeights(), "Multi Hyp: mhData.weightIdx >= pu.cs->sps->getSpsNext().getNumAddHypWeights()");
unary_max_symbol(mhData.weightIdx, Ctx::MHWeight(), Ctx::MHWeight(1), pu.cs->sps->getNumAddHypWeights() - 1);
}
if( ( pu.addHypData.size() - pu.numMergedAddHyps ) < maxNumAddHyps )
{
m_BinEncoder.encodeBin( 0, Ctx::MultiHypothesisFlag( hypIdx ) );
}
}
void CABACWriter::ref_idx_mh(const int numRef, const int refIdx)
{
if (numRef <= 1)
{
return;
}
m_BinEncoder.encodeBin((refIdx > 0), Ctx::MHRefPic());
if (numRef <= 2 || refIdx == 0)
{
return;
}
m_BinEncoder.encodeBin((refIdx > 1), Ctx::MHRefPic(1));
if (numRef <= 3 || refIdx == 1)
{
return;
}
for (int idx = 3; idx < numRef; idx++)
{
if (refIdx > idx - 1)
{
m_BinEncoder.encodeBinEP(1);
}
else
{
m_BinEncoder.encodeBinEP(0);
break;
}
}
}
#endif
void CABACWriter::mvp_flag( const PredictionUnit& pu, RefPicList eRefList )
{
#if JVET_X0083_BM_AMVP_MERGE_MODE
if (pu.amvpMergeModeFlag[eRefList])
{
return;
}
#endif
#if JVET_Y0129_MVD_SIGNAL_AMVP_MERGE_MODE
#if JVET_AE0169_BIPREDICTIVE_IBC
if (pu.amvpMergeModeFlag[1 - eRefList] == true && !CU::isIBC(*pu.cu))
#else
if (pu.amvpMergeModeFlag[1 - eRefList] == true)
#endif
{
if (pu.mvpIdx[eRefList] < 2)
{
#if TM_AMVP
#if JVET_Y0128_NON_CTC || (JVET_AA0132_CONFIGURABLE_TM_TOOLS && TM_AMVP)
#if JVET_Z0054_BLK_REF_PIC_REORDER
if (pu.cs->sps->getUseARL())
{
RefListAndRefIdx refListComb = pu.cs->slice->getRefPicCombinedListAmvpMerge()[pu.refIdxLC];
if (PU::checkTmEnableCondition(pu.cs->sps, pu.cs->pps, pu.cu->slice->getRefPic(refListComb.refList, refListComb.refIdx)) == false)
{
m_BinEncoder.encodeBin(0, Ctx::MVPIdx());
}
}
else
#endif
if (PU::checkTmEnableCondition(pu.cs->sps, pu.cs->pps, pu.cu->slice->getRefPic(eRefList, pu.refIdx[eRefList])) == false)
#else
if(!pu.cu->cs->sps->getUseDMVDMode() || pu.cu->affine || CU::isIBC(*pu.cu))
#endif
#endif
{
m_BinEncoder.encodeBin( 0, Ctx::MVPIdx() );
}
m_BinEncoder.encodeBinEP( pu.mvpIdx[eRefList] );
}
else
{
m_BinEncoder.encodeBin( 1, Ctx::MVPIdx() );
}
return;
}
#endif
#if TM_AMVP
#if JVET_Y0128_NON_CTC || JVET_AA0132_CONFIGURABLE_TM_TOOLS
bool needToCodeMvpIdx = false;
if (pu.cu->affine || CU::isIBC(*pu.cu))
{
needToCodeMvpIdx = true;
}
#if JVET_Z0054_BLK_REF_PIC_REORDER
else if (PU::useRefCombList(pu))
{
needToCodeMvpIdx = pu.refIdxLC >= pu.cs->slice->getNumNonScaledRefPic()
#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
|| !pu.cs->sps->getUseTMAmvpMode()
#else
|| !pu.cs->sps->getUseDMVDMode()
#endif
;
}
else if (PU::useRefPairList(pu))
{
needToCodeMvpIdx = pu.refPairIdx >= pu.cs->slice->getNumNonScaledRefPicPair()
#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
|| !pu.cs->sps->getUseTMAmvpMode()
#else
|| !pu.cs->sps->getUseDMVDMode()
#endif
;
}
#endif
else if (PU::checkTmEnableCondition(pu.cs->sps, pu.cs->pps, pu.cu->slice->getRefPic(eRefList, pu.refIdx[eRefList])) == false)
{
needToCodeMvpIdx = true;
}
if (needToCodeMvpIdx)
#else
if(!pu.cu->cs->sps->getUseDMVDMode() || pu.cu->affine || CU::isIBC(*pu.cu))
#endif
#endif
m_BinEncoder.encodeBin( pu.mvpIdx[eRefList], Ctx::MVPIdx() );
DTRACE( g_trace_ctx, D_SYNTAX, "mvp_flag() value=%d pos=(%d,%d)\n", pu.mvpIdx[eRefList], pu.lumaPos().x, pu.lumaPos().y );
#if !JVET_Z0054_BLK_REF_PIC_REORDER
DTRACE( g_trace_ctx, D_SYNTAX, "mvpIdx(refList:%d)=%d\n", eRefList, pu.mvpIdx[eRefList] );
#endif
}
#if JVET_AG0135_AFFINE_CIIP
void CABACWriter::ciipAffineFlag(const PredictionUnit& pu)
{
if (!pu.cu->slice->isIntra() && pu.cs->sps->getUseCiipAffine() && (pu.cu->slice->getPicHeader()->getMaxNumAffineMergeCand() > 0) && pu.cu->lumaSize().width >= 8 && pu.cu->lumaSize().height >= 8)
{
unsigned ctxId = DeriveCtx::CtxCiipAffineFlag(*pu.cu);
m_BinEncoder.encodeBin(pu.ciipAffine, Ctx::CiipAffineFlag(ctxId));
}
}
#endif
void CABACWriter::Ciip_flag(const PredictionUnit& pu)
{
if (!pu.cs->sps->getUseCiip())
{
CHECK(pu.ciipFlag == true, "invalid Ciip SPS");
return;
}
if (pu.cu->skip)
{
CHECK(pu.ciipFlag == true, "invalid Ciip and skip");
return;
}
m_BinEncoder.encodeBin(pu.ciipFlag, Ctx::CiipFlag());
DTRACE(g_trace_ctx, D_SYNTAX, "ciip_flag() ciip=%d pos=(%d,%d) size=%dx%d\n", pu.ciipFlag ? 1 : 0, pu.lumaPos().x, pu.lumaPos().y, pu.lumaSize().width, pu.lumaSize().height);
#if CIIP_PDPC
if( pu.ciipFlag )
{
#if JVET_X0141_CIIP_TIMD_TM && TM_MRG
#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
#if JVET_AG0135_AFFINE_CIIP
ciipAffineFlag(pu);
if (!pu.ciipAffine)
{
#endif
tm_merge_flag(pu);
#if JVET_AG0135_AFFINE_CIIP
}
#endif
#else
if (pu.cs->slice->getSPS()->getUseCiipTmMrg())
{
m_BinEncoder.encodeBin(pu.tmMergeFlag, Ctx::CiipTMMergeFlag());
DTRACE(g_trace_ctx, D_SYNTAX, "ciip_flag() ciip_tm_merge_flag=%d\n", pu.tmMergeFlag);
}
#endif
#endif
#if JVET_AG0135_AFFINE_CIIP
if (!pu.ciipAffine)
{
#endif
m_BinEncoder.encodeBin(pu.ciipPDPC, Ctx::CiipFlag(1));
#if JVET_AG0135_AFFINE_CIIP
}
#endif
DTRACE(g_trace_ctx, D_SYNTAX, "ciip_flag() ciip_pdpc_flag=%d pos=(%d,%d) size=%dx%d\n", pu.ciipPDPC ? 1 : 0, pu.lumaPos().x, pu.lumaPos().y, pu.lumaSize().width, pu.lumaSize().height);
}
#else
#if JVET_X0141_CIIP_TIMD_TM && TM_MRG
if (pu.ciipFlag && pu.cs->slice->getSPS()->getUseCiipTmMrg())
{
#if JVET_AA0132_CONFIGURABLE_TM_TOOLS
tm_merge_flag(pu);
#else
m_BinEncoder.encodeBin(pu.tmMergeFlag, Ctx::CiipTMMergeFlag());
DTRACE(g_trace_ctx, D_SYNTAX, "ciip_flag() ciip_tm_merge_flag=%d\n", pu.tmMergeFlag);
#endif
}
#endif
#endif
}
//================================================================================
// clause 7.3.8.8
//--------------------------------------------------------------------------------
// void transform_tree ( cs, area, cuCtx, chromaCbfs )
// bool split_transform_flag( split, depth )
// bool cbf_comp ( cbf, area, depth )
//================================================================================
void CABACWriter::transform_tree(const CodingStructure& cs, Partitioner& partitioner, CUCtx& cuCtx, const PartSplit ispType, const int subTuIdx
#if JVET_AE0102_LFNST_CTX
, const bool codeTuCoeff
#endif
)
{
const UnitArea& area = partitioner.currArea();
int subTuCounter = subTuIdx;
const TransformUnit& tu = *cs.getTU(area.blocks[partitioner.chType].pos(), partitioner.chType, subTuIdx);
const CodingUnit& cu = *tu.cu;
const unsigned trDepth = partitioner.currTrDepth;
const bool split = (tu.depth > trDepth);
// split_transform_flag
if( partitioner.canSplit( TU_MAX_TR_SPLIT, cs
#if JVET_AI0087_BTCUS_RESTRICTION
, false, false
#endif
) )
{
CHECK( !split, "transform split implied" );
}
else if( cu.sbtInfo && partitioner.canSplit( PartSplit( cu.getSbtTuSplit() ), cs
#if JVET_AI0087_BTCUS_RESTRICTION
, false, false
#endif
) )
{
CHECK( !split, "transform split implied - sbt" );
}
else
CHECK( split && !cu.ispMode, "transform split not allowed with QTBT" );
if( split )
{
if( partitioner.canSplit( TU_MAX_TR_SPLIT, cs
#if JVET_AI0087_BTCUS_RESTRICTION
, false, false
#endif
) )
{
#if ENABLE_TRACING
const CompArea &tuArea = partitioner.currArea().blocks[partitioner.chType];
DTRACE( g_trace_ctx, D_SYNTAX, "transform_tree() maxTrSplit chType=%d pos=(%d,%d) size=%dx%d\n", partitioner.chType, tuArea.x, tuArea.y, tuArea.width, tuArea.height );
#endif
partitioner.splitCurrArea( TU_MAX_TR_SPLIT, cs );
}
else if( cu.ispMode )
{
partitioner.splitCurrArea( ispType, cs );
}
else if( cu.sbtInfo && partitioner.canSplit( PartSplit( cu.getSbtTuSplit() ), cs
#if JVET_AI0087_BTCUS_RESTRICTION
, false, false
#endif
) )
{
partitioner.splitCurrArea( PartSplit( cu.getSbtTuSplit() ), cs );
}
else
THROW( "Implicit TU split not available" );
do
{
transform_tree( cs, partitioner, cuCtx, ispType, subTuCounter );
subTuCounter += subTuCounter != -1 ? 1 : 0;
} while( partitioner.nextPart( cs ) );
partitioner.exitCurrSplit();
}
else
{
DTRACE( g_trace_ctx, D_SYNTAX, "transform_unit() pos=(%d,%d) size=%dx%d depth=%d trDepth=%d\n", tu.blocks[tu.chType].x, tu.blocks[tu.chType].y, tu.blocks[tu.chType].width, tu.blocks[tu.chType].height, cu.depth, partitioner.currTrDepth );
transform_unit( tu, cuCtx, partitioner, subTuCounter);
}
}
void CABACWriter::cbf_comp( const CodingStructure& cs, bool cbf, const CompArea& area, unsigned depth, const bool prevCbf, const bool useISP )
{
unsigned ctxId = DeriveCtx::CtxQtCbf(area.compID, prevCbf, useISP && isLuma(area.compID));
const CtxSet &ctxSet = Ctx::QtCbf[area.compID];
if ((area.compID == COMPONENT_Y && cs.getCU(area.pos(), toChannelType(area.compID))->bdpcmMode)
|| (area.compID != COMPONENT_Y && cs.getCU(area.pos(), toChannelType(area.compID)) != NULL && cs.getCU(area.pos(), toChannelType(area.compID))->bdpcmModeChroma))
{
if (area.compID == COMPONENT_Y)
ctxId = 1;
else if (area.compID == COMPONENT_Cb)
ctxId = 1;
else
ctxId = 2;
m_BinEncoder.encodeBin(cbf, ctxSet(ctxId));
}
else
{
m_BinEncoder.encodeBin( cbf, ctxSet( ctxId ) );
}
DTRACE( g_trace_ctx, D_SYNTAX, "cbf_comp() etype=%d pos=(%d,%d) ctx=%d cbf=%d\n", area.compID, area.x, area.y, ctxId, cbf );
}
//================================================================================
// clause 7.3.8.9
//--------------------------------------------------------------------------------
// void mvd_coding( pu, refList )
//================================================================================
#if JVET_AD0140_MVD_PREDICTION
void CABACWriter::mvd_coding( const Mv &rMvd, int8_t imv, const MvdSuffixInfo* const pSi
#if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
, bool codeSign
#endif
)
{
const bool ctxCoding = nullptr != pSi && !codeSign;
int horMvd = rMvd.getHor();
int verMvd = rMvd.getVer();
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());
const int iEgcOffset = (!codeSign && ctxCoding) ? pSi->getEGCOffset() : 1;
if ( iEgcOffset!=0 ) // if abs_mvd_greater1_flag is compensated in remainder?
{
// 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 (!codeSign && ctxCoding)
{
#if ENABLE_TRACING
int horParam = -1;
int verParam = -1;
#endif
if (horAbs > iEgcOffset)
{
#if ENABLE_TRACING
horParam =
#endif
xWriteMvdPrefix(horAbs - 1 - iEgcOffset, MVD_CODING_GOLOMB_ORDER);
}
if (verAbs > iEgcOffset)
{
#if ENABLE_TRACING
verParam =
#endif
xWriteMvdPrefix(verAbs - 1 - iEgcOffset, MVD_CODING_GOLOMB_ORDER);
}
#if ENABLE_TRACING
if (horParam == -1)
{
DTRACE(g_trace_ctx, D_SYNTAX, "mvd_coding() abs(mvd_hor) = %d \n", horAbs);
}
else
{
DTRACE(g_trace_ctx, D_SYNTAX, "mvd_coding() mvd_hor prefix=%d \n", horParam);
}
if (verParam == -1)
{
DTRACE(g_trace_ctx, D_SYNTAX, "mvd_coding() abs(mvd_ver) = %d \n", verAbs);
}
else
{
DTRACE(g_trace_ctx, D_SYNTAX, "mvd_coding() mvd_ver prefix=%d \n", verParam);
}
#endif
}
else
{
DTRACE(g_trace_ctx, D_SYNTAX, "mvd_coding() code_sign=%d \n", codeSign);
if( horAbs > 0 )
{
if( horAbs > 1 )
{
m_BinEncoder.encodeRemAbsEP(horAbs - 2, 1, 0, MV_BITS - 1);
}
#if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
if (codeSign)
#endif
m_BinEncoder.encodeBinEP( (horMvd < 0) );
}
if( verAbs > 0 )
{
if( verAbs > 1 )
{
m_BinEncoder.encodeRemAbsEP(verAbs - 2, 1, 0, MV_BITS - 1);
}
#if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
if (codeSign)
#endif
m_BinEncoder.encodeBinEP( (verMvd < 0) );
}
DTRACE(g_trace_ctx, D_SYNTAX, "mvd_coding() abs(mvd_hor)=%d \n", horAbs);
DTRACE(g_trace_ctx, D_SYNTAX, "mvd_coding() abs(mvd_ver)=%d \n", verAbs);
}
}
unsigned CABACWriter::xWriteMvdPrefix( unsigned uiSymbol, int param )
{
unsigned bins = 0;
unsigned numBins = 0;
while (uiSymbol >= (unsigned)(1 << param))
{
bins <<= 1;
bins++;
numBins++;
uiSymbol -= 1 << param;
param++;
}
bins <<= 1;
numBins++;
unsigned temp = 0;
for (int i = numBins - 1; i >= 0; i--)
{
temp = bins >> i;
m_BinEncoder.encodeBinEP(temp);
bins -= (temp << i);
}
return numBins - 1; // less by 1 as compared to what xReadBvdContextPrefix() returns
}
void CABACWriter::xWriteMvdContextSuffix(unsigned uiSymbol, int param, int paramUpdated, int numSkipMSB )
{
unsigned numBins = 0;
while (uiSymbol >= (unsigned) (1 << param))
{
numBins++;
uiSymbol -= 1 << param;
param++;
}
numBins++;
paramUpdated++;
CHECK(paramUpdated != numBins, "Enc side prefix bits check error");
if (0 != numSkipMSB)
{
CHECK(paramUpdated == 0, "param_updated = 0");
paramUpdated-= numSkipMSB;
unsigned skipMask = ( 1 << (paramUpdated + numSkipMSB)) -1 - ((1 << (paramUpdated)) - 1);
uiSymbol &= ~skipMask;
CHECK(uiSymbol >= (1 << paramUpdated), "uiSymbol >= (1<<paramUpdated)");
}
if (paramUpdated > 0)
{
m_BinEncoder.encodeBinsEP(uiSymbol, paramUpdated);
}
}
void CABACWriter::mvdCodingRemainder(const Mv& rMvd, const MvdSuffixInfo& si, int8_t imv)
{
CHECK(si.horOffsetPrediction > (1<<15), "Attempt to write uninitialized horOffsetPrediction");
CHECK(si.verOffsetPrediction > (1<<15), "Attempt to write uninitialized verOffsetPrediction");
int horAbs = rMvd.getAbsHor();
int verAbs = rMvd.getAbsVer();
const int horParam = si.horPrefix;
const int verParam = si.verPrefix;
const unsigned int horOffsetPrediction = si.horOffsetPrediction;
const unsigned int verOffsetPrediction = si.verOffsetPrediction;
const int iEgcOffset = si.getEGCOffset();
if (horParam >= 0 || verParam >= 0)
{
const int iHorMSBins = std::max(0, si.horOffsetPredictionNumBins);
const int iVerMSBins = std::max(0, si.verOffsetPredictionNumBins);
if (horParam >= 0)
{
for (int i = iHorMSBins - 1; i >= 0; --i)
{
int bin = (horOffsetPrediction >> i) & 1;
const int prev2Bin = (i + 1 > iHorMSBins - 1) ? -1
: (i + 1 == iHorMSBins - 1) ? si.horSignHypMatch
: /*otherwise*/ (horOffsetPrediction >> 1) & 1;
const int prevBin = (i == iHorMSBins - 1) ? si.horSignHypMatch : (horOffsetPrediction & 1);
const int imvShift = MotionModelCheck::isAffine(si.m_motionModel) ? Mv::getImvPrecShiftAffineMvd(imv) : Mv::getImvPrecShiftMvd(imv);
const int iCtxIdx = DeriveCtx::ctxSmMvdBin(prev2Bin, prevBin, true, i + imvShift, si.m_motionModel);
const unsigned int ctx = Ctx::MvsdIdxMVDMSB(iCtxIdx);
m_BinEncoder.encodeBin((0 == bin) ? 1 : 0, ctx);
}
DTRACE(g_trace_ctx, D_SYNTAX, "Codeword for MVD suffix prediction bins for horizontal component: %d \n", horOffsetPrediction);
DTRACE(g_trace_ctx, D_SYNTAX, "Number of MVD suffix prediction bins for horizontal component: %d \n", iHorMSBins);
CHECK(horParam < 0, "horParam < 0");
DTRACE(g_trace_ctx, D_SYNTAX, "Number of explicitly coded MVD horizontal suffix bins: %d \n", horParam - iHorMSBins + 1);
xWriteMvdContextSuffix(horAbs - 1 - iEgcOffset, MVD_CODING_GOLOMB_ORDER, horParam, iHorMSBins);
}
if (verParam >= 0)
{
for (int i = iVerMSBins - 1; i >= 0; --i)
{
int bin = (verOffsetPrediction >> i) & 1;
const int prev2Bin = (i + 1 > iVerMSBins - 1) ? -1
: (i + 1 == iVerMSBins - 1) ? si.verSignHypMatch
: /*otherwise*/ (verOffsetPrediction >> 1) & 1;
const int prevBin = (i == iVerMSBins - 1) ? si.verSignHypMatch : (verOffsetPrediction & 1);
const int imvShift = MotionModelCheck::isAffine(si.m_motionModel) ? Mv::getImvPrecShiftAffineMvd(imv) : Mv::getImvPrecShiftMvd(imv);
const int iCtxIdx = DeriveCtx::ctxSmMvdBin(prev2Bin, prevBin, false, i + imvShift, si.m_motionModel);
const unsigned int ctx = Ctx::MvsdIdxMVDMSB(iCtxIdx);
m_BinEncoder.encodeBin((0 == bin) ? 1 : 0, ctx);
}
DTRACE(g_trace_ctx, D_SYNTAX, "Codeword for MVD suffix prediction bins for vertical component: %d \n", verOffsetPrediction);
DTRACE(g_trace_ctx, D_SYNTAX, "Number of MVD suffix prediction bins for vertical component: %d \n", iVerMSBins);
CHECK(verParam < 0, "verParam < 0");
DTRACE(g_trace_ctx, D_SYNTAX, "Number of explicitly coded MVD vertical suffix bins: %d \n", verParam - iVerMSBins + 1);
xWriteMvdContextSuffix(verAbs - 1 - iEgcOffset, MVD_CODING_GOLOMB_ORDER, verParam, iVerMSBins);
}
}
else
{
if (horAbs > 1)
{
xWriteMvdContextSuffix(horAbs - 2, MVD_CODING_GOLOMB_ORDER, horParam, 0 );
DTRACE(g_trace_ctx, D_SYNTAX, "mvd_coding_remainder() hor_suffix=%d \n", horAbs - 2);
}
if (verAbs > 1)
{
xWriteMvdContextSuffix(verAbs - 2, MVD_CODING_GOLOMB_ORDER, verParam, 0 );
DTRACE(g_trace_ctx, D_SYNTAX, "mvd_coding_remainder() ver_suffix=%d \n", verAbs - 2);
}
DTRACE(g_trace_ctx, D_SYNTAX, "mvd_coding_remainder() abs(mvd)=(%d,%d) \n", horAbs, verAbs);
}
}
#else
void CABACWriter::mvd_coding(const Mv& rMvd, int8_t imv
#if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
, bool codeSign
#endif
#if JVET_AA0070_RRIBC
, const int &rribcFlipType
#endif
)
{
int horMvd = rMvd.getHor();
int verMvd = rMvd.getVer();
if ( imv > 0 )
{
CHECK((horMvd % 2) != 0 && (verMvd % 2) != 0, "IMV: MVD is not a multiple of 2");
horMvd >>= 1;
verMvd >>= 1;
if (imv < IMV_HPEL)
{
CHECK((horMvd % 2) != 0 && (verMvd % 2) != 0, "IMV: MVD is not a multiple of 4");
horMvd >>= 1;
verMvd >>= 1;
if (imv == IMV_4PEL)//IMV_4PEL
{
CHECK((horMvd % 4) != 0 && (verMvd % 4) != 0, "IMV: MVD is not a multiple of 16");
horMvd >>= 2;
verMvd >>= 2;
}
}
}
unsigned horAbs = unsigned( horMvd < 0 ? -horMvd : horMvd );
unsigned verAbs = unsigned( verMvd < 0 ? -verMvd : verMvd );
// abs_mvd_greater0_flag[ 0 | 1 ]
#if JVET_AA0070_RRIBC
if (rribcFlipType != 2)
{
m_BinEncoder.encodeBin((horAbs > 0), Ctx::Mvd());
}
if (rribcFlipType != 1)
{
m_BinEncoder.encodeBin((verAbs > 0), Ctx::Mvd());
}
#else
m_BinEncoder.encodeBin((horAbs > 0), Ctx::Mvd());
m_BinEncoder.encodeBin((verAbs > 0), Ctx::Mvd());
#endif
// 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 )
{
m_BinEncoder.encodeRemAbsEP(horAbs - 2, 1, 0, MV_BITS - 1);
}
#if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
if (codeSign)
#endif
m_BinEncoder.encodeBinEP( (horMvd < 0) );
}
if( verAbs > 0 )
{
if( verAbs > 1 )
{
m_BinEncoder.encodeRemAbsEP(verAbs - 2, 1, 0, MV_BITS - 1);
}
#if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
if (codeSign)
#endif
m_BinEncoder.encodeBinEP( (verMvd < 0) );
}
}
#endif
#if JVET_Z0131_IBC_BVD_BINARIZATION
#if JVET_AC0104_IBC_BVD_PREDICTION
unsigned CABACWriter::xWriteBvdContextPrefix(unsigned uiSymbol, unsigned ctxT, int offset, int param )
{
unsigned bins = 0;
unsigned numBins = 0;
while (uiSymbol >= (unsigned)(1 << param))
{
bins <<= 1;
bins++;
numBins++;
uiSymbol -= 1 << param;
param++;
}
bins <<= 1;
numBins++;
unsigned temp = 0;
unsigned bitCount = 0;
for (int i = numBins - 1; i >= 0; i--)
{
temp = bins >> i;
if (bitCount >= ctxT)
{
m_BinEncoder.encodeBinEP(temp);
}
else
{
m_BinEncoder.encodeBin(temp, Ctx::Bvd(offset + bitCount + 1));
}
bins -= (temp << i);
bitCount++;
}
return numBins - 1; // less by 1 as compared to what xReadBvdContextPrefix() returns
}
void CABACWriter::xWriteBvdContextSuffix(unsigned uiSymbol, int param, int paramUpdated, int numSkipMSB )
{
unsigned numBins = 0;
while (uiSymbol >= (unsigned) (1 << param))
{
numBins++;
uiSymbol -= 1 << param;
param++;
}
numBins++;
paramUpdated++;
CHECK(paramUpdated != numBins, "Enc side prefix bits check error");
if (0 != numSkipMSB)
{
CHECK(paramUpdated == 0, "paramUpdated = 0");
paramUpdated-= numSkipMSB;
unsigned skipMask = ( 1 << (paramUpdated + numSkipMSB)) -1 - ((1 << (paramUpdated)) - 1);
uiSymbol &= ~skipMask;
CHECK(uiSymbol >= (1 << paramUpdated), "uiSymbol >= (1<<paramUpdated)");
}
if (paramUpdated > 0)
{
CHECK(uiSymbol >= (1 << (paramUpdated+1)), "uiSymbol >= (1<<paramUpdated)");
m_BinEncoder.encodeBinsEP(uiSymbol, paramUpdated);
}
}
#endif
void CABACWriter::xWriteBvdContext(unsigned uiSymbol, unsigned ctxT, int offset, int param)
{
unsigned bins = 0;
unsigned numBins = 0;
while (uiSymbol >= (unsigned)(1 << param))
{
bins <<= 1;
bins++;
numBins++;
uiSymbol -= 1 << param;
param++;
}
bins <<= 1;
numBins++;
unsigned temp = 0;
unsigned bitCount = 0;
for (int i = numBins-1; i >=0 ; i--)
{
temp = bins>>i;
if (bitCount >= ctxT)
{
m_BinEncoder.encodeBinEP(temp);
}
else
{
m_BinEncoder.encodeBin(temp, Ctx::Bvd(offset + bitCount + 1));
}
bins -= (temp << i);
bitCount++;
}
m_BinEncoder.encodeBinsEP(uiSymbol, param);
}
#endif
#if JVET_AC0104_IBC_BVD_PREDICTION
void CABACWriter::bvdCodingRemainder(const Mv& rMvd, const MvdSuffixInfo& si, int8_t imv )
{
int horAbs = rMvd.getAbsHor();
int verAbs = rMvd.getAbsVer();
const unsigned int horOffsetPrediction = si.horOffsetPrediction;
const unsigned int verOffsetPrediction = si.verOffsetPrediction;
const int horParam = si.horPrefix;
const int verParam = si.verPrefix;
if (horParam >= 0 || verParam >= 0)
{
const int iHorMSBins = si.horOffsetPredictionNumBins;
const int iVerMSBins = si.verOffsetPredictionNumBins;
if (horParam >= 0)
{
for (int i = iHorMSBins - 1; i >= 0; --i)
{
const int bin = (horOffsetPrediction >> i) & 1;
const int prev2Bin = (i + 1 > iHorMSBins - 1) ? -1 :
(i + 1 == iHorMSBins - 1) ? si.horSignHypMatch :
/*otherwise*/ (horOffsetPrediction>> (i + 2)) & 1;
const int prevBin = (i == iHorMSBins - 1) ? si.horSignHypMatch : ((horOffsetPrediction >> (i+1)) & 1);
const int imvShift = Mv::getImvPrecShift(imv
#if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
, si.isFracBvEnabled
#endif
);
const int iCtxIdx = DeriveCtx::CtxSmBvdBin(prev2Bin, prevBin, true, i + imvShift);
const unsigned int ctx = Ctx::MvsdIdxBVDMSB(iCtxIdx);
m_BinEncoder.encodeBin((0 == bin) ? 1 : 0, ctx);
}
xWriteBvdContextSuffix(horAbs - 1, BVD_CODING_GOLOMB_ORDER, horParam, iHorMSBins );
}
if (verParam >= 0)
{
for (int i = iVerMSBins - 1; i >= 0; --i)
{
const int bin = (verOffsetPrediction >> i) & 1;
const int prev2Bin = (i + 1 > iVerMSBins - 1) ? -1 :
(i + 1 == iVerMSBins - 1) ? si.verSignHypMatch :
/*otherwise*/ (verOffsetPrediction>> (i + 2)) & 1;
const int prevBin = (i == iVerMSBins - 1) ? si.verSignHypMatch : ((verOffsetPrediction>>(i+1)) & 1);
const int imvShift = Mv::getImvPrecShift(imv
#if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
, si.isFracBvEnabled
#endif
);
const int iCtxIdx = DeriveCtx::CtxSmBvdBin(prev2Bin, prevBin, false, i + imvShift);
const unsigned int ctx = Ctx::MvsdIdxBVDMSB(iCtxIdx);
m_BinEncoder.encodeBin((0 == bin) ? 1 : 0, ctx);
}
xWriteBvdContextSuffix(verAbs - 1, BVD_CODING_GOLOMB_ORDER, verParam, iVerMSBins);
}
}
else
{
if (horAbs != 0)
{
xWriteBvdContextSuffix(horAbs - 1, BVD_CODING_GOLOMB_ORDER, horParam, 0 );
}
if (verAbs != 0)
{
xWriteBvdContextSuffix(verAbs - 1, BVD_CODING_GOLOMB_ORDER, verParam, 0 );
}
}
}
#endif
#if JVET_Z0131_IBC_BVD_BINARIZATION
#if JVET_AA0070_RRIBC
#if JVET_AC0104_IBC_BVD_PREDICTION
#if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
void CABACWriter::bvdCoding(const Mv &rMvd, const bool useBvdPred, const bool useBvpCluster, int bvOneZeroComp,
int bvZeroCompDir, const int &rribcFlipType)
#else
void CABACWriter::bvdCoding(const Mv& rMvd, const bool useBvdPred, const int& rribcFlipType)
#endif
#else
#if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
void CABACWriter::bvdCoding(const Mv &rMvd, const bool useBvpCluster, int bvOneZeroComp, int bvZeroCompDir,
const int &rribcFlipType)
#else
void CABACWriter::bvdCoding(const Mv& rMvd, const int& rribcFlipType)
#endif
#endif
#else
#if JVET_AC0104_IBC_BVD_PREDICTION
#if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
void CABACWriter::bvdCoding(const Mv &rMvd, const bool useBvdPred, const bool useBvpCluster, int bvOneZeroComp,
int bvZeroCompDir)
#else
void CABACWriter::bvdCoding(const Mv& rMvd, const bool useBvdPred)
#endif
#else
#if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
void CABACWriter::bvdCoding(const Mv &rMvd, const bool useBvpCluster, int bvOneZeroComp, int bvZeroCompDir)
#else
void CABACWriter::bvdCoding(const Mv& rMvd)
#endif
#endif
#endif
{
int horMvd = rMvd.getHor();
int verMvd = rMvd.getVer();
unsigned horAbs = unsigned( horMvd < 0 ? -horMvd : horMvd );
unsigned verAbs = unsigned( verMvd < 0 ? -verMvd : verMvd );
#if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
if (useBvpCluster)
{
if (bvOneZeroComp)
{
if (bvZeroCompDir == 1)
{
m_BinEncoder.encodeBin((horAbs > 0), Ctx::Bvd(HOR_BVD_CTX_OFFSET));
}
if (bvZeroCompDir == 2)
{
m_BinEncoder.encodeBin((verAbs > 0), Ctx::Bvd(VER_BVD_CTX_OFFSET));
}
}
else
{
m_BinEncoder.encodeBin((horAbs > 0), Ctx::Bvd(HOR_BVD_CTX_OFFSET));
m_BinEncoder.encodeBin((verAbs > 0), Ctx::Bvd(VER_BVD_CTX_OFFSET));
}
}
else
{
#if JVET_AA0070_RRIBC
if (rribcFlipType != 2)
{
m_BinEncoder.encodeBin((horAbs > 0), Ctx::Bvd(HOR_BVD_CTX_OFFSET));
}
if (rribcFlipType != 1)
{
m_BinEncoder.encodeBin((verAbs > 0), Ctx::Bvd(VER_BVD_CTX_OFFSET));
}
#else
m_BinEncoder.encodeBin((horAbs > 0), Ctx::Bvd(HOR_BVD_CTX_OFFSET));
m_BinEncoder.encodeBin((verAbs > 0), Ctx::Bvd(VER_BVD_CTX_OFFSET));
#endif
}
#else
#if JVET_AA0070_RRIBC
if (rribcFlipType != 2)
{
m_BinEncoder.encodeBin((horAbs > 0), Ctx::Bvd(HOR_BVD_CTX_OFFSET));
}
if (rribcFlipType != 1)
{
m_BinEncoder.encodeBin((verAbs > 0), Ctx::Bvd(VER_BVD_CTX_OFFSET));
}
#else
m_BinEncoder.encodeBin( (horAbs > 0), Ctx::Bvd(HOR_BVD_CTX_OFFSET) );
m_BinEncoder.encodeBin( (verAbs > 0), Ctx::Bvd(VER_BVD_CTX_OFFSET) );
#endif
#endif
#if JVET_AC0104_IBC_BVD_PREDICTION
if (useBvdPred)
{
if (horAbs)
{
xWriteBvdContextPrefix(horAbs - 1, NUM_HOR_BVD_CTX, HOR_BVD_CTX_OFFSET, BVD_CODING_GOLOMB_ORDER);
}
if (verAbs)
{
xWriteBvdContextPrefix(verAbs - 1, NUM_VER_BVD_CTX, VER_BVD_CTX_OFFSET, BVD_CODING_GOLOMB_ORDER);
}
}
else
{
#endif
if (horAbs > 0)
{
xWriteBvdContext(horAbs - 1, NUM_HOR_BVD_CTX, HOR_BVD_CTX_OFFSET, BVD_CODING_GOLOMB_ORDER);
#if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV && JVET_AA0070_RRIBC
if (useBvpCluster)
{
if (!bvOneZeroComp) // not send the sign
{
m_BinEncoder.encodeBinEP((horMvd < 0));
}
}
else
{
m_BinEncoder.encodeBinEP((horMvd < 0));
}
#else
m_BinEncoder.encodeBinEP((horMvd < 0));
#endif
}
if (verAbs > 0)
{
xWriteBvdContext(verAbs - 1, NUM_VER_BVD_CTX, VER_BVD_CTX_OFFSET, BVD_CODING_GOLOMB_ORDER);
#if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV && JVET_AA0070_RRIBC
if (useBvpCluster)
{
if (!bvOneZeroComp) // not send the sign
{
m_BinEncoder.encodeBinEP((verMvd < 0));
}
}
else
{
m_BinEncoder.encodeBinEP((verMvd < 0));
}
#else
m_BinEncoder.encodeBinEP((verMvd < 0));
#endif
}
#if JVET_AC0104_IBC_BVD_PREDICTION
}
#endif
}
#endif
#if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED || JVET_AC0104_IBC_BVD_PREDICTION
void CABACWriter::mvsdIdxFunc(const PredictionUnit &pu, RefPicList eRefList)
{
#if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
if (!pu.isMvdPredApplicable())
{
return;
}
#endif
#if JVET_AC0104_IBC_BVD_PREDICTION
if (CU::isIBC(*pu.cu) && !pu.isBvdPredApplicable())
{
return;
}
#endif
if (pu.cu->cs->picHeader->getMvdL1ZeroFlag() && eRefList == REF_PIC_LIST_1 && pu.interDir == 3)
{
return;
}
if (pu.cu->smvdMode && eRefList == REF_PIC_LIST_1)
{
return;
}
#if JVET_Z0054_BLK_REF_PIC_REORDER && !JVET_AD0140_MVD_PREDICTION
if (PU::useRefPairList(pu))
{
if (pu.interDir == 3 && eRefList == REF_PIC_LIST_1 && (pu.mvd[0].getHor() || pu.mvd[0].getVer()))
{
if (pu.mvd[eRefList].getHor())
{
m_BinEncoder.encodeBinEP(pu.mvd[eRefList].getHor() < 0);
}
if (pu.mvd[eRefList].getVer())
{
m_BinEncoder.encodeBinEP(pu.mvd[eRefList].getVer() < 0);
}
return;
}
}
#endif
Mv trMv = Mv(pu.mvd[eRefList].getAbsHor(), pu.mvd[eRefList].getAbsVer());
int Thres = THRES_TRANS;
int mvsdIdx = pu.mvsdIdx[eRefList];
#if !JVET_AD0140_MVD_PREDICTION
#if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV && JVET_AA0070_RRIBC
if (pu.isBvpClusterApplicable())
{
if (trMv != Mv(0, 0) && pu.cu->rribcFlipType == 0)
{
CHECK(mvsdIdx == -1, "mvsdIdx == -1 for transMv");
}
}
else
{
if (trMv != Mv(0, 0))
{
CHECK(mvsdIdx == -1, "mvsdIdx == -1 for transMv");
}
}
#else
if (trMv != Mv(0, 0))
{
CHECK(mvsdIdx == -1, "mvsdIdx == -1 for transMv");
}
#endif
#endif
#if JVET_AC0104_IBC_BVD_PREDICTION
if (CU::isIBC(*pu.cu))
{
Mv mvd = pu.mvd[eRefList];
mvd.changeIbcPrecInternal2Amvr(pu.cu->imv);
MvdSuffixInfo si = pu.bvdSuffixInfo;
#if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
si.isFracBvEnabled = pu.cs->sps->getIBCFracFlag();
#endif
si.initPrefixes(mvd, pu.cu->imv, false);
if (si.horPrefix >= 0)
{
CHECK(si.horOffsetPredictionNumBins != pu.bvdSuffixInfo.horOffsetPredictionNumBins, "mismatch in RDO and writing");
CHECK(si.horPrefix != pu.bvdSuffixInfo.horPrefix, "mismatch in RDO and writing");
}
if (si.verPrefix >= 0)
{
CHECK(si.verPrefix != pu.bvdSuffixInfo.verPrefix, "mismatch in RDO and writing");
CHECK(si.verOffsetPredictionNumBins != pu.bvdSuffixInfo.verOffsetPredictionNumBins, "mismatch in RDO and writing");
}
int horPrefix = si.horPrefix;
int verPrefix = si.verPrefix;
si.horSignHypMatch = -1;
si.verSignHypMatch = -1;
if (horPrefix < 0 && verPrefix < 0)
{
return;
}
Mv trMv = Mv(horPrefix < 0 ? 0 : MvdSuffixInfo::xGetGolombGroupMinValue(horPrefix),
verPrefix < 0 ? 0 : MvdSuffixInfo::xGetGolombGroupMinValue(verPrefix));
trMv.changeTransPrecAmvr2Internal(pu.cu->imv);
#if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV && JVET_AA0070_RRIBC
if (0 != pu.cu->rribcFlipType && pu.isBvpClusterApplicable())
{
bvdCodingRemainder(mvd, si, pu.cu->imv);
return;
}
#endif
if (pu.mvd[eRefList].getHor())
{
if (pu.bvdSuffixInfo.horEncodeSignInEP)
{
unsigned bin = pu.mvd[eRefList].getHor() < 0 ? 1 : 0;
m_BinEncoder.encodeBinEP(bin);
}
else
{
uint8_t ctxId = (trMv.getHor() <= Thres) ? 0 : 1;
int bin = mvsdIdx & 1;
#if JVET_AD0140_MVD_PREDICTION
m_BinEncoder.encodeBin(bin, Ctx::MvsdIdxIBC(ctxId));
#else
m_BinEncoder.encodeBin(bin, Ctx::MvsdIdx(ctxId));
#endif
si.horSignHypMatch = 0 == bin;
mvsdIdx >>= 1;
}
} // if (pu.mvd[eRefList].getHor())
if (pu.mvd[eRefList].getVer())
{
if (pu.bvdSuffixInfo.verEncodeSignInEP)
{
unsigned bin = pu.mvd[eRefList].getVer() < 0 ? 1 : 0;
m_BinEncoder.encodeBinEP(bin);
}
else
{
uint8_t ctxId = (trMv.getVer() <= Thres) ? 0 : 1;
int bin = mvsdIdx & 1;
#if JVET_AD0140_MVD_PREDICTION
m_BinEncoder.encodeBin(bin, Ctx::MvsdIdxIBC(ctxId));
#else
m_BinEncoder.encodeBin(bin, Ctx::MvsdIdx(ctxId));
#endif
si.verSignHypMatch = 0 == bin;
mvsdIdx >>= 1;
}
} // if (pu.mvd[eRefList].getVer())
bvdCodingRemainder(mvd, si, pu.cu->imv );
return;
}
#endif
#if JVET_AD0140_MVD_PREDICTION
MvdSuffixInfo si = pu.mvdSuffixInfo.mvBins[eRefList][0];
const int horPrefix = si.horPrefix;
const int verPrefix = si.verPrefix;
trMv = Mv(horPrefix < 0 ? 0 : MvdSuffixInfo::xGetGolombGroupMinValue(horPrefix),
verPrefix < 0 ? 0 : MvdSuffixInfo::xGetGolombGroupMinValue(verPrefix));
trMv.changeTransPrecAmvr2Internal(pu.cu->imv);
if (pu.mvd[eRefList].getHor())
{
if( si.horEncodeSignInEP )
{
unsigned bin = pu.mvd[eRefList].getHor() < 0 ? 1 : 0;
m_BinEncoder.encodeBinEP( bin );
}
else
{
uint8_t ctxId = ( trMv.getHor() <= Thres ) ? 0 : 1;
int bin = mvsdIdx & 1;
m_BinEncoder.encodeBin( bin, Ctx::MvsdIdx( ctxId ) );
DTRACE( g_trace_ctx, D_SYNTAX, "mvsd hor: bin=%d, ctx=%d \n", bin, ctxId );
mvsdIdx >>= 1;
}
}
if (pu.mvd[eRefList].getVer())
{
if( si.verEncodeSignInEP )
{
unsigned bin = pu.mvd[eRefList].getVer() < 0 ? 1 : 0;
m_BinEncoder.encodeBinEP( bin );
}
else
{
uint8_t ctxId = ( trMv.getVer() <= Thres ) ? 0 : 1;
int bin = mvsdIdx & 1;
m_BinEncoder.encodeBin( bin, Ctx::MvsdIdx( ctxId ) );
DTRACE( g_trace_ctx, D_SYNTAX, "mvsd ver: bin=%d, ctx=%d \n", bin, ctxId );
mvsdIdx >>= 1;
}
}
if (eRefList == REF_PIC_LIST_1 || pu.interDir == 1
|| (pu.cu->cs->picHeader->getMvdL1ZeroFlag() && eRefList == REF_PIC_LIST_0 && pu.interDir == 3)
|| pu.cu->smvdMode
)
{
bool writeL0Suffixes = pu.interDir != 2;
bool writeL1Suffixes = pu.interDir != 1 && !( pu.cu->cs->picHeader->getMvdL1ZeroFlag() && pu.interDir == 3 );
if( pu.cu->smvdMode )
{
CHECK( pu.interDir != 3, "SMVD mode should be B-prediction" );
writeL0Suffixes &= ( eRefList == 0 );
writeL1Suffixes = false; // &= (eRefList == 1);
const int maxNumBins = MvdSuffixInfoMv::getBinBudgetForPrediction( pu.Y().width, pu.Y().height, pu.cu->imv );
const auto& si = pu.mvdSuffixInfo.mvBins[0][0];
CHECK( si.getNumBinsOfSignsAndSuffixes() > maxNumBins, "Bin budget exceeded" );
}
for( int i = REF_PIC_LIST_0; i < NUM_REF_PIC_LIST_01; ++i ) // read MVD suffixes
{
Mv mvd = pu.mvd[i];
mvd.changeTransPrecInternal2Amvr( pu.cu->imv );
if( ( i == 0 && !writeL0Suffixes ) || ( i == 1 && !writeL1Suffixes ) || ( !mvd.getHor() && !mvd.getVer() ) )
{
continue;
}
MvdSuffixInfoMv currSI = pu.mvdSuffixInfo;
int verPrefix = currSI.mvBins[i][0].verPrefix;
int horPrefix = currSI.mvBins[i][0].horPrefix;
CHECK( 0 > currSI.actualMvCompNum[i], "Uninitialized suffix info" );
if( horPrefix >= 0 || verPrefix >= 0 )
{
mvdCodingRemainder( mvd, currSI.mvBins[i][0], pu.cu->imv );
}
}
}
else
{
Mv mvd = pu.mvd[eRefList];
mvd.changeTransPrecInternal2Amvr( pu.cu->imv );
}
#elif JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
if (pu.mvd[eRefList].getHor())
{
uint8_t ctxId = (trMv.getHor() <= Thres) ? 0 : 1;
int bin = mvsdIdx & 1;
m_BinEncoder.encodeBin(bin, Ctx::MvsdIdx(ctxId));
mvsdIdx >>= 1;
}
if (pu.mvd[eRefList].getVer())
{
uint8_t ctxId = (trMv.getVer() <= Thres) ? 0 : 1;
int bin = mvsdIdx & 1;
m_BinEncoder.encodeBin(bin, Ctx::MvsdIdx(ctxId));
mvsdIdx >>= 1;
}
#endif
}
#endif
#if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
void CABACWriter::mvsdAffineIdxFunc(const PredictionUnit &pu, RefPicList eRefList)
{
if (!pu.cu->affine)
{
return;
}
if (!pu.isMvdPredApplicable())
{
return;
}
if (pu.cu->cs->picHeader->getMvdL1ZeroFlag() && eRefList == REF_PIC_LIST_1 && pu.interDir == 3)
{
return;
}
#if JVET_Z0054_BLK_REF_PIC_REORDER && !JVET_AD0140_MVD_PREDICTION
if (PU::useRefPairList(pu))
{
if (pu.interDir == 3 && eRefList == REF_PIC_LIST_1 &&
(pu.mvdAffi[0][0].getHor() || pu.mvdAffi[0][0].getVer() ||
pu.mvdAffi[0][1].getHor() || pu.mvdAffi[0][1].getVer() ||
(pu.cu->affineType == AFFINEMODEL_6PARAM && (pu.mvdAffi[0][2].getHor() || pu.mvdAffi[0][2].getVer()))
)
)
{
if (pu.mvdAffi[eRefList][0].getHor())
{
m_BinEncoder.encodeBinEP(pu.mvdAffi[eRefList][0].getHor() < 0);
}
if (pu.mvdAffi[eRefList][0].getVer())
{
m_BinEncoder.encodeBinEP(pu.mvdAffi[eRefList][0].getVer() < 0);
}
if (pu.mvdAffi[eRefList][1].getHor())
{
m_BinEncoder.encodeBinEP(pu.mvdAffi[eRefList][1].getHor() < 0);
}
if (pu.mvdAffi[eRefList][1].getVer())
{
m_BinEncoder.encodeBinEP(pu.mvdAffi[eRefList][1].getVer() < 0);
}
if (pu.cu->affineType == AFFINEMODEL_6PARAM)
{
if (pu.mvdAffi[eRefList][2].getHor())
{
m_BinEncoder.encodeBinEP(pu.mvdAffi[eRefList][2].getHor() < 0);
}
if (pu.mvdAffi[eRefList][2].getVer())
{
m_BinEncoder.encodeBinEP(pu.mvdAffi[eRefList][2].getVer() < 0);
}
}
return;
}
}
#endif
Mv AffMv[3];
AffMv[0] = Mv(pu.mvdAffi[eRefList][0].getAbsHor(), pu.mvdAffi[eRefList][0].getAbsVer());
AffMv[1] = Mv(pu.mvdAffi[eRefList][1].getAbsHor(), pu.mvdAffi[eRefList][1].getAbsVer());
AffMv[2] = Mv(pu.mvdAffi[eRefList][2].getAbsHor(), pu.mvdAffi[eRefList][2].getAbsVer());
int Thres = THRES_AFFINE;
int mvsdIdx = pu.mvsdIdx[eRefList];
#if JVET_AD0140_MVD_PREDICTION
const int numAffinesInRpl = 2 + (pu.cu->affineType == AFFINEMODEL_6PARAM);
for (int i = 0; i < numAffinesInRpl; ++i)
{
MvdSuffixInfo si = pu.mvdSuffixInfo.mvBins[eRefList][i]; //create modifiable copy
// get signs
const int horPrefix = si.horPrefix;
const int verPrefix = si.verPrefix;
Mv TrMv = Mv(horPrefix < 0 ? 0 : MvdSuffixInfo::xGetGolombGroupMinValue(horPrefix),
verPrefix < 0 ? 0 : MvdSuffixInfo::xGetGolombGroupMinValue(verPrefix));
TrMv.changeAffinePrecAmvr2Internal(pu.cu->imv);
if (pu.mvdAffi[eRefList][i].getHor())
{
if (si.horEncodeSignInEP)
{
unsigned bin = pu.mvdAffi[eRefList][i].getHor() < 0 ? 1 : 0;
m_BinEncoder.encodeBinEP(bin);
}
else
{
uint8_t ctxId = (TrMv.getHor() <= Thres) ? 2 : 3;
int bin = mvsdIdx & 1;
m_BinEncoder.encodeBin(bin, Ctx::MvsdIdx(ctxId));
mvsdIdx >>= 1;
}
}
if (pu.mvdAffi[eRefList][i].getVer())
{
if (si.verEncodeSignInEP)
{
unsigned bin = pu.mvdAffi[eRefList][i].getVer() < 0 ? 1 : 0;
m_BinEncoder.encodeBinEP(bin);
}
else
{
uint8_t ctxId = (TrMv.getVer() <= Thres) ? 2 : 3;
int bin = mvsdIdx & 1;
m_BinEncoder.encodeBin(bin, Ctx::MvsdIdx(ctxId));
mvsdIdx >>= 1;
}
}
}
// calc and write suffix bins
if (eRefList == REF_PIC_LIST_1 || pu.interDir == 1
|| (pu.cu->cs->picHeader->getMvdL1ZeroFlag() && eRefList == REF_PIC_LIST_0 && pu.interDir == 3)) // current RPL = L1 or there is only L0: now we can specify num of predicted suffix bins
{
bool writeL0Suffixes = pu.interDir != 2;
bool writeL1Suffixes = pu.interDir != 1 && !(pu.cu->cs->picHeader->getMvdL1ZeroFlag() && pu.interDir == 3);
// write suffixes
for (int i = REF_PIC_LIST_0; i < NUM_REF_PIC_LIST_01; ++i) // read MVD suffixes
{
for (int j = 0; j < numAffinesInRpl; ++j)
{
Mv mvdAffine = pu.mvdAffi[i][j];
mvdAffine.changeAffinePrecInternal2Amvr(pu.cu->imv);
if ((i == 0 && !writeL0Suffixes) || (i == 1 && !writeL1Suffixes) || (!mvdAffine.getHor() && !mvdAffine.getVer()))
{
continue;
}
auto si = pu.mvdSuffixInfo.mvBins[i][j];
int verPrefix = si.verPrefix;
int horPrefix = si.horPrefix;
if (horPrefix >= 0 || verPrefix >= 0)
{
mvdCodingRemainder(mvdAffine, si, pu.cu->imv);
}
}
}
}
#else
if (AffMv[0] != Mv(0, 0) || AffMv[1] != Mv(0, 0) || (pu.cu->affineType == AFFINEMODEL_6PARAM && AffMv[2] != Mv(0, 0)))
{
CHECK(mvsdIdx == -1, "mvsdIdx == -1 for AffineMv");
}
if (pu.mvdAffi[eRefList][0].getHor())
{
uint8_t ctxId = (AffMv[0].getHor() <= Thres) ? 2 : 3;
int bin = mvsdIdx & 1;
m_BinEncoder.encodeBin(bin, Ctx::MvsdIdx(ctxId));
mvsdIdx >>= 1;
}
if (pu.mvdAffi[eRefList][0].getVer())
{
uint8_t ctxId = (AffMv[0].getVer() <= Thres) ? 2 : 3;
int bin = mvsdIdx & 1;
m_BinEncoder.encodeBin(bin, Ctx::MvsdIdx(ctxId));
mvsdIdx >>= 1;
}
if (pu.mvdAffi[eRefList][1].getHor())
{
uint8_t ctxId = (AffMv[1].getHor() <= Thres) ? 2 : 3;
int bin = mvsdIdx & 1;
m_BinEncoder.encodeBin(bin, Ctx::MvsdIdx(ctxId));
mvsdIdx >>= 1;
}
if (pu.mvdAffi[eRefList][1].getVer())
{
uint8_t ctxId = (AffMv[1].getVer() <= Thres) ? 2 : 3;
int bin = mvsdIdx & 1;
m_BinEncoder.encodeBin(bin, Ctx::MvsdIdx(ctxId));
mvsdIdx >>= 1;
}
if (pu.cu->affineType == AFFINEMODEL_6PARAM)
{
if (pu.mvdAffi[eRefList][2].getHor())
{
uint8_t ctxId = (AffMv[2].getHor() <= Thres) ? 2 : 3;
int bin = mvsdIdx & 1;
m_BinEncoder.encodeBin(bin, Ctx::MvsdIdx(ctxId));
mvsdIdx >>= 1;
}
if (pu.mvdAffi[eRefList][2].getVer())
{
uint8_t ctxId = (AffMv[2].getVer() <= Thres) ? 2 : 3;
int bin = mvsdIdx & 1;
m_BinEncoder.encodeBin(bin, Ctx::MvsdIdx(ctxId));
mvsdIdx >>= 1;
}
}
#endif
DTRACE(g_trace_ctx, D_SYNTAX, "mvsd_affine_idx_func() mvsdIdx=%d\n", pu.mvsdIdx[eRefList]); // eRefList can have enc-dec mismatch
}
#endif
//================================================================================
// clause 7.3.8.10
//--------------------------------------------------------------------------------
// void transform_unit ( tu, cuCtx, chromaCbfs )
// void cu_qp_delta ( cu )
// void cu_chroma_qp_offset ( cu )
//================================================================================
void CABACWriter::transform_unit(const TransformUnit& tu, CUCtx& cuCtx, Partitioner& partitioner, const int subTuCounter
#if JVET_AE0102_LFNST_CTX
, const bool codeTuCoeff
#endif
)
{
const CodingStructure& cs = *tu.cs;
const CodingUnit& cu = *tu.cu;
const UnitArea& area = partitioner.currArea();
const unsigned trDepth = partitioner.currTrDepth;
ChromaCbfs chromaCbfs;
#if JVET_AE0102_LFNST_CTX
if ( codeTuCoeff == false )
{
#endif
CHECK(tu.depth != trDepth, " transform unit should be not be futher partitioned");
// cbf_cb & cbf_cr
if (area.chromaFormat != CHROMA_400)
{
const bool chromaCbfISP = area.blocks[COMPONENT_Cb].valid() && cu.ispMode;
#if INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS
if (area.blocks[COMPONENT_Cb].valid() && (!CS::isDualITree(cs) || partitioner.chType == CHANNEL_TYPE_CHROMA) && (!cu.ispMode || chromaCbfISP))
#else
if (area.blocks[COMPONENT_Cb].valid() && (!cu.isSepTree() || partitioner.chType == CHANNEL_TYPE_CHROMA) && (!cu.ispMode || chromaCbfISP))
#endif
{
unsigned cbfDepth = chromaCbfISP ? trDepth - 1 : trDepth;
{
chromaCbfs.Cb = TU::getCbfAtDepth( tu, COMPONENT_Cb, trDepth );
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 && tu.noResidual) )
{
cbf_comp( cs, chromaCbfs.Cr, area.blocks[COMPONENT_Cr], cbfDepth, chromaCbfs.Cb );
}
}
}
#if INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS
else if (CS::isDualITree(cs))
#else
else if (cu.isSepTree())
#endif
{
chromaCbfs = ChromaCbfs(false);
}
}
#if INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS
else if (CS::isDualITree(cs))
#else
else if (cu.isSepTree())
#endif
{
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 lumaCbfIsInferredACT = (cu.colorTransform && cu.predMode == MODE_INTRA && trDepth == 0 && !chromaCbfs.sigChroma(area.chromaFormat));
CHECK(lumaCbfIsInferredACT && !TU::getCbfAtDepth(tu, COMPONENT_Y, trDepth), "adaptive color transform cannot have all zero coefficients");
bool lastCbfIsInferred = lumaCbfIsInferredACT; // ISP and ACT are mutually exclusive
bool previousCbf = false;
bool rootCbfSoFar = false;
if (cu.ispMode)
{
uint32_t nTus = cu.ispMode == HOR_INTRA_SUBPARTITIONS ? cu.lheight() >> floorLog2(tu.lheight()) : cu.lwidth() >> floorLog2(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);
}
}
}
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;
if (!lumaOnly)
{
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]);
}
#if TU_256
if ((cu.lwidth() > MAX_TB_SIZEY || cu.lheight() > MAX_TB_SIZEY || cbfLuma || cbfChroma) &&
#else
if ((cu.lwidth() > 64 || cu.lheight() > 64 || cbfLuma || cbfChroma) &&
#endif
#if INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS
(!CS::isDualITree(*tu.cs) || isLuma(tu.chType)))
#else
(!tu.cu->isSepTree() || isLuma(tu.chType)))
#endif
{
if (cu.cs->pps->getUseDQP() && !cuCtx.isDQPCoded)
{
cu_qp_delta(cu, cuCtx.qp, cu.qp);
cuCtx.qp = cu.qp;
cuCtx.isDQPCoded = true;
}
}
#if INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS
if (!CS::isDualITree(*tu.cs) || isChroma(tu.chType)) // !DUAL_TREE_LUMA
#else
if (!cu.isSepTree() || isChroma(tu.chType)) // !DUAL_TREE_LUMA
#endif
{
#if INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS
SizeType channelWidth = !CS::isDualITree(*tu.cs) ? cu.lwidth() : cu.chromaSize().width;
SizeType channelHeight = !CS::isDualITree(*tu.cs) ? cu.lheight() : cu.chromaSize().height;
#else
SizeType channelWidth = !cu.isSepTree() ? cu.lwidth() : cu.chromaSize().width;
SizeType channelHeight = !cu.isSepTree() ? cu.lheight() : cu.chromaSize().height;
#endif
#if TU_256
if (cu.cs->slice->getUseChromaQpAdj() && (channelWidth > MAX_TB_SIZEY || channelHeight > MAX_TB_SIZEY || cbfChroma) && !cuCtx.isChromaQpAdjCoded)
#else
if (cu.cs->slice->getUseChromaQpAdj() && (channelWidth > 64 || channelHeight > 64 || cbfChroma) && !cuCtx.isChromaQpAdjCoded)
#endif
{
cu_chroma_qp_offset(cu);
cuCtx.isChromaQpAdjCoded = true;
}
}
#if JVET_AF0073_INTER_CCP_MERGE
if ( !lumaOnly )
{
interCcpMerge( tu );
}
#endif
#if JVET_AE0059_INTER_CCCM
if ( !lumaOnly )
{
interCccm( tu );
}
#endif
if( !lumaOnly )
{
joint_cb_cr( tu, ( cbf[COMPONENT_Cb] ? 2 : 0 ) + ( cbf[COMPONENT_Cr] ? 1 : 0 ) );
}
#if JVET_AE0102_LFNST_CTX
}
#endif
#if JVET_AE0102_LFNST_CTX
if ( TU::getCbf(tu, COMPONENT_Y) != 0 )
#else
if( cbfLuma )
#endif
{
residual_coding( tu, COMPONENT_Y, &cuCtx
#if JVET_AE0102_LFNST_CTX
, codeTuCoeff
#endif
);
}
#if JVET_AE0102_LFNST_CTX
if ( !(cu.chromaFormat == CHROMA_400 || !tu.blocks[COMPONENT_Cb].valid()))
#else
if( !lumaOnly )
#endif
{
for( ComponentID compID = COMPONENT_Cb; compID <= COMPONENT_Cr; compID = ComponentID( compID + 1 ) )
{
#if JVET_AE0102_LFNST_CTX
if ( TU::getCbf(tu, compID) )
#else
if( cbf[ compID ] )
#endif
{
residual_coding( tu, compID, &cuCtx
#if JVET_AE0102_LFNST_CTX
, codeTuCoeff
#endif
);
}
}
}
}
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->getChromaQpOffsetListLen();
if( length > 1 )
{
unary_max_symbol( qpAdj-1, Ctx::ChromaQpAdjIdc(), Ctx::ChromaQpAdjIdc(), length-1 );
}
}
DTRACE(g_trace_ctx, D_SYNTAX, "cu_chroma_qp_offset() chroma_qp_adj=%d\n", cu.chromaQpAdj);
}
//================================================================================
// clause 7.3.8.11
//--------------------------------------------------------------------------------
// void residual_coding ( tu, compID )
// void transform_skip_flag ( tu, compID )
// void last_sig_coeff ( coeffCtx )
// void residual_coding_subblock( coeffCtx )
//================================================================================
void CABACWriter::joint_cb_cr( const TransformUnit& tu, const int cbfMask )
{
if ( !tu.cu->slice->getSPS()->getJointCbCrEnabledFlag() )
{
return;
}
CHECK( tu.jointCbCr && tu.jointCbCr != cbfMask, "wrong value of jointCbCr (" << (int)tu.jointCbCr << " vs " << (int)cbfMask << ")" );
if( ( CU::isIntra( *tu.cu ) && cbfMask ) || ( cbfMask == 3 ) )
{
m_BinEncoder.encodeBin( tu.jointCbCr ? 1 : 0, Ctx::JointCbCrFlag( cbfMask - 1 ) );
}
}
void CABACWriter::residual_coding( const TransformUnit& tu, ComponentID compID, CUCtx* cuCtx
#if JVET_AE0102_LFNST_CTX
, const bool codeTuCoeff
#endif
)
{
const CodingUnit& cu = *tu.cu;
#if JVET_AE0102_LFNST_CTX
DTRACE( g_trace_ctx, D_SYNTAX, "residual_coding() codeTuCoeff=%d etype=%d pos=(%d,%d) size=%dx%d predMode=%d\n", codeTuCoeff, tu.blocks[compID].compID, tu.blocks[compID].x, tu.blocks[compID].y, tu.blocks[compID].width, tu.blocks[compID].height, cu.predMode );
#else
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 );
#endif
if( compID == COMPONENT_Cr && tu.jointCbCr == 3 )
return;
#if SIGN_PREDICTION
const bool signPredQualified = TU::getDelayedSignCoding(tu, compID);
#endif
#if JVET_AE0102_LFNST_CTX
if (codeTuCoeff == false)
{
#endif
ts_flag ( tu, compID );
#if JVET_AE0102_LFNST_CTX
}
#endif
if( tu.mtsIdx[compID] == MTS_SKIP && !tu.cs->slice->getTSResidualCodingDisabledFlag() )
{
#if JVET_AE0102_LFNST_CTX
if (!isEncoding())
{
#endif
residual_codingTS( tu, compID );
#if JVET_AE0102_LFNST_CTX
}
else
{
if (codeTuCoeff == true)
{
residual_codingTS(tu, compID);
}
}
#endif
return;
}
// determine sign hiding
bool signHiding = cu.cs->slice->getSignDataHidingEnabledFlag();
// 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 JVET_AE0102_LFNST_CTX
if (codeTuCoeff == false)
{
#endif
#if !EXTENDED_LFNST
if (cuCtx && tu.mtsIdx[compID] != MTS_SKIP && tu.blocks[compID].height >= 4 && tu.blocks[compID].width >= 4)
{
#if JVET_AC0130_NSPT
uint32_t width = tu.blocks[compID].width;
uint32_t height = tu.blocks[compID].height;
#if JVET_AH0103_LOW_DELAY_LFNST_NSPT
bool spsIntraLfnstEnabled = ( ( tu.cu->slice->getSliceType() == I_SLICE && tu.cu->cs->sps->getUseIntraLFNSTISlice() ) ||
( tu.cu->slice->getSliceType() != I_SLICE && tu.cu->cs->sps->getUseIntraLFNSTPBSlice() ) );
bool allowNSPT = CU::isNSPTAllowed( tu, compID, width, height, spsIntraLfnstEnabled && CU::isIntra( *( tu.cu ) ) );
#else
bool allowNSPT = CU::isNSPTAllowed(tu, compID, width, height, CU::isIntra(*(tu.cu)));
#endif
#if JVET_W0119_LFNST_EXTENSION
const int maxLfnstPos = (allowNSPT ? PU::getNSPTMatrixDim(width, height) : PU::getLFNSTMatrixDim(width, height)) - 1;
#else
const int maxLfnstPos = allowNSPT ? PU::getNSPTMatrixDim(width, height) - 1 : (((tu.blocks[compID].height == 4 && tu.blocks[compID].width == 4) || (tu.blocks[compID].height == 8 && tu.blocks[compID].width == 8)) ? 7 : 15);
#endif
#else
#if JVET_W0119_LFNST_EXTENSION
const int maxLfnstPos = PU::getLFNSTMatrixDim(tu.blocks[compID].width, tu.blocks[compID].height) - 1;
#else
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;
#endif
#endif
cuCtx->violatesLfnstConstrained[toChannelType(compID)] |= cctx.scanPosLast() > maxLfnstPos;
}
#endif
if (cuCtx && tu.mtsIdx[compID] != MTS_SKIP && tu.blocks[compID].height >= 4 && tu.blocks[compID].width >= 4)
{
#if JVET_AG0061_INTER_LFNST_NSPT
const int lfnstLastScanPosTh = isLuma( compID ) ? ( CU::isIntra( *( tu.cu ) ) ? LFNST_LAST_SIG_LUMA : LFNST_LAST_SIG_LUMA_INTER ) : LFNST_LAST_SIG_CHROMA;
cuCtx->lfnstLastScanPos |= ( CU::isIntra( *( tu.cu ) ) || isLuma( compID ) ) ? ( cctx.scanPosLast() >= lfnstLastScanPosTh ) : false;
#else
const int lfnstLastScanPosTh = isLuma(compID) ? LFNST_LAST_SIG_LUMA : LFNST_LAST_SIG_CHROMA;
cuCtx->lfnstLastScanPos |= cctx.scanPosLast() >= lfnstLastScanPosTh;
#endif
}
if (cuCtx && isLuma(compID) && tu.mtsIdx[compID] != MTS_SKIP)
{
cuCtx->mtsLastScanPos |= cctx.scanPosLast() >= 1;
#if JVET_Y0142_ADAPT_INTRA_MTS
const int coeffStride = tu.getCoeffs(compID).stride;
const int uiWidth = tu.getCoeffs(compID).width;
const int uiHeight = tu.getCoeffs(compID).height;
uint64_t coeffAbsSum = 0;
for (int y = 0; y < uiHeight; y++)
{
for (int x = 0; x < uiWidth; x++)
{
coeffAbsSum += abs(coeff[(y * coeffStride) + x]);
}
}
cuCtx->mtsCoeffAbsSum = (int64_t)coeffAbsSum;
#endif
}
// code last coeff position
last_sig_coeff( cctx, tu, compID );
#if JVET_AE0102_LFNST_CTX
if ( isEncoding() && codeTuCoeff == false)
{
#if EXTENDED_LFNST
int subSetId = cctx.scanPosLast() >> cctx.log2CGSize();
cctx.initSubblock(subSetId);
if (cuCtx && tu.blocks[compID].width >= 4 && tu.blocks[compID].height >= 4)
{
const bool whge3 = tu.blocks[compID].width >= 8 && tu.blocks[compID].height >= 8;
const bool isLfnstViolated = whge3 ? ((cctx.cgPosY() > 1 || cctx.cgPosX() > 1)) : ( (cctx.cgPosY() > 0 || cctx.cgPosX() > 0));
cuCtx->violatesLfnstConstrained[toChannelType(compID)] |= isLfnstViolated;
}
#endif
return;
}
}
#endif
// code subblocks
#if TCQ_8STATES
const uint64_t stateTab = g_stateTransTab[ tu.cs->slice->getDepQuantEnabledIdc() ];
#else
const int stateTab = ( tu.cs->slice->getDepQuantEnabledFlag() ? 32040 : 0 );
#endif
int state = 0;
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;
for( int subSetId = ( cctx.scanPosLast() >> cctx.log2CGSize() ); subSetId >= 0; subSetId--)
{
cctx.initSubblock ( subSetId, sigGroupFlags[subSetId] );
#if !TU_256
if( tu.cs->sps->getUseMTS() && tu.cu->sbtInfo != 0 && tu.blocks[ compID ].height <= 32 && tu.blocks[ compID ].width <= 32 && 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;
}
}
#endif
#if JVET_AE0102_LFNST_CTX
int lfnstidx = (cuCtx != nullptr && !cuCtx->lfnstLastScanPos && !cu.ispMode) ? 0 : cu.lfnstIdx;
if (lfnstidx == 0 && cu.lfnstIdx != 0)
{
cctx.updateCtxSets();
}
residual_coding_subblock(cctx, coeff, stateTab, state, lfnstidx);
#else
residual_coding_subblock(cctx, coeff, stateTab, state);
#endif
#if !TU_256
if ( cuCtx && isLuma(compID) && cctx.isSigGroup() && ( cctx.cgPosY() > 3 || cctx.cgPosX() > 3 ) )
{
cuCtx->violatesMtsCoeffConstraint = true;
}
#endif
#if JVET_AE0102_LFNST_CTX
if ( !isEncoding() )
{
#endif
#if EXTENDED_LFNST
if (cuCtx && tu.blocks[compID].width >= 4 && tu.blocks[compID].height >= 4)
{
const bool whge3 = tu.blocks[compID].width >= 8 && tu.blocks[compID].height >= 8;
const bool isLfnstViolated = whge3 ? (cctx.isSigGroup() && (cctx.cgPosY() > 1 || cctx.cgPosX() > 1)) : (cctx.isSigGroup() && (cctx.cgPosY() > 0 || cctx.cgPosX() > 0));
cuCtx->violatesLfnstConstrained[toChannelType(compID)] |= isLfnstViolated;
}
#endif
#if JVET_AE0102_LFNST_CTX
}
#endif
}
#if SIGN_PREDICTION
if(signPredQualified && typeid(m_BinEncoder) == typeid(BitEstimator_Std))
{
bool codeSigns = true;
if(tu.jointCbCr)
{
if( (tu.jointCbCr>>1) && compID == COMPONENT_Cb )
{
codeSigns = true;
}
if( !(tu.jointCbCr>>1) && compID == COMPONENT_Cr)
{
codeSigns = true;
}
}
if(codeSigns)
{
codePredictedSigns(const_cast<TransformUnit &>(tu), compID);
}
}
#endif
}
void CABACWriter::ts_flag( const TransformUnit& tu, ComponentID compID )
{
int tsFlag = tu.mtsIdx[compID] == MTS_SKIP ? 1 : 0;
int ctxIdx = isLuma(compID) ? 0 : 1;
if( TU::isTSAllowed ( tu, compID ) )
{
m_BinEncoder.encodeBin( tsFlag, Ctx::TransformSkipFlag(ctxIdx));
}
DTRACE(g_trace_ctx, D_SYNTAX, "ts_flag() etype=%d pos=(%d,%d) mtsIdx=%d\n", COMPONENT_Y, tu.blocks[compID].x, tu.blocks[compID].y, tsFlag);
}
void CABACWriter::mts_idx( const CodingUnit& cu, CUCtx* cuCtx )
{
TransformUnit &tu = *cu.firstTU;
int mtsIdx = tu.mtsIdx[COMPONENT_Y];
if( CU::isMTSAllowed( cu, COMPONENT_Y ) && cuCtx && !cuCtx->violatesMtsCoeffConstraint &&
cuCtx->mtsLastScanPos && cu.lfnstIdx == 0 && mtsIdx != MTS_SKIP)
{
int symbol = mtsIdx != MTS_DCT2_DCT2 ? 1 : 0;
#if JVET_W0103_INTRA_MTS
#if JVET_Y0142_ADAPT_INTRA_MTS
#if JVET_Y0159_INTER_MTS
int ctxIdx = 0;
if (CU::isIntra(cu))
{
ctxIdx = (cuCtx->mtsCoeffAbsSum > MTS_TH_COEFF[1]) ? 2 : (cuCtx->mtsCoeffAbsSum > MTS_TH_COEFF[0]) ? 1 : 0;
}
#else
int ctxIdx = (cuCtx->mtsCoeffAbsSum > MTS_TH_COEFF[1]) ? 2 : (cuCtx->mtsCoeffAbsSum > MTS_TH_COEFF[0]) ? 1 : 0;
#endif
#else
int ctxIdx = (cu.mipFlag) ? 3 : 0;
#endif
#else
int ctxIdx = 0;
#endif
m_BinEncoder.encodeBin( symbol, Ctx::MTSIdx(ctxIdx));
if( symbol )
{
#if JVET_W0103_INTRA_MTS
int trIdx = (tu.mtsIdx[COMPONENT_Y] - MTS_DST7_DST7);
#if JVET_Y0142_ADAPT_INTRA_MTS
#if JVET_Y0159_INTER_MTS
int nCands = CU::isIntra(cu) ? MTS_NCANDS[ctxIdx] : 4;
#else
int nCands = MTS_NCANDS[ctxIdx];
#endif
if (trIdx < 0 || trIdx >= nCands)
{
//Don't do anything.
}
else
{
CHECK(trIdx < 0 || trIdx >= nCands, "trIdx outside range");
xWriteTruncBinCode(trIdx, nCands);
}
#else
CHECK(trIdx < 0 || trIdx >= 4, "trIdx outside range");
m_BinEncoder.encodeBin(trIdx >> 1, Ctx::MTSIdx(1));
m_BinEncoder.encodeBin(trIdx & 1, Ctx::MTSIdx(2));
#endif
#else
ctxIdx = 1;
for( int i = 0; i < 3; i++, ctxIdx++ )
{
symbol = mtsIdx > i + MTS_DST7_DST7 ? 1 : 0;
m_BinEncoder.encodeBin( symbol, Ctx::MTSIdx(ctxIdx));
if( !symbol )
{
break;
}
}
#endif
}
DTRACE(g_trace_ctx, D_SYNTAX, "mts_idx() etype=%d pos=(%d,%d) mtsIdx=%d\n", COMPONENT_Y, tu.cu->lx(), tu.cu->ly(), mtsIdx);
}
}
void CABACWriter::isp_mode( const CodingUnit& cu )
{
if( !CU::isIntra( cu ) || !isLuma( cu.chType ) || cu.firstPU->multiRefIdx || !cu.cs->sps->getUseISP() || cu.bdpcmMode || !CU::canUseISP( cu, getFirstComponentOfChannel( cu.chType ) ) || cu.colorTransform
#if ENABLE_DIMD && JVET_V0087_DIMD_NO_ISP
|| cu.dimd
#endif
#if JVET_AB0155_SGPM
|| cu.sgpm
#endif
)
{
CHECK( cu.ispMode != NOT_INTRA_SUBPARTITIONS, "cu.ispMode != 0" );
return;
}
if ( cu.ispMode == NOT_INTRA_SUBPARTITIONS )
{
#if JVET_W0123_TIMD_FUSION
m_BinEncoder.encodeBin( 0, cu.timd ? Ctx::ISPMode( 2 ) : Ctx::ISPMode( 0 ) );
#else
m_BinEncoder.encodeBin( 0, Ctx::ISPMode( 0 ) );
#endif
}
else
{
#if JVET_W0123_TIMD_FUSION
m_BinEncoder.encodeBin( 1, cu.timd ? Ctx::ISPMode( 2 ) : Ctx::ISPMode( 0 ) );
#else
m_BinEncoder.encodeBin( 1, Ctx::ISPMode( 0 ) );
#endif
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 );
}
void CABACWriter::residual_lfnst_mode( const CodingUnit& cu, CUCtx& cuCtx )
{
#if INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS
int chIdx = CS::isDualITree(*cu.cs) && cu.chType == CHANNEL_TYPE_CHROMA ? 1 : 0;
#else
int chIdx = cu.isSepTree() && cu.chType == CHANNEL_TYPE_CHROMA ? 1 : 0;
#endif
#if JVET_AH0103_LOW_DELAY_LFNST_NSPT
bool spsIntraLfnstEnabled = ( ( cu.slice->getSliceType() == I_SLICE && cu.cs->sps->getUseIntraLFNSTISlice() ) ||
( cu.slice->getSliceType() != I_SLICE && cu.cs->sps->getUseIntraLFNSTPBSlice() ) );
#endif
if( ( cu.ispMode && !CU::canUseLfnstWithISP( cu, cu.chType ) ) ||
#if JVET_AH0103_LOW_DELAY_LFNST_NSPT
#if JVET_V0130_INTRA_TMP
( spsIntraLfnstEnabled && CU::isIntra( cu ) && ( ( cu.mipFlag && !allowLfnstWithMip( cu.firstPU->lumaSize() ) ) || ( cu.tmpFlag && !allowLfnstWithTmp() ) ) ) ||
#else
( spsIntraLfnstEnabled && CU::isIntra( cu ) && cu.mipFlag && !allowLfnstWithMip( cu.firstPU->lumaSize() ) ) ||
#endif
#else
#if JVET_V0130_INTRA_TMP
(cu.cs->sps->getUseLFNST() && CU::isIntra(cu) && ((cu.mipFlag && !allowLfnstWithMip(cu.firstPU->lumaSize())) || (cu.tmpFlag && !allowLfnstWithTmp()))) ||
#else
(cu.cs->sps->getUseLFNST() && CU::isIntra(cu) && cu.mipFlag && !allowLfnstWithMip(cu.firstPU->lumaSize())) ||
#endif
#endif
#if INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS
(CS::isDualITree(*cu.cs) && cu.chType == CHANNEL_TYPE_CHROMA && std::min(cu.blocks[1].width, cu.blocks[1].height) < 4)
#else
( cu.isSepTree() && cu.chType == CHANNEL_TYPE_CHROMA && std::min( cu.blocks[ 1 ].width, cu.blocks[ 1 ].height ) < 4 )
#endif
|| ( cu.blocks[ chIdx ].lumaSize().width > cu.cs->sps->getMaxTbSize() || cu.blocks[ chIdx ].lumaSize().height > cu.cs->sps->getMaxTbSize() )
#if JVET_AG0061_INTER_LFNST_NSPT && JVET_AI0050_SBT_LFNST
|| ( !cu.cs->sps->getUseSbtLFNST() && cu.sbtInfo && CU::isInter( cu ))
#elif JVET_AG0061_INTER_LFNST_NSPT
|| ( cu.sbtInfo && CU::isInter( cu ) ) //JVET-AG0208 (EE2-related: On LFNST/NSPT index signalling)
#endif
)
{
return;
}
#if JVET_W0123_TIMD_FUSION
if (cu.timd && (cu.ispMode || cu.firstPU->multiRefIdx))
{
return;
}
#endif
#if JVET_AG0061_INTER_LFNST_NSPT
#if JVET_AH0103_LOW_DELAY_LFNST_NSPT
if( ( spsIntraLfnstEnabled && CU::isIntra( cu ) ) || ( cu.cs->sps->getUseInterLFNST() && CU::isInter( cu ) ) )
#else
if (cu.cs->sps->getUseLFNST() && (CU::isIntra(cu) || CU::isInter(cu)))
#endif
#else
#if JVET_AH0103_LOW_DELAY_LFNST_NSPT
if( spsIntraLfnstEnabled && CU::isIntra( cu ) )
#else
if (cu.cs->sps->getUseLFNST() && CU::isIntra(cu))
#endif
#endif
{
#if INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS
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;
#else
const bool lumaFlag = cu.isSepTree() ? ( isLuma( cu.chType ) ? true : false ) : true;
const bool chromaFlag = cu.isSepTree() ? ( isChroma( cu.chType ) ? true : false ) : true;
#endif
bool nonZeroCoeffNonTsCorner8x8 = ( lumaFlag && cuCtx.violatesLfnstConstrained[CHANNEL_TYPE_LUMA] ) || (chromaFlag && cuCtx.violatesLfnstConstrained[CHANNEL_TYPE_CHROMA] );
bool isTrSkip = false;
for (auto &currTU : CU::traverseTUs(cu))
{
const uint32_t numValidComp = getNumberValidComponents(cu.chromaFormat);
for (uint32_t compID = COMPONENT_Y; compID < numValidComp; compID++)
{
if (currTU.blocks[compID].valid() && TU::getCbf(currTU, (ComponentID)compID) && currTU.mtsIdx[compID] == MTS_SKIP)
{
isTrSkip = true;
break;
}
}
}
if( (!cuCtx.lfnstLastScanPos && !cu.ispMode) || nonZeroCoeffNonTsCorner8x8 || isTrSkip )
{
return;
}
}
else
{
return;
}
#if JVET_AG0061_INTER_LFNST_NSPT
if (CU::isInter(cu))
{
uint32_t idxLFNST = cu.lfnstIdx;
assert(idxLFNST < 4);
m_BinEncoder.encodeBin(idxLFNST > 0, Ctx::InterLFNSTIdx(0));
if (idxLFNST > 0)
{
m_BinEncoder.encodeBin(idxLFNST > 1, Ctx::InterLFNSTIdx(1));
if (idxLFNST > 1)
{
m_BinEncoder.encodeBin(idxLFNST > 2, Ctx::InterLFNSTIdx(2));
}
}
#if JVET_AI0050_INTER_MTSS
if (cu.cs->sps->getUseInterMTSS() && idxLFNST > 0 && cu.geoFlag)
{
m_BinEncoder.encodeBin(cu.lfnstIntra, Ctx::InterLFNSTIntraIdx());
}
#endif
}
else
{
#endif
unsigned cctx = 0;
#if INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS
if (CS::isDualITree(*cu.cs)) cctx++;
#else
if ( cu.isSepTree() ) cctx++;
#endif
#if EXTENDED_LFNST || JVET_W0119_LFNST_EXTENSION
uint32_t idxLFNST = cu.lfnstIdx;
assert(idxLFNST < 4);
uint32_t firstBit = idxLFNST & 1;
uint32_t secondBit = (idxLFNST >> 1) & 1;
m_BinEncoder.encodeBin(firstBit, Ctx::LFNSTIdx(cctx));
cctx = 2 + firstBit;
m_BinEncoder.encodeBin(secondBit, Ctx::LFNSTIdx(cctx));
#else
const uint32_t idxLFNST = cu.lfnstIdx;
assert( idxLFNST < 3 );
m_BinEncoder.encodeBin( idxLFNST ? 1 : 0, Ctx::LFNSTIdx( cctx ) );
if( idxLFNST )
{
m_BinEncoder.encodeBin( (idxLFNST - 1) ? 1 : 0, Ctx::LFNSTIdx(2));
}
#endif
#if JVET_AG0061_INTER_LFNST_NSPT
}
#endif
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 );
}
void CABACWriter::last_sig_coeff( CoeffCodingContext& cctx, const TransformUnit& tu, ComponentID compID )
{
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_256
if( tu.cs->sps->getUseMTS() && tu.cu->sbtInfo != 0 && tu.blocks[ compID ].width <= 32 && tu.blocks[ compID ].height <= 32 && compID == COMPONENT_Y )
{
maxLastPosX = ( tu.blocks[compID].width == 32 ) ? g_uiGroupIdx[ 15 ] : maxLastPosX;
maxLastPosY = ( tu.blocks[compID].height == 32 ) ? g_uiGroupIdx[ 15 ] : maxLastPosY;
}
#endif
for( CtxLast = 0; CtxLast < GroupIdxX; CtxLast++ )
{
m_BinEncoder.encodeBin( 1, cctx.lastXCtxId( CtxLast ) );
}
if( GroupIdxX < maxLastPosX )
{
m_BinEncoder.encodeBin(0, cctx.lastXCtxId(CtxLast));
}
for( CtxLast = 0; CtxLast < GroupIdxY; CtxLast++ )
{
m_BinEncoder.encodeBin(1, cctx.lastYCtxId(CtxLast));
}
if( GroupIdxY < maxLastPosY )
{
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 );
}
}
DTRACE(g_trace_ctx, D_SYNTAX_RESI, "last_sig_coeff() scan_pos_last=%d\n", cctx.scanPosLast());
}
#if TCQ_8STATES
#if JVET_AE0102_LFNST_CTX
void CABACWriter::residual_coding_subblock(CoeffCodingContext& cctx, const TCoeff* coeff, const uint64_t stateTransTable, int& state, int lfnstIdx)
#else
void CABACWriter::residual_coding_subblock(CoeffCodingContext& cctx, const TCoeff* coeff, const uint64_t stateTransTable, int& state)
#endif
#else
void CABACWriter::residual_coding_subblock(CoeffCodingContext &cctx, const TCoeff *coeff, const int stateTransTable,
int &state)
#endif
{
//===== init =====
const int minSubPos = cctx.minSubPos();
const bool isLast = cctx.isLast();
#if SIGN_PREDICTION
#if JVET_Y0141_SIGN_PRED_IMPROVE
const int cgStartPosX = cctx.cgPosX() << cctx.log2CGWidth();
const int cgStartPosY = cctx.cgPosY() << cctx.log2CGHeight();
const bool isSPArea = (cgStartPosX < SIGN_PRED_FREQ_RANGE) && (cgStartPosY < SIGN_PRED_FREQ_RANGE);
const bool signPredQualified = cctx.getPredSignsQualified() > 0 && isSPArea && cctx.width() >= 4 && cctx.height() >= 4;
#else
const bool isFirst = !cctx.isNotFirst();
const bool signPredQualified = cctx.getPredSignsQualified() > 0 && isFirst && cctx.width() >= 4 && cctx.height() >= 4 ;
#endif
#endif
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() );
DTRACE(g_trace_ctx, D_SYNTAX_RESI, "sig_group() bin=%d\n", 1);
}
else
{
m_BinEncoder.encodeBin( 0, cctx.sigGroupCtxId() );
DTRACE(g_trace_ctx, D_SYNTAX_RESI, "sig_group() bin=%d\n", 0);
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;
#if JVET_R0351_HIGH_BIT_DEPTH_SUPPORT_VS
TCoeff remAbsLevel = -1;
#else
int remAbsLevel = -1;
#endif
int numNonZero = 0;
unsigned signPattern = 0;
int remRegBins = cctx.regBinLimit;
int firstPosMode2 = minSubPos - 1;
for( ; nextSigPos >= minSubPos && remRegBins >= 4; nextSigPos-- )
{
TCoeff Coeff = coeff[ cctx.blockPos( nextSigPos ) ];
unsigned sigFlag = ( Coeff != 0 );
if( numNonZero || nextSigPos != inferSigPos )
{
#if JVET_AE0102_LFNST_CTX
const unsigned sigCtxId = cctx.sigCtxIdAbs(nextSigPos, coeff, state, lfnstIdx);
#else
const unsigned sigCtxId = cctx.sigCtxIdAbs(nextSigPos, coeff, state);
#endif
m_BinEncoder.encodeBin( sigFlag, sigCtxId );
DTRACE( g_trace_ctx, D_SYNTAX_RESI, "sig_bin() bin=%d ctx=%d\n", sigFlag, sigCtxId );
remRegBins--;
}
else if( nextSigPos != cctx.scanPosLast() )
{
#if JVET_AE0102_LFNST_CTX
cctx.sigCtxIdAbs(nextSigPos, coeff, state, lfnstIdx); // required for setting variables that are needed for gtx/par context selection
#else
cctx.sigCtxIdAbs(nextSigPos, coeff, state); // required for setting variables that are needed for gtx/par context selection
#endif
}
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;
#if !JVET_AG0100_TRANSFORM_COEFFICIENT_CODING
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--;
#endif
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--;
#if JVET_AG0100_TRANSFORM_COEFFICIENT_CODING
if (gt2)
{
int gtX = 1;
for (int i = 1; i < GTN - 1; i++)
{
if (gtX)
{
remAbsLevel -= 1;
gtX = !!remAbsLevel;
unsigned int ctxId = (i == 1) ? cctx.greater3CtxIdAbs(ctxOff) : cctx.greater4CtxIdAbs(ctxOff);
m_BinEncoder.encodeBin(gtX, ctxId);
DTRACE(g_trace_ctx, D_SYNTAX_RESI, "gt%d_flag() bin=%d ctx=%d\n", i + 2, gtX, ctxId);
remRegBins--;
}
else
{
gtX = 0;
break;
}
}
if (gtX)
{
remAbsLevel -= 1;
m_BinEncoder.encodeBinEP(remAbsLevel & 1);
DTRACE(g_trace_ctx, D_SYNTAX_RESI, "par_flag() bin=%d \n", remAbsLevel & 1);
remAbsLevel >>= 1;
}
}
#endif
}
}
#if TCQ_8STATES
state = int( ( stateTransTable >> ((state<<3)+((Coeff&1)<<2)) ) & 15 );
#else
state = ( stateTransTable >> ((state<<2)+((Coeff&1)<<1)) ) & 3;
#endif
}
firstPosMode2 = nextSigPos;
cctx.regBinLimit = remRegBins;
//===== 2nd PASS: Go-rice codes =====
unsigned ricePar = 0;
for( int scanPos = firstSigPos; scanPos > firstPosMode2; scanPos-- )
{
#if JVET_AE0102_LFNST_CTX
#if JVET_AG0100_TRANSFORM_COEFFICIENT_CODING
int sumAll = cctx.templateAbsSum2(scanPos, coeff, GTN_LEVEL);
#else
int sumAll = cctx.templateAbsSum(scanPos, coeff, 4, lfnstIdx);
#endif
#else
int sumAll = cctx.templateAbsSum(scanPos, coeff, 4);
#endif
#if JVET_AG0100_TRANSFORM_COEFFICIENT_CODING
ricePar = g_auiGoRiceParsCoeffGTN[sumAll];
#else
ricePar = g_auiGoRiceParsCoeff[sumAll];
#endif
#if JVET_R0351_HIGH_BIT_DEPTH_SUPPORT_VS
unsigned absLevel = (unsigned) abs( coeff[ cctx.blockPos( scanPos ) ] );
#else
unsigned absLevel = abs( coeff[ cctx.blockPos( scanPos ) ] );
#endif
#if JVET_AG0100_TRANSFORM_COEFFICIENT_CODING
if (absLevel >= GTN_LEVEL)
#else
if( absLevel >= 4 )
#endif
{
#if JVET_AG0100_TRANSFORM_COEFFICIENT_CODING
unsigned rem = (absLevel - GTN_LEVEL) >> 1;
#else
unsigned rem = ( absLevel - 4 ) >> 1;
#endif
m_BinEncoder.encodeRemAbsEP( rem, ricePar, COEF_REMAIN_BIN_REDUCTION, 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 ) ];
#if JVET_R0351_HIGH_BIT_DEPTH_SUPPORT_VS
unsigned absLevel = (unsigned) abs( Coeff );
#else
unsigned absLevel = abs( Coeff );
#endif
#if JVET_AE0102_LFNST_CTX
int sumAll = cctx.templateAbsSum(scanPos, coeff, 0, lfnstIdx);
#else
int sumAll = cctx.templateAbsSum(scanPos, coeff, 0);
#endif
int rice = g_auiGoRiceParsCoeff [sumAll];
int pos0 = g_auiGoRicePosCoeff0(state, rice);
unsigned rem = ( absLevel == 0 ? pos0 : absLevel <= pos0 ? absLevel-1 : absLevel );
m_BinEncoder.encodeRemAbsEP( rem, rice, COEF_REMAIN_BIN_REDUCTION, cctx.maxLog2TrDRange() );
DTRACE( g_trace_ctx, D_SYNTAX_RESI, "rem_val() bin=%d ctx=%d\n", rem, rice );
#if TCQ_8STATES
state = int( ( stateTransTable >> ((state<<3)+((absLevel&1)<<2)) ) & 15 );
#else
state = ( stateTransTable >> ((state<<2)+((absLevel&1)<<1)) ) & 3;
#endif
if( absLevel )
{
numNonZero++;
firstNZPos = scanPos;
lastNZPos = std::max<int>( lastNZPos, scanPos );
signPattern <<= 1;
if( Coeff < 0 ) signPattern++;
}
}
//===== encode sign's =====
unsigned numSigns = numNonZero;
if( cctx.hideSign( firstNZPos, lastNZPos ) )
{
numSigns --;
signPattern >>= 1;
}
#if SIGN_PREDICTION
if( !signPredQualified)
{
#endif
m_BinEncoder.encodeBinsEP( signPattern, numSigns );
#if SIGN_PREDICTION
}
#endif
}
void CABACWriter::residual_codingTS( const TransformUnit& tu, ComponentID compID )
{
DTRACE( g_trace_ctx, D_SYNTAX, "residual_coding_ts() 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, isLuma(compID) ? tu.cu->bdpcmMode : tu.cu->bdpcmModeChroma);
const TCoeff* coeff = tu.getCoeffs( compID ).buf;
int maxCtxBins = (cctx.maxNumCoeff() * 7) >> 2;
cctx.setNumCtxBins(maxCtxBins);
// 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() )
{
m_BinEncoder.encodeBin( 1, cctx.sigGroupCtxId( true ) );
DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_sig_group() bin=%d ctx=%d\n", 1, cctx.sigGroupCtxId() );
}
else
{
m_BinEncoder.encodeBin( 0, cctx.sigGroupCtxId( true ) );
DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_sig_group() bin=%d ctx=%d\n", 0, cctx.sigGroupCtxId() );
return;
}
}
//===== encode absolute values =====
const int inferSigPos = minSubPos;
int remAbsLevel = -1;
int numNonZero = 0;
int rightPixel, belowPixel, modAbsCoeff;
int lastScanPosPass1 = -1;
int lastScanPosPass2 = -1;
for (; nextSigPos <= minSubPos && cctx.numCtxBins() >= 4; nextSigPos++)
{
TCoeff Coeff = coeff[ cctx.blockPos( nextSigPos ) ];
unsigned sigFlag = ( Coeff != 0 );
if( numNonZero || nextSigPos != inferSigPos )
{
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 );
cctx.decimateNumCtxBins(1);
}
if( sigFlag )
{
//===== encode sign's =====
int sign = Coeff < 0;
const unsigned signCtxId = cctx.signCtxIdAbsTS(nextSigPos, coeff, cctx.bdpcm());
m_BinEncoder.encodeBin(sign, signCtxId);
DTRACE(g_trace_ctx, D_SYNTAX_RESI, "ts_sign() bin=%d ctx=%d\n", sign, signCtxId);
cctx.decimateNumCtxBins(1);
numNonZero++;
cctx.neighTS(rightPixel, belowPixel, nextSigPos, coeff);
modAbsCoeff = cctx.deriveModCoeff(rightPixel, belowPixel, abs(Coeff), cctx.bdpcm());
remAbsLevel = modAbsCoeff - 1;
unsigned gt1 = !!remAbsLevel;
const unsigned gt1CtxId = cctx.lrg1CtxIdAbsTS(nextSigPos, coeff, cctx.bdpcm());
m_BinEncoder.encodeBin(gt1, gt1CtxId);
DTRACE(g_trace_ctx, D_SYNTAX_RESI, "ts_gt1_flag() bin=%d ctx=%d\n", gt1, gt1CtxId);
cctx.decimateNumCtxBins(1);
if( gt1 )
{
remAbsLevel -= 1;
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() );
cctx.decimateNumCtxBins(1);
}
}
lastScanPosPass1 = nextSigPos;
}
int cutoffVal = 2;
int numGtBins = 4;
for (int scanPos = firstSigPos; scanPos <= minSubPos && cctx.numCtxBins() >= 4; scanPos++)
{
unsigned absLevel;
cctx.neighTS(rightPixel, belowPixel, scanPos, coeff);
absLevel = cctx.deriveModCoeff(rightPixel, belowPixel, abs(coeff[cctx.blockPos(scanPos)]), cctx.bdpcm());
cutoffVal = 2;
for (int i = 0; i < numGtBins; i++)
{
if (absLevel >= cutoffVal)
{
unsigned gt2 = (absLevel >= (cutoffVal + 2));
m_BinEncoder.encodeBin(gt2, cctx.greaterXCtxIdAbsTS(cutoffVal >> 1));
DTRACE(g_trace_ctx, D_SYNTAX_RESI, "ts_gt%d_flag() bin=%d ctx=%d sp=%d coeff=%d\n", i, gt2, cctx.greaterXCtxIdAbsTS(cutoffVal >> 1), scanPos, min<int>(absLevel, cutoffVal + 2 + (absLevel&1)));
cctx.decimateNumCtxBins(1);
}
cutoffVal += 2;
}
lastScanPosPass2 = scanPos;
}
//===== coeff bypass ====
for( int scanPos = firstSigPos; scanPos <= minSubPos; scanPos++ )
{
unsigned absLevel;
cctx.neighTS(rightPixel, belowPixel, scanPos, coeff);
cutoffVal = (scanPos <= lastScanPosPass2 ? 10 : (scanPos <= lastScanPosPass1 ? 2 : 0));
absLevel = cctx.deriveModCoeff(rightPixel, belowPixel, abs(coeff[cctx.blockPos(scanPos)]), cctx.bdpcm()||!cutoffVal);
if( absLevel >= cutoffVal )
{
int rice = cctx.templateAbsSumTS( scanPos, coeff );
unsigned rem = scanPos <= lastScanPosPass1 ? (absLevel - cutoffVal) >> 1 : absLevel;
m_BinEncoder.encodeRemAbsEP( rem, rice, COEF_REMAIN_BIN_REDUCTION, cctx.maxLog2TrDRange() );
DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_rem_val() bin=%d ctx=%d sp=%d\n", rem, rice, scanPos );
if (absLevel && scanPos > lastScanPosPass1)
{
int sign = coeff[cctx.blockPos(scanPos)] < 0;
m_BinEncoder.encodeBinEP(sign);
DTRACE(g_trace_ctx, D_SYNTAX_RESI, "ts_rice_sign() bin=%d\n", sign);
}
}
}
}
//================================================================================
// helper functions
//--------------------------------------------------------------------------------
// void unary_max_symbol ( symbol, ctxId0, ctxIdN, maxSymbol )
// void unary_max_eqprob ( symbol, maxSymbol )
// void exp_golomb_eqprob ( symbol, count )
//================================================================================
void CABACWriter::unary_max_symbol( unsigned symbol, unsigned ctxId0, unsigned ctxIdN, unsigned maxSymbol )
{
CHECK( symbol > maxSymbol, "symbol > maxSymbol" );
const unsigned totalBinsToWrite = std::min( symbol + 1, maxSymbol );
for( unsigned binsWritten = 0; binsWritten < totalBinsToWrite; ++binsWritten )
{
const unsigned nextBin = symbol > binsWritten;
m_BinEncoder.encodeBin( nextBin, binsWritten == 0 ? ctxId0 : ctxIdN );
}
}
void CABACWriter::unary_max_eqprob( unsigned symbol, unsigned maxSymbol )
{
if( maxSymbol == 0 )
{
return;
}
bool codeLast = ( maxSymbol > symbol );
unsigned bins = 0;
unsigned numBins = 0;
while( symbol-- )
{
bins <<= 1;
bins ++;
numBins++;
}
if( codeLast )
{
bins <<= 1;
numBins++;
}
CHECK(!( numBins <= 32 ), "Unspecified error");
m_BinEncoder.encodeBinsEP( bins, numBins );
}
void CABACWriter::exp_golomb_eqprob( unsigned symbol, unsigned count )
{
unsigned bins = 0;
unsigned numBins = 0;
while( symbol >= (unsigned)(1<<count) )
{
bins <<= 1;
bins++;
numBins++;
symbol -= 1 << count;
count++;
}
bins <<= 1;
numBins++;
//CHECK(!( numBins + count <= 32 ), "Unspecified error");
m_BinEncoder.encodeBinsEP(bins, numBins);
m_BinEncoder.encodeBinsEP(symbol, count);
}
void CABACWriter::codeAlfCtuEnableFlags( CodingStructure& cs, ChannelType channel, AlfParam* alfParam)
{
if( isLuma( channel ) )
{
if( alfParam->enabledFlag[COMPONENT_Y] )
{
codeAlfCtuEnableFlags( cs, COMPONENT_Y, alfParam );
}
}
else
{
if( alfParam->enabledFlag[COMPONENT_Cb] )
{
codeAlfCtuEnableFlags( cs, COMPONENT_Cb, alfParam );
}
if( alfParam->enabledFlag[COMPONENT_Cr] )
{
codeAlfCtuEnableFlags( cs, COMPONENT_Cr, alfParam );
}
}
}
void CABACWriter::codeAlfCtuEnableFlags( CodingStructure& cs, ComponentID compID, AlfParam* alfParam)
{
uint32_t numCTUs = cs.pcv->sizeInCtus;
for( int ctuIdx = 0; ctuIdx < numCTUs; ctuIdx++ )
{
codeAlfCtuEnableFlag( cs, ctuIdx, compID, alfParam );
}
}
void CABACWriter::codeAlfCtuEnableFlag( CodingStructure& cs, uint32_t ctuRsAddr, const int compIdx, AlfParam* alfParam)
{
const bool alfComponentEnabled = (alfParam != NULL) ? alfParam->enabledFlag[compIdx] : cs.slice->getTileGroupAlfEnabledFlag((ComponentID)compIdx);
if( cs.sps->getALFEnabledFlag() && alfComponentEnabled )
{
const PreCalcValues& pcv = *cs.pcv;
int frame_width_in_ctus = pcv.widthInCtus;
int ry = ctuRsAddr / frame_width_in_ctus;
int rx = ctuRsAddr - ry * frame_width_in_ctus;
const Position pos( rx * cs.pcv->maxCUWidth, ry * cs.pcv->maxCUHeight );
const uint32_t curSliceIdx = cs.slice->getIndependentSliceIdx();
const uint32_t curTileIdx = cs.pps->getTileIdx( pos );
bool leftAvail = cs.getCURestricted( pos.offset( -(int)pcv.maxCUWidth, 0 ), pos, curSliceIdx, curTileIdx, CH_L ) ? true : false;
bool aboveAvail = cs.getCURestricted( pos.offset( 0, -(int)pcv.maxCUHeight ), pos, curSliceIdx, curTileIdx, CH_L ) ? true : false;
int leftCTUAddr = leftAvail ? ctuRsAddr - 1 : -1;
int aboveCTUAddr = aboveAvail ? ctuRsAddr - frame_width_in_ctus : -1;
uint8_t* ctbAlfFlag = cs.slice->getPic()->getAlfCtuEnableFlag( compIdx );
int ctx = 0;
ctx += leftCTUAddr > -1 ? ( ctbAlfFlag[leftCTUAddr] ? 1 : 0 ) : 0;
ctx += aboveCTUAddr > -1 ? ( ctbAlfFlag[aboveCTUAddr] ? 1 : 0 ) : 0;
m_BinEncoder.encodeBin( ctbAlfFlag[ctuRsAddr], Ctx::ctbAlfFlag( compIdx * 3 + ctx ) );
}
}
#if JVET_X0071_LONGER_CCALF
void CABACWriter::codeCcAlfFilterControlIdc(uint8_t idcVal, CodingStructure &cs, const ComponentID compID,
const int curIdx, const uint8_t *filterControlIdc, Position lumaPos,
const int filterCount)
{
CHECK(idcVal > filterCount, "Filter index is too large");
const uint32_t curSliceIdx = cs.slice->getIndependentSliceIdx();
const uint32_t curTileIdx = cs.pps->getTileIdx(lumaPos);
Position leftLumaPos = lumaPos.offset(-(int)cs.pcv->maxCUWidth, 0);
Position aboveLumaPos = lumaPos.offset(0, -(int)cs.pcv->maxCUWidth);
bool leftAvail = cs.getCURestricted(leftLumaPos, lumaPos, curSliceIdx, curTileIdx, CH_L) ? true : false;
bool aboveAvail = cs.getCURestricted(aboveLumaPos, lumaPos, curSliceIdx, curTileIdx, CH_L) ? true : false;
int ctxt = 0;
if (leftAvail)
{
ctxt += (filterControlIdc[curIdx - 1] != 1) ? 1 : 0;
}
if (aboveAvail)
{
ctxt += (filterControlIdc[curIdx - cs.pcv->widthInCtus] != 1) ? 1 : 0;
}
ctxt += (compID == COMPONENT_Cr) ? 3 : 0;
int pos0 = 1;
unsigned mappedIdc = (idcVal == 0 ? pos0 : idcVal <= pos0 ? idcVal - 1 : idcVal);
m_BinEncoder.encodeBin((mappedIdc == 0) ? 0 : 1, Ctx::CcAlfFilterControlFlag(ctxt)); // ON/OFF flag is context coded
if (mappedIdc > 0)
{
int val = (mappedIdc - 1);
while (val)
{
m_BinEncoder.encodeBinEP(1);
val--;
}
if (mappedIdc < filterCount)
{
m_BinEncoder.encodeBinEP(0);
}
}
DTRACE(g_trace_ctx, D_SYNTAX, "cc_alf_filter_control_idc() compID=%d pos=(%d,%d) ctxt=%d, filterCount=%d, idcVal=%d\n", compID, lumaPos.x, lumaPos.y, ctxt, filterCount, idcVal);
}
#else
void CABACWriter::codeCcAlfFilterControlIdc(uint8_t idcVal, CodingStructure &cs, const ComponentID compID,
const int curIdx, const uint8_t *filterControlIdc, Position lumaPos,
const int filterCount)
{
CHECK(idcVal > filterCount, "Filter index is too large");
const uint32_t curSliceIdx = cs.slice->getIndependentSliceIdx();
const uint32_t curTileIdx = cs.pps->getTileIdx( lumaPos );
Position leftLumaPos = lumaPos.offset(-(int)cs.pcv->maxCUWidth, 0);
Position aboveLumaPos = lumaPos.offset(0, -(int)cs.pcv->maxCUWidth);
bool leftAvail = cs.getCURestricted( leftLumaPos, lumaPos, curSliceIdx, curTileIdx, CH_L ) ? true : false;
bool aboveAvail = cs.getCURestricted( aboveLumaPos, lumaPos, curSliceIdx, curTileIdx, CH_L ) ? true : false;
int ctxt = 0;
if (leftAvail)
{
ctxt += ( filterControlIdc[curIdx - 1]) ? 1 : 0;
}
if (aboveAvail)
{
ctxt += (filterControlIdc[curIdx - cs.pcv->widthInCtus]) ? 1 : 0;
}
ctxt += ( compID == COMPONENT_Cr ) ? 3 : 0;
m_BinEncoder.encodeBin( ( idcVal == 0 ) ? 0 : 1, Ctx::CcAlfFilterControlFlag( ctxt ) ); // ON/OFF flag is context coded
if ( idcVal > 0 )
{
int val = (idcVal - 1);
while ( val )
{
m_BinEncoder.encodeBinEP( 1 );
val--;
}
if ( idcVal < filterCount )
{
m_BinEncoder.encodeBinEP( 0 );
}
}
DTRACE( g_trace_ctx, D_SYNTAX, "cc_alf_filter_control_idc() compID=%d pos=(%d,%d) ctxt=%d, filterCount=%d, idcVal=%d\n", compID, lumaPos.x, lumaPos.y, ctxt, filterCount, idcVal );
}
#endif
void CABACWriter::code_unary_fixed( unsigned symbol, unsigned ctxId, unsigned unary_max, unsigned fixed )
{
bool unary = (symbol <= unary_max);
m_BinEncoder.encodeBin( unary, ctxId );
if( unary )
{
unary_max_eqprob( symbol, unary_max );
}
else
{
m_BinEncoder.encodeBinsEP( symbol - unary_max - 1, fixed );
}
}
#if JVET_V0130_INTRA_TMP
void CABACWriter::tmp_flag(const CodingUnit& cu)
{
if (!cu.Y().valid())
{
return;
}
#if JVET_X0124_TMP_SIGNAL
if (cu.dimd)
{
return;
}
#endif
if (!cu.cs->sps->getUseIntraTMP())
{
return;
}
unsigned ctxId = DeriveCtx::CtxTmpFlag(cu);
m_BinEncoder.encodeBin(cu.tmpFlag, Ctx::TmpFlag(ctxId));
DTRACE(g_trace_ctx, D_SYNTAX, "tmp_flag() pos=(%d,%d) mode=%d\n", cu.lumaPos().x, cu.lumaPos().y, cu.tmpFlag ? 1 : 0);
#if JVET_AD0086_ENHANCED_INTRA_TMP
if (cu.tmpFlag)
{
unsigned ctxId_fusion = DeriveCtx::CtxTmpFusionFlag(cu);
m_BinEncoder.encodeBin(cu.tmpFusionFlag, Ctx::TmpFusion(ctxId_fusion));
DTRACE(g_trace_ctx, D_SYNTAX, "tmp_fusion_flag() pos=(%d,%d) mode=%d\n", cu.lumaPos().x, cu.lumaPos().y,
cu.tmpFusionFlag ? 1 : 0);
if (cu.tmpFusionFlag)
{
m_BinEncoder.encodeBin(cu.tmpIdx >= TMP_GROUP_IDX ? 1: 0, Ctx::TmpFusion(4));
int tmpFusionIdx = cu.tmpIdx;
tmpFusionIdx = tmpFusionIdx >= TMP_GROUP_IDX ? tmpFusionIdx - TMP_GROUP_IDX: tmpFusionIdx;
m_BinEncoder.encodeBin(tmpFusionIdx ? 1: 0, Ctx::TmpFusion(5));
if (tmpFusionIdx)
{
m_BinEncoder.encodeBinEP(tmpFusionIdx > 1 ? 1 : 0);
}
DTRACE(g_trace_ctx, D_SYNTAX, "tmp_fusion_idx() pos=(%d,%d) mode=%d\n", cu.lumaPos().x, cu.lumaPos().y, cu.tmpIdx);
#if JVET_AG0136_INTRA_TMP_LIC
m_BinEncoder.encodeBin(cu.tmpLicFlag, Ctx::TmpLic(0));
DTRACE(g_trace_ctx, D_SYNTAX, "tmpLicFlag pos=(%d,%d) value=%d\n", cu.lumaPos().x, cu.lumaPos().y, cu.tmpLicFlag);
#endif
}
else
{
if (cu.tmpIdx < 3)
{
m_BinEncoder.encodeBin(1, Ctx::TmpIdx(0));
if (cu.tmpIdx == 0)
{
m_BinEncoder.encodeBin(1, Ctx::TmpIdx(1));
}
else
{
m_BinEncoder.encodeBin(0, Ctx::TmpIdx(1));
if (cu.tmpIdx == 1)
{
m_BinEncoder.encodeBin(1, Ctx::TmpIdx(2));
}
else
{
m_BinEncoder.encodeBin(0, Ctx::TmpIdx(2));
}
}
}
else
{
m_BinEncoder.encodeBin(0, Ctx::TmpIdx(0));
xWriteTruncBinCode(cu.tmpIdx - 3, MTMP_NUM - 3);
}
DTRACE(g_trace_ctx, D_SYNTAX, "tmp_idx() pos=(%d,%d) mode=%d\n", cu.lumaPos().x, cu.lumaPos().y, cu.tmpIdx);
m_BinEncoder.encodeBin(cu.tmpFlmFlag, Ctx::TmpFusion(3));
DTRACE(g_trace_ctx, D_SYNTAX, "tmp_flm_flag() pos=(%d,%d) mode=%d\n", cu.lumaPos().x, cu.lumaPos().y,
cu.tmpFlmFlag);
#if JVET_AG0136_INTRA_TMP_LIC
if (!cu.tmpFlmFlag)
{
m_BinEncoder.encodeBin(cu.tmpLicFlag, Ctx::TmpLic(0));
DTRACE(g_trace_ctx, D_SYNTAX, "tmpLicFlag() pos=(%d,%d) mode=%d\n", cu.lumaPos().x, cu.lumaPos().y, cu.tmpLicFlag);
if (cu.slice->getSPS()->getItmpLicExtension() && cu.tmpLicFlag)
{
const int bin1 = (cu.ibcLicIdx == IBC_LIC_IDX) || (cu.ibcLicIdx == IBC_LIC_IDX_M) ? 0 : 1;
const int bin2 = (cu.ibcLicIdx == IBC_LIC_IDX) || (cu.ibcLicIdx == IBC_LIC_IDX_T) ? 0 : 1;
m_BinEncoder.encodeBin(bin1, Ctx::ItmpLicIndex(0));
m_BinEncoder.encodeBin(bin2, Ctx::ItmpLicIndex(1));
DTRACE(g_trace_ctx, D_SYNTAX, "tmp_lic_idx=%d\n", cu.ibcLicIdx);
}
}
#if !JVET_AH0200_INTRA_TMP_BV_REORDER
if (!cu.tmpFlmFlag && !cu.tmpLicFlag)
#else
if (!cu.tmpFlmFlag)
#endif
#else
if (!cu.tmpFlmFlag)
#endif
{
#if JVET_AH0200_INTRA_TMP_BV_REORDER
if(cu.lwidth() * cu.lheight() <= TMP_SKIP_REFINE_THRESHOLD)
{
if(cu.tmpFracIdx > 0)
{
m_BinEncoder.encodeBin(1, Ctx::TmpFlag(7));
}
else
{
m_BinEncoder.encodeBin(0, Ctx::TmpFlag(7));
}
}
DTRACE(g_trace_ctx, D_SYNTAX, "tmpFracIdx pos=(%d,%d) value=%d\n", cu.lumaPos().x, cu.lumaPos().y, cu.tmpFracIdx);
#else
m_BinEncoder.encodeBin(cu.tmpIsSubPel != 0 ? 1 : 0, Ctx::TmpFlag(4));
if (cu.tmpIsSubPel)
{
m_BinEncoder.encodeBin(cu.tmpIsSubPel >= 2 ? 1 : 0, Ctx::TmpFlag(5));
if (cu.tmpIsSubPel >= 2)
{
m_BinEncoder.encodeBin(cu.tmpIsSubPel == 3 ? 1 : 0, Ctx::TmpFlag(6));
}
m_BinEncoder.encodeBinsEP(cu.tmpSubPelIdx, 3);
}
DTRACE(g_trace_ctx, D_SYNTAX, "tmp_is_subpel() pos=(%d,%d) mode=%d\n", cu.lumaPos().x, cu.lumaPos().y, cu.tmpIsSubPel);
#endif
}
}
}
#endif
}
#endif
void CABACWriter::mip_flag( const CodingUnit& cu )
{
#if ENABLE_DIMD
if (cu.dimd)
{
return;
}
#endif
if( !cu.Y().valid() )
{
return;
}
if( !cu.cs->sps->getUseMIP() )
{
return;
}
unsigned ctxId = DeriveCtx::CtxMipFlag( cu );
m_BinEncoder.encodeBin( cu.mipFlag, Ctx::MipFlag( ctxId ) );
DTRACE( g_trace_ctx, D_SYNTAX, "mip_flag() pos=(%d,%d) mode=%d\n", cu.lumaPos().x, cu.lumaPos().y, cu.mipFlag ? 1 : 0 );
}
void CABACWriter::mip_pred_modes( const CodingUnit& cu )
{
if( !cu.Y().valid() )
{
return;
}
for( const auto &pu : CU::traversePUs( cu ) )
{
mip_pred_mode( pu );
}
}
void CABACWriter::mip_pred_mode( const PredictionUnit& pu )
{
m_BinEncoder.encodeBinEP( (pu.mipTransposedFlag ? 1 : 0) );
const int numModes = getNumModesMip( pu.Y() );
CHECKD( pu.intraDir[CHANNEL_TYPE_LUMA] < 0 || pu.intraDir[CHANNEL_TYPE_LUMA] >= numModes, "Invalid MIP mode" );
xWriteTruncBinCode( pu.intraDir[CHANNEL_TYPE_LUMA], numModes );
DTRACE( g_trace_ctx, D_SYNTAX, "mip_pred_mode() pos=(%d,%d) mode=%d transposed=%d\n", pu.lumaPos().x, pu.lumaPos().y, pu.intraDir[CHANNEL_TYPE_LUMA], pu.mipTransposedFlag ? 1 : 0 );
}
void CABACWriter::codeAlfCtuFilterIndex(CodingStructure& cs, uint32_t ctuRsAddr, bool alfEnableLuma)
{
if ( (!cs.sps->getALFEnabledFlag()) || (!alfEnableLuma))
{
return;
}
uint8_t* ctbAlfFlag = cs.slice->getPic()->getAlfCtuEnableFlag(COMPONENT_Y);
if (!ctbAlfFlag[ctuRsAddr])
{
return;
}
short* alfCtbFilterIndex = cs.slice->getPic()->getAlfCtbFilterIndex();
const unsigned filterSetIdx = alfCtbFilterIndex[ctuRsAddr];
unsigned numAps = cs.slice->getTileGroupNumAps();
unsigned numAvailableFiltSets = numAps + NUM_FIXED_FILTER_SETS;
if (numAvailableFiltSets > NUM_FIXED_FILTER_SETS)
{
int useTemporalFilt = (filterSetIdx >= NUM_FIXED_FILTER_SETS) ? 1 : 0;
m_BinEncoder.encodeBin(useTemporalFilt, Ctx::AlfUseTemporalFilt());
if (useTemporalFilt)
{
CHECK((filterSetIdx - NUM_FIXED_FILTER_SETS) >= (numAvailableFiltSets - NUM_FIXED_FILTER_SETS), "temporal non-latest set");
if (numAps > 1)
{
xWriteTruncBinCode(filterSetIdx - NUM_FIXED_FILTER_SETS, numAvailableFiltSets - NUM_FIXED_FILTER_SETS);
}
}
else
{
CHECK(filterSetIdx >= NUM_FIXED_FILTER_SETS, "fixed set larger than temporal");
xWriteTruncBinCode(filterSetIdx, NUM_FIXED_FILTER_SETS);
}
}
else
{
CHECK(filterSetIdx >= NUM_FIXED_FILTER_SETS, "fixed set numavail < num_fixed");
xWriteTruncBinCode(filterSetIdx, NUM_FIXED_FILTER_SETS);
}
}
void CABACWriter::codeAlfCtuAlternatives( CodingStructure& cs, ChannelType channel, AlfParam* alfParam)
{
if( isChroma( channel ) )
{
if( alfParam->enabledFlag[COMPONENT_Cb] )
{
codeAlfCtuAlternatives( cs, COMPONENT_Cb, alfParam );
}
if( alfParam->enabledFlag[COMPONENT_Cr] )
{
codeAlfCtuAlternatives( cs, COMPONENT_Cr, alfParam );
}
}
}
void CABACWriter::codeAlfCtuAlternatives( CodingStructure& cs, ComponentID compID, AlfParam* alfParam)
{
if( compID == COMPONENT_Y )
{
return;
}
uint32_t numCTUs = cs.pcv->sizeInCtus;
uint8_t* ctbAlfFlag = cs.slice->getPic()->getAlfCtuEnableFlag( compID );
for( int ctuIdx = 0; ctuIdx < numCTUs; ctuIdx++ )
{
if( ctbAlfFlag[ctuIdx] )
{
codeAlfCtuAlternative( cs, ctuIdx, compID, alfParam );
}
}
}
void CABACWriter::codeAlfCtuAlternative( CodingStructure& cs, uint32_t ctuRsAddr, const int compIdx, const AlfParam* alfParam
#if ALF_IMPROVEMENT
, int numAltLuma
#endif
)
{
#if ALF_IMPROVEMENT
if (compIdx == COMPONENT_Y)
{
if (alfParam || (cs.sps->getALFEnabledFlag() && cs.slice->getTileGroupAlfEnabledFlag((ComponentID)compIdx)))
{
uint8_t* ctbAlfFlag = cs.slice->getPic()->getAlfCtuEnableFlag(compIdx);
short* ctbAlfFilterSetIndex = cs.slice->getPic()->getAlfCtbFilterIndex();
if (ctbAlfFlag[ctuRsAddr] && ctbAlfFilterSetIndex[ctuRsAddr] >= NUM_FIXED_FILTER_SETS)
{
uint8_t* ctbAlfAlternative = cs.slice->getPic()->getAlfCtuAlternativeData(compIdx);
unsigned numOnes = ctbAlfAlternative[ctuRsAddr];
assert(ctbAlfAlternative[ctuRsAddr] < numAltLuma);
for( int i = 0; i < numOnes; ++i )
{
m_BinEncoder.encodeBin( 1, Ctx::ctbAlfAlternative( compIdx ) );
}
if( numOnes < numAltLuma - 1 )
{
m_BinEncoder.encodeBin( 0, Ctx::ctbAlfAlternative( compIdx ) );
}
}
}
}
else
{
#else
if( compIdx == COMPONENT_Y )
return;
#endif
int apsIdx = alfParam ? 0 : cs.slice->getTileGroupApsIdChroma();
const AlfParam& alfParamRef = alfParam ? (*alfParam) : cs.slice->getAlfAPSs()[apsIdx]->getAlfAPSParam();
if( alfParam || (cs.sps->getALFEnabledFlag() && cs.slice->getTileGroupAlfEnabledFlag( (ComponentID)compIdx )) )
{
uint8_t* ctbAlfFlag = cs.slice->getPic()->getAlfCtuEnableFlag( compIdx );
if( ctbAlfFlag[ctuRsAddr] )
{
const int numAlts = alfParamRef.numAlternativesChroma;
uint8_t* ctbAlfAlternative = cs.slice->getPic()->getAlfCtuAlternativeData( compIdx );
unsigned numOnes = ctbAlfAlternative[ctuRsAddr];
assert( ctbAlfAlternative[ctuRsAddr] < numAlts );
#if ALF_IMPROVEMENT
for( int i = 0; i < numOnes; ++i )
{
m_BinEncoder.encodeBin( 1, Ctx::ctbAlfAlternative( compIdx ) );
}
if( numOnes < numAlts-1 )
{
m_BinEncoder.encodeBin( 0, Ctx::ctbAlfAlternative( compIdx ) );
}
#else
for( int i = 0; i < numOnes; ++i )
{
m_BinEncoder.encodeBin( 1, Ctx::ctbAlfAlternative( compIdx - 1 ) );
}
if( numOnes < numAlts - 1 )
{
m_BinEncoder.encodeBin( 0, Ctx::ctbAlfAlternative( compIdx - 1 ) );
}
#endif
}
}
#if ALF_IMPROVEMENT
}
#endif
}
#if INTER_LIC
void CABACWriter::cu_lic_flag(const CodingUnit& cu)
{
if (CU::isLICFlagPresent(cu))
{
#if JVET_AG0276_LIC_SLOPE_ADJUST
unsigned ctxId = DeriveCtx::CtxLicFlag( cu );
m_BinEncoder.encodeBin(cu.licFlag ? 1 : 0, Ctx::LICFlag(ctxId));
#else
m_BinEncoder.encodeBin(cu.licFlag ? 1 : 0, Ctx::LICFlag(0));
#endif
DTRACE(g_trace_ctx, D_SYNTAX, "cu_lic_flag() lic_flag=%d\n", cu.licFlag ? 1 : 0);
#if JVET_AG0276_LIC_SLOPE_ADJUST
if (cu.licFlag && CU::isLicSlopeAllowed(cu) && cu.firstPU->interDir != 3)
{
int delta = cu.licDelta;
m_BinEncoder.encodeBin( delta != 0 ? 1 : 0, Ctx::LicDelta(0) );
if ( delta )
{
m_BinEncoder.encodeBin( delta < 0 ? 1 : 0, Ctx::LicDelta(1) );
}
}
#endif
}
}
#endif
#if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
void CABACWriter::bvOneZeroComp(const CodingUnit &cu)
{
if (!CU::isIBC(cu) || cu.firstPU->mergeFlag)
{
return;
}
unsigned ctxId = DeriveCtx::CtxbvOneZeroComp(cu);
m_BinEncoder.encodeBin(cu.bvOneZeroComp > 0, Ctx::bvOneZeroComp(ctxId));
if (cu.bvOneZeroComp)
{
// Write the BV direction
m_BinEncoder.encodeBin(cu.bvZeroCompDir >> 1, Ctx::bvOneZeroComp(3));
#if JVET_AA0070_RRIBC
#if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
if (cu.cs->sps->getUseRRIbc())
{
#endif
ctxId = DeriveCtx::CtxRribcFlipType(cu);
m_BinEncoder.encodeBin(cu.rribcFlipType > 0, Ctx::rribcFlipType(ctxId));
#if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
}
#endif
#endif
}
DTRACE(g_trace_ctx, D_SYNTAX, "rribc_data() rribc_flip_type = %d\n", cu.rribcFlipType);
}
#endif
#if JVET_AA0070_RRIBC
void CABACWriter::rribcData(const CodingUnit& cu)
{
#if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
if (!cu.cs->sps->getUseRRIbc() || !CU::isIBC(cu) || cu.firstPU->mergeFlag)
#else
if (!CU::isIBC(cu) || cu.firstPU->mergeFlag)
#endif
{
return;
}
unsigned ctxId = DeriveCtx::CtxRribcFlipType(cu);
m_BinEncoder.encodeBin(cu.rribcFlipType > 0, Ctx::rribcFlipType(ctxId));
if (cu.rribcFlipType)
{
CHECK(cu.rribcFlipType != 1 && cu.rribcFlipType != 2, "cu.rribcFlipType != 1 && cu.rribcFlipType != 2");
m_BinEncoder.encodeBin(cu.rribcFlipType >> 1, Ctx::rribcFlipType(3));
}
DTRACE(g_trace_ctx, D_SYNTAX, "rribc_data() rribc_flip_type = %d\n", cu.rribcFlipType);
}
#endif
#if SIGN_PREDICTION
#if JVET_Y0141_SIGN_PRED_IMPROVE
struct SignCombInfo
{
unsigned idx;
bool sign;
bool isSignPred;
SignCombInfo(const unsigned _sign, const unsigned _idx, const bool _isPred)
: idx(_idx), sign(_sign), isSignPred(_isPred)
{
}
};
bool compareOrderIdx(SignCombInfo cand0, SignCombInfo cand1)
{
return (cand0.idx < cand1.idx);
}
#endif
void CABACWriter::codePredictedSigns( TransformUnit &tu, ComponentID compID )
{
const CtxSet* ctx = &Ctx::signPred[toChannelType( compID )];
int ctxOffset = CU::isIntra( *tu.cu ) ? 0 : 2;
const bool useSignPred = TU::getUseSignPred( tu, compID );
CoeffBuf buff = tu.getCoeffs( compID );
AreaBuf<SIGN_PRED_TYPE> signBuff = tu.getCoeffSigns(compID);
TCoeff *coeff = buff.buf;
SIGN_PRED_TYPE *signs = signBuff.buf;
#if JVET_Y0141_SIGN_PRED_IMPROVE
IdxBuf signScanIdxBuff = tu.getCoeffSignsScanIdx(compID);
unsigned *signScanIdx = signScanIdxBuff.buf;
uint32_t extAreaWidth = std::min(tu.blocks[compID].width, (uint32_t)SIGN_PRED_FREQ_RANGE);
uint32_t extAreaHeight = std::min(tu.blocks[compID].height, (uint32_t)SIGN_PRED_FREQ_RANGE);
if (!useSignPred)
{
for (uint32_t y = 0; y < extAreaHeight; y++)
{
for (uint32_t x = 0; x < extAreaWidth; x++)
{
TCoeff coef = coeff[x];
if (coef)
{
if (signs[x] != SIGN_PRED_HIDDEN)
{
m_BinEncoder.encodeBinEP(coef < 0 ? 1 : 0);
}
}
}
coeff += buff.stride;
signs += signBuff.stride;
}
}
else
{
std::vector<SignCombInfo> signCombList;
bool lfnstEnabled = tu.checkLFNSTApplied(compID);
static_vector<uint32_t, SIGN_PRED_MAX_NUM> levelList;
const int32_t maxNumPredSigns =
lfnstEnabled ? std::min<int>(4, tu.cs->sps->getNumPredSigns()) : tu.cs->sps->getNumPredSigns();
CHECK(maxNumPredSigns > levelList.max_size(), "levelList is too small");
uint32_t extAreaSize = (lfnstEnabled ? 4 : tu.cs->sps->getSignPredArea());
uint32_t spAreaWidth = std::min(tu.blocks[compID].width, extAreaSize);
uint32_t spAreaHeight = std::min(tu.blocks[compID].height, extAreaSize);
for (uint32_t y = 0; y < spAreaHeight; y++)
{
for (uint32_t x = 0; x < spAreaWidth; x++)
{
TCoeff coef = coeff[x];
if (coef)
{
SIGN_PRED_TYPE sign = signs[x];
if (sign != SIGN_PRED_HIDDEN)
{
if (sign == SIGN_PRED_BYPASS)
{
const bool curSign = coef < 0;
unsigned scanIdx = signScanIdx[x];
SignCombInfo signCand(curSign, scanIdx, false);
signCombList.push_back(signCand);
}
else
{
const bool errSignPred =
!(coef > 0 && sign == SIGN_PRED_POSITIVE) && !(coef < 0 && sign == SIGN_PRED_NEGATIVE);
unsigned scanIdx = signScanIdx[x];
SignCombInfo signCand(errSignPred, scanIdx, true);
signCombList.push_back(signCand);
}
if (levelList.size() < maxNumPredSigns)
{
levelList.push_back(abs(coef));
}
}
}
}
coeff += buff.stride;
signs += signBuff.stride;
signScanIdx += signScanIdxBuff.stride;
}
std::stable_sort(signCombList.begin(), signCombList.end(), compareOrderIdx);
int numScanPos = 0;
for (uint32_t idx = 0; idx < signCombList.size(); idx++)
{
if (signCombList[idx].isSignPred)
{
const bool errSignPred = signCombList[idx].sign;
uint32_t level = levelList[numScanPos++];
int levOffset = (level < 2) ? 0 : 1;
m_BinEncoder.encodeBin(errSignPred ? 1 : 0, (*ctx)(ctxOffset + levOffset));
}
else
{
const bool curSign = signCombList[idx].sign;
m_BinEncoder.encodeBinEP(curSign ? 1 : 0);
}
}
if (spAreaWidth != extAreaWidth || spAreaHeight != extAreaHeight)
{
coeff = buff.buf;
for (uint32_t y = 0; y < extAreaHeight; y++)
{
uint32_t startX = (y < spAreaHeight) ? spAreaWidth : 0;
uint32_t endX = extAreaWidth - 1;
for (uint32_t x = startX; x <= endX; x++)
{
TCoeff coef = coeff[x];
if (coef)
{
uint32_t curSign = (coef < 0) ? 1 : 0;
m_BinEncoder.encodeBinEP(curSign);
}
}
coeff += buff.stride;
}
}
}
#else
for( uint32_t y = 0; y < SIGN_PRED_FREQ_RANGE; y++ )
{
for( uint32_t x = 0; x < SIGN_PRED_FREQ_RANGE; x++ )
{
TCoeff coef = coeff[x];
if( coef )
{
SIGN_PRED_TYPE sign = signs[x];
if (sign != SIGN_PRED_HIDDEN)
{
if( sign == SIGN_PRED_BYPASS || !useSignPred )
{
m_BinEncoder.encodeBinEP( coef < 0 ? 1 : 0 );
}
else
{
uint32_t errSignPred =
((coef > 0 && sign == SIGN_PRED_POSITIVE) || (coef < 0 && sign == SIGN_PRED_NEGATIVE)) ? 0 : 1;
uint32_t ctxId = ( x || y ) ? 1 : 0;
m_BinEncoder.encodeBin( errSignPred, ( *ctx )( ctxId + ctxOffset ) );
}
}
}
}
coeff += buff.stride;
signs += signBuff.stride;
}
#endif
}
#endif
#if JVET_X0083_BM_AMVP_MERGE_MODE
void CABACWriter::amvpMerge_mode( const PredictionUnit& pu )
{
if (PU::isBipredRestriction(pu))
{
CHECK(1, "this is not possible");
return;
}
if (pu.amvpMergeModeFlag[0] || pu.amvpMergeModeFlag[1])
{
m_BinEncoder.encodeBin(1, Ctx::amFlagState());
DTRACE(g_trace_ctx, D_SYNTAX, "amvp_merge_mode() am_flag=%d\n", 1);
#if JVET_Z0054_BLK_REF_PIC_REORDER
if (pu.cs->sps->getUseARL())
{
// signaled by refIdxLC
}
else
#endif
if (pu.cu->cs->picHeader->getMvdL1ZeroFlag() == false)
{
if (pu.amvpMergeModeFlag[REF_PIC_LIST_0])
{
m_BinEncoder.encodeBinEP(0);
DTRACE(g_trace_ctx, D_SYNTAX, "amvp_merge_mode() dir=%d\n", 0);
}
else
{
m_BinEncoder.encodeBinEP(1);
DTRACE(g_trace_ctx, D_SYNTAX, "amvp_merge_mode() dir=%d\n", 1);
}
}
}
else
{
#if JVET_Y0128_NON_CTC
if (pu.cu->slice->getUseAmvpMergeMode())
#else
if (!pu.cu->slice->getCheckLDC())
#endif
{
m_BinEncoder.encodeBin(0, Ctx::amFlagState());
DTRACE(g_trace_ctx, D_SYNTAX, "amvp_merge_mode() am_flag=%d\n", 0);
}
}
}
#endif
#if JVET_AB0157_TMRL
void CABACWriter::cuTmrlFlag(const CodingUnit& cu)
{
#if !JVET_AD0082_TMRL_CONFIG
if (!CU::allowTmrl(cu))
{
return;
}
#endif
const PredictionUnit* pu = cu.firstPU;
#if !JVET_AD0082_TMRL_CONFIG
#if JVET_W0123_TIMD_FUSION
if (cu.timd)
{
CHECK(cu.tmrlFlag, "TMRL cannot combine with TIMD.");
unsigned int bin = pu->multiRefIdx != MULTI_REF_LINE_IDX[0];
m_BinEncoder.encodeBin(bin, Ctx::MultiRefLineIdx(5)); // TIMD MRL
if (bin)
{
bin = pu->multiRefIdx != MULTI_REF_LINE_IDX[1];
m_BinEncoder.encodeBin(bin, Ctx::MultiRefLineIdx(6)); // which line
}
DTRACE(g_trace_ctx, D_SYNTAX, "extend_ref_line() idx=%d pos=(%d,%d) ref_idx=%d\n", bin, pu->lumaPos().x, pu->lumaPos().y, pu->multiRefIdx);
}
else
{
#endif
#endif
int ctxId = 0;
m_BinEncoder.encodeBin(cu.tmrlFlag, Ctx::TmrlDerive(ctxId++));
DTRACE(g_trace_ctx, D_SYNTAX, "cu_tmrl_flag() ctx=%d pos=(%d,%d) tmrl=%d\n", 0, cu.lumaPos().x, cu.lumaPos().y, cu.tmrlFlag);
if (cu.tmrlFlag)
{
const int maxNumCtxBins = (MRL_LIST_SIZE / MRL_IDX_RICE_CODE_DIVISOR) - 1;
int mrlIdxPrefix = cu.tmrlListIdx / MRL_IDX_RICE_CODE_DIVISOR;
for (int val = 0; val < maxNumCtxBins; val++)
{
unsigned int bin = (val == mrlIdxPrefix ? 0 : 1);
m_BinEncoder.encodeBin(bin, Ctx::TmrlDerive(ctxId++));
if (!bin)
{
break;
}
}
uint32_t mrlIdxSuffix = uint32_t(cu.tmrlListIdx & (MRL_IDX_RICE_CODE_DIVISOR - 1));
m_BinEncoder.encodeBin((mrlIdxSuffix & 1), Ctx::TmrlDerive(maxNumCtxBins + 1));
m_BinEncoder.encodeBin(((mrlIdxSuffix >> 1) & 1), Ctx::TmrlDerive(maxNumCtxBins + 2));
DTRACE(g_trace_ctx, D_SYNTAX, "cu_tmrl_idx() ctx=%d pos=(%d,%d) tmrlidx=%d\n", 0, cu.lumaPos().x, cu.lumaPos().y, cu.tmrlListIdx);
}
else
{
CHECK(pu->multiRefIdx, "?");
}
#if !JVET_AD0082_TMRL_CONFIG
#if JVET_W0123_TIMD_FUSION
}
#endif
#endif
}
#endif
#if JVET_AE0059_INTER_CCCM
void CABACWriter::interCccm(const TransformUnit& tu)
{
if (TU::interCccmAllowed(tu))
{
m_BinEncoder.encodeBin(tu.interCccm > 0 ? 1 : 0, Ctx::InterCccmFlag(0));
DTRACE(g_trace_ctx, D_SYNTAX, "inter_cccm() pos=(%d,%d) inter_cccm_flag=%d\n", tu.blocks[tu.chType].x, tu.blocks[tu.chType].y, tu.interCccm > 0 ? 1 : 0);
}
}
#endif
#if JVET_AF0073_INTER_CCP_MERGE
void CABACWriter::interCcpMerge(const TransformUnit& tu)
{
if (TU::interCcpMergeAllowed(tu))
{
#if JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0
m_BinEncoder.encodeBin(tu.interCcpMerge > 0 ? 1 : 0, Ctx::InterCcpMergeFlag(tu.cbf[COMPONENT_Y] ? 0 : 1));
#else
m_BinEncoder.encodeBin(tu.interCcpMerge > 0 ? 1 : 0, Ctx::InterCcpMergeFlag(0));
#endif
DTRACE(g_trace_ctx, D_SYNTAX, "inter_ccp_merge() pos=(%d,%d) inter_ccp_merge_flag=%d\n", tu.blocks[tu.chType].x, tu.blocks[tu.chType].y, tu.interCcpMerge > 0 ? 1 : 0);
}
}
#endif
//! \}