Coverage Report

Created: 2026-10-17 06:56

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