Newer
Older

Karsten Suehring
committed
CodingUnit &cu = tempCS->addCU( tempCS->area, partitioner.chType );
partitioner.setCUData( cu );
cu.slice = tempCS->slice;
#if HEVC_TILES_WPP
cu.tileIdx = tempCS->picture->tileMap->getTileIdxMap( tempCS->area.lumaPos() );
#endif
cu.skip = false;
cu.mmvdSkip = false;

Karsten Suehring
committed
//cu.affine
cu.predMode = MODE_INTER;
cu.transQuantBypass = encTestMode.lossless;
cu.chromaQpAdj = cu.transQuantBypass ? 0 : m_cuChromaQpOffsetIdxPlus1;
cu.qp = encTestMode.qp;
CU::addPUs( cu );
cu.GBiIdx = g_GbiSearchOrder[gbiLoopIdx];
uint8_t gbiIdx = cu.GBiIdx;
bool testGbi = (gbiIdx != GBI_DEFAULT);

Karsten Suehring
committed
m_pcInterSearch->predInterSearch( cu, partitioner );
gbiIdx = CU::getValidGbiIdx(cu);
if( testGbi && gbiIdx == GBI_DEFAULT ) // Enabled GBi but the search results is uni.
{
tempCS->initStructData(encTestMode.qp, encTestMode.lossless);
continue;
}
CHECK(!(testGbi || (!testGbi && gbiIdx == GBI_DEFAULT)), " !( bTestGbi || (!bTestGbi && gbiIdx == GBI_DEFAULT ) )");
bool isEqualUni = false;
if( m_pcEncCfg->getUseGBiFast() )
{
if( cu.firstPU->interDir != 3 && testGbi == 0 )
{
isEqualUni = true;
}
}
#if JVET_M0464_UNI_MTS
xEncodeInterResidual( tempCS, bestCS, partitioner, encTestMode, 0
, 0
, &equGBiCost
#else
xEncodeInterResidual( tempCS, bestCS, partitioner, encTestMode, 0
, 1
, 0
);
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
if( g_GbiSearchOrder[gbiLoopIdx] == GBI_DEFAULT )
m_pcInterSearch->setAffineModeSelected((bestCS->cus.front()->affine && !(bestCS->cus.front()->firstPU->mergeFlag)));
tempCS->initStructData(encTestMode.qp, encTestMode.lossless);
double skipTH = MAX_DOUBLE;
skipTH = (m_pcEncCfg->getUseGBiFast() ? 1.05 : MAX_DOUBLE);
if( equGBiCost > curBestCost * skipTH )
{
break;
}
if( m_pcEncCfg->getUseGBiFast() )
{
if( isEqualUni == true && m_pcEncCfg->getIntraPeriod() == -1 )
{
break;
}
}
if( g_GbiSearchOrder[gbiLoopIdx] == GBI_DEFAULT && xIsGBiSkip(cu) && m_pcEncCfg->getUseGBiFast() )
{
break;
}
} // for( UChar gbiLoopIdx = 0; gbiLoopIdx < gbiLoopNum; gbiLoopIdx++ )
if ( m_bestModeUpdated && bestCS->cost != MAX_DOUBLE )
{
xCalDebCost( *bestCS, partitioner );
}

