Commit aa17a16a authored by Hongbin Liu's avatar Hongbin Liu Committed by Frank Bossen

JVET-M0246: adaptive MV precision for affine inter mode

parent 68ecfe81
......@@ -113,6 +113,7 @@ IMV : 2
ALF : 1
IBC : 0 # turned off in CTC
AllowDisFracMMVD : 1
AffineAmvr : 0
# Fast tools
PBIntraFast : 1
......
......@@ -130,6 +130,7 @@ ALF : 1
MHIntra : 1
IBC : 0 # turned off in CTC
AllowDisFracMMVD : 1
AffineAmvr : 0
# Fast tools
PBIntraFast : 1
......
......@@ -133,6 +133,7 @@ MHIntra : 1
Triangle : 1
IBC : 0 # turned off in CTC
AllowDisFracMMVD : 1
AffineAmvr : 0
# Fast tools
PBIntraFast : 1
......
......@@ -148,6 +148,7 @@ MHIntra : 1
Triangle : 1
IBC : 0 # turned off in CTC
AllowDisFracMMVD : 1
AffineAmvr : 1
# Fast tools
PBIntraFast : 1
......
......@@ -259,6 +259,9 @@ void EncApp::xInitLibCfg()
m_cEncLib.setUseTriangle ( m_Triangle );
#if JVET_M0255_FRACMMVD_SWITCH
m_cEncLib.setAllowDisFracMMVD ( m_allowDisFracMMVD );
#endif
#if JVET_M0246_AFFINE_AMVR
m_cEncLib.setUseAffineAmvr ( m_AffineAmvr );
#endif
m_cEncLib.setIBCMode ( m_IBCMode );
m_cEncLib.setIBCLocalSearchRangeX ( m_IBCLocalSearchRangeX );
......
......@@ -866,6 +866,9 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
("Triangle", m_Triangle, false, "Enable triangular shape motion vector prediction (0:off, 1:on)")
#if JVET_M0255_FRACMMVD_SWITCH
("AllowDisFracMMVD", m_allowDisFracMMVD, false, "Disable fractional MVD in MMVD mode adaptively")
#endif
#if JVET_M0246_AFFINE_AMVR
("AffineAmvr", m_AffineAmvr, false, "Eanble AMVR for affine inter mode")
#endif
( "IBC", m_IBCMode, 0u, "IBCMode (0x1:enabled, 0x0:disabled) [default: disabled]")
( "IBCLocalSearchRangeX", m_IBCLocalSearchRangeX, 128u, "Search range of IBC local search in x direction")
......@@ -3149,6 +3152,9 @@ void EncAppCfg::xPrintParameter()
msg( VERBOSE, "Triangle:%d ", m_Triangle );
#if JVET_M0255_FRACMMVD_SWITCH
msg( VERBOSE, "AllowDisFracMMVD:%d ", m_allowDisFracMMVD );
#endif
#if JVET_M0246_AFFINE_AMVR
msg( VERBOSE, "AffineAmvr:%d ", m_AffineAmvr );
#endif
}
msg(VERBOSE, "IBC:%d ", m_IBCMode);
......
......@@ -240,6 +240,9 @@ protected:
#if JVET_M0255_FRACMMVD_SWITCH
bool m_allowDisFracMMVD;
#endif
#if JVET_M0246_AFFINE_AMVR
bool m_AffineAmvr;
#endif
unsigned m_IBCMode;
unsigned m_IBCLocalSearchRangeX;
......@@ -248,7 +251,7 @@ protected:
unsigned m_IBCHashSearchMaxCand;
unsigned m_IBCHashSearchRange4SmallBlk;
unsigned m_IBCFastMethod;
bool m_wrapAround;
unsigned m_wrapAroundOffset;
......
......@@ -62,6 +62,9 @@ CodingStructure::CodingStructure(CUCache& cuCache, PUCache& puCache, TUCache& tu
: area ()
, picture ( nullptr )
, parent ( nullptr )
#if JVET_M0246_AFFINE_AMVR
, bestCS ( nullptr )
#endif
, m_isTuEnc ( false )
, m_cuCache ( cuCache )
, m_puCache ( puCache )
......
......@@ -79,7 +79,9 @@ public:
Picture *picture;
CodingStructure *parent;
#if JVET_M0246_AFFINE_AMVR
CodingStructure *bestCS;
#endif
Slice *slice;
UnitScale unitScale[MAX_NUM_COMPONENT];
......
......@@ -1241,15 +1241,28 @@ const CtxSet ContextSetCfg::ChromaQpAdjIdc = ContextSetCfg::addCtxSet
const CtxSet ContextSetCfg::ImvFlag = ContextSetCfg::addCtxSet
({
#if JVET_M0453_CABAC_ENGINE
#if JVET_M0246_AFFINE_AMVR
{ 227, 214, 230, 195, 227, 214, },
{ 213, 229, 230, 166, 213, 229, },
{ CNU, CNU, CNU, CNU, CNU, CNU, },
{ 1, 4, 4, 5, 1, 4, },
#else
{ 227, 214, 230, 195,},
{ 213, 229, 230, 166,},
{ CNU, CNU, CNU, CNU,},
{ 1, 4, 4, 5,},
#endif
#else
#if BD_AFFINE_AMVR
{ 212, 214, 230, 182, 212, 214 },
{ 212, 214, 230, 182, 212, 214 },
{ CNU, CNU, CNU, CNU, CNU, CNU },
#else
{ 212, 214, 230, 182, },
{ 212, 214, 230, 182, },
{ CNU, CNU, CNU, CNU, },
#endif
#endif
});
const CtxSet ContextSetCfg::ctbAlfFlag =
......
......@@ -51,6 +51,9 @@ enum MvPrecision
{
MV_PRECISION_4PEL = 0, // 4-pel
MV_PRECISION_INT = 2, // 1-pel, shift 2 bits from 4-pel
#if JVET_M0246_AFFINE_AMVR
MV_PRECISION_HALF = 3, // 1/2-pel
#endif
MV_PRECISION_QUARTER = 4, // 1/4-pel (the precision of regular MV difference signaling), shift 4 bits from 4-pel
MV_PRECISION_INTERNAL = 6, // 1/16-pel (the precision of internal MV), shift 6 bits from 4-pel
};
......
......@@ -1840,6 +1840,9 @@ SPS::SPS()
, m_bNoLadfConstraintFlag (false)
, m_bNoDepQuantConstraintFlag (false)
, m_bNoSignDataHidingConstraintFlag(false)
#if JVET_M0246_AFFINE_AMVR
, m_affineAmvrEnabledFlag ( false )
#endif
#if HEVC_VPS
, m_VPSId ( 0)
#endif
......
......@@ -942,6 +942,9 @@ private:
bool m_bNoDepQuantConstraintFlag;
bool m_bNoSignDataHidingConstraintFlag;
#if JVET_M0246_AFFINE_AMVR
bool m_affineAmvrEnabledFlag;
#endif
#if HEVC_VPS
int m_VPSId;
#endif
......@@ -1227,6 +1230,10 @@ public:
void setUseStrongIntraSmoothing(bool bVal) { m_useStrongIntraSmoothing = bVal; }
bool getUseStrongIntraSmoothing() const { return m_useStrongIntraSmoothing; }
#endif
#if JVET_M0246_AFFINE_AMVR
void setAffineAmvrEnabledFlag( bool val ) { m_affineAmvrEnabledFlag = val; }
bool getAffineAmvrEnabledFlag() const { return m_affineAmvrEnabledFlag; }
#endif
bool getVuiParametersPresentFlag() const { return m_vuiParametersPresentFlag; }
void setVuiParametersPresentFlag(bool b) { m_vuiParametersPresentFlag = b; }
......
......@@ -107,6 +107,7 @@ typedef std::pair<int, bool> TrMode;
typedef std::pair<int, int> TrCost;
#endif
#define JVET_M0246_AFFINE_AMVR 1
#define JVET_M0421_SPLIT_SIG 1
#define JVET_M0173_MOVE_GT2_TO_FIRST_PASS 1 // Moving the gtr2 flag to the first coding pass
......
......@@ -2104,14 +2104,36 @@ bool PU::addAffineMVPCandUnscaled( const PredictionUnit &pu, const RefPicList &r
}
xInheritedAffineMv( pu, neibPU, eRefPicListIndex, outputAffineMv );
outputAffineMv[0].roundToPrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
outputAffineMv[1].roundToPrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
#if JVET_M0246_AFFINE_AMVR
if ( pu.cu->imv == 0 )
{
#endif
outputAffineMv[0].roundToPrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
outputAffineMv[1].roundToPrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
#if JVET_M0246_AFFINE_AMVR
}
else if ( pu.cu->imv == 2 )
{
outputAffineMv[0].roundToPrecision( MV_PRECISION_INTERNAL, MV_PRECISION_INT );
outputAffineMv[1].roundToPrecision( MV_PRECISION_INTERNAL, MV_PRECISION_INT );
}
#endif
affiAMVPInfo.mvCandLT[affiAMVPInfo.numCand] = outputAffineMv[0];
affiAMVPInfo.mvCandRT[affiAMVPInfo.numCand] = outputAffineMv[1];
if ( pu.cu->affineType == AFFINEMODEL_6PARAM )
{
outputAffineMv[2].roundToPrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
#if JVET_M0246_AFFINE_AMVR
if ( pu.cu->imv == 0 )
{
#endif
outputAffineMv[2].roundToPrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
#if JVET_M0246_AFFINE_AMVR
}
else if ( pu.cu->imv == 2 )
{
outputAffineMv[2].roundToPrecision( MV_PRECISION_INTERNAL, MV_PRECISION_INT );
}
#endif
affiAMVPInfo.mvCandLB[affiAMVPInfo.numCand] = outputAffineMv[2];
}
affiAMVPInfo.numCand++;
......@@ -2240,9 +2262,16 @@ void PU::fillAffineMvpCand(PredictionUnit &pu, const RefPicList &eRefPicList, co
{
for (int i = 0; i < affiAMVPInfo.numCand; i++)
{
affiAMVPInfo.mvCandLT[i].changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
affiAMVPInfo.mvCandRT[i].changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
affiAMVPInfo.mvCandLB[i].changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
#if JVET_M0246_AFFINE_AMVR
if ( pu.cu->imv != 1 )
{
#endif
affiAMVPInfo.mvCandLT[i].changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
affiAMVPInfo.mvCandRT[i].changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
affiAMVPInfo.mvCandLB[i].changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
#if JVET_M0246_AFFINE_AMVR
}
#endif
}
return;
}
......@@ -2294,10 +2323,22 @@ void PU::fillAffineMvpCand(PredictionUnit &pu, const RefPicList &eRefPicList, co
outputAffineMv[1] = amvpInfo1.mvCand[0];
outputAffineMv[2] = amvpInfo2.mvCand[0];
outputAffineMv[0].roundToPrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
outputAffineMv[1].roundToPrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
outputAffineMv[2].roundToPrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
#if JVET_M0246_AFFINE_AMVR
if ( pu.cu->imv == 0 )
{
#endif
outputAffineMv[0].roundToPrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
outputAffineMv[1].roundToPrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
outputAffineMv[2].roundToPrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
#if JVET_M0246_AFFINE_AMVR
}
else if ( pu.cu->imv == 2 )
{
outputAffineMv[0].roundToPrecision( MV_PRECISION_INTERNAL, MV_PRECISION_INT );
outputAffineMv[1].roundToPrecision( MV_PRECISION_INTERNAL, MV_PRECISION_INT );
outputAffineMv[2].roundToPrecision( MV_PRECISION_INTERNAL, MV_PRECISION_INT );
}
#endif
if ( cornerMVPattern == 7 || (cornerMVPattern == 3 && pu.cu->affineType == AFFINEMODEL_4PARAM) )
{
......@@ -2372,7 +2413,18 @@ void PU::fillAffineMvpCand(PredictionUnit &pu, const RefPicList &eRefPicList, co
if ( (C0Avail && getColocatedMVP( pu, eRefPicList, posC0, cColMv, refIdxCol )) || getColocatedMVP( pu, eRefPicList, posC1, cColMv, refIdxCol ) )
#endif
{
cColMv.roundToPrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
#if JVET_M0246_AFFINE_AMVR
if ( pu.cu->imv == 0 )
{
#endif
cColMv.roundToPrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
#if JVET_M0246_AFFINE_AMVR
}
else if ( pu.cu->imv == 2 )
{
cColMv.roundToPrecision( MV_PRECISION_INTERNAL, MV_PRECISION_INT );
}
#endif
affiAMVPInfo.mvCandLT[affiAMVPInfo.numCand] = cColMv;
affiAMVPInfo.mvCandRT[affiAMVPInfo.numCand] = cColMv;
affiAMVPInfo.mvCandLB[affiAMVPInfo.numCand] = cColMv;
......@@ -2395,9 +2447,16 @@ void PU::fillAffineMvpCand(PredictionUnit &pu, const RefPicList &eRefPicList, co
for (int i = 0; i < affiAMVPInfo.numCand; i++)
{
affiAMVPInfo.mvCandLT[i].changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
affiAMVPInfo.mvCandRT[i].changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
affiAMVPInfo.mvCandLB[i].changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
#if JVET_M0246_AFFINE_AMVR
if ( pu.cu->imv != 1 )
{
#endif
affiAMVPInfo.mvCandLT[i].changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
affiAMVPInfo.mvCandRT[i].changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
affiAMVPInfo.mvCandLB[i].changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
#if JVET_M0246_AFFINE_AMVR
}
#endif
}
......@@ -4367,6 +4426,47 @@ bool CU::hasSubCUNonZeroMVd( const CodingUnit& cu )
return bNonZeroMvd;
}
#if JVET_M0246_AFFINE_AMVR
bool CU::hasSubCUNonZeroAffineMVd( const CodingUnit& cu )
{
bool nonZeroAffineMvd = false;
if ( !cu.affine || cu.firstPU->mergeFlag )
{
return false;
}
for ( const auto &pu : CU::traversePUs( cu ) )
{
if ( ( !pu.mergeFlag ) && ( !cu.skip ) )
{
if ( pu.interDir != 2 /* PRED_L1 */ )
{
for ( int i = 0; i < ( cu.affineType == AFFINEMODEL_6PARAM ? 3 : 2 ); i++ )
{
nonZeroAffineMvd |= pu.mvdAffi[REF_PIC_LIST_0][i].getHor() != 0;
nonZeroAffineMvd |= pu.mvdAffi[REF_PIC_LIST_0][i].getVer() != 0;
}
}
if ( pu.interDir != 1 /* PRED_L0 */ )
{
if ( !pu.cu->cs->slice->getMvdL1ZeroFlag() || pu.interDir != 3 /* PRED_BI */ )
{
for ( int i = 0; i < ( cu.affineType == AFFINEMODEL_6PARAM ? 3 : 2 ); i++ )
{
nonZeroAffineMvd |= pu.mvdAffi[REF_PIC_LIST_1][i].getHor() != 0;
nonZeroAffineMvd |= pu.mvdAffi[REF_PIC_LIST_1][i].getVer() != 0;
}
}
}
}
}
return nonZeroAffineMvd;
}
#endif
int CU::getMaxNeighboriMVCandNum( const CodingStructure& cs, const Position& pos )
{
const int numDefault = 0;
......
......@@ -92,6 +92,9 @@ namespace CU
cTUTraverser traverseTUs (const CodingUnit& cu);
bool hasSubCUNonZeroMVd (const CodingUnit& cu);
#if JVET_M0246_AFFINE_AMVR
bool hasSubCUNonZeroAffineMVd ( const CodingUnit& cu );
#endif
int getMaxNeighboriMVCandNum (const CodingStructure& cs, const Position& pos);
void resetMVDandMV2Int ( CodingUnit& cu, InterPrediction *interPred );
......
......@@ -979,6 +979,13 @@ void CABACReader::imv_mode( CodingUnit& cu, MergeCtx& mrgCtx )
return;
}
#if JVET_M0246_AFFINE_AMVR
if ( cu.affine )
{
return;
}
#endif
const SPSNext& spsNext = cu.cs->sps->getSpsNext();
unsigned value = 0;
......@@ -1000,6 +1007,39 @@ void CABACReader::imv_mode( CodingUnit& cu, MergeCtx& mrgCtx )
DTRACE( g_trace_ctx, D_SYNTAX, "imv_mode() IMVFlag=%d\n", cu.imv );
}
#if JVET_M0246_AFFINE_AMVR
void CABACReader::affine_amvr_mode( CodingUnit& cu, MergeCtx& mrgCtx )
{
RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET( STATS__CABAC_BITS__OTHER );
const SPS* sps = cu.slice->getSPS();
if( !sps->getAffineAmvrEnabledFlag() || !cu.affine )
{
return;
}
if ( !CU::hasSubCUNonZeroAffineMVd( cu ) )
{
return;
}
unsigned value = 0;
value = m_BinDecoder.decodeBin( Ctx::ImvFlag( 4 ) );
DTRACE( g_trace_ctx, D_SYNTAX, "affine_amvr_mode() value=%d ctx=%d\n", value, 4 );
if( value )
{
value = m_BinDecoder.decodeBin( Ctx::ImvFlag( 5 ) );
DTRACE( g_trace_ctx, D_SYNTAX, "affine_amvr_mode() value=%d ctx=%d\n", value, 5 );
value++;
}
cu.imv = value;
DTRACE( g_trace_ctx, D_SYNTAX, "affine_amvr_mode() IMVFlag=%d\n", cu.imv );
}
#endif
void CABACReader::pred_mode( CodingUnit& cu )
{
RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET( STATS__CABAC_BITS__PRED_MODE );
......@@ -1057,7 +1097,9 @@ void CABACReader::cu_pred_data( CodingUnit &cu )
}
imv_mode ( cu, mrgCtx );
#if JVET_M0246_AFFINE_AMVR
affine_amvr_mode( cu, mrgCtx );
#endif
cu_gbi_flag( cu );
}
......
......@@ -107,6 +107,9 @@ public:
void merge_idx ( PredictionUnit& pu );
void mmvd_merge_idx(PredictionUnit& pu);
void imv_mode ( CodingUnit& cu, MergeCtx& mrgCtx );
#if JVET_M0246_AFFINE_AMVR
void affine_amvr_mode ( CodingUnit& cu, MergeCtx& mrgCtx );
#endif
void inter_pred_idc ( PredictionUnit& pu );
void ref_idx ( PredictionUnit& pu, RefPicList eRefList );
void mvp_flag ( PredictionUnit& pu, RefPicList eRefList );
......
......@@ -583,7 +583,11 @@ void DecCu::xDeriveCUMV( CodingUnit &cu )
else
{
#if REUSE_CU_RESULTS
#if JVET_M0246_AFFINE_AMVR
if ( cu.imv && !pu.cu->affine && !cu.cs->pcv->isEncoder )
#else
if (cu.imv && !cu.cs->pcv->isEncoder)
#endif
#else
if (cu.imv)
#endif
......@@ -608,7 +612,35 @@ void DecCu::xDeriveCUMV( CodingUnit &cu )
// Mv mv[3];
CHECK( pu.refIdx[eRefList] < 0, "Unexpected negative refIdx." );
#if JVET_M0246_AFFINE_AMVR
Mv tmpMvd[3];
memcpy( tmpMvd, pu.mvdAffi[eRefList], 3 * sizeof( Mv ) );
const int imvShift = ( !cu.cs->pcv->isEncoder && pu.cu->imv == 2 ) ? MV_FRACTIONAL_BITS_DIFF : 0;
pu.mvdAffi[eRefList][0] <<= imvShift;
pu.mvdAffi[eRefList][1] <<= imvShift;
Mv mvLT = affineAMVPInfo.mvCandLT[mvp_idx] + pu.mvdAffi[eRefList][0];
Mv mvRT = affineAMVPInfo.mvCandRT[mvp_idx] + pu.mvdAffi[eRefList][1];
mvRT += pu.mvdAffi[eRefList][0];
if ( pu.cu->imv != 1 )
{
mvLT.changePrecision( MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL );
mvRT.changePrecision( MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL );
}
Mv mvLB;
if ( cu.affineType == AFFINEMODEL_6PARAM )
{
pu.mvdAffi[eRefList][2] <<= imvShift;
mvLB = affineAMVPInfo.mvCandLB[mvp_idx] + pu.mvdAffi[eRefList][2];
mvLB += pu.mvdAffi[eRefList][0];
if ( pu.cu->imv != 1 )
{
mvLB.changePrecision( MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL );
}
}
memcpy( pu.mvdAffi[eRefList], tmpMvd, 3 * sizeof( Mv ) );
#else
Mv mvLT = affineAMVPInfo.mvCandLT[mvp_idx] + pu.mvdAffi[eRefList][0];
Mv mvRT = affineAMVPInfo.mvCandRT[mvp_idx] + pu.mvdAffi[eRefList][1];
mvRT += pu.mvdAffi[eRefList][0];
......@@ -622,6 +654,7 @@ void DecCu::xDeriveCUMV( CodingUnit &cu )
mvLB += pu.mvdAffi[eRefList][0];
mvLB.changePrecision(MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL);
}
#endif
PU::setAllAffineMv( pu, mvLT, mvRT, mvLB, eRefList );
}
}
......
......@@ -1050,7 +1050,9 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS)
#if JVET_M0255_FRACMMVD_SWITCH
READ_FLAG( uiCode, "sps_fracmmvd_disabled_flag" ); pcSPS->setDisFracMmvdEnabledFlag ( uiCode != 0 );
#endif
#if JVET_M0246_AFFINE_AMVR
READ_FLAG( uiCode, "sps_affine_amvr_enabled_flag" ); pcSPS->setAffineAmvrEnabledFlag ( uiCode != 0 );
#endif
#if HEVC_USE_SCALING_LISTS
READ_FLAG( uiCode, "scaling_list_enabled_flag" ); pcSPS->setScalingListFlag ( uiCode );
if(pcSPS->getScalingListFlag())
......
......@@ -830,6 +830,9 @@ void CABACWriter::cu_pred_data( const CodingUnit& cu )
}
imv_mode ( cu );
#if JVET_M0246_AFFINE_AMVR
affine_amvr_mode( cu );
#endif
cu_gbi_flag( cu );
......@@ -1326,6 +1329,9 @@ void CABACWriter::prediction_unit( const PredictionUnit& pu )
}
else
{
#if JVET_M0246_AFFINE_AMVR
int8_t affineMvdShift = pu.cu->imv ? ( pu.cu->imv == 1 ? -1 : 1 ) : 0;
#endif
inter_pred_idc( pu );
affine_flag ( *pu.cu );
#if JVET_M0444_SMVD
......@@ -1336,12 +1342,21 @@ void CABACWriter::prediction_unit( const PredictionUnit& pu )
ref_idx ( pu, REF_PIC_LIST_0 );
if ( pu.cu->affine )
{
#if JVET_M0246_AFFINE_AMVR
mvd_coding( pu.mvdAffi[REF_PIC_LIST_0][0], affineMvdShift );
mvd_coding( pu.mvdAffi[REF_PIC_LIST_0][1], affineMvdShift );
if ( pu.cu->affineType == AFFINEMODEL_6PARAM )
{
mvd_coding( pu.mvdAffi[REF_PIC_LIST_0][2], affineMvdShift );
}
#else
mvd_coding(pu.mvdAffi[REF_PIC_LIST_0][0], 0);
mvd_coding(pu.mvdAffi[REF_PIC_LIST_0][1], 0);
if ( pu.cu->affineType == AFFINEMODEL_6PARAM )
{
mvd_coding(pu.mvdAffi[REF_PIC_LIST_0][2], 0);
}
#endif
}
else
{
......@@ -1360,12 +1375,21 @@ void CABACWriter::prediction_unit( const PredictionUnit& pu )
{
if ( pu.cu->affine )
{
#if JVET_M0246_AFFINE_AMVR
mvd_coding( pu.mvdAffi[REF_PIC_LIST_1][0], affineMvdShift );
mvd_coding( pu.mvdAffi[REF_PIC_LIST_1][1], affineMvdShift );
if ( pu.cu->affineType == AFFINEMODEL_6PARAM )
{
mvd_coding( pu.mvdAffi[REF_PIC_LIST_1][2], affineMvdShift );
}
#else
mvd_coding(pu.mvdAffi[REF_PIC_LIST_1][0], 0);
mvd_coding(pu.mvdAffi[REF_PIC_LIST_1][1], 0);
if ( pu.cu->affineType == AFFINEMODEL_6PARAM )
{
mvd_coding(pu.mvdAffi[REF_PIC_LIST_1][2], 0);
}
#endif
}
else
{
......@@ -1451,6 +1475,12 @@ void CABACWriter::imv_mode( const CodingUnit& cu )
{
return;
}
#if JVET_M0246_AFFINE_AMVR
if ( cu.affine )
{
return;
}
#endif
bool bNonZeroMvd = CU::hasSubCUNonZeroMVd( cu );
if( !bNonZeroMvd )
......@@ -1472,6 +1502,33 @@ void CABACWriter::imv_mode( const CodingUnit& cu )
DTRACE( g_trace_ctx, D_SYNTAX, "imv_mode() IMVFlag=%d\n", cu.imv );
}
#if JVET_M0246_AFFINE_AMVR
void CABACWriter::affine_amvr_mode( const CodingUnit& cu )
{
const SPS* sps = cu.slice->getSPS();
if( !sps->getAffineAmvrEnabledFlag() || !cu.affine )
{
return;
}
if ( !CU::hasSubCUNonZeroAffineMVd( cu ) )
{
return;
}
m_BinEncoder.encodeBin( ( cu.imv > 0 ), Ctx::ImvFlag( 4 ) );
DTRACE( g_trace_ctx, D_SYNTAX, "affine_amvr_mode() value=%d ctx=%d\n", ( cu.imv > 0 ), 4 );
if( cu.imv > 0 )
{
m_BinEncoder.encodeBin( ( cu.imv > 1 ), Ctx::ImvFlag( 5 ) );
DTRACE( g_trace_ctx, D_SYNTAX, "affine_amvr_mode() value=%d ctx=%d\n", ( cu.imv > 1 ), 5 );
}
DTRACE( g_trace_ctx, D_SYNTAX, "affine_amvr_mode() IMVFlag=%d\n", cu.imv );
}
#endif
void CABACWriter::merge_idx( const PredictionUnit& pu )
{
......@@ -2001,12 +2058,19 @@ void CABACWriter::cbf_comp( const CodingStructure& cs, bool cbf, const CompArea&
//--------------------------------------------------------------------------------
// void mvd_coding( pu, refList )
//================================================================================
#if JVET_M0246_AFFINE_AMVR
void CABACWriter::mvd_coding( const Mv &rMvd, int8_t imv )
#else
void CABACWriter::mvd_coding( const Mv &rMvd, uint8_t imv )
#endif
{
int horMvd = rMvd.getHor();
int verMvd = rMvd.getVer();
#if JVET_M0246_AFFINE_AMVR
if ( imv > 0 )
#else
if( imv )
#endif
{
CHECK( (horMvd % 4) != 0 && (verMvd % 4) != 0, "IMV: MVD is not a multiple of 4" );
horMvd >>= 2;
......
......@@ -117,6 +117,9 @@ public:
void merge_idx ( const PredictionUnit& pu );
void mmvd_merge_idx(const PredictionUnit& pu);
void imv_mode ( const CodingUnit& cu );
#if JVET_M0246_AFFINE_AMVR
void affine_amvr_mode ( const CodingUnit& cu );
#endif
void inter_pred_idc ( const PredictionUnit& pu );
void ref_idx ( const PredictionUnit& pu, RefPicList eRefList );
void mvp_flag ( const PredictionUnit& pu, RefPicList eRefList );
......@@ -136,8 +139,11 @@ public:
void cbf_comp ( const CodingStructure& cs, bool cbf, const CompArea& area, unsigned depth, const bool prevCbCbf = false );
// mvd coding (clause 7.3.8.9)
#if JVET_M0246_AFFINE_AMVR
void mvd_coding ( const Mv &rMvd, int8_t imv );
#else
void mvd_coding ( const Mv &rMvd, uint8_t imv );
#endif
// transform unit (clause 7.3.8.10)
void transform_unit ( const TransformUnit& tu, CUCtx& cuCtx, ChromaCbfs& chromaCbfs );
void cu_qp_delta ( const CodingUnit& cu, int predQP, const int8_t qp );
......
......@@ -240,6 +240,9 @@ protected:
bool m_Triangle;
#if JVET_M0255_FRACMMVD_SWITCH
bool m_allowDisFracMMVD;
#endif
#if JVET_M0246_AFFINE_AMVR
bool m_AffineAmvr;
#endif
unsigned m_IBCMode;
unsigned m_IBCLocalSearchRangeX;
......@@ -248,7 +251,7 @@ protected:
unsigned m_IBCHashSearchMaxCand;
unsigned m_IBCHashSearchRange4SmallBlk;
unsigned m_IBCFastMethod;
bool m_wrapAround;
unsigned m_wrapAroundOffset;
......@@ -760,6 +763,10 @@ public:
void setAllowDisFracMMVD ( bool b ) { m_allowDisFracMMVD = b; }
bool getAllowDisFracMMVD () const { return m_allowDisFracMMVD; }
#endif
#if JVET_M0246_AFFINE_AMVR
void setUseAffineAmvr ( bool b ) { m_AffineAmvr = b; }
bool getUseAffineAmvr () const { return m_AffineAmvr; }
#endif
void setIBCMode (unsigned n) { m_IBCMode = n; }
unsigned getIBCMode () const { return m_IBCMode; }
......
......@@ -695,6 +695,9 @@ void EncCu::xCompressCU( CodingStructure *&tempCS, CodingStructure *&bestCS, Par
#if JVET_M0170_MRG_SHARELIST
int startShareThisLevel = 0;
#endif
#if JVET_M0246_AFFINE_AMVR
m_pcInterSearch->resetSavedAffineMotion();
#endif
do
{
......@@ -731,11 +734,23 @@ void EncCu::xCompressCU( CodingStructure *&tempCS, CodingStructure *&bestCS, Par