forked from mirror/libbpg
734 lines
24 KiB
C++
734 lines
24 KiB
C++
/* 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;
|
|
}
|
|
//! \}
|