Commit 27f459b6 authored by Huanbang Chen's avatar Huanbang Chen Committed by Daniel

Integrated JVET-M0444 SMVD to VTM.

parent 363527c9
......@@ -108,6 +108,9 @@ enum CodingStatisticsType
STATS__TOOL_TOTAL_FRAME,// This is a special case and is not included in the report.
STATS__TOOL_AFF,
STATS__TOOL_EMT,
#if JVET_M0444_SMVD
STATS__CABAC_BITS__SYMMVD_FLAG,
#endif
STATS__TOOL_TOTAL,
STATS__NUM_STATS
};
......@@ -184,6 +187,9 @@ static inline const char* getName(CodingStatisticsType name)
"CABAC_BITS__TRIANGLE_FLAG",
"CABAC_BITS__TRIANGLE_INDEX",
"CABAC_BITS__MULTI_REF_LINE",
#if JVET_M0444_SMVD
"CABAC_BITS__SYMMVD_FLAG",
#endif
"TOOL_FRAME",
"TOOL_AFFINE",
"TOOL_EMT",
......
......@@ -1065,6 +1065,15 @@ const CtxSet ContextSetCfg::MVPIdx = ContextSetCfg::addCtxSet
#endif
});
#if JVET_M0444_SMVD
const CtxSet ContextSetCfg::SmvdFlag = ContextSetCfg::addCtxSet
( {
{ 154, },
{ 110, },
{ CNU, },
} );
#endif
const CtxSet ContextSetCfg::SaoMergeFlag = ContextSetCfg::addCtxSet
({
#if JVET_M0453_CABAC_ENGINE
......
......@@ -304,6 +304,9 @@ public:
static const CtxSet MHIntraPredMode;
static const CtxSet TriangleFlag;
static const CtxSet TriangleIdx;
#if JVET_M0444_SMVD
static const CtxSet SmvdFlag;
#endif
static const unsigned NumberOfContexts;
// combined sets for less complex copying
......
......@@ -446,6 +446,13 @@ void InterPrediction::xPredInterBi(PredictionUnit& pu, PelUnitBuf &pcYuvPred)
}
}
#if JVET_M0444_SMVD
if (bioApplied && pu.cu->smvdMode)
{
bioApplied = false;
}
#endif
if (pu.cu->cs->sps->getSpsNext().getUseGBi() && bioApplied && pu.cu->GBiIdx != GBI_DEFAULT)
{
bioApplied = false;
......
......@@ -206,6 +206,13 @@ public:
{
roundToPrecision(src, m_amvrPrecision[amvr]);
}
#if JVET_M0444_SMVD
Mv getSymmvdMv(const Mv& curMvPred, const Mv& tarMvPred)
{
return Mv(tarMvPred.hor - hor + curMvPred.hor, tarMvPred.ver - ver + curMvPred.ver);
}
#endif
};// END CLASS DEFINITION MV
namespace std
......
......@@ -74,6 +74,9 @@ Slice::Slice()
, m_signDataHidingEnabledFlag ( false )
#endif
, m_bCheckLDC ( false )
#if JVET_M0444_SMVD
, m_bBiDirPred ( false )
#endif
, m_iSliceQpDelta ( 0 )
, m_iDepth ( 0 )
#if HEVC_VPS
......@@ -192,6 +195,12 @@ void Slice::initSlice()
m_bCheckLDC = false;
#if JVET_M0444_SMVD
m_bBiDirPred = false;
m_symRefIdx[0] = -1;
m_symRefIdx[1] = -1;
#endif
for (uint32_t component = 0; component < MAX_NUM_COMPONENT; component++)
{
m_iSliceChromaQpDelta[component] = 0;
......@@ -764,6 +773,13 @@ void Slice::copySliceInfo(Slice *pSrc, bool cpyAlmostAll)
m_bCheckLDC = pSrc->m_bCheckLDC;
m_iSliceQpDelta = pSrc->m_iSliceQpDelta;
#if JVET_M0444_SMVD
m_bBiDirPred = pSrc->m_bBiDirPred;
m_symRefIdx[0] = pSrc->m_symRefIdx[0];
m_symRefIdx[1] = pSrc->m_symRefIdx[1];
#endif
for (uint32_t component = 0; component < MAX_NUM_COMPONENT; component++)
{
m_iSliceChromaQpDelta[component] = pSrc->m_iSliceChromaQpDelta[component];
......
......@@ -1572,6 +1572,11 @@ private:
#endif
bool m_bCheckLDC;
#if JVET_M0444_SMVD
bool m_bBiDirPred;
int m_symRefIdx[2];
#endif
// Data
int m_iSliceQpDelta;
int m_iSliceChromaQpDelta[MAX_NUM_COMPONENT];
......@@ -1760,6 +1765,12 @@ public:
void setCheckLDC( bool b ) { m_bCheckLDC = b; }
void setMvdL1ZeroFlag( bool b) { m_bLMvdL1Zero = b; }
#if JVET_M0444_SMVD
void setBiDirPred( bool b, int refIdx0, int refIdx1 ) { m_bBiDirPred = b; m_symRefIdx[0] = refIdx0; m_symRefIdx[1] = refIdx1; }
bool getBiDirPred() const { return m_bBiDirPred; }
int getSymRefIdx( int refList ) const { return m_symRefIdx[refList]; }
#endif
bool isIntra() const { return m_eSliceType == I_SLICE; }
bool isInterB() const { return m_eSliceType == B_SLICE; }
bool isInterP() const { return m_eSliceType == P_SLICE; }
......
......@@ -50,6 +50,8 @@
#include <assert.h>
#include <cassert>
#define JVET_M0444_SMVD 1 // SMVD mode
#define JVET_M0142_CCLM_COLLOCATED_CHROMA 1 // Adding support for chroma sample location type 2 in CCLM
#define JVET_M0479_18BITS_MV_CLIP 1
......
......@@ -273,6 +273,10 @@ CodingUnit& CodingUnit::operator=( const CodingUnit& other )
for (int i = 0; i<2; i++)
refIdxBi[i] = other.refIdxBi[i];
cpr = other.cpr;
#if JVET_M0444_SMVD
smvdMode = other.smvdMode;
#endif
return *this;
}
......@@ -306,6 +310,9 @@ void CodingUnit::initData()
for (int i = 0; i < 2; i++)
refIdxBi[i] = -1;
cpr = false;
#if JVET_M0444_SMVD
smvdMode = 0;
#endif
}
......
......@@ -313,6 +313,9 @@ struct CodingUnit : public UnitArea
// needed for fast imv mode decisions
int8_t imvNumCand;
bool cpr;
#if JVET_M0444_SMVD
uint8_t smvdMode;
#endif
CodingUnit() : chType( CH_L ) { }
CodingUnit(const UnitArea &unit);
......
......@@ -1342,6 +1342,9 @@ void CABACReader::prediction_unit( PredictionUnit& pu, MergeCtx& mrgCtx )
{
inter_pred_idc( pu );
affine_flag ( *pu.cu );
#if JVET_M0444_SMVD
smvd_mode( pu );
#endif
if( pu.interDir != 2 /* PRED_L1 */ )
{
......@@ -1364,6 +1367,10 @@ void CABACReader::prediction_unit( PredictionUnit& pu, MergeCtx& mrgCtx )
if( pu.interDir != 1 /* PRED_L0 */ )
{
#if JVET_M0444_SMVD
if ( pu.cu->smvdMode != 1 )
{
#endif
ref_idx ( pu, REF_PIC_LIST_1 );
if( pu.cu->cs->slice->getMvdL1ZeroFlag() && pu.interDir == 3 /* PRED_BI */ )
{
......@@ -1385,6 +1392,9 @@ void CABACReader::prediction_unit( PredictionUnit& pu, MergeCtx& mrgCtx )
{
mvd_coding( pu.mvd[REF_PIC_LIST_1] );
}
#if JVET_M0444_SMVD
}
#endif
mvp_flag ( pu, REF_PIC_LIST_1 );
}
}
......@@ -1396,9 +1406,40 @@ void CABACReader::prediction_unit( PredictionUnit& pu, MergeCtx& mrgCtx )
pu.cu->GBiIdx = GBI_DEFAULT;
}
#if JVET_M0444_SMVD
if ( pu.cu->smvdMode )
{
RefPicList eCurRefList = (RefPicList)(pu.cu->smvdMode - 1);
pu.mvd[1 - eCurRefList].set( -pu.mvd[eCurRefList].hor, -pu.mvd[eCurRefList].ver );
pu.refIdx[1 - eCurRefList] = pu.cs->slice->getSymRefIdx( 1 - eCurRefList );
}
#endif
PU::spanMotionInfo( pu, mrgCtx );
}
#if JVET_M0444_SMVD
void CABACReader::smvd_mode( PredictionUnit& pu )
{
pu.cu->smvdMode = 0;
if ( pu.interDir != 3 || pu.cu->affine )
{
return;
}
if ( pu.cs->slice->getBiDirPred() == false )
{
return;
}
RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET( STATS__CABAC_BITS__SYMMVD_FLAG );
pu.cu->smvdMode = m_BinDecoder.decodeBin( Ctx::SmvdFlag() ) ? 1 : 0;
DTRACE( g_trace_ctx, D_SYNTAX, "symmvd_flag() symmvd=%d pos=(%d,%d) size=%dx%d\n", pu.cu->smvdMode ? 1 : 0, pu.lumaPos().x, pu.lumaPos().y, pu.lumaSize().width, pu.lumaSize().height );
}
#endif
void CABACReader::subblock_merge_flag( CodingUnit& cu )
{
if ( cu.firstPU->mergeFlag && (cu.firstPU->mmvdMergeFlag || cu.mmvdSkip) )
......@@ -1644,6 +1685,14 @@ void CABACReader::ref_idx( PredictionUnit &pu, RefPicList eRefList )
{
RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET( STATS__CABAC_BITS__REF_FRM_IDX );
#if JVET_M0444_SMVD
if ( pu.cu->smvdMode )
{
pu.refIdx[eRefList] = pu.cs->slice->getSymRefIdx( eRefList );
return;
}
#endif
int numRef = pu.cs->slice->getNumRefIdx(eRefList);
if( numRef <= 1 || !m_BinDecoder.decodeBin( Ctx::RefPic() ) )
{
......
......@@ -109,6 +109,9 @@ public:
void MHIntra_flag ( PredictionUnit& pu );
void MHIntra_luma_pred_modes ( CodingUnit& cu );
void triangle_mode ( CodingUnit& cu );
#if JVET_M0444_SMVD
void smvd_mode ( PredictionUnit& pu );
#endif
// pcm samples (clause 7.3.8.7)
void pcm_samples ( TransformUnit& tu );
......
......@@ -1116,6 +1116,84 @@ bool DecLib::xDecodeSlice(InputNALUnit &nalu, int &iSkipFrame, int iPOCLastDispl
pcSlice->setCheckLDC(bLowDelay);
}
#if JVET_M0444_SMVD
if ( pcSlice->getCheckLDC() == false && pcSlice->getMvdL1ZeroFlag() == false )
{
int currPOC = pcSlice->getPOC();
int forwardPOC = currPOC;
int bacwardPOC = currPOC;
int ref = 0;
int refIdx0 = -1;
int refIdx1 = -1;
// search nearest forward POC in List 0
for ( ref = 0; ref < pcSlice->getNumRefIdx( REF_PIC_LIST_0 ); ref++ )
{
int poc = pcSlice->getRefPic( REF_PIC_LIST_0, ref )->getPOC();
if ( poc < currPOC && (poc > forwardPOC || refIdx0 == -1) )
{
forwardPOC = poc;
refIdx0 = ref;
}
}
// search nearest backward POC in List 1
for ( ref = 0; ref < pcSlice->getNumRefIdx( REF_PIC_LIST_1 ); ref++ )
{
int poc = pcSlice->getRefPic( REF_PIC_LIST_1, ref )->getPOC();
if ( poc > currPOC && (poc < bacwardPOC || refIdx1 == -1) )
{
bacwardPOC = poc;
refIdx1 = ref;
}
}
if ( !(forwardPOC < currPOC && bacwardPOC > currPOC) )
{
forwardPOC = currPOC;
bacwardPOC = currPOC;
refIdx0 = -1;
refIdx1 = -1;
// search nearest backward POC in List 0
for ( ref = 0; ref < pcSlice->getNumRefIdx( REF_PIC_LIST_0 ); ref++ )
{
int poc = pcSlice->getRefPic( REF_PIC_LIST_0, ref )->getPOC();
if ( poc > currPOC && (poc < bacwardPOC || refIdx0 == -1) )
{
bacwardPOC = poc;
refIdx0 = ref;
}
}
// search nearest forward POC in List 1
for ( ref = 0; ref < pcSlice->getNumRefIdx( REF_PIC_LIST_1 ); ref++ )
{
int poc = pcSlice->getRefPic( REF_PIC_LIST_1, ref )->getPOC();
if ( poc < currPOC && (poc > forwardPOC || refIdx1 == -1) )
{
forwardPOC = poc;
refIdx1 = ref;
}
}
}
if ( forwardPOC < currPOC && bacwardPOC > currPOC )
{
pcSlice->setBiDirPred( true, refIdx0, refIdx1 );
}
else
{
pcSlice->setBiDirPred( false, -1, -1 );
}
}
else
{
pcSlice->setBiDirPred( false, -1, -1 );
}
#endif
//---------------
pcSlice->setRefPOCList();
......
......@@ -1328,6 +1328,9 @@ void CABACWriter::prediction_unit( const PredictionUnit& pu )
{
inter_pred_idc( pu );
affine_flag ( *pu.cu );
#if JVET_M0444_SMVD
smvd_mode( pu );
#endif
if( pu.interDir != 2 /* PRED_L1 */ )
{
ref_idx ( pu, REF_PIC_LIST_0 );
......@@ -1348,6 +1351,10 @@ void CABACWriter::prediction_unit( const PredictionUnit& pu )
}
if( pu.interDir != 1 /* PRED_L0 */ )
{
#if JVET_M0444_SMVD
if ( pu.cu->smvdMode != 1 )
{
#endif
ref_idx ( pu, REF_PIC_LIST_1 );
if( !pu.cs->slice->getMvdL1ZeroFlag() || pu.interDir != 3 /* PRED_BI */ )
{
......@@ -1365,11 +1372,33 @@ void CABACWriter::prediction_unit( const PredictionUnit& pu )
mvd_coding( pu.mvd[REF_PIC_LIST_1], pu.cu->imv );
}
}
#if JVET_M0444_SMVD
}
#endif
mvp_flag ( pu, REF_PIC_LIST_1 );
}
}
}
#if JVET_M0444_SMVD
void CABACWriter::smvd_mode( const PredictionUnit& pu )
{
if ( pu.interDir != 3 || pu.cu->affine )
{
return;
}
if ( pu.cs->slice->getBiDirPred() == false )
{
return;
}
m_BinEncoder.encodeBin( pu.cu->smvdMode ? 1 : 0, Ctx::SmvdFlag() );
DTRACE( g_trace_ctx, D_SYNTAX, "symmvd_flag() symmvd=%d pos=(%d,%d) size=%dx%d\n", pu.cu->smvdMode ? 1 : 0, pu.lumaPos().x, pu.lumaPos().y, pu.lumaSize().width, pu.lumaSize().height );
}
#endif
void CABACWriter::subblock_merge_flag( const CodingUnit& cu )
{
if ( cu.firstPU->mergeFlag && (cu.firstPU->mmvdMergeFlag || cu.mmvdSkip) )
......@@ -1607,6 +1636,14 @@ void CABACWriter::inter_pred_idc( const PredictionUnit& pu )
void CABACWriter::ref_idx( const PredictionUnit& pu, RefPicList eRefList )
{
#if JVET_M0444_SMVD
if ( pu.cu->smvdMode )
{
CHECK( pu.refIdx[eRefList] != pu.cs->slice->getSymRefIdx( eRefList ), "Invalid reference index!\n" );
return;
}
#endif
int numRef = pu.cs->slice->getNumRefIdx(eRefList);
if( numRef <= 1 )
{
......
......@@ -124,6 +124,9 @@ public:
void MHIntra_flag ( const PredictionUnit& pu );
void MHIntra_luma_pred_modes ( const CodingUnit& cu );
void triangle_mode ( const CodingUnit& cu );
#if JVET_M0444_SMVD
void smvd_mode ( const PredictionUnit& pu );
#endif
// pcm samples (clause 7.3.8.7)
void pcm_samples ( const TransformUnit& tu );
......
......@@ -1842,6 +1842,81 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic,
pcPic->slices[pcSlice->getSliceSegmentIdx()]->setMvdL1ZeroFlag(pcSlice->getMvdL1ZeroFlag());
#endif
#if JVET_M0444_SMVD
if ( pcSlice->getCheckLDC() == false && pcSlice->getMvdL1ZeroFlag() == false )
{
int currPOC = pcSlice->getPOC();
int forwardPOC = currPOC;
int bacwardPOC = currPOC;
int ref = 0, refIdx0 = -1, refIdx1 = -1;
// search nearest forward POC in List 0
for ( ref = 0; ref < pcSlice->getNumRefIdx( REF_PIC_LIST_0 ); ref++ )
{
int poc = pcSlice->getRefPic( REF_PIC_LIST_0, ref )->getPOC();
if ( poc < currPOC && (poc > forwardPOC || refIdx0 == -1) )
{
forwardPOC = poc;
refIdx0 = ref;
}
}
// search nearest backward POC in List 1
for ( ref = 0; ref < pcSlice->getNumRefIdx( REF_PIC_LIST_1 ); ref++ )
{
int poc = pcSlice->getRefPic( REF_PIC_LIST_1, ref )->getPOC();
if ( poc > currPOC && (poc < bacwardPOC || refIdx1 == -1) )
{
bacwardPOC = poc;
refIdx1 = ref;
}
}
if ( !(forwardPOC < currPOC && bacwardPOC > currPOC) )
{
forwardPOC = currPOC;
bacwardPOC = currPOC;
refIdx0 = -1;
refIdx1 = -1;
// search nearest backward POC in List 0
for ( ref = 0; ref < pcSlice->getNumRefIdx( REF_PIC_LIST_0 ); ref++ )
{
int poc = pcSlice->getRefPic( REF_PIC_LIST_0, ref )->getPOC();
if ( poc > currPOC && (poc < bacwardPOC || refIdx0 == -1) )
{
bacwardPOC = poc;
refIdx0 = ref;
}
}
// search nearest forward POC in List 1
for ( ref = 0; ref < pcSlice->getNumRefIdx( REF_PIC_LIST_1 ); ref++ )
{
int poc = pcSlice->getRefPic( REF_PIC_LIST_1, ref )->getPOC();
if ( poc < currPOC && (poc > forwardPOC || refIdx1 == -1) )
{
forwardPOC = poc;
refIdx1 = ref;
}
}
}
if ( forwardPOC < currPOC && bacwardPOC > currPOC )
{
pcSlice->setBiDirPred( true, refIdx0, refIdx1 );
}
else
{
pcSlice->setBiDirPred( false, -1, -1 );
}
}
else
{
pcSlice->setBiDirPred( false, -1, -1 );
}
#endif
double lambda = 0.0;
int actualHeadBits = 0;
......
......@@ -1523,6 +1523,10 @@ void InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner)
uint32_t uiLastModeTemp = 0;
int iRefStart, iRefEnd;
#if JVET_M0444_SMVD
int symMode = 0;
#endif
int bestBiPRefIdxL1 = 0;
int bestBiPMvpL1 = 0;
Distortion biPDistTemp = std::numeric_limits<Distortion>::max();
......@@ -1813,7 +1817,12 @@ void InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner)
}
}
uiBitsTemp += m_auiMVPIdxCost[aaiMvpIdxBi[iRefList][iRefIdxTemp]][AMVP_MAX_NUM_CANDS];
#if JVET_M0444_SMVD
if ( cs.slice->getBiDirPred() )
{
uiBitsTemp += 1; // add one bit for symmetrical MVD mode
}
#endif
// call ME
xCopyAMVPInfo(&aacAMVPInfo[iRefList][iRefIdxTemp], &amvp[eRefPicList] );
xMotionEstimation ( pu, origBuf, eRefPicList, cMvPredBi[iRefList][iRefIdxTemp], iRefIdxTemp, cMvTemp[iRefList][iRefIdxTemp], aaiMvpIdxBi[iRefList][iRefIdxTemp], uiBitsTemp, uiCostTemp, amvp[eRefPicList], true );
......@@ -1860,6 +1869,113 @@ void InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner)
} // for loop-iter
cu.refIdxBi[0] = iRefIdxBi[0];
cu.refIdxBi[1] = iRefIdxBi[1];
#if JVET_M0444_SMVD
if ( cs.slice->getBiDirPred() )
{
Distortion symCost;
Mv cMvPredSym[2];
int mvpIdxSym[2];
int curRefList = REF_PIC_LIST_0;
int tarRefList = 1 - curRefList;
RefPicList eCurRefList = (curRefList ? REF_PIC_LIST_1 : REF_PIC_LIST_0);
int refIdxCur = cs.slice->getSymRefIdx( curRefList );
int refIdxTar = cs.slice->getSymRefIdx( tarRefList );
MvField cCurMvField, cTarMvField;
Distortion costStart = std::numeric_limits<Distortion>::max();
for ( int i = 0; i < aacAMVPInfo[curRefList][refIdxCur].numCand; i++ )
{
for ( int j = 0; j < aacAMVPInfo[tarRefList][refIdxTar].numCand; j++ )
{
cCurMvField.setMvField( aacAMVPInfo[curRefList][refIdxCur].mvCand[i], refIdxCur );
cTarMvField.setMvField( aacAMVPInfo[tarRefList][refIdxTar].mvCand[j], refIdxTar );
Distortion cost = xGetSymmetricCost( pu, origBuf, eCurRefList, cCurMvField, cTarMvField, gbiIdx );
if ( cost < costStart )
{
costStart = cost;
cMvPredSym[curRefList] = aacAMVPInfo[curRefList][refIdxCur].mvCand[i];
cMvPredSym[tarRefList] = aacAMVPInfo[tarRefList][refIdxTar].mvCand[j];
mvpIdxSym[curRefList] = i;
mvpIdxSym[tarRefList] = j;
}
}
}
cCurMvField.mv = cMvPredSym[curRefList];
cTarMvField.mv = cMvPredSym[tarRefList];
m_pcRdCost->setCostScale(0);
m_pcRdCost->setPredictor(cMvPredSym[curRefList]);
uint32_t bits = m_pcRdCost->getBitsOfVectorWithPredictor(cCurMvField.mv.hor, cCurMvField.mv.ver, (pu.cu->imv << 1));
bits += m_auiMVPIdxCost[mvpIdxSym[curRefList]][AMVP_MAX_NUM_CANDS];
bits += m_auiMVPIdxCost[mvpIdxSym[tarRefList]][AMVP_MAX_NUM_CANDS];
costStart += m_pcRdCost->getCost(bits);
std::vector<Mv> symmvdCands;
symmvdCands.push_back(cMvTemp[curRefList][refIdxCur]);
if (iRefIdxBi[curRefList] == refIdxCur && cMvBi[curRefList] != cMvTemp[curRefList][refIdxCur])
{
symmvdCands.push_back(cMvBi[curRefList]);
}
for (auto mvStart : symmvdCands)
{
bool checked = false; //if it has been checkin in the mvPred.
for (int i = 0; i < aacAMVPInfo[curRefList][refIdxCur].numCand && !checked; i++)
{
checked |= (mvStart == aacAMVPInfo[curRefList][refIdxCur].mvCand[i]);
}
if (checked)
break;
Distortion bestCost = costStart;
symmvdCheckBestMvp(pu, origBuf, mvStart, (RefPicList)curRefList, aacAMVPInfo, gbiIdx, cMvPredSym, mvpIdxSym, costStart);
if (costStart < bestCost)
{
cCurMvField.setMvField(mvStart, refIdxCur);
cTarMvField.setMvField(mvStart.getSymmvdMv(cMvPredSym[curRefList], cMvPredSym[tarRefList]), refIdxTar);
}
}
Mv startPtMv = cCurMvField.mv;
Distortion mvpCost = m_pcRdCost->getCost(m_auiMVPIdxCost[mvpIdxSym[curRefList]][AMVP_MAX_NUM_CANDS] + m_auiMVPIdxCost[mvpIdxSym[tarRefList]][AMVP_MAX_NUM_CANDS]);