Coverage Report

Created: 2026-08-31 06:22

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