Commit 4076fc2f authored by Philippe de Lagrange's avatar Philippe de Lagrange

JVET-M0113/M0188 quantization groups based on area

parent b0411ca2
......@@ -26,7 +26,7 @@ FDM : 1 # Fast Decision for Merge RD cost
#======== Quantization =============
QP : 32 # Quantization parameter(0-51)
MaxDeltaQP : 0 # CU-based multi-QP optimization
MaxCuDQPDepth : 0 # Max depth of a minimum CuDQP for sub-LCU-level delta QP
MaxCuDQPSubdiv : 0 # Maximum subdiv for CU luma Qp adjustment
DeltaQpRD : 0 # Slice-based multi-QP optimization
RDOQ : 1 # RDOQ
RDOQTS : 1 # RDOQ for transform skip
......
......@@ -34,7 +34,7 @@ FDM : 1 # Fast Decision for Merge RD cost
#======== Quantization =============
QP : 32 # Quantization parameter(0-51)
MaxDeltaQP : 0 # CU-based multi-QP optimization
MaxCuDQPDepth : 0 # Max depth of a minimum CuDQP for sub-LCU-level delta QP
MaxCuDQPSubdiv : 0 # Maximum subdiv for CU luma Qp adjustment
DeltaQpRD : 0 # Slice-based multi-QP optimization
RDOQ : 1 # RDOQ
RDOQTS : 1 # RDOQ for transform skip
......
......@@ -34,7 +34,7 @@ FDM : 1 # Fast Decision for Merge RD cost
#======== Quantization =============
QP : 32 # Quantization parameter(0-51)
MaxDeltaQP : 0 # CU-based multi-QP optimization
MaxCuDQPDepth : 0 # Max depth of a minimum CuDQP for sub-LCU-level delta QP
MaxCuDQPSubdiv : 0 # Maximum subdiv for CU luma Qp adjustment
DeltaQpRD : 0 # Slice-based multi-QP optimization
RDOQ : 1 # RDOQ
RDOQTS : 1 # RDOQ for transform skip
......
......@@ -48,7 +48,7 @@ FDM : 1 # Fast Decision for Merge RD cost
#======== Quantization =============
QP : 32 # Quantization parameter(0-51)
MaxDeltaQP : 0 # CU-based multi-QP optimization
MaxCuDQPDepth : 0 # Max depth of a minimum CuDQP for sub-LCU-level delta QP
MaxCuDQPSubdiv : 0 # Maximum subdiv for CU luma Qp adjustment
DeltaQpRD : 0 # Slice-based multi-QP optimization
RDOQ : 1 # RDOQ
RDOQTS : 1 # RDOQ for transform skip
......
......@@ -216,8 +216,13 @@ void EncApp::xInitLibCfg()
//====== Quality control ========
m_cEncLib.setMaxDeltaQP ( m_iMaxDeltaQP );
#if JVET_M0113_M0188_QG_SIZE
m_cEncLib.setCuQpDeltaSubdiv ( m_cuQpDeltaSubdiv );
m_cEncLib.setCuChromaQpOffsetSubdiv ( m_cuChromaQpOffsetSubdiv );
#else
m_cEncLib.setMaxCuDQPDepth ( m_iMaxCuDQPDepth );
m_cEncLib.setDiffCuChromaQpOffsetDepth ( m_diffCuChromaQpOffsetDepth );
#endif
m_cEncLib.setChromaCbQpOffset ( m_cbQpOffset );
m_cEncLib.setChromaCrQpOffset ( m_crQpOffset );
m_cEncLib.setChromaCbQpOffsetDualTree ( m_cbQpOffsetDualTree );
......
......@@ -997,8 +997,13 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
#endif
("DeltaQpRD,-dqr", m_uiDeltaQpRD, 0u, "max dQp offset for slice")
("MaxDeltaQP,d", m_iMaxDeltaQP, 0, "max dQp offset for block")
#if JVET_M0113_M0188_QG_SIZE
("MaxCuDQPSubdiv,-dqd", m_cuQpDeltaSubdiv, 0, "Maximum subdiv for CU luma Qp adjustment")
("MaxCuChromaQpOffsetSubdiv", m_cuChromaQpOffsetSubdiv, -1, "Maximum subdiv for CU chroma Qp adjustment - set less than 0 to disable")
#else
("MaxCuDQPDepth,-dqd", m_iMaxCuDQPDepth, 0, "max depth for a minimum CuDQP")
("MaxCUChromaQpAdjustmentDepth", m_diffCuChromaQpOffsetDepth, -1, "Maximum depth for CU chroma Qp adjustment - set less than 0 to disable")
#endif
("FastDeltaQP", m_bFastDeltaQP, false, "Fast Delta QP Algorithm")
#if SHARP_LUMA_DELTA_QP
("LumaLevelToDeltaQPMode", lumaLevelToDeltaQPMode, 0u, "Luma based Delta QP 0(default): not used. 1: Based on CTU average, 2: Based on Max luma in CTU")
......@@ -1573,7 +1578,11 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
!m_enableIntraReferenceSmoothing ||
m_persistentRiceAdaptationEnabledFlag ||
m_log2MaxTransformSkipBlockSize!=2;
#if JVET_M0113_M0188_QG_SIZE
const bool bUsingChromaQPAdjustment= m_cuChromaQpOffsetSubdiv >= 0;
#else
const bool bUsingChromaQPAdjustment= m_diffCuChromaQpOffsetDepth >= 0;
#endif
const bool bUsingExtendedPrecision = m_extendedPrecisionProcessingFlag;
if (m_onePictureOnlyConstraintFlag)
{
......@@ -2121,7 +2130,11 @@ bool EncAppCfg::xCheckParameter()
!m_enableIntraReferenceSmoothing ||
m_persistentRiceAdaptationEnabledFlag ||
m_log2MaxTransformSkipBlockSize!=2;
#if JVET_M0113_M0188_QG_SIZE
const bool bUsingChromaQPTool = m_cuChromaQpOffsetSubdiv >= 0;
#else
const bool bUsingChromaQPTool = m_diffCuChromaQpOffsetDepth >= 0;
#endif
const bool bUsingExtendedPrecision = m_extendedPrecisionProcessingFlag;
xConfirmPara((m_chromaFormatConstraint==CHROMA_420 || m_chromaFormatConstraint==CHROMA_400) && bUsingChromaQPTool, "CU Chroma QP adjustment cannot be used for 4:0:0 or 4:2:0 RExt profiles");
......@@ -3088,7 +3101,11 @@ void EncAppCfg::xPrintParameter()
#else
msg( DETAILS, "QP : %5.2f\n", m_fQP );
#endif
#if JVET_M0113_M0188_QG_SIZE
msg( DETAILS, "Max dQP signaling subdiv : %d\n", m_cuQpDeltaSubdiv);
#else
msg( DETAILS, "Max dQP signaling depth : %d\n", m_iMaxCuDQPDepth);
#endif
msg( DETAILS, "Cb QP Offset (dual tree) : %d (%d)\n", m_cbQpOffset, m_cbQpOffsetDualTree);
msg( DETAILS, "Cr QP Offset (dual tree) : %d (%d)\n", m_crQpOffset, m_crQpOffsetDualTree);
......@@ -3100,7 +3117,11 @@ void EncAppCfg::xPrintParameter()
msg( DETAILS, "PCM sample bit depth : (Y:%d, C:%d)\n", m_bPCMInputBitDepthFlag ? m_MSBExtendedBitDepth[CHANNEL_TYPE_LUMA] : m_internalBitDepth[CHANNEL_TYPE_LUMA],
m_bPCMInputBitDepthFlag ? m_MSBExtendedBitDepth[CHANNEL_TYPE_CHROMA] : m_internalBitDepth[CHANNEL_TYPE_CHROMA] );
msg( DETAILS, "Intra reference smoothing : %s\n", (m_enableIntraReferenceSmoothing ? "Enabled" : "Disabled") );
#if JVET_M0113_M0188_QG_SIZE
msg( DETAILS, "cu_chroma_qp_offset_subdiv : %d\n", m_cuChromaQpOffsetSubdiv);
#else
msg( DETAILS, "diff_cu_chroma_qp_offset_depth : %d\n", m_diffCuChromaQpOffsetDepth);
#endif
msg( DETAILS, "extended_precision_processing_flag : %s\n", (m_extendedPrecisionProcessingFlag ? "Enabled" : "Disabled") );
msg( DETAILS, "implicit_rdpcm_enabled_flag : %s\n", (m_rdpcmEnabledFlag[RDPCM_SIGNAL_IMPLICIT] ? "Enabled" : "Disabled") );
msg( DETAILS, "explicit_rdpcm_enabled_flag : %s\n", (m_rdpcmEnabledFlag[RDPCM_SIGNAL_EXPLICIT] ? "Enabled" : "Disabled") );
......
......@@ -205,8 +205,13 @@ protected:
int* m_aidQP; ///< array of slice QP values
int m_iMaxDeltaQP; ///< max. |delta QP|
uint32_t m_uiDeltaQpRD; ///< dQP range for multi-pass slice QP optimization
#if JVET_M0113_M0188_QG_SIZE
int m_cuQpDeltaSubdiv; ///< Maximum subdiv for CU luma Qp adjustment (0:default)
int m_cuChromaQpOffsetSubdiv; ///< If negative, then do not apply chroma qp offsets.
#else
int m_iMaxCuDQPDepth; ///< Max. depth for a minimum CuDQPSize (0:default)
int m_diffCuChromaQpOffsetDepth; ///< If negative, then do not apply chroma qp offsets.
#endif
bool m_bFastDeltaQP; ///< Fast Delta QP (false:default)
int m_cbQpOffset; ///< Chroma Cb QP Offset (0:default)
......
......@@ -249,13 +249,22 @@ class CUCtx
{
public:
CUCtx() : isDQPCoded(false), isChromaQpAdjCoded(false),
#if JVET_M0113_M0188_QG_SIZE
qgStart(false),
#endif
numNonZeroCoeffNonTs(0) {}
CUCtx(int _qp) : isDQPCoded(false), isChromaQpAdjCoded(false),
#if JVET_M0113_M0188_QG_SIZE
qgStart(false),
#endif
numNonZeroCoeffNonTs(0), qp(_qp) {}
~CUCtx() {}
public:
bool isDQPCoded;
bool isChromaQpAdjCoded;
#if JVET_M0113_M0188_QG_SIZE
bool qgStart;
#endif
uint32_t numNonZeroCoeffNonTs;
int8_t qp; // used as a previous(last) QP and for QP prediction
};
......
......@@ -1879,7 +1879,11 @@ const int SPS::m_winUnitY[]={1,2,1,1};
PPSRExt::PPSRExt()
: m_log2MaxTransformSkipBlockSize (2)
, m_crossComponentPredictionEnabledFlag(false)
#if JVET_M0113_M0188_QG_SIZE
, m_cuChromaQpOffsetSubdiv (0)
#else
, m_diffCuChromaQpOffsetDepth (0)
#endif
, m_chromaQpOffsetListLen (0)
// m_ChromaQpAdjTableIncludingNullEntry initialized below
// m_log2SaoOffsetScale initialized below
......@@ -1899,7 +1903,11 @@ PPS::PPS()
, m_useDQP (false)
, m_bConstrainedIntraPred (false)
, m_bSliceChromaQpFlag (false)
#if JVET_M0113_M0188_QG_SIZE
, m_cuQpDeltaSubdiv (0)
#else
, m_uiMaxCuDQPDepth (0)
#endif
, m_chromaCbQpOffset (0)
, m_chromaCrQpOffset (0)
, m_numRefIdxL0DefaultActive (1)
......
......@@ -1330,7 +1330,11 @@ private:
bool m_crossComponentPredictionEnabledFlag;
// Chroma QP Adjustments
#if JVET_M0113_M0188_QG_SIZE
int m_cuChromaQpOffsetSubdiv;
#else
int m_diffCuChromaQpOffsetDepth;
#endif
int m_chromaQpOffsetListLen; // size (excludes the null entry used in the following array).
ChromaQpAdj m_ChromaQpAdjTableIncludingNullEntry[1+MAX_QP_OFFSET_LIST_SIZE]; //!< Array includes entry [0] for the null offset used when cu_chroma_qp_offset_flag=0, and entries [cu_chroma_qp_offset_idx+1...] otherwise
......@@ -1356,8 +1360,13 @@ public:
void clearChromaQpOffsetList() { m_chromaQpOffsetListLen = 0; }
#if JVET_M0113_M0188_QG_SIZE
uint32_t getCuChromaQpOffsetSubdiv () const { return m_cuChromaQpOffsetSubdiv; }
void setCuChromaQpOffsetSubdiv ( uint32_t u ) { m_cuChromaQpOffsetSubdiv = u; }
#else
uint32_t getDiffCuChromaQpOffsetDepth () const { return m_diffCuChromaQpOffsetDepth; }
void setDiffCuChromaQpOffsetDepth ( uint32_t u ) { m_diffCuChromaQpOffsetDepth = u; }
#endif
bool getChromaQpOffsetListEnabledFlag() const { return getChromaQpOffsetListLen()>0; }
int getChromaQpOffsetListLen() const { return m_chromaQpOffsetListLen; }
......@@ -1395,7 +1404,11 @@ private:
bool m_bSliceChromaQpFlag; // slicelevel_chroma_qp_flag
// access channel
uint32_t m_uiMaxCuDQPDepth;
#if JVET_M0113_M0188_QG_SIZE
uint32_t m_cuQpDeltaSubdiv; // cu_qp_delta_subdiv
#else
uint32_t m_uiMaxCuDQPDepth;
#endif
int m_chromaCbQpOffset;
int m_chromaCrQpOffset;
......@@ -1463,8 +1476,13 @@ public:
bool getSliceChromaQpFlag() const { return m_bSliceChromaQpFlag; }
void setSliceChromaQpFlag( bool b ) { m_bSliceChromaQpFlag = b; }
#if JVET_M0113_M0188_QG_SIZE
void setCuQpDeltaSubdiv( uint32_t u ) { m_cuQpDeltaSubdiv = u; }
uint32_t getCuQpDeltaSubdiv() const { return m_cuQpDeltaSubdiv; }
#else
void setMaxCuDQPDepth( uint32_t u ) { m_uiMaxCuDQPDepth = u; }
uint32_t getMaxCuDQPDepth() const { return m_uiMaxCuDQPDepth; }
#endif
void setQpOffset(ComponentID compID, int i )
{
......
......@@ -372,6 +372,7 @@ typedef std::pair<int, int> TrCost;
#define ER_CHROMA_QP_WCG_PPS 1 ///< Chroma QP model for WCG used in Anchor 3.2
#define ENABLE_QPA 1 ///< Non-normative perceptual QP adaptation according to JVET-H0047 and JVET-K0206. Deactivated by default, activated using encoder arguments --PerceptQPA=1 --SliceChromaQPOffsetPeriodicity=1
#define ENABLE_QPA_SUB_CTU ( 1 && ENABLE_QPA ) ///< when maximum delta-QP depth is greater than zero, use sub-CTU QPA
#define JVET_M0113_M0188_QG_SIZE 1 ///< JVET-M0113/M0188 quantization groups based on area
#define RDOQ_CHROMA 1 ///< use of RDOQ in chroma
......
......@@ -53,6 +53,10 @@ PartLevel::PartLevel()
, implicitSplit ( CU_DONT_SPLIT )
, firstSubPartSplit ( CU_DONT_SPLIT )
, canQtSplit ( true )
#if JVET_M0113_M0188_QG_SIZE
, qgEnable ( true )
, qgChromaEnable ( true )
#endif
{
}
......@@ -65,6 +69,10 @@ PartLevel::PartLevel( const PartSplit _split, const Partitioning& _parts )
, implicitSplit ( CU_DONT_SPLIT )
, firstSubPartSplit ( CU_DONT_SPLIT )
, canQtSplit ( true )
#if JVET_M0113_M0188_QG_SIZE
, qgEnable ( true )
, qgChromaEnable ( true )
#endif
{
}
......@@ -77,6 +85,10 @@ PartLevel::PartLevel( const PartSplit _split, Partitioning&& _parts )
, implicitSplit ( CU_DONT_SPLIT )
, firstSubPartSplit ( CU_DONT_SPLIT )
, canQtSplit ( true )
#if JVET_M0113_M0188_QG_SIZE
, qgEnable ( true )
, qgChromaEnable ( true )
#endif
{
}
......@@ -117,6 +129,9 @@ void Partitioner::copyState( const Partitioner& other )
currDepth = other.currDepth;
currMtDepth = other.currMtDepth;
currTrDepth = other.currTrDepth;
#if JVET_M0113_M0188_QG_SIZE
currSubdiv = other.currSubdiv;
#endif
currImplicitBtDepth
= other.currImplicitBtDepth;
chType = other.chType;
......@@ -224,6 +239,9 @@ void QTBTPartitioner::initCtu( const UnitArea& ctuArea, const ChannelType _chTyp
currBtDepth = 0;
currMtDepth = 0;
currQtDepth = 0;
#if JVET_M0113_M0188_QG_SIZE
currSubdiv = 0;
#endif
currImplicitBtDepth = 0;
chType = _chType;
......@@ -237,6 +255,10 @@ void QTBTPartitioner::splitCurrArea( const PartSplit split, const CodingStructur
bool isImplicit = isSplitImplicit( split, cs );
bool canQtSplit = canSplit( CU_QUAD_SPLIT, cs );
#if JVET_M0113_M0188_QG_SIZE
bool qgEnable = currQgEnable();
bool qgChromaEnable = currQgChromaEnable();
#endif
switch( split )
{
......@@ -272,6 +294,9 @@ void QTBTPartitioner::splitCurrArea( const PartSplit split, const CodingStructur
}
currDepth++;
#if JVET_M0113_M0188_QG_SIZE
currSubdiv++;
#endif
#if _DEBUG
m_currArea = m_partStack.back().parts.front();
#endif
......@@ -301,6 +326,9 @@ void QTBTPartitioner::splitCurrArea( const PartSplit split, const CodingStructur
{
// first and last part of triple split are equivalent to double bt split
currBtDepth++;
#if JVET_M0113_M0188_QG_SIZE
currSubdiv++;
#endif
}
m_partStack.back().canQtSplit = canQtSplit;
}
......@@ -311,7 +339,14 @@ void QTBTPartitioner::splitCurrArea( const PartSplit split, const CodingStructur
currMtDepth = 0;
currBtDepth = 0;
currQtDepth++;
#if JVET_M0113_M0188_QG_SIZE
currSubdiv++;
#endif
}
#if JVET_M0113_M0188_QG_SIZE
m_partStack.back().qgEnable = qgEnable && (currSubdiv <= cs.pps->getCuQpDeltaSubdiv());
m_partStack.back().qgChromaEnable = qgChromaEnable && (currSubdiv <= cs.pps->getPpsRangeExtension().getCuChromaQpOffsetSubdiv());
#endif
}
#if JVET_M0421_SPLIT_SIG
......@@ -630,6 +665,9 @@ void QTBTPartitioner::exitCurrSplit()
CHECK( currDepth == 0, "depth is '0', although a split was performed" );
currDepth--;
#if JVET_M0113_M0188_QG_SIZE
currSubdiv--;
#endif
#if _DEBUG
m_currArea = m_partStack.back().parts[m_partStack.back().idx];
#endif
......@@ -646,6 +684,9 @@ void QTBTPartitioner::exitCurrSplit()
{
CHECK( currBtDepth == 0, "BT depth is '0', athough a TT split was performed" );
currBtDepth--;
#if JVET_M0113_M0188_QG_SIZE
currSubdiv--;
#endif
}
}
else if( currSplit == TU_MAX_TR_SPLIT )
......@@ -666,6 +707,9 @@ void QTBTPartitioner::exitCurrSplit()
CHECK( currQtDepth == 0, "QT depth is '0', although a QT split was performed" );
currQtDepth--;
#if JVET_M0113_M0188_QG_SIZE
currSubdiv--;
#endif
}
}
......@@ -691,6 +735,10 @@ bool QTBTPartitioner::nextPart( const CodingStructure &cs, bool autoPop /*= fals
// adapt the current bt depth
if( currIdx == 1 ) currBtDepth--;
else currBtDepth++;
#if JVET_M0113_M0188_QG_SIZE
if( currIdx == 1 ) currSubdiv--;
else currSubdiv++;
#endif
}
#if _DEBUG
m_currArea = m_partStack.back().parts[currIdx];
......
......@@ -100,6 +100,10 @@ struct PartLevel
PartSplit implicitSplit;
PartSplit firstSubPartSplit;
bool canQtSplit;
#if JVET_M0113_M0188_QG_SIZE
bool qgEnable;
bool qgChromaEnable;
#endif
PartLevel();
PartLevel( const PartSplit _split, const Partitioning& _parts );
......@@ -123,6 +127,9 @@ public:
unsigned currTrDepth;
unsigned currBtDepth;
unsigned currMtDepth;
#if JVET_M0113_M0188_QG_SIZE
unsigned currSubdiv;
#endif
unsigned currImplicitBtDepth;
ChannelType chType;
......@@ -133,6 +140,10 @@ public:
const UnitArea& currArea () const { return currPartLevel().parts[currPartIdx()]; }
const unsigned currPartIdx () const { return currPartLevel().idx; }
const PartitioningStack& getPartStack () const { return m_partStack; }
#if JVET_M0113_M0188_QG_SIZE
const bool currQgEnable () const { return currPartLevel().qgEnable; }
const bool currQgChromaEnable () const { return currPartLevel().qgChromaEnable; }
#endif
SplitSeries getSplitSeries () const;
......
......@@ -196,6 +196,7 @@ int CU::predictQP( const CodingUnit& cu, const int prevQP )
return ( a + b + 1 ) >> 1;
}
#if !JVET_M0113_M0188_QG_SIZE
bool CU::isQGStart( const CodingUnit& cu, Partitioner& partitioner )
{
int maxDqpDepth = cu.slice->getPPS()->getMaxCuDQPDepth();
......@@ -211,6 +212,7 @@ bool CU::isQGStart( const CodingUnit& cu, Partitioner& partitioner )
else
return true;
}
#endif
uint32_t CU::getNumPUs( const CodingUnit& cu )
{
......
......@@ -77,7 +77,9 @@ namespace CU
uint32_t getCtuAddr (const CodingUnit &cu);
int predictQP (const CodingUnit& cu, const int prevQP );
#if !JVET_M0113_M0188_QG_SIZE
bool isQGStart (const CodingUnit& cu, Partitioner& partitioner ); // check if start of a Quantization Group
#endif
uint32_t getNumPUs (const CodingUnit& cu);
void addPUs ( CodingUnit& cu);
......
......@@ -385,11 +385,20 @@ bool CABACReader::coding_tree( CodingStructure& cs, Partitioner& partitioner, CU
bool lastSegment = false;
// Reset delta QP coding flag and ChromaQPAdjustemt coding flag
#if JVET_M0113_M0188_QG_SIZE
if( pps.getUseDQP() && partitioner.currQgEnable() )
{
cuCtx.qgStart = true;
cuCtx.isDQPCoded = false;
}
if( cs.slice->getUseChromaQpAdj() && partitioner.currQgChromaEnable() )
#else
if( pps.getUseDQP() && partitioner.currDepth <= pps.getMaxCuDQPDepth() )
{
cuCtx.isDQPCoded = false;
}
if( cs.slice->getUseChromaQpAdj() && partitioner.currDepth <= pps.getPpsRangeExtension().getDiffCuChromaQpOffsetDepth() )
#endif
{
cuCtx.isChromaQpAdjCoded = false;
}
......@@ -397,12 +406,20 @@ bool CABACReader::coding_tree( CodingStructure& cs, Partitioner& partitioner, CU
// Reset delta QP coding flag and ChromaQPAdjustemt coding flag
if (CS::isDualITree(cs) && pPartitionerChroma != nullptr)
{
#if JVET_M0113_M0188_QG_SIZE
if (pps.getUseDQP() && pPartitionerChroma->currQgEnable())
{
pCuCtxChroma->qgStart = true;
pCuCtxChroma->isDQPCoded = false;
}
if (cs.slice->getUseChromaQpAdj() && pPartitionerChroma->currQgChromaEnable())
#else
if (pps.getUseDQP() && pPartitionerChroma->currDepth <= pps.getMaxCuDQPDepth())
{
pCuCtxChroma->isDQPCoded = false;
}
if (cs.slice->getUseChromaQpAdj() && pPartitionerChroma->currDepth <= pps.getPpsRangeExtension().getDiffCuChromaQpOffsetDepth())
#endif
{
pCuCtxChroma->isChromaQpAdjCoded = false;
}
......@@ -638,8 +655,14 @@ bool CABACReader::coding_tree( CodingStructure& cs, Partitioner& partitioner, CU
#endif
// Predict QP on start of quantization group
#if JVET_M0113_M0188_QG_SIZE
if( cuCtx.qgStart )
{
cuCtx.qgStart = false;
#else
if( pps.getUseDQP() && !cuCtx.isDQPCoded && CU::isQGStart( cu, partitioner ) )
{
#endif
cuCtx.qp = CU::predictQP( cu, cuCtx.qp );
}
......
......@@ -413,12 +413,21 @@ void HLSyntaxReader::parsePPS( PPS* pcPPS )
READ_FLAG( uiCode, "cu_qp_delta_enabled_flag" ); pcPPS->setUseDQP( uiCode ? true : false );
if( pcPPS->getUseDQP() )
{
#if JVET_M0113_M0188_QG_SIZE
READ_UVLC( uiCode, "cu_qp_delta_subdiv" );
pcPPS->setCuQpDeltaSubdiv( uiCode );
#else
READ_UVLC( uiCode, "diff_cu_qp_delta_depth" );
pcPPS->setMaxCuDQPDepth( uiCode );
#endif
}
else
{
#if JVET_M0113_M0188_QG_SIZE
pcPPS->setCuQpDeltaSubdiv( 0 );
#else
pcPPS->setMaxCuDQPDepth( 0 );
#endif
}
READ_SVLC( iCode, "pps_cb_qp_offset");
pcPPS->setQpOffset(COMPONENT_Cb, iCode);
......@@ -561,11 +570,19 @@ void HLSyntaxReader::parsePPS( PPS* pcPPS )
if (uiCode == 0)
{
ppsRangeExtension.clearChromaQpOffsetList();
#if JVET_M0113_M0188_QG_SIZE
ppsRangeExtension.setCuChromaQpOffsetSubdiv(0);
#else
ppsRangeExtension.setDiffCuChromaQpOffsetDepth(0);
#endif
}
else
{
#if JVET_M0113_M0188_QG_SIZE
READ_UVLC(uiCode, "cu_chroma_qp_offset_subdiv"); ppsRangeExtension.setCuChromaQpOffsetSubdiv(uiCode);
#else
READ_UVLC(uiCode, "diff_cu_chroma_qp_offset_depth"); ppsRangeExtension.setDiffCuChromaQpOffsetDepth(uiCode);
#endif
uint32_t tableSizeMinus1 = 0;
READ_UVLC(tableSizeMinus1, "chroma_qp_offset_list_len_minus1");
CHECK(tableSizeMinus1 >= MAX_QP_OFFSET_LIST_SIZE, "Table size exceeds maximum");
......
......@@ -375,22 +375,40 @@ void CABACWriter::coding_tree(const CodingStructure& cs, Partitioner& partitione
const CodingUnit &cu = *cs.getCU( currArea.blocks[partitioner.chType], partitioner.chType );
// Reset delta QP coding flag and ChromaQPAdjustemt coding flag
#if JVET_M0113_M0188_QG_SIZE
if( pps.getUseDQP() && partitioner.currQgEnable() )
{
cuCtx.qgStart = true;
cuCtx.isDQPCoded = false;
}
if( cs.slice->getUseChromaQpAdj() && partitioner.currQgChromaEnable() )
#else
if( pps.getUseDQP() && partitioner.currDepth <= pps.getMaxCuDQPDepth() )
{
cuCtx.isDQPCoded = false;
}
if( cs.slice->getUseChromaQpAdj() && partitioner.currDepth <= pps.getPpsRangeExtension().getDiffCuChromaQpOffsetDepth() )
#endif
{
cuCtx.isChromaQpAdjCoded = false;
}
// Reset delta QP coding flag and ChromaQPAdjustemt coding flag
if (CS::isDualITree(cs) && pPartitionerChroma != nullptr)
{
#if JVET_M0113_M0188_QG_SIZE
if (pps.getUseDQP() && pPartitionerChroma->currQgEnable())
{
pCuCtxChroma->qgStart = true;
pCuCtxChroma->isDQPCoded = false;
}
if (cs.slice->getUseChromaQpAdj() && pPartitionerChroma->currQgChromaEnable())
#else
if (pps.getUseDQP() && pPartitionerChroma->currDepth <= pps.getMaxCuDQPDepth())
{
pCuCtxChroma->isDQPCoded = false;
}
if (cs.slice->getUseChromaQpAdj() && pPartitionerChroma->currDepth <= pps.getPpsRangeExtension().getDiffCuChromaQpOffsetDepth())
#endif
{
pCuCtxChroma->isChromaQpAdjCoded = false;
}
......@@ -521,8 +539,14 @@ void CABACWriter::coding_tree(const CodingStructure& cs, Partitioner& partitione
#endif
// Predict QP on start of quantization group
#if JVET_M0113_M0188_QG_SIZE
if( cuCtx.qgStart )
{
cuCtx.qgStart = false;
#else
if( pps.getUseDQP() && !cuCtx.isDQPCoded && CU::isQGStart( cu, partitioner ) )
{
#endif
cuCtx.qp = CU::predictQP( cu, cuCtx.qp );
}
......
......@@ -335,8 +335,13 @@ protected:
//====== Quality control ========
int m_iMaxDeltaQP; // Max. absolute delta QP (1:default)
#if JVET_M0113_M0188_QG_SIZE
int m_cuQpDeltaSubdiv; // Max. subdivision level for a CuDQP (0:default)
int m_cuChromaQpOffsetSubdiv; ///< If negative, then do not apply chroma qp offsets.
#else
int m_iMaxCuDQPDepth; // Max. depth for a minimum CuDQP (0:default)
int m_diffCuChromaQpOffsetDepth; ///< If negative, then do not apply chroma qp offsets.
#endif
int m_chromaCbQpOffset; // Chroma Cb QP Offset (0:default)
int m_chromaCrQpOffset; // Chroma Cr Qp Offset (0:default)
......@@ -923,10 +928,16 @@ public:
//====== Quality control ========
void setMaxDeltaQP ( int i ) { m_iMaxDeltaQP = i; }
#if JVET_M0113_M0188_QG_SIZE
void setCuQpDeltaSubdiv ( int i ) { m_cuQpDeltaSubdiv = i; }
int getCuChromaQpOffsetSubdiv () const { return m_cuChromaQpOffsetSubdiv; }
void setCuChromaQpOffsetSubdiv (int value) { m_cuChromaQpOffsetSubdiv = value; }
#else
void setMaxCuDQPDepth ( int i ) { m_iMaxCuDQPDepth = i; }
int getDiffCuChromaQpOffsetDepth () const { return m_diffCuChromaQpOffsetDepth; }
void setDiffCuChromaQpOffsetDepth (int value) { m_diffCuChromaQpOffsetDepth = value; }
#endif
void setChromaCbQpOffset ( int i ) { m_chromaCbQpOffset = i; }
void setChromaCrQpOffset ( int i ) { m_chromaCrQpOffset = i; }
......@@ -1030,7 +1041,11 @@ public:
//==== Quality control ========
int getMaxDeltaQP () const { return m_iMaxDeltaQP; }
#if JVET_M0113_M0188_QG_SIZE
int getCuQpDeltaSubdiv () const { return m_cuQpDeltaSubdiv; }
#else
int getMaxCuDQPDepth () const { return m_iMaxCuDQPDepth; }
#endif
bool getUseAdaptiveQP () const { return m_bUseAdaptiveQP; }
int getQPAdaptationRange () const { return m_iQPAdaptationRange; }
#if ENABLE_QPA
......
......@@ -668,8 +668,14 @@ void EncCu::xCompressCU( CodingStructure *&tempCS, CodingStructure *&bestCS, Par
if( slice.getUseChromaQpAdj() )
{
#if JVET_M0113_M0188_QG_SIZE
// TODO M0133 : double check encoder decisions with respect to chroma QG detection and actual encode
int lgMinCuSize = sps.getLog2MinCodingBlockSize() +
std::max<int>( 0, sps.getLog2DiffMaxMinCodingBlockSize() - int( pps.getPpsRangeExtension().getCuChromaQpOffsetSubdiv()/2 ) );
#else
int lgMinCuSize = sps.getLog2MinCodingBlockSize() +
std::max<int>( 0, sps.getLog2DiffMaxMinCodingBlockSize() - int( pps.getPpsRangeExtension().getDiffCuChromaQpOffsetDepth() ) );
#endif
m_cuChromaQpOffsetIdxPlus1 = ( ( uiLPelX >> lgMinCuSize ) + ( uiTPelY >> lgMinCuSize ) ) % ( pps.getPpsRangeExtension().getChromaQpOffsetListLen() + 1 );
}
......@@ -711,7 +717,11 @@ void EncCu::xCompressCU( CodingStructure *&tempCS, CodingStructure *&bestCS, Par
}
#if SHARP_LUMA_DELTA_QP || ENABLE_QPA_SUB_CTU
#if JVET_M0113_M0188_QG_SIZE
if (partitioner.currQgEnable() && (
#else
if (partitioner.currDepth <= pps.getMaxCuDQPDepth() && (
#endif
#if SHARP_LUMA_DELTA_QP
(m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled()) ||
#endif
......@@ -1127,12 +1137,14 @@ void EncCu::copyState( EncCu* other, Partitioner& partitioner, const UnitArea& c
void EncCu::xCheckModeSplit(CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode )
{
const int qp = encTestMode.qp;
const PPS &pps = *tempCS->pps;
const Slice &slice = *tempCS->slice;
const bool bIsLosslessMode = false; // False at this level. Next level down may set it to true.
const int oldPrevQp = tempCS->prevQP[partitioner.chType];
const auto oldMotionLut = tempCS->motionLut;
const uint32_t currDepth = partitioner.currDepth;
#if !JVET_M0113_M0188_QG_SIZE
const PPS &pps = *tempCS->pps;
const uint32_t currDepth = partitioner.currDepth;
#endif
const PartSplit split = getPartSplit( encTestMode );
......@@ -1253,6 +1265,9 @@ void EncCu::xCheckModeSplit(CodingStructure *&tempCS, CodingStructure *&bestCS,
#endif
partitioner.splitCurrArea( split, *tempCS );
#if JVET_M0113_M0188_QG_SIZE
bool qgEnableChildren = partitioner.currQgEnable(); // QG possible at children level
#endif
m_CurrCtx++;
......@@ -1308,7 +1323,11 @@ void EncCu::xCheckModeSplit(CodingStructure *&tempCS, CodingStructure *&bestCS,
bool keepResi = KEEP_PRED_AND_RESI_SIGNALS;
tempCS->useSubStructure( *bestSubCS, partitioner.chType, CS::getArea( *tempCS, subCUArea, partitioner.chType ), KEEP_PRED_AND_RESI_SIGNALS, true, keepResi, keepResi );
#if JVET_M0113_M0188_QG_SIZE
if( partitioner.currQgEnable() )
#else
if(currDepth < pps.getMaxCuDQPDepth())
#endif
{
tempCS->prevQP[partitioner.chType] = bestSubCS->prevQP[partitioner.chType];
}
......@@ -1381,6 +1400,9 @@ void EncCu::xCheckModeSplit(CodingStructure *&tempCS, CodingStructure *&bestCS,
tempCS->cost = m_pcRdCost->calcRdCost( tempCS->fracBits, tempCS->dist );
// Check Delta QP bits for splitted structure
#if JVET_M0113_M0188_QG_SIZE
if( !qgEnableChildren ) // check at deepest QG level only
#endif
xCheckDQP( *tempCS, partitioner, true );
// If the configuration being tested exceeds the maximum number of bytes for a slice / slice-segment, then
......@@ -1772,15 +1794,23 @@ void EncCu::xCheckDQP( CodingStructure& cs, Partitioner& partitioner, bool bKeep
return;
}
#if JVET_M0113_M0188_QG_SIZE
if( !partitioner.currQgEnable() ) // do not consider split or leaf/not leaf QG condition (checked by caller)
#else
// partitioner.currDepth != cs.pps->getMaxCuDQPDepth() means we are not at leaf QG level (condition needed to call predictQP only once per QG)
if( bKeepCtx && partitioner.currDepth != cs.pps->getMaxCuDQPDepth() )
#endif
{
return;
}
#if !JVET_M0113_M0188_QG_SIZE
// not split or implicit, and deeper than QG (never happens with JVET_M0113_M0188_QG_SIZE)
if( !bKeepCtx && partitioner.currDepth > cs.pps->getMaxCuDQPDepth() )
{
return;
}