Newer
Older
unsigned &riceStats = m_binEncoder.getCtx().getGRAdaptStats((unsigned) (cctx.compID()));
cctx.updateRiceStat(riceStats, rem, 1);
cctx.setUpdateHist(0);
updateHistory = 0;
}
}
}
//===== coeff bypass ====
for (int scanPos = minPos2ndPass; scanPos >= minSubPos; scanPos--)
TCoeff coeffVal = coeff[cctx.blockPos(scanPos)];
unsigned absLevel = (unsigned) abs(coeffVal);
int rice = (cctx.*(cctx.deriveRiceRRC))(scanPos, coeff, 0);
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 );
state = ( stateTransTable >> ((state<<2)+((absLevel&1)<<1)) ) & 3;
if ((updateHistory) && (rem > 0))
{
unsigned &riceStats = m_binEncoder.getCtx().getGRAdaptStats((unsigned) cctx.compID());
cctx.updateRiceStat(riceStats, rem, 0);
cctx.setUpdateHist(0);
updateHistory = 0;
}
if( absLevel )
{
numNonZero++;
firstNZPos = scanPos;
lastNZPos = std::max<int>( lastNZPos, scanPos );
signPattern <<= 1;
}
}

Karsten Suehring
committed
//===== encode sign's =====
unsigned numSigns = numNonZero;
if( cctx.hideSign( firstNZPos, lastNZPos ) )
{
numSigns --;
signPattern >>= 1;
}

Karsten Suehring
committed
}
void CABACWriter::residual_codingTS( const TransformUnit& tu, ComponentID compID )
{
DTRACE( g_trace_ctx, D_SYNTAX, "residual_codingTS() etype=%d pos=(%d,%d) size=%dx%d\n", tu.blocks[compID].compID, tu.blocks[compID].x, tu.blocks[compID].y, tu.blocks[compID].width, tu.blocks[compID].height );
// init coeff coding context
CoeffCodingContext cctx ( tu, compID, false, 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] );
Hong-Jheng Jhu
committed
int goRiceParam = 1;
bool ricePresentFlag = false;
unsigned RiceBit[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
if (tu.cu->slice->getSPS()->getSpsRangeExtension().getTSRCRicePresentFlag() && tu.mtsIdx[compID] == MtsType::SKIP)
Hong-Jheng Jhu
committed
{
goRiceParam = goRiceParam + tu.cu->slice->getTsrcIndex();
Hong-Jheng Jhu
committed
if (isEncoding())
{
ricePresentFlag = true;
for (int i = 0; i < MAX_TSRC_RICE; i++)
{
RiceBit[i] = tu.cu->slice->getRiceBit(i);
}
}
}
residual_coding_subblockTS( cctx, coeff, RiceBit, goRiceParam, ricePresentFlag);
if (tu.cu->slice->getSPS()->getSpsRangeExtension().getTSRCRicePresentFlag() && tu.mtsIdx[compID] == MtsType::SKIP
&& isEncoding())
Hong-Jheng Jhu
committed
{
for (int i = 0; i < MAX_TSRC_RICE; i++)
{
tu.cu->slice->setRiceBit(i, RiceBit[i]);
}
}
void CABACWriter::residual_coding_subblockTS(CoeffCodingContext &cctx, const TCoeff *coeff, unsigned (&RiceBit)[8],
const int riceParam, bool ricePresentFlag)
{
//===== 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() )
{
DTRACE(g_trace_ctx, D_SYNTAX_RESI, "ts_sigGroup() bin=%d ctx=%d\n", 1, cctx.sigGroupCtxId());
}
else
{
DTRACE(g_trace_ctx, D_SYNTAX_RESI, "ts_sigGroup() 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 coeffVal = coeff[cctx.blockPos(nextSigPos)];
unsigned sigFlag = (coeffVal != 0);
if( numNonZero || nextSigPos != inferSigPos )
{
const unsigned sigCtxId = cctx.sigCtxIdAbsTS(nextSigPos, coeff);
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 =====
const unsigned signCtxId = cctx.signCtxIdAbsTS(nextSigPos, coeff, cctx.bdpcm());
cctx.neighTS(rightPixel, belowPixel, nextSigPos, coeff);
modAbsCoeff = cctx.deriveModCoeff(rightPixel, belowPixel, abs(coeffVal), cctx.bdpcm() != BdpcmMode::NONE);
remAbsLevel = modAbsCoeff - 1;
unsigned gt1 = !!remAbsLevel;
const unsigned gt1CtxId = cctx.lrg1CtxIdAbsTS(nextSigPos, coeff, cctx.bdpcm());
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++)
Mohammed Golam Sarwer
committed
{
unsigned absLevel;
cctx.neighTS(rightPixel, belowPixel, scanPos, coeff);
absLevel =
cctx.deriveModCoeff(rightPixel, belowPixel, abs(coeff[cctx.blockPos(scanPos)]), cctx.bdpcm() != BdpcmMode::NONE);
Mohammed Golam Sarwer
committed
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, std::min<int>(absLevel, cutoffVal + 2));
cctx.decimateNumCtxBins(1);
Mohammed Golam Sarwer
committed
}
cutoffVal += 2;
}
lastScanPosPass2 = scanPos;
Mohammed Golam Sarwer
committed
}
//===== 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() != BdpcmMode::NONE || cutoffVal == 0);
if( absLevel >= cutoffVal )
{
unsigned rem = scanPos <= lastScanPosPass1 ? (absLevel - cutoffVal) >> 1 : absLevel;
m_binEncoder.encodeRemAbsEP(rem, riceParam, COEF_REMAIN_BIN_REDUCTION, cctx.maxLog2TrDRange());
DTRACE(g_trace_ctx, D_SYNTAX_RESI, "ts_rem_val() bin=%d ctx=%d sp=%d\n", rem, riceParam, scanPos);
Hong-Jheng Jhu
committed
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
if ( ricePresentFlag && (isEncoding()) && (cctx.compID() == COMPONENT_Y))
{
for (int idx = 1; idx < 9; idx++)
{
uint32_t length;
uint32_t symbol = rem;
if (rem < (5 << idx))
{
length = rem >> idx;
RiceBit[idx - 1] += (length + 1 + idx);
}
else
{
length = idx;
symbol = symbol - (5 << idx);
while (symbol >= (1 << length))
{
symbol -= (1 << (length++));
}
RiceBit[idx - 1] += (5 + length + 1 - idx + length);
}
}
}
if (absLevel && scanPos > lastScanPosPass1)
{
const int sign = coeff[cctx.blockPos(scanPos)] < 0 ? 1 : 0;

Karsten Suehring
committed
//================================================================================
// 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);

Karsten Suehring
committed
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
}
}
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");

Karsten Suehring
committed
}
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);

