Coverage Report

Created: 2026-10-28 06:18

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/work/vvdec/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) 2018-2026, Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. & The VVdeC 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
/** \file     Prediction.cpp
44
    \brief    prediction class
45
*/
46
47
#define DONT_UNDEF_SIZE_AWARE_PER_EL_OP
48
49
#include "IntraPrediction.h"
50
51
#include "Unit.h"
52
#include "UnitTools.h"
53
54
#include "Buffer.h"
55
56
#include "dtrace_next.h"
57
#include "Rom.h"
58
59
#include <memory.h>
60
#include <array>
61
62
#include "CommonLib/InterpolationFilter.h"
63
#include "CommonLib/TimeProfiler.h"
64
65
namespace vvdec
66
{
67
68
// ====================================================================================================================
69
// Tables
70
// ====================================================================================================================
71
72
const uint8_t IntraPrediction::m_aucIntraFilter[MAX_NUM_CHANNEL_TYPE][MAX_INTRA_FILTER_DEPTHS] =
73
{
74
  { // Luma
75
    24, //   1xn
76
    24, //   2xn
77
    24, //   4xn
78
    14, //   8xn
79
    2,  //  16xn
80
    0,  //  32xn
81
    0,  //  64xn
82
    0,  // 128xn
83
  },
84
  { // Chroma
85
    40, //   1xn
86
    40, //   2xn
87
    40, //   4xn
88
    28, //   8xn
89
    4,  //  16xn
90
    0,  //  32xn
91
    0,  //  64xn
92
    0,  // 128xn
93
  }
94
};
95
96
const TFilterCoeff g_intraGaussFilter[32][4] = {
97
  { 16, 32, 16,  0 },
98
  { 16, 32, 16,  0 },
99
  { 15, 31, 17,  1 },
100
  { 15, 31, 17,  1 },
101
  { 14, 30, 18,  2 },
102
  { 14, 30, 18,  2 },
103
  { 13, 29, 19,  3 },
104
  { 13, 29, 19,  3 },
105
  { 12, 28, 20,  4 },
106
  { 12, 28, 20,  4 },
107
  { 11, 27, 21,  5 },
108
  { 11, 27, 21,  5 },
109
  { 10, 26, 22,  6 },
110
  { 10, 26, 22,  6 },
111
  {  9, 25, 23,  7 },
112
  {  9, 25, 23,  7 },
113
  {  8, 24, 24,  8 },
114
  {  8, 24, 24,  8 },
115
  {  7, 23, 25,  9 },
116
  {  7, 23, 25,  9 },
117
  {  6, 22, 26, 10 },
118
  {  6, 22, 26, 10 },
119
  {  5, 21, 27, 11 },
120
  {  5, 21, 27, 11 },
121
  {  4, 20, 28, 12 },
122
  {  4, 20, 28, 12 },
123
  {  3, 19, 29, 13 },
124
  {  3, 19, 29, 13 },
125
  {  2, 18, 30, 14 },
126
  {  2, 18, 30, 14 },
127
  {  1, 17, 31, 15 },
128
  {  1, 17, 31, 15 },
129
};
130
131
// Pure vertical prediction with PDPC. A horizontal mode is predicted transposed with the same function.
132
// refMain and refSide point at the reference sample before the first one of the block.
133
void IntraPredHorVerPdpcCore( Pel* pDst, const ptrdiff_t dstStride, const Pel* refMain, const Pel* refSide, const int width, const int height, const int scale, const Pel topLeft, const ClpRng& clpRng )
134
0
{
135
0
  const int lev[4] = { std::min( 3, width ), std::min( 6, width ), std::min( 12, width ), std::min( 24, width ) };
136
137
0
  for( int y = 0; y < height; y++ )
138
0
  {
139
0
    const Pel  left =  refSide[y + 1];
140
0
          Pel *line = &pDst[y * dstStride];
141
0
    for( int x = 0; x < lev[scale]; x++ )
142
0
    {
143
0
      int wL = 32 >> std::min( 31, ( ( x << 1 ) >> scale ) );
144
0
      *line++ = ClipPel( ( wL * ( left - topLeft ) + refMain[x + 1] * ( 1 << 6 ) + 32 ) >> 6, clpRng );
145
0
    }
146
0
    memcpy( line, refMain + lev[scale] + 1, ( width - lev[scale] ) * sizeof( Pel ) );
147
0
  }
148
0
}
149
150
void GetLumaRecPixel420Core (const int width,const int height, const Pel* pRecSrc0,const ptrdiff_t iRecStride,Pel* pDst0,const ptrdiff_t iDstStride)
151
0
{
152
0
  for( int y = 0; y < height; y++ )
153
0
    {
154
0
      for( int x = 0; x < width; x ++ )
155
0
      {
156
0
        pDst0[x + 0 ] = (   pRecSrc0[( (x + 0 ) << 1 )    ] * 2
157
0
                          + pRecSrc0[( (x + 0 ) << 1 ) + 1] * 1
158
0
                          + pRecSrc0[( (x + 0 ) << 1 ) - 1] * 1
159
0
                          + pRecSrc0[( (x + 0 ) << 1 ) + iRecStride] * 2
160
0
                          + pRecSrc0[( (x + 0 ) << 1 ) + 1 + iRecStride] * 1
161
0
                          + pRecSrc0[( (x + 0 ) << 1 ) - 1 + iRecStride] * 1
162
0
                          + 4 ) >> 3;
163
0
      }
164
0
      pDst0 += iDstStride;
165
0
      pRecSrc0 += (iRecStride<<1);
166
0
    }
167
0
}
168
169
/** Function for deriving planar intra prediction. This function derives the prediction samples for planar mode (intra coding).
170
 */
171
172
//NOTE: Bit-Limit - 24-bit source
173
void xPredIntraPlanarCore( const CPelBuf &pSrc, PelBuf &pDst, const SPS& sps )
174
0
{
175
  // with some optimizations gcc gives spurious "-Wmaybe-uninitialized" warnings here
176
  GCC_WARNING_DISABLE_maybe_uninitialized
177
178
0
  const uint32_t width  = pDst.width;
179
0
  const uint32_t height = pDst.height;
180
0
  const uint32_t log2W  = getLog2( width );
181
0
  const uint32_t log2H  = getLog2( height );
182
0
  int leftColumn[MAX_CU_SIZE + 1], topRow[MAX_CU_SIZE + 1], bottomRow[MAX_CU_SIZE], rightColumn[MAX_CU_SIZE];
183
0
  const uint32_t offset = 1 << (log2W + log2H);
184
  // Get left and above reference column and row
185
0
  for( int k = 0; k < width + 1; k++ )
186
0
  {
187
0
    topRow[k] = pSrc.at( k + 1, 0 );
188
0
  }
189
190
0
  for( int k = 0; k < height + 1; k++ )
191
0
  {
192
0
    leftColumn[k] = pSrc.at( 0, k + 1 );
193
0
  }
194
195
  // Prepare intermediate variables used in interpolation
196
0
  int bottomLeft = leftColumn[height];
197
0
  int topRight = topRow[width];
198
199
0
  for( int k = 0; k < width; k++ )
200
0
  {
201
0
    bottomRow[k] = bottomLeft - topRow[k];
202
0
    topRow[k]    = topRow[k] << log2H;
203
0
  }
204
205
0
  for( int k = 0; k < height; k++ )
206
0
  {
207
0
    rightColumn[k] = topRight - leftColumn[k];
208
0
    leftColumn[k]  = leftColumn[k] << log2W;
209
0
  }
210
211
0
  const uint32_t finalShift = 1 + log2W + log2H;
212
0
  const ptrdiff_t stride     = pDst.stride;
213
0
  Pel*       pred       = pDst.buf;
214
0
  for( int y = 0; y < height; y++, pred += stride )
215
0
  {
216
0
    int horPred = leftColumn[y];
217
218
0
    for( int x = 0; x < width; x++ )
219
0
    {
220
0
      horPred += rightColumn[y];
221
0
      topRow[x] += bottomRow[x];
222
223
0
      int vertPred = topRow[x];
224
0
      pred[x]      = ( ( horPred << log2H ) + ( vertPred << log2W ) + offset ) >> finalShift;
225
226
0
    }
227
0
  }
228
0
  GCC_WARNING_RESET
229
0
}
230
231
void  IntraPredSampleFilterCore(Pel *ptrSrc,const ptrdiff_t  srcStride,PelBuf &piPred,const uint32_t uiDirMode,const ClpRng& clpRng)
232
0
{
233
0
  const CPelBuf srcBuf  ( ptrSrc, ( SizeType ) srcStride, ( SizeType ) srcStride );
234
0
  const int     iWidth  = piPred.width;
235
0
  const int     iHeight = piPred.height;
236
0
  PelBuf        dstBuf  = piPred;
237
238
0
  const int scale = ((getLog2(iWidth) - 2 + getLog2(iHeight) - 2 + 2) >> 2);
239
0
  CHECK(scale < 0 || scale > 31, "PDPC: scale < 0 || scale > 31");
240
241
0
#if 1
242
0
  if( uiDirMode == PLANAR_IDX || uiDirMode == DC_IDX )
243
0
  {
244
0
    for( int y = 0; y < iHeight; y++ )
245
0
    {
246
0
      const int wT   = 32 >> std::min(31, ((y << 1) >> scale));
247
//      const Pel left = srcBuf.at(y + 1, 1);
248
0
      const Pel left = srcBuf.at(0, y + 1 );
249
0
      for (int x = 0; x < iWidth; x++)
250
0
      {
251
0
        const int wL    = 32 >> std::min(31, ((x << 1) >> scale));
252
0
        const Pel top   = srcBuf.at(x + 1, 0);
253
0
        const Pel val   = dstBuf.at(x, y);
254
0
        dstBuf.at(x, y) = val + ((wL * (left - val) + wT * (top - val) + 32) >> 6);
255
0
      }
256
0
    }
257
0
  }
258
#else
259
  const int lev[4]={std::min(3,iWidth),std::min(6,iWidth),std::min(12,iWidth),std::min(24,iWidth)};
260
  if (uiDirMode == PLANAR_IDX)
261
  {
262
    for (int y = 0; y < iHeight; y++)
263
    {
264
      int wT = 32 >> std::min(31, ((y << 1) >> scale));
265
      const Pel left = srcBuf.at(0, y + 1);
266
      if (wT)
267
      {
268
        for (int x = 0; x < iWidth; x++)
269
        {
270
          const Pel top = srcBuf.at(x + 1, 0);
271
          int wL = 32 >> std::min(31, ((x << 1) >> scale));
272
          dstBuf.at(x, y) = ClipPel((wL * left + wT * top + (64 - wL - wT) * dstBuf.at(x, y) + 32) >> 6, clpRng);
273
274
        }
275
      }
276
      else
277
      {
278
        for (int x = 0; x < lev[scale]; x++)   // bis wL 0 ist, das ist bei x lev[scale]
279
        {
280
          int wL = 32 >> std::min(31, ((x << 1) >> scale));
281
          dstBuf.at(x, y) = ClipPel((wL * left + (64 - wL) * dstBuf.at(x, y) + 32) >> 6, clpRng);
282
        }
283
      }
284
    }
285
  }
286
  else if (uiDirMode == DC_IDX)
287
  {
288
    const Pel topLeft = srcBuf.at(0, 0);
289
    for (int y = 0; y < iHeight; y++)
290
    {
291
      int wT = 32 >> std::min(31, ((y << 1) >> scale));
292
      const Pel left = srcBuf.at(0, y + 1);
293
      if (wT)
294
      {
295
296
        for (int x = 0; x < iWidth; x++)
297
        {
298
          const Pel top = srcBuf.at(x + 1, 0);
299
          int wL = 32 >> std::min(31, ((x << 1) >> scale));
300
          int wTL = (wL >> 4) + (wT >> 4);
301
          dstBuf.at(x, y) = ClipPel((wL * left + wT * top - wTL * topLeft + (64 - wL - wT + wTL) * dstBuf.at(x, y) + 32) >> 6, clpRng);
302
          }
303
      }
304
      else
305
      {
306
        for (int x = 0; x < lev[scale]; x++)
307
        {
308
          const Pel top = srcBuf.at(x + 1, 0);
309
          int wL = 32 >> std::min(31, ((x << 1) >> scale));
310
          int wTL = (wL >> 4) + (wT >> 4);
311
          dstBuf.at(x, y) = ClipPel((wL * left + wT * top - wTL * topLeft + (64 - wL - wT + wTL) * dstBuf.at(x, y) + 32) >> 6, clpRng);
312
        }
313
314
      }
315
    }
316
  }
317
#endif
318
0
}
319
320
template<typename T>
321
void IntraPredAngleCore(T* pDstBuf,const ptrdiff_t dstStride,T* refMain,int width,int height,int deltaPos,int intraPredAngle,const TFilterCoeff *ff,const bool useCubicFilter,const ClpRng& clpRng)
322
0
{
323
0
    for (int y = 0; y<height; y++ )
324
0
    {
325
0
      const int deltaInt   = deltaPos >> 5;
326
0
      const int deltaFract = deltaPos & ( 32 - 1 );
327
328
0
      Pel p[4];
329
330
0
      int refMainIndex = deltaInt + 1;
331
332
0
      const TFilterCoeff *f = &ff[deltaFract << 2];
333
334
0
      for( int x = 0; x < width; x++, refMainIndex++ )
335
0
      {
336
0
        p[0] = refMain[refMainIndex - 1];
337
0
        p[1] = refMain[refMainIndex    ];
338
0
        p[2] = refMain[refMainIndex + 1];
339
0
        p[3] = refMain[refMainIndex + 2];
340
341
0
        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);
342
343
0
        if( useCubicFilter ) // only cubic filter has negative coefficients and requires clipping
344
0
        {
345
0
          pDstBuf[y*dstStride + x] = ClipPel( pDstBuf[y*dstStride + x], clpRng );
346
0
        }
347
0
      }
348
0
      deltaPos += intraPredAngle;
349
0
    }
350
0
}
351
352
template<typename T>
353
void IntraPredAngleChroma(T* pDstBuf,const ptrdiff_t dstStride,int16_t* pBorder,int width,int height,int deltaPos,int intraPredAngle)
354
0
{
355
0
  for (int y = 0; y<height; y++)
356
0
  {
357
0
    const int deltaInt   = deltaPos >> 5;
358
0
    const int deltaFract = deltaPos & (32 - 1);
359
360
    // Do linear filtering
361
0
    const Pel *pRM = pBorder + deltaInt + 1;
362
0
    int lastRefMainPel = *pRM++;
363
364
0
    for( int x = 0; x < width; pRM++, x++ )
365
0
    {
366
0
      int thisRefMainPel = *pRM;
367
0
      pDstBuf[x + 0] = ( Pel ) ( ( ( 32 - deltaFract )*lastRefMainPel + deltaFract*thisRefMainPel + 16 ) >> 5 );
368
0
      lastRefMainPel = thisRefMainPel;
369
0
    }
370
0
    deltaPos += intraPredAngle;
371
0
    pDstBuf += dstStride;
372
0
  }
373
374
0
}
375
376
// ====================================================================================================================
377
// Constructor / destructor / initialize
378
// ====================================================================================================================
379
380
30.5k
IntraPrediction::IntraPrediction() : m_currChromaFormat( NUM_CHROMA_FORMAT )
381
30.5k
{
382
30.5k
  IntraPredAngleCore4 = IntraPredAngleCore;
383
30.5k
  IntraPredAngleCore8 = IntraPredAngleCore;
384
30.5k
  IntraPredAngleChroma4 = IntraPredAngleChroma;
385
30.5k
  IntraPredAngleChroma8 = IntraPredAngleChroma;
386
387
30.5k
  IntraPredSampleFilter8 = IntraPredSampleFilterCore;
388
30.5k
  IntraPredSampleFilter16 = IntraPredSampleFilterCore;
389
390
30.5k
  xPredIntraPlanar = xPredIntraPlanarCore;
391
30.5k
  IntraPredHorVerPdpc = IntraPredHorVerPdpcCore;
392
393
30.5k
  GetLumaRecPixel420 = GetLumaRecPixel420Core;
394
30.5k
}
395
396
IntraPrediction::~IntraPrediction()
397
30.5k
{
398
30.5k
  destroy();
399
30.5k
}
400
401
void IntraPrediction::destroy()
402
30.5k
{
403
30.5k
}
404
405
void IntraPrediction::init(ChromaFormat chromaFormatIDC, const unsigned bitDepthY)
406
0
{
407
  // if it has been initialised before, but the chroma format has changed, release the memory and start again.
408
0
  if (m_currChromaFormat != chromaFormatIDC)
409
0
  {
410
0
    destroy();
411
0
  }
412
413
0
  m_currChromaFormat = chromaFormatIDC;
414
415
0
  std::fill_n( m_neighborSize, 3, 0 );
416
0
  m_lastCUidx = -1;
417
418
#if ENABLE_SIMD_OPT_INTRAPRED && defined( TARGET_SIMD_X86 )
419
  initIntraPredictionX86();
420
#endif
421
#if ENABLE_SIMD_OPT_INTRAPRED && defined( TARGET_SIMD_ARM )
422
  initIntraPredictionARM();
423
#endif
424
0
}
425
426
// ====================================================================================================================
427
// Public member functions
428
// ====================================================================================================================
429
430
// Function for calculating DC value of the reference samples used in Intra prediction
431
//NOTE: Bit-Limit - 25-bit source
432
Pel IntraPrediction::xGetPredValDc( const CPelBuf &pSrc, const Size &dstSize, const int mrlIdx )
433
0
{
434
0
  CHECK( dstSize.width == 0 || dstSize.height == 0, "Empty area provided" );
435
436
0
  int idx, sum = 0;
437
0
  Pel dcVal;
438
0
  const int  width     = dstSize.width;
439
0
  const int  height    = dstSize.height;
440
0
  const auto denom     = (width == height) ? (width << 1) : std::max(width,height);
441
0
  const auto divShift  = getLog2(denom);
442
0
  const auto divOffset = (denom >> 1);
443
444
0
  if( width >= height )
445
0
  {
446
0
    for( idx = 0; idx < width; idx++ )
447
0
    {
448
0
      sum += pSrc.at( mrlIdx + 1 + idx, 0 );
449
0
    }
450
0
  }
451
0
  if( width <= height )
452
0
  {
453
0
    for( idx = 0; idx < height; idx++ )
454
0
    {
455
0
      sum += pSrc.at( 0, mrlIdx + 1 + idx );
456
0
    }
457
0
  }
458
459
0
  dcVal = (sum + divOffset) >> divShift;
460
0
  return dcVal;
461
0
}
462
463
int IntraPrediction::getWideAngle( int width, int height, int predMode )
464
0
{
465
0
  if ( predMode > DC_IDX && predMode <= VDIA_IDX )
466
0
  {
467
0
    int modeShift[] = { 0, 6, 10, 12, 14, 15 };
468
0
    int deltaSize = abs(getLog2(width) - getLog2(height));
469
0
    if (width > height && predMode < 2 + modeShift[deltaSize])
470
0
    {
471
0
      predMode += (VDIA_IDX - 1);
472
0
    }
473
0
    else if (height > width && predMode > VDIA_IDX - modeShift[deltaSize])
474
0
    {
475
0
      predMode -= (VDIA_IDX - 1);
476
0
    }
477
0
  }
478
0
  return predMode;
479
0
}
480
481
void IntraPrediction::setReferenceArrayLengths( const CompArea &area )
482
0
{
483
  // set Top and Left reference samples length
484
0
  const int  width    = area.width;
485
0
  const int  height   = area.height;
486
487
0
  m_leftRefLength     = (height << 1);
488
0
  m_topRefLength      = (width << 1);
489
490
0
}
491
492
493
494
void IntraPrediction::predIntraAng( const ComponentID compID, PelBuf &piPred, const CodingUnit &cu, const bool useFilteredPredSamples )
495
0
{
496
0
  const ChannelType    channelType  = toChannelType( compID );
497
0
  const int            iWidth       = piPred.width;
498
0
  const int            iHeight      = piPred.height;
499
0
  const Size           cuSize       = Size( cu.blocks[compID].width, cu.blocks[compID].height );
500
0
  CHECK( CU::isMIP(cu, toChannelType(compID)), "We should not get here for MIP." );
501
0
  const uint32_t       uiDirMode    = isLuma( compID ) && cu.bdpcmMode() ? BDPCM_IDX : !isLuma(compID) && cu.bdpcmModeChroma() ? BDPCM_IDX : PU::getFinalIntraMode(cu, channelType);
502
503
0
  CHECKD( iWidth == 2, "Width of 2 is not supported" );
504
505
0
  const int     multiRefIdx = ( compID == COMPONENT_Y ) ? cu.multiRefIdx() : 0;
506
0
  const bool    useISP      = cu.ispMode() && isLuma( compID );
507
0
  const int     srcStride   = m_topRefLength  + 1 + multiRefIdx;
508
0
  const int     srcHStride  = m_leftRefLength + 1 + multiRefIdx;
509
0
  const ClpRng& clpRng      ( cu.slice->clpRng( compID ) );
510
0
        bool    doPDPC      = ( iWidth >= MIN_TB_SIZEY && iHeight >= MIN_TB_SIZEY ) && multiRefIdx == 0;
511
512
0
  const PelBuf& srcBuf = cu.ispMode() && isLuma(compID) ? getISPBuffer( useFilteredPredSamples ) : PelBuf(getPredictorPtr(compID, useFilteredPredSamples), srcStride, srcHStride);
513
514
0
  switch (uiDirMode)
515
0
  {
516
0
    case(PLANAR_IDX): xPredIntraPlanar(srcBuf, piPred, *cu.sps); break;
517
0
    case(DC_IDX):     xPredIntraDc    (srcBuf, piPred, channelType, false, multiRefIdx); break;
518
0
    case(BDPCM_IDX):  xPredIntraBDPCM(srcBuf, piPred, isLuma(compID) ? cu.bdpcmMode() : cu.bdpcmModeChroma(), clpRng); break;
519
0
    case(2):
520
0
    case(DIA_IDX):
521
0
    case(VDIA_IDX):
522
0
      if (getWideAngle(useISP ? cuSize.width : iWidth, useISP ? cuSize.height : iHeight, uiDirMode) == static_cast<int>(uiDirMode)) // check if uiDirMode is not wide-angle
523
0
      {
524
0
        xPredIntraAng(srcBuf, piPred, channelType, uiDirMode, clpRng, *cu.sps, multiRefIdx, useFilteredPredSamples, doPDPC, useISP, cuSize );
525
0
        break;
526
0
      }
527
0
    default:          xPredIntraAng(srcBuf, piPred, channelType, uiDirMode, clpRng, *cu.sps, multiRefIdx, useFilteredPredSamples, doPDPC, useISP, cuSize); break;
528
0
  }
529
530
0
  if( doPDPC && (uiDirMode == PLANAR_IDX || uiDirMode == DC_IDX ) )
531
0
  {
532
0
    if (iWidth>8)
533
0
      IntraPredSampleFilter16(srcBuf.buf,srcBuf.stride,piPred,uiDirMode,clpRng);
534
0
    else
535
0
      IntraPredSampleFilter8(srcBuf.buf,srcBuf.stride,piPred,uiDirMode,clpRng);
536
0
  }
537
0
}
538
539
void IntraPrediction::predIntraChromaLM( const ComponentID compID, PelBuf& piPred, const CodingUnit& cu, const CompArea& chromaArea, int intraDir )
540
0
{
541
0
  int  iLumaStride = 0;
542
0
  PelBuf Temp;
543
0
  if( (intraDir == MDLM_L_IDX) || (intraDir == MDLM_T_IDX) )
544
0
  {
545
0
    iLumaStride = 2 * MAX_TU_SIZE_FOR_PROFILE + 1;
546
0
    Temp = PelBuf( m_piYuvExt[1] + iLumaStride + 1, iLumaStride, Size( chromaArea ) );
547
0
  }
548
0
  else
549
0
  {
550
0
    iLumaStride = MAX_TU_SIZE_FOR_PROFILE + 1;
551
0
    Temp = PelBuf( m_piYuvExt[1] + iLumaStride + 1, iLumaStride, Size( chromaArea ) );
552
0
  }
553
0
  int a, b, iShift;
554
0
  xGetLMParameters( cu, compID, chromaArea, a, b, iShift );
555
556
  ////// final prediction
557
0
  piPred.copyFrom( Temp );
558
0
  piPred.linearTransform( a, iShift, b, true, cu.slice->clpRng( compID ) );
559
0
}
560
561
void IntraPrediction::xPredIntraDc( const CPelBuf &pSrc, PelBuf &pDst, const ChannelType channelType, const bool enableBoundaryFilter, const int mrlIdx )
562
0
{
563
0
  const Pel dcval = xGetPredValDc( pSrc, pDst, mrlIdx );
564
0
  pDst.fill( dcval );
565
0
}
566
567
// Function for deriving the angular Intra predictions
568
void IntraPredAngleCore(Pel *pDstBuf,const int dstStride,Pel* refMain,int width,int height,int deltaPos,int intraPredAngle,const TFilterCoeff *ff,const bool useCubicFilter,const ClpRng& clpRng)
569
0
{
570
0
  for (int y = 0; y<height; y++ )
571
0
  {
572
0
    const int deltaInt   = deltaPos >> 5;
573
0
    const int deltaFract = deltaPos & ( 32 - 1 );
574
575
0
    Pel p[4];
576
577
0
    int refMainIndex = deltaInt + 1;
578
579
0
    const TFilterCoeff *f = &ff[deltaFract << 2];
580
581
0
    for( int x = 0; x < width; x++, refMainIndex++ )
582
0
    {
583
0
      p[0] = refMain[refMainIndex - 1];
584
0
      p[1] = refMain[refMainIndex    ];
585
0
      p[2] = refMain[refMainIndex + 1];
586
0
      p[3] = refMain[refMainIndex + 2];
587
588
0
      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);
589
590
0
      if( useCubicFilter ) // only cubic filter has negative coefficients and requires clipping
591
0
      {
592
0
        pDstBuf[y*dstStride + x] = ClipPel( pDstBuf[y*dstStride + x], clpRng );
593
0
      }
594
0
    }
595
0
    deltaPos += intraPredAngle;
596
0
  }
