IntraPrediction.cpp 79.3 KB
Newer Older
1
2
3
4
5
/* 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.
 *
6
 * Copyright (c) 2010-2019, ITU/ISO/IEC
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>

49
50
#include "CommonLib/InterpolationFilter.h"

51
52
53
54
55
56
57
58
59
60
//! \ingroup CommonLib
//! \{

// ====================================================================================================================
// Tables
// ====================================================================================================================

const uint8_t IntraPrediction::m_aucIntraFilter[MAX_NUM_CHANNEL_TYPE][MAX_INTRA_FILTER_DEPTHS] =
{
  { // Luma
61
62
63
64
65
#if JVET_O0277_INTRA_SMALL_BLOCK_DCTIF
    24, //   1xn
    24, //   2xn
    24, //   4xn
#else
66
67
68
    20, //   1xn
    20, //   2xn
    20, //   4xn
69
#endif
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
    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
  }
};

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
114
115
116
117
118
119
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 },
120
  { 3, 17, 29, 15 }
121
122
};

123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
// ====================================================================================================================
// 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;
    }
  }
138
139
140
141
142
143
144
  for (uint32_t ch = 0; ch < MAX_NUM_COMPONENT; ch++)
  {
    for (uint32_t buf = 0; buf < 4; buf++)
    {
      m_yuvExt2[ch][buf] = nullptr;
    }
  }
145
146

  m_piTemp = nullptr;
Xiang Ma's avatar
Xiang Ma committed
147
  m_pMdlmTemp = nullptr;
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
}

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;
    }
  }
165
166
167
168
169
170
171
172
  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;
    }
  }
173
174
175

  delete[] m_piTemp;
  m_piTemp = nullptr;
Xiang Ma's avatar
Xiang Ma committed
176
177
  delete[] m_pMdlmTemp;
  m_pMdlmTemp = nullptr;
178
#if JVET_O0119_BASE_PALETTE_444
179
  if (m_runTypeRD)   { xFree(m_runTypeRD);   m_runTypeRD = NULL; }
180
181
  if (m_runLengthRD) { xFree(m_runLengthRD); m_runLengthRD = NULL; }
#endif
182
183
184
185
186
187
188
189
190
191
}

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();
  }

192
193
194
195
196
  if (m_yuvExt2[COMPONENT_Y][0] != nullptr && m_currChromaFormat != chromaFormatIDC)
  {
    destroy();
  }

197
198
199
200
  m_currChromaFormat = chromaFormatIDC;

  if (m_piYuvExt[COMPONENT_Y][PRED_BUF_UNFILTERED] == nullptr) // check if first is null (in which case, nothing initialised yet)
  {
201
202
203
#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
Liang Zhao's avatar
Liang Zhao committed
204
    m_iYuvExtSize = (MAX_CU_SIZE * 2 + 1 + MAX_REF_LINE_IDX * 33) * (MAX_CU_SIZE * 2 + 1 + MAX_REF_LINE_IDX * 33);
205
#endif
206
207
208
209
210
211
212
213
214
215

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

216
217
218
219
220
221
222
223
224
225
226
227
228
  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];
      }
    }
  }

229
230
231
232
  if (m_piTemp == nullptr)
  {
    m_piTemp = new Pel[(MAX_CU_SIZE + 1) * (MAX_CU_SIZE + 1)];
  }
Xiang Ma's avatar
Xiang Ma committed
233
234
235
236
  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.
  }
237
238
239
240
#if JVET_O0119_BASE_PALETTE_444
  m_runTypeRD = (bool*)xMalloc(bool, MAX_CU_SIZE*MAX_CU_SIZE);
  m_runLengthRD = (Pel*)xMalloc(Pel, MAX_CU_SIZE*MAX_CU_SIZE);
#endif
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
}

// ====================================================================================================================
// 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 )
  {
263
264
    for( idx = 0; idx < width; idx++ )
    {
265
#if JVET_O0426_MRL_REF_SAMPLES_DC_MODE
266
      sum += pSrc.at(m_ipaParam.multiRefIndex + 1 + idx, 0);
267
#else
268
      sum += pSrc.at( 1 + idx, 0 );
269
#endif
270
    }
271
272
273
  }
  if ( width <= height )
  {
274
275
    for( idx = 0; idx < height; idx++ )
    {
276
#if JVET_O0426_MRL_REF_SAMPLES_DC_MODE
277
      sum += pSrc.at(0, m_ipaParam.multiRefIndex + 1 + idx);
278
#else
279
      sum += pSrc.at( 0, 1 + idx );
280
#endif
281
    }
282
283
284
285
286
287
  }

  dcVal = (sum + divOffset) >> divShift;
  return dcVal;
}

Frank Bossen's avatar
Frank Bossen committed
288
289
290
int IntraPrediction::getWideAngle( int width, int height, int predMode )
{
  if ( predMode > DC_IDX && predMode <= VDIA_IDX )
291
  {
Frank Bossen's avatar
Frank Bossen committed
292
293
294
    int modeShift[] = { 0, 6, 10, 12, 14, 15 };
    int deltaSize = abs(g_aucLog2[width] - g_aucLog2[height]);
    if (width > height && predMode < 2 + modeShift[deltaSize])
295
    {
Frank Bossen's avatar
Frank Bossen committed
296
297
298
299
300
      predMode += (VDIA_IDX - 1);
    }
    else if (height > width && predMode > VDIA_IDX - modeShift[deltaSize])
    {
      predMode -= (VDIA_IDX - 1);
301
302
    }
  }
Frank Bossen's avatar
Frank Bossen committed
303
304
  return predMode;
}
305

Frank Bossen's avatar
Frank Bossen committed
306
307
308
309
310
void IntraPrediction::setReferenceArrayLengths( const CompArea &area )
{
  // set Top and Left reference samples length
  const int  width    = area.width;
  const int  height   = area.height;
311

Frank Bossen's avatar
Frank Bossen committed
312
313
  m_leftRefLength     = (height << 1);
  m_topRefLength      = (width << 1);
314

Frank Bossen's avatar
Frank Bossen committed
315
}
316

317
void IntraPrediction::predIntraAng( const ComponentID compId, PelBuf &piPred, const PredictionUnit &pu)
318
319
320
321
322
{
  const ComponentID    compID       = MAP_CHROMA( compId );
  const ChannelType    channelType  = toChannelType( compID );
  const int            iWidth       = piPred.width;
  const int            iHeight      = piPred.height;
323
  const uint32_t       uiDirMode    = isLuma( compId ) && pu.cu->bdpcmMode ? BDPCM_IDX : PU::getFinalIntraMode( pu, channelType );
324
325
326

  CHECK( g_aucLog2[iWidth] < 2 && pu.cs->pcv->noChroma2x2, "Size not allowed" );
  CHECK( g_aucLog2[iWidth] > 7, "Size not allowed" );
Liang Zhao's avatar
Liang Zhao committed
327

328
  const int multiRefIdx = m_ipaParam.multiRefIndex;
329
330
331
332
#if JVET_O0364_PADDING
  const int srcStride  = m_topRefLength + 1 + multiRefIdx;
  const int srcHStride = m_leftRefLength + 1 + multiRefIdx;
#else
333
334
335
  const int whRatio     = m_ipaParam.whRatio;
  const int hwRatio     = m_ipaParam.hwRatio;

Liang Zhao's avatar
Liang Zhao committed
336
337
  const int  srcStride  = m_topRefLength  + 1 + (whRatio + 1) * multiRefIdx;
  const int  srcHStride = m_leftRefLength + 1 + (hwRatio + 1) * multiRefIdx;
338
#endif
339
340
341
342
  
#if JVET_O0502_ISP_CLEANUP
  const CPelBuf& srcBuf = pu.cu->ispMode && isLuma(compID) ? getISPBuffer() : CPelBuf(getPredictorPtr(compID), srcStride, srcHStride);
#else
343
  const CPelBuf & srcBuf = CPelBuf(getPredictorPtr(compID), srcStride, srcHStride);
344
#endif
345
346
347
348
  const ClpRng& clpRng(pu.cu->cs->slice->clpRng(compID));

  switch (uiDirMode)
  {
349
350
    case(PLANAR_IDX): xPredIntraPlanar(srcBuf, piPred); break;
    case(DC_IDX):     xPredIntraDc(srcBuf, piPred, channelType, false); break;
351
    case(BDPCM_IDX):  xPredIntraBDPCM(srcBuf, piPred, pu.cu->bdpcmMode, clpRng); break;
352
    default:          xPredIntraAng(srcBuf, piPred, channelType, clpRng); break;
353
354
  }

355
  if (m_ipaParam.applyPDPC)
356
357
358
359
360
  {
    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");

361
362
363
#if JVET_O0364_PDPC_DC
    if (uiDirMode == PLANAR_IDX || uiDirMode == DC_IDX)
#else
364
    if (uiDirMode == PLANAR_IDX)
365
#endif
366
367
368
    {
      for (int y = 0; y < iHeight; y++)
      {
Frank Bossen's avatar
Frank Bossen committed
369
        const int wT   = 32 >> std::min(31, ((y << 1) >> scale));
370
371
372
        const Pel left = srcBuf.at(0, y + 1);
        for (int x = 0; x < iWidth; x++)
        {
Frank Bossen's avatar
Frank Bossen committed
373
374
375
376
          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);
377
378
379
        }
      }
    }
380
#if !JVET_O0364_PDPC_DC
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
    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);
        }
      }
    }
397
#endif
398
399
  }
}
Frank Bossen's avatar
Frank Bossen committed
400

401
402
403
404
void IntraPrediction::predIntraChromaLM(const ComponentID compID, PelBuf &piPred, const PredictionUnit &pu, const CompArea& chromaArea, int intraDir)
{
  int  iLumaStride = 0;
  PelBuf Temp;
Xiang Ma's avatar
Xiang Ma committed
405
406
407
408
409
410
411
  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
  {
Frank Bossen's avatar
Frank Bossen committed
412
413
    iLumaStride = MAX_CU_SIZE + 1;
    Temp = PelBuf(m_piTemp + iLumaStride + 1, iLumaStride, Size(chromaArea));
Xiang Ma's avatar
Xiang Ma committed
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));
}

/** Function for deriving planar intra prediction. This function derives the prediction samples for planar mode (intra coding).
 */

