Coverage Report

Created: 2026-09-14 06:44

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/work/vvenc/source/Lib/CommonLib/IntraPrediction.cpp
Line
Count
Source
1
/* -----------------------------------------------------------------------------
2
The copyright in this software is being made available under the Clear BSD
3
License, included below. No patent rights, trademark rights and/or 
4
other Intellectual Property Rights other than the copyrights concerning 
5
the Software are granted under this license.
6
7
The Clear BSD License
8
9
Copyright (c) 2019-2026, Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. & The VVenC Authors.
10
All rights reserved.
11
12
Redistribution and use in source and binary forms, with or without modification,
13
are permitted (subject to the limitations in the disclaimer below) provided that
14
the following conditions are met:
15
16
     * Redistributions of source code must retain the above copyright notice,
17
     this list of conditions and the following disclaimer.
18
19
     * Redistributions in binary form must reproduce the above copyright
20
     notice, this list of conditions and the following disclaimer in the
21
     documentation and/or other materials provided with the distribution.
22
23
     * Neither the name of the copyright holder nor the names of its
24
     contributors may be used to endorse or promote products derived from this
25
     software without specific prior written permission.
26
27
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY
28
THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
29
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
31
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
32
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
33
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
34
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
35
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
36
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38
POSSIBILITY OF SUCH DAMAGE.
39
40
41
------------------------------------------------------------------------------------------- */
42
43
44
/** \file     Prediction.cpp
45
    \brief    prediction class
46
*/
47
48
#include "IntraPrediction.h"
49
#include "Unit.h"
50
#include "UnitTools.h"
51
#include "Rom.h"
52
#include "InterpolationFilter.h"
53
#include "dtrace_next.h"
54
55
#include <memory.h>
56
57
//! \ingroup CommonLib
58
//! \{
59
60
namespace vvenc {
61
62
// ====================================================================================================================
63
// Tables
64
// ====================================================================================================================
65
66
const uint8_t IntraPrediction::m_aucIntraFilter[MAX_INTRA_FILTER_DEPTHS] =
67
{
68
  24, //   1xn
69
  24, //   2xn
70
  24, //   4xn
71
  14, //   8xn
72
  2,  //  16xn
73
  0,  //  32xn
74
  0,  //  64xn
75
  0   // 128xn
76
};
77
78
//NOTE: Bit-Limit - 24-bit source
79
void xPredIntraPlanar_Core( PelBuf& pDst, const CPelBuf& pSrc )
80
120k
{
81
120k
  const uint32_t width  = pDst.width;
82
120k
  const uint32_t height = pDst.height;
83
120k
  const uint32_t log2W  = Log2(width);
84
120k
  const uint32_t log2H  = Log2(height);
85
86
120k
  int leftColumn[MAX_TB_SIZEY + 1], topRow[MAX_TB_SIZEY + 1], bottomRow[MAX_TB_SIZEY], rightColumn[MAX_TB_SIZEY];
87
120k
  const uint32_t offset = 1 << (log2W + log2H);
88
89
  // Get left and above reference column and row
90
2.47M
  for( int k = 0; k < width + 1; k++ )
91
2.35M
  {
92
2.35M
    topRow[k] = pSrc.at( k + 1, 0 );
93
2.35M
  }
94
95
2.45M
  for( int k = 0; k < height + 1; k++ )
96
2.33M
  {
97
2.33M
    leftColumn[k] = pSrc.at( k + 1, 1 );
98
2.33M
  }
99
100
  // Prepare intermediate variables used in interpolation
101
120k
  int bottomLeft = leftColumn[height];
102
120k
  int topRight = topRow[width];
103
104
  // with some optimizations gcc-8 gives spurious "-Wmaybe-uninitialized" warnings here (says leftColumn or topRow would be uninitialized here)
105
120k
  GCC_WARNING_DISABLE_maybe_uninitialized
106
2.35M
  for( int k = 0; k < width; k++ )
107
2.22M
  {
108
2.22M
    bottomRow[k] = bottomLeft - topRow[k];
109
2.22M
    topRow[k]    = topRow[k] << log2H;
110
2.22M
  }
111
112
2.33M
  for( int k = 0; k < height; k++ )
113
2.21M
  {
114
2.21M
    rightColumn[k] = topRight - leftColumn[k];
115
2.21M
    leftColumn[k]  = leftColumn[k] << log2W;
116
2.21M
  }
117
120k
  GCC_WARNING_RESET
118
119
120k
  const uint32_t finalShift = 1 + log2W + log2H;
120
120k
  const uint32_t stride     = pDst.stride;
121
120k
  Pel*       pred       = pDst.buf;
122
2.33M
  for( int y = 0; y < height; y++, pred += stride )
123
2.21M
  {
124
2.21M
    int horPred = leftColumn[y];
125
126
53.0M
    for( int x = 0; x < width; x++ )
127
50.7M
    {
128
50.7M
      horPred += rightColumn[y];
129
50.7M
      topRow[x] += bottomRow[x];
130
131
50.7M
      int vertPred = topRow[x];
132
50.7M
      pred[x]      = ( ( horPred << log2H ) + ( vertPred << log2W ) + offset ) >> finalShift;
133
50.7M
    }
134
2.21M
  }
135
120k
}
136
137
void  IntraPredSampleFilter_Core(PelBuf& dstBuf, const CPelBuf& pSrc)
138
357k
{
139
357k
  const int iWidth  = dstBuf.width;
140
357k
  const int iHeight = dstBuf.height;
141
142
357k
  const int scale = ((Log2(iWidth*iHeight) - 2) >> 2);
143
357k
  CHECK(scale < 0 || scale > 31, "PDPC: scale < 0 || scale > 31");
144
145
6.49M
  for (int y = 0; y < iHeight; y++)
146
6.13M
  {
147
6.13M
    const int wT   = 32 >> std::min(31, ((y << 1) >> scale));
148
6.13M
    const Pel left = pSrc.at(y + 1, 1);
149
137M
    for (int x = 0; x < iWidth; x++)
150
131M
    {
151
131M
      const int wL    = 32 >> std::min(31, ((x << 1) >> scale));
152
131M
      const Pel top   = pSrc.at(x + 1, 0);
153
131M
      const Pel val   = dstBuf.at(x, y);
154
131M
      dstBuf.at(x, y) = val + ((wL * (left - val) + wT * (top - val) + 32) >> 6);
155
131M
    }
156
6.13M
  }
157
357k
}
158
159
void IntraHorVerPDPC_Core(Pel* pDsty,const int dstStride,Pel* refSide,const int width,const int height,int scale,const Pel* refMain, const ClpRng& clpRng)
160
390k
{
161
390k
  const Pel topLeft = refMain[0];
162
163
6.24M
  for( int y = 0; y < height; y++ )
164
5.85M
  {
165
5.85M
    memcpy(pDsty,&refMain[1],width*sizeof(Pel));
166
5.85M
    const Pel left    = refSide[1 + y];
167
45.6M
    for (int x = 0; x < std::min(3 << scale, width); x++)
168
39.8M
    {
169
39.8M
      const int wL  = 32 >> (2 * x >> scale);
170
39.8M
      const Pel val = pDsty[x];
171
39.8M
      pDsty[x]      = ClipPel(val + ((wL * (left - topLeft) + 32) >> 6), clpRng);
172
39.8M
    }
173
5.85M
    pDsty += dstStride;
174
5.85M
  }
175
390k
}
176
void IntraAnglePDPC_Core(Pel* pDsty,const int dstStride,Pel* refSide,const int width,const int height,int scale,int invAngle)
177
426k
{
178
9.62M
  for (int y = 0; y<height; y++, pDsty += dstStride)
179
9.20M
  {
180
9.20M
    int       invAngleSum = 256;
181
98.4M
    for (int x = 0; x < std::min(3 << scale, width); x++)
182
89.2M
    {
183
89.2M
      invAngleSum += invAngle;
184
89.2M
      int wL   = 32 >> (2 * x >> scale);
185
89.2M
      Pel left = refSide[y + (invAngleSum >> 9) + 1];
186
89.2M
      pDsty[x] = pDsty[x] + ((wL * (left - pDsty[x]) + 32) >> 6);
187
89.2M
    }
188
9.20M
  }
189
426k
}
190
191
void IntraPredAngleLuma_Core(Pel* pDstBuf,const ptrdiff_t dstStride,Pel* refMain,int width,int height,int deltaPos,int intraPredAngle,const TFilterCoeff *ff_unused,const bool useCubicFilter,const ClpRng& clpRng)
192
550k
{
193
16.3M
  for (int y = 0; y<height; y++ )
194
15.7M
  {
195
15.7M
    const int deltaInt   = deltaPos >> 5;
196
15.7M
    const int deltaFract = deltaPos & ( 32 - 1 );
197
198
15.7M
    const TFilterCoeff      intraSmoothingFilter[4] = {TFilterCoeff(16 - (deltaFract >> 1)), TFilterCoeff(32 - (deltaFract >> 1)), TFilterCoeff(16 + (deltaFract >> 1)), TFilterCoeff(deltaFract >> 1)};
199
15.7M
    const TFilterCoeff *f = useCubicFilter ? InterpolationFilter::getChromaFilterTable(deltaFract) : intraSmoothingFilter;
200
201
15.7M
    Pel p[4];
202
203
15.7M
    int refMainIndex = deltaInt + 1;
204
205
 //   const TFilterCoeff *f = &ff[deltaFract << 2];
206
207
647M
    for( int x = 0; x < width; x++, refMainIndex++ )
208
631M
    {
209
631M
      p[0] = refMain[refMainIndex - 1];
210
631M
      p[1] = refMain[refMainIndex    ];
211
631M
      p[2] = refMain[refMainIndex + 1];
212
631M
      p[3] = refMain[refMainIndex + 2];
213
214
631M
      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);
215
216
631M
      if( useCubicFilter ) // only cubic filter has negative coefficients and requires clipping
217
85.1M
      {
218
85.1M
        pDstBuf[y*dstStride + x] = ClipPel( pDstBuf[y*dstStride + x], clpRng );
219
85.1M
      }
220
631M
    }
221
15.7M
    deltaPos += intraPredAngle;
222
15.7M
  }
223
550k
}
224
225
void IntraPredAngleChroma_Core(Pel* pDstBuf,const ptrdiff_t dstStride,int16_t* pBorder,int width,int height,int deltaPos,int intraPredAngle)
226
57.1k
{
227
481k
  for (int y = 0; y<height; y++)
228
424k
  {
229
424k
    const int deltaInt   = deltaPos >> 5;
230
424k
    const int deltaFract = deltaPos & (32 - 1);
231
232
    // Do linear filtering
233
424k
    const Pel* pRM = pBorder + deltaInt + 1;
234
424k
    int lastRefMainPel = *pRM++;
235
236
11.2M
    for( int x = 0; x < width; pRM++, x++ )
237
10.8M
    {
238
10.8M
      int thisRefMainPel = *pRM;
239
10.8M
      pDstBuf[x + 0] = ( Pel ) ( ( ( 32 - deltaFract )*lastRefMainPel + deltaFract*thisRefMainPel + 16 ) >> 5 );
240
10.8M
      lastRefMainPel = thisRefMainPel;
241
10.8M
    }
242
424k
    deltaPos += intraPredAngle;
243
424k
    pDstBuf += dstStride;
244
424k
  }
245
57.1k
}
246
247
// ====================================================================================================================
248
// Constructor / destructor / initialize
249
// ====================================================================================================================
250
251
IntraPrediction::IntraPrediction( bool enableOpt )
252
19.1k
:  m_pMdlmTemp( nullptr )
253
19.1k
,  m_currChromaFormat( NUM_CHROMA_FORMAT )
254
19.1k
{
255
19.1k
  IntraPredAngleLuma    = IntraPredAngleLuma_Core;
256
19.1k
  IntraPredAngleChroma  = IntraPredAngleChroma_Core;
257
19.1k
  IntraAnglePDPC        = IntraAnglePDPC_Core;
258
19.1k
  IntraHorVerPDPC       = IntraHorVerPDPC_Core;
259
19.1k
  IntraPredSampleFilter = IntraPredSampleFilter_Core;
260
19.1k
  xPredIntraPlanar      = xPredIntraPlanar_Core;
261
262
19.1k
#if ENABLE_SIMD_OPT_INTRAPRED
263
19.1k
  if( enableOpt )
264
19.1k
  {
265
#if defined( TARGET_SIMD_X86 )
266
    initIntraPredictionX86();
267
#endif
268
#if defined( TARGET_SIMD_ARM )
269
    initIntraPredictionARM();
270
#endif
271
19.1k
  }
272
19.1k
#endif // ENABLE_SIMD_OPT_INTRAPRED
273
19.1k
}
274
275
IntraPrediction::~IntraPrediction()
276
19.1k
{
277
19.1k
  destroy();
278
19.1k
}
279
280
void IntraPrediction::destroy()
281
19.1k
{
282
19.1k
  delete[] m_pMdlmTemp;
283
19.1k
  m_pMdlmTemp = nullptr;
284
19.1k
}
285
286
void IntraPrediction::init(ChromaFormat chromaFormatIDC, const unsigned bitDepthY)
287
19.1k
{
288
19.1k
  m_currChromaFormat = chromaFormatIDC;
289
290
19.1k
  if (m_pMdlmTemp == nullptr)
291
19.1k
  {
292
19.1k
    m_pMdlmTemp = new Pel[(2 * MAX_TB_SIZEY + 1)*(2 * MAX_TB_SIZEY + 1)];//MDLM will use top-above and left-below samples.
293
19.1k
  }
294
19.1k
}
295
296
// ====================================================================================================================
297
// Public member functions
298
// ====================================================================================================================
299
300
// Function for calculating DC value of the reference samples used in Intra prediction
301
//NOTE: Bit-Limit - 25-bit source
302
Pel IntraPrediction::xGetPredValDc( const CPelBuf& pSrc, const Size& dstSize )
303
280k
{
304
280k
  CHECK( dstSize.width == 0 || dstSize.height == 0, "Empty area provided" );
305
306
280k
  int idx, sum = 0;
307
280k
  Pel dcVal;
308
280k
  const int width  = dstSize.width;
309
280k
  const int height = dstSize.height;
310
280k
  const auto denom     = (width == height) ? (width << 1) : std::max(width,height);
311
280k
  const auto divShift  = Log2(denom);
312
280k
  const auto divOffset = (denom >> 1);
313
280k
  const int off = m_ipaParam.multiRefIndex + 1;
314
315
316
280k
  if ( width >= height )
317
197k
  {
318
4.35M
    for( idx = 0; idx < width; idx++ )
319
4.15M
    {
320
4.15M
      sum += pSrc.at( off + idx, 0);
321
4.15M
    }
322
197k
  }
323
280k
  if ( width <= height )
324
189k
  {
325
4.31M
    for( idx = 0; idx < height; idx++ )
326
4.12M
    {
327
4.12M
      sum += pSrc.at( off + idx, 1);
328
4.12M
    }
329
189k
  }
330
331
280k
  dcVal = (sum + divOffset) >> divShift;
332
280k
  return dcVal;
333
280k
}
334
335
int IntraPrediction::getWideAngle( int width, int height, int predMode )
336
1.91M
{
337
1.91M
  if ( predMode > DC_IDX && predMode <= VDIA_IDX )
338
1.32M
  {
339
1.32M
    int modeShift[] = { 0, 6, 10, 12, 14, 15 };
340
1.32M
    int deltaSize = abs(Log2(width) - Log2(height));
341
1.32M
    if (width > height && predMode < 2 + modeShift[deltaSize])
342
38.0k
    {
343
38.0k
      predMode += (VDIA_IDX - 1);
344
38.0k
    }
345
1.28M
    else if (height > width && predMode > VDIA_IDX - modeShift[deltaSize])
346
67.1k
    {
347
67.1k
      predMode -= (VDIA_IDX - 1);
348
67.1k
    }
349
1.32M
  }
350
1.91M
  return predMode;
351
1.91M
}
352
353
void IntraPrediction::predIntraAng( const ComponentID compId, PelBuf& piPred, const CodingUnit& cu)
354
1.70M
{
355
1.70M
  const ComponentID    compID       = compId;
356
1.70M
  const ChannelType    channelType  = toChannelType( compID );
357
1.70M
  const uint32_t       uiDirMode = cu.bdpcmM[channelType] ? BDPCM_IDX : CU::getFinalIntraMode(cu, channelType);
358
359
1.70M
  CHECK( Log2(piPred.width) > 7, "Size not allowed" );
360
361
//  const int multiRefIdx = m_ipaParam.multiRefIndex;
362
1.70M
  const int srcStride  = m_refBufferStride[compID];
363
1.70M
  const int srcHStride = 2;
364
365
1.70M
  const CPelBuf& srcBuf = CPelBuf(getPredictorPtr(compID), srcStride, srcHStride);
366
1.70M
  const ClpRng& clpRng(cu.cs->slice->clpRngs[compID]);
367
368
1.70M
  switch (uiDirMode)
369
1.70M
  {
370
120k
    case(PLANAR_IDX): xPredIntraPlanar(piPred, srcBuf); break;
371
280k
    case(DC_IDX):     xPredIntraDc    ( piPred, srcBuf ); break;
372
82.2k
    case(BDPCM_IDX):  xPredIntraBDPCM ( piPred, srcBuf, cu.bdpcmM[channelType], clpRng); break;
373
1.21M
    default:          xPredIntraAng   ( piPred, srcBuf, channelType, clpRng); break;
374
1.70M
  }
375
376
1.70M
  if (m_ipaParam.applyPDPC)
377
1.25M
  {
378
1.25M
    if (uiDirMode == PLANAR_IDX || uiDirMode == DC_IDX)
379
357k
    {
380
357k
      IntraPredSampleFilter(piPred, srcBuf);
381
357k
    }
382
1.25M
  }
383
1.70M
}
384
385
void IntraPrediction::predIntraChromaLM(const ComponentID compID, PelBuf& piPred, const CodingUnit& cu, const CompArea& chromaArea, int intraDir)
386
202k
{
387
202k
  CHECK( piPred.width > MAX_TB_SIZEY || piPred.height > MAX_TB_SIZEY, "not enough memory");
388
202k
  const int iLumaStride = 2 * MAX_TB_SIZEY + 1;
389
202k
  PelBuf Temp = PelBuf(m_pMdlmTemp + iLumaStride + 1, iLumaStride, Size(chromaArea));
390
391
202k
  int a, b, iShift;
392
202k
  xGetLMParameters(cu, compID, chromaArea, a, b, iShift); // th shift result is unsigned
393
394
  ////// final prediction
395
202k
  piPred.copyFrom(Temp);
396
202k
  piPred.linearTransform(a, iShift, b, true, cu.cs->slice->clpRngs[compID]);
397
202k
}
398
399
/** Function for deriving planar intra prediction. This function derives the prediction samples for planar mode (intra coding).
400
 */