597
0
}
598
599
600
/** Function for deriving the simplified angular intra predictions.
601
 *
602
 * This function derives the prediction samples for the angular mode based on the prediction direction indicated by
603
 * the prediction mode index. The prediction direction is given by the displacement of the bottom row of the block and
604
 * the reference row above the block in the case of vertical prediction or displacement of the rightmost column
605
 * of the block and reference column left from the block in the case of the horizontal prediction. The displacement
606
 * is signalled at 1/32 pixel accuracy. When projection of the predicted pixel falls inbetween reference samples,
607
 * the predicted value for the pixel is linearly interpolated from the reference samples. All reference samples are taken
608
 * from the extended main reference.
609
 */
610
//NOTE: Bit-Limit - 25-bit source
611
612
void IntraPrediction::xPredIntraAng( const CPelBuf &pSrc, PelBuf &pDst, const ChannelType channelType, const uint32_t dirMode, const ClpRng& clpRng, const SPS& sps,
613
                                           int      multiRefIdx,
614
                                     const bool     useFilteredPredSamples ,
615
                                           bool     &doPDPC,
616
                                     const bool     useISP,
617
                                     const Size     cuSize
618
                                    )
619
0
{
620
0
  int width =int(pDst.width);
621
0
  int height=int(pDst.height);
622
623
0
  CHECK( !( dirMode > DC_IDX && dirMode < NUM_LUMA_MODE ), "Invalid intra dir" );
624
0
  int              predMode           = useISP ? getWideAngle( cuSize.width, cuSize.height, dirMode ) : getWideAngle( width, height, dirMode );
625
0
  const bool       bIsModeVer         = predMode >= DIA_IDX;
626
0
  const int        intraPredAngleMode = (bIsModeVer) ? predMode - VER_IDX : -(predMode - HOR_IDX);
627
0
  const int        absAngMode         = abs(intraPredAngleMode);
628
0
  const int        signAng            = intraPredAngleMode < 0 ? -1 : 1;
629
630
  // Set bitshifts and scale the angle parameter to block size
631
0
  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 };
