Coverage Report

Created: 2026-07-30 06:27

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