Ticket #1437: source_Lib_CommonLib_IntraPrediction.cpp

File source_Lib_CommonLib_IntraPrediction.cpp, 65.1 KB (added by wzq_arcvideo, 3 years ago)

bugs in IntraPrediction::getModifiedWideAngle

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