632
0
  static const int invAngTable[32] = {
633
0
    0,   16384, 8192, 5461, 4096, 2731, 2048, 1638, 1365, 1170, 1024, 910, 819, 712, 630, 565,
634
0
    512, 468,   420,  364,  321,  287,  256,  224,  191,  161,  128,  96,  64,  48,  32,  16
635
0
  };   // (512 * 32) / Angle
636
0
  int invAngle                    = invAngTable[absAngMode];
637
0
  int absAng                      = angTable   [absAngMode];
638
0
  int intraPredAngle              = signAng * absAng;
639
640
0
  Pel* refMain;
641
0
  Pel* refSide;
642
643
0
  Pel  refAbove[2 * MAX_CU_SIZE + 3 + 33 * MAX_REF_LINE_IDX];
644
0
  Pel  refLeft [2 * MAX_CU_SIZE + 3 + 33 * MAX_REF_LINE_IDX];
645
646
  // Initialize the Main and Left reference array.
647
0
  if (intraPredAngle < 0)
648
0
  {
649
0
    for (int x = 0; x <= width + 1 + multiRefIdx; x++)
650
0
    {
651
0
      refAbove[x + height] = pSrc.at(x, 0);
652
0
    }
653
0
    for (int y = 0; y <= height + 1 + multiRefIdx; y++)
654
0
    {
655
0
      refLeft[y + width] = pSrc.at(0, y);
656
0
    }
657
0
    refMain = bIsModeVer ? refAbove + height : refLeft + width;
658
0
    refSide = bIsModeVer ? refLeft  + width : refAbove + height;
659
660
    // Extend the Main reference to the left.
661
0
    int sizeSide = bIsModeVer ? height : width;
662
0
    for (int k = -sizeSide; k <= -1; k++)
663
0
    {
664
0
      refMain[k] = refSide[std::min((-k * invAngle + 256) >> 9, sizeSide)];
665
0
    }
666
0
  }
667
0
  else
668
0
  {
669
    //for (int x = 0; x <= m_topRefLength + multiRefIdx; x++)
670
    //{
671
    //  refAbove[x] = pSrc.at(x, 0);
672
    //}
673
0
    memcpy( refAbove, pSrc.buf, ( m_topRefLength + multiRefIdx + 1 ) * sizeof( Pel ) );
674
0
    for (int y = 0; y <= m_leftRefLength + multiRefIdx; y++)
675
0
    {
676
0
      refLeft[y] = pSrc.at(0, y);
677
0
    }
678
679
0
    refMain = bIsModeVer ? refAbove : refLeft;
680
0
    refSide = bIsModeVer ? refLeft : refAbove;
681
682
    // Extend main reference to right using replication
683
0
    const int log2Ratio = getLog2(width) - getLog2(height);
684
0
    const int s         = std::max<int>(0, bIsModeVer ? log2Ratio : -log2Ratio);
685
0
    const int maxIndex  = (multiRefIdx << s) + 2;
686
0
    const int refLength = bIsModeVer ? m_topRefLength : m_leftRefLength;
687
0
    const Pel val       = refMain[refLength + multiRefIdx];
688
0
    for (int z = 1; z <= maxIndex; z++)
689
0
    {
690
0
      refMain[refLength + multiRefIdx + z] = val;
691
0
    }
692
0
  }
693
694
  // swap width/height if we are doing a horizontal mode:
695
0
  Pel tempArray[MAX_TB_SIZEY*MAX_TB_SIZEY];
696
0
  const ptrdiff_t dstStride = bIsModeVer ? pDst.stride : MAX_TB_SIZEY;
697
0
  Pel *pDstBuf = bIsModeVer ? pDst.buf : tempArray;
698
0
  if (!bIsModeVer)
699
0
  {
700
0
    std::swap(width, height);
701
0
  }
702
703
  // compensate for line offset in reference line buffers
704
0
  refMain += multiRefIdx;
705
0
  refSide += multiRefIdx;
706
707
0
  if( intraPredAngle == 0 )  // pure vertical or pure horizontal
708
0
  {
709
0
    if( doPDPC )
710
0
    {
711
0
      const int scale = ( ( getLog2( width ) - 2 + getLog2( height ) - 2 + 2 ) >> 2 );
712
0
      CHECK( scale < 0 || scale > 3, "PDPC: scale < 0 || scale > 3" );
713
714
0
      IntraPredHorVerPdpc( pDstBuf, dstStride, refMain, refSide, width, height, scale, pSrc.at( 0, 0 ), clpRng );
715
0
    }
716
0
    else
717
0
    {
718
0
      for( int y = 0; y < height; y++ )
719
0
      {
720
0
        memcpy( pDstBuf + y * dstStride, refMain + 1, width * sizeof( Pel ) );
721
0
      }
722
723
0
    }
724
0
  }
725
0
  else
726
0
  {
727
0
    Pel *pDsty=pDstBuf;
728
729
0
    if( !(0 == (absAng & 0x1F)) )
730
0
    {
731
0
      if( isLuma(channelType) )
732
0
      {
733
0
        int deltaPos = intraPredAngle * (1 + multiRefIdx);
734
0
        bool interpolationFlag = false, filterFlag = false;
735
0
        const int diff = std::min<int>( abs( predMode - HOR_IDX ), abs( predMode - VER_IDX ) );
736
0
        const int log2Size = ((getLog2(width) + getLog2(height)) >> 1);
737
0
        CHECKD( log2Size >= MAX_INTRA_FILTER_DEPTHS, "Size not supported" );
738
0
        filterFlag = (diff > m_aucIntraFilter[channelType][log2Size]);
739
740
0
        if( filterFlag )
741
0
        {
742
0
          const bool isRefFilter = 0 == ( absAng & 0x1F );
743
0
          interpolationFlag = !isRefFilter;
744
0
        }
745
0
        const bool useCubicFilter = useISP ? true : ( !interpolationFlag || multiRefIdx > 0 );
746
0
        const TFilterCoeff *f              = (useCubicFilter) ? InterpolationFilter::getChromaFilterTable(0) : g_intraGaussFilter[0];
747
0
        if( ( width & 7 ) == 0 )
748
0
        {
749
0
          IntraPredAngleCore8(pDstBuf,dstStride,refMain,width,height,deltaPos,intraPredAngle,f,useCubicFilter,clpRng);
750
751
0
        }
752
0
        else if( ( width & 3 ) == 0 )
753
0
        {
754
0
          IntraPredAngleCore4(pDstBuf,dstStride,refMain,width,height,deltaPos,intraPredAngle,f,useCubicFilter,clpRng);
755
0
        }
756
0
        else
757
0
        {
758
0
          CHECK( !useISP, "should not happen" );
759
760
0
          for (int y = 0; y<height; y++ )
761
0
          {
762
0
            const int deltaInt   = deltaPos >> 5;
763
0
            const int deltaFract = deltaPos & ( 32 - 1 );
764
765
0
            Pel p[4];
766
767
0
            int refMainIndex = deltaInt + 1;
768
769
0
            const TFilterCoeff *ff = &f[deltaFract << 2];
770
771
0
            for( int x = 0; x < width; x++, refMainIndex++ )
772
0
            {
773
0
              p[0] = refMain[refMainIndex - 1];
774
0
              p[1] = refMain[refMainIndex    ];
775
0
              p[2] = refMain[refMainIndex + 1];
776
0
              p[3] = refMain[refMainIndex + 2];
777
778
0
              pDstBuf[y*dstStride + x] = static_cast<Pel>((static_cast<int>(ff[0] * p[0]) + static_cast<int>(ff[1] * p[1]) + static_cast<int>(ff[2] * p[2]) + static_cast<int>(ff[3] * p[3]) + 32) >> 6);
779
780
0
              if( useCubicFilter ) // only cubic filter has negative coefficients and requires clipping
781
0
              {
782
0
                pDstBuf[y*dstStride + x] = ClipPel( pDstBuf[y*dstStride + x], clpRng );
783
0
              }
784
0
            }
785
0
            deltaPos += intraPredAngle;
786
0
          }
787
0
        }
788
789
0
      }
790
0
      else
791
0
      {
792
0
        int deltaPos = intraPredAngle * (1 + multiRefIdx);
793
0
        if ( width >=8 )
794
0
        {
795
0
          IntraPredAngleChroma8(pDstBuf,dstStride,refMain,width,height,deltaPos,intraPredAngle);
796
0
        }
797
0
        else if( width == 4 )
798
0
        {
799
0
          IntraPredAngleChroma4(pDstBuf,dstStride,refMain,width,height,deltaPos,intraPredAngle);
800
0
        }
801
0
        else
802
0
        {
803
0
          IntraPredAngleChroma(pDstBuf,dstStride,refMain,width,height,deltaPos,intraPredAngle);
804
0
        }
805
0
      }
806
807
0
    }
808
0
    else
809
0
    {
810
0
      for (int y = 0, deltaPos = intraPredAngle * (1 + multiRefIdx); y<height; y++, deltaPos += intraPredAngle, pDsty += dstStride)
811
0
      {
812
0
        const int deltaInt   = deltaPos >> 5;
813
        // Just copy the integer samples
814
0
        memcpy(pDsty,refMain  + deltaInt + 1,width*sizeof(Pel));
815
0
      }
816
0
    }
817
818
0
    pDsty=pDstBuf;
819
0
    for (int y = 0; y<height; y++, pDsty += dstStride)
820
0
    {
821
0
      int angularScale = 0;
822
0
      if( intraPredAngle < 0 )
823
0
      {
824
0
        doPDPC = false;
825
0
      }
826
0
      else if( intraPredAngle > 0 )
827
0
      {
828
0
        const int sideSize = predMode >= DIA_IDX ? pDst.height : pDst.width;
829
0
        const int maxScale = 2;
830
831
0
        angularScale = std::min(maxScale, getLog2(sideSize) - (getLog2(3 * invAngle - 2) - 8));
832
0
        doPDPC &= angularScale >= 0;
833
0
      }
834
835
0
      if( doPDPC )
836
0
      {
837
0
        int invAngleSum = 256;
838
839
0
        for (int x = 0; x < std::min(3 << angularScale, width); x++)
840
0
        {
841
0
          invAngleSum += invAngle;
842
843
0
          int wL   = 32 >> (2 * x >> angularScale);
844
0
          Pel left = refSide[y + (invAngleSum >> 9) + 1];
845
0
          pDsty[x] = pDsty[x] + ((wL * (left - pDsty[x]) + 32) >> 6);
846
0
        }
847
0
      }
848
0
    }
849
0
  }
850
851
  // Flip the block if this is the horizontal mode
852
0
  if( !bIsModeVer )
853
0
  {
854
0
    pDst.transposedFrom( CPelBuf( pDstBuf, dstStride, width, height ) );
855
0
  }
