Commit eba0518f authored by Karsten Suehring's avatar Karsten Suehring

JVET-K0220: Encoder control for faster encoding

parent 286fbd17
......@@ -120,8 +120,6 @@ DepQuant : 1
PBIntraFast : 1
FastMrg : 1
AMaxBT : 1
SaveLoadEncInfo : 1 # fast QTBT tool
SaveLoadSplitDecision : 0 # fast QTBT tool
### DO NOT ADD ANYTHING BELOW THIS LINE ###
### DO NOT DELETE THE EMPTY LINE BELOW ###
......@@ -107,8 +107,6 @@ DepQuant : 1
PBIntraFast : 1
FastMrg : 1
AMaxBT : 1
SaveLoadEncInfo : 1 # fast QTBT tool
SaveLoadSplitDecision : 0 # fast QTBT tool
### DO NOT ADD ANYTHING BELOW THIS LINE ###
### DO NOT DELETE THE EMPTY LINE BELOW ###
......@@ -136,8 +136,6 @@ DepQuant : 1
PBIntraFast : 1
FastMrg : 1
AMaxBT : 1
SaveLoadEncInfo : 1 # fast QTBT tool
SaveLoadSplitDecision : 0 # fast QTBT tool
### DO NOT ADD ANYTHING BELOW THIS LINE ###
### DO NOT DELETE THE EMPTY LINE BELOW ###
......@@ -123,9 +123,6 @@ DepQuant : 1
PBIntraFast : 1
FastMrg : 1
AMaxBT : 1
SaveLoadEncInfo : 1 # fast QTBT tool
SaveLoadSplitDecision : 0 # fast QTBT tool
### DO NOT ADD ANYTHING BELOW THIS LINE ###
### DO NOT DELETE THE EMPTY LINE BELOW ###
......@@ -136,8 +136,6 @@ DepQuant : 1
PBIntraFast : 1
FastMrg : 1
AMaxBT : 1
SaveLoadEncInfo : 1 # fast QTBT tool
SaveLoadSplitDecision : 0 # fast QTBT tool
### DO NOT ADD ANYTHING BELOW THIS LINE ###
### DO NOT DELETE THE EMPTY LINE BELOW ###
......@@ -123,8 +123,6 @@ DepQuant : 1
PBIntraFast : 1
FastMrg : 1
AMaxBT : 1
SaveLoadEncInfo : 1 # fast QTBT tool
SaveLoadSplitDecision : 0 # fast QTBT tool
### DO NOT ADD ANYTHING BELOW THIS LINE ###
### DO NOT DELETE THE EMPTY LINE BELOW ###
......@@ -150,8 +150,6 @@ DepQuant : 1
PBIntraFast : 1
FastMrg : 1
AMaxBT : 1
SaveLoadEncInfo : 1 # fast QTBT tool
SaveLoadSplitDecision : 0 # fast QTBT tool
### DO NOT ADD ANYTHING BELOW THIS LINE ###
### DO NOT DELETE THE EMPTY LINE BELOW ###
......@@ -137,8 +137,6 @@ DepQuant : 1
PBIntraFast : 1
FastMrg : 1
AMaxBT : 1
SaveLoadEncInfo : 1 # fast QTBT tool
SaveLoadSplitDecision : 0 # fast QTBT tool
### DO NOT ADD ANYTHING BELOW THIS LINE ###
......
......@@ -297,8 +297,10 @@ Void EncApp::xInitLibCfg()
m_cEncLib.setUseFastMerge ( m_useFastMrg );
m_cEncLib.setUsePbIntraFast ( m_usePbIntraFast );
m_cEncLib.setUseAMaxBT ( m_useAMaxBT );
#if !JVET_K0220_ENC_CTRL
m_cEncLib.setUseSaveLoadEncInfo ( m_useSaveLoadEncInfo );
m_cEncLib.setUseSaveLoadSplitDecision ( m_useSaveLoadSplitDecision );
#endif
m_cEncLib.setUseE0023FastEnc ( m_e0023FastEnc );
m_cEncLib.setUseContentBasedFastQtbt ( m_contentBasedFastQtbt );
m_cEncLib.setCrossComponentPredictionEnabledFlag ( m_crossComponentPredictionEnabledFlag );
......
......@@ -885,8 +885,10 @@ Bool EncAppCfg::parseCfg( Int argc, TChar* argv[] )
("FastMrg", m_useFastMrg, false, "Fast methods for inter merge")
("PBIntraFast", m_usePbIntraFast, false, "Fast assertion if the intra mode is probable")
("AMaxBT", m_useAMaxBT, false, "Adaptive maximal BT-size")
#if !JVET_K0220_ENC_CTRL
("SaveLoadEncInfo", m_useSaveLoadEncInfo, false, "Reuse of previous encoder decision for same block generated by different partition methods")
("SaveLoadSplitDecision", m_useSaveLoadSplitDecision, false, "Reuse of previous split decision for same block generated by different partition methods")
#endif
("E0023FastEnc", m_e0023FastEnc, true, "Fast encoding setting for QTBT (proposal E0023)")
("ContentBasedFastQtbt", m_contentBasedFastQtbt, false, "Signal based QTBT speed-up")
// Unit definition parameters
......@@ -1937,8 +1939,10 @@ Bool EncAppCfg::xCheckParameter()
xConfirmPara( m_OBMC, "OBMC is only allowed in NEXT profile" );
#endif
xConfirmPara( m_useFastLCTU, "Fast large CTU can only be applied when encoding with NEXT profile" );
#if !JVET_K0220_ENC_CTRL
xConfirmPara( m_useSaveLoadEncInfo, "Encoder decision saving can only be applied when encoding with NEXT profile" );
xConfirmPara( m_useSaveLoadSplitDecision, "Encoder split decision saving can only be applied when encoding with NEXT profile" );
#endif
#if JEM_TOOLS
xConfirmPara( m_EMT, "EMT only allowed with NEXT profile" );
xConfirmPara( m_FastEMT, "EMT only allowed with NEXT profile" );
......@@ -1980,14 +1984,18 @@ Bool EncAppCfg::xCheckParameter()
#if JEM_TOOLS
xConfirmPara( m_LICMode > 2, "LICMode > 2 is not supported." );
#endif
#if !JVET_K0220_ENC_CTRL
xConfirmPara( m_useSaveLoadEncInfo && !m_QTBT, "Encoder decision saving can only be applied with QTBT" );
#endif
xConfirmPara( !m_QTBT && m_MTT, "Multi type tree is an extension of QTBT, thus QTBT has to be enabled for MTT" );
#if !JVET_K0220_ENC_CTRL
#if !HM_QTBT_AS_IN_JEM_QUANT
#endif
xConfirmPara( m_useSaveLoadSplitDecision && !m_QTBT, "Encoder split decision saving can only be applied with QTBT" );
#endif
#if JEM_TOOLS
xConfirmPara( !( m_OBMCBlkSize == 4 || m_OBMCBlkSize == 8 ), "OBMC Block Size must be set to 4 or 8 samples" );
xConfirmPara( m_Affine && !m_highPrecisionMv, "Affine is not yet implemented for HighPrecMv off." );
......@@ -3254,11 +3262,13 @@ Void EncAppCfg::xPrintParameter()
{
msg( VERBOSE, "LCTUFast:%d ", m_useFastLCTU );
}
#if !JVET_K0220_ENC_CTRL
if( m_QTBT )
{
msg( VERBOSE, "SaveLoadEncInfo:%d ", m_useSaveLoadEncInfo );
msg( VERBOSE, "SaveLoadSplitDecision:%d ", m_useSaveLoadSplitDecision );
}
#endif
msg( VERBOSE, "FastMrg:%d ", m_useFastMrg );
msg( VERBOSE, "PBIntraFast:%d ", m_usePbIntraFast );
#if JEM_TOOLS
......
......@@ -263,8 +263,10 @@ protected:
bool m_usePbIntraFast;
bool m_useAMaxBT;
bool m_useFastMrg;
#if !JVET_K0220_ENC_CTRL
bool m_useSaveLoadEncInfo;
bool m_useSaveLoadSplitDecision;
#endif
bool m_e0023FastEnc;
bool m_contentBasedFastQtbt;
......
......@@ -285,7 +285,9 @@ static const Int MAX_CU_TILING_PARTITIONS = 1 << ( MAX_LOG2_DIFF_CU_TR_SIZE << 1
#endif
static const Int JVET_C0024_ZERO_OUT_TH = 32;
#if !JVET_K0220_ENC_CTRL
static const Double JVET_D0077_SPLIT_DECISION_COST_SCALE = 1.05;
#endif
static const Int MAX_NUM_PART_IDXS_IN_CTU_WIDTH = MAX_CU_SIZE/MIN_PU_SIZE; ///< maximum number of partition indices across the width of a CTU (or height of a CTU)
static const Int SCALING_LIST_REM_NUM = 6;
......@@ -355,7 +357,9 @@ static const SplitSeries SPLIT_DMULT = 5;
static const SplitSeries SPLIT_MASK = 31; ///< = (1 << SPLIT_BITS) - 1
static const Int SKIP_DEPTH = 3;
#if !JVET_K0220_ENC_CTRL
static const Int SKIPHORNOVERQT_DEPTH_TH = 2;
#endif
static const Int PICTURE_DISTANCE_TH = 1;
static const Int FAST_SKIP_DEPTH = 2;
......
......@@ -110,7 +110,7 @@ struct MotionInfo
UShort sliceIdx;
Mv mv [ NUM_REF_PIC_LIST_01 ];
#if JEM_TOOLS
#if JEM_TOOLS && !JVET_K0220_ENC_CTRL
Mv mvdAffi[ NUM_REF_PIC_LIST_01 ];
#endif
Short refIdx [ NUM_REF_PIC_LIST_01 ];
......
......@@ -53,6 +53,11 @@
#define JVET_K0072 1
#define JVET_K0220_ENC_CTRL 1 // remove HM_NO_ADDITIONAL_SPEEDUPS when adopting
#if JVET_K0220_ENC_CTRL
#define REUSE_CU_RESULTS 1
#endif
#ifndef JEM_TOOLS
#define JEM_TOOLS 1 // Defines the inclusion of JEM tools into compiled executable
......@@ -131,7 +136,11 @@
#define ENABLE_BMS 1
#if QTBT_AS_IN_JEM // macros which will cause changes in the decoder behavior ara marked with *** - keep them on to retain compatibility with JEM-toolcheck
#if JVET_K0220_ENC_CTRL
#define HM_NO_ADDITIONAL_SPEEDUPS 0
#else
#define HM_NO_ADDITIONAL_SPEEDUPS 1
#endif
#define HM_QTBT_AS_IN_JEM 1 // ***
#if HM_QTBT_AS_IN_JEM
#define HM_QTBT_AS_IN_JEM_CONTEXT 1 // ***
......
......@@ -351,6 +351,13 @@ Void PredictionUnit::initData()
refIdx[i] = -1;
mv[i] .setZero();
mvd[i] .setZero();
#if JEM_TOOLS && JVET_K0220_ENC_CTRL
for( UInt j = 0; j < 2; j++ )
{
mvdAffi[i][j].setZero();
}
#endif
}
}
......@@ -381,6 +388,13 @@ PredictionUnit& PredictionUnit::operator=(const InterPredictionData& predData)
mv[i] = predData.mv[i];
mvd[i] = predData.mvd[i];
refIdx[i] = predData.refIdx[i];
#if JEM_TOOLS && JVET_K0220_ENC_CTRL
for( UInt j = 0; j < 2; j++ )
{
mvdAffi[i][j] = predData.mvdAffi[i][j];
}
#endif
}
return *this;
......@@ -408,6 +422,13 @@ PredictionUnit& PredictionUnit::operator=( const PredictionUnit& other )
mv[i] = other.mv[i];
mvd[i] = other.mvd[i];
refIdx[i] = other.refIdx[i];
#if JEM_TOOLS && JVET_K0220_ENC_CTRL
for( UInt j = 0; j < 2; j++ )
{
mvdAffi[i][j] = other.mvdAffi[i][j];
}
#endif
}
return *this;
......
......@@ -369,6 +369,9 @@ struct InterPredictionData
#if JEM_TOOLS
UChar frucMrgMode;
Bool mvRefine;
#if JVET_K0220_ENC_CTRL
Mv mvdAffi [NUM_REF_PIC_LIST_01][2];
#endif
#endif
};
......
......@@ -3288,6 +3288,7 @@ Void PU::setAllAffineMv( PredictionUnit& pu, Mv affLT, Mv affRT, Mv affLB, RefPi
mb.at( 0, mb.height - 1 ).mv[eRefList] = affLB;
mb.at( mb.width - 1, mb.height - 1 ).mv[eRefList] = mv;
}
#if !JVET_K0220_ENC_CTRL
Void PU::setAllAffineMvd( MotionBuf mb, const Mv& affLT, const Mv& affRT, RefPicList eRefList, Bool rectCUs )
{
......@@ -3321,6 +3322,7 @@ Void PU::setAllAffineMvd( MotionBuf mb, const Mv& affLT, const Mv& affRT, RefPic
}
}
#endif
#endif
void PU::spanMotionInfo( PredictionUnit &pu, const MergeCtx &mrgCtx )
{
......
......@@ -150,7 +150,9 @@ namespace PU
void getAffineMergeCand (const PredictionUnit &pu, MvField (*mvFieldNeighbours)[3], unsigned char &interDirNeighbours, int &numValidMergeCand );
void setAllAffineMvField ( PredictionUnit &pu, MvField *mvField, RefPicList eRefList );
void setAllAffineMv ( PredictionUnit &pu, Mv affLT, Mv affRT, Mv affLB, RefPicList eRefList );
#if !JVET_K0220_ENC_CTRL
void setAllAffineMvd ( MotionBuf mb, const Mv& affLT, const Mv& affRT, RefPicList eRefList, Bool useQTBT );
#endif
bool isBIOLDB (const PredictionUnit &pu);
#endif
bool isBiPredFromDifferentDir (const PredictionUnit &pu);
......
......@@ -129,7 +129,9 @@ enum DTRACE_CHANNEL
D_DQP, // Delta QP read/write
D_QP, // final CU QP at reading/writing stage
D_QP_PER_CTU, // final QP per CTU at reading
#if !JVET_K0220_ENC_CTRL
D_SAVE_LOAD, // save load encoder info
#endif
D_MISC, // Miscellaneous
D_DECISIONTREE, // decision tree tracing
D_TU_ABS_SUM,
......@@ -227,7 +229,9 @@ inline CDTrace* tracing_init( std::string& sTracingFile, std::string& sTracingRu
_CNL_DEF( D_DQP ),
_CNL_DEF( D_QP ),
_CNL_DEF( D_QP_PER_CTU ),
#if !JVET_K0220_ENC_CTRL
_CNL_DEF( D_SAVE_LOAD ),
#endif
_CNL_DEF( D_MISC ),
_CNL_DEF( D_DECISIONTREE ),
_CNL_DEF( D_TU_ABS_SUM ),
......
......@@ -1696,7 +1696,13 @@ void CABACReader::prediction_unit( PredictionUnit& pu, MergeCtx& mrgCtx )
mvd_coding( affLT );
mvd_coding( affRT );
#if JVET_K0220_ENC_CTRL
pu.mvdAffi[REF_PIC_LIST_0][0] = affLT;
pu.mvdAffi[REF_PIC_LIST_0][1] = affRT;
#else
PU::setAllAffineMvd( pu.getMotionBuf(), affLT, affRT, REF_PIC_LIST_0, pu.cs->pcv->rectCUs );
#endif
}
else
#endif
......@@ -1725,7 +1731,12 @@ void CABACReader::prediction_unit( PredictionUnit& pu, MergeCtx& mrgCtx )
mvd_coding( affLT );
mvd_coding( affRT );
#if JVET_K0220_ENC_CTRL
pu.mvdAffi[REF_PIC_LIST_1][0] = affLT;
pu.mvdAffi[REF_PIC_LIST_1][1] = affRT;
#else
PU::setAllAffineMvd( pu.getMotionBuf(), affLT, affRT, REF_PIC_LIST_1, pu.cs->pcv->rectCUs );
#endif
}
#endif
else
......
......@@ -209,6 +209,12 @@ Void DecCu::xIntraRecBlk( TransformUnit& tu, const ComponentID compID )
#if !KEEP_PRED_AND_RESI_SIGNALS
pReco.copyFrom( piPred );
#endif
#if REUSE_CU_RESULTS
if( cs.pcv->isEncoder )
{
cs.picture->getRecoBuf( area ).copyFrom( pReco );
}
#endif
}
Void DecCu::xReconIntraQT( CodingUnit &cu )
......@@ -507,7 +513,11 @@ Void DecCu::xDeriveCUMV( CodingUnit &cu )
}
else
{
#if REUSE_CU_RESULTS
if( cu.imv && !cu.cs->pcv->isEncoder )
#else
if( cu.imv )
#endif
{
PU::applyImv( pu, mrgCtx, m_pcInterPred );
}
......@@ -530,11 +540,16 @@ Void DecCu::xDeriveCUMV( CodingUnit &cu )
// Mv mv[3];
CHECK( pu.refIdx[eRefList] < 0, "Unexpected negative refIdx." );
#if JVET_K0220_ENC_CTRL
Mv mvLT = affineAMVPInfo.mvCandLT[mvp_idx] + pu.mvdAffi[eRefList][0];
Mv mvRT = affineAMVPInfo.mvCandRT[mvp_idx] + pu.mvdAffi[eRefList][1];
#else
Position posLT = pu.Y().topLeft();
Position posRT = pu.Y().topRight();
Mv mvLT = affineAMVPInfo.mvCandLT[mvp_idx] + pu.getMotionInfo( posLT ).mvdAffi[eRefList];
Mv mvRT = affineAMVPInfo.mvCandRT[mvp_idx] + pu.getMotionInfo( posRT ).mvdAffi[eRefList];
#endif
CHECK( !mvLT.highPrec, "unexpected lp mv" );
CHECK( !mvRT.highPrec, "unexpected lp mv" );
......
......@@ -1849,9 +1849,14 @@ void CABACWriter::prediction_unit( const PredictionUnit& pu )
#if JEM_TOOLS
if( pu.cu->affine )
{
#if JVET_K0220_ENC_CTRL
mvd_coding( pu.mvdAffi[REF_PIC_LIST_0][0], 0 );
mvd_coding( pu.mvdAffi[REF_PIC_LIST_0][1], 0 );
#else
CMotionBuf mb = pu.getMotionBuf();
mvd_coding( mb.at( 0, 0 ).mvdAffi[REF_PIC_LIST_0], 0 );
mvd_coding( mb.at( mb.width-1, 0 ).mvdAffi[REF_PIC_LIST_0], 0 );
#endif
}
else
#endif
......@@ -1872,9 +1877,14 @@ void CABACWriter::prediction_unit( const PredictionUnit& pu )
#if JEM_TOOLS
if( pu.cu->affine )
{
#if JVET_K0220_ENC_CTRL
mvd_coding( pu.mvdAffi[REF_PIC_LIST_1][0], 0 );
mvd_coding( pu.mvdAffi[REF_PIC_LIST_1][1], 0 );
#else
CMotionBuf mb = pu.getMotionBuf();
mvd_coding( mb.at( 0, 0 ).mvdAffi[REF_PIC_LIST_1], 0 );
mvd_coding( mb.at( mb.width-1, 0 ).mvdAffi[REF_PIC_LIST_1], 0 );
#endif
}
else
#endif
......
......@@ -258,8 +258,10 @@ protected:
bool m_useFastMrg;
bool m_usePbIntraFast;
bool m_useAMaxBT;
#if !JVET_K0220_ENC_CTRL
bool m_useSaveLoadEncInfo;
bool m_useSaveLoadSplitDecision;
#endif
bool m_e0023FastEnc;
bool m_contentBasedFastQtbt;
......@@ -780,11 +782,14 @@ public:
bool getUsePbIntraFast () const { return m_usePbIntraFast; }
Void setUseAMaxBT ( bool n ) { m_useAMaxBT = n; }
bool getUseAMaxBT () const { return m_useAMaxBT; }
#if !JVET_K0220_ENC_CTRL
Void setUseSaveLoadEncInfo ( bool b ) { m_useSaveLoadEncInfo = b; }
Void setUseSaveLoadSplitDecision ( bool b ) { m_useSaveLoadSplitDecision = b; }
bool getUseSaveLoadEncInfo () const { return m_useSaveLoadEncInfo; }
bool getUseSaveLoadSplitDecision () const { return m_useSaveLoadSplitDecision; }
#endif
void setUseE0023FastEnc ( bool b ) { m_e0023FastEnc = b; }
bool getUseE0023FastEnc () const { return m_e0023FastEnc; }
void setUseContentBasedFastQtbt ( bool b ) { m_contentBasedFastQtbt = b; }
......@@ -838,7 +843,11 @@ public:
#endif
Void setChromaFormatIdc ( ChromaFormat cf ) { m_chromaFormatIDC = cf; }
#if REUSE_CU_RESULTS
ChromaFormat getChromaFormatIdc ( ) const { return m_chromaFormatIDC; }
#else
ChromaFormat getChromaFormatIdc ( ) { return m_chromaFormatIDC; }
#endif
#if SHARP_LUMA_DELTA_QP
Void setLumaLevelToDeltaQPControls( const LumaLevelToDeltaQPMapping &lumaLevelToDeltaQPMapping ) { m_lumaLevelToDeltaQPMapping=lumaLevelToDeltaQPMapping; }
......
......@@ -181,6 +181,10 @@ void EncCu::create( EncCfg* encCfg )
THROW( "Unknown partitioner!" );
}
#if REUSE_CU_RESULTS
m_modeCtrl->create( *encCfg );
#endif
for( unsigned ui = 0; ui < MRG_MAX_NUM_CANDS; ui++ )
{
m_acMergeBuffer[ui].create( chromaFormat, Area( 0, 0, uiMaxWidth, uiMaxHeight ) );
......@@ -222,6 +226,10 @@ void EncCu::destroy()
delete[] m_pBestCS; m_pBestCS = nullptr;
delete[] m_pTempCS; m_pTempCS = nullptr;
#if REUSE_CU_RESULTS
m_modeCtrl->destroy();
#endif
delete m_modeCtrl;
m_modeCtrl = nullptr;
......@@ -242,8 +250,8 @@ void EncCu::destroy()
delete[] m_pImvTempCS;
m_pImvTempCS = nullptr;
}
#endif
#endif
#if JEM_TOOLS
if( m_pTempCUWoOBMC )
{
......@@ -269,8 +277,8 @@ void EncCu::destroy()
delete[] m_pPredBufWoOBMC;
m_pPredBufWoOBMC = nullptr;
}
#endif
#endif
for( unsigned ui = 0; ui < MRG_MAX_NUM_CANDS; ui++ )
{
m_acMergeBuffer[ui].destroy();
......@@ -303,10 +311,16 @@ void EncCu::init( EncLib* pcEncLib, const SPS& sps PARL_PARAM( const int tId ) )
m_dataId = tId;
#endif
#if REUSE_CU_RESULTS
DecCu::init( m_pcTrQuant, m_pcIntraSearch, m_pcInterSearch );
#endif
m_modeCtrl->init( m_pcEncCfg, m_pcRateCtrl, m_pcRdCost );
m_pcInterSearch->setModeCtrl( m_modeCtrl );
#if !JVET_K0220_ENC_CTRL
m_pcIntraSearch->setModeCtrl( m_modeCtrl );
#endif
}
// ====================================================================================================================
......@@ -666,6 +680,12 @@ void EncCu::xCompressCU( CodingStructure *&tempCS, CodingStructure *&bestCS, Par
{
xCheckRDCostAffineMerge2Nx2N( tempCS, bestCS, partitioner, currTestMode );
}
#endif
#if REUSE_CU_RESULTS
else if( currTestMode.type == ETM_RECO_CACHED )
{
xReuseCachedResult( tempCS, bestCS, partitioner );
}
#endif
else if( currTestMode.type == ETM_MERGE_SKIP )
{
......@@ -975,9 +995,48 @@ void EncCu::xCheckModeSplit(CodingStructure *&tempCS, CodingStructure *&bestCS,
tempCS->initStructData( qp, bIsLosslessMode );
#if !JVET_K0220_ENC_CTRL
partitioner.splitCurrArea( split, *tempCS );
#endif
m_CABACEstimator->getCtx() = m_CurrCtx->start;
#if JVET_K0220_ENC_CTRL
if( tempCS->sps->getSpsNext().getUseQTBT() )
{
const TempCtx ctxStartSP( m_CtxCache, SubCtx( Ctx::SplitFlag, m_CABACEstimator->getCtx() ) );
const TempCtx ctxStartBT( m_CtxCache, SubCtx( Ctx::BTSplitFlag, m_CABACEstimator->getCtx() ) );
m_CABACEstimator->resetBits();
if( partitioner.getImplicitSplit( *tempCS ) != CU_QUAD_SPLIT )
{
if( partitioner.canSplit( CU_QUAD_SPLIT, *tempCS ) )
{
m_CABACEstimator->split_cu_flag( split == CU_QUAD_SPLIT, *tempCS, partitioner );
}
if( split != CU_QUAD_SPLIT )
{
m_CABACEstimator->split_cu_mode_mt( split, *tempCS, partitioner );
}
}
const double factor = ( tempCS->currQP[partitioner.chType] > 30 ? 1.1 : 1.075 );
const double cost = m_pcRdCost->calcRdCost( UInt64( m_CABACEstimator->getEstFracBits() + ( ( bestCS->fracBits ) / factor ) ), Distortion( bestCS->dist / factor ) );
m_CABACEstimator->getCtx() = SubCtx( Ctx::SplitFlag, ctxStartSP );
m_CABACEstimator->getCtx() = SubCtx( Ctx::BTSplitFlag, ctxStartBT );
if( cost > bestCS->cost )
{
xCheckBestMode( tempCS, bestCS, partitioner, encTestMode );
return;
}
}
partitioner.splitCurrArea( split, *tempCS );
#endif
m_CurrCtx++;
tempCS->getRecoBuf().fill( 0 );
......@@ -1135,7 +1194,9 @@ void EncCu::xCheckRDCostIntra( CodingStructure *&tempCS, CodingStructure *&bestC
bool skipSecondEmtPass = m_modeCtrl->getSkipSecondEMTPass();
#endif
#if JEM_TOOLS
#if !JVET_K0220_ENC_CTRL
auto slsCtrl = dynamic_cast<SaveLoadEncInfoCtrl*>( m_modeCtrl );
#endif
const SPS &sps = *tempCS->sps;
#endif
const PPS &pps = *tempCS->pps;
......@@ -1171,6 +1232,7 @@ void EncCu::xCheckRDCostIntra( CodingStructure *&tempCS, CodingStructure *&bestC
{
#if JEM_TOOLS
//Possible early EMT tests interruptions
#if !JVET_K0220_ENC_CTRL
//1) saveLoadTag code for EMT
if( sps.getSpsNext().getUseQTBT() && slsCtrl && m_pcEncCfg->getUseSaveLoadEncInfo() )
{
......@@ -1179,6 +1241,7 @@ void EncCu::xCheckRDCostIntra( CodingStructure *&tempCS, CodingStructure *&bestC
continue;
}
}
#endif
//2) Second EMT pass. This "if clause" is necessary because of the NSST and PDPC "for loops".
if( emtCuFlag && skipSecondEmtPass )
{
......@@ -1324,7 +1387,11 @@ void EncCu::xCheckRDCostIntra( CodingStructure *&tempCS, CodingStructure *&bestC
#if JEM_TOOLS
//now we check whether the second pass of SIZE_2Nx2N and the whole Intra SIZE_NxN should be skipped or not
#if JVET_K0220_ENC_CTRL
if( !emtCuFlag && !tempCS->slice->isIntra() && bestCU && bestCU->predMode != MODE_INTRA && cu.partSize == SIZE_2Nx2N && m_pcEncCfg->getFastInterEMT() )
#else
if( !emtCuFlag && !tempCS->slice->isIntra() && bestCU && bestCU->predMode != MODE_INTRA && cu.partSize == SIZE_2Nx2N && m_pcEncCfg->getFastInterEMT() && ( m_pcEncCfg->getUseSaveLoadEncInfo() ? ( bestInterCost < MAX_DOUBLE ) : true ) )
#endif
{
const double thEmtInterFastSkipIntra = 1.4; // Skip checking Intra if "2Nx2N using DCT2" is worse than best Inter mode
if( costSize2Nx2NemtFirstPass > thEmtInterFastSkipIntra * bestInterCost )
......@@ -1934,7 +2001,9 @@ void EncCu::xCheckRDCostInterWoOBMC( CodingStructure *&tempCS, CodingStructure *
void EncCu::xCheckRDCostMerge2Nx2NFRUC( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode )
{
const Slice &slice = *tempCS->slice;
#if !JVET_K0220_ENC_CTRL
auto slsCtrl = dynamic_cast< SaveLoadEncInfoCtrl* >( m_modeCtrl );
#endif
if( !slice.getSPS()->getSpsNext().getUseFRUCMrgMode() )
{
......@@ -1961,11 +2030,13 @@ void EncCu::xCheckRDCostMerge2Nx2NFRUC( CodingStructure *&tempCS, CodingStructur
for( Int nME = 0; nME < 2; nME++ )
{
#if !JVET_K0220_ENC_CTRL
if( slsCtrl && m_pcEncCfg->getUseSaveLoadEncInfo() && LOAD_ENC_INFO == slsCtrl->getSaveLoadTag( tempCS->area ) && uhFRUCME[nME] != slsCtrl->getSaveLoadFrucMode( tempCS->area ) )
{
continue;
}
#endif
tempCS->initStructData( encTestMode.qp, encTestMode.lossless );
Bool bAvailable = false;
......@@ -2334,5 +2405,78 @@ void EncCu::xEncodeDontSplit( CodingStructure &cs, Partitioner &partitioner )
}
#if REUSE_CU_RESULTS
void EncCu::xReuseCachedResult( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner )
{
const SPS &sps = *tempCS->sps;
BestEncInfoCache* bestEncCache = dynamic_cast<BestEncInfoCache*>( m_modeCtrl );
CHECK( !bestEncCache, "If this mode is chosen, mode controller has to implement the mode caching capabilities" );
EncTestMode cachedMode;
if( bestEncCache->setCsFrom( *tempCS, cachedMode, partitioner ) )
{
CodingUnit& cu = *tempCS->cus.front();
partitioner.setCUData( cu );
if( CU::isIntra( cu ) )
{
xReconIntraQT( cu );
}
else
{
xDeriveCUMV( cu );
xReconInter( cu );
}
Distortion finalDistortion = 0;
const Int numValidComponents = getNumberValidComponents( tempCS->area.chromaFormat );
for( Int comp = 0; comp < numValidComponents; comp++ )
{
const ComponentID compID = ComponentID( comp );
if( CS::isDualITree( *tempCS ) && toChannelType( compID ) != partitioner.chType )
{
continue;
}
CPelBuf reco = tempCS->getRecoBuf( compID );
CPelBuf org = tempCS->getOrgBuf ( compID );
#if WCG_EXT
if( m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled() )
{
const CPelBuf orgLuma = tempCS->getOrgBuf( cs.area.blocks[COMPONENT_Y] );
finalDistortion += m_pcRdCost->getDistPart( org, reco, sps.getBitDepth( toChannelType( compID ) ), compID, DF_SSE_WTD, &orgLuma );
}
else
#endif
finalDistortion += m_pcRdCost->getDistPart( org, reco, sps.getBitDepth( toChannelType( compID ) ), compID, DF_SSE );
}
m_CABACEstimator->getCtx() = m_CurrCtx->start;
m_CABACEstimator->resetBits();
CUCtx cuCtx;
cuCtx.isDQPCoded = true;
cuCtx.isChromaQpAdjCoded = true;
m_CABACEstimator->coding_unit( cu, partitioner, cuCtx );
tempCS->dist = finalDistortion;
tempCS->fracBits = m_CABACEstimator->getEstFracBits();
tempCS->cost = m_pcRdCost->calcRdCost( tempCS->fracBits, tempCS->dist );
xEncodeDontSplit( *tempCS, partitioner );
xCheckDQP ( *tempCS, partitioner );
xCheckBestMode ( tempCS, bestCS, partitioner, cachedMode );
}
else
{
THROW( "Should never happen!" );
}
}
#endif
//! \}
......@@ -46,6 +46,10 @@
#include "CommonLib/Unit.h"
#include "CommonLib/UnitPartitioner.h"
#if REUSE_CU_RESULTS
#include "DecoderLib/DecCu.h"
#endif
#include "CABACWriter.h"
#include "IntraSearch.h"
#include "InterSearch.h"
......@@ -64,6 +68,9 @@ class EncSlice;
/// CU encoder class
class EncCu
#if REUSE_CU_RESULTS
: DecCu
#endif
{
private:
......@@ -180,9 +187,13 @@ protected:
( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode );