diff --git a/source/Lib/CommonLib/ContextModelling.h b/source/Lib/CommonLib/ContextModelling.h index f746b9d8346c6f2d4e789ea0d7a300e4dd04ef57..63b246b309120b14cece605c405581a13630a793 100644 --- a/source/Lib/CommonLib/ContextModelling.h +++ b/source/Lib/CommonLib/ContextModelling.h @@ -99,6 +99,12 @@ public: void setNumCtxBins ( int n ) { m_remainingContextBins = n; } unsigned sigGroupCtxId ( bool ts = false ) const { return ts ? m_sigGroupCtxIdTS : m_sigGroupCtxId; } bool bdpcm () const { return m_bdpcm; } + +#if JVET_P0072_SIMPLIFIED_TSRC + void decimateNumCtxBins(int n) { m_remainingContextBins -= n; } + void increaseNumCtxBins(int n) { m_remainingContextBins += n; } +#endif + unsigned sigCtxIdAbs( int scanPos, const TCoeff* coeff, const int state ) { const uint32_t posY = m_scan[scanPos].y; @@ -295,6 +301,11 @@ public: int deriveModCoeff(int rightPixel, int belowPixel, int absCoeff, int bdpcm = 0) { + +#if JVET_P0072_SIMPLIFIED_TSRC + if (absCoeff == 0) + return 0; +#endif int pred1, absBelow = abs(belowPixel), absRight = abs(rightPixel); int absCoeffMod = absCoeff; @@ -318,6 +329,12 @@ public: int decDeriveModCoeff(int rightPixel, int belowPixel, int absCoeff) { + +#if JVET_P0072_SIMPLIFIED_TSRC + if (absCoeff == 0) + return 0; +#endif + int pred1, absBelow = abs(belowPixel), absRight = abs(rightPixel); pred1 = std::max(absBelow, absRight); diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index 74e6e090d2d0158089ff38dcf8c4fcd09c923119..bc0364ee0f2b92171caff4a48692481a975c8517 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -51,6 +51,7 @@ #include <cassert> + #define JVET_P0154_PROF_SAMPLE_OFFSET_CLIPPING 1 // JVET-P0154/P0094/P0172/P0413/P0518/P0281: Clip the PROF sample offset to 14-bit #define JVET_P1023_DMVR_BDOF_RP_CONDITION 1 // JVET_P1023: Reference picture conditions in DMVR and BDOF @@ -59,6 +60,9 @@ #define JVET_P0072_SIMPLIFIED_TSRC 1 // JVET-P0072: Simplified transform-skip residual coding +#define JVET_P0072_SIMPLIFIED_TSRC 1 // JVET-P0072: Simplified transform-skip residual coding + + #define JVET_P0164_ALF_SYNTAX_SIMP 1 // JVET-p0164: simplify alf syntax with method2 diff --git a/source/Lib/DecoderLib/CABACReader.cpp b/source/Lib/DecoderLib/CABACReader.cpp index 414ec0e0200bbb5c2c5cb0ddb66e9445f7c69b32..51ea4f579144bd121c63205474ae467cdf67ca46 100644 --- a/source/Lib/DecoderLib/CABACReader.cpp +++ b/source/Lib/DecoderLib/CABACReader.cpp @@ -3308,8 +3308,12 @@ void CABACReader::residual_codingTS( TransformUnit& tu, ComponentID compID ) // init coeff coding context CoeffCodingContext cctx ( tu, compID, false, tu.cu->bdpcmMode ); TCoeff* coeff = tu.getCoeffs( compID ).buf; - +#if JVET_P0072_SIMPLIFIED_TSRC + int maxCtxBins = (cctx.maxNumCoeff() * 7) >> 2; + cctx.setNumCtxBins(maxCtxBins); +#else cctx.setNumCtxBins( 2 * tu.lwidth()*tu.lheight() ); +#endif for( int subSetId = 0; subSetId <= ( cctx.maxNumCoeff() - 1 ) >> cctx.log2CGSize(); subSetId++ ) { @@ -3367,24 +3371,36 @@ void CABACReader::residual_coding_subblockTS( CoeffCodingContext& cctx, TCoeff* int numNonZero = 0; int sigBlkPos[ 1 << MLS_CG_SIZE ]; +#if JVET_P0072_SIMPLIFIED_TSRC + int lastScanPosPass1 = -1; + int lastScanPosPass2 = -1; + for (; nextSigPos <= minSubPos && cctx.numCtxBins() >= 4; nextSigPos++) +#else for( ; nextSigPos <= minSubPos; nextSigPos++ ) +#endif { int blkPos = cctx.blockPos( nextSigPos ); unsigned sigFlag = ( !numNonZero && nextSigPos == inferSigPos ); if( !sigFlag ) { RExt__DECODER_DEBUG_BIT_STATISTICS_SET( ctype_map ); +#if !JVET_P0072_SIMPLIFIED_TSRC if( cctx.isContextCoded() ) { +#endif const unsigned sigCtxId = cctx.sigCtxIdAbsTS( nextSigPos, coeff ); sigFlag = m_BinDecoder.decodeBin( sigCtxId ); DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_sig_bin() bin=%d ctx=%d\n", sigFlag, sigCtxId ); +#if JVET_P0072_SIMPLIFIED_TSRC + cctx.decimateNumCtxBins(1); +#else } else { sigFlag = m_BinDecoder.decodeBinEP( ); DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_sig_bin() EPbin=%d\n", sigFlag ); } +#endif } if( sigFlag ) @@ -3396,15 +3412,21 @@ void CABACReader::residual_coding_subblockTS( CoeffCodingContext& cctx, TCoeff* RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET_SIZE2( STATS__CABAC_BITS__SIGN_BIT, Size( cctx.width(), cctx.height() ), cctx.compID() ); #endif int sign; +#if !JVET_P0072_SIMPLIFIED_TSRC if( cctx.isContextCoded() ) { +#endif const unsigned signCtxId = cctx.signCtxIdAbsTS(nextSigPos, coeff, cctx.bdpcm()); sign = m_BinDecoder.decodeBin(signCtxId); +#if JVET_P0072_SIMPLIFIED_TSRC + cctx.decimateNumCtxBins(1); +#else } else { sign = m_BinDecoder.decodeBinEP( ); } +#endif signPattern += ( sign << numNonZero ); @@ -3413,41 +3435,60 @@ void CABACReader::residual_coding_subblockTS( CoeffCodingContext& cctx, TCoeff* RExt__DECODER_DEBUG_BIT_STATISTICS_SET( ctype_gt1 ); unsigned gt1Flag; const unsigned gt1CtxId = cctx.lrg1CtxIdAbsTS(nextSigPos, coeff, cctx.bdpcm()); +#if !JVET_P0072_SIMPLIFIED_TSRC if( cctx.isContextCoded() ) { +#endif gt1Flag = m_BinDecoder.decodeBin(gt1CtxId); DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_gt1_flag() bin=%d ctx=%d\n", gt1Flag, gt1CtxId ); +#if JVET_P0072_SIMPLIFIED_TSRC + cctx.decimateNumCtxBins(1); +#else } else { gt1Flag = m_BinDecoder.decodeBinEP( ); DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_gt1_flag() EPbin=%d\n", gt1Flag ); } +#endif unsigned parFlag = 0; if( gt1Flag ) { RExt__DECODER_DEBUG_BIT_STATISTICS_SET( ctype_par ); +#if !JVET_P0072_SIMPLIFIED_TSRC if( cctx.isContextCoded() ) { +#endif parFlag = m_BinDecoder.decodeBin( cctx.parityCtxIdAbsTS() ); DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_par_flag() bin=%d ctx=%d\n", parFlag, cctx.parityCtxIdAbsTS() ); +#if JVET_P0072_SIMPLIFIED_TSRC + cctx.decimateNumCtxBins(1); +#else } else { parFlag = m_BinDecoder.decodeBinEP( ); DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_par_flag() EPbin=%d\n", parFlag ); } +#endif } coeff[ blkPos ] = (sign ? -1 : 1 ) * (1 + parFlag + gt1Flag); } +#if JVET_P0072_SIMPLIFIED_TSRC + lastScanPosPass1 = nextSigPos; +#endif } int cutoffVal = 2; const int numGtBins = 4; //===== 2nd PASS: gt2 ===== +#if JVET_P0072_SIMPLIFIED_TSRC + for (int scanPos = firstSigPos; scanPos <= minSubPos && cctx.numCtxBins() >= 4; scanPos++) +#else for (int scanPos = firstSigPos; scanPos <= minSubPos; scanPos++) +#endif { TCoeff& tcoeff = coeff[cctx.blockPos(scanPos)]; cutoffVal = 2; @@ -3461,11 +3502,16 @@ void CABACReader::residual_coding_subblockTS( CoeffCodingContext& cctx, TCoeff* { RExt__DECODER_DEBUG_BIT_STATISTICS_SET(ctype_gt2); unsigned gt2Flag; +#if !JVET_P0072_SIMPLIFIED_TSRC if (cctx.isContextCoded()) { +#endif gt2Flag = m_BinDecoder.decodeBin(cctx.greaterXCtxIdAbsTS(cutoffVal >> 1)); tcoeff += (gt2Flag << 1); DTRACE(g_trace_ctx, D_SYNTAX_RESI, "ts_gt%d_flag() bin=%d ctx=%d sp=%d coeff=%d\n", i, gt2Flag, cctx.greaterXCtxIdAbsTS(cutoffVal >> 1), scanPos, tcoeff); +#if JVET_P0072_SIMPLIFIED_TSRC + cctx.decimateNumCtxBins(1); +#else } else { @@ -3473,21 +3519,44 @@ void CABACReader::residual_coding_subblockTS( CoeffCodingContext& cctx, TCoeff* tcoeff += (gt2Flag << 1); DTRACE(g_trace_ctx, D_SYNTAX_RESI, "ts_gt%d_flag() EPbin=%d sp=%d coeff=%d\n", i, gt2Flag, scanPos, tcoeff); } +#endif } cutoffVal += 2; } +#if JVET_P0072_SIMPLIFIED_TSRC + lastScanPosPass2 = scanPos; +#endif } //===== 3rd PASS: Go-rice codes ===== for( int scanPos = firstSigPos; scanPos <= minSubPos; scanPos++ ) { TCoeff& tcoeff = coeff[ cctx.blockPos( scanPos ) ]; RExt__DECODER_DEBUG_BIT_STATISTICS_SET( ctype_escs ); + +#if JVET_P0072_SIMPLIFIED_TSRC + cutoffVal = (scanPos <= lastScanPosPass2 ? 10 : (scanPos <= lastScanPosPass1 ? 2 : 0)); + if (tcoeff < 0) + { + tcoeff = -tcoeff; + } +#endif if( tcoeff >= cutoffVal ) { int rice = cctx.templateAbsSumTS( scanPos, coeff ); int rem = m_BinDecoder.decodeRemAbsEP( rice, cctx.extPrec(), cctx.maxLog2TrDRange() ); DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_rem_val() bin=%d ctx=%d sp=%d\n", rem, rice, scanPos ); +#if JVET_P0072_SIMPLIFIED_TSRC + tcoeff += (scanPos <= lastScanPosPass1) ? (rem << 1) : rem; + if (tcoeff && scanPos > lastScanPosPass1) + { + int blkPos = cctx.blockPos(scanPos); + int sign = m_BinDecoder.decodeBinEP(); + signPattern += (sign << numNonZero); + sigBlkPos[numNonZero++] = blkPos; + } +#else tcoeff += ( rem << 1 ); +#endif } if (!cctx.bdpcm()) { diff --git a/source/Lib/EncoderLib/CABACWriter.cpp b/source/Lib/EncoderLib/CABACWriter.cpp index d98d1934de3508c28dfe73e87b49d4b9f8227a15..810e099f00035967f3eb4b3d4e2274433895adaa 100644 --- a/source/Lib/EncoderLib/CABACWriter.cpp +++ b/source/Lib/EncoderLib/CABACWriter.cpp @@ -3070,8 +3070,12 @@ void CABACWriter::residual_codingTS( const TransformUnit& tu, ComponentID compID // init coeff coding context CoeffCodingContext cctx ( tu, compID, false, tu.cu->bdpcmMode ); const TCoeff* coeff = tu.getCoeffs( compID ).buf; - +#if JVET_P0072_SIMPLIFIED_TSRC + int maxCtxBins = (cctx.maxNumCoeff() * 7) >> 2; + cctx.setNumCtxBins(maxCtxBins); +#else cctx.setNumCtxBins( 2 * tu.lwidth()*tu.lheight() ); +#endif // determine and set last coeff position and sig group flags std::bitset<MLS_GRP_NUM> sigGroupFlags; @@ -3122,38 +3126,56 @@ void CABACWriter::residual_coding_subblockTS( CoeffCodingContext& cctx, const TC int rightPixel, belowPixel, modAbsCoeff; +#if JVET_P0072_SIMPLIFIED_TSRC + int lastScanPosPass1 = -1; + int lastScanPosPass2 = -1; + for (; nextSigPos <= minSubPos && cctx.numCtxBins() >= 4; nextSigPos++) +#else for( ; nextSigPos <= minSubPos; nextSigPos++ ) +#endif { TCoeff Coeff = coeff[ cctx.blockPos( nextSigPos ) ]; unsigned sigFlag = ( Coeff != 0 ); if( numNonZero || nextSigPos != inferSigPos ) { +#if !JVET_P0072_SIMPLIFIED_TSRC if( cctx.isContextCoded() ) { +#endif const unsigned sigCtxId = cctx.sigCtxIdAbsTS( nextSigPos, coeff ); m_BinEncoder.encodeBin( sigFlag, sigCtxId ); DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_sig_bin() bin=%d ctx=%d\n", sigFlag, sigCtxId ); +#if JVET_P0072_SIMPLIFIED_TSRC + cctx.decimateNumCtxBins(1); +#else } else { m_BinEncoder.encodeBinEP( sigFlag ); DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_sig_bin() EPbin=%d\n", sigFlag ); } +#endif } if( sigFlag ) { //===== encode sign's ===== int sign = Coeff < 0; +#if !JVET_P0072_SIMPLIFIED_TSRC if( cctx.isContextCoded() ) { +#endif const unsigned signCtxId = cctx.signCtxIdAbsTS(nextSigPos, coeff, cctx.bdpcm()); m_BinEncoder.encodeBin(sign, signCtxId); +#if JVET_P0072_SIMPLIFIED_TSRC + cctx.decimateNumCtxBins(1); +#else } else { m_BinEncoder.encodeBinEP( sign ); } +#endif numNonZero++; cctx.neighTS(rightPixel, belowPixel, nextSigPos, coeff); modAbsCoeff = cctx.deriveModCoeff(rightPixel, belowPixel, abs(Coeff), cctx.bdpcm()); @@ -3161,38 +3183,56 @@ void CABACWriter::residual_coding_subblockTS( CoeffCodingContext& cctx, const TC unsigned gt1 = !!remAbsLevel; const unsigned gt1CtxId = cctx.lrg1CtxIdAbsTS(nextSigPos, coeff, cctx.bdpcm()); +#if !JVET_P0072_SIMPLIFIED_TSRC if (cctx.isContextCoded()) { +#endif m_BinEncoder.encodeBin(gt1, gt1CtxId); DTRACE(g_trace_ctx, D_SYNTAX_RESI, "ts_gt1_flag() bin=%d ctx=%d\n", gt1, gt1CtxId); +#if JVET_P0072_SIMPLIFIED_TSRC + cctx.decimateNumCtxBins(1); +#else } else { m_BinEncoder.encodeBinEP(gt1); DTRACE(g_trace_ctx, D_SYNTAX_RESI, "ts_gt1_flag() EPbin=%d\n", gt1); } +#endif if( gt1 ) { remAbsLevel -= 1; +#if !JVET_P0072_SIMPLIFIED_TSRC if( cctx.isContextCoded() ) { +#endif m_BinEncoder.encodeBin( remAbsLevel&1, cctx.parityCtxIdAbsTS() ); DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_par_flag() bin=%d ctx=%d\n", remAbsLevel&1, cctx.parityCtxIdAbsTS() ); +#if JVET_P0072_SIMPLIFIED_TSRC + cctx.decimateNumCtxBins(1); +#else } else { m_BinEncoder.encodeBinEP( remAbsLevel&1 ); DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_par_flag() EPbin=%d\n", remAbsLevel&1 ); } +#endif } } +#if JVET_P0072_SIMPLIFIED_TSRC + lastScanPosPass1 = nextSigPos; +#endif } int cutoffVal = 2; int numGtBins = 4; - +#if JVET_P0072_SIMPLIFIED_TSRC + for (int scanPos = firstSigPos; scanPos <= minSubPos && cctx.numCtxBins() >= 4; scanPos++) +#else for (int scanPos = firstSigPos; scanPos <= minSubPos; scanPos++) +#endif { unsigned absLevel; cctx.neighTS(rightPixel, belowPixel, scanPos, coeff); @@ -3203,19 +3243,28 @@ void CABACWriter::residual_coding_subblockTS( CoeffCodingContext& cctx, const TC if (absLevel >= cutoffVal) { unsigned gt2 = (absLevel >= (cutoffVal + 2)); +#if !JVET_P0072_SIMPLIFIED_TSRC if (cctx.isContextCoded()) { +#endif m_BinEncoder.encodeBin(gt2, cctx.greaterXCtxIdAbsTS(cutoffVal >> 1)); DTRACE(g_trace_ctx, D_SYNTAX_RESI, "ts_gt%d_flag() bin=%d ctx=%d sp=%d coeff=%d\n", i, gt2, cctx.greaterXCtxIdAbsTS(cutoffVal >> 1), scanPos, min<int>(absLevel, cutoffVal + 2)); +#if JVET_P0072_SIMPLIFIED_TSRC + cctx.decimateNumCtxBins(1); +#else } else { m_BinEncoder.encodeBinEP(gt2); DTRACE(g_trace_ctx, D_SYNTAX_RESI, "ts_gt%d_flag() EPbin=%d sp=%d coeff=%d\n", i, gt2, scanPos, min<int>(absLevel, cutoffVal + 2)); } +#endif } cutoffVal += 2; } +#if JVET_P0072_SIMPLIFIED_TSRC + lastScanPosPass2 = scanPos; +#endif } //===== coeff bypass ==== @@ -3224,12 +3273,27 @@ void CABACWriter::residual_coding_subblockTS( CoeffCodingContext& cctx, const TC unsigned absLevel; cctx.neighTS(rightPixel, belowPixel, scanPos, coeff); absLevel = cctx.deriveModCoeff(rightPixel, belowPixel, abs(coeff[cctx.blockPos(scanPos)]), cctx.bdpcm()); +#if JVET_P0072_SIMPLIFIED_TSRC + cutoffVal = (scanPos <= lastScanPosPass2 ? 10 : (scanPos <= lastScanPosPass1 ? 2 : 0)); +#endif if( absLevel >= cutoffVal ) { int rice = cctx.templateAbsSumTS( scanPos, coeff ); +#if JVET_P0072_SIMPLIFIED_TSRC + unsigned rem = scanPos <= lastScanPosPass1 ? (absLevel - cutoffVal) >> 1 : absLevel; +#else unsigned rem = ( absLevel - cutoffVal ) >> 1; +#endif m_BinEncoder.encodeRemAbsEP( rem, rice, cctx.extPrec(), cctx.maxLog2TrDRange() ); DTRACE( g_trace_ctx, D_SYNTAX_RESI, "ts_rem_val() bin=%d ctx=%d sp=%d\n", rem, rice, scanPos ); + +#if JVET_P0072_SIMPLIFIED_TSRC + if (absLevel && scanPos > lastScanPosPass1) + { + int sign = coeff[cctx.blockPos(scanPos)] < 0; + m_BinEncoder.encodeBinEP(sign); + } +#endif } } }