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
{
Chia-Ming Tsai
committed
#if JVET_O0277_INTRA_SMALL_BLOCK_DCTIF
24, // 1xn
24, // 2xn
24, // 4xn
Chia-Ming Tsai
committed
#else
20, // 1xn
20, // 2xn
20, // 4xn
Chia-Ming Tsai
committed
#endif
14, // 8xn
2, // 16xn
0, // 32xn
0, // 64xn
0 // 128xn

Karsten Suehring
committed
};
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
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 }

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 < NUM_PRED_BUF; buf++)
{
m_piYuvExt[ch][buf] = nullptr;
}
}
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_O0119_BASE_PALETTE_444
m_runTypeRD = nullptr;
m_runLengthRD = nullptr;
#endif

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 < NUM_PRED_BUF; buf++)
{
delete[] m_piYuvExt[ch][buf];
m_piYuvExt[ch][buf] = nullptr;
}
}
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;
Yung-Hsuan Chao (Jessie)
committed
#if JVET_O0119_BASE_PALETTE_444
if (m_runTypeRD) { xFree( m_runTypeRD ); m_runTypeRD = NULL; }
if (m_runLengthRD) { xFree( m_runLengthRD); m_runLengthRD = NULL; }
Yung-Hsuan Chao (Jessie)
committed
#endif

Karsten Suehring
committed
}
void IntraPrediction::init(ChromaFormat chromaFormatIDC, const unsigned bitDepthY)
{
// if it has been initialised before, but the chroma format has changed, release the memory and start again.
if (m_piYuvExt[COMPONENT_Y][PRED_BUF_UNFILTERED] != nullptr && m_currChromaFormat != chromaFormatIDC)
{
destroy();
}
if (m_yuvExt2[COMPONENT_Y][0] != nullptr && m_currChromaFormat != chromaFormatIDC)
{
destroy();
}

Karsten Suehring
committed
m_currChromaFormat = chromaFormatIDC;
if (m_piYuvExt[COMPONENT_Y][PRED_BUF_UNFILTERED] == nullptr) // check if first is null (in which case, nothing initialised yet)
{
#if JVET_O0364_PADDING
m_iYuvExtSize = (MAX_CU_SIZE * 2 + 1 + MAX_REF_LINE_IDX) * (MAX_CU_SIZE * 2 + 1 + MAX_REF_LINE_IDX);
#else
m_iYuvExtSize = (MAX_CU_SIZE * 2 + 1 + MAX_REF_LINE_IDX * 33) * (MAX_CU_SIZE * 2 + 1 + MAX_REF_LINE_IDX * 33);

Karsten Suehring
committed
for (uint32_t ch = 0; ch < MAX_NUM_COMPONENT; ch++)
{
for (uint32_t buf = 0; buf < NUM_PRED_BUF; buf++)
{
m_piYuvExt[ch][buf] = new Pel[m_iYuvExtSize];
}
}
}
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.
}
Yung-Hsuan Chao (Jessie)
committed
#if JVET_O0119_BASE_PALETTE_444
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);
}
Yung-Hsuan Chao (Jessie)
committed
#endif

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
#if JVET_O0426_MRL_REF_SAMPLES_DC_MODE
Adarsh Krishnan Ramasubramonian
committed
sum += pSrc.at(m_ipaParam.multiRefIndex + 1 + idx, 0);
Adarsh Krishnan Ramasubramonian
committed
#else

Christian Helmrich
committed
sum += pSrc.at( 1 + idx, 0 );
Adarsh Krishnan Ramasubramonian
committed
#endif

Christian Helmrich
committed
}

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

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

