diff --git a/cfg/encoder_lowdelay_vtm.cfg b/cfg/encoder_lowdelay_vtm.cfg index 71db8a36cea81aab0b2a05236d942766f31fc7b7..4bfdd9fa3d242a466442cbac4ab08580ba5719cf 100644 --- a/cfg/encoder_lowdelay_vtm.cfg +++ b/cfg/encoder_lowdelay_vtm.cfg @@ -113,6 +113,7 @@ MTS : 1 MTSIntraMaxCand : 3 MTSInterMaxCand : 4 SBT : 1 +MMVD : 1 Affine : 1 SubPuMvp : 1 MaxNumMergeCand : 6 diff --git a/cfg/encoder_randomaccess_vtm.cfg b/cfg/encoder_randomaccess_vtm.cfg index 948f0055c26f9086c0f61c9509ff35b8616ef9a8..20525f128d092c3ad161a1e7bb2833ea71dd60df 100644 --- a/cfg/encoder_randomaccess_vtm.cfg +++ b/cfg/encoder_randomaccess_vtm.cfg @@ -127,6 +127,7 @@ MTS : 1 MTSIntraMaxCand : 3 MTSInterMaxCand : 4 SBT : 1 +MMVD : 1 Affine : 1 SubPuMvp : 1 MaxNumMergeCand : 6 diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp index 5be9d2cc9dc87ab7cb1a83219897bd5ac36e3047..c64fe2a0ee9de5487b128fbb01714ee9f8f4822e 100644 --- a/source/App/EncoderApp/EncApp.cpp +++ b/source/App/EncoderApp/EncApp.cpp @@ -279,6 +279,9 @@ void EncApp::xInitLibCfg() m_cEncLib.setUseAffineAmvr ( m_AffineAmvr ); m_cEncLib.setUseAffineAmvrEncOpt ( m_AffineAmvrEncOpt ); m_cEncLib.setDMVR ( m_DMVR ); +#if JVET_N0127_MMVD_SPS_FLAG + m_cEncLib.setMMVD ( m_MMVD ); +#endif #if JVET_N0449_MMVD_SIMP m_cEncLib.setMmvdDisNum (m_MmvdDisNum); #endif diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp index 294b46d88f3804bad84b93476039fc1478a9b2bd..4e118265551014b3cf3d9a0a3a6b68d71930955e 100644 --- a/source/App/EncoderApp/EncAppCfg.cpp +++ b/source/App/EncoderApp/EncAppCfg.cpp @@ -835,6 +835,9 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) ("MaxBTDepthISliceC", m_uiMaxBTDepthIChroma, 3u, "MaxBTDepthISliceC") ("DualITree", m_dualTree, false, "Use separate QTBT trees for intra slice luma and chroma channel types") ("SubPuMvp", m_SubPuMvpMode, 0, "Enable Sub-PU temporal motion vector prediction (0:off, 1:ATMVP, 2:STMVP, 3:ATMVP+STMVP) [default: off]") +#if JVET_N0127_MMVD_SPS_FLAG + ("MMVD", m_MMVD, false, "Merge mode with Motion Vector Difference") +#endif ("Affine", m_Affine, false, "Enable affine prediction (0:off, 1:on) [default: off]") ("AffineType", m_AffineType, true, "Enable affine type prediction (0:off, 1:on) [default: on]" ) ("BIO", m_BIO, false, "Enable bi-directional optical flow") @@ -1965,6 +1968,9 @@ bool EncAppCfg::xCheckParameter() xConfirmPara( m_GBiFast, "GBiFast is only allowed with NEXT profile" ); xConfirmPara( m_Triangle, "Triangle is only allowed with NEXT profile" ); xConfirmPara(m_DMVR, "DMVR only allowed with NEXT profile"); +#if JVET_N0127_MMVD_SPS_FLAG + xConfirmPara(m_MMVD, "MMVD only allowed with NEXT profile"); +#endif #if JVET_N0449_MMVD_SIMP xConfirmPara(m_MmvdDisNum, "Number of distance MMVD entry setting only allowed with NEXT profile"); #endif @@ -3112,6 +3118,9 @@ void EncAppCfg::xPrintParameter() if( m_profile == Profile::NEXT ) { msg( VERBOSE, "\nNEXT TOOL CFG: " ); +#if JVET_N0127_MMVD_SPS_FLAG + msg( VERBOSE, "MMVD:%d ", m_MMVD); +#endif msg( VERBOSE, "Affine:%d ", m_Affine ); if ( m_Affine ) { @@ -3136,7 +3145,13 @@ void EncAppCfg::xPrintParameter() #endif msg(VERBOSE, "MHIntra:%d ", m_MHIntra); msg( VERBOSE, "Triangle:%d ", m_Triangle ); +#if JVET_N0127_MMVD_SPS_FLAG + m_allowDisFracMMVD = m_MMVD ? m_allowDisFracMMVD : false; + if ( m_MMVD ) + msg(VERBOSE, "AllowDisFracMMVD:%d ", m_allowDisFracMMVD); +#else msg( VERBOSE, "AllowDisFracMMVD:%d ", m_allowDisFracMMVD ); +#endif msg( VERBOSE, "AffineAmvr:%d ", m_AffineAmvr ); m_AffineAmvrEncOpt = m_AffineAmvr ? m_AffineAmvrEncOpt : false; msg( VERBOSE, "AffineAmvrEncOpt:%d ", m_AffineAmvrEncOpt ); diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h index c429a95f5e32272afcf3223bc567caab75c6045b..37f73469575d3cb0f6a2e902ebfdeca6c77cc6ce 100644 --- a/source/App/EncoderApp/EncAppCfg.h +++ b/source/App/EncoderApp/EncAppCfg.h @@ -260,6 +260,9 @@ protected: bool m_AffineAmvr; bool m_AffineAmvrEncOpt; bool m_DMVR; +#if JVET_N0127_MMVD_SPS_FLAG + bool m_MMVD; +#endif #if JVET_N0449_MMVD_SIMP int m_MmvdDisNum; #endif diff --git a/source/Lib/CommonLib/Slice.cpp b/source/Lib/CommonLib/Slice.cpp index 7e25a30b79fd1d880cf3192dce882f3e983378b6..6135d726fdaf5dc6092f1470c01b7c86fca700d0 100644 --- a/source/Lib/CommonLib/Slice.cpp +++ b/source/Lib/CommonLib/Slice.cpp @@ -1776,6 +1776,9 @@ SPS::SPS() #endif , m_affineAmvrEnabledFlag ( false ) , m_DMVR ( false ) +#if JVET_N0127_MMVD_SPS_FLAG +, m_MMVD ( false ) +#endif , m_SBT ( false ) , m_MaxSbtSize ( 32 ) #if HEVC_VPS diff --git a/source/Lib/CommonLib/Slice.h b/source/Lib/CommonLib/Slice.h index f68f0f8aa915e5b33e55ed92a0cc6cf06ef467be..8cd2ea7197d86218c0e12cc847b845f516e12662 100644 --- a/source/Lib/CommonLib/Slice.h +++ b/source/Lib/CommonLib/Slice.h @@ -1012,6 +1012,9 @@ private: bool m_affineAmvrEnabledFlag; bool m_DMVR; +#if JVET_N0127_MMVD_SPS_FLAG + bool m_MMVD; +#endif bool m_SBT; uint8_t m_MaxSbtSize; #if HEVC_VPS @@ -1299,6 +1302,10 @@ public: void setDisFracMmvdEnabledFlag( bool b ) { m_disFracMmvdEnabledFlag = b; } bool getUseDMVR()const { return m_DMVR; } void setUseDMVR(bool b) { m_DMVR = b; } +#if JVET_N0127_MMVD_SPS_FLAG + bool getUseMMVD()const { return m_MMVD; } + void setUseMMVD(bool b) { m_MMVD = b; } +#endif uint32_t getMaxTLayers() const { return m_uiMaxTLayers; } void setMaxTLayers( uint32_t uiMaxTLayers ) { CHECK( uiMaxTLayers > MAX_TLAYER, "Invalid number T-layers" ); m_uiMaxTLayers = uiMaxTLayers; } diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index a3a4dd41ab54b6b502f33b5ed274f29e558e5feb..f716844d062d3546690cecf5b41192836452401a 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -50,6 +50,8 @@ #include <assert.h> #include <cassert> +#define JVET_N0127_MMVD_SPS_FLAG 1 + #define JVET_N0286_SIMPLIFIED_GBI_IDX 1 // Simplified coding of the GBi index #define JVET_N600_AMVR_TPM_CTX_REDUCTION 1 diff --git a/source/Lib/DecoderLib/CABACReader.cpp b/source/Lib/DecoderLib/CABACReader.cpp index 6fa451665a24aa881d020b81ad286b5d97e55bb7..428b3ac53ef8138641344a57b8bfa0bb12b5f2f5 100644 --- a/source/Lib/DecoderLib/CABACReader.cpp +++ b/source/Lib/DecoderLib/CABACReader.cpp @@ -768,9 +768,20 @@ void CABACReader::cu_skip_flag( CodingUnit& cu ) #if JVET_MMVD_OFF_MACRO cu.mmvdSkip = false; #else - unsigned mmvdSkip = m_BinDecoder.decodeBin(Ctx::MmvdFlag(0)); - cu.mmvdSkip = mmvdSkip; - DTRACE(g_trace_ctx, D_SYNTAX, "mmvd_cu_skip_flag() ctx=%d mmvd_skip=%d\n", 0, mmvdSkip ? 1 : 0); +#if JVET_N0127_MMVD_SPS_FLAG + if (cu.cs->slice->getSPS()->getUseMMVD()) + { +#endif + unsigned mmvdSkip = m_BinDecoder.decodeBin(Ctx::MmvdFlag(0)); + cu.mmvdSkip = mmvdSkip; + DTRACE(g_trace_ctx, D_SYNTAX, "mmvd_cu_skip_flag() ctx=%d mmvd_skip=%d\n", 0, mmvdSkip ? 1 : 0); +#if JVET_N0127_MMVD_SPS_FLAG + } + else + { + cu.mmvdSkip = false; + } +#endif #endif cu.skip = true; cu.rootCbf = false; @@ -1561,11 +1572,21 @@ void CABACReader::merge_flag( PredictionUnit& pu ) #if JVET_MMVD_OFF_MACRO pu.mmvdMergeFlag = false; #else - if (pu.mergeFlag) + if (pu.mergeFlag +#if JVET_N0127_MMVD_SPS_FLAG + && pu.cs->sps->getUseMMVD() +#endif + ) { pu.mmvdMergeFlag = (m_BinDecoder.decodeBin(Ctx::MmvdFlag(0))); DTRACE(g_trace_ctx, D_SYNTAX, "mmvd_merge_flag() mmvd_merge=%d pos=(%d,%d) size=%dx%d\n", pu.mmvdMergeFlag ? 1 : 0, pu.lumaPos().x, pu.lumaPos().y, pu.lumaSize().width, pu.lumaSize().height); } +#if JVET_N0127_MMVD_SPS_FLAG + else + { + pu.mmvdMergeFlag = false; + } +#endif #endif } diff --git a/source/Lib/DecoderLib/VLCReader.cpp b/source/Lib/DecoderLib/VLCReader.cpp index 38a2c5cf776c6264eedbd1542aea780a4b5d2c2b..3dda34d9a3ef4e82090b9aa1ddf28e7c48d6bea4 100644 --- a/source/Lib/DecoderLib/VLCReader.cpp +++ b/source/Lib/DecoderLib/VLCReader.cpp @@ -1094,7 +1094,9 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS) READ_FLAG( uiCode, "sps_affine_amvr_enabled_flag" ); pcSPS->setAffineAmvrEnabledFlag ( uiCode != 0 ); READ_FLAG(uiCode, "sps_dmvr_enable_flag"); pcSPS->setUseDMVR(uiCode != 0); - +#if JVET_N0127_MMVD_SPS_FLAG + READ_FLAG(uiCode, "sps_mmvd_enable_flag"); pcSPS->setUseMMVD(uiCode != 0); +#endif // KJS: sps_cclm_enabled_flag READ_FLAG( uiCode, "lm_chroma_enabled_flag" ); pcSPS->setUseLMChroma ( uiCode != 0 ); if ( pcSPS->getUseLMChroma() && pcSPS->getChromaFormatIdc() == CHROMA_420 ) @@ -1122,7 +1124,14 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS) READ_FLAG( uiCode, "triangle_flag" ); pcSPS->setUseTriangle ( uiCode != 0 ); // KJS: not in draft yet +#if JVET_N0127_MMVD_SPS_FLAG + if ( pcSPS->getUseMMVD() ) + { + READ_FLAG(uiCode, "sps_fracmmvd_disabled_flag"); pcSPS->setDisFracMmvdEnabledFlag ( uiCode != 0 ); + } +#else READ_FLAG( uiCode, "sps_fracmmvd_disabled_flag" ); pcSPS->setDisFracMmvdEnabledFlag ( uiCode != 0 ); +#endif // KJS: not in draft yet READ_FLAG(uiCode, "sbt_enable_flag"); pcSPS->setUseSBT(uiCode != 0); if( pcSPS->getUseSBT() ) diff --git a/source/Lib/EncoderLib/CABACWriter.cpp b/source/Lib/EncoderLib/CABACWriter.cpp index 4aa704fb80230a567c42e2db76a943fc06969653..712040c8a433c0812bbd48f4464728e1af365cc4 100644 --- a/source/Lib/EncoderLib/CABACWriter.cpp +++ b/source/Lib/EncoderLib/CABACWriter.cpp @@ -650,7 +650,11 @@ void CABACWriter::cu_skip_flag( const CodingUnit& cu ) m_BinEncoder.encodeBin(CU::isIBC(cu) ? 1 : 0, Ctx::IBCFlag(ctxidx)); DTRACE(g_trace_ctx, D_SYNTAX, "ibc() ctx=%d cu.predMode=%d\n", ctxidx, cu.predMode); #if !JVET_MMVD_OFF_MACRO - if (CU::isInter(cu)) + if (CU::isInter(cu) +#if JVET_N0127_MMVD_SPS_FLAG + && cu.cs->slice->getSPS()->getUseMMVD() +#endif + ) { m_BinEncoder.encodeBin(cu.mmvdSkip, Ctx::MmvdFlag(0)); DTRACE(g_trace_ctx, D_SYNTAX, "mmvd_cu_skip_flag() ctx=%d mmvd_skip=%d\n", 0, cu.mmvdSkip ? 1 : 0); @@ -658,7 +662,11 @@ void CABACWriter::cu_skip_flag( const CodingUnit& cu ) #endif } #if !JVET_MMVD_OFF_MACRO - if (cu.skip && !cu.cs->slice->getSPS()->getIBCFlag()) + if (cu.skip && !cu.cs->slice->getSPS()->getIBCFlag() +#if JVET_N0127_MMVD_SPS_FLAG + && cu.cs->slice->getSPS()->getUseMMVD() +#endif + ) { m_BinEncoder.encodeBin(cu.mmvdSkip, Ctx::MmvdFlag(0)); DTRACE(g_trace_ctx, D_SYNTAX, "mmvd_cu_skip_flag() ctx=%d mmvd_skip=%d\n", 0, cu.mmvdSkip ? 1 : 0); @@ -1448,7 +1456,11 @@ void CABACWriter::merge_flag( const PredictionUnit& pu ) return; } #if !JVET_MMVD_OFF_MACRO - if (pu.mergeFlag) + if (pu.mergeFlag +#if JVET_N0127_MMVD_SPS_FLAG + && pu.cs->sps->getUseMMVD() +#endif + ) { m_BinEncoder.encodeBin(pu.mmvdMergeFlag, Ctx::MmvdFlag(0)); DTRACE(g_trace_ctx, D_SYNTAX, "mmvd_merge_flag() mmvd_merge=%d pos=(%d,%d) size=%dx%d\n", pu.mmvdMergeFlag ? 1 : 0, pu.lumaPos().x, pu.lumaPos().y, pu.lumaSize().width, pu.lumaSize().height); diff --git a/source/Lib/EncoderLib/EncCfg.h b/source/Lib/EncoderLib/EncCfg.h index c955989a12b1899e1cbacfbd33353600e762773d..906f18c3d14be3661422ba7649fddaccccd8de89 100644 --- a/source/Lib/EncoderLib/EncCfg.h +++ b/source/Lib/EncoderLib/EncCfg.h @@ -240,6 +240,9 @@ protected: bool m_HashME; bool m_AffineAmvrEncOpt; bool m_DMVR; +#if JVET_N0127_MMVD_SPS_FLAG + bool m_MMVD; +#endif #if JVET_N0449_MMVD_SIMP int m_MmvdDisNum; #endif @@ -763,6 +766,10 @@ public: bool getUseAffineAmvrEncOpt () const { return m_AffineAmvrEncOpt; } void setDMVR ( bool b ) { m_DMVR = b; } bool getDMVR () const { return m_DMVR; } +#if JVET_N0127_MMVD_SPS_FLAG + void setMMVD (bool b) { m_MMVD = b; } + bool getMMVD () const { return m_MMVD; } +#endif #if JVET_N0449_MMVD_SIMP void setMmvdDisNum ( int b ) { m_MmvdDisNum = b; } int getMmvdDisNum () const { return m_MmvdDisNum; } diff --git a/source/Lib/EncoderLib/EncCu.cpp b/source/Lib/EncoderLib/EncCu.cpp index faefbe832d8229761c7c3ad71d2c4b7cb221f842..0023714e0fe704bce744022925d8d84be5ed98ca 100644 --- a/source/Lib/EncoderLib/EncCu.cpp +++ b/source/Lib/EncoderLib/EncCu.cpp @@ -1851,6 +1851,9 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& uiBitsCand--; } #if !JVET_MMVD_OFF_MACRO +#if JVET_N0127_MMVD_SPS_FLAG + if ( pu.cs->sps->getUseMMVD() ) +#endif uiBitsCand++; // for mmvd_flag #endif double cost = (double)uiSad + (double)uiBitsCand * sqrtLambdaForFirstPass; @@ -1978,6 +1981,9 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& cu.mmvdSkip = true; int tempNum = 0; tempNum = MMVD_ADD_NUM; +#if JVET_N0127_MMVD_SPS_FLAG + if ( pu.cs->sps->getUseMMVD() ) +#endif for (uint32_t mergeCand = mergeCtx.numValidMergeCand; mergeCand < mergeCtx.numValidMergeCand + tempNum; mergeCand++) { const int mmvdMergeCand = mergeCand - mergeCtx.numValidMergeCand; diff --git a/source/Lib/EncoderLib/EncLib.cpp b/source/Lib/EncoderLib/EncLib.cpp index 1f956d4025aab93b239a6a54bf0f5fea2cd738ac..875df115ed58a6b4844c55e0b16eab66b84ce04d 100644 --- a/source/Lib/EncoderLib/EncLib.cpp +++ b/source/Lib/EncoderLib/EncLib.cpp @@ -976,7 +976,14 @@ void EncLib::xInitSPS(SPS &sps) sps.setUseMHIntra ( m_MHIntra ); sps.setUseTriangle ( m_Triangle ); +#if JVET_N0127_MMVD_SPS_FLAG + sps.setUseMMVD ( m_MMVD ); +#endif +#if JVET_N0127_MMVD_SPS_FLAG + sps.setDisFracMmvdEnabledFlag(( m_MMVD ) ? m_allowDisFracMMVD : false); +#else sps.setDisFracMmvdEnabledFlag ( m_allowDisFracMMVD ); +#endif sps.setAffineAmvrEnabledFlag ( m_AffineAmvr ); sps.setUseDMVR ( m_DMVR ); diff --git a/source/Lib/EncoderLib/VLCWriter.cpp b/source/Lib/EncoderLib/VLCWriter.cpp index 5c136db268a14a2c576f374d15738d35e26adbce..5292a80de2e179a08f322c39a25605d54145d23e 100644 --- a/source/Lib/EncoderLib/VLCWriter.cpp +++ b/source/Lib/EncoderLib/VLCWriter.cpp @@ -750,7 +750,9 @@ void HLSWriter::codeSPS( const SPS* pcSPS ) WRITE_FLAG( pcSPS->getAffineAmvrEnabledFlag() ? 1 : 0, "sps_affine_amvr_enabled_flag" ); WRITE_FLAG( pcSPS->getUseDMVR() ? 1 : 0, "sps_dmvr_enable_flag" ); - +#if JVET_N0127_MMVD_SPS_FLAG + WRITE_FLAG(pcSPS->getUseMMVD() ? 1 : 0, "sps_mmvd_enable_flag"); +#endif // KJS: sps_cclm_enabled_flag WRITE_FLAG( pcSPS->getUseLMChroma() ? 1 : 0, "lm_chroma_enabled_flag" ); if ( pcSPS->getUseLMChroma() && pcSPS->getChromaFormatIdc() == CHROMA_420 ) @@ -779,7 +781,14 @@ void HLSWriter::codeSPS( const SPS* pcSPS ) WRITE_FLAG( pcSPS->getUseTriangle() ? 1: 0, "triangle_flag" ); // KJS: not in draft yet +#if JVET_N0127_MMVD_SPS_FLAG + if ( pcSPS->getUseMMVD() ) + { + WRITE_FLAG(pcSPS->getDisFracMmvdEnabledFlag() ? 1 : 0, "sps_fracmmvd_disabled_flag"); + } +#else WRITE_FLAG( pcSPS->getDisFracMmvdEnabledFlag() ? 1 : 0, "sps_fracmmvd_disabled_flag" ); +#endif // KJS: not in draft yet WRITE_FLAG( pcSPS->getUseSBT() ? 1 : 0, "sbt_enable_flag"); if( pcSPS->getUseSBT() )