401
402
void IntraPrediction::xPredIntraDc( PelBuf& pDst, const CPelBuf& pSrc )
403
280k
{
404
280k
  const Pel dcval = xGetPredValDc( pSrc, pDst );
405
280k
  pDst.fill( dcval );
406
280k
}
407
408
// Function for initialization of intra prediction parameters
409
void IntraPrediction::initPredIntraParams(const CodingUnit& cu, const CompArea area, const SPS& sps)
410
1.91M
{
411
1.91M
  const ComponentID compId = area.compID;
412
1.91M
  const ChannelType chType = toChannelType(compId);
413
414
1.91M
  const bool        useISP = NOT_INTRA_SUBPARTITIONS != cu.ispMode && isLuma( chType );
415
416
1.91M
  const Size   cuSize    = Size( cu.blocks[compId].width, cu.blocks[compId].height );
417
1.91M
  const Size   puSize    = Size( area.width, area.height );
418
1.91M
  const Size&  blockSize = useISP ? cuSize : puSize;
419
1.91M
  const int      dirMode = CU::getFinalIntraMode(cu, chType);
420
1.91M
  const int     predMode = getWideAngle( blockSize.width, blockSize.height, dirMode );
421
422
1.91M
  m_ipaParam.isModeVer            = predMode >= DIA_IDX;
423
1.91M
  m_ipaParam.multiRefIndex        = isLuma (chType) ? cu.multiRefIdx : 0 ;
424
1.91M
  m_ipaParam.refFilterFlag        = false;
425
1.91M
  m_ipaParam.interpolationFlag    = false;
426
1.91M
  m_ipaParam.applyPDPC            = (puSize.width >= MIN_TB_SIZEY && puSize.height >= MIN_TB_SIZEY) && m_ipaParam.multiRefIndex == 0;
427
428
1.91M
  const int    intraPredAngleMode = (m_ipaParam.isModeVer) ? predMode - VER_IDX : -(predMode - HOR_IDX);
429
430
431
1.91M
  int absAng = 0;
432
1.91M
  if (dirMode > DC_IDX && dirMode < NUM_LUMA_MODE) // intraPredAngle for directional modes
433
1.32M
  {
434
1.32M
    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 };
435
1.32M
    static const int invAngTable[32] = {
436
1.32M
      0,   16384, 8192, 5461, 4096, 2731, 2048, 1638, 1365, 1170, 1024, 910, 819, 712, 630, 565,
437
1.32M
      512, 468,   420,  364,  321,  287,  256,  224,  191,  161,  128,  96,  64,  48,  32,  16
438
1.32M
    };   // (512 * 32) / Angle
439
440
1.32M
    const int     absAngMode         = abs(intraPredAngleMode);
441
1.32M
    const int     signAng            = intraPredAngleMode < 0 ? -1 : 1;
442
1.32M
                  absAng             = angTable  [absAngMode];
443
444
1.32M
    m_ipaParam.absInvAngle           = invAngTable[absAngMode];
445
1.32M
    m_ipaParam.intraPredAngle        = signAng * absAng;
446
1.32M
    if (intraPredAngleMode < 0)
447
236k
    {
448
236k
      m_ipaParam.applyPDPC = false;
449
236k
    }
450
1.08M
    else if (intraPredAngleMode > 0)
451
537k
    {
452
537k
      const int sideSize = m_ipaParam.isModeVer ? puSize.height : puSize.width;
453
537k
      const int maxScale = 2;
454
455
537k
      m_ipaParam.angularScale = std::min(maxScale, floorLog2(sideSize) - (floorLog2(3 * m_ipaParam.absInvAngle - 2) - 8));
456
537k
      m_ipaParam.applyPDPC &= m_ipaParam.angularScale >= 0;
457
537k
    }
458
1.32M
  }
459
460
  // high level conditions and DC intra prediction
461
1.91M
  if( !isLuma( chType )
462
789k
    || useISP
463
769k
    || CU::isMIP( cu, chType ) //th remove this
464
723k
    || m_ipaParam.multiRefIndex
465
571k
    || DC_IDX == dirMode
466
1.91M
    )
467
1.36M
  {
468
1.36M
  }
469
543k
  else if (cu.bdpcmM[chType])
470
7.06k
  {
471
7.06k
    m_ipaParam.refFilterFlag = false;
472
7.06k
  }
473
536k
  else if (dirMode == PLANAR_IDX) // Planar intra prediction
474
28.8k
  {
475
28.8k
    m_ipaParam.refFilterFlag = puSize.width * puSize.height > 32 ? true : false;
476
28.8k
  }
477
507k
  else if (!useISP)// HOR, VER and angular modes (MDIS)
