Commit 0ff7b781 authored by Jani Lainema's avatar Jani Lainema
Browse files

JVET-N0054: Joint chroma residual mode

parent 987cb4bd
...@@ -202,6 +202,10 @@ void EncApp::xInitLibCfg() ...@@ -202,6 +202,10 @@ void EncApp::xInitLibCfg()
m_cEncLib.setChromaCrQpOffset ( m_crQpOffset ); m_cEncLib.setChromaCrQpOffset ( m_crQpOffset );
m_cEncLib.setChromaCbQpOffsetDualTree ( m_cbQpOffsetDualTree ); m_cEncLib.setChromaCbQpOffsetDualTree ( m_cbQpOffsetDualTree );
m_cEncLib.setChromaCrQpOffsetDualTree ( m_crQpOffsetDualTree ); m_cEncLib.setChromaCrQpOffsetDualTree ( m_crQpOffsetDualTree );
#if JVET_N0054_JOINT_CHROMA
m_cEncLib.setChromaCbCrQpOffset ( m_cbCrQpOffset );
m_cEncLib.setChromaCbCrQpOffsetDualTree ( m_cbCrQpOffsetDualTree );
#endif
#if ER_CHROMA_QP_WCG_PPS #if ER_CHROMA_QP_WCG_PPS
m_cEncLib.setWCGChromaQpControl ( m_wcgChromaQpControl ); m_cEncLib.setWCGChromaQpControl ( m_wcgChromaQpControl );
#endif #endif
......
...@@ -979,6 +979,10 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) ...@@ -979,6 +979,10 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
("CrQpOffset,-crqpofs", m_crQpOffset, 0, "Chroma Cr QP Offset") ("CrQpOffset,-crqpofs", m_crQpOffset, 0, "Chroma Cr QP Offset")
("CbQpOffsetDualTree", m_cbQpOffsetDualTree, 0, "Chroma Cb QP Offset for dual tree") ("CbQpOffsetDualTree", m_cbQpOffsetDualTree, 0, "Chroma Cb QP Offset for dual tree")
("CrQpOffsetDualTree", m_crQpOffsetDualTree, 0, "Chroma Cr QP Offset for dual tree") ("CrQpOffsetDualTree", m_crQpOffsetDualTree, 0, "Chroma Cr QP Offset for dual tree")
#if JVET_N0054_JOINT_CHROMA
("CbCrQpOffset,-cbcrqpofs", m_cbCrQpOffset, -1, "QP Offset for joint Cr-Cr mode")
("CbCrQpOffsetDualTree", m_cbCrQpOffsetDualTree, 0, "QP Offset for joint Cr-Cr mode in dual tree")
#endif
#if ER_CHROMA_QP_WCG_PPS #if ER_CHROMA_QP_WCG_PPS
("WCGPPSEnable", m_wcgChromaQpControl.enabled, false, "1: Enable the WCG PPS chroma modulation scheme. 0 (default) disabled") ("WCGPPSEnable", m_wcgChromaQpControl.enabled, false, "1: Enable the WCG PPS chroma modulation scheme. 0 (default) disabled")
("WCGPPSCbQpScale", m_wcgChromaQpControl.chromaCbQpScale, 1.0, "WCG PPS Chroma Cb QP Scale") ("WCGPPSCbQpScale", m_wcgChromaQpControl.chromaCbQpScale, 1.0, "WCG PPS Chroma Cb QP Scale")
...@@ -2258,6 +2262,12 @@ bool EncAppCfg::xCheckParameter() ...@@ -2258,6 +2262,12 @@ bool EncAppCfg::xCheckParameter()
xConfirmPara( m_cbQpOffsetDualTree > 12, "Max. Chroma Cb QP Offset for dual tree is 12" ); xConfirmPara( m_cbQpOffsetDualTree > 12, "Max. Chroma Cb QP Offset for dual tree is 12" );
xConfirmPara( m_crQpOffsetDualTree < -12, "Min. Chroma Cr QP Offset for dual tree is -12" ); xConfirmPara( m_crQpOffsetDualTree < -12, "Min. Chroma Cr QP Offset for dual tree is -12" );
xConfirmPara( m_crQpOffsetDualTree > 12, "Max. Chroma Cr QP Offset for dual tree is 12" ); xConfirmPara( m_crQpOffsetDualTree > 12, "Max. Chroma Cr QP Offset for dual tree is 12" );
#if JVET_N0054_JOINT_CHROMA
xConfirmPara( m_cbCrQpOffset < -12, "Min. Joint Cb-Cr QP Offset is -12" );
xConfirmPara( m_cbCrQpOffset > 12, "Max. Joint Cb-Cr QP Offset is 12" );
xConfirmPara( m_cbCrQpOffsetDualTree < -12, "Min. Joint Cb-Cr QP Offset for dual tree is -12" );
xConfirmPara( m_cbCrQpOffsetDualTree > 12, "Max. Joint Cb-Cr QP Offset for dual tree is 12" );
#endif
xConfirmPara( m_iQPAdaptationRange <= 0, "QP Adaptation Range must be more than 0" ); xConfirmPara( m_iQPAdaptationRange <= 0, "QP Adaptation Range must be more than 0" );
if (m_iDecodingRefreshType == 2) if (m_iDecodingRefreshType == 2)
......
...@@ -203,6 +203,10 @@ protected: ...@@ -203,6 +203,10 @@ protected:
int m_crQpOffset; ///< Chroma Cr QP Offset (0:default) int m_crQpOffset; ///< Chroma Cr QP Offset (0:default)
int m_cbQpOffsetDualTree; ///< Chroma Cb QP Offset for dual tree (overwrite m_cbQpOffset for dual tree) int m_cbQpOffsetDualTree; ///< Chroma Cb QP Offset for dual tree (overwrite m_cbQpOffset for dual tree)
int m_crQpOffsetDualTree; ///< Chroma Cr QP Offset for dual tree (overwrite m_crQpOffset for dual tree) int m_crQpOffsetDualTree; ///< Chroma Cr QP Offset for dual tree (overwrite m_crQpOffset for dual tree)
#if JVET_N0054_JOINT_CHROMA
int m_cbCrQpOffset; ///< QP Offset for joint Cb-Cr mode
int m_cbCrQpOffsetDualTree; ///< QP Offset for joint Cb-Cr mode (overwrite m_cbCrQpOffset for dual tree)
#endif
#if ER_CHROMA_QP_WCG_PPS #if ER_CHROMA_QP_WCG_PPS
WCGChromaQPControl m_wcgChromaQpControl; ///< Wide-colour-gamut chroma QP control. WCGChromaQPControl m_wcgChromaQpControl; ///< Wide-colour-gamut chroma QP control.
#endif #endif
......
...@@ -116,6 +116,10 @@ struct AreaBuf : public Size ...@@ -116,6 +116,10 @@ struct AreaBuf : public Size
void copyClip ( const AreaBuf<const T> &src, const ClpRng& clpRng); void copyClip ( const AreaBuf<const T> &src, const ClpRng& clpRng);
void subtract ( const AreaBuf<const T> &other ); void subtract ( const AreaBuf<const T> &other );
#if JVET_N0054_JOINT_CHROMA
void copyAndNegate ( const AreaBuf<const T> &other );
void subtractAndHalve ( const AreaBuf<const T> &other );
#endif
void extendSingleBorderPel(); void extendSingleBorderPel();
void extendBorderPel ( unsigned margin ); void extendBorderPel ( unsigned margin );
void addWeightedAvg ( const AreaBuf<const T> &other1, const AreaBuf<const T> &other2, const ClpRng& clpRng, const int8_t gbiIdx); void addWeightedAvg ( const AreaBuf<const T> &other1, const AreaBuf<const T> &other2, const ClpRng& clpRng, const int8_t gbiIdx);
...@@ -360,6 +364,50 @@ void AreaBuf<T>::subtract( const AreaBuf<const T> &other ) ...@@ -360,6 +364,50 @@ void AreaBuf<T>::subtract( const AreaBuf<const T> &other )
#undef SUBS_INC #undef SUBS_INC
} }
#if JVET_N0054_JOINT_CHROMA
template<typename T>
void AreaBuf<T>::copyAndNegate( const AreaBuf<const T> &other )
{
CHECK( width != other.width, "Incompatible size" );
CHECK( height != other.height, "Incompatible size" );
T* dest = buf;
const T* subs = other.buf;
#define SUBS_INC \
dest += stride; \
subs += other.stride; \
#define SUBS_OP( ADDR ) dest[ADDR] = -subs[ADDR]
SIZE_AWARE_PER_EL_OP( SUBS_OP, SUBS_INC );
#undef SUBS_OP
#undef SUBS_INC
}
template<typename T>
void AreaBuf<T>::subtractAndHalve( const AreaBuf<const T> &other )
{
CHECK( width != other.width, "Incompatible size" );
CHECK( height != other.height, "Incompatible size" );
T* dest = buf;
const T* subs = other.buf;
#define SUBS_INC \
dest += stride; \
subs += other.stride; \
#define SUBS_OP( ADDR ) dest[ADDR] = ( dest[ADDR] - subs[ADDR] ) / 2
SIZE_AWARE_PER_EL_OP( SUBS_OP, SUBS_INC );
#undef SUBS_OP
#undef SUBS_INC
}
#endif
template<typename T> template<typename T>
void AreaBuf<T>::copyClip( const AreaBuf<const T> &src, const ClpRng& clpRng ) void AreaBuf<T>::copyClip( const AreaBuf<const T> &src, const ClpRng& clpRng )
{ {
......
...@@ -771,6 +771,16 @@ const CtxSet ContextSetCfg::IBCFlag = ContextSetCfg::addCtxSet ...@@ -771,6 +771,16 @@ const CtxSet ContextSetCfg::IBCFlag = ContextSetCfg::addCtxSet
{ 5, 5, 8, }, { 5, 5, 8, },
}); });
#if JVET_N0054_JOINT_CHROMA
const CtxSet ContextSetCfg::JointCbCrFlag = ContextSetCfg::addCtxSet
({
{ CNU, },
{ CNU, },
{ CNU, },
{ DWS, },
});
#endif
const unsigned ContextSetCfg::NumberOfContexts = (unsigned)ContextSetCfg::sm_InitTables[0].size(); const unsigned ContextSetCfg::NumberOfContexts = (unsigned)ContextSetCfg::sm_InitTables[0].size();
......
...@@ -249,6 +249,9 @@ public: ...@@ -249,6 +249,9 @@ public:
static const CtxSet SmvdFlag; static const CtxSet SmvdFlag;
static const CtxSet IBCFlag; static const CtxSet IBCFlag;
static const CtxSet ISPMode; static const CtxSet ISPMode;
#if JVET_N0054_JOINT_CHROMA
static const CtxSet JointCbCrFlag;
#endif
static const unsigned NumberOfContexts; static const unsigned NumberOfContexts;
// combined sets for less complex copying // combined sets for less complex copying
......
...@@ -103,8 +103,13 @@ QpParam::QpParam(const TransformUnit& tu, const ComponentID &compIDX, const int ...@@ -103,8 +103,13 @@ QpParam::QpParam(const TransformUnit& tu, const ComponentID &compIDX, const int
if (isChroma(compID)) if (isChroma(compID))
{ {
#if JVET_N0054_JOINT_CHROMA
chromaQpOffset += tu.cs->pps->getQpOffset ( tu.jointCbCr ? JOINT_CbCr : compID );
chromaQpOffset += tu.cs->slice->getSliceChromaQpDelta( tu.jointCbCr ? JOINT_CbCr : compID );
#else
chromaQpOffset += tu.cs->pps->getQpOffset( compID ); chromaQpOffset += tu.cs->pps->getQpOffset( compID );
chromaQpOffset += tu.cs->slice->getSliceChromaQpDelta( compID ); chromaQpOffset += tu.cs->slice->getSliceChromaQpDelta( compID );
#endif
chromaQpOffset += tu.cs->pps->getPpsRangeExtension().getChromaQpOffsetListEntry( tu.cu->chromaQpAdj ).u.offset[int( compID ) - 1]; chromaQpOffset += tu.cs->pps->getPpsRangeExtension().getChromaQpOffsetListEntry( tu.cu->chromaQpAdj ).u.offset[int( compID ) - 1];
} }
......
...@@ -149,6 +149,9 @@ Slice::Slice() ...@@ -149,6 +149,9 @@ Slice::Slice()
m_lambdas [component] = 0.0; m_lambdas [component] = 0.0;
m_iSliceChromaQpDelta[component] = 0; m_iSliceChromaQpDelta[component] = 0;
} }
#if JVET_N0054_JOINT_CHROMA
m_iSliceChromaQpDelta[JOINT_CbCr] = 0;
#endif
initEqualRef(); initEqualRef();
...@@ -208,6 +211,9 @@ void Slice::initSlice() ...@@ -208,6 +211,9 @@ void Slice::initSlice()
{ {
m_iSliceChromaQpDelta[component] = 0; m_iSliceChromaQpDelta[component] = 0;
} }
#if JVET_N0054_JOINT_CHROMA
m_iSliceChromaQpDelta[JOINT_CbCr] = 0;
#endif
m_maxNumMergeCand = MRG_MAX_NUM_CANDS; m_maxNumMergeCand = MRG_MAX_NUM_CANDS;
m_maxNumAffineMergeCand = AFFINE_MRG_MAX_NUM_CANDS; m_maxNumAffineMergeCand = AFFINE_MRG_MAX_NUM_CANDS;
...@@ -776,6 +782,10 @@ void Slice::copySliceInfo(Slice *pSrc, bool cpyAlmostAll) ...@@ -776,6 +782,10 @@ void Slice::copySliceInfo(Slice *pSrc, bool cpyAlmostAll)
{ {
m_iSliceChromaQpDelta[component] = pSrc->m_iSliceChromaQpDelta[component]; m_iSliceChromaQpDelta[component] = pSrc->m_iSliceChromaQpDelta[component];
} }
#if JVET_N0054_JOINT_CHROMA
m_iSliceChromaQpDelta[JOINT_CbCr] = pSrc->m_iSliceChromaQpDelta[JOINT_CbCr];
#endif
for (i = 0; i < NUM_REF_PIC_LIST_01; i++) for (i = 0; i < NUM_REF_PIC_LIST_01; i++)
{ {
for (j = 0; j < MAX_NUM_REF; j++) for (j = 0; j < MAX_NUM_REF; j++)
...@@ -1900,6 +1910,9 @@ PPS::PPS() ...@@ -1900,6 +1910,9 @@ PPS::PPS()
, m_cuQpDeltaSubdiv (0) , m_cuQpDeltaSubdiv (0)
, m_chromaCbQpOffset (0) , m_chromaCbQpOffset (0)
, m_chromaCrQpOffset (0) , m_chromaCrQpOffset (0)
#if JVET_N0054_JOINT_CHROMA
, m_chromaCbCrQpOffset (0)
#endif
, m_numRefIdxL0DefaultActive (1) , m_numRefIdxL0DefaultActive (1)
, m_numRefIdxL1DefaultActive (1) , m_numRefIdxL1DefaultActive (1)
, m_TransquantBypassEnabledFlag (false) , m_TransquantBypassEnabledFlag (false)
......
...@@ -1503,6 +1503,9 @@ private: ...@@ -1503,6 +1503,9 @@ private:
int m_chromaCbQpOffset; int m_chromaCbQpOffset;
int m_chromaCrQpOffset; int m_chromaCrQpOffset;
#if JVET_N0054_JOINT_CHROMA
int m_chromaCbCrQpOffset;
#endif
uint32_t m_numRefIdxL0DefaultActive; uint32_t m_numRefIdxL0DefaultActive;
uint32_t m_numRefIdxL1DefaultActive; uint32_t m_numRefIdxL1DefaultActive;
...@@ -1580,6 +1583,12 @@ public: ...@@ -1580,6 +1583,12 @@ public:
{ {
m_chromaCrQpOffset = i; m_chromaCrQpOffset = i;
} }
#if JVET_N0054_JOINT_CHROMA
else if (compID==JOINT_CbCr)
{
m_chromaCbCrQpOffset = i;
}
#endif
else else
{ {
THROW( "Invalid chroma QP offset" ); THROW( "Invalid chroma QP offset" );
...@@ -1587,7 +1596,11 @@ public: ...@@ -1587,7 +1596,11 @@ public:
} }
int getQpOffset(ComponentID compID) const int getQpOffset(ComponentID compID) const
{ {
#if JVET_N0054_JOINT_CHROMA
return (compID==COMPONENT_Y) ? 0 : (compID==COMPONENT_Cb ? m_chromaCbQpOffset : compID==COMPONENT_Cr ? m_chromaCrQpOffset : m_chromaCbCrQpOffset );
#else
return (compID==COMPONENT_Y) ? 0 : (compID==COMPONENT_Cb ? m_chromaCbQpOffset : m_chromaCrQpOffset ); return (compID==COMPONENT_Y) ? 0 : (compID==COMPONENT_Cb ? m_chromaCbQpOffset : m_chromaCrQpOffset );
#endif
} }
void setNumRefIdxL0DefaultActive(uint32_t ui) { m_numRefIdxL0DefaultActive=ui; } void setNumRefIdxL0DefaultActive(uint32_t ui) { m_numRefIdxL0DefaultActive=ui; }
...@@ -1752,7 +1765,11 @@ private: ...@@ -1752,7 +1765,11 @@ private:
// Data // Data
int m_iSliceQpDelta; int m_iSliceQpDelta;
#if JVET_N0054_JOINT_CHROMA
int m_iSliceChromaQpDelta[MAX_NUM_COMPONENT+1];
#else
int m_iSliceChromaQpDelta[MAX_NUM_COMPONENT]; int m_iSliceChromaQpDelta[MAX_NUM_COMPONENT];
#endif
Picture* m_apcRefPicList [NUM_REF_PIC_LIST_01][MAX_NUM_REF+1]; Picture* m_apcRefPicList [NUM_REF_PIC_LIST_01][MAX_NUM_REF+1];
int m_aiRefPOCList [NUM_REF_PIC_LIST_01][MAX_NUM_REF+1]; int m_aiRefPOCList [NUM_REF_PIC_LIST_01][MAX_NUM_REF+1];
bool m_bIsUsedAsLongTerm[NUM_REF_PIC_LIST_01][MAX_NUM_REF+1]; bool m_bIsUsedAsLongTerm[NUM_REF_PIC_LIST_01][MAX_NUM_REF+1];
......
...@@ -50,6 +50,8 @@ ...@@ -50,6 +50,8 @@
#include <assert.h> #include <assert.h>
#include <cassert> #include <cassert>
#define JVET_N0054_JOINT_CHROMA 1 // Joint chroma residual coding mode
#define JVET_N0334_MVCLIPPING 1 // prevention of MV stroage overflow and alignment with spec of MV/CPMV modular for AMVP mode #define JVET_N0334_MVCLIPPING 1 // prevention of MV stroage overflow and alignment with spec of MV/CPMV modular for AMVP mode
#define JVET_N0481_BCW_CONSTRUCTED_AFFINE 1 #define JVET_N0481_BCW_CONSTRUCTED_AFFINE 1
...@@ -447,6 +449,9 @@ enum ComponentID ...@@ -447,6 +449,9 @@ enum ComponentID
COMPONENT_Cb = 1, COMPONENT_Cb = 1,
COMPONENT_Cr = 2, COMPONENT_Cr = 2,
MAX_NUM_COMPONENT = 3, MAX_NUM_COMPONENT = 3,
#if JVET_N0054_JOINT_CHROMA
JOINT_CbCr = MAX_NUM_COMPONENT,
#endif
MAX_NUM_TBLOCKS = MAX_NUM_COMPONENT MAX_NUM_TBLOCKS = MAX_NUM_COMPONENT
}; };
......
...@@ -614,6 +614,9 @@ void TransformUnit::initData() ...@@ -614,6 +614,9 @@ void TransformUnit::initData()
depth = 0; depth = 0;
mtsIdx = 0; mtsIdx = 0;
noResidual = false; noResidual = false;
#if JVET_N0054_JOINT_CHROMA
jointCbCr = 0;
#endif
m_chromaResScaleInv = 0; m_chromaResScaleInv = 0;
} }
...@@ -649,6 +652,9 @@ TransformUnit& TransformUnit::operator=(const TransformUnit& other) ...@@ -649,6 +652,9 @@ TransformUnit& TransformUnit::operator=(const TransformUnit& other)
depth = other.depth; depth = other.depth;
mtsIdx = other.mtsIdx; mtsIdx = other.mtsIdx;
noResidual = other.noResidual; noResidual = other.noResidual;
#if JVET_N0054_JOINT_CHROMA
jointCbCr = other.jointCbCr;
#endif
return *this; return *this;
} }
...@@ -670,6 +676,9 @@ void TransformUnit::copyComponentFrom(const TransformUnit& other, const Componen ...@@ -670,6 +676,9 @@ void TransformUnit::copyComponentFrom(const TransformUnit& other, const Componen
depth = other.depth; depth = other.depth;
mtsIdx = isLuma( i ) ? other.mtsIdx : mtsIdx; mtsIdx = isLuma( i ) ? other.mtsIdx : mtsIdx;
noResidual = other.noResidual; noResidual = other.noResidual;
#if JVET_N0054_JOINT_CHROMA
jointCbCr = isChroma( i ) ? other.jointCbCr : jointCbCr;
#endif
} }
CoeffBuf TransformUnit::getCoeffs(const ComponentID id) { return CoeffBuf(m_coeffs[id], blocks[id]); } CoeffBuf TransformUnit::getCoeffs(const ComponentID id) { return CoeffBuf(m_coeffs[id], blocks[id]); }
......
...@@ -440,6 +440,9 @@ struct TransformUnit : public UnitArea ...@@ -440,6 +440,9 @@ struct TransformUnit : public UnitArea
uint8_t depth; uint8_t depth;
uint8_t mtsIdx; uint8_t mtsIdx;
bool noResidual; bool noResidual;
#if JVET_N0054_JOINT_CHROMA
uint8_t jointCbCr;
#endif
uint8_t cbf [ MAX_NUM_TBLOCKS ]; uint8_t cbf [ MAX_NUM_TBLOCKS ];
RDPCMMode rdpcm [ MAX_NUM_TBLOCKS ]; RDPCMMode rdpcm [ MAX_NUM_TBLOCKS ];
int8_t compAlpha [ MAX_NUM_TBLOCKS ]; int8_t compAlpha [ MAX_NUM_TBLOCKS ];
......
...@@ -2346,11 +2346,30 @@ void CABACReader::cu_chroma_qp_offset( CodingUnit& cu ) ...@@ -2346,11 +2346,30 @@ void CABACReader::cu_chroma_qp_offset( CodingUnit& cu )
// void residual_coding_subblock( coeffCtx ) // void residual_coding_subblock( coeffCtx )
//================================================================================ //================================================================================
#if JVET_N0054_JOINT_CHROMA
void CABACReader::joint_cb_cr( TransformUnit& tu )
{
tu.jointCbCr = m_BinDecoder.decodeBin( Ctx::JointCbCrFlag( 0 ) );
}
#endif
void CABACReader::residual_coding( TransformUnit& tu, ComponentID compID ) void CABACReader::residual_coding( TransformUnit& tu, ComponentID compID )
{ {
const CodingUnit& cu = *tu.cu; const CodingUnit& cu = *tu.cu;
DTRACE( g_trace_ctx, D_SYNTAX, "residual_coding() etype=%d pos=(%d,%d) size=%dx%d predMode=%d\n", tu.blocks[compID].compID, tu.blocks[compID].x, tu.blocks[compID].y, tu.blocks[compID].width, tu.blocks[compID].height, cu.predMode ); DTRACE( g_trace_ctx, D_SYNTAX, "residual_coding() etype=%d pos=(%d,%d) size=%dx%d predMode=%d\n", tu.blocks[compID].compID, tu.blocks[compID].x, tu.blocks[compID].y, tu.blocks[compID].width, tu.blocks[compID].height, cu.predMode );
#if JVET_N0054_JOINT_CHROMA
// Joint Cb-Cr residual mode is signalled if both Cb and Cr cfbs are true
if ( compID == COMPONENT_Cr && TU::getCbf( tu, COMPONENT_Cb ) )
{
joint_cb_cr( tu );
// No Cr residual in bitstream in joint Cb-Cr residual mode
if ( tu.jointCbCr )
return;
}
#endif
// parse transform skip and explicit rdpcm mode // parse transform skip and explicit rdpcm mode
mts_coding ( tu, compID ); mts_coding ( tu, compID );
explicit_rdpcm_mode( tu, compID ); explicit_rdpcm_mode( tu, compID );
......
...@@ -130,6 +130,9 @@ public: ...@@ -130,6 +130,9 @@ public:
void explicit_rdpcm_mode ( TransformUnit& tu, ComponentID compID ); void explicit_rdpcm_mode ( TransformUnit& tu, ComponentID compID );
int last_sig_coeff ( CoeffCodingContext& cctx, TransformUnit& tu, ComponentID compID ); int last_sig_coeff ( CoeffCodingContext& cctx, TransformUnit& tu, ComponentID compID );
void residual_coding_subblock ( CoeffCodingContext& cctx, TCoeff* coeff, const int stateTransTable, int& state ); void residual_coding_subblock ( CoeffCodingContext& cctx, TCoeff* coeff, const int stateTransTable, int& state );
#if JVET_N0054_JOINT_CHROMA
void joint_cb_cr ( TransformUnit& tu );
#endif
// cross component prediction (clause 7.3.8.12) // cross component prediction (clause 7.3.8.12)
void cross_comp_pred ( TransformUnit& tu, ComponentID compID ); void cross_comp_pred ( TransformUnit& tu, ComponentID compID );
......
...@@ -222,6 +222,12 @@ void DecCu::xIntraRecBlk( TransformUnit& tu, const ComponentID compID ) ...@@ -222,6 +222,12 @@ void DecCu::xIntraRecBlk( TransformUnit& tu, const ComponentID compID )
const QpParam cQP( tu, compID ); const QpParam cQP( tu, compID );
#if JVET_N0054_JOINT_CHROMA
// Joint chroma residual mode: Cr uses negative of the signalled Cb residual
if ( tu.jointCbCr && compID == COMPONENT_Cr )
piResi.copyAndNegate( cs.getResiBuf( tu.blocks[COMPONENT_Cb] ) );
else
#endif
if( TU::getCbf( tu, compID ) ) if( TU::getCbf( tu, compID ) )
{ {
m_pcTrQuant->invTransformNxN( tu, compID, piResi, cQP ); m_pcTrQuant->invTransformNxN( tu, compID, piResi, cQP );
...@@ -235,6 +241,9 @@ void DecCu::xIntraRecBlk( TransformUnit& tu, const ComponentID compID ) ...@@ -235,6 +241,9 @@ void DecCu::xIntraRecBlk( TransformUnit& tu, const ComponentID compID )
flag = flag && (tu.blocks[compID].width*tu.blocks[compID].height > 4); flag = flag && (tu.blocks[compID].width*tu.blocks[compID].height > 4);
if (flag && TU::getCbf(tu, compID) && isChroma(compID) && slice.getReshapeInfo().getSliceReshapeChromaAdj()) if (flag && TU::getCbf(tu, compID) && isChroma(compID) && slice.getReshapeInfo().getSliceReshapeChromaAdj())
{ {
#if JVET_N0054_JOINT_CHROMA
if ( !(tu.jointCbCr && compID == COMPONENT_Cr) ) // // Joint chroma residual mode: chroma scaling took place already when doing Cb
#endif
piResi.scaleSignal(tu.getChromaAdj(), 0, tu.cu->cs->slice->clpRng(compID)); piResi.scaleSignal(tu.getChromaAdj(), 0, tu.cu->cs->slice->clpRng(compID));
} }
if( isChroma(compID) && tu.compAlpha[compID] != 0 ) if( isChroma(compID) && tu.compAlpha[compID] != 0 )
...@@ -537,6 +546,12 @@ void DecCu::xDecodeInterTU( TransformUnit & currTU, const ComponentID compID ) ...@@ -537,6 +546,12 @@ void DecCu::xDecodeInterTU( TransformUnit & currTU, const ComponentID compID )
const QpParam cQP(currTU, compID); const QpParam cQP(currTU, compID);
#if JVET_N0054_JOINT_CHROMA
// Joint chroma residual mode: Cr uses negative of the signalled Cb residual
if ( currTU.jointCbCr && compID == COMPONENT_Cr )
resiBuf.copyAndNegate( cs.getResiBuf( currTU.blocks[COMPONENT_Cb] ) );
else
#endif
if( TU::getCbf( currTU, compID ) ) if( TU::getCbf( currTU, compID ) )
{ {
m_pcTrQuant->invTransformNxN( currTU, compID, resiBuf, cQP ); m_pcTrQuant->invTransformNxN( currTU, compID, resiBuf, cQP );
...@@ -550,6 +565,9 @@ void DecCu::xDecodeInterTU( TransformUnit & currTU, const ComponentID compID ) ...@@ -550,6 +565,9 @@ void DecCu::xDecodeInterTU( TransformUnit & currTU, const ComponentID compID )
const Slice &slice = *cs.slice; const Slice &slice = *cs.slice;
if ( slice.getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag() && isChroma(compID) && TU::getCbf(currTU, compID) && slice.getReshapeInfo().getSliceReshapeChromaAdj() && currTU.blocks[compID].width*currTU.blocks[compID].height > 4 ) if ( slice.getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag() && isChroma(compID) && TU::getCbf(currTU, compID) && slice.getReshapeInfo().getSliceReshapeChromaAdj() && currTU.blocks[compID].width*currTU.blocks[compID].height > 4 )
{ {
#if JVET_N0054_JOINT_CHROMA
if ( !(currTU.jointCbCr && compID == COMPONENT_Cr) ) // Joint chroma residual mode: chroma scaling took place already when doing Cb
#endif
resiBuf.scaleSignal(currTU.getChromaAdj(), 0, currTU.cu->cs->slice->clpRng(compID)); resiBuf.scaleSignal(currTU.getChromaAdj(), 0, currTU.cu->cs->slice->clpRng(compID));
} }
if( isChroma( compID ) && currTU.compAlpha[compID] != 0 ) if( isChroma( compID ) && currTU.compAlpha[compID] != 0 )
......
...@@ -430,6 +430,13 @@ void HLSyntaxReader::parsePPS( PPS* pcPPS ) ...@@ -430,6 +430,13 @@ void HLSyntaxReader::parsePPS( PPS* pcPPS )
CHECK( pcPPS->getQpOffset(COMPONENT_Cr) < -12, "Invalid Cr QP offset" ); CHECK( pcPPS->getQpOffset(COMPONENT_Cr) < -12, "Invalid Cr QP offset" );
CHECK( pcPPS->getQpOffset(COMPONENT_Cr) > 12, "Invalid Cr QP offset" ); CHECK( pcPPS->getQpOffset(COMPONENT_Cr) > 12, "Invalid Cr QP offset" );
#if JVET_N0054_JOINT_CHROMA
READ_SVLC( iCode, "pps_cb_cr_qp_offset");
pcPPS->setQpOffset(JOINT_CbCr, iCode);
CHECK( pcPPS->getQpOffset(JOINT_CbCr) < -12, "Invalid CbCr QP offset" );
CHECK( pcPPS->getQpOffset(JOINT_CbCr) > 12, "Invalid CbCr QP offset" );
#endif
CHECK(MAX_NUM_COMPONENT>3, "Invalid maximal number of components"); CHECK(MAX_NUM_COMPONENT>3, "Invalid maximal number of components");
READ_FLAG( uiCode, "pps_slice_chroma_qp_offsets_present_flag" ); READ_FLAG( uiCode, "pps_slice_chroma_qp_offsets_present_flag" );
...@@ -1926,6 +1933,15 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, ParameterSetManager *para ...@@ -1926,6 +1933,15 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, ParameterSetManager *para
CHECK( pcSlice->getSliceChromaQpDelta(COMPONENT_Cr) > 12, "Invalid chroma QP offset" ); CHECK( pcSlice->getSliceChromaQpDelta(COMPONENT_Cr) > 12, "Invalid chroma QP offset" );
CHECK( (pps->getQpOffset(COMPONENT_Cr) + pcSlice->getSliceChromaQpDelta(COMPONENT_Cr)) < -12, "Invalid chroma QP offset" ); CHECK( (pps->getQpOffset(COMPONENT_Cr) + pcSlice->getSliceChromaQpDelta(COMPONENT_Cr)) < -12, "Invalid chroma QP offset" );
CHECK( (pps->getQpOffset(COMPONENT_Cr) + pcSlice->getSliceChromaQpDelta(COMPONENT_Cr)) > 12, "Invalid chroma QP offset" ); CHECK( (pps->getQpOffset(COMPONENT_Cr) + pcSlice->getSliceChromaQpDelta(COMPONENT_Cr)) > 12, "Invalid chroma QP offset" );
#if JVET_N0054_JOINT_CHROMA
READ_SVLC( iCode, "slice_cb_cr_qp_offset" );
pcSlice->setSliceChromaQpDelta(JOINT_CbCr, iCode );
CHECK( pcSlice->getSliceChromaQpDelta(JOINT_CbCr) < -12, "Invalid chroma QP offset" );
CHECK( pcSlice->getSliceChromaQpDelta(JOINT_CbCr) > 12, "Invalid chroma QP offset" );
CHECK( (pps->getQpOffset(JOINT_CbCr) + pcSlice->getSliceChromaQpDelta(JOINT_CbCr)) < -12, "Invalid chroma QP offset" );
CHECK( (pps->getQpOffset(JOINT_CbCr) + pcSlice->getSliceChromaQpDelta(JOINT_CbCr)) > 12, "Invalid chroma QP offset" );
#endif
} }
} }
......
...@@ -2230,11 +2230,30 @@ void CABACWriter::cu_chroma_qp_offset( const CodingUnit& cu ) ...@@ -2230,11 +2230,30 @@ void CABACWriter::cu_chroma_qp_offset( const CodingUnit& cu )
// void residual_coding_subblock( coeffCtx ) // void residual_coding_subblock( coeffCtx )
//================================================================================ //================================================================================
#if JVET_N0054_JOINT_CHROMA
void CABACWriter::joint_cb_cr( const TransformUnit& tu )
{
m_BinEncoder.encodeBin( tu.jointCbCr ? 1 : 0, Ctx::JointCbCrFlag( 0 ) );
}
#endif