Coverage Report

Created: 2026-10-28 06:18

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
5.97k
  : m_pSaveCS       (nullptr)
68
5.97k
  , m_pcEncCfg      (nullptr)
69
5.97k
  , m_pcTrQuant     (nullptr)
70
5.97k
  , m_pcRdCost      (nullptr)
71
5.97k
  , m_CABACEstimator(nullptr)
72
5.97k
  , m_CtxCache      (nullptr)
73
5.97k
{
74
5.97k
}
75
76
void IntraSearch::init(const VVEncCfg &encCfg, TrQuant *pTrQuant, RdCost *pRdCost, SortedPelUnitBufs<SORTED_BUFS> *pSortedPelUnitBufs, XUCache &unitCache )
77
5.97k
{
78
5.97k
  IntraPrediction::init( encCfg.m_internChromaFormat, encCfg.m_internalBitDepth[ CH_L ] );
79
80
5.97k
  m_pcEncCfg          = &encCfg;
81
5.97k
  m_pcTrQuant         = pTrQuant;
82
5.97k
  m_pcRdCost          = pRdCost;
83
5.97k
  m_SortedPelUnitBufs = pSortedPelUnitBufs;
84
85
5.97k
  const ChromaFormat chrFormat = encCfg.m_internChromaFormat;
86
5.97k
  const int maxCUSize          = encCfg.m_CTUSize;
87
88
5.97k
  Area area = Area( 0, 0, maxCUSize, maxCUSize );
89
90
5.97k
  m_pTempCS = new CodingStructure( unitCache, nullptr );
91
5.97k
  m_pBestCS = new CodingStructure( unitCache, nullptr );
92
93
5.97k
  m_pTempCS->createForSearch( chrFormat, area );
94
5.97k
  m_pBestCS->createForSearch( chrFormat, area );
95
96
5.97k
  const int uiNumSaveLayersToAllocate = 3;
97
5.97k
  m_pSaveCS = new CodingStructure*[uiNumSaveLayersToAllocate];
98
23.8k
  for( int layer = 0; layer < uiNumSaveLayersToAllocate; layer++ )
99
17.9k
  {
100
17.9k
    m_pSaveCS[ layer ] = new CodingStructure( unitCache, nullptr );
101
17.9k
    m_pSaveCS[ layer ]->createForSearch( chrFormat, Area( 0, 0, maxCUSize, maxCUSize ) );
102
17.9k
    m_pSaveCS[ layer ]->initStructData();
103
17.9k
  }
104
105
5.97k
  CompArea chromaArea( COMP_Cb, chrFormat, area, true );
106
35.8k
  for( int i = 0; i < 5; i++ )
107
29.8k
  {
108
29.8k
    m_orgResiCb[i].create( chromaArea );
109
29.8k
    m_orgResiCr[i].create( chromaArea );
110
29.8k
  }
111
5.97k
}
112
113
void IntraSearch::destroy()
114
5.97k
{
115
5.97k
  if ( m_pSaveCS )
116
5.97k
  {
117
5.97k
    const int uiNumSaveLayersToAllocate = 3;
118
23.8k
    for( int layer = 0; layer < uiNumSaveLayersToAllocate; layer++ )
119
17.9k
    {
120
17.9k
      if ( m_pSaveCS[ layer ] ) { m_pSaveCS[ layer ]->destroy(); delete m_pSaveCS[ layer ]; }
121
17.9k
    }
122
5.97k
    delete[] m_pSaveCS;
123
5.97k
    m_pSaveCS = nullptr;
124
5.97k
  }
125
126
5.97k
  if( m_pTempCS )
127
5.97k
  {
128
5.97k
    m_pTempCS->destroy();
129
5.97k
    delete m_pTempCS; m_pTempCS = nullptr;
130
5.97k
  }
131
132
5.97k
  if( m_pBestCS )
133
5.97k
  {
134
5.97k
    m_pBestCS->destroy();
135
5.97k
    delete m_pBestCS; m_pBestCS = nullptr;
136
5.97k
  }
137
5.97k
}
138
139
IntraSearch::~IntraSearch()
140
5.97k
{
141
5.97k
  destroy();
142
5.97k
}
143
144
void IntraSearch::setCtuEncRsrc( CABACWriter* cabacEstimator, CtxCache *ctxCache )
145
4.97k
{
146
4.97k
  m_CABACEstimator = cabacEstimator;
147
4.97k
  m_CtxCache       = ctxCache;
148
4.97k
}
149
150
//////////////////////////////////////////////////////////////////////////
151
// INTRA PREDICTION
152
//////////////////////////////////////////////////////////////////////////
153
static constexpr double COST_UNKNOWN = -65536.0;
154
155
double IntraSearch::xFindInterCUCost( CodingUnit &cu )
156
32.4k
{
157
32.4k
  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
32.4k
  return COST_UNKNOWN;
169
32.4k
}
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
32.4k
{
177
32.4k
  PROFILER_SCOPE_AND_STAGE_EXT( 1, _TPROF, P_INTRA_EST_RD_CAND, cu.cs, CH_L );
178
32.4k
  const uint16_t intra_ctx_size = Ctx::IntraLumaMpmFlag.size() + Ctx::IntraLumaPlanarFlag.size() + Ctx::MultiRefLineIdx.size() + Ctx::ISPMode.size() + Ctx::MipFlag.size();
179
32.4k
  const TempCtx  ctxStartIntraCtx(m_CtxCache, SubCtx(CtxSet(Ctx::IntraLumaMpmFlag(), intra_ctx_size), m_CABACEstimator->getCtx()));
180
32.4k
  const double   sqrtLambdaForFirstPass = m_pcRdCost->getMotionLambda() * FRAC_BITS_SCALE;
181
32.4k
  const int numModesAvailable = NUM_LUMA_MODE; // total number of Intra modes
182
183
32.4k
  CHECK(numModesForFullRD >= numModesAvailable, "Too many modes for full RD search");
184
185
32.4k
  const SPS& sps     = *cu.cs->sps;
186
32.4k
  const bool fastMip = sps.MIP && m_pcEncCfg->m_useFastMIP;
187
188
  // this should always be true
189
32.4k
  CHECK( !cu.Y().valid(), "CU is not valid" );
190
191
32.4k
  const CompArea& area = cu.Y();
192
193
32.4k
  const UnitArea localUnitArea(area.chromaFormat, Area(0, 0, area.width, area.height));
194
32.4k
  if( testMip)
195
24.8k
  {
196
24.8k
    numModesForFullRD += fastMip ? numModesForFullRD - std::min( m_pcEncCfg->m_useFastMIP, numModesForFullRD )
197
24.8k
                                 : numModesForFullRD;
198
24.8k
    m_SortedPelUnitBufs->prepare( localUnitArea, numModesForFullRD + 1 );
199
24.8k
  }
200
7.57k
  else
201
7.57k
  {
202
7.57k
    m_SortedPelUnitBufs->prepare( localUnitArea, numModesForFullRD );
203
7.57k
  }
204
205
32.4k
  CPelBuf piOrg   = cu.cs->getOrgBuf(COMP_Y);
206
32.4k
  PelBuf piPred  = m_SortedPelUnitBufs->getTestBuf(COMP_Y);
207
208
32.4k
  DistParam distParam    = m_pcRdCost->setDistParam( piOrg, piPred, sps.bitDepths[ CH_L ], DF_HAD_2SAD); // Use HAD (SATD) cost
209
210
32.4k
  const int numHadCand = (testMip ? 2 : 1) * 3;
211
212
  //*** Derive (regular) candidates using Hadamard
213
32.4k
  cu.mipFlag = false;
214
32.4k
  cu.multiRefIdx = 0;
215
216
  //===== init pattern for luma prediction =====
217
32.4k
  initIntraPatternChType(cu, cu.Y(), true);
218
219
32.4k
  bool satdChecked[NUM_INTRA_MODE] = { false };
220
221
32.4k
  const unsigned* mpmLst = m_searchMpmLst;   // derived for this CU in estIntraPredLumaQT
222
223
32.4k
  const int decMsk = ( 1 << m_pcEncCfg->m_IntraEstDecBit ) - 1;
224
225
32.4k
  m_parentCandList.resize( 0 );
226
32.4k
  m_parentCandList.reserve( ( numModesAvailable >> m_pcEncCfg->m_IntraEstDecBit ) + 2 );
227
228
2.20M
  for( unsigned mode = 0; mode < numModesAvailable; mode++ )
229
2.17M
  {
230
    // Skip checking extended Angular modes in the first round of SATD
231
2.17M
    if( mode > DC_IDX && ( mode & decMsk ) )
232
1.58M
    {
233
1.58M
      continue;
234
1.58M
    }
235
236
583k
    m_parentCandList.push_back( ModeInfo( false, false, 0, NOT_INTRA_SUBPARTITIONS, mode ) );
237
583k
  }
238
   
239
129k
  for( int decDst = 1 << m_pcEncCfg->m_IntraEstDecBit; decDst > 0; decDst >>= 1 )
240
97.2k
  {
241
875k
    for( unsigned idx = 0; idx < m_parentCandList.size(); idx++ )
242
778k
    {
243
778k
      int modeParent = m_parentCandList[idx].modeId;
244
245
778k
      int off = decDst & decMsk;
246
778k
      int inc = decDst << 1;
247
248
778k
#if 1 // INTRA_AS_IN_VTM
249
778k
      if( off != 0 && ( modeParent <= ( DC_IDX + 1 ) || modeParent >= ( NUM_LUMA_MODE - 1 ) ) )
250
126k
      {
251
126k
        continue;
252
126k
      }
253
254
651k
#endif
255
1.37M
      for( int mode = modeParent - off; mode < modeParent + off + 1; mode += inc )
256
718k
      {
257
718k
        if( satdChecked[mode] || mode < 0 || mode >= NUM_LUMA_MODE )
258
2.72k
        {
259
2.72k
          continue;
260
2.72k
        }
261
262
716k
        cu.intraDir[0] = mode;
263
264
716k
        initPredIntraParams( cu, cu.Y(), sps );
265
716k
        distParam.cur.buf = piPred.buf = m_SortedPelUnitBufs->getTestBuf().Y().buf;
266
716k
        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
716k
        Distortion minSadHad = distParam.distFunc( distParam );
271
272
716k
        uint64_t fracModeBits = xFracModeBitsIntraLuma( cu, mpmLst );
273
274
        //restore ctx
275
716k
        m_CABACEstimator->getCtx() = SubCtx( CtxSet( Ctx::IntraLumaMpmFlag(), intra_ctx_size ), ctxStartIntraCtx );
276
277
716k
        double cost = ( double ) minSadHad + ( double ) fracModeBits * sqrtLambdaForFirstPass;
278
716k
        DTRACE( g_trace_ctx, D_INTRA_COST, "IntraHAD: %u, %llu, %f (%d)\n", minSadHad, fracModeBits, cost, mode );
279
280
716k
        int insertPos = -1;
281
716k
        updateCandList( ModeInfo( false, false, 0, NOT_INTRA_SUBPARTITIONS, mode ), cost, RdModeList, CandCostList, numModesForFullRD, &insertPos );
282
716k
        updateCandList( ModeInfo( false, false, 0, NOT_INTRA_SUBPARTITIONS, mode ), ( double ) minSadHad, HadModeList, CandHadList, numHadCand );
283
716k
        m_SortedPelUnitBufs->insert( insertPos, ( int ) RdModeList.size() );
284
285
716k
        satdChecked[mode] = true;
286
716k
      }
287
651k
    }
288
289
97.2k
    m_parentCandList.resize( RdModeList.size() );
290
97.2k
    std::copy( RdModeList.cbegin(), RdModeList.cend(), m_parentCandList.begin() );
291
97.2k
  }
292
293
32.4k
  const bool isFirstLineOfCtu = (((cu.block(COMP_Y).y)&((cu.cs->sps)->CTUSize - 1)) == 0);
294
32.4k
  if( m_pcEncCfg->m_MRL && ! isFirstLineOfCtu )
295
19.6k
  {
296
19.6k
    cu.multiRefIdx = 1;
297
19.6k
    unsigned  multiRefMPM [NUM_MOST_PROBABLE_MODES];
298
19.6k
    CU::getIntraMPMs(cu, multiRefMPM);
299
300
58.8k
    for (int mRefNum = 1; mRefNum < MRL_NUM_REF_LINES; mRefNum++)
301
39.2k
    {
302
39.2k
      int multiRefIdx = MULTI_REF_LINE_IDX[mRefNum];
303
304
39.2k
      cu.multiRefIdx = multiRefIdx;
305
39.2k
      initIntraPatternChType(cu, cu.Y(), true);
306
307
235k
      for (int x = 1; x < NUM_MOST_PROBABLE_MODES; x++)
308
196k
      {
309
196k
        cu.intraDir[0] = multiRefMPM[x];
310
196k
        initPredIntraParams(cu, cu.Y(), sps);
311
196k
        distParam.cur.buf = piPred.buf = m_SortedPelUnitBufs->getTestBuf().Y().buf;
312
196k
        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
196k
        Distortion minSadHad = distParam.distFunc(distParam);
317
318
        // NB xFracModeBitsIntra will not affect the mode for chroma that may have already been pre-estimated.
319
196k
        uint64_t fracModeBits = xFracModeBitsIntraLuma( cu, mpmLst );
320
321
        //restore ctx
322
196k
        m_CABACEstimator->getCtx() = SubCtx(CtxSet(Ctx::IntraLumaMpmFlag(), intra_ctx_size), ctxStartIntraCtx);
323
324
196k
        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
196k
        int insertPos = -1;
328
196k
        updateCandList( ModeInfo( false, false, multiRefIdx, NOT_INTRA_SUBPARTITIONS, cu.intraDir[0] ), cost, RdModeList,  CandCostList, numModesForFullRD, &insertPos );
329
196k
        updateCandList( ModeInfo( false, false, multiRefIdx, NOT_INTRA_SUBPARTITIONS, cu.intraDir[0] ), (double)minSadHad, HadModeList, CandHadList,  numHadCand );
330
196k
        m_SortedPelUnitBufs->insert(insertPos, (int)RdModeList.size());
331
196k
      }
332
39.2k
    }
333
19.6k
    cu.multiRefIdx = 0;
334
19.6k
  }
335
336
32.4k
  if (testMip)
337
24.8k
  {
338
24.8k
    cu.mipFlag = true;
339
24.8k
    cu.multiRefIdx = 0;
340
341
24.8k
    double mipHadCost[MAX_NUM_MIP_MODE] = { MAX_DOUBLE };
342
343
24.8k
    initIntraPatternChType(cu, cu.Y());
344
24.8k
    initIntraMip( cu );
345
346
24.8k
    const int transpOff    = getNumModesMip( cu.Y() );
347
24.8k
    const int numModesFull = (transpOff << 1);
348
325k
    for( uint32_t uiModeFull = 0; uiModeFull < numModesFull; uiModeFull++ )
349
300k
    {
350
300k
      const bool     isTransposed = (uiModeFull >= transpOff ? true : false);
351
300k
      const uint32_t uiMode       = (isTransposed ? uiModeFull - transpOff : uiModeFull);
352
353
300k
      cu.mipTransposedFlag = isTransposed;
354
300k
      cu.intraDir[CH_L] = uiMode;
355
300k
      distParam.cur.buf = piPred.buf = m_SortedPelUnitBufs->getTestBuf().Y().buf;
356
300k
      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
300k
      Distortion minSadHad = distParam.distFunc(distParam);
361
362
300k
      uint64_t fracModeBits = xFracModeBitsIntraLuma( cu, mpmLst );
363
364
      //restore ctx
365
300k
      m_CABACEstimator->getCtx() = SubCtx(CtxSet(Ctx::IntraLumaMpmFlag(), intra_ctx_size), ctxStartIntraCtx);
366
367
300k
      double cost = double(minSadHad) + double(fracModeBits) * sqrtLambdaForFirstPass;
368
300k
      mipHadCost[uiModeFull] = cost;
369
300k
      DTRACE(g_trace_ctx, D_INTRA_COST, "IntraMIP: %u, %llu, %f (%d)\n", minSadHad, fracModeBits, cost, uiModeFull);
370
371
300k
      int insertPos = -1;
372
300k
      updateCandList( ModeInfo( true, isTransposed, 0, NOT_INTRA_SUBPARTITIONS, cu.intraDir[0] ), cost, RdModeList,  CandCostList, numModesForFullRD+1, &insertPos );
373
300k
      updateCandList( ModeInfo( true, isTransposed, 0, NOT_INTRA_SUBPARTITIONS, cu.intraDir[0] ), 0.8*(double)minSadHad, HadModeList, CandHadList,  numHadCand );
374
300k
      m_SortedPelUnitBufs->insert(insertPos, (int)RdModeList.size());
375
300k
    }
376
377
24.8k
    const double thresholdHadCost = 1.0 + 1.4 / sqrt((double)(cu.lwidth()*cu.lheight()));
378
24.8k
    xReduceHadCandList(RdModeList, CandCostList, *m_SortedPelUnitBufs, numModesForFullRD, thresholdHadCost, mipHadCost, cu, fastMip);
379
24.8k
  }
380
381
32.4k
  if( m_pcEncCfg->m_bFastUDIUseMPMEnabled )
382
32.4k
  {
383
32.4k
    const int numMPMs = NUM_MOST_PROBABLE_MODES;
384
32.4k
    unsigned  intraMpms[numMPMs];
385
386
32.4k
    cu.multiRefIdx = 0;
387
388
32.4k
    const int numCand = CU::getIntraMPMs( cu, intraMpms );
389
32.4k
    ModeInfo mostProbableMode(false, false, 0, NOT_INTRA_SUBPARTITIONS, 0);
390
391
65.6k
    for( int j = 0; j < numCand; j++ )
392
33.2k
    {
393
33.2k
      bool mostProbableModeIncluded = false;
394
33.2k
      mostProbableMode.modeId = intraMpms[j];
395
396
169k
      for( int i = 0; i < numModesForFullRD; i++ )
397
136k
      {
398
136k
        mostProbableModeIncluded |= ( mostProbableMode == RdModeList[i] );
399
136k
      }
400
33.2k
      if( !mostProbableModeIncluded )
401
179
      {
402
179
        numModesForFullRD++;
403
179
        RdModeList.push_back( mostProbableMode );
404
179
        CandCostList.push_back(0);
405
179
      }
406
33.2k
    }
407
32.4k
  }
408
32.4k
}
409
410
bool IntraSearch::estIntraPredLumaQT(CodingUnit &cu, Partitioner &partitioner, double bestCost)
411
32.4k
{
412
32.4k
  CU::getIntraMPMs( cu, m_searchMpmLst );
413
32.4k
  m_searchMpmArea  = cu.Y();
414
32.4k
  m_searchMpmValid = true;
415
416
32.4k
  const bool validReturn = xEstIntraPredLumaQT( cu, partitioner, bestCost );
417
418
32.4k
  m_searchMpmValid = false;
419
32.4k
  return validReturn;
420
32.4k
}
421
422
bool IntraSearch::xEstIntraPredLumaQT(CodingUnit &cu, Partitioner &partitioner, double bestCost)
423
32.4k
{
424
32.4k
  CodingStructure       &cs           = *cu.cs;
425
32.4k
  const int             width         = partitioner.currArea().lwidth();
426
32.4k
  const int             height        = partitioner.currArea().lheight();
427
428
  //===== loop over partitions =====
429
430
32.4k
  const TempCtx ctxStart           ( m_CtxCache, m_CABACEstimator->getCtx() );
431
432
  // variables for saving fast intra modes scan results across multiple LFNST passes
433
32.4k
  double costInterCU = xFindInterCUCost( cu );
434
435
32.4k
  bool validReturn = false;
436
437
  //===== determine set of modes to be tested (using prediction signal only) =====
438
32.4k
  int numModesAvailable = NUM_LUMA_MODE; // total number of Intra modes
439
32.4k
  static_vector<ModeInfo, FAST_UDI_MAX_RDMODE_NUM> RdModeList;
440
32.4k
  static_vector<ModeInfo, FAST_UDI_MAX_RDMODE_NUM> HadModeList;
441
32.4k
  static_vector<double, FAST_UDI_MAX_RDMODE_NUM> CandCostList;
442
32.4k
  static_vector<double, FAST_UDI_MAX_RDMODE_NUM> CandHadList;
443
444
32.4k
  int numModesForFullRD = g_aucIntraModeNumFast_UseMPM_2D[Log2(width) - MIN_CU_LOG2][Log2(height) - MIN_CU_LOG2];
445
32.4k
  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
32.4k
  const SPS& sps = *cu.cs->sps;
452
32.4k
  const bool mipAllowed = sps.MIP && cu.lwidth() <= sps.getMaxTbSize() && cu.lheight() <= sps.getMaxTbSize() && ((cu.lfnstIdx == 0) || allowLfnstWithMip(cu.lumaSize()));
453
32.4k
  const int SizeThr     = 8 >> std::max( 0, m_pcEncCfg->m_useFastMIP - 1 );
454
32.4k
  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
32.4k
  bool testISP = sps.ISP && CU::canUseISP(width, height, cu.cs->sps->getMaxTbSize());
456
32.4k
  if (testISP)
457
32.4k
  {
458
32.4k
    int numTotalPartsHor = (int)width >> floorLog2(CU::getISPSplitDim(width, height, TU_1D_VERT_SPLIT));
459
32.4k
    int numTotalPartsVer = (int)height >> floorLog2(CU::getISPSplitDim(width, height, TU_1D_HORZ_SPLIT));
460
32.4k
    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
32.4k
    numTotalPartsHor = sps.LFNST && CU::canUseLfnstWithISP(cu.Y(), HOR_INTRA_SUBPARTITIONS) ? numTotalPartsHor : 0;
464
32.4k
    numTotalPartsVer = sps.LFNST && CU::canUseLfnstWithISP(cu.Y(), VER_INTRA_SUBPARTITIONS) ? numTotalPartsVer : 0;
465
97.2k
    for (int j = 1; j < NUM_LFNST_NUM_PER_SET; j++)
466
64.8k
    {
467
64.8k
      m_ispTestedModes[j].init(numTotalPartsHor, numTotalPartsVer, 0);
468
64.8k
    }
469
32.4k
    testISP = m_ispTestedModes[0].numTotalParts[0];
470
32.4k
  }
471
0
  else
472
0
  {
473
0
    m_ispTestedModes[0].init(0, 0, 0);
474
0
  }
475
476
32.4k
  xEstimateLumaRdModeList(numModesForFullRD, RdModeList, HadModeList, CandCostList, CandHadList, cu, testMip);
477
478
32.4k
  CHECK( (size_t)numModesForFullRD != RdModeList.size(), "Inconsistent state!" );
479
480
  // after this point, don't use numModesForFullRD
481
32.4k
  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
32.4k
  ModeInfo bestPUMode;
524
525
32.4k
  CodingStructure *csTemp = m_pTempCS;
526
32.4k
  CodingStructure *csBest = m_pBestCS;
527
528
32.4k
  csTemp->slice   = csBest->slice   = cs.slice;
529
32.4k
  csTemp->picture = csBest->picture = cs.picture;
530
32.4k
  csTemp->compactResize( cu );
531
32.4k
  csBest->compactResize( cu );
532
32.4k
  csTemp->initStructData();
533
32.4k
  csBest->initStructData();
534
535
32.4k
  int   bestLfnstIdx  = 0;
536
32.4k
  const bool useBDPCM = cs.picture->useBDPCM;
537
32.4k
  int   NumBDPCMCand  = (useBDPCM && sps.BDPCM && CU::bdpcmAllowed(cu, ComponentID(partitioner.chType))) ? 2 : 0;
538
32.4k
  int   bestbdpcmMode = 0;
539
32.4k
  int   bestISP       = 0;
540
32.4k
  int   bestMrl       = 0;
541
32.4k
  bool  bestMip       = 0;
542
32.4k
  int   EndMode       = (int)RdModeList.size();
543
32.4k
  bool  useISPlfnst   = testISP && sps.LFNST;
544
32.4k
  bool  noLFNST_ts    = false;
545
32.4k
  double bestCostIsp[2] = { MAX_DOUBLE, MAX_DOUBLE };
546
32.4k
  bool disableMTS = false;
547
32.4k
  bool disableLFNST = false;
548
32.4k
  bool disableDCT2test = false;
549
32.4k
  if (m_pcEncCfg->m_FastIntraTools)
550
32.4k
  {
551
32.4k
    int speedIntra = 0;
552
32.4k
    xSpeedUpIntra(bestCost, EndMode, speedIntra, cu);
553
32.4k
    disableMTS = (speedIntra >> 2 ) & 0x1;
554
32.4k
    disableLFNST = (speedIntra >> 1) & 0x1;
555
32.4k
    disableDCT2test = speedIntra>>3;
556
32.4k
    if (disableLFNST)
557
29.1k
    {
558
29.1k
      noLFNST_ts = true;
559
29.1k
      useISPlfnst = false;
560
29.1k
    }
561
32.4k
    if (speedIntra & 0x1)
562
29.1k
    {
563
29.1k
      testISP = false;
564
29.1k
    }
565
32.4k
  }
566
567
174k
  for (int mode_cur = 0; mode_cur < EndMode + NumBDPCMCand; mode_cur++)
568
141k
  {
569
141k
    int mode = mode_cur;
570
141k
    if (mode_cur >= EndMode)
571
8.65k
    {
572
8.65k
      mode = mode_cur - EndMode ? -1 : -2;
573
8.65k
      testISP = false;
574
8.65k
    }
575
    // set CU/PU to luma prediction mode
576
141k
    ModeInfo testMode;
577
141k
    int noISP = 0;
578
141k
    int endISP = testISP ? 2 : 0;
579
141k
    bool noLFNST = false || noLFNST_ts;
580
141k
    if (mode && useISPlfnst)
581
10.8k
    {
582
10.8k
      noLFNST |= (bestCostIsp[0] > (bestCostIsp[1] * 1.4));
583
10.8k
      if (mode > 2)
584
2.96k
      {
585
2.96k
        endISP = 0;
586
2.96k
        testISP = false;
587
2.96k
      }
588
10.8k
    }
589
141k
    if (testISP)
590
6.91k
    {
591
6.91k
      xSpeedUpISP(1, testISP, mode, noISP, endISP, cu, RdModeList, bestPUMode, bestISP, bestLfnstIdx);
592
6.91k
    }
593
141k
    int startISP = 0;
594
141k
    if (disableDCT2test && mode && bestISP)
595
0
    {
596
0
      startISP = endISP ? 1 : 0;
597
0
    }
598
293k
    for (int ispM = startISP; ispM <= endISP; ispM++)
599
151k
    {
600
151k
      if (ispM && (ispM == noISP))
601
51
      {
602
51
        continue;
603
51
      }
604
605
151k
      if (mode < 0)
606
8.65k
      {
607
8.65k
        cu.bdpcmM[CH_L] = -mode;
608
8.65k
        testMode = ModeInfo(false, false, 0, NOT_INTRA_SUBPARTITIONS, cu.bdpcmM[CH_L] == 2 ? VER_IDX : HOR_IDX);
609
8.65k
      }
610
143k
      else
611
143k
      {
612
143k
        testMode = RdModeList[mode];
613
143k
        cu.bdpcmM[CH_L] = 0;
614
143k
      }
615
616
151k
      cu.ispMode = ispM;
617
151k
      cu.mipFlag = testMode.mipFlg;
618
151k
      cu.mipTransposedFlag = testMode.mipTrFlg;
619
151k
      cu.multiRefIdx = testMode.mRefId;
620
151k
      cu.intraDir[CH_L] = testMode.modeId;
621
151k
      if (cu.ispMode && xSpeedUpISP(0, testISP, mode, noISP, endISP, cu, RdModeList, bestPUMode, bestISP, 0) )
622
3.60k
      {
623
3.60k
        continue;
624
3.60k
      }
625
148k
      if (m_pcEncCfg->m_FastIntraTools && (cu.ispMode || sps.LFNST || sps.MTS))
626
148k
      {
627
148k
        m_ispTestedModes[0].intraWasTested = true;
628
148k
      }
629
148k
      CHECK(cu.mipFlag && cu.multiRefIdx, "Error: combination of MIP and MRL not supported");
630
148k
      CHECK(cu.multiRefIdx && (cu.intraDir[0] == PLANAR_IDX), "Error: combination of MRL and Planar mode not supported");
631
148k
      CHECK(cu.ispMode && cu.mipFlag, "Error: combination of ISP and MIP not supported");
632
148k
      CHECK(cu.ispMode && cu.multiRefIdx, "Error: combination of ISP and MRL not supported");
633
634
      // determine residual for partition
635
148k
      cs.initSubStructure(*csTemp, partitioner.chType, cs.area, true);
636
148k
      int doISP = (((cu.ispMode == 0) && noLFNST) || (useISPlfnst && mode && cu.ispMode && (bestLfnstIdx == 0)) || disableLFNST) ? -mode : mode;
637
148k
      xIntraCodingLumaQT(*csTemp, partitioner, m_SortedPelUnitBufs->getBufFromSortedList(mode), bestCost, doISP, disableMTS);
638
639
148k
      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
148k
        cu.blocks[0].y, width, height, csTemp->cost, testMode.modeId, testMode.ispMod,
641
148k
        cu.multiRefIdx, cu.mipFlag, cu.lfnstIdx, cu.mtsFlag);
642
643
148k
      if (cu.ispMode && !csTemp->cus[0]->firstTU->cbf[COMP_Y])
644
2.38k
      {
645
2.38k
        csTemp->cost = MAX_DOUBLE;
646
2.38k
        csTemp->costDbOffset = 0;
647
2.38k
      }
648
148k
      if (useISPlfnst)
649
20.6k
      {
650
20.6k
        int n = (cu.ispMode == 0) ? 0 : 1;
651
20.6k
        bestCostIsp[n] = csTemp->cost < bestCostIsp[n] ? csTemp->cost : bestCostIsp[n];
652
20.6k
      }
653
654
      // check r-d cost
655
148k
      if (csTemp->cost < csBest->cost)
656
40.0k
      {
657
40.0k
        validReturn   = true;
658
40.0k
        std::swap(csTemp, csBest);
659
40.0k
        bestPUMode    = testMode;
660
40.0k
        bestLfnstIdx  = csBest->cus[0]->lfnstIdx;
661
40.0k
        bestISP       = csBest->cus[0]->ispMode;
662
40.0k
        bestMip       = csBest->cus[0]->mipFlag;
663
40.0k
        bestMrl       = csBest->cus[0]->multiRefIdx;
664
40.0k
        bestbdpcmMode = cu.bdpcmM[CH_L];
665
40.0k
        m_ispTestedModes[bestLfnstIdx].bestSplitSoFar = ISPType(bestISP);
666
40.0k
        if (csBest->cost < bestCost)
667
40.0k
        {
668
40.0k
          bestCost = csBest->cost;
669
40.0k
        }
670
40.0k
        if ((csBest->getTU(partitioner.chType)->mtsIdx[COMP_Y] == MTS_SKIP) && ( floorLog2(csBest->getTU(partitioner.chType)->blocks[COMP_Y].area()) >= 6 ))
671
4.94k
        {
672
4.94k
          noLFNST_ts = 1;
673
4.94k
        }
674
40.0k
      }
675
676
      // reset context models
677
148k
      m_CABACEstimator->getCtx() = ctxStart;
678
679
148k
      csTemp->releaseIntermediateData();
680
681
148k
      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
148k
    }
691
141k
  } // Mode loop