478
507k
  {
479
507k
    bool filterFlag = false;
480
507k
    {
481
507k
      const int diff = std::min<int>( abs( predMode - HOR_IDX ), abs( predMode - VER_IDX ) );
482
507k
      const int log2Size = (Log2(puSize.width * puSize.height) >> 1);
483
507k
      CHECK( log2Size >= MAX_INTRA_FILTER_DEPTHS, "Size not supported" );
484
507k
      filterFlag = (diff > m_aucIntraFilter[log2Size]);
485
507k
    }
486
487
    // Selelection of either ([1 2 1] / 4 ) refrence filter OR Gaussian 4-tap interpolation filter
488
507k
    if (filterFlag)
489
410k
    {
490
410k
      const bool isRefFilter       =  isIntegerSlope(absAng);
491
410k
      CHECK( puSize.width * puSize.height <= 32, "DCT-IF interpolation filter is always used for 4x4, 4x8, and 8x4 luma CB" );
492
410k
      m_ipaParam.refFilterFlag     =  isRefFilter;
493
410k
      m_ipaParam.interpolationFlag = !isRefFilter;
494
410k
    }
495
507k
  }
496
1.91M
}
497
498
}   // namespace vvenc
499
500
#ifdef TARGET_SIMD_X86
501
#include "x86/CommonDefX86.h"
502
#endif
503
504
namespace vvenc {
505
506
/** Function for deriving the simplified angular intra predictions.
507
*
508
* This function derives the prediction samples for the angular mode based on the prediction direction indicated by
509
* the prediction mode index. The prediction direction is given by the displacement of the bottom row of the block and
510
* the reference row above the block in the case of vertical prediction or displacement of the rightmost column
511
* of the block and reference column left from the block in the case of the horizontal prediction. The displacement
512
* is signalled at 1/32 pixel accuracy. When projection of the predicted pixel falls inbetween reference samples,
513
* the predicted value for the pixel is linearly interpolated from the reference samples. All reference samples are taken
514
* from the extended main reference.
515
*/
516
//NOTE: Bit-Limit - 25-bit source
517
518
void IntraPrediction::xPredIntraAng( PelBuf& pDst, const CPelBuf& pSrc, const ChannelType channelType, const ClpRng& clpRng)
519
1.21M
{
520
1.21M
  int width =int(pDst.width);
521
1.21M
  int height=int(pDst.height);
522
523
1.21M
  const bool bIsModeVer     = m_ipaParam.isModeVer;
524
1.21M
  const int  multiRefIdx    = m_ipaParam.multiRefIndex;
525
1.21M
  const int  intraPredAngle = m_ipaParam.intraPredAngle;
526
1.21M
  const int  absInvAngle    = m_ipaParam.absInvAngle;
527
528
1.21M
  Pel* refMain;
529
1.21M
  Pel* refSide;
530
531
1.21M
  Pel  refAbove[2 * MAX_CU_SIZE + 3 + 33 * MAX_REF_LINE_IDX];
532
1.21M
  Pel  refLeft [2 * MAX_CU_SIZE + 3 + 33 * MAX_REF_LINE_IDX];
533
534
  // Initialize the Main and Left reference array.
535
1.21M
  if (intraPredAngle < 0)
536
235k
  {
537
235k
    memcpy(&refAbove[height],pSrc.buf,(width + 2 + multiRefIdx)*sizeof(Pel));
538
7.87M
    for (int y = 0; y <= height + 1 + multiRefIdx; y++)
539
7.63M
    {
540
7.63M
      refLeft[y + width] = pSrc.at(y, 1);
541
7.63M
    }
542
235k
    refMain = bIsModeVer ? refAbove + height : refLeft + width;
543
235k
    refSide = bIsModeVer ? refLeft + width : refAbove + height;
544
545
    // Extend the Main reference to the left.
546
235k
    int sizeSide = bIsModeVer ? height : width;
547
7.34M
    for (int k = -sizeSide; k <= -1; k++)
548
7.10M
    {
549
7.10M
      refMain[k] = refSide[std::min((-k * absInvAngle + 256) >> 9, sizeSide)];
550
7.10M
    }
551
235k
  }
552
983k
  else
553
983k
  {
554
983k
    memcpy(&refAbove[0], pSrc.buf, ((m_topRefLength)+multiRefIdx + 1) * sizeof(Pel));
555
43.1M
    for (int y = 0; y <= m_leftRefLength + multiRefIdx; y++)
556
42.2M
    {
557
42.2M
      refLeft[y] = pSrc.at(y, 1);
558
42.2M
    }
559
560
983k
    refMain = bIsModeVer ? refAbove : refLeft;
561
983k
    refSide = bIsModeVer ? refLeft : refAbove;
562
563
    // Extend main reference to right using replication
564
983k
    const int log2Ratio = Log2(width) - Log2(height);
565
983k
    const int s         = std::max<int>(0, bIsModeVer ? log2Ratio : -log2Ratio);
566
983k
    const int maxIndex  = (multiRefIdx << s) + 2;
567
983k
    const int refLength = bIsModeVer ? m_topRefLength : m_leftRefLength;
568
983k
    const Pel val       = refMain[refLength + multiRefIdx];
569
3.16M
    for (int z = 1; z <= maxIndex; z++)
570
2.18M
    {
571
2.18M
      refMain[refLength + multiRefIdx + z] = val;
572
2.18M
    }
573
983k
  }
574
575
  // swap width/height if we are doing a horizontal mode:
576
1.21M
  if (!bIsModeVer)
577
592k
  {
578
592k
    std::swap(width, height);
579
592k
  }
580
1.21M
  Pel tempArray[MAX_CU_SIZE*MAX_CU_SIZE];
581
1.21M
  const int dstStride = bIsModeVer ? pDst.stride : MAX_CU_SIZE;
582
1.21M
  Pel* pDstBuf = bIsModeVer ? pDst.buf : tempArray;
583
584
  // compensate for line offset in reference line buffers
585
1.21M
  refMain += multiRefIdx;
586
1.21M
  refSide += multiRefIdx;
587
588
1.21M
  Pel* pDsty = pDstBuf;
589
590
1.21M
  if( intraPredAngle == 0 )  // pure vertical or pure horizontal
591
466k
  {
592
466k
    if (m_ipaParam.applyPDPC)
593
390k
    {
594
390k
      const int scale   = (Log2(width * height) - 2) >> 2;
595
390k
      IntraHorVerPDPC(pDsty,dstStride,refSide,width,height,scale,refMain,clpRng);
596
390k
    }
597
75.5k
    else
598
75.5k
    {
599
1.89M
      for( int y = 0; y < height; y++ )
600
1.81M
      {
601
1.81M
        memcpy(pDsty,&refMain[1],width*sizeof(Pel));
602
1.81M
        pDsty += dstStride;
603
1.81M
      }
604
75.5k
    }
605
466k
  }
606
753k
  else
607
753k
  {
608
753k
    if( !isIntegerSlope( abs( intraPredAngle ) ) )
609
607k
    {
610
607k
      int deltaPos = intraPredAngle * ( 1 + multiRefIdx );
611
607k
      if( isLuma( channelType ) )
612
550k
      {
613
550k
        if( width <= 2 )
614
0
        {
615
0
          for( int y = 0, deltaPos = intraPredAngle * ( 1 + multiRefIdx );
616
0
               y < height;
617
0
               y++, deltaPos += intraPredAngle, pDsty += dstStride )
618
0
          {
619
0
            const int deltaInt   = deltaPos >> 5;
620
0
            const int deltaFract = deltaPos & 31;
621
622
0
            if( !isIntegerSlope( abs( intraPredAngle ) ) )
623
0
            {
624
0
              const bool useCubicFilter = !m_ipaParam.interpolationFlag;
625
626
0
              const TFilterCoeff intraSmoothingFilter[4] = { TFilterCoeff( 16 - ( deltaFract >> 1 ) ),
627
0
                                                             TFilterCoeff( 32 - ( deltaFract >> 1 ) ),
628
0
                                                             TFilterCoeff( 16 + ( deltaFract >> 1 ) ),
629
0
                                                             TFilterCoeff(      ( deltaFract >> 1 ) ) };
630
0
              const TFilterCoeff* const f =
631
0
                ( useCubicFilter ) ? InterpolationFilter::getChromaFilterTable( deltaFract ) : intraSmoothingFilter;
632
633
0
              for( int x = 0; x < width; x++ )
634
0
              {
635
0
                Pel p[4];
636
637
0
                p[0] = refMain[deltaInt + x + 0];
638
0
                p[1] = refMain[deltaInt + x + 1];
639
0
                p[2] = refMain[deltaInt + x + 2];
640
0
                p[3] = refMain[deltaInt + x + 3];
641
642
0
                Pel val = ( f[0] * p[0] + f[1] * p[1] + f[2] * p[2] + f[3] * p[3] + 32 ) >> 6;
643
644
0
                pDsty[x] = ClipPel( val, clpRng );   // always clip even though not always needed
645
0
              }
646
0
            }
647
0
          }
648
0
        }
649
550k
        else
650
550k
        {
651
550k
          IntraPredAngleLuma(pDstBuf, dstStride, refMain, width, height, deltaPos, intraPredAngle, nullptr, !m_ipaParam.interpolationFlag, clpRng);
652
550k
        }
653
550k
      }
654
57.1k
      else
655
57.1k
      {
656
57.1k
        IntraPredAngleChroma(pDstBuf,dstStride,refMain,width,height,deltaPos,intraPredAngle);
657
57.1k
      }
658
607k
    }
659
145k
    else
660
145k
    {
661
2.18M
      for (int y = 0, deltaPos = intraPredAngle * (1 + multiRefIdx); y<height; y++, deltaPos += intraPredAngle, pDsty += dstStride)
662
2.03M
      {
663
2.03M
        const int deltaInt   = deltaPos >> 5;
664
        // Just copy the integer samples
665
2.03M
        memcpy(pDsty,refMain  + deltaInt + 1,width*sizeof(Pel));
666
2.03M
      }
667
145k
    }
668
669
753k
    if (m_ipaParam.applyPDPC)
670
426k
    {
671
426k
      pDsty = pDstBuf;
672
426k
      IntraAnglePDPC(pDsty,dstStride,refSide,width,height,m_ipaParam.angularScale,absInvAngle);
673
426k
    }
674
753k
  } // else
675
676
  // Flip the block if this is the horizontal mode
677
1.21M
  if( !bIsModeVer )
678
592k
  {
679
592k
    pDst.transposedFrom( CPelBuf( pDstBuf, dstStride, width, height) );
680
592k
  }
681
1.21M
}
682
683
void IntraPrediction::xPredIntraBDPCM(PelBuf& pDst, const CPelBuf& pSrc, const uint32_t dirMode, const ClpRng& clpRng)
684
82.2k
{
685
82.2k
  const int wdt = pDst.width;
686
82.2k
  const int hgt = pDst.height;
687
688
82.2k
  const int strideP = pDst.stride;
689
82.2k
  const int strideS = pSrc.stride;
690
691
82.2k
  CHECK(!(dirMode == 1 || dirMode == 2), "Incorrect BDPCM mode parameter.");
692
693
82.2k
  Pel* pred = &pDst.buf[0];
694
82.2k
  if (dirMode == 1)
695
3.53k
  {
696
3.53k
    Pel  val;
697
48.9k
    for (int y = 0; y < hgt; y++)
698
45.3k
    {
699
45.3k
      val = pSrc.buf[(y + 1) + strideS];
700
659k
      for (int x = 0; x < wdt; x++)
701
614k
      {
702
614k
        pred[x] = val;
703
614k
      }
704
45.3k
      pred += strideP;
705
45.3k
    }
706
3.53k
  }
707
78.6k
  else
708
78.6k
  {
709
806k
    for (int y = 0; y < hgt; y++)
710
728k
    {
711
8.15M
      for (int x = 0; x < wdt; x++)
712
7.42M
      {
713
7.42M
        pred[x] = pSrc.buf[x + 1];
714
7.42M
      }
715
728k
      pred += strideP;
716
728k
    }
717
78.6k
  }
718
82.2k
}
719
720
inline bool isAboveLeftAvailable  ( const CodingUnit &cu, const ChannelType& chType, const Position& posLT );
721
inline int  isAboveAvailable      ( const CodingUnit &cu, const ChannelType& chType, const Position& posLT, const uint32_t numUnits, const uint32_t unitWidth, bool *validFlags );
722
inline int  isLeftAvailable       ( const CodingUnit &cu, const ChannelType& chType, const Position& posLT, const uint32_t numUnits, const uint32_t unitWidth, bool *validFlags );
723
inline int  isAboveRightAvailable ( const CodingUnit &cu, const ChannelType& chType, const Position& posRT, const uint32_t numUnits, const uint32_t unitHeight, bool *validFlags );
724
inline int  isBelowLeftAvailable  ( const CodingUnit &cu, const ChannelType& chType, const Position& posLB, const uint32_t numUnits, const uint32_t unitHeight, bool *validFlags );
725
726
void IntraPrediction::initIntraPatternChType(const CodingUnit &cu, const CompArea& area, const bool forceRefFilterFlag)
727
792k
{
728
792k
  const CodingStructure& cs   = *cu.cs;
729
730
792k
  if (!forceRefFilterFlag)
731
736k
  {
732
736k
    initPredIntraParams(cu, area, *cs.sps);
733
736k
  }
734
735
792k
  Pel *refBufUnfiltered = m_refBuffer[area.compID][PRED_BUF_UNFILTERED];
736
792k
  Pel *refBufFiltered   = m_refBuffer[area.compID][PRED_BUF_FILTERED];
737
738
792k
  setReferenceArrayLengths(area);
739
740
  // ----- Step 1: unfiltered reference samples -----
741
792k
  xFillReferenceSamples( cs.picture->getRecoBuf( area ), refBufUnfiltered, area, cu );
742
  // ----- Step 2: filtered reference samples -----
743
792k
  if( m_ipaParam.refFilterFlag || forceRefFilterFlag )
744
59.1k
  {
745
59.1k
    xFilterReferenceSamples( refBufUnfiltered, refBufFiltered, area, *cs.sps, cu.multiRefIdx );
746
59.1k
  }
747
792k
}
748
749
void IntraPrediction::reset()
750
81.7k
{
751
81.7k
  m_lastCh = MAX_NUM_CH;
752
81.7k
  m_lastArea = Area(0,0,0,0);
753
81.7k
}
754
755
void IntraPrediction::xFillReferenceSamples( const CPelBuf& recoBuf, Pel* refBufUnfiltered, const CompArea& area, const CodingUnit &cu )
756
807k
{
757
807k
  const ChannelType      chType = toChannelType( area.compID );
758
807k
  const CodingStructure &cs     = *cu.cs;
759
807k
  const SPS             &sps    = *cs.sps;
760
807k
  const PreCalcValues   &pcv    = *cs.pcv;
761
762
807k
  const int multiRefIdx         = (area.compID == COMP_Y) ? cu.multiRefIdx : 0;
763
764
807k
  const int  tuWidth            = area.width;
765
807k
  const int  tuHeight           = area.height;
766
807k
  const int  predSize           = m_topRefLength;
767
807k
  const int  predHSize          = m_leftRefLength;
768
807k
  const int predStride = predSize + 1 + multiRefIdx;
769
807k
  m_refBufferStride[area.compID] = predStride;
770
771
807k
  const int  unitWidth          = tuWidth  <= 2 && cu.ispMode && isLuma(area.compID) ? tuWidth  : pcv.minCUSize >> getComponentScaleX(area.compID, sps.chromaFormatIdc);
772
807k
  const int  unitHeight         = tuHeight <= 2 && cu.ispMode && isLuma(area.compID) ? tuHeight : pcv.minCUSize >> getComponentScaleY(area.compID, sps.chromaFormatIdc);
773
774
807k
  const int  totalAboveUnits    = (predSize + (unitWidth - 1)) / unitWidth;
775
807k
  const int  totalLeftUnits     = (predHSize + (unitHeight - 1)) / unitHeight;
776
807k
  const int  totalUnits         = totalAboveUnits + totalLeftUnits + 1; //+1 for top-left
777
778
807k
  if( m_lastArea != area || m_lastCh != chType )
779
81.7k
  {
780
81.7k
    m_lastCh = chType;
781
81.7k
    m_lastArea = area;
782
81.7k
    const int  numAboveUnits      = std::max<int>( tuWidth / unitWidth, 1 );
783
81.7k
    const int  numLeftUnits       = std::max<int>( tuHeight / unitHeight, 1 );
784
81.7k
    const int  numAboveRightUnits = totalAboveUnits - numAboveUnits;
785
81.7k
    const int  numLeftBelowUnits  = totalLeftUnits - numLeftUnits;
786
787
81.7k
    CHECK( numAboveUnits <= 0 || numLeftUnits <= 0 || numAboveRightUnits <= 0 || numLeftBelowUnits <= 0, "Size not supported" );
788
789
    // ----- Step 1: analyze neighborhood -----
790
81.7k
    const Position posLT          = area;
791
81.7k
    const Position posRT          = area.topRight();
792
81.7k
    const Position posLB          = area.bottomLeft();
793
794
81.7k
    m_numIntraNeighbor = 0;
795
796
81.7k
    memset( m_neighborFlags, 0, totalUnits );
797
798
81.7k
    m_neighborFlags[totalLeftUnits] = isAboveLeftAvailable( cu, chType, posLT );
799
81.7k
    m_numIntraNeighbor += m_neighborFlags[totalLeftUnits] ? 1 : 0;
800
81.7k
    m_numIntraNeighbor += isAboveAvailable     ( cu, chType, posLT, numAboveUnits,      unitWidth,  (m_neighborFlags + totalLeftUnits + 1) );
801
81.7k
    m_numIntraNeighbor += isAboveRightAvailable( cu, chType, posRT, numAboveRightUnits, unitWidth,  (m_neighborFlags + totalLeftUnits + 1 + numAboveUnits) );
802
81.7k
    m_numIntraNeighbor += isLeftAvailable      ( cu, chType, posLT, numLeftUnits,       unitHeight, (m_neighborFlags + totalLeftUnits - 1) );
803
81.7k
    m_numIntraNeighbor += isBelowLeftAvailable ( cu, chType, posLB, numLeftBelowUnits,  unitHeight, (m_neighborFlags + totalLeftUnits - 1 - numLeftUnits) );
804
81.7k
  }
805
  // ----- Step 2: fill reference samples (depending on neighborhood) -----
806
807
807k
  const Pel*  srcBuf    = recoBuf.buf;
808
807k
  const int   srcStride = recoBuf.stride;
809
807k
        Pel*  ptrDst    = refBufUnfiltered;
810
807k
  const Pel*  ptrSrc;
811
807k
  const Pel   valueDC   = 1 << (sps.bitDepths[ chType ] - 1);
812
813
814
807k
  if( m_numIntraNeighbor == 0 )
815
260k
  {
816
    // Fill border with DC value
817
7.83M
    for (int j = 0; j <= predSize + multiRefIdx; j++) { ptrDst[j] = valueDC; }
818
7.61M
    for (int i = 0; i <= predHSize + multiRefIdx; i++) { ptrDst[i+predStride] = valueDC; }
819
260k
  }
820
547k
  else if( m_numIntraNeighbor == totalUnits )
821
1.15k
  {
822
    // Fill top-left border and top and top right with rec. samples
823
1.15k
    ptrSrc = srcBuf - (1 + multiRefIdx) * srcStride - (1 + multiRefIdx);
824
93.4k
    for (int j = 0; j <= predSize + multiRefIdx; j++) { ptrDst[j] = ptrSrc[j]; }
825
93.4k
    for (int i = 0; i <= predHSize + multiRefIdx; i++)
826
92.2k
    {
827
92.2k
      ptrDst[i + predStride] = ptrSrc[i * srcStride];
828
92.2k
    }
829
1.15k
  }
830
545k
  else // reference samples are partially available
831
545k
  {
832
    // Fill top-left sample(s) if available
833
545k
    ptrSrc = srcBuf - (1 + multiRefIdx) * srcStride - (1 + multiRefIdx);
834
545k
    ptrDst = refBufUnfiltered;
835
545k
    if (m_neighborFlags[totalLeftUnits])
836
184k
    {
837
184k
      ptrDst[0] = ptrSrc[0];
838
184k
      ptrDst[predStride] = ptrSrc[0];
839
220k
      for (int i = 1; i <= multiRefIdx; i++)
840
36.6k
      {
841
36.6k
        ptrDst[i] = ptrSrc[i];
842
36.6k
        ptrDst[i + predStride] = ptrSrc[i * srcStride];
843
36.6k
      }
844
184k
    }
845
846
    // Fill left & below-left samples if available (downwards)
847
545k
    ptrSrc += (1 + multiRefIdx) * srcStride;
848
545k
    ptrDst += (1 + multiRefIdx) + predStride;
849
8.01M
    for (int unitIdx = totalLeftUnits - 1; unitIdx > 0; unitIdx--)
850
7.47M
    {
851
7.47M
      if (m_neighborFlags[unitIdx])
852
3.24M
      {
853
11.1M
        for (int i = 0; i < unitHeight; i++)
854
7.86M
        {
855
7.86M
          ptrDst[i] = ptrSrc[i*srcStride];
856
7.86M
        }
857
3.24M
      }
858
7.47M
      ptrSrc += unitHeight * srcStride;
859
7.47M
      ptrDst += unitHeight;
860
7.47M
    }
861
    // Fill last below-left sample(s)
862
545k
    if (m_neighborFlags[0])
863
17.5k
    {
864
17.5k
      int lastSample = (predHSize % unitHeight == 0) ? unitHeight : predHSize % unitHeight;
865
70.5k
      for (int i = 0; i < lastSample; i++)
866
53.0k
      {
867
53.0k
        ptrDst[i] = ptrSrc[i*srcStride];
868
53.0k
      }
869
17.5k
    }
870
871
    // Fill above & above-right samples if available (left-to-right)
872
545k
    ptrSrc = srcBuf - srcStride * (1 + multiRefIdx);
873
545k
    ptrDst = refBufUnfiltered + 1 + multiRefIdx;
874
8.02M
    for (int unitIdx = totalLeftUnits + 1; unitIdx < totalUnits - 1; unitIdx++)
875
7.47M
    {
876
7.47M
      if (m_neighborFlags[unitIdx])
877
4.08M
      {
878
4.08M
        memcpy(ptrDst,ptrSrc,unitWidth*sizeof(Pel));
879
4.08M
      }
880
7.47M
      ptrSrc += unitWidth;
881
7.47M
      ptrDst += unitWidth;
882
7.47M
    }
883
    // Fill last above-right sample(s)
884
545k
    if (m_neighborFlags[totalUnits - 1])
885
63.7k
    {
886
63.7k
      int lastSample = (predSize % unitWidth == 0) ? unitWidth : predSize % unitWidth;
887
63.7k
      memcpy(ptrDst,ptrSrc,lastSample*sizeof(Pel));
888
63.7k
    }
889
890
    // pad from first available down to the last below-left
891
545k
    ptrDst = refBufUnfiltered;
892
545k
    int lastAvailUnit = 0;
893
545k
    if (!m_neighborFlags[0])
894
528k
    {
895
528k
      int firstAvailUnit = 1;
896
4.95M
      while (firstAvailUnit < totalUnits && !m_neighborFlags[firstAvailUnit])
897
4.42M
      {
898
4.42M
        firstAvailUnit++;
899
4.42M
      }
900
901
      // first available sample
902
528k
      int firstAvailRow = -1;
903
528k
      int firstAvailCol = 0;
904
528k
      if (firstAvailUnit < totalLeftUnits)
905
329k
      {
906
329k
        firstAvailRow = (totalLeftUnits - firstAvailUnit) * unitHeight + multiRefIdx;
907
329k
      }
908
199k
      else if (firstAvailUnit == totalLeftUnits)
909
0
      {
910
0
        firstAvailRow = multiRefIdx;
911
0
      }
912
199k
      else
913
199k
      {
914
199k
        firstAvailCol = (firstAvailUnit - totalLeftUnits - 1) * unitWidth + 1 + multiRefIdx;
915
199k
      }
916
528k
      const Pel firstAvailSample = ptrDst[firstAvailRow < 0 ? firstAvailCol : firstAvailRow + predStride];
917
918
      // last sample below-left (n.a.)
919
528k
      int lastRow = predHSize + multiRefIdx;
920
921
      // fill left column
922
12.1M
      for (int i = lastRow; i > firstAvailRow; i--)
923
11.5M
      {
924
11.5M
        ptrDst[i + predStride] = firstAvailSample;
925
11.5M
      }
926
      // fill top row
927
528k
      if (firstAvailCol > 0)
928
199k
      {
929
408k
        for (int j = 0; j < firstAvailCol; j++)
930
209k
        {
931
209k
          ptrDst[j] = firstAvailSample;
932
209k
        }
933
199k
      }
934
528k
      lastAvailUnit = firstAvailUnit;
935
528k
    }
936
937
    // pad all other reference samples.
938
545k
    int currUnit = lastAvailUnit + 1;
939
11.6M
    while (currUnit < totalUnits)
940
11.0M
    {
941
11.0M
      if (!m_neighborFlags[currUnit]) // samples not available
942
4.04M
      {
943
        // last available sample
944
4.04M
        int lastAvailRow = -1;
945
4.04M
        int lastAvailCol = 0;
946
4.04M
        if (lastAvailUnit < totalLeftUnits)
947
162k
        {
948
162k
          lastAvailRow = (totalLeftUnits - lastAvailUnit - 1) * unitHeight + multiRefIdx + 1;
949
162k
        }
950
3.88M
        else if (lastAvailUnit == totalLeftUnits)
951
162k
        {
952
162k
          lastAvailCol = multiRefIdx;
953
162k
        }
954
3.71M
        else
955
3.71M
        {
956
3.71M
          lastAvailCol = (lastAvailUnit - totalLeftUnits) * unitWidth + multiRefIdx;
957
3.71M
        }
958
4.04M
        const Pel lastAvailSample = ptrDst[lastAvailRow < 0 ? lastAvailCol : lastAvailRow + predStride];
959
960
        // fill current unit with last available sample
961
4.04M
        if (currUnit < totalLeftUnits)
962
0
        {
963
0
          for (int i = lastAvailRow - 1; i >= lastAvailRow - unitHeight; i--)
964
0
          {
965
0
            ptrDst[i + predStride] = lastAvailSample;
966
0
          }
967
0
        }
968
4.04M
        else if (currUnit == totalLeftUnits)
969
162k
        {
970
324k
          for (int i = 0; i < multiRefIdx + 1; i++)
971
162k
          {
972
162k
            ptrDst[i + predStride] = lastAvailSample;
973
162k
          }
974
324k
          for (int j = 0; j < multiRefIdx + 1; j++)
975
162k
          {
976
162k
            ptrDst[j] = lastAvailSample;
977
162k
          }
978
162k
        }
979
3.88M
        else
980
3.88M
        {
981
3.88M
          int numSamplesInUnit = (currUnit == totalUnits - 1) ? ((predSize % unitWidth == 0) ? unitWidth : predSize % unitWidth) : unitWidth;
982
12.7M
          for (int j = lastAvailCol + 1; j <= lastAvailCol + numSamplesInUnit; j++)
983
8.86M
          {
984
8.86M
            ptrDst[j] = lastAvailSample;
985
8.86M
          }
986
3.88M
        }
987
4.04M
      }
988
11.0M
      lastAvailUnit = currUnit;
989
11.0M
      currUnit++;
990
11.0M
    }
991
545k
  }
992
807k
}
993
994
void IntraPrediction::xFilterReferenceSamples( const Pel* refBufUnfiltered, Pel* refBufFiltered, const CompArea& area, const SPS &sps
995
  , int multiRefIdx
996
  , int stride
997
)
998
59.1k
{
999
59.1k
  if (area.compID != COMP_Y)
1000
0
  {
1001
0
    multiRefIdx = 0;
1002
0
  }
1003
59.1k
  const int predSize = m_topRefLength + multiRefIdx;
1004
59.1k
  const int predHSize = m_leftRefLength + multiRefIdx;
1005
59.1k
  const int predStride = stride == 0 ? predSize + 1 : stride;
1006
1007
1008
59.1k
  const Pel topLeft =
1009
59.1k
    (refBufUnfiltered[0] + refBufUnfiltered[1] + refBufUnfiltered[predStride] + refBufUnfiltered[predStride + 1] + 2)
1010
59.1k
    >> 2;
1011
1012
59.1k
  refBufFiltered[0] = topLeft;
1013
1014
3.39M
  for (int i = 1; i < predSize; i++)
1015
3.33M
  {
1016
3.33M
    refBufFiltered[i] = (refBufUnfiltered[i - 1] + 2 * refBufUnfiltered[i] + refBufUnfiltered[i + 1] + 2) >> 2;
1017
3.33M
  }
1018
59.1k
  refBufFiltered[predSize] = refBufUnfiltered[predSize];
1019
1020
59.1k
  refBufFiltered += predStride;
1021
59.1k
  refBufUnfiltered += predStride;
1022
1023
59.1k
  refBufFiltered[0] = topLeft;
1024
1025
3.40M
  for (int i = 1; i < predHSize; i++)
1026
3.34M
  {
1027
3.34M
    refBufFiltered[i] = (refBufUnfiltered[i - 1] + 2 * refBufUnfiltered[i] + refBufUnfiltered[i + 1] + 2) >> 2;
1028
3.34M
  }
1029
59.1k
  refBufFiltered[predHSize] = refBufUnfiltered[predHSize];
1030
59.1k
}
1031
1032
bool isAboveLeftAvailable(const CodingUnit &cu, const ChannelType& chType, const Position& posLT)
1033
81.7k
{
1034
81.7k
  const CodingStructure& cs = *cu.cs;
1035
81.7k
  const Position refPos = posLT.offset(-1, -1);
1036
1037
81.7k
  return (cs.getCURestricted(refPos, cu, chType) != NULL);
1038
81.7k
}
1039
1040
int isAboveAvailable(const CodingUnit &cu, const ChannelType& chType, const Position& posLT, const uint32_t numUnits, const uint32_t unitWidth, bool *bValidFlags)
1041
361k
{
1042
361k
  const CodingStructure& cs = *cu.cs;
1043
1044
361k
  bool *    validFlags  = bValidFlags;
1045
361k
  int       numIntra    = 0;
1046
361k
  const int maxDx       = numUnits * unitWidth;
1047
361k
  unsigned  checkPosX   = 0;
1048
361k
  bool      valid       = false;
1049
1050
1.53M
  for (int dx = 0; dx < maxDx; dx += unitWidth)
1051
1.38M
  {
1052
1.38M
    if( dx >= checkPosX )
1053
363k
    {
1054
363k
      const Position refPos = posLT.offset(dx, -1);
1055
1056
363k
      const CodingUnit* cuN = cs.getCURestricted(refPos, cu, chType);
1057
363k
      valid = (cuN != NULL);
1058
363k
      if( cuN ) checkPosX = chType == CH_C ? (cuN->Cb().x + cuN->Cb().width - posLT.x) : (cuN->Y().x + cuN->Y().width - posLT.x);
1059
215k
      else break;
1060
363k
    }
1061
1062
1.16M
    numIntra += valid ? 1 : 0;
1063
1.16M
    *validFlags = valid;
1064
1065
1.16M
    validFlags++;
1066
1.16M
  }
1067
1068
361k
  return numIntra;
1069
361k
}
1070
1071
int isLeftAvailable(const CodingUnit &cu, const ChannelType& chType, const Position& posLT, const uint32_t numUnits, const uint32_t unitHeight, bool *bValidFlags)
1072
361k
{
1073
361k
  const CodingStructure& cs = *cu.cs;
1074
1075
361k
  bool *    validFlags = bValidFlags;
1076
361k
  int       numIntra   = 0;
1077
361k
  const int maxDy      = numUnits * unitHeight;
1078
361k
  unsigned checkPosY   = 0;
1079
361k
  bool     valid       = false;
1080
1081
1.42M
  for (int dy = 0; dy < maxDy; dy += unitHeight)
1082
1.29M
  {
1083
1.29M
    if( dy >= checkPosY )
1084
364k
    {
1085
364k
      const Position refPos = posLT.offset(-1, dy);
1086
1087
364k
      const CodingUnit* cuN = cs.getCURestricted(refPos, cu, chType);
1088
364k
      valid = (cuN != NULL);
1089
364k
      if( cuN ) checkPosY = chType == CH_C ? (cuN->Cb().y + cuN->Cb().height - posLT.y) : (cuN->Y().y + cuN->Y().height - posLT.y);
1090
227k
      else break;
1091
364k
    }
1092
1093
18.4E
    numIntra += valid ? 1 : 0;
1094
1.06M
    *validFlags = valid;
1095
1096
1.06M
    validFlags--;
1097
1.06M
  }
1098
1099
361k
  return numIntra;
1100
361k
}
1101
1102
int isAboveRightAvailable(const CodingUnit &cu, const ChannelType& chType, const Position& posRT, const uint32_t numUnits, const uint32_t unitWidth, bool *bValidFlags )
1103
183k
{
1104
183k
  const CodingStructure& cs = *cu.cs;
1105
1106
183k
  bool *    validFlags = bValidFlags;
1107
183k
  int       numIntra   = 0;
1108
183k
  const int maxDx      = numUnits * unitWidth;
1109
183k
  unsigned  checkPosX   = 0;
1110
183k
  bool      valid       = false;
1111
1112
589k
  for (int dx = 0; dx < maxDx; dx += unitWidth)
1113
563k
  {
1114
563k
    if( dx >= checkPosX )
1115
213k
    {
1116
213k
      const Position refPos = posRT.offset(unitWidth + dx, -1);
1117
1118
213k
      const CodingUnit* cuN = cs.getCURestricted(refPos, cu, chType);
1119
213k
      valid = (cuN != NULL);
1120
213k
      if(cuN) checkPosX = chType == CH_C ? (cuN->Cb().x + cuN->Cb().width - (posRT.x + unitWidth)) : (cuN->Y().x + cuN->Y().width - (posRT.x + unitWidth));
1121
157k
      else break;
1122
213k
    }
1123
1124
405k
    numIntra += valid ? 1 : 0;
1125
405k
    *validFlags = valid;
1126
1127
405k
    validFlags++;
1128
405k
  }
1129
1130
183k
  return numIntra;
1131
183k
}
1132
1133
int isBelowLeftAvailable(const CodingUnit &cu, const ChannelType& chType, const Position& posLB, const uint32_t numUnits, const uint32_t unitHeight, bool *bValidFlags )
1134
173k
{
1135
173k
  const CodingStructure& cs = *cu.cs;
1136
1137
173k
  bool *    validFlags = bValidFlags;
1138
173k
  int       numIntra   = 0;
1139
173k
  const int maxDy      = numUnits * unitHeight;
1140
173k
  unsigned  checkPosY   = 0;
1141
173k
  bool      valid       = false;
1142
1143
308k
  for (int dy = 0; dy < maxDy; dy += unitHeight)
1144
301k
  {
1145
301k
    if( dy >= checkPosY )
1146
191k
    {
1147
191k
      const Position refPos = posLB.offset(-1, unitHeight + dy);
1148
1149
191k
      const CodingUnit* cuN = cs.getCURestricted(refPos, cu, chType);
1150
191k
      valid = (cuN != NULL);
1151
191k
      if( cuN ) checkPosY = chType == CH_C ? (cuN->Cb().y + cuN->Cb().height - (posLB.y + unitHeight)) : (cuN->Y().y + cuN->Y().height - (posLB.y + unitHeight));
1152
167k
      else break;
1153
191k
    }
1154
1155
134k
    numIntra += valid ? 1 : 0;
1156
134k
    *validFlags = valid;
1157
1158
134k
    validFlags--;
1159
134k
  }
1160
1161
173k
  return numIntra;
1162
173k
}
1163
1164
// LumaRecPixels
1165
void IntraPrediction::loadLMLumaRecPels(const CodingUnit& cu, const CompArea& chromaArea )
1166
77.2k
{
1167
77.2k
  int iDstStride = 2 * MAX_TB_SIZEY + 1;
1168
77.2k
  Pel* pDst0 = m_pMdlmTemp + iDstStride + 1;
1169
  //assert 420 chroma subsampling
1170
77.2k
  CompArea lumaArea = CompArea( COMP_Y, cu.chromaFormat, chromaArea.lumaPos(), recalcSize( cu.chromaFormat, CH_C, CH_L, chromaArea.size() ) );//needed for correct pos/size (4x4 Tus)
1171
1172
77.2k
  CHECK(lumaArea.width == chromaArea.width && CHROMA_444 != cu.chromaFormat, "");
1173
77.2k
  CHECK(lumaArea.height == chromaArea.height && CHROMA_444 != cu.chromaFormat && CHROMA_422 != cu.chromaFormat, "");
1174
1175
77.2k
  const SizeType uiCWidth = chromaArea.width;
1176
77.2k
  const SizeType uiCHeight = chromaArea.height;
1177
1178
77.2k
  const CPelBuf Src = cu.cs->picture->getRecoBuf( lumaArea );
1179
77.2k
  Pel const* pRecSrc0   = Src.bufAt( 0, 0 );
1180
77.2k
  int iRecStride        = Src.stride;
1181
77.2k
  int logSubWidthC  = getChannelTypeScaleX(CH_C, cu.chromaFormat);
1182
77.2k
  int logSubHeightC = getChannelTypeScaleY(CH_C, cu.chromaFormat);
1183
1184
77.2k
  int iRecStride2       = iRecStride << logSubHeightC;
1185
1186
77.2k
  const CompArea& area = isChroma( cu.chType ) ? chromaArea : lumaArea;
1187
1188
77.2k
  const uint32_t uiTuWidth  = area.width;
1189
77.2k
  const uint32_t uiTuHeight = area.height;
1190
1191
77.2k
  const int  unitWidthLog2  = MIN_CU_LOG2 - getComponentScaleX( area.compID, area.chromaFormat );
1192
77.2k
  const int  unitHeightLog2 = MIN_CU_LOG2 - getComponentScaleY( area.compID, area.chromaFormat );
1193
77.2k
  const int  unitWidth  = 1<<unitWidthLog2;
1194
77.2k
  const int  unitHeight = 1<<unitHeightLog2;
1195
1196
77.2k
  const int  iTUWidthInUnits  = uiTuWidth >> unitWidthLog2;
1197
77.2k
  const int  iTUHeightInUnits = uiTuHeight >> unitHeightLog2;
1198
77.2k
  const int  iAboveUnits      = iTUWidthInUnits;
1199
77.2k
  const int  iLeftUnits       = iTUHeightInUnits;
1200
1201
77.2k
  const int  chromaUnitWidthLog2  = MIN_CU_LOG2 - logSubWidthC;
1202
77.2k
  const int  chromaUnitHeightLog2 = MIN_CU_LOG2 - logSubHeightC;
1203
77.2k
  const int  chromaUnitWidth = 1<<chromaUnitWidthLog2;
1204
77.2k
  const int  chromaUnitHeight = 1<<chromaUnitHeightLog2;
1205
77.2k
  const int  topTemplateSampNum = 2 * uiCWidth; // for MDLM, the number of template samples is 2W or 2H.
1206
77.2k
  const int  leftTemplateSampNum = 2 * uiCHeight;
1207
77.2k
  const int  totalAboveUnits = (topTemplateSampNum + (chromaUnitWidth - 1)) >> chromaUnitWidthLog2;
1208
77.2k
  const int  totalLeftUnits = (leftTemplateSampNum + (chromaUnitHeight - 1)) >> chromaUnitHeightLog2;
1209
77.2k
  const int  totalUnits = totalLeftUnits + totalAboveUnits + 1;
1210
77.2k
  const int  aboveRightUnits = totalAboveUnits - iAboveUnits;
1211
77.2k
  const int  leftBelowUnits = totalLeftUnits - iLeftUnits;
1212
1213
77.2k
  int avaiAboveRightUnits = 0;
1214
77.2k
  int avaiLeftBelowUnits = 0;
1215
77.2k
  bool  bNeighborFlags[4 * MAX_NUM_PART_IDXS_IN_CTU_WIDTH + 1];
1216
77.2k
  memset(bNeighborFlags, 0, totalUnits);
1217
77.2k
  bool aboveIsAvailable, leftIsAvailable;
1218
77.2k
  const ChannelType areaCh = toChannelType( area.compID );
1219
1220
77.2k
  int availlableUnit = isLeftAvailable(cu, areaCh, area.pos(), iLeftUnits, unitHeight, (bNeighborFlags + iLeftUnits + leftBelowUnits - 1));
1221
1222
77.2k
  leftIsAvailable = availlableUnit == iTUHeightInUnits;
1223
1224
77.2k
  availlableUnit = isAboveAvailable(cu, areaCh, area.pos(), iAboveUnits, unitWidth, (bNeighborFlags + iLeftUnits + leftBelowUnits + 1));
1225
1226
77.2k
  aboveIsAvailable = availlableUnit == iTUWidthInUnits;
1227
1228
77.2k
  if (leftIsAvailable)   // if left is not available, then the below left is not available
1229
25.4k
  {
1230
25.4k
    avaiLeftBelowUnits = isBelowLeftAvailable(cu, areaCh, area.bottomLeftComp(area.compID), leftBelowUnits, unitHeight, (bNeighborFlags + leftBelowUnits - 1));
1231
25.4k
  }
1232
1233
77.2k
  if (aboveIsAvailable)   // if above is not available, then  the above right is not available.
1234
27.9k
  {
1235
27.9k
    avaiAboveRightUnits = isAboveRightAvailable(cu, areaCh, area.topRightComp(area.compID), aboveRightUnits, unitWidth, (bNeighborFlags + iLeftUnits + leftBelowUnits + iAboveUnits + 1));
1236
27.9k
  }
1237
1238
77.2k
  Pel*       pDst  = nullptr;
1239
77.2k
  Pel const* piSrc = nullptr;
1240
1241
77.2k
  bool isFirstRowOfCtu = (lumaArea.y & ((cu.cs->sps)->CTUSize - 1)) == 0;
1242
1243
77.2k
  if (aboveIsAvailable)
1244
27.9k
  {
1245
27.9k
    pDst  = pDst0    - iDstStride;
1246
27.9k
    int addedAboveRight = 0;
1247
27.9k
    if ((cu.intraDir[1] == MDLM_L_IDX) || (cu.intraDir[1] == MDLM_T_IDX))
1248
24.3k
    {
1249
24.3k
      addedAboveRight = avaiAboveRightUnits*chromaUnitWidth;
1250
24.3k
    }
1251
617k
    for (int i = 0; i < uiCWidth + addedAboveRight; i++)
1252
589k
    {
1253
589k
      const bool leftPadding = i == 0 && !leftIsAvailable;
1254
589k
      if (cu.chromaFormat == CHROMA_444)
1255
0
      {
1256
0
        piSrc = pRecSrc0 - iRecStride;
1257
0
        pDst[i] = piSrc[i];
1258
0
      }
1259
589k
      else if (isFirstRowOfCtu)
1260
133k
      {
1261
133k
        piSrc   = pRecSrc0 - iRecStride;
1262
133k
        pDst[i] = (piSrc[2 * i] * 2 + piSrc[2 * i - (leftPadding ? 0 : 1)] + piSrc[2 * i + 1] + 2) >> 2;
1263
133k
      }
1264
455k
      else if (cu.chromaFormat == CHROMA_422)
1265
0
      {
1266
0
        piSrc = pRecSrc0 - iRecStride2;
1267
1268
0
        int s = 2;
1269
0
        s += piSrc[2 * i] * 2;
1270
0
        s += piSrc[2 * i - (leftPadding ? 0 : 1)];
1271
0
        s += piSrc[2 * i + 1];
1272
0
        pDst[i] = s >> 2;
1273
0
      }
1274
455k
      else if (cu.cs->sps->verCollocatedChroma )
1275
0
      {
1276
0
        piSrc = pRecSrc0 - iRecStride2;
1277
1278
0
        int s = 4;
1279
0
        s += piSrc[2 * i - iRecStride];
1280
0
        s += piSrc[2 * i] * 4;
1281
0
        s += piSrc[2 * i - (leftPadding ? 0 : 1)];
1282
0
        s += piSrc[2 * i + 1];
1283
0
        s += piSrc[2 * i + iRecStride];
1284
0
        pDst[i] = s >> 3;
1285
0
      }
1286
455k
      else
1287
455k
      {
1288
455k
        piSrc = pRecSrc0 - iRecStride2;
1289
455k
        int s = 4;
1290
455k
        s += piSrc[2 * i] * 2;
1291
455k
        s += piSrc[2 * i + 1];
1292
455k
        s += piSrc[2 * i - (leftPadding ? 0 : 1)];
1293
455k
        s += piSrc[2 * i + iRecStride] * 2;
1294
455k
        s += piSrc[2 * i + 1 + iRecStride];
1295
455k
        s += piSrc[2 * i + iRecStride - (leftPadding ? 0 : 1)];
1296
455k
        pDst[i] = s >> 3;
1297
455k
      }
1298
589k
    }
1299
27.9k
  }
1300
1301
77.2k
  if (leftIsAvailable)
1302
25.4k
  {
1303
25.4k
    pDst  = pDst0    - 1;
1304
25.4k
    piSrc = pRecSrc0 - 1 - logSubWidthC;
1305
1306
25.4k
    int addedLeftBelow = 0;
1307
25.4k
    if ((cu.intraDir[1] == MDLM_L_IDX) || (cu.intraDir[1] == MDLM_T_IDX))
1308
22.5k
    {
1309
22.5k
      addedLeftBelow = avaiLeftBelowUnits*chromaUnitHeight;
1310
22.5k
    }
1311
1312
511k
    for (int j = 0; j < uiCHeight + addedLeftBelow; j++)
1313
486k
    {
1314
486k
      if (cu.chromaFormat == CHROMA_444)
1315
0
      {
1316
0
        pDst[0] = piSrc[0];
1317
0
      }
1318
486k
      else if (cu.chromaFormat == CHROMA_422)
1319
0
      {
1320
0
        int s = 2;
1321
0
        s += piSrc[0] * 2;
1322
0
        s += piSrc[-1];
1323
0
        s += piSrc[1];
1324
0
        pDst[0] = s >> 2;
1325
0
      }
1326
486k
      else if (cu.cs->sps->verCollocatedChroma)
1327
0
      {
1328
0
        const bool abovePadding = j == 0 && !aboveIsAvailable;
1329
1330
0
        int s = 4;
1331
0
        s += piSrc[-(abovePadding ? 0 : iRecStride)];
1332
0
        s += piSrc[0] * 4;
1333
0
        s += piSrc[-1];
1334
0
        s += piSrc[1];
1335
0
        s += piSrc[iRecStride];
1336
0
        pDst[0] = s >> 3;
1337
0
      }
1338
486k
      else
1339
486k
      {
1340
486k
        int s = 4;
1341
486k
        s += piSrc[0] * 2;
1342
486k
        s += piSrc[1];
1343
486k
        s += piSrc[-1];
1344
486k
        s += piSrc[iRecStride] * 2;
1345
486k
        s += piSrc[iRecStride + 1];
1346
486k
        s += piSrc[iRecStride - 1];
1347
486k
        pDst[0] = s >> 3;
1348
486k
      }
1349
1350
486k
      piSrc += iRecStride2;
1351
486k
      pDst  += iDstStride;
1352
486k
    }
1353
25.4k
  }
1354
1355
  // inner part from reconstructed picture buffer
1356
1.06M
  for( int j = 0; j < uiCHeight; j++ )
1357
989k
  {
1358
16.3M
    for( int i = 0; i < uiCWidth; i++ )
1359
15.3M
    {
1360
15.3M
      if (cu.chromaFormat == CHROMA_444)
1361
0
      {
1362
0
        pDst0[i] = pRecSrc0[i];
1363
0
      }
1364
15.3M
      else if (cu.chromaFormat == CHROMA_422)
1365
0
      {
1366
0
        const bool leftPadding  = i == 0 && !leftIsAvailable;
1367
1368
0
        int s = 2;
1369
0
        s += pRecSrc0[2 * i] * 2;
1370
0
        s += pRecSrc0[2 * i - (leftPadding ? 0 : 1)];
1371
0
        s += pRecSrc0[2 * i + 1];
1372
0
        pDst0[i] = s >> 2;
1373
0
      }
1374
15.3M
      else if (cu.cs->sps->verCollocatedChroma)
1375
0
      {
1376
0
        const bool leftPadding  = i == 0 && !leftIsAvailable;
1377
0
        const bool abovePadding = j == 0 && !aboveIsAvailable;
1378
1379
0
        int s = 4;
1380
0
        s += pRecSrc0[2 * i - (abovePadding ? 0 : iRecStride)];
1381
0
        s += pRecSrc0[2 * i] * 4;
1382
0
        s += pRecSrc0[2 * i - (leftPadding ? 0 : 1)];
1383
0
        s += pRecSrc0[2 * i + 1];
1384
0
        s += pRecSrc0[2 * i + iRecStride];
1385
0
        pDst0[i] = s >> 3;
1386
0
      }
1387
15.3M
      else
1388
15.3M
      {
1389
15.3M
        CHECK(cu.chromaFormat != CHROMA_420, "Chroma format must be 4:2:0 for vertical filtering");
1390
15.3M
        const bool leftPadding = i == 0 && !leftIsAvailable;
1391
1392
15.3M
        int s = 4;
1393
15.3M
        s += pRecSrc0[2 * i] * 2;
1394
15.3M
        s += pRecSrc0[2 * i + 1];
1395
15.3M
        s += pRecSrc0[2 * i - (leftPadding ? 0 : 1)];
1396
15.3M
        s += pRecSrc0[2 * i + iRecStride] * 2;
1397
15.3M
        s += pRecSrc0[2 * i + 1 + iRecStride];
1398
15.3M
        s += pRecSrc0[2 * i + iRecStride - (leftPadding ? 0 : 1)];
1399
15.3M
        pDst0[i] = s >> 3;
1400
15.3M
      }
1401
15.3M
    }
1402
1403
989k
    pDst0    += iDstStride;
1404
989k
    pRecSrc0 += iRecStride2;
1405
989k
  }
1406
77.2k
}
1407
1408
void IntraPrediction::xGetLMParameters(const CodingUnit& cu, const ComponentID compID,
1409
                                              const CompArea& chromaArea,
1410
                                              int& a, int& b, int& iShift)
1411
202k
{
1412
202k
  CHECK(compID == COMP_Y, "");
1413
1414
202k
  const SizeType cWidth  = chromaArea.width;
1415
202k
  const SizeType cHeight = chromaArea.height;
1416
1417
202k
  const Position posLT = chromaArea;
1418
1419
202k
  CodingStructure & cs = *(cu.cs);
1420
1421
202k
  const SPS &        sps           = *cs.sps;
1422
202k
  const uint32_t     tuWidth     = chromaArea.width;
1423
202k
  const uint32_t     tuHeight    = chromaArea.height;
1424
202k
  const ChromaFormat nChromaFormat = sps.chromaFormatIdc;
1425
1426
202k
  const int unitWidthLog2    = MIN_CU_LOG2 - getComponentScaleX(chromaArea.compID, nChromaFormat);
1427
202k
  const int unitHeightLog2   = MIN_CU_LOG2 - getComponentScaleY(chromaArea.compID, nChromaFormat);
1428
202k
  const int unitWidth    = 1<<unitWidthLog2;
1429
202k
  const int unitHeight   = 1<<unitHeightLog2;
1430
1431
202k
  const int tuWidthInUnits  = tuWidth >> unitWidthLog2;
1432
202k
  const int tuHeightInUnits = tuHeight >> unitHeightLog2;
1433
202k
  const int aboveUnits      = tuWidthInUnits;
1434
202k
  const int leftUnits       = tuHeightInUnits;
1435
202k
  int topTemplateSampNum = 2 * cWidth; // for MDLM, the template sample number is 2W or 2H;
1436
202k
  int leftTemplateSampNum = 2 * cHeight;
1437
202k
  int totalAboveUnits = (topTemplateSampNum + (unitWidth - 1)) >> unitWidthLog2;
1438
202k
  int totalLeftUnits = (leftTemplateSampNum + (unitHeight - 1)) >> unitHeightLog2;
1439
202k
  int totalUnits = totalLeftUnits + totalAboveUnits + 1;
1440
202k
  int aboveRightUnits = totalAboveUnits - aboveUnits;
1441
202k
  int leftBelowUnits = totalLeftUnits - leftUnits;
1442
202k
  int avaiAboveRightUnits = 0;
1443
202k
  int avaiLeftBelowUnits = 0;
1444
202k
  int avaiAboveUnits = 0;
1445
202k
  int avaiLeftUnits = 0;
1446
1447
202k
  const int curChromaMode = cu.intraDir[1];
1448
202k
  bool neighborFlags[4 * MAX_NUM_PART_IDXS_IN_CTU_WIDTH + 1];
1449
202k
  memset(neighborFlags, 0, totalUnits);
1450
1451
202k
  bool aboveAvailable, leftAvailable;
1452
1453
202k
  int availableUnit = isAboveAvailable(cu, CH_C, posLT, aboveUnits, unitWidth,
1454
202k
    (neighborFlags + leftUnits + leftBelowUnits + 1));
1455
202k
  aboveAvailable = availableUnit == tuWidthInUnits;
1456
1457
202k
  availableUnit = isLeftAvailable(cu, CH_C, posLT, leftUnits, unitHeight,
1458
202k
    (neighborFlags + leftUnits + leftBelowUnits - 1));
1459
202k
  leftAvailable = availableUnit == tuHeightInUnits;
1460
202k
  if (leftAvailable) // if left is not available, then the below left is not available
1461
66.4k
  {
1462
66.4k
    avaiLeftUnits = tuHeightInUnits;
1463
66.4k
    avaiLeftBelowUnits = isBelowLeftAvailable(cu, CH_C, chromaArea.bottomLeftComp(chromaArea.compID), leftBelowUnits, unitHeight, (neighborFlags + leftBelowUnits - 1));
1464
66.4k
  }
1465
202k
  if (aboveAvailable) // if above is not available, then  the above right is not available.
1466
74.1k
  {
1467
74.1k
    avaiAboveUnits = tuWidthInUnits;
1468
74.1k
    avaiAboveRightUnits = isAboveRightAvailable(cu, CH_C, chromaArea.topRightComp(chromaArea.compID), aboveRightUnits, unitWidth, (neighborFlags + leftUnits + leftBelowUnits + aboveUnits + 1));
1469
74.1k
  }
1470
1471
202k
  const int srcStride = 2 * MAX_TB_SIZEY + 1;
1472
202k
  Pel* srcColor0 = m_pMdlmTemp + srcStride + 1;
1473
1474
202k
  Pel* curChroma0 = getPredictorPtr(compID);
1475
1476
202k
  unsigned internalBitDepth = sps.bitDepths[CH_C];
1477
1478
202k
  int minLuma[2] = {  MAX_INT, 0 };
1479
202k
  int maxLuma[2] = { -MAX_INT, 0 };
1480
1481
202k
  Pel* src = srcColor0 - srcStride;
1482
202k
  int actualTopTemplateSampNum = 0;
1483
202k
  int actualLeftTemplateSampNum = 0;
1484
202k
  if (curChromaMode == MDLM_T_IDX)
1485
80.4k
  {
1486
80.4k
    leftAvailable = 0;
1487
80.4k
    avaiAboveRightUnits = avaiAboveRightUnits > (cHeight>>unitWidthLog2) ?  cHeight>>unitWidthLog2 : avaiAboveRightUnits;
1488
80.4k
    actualTopTemplateSampNum = unitWidth*(avaiAboveUnits + avaiAboveRightUnits);
1489
80.4k
  }
1490
121k
  else if (curChromaMode == MDLM_L_IDX)
1491
80.4k
  {
1492
80.4k
    aboveAvailable = 0;
1493
80.4k
    avaiLeftBelowUnits = avaiLeftBelowUnits > (cWidth>>unitHeightLog2) ? cWidth>>unitHeightLog2 : avaiLeftBelowUnits;
1494
80.4k
    actualLeftTemplateSampNum = unitHeight*(avaiLeftUnits + avaiLeftBelowUnits);
1495
80.4k
  }
1496
41.1k
  else if (curChromaMode == LM_CHROMA_IDX)
1497
41.1k
  {
1498
41.1k
    actualTopTemplateSampNum = cWidth;
1499
41.1k
    actualLeftTemplateSampNum = cHeight;
1500
41.1k
  }
1501
202k
  int startPos[2]; //0:Above, 1: Left
1502
202k
  int pickStep[2];
1503
1504
202k
  int aboveIs4 = leftAvailable  ? 0 : 1;
1505
202k
  int leftIs4 =  aboveAvailable ? 0 : 1;
1506
1507
202k
  startPos[0] = actualTopTemplateSampNum >> (2 + aboveIs4);
1508
202k
  pickStep[0] = std::max(1, actualTopTemplateSampNum >> (1 + aboveIs4));
1509
1510
202k
  startPos[1] = actualLeftTemplateSampNum >> (2 + leftIs4);
1511
202k
  pickStep[1] = std::max(1, actualLeftTemplateSampNum >> (1 + leftIs4));
1512
1513
202k
  Pel selectLumaPix[4] = { 0, 0, 0, 0 };
1514
202k
  Pel selectChromaPix[4] = { 0, 0, 0, 0 };
1515
1516
202k
  int cntT, cntL;
1517
202k
  cntT = cntL = 0;
1518
202k
  int cnt = 0;
1519
202k
  if (aboveAvailable)
1520
40.6k
  {
1521
40.6k
    cntT = std::min(actualTopTemplateSampNum, (1 + aboveIs4) << 1);
1522
40.6k
    src = srcColor0 - srcStride;
1523
40.6k
    const Pel *cur = curChroma0 + 1;
1524
201k
    for (int pos = startPos[0]; cnt < cntT; pos += pickStep[0], cnt++)
1525
160k
    {
1526
160k
      selectLumaPix[cnt] = src[pos];
1527
160k
      selectChromaPix[cnt] = cur[pos];
1528
160k
    }
1529
40.6k
  }
1530
1531
202k
  if (leftAvailable)
1532
36.1k
  {
1533
36.1k
    cntL = std::min(actualLeftTemplateSampNum, ( 1 + leftIs4 ) << 1 );
1534
36.1k
    src = srcColor0 - 1;
1535
36.1k
    const Pel *cur = curChroma0 + m_refBufferStride[compID] + 1;
1536
178k
    for (int pos = startPos[1], cnt = 0; cnt < cntL; pos += pickStep[1], cnt++)
1537
142k
    {
1538
142k
      selectLumaPix[cnt + cntT] = src[pos * srcStride];
1539
142k
      selectChromaPix[cnt + cntT] = cur[pos];
1540
142k
    }
1541
36.1k
  }
1542
202k
  cnt = cntL + cntT;
1543
1544
202k
  if (cnt == 2)
1545
16
  {
1546
16
    selectLumaPix[3] = selectLumaPix[0]; selectChromaPix[3] = selectChromaPix[0];
1547
16
    selectLumaPix[2] = selectLumaPix[1]; selectChromaPix[2] = selectChromaPix[1];
1548
16
    selectLumaPix[0] = selectLumaPix[1]; selectChromaPix[0] = selectChromaPix[1];
1549
16
    selectLumaPix[1] = selectLumaPix[3]; selectChromaPix[1] = selectChromaPix[3];
1550
16
  }
1551
1552
202k
  int minGrpIdx[2] = { 0, 2 };
1553
202k
  int maxGrpIdx[2] = { 1, 3 };
1554
202k
  int *tmpMinGrp = minGrpIdx;
1555
202k
  int *tmpMaxGrp = maxGrpIdx;
1556
202k
  if (selectLumaPix[tmpMinGrp[0]] > selectLumaPix[tmpMinGrp[1]]) std::swap(tmpMinGrp[0], tmpMinGrp[1]);
1557
202k
  if (selectLumaPix[tmpMaxGrp[0]] > selectLumaPix[tmpMaxGrp[1]]) std::swap(tmpMaxGrp[0], tmpMaxGrp[1]);
1558
202k
  if (selectLumaPix[tmpMinGrp[0]] > selectLumaPix[tmpMaxGrp[1]]) std::swap(tmpMinGrp, tmpMaxGrp);
1559
202k
  if (selectLumaPix[tmpMinGrp[1]] > selectLumaPix[tmpMaxGrp[0]]) std::swap(tmpMinGrp[1], tmpMaxGrp[0]);
1560
1561
202k
  minLuma[0] = (selectLumaPix[tmpMinGrp[0]] + selectLumaPix[tmpMinGrp[1]] + 1 )>>1;
1562
202k
  minLuma[1] = (selectChromaPix[tmpMinGrp[0]] + selectChromaPix[tmpMinGrp[1]] + 1) >> 1;
1563
202k
  maxLuma[0] = (selectLumaPix[tmpMaxGrp[0]] + selectLumaPix[tmpMaxGrp[1]] + 1 )>>1;
1564
202k
  maxLuma[1] = (selectChromaPix[tmpMaxGrp[0]] + selectChromaPix[tmpMaxGrp[1]] + 1) >> 1;
1565
1566
202k
  if (leftAvailable || aboveAvailable)
1567
75.6k
  {
1568
75.6k
    int diff = maxLuma[0] - minLuma[0];
1569
75.6k
    if (diff > 0)
1570
438
    {
1571
438
      int diffC = maxLuma[1] - minLuma[1];
1572
438
      int x = floorLog2( diff );
1573
438
      static const uint8_t DivSigTable[1 << 4] = {
1574
        // 4bit significands - 8 ( MSB is omitted )
1575
438
        0,  7,  6,  5,  5,  4,  4,  3,  3,  2,  2,  1,  1,  1,  1,  0
1576
438
      };
1577
438
      int normDiff = (diff << 4 >> x) & 15;
1578
438
      int v = DivSigTable[normDiff] | 8;
1579
438
      x += normDiff != 0;
1580
1581
438
      int y = diffC == 0 ? 0 : floorLog2( abs( diffC ) ) + 1;
1582
438
      int add = 1 << y >> 1;
1583
438
      a = (diffC * v + add) >> y;
1584
438
      iShift = 3 + x - y;
1585
438
      if ( iShift < 1 )
1586
0
      {
1587
0
        iShift = 1;
1588
0
        a = ( (a == 0)? 0: (a < 0)? -15 : 15 );   // a=Sign(a)*15
1589
0
      }
1590
438
      b = minLuma[1] - ((a * minLuma[0]) >> iShift);
1591
438
    }
1592
75.1k
    else
1593
75.1k
    {
1594
75.1k
      a = 0;
1595
75.1k
      b = minLuma[1];
1596
75.1k
      iShift = 0;
1597
75.1k
    }
1598
75.6k
  }
1599
126k
  else
1600
126k
  {
1601
126k
    a = 0;
1602
126k
    b = 1 << (internalBitDepth - 1);
1603
126k
    iShift = 0;
1604
126k
  }
1605
202k
}
1606
1607
void IntraPrediction::initIntraMip( const CodingUnit& cu )
1608
42.8k
{
1609
42.8k
  CHECK( cu.lwidth() > cu.cs->sps->getMaxTbSize() || cu.lheight() > cu.cs->sps->getMaxTbSize(), "Error: block size not supported for MIP" );
1610
1611
  // prepare input (boundary) data for prediction
1612
42.8k
  CHECK(m_ipaParam.refFilterFlag, "ERROR: unfiltered refs expected for MIP");
1613
42.8k
  Pel *ptrSrc = getPredictorPtr(COMP_Y);
1614
42.8k
  const int srcStride  = m_refBufferStride[COMP_Y];
1615
42.8k
  const int srcHStride = 2;
1616
1617
42.8k
  m_matrixIntraPred.prepareInputForPred(CPelBuf(ptrSrc, srcStride, srcHStride), cu.Y(), cu.slice->sps->bitDepths[CH_L]);
1618
42.8k
}
1619
1620
void IntraPrediction::predIntraMip( PelBuf &piPred, const CodingUnit& cu )
1621
256k
{
1622
256k
  CHECK( cu.lwidth() > cu.cs->sps->getMaxTbSize() || cu.lheight() > cu.cs->sps->getMaxTbSize(), "Error: block size not supported for MIP" );
1623
256k
  CHECK( cu.lwidth() != (1 << floorLog2(cu.lwidth())) || cu.lheight() != (1 << floorLog2(cu.lheight())), "Error: expecting blocks of size 2^M x 2^N" );
1624
1625
  // generate mode-specific prediction
1626
256k
  const int bitDepth = cu.slice->sps->bitDepths[CH_L];
1627
1628
256k
  CHECK( cu.lwidth() != piPred.stride, " no support yet" );
1629
 
1630
256k
  m_matrixIntraPred.predBlock(piPred.buf, cu.intraDir[CH_L], cu.mipTransposedFlag, bitDepth);
1631
256k
}
1632
1633
void IntraPrediction::initIntraPatternChTypeISP(const CodingUnit& cu, const CompArea& area, PelBuf& recBuf,
1634
  const bool forceRefFilterFlag)
1635
19.6k
{
1636
19.6k
  const CodingStructure& cs = *cu.cs;
1637
1638
19.6k
  if (!forceRefFilterFlag)
1639
19.6k
  {
1640
19.6k
    initPredIntraParams(cu, area, *cs.sps);
1641
19.6k
  }
1642
1643
19.6k
  const Position posLT = area;
1644
19.6k
  bool           isLeftAvail =
1645
19.6k
    (cs.getCURestricted(posLT.offset(-1, 0), cu, CH_L) != NULL);
1646
19.6k
  bool isAboveAvail =
1647
19.6k
    (cs.getCURestricted(posLT.offset(0, -1), cu, CH_L) != NULL);
1648
  // ----- Step 1: unfiltered reference samples -----
1649
19.6k
  if (cu.blocks[area.compID].x == area.x && cu.blocks[area.compID].y == area.y)
1650
15.4k
  {
1651
15.4k
    Pel* refBufUnfiltered = m_refBuffer[area.compID][PRED_BUF_UNFILTERED];
1652
    // With the first subpartition all the CU reference samples are fetched at once in a single call to
1653
    // xFillReferenceSamples
1654
15.4k
    if (cu.ispMode == HOR_INTRA_SUBPARTITIONS)
1655
7.43k
    {
1656
7.43k
      m_leftRefLength = cu.Y().height << 1;
1657
7.43k
      m_topRefLength = cu.Y().width + area.width;
1658
7.43k
    }
1659
8.01k
    else   // if (cu.ispMode == VER_INTRA_SUBPARTITIONS)
1660
8.01k
    {
1661
8.01k
      m_leftRefLength = cu.Y().height + area.height;
1662
8.01k
      m_topRefLength = cu.Y().width << 1;
1663
8.01k
    }
1664
1665
15.4k
    xFillReferenceSamples(cs.picture->getRecoBuf(cu.Y()), refBufUnfiltered, cu.Y(), cu);
1666
1667
    // After having retrieved all the CU reference samples, the number of reference samples is now adjusted for the
1668
    // current subpartition
1669
15.4k
    m_topRefLength = cu.blocks[area.compID].width + area.width;
1670
15.4k
    m_leftRefLength = cu.blocks[area.compID].height + area.height;
1671
15.4k
  }
1672
4.21k
  else
1673
4.21k
  {
1674
4.21k
    m_topRefLength = cu.blocks[area.compID].width + area.width;
1675
4.21k
    m_leftRefLength = cu.blocks[area.compID].height + area.height;
1676
1677
4.21k
    const int predSizeHor = m_topRefLength;
1678
4.21k
    const int predSizeVer = m_leftRefLength;
1679
4.21k
    if (cu.ispMode == HOR_INTRA_SUBPARTITIONS)
1680
3.21k
    {
1681
3.21k
      Pel* src = recBuf.bufAt(0, -1);
1682
3.21k
      Pel* ref = m_refBuffer[area.compID][PRED_BUF_UNFILTERED] + m_refBufferStride[area.compID];
1683
3.21k
      if (isLeftAvail)
1684
0
      {
1685
0
        for (int i = 0; i <= 2 * cu.blocks[area.compID].height - area.height; i++)
1686
0
        {
1687
0
          ref[i] = ref[i + area.height];
1688
0
        }
1689
0
      }
1690
3.21k
      else
1691
3.21k
      {
1692
66.6k
        for (int i = 0; i <= predSizeVer; i++)
1693
63.4k
        {
1694
63.4k
          ref[i] = src[0];
1695
63.4k
        }
1696
3.21k
      }
1697
3.21k
      Pel* dst = m_refBuffer[area.compID][PRED_BUF_UNFILTERED] + 1;
1698
3.21k
      dst[-1] = ref[0];
1699
66.1k
      for (int i = 0; i < area.width; i++)
1700
62.9k
      {
1701
62.9k
        dst[i] = src[i];
1702
62.9k
      }
1703
3.21k
      Pel sample = src[area.width - 1];
1704
3.21k
      dst += area.width;
1705
66.1k
      for (int i = 0; i < predSizeHor - area.width; i++)
1706
62.9k
      {
1707
62.9k
        dst[i] = sample;
1708
62.9k
      }
1709
3.21k
    }
1710
998
    else
1711
998
    {
1712
998
      Pel* src = recBuf.bufAt(-1, 0);
1713
998
      Pel* ref = m_refBuffer[area.compID][PRED_BUF_UNFILTERED];
1714
998
      if (isAboveAvail)
1715
0
      {
1716
0
        for (int i = 0; i <= 2 * cu.blocks[area.compID].width - area.width; i++)
1717
0
        {
1718
0
          ref[i] = ref[i + area.width];
1719
0
        }
1720
0
      }
1721
998
      else
1722
998
      {
1723
21.9k
        for (int i = 0; i <= predSizeHor; i++)
1724
20.9k
        {
1725
20.9k
          ref[i] = src[0];
1726
20.9k
        }
1727
998
      }
1728
998
      Pel* dst = m_refBuffer[area.compID][PRED_BUF_UNFILTERED] + m_refBufferStride[area.compID] + 1;
1729
998
      dst[-1] = ref[0];
1730
22.7k
      for (int i = 0; i < area.height; i++)
1731
21.7k
      {
1732
21.7k
        *dst = *src;
1733
21.7k
        src += recBuf.stride;
1734
21.7k
        dst++;
1735
21.7k
      }
1736
998
      Pel sample = src[-recBuf.stride];
1737
22.7k
      for (int i = 0; i < predSizeVer - area.height; i++)
1738
21.7k
      {
1739
21.7k
        *dst = sample;
1740
21.7k
        dst++;
1741
21.7k
      }
1742
998
    }
1743
4.21k
  }
1744
  // ----- Step 2: filtered reference samples -----
1745
19.6k
  if (m_ipaParam.refFilterFlag || forceRefFilterFlag)
1746
0
  {
1747
0
    Pel* refBufUnfiltered = m_refBuffer[area.compID][PRED_BUF_UNFILTERED];
1748
0
    Pel* refBufFiltered = m_refBuffer[area.compID][PRED_BUF_FILTERED];
1749
0
    xFilterReferenceSamples(refBufUnfiltered, refBufFiltered, area, *cs.sps, cu.multiRefIdx);
1750
0
  }
1751
19.6k
}
1752
1753
void IntraPrediction::setReferenceArrayLengths(const CompArea& area)
1754
792k
{
1755
  // set Top and Left reference samples length
1756
792k
  const int width = area.width;
1757
792k
  const int height = area.height;
1758
1759
792k
  m_leftRefLength = (height << 1);
1760
792k
  m_topRefLength = (width << 1);
1761
792k
}
1762
1763
} // namespace vvenc
1764
1765
//! \}
1766