diff jctvc/TLibCommon/TComPattern.cpp @ 0:772086c29cc7

Initial import.
author Matti Hamalainen <ccr@tnsp.org>
date Wed, 16 Nov 2016 11:16:33 +0200
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jctvc/TLibCommon/TComPattern.cpp	Wed Nov 16 11:16:33 2016 +0200
@@ -0,0 +1,734 @@
+/* The copyright in this software is being made available under the BSD
+ * License, included below. This software may be subject to other third party
+ * and contributor rights, including patent rights, and no such rights are
+ * granted under this license.
+ *
+ * Copyright (c) 2010-2014, ITU/ISO/IEC
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *  * Neither the name of the ITU/ISO/IEC nor the names of its contributors may
+ *    be used to endorse or promote products derived from this software without
+ *    specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** \file     TComPattern.cpp
+    \brief    neighbouring pixel access classes
+*/
+
+#include "TComPic.h"
+#include "TComPattern.h"
+#include "TComDataCU.h"
+#include "TComTU.h"
+#include "Debug.h"
+#include "TComPrediction.h"
+
+//! \ingroup TLibCommon
+//! \{
+
+// Forward declarations
+
+/// padding of unavailable reference samples for intra prediction
+#if O0043_BEST_EFFORT_DECODING
+Void fillReferenceSamples( const Int bitDepth, const Int bitDepthDelta, TComDataCU* pcCU, const Pel* piRoiOrigin, Pel* piAdiTemp, const Bool* bNeighborFlags,
+#else
+Void fillReferenceSamples( const Int bitDepth, TComDataCU* pcCU, const Pel* piRoiOrigin, Pel* piAdiTemp, const Bool* bNeighborFlags,
+#endif
+                           const Int iNumIntraNeighbor, const Int unitWidth, const Int unitHeight, const Int iAboveUnits, const Int iLeftUnits,
+                           const UInt uiCuWidth, const UInt uiCuHeight, const UInt uiWidth, const UInt uiHeight, const Int iPicStride,
+                           const ChannelType chType, const ChromaFormat chFmt );
+
+/// constrained intra prediction
+Bool  isAboveLeftAvailable  ( TComDataCU* pcCU, UInt uiPartIdxLT );
+Int   isAboveAvailable      ( TComDataCU* pcCU, UInt uiPartIdxLT, UInt uiPartIdxRT, Bool* bValidFlags );
+Int   isLeftAvailable       ( TComDataCU* pcCU, UInt uiPartIdxLT, UInt uiPartIdxLB, Bool* bValidFlags );
+Int   isAboveRightAvailable ( TComDataCU* pcCU, UInt uiPartIdxLT, UInt uiPartIdxRT, Bool* bValidFlags );
+Int   isBelowLeftAvailable  ( TComDataCU* pcCU, UInt uiPartIdxLT, UInt uiPartIdxLB, Bool* bValidFlags );
+
+
+// ====================================================================================================================
+// Public member functions (TComPatternParam)
+// ====================================================================================================================
+
+/** \param  piTexture     pixel data
+ \param  iRoiWidth     pattern width
+ \param  iRoiHeight    pattern height
+ \param  iStride       buffer stride
+ \param  iOffsetLeft   neighbour offset (left)
+ \param  iOffsetRight  neighbour offset (right)
+ \param  iOffsetAbove  neighbour offset (above)
+ \param  iOffsetBottom neighbour offset (bottom)
+ */
+Void TComPatternParam::setPatternParamPel ( Pel* piTexture,
+                                           Int iRoiWidth,
+                                           Int iRoiHeight,
+                                           Int iStride
+                                           )
+{
+  m_piROIOrigin    = piTexture;
+  m_iROIWidth       = iRoiWidth;
+  m_iROIHeight      = iRoiHeight;
+  m_iPatternStride  = iStride;
+}
+
+// ====================================================================================================================
+// Public member functions (TComPattern)
+// ====================================================================================================================
+
+Void TComPattern::initPattern (Pel* piY,
+                               Int iRoiWidth,
+                               Int iRoiHeight,
+                               Int iStride)
+{
+  m_cPatternY. setPatternParamPel( piY,  iRoiWidth, iRoiHeight, iStride);
+}
+
+
+// TODO: move this function to TComPrediction.cpp.
+Void TComPrediction::initAdiPatternChType( TComTU &rTu, Bool& bAbove, Bool& bLeft, const ComponentID compID, const Bool bFilterRefSamples DEBUG_STRING_FN_DECLARE(sDebug))
+{
+  const ChannelType chType    = toChannelType(compID);
+
+  TComDataCU *pcCU=rTu.getCU();
+  const UInt uiZorderIdxInPart=rTu.GetAbsPartIdxTU();
+  const UInt uiTuWidth        = rTu.getRect(compID).width;
+  const UInt uiTuHeight       = rTu.getRect(compID).height;
+  const UInt uiTuWidth2       = uiTuWidth  << 1;
+  const UInt uiTuHeight2      = uiTuHeight << 1;
+
+  const Int  iBaseUnitSize    = g_uiMaxCUWidth >> g_uiMaxCUDepth;
+  const Int  iUnitWidth       = iBaseUnitSize  >> pcCU->getPic()->getPicYuvRec()->getComponentScaleX(compID);
+  const Int  iUnitHeight      = iBaseUnitSize  >> pcCU->getPic()->getPicYuvRec()->getComponentScaleY(compID);
+  const Int  iTUWidthInUnits  = uiTuWidth  / iUnitWidth;
+  const Int  iTUHeightInUnits = uiTuHeight / iUnitHeight;
+  const Int  iAboveUnits      = iTUWidthInUnits  << 1;
+  const Int  iLeftUnits       = iTUHeightInUnits << 1;
+
+  assert(iTUHeightInUnits > 0 && iTUWidthInUnits > 0);
+
+  const Int  iPartIdxStride   = pcCU->getPic()->getNumPartInCtuWidth();
+  const UInt uiPartIdxLT      = pcCU->getZorderIdxInCtu() + uiZorderIdxInPart;
+  const UInt uiPartIdxRT      = g_auiRasterToZscan[ g_auiZscanToRaster[ uiPartIdxLT ] +   iTUWidthInUnits  - 1                   ];
+  const UInt uiPartIdxLB      = g_auiRasterToZscan[ g_auiZscanToRaster[ uiPartIdxLT ] + ((iTUHeightInUnits - 1) * iPartIdxStride)];
+
+  Int   iPicStride = pcCU->getPic()->getStride(compID);
+  Bool  bNeighborFlags[4 * MAX_NUM_SPU_W + 1];
+  Int   iNumIntraNeighbor = 0;
+
+  bNeighborFlags[iLeftUnits] = isAboveLeftAvailable( pcCU, uiPartIdxLT );
+  iNumIntraNeighbor += bNeighborFlags[iLeftUnits] ? 1 : 0;
+  iNumIntraNeighbor  += isAboveAvailable     ( pcCU, uiPartIdxLT, uiPartIdxRT, (bNeighborFlags + iLeftUnits + 1)                    );
+  iNumIntraNeighbor  += isAboveRightAvailable( pcCU, uiPartIdxLT, uiPartIdxRT, (bNeighborFlags + iLeftUnits + 1 + iTUWidthInUnits ) );
+  iNumIntraNeighbor  += isLeftAvailable      ( pcCU, uiPartIdxLT, uiPartIdxLB, (bNeighborFlags + iLeftUnits - 1)                    );
+  iNumIntraNeighbor  += isBelowLeftAvailable ( pcCU, uiPartIdxLT, uiPartIdxLB, (bNeighborFlags + iLeftUnits - 1 - iTUHeightInUnits) );
+
+  bAbove = true;
+  bLeft  = true;
+
+  const ChromaFormat chFmt       = rTu.GetChromaFormat();
+  const UInt         uiROIWidth  = uiTuWidth2+1;
+  const UInt         uiROIHeight = uiTuHeight2+1;
+
+  assert(uiROIWidth*uiROIHeight <= m_iYuvExtSize);
+
+#ifdef DEBUG_STRING
+  std::stringstream ss(stringstream::out);
+#endif
+
+  {
+    Pel *piAdiTemp   = m_piYuvExt[compID][PRED_BUF_UNFILTERED];
+    Pel *piRoiOrigin = pcCU->getPic()->getPicYuvRec()->getAddr(compID, pcCU->getCtuRsAddr(), pcCU->getZorderIdxInCtu()+uiZorderIdxInPart);
+#if O0043_BEST_EFFORT_DECODING
+    fillReferenceSamples (g_bitDepthInStream[chType], g_bitDepthInStream[chType] - g_bitDepth[chType], pcCU, piRoiOrigin, piAdiTemp, bNeighborFlags, iNumIntraNeighbor,  iUnitWidth, iUnitHeight, iAboveUnits, iLeftUnits,
+#else
+    fillReferenceSamples (g_bitDepth[chType], pcCU, piRoiOrigin, piAdiTemp, bNeighborFlags, iNumIntraNeighbor,  iUnitWidth, iUnitHeight, iAboveUnits, iLeftUnits,
+#endif
+                          uiTuWidth, uiTuHeight, uiROIWidth, uiROIHeight, iPicStride, toChannelType(compID), chFmt);
+
+
+#ifdef DEBUG_STRING
+    if (DebugOptionList::DebugString_Pred.getInt()&DebugStringGetPredModeMask(MODE_INTRA))
+    {
+      ss << "###: generating Ref Samples for channel " << compID << " and " << rTu.getRect(compID).width << " x " << rTu.getRect(compID).height << "\n";
+      for (UInt y=0; y<uiROIHeight; y++)
+      {
+        ss << "###: - ";
+        for (UInt x=0; x<uiROIWidth; x++)
+        {
+          if (x==0 || y==0)
+            ss << piAdiTemp[y*uiROIWidth + x] << ", ";
+//          if (x%16==15) ss << "\nPart size: ~ ";
+        }
+        ss << "\n";
+      }
+    }
+#endif
+
+    if (bFilterRefSamples)
+    {
+      // generate filtered intra prediction samples
+
+            Int          stride    = uiROIWidth;
+      const Pel         *piSrcPtr  = piAdiTemp                             + (stride * uiTuHeight2); // bottom left
+            Pel         *piDestPtr = m_piYuvExt[compID][PRED_BUF_FILTERED] + (stride * uiTuHeight2); // bottom left
+
+      //------------------------------------------------
+
+      Bool useStrongIntraSmoothing = isLuma(chType) && pcCU->getSlice()->getSPS()->getUseStrongIntraSmoothing();
+
+      const Pel bottomLeft = piAdiTemp[stride * uiTuHeight2];
+      const Pel topLeft    = piAdiTemp[0];
+      const Pel topRight   = piAdiTemp[uiTuWidth2];
+
+      if (useStrongIntraSmoothing)
+      {
+#if O0043_BEST_EFFORT_DECODING
+        const Int  threshold     = 1 << (g_bitDepthInStream[chType] - 5);
+#else
+        const Int  threshold     = 1 << (g_bitDepth[chType] - 5);
+#endif
+        const Bool bilinearLeft  = abs((bottomLeft + topLeft ) - (2 * piAdiTemp[stride * uiTuHeight])) < threshold; //difference between the
+        const Bool bilinearAbove = abs((topLeft    + topRight) - (2 * piAdiTemp[         uiTuWidth ])) < threshold; //ends and the middle
+        if ((uiTuWidth < 32) || (!bilinearLeft) || (!bilinearAbove))
+          useStrongIntraSmoothing = false;
+      }
+
+      *piDestPtr = *piSrcPtr; // bottom left is not filtered
+      piDestPtr -= stride;
+      piSrcPtr  -= stride;
+
+      //------------------------------------------------
+
+      //left column (bottom to top)
+
+      if (useStrongIntraSmoothing)
+      {
+        const Int shift = g_aucConvertToBit[uiTuHeight] + 3; //log2(uiTuHeight2)
+
+        for(UInt i=1; i<uiTuHeight2; i++, piDestPtr-=stride)
+        {
+          *piDestPtr = (((uiTuHeight2 - i) * bottomLeft) + (i * topLeft) + uiTuHeight) >> shift;
+        }
+
+        piSrcPtr -= stride * (uiTuHeight2 - 1);
+      }
+      else
+      {
+        for(UInt i=1; i<uiTuHeight2; i++, piDestPtr-=stride, piSrcPtr-=stride)
+        {
+          *piDestPtr = ( piSrcPtr[stride] + 2*piSrcPtr[0] + piSrcPtr[-stride] + 2 ) >> 2;
+        }
+      }
+
+      //------------------------------------------------
+
+      //top-left
+
+      if (useStrongIntraSmoothing)
+      {
+        *piDestPtr = piSrcPtr[0];
+      }
+      else
+      {
+        *piDestPtr = ( piSrcPtr[stride] + 2*piSrcPtr[0] + piSrcPtr[1] + 2 ) >> 2;
+      }
+      piDestPtr += 1;
+      piSrcPtr  += 1;
+
+      //------------------------------------------------
+
+      //top row (left-to-right)
+
+      if (useStrongIntraSmoothing)
+      {
+        const Int shift = g_aucConvertToBit[uiTuWidth] + 3; //log2(uiTuWidth2)
+
+        for(UInt i=1; i<uiTuWidth2; i++, piDestPtr++)
+        {
+          *piDestPtr = (((uiTuWidth2 - i) * topLeft) + (i * topRight) + uiTuWidth) >> shift;
+        }
+
+        piSrcPtr += uiTuWidth2 - 1;
+      }
+      else
+      {
+        for(UInt i=1; i<uiTuWidth2; i++, piDestPtr++, piSrcPtr++)
+        {
+          *piDestPtr = ( piSrcPtr[1] + 2*piSrcPtr[0] + piSrcPtr[-1] + 2 ) >> 2;
+        }
+      }
+
+      //------------------------------------------------
+
+      *piDestPtr=*piSrcPtr; // far right is not filtered
+
+#ifdef DEBUG_STRING
+    if (DebugOptionList::DebugString_Pred.getInt()&DebugStringGetPredModeMask(MODE_INTRA))
+    {
+      ss << "###: filtered result for channel " << compID <<"\n";
+      for (UInt y=0; y<uiROIHeight; y++)
+      {
+        ss << "###: - ";
+        for (UInt x=0; x<uiROIWidth; x++)
+        {
+          if (x==0 || y==0)
+            ss << m_piYuvExt[compID][PRED_BUF_FILTERED][y*uiROIWidth + x] << ", ";
+//          if (x%16==15) ss << "\nPart size: ~ ";
+        }
+        ss << "\n";
+      }
+    }
+#endif
+
+
+    }
+  }
+  DEBUG_STRING_APPEND(sDebug, ss.str())
+}
+
+#if O0043_BEST_EFFORT_DECODING
+Void fillReferenceSamples( const Int bitDepth, const Int bitDepthDelta, TComDataCU* pcCU, const Pel* piRoiOrigin, Pel* piAdiTemp, const Bool* bNeighborFlags,
+#else
+Void fillReferenceSamples( const Int bitDepth, TComDataCU* pcCU, const Pel* piRoiOrigin, Pel* piAdiTemp, const Bool* bNeighborFlags,
+#endif
+                           const Int iNumIntraNeighbor, const Int unitWidth, const Int unitHeight, const Int iAboveUnits, const Int iLeftUnits,
+                           const UInt uiCuWidth, const UInt uiCuHeight, const UInt uiWidth, const UInt uiHeight, const Int iPicStride,
+                           const ChannelType chType, const ChromaFormat chFmt )
+{
+  const Pel* piRoiTemp;
+  Int  i, j;
+  Int  iDCValue = 1 << (bitDepth - 1);
+  const Int iTotalUnits = iAboveUnits + iLeftUnits + 1; //+1 for top-left
+
+  if (iNumIntraNeighbor == 0)
+  {
+    // Fill border with DC value
+    for (i=0; i<uiWidth; i++)
+    {
+      piAdiTemp[i] = iDCValue;
+    }
+    for (i=1; i<uiHeight; i++)
+    {
+      piAdiTemp[i*uiWidth] = iDCValue;
+    }
+  }
+  else if (iNumIntraNeighbor == iTotalUnits)
+  {
+    // Fill top-left border and top and top right with rec. samples
+    piRoiTemp = piRoiOrigin - iPicStride - 1;
+
+    for (i=0; i<uiWidth; i++)
+    {
+#if O0043_BEST_EFFORT_DECODING
+      piAdiTemp[i] = piRoiTemp[i] << bitDepthDelta;
+#else
+      piAdiTemp[i] = piRoiTemp[i];
+#endif
+    }
+
+    // Fill left and below left border with rec. samples
+    piRoiTemp = piRoiOrigin - 1;
+
+    for (i=1; i<uiHeight; i++)
+    {
+#if O0043_BEST_EFFORT_DECODING
+      piAdiTemp[i*uiWidth] = (*(piRoiTemp)) << bitDepthDelta;
+#else
+      piAdiTemp[i*uiWidth] = *(piRoiTemp);
+#endif
+      piRoiTemp += iPicStride;
+    }
+  }
+  else // reference samples are partially available
+  {
+    // all above units have "unitWidth" samples each, all left/below-left units have "unitHeight" samples each
+    const Int  iTotalSamples = (iLeftUnits * unitHeight) + ((iAboveUnits + 1) * unitWidth);
+    Pel  piAdiLine[5 * MAX_CU_SIZE];
+    Pel  *piAdiLineTemp;
+    const Bool *pbNeighborFlags;
+
+
+    // Initialize
+    for (i=0; i<iTotalSamples; i++)
+    {
+      piAdiLine[i] = iDCValue;
+    }
+
+    // Fill top-left sample
+    piRoiTemp = piRoiOrigin - iPicStride - 1;
+    piAdiLineTemp = piAdiLine + (iLeftUnits * unitHeight);
+    pbNeighborFlags = bNeighborFlags + iLeftUnits;
+    if (*pbNeighborFlags)
+    {
+#if O0043_BEST_EFFORT_DECODING
+      Pel topLeftVal=piRoiTemp[0] << bitDepthDelta;
+#else
+      Pel topLeftVal=piRoiTemp[0];
+#endif
+      for (i=0; i<unitWidth; i++)
+      {
+        piAdiLineTemp[i] = topLeftVal;
+      }
+    }
+
+    // Fill left & below-left samples (downwards)
+    piRoiTemp += iPicStride;
+    piAdiLineTemp--;
+    pbNeighborFlags--;
+
+    for (j=0; j<iLeftUnits; j++)
+    {
+      if (*pbNeighborFlags)
+      {
+        for (i=0; i<unitHeight; i++)
+        {
+#if O0043_BEST_EFFORT_DECODING
+          piAdiLineTemp[-i] = piRoiTemp[i*iPicStride] << bitDepthDelta;
+#else
+          piAdiLineTemp[-i] = piRoiTemp[i*iPicStride];
+#endif
+        }
+      }
+      piRoiTemp += unitHeight*iPicStride;
+      piAdiLineTemp -= unitHeight;
+      pbNeighborFlags--;
+    }
+
+    // Fill above & above-right samples (left-to-right) (each unit has "unitWidth" samples)
+    piRoiTemp = piRoiOrigin - iPicStride;
+    // offset line buffer by iNumUints2*unitHeight (for left/below-left) + unitWidth (for above-left)
+    piAdiLineTemp = piAdiLine + (iLeftUnits * unitHeight) + unitWidth;
+    pbNeighborFlags = bNeighborFlags + iLeftUnits + 1;
+    for (j=0; j<iAboveUnits; j++)
+    {
+      if (*pbNeighborFlags)
+      {
+        for (i=0; i<unitWidth; i++)
+        {
+#if O0043_BEST_EFFORT_DECODING
+          piAdiLineTemp[i] = piRoiTemp[i] << bitDepthDelta;
+#else
+          piAdiLineTemp[i] = piRoiTemp[i];
+#endif
+        }
+      }
+      piRoiTemp += unitWidth;
+      piAdiLineTemp += unitWidth;
+      pbNeighborFlags++;
+    }
+
+    // Pad reference samples when necessary
+    Int iCurrJnit = 0;
+    Pel  *piAdiLineCur   = piAdiLine;
+    const UInt piAdiLineTopRowOffset = iLeftUnits * (unitHeight - unitWidth);
+
+    if (!bNeighborFlags[0])
+    {
+      // very bottom unit of bottom-left; at least one unit will be valid.
+      {
+        Int   iNext = 1;
+        while (iNext < iTotalUnits && !bNeighborFlags[iNext])
+        {
+          iNext++;
+        }
+        Pel *piAdiLineNext = piAdiLine + ((iNext < iLeftUnits) ? (iNext * unitHeight) : (piAdiLineTopRowOffset + (iNext * unitWidth)));
+        const Pel refSample = *piAdiLineNext;
+        // Pad unavailable samples with new value
+        Int iNextOrTop = std::min<Int>(iNext, iLeftUnits);
+        // fill left column
+        while (iCurrJnit < iNextOrTop)
+        {
+          for (i=0; i<unitHeight; i++)
+          {
+            piAdiLineCur[i] = refSample;
+          }
+          piAdiLineCur += unitHeight;
+          iCurrJnit++;
+        }
+        // fill top row
+        while (iCurrJnit < iNext)
+        {
+          for (i=0; i<unitWidth; i++)
+          {
+            piAdiLineCur[i] = refSample;
+          }
+          piAdiLineCur += unitWidth;
+          iCurrJnit++;
+        }
+      }
+    }
+
+    // pad all other reference samples.
+    while (iCurrJnit < iTotalUnits)
+    {
+      if (!bNeighborFlags[iCurrJnit]) // samples not available
+      {
+        {
+          const Int numSamplesInCurrUnit = (iCurrJnit >= iLeftUnits) ? unitWidth : unitHeight;
+          const Pel refSample = *(piAdiLineCur-1);
+          for (i=0; i<numSamplesInCurrUnit; i++)
+          {
+            piAdiLineCur[i] = refSample;
+          }
+          piAdiLineCur += numSamplesInCurrUnit;
+          iCurrJnit++;
+        }
+      }
+      else
+      {
+        piAdiLineCur += (iCurrJnit >= iLeftUnits) ? unitWidth : unitHeight;
+        iCurrJnit++;
+      }
+    }
+
+    // Copy processed samples
+
+    piAdiLineTemp = piAdiLine + uiHeight + unitWidth - 2;
+    // top left, top and top right samples
+    for (i=0; i<uiWidth; i++)
+    {
+      piAdiTemp[i] = piAdiLineTemp[i];
+    }
+
+    piAdiLineTemp = piAdiLine + uiHeight - 1;
+    for (i=1; i<uiHeight; i++)
+    {
+      piAdiTemp[i*uiWidth] = piAdiLineTemp[-i];
+    }
+  }
+}
+
+/** Get pointer to reference samples for intra prediction
+ * \param uiDirMode   prediction mode index
+ * \param log2BlkSize size of block (2 = 4x4, 3 = 8x8, 4 = 16x16, 5 = 32x32, 6 = 64x64)
+ * \param piAdiBuf    pointer to unfiltered reference samples
+ * \return            pointer to (possibly filtered) reference samples
+ *
+ * The prediction mode index is used to determine whether a smoothed reference sample buffer is returned.
+ */
+
+Bool TComPrediction::filteringIntraReferenceSamples(const ComponentID compID, UInt uiDirMode, UInt uiTuChWidth, UInt uiTuChHeight, const ChromaFormat chFmt, const Bool intraReferenceSmoothingDisabled)
+{
+  Bool bFilter;
+
+  if (!filterIntraReferenceSamples(toChannelType(compID), chFmt, intraReferenceSmoothingDisabled))
+  {
+    bFilter=false;
+  }
+  else
+  {
+    assert(uiTuChWidth>=4 && uiTuChHeight>=4 && uiTuChWidth<128 && uiTuChHeight<128);
+
+    if (uiDirMode == DC_IDX)
+    {
+      bFilter=false; //no smoothing for DC or LM chroma
+    }
+    else
+    {
+      Int diff = min<Int>(abs((Int) uiDirMode - HOR_IDX), abs((Int)uiDirMode - VER_IDX));
+      UInt sizeIndex=g_aucConvertToBit[uiTuChWidth];
+      assert(sizeIndex < MAX_INTRA_FILTER_DEPTHS);
+      bFilter = diff > m_aucIntraFilter[toChannelType(compID)][sizeIndex];
+    }
+  }
+  return bFilter;
+}
+
+Bool isAboveLeftAvailable( TComDataCU* pcCU, UInt uiPartIdxLT )
+{
+  Bool bAboveLeftFlag;
+  UInt uiPartAboveLeft;
+  TComDataCU* pcCUAboveLeft = pcCU->getPUAboveLeft( uiPartAboveLeft, uiPartIdxLT );
+  if(pcCU->getSlice()->getPPS()->getConstrainedIntraPred())
+  {
+    bAboveLeftFlag = ( pcCUAboveLeft && pcCUAboveLeft->isIntra( uiPartAboveLeft ) );
+  }
+  else
+  {
+    bAboveLeftFlag = (pcCUAboveLeft ? true : false);
+  }
+  return bAboveLeftFlag;
+}
+
+Int isAboveAvailable( TComDataCU* pcCU, UInt uiPartIdxLT, UInt uiPartIdxRT, Bool *bValidFlags )
+{
+  const UInt uiRasterPartBegin = g_auiZscanToRaster[uiPartIdxLT];
+  const UInt uiRasterPartEnd = g_auiZscanToRaster[uiPartIdxRT]+1;
+  const UInt uiIdxStep = 1;
+  Bool *pbValidFlags = bValidFlags;
+  Int iNumIntra = 0;
+
+  for ( UInt uiRasterPart = uiRasterPartBegin; uiRasterPart < uiRasterPartEnd; uiRasterPart += uiIdxStep )
+  {
+    UInt uiPartAbove;
+    TComDataCU* pcCUAbove = pcCU->getPUAbove( uiPartAbove, g_auiRasterToZscan[uiRasterPart] );
+    if(pcCU->getSlice()->getPPS()->getConstrainedIntraPred())
+    {
+      if ( pcCUAbove && pcCUAbove->isIntra( uiPartAbove ) )
+      {
+        iNumIntra++;
+        *pbValidFlags = true;
+      }
+      else
+      {
+        *pbValidFlags = false;
+      }
+    }
+    else
+    {
+      if (pcCUAbove)
+      {
+        iNumIntra++;
+        *pbValidFlags = true;
+      }
+      else
+      {
+        *pbValidFlags = false;
+      }
+    }
+    pbValidFlags++;
+  }
+  return iNumIntra;
+}
+
+Int isLeftAvailable( TComDataCU* pcCU, UInt uiPartIdxLT, UInt uiPartIdxLB, Bool *bValidFlags )
+{
+  const UInt uiRasterPartBegin = g_auiZscanToRaster[uiPartIdxLT];
+  const UInt uiRasterPartEnd = g_auiZscanToRaster[uiPartIdxLB]+1;
+  const UInt uiIdxStep = pcCU->getPic()->getNumPartInCtuWidth();
+  Bool *pbValidFlags = bValidFlags;
+  Int iNumIntra = 0;
+
+  for ( UInt uiRasterPart = uiRasterPartBegin; uiRasterPart < uiRasterPartEnd; uiRasterPart += uiIdxStep )
+  {
+    UInt uiPartLeft;
+    TComDataCU* pcCULeft = pcCU->getPULeft( uiPartLeft, g_auiRasterToZscan[uiRasterPart] );
+    if(pcCU->getSlice()->getPPS()->getConstrainedIntraPred())
+    {
+      if ( pcCULeft && pcCULeft->isIntra( uiPartLeft ) )
+      {
+        iNumIntra++;
+        *pbValidFlags = true;
+      }
+      else
+      {
+        *pbValidFlags = false;
+      }
+    }
+    else
+    {
+      if ( pcCULeft )
+      {
+        iNumIntra++;
+        *pbValidFlags = true;
+      }
+      else
+      {
+        *pbValidFlags = false;
+      }
+    }
+    pbValidFlags--; // opposite direction
+  }
+
+  return iNumIntra;
+}
+
+Int isAboveRightAvailable( TComDataCU* pcCU, UInt uiPartIdxLT, UInt uiPartIdxRT, Bool *bValidFlags )
+{
+  const UInt uiNumUnitsInPU = g_auiZscanToRaster[uiPartIdxRT] - g_auiZscanToRaster[uiPartIdxLT] + 1;
+  Bool *pbValidFlags = bValidFlags;
+  Int iNumIntra = 0;
+
+  for ( UInt uiOffset = 1; uiOffset <= uiNumUnitsInPU; uiOffset++ )
+  {
+    UInt uiPartAboveRight;
+    TComDataCU* pcCUAboveRight = pcCU->getPUAboveRightAdi( uiPartAboveRight, uiPartIdxRT, uiOffset );
+    if(pcCU->getSlice()->getPPS()->getConstrainedIntraPred())
+    {
+      if ( pcCUAboveRight && pcCUAboveRight->isIntra( uiPartAboveRight ) )
+      {
+        iNumIntra++;
+        *pbValidFlags = true;
+      }
+      else
+      {
+        *pbValidFlags = false;
+      }
+    }
+    else
+    {
+      if ( pcCUAboveRight )
+      {
+        iNumIntra++;
+        *pbValidFlags = true;
+      }
+      else
+      {
+        *pbValidFlags = false;
+      }
+    }
+    pbValidFlags++;
+  }
+
+  return iNumIntra;
+}
+
+Int isBelowLeftAvailable( TComDataCU* pcCU, UInt uiPartIdxLT, UInt uiPartIdxLB, Bool *bValidFlags )
+{
+  const UInt uiNumUnitsInPU = (g_auiZscanToRaster[uiPartIdxLB] - g_auiZscanToRaster[uiPartIdxLT]) / pcCU->getPic()->getNumPartInCtuWidth() + 1;
+  Bool *pbValidFlags = bValidFlags;
+  Int iNumIntra = 0;
+
+  for ( UInt uiOffset = 1; uiOffset <= uiNumUnitsInPU; uiOffset++ )
+  {
+    UInt uiPartBelowLeft;
+    TComDataCU* pcCUBelowLeft = pcCU->getPUBelowLeftAdi( uiPartBelowLeft, uiPartIdxLB, uiOffset );
+    if(pcCU->getSlice()->getPPS()->getConstrainedIntraPred())
+    {
+      if ( pcCUBelowLeft && pcCUBelowLeft->isIntra( uiPartBelowLeft ) )
+      {
+        iNumIntra++;
+        *pbValidFlags = true;
+      }
+      else
+      {
+        *pbValidFlags = false;
+      }
+    }
+    else
+    {
+      if ( pcCUBelowLeft )
+      {
+        iNumIntra++;
+        *pbValidFlags = true;
+      }
+      else
+      {
+        *pbValidFlags = false;
+      }
+    }
+    pbValidFlags--; // opposite direction
+  }
+
+  return iNumIntra;
+}
+//! \}