//NOTE: Bit-Limit - 24-bit source
427
void IntraPrediction::xPredIntraPlanar( const CPelBuf &pSrc, PelBuf &pDst )
428
429
430
{
  const uint32_t width  = pDst.width;
  const uint32_t height = pDst.height;
431
432
  const uint32_t log2W  = g_aucLog2[width  < 2 ? 2 : width];
  const uint32_t log2H  = g_aucLog2[height < 2 ? 2 : height];
433
434

  int leftColumn[MAX_CU_SIZE + 1], topRow[MAX_CU_SIZE + 1], bottomRow[MAX_CU_SIZE], rightColumn[MAX_CU_SIZE];
435
  const uint32_t offset = 1 << (log2W + log2H);
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

  // 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 );
}

487
488
489
490
491
492
493
494
495
496
497
498
499
500
// 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 );

Frank Bossen's avatar
Frank Bossen committed
501
#if !JVET_O0364_PADDING
502
503
  m_ipaParam.whRatio              = std::max( unsigned( 1 ), blockSize.width  / blockSize.height ) ;
  m_ipaParam.hwRatio              = std::max( unsigned( 1 ), blockSize.height / blockSize.width  ) ;
Frank Bossen's avatar
Frank Bossen committed
504
#endif
505
506
507
508
  m_ipaParam.isModeVer            = predMode >= DIA_IDX;
  m_ipaParam.multiRefIndex        = isLuma (chType) ? pu.multiRefIdx : 0 ;
  m_ipaParam.refFilterFlag        = false;
  m_ipaParam.interpolationFlag    = false;
