Ticket #115: IntraSearch.cpp

File IntraSearch.cpp, 68.3 KB (added by keydel, 5 years ago)

bugfix example

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-2018, 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     EncSearch.cpp
35 *  \brief    encoder intra search class
36 */
37
38#include "IntraSearch.h"
39
40#include "EncModeCtrl.h"
41
42#include "CommonLib/CommonDef.h"
43#include "CommonLib/Rom.h"
44#include "CommonLib/Picture.h"
45#include "CommonLib/UnitTools.h"
46
47#include "CommonLib/dtrace_next.h"
48#include "CommonLib/dtrace_buffer.h"
49
50#include <math.h>
51#include <limits>
52
53 //! \ingroup EncoderLib
54 //! \{
55
56IntraSearch::IntraSearch()
57  : m_pSplitCS      (nullptr)
58  , m_pFullCS       (nullptr)
59  , m_pBestCS       (nullptr)
60  , m_pcEncCfg      (nullptr)
61  , m_pcTrQuant     (nullptr)
62  , m_pcRdCost      (nullptr)
63  , m_CABACEstimator(nullptr)
64  , m_CtxCache      (nullptr)
65  , m_isInitialized (false)
66{
67  for( uint32_t ch = 0; ch < MAX_NUM_TBLOCKS; ch++ )
68  {
69    m_pSharedPredTransformSkip[ch] = nullptr;
70  }
71}
72
73
74void IntraSearch::destroy()
75{
76  CHECK( !m_isInitialized, "Not initialized" );
77
78  if( m_pcEncCfg )
79  {
80    bool BTnoRQT = m_pcEncCfg->getQTBT();
81
82
83    const uint32_t uiNumLayersToAllocateSplit = BTnoRQT ? 1 : m_pcEncCfg->getQuadtreeTULog2MaxSize() - m_pcEncCfg->getQuadtreeTULog2MinSize() + 1;
84    const uint32_t uiNumLayersToAllocateFull  = BTnoRQT ? 1 : m_pcEncCfg->getQuadtreeTULog2MaxSize() - m_pcEncCfg->getQuadtreeTULog2MinSize() + 1;
85    const int uiNumSaveLayersToAllocate = 2;
86
87    for( uint32_t layer = 0; layer < uiNumSaveLayersToAllocate; layer++ )
88    {
89      m_pSaveCS[layer]->destroy();
90      delete m_pSaveCS[layer];
91    }
92
93    uint32_t numWidths  = gp_sizeIdxInfo->numWidths();
94    uint32_t numHeights = gp_sizeIdxInfo->numHeights();
95
96    for( uint32_t width = 0; width < numWidths; width++ )
97    {
98      for( uint32_t height = 0; height < numHeights; height++ )
99      {
100        if( ( BTnoRQT || width == height ) && gp_sizeIdxInfo->isCuSize( gp_sizeIdxInfo->sizeFrom( width ) ) && gp_sizeIdxInfo->isCuSize( gp_sizeIdxInfo->sizeFrom( height ) ) )
101        {
102          for( uint32_t layer = 0; layer < uiNumLayersToAllocateSplit; layer++ )
103          {
104            m_pSplitCS[width][height][layer]->destroy();
105
106            delete m_pSplitCS[width][height][layer];
107          }
108
109          for( uint32_t layer = 0; layer < uiNumLayersToAllocateFull; layer++ )
110          {
111            m_pFullCS[width][height][layer]->destroy();
112
113            delete m_pFullCS[width][height][layer];
114          }
115
116          delete[] m_pSplitCS[width][height];
117          delete[] m_pFullCS [width][height];
118
119          m_pBestCS[width][height]->destroy();
120          m_pTempCS[width][height]->destroy();
121
122          delete m_pTempCS[width][height];
123          delete m_pBestCS[width][height];
124        }
125      }
126
127      delete[] m_pSplitCS[width];
128      delete[] m_pFullCS [width];
129
130      delete[] m_pTempCS[width];
131      delete[] m_pBestCS[width];
132    }
133
134    delete[] m_pSplitCS;
135    delete[] m_pFullCS;
136
137    delete[] m_pBestCS;
138    delete[] m_pTempCS;
139
140    delete[] m_pSaveCS;
141  }
142
143  m_pSplitCS = m_pFullCS = nullptr;
144
145  m_pBestCS = m_pTempCS = nullptr;
146
147  m_pSaveCS = nullptr;
148
149  for( uint32_t ch = 0; ch < MAX_NUM_TBLOCKS; ch++ )
150  {
151    delete[] m_pSharedPredTransformSkip[ch];
152    m_pSharedPredTransformSkip[ch] = nullptr;
153  }
154
155  m_isInitialized = false;
156}
157
158IntraSearch::~IntraSearch()
159{
160  if( m_isInitialized )
161  {
162    destroy();
163  }
164}
165
166void IntraSearch::init( EncCfg*        pcEncCfg,
167                        TrQuant*       pcTrQuant,
168                        RdCost*        pcRdCost,
169                        CABACWriter*   CABACEstimator,
170                        CtxCache*      ctxCache,
171                        const uint32_t     maxCUWidth,
172                        const uint32_t     maxCUHeight,
173                        const uint32_t     maxTotalCUDepth
174)
175{
176  CHECK(m_isInitialized, "Already initialized");
177  m_pcEncCfg                     = pcEncCfg;
178  m_pcTrQuant                    = pcTrQuant;
179  m_pcRdCost                     = pcRdCost;
180  m_CABACEstimator               = CABACEstimator;
181  m_CtxCache                     = ctxCache;
182
183  const ChromaFormat cform = pcEncCfg->getChromaFormatIdc();
184
185  IntraPrediction::init( cform, pcEncCfg->getBitDepth( CHANNEL_TYPE_LUMA ) );
186
187  for( uint32_t ch = 0; ch < MAX_NUM_TBLOCKS; ch++ )
188  {
189    m_pSharedPredTransformSkip[ch] = new Pel[MAX_CU_SIZE * MAX_CU_SIZE];
190  }
191
192  uint32_t numWidths  = gp_sizeIdxInfo->numWidths();
193  uint32_t numHeights = gp_sizeIdxInfo->numHeights();
194
195  bool BTnoRQT = m_pcEncCfg->getQTBT();
196
197  const uint32_t uiNumLayersToAllocateSplit = BTnoRQT ? 1 : pcEncCfg->getQuadtreeTULog2MaxSize() - pcEncCfg->getQuadtreeTULog2MinSize() + 1;
198  const uint32_t uiNumLayersToAllocateFull  = BTnoRQT ? 1 : pcEncCfg->getQuadtreeTULog2MaxSize() - pcEncCfg->getQuadtreeTULog2MinSize() + 1;
199
200  m_pBestCS = new CodingStructure**[numWidths];
201  m_pTempCS = new CodingStructure**[numWidths];
202
203  m_pFullCS  = new CodingStructure***[numWidths];
204  m_pSplitCS = new CodingStructure***[numWidths];
205
206  for( uint32_t width = 0; width < numWidths; width++ )
207  {
208    m_pBestCS[width] = new CodingStructure*[numHeights];
209    m_pTempCS[width] = new CodingStructure*[numHeights];
210
211    m_pFullCS [width] = new CodingStructure**[numHeights];
212    m_pSplitCS[width] = new CodingStructure**[numHeights];
213
214    for( uint32_t height = 0; height < numHeights; height++ )
215    {
216      if( ( BTnoRQT || width == height ) && gp_sizeIdxInfo->isCuSize( gp_sizeIdxInfo->sizeFrom( width ) ) && gp_sizeIdxInfo->isCuSize( gp_sizeIdxInfo->sizeFrom( height ) ) )
217      {
218        m_pBestCS[width][height] = new CodingStructure( m_unitCache.cuCache, m_unitCache.puCache, m_unitCache.tuCache );
219        m_pTempCS[width][height] = new CodingStructure( m_unitCache.cuCache, m_unitCache.puCache, m_unitCache.tuCache );
220
221        m_pBestCS[width][height]->create( m_pcEncCfg->getChromaFormatIdc(), Area( 0, 0, gp_sizeIdxInfo->sizeFrom( width ), gp_sizeIdxInfo->sizeFrom( height ) ), false );
222        m_pTempCS[width][height]->create( m_pcEncCfg->getChromaFormatIdc(), Area( 0, 0, gp_sizeIdxInfo->sizeFrom( width ), gp_sizeIdxInfo->sizeFrom( height ) ), false );
223        m_pFullCS [width][height] = new CodingStructure*[uiNumLayersToAllocateFull];
224        m_pSplitCS[width][height] = new CodingStructure*[uiNumLayersToAllocateSplit];
225
226        for( uint32_t layer = 0; layer < uiNumLayersToAllocateFull; layer++ )
227        {
228          m_pFullCS [width][height][layer] = new CodingStructure( m_unitCache.cuCache, m_unitCache.puCache, m_unitCache.tuCache );
229
230          m_pFullCS [width][height][layer]->create( m_pcEncCfg->getChromaFormatIdc(), Area( 0, 0, gp_sizeIdxInfo->sizeFrom( width ), gp_sizeIdxInfo->sizeFrom( height ) ), false );
231        }
232
233        for( uint32_t layer = 0; layer < uiNumLayersToAllocateSplit; layer++ )
234        {
235          m_pSplitCS[width][height][layer] = new CodingStructure( m_unitCache.cuCache, m_unitCache.puCache, m_unitCache.tuCache );
236
237          m_pSplitCS[width][height][layer]->create( m_pcEncCfg->getChromaFormatIdc(), Area( 0, 0, gp_sizeIdxInfo->sizeFrom( width ), gp_sizeIdxInfo->sizeFrom( height ) ), false );
238        }
239      }
240      else
241      {
242        m_pBestCS[width][height] = nullptr;
243        m_pTempCS[width][height] = nullptr;
244
245        m_pFullCS [width][height] = nullptr;
246        m_pSplitCS[width][height] = nullptr;
247      }
248    }
249  }
250
251  const int uiNumSaveLayersToAllocate = 2;
252
253  m_pSaveCS = new CodingStructure*[uiNumSaveLayersToAllocate];
254
255  for( uint32_t depth = 0; depth < uiNumSaveLayersToAllocate; depth++ )
256  {
257    m_pSaveCS[depth] = new CodingStructure( m_unitCache.cuCache, m_unitCache.puCache, m_unitCache.tuCache );
258    m_pSaveCS[depth]->create( UnitArea( cform, Area( 0, 0, maxCUWidth, maxCUHeight ) ), false );
259  }
260
261  m_isInitialized = true;
262}
263
264
265//////////////////////////////////////////////////////////////////////////
266// INTRA PREDICTION
267//////////////////////////////////////////////////////////////////////////
268
269void IntraSearch::estIntraPredLumaQT( CodingUnit &cu, Partitioner &partitioner )
270{
271  CodingStructure       &cs            = *cu.cs;
272  const SPS             &sps           = *cs.sps;
273  const uint32_t             uiWidthBit    = cs.pcv->rectCUs ? g_aucLog2[partitioner.currArea().lwidth() ] : CU::getIntraSizeIdx(cu);
274  const uint32_t             uiHeightBit   =                   g_aucLog2[partitioner.currArea().lheight()];
275
276  // Lambda calculation at equivalent Qp of 4 is recommended because at that Qp, the quantization divisor is 1.
277  const double sqrtLambdaForFirstPass = m_pcRdCost->getMotionLambda(cu.transQuantBypass) / double(1 << SCALE_BITS);
278
279
280  //===== loop over partitions =====
281
282  const TempCtx ctxStart          ( m_CtxCache, m_CABACEstimator->getCtx() );
283  const TempCtx ctxStartIntraMode ( m_CtxCache, SubCtx( Ctx::IPredMode[CHANNEL_TYPE_LUMA],        m_CABACEstimator->getCtx() ) );
284#if INTRA_SEARCH_CONTEXT_BUGFIX
285#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
286  const TempCtx ctxStartMHIntraMode ( m_CtxCache, SubCtx( Ctx::MHIntraPredMode,        m_CABACEstimator->getCtx() ) );
287#endif
288#if JVET_L0283_MULTI_REF_LINE
289  const TempCtx ctxStartMrlIdx      ( m_CtxCache, SubCtx( Ctx::MultiRefLineIdx,        m_CABACEstimator->getCtx() ) );
290#endif
291#endif
292
293  CHECK( !cu.firstPU, "CU has no PUs" );
294  const bool keepResi   = cs.pps->getPpsRangeExtension().getCrossComponentPredictionEnabledFlag() || KEEP_PRED_AND_RESI_SIGNALS;
295
296
297  uint32_t extraModes = 0; // add two extra modes, which would be used after uiMode <= DC_IDX is removed for cu.nsstIdx == 3
298
299
300  const int width   = partitioner.currArea().lwidth();
301  const int height  = partitioner.currArea().lheight();
302
303  // Marking EMT usage for faster EMT
304  // 0: EMT is either not applicable for current CU (cuWidth > EMT_INTRA_MAX_CU or cuHeight > EMT_INTRA_MAX_CU), not active in the config file or the fast decision algorithm is not used in this case
305  // 1: EMT fast algorithm can be applied for the current CU, and the DCT2 is being checked
306  // 2: EMT is being checked for current CU. Stored results of DCT2 can be utilized for speedup
307  uint8_t emtUsageFlag = 0;
308  const int maxSizeEMT = cs.pcv->noRQT ? EMT_INTRA_MAX_CU_WITH_QTBT : EMT_INTRA_MAX_CU;
309  if( width <= maxSizeEMT && height <= maxSizeEMT && sps.getSpsNext().getUseIntraEMT() )
310  {
311    emtUsageFlag = cu.emtFlag == 1 ? 2 : 1;
312  }
313
314  bool isAllIntra = m_pcEncCfg->getIntraPeriod() == 1;
315
316  if( cs.pcv->rectCUs )
317  {
318    if( width * height < 64 && !isAllIntra )
319    {
320      emtUsageFlag = 0; //this forces the recalculation of the candidates list. Why is this necessary? (to be checked)
321    }
322  }
323
324  static_vector<uint32_t,   FAST_UDI_MAX_RDMODE_NUM> uiHadModeList;
325  static_vector<double, FAST_UDI_MAX_RDMODE_NUM> CandCostList;
326  static_vector<double, FAST_UDI_MAX_RDMODE_NUM> CandHadList;
327
328#if JVET_L0283_MULTI_REF_LINE
329  static_vector<int, FAST_UDI_MAX_RDMODE_NUM> extendRefList;
330  static_vector<int, FAST_UDI_MAX_RDMODE_NUM>* nullList = NULL;
331#endif
332
333  auto &pu = *cu.firstPU;
334  int puIndex = 0;
335  {
336    CandHadList.clear();
337    CandCostList.clear();
338    uiHadModeList.clear();
339#if JVET_L0283_MULTI_REF_LINE
340    extendRefList.clear();
341#endif
342
343    CHECK(pu.cu != &cu, "PU is not contained in the CU");
344
345    //===== determine set of modes to be tested (using prediction signal only) =====
346    int numModesAvailable = NUM_LUMA_MODE; // total number of Intra modes
347    static_vector< uint32_t, FAST_UDI_MAX_RDMODE_NUM > uiRdModeList;
348
349    int numModesForFullRD = 3;
350    if( cs.pcv->rectCUs )
351    {
352      numModesForFullRD = g_aucIntraModeNumFast_UseMPM_2D[uiWidthBit - MIN_CU_LOG2][uiHeightBit - MIN_CU_LOG2];
353    }
354    else
355    {
356      numModesForFullRD = m_pcEncCfg->getFastUDIUseMPMEnabled() ? g_aucIntraModeNumFast_UseMPM[uiWidthBit] : g_aucIntraModeNumFast_NotUseMPM[uiWidthBit];
357      numModesForFullRD -= 1;
358    }
359
360#if INTRA_FULL_SEARCH
361    numModesForFullRD = numModesAvailable;
362#endif
363
364
365    if( emtUsageFlag != 2 )
366    {
367      // this should always be true
368      CHECK( !pu.Y().valid(), "PU is not valid" );
369#if JVET_L0283_MULTI_REF_LINE
370      bool isFirstLineOfCtu = (((pu.block(COMPONENT_Y).y)&((pu.cs->sps)->getMaxCUWidth() - 1)) == 0);
371      int numOfPassesExtendRef = (isFirstLineOfCtu ? 1 : MRL_NUM_REF_LINES);
372      pu.multiRefIdx = 0;
373#endif
374
375      //===== init pattern for luma prediction =====
376      initIntraPatternChType( cu, pu.Y(), IntraPrediction::useFilteredIntraRefSamples( COMPONENT_Y, pu, false, pu ) );
377      if( numModesForFullRD != numModesAvailable )
378      {
379        CHECK( numModesForFullRD >= numModesAvailable, "Too many modes for full RD search" );
380
381        const CompArea &area = pu.Y();
382
383        PelBuf piOrg         = cs.getOrgBuf(area);
384        PelBuf piPred        = cs.getPredBuf(area);
385
386        DistParam distParam;
387
388        const bool bUseHadamard = cu.transQuantBypass == 0;
389
390        m_pcRdCost->setDistParam(distParam, piOrg, piPred, sps.getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, bUseHadamard);
391
392        distParam.applyWeight = false;
393
394        bool bSatdChecked[NUM_INTRA_MODE];
395        memset( bSatdChecked, 0, sizeof( bSatdChecked ) );
396
397        {
398          for( int modeIdx = 0; modeIdx < numModesAvailable; modeIdx++ )
399          {
400            uint32_t       uiMode = modeIdx;
401            Distortion uiSad  = 0;
402
403            // Skip checking extended Angular modes in the first round of SATD
404            if( uiMode > DC_IDX && ( uiMode & 1 ) )
405            {
406              continue;
407            }
408
409            bSatdChecked[uiMode] = true;
410
411            pu.intraDir[0] = modeIdx;
412
413            if( useDPCMForFirstPassIntraEstimation( pu, uiMode ) )
414            {
415              encPredIntraDPCM( COMPONENT_Y, piOrg, piPred, uiMode );
416            }
417            else
418            {
419              predIntraAng( COMPONENT_Y, piPred, pu, IntraPrediction::useFilteredIntraRefSamples( COMPONENT_Y, pu, true, pu ) );
420            }
421            // use Hadamard transform here
422            uiSad += distParam.distFunc(distParam);
423
424            // NB xFracModeBitsIntra will not affect the mode for chroma that may have already been pre-estimated.
425#if INTRA_SEARCH_CONTEXT_BUGFIX
426            m_CABACEstimator->getCtx() = SubCtx( Ctx::IPredMode[CHANNEL_TYPE_LUMA], ctxStartIntraMode );
427#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
428            m_CABACEstimator->getCtx() = SubCtx( Ctx::MHIntraPredMode, ctxStartMHIntraMode );
429#endif
430#if JVET_L0283_MULTI_REF_LINE
431            m_CABACEstimator->getCtx() = SubCtx( Ctx::MultiRefLineIdx, ctxStartMrlIdx );
432#endif
433#else
434            m_CABACEstimator->getCtx() = SubCtx( Ctx::IPredMode[CHANNEL_TYPE_LUMA], ctxStartIntraMode );
435#endif
436
437            uint64_t fracModeBits = xFracModeBitsIntra(pu, uiMode, CHANNEL_TYPE_LUMA);
438
439            double cost = ( double ) uiSad + ( double ) fracModeBits * sqrtLambdaForFirstPass;
440
441            DTRACE( g_trace_ctx, D_INTRA_COST, "IntraHAD: %u, %llu, %f (%d)\n", uiSad, fracModeBits, cost, uiMode );
442
443            updateCandList( uiMode, cost,  uiRdModeList, CandCostList
444#if JVET_L0283_MULTI_REF_LINE
445              , extendRefList, 0
446#endif             
447              , numModesForFullRD + extraModes );
448            updateCandList(uiMode, (double) uiSad, uiHadModeList, CandHadList
449#if JVET_L0283_MULTI_REF_LINE
450              , *nullList, -1
451#endif             
452              , 3 + extraModes);
453          }
454        } // NSSTFlag
455
456        // forget the extra modes
457        uiRdModeList.resize( numModesForFullRD );
458#if JVET_L0283_MULTI_REF_LINE
459        CandCostList.resize(numModesForFullRD);
460        extendRefList.resize(numModesForFullRD);
461#endif
462        static_vector<unsigned, FAST_UDI_MAX_RDMODE_NUM> parentCandList(FAST_UDI_MAX_RDMODE_NUM);
463        std::copy_n(uiRdModeList.begin(), numModesForFullRD, parentCandList.begin());
464
465        // Second round of SATD for extended Angular modes
466        for (int modeIdx = 0; modeIdx < numModesForFullRD; modeIdx++)
467        {
468          unsigned parentMode = parentCandList[modeIdx];
469          if (parentMode > (DC_IDX + 1) && parentMode < (NUM_LUMA_MODE - 1))
470          {
471            for (int subModeIdx = -1; subModeIdx <= 1; subModeIdx += 2)
472            {
473              unsigned mode = parentMode + subModeIdx;
474
475
476              if (!bSatdChecked[mode])
477              {
478                pu.intraDir[0] = mode;
479
480                if (useDPCMForFirstPassIntraEstimation(pu, mode))
481                {
482                  encPredIntraDPCM(COMPONENT_Y, piOrg, piPred, mode);
483                }
484                else
485                {
486                  predIntraAng(COMPONENT_Y, piPred, pu,
487                               IntraPrediction::useFilteredIntraRefSamples(COMPONENT_Y, pu, true, pu));
488                }
489                // use Hadamard transform here
490                Distortion sad = distParam.distFunc(distParam);
491
492                // NB xFracModeBitsIntra will not affect the mode for chroma that may have already been pre-estimated.
493#if INTRA_SEARCH_CONTEXT_BUGFIX
494                m_CABACEstimator->getCtx() = SubCtx( Ctx::IPredMode[CHANNEL_TYPE_LUMA], ctxStartIntraMode );
495#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
496                m_CABACEstimator->getCtx() = SubCtx( Ctx::MHIntraPredMode, ctxStartMHIntraMode );
497#endif
498#if JVET_L0283_MULTI_REF_LINE
499                m_CABACEstimator->getCtx() = SubCtx( Ctx::MultiRefLineIdx, ctxStartMrlIdx );
500#endif
501#else
502                m_CABACEstimator->getCtx() = SubCtx(Ctx::IPredMode[CHANNEL_TYPE_LUMA], ctxStartIntraMode);
503#endif
504
505                uint64_t fracModeBits = xFracModeBitsIntra(pu, mode, CHANNEL_TYPE_LUMA);
506
507                double cost = (double) sad + (double) fracModeBits * sqrtLambdaForFirstPass;
508
509                updateCandList(mode, cost, uiRdModeList, CandCostList
510#if JVET_L0283_MULTI_REF_LINE
511                  , extendRefList, 0
512#endif
513                  , numModesForFullRD);
514                updateCandList(mode, (double)sad, uiHadModeList, CandHadList
515#if JVET_L0283_MULTI_REF_LINE
516                  , *nullList, -1
517#endif                 
518                  , 3);
519
520                bSatdChecked[mode] = true;
521              }
522            }
523          }
524        }
525#if JVET_L0283_MULTI_REF_LINE
526        pu.multiRefIdx = 1;
527        const int  numMPMs = NUM_MOST_PROBABLE_MODES;
528        unsigned  multiRefMPM [numMPMs];
529        PU::getIntraMPMs(pu, multiRefMPM);
530        for (int mRefNum = 1; mRefNum < numOfPassesExtendRef; mRefNum++)
531        {
532          int multiRefIdx = MULTI_REF_LINE_IDX[mRefNum];
533
534          pu.multiRefIdx = multiRefIdx;
535          {
536            initIntraPatternChType(cu, pu.Y(), IntraPrediction::useFilteredIntraRefSamples(COMPONENT_Y, pu, false, pu));
537          }
538          for (int x = 0; x < numMPMs; x++)
539          {
540            uint32_t mode = multiRefMPM[x];
541            {
542              pu.intraDir[0] = mode;
543
544              if (useDPCMForFirstPassIntraEstimation(pu, mode))
545              {
546                encPredIntraDPCM(COMPONENT_Y, piOrg, piPred, mode);
547              }
548              else
549              {
550                predIntraAng(COMPONENT_Y, piPred, pu, IntraPrediction::useFilteredIntraRefSamples(COMPONENT_Y, pu, true, pu));
551              }
552
553              // use Hadamard transform here
554              Distortion sad = distParam.distFunc(distParam);
555
556              // NB xFracModeBitsIntra will not affect the mode for chroma that may have already been pre-estimated.
557#if INTRA_SEARCH_CONTEXT_BUGFIX
558              m_CABACEstimator->getCtx() = SubCtx( Ctx::IPredMode[CHANNEL_TYPE_LUMA], ctxStartIntraMode );
559#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
560              m_CABACEstimator->getCtx() = SubCtx( Ctx::MHIntraPredMode, ctxStartMHIntraMode );
561#endif
562#if JVET_L0283_MULTI_REF_LINE
563              m_CABACEstimator->getCtx() = SubCtx( Ctx::MultiRefLineIdx, ctxStartMrlIdx );
564#endif
565#else
566              m_CABACEstimator->getCtx() = SubCtx(Ctx::IPredMode[CHANNEL_TYPE_LUMA], ctxStartIntraMode);
567#endif
568
569              uint64_t fracModeBits = xFracModeBitsIntra(pu, mode, CHANNEL_TYPE_LUMA);
570
571              double cost = (double)sad + (double)fracModeBits * sqrtLambdaForFirstPass;
572              updateCandList(mode, cost, uiRdModeList, CandCostList, extendRefList, multiRefIdx, numModesForFullRD);
573            }
574          }
575        }
576        CandCostList.resize(numModesForFullRD);
577        extendRefList.resize(numModesForFullRD);
578#endif
579        if( m_pcEncCfg->getFastUDIUseMPMEnabled() )
580        {
581          const int numMPMs = NUM_MOST_PROBABLE_MODES;
582          unsigned  uiPreds[numMPMs];
583
584#if JVET_L0283_MULTI_REF_LINE
585          pu.multiRefIdx = 0;
586#endif
587
588          const int numCand = PU::getIntraMPMs( pu, uiPreds );
589
590          for( int j = 0; j < numCand; j++ )
591          {
592            bool mostProbableModeIncluded = false;
593            int  mostProbableMode         = uiPreds[j];
594
595
596            for( int i = 0; i < numModesForFullRD; i++ )
597            {
598#if JVET_L0283_MULTI_REF_LINE
599              mostProbableModeIncluded |= (mostProbableMode == uiRdModeList[i] && extendRefList[i] == 0);
600#else
601              mostProbableModeIncluded |= ( mostProbableMode == uiRdModeList[i] );
602#endif
603            }
604            if( !mostProbableModeIncluded )
605            {
606#if JVET_L0283_MULTI_REF_LINE
607              extendRefList.push_back(0);
608#endif
609              numModesForFullRD++;
610              uiRdModeList.push_back( mostProbableMode );
611            }
612          }
613        }
614      }
615      else
616      {
617        for( int i = 0; i < numModesForFullRD; i++ )
618        {
619          uiRdModeList.push_back( i );
620        }
621      }
622      if( emtUsageFlag == 1 )
623      {
624        // Store the modes to be checked with RD
625        m_savedNumRdModes[puIndex] = numModesForFullRD;
626        std::copy_n( uiRdModeList.begin(), numModesForFullRD, m_savedRdModeList[puIndex] );
627#if JVET_L0283_MULTI_REF_LINE
628        std::copy_n(extendRefList.begin(), numModesForFullRD, m_savedExtendRefList[puIndex]);
629#endif
630      }
631    }
632    else //emtUsage = 2 (here we potentially reduce the number of modes that will be full-RD checked)
633    {
634      if( isAllIntra && m_pcEncCfg->getFastIntraEMT() )
635      {
636        double thresholdSkipMode;
637        if( cs.pcv->noRQT )
638        {
639          thresholdSkipMode = 1.0 + 1.4 / sqrt( ( double ) ( width*height ) );
640        }
641        else
642        {
643          switch( width )
644          {
645          case  4: thresholdSkipMode = 1.47; break; // Skip checking   4x4 Intra modes using the R-D cost in the DCT2-pass
646          case  8: thresholdSkipMode = 1.28; break; // Skip checking   8x8 Intra modes using the R-D cost in the DCT2-pass
647          case 16: thresholdSkipMode = 1.12; break; // Skip checking 16x16 Intra modes using the R-D cost in the DCT2-pass
648          case 32: thresholdSkipMode = 1.06; break; // Skip checking 32x32 Intra modes using the R-D cost in the DCT2-pass
649          default: thresholdSkipMode = 1.06; break; // Skip checking 32x32 Intra modes using the R-D cost in the DCT2-pass
650          }
651        }
652
653        numModesForFullRD = 0;
654
655        // Skip checking the modes with much larger R-D cost than the best mode
656        for( int i = 0; i < m_savedNumRdModes[puIndex]; i++ )
657        {
658          if( m_modeCostStore[puIndex][i] <= thresholdSkipMode * m_bestModeCostStore[puIndex] )
659          {
660            uiRdModeList.push_back( m_savedRdModeList[puIndex][i] );
661#if JVET_L0283_MULTI_REF_LINE
662            extendRefList.push_back(m_savedExtendRefList[puIndex][i]);
663#endif
664            numModesForFullRD++;
665          }
666        }
667      }
668      else //this is necessary because we skip the candidates list calculation, since it was already obtained for the DCT-II. Now we load it
669      {
670        // Restore the modes to be checked with RD
671        numModesForFullRD = m_savedNumRdModes[puIndex];
672        uiRdModeList.resize( numModesForFullRD );
673        std::copy_n( m_savedRdModeList[puIndex], m_savedNumRdModes[puIndex], uiRdModeList.begin() );
674#if JVET_L0283_MULTI_REF_LINE
675        CandCostList.resize(numModesForFullRD);
676        extendRefList.resize(numModesForFullRD);
677        std::copy_n(m_savedExtendRefList[puIndex], m_savedNumRdModes[puIndex], extendRefList.begin());
678#endif
679      }
680    }
681
682
683    CHECK( numModesForFullRD != uiRdModeList.size(), "Inconsistent state!" );
684
685    // after this point, don't use numModesForFullRD
686
687    // PBINTRA fast
688    if( m_pcEncCfg->getUsePbIntraFast() && !cs.slice->isIntra() && cu.partSize == SIZE_2Nx2N && uiRdModeList.size() < numModesAvailable && emtUsageFlag != 2 )
689    {
690      if( CandHadList.size() < 3 || CandHadList[2] > cs.interHad * PBINTRA_RATIO )
691      {
692        uiRdModeList.resize( std::min<size_t>( uiRdModeList.size(), 2 ) );
693      }
694      if( CandHadList.size() < 2 || CandHadList[1] > cs.interHad * PBINTRA_RATIO )
695      {
696        uiRdModeList.resize( std::min<size_t>( uiRdModeList.size(), 1 ) );
697      }
698      if( CandHadList.size() < 1 || CandHadList[0] > cs.interHad * PBINTRA_RATIO )
699      {
700        cs.dist = std::numeric_limits<Distortion>::max();
701        cs.interHad = 0;
702
703        //===== reset context models =====
704#if INTRA_SEARCH_CONTEXT_BUGFIX
705        m_CABACEstimator->getCtx() = SubCtx( Ctx::IPredMode[CHANNEL_TYPE_LUMA], ctxStartIntraMode );
706#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
707        m_CABACEstimator->getCtx() = SubCtx( Ctx::MHIntraPredMode, ctxStartMHIntraMode );
708#endif
709#if JVET_L0283_MULTI_REF_LINE
710        m_CABACEstimator->getCtx() = SubCtx( Ctx::MultiRefLineIdx, ctxStartMrlIdx );
711#endif
712#else
713        m_CABACEstimator->getCtx() = SubCtx( Ctx::IPredMode       [CHANNEL_TYPE_LUMA], ctxStartIntraMode );
714#endif
715
716        return;
717      }
718    }
719
720    //===== check modes (using r-d costs) =====
721    uint32_t       uiBestPUMode  = 0;
722#if JVET_L0283_MULTI_REF_LINE
723    int            bestExtendRef = 0;
724#endif
725
726    CodingStructure *csTemp = m_pTempCS[gp_sizeIdxInfo->idxFrom( cu.lwidth() )][gp_sizeIdxInfo->idxFrom( cu.lheight() )];
727    CodingStructure *csBest = m_pBestCS[gp_sizeIdxInfo->idxFrom( cu.lwidth() )][gp_sizeIdxInfo->idxFrom( cu.lheight() )];
728
729    csTemp->slice = cs.slice;
730    csBest->slice = cs.slice;
731    csTemp->initStructData();
732    csBest->initStructData();
733
734    // just to be sure
735    numModesForFullRD = ( int ) uiRdModeList.size();
736    for (uint32_t uiMode = 0; uiMode < numModesForFullRD; uiMode++)
737    {
738      // set luma prediction mode
739      uint32_t uiOrgMode = uiRdModeList[uiMode];
740
741      pu.intraDir[0] = uiOrgMode;
742#if JVET_L0283_MULTI_REF_LINE
743      int multiRefIdx = extendRefList[uiMode];
744      pu.multiRefIdx  = multiRefIdx;
745      CHECK(pu.multiRefIdx && (pu.intraDir[0] == DC_IDX || pu.intraDir[0] == PLANAR_IDX), "ERL");
746#endif
747
748
749      // set context models
750      m_CABACEstimator->getCtx() = ctxStart;
751
752      // determine residual for partition
753      cs.initSubStructure( *csTemp, partitioner.chType, cs.area, true );
754
755      xRecurIntraCodingLumaQT( *csTemp, partitioner );
756
757      if( emtUsageFlag == 1 && m_pcEncCfg->getFastIntraEMT() )
758      {
759        m_modeCostStore[puIndex][uiMode] = csTemp->cost; //cs.cost;
760      }
761
762
763      DTRACE( g_trace_ctx, D_INTRA_COST, "IntraCost T %f (%d) \n", csTemp->cost, uiOrgMode );
764
765      // check r-d cost
766      if( csTemp->cost < csBest->cost )
767      {
768        std::swap( csTemp, csBest );
769
770        uiBestPUMode  = uiOrgMode;
771#if JVET_L0283_MULTI_REF_LINE
772        bestExtendRef = multiRefIdx;
773#endif
774
775        if( ( emtUsageFlag == 1 ) && m_pcEncCfg->getFastIntraEMT() )
776        {
777          m_bestModeCostStore[puIndex] = csBest->cost; //cs.cost;
778        }
779      }
780
781      csTemp->releaseIntermediateData();
782    } // Mode loop
783
784    cs.useSubStructure( *csBest, partitioner.chType, pu.singleChan( CHANNEL_TYPE_LUMA ), KEEP_PRED_AND_RESI_SIGNALS, true, keepResi, keepResi );
785
786    csBest->releaseIntermediateData();
787    //=== update PU data ====
788    pu.intraDir[0] = uiBestPUMode;
789#if JVET_L0283_MULTI_REF_LINE
790    pu.multiRefIdx = bestExtendRef;
791#endif
792  }
793
794  //===== reset context models =====
795  m_CABACEstimator->getCtx() = ctxStart;
796}
797
798void IntraSearch::estIntraPredChromaQT(CodingUnit &cu, Partitioner &partitioner)
799{
800  const ChromaFormat format   = cu.chromaFormat;
801  const uint32_t    numberValidComponents = getNumberValidComponents(format);
802  CodingStructure &cs = *cu.cs;
803  const TempCtx ctxStart  ( m_CtxCache, m_CABACEstimator->getCtx() );
804
805  cs.setDecomp( cs.area.Cb(), false );
806
807  auto &pu = *cu.firstPU;
808
809  {
810    uint32_t       uiBestMode = 0;
811    Distortion uiBestDist = 0;
812    double     dBestCost = MAX_DOUBLE;
813
814    //----- init mode list ----
815    {
816      uint32_t  uiMinMode = 0;
817      uint32_t  uiMaxMode = NUM_CHROMA_MODE;
818
819      //----- check chroma modes -----
820      uint32_t chromaCandModes[ NUM_CHROMA_MODE ];
821      PU::getIntraChromaCandModes( pu, chromaCandModes );
822
823      // create a temporary CS
824      CodingStructure &saveCS = *m_pSaveCS[0];
825      saveCS.pcv      = cs.pcv;
826      saveCS.picture  = cs.picture;
827      saveCS.area.repositionTo( cs.area );
828      saveCS.clearTUs();
829
830      if( CS::isDualITree( cs ) )
831      {
832        if( partitioner.canSplit( TU_MAX_TR_SPLIT, cs ) )
833        {
834          partitioner.splitCurrArea( TU_MAX_TR_SPLIT, cs );
835
836          do
837          {
838            cs.addTU( CS::getArea( cs, partitioner.currArea(), partitioner.chType ), partitioner.chType ).depth = partitioner.currTrDepth;
839          } while( partitioner.nextPart( cs ) );
840
841          partitioner.exitCurrSplit();
842        }
843        else
844        cs.addTU( CS::getArea( cs, partitioner.currArea(), partitioner.chType ), partitioner.chType );
845      }
846
847      std::vector<TransformUnit*> orgTUs;
848
849
850      // create a store for the TUs
851      for( const auto &ptu : cs.tus )
852      {
853        // for split TUs in HEVC, add the TUs without Chroma parts for correct setting of Cbfs
854        if( pu.contains( *ptu, CHANNEL_TYPE_CHROMA ) || ( !cs.pcv->noRQT && !ptu->Cb().valid() && !ptu->Cr().valid() ) )
855        {
856          saveCS.addTU( *ptu, partitioner.chType );
857          orgTUs.push_back( ptu );
858        }
859      }
860#if JVET_L0338_MDLM
861      // SATD pre-selecting.
862      int satdModeList[NUM_CHROMA_MODE];
863      int64_t satdSortedCost[NUM_CHROMA_MODE];
864      for (int i = 0; i < NUM_CHROMA_MODE; i++)
865      {
866        satdSortedCost[i] = 0; // for the mode not pre-select by SATD, do RDO by default, so set the initial value 0.
867        satdModeList[i] = 0;
868      }
869      bool modeIsEnable[NUM_INTRA_MODE + 1]; // use intra mode idx to check whether enable
870      for (int i = 0; i < NUM_INTRA_MODE + 1; i++)
871      {
872        modeIsEnable[i] = 1;
873      }
874
875      DistParam distParam;
876      const bool useHadamard = true;
877      pu.intraDir[1] = MDLM_L_IDX; // temporary assigned, just to indicate this is a MDLM mode. for luma down-sampling operation.
878
879      initIntraPatternChType(cu, pu.Cb());
880      initIntraPatternChType(cu, pu.Cr());
881      xGetLumaRecPixels(pu, pu.Cb());
882
883      for (int idx = uiMinMode; idx <= uiMaxMode - 1; idx++)
884      {
885        int mode = chromaCandModes[idx];
886        satdModeList[idx] = mode;
887        if (PU::isLMCMode(mode) && !PU::isLMCModeEnabled(pu, mode))
888        {
889          continue;
890        }
891        if ((mode == LM_CHROMA_IDX) || (mode == PLANAR_IDX) || (mode == DM_CHROMA_IDX)) // only pre-check regular modes and MDLM modes, not including DM ,Planar, and LM
892        {
893          continue;
894        }
895        pu.intraDir[1] = mode; // temporary assigned, for SATD checking.
896
897        int64_t sad = 0;
898        CodingStructure& cs = *(pu.cs);
899
900        CompArea areaCb = pu.Cb();
901        PelBuf orgCb = cs.getOrgBuf(areaCb);
902        PelBuf predCb = cs.getPredBuf(areaCb);
903
904        m_pcRdCost->setDistParam(distParam, orgCb, predCb, pu.cs->sps->getBitDepth(CHANNEL_TYPE_CHROMA), COMPONENT_Cb, useHadamard);
905        distParam.applyWeight = false;
906
907        if (PU::isLMCMode(mode))
908        {
909          predIntraChromaLM(COMPONENT_Cb, predCb, pu, areaCb, mode);
910        }
911        else
912        {
913          predIntraAng(COMPONENT_Cb, predCb, pu, false);
914        }
915
916        sad += distParam.distFunc(distParam);
917
918        CompArea areaCr = pu.Cr();
919        PelBuf orgCr = cs.getOrgBuf(areaCr);
920        PelBuf predCr = cs.getPredBuf(areaCr);
921
922        m_pcRdCost->setDistParam(distParam, orgCr, predCr, pu.cs->sps->getBitDepth(CHANNEL_TYPE_CHROMA), COMPONENT_Cr, useHadamard);
923        distParam.applyWeight = false;
924
925        if (PU::isLMCMode(mode))
926        {
927          predIntraChromaLM(COMPONENT_Cr, predCr, pu, areaCr, mode);
928        }
929        else
930        {
931          predIntraAng(COMPONENT_Cr, predCr, pu, false);
932        }
933        sad += distParam.distFunc(distParam);
934        satdSortedCost[idx] = sad;
935      }
936      // sort the mode based on the cost from small to large.
937      int tempIdx = 0;
938      int64_t tempCost = 0;
939      for (int i = uiMinMode; i <= uiMaxMode - 1; i++)
940      {
941        for (int j = i + 1; j <= uiMaxMode - 1; j++)
942        {
943          if (satdSortedCost[j] < satdSortedCost[i])
944          {
945            tempIdx = satdModeList[i];
946            satdModeList[i] = satdModeList[j];
947            satdModeList[j] = tempIdx;
948
949            tempCost = satdSortedCost[i];
950            satdSortedCost[i] = satdSortedCost[j];
951            satdSortedCost[j] = tempCost;
952
953          }
954        }
955      }
956      int reducedModeNumber = 2; // reduce the number of chroma modes
957      for (int i = 0; i < reducedModeNumber; i++)
958      {
959        modeIsEnable[satdModeList[uiMaxMode - 1 - i]] = 0; // disable the last reducedModeNumber modes
960      }
961#endif
962
963      // save the dist
964      Distortion baseDist = cs.dist;
965
966      for (uint32_t uiMode = uiMinMode; uiMode < uiMaxMode; uiMode++)
967      {
968        const int chromaIntraMode = chromaCandModes[uiMode];
969        if( PU::isLMCMode( chromaIntraMode ) && ! PU::isLMCModeEnabled( pu, chromaIntraMode ) )
970        {
971          continue;
972        }
973#if JVET_L0338_MDLM
974        if (!modeIsEnable[chromaIntraMode] && PU::isLMCModeEnabled(pu, chromaIntraMode)) // when CCLM is disable, then MDLM is disable. not use satd checking
975        {
976          continue;
977        }
978#endif
979        cs.setDecomp( pu.Cb(), false );
980        cs.dist = baseDist;
981        //----- restore context models -----
982        m_CABACEstimator->getCtx() = ctxStart;
983
984        //----- chroma coding -----
985        pu.intraDir[1] = chromaIntraMode;
986
987        xRecurIntraChromaCodingQT( cs, partitioner );
988
989        if (cs.pps->getUseTransformSkip())
990        {
991          m_CABACEstimator->getCtx() = ctxStart;
992        }
993
994        uint64_t fracBits   = xGetIntraFracBitsQT( cs, partitioner, false, true );
995        Distortion uiDist = cs.dist;
996        double    dCost   = m_pcRdCost->calcRdCost( fracBits, uiDist - baseDist );
997
998        //----- compare -----
999        if( dCost < dBestCost )
1000        {
1001          for( uint32_t i = getFirstComponentOfChannel( CHANNEL_TYPE_CHROMA ); i < numberValidComponents; i++ )
1002          {
1003            const CompArea &area = pu.blocks[i];
1004
1005            saveCS.getRecoBuf     ( area ).copyFrom( cs.getRecoBuf   ( area ) );
1006#if KEEP_PRED_AND_RESI_SIGNALS
1007            saveCS.getPredBuf     ( area ).copyFrom( cs.getPredBuf   ( area ) );
1008            saveCS.getResiBuf     ( area ).copyFrom( cs.getResiBuf   ( area ) );
1009#endif
1010            cs.picture->getRecoBuf( area ).copyFrom( cs.getRecoBuf( area ) );
1011
1012            for( uint32_t j = 0; j < saveCS.tus.size(); j++ )
1013            {
1014              saveCS.tus[j]->copyComponentFrom( *orgTUs[j], area.compID );
1015            }
1016          }
1017
1018          dBestCost  = dCost;
1019          uiBestDist = uiDist;
1020          uiBestMode = chromaIntraMode;
1021        }
1022      }
1023
1024      for( uint32_t i = getFirstComponentOfChannel( CHANNEL_TYPE_CHROMA ); i < numberValidComponents; i++ )
1025      {
1026        const CompArea &area = pu.blocks[i];
1027
1028        cs.getRecoBuf         ( area ).copyFrom( saveCS.getRecoBuf( area ) );
1029#if KEEP_PRED_AND_RESI_SIGNALS
1030        cs.getPredBuf         ( area ).copyFrom( saveCS.getPredBuf( area ) );
1031        cs.getResiBuf         ( area ).copyFrom( saveCS.getResiBuf( area ) );
1032#endif
1033        cs.picture->getRecoBuf( area ).copyFrom( cs.    getRecoBuf( area ) );
1034
1035        for( uint32_t j = 0; j < saveCS.tus.size(); j++ )
1036        {
1037          orgTUs[ j ]->copyComponentFrom( *saveCS.tus[ j ], area.compID );
1038        }
1039      }
1040    }
1041
1042    pu.intraDir[1] = uiBestMode;
1043    cs.dist        = uiBestDist;
1044  }
1045
1046  //----- restore context models -----
1047  m_CABACEstimator->getCtx() = ctxStart;
1048}
1049
1050void IntraSearch::IPCMSearch(CodingStructure &cs, Partitioner& partitioner)
1051{
1052  for (uint32_t ch = 0; ch < getNumberValidTBlocks( *cs.pcv ); ch++)
1053  {
1054    const ComponentID compID = ComponentID(ch);
1055
1056    xEncPCM(cs, partitioner, compID);
1057  }
1058
1059  cs.getPredBuf().fill(0);
1060  cs.getResiBuf().fill(0);
1061  cs.getOrgResiBuf().fill(0);
1062
1063  cs.dist     = 0;
1064  cs.fracBits = 0;
1065  cs.cost     = 0;
1066
1067  cs.setDecomp(cs.area);
1068  cs.picture->getRecoBuf(cs.area).copyFrom(cs.getRecoBuf());
1069}
1070
1071void IntraSearch::xEncPCM(CodingStructure &cs, Partitioner& partitioner, const ComponentID &compID)
1072{
1073  TransformUnit &tu = *cs.getTU( partitioner.chType );
1074
1075  const int  channelBitDepth = cs.sps->getBitDepth(toChannelType(compID));
1076  const uint32_t uiPCMBitDepth = cs.sps->getPCMBitDepth(toChannelType(compID));
1077
1078  const int pcmShiftRight = (channelBitDepth - int(uiPCMBitDepth));
1079
1080  CompArea  area    = tu.blocks[compID];
1081  PelBuf    pcmBuf  = tu.getPcmbuf  (compID);
1082  PelBuf    recBuf  = cs.getRecoBuf ( area );
1083  CPelBuf   orgBuf  = cs.getOrgBuf  ( area );
1084
1085  CHECK(pcmShiftRight < 0, "Negative shift");
1086
1087  for (uint32_t uiY = 0; uiY < pcmBuf.height; uiY++)
1088  {
1089    for (uint32_t uiX = 0; uiX < pcmBuf.width; uiX++)
1090    {
1091      // Encode
1092      pcmBuf.at(uiX, uiY) = orgBuf.at(uiX, uiY) >> pcmShiftRight;
1093      // Reconstruction
1094      recBuf.at(uiX, uiY) = pcmBuf.at(uiX, uiY) << pcmShiftRight;
1095    }
1096  }
1097}
1098
1099// -------------------------------------------------------------------------------------------------------------------
1100// Intra search
1101// -------------------------------------------------------------------------------------------------------------------
1102
1103void IntraSearch::xEncIntraHeader(CodingStructure &cs, Partitioner &partitioner, const bool &bLuma, const bool &bChroma)
1104{
1105  CodingUnit &cu = *cs.getCU( partitioner.chType );
1106
1107  if (bLuma)
1108  {
1109    bool isFirst = partitioner.currArea().lumaPos() == cs.area.lumaPos();
1110
1111    // CU header
1112    if( isFirst )
1113    {
1114      if( !cs.slice->isIntra() 
1115#if JVET_L0293_CPR
1116        && cu.Y().valid()
1117#endif
1118        )
1119      {
1120        if( cs.pps->getTransquantBypassEnabledFlag() )
1121        {
1122          m_CABACEstimator->cu_transquant_bypass_flag( cu );
1123        }
1124        m_CABACEstimator->cu_skip_flag( cu );
1125        m_CABACEstimator->pred_mode   ( cu );
1126      }
1127#if JVET_L0283_MULTI_REF_LINE
1128      m_CABACEstimator->extend_ref_line(cu);
1129#endif
1130      if( CU::isIntra(cu) && cu.partSize == SIZE_2Nx2N )
1131      {
1132        m_CABACEstimator->pcm_data( cu );
1133        if( cu.ipcm )
1134        {
1135          return;
1136        }
1137      }
1138    }
1139
1140    PredictionUnit &pu = *cs.getPU(partitioner.currArea().lumaPos(), partitioner.chType);
1141
1142    // luma prediction mode
1143    if (cu.partSize == SIZE_2Nx2N)
1144    {
1145      if (isFirst)
1146      {
1147#if JVET_L0293_CPR
1148        if ( !cu.Y().valid())
1149          m_CABACEstimator->pred_mode( cu );
1150#endif
1151        m_CABACEstimator->intra_luma_pred_mode( pu );
1152      }
1153    }
1154  }
1155
1156  if (bChroma)
1157  {
1158    bool isFirst = partitioner.currArea().Cb().valid() && partitioner.currArea().chromaPos() == cs.area.chromaPos();
1159
1160    PredictionUnit &pu = *cs.getPU( partitioner.currArea().chromaPos(), CHANNEL_TYPE_CHROMA );
1161
1162    if( cu.partSize == SIZE_2Nx2N )
1163    {
1164      if( isFirst )
1165      {
1166        m_CABACEstimator->intra_chroma_pred_mode( pu );
1167      }
1168    }
1169  }
1170}
1171
1172void IntraSearch::xEncSubdivCbfQT(CodingStructure &cs, Partitioner &partitioner, const bool &bLuma, const bool &bChroma)
1173{
1174  const UnitArea &currArea = partitioner.currArea();
1175  TransformUnit &currTU    = *cs.getTU( currArea.blocks[partitioner.chType], partitioner.chType );
1176#if HM_EMT_NSST_AS_IN_JEM
1177  CodingUnit &currCU       = *currTU.cu;
1178#endif
1179  uint32_t currDepth           = partitioner.currTrDepth;
1180
1181  const bool subdiv        = currTU.depth > currDepth;
1182
1183  if( cs.pcv->noRQT )
1184  {
1185    if( partitioner.canSplit( TU_MAX_TR_SPLIT, cs ) )
1186    {
1187      CHECK( !subdiv, "TU split implied" );
1188    }
1189    else
1190      CHECK( subdiv, "No TU subdivision is allowed with QTBT" );
1191  }
1192
1193  if (bChroma)
1194  {
1195    const uint32_t numberValidComponents = getNumberValidComponents(currArea.chromaFormat);
1196
1197    for (uint32_t ch = COMPONENT_Cb; ch < numberValidComponents; ch++)
1198    {
1199      const ComponentID compID = ComponentID(ch);
1200
1201      if( currDepth == 0 || TU::getCbfAtDepth( currTU, compID, currDepth - 1 ) )
1202      {
1203        const bool prevCbf = ( compID == COMPONENT_Cr ? TU::getCbfAtDepth( currTU, COMPONENT_Cb, currDepth ) : false );
1204        m_CABACEstimator->cbf_comp( cs, TU::getCbfAtDepth( currTU, compID, currDepth ), currArea.blocks[compID], currDepth, prevCbf );
1205
1206      }
1207    }
1208  }
1209
1210  if (subdiv)
1211  {
1212#if HM_EMT_NSST_AS_IN_JEM
1213    if( currDepth == 0 && bLuma ) m_CABACEstimator->emt_cu_flag( currCU );
1214#endif
1215
1216    if( partitioner.canSplit( TU_MAX_TR_SPLIT, cs ) )
1217    {
1218      partitioner.splitCurrArea( TU_MAX_TR_SPLIT, cs );
1219    }
1220    else
1221    THROW( "Cannot perform an implicit split!" );
1222
1223    do
1224    {
1225      xEncSubdivCbfQT( cs, partitioner, bLuma, bChroma );
1226    } while( partitioner.nextPart( cs ) );
1227
1228    partitioner.exitCurrSplit();
1229  }
1230  else
1231  {
1232#if HM_EMT_NSST_AS_IN_JEM
1233    if( currDepth == 0 && bLuma && TU::getCbfAtDepth( currTU, COMPONENT_Y, 0 ) ) m_CABACEstimator->emt_cu_flag( currCU );
1234
1235#endif
1236    //===== Cbfs =====
1237    if (bLuma)
1238    {
1239      m_CABACEstimator->cbf_comp( cs, TU::getCbfAtDepth( currTU, COMPONENT_Y, currDepth ), currTU.Y(), currTU.depth );
1240    }
1241  }
1242}
1243
1244void IntraSearch::xEncCoeffQT(CodingStructure &cs, Partitioner &partitioner, const ComponentID &compID)
1245{
1246  const UnitArea &currArea  = partitioner.currArea();
1247  TransformUnit &currTU     = *cs.getTU( currArea.blocks[partitioner.chType], partitioner.chType );
1248  uint32_t      currDepth       = partitioner.currTrDepth;
1249  const bool subdiv         = currTU.depth > currDepth;
1250
1251  if (subdiv)
1252  {
1253    if (partitioner.canSplit(TU_MAX_TR_SPLIT, cs))
1254    {
1255      partitioner.splitCurrArea(TU_MAX_TR_SPLIT, cs);
1256    }
1257    else
1258      THROW("Implicit TU split not available!");
1259
1260    do
1261    {
1262      xEncCoeffQT( cs, partitioner, compID );
1263    } while( partitioner.nextPart( cs ) );
1264
1265    partitioner.exitCurrSplit();
1266  }
1267  else
1268
1269  if( currArea.blocks[compID].valid() )
1270  {
1271    if( TU::hasCrossCompPredInfo( currTU, compID ) )
1272    {
1273      m_CABACEstimator->cross_comp_pred( currTU, compID );
1274    }
1275    if( TU::getCbf( currTU, compID ) )
1276    {
1277      m_CABACEstimator->residual_coding( currTU, compID );
1278    }
1279  }
1280}
1281
1282uint64_t IntraSearch::xGetIntraFracBitsQT( CodingStructure &cs, Partitioner &partitioner, const bool &bLuma, const bool &bChroma )
1283{
1284  m_CABACEstimator->resetBits();
1285
1286  xEncIntraHeader( cs, partitioner, bLuma, bChroma );
1287  xEncSubdivCbfQT( cs, partitioner, bLuma, bChroma );
1288
1289  if( bLuma )
1290  {
1291    xEncCoeffQT( cs, partitioner, COMPONENT_Y );
1292  }
1293  if( bChroma )
1294  {
1295    xEncCoeffQT( cs, partitioner, COMPONENT_Cb );
1296    xEncCoeffQT( cs, partitioner, COMPONENT_Cr );
1297  }
1298
1299  uint64_t fracBits = m_CABACEstimator->getEstFracBits();
1300  return fracBits;
1301}
1302
1303uint64_t IntraSearch::xGetIntraFracBitsQTChroma(TransformUnit& currTU, const ComponentID &compID)
1304{
1305  m_CABACEstimator->resetBits();
1306
1307  if( TU::hasCrossCompPredInfo( currTU, compID ) )
1308  {
1309    m_CABACEstimator->cross_comp_pred( currTU, compID );
1310  }
1311  if( TU::getCbf( currTU, compID ) )
1312  {
1313    m_CABACEstimator->residual_coding( currTU, compID );
1314  }
1315
1316  uint64_t fracBits = m_CABACEstimator->getEstFracBits();
1317  return fracBits;
1318}
1319
1320void IntraSearch::xIntraCodingTUBlock(TransformUnit &tu, const ComponentID &compID, const bool &checkCrossCPrediction, Distortion& ruiDist, const int &default0Save1Load2, uint32_t* numSig )
1321{
1322  if (!tu.blocks[compID].valid())
1323  {
1324    return;
1325  }
1326
1327  CodingStructure &cs                       = *tu.cs;
1328
1329  const CompArea      &area                 = tu.blocks[compID];
1330  const SPS           &sps                  = *cs.sps;
1331  const PPS           &pps                  = *cs.pps;
1332
1333  const ChannelType    chType               = toChannelType(compID);
1334  const int            bitDepth             = sps.getBitDepth(chType);
1335
1336  PelBuf         piOrg                      = cs.getOrgBuf    (area);
1337  PelBuf         piPred                     = cs.getPredBuf   (area);
1338  PelBuf         piResi                     = cs.getResiBuf   (area);
1339  PelBuf         piOrgResi                  = cs.getOrgResiBuf(area);
1340  PelBuf         piReco                     = cs.getRecoBuf   (area);
1341
1342  const PredictionUnit &pu                  = *cs.getPU(area.pos(), chType);
1343  const uint32_t           uiChFinalMode        = PU::getFinalIntraMode(pu, chType);
1344
1345  const bool           bUseCrossCPrediction = pps.getPpsRangeExtension().getCrossComponentPredictionEnabledFlag() && isChroma( compID ) && PU::isChromaIntraModeCrossCheckMode( pu ) && checkCrossCPrediction;
1346  const bool           ccUseRecoResi        = m_pcEncCfg->getUseReconBasedCrossCPredictionEstimate();
1347
1348#if !JVET_L0059_MTS_SIMP
1349  const uint8_t          transformIndex       = tu.cu->emtFlag && compID == COMPONENT_Y ? tu.emtIdx : DCT2_EMT ;
1350#endif
1351
1352  //===== init availability pattern =====
1353  PelBuf sharedPredTS( m_pSharedPredTransformSkip[compID], area );
1354  if( default0Save1Load2 != 2 )
1355  {
1356    const bool bUseFilteredPredictions = IntraPrediction::useFilteredIntraRefSamples( compID, pu, true, tu );
1357    initIntraPatternChType( *tu.cu, area, bUseFilteredPredictions );
1358
1359    //===== get prediction signal =====
1360    if( compID != COMPONENT_Y && PU::isLMCMode( uiChFinalMode ) )
1361    {
1362      {
1363        xGetLumaRecPixels( pu, area );
1364      }
1365      predIntraChromaLM( compID, piPred, pu, area, uiChFinalMode );
1366    }
1367    else
1368    {
1369      predIntraAng( compID, piPred, pu, bUseFilteredPredictions );
1370    }
1371
1372
1373    // save prediction
1374    if( default0Save1Load2 == 1 )
1375    {
1376      sharedPredTS.copyFrom( piPred );
1377    }
1378  }
1379  else
1380  {
1381    // load prediction
1382    piPred.copyFrom( sharedPredTS );
1383  }
1384
1385
1386  DTRACE( g_trace_ctx, D_PRED, "@(%4d,%4d) [%2dx%2d] IMode=%d\n", tu.lx(), tu.ly(), tu.lwidth(), tu.lheight(), uiChFinalMode );
1387  //DTRACE_PEL_BUF( D_PRED, piPred, tu, tu.cu->predMode, COMPONENT_Y );
1388
1389  //===== get residual signal =====
1390  piResi.copyFrom( piOrg  );
1391  piResi.subtract( piPred );
1392
1393  if (pps.getPpsRangeExtension().getCrossComponentPredictionEnabledFlag() && isLuma(compID))
1394  {
1395    piOrgResi.copyFrom (piResi);
1396  }
1397
1398  if (bUseCrossCPrediction)
1399  {
1400    if (xCalcCrossComponentPredictionAlpha(tu, compID, ccUseRecoResi) == 0)
1401    {
1402      return;
1403    }
1404    CrossComponentPrediction::crossComponentPrediction(tu, compID, cs.getResiBuf(tu.Y()), piResi, piResi, false);
1405  }
1406
1407  //===== transform and quantization =====
1408  //--- init rate estimation arrays for RDOQ ---
1409  //--- transform and quantization           ---
1410  TCoeff uiAbsSum = 0;
1411
1412  const QpParam cQP(tu, compID);
1413
1414#if RDOQ_CHROMA_LAMBDA
1415  m_pcTrQuant->selectLambda(compID);
1416#endif
1417
1418
1419  m_pcTrQuant->transformNxN(tu, compID, cQP, uiAbsSum, m_CABACEstimator->getCtx());
1420
1421#if !JVET_L0059_MTS_SIMP
1422  if( transformIndex != DCT2_EMT && ( !tu.transformSkip[COMPONENT_Y] ) ) //this can only be true if compID is luma
1423  {
1424    *numSig = 0;
1425    TCoeff* coeffBuffer = tu.getCoeffs(compID).buf;
1426    for( uint32_t uiX = 0; uiX < tu.Y().area(); uiX++ )
1427    {
1428      if( coeffBuffer[uiX] )
1429      {
1430        ( *numSig )++;
1431        if( *numSig > g_EmtSigNumThr )
1432        {
1433          break;
1434        }
1435      }
1436    }
1437    //if the number of significant coeffs is less than the threshold, then only the default transform (which has a 0 index, but it is the DST7) is allowed
1438    if( transformIndex != 0 && *numSig <= g_EmtSigNumThr && !tu.transformSkip[compID] )
1439    {
1440      return;
1441    }
1442  }
1443#endif
1444
1445  DTRACE( g_trace_ctx, D_TU_ABS_SUM, "%d: comp=%d, abssum=%d\n", DTRACE_GET_COUNTER( g_trace_ctx, D_TU_ABS_SUM ), compID, uiAbsSum );
1446
1447
1448  //--- inverse transform ---
1449  if (uiAbsSum > 0)
1450  {
1451    m_pcTrQuant->invTransformNxN(tu, compID, piResi, cQP);
1452  }
1453  else
1454  {
1455    piResi.fill(0);
1456  }
1457
1458  //===== reconstruction =====
1459  if (bUseCrossCPrediction)
1460  {
1461    CrossComponentPrediction::crossComponentPrediction(tu, compID, cs.getResiBuf(tu.Y()), piResi, piResi, true);
1462  }
1463
1464  piReco.reconstruct(piPred, piResi, cs.slice->clpRng( compID ));
1465
1466  //===== update distortion =====
1467#if WCG_EXT
1468  if( m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled() )
1469  {
1470    const CPelBuf orgLuma = cs.getOrgBuf( cs.area.blocks[COMPONENT_Y] );
1471    ruiDist += m_pcRdCost->getDistPart( piOrg, piReco, bitDepth, compID, DF_SSE_WTD, &orgLuma );
1472  }
1473  else
1474#endif
1475  {
1476    ruiDist += m_pcRdCost->getDistPart( piOrg, piReco, bitDepth, compID, DF_SSE );
1477  }
1478}
1479
1480void IntraSearch::xRecurIntraCodingLumaQT( CodingStructure &cs, Partitioner &partitioner )
1481{
1482  const UnitArea &currArea = partitioner.currArea();
1483  const CodingUnit &cu     = *cs.getCU(currArea.lumaPos(), partitioner.chType);
1484  uint32_t     currDepth       = partitioner.currTrDepth;
1485  const PPS &pps           = *cs.pps;
1486  const bool keepResi      = pps.getPpsRangeExtension().getCrossComponentPredictionEnabledFlag() || KEEP_PRED_AND_RESI_SIGNALS;
1487  bool bCheckFull          = true;
1488  bool bCheckSplit         = false;
1489  bCheckFull               = cs.pcv->noRQT && !partitioner.canSplit( TU_MAX_TR_SPLIT, cs );
1490  bCheckSplit              = cs.pcv->noRQT &&  partitioner.canSplit( TU_MAX_TR_SPLIT, cs );
1491
1492  uint32_t    numSig           = 0;
1493
1494  if( !cs.pcv->noRQT )
1495  {
1496  }
1497
1498  bool    checkInitTrDepth = false, checkInitTrDepthTransformSkipWinner = false;
1499
1500  double     dSingleCost                        = MAX_DOUBLE;
1501  Distortion uiSingleDistLuma                   = 0;
1502  uint64_t     singleFracBits                     = 0;
1503  bool       checkTransformSkip                 = pps.getUseTransformSkip();
1504  int        bestModeId[MAX_NUM_COMPONENT]      = {0, 0, 0};
1505  uint8_t      nNumTransformCands                 = cu.emtFlag ? 4 : 1; //4 is the number of transforms of emt
1506  bool       isAllIntra                         = m_pcEncCfg->getIntraPeriod() == 1;
1507
1508  uint8_t numTransformIndexCands                  = nNumTransformCands;
1509
1510  const TempCtx ctxStart  ( m_CtxCache, m_CABACEstimator->getCtx() );
1511  TempCtx       ctxBest   ( m_CtxCache );
1512
1513  CodingStructure *csSplit = nullptr;
1514  CodingStructure *csFull  = nullptr;
1515
1516  if( bCheckSplit )
1517  {
1518    csSplit = &cs;
1519  }
1520  else if( bCheckFull )
1521  {
1522    csFull = &cs;
1523  }
1524
1525  if( bCheckFull )
1526  {
1527    csFull->cost = 0.0;
1528
1529    TransformUnit &tu = csFull->addTU( CS::getArea( *csFull, currArea, partitioner.chType ), partitioner.chType );
1530    tu.depth = currDepth;
1531
1532    checkTransformSkip &= TU::hasTransformSkipFlag( *tu.cs, tu.Y() );
1533    checkTransformSkip &= !cu.transQuantBypass;
1534    checkTransformSkip &= !cu.emtFlag;
1535
1536    CHECK( !tu.Y().valid(), "Invalid TU" );
1537
1538    //this prevents transformSkip from being checked because we already know it's not the best mode
1539    checkTransformSkip = ( checkInitTrDepth && !checkInitTrDepthTransformSkipWinner ) ? false : checkTransformSkip;
1540
1541
1542    CHECK( checkInitTrDepthTransformSkipWinner && !checkTransformSkip, "Transform Skip must be enabled if it was the winner in the previous call of xRecurIntraCodingLumaQT!" );
1543
1544    CodingStructure &saveCS = *m_pSaveCS[0];
1545
1546    TransformUnit *tmpTU = nullptr;
1547
1548    Distortion singleDistTmpLuma = 0;
1549    uint64_t     singleTmpFracBits = 0;
1550    double     singleCostTmp     = 0;
1551    int        firstCheckId      = 0;
1552
1553    //we add the EMT candidates to the loop. TransformSkip will still be the last one to be checked (when modeId == lastCheckId) as long as checkTransformSkip is true
1554    int        lastCheckId       = numTransformIndexCands - ( firstCheckId + 1 ) + ( int ) checkTransformSkip;
1555    bool isNotOnlyOneMode        = lastCheckId != firstCheckId && !checkInitTrDepthTransformSkipWinner;
1556
1557    if( isNotOnlyOneMode )
1558    {
1559      saveCS.pcv     = cs.pcv;
1560      saveCS.picture = cs.picture;
1561      saveCS.area.repositionTo(cs.area);
1562      saveCS.clearTUs();
1563      tmpTU = &saveCS.addTU(currArea, partitioner.chType);
1564    }
1565
1566    bool cbfBestMode = false;
1567
1568
1569    for( int modeId = firstCheckId; modeId <= lastCheckId; modeId++ )
1570    {
1571      if( checkInitTrDepthTransformSkipWinner )
1572      {
1573        //If this is a full RQT call and the winner of the first call (checkFirst=true) was transformSkip, then we skip the first iteration of the loop, since transform skip always comes at the end
1574        if( modeId == firstCheckId )
1575        {
1576          continue;
1577        }
1578      }
1579
1580      uint8_t transformIndex = modeId;
1581
1582
1583      if( ( transformIndex < lastCheckId ) || ( ( transformIndex == lastCheckId ) && !checkTransformSkip ) ) //we avoid this if the mode is transformSkip
1584      {
1585        // Skip checking other transform candidates if zero CBF is encountered and it is the best transform so far
1586        if( m_pcEncCfg->getFastIntraEMT() && isAllIntra && transformIndex && !cbfBestMode )
1587        {
1588          continue;
1589        }
1590      }
1591
1592      if ((modeId != firstCheckId) && isNotOnlyOneMode)
1593      {
1594        m_CABACEstimator->getCtx() = ctxStart;
1595      }
1596
1597      int default0Save1Load2 = 0;
1598      singleDistTmpLuma = 0;
1599
1600      if (modeId == firstCheckId && modeId != lastCheckId && !checkInitTrDepthTransformSkipWinner )
1601      {
1602        default0Save1Load2 = 1;
1603      }
1604      else if (modeId != firstCheckId)
1605      {
1606        default0Save1Load2 = 2;
1607      }
1608
1609      if (cu.emtFlag)
1610      {
1611        tu.emtIdx = transformIndex;
1612      }
1613      if( !checkTransformSkip )
1614      {
1615        tu.transformSkip[COMPONENT_Y] = false;
1616      }
1617      else
1618      {
1619        tu.transformSkip[COMPONENT_Y] = modeId == lastCheckId;
1620      }
1621
1622      xIntraCodingTUBlock( tu, COMPONENT_Y, false, singleDistTmpLuma, default0Save1Load2, &numSig );
1623
1624      //----- determine rate and r-d cost -----
1625      //the condition (transformIndex != DCT2_EMT) seems to be irrelevant, since DCT2_EMT=7 and the highest value of transformIndex is 4
1626#if JVET_L0059_MTS_SIMP
1627      if( ( modeId == lastCheckId && checkTransformSkip && !TU::getCbfAtDepth( tu, COMPONENT_Y, currDepth ) ) )
1628#else
1629      if( ( modeId == lastCheckId && checkTransformSkip && !TU::getCbfAtDepth( tu, COMPONENT_Y, currDepth ) )
1630        || ( tu.emtIdx > 0 && ( checkTransformSkip ? transformIndex != lastCheckId : true ) && tu.emtIdx != DCT2_EMT && numSig <= g_EmtSigNumThr ) )
1631#endif
1632      {
1633        //In order not to code TS flag when cbf is zero, the case for TS with cbf being zero is forbidden.
1634        singleCostTmp = MAX_DOUBLE;
1635      }
1636      else
1637      {
1638        singleTmpFracBits = xGetIntraFracBitsQT( *csFull, partitioner, true, false );
1639        singleCostTmp     = m_pcRdCost->calcRdCost( singleTmpFracBits, singleDistTmpLuma );
1640      }
1641
1642      if (singleCostTmp < dSingleCost)
1643      {
1644        dSingleCost       = singleCostTmp;
1645        uiSingleDistLuma  = singleDistTmpLuma;
1646        singleFracBits    = singleTmpFracBits;
1647
1648        bestModeId[COMPONENT_Y] = modeId;
1649        cbfBestMode       = TU::getCbfAtDepth( tu, COMPONENT_Y, currDepth );
1650
1651
1652        if( bestModeId[COMPONENT_Y] != lastCheckId )
1653        {
1654#if KEEP_PRED_AND_RESI_SIGNALS
1655          saveCS.getPredBuf( tu.Y() ).copyFrom( csFull->getPredBuf( tu.Y() ) );
1656#endif
1657          saveCS.getRecoBuf( tu.Y() ).copyFrom( csFull->getRecoBuf( tu.Y() ) );
1658
1659          if( keepResi )
1660          {
1661            saveCS.getResiBuf   ( tu.Y() ).copyFrom( csFull->getResiBuf   ( tu.Y() ) );
1662            saveCS.getOrgResiBuf( tu.Y() ).copyFrom( csFull->getOrgResiBuf( tu.Y() ) );
1663          }
1664
1665          tmpTU->copyComponentFrom( tu, COMPONENT_Y );
1666
1667          ctxBest = m_CABACEstimator->getCtx();
1668        }
1669      }
1670    }
1671
1672    if( bestModeId[COMPONENT_Y] != lastCheckId )
1673    {
1674#if KEEP_PRED_AND_RESI_SIGNALS
1675      csFull->getPredBuf( tu.Y() ).copyFrom( saveCS.getPredBuf( tu.Y() ) );
1676#endif
1677      csFull->getRecoBuf( tu.Y() ).copyFrom( saveCS.getRecoBuf( tu.Y() ) );
1678
1679      if( keepResi )
1680      {
1681        csFull->getResiBuf   ( tu.Y() ).copyFrom( saveCS.getResiBuf   ( tu.Y() ) );
1682        csFull->getOrgResiBuf( tu.Y() ).copyFrom( saveCS.getOrgResiBuf( tu.Y() ) );
1683      }
1684
1685      tu.copyComponentFrom( *tmpTU, COMPONENT_Y );
1686
1687      if( !bCheckSplit )
1688      {
1689        m_CABACEstimator->getCtx() = ctxBest;
1690      }
1691    }
1692    else if( bCheckSplit )
1693    {
1694      ctxBest = m_CABACEstimator->getCtx();
1695    }
1696
1697    csFull->cost     += dSingleCost;
1698    csFull->dist     += uiSingleDistLuma;
1699    csFull->fracBits += singleFracBits;
1700  }
1701
1702  if( bCheckSplit )
1703  {
1704    //----- store full entropy coding status, load original entropy coding status -----
1705    if( bCheckFull )
1706    {
1707      m_CABACEstimator->getCtx() = ctxStart;
1708    }
1709    //----- code splitted block -----
1710    csSplit->cost = 0;
1711
1712    bool uiSplitCbfLuma  = false;
1713    bool splitIsSelected = true;
1714    if( cs.pcv->noRQT && partitioner.canSplit( TU_MAX_TR_SPLIT, cs ) )
1715    {
1716      partitioner.splitCurrArea( TU_MAX_TR_SPLIT, cs );
1717    }
1718
1719    do
1720    {
1721      xRecurIntraCodingLumaQT( *csSplit, partitioner );
1722
1723      csSplit->setDecomp( partitioner.currArea().Y() );
1724
1725      uiSplitCbfLuma |= TU::getCbfAtDepth( *csSplit->getTU( partitioner.currArea().lumaPos(), partitioner.chType ), COMPONENT_Y, partitioner.currTrDepth );
1726
1727
1728
1729    } while( partitioner.nextPart( *csSplit ) );
1730
1731    partitioner.exitCurrSplit();
1732
1733    if( splitIsSelected )
1734    {
1735      for( auto &ptu : csSplit->tus )
1736      {
1737        if( currArea.Y().contains( ptu->Y() ) )
1738        {
1739          TU::setCbfAtDepth( *ptu, COMPONENT_Y, currDepth, uiSplitCbfLuma ? 1 : 0 );
1740        }
1741      }
1742
1743      //----- restore context states -----
1744      m_CABACEstimator->getCtx() = ctxStart;
1745
1746      //----- determine rate and r-d cost -----
1747      csSplit->fracBits = xGetIntraFracBitsQT(*csSplit, partitioner, true, false);
1748
1749      //--- update cost ---
1750      csSplit->cost     = m_pcRdCost->calcRdCost(csSplit->fracBits, csSplit->dist);
1751    }
1752  }
1753
1754  if( csFull || csSplit )
1755  {
1756    {
1757      // otherwise this would've happened in useSubStructure
1758      cs.picture->getRecoBuf( currArea.Y() ).copyFrom( cs.getRecoBuf( currArea.Y() ) );
1759    }
1760
1761    cs.cost = m_pcRdCost->calcRdCost( cs.fracBits, cs.dist );
1762  }
1763}
1764
1765ChromaCbfs IntraSearch::xRecurIntraChromaCodingQT(CodingStructure &cs, Partitioner& partitioner)
1766{
1767  UnitArea currArea                   = partitioner.currArea();
1768  const bool keepResi                 = cs.sps->getSpsNext().getUseLMChroma() || KEEP_PRED_AND_RESI_SIGNALS;
1769  if( !currArea.Cb().valid() ) return ChromaCbfs( false );
1770
1771
1772  TransformUnit &currTU               = *cs.getTU( currArea.chromaPos(), CHANNEL_TYPE_CHROMA );
1773  const PredictionUnit &pu            = *cs.getPU( currArea.chromaPos(), CHANNEL_TYPE_CHROMA );
1774  const TransformUnit &currTULuma     = CS::isDualITree( cs ) ? *cs.picture->cs->getTU( currArea.lumaPos(), CHANNEL_TYPE_LUMA ) : currTU;
1775
1776  uint32_t     currDepth                  = partitioner.currTrDepth;
1777  const PPS &pps                      = *cs.pps;
1778  ChromaCbfs cbfs                     ( false );
1779
1780  if (currDepth == currTU.depth)
1781  {
1782    if (!currArea.Cb().valid() || !currArea.Cr().valid())
1783    {
1784      return cbfs;
1785    }
1786
1787    bool checkTransformSkip = pps.getUseTransformSkip();
1788    checkTransformSkip &= TU::hasTransformSkipFlag( *currTU.cs, partitioner.currArea().Cb() );
1789
1790    if( m_pcEncCfg->getUseTransformSkipFast() )
1791    {
1792      checkTransformSkip &= TU::hasTransformSkipFlag( *currTU.cs, partitioner.currArea().Y() );
1793
1794      if( checkTransformSkip && cs.pcv->noChroma2x2 )
1795      {
1796        int nbLumaSkip = currTULuma.transformSkip[0] ? 1 : 0;
1797
1798        {
1799          // the chroma blocks are co-located with the last luma block, so backwards references are needed
1800          nbLumaSkip += cs.getTU( currTULuma.Y().topLeft().offset( -1,  0 ), partitioner.chType )->transformSkip[0] ? 1 : 0;
1801          nbLumaSkip += cs.getTU( currTULuma.Y().topLeft().offset( -1, -1 ), partitioner.chType )->transformSkip[0] ? 1 : 0;
1802          nbLumaSkip += cs.getTU( currTULuma.Y().topLeft().offset(  0, -1 ), partitioner.chType )->transformSkip[0] ? 1 : 0;
1803        }
1804
1805        checkTransformSkip &= ( nbLumaSkip > 0 );
1806      }
1807    }
1808
1809    CodingStructure &saveCS = *m_pSaveCS[1];
1810    saveCS.pcv      = cs.pcv;
1811    saveCS.picture  = cs.picture;
1812    saveCS.area.repositionTo( cs.area );
1813    saveCS.initStructData( -1, false, true );
1814
1815    TransformUnit &tmpTU = saveCS.addTU(currArea, partitioner.chType);
1816
1817
1818    cs.setDecomp(currArea.Cb(), true); // set in advance (required for Cb2/Cr2 in 4:2:2 video)
1819
1820    const unsigned      numTBlocks  = ::getNumberValidTBlocks( *cs.pcv );
1821
1822    for( uint32_t c = COMPONENT_Cb; c < numTBlocks; c++)
1823    {
1824      const ComponentID compID  = ComponentID(c);
1825      const CompArea&   area    = currTU.blocks[compID];
1826
1827      double     dSingleCost    = MAX_DOUBLE;
1828      int        bestModeId     = 0;
1829      Distortion singleDistC    = 0;
1830      Distortion singleDistCTmp = 0;
1831      double     singleCostTmp  = 0;
1832
1833      const bool checkCrossComponentPrediction = PU::isChromaIntraModeCrossCheckMode( pu ) && pps.getPpsRangeExtension().getCrossComponentPredictionEnabledFlag() && TU::getCbf( currTU, COMPONENT_Y );
1834
1835      const int  crossCPredictionModesToTest = checkCrossComponentPrediction ? 2 : 1;
1836      const int  transformSkipModesToTest    = checkTransformSkip ? 2 : 1;
1837      const int  totalModesToTest            = crossCPredictionModesToTest * transformSkipModesToTest;
1838      const bool isOneMode                   = (totalModesToTest == 1);
1839
1840      int currModeId = 0;
1841      int default0Save1Load2 = 0;
1842
1843      TempCtx ctxStart  ( m_CtxCache );
1844      TempCtx ctxBest   ( m_CtxCache );
1845
1846      if (!isOneMode)
1847      {
1848        ctxStart = m_CABACEstimator->getCtx();
1849      }
1850
1851      for (int transformSkipModeId = 0; transformSkipModeId < transformSkipModesToTest; transformSkipModeId++)
1852      {
1853        for (int crossCPredictionModeId = 0; crossCPredictionModeId < crossCPredictionModesToTest; crossCPredictionModeId++)
1854        {
1855          currTU.compAlpha    [compID] = 0;
1856          currTU.transformSkip[compID] = transformSkipModeId;
1857
1858          currModeId++;
1859
1860          const bool isFirstMode = (currModeId == 1);
1861          const bool isLastMode  = (currModeId == totalModesToTest); // currModeId is indexed from 1
1862
1863          if (isOneMode)
1864          {
1865            default0Save1Load2 = 0;
1866          }
1867          else if (!isOneMode && (transformSkipModeId == 0) && (crossCPredictionModeId == 0))
1868          {
1869            default0Save1Load2 = 1; //save prediction on first mode
1870          }
1871          else
1872          {
1873            default0Save1Load2 = 2; //load it on subsequent modes
1874          }
1875
1876          if (!isFirstMode) // if not first mode to be tested
1877          {
1878            m_CABACEstimator->getCtx() = ctxStart;
1879          }
1880
1881          singleDistCTmp = 0;
1882
1883          xIntraCodingTUBlock( currTU, compID, crossCPredictionModeId != 0, singleDistCTmp, default0Save1Load2 );
1884
1885          if( ( ( crossCPredictionModeId == 1 ) && ( currTU.compAlpha[compID] == 0 ) ) || ( ( transformSkipModeId == 1 ) && !TU::getCbf( currTU, compID ) ) ) //In order not to code TS flag when cbf is zero, the case for TS with cbf being zero is forbidden.
1886          {
1887            singleCostTmp = MAX_DOUBLE;
1888          }
1889          else if( !isOneMode )
1890          {
1891            uint64_t fracBitsTmp = xGetIntraFracBitsQTChroma( currTU, compID );
1892            singleCostTmp = m_pcRdCost->calcRdCost( fracBitsTmp, singleDistCTmp );
1893          }
1894
1895          if( singleCostTmp < dSingleCost )
1896          {
1897            dSingleCost = singleCostTmp;
1898            singleDistC = singleDistCTmp;
1899            bestModeId  = currModeId;
1900
1901            if( !isLastMode )
1902            {
1903#if KEEP_PRED_AND_RESI_SIGNALS
1904              saveCS.getPredBuf   (area).copyFrom(cs.getPredBuf   (area));
1905              saveCS.getOrgResiBuf(area).copyFrom(cs.getOrgResiBuf(area));
1906#endif
1907              if( keepResi )
1908              {
1909                saveCS.getResiBuf (area).copyFrom(cs.getResiBuf   (area));
1910              }
1911              saveCS.getRecoBuf   (area).copyFrom(cs.getRecoBuf   (area));
1912
1913              tmpTU.copyComponentFrom(currTU, compID);
1914
1915              ctxBest = m_CABACEstimator->getCtx();
1916            }
1917          }
1918        }
1919      }
1920
1921      if (bestModeId < totalModesToTest)
1922      {
1923#if KEEP_PRED_AND_RESI_SIGNALS
1924        cs.getPredBuf   (area).copyFrom(saveCS.getPredBuf   (area));
1925        cs.getOrgResiBuf(area).copyFrom(saveCS.getOrgResiBuf(area));
1926#endif
1927        if( keepResi )
1928        {
1929          cs.getResiBuf (area).copyFrom(saveCS.getResiBuf   (area));
1930        }
1931        cs.getRecoBuf   (area).copyFrom(saveCS.getRecoBuf   (area));
1932
1933        currTU.copyComponentFrom(tmpTU, compID);
1934
1935        m_CABACEstimator->getCtx() = ctxBest;
1936      }
1937
1938      cs.picture->getRecoBuf(area).copyFrom(cs.getRecoBuf(area));
1939
1940      cbfs.cbf(compID) = TU::getCbf(currTU, compID);
1941
1942      cs.dist += singleDistC;
1943    }
1944  }
1945  else
1946  {
1947    unsigned    numValidTBlocks   = ::getNumberValidTBlocks( *cs.pcv );
1948    ChromaCbfs  SplitCbfs         ( false );
1949
1950    if( partitioner.canSplit( TU_MAX_TR_SPLIT, cs ) )
1951    {
1952      partitioner.splitCurrArea( TU_MAX_TR_SPLIT, cs );
1953    }
1954    else
1955      THROW( "Implicit TU split not available" );
1956
1957    do
1958    {
1959      ChromaCbfs subCbfs = xRecurIntraChromaCodingQT( cs, partitioner );
1960
1961      for( uint32_t ch = COMPONENT_Cb; ch < numValidTBlocks; ch++ )
1962      {
1963        const ComponentID compID = ComponentID( ch );
1964        SplitCbfs.cbf( compID ) |= subCbfs.cbf( compID );
1965      }
1966    } while( partitioner.nextPart( cs ) );
1967
1968    partitioner.exitCurrSplit();
1969
1970    {
1971
1972      cbfs.Cb |= SplitCbfs.Cb;
1973      cbfs.Cr |= SplitCbfs.Cr;
1974
1975      for( auto &ptu : cs.tus )
1976      {
1977        if( currArea.Cb().contains( ptu->Cb() ) || ( !ptu->Cb().valid() && currArea.Y().contains( ptu->Y() ) ) )
1978        {
1979          TU::setCbfAtDepth( *ptu, COMPONENT_Cb, currDepth, SplitCbfs.Cb );
1980          TU::setCbfAtDepth( *ptu, COMPONENT_Cr, currDepth, SplitCbfs.Cr );
1981        }
1982      }
1983    }
1984  }
1985
1986  return cbfs;
1987}
1988
1989uint64_t IntraSearch::xFracModeBitsIntra(PredictionUnit &pu, const uint32_t &uiMode, const ChannelType &chType)
1990{
1991  uint32_t orgMode = uiMode;
1992
1993#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
1994  if (!pu.mhIntraFlag)
1995#endif
1996  std::swap(orgMode, pu.intraDir[chType]);
1997
1998  m_CABACEstimator->resetBits();
1999
2000  if( isLuma( chType ) )
2001  {
2002#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
2003    if ( pu.mhIntraFlag )
2004      m_CABACEstimator->MHIntra_luma_pred_modes(*pu.cu);
2005    else
2006    {
2007#if JVET_L0283_MULTI_REF_LINE
2008      m_CABACEstimator->extend_ref_line(pu);
2009#endif
2010      m_CABACEstimator->intra_luma_pred_mode(pu);
2011    }
2012#else
2013#if JVET_L0283_MULTI_REF_LINE
2014    m_CABACEstimator->extend_ref_line(pu);
2015#endif
2016    m_CABACEstimator->intra_luma_pred_mode( pu );
2017#endif
2018  }
2019  else
2020  {
2021    m_CABACEstimator->intra_chroma_pred_mode( pu );
2022  }
2023
2024#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
2025  if ( !pu.mhIntraFlag )
2026#endif
2027  std::swap(orgMode, pu.intraDir[chType]);
2028
2029  return m_CABACEstimator->getEstFracBits();
2030}
2031
2032
2033
2034void IntraSearch::encPredIntraDPCM( const ComponentID &compID, PelBuf &pOrg, PelBuf &pDst, const uint32_t &uiDirMode )
2035{
2036  CHECK( pOrg.buf == 0, "Encoder DPCM called without original buffer" );
2037
2038  const int srcStride = m_topRefLength + 1;
2039  CPelBuf   pSrc = CPelBuf(getPredictorPtr(compID), srcStride, m_leftRefLength + 1);
2040
2041  // Sample Adaptive intra-Prediction (SAP)
2042  if( uiDirMode == HOR_IDX )
2043  {
2044    // left column filled with reference samples, remaining columns filled with pOrg data
2045    for( int y = 0; y < pDst.height; y++ )
2046    {
2047      pDst.at( 0, y ) = pSrc.at( 0, 1 + y );
2048    }
2049    CPelBuf orgRest  = pOrg.subBuf( 0, 0, pOrg.width - 1, pOrg.height );
2050    PelBuf  predRest = pDst.subBuf( 1, 0, pDst.width - 1, pDst.height );
2051
2052    predRest.copyFrom( orgRest );
2053  }
2054  else // VER_IDX
2055  {
2056    // top row filled with reference samples, remaining rows filled with pOrg data
2057    for( int x = 0; x < pDst.width; x++ )
2058    {
2059      pDst.at( x, 0 ) = pSrc.at( 1 + x, 0 );
2060    }
2061    CPelBuf orgRest  = pOrg.subBuf( 0, 0, pOrg.width, pOrg.height - 1 );
2062    PelBuf  predRest = pDst.subBuf( 0, 1, pDst.width, pDst.height - 1 );
2063
2064    predRest.copyFrom( orgRest );
2065  }
2066}
2067
2068bool IntraSearch::useDPCMForFirstPassIntraEstimation( const PredictionUnit &pu, const uint32_t &uiDirMode )
2069{
2070  return CU::isRDPCMEnabled( *pu.cu ) && pu.cu->transQuantBypass && (uiDirMode == HOR_IDX || uiDirMode == VER_IDX);
2071}