Coverage Report

Created: 2026-09-01 06:57

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