Newer
Older
rdCostA += ( 1 << SCALE_BITS ) + goRiceTab[ pqDataA.absLevel <= m_goRiceZero ? pqDataA.absLevel - 1 : ( pqDataA.absLevel < RICEMAX ? pqDataA.absLevel : RICEMAX - 1 ) ];
rdCostB += ( 1 << SCALE_BITS ) + goRiceTab[ pqDataB.absLevel <= m_goRiceZero ? pqDataB.absLevel - 1 : ( pqDataB.absLevel < RICEMAX ? pqDataB.absLevel : RICEMAX - 1 ) ];
rdCostZ += goRiceTab[ m_goRiceZero ];
if( rdCostA < decisionA.rdCost )
decisionA.rdCost = rdCostA;
decisionA.absLevel = pqDataA.absLevel;
decisionA.prevId = m_stateId;
if( rdCostZ < decisionA.rdCost )
{
decisionA.rdCost = rdCostZ;
decisionA.absLevel = 0;
decisionA.prevId = m_stateId;
}
if( rdCostB < decisionB.rdCost )
{
decisionB.rdCost = rdCostB;
decisionB.absLevel = pqDataB.absLevel;
decisionB.prevId = m_stateId;
}

Karsten Suehring
committed
inline void checkRdCostStart(int32_t lastOffset, const PQData &pqData, Decision &decision) const
{
int64_t rdCost = pqData.deltaDist + lastOffset;
if (pqData.absLevel < 4)
{
rdCost += m_coeffFracBits.bits[pqData.absLevel];
}
else
{
const unsigned value = (pqData.absLevel - 4) >> 1;
rdCost += m_coeffFracBits.bits[pqData.absLevel - (value << 1)] + g_goRiceBits[m_goRicePar][value < RICEMAX ? value : RICEMAX-1];
}

Karsten Suehring
committed
if( rdCost < decision.rdCost )
{
decision.rdCost = rdCost;
decision.absLevel = pqData.absLevel;
decision.prevId = -1;
}
}
inline void checkRdCostSkipSbb(Decision &decision) const
{
int64_t rdCost = m_rdCost + m_sbbFracBits.intBits[0];
if( rdCost < decision.rdCost )
{
decision.rdCost = rdCost;
decision.absLevel = 0;
decision.prevId = 4+m_stateId;
}
}
inline void checkRdCostSkipSbbZeroOut(Decision &decision) const
{
int64_t rdCost = m_rdCost + m_sbbFracBits.intBits[0];
decision.rdCost = rdCost;
decision.absLevel = 0;
decision.prevId = 4 + m_stateId;
}

Karsten Suehring
committed
private:
int64_t m_rdCost;
uint16_t m_absLevelsAndCtxInit[24]; // 16x8bit for abs levels + 16x16bit for ctx init id
int8_t m_numSigSbb;
#if JVET_O0052_TU_LEVEL_CTX_CODED_BIN_CONSTRAINT
int m_remRegBins;
#else
int8_t m_remRegBins;
int8_t m_refSbbCtxId;

Karsten Suehring
committed
BinFracBits m_sbbFracBits;
BinFracBits m_sigFracBits;
CoeffFracBits m_coeffFracBits;
int8_t m_goRicePar;
int8_t m_goRiceZero;
const int8_t m_stateId;

Karsten Suehring
committed
const BinFracBits*const m_sigFracBitsArray;
const CoeffFracBits*const m_gtxFracBitsArray;
const uint32_t*const m_goRiceZeroArray;

Karsten Suehring
committed
CommonCtx& m_commonCtx;
#if JVET_O0052_TU_LEVEL_CTX_CODED_BIN_CONSTRAINT
public:
unsigned effWidth;
unsigned effHeight;
#endif

Karsten Suehring
committed
};
State::State( const RateEstimator& rateEst, CommonCtx& commonCtx, const int stateId )
: m_sbbFracBits { { 0, 0 } }
, m_stateId ( stateId )
, m_sigFracBitsArray( rateEst.sigFlagBits(stateId) )
, m_gtxFracBitsArray( rateEst.gtxFracBits(stateId) )
, m_goRiceZeroArray ( g_auiGoRicePosCoeff0[std::max(0,stateId-1)] )