692
693
32.4k
  if (m_pcEncCfg->m_FastIntraTools && (sps.ISP|| sps.LFNST || sps.MTS))
694
32.4k
  {
695
32.4k
    int bestMode = csBest->getTU(partitioner.chType)->mtsIdx[COMP_Y] ? 4 : 0;
696
32.4k
    bestMode |= bestLfnstIdx ? 2 : 0;
697
32.4k
    bestMode |= bestISP ? 1 : 0;
698
32.4k
    m_ispTestedModes[0].bestIntraMode = bestMode;
699
32.4k
  }
700
32.4k
  cu.ispMode = bestISP;
701
32.4k
  if( validReturn )
702
32.4k
  {
703
32.4k
    cs.useSubStructure( *csBest, partitioner.chType, TREE_D, cu.singleChan( CH_L ), true );
704
705
    //=== update PU data ====
706
32.4k
    cu.lfnstIdx           = bestLfnstIdx;
707
32.4k
    cu.mipTransposedFlag  = bestPUMode.mipTrFlg;
708
32.4k
    cu.intraDir[CH_L]     = bestPUMode.modeId;
709
32.4k
    cu.bdpcmM[CH_L]       = bestbdpcmMode;
710
32.4k
    cu.mipFlag            = bestMip;
711
32.4k
    cu.multiRefIdx        = bestMrl;
712
32.4k
  }
713
0
  else
714
0
  {
715
0
    THROW("fix this");
716
0
  }