Christian Helmrich
committed
sum += pSrc.at( 0, 1 + idx );
Adarsh Krishnan Ramasubramonian
committed
#endif

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;
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" );
Alexey Filippov
committed
const int multiRefIdx = m_ipaParam.multiRefIndex;
#if JVET_O0364_PADDING
const int srcStride = m_topRefLength + 1 + multiRefIdx;
const int srcHStride = m_leftRefLength + 1 + multiRefIdx;
#else
Alexey Filippov
committed
const int whRatio = m_ipaParam.whRatio;
const int hwRatio = m_ipaParam.hwRatio;
const int srcStride = m_topRefLength + 1 + (whRatio + 1) * multiRefIdx;
const int srcHStride = m_leftRefLength + 1 + (hwRatio + 1) * multiRefIdx;
#if JVET_O0502_ISP_CLEANUP
const CPelBuf& srcBuf = pu.cu->ispMode && isLuma(compID) ? getISPBuffer() : CPelBuf(getPredictorPtr(compID), srcStride, srcHStride);
#else
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;
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 JVET_O0364_PDPC_DC
if (uiDirMode == PLANAR_IDX || uiDirMode == DC_IDX)
#else

Karsten Suehring
committed
if (uiDirMode == PLANAR_IDX)
#endif

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

Karsten Suehring
committed
const Pel left = srcBuf.at(0, y + 1);
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
}
}
}
#if !JVET_O0364_PDPC_DC

Karsten Suehring
committed
else if (uiDirMode == DC_IDX)
{
const Pel topLeft = srcBuf.at(0, 0);
for (int y = 0; y < iHeight; y++)
{
int wT = 32 >> std::min(31, ((y << 1) >> scale));
const Pel left = srcBuf.at(0, y + 1);
for (int x = 0; x < iWidth; x++)
{
const Pel top = srcBuf.at(x + 1, 0);
int wL = 32 >> std::min(31, ((x << 1) >> scale));
int wTL = (wL >> 4) + (wT >> 4);
dstBuf.at(x, y) = ClipPel((wL * left + wT * top - wTL * topLeft + (64 - wL - wT + wTL) * dstBuf.at(x, y) + 32) >> 6, clpRng);
}
}
}
#endif

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;
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
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
// 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( 0, k + 1 );
}
// 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 );
Alexey Filippov
committed
m_ipaParam.whRatio = std::max( unsigned( 1 ), blockSize.width / blockSize.height ) ;
m_ipaParam.hwRatio = std::max( unsigned( 1 ), blockSize.height / blockSize.width ) ;
Alexey Filippov
committed
m_ipaParam.isModeVer = predMode >= DIA_IDX;
m_ipaParam.multiRefIndex = isLuma (chType) ? pu.multiRefIdx : 0 ;
m_ipaParam.refFilterFlag = false;
m_ipaParam.interpolationFlag = false;
#if JVET_O0502_ISP_CLEANUP
m_ipaParam.applyPDPC = ((puSize.width >= MIN_TB_SIZEY && puSize.height >= MIN_TB_SIZEY) || !isLuma(compId)) && m_ipaParam.multiRefIndex == 0;
#else
Alexey Filippov
committed
m_ipaParam.applyPDPC = !useISP && 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 };
#if JVET_O0364_PADDING
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
#else
static const int invAngTable[32] = { 0, 8192, 4096, 2731, 2048, 1365, 1024, 819, 683, 585, 512, 455, 410, 356, 315, 282, 256, 234, 210, 182, 161, 144, 128, 112, 95, 80, 64, 48, 32, 24, 16, 8 }; // (256 * 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 JVET_O0364_PDPC_ANGULAR
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;
#if JVET_O0364_PADDING
m_ipaParam.angularScale = std::min(maxScale, floorLog2(sideSize) - (floorLog2(3 * m_ipaParam.invAngle - 2) - 8));
m_ipaParam.angularScale = std::min(maxScale, floorLog2(sideSize) - (floorLog2(3 * m_ipaParam.invAngle - 2) - 7));
m_ipaParam.applyPDPC &= m_ipaParam.angularScale >= 0;
}
#else
Alexey Filippov
committed
m_ipaParam.applyPDPC &= m_ipaParam.intraPredAngle == 0 || m_ipaParam.intraPredAngle >= 12; // intra prediction modes: HOR, VER, x, where x>=VDIA-8 or x<=2+8
Alexey Filippov
committed
}
// high level conditions and DC intra prediction
if( sps.getSpsRangeExtension().getIntraSmoothingDisabledFlag()
|| !isLuma( chType )
Alexey Filippov
committed
|| useISP
#if JVET_O0925_MIP_SIMPLIFICATIONS
|| PU::isMIP( pu, chType )
#endif
Alexey Filippov
committed
|| m_ipaParam.multiRefIndex
|| DC_IDX == dirMode
)
Alexey Filippov
committed
if (useISP)
{
m_ipaParam.interpolationFlag = (m_ipaParam.isModeVer ? puSize.width : puSize.height) > 8 ? true : false ;
}
Alexey Filippov
committed
}
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)
{
Chia-Ming Tsai
committed
#if !JVET_O0277_INTRA_SMALL_BLOCK_DCTIF
Alexey Filippov
committed
if (predMode != dirMode ) // wide-anlge mode
{
filterFlag = true;
}
else
Chia-Ming Tsai
committed
#endif
Alexey Filippov
committed
{
Chia-Ming Tsai
committed
#if JVET_O0277_INTRA_SMALL_BLOCK_DCTIF
const int diff = std::min<int>( abs( predMode - HOR_IDX ), abs( predMode - VER_IDX ) );
#else
Alexey Filippov
committed
const int diff = std::min<int>( abs( dirMode - HOR_IDX ), abs( dirMode - VER_IDX ) );
Chia-Ming Tsai
committed
#endif
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
#if JVET_O0277_INTRA_SMALL_BLOCK_DCTIF
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;
#else
m_ipaParam.refFilterFlag = isRefFilter && puSize.width * puSize.height > 32;
Chia-Ming Tsai
committed
#endif
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;
Alexey Filippov
committed
const int whRatio = m_ipaParam.whRatio;
const int hwRatio = m_ipaParam.hwRatio;
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)
{
#if JVET_O0364_PADDING
{
refAbove[x + height] = pSrc.at(x, 0);
}
{
refLeft[y + width] = pSrc.at(0, y);
}
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)];
}
#else
Alexey Filippov
committed
const int width = pDst.width + 1;
const int height = pDst.height + 1;
const int lastIdx = (bIsModeVer ? width : height) + multiRefIdx;
const int firstIdx = (((bIsModeVer ? height : width) - 1) * intraPredAngle) >> 5;
for (int x = 0; x < width + 1 + multiRefIdx; x++)

