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_NUM_CHANNEL_TYPE][MAX_INTRA_FILTER_DEPTHS] =
{
{ // Luma
20, // 1xn
20, // 2xn
20, // 4xn
14, // 8xn
2, // 16xn
0, // 32xn
0, // 64xn
0, // 128xn
},
{ // Chroma
40, // 1xn
40, // 2xn
40, // 4xn
28, // 8xn
4, // 16xn
0, // 32xn
0, // 64xn
0, // 128xn
}
};
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
108
109
110
111
112
113
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;

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;

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)
{
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.
}

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 = g_aucLog2[denom];
const auto divOffset = (denom >> 1);
if ( width >= height )
{

Christian Helmrich
committed
for( idx = 0; idx < width; idx++ )
{
sum += pSrc.at( 1 + idx, 0 );
}

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

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

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 )
{
int modeShift[] = { 0, 6, 10, 12, 14, 15 };
int deltaSize = abs(g_aucLog2[width] - g_aucLog2[height]);
if (width > height && predMode < 2 + modeShift[deltaSize])
{
predMode += (VDIA_IDX - 1);
}
else if (height > width && predMode > VDIA_IDX - modeShift[deltaSize])
{
predMode -= (VDIA_IDX - 1);
}

Karsten Suehring
committed
}
return predMode;
}
void IntraPrediction::setReferenceArrayLengths( const CompArea &area )
{
// set Top and Left reference samples length
const int width = area.width;
const int height = area.height;
m_leftRefLength = (height << 1);
m_topRefLength = (width << 1);
}
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;
Alexey Filippov
committed
const uint32_t uiDirMode = PU::getFinalIntraMode( pu, channelType );

Karsten Suehring
committed
CHECK( g_aucLog2[iWidth] < 2 && pu.cs->pcv->noChroma2x2, "Size not allowed" );
CHECK( g_aucLog2[iWidth] > 7, "Size not allowed" );
Alexey Filippov
committed
const int multiRefIdx = m_ipaParam.multiRefIndex;
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;

Karsten Suehring
committed
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;
default: xPredIntraAng(srcBuf, piPred, channelType, clpRng); break;

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

