Newer
Older

Karsten Suehring
committed
/* 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-2019, ITU/ISO/IEC

Karsten Suehring
committed
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
* 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 Prediction.cpp
\brief prediction class
*/
#include "IntraPrediction.h"
#include "Unit.h"
#include "UnitTools.h"
#include "Buffer.h"
#include "dtrace_next.h"
#include "Rom.h"
#include <memory.h>
#include "CommonLib/InterpolationFilter.h"

Karsten Suehring
committed
//! \ingroup CommonLib
//! \{
// ====================================================================================================================
// Tables
// ====================================================================================================================
const uint8_t IntraPrediction::m_aucIntraFilter[MAX_INTRA_FILTER_DEPTHS] =

Karsten Suehring
committed
{
24, // 1xn
24, // 2xn
24, // 4xn
14, // 8xn
2, // 16xn
0, // 32xn
0, // 64xn
0 // 128xn

Karsten Suehring
committed
};
#if !JVET_P0599_INTRA_SMOOTHING_INTERP_FILT
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 },

Christian Helmrich
committed
{ 3, 17, 29, 15 }
#endif //!JVET_P0599_INTRA_SMOOTHING_INTERP_FILT

Karsten Suehring
committed
// ====================================================================================================================
// Constructor / destructor / initialize
// ====================================================================================================================
IntraPrediction::IntraPrediction()
:
m_currChromaFormat( NUM_CHROMA_FORMAT )
{
for (uint32_t ch = 0; ch < MAX_NUM_COMPONENT; ch++)
{
for (uint32_t buf = 0; buf < 4; buf++)
{
m_yuvExt2[ch][buf] = nullptr;
}
}

Karsten Suehring
committed
m_piTemp = nullptr;
#if !JVET_P0077_LINE_CG_PALETTE

Karsten Suehring
committed
}
IntraPrediction::~IntraPrediction()
{
destroy();
}
void IntraPrediction::destroy()
{
for (uint32_t ch = 0; ch < MAX_NUM_COMPONENT; ch++)
{
for (uint32_t buf = 0; buf < 4; buf++)
{
delete[] m_yuvExt2[ch][buf];
m_yuvExt2[ch][buf] = nullptr;
}
}

Karsten Suehring
committed
delete[] m_piTemp;
m_piTemp = nullptr;
delete[] m_pMdlmTemp;
m_pMdlmTemp = nullptr;
#if !JVET_P0077_LINE_CG_PALETTE
if (m_runTypeRD) { xFree( m_runTypeRD ); m_runTypeRD = NULL; }
if (m_runLengthRD) { xFree( m_runLengthRD); m_runLengthRD = NULL; }

Karsten Suehring
committed
}
void IntraPrediction::init(ChromaFormat chromaFormatIDC, const unsigned bitDepthY)
{
if (m_yuvExt2[COMPONENT_Y][0] != nullptr && m_currChromaFormat != chromaFormatIDC)
{
destroy();
}

Karsten Suehring
committed
m_currChromaFormat = chromaFormatIDC;
if (m_yuvExt2[COMPONENT_Y][0] == nullptr) // check if first is null (in which case, nothing initialised yet)
{
m_yuvExtSize2 = (MAX_CU_SIZE) * (MAX_CU_SIZE);
for (uint32_t ch = 0; ch < MAX_NUM_COMPONENT; ch++)
{
for (uint32_t buf = 0; buf < 4; buf++)
{
m_yuvExt2[ch][buf] = new Pel[m_yuvExtSize2];
}
}
}

Karsten Suehring
committed
if (m_piTemp == nullptr)
{
m_piTemp = new Pel[(MAX_CU_SIZE + 1) * (MAX_CU_SIZE + 1)];
}
if (m_pMdlmTemp == nullptr)
{
m_pMdlmTemp = new Pel[(2 * MAX_CU_SIZE + 1)*(2 * MAX_CU_SIZE + 1)];//MDLM will use top-above and left-below samples.
}
#if !JVET_P0077_LINE_CG_PALETTE
if (m_runTypeRD == nullptr)
{
m_runTypeRD = (bool *) xMalloc(bool, MAX_CU_SIZE * MAX_CU_SIZE);
}
if (m_runLengthRD == nullptr)
{
m_runLengthRD = (Pel *) xMalloc(Pel, MAX_CU_SIZE * MAX_CU_SIZE);
}

Karsten Suehring
committed
}
// ====================================================================================================================
// Public member functions
// ====================================================================================================================
// Function for calculating DC value of the reference samples used in Intra prediction
//NOTE: Bit-Limit - 25-bit source
Pel IntraPrediction::xGetPredValDc( const CPelBuf &pSrc, const Size &dstSize )
{
CHECK( dstSize.width == 0 || dstSize.height == 0, "Empty area provided" );
int idx, sum = 0;
Pel dcVal;
const int width = dstSize.width;
const int height = dstSize.height;
const auto denom = (width == height) ? (width << 1) : std::max(width,height);
const auto divShift = floorLog2(denom);

Karsten Suehring
committed
const auto divOffset = (denom >> 1);
if ( width >= height )
{

Christian Helmrich
committed
for( idx = 0; idx < width; idx++ )
{
Adarsh Krishnan Ramasubramonian
committed
sum += pSrc.at(m_ipaParam.multiRefIndex + 1 + idx, 0);

Christian Helmrich
committed
}

Karsten Suehring
committed
}
if ( width <= height )
{

Christian Helmrich
committed
for( idx = 0; idx < height; idx++ )
{
sum += pSrc.at(m_ipaParam.multiRefIndex + 1 + idx, 1);

Christian Helmrich
committed
}

Karsten Suehring
committed
}
dcVal = (sum + divOffset) >> divShift;
return dcVal;
}
int IntraPrediction::getWideAngle( int width, int height, int predMode )
{
if ( predMode > DC_IDX && predMode <= VDIA_IDX )

Karsten Suehring
committed
{
int modeShift[] = { 0, 6, 10, 12, 14, 15 };
int deltaSize = abs(floorLog2(width) - floorLog2(height));
if (width > height && predMode < 2 + modeShift[deltaSize])

Karsten Suehring
committed
{
predMode += (VDIA_IDX - 1);
}
else if (height > width && predMode > VDIA_IDX - modeShift[deltaSize])
{
predMode -= (VDIA_IDX - 1);

Karsten Suehring
committed
}
}

Karsten Suehring
committed
void IntraPrediction::setReferenceArrayLengths( const CompArea &area )
{
// set Top and Left reference samples length
const int width = area.width;
const int height = area.height;

Karsten Suehring
committed
m_leftRefLength = (height << 1);
m_topRefLength = (width << 1);

Karsten Suehring
committed

Karsten Suehring
committed
Alexey Filippov
committed
void IntraPrediction::predIntraAng( const ComponentID compId, PelBuf &piPred, const PredictionUnit &pu)

Karsten Suehring
committed
{
const ComponentID compID = MAP_CHROMA( compId );
const ChannelType channelType = toChannelType( compID );
const int iWidth = piPred.width;
const int iHeight = piPred.height;
#if JVET_P0641_REMOVE_2xN_CHROMA_INTRA
CHECK(iWidth == 2, "Width of 2 is not supported");
#endif
#if JVET_P0059_CHROMA_BDPCM
const uint32_t uiDirMode = isLuma( compId ) && pu.cu->bdpcmMode ? BDPCM_IDX : !isLuma(compId) && pu.cu->bdpcmModeChroma ? BDPCM_IDX : PU::getFinalIntraMode(pu, channelType);
#else
const uint32_t uiDirMode = isLuma( compId ) && pu.cu->bdpcmMode ? BDPCM_IDX : PU::getFinalIntraMode( pu, channelType );

Karsten Suehring
committed
CHECK( floorLog2(iWidth) < 2 && pu.cs->pcv->noChroma2x2, "Size not allowed" );
CHECK( floorLog2(iWidth) > 7, "Size not allowed" );
const int srcStride = m_refBufferStride[compID];
const int srcHStride = 2;
Alexey Filippov
committed
const CPelBuf & srcBuf = CPelBuf(getPredictorPtr(compID), srcStride, srcHStride);

Karsten Suehring
committed
const ClpRng& clpRng(pu.cu->cs->slice->clpRng(compID));
switch (uiDirMode)
{
Alexey Filippov
committed
case(PLANAR_IDX): xPredIntraPlanar(srcBuf, piPred); break;
case(DC_IDX): xPredIntraDc(srcBuf, piPred, channelType, false); break;
#if JVET_P0059_CHROMA_BDPCM
case(BDPCM_IDX): xPredIntraBDPCM(srcBuf, piPred, isLuma(compID) ? pu.cu->bdpcmMode : pu.cu->bdpcmModeChroma, clpRng); break;
#else
case(BDPCM_IDX): xPredIntraBDPCM(srcBuf, piPred, pu.cu->bdpcmMode, clpRng); break;
Alexey Filippov
committed
default: xPredIntraAng(srcBuf, piPred, channelType, clpRng); break;

Karsten Suehring
committed
}
Alexey Filippov
committed
if (m_ipaParam.applyPDPC)

Karsten Suehring
committed
{
PelBuf dstBuf = piPred;
const int scale = ((floorLog2(iWidth) - 2 + floorLog2(iHeight) - 2 + 2) >> 2);

Karsten Suehring
committed
CHECK(scale < 0 || scale > 31, "PDPC: scale < 0 || scale > 31");
if (uiDirMode == PLANAR_IDX || uiDirMode == DC_IDX)

Karsten Suehring
committed
{
for (int y = 0; y < iHeight; y++)
{
const int wT = 32 >> std::min(31, ((y << 1) >> scale));
const Pel left = srcBuf.at(y + 1, 1);

Karsten Suehring
committed
for (int x = 0; x < iWidth; x++)
{
const int wL = 32 >> std::min(31, ((x << 1) >> scale));
const Pel top = srcBuf.at(x + 1, 0);
const Pel val = dstBuf.at(x, y);
dstBuf.at(x, y) = val + ((wL * (left - val) + wT * (top - val) + 32) >> 6);

Karsten Suehring
committed
}
}
}
}
}

Karsten Suehring
committed
void IntraPrediction::predIntraChromaLM(const ComponentID compID, PelBuf &piPred, const PredictionUnit &pu, const CompArea& chromaArea, int intraDir)
{
int iLumaStride = 0;
PelBuf Temp;
if ((intraDir == MDLM_L_IDX) || (intraDir == MDLM_T_IDX))
{
iLumaStride = 2 * MAX_CU_SIZE + 1;
Temp = PelBuf(m_pMdlmTemp + iLumaStride + 1, iLumaStride, Size(chromaArea));
}
else
{
iLumaStride = MAX_CU_SIZE + 1;
Temp = PelBuf(m_piTemp + iLumaStride + 1, iLumaStride, Size(chromaArea));

Karsten Suehring
committed
int a, b, iShift;
xGetLMParameters(pu, compID, chromaArea, a, b, iShift);
////// final prediction
piPred.copyFrom(Temp);
piPred.linearTransform(a, iShift, b, true, pu.cs->slice->clpRng(compID));
}
/** Function for deriving planar intra prediction. This function derives the prediction samples for planar mode (intra coding).
*/
//NOTE: Bit-Limit - 24-bit source
Alexey Filippov
committed
void IntraPrediction::xPredIntraPlanar( const CPelBuf &pSrc, PelBuf &pDst )

Karsten Suehring
committed
{
const uint32_t width = pDst.width;
const uint32_t height = pDst.height;
#if JVET_P0329_PLANAR_SIMPLIFICATION
const uint32_t log2W = floorLog2( width );
const uint32_t log2H = floorLog2( height );
#else
const uint32_t log2W = floorLog2(width < 2 ? 2 : width);
const uint32_t log2H = floorLog2(height < 2 ? 2 : height);

Karsten Suehring
committed
int leftColumn[MAX_CU_SIZE + 1], topRow[MAX_CU_SIZE + 1], bottomRow[MAX_CU_SIZE], rightColumn[MAX_CU_SIZE];
const uint32_t offset = 1 << (log2W + log2H);

Karsten Suehring
committed
// Get left and above reference column and row
for( int k = 0; k < width + 1; k++ )
{
topRow[k] = pSrc.at( k + 1, 0 );
}
for( int k = 0; k < height + 1; k++ )
{
leftColumn[k] = pSrc.at(k + 1, 1);

Karsten Suehring
committed
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
}
// Prepare intermediate variables used in interpolation
int bottomLeft = leftColumn[height];
int topRight = topRow[width];
for( int k = 0; k < width; k++ )
{
bottomRow[k] = bottomLeft - topRow[k];
topRow[k] = topRow[k] << log2H;
}
for( int k = 0; k < height; k++ )
{
rightColumn[k] = topRight - leftColumn[k];
leftColumn[k] = leftColumn[k] << log2W;
}
const uint32_t finalShift = 1 + log2W + log2H;
const uint32_t stride = pDst.stride;
Pel* pred = pDst.buf;
for( int y = 0; y < height; y++, pred += stride )
{
int horPred = leftColumn[y];
for( int x = 0; x < width; x++ )
{
horPred += rightColumn[y];
topRow[x] += bottomRow[x];
int vertPred = topRow[x];
pred[x] = ( ( horPred << log2H ) + ( vertPred << log2W ) + offset ) >> finalShift;
}
}
}
void IntraPrediction::xPredIntraDc( const CPelBuf &pSrc, PelBuf &pDst, const ChannelType channelType, const bool enableBoundaryFilter )
{
const Pel dcval = xGetPredValDc( pSrc, pDst );
pDst.fill( dcval );
}
Alexey Filippov
committed
// Function for initialization of intra prediction parameters
void IntraPrediction::initPredIntraParams(const PredictionUnit & pu, const CompArea area, const SPS& sps)
{
const ComponentID compId = area.compID;
const ChannelType chType = toChannelType(compId);
const bool useISP = NOT_INTRA_SUBPARTITIONS != pu.cu->ispMode && isLuma( chType );
const Size cuSize = Size( pu.cu->blocks[compId].width, pu.cu->blocks[compId].height );
const Size puSize = Size( area.width, area.height );
const Size& blockSize = useISP ? cuSize : puSize;
const int dirMode = PU::getFinalIntraMode(pu, chType);
const int predMode = getWideAngle( blockSize.width, blockSize.height, dirMode );
m_ipaParam.isModeVer = predMode >= DIA_IDX;
m_ipaParam.multiRefIndex = isLuma (chType) ? pu.multiRefIdx : 0 ;
m_ipaParam.refFilterFlag = false;
m_ipaParam.interpolationFlag = false;
m_ipaParam.applyPDPC = ((puSize.width >= MIN_TB_SIZEY && puSize.height >= MIN_TB_SIZEY) || !isLuma(compId)) && m_ipaParam.multiRefIndex == 0;
Alexey Filippov
committed
const int intraPredAngleMode = (m_ipaParam.isModeVer) ? predMode - VER_IDX : -(predMode - HOR_IDX);
int absAng = 0;
if (dirMode > DC_IDX && dirMode < NUM_LUMA_MODE) // intraPredAngle for directional modes
{
static const int angTable[32] = { 0, 1, 2, 3, 4, 6, 8, 10, 12, 14, 16, 18, 20, 23, 26, 29, 32, 35, 39, 45, 51, 57, 64, 73, 86, 102, 128, 171, 256, 341, 512, 1024 };
static const int invAngTable[32] = {
0, 16384, 8192, 5461, 4096, 2731, 2048, 1638, 1365, 1170, 1024, 910, 819, 712, 630, 565,
512, 468, 420, 364, 321, 287, 256, 224, 191, 161, 128, 96, 64, 48, 32, 16
}; // (512 * 32) / Angle
Alexey Filippov
committed
const int absAngMode = abs(intraPredAngleMode);
const int signAng = intraPredAngleMode < 0 ? -1 : 1;
absAng = angTable [absAngMode];
m_ipaParam.invAngle = invAngTable[absAngMode];
m_ipaParam.intraPredAngle = signAng * absAng;
if (intraPredAngleMode < 0)
{
m_ipaParam.applyPDPC = false;
}
else if (intraPredAngleMode > 0)
{
const int sideSize = m_ipaParam.isModeVer ? puSize.height : puSize.width;
const int maxScale = 2;
m_ipaParam.angularScale = std::min(maxScale, floorLog2(sideSize) - (floorLog2(3 * m_ipaParam.invAngle - 2) - 8));
m_ipaParam.applyPDPC &= m_ipaParam.angularScale >= 0;
}
Alexey Filippov
committed
}
// high level conditions and DC intra prediction
if( sps.getSpsRangeExtension().getIntraSmoothingDisabledFlag()
|| !isLuma( chType )
Alexey Filippov
committed
|| useISP
Alexey Filippov
committed
|| m_ipaParam.multiRefIndex
|| DC_IDX == dirMode
)
Alexey Filippov
committed
}
#if JVET_P0059_CHROMA_BDPCM
else if ((isLuma(chType) && pu.cu->bdpcmMode) || (!isLuma(chType) && pu.cu->bdpcmModeChroma)) // BDPCM
#else
else if (isLuma( chType ) && pu.cu->bdpcmMode) // BDPCM
{
m_ipaParam.refFilterFlag = false;
}
else if (dirMode == PLANAR_IDX) // Planar intra prediction
Alexey Filippov
committed
{
m_ipaParam.refFilterFlag = puSize.width * puSize.height > 32 ? true : false;
}
else if (!useISP)// HOR, VER and angular modes (MDIS)
{
Alexey Filippov
committed
{
Chia-Ming Tsai
committed
const int diff = std::min<int>( abs( predMode - HOR_IDX ), abs( predMode - VER_IDX ) );
const int log2Size = ((floorLog2(puSize.width) + floorLog2(puSize.height)) >> 1);
Alexey Filippov
committed
CHECK( log2Size >= MAX_INTRA_FILTER_DEPTHS, "Size not supported" );
filterFlag = (diff > m_aucIntraFilter[log2Size]);
Alexey Filippov
committed
}
// Selelection of either ([1 2 1] / 4 ) refrence filter OR Gaussian 4-tap interpolation filter
if (filterFlag)
{
const bool isRefFilter = isIntegerSlope(absAng);
Chia-Ming Tsai
committed
CHECK( puSize.width * puSize.height <= 32, "DCT-IF interpolation filter is always used for 4x4, 4x8, and 8x4 luma CB" );
Chia-Ming Tsai
committed
m_ipaParam.refFilterFlag = isRefFilter;
Alexey Filippov
committed
m_ipaParam.interpolationFlag = !isRefFilter;
}
}
}

Karsten Suehring
committed
/** Function for deriving the simplified angular intra predictions.
*
* This function derives the prediction samples for the angular mode based on the prediction direction indicated by
* the prediction mode index. The prediction direction is given by the displacement of the bottom row of the block and
* the reference row above the block in the case of vertical prediction or displacement of the rightmost column
* of the block and reference column left from the block in the case of the horizontal prediction. The displacement
* is signalled at 1/32 pixel accuracy. When projection of the predicted pixel falls inbetween reference samples,
* the predicted value for the pixel is linearly interpolated from the reference samples. All reference samples are taken
* from the extended main reference.
*/
//NOTE: Bit-Limit - 25-bit source
Alexey Filippov
committed
void IntraPrediction::xPredIntraAng( const CPelBuf &pSrc, PelBuf &pDst, const ChannelType channelType, const ClpRng& clpRng)

Karsten Suehring
committed
{
int width =int(pDst.width);
int height=int(pDst.height);
Alexey Filippov
committed
const bool bIsModeVer = m_ipaParam.isModeVer;
const int multiRefIdx = m_ipaParam.multiRefIndex;
Alexey Filippov
committed
const int intraPredAngle = m_ipaParam.intraPredAngle;
const int invAngle = m_ipaParam.invAngle;

Karsten Suehring
committed
Pel* refMain;
Pel* refSide;
Pel refAbove[2 * MAX_CU_SIZE + 3 + 33 * MAX_REF_LINE_IDX];
Pel refLeft [2 * MAX_CU_SIZE + 3 + 33 * MAX_REF_LINE_IDX];

Karsten Suehring
committed
// Initialize the Main and Left reference array.
if (intraPredAngle < 0)
{
{
refAbove[x + height] = pSrc.at(x, 0);
}
refLeft[y + width] = pSrc.at(y, 1);
}
refMain = bIsModeVer ? refAbove + height : refLeft + width;
refSide = bIsModeVer ? refLeft + width : refAbove + height;
// Extend the Main reference to the left.
for (int k = -sizeSide; k <= -1; k++)
{
refMain[k] = refSide[std::min((-k * invAngle + 256) >> 9, sizeSide)];
}

Karsten Suehring
committed
}
else
{
for (int x = 0; x <= m_topRefLength + multiRefIdx; x++)
{
refAbove[x] = pSrc.at(x, 0);
}
for (int y = 0; y <= m_leftRefLength + multiRefIdx; y++)
{
refLeft[y] = pSrc.at(y, 1);
}
refMain = bIsModeVer ? refAbove : refLeft;
refSide = bIsModeVer ? refLeft : refAbove;
// Extend main reference to right using replication
const int log2Ratio = floorLog2(width) - floorLog2(height);
const int s = std::max<int>(0, bIsModeVer ? log2Ratio : -log2Ratio);
const int maxIndex = (multiRefIdx << s) + 2;
const int refLength = bIsModeVer ? m_topRefLength : m_leftRefLength;
const Pel val = refMain[refLength + multiRefIdx];
for (int z = 1; z <= maxIndex; z++)
{
refMain[refLength + multiRefIdx + z] = val;

Karsten Suehring
committed
}
// swap width/height if we are doing a horizontal mode:
if (!bIsModeVer)
{
std::swap(width, height);
}
Pel tempArray[MAX_CU_SIZE * MAX_CU_SIZE];
const int dstStride = bIsModeVer ? pDst.stride : width;
Pel * pDstBuf = bIsModeVer ? pDst.buf : tempArray;

Karsten Suehring
committed
// compensate for line offset in reference line buffers
refMain += multiRefIdx;
refSide += multiRefIdx;

Karsten Suehring
committed

Karsten Suehring
committed
if( intraPredAngle == 0 ) // pure vertical or pure horizontal
{
for( int y = 0; y < height; y++ )
{
for( int x = 0; x < width; x++ )
{

Karsten Suehring
committed
}
const int scale = (floorLog2(width) + floorLog2(height) - 2) >> 2;
const Pel topLeft = refMain[0];
const Pel left = refSide[1 + y];
for (int x = 0; x < std::min(3 << scale, width); x++)
{
const int wL = 32 >> (2 * x >> scale);
const Pel val = pDsty[x];
pDsty[x] = ClipPel(val + ((wL * (left - topLeft) + 32) >> 6), clpRng);
}

Karsten Suehring
committed
}

Karsten Suehring
committed
}
}
else
{
for (int y = 0, deltaPos = intraPredAngle * (1 + multiRefIdx); y<height; y++, deltaPos += intraPredAngle, pDsty += dstStride)

Karsten Suehring
committed
{
const int deltaInt = deltaPos >> 5;
const int deltaFract = deltaPos & 31;

Karsten Suehring
committed
Alexey Filippov
committed
if ( !isIntegerSlope( abs(intraPredAngle) ) )

Karsten Suehring
committed
{
if( isLuma(channelType) )
{
const bool useCubicFilter = !m_ipaParam.interpolationFlag;
#if JVET_P0599_INTRA_SMOOTHING_INTERP_FILT
const TFilterCoeff intraSmoothingFilter[4] = {TFilterCoeff(16 - (deltaFract >> 1)), TFilterCoeff(32 - (deltaFract >> 1)), TFilterCoeff(16 + (deltaFract >> 1)), TFilterCoeff(deltaFract >> 1)};
const TFilterCoeff* const f = (useCubicFilter) ? InterpolationFilter::getChromaFilterTable(deltaFract) : intraSmoothingFilter;
#else //!JVET_P0599_INTRA_SMOOTHING_INTERP_FILT
const TFilterCoeff *const f =
(useCubicFilter) ? InterpolationFilter::getChromaFilterTable(deltaFract) : g_intraGaussFilter[deltaFract];
#endif //JVET_P0599_INTRA_SMOOTHING_INTERP_FILT
p[0] = refMain[deltaInt + x];
p[1] = refMain[deltaInt + x + 1];
p[2] = refMain[deltaInt + x + 2];
p[3] = refMain[deltaInt + x + 3];
Pel val = (f[0] * p[0] + f[1] * p[1] + f[2] * p[2] + f[3] * p[3] + 32) >> 6;
pDsty[x] = ClipPel(val, clpRng); // always clip even though not always needed

Karsten Suehring
committed
{
// Do linear filtering

Karsten Suehring
committed
{
Pel p[2];
p[0] = refMain[deltaInt + x + 1];
p[1] = refMain[deltaInt + x + 2];
pDsty[x] = p[0] + ((deltaFract * (p[1] - p[0]) + 16) >> 5);

Karsten Suehring
committed
}
}
}
else
{
// Just copy the integer samples
for( int x = 0; x < width; x++ )
{
pDsty[x] = refMain[x + deltaInt + 1];
}
}
if (m_ipaParam.applyPDPC)
{
const int scale = m_ipaParam.angularScale;
int invAngleSum = 256;
for (int x = 0; x < std::min(3 << scale, width); x++)
{
invAngleSum += invAngle;
int wL = 32 >> (2 * x >> scale);
Pel left = refSide[y + (invAngleSum >> 9) + 1];
pDsty[x] = pDsty[x] + ((wL * (left - pDsty[x]) + 32) >> 6);
}
}

Karsten Suehring
committed
}
}
// Flip the block if this is the horizontal mode
if( !bIsModeVer )
{
for( int y = 0; y < height; y++ )
{
for( int x = 0; x < width; x++ )
{
pDst.at( y, x ) = pDstBuf[x];
}
pDstBuf += dstStride;
}
}
}
void IntraPrediction::xPredIntraBDPCM(const CPelBuf &pSrc, PelBuf &pDst, const uint32_t dirMode, const ClpRng& clpRng )
{
const int wdt = pDst.width;
const int hgt = pDst.height;
const int strideP = pDst.stride;
const int strideS = pSrc.stride;
CHECK( !( dirMode == 1 || dirMode == 2 ), "Incorrect BDPCM mode parameter." );
if( dirMode == 1 )
{
Pel val;
for( int y = 0; y < hgt; y++ )
{
val = pSrc.buf[(y + 1) + strideS];
for( int x = 0; x < wdt; x++ )
{
}
}
else
{
for( int y = 0; y < hgt; y++ )
{
for( int x = 0; x < wdt; x++ )
{

Karsten Suehring
committed
bool IntraPrediction::useDPCMForFirstPassIntraEstimation(const PredictionUnit &pu, const uint32_t &uiDirMode)
{
return CU::isRDPCMEnabled(*pu.cu) && pu.cu->transQuantBypass && (uiDirMode == HOR_IDX || uiDirMode == VER_IDX);
}
void IntraPrediction::geneWeightedPred(const ComponentID compId, PelBuf &pred, const PredictionUnit &pu, Pel *srcBuf)
{
const int width = pred.width;
#if JVET_P0641_REMOVE_2xN_CHROMA_INTRA
CHECK(width == 2, "Width of 2 is not supported");
#endif
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
const int height = pred.height;
const int srcStride = width;
const int dstStride = pred.stride;
Pel* dstBuf = pred.buf;
int wIntra, wMerge;
const Position posBL = pu.Y().bottomLeft();
const Position posTR = pu.Y().topRight();
const PredictionUnit *neigh0 = pu.cs->getPURestricted(posBL.offset(-1, 0), pu, CHANNEL_TYPE_LUMA);
const PredictionUnit *neigh1 = pu.cs->getPURestricted(posTR.offset(0, -1), pu, CHANNEL_TYPE_LUMA);
bool isNeigh0Intra = neigh0 && (CU::isIntra(*neigh0->cu));
bool isNeigh1Intra = neigh1 && (CU::isIntra(*neigh1->cu));
if (isNeigh0Intra && isNeigh1Intra)
{
wIntra = 3; wMerge = 1;
}
else
{
if (!isNeigh0Intra && !isNeigh1Intra)
{
wIntra = 1; wMerge = 3;
}
else
{
wIntra = 2; wMerge = 2;
}
}
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
dstBuf[y*dstStride + x] = (wMerge * dstBuf[y*dstStride + x] + wIntra * srcBuf[y*srcStride + x] + 2) >> 2;
}
}
}
void IntraPrediction::switchBuffer(const PredictionUnit &pu, ComponentID compID, PelBuf srcBuff, Pel *dst)
{
Pel *src = srcBuff.bufAt(0, 0);
int compWidth = compID == COMPONENT_Y ? pu.Y().width : pu.Cb().width;
int compHeight = compID == COMPONENT_Y ? pu.Y().height : pu.Cb().height;
for (int i = 0; i < compHeight; i++)
{
memcpy(dst, src, compWidth * sizeof(Pel));
src += srcBuff.stride;
dst += compWidth;
}
}
void IntraPrediction::geneIntrainterPred(const CodingUnit &cu)
{
if (!cu.firstPU->mhIntraFlag)
{
return;
}
const PredictionUnit* pu = cu.firstPU;
Alexey Filippov
committed
initIntraPatternChType(cu, pu->Y());
predIntraAng(COMPONENT_Y, cu.cs->getPredBuf(*pu).Y(), *pu);
#if JVET_P0641_REMOVE_2xN_CHROMA_INTRA
if (pu->chromaSize().width > 2)
{
#endif
initIntraPatternChType(cu, pu->Cb());
predIntraAng(COMPONENT_Cb, cu.cs->getPredBuf(*pu).Cb(), *pu);
Alexey Filippov
committed
initIntraPatternChType(cu, pu->Cr());
predIntraAng(COMPONENT_Cr, cu.cs->getPredBuf(*pu).Cr(), *pu);
#if JVET_P0641_REMOVE_2xN_CHROMA_INTRA
}
#endif
for (int currCompID = 0; currCompID < 3; currCompID++)
{
#if JVET_P0641_REMOVE_2xN_CHROMA_INTRA
if (pu->chromaSize().width <= 2 && currCompID > 0)
continue;
#endif
ComponentID currCompID2 = (ComponentID)currCompID;
PelBuf tmpBuf = currCompID == 0 ? cu.cs->getPredBuf(*pu).Y() : (currCompID == 1 ? cu.cs->getPredBuf(*pu).Cb() : cu.cs->getPredBuf(*pu).Cr());
switchBuffer(*pu, currCompID2, tmpBuf, getPredictorPtr2(currCompID2, 0));
}
}

Karsten Suehring
committed
inline bool isAboveLeftAvailable ( const CodingUnit &cu, const ChannelType &chType, const Position &posLT );
inline int isAboveAvailable ( const CodingUnit &cu, const ChannelType &chType, const Position &posLT, const uint32_t uiNumUnitsInPU, const uint32_t unitWidth, bool *validFlags );
inline int isLeftAvailable ( const CodingUnit &cu, const ChannelType &chType, const Position &posLT, const uint32_t uiNumUnitsInPU, const uint32_t unitWidth, bool *validFlags );
inline int isAboveRightAvailable ( const CodingUnit &cu, const ChannelType &chType, const Position &posRT, const uint32_t uiNumUnitsInPU, const uint32_t unitHeight, bool *validFlags );
inline int isBelowLeftAvailable ( const CodingUnit &cu, const ChannelType &chType, const Position &posLB, const uint32_t uiNumUnitsInPU, const uint32_t unitHeight, bool *validFlags );
Alexey Filippov
committed
void IntraPrediction::initIntraPatternChType(const CodingUnit &cu, const CompArea &area, const bool forceRefFilterFlag)

Karsten Suehring
committed
{
#if JVET_P0641_REMOVE_2xN_CHROMA_INTRA
CHECK(area.width == 2, "Width of 2 is not supported");
#endif

Karsten Suehring
committed
const CodingStructure& cs = *cu.cs;
Alexey Filippov
committed
if (!forceRefFilterFlag)
{
initPredIntraParams(*cu.firstPU, area, *cs.sps);
}
Pel *refBufUnfiltered = m_refBuffer[area.compID][PRED_BUF_UNFILTERED];
Pel *refBufFiltered = m_refBuffer[area.compID][PRED_BUF_FILTERED];

Karsten Suehring
committed

Karsten Suehring
committed
// ----- Step 1: unfiltered reference samples -----
xFillReferenceSamples( cs.picture->getRecoBuf( area ), refBufUnfiltered, area, cu );
// ----- Step 2: filtered reference samples -----
Alexey Filippov
committed
if( m_ipaParam.refFilterFlag || forceRefFilterFlag )

Karsten Suehring
committed
{
Alexey Filippov
committed
xFilterReferenceSamples( refBufUnfiltered, refBufFiltered, area, *cs.sps, cu.firstPU->multiRefIdx );

Karsten Suehring
committed
}
}
void IntraPrediction::initIntraPatternChTypeISP(const CodingUnit& cu, const CompArea& area, PelBuf& recBuf, const bool forceRefFilterFlag)
{
const CodingStructure& cs = *cu.cs;
if (!forceRefFilterFlag)
{
initPredIntraParams(*cu.firstPU, area, *cs.sps);
}
const Position posLT = area;
bool isLeftAvail = cs.isDecomp(posLT.offset(-1, 0), CHANNEL_TYPE_LUMA);
bool isAboveAvail = cs.isDecomp(posLT.offset(0, -1), CHANNEL_TYPE_LUMA);
// ----- Step 1: unfiltered reference samples -----
if (cu.blocks[area.compID].x == area.x && cu.blocks[area.compID].y == area.y)
{
Pel *refBufUnfiltered = m_refBuffer[area.compID][PRED_BUF_UNFILTERED];
// With the first subpartition all the CU reference samples are fetched at once in a single call to xFillReferenceSamples
if (cu.ispMode == HOR_INTRA_SUBPARTITIONS)
{
m_leftRefLength = cu.Y().height << 1;
m_topRefLength = cu.Y().width + area.width;
}
else //if (cu.ispMode == VER_INTRA_SUBPARTITIONS)
{
m_leftRefLength = cu.Y().height + area.height;
m_topRefLength = cu.Y().width << 1;
}
xFillReferenceSamples(cs.picture->getRecoBuf(cu.Y()), refBufUnfiltered, cu.Y(), cu);
// After having retrieved all the CU reference samples, the number of reference samples is now adjusted for the current subpartition
m_topRefLength = cu.blocks[area.compID].width + area.width;
m_leftRefLength = cu.blocks[area.compID].height + area.height;
}
else
{
m_topRefLength = cu.blocks[area.compID].width + area.width;
m_leftRefLength = cu.blocks[area.compID].height + area.height;
const int predSizeHor = m_topRefLength;
const int predSizeVer = m_leftRefLength;
if (cu.ispMode == HOR_INTRA_SUBPARTITIONS)
{
Pel* src = recBuf.bufAt(0, -1);
Pel *ref = m_refBuffer[area.compID][PRED_BUF_UNFILTERED] + m_refBufferStride[area.compID];
if (isLeftAvail)
{
for (int i = 0; i <= 2 * cu.blocks[area.compID].height - area.height; i++)
{
ref[i] = ref[i + area.height];
}
}
else
{
for (int i = 0; i <= predSizeVer; i++)
{
ref[i] = src[0];
}
}
Pel *dst = m_refBuffer[area.compID][PRED_BUF_UNFILTERED] + 1;
dst[-1] = ref[0];
for (int i = 0; i < area.width; i++)
{
dst[i] = src[i];
}
Pel sample = src[area.width - 1];
dst += area.width;
for (int i = 0; i < predSizeHor - area.width; i++)
{
dst[i] = sample;
}
}
else
{
Pel* src = recBuf.bufAt(-1, 0);
Pel *ref = m_refBuffer[area.compID][PRED_BUF_UNFILTERED];
if (isAboveAvail)
{
for (int i = 0; i <= 2 * cu.blocks[area.compID].width - area.width; i++)
{
ref[i] = ref[i + area.width];
}
}
else
{
for (int i = 0; i <= predSizeHor; i++)
{
ref[i] = src[0];
}
}
Pel *dst = m_refBuffer[area.compID][PRED_BUF_UNFILTERED] + m_refBufferStride[area.compID] + 1;
dst[-1] = ref[0];
for (int i = 0; i < area.height; i++)
{
*dst = *src;
src += recBuf.stride;
}
Pel sample = src[-recBuf.stride];
for (int i = 0; i < predSizeVer - area.height; i++)
{
*dst = sample;
}
}
}
// ----- Step 2: filtered reference samples -----
if (m_ipaParam.refFilterFlag || forceRefFilterFlag)
{
Pel *refBufUnfiltered = m_refBuffer[area.compID][PRED_BUF_UNFILTERED];
Pel *refBufFiltered = m_refBuffer[area.compID][PRED_BUF_FILTERED];
xFilterReferenceSamples(refBufUnfiltered, refBufFiltered, area, *cs.sps, cu.firstPU->multiRefIdx);