509
510
511
#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
512
  m_ipaParam.applyPDPC            = !useISP && m_ipaParam.multiRefIndex == 0;
513
#endif
514
515
516
517
518
519
520
521

  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 };
522
523
524
525
526
527
#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
Liang Zhao's avatar
Liang Zhao committed
528
    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
529
#endif
530
531
532
533
534
535
536

    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;
537
538
539
540
541
542
543
544
545
546
#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;

547
548
549
#if JVET_O0364_PADDING
      m_ipaParam.angularScale = std::min(maxScale, g_aucLog2[sideSize] - (floorLog2(3 * m_ipaParam.invAngle - 2) - 8));
#else
550
      m_ipaParam.angularScale = std::min(maxScale, g_aucLog2[sideSize] - (floorLog2(3 * m_ipaParam.invAngle - 2) - 7));
551
#endif
552
553
554
      m_ipaParam.applyPDPC &= m_ipaParam.angularScale >= 0;
    }
#else
555
    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
556
#endif
557
558
  }

559
560
561
  // high level conditions and DC intra prediction
  if(   sps.getSpsRangeExtension().getIntraSmoothingDisabledFlag()
    || !isLuma( chType )
562
    || useISP
563
564
565
#if JVET_O0925_MIP_SIMPLIFICATIONS
    || PU::isMIP( pu, chType )
#endif
566
567
568
    || m_ipaParam.multiRefIndex
    || DC_IDX == dirMode
    )