Karsten Suehring
committed
}
bool EncCu::xCheckRDCostInterIMV( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode )
{
int iIMV = int( ( encTestMode.opts & ETO_IMV ) >> ETO_IMV_SHIFT );
m_pcInterSearch->setAffineModeSelected(false);

Karsten Suehring
committed
// Only int-Pel, 4-Pel and fast 4-Pel allowed
CHECK( iIMV != 1 && iIMV != 2 && iIMV != 3, "Unsupported IMV Mode" );
// Fast 4-Pel Mode
#if JVET_M0428_ENC_DB_OPT
m_bestModeUpdated = tempCS->useDbCost = bestCS->useDbCost = false;
#endif

Karsten Suehring
committed
EncTestMode encTestModeBase = encTestMode; // copy for clearing non-IMV options
encTestModeBase.opts = EncTestModeOpts( encTestModeBase.opts & ETO_IMV ); // clear non-IMV options (is that intended?)
tempCS->initStructData( encTestMode.qp, encTestMode.lossless );
m_pcInterSearch->resetBufferedUniMotions();
int gbiLoopNum = (tempCS->slice->isInterB() ? GBI_NUM : 1);
gbiLoopNum = (tempCS->slice->getSPS()->getUseGBi() ? gbiLoopNum : 1);
if( tempCS->area.lwidth() * tempCS->area.lheight() < GBI_SIZE_CONSTRAINT )
{
gbiLoopNum = 1;
}
#if JVET_M0246_AFFINE_AMVR
bool validMode = false;
#endif
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
double curBestCost = bestCS->cost;
double equGBiCost = MAX_DOUBLE;
for( int gbiLoopIdx = 0; gbiLoopIdx < gbiLoopNum; gbiLoopIdx++ )
{
if( m_pcEncCfg->getUseGBiFast() )
{
auto blkCache = dynamic_cast< CacheBlkInfoCtrl* >(m_modeCtrl);
if( blkCache )
{
bool isBestInter = blkCache->getInter(bestCS->area);
uint8_t bestGBiIdx = blkCache->getGbiIdx(bestCS->area);
if( isBestInter && g_GbiSearchOrder[gbiLoopIdx] != GBI_DEFAULT && g_GbiSearchOrder[gbiLoopIdx] != bestGBiIdx )
{
continue;
}
}
}
if( !tempCS->slice->getCheckLDC() )
{
if( gbiLoopIdx != 0 && gbiLoopIdx != 3 && gbiLoopIdx != 4 )
{
continue;
}
}
if( m_pcEncCfg->getUseGBiFast() && tempCS->slice->getCheckLDC() && g_GbiSearchOrder[gbiLoopIdx] != GBI_DEFAULT
&& (m_bestGbiIdx[0] >= 0 && g_GbiSearchOrder[gbiLoopIdx] != m_bestGbiIdx[0])
&& (m_bestGbiIdx[1] >= 0 && g_GbiSearchOrder[gbiLoopIdx] != m_bestGbiIdx[1]))
{
continue;
}
CodingUnit &cu = tempCS->addCU( tempCS->area, partitioner.chType );

Karsten Suehring
committed
partitioner.setCUData( cu );
cu.slice = tempCS->slice;

Karsten Suehring
committed
#if HEVC_TILES_WPP
cu.tileIdx = tempCS->picture->tileMap->getTileIdxMap( tempCS->area.lumaPos() );

Karsten Suehring
committed
#endif
cu.skip = false;
cu.mmvdSkip = false;
//cu.affine
cu.predMode = MODE_INTER;
cu.transQuantBypass = encTestMode.lossless;
cu.chromaQpAdj = cu.transQuantBypass ? 0 : m_cuChromaQpOffsetIdxPlus1;
cu.qp = encTestMode.qp;

Karsten Suehring
committed

Karsten Suehring
committed
cu.imv = iIMV > 1 ? 2 : 1;

Karsten Suehring
committed
cu.emtFlag = false;

Karsten Suehring
committed
bool testGbi;
uint8_t gbiIdx;
#if JVET_M0246_AFFINE_AMVR
bool affineAmvrEanbledFlag = cu.slice->getSPS()->getAffineAmvrEnabledFlag();
#endif
cu.GBiIdx = g_GbiSearchOrder[gbiLoopIdx];
gbiIdx = cu.GBiIdx;
testGbi = (gbiIdx != GBI_DEFAULT);
#if JVET_M0246_AFFINE_AMVR
m_pcInterSearch->predInterSearch( cu, partitioner );
#if JVET_M0246_AFFINE_AMVR
if ( cu.firstPU->interDir <= 3 )
{
gbiIdx = CU::getValidGbiIdx(cu);

Karsten Suehring
committed
}
else
{

Karsten Suehring
committed
if( m_pcEncCfg->getMCTSEncConstraint() && ( ( cu.firstPU->refIdx[L0] < 0 && cu.firstPU->refIdx[L1] < 0 ) || ( !( MCTSHelper::checkMvBufferForMCTSConstraint( *cu.firstPU ) ) ) ) )
{
// Do not use this mode
tempCS->initStructData( encTestMode.qp, encTestMode.lossless );
continue;
}
#endif
if( testGbi && gbiIdx == GBI_DEFAULT ) // Enabled GBi but the search results is uni.
{
tempCS->initStructData(encTestMode.qp, encTestMode.lossless);
continue;
}
CHECK(!(testGbi || (!testGbi && gbiIdx == GBI_DEFAULT)), " !( bTestGbi || (!bTestGbi && gbiIdx == GBI_DEFAULT ) )");
bool isEqualUni = false;
if( m_pcEncCfg->getUseGBiFast() )
{
if( cu.firstPU->interDir != 3 && testGbi == 0 )
{
isEqualUni = true;
}
}
#if JVET_M0246_AFFINE_AMVR
if ( !CU::hasSubCUNonZeroMVd( cu ) && !CU::hasSubCUNonZeroAffineMVd( cu ) )
#else

Karsten Suehring
committed
if( !CU::hasSubCUNonZeroMVd( cu ) )

Karsten Suehring
committed
{
if (m_modeCtrl->useModeResult(encTestModeBase, tempCS, partitioner))
{
std::swap(tempCS, bestCS);
// store temp best CI for next CU coding
m_CurrCtx->best = m_CABACEstimator->getCtx();
}
#if JVET_M0246_AFFINE_AMVR
if ( affineAmvrEanbledFlag )
{
tempCS->initStructData( encTestMode.qp, encTestMode.lossless );
continue;
}
else
{
return false;
}
#else

Karsten Suehring
committed
return false;

Karsten Suehring
committed
}
#if JVET_M0464_UNI_MTS
xEncodeInterResidual( tempCS, bestCS, partitioner, encTestModeBase, 0
, 0
, &equGBiCost
#else
xEncodeInterResidual( tempCS, bestCS, partitioner, encTestModeBase, 0
, true
, 0

Karsten Suehring
committed
tempCS->initStructData(encTestMode.qp, encTestMode.lossless);
double skipTH = MAX_DOUBLE;
skipTH = (m_pcEncCfg->getUseGBiFast() ? 1.05 : MAX_DOUBLE);
if( equGBiCost > curBestCost * skipTH )
{
break;
}
if( m_pcEncCfg->getUseGBiFast() )
{
if( isEqualUni == true && m_pcEncCfg->getIntraPeriod() == -1 )
{
break;
}
}
if( g_GbiSearchOrder[gbiLoopIdx] == GBI_DEFAULT && xIsGBiSkip(cu) && m_pcEncCfg->getUseGBiFast() )
{
break;
}
#if JVET_M0246_AFFINE_AMVR
validMode = true;
#endif
} // for( UChar gbiLoopIdx = 0; gbiLoopIdx < gbiLoopNum; gbiLoopIdx++ )
if ( m_bestModeUpdated && bestCS->cost != MAX_DOUBLE )
{
xCalDebCost( *bestCS, partitioner );
}
#if JVET_M0246_AFFINE_AMVR
return tempCS->slice->getSPS()->getAffineAmvrEnabledFlag() ? validMode : true;
#else

Karsten Suehring
committed
return true;

Karsten Suehring
committed
}
void EncCu::xCalDebCost( CodingStructure &cs, Partitioner &partitioner, bool calDist )
if ( cs.slice->getDeblockingFilterDisable() || ( !m_pcEncCfg->getUseEncDbOpt() && !calDist ) )
{
m_pcLoopFilter->setEnc(true);
const ChromaFormat format = cs.area.chromaFormat;
CodingUnit* cu = cs.getCU(partitioner.chType);
const Position lumaPos = cu->Y().valid() ? cu->Y().pos() : recalcPosition( format, cu->chType, CHANNEL_TYPE_LUMA, cu->blocks[cu->chType].pos() );
bool topEdgeAvai = lumaPos.y > 0 && ( ( lumaPos.y % 8 ) == 0 );
bool leftEdgeAvai = lumaPos.x > 0 && ( ( lumaPos.x % 8 ) == 0 );
bool anyEdgeAvai = topEdgeAvai || leftEdgeAvai;
cs.costDbOffset = 0;
const UnitArea currCsArea = clipArea( CS::getArea( cs, cs.area, partitioner.chType ), *cs.picture );
ComponentID compStr = ( CS::isDualITree( cs ) && !isLuma( partitioner.chType ) ) ? COMPONENT_Cb : COMPONENT_Y;
ComponentID compEnd = ( CS::isDualITree( cs ) && isLuma( partitioner.chType ) ) ? COMPONENT_Y : COMPONENT_Cr;
const ComponentID compID = ComponentID( comp );
CPelBuf org = cs.getOrgBuf( compID );
CPelBuf reco = cs.getRecoBuf( compID );
finalDistortion += getDistortionDb( cs, org, reco, compID, currCsArea.block( compID ), false );
ComponentID compStr = ( CS::isDualITree( cs ) && !isLuma( partitioner.chType ) ) ? COMPONENT_Cb : COMPONENT_Y;
ComponentID compEnd = ( CS::isDualITree( cs ) && isLuma( partitioner.chType ) ) ? COMPONENT_Y : COMPONENT_Cr;
const UnitArea currCsArea = clipArea( CS::getArea( cs, cs.area, partitioner.chType ), *cs.picture );
PelStorage& picDbBuf = m_pcLoopFilter->getDbEncPicYuvBuffer();
//deblock neighbour pixels
const Size lumaSize = cu->Y().valid() ? cu->Y().size() : recalcSize( format, cu->chType, CHANNEL_TYPE_LUMA, cu->blocks[cu->chType].size() );
#if JVET_M0471_LONG_DEBLOCKING_FILTERS
const int verOffset = lumaPos.y > 7 ? 8 : 4;
const int horOffset = lumaPos.x > 7 ? 8 : 4;
#else
const int verOffset = 4;
const int horOffset = 4;
#endif
const UnitArea areaTop( format, Area( lumaPos.x, lumaPos.y - verOffset, lumaSize.width, verOffset ) );
const UnitArea areaLeft( format, Area( lumaPos.x - horOffset, lumaPos.y, horOffset, lumaSize.height ) );
for ( int compIdx = compStr; compIdx <= compEnd; compIdx++ )
{
ComponentID compId = (ComponentID)compIdx;
//Copy current CU's reco to Deblock Pic Buffer
const CompArea& curCompArea = currCsArea.block( compId );
picDbBuf.getBuf( curCompArea ).copyFrom( cs.getRecoBuf( curCompArea ) );
if ( cs.slice->getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getSliceReshaperInfo().getUseSliceReshaper() && isLuma( compId ) )
picDbBuf.getBuf( curCompArea ).rspSignal( m_pcReshape->getInvLUT() );
picDbBuf.getBuf( compArea ).copyFrom( cs.picture->getRecoBuf( compArea ) );
if ( cs.slice->getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getSliceReshaperInfo().getUseSliceReshaper() && isLuma( compId ) )
picDbBuf.getBuf( compArea ).rspSignal( m_pcReshape->getInvLUT() );
const CompArea& compArea = areaTop.block( compId );
picDbBuf.getBuf( compArea ).copyFrom( cs.picture->getRecoBuf( compArea ) );
if ( cs.slice->getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getSliceReshaperInfo().getUseSliceReshaper() && isLuma( compId ) )
picDbBuf.getBuf( compArea ).rspSignal( m_pcReshape->getInvLUT() );
for ( int compIdx = compStr; compIdx <= compEnd; compIdx++ )
CPelBuf reco = picDbBuf.getBuf( currCsArea.block( compId ) );
CPelBuf org = cs.getOrgBuf( compId );
distCur += getDistortionDb( cs, org, reco, compId, currCsArea.block( compId ), true );
}
//calculate difference between DB_before_SSE and DB_after_SSE for neighbouring CUs
Distortion distBeforeDb = 0, distAfterDb = 0;
for (int compIdx = compStr; compIdx <= compEnd; compIdx++)
{
ComponentID compId = (ComponentID)compIdx;
const CompArea& compArea = areaLeft.block( compId );
CPelBuf org = cs.picture->getOrigBuf( compArea );
CPelBuf reco = cs.picture->getRecoBuf( compArea );
CPelBuf recoDb = picDbBuf.getBuf( compArea );
distBeforeDb += getDistortionDb( cs, org, reco, compId, compArea, false );
distAfterDb += getDistortionDb( cs, org, recoDb, compId, compArea, true );
const CompArea& compArea = areaTop.block( compId );
CPelBuf org = cs.picture->getOrigBuf( compArea );
CPelBuf reco = cs.picture->getRecoBuf( compArea );
CPelBuf recoDb = picDbBuf.getBuf( compArea );
distBeforeDb += getDistortionDb( cs, org, reco, compId, compArea, false );
distAfterDb += getDistortionDb( cs, org, recoDb, compId, compArea, true );
}
}
//updated cost
int64_t distTmp = distCur - cs.dist + distAfterDb - distBeforeDb;
int sign = distTmp < 0 ? -1 : 1;
distTmp = distTmp < 0 ? -distTmp : distTmp;
cs.costDbOffset = sign * m_pcRdCost->calcRdCost( 0, distTmp );
Distortion EncCu::getDistortionDb( CodingStructure &cs, CPelBuf org, CPelBuf reco, ComponentID compID, const CompArea& compArea, bool afterDb )
CPelBuf orgLuma = cs.picture->getOrigBuf( cs.area.blocks[COMPONENT_Y] );
if ( m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled() || (
m_pcEncCfg->getReshaper() && ( cs.slice->getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag() ) ) )
if ( m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled() )
if ( compID == COMPONENT_Y && !afterDb && !m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled())
CompArea tmpArea( COMPONENT_Y, cs.area.chromaFormat, Position( 0, 0 ), compArea.size() );
PelBuf tmpRecLuma = m_tmpStorageLCU->getBuf( tmpArea );
tmpRecLuma.copyFrom( reco );
tmpRecLuma.rspSignal( m_pcReshape->getInvLUT() );
dist += m_pcRdCost->getDistPart( org, tmpRecLuma, cs.sps->getBitDepth( toChannelType( compID ) ), compID, DF_SSE_WTD, &orgLuma );
dist += m_pcRdCost->getDistPart( org, reco, cs.sps->getBitDepth( toChannelType( compID ) ), compID, DF_SSE_WTD, &orgLuma );
else if ( m_pcEncCfg->getReshaper() && cs.slice->getReshapeInfo().getUseSliceReshaper() && cs.slice->isIntra() ) //intra slice
CompArea tmpArea( COMPONENT_Y, cs.area.chromaFormat, Position( 0, 0 ), compArea.size() );
PelBuf tmpRecLuma = m_tmpStorageLCU->getBuf( tmpArea );
tmpRecLuma.copyFrom( reco );
tmpRecLuma.rspSignal( m_pcReshape->getFwdLUT() );
dist += m_pcRdCost->getDistPart( org, tmpRecLuma, cs.sps->getBitDepth( toChannelType( compID ) ), compID, DF_SSE );
dist += m_pcRdCost->getDistPart( org, reco, cs.sps->getBitDepth(toChannelType( compID ) ), compID, DF_SSE );
dist = m_pcRdCost->getDistPart( org, reco, cs.sps->getBitDepth( toChannelType( compID ) ), compID, DF_SSE );
#if JVET_M0464_UNI_MTS
void EncCu::xEncodeInterResidual( CodingStructure *&tempCS
, CodingStructure *&bestCS
, Partitioner &partitioner
, const EncTestMode& encTestMode
, int residualPass
, bool* bestHasNonResi
, double* equGBiCost
#else
void EncCu::xEncodeInterResidual( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode, int residualPass
, CodingStructure* imvCS
, int emtMode
, bool* bestHasNonResi

Karsten Suehring
committed
{
if( residualPass == 1 && encTestMode.lossless )
{
return;
}
CodingUnit* cu = tempCS->getCU( partitioner.chType );
double bestCostInternal = MAX_DOUBLE;
double bestCost = bestCS->cost;
#if JVET_M0140_SBT
double bestCostBegin = bestCS->cost;
CodingUnit* prevBestCU = bestCS->getCU( partitioner.chType );
uint8_t prevBestSbt = ( prevBestCU == nullptr ) ? 0 : prevBestCU->sbtInfo;
#endif
const SPS& sps = *tempCS->sps;
const int maxSizeEMT = EMT_INTER_MAX_CU_WITH_QTBT;
bool swapped = false; // avoid unwanted data copy
bool reloadCU = false;
const bool considerEmtSecondPass = emtMode && sps.getUseInterEMT() && partitioner.currArea().lwidth() <= maxSizeEMT && partitioner.currArea().lheight() <= maxSizeEMT;
int minEMTMode = 0;
int maxEMTMode = (considerEmtSecondPass?1:0);

Karsten Suehring
committed
// Not allow very big |MVd| to avoid CABAC crash caused by too large MVd. Normally no impact on coding performance.
const int maxMvd = 1 << 15;
const PredictionUnit& pu = *cu->firstPU;
if (!cu->affine)
{
if ((pu.refIdx[0] >= 0 && (pu.mvd[0].getAbsHor() >= maxMvd || pu.mvd[0].getAbsVer() >= maxMvd))
|| (pu.refIdx[1] >= 0 && (pu.mvd[1].getAbsHor() >= maxMvd || pu.mvd[1].getAbsVer() >= maxMvd)))
{
return;
}
}
Xiang Li
committed
else
{
for (int refList = 0; refList < NUM_REF_PIC_LIST_01; refList++)
{
if (pu.refIdx[refList] >= 0)
{
for (int ctrlP = 1 + (cu->affineType == AFFINEMODEL_6PARAM); ctrlP >= 0; ctrlP--)
{
if (pu.mvdAffi[refList][ctrlP].getAbsHor() >= maxMvd || pu.mvdAffi[refList][ctrlP].getAbsVer() >= maxMvd)
{
return;
}
}
}
}
}
Yin Zhao
committed
#if JVET_M0464_UNI_MTS
const bool mtsAllowed = tempCS->sps->getUseInterMTS() && CU::isInter( *cu ) && partitioner.currArea().lwidth() <= MTS_INTER_MAX_CU_SIZE && partitioner.currArea().lheight() <= MTS_INTER_MAX_CU_SIZE;
Yin Zhao
committed
#else
const bool mtsAllowed = considerEmtSecondPass;
#endif
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
uint8_t sbtAllowed = cu->checkAllowedSbt();
uint8_t numRDOTried = 0;
Distortion sbtOffDist = 0;
bool sbtOffRootCbf = 0;
double sbtOffCost = MAX_DOUBLE;
double currBestCost = MAX_DOUBLE;
bool doPreAnalyzeResi = ( sbtAllowed || mtsAllowed ) && residualPass == 0;
m_pcInterSearch->initTuAnalyzer();
if( doPreAnalyzeResi )
{
m_pcInterSearch->calcMinDistSbt( *tempCS, *cu, sbtAllowed );
}
auto slsSbt = dynamic_cast<SaveLoadEncInfoSbt*>( m_modeCtrl );
int slShift = 4 + std::min( (int)gp_sizeIdxInfo->idxFrom( cu->lwidth() ) + (int)gp_sizeIdxInfo->idxFrom( cu->lheight() ), 9 );
Distortion curPuSse = m_pcInterSearch->getEstDistSbt( NUMBER_SBT_MODE );
uint8_t currBestSbt = 0;
uint8_t currBestTrs = MAX_UCHAR;
uint8_t histBestSbt = MAX_UCHAR;
uint8_t histBestTrs = MAX_UCHAR;
m_pcInterSearch->setHistBestTrs( MAX_UCHAR, MAX_UCHAR );
if( doPreAnalyzeResi )
{
if( m_pcInterSearch->getSkipSbtAll() && !mtsAllowed ) //emt is off
{
histBestSbt = 0; //try DCT2
m_pcInterSearch->setHistBestTrs( histBestSbt, histBestTrs );
}
else
{
assert( curPuSse != std::numeric_limits<uint64_t>::max() );
uint16_t compositeSbtTrs = slsSbt->findBestSbt( cu->cs->area, (uint32_t)( curPuSse >> slShift ) );
histBestSbt = ( compositeSbtTrs >> 0 ) & 0xff;
histBestTrs = ( compositeSbtTrs >> 8 ) & 0xff;
if( m_pcInterSearch->getSkipSbtAll() && CU::isSbtMode( histBestSbt ) ) //special case, skip SBT when loading SBT
{
histBestSbt = 0; //try DCT2
}
m_pcInterSearch->setHistBestTrs( histBestSbt, histBestTrs );
}
}
#endif
if( emtMode == 2 )
{
minEMTMode = maxEMTMode = (cu->emtFlag?1:0);
}

Karsten Suehring
committed
for( int curEmtMode = minEMTMode; curEmtMode <= maxEMTMode; curEmtMode++ )

Karsten Suehring
committed
{
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
4661
4662
4663
4664
4665
4666
4667
4668
4669
4670
4671
4672
4673
4674
if( reloadCU )
{
if( bestCost == bestCS->cost ) //The first EMT pass didn't become the bestCS, so we clear the TUs generated
{
tempCS->clearTUs();
}
else if( false == swapped )
{
tempCS->initStructData( encTestMode.qp, encTestMode.lossless );
tempCS->copyStructure( *bestCS, partitioner.chType );
tempCS->getPredBuf().copyFrom( bestCS->getPredBuf() );
bestCost = bestCS->cost;
cu = tempCS->getCU( partitioner.chType );
swapped = true;
}
else
{
tempCS->clearTUs();
bestCost = bestCS->cost;
cu = tempCS->getCU( partitioner.chType );
}
//we need to restart the distortion for the new tempCS, the bit count and the cost
tempCS->dist = 0;
tempCS->fracBits = 0;
tempCS->cost = MAX_DOUBLE;
}
reloadCU = true; // enable cu reloading

Karsten Suehring
committed
cu->skip = false;
cu->emtFlag = curEmtMode;
#if JVET_M0140_SBT
cu->sbtInfo = 0;
#endif

Karsten Suehring
committed
const bool skipResidual = residualPass == 1;
#if JVET_M0140_SBT // skip DCT-2 and EMT if historical best transform mode is SBT
if( skipResidual || histBestSbt == MAX_UCHAR || !CU::isSbtMode( histBestSbt ) )
{
#endif

Karsten Suehring
committed
m_pcInterSearch->encodeResAndCalcRdInterCU( *tempCS, partitioner, skipResidual );
Yin Zhao
committed
#if JVET_M0464_UNI_MTS
numRDOTried += mtsAllowed ? 2 : 1;
Yin Zhao
committed
#else
numRDOTried++;
#endif

Karsten Suehring
committed
xEncodeDontSplit( *tempCS, partitioner );
xCheckDQP( *tempCS, partitioner );
#if !JVET_M0140_SBT //harmonize with GBI fast algorithm (move the code to the end of this function)
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
if( ETM_INTER_ME == encTestMode.type )
{
if( equGBiCost != NULL )
{
if( tempCS->cost < (*equGBiCost) && cu->GBiIdx == GBI_DEFAULT )
{
(*equGBiCost) = tempCS->cost;
}
}
else
{
CHECK(equGBiCost == NULL, "equGBiCost == NULL");
}
if( tempCS->slice->getCheckLDC() && !cu->imv && cu->GBiIdx != GBI_DEFAULT && tempCS->cost < m_bestGbiCost[1] )
{
if( tempCS->cost < m_bestGbiCost[0] )
{
m_bestGbiCost[1] = m_bestGbiCost[0];
m_bestGbiCost[0] = tempCS->cost;
m_bestGbiIdx[1] = m_bestGbiIdx[0];
m_bestGbiIdx[0] = cu->GBiIdx;
}
else
{
m_bestGbiCost[1] = tempCS->cost;
m_bestGbiIdx[1] = cu->GBiIdx;
}
}
}
double emtFirstPassCost = tempCS->cost;

Karsten Suehring
committed
if( NULL != bestHasNonResi && (bestCostInternal > tempCS->cost) )
{
bestCostInternal = tempCS->cost;
if (!(tempCS->getPU(partitioner.chType)->mhIntraFlag))

Karsten Suehring
committed
*bestHasNonResi = !cu->rootCbf;
}
if (cu->rootCbf == false)
{
if (tempCS->getPU(partitioner.chType)->mhIntraFlag)
{
tempCS->cost = MAX_DOUBLE;
return;
}
}
Yin Zhao
committed
#if JVET_M0464_UNI_MTS
currBestCost = tempCS->cost;
sbtOffCost = tempCS->cost;
sbtOffDist = tempCS->dist;
sbtOffRootCbf = cu->rootCbf;
currBestSbt = CU::getSbtInfo( cu->firstTU->mtsIdx > 1 ? SBT_OFF_MTS : SBT_OFF_DCT, 0 );
currBestTrs = cu->firstTU->mtsIdx;
Yin Zhao
committed
#else
if( curEmtMode == 0 )
{
currBestCost = tempCS->cost;
sbtOffCost = tempCS->cost;
sbtOffDist = tempCS->dist;
sbtOffRootCbf = cu->rootCbf;
}
else
{
if( tempCS->cost < currBestCost )
{
currBestSbt = CU::getSbtInfo(SBT_OFF_MTS, 0);
currBestTrs = cu->firstTU->emtIdx;
currBestCost = tempCS->cost;
}
}
#endif
if( cu->lwidth() <= MAX_TB_SIZEY && cu->lheight() <= MAX_TB_SIZEY )
{
CHECK( tempCS->tus.size() != 1, "tu must be only one" );
}
#endif

Karsten Suehring
committed
#if WCG_EXT
DTRACE_MODE_COST( *tempCS, m_pcRdCost->getLambda( true ) );
#else
DTRACE_MODE_COST( *tempCS, m_pcRdCost->getLambda() );
#endif
xCheckBestMode( tempCS, bestCS, partitioner, encTestMode );
//now we check whether the second pass should be skipped or not
Yin Zhao
committed
#if JVET_M0140_SBT
if( !curEmtMode && maxEMTMode && !CU::isMtsMode(histBestSbt) )
#else
if( !curEmtMode && maxEMTMode )
Yin Zhao
committed
#endif
{
const double thresholdToSkipEmtSecondPass = 1.1; // Skip checking EMT transforms
const bool bCond1 = !cu->firstTU->cbf[COMPONENT_Y];

Karsten Suehring
committed
const bool bCond3 = emtFirstPassCost > ( bestCost * thresholdToSkipEmtSecondPass );
if( m_pcEncCfg->getFastInterEMT() && (bCond1 || bCond3 ) )
{
maxEMTMode = 0; // do not test EMT
}
}
#endif
#if JVET_M0140_SBT // skip DCT-2 and EMT
}
#endif
#if JVET_M0140_SBT //RDO for SBT
Yin Zhao
committed
#if !JVET_M0464_UNI_MTS // skip EMT
if( histBestSbt != MAX_UCHAR && !CU::isMtsMode(histBestSbt) )
{
maxEMTMode = 0;
}
#endif
uint8_t numSbtRdo = CU::numSbtModeRdo( sbtAllowed );
//early termination if all SBT modes are not allowed
//normative
Yin Zhao
committed
#if JVET_M0464_UNI_MTS
if( !sbtAllowed || skipResidual )
Yin Zhao
committed
#else
if( !sbtAllowed || skipResidual || cu->emtFlag )
#endif
4836
4837
4838
4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
{
numSbtRdo = 0;
}
//fast algorithm
if( ( histBestSbt != MAX_UCHAR && !CU::isSbtMode( histBestSbt ) ) || m_pcInterSearch->getSkipSbtAll() )
{
numSbtRdo = 0;
}
if( bestCost != MAX_DOUBLE && sbtOffCost != MAX_DOUBLE )
{
double th = 1.07;
if( !( prevBestSbt == 0 || m_sbtCostSave[0] == MAX_DOUBLE ) )
{
assert( m_sbtCostSave[1] <= m_sbtCostSave[0] );
th *= ( m_sbtCostSave[0] / m_sbtCostSave[1] );
}
if( sbtOffCost > bestCost * th )
{
numSbtRdo = 0;
}
}
if( !sbtOffRootCbf && sbtOffCost != MAX_DOUBLE )
{
double th = Clip3( 0.05, 0.55, ( 27 - cu->qp ) * 0.02 + 0.35 );
if( sbtOffCost < m_pcRdCost->calcRdCost( ( cu->lwidth() * cu->lheight() ) << SCALE_BITS, 0 ) * th )
{
numSbtRdo = 0;
}
}
if( histBestSbt != MAX_UCHAR && numSbtRdo != 0 )
{
numSbtRdo = 1;
m_pcInterSearch->initSbtRdoOrder( CU::getSbtMode( CU::getSbtIdx( histBestSbt ), CU::getSbtPos( histBestSbt ) ) );
}
for( int sbtModeIdx = 0; sbtModeIdx < numSbtRdo; sbtModeIdx++ )
{
uint8_t sbtMode = m_pcInterSearch->getSbtRdoOrder( sbtModeIdx );
uint8_t sbtIdx = CU::getSbtIdxFromSbtMode( sbtMode );
uint8_t sbtPos = CU::getSbtPosFromSbtMode( sbtMode );
//fast algorithm (early skip, save & load)
if( histBestSbt == MAX_UCHAR )
{
uint8_t skipCode = m_pcInterSearch->skipSbtByRDCost( cu->lwidth(), cu->lheight(), cu->mtDepth, sbtIdx, sbtPos, bestCS->cost, sbtOffDist, sbtOffCost, sbtOffRootCbf );
if( skipCode != MAX_UCHAR )
{
continue;
}
if( sbtModeIdx > 0 )
{
uint8_t prevSbtMode = m_pcInterSearch->getSbtRdoOrder( sbtModeIdx - 1 );
//make sure the prevSbtMode is the same size as the current SBT mode (otherwise the estimated dist may not be comparable)
if( CU::isSameSbtSize( prevSbtMode, sbtMode ) )
{
Distortion currEstDist = m_pcInterSearch->getEstDistSbt( sbtMode );
Distortion prevEstDist = m_pcInterSearch->getEstDistSbt( prevSbtMode );
if( currEstDist > prevEstDist * 1.15 )
{
continue;
}
}
}
}
//init tempCS and TU
if( bestCost == bestCS->cost ) //The first EMT pass didn't become the bestCS, so we clear the TUs generated
{
tempCS->clearTUs();
}
else if( false == swapped )
{
tempCS->initStructData( encTestMode.qp, encTestMode.lossless );
tempCS->copyStructure( *bestCS, partitioner.chType );
tempCS->getPredBuf().copyFrom( bestCS->getPredBuf() );
bestCost = bestCS->cost;
cu = tempCS->getCU( partitioner.chType );
swapped = true;
}
else
{
tempCS->clearTUs();
bestCost = bestCS->cost;
cu = tempCS->getCU( partitioner.chType );
}
//we need to restart the distortion for the new tempCS, the bit count and the cost
tempCS->dist = 0;
tempCS->fracBits = 0;
tempCS->cost = MAX_DOUBLE;
Yin Zhao
committed
#if !JVET_M0464_UNI_MTS
cu->emtFlag = curEmtMode;
#endif
4931
4932
4933
4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
cu->skip = false;
//set SBT info
cu->setSbtIdx( sbtIdx );
cu->setSbtPos( sbtPos );
//try residual coding
m_pcInterSearch->encodeResAndCalcRdInterCU( *tempCS, partitioner, skipResidual );
numRDOTried++;
xEncodeDontSplit( *tempCS, partitioner );
xCheckDQP( *tempCS, partitioner );
if( NULL != bestHasNonResi && ( bestCostInternal > tempCS->cost ) )
{
bestCostInternal = tempCS->cost;
if( !( tempCS->getPU( partitioner.chType )->mhIntraFlag ) )
*bestHasNonResi = !cu->rootCbf;
}
if( tempCS->cost < currBestCost )
{
currBestSbt = cu->sbtInfo;
Yin Zhao
committed
#if JVET_M0464_UNI_MTS
currBestTrs = tempCS->tus[cu->sbtInfo ? cu->getSbtPos() : 0]->mtsIdx;
Yin Zhao
committed
#else
currBestTrs = tempCS->tus[cu->sbtInfo ? cu->getSbtPos() : 0]->emtIdx;
#endif
assert( currBestTrs == 0 || currBestTrs == 1 );
currBestCost = tempCS->cost;
}
#if WCG_EXT
DTRACE_MODE_COST( *tempCS, m_pcRdCost->getLambda( true ) );
#else
DTRACE_MODE_COST( *tempCS, m_pcRdCost->getLambda() );
#endif
xCheckBestMode( tempCS, bestCS, partitioner, encTestMode );
}
if( bestCostBegin != bestCS->cost )
{
m_sbtCostSave[0] = sbtOffCost;
m_sbtCostSave[1] = currBestCost;
}
} //end emt loop
4979
4980
4981
4982
4983
4984
4985
4986
4987
4988
4989
4990
4991
4992
4993
4994
4995
4996
4997
4998
4999
5000
#if JVET_M0140_SBT
if( histBestSbt == MAX_UCHAR && doPreAnalyzeResi && numRDOTried > 1 )
{
slsSbt->saveBestSbt( cu->cs->area, (uint32_t)( curPuSse >> slShift ), currBestSbt, currBestTrs );
}
#endif
#if JVET_M0140_SBT //harmonize with GBI fast algorithm (move the code here)
tempCS->cost = currBestCost;
if( ETM_INTER_ME == encTestMode.type )
{
if( equGBiCost != NULL )
{
if( tempCS->cost < ( *equGBiCost ) && cu->GBiIdx == GBI_DEFAULT )
{
( *equGBiCost ) = tempCS->cost;
}
}
else
{
CHECK( equGBiCost == NULL, "equGBiCost == NULL" );
}