diff --git a/source/Lib/CommonLib/InterpolationFilter.h b/source/Lib/CommonLib/InterpolationFilter.h index e743106336d3606473bd7f1d005587860e8937ac..4535b6bc56ba52fd6130e4f7e8a5443fac1a7770 100644 --- a/source/Lib/CommonLib/InterpolationFilter.h +++ b/source/Lib/CommonLib/InterpolationFilter.h @@ -92,6 +92,10 @@ public: #if JVET_J0090_MEMORY_BANDWITH_MEASURE void cacheAssign( CacheModel *cache ) { m_cacheModel = cache; } #endif + +#if JVET_L0628_4TAP_INTRA + static TFilterCoeff const * const getChromaFilterTable(const int deltaFract) { return m_chromaFilter[deltaFract]; }; +#endif //JVET_L0628_4TAP_INTRA }; //! \} diff --git a/source/Lib/CommonLib/IntraPrediction.cpp b/source/Lib/CommonLib/IntraPrediction.cpp index 66a724286a81183ed80d35102a69571a7cebe374..45a66514af173d329092688d2a6d9e9691f31022 100644 --- a/source/Lib/CommonLib/IntraPrediction.cpp +++ b/source/Lib/CommonLib/IntraPrediction.cpp @@ -46,6 +46,10 @@ #include <memory.h> +#if JVET_L0628_4TAP_INTRA +#include "CommonLib/InterpolationFilter.h" +#endif //JVET_L0628_4TAP_INTRA + //! \ingroup CommonLib //! \{ @@ -62,7 +66,7 @@ const uint8_t IntraPrediction::m_aucIntraFilter[MAX_NUM_CHANNEL_TYPE][MAX_INTRA_ 14, // 8xn 2, // 16xn 0, // 32xn -#if HM_MDIS_AS_IN_JEM +#if HM_MDIS_AS_IN_JEM && !JVET_L0628_4TAP_INTRA 20, // 64xn #else 0, // 64xn @@ -76,7 +80,7 @@ const uint8_t IntraPrediction::m_aucIntraFilter[MAX_NUM_CHANNEL_TYPE][MAX_INTRA_ 28, // 8xn 4, // 16xn 0, // 32xn -#if HM_MDIS_AS_IN_JEM +#if HM_MDIS_AS_IN_JEM && !JVET_L0628_4TAP_INTRA 40, // 64xn #else 0, // 64xn @@ -85,6 +89,43 @@ const uint8_t IntraPrediction::m_aucIntraFilter[MAX_NUM_CHANNEL_TYPE][MAX_INTRA_ } }; +#if JVET_L0628_4TAP_INTRA +const TFilterCoeff g_intraGaussFilter[32][4] = { + { 16, 32, 16, 0 }, + { 15, 29, 17, 3 }, + { 15, 29, 17, 3 }, + { 14, 29, 18, 3 }, + { 13, 29, 18, 4 }, + { 13, 28, 19, 4 }, + { 13, 28, 19, 4 }, + { 12, 28, 20, 4 }, + { 11, 28, 20, 5 }, + { 11, 27, 21, 5 }, + { 10, 27, 22, 5 }, + { 9, 27, 22, 6 }, + { 9, 26, 23, 6 }, + { 9, 26, 23, 6 }, + { 8, 25, 24, 7 }, + { 8, 25, 24, 7 }, + { 8, 24, 24, 8 }, + { 7, 24, 25, 8 }, + { 7, 24, 25, 8 }, + { 6, 23, 26, 9 }, + { 6, 23, 26, 9 }, + { 6, 22, 27, 9 }, + { 5, 22, 27, 10 }, + { 5, 21, 27, 11 }, + { 5, 20, 28, 11 }, + { 4, 20, 28, 12 }, + { 4, 19, 28, 13 }, + { 4, 19, 28, 13 }, + { 4, 18, 29, 13 }, + { 3, 18, 29, 14 }, + { 3, 17, 29, 15 }, + { 3, 17, 29, 15 } +}; +#endif + // ==================================================================================================================== // Constructor / destructor / initialize // ==================================================================================================================== @@ -255,7 +296,19 @@ void IntraPrediction::predIntraAng( const ComponentID compId, PelBuf &piPred, co { case(PLANAR_IDX): xPredIntraPlanar(CPelBuf(ptrSrc, srcStride, srcHStride), piPred, *pu.cs->sps); break; case(DC_IDX): xPredIntraDc(CPelBuf(ptrSrc, srcStride, srcHStride), piPred, channelType, false); break; +#if JVET_L0628_4TAP_INTRA + case(2): + case(DIA_IDX): + case(VDIA_IDX): + if (getWideAngle(iWidth, iHeight, uiDirMode) == static_cast<int>(uiDirMode)) // check if uiDirMode is not wide-angle + { + xPredIntraAng(CPelBuf(ptrSrc, srcStride, srcHStride), piPred, channelType, uiDirMode, clpRng, *pu.cs->sps, useFilteredPredSamples); + break; + } + default: xPredIntraAng(CPelBuf(getPredictorPtr(compID, false), srcStride, srcHStride), piPred, channelType, uiDirMode, clpRng, *pu.cs->sps, useFilteredPredSamples); break; +#else //JVET_L0628_4TAP_INTRA default: xPredIntraAng(CPelBuf(ptrSrc, srcStride, srcHStride), piPred, channelType, uiDirMode, clpRng, *pu.cs->sps, false); break; +#endif //JVET_L0628_4TAP_INTRA } bool pdpcCondition = (uiDirMode == PLANAR_IDX || uiDirMode == DC_IDX || uiDirMode == HOR_IDX || uiDirMode == VER_IDX); @@ -475,6 +528,8 @@ void IntraPrediction::xDCPredFiltering(const CPelBuf &pSrc, PelBuf &pDst, const //NOTE: Bit-Limit - 25-bit source #if HEVC_USE_HOR_VER_PREDFILTERING void IntraPrediction::xPredIntraAng( const CPelBuf &pSrc, PelBuf &pDst, const ChannelType channelType, const uint32_t dirMode, const ClpRng& clpRng, const bool bEnableEdgeFilters, const SPS& sps, const bool enableBoundaryFilter ) +#elif JVET_L0628_4TAP_INTRA +void IntraPrediction::xPredIntraAng( const CPelBuf &pSrc, PelBuf &pDst, const ChannelType channelType, const uint32_t dirMode, const ClpRng& clpRng, const SPS& sps, const bool useFilteredPredSamples ) #else void IntraPrediction::xPredIntraAng( const CPelBuf &pSrc, PelBuf &pDst, const ChannelType channelType, const uint32_t dirMode, const ClpRng& clpRng, const SPS& sps, const bool enableBoundaryFilter ) #endif @@ -512,6 +567,12 @@ void IntraPrediction::xPredIntraAng( const CPelBuf &pSrc, PelBuf &pDst, const Ch // Initialize the Main and Left reference array. if (intraPredAngle < 0) { +#if JVET_L0628_4TAP_INTRA + auto width = int(pDst.width) +1; + auto height = int(pDst.height)+1; + auto lastIdx = bIsModeVer ? width : height; + auto firstIdx = ( ((bIsModeVer ? height : width) -1) * intraPredAngle ) >> 5; +#endif //JVET_L0628_4TAP_INTRA for( int x = 0; x < width + 1; x++ ) { refAbove[x + height - 1] = pSrc.at( x, 0 ); @@ -525,25 +586,49 @@ void IntraPrediction::xPredIntraAng( const CPelBuf &pSrc, PelBuf &pDst, const Ch // Extend the Main reference to the left. int invAngleSum = 128; // rounding for (shift by 8) +#if JVET_L0628_4TAP_INTRA + for( int k = -1; k > firstIdx; k-- ) +#else //JVET_L0628_4TAP_INTRA const int refMainOffsetPreScale = bIsModeVer ? height : width; for( int k = -1; k > (refMainOffsetPreScale * intraPredAngle) >> 5; k-- ) +#endif //JVET_L0628_4TAP_INTRA { invAngleSum += invAngle; refMain[k] = refSide[invAngleSum>>8]; } +#if JVET_L0628_4TAP_INTRA + refMain[lastIdx] = refMain[lastIdx-1]; + refMain[firstIdx] = refMain[firstIdx+1]; +#endif //JVET_L0628_4TAP_INTRA } else { for( int x = 0; x < m_topRefLength + 1; x++ ) { +#if JVET_L0628_4TAP_INTRA + refAbove[x+1] = pSrc.at(x, 0); +#else //JVET_L0628_4TAP_INTRA refAbove[x] = pSrc.at(x, 0); +#endif //JVET_L0628_4TAP_INTRA } for( int y = 0; y < m_leftRefLength + 1; y++ ) { +#if JVET_L0628_4TAP_INTRA + refLeft[y+1] = pSrc.at(0, y); +#else //JVET_L0628_4TAP_INTRA refLeft[y] = pSrc.at(0, y); +#endif //JVET_L0628_4TAP_INTRA } refMain = bIsModeVer ? refAbove : refLeft ; refSide = bIsModeVer ? refLeft : refAbove; + +#if JVET_L0628_4TAP_INTRA + refMain++; + refSide++; + refMain[-1] = refMain[0]; + auto lastIdx = 1 + ((bIsModeVer) ? m_topRefLength : m_leftRefLength); + refMain[lastIdx] = refMain[lastIdx-1]; +#endif //JVET_L0628_4TAP_INTRA } // swap width/height if we are doing a horizontal mode: @@ -584,12 +669,40 @@ void IntraPrediction::xPredIntraAng( const CPelBuf &pSrc, PelBuf &pDst, const Ch const int deltaInt = deltaPos >> 5; const int deltaFract = deltaPos & (32 - 1); -#if HM_4TAPIF_AS_IN_JEM +#if JVET_L0628_4TAP_INTRA + if( (absAng & (32 - 1)) != 0 ) // use 4-tap interpolation only for intra prediction modes with fractional displacements +#elif HM_4TAPIF_AS_IN_JEM if( deltaFract ) -#else +#else //JVET_L0628_4TAP_INTRA if( absAng < 32 ) #endif { +#if JVET_L0628_4TAP_INTRA + if( isLuma(channelType) ) + { + Pel p[4]; + const bool useCubicFilter = !useFilteredPredSamples; + TFilterCoeff const * const f = (useCubicFilter) ? InterpolationFilter::getChromaFilterTable(deltaFract) : g_intraGaussFilter[deltaFract]; + + int refMainIndex = deltaInt + 1; + + for( int x = 0; x < width; x++, refMainIndex++ ) + { + p[0] = refMain[refMainIndex - 1]; + p[1] = refMain[refMainIndex]; + p[2] = refMain[refMainIndex + 1]; + p[3] = refMain[refMainIndex + 2]; + + pDstBuf[y*dstStride + x] = static_cast<Pel>((static_cast<int>(f[0] * p[0]) + static_cast<int>(f[1] * p[1]) + static_cast<int>(f[2] * p[2]) + static_cast<int>(f[3] * p[3]) + 32) >> 6); + + if( useCubicFilter ) // only cubic filter has negative coefficients and requires clipping + { + pDstBuf[y*dstStride + x] = ClipPel( pDstBuf[y*dstStride + x], clpRng ); + } + } + } + else +#endif //JVET_L0628_4TAP_INTRA { // Do linear filtering const Pel *pRM = refMain + deltaInt + 1; diff --git a/source/Lib/CommonLib/IntraPrediction.h b/source/Lib/CommonLib/IntraPrediction.h index 8ff3a8ee50297f4116972e0fdf3914bf54b411e2..9d8002a8ce3d02c536ae836cb7c4fb8202fd241f 100644 --- a/source/Lib/CommonLib/IntraPrediction.h +++ b/source/Lib/CommonLib/IntraPrediction.h @@ -86,8 +86,12 @@ protected: void xPredIntraDc ( const CPelBuf &pSrc, PelBuf &pDst, const ChannelType channelType, const bool enableBoundaryFilter = true ); #if HEVC_USE_HOR_VER_PREDFILTERING void xPredIntraAng ( const CPelBuf &pSrc, PelBuf &pDst, const ChannelType channelType, const uint32_t dirMode, const ClpRng& clpRng, const bool bEnableEdgeFilters, const SPS& sps, const bool enableBoundaryFilter = true ); +#else +#if JVET_L0628_4TAP_INTRA + void xPredIntraAng ( const CPelBuf &pSrc, PelBuf &pDst, const ChannelType channelType, const uint32_t dirMode, const ClpRng& clpRng, const SPS& sps, const bool useFilteredPredSamples ); #else void xPredIntraAng ( const CPelBuf &pSrc, PelBuf &pDst, const ChannelType channelType, const uint32_t dirMode, const ClpRng& clpRng, const SPS& sps, const bool enableBoundaryFilter = true ); +#endif //JVET_L0628_4TAP_INTRA #endif Pel xGetPredValDc ( const CPelBuf &pSrc, const Size &dstSize ); diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index 55d43365e2db12d87b7eef10e7cf9a9648a8170c..d8e34d3bbdeeb7864ac7ad84f0b0e6bc8461d5f3 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -82,6 +82,8 @@ #define JVET_L0646_GBI 1 // Generalized bi-prediction (GBi) +#define JVET_L0628_4TAP_INTRA 1 // 4-tap intra-interpolation filtering with switching between Gaussian and DCT-IF filters for luma component + #define REUSE_CU_RESULTS 1 #define REMOVE_MV_ADAPT_PREC 1 // remove the high precision flag in the MV class