569
  {
570
#if !JVET_O0502_ISP_CLEANUP
571
572
573
574
    if (useISP)
    {
      m_ipaParam.interpolationFlag = (m_ipaParam.isModeVer ? puSize.width : puSize.height) > 8 ? true : false ;
    }
575
#endif
576
  }
577
578
579
580
  else if (isLuma( chType ) && pu.cu->bdpcmMode) // BDPCM
  {
    m_ipaParam.refFilterFlag = false;
  }
581
  else if (dirMode == PLANAR_IDX) // Planar intra prediction
582
583
584
585
586
  {
    m_ipaParam.refFilterFlag = puSize.width * puSize.height > 32 ? true : false;
  }
  else if (!useISP)// HOR, VER and angular modes (MDIS)
  {
587
    bool filterFlag = false;
588
#if !JVET_O0277_INTRA_SMALL_BLOCK_DCTIF
589
590
591
592
593
    if (predMode != dirMode ) // wide-anlge mode
    {
      filterFlag = true;
    }
    else
594
#endif
595
    {
596
597
598
#if JVET_O0277_INTRA_SMALL_BLOCK_DCTIF
      const int diff = std::min<int>( abs( predMode - HOR_IDX ), abs( predMode - VER_IDX ) );
#else
599
      const int diff = std::min<int>( abs( dirMode - HOR_IDX ), abs( dirMode - VER_IDX ) );
600
#endif
601
602
603
604
605
606
607
608
      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)
    {
609
      const bool isRefFilter       =  isIntegerSlope(absAng);
610
#if JVET_O0277_INTRA_SMALL_BLOCK_DCTIF
611
      CHECK( puSize.width * puSize.height <= 32, "DCT-IF interpolation filter is always used for 4x4, 4x8, and 8x4 luma CB" );
612
613
      m_ipaParam.refFilterFlag     =  isRefFilter;
#else
PoHan Lin's avatar
PoHan Lin committed
614
      m_ipaParam.refFilterFlag = isRefFilter && puSize.width * puSize.height > 32;
615
#endif
616
617
618
619
620
      m_ipaParam.interpolationFlag = !isRefFilter;
    }
  }
}

621
622
623
624
625
626
627
628
629
630
631
632