Karsten Suehring
committed
{
refAbove[x + height - 1] = pSrc.at( x, 0 );
}
for (int y = 0; y < height + 1 + multiRefIdx; y++)

Karsten Suehring
committed
{
refLeft[y + width - 1] = pSrc.at( 0, y );
}
refMain = (bIsModeVer ? refAbove + height : refLeft + width ) - 1;
refSide = (bIsModeVer ? refLeft + width : refAbove + height) - 1;
// Extend the Main reference to the left.
int invAngleSum = 128; // rounding for (shift by 8)
for( int k = -1; k > firstIdx; k-- )

Karsten Suehring
committed
{
invAngleSum += invAngle;
refMain[k] = refSide[invAngleSum>>8];
}
refMain[lastIdx] = refMain[lastIdx-1];
refMain[firstIdx] = refMain[firstIdx+1];

Karsten Suehring
committed
}
else
{
#if JVET_O0364_PADDING
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(0, y);
}
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;
}
#else
for (int x = 0; x < m_topRefLength + 1 + (whRatio + 1) * multiRefIdx; x++)

Karsten Suehring
committed
{
refAbove[x+1] = pSrc.at(x, 0);

Karsten Suehring
committed
}
for (int y = 0; y < m_leftRefLength + 1 + (hwRatio + 1) * multiRefIdx; y++)

Karsten Suehring
committed
{
refLeft[y+1] = pSrc.at(0, y);

Karsten Suehring
committed
}
refMain = bIsModeVer ? refAbove : refLeft ;
refSide = bIsModeVer ? refLeft : refAbove;
refMain++;
refSide++;
refMain[-1] = refMain[0];
auto lastIdx = 1 + ((bIsModeVer) ? m_topRefLength + (whRatio + 1) * multiRefIdx : m_leftRefLength + (hwRatio + 1) * multiRefIdx);
refMain[lastIdx] = refMain[lastIdx-1];

