diff --git a/doc/software-manual.tex b/doc/software-manual.tex index 4b25c82181df708381cf77f1928b765596011fde..0e98b594edb56456cf1fdf9bde631d894e87e1c3 100644 --- a/doc/software-manual.tex +++ b/doc/software-manual.tex @@ -1277,6 +1277,12 @@ $} \end{displaymath} \\ +\Option{Log2ParallelMergeLevel} & +%\ShortOption{\None} & +\Default{2} & +Defines the SPS-derived Log2ParallelMergeLevel variable. +\\ + \Option{MaxNumMergeCand} & %\ShortOption{\None} & \Default{5} & diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp index 51e75c6300ab302124092ac7873abeeea00cd068..18766077641f53174beec1c9dbc5bccae2d83af0 100644 --- a/source/App/EncoderApp/EncApp.cpp +++ b/source/App/EncoderApp/EncApp.cpp @@ -520,6 +520,11 @@ void EncApp::xInitLibCfg() m_cEncLib.setUseWP ( m_useWeightedPred ); m_cEncLib.setWPBiPred ( m_useWeightedBiPred ); +#if JVET_Q0297_MER + //====== Parallel Merge Estimation ======== + m_cEncLib.setLog2ParallelMergeLevelMinus2(m_log2ParallelMergeLevel - 2); +#endif + //====== Tiles and Slices ======== m_cEncLib.setNoPicPartitionFlag( !m_picPartitionFlag ); if( m_picPartitionFlag ) diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp index f27d191cb33042633c8304ef4bc18d213e437841..5e17c31335b0ea385a2d340e5bf23b7e9dce64cb 100644 --- a/source/App/EncoderApp/EncAppCfg.cpp +++ b/source/App/EncoderApp/EncAppCfg.cpp @@ -1133,6 +1133,9 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) ("WeightedPredP,-wpP", m_useWeightedPred, false, "Use weighted prediction in P slices") ("WeightedPredB,-wpB", m_useWeightedBiPred, false, "Use weighted (bidirectional) prediction in B slices") ("WeightedPredMethod,-wpM", tmpWeightedPredictionMethod, int(WP_PER_PICTURE_WITH_SIMPLE_DC_COMBINED_COMPONENT), "Weighted prediction method") +#if JVET_Q0297_MER + ("Log2ParallelMergeLevel", m_log2ParallelMergeLevel, 2u, "Parallel merge estimation region") +#endif ("WaveFrontSynchro", m_entropyCodingSyncEnabledFlag, false, "0: entropy coding sync disabled; 1 entropy coding sync enabled") ("ScalingList", m_useScalingListId, SCALING_LIST_OFF, "0/off: no scaling list, 1/default: default scaling lists, 2/file: scaling lists specified in ScalingListFile") ("ScalingListFile", m_scalingListFileName, string(""), "Scaling list file name. Use an empty string to produce help.") @@ -3418,7 +3421,9 @@ bool EncAppCfg::xCheckParameter() xConfirmPara( m_gcmpSEIGuardBandSamplesMinus1 < 0 || m_gcmpSEIGuardBandSamplesMinus1 > 15, "SEIGcmpGuardBandSamplesMinus1 must be in the range of 0 to 15"); } } - +#if JVET_Q0297_MER + xConfirmPara(m_log2ParallelMergeLevel < 2, "Log2ParallelMergeLevel should be larger than or equal to 2"); +#endif #if U0033_ALTERNATIVE_TRANSFER_CHARACTERISTICS_SEI xConfirmPara(m_preferredTransferCharacteristics > 255, "transfer_characteristics_idc should not be greater than 255."); #endif @@ -3626,6 +3631,9 @@ void EncAppCfg::xPrintParameter() msg( VERBOSE, "WPP:%d ", (int)m_useWeightedPred); msg( VERBOSE, "WPB:%d ", (int)m_useWeightedBiPred); +#if JVET_Q0297_MER + msg( VERBOSE, "PME:%d ", m_log2ParallelMergeLevel); +#endif const int iWaveFrontSubstreams = m_entropyCodingSyncEnabledFlag ? (m_iSourceHeight + m_uiMaxCUHeight - 1) / m_uiMaxCUHeight : 1; msg( VERBOSE, " WaveFrontSynchro:%d WaveFrontSubstreams:%d", m_entropyCodingSyncEnabledFlag?1:0, iWaveFrontSubstreams); msg( VERBOSE, " ScalingList:%d ", m_useScalingListId ); diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h index f71b665711b53e45d2026ac3ece890a16819f6a1..4382d99d40d63f26205df77ba97c11dab3a21f85 100644 --- a/source/App/EncoderApp/EncAppCfg.h +++ b/source/App/EncoderApp/EncAppCfg.h @@ -584,6 +584,9 @@ protected: bool m_useWeightedBiPred; ///< Use of bi-directional weighted prediction in B slices WeightedPredictionMethod m_weightedPredictionMethod; +#if JVET_Q0297_MER + uint32_t m_log2ParallelMergeLevel; ///< Parallel merge estimation region +#endif uint32_t m_maxNumMergeCand; ///< Max number of merge candidates uint32_t m_maxNumAffineMergeCand; ///< Max number of affine merge candidates uint32_t m_maxNumTriangleCand; diff --git a/source/Lib/CommonLib/Slice.h b/source/Lib/CommonLib/Slice.h index 584b3f9527c4d9031335864ca3aaf1327dc65eea..fb16ab0dedd95ae76e33e30ada27d09a0c06d518 100644 --- a/source/Lib/CommonLib/Slice.h +++ b/source/Lib/CommonLib/Slice.h @@ -1178,6 +1178,10 @@ private: bool m_rprEnabledFlag; bool m_interLayerPresentFlag; +#if JVET_Q0297_MER + uint32_t m_log2ParallelMergeLevelMinus2; +#endif + public: SPS(); @@ -1486,6 +1490,10 @@ void setCCALFEnabledFlag( bool b ) bool getInterLayerPresentFlag() const { return m_interLayerPresentFlag; } void setInterLayerPresentFlag( bool b ) { m_interLayerPresentFlag = b; } +#if JVET_Q0297_MER + uint32_t getLog2ParallelMergeLevelMinus2() const { return m_log2ParallelMergeLevelMinus2; } + void setLog2ParallelMergeLevelMinus2(uint32_t mrgLevel) { m_log2ParallelMergeLevelMinus2 = mrgLevel; } +#endif }; diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index 0ec6033bc953f84d647580bbd396a686f578c0f4..0ee2cf6433eb430ba5fd30578da9cf5a851490c7 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -83,6 +83,8 @@ #define JVET_Q0054 1 // fix for long luma deblocking decision #define JVET_Q0795_CCALF 1 // Cross-component ALF +#define JVET_Q0297_MER 1 // JVET_Q0297: Merge estimation region + #define JVET_Q0483_CLIP_TMVP 1 // JVET-Q0483: Clip TMVP when no scaling is applied #define JVET_Q0516_MTS_SIGNALLING_DC_ONLY_COND 1 // JVET-Q0516/Q0685: disable MTS when there is only DC coefficient diff --git a/source/Lib/CommonLib/UnitTools.cpp b/source/Lib/CommonLib/UnitTools.cpp index 4fee46c1068cc79f70488c33b47dbf4682abad7f..7dae6ae23dc5e80a70fa1075dc85359a119c1ee8 100644 --- a/source/Lib/CommonLib/UnitTools.cpp +++ b/source/Lib/CommonLib/UnitTools.cpp @@ -250,6 +250,14 @@ void CU::saveMotionInHMVP( const CodingUnit& cu, const bool isToBeDone ) mi.BcwIdx = (mi.interDir == 3) ? cu.BcwIdx : BCW_DEFAULT; +#if JVET_Q0297_MER + const unsigned log2ParallelMergeLevel = (pu.cs->sps->getLog2ParallelMergeLevelMinus2() + 2); + const unsigned xBr = pu.cu->Y().width + pu.cu->Y().x; + const unsigned yBr = pu.cu->Y().height + pu.cu->Y().y; + bool enableHmvp = ((xBr >> log2ParallelMergeLevel) > (pu.cu->Y().x >> log2ParallelMergeLevel)) && ((yBr >> log2ParallelMergeLevel) > (pu.cu->Y().y >> log2ParallelMergeLevel)); + bool enableInsertion = CU::isIBC(cu) || enableHmvp; + if (enableInsertion) +#endif cu.cs->addMiToLut(CU::isIBC(cu) ? cu.cs->motionLut.lutIbc : cu.cs->motionLut.lut, mi); } } @@ -744,7 +752,11 @@ void PU::getIBCMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const //left const PredictionUnit* puLeft = cs.getPURestricted(posLB.offset(-1, 0), pu, pu.chType); bool isGt4x4 = pu.lwidth() * pu.lheight() > 16; +#if JVET_Q0297_MER + const bool isAvailableA1 = puLeft && pu.cu != puLeft->cu && CU::isIBC(*puLeft->cu); +#else const bool isAvailableA1 = puLeft && isDiffMER(pu, *puLeft) && pu.cu != puLeft->cu && CU::isIBC(*puLeft->cu); +#endif if (isGt4x4 && isAvailableA1) { miLeft = puLeft->getMotionInfo(posLB.offset(-1, 0)); @@ -768,7 +780,11 @@ void PU::getIBCMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const // above const PredictionUnit *puAbove = cs.getPURestricted(posRT.offset(0, -1), pu, pu.chType); +#if JVET_Q0297_MER + bool isAvailableB1 = puAbove && pu.cu != puAbove->cu && CU::isIBC(*puAbove->cu); +#else bool isAvailableB1 = puAbove && isDiffMER(pu, *puAbove) && pu.cu != puAbove->cu && CU::isIBC(*puAbove->cu); +#endif if (isGt4x4 && isAvailableB1) { miAbove = puAbove->getMotionInfo(posRT.offset(0, -1)); @@ -1490,6 +1506,19 @@ bool PU::isDiffMER(const PredictionUnit &pu1, const PredictionUnit &pu2) const unsigned xP = pu2.lumaPos().x; const unsigned yP = pu2.lumaPos().y; +#if JVET_Q0297_MER + unsigned plevel = pu1.cs->sps->getLog2ParallelMergeLevelMinus2() + 2; + + if ((xN >> plevel) != (xP >> plevel)) + { + return true; + } + + if ((yN >> plevel) != (yP >> plevel)) + { + return true; +} +#else if ((xN >> 2) != (xP >> 2)) { return true; @@ -1499,6 +1528,7 @@ bool PU::isDiffMER(const PredictionUnit &pu1, const PredictionUnit &pu2) { return true; } +#endif return false; } @@ -2355,6 +2385,9 @@ const int getAvailableAffineNeighboursForLeftPredictor( const PredictionUnit &pu const PredictionUnit *puLeftBottom = pu.cs->getPURestricted( posLB.offset( -1, 1 ), pu, pu.chType ); if ( puLeftBottom && puLeftBottom->cu->affine && puLeftBottom->mergeType == MRG_TYPE_DEFAULT_N +#if JVET_Q0297_MER + && PU::isDiffMER(pu, *puLeftBottom) +#endif ) { npu[num++] = puLeftBottom; @@ -2364,6 +2397,9 @@ const int getAvailableAffineNeighboursForLeftPredictor( const PredictionUnit &pu const PredictionUnit* puLeft = pu.cs->getPURestricted( posLB.offset( -1, 0 ), pu, pu.chType ); if ( puLeft && puLeft->cu->affine && puLeft->mergeType == MRG_TYPE_DEFAULT_N +#if JVET_Q0297_MER + && PU::isDiffMER(pu, *puLeft) +#endif ) { npu[num++] = puLeft; @@ -2382,6 +2418,9 @@ const int getAvailableAffineNeighboursForAbovePredictor( const PredictionUnit &p const PredictionUnit* puAboveRight = pu.cs->getPURestricted( posRT.offset( 1, -1 ), pu, pu.chType ); if ( puAboveRight && puAboveRight->cu->affine && puAboveRight->mergeType == MRG_TYPE_DEFAULT_N +#if JVET_Q0297_MER + && PU::isDiffMER(pu, *puAboveRight) +#endif ) { npu[num++] = puAboveRight; @@ -2391,6 +2430,9 @@ const int getAvailableAffineNeighboursForAbovePredictor( const PredictionUnit &p const PredictionUnit* puAbove = pu.cs->getPURestricted( posRT.offset( 0, -1 ), pu, pu.chType ); if ( puAbove && puAbove->cu->affine && puAbove->mergeType == MRG_TYPE_DEFAULT_N +#if JVET_Q0297_MER + && PU::isDiffMER(pu, *puAbove) +#endif ) { npu[num++] = puAbove; @@ -2400,6 +2442,9 @@ const int getAvailableAffineNeighboursForAbovePredictor( const PredictionUnit &p const PredictionUnit *puAboveLeft = pu.cs->getPURestricted( posLT.offset( -1, -1 ), pu, pu.chType ); if ( puAboveLeft && puAboveLeft->cu->affine && puAboveLeft->mergeType == MRG_TYPE_DEFAULT_N +#if JVET_Q0297_MER + && PU::isDiffMER(pu, *puAboveLeft) +#endif ) { npu[num++] = puAboveLeft; @@ -2557,6 +2602,9 @@ void PU::getAffineMergeCand( const PredictionUnit &pu, AffineMergeCtx& affMrgCtx const PredictionUnit* puNeigh = cs.getPURestricted( pos, pu, pu.chType ); if ( puNeigh && CU::isInter( *puNeigh->cu ) +#if JVET_Q0297_MER + && PU::isDiffMER(pu, *puNeigh) +#endif ) { isAvailable[0] = true; @@ -2575,6 +2623,9 @@ void PU::getAffineMergeCand( const PredictionUnit &pu, AffineMergeCtx& affMrgCtx if ( puNeigh && CU::isInter( *puNeigh->cu ) +#if JVET_Q0297_MER + && PU::isDiffMER(pu, *puNeigh) +#endif ) { isAvailable[1] = true; @@ -2593,6 +2644,9 @@ void PU::getAffineMergeCand( const PredictionUnit &pu, AffineMergeCtx& affMrgCtx if ( puNeigh && CU::isInter( *puNeigh->cu ) +#if JVET_Q0297_MER + && PU::isDiffMER(pu, *puNeigh) +#endif ) { isAvailable[2] = true; diff --git a/source/Lib/DecoderLib/VLCReader.cpp b/source/Lib/DecoderLib/VLCReader.cpp index 015a5461e5e49b0e5cd94b8adf746deae1fb0c11..12034590cb41586fab518b9c1bc856adf0121626 100644 --- a/source/Lib/DecoderLib/VLCReader.cpp +++ b/source/Lib/DecoderLib/VLCReader.cpp @@ -1561,6 +1561,11 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS) } #endif +#if JVET_Q0297_MER + READ_UVLC(uiCode, "log2_parallel_merge_level_minus2"); + pcSPS->setLog2ParallelMergeLevelMinus2(uiCode); +#endif + // KJS: reference picture sets to be replaced // KJS: not found in draft -> does not exist diff --git a/source/Lib/EncoderLib/EncCfg.h b/source/Lib/EncoderLib/EncCfg.h index ceadd3249c16ec8c708fcb7c2a09004133c778b6..2ad77c7d656218b9b8ad503a02b40c8f3526a053 100644 --- a/source/Lib/EncoderLib/EncCfg.h +++ b/source/Lib/EncoderLib/EncCfg.h @@ -595,6 +595,9 @@ protected: bool m_useWeightedPred; //< Use of Weighting Prediction (P_SLICE) bool m_useWeightedBiPred; //< Use of Bi-directional Weighting Prediction (B_SLICE) WeightedPredictionMethod m_weightedPredictionMethod; +#if JVET_Q0297_MER + uint32_t m_log2ParallelMergeLevelMinus2; ///< Parallel merge estimation region +#endif uint32_t m_maxNumMergeCand; ///< Maximum number of merge candidates uint32_t m_maxNumAffineMergeCand; ///< Maximum number of affine merge candidates uint32_t m_maxNumTriangleCand; @@ -1592,6 +1595,10 @@ public: void setWPBiPred ( bool b ) { m_useWeightedBiPred = b; } bool getUseWP () { return m_useWeightedPred; } bool getWPBiPred () { return m_useWeightedBiPred; } +#if JVET_Q0297_MER + void setLog2ParallelMergeLevelMinus2(uint32_t u) { m_log2ParallelMergeLevelMinus2 = u; } + uint32_t getLog2ParallelMergeLevelMinus2() { return m_log2ParallelMergeLevelMinus2; } +#endif void setMaxNumMergeCand ( uint32_t u ) { m_maxNumMergeCand = u; } uint32_t getMaxNumMergeCand () { return m_maxNumMergeCand; } void setMaxNumAffineMergeCand ( uint32_t u ) { m_maxNumAffineMergeCand = u; } diff --git a/source/Lib/EncoderLib/EncLib.cpp b/source/Lib/EncoderLib/EncLib.cpp index 834b3e98b50f449ec6b38bd1f5b10fd8380e48c6..ce012c6701bde75ce6c7dc2dfcf4b7072f6b3ed8 100644 --- a/source/Lib/EncoderLib/EncLib.cpp +++ b/source/Lib/EncoderLib/EncLib.cpp @@ -1266,6 +1266,10 @@ void EncLib::xInitSPS( SPS& sps, VPS& vps ) } sps.setRprEnabledFlag( m_rprEnabled || sps.getInterLayerPresentFlag() ); + +#if JVET_Q0297_MER + sps.setLog2ParallelMergeLevelMinus2( m_log2ParallelMergeLevelMinus2 ); +#endif } void EncLib::xInitHrdParameters(SPS &sps) diff --git a/source/Lib/EncoderLib/EncModeCtrl.cpp b/source/Lib/EncoderLib/EncModeCtrl.cpp index 922835d58ac9ce7643923b6436c7b5e87d726262..833986d556bfcc41d0d55384bb98477efd857666 100644 --- a/source/Lib/EncoderLib/EncModeCtrl.cpp +++ b/source/Lib/EncoderLib/EncModeCtrl.cpp @@ -1830,6 +1830,20 @@ bool EncModeCtrlMTnoRQT::tryMode( const EncTestMode& encTestmode, const CodingSt } if( split == CU_QUAD_SPLIT ) cuECtx.set( DID_QUAD_SPLIT, true ); +#if JVET_Q0297_MER + if (cs.sps->getLog2ParallelMergeLevelMinus2()) + { + const CompArea& area = partitioner.currArea().Y(); + const SizeType size = 1 << (cs.sps->getLog2ParallelMergeLevelMinus2() + 2); + if (!cs.slice->isIntra() && (area.width > size || area.height > size)) + { + if (area.height <= size && split == CU_HORZ_SPLIT) return false; + if (area.width <= size && split == CU_VERT_SPLIT) return false; + if (area.height <= 2 * size && split == CU_TRIH_SPLIT) return false; + if (area.width <= 2 * size && split == CU_TRIV_SPLIT) return false; + } + } +#endif return true; } else diff --git a/source/Lib/EncoderLib/VLCWriter.cpp b/source/Lib/EncoderLib/VLCWriter.cpp index ab3cb102b9e66b9de389e7e644a998a66b298f40..425e1748505b4658603638234a300685d82abb42 100644 --- a/source/Lib/EncoderLib/VLCWriter.cpp +++ b/source/Lib/EncoderLib/VLCWriter.cpp @@ -1042,6 +1042,9 @@ void HLSWriter::codeSPS( const SPS* pcSPS ) } } #endif +#if JVET_Q0297_MER + WRITE_UVLC(pcSPS->getLog2ParallelMergeLevelMinus2(), "log2_parallel_merge_level_minus2"); +#endif // KJS: reference picture sets to be replaced