856
0
}
857
858
void IntraPrediction::xPredIntraBDPCM(const CPelBuf &pSrc, PelBuf &pDst, const uint32_t dirMode, const ClpRng& clpRng )
859
0
{
860
0
  const int wdt = pDst.width;
861
0
  const int hgt = pDst.height;
862
863
0
  const ptrdiff_t strideP = pDst.stride;
864
0
  const ptrdiff_t strideS = pSrc.stride;
865
866
0
  CHECK( !( dirMode == 1 || dirMode == 2 ), "Incorrect BDPCM mode parameter." );
867
868
0
  Pel* pred = &pDst.buf[0];
869
0
  if( dirMode == 1 )
870
0
  {
871
0
    Pel  val;
872
0
    for( int y = 0; y < hgt; y++ )
873
0
    {
874
0
      val = pSrc.buf[(y + 1) * strideS];
875
0
      for( int x = 0; x < wdt; x++ )
876
0
      {
877
0
        pred[x] = val;
878
0
      }
879
0
      pred += strideP;
880
0
    }
881
0
  }
882
0
  else
883
0
  {
884
0
    for( int y = 0; y < hgt; y++ )
885
0
    {
886
0
      for( int x = 0; x < wdt; x++ )
887
0
      {
888
0
        pred[x] = pSrc.buf[x + 1];
889
0
      }
890
0
      pred += strideP;
891
0
    }
892
0
  }
893
0
}
894
895
void IntraPrediction::predBlendIntraCiip( PelUnitBuf &predUnit, const CodingUnit &cu )
896
0
{
897
0
  int maxCompID = 1;
898
899
0
  if( isChromaEnabled( cu.chromaFormat ) && cu.chromaSize().width > 2 )
900
0
  {
901
0
    maxCompID = MAX_NUM_COMPONENT;
902
0
  }
903
904
0
  for( int currCompID = 0; currCompID < maxCompID; currCompID++ )
905
0
  {
906
0
    PelBuf&              pred   = predUnit.bufs[ currCompID ];
907
0
    const int            width  = pred.width;
908
0
    const int            height = pred.height;
909
0
    const ptrdiff_t      srcStride = width;
910
0
    const ptrdiff_t      dstStride = pred.stride;
911
0
    Pel*                 dstBuf    = pred.buf;
912
0
    const bool           isUseFilter = currCompID == 0 && IntraPrediction::useFilteredIntraRefSamples( COMPONENT_Y, cu, cu );
913
0
    Pel*                 srcBuf    = m_piYuvExt[!isUseFilter];
914
0
    PelBuf               srcAreaBuf( srcBuf, srcStride, width, height );
915
916
0
    {
917
0
      PROFILER_SCOPE_AND_STAGE_EXT( 1, g_timeProfiler, P_INTRAPRED, *cu.cs, compID );
918
919
0
      initIntraPatternChType( cu.firstTU, cu.blocks[currCompID], isUseFilter );
920
0
      predIntraAng( ComponentID( currCompID ), srcAreaBuf, cu, isUseFilter );
921
0
    }
922
923
0
    CHECKD( width == 2, "Width of 2 is not supported" );
924
925
0
    const Position posBL = cu.Y().bottomLeft();
926
0
    const Position posTR = cu.Y().topRight();
927
928
0
    const CodingUnit* cuLeft  = cu.cs->getCURestricted( posBL.offset( -1, 0 ), cu, CHANNEL_TYPE_LUMA, cu.left );
929
0
    const CodingUnit* cuAbove = cu.cs->getCURestricted( posTR.offset( 0, -1 ), cu, CHANNEL_TYPE_LUMA, cu.above );
930
931
0
    const bool isNeigh0Intra = cuLeft  && ( CU::isIntra( *cuLeft ) );
932
0
    const bool isNeigh1Intra = cuAbove && ( CU::isIntra( *cuAbove ) );
933
934
0
    const int wIntra = 3 - !isNeigh0Intra - !isNeigh1Intra;
935
0
    const int wMerge = 3 - !!isNeigh0Intra - !!isNeigh1Intra;
936
937
0
    for( int y = 0; y < height; y++ )
938
0
    {
939
0
      for( int x = 0; x < width; x += 4 )
940
0
      {
941
0
        dstBuf[y * dstStride + x + 0] = ( wMerge * dstBuf[y * dstStride + x + 0] + wIntra * srcBuf[y * srcStride + x + 0] + 2 ) >> 2;
942
0
        dstBuf[y * dstStride + x + 1] = ( wMerge * dstBuf[y * dstStride + x + 1] + wIntra * srcBuf[y * srcStride + x + 1] + 2 ) >> 2;
943
0
        dstBuf[y * dstStride + x + 2] = ( wMerge * dstBuf[y * dstStride + x + 2] + wIntra * srcBuf[y * srcStride + x + 2] + 2 ) >> 2;
944
0
        dstBuf[y * dstStride + x + 3] = ( wMerge * dstBuf[y * dstStride + x + 3] + wIntra * srcBuf[y * srcStride + x + 3] + 2 ) >> 2;
945
0
      }
946
0
    }
947
0
  }
948
0
}
949
950
inline int isAboveAvailable(const TransformUnit &tu, const ChannelType &chType, const Position &posLT,
951
                            const uint32_t uiNumUnitsInPU, const uint32_t unitWidthLog2);
952
inline int isLeftAvailable(const TransformUnit &tu, const ChannelType &chType, const Position &posLT,
953
                           const uint32_t uiNumUnitsInPU, const uint32_t unitHeightLog2);