Karsten Suehring
committed
}
// swap width/height if we are doing a horizontal mode:
Pel tempArray[MAX_CU_SIZE*MAX_CU_SIZE];
const int dstStride = bIsModeVer ? pDst.stride : MAX_CU_SIZE;
Pel *pDstBuf = bIsModeVer ? pDst.buf : tempArray;
if (!bIsModeVer)
{
std::swap(width, height);
}
// 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;
const TFilterCoeff *const f =
(useCubicFilter) ? InterpolationFilter::getChromaFilterTable(deltaFract) : g_intraGaussFilter[deltaFract];
p[0] = refMain[deltaInt + x];
p[1] = refMain[deltaInt + x + 1];
p[2] = refMain[deltaInt + x + 2];
#if JVET_O0364_PADDING
p[3] = refMain[deltaInt + x + 3];
#else
p[3] = f[3] != 0 ? refMain[deltaInt + x + 3] : 0;
#endif
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 JVET_O0364_PDPC_ANGULAR
if (m_ipaParam.applyPDPC)
{
const int scale = m_ipaParam.angularScale;
#if JVET_O0364_PADDING
int invAngleSum = 256;
#else
int invAngleSum = 128;
for (int x = 0; x < std::min(3 << scale, width); x++)
{
invAngleSum += invAngle;
int wL = 32 >> (2 * x >> scale);
#if JVET_O0364_PADDING
Pel left = refSide[y + (invAngleSum >> 9) + 1];
#else
Pel left = refSide[y + (invAngleSum >> 8) + 1];
pDsty[x] = pDsty[x] + ((wL * (left - pDsty[x]) + 32) >> 6);
}
}
#else
const int scale = ((floorLog2(width) - 2 + floorLog2(height) - 2 + 2) >> 2);

Karsten Suehring
committed
CHECK(scale < 0 || scale > 31, "PDPC: scale < 0 || scale > 31");
Alexey Filippov
committed
if (m_ipaParam.applyPDPC)

Karsten Suehring
committed
{
if (m_ipaParam.intraPredAngle == 32) // intra prediction modes: 2 and VDIA

Karsten Suehring
committed
{
Alexey Filippov
committed
int wT = 16 >> std::min(31, ((y << 1) >> scale));

Karsten Suehring
committed
Alexey Filippov
committed
for (int x = 0; x < width; x++)
{
int wL = 16 >> std::min(31, ((x << 1) >> scale));
if (wT + wL == 0) break;
int c = x + y + 1;
if (c >= 2 * height) { wL = 0; }
if (c >= 2 * width) { wT = 0; }
const Pel left = (wL != 0) ? refSide[c + 1] : 0;
const Pel top = (wT != 0) ? refMain[c + 1] : 0;

Karsten Suehring
committed
Alexey Filippov
committed
pDsty[x] = ClipPel((wL * left + wT * top + (64 - wL - wT) * pDsty[x] + 32) >> 6, clpRng);
}

Karsten Suehring
committed
}
Alexey Filippov
committed
else

Karsten Suehring
committed
{
#if JVET_O0364_PADDING
int invAngleSum0 = 4;
#else
Alexey Filippov
committed
int invAngleSum0 = 2;
Alexey Filippov
committed
for (int x = 0; x < width; x++)
{
invAngleSum0 += invAngle;
#if JVET_O0364_PADDING
int deltaPos0 = invAngleSum0 >> 3;
#else
Alexey Filippov
committed
int deltaPos0 = invAngleSum0 >> 2;
Alexey Filippov
committed
int deltaFrac0 = deltaPos0 & 63;
int deltaInt0 = deltaPos0 >> 6;

Karsten Suehring
committed
Alexey Filippov
committed
int deltay = y + deltaInt0 + 1;
if (deltay >(bIsModeVer ? m_leftRefLength : m_topRefLength) - 1) break;

Karsten Suehring
committed
Alexey Filippov
committed
int wL = 32 >> std::min(31, ((x << 1) >> scale));
if (wL == 0) break;
Pel *p = refSide + deltay;

Karsten Suehring
committed
Alexey Filippov
committed
Pel left = p[deltaFrac0 >> 5];
pDsty[x] = ClipPel((wL * left + (64 - wL) * pDsty[x] + 32) >> 6, clpRng);
}

Karsten Suehring
committed
}
}

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;
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