Karsten Suehring
committed
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
{
PelBuf dstBuf = piPred;
const int scale = ((g_aucLog2[iWidth] - 2 + g_aucLog2[iHeight] - 2 + 2) >> 2);
CHECK(scale < 0 || scale > 31, "PDPC: scale < 0 || scale > 31");
if (uiDirMode == PLANAR_IDX)
{
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));
dstBuf.at(x, y) = ClipPel((wL * left + wT * top + (64 - wL - wT) * dstBuf.at(x, y) + 32) >> 6, clpRng);
}
}
}
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);
}
}
}
else if (uiDirMode == HOR_IDX)
{
const Pel topLeft = srcBuf.at(0, 0);
for (int y = 0; y < iHeight; y++)
{
int wT = 32 >> std::min(31, ((y << 1) >> scale));
for (int x = 0; x < iWidth; x++)
{
const Pel top = srcBuf.at(x + 1, 0);
int wTL = wT;
dstBuf.at(x, y) = ClipPel((wT * top - wTL * topLeft + (64 - wT + wTL) * dstBuf.at(x, y) + 32) >> 6, clpRng);
}
}
}
else if (uiDirMode == VER_IDX)
{
const Pel topLeft = srcBuf.at(0, 0);
for (int y = 0; y < iHeight; y++)
{
const Pel left = srcBuf.at(0, y + 1);
for (int x = 0; x < iWidth; x++)
{
int wL = 32 >> std::min(31, ((x << 1) >> scale));
int wTL = wL;
dstBuf.at(x, y) = ClipPel((wL * left - wTL * topLeft + (64 - wL + wTL) * dstBuf.at(x, y) + 32) >> 6, clpRng);
}
}
}
}
}
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
{

Karsten Suehring
committed
iLumaStride = MAX_CU_SIZE + 1;
Temp = PelBuf(m_piTemp + iLumaStride + 1, iLumaStride, Size(chromaArea));

Karsten Suehring
committed
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
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));
}
void IntraPrediction::xFilterGroup(Pel* pMulDst[], int i, Pel const * const piSrc, int iRecStride, bool bAboveAvaillable, bool bLeftAvaillable)
{
pMulDst[0][i] = (piSrc[1] + piSrc[iRecStride + 1] + 1) >> 1;
pMulDst[1][i] = (piSrc[iRecStride] + piSrc[iRecStride + 1] + 1) >> 1;
pMulDst[3][i] = (piSrc[0] + piSrc[1] + 1) >> 1;
pMulDst[2][i] = (piSrc[0] + piSrc[1] + piSrc[iRecStride] + piSrc[iRecStride + 1] + 2) >> 2;
}
/** 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 = g_aucLog2[width < 2 ? 2 : width];
const uint32_t log2H = g_aucLog2[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
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
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
// 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 );
#if HEVC_USE_DC_PREDFILTERING
if( enableBoundaryFilter )
{
xDCPredFiltering( pSrc, pDst, channelType );
}
#endif
}
#if HEVC_USE_DC_PREDFILTERING
/** Function for filtering intra DC predictor. This function performs filtering left and top edges of the prediction samples for DC mode (intra coding).
*/
void IntraPrediction::xDCPredFiltering(const CPelBuf &pSrc, PelBuf &pDst, const ChannelType &channelType)
{
uint32_t iWidth = pDst.width;
uint32_t iHeight = pDst.height;
int x, y;
if (isLuma(channelType) && (iWidth <= MAXIMUM_INTRA_FILTERED_WIDTH) && (iHeight <= MAXIMUM_INTRA_FILTERED_HEIGHT))
{
//top-left
pDst.at(0, 0) = (Pel)((pSrc.at(1, 0) + pSrc.at(0, 1) + 2 * pDst.at(0, 0) + 2) >> 2);
//top row (vertical filter)
for ( x = 1; x < iWidth; x++ )
{
pDst.at(x, 0) = (Pel)((pSrc.at(x + 1, 0) + 3 * pDst.at(x, 0) + 2) >> 2);
}
//left column (horizontal filter)
for ( y = 1; y < iHeight; y++ )
{
pDst.at(0, y) = (Pel)((pSrc.at(0, y + 1) + 3 * pDst.at(0, y) + 2) >> 2);
}
}
return;
}
#endif
Alexey Filippov
committed
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
// 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.whRatio = std::max( unsigned( 1 ), blockSize.width / blockSize.height ) ;
m_ipaParam.hwRatio = std::max( unsigned( 1 ), blockSize.height / blockSize.width ) ;
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 = !useISP && m_ipaParam.multiRefIndex == 0;
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, 8192, 4096, 2731, 2048, 1365, 1024, 819, 683, 585, 512, 455, 410, 356, 315, 282, 256, 234, 210, 182, 160, 144, 128, 112, 95, 80, 64, 48, 32, 24, 16, 8 }; // (256 * 32) / Angle
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;
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
}
// high level conditions and DC intra prediction
if( sps.getSpsRangeExtension().getIntraSmoothingDisabledFlag()
#if JVET_N0671_INTRA_TPM_ALIGNWITH420
|| !isLuma( chType )
#else
Alexey Filippov
committed
|| ( !isLuma( chType ) && pu.chromaFormat != CHROMA_444 )
Alexey Filippov
committed
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
|| useISP
|| m_ipaParam.multiRefIndex
|| DC_IDX == dirMode
)
{
if (useISP)
{
m_ipaParam.interpolationFlag = (m_ipaParam.isModeVer ? puSize.width : puSize.height) > 8 ? true : false ;
}
}
else if (dirMode == PLANAR_IDX) // Planar intra prediction
{
m_ipaParam.refFilterFlag = puSize.width * puSize.height > 32 ? true : false;
}
else if (!useISP)// HOR, VER and angular modes (MDIS)
{
bool filterFlag = false;
if (predMode != dirMode ) // wide-anlge mode
{
filterFlag = true;
}
else
{
const int diff = std::min<int>( abs( dirMode - HOR_IDX ), abs( dirMode - VER_IDX ) );
const int log2Size = ((g_aucLog2[puSize.width] + g_aucLog2[puSize.height]) >> 1);
CHECK( log2Size >= MAX_INTRA_FILTER_DEPTHS, "Size not supported" );
filterFlag = (diff > m_aucIntraFilter[chType][log2Size]);
}
// Selelection of either ([1 2 1] / 4 ) refrence filter OR Gaussian 4-tap interpolation filter
if (filterFlag)
{
const bool isRefFilter = isIntegerSlope(absAng);
#if JVET_N0435_WAIP_HARMONIZATION
m_ipaParam.refFilterFlag = isRefFilter && puSize.width * puSize.height > 32;
#else
Alexey Filippov
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 whRatio = m_ipaParam.whRatio;
const int hwRatio = m_ipaParam.hwRatio;
const int multiRefIdx = m_ipaParam.multiRefIndex;
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)
{
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
{
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
if( intraPredAngle == 0 ) // pure vertical or pure horizontal
{
for( int y = 0; y < height; y++ )
{
for( int x = 0; x < width; x++ )
{
pDstBuf[y*dstStride + x] = refMain[x + 1];
}
}
#if HEVC_USE_HOR_VER_PREDFILTERING

Karsten Suehring
committed
{
for( int y = 0; y < height; y++ )
{
pDstBuf[y*dstStride] = ClipPel( pDstBuf[y*dstStride] + ( ( refSide[y + 1] - refSide[0] ) >> 1 ), clpRng );
}
}
#endif
}
else
{
Pel *pDsty=pDstBuf;
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 & (32 - 1);
Alexey Filippov
committed
if ( !isIntegerSlope( abs(intraPredAngle) ) )

Karsten Suehring
committed
{
if( isLuma(channelType) )
{
Pel p[4];
Alexey Filippov
committed
const bool useCubicFilter = !m_ipaParam.interpolationFlag;
TFilterCoeff const * const f = (useCubicFilter) ? InterpolationFilter::getChromaFilterTable(deltaFract) : g_intraGaussFilter[deltaFract];
int refMainIndex = deltaInt + 1;
for( int x = 0; x < width; x++, refMainIndex++ )
{
p[0] = refMain[refMainIndex - 1];
p[1] = refMain[refMainIndex];
p[2] = refMain[refMainIndex + 1];
p[3] = f[3] != 0 ? refMain[refMainIndex + 2] : 0;
pDstBuf[y*dstStride + x] = static_cast<Pel>((static_cast<int>(f[0] * p[0]) + static_cast<int>(f[1] * p[1]) + static_cast<int>(f[2] * p[2]) + static_cast<int>(f[3] * p[3]) + 32) >> 6);
if( useCubicFilter ) // only cubic filter has negative coefficients and requires clipping
{
pDstBuf[y*dstStride + x] = ClipPel( pDstBuf[y*dstStride + x], clpRng );
}
}
}
else

Karsten Suehring
committed
{
// Do linear filtering
const Pel *pRM = refMain + deltaInt + 1;
int lastRefMainPel = *pRM++;
for( int x = 0; x < width; pRM++, x++ )
{
int thisRefMainPel = *pRM;
pDsty[x + 0] = ( Pel ) ( ( ( 32 - deltaFract )*lastRefMainPel + deltaFract*thisRefMainPel + 16 ) >> 5 );
lastRefMainPel = thisRefMainPel;
}
}
}
else
{
// Just copy the integer samples
for( int x = 0; x < width; x++ )
{
pDsty[x] = refMain[x + deltaInt + 1];
}
}
const int scale = ((g_aucLog2[width] - 2 + g_aucLog2[height] - 2 + 2) >> 2);
CHECK(scale < 0 || scale > 31, "PDPC: scale < 0 || scale > 31");
Alexey Filippov
committed
if (m_ipaParam.applyPDPC)

Karsten Suehring
committed
{
Alexey Filippov
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
{
Alexey Filippov
committed
int invAngleSum0 = 2;
for (int x = 0; x < width; x++)
{
invAngleSum0 += invAngle;
int deltaPos0 = invAngleSum0 >> 2;
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
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
}
}
}
#if HEVC_USE_HOR_VER_PREDFILTERING
if( edgeFilter && absAng <= 1 )
{
for( int y = 0; y < height; y++ )
{
pDstBuf[y*dstStride] = ClipPel( pDstBuf[y*dstStride] + ((refSide[y + 1] - refSide[0]) >> 2), clpRng );
}
}
#endif
}
// 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;
}
}
}
bool IntraPrediction::useDPCMForFirstPassIntraEstimation(const PredictionUnit &pu, const uint32_t &uiDirMode)
{
return CU::isRDPCMEnabled(*pu.cu) && pu.cu->transQuantBypass && (uiDirMode == HOR_IDX || uiDirMode == VER_IDX);
}
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
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;
const uint32_t dirMode = PU::getFinalIntraMode(pu, toChannelType(compId));
const ClpRng& clpRng(pu.cu->cs->slice->clpRng(compId));
Pel* dstBuf = pred.buf;
int k, l;
bool modeDC = (dirMode <= DC_IDX);
Pel wIntra1 = 6, wInter1 = 2, wIntra2 = 5, wInter2 = 3, wIntra3 = 3, wInter3 = 5, wIntra4 = 2, wInter4 = 6;
if (modeDC || width < 4 || height < 4)
{
for (k = 0; k<height; k++)
{
for (l = 0; l<width; l++)
{
dstBuf[k*dstStride + l] = ClipPel((((dstBuf[k*dstStride + l] * 4) + (srcBuf[k*srcStride + l] * 4)) >> 3), clpRng);
}
}
}
else
{
if (dirMode <= DIA_IDX)
{
int interval = (width >> 2);
for (k = 0; k<height; k++)
{
for (l = 0; l<width; l++)
{
if (l<interval)
{
dstBuf[k*dstStride + l] = ClipPel((((dstBuf[k*dstStride + l] * wInter1) + (srcBuf[k*srcStride + l] * wIntra1)) >> 3), clpRng);
}
else if (l >= interval && l < (2 * interval))
{
dstBuf[k*dstStride + l] = ClipPel((((dstBuf[k*dstStride + l] * wInter2) + (srcBuf[k*srcStride + l] * wIntra2)) >> 3), clpRng);
}
else if (l >= (interval * 2) && l < (3 * interval))
{
dstBuf[k*dstStride + l] = ClipPel((((dstBuf[k*dstStride + l] * wInter3) + (srcBuf[k*srcStride + l] * wIntra3)) >> 3), clpRng);
}
else
{
dstBuf[k*dstStride + l] = ClipPel((((dstBuf[k*dstStride + l] * wInter4) + (srcBuf[k*srcStride + l] * wIntra4)) >> 3), clpRng);
}
}
}
}
else
{
int interval = (height >> 2);
for (k = 0; k<height; k++)
{
for (l = 0; l<width; l++)
{
if (k<interval)
{
dstBuf[k*dstStride + l] = ClipPel((((dstBuf[k*dstStride + l] * wInter1) + (srcBuf[k*srcStride + l] * wIntra1)) >> 3), clpRng);
}
else if (k >= interval && k < (2 * interval))
{
dstBuf[k*dstStride + l] = ClipPel((((dstBuf[k*dstStride + l] * wInter2) + (srcBuf[k*srcStride + l] * wIntra2)) >> 3), clpRng);
}
else if (k >= (interval * 2) && k < (3 * interval))
{
dstBuf[k*dstStride + l] = ClipPel((((dstBuf[k*dstStride + l] * wInter3) + (srcBuf[k*srcStride + l] * wIntra3)) >> 3), clpRng);
}
else
{
dstBuf[k*dstStride + l] = ClipPel((((dstBuf[k*dstStride + l] * wInter4) + (srcBuf[k*srcStride + l] * wIntra4)) >> 3), clpRng);
}
}
}
}
}
}
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);
initIntraPatternChType(cu, pu->Cb());
predIntraAng(COMPONENT_Cb, cu.cs->getPredBuf(*pu).Cb(), *pu);
initIntraPatternChType(cu, pu->Cr());
predIntraAng(COMPONENT_Cr, cu.cs->getPredBuf(*pu).Cr(), *pu);
for (int currCompID = 0; currCompID < 3; currCompID++)
{
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
{
const CodingStructure& cs = *cu.cs;
Alexey Filippov
committed
if (!forceRefFilterFlag)
{
initPredIntraParams(*cu.firstPU, area, *cs.sps);
}

Karsten Suehring
committed
Pel *refBufUnfiltered = m_piYuvExt[area.compID][PRED_BUF_UNFILTERED];
Pel *refBufFiltered = m_piYuvExt[area.compID][PRED_BUF_FILTERED];