Coverage Report

Created: 2026-10-17 06:56

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/work/vvenc/source/Lib/EncoderLib/IntraSearch.cpp
Line
Count
Source
1
/* -----------------------------------------------------------------------------
2
The copyright in this software is being made available under the Clear BSD
3
License, included below. No patent rights, trademark rights and/or 
4
other Intellectual Property Rights other than the copyrights concerning 
5
the Software are granted under this license.
6
7
The Clear BSD License
8
9
Copyright (c) 2019-2026, Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. & The VVenC Authors.
10
All rights reserved.
11
12
Redistribution and use in source and binary forms, with or without modification,
13
are permitted (subject to the limitations in the disclaimer below) provided that
14
the following conditions are met:
15
16
     * Redistributions of source code must retain the above copyright notice,
17
     this list of conditions and the following disclaimer.
18
19
     * Redistributions in binary form must reproduce the above copyright
20
     notice, this list of conditions and the following disclaimer in the
21
     documentation and/or other materials provided with the distribution.
22
23
     * Neither the name of the copyright holder nor the names of its
24
     contributors may be used to endorse or promote products derived from this
25
     software without specific prior written permission.
26
27
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY
28
THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
29
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
31
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
32
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
33
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
34
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
35
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
36
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38
POSSIBILITY OF SUCH DAMAGE.
39
40
41
------------------------------------------------------------------------------------------- */
42
43
44
/** \file     EncSearch.cpp
45
 *  \brief    encoder intra search class
46
 */