954
955
void IntraPrediction::initIntraPatternChType(const TransformUnit &tu, const CompArea &area, const bool bFilterRefSamples)
956
0
{
957
0
  CHECK( area.width == 2, "Width of 2 is not supported" );
958
0
  const CodingStructure& cs   = *tu.cu->cs;
959
960
0
  Pel *refBufUnfiltered   = m_piYuvExt[PRED_BUF_UNFILTERED];
961
0
  Pel *refBufFiltered     = m_piYuvExt[PRED_BUF_FILTERED];
962
963
0
  setReferenceArrayLengths( area );
964
965
  // ----- Step 1: unfiltered reference samples -----
966
0
  xFillReferenceSamples( cs.picture->getRecoBuf( area ), refBufUnfiltered, area, tu );
967
  // ----- Step 2: filtered reference samples -----
968
0
  if( bFilterRefSamples )
969
0
  {
970
0
    xFilterReferenceSamples( refBufUnfiltered, refBufFiltered, area, *cs.sps , tu.cu->multiRefIdx() );
971
0
  }
972
0
}
973
974
void IntraPrediction::initIntraPatternChTypeISP(const CodingUnit& cu, const CompArea& area, PelBuf& recBuf)
975
0
{
976
0
  const CodingStructure& cs = *cu.cs;
977
978
0
  const Position &posLT = area.pos();
979
0
  bool isLeftAvail  = nullptr != cs.getCURestricted( posLT.offset( -1, 0 ), cu, CH_L, posLT.x == cu.lx() ? cu.left : &cu );
980
0
  bool isAboveAvail = nullptr != cs.getCURestricted( posLT.offset( 0, -1 ), cu, CH_L, posLT.y == cu.ly() ? cu.left : &cu );
981
982
  // ----- Step 1: unfiltered reference samples -----
983
0
  if( cu.blocks[area.compID()].x == area.x && cu.blocks[area.compID()].y == area.y )
984
0
  {
985
0
    Pel* refBufUnfiltered = m_piYuvExt[PRED_BUF_UNFILTERED];
986
    // With the first subpartition all the CU reference samples are fetched at once in a single call to xFillReferenceSamples
987
0
    if( cu.ispMode() == HOR_INTRA_SUBPARTITIONS )
988
0
    {
989
0
      m_leftRefLength = cu.Y().height << 1;
990
0
      m_topRefLength  = cu.Y().width + area.width;
991
0
    }
992
0
    else //if (cu.ispMode() == VER_INTRA_SUBPARTITIONS)
993
0
    {
994
0
      m_leftRefLength = cu.Y().height + area.height;
995
0
      m_topRefLength  = cu.Y().width << 1;
996
0
    }
997
998
0
    const int srcStride = m_topRefLength + 1;
999
0
    const int srcHStride = m_leftRefLength + 1;
1000
1001
0
    m_pelBufISP[0] = m_pelBufISPBase[0] = PelBuf(m_piYuvExt[PRED_BUF_UNFILTERED], srcStride, srcHStride);
1002
0
    m_pelBufISP[1] = m_pelBufISPBase[1] = PelBuf(m_piYuvExt[PRED_BUF_FILTERED], srcStride, srcHStride);
1003
1004
0
    xFillReferenceSamples( cs.picture->getRecoBuf( cu.Y() ), refBufUnfiltered, cu.Y(), isLuma( area.compID() ) ? cu.firstTU : *cu.lastTU );
1005
1006
    // After having retrieved all the CU reference samples, the number of reference samples is now adjusted for the current subpartition
1007
0
    m_topRefLength = cu.blocks[area.compID()].width + area.width;
1008
0
    m_leftRefLength = cu.blocks[area.compID()].height + area.height;
1009
0
  }
1010
0
  else
1011
0
  {
1012
    //Now we only need to fetch the newly available reconstructed samples from the previously coded TU
1013
0
    Position tuPos = area;
1014
0
    tuPos.relativeTo(cu.Y());
1015
0
    m_pelBufISP[0] = m_pelBufISPBase[0].subBuf(tuPos, area.size());
1016
0
    m_pelBufISP[1] = m_pelBufISPBase[1].subBuf(tuPos, area.size());
1017
1018
0
    PelBuf& dstBuf = m_pelBufISP[0];
1019
1020
0
    m_topRefLength = cu.blocks[area.compID()].width + area.width;
1021
0
    m_leftRefLength = cu.blocks[area.compID()].height + area.height;
1022
1023
0
    const int predSizeHor = m_topRefLength;
1024
0
    const int predSizeVer = m_leftRefLength;
1025
0
    if (cu.ispMode() == HOR_INTRA_SUBPARTITIONS)
1026
0
    {
1027
0
      Pel* src = recBuf.bufAt(0, -1);
1028
0
      Pel* dst = dstBuf.bufAt(1, 0);
1029
0
      for (int i = 0; i < area.width; i++)
1030
0
      {
1031
0
        dst[i] = src[i];
1032
0
      }
1033
0
      Pel sample = src[area.width - 1];
1034
0
      dst += area.width;
1035
0
      for (int i = 0; i < predSizeHor - area.width; i++)
1036
0
      {
1037
0
        dst[i] = sample;
1038
0
      }
1039
0
      if (!isLeftAvail) //if left is not avaible, then it is necessary to fetch these samples for each subpartition
1040
0
      {
1041
0
        Pel* dst = dstBuf.bufAt(0, 0);
1042
0
        Pel  sample = src[0];
1043
0
        for (int i = 0; i < predSizeVer + 1; i++)
1044
0
        {
1045
0
          *dst = sample;
1046
0
          dst += dstBuf.stride;
1047
0
        }
1048
0
      }
1049
0
    }
1050
0
    else
1051
0
    {
1052
0
      Pel* src = recBuf.bufAt(-1, 0);
1053
0
      Pel* dst = dstBuf.bufAt(0, 1);
1054
0
      for (int i = 0; i < area.height; i++)
1055
0
      {
1056
0
        *dst = *src;
1057
0
        src += recBuf.stride;
1058
0
        dst += dstBuf.stride;
1059
0
      }
1060
0
      Pel sample = src[-recBuf.stride];
1061
0
      for (int i = 0; i < predSizeVer - area.height; i++)
1062
0
      {
1063
0
        *dst = sample;
1064
0
        dst += dstBuf.stride;
1065
0
      }
1066
1067
0
      if (!isAboveAvail) //if above is not avaible, then it is necessary to fetch these samples for each subpartition
1068
0
      {
1069
0
        Pel* dst = dstBuf.bufAt(0, 0);
1070
0
        Pel  sample = recBuf.at(-1, 0);
1071
0
        for (int i = 0; i < predSizeHor + 1; i++)
1072
0
        {
1073
0
          dst[i] = sample;
1074
0
        }
1075
0
      }
1076
0
    }
1077
0
  }
1078
0
}
1079
1080
void IntraPrediction::xFillReferenceSamples( const CPelBuf &recoBuf, Pel* refBufUnfiltered, const CompArea &area, const TransformUnit &tu )
1081
0
{
1082
0
  const ChannelType      chType = toChannelType( area.compID() );
1083
0
  const CodingUnit      &cu     = *tu.cu;
1084
0
  const CodingStructure &cs     = *cu.cs;
1085
0
  const SPS             &sps    = *cs.sps;
1086
0
  const PreCalcValues   &pcv    = *cs.pcv;
1087
1088
0
  const int multiRefIdx         = (area.compID() == COMPONENT_Y) ? cu.multiRefIdx() : 0;
1089
1090
0
  const int  tuWidth            = area.width;
1091
0
  const int  tuHeight           = area.height;
1092
0
  const int  predSize           = m_topRefLength;
1093
0
  const int  predHSize          = m_leftRefLength;
1094
0
  const int  predStride         = predSize + 1 + multiRefIdx;
1095
1096
0
  const int  csx                = getChannelTypeScaleX( chType, pcv.chrFormat );
1097
0
  const int  csy                = getChannelTypeScaleY( chType, pcv.chrFormat );
1098
1099
  // the unit sizes are powers of two, so shifts replace the divisions by them
1100
0
  const int  unitWidthLog2      = pcv.minCUWidthLog2  - csx;
1101
0
  const int  unitHeightLog2     = pcv.minCUHeightLog2 - csy;
1102
0
  const int  unitWidth          = 1 << unitWidthLog2;
1103
0
  const int  unitHeight         = 1 << unitHeightLog2;
1104
1105
0
  const int  totalAboveUnits    = (predSize + (unitWidth - 1)) >> unitWidthLog2;
1106
0
  const int  totalLeftUnits     = (predHSize + (unitHeight - 1)) >> unitHeightLog2;
1107
0
  const int  totalUnits         = totalAboveUnits + totalLeftUnits + 1; //+1 for top-left
1108
0
  const int  numAboveUnits      = tuWidth >> unitWidthLog2;
1109
0
  const int  numLeftUnits       = tuHeight >> unitHeightLog2;
1110
0
  const int  numAboveRightUnits = totalAboveUnits - numAboveUnits;
1111
0
  const int  numLeftBelowUnits  = totalLeftUnits - numLeftUnits;
1112
1113
0
  CHECK( numAboveUnits <= 0 || numLeftUnits <= 0 || numAboveRightUnits <= 0 || numLeftBelowUnits <= 0, "Size not supported" );
1114
1115
  // ----- Step 1: analyze neighborhood -----
1116
0
  if( m_lastCUidx == tu.cu->idx && area.compID() != getFirstComponentOfChannel( tu.cu->chType() ) )
1117
0
  {
1118
0
  }
1119
0
  else
1120
0
  {
1121
0
    const Position posLT = area.pos();
1122
  
1123
0
    const bool sameCTUx  = !!( posLT.x & ( pcv.maxCUWidthMask  >> csx ) );
1124
0
    const bool sameCTUy  = !!( posLT.y & ( pcv.maxCUHeightMask >> csy ) );
1125
0
    const bool sameCTU   = sameCTUx && sameCTUy;
1126
1127
0
    m_neighborSize[0]    = sameCTU ? 1 : !!cu.cs->getCURestricted( posLT.offset( -1, -1 ), cu, chType, cu.left ? cu.left : cu.above );
1128
1129
0
    if( cu.above || area.y > tu.cu->blocks[chType].y )
1130
0
    {
1131
0
      m_neighborSize[1] = numAboveUnits;
1132
1133
0
      Position posAR{ posLT.x + ( PosType ) area.width, posLT.y };
1134
0
      m_neighborSize[1] += isAboveAvailable( tu, chType, posAR, numAboveRightUnits, unitWidthLog2 );
1135
0
    }
1136
0
    else
1137
0
      m_neighborSize[1] = 0;
1138
1139
0
    if( cu.left || area.x > tu.cu->blocks[chType].x )
1140
0
    {
1141
0
      m_neighborSize[2] = numLeftUnits;
1142
1143
0
      Position posLB{ posLT.x, posLT.y + ( PosType ) area.height };
1144
0
      m_neighborSize[2] += isLeftAvailable( tu, chType, posLB, numLeftBelowUnits, unitHeightLog2 );
1145
0
    }
1146
0
    else
1147
0
      m_neighborSize[2] = 0;
1148
1149
0
    m_lastCUidx = tu.cu->idx;
1150
0
  }
1151
1152
0
  int numIntraNeighbor = m_neighborSize[0] + m_neighborSize[1] + m_neighborSize[2];
1153
1154
  // ----- Step 2: fill reference samples (depending on neighborhood) -----
1155
0
  const Pel*  srcBuf    = recoBuf.buf;
1156
0
  const ptrdiff_t srcStride = recoBuf.stride;
1157
0
        Pel*  ptrDst    = refBufUnfiltered;
1158
0
  const Pel*  ptrSrc;
1159
0
  const Pel   valueDC   = 1 << (sps.getBitDepth() - 1);
1160
1161
0
  if( numIntraNeighbor == 0 )
1162
0
  {
1163
    // Fill border with DC value
1164
0
    for (int j = 0; j <= predSize + multiRefIdx; j++) { ptrDst[j] = valueDC; }
1165
0
    for (int i = 1; i <= predHSize + multiRefIdx; i++) { ptrDst[i*predStride] = valueDC; }
1166
0
  }
1167
0
  else if( numIntraNeighbor == totalUnits )
1168
0
  {
1169
    // Fill top-left border and top and top right with rec. samples
1170
0
    ptrSrc = srcBuf - (1 + multiRefIdx) * srcStride - (1 + multiRefIdx);
1171
0
    for (int j = 0; j <= predSize + multiRefIdx; j++) { ptrDst[j] = ptrSrc[j]; }
1172
0
    ptrSrc = srcBuf - multiRefIdx * srcStride - (1 + multiRefIdx);
1173
0
    for (int i = 1; i <= predHSize + multiRefIdx; i++) { ptrDst[i*predStride] = *(ptrSrc); ptrSrc += srcStride; }
1174
0
  }
1175
0
  else // reference samples are partially available
1176
0
  {
1177
    // Fill top-left sample(s) if available
1178
0
    if ( m_neighborSize[2] > 0) {  // left is available
1179
      // Fill left & below-left samples if available (downwards)
1180
0
      ptrSrc = srcBuf - (1 + multiRefIdx);
1181
0
      ptrDst = refBufUnfiltered + (1 + multiRefIdx) * predStride;
1182
0
      int tmpSize = m_neighborSize[2] * unitHeight;
1183
0
      tmpSize = std::min(tmpSize, predHSize);
1184
0
      for (int i = 0; i < tmpSize; i++) {
1185
0
        ptrDst[i * predStride] = ptrSrc[i * srcStride];
1186
0
      }
1187
1188
      // pad
1189
0
      Pel tmpPixel = ptrDst[(tmpSize - 1) * predStride];
1190
0
      for (int i = tmpSize; i < predHSize; i++) {
1191
0
        ptrDst[i * predStride] = tmpPixel;
1192
0
      }
1193
1194
      // Fill top-left sample(s) if available
1195
0
      if ( m_neighborSize[0]) {
1196
0
        ptrSrc = srcBuf - (1 + multiRefIdx) * srcStride - (1 + multiRefIdx);
1197
0
        ptrDst = refBufUnfiltered;
1198
0
        memcpy(ptrDst, ptrSrc, sizeof(Pel) * (multiRefIdx + 1));
1199
0
        for (int i = 1; i <= multiRefIdx; i++) {
1200
0
          ptrDst[i * predStride] = ptrSrc[i * srcStride];
1201
0
        }
1202
0
      } else {                                // pad
1203
0
        ptrSrc = srcBuf - (1 + multiRefIdx);  // left pixel
1204
0
        ptrDst = refBufUnfiltered;
1205
0
        tmpPixel = ptrSrc[0];
1206
0
        ptrDst[0] = tmpPixel;
1207
0
        for (int i = 1; i <= multiRefIdx; i++) {
1208
0
          ptrDst[i] = tmpPixel;
1209
0
          ptrDst[i * predStride] = tmpPixel;
1210
0
        }
1211
0
      }
1212
1213
      // Fill above & above-right samples if available (left-to-right)
1214
0
      if ( m_neighborSize[1]) {
1215
0
        ptrSrc = srcBuf - srcStride * (1 + multiRefIdx);
1216
0
        ptrDst = refBufUnfiltered + 1 + multiRefIdx;
1217
0
        tmpSize = m_neighborSize[1] * unitWidth;
1218
0
        tmpSize = std::min(tmpSize, predSize);
1219
0
        memcpy(ptrDst, ptrSrc, tmpSize * sizeof(Pel));
1220
        // pad
1221
0
        Pel tmpPixel = ptrDst[tmpSize - 1];
1222
0
        for (int i = tmpSize; i < predSize; i++) {
1223
0
          ptrDst[i] = tmpPixel;
1224
0
        }
1225
0
      } else {  // all not available, pad
1226
0
        ptrSrc = srcBuf - srcStride * (1 + multiRefIdx);
1227
0
        ptrDst = refBufUnfiltered + 1 + multiRefIdx;
1228
0
        Pel tmpPixel = ptrDst[-1];
1229
0
        std::fill_n(ptrDst, predSize, tmpPixel);
1230
0
      }
1231
0
    } else {  // left is not available, top must be available
1232
      // Fill above & above-right samples (left-to-right)
1233
0
      ptrSrc = srcBuf - srcStride * (1 + multiRefIdx);
1234
0
      ptrDst = refBufUnfiltered + 1 + multiRefIdx;
1235
0
      int tmpSize = m_neighborSize[1] * unitWidth;
1236
0
      tmpSize = std::min(tmpSize, predSize);
1237
0
      memcpy(ptrDst, ptrSrc, tmpSize * sizeof(Pel));
1238
      // pad
1239
0
      Pel tmpPixel = ptrDst[tmpSize - 1];
1240
0
      for (int i = tmpSize; i < predSize; i++) {
1241
0
        ptrDst[i] = tmpPixel;
1242
0
      }
1243
1244
0
      tmpPixel = ptrSrc[0];
1245
      // pad top-left sample(s)
1246
0
      ptrDst = refBufUnfiltered;
1247
0
      ptrDst[0] = tmpPixel;
1248
0
      for (int i = 1; i <= multiRefIdx; i++) {
1249
0
        ptrDst[i] = tmpPixel;
1250
0
        ptrDst[i * predStride] = tmpPixel;
1251
0
      }
1252
1253
      // pad left sample(s)
1254
0
      ptrDst = refBufUnfiltered + (1 + multiRefIdx) * predStride;
1255
0
      for (int i = 0; i < predHSize; i++) {
1256
0
        ptrDst[i * predStride] = tmpPixel;
1257
0
      }
1258
0
    }
1259
0
  }
1260
0
}
1261
1262
void IntraPrediction::xFilterReferenceSamples( const Pel* refBufUnfiltered, Pel* refBufFiltered, const CompArea &area, const SPS &sps, int multiRefIdx, ptrdiff_t stride ) const
1263
0
{
1264
0
  if (area.compID() != COMPONENT_Y)
1265
0
  {
1266
0
    multiRefIdx = 0;
1267
0
  }
1268
0
  const int       predSize   = m_topRefLength  + multiRefIdx;
1269
0
  const int       predHSize  = m_leftRefLength + multiRefIdx;
1270
0
  const ptrdiff_t predStride = stride == 0 ? predSize + 1 : stride;
1271
1272
1273
1274
  // Regular reference sample filter
1275
0
  const Pel *piSrcPtr  = refBufUnfiltered + (predStride * predHSize); // bottom left
1276
0
        Pel *piDestPtr = refBufFiltered   + (predStride * predHSize); // bottom left
1277
1278
  // bottom left (not filtered)
1279
0
  *piDestPtr = *piSrcPtr;
1280
0
  piDestPtr -= predStride;
1281
0
  piSrcPtr  -= predStride;
1282
  //left column (bottom to top)
1283
0
  for( int i = 1; i < predHSize; i++, piDestPtr -= predStride, piSrcPtr -= predStride)
1284
0
  {
1285
0
    *piDestPtr = (piSrcPtr[predStride] + 2 * piSrcPtr[0] + piSrcPtr[-predStride] + 2) >> 2;
1286
0
  }
1287
  //top-left
1288
0
  *piDestPtr = (piSrcPtr[predStride] + 2 * piSrcPtr[0] + piSrcPtr[1] + 2) >> 2;
1289
0
  piDestPtr++;
1290
0
  piSrcPtr++;
1291
  //top row (left-to-right)
1292
0
  for( uint32_t i=1; i < predSize; i++, piDestPtr++, piSrcPtr++ )
1293
0
  {
1294
0
    *piDestPtr = (piSrcPtr[1] + 2 * piSrcPtr[0] + piSrcPtr[-1] + 2) >> 2;
1295
0
  }
1296
  // top right (not filtered)
1297
0
  *piDestPtr=*piSrcPtr;
1298
0
}
1299
1300
static bool getUseFilterRef( const int predMode )
1301
0
{
1302
0
  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 };
1303
1304
0
  const int     intraPredAngleMode = ( predMode >= DIA_IDX ) ? predMode - VER_IDX : -( predMode - HOR_IDX );
1305
1306
0
  const int     absAngMode         = abs(intraPredAngleMode);
1307
0
  const int     absAng             = angTable   [absAngMode];
1308
1309
0
  return 0 == ( absAng & 0x1F );
1310
0
}
1311
1312
bool IntraPrediction::useFilteredIntraRefSamples( const ComponentID &compID, const CodingUnit &cu, const UnitArea &tuArea )
1313
0
{
1314
  //const SPS         &sps    = *cu.sps;
1315
0
  const ChannelType  chType = toChannelType( compID );
1316
1317
  // high level conditions
1318
  //if( sps.getSpsRangeExtension().getIntraSmoothingDisabledFlag() )  { return false; }
1319
  //if( !isLuma( chType ) )                                           { return false; }
1320
  //if( cu.ispMode() && isLuma(compID) )                              { return false; }
1321
  //if( CU::isMIP( cu, chType ) )                                     { return false; }
1322
0
  if( cu.multiRefIdx() )                                            { return false; }
1323
0
  if( cu.bdpcmMode() )                                              { return false; }
1324
1325
  // pred. mode related conditions
1326
0
  const int dirMode = PU::getFinalIntraMode( cu, chType );
1327
0
  if (dirMode == DC_IDX)                                            { return false; }
1328
0
  if (dirMode == PLANAR_IDX)
1329
0
  {
1330
0
    return tuArea.blocks[compID].area() > 32 ? true : false;
1331
0
  }
1332
1333
0
  const int predMode = getWideAngle(tuArea.blocks[compID].width, tuArea.blocks[compID].height, dirMode);
1334
0
  const int diff     = std::min<int>( abs( predMode - HOR_IDX ), abs( predMode - VER_IDX ) );
1335
0
  const int log2Size = ( ( getLog2( tuArea.blocks[compID].width ) + getLog2( tuArea.blocks[compID].height ) ) >> 1 );
1336
0
  CHECKD( log2Size >= MAX_INTRA_FILTER_DEPTHS, "Size not supported" );
1337
0
  return diff > m_aucIntraFilter[ chType ][ log2Size ] && getUseFilterRef( predMode );
1338
0
}
1339
1340
static inline TransformUnit const* getTU( const CodingUnit& cu, const Position& pos, const ChannelType chType )
1341
0
{
1342
0
  const TransformUnit* ptu = &cu.firstTU;
1343
1344
0
  if( !ptu->next ) return ptu;
1345
1346
0
  while( !( ptu->blocks[chType].x + ptu->blocks[chType].width > pos.x && ptu->blocks[chType].y + ptu->blocks[chType].height > pos.y ) )
1347
0
  {
1348
0
    ptu = ptu->next;
1349
0
  }
1350
1351
0
  return ptu;
1352
0
}
1353
1354
int isAboveAvailable(const TransformUnit &tu, const ChannelType &chType, const Position &posLT,
1355
                     const uint32_t uiNumUnitsInPU, const uint32_t unitWidthLog2)