/** 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
633
634

void IntraPrediction::xPredIntraAng( const CPelBuf &pSrc, PelBuf &pDst, const ChannelType channelType, const ClpRng& clpRng)
635
636
637
638
{
  int width =int(pDst.width);
  int height=int(pDst.height);

639
  const bool bIsModeVer     = m_ipaParam.isModeVer;
Frank Bossen's avatar
Frank Bossen committed
640
#if !JVET_O0364_PADDING
641
642
  const int  whRatio        = m_ipaParam.whRatio;
  const int  hwRatio        = m_ipaParam.hwRatio;
Frank Bossen's avatar
Frank Bossen committed
643
#endif
644
  const int  multiRefIdx    = m_ipaParam.multiRefIndex;
645
646
  const int  intraPredAngle = m_ipaParam.intraPredAngle;
  const int  invAngle       = m_ipaParam.invAngle;
647
648
649
650

  Pel* refMain;
  Pel* refSide;

Liang Zhao's avatar
Liang Zhao committed
651
652
  Pel  refAbove[2 * MAX_CU_SIZE + 3 + 33 * MAX_REF_LINE_IDX];
  Pel  refLeft [2 * MAX_CU_SIZE + 3 + 33 * MAX_REF_LINE_IDX];
653
654
655
656

  // Initialize the Main and Left reference array.
  if (intraPredAngle < 0)
  {
657
#if JVET_O0364_PADDING
Frank Bossen's avatar
Frank Bossen committed
658
    for (int x = 0; x <= width + 1 + multiRefIdx; x++)
659
660
661
    {
      refAbove[x + height] = pSrc.at(x, 0);
    }
Frank Bossen's avatar
Frank Bossen committed
662
    for (int y = 0; y <= height + 1 + multiRefIdx; y++)
663
664
665
666
667
668
669
    {
      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.
Frank Bossen's avatar
Frank Bossen committed
670
    int sizeSide = bIsModeVer ? height : width;
671
672
673
674
675
    for (int k = -sizeSide; k <= -1; k++)
    {
      refMain[k] = refSide[std::min((-k * invAngle + 256) >> 9, sizeSide)];
    }
#else
676
677
678
679
680
    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;

681
    for (int x = 0; x < width + 1 + multiRefIdx; x++)
682
683
684
    {
      refAbove[x + height - 1] = pSrc.at( x, 0 );
    }
685
    for (int y = 0; y < height + 1 + multiRefIdx; y++)
686
687
688
689
690
691
692
693
    {
      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)
694
    for( int k = -1; k > firstIdx; k-- )
695
696
697
698
    {
      invAngleSum += invAngle;
      refMain[k] = refSide[invAngleSum>>8];
    }
699
700
    refMain[lastIdx] = refMain[lastIdx-1];
    refMain[firstIdx] = refMain[firstIdx+1];
701
#endif
702
703
704
  }
  else
  {
705
706
707
708
709
710
711
712
713
714
715
716
717
718
#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
Frank Bossen's avatar
Frank Bossen committed
719
720
721
722
723
    const int log2Ratio = g_aucLog2[width] - g_aucLog2[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];
724
725
    for (int z = 1; z <= maxIndex; z++)
    {
Frank Bossen's avatar
Frank Bossen committed
726
      refMain[refLength + multiRefIdx + z] = val;
727
728
    }
#else
Liang Zhao's avatar
Liang Zhao committed
729
    for (int x = 0; x < m_topRefLength + 1 + (whRatio + 1) * multiRefIdx; x++)
730
    {
731
      refAbove[x+1] = pSrc.at(x, 0);
732
    }
Liang Zhao's avatar
Liang Zhao committed
733
    for (int y = 0; y < m_leftRefLength + 1 + (hwRatio + 1) * multiRefIdx; y++)
734
    {
735
      refLeft[y+1]  = pSrc.at(0, y);
736
737
738
    }
    refMain = bIsModeVer ? refAbove : refLeft ;
    refSide = bIsModeVer ? refLeft  : refAbove;
739
740
741
742

    refMain++;
    refSide++;
    refMain[-1] = refMain[0];
Liang Zhao's avatar
Liang Zhao committed
743
    auto lastIdx = 1 + ((bIsModeVer) ? m_topRefLength + (whRatio + 1) * multiRefIdx : m_leftRefLength +  (hwRatio + 1) * multiRefIdx);
744
    refMain[lastIdx] = refMain[lastIdx-1];
745
#endif
746
747
748
749
750
751
752
753
754
755
756
  }

  // 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);
  }

757
758
759
  // compensate for line offset in reference line buffers
  refMain += multiRefIdx;
  refSide += multiRefIdx;
760

Frank Bossen's avatar
Frank Bossen committed
761
762
  Pel *pDsty = pDstBuf;

763
764
765
766
767
768
  if( intraPredAngle == 0 )  // pure vertical or pure horizontal
  {
    for( int y = 0; y < height; y++ )
    {
      for( int x = 0; x < width; x++ )
      {
Frank Bossen's avatar
Frank Bossen committed
769
        pDsty[x] = refMain[x + 1];
770
      }
Frank Bossen's avatar
Frank Bossen committed
771
772
773
774
775
776
777
778
779
780
781
782

      if (m_ipaParam.applyPDPC)
      {
        const int scale   = (g_aucLog2[width] + g_aucLog2[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);
        }
783
      }
Frank Bossen's avatar
Frank Bossen committed
784
785

      pDsty += dstStride;
786
787
788
789
    }
  }
  else
  {
790
    for (int y = 0, deltaPos = intraPredAngle * (1 + multiRefIdx); y<height; y++, deltaPos += intraPredAngle, pDsty += dstStride)
791
792
    {
      const int deltaInt   = deltaPos >> 5;
793
      const int deltaFract = deltaPos & 31;
794

795
      if ( !isIntegerSlope( abs(intraPredAngle) ) )
796
      {
797
798
        if( isLuma(channelType) )
        {
799
          const bool useCubicFilter = !m_ipaParam.interpolationFlag;
800

801
802
          const TFilterCoeff *const f =
            (useCubicFilter) ? InterpolationFilter::getChromaFilterTable(deltaFract) : g_intraGaussFilter[deltaFract];
803

804
          for (int x = 0; x < width; x++)
805
          {
806
            Pel p[4];
807

808
809
810
811
812
813
814
815
            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
816

817
            Pel val = (f[0] * p[0] + f[1] * p[1] + f[2] * p[2] + f[3] * p[3] + 32) >> 6;
818

819
            pDsty[x] = ClipPel(val, clpRng);   // always clip even though not always needed
820
821
822
          }
        }
        else
823
824
        {
          // Do linear filtering
825
          for (int x = 0; x < width; x++)
826
          {
827
828
829
830
831
832
            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);
833
834
835
836
837
838
839
840
841
842
843
          }
        }
      }
      else
      {
        // Just copy the integer samples
        for( int x = 0; x < width; x++ )
        {
          pDsty[x] = refMain[x + deltaInt + 1];
        }
      }
844
845
846
847
#if JVET_O0364_PDPC_ANGULAR
      if (m_ipaParam.applyPDPC)
      {
        const int scale       = m_ipaParam.angularScale;
848
849
850
#if JVET_O0364_PADDING
        int       invAngleSum = 256;
#else
851
        int       invAngleSum = 128;
852
#endif
853
854
855
856
857
858

        for (int x = 0; x < std::min(3 << scale, width); x++)
        {
          invAngleSum += invAngle;

          int wL   = 32 >> (2 * x >> scale);
859
860
861
#if JVET_O0364_PADDING
          Pel left = refSide[y + (invAngleSum >> 9) + 1];
#else
862
          Pel left = refSide[y + (invAngleSum >> 8) + 1];
863
#endif
864
865
866
867
          pDsty[x] = pDsty[x] + ((wL * (left - pDsty[x]) + 32) >> 6);
        }
      }
#else
868
869
      const int scale = ((g_aucLog2[width] - 2 + g_aucLog2[height] - 2 + 2) >> 2);
      CHECK(scale < 0 || scale > 31, "PDPC: scale < 0 || scale > 31");
870
      if (m_ipaParam.applyPDPC)
871
      {
872
        if (m_ipaParam.intraPredAngle == 32) // intra prediction modes: 2 and VDIA
873
        {
874
          int wT = 16 >> std::min(31, ((y << 1) >> scale));
875

876
877
878
879
880
881
882
883
884
885
          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;
886

887
888
            pDsty[x] = ClipPel((wL * left + wT * top + (64 - wL - wT) * pDsty[x] + 32) >> 6, clpRng);
          }
889
        }
890
        else
891
        {
892
893
894
#if JVET_O0364_PADDING
          int invAngleSum0 = 4;
#else
895
          int invAngleSum0 = 2;
896
#endif
897
898
899
          for (int x = 0; x < width; x++)
          {
            invAngleSum0 += invAngle;
900
901
902
#if JVET_O0364_PADDING
            int deltaPos0 = invAngleSum0 >> 3;
#else
903
            int deltaPos0 = invAngleSum0 >> 2;
904
#endif
905
906
            int deltaFrac0 = deltaPos0 & 63;
            int deltaInt0 = deltaPos0 >> 6;
907

908
909
            int deltay = y + deltaInt0 + 1;
            if (deltay >(bIsModeVer ? m_leftRefLength : m_topRefLength) - 1) break;
910

911
912
913
            int wL = 32 >> std::min(31, ((x << 1) >> scale));
            if (wL == 0) break;
            Pel *p = refSide + deltay;
914

915
916
917
            Pel left = p[deltaFrac0 >> 5];
            pDsty[x] = ClipPel((wL * left + (64 - wL) * pDsty[x] + 32) >> 6, clpRng);
          }
918
919
        }
      }
920
#endif
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
    }
  }

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

938
939
940
941
942
943
944
945
946
947
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." );

948
  Pel* pred = &pDst.buf[0];
949
950
951
952
953
954
955
956
  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++ )
      {
957
        pred[x] = val;
958
      }
959
      pred += strideP;
960
961
962
963
964
965
966
967
    }
  }
  else
  {
    for( int y = 0; y < hgt; y++ )
    {
      for( int x = 0; x < wdt; x++ )
      {
968
        pred[x] = pSrc.buf[x + 1];
969
      }
970
      pred += strideP;
971
972
973
    }
  }
}
974
975
976
977
978
979

bool IntraPrediction::useDPCMForFirstPassIntraEstimation(const PredictionUnit &pu, const uint32_t &uiDirMode)
{
  return CU::isRDPCMEnabled(*pu.cu) && pu.cu->transQuantBypass && (uiDirMode == HOR_IDX || uiDirMode == VER_IDX);
}

Luong Pham Van's avatar
Luong Pham Van committed
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
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;
  }