Karsten Suehring
committed
, m_commonCtx ( commonCtx )
{
}
template<uint8_t numIPos>
inline void State::updateState(const ScanInfo &scanInfo, const State *prevStates, const Decision &decision)
{
m_rdCost = decision.rdCost;
if( decision.prevId > -2 )
{
if( decision.prevId >= 0 )
{
const State* prvState = prevStates + decision.prevId;
m_numSigSbb = prvState->m_numSigSbb + !!decision.absLevel;
m_refSbbCtxId = prvState->m_refSbbCtxId;
m_sbbFracBits = prvState->m_sbbFracBits;
m_remRegBins = prvState->m_remRegBins - 1;
m_goRicePar = prvState->m_goRicePar;
if( m_remRegBins >= 4 )
m_remRegBins -= (decision.absLevel < 2 ? decision.absLevel : 3);

Karsten Suehring
committed
::memcpy( m_absLevelsAndCtxInit, prvState->m_absLevelsAndCtxInit, 48*sizeof(uint8_t) );
}
else
{
m_numSigSbb = 1;
m_refSbbCtxId = -1;
#if JVET_O0052_TU_LEVEL_CTX_CODED_BIN_CONSTRAINT
int ctxBinSampleRatio = (scanInfo.chType == CHANNEL_TYPE_LUMA) ? MAX_TU_LEVEL_CTX_CODED_BIN_CONSTRAINT_LUMA : MAX_TU_LEVEL_CTX_CODED_BIN_CONSTRAINT_CHROMA;
m_remRegBins = (effWidth * effHeight *ctxBinSampleRatio) / 16 - (decision.absLevel < 2 ? decision.absLevel : 3);
#else
if ( scanInfo.sbbSize == 4 )
{
m_remRegBins = MAX_NUM_REG_BINS_2x2SUBBLOCK - (decision.absLevel < 2 ? decision.absLevel : 3);
}
else
{
m_remRegBins = MAX_NUM_REG_BINS_4x4SUBBLOCK - (decision.absLevel < 2 ? decision.absLevel : 3);

Karsten Suehring
committed
::memset( m_absLevelsAndCtxInit, 0, 48*sizeof(uint8_t) );
}
uint8_t* levels = reinterpret_cast<uint8_t*>(m_absLevelsAndCtxInit);
levels[ scanInfo.insidePos ] = (uint8_t)std::min<TCoeff>( 255, decision.absLevel );
if (m_remRegBins >= 4)
{
TCoeff tinit = m_absLevelsAndCtxInit[8 + scanInfo.nextInsidePos];
TCoeff sumAbs1 = (tinit >> 3) & 31;
TCoeff sumNum = tinit & 7;
#define UPDATE(k) {TCoeff t=levels[scanInfo.nextNbInfoSbb.inPos[k]]; sumAbs1+=std::min<TCoeff>(4+(t&1),t); sumNum+=!!t; }
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
if (numIPos == 1)
{
UPDATE(0);
}
else if (numIPos == 2)
{
UPDATE(0);
UPDATE(1);
}
else if (numIPos == 3)
{
UPDATE(0);
UPDATE(1);
UPDATE(2);
}
else if (numIPos == 4)
{
UPDATE(0);
UPDATE(1);
UPDATE(2);
UPDATE(3);
}
else if (numIPos == 5)
{
UPDATE(0);
UPDATE(1);
UPDATE(2);
UPDATE(3);
UPDATE(4);
}
#undef UPDATE
TCoeff sumGt1 = sumAbs1 - sumNum;
#if JVET_O0617_SIG_FLAG_CONTEXT_REDUCTION
m_sigFracBits = m_sigFracBitsArray[scanInfo.sigCtxOffsetNext + std::min( (sumAbs1+1)>>1, 3 )];
#else
m_sigFracBits = m_sigFracBitsArray[scanInfo.sigCtxOffsetNext + (sumAbs1 < 5 ? sumAbs1 : 5)];
#endif
m_coeffFracBits = m_gtxFracBitsArray[scanInfo.gtxCtxOffsetNext + (sumGt1 < 4 ? sumGt1 : 4)];
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
TCoeff sumAbs = m_absLevelsAndCtxInit[8 + scanInfo.nextInsidePos] >> 8;
#define UPDATE(k) {TCoeff t=levels[scanInfo.nextNbInfoSbb.inPos[k]]; sumAbs+=t; }
if (numIPos == 1)
{
UPDATE(0);
}
else if (numIPos == 2)
{
UPDATE(0);
UPDATE(1);
}
else if (numIPos == 3)
{
UPDATE(0);
UPDATE(1);
UPDATE(2);
}
else if (numIPos == 4)
{
UPDATE(0);
UPDATE(1);
UPDATE(2);
UPDATE(3);
}
else if (numIPos == 5)
{
UPDATE(0);
UPDATE(1);
UPDATE(2);
UPDATE(3);
UPDATE(4);
}
#undef UPDATE
int sumAll = std::max(std::min(31, (int)sumAbs - 4 * 5), 0);
m_goRicePar = g_auiGoRiceParsCoeff[sumAll];
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
}
else
{
TCoeff sumAbs = m_absLevelsAndCtxInit[8 + scanInfo.nextInsidePos] >> 8;
#define UPDATE(k) {TCoeff t=levels[scanInfo.nextNbInfoSbb.inPos[k]]; sumAbs+=t; }
if (numIPos == 1)
{
UPDATE(0);
}
else if (numIPos == 2)
{
UPDATE(0);
UPDATE(1);
}
else if (numIPos == 3)
{
UPDATE(0);
UPDATE(1);
UPDATE(2);
}
else if (numIPos == 4)
{
UPDATE(0);
UPDATE(1);
UPDATE(2);
UPDATE(3);
}
else if (numIPos == 5)
{
UPDATE(0);
UPDATE(1);
UPDATE(2);
UPDATE(3);
UPDATE(4);
}
#undef UPDATE
sumAbs = std::min<TCoeff>(31, sumAbs);
m_goRicePar = g_auiGoRiceParsCoeff[sumAbs];
m_goRiceZero = m_goRiceZeroArray[sumAbs];
}

Karsten Suehring
committed
}
}
inline void State::updateStateEOS(const ScanInfo &scanInfo, const State *prevStates, const State *skipStates,
const Decision &decision)
{
m_rdCost = decision.rdCost;
if( decision.prevId > -2 )
{
const State* prvState = 0;
if( decision.prevId >= 4 )
{
CHECK( decision.absLevel != 0, "cannot happen" );
prvState = skipStates + ( decision.prevId - 4 );
m_numSigSbb = 0;
::memset( m_absLevelsAndCtxInit, 0, 16*sizeof(uint8_t) );
}
else if( decision.prevId >= 0 )

Karsten Suehring
committed
{
prvState = prevStates + decision.prevId;
m_numSigSbb = prvState->m_numSigSbb + !!decision.absLevel;

Karsten Suehring
committed
::memcpy( m_absLevelsAndCtxInit, prvState->m_absLevelsAndCtxInit, 16*sizeof(uint8_t) );
}
else
{
m_numSigSbb = 1;
::memset( m_absLevelsAndCtxInit, 0, 16*sizeof(uint8_t) );
}
reinterpret_cast<uint8_t*>(m_absLevelsAndCtxInit)[ scanInfo.insidePos ] = (uint8_t)std::min<TCoeff>( 255, decision.absLevel );
m_commonCtx.update( scanInfo, prvState, *this );
TCoeff tinit = m_absLevelsAndCtxInit[ 8 + scanInfo.nextInsidePos ];
TCoeff sumNum = tinit & 7;
TCoeff sumAbs1 = ( tinit >> 3 ) & 31;
TCoeff sumGt1 = sumAbs1 - sumNum;
#if JVET_O0617_SIG_FLAG_CONTEXT_REDUCTION
m_sigFracBits = m_sigFracBitsArray[ scanInfo.sigCtxOffsetNext + std::min( (sumAbs1+1)>>1, 3 ) ];
#else

Karsten Suehring
committed
m_sigFracBits = m_sigFracBitsArray[ scanInfo.sigCtxOffsetNext + ( sumAbs1 < 5 ? sumAbs1 : 5 ) ];
#endif

Karsten Suehring
committed
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
m_coeffFracBits = m_gtxFracBitsArray[ scanInfo.gtxCtxOffsetNext + ( sumGt1 < 4 ? sumGt1 : 4 ) ];
}
}
inline void CommonCtx::update(const ScanInfo &scanInfo, const State *prevState, State &currState)
{
uint8_t* sbbFlags = m_currSbbCtx[ currState.m_stateId ].sbbFlags;
uint8_t* levels = m_currSbbCtx[ currState.m_stateId ].levels;
std::size_t setCpSize = m_nbInfo[ scanInfo.scanIdx - 1 ].maxDist * sizeof(uint8_t);
if( prevState && prevState->m_refSbbCtxId >= 0 )
{
::memcpy( sbbFlags, m_prevSbbCtx[prevState->m_refSbbCtxId].sbbFlags, scanInfo.numSbb*sizeof(uint8_t) );
::memcpy( levels + scanInfo.scanIdx, m_prevSbbCtx[prevState->m_refSbbCtxId].levels + scanInfo.scanIdx, setCpSize );
}
else
{
::memset( sbbFlags, 0, scanInfo.numSbb*sizeof(uint8_t) );
::memset( levels + scanInfo.scanIdx, 0, setCpSize );
}
sbbFlags[ scanInfo.sbbPos ] = !!currState.m_numSigSbb;
::memcpy( levels + scanInfo.scanIdx, currState.m_absLevelsAndCtxInit, scanInfo.sbbSize*sizeof(uint8_t) );
const int sigNSbb = ( ( scanInfo.nextSbbRight ? sbbFlags[ scanInfo.nextSbbRight ] : false ) || ( scanInfo.nextSbbBelow ? sbbFlags[ scanInfo.nextSbbBelow ] : false ) ? 1 : 0 );
currState.m_numSigSbb = 0;
#if JVET_O0052_TU_LEVEL_CTX_CODED_BIN_CONSTRAINT
if (prevState)
{
currState.m_remRegBins = prevState->m_remRegBins;
}
else
{
int ctxBinSampleRatio = (scanInfo.chType == CHANNEL_TYPE_LUMA) ? MAX_TU_LEVEL_CTX_CODED_BIN_CONSTRAINT_LUMA : MAX_TU_LEVEL_CTX_CODED_BIN_CONSTRAINT_CHROMA;
currState.m_remRegBins = (currState.effWidth * currState.effHeight *ctxBinSampleRatio) / 16;
}
#else
if (scanInfo.sbbSize == 4)
{
currState.m_remRegBins = MAX_NUM_REG_BINS_2x2SUBBLOCK;
}
else
{
currState.m_remRegBins = MAX_NUM_REG_BINS_4x4SUBBLOCK;
currState.m_goRicePar = 0;

Karsten Suehring
committed
currState.m_refSbbCtxId = currState.m_stateId;
currState.m_sbbFracBits = m_sbbFlagBits[ sigNSbb ];
uint16_t templateCtxInit[16];
const int scanBeg = scanInfo.scanIdx - scanInfo.sbbSize;
const NbInfoOut* nbOut = m_nbInfo + scanBeg;
const uint8_t* absLevels = levels + scanBeg;
for( int id = 0; id < scanInfo.sbbSize; id++, nbOut++ )
{
if( nbOut->num )
{
TCoeff sumAbs = 0, sumAbs1 = 0, sumNum = 0;
#define UPDATE(k) {TCoeff t=absLevels[nbOut->outPos[k]]; sumAbs+=t; sumAbs1+=std::min<TCoeff>(4+(t&1),t); sumNum+=!!t; }

Karsten Suehring
committed
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
UPDATE(0);
if( nbOut->num > 1 )
{
UPDATE(1);
if( nbOut->num > 2 )
{
UPDATE(2);
if( nbOut->num > 3 )
{
UPDATE(3);
if( nbOut->num > 4 )
{
UPDATE(4);
}
}
}
}
#undef UPDATE
templateCtxInit[id] = uint16_t(sumNum) + ( uint16_t(sumAbs1) << 3 ) + ( (uint16_t)std::min<TCoeff>( 127, sumAbs ) << 8 );
}
else
{
templateCtxInit[id] = 0;
}
}
::memset( currState.m_absLevelsAndCtxInit, 0, 16*sizeof(uint8_t) );
::memcpy( currState.m_absLevelsAndCtxInit + 8, templateCtxInit, 16*sizeof(uint16_t) );
}
/*================================================================================*/
/*===== =====*/
/*===== T C Q =====*/
/*===== =====*/
/*================================================================================*/
class DepQuant : private RateEstimator
{
public:
DepQuant();
Chen-Yen Lai
committed
void quant ( TransformUnit& tu, const CCoeffBuf& srcCoeff, const ComponentID compID, const QpParam& cQP, const double lambda, const Ctx& ctx, TCoeff& absSum, bool enableScalingLists, int* quantCoeff );
void dequant ( const TransformUnit& tu, CoeffBuf& recCoeff, const ComponentID compID, const QpParam& cQP, bool enableScalingLists, int* quantCoeff );

Karsten Suehring
committed
private:
void xDecideAndUpdate ( const TCoeff absCoeff, const ScanInfo& scanInfo, bool zeroOut, int quantCoeff);
void xDecide ( const ScanPosType spt, const TCoeff absCoeff, const int lastOffset, Decision* decisions, bool zeroOut, int quantCoeff );

Karsten Suehring
committed
private:
CommonCtx m_commonCtx;
State m_allStates[ 12 ];
State* m_currStates;
State* m_prevStates;
State* m_skipStates;
State m_startState;
Quantizer m_quant;
Decision m_trellis[ MAX_TB_SIZEY * MAX_TB_SIZEY ][ 8 ];

Karsten Suehring
committed
};
#define TINIT(x) {*this,m_commonCtx,x}
DepQuant::DepQuant()
: RateEstimator ()
, m_commonCtx ()
, m_allStates {TINIT(0),TINIT(1),TINIT(2),TINIT(3),TINIT(0),TINIT(1),TINIT(2),TINIT(3),TINIT(0),TINIT(1),TINIT(2),TINIT(3)}
, m_currStates ( m_allStates )
, m_prevStates ( m_currStates + 4 )
, m_skipStates ( m_prevStates + 4 )
, m_startState TINIT(0)
{}
#undef TINIT
void DepQuant::dequant( const TransformUnit& tu, CoeffBuf& recCoeff, const ComponentID compID, const QpParam& cQP, bool enableScalingLists, int* piDequantCoef )

Karsten Suehring
committed
{
m_quant.dequantBlock( tu, compID, cQP, recCoeff, enableScalingLists, piDequantCoef );

Karsten Suehring
committed
}
#define DINIT(l,p) {std::numeric_limits<int64_t>::max()>>2,l,p}
static const Decision startDec[8] = {DINIT(-1,-2),DINIT(-1,-2),DINIT(-1,-2),DINIT(-1,-2),DINIT(0,4),DINIT(0,5),DINIT(0,6),DINIT(0,7)};
#undef DINIT
Chen-Yen Lai
committed
void DepQuant::xDecide( const ScanPosType spt, const TCoeff absCoeff, const int lastOffset, Decision* decisions, bool zeroOut, int quanCoeff)

Karsten Suehring
committed
{
::memcpy( decisions, startDec, 8*sizeof(Decision) );
if( zeroOut )
{
if( spt==SCAN_EOCSBB )
{
m_skipStates[0].checkRdCostSkipSbbZeroOut( decisions[0] );
m_skipStates[1].checkRdCostSkipSbbZeroOut( decisions[1] );
m_skipStates[2].checkRdCostSkipSbbZeroOut( decisions[2] );
m_skipStates[3].checkRdCostSkipSbbZeroOut( decisions[3] );
}
return;
}
#endif

Karsten Suehring
committed
PQData pqData[4];
Chen-Yen Lai
committed
m_quant.preQuantCoeff( absCoeff, pqData, quanCoeff );
m_prevStates[0].checkRdCosts( spt, pqData[0], pqData[2], decisions[0], decisions[2]);
m_prevStates[1].checkRdCosts( spt, pqData[0], pqData[2], decisions[2], decisions[0]);
m_prevStates[2].checkRdCosts( spt, pqData[3], pqData[1], decisions[1], decisions[3]);
m_prevStates[3].checkRdCosts( spt, pqData[3], pqData[1], decisions[3], decisions[1]);
#else
m_prevStates[0].checkRdCosts( spt, pqData[0], pqData[2], decisions[0], decisions[2], zeroOut );
m_prevStates[1].checkRdCosts( spt, pqData[0], pqData[2], decisions[2], decisions[0], zeroOut );
m_prevStates[2].checkRdCosts( spt, pqData[3], pqData[1], decisions[1], decisions[3], zeroOut );
m_prevStates[3].checkRdCosts( spt, pqData[3], pqData[1], decisions[3], decisions[1], zeroOut );

Karsten Suehring
committed
if( spt==SCAN_EOCSBB )
{
if( zeroOut )
{
m_skipStates[0].checkRdCostSkipSbbZeroOut( decisions[0] );
m_skipStates[1].checkRdCostSkipSbbZeroOut( decisions[1] );
m_skipStates[2].checkRdCostSkipSbbZeroOut( decisions[2] );
m_skipStates[3].checkRdCostSkipSbbZeroOut( decisions[3] );
}
else
{
m_skipStates[0].checkRdCostSkipSbb( decisions[0] );
m_skipStates[1].checkRdCostSkipSbb( decisions[1] );
m_skipStates[2].checkRdCostSkipSbb( decisions[2] );
m_skipStates[3].checkRdCostSkipSbb( decisions[3] );

Karsten Suehring
committed
}
if( !zeroOut )
{

Karsten Suehring
committed
m_startState.checkRdCostStart( lastOffset, pqData[0], decisions[0] );
m_startState.checkRdCostStart( lastOffset, pqData[2], decisions[2] );

Karsten Suehring
committed
}
void DepQuant::xDecideAndUpdate( const TCoeff absCoeff, const ScanInfo& scanInfo, bool zeroOut, int quantCoeff )

Karsten Suehring
committed
{
Decision* decisions = m_trellis[ scanInfo.scanIdx ];
std::swap( m_prevStates, m_currStates );
xDecide( scanInfo.spt, absCoeff, lastOffset(scanInfo.scanIdx), decisions, zeroOut, quantCoeff );

Karsten Suehring
committed
if( scanInfo.scanIdx )
{
if( scanInfo.eosbb )
{
m_commonCtx.swap();
m_currStates[0].updateStateEOS( scanInfo, m_prevStates, m_skipStates, decisions[0] );
m_currStates[1].updateStateEOS( scanInfo, m_prevStates, m_skipStates, decisions[1] );
m_currStates[2].updateStateEOS( scanInfo, m_prevStates, m_skipStates, decisions[2] );
m_currStates[3].updateStateEOS( scanInfo, m_prevStates, m_skipStates, decisions[3] );
::memcpy( decisions+4, decisions, 4*sizeof(Decision) );
}

Karsten Suehring
committed
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
{
switch( scanInfo.nextNbInfoSbb.num )
{
case 0:
m_currStates[0].updateState<0>( scanInfo, m_prevStates, decisions[0] );
m_currStates[1].updateState<0>( scanInfo, m_prevStates, decisions[1] );
m_currStates[2].updateState<0>( scanInfo, m_prevStates, decisions[2] );
m_currStates[3].updateState<0>( scanInfo, m_prevStates, decisions[3] );
break;
case 1:
m_currStates[0].updateState<1>( scanInfo, m_prevStates, decisions[0] );
m_currStates[1].updateState<1>( scanInfo, m_prevStates, decisions[1] );
m_currStates[2].updateState<1>( scanInfo, m_prevStates, decisions[2] );
m_currStates[3].updateState<1>( scanInfo, m_prevStates, decisions[3] );
break;
case 2:
m_currStates[0].updateState<2>( scanInfo, m_prevStates, decisions[0] );
m_currStates[1].updateState<2>( scanInfo, m_prevStates, decisions[1] );
m_currStates[2].updateState<2>( scanInfo, m_prevStates, decisions[2] );
m_currStates[3].updateState<2>( scanInfo, m_prevStates, decisions[3] );
break;
case 3:
m_currStates[0].updateState<3>( scanInfo, m_prevStates, decisions[0] );
m_currStates[1].updateState<3>( scanInfo, m_prevStates, decisions[1] );
m_currStates[2].updateState<3>( scanInfo, m_prevStates, decisions[2] );
m_currStates[3].updateState<3>( scanInfo, m_prevStates, decisions[3] );
break;
case 4:
m_currStates[0].updateState<4>( scanInfo, m_prevStates, decisions[0] );
m_currStates[1].updateState<4>( scanInfo, m_prevStates, decisions[1] );
m_currStates[2].updateState<4>( scanInfo, m_prevStates, decisions[2] );
m_currStates[3].updateState<4>( scanInfo, m_prevStates, decisions[3] );
break;
default:
m_currStates[0].updateState<5>( scanInfo, m_prevStates, decisions[0] );
m_currStates[1].updateState<5>( scanInfo, m_prevStates, decisions[1] );
m_currStates[2].updateState<5>( scanInfo, m_prevStates, decisions[2] );
m_currStates[3].updateState<5>( scanInfo, m_prevStates, decisions[3] );
}
}
if( scanInfo.spt == SCAN_SOCSBB )

Karsten Suehring
committed
{
std::swap( m_prevStates, m_skipStates );
}
}
}
Chen-Yen Lai
committed
void DepQuant::quant( TransformUnit& tu, const CCoeffBuf& srcCoeff, const ComponentID compID, const QpParam& cQP, const double lambda, const Ctx& ctx, TCoeff& absSum, bool enableScalingLists, int* quantCoeff )

Karsten Suehring
committed
{
CHECKD( tu.cs->sps->getSpsRangeExtension().getExtendedPrecisionProcessingFlag(), "ext precision is not supported" );

Karsten Suehring
committed
//===== reset / pre-init =====
const TUParameters& tuPars = *g_Rom.getTUPars( tu.blocks[compID], compID );

Karsten Suehring
committed
m_quant.initQuantBlock ( tu, compID, cQP, lambda );
TCoeff* qCoeff = tu.getCoeffs( compID ).buf;
const TCoeff* tCoeff = srcCoeff.buf;
const int numCoeff = tu.blocks[compID].area();
::memset( tu.getCoeffs( compID ).buf, 0x00, numCoeff*sizeof(TCoeff) );
absSum = 0;
const CompArea& area = tu.blocks[ compID ];
const uint32_t width = area.width;
const uint32_t height = area.height;
const uint32_t lfnstIdx = tu.cu->lfnstIdx;
//===== scaling matrix ====
//const int qpDQ = cQP.Qp + 1;
//const int qpPer = qpDQ / 6;
//const int qpRem = qpDQ - 6 * qpPer;
//TCoeff thresTmp = thres;
bool zeroOut = false;
bool zeroOutforThres = false;
int effWidth = tuPars.m_width, effHeight = tuPars.m_height;
#if JVET_O0538_SPS_CONTROL_ISP_SBT
if( ( tu.mtsIdx > MTS_SKIP || ( tu.cs->sps->getUseMTS() && tu.cu->sbtInfo != 0 && tuPars.m_height <= 32 && tuPars.m_width <= 32 ) ) && !tu.cu->transQuantBypass && compID == COMPONENT_Y )
#else
if ((tu.mtsIdx > MTS_SKIP || (tu.cu->sbtInfo != 0 && tuPars.m_height <= 32 && tuPars.m_width <= 32)) && !tu.cu->transQuantBypass && compID == COMPONENT_Y)
#endif
{
effHeight = (tuPars.m_height == 32) ? 16 : tuPars.m_height;
effWidth = (tuPars.m_width == 32) ? 16 : tuPars.m_width;
zeroOut = (effHeight < tuPars.m_height || effWidth < tuPars.m_width);
}
zeroOutforThres = zeroOut || (32 < tuPars.m_height || 32 < tuPars.m_width);

Karsten Suehring
committed
//===== find first test position =====
Chen-Yen Lai
committed
int firstTestPos = numCoeff - 1;
if( lfnstIdx > 0 && tu.mtsIdx != MTS_SKIP && width >= 4 && height >= 4 )
{
firstTestPos = ( ( width == 4 && height == 4 ) || ( width == 8 && height == 8 ) ) ? 7 : 15 ;
}
#else
if( lfnstIdx > 0 && tu.mtsIdx != MTS_SKIP && ( ( width == 4 && height == 4 ) || ( width == 8 && height == 8 ) ) )
{
firstTestPos = 7;
}
const TCoeff defaultQuantisationCoefficient = (TCoeff)m_quant.getQScale();

Karsten Suehring
committed
const TCoeff thres = m_quant.getLastThreshold();
for( ; firstTestPos >= 0; firstTestPos-- )
{
if (zeroOutforThres && (tuPars.m_scanId2BlkPos[firstTestPos].x >= ((tuPars.m_width == 32 && zeroOut) ? 16 : 32)
|| tuPars.m_scanId2BlkPos[firstTestPos].y >= ((tuPars.m_height == 32 && zeroOut) ? 16 : 32)))
Chen-Yen Lai
committed
TCoeff thresTmp = (enableScalingLists) ? TCoeff(thres / (4 * quantCoeff[tuPars.m_scanId2BlkPos[firstTestPos].idx]))
: TCoeff(thres / (4 * defaultQuantisationCoefficient));
if (abs(tCoeff[tuPars.m_scanId2BlkPos[firstTestPos].idx]) > thresTmp)

Karsten Suehring
committed
{
break;
}
}
if( firstTestPos < 0 )
{
return;
}
//===== real init =====
RateEstimator::initCtx( tuPars, tu, compID, ctx.getFracBitsAcess() );
m_commonCtx.reset( tuPars, *this );

Karsten Suehring
committed
for( int k = 0; k < 12; k++ )
{
m_allStates[k].init();
}
m_startState.init();
#if JVET_O0052_TU_LEVEL_CTX_CODED_BIN_CONSTRAINT
int effectWidth = std::min(32, effWidth);
int effectHeight = std::min(32, effHeight);
for (int k = 0; k < 12; k++)
{
m_allStates[k].effWidth = effectWidth;
m_allStates[k].effHeight = effectHeight;
}
m_startState.effWidth = effectWidth;
m_startState.effHeight = effectHeight;
#endif

Karsten Suehring
committed
//===== populate trellis =====
for( int scanIdx = firstTestPos; scanIdx >= 0; scanIdx-- )
{
const ScanInfo& scanInfo = tuPars.m_scanInfo[ scanIdx ];
bool lfnstZeroOut = lfnstIdx > 0 && tu.mtsIdx != MTS_SKIP && width >= 4 && height >= 4 &&
( ( ( ( width >= 8 && height >= 8 ) && scanIdx >= 16 ) || ( ( ( width == 4 && height == 4 ) || ( width == 8 && height == 8 ) ) && scanIdx >= 8 ) ) && scanIdx < 48 );
Chen-Yen Lai
committed
m_quant.initQuantBlock(tu, compID, cQP, lambda, quantCoeff[scanInfo.rasterPos]);
xDecideAndUpdate( abs( tCoeff[scanInfo.rasterPos]), scanInfo, (zeroOut && (scanInfo.posX >= effWidth || scanInfo.posY >= effHeight)) || lfnstZeroOut, quantCoeff[scanInfo.rasterPos] );
else
xDecideAndUpdate( abs( tCoeff[scanInfo.rasterPos]), scanInfo, (zeroOut && (scanInfo.posX >= effWidth || scanInfo.posY >= effHeight)) || lfnstZeroOut, defaultQuantisationCoefficient );
#else
if (enableScalingLists)
{
m_quant.initQuantBlock(tu, compID, cQP, lambda, quantCoeff[scanInfo.rasterPos]);
xDecideAndUpdate( abs( tCoeff[scanInfo.rasterPos]), scanInfo, (zeroOut && (scanInfo.posX >= effWidth || scanInfo.posY >= effHeight)), quantCoeff[scanInfo.rasterPos] );
}
else
xDecideAndUpdate( abs( tCoeff[scanInfo.rasterPos]), scanInfo, (zeroOut && (scanInfo.posX >= effWidth || scanInfo.posY >= effHeight)), defaultQuantisationCoefficient );
#endif

Karsten Suehring
committed
//===== find best path =====
Decision decision = { std::numeric_limits<int64_t>::max(), -1, -2 };
int64_t minPathCost = 0;
for( int8_t stateId = 0; stateId < 4; stateId++ )
{
int64_t pathCost = m_trellis[0][stateId].rdCost;
if( pathCost < minPathCost )
{
decision.prevId = stateId;
minPathCost = pathCost;
}
}
//===== backward scanning =====
int scanIdx = 0;
for( ; decision.prevId >= 0; scanIdx++ )
{
decision = m_trellis[ scanIdx ][ decision.prevId ];
int32_t blkpos = tuPars.m_scanId2BlkPos[scanIdx].idx;

Karsten Suehring
committed
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
qCoeff[ blkpos ] = ( tCoeff[ blkpos ] < 0 ? -decision.absLevel : decision.absLevel );
absSum += decision.absLevel;
}
}
}; // namespace DQIntern
//===== interface class =====
DepQuant::DepQuant( const Quant* other, bool enc ) : QuantRDOQ( other )
{
const DepQuant* dq = dynamic_cast<const DepQuant*>( other );
CHECK( other && !dq, "The DepQuant cast must be successfull!" );
p = new DQIntern::DepQuant();
if( enc )
{
DQIntern::g_Rom.init();
}
}
DepQuant::~DepQuant()
{
delete static_cast<DQIntern::DepQuant*>(p);
}
void DepQuant::quant( TransformUnit &tu, const ComponentID &compID, const CCoeffBuf &pSrc, TCoeff &uiAbsSum, const QpParam &cQP, const Ctx& ctx )
{
if( tu.cs->slice->getDepQuantEnabledFlag() && (tu.mtsIdx != MTS_SKIP || !isLuma(compID)) )

Karsten Suehring
committed
{
#if JVET_O0919_TS_MIN_QP
const int qpDQ = cQP.Qp(tu.mtsIdx==MTS_SKIP && isLuma(compID)) + 1;
#else
const int qpPer = qpDQ / 6;
const int qpRem = qpDQ - 6 * qpPer;
const CompArea &rect = tu.blocks[compID];
Chen-Yen Lai
committed
const int width = rect.width;
const int height = rect.height;
uint32_t scalingListType = getScalingListType(tu.cu->predMode, compID);
CHECK(scalingListType >= SCALING_LIST_NUM, "Invalid scaling list");
Chen-Yen Lai
committed
const uint32_t log2TrWidth = g_aucLog2[width];
const uint32_t log2TrHeight = g_aucLog2[height];
const bool enableScalingLists = getUseScalingList(width, height, (tu.mtsIdx == MTS_SKIP && isLuma(compID)));
Chen-Yen Lai
committed
static_cast<DQIntern::DepQuant*>(p)->quant( tu, pSrc, compID, cQP, Quant::m_dLambda, ctx, uiAbsSum, enableScalingLists, Quant::getQuantCoeff(scalingListType, qpRem, log2TrWidth, log2TrHeight) );

Karsten Suehring
committed
}
else
{
QuantRDOQ::quant( tu, compID, pSrc, uiAbsSum, cQP, ctx );
}
}
void DepQuant::dequant( const TransformUnit &tu, CoeffBuf &dstCoeff, const ComponentID &compID, const QpParam &cQP )
{
if( tu.cs->slice->getDepQuantEnabledFlag() && (tu.mtsIdx != MTS_SKIP || !isLuma(compID)) )

Karsten Suehring
committed
{
#if JVET_O0919_TS_MIN_QP
const int qpDQ = cQP.Qp(tu.mtsIdx==MTS_SKIP && isLuma(compID)) + 1;
#else
const int qpPer = qpDQ / 6;
const int qpRem = qpDQ - 6 * qpPer;
const CompArea &rect = tu.blocks[compID];
Chen-Yen Lai
committed
const int width = rect.width;
const int height = rect.height;
uint32_t scalingListType = getScalingListType(tu.cu->predMode, compID);
CHECK(scalingListType >= SCALING_LIST_NUM, "Invalid scaling list");
Chen-Yen Lai
committed
const uint32_t log2TrWidth = g_aucLog2[width];
const uint32_t log2TrHeight = g_aucLog2[height];
const bool enableScalingLists = getUseScalingList(width, height, (tu.mtsIdx == MTS_SKIP && isLuma(compID)));
Chen-Yen Lai
committed
static_cast<DQIntern::DepQuant*>(p)->dequant( tu, dstCoeff, compID, cQP, enableScalingLists, Quant::getDequantCoeff(scalingListType, qpRem, log2TrWidth, log2TrHeight) );