Coverage Report

Created: 2026-10-28 06:18

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