Coverage Report

Created: 2026-09-02 06:43

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