47
48
#include "IntraSearch.h"
49
#include "EncPicture.h"
50
#include "CommonLib/CommonDef.h"
51
#include "CommonLib/Rom.h"
52
#include "CommonLib/Picture.h"
53
#include "CommonLib/UnitTools.h"
54
#include "CommonLib/dtrace_next.h"
55
#include "CommonLib/dtrace_buffer.h"
56
#include <math.h>
57
#include "vvenc/vvencCfg.h"
58
59
//! \ingroup EncoderLib
60
//! \{
61
62
namespace vvenc {
63
64
#define PLTCtx(c) SubCtx( Ctx::Palette, c )
65
66
IntraSearch::IntraSearch()
67
4.62k
  : m_pSaveCS       (nullptr)
68
4.62k
  , m_pcEncCfg      (nullptr)
69
4.62k
  , m_pcTrQuant     (nullptr)
70
4.62k
  , m_pcRdCost      (nullptr)
71
4.62k
  , m_CABACEstimator(nullptr)
72
4.62k
  , m_CtxCache      (nullptr)
73
4.62k
{
74
4.62k
}
75
76
void IntraSearch::init(const VVEncCfg &encCfg, TrQuant *pTrQuant, RdCost *pRdCost, SortedPelUnitBufs<SORTED_BUFS> *pSortedPelUnitBufs, XUCache &unitCache )
77
4.62k
{
78
4.62k
  IntraPrediction::init( encCfg.m_internChromaFormat, encCfg.m_internalBitDepth[ CH_L ] );
79
80
4.62k
  m_pcEncCfg          = &encCfg;
81
4.62k
  m_pcTrQuant         = pTrQuant;
82
4.62k
  m_pcRdCost          = pRdCost;
83
4.62k
  m_SortedPelUnitBufs = pSortedPelUnitBufs;
84
85
4.62k
  const ChromaFormat chrFormat = encCfg.m_internChromaFormat;
86
4.62k
  const int maxCUSize          = encCfg.m_CTUSize;
87
88
4.62k
  Area area = Area( 0, 0, maxCUSize, maxCUSize );
89
90
4.62k
  m_pTempCS = new CodingStructure( unitCache, nullptr );
91
4.62k
  m_pBestCS = new CodingStructure( unitCache, nullptr );
92
93
4.62k
  m_pTempCS->createForSearch( chrFormat, area );
94
4.62k
  m_pBestCS->createForSearch( chrFormat, area );
95
96
4.62k
  const int uiNumSaveLayersToAllocate = 3;
97
4.62k
  m_pSaveCS = new CodingStructure*[uiNumSaveLayersToAllocate];
98
18.4k
  for( int layer = 0; layer < uiNumSaveLayersToAllocate; layer++ )
99
13.8k
  {
100
13.8k
    m_pSaveCS[ layer ] = new CodingStructure( unitCache, nullptr );
101
13.8k
    m_pSaveCS[ layer ]->createForSearch( chrFormat, Area( 0, 0, maxCUSize, maxCUSize ) );
102
13.8k
    m_pSaveCS[ layer ]->initStructData();
103
13.8k
  }
104
105
4.62k
  CompArea chromaArea( COMP_Cb, chrFormat, area, true );
106
27.7k
  for( int i = 0; i < 5; i++ )
107
23.1k
  {
108
23.1k
    m_orgResiCb[i].create( chromaArea );
109
23.1k
    m_orgResiCr[i].create( chromaArea );
110
23.1k
  }
111
4.62k
}
112
113
void IntraSearch::destroy()
114
4.62k
{
115
4.62k
  if ( m_pSaveCS )
116
4.62k
  {
117
4.62k
    const int uiNumSaveLayersToAllocate = 3;
118
18.4k
    for( int layer = 0; layer < uiNumSaveLayersToAllocate; layer++ )
119
13.8k
    {
120
13.8k
      if ( m_pSaveCS[ layer ] ) { m_pSaveCS[ layer ]->destroy(); delete m_pSaveCS[ layer ]; }
121
13.8k
    }
122
4.62k
    delete[] m_pSaveCS;
123
4.62k
    m_pSaveCS = nullptr;
124
4.62k
  }
125
126
4.62k
  if( m_pTempCS )
127
4.62k
  {
128
4.62k
    m_pTempCS->destroy();
129
4.62k
    delete m_pTempCS; m_pTempCS = nullptr;
130
4.62k
  }
131
132
4.62k
  if( m_pBestCS )
133
4.62k
  {
134
4.62k
    m_pBestCS->destroy();
135
4.62k
    delete m_pBestCS; m_pBestCS = nullptr;
136
4.62k
  }
137
4.62k
}
138
139
IntraSearch::~IntraSearch()
140
4.62k
{
141
4.62k
  destroy();
142
4.62k
}
143
144
void IntraSearch::setCtuEncRsrc( CABACWriter* cabacEstimator, CtxCache *ctxCache )
145
3.50k
{
146
3.50k
  m_CABACEstimator = cabacEstimator;
147
3.50k
  m_CtxCache       = ctxCache;
148
3.50k
}
149
150
//////////////////////////////////////////////////////////////////////////
151
// INTRA PREDICTION
152
//////////////////////////////////////////////////////////////////////////
153
static constexpr double COST_UNKNOWN = -65536.0;
154
155
double IntraSearch::xFindInterCUCost( CodingUnit &cu )
156
23.7k
{
157
23.7k
  if( CU::isConsIntra(cu) && !cu.slice->isIntra() )
158
0
  {
159
    //search corresponding inter CU cost
160
0
    for( int i = 0; i < m_numCuInSCIPU; i++ )
161
0
    {
162
0
      if( cu.lumaPos() == m_cuAreaInSCIPU[i].pos() && cu.lumaSize() == m_cuAreaInSCIPU[i].size() )
163
0
      {
164
0
        return m_cuCostInSCIPU[i];
165
0
      }
166
0
    }
167
0
  }
168
23.7k
  return COST_UNKNOWN;
169
23.7k
}
170
171
void IntraSearch::xEstimateLumaRdModeList(int& numModesForFullRD,
172
  static_vector<ModeInfo, FAST_UDI_MAX_RDMODE_NUM>& RdModeList,
173
  static_vector<ModeInfo, FAST_UDI_MAX_RDMODE_NUM>& HadModeList,
174
  static_vector<double, FAST_UDI_MAX_RDMODE_NUM>& CandCostList,
175
  static_vector<double, FAST_UDI_MAX_RDMODE_NUM>& CandHadList, CodingUnit& cu, bool testMip )
176
23.7k
{
177
23.7k
  PROFILER_SCOPE_AND_STAGE_EXT( 1, _TPROF, P_INTRA_EST_RD_CAND, cu.cs, CH_L );
178
23.7k
  const uint16_t intra_ctx_size = Ctx::IntraLumaMpmFlag.size() + Ctx::IntraLumaPlanarFlag.size() + Ctx::MultiRefLineIdx.size() + Ctx::ISPMode.size() + Ctx::MipFlag.size();
179
23.7k
  const TempCtx  ctxStartIntraCtx(m_CtxCache, SubCtx(CtxSet(Ctx::IntraLumaMpmFlag(), intra_ctx_size), m_CABACEstimator->getCtx()));
180
23.7k
  const double   sqrtLambdaForFirstPass = m_pcRdCost->getMotionLambda() * FRAC_BITS_SCALE;
181
23.7k
  const int numModesAvailable = NUM_LUMA_MODE; // total number of Intra modes
182
183
23.7k
  CHECK(numModesForFullRD >= numModesAvailable, "Too many modes for full RD search");
184
185
23.7k
  const SPS& sps     = *cu.cs->sps;
186
23.7k
  const bool fastMip = sps.MIP && m_pcEncCfg->m_useFastMIP;
187
188
  // this should always be true
189
23.7k
  CHECK( !cu.Y().valid(), "CU is not valid" );
190
191
23.7k
  const CompArea& area = cu.Y();
192
193
23.7k
  const UnitArea localUnitArea(area.chromaFormat, Area(0, 0, area.width, area.height));
194
23.7k
  if( testMip)
195
18.1k
  {
196
18.1k
    numModesForFullRD += fastMip ? numModesForFullRD - std::min( m_pcEncCfg->m_useFastMIP, numModesForFullRD )
197
18.1k
                                 : numModesForFullRD;
198
18.1k
    m_SortedPelUnitBufs->prepare( localUnitArea, numModesForFullRD + 1 );
199
18.1k
  }
200
5.54k
  else
201
5.54k
  {
202
5.54k
    m_SortedPelUnitBufs->prepare( localUnitArea, numModesForFullRD );
203
5.54k
  }
204
205
23.7k
  CPelBuf piOrg   = cu.cs->getOrgBuf(COMP_Y);
206
23.7k
  PelBuf piPred  = m_SortedPelUnitBufs->getTestBuf(COMP_Y);
207
208
23.7k
  DistParam distParam    = m_pcRdCost->setDistParam( piOrg, piPred, sps.bitDepths[ CH_L ], DF_HAD_2SAD); // Use HAD (SATD) cost
209
210
23.7k
  const int numHadCand = (testMip ? 2 : 1) * 3;
211
212
  //*** Derive (regular) candidates using Hadamard
213
23.7k
  cu.mipFlag = false;
214
23.7k
  cu.multiRefIdx = 0;
215
216
  //===== init pattern for luma prediction =====
217
23.7k
  initIntraPatternChType(cu, cu.Y(), true);
218
219
23.7k
  bool satdChecked[NUM_INTRA_MODE] = { false };
220
221
23.7k
  const unsigned* mpmLst = m_searchMpmLst;   // derived for this CU in estIntraPredLumaQT
222
223
23.7k
  const int decMsk = ( 1 << m_pcEncCfg->m_IntraEstDecBit ) - 1;
224
225
23.7k
  m_parentCandList.resize( 0 );
226
23.7k
  m_parentCandList.reserve( ( numModesAvailable >> m_pcEncCfg->m_IntraEstDecBit ) + 2 );
227
228
1.61M
  for( unsigned mode = 0; mode < numModesAvailable; mode++ )
229
1.59M
  {
230
    // Skip checking extended Angular modes in the first round of SATD
231
1.59M
    if( mode > DC_IDX && ( mode & decMsk ) )
232
1.16M
    {
233
1.16M
      continue;
234
1.16M
    }
235
236
427k
    m_parentCandList.push_back( ModeInfo( false, false, 0, NOT_INTRA_SUBPARTITIONS, mode ) );
237
427k
  }
238
   
239
94.9k
  for( int decDst = 1 << m_pcEncCfg->m_IntraEstDecBit; decDst > 0; decDst >>= 1 )
240
71.2k
  {
241
640k
    for( unsigned idx = 0; idx < m_parentCandList.size(); idx++ )
242
569k
    {
243
569k
      int modeParent = m_parentCandList[idx].modeId;
244
245
569k
      int off = decDst & decMsk;
246
569k
      int inc = decDst << 1;
247
248
569k
#if 1 // INTRA_AS_IN_VTM
249
569k
      if( off != 0 && ( modeParent <= ( DC_IDX + 1 ) || modeParent >= ( NUM_LUMA_MODE - 1 ) ) )
250
92.3k
      {
251
92.3k
        continue;
252
92.3k
      }
253
254
477k
#endif
255
1.00M
      for( int mode = modeParent - off; mode < modeParent + off + 1; mode += inc )
256
527k
      {
257
527k
        if( satdChecked[mode] || mode < 0 || mode >= NUM_LUMA_MODE )
258
2.50k
        {
259
2.50k
          continue;
260
2.50k
        }
261
262
524k
        cu.intraDir[0] = mode;
263
264
524k
        initPredIntraParams( cu, cu.Y(), sps );
265
524k
        distParam.cur.buf = piPred.buf = m_SortedPelUnitBufs->getTestBuf().Y().buf;
266
524k
        predIntraAng( COMP_Y, piPred, cu );
267
268
        // Use the min between SAD and HAD as the cost criterion
269
        // SAD is scaled by 2 to align with the scaling of HAD
270
524k
        Distortion minSadHad = distParam.distFunc( distParam );
271
272
524k
        uint64_t fracModeBits = xFracModeBitsIntraLuma( cu, mpmLst );
273
274
        //restore ctx
275
524k
        m_CABACEstimator->getCtx() = SubCtx( CtxSet( Ctx::IntraLumaMpmFlag(), intra_ctx_size ), ctxStartIntraCtx );
276
277
524k
        double cost = ( double ) minSadHad + ( double ) fracModeBits * sqrtLambdaForFirstPass;
278
524k
        DTRACE( g_trace_ctx, D_INTRA_COST, "IntraHAD: %u, %llu, %f (%d)\n", minSadHad, fracModeBits, cost, mode );
279
280
524k
        int insertPos = -1;
281
524k
        updateCandList( ModeInfo( false, false, 0, NOT_INTRA_SUBPARTITIONS, mode ), cost, RdModeList, CandCostList, numModesForFullRD, &insertPos );
282
524k
        updateCandList( ModeInfo( false, false, 0, NOT_INTRA_SUBPARTITIONS, mode ), ( double ) minSadHad, HadModeList, CandHadList, numHadCand );
283
524k
        m_SortedPelUnitBufs->insert( insertPos, ( int ) RdModeList.size() );
284
285
524k
        satdChecked[mode] = true;
286
524k
      }
287
477k
    }
288
289
71.2k
    m_parentCandList.resize( RdModeList.size() );
290
71.2k
    std::copy( RdModeList.cbegin(), RdModeList.cend(), m_parentCandList.begin() );
291
71.2k
  }
292
293
23.7k
  const bool isFirstLineOfCtu = (((cu.block(COMP_Y).y)&((cu.cs->sps)->CTUSize - 1)) == 0);
294
23.7k
  if( m_pcEncCfg->m_MRL && ! isFirstLineOfCtu )
295
14.3k
  {
296
14.3k
    cu.multiRefIdx = 1;
297
14.3k
    unsigned  multiRefMPM [NUM_MOST_PROBABLE_MODES];
298
14.3k
    CU::getIntraMPMs(cu, multiRefMPM);
299
300
43.1k
    for (int mRefNum = 1; mRefNum < MRL_NUM_REF_LINES; mRefNum++)
301
28.7k
    {
302
28.7k
      int multiRefIdx = MULTI_REF_LINE_IDX[mRefNum];
303
304
28.7k
      cu.multiRefIdx = multiRefIdx;
305
28.7k
      initIntraPatternChType(cu, cu.Y(), true);
306
307
172k
      for (int x = 1; x < NUM_MOST_PROBABLE_MODES; x++)
308
143k
      {
309
143k
        cu.intraDir[0] = multiRefMPM[x];
310
143k
        initPredIntraParams(cu, cu.Y(), sps);
311
143k
        distParam.cur.buf = piPred.buf = m_SortedPelUnitBufs->getTestBuf().Y().buf;
312
143k
        predIntraAng(COMP_Y, piPred, cu);
313
314
        // Use the min between SAD and SATD as the cost criterion
315
        // SAD is scaled by 2 to align with the scaling of HAD
316
143k
        Distortion minSadHad = distParam.distFunc(distParam);
317
318
        // NB xFracModeBitsIntra will not affect the mode for chroma that may have already been pre-estimated.
319
143k
        uint64_t fracModeBits = xFracModeBitsIntraLuma( cu, mpmLst );
320
321
        //restore ctx
322
143k
        m_CABACEstimator->getCtx() = SubCtx(CtxSet(Ctx::IntraLumaMpmFlag(), intra_ctx_size), ctxStartIntraCtx);
323
324
143k
        double cost = (double) minSadHad + (double) fracModeBits * sqrtLambdaForFirstPass;
325
//        DTRACE(g_trace_ctx, D_INTRA_COST, "IntraMRL: %u, %llu, %f (%d)\n", minSadHad, fracModeBits, cost, cu.intraDir[0]);
326
327
143k
        int insertPos = -1;
328
143k
        updateCandList( ModeInfo( false, false, multiRefIdx, NOT_INTRA_SUBPARTITIONS, cu.intraDir[0] ), cost, RdModeList,  CandCostList, numModesForFullRD, &insertPos );
329
143k
        updateCandList( ModeInfo( false, false, multiRefIdx, NOT_INTRA_SUBPARTITIONS, cu.intraDir[0] ), (double)minSadHad, HadModeList, CandHadList,  numHadCand );
330
143k
        m_SortedPelUnitBufs->insert(insertPos, (int)RdModeList.size());
331
143k
      }
332
28.7k
    }
333
14.3k
    cu.multiRefIdx = 0;
334
14.3k
  }
335
336
23.7k
  if (testMip)
337
18.1k
  {
338
18.1k
    cu.mipFlag = true;
339
18.1k
    cu.multiRefIdx = 0;
340
341
18.1k
    double mipHadCost[MAX_NUM_MIP_MODE] = { MAX_DOUBLE };
342
343
18.1k
    initIntraPatternChType(cu, cu.Y());
344
18.1k
    initIntraMip( cu );
345
346
18.1k
    const int transpOff    = getNumModesMip( cu.Y() );
347
18.1k
    const int numModesFull = (transpOff << 1);
348
238k
    for( uint32_t uiModeFull = 0; uiModeFull < numModesFull; uiModeFull++ )
349
219k
    {
350
219k
      const bool     isTransposed = (uiModeFull >= transpOff ? true : false);
351
219k
      const uint32_t uiMode       = (isTransposed ? uiModeFull - transpOff : uiModeFull);
352
353
219k
      cu.mipTransposedFlag = isTransposed;
354
219k
      cu.intraDir[CH_L] = uiMode;
355
219k
      distParam.cur.buf = piPred.buf = m_SortedPelUnitBufs->getTestBuf().Y().buf;
356
219k
      predIntraMip(piPred, cu);
357
358
      // Use the min between SAD and HAD as the cost criterion
359
      // SAD is scaled by 2 to align with the scaling of HAD
360
219k
      Distortion minSadHad = distParam.distFunc(distParam);
361
362
219k
      uint64_t fracModeBits = xFracModeBitsIntraLuma( cu, mpmLst );
363
364
      //restore ctx
365
219k
      m_CABACEstimator->getCtx() = SubCtx(CtxSet(Ctx::IntraLumaMpmFlag(), intra_ctx_size), ctxStartIntraCtx);
366
367
219k
      double cost = double(minSadHad) + double(fracModeBits) * sqrtLambdaForFirstPass;
368
219k
      mipHadCost[uiModeFull] = cost;
369
219k
      DTRACE(g_trace_ctx, D_INTRA_COST, "IntraMIP: %u, %llu, %f (%d)\n", minSadHad, fracModeBits, cost, uiModeFull);
370
371
219k
      int insertPos = -1;
372
219k
      updateCandList( ModeInfo( true, isTransposed, 0, NOT_INTRA_SUBPARTITIONS, cu.intraDir[0] ), cost, RdModeList,  CandCostList, numModesForFullRD+1, &insertPos );
373
219k
      updateCandList( ModeInfo( true, isTransposed, 0, NOT_INTRA_SUBPARTITIONS, cu.intraDir[0] ), 0.8*(double)minSadHad, HadModeList, CandHadList,  numHadCand );
374
219k
      m_SortedPelUnitBufs->insert(insertPos, (int)RdModeList.size());
375
219k
    }
376
377
18.1k
    const double thresholdHadCost = 1.0 + 1.4 / sqrt((double)(cu.lwidth()*cu.lheight()));
378
18.1k
    xReduceHadCandList(RdModeList, CandCostList, *m_SortedPelUnitBufs, numModesForFullRD, thresholdHadCost, mipHadCost, cu, fastMip);
379
18.1k
  }
380
381
23.7k
  if( m_pcEncCfg->m_bFastUDIUseMPMEnabled )
382
23.7k
  {
383
23.7k
    const int numMPMs = NUM_MOST_PROBABLE_MODES;
384
23.7k
    unsigned  intraMpms[numMPMs];
385
386
23.7k
    cu.multiRefIdx = 0;
387
388
23.7k
    const int numCand = CU::getIntraMPMs( cu, intraMpms );
389
23.7k
    ModeInfo mostProbableMode(false, false, 0, NOT_INTRA_SUBPARTITIONS, 0);
390
391
48.2k
    for( int j = 0; j < numCand; j++ )
392
24.5k
    {
393
24.5k
      bool mostProbableModeIncluded = false;
394
24.5k
      mostProbableMode.modeId = intraMpms[j];
395
396
124k
      for( int i = 0; i < numModesForFullRD; i++ )
397
100k
      {
398
100k
        mostProbableModeIncluded |= ( mostProbableMode == RdModeList[i] );
399
100k
      }
400
24.5k
      if( !mostProbableModeIncluded )
401
175
      {
402
175
        numModesForFullRD++;
403
175
        RdModeList.push_back( mostProbableMode );
404
175
        CandCostList.push_back(0);
405
175
      }
406
24.5k
    }
407
23.7k
  }
408
23.7k
}
409
410
bool IntraSearch::estIntraPredLumaQT(CodingUnit &cu, Partitioner &partitioner, double bestCost)
411
23.7k
{
412
23.7k
  CU::getIntraMPMs( cu, m_searchMpmLst );
413
23.7k
  m_searchMpmArea  = cu.Y();
414
23.7k
  m_searchMpmValid = true;
415
416
23.7k
  const bool validReturn = xEstIntraPredLumaQT( cu, partitioner, bestCost );
417
418
23.7k
  m_searchMpmValid = false;
419
23.7k
  return validReturn;
420
23.7k
}
421
422
bool IntraSearch::xEstIntraPredLumaQT(CodingUnit &cu, Partitioner &partitioner, double bestCost)
423
23.7k
{
424
23.7k
  CodingStructure       &cs           = *cu.cs;
425
23.7k
  const int             width         = partitioner.currArea().lwidth();
426
23.7k
  const int             height        = partitioner.currArea().lheight();
427
428
  //===== loop over partitions =====
429
430
23.7k
  const TempCtx ctxStart           ( m_CtxCache, m_CABACEstimator->getCtx() );
431
432
  // variables for saving fast intra modes scan results across multiple LFNST passes
433
23.7k
  double costInterCU = xFindInterCUCost( cu );
434
435
23.7k
  bool validReturn = false;
436
437
  //===== determine set of modes to be tested (using prediction signal only) =====
438
23.7k
  int numModesAvailable = NUM_LUMA_MODE; // total number of Intra modes
439
23.7k
  static_vector<ModeInfo, FAST_UDI_MAX_RDMODE_NUM> RdModeList;
440
23.7k
  static_vector<ModeInfo, FAST_UDI_MAX_RDMODE_NUM> HadModeList;
441
23.7k
  static_vector<double, FAST_UDI_MAX_RDMODE_NUM> CandCostList;
442
23.7k
  static_vector<double, FAST_UDI_MAX_RDMODE_NUM> CandHadList;
443
444
23.7k
  int numModesForFullRD = g_aucIntraModeNumFast_UseMPM_2D[Log2(width) - MIN_CU_LOG2][Log2(height) - MIN_CU_LOG2];
445
23.7k
  if (m_pcEncCfg->m_numIntraModesFullRD > 0)
446
0
    numModesForFullRD=m_pcEncCfg->m_numIntraModesFullRD;
447
448
#if INTRA_FULL_SEARCH
449
  numModesForFullRD = numModesAvailable;
450
#endif
451
23.7k
  const SPS& sps = *cu.cs->sps;
452
23.7k
  const bool mipAllowed = sps.MIP && cu.lwidth() <= sps.getMaxTbSize() && cu.lheight() <= sps.getMaxTbSize() && ((cu.lfnstIdx == 0) || allowLfnstWithMip(cu.lumaSize()));
453
23.7k
  const int SizeThr     = 8 >> std::max( 0, m_pcEncCfg->m_useFastMIP - 1 );
454
23.7k
  const bool testMip    = mipAllowed && ( cu.lwidth() <= ( SizeThr * cu.lheight() ) && cu.lheight() <= ( SizeThr * cu.lwidth() ) ) && ( cu.lwidth() <= MIP_MAX_WIDTH && cu.lheight() <= MIP_MAX_HEIGHT );
455
23.7k
  bool testISP = sps.ISP && CU::canUseISP(width, height, cu.cs->sps->getMaxTbSize());
456
23.7k
  if (testISP)
457
23.7k
  {
458
23.7k
    int numTotalPartsHor = (int)width >> floorLog2(CU::getISPSplitDim(width, height, TU_1D_VERT_SPLIT));
459
23.7k
    int numTotalPartsVer = (int)height >> floorLog2(CU::getISPSplitDim(width, height, TU_1D_HORZ_SPLIT));
460
23.7k
    m_ispTestedModes[0].init(numTotalPartsHor, numTotalPartsVer, 0);
461
    // the total number of subpartitions is modified to take into account the cases where LFNST cannot be combined with
462
    // ISP due to size restrictions
463
23.7k
    numTotalPartsHor = sps.LFNST && CU::canUseLfnstWithISP(cu.Y(), HOR_INTRA_SUBPARTITIONS) ? numTotalPartsHor : 0;
464
23.7k
    numTotalPartsVer = sps.LFNST && CU::canUseLfnstWithISP(cu.Y(), VER_INTRA_SUBPARTITIONS) ? numTotalPartsVer : 0;
465
71.2k
    for (int j = 1; j < NUM_LFNST_NUM_PER_SET; j++)
466
47.4k
    {
467
47.4k
      m_ispTestedModes[j].init(numTotalPartsHor, numTotalPartsVer, 0);
468
47.4k
    }
469
23.7k
    testISP = m_ispTestedModes[0].numTotalParts[0];
470
23.7k
  }
471
1
  else
472
1
  {
473
1
    m_ispTestedModes[0].init(0, 0, 0);
474
1
  }
475
476
23.7k
  xEstimateLumaRdModeList(numModesForFullRD, RdModeList, HadModeList, CandCostList, CandHadList, cu, testMip);
477
478
23.7k
  CHECK( (size_t)numModesForFullRD != RdModeList.size(), "Inconsistent state!" );
479
480
  // after this point, don't use numModesForFullRD
481
23.7k
  if( m_pcEncCfg->m_usePbIntraFast && !cs.slice->isIntra() && RdModeList.size() < numModesAvailable )
482
0
  {
483
0
    double pbintraRatio = m_pcEncCfg->m_usePbIntraFast == 1 && ( cs.area.lwidth() >= 16 && cs.area.lheight() >= 16 ) ? 1.2 : PBINTRA_RATIO;
484
485
0
    int maxSize = -1;
486
0
    ModeInfo bestMipMode;
487
0
    int bestMipIdx = -1;
488
0
    for( int idx = 0; idx < RdModeList.size(); idx++ )
489
0
    {
490
0
      if( RdModeList[idx].mipFlg )
491
0
      {
492
0
        bestMipMode = RdModeList[idx];
493
0
        bestMipIdx = idx;
494
0
        break;
495
0
      }
496
0
    }
497
0
    const int numHadCand = 3;
498
0
    for (int k = numHadCand - 1; k >= 0; k--)
499
0
    {
500
0
      if (CandHadList.size() < (k + 1) || CandHadList[k] > cs.interHad * pbintraRatio) { maxSize = k; }
501
0
    }
502
0
    if (maxSize > 0)
503
0
    {
504
0
      RdModeList.resize(std::min<size_t>(RdModeList.size(), maxSize));
505
0
      if( bestMipIdx >= 0 )
506
0
      {
507
0
        if( RdModeList.size() <= bestMipIdx )
508
0
        {
509
0
          RdModeList.push_back(bestMipMode);
510
0
          m_SortedPelUnitBufs->swap( maxSize, bestMipIdx );
511
0
        }
512
0
      }
513
0
    }
514
0
    if (maxSize == 0)
515
0
    {
516
0
      cs.dist = MAX_DISTORTION;
517
0
      cs.interHad = 0;
518
0
      return false;
519
0
    }
520
0
  }
521
522
  //===== check modes (using r-d costs) =====
523
23.7k
  ModeInfo bestPUMode;
524
525
23.7k
  CodingStructure *csTemp = m_pTempCS;
526
23.7k
  CodingStructure *csBest = m_pBestCS;
527
528
23.7k
  csTemp->slice   = csBest->slice   = cs.slice;
529
23.7k
  csTemp->picture = csBest->picture = cs.picture;
530
23.7k
  csTemp->compactResize( cu );
531
23.7k
  csBest->compactResize( cu );
532
23.7k
  csTemp->initStructData();
533
23.7k
  csBest->initStructData();
534
535
23.7k
  int   bestLfnstIdx  = 0;
536
23.7k
  const bool useBDPCM = cs.picture->useBDPCM;
537
23.7k
  int   NumBDPCMCand  = (useBDPCM && sps.BDPCM && CU::bdpcmAllowed(cu, ComponentID(partitioner.chType))) ? 2 : 0;
538
23.7k
  int   bestbdpcmMode = 0;
539
23.7k
  int   bestISP       = 0;
540
23.7k
  int   bestMrl       = 0;
541
23.7k
  bool  bestMip       = 0;
542
23.7k
  int   EndMode       = (int)RdModeList.size();
543
23.7k
  bool  useISPlfnst   = testISP && sps.LFNST;
544
23.7k
  bool  noLFNST_ts    = false;
545
23.7k
  double bestCostIsp[2] = { MAX_DOUBLE, MAX_DOUBLE };
546
23.7k
  bool disableMTS = false;
547
23.7k
  bool disableLFNST = false;
548
23.7k
  bool disableDCT2test = false;
549
23.7k
  if (m_pcEncCfg->m_FastIntraTools)
550
23.7k
  {
551
23.7k
    int speedIntra = 0;
552
23.7k
    xSpeedUpIntra(bestCost, EndMode, speedIntra, cu);
553
23.7k
    disableMTS = (speedIntra >> 2 ) & 0x1;
554
23.7k
    disableLFNST = (speedIntra >> 1) & 0x1;
555
23.7k
    disableDCT2test = speedIntra>>3;
556
23.7k
    if (disableLFNST)
557
21.1k
    {
558
21.1k
      noLFNST_ts = true;
559
21.1k
      useISPlfnst = false;
560
21.1k
    }
561
23.7k
    if (speedIntra & 0x1)
562
21.1k
    {
563
21.1k
      testISP = false;
564
21.1k
    }
565
23.7k
  }
566
567
128k
  for (int mode_cur = 0; mode_cur < EndMode + NumBDPCMCand; mode_cur++)
568
104k
  {
569
104k
    int mode = mode_cur;
570
104k
    if (mode_cur >= EndMode)
571
7.29k
    {
572
7.29k
      mode = mode_cur - EndMode ? -1 : -2;
573
7.29k
      testISP = false;
574
7.29k
    }
575
    // set CU/PU to luma prediction mode
576
104k
    ModeInfo testMode;
577
104k
    int noISP = 0;
578
104k
    int endISP = testISP ? 2 : 0;
579
104k
    bool noLFNST = false || noLFNST_ts;
580
104k
    if (mode && useISPlfnst)
581
8.64k
    {
582
8.64k
      noLFNST |= (bestCostIsp[0] > (bestCostIsp[1] * 1.4));
583
8.64k
      if (mode > 2)
584
2.30k
      {
585
2.30k
        endISP = 0;
586
2.30k
        testISP = false;
587
2.30k
      }
588
8.64k
    }
589
104k
    if (testISP)
590
5.48k
    {
591
5.48k
      xSpeedUpISP(1, testISP, mode, noISP, endISP, cu, RdModeList, bestPUMode, bestISP, bestLfnstIdx);
592
5.48k
    }
593
104k
    int startISP = 0;
594
104k
    if (disableDCT2test && mode && bestISP)
595
0
    {
596
0
      startISP = endISP ? 1 : 0;
597
0
    }
598
216k
    for (int ispM = startISP; ispM <= endISP; ispM++)
599
112k
    {
600
112k
      if (ispM && (ispM == noISP))
601
55
      {
602
55
        continue;
603
55
      }
604
605
112k
      if (mode < 0)
606
7.29k
      {
607
7.29k
        cu.bdpcmM[CH_L] = -mode;
608
7.29k
        testMode = ModeInfo(false, false, 0, NOT_INTRA_SUBPARTITIONS, cu.bdpcmM[CH_L] == 2 ? VER_IDX : HOR_IDX);
609
7.29k
      }
610
105k
      else
611
105k
      {
612
105k
        testMode = RdModeList[mode];
613
105k
        cu.bdpcmM[CH_L] = 0;
614
105k
      }
615
616
112k
      cu.ispMode = ispM;
617
112k
      cu.mipFlag = testMode.mipFlg;
618
112k
      cu.mipTransposedFlag = testMode.mipTrFlg;
619
112k
      cu.multiRefIdx = testMode.mRefId;
620
112k
      cu.intraDir[CH_L] = testMode.modeId;
621
112k
      if (cu.ispMode && xSpeedUpISP(0, testISP, mode, noISP, endISP, cu, RdModeList, bestPUMode, bestISP, 0) )
622
2.87k
      {
623
2.87k
        continue;
624
2.87k
      }
625
109k
      if (m_pcEncCfg->m_FastIntraTools && (cu.ispMode || sps.LFNST || sps.MTS))
626
109k
      {
627
109k
        m_ispTestedModes[0].intraWasTested = true;
628
109k
      }
629
109k
      CHECK(cu.mipFlag && cu.multiRefIdx, "Error: combination of MIP and MRL not supported");
630
109k
      CHECK(cu.multiRefIdx && (cu.intraDir[0] == PLANAR_IDX), "Error: combination of MRL and Planar mode not supported");
631
109k
      CHECK(cu.ispMode && cu.mipFlag, "Error: combination of ISP and MIP not supported");
632
109k
      CHECK(cu.ispMode && cu.multiRefIdx, "Error: combination of ISP and MRL not supported");
633
634
      // determine residual for partition
635
109k
      cs.initSubStructure(*csTemp, partitioner.chType, cs.area, true);
636
109k
      int doISP = (((cu.ispMode == 0) && noLFNST) || (useISPlfnst && mode && cu.ispMode && (bestLfnstIdx == 0)) || disableLFNST) ? -mode : mode;
637
109k
      xIntraCodingLumaQT(*csTemp, partitioner, m_SortedPelUnitBufs->getBufFromSortedList(mode), bestCost, doISP, disableMTS);
638
639
109k
      DTRACE(g_trace_ctx, D_INTRA_COST, "IntraCost T [x=%d,y=%d,w=%d,h=%d] %f (%d,%d,%d,%d,%d,%d) \n", cu.blocks[0].x,
640
109k
        cu.blocks[0].y, width, height, csTemp->cost, testMode.modeId, testMode.ispMod,
641
109k
        cu.multiRefIdx, cu.mipFlag, cu.lfnstIdx, cu.mtsFlag);
642
643
109k
      if (cu.ispMode && !csTemp->cus[0]->firstTU->cbf[COMP_Y])
644
1.74k
      {
645
1.74k
        csTemp->cost = MAX_DOUBLE;
646
1.74k
        csTemp->costDbOffset = 0;
647
1.74k
      }
648
109k
      if (useISPlfnst)
649
16.3k
      {
650
16.3k
        int n = (cu.ispMode == 0) ? 0 : 1;
651
16.3k
        bestCostIsp[n] = csTemp->cost < bestCostIsp[n] ? csTemp->cost : bestCostIsp[n];
652
16.3k
      }
653
654
      // check r-d cost
655
109k
      if (csTemp->cost < csBest->cost)
656
30.6k
      {
657
30.6k
        validReturn   = true;
658
30.6k
        std::swap(csTemp, csBest);
659
30.6k
        bestPUMode    = testMode;
660
30.6k
        bestLfnstIdx  = csBest->cus[0]->lfnstIdx;
661
30.6k
        bestISP       = csBest->cus[0]->ispMode;
662
30.6k
        bestMip       = csBest->cus[0]->mipFlag;
663
30.6k
        bestMrl       = csBest->cus[0]->multiRefIdx;
664
30.6k
        bestbdpcmMode = cu.bdpcmM[CH_L];
665
30.6k
        m_ispTestedModes[bestLfnstIdx].bestSplitSoFar = ISPType(bestISP);
666
30.6k
        if (csBest->cost < bestCost)
667
30.6k
        {
668
30.6k
          bestCost = csBest->cost;
669
30.6k
        }
670
30.6k
        if ((csBest->getTU(partitioner.chType)->mtsIdx[COMP_Y] == MTS_SKIP) && ( floorLog2(csBest->getTU(partitioner.chType)->blocks[COMP_Y].area()) >= 6 ))
671
4.46k
        {
672
4.46k
          noLFNST_ts = 1;
673
4.46k
        }
674
30.6k
      }
675
676
      // reset context models
677
109k
      m_CABACEstimator->getCtx() = ctxStart;
678
679
109k
      csTemp->releaseIntermediateData();
680
681
109k
      if (m_pcEncCfg->m_fastLocalDualTreeMode && CU::isConsIntra(cu) && !cu.slice->isIntra() && csBest->cost != MAX_DOUBLE && costInterCU != COST_UNKNOWN && mode >= 0)
682
0
      {
683
0
        if( (m_pcEncCfg->m_fastLocalDualTreeMode == 2) || (csBest->cost > costInterCU * 1.5))
684
0
        {
685
          //Note: only try one intra mode, which is especially useful to reduce EncT for LDB case (around 4%)
686
0
          EndMode = 0;
687
0
          break;
688
0
        }
689
0
      }
690
109k
    }
691
104k
  } // Mode loop
692
693
23.7k
  if (m_pcEncCfg->m_FastIntraTools && (sps.ISP|| sps.LFNST || sps.MTS))
694
23.7k
  {
695
23.7k
    int bestMode = csBest->getTU(partitioner.chType)->mtsIdx[COMP_Y] ? 4 : 0;
696
23.7k
    bestMode |= bestLfnstIdx ? 2 : 0;
697
23.7k
    bestMode |= bestISP ? 1 : 0;
698
23.7k
    m_ispTestedModes[0].bestIntraMode = bestMode;
699
23.7k
  }
700
23.7k
  cu.ispMode = bestISP;
701
23.7k
  if( validReturn )
702
23.7k
  {
703
23.7k
    cs.useSubStructure( *csBest, partitioner.chType, TREE_D, cu.singleChan( CH_L ), true );
704
705
    //=== update PU data ====
706
23.7k
    cu.lfnstIdx           = bestLfnstIdx;
707
23.7k
    cu.mipTransposedFlag  = bestPUMode.mipTrFlg;
708
23.7k
    cu.intraDir[CH_L]     = bestPUMode.modeId;
709
23.7k
    cu.bdpcmM[CH_L]       = bestbdpcmMode;
710
23.7k
    cu.mipFlag            = bestMip;
711
23.7k
    cu.multiRefIdx        = bestMrl;
712
23.7k
  }
713
0
  else
714
0
  {
715
0
    THROW("fix this");
716
0
  }
717
718
23.7k
  csBest->releaseIntermediateData();
719
720
23.7k
  return validReturn;
721
23.7k
}
722
723
void IntraSearch::estIntraPredChromaQT( CodingUnit& cu, Partitioner& partitioner, const double maxCostAllowed )
724
54.0k
{
725
54.0k
  PROFILER_SCOPE_AND_STAGE_EXT( 0, _TPROF, P_INTRA_CHROMA, cu.cs, CH_C );
726
54.0k
  const TempCtx ctxStart( m_CtxCache, m_CABACEstimator->getCtx() );
727
54.0k
  CodingStructure &cs   = *cu.cs;
728
54.0k
  bool lumaUsesISP      = !CU::isSepTree(cu) && cu.ispMode;
729
54.0k
  PartSplit ispType     = lumaUsesISP ? CU::getISPType(cu, COMP_Y) : TU_NO_ISP;
730
54.0k
  double bestCostSoFar  = maxCostAllowed;
731
54.0k
  const uint32_t numberValidComponents = getNumberValidComponents( cu.chromaFormat );
732
54.0k
  const bool useBDPCM   = cs.picture->useBDPCM;
733
734
54.0k
  uint32_t   uiBestMode = 0;
735
54.0k
  Distortion uiBestDist = 0;
736
54.0k
  double     dBestCost  = MAX_DOUBLE;
737
738
  //----- init mode list ----
739
54.0k
  {
740
54.0k
    uint32_t  uiMinMode = 0;
741
54.0k
    uint32_t  uiMaxMode = NUM_CHROMA_MODE;
742
743
54.0k
    const int reducedModeNumber = uiMaxMode >> (m_pcEncCfg->m_reduceIntraChromaModesFullRD ? 1 : 2);
744
    //----- check chroma modes -----
745
54.0k
    uint32_t chromaCandModes[ NUM_CHROMA_MODE ];
746
54.0k
    CU::getIntraChromaCandModes( cu, chromaCandModes );
747
748
    // create a temporary CS
749
54.0k
    CodingStructure &saveCS = *m_pSaveCS[0];
750
54.0k
    saveCS.pcv      = cs.pcv;
751
54.0k
    saveCS.picture  = cs.picture;
752
54.0k
    saveCS.area.repositionTo( cs.area );
753
54.0k
    saveCS.clearTUs();
754
755
54.0k
    if( !CU::isSepTree(cu) && cu.ispMode )
756
0
    {
757
0
      saveCS.clearCUs();
758
0
    }
759
760
54.0k
    if( CU::isSepTree(cu) )
761
54.0k
    {
762
54.0k
      if( partitioner.canSplit( TU_MAX_TR_SPLIT, cs ) )
763
0
      {
764
0
        partitioner.splitCurrArea( TU_MAX_TR_SPLIT, cs );
765
766
0
        do
767
0
        {
768
0
          cs.addTU( CS::getArea( cs, partitioner.currArea(), partitioner.chType, partitioner.treeType ), partitioner.chType, &cu ).depth = partitioner.currTrDepth;
769
0
        } while( partitioner.nextPart( cs ) );
770
771
0
        partitioner.exitCurrSplit();
772
0
      }
773
54.0k
      else
774
54.0k
        cs.addTU( CS::getArea( cs, partitioner.currArea(), partitioner.chType, partitioner.treeType ), partitioner.chType, &cu );
775
54.0k
    }
776
777
    // create a store for the TUs
778
54.0k
    std::vector<TransformUnit*> orgTUs;
779
54.0k
    for( const auto &ptu : cs.tus )
780
54.0k
    {
781
      // for split TUs in HEVC, add the TUs without Chroma parts for correct setting of Cbfs
782
54.0k
      if (lumaUsesISP || cu.contains(*ptu, CH_C))
783
54.0k
      {
784
54.0k
        saveCS.addTU( *ptu, partitioner.chType, nullptr );
785
54.0k
        orgTUs.push_back( ptu );
786
54.0k
      }
787
54.0k
    }
788
789
    // SATD pre-selecting.
790
54.0k
    int     satdModeList  [NUM_CHROMA_MODE] = { 0 };
791
54.0k
    int64_t satdSortedCost[NUM_CHROMA_MODE] = { 0 };
792
54.0k
    bool    modeDisable[NUM_INTRA_MODE + 1] = { false }; // use intra mode idx to check whether enable
793
794
54.0k
    CodingStructure& cs = *(cu.cs);
795
54.0k
    CompArea areaCb = cu.Cb();
796
54.0k
    CompArea areaCr = cu.Cr();
797
54.0k
    CPelBuf orgCb  = cs.getOrgBuf (COMP_Cb);
798
54.0k
    PelBuf predCb  = cs.getPredBuf(COMP_Cb);
799
54.0k
    CPelBuf orgCr  = cs.getOrgBuf (COMP_Cr);
800
54.0k
    PelBuf predCr  = cs.getPredBuf(COMP_Cr);
801
802
54.0k
    DistParam distParamSadCb  = m_pcRdCost->setDistParam( orgCb, predCb, cu.cs->sps->bitDepths[ CH_C ], DF_SAD);
803
54.0k
    DistParam distParamSatdCb = m_pcRdCost->setDistParam( orgCb, predCb, cu.cs->sps->bitDepths[ CH_C ], DF_HAD);
804
54.0k
    DistParam distParamSadCr  = m_pcRdCost->setDistParam( orgCr, predCr, cu.cs->sps->bitDepths[ CH_C ], DF_SAD);
805
54.0k
    DistParam distParamSatdCr = m_pcRdCost->setDistParam( orgCr, predCr, cu.cs->sps->bitDepths[ CH_C ], DF_HAD);
806
807
54.0k
    cu.intraDir[1] = MDLM_L_IDX; // temporary assigned, just to indicate this is a MDLM mode. for luma down-sampling operation.
808
809
54.0k
    initIntraPatternChType(cu, cu.Cb());
810
54.0k
    initIntraPatternChType(cu, cu.Cr());
811
54.0k
    loadLMLumaRecPels(cu, cu.Cb());
812
813
486k
    for (int idx = uiMinMode; idx < uiMaxMode; idx++)
814
432k
    {
815
432k
      int mode = chromaCandModes[idx];
816
432k
      satdModeList[idx] = mode;
817
432k
      if (CU::isLMCMode(mode) && ( !CU::isLMCModeEnabled(cu, mode) || cu.slice->lmChromaCheckDisable ) )
818
47.1k
      {
819
47.1k
        continue;
820
47.1k
      }
821
385k
      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
822
94.2k
      {
823
94.2k
        continue;
824
94.2k
      }
825
826
291k
      cu.intraDir[1]    = mode; // temporary assigned, for SATD checking.
827
828
291k
      const bool isLMCMode = CU::isLMCMode(mode);
829
291k
      if( isLMCMode )
830
76.6k
      {
831
76.6k
        predIntraChromaLM(COMP_Cb, predCb, cu, areaCb, mode);
832
76.6k
      }
833
214k
      else
834
214k
      {
835
214k
        initPredIntraParams(cu, cu.Cb(), *cs.sps);
836
214k
        predIntraAng(COMP_Cb, predCb, cu);
837
214k
      }
838
291k
      int64_t sadCb = distParamSadCb.distFunc(distParamSadCb) * 2;
839
291k
      int64_t satdCb = distParamSatdCb.distFunc(distParamSatdCb);
840
291k
      int64_t sad = std::min(sadCb, satdCb);
841
842
291k
      if( isLMCMode )
843
76.6k
      {
844
76.6k
        predIntraChromaLM(COMP_Cr, predCr, cu, areaCr, mode);
845
76.6k
      }
846
214k
      else
847
214k
      {
848
214k
        initPredIntraParams(cu, cu.Cr(), *cs.sps);
849
214k
        predIntraAng(COMP_Cr, predCr, cu);
850
214k
      }
851
291k
      int64_t sadCr = distParamSadCr.distFunc(distParamSadCr) * 2;
852
291k
      int64_t satdCr = distParamSatdCr.distFunc(distParamSatdCr);
853
291k
      sad += std::min(sadCr, satdCr);
854
291k
      satdSortedCost[idx] = sad;
855
291k
    }
856
857
    // sort the mode based on the cost from small to large.
858
486k
    for (int i = uiMinMode; i <= uiMaxMode - 1; i++)
859
432k
    {
860
1.94M
      for (int j = i + 1; j <= uiMaxMode - 1; j++)
861
1.51M
      {
862
1.51M
        if (satdSortedCost[j] < satdSortedCost[i])
863
93.0k
        {
864
93.0k
          std::swap( satdModeList[i],   satdModeList[j]);
865
93.0k
          std::swap( satdSortedCost[i], satdSortedCost[j]);
866
93.0k
        }
867
1.51M
      }
868
432k
    }
869
870
270k
    for (int i = 0; i < reducedModeNumber; i++)
871
216k
    {
872
216k
      modeDisable[satdModeList[uiMaxMode - 1 - i]] = true; // disable the last reducedModeNumber modes
873
216k
    }
874
875
54.0k
    int bestLfnstIdx = 0;
876
    // save the dist
877
54.0k
    Distortion baseDist = cs.dist;
878
54.0k
    int32_t bestbdpcmMode = 0;
879
54.0k
    uint32_t numbdpcmModes = ( useBDPCM && CU::bdpcmAllowed(cu, COMP_Cb)
880
36.5k
        && ((partitioner.chType == CH_C) || (cu.ispMode == 0 && cu.lfnstIdx == 0 && cu.firstTU->mtsIdx[COMP_Y] == MTS_SKIP))) ? 2 : 0;
881
559k
    for (int mode_cur = uiMinMode; mode_cur < (int)(uiMaxMode + numbdpcmModes); mode_cur++)
882
505k
    {
883
505k
      int mode = mode_cur;
884
505k
      if (mode_cur >= uiMaxMode)
885
73.1k
      {
886
73.1k
        mode = mode_cur > uiMaxMode ? -1 : -2; //set bdpcm mode
887
73.1k
        if ((mode == -1) && (saveCS.tus[0]->mtsIdx[COMP_Cb] != MTS_SKIP) && (saveCS.tus[0]->mtsIdx[COMP_Cr] != MTS_SKIP))
888
36.5k
        {
889
36.5k
          continue;
890
36.5k
        }
891
73.1k
      }
892
469k
      int chromaIntraMode;
893
469k
      if (mode < 0)
894
36.5k
      {
895
36.5k
        cu.bdpcmM[CH_C] = -mode;
896
36.5k
        chromaIntraMode = cu.bdpcmM[CH_C] == 2 ? chromaCandModes[1] : chromaCandModes[2];
897
36.5k
      }
898
432k
      else
899
432k
      {
900
432k
        cu.bdpcmM[CH_C] = 0;
901
432k
        chromaIntraMode = chromaCandModes[mode];
902
432k
        if (CU::isLMCMode(chromaIntraMode) && ( !CU::isLMCModeEnabled(cu, chromaIntraMode) || cu.slice->lmChromaCheckDisable ) )
903
47.1k
        {
904
47.1k
          continue;
905
47.1k
        }
906
385k
        if (modeDisable[chromaIntraMode] && CU::isLMCModeEnabled(cu, chromaIntraMode)) // when CCLM is disable, then MDLM is disable. not use satd checking
907
153k
        {
908
153k
          continue;
909
153k
        }
910
385k
      }
911
268k
      cs.dist = baseDist;
912
      //----- restore context models -----
913
268k
      m_CABACEstimator->getCtx() = ctxStart;
914
915
      //----- chroma coding -----
916
268k
      cu.intraDir[1] = chromaIntraMode;
917
268k
      m_ispTestedModes[0].IspType = ispType;
918
268k
      m_ispTestedModes[0].subTuCounter = -1;
919
268k
      xIntraChromaCodingQT( cs, partitioner );
920
268k
      if (lumaUsesISP && cs.dist == MAX_UINT)
921
0
      {
922
0
        continue;
923
0
      }
924
925
268k
      if (cs.sps->transformSkip)
926
268k
      {
927
268k
        m_CABACEstimator->getCtx() = ctxStart;
928
268k
      }
929
268k
      m_ispTestedModes[0].IspType = ispType;
930
268k
      m_ispTestedModes[0].subTuCounter = -1;
931
268k
      uint64_t fracBits   = xGetIntraFracBitsQT( cs, partitioner, false );
932
268k
      Distortion uiDist = cs.dist;
933
268k
      double    dCost   = m_pcRdCost->calcRdCost( fracBits, uiDist - baseDist );
934
935
      //----- compare -----
936
268k
      if( dCost < dBestCost )
937
97.5k
      {
938
97.5k
        if (lumaUsesISP && (dCost < bestCostSoFar))
939
0
        {
940
0
          bestCostSoFar = dCost;
941
0
        }
942
292k
        for( uint32_t i = getFirstComponentOfChannel( CH_C ); i < numberValidComponents; i++ )
943
195k
        {
944
195k
          const CompArea& area = cu.blocks[i];
945
195k
          saveCS.getRecoBuf     ( area ).copyFrom( cs.getRecoBuf   ( area ) );
946
195k
          cs.picture->getRecoBuf( area ).copyFrom( cs.getRecoBuf   ( area ) );
947
390k
          for( uint32_t j = 0; j < saveCS.tus.size(); j++ )
948
195k
          {
949
195k
            saveCS.tus[j]->copyComponentFrom( *orgTUs[j], area.compID );
950
195k
          }
951
195k
        }
952
97.5k
        dBestCost    = dCost;
953
97.5k
        uiBestDist   = uiDist;
954
97.5k
        uiBestMode   = chromaIntraMode;
955
97.5k
        bestLfnstIdx = cu.lfnstIdx;
956
97.5k
        bestbdpcmMode = cu.bdpcmM[CH_C];
957
958
97.5k
      }
959
268k
    }
960
54.0k
    cu.lfnstIdx = bestLfnstIdx;
961
54.0k
    cu.bdpcmM[CH_C]= bestbdpcmMode;
962
963
162k
    for( uint32_t i = getFirstComponentOfChannel( CH_C ); i < numberValidComponents; i++ )
964
108k
    {
965
108k
      const CompArea& area = cu.blocks[i];
966
967
108k
      cs.getRecoBuf         ( area ).copyFrom( saveCS.getRecoBuf( area ) );
968
108k
      cs.picture->getRecoBuf( area ).copyFrom( cs.getRecoBuf    ( area ) );
969
970
216k
      for( uint32_t j = 0; j < saveCS.tus.size(); j++ )
971
108k
      {
972
108k
        orgTUs[ j ]->copyComponentFrom( *saveCS.tus[ j ], area.compID );
973
108k
      }
974
108k
    }
975
54.0k
  }
976
54.0k
  cu.intraDir[1] = uiBestMode;
977
54.0k
  cs.dist        = uiBestDist;
978
979
  //----- restore context models -----
980
54.0k
  m_CABACEstimator->getCtx() = ctxStart;
981
54.0k
  if (lumaUsesISP && bestCostSoFar >= maxCostAllowed)
982
0
  {
983
0
    cu.ispMode = 0;
984
0
  }
985
54.0k
}
986
987
void IntraSearch::saveCuAreaCostInSCIPU( Area area, double cost )
988
0
{
989
0
  if( m_numCuInSCIPU < NUM_INTER_CU_INFO_SAVE )
990
0
  {
991
0
    m_cuAreaInSCIPU[m_numCuInSCIPU] = area;
992
0
    m_cuCostInSCIPU[m_numCuInSCIPU] = cost;
993
0
    m_numCuInSCIPU++;
994
0
  }
995
0
}
996
997
void IntraSearch::initCuAreaCostInSCIPU()
998
0
{
999
0
  for( int i = 0; i < NUM_INTER_CU_INFO_SAVE; i++ )
1000
0
  {
1001
0
    m_cuAreaInSCIPU[i] = Area();
1002
0
    m_cuCostInSCIPU[i] = 0;
1003
0
  }
1004
0
  m_numCuInSCIPU = 0;
1005
0
}
1006
// -------------------------------------------------------------------------------------------------------------------
1007
// Intra search
1008
// -------------------------------------------------------------------------------------------------------------------
1009
1010
void IntraSearch::xEncIntraHeader( CodingStructure &cs, Partitioner &partitioner, const bool luma )
1011
445k
{
1012
445k
  CodingUnit &cu = *cs.getCU( partitioner.chType, partitioner.treeType );
1013
1014
445k
  if (luma)
1015
177k
  {
1016
177k
    bool isFirst = cu.ispMode ? m_ispTestedModes[0].subTuCounter == 0 : partitioner.currArea().lumaPos() == cs.area.lumaPos();
1017
1018
    // CU header
1019
177k
    if( isFirst )
1020
173k
    {
1021
173k
      if ((!cs.slice->isIntra() || cs.slice->sps->IBC || cs.slice->sps->PLT) && cu.Y().valid())
1022
173k
      {
1023
173k
        m_CABACEstimator->pred_mode   ( cu );
1024
173k
      }
1025
173k
      m_CABACEstimator->bdpcm_mode  ( cu, ComponentID(partitioner.chType) );
1026
173k
    }
1027
1028
    // luma prediction mode
1029
177k
    if (isFirst)
1030
173k
    {
1031
173k
      if ( !cu.Y().valid())
1032
0
      {
1033
0
        m_CABACEstimator->pred_mode( cu );
1034
0
      }
1035
173k
      const bool searchedCu = m_searchMpmValid && m_searchMpmArea == cu.Y();
1036
173k
#if defined( _DEBUG )
1037
173k
      if( searchedCu )
1038
173k
      {
1039
173k
        unsigned mpmLst[NUM_MOST_PROBABLE_MODES];
1040
173k
        CU::getIntraMPMs( cu, mpmLst );
1041
173k
        CHECK( !std::equal( mpmLst, mpmLst + NUM_MOST_PROBABLE_MODES, m_searchMpmLst ), "MPM list of the searched CU is out of date" );
1042
173k
      }
1043
173k
#endif
1044
173k
      m_CABACEstimator->intra_luma_pred_mode( cu, searchedCu ? m_searchMpmLst : nullptr );
1045
173k
    }
1046
177k
  }
1047
268k
  else //  if (chroma)
1048
268k
  {
1049
268k
    bool isFirst = partitioner.currArea().Cb().valid() && partitioner.currArea().chromaPos() == cs.area.chromaPos();
1050
1051
268k
    if( isFirst )
1052
268k
    {
1053
268k
      m_CABACEstimator->bdpcm_mode(cu, ComponentID(CH_C));
1054
268k
      m_CABACEstimator->intra_chroma_pred_mode(  cu );
1055
268k
    }
1056
268k
  }
1057
445k
}
1058
1059
void IntraSearch::xEncSubdivCbfQT( CodingStructure &cs, Partitioner &partitioner, const bool luma )
1060
445k
{
1061
445k
  const UnitArea& currArea = partitioner.currArea();
1062
445k
  int subTuCounter = m_ispTestedModes[0].subTuCounter;
1063
445k
  TransformUnit  &currTU   = *cs.getTU(currArea.blocks[partitioner.chType], partitioner.chType, subTuCounter);
1064
445k
  CodingUnit     &currCU   = *currTU.cu;
1065
445k
  const uint32_t currDepth = partitioner.currTrDepth;
1066
445k
  const bool  subdiv = currTU.depth > currDepth;
1067
445k
  ComponentID compID = partitioner.chType == CH_L ? COMP_Y : COMP_Cb;
1068
1069
445k
  if (!luma)
1070
268k
  {
1071
268k
    const bool chromaCbfISP = currArea.blocks[COMP_Cb].valid() && currCU.ispMode && !subdiv;
1072
268k
    if (!currCU.ispMode || chromaCbfISP)
1073
268k
    {
1074
268k
      const uint32_t numberValidComponents = getNumberValidComponents(currArea.chromaFormat);
1075
268k
      const uint32_t cbfDepth = (chromaCbfISP ? currDepth - 1 : currDepth);
1076
1077
805k
      for (uint32_t ch = COMP_Cb; ch < numberValidComponents; ch++)
1078
536k
      {
1079
536k
        const ComponentID compID = ComponentID(ch);
1080
536k
        if (currDepth == 0 || TU::getCbfAtDepth(currTU, compID, currDepth - 1) || chromaCbfISP)
1081
536k
        {
1082
536k
          const bool prevCbf = (compID == COMP_Cr ? TU::getCbfAtDepth(currTU, COMP_Cb, currDepth) : false);
1083
536k
          m_CABACEstimator->cbf_comp(currCU, TU::getCbfAtDepth(currTU, compID, currDepth), currArea.blocks[compID], cbfDepth, prevCbf);
1084
536k
        }
1085
536k
      }
1086
268k
    }
1087
268k
  }
1088
1089
445k
  if (subdiv)
1090
0
  {
1091
0
    if (partitioner.canSplit(TU_MAX_TR_SPLIT, cs))
1092
0
    {
1093
0
      partitioner.splitCurrArea(TU_MAX_TR_SPLIT, cs);
1094
0
    }
1095
0
    else if (currCU.ispMode && isLuma(compID))
1096
0
    {
1097
0
      partitioner.splitCurrArea(m_ispTestedModes[0].IspType, cs);
1098
0
    }
1099
0
    else
1100
0
      THROW("Cannot perform an implicit split!");
1101
1102
0
    do
1103
0
    {
1104
0
      xEncSubdivCbfQT(cs, partitioner, luma);   //?
1105
0
      subTuCounter += subTuCounter != -1 ? 1 : 0;
1106
0
    } while (partitioner.nextPart(cs));
1107
1108
0
    partitioner.exitCurrSplit();
1109
0
  }
1110
445k
  else
1111
445k
  {
1112
    //===== Cbfs =====
1113
445k
    if (luma)
1114
177k
    {
1115
177k
      bool previousCbf = false;
1116
177k
      bool lastCbfIsInferred = false;
1117
177k
      if (m_ispTestedModes[0].IspType != TU_NO_ISP)
1118
14.2k
      {
1119
14.2k
        bool     rootCbfSoFar = false;
1120
14.2k
        uint32_t nTus = currCU.ispMode == HOR_INTRA_SUBPARTITIONS ? currCU.lheight() >> floorLog2(currTU.lheight())
1121
14.2k
          : currCU.lwidth() >> floorLog2(currTU.lwidth());
1122
14.2k
        if (subTuCounter == nTus - 1)
1123
1.39k
        {
1124
1.39k
          TransformUnit* tuPointer = currCU.firstTU;
1125
5.57k
          for (int tuIdx = 0; tuIdx < nTus - 1; tuIdx++)
1126
4.17k
          {
1127
4.17k
            rootCbfSoFar |= TU::getCbfAtDepth(*tuPointer, COMP_Y, currDepth);
1128
4.17k
            tuPointer = tuPointer->next;
1129
4.17k
          }
1130
1.39k
          if (!rootCbfSoFar)
1131
0
          {
1132
0
            lastCbfIsInferred = true;
1133
0
          }
1134
1.39k
        }
1135
14.2k
        if (!lastCbfIsInferred)
1136
14.2k
        {
1137
14.2k
          previousCbf = TU::getPrevTuCbfAtDepth(currTU, COMP_Y, partitioner.currTrDepth);
1138
14.2k
        }
1139
14.2k
      }
1140
177k
      if (!lastCbfIsInferred)
1141
177k
      {
1142
177k
        m_CABACEstimator->cbf_comp(currCU, TU::getCbfAtDepth(currTU, COMP_Y, currDepth), currTU.Y(), currTU.depth, previousCbf, currCU.ispMode);
1143
177k
      }
1144
177k
    }
1145
445k
  }
1146
445k
}
1147
void IntraSearch::xEncCoeffQT(CodingStructure& cs, Partitioner& partitioner, const ComponentID compID, CUCtx* cuCtx, const int subTuIdx, const PartSplit ispType)
1148
714k
{
1149
714k
  const UnitArea& currArea  = partitioner.currArea();
1150
1151
714k
  int subTuCounter          = m_ispTestedModes[0].subTuCounter;
1152
714k
  TransformUnit& currTU     = *cs.getTU(currArea.blocks[partitioner.chType], partitioner.chType, subTuCounter);
1153
714k
  uint32_t   currDepth      = partitioner.currTrDepth;
1154
714k
  const bool subdiv         = currTU.depth > currDepth;
1155
1156
714k
  if (subdiv)
1157
0
  {
1158
0
    if (partitioner.canSplit(TU_MAX_TR_SPLIT, cs))
1159
0
    {
1160
0
      partitioner.splitCurrArea(TU_MAX_TR_SPLIT, cs);
1161
0
    }
1162
0
    else if (currTU.cu->ispMode)
1163
0
    {
1164
0
      partitioner.splitCurrArea(m_ispTestedModes[0].IspType, cs);
1165
0
    }
1166
0
    else
1167
0
      THROW("Implicit TU split not available!");
1168
1169
0
    do
1170
0
    {
1171
0
      xEncCoeffQT(cs, partitioner, compID, cuCtx, subTuCounter, m_ispTestedModes[0].IspType);
1172
0
      subTuCounter += subTuCounter != -1 ? 1 : 0;
1173
0
    } while( partitioner.nextPart( cs ) );
1174
1175
0
    partitioner.exitCurrSplit();
1176
0
  }
1177
714k
  else
1178
1179
714k
  if( currArea.blocks[compID].valid() )
1180
714k
  {
1181
714k
    if( compID == COMP_Cr )
1182
268k
    {
1183
268k
      const int cbfMask = ( TU::getCbf( currTU, COMP_Cb ) ? 2 : 0 ) + ( TU::getCbf( currTU, COMP_Cr ) ? 1 : 0 );
1184
268k
      m_CABACEstimator->joint_cb_cr( currTU, cbfMask );
1185
268k
    }
1186
714k
    if( TU::getCbf( currTU, compID ) )
1187
219k
    {
1188
219k
      if( isLuma(compID) )
1189
24.6k
      {
1190
24.6k
        m_CABACEstimator->residual_coding( currTU, compID, cuCtx );
1191
24.6k
        m_CABACEstimator->mts_idx( *currTU.cu, cuCtx );
1192
24.6k
      }
1193
194k
      else
1194
194k
        m_CABACEstimator->residual_coding( currTU, compID );
1195
219k
    }
1196
714k
  }
1197
714k
}
1198
1199
uint64_t IntraSearch::xGetIntraFracBitsQT( CodingStructure &cs, Partitioner &partitioner, const bool luma, CUCtx *cuCtx )
1200
445k
{
1201
445k
  m_CABACEstimator->resetBits();
1202
1203
445k
  xEncIntraHeader( cs, partitioner, luma );
1204
445k
  xEncSubdivCbfQT( cs, partitioner, luma );
1205
1206
445k
  if( luma )
1207
177k
  {
1208
177k
    xEncCoeffQT( cs, partitioner, COMP_Y, cuCtx );
1209
1210
177k
    CodingUnit &cu = *cs.cus[0];
1211
177k
    if (cuCtx /*&& CU::isSepTree(cu)*/
1212
112k
      && (!cu.ispMode || (cu.lfnstIdx && m_ispTestedModes[0].subTuCounter == 0)
1213
9.11k
        || (!cu.lfnstIdx
1214
7.73k
          && m_ispTestedModes[0].subTuCounter == m_ispTestedModes[cu.lfnstIdx].numTotalParts[cu.ispMode - 1] - 1)))
1215
104k
    {
1216
104k
      m_CABACEstimator->residual_lfnst_mode( cu, *cuCtx );
1217
104k
    }
1218
177k
  }
1219
268k
  else
1220
268k
  {
1221
268k
    xEncCoeffQT( cs, partitioner, COMP_Cb );
1222
268k
    xEncCoeffQT( cs, partitioner, COMP_Cr );
1223
268k
  }
1224
1225
445k
  uint64_t fracBits = m_CABACEstimator->getEstFracBits();
1226
445k
  return fracBits;
1227
445k
}
1228
1229
uint64_t IntraSearch::xGetIntraFracBitsQTChroma(const TransformUnit& currTU, const ComponentID compID, CUCtx *cuCtx)
1230
1.67M
{
1231
1.67M
  m_CABACEstimator->resetBits();
1232
1233
1.67M
  if ( currTU.jointCbCr )
1234
250k
  {
1235
250k
    const int cbfMask = ( TU::getCbf( currTU, COMP_Cb ) ? 2 : 0 ) + ( TU::getCbf( currTU, COMP_Cr ) ? 1 : 0 );
1236
250k
    m_CABACEstimator->cbf_comp( *currTU.cu, cbfMask>>1, currTU.blocks[ COMP_Cb ], currTU.depth, false );
1237
250k
    m_CABACEstimator->cbf_comp( *currTU.cu, cbfMask &1, currTU.blocks[ COMP_Cr ], currTU.depth, cbfMask>>1 );
1238
250k
    if( cbfMask )
1239
250k
      m_CABACEstimator->joint_cb_cr( currTU, cbfMask );
1240
250k
    if (cbfMask >> 1)
1241
248k
      m_CABACEstimator->residual_coding( currTU, COMP_Cb, cuCtx );
1242
250k
    if (cbfMask & 1)
1243
250k
      m_CABACEstimator->residual_coding( currTU, COMP_Cr, cuCtx );
1244
250k
  }
1245
1.42M
  else
1246
1.42M
  {
1247
1.42M
    if ( compID == COMP_Cb )
1248
712k
      m_CABACEstimator->cbf_comp( *currTU.cu, TU::getCbf( currTU, compID ), currTU.blocks[ compID ], currTU.depth, false );
1249
712k
    else
1250
712k
    {
1251
712k
      const bool cbCbf    = TU::getCbf( currTU, COMP_Cb );
1252
712k
      const bool crCbf    = TU::getCbf( currTU, compID );
1253
712k
      const int  cbfMask  = ( cbCbf ? 2 : 0 ) + ( crCbf ? 1 : 0 );
1254
712k
      m_CABACEstimator->cbf_comp( *currTU.cu, crCbf, currTU.blocks[ compID ], currTU.depth, cbCbf );
1255
712k
      m_CABACEstimator->joint_cb_cr( currTU, cbfMask );
1256
712k
    }
1257
1.42M
  }
1258
1259
1.67M
  if( !currTU.jointCbCr && TU::getCbf( currTU, compID ) )
1260
504k
  {
1261
504k
    m_CABACEstimator->residual_coding( currTU, compID, cuCtx );
1262
504k
  }
1263
1264
1.67M
  uint64_t fracBits = m_CABACEstimator->getEstFracBits();
1265
1.67M
  return fracBits;
1266
1.67M
}
1267
1268
void IntraSearch::xIntraCodingTUBlock(TransformUnit &tu, const ComponentID compID, const bool checkCrossCPrediction, Distortion &ruiDist, uint32_t *numSig, PelUnitBuf *predBuf, const bool loadTr)
1269
1.86M
{
1270
1.86M
  if (!tu.blocks[compID].valid())
1271
0
  {
1272
0
    return;
1273
0
  }
1274
1275
1.86M
  CodingStructure &cs             = *tu.cs;
1276
1.86M
  const CompArea      &area       = tu.blocks[compID];
1277
1.86M
  const SPS           &sps        = *cs.sps;
1278
1279
1.86M
  const ChannelType    chType     = toChannelType(compID);
1280
1.86M
  const int            bitDepth   = sps.bitDepths[chType];
1281
1282
1.86M
  CPelBuf        piOrg            = cs.getOrgBuf    (area);
1283
1.86M
  PelBuf         piPred           = cs.getPredBuf   (area);
1284
1.86M
  PelBuf         piResi           = cs.getResiBuf   (area);
1285
1.86M
  PelBuf         piReco           = cs.getRecoBuf   (area);
1286
1287
1.86M
  const CodingUnit& cu            = *tu.cu;
1288
1289
  //===== init availability pattern =====
1290
1.86M
  CHECK( tu.jointCbCr && compID == COMP_Cr, "wrong combination of compID and jointCbCr" );
1291
1.86M
  bool jointCbCr = tu.jointCbCr && compID == COMP_Cb;
1292
1293
1.86M
  if ( isLuma(compID) )
1294
182k
  {
1295
182k
    bool predRegDiffFromTB = CU::isPredRegDiffFromTB(*tu.cu );
1296
182k
    bool firstTBInPredReg  = false;
1297
182k
    CompArea areaPredReg(COMP_Y, tu.chromaFormat, area);
1298
182k
    if (tu.cu->ispMode )
1299
19.2k
    {
1300
19.2k
      firstTBInPredReg = CU::isFirstTBInPredReg(*tu.cu, area);
1301
19.2k
      if (predRegDiffFromTB)
1302
0
      {
1303
0
        if (firstTBInPredReg)
1304
0
        {
1305
0
          CU::adjustPredArea(areaPredReg);
1306
0
          initIntraPatternChTypeISP(*tu.cu, areaPredReg, piReco);
1307
0
        }
1308
0
      }
1309
19.2k
      else
1310
19.2k
        initIntraPatternChTypeISP(*tu.cu, area, piReco);
1311
19.2k
    }
1312
163k
    else if( !predBuf )
1313
28.2k
    {
1314
28.2k
      initIntraPatternChType(*tu.cu, area);
1315
28.2k
    }
1316
1317
    //===== get prediction signal =====
1318
182k
    if (predRegDiffFromTB)
1319
0
    {
1320
0
      if (firstTBInPredReg)
1321
0
      {
1322
0
        PelBuf piPredReg = cs.getPredBuf(areaPredReg);
1323
0
        predIntraAng(compID, piPredReg, cu);
1324
0
      }
1325
0
    }
1326
182k
    else
1327
182k
    {
1328
182k
      if( predBuf )
1329
134k
      {
1330
134k
        piPred.copyFrom( predBuf->Y() );
1331
134k
      }
1332
47.4k
      else if( CU::isMIP( cu, CH_L ) )
1333
20.7k
      {
1334
20.7k
        initIntraMip( cu );
1335
20.7k
        predIntraMip( piPred, cu );
1336
20.7k
      }
1337
26.7k
      else
1338
26.7k
      {
1339
26.7k
        predIntraAng(compID, piPred, cu);
1340
26.7k
      }
1341
182k
    }
1342
182k
  }
1343
1.86M
  DTRACE( g_trace_ctx, D_PRED, "@(%4d,%4d) [%2dx%2d] IMode=%d\n", tu.lx(), tu.ly(), tu.lwidth(), tu.lheight(), CU::getFinalIntraMode(cu, chType) );
1344
1345
1.86M
  if (isLuma(compID))
1346
182k
  {
1347
    //===== get residual signal =====
1348
182k
    piResi.subtract( piOrg, piPred );
1349
182k
  }
1350
1351
  //===== transform and quantization =====
1352
  //--- init rate estimation arrays for RDOQ ---
1353
  //--- transform and quantization           ---
1354
1.86M
  TCoeff uiAbsSum = 0;
1355
1.86M
  const QpParam cQP(tu, compID);
1356
1357
1.86M
  m_pcTrQuant->selectLambda(compID);
1358
1359
1.86M
  if ( jointCbCr )
1360
254k
  {
1361
    // Lambda is loosened for the joint mode with respect to single modes as the same residual is used for both chroma blocks
1362
254k
    const int    absIct = abs( TU::getICTMode(tu) );
1363
254k
    const double lfact  = ( absIct == 1 || absIct == 3 ? 0.8 : 0.5 );
1364
254k
    m_pcTrQuant->scaleLambda( lfact );
1365
254k
  }
1366
1.86M
  if ( sps.jointCbCr && isChroma(compID) && (tu.cu->cs->slice->sliceQp > 18) )
1367
1.11M
  {
1368
1.11M
    m_pcTrQuant->scaleLambda( 1.3 );
1369
1.11M
  }
1370
1371
1.86M
  if( isLuma(compID) )
1372
182k
  {
1373
182k
    m_pcTrQuant->transformNxN(tu, compID, cQP, uiAbsSum, m_CABACEstimator->getCtx(), loadTr);
1374
1375
182k
    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 );
1376
182k
    if (tu.cu->ispMode && isLuma(compID) && CU::isISPLast(*tu.cu, area, area.compID) && CU::allLumaCBFsAreZero(*tu.cu))
1377
0
    {
1378
      // ISP has to have at least one non-zero CBF
1379
0
      ruiDist = MAX_INT;
1380
0
      return;
1381
0
    }
1382
    //--- inverse transform ---
1383
182k
    if (uiAbsSum > 0)
1384
29.5k
    {
1385
29.5k
      m_pcTrQuant->invTransformNxN(tu, compID, piResi, cQP);
1386
29.5k
    }
1387
152k
    else
1388
152k
    {
1389
152k
      piResi.fill(0);
1390
152k
    }
1391
182k
  }
1392
1.67M
  else // chroma
1393
1.67M
  {
1394
1.67M
    PelBuf          crPred = cs.getPredBuf ( COMP_Cr );
1395
1.67M
    PelBuf          crResi = cs.getResiBuf ( COMP_Cr );
1396
1.67M
    PelBuf          crReco = cs.getRecoBuf ( COMP_Cr );
1397
1398
1.67M
    int         codedCbfMask  = 0;
1399
1.67M
    ComponentID codeCompId    = (tu.jointCbCr ? (tu.jointCbCr >> 1 ? COMP_Cb : COMP_Cr) : compID);
1400
1.67M
    const QpParam qpCbCr(tu, codeCompId);
1401
1402
1.67M
    if( tu.jointCbCr )
1403
254k
    {
1404
254k
      ComponentID otherCompId = ( codeCompId==COMP_Cr ? COMP_Cb : COMP_Cr );
1405
254k
      tu.getCoeffs( otherCompId ).fill(0); // do we need that?
1406
254k
      TU::setCbfAtDepth (tu, otherCompId, tu.depth, false );
1407
254k
    }
1408
1.67M
    PelBuf& codeResi = ( codeCompId == COMP_Cr ? crResi : piResi );
1409
1.67M
    uiAbsSum = 0;
1410
1.67M
    m_pcTrQuant->transformNxN(tu, codeCompId, qpCbCr, uiAbsSum, m_CABACEstimator->getCtx(), loadTr);
1411
1.67M
    DTRACE( g_trace_ctx, D_TU_ABS_SUM, "%d: comp=%d, abssum=%d\n", DTRACE_GET_COUNTER( g_trace_ctx, D_TU_ABS_SUM ), codeCompId, uiAbsSum );
1412
1.67M
    if( uiAbsSum > 0 )
1413
755k
    {
1414
755k
      m_pcTrQuant->invTransformNxN(tu, codeCompId, codeResi, qpCbCr);
1415
755k
      codedCbfMask += ( codeCompId == COMP_Cb ? 2 : 1 );
1416
755k
    }
1417
922k
    else
1418
922k
    {
1419
922k
      codeResi.fill(0);
1420
922k
    }
1421
1422
1.67M
    if( tu.jointCbCr )
1423
254k
    {
1424
254k
      if( tu.jointCbCr == 3 && codedCbfMask == 2 )
1425
248k
      {
1426
248k
        codedCbfMask = 3;
1427
248k
        TU::setCbfAtDepth (tu, COMP_Cr, tu.depth, true );
1428
248k
      }
1429
254k
      if( tu.jointCbCr != codedCbfMask )
1430
3.46k
      {
1431
3.46k
        ruiDist = MAX_DISTORTION;
1432
3.46k
        return;
1433
3.46k
      }
1434
250k
      m_pcTrQuant->invTransformICT( tu, piResi, crResi );
1435
250k
      uiAbsSum = codedCbfMask;
1436
250k
    }
1437
1438
    //===== reconstruction =====
1439
1.67M
    if( jointCbCr )
1440
250k
    {
1441
250k
      crReco.reconstruct(crPred, crResi, cs.slice->clpRngs[ COMP_Cr ]);
1442
250k
    }
1443
1.67M
  }
1444
1.85M
  piReco.reconstruct(piPred, piResi, cs.slice->clpRngs[ compID ]);
1445
  
1446
1447
1448
  //===== update distortion =====
1449
1.85M
  ruiDist += m_pcRdCost->getDistPart( piOrg, piReco, bitDepth, compID, DF_SSE );
1450
1.85M
  if( jointCbCr )
1451
250k
  {
1452
250k
    CPelBuf         crOrg  = cs.getOrgBuf  ( COMP_Cr );
1453
250k
    PelBuf          crReco = cs.getRecoBuf ( COMP_Cr );
1454
250k
    ruiDist += m_pcRdCost->getDistPart( crOrg, crReco, bitDepth, COMP_Cr, DF_SSE );
1455
250k
  }
1456
1.85M
}
1457
1458
void IntraSearch::xIntraCodingLumaQT(CodingStructure& cs, Partitioner& partitioner, PelUnitBuf* predBuf, const double bestCostSoFar, int numMode, bool disableMTS)
1459
109k
{
1460
109k
  PROFILER_SCOPE_AND_STAGE_EXT( 0, _TPROF, P_INTRA_RD_SEARCH_LUMA, &cs, partitioner.chType );
1461
109k
  const UnitArea& currArea  = partitioner.currArea();
1462
109k
  uint32_t        currDepth = partitioner.currTrDepth;
1463
109k
  Distortion singleDistLuma = 0;
1464
109k
  uint32_t   numSig         = 0;
1465
109k
  const SPS &sps            = *cs.sps;
1466
109k
  CodingUnit &cu            = *cs.cus[0];
1467
109k
  bool mtsAllowed = (numMode < 0) || disableMTS ? false : CU::isMTSAllowed(cu, COMP_Y);
1468
109k
  uint64_t singleFracBits   = 0;
1469
109k
  bool   splitCbfLumaSum    = false;
1470
109k
  double bestCostForISP     = bestCostSoFar;
1471
109k
  double dSingleCost        = MAX_DOUBLE;
1472
109k
  int endLfnstIdx           = (partitioner.isSepTree(cs) && partitioner.chType == CH_C && (currArea.lwidth() < 8 || currArea.lheight() < 8))
1473
109k
                           || (currArea.lwidth() > sps.getMaxTbSize() || currArea.lheight() > sps.getMaxTbSize()) || !sps.LFNST || (numMode < 0) ? 0 : 2;
1474
109k
  const bool useTS          = cs.picture->useTS;
1475
109k
  numMode                   = (numMode < 0) ? -numMode : numMode;
1476
1477
109k
  if (cu.mipFlag && !allowLfnstWithMip(cu.lumaSize()))
1478
1.99k
  {
1479
1.99k
    endLfnstIdx = 0;
1480
1.99k
  }
1481
109k
  int bestMTS = 0;
1482
109k
  int EndMTS  = mtsAllowed ? m_pcEncCfg->m_MTSIntraMaxCand : 0;
1483
109k
  if (cu.ispMode && (EndMTS || endLfnstIdx))
1484
5.16k
  {
1485
5.16k
    EndMTS = 0;
1486
5.16k
    if ((m_ispTestedModes[1].numTotalParts[cu.ispMode - 1] == 0)
1487
299
     && (m_ispTestedModes[2].numTotalParts[cu.ispMode - 1] == 0))
1488
299
    {
1489
299
      endLfnstIdx = 0;
1490
299
    }
1491
5.16k
  }
1492
109k
  if (cu.bdpcmM[CH_L])
1493
7.29k
  {
1494
7.29k
    endLfnstIdx = 0;
1495
7.29k
    EndMTS = 0;
1496
7.29k
  }
1497
109k
  bool checkTransformSkip = sps.transformSkip;
1498
1499
109k
  SizeType transformSkipMaxSize = 1 << sps.log2MaxTransformSkipBlockSize;
1500
109k
  bool tsAllowed = useTS  && cu.cs->sps->transformSkip && (!cu.ispMode) && (!cu.bdpcmM[CH_L]) && (!cu.sbtInfo);
1501
109k
  tsAllowed &= cu.blocks[COMP_Y].width <= transformSkipMaxSize && cu.blocks[COMP_Y].height <= transformSkipMaxSize;
1502
109k
  if (tsAllowed)
1503
14.6k
  {
1504
14.6k
    EndMTS += 1;
1505
14.6k
  }
1506
109k
  if (endLfnstIdx || EndMTS)
1507
44.6k
  {
1508
44.6k
    bool       splitCbfLuma  = false;
1509
44.6k
    const PartSplit ispType  = CU::getISPType(cu, COMP_Y);
1510
44.6k
    CUCtx cuCtx;
1511
44.6k
    cuCtx.isDQPCoded         = true;
1512
44.6k
    cuCtx.isChromaQpAdjCoded = true;
1513
44.6k
    cs.cost                  = 0.0;
1514
44.6k
    Distortion       singleDistTmpLuma = 0;
1515
44.6k
    uint64_t         singleTmpFracBits = 0;
1516
44.6k
    double           singleCostTmp     = 0;
1517
44.6k
    const TempCtx    ctxStart          (m_CtxCache, m_CABACEstimator->getCtx());
1518
44.6k
          TempCtx    ctxBest           (m_CtxCache);
1519
44.6k
    CodingStructure &saveCS            = *m_pSaveCS[cu.ispMode?0:1];
1520
44.6k
    TransformUnit *  tmpTU             = nullptr;
1521
44.6k
    int              bestLfnstIdx      = 0;
1522
44.6k
    int              startLfnstIdx     = 0;
1523
    // speedUps LFNST
1524
44.6k
    bool   rapidLFNST                  = false;
1525
44.6k
    bool   rapidDCT                    = false;
1526
44.6k
    double thresholdDCT                = 1;
1527
1528
44.6k
    if (m_pcEncCfg->m_MTS == 2)
1529
0
    {
1530
0
      thresholdDCT += 1.4 / sqrt(cu.lwidth() * cu.lheight());
1531
0
    }
1532
1533
44.6k
    if (m_pcEncCfg->m_LFNST > 1)
1534
0
    {
1535
0
      rapidLFNST = true;
1536
1537
0
      if (m_pcEncCfg->m_LFNST > 2)
1538
0
      {
1539
0
        rapidDCT    = true;
1540
0
        endLfnstIdx = endLfnstIdx ? 1 : 0;
1541
0
      }
1542
0
    }
1543
1544
44.6k
    saveCS.pcv              = cs.pcv;
1545
44.6k
    saveCS.picture          = cs.picture;
1546
44.6k
    saveCS.area.repositionTo( cs.area);
1547
1548
44.6k
    if (cu.ispMode)
1549
4.86k
    {
1550
4.86k
      partitioner.splitCurrArea(ispType, cs);
1551
4.86k
    }
1552
1553
44.6k
    TransformUnit& tu = cs.addTU(CS::getArea(cs, partitioner.currArea(), partitioner.chType, partitioner.treeType), partitioner.chType, cs.cus[0]);
1554
1555
44.6k
    if (cu.ispMode)
1556
4.86k
    {
1557
4.86k
      saveCS.clearTUs();
1558
4.86k
      do
1559
19.4k
      {
1560
19.4k
        saveCS.addTU(
1561
19.4k
          CS::getArea(cs, partitioner.currArea(), partitioner.chType, partitioner.treeType),
1562
19.4k
          partitioner.chType, cs.cus[0]);
1563
19.4k
      } while (partitioner.nextPart(cs));
1564
1565
4.86k
      partitioner.exitCurrSplit();
1566
4.86k
    }
1567
39.8k
    else
1568
39.8k
    {
1569
39.8k
      tmpTU = saveCS.tus.empty() ? &saveCS.addTU( currArea, partitioner.chType, nullptr ) : saveCS.tus.front();
1570
39.8k
      tmpTU->initData();
1571
39.8k
      tmpTU->UnitArea::operator=( currArea );
1572
39.8k
    }
1573
1574
1575
44.6k
    TrModeList trModes{ TrMode(0, true) };
1576
44.6k
    if (tsAllowed)
1577
14.6k
    {
1578
14.6k
      trModes.push_back(TrMode(1, true));
1579
14.6k
    }
1580
44.6k
    double dct2Cost           = MAX_DOUBLE;
1581
44.6k
    double trGrpStopThreshold = 1.001;
1582
44.6k
    double trGrpBestCost      = MAX_DOUBLE;
1583
1584
44.6k
    if (mtsAllowed)
1585
0
    {
1586
0
      if (m_pcEncCfg->m_LFNST)
1587
0
      {
1588
0
        uint32_t uiIntraMode = cs.cus[0]->intraDir[partitioner.chType];
1589
0
        int MTScur           = (uiIntraMode < 34) ? MTS_DST7_DCT8 : MTS_DCT8_DST7;
1590
1591
0
        trModes.push_back(TrMode(     2, true));
1592
0
        trModes.push_back(TrMode(MTScur, true));
1593
1594
0
        MTScur = (uiIntraMode < 34) ? MTS_DCT8_DST7 : MTS_DST7_DCT8;
1595
1596
0
        trModes.push_back(TrMode(MTScur,            true));
1597
0
        trModes.push_back(TrMode(MTS_DST7_DST7 + 3, true));
1598
0
      }
1599
0
      else
1600
0
      {
1601
0
        for (int i = 2; i < 6; i++)
1602
0
        {
1603
0
          trModes.push_back(TrMode(i, true));
1604
0
        }
1605
0
      }
1606
0
    }
1607
1608
44.6k
    if ((EndMTS && !m_pcEncCfg->m_LFNST) || (tsAllowed && !mtsAllowed))
1609
14.6k
    {
1610
14.6k
      xPreCheckMTS(tu, &trModes, m_pcEncCfg->m_MTSIntraMaxCand, predBuf);
1611
14.6k
      if (!mtsAllowed && !trModes[1].second)
1612
2.81k
      {
1613
2.81k
        EndMTS = 0;
1614
2.81k
      }
1615
14.6k
    }
1616
1617
44.6k
    bool NStopMTS = true;
1618
1619
89.3k
    for (int modeId = 0; modeId <= EndMTS && NStopMTS; modeId++)
1620
44.6k
    {
1621
44.6k
      if (modeId > 1)
1622
0
      {
1623
0
        trGrpBestCost = MAX_DOUBLE;
1624
0
      }
1625
157k
      for (int lfnstIdx = startLfnstIdx; lfnstIdx <= endLfnstIdx; lfnstIdx++)
1626
113k
      {
1627
113k
        if (lfnstIdx && modeId)
1628
0
        {
1629
0
          continue;
1630
0
        }
1631
113k
        if (mtsAllowed || tsAllowed)
1632
23.0k
        {
1633
23.0k
          if (m_pcEncCfg->m_TS && bestMTS == MTS_SKIP)
1634
0
          {
1635
0
            break;
1636
0
          }
1637
23.0k
          if (!m_pcEncCfg->m_LFNST && !trModes[modeId].second && mtsAllowed)
1638
0
          {
1639
0
            continue;
1640
0
          }
1641
1642
23.0k
          tu.mtsIdx[COMP_Y] = trModes[modeId].first;
1643
23.0k
        }
1644
1645
113k
        if (cu.ispMode && lfnstIdx)
1646
9.72k
        {
1647
9.72k
          if (m_ispTestedModes[lfnstIdx].numTotalParts[cu.ispMode - 1] == 0)
1648
0
          {
1649
0
            if (lfnstIdx == 2)
1650
0
            {
1651
0
              endLfnstIdx = 1;
1652
0
            }
1653
0
            continue;
1654
0
          }
1655
9.72k
        }
1656
1657
113k
        cu.lfnstIdx                          = lfnstIdx;
1658
113k
        cuCtx.lfnstLastScanPos               = false;
1659
113k
        cuCtx.violatesLfnstConstrained[CH_L] = false;
1660
113k
        cuCtx.violatesLfnstConstrained[CH_C] = false;
1661
1662
113k
        if ((lfnstIdx != startLfnstIdx) || (modeId))
1663
68.4k
        {
1664
68.4k
          m_CABACEstimator->getCtx() = ctxStart;
1665
68.4k
        }
1666
1667
113k
        singleDistTmpLuma = 0;
1668
1669
113k
        if (cu.ispMode)
1670
14.5k
        {
1671
14.5k
          splitCbfLuma = false;
1672
1673
14.5k
          partitioner.splitCurrArea(ispType, cs);
1674
1675
14.5k
          singleCostTmp = xTestISP(cs, partitioner, bestCostForISP, ispType, splitCbfLuma, singleTmpFracBits, singleDistTmpLuma, cuCtx);
1676
1677
14.5k
          partitioner.exitCurrSplit();
1678
1679
14.5k
          if (modeId && (singleCostTmp == MAX_DOUBLE))
1680
0
          {
1681
0
            m_ispTestedModes[lfnstIdx].numTotalParts[cu.ispMode - 1] = 0;
1682
0
          }
1683
1684
14.5k
          bool storeCost = (numMode == 1) ? true : false;
1685
1686
14.5k
          if ((m_pcEncCfg->m_ISP >= 2) && (numMode <= 1))
1687
14.5k
          {
1688
14.5k
            storeCost = true;
1689
14.5k
          }
1690
1691
14.5k
          if (storeCost)
1692
14.5k
          {
1693
14.5k
            m_ispTestedModes[0].bestCost[cu.ispMode - 1] = singleCostTmp;
1694
14.5k
          }
1695
14.5k
        }
1696
98.5k
        else
1697
98.5k
        {
1698
98.5k
          bool TrLoad = (EndMTS && !m_pcEncCfg->m_LFNST) || (tsAllowed && !mtsAllowed && (lfnstIdx == 0)) ? true : false;
1699
1700
98.5k
          xIntraCodingTUBlock(tu, COMP_Y, false, singleDistTmpLuma, &numSig, predBuf, TrLoad);
1701
1702
98.5k
          cuCtx.mtsLastScanPos = false;
1703
          //----- determine rate and r-d cost -----
1704
98.5k
        if ((sps.LFNST ? (modeId == EndMTS && modeId != 0 && checkTransformSkip) : (trModes[modeId].first != 0)) && !TU::getCbfAtDepth(tu, COMP_Y, currDepth))
1705
0
        {
1706
0
          singleCostTmp = MAX_DOUBLE;
1707
0
        }
1708
98.5k
        else
1709
98.5k
        {
1710
98.5k
          m_ispTestedModes[0].IspType      = TU_NO_ISP;
1711
98.5k
          m_ispTestedModes[0].subTuCounter = -1;
1712
98.5k
          singleTmpFracBits = xGetIntraFracBitsQT(cs, partitioner, true, &cuCtx);
1713
1714
98.5k
          if (tu.mtsIdx[COMP_Y] > MTS_SKIP)
1715
0
          {
1716
0
            if (!cuCtx.mtsLastScanPos)
1717
0
            {
1718
0
              singleCostTmp = MAX_DOUBLE;
1719
0
            }
1720
0
            else
1721
0
            {
1722
0
              singleCostTmp = m_pcRdCost->calcRdCost(singleTmpFracBits, singleDistTmpLuma);
1723
0
            }
1724
0
          }
1725
98.5k
          else
1726
98.5k
          {
1727
98.5k
            singleCostTmp = m_pcRdCost->calcRdCost(singleTmpFracBits, singleDistTmpLuma);
1728
98.5k
          }
1729
98.5k
        }
1730
1731
98.5k
          if (((EndMTS && (m_pcEncCfg->m_MTS == 2)) || rapidLFNST) && modeId == 0 && lfnstIdx == 0)
1732
0
          {
1733
0
            if (singleCostTmp > bestCostSoFar * thresholdDCT)
1734
0
            {
1735
0
              EndMTS = 0;
1736
1737
0
              if (rapidDCT)
1738
0
              {
1739
0
                endLfnstIdx = 0;   // break the loop but do not cpy best
1740
0
              }
1741
0
            }
1742
0
          }
1743
1744
98.5k
          if (lfnstIdx && !cuCtx.lfnstLastScanPos && !cu.ispMode)
1745
49.0k
          {
1746
49.0k
            bool rootCbfL = false;
1747
1748
196k
            for (uint32_t t = 0; t < getNumberValidTBlocks(*cu.cs->pcv); t++)
1749
147k
            {
1750
147k
              rootCbfL |= tu.cbf[t] != 0;
1751
147k
            }
1752
1753
49.0k
            if (rapidLFNST && !rootCbfL)
1754
0
            {
1755
0
              endLfnstIdx = lfnstIdx; // break the loop
1756
0
            }
1757
49.0k
            bool cbfAtZeroDepth = CU::isSepTree(cu)
1758
49.0k
              ? rootCbfL
1759
49.0k
              : (cs.area.chromaFormat != CHROMA_400 && std::min(cu.firstTU->blocks[1].width, cu.firstTU->blocks[1].height) < 4)
1760
0
                ? TU::getCbfAtDepth(tu, COMP_Y, currDepth)
1761
0
                : rootCbfL;
1762
1763
49.0k
            if (cbfAtZeroDepth)
1764
357
            {
1765
357
              singleCostTmp = MAX_DOUBLE;
1766
357
            }
1767
49.0k
          }
1768
98.5k
        }
1769
1770
113k
        if (singleCostTmp < dSingleCost)
1771
41.2k
        {
1772
41.2k
          trGrpBestCost  = singleCostTmp;
1773
41.2k
          dSingleCost    = singleCostTmp;
1774
41.2k
          singleDistLuma = singleDistTmpLuma;
1775
41.2k
          singleFracBits = singleTmpFracBits;
1776
41.2k
          bestLfnstIdx   = lfnstIdx;
1777
41.2k
          bestMTS        = modeId;
1778
1779
41.2k
          if (dSingleCost < bestCostForISP)
1780
25.6k
          {
1781
25.6k
            bestCostForISP = dSingleCost;
1782
25.6k
          }
1783
1784
41.2k
          splitCbfLumaSum = splitCbfLuma;
1785
1786
41.2k
          if (lfnstIdx == 0 && modeId == 0 && cu.ispMode == 0)
1787
39.8k
          {
1788
39.8k
            dct2Cost = singleCostTmp;
1789
1790
39.8k
            if (!TU::getCbfAtDepth(tu, COMP_Y, currDepth))
1791
33.6k
            {
1792
33.6k
              if (rapidLFNST)
1793
0
              {
1794
0
                 endLfnstIdx = 0;   // break the loop but do not cpy best
1795
0
              }
1796
1797
33.6k
              EndMTS = 0;
1798
33.6k
            }
1799
39.8k
          }
1800
1801
41.2k
          if (bestLfnstIdx != endLfnstIdx || bestMTS != EndMTS)
1802
30.5k
          {
1803
30.5k
            if (cu.ispMode)
1804
1.06k
            {
1805
1.06k
              saveCS.getRecoBuf(currArea.Y()).copyFrom(cs.getRecoBuf(currArea.Y()));
1806
1807
5.30k
              for (uint32_t j = 0; j < cs.tus.size(); j++)
1808
4.24k
              {
1809
4.24k
                saveCS.tus[j]->copyComponentFrom(*cs.tus[j], COMP_Y);
1810
4.24k
              }
1811
1.06k
            }
1812
29.5k
            else
1813
29.5k
            {
1814
29.5k
              saveCS.getPredBuf(tu.Y()).copyFrom(cs.getPredBuf(tu.Y()));
1815
29.5k
              saveCS.getRecoBuf(tu.Y()).copyFrom(cs.getRecoBuf(tu.Y()));
1816
1817
29.5k
              tmpTU->copyComponentFrom(tu, COMP_Y);
1818
29.5k
            }
1819
1820
30.5k
            ctxBest = m_CABACEstimator->getCtx();
1821
30.5k
          }
1822
      
1823
41.2k
        }
1824
71.9k
        else
1825
71.9k
        {
1826
71.9k
          if( rapidLFNST )
1827
0
          {
1828
0
            endLfnstIdx = lfnstIdx; // break the loop
1829
0
          }
1830
71.9k
        }
1831
113k
      }
1832
44.6k
      if (m_pcEncCfg->m_LFNST && m_pcEncCfg->m_MTS == 2 && modeId && modeId != EndMTS)
1833
0
      {
1834
0
        NStopMTS = false;
1835
1836
0
        if (bestMTS || bestLfnstIdx)
1837
0
        {
1838
0
          if ((modeId > 1 && bestMTS == modeId) || modeId == 1)
1839
0
          {
1840
0
            NStopMTS = (dct2Cost / trGrpBestCost) < trGrpStopThreshold;
1841
0
          }
1842
0
        }
1843
0
      }
1844
44.6k
    }
1845
1846
44.6k
    cu.lfnstIdx = bestLfnstIdx;
1847
44.6k
    if (dSingleCost != MAX_DOUBLE)
1848
40.7k
    {
1849
40.7k
      if (bestLfnstIdx != endLfnstIdx || bestMTS != EndMTS)
1850
30.1k
      {
1851
30.1k
        if (cu.ispMode)
1852
745
        {
1853
745
          const UnitArea& currArea = partitioner.currArea();
1854
745
          cs.getRecoBuf(currArea.Y()).copyFrom(saveCS.getRecoBuf(currArea.Y()));
1855
1856
745
          if (saveCS.tus.size() != cs.tus.size())
1857
0
          {
1858
0
            partitioner.splitCurrArea(ispType, cs);
1859
1860
0
            do
1861
0
            {
1862
0
              partitioner.nextPart(cs);
1863
0
              cs.addTU(CS::getArea(cs, partitioner.currArea(), partitioner.chType, partitioner.treeType),
1864
0
                partitioner.chType, cs.cus[0]);
1865
0
            } while (saveCS.tus.size() != cs.tus.size());
1866
1867
0
            partitioner.exitCurrSplit();
1868
0
          }
1869
1870
3.72k
          for (uint32_t j = 0; j < saveCS.tus.size(); j++)
1871
2.98k
          {
1872
2.98k
            cs.tus[j]->copyComponentFrom(*saveCS.tus[j], COMP_Y);
1873
2.98k
          }
1874
745
        }
1875
29.3k
        else
1876
29.3k
        {
1877
29.3k
          cs.getRecoBuf(tu.Y()).copyFrom(saveCS.getRecoBuf(tu.Y()));
1878
1879
29.3k
          tu.copyComponentFrom(*tmpTU, COMP_Y);
1880
29.3k
        }
1881
1882
30.1k
        m_CABACEstimator->getCtx() = ctxBest;
1883
30.1k
      }
1884
1885
      // otherwise this would've happened in useSubStructure
1886
40.7k
      cs.picture->getRecoBuf(currArea.Y()).copyFrom(cs.getRecoBuf(currArea.Y()));
1887
40.7k
    }
1888
44.6k
  }
1889
64.8k
  else
1890
64.8k
  {
1891
64.8k
    if (cu.ispMode)
1892
299
    {
1893
299
      const PartSplit ispType = CU::getISPType(cu, COMP_Y);
1894
299
      partitioner.splitCurrArea(ispType, cs);
1895
1896
299
      CUCtx      cuCtx;
1897
299
      dSingleCost = xTestISP(cs, partitioner, bestCostForISP, ispType, splitCbfLumaSum, singleFracBits, singleDistLuma, cuCtx);
1898
299
      partitioner.exitCurrSplit();
1899
299
      bool storeCost = (numMode == 1) ? true : false;
1900
299
      if ((m_pcEncCfg->m_ISP >= 2) && (numMode <= 1))
1901
299
      {
1902
299
        storeCost = true;
1903
299
      }
1904
299
      if (storeCost)
1905
299
      {
1906
299
        m_ispTestedModes[0].bestCost[cu.ispMode - 1] = dSingleCost;
1907
299
      }
1908
299
    }
1909
64.5k
    else
1910
64.5k
    {
1911
64.5k
      TransformUnit& tu =
1912
64.5k
        cs.addTU(CS::getArea(cs, currArea, partitioner.chType, partitioner.treeType), partitioner.chType, cs.cus[0]);
1913
64.5k
      tu.depth = currDepth;
1914
1915
64.5k
      CHECK(!tu.Y().valid(), "Invalid TU");
1916
64.5k
      xIntraCodingTUBlock(tu, COMP_Y, false, singleDistLuma, &numSig, predBuf);
1917
      //----- determine rate and r-d cost -----
1918
64.5k
      m_ispTestedModes[0].IspType = TU_NO_ISP;
1919
64.5k
      m_ispTestedModes[0].subTuCounter = -1;
1920
64.5k
      singleFracBits = xGetIntraFracBitsQT(cs, partitioner, true);
1921
64.5k
      dSingleCost = m_pcRdCost->calcRdCost(singleFracBits, singleDistLuma);
1922
64.5k
    }
1923
64.8k
  }
1924
1925
109k
  if (cu.ispMode)
1926
5.16k
  { 
1927
5.16k
    for (auto& ptu : cs.tus)
1928
8.51k
    {
1929
8.51k
      if (currArea.Y().contains(ptu->Y()))
1930
8.51k
      {
1931
8.51k
        TU::setCbfAtDepth(*ptu, COMP_Y, currDepth, splitCbfLumaSum ? 1 : 0);
1932
8.51k
      }
1933
8.51k
    }
1934
5.16k
  }
1935
109k
  cs.dist     += singleDistLuma;
1936
109k
  cs.fracBits += singleFracBits;
1937
109k
  cs.cost      = dSingleCost;
1938
1939
109k
  STAT_COUNT_CU_MODES( partitioner.chType == CH_L, g_cuCounters1D[CU_RD_TESTS][0][!cs.slice->isIntra() + cs.slice->depth] );
1940
109k
  STAT_COUNT_CU_MODES( partitioner.chType == CH_L && !cs.slice->isIntra(), g_cuCounters2D[CU_RD_TESTS][Log2( cs.area.lheight() )][Log2( cs.area.lwidth() )] );
1941
109k
}
1942
1943
ChromaCbfs IntraSearch::xIntraChromaCodingQT(CodingStructure& cs, Partitioner& partitioner)
1944
268k
{
1945
268k
  UnitArea    currArea      = partitioner.currArea();
1946
1947
268k
  if( !currArea.Cb().valid() ) 
1948
0
    return ChromaCbfs(false);
1949
1950
268k
  TransformUnit& currTU     = *cs.getTU( currArea.chromaPos(), CH_C );
1951
268k
  const CodingUnit& cu  = *cs.getCU( currArea.chromaPos(), CH_C, TREE_D );
1952
268k
  ChromaCbfs cbfs(false);
1953
268k
  uint32_t   currDepth = partitioner.currTrDepth;
1954
268k
  const bool useTS = cs.picture->useTS;
1955
268k
  if (currDepth == currTU.depth)
1956
268k
  {
1957
268k
    if (!currArea.Cb().valid() || !currArea.Cr().valid())
1958
0
    {
1959
0
      return cbfs;
1960
0
    }
1961
1962
268k
    CodingStructure& saveCS = *m_pSaveCS[1];
1963
268k
    saveCS.pcv = cs.pcv;
1964
268k
    saveCS.picture = cs.picture;
1965
268k
    saveCS.area.repositionTo(cs.area);
1966
1967
268k
    TransformUnit& tmpTU = saveCS.tus.empty() ? saveCS.addTU(currArea, partitioner.chType, nullptr) : *saveCS.tus.front();
1968
268k
    tmpTU.initData();
1969
268k
    tmpTU.UnitArea::operator=(currArea);
1970
268k
    const unsigned      numTBlocks = getNumberValidTBlocks(*cs.pcv);
1971
1972
268k
    CompArea& cbArea = currTU.blocks[COMP_Cb];
1973
268k
    CompArea& crArea = currTU.blocks[COMP_Cr];
1974
268k
    double     bestCostCb = MAX_DOUBLE;
1975
268k
    double     bestCostCr = MAX_DOUBLE;
1976
268k
    Distortion bestDistCb = 0;
1977
268k
    Distortion bestDistCr = 0;
1978
1979
268k
    TempCtx ctxStartTU(m_CtxCache);
1980
268k
    TempCtx ctxStart(m_CtxCache);
1981
268k
    TempCtx ctxBest(m_CtxCache);
1982
1983
268k
    ctxStartTU = m_CABACEstimator->getCtx();
1984
268k
    ctxStart = m_CABACEstimator->getCtx();
1985
268k
    currTU.jointCbCr = 0;
1986
1987
    // Do predictions here to avoid repeating the "default0Save1Load2" stuff
1988
268k
    int  predMode = cu.bdpcmM[CH_C] ? BDPCM_IDX : CU::getFinalIntraMode(cu, CH_C);
1989
1990
268k
    PelBuf piPredCb = cs.getPredBuf(COMP_Cb);
1991
268k
    PelBuf piPredCr = cs.getPredBuf(COMP_Cr);
1992
1993
268k
    initIntraPatternChType(*currTU.cu, cbArea);
1994
268k
    initIntraPatternChType(*currTU.cu, crArea);
1995
1996
268k
    if (CU::isLMCMode(predMode))
1997
19.5k
    {
1998
19.5k
      loadLMLumaRecPels(cu, cbArea);
1999
19.5k
      predIntraChromaLM(COMP_Cb, piPredCb, cu, cbArea, predMode);
2000
19.5k
      predIntraChromaLM(COMP_Cr, piPredCr, cu, crArea, predMode);
2001
19.5k
    }
2002
248k
    else
2003
248k
    {
2004
248k
      predIntraAng(COMP_Cb, piPredCb, cu);
2005
248k
      predIntraAng(COMP_Cr, piPredCr, cu);
2006
248k
    }
2007
2008
    // determination of chroma residuals including reshaping and cross-component prediction
2009
    //----- get chroma residuals -----
2010
268k
    PelBuf resiCb = cs.getResiBuf(COMP_Cb);
2011
268k
    PelBuf resiCr = cs.getResiBuf(COMP_Cr);
2012
268k
    resiCb.subtract(cs.getOrgBuf(COMP_Cb), piPredCb);
2013
268k
    resiCr.subtract(cs.getOrgBuf(COMP_Cr), piPredCr);
2014
2015
    //===== store original residual signals (std and crossCompPred) =====
2016
1.61M
    for( int k = 0; k < 5; k++ )
2017
1.34M
    {
2018
1.34M
      m_orgResiCb[k].compactResize( cbArea );
2019
1.34M
      m_orgResiCr[k].compactResize( crArea );
2020
1.34M
    }
2021
536k
    for (int k = 0; k < 1; k += 4)
2022
268k
    {
2023
268k
      m_orgResiCb[k].copyFrom(resiCb);
2024
268k
      m_orgResiCr[k].copyFrom(resiCr);
2025
268k
    }
2026
2027
268k
    CUCtx cuCtx;
2028
268k
    cuCtx.isDQPCoded = true;
2029
268k
    cuCtx.isChromaQpAdjCoded = true;
2030
268k
    cuCtx.lfnstLastScanPos = false;
2031
2032
268k
    CodingStructure& saveCScur = *m_pSaveCS[2];
2033
2034
268k
    saveCScur.pcv = cs.pcv;
2035
268k
    saveCScur.picture = cs.picture;
2036
268k
    saveCScur.area.repositionTo(cs.area);
2037
2038
268k
    TransformUnit& tmpTUcur = saveCScur.tus.empty() ? saveCScur.addTU(currArea, partitioner.chType, nullptr) : *saveCScur.tus.front();
2039
268k
    tmpTUcur.initData();
2040
268k
    tmpTUcur.UnitArea::operator=(currArea);
2041
2042
268k
    TempCtx ctxBestTUL(m_CtxCache);
2043
2044
268k
    const SPS& sps = *cs.sps;
2045
268k
    double     bestCostCbcur = MAX_DOUBLE;
2046
268k
    double     bestCostCrcur = MAX_DOUBLE;
2047
268k
    Distortion bestDistCbcur = 0;
2048
268k
    Distortion bestDistCrcur = 0;
2049
2050
268k
    int  endLfnstIdx = (partitioner.isSepTree(cs) && partitioner.chType == CH_C && (partitioner.currArea().lwidth() < 8 || partitioner.currArea().lheight() < 8))
2051
256k
      || (partitioner.currArea().lwidth() > sps.getMaxTbSize() || partitioner.currArea().lheight() > sps.getMaxTbSize()) || !sps.LFNST ? 0 : 2;
2052
268k
    int  startLfnstIdx = 0;
2053
268k
    int  bestLfnstIdx = 0;
2054
268k
    bool testLFNST = sps.LFNST;
2055
2056
    // speedUps LFNST
2057
268k
    bool rapidLFNST = false;
2058
268k
    if (m_pcEncCfg->m_LFNST > 1)
2059
0
    {
2060
0
      rapidLFNST = true;
2061
0
      if (m_pcEncCfg->m_LFNST > 2)
2062
0
      {
2063
0
        endLfnstIdx = endLfnstIdx ? 1 : 0;
2064
0
      }
2065
0
    }
2066
268k
    int ts_used = 0;
2067
268k
    bool testTS = false;
2068
268k
    if (partitioner.chType != CH_C)
2069
0
    {
2070
0
      startLfnstIdx = currTU.cu->lfnstIdx;
2071
0
      endLfnstIdx = currTU.cu->lfnstIdx;
2072
0
      bestLfnstIdx = currTU.cu->lfnstIdx;
2073
0
      testLFNST  = false;
2074
0
      rapidLFNST = false;
2075
0
      ts_used = currTU.mtsIdx[COMP_Y];
2076
0
    }
2077
268k
    if (cu.bdpcmM[CH_C])
2078
36.5k
    {
2079
36.5k
      endLfnstIdx = 0;
2080
36.5k
      testLFNST = false;
2081
36.5k
    }
2082
2083
268k
    double dSingleCostAll = MAX_DOUBLE;
2084
268k
    double singleCostTmpAll = 0;
2085
2086
980k
    for (int lfnstIdx = startLfnstIdx; lfnstIdx <= endLfnstIdx; lfnstIdx++)
2087
712k
    {
2088
712k
      if (rapidLFNST && lfnstIdx)
2089
0
      {
2090
0
        if ((lfnstIdx == 2) && (bestLfnstIdx == 0))
2091
0
        {
2092
0
          continue;
2093
0
        }
2094
0
      }
2095
2096
712k
      currTU.cu->lfnstIdx = lfnstIdx;
2097
712k
      if (lfnstIdx)
2098
443k
      {
2099
443k
        m_CABACEstimator->getCtx() = ctxStartTU;
2100
443k
      }
2101
2102
712k
      cuCtx.lfnstLastScanPos = false;
2103
712k
      cuCtx.violatesLfnstConstrained[CH_L] = false;
2104
712k
      cuCtx.violatesLfnstConstrained[CH_C] = false;
2105
2106
2.13M
      for (uint32_t c = COMP_Cb; c < numTBlocks; c++)
2107
1.42M
      {
2108
1.42M
        const ComponentID compID = ComponentID(c);
2109
1.42M
        const CompArea& area = currTU.blocks[compID];
2110
1.42M
        double     dSingleCost = MAX_DOUBLE;
2111
1.42M
        Distortion singleDistCTmp = 0;
2112
1.42M
        double     singleCostTmp = 0;
2113
1.42M
        bool tsAllowed = useTS && TU::isTSAllowed(currTU, compID) && m_pcEncCfg->m_useChromaTS && !currTU.cu->lfnstIdx && !cu.bdpcmM[CH_C];
2114
1.42M
        if ((partitioner.chType == CH_L) && (!ts_used))
2115
0
        {
2116
0
          tsAllowed = false;
2117
0
        }
2118
1.42M
        uint8_t nNumTransformCands = 1 + (tsAllowed ? 1 : 0); // DCT + TS = 2 tests       
2119
1.42M
        TrModeList trModes;
2120
1.42M
        if (nNumTransformCands > 1)
2121
0
        {
2122
0
          trModes.push_back(TrMode(0, true));   // DCT2
2123
0
          trModes.push_back(TrMode(1, true));   // TS
2124
0
          testTS = true;
2125
0
        }
2126
1.42M
        bool cbfDCT2 = true;
2127
1.42M
        const bool isLastMode = testLFNST || cs.sps->jointCbCr ||  tsAllowed ? false : true;
2128
1.42M
        int bestModeId = 0;
2129
1.42M
        ctxStart = m_CABACEstimator->getCtx();
2130
2.84M
        for (int modeId = 0; modeId < nNumTransformCands; modeId++)
2131
1.42M
        {
2132
1.42M
          if (lfnstIdx || modeId)
2133
887k
          {
2134
887k
            resiCb.copyFrom(m_orgResiCb[0]);
2135
887k
            resiCr.copyFrom(m_orgResiCr[0]);
2136
887k
          }
2137
1.42M
          if (modeId == 0)
2138
1.42M
          {
2139
1.42M
            if ( tsAllowed)
2140
0
            {
2141
0
              xPreCheckMTS(currTU, &trModes, m_pcEncCfg->m_MTSIntraMaxCand, 0, compID);
2142
0
            }
2143
1.42M
          }
2144
2145
1.42M
          currTU.mtsIdx[compID] = currTU.cu->bdpcmM[CH_C] ? MTS_SKIP : modeId;
2146
2147
1.42M
          if (modeId)
2148
0
          {
2149
0
            if (!cbfDCT2 && trModes[modeId].first == MTS_SKIP)
2150
0
            {
2151
0
              break;
2152
0
            }
2153
0
            m_CABACEstimator->getCtx() = ctxStart;
2154
0
          }
2155
1.42M
          singleDistCTmp = 0;
2156
1.42M
          if (tsAllowed)
2157
0
          {
2158
0
            xIntraCodingTUBlock(currTU, compID, false, singleDistCTmp, 0, 0, true);
2159
0
            if ((modeId == 0) && (!trModes[modeId + 1].second))
2160
0
            {
2161
0
              nNumTransformCands = 1;
2162
0
            }
2163
0
          }
2164
1.42M
          else
2165
1.42M
        {
2166
1.42M
          xIntraCodingTUBlock(currTU, compID, false, singleDistCTmp);
2167
1.42M
        }
2168
1.42M
        if (((currTU.mtsIdx[compID] == MTS_SKIP && !currTU.cu->bdpcmM[CH_C])
2169
0
          && !TU::getCbf(currTU, compID)))   // In order not to code TS flag when cbf is zero, the case for TS with
2170
                                             // cbf being zero is forbidden.
2171
0
        {
2172
0
          singleCostTmp = MAX_DOUBLE;
2173
0
        }
2174
1.42M
        else
2175
1.42M
        {
2176
1.42M
          uint64_t fracBitsTmp = xGetIntraFracBitsQTChroma(currTU, compID, &cuCtx);
2177
1.42M
          singleCostTmp = m_pcRdCost->calcRdCost(fracBitsTmp, singleDistCTmp);
2178
1.42M
        }
2179
2180
1.42M
        if (singleCostTmp < dSingleCost)
2181
1.42M
        {
2182
1.42M
          dSingleCost = singleCostTmp;
2183
2184
1.42M
          if (compID == COMP_Cb)
2185
712k
          {
2186
712k
            bestCostCb = singleCostTmp;
2187
712k
            bestDistCb = singleDistCTmp;
2188
712k
          }
2189
712k
          else
2190
712k
          {
2191
712k
            bestCostCr = singleCostTmp;
2192
712k
            bestDistCr = singleDistCTmp;
2193
712k
          }
2194
1.42M
          bestModeId = modeId;
2195
1.42M
          if (currTU.mtsIdx[compID] == MTS_DCT2_DCT2)
2196
1.35M
          {
2197
1.35M
            cbfDCT2 = TU::getCbfAtDepth(currTU, compID, currDepth);
2198
1.35M
          }
2199
1.42M
          if (!isLastMode)
2200
1.42M
          {
2201
1.42M
            saveCS.getRecoBuf(area).copyFrom(cs.getRecoBuf(area));
2202
1.42M
            tmpTU.copyComponentFrom(currTU, compID);
2203
1.42M
            ctxBest = m_CABACEstimator->getCtx();
2204
1.42M
          }
2205
1.42M
        }
2206
1.42M
        }
2207
1.42M
        if (testTS && ((c == COMP_Cb && bestModeId < (nNumTransformCands - 1)) ))
2208
0
        {
2209
0
          m_CABACEstimator->getCtx() = ctxBest;
2210
2211
0
          currTU.copyComponentFrom(tmpTU, COMP_Cb); // Cbf of Cb is needed to estimate cost for Cr Cbf
2212
0
        }
2213
1.42M
      }
2214
2215
712k
      singleCostTmpAll = bestCostCb + bestCostCr;
2216
2217
712k
      bool rootCbfL = false;
2218
712k
      if (testLFNST)
2219
675k
      {
2220
2.70M
        for (uint32_t t = 0; t < getNumberValidTBlocks(*cs.pcv); t++)
2221
2.02M
        {
2222
2.02M
          rootCbfL |= bool(tmpTU.cbf[t]);
2223
2.02M
        }
2224
675k
        if (rapidLFNST && !rootCbfL)
2225
0
        {
2226
0
          endLfnstIdx = lfnstIdx; // end this
2227
0
        }
2228
675k
      }
2229
2230
712k
      if (testLFNST && lfnstIdx && !cuCtx.lfnstLastScanPos)
2231
291k
      {
2232
291k
        bool cbfAtZeroDepth = CU::isSepTree(*currTU.cu)
2233
291k
          ? rootCbfL : (cs.area.chromaFormat != CHROMA_400
2234
0
            && std::min(tmpTU.blocks[1].width, tmpTU.blocks[1].height) < 4)
2235
0
          ? TU::getCbfAtDepth(currTU, COMP_Y, currTU.depth) : rootCbfL;
2236
291k
        if (cbfAtZeroDepth)
2237
1.60k
        {
2238
1.60k
          singleCostTmpAll = MAX_DOUBLE;
2239
1.60k
        }
2240
291k
      }
2241
712k
      if ((testLFNST || testTS) && (singleCostTmpAll < dSingleCostAll))
2242
231k
      {
2243
231k
        bestLfnstIdx = lfnstIdx;
2244
231k
        if ((lfnstIdx != endLfnstIdx) || testTS)
2245
221k
        {
2246
221k
          dSingleCostAll = singleCostTmpAll;
2247
2248
221k
          bestCostCbcur = bestCostCb;
2249
221k
          bestCostCrcur = bestCostCr;
2250
221k
          bestDistCbcur = bestDistCb;
2251
221k
          bestDistCrcur = bestDistCr;
2252
2253
221k
          saveCScur.getRecoBuf(cbArea).copyFrom(saveCS.getRecoBuf(cbArea));
2254
221k
          saveCScur.getRecoBuf(crArea).copyFrom(saveCS.getRecoBuf(crArea));
2255
2256
221k
          tmpTUcur.copyComponentFrom(tmpTU, COMP_Cb);
2257
221k
          tmpTUcur.copyComponentFrom(tmpTU, COMP_Cr);
2258
221k
        }
2259
231k
        ctxBestTUL = m_CABACEstimator->getCtx();
2260
231k
      }
2261
712k
    }
2262
268k
    if ((testLFNST && (bestLfnstIdx != endLfnstIdx)) || testTS)
2263
221k
    {
2264
221k
      bestCostCb = bestCostCbcur;
2265
221k
      bestCostCr = bestCostCrcur;
2266
221k
      bestDistCb = bestDistCbcur;
2267
221k
      bestDistCr = bestDistCrcur;
2268
221k
      currTU.cu->lfnstIdx = bestLfnstIdx;
2269
221k
      if (!cs.sps->jointCbCr)
2270
0
      {
2271
0
        cs.getRecoBuf(cbArea).copyFrom(saveCScur.getRecoBuf(cbArea));
2272
0
        cs.getRecoBuf(crArea).copyFrom(saveCScur.getRecoBuf(crArea));
2273
2274
0
        currTU.copyComponentFrom(tmpTUcur, COMP_Cb);
2275
0
        currTU.copyComponentFrom(tmpTUcur, COMP_Cr);
2276
2277
0
        m_CABACEstimator->getCtx() = ctxBestTUL;
2278
0
      }
2279
221k
    }
2280
2281
268k
    Distortion bestDistCbCr = bestDistCb + bestDistCr;
2282
2283
268k
    if (cs.sps->jointCbCr)
2284
268k
    {
2285
268k
      if ((testLFNST && (bestLfnstIdx != endLfnstIdx)) || testTS)
2286
221k
      {
2287
221k
        saveCS.getRecoBuf(cbArea).copyFrom(saveCScur.getRecoBuf(cbArea));
2288
221k
        saveCS.getRecoBuf(crArea).copyFrom(saveCScur.getRecoBuf(crArea));
2289
2290
221k
        tmpTU.copyComponentFrom(tmpTUcur, COMP_Cb);
2291
221k
        tmpTU.copyComponentFrom(tmpTUcur, COMP_Cr);
2292
221k
        m_CABACEstimator->getCtx() = ctxBestTUL;
2293
221k
        ctxBest = m_CABACEstimator->getCtx();
2294
221k
      }
2295
      // Test using joint chroma residual coding
2296
268k
      double     bestCostCbCr = bestCostCb + bestCostCr;
2297
268k
      int        bestJointCbCr = 0;
2298
268k
      bool checkDCTOnly = m_pcEncCfg->m_useChromaTS && ((TU::getCbf(tmpTU, COMP_Cb) && tmpTU.mtsIdx[COMP_Cb] == MTS_DCT2_DCT2 && !TU::getCbf(tmpTU, COMP_Cr)) ||
2299
0
        (TU::getCbf(tmpTU, COMP_Cr) && tmpTU.mtsIdx[COMP_Cr] == MTS_DCT2_DCT2 && !TU::getCbf(tmpTU, COMP_Cb)) ||
2300
0
        (TU::getCbf(tmpTU, COMP_Cb) && tmpTU.mtsIdx[COMP_Cb] == MTS_DCT2_DCT2 && TU::getCbf(tmpTU, COMP_Cr) && tmpTU.mtsIdx[COMP_Cr] == MTS_DCT2_DCT2));
2301
268k
      bool checkTSOnly = m_pcEncCfg->m_useChromaTS && ((TU::getCbf(tmpTU, COMP_Cb) && tmpTU.mtsIdx[COMP_Cb] == MTS_SKIP && !TU::getCbf(tmpTU, COMP_Cr)) ||
2302
0
        (TU::getCbf(tmpTU, COMP_Cr) && tmpTU.mtsIdx[COMP_Cr] == MTS_SKIP && !TU::getCbf(tmpTU, COMP_Cb)) ||
2303
0
        (TU::getCbf(tmpTU, COMP_Cb) && tmpTU.mtsIdx[COMP_Cb] == MTS_SKIP && TU::getCbf(tmpTU, COMP_Cr) && tmpTU.mtsIdx[COMP_Cr] == MTS_SKIP));
2304
268k
      bool       lastIsBest = false;
2305
268k
      bool noLFNST1 = false;
2306
268k
      if (rapidLFNST && (startLfnstIdx != endLfnstIdx))
2307
0
      {
2308
0
        if (bestLfnstIdx == 2)
2309
0
        {
2310
0
          noLFNST1 = true;
2311
0
        }
2312
0
        else
2313
0
        {
2314
0
          endLfnstIdx = 1;
2315
0
        }
2316
0
      }
2317
2318
980k
      for (int lfnstIdxj = startLfnstIdx; lfnstIdxj <= endLfnstIdx; lfnstIdxj++)
2319
712k
      {
2320
712k
        if (rapidLFNST && noLFNST1 && (lfnstIdxj == 1))
2321
0
        {
2322
0
          continue;
2323
0
        }
2324
712k
        currTU.cu->lfnstIdx = lfnstIdxj;
2325
712k
        std::vector<int> jointCbfMasksToTest;
2326
712k
        if (TU::getCbf(tmpTU, COMP_Cb) || TU::getCbf(tmpTU, COMP_Cr))
2327
254k
        {
2328
254k
          jointCbfMasksToTest = m_pcTrQuant->selectICTCandidates(currTU, m_orgResiCb, m_orgResiCr);
2329
254k
        }
2330
712k
        for (int cbfMask : jointCbfMasksToTest)
2331
254k
        {
2332
254k
          currTU.jointCbCr = (uint8_t)cbfMask;
2333
254k
          ComponentID codeCompId = ((currTU.jointCbCr >> 1) ? COMP_Cb : COMP_Cr);
2334
254k
          ComponentID otherCompId = ((codeCompId == COMP_Cb) ? COMP_Cr : COMP_Cb);
2335
254k
          bool tsAllowed = useTS && TU::isTSAllowed(currTU, codeCompId) && (m_pcEncCfg->m_useChromaTS) && !currTU.cu->lfnstIdx && !cu.bdpcmM[CH_C];
2336
254k
          if ((partitioner.chType == CH_L)&& tsAllowed && (currTU.mtsIdx[COMP_Y] != MTS_SKIP))
2337
0
          {
2338
0
            tsAllowed = false;
2339
0
          }
2340
254k
          if (!tsAllowed)
2341
254k
          {
2342
254k
            checkTSOnly = false;
2343
254k
          }
2344
254k
          uint8_t     numTransformCands = 1 + (tsAllowed && !(checkDCTOnly || checkTSOnly)? 1 : 0); // DCT + TS = 2 tests
2345
254k
          TrModeList trModes;
2346
254k
          if (numTransformCands > 1)
2347
0
          {
2348
0
            trModes.push_back(TrMode(0, true)); // DCT2
2349
0
            trModes.push_back(TrMode(1, true));//TS
2350
0
          }
2351
254k
          else
2352
254k
          {
2353
254k
            currTU.mtsIdx[codeCompId] = checkTSOnly || currTU.cu->bdpcmM[CH_C] ? 1 : 0;
2354
254k
          }
2355
2356
508k
          for (int modeId = 0; modeId < numTransformCands; modeId++)
2357
254k
          {
2358
254k
            Distortion distTmp = 0;
2359
254k
            currTU.mtsIdx[codeCompId] = currTU.cu->bdpcmM[CH_C] ? MTS_SKIP : MTS_DCT2_DCT2;
2360
254k
            if (numTransformCands > 1)
2361
0
            {
2362
0
              currTU.mtsIdx[codeCompId] = currTU.cu->bdpcmM[CH_C] ? MTS_SKIP : trModes[modeId].first;
2363
0
            }
2364
254k
            currTU.mtsIdx[otherCompId] = MTS_DCT2_DCT2;
2365
2366
254k
            m_CABACEstimator->getCtx() = ctxStartTU;
2367
2368
254k
            resiCb.copyFrom(m_orgResiCb[cbfMask]);
2369
254k
            resiCr.copyFrom(m_orgResiCr[cbfMask]);
2370
254k
            if ((modeId == 0) && (numTransformCands > 1))
2371
0
            {
2372
0
              xPreCheckMTS(currTU, &trModes, m_pcEncCfg->m_MTSIntraMaxCand, 0, COMP_Cb);
2373
0
              currTU.mtsIdx[codeCompId] = trModes[modeId].first;
2374
0
              currTU.mtsIdx[(codeCompId == COMP_Cr) ? COMP_Cb : COMP_Cr] = MTS_DCT2_DCT2;
2375
0
            }
2376
254k
            cuCtx.lfnstLastScanPos = false;
2377
254k
            cuCtx.violatesLfnstConstrained[CH_L] = false;
2378
254k
            cuCtx.violatesLfnstConstrained[CH_C] = false;
2379
254k
            if (numTransformCands > 1)
2380
0
            {
2381
0
              xIntraCodingTUBlock(currTU, COMP_Cb, false, distTmp, 0, 0, true);
2382
0
              if ((modeId == 0) && !trModes[modeId + 1].second)
2383
0
              {
2384
0
                numTransformCands = 1;
2385
0
              }
2386
0
            }
2387
254k
            else
2388
254k
            {
2389
254k
              xIntraCodingTUBlock(currTU, COMP_Cb, false, distTmp, 0);
2390
254k
            }
2391
2392
254k
            double costTmp = std::numeric_limits<double>::max();
2393
254k
            if (distTmp < MAX_DISTORTION)
2394
250k
            {
2395
250k
              uint64_t bits = xGetIntraFracBitsQTChroma(currTU, COMP_Cb, &cuCtx);
2396
250k
              costTmp = m_pcRdCost->calcRdCost(bits, distTmp);
2397
250k
            }
2398
3.46k
            else if (!currTU.mtsIdx[codeCompId])
2399
3.46k
            {
2400
3.46k
              numTransformCands = 1;
2401
3.46k
            }
2402
254k
            bool rootCbfL = false;
2403
1.01M
            for (uint32_t t = 0; t < getNumberValidTBlocks(*cs.pcv); t++)
2404
762k
            {
2405
762k
              rootCbfL |= bool(tmpTU.cbf[t]);
2406
762k
            }
2407
254k
            if (rapidLFNST && !rootCbfL)
2408
0
            {
2409
0
              endLfnstIdx = lfnstIdxj;
2410
0
            }
2411
254k
            if (testLFNST && currTU.cu->lfnstIdx && !cuCtx.lfnstLastScanPos)
2412
3.40k
            {
2413
3.40k
              bool cbfAtZeroDepth = CU::isSepTree(*currTU.cu) ? rootCbfL
2414
3.40k
                : (cs.area.chromaFormat != CHROMA_400 && std::min(tmpTU.blocks[1].width, tmpTU.blocks[1].height) < 4)
2415
0
                ? TU::getCbfAtDepth(currTU, COMP_Y, currTU.depth) : rootCbfL;
2416
3.40k
              if (cbfAtZeroDepth)
2417
3.40k
              {
2418
3.40k
                costTmp = MAX_DOUBLE;
2419
3.40k
              }
2420
3.40k
            }
2421
254k
            if (costTmp < bestCostCbCr)
2422
95.6k
            {
2423
95.6k
              bestCostCbCr = costTmp;
2424
95.6k
              bestDistCbCr = distTmp;
2425
95.6k
              bestJointCbCr = currTU.jointCbCr;
2426
2427
              // store data
2428
95.6k
              bestLfnstIdx = lfnstIdxj;
2429
95.6k
              if ((cbfMask != jointCbfMasksToTest.back() || (lfnstIdxj != endLfnstIdx)) || (modeId != (numTransformCands - 1)))
2430
77.9k
              {
2431
77.9k
                saveCS.getRecoBuf(cbArea).copyFrom(cs.getRecoBuf(cbArea));
2432
77.9k
                saveCS.getRecoBuf(crArea).copyFrom(cs.getRecoBuf(crArea));
2433
2434
77.9k
                tmpTU.copyComponentFrom(currTU, COMP_Cb);
2435
77.9k
                tmpTU.copyComponentFrom(currTU, COMP_Cr);
2436
2437
77.9k
                ctxBest = m_CABACEstimator->getCtx();
2438
77.9k
              }
2439
17.7k
              else
2440
17.7k
              {
2441
17.7k
                lastIsBest = true;
2442
17.7k
                cs.cus[0]->lfnstIdx = bestLfnstIdx;
2443
17.7k
              }
2444
95.6k
            }
2445
254k
          }
2446
254k
        }
2447
2448
        // Retrieve the best CU data (unless it was the very last one tested)
2449
712k
      }
2450
268k
      if (!lastIsBest)
2451
250k
      {
2452
250k
        cs.getRecoBuf(cbArea).copyFrom(saveCS.getRecoBuf(cbArea));
2453
250k
        cs.getRecoBuf(crArea).copyFrom(saveCS.getRecoBuf(crArea));
2454
2455
250k
        cs.cus[0]->lfnstIdx = bestLfnstIdx;
2456
250k
        currTU.copyComponentFrom(tmpTU, COMP_Cb);
2457
250k
        currTU.copyComponentFrom(tmpTU, COMP_Cr);
2458
250k
        m_CABACEstimator->getCtx() = ctxBest;
2459
250k
      }
2460
268k
      currTU.jointCbCr = (TU::getCbf(currTU, COMP_Cb) || TU::getCbf(currTU, COMP_Cr)) ? bestJointCbCr : 0;
2461
268k
    } // jointCbCr
2462
2463
268k
    cs.dist += bestDistCbCr;
2464
268k
    cuCtx.violatesLfnstConstrained[CH_L] = false;
2465
268k
    cuCtx.violatesLfnstConstrained[CH_C] = false;
2466
268k
    cuCtx.lfnstLastScanPos = false;
2467
268k
    cuCtx.violatesMtsCoeffConstraint = false;
2468
268k
    cuCtx.mtsLastScanPos = false;
2469
268k
    cbfs.cbf(COMP_Cb) = TU::getCbf(currTU, COMP_Cb);
2470
268k
    cbfs.cbf(COMP_Cr) = TU::getCbf(currTU, COMP_Cr);
2471
268k
  }
2472
1
  else
2473
1
  {
2474
1
    unsigned   numValidTBlocks = getNumberValidTBlocks(*cs.pcv);
2475
1
    ChromaCbfs SplitCbfs(false);
2476
2477
1
    if (partitioner.canSplit(TU_MAX_TR_SPLIT, cs))
2478
0
    {
2479
0
      partitioner.splitCurrArea(TU_MAX_TR_SPLIT, cs);
2480
0
    }
2481
1
    else if (currTU.cu->ispMode)
2482
0
    {
2483
0
      partitioner.splitCurrArea(m_ispTestedModes[0].IspType, cs);
2484
0
    }
2485
1
    else
2486
1
      THROW("Implicit TU split not available");
2487
2488
0
    do
2489
0
    {
2490
0
      ChromaCbfs subCbfs = xIntraChromaCodingQT(cs, partitioner);
2491
2492
0
      for (uint32_t ch = COMP_Cb; ch < numValidTBlocks; ch++)
2493
0
      {
2494
0
        const ComponentID compID = ComponentID(ch);
2495
0
        SplitCbfs.cbf(compID) |= subCbfs.cbf(compID);
2496
0
      }
2497
0
    } while (partitioner.nextPart(cs));
2498
2499
0
    partitioner.exitCurrSplit();
2500
2501
    /*if (lumaUsesISP && cs.dist == MAX_UINT) //ahenkel
2502
    {
2503
      return cbfs;
2504
    }*/
2505
0
    {
2506
0
      cbfs.Cb |= SplitCbfs.Cb;
2507
0
      cbfs.Cr |= SplitCbfs.Cr;
2508
2509
0
      if (1)   //(!lumaUsesISP)
2510
0
      {
2511
0
        for (auto& ptu : cs.tus)
2512
0
        {
2513
0
          if (currArea.Cb().contains(ptu->Cb()) || (!ptu->Cb().valid() && currArea.Y().contains(ptu->Y())))
2514
0
          {
2515
0
            TU::setCbfAtDepth(*ptu, COMP_Cb, currDepth, SplitCbfs.Cb);
2516
0
            TU::setCbfAtDepth(*ptu, COMP_Cr, currDepth, SplitCbfs.Cr);
2517
0
          }
2518
0
        }
2519
0
      }
2520
0
    }
2521
0
  }
2522
268k
  return cbfs;
2523
268k
}
2524
2525
uint64_t IntraSearch::xFracModeBitsIntraLuma(const CodingUnit& cu, const unsigned* mpmLst)
2526
888k
{
2527
888k
  m_CABACEstimator->resetBits();
2528
2529
888k
  if (!cu.ciip)
2530
888k
  {
2531
888k
    m_CABACEstimator->intra_luma_pred_mode(cu, mpmLst);
2532
888k
  }
2533
2534
888k
  return m_CABACEstimator->getEstFracBits();
2535
888k
}
2536
2537
template<typename T, size_t N, int M>
2538
void IntraSearch::xReduceHadCandList(static_vector<T, N>& candModeList, static_vector<double, N>& candCostList, SortedPelUnitBufs<M>& sortedPelBuffer, int& numModesForFullRD, const double thresholdHadCost, const double* mipHadCost, const CodingUnit& cu, const bool fastMip)
2539
18.1k
{
2540
18.1k
  const int maxCandPerType = numModesForFullRD >> 1;
2541
18.1k
  static_vector<ModeInfo, FAST_UDI_MAX_RDMODE_NUM> tempRdModeList;
2542
18.1k
  static_vector<double, FAST_UDI_MAX_RDMODE_NUM> tempCandCostList;
2543
18.1k
  const double minCost = candCostList[0];
2544
18.1k
  bool keepOneMip = candModeList.size() > numModesForFullRD;
2545
18.1k
  const int maxNumConv = 3; 
2546
2547
18.1k
  int numConv = 0;
2548
18.1k
  int numMip = 0;
2549
82.3k
  for (int idx = 0; idx < candModeList.size() - (keepOneMip?0:1); idx++)
2550
64.1k
  {
2551
64.1k
    bool addMode = false;
2552
64.1k
    const ModeInfo& orgMode = candModeList[idx];
2553
2554
64.1k
    if (!orgMode.mipFlg)
2555
45.9k
    {
2556
45.9k
      addMode = (numConv < maxNumConv);
2557
45.9k
      numConv += addMode ? 1:0;
2558
45.9k
    }
2559
18.1k
    else
2560
18.1k
    {
2561
18.1k
      addMode = ( numMip < maxCandPerType || (candCostList[idx] < thresholdHadCost * minCost) || keepOneMip );
2562
18.1k
      keepOneMip = false;
2563
18.1k
      numMip += addMode ? 1:0;
2564
18.1k
    }
2565
64.1k
    if( addMode )
2566
64.1k
    {
2567
64.1k
      tempRdModeList.push_back(orgMode);
2568
64.1k
      tempCandCostList.push_back(candCostList[idx]);
2569
64.1k
    }
2570
64.1k
  }
2571
2572
  // sort Pel Buffer
2573
18.1k
  int i = -1;
2574
18.1k
  for( auto &m: tempRdModeList)
2575
64.1k
  {
2576
64.1k
    if( ! (m == candModeList.at( ++i )) )
2577
0
    {
2578
0
      for( int j = i; j < (int)candModeList.size()-1; )
2579
0
      {
2580
0
        if( m == candModeList.at( ++j ) )
2581
0
        {
2582
0
          sortedPelBuffer.swap( i, j);
2583
0
          break;
2584
0
        }
2585
0
      }
2586
0
    }
2587
64.1k
  }
2588
18.1k
  sortedPelBuffer.reduceTo( (int)tempRdModeList.size() );
2589
2590
18.1k
  if ((cu.lwidth() > 8 && cu.lheight() > 8))
2591
16.1k
  {
2592
    // Sort MIP candidates by Hadamard cost
2593
16.1k
    const int transpOff = getNumModesMip(cu.Y());
2594
16.1k
    static_vector<uint8_t, FAST_UDI_MAX_RDMODE_NUM> sortedMipModes(0);
2595
16.1k
    static_vector<double, FAST_UDI_MAX_RDMODE_NUM> sortedMipCost(0);
2596
16.1k
    for (uint8_t mode : { 0, 1, 2 })
2597
48.5k
    {
2598
48.5k
      uint8_t candMode = mode + uint8_t((mipHadCost[mode + transpOff] < mipHadCost[mode]) ? transpOff : 0);
2599
48.5k
      updateCandList(candMode, mipHadCost[candMode], sortedMipModes, sortedMipCost, 3);
2600
48.5k
    }
2601
2602
    // Append MIP mode to RD mode list
2603
16.1k
    const int modeListSize = int(tempRdModeList.size());
2604
32.3k
    for (int idx = 0; idx < 3; idx++)
2605
32.3k
    {
2606
32.3k
      const bool     isTransposed = (sortedMipModes[idx] >= transpOff ? true : false);
2607
32.3k
      const uint32_t mipIdx       = (isTransposed ? sortedMipModes[idx] - transpOff : sortedMipModes[idx]);
2608
32.3k
      const ModeInfo mipMode( true, isTransposed, 0, NOT_INTRA_SUBPARTITIONS, mipIdx );
2609
32.3k
      bool alreadyIncluded = false;
2610
129k
      for (int modeListIdx = 0; modeListIdx < modeListSize; modeListIdx++)
2611
113k
      {
2612
113k
        if (tempRdModeList[modeListIdx] == mipMode)
2613
16.1k
        {
2614
16.1k
          alreadyIncluded = true;
2615
16.1k
          break;
2616
16.1k
        }
2617
113k
      }
2618
2619
32.3k
      if (!alreadyIncluded)
2620
16.1k
      {
2621
16.1k
        tempRdModeList.push_back(mipMode);
2622
16.1k
        tempCandCostList.push_back(0);
2623
16.1k
        if( fastMip ) break;
2624
16.1k
      }
2625
32.3k
    }
2626
16.1k
  }
2627
2628
18.1k
  candModeList = tempRdModeList;
2629
18.1k
  candCostList = tempCandCostList;
2630
18.1k
  numModesForFullRD = int(candModeList.size());
2631
18.1k
}
2632
2633
void IntraSearch::xPreCheckMTS(TransformUnit &tu, TrModeList *trModes, const int maxCand, PelUnitBuf *predBuf, const ComponentID& compID)
2634
14.6k
{
2635
14.6k
  if (compID == COMP_Y)
2636
14.6k
  {
2637
14.6k
    CodingStructure&  cs = *tu.cs;
2638
14.6k
    const CompArea& area = tu.blocks[compID];
2639
14.6k
    const CodingUnit& cu = *cs.getCU(area.pos(), CH_L,TREE_D);
2640
14.6k
    PelBuf piPred = cs.getPredBuf(area);
2641
14.6k
    PelBuf piResi = cs.getResiBuf(area);
2642
2643
14.6k
    initIntraPatternChType(*tu.cu, area);
2644
14.6k
    if (predBuf)
2645
13.0k
    {
2646
13.0k
      piPred.copyFrom(predBuf->Y());
2647
13.0k
    }
2648
1.54k
    else if (CU::isMIP(cu, CH_L))
2649
1.52k
    {
2650
1.52k
      initIntraMip(cu);
2651
1.52k
      predIntraMip(piPred, cu);
2652
1.52k
    }
2653
20
    else
2654
20
    {
2655
20
      predIntraAng(COMP_Y, piPred, cu);
2656
20
    }
2657
2658
    //===== get residual signal =====
2659
14.6k
    CPelBuf piOrg = cs.getOrgBuf(COMP_Y);
2660
14.6k
    piResi.subtract(piOrg, piPred);
2661
14.6k
    m_pcTrQuant->checktransformsNxN(tu, trModes, m_pcEncCfg->m_MTSIntraMaxCand, compID);
2662
14.6k
  }
2663
0
  else
2664
0
  {
2665
0
    ComponentID codeCompId = (tu.jointCbCr ? (tu.jointCbCr >> 1 ? COMP_Cb : COMP_Cr) : compID);
2666
0
    m_pcTrQuant->checktransformsNxN(tu, trModes, m_pcEncCfg->m_MTSIntraMaxCand, codeCompId);
2667
0
  }
2668
14.6k
}
2669
2670
double IntraSearch::xTestISP(CodingStructure& cs, Partitioner& subTuPartitioner, double bestCostForISP, PartSplit ispType, bool& splitcbf, uint64_t& singleFracBits, Distortion& singleDistLuma, CUCtx& cuCtx)
2671
14.8k
{
2672
14.8k
  int  subTuCounter = 0;
2673
14.8k
  bool earlySkipISP = false;
2674
14.8k
  bool splitCbfLuma = false;
2675
14.8k
  CodingUnit& cu = *cs.cus[0];
2676
2677
14.8k
  Distortion singleDistTmpLumaSUM = 0;
2678
14.8k
  uint64_t   singleTmpFracBitsSUM = 0;
2679
14.8k
  double     singleCostTmpSUM = 0;
2680
14.8k
  cuCtx.isDQPCoded = true;
2681
14.8k
  cuCtx.isChromaQpAdjCoded = true;
2682
2683
14.8k
  do
2684
19.2k
  {
2685
19.2k
    Distortion singleDistTmpLuma = 0;
2686
19.2k
    uint64_t   singleTmpFracBits = 0;
2687
19.2k
    double     singleCostTmp = 0;
2688
19.2k
    TransformUnit& tmpTUcur = ((cs.tus.size() < (subTuCounter + 1)))
2689
19.2k
      ? cs.addTU(CS::getArea(cs, subTuPartitioner.currArea(), subTuPartitioner.chType,
2690
3.65k
        subTuPartitioner.treeType),
2691
3.65k
        subTuPartitioner.chType, cs.cus[0])
2692
19.2k
      : *cs.tus[subTuCounter];
2693
19.2k
    tmpTUcur.depth = subTuPartitioner.currTrDepth;
2694
2695
    // Encode TU
2696
19.2k
    xIntraCodingTUBlock(tmpTUcur, COMP_Y, false, singleDistTmpLuma, 0);
2697
19.2k
    cuCtx.mtsLastScanPos = false;
2698
2699
19.2k
    if (singleDistTmpLuma == MAX_INT)   // all zero CBF skip
2700
0
    {
2701
0
      earlySkipISP = true;
2702
0
      singleCostTmpSUM = MAX_DOUBLE;
2703
0
      break;
2704
0
    }
2705
2706
19.2k
    if (m_pcRdCost->calcRdCost(singleTmpFracBitsSUM, singleDistTmpLumaSUM + singleDistTmpLuma) > bestCostForISP)
2707
4.96k
    {
2708
4.96k
      earlySkipISP = true;
2709
4.96k
    }
2710
14.2k
    else
2711
14.2k
    {
2712
14.2k
      m_ispTestedModes[0].IspType = ispType;
2713
14.2k
      m_ispTestedModes[0].subTuCounter = subTuCounter;
2714
14.2k
      singleTmpFracBits = xGetIntraFracBitsQT(cs, subTuPartitioner, true, &cuCtx);
2715
14.2k
    }
2716
19.2k
    singleCostTmp = m_pcRdCost->calcRdCost(singleTmpFracBits, singleDistTmpLuma);
2717
2718
19.2k
    singleCostTmpSUM     += singleCostTmp;
2719
19.2k
    singleDistTmpLumaSUM += singleDistTmpLuma;
2720
19.2k
    singleTmpFracBitsSUM += singleTmpFracBits;
2721
2722
19.2k
    subTuCounter++;
2723
2724
19.2k
    splitCbfLuma |= TU::getCbfAtDepth( *cs.getTU(subTuPartitioner.currArea().lumaPos(), subTuPartitioner.chType, subTuCounter - 1), 
2725
19.2k
                                       COMP_Y, subTuPartitioner.currTrDepth);
2726
19.2k
    int nSubPartitions = m_ispTestedModes[cu.lfnstIdx].numTotalParts[cu.ispMode - 1];
2727
19.2k
    bool doStop = (m_pcEncCfg->m_ISP != 1) || (subTuCounter < nSubPartitions);
2728
19.2k
    if (doStop)
2729
19.2k
    {
2730
19.2k
      if (singleCostTmpSUM > bestCostForISP)
2731
12.4k
      {
2732
12.4k
        earlySkipISP = true;
2733
12.4k
        break;
2734
12.4k
      }
2735
6.83k
      if (subTuCounter < nSubPartitions)
2736
5.44k
      {
2737
5.44k
        double threshold = nSubPartitions == 2 ? 0.95 : subTuCounter == 1 ? 0.83 : 0.91;
2738
5.44k
        if (singleCostTmpSUM > bestCostForISP * threshold)
2739
1.08k
        {
2740
1.08k
          earlySkipISP = true;
2741
1.08k
          break;
2742
1.08k
        }
2743
5.44k
      }
2744
6.83k
    }
2745
19.2k
  } while (subTuPartitioner.nextPart(cs));
2746
14.8k
  singleDistLuma = singleDistTmpLumaSUM;
2747
14.8k
  singleFracBits = singleTmpFracBitsSUM;
2748
2749
14.8k
  splitcbf = splitCbfLuma;
2750
14.8k
  return earlySkipISP ? MAX_DOUBLE : singleCostTmpSUM;
2751
14.8k
}
2752
2753
int IntraSearch::xSpeedUpISP(int speed, bool& testISP, int mode, int& noISP, int& endISP, CodingUnit& cu, static_vector<ModeInfo, FAST_UDI_MAX_RDMODE_NUM>& RdModeList, const ModeInfo& bestPUMode, int bestISP, int bestLfnstIdx)
2754
13.5k
{
2755
13.5k
  if (speed)
2756
5.48k
  {
2757
5.48k
    if (mode >= 1)
2758
2.89k
    {
2759
2.89k
      if (m_ispTestedModes[0].splitIsFinished[1] && m_ispTestedModes[0].splitIsFinished[0])
2760
0
      {
2761
0
        testISP = false;
2762
0
        endISP = 0;
2763
0
      }
2764
2.89k
      else
2765
2.89k
      {
2766
2.89k
        if (m_pcEncCfg->m_ISP >= 2)
2767
2.89k
        {
2768
2.89k
          if (mode == 1) //best Hor||Ver
2769
2.58k
          {
2770
2.58k
            int bestDir = 0;
2771
7.76k
            for (int d = 0; d < 2; d++)
2772
5.17k
            {
2773
5.17k
              int d2 = d ? 0 : 1;
2774
5.17k
              if ((m_ispTestedModes[0].bestCost[d] <= m_ispTestedModes[0].bestCost[d2])
2775
4.86k
                && (m_ispTestedModes[0].bestCost[d] != MAX_DOUBLE))
2776
308
              {
2777
308
                bestDir = d + 1;
2778
308
                m_ispTestedModes[0].splitIsFinished[d2] = true;
2779
308
              }
2780
5.17k
            }
2781
2.58k
            m_ispTestedModes[0].bestModeSoFar = bestDir;
2782
2.58k
            if (m_ispTestedModes[0].bestModeSoFar <= 0)
2783
2.28k
            {
2784
2.28k
              m_ispTestedModes[0].splitIsFinished[1] = true;
2785
2.28k
              m_ispTestedModes[0].splitIsFinished[0] = true;
2786
2.28k
              testISP = false;
2787
2.28k
              endISP = 0;
2788
2.28k
            }
2789
2.58k
          }
2790
2.89k
          if (m_ispTestedModes[0].bestModeSoFar == 2)
2791
80
          {
2792
80
            noISP = 1;
2793
80
          }
2794
2.81k
          else
2795
2.81k
          {
2796
2.81k
            endISP = 1;
2797
2.81k
          }
2798
2.89k
        }
2799
2.89k
      }
2800
2.89k
    }
2801
5.48k
    if (testISP)
2802
3.20k
    {
2803
3.20k
      if (mode == 2)
2804
308
      {
2805
924
        for (int d = 0; d < 2; d++)
2806
616
        {
2807
616
          int d2 = d ? 0 : 1;
2808
616
          if (m_ispTestedModes[0].bestCost[d] == MAX_DOUBLE)
2809
283
          {
2810
283
            m_ispTestedModes[0].splitIsFinished[d] = true;
2811
283
          }
2812
616
          if ((m_ispTestedModes[0].bestCost[d2] < 1.3 * m_ispTestedModes[0].bestCost[d])
2813
333
            && (int(m_ispTestedModes[0].bestSplitSoFar) != (d + 1)))
2814
252
          {
2815
252
            if (d)
2816
212
            {
2817
212
              endISP = 1;
2818
212
            }
2819
40
            else
2820
40
            {
2821
40
              noISP = 1;
2822
40
            }
2823
252
            m_ispTestedModes[0].splitIsFinished[d] = true;
2824
252
          }
2825
616
        }
2826
308
      }
2827
2.89k
      else
2828
2.89k
      {
2829
2.89k
        if (m_ispTestedModes[0].splitIsFinished[0])
2830
40
        {
2831
40
          noISP = 1;
2832
40
        }
2833
2.89k
        if (m_ispTestedModes[0].splitIsFinished[1])
2834
268
        {
2835
268
          endISP = 1;
2836
268
        }
2837
2.89k
      }
2838
3.20k
    }
2839
5.48k
    if ((noISP == 1) && (endISP == 1))
2840
25
    {
2841
25
      endISP = 0;
2842
25
    }
2843
5.48k
  }
2844
8.03k
  else
2845
8.03k
  {
2846
8.03k
    bool stopFound = false;
2847
8.03k
    if (m_pcEncCfg->m_ISP >= 3)
2848
8.03k
    {
2849
8.03k
      if (mode)
2850
2.87k
      {
2851
2.87k
        if ((bestISP == 0) || ((bestPUMode.modeId != RdModeList[mode - 1].modeId)
2852
101
          && (bestPUMode.modeId != RdModeList[mode].modeId)))
2853
1.95k
        {
2854
1.95k
          stopFound = true;
2855
1.95k
        }
2856
2.87k
      }
2857
8.03k
    }
2858
8.03k
    if (cu.mipFlag || cu.multiRefIdx)
2859
185
    {
2860
185
      cu.mipFlag = false;
2861
185
      cu.multiRefIdx = 0;
2862
185
      if (!stopFound)
2863
0
      {
2864
0
        for (int k = 0; k < mode; k++)
2865
0
        {
2866
0
          if (cu.intraDir[CH_L] == RdModeList[k].modeId)
2867
0
          {
2868
0
            stopFound = true;
2869
0
            break;
2870
0
          }
2871
0
        }
2872
0
      }
2873
185
    }
2874
8.03k
    if (stopFound)
2875
1.95k
    {
2876
1.95k
      testISP = false;
2877
1.95k
      endISP = 0;
2878
1.95k
      return 1;
2879
1.95k
    }
2880
6.08k
    if (!stopFound && (m_pcEncCfg->m_ISP >= 2) && (cu.intraDir[CH_L] == DC_IDX))
2881
926
    {
2882
926
      stopFound = true;
2883
926
      endISP = 0;
2884
926
      return 1;
2885
926
    }
2886
6.08k
  }
2887
10.6k
  return 0;
2888
13.5k
}
2889
2890
void IntraSearch::xSpeedUpIntra(double bestcost, int& EndMode, int& speedIntra, CodingUnit& cu)
2891
23.7k
{
2892
23.7k
  int bestIdxbefore = m_ispTestedModes[0].bestIntraMode;
2893
23.7k
  if (m_ispTestedModes[0].isIntra)
2894
0
  {
2895
0
    if (bestIdxbefore == 1)//ISP
2896
0
    {
2897
0
      speedIntra = 14;
2898
0
    }
2899
0
    if (bestIdxbefore == 4)//MTS
2900
0
    {
2901
0
      speedIntra = 3;
2902
0
    }
2903
0
  }
2904
23.7k
  else if (!cu.cs->slice->isIntra())
2905
0
  {
2906
0
    if (bestcost != MAX_DOUBLE)
2907
0
    {
2908
0
      speedIntra = 10;
2909
0
    }
2910
0
  }
2911
23.7k
  if (m_ispTestedModes[0].bestBefore[0] == -1)
2912
21.1k
  {
2913
21.1k
    speedIntra |= 7;
2914
21.1k
    if (m_pcEncCfg->m_FastIntraTools == 2)
2915
0
    {
2916
0
      EndMode = 1;
2917
0
    }
2918
21.1k
  }
2919
23.7k
  if (!cu.cs->slice->isIntra())
2920
0
  {
2921
0
    if ((m_ispTestedModes[0].bestBefore[1] == 1) || (m_ispTestedModes[0].bestBefore[2] == 1))
2922
0
    {
2923
0
      speedIntra |= 2;
2924
0
    }
2925
0
    if ((m_ispTestedModes[0].bestBefore[1] == 4) || (m_ispTestedModes[0].bestBefore[2] == 4))
2926
0
    {
2927
0
      speedIntra |= 3;
2928
0
    }
2929
0
    if ((m_ispTestedModes[0].bestBefore[1] == 2) || (m_ispTestedModes[0].bestBefore[2] == 2))
2930
0
    {
2931
0
      speedIntra |= 1;
2932
0
    }
2933
0
  }
2934
23.7k
}
2935
2936
} // namespace vvenc
2937
2938
//! \}
2939