Karsten Suehring
committed
}
void CABACWriter::codeAlfCtuEnableFlags( CodingStructure& cs, ChannelType channel, AlfParam* alfParam)

Karsten Suehring
committed
{
if( isLuma( channel ) )
{
if (alfParam->enabledFlag[COMPONENT_Y])

Karsten Suehring
committed
codeAlfCtuEnableFlags( cs, COMPONENT_Y, alfParam );

Karsten Suehring
committed
}
else
{
if (alfParam->enabledFlag[COMPONENT_Cb])

Karsten Suehring
committed
codeAlfCtuEnableFlags( cs, COMPONENT_Cb, alfParam );

Karsten Suehring
committed
if (alfParam->enabledFlag[COMPONENT_Cr])

Karsten Suehring
committed
codeAlfCtuEnableFlags( cs, COMPONENT_Cr, alfParam );

Karsten Suehring
committed
}
}
void CABACWriter::codeAlfCtuEnableFlags( CodingStructure& cs, ComponentID compID, AlfParam* alfParam)

Karsten Suehring
committed
{
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)

Karsten Suehring
committed
{
const bool alfComponentEnabled =
(alfParam != nullptr) ? alfParam->enabledFlag[compIdx] : cs.slice->getAlfEnabledFlag((ComponentID) compIdx);

Karsten Suehring
committed
if( cs.sps->getALFEnabledFlag() && alfComponentEnabled )

Karsten Suehring
committed
{
const PreCalcValues& pcv = *cs.pcv;
const int frameWidthInCtus = pcv.widthInCtus;
const int ry = ctuRsAddr / frameWidthInCtus;
const int rx = ctuRsAddr - ry * frameWidthInCtus;
const Position pos(rx * cs.pcv->maxCUWidth, ry * cs.pcv->maxCUHeight);
const uint32_t curSliceIdx = cs.slice->getIndependentSliceIdx();
const TileIdx curTileIdx = cs.pps->getTileIdx(pos);
cs.getCURestricted(pos.offset(-(int) pcv.maxCUWidth, 0), pos, curSliceIdx, curTileIdx, ChannelType::LUMA)
!= nullptr;
cs.getCURestricted(pos.offset(0, -(int) pcv.maxCUHeight), pos, curSliceIdx, curTileIdx, ChannelType::LUMA)
!= nullptr;
const int leftCTUAddr = leftAvail ? ctuRsAddr - 1 : -1;
const int aboveCTUAddr = aboveAvail ? ctuRsAddr - frameWidthInCtus : -1;

Karsten Suehring
committed
AlfMode *alfModes = cs.slice->getPic()->getAlfModes(compIdx);
ctx += leftCTUAddr > -1 ? (alfModes[leftCTUAddr] != AlfMode::OFF ? 1 : 0) : 0;
ctx += aboveCTUAddr > -1 ? (alfModes[aboveCTUAddr] != AlfMode::OFF ? 1 : 0) : 0;
m_binEncoder.encodeBin(alfModes[ctuRsAddr] != AlfMode::OFF, Ctx::alfCtbFlag(compIdx * 3 + ctx));

Karsten Suehring
committed
}
}
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 TileIdx 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, ChannelType::LUMA) ? true : false;
bool aboveAvail =
cs.getCURestricted(aboveLumaPos, lumaPos, curSliceIdx, curTileIdx, ChannelType::LUMA) ? 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 )
{
val--;
}
if ( idcVal < filterCount )
{
}
}
DTRACE( g_trace_ctx, D_SYNTAX, "ccAlfFilterControlIdc() compID=%d pos=(%d,%d) ctxt=%d, filterCount=%d, idcVal=%d\n", compID, lumaPos.x, lumaPos.y, ctxt, filterCount, idcVal );
}
void CABACWriter::mip_flag( const CodingUnit& cu )
{
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 = MatrixIntraPrediction::getNumModesMip(pu.Y());
CHECKD(pu.intraDir[ChannelType::LUMA] < 0 || pu.intraDir[ChannelType::LUMA] >= numModes, "Invalid MIP mode");
xWriteTruncBinCode(pu.intraDir[ChannelType::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[ChannelType::LUMA], pu.mipTransposedFlag ? 1 : 0);
void CABACWriter::codeAlfCtuFilterIndex(CodingStructure& cs, uint32_t ctuRsAddr, bool alfEnableLuma)
if (!cs.sps->getALFEnabledFlag() || !alfEnableLuma)
{
return;
}
AlfMode *alfModes = cs.slice->getPic()->getAlfModes(COMPONENT_Y);
AlfMode m = alfModes[ctuRsAddr];
if (m == AlfMode::OFF)
{
return;
}
const int numAps = cs.slice->getNumAlfApsIdsLuma();
const bool alfUseApsFlag = !isAlfLumaFixed(m);
if (numAps > 0)
m_binEncoder.encodeBin(alfUseApsFlag ? 1 : 0, Ctx::alfUseApsFlag());
}
if (alfUseApsFlag)
{
const uint32_t alfLumaPrevFilterIdx = m - AlfMode::LUMA0;
CHECK(alfLumaPrevFilterIdx >= numAps, "alfLumaPrevFilterIdx is too large");
if (numAps > 1)
xWriteTruncBinCode(alfLumaPrevFilterIdx, numAps);
}
else
{
const uint32_t alfLumaFixedFilterIdx = m - AlfMode::LUMA_FIXED0;
xWriteTruncBinCode(alfLumaFixedFilterIdx, ALF_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;
AlfMode *alfModes = cs.slice->getPic()->getAlfModes(compID);
for( int ctuIdx = 0; ctuIdx < numCTUs; ctuIdx++ )
{
if (alfModes[ctuIdx] != AlfMode::OFF)
{
codeAlfCtuAlternative( cs, ctuIdx, compID, alfParam );
}
}
}
void CABACWriter::codeAlfCtuAlternative( CodingStructure& cs, uint32_t ctuRsAddr, const int compIdx, const AlfParam* alfParam)
{
if( compIdx == COMPONENT_Y )
return;
int apsIdx = alfParam ? 0 : cs.slice->getAlfApsIdChroma();
const AlfParam& alfParamRef = alfParam ? (*alfParam) : cs.slice->getAlfAPSs()[apsIdx]->getAlfAPSParam();
if( alfParam || (cs.sps->getALFEnabledFlag() && cs.slice->getAlfEnabledFlag( (ComponentID)compIdx )) )
{
AlfMode *alfModes = cs.slice->getPic()->getAlfModes(compIdx);
if (alfModes[ctuRsAddr] != AlfMode::OFF)
{
const int numAlts = alfParamRef.numAlternativesChroma;
const int numOnes = alfModes[ctuRsAddr] - AlfMode::CHROMA0;
CHECK(numOnes >= numAlts, "Invalid ALF mode");
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));
}
}
}