1356
0
{
1357
0
  const CodingUnit      &cu = *tu.cu;
1358
0
  const CodingStructure &cs = *cu.cs;
1359
1360
0
  int maxDx = uiNumUnitsInPU << unitWidthLog2;
1361
0
  Position refPos = posLT.offset(0, -1);
1362
0
  const TransformUnit *pcTUAbove = nullptr;
1363
0
  const int currTUIdx = tu.idx;
1364
0
  int dx = 0;
1365
1366
0
  while( dx < maxDx )
1367
0
  {
1368
0
    const CodingUnit* cuAbove = cs.getCURestricted( refPos, cu, chType, pcTUAbove ? nullptr : cu.above );
1369
1370
0
    if( !cuAbove ) break;
1371
0
    pcTUAbove = getTU( *cuAbove, refPos, chType );
1372
0
    if( cuAbove->ctuData == cu.ctuData && pcTUAbove->idx >= currTUIdx ) break;
1373
1374
0
    int diff  = ( int ) pcTUAbove->blocks[chType].width - refPos.x + pcTUAbove->blocks[chType].x;
1375
0
    dx       += diff;
1376
0
    refPos.x += diff;
1377
0
  }
1378
1379
0
  int neighborSize = dx >> unitWidthLog2;
1380
0
  neighborSize = std::min<int>( neighborSize, uiNumUnitsInPU );
1381
0
  return neighborSize;
1382
0
}
1383
1384
int isLeftAvailable(const TransformUnit &tu, const ChannelType &chType, const Position &posLT,
1385
                    const uint32_t uiNumUnitsInPU, const uint32_t unitHeightLog2)