717
718
32.4k
  csBest->releaseIntermediateData();
719
720
32.4k
  return validReturn;
721
32.4k
}
722
723
void IntraSearch::estIntraPredChromaQT( CodingUnit& cu, Partitioner& partitioner, const double maxCostAllowed )
724
72.5k
{
725
72.5k
  PROFILER_SCOPE_AND_STAGE_EXT( 0, _TPROF, P_INTRA_CHROMA, cu.cs, CH_C );
726
72.5k
  const TempCtx ctxStart( m_CtxCache, m_CABACEstimator->getCtx() );
727
72.5k
  CodingStructure &cs   = *cu.cs;
728
72.5k
  bool lumaUsesISP      = !CU::isSepTree(cu) && cu.ispMode;
729
72.5k
  PartSplit ispType     = lumaUsesISP ? CU::getISPType(cu, COMP_Y) : TU_NO_ISP;
730
72.5k
  double bestCostSoFar  = maxCostAllowed;
731
72.5k
  const uint32_t numberValidComponents = getNumberValidComponents( cu.chromaFormat );
732
72.5k
  const bool useBDPCM   = cs.picture->useBDPCM;
733
734
72.5k
  uint32_t   uiBestMode = 0;
735
72.5k
  Distortion uiBestDist = 0;
736
72.5k
  double     dBestCost  = MAX_DOUBLE;
737
738
  //----- init mode list ----
739
72.5k
  {
740
72.5k
    uint32_t  uiMinMode = 0;
741
72.5k
    uint32_t  uiMaxMode = NUM_CHROMA_MODE;
742
743
72.5k
    const int reducedModeNumber = uiMaxMode >> (m_pcEncCfg->m_reduceIntraChromaModesFullRD ? 1 : 2);
744
    //----- check chroma modes -----
745
72.5k
    uint32_t chromaCandModes[ NUM_CHROMA_MODE ];
746
72.5k
    CU::getIntraChromaCandModes( cu, chromaCandModes );
747
748
    // create a temporary CS
749
72.5k
    CodingStructure &saveCS = *m_pSaveCS[0];
750
72.5k
    saveCS.pcv      = cs.pcv;
751
72.5k
    saveCS.picture  = cs.picture;
752
72.5k
    saveCS.area.repositionTo( cs.area );
753
72.5k
    saveCS.clearTUs();
754
755
72.5k
    if( !CU::isSepTree(cu) && cu.ispMode )
756
0
    {
757
0
      saveCS.clearCUs();
758
0
    }
759
760
72.5k
    if( CU::isSepTree(cu) )
761
72.5k
    {
762
72.5k
      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
72.5k
      else
774
72.5k
        cs.addTU( CS::getArea( cs, partitioner.currArea(), partitioner.chType, partitioner.treeType ), partitioner.chType, &cu );
775
72.5k
    }
776
777
    // create a store for the TUs
778
72.5k
    std::vector<TransformUnit*> orgTUs;
779
72.5k
    for( const auto &ptu : cs.tus )
780
72.5k
    {
781
      // for split TUs in HEVC, add the TUs without Chroma parts for correct setting of Cbfs
782
72.5k
      if (lumaUsesISP || cu.contains(*ptu, CH_C))
783
72.5k
      {
784
72.5k
        saveCS.addTU( *ptu, partitioner.chType, nullptr );
785
72.5k
        orgTUs.push_back( ptu );
786
72.5k
      }
787
72.5k
    }
788
789
    // SATD pre-selecting.
790
72.5k
    int     satdModeList  [NUM_CHROMA_MODE] = { 0 };
791
72.5k
    int64_t satdSortedCost[NUM_CHROMA_MODE] = { 0 };
792
72.5k
    bool    modeDisable[NUM_INTRA_MODE + 1] = { false }; // use intra mode idx to check whether enable
793
794
72.5k
    CodingStructure& cs = *(cu.cs);
795
72.5k
    CompArea areaCb = cu.Cb();
796
72.5k
    CompArea areaCr = cu.Cr();
797
72.5k
    CPelBuf orgCb  = cs.getOrgBuf (COMP_Cb);
798
72.5k
    PelBuf predCb  = cs.getPredBuf(COMP_Cb);
799
72.5k
    CPelBuf orgCr  = cs.getOrgBuf (COMP_Cr);
800
72.5k
    PelBuf predCr  = cs.getPredBuf(COMP_Cr);
801
802
72.5k
    DistParam distParamSadCb  = m_pcRdCost->setDistParam( orgCb, predCb, cu.cs->sps->bitDepths[ CH_C ], DF_SAD);
803
72.5k
    DistParam distParamSatdCb = m_pcRdCost->setDistParam( orgCb, predCb, cu.cs->sps->bitDepths[ CH_C ], DF_HAD);
804
72.5k
    DistParam distParamSadCr  = m_pcRdCost->setDistParam( orgCr, predCr, cu.cs->sps->bitDepths[ CH_C ], DF_SAD);
805
72.5k
    DistParam distParamSatdCr = m_pcRdCost->setDistParam( orgCr, predCr, cu.cs->sps->bitDepths[ CH_C ], DF_HAD);
806
807
72.5k
    cu.intraDir[1] = MDLM_L_IDX; // temporary assigned, just to indicate this is a MDLM mode. for luma down-sampling operation.
808
809
72.5k
    initIntraPatternChType(cu, cu.Cb());
810
72.5k
    initIntraPatternChType(cu, cu.Cr());
811
72.5k
    loadLMLumaRecPels(cu, cu.Cb());
812
813
652k
    for (int idx = uiMinMode; idx < uiMaxMode; idx++)
814
580k
    {
815
580k
      int mode = chromaCandModes[idx];
816
580k
      satdModeList[idx] = mode;
817
580k
      if (CU::isLMCMode(mode) && ( !CU::isLMCModeEnabled(cu, mode) || cu.slice->lmChromaCheckDisable ) )
818
62.4k
      {
819
62.4k
        continue;
820
62.4k
      }
821
517k
      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
126k
      {
823
126k
        continue;
824
126k
      }
825
826
391k
      cu.intraDir[1]    = mode; // temporary assigned, for SATD checking.
827
828
391k
      const bool isLMCMode = CU::isLMCMode(mode);
829
391k
      if( isLMCMode )
830
103k
      {
831
103k
        predIntraChromaLM(COMP_Cb, predCb, cu, areaCb, mode);
832
103k
      }
833
287k
      else
834
287k
      {
835
287k
        initPredIntraParams(cu, cu.Cb(), *cs.sps);
836
287k
        predIntraAng(COMP_Cb, predCb, cu);
837
287k
      }
838
391k
      int64_t sadCb = distParamSadCb.distFunc(distParamSadCb) * 2;
839
391k
      int64_t satdCb = distParamSatdCb.distFunc(distParamSatdCb);
840
391k
      int64_t sad = std::min(sadCb, satdCb);
841
842
391k
      if( isLMCMode )
843
103k
      {
844
103k
        predIntraChromaLM(COMP_Cr, predCr, cu, areaCr, mode);
845
103k
      }
846
287k
      else
847
287k
      {
848
287k
        initPredIntraParams(cu, cu.Cr(), *cs.sps);
849
287k
        predIntraAng(COMP_Cr, predCr, cu);
850
287k
      }
851
391k
      int64_t sadCr = distParamSadCr.distFunc(distParamSadCr) * 2;
852
391k
      int64_t satdCr = distParamSatdCr.distFunc(distParamSatdCr);
853
391k
      sad += std::min(sadCr, satdCr);
854
391k
      satdSortedCost[idx] = sad;
855
391k
    }
856
857
    // sort the mode based on the cost from small to large.
858
652k
    for (int i = uiMinMode; i <= uiMaxMode - 1; i++)
859
580k
    {
860
2.61M
      for (int j = i + 1; j <= uiMaxMode - 1; j++)
861
2.03M
      {
862
2.03M
        if (satdSortedCost[j] < satdSortedCost[i])
863
123k
        {
864
123k
          std::swap( satdModeList[i],   satdModeList[j]);
865
123k
          std::swap( satdSortedCost[i], satdSortedCost[j]);
866
123k
        }
867
2.03M
      }
868
580k
    }
869
870
362k
    for (int i = 0; i < reducedModeNumber; i++)
871
290k
    {
872
290k
      modeDisable[satdModeList[uiMaxMode - 1 - i]] = true; // disable the last reducedModeNumber modes
873
290k
    }
874
875
72.5k
    int bestLfnstIdx = 0;
876
    // save the dist
877
72.5k
    Distortion baseDist = cs.dist;
878
72.5k
    int32_t bestbdpcmMode = 0;
879
72.5k
    uint32_t numbdpcmModes = ( useBDPCM && CU::bdpcmAllowed(cu, COMP_Cb)
880
47.5k
        && ((partitioner.chType == CH_C) || (cu.ispMode == 0 && cu.lfnstIdx == 0 && cu.firstTU->mtsIdx[COMP_Y] == MTS_SKIP))) ? 2 : 0;
881
747k
    for (int mode_cur = uiMinMode; mode_cur < (int)(uiMaxMode + numbdpcmModes); mode_cur++)
882
675k
    {
883
675k
      int mode = mode_cur;
884
675k
      if (mode_cur >= uiMaxMode)
885
95.0k
      {
886
95.0k
        mode = mode_cur > uiMaxMode ? -1 : -2; //set bdpcm mode
887
95.0k
        if ((mode == -1) && (saveCS.tus[0]->mtsIdx[COMP_Cb] != MTS_SKIP) && (saveCS.tus[0]->mtsIdx[COMP_Cr] != MTS_SKIP))
888
47.5k
        {
889
47.5k
          continue;
890
47.5k
        }
891
95.0k
      }
892
627k
      int chromaIntraMode;
893
627k
      if (mode < 0)
894
47.5k
      {
895
47.5k
        cu.bdpcmM[CH_C] = -mode;
896
47.5k
        chromaIntraMode = cu.bdpcmM[CH_C] == 2 ? chromaCandModes[1] : chromaCandModes[2];
897
47.5k
      }
898
579k
      else
899
579k
      {
900
579k
        cu.bdpcmM[CH_C] = 0;
901
579k
        chromaIntraMode = chromaCandModes[mode];
902
579k
        if (CU::isLMCMode(chromaIntraMode) && ( !CU::isLMCModeEnabled(cu, chromaIntraMode) || cu.slice->lmChromaCheckDisable ) )
903
62.4k
        {
904
62.4k
          continue;
905
62.4k
        }
906
517k
        if (modeDisable[chromaIntraMode] && CU::isLMCModeEnabled(cu, chromaIntraMode)) // when CCLM is disable, then MDLM is disable. not use satd checking
907
206k
        {
908
206k
          continue;
909
206k
        }
910
517k
      }
911
358k
      cs.dist = baseDist;
912
      //----- restore context models -----
913
358k
      m_CABACEstimator->getCtx() = ctxStart;
914
915
      //----- chroma coding -----
916
358k
      cu.intraDir[1] = chromaIntraMode;
917
358k
      m_ispTestedModes[0].IspType = ispType;
918
358k
      m_ispTestedModes[0].subTuCounter = -1;
919
358k
      xIntraChromaCodingQT( cs, partitioner );
920
358k
      if (lumaUsesISP && cs.dist == MAX_UINT)
921
0
      {
922
0
        continue;
923
0
      }
924
925
358k
      if (cs.sps->transformSkip)
926
358k
      {
927
358k
        m_CABACEstimator->getCtx() = ctxStart;
928
358k
      }
929
358k
      m_ispTestedModes[0].IspType = ispType;
930
358k
      m_ispTestedModes[0].subTuCounter = -1;
931
358k
      uint64_t fracBits   = xGetIntraFracBitsQT( cs, partitioner, false );
932
358k
      Distortion uiDist = cs.dist;
933
358k
      double    dCost   = m_pcRdCost->calcRdCost( fracBits, uiDist - baseDist );
934
935
      //----- compare -----
936
358k
      if( dCost < dBestCost )
937
130k
      {
938
130k
        if (lumaUsesISP && (dCost < bestCostSoFar))
939
0
        {
940
0
          bestCostSoFar = dCost;
941
0
        }
942
390k
        for( uint32_t i = getFirstComponentOfChannel( CH_C ); i < numberValidComponents; i++ )
943
260k
        {
944
260k
          const CompArea& area = cu.blocks[i];
945
260k
          saveCS.getRecoBuf     ( area ).copyFrom( cs.getRecoBuf   ( area ) );
946
260k
          cs.picture->getRecoBuf( area ).copyFrom( cs.getRecoBuf   ( area ) );
947
520k
          for( uint32_t j = 0; j < saveCS.tus.size(); j++ )
948
260k
          {
949
260k
            saveCS.tus[j]->copyComponentFrom( *orgTUs[j], area.compID );
950
260k
          }
951
260k
        }
952
130k
        dBestCost    = dCost;
953
130k
        uiBestDist   = uiDist;
954
130k
        uiBestMode   = chromaIntraMode;
955
130k
        bestLfnstIdx = cu.lfnstIdx;
956
130k
        bestbdpcmMode = cu.bdpcmM[CH_C];
957
958
130k
      }
959
358k
    }
960
72.5k
    cu.lfnstIdx = bestLfnstIdx;
961
72.5k
    cu.bdpcmM[CH_C]= bestbdpcmMode;
962
963
217k
    for( uint32_t i = getFirstComponentOfChannel( CH_C ); i < numberValidComponents; i++ )
964
145k
    {
965
145k
      const CompArea& area = cu.blocks[i];
966
967
145k
      cs.getRecoBuf         ( area ).copyFrom( saveCS.getRecoBuf( area ) );
968
145k
      cs.picture->getRecoBuf( area ).copyFrom( cs.getRecoBuf    ( area ) );
969
970
290k
      for( uint32_t j = 0; j < saveCS.tus.size(); j++ )
971
145k
      {
972
145k
        orgTUs[ j ]->copyComponentFrom( *saveCS.tus[ j ], area.compID );
973
145k
      }
974
145k
    }
975
72.5k
  }
976
72.5k
  cu.intraDir[1] = uiBestMode;
977
72.5k
  cs.dist        = uiBestDist;
978
979
  //----- restore context models -----
980
72.5k
  m_CABACEstimator->getCtx() = ctxStart;
981
72.5k
  if (lumaUsesISP && bestCostSoFar >= maxCostAllowed)
982
0
  {
983
0
    cu.ispMode = 0;
984
0
  }
985
72.5k
}
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
597k
{
1012
597k
  CodingUnit &cu = *cs.getCU( partitioner.chType, partitioner.treeType );
1013
1014
597k
  if (luma)
1015
238k
  {
1016
238k
    bool isFirst = cu.ispMode ? m_ispTestedModes[0].subTuCounter == 0 : partitioner.currArea().lumaPos() == cs.area.lumaPos();
1017
1018
    // CU header
1019
238k
    if( isFirst )
1020
234k
    {
1021
234k
      if ((!cs.slice->isIntra() || cs.slice->sps->IBC || cs.slice->sps->PLT) && cu.Y().valid())
1022
234k
      {
1023
234k
        m_CABACEstimator->pred_mode   ( cu );
1024
234k
      }
1025
234k
      m_CABACEstimator->bdpcm_mode  ( cu, ComponentID(partitioner.chType) );
1026
234k
    }
1027
1028
    // luma prediction mode
1029
238k
    if (isFirst)
1030
234k
    {
1031
234k
      if ( !cu.Y().valid())
1032
0
      {
1033
0
        m_CABACEstimator->pred_mode( cu );
1034
0
      }
1035
234k
      const bool searchedCu = m_searchMpmValid && m_searchMpmArea == cu.Y();
1036
234k
#if defined( _DEBUG )
1037
234k
      if( searchedCu )
1038
234k
      {
1039
234k
        unsigned mpmLst[NUM_MOST_PROBABLE_MODES];
1040
234k
        CU::getIntraMPMs( cu, mpmLst );
1041
234k
        CHECK( !std::equal( mpmLst, mpmLst + NUM_MOST_PROBABLE_MODES, m_searchMpmLst ), "MPM list of the searched CU is out of date" );
1042
234k
      }
1043
234k
#endif
1044
234k
      m_CABACEstimator->intra_luma_pred_mode( cu, searchedCu ? m_searchMpmLst : nullptr );
1045
234k
    }
1046
238k
  }
1047
358k
  else //  if (chroma)
1048
358k
  {
1049
358k
    bool isFirst = partitioner.currArea().Cb().valid() && partitioner.currArea().chromaPos() == cs.area.chromaPos();
1050
1051
358k
    if( isFirst )
1052
358k
    {
1053
358k
      m_CABACEstimator->bdpcm_mode(cu, ComponentID(CH_C));
1054
358k
      m_CABACEstimator->intra_chroma_pred_mode(  cu );
1055
358k
    }
1056
358k
  }
1057
597k
}
1058
1059
void IntraSearch::xEncSubdivCbfQT( CodingStructure &cs, Partitioner &partitioner, const bool luma )
1060
597k
{
1061
597k
  const UnitArea& currArea = partitioner.currArea();
1062
597k
  int subTuCounter = m_ispTestedModes[0].subTuCounter;
1063
597k
  TransformUnit  &currTU   = *cs.getTU(currArea.blocks[partitioner.chType], partitioner.chType, subTuCounter);
1064
597k
  CodingUnit     &currCU   = *currTU.cu;
1065
597k
  const uint32_t currDepth = partitioner.currTrDepth;
1066
597k
  const bool  subdiv = currTU.depth > currDepth;
1067
597k
  ComponentID compID = partitioner.chType == CH_L ? COMP_Y : COMP_Cb;
1068
1069
597k
  if (!luma)
1070
358k
  {
1071
358k
    const bool chromaCbfISP = currArea.blocks[COMP_Cb].valid() && currCU.ispMode && !subdiv;
1072
358k
    if (!currCU.ispMode || chromaCbfISP)
1073
358k
    {
1074
358k
      const uint32_t numberValidComponents = getNumberValidComponents(currArea.chromaFormat);
1075
358k
      const uint32_t cbfDepth = (chromaCbfISP ? currDepth - 1 : currDepth);
1076
1077
1.07M
      for (uint32_t ch = COMP_Cb; ch < numberValidComponents; ch++)
1078
716k
      {
1079
716k
        const ComponentID compID = ComponentID(ch);
1080
716k
        if (currDepth == 0 || TU::getCbfAtDepth(currTU, compID, currDepth - 1) || chromaCbfISP)
1081
716k
        {
1082
716k
          const bool prevCbf = (compID == COMP_Cr ? TU::getCbfAtDepth(currTU, COMP_Cb, currDepth) : false);
1083
716k
          m_CABACEstimator->cbf_comp(currCU, TU::getCbfAtDepth(currTU, compID, currDepth), currArea.blocks[compID], cbfDepth, prevCbf);
1084
716k
        }
1085
716k
      }
1086
358k
    }
1087
358k
  }
1088
1089
597k
  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
597k
  else
1111
597k
  {
1112
    //===== Cbfs =====
1113
597k
    if (luma)
1114
238k
    {
1115
238k
      bool previousCbf = false;
1116
238k
      bool lastCbfIsInferred = false;
1117
238k
      if (m_ispTestedModes[0].IspType != TU_NO_ISP)
1118
17.2k
      {
1119
17.2k
        bool     rootCbfSoFar = false;
1120
17.2k
        uint32_t nTus = currCU.ispMode == HOR_INTRA_SUBPARTITIONS ? currCU.lheight() >> floorLog2(currTU.lheight())
1121
17.2k
          : currCU.lwidth() >> floorLog2(currTU.lwidth());
1122
17.2k
        if (subTuCounter == nTus - 1)
1123
1.51k
        {
1124
1.51k
          TransformUnit* tuPointer = currCU.firstTU;
1125
6.04k
          for (int tuIdx = 0; tuIdx < nTus - 1; tuIdx++)
1126
4.53k
          {
1127
4.53k
            rootCbfSoFar |= TU::getCbfAtDepth(*tuPointer, COMP_Y, currDepth);
1128
4.53k
            tuPointer = tuPointer->next;
1129
4.53k
          }
1130
1.51k
          if (!rootCbfSoFar)
1131
0
          {
1132
0
            lastCbfIsInferred = true;
1133
0
          }
1134
1.51k
        }
1135
17.2k
        if (!lastCbfIsInferred)
1136
17.2k
        {
1137
17.2k
          previousCbf = TU::getPrevTuCbfAtDepth(currTU, COMP_Y, partitioner.currTrDepth);
1138
17.2k
        }
1139
17.2k
      }
1140
238k
      if (!lastCbfIsInferred)
1141
238k
      {
1142
238k
        m_CABACEstimator->cbf_comp(currCU, TU::getCbfAtDepth(currTU, COMP_Y, currDepth), currTU.Y(), currTU.depth, previousCbf, currCU.ispMode);
1143
238k
      }
1144
238k
    }
1145
597k
  }
1146
597k
}
1147
void IntraSearch::xEncCoeffQT(CodingStructure& cs, Partitioner& partitioner, const ComponentID compID, CUCtx* cuCtx, const int subTuIdx, const PartSplit ispType)
1148
955k
{
1149
955k
  const UnitArea& currArea  = partitioner.currArea();
1150
1151
955k
  int subTuCounter          = m_ispTestedModes[0].subTuCounter;
1152
955k
  TransformUnit& currTU     = *cs.getTU(currArea.blocks[partitioner.chType], partitioner.chType, subTuCounter);
1153
955k
  uint32_t   currDepth      = partitioner.currTrDepth;
1154
955k
  const bool subdiv         = currTU.depth > currDepth;
1155
1156
955k
  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
955k
  else
1178
1179
955k
  if( currArea.blocks[compID].valid() )
1180
955k
  {
1181
955k
    if( compID == COMP_Cr )
1182
358k
    {
1183
358k
      const int cbfMask = ( TU::getCbf( currTU, COMP_Cb ) ? 2 : 0 ) + ( TU::getCbf( currTU, COMP_Cr ) ? 1 : 0 );
1184
358k
      m_CABACEstimator->joint_cb_cr( currTU, cbfMask );
1185
358k
    }
1186
955k
    if( TU::getCbf( currTU, compID ) )
1187
285k
    {
1188
285k
      if( isLuma(compID) )
1189
30.1k
      {
1190
30.1k
        m_CABACEstimator->residual_coding( currTU, compID, cuCtx );
1191
30.1k
        m_CABACEstimator->mts_idx( *currTU.cu, cuCtx );
1192
30.1k
      }
1193
255k
      else
1194
255k
        m_CABACEstimator->residual_coding( currTU, compID );
1195
285k
    }
1196
955k
  }
1197
955k
}
1198
1199
uint64_t IntraSearch::xGetIntraFracBitsQT( CodingStructure &cs, Partitioner &partitioner, const bool luma, CUCtx *cuCtx )
1200
597k
{
1201
597k
  m_CABACEstimator->resetBits();
1202
1203
597k
  xEncIntraHeader( cs, partitioner, luma );
1204
597k
  xEncSubdivCbfQT( cs, partitioner, luma );
1205
1206
597k
  if( luma )
1207
238k
  {
1208
238k
    xEncCoeffQT( cs, partitioner, COMP_Y, cuCtx );
1209
1210
238k
    CodingUnit &cu = *cs.cus[0];
1211
238k
    if (cuCtx /*&& CU::isSepTree(cu)*/
1212
149k
      && (!cu.ispMode || (cu.lfnstIdx && m_ispTestedModes[0].subTuCounter == 0)
1213
10.7k
        || (!cu.lfnstIdx
1214
9.20k
          && m_ispTestedModes[0].subTuCounter == m_ispTestedModes[cu.lfnstIdx].numTotalParts[cu.ispMode - 1] - 1)))
1215
139k
    {
1216
139k
      m_CABACEstimator->residual_lfnst_mode( cu, *cuCtx );
1217
139k
    }
1218
238k
  }
1219
358k
  else
1220
358k
  {
1221
358k
    xEncCoeffQT( cs, partitioner, COMP_Cb );
1222
358k
    xEncCoeffQT( cs, partitioner, COMP_Cr );
1223
358k
  }
1224
1225
597k
  uint64_t fracBits = m_CABACEstimator->getEstFracBits();
1226
597k
  return fracBits;
1227
597k
}
1228
1229
uint64_t IntraSearch::xGetIntraFracBitsQTChroma(const TransformUnit& currTU, const ComponentID compID, CUCtx *cuCtx)
1230
2.23M
{
1231
2.23M
  m_CABACEstimator->resetBits();
1232
1233
2.23M
  if ( currTU.jointCbCr )
1234
329k
  {
1235
329k
    const int cbfMask = ( TU::getCbf( currTU, COMP_Cb ) ? 2 : 0 ) + ( TU::getCbf( currTU, COMP_Cr ) ? 1 : 0 );
1236
329k
    m_CABACEstimator->cbf_comp( *currTU.cu, cbfMask>>1, currTU.blocks[ COMP_Cb ], currTU.depth, false );
1237
329k
    m_CABACEstimator->cbf_comp( *currTU.cu, cbfMask &1, currTU.blocks[ COMP_Cr ], currTU.depth, cbfMask>>1 );
1238
329k
    if( cbfMask )
1239
329k
      m_CABACEstimator->joint_cb_cr( currTU, cbfMask );
1240
329k
    if (cbfMask >> 1)
1241
327k
      m_CABACEstimator->residual_coding( currTU, COMP_Cb, cuCtx );
1242
329k
    if (cbfMask & 1)
1243
329k
      m_CABACEstimator->residual_coding( currTU, COMP_Cr, cuCtx );
1244
329k
  }
1245
1.90M
  else
1246
1.90M
  {
1247
1.90M
    if ( compID == COMP_Cb )
1248
954k
      m_CABACEstimator->cbf_comp( *currTU.cu, TU::getCbf( currTU, compID ), currTU.blocks[ compID ], currTU.depth, false );
1249
954k
    else
1250
954k
    {
1251
954k
      const bool cbCbf    = TU::getCbf( currTU, COMP_Cb );
1252
954k
      const bool crCbf    = TU::getCbf( currTU, compID );
1253
954k
      const int  cbfMask  = ( cbCbf ? 2 : 0 ) + ( crCbf ? 1 : 0 );
1254
954k
      m_CABACEstimator->cbf_comp( *currTU.cu, crCbf, currTU.blocks[ compID ], currTU.depth, cbCbf );
1255
954k
      m_CABACEstimator->joint_cb_cr( currTU, cbfMask );
1256
954k
    }
1257
1.90M
  }
1258
1259
2.23M
  if( !currTU.jointCbCr && TU::getCbf( currTU, compID ) )
1260
664k
  {
1261
664k
    m_CABACEstimator->residual_coding( currTU, compID, cuCtx );
1262
664k
  }
1263
1264
2.23M
  uint64_t fracBits = m_CABACEstimator->getEstFracBits();
1265
2.23M
  return fracBits;
1266
2.23M
}
1267
1268
void IntraSearch::xIntraCodingTUBlock(TransformUnit &tu, const ComponentID compID, const bool checkCrossCPrediction, Distortion &ruiDist, uint32_t *numSig, PelUnitBuf *predBuf, const bool loadTr)
1269
2.48M
{
1270
2.48M
  if (!tu.blocks[compID].valid())
1271
0
  {
1272
0
    return;
1273
0
  }
1274
1275
2.48M
  CodingStructure &cs             = *tu.cs;
1276
2.48M
  const CompArea      &area       = tu.blocks[compID];
1277
2.48M
  const SPS           &sps        = *cs.sps;
1278
1279
2.48M
  const ChannelType    chType     = toChannelType(compID);
1280
2.48M
  const int            bitDepth   = sps.bitDepths[chType];
1281
1282
2.48M
  CPelBuf        piOrg            = cs.getOrgBuf    (area);
1283
2.48M
  PelBuf         piPred           = cs.getPredBuf   (area);
1284
2.48M
  PelBuf         piResi           = cs.getResiBuf   (area);
1285
2.48M
  PelBuf         piReco           = cs.getRecoBuf   (area);
1286
1287
2.48M
  const CodingUnit& cu            = *tu.cu;
1288
1289
  //===== init availability pattern =====
1290
2.48M
  CHECK( tu.jointCbCr && compID == COMP_Cr, "wrong combination of compID and jointCbCr" );
1291
2.48M
  bool jointCbCr = tu.jointCbCr && compID == COMP_Cb;
1292
1293
2.48M
  if ( isLuma(compID) )
1294
245k
  {
1295
245k
    bool predRegDiffFromTB = CU::isPredRegDiffFromTB(*tu.cu );
1296
245k
    bool firstTBInPredReg  = false;
1297
245k
    CompArea areaPredReg(COMP_Y, tu.chromaFormat, area);
1298
245k
    if (tu.cu->ispMode )
1299
23.7k
    {
1300
23.7k
      firstTBInPredReg = CU::isFirstTBInPredReg(*tu.cu, area);
1301
23.7k
      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
23.7k
      else
1310
23.7k
        initIntraPatternChTypeISP(*tu.cu, area, piReco);
1311
23.7k
    }
1312
221k
    else if( !predBuf )
1313
37.1k
    {
1314
37.1k
      initIntraPatternChType(*tu.cu, area);
1315
37.1k
    }
1316
1317
    //===== get prediction signal =====
1318
245k
    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
245k
    else
1327
245k
    {
1328
245k
      if( predBuf )
1329
184k
      {
1330
184k
        piPred.copyFrom( predBuf->Y() );
1331
184k
      }
1332
60.9k
      else if( CU::isMIP( cu, CH_L ) )
1333
28.3k
      {
1334
28.3k
        initIntraMip( cu );
1335
28.3k
        predIntraMip( piPred, cu );
1336
28.3k
      }
1337
32.6k
      else
1338
32.6k
      {
1339
32.6k
        predIntraAng(compID, piPred, cu);
1340
32.6k
      }
1341
245k
    }
1342
245k
  }
1343
2.48M
  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
2.48M
  if (isLuma(compID))
1346
245k
  {
1347
    //===== get residual signal =====
1348
245k
    piResi.subtract( piOrg, piPred );
1349
245k
  }
1350
1351
  //===== transform and quantization =====
1352
  //--- init rate estimation arrays for RDOQ ---
1353
  //--- transform and quantization           ---
1354
2.48M
  TCoeff uiAbsSum = 0;
1355
2.48M
  const QpParam cQP(tu, compID);
1356
1357
2.48M
  m_pcTrQuant->selectLambda(compID);
1358
1359
2.48M
  if ( jointCbCr )
1360
334k
  {
1361
    // Lambda is loosened for the joint mode with respect to single modes as the same residual is used for both chroma blocks
1362
334k
    const int    absIct = abs( TU::getICTMode(tu) );
1363
334k
    const double lfact  = ( absIct == 1 || absIct == 3 ? 0.8 : 0.5 );
1364
334k
    m_pcTrQuant->scaleLambda( lfact );
1365
334k
  }
1366
2.48M
  if ( sps.jointCbCr && isChroma(compID) && (tu.cu->cs->slice->sliceQp > 18) )
1367
1.48M
  {
1368
1.48M
    m_pcTrQuant->scaleLambda( 1.3 );
1369
1.48M
  }
1370
1371
2.48M
  if( isLuma(compID) )
1372
245k
  {
1373
245k
    m_pcTrQuant->transformNxN(tu, compID, cQP, uiAbsSum, m_CABACEstimator->getCtx(), loadTr);
1374
1375
245k
    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
245k
    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
245k
    if (uiAbsSum > 0)
1384
36.6k
    {
1385
36.6k
      m_pcTrQuant->invTransformNxN(tu, compID, piResi, cQP);
1386
36.6k
    }
1387
208k
    else
1388
208k
    {
1389
208k
      piResi.fill(0);
1390
208k
    }
1391
245k
  }
1392
2.24M
  else // chroma
1393
2.24M
  {
1394
2.24M
    PelBuf          crPred = cs.getPredBuf ( COMP_Cr );
1395
2.24M
    PelBuf          crResi = cs.getResiBuf ( COMP_Cr );
1396
2.24M
    PelBuf          crReco = cs.getRecoBuf ( COMP_Cr );
1397
1398
2.24M
    int         codedCbfMask  = 0;
1399
2.24M
    ComponentID codeCompId    = (tu.jointCbCr ? (tu.jointCbCr >> 1 ? COMP_Cb : COMP_Cr) : compID);
1400
2.24M
    const QpParam qpCbCr(tu, codeCompId);
1401
1402
2.24M
    if( tu.jointCbCr )
1403
334k
    {
1404
334k
      ComponentID otherCompId = ( codeCompId==COMP_Cr ? COMP_Cb : COMP_Cr );
1405
334k
      tu.getCoeffs( otherCompId ).fill(0); // do we need that?
1406
334k
      TU::setCbfAtDepth (tu, otherCompId, tu.depth, false );
1407
334k
    }
1408
2.24M
    PelBuf& codeResi = ( codeCompId == COMP_Cr ? crResi : piResi );
1409
2.24M
    uiAbsSum = 0;
1410
2.24M
    m_pcTrQuant->transformNxN(tu, codeCompId, qpCbCr, uiAbsSum, m_CABACEstimator->getCtx(), loadTr);
1411
2.24M
    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
2.24M
    if( uiAbsSum > 0 )
1413
993k
    {
1414
993k
      m_pcTrQuant->invTransformNxN(tu, codeCompId, codeResi, qpCbCr);
1415
993k
      codedCbfMask += ( codeCompId == COMP_Cb ? 2 : 1 );
1416
993k
    }
1417
1.25M
    else
1418
1.25M
    {
1419
1.25M
      codeResi.fill(0);
1420
1.25M
    }
1421
1422
2.24M
    if( tu.jointCbCr )
1423
334k
    {
1424
334k
      if( tu.jointCbCr == 3 && codedCbfMask == 2 )
1425
327k
      {
1426
327k
        codedCbfMask = 3;
1427
327k
        TU::setCbfAtDepth (tu, COMP_Cr, tu.depth, true );
1428
327k
      }
1429
334k
      if( tu.jointCbCr != codedCbfMask )
1430
4.86k
      {
1431
4.86k
        ruiDist = MAX_DISTORTION;
1432
4.86k
        return;
1433
4.86k
      }
1434
329k
      m_pcTrQuant->invTransformICT( tu, piResi, crResi );
1435
329k
      uiAbsSum = codedCbfMask;
1436
329k
    }
1437
1438
    //===== reconstruction =====
1439
2.23M
    if( jointCbCr )
1440
329k
    {
1441
329k
      crReco.reconstruct(crPred, crResi, cs.slice->clpRngs[ COMP_Cr ]);
1442
329k
    }
1443
2.23M
  }
1444
2.48M
  piReco.reconstruct(piPred, piResi, cs.slice->clpRngs[ compID ]);
1445
  
1446
1447
1448
  //===== update distortion =====
1449
2.48M
  ruiDist += m_pcRdCost->getDistPart( piOrg, piReco, bitDepth, compID, DF_SSE );
1450
2.48M
  if( jointCbCr )
1451
329k
  {
1452
329k
    CPelBuf         crOrg  = cs.getOrgBuf  ( COMP_Cr );
1453
329k
    PelBuf          crReco = cs.getRecoBuf ( COMP_Cr );
1454
329k
    ruiDist += m_pcRdCost->getDistPart( crOrg, crReco, bitDepth, COMP_Cr, DF_SSE );
1455
329k
  }
1456
2.48M
}
1457
1458
void IntraSearch::xIntraCodingLumaQT(CodingStructure& cs, Partitioner& partitioner, PelUnitBuf* predBuf, const double bestCostSoFar, int numMode, bool disableMTS)
1459
148k
{
1460
148k
  PROFILER_SCOPE_AND_STAGE_EXT( 0, _TPROF, P_INTRA_RD_SEARCH_LUMA, &cs, partitioner.chType );
1461
148k
  const UnitArea& currArea  = partitioner.currArea();
1462
148k
  uint32_t        currDepth = partitioner.currTrDepth;
1463
148k
  Distortion singleDistLuma = 0;
1464
148k
  uint32_t   numSig         = 0;
1465
148k
  const SPS &sps            = *cs.sps;
1466
148k
  CodingUnit &cu            = *cs.cus[0];
1467
148k
  bool mtsAllowed = (numMode < 0) || disableMTS ? false : CU::isMTSAllowed(cu, COMP_Y);
1468
148k
  uint64_t singleFracBits   = 0;
1469
148k
  bool   splitCbfLumaSum    = false;
1470
148k
  double bestCostForISP     = bestCostSoFar;
1471
148k
  double dSingleCost        = MAX_DOUBLE;
1472
148k
  int endLfnstIdx           = (partitioner.isSepTree(cs) && partitioner.chType == CH_C && (currArea.lwidth() < 8 || currArea.lheight() < 8))
1473
148k
                           || (currArea.lwidth() > sps.getMaxTbSize() || currArea.lheight() > sps.getMaxTbSize()) || !sps.LFNST || (numMode < 0) ? 0 : 2;
1474
148k
  const bool useTS          = cs.picture->useTS;
1475
148k
  numMode                   = (numMode < 0) ? -numMode : numMode;
1476
1477
148k
  if (cu.mipFlag && !allowLfnstWithMip(cu.lumaSize()))
1478
2.42k
  {
1479
2.42k
    endLfnstIdx = 0;
1480
2.42k
  }
1481
148k
  int bestMTS = 0;
1482
148k
  int EndMTS  = mtsAllowed ? m_pcEncCfg->m_MTSIntraMaxCand : 0;
1483
148k
  if (cu.ispMode && (EndMTS || endLfnstIdx))
1484
6.57k
  {
1485
6.57k
    EndMTS = 0;
1486
6.57k
    if ((m_ispTestedModes[1].numTotalParts[cu.ispMode - 1] == 0)
1487
340
     && (m_ispTestedModes[2].numTotalParts[cu.ispMode - 1] == 0))
1488
340
    {
1489
340
      endLfnstIdx = 0;
1490
340
    }
1491
6.57k
  }
1492
148k
  if (cu.bdpcmM[CH_L])
1493
8.65k
  {
1494
8.65k
    endLfnstIdx = 0;
1495
8.65k
    EndMTS = 0;
1496
8.65k
  }
1497
148k
  bool checkTransformSkip = sps.transformSkip;
1498
1499
148k
  SizeType transformSkipMaxSize = 1 << sps.log2MaxTransformSkipBlockSize;
1500
148k
  bool tsAllowed = useTS  && cu.cs->sps->transformSkip && (!cu.ispMode) && (!cu.bdpcmM[CH_L]) && (!cu.sbtInfo);
1501
148k
  tsAllowed &= cu.blocks[COMP_Y].width <= transformSkipMaxSize && cu.blocks[COMP_Y].height <= transformSkipMaxSize;
1502
148k
  if (tsAllowed)
1503
17.3k
  {
1504
17.3k
    EndMTS += 1;
1505
17.3k
  }
1506
148k
  if (endLfnstIdx || EndMTS)
1507
58.6k
  {
1508
58.6k
    bool       splitCbfLuma  = false;
1509
58.6k
    const PartSplit ispType  = CU::getISPType(cu, COMP_Y);
1510
58.6k
    CUCtx cuCtx;
1511
58.6k
    cuCtx.isDQPCoded         = true;
1512
58.6k
    cuCtx.isChromaQpAdjCoded = true;
1513
58.6k
    cs.cost                  = 0.0;
1514
58.6k
    Distortion       singleDistTmpLuma = 0;
1515
58.6k
    uint64_t         singleTmpFracBits = 0;
1516
58.6k
    double           singleCostTmp     = 0;
1517
58.6k
    const TempCtx    ctxStart          (m_CtxCache, m_CABACEstimator->getCtx());
1518
58.6k
          TempCtx    ctxBest           (m_CtxCache);
1519
58.6k
    CodingStructure &saveCS            = *m_pSaveCS[cu.ispMode?0:1];
1520
58.6k
    TransformUnit *  tmpTU             = nullptr;
1521
58.6k
    int              bestLfnstIdx      = 0;
1522
58.6k
    int              startLfnstIdx     = 0;
1523
    // speedUps LFNST
1524
58.6k
    bool   rapidLFNST                  = false;
1525
58.6k
    bool   rapidDCT                    = false;
1526
58.6k
    double thresholdDCT                = 1;
1527
1528
58.6k
    if (m_pcEncCfg->m_MTS == 2)
1529
0
    {
1530
0
      thresholdDCT += 1.4 / sqrt(cu.lwidth() * cu.lheight());
1531
0
    }
1532
1533
58.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
58.6k
    saveCS.pcv              = cs.pcv;
1545
58.6k
    saveCS.picture          = cs.picture;
1546
58.6k
    saveCS.area.repositionTo( cs.area);
1547
1548
58.6k
    if (cu.ispMode)
1549
6.23k
    {
1550
6.23k
      partitioner.splitCurrArea(ispType, cs);
1551
6.23k
    }
1552
1553
58.6k
    TransformUnit& tu = cs.addTU(CS::getArea(cs, partitioner.currArea(), partitioner.chType, partitioner.treeType), partitioner.chType, cs.cus[0]);
1554
1555
58.6k
    if (cu.ispMode)
1556
6.23k
    {
1557
6.23k
      saveCS.clearTUs();
1558
6.23k
      do
1559
24.9k
      {
1560
24.9k
        saveCS.addTU(
1561
24.9k
          CS::getArea(cs, partitioner.currArea(), partitioner.chType, partitioner.treeType),
1562
24.9k
          partitioner.chType, cs.cus[0]);
1563
24.9k
      } while (partitioner.nextPart(cs));
1564
1565
6.23k
      partitioner.exitCurrSplit();
1566
6.23k
    }
1567
52.4k
    else
1568
52.4k
    {
1569
52.4k
      tmpTU = saveCS.tus.empty() ? &saveCS.addTU( currArea, partitioner.chType, nullptr ) : saveCS.tus.front();
1570
52.4k
      tmpTU->initData();
1571
52.4k
      tmpTU->UnitArea::operator=( currArea );
1572
52.4k
    }
1573
1574
1575
58.6k
    TrModeList trModes{ TrMode(0, true) };
1576
58.6k
    if (tsAllowed)
1577
17.3k
    {
1578
17.3k
      trModes.push_back(TrMode(1, true));
1579
17.3k
    }
1580
58.6k
    double dct2Cost           = MAX_DOUBLE;
1581
58.6k
    double trGrpStopThreshold = 1.001;
1582
58.6k
    double trGrpBestCost      = MAX_DOUBLE;
1583
1584
58.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
58.6k
    if ((EndMTS && !m_pcEncCfg->m_LFNST) || (tsAllowed && !mtsAllowed))
1609
17.3k
    {
1610
17.3k
      xPreCheckMTS(tu, &trModes, m_pcEncCfg->m_MTSIntraMaxCand, predBuf);
1611
17.3k
      if (!mtsAllowed && !trModes[1].second)
1612
3.19k
      {
1613
3.19k
        EndMTS = 0;
1614
3.19k
      }
1615
17.3k
    }
1616
1617
58.6k
    bool NStopMTS = true;
1618
1619
117k
    for (int modeId = 0; modeId <= EndMTS && NStopMTS; modeId++)
1620
58.6k
    {
1621
58.6k
      if (modeId > 1)
1622
0
      {
1623
0
        trGrpBestCost = MAX_DOUBLE;
1624
0
      }
1625
209k
      for (int lfnstIdx = startLfnstIdx; lfnstIdx <= endLfnstIdx; lfnstIdx++)
1626
151k
      {
1627
151k
        if (lfnstIdx && modeId)
1628
0
        {
1629
0
          continue;
1630
0
        }
1631
151k
        if (mtsAllowed || tsAllowed)
1632
27.1k
        {
1633
27.1k
          if (m_pcEncCfg->m_TS && bestMTS == MTS_SKIP)
1634
0
          {
1635
0
            break;
1636
0
          }
1637
27.1k
          if (!m_pcEncCfg->m_LFNST && !trModes[modeId].second && mtsAllowed)
1638
0
          {
1639
0
            continue;
1640
0
          }
1641
1642
27.1k
          tu.mtsIdx[COMP_Y] = trModes[modeId].first;
1643
27.1k
        }
1644
1645
151k
        if (cu.ispMode && lfnstIdx)
1646
12.4k
        {
1647
12.4k
          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
12.4k
        }
1656
1657
151k
        cu.lfnstIdx                          = lfnstIdx;
1658
151k
        cuCtx.lfnstLastScanPos               = false;
1659
151k
        cuCtx.violatesLfnstConstrained[CH_L] = false;
1660
151k
        cuCtx.violatesLfnstConstrained[CH_C] = false;
1661
1662
151k
        if ((lfnstIdx != startLfnstIdx) || (modeId))
1663
92.3k
        {
1664
92.3k
          m_CABACEstimator->getCtx() = ctxStart;
1665
92.3k
        }
1666
1667
151k
        singleDistTmpLuma = 0;
1668
1669
151k
        if (cu.ispMode)
1670
18.7k
        {
1671
18.7k
          splitCbfLuma = false;
1672
1673
18.7k
          partitioner.splitCurrArea(ispType, cs);
1674
1675
18.7k
          singleCostTmp = xTestISP(cs, partitioner, bestCostForISP, ispType, splitCbfLuma, singleTmpFracBits, singleDistTmpLuma, cuCtx);
1676
1677
18.7k
          partitioner.exitCurrSplit();
1678
1679
18.7k
          if (modeId && (singleCostTmp == MAX_DOUBLE))
1680
0
          {
1681
0
            m_ispTestedModes[lfnstIdx].numTotalParts[cu.ispMode - 1] = 0;
1682
0
          }
1683
1684
18.7k
          bool storeCost = (numMode == 1) ? true : false;
1685
1686
18.7k
          if ((m_pcEncCfg->m_ISP >= 2) && (numMode <= 1))
1687
18.7k
          {
1688
18.7k
            storeCost = true;
1689
18.7k
          }
1690
1691
18.7k
          if (storeCost)
1692
18.7k
          {
1693
18.7k
            m_ispTestedModes[0].bestCost[cu.ispMode - 1] = singleCostTmp;
1694
18.7k
          }
1695
18.7k
        }
1696
132k
        else
1697
132k
        {
1698
132k
          bool TrLoad = (EndMTS && !m_pcEncCfg->m_LFNST) || (tsAllowed && !mtsAllowed && (lfnstIdx == 0)) ? true : false;
1699
1700
132k
          xIntraCodingTUBlock(tu, COMP_Y, false, singleDistTmpLuma, &numSig, predBuf, TrLoad);
1701
1702
132k
          cuCtx.mtsLastScanPos = false;
1703
          //----- determine rate and r-d cost -----
1704
132k
        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
132k
        else
1709
132k
        {
1710
132k
          m_ispTestedModes[0].IspType      = TU_NO_ISP;
1711
132k
          m_ispTestedModes[0].subTuCounter = -1;
1712
132k
          singleTmpFracBits = xGetIntraFracBitsQT(cs, partitioner, true, &cuCtx);
1713
1714
132k
          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
132k
          else
1726
132k
          {
1727
132k
            singleCostTmp = m_pcRdCost->calcRdCost(singleTmpFracBits, singleDistTmpLuma);
1728
132k
          }
1729
132k
        }
1730
1731
132k
          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
132k
          if (lfnstIdx && !cuCtx.lfnstLastScanPos && !cu.ispMode)
1745
67.4k
          {
1746
67.4k
            bool rootCbfL = false;
1747
1748
269k
            for (uint32_t t = 0; t < getNumberValidTBlocks(*cu.cs->pcv); t++)
1749
202k
            {
1750
202k
              rootCbfL |= tu.cbf[t] != 0;
1751
202k
            }
1752
1753
67.4k
            if (rapidLFNST && !rootCbfL)
1754
0
            {
1755
0
              endLfnstIdx = lfnstIdx; // break the loop
1756
0
            }
1757
67.4k
            bool cbfAtZeroDepth = CU::isSepTree(cu)
1758
67.4k
              ? rootCbfL
1759
67.4k
              : (cs.area.chromaFormat != CHROMA_400 && std::min(cu.firstTU->blocks[1].width, cu.firstTU->blocks[1].height) < 4)
1760
1
                ? TU::getCbfAtDepth(tu, COMP_Y, currDepth)
1761
1
                : rootCbfL;
1762
1763
67.4k
            if (cbfAtZeroDepth)
1764
427
            {
1765
427
              singleCostTmp = MAX_DOUBLE;
1766
427
            }
1767
67.4k
          }
1768
132k
        }
1769
1770
151k
        if (singleCostTmp < dSingleCost)
1771
53.9k
        {
1772
53.9k
          trGrpBestCost  = singleCostTmp;
1773
53.9k
          dSingleCost    = singleCostTmp;
1774
53.9k
          singleDistLuma = singleDistTmpLuma;
1775
53.9k
          singleFracBits = singleTmpFracBits;
1776
53.9k
          bestLfnstIdx   = lfnstIdx;
1777
53.9k
          bestMTS        = modeId;
1778
1779
53.9k
          if (dSingleCost < bestCostForISP)
1780
34.5k
          {
1781
34.5k
            bestCostForISP = dSingleCost;
1782
34.5k
          }
1783
1784
53.9k
          splitCbfLumaSum = splitCbfLuma;
1785
1786
53.9k
          if (lfnstIdx == 0 && modeId == 0 && cu.ispMode == 0)
1787
52.4k
          {
1788
52.4k
            dct2Cost = singleCostTmp;
1789
1790
52.4k
            if (!TU::getCbfAtDepth(tu, COMP_Y, currDepth))
1791
44.7k
            {
1792
44.7k
              if (rapidLFNST)
1793
0
              {
1794
0
                 endLfnstIdx = 0;   // break the loop but do not cpy best
1795
0
              }
1796
1797
44.7k
              EndMTS = 0;
1798
44.7k
            }
1799
52.4k
          }
1800
1801
53.9k
          if (bestLfnstIdx != endLfnstIdx || bestMTS != EndMTS)
1802
41.3k
          {
1803
41.3k
            if (cu.ispMode)
1804
1.16k
            {
1805
1.16k
              saveCS.getRecoBuf(currArea.Y()).copyFrom(cs.getRecoBuf(currArea.Y()));
1806
1807
5.82k
              for (uint32_t j = 0; j < cs.tus.size(); j++)
1808
4.65k
              {
1809
4.65k
                saveCS.tus[j]->copyComponentFrom(*cs.tus[j], COMP_Y);
1810
4.65k
              }
1811
1.16k
            }
1812
40.1k
            else
1813
40.1k
            {
1814
40.1k
              saveCS.getPredBuf(tu.Y()).copyFrom(cs.getPredBuf(tu.Y()));
1815
40.1k
              saveCS.getRecoBuf(tu.Y()).copyFrom(cs.getRecoBuf(tu.Y()));
1816
1817
40.1k
              tmpTU->copyComponentFrom(tu, COMP_Y);
1818
40.1k
            }
1819
1820
41.3k
            ctxBest = m_CABACEstimator->getCtx();
1821
41.3k
          }
1822
      
1823
53.9k
        }
1824
97.0k
        else
1825
97.0k
        {
1826
97.0k
          if( rapidLFNST )
1827
0
          {
1828
0
            endLfnstIdx = lfnstIdx; // break the loop
1829
0
          }
1830
97.0k
        }
1831
151k
      }
1832
58.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
58.6k
    }
1845
1846
58.6k
    cu.lfnstIdx = bestLfnstIdx;
1847
58.6k
    if (dSingleCost != MAX_DOUBLE)
1848
53.4k
    {
1849
53.4k
      if (bestLfnstIdx != endLfnstIdx || bestMTS != EndMTS)
1850
40.7k
      {
1851
40.7k
        if (cu.ispMode)
1852
822
        {
1853
822
          const UnitArea& currArea = partitioner.currArea();
1854
822
          cs.getRecoBuf(currArea.Y()).copyFrom(saveCS.getRecoBuf(currArea.Y()));
1855
1856
822
          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
4.11k
          for (uint32_t j = 0; j < saveCS.tus.size(); j++)
1871
3.28k
          {
1872
3.28k
            cs.tus[j]->copyComponentFrom(*saveCS.tus[j], COMP_Y);
1873
3.28k
          }
1874
822
        }
1875
39.9k
        else
1876
39.9k
        {
1877
39.9k
          cs.getRecoBuf(tu.Y()).copyFrom(saveCS.getRecoBuf(tu.Y()));
1878
1879
39.9k
          tu.copyComponentFrom(*tmpTU, COMP_Y);
1880
39.9k
        }
1881
1882
40.7k
        m_CABACEstimator->getCtx() = ctxBest;
1883
40.7k
      }
1884
1885
      // otherwise this would've happened in useSubStructure
1886
53.4k
      cs.picture->getRecoBuf(currArea.Y()).copyFrom(cs.getRecoBuf(currArea.Y()));
1887
53.4k
    }
1888
58.6k
  }
1889
89.5k
  else
1890
89.5k
  {
1891
89.5k
    if (cu.ispMode)
1892
340
    {
1893
340
      const PartSplit ispType = CU::getISPType(cu, COMP_Y);
1894
340
      partitioner.splitCurrArea(ispType, cs);
1895
1896
340
      CUCtx      cuCtx;
1897
340
      dSingleCost = xTestISP(cs, partitioner, bestCostForISP, ispType, splitCbfLumaSum, singleFracBits, singleDistLuma, cuCtx);
1898
340
      partitioner.exitCurrSplit();
1899
340
      bool storeCost = (numMode == 1) ? true : false;
1900
340
      if ((m_pcEncCfg->m_ISP >= 2) && (numMode <= 1))
1901
340
      {
1902
340
        storeCost = true;
1903
340
      }
1904
340
      if (storeCost)
1905
340
      {
1906
340
        m_ispTestedModes[0].bestCost[cu.ispMode - 1] = dSingleCost;
1907
340
      }
1908
340
    }
1909
89.2k
    else
1910
89.2k
    {
1911
89.2k
      TransformUnit& tu =
1912
89.2k
        cs.addTU(CS::getArea(cs, currArea, partitioner.chType, partitioner.treeType), partitioner.chType, cs.cus[0]);
1913
89.2k
      tu.depth = currDepth;
1914
1915
89.2k
      CHECK(!tu.Y().valid(), "Invalid TU");
1916
89.2k
      xIntraCodingTUBlock(tu, COMP_Y, false, singleDistLuma, &numSig, predBuf);
1917
      //----- determine rate and r-d cost -----
1918
89.2k
      m_ispTestedModes[0].IspType = TU_NO_ISP;
1919
89.2k
      m_ispTestedModes[0].subTuCounter = -1;
1920
89.2k
      singleFracBits = xGetIntraFracBitsQT(cs, partitioner, true);
1921
89.2k
      dSingleCost = m_pcRdCost->calcRdCost(singleFracBits, singleDistLuma);
1922
89.2k
    }
1923
89.5k
  }
1924
1925
148k
  if (cu.ispMode)
1926
6.57k
  { 
1927
6.57k
    for (auto& ptu : cs.tus)
1928
10.2k
    {
1929
10.2k
      if (currArea.Y().contains(ptu->Y()))
1930
10.2k
      {
1931
10.2k
        TU::setCbfAtDepth(*ptu, COMP_Y, currDepth, splitCbfLumaSum ? 1 : 0);
1932
10.2k
      }
1933
10.2k
    }
1934
6.57k
  }
1935
148k
  cs.dist     += singleDistLuma;
1936
148k
  cs.fracBits += singleFracBits;
1937
148k
  cs.cost      = dSingleCost;
1938
1939
148k
  STAT_COUNT_CU_MODES( partitioner.chType == CH_L, g_cuCounters1D[CU_RD_TESTS][0][!cs.slice->isIntra() + cs.slice->depth] );
1940
148k
  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
148k
}
1942
1943
ChromaCbfs IntraSearch::xIntraChromaCodingQT(CodingStructure& cs, Partitioner& partitioner)
1944
358k
{
1945
358k
  UnitArea    currArea      = partitioner.currArea();
1946
1947
358k
  if( !currArea.Cb().valid() ) 
1948
0
    return ChromaCbfs(false);
1949
1950
358k
  TransformUnit& currTU     = *cs.getTU( currArea.chromaPos(), CH_C );
1951
358k
  const CodingUnit& cu  = *cs.getCU( currArea.chromaPos(), CH_C, TREE_D );
1952
358k
  ChromaCbfs cbfs(false);
1953
358k
  uint32_t   currDepth = partitioner.currTrDepth;
1954
358k
  const bool useTS = cs.picture->useTS;
1955
358k
  if (currDepth == currTU.depth)
1956
358k
  {
1957
358k
    if (!currArea.Cb().valid() || !currArea.Cr().valid())
1958
0
    {
1959
0
      return cbfs;
1960
0
    }
1961
1962
358k
    CodingStructure& saveCS = *m_pSaveCS[1];
1963
358k
    saveCS.pcv = cs.pcv;
1964
358k
    saveCS.picture = cs.picture;
1965
358k
    saveCS.area.repositionTo(cs.area);
1966
1967
358k
    TransformUnit& tmpTU = saveCS.tus.empty() ? saveCS.addTU(currArea, partitioner.chType, nullptr) : *saveCS.tus.front();
1968
358k
    tmpTU.initData();
1969
358k
    tmpTU.UnitArea::operator=(currArea);
1970
358k
    const unsigned      numTBlocks = getNumberValidTBlocks(*cs.pcv);
1971
1972
358k
    CompArea& cbArea = currTU.blocks[COMP_Cb];
1973
358k
    CompArea& crArea = currTU.blocks[COMP_Cr];
1974
358k
    double     bestCostCb = MAX_DOUBLE;
1975
358k
    double     bestCostCr = MAX_DOUBLE;
1976
358k
    Distortion bestDistCb = 0;
1977
358k
    Distortion bestDistCr = 0;
1978
1979
358k
    TempCtx ctxStartTU(m_CtxCache);
1980
358k
    TempCtx ctxStart(m_CtxCache);
1981
358k
    TempCtx ctxBest(m_CtxCache);
1982
1983
358k
    ctxStartTU = m_CABACEstimator->getCtx();
1984
358k
    ctxStart = m_CABACEstimator->getCtx();
1985
358k
    currTU.jointCbCr = 0;
1986
1987
    // Do predictions here to avoid repeating the "default0Save1Load2" stuff
1988
358k
    int  predMode = cu.bdpcmM[CH_C] ? BDPCM_IDX : CU::getFinalIntraMode(cu, CH_C);
1989
1990
358k
    PelBuf piPredCb = cs.getPredBuf(COMP_Cb);
1991
358k
    PelBuf piPredCr = cs.getPredBuf(COMP_Cr);
1992
1993
358k
    initIntraPatternChType(*currTU.cu, cbArea);
1994
358k
    initIntraPatternChType(*currTU.cu, crArea);
1995
1996
358k
    if (CU::isLMCMode(predMode))
1997
26.0k
    {
1998
26.0k
      loadLMLumaRecPels(cu, cbArea);
1999
26.0k
      predIntraChromaLM(COMP_Cb, piPredCb, cu, cbArea, predMode);
2000
26.0k
      predIntraChromaLM(COMP_Cr, piPredCr, cu, crArea, predMode);
2001
26.0k
    }
2002
332k
    else
2003
332k
    {
2004
332k
      predIntraAng(COMP_Cb, piPredCb, cu);
2005
332k
      predIntraAng(COMP_Cr, piPredCr, cu);
2006
332k
    }
2007
2008
    // determination of chroma residuals including reshaping and cross-component prediction
2009
    //----- get chroma residuals -----
2010
358k
    PelBuf resiCb = cs.getResiBuf(COMP_Cb);
2011
358k
    PelBuf resiCr = cs.getResiBuf(COMP_Cr);
2012
358k
    resiCb.subtract(cs.getOrgBuf(COMP_Cb), piPredCb);
2013
358k
    resiCr.subtract(cs.getOrgBuf(COMP_Cr), piPredCr);
2014
2015
    //===== store original residual signals (std and crossCompPred) =====
2016
2.15M
    for( int k = 0; k < 5; k++ )
2017
1.79M
    {
2018
1.79M
      m_orgResiCb[k].compactResize( cbArea );
2019
1.79M
      m_orgResiCr[k].compactResize( crArea );
2020
1.79M
    }
2021
716k
    for (int k = 0; k < 1; k += 4)
2022
358k
    {
2023
358k
      m_orgResiCb[k].copyFrom(resiCb);
2024
358k
      m_orgResiCr[k].copyFrom(resiCr);
2025
358k
    }
2026
2027
358k
    CUCtx cuCtx;
2028
358k
    cuCtx.isDQPCoded = true;
2029
358k
    cuCtx.isChromaQpAdjCoded = true;
2030
358k
    cuCtx.lfnstLastScanPos = false;
2031
2032
358k
    CodingStructure& saveCScur = *m_pSaveCS[2];
2033
2034
358k
    saveCScur.pcv = cs.pcv;
2035
358k
    saveCScur.picture = cs.picture;
2036
358k
    saveCScur.area.repositionTo(cs.area);
2037
2038
358k
    TransformUnit& tmpTUcur = saveCScur.tus.empty() ? saveCScur.addTU(currArea, partitioner.chType, nullptr) : *saveCScur.tus.front();
2039
358k
    tmpTUcur.initData();
2040
358k
    tmpTUcur.UnitArea::operator=(currArea);
2041
2042
358k
    TempCtx ctxBestTUL(m_CtxCache);
2043
2044
358k
    const SPS& sps = *cs.sps;
2045
358k
    double     bestCostCbcur = MAX_DOUBLE;
2046
358k
    double     bestCostCrcur = MAX_DOUBLE;
2047
358k
    Distortion bestDistCbcur = 0;
2048
358k
    Distortion bestDistCrcur = 0;
2049
2050
358k
    int  endLfnstIdx = (partitioner.isSepTree(cs) && partitioner.chType == CH_C && (partitioner.currArea().lwidth() < 8 || partitioner.currArea().lheight() < 8))
2051
343k
      || (partitioner.currArea().lwidth() > sps.getMaxTbSize() || partitioner.currArea().lheight() > sps.getMaxTbSize()) || !sps.LFNST ? 0 : 2;
2052
358k
    int  startLfnstIdx = 0;
2053
358k
    int  bestLfnstIdx = 0;
2054
358k
    bool testLFNST = sps.LFNST;
2055
2056
    // speedUps LFNST
2057
358k
    bool rapidLFNST = false;
2058
358k
    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
358k
    int ts_used = 0;
2067
358k
    bool testTS = false;
2068
358k
    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
358k
    if (cu.bdpcmM[CH_C])
2078
47.5k
    {
2079
47.5k
      endLfnstIdx = 0;
2080
47.5k
      testLFNST = false;
2081
47.5k
    }
2082
2083
358k
    double dSingleCostAll = MAX_DOUBLE;
2084
358k
    double singleCostTmpAll = 0;
2085
2086
1.31M
    for (int lfnstIdx = startLfnstIdx; lfnstIdx <= endLfnstIdx; lfnstIdx++)
2087
954k
    {
2088
954k
      if (rapidLFNST && lfnstIdx)
2089
0
      {
2090
0
        if ((lfnstIdx == 2) && (bestLfnstIdx == 0))
2091
0
        {
2092
0
          continue;
2093
0
        }
2094
0
      }
2095
2096
954k
      currTU.cu->lfnstIdx = lfnstIdx;
2097
954k
      if (lfnstIdx)
2098
596k
      {
2099
596k
        m_CABACEstimator->getCtx() = ctxStartTU;
2100
596k
      }
2101
2102
954k
      cuCtx.lfnstLastScanPos = false;
2103
954k
      cuCtx.violatesLfnstConstrained[CH_L] = false;
2104
954k
      cuCtx.violatesLfnstConstrained[CH_C] = false;
2105
2106
2.86M
      for (uint32_t c = COMP_Cb; c < numTBlocks; c++)
2107
1.90M
      {
2108
1.90M
        const ComponentID compID = ComponentID(c);
2109
1.90M
        const CompArea& area = currTU.blocks[compID];
2110
1.90M
        double     dSingleCost = MAX_DOUBLE;
2111
1.90M
        Distortion singleDistCTmp = 0;
2112
1.90M
        double     singleCostTmp = 0;
2113
1.90M
        bool tsAllowed = useTS && TU::isTSAllowed(currTU, compID) && m_pcEncCfg->m_useChromaTS && !currTU.cu->lfnstIdx && !cu.bdpcmM[CH_C];
2114
1.90M
        if ((partitioner.chType == CH_L) && (!ts_used))
2115
0
        {
2116
0
          tsAllowed = false;
2117
0
        }
2118
1.90M
        uint8_t nNumTransformCands = 1 + (tsAllowed ? 1 : 0); // DCT + TS = 2 tests       
2119
1.90M
        TrModeList trModes;
2120
1.90M
        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.90M
        bool cbfDCT2 = true;
2127
1.90M
        const bool isLastMode = testLFNST || cs.sps->jointCbCr ||  tsAllowed ? false : true;
2128
1.90M
        int bestModeId = 0;
2129
1.90M
        ctxStart = m_CABACEstimator->getCtx();
2130
3.81M
        for (int modeId = 0; modeId < nNumTransformCands; modeId++)
2131
1.90M
        {
2132
1.90M
          if (lfnstIdx || modeId)
2133
1.19M
          {
2134
1.19M
            resiCb.copyFrom(m_orgResiCb[0]);
2135
1.19M
            resiCr.copyFrom(m_orgResiCr[0]);
2136
1.19M
          }
2137
1.90M
          if (modeId == 0)
2138
1.90M
          {
2139
1.90M
            if ( tsAllowed)
2140
0
            {
2141
0
              xPreCheckMTS(currTU, &trModes, m_pcEncCfg->m_MTSIntraMaxCand, 0, compID);
2142
0
            }
2143
1.90M
          }
2144
2145
1.90M
          currTU.mtsIdx[compID] = currTU.cu->bdpcmM[CH_C] ? MTS_SKIP : modeId;
2146
2147
1.90M
          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.90M
          singleDistCTmp = 0;
2156
1.90M
          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.90M
          else
2165
1.90M
        {
2166
1.90M
          xIntraCodingTUBlock(currTU, compID, false, singleDistCTmp);
2167
1.90M
        }
2168
1.90M
        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.90M
        else
2175
1.90M
        {
2176
1.90M
          uint64_t fracBitsTmp = xGetIntraFracBitsQTChroma(currTU, compID, &cuCtx);
2177
1.90M
          singleCostTmp = m_pcRdCost->calcRdCost(fracBitsTmp, singleDistCTmp);
2178
1.90M
        }
2179
2180
1.90M
        if (singleCostTmp < dSingleCost)
2181
1.90M
        {
2182
1.90M
          dSingleCost = singleCostTmp;
2183
2184
1.90M
          if (compID == COMP_Cb)
2185
954k
          {
2186
954k
            bestCostCb = singleCostTmp;
2187
954k
            bestDistCb = singleDistCTmp;
2188
954k
          }
2189
954k
          else
2190
954k
          {
2191
954k
            bestCostCr = singleCostTmp;
2192
954k
            bestDistCr = singleDistCTmp;
2193
954k
          }
2194
1.90M
          bestModeId = modeId;
2195
1.90M
          if (currTU.mtsIdx[compID] == MTS_DCT2_DCT2)
2196
1.81M
          {
2197
1.81M
            cbfDCT2 = TU::getCbfAtDepth(currTU, compID, currDepth);
2198
1.81M
          }
2199
1.90M
          if (!isLastMode)
2200
1.90M
          {
2201
1.90M
            saveCS.getRecoBuf(area).copyFrom(cs.getRecoBuf(area));
2202
1.90M
            tmpTU.copyComponentFrom(currTU, compID);
2203
1.90M
            ctxBest = m_CABACEstimator->getCtx();
2204
1.90M
          }
2205
1.90M
        }
2206
1.90M
        }
2207
1.90M
        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.90M
      }
2214
2215
954k
      singleCostTmpAll = bestCostCb + bestCostCr;
2216
2217
954k
      bool rootCbfL = false;
2218
954k
      if (testLFNST)
2219
907k
      {
2220
3.62M
        for (uint32_t t = 0; t < getNumberValidTBlocks(*cs.pcv); t++)
2221
2.72M
        {
2222
2.72M
          rootCbfL |= bool(tmpTU.cbf[t]);
2223
2.72M
        }
2224
907k
        if (rapidLFNST && !rootCbfL)
2225
0
        {
2226
0
          endLfnstIdx = lfnstIdx; // end this
2227
0
        }
2228
907k
      }
2229
2230
954k
      if (testLFNST && lfnstIdx && !cuCtx.lfnstLastScanPos)
2231
395k
      {
2232
395k
        bool cbfAtZeroDepth = CU::isSepTree(*currTU.cu)
2233
395k
          ? 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
395k
        if (cbfAtZeroDepth)
2237
2.25k
        {
2238
2.25k
          singleCostTmpAll = MAX_DOUBLE;
2239
2.25k
        }
2240
395k
      }
2241
954k
      if ((testLFNST || testTS) && (singleCostTmpAll < dSingleCostAll))
2242
310k
      {
2243
310k
        bestLfnstIdx = lfnstIdx;
2244
310k
        if ((lfnstIdx != endLfnstIdx) || testTS)
2245
298k
        {
2246
298k
          dSingleCostAll = singleCostTmpAll;
2247
2248
298k
          bestCostCbcur = bestCostCb;
2249
298k
          bestCostCrcur = bestCostCr;
2250
298k
          bestDistCbcur = bestDistCb;
2251
298k
          bestDistCrcur = bestDistCr;
2252
2253
298k
          saveCScur.getRecoBuf(cbArea).copyFrom(saveCS.getRecoBuf(cbArea));
2254
298k
          saveCScur.getRecoBuf(crArea).copyFrom(saveCS.getRecoBuf(crArea));
2255
2256
298k
          tmpTUcur.copyComponentFrom(tmpTU, COMP_Cb);
2257
298k
          tmpTUcur.copyComponentFrom(tmpTU, COMP_Cr);
2258
298k
        }
2259
310k
        ctxBestTUL = m_CABACEstimator->getCtx();
2260
310k
      }
2261
954k
    }
2262
358k
    if ((testLFNST && (bestLfnstIdx != endLfnstIdx)) || testTS)
2263
298k
    {
2264
298k
      bestCostCb = bestCostCbcur;
2265
298k
      bestCostCr = bestCostCrcur;
2266
298k
      bestDistCb = bestDistCbcur;
2267
298k
      bestDistCr = bestDistCrcur;
2268
298k
      currTU.cu->lfnstIdx = bestLfnstIdx;
2269
298k
      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
298k
    }
2280
2281
358k
    Distortion bestDistCbCr = bestDistCb + bestDistCr;
2282
2283
358k
    if (cs.sps->jointCbCr)
2284
358k
    {
2285
358k
      if ((testLFNST && (bestLfnstIdx != endLfnstIdx)) || testTS)
2286
298k
      {
2287
298k
        saveCS.getRecoBuf(cbArea).copyFrom(saveCScur.getRecoBuf(cbArea));
2288
298k
        saveCS.getRecoBuf(crArea).copyFrom(saveCScur.getRecoBuf(crArea));
2289
2290
298k
        tmpTU.copyComponentFrom(tmpTUcur, COMP_Cb);
2291
298k
        tmpTU.copyComponentFrom(tmpTUcur, COMP_Cr);
2292
298k
        m_CABACEstimator->getCtx() = ctxBestTUL;
2293
298k
        ctxBest = m_CABACEstimator->getCtx();
2294
298k
      }
2295
      // Test using joint chroma residual coding
2296
358k
      double     bestCostCbCr = bestCostCb + bestCostCr;
2297
358k
      int        bestJointCbCr = 0;
2298
358k
      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
358k
      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
358k
      bool       lastIsBest = false;
2305
358k
      bool noLFNST1 = false;
2306
358k
      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
1.31M
      for (int lfnstIdxj = startLfnstIdx; lfnstIdxj <= endLfnstIdx; lfnstIdxj++)
2319
954k
      {
2320
954k
        if (rapidLFNST && noLFNST1 && (lfnstIdxj == 1))
2321
0
        {
2322
0
          continue;
2323
0
        }
2324
954k
        currTU.cu->lfnstIdx = lfnstIdxj;
2325
954k
        std::vector<int> jointCbfMasksToTest;
2326
954k
        if (TU::getCbf(tmpTU, COMP_Cb) || TU::getCbf(tmpTU, COMP_Cr))
2327
334k
        {
2328
334k
          jointCbfMasksToTest = m_pcTrQuant->selectICTCandidates(currTU, m_orgResiCb, m_orgResiCr);
2329
334k
        }
2330
954k
        for (int cbfMask : jointCbfMasksToTest)
2331
334k
        {
2332
334k
          currTU.jointCbCr = (uint8_t)cbfMask;
2333
334k
          ComponentID codeCompId = ((currTU.jointCbCr >> 1) ? COMP_Cb : COMP_Cr);
2334
334k
          ComponentID otherCompId = ((codeCompId == COMP_Cb) ? COMP_Cr : COMP_Cb);
2335
334k
          bool tsAllowed = useTS && TU::isTSAllowed(currTU, codeCompId) && (m_pcEncCfg->m_useChromaTS) && !currTU.cu->lfnstIdx && !cu.bdpcmM[CH_C];
2336
334k
          if ((partitioner.chType == CH_L)&& tsAllowed && (currTU.mtsIdx[COMP_Y] != MTS_SKIP))
2337
0
          {
2338
0
            tsAllowed = false;
2339
0
          }
2340
334k
          if (!tsAllowed)
2341
334k
          {
2342
334k
            checkTSOnly = false;
2343
334k
          }
2344
334k
          uint8_t     numTransformCands = 1 + (tsAllowed && !(checkDCTOnly || checkTSOnly)? 1 : 0); // DCT + TS = 2 tests
2345
334k
          TrModeList trModes;
2346
334k
          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
334k
          else
2352
334k
          {
2353
334k
            currTU.mtsIdx[codeCompId] = checkTSOnly || currTU.cu->bdpcmM[CH_C] ? 1 : 0;
2354
334k
          }
2355
2356
669k
          for (int modeId = 0; modeId < numTransformCands; modeId++)
2357
334k
          {
2358
334k
            Distortion distTmp = 0;
2359
334k
            currTU.mtsIdx[codeCompId] = currTU.cu->bdpcmM[CH_C] ? MTS_SKIP : MTS_DCT2_DCT2;
2360
334k
            if (numTransformCands > 1)
2361
0
            {
2362
0
              currTU.mtsIdx[codeCompId] = currTU.cu->bdpcmM[CH_C] ? MTS_SKIP : trModes[modeId].first;
2363
0
            }
2364
334k
            currTU.mtsIdx[otherCompId] = MTS_DCT2_DCT2;
2365
2366
334k
            m_CABACEstimator->getCtx() = ctxStartTU;
2367
2368
334k
            resiCb.copyFrom(m_orgResiCb[cbfMask]);
2369
334k
            resiCr.copyFrom(m_orgResiCr[cbfMask]);
2370
334k
            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
334k
            cuCtx.lfnstLastScanPos = false;
2377
334k
            cuCtx.violatesLfnstConstrained[CH_L] = false;
2378
334k
            cuCtx.violatesLfnstConstrained[CH_C] = false;
2379
334k
            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
334k
            else
2388
334k
            {
2389
334k
              xIntraCodingTUBlock(currTU, COMP_Cb, false, distTmp, 0);
2390
334k
            }
2391
2392
334k
            double costTmp = std::numeric_limits<double>::max();
2393
334k
            if (distTmp < MAX_DISTORTION)
2394
329k
            {
2395
329k
              uint64_t bits = xGetIntraFracBitsQTChroma(currTU, COMP_Cb, &cuCtx);
2396
329k
              costTmp = m_pcRdCost->calcRdCost(bits, distTmp);
2397
329k
            }
2398
4.86k
            else if (!currTU.mtsIdx[codeCompId])
2399
4.86k
            {
2400
4.86k
              numTransformCands = 1;
2401
4.86k
            }
2402
334k
            bool rootCbfL = false;
2403
1.33M
            for (uint32_t t = 0; t < getNumberValidTBlocks(*cs.pcv); t++)
2404
1.00M
            {
2405
1.00M
              rootCbfL |= bool(tmpTU.cbf[t]);
2406
1.00M
            }
2407
334k
            if (rapidLFNST && !rootCbfL)
2408
0
            {
2409
0
              endLfnstIdx = lfnstIdxj;
2410
0
            }
2411
334k
            if (testLFNST && currTU.cu->lfnstIdx && !cuCtx.lfnstLastScanPos)
2412
4.80k
            {
2413
4.80k
              bool cbfAtZeroDepth = CU::isSepTree(*currTU.cu) ? rootCbfL
2414
4.80k
                : (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
4.80k
              if (cbfAtZeroDepth)
2417
4.80k
              {
2418
4.80k
                costTmp = MAX_DOUBLE;
2419
4.80k
              }
2420
4.80k
            }
2421
334k
            if (costTmp < bestCostCbCr)
2422
125k
            {
2423
125k
              bestCostCbCr = costTmp;
2424
125k
              bestDistCbCr = distTmp;
2425
125k
              bestJointCbCr = currTU.jointCbCr;
2426
2427
              // store data
2428
125k
              bestLfnstIdx = lfnstIdxj;
2429
125k
              if ((cbfMask != jointCbfMasksToTest.back() || (lfnstIdxj != endLfnstIdx)) || (modeId != (numTransformCands - 1)))
2430
102k
              {
2431
102k
                saveCS.getRecoBuf(cbArea).copyFrom(cs.getRecoBuf(cbArea));
2432
102k
                saveCS.getRecoBuf(crArea).copyFrom(cs.getRecoBuf(crArea));
2433
2434
102k
                tmpTU.copyComponentFrom(currTU, COMP_Cb);
2435
102k
                tmpTU.copyComponentFrom(currTU, COMP_Cr);
2436
2437
102k
                ctxBest = m_CABACEstimator->getCtx();
2438
102k
              }
2439
23.0k
              else
2440
23.0k
              {
2441
23.0k
                lastIsBest = true;
2442
23.0k
                cs.cus[0]->lfnstIdx = bestLfnstIdx;
2443
23.0k
              }
2444
125k
            }
2445
334k
          }
2446
334k
        }
2447
2448
        // Retrieve the best CU data (unless it was the very last one tested)
2449
954k
      }
2450
358k
      if (!lastIsBest)
2451
335k
      {
2452
335k
        cs.getRecoBuf(cbArea).copyFrom(saveCS.getRecoBuf(cbArea));
2453
335k
        cs.getRecoBuf(crArea).copyFrom(saveCS.getRecoBuf(crArea));
2454
2455
335k
        cs.cus[0]->lfnstIdx = bestLfnstIdx;
2456
335k
        currTU.copyComponentFrom(tmpTU, COMP_Cb);
2457
335k
        currTU.copyComponentFrom(tmpTU, COMP_Cr);
2458
335k
        m_CABACEstimator->getCtx() = ctxBest;
2459
335k
      }
2460
358k
      currTU.jointCbCr = (TU::getCbf(currTU, COMP_Cb) || TU::getCbf(currTU, COMP_Cr)) ? bestJointCbCr : 0;
2461
358k
    } // jointCbCr
2462
2463
358k
    cs.dist += bestDistCbCr;
2464
358k
    cuCtx.violatesLfnstConstrained[CH_L] = false;
2465
358k
    cuCtx.violatesLfnstConstrained[CH_C] = false;
2466
358k
    cuCtx.lfnstLastScanPos = false;
2467
358k
    cuCtx.violatesMtsCoeffConstraint = false;
2468
358k
    cuCtx.mtsLastScanPos = false;
2469
358k
    cbfs.cbf(COMP_Cb) = TU::getCbf(currTU, COMP_Cb);
2470
358k
    cbfs.cbf(COMP_Cr) = TU::getCbf(currTU, COMP_Cr);
2471
358k
  }
2472
2
  else
2473
2
  {
2474
2
    unsigned   numValidTBlocks = getNumberValidTBlocks(*cs.pcv);
2475
2
    ChromaCbfs SplitCbfs(false);
2476
2477
2
    if (partitioner.canSplit(TU_MAX_TR_SPLIT, cs))
2478
0
    {
2479
0
      partitioner.splitCurrArea(TU_MAX_TR_SPLIT, cs);
2480
0
    }
2481
2
    else if (currTU.cu->ispMode)
2482
0
    {
2483
0
      partitioner.splitCurrArea(m_ispTestedModes[0].IspType, cs);
2484
0
    }
2485
2
    else
2486
2
      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
358k
  return cbfs;
2523
358k
}
2524
2525
uint64_t IntraSearch::xFracModeBitsIntraLuma(const CodingUnit& cu, const unsigned* mpmLst)
2526
1.21M
{
2527
1.21M
  m_CABACEstimator->resetBits();
2528
2529
1.21M
  if (!cu.ciip)
2530
1.21M
  {
2531
1.21M
    m_CABACEstimator->intra_luma_pred_mode(cu, mpmLst);
2532
1.21M
  }
2533
2534
1.21M
  return m_CABACEstimator->getEstFracBits();
2535
1.21M
}
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
24.8k
{
2540
24.8k
  const int maxCandPerType = numModesForFullRD >> 1;
2541
24.8k
  static_vector<ModeInfo, FAST_UDI_MAX_RDMODE_NUM> tempRdModeList;
2542
24.8k
  static_vector<double, FAST_UDI_MAX_RDMODE_NUM> tempCandCostList;
2543
24.8k
  const double minCost = candCostList[0];
2544
24.8k
  bool keepOneMip = candModeList.size() > numModesForFullRD;
2545
24.8k
  const int maxNumConv = 3; 
2546
2547
24.8k
  int numConv = 0;
2548
24.8k
  int numMip = 0;
2549
112k
  for (int idx = 0; idx < candModeList.size() - (keepOneMip?0:1); idx++)
2550
87.6k
  {
2551
87.6k
    bool addMode = false;
2552
87.6k
    const ModeInfo& orgMode = candModeList[idx];
2553
2554
87.6k
    if (!orgMode.mipFlg)
2555
62.8k
    {
2556
62.8k
      addMode = (numConv < maxNumConv);
2557
62.8k
      numConv += addMode ? 1:0;
2558
62.8k
    }
2559
24.8k
    else
2560
24.8k
    {
2561
24.8k
      addMode = ( numMip < maxCandPerType || (candCostList[idx] < thresholdHadCost * minCost) || keepOneMip );
2562
24.8k
      keepOneMip = false;
2563
24.8k
      numMip += addMode ? 1:0;
2564
24.8k
    }
2565
87.6k
    if( addMode )
2566
87.6k
    {
2567
87.6k
      tempRdModeList.push_back(orgMode);
2568
87.6k
      tempCandCostList.push_back(candCostList[idx]);
2569
87.6k
    }
2570
87.6k
  }
2571
2572
  // sort Pel Buffer
2573
24.8k
  int i = -1;
2574
24.8k
  for( auto &m: tempRdModeList)
2575
87.6k
  {
2576
87.6k
    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
87.6k
  }
2588
24.8k
  sortedPelBuffer.reduceTo( (int)tempRdModeList.size() );
2589
2590
24.8k
  if ((cu.lwidth() > 8 && cu.lheight() > 8))
2591
22.4k
  {
2592
    // Sort MIP candidates by Hadamard cost
2593
22.4k
    const int transpOff = getNumModesMip(cu.Y());
2594
22.4k
    static_vector<uint8_t, FAST_UDI_MAX_RDMODE_NUM> sortedMipModes(0);
2595
22.4k
    static_vector<double, FAST_UDI_MAX_RDMODE_NUM> sortedMipCost(0);
2596
22.4k
    for (uint8_t mode : { 0, 1, 2 })
2597
67.2k
    {
2598
67.2k
      uint8_t candMode = mode + uint8_t((mipHadCost[mode + transpOff] < mipHadCost[mode]) ? transpOff : 0);
2599
67.2k
      updateCandList(candMode, mipHadCost[candMode], sortedMipModes, sortedMipCost, 3);
2600
67.2k
    }
2601
2602
    // Append MIP mode to RD mode list
2603
22.4k
    const int modeListSize = int(tempRdModeList.size());
2604
44.8k
    for (int idx = 0; idx < 3; idx++)
2605
44.8k
    {
2606
44.8k
      const bool     isTransposed = (sortedMipModes[idx] >= transpOff ? true : false);
2607
44.8k
      const uint32_t mipIdx       = (isTransposed ? sortedMipModes[idx] - transpOff : sortedMipModes[idx]);
2608
44.8k
      const ModeInfo mipMode( true, isTransposed, 0, NOT_INTRA_SUBPARTITIONS, mipIdx );
2609
44.8k
      bool alreadyIncluded = false;
2610
179k
      for (int modeListIdx = 0; modeListIdx < modeListSize; modeListIdx++)
2611
157k
      {
2612
157k
        if (tempRdModeList[modeListIdx] == mipMode)
2613
22.4k
        {
2614
22.4k
          alreadyIncluded = true;
2615
22.4k
          break;
2616
22.4k
        }
2617
157k
      }
2618
2619
44.8k
      if (!alreadyIncluded)
2620
22.4k
      {
2621
22.4k
        tempRdModeList.push_back(mipMode);
2622
22.4k
        tempCandCostList.push_back(0);
2623
22.4k
        if( fastMip ) break;
2624
22.4k
      }
2625
44.8k
    }
2626
22.4k
  }
2627
2628
24.8k
  candModeList = tempRdModeList;
2629
24.8k
  candCostList = tempCandCostList;
2630
24.8k
  numModesForFullRD = int(candModeList.size());
2631
24.8k
}
2632
2633
void IntraSearch::xPreCheckMTS(TransformUnit &tu, TrModeList *trModes, const int maxCand, PelUnitBuf *predBuf, const ComponentID& compID)
2634
17.3k
{
2635
17.3k
  if (compID == COMP_Y)
2636
17.3k
  {
2637
17.3k
    CodingStructure&  cs = *tu.cs;
2638
17.3k
    const CompArea& area = tu.blocks[compID];
2639
17.3k
    const CodingUnit& cu = *cs.getCU(area.pos(), CH_L,TREE_D);
2640
17.3k
    PelBuf piPred = cs.getPredBuf(area);
2641
17.3k
    PelBuf piResi = cs.getResiBuf(area);
2642
2643
17.3k
    initIntraPatternChType(*tu.cu, area);
2644
17.3k
    if (predBuf)
2645
15.5k
    {
2646
15.5k
      piPred.copyFrom(predBuf->Y());
2647
15.5k
    }
2648
1.79k
    else if (CU::isMIP(cu, CH_L))
2649
1.77k
    {
2650
1.77k
      initIntraMip(cu);
2651
1.77k
      predIntraMip(piPred, cu);
2652
1.77k
    }
2653
23
    else
2654
23
    {
2655
23
      predIntraAng(COMP_Y, piPred, cu);
2656
23
    }
2657
2658
    //===== get residual signal =====
2659
17.3k
    CPelBuf piOrg = cs.getOrgBuf(COMP_Y);
2660
17.3k
    piResi.subtract(piOrg, piPred);
2661
17.3k
    m_pcTrQuant->checktransformsNxN(tu, trModes, m_pcEncCfg->m_MTSIntraMaxCand, compID);
2662
17.3k
  }
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
17.3k
}
2669
2670
double IntraSearch::xTestISP(CodingStructure& cs, Partitioner& subTuPartitioner, double bestCostForISP, PartSplit ispType, bool& splitcbf, uint64_t& singleFracBits, Distortion& singleDistLuma, CUCtx& cuCtx)
2671
19.0k
{
2672
19.0k
  int  subTuCounter = 0;
2673
19.0k
  bool earlySkipISP = false;
2674
19.0k
  bool splitCbfLuma = false;
2675
19.0k
  CodingUnit& cu = *cs.cus[0];
2676
2677
19.0k
  Distortion singleDistTmpLumaSUM = 0;
2678
19.0k
  uint64_t   singleTmpFracBitsSUM = 0;
2679
19.0k
  double     singleCostTmpSUM = 0;
2680
19.0k
  cuCtx.isDQPCoded = true;
2681
19.0k
  cuCtx.isChromaQpAdjCoded = true;
2682
2683
19.0k
  do
2684
23.7k
  {
2685
23.7k
    Distortion singleDistTmpLuma = 0;
2686
23.7k
    uint64_t   singleTmpFracBits = 0;
2687
23.7k
    double     singleCostTmp = 0;
2688
23.7k
    TransformUnit& tmpTUcur = ((cs.tus.size() < (subTuCounter + 1)))
2689
23.7k
      ? cs.addTU(CS::getArea(cs, subTuPartitioner.currArea(), subTuPartitioner.chType,
2690
3.97k
        subTuPartitioner.treeType),
2691
3.97k
        subTuPartitioner.chType, cs.cus[0])
2692
23.7k
      : *cs.tus[subTuCounter];
2693
23.7k
    tmpTUcur.depth = subTuPartitioner.currTrDepth;
2694
2695
    // Encode TU
2696
23.7k
    xIntraCodingTUBlock(tmpTUcur, COMP_Y, false, singleDistTmpLuma, 0);
2697
23.7k
    cuCtx.mtsLastScanPos = false;
2698
2699
23.7k
    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
23.7k
    if (m_pcRdCost->calcRdCost(singleTmpFracBitsSUM, singleDistTmpLumaSUM + singleDistTmpLuma) > bestCostForISP)
2707
6.49k
    {
2708
6.49k
      earlySkipISP = true;
2709
6.49k
    }
2710
17.2k
    else
2711
17.2k
    {
2712
17.2k
      m_ispTestedModes[0].IspType = ispType;
2713
17.2k
      m_ispTestedModes[0].subTuCounter = subTuCounter;
2714
17.2k
      singleTmpFracBits = xGetIntraFracBitsQT(cs, subTuPartitioner, true, &cuCtx);
2715
17.2k
    }
2716
23.7k
    singleCostTmp = m_pcRdCost->calcRdCost(singleTmpFracBits, singleDistTmpLuma);
2717
2718
23.7k
    singleCostTmpSUM     += singleCostTmp;
2719
23.7k
    singleDistTmpLumaSUM += singleDistTmpLuma;
2720
23.7k
    singleTmpFracBitsSUM += singleTmpFracBits;
2721
2722
23.7k
    subTuCounter++;
2723
2724
23.7k
    splitCbfLuma |= TU::getCbfAtDepth( *cs.getTU(subTuPartitioner.currArea().lumaPos(), subTuPartitioner.chType, subTuCounter - 1), 
2725
23.7k
                                       COMP_Y, subTuPartitioner.currTrDepth);
2726
23.7k
    int nSubPartitions = m_ispTestedModes[cu.lfnstIdx].numTotalParts[cu.ispMode - 1];
2727
23.7k
    bool doStop = (m_pcEncCfg->m_ISP != 1) || (subTuCounter < nSubPartitions);
2728
23.7k
    if (doStop)
2729
23.7k
    {
2730
23.7k
      if (singleCostTmpSUM > bestCostForISP)
2731
16.2k
      {
2732
16.2k
        earlySkipISP = true;
2733
16.2k
        break;
2734
16.2k
      }
2735
7.49k
      if (subTuCounter < nSubPartitions)
2736
5.98k
      {
2737
5.98k
        double threshold = nSubPartitions == 2 ? 0.95 : subTuCounter == 1 ? 0.83 : 0.91;
2738
5.98k
        if (singleCostTmpSUM > bestCostForISP * threshold)
2739
1.27k
        {
2740
1.27k
          earlySkipISP = true;
2741
1.27k
          break;
2742
1.27k
        }
2743
5.98k
      }
2744
7.49k
    }
2745
23.7k
  } while (subTuPartitioner.nextPart(cs));
2746
19.0k
  singleDistLuma = singleDistTmpLumaSUM;
2747
19.0k
  singleFracBits = singleTmpFracBitsSUM;
2748
2749
19.0k
  splitcbf = splitCbfLuma;
2750
19.0k
  return earlySkipISP ? MAX_DOUBLE : singleCostTmpSUM;
2751
19.0k
}
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
17.0k
{
2755
17.0k
  if (speed)
2756
6.91k
  {
2757
6.91k
    if (mode >= 1)
2758
3.61k
    {
2759
3.61k
      if (m_ispTestedModes[0].splitIsFinished[1] && m_ispTestedModes[0].splitIsFinished[0])
2760
0
      {
2761
0
        testISP = false;
2762
0
        endISP = 0;
2763
0
      }
2764
3.61k
      else
2765
3.61k
      {
2766
3.61k
        if (m_pcEncCfg->m_ISP >= 2)
2767
3.61k
        {
2768
3.61k
          if (mode == 1) //best Hor||Ver
2769
3.29k
          {
2770
3.29k
            int bestDir = 0;
2771
9.88k
            for (int d = 0; d < 2; d++)
2772
6.58k
            {
2773
6.58k
              int d2 = d ? 0 : 1;
2774
6.58k
              if ((m_ispTestedModes[0].bestCost[d] <= m_ispTestedModes[0].bestCost[d2])
2775
6.26k
                && (m_ispTestedModes[0].bestCost[d] != MAX_DOUBLE))
2776
323
              {
2777
323
                bestDir = d + 1;
2778
323
                m_ispTestedModes[0].splitIsFinished[d2] = true;
2779
323
              }
2780
6.58k
            }
2781
3.29k
            m_ispTestedModes[0].bestModeSoFar = bestDir;
2782
3.29k
            if (m_ispTestedModes[0].bestModeSoFar <= 0)
2783
2.97k
            {
2784
2.97k
              m_ispTestedModes[0].splitIsFinished[1] = true;
2785
2.97k
              m_ispTestedModes[0].splitIsFinished[0] = true;
2786
2.97k
              testISP = false;
2787
2.97k
              endISP = 0;
2788
2.97k
            }
2789
3.29k
          }
2790
3.61k
          if (m_ispTestedModes[0].bestModeSoFar == 2)
2791
74
          {
2792
74
            noISP = 1;
2793
74
          }
2794
3.54k
          else
2795
3.54k
          {
2796
3.54k
            endISP = 1;
2797
3.54k
          }
2798
3.61k
        }
2799
3.61k
      }
2800
3.61k
    }
2801
6.91k
    if (testISP)
2802
3.94k
    {
2803
3.94k
      if (mode == 2)
2804
323
      {
2805
969
        for (int d = 0; d < 2; d++)
2806
646
        {
2807
646
          int d2 = d ? 0 : 1;
2808
646
          if (m_ispTestedModes[0].bestCost[d] == MAX_DOUBLE)
2809
300
          {
2810
300
            m_ispTestedModes[0].splitIsFinished[d] = true;
2811
300
          }
2812
646
          if ((m_ispTestedModes[0].bestCost[d2] < 1.3 * m_ispTestedModes[0].bestCost[d])
2813
346
            && (int(m_ispTestedModes[0].bestSplitSoFar) != (d + 1)))
2814
256
          {
2815
256
            if (d)
2816
219
            {
2817
219
              endISP = 1;
2818
219
            }
2819
37
            else
2820
37
            {
2821
37
              noISP = 1;
2822
37
            }
2823
256
            m_ispTestedModes[0].splitIsFinished[d] = true;
2824
256
          }
2825
646
        }
2826
323
      }
2827
3.61k
      else
2828
3.61k
      {
2829
3.61k
        if (m_ispTestedModes[0].splitIsFinished[0])
2830
37
        {
2831
37
          noISP = 1;
2832
37
        }
2833
3.61k
        if (m_ispTestedModes[0].splitIsFinished[1])
2834
286
        {
2835
286
          endISP = 1;
2836
286
        }
2837
3.61k
      }
2838
3.94k
    }
2839
6.91k
    if ((noISP == 1) && (endISP == 1))
2840
23
    {
2841
23
      endISP = 0;
2842
23
    }
2843
6.91k
  }
2844
10.1k
  else
2845
10.1k
  {
2846
10.1k
    bool stopFound = false;
2847
10.1k
    if (m_pcEncCfg->m_ISP >= 3)
2848
10.1k
    {
2849
10.1k
      if (mode)
2850
3.59k
      {
2851
3.59k
        if ((bestISP == 0) || ((bestPUMode.modeId != RdModeList[mode - 1].modeId)
2852
103
          && (bestPUMode.modeId != RdModeList[mode].modeId)))
2853
2.59k
        {
2854
2.59k
          stopFound = true;
2855
2.59k
        }
2856
3.59k
      }
2857
10.1k
    }
2858
10.1k
    if (cu.mipFlag || cu.multiRefIdx)
2859
198
    {
2860
198
      cu.mipFlag = false;
2861
198
      cu.multiRefIdx = 0;
2862
198
      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
198
    }
2874
10.1k
    if (stopFound)
2875
2.59k
    {
2876
2.59k
      testISP = false;
2877
2.59k
      endISP = 0;
2878
2.59k
      return 1;
2879
2.59k
    }
2880
7.58k
    if (!stopFound && (m_pcEncCfg->m_ISP >= 2) && (cu.intraDir[CH_L] == DC_IDX))
2881
1.00k
    {
2882
1.00k
      stopFound = true;
2883
1.00k
      endISP = 0;
2884
1.00k
      return 1;
2885
1.00k
    }
2886
7.58k
  }
2887
13.4k
  return 0;
2888
17.0k
}
2889
2890
void IntraSearch::xSpeedUpIntra(double bestcost, int& EndMode, int& speedIntra, CodingUnit& cu)
2891
32.4k
{
2892
32.4k
  int bestIdxbefore = m_ispTestedModes[0].bestIntraMode;
2893
32.4k
  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
32.4k
  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
32.4k
  if (m_ispTestedModes[0].bestBefore[0] == -1)
2912
29.1k
  {
2913
29.1k
    speedIntra |= 7;
2914
29.1k
    if (m_pcEncCfg->m_FastIntraTools == 2)
2915
0
    {
2916
0
      EndMode = 1;
2917
0
    }
2918
29.1k
  }
2919
32.4k
  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
32.4k
}
2935
2936
} // namespace vvenc
2937
2938
//! \}
2939