1386
0
{
1387
0
  const CodingUnit      &cu = *tu.cu;
1388
0
  const CodingStructure &cs = *cu.cs;
1389
1390
0
  int maxDy = uiNumUnitsInPU << unitHeightLog2;
1391
0
  Position refPos = posLT.offset(-1, 0);
1392
0
  const TransformUnit *pcTULeft = nullptr;
1393
0
  int currTUIdx = tu.idx;
1394
0
  int dy = 0;
1395
1396
0
  while( dy < maxDy )
1397
0
  {
1398
0
    const CodingUnit* cuLeft = cs.getCURestricted( refPos, cu, chType, pcTULeft ? nullptr : cu.left );
1399
1400
0
    if( !cuLeft ) break;
1401
0
    pcTULeft = getTU( *cuLeft, refPos, chType );
1402
0
    if( cuLeft->ctuData == cu.ctuData && pcTULeft->idx >= currTUIdx ) break;
1403
1404
0
    int diff  = ( int ) pcTULeft->blocks[chType].height - refPos.y + pcTULeft->blocks[chType].y;
1405
0
    dy       += diff;
1406
0
    refPos.y += diff;
1407
0
  }
1408
1409
0
  int neighborSize = dy >> unitHeightLog2;
1410
0
  neighborSize = std::min<int>( neighborSize, uiNumUnitsInPU );
1411
0
  return neighborSize;
1412
0
}
1413
// LumaRecPixels
1414
NO_THREAD_SANITIZE void IntraPrediction::xGetLumaRecPixels(const CodingUnit &cu, CompArea chromaArea)
1415
0
{
1416
0
  int iDstStride = 0;
1417
0
  Pel* pDst0 = 0;
1418
0
  int curChromaMode = cu.intraDir[1];
1419
0
  if ((curChromaMode == MDLM_L_IDX) || (curChromaMode == MDLM_T_IDX))
1420
0
  {
1421
0
    iDstStride = 2 * MAX_TU_SIZE_FOR_PROFILE + 1;
1422
0
    pDst0      = m_piYuvExt[1] + iDstStride + 1;
1423
0
  }
1424
0
  else
1425
0
  {
1426
0
    iDstStride = MAX_TU_SIZE_FOR_PROFILE + 1;
1427
0
    pDst0      = m_piYuvExt[1] + iDstStride + 1; //MMLM_SAMPLE_NEIGHBOR_LINES;
1428
0
  }
1429
  //assert 420 chroma subsampling
1430
0
  CompArea lumaArea = CompArea( COMPONENT_Y, chromaArea.lumaPos( cu.chromaFormat),
1431
0
                                recalcSize( cu.chromaFormat, CHANNEL_TYPE_CHROMA, CHANNEL_TYPE_LUMA, chromaArea.size() ) );//needed for correct pos/size (4x4 Tus)
1432
1433
1434
0
  CHECK( lumaArea.width  == chromaArea.width  && CHROMA_444 != cu.chromaFormat, "" );
1435
0
  CHECK( lumaArea.height == chromaArea.height && CHROMA_444 != cu.chromaFormat && CHROMA_422 != cu.chromaFormat, "" );
1436
1437
0
  const SizeType uiCWidth = chromaArea.width;
1438
0
  const SizeType uiCHeight = chromaArea.height;
1439
1440
0
  CPelBuf Src = cu.cs->picture->getRecoBuf( lumaArea );
1441
0
  Pel const* pRecSrc0   = Src.bufAt( 0, 0 );
1442
0
  ptrdiff_t iRecStride  = Src.stride;
1443
0
  int logSubWidthC  = getChannelTypeScaleX(CHANNEL_TYPE_CHROMA, cu.chromaFormat);
1444
0
  int logSubHeightC = getChannelTypeScaleY(CHANNEL_TYPE_CHROMA, cu.chromaFormat);
1445
1446
1447
0
  ptrdiff_t iRecStride2 = iRecStride << logSubHeightC;    // TODO: really Height here? not Width?
1448
0
  const int mult        =          1 << logSubWidthC ;
1449
1450
0
  const CompArea& area = isChroma( cu.chType() ) ? chromaArea : lumaArea;
1451
1452
0
  const uint32_t uiTuWidth  = area.width;
1453
0
  const uint32_t uiTuHeight = area.height;
1454
1455
0
  int iBaseUnitSize = ( 1 << MIN_CU_LOG2 );
1456
1457
0
  const int  iUnitWidth       = iBaseUnitSize >> getComponentScaleX( area.compID(), cu.chromaFormat );
1458
0
  const int  iUnitHeight      = iBaseUnitSize >> getComponentScaleY( area.compID(), cu.chromaFormat );
1459
0
  const int  iTUWidthInUnits  = uiTuWidth  / iUnitWidth;
1460
0
  const int  iTUHeightInUnits = uiTuHeight / iUnitHeight;
1461
0
  const int  iAboveUnits      = iTUWidthInUnits;
1462
0
  const int  iLeftUnits       = iTUHeightInUnits;
1463
0
  const int  chromaUnitWidth  = iBaseUnitSize >> getComponentScaleX(COMPONENT_Cb, cu.chromaFormat);
1464
0
  const int  chromaUnitHeight = iBaseUnitSize >> getComponentScaleY(COMPONENT_Cb, cu.chromaFormat);
1465
0
  const int  topTemplateSampNum  = 2 * uiCWidth; // for MDLM, the number of template samples is 2W or 2H.
1466
0
  const int  leftTemplateSampNum = 2 * uiCHeight;
1467
0
  CHECKD( !( m_topRefLength >= topTemplateSampNum ), "Error!" );
1468
0
  CHECKD( !( m_leftRefLength >= leftTemplateSampNum ), "Error!" );
1469
0
  int totalAboveUnits = (curChromaMode == MDLM_T_IDX) ? (topTemplateSampNum + (chromaUnitWidth - 1)) / chromaUnitWidth : iAboveUnits;
1470
0
  int totalLeftUnits = (curChromaMode == MDLM_L_IDX) ? (leftTemplateSampNum + (chromaUnitHeight - 1)) / chromaUnitHeight : iLeftUnits;
1471
1472
0
  const int  availlableLeftUnit = ( cu.left || chromaArea.x > cu.blocks[CH_C].x ) ? totalLeftUnits : 0;
1473
0
  const bool bLeftAvaillable    = availlableLeftUnit >= iTUHeightInUnits;
1474
  
1475
0
  const int  availlableAboveUnit = ( cu.above || chromaArea.y > cu.blocks[CH_C].y ) ? totalAboveUnits : 0;
1476
0
  const bool bAboveAvaillable    = availlableAboveUnit >= iTUWidthInUnits;
1477
1478
0
  Pel*       pDst  = nullptr;
1479
0
  Pel const* piSrc = nullptr;
1480
1481
0
  bool isFirstRowOfCtu            = ( lumaArea.y & ( cu.sps->getCTUSize() - 1) ) == 0;
1482
0
  const ptrdiff_t strOffset       = ( CHROMA_444 == cu.chromaFormat ) ? 0 : iRecStride;
1483
1484
0
  int c0_3tap = 2, c1_3tap = 1, c2_3tap = 1,                                        offset_3tap = 2, shift_3tap = 2; //sum = 4
1485
0
  int c0_5tap = 1, c1_5tap = 4, c2_5tap = 1, c3_5tap = 1, c4_5tap = 1,              offset_5tap = 4, shift_5tap = 3; //sum = 8
1486
0
  int c0_6tap = 2, c1_6tap = 1, c2_6tap = 1, c3_6tap = 2, c4_6tap = 1, c5_6tap = 1, offset_6tap = 4, shift_6tap = 3; //sum = 8
1487
1488
0
  switch (cu.chromaFormat)
1489
0
  {
1490
0
    case CHROMA_422: //overwrite filter coefficient values for 422
1491
0
      c0_3tap = 2, c1_3tap = 1, c2_3tap = 1,                                        offset_3tap = 2, shift_3tap = 2; //sum = 4
1492
0
      c0_5tap = 0, c1_5tap = 2, c2_5tap = 1, c3_5tap = 1, c4_5tap = 0,              offset_5tap = 2, shift_5tap = 2; //sum = 4
1493
0
      c0_6tap = 2, c1_6tap = 1, c2_6tap = 1, c3_6tap = 0, c4_6tap = 0, c5_6tap = 0, offset_6tap = 2, shift_6tap = 2; //sum = 4
1494
0
      break;
1495
1496
0
    case CHROMA_444:  //overwrite filter coefficient values for 444
1497
0
      c0_3tap = 1, c1_3tap = 0, c2_3tap = 0,                                        offset_3tap = 0, shift_3tap = 0; //sum = 1
1498
0
      c0_5tap = 0, c1_5tap = 1, c2_5tap = 0, c3_5tap = 0, c4_5tap = 0,              offset_5tap = 0, shift_5tap = 0; //sum = 1
1499
0
      c0_6tap = 1, c1_6tap = 0, c2_6tap = 0, c3_6tap = 0, c4_6tap = 0, c5_6tap = 0, offset_6tap = 0, shift_6tap = 0; //sum = 1
1500
0
      break;
1501
1502
0
    default:
1503
0
      break;
1504
0
  }
1505
1506
0
  if( bAboveAvaillable )
1507
0
  {
1508
0
    pDst  = pDst0    - iDstStride;
1509
0
    int avaiAboveSizes = availlableAboveUnit * chromaUnitWidth;
1510
0
    for (int i = 0; i < avaiAboveSizes; i++)
1511
0
    {
1512
0
      if (isFirstRowOfCtu)
1513
0
      {
1514
0
        piSrc = pRecSrc0 - iRecStride;
1515
1516
0
        if ((i == 0 && !bLeftAvaillable) || (i == uiCWidth + avaiAboveSizes - 1 + logSubWidthC))
1517
0
        {
1518
0
          pDst[i] = (piSrc[mult * i] * c0_3tap + piSrc[mult * i] * c1_3tap + piSrc[mult * i + 1] * c2_3tap + offset_3tap) >> shift_3tap;
1519
0
        }
1520
0
        else
1521
0
        {
1522
0
          pDst[i] = (piSrc[mult * i] * c0_3tap + piSrc[mult * i - 1] * c1_3tap + piSrc[mult * i + 1] * c2_3tap + offset_3tap) >> shift_3tap;
1523
0
        }
1524
0
      }
1525
0
      else if( cu.sps->getCclmCollocatedChromaFlag() )
1526
0
      {
1527
0
        piSrc = pRecSrc0 - iRecStride2;
1528
1529
0
        if ((i == 0 && !bLeftAvaillable) || (i == uiCWidth + avaiAboveSizes - 1 + logSubWidthC))
1530
0
        {
1531
0
          pDst[i] = (piSrc[mult * i - strOffset] * c0_5tap
1532
0
                  +  piSrc[mult * i]             * c1_5tap + piSrc[mult * i] * c2_5tap + piSrc[mult * i + 1] * c3_5tap
1533
0
                  +  piSrc[mult * i + strOffset] * c4_5tap
1534
0
                  +  offset_5tap) >> shift_5tap;
1535
0
        }
1536
0
        else
1537
0
        {
1538
0
          pDst[i] = (piSrc[mult * i - strOffset] * c0_5tap
1539
0
                  +  piSrc[mult * i]             * c1_5tap + piSrc[mult * i - 1] * c2_5tap + piSrc[mult * i + 1] * c3_5tap
1540
0
                  +  piSrc[mult * i + strOffset] * c4_5tap
1541
0
                  +  offset_5tap) >> shift_5tap;
1542
0
        }
1543
0
      }
1544
0
      else
1545
0
      {
1546
0
        piSrc = pRecSrc0 - iRecStride2;
1547
1548
0
        if ((i == 0 && !bLeftAvaillable) || (i == uiCWidth + avaiAboveSizes - 1 + logSubWidthC))
1549
0
        {
1550
0
          pDst[i] = ((piSrc[mult * i]            * c0_6tap + piSrc[mult * i]             * c1_6tap + piSrc[mult * i + 1]             * c2_6tap)
1551
0
                  + (piSrc[mult * i + strOffset] * c3_6tap + piSrc[mult * i + strOffset] * c4_6tap + piSrc[mult * i + 1 + strOffset] * c5_6tap)
1552
0
                  + offset_6tap) >> shift_6tap;
1553
0
        }
1554
0
        else
1555
0
        {
1556
0
          pDst[i] = ((piSrc[mult * i]            * c0_6tap + piSrc[mult * i - 1]             * c1_6tap + piSrc[mult * i + 1]             * c2_6tap)
1557
0
                  + (piSrc[mult * i + strOffset] * c3_6tap + piSrc[mult * i - 1 + strOffset] * c4_6tap + piSrc[mult * i + 1 + strOffset] * c5_6tap)
1558
0
                  + offset_6tap) >> shift_6tap;
1559
0
        }
1560
0
      }
1561
0
    }
1562
0
  }
1563
1564
0
  if( bLeftAvaillable )
1565
0
  {
1566
0
    pDst  = pDst0    - 1;
1567
1568
0
    piSrc = pRecSrc0 - 2 - logSubWidthC;
1569
1570
0
    int availlableLeftSizes = availlableLeftUnit * chromaUnitHeight;
1571
0
    for (int j = 0; j < availlableLeftSizes; j++)
1572
0
    {
1573
0
      if( cu.sps->getCclmCollocatedChromaFlag() )
1574
0
      {
1575
0
        if ((j == 0 && !bAboveAvaillable) || (j == uiCHeight + availlableLeftSizes - 1 + logSubWidthC))
1576
0
        {
1577
0
          pDst[0] = ( piSrc[1            ] * c0_5tap
1578
0
                    + piSrc[1            ] * c1_5tap + piSrc[0] * c2_5tap + piSrc[2] * c3_5tap
1579
0
                    + piSrc[1 + strOffset] * c4_5tap
1580
0
                    + offset_5tap ) >> shift_5tap;
1581
0
        }
1582
0
        else
1583
0
        {
1584
0
          pDst[0] = ( piSrc[1 - strOffset] * c0_5tap
1585
0
                    + piSrc[1            ] * c1_5tap + piSrc[0] * c2_5tap + piSrc[2] * c3_5tap
1586
0
                    + piSrc[1 + strOffset] * c4_5tap
1587
0
                    + offset_5tap ) >> shift_5tap;
1588
0
        }
1589
0
      }
1590
0
      else
1591
0
      {
1592
0
        pDst[0] = ((piSrc[1]             * c0_6tap + piSrc[0]         * c1_6tap + piSrc[2]             * c2_6tap)
1593
0
                +  (piSrc[1 + strOffset] * c3_6tap + piSrc[strOffset] * c4_6tap + piSrc[2 + strOffset] * c5_6tap)
1594
0
                +   offset_6tap) >> shift_6tap;
1595
0
      }
1596
1597
0
      piSrc += iRecStride2;
1598
0
      pDst  += iDstStride;
1599
0
    }
1600
0
  }
1601
1602
0
  if( cu.sps->getCclmCollocatedChromaFlag() )
1603
0
  {
1604
    // TODO: unroll loop
1605
0
    for( int j = 0; j < uiCHeight; j++ )
1606
0
    {
1607
0
      for( int i = 0; i < uiCWidth; i++ )
1608
0
      {
1609
0
        if( i == 0 && !bLeftAvaillable )
1610
0
        {
1611
0
          if( j == 0 && !bAboveAvaillable )
1612
0
          {
1613
0
            pDst0[i] = (pRecSrc0[mult * i] * c0_5tap
1614
0
                     +  pRecSrc0[mult * i] * c1_5tap + pRecSrc0[mult * i] * c2_5tap + pRecSrc0[mult * i + 1] * c3_5tap
1615
0
                     +  pRecSrc0[mult * i + strOffset] * c4_5tap
1616
0
                     +  offset_5tap) >> shift_5tap;
1617
0
          }
1618
0
          else
1619
0
          {
1620
0
            pDst0[i] = (pRecSrc0[mult * i - strOffset] * c0_5tap
1621
0
                     +  pRecSrc0[mult * i] * c1_5tap + pRecSrc0[mult * i] * c2_5tap + pRecSrc0[mult * i + 1] * c3_5tap
1622
0
                     +  pRecSrc0[mult * i + strOffset] * c4_5tap
1623
0
                     +  offset_5tap) >> shift_5tap;
1624
0
          }
1625
0
        }
1626
0
        else if( j == 0 && !bAboveAvaillable )
1627
0
        {
1628
0
          pDst0[i] = (pRecSrc0[mult * i] * c0_5tap
1629
0
                   +  pRecSrc0[mult * i] * c1_5tap + pRecSrc0[mult * i - 1] * c2_5tap + pRecSrc0[mult * i + 1] * c3_5tap
1630
0
                   +  pRecSrc0[mult * i + strOffset] * c4_5tap
1631
0
                   +  offset_5tap) >> shift_5tap;
1632
0
        }
1633
0
        else
1634
0
        {
1635
0
          pDst0[i] = (pRecSrc0[mult * i - strOffset] * c0_5tap
1636
0
                   +  pRecSrc0[mult * i]             * c1_5tap + pRecSrc0[mult * i - 1] * c2_5tap + pRecSrc0[mult * i + 1] * c3_5tap
1637
0
                   +  pRecSrc0[mult * i + strOffset] * c4_5tap
1638
0
                   +  offset_5tap) >> shift_5tap;
1639
0
        }
1640
0
      }
1641
0
      pDst0    += iDstStride;
1642
0
      pRecSrc0 += iRecStride2;
1643
0
    }
1644
0
    return;
1645
0
  }
1646
1647
1648
1649
1650
0
#define GET_LUMA_REC_PIX_INC   \
1651
0
  pDst0 += iDstStride;         \
1652
0
  pRecSrc0 += iRecStride2
1653
1654
0
#define GET_LUMA_REC_PIX_OP2(ADDR)                                                    \
1655
0
  pDst0[ADDR] = (   pRecSrc0[( (ADDR) << logSubWidthC )    ]              * c0_6tap   \
1656
0
                  + pRecSrc0[( (ADDR) << logSubWidthC ) + 1]              * c1_6tap   \
1657
0
                  + pRecSrc0[( (ADDR) << logSubWidthC ) - 1]              * c2_6tap   \
1658
0
                  + pRecSrc0[( (ADDR) << logSubWidthC )     + iRecStride] * c3_6tap   \
1659
0
                  + pRecSrc0[( (ADDR) << logSubWidthC ) + 1 + iRecStride] * c4_6tap   \
1660
0
                  + pRecSrc0[( (ADDR) << logSubWidthC ) - 1 + iRecStride] * c5_6tap   \
1661
0
                  + offset_6tap ) >> shift_6tap
1662
1663
0
#define GET_LUMA_REC_PIX_OP1(ADDR)                          \
1664
0
  if( !(ADDR) )                                             \
1665
0
  {                                                         \
1666
0
    pDst0[0] = (   pRecSrc0[0    ]              * c0_6tap   \
1667
0
                 + pRecSrc0[0 + 1]              * c1_6tap   \
1668
0
                 + pRecSrc0[0]                  * c2_6tap   \
1669
0
                 + pRecSrc0[0     + iRecStride] * c3_6tap   \
1670
0
                 + pRecSrc0[0 + 1 + iRecStride] * c4_6tap   \
1671
0
                 + pRecSrc0[0     + iRecStride] * c5_6tap   \
1672
0
                 + offset_6tap ) >> shift_6tap;             \
1673
0
  }                                                         \
1674
0
  else                                                      \
1675
0
  {                                                         \
1676
0
    GET_LUMA_REC_PIX_OP2(ADDR);                             \
1677
0
  }
1678
1679
0
  int width  = uiCWidth;
1680
0
  int height = uiCHeight;
1681
1682
0
  if( bLeftAvaillable )
1683
0
  {
1684
0
    if( cu.chromaFormat == CHROMA_420 )
1685
0
    {
1686
0
      GetLumaRecPixel420( width, height, pRecSrc0, iRecStride, pDst0, iDstStride );
1687
      //      SIZE_AWARE_PER_EL_OP( GET_LUMA_REC_PIX_OP2, GET_LUMA_REC_PIX_INC );
1688
0
    }
1689
0
    else  //TODO add SIMD for 422,444
1690
0
    {
1691
0
      SIZE_AWARE_PER_EL_OP( GET_LUMA_REC_PIX_OP2, GET_LUMA_REC_PIX_INC );
1692
0
    }
1693
0
  }
1694
0
  else
1695
0
  {
1696
0
    SIZE_AWARE_PER_EL_OP( GET_LUMA_REC_PIX_OP1, GET_LUMA_REC_PIX_INC );
1697
0
  }
1698
0
}
1699
1700
#undef GET_LUMA_REC_PIX_INC
1701
#undef GET_LUMA_REC_PIX_OP1
1702
#undef GET_LUMA_REC_PIX_OP2
1703
#undef SIZE_AWARE_PER_EL_OP
1704
1705
void IntraPrediction::xGetLMParameters(const CodingUnit &cu, const ComponentID compID,
1706
                                              const CompArea &chromaArea,
1707
                                              int &a, int &b, int &iShift)
1708
0
{
1709
0
  CHECK(compID == COMPONENT_Y, "");
1710
1711
0
  const SizeType cWidth  = chromaArea.width;
1712
0
  const SizeType cHeight = chromaArea.height;
1713
1714
0
  const Position posLT = chromaArea;
1715
1716
0
  const CodingStructure &cs = *cu.cs;
1717
1718
0
  const SPS &        sps           = *cs.sps;
1719
0
  const uint32_t     tuWidth     = chromaArea.width;
1720
0
  const uint32_t     tuHeight    = chromaArea.height;
1721
0
  const ChromaFormat nChromaFormat = sps.getChromaFormatIdc();
1722
1723
0
  const int baseUnitSize   = 1 << MIN_CU_LOG2;
1724
0
  const int unitWidthLog2  = MIN_CU_LOG2 - getComponentScaleX(chromaArea.compID(), nChromaFormat);
1725
0
  const int unitHeightLog2 = MIN_CU_LOG2 - getComponentScaleX(chromaArea.compID(), nChromaFormat);
1726
0
  const int unitWidth      = baseUnitSize >> getComponentScaleX(chromaArea.compID(), nChromaFormat);
1727
0
  const int unitHeight     = baseUnitSize >> getComponentScaleX(chromaArea.compID(), nChromaFormat);
1728
1729
0
  const int tuWidthInUnits  = tuWidth / unitWidth;
1730
0
  const int tuHeightInUnits = tuHeight / unitHeight;
1731
0
  const int aboveUnits      = tuWidthInUnits;
1732
0
  const int leftUnits       = tuHeightInUnits;
1733
0
  int topTemplateSampNum = 2 * cWidth; // for MDLM, the template sample number is 2W or 2H;
1734
0
  int leftTemplateSampNum = 2 * cHeight;
1735
0
  CHECKD( !(m_topRefLength >= topTemplateSampNum),   "Error!" );
1736
0
  CHECKD( !(m_leftRefLength >= leftTemplateSampNum), "Error!" );
1737
0
  int totalAboveUnits = (topTemplateSampNum + (unitWidth - 1)) / unitWidth;
1738
0
  int totalLeftUnits = (leftTemplateSampNum + (unitHeight - 1)) / unitHeight;
1739
0
  int aboveRightUnits = totalAboveUnits - aboveUnits;
1740
0
  int leftBelowUnits = totalLeftUnits - leftUnits;
1741
1742
0
  int curChromaMode = cu.intraDir[1];
1743
0
  bool aboveAvailable = 0, leftAvailable = 0;
1744
1745
0
  const TransformUnit& tu = *getTU( cu, chromaArea.pos(), CH_C );
1746
1747
0
  Pel *srcColor0, *curChroma0;
1748
0
  int  srcStride, curStride;
1749
1750
0
  PelBuf temp;
1751
0
  if ((curChromaMode == MDLM_L_IDX) || (curChromaMode == MDLM_T_IDX))
1752
0
  {
1753
0
    srcStride = 2 * MAX_TU_SIZE_FOR_PROFILE + 1;
1754
0
    temp      = PelBuf(m_piYuvExt[1] + srcStride + 1, srcStride, Size(chromaArea));
1755
0
  }
1756
0
  else
1757
0
  {
1758
0
    srcStride = MAX_TU_SIZE_FOR_PROFILE + 1;
1759
0
    temp      = PelBuf(m_piYuvExt[1] + srcStride + 1, srcStride, Size(chromaArea));
1760
0
  }
1761
0
  srcColor0 = temp.bufAt(0, 0);
1762
0
  curChroma0 = getPredictorPtr(compID);
1763
1764
0
  curStride = m_topRefLength + 1;
1765
1766
0
  curChroma0 += curStride + 1;
1767
1768
0
  unsigned internalBitDepth = sps.getBitDepth();
1769
1770
0
  int minLuma[2] = {  MAX_INT, 0 };
1771
0
  int maxLuma[2] = { -MAX_INT, 0 };
1772
1773
0
  Pel *src = srcColor0 - srcStride;
1774
0
  Pel *cur = curChroma0 - curStride;
1775
0
  int actualTopTemplateSampNum = 0;
1776
0
  int actualLeftTemplateSampNum = 0;
1777
0
  if( curChromaMode == MDLM_T_IDX )
1778
0
  {
1779
0
    int avaiAboveUnits = 0;
1780
1781
0
    if( tu.cu->above || chromaArea.y > tu.cu->blocks[CH_C].y )
1782
0
    {
1783
0
      avaiAboveUnits  = aboveUnits;
1784
0
      aboveRightUnits = aboveRightUnits > ( cHeight / unitWidth ) ? cHeight / unitWidth : aboveRightUnits;
1785
0
      avaiAboveUnits += isAboveAvailable( tu, CHANNEL_TYPE_CHROMA, { posLT.x + ( PosType ) cWidth, posLT.y }, aboveRightUnits, unitWidthLog2 );
1786
0
    }
1787
1788
0
    aboveAvailable           = avaiAboveUnits >= tuWidthInUnits;
1789
0
    actualTopTemplateSampNum = unitWidth * avaiAboveUnits;
1790
0
  }
1791
0
  else if( curChromaMode == MDLM_L_IDX )
1792
0
  {
1793
0
    int avaiLeftUnits = 0;
1794
    
1795
0
    if( tu.cu->left || chromaArea.x > tu.cu->blocks[CH_C].x )
1796
0
    {
1797
0
      avaiLeftUnits  = leftUnits;
1798
0
      leftBelowUnits = leftBelowUnits > ( cWidth / unitHeight ) ? cWidth / unitHeight : leftBelowUnits;
1799
0
      avaiLeftUnits += isLeftAvailable( tu, CHANNEL_TYPE_CHROMA, { posLT.x, posLT.y + ( PosType ) cHeight }, leftBelowUnits, unitHeightLog2 );
1800
0
    }
1801
    
1802
0
    leftAvailable             = avaiLeftUnits >= tuHeightInUnits;
1803
0
    actualLeftTemplateSampNum = unitHeight * avaiLeftUnits;
1804
0
  }
1805
0
  else if( curChromaMode == LM_CHROMA_IDX )
1806
0
  {
1807
0
    aboveAvailable = tu.cu->above || chromaArea.y > tu.cu->blocks[CH_C].y;
1808
0
    leftAvailable  = tu.cu->left || chromaArea.x > tu.cu->blocks[CH_C].x;
1809
0
    actualTopTemplateSampNum =  cWidth;
1810
0
    actualLeftTemplateSampNum = cHeight;
1811
0
  }
1812
0
  int startPos[2]; //0:Above, 1: Left
1813
0
  int pickStep[2];
1814
1815
0
  int aboveIs4 = leftAvailable  ? 0 : 1;
1816
0
  int leftIs4 =  aboveAvailable ? 0 : 1;
1817
1818
0
  startPos[0] = actualTopTemplateSampNum >> (2 + aboveIs4);
1819
0
  pickStep[0] = std::max(1, actualTopTemplateSampNum >> (1 + aboveIs4));
1820
1821
0
  startPos[1] = actualLeftTemplateSampNum >> (2 + leftIs4);
1822
0
  pickStep[1] = std::max(1, actualLeftTemplateSampNum >> (1 + leftIs4));
1823
1824
0
  Pel selectLumaPix[4] = { 0, 0, 0, 0 };
1825
0
  Pel selectChromaPix[4] = { 0, 0, 0, 0 };
1826
1827
0
  int cntT, cntL;
1828
0
  cntT = cntL = 0;
1829
0
  int cnt = 0;
1830
0
  if (aboveAvailable)
1831
0
  {
1832
0
    cntT = std::min(actualTopTemplateSampNum, (1 + aboveIs4) << 1);
1833
0
    src = srcColor0 - srcStride;
1834
0
    cur = curChroma0 - curStride;
1835
0
    for (int pos = startPos[0]; cnt < cntT; pos += pickStep[0], cnt++)
1836
0
    {
1837
0
      selectLumaPix[cnt] = src[pos];
1838
0
      selectChromaPix[cnt] = cur[pos];
1839
0
    }
1840
0
  }
1841
1842
0
  if (leftAvailable)
1843
0
  {
1844
0
    cntL = std::min(actualLeftTemplateSampNum, ( 1 + leftIs4 ) << 1 );
1845
0
    src = srcColor0 - 1;
1846
0
    cur = curChroma0 - 1;
1847
0
    for (int pos = startPos[1], cnt = 0; cnt < cntL; pos += pickStep[1], cnt++)
1848
0
    {
1849
0
      selectLumaPix[cnt + cntT] = src[pos * srcStride];
1850
0
      selectChromaPix[cnt+ cntT] = cur[pos * curStride];
1851
0
    }
1852
0
  }
1853
0
  cnt = cntL + cntT;
1854
1855
0
  if (cnt == 2)
1856
0
  {
1857
0
    selectLumaPix[3] = selectLumaPix[0]; selectChromaPix[3] = selectChromaPix[0];
1858
0
    selectLumaPix[2] = selectLumaPix[1]; selectChromaPix[2] = selectChromaPix[1];
1859
0
    selectLumaPix[0] = selectLumaPix[1]; selectChromaPix[0] = selectChromaPix[1];
1860
0
    selectLumaPix[1] = selectLumaPix[3]; selectChromaPix[1] = selectChromaPix[3];
1861
0
  }
1862
1863
0
  int minGrpIdx[2] = { 0, 2 };
1864
0
  int maxGrpIdx[2] = { 1, 3 };
1865
0
  int *tmpMinGrp = minGrpIdx;
1866
0
  int *tmpMaxGrp = maxGrpIdx;
1867
0
  if (selectLumaPix[tmpMinGrp[0]] > selectLumaPix[tmpMinGrp[1]]) std::swap(tmpMinGrp[0], tmpMinGrp[1]);
1868
0
  if (selectLumaPix[tmpMaxGrp[0]] > selectLumaPix[tmpMaxGrp[1]]) std::swap(tmpMaxGrp[0], tmpMaxGrp[1]);
1869
0
  if (selectLumaPix[tmpMinGrp[0]] > selectLumaPix[tmpMaxGrp[1]]) std::swap(tmpMinGrp, tmpMaxGrp);       // TODO: really? not std::swap(tmpMinGrp[0], tmpMaxGrp[1]); ?
1870
0
  if (selectLumaPix[tmpMinGrp[1]] > selectLumaPix[tmpMaxGrp[0]]) std::swap(tmpMinGrp[1], tmpMaxGrp[0]);
1871
1872
0
  minLuma[0] = (selectLumaPix  [tmpMinGrp[0]] + selectLumaPix  [tmpMinGrp[1]] + 1) >> 1;
1873
0
  minLuma[1] = (selectChromaPix[tmpMinGrp[0]] + selectChromaPix[tmpMinGrp[1]] + 1) >> 1;
1874
0
  maxLuma[0] = (selectLumaPix  [tmpMaxGrp[0]] + selectLumaPix  [tmpMaxGrp[1]] + 1) >> 1;
1875
0
  maxLuma[1] = (selectChromaPix[tmpMaxGrp[0]] + selectChromaPix[tmpMaxGrp[1]] + 1) >> 1;
1876
1877
0
  if (leftAvailable || aboveAvailable)
1878
0
  {
1879
0
    int diff = maxLuma[0] - minLuma[0];
1880
0
    if (diff > 0)
1881
0
    {
1882
0
      int diffC = maxLuma[1] - minLuma[1];
1883
0
      int x = getLog2( diff );
1884
0
      static const uint8_t DivSigTable[1 << 4] = {
1885
        // 4bit significands - 8 ( MSB is omitted )
1886
0
        0,  7,  6,  5,  5,  4,  4,  3,  3,  2,  2,  1,  1,  1,  1,  0
1887
0
      };
1888
0
      int normDiff = (diff << 4 >> x) & 15;
1889
0
      int v = DivSigTable[normDiff] | 8;
1890
0
      x += normDiff != 0;
1891
1892
0
      int y = diffC == 0 ? 0 : getLog2( abs( diffC ) ) + 1;
1893
0
      int add = 1 << y >> 1;
1894
0
      a = (diffC * v + add) >> y;
1895
0
      iShift = 3 + x - y;
1896
0
      if ( iShift < 1 ) {
1897
0
        iShift = 1;
1898
0
        a = ( (a == 0)? 0: (a < 0)? -15 : 15 );   // a=Sign(a)*15
1899
0
      }
1900
0
      b = minLuma[1] - ((a * minLuma[0]) >> iShift);
1901
0
    }
1902
0
    else
1903
0
    {
1904
0
      a = 0;
1905
0
      b = minLuma[1];
1906
0
      iShift = 0;
1907
0
    }
1908
0
  }
1909
0
  else
1910
0
  {
1911
0
    a = 0;
1912
1913
0
    b = 1 << (internalBitDepth - 1);
1914
1915
0
    iShift = 0;
1916
0
  }
1917
0
}
1918
1919
void IntraPrediction::initIntraMip( const CodingUnit &cu, const CompArea &area )
1920
0
{
1921
0
  CHECK( area.width > MIP_MAX_WIDTH || area.height > MIP_MAX_HEIGHT, "Error: block size not supported for MIP" );
1922
1923
  // prepare input (boundary) data for prediction
1924
//  CHECK( m_ipaParam.refFilterFlag, "ERROR: unfiltered refs expected for MIP" );
1925
0
  Pel *ptrSrc = getPredictorPtr( area.compID() );
1926
0
  const int srcStride  = m_topRefLength  + 1; //TODO: check this if correct
1927
0
  const int srcHStride = m_leftRefLength + 1;
1928
1929
0
  m_matrixIntraPred.prepareInputForPred( CPelBuf( ptrSrc, srcStride, srcHStride ), area, cu.sps->getBitDepth(), area.compID() );
1930
0
}
1931
1932
void IntraPrediction::predIntraMip( const ComponentID compId, PelBuf &piPred, const CodingUnit &cu )
1933
0
{
1934
0
  CHECK( piPred.width > MIP_MAX_WIDTH || piPred.height > MIP_MAX_HEIGHT, "Error: block size not supported for MIP" );
1935
0
  CHECK( piPred.width != (1 << getLog2(piPred.width)) || piPred.height != (1 << getLog2(piPred.height)), "Error: expecting blocks of size 2^M x 2^N" );
1936
1937
  // generate mode-specific prediction
1938
0
  uint32_t modeIdx       = MAX_NUM_MIP_MODE;
1939
0
  bool     transposeFlag = false;
1940
0
  if( compId == COMPONENT_Y )
1941
0
  {
1942
0
    modeIdx       = cu.intraDir[CHANNEL_TYPE_LUMA];
1943
0
    transposeFlag = cu.mipTransposedFlag();
1944
0
  }
1945
0
  else
1946
0
  {
1947
0
    const CodingUnit &coLocatedLumaPU = PU::getCoLocatedLumaPU(cu);
1948
1949
0
    CHECK(cu.intraDir[CHANNEL_TYPE_CHROMA] != DM_CHROMA_IDX, "Error: MIP is only supported for chroma with DM_CHROMA.");
1950
0
    CHECK(!coLocatedLumaPU.mipFlag(), "Error: Co-located luma CU should use MIP.");
1951
1952
0
    modeIdx       = coLocatedLumaPU.intraDir[CHANNEL_TYPE_LUMA];
1953
0
    transposeFlag = coLocatedLumaPU.mipTransposedFlag();
1954
0
  }
1955
1956
0
  CHECK(modeIdx >= getNumModesMip(piPred), "Error: Wrong MIP mode index");
1957
1958
0
  const int bitDepth = cu.sps->getBitDepth();
1959
0
  m_matrixIntraPred.predBlock( piPred, modeIdx, piPred, transposeFlag, bitDepth, compId, m_piYuvExt[0] );
1960
0
}
1961
1962
}