Coverage Report

Created: 2026-09-14 06:44

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.1k
  : m_pSaveCS       (nullptr)
68
19.1k
  , m_pcEncCfg      (nullptr)
69
19.1k
  , m_pcTrQuant     (nullptr)
70
19.1k
  , m_pcRdCost      (nullptr)
71
19.1k
  , m_CABACEstimator(nullptr)
72
19.1k
  , m_CtxCache      (nullptr)
73
19.1k
{
74
19.1k
}
75
76
void IntraSearch::init(const VVEncCfg &encCfg, TrQuant *pTrQuant, RdCost *pRdCost, SortedPelUnitBufs<SORTED_BUFS> *pSortedPelUnitBufs, XUCache &unitCache )
77
19.1k
{
78
19.1k
  IntraPrediction::init( encCfg.m_internChromaFormat, encCfg.m_internalBitDepth[ CH_L ] );
79
80
19.1k
  m_pcEncCfg          = &encCfg;
81
19.1k
  m_pcTrQuant         = pTrQuant;
82
19.1k
  m_pcRdCost          = pRdCost;
83
19.1k
  m_SortedPelUnitBufs = pSortedPelUnitBufs;
84
85
19.1k
  const ChromaFormat chrFormat = encCfg.m_internChromaFormat;
86
19.1k
  const int maxCUSize          = encCfg.m_CTUSize;
87
88
19.1k
  Area area = Area( 0, 0, maxCUSize, maxCUSize );
89
90
19.1k
  m_pTempCS = new CodingStructure( unitCache, nullptr );
91
19.1k
  m_pBestCS = new CodingStructure( unitCache, nullptr );
92
93
19.1k
  m_pTempCS->createForSearch( chrFormat, area );
94
19.1k
  m_pBestCS->createForSearch( chrFormat, area );
95
96
19.1k
  const int uiNumSaveLayersToAllocate = 3;
97
19.1k
  m_pSaveCS = new CodingStructure*[uiNumSaveLayersToAllocate];
98
76.7k
  for( int layer = 0; layer < uiNumSaveLayersToAllocate; layer++ )
99
57.5k
  {
100
57.5k
    m_pSaveCS[ layer ] = new CodingStructure( unitCache, nullptr );
101
57.5k
    m_pSaveCS[ layer ]->createForSearch( chrFormat, Area( 0, 0, maxCUSize, maxCUSize ) );
102
57.5k
    m_pSaveCS[ layer ]->initStructData();
103
57.5k
  }
104
105
19.1k
  CompArea chromaArea( COMP_Cb, chrFormat, area, true );
106
115k
  for( int i = 0; i < 5; i++ )
107
95.9k
  {
108
95.9k
    m_orgResiCb[i].create( chromaArea );
109
95.9k
    m_orgResiCr[i].create( chromaArea );
110
95.9k
  }
111
19.1k
}
112
113
void IntraSearch::destroy()
114
19.1k
{
115
19.1k
  if ( m_pSaveCS )
116
19.1k
  {
117
19.1k
    const int uiNumSaveLayersToAllocate = 3;
118
76.7k
    for( int layer = 0; layer < uiNumSaveLayersToAllocate; layer++ )
119
57.5k
    {
120
57.5k
      if ( m_pSaveCS[ layer ] ) { m_pSaveCS[ layer ]->destroy(); delete m_pSaveCS[ layer ]; }
121
57.5k
    }
122
19.1k
    delete[] m_pSaveCS;
123
19.1k
    m_pSaveCS = nullptr;
124
19.1k
  }
125
126
19.1k
  if( m_pTempCS )
127
19.1k
  {
128
19.1k
    m_pTempCS->destroy();
129
19.1k
    delete m_pTempCS; m_pTempCS = nullptr;
130
19.1k
  }
131
132
19.1k
  if( m_pBestCS )
133
19.1k
  {
134
19.1k
    m_pBestCS->destroy();
135
19.1k
    delete m_pBestCS; m_pBestCS = nullptr;
136
19.1k
  }
137
19.1k
}
138
139
IntraSearch::~IntraSearch()
140
19.1k
{
141
19.1k
  destroy();
142
19.1k
}
143
144
void IntraSearch::setCtuEncRsrc( CABACWriter* cabacEstimator, CtxCache *ctxCache )
145
3.84k
{
146
3.84k
  m_CABACEstimator = cabacEstimator;
147
3.84k
  m_CtxCache       = ctxCache;
148
3.84k
}
149
150
//////////////////////////////////////////////////////////////////////////
151
// INTRA PREDICTION
152
//////////////////////////////////////////////////////////////////////////
153
static constexpr double COST_UNKNOWN = -65536.0;
154
155
double IntraSearch::xFindInterCUCost( CodingUnit &cu )
156
25.1k
{
157
25.1k
  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.1k
  return COST_UNKNOWN;
169
25.1k
}
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.1k
{
177
25.1k
  PROFILER_SCOPE_AND_STAGE_EXT( 1, _TPROF, P_INTRA_EST_RD_CAND, cu.cs, CH_L );
178
25.1k
  const uint16_t intra_ctx_size = Ctx::IntraLumaMpmFlag.size() + Ctx::IntraLumaPlanarFlag.size() + Ctx::MultiRefLineIdx.size() + Ctx::ISPMode.size() + Ctx::MipFlag.size();
179
25.1k
  const TempCtx  ctxStartIntraCtx(m_CtxCache, SubCtx(CtxSet(Ctx::IntraLumaMpmFlag(), intra_ctx_size), m_CABACEstimator->getCtx()));
180
25.1k
  const double   sqrtLambdaForFirstPass = m_pcRdCost->getMotionLambda() * FRAC_BITS_SCALE;
181
25.1k
  const int numModesAvailable = NUM_LUMA_MODE; // total number of Intra modes
182
183
25.1k
  CHECK(numModesForFullRD >= numModesAvailable, "Too many modes for full RD search");
184
185
25.1k
  const SPS& sps     = *cu.cs->sps;
186
25.1k
  const bool fastMip = sps.MIP && m_pcEncCfg->m_useFastMIP;
187
188
  // this should always be true
189
25.1k
  CHECK( !cu.Y().valid(), "CU is not valid" );
190
191
25.1k
  const CompArea& area = cu.Y();
192
193
25.1k
  const UnitArea localUnitArea(area.chromaFormat, Area(0, 0, area.width, area.height));
194
25.1k
  if( testMip)
195
19.2k
  {
196
19.2k
    numModesForFullRD += fastMip ? numModesForFullRD - std::min( m_pcEncCfg->m_useFastMIP, numModesForFullRD )
197
19.2k
                                 : numModesForFullRD;
198
19.2k
    m_SortedPelUnitBufs->prepare( localUnitArea, numModesForFullRD + 1 );
199
19.2k
  }
200
5.88k
  else
201
5.88k
  {
202
5.88k
    m_SortedPelUnitBufs->prepare( localUnitArea, numModesForFullRD );
203
5.88k
  }
204
205
25.1k
  CPelBuf piOrg   = cu.cs->getOrgBuf(COMP_Y);
206
25.1k
  PelBuf piPred  = m_SortedPelUnitBufs->getTestBuf(COMP_Y);
207
208
25.1k
  DistParam distParam    = m_pcRdCost->setDistParam( piOrg, piPred, sps.bitDepths[ CH_L ], DF_HAD_2SAD); // Use HAD (SATD) cost
209
210
25.1k
  const int numHadCand = (testMip ? 2 : 1) * 3;
211
212
  //*** Derive (regular) candidates using Hadamard
213
25.1k
  cu.mipFlag = false;
214
25.1k
  cu.multiRefIdx = 0;
215
216
  //===== init pattern for luma prediction =====
217
25.1k
  initIntraPatternChType(cu, cu.Y(), true);
218
219
25.1k
  bool satdChecked[NUM_INTRA_MODE] = { false };
220
221
25.1k
  unsigned mpmLst[NUM_MOST_PROBABLE_MODES];
222
25.1k
  CU::getIntraMPMs(cu, mpmLst);
223
224
25.1k
  const int decMsk = ( 1 << m_pcEncCfg->m_IntraEstDecBit ) - 1;
225
226
25.1k
  m_parentCandList.resize( 0 );
227
25.1k
  m_parentCandList.reserve( ( numModesAvailable >> m_pcEncCfg->m_IntraEstDecBit ) + 2 );
228
229
1.70M
  for( unsigned mode = 0; mode < numModesAvailable; mode++ )
230
1.68M
  {
231
    // Skip checking extended Angular modes in the first round of SATD
232
1.68M
    if( mode > DC_IDX && ( mode & decMsk ) )
233
1.23M
    {
234
1.23M
      continue;
235
1.23M
    }
236
237
452k
    m_parentCandList.push_back( ModeInfo( false, false, 0, NOT_INTRA_SUBPARTITIONS, mode ) );
238
452k
  }
239
   
240
100k
  for( int decDst = 1 << m_pcEncCfg->m_IntraEstDecBit; decDst > 0; decDst >>= 1 )
241
75.4k
  {
242
678k
    for( unsigned idx = 0; idx < m_parentCandList.size(); idx++ )
243
603k
    {
244
603k
      int modeParent = m_parentCandList[idx].modeId;
245
246
603k
      int off = decDst & decMsk;
247
603k
      int inc = decDst << 1;
248
249
603k
#if 1 // INTRA_AS_IN_VTM
250
603k
      if( off != 0 && ( modeParent <= ( DC_IDX + 1 ) || modeParent >= ( NUM_LUMA_MODE - 1 ) ) )
251
98.1k
      {
252
98.1k
        continue;
253
98.1k
      }
254
255
505k
#endif
256
1.06M
      for( int mode = modeParent - off; mode < modeParent + off + 1; mode += inc )
257
557k
      {
258
557k
        if( satdChecked[mode] || mode < 0 || mode >= NUM_LUMA_MODE )
259
2.28k
        {
260
2.28k
          continue;
261
2.28k
        }
262
263
555k
        cu.intraDir[0] = mode;
264
265
555k
        initPredIntraParams( cu, cu.Y(), sps );
266
555k
        distParam.cur.buf = piPred.buf = m_SortedPelUnitBufs->getTestBuf().Y().buf;
267
555k
        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
555k
        Distortion minSadHad = distParam.distFunc( distParam );
272
273
555k
        uint64_t fracModeBits = xFracModeBitsIntraLuma( cu, mpmLst );
274
275
        //restore ctx
276
555k
        m_CABACEstimator->getCtx() = SubCtx( CtxSet( Ctx::IntraLumaMpmFlag(), intra_ctx_size ), ctxStartIntraCtx );
277
278
555k
        double cost = ( double ) minSadHad + ( double ) fracModeBits * sqrtLambdaForFirstPass;
279
555k
        DTRACE( g_trace_ctx, D_INTRA_COST, "IntraHAD: %u, %llu, %f (%d)\n", minSadHad, fracModeBits, cost, mode );
280
281
555k
        int insertPos = -1;
282
555k
        updateCandList( ModeInfo( false, false, 0, NOT_INTRA_SUBPARTITIONS, mode ), cost, RdModeList, CandCostList, numModesForFullRD, &insertPos );
283
555k
        updateCandList( ModeInfo( false, false, 0, NOT_INTRA_SUBPARTITIONS, mode ), ( double ) minSadHad, HadModeList, CandHadList, numHadCand );
284
555k
        m_SortedPelUnitBufs->insert( insertPos, ( int ) RdModeList.size() );
285
286
555k
        satdChecked[mode] = true;
287
555k
      }
288
505k
    }
289
290
75.4k
    m_parentCandList.resize( RdModeList.size() );
291
75.4k
    std::copy( RdModeList.cbegin(), RdModeList.cend(), m_parentCandList.begin() );
292
75.4k
  }
293
294
25.1k
  const bool isFirstLineOfCtu = (((cu.block(COMP_Y).y)&((cu.cs->sps)->CTUSize - 1)) == 0);
295
25.1k
  if( m_pcEncCfg->m_MRL && ! isFirstLineOfCtu )
296
15.1k
  {
297
15.1k
    cu.multiRefIdx = 1;
298
15.1k
    unsigned  multiRefMPM [NUM_MOST_PROBABLE_MODES];
299
15.1k
    CU::getIntraMPMs(cu, multiRefMPM);
300
301
45.4k
    for (int mRefNum = 1; mRefNum < MRL_NUM_REF_LINES; mRefNum++)
302
30.2k
    {
303
30.2k
      int multiRefIdx = MULTI_REF_LINE_IDX[mRefNum];
304
305
30.2k
      cu.multiRefIdx = multiRefIdx;
306
30.2k
      initIntraPatternChType(cu, cu.Y(), true);
307
308
181k
      for (int x = 1; x < NUM_MOST_PROBABLE_MODES; x++)
309
151k
      {
310
151k
        cu.intraDir[0] = multiRefMPM[x];
311
151k
        initPredIntraParams(cu, cu.Y(), sps);
312
151k
        distParam.cur.buf = piPred.buf = m_SortedPelUnitBufs->getTestBuf().Y().buf;
313
151k
        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
151k
        Distortion minSadHad = distParam.distFunc(distParam);
318
319
        // NB xFracModeBitsIntra will not affect the mode for chroma that may have already been pre-estimated.
320
151k
        uint64_t fracModeBits = xFracModeBitsIntraLuma( cu, mpmLst );
321
322
        //restore ctx
323
151k
        m_CABACEstimator->getCtx() = SubCtx(CtxSet(Ctx::IntraLumaMpmFlag(), intra_ctx_size), ctxStartIntraCtx);
324
325
151k
        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
151k
        int insertPos = -1;
329
151k
        updateCandList( ModeInfo( false, false, multiRefIdx, NOT_INTRA_SUBPARTITIONS, cu.intraDir[0] ), cost, RdModeList,  CandCostList, numModesForFullRD, &insertPos );
330
151k
        updateCandList( ModeInfo( false, false, multiRefIdx, NOT_INTRA_SUBPARTITIONS, cu.intraDir[0] ), (double)minSadHad, HadModeList, CandHadList,  numHadCand );
331
151k
        m_SortedPelUnitBufs->insert(insertPos, (int)RdModeList.size());
332
151k
      }
333
30.2k
    }
334
15.1k
    cu.multiRefIdx = 0;
335
15.1k
  }
336
337
25.1k
  if (testMip)
338
19.2k
  {
339
19.2k
    cu.mipFlag = true;
340
19.2k
    cu.multiRefIdx = 0;
341
342
19.2k
    double mipHadCost[MAX_NUM_MIP_MODE] = { MAX_DOUBLE };
343
344
19.2k
    initIntraPatternChType(cu, cu.Y());
345
19.2k
    initIntraMip( cu );
346
347
19.2k
    const int transpOff    = getNumModesMip( cu.Y() );
348
19.2k
    const int numModesFull = (transpOff << 1);
349
251k
    for( uint32_t uiModeFull = 0; uiModeFull < numModesFull; uiModeFull++ )
350
232k
    {
351
232k
      const bool     isTransposed = (uiModeFull >= transpOff ? true : false);
352
232k
      const uint32_t uiMode       = (isTransposed ? uiModeFull - transpOff : uiModeFull);
353
354
232k
      cu.mipTransposedFlag = isTransposed;
355
232k
      cu.intraDir[CH_L] = uiMode;
356
232k
      distParam.cur.buf = piPred.buf = m_SortedPelUnitBufs->getTestBuf().Y().buf;
357
232k
      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
232k
      Distortion minSadHad = distParam.distFunc(distParam);
362
363
232k
      uint64_t fracModeBits = xFracModeBitsIntraLuma( cu, mpmLst );
364
365
      //restore ctx
366
232k
      m_CABACEstimator->getCtx() = SubCtx(CtxSet(Ctx::IntraLumaMpmFlag(), intra_ctx_size), ctxStartIntraCtx);
367
368
232k
      double cost = double(minSadHad) + double(fracModeBits) * sqrtLambdaForFirstPass;
369
232k
      mipHadCost[uiModeFull] = cost;
370
232k
      DTRACE(g_trace_ctx, D_INTRA_COST, "IntraMIP: %u, %llu, %f (%d)\n", minSadHad, fracModeBits, cost, uiModeFull);
371
372
232k
      int insertPos = -1;
373
232k
      updateCandList( ModeInfo( true, isTransposed, 0, NOT_INTRA_SUBPARTITIONS, cu.intraDir[0] ), cost, RdModeList,  CandCostList, numModesForFullRD+1, &insertPos );
374
232k
      updateCandList( ModeInfo( true, isTransposed, 0, NOT_INTRA_SUBPARTITIONS, cu.intraDir[0] ), 0.8*(double)minSadHad, HadModeList, CandHadList,  numHadCand );
375
232k
      m_SortedPelUnitBufs->insert(insertPos, (int)RdModeList.size());
376
232k
    }
377
378
19.2k
    const double thresholdHadCost = 1.0 + 1.4 / sqrt((double)(cu.lwidth()*cu.lheight()));
379
19.2k
    xReduceHadCandList(RdModeList, CandCostList, *m_SortedPelUnitBufs, numModesForFullRD, thresholdHadCost, mipHadCost, cu, fastMip);
380
19.2k
  }
381
382
25.1k
  if( m_pcEncCfg->m_bFastUDIUseMPMEnabled )
383
25.1k
  {
384
25.1k
    const int numMPMs = NUM_MOST_PROBABLE_MODES;
385
25.1k
    unsigned  intraMpms[numMPMs];
386
387
25.1k
    cu.multiRefIdx = 0;
388
389
25.1k
    const int numCand = CU::getIntraMPMs( cu, intraMpms );
390
25.1k
    ModeInfo mostProbableMode(false, false, 0, NOT_INTRA_SUBPARTITIONS, 0);
391
392
50.9k
    for( int j = 0; j < numCand; j++ )
393
25.8k
    {
394
25.8k
      bool mostProbableModeIncluded = false;
395
25.8k
      mostProbableMode.modeId = intraMpms[j];
396
397
131k
      for( int i = 0; i < numModesForFullRD; i++ )
398
105k
      {
399
105k
        mostProbableModeIncluded |= ( mostProbableMode == RdModeList[i] );
400
105k
      }
401
25.8k
      if( !mostProbableModeIncluded )
402
178
      {
403
178
        numModesForFullRD++;
404
178
        RdModeList.push_back( mostProbableMode );
405
178
        CandCostList.push_back(0);
406
178
      }
407
25.8k
    }
408
25.1k
  }
409
25.1k
}
410
411
bool IntraSearch::estIntraPredLumaQT(CodingUnit &cu, Partitioner &partitioner, double bestCost)
412
25.1k
{
413
25.1k
  CodingStructure       &cs           = *cu.cs;
414
25.1k
  const int             width         = partitioner.currArea().lwidth();
415
25.1k
  const int             height        = partitioner.currArea().lheight();
416
417
  //===== loop over partitions =====
418
419
25.1k
  const TempCtx ctxStart           ( m_CtxCache, m_CABACEstimator->getCtx() );
420
421
  // variables for saving fast intra modes scan results across multiple LFNST passes
422
25.1k
  double costInterCU = xFindInterCUCost( cu );
423
424
25.1k
  bool validReturn = false;
425
426
  //===== determine set of modes to be tested (using prediction signal only) =====
427
25.1k
  int numModesAvailable = NUM_LUMA_MODE; // total number of Intra modes
428
25.1k
  static_vector<ModeInfo, FAST_UDI_MAX_RDMODE_NUM> RdModeList;
429
25.1k
  static_vector<ModeInfo, FAST_UDI_MAX_RDMODE_NUM> HadModeList;
430
25.1k
  static_vector<double, FAST_UDI_MAX_RDMODE_NUM> CandCostList;
431
25.1k
  static_vector<double, FAST_UDI_MAX_RDMODE_NUM> CandHadList;
432
433
25.1k
  int numModesForFullRD = g_aucIntraModeNumFast_UseMPM_2D[Log2(width) - MIN_CU_LOG2][Log2(height) - MIN_CU_LOG2];
434
25.1k
  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.1k
  const SPS& sps = *cu.cs->sps;
441
25.1k
  const bool mipAllowed = sps.MIP && cu.lwidth() <= sps.getMaxTbSize() && cu.lheight() <= sps.getMaxTbSize() && ((cu.lfnstIdx == 0) || allowLfnstWithMip(cu.lumaSize()));
442
25.1k
  const int SizeThr     = 8 >> std::max( 0, m_pcEncCfg->m_useFastMIP - 1 );
443
25.1k
  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.1k
  bool testISP = sps.ISP && CU::canUseISP(width, height, cu.cs->sps->getMaxTbSize());
445
25.1k
  if (testISP)
446
25.1k
  {
447
25.1k
    int numTotalPartsHor = (int)width >> floorLog2(CU::getISPSplitDim(width, height, TU_1D_VERT_SPLIT));
448
25.1k
    int numTotalPartsVer = (int)height >> floorLog2(CU::getISPSplitDim(width, height, TU_1D_HORZ_SPLIT));
449
25.1k
    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.1k
    numTotalPartsHor = sps.LFNST && CU::canUseLfnstWithISP(cu.Y(), HOR_INTRA_SUBPARTITIONS) ? numTotalPartsHor : 0;
453
25.1k
    numTotalPartsVer = sps.LFNST && CU::canUseLfnstWithISP(cu.Y(), VER_INTRA_SUBPARTITIONS) ? numTotalPartsVer : 0;
454
75.4k
    for (int j = 1; j < NUM_LFNST_NUM_PER_SET; j++)
455
50.2k
    {
456
50.2k
      m_ispTestedModes[j].init(numTotalPartsHor, numTotalPartsVer, 0);
457
50.2k
    }
458
25.1k
    testISP = m_ispTestedModes[0].numTotalParts[0];
459
25.1k
  }
460
0
  else
461
0
  {
462
0
    m_ispTestedModes[0].init(0, 0, 0);
463
0
  }
464
465
25.1k
  xEstimateLumaRdModeList(numModesForFullRD, RdModeList, HadModeList, CandCostList, CandHadList, cu, testMip);
466
467
25.1k
  CHECK( (size_t)numModesForFullRD != RdModeList.size(), "Inconsistent state!" );
468
469
  // after this point, don't use numModesForFullRD
470
25.1k
  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.1k
  ModeInfo bestPUMode;
513
514
25.1k
  CodingStructure *csTemp = m_pTempCS;
515
25.1k
  CodingStructure *csBest = m_pBestCS;
516
517
25.1k
  csTemp->slice   = csBest->slice   = cs.slice;
518
25.1k
  csTemp->picture = csBest->picture = cs.picture;
519
25.1k
  csTemp->compactResize( cu );
520
25.1k
  csBest->compactResize( cu );
521
25.1k
  csTemp->initStructData();
522
25.1k
  csBest->initStructData();
523
524
25.1k
  int   bestLfnstIdx  = 0;
525
25.1k
  const bool useBDPCM = cs.picture->useBDPCM;
526
25.1k
  int   NumBDPCMCand  = (useBDPCM && sps.BDPCM && CU::bdpcmAllowed(cu, ComponentID(partitioner.chType))) ? 2 : 0;
527
25.1k
  int   bestbdpcmMode = 0;
528
25.1k
  int   bestISP       = 0;
529
25.1k
  int   bestMrl       = 0;
530
25.1k
  bool  bestMip       = 0;
531
25.1k
  int   EndMode       = (int)RdModeList.size();
532
25.1k
  bool  useISPlfnst   = testISP && sps.LFNST;
533
25.1k
  bool  noLFNST_ts    = false;
534
25.1k
  double bestCostIsp[2] = { MAX_DOUBLE, MAX_DOUBLE };
535
25.1k
  bool disableMTS = false;
536
25.1k
  bool disableLFNST = false;
537
25.1k
  bool disableDCT2test = false;
538
25.1k
  if (m_pcEncCfg->m_FastIntraTools)
539
25.1k
  {
540
25.1k
    int speedIntra = 0;
541
25.1k
    xSpeedUpIntra(bestCost, EndMode, speedIntra, cu);
542
25.1k
    disableMTS = (speedIntra >> 2 ) & 0x1;
543
25.1k
    disableLFNST = (speedIntra >> 1) & 0x1;
544
25.1k
    disableDCT2test = speedIntra>>3;
545
25.1k
    if (disableLFNST)
546
22.4k
    {
547
22.4k
      noLFNST_ts = true;
548
22.4k
      useISPlfnst = false;
549
22.4k
    }
550
25.1k
    if (speedIntra & 0x1)
551
22.4k
    {
552
22.4k
      testISP = false;
553
22.4k
    }
554
25.1k
  }
555
556
135k
  for (int mode_cur = 0; mode_cur < EndMode + NumBDPCMCand; mode_cur++)
557
109k
  {
558
109k
    int mode = mode_cur;
559
109k
    if (mode_cur >= EndMode)
560
7.06k
    {
561
7.06k
      mode = mode_cur - EndMode ? -1 : -2;
562
7.06k
      testISP = false;
563
7.06k
    }
564
    // set CU/PU to luma prediction mode
565
109k
    ModeInfo testMode;
566
109k
    int noISP = 0;
567
109k
    int endISP = testISP ? 2 : 0;
568
109k
    bool noLFNST = false || noLFNST_ts;
569
109k
    if (mode && useISPlfnst)
570
8.88k
    {
571
8.88k
      noLFNST |= (bestCostIsp[0] > (bestCostIsp[1] * 1.4));
572
8.88k
      if (mode > 2)
573
2.40k
      {
574
2.40k
        endISP = 0;
575
2.40k
        testISP = false;
576
2.40k
      }
577
8.88k
    }
578
109k
    if (testISP)
579
5.65k
    {
580
5.65k
      xSpeedUpISP(1, testISP, mode, noISP, endISP, cu, RdModeList, bestPUMode, bestISP, bestLfnstIdx);
581
5.65k
    }
582
109k
    int startISP = 0;
583
109k
    if (disableDCT2test && mode && bestISP)
584
0
    {
585
0
      startISP = endISP ? 1 : 0;
586
0
    }
587
228k
    for (int ispM = startISP; ispM <= endISP; ispM++)
588
118k
    {
589
118k
      if (ispM && (ispM == noISP))
590
53
      {
591
53
        continue;
592
53
      }
593
594
118k
      if (mode < 0)
595
7.06k
      {
596
7.06k
        cu.bdpcmM[CH_L] = -mode;
597
7.06k
        testMode = ModeInfo(false, false, 0, NOT_INTRA_SUBPARTITIONS, cu.bdpcmM[CH_L] == 2 ? VER_IDX : HOR_IDX);
598
7.06k
      }
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
2.95k
      {
612
2.95k
        continue;
613
2.95k
      }
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.87k
      {
634
1.87k
        csTemp->cost = MAX_DOUBLE;
635
1.87k
        csTemp->costDbOffset = 0;
636
1.87k
      }
637
115k
      if (useISPlfnst)
638
16.9k
      {
639
16.9k
        int n = (cu.ispMode == 0) ? 0 : 1;
640
16.9k
        bestCostIsp[n] = csTemp->cost < bestCostIsp[n] ? csTemp->cost : bestCostIsp[n];
641
16.9k
      }
642
643
      // check r-d cost
644
115k
      if (csTemp->cost < csBest->cost)
645
31.7k
      {
646
31.7k
        validReturn   = true;
647
31.7k
        std::swap(csTemp, csBest);
648
31.7k
        bestPUMode    = testMode;
649
31.7k
        bestLfnstIdx  = csBest->cus[0]->lfnstIdx;
650
31.7k
        bestISP       = csBest->cus[0]->ispMode;
651
31.7k
        bestMip       = csBest->cus[0]->mipFlag;
652
31.7k
        bestMrl       = csBest->cus[0]->multiRefIdx;
653
31.7k
        bestbdpcmMode = cu.bdpcmM[CH_L];
654
31.7k
        m_ispTestedModes[bestLfnstIdx].bestSplitSoFar = ISPType(bestISP);
655
31.7k
        if (csBest->cost < bestCost)
656
31.7k
        {
657
31.7k
          bestCost = csBest->cost;
658
31.7k
        }
659
31.7k
        if ((csBest->getTU(partitioner.chType)->mtsIdx[COMP_Y] == MTS_SKIP) && ( floorLog2(csBest->getTU(partitioner.chType)->blocks[COMP_Y].area()) >= 6 ))
660
4.20k
        {
661
4.20k
          noLFNST_ts = 1;
662
4.20k
        }
663
31.7k
      }
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
109k
  } // Mode loop
681
682
25.1k
  if (m_pcEncCfg->m_FastIntraTools && (sps.ISP|| sps.LFNST || sps.MTS))
683
25.1k
  {
684
25.1k
    int bestMode = csBest->getTU(partitioner.chType)->mtsIdx[COMP_Y] ? 4 : 0;
685
25.1k
    bestMode |= bestLfnstIdx ? 2 : 0;
686
25.1k
    bestMode |= bestISP ? 1 : 0;
687
25.1k
    m_ispTestedModes[0].bestIntraMode = bestMode;
688
25.1k
  }
689
25.1k
  cu.ispMode = bestISP;
690
25.1k
  if( validReturn )
691
25.1k
  {
692
25.1k
    cs.useSubStructure( *csBest, partitioner.chType, TREE_D, cu.singleChan( CH_L ), true );
693
694
    //=== update PU data ====
695
25.1k
    cu.lfnstIdx           = bestLfnstIdx;
696
25.1k
    cu.mipTransposedFlag  = bestPUMode.mipTrFlg;
697
25.1k
    cu.intraDir[CH_L]     = bestPUMode.modeId;
698
25.1k
    cu.bdpcmM[CH_L]       = bestbdpcmMode;
699
25.1k
    cu.mipFlag            = bestMip;
700
25.1k
    cu.multiRefIdx        = bestMrl;
701
25.1k
  }
702
0
  else
703
0
  {
704
0
    THROW("fix this");
705
0
  }
706
707
25.1k
  csBest->releaseIntermediateData();
708
709
25.1k
  return validReturn;
710
25.1k
}
711
712
void IntraSearch::estIntraPredChromaQT( CodingUnit& cu, Partitioner& partitioner, const double maxCostAllowed )
713
56.6k
{
714
56.6k
  PROFILER_SCOPE_AND_STAGE_EXT( 0, _TPROF, P_INTRA_CHROMA, cu.cs, CH_C );
715
56.6k
  const TempCtx ctxStart( m_CtxCache, m_CABACEstimator->getCtx() );
716
56.6k
  CodingStructure &cs   = *cu.cs;
717
56.6k
  bool lumaUsesISP      = !CU::isSepTree(cu) && cu.ispMode;
718
56.6k
  PartSplit ispType     = lumaUsesISP ? CU::getISPType(cu, COMP_Y) : TU_NO_ISP;
719
56.6k
  double bestCostSoFar  = maxCostAllowed;
720
56.6k
  const uint32_t numberValidComponents = getNumberValidComponents( cu.chromaFormat );
721
56.6k
  const bool useBDPCM   = cs.picture->useBDPCM;
722
723
56.6k
  uint32_t   uiBestMode = 0;
724
56.6k
  Distortion uiBestDist = 0;
725
56.6k
  double     dBestCost  = MAX_DOUBLE;
726
727
  //----- init mode list ----
728
56.6k
  {
729
56.6k
    uint32_t  uiMinMode = 0;
730
56.6k
    uint32_t  uiMaxMode = NUM_CHROMA_MODE;
731
732
56.6k
    const int reducedModeNumber = uiMaxMode >> (m_pcEncCfg->m_reduceIntraChromaModesFullRD ? 1 : 2);
733
    //----- check chroma modes -----
734
56.6k
    uint32_t chromaCandModes[ NUM_CHROMA_MODE ];
735
56.6k
    CU::getIntraChromaCandModes( cu, chromaCandModes );
736
737
    // create a temporary CS
738
56.6k
    CodingStructure &saveCS = *m_pSaveCS[0];
739
56.6k
    saveCS.pcv      = cs.pcv;
740
56.6k
    saveCS.picture  = cs.picture;
741
56.6k
    saveCS.area.repositionTo( cs.area );
742
56.6k
    saveCS.clearTUs();
743
744
56.6k
    if( !CU::isSepTree(cu) && cu.ispMode )
745
0
    {
746
0
      saveCS.clearCUs();
747
0
    }
748
749
56.6k
    if( CU::isSepTree(cu) )
750
56.6k
    {
751
56.6k
      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
56.6k
      else
763
56.6k
        cs.addTU( CS::getArea( cs, partitioner.currArea(), partitioner.chType, partitioner.treeType ), partitioner.chType, &cu );
764
56.6k
    }
765
766
    // create a store for the TUs
767
56.6k
    std::vector<TransformUnit*> orgTUs;
768
56.6k
    for( const auto &ptu : cs.tus )
769
56.6k
    {
770
      // for split TUs in HEVC, add the TUs without Chroma parts for correct setting of Cbfs
771
56.6k
      if (lumaUsesISP || cu.contains(*ptu, CH_C))
772
56.6k
      {
773
56.6k
        saveCS.addTU( *ptu, partitioner.chType, nullptr );
774
56.6k
        orgTUs.push_back( ptu );
775
56.6k
      }
776
56.6k
    }
777
778
    // SATD pre-selecting.
779
56.6k
    int     satdModeList  [NUM_CHROMA_MODE] = { 0 };
780
56.6k
    int64_t satdSortedCost[NUM_CHROMA_MODE] = { 0 };
781
56.6k
    bool    modeDisable[NUM_INTRA_MODE + 1] = { false }; // use intra mode idx to check whether enable
782
783
56.6k
    CodingStructure& cs = *(cu.cs);
784
56.6k
    CompArea areaCb = cu.Cb();
785
56.6k
    CompArea areaCr = cu.Cr();
786
56.6k
    CPelBuf orgCb  = cs.getOrgBuf (COMP_Cb);
787
56.6k
    PelBuf predCb  = cs.getPredBuf(COMP_Cb);
788
56.6k
    CPelBuf orgCr  = cs.getOrgBuf (COMP_Cr);
789
56.6k
    PelBuf predCr  = cs.getPredBuf(COMP_Cr);
790
791
56.6k
    DistParam distParamSadCb  = m_pcRdCost->setDistParam( orgCb, predCb, cu.cs->sps->bitDepths[ CH_C ], DF_SAD);
792
56.6k
    DistParam distParamSatdCb = m_pcRdCost->setDistParam( orgCb, predCb, cu.cs->sps->bitDepths[ CH_C ], DF_HAD);
793
56.6k
    DistParam distParamSadCr  = m_pcRdCost->setDistParam( orgCr, predCr, cu.cs->sps->bitDepths[ CH_C ], DF_SAD);
794
56.6k
    DistParam distParamSatdCr = m_pcRdCost->setDistParam( orgCr, predCr, cu.cs->sps->bitDepths[ CH_C ], DF_HAD);
795
796
56.6k
    cu.intraDir[1] = MDLM_L_IDX; // temporary assigned, just to indicate this is a MDLM mode. for luma down-sampling operation.
797
798
56.6k
    initIntraPatternChType(cu, cu.Cb());
799
56.6k
    initIntraPatternChType(cu, cu.Cr());
800
56.6k
    loadLMLumaRecPels(cu, cu.Cb());
801
802
509k
    for (int idx = uiMinMode; idx < uiMaxMode; idx++)
803
452k
    {
804
452k
      int mode = chromaCandModes[idx];
805
452k
      satdModeList[idx] = mode;
806
452k
      if (CU::isLMCMode(mode) && ( !CU::isLMCModeEnabled(cu, mode) || cu.slice->lmChromaCheckDisable ) )
807
49.1k
      {
808
49.1k
        continue;
809
49.1k
      }
810
403k
      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
98.6k
      {
812
98.6k
        continue;
813
98.6k
      }
814
815
305k
      cu.intraDir[1]    = mode; // temporary assigned, for SATD checking.
816
817
305k
      const bool isLMCMode = CU::isLMCMode(mode);
818
305k
      if( isLMCMode )
819
80.4k
      {
820
80.4k
        predIntraChromaLM(COMP_Cb, predCb, cu, areaCb, mode);
821
80.4k
      }
822
224k
      else
823
224k
      {
824
224k
        initPredIntraParams(cu, cu.Cb(), *cs.sps);
825
224k
        predIntraAng(COMP_Cb, predCb, cu);
826
224k
      }
827
305k
      int64_t sadCb = distParamSadCb.distFunc(distParamSadCb) * 2;
828
305k
      int64_t satdCb = distParamSatdCb.distFunc(distParamSatdCb);
829
305k
      int64_t sad = std::min(sadCb, satdCb);
830
831
305k
      if( isLMCMode )
832
80.4k
      {
833
80.4k
        predIntraChromaLM(COMP_Cr, predCr, cu, areaCr, mode);
834
80.4k
      }
835
224k
      else
836
224k
      {
837
224k
        initPredIntraParams(cu, cu.Cr(), *cs.sps);
838
224k
        predIntraAng(COMP_Cr, predCr, cu);
839
224k
      }
840
305k
      int64_t sadCr = distParamSadCr.distFunc(distParamSadCr) * 2;
841
305k
      int64_t satdCr = distParamSatdCr.distFunc(distParamSatdCr);
842
305k
      sad += std::min(sadCr, satdCr);
843
305k
      satdSortedCost[idx] = sad;
844
305k
    }
845
846
    // sort the mode based on the cost from small to large.
847
509k
    for (int i = uiMinMode; i <= uiMaxMode - 1; i++)
848
452k
    {
849
2.03M
      for (int j = i + 1; j <= uiMaxMode - 1; j++)
850
1.58M
      {
851
1.58M
        if (satdSortedCost[j] < satdSortedCost[i])
852
97.7k
        {
853
97.7k
          std::swap( satdModeList[i],   satdModeList[j]);
854
97.7k
          std::swap( satdSortedCost[i], satdSortedCost[j]);
855
97.7k
        }
856
1.58M
      }
857
452k
    }
858
859
283k
    for (int i = 0; i < reducedModeNumber; i++)
860
226k
    {
861
226k
      modeDisable[satdModeList[uiMaxMode - 1 - i]] = true; // disable the last reducedModeNumber modes
862
226k
    }
863
864
56.6k
    int bestLfnstIdx = 0;
865
    // save the dist
866
56.6k
    Distortion baseDist = cs.dist;
867
56.6k
    int32_t bestbdpcmMode = 0;
868
56.6k
    uint32_t numbdpcmModes = ( useBDPCM && CU::bdpcmAllowed(cu, COMP_Cb)
869
37.5k
        && ((partitioner.chType == CH_C) || (cu.ispMode == 0 && cu.lfnstIdx == 0 && cu.firstTU->mtsIdx[COMP_Y] == MTS_SKIP))) ? 2 : 0;
870
584k
    for (int mode_cur = uiMinMode; mode_cur < (int)(uiMaxMode + numbdpcmModes); mode_cur++)
871
528k
    {
872
528k
      int mode = mode_cur;
873
528k
      if (mode_cur >= uiMaxMode)
874
75.1k
      {
875
75.1k
        mode = mode_cur > uiMaxMode ? -1 : -2; //set bdpcm mode
876
75.1k
        if ((mode == -1) && (saveCS.tus[0]->mtsIdx[COMP_Cb] != MTS_SKIP) && (saveCS.tus[0]->mtsIdx[COMP_Cr] != MTS_SKIP))
877
37.5k
        {
878
37.5k
          continue;
879
37.5k
        }
880
75.1k
      }
881
490k
      int chromaIntraMode;
882
490k
      if (mode < 0)
883
37.5k
      {
884
37.5k
        cu.bdpcmM[CH_C] = -mode;
885
37.5k
        chromaIntraMode = cu.bdpcmM[CH_C] == 2 ? chromaCandModes[1] : chromaCandModes[2];
886
37.5k
      }
887
452k
      else
888
452k
      {
889
452k
        cu.bdpcmM[CH_C] = 0;
890
452k
        chromaIntraMode = chromaCandModes[mode];
891
452k
        if (CU::isLMCMode(chromaIntraMode) && ( !CU::isLMCModeEnabled(cu, chromaIntraMode) || cu.slice->lmChromaCheckDisable ) )
892
49.1k
        {
893
49.1k
          continue;
894
49.1k
        }
895
403k
        if (modeDisable[chromaIntraMode] && CU::isLMCModeEnabled(cu, chromaIntraMode)) // when CCLM is disable, then MDLM is disable. not use satd checking
896
160k
        {
897
160k
          continue;
898
160k
        }
899
403k
      }
900
280k
      cs.dist = baseDist;
901
      //----- restore context models -----
902
280k
      m_CABACEstimator->getCtx() = ctxStart;
903
904
      //----- chroma coding -----
905
280k
      cu.intraDir[1] = chromaIntraMode;
906
280k
      m_ispTestedModes[0].IspType = ispType;
907
280k
      m_ispTestedModes[0].subTuCounter = -1;
908
280k
      xIntraChromaCodingQT( cs, partitioner );
909
280k
      if (lumaUsesISP && cs.dist == MAX_UINT)
910
0
      {
911
0
        continue;
912
0
      }
913
914
280k
      if (cs.sps->transformSkip)
915
280k
      {
916
280k
        m_CABACEstimator->getCtx() = ctxStart;
917
280k
      }
918
280k
      m_ispTestedModes[0].IspType = ispType;
919
280k
      m_ispTestedModes[0].subTuCounter = -1;
920
280k
      uint64_t fracBits   = xGetIntraFracBitsQT( cs, partitioner, false );
921
280k
      Distortion uiDist = cs.dist;
922
280k
      double    dCost   = m_pcRdCost->calcRdCost( fracBits, uiDist - baseDist );
923
924
      //----- compare -----
925
280k
      if( dCost < dBestCost )
926
101k
      {
927
101k
        if (lumaUsesISP && (dCost < bestCostSoFar))
928
0
        {
929
0
          bestCostSoFar = dCost;
930
0
        }
931
305k
        for( uint32_t i = getFirstComponentOfChannel( CH_C ); i < numberValidComponents; i++ )
932
203k
        {
933
203k
          const CompArea& area = cu.blocks[i];
934
203k
          saveCS.getRecoBuf     ( area ).copyFrom( cs.getRecoBuf   ( area ) );
935
203k
          cs.picture->getRecoBuf( area ).copyFrom( cs.getRecoBuf   ( area ) );
936
407k
          for( uint32_t j = 0; j < saveCS.tus.size(); j++ )
937
203k
          {
938
203k
            saveCS.tus[j]->copyComponentFrom( *orgTUs[j], area.compID );
939
203k
          }
940
203k
        }
941
101k
        dBestCost    = dCost;
942
101k
        uiBestDist   = uiDist;
943
101k
        uiBestMode   = chromaIntraMode;
944
101k
        bestLfnstIdx = cu.lfnstIdx;
945
101k
        bestbdpcmMode = cu.bdpcmM[CH_C];
946
947
101k
      }
948
280k
    }
949
56.6k
    cu.lfnstIdx = bestLfnstIdx;
950
56.6k
    cu.bdpcmM[CH_C]= bestbdpcmMode;
951
952
169k
    for( uint32_t i = getFirstComponentOfChannel( CH_C ); i < numberValidComponents; i++ )
953
113k
    {
954
113k
      const CompArea& area = cu.blocks[i];
955
956
113k
      cs.getRecoBuf         ( area ).copyFrom( saveCS.getRecoBuf( area ) );
957
113k
      cs.picture->getRecoBuf( area ).copyFrom( cs.getRecoBuf    ( area ) );
958
959
226k
      for( uint32_t j = 0; j < saveCS.tus.size(); j++ )
960
113k
      {
961
113k
        orgTUs[ j ]->copyComponentFrom( *saveCS.tus[ j ], area.compID );
962
113k
      }
963
113k
    }
964
56.6k
  }
965
56.6k
  cu.intraDir[1] = uiBestMode;
966
56.6k
  cs.dist        = uiBestDist;
967
968
  //----- restore context models -----
969
56.6k
  m_CABACEstimator->getCtx() = ctxStart;
970
56.6k
  if (lumaUsesISP && bestCostSoFar >= maxCostAllowed)
971
0
  {
972
0
    cu.ispMode = 0;
973
0
  }
974
56.6k
}
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
467k
{
1001
467k
  CodingUnit &cu = *cs.getCU( partitioner.chType, partitioner.treeType );
1002
1003
467k
  if (luma)
1004
186k
  {
1005
186k
    bool isFirst = cu.ispMode ? m_ispTestedModes[0].subTuCounter == 0 : partitioner.currArea().lumaPos() == cs.area.lumaPos();
1006
1007
    // CU header
1008
186k
    if( isFirst )
1009
182k
    {
1010
182k
      if ((!cs.slice->isIntra() || cs.slice->sps->IBC || cs.slice->sps->PLT) && cu.Y().valid())
1011
182k
      {
1012
182k
        m_CABACEstimator->pred_mode   ( cu );
1013
182k
      }
1014
182k
      m_CABACEstimator->bdpcm_mode  ( cu, ComponentID(partitioner.chType) );
1015
182k
    }
1016
1017
    // luma prediction mode
1018
186k
    if (isFirst)
1019
182k
    {
1020
182k
      if ( !cu.Y().valid())
1021
0
      {
1022
0
        m_CABACEstimator->pred_mode( cu );
1023
0
      }
1024
182k
      m_CABACEstimator->intra_luma_pred_mode( cu );
1025
182k
    }
1026
186k
  }
1027
280k
  else //  if (chroma)
1028
280k
  {
1029
280k
    bool isFirst = partitioner.currArea().Cb().valid() && partitioner.currArea().chromaPos() == cs.area.chromaPos();
1030
1031
280k
    if( isFirst )
1032
280k
    {
1033
280k
      m_CABACEstimator->bdpcm_mode(cu, ComponentID(CH_C));
1034
280k
      m_CABACEstimator->intra_chroma_pred_mode(  cu );
1035
280k
    }
1036
280k
  }
1037
467k
}
1038
1039
void IntraSearch::xEncSubdivCbfQT( CodingStructure &cs, Partitioner &partitioner, const bool luma )
1040
467k
{
1041
467k
  const UnitArea& currArea = partitioner.currArea();
1042
467k
  int subTuCounter = m_ispTestedModes[0].subTuCounter;
1043
467k
  TransformUnit  &currTU   = *cs.getTU(currArea.blocks[partitioner.chType], partitioner.chType, subTuCounter);
1044
467k
  CodingUnit     &currCU   = *currTU.cu;
1045
467k
  const uint32_t currDepth = partitioner.currTrDepth;
1046
467k
  const bool  subdiv = currTU.depth > currDepth;
1047
467k
  ComponentID compID = partitioner.chType == CH_L ? COMP_Y : COMP_Cb;
1048
1049
467k
  if (!luma)
1050
280k
  {
1051
280k
    const bool chromaCbfISP = currArea.blocks[COMP_Cb].valid() && currCU.ispMode && !subdiv;
1052
280k
    if (!currCU.ispMode || chromaCbfISP)
1053
280k
    {
1054
280k
      const uint32_t numberValidComponents = getNumberValidComponents(currArea.chromaFormat);
1055
280k
      const uint32_t cbfDepth = (chromaCbfISP ? currDepth - 1 : currDepth);
1056
1057
841k
      for (uint32_t ch = COMP_Cb; ch < numberValidComponents; ch++)
1058
560k
      {
1059
560k
        const ComponentID compID = ComponentID(ch);
1060
560k
        if (currDepth == 0 || TU::getCbfAtDepth(currTU, compID, currDepth - 1) || chromaCbfISP)
1061
560k
        {
1062
560k
          const bool prevCbf = (compID == COMP_Cr ? TU::getCbfAtDepth(currTU, COMP_Cb, currDepth) : false);
1063
560k
          m_CABACEstimator->cbf_comp(currCU, TU::getCbfAtDepth(currTU, compID, currDepth), currArea.blocks[compID], cbfDepth, prevCbf);
1064
560k
        }
1065
560k
      }
1066
280k
    }
1067
280k
  }
1068
1069
467k
  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
467k
  else
1091
467k
  {
1092
    //===== Cbfs =====
1093
467k
    if (luma)
1094
186k
    {
1095
186k
      bool previousCbf = false;
1096
186k
      bool lastCbfIsInferred = false;
1097
186k
      if (m_ispTestedModes[0].IspType != TU_NO_ISP)
1098
14.5k
      {
1099
14.5k
        bool     rootCbfSoFar = false;
1100
14.5k
        uint32_t nTus = currCU.ispMode == HOR_INTRA_SUBPARTITIONS ? currCU.lheight() >> floorLog2(currTU.lheight())
1101
14.5k
          : currCU.lwidth() >> floorLog2(currTU.lwidth());
1102
14.5k
        if (subTuCounter == nTus - 1)
1103
1.35k
        {
1104
1.35k
          TransformUnit* tuPointer = currCU.firstTU;
1105
5.41k
          for (int tuIdx = 0; tuIdx < nTus - 1; tuIdx++)
1106
4.05k
          {
1107
4.05k
            rootCbfSoFar |= TU::getCbfAtDepth(*tuPointer, COMP_Y, currDepth);
1108
4.05k
            tuPointer = tuPointer->next;
1109
4.05k
          }
1110
1.35k
          if (!rootCbfSoFar)
1111
0
          {
1112
0
            lastCbfIsInferred = true;
1113
0
          }
1114
1.35k
        }
1115
14.5k
        if (!lastCbfIsInferred)
1116
14.5k
        {
1117
14.5k
          previousCbf = TU::getPrevTuCbfAtDepth(currTU, COMP_Y, partitioner.currTrDepth);
1118
14.5k
        }
1119
14.5k
      }
1120
186k
      if (!lastCbfIsInferred)
1121
186k
      {
1122
186k
        m_CABACEstimator->cbf_comp(currCU, TU::getCbfAtDepth(currTU, COMP_Y, currDepth), currTU.Y(), currTU.depth, previousCbf, currCU.ispMode);
1123
186k
      }
1124
186k
    }
1125
467k
  }
1126
467k
}
1127
void IntraSearch::xEncCoeffQT(CodingStructure& cs, Partitioner& partitioner, const ComponentID compID, CUCtx* cuCtx, const int subTuIdx, const PartSplit ispType)
1128
747k
{
1129
747k
  const UnitArea& currArea  = partitioner.currArea();
1130
1131
747k
  int subTuCounter          = m_ispTestedModes[0].subTuCounter;
1132
747k
  TransformUnit& currTU     = *cs.getTU(currArea.blocks[partitioner.chType], partitioner.chType, subTuCounter);
1133
747k
  uint32_t   currDepth      = partitioner.currTrDepth;
1134
747k
  const bool subdiv         = currTU.depth > currDepth;
1135
1136
747k
  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
747k
  else
1158
1159
747k
  if( currArea.blocks[compID].valid() )
1160
747k
  {
1161
747k
    if( compID == COMP_Cr )
1162
280k
    {
1163
280k
      const int cbfMask = ( TU::getCbf( currTU, COMP_Cb ) ? 2 : 0 ) + ( TU::getCbf( currTU, COMP_Cr ) ? 1 : 0 );
1164
280k
      m_CABACEstimator->joint_cb_cr( currTU, cbfMask );
1165
280k
    }
1166
747k
    if( TU::getCbf( currTU, compID ) )
1167
226k
    {
1168
226k
      if( isLuma(compID) )
1169
25.0k
      {
1170
25.0k
        m_CABACEstimator->residual_coding( currTU, compID, cuCtx );
1171
25.0k
        m_CABACEstimator->mts_idx( *currTU.cu, cuCtx );
1172
25.0k
      }
1173
201k
      else
1174
201k
        m_CABACEstimator->residual_coding( currTU, compID );
1175
226k
    }
1176
747k
  }
1177
747k
}
1178
1179
uint64_t IntraSearch::xGetIntraFracBitsQT( CodingStructure &cs, Partitioner &partitioner, const bool luma, CUCtx *cuCtx )
1180
467k
{
1181
467k
  m_CABACEstimator->resetBits();
1182
1183
467k
  xEncIntraHeader( cs, partitioner, luma );
1184
467k
  xEncSubdivCbfQT( cs, partitioner, luma );
1185
1186
467k
  if( luma )
1187
186k
  {
1188
186k
    xEncCoeffQT( cs, partitioner, COMP_Y, cuCtx );
1189
1190
186k
    CodingUnit &cu = *cs.cus[0];
1191
186k
    if (cuCtx /*&& CU::isSepTree(cu)*/
1192
117k
      && (!cu.ispMode || (cu.lfnstIdx && m_ispTestedModes[0].subTuCounter == 0)
1193
9.12k
        || (!cu.lfnstIdx
1194
7.77k
          && m_ispTestedModes[0].subTuCounter == m_ispTestedModes[cu.lfnstIdx].numTotalParts[cu.ispMode - 1] - 1)))
1195
109k
    {
1196
109k
      m_CABACEstimator->residual_lfnst_mode( cu, *cuCtx );
1197
109k
    }
1198
186k
  }
1199
280k
  else
1200
280k
  {
1201
280k
    xEncCoeffQT( cs, partitioner, COMP_Cb );
1202
280k
    xEncCoeffQT( cs, partitioner, COMP_Cr );
1203
280k
  }
1204
1205
467k
  uint64_t fracBits = m_CABACEstimator->getEstFracBits();
1206
467k
  return fracBits;
1207
467k
}
1208
1209
uint64_t IntraSearch::xGetIntraFracBitsQTChroma(const TransformUnit& currTU, const ComponentID compID, CUCtx *cuCtx)
1210
1.75M
{
1211
1.75M
  m_CABACEstimator->resetBits();
1212
1213
1.75M
  if ( currTU.jointCbCr )
1214
260k
  {
1215
260k
    const int cbfMask = ( TU::getCbf( currTU, COMP_Cb ) ? 2 : 0 ) + ( TU::getCbf( currTU, COMP_Cr ) ? 1 : 0 );
1216
260k
    m_CABACEstimator->cbf_comp( *currTU.cu, cbfMask>>1, currTU.blocks[ COMP_Cb ], currTU.depth, false );
1217
260k
    m_CABACEstimator->cbf_comp( *currTU.cu, cbfMask &1, currTU.blocks[ COMP_Cr ], currTU.depth, cbfMask>>1 );
1218
260k
    if( cbfMask )
1219
260k
      m_CABACEstimator->joint_cb_cr( currTU, cbfMask );
1220
260k
    if (cbfMask >> 1)
1221
258k
      m_CABACEstimator->residual_coding( currTU, COMP_Cb, cuCtx );
1222
260k
    if (cbfMask & 1)
1223
260k
      m_CABACEstimator->residual_coding( currTU, COMP_Cr, cuCtx );
1224
260k
  }
1225
1.49M
  else
1226
1.49M
  {
1227
1.49M
    if ( compID == COMP_Cb )
1228
745k
      m_CABACEstimator->cbf_comp( *currTU.cu, TU::getCbf( currTU, compID ), currTU.blocks[ compID ], currTU.depth, false );
1229
745k
    else
1230
745k
    {
1231
745k
      const bool cbCbf    = TU::getCbf( currTU, COMP_Cb );
1232
745k
      const bool crCbf    = TU::getCbf( currTU, compID );
1233
745k
      const int  cbfMask  = ( cbCbf ? 2 : 0 ) + ( crCbf ? 1 : 0 );
1234
745k
      m_CABACEstimator->cbf_comp( *currTU.cu, crCbf, currTU.blocks[ compID ], currTU.depth, cbCbf );
1235
745k
      m_CABACEstimator->joint_cb_cr( currTU, cbfMask );
1236
745k
    }
1237
1.49M
  }
1238
1239
1.75M
  if( !currTU.jointCbCr && TU::getCbf( currTU, compID ) )
1240
523k
  {
1241
523k
    m_CABACEstimator->residual_coding( currTU, compID, cuCtx );
1242
523k
  }
1243
1244
1.75M
  uint64_t fracBits = m_CABACEstimator->getEstFracBits();
1245
1.75M
  return fracBits;
1246
1.75M
}
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.94M
{
1250
1.94M
  if (!tu.blocks[compID].valid())
1251
0
  {
1252
0
    return;
1253
0
  }
1254
1255
1.94M
  CodingStructure &cs             = *tu.cs;
1256
1.94M
  const CompArea      &area       = tu.blocks[compID];
1257
1.94M
  const SPS           &sps        = *cs.sps;
1258
1259
1.94M
  const ChannelType    chType     = toChannelType(compID);
1260
1.94M
  const int            bitDepth   = sps.bitDepths[chType];
1261
1262
1.94M
  CPelBuf        piOrg            = cs.getOrgBuf    (area);
1263
1.94M
  PelBuf         piPred           = cs.getPredBuf   (area);
1264
1.94M
  PelBuf         piResi           = cs.getResiBuf   (area);
1265
1.94M
  PelBuf         piReco           = cs.getRecoBuf   (area);
1266
1267
1.94M
  const CodingUnit& cu            = *tu.cu;
1268
1269
  //===== init availability pattern =====
1270
1.94M
  CHECK( tu.jointCbCr && compID == COMP_Cr, "wrong combination of compID and jointCbCr" );
1271
1.94M
  bool jointCbCr = tu.jointCbCr && compID == COMP_Cb;
1272
1273
1.94M
  if ( isLuma(compID) )
1274
191k
  {
1275
191k
    bool predRegDiffFromTB = CU::isPredRegDiffFromTB(*tu.cu );
1276
191k
    bool firstTBInPredReg  = false;
1277
191k
    CompArea areaPredReg(COMP_Y, tu.chromaFormat, area);
1278
191k
    if (tu.cu->ispMode )
1279
19.6k
    {
1280
19.6k
      firstTBInPredReg = CU::isFirstTBInPredReg(*tu.cu, area);
1281
19.6k
      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
19.6k
      else
1290
19.6k
        initIntraPatternChTypeISP(*tu.cu, area, piReco);
1291
19.6k
    }
1292
172k
    else if( !predBuf )
1293
29.3k
    {
1294
29.3k
      initIntraPatternChType(*tu.cu, area);
1295
29.3k
    }
1296
1297
    //===== get prediction signal =====
1298
191k
    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
191k
    else
1307
191k
    {
1308
191k
      if( predBuf )
1309
142k
      {
1310
142k
        piPred.copyFrom( predBuf->Y() );
1311
142k
      }
1312
49.0k
      else if( CU::isMIP( cu, CH_L ) )
1313
22.1k
      {
1314
22.1k
        initIntraMip( cu );
1315
22.1k
        predIntraMip( piPred, cu );
1316
22.1k
      }
1317
26.9k
      else
1318
26.9k
      {
1319
26.9k
        predIntraAng(compID, piPred, cu);
1320
26.9k
      }
1321
191k
    }
1322
191k
  }
1323
1.94M
  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.94M
  if (isLuma(compID))
1326
191k
  {
1327
    //===== get residual signal =====
1328
191k
    piResi.subtract( piOrg, piPred );
1329
191k
  }
1330
1331
  //===== transform and quantization =====
1332
  //--- init rate estimation arrays for RDOQ ---
1333
  //--- transform and quantization           ---
1334
1.94M
  TCoeff uiAbsSum = 0;
1335
1.94M
  const QpParam cQP(tu, compID);
1336
1337
1.94M
  m_pcTrQuant->selectLambda(compID);
1338
1339
1.94M
  if ( jointCbCr )
1340
263k
  {
1341
    // Lambda is loosened for the joint mode with respect to single modes as the same residual is used for both chroma blocks
1342
263k
    const int    absIct = abs( TU::getICTMode(tu) );
1343
263k
    const double lfact  = ( absIct == 1 || absIct == 3 ? 0.8 : 0.5 );
1344
263k
    m_pcTrQuant->scaleLambda( lfact );
1345
263k
  }
1346
1.94M
  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.94M
  if( isLuma(compID) )
1352
191k
  {
1353
191k
    m_pcTrQuant->transformNxN(tu, compID, cQP, uiAbsSum, m_CABACEstimator->getCtx(), loadTr);
1354
1355
191k
    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
191k
    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
191k
    if (uiAbsSum > 0)
1364
30.1k
    {
1365
30.1k
      m_pcTrQuant->invTransformNxN(tu, compID, piResi, cQP);
1366
30.1k
    }
1367
161k
    else
1368
161k
    {
1369
161k
      piResi.fill(0);
1370
161k
    }
1371
191k
  }
1372
1.75M
  else // chroma
1373
1.75M
  {
1374
1.75M
    PelBuf          crPred = cs.getPredBuf ( COMP_Cr );
1375
1.75M
    PelBuf          crResi = cs.getResiBuf ( COMP_Cr );
1376
1.75M
    PelBuf          crReco = cs.getRecoBuf ( COMP_Cr );
1377
1378
1.75M
    int         codedCbfMask  = 0;
1379
1.75M
    ComponentID codeCompId    = (tu.jointCbCr ? (tu.jointCbCr >> 1 ? COMP_Cb : COMP_Cr) : compID);
1380
1.75M
    const QpParam qpCbCr(tu, codeCompId);
1381
1382
1.75M
    if( tu.jointCbCr )
1383
263k
    {
1384
263k
      ComponentID otherCompId = ( codeCompId==COMP_Cr ? COMP_Cb : COMP_Cr );
1385
263k
      tu.getCoeffs( otherCompId ).fill(0); // do we need that?
1386
263k
      TU::setCbfAtDepth (tu, otherCompId, tu.depth, false );
1387
263k
    }
1388
1.75M
    PelBuf& codeResi = ( codeCompId == COMP_Cr ? crResi : piResi );
1389
1.75M
    uiAbsSum = 0;
1390
1.75M
    m_pcTrQuant->transformNxN(tu, codeCompId, qpCbCr, uiAbsSum, m_CABACEstimator->getCtx(), loadTr);
1391
1.75M
    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.75M
    if( uiAbsSum > 0 )
1393
783k
    {
1394
783k
      m_pcTrQuant->invTransformNxN(tu, codeCompId, codeResi, qpCbCr);
1395
783k
      codedCbfMask += ( codeCompId == COMP_Cb ? 2 : 1 );
1396
783k
    }
1397
970k
    else
1398
970k
    {
1399
970k
      codeResi.fill(0);
1400
970k
    }
1401
1402
1.75M
    if( tu.jointCbCr )
1403
263k
    {
1404
263k
      if( tu.jointCbCr == 3 && codedCbfMask == 2 )
1405
258k
      {
1406
258k
        codedCbfMask = 3;
1407
258k
        TU::setCbfAtDepth (tu, COMP_Cr, tu.depth, true );
1408
258k
      }
1409
263k
      if( tu.jointCbCr != codedCbfMask )
1410
3.27k
      {
1411
3.27k
        ruiDist = MAX_DISTORTION;
1412
3.27k
        return;
1413
3.27k
      }
1414
260k
      m_pcTrQuant->invTransformICT( tu, piResi, crResi );
1415
260k
      uiAbsSum = codedCbfMask;
1416
260k
    }
1417
1418
    //===== reconstruction =====
1419
1.75M
    if( jointCbCr )
1420
260k
    {
1421
260k
      crReco.reconstruct(crPred, crResi, cs.slice->clpRngs[ COMP_Cr ]);
1422
260k
    }
1423
1.75M
  }
1424
1.94M
  piReco.reconstruct(piPred, piResi, cs.slice->clpRngs[ compID ]);
1425
  
1426
1427
1428
  //===== update distortion =====
1429
1.94M
  ruiDist += m_pcRdCost->getDistPart( piOrg, piReco, bitDepth, compID, DF_SSE );
1430
1.94M
  if( jointCbCr )
1431
260k
  {
1432
260k
    CPelBuf         crOrg  = cs.getOrgBuf  ( COMP_Cr );
1433
260k
    PelBuf          crReco = cs.getRecoBuf ( COMP_Cr );
1434
260k
    ruiDist += m_pcRdCost->getDistPart( crOrg, crReco, bitDepth, COMP_Cr, DF_SSE );
1435
260k
  }
1436
1.94M
}
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
1.91k
  {
1459
1.91k
    endLfnstIdx = 0;
1460
1.91k
  }
1461
115k
  int bestMTS = 0;
1462
115k
  int EndMTS  = mtsAllowed ? m_pcEncCfg->m_MTSIntraMaxCand : 0;
1463
115k
  if (cu.ispMode && (EndMTS || endLfnstIdx))
1464
5.34k
  {
1465
5.34k
    EndMTS = 0;
1466
5.34k
    if ((m_ispTestedModes[1].numTotalParts[cu.ispMode - 1] == 0)
1467
291
     && (m_ispTestedModes[2].numTotalParts[cu.ispMode - 1] == 0))
1468
291
    {
1469
291
      endLfnstIdx = 0;
1470
291
    }
1471
5.34k
  }
1472
115k
  if (cu.bdpcmM[CH_L])
1473
7.06k
  {
1474
7.06k
    endLfnstIdx = 0;
1475
7.06k
    EndMTS = 0;
1476
7.06k
  }
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.1k
  {
1484
14.1k
    EndMTS += 1;
1485
14.1k
  }
1486
115k
  if (endLfnstIdx || EndMTS)
1487
46.2k
  {
1488
46.2k
    bool       splitCbfLuma  = false;
1489
46.2k
    const PartSplit ispType  = CU::getISPType(cu, COMP_Y);
1490
46.2k
    CUCtx cuCtx;
1491
46.2k
    cuCtx.isDQPCoded         = true;
1492
46.2k
    cuCtx.isChromaQpAdjCoded = true;
1493
46.2k
    cs.cost                  = 0.0;
1494
46.2k
    Distortion       singleDistTmpLuma = 0;
1495
46.2k
    uint64_t         singleTmpFracBits = 0;
1496
46.2k
    double           singleCostTmp     = 0;
1497
46.2k
    const TempCtx    ctxStart          (m_CtxCache, m_CABACEstimator->getCtx());
1498
46.2k
          TempCtx    ctxBest           (m_CtxCache);
1499
46.2k
    CodingStructure &saveCS            = *m_pSaveCS[cu.ispMode?0:1];
1500
46.2k
    TransformUnit *  tmpTU             = nullptr;
1501
46.2k
    int              bestLfnstIdx      = 0;
1502
46.2k
    int              startLfnstIdx     = 0;
1503
    // speedUps LFNST
1504
46.2k
    bool   rapidLFNST                  = false;
1505
46.2k
    bool   rapidDCT                    = false;
1506
46.2k
    double thresholdDCT                = 1;
1507
1508
46.2k
    if (m_pcEncCfg->m_MTS == 2)
1509
0
    {
1510
0
      thresholdDCT += 1.4 / sqrt(cu.lwidth() * cu.lheight());
1511
0
    }
1512
1513
46.2k
    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.2k
    saveCS.pcv              = cs.pcv;
1525
46.2k
    saveCS.picture          = cs.picture;
1526
46.2k
    saveCS.area.repositionTo( cs.area);
1527
1528
46.2k
    if (cu.ispMode)
1529
5.05k
    {
1530
5.05k
      partitioner.splitCurrArea(ispType, cs);
1531
5.05k
    }
1532
1533
46.2k
    TransformUnit& tu = cs.addTU(CS::getArea(cs, partitioner.currArea(), partitioner.chType, partitioner.treeType), partitioner.chType, cs.cus[0]);
1534
1535
46.2k
    if (cu.ispMode)
1536
5.05k
    {
1537
5.05k
      saveCS.clearTUs();
1538
5.05k
      do
1539
20.2k
      {
1540
20.2k
        saveCS.addTU(
1541
20.2k
          CS::getArea(cs, partitioner.currArea(), partitioner.chType, partitioner.treeType),
1542
20.2k
          partitioner.chType, cs.cus[0]);
1543
20.2k
      } while (partitioner.nextPart(cs));
1544
1545
5.05k
      partitioner.exitCurrSplit();
1546
5.05k
    }
1547
41.1k
    else
1548
41.1k
    {
1549
41.1k
      tmpTU = saveCS.tus.empty() ? &saveCS.addTU( currArea, partitioner.chType, nullptr ) : saveCS.tus.front();
1550
41.1k
      tmpTU->initData();
1551
41.1k
      tmpTU->UnitArea::operator=( currArea );
1552
41.1k
    }
1553
1554
1555
46.2k
    std::vector<TrMode> trModes{ TrMode(0, true) };
1556
46.2k
    if (tsAllowed)
1557
14.1k
    {
1558
14.1k
      trModes.push_back(TrMode(1, true));
1559
14.1k
    }
1560
46.2k
    double dct2Cost           = MAX_DOUBLE;
1561
46.2k
    double trGrpStopThreshold = 1.001;
1562
46.2k
    double trGrpBestCost      = MAX_DOUBLE;
1563
1564
46.2k
    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.2k
    if ((EndMTS && !m_pcEncCfg->m_LFNST) || (tsAllowed && !mtsAllowed))
1589
14.1k
    {
1590
14.1k
      xPreCheckMTS(tu, &trModes, m_pcEncCfg->m_MTSIntraMaxCand, predBuf);
1591
14.1k
      if (!mtsAllowed && !trModes[1].second)
1592
2.87k
      {
1593
2.87k
        EndMTS = 0;
1594
2.87k
      }
1595
14.1k
    }
1596
1597
46.2k
    bool NStopMTS = true;
1598
1599
92.4k
    for (int modeId = 0; modeId <= EndMTS && NStopMTS; modeId++)
1600
46.2k
    {
1601
46.2k
      if (modeId > 1)
1602
0
      {
1603
0
        trGrpBestCost = MAX_DOUBLE;
1604
0
      }
1605
164k
      for (int lfnstIdx = startLfnstIdx; lfnstIdx <= endLfnstIdx; lfnstIdx++)
1606
118k
      {
1607
118k
        if (lfnstIdx && modeId)
1608
0
        {
1609
0
          continue;
1610
0
        }
1611
118k
        if (mtsAllowed || tsAllowed)
1612
22.2k
        {
1613
22.2k
          if (m_pcEncCfg->m_TS && bestMTS == MTS_SKIP)
1614
0
          {
1615
0
            break;
1616
0
          }
1617
22.2k
          if (!m_pcEncCfg->m_LFNST && !trModes[modeId].second && mtsAllowed)
1618
0
          {
1619
0
            continue;
1620
0
          }
1621
1622
22.2k
          tu.mtsIdx[COMP_Y] = trModes[modeId].first;
1623
22.2k
        }
1624
1625
118k
        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
118k
        cu.lfnstIdx                          = lfnstIdx;
1638
118k
        cuCtx.lfnstLastScanPos               = false;
1639
118k
        cuCtx.violatesLfnstConstrained[CH_L] = false;
1640
118k
        cuCtx.violatesLfnstConstrained[CH_C] = false;
1641
1642
118k
        if ((lfnstIdx != startLfnstIdx) || (modeId))
1643
72.2k
        {
1644
72.2k
          m_CABACEstimator->getCtx() = ctxStart;
1645
72.2k
        }
1646
1647
118k
        singleDistTmpLuma = 0;
1648
1649
118k
        if (cu.ispMode)
1650
15.1k
        {
1651
15.1k
          splitCbfLuma = false;
1652
1653
15.1k
          partitioner.splitCurrArea(ispType, cs);
1654
1655
15.1k
          singleCostTmp = xTestISP(cs, partitioner, bestCostForISP, ispType, splitCbfLuma, singleTmpFracBits, singleDistTmpLuma, cuCtx);
1656
1657
15.1k
          partitioner.exitCurrSplit();
1658
1659
15.1k
          if (modeId && (singleCostTmp == MAX_DOUBLE))
1660
0
          {
1661
0
            m_ispTestedModes[lfnstIdx].numTotalParts[cu.ispMode - 1] = 0;
1662
0
          }
1663
1664
15.1k
          bool storeCost = (numMode == 1) ? true : false;
1665
1666
15.1k
          if ((m_pcEncCfg->m_ISP >= 2) && (numMode <= 1))
1667
15.1k
          {
1668
15.1k
            storeCost = true;
1669
15.1k
          }
1670
1671
15.1k
          if (storeCost)
1672
15.1k
          {
1673
15.1k
            m_ispTestedModes[0].bestCost[cu.ispMode - 1] = singleCostTmp;
1674
15.1k
          }
1675
15.1k
        }
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
368
            {
1745
368
              singleCostTmp = MAX_DOUBLE;
1746
368
            }
1747
52.2k
          }
1748
103k
        }
1749
1750
118k
        if (singleCostTmp < dSingleCost)
1751
42.5k
        {
1752
42.5k
          trGrpBestCost  = singleCostTmp;
1753
42.5k
          dSingleCost    = singleCostTmp;
1754
42.5k
          singleDistLuma = singleDistTmpLuma;
1755
42.5k
          singleFracBits = singleTmpFracBits;
1756
42.5k
          bestLfnstIdx   = lfnstIdx;
1757
42.5k
          bestMTS        = modeId;
1758
1759
42.5k
          if (dSingleCost < bestCostForISP)
1760
27.0k
          {
1761
27.0k
            bestCostForISP = dSingleCost;
1762
27.0k
          }
1763
1764
42.5k
          splitCbfLumaSum = splitCbfLuma;
1765
1766
42.5k
          if (lfnstIdx == 0 && modeId == 0 && cu.ispMode == 0)
1767
41.1k
          {
1768
41.1k
            dct2Cost = singleCostTmp;
1769
1770
41.1k
            if (!TU::getCbfAtDepth(tu, COMP_Y, currDepth))
1771
34.8k
            {
1772
34.8k
              if (rapidLFNST)
1773
0
              {
1774
0
                 endLfnstIdx = 0;   // break the loop but do not cpy best
1775
0
              }
1776
1777
34.8k
              EndMTS = 0;
1778
34.8k
            }
1779
41.1k
          }
1780
1781
42.5k
          if (bestLfnstIdx != endLfnstIdx || bestMTS != EndMTS)
1782
32.3k
          {
1783
32.3k
            if (cu.ispMode)
1784
1.04k
            {
1785
1.04k
              saveCS.getRecoBuf(currArea.Y()).copyFrom(cs.getRecoBuf(currArea.Y()));
1786
1787
5.21k
              for (uint32_t j = 0; j < cs.tus.size(); j++)
1788
4.16k
              {
1789
4.16k
                saveCS.tus[j]->copyComponentFrom(*cs.tus[j], COMP_Y);
1790
4.16k
              }
1791
1.04k
            }
1792
31.2k
            else
1793
31.2k
            {
1794
31.2k
              saveCS.getPredBuf(tu.Y()).copyFrom(cs.getPredBuf(tu.Y()));
1795
31.2k
              saveCS.getRecoBuf(tu.Y()).copyFrom(cs.getRecoBuf(tu.Y()));
1796
1797
31.2k
              tmpTU->copyComponentFrom(tu, COMP_Y);
1798
31.2k
            }
1799
1800
32.3k
            ctxBest = m_CABACEstimator->getCtx();
1801
32.3k
          }
1802
      
1803
42.5k
        }
1804
75.9k
        else
1805
75.9k
        {
1806
75.9k
          if( rapidLFNST )
1807
0
          {
1808
0
            endLfnstIdx = lfnstIdx; // break the loop
1809
0
          }
1810
75.9k
        }
1811
118k
      }
1812
46.2k
      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.2k
    }
1825
1826
46.2k
    cu.lfnstIdx = bestLfnstIdx;
1827
46.2k
    if (dSingleCost != MAX_DOUBLE)
1828
42.0k
    {
1829
42.0k
      if (bestLfnstIdx != endLfnstIdx || bestMTS != EndMTS)
1830
31.8k
      {
1831
31.8k
        if (cu.ispMode)
1832
735
        {
1833
735
          const UnitArea& currArea = partitioner.currArea();
1834
735
          cs.getRecoBuf(currArea.Y()).copyFrom(saveCS.getRecoBuf(currArea.Y()));
1835
1836
735
          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.67k
          for (uint32_t j = 0; j < saveCS.tus.size(); j++)
1851
2.94k
          {
1852
2.94k
            cs.tus[j]->copyComponentFrom(*saveCS.tus[j], COMP_Y);
1853
2.94k
          }
1854
735
        }
1855
31.0k
        else
1856
31.0k
        {
1857
31.0k
          cs.getRecoBuf(tu.Y()).copyFrom(saveCS.getRecoBuf(tu.Y()));
1858
1859
31.0k
          tu.copyComponentFrom(*tmpTU, COMP_Y);
1860
31.0k
        }
1861
1862
31.8k
        m_CABACEstimator->getCtx() = ctxBest;
1863
31.8k
      }
1864
1865
      // otherwise this would've happened in useSubStructure
1866
42.0k
      cs.picture->getRecoBuf(currArea.Y()).copyFrom(cs.getRecoBuf(currArea.Y()));
1867
42.0k
    }
1868
46.2k
  }
1869
68.9k
  else
1870
68.9k
  {
1871
68.9k
    if (cu.ispMode)
1872
291
    {
1873
291
      const PartSplit ispType = CU::getISPType(cu, COMP_Y);
1874
291
      partitioner.splitCurrArea(ispType, cs);
1875
1876
291
      CUCtx      cuCtx;
1877
291
      dSingleCost = xTestISP(cs, partitioner, bestCostForISP, ispType, splitCbfLumaSum, singleFracBits, singleDistLuma, cuCtx);
1878
291
      partitioner.exitCurrSplit();
1879
291
      bool storeCost = (numMode == 1) ? true : false;
1880
291
      if ((m_pcEncCfg->m_ISP >= 2) && (numMode <= 1))
1881
291
      {
1882
291
        storeCost = true;
1883
291
      }
1884
291
      if (storeCost)
1885
291
      {
1886
291
        m_ispTestedModes[0].bestCost[cu.ispMode - 1] = dSingleCost;
1887
291
      }
1888
291
    }
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.34k
  { 
1907
5.34k
    for (auto& ptu : cs.tus)
1908
8.57k
    {
1909
8.57k
      if (currArea.Y().contains(ptu->Y()))
1910
8.57k
      {
1911
8.57k
        TU::setCbfAtDepth(*ptu, COMP_Y, currDepth, splitCbfLumaSum ? 1 : 0);
1912
8.57k
      }
1913
8.57k
    }
1914
5.34k
  }
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
280k
{
1925
280k
  UnitArea    currArea      = partitioner.currArea();
1926
1927
280k
  if( !currArea.Cb().valid() ) 
1928
0
    return ChromaCbfs(false);
1929
1930
280k
  TransformUnit& currTU     = *cs.getTU( currArea.chromaPos(), CH_C );
1931
280k
  const CodingUnit& cu  = *cs.getCU( currArea.chromaPos(), CH_C, TREE_D );
1932
280k
  ChromaCbfs cbfs(false);
1933
280k
  uint32_t   currDepth = partitioner.currTrDepth;
1934
280k
  const bool useTS = cs.picture->useTS;
1935
280k
  if (currDepth == currTU.depth)
1936
280k
  {
1937
280k
    if (!currArea.Cb().valid() || !currArea.Cr().valid())
1938
0
    {
1939
0
      return cbfs;
1940
0
    }
1941
1942
280k
    CodingStructure& saveCS = *m_pSaveCS[1];
1943
280k
    saveCS.pcv = cs.pcv;
1944
280k
    saveCS.picture = cs.picture;
1945
280k
    saveCS.area.repositionTo(cs.area);
1946
1947
280k
    TransformUnit& tmpTU = saveCS.tus.empty() ? saveCS.addTU(currArea, partitioner.chType, nullptr) : *saveCS.tus.front();
1948
280k
    tmpTU.initData();
1949
280k
    tmpTU.UnitArea::operator=(currArea);
1950
280k
    const unsigned      numTBlocks = getNumberValidTBlocks(*cs.pcv);
1951
1952
280k
    CompArea& cbArea = currTU.blocks[COMP_Cb];
1953
280k
    CompArea& crArea = currTU.blocks[COMP_Cr];
1954
280k
    double     bestCostCb = MAX_DOUBLE;
1955
280k
    double     bestCostCr = MAX_DOUBLE;
1956
280k
    Distortion bestDistCb = 0;
1957
280k
    Distortion bestDistCr = 0;
1958
1959
280k
    TempCtx ctxStartTU(m_CtxCache);
1960
280k
    TempCtx ctxStart(m_CtxCache);
1961
280k
    TempCtx ctxBest(m_CtxCache);
1962
1963
280k
    ctxStartTU = m_CABACEstimator->getCtx();
1964
280k
    ctxStart = m_CABACEstimator->getCtx();
1965
280k
    currTU.jointCbCr = 0;
1966
1967
    // Do predictions here to avoid repeating the "default0Save1Load2" stuff
1968
280k
    int  predMode = cu.bdpcmM[CH_C] ? BDPCM_IDX : CU::getFinalIntraMode(cu, CH_C);
1969
1970
280k
    PelBuf piPredCb = cs.getPredBuf(COMP_Cb);
1971
280k
    PelBuf piPredCr = cs.getPredBuf(COMP_Cr);
1972
1973
280k
    initIntraPatternChType(*currTU.cu, cbArea);
1974
280k
    initIntraPatternChType(*currTU.cu, crArea);
1975
1976
280k
    if (CU::isLMCMode(predMode))
1977
20.5k
    {
1978
20.5k
      loadLMLumaRecPels(cu, cbArea);
1979
20.5k
      predIntraChromaLM(COMP_Cb, piPredCb, cu, cbArea, predMode);
1980
20.5k
      predIntraChromaLM(COMP_Cr, piPredCr, cu, crArea, predMode);
1981
20.5k
    }
1982
259k
    else
1983
259k
    {
1984
259k
      predIntraAng(COMP_Cb, piPredCb, cu);
1985
259k
      predIntraAng(COMP_Cr, piPredCr, cu);
1986
259k
    }
1987
1988
    // determination of chroma residuals including reshaping and cross-component prediction
1989
    //----- get chroma residuals -----
1990
280k
    PelBuf resiCb = cs.getResiBuf(COMP_Cb);
1991
280k
    PelBuf resiCr = cs.getResiBuf(COMP_Cr);
1992
280k
    resiCb.subtract(cs.getOrgBuf(COMP_Cb), piPredCb);
1993
280k
    resiCr.subtract(cs.getOrgBuf(COMP_Cr), piPredCr);
1994
1995
    //===== store original residual signals (std and crossCompPred) =====
1996
1.68M
    for( int k = 0; k < 5; k++ )
1997
1.40M
    {
1998
1.40M
      m_orgResiCb[k].compactResize( cbArea );
1999
1.40M
      m_orgResiCr[k].compactResize( crArea );
2000
1.40M
    }
2001
560k
    for (int k = 0; k < 1; k += 4)
2002
280k
    {
2003
280k
      m_orgResiCb[k].copyFrom(resiCb);
2004
280k
      m_orgResiCr[k].copyFrom(resiCr);
2005
280k
    }
2006
2007
280k
    CUCtx cuCtx;
2008
280k
    cuCtx.isDQPCoded = true;
2009
280k
    cuCtx.isChromaQpAdjCoded = true;
2010
280k
    cuCtx.lfnstLastScanPos = false;
2011
2012
280k
    CodingStructure& saveCScur = *m_pSaveCS[2];
2013
2014
280k
    saveCScur.pcv = cs.pcv;
2015
280k
    saveCScur.picture = cs.picture;
2016
280k
    saveCScur.area.repositionTo(cs.area);
2017
2018
280k
    TransformUnit& tmpTUcur = saveCScur.tus.empty() ? saveCScur.addTU(currArea, partitioner.chType, nullptr) : *saveCScur.tus.front();
2019
280k
    tmpTUcur.initData();
2020
280k
    tmpTUcur.UnitArea::operator=(currArea);
2021
2022
280k
    TempCtx ctxBestTUL(m_CtxCache);
2023
2024
280k
    const SPS& sps = *cs.sps;
2025
280k
    double     bestCostCbcur = MAX_DOUBLE;
2026
280k
    double     bestCostCrcur = MAX_DOUBLE;
2027
280k
    Distortion bestDistCbcur = 0;
2028
280k
    Distortion bestDistCrcur = 0;
2029
2030
280k
    int  endLfnstIdx = (partitioner.isSepTree(cs) && partitioner.chType == CH_C && (partitioner.currArea().lwidth() < 8 || partitioner.currArea().lheight() < 8))
2031
267k
      || (partitioner.currArea().lwidth() > sps.getMaxTbSize() || partitioner.currArea().lheight() > sps.getMaxTbSize()) || !sps.LFNST ? 0 : 2;
2032
280k
    int  startLfnstIdx = 0;
2033
280k
    int  bestLfnstIdx = 0;
2034
280k
    bool testLFNST = sps.LFNST;
2035
2036
    // speedUps LFNST
2037
280k
    bool rapidLFNST = false;
2038
280k
    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
280k
    int ts_used = 0;
2047
280k
    bool testTS = false;
2048
280k
    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
280k
    if (cu.bdpcmM[CH_C])
2058
37.5k
    {
2059
37.5k
      endLfnstIdx = 0;
2060
37.5k
      testLFNST = false;
2061
37.5k
    }
2062
2063
280k
    double dSingleCostAll = MAX_DOUBLE;
2064
280k
    double singleCostTmpAll = 0;
2065
2066
1.02M
    for (int lfnstIdx = startLfnstIdx; lfnstIdx <= endLfnstIdx; lfnstIdx++)
2067
745k
    {
2068
745k
      if (rapidLFNST && lfnstIdx)
2069
0
      {
2070
0
        if ((lfnstIdx == 2) && (bestLfnstIdx == 0))
2071
0
        {
2072
0
          continue;
2073
0
        }
2074
0
      }
2075
2076
745k
      currTU.cu->lfnstIdx = lfnstIdx;
2077
745k
      if (lfnstIdx)
2078
465k
      {
2079
465k
        m_CABACEstimator->getCtx() = ctxStartTU;
2080
465k
      }
2081
2082
745k
      cuCtx.lfnstLastScanPos = false;
2083
745k
      cuCtx.violatesLfnstConstrained[CH_L] = false;
2084
745k
      cuCtx.violatesLfnstConstrained[CH_C] = false;
2085
2086
2.23M
      for (uint32_t c = COMP_Cb; c < numTBlocks; c++)
2087
1.49M
      {
2088
1.49M
        const ComponentID compID = ComponentID(c);
2089
1.49M
        const CompArea& area = currTU.blocks[compID];
2090
1.49M
        double     dSingleCost = MAX_DOUBLE;
2091
1.49M
        Distortion singleDistCTmp = 0;
2092
1.49M
        double     singleCostTmp = 0;
2093
1.49M
        bool tsAllowed = useTS && TU::isTSAllowed(currTU, compID) && m_pcEncCfg->m_useChromaTS && !currTU.cu->lfnstIdx && !cu.bdpcmM[CH_C];
2094
1.49M
        if ((partitioner.chType == CH_L) && (!ts_used))
2095
0
        {
2096
0
          tsAllowed = false;
2097
0
        }
2098
1.49M
        uint8_t nNumTransformCands = 1 + (tsAllowed ? 1 : 0); // DCT + TS = 2 tests       
2099
1.49M
        std::vector<TrMode> trModes;
2100
1.49M
        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.49M
        bool cbfDCT2 = true;
2107
1.49M
        const bool isLastMode = testLFNST || cs.sps->jointCbCr ||  tsAllowed ? false : true;
2108
1.49M
        int bestModeId = 0;
2109
1.49M
        ctxStart = m_CABACEstimator->getCtx();
2110
2.98M
        for (int modeId = 0; modeId < nNumTransformCands; modeId++)
2111
1.49M
        {
2112
1.49M
          if (lfnstIdx || modeId)
2113
930k
          {
2114
930k
            resiCb.copyFrom(m_orgResiCb[0]);
2115
930k
            resiCr.copyFrom(m_orgResiCr[0]);
2116
930k
          }
2117
1.49M
          if (modeId == 0)
2118
1.49M
          {
2119
1.49M
            if ( tsAllowed)
2120
0
            {
2121
0
              xPreCheckMTS(currTU, &trModes, m_pcEncCfg->m_MTSIntraMaxCand, 0, compID);
2122
0
            }
2123
1.49M
          }
2124
2125
1.49M
          currTU.mtsIdx[compID] = currTU.cu->bdpcmM[CH_C] ? MTS_SKIP : modeId;
2126
2127
1.49M
          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.49M
          singleDistCTmp = 0;
2136
1.49M
          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.49M
          else
2145
1.49M
        {
2146
1.49M
          xIntraCodingTUBlock(currTU, compID, false, singleDistCTmp);
2147
1.49M
        }
2148
1.49M
        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.49M
        else
2155
1.49M
        {
2156
1.49M
          uint64_t fracBitsTmp = xGetIntraFracBitsQTChroma(currTU, compID, &cuCtx);
2157
1.49M
          singleCostTmp = m_pcRdCost->calcRdCost(fracBitsTmp, singleDistCTmp);
2158
1.49M
        }
2159
2160
1.49M
        if (singleCostTmp < dSingleCost)
2161
1.49M
        {
2162
1.49M
          dSingleCost = singleCostTmp;
2163
2164
1.49M
          if (compID == COMP_Cb)
2165
745k
          {
2166
745k
            bestCostCb = singleCostTmp;
2167
745k
            bestDistCb = singleDistCTmp;
2168
745k
          }
2169
745k
          else
2170
745k
          {
2171
745k
            bestCostCr = singleCostTmp;
2172
745k
            bestDistCr = singleDistCTmp;
2173
745k
          }
2174
1.49M
          bestModeId = modeId;
2175
1.49M
          if (currTU.mtsIdx[compID] == MTS_DCT2_DCT2)
2176
1.41M
          {
2177
1.41M
            cbfDCT2 = TU::getCbfAtDepth(currTU, compID, currDepth);
2178
1.41M
          }
2179
1.49M
          if (!isLastMode)
2180
1.49M
          {
2181
1.49M
            saveCS.getRecoBuf(area).copyFrom(cs.getRecoBuf(area));
2182
1.49M
            tmpTU.copyComponentFrom(currTU, compID);
2183
1.49M
            ctxBest = m_CABACEstimator->getCtx();
2184
1.49M
          }
2185
1.49M
        }
2186
1.49M
        }
2187
1.49M
        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.49M
      }
2194
2195
745k
      singleCostTmpAll = bestCostCb + bestCostCr;
2196
2197
745k
      bool rootCbfL = false;
2198
745k
      if (testLFNST)
2199
708k
      {
2200
2.83M
        for (uint32_t t = 0; t < getNumberValidTBlocks(*cs.pcv); t++)
2201
2.12M
        {
2202
2.12M
          rootCbfL |= bool(tmpTU.cbf[t]);
2203
2.12M
        }
2204
708k
        if (rapidLFNST && !rootCbfL)
2205
0
        {
2206
0
          endLfnstIdx = lfnstIdx; // end this
2207
0
        }
2208
708k
      }
2209
2210
745k
      if (testLFNST && lfnstIdx && !cuCtx.lfnstLastScanPos)
2211
306k
      {
2212
306k
        bool cbfAtZeroDepth = CU::isSepTree(*currTU.cu)
2213
306k
          ? 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
306k
        if (cbfAtZeroDepth)
2217
1.49k
        {
2218
1.49k
          singleCostTmpAll = MAX_DOUBLE;
2219
1.49k
        }
2220
306k
      }
2221
745k
      if ((testLFNST || testTS) && (singleCostTmpAll < dSingleCostAll))
2222
242k
      {
2223
242k
        bestLfnstIdx = lfnstIdx;
2224
242k
        if ((lfnstIdx != endLfnstIdx) || testTS)
2225
232k
        {
2226
232k
          dSingleCostAll = singleCostTmpAll;
2227
2228
232k
          bestCostCbcur = bestCostCb;
2229
232k
          bestCostCrcur = bestCostCr;
2230
232k
          bestDistCbcur = bestDistCb;
2231
232k
          bestDistCrcur = bestDistCr;
2232
2233
232k
          saveCScur.getRecoBuf(cbArea).copyFrom(saveCS.getRecoBuf(cbArea));
2234
232k
          saveCScur.getRecoBuf(crArea).copyFrom(saveCS.getRecoBuf(crArea));
2235
2236
232k
          tmpTUcur.copyComponentFrom(tmpTU, COMP_Cb);
2237
232k
          tmpTUcur.copyComponentFrom(tmpTU, COMP_Cr);
2238
232k
        }
2239
242k
        ctxBestTUL = m_CABACEstimator->getCtx();
2240
242k
      }
2241
745k
    }
2242
280k
    if ((testLFNST && (bestLfnstIdx != endLfnstIdx)) || testTS)
2243
232k
    {
2244
232k
      bestCostCb = bestCostCbcur;
2245
232k
      bestCostCr = bestCostCrcur;
2246
232k
      bestDistCb = bestDistCbcur;
2247
232k
      bestDistCr = bestDistCrcur;
2248
232k
      currTU.cu->lfnstIdx = bestLfnstIdx;
2249
232k
      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
232k
    }
2260
2261
280k
    Distortion bestDistCbCr = bestDistCb + bestDistCr;
2262
2263
280k
    if (cs.sps->jointCbCr)
2264
280k
    {
2265
280k
      if ((testLFNST && (bestLfnstIdx != endLfnstIdx)) || testTS)
2266
232k
      {
2267
232k
        saveCS.getRecoBuf(cbArea).copyFrom(saveCScur.getRecoBuf(cbArea));
2268
232k
        saveCS.getRecoBuf(crArea).copyFrom(saveCScur.getRecoBuf(crArea));
2269
2270
232k
        tmpTU.copyComponentFrom(tmpTUcur, COMP_Cb);
2271
232k
        tmpTU.copyComponentFrom(tmpTUcur, COMP_Cr);
2272
232k
        m_CABACEstimator->getCtx() = ctxBestTUL;
2273
232k
        ctxBest = m_CABACEstimator->getCtx();
2274
232k
      }
2275
      // Test using joint chroma residual coding
2276
280k
      double     bestCostCbCr = bestCostCb + bestCostCr;
2277
280k
      int        bestJointCbCr = 0;
2278
280k
      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
280k
      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
280k
      bool       lastIsBest = false;
2285
280k
      bool noLFNST1 = false;
2286
280k
      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.02M
      for (int lfnstIdxj = startLfnstIdx; lfnstIdxj <= endLfnstIdx; lfnstIdxj++)
2299
745k
      {
2300
745k
        if (rapidLFNST && noLFNST1 && (lfnstIdxj == 1))
2301
0
        {
2302
0
          continue;
2303
0
        }
2304
745k
        currTU.cu->lfnstIdx = lfnstIdxj;
2305
745k
        std::vector<int> jointCbfMasksToTest;
2306
745k
        if (TU::getCbf(tmpTU, COMP_Cb) || TU::getCbf(tmpTU, COMP_Cr))
2307
263k
        {
2308
263k
          jointCbfMasksToTest = m_pcTrQuant->selectICTCandidates(currTU, m_orgResiCb, m_orgResiCr);
2309
263k
        }
2310
745k
        for (int cbfMask : jointCbfMasksToTest)
2311
263k
        {
2312
263k
          currTU.jointCbCr = (uint8_t)cbfMask;
2313
263k
          ComponentID codeCompId = ((currTU.jointCbCr >> 1) ? COMP_Cb : COMP_Cr);
2314
263k
          ComponentID otherCompId = ((codeCompId == COMP_Cb) ? COMP_Cr : COMP_Cb);
2315
263k
          bool tsAllowed = useTS && TU::isTSAllowed(currTU, codeCompId) && (m_pcEncCfg->m_useChromaTS) && !currTU.cu->lfnstIdx && !cu.bdpcmM[CH_C];
2316
263k
          if ((partitioner.chType == CH_L)&& tsAllowed && (currTU.mtsIdx[COMP_Y] != MTS_SKIP))
2317
0
          {
2318
0
            tsAllowed = false;
2319
0
          }
2320
263k
          if (!tsAllowed)
2321
263k
          {
2322
263k
            checkTSOnly = false;
2323
263k
          }
2324
263k
          uint8_t     numTransformCands = 1 + (tsAllowed && !(checkDCTOnly || checkTSOnly)? 1 : 0); // DCT + TS = 2 tests
2325
263k
          std::vector<TrMode> trModes;
2326
263k
          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
263k
          else
2332
263k
          {
2333
263k
            currTU.mtsIdx[codeCompId] = checkTSOnly || currTU.cu->bdpcmM[CH_C] ? 1 : 0;
2334
263k
          }
2335
2336
527k
          for (int modeId = 0; modeId < numTransformCands; modeId++)
2337
263k
          {
2338
263k
            Distortion distTmp = 0;
2339
263k
            currTU.mtsIdx[codeCompId] = currTU.cu->bdpcmM[CH_C] ? MTS_SKIP : MTS_DCT2_DCT2;
2340
263k
            if (numTransformCands > 1)
2341
0
            {
2342
0
              currTU.mtsIdx[codeCompId] = currTU.cu->bdpcmM[CH_C] ? MTS_SKIP : trModes[modeId].first;
2343
0
            }
2344
263k
            currTU.mtsIdx[otherCompId] = MTS_DCT2_DCT2;
2345
2346
263k
            m_CABACEstimator->getCtx() = ctxStartTU;
2347
2348
263k
            resiCb.copyFrom(m_orgResiCb[cbfMask]);
2349
263k
            resiCr.copyFrom(m_orgResiCr[cbfMask]);
2350
263k
            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
263k
            cuCtx.lfnstLastScanPos = false;
2357
263k
            cuCtx.violatesLfnstConstrained[CH_L] = false;
2358
263k
            cuCtx.violatesLfnstConstrained[CH_C] = false;
2359
263k
            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
263k
            else
2368
263k
            {
2369
263k
              xIntraCodingTUBlock(currTU, COMP_Cb, false, distTmp, 0);
2370
263k
            }
2371
2372
263k
            double costTmp = std::numeric_limits<double>::max();
2373
263k
            if (distTmp < MAX_DISTORTION)
2374
260k
            {
2375
260k
              uint64_t bits = xGetIntraFracBitsQTChroma(currTU, COMP_Cb, &cuCtx);
2376
260k
              costTmp = m_pcRdCost->calcRdCost(bits, distTmp);
2377
260k
            }
2378
3.27k
            else if (!currTU.mtsIdx[codeCompId])
2379
3.27k
            {
2380
3.27k
              numTransformCands = 1;
2381
3.27k
            }
2382
263k
            bool rootCbfL = false;
2383
1.05M
            for (uint32_t t = 0; t < getNumberValidTBlocks(*cs.pcv); t++)
2384
790k
            {
2385
790k
              rootCbfL |= bool(tmpTU.cbf[t]);
2386
790k
            }
2387
263k
            if (rapidLFNST && !rootCbfL)
2388
0
            {
2389
0
              endLfnstIdx = lfnstIdxj;
2390
0
            }
2391
263k
            if (testLFNST && currTU.cu->lfnstIdx && !cuCtx.lfnstLastScanPos)
2392
3.22k
            {
2393
3.22k
              bool cbfAtZeroDepth = CU::isSepTree(*currTU.cu) ? rootCbfL
2394
3.22k
                : (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.22k
              if (cbfAtZeroDepth)
2397
3.22k
              {
2398
3.22k
                costTmp = MAX_DOUBLE;
2399
3.22k
              }
2400
3.22k
            }
2401
263k
            if (costTmp < bestCostCbCr)
2402
99.3k
            {
2403
99.3k
              bestCostCbCr = costTmp;
2404
99.3k
              bestDistCbCr = distTmp;
2405
99.3k
              bestJointCbCr = currTU.jointCbCr;
2406
2407
              // store data
2408
99.3k
              bestLfnstIdx = lfnstIdxj;
2409
99.3k
              if ((cbfMask != jointCbfMasksToTest.back() || (lfnstIdxj != endLfnstIdx)) || (modeId != (numTransformCands - 1)))
2410
80.8k
              {
2411
80.8k
                saveCS.getRecoBuf(cbArea).copyFrom(cs.getRecoBuf(cbArea));
2412
80.8k
                saveCS.getRecoBuf(crArea).copyFrom(cs.getRecoBuf(crArea));
2413
2414
80.8k
                tmpTU.copyComponentFrom(currTU, COMP_Cb);
2415
80.8k
                tmpTU.copyComponentFrom(currTU, COMP_Cr);
2416
2417
80.8k
                ctxBest = m_CABACEstimator->getCtx();
2418
80.8k
              }
2419
18.4k
              else
2420
18.4k
              {
2421
18.4k
                lastIsBest = true;
2422
18.4k
                cs.cus[0]->lfnstIdx = bestLfnstIdx;
2423
18.4k
              }
2424
99.3k
            }
2425
263k
          }
2426
263k
        }
2427
2428
        // Retrieve the best CU data (unless it was the very last one tested)
2429
745k
      }
2430
280k
      if (!lastIsBest)
2431
261k
      {
2432
261k
        cs.getRecoBuf(cbArea).copyFrom(saveCS.getRecoBuf(cbArea));
2433
261k
        cs.getRecoBuf(crArea).copyFrom(saveCS.getRecoBuf(crArea));
2434
2435
261k
        cs.cus[0]->lfnstIdx = bestLfnstIdx;
2436
261k
        currTU.copyComponentFrom(tmpTU, COMP_Cb);
2437
261k
        currTU.copyComponentFrom(tmpTU, COMP_Cr);
2438
261k
        m_CABACEstimator->getCtx() = ctxBest;
2439
261k
      }
2440
280k
      currTU.jointCbCr = (TU::getCbf(currTU, COMP_Cb) || TU::getCbf(currTU, COMP_Cr)) ? bestJointCbCr : 0;
2441
280k
    } // jointCbCr
2442
2443
280k
    cs.dist += bestDistCbCr;
2444
280k
    cuCtx.violatesLfnstConstrained[CH_L] = false;
2445
280k
    cuCtx.violatesLfnstConstrained[CH_C] = false;
2446
280k
    cuCtx.lfnstLastScanPos = false;
2447
280k
    cuCtx.violatesMtsCoeffConstraint = false;
2448
280k
    cuCtx.mtsLastScanPos = false;
2449
280k
    cbfs.cbf(COMP_Cb) = TU::getCbf(currTU, COMP_Cb);
2450
280k
    cbfs.cbf(COMP_Cr) = TU::getCbf(currTU, COMP_Cr);
2451
280k
  }
2452
0
  else
2453
0
  {
2454
0
    unsigned   numValidTBlocks = getNumberValidTBlocks(*cs.pcv);
2455
0
    ChromaCbfs SplitCbfs(false);
2456
2457
0
    if (partitioner.canSplit(TU_MAX_TR_SPLIT, cs))
2458
0
    {
2459
0
      partitioner.splitCurrArea(TU_MAX_TR_SPLIT, cs);
2460
0
    }
2461
0
    else if (currTU.cu->ispMode)
2462
0
    {
2463
0
      partitioner.splitCurrArea(m_ispTestedModes[0].IspType, cs);
2464
0
    }
2465
0
    else
2466
0
      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
280k
  return cbfs;
2503
280k
}
2504
2505
uint64_t IntraSearch::xFracModeBitsIntraLuma(const CodingUnit& cu, const unsigned* mpmLst)
2506
939k
{
2507
939k
  m_CABACEstimator->resetBits();
2508
2509
939k
  if (!cu.ciip)
2510
939k
  {
2511
939k
    m_CABACEstimator->intra_luma_pred_mode(cu, mpmLst);
2512
939k
  }
2513
2514
939k
  return m_CABACEstimator->getEstFracBits();
2515
939k
}
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.2k
{
2520
19.2k
  const int maxCandPerType = numModesForFullRD >> 1;
2521
19.2k
  static_vector<ModeInfo, FAST_UDI_MAX_RDMODE_NUM> tempRdModeList;
2522
19.2k
  static_vector<double, FAST_UDI_MAX_RDMODE_NUM> tempCandCostList;
2523
19.2k
  const double minCost = candCostList[0];
2524
19.2k
  bool keepOneMip = candModeList.size() > numModesForFullRD;
2525
19.2k
  const int maxNumConv = 3; 
2526
2527
19.2k
  int numConv = 0;
2528
19.2k
  int numMip = 0;
2529
86.8k
  for (int idx = 0; idx < candModeList.size() - (keepOneMip?0:1); idx++)
2530
67.6k
  {
2531
67.6k
    bool addMode = false;
2532
67.6k
    const ModeInfo& orgMode = candModeList[idx];
2533
2534
67.6k
    if (!orgMode.mipFlg)
2535
48.3k
    {
2536
48.3k
      addMode = (numConv < maxNumConv);
2537
48.3k
      numConv += addMode ? 1:0;
2538
48.3k
    }
2539
19.2k
    else
2540
19.2k
    {
2541
19.2k
      addMode = ( numMip < maxCandPerType || (candCostList[idx] < thresholdHadCost * minCost) || keepOneMip );
2542
19.2k
      keepOneMip = false;
2543
19.2k
      numMip += addMode ? 1:0;
2544
19.2k
    }
2545
67.6k
    if( addMode )
2546
67.6k
    {
2547
67.6k
      tempRdModeList.push_back(orgMode);
2548
67.6k
      tempCandCostList.push_back(candCostList[idx]);
2549
67.6k
    }
2550
67.6k
  }
2551
2552
  // sort Pel Buffer
2553
19.2k
  int i = -1;
2554
19.2k
  for( auto &m: tempRdModeList)
2555
67.6k
  {
2556
67.6k
    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.6k
  }
2568
19.2k
  sortedPelBuffer.reduceTo( (int)tempRdModeList.size() );
2569
2570
19.2k
  if ((cu.lwidth() > 8 && cu.lheight() > 8))
2571
17.3k
  {
2572
    // Sort MIP candidates by Hadamard cost
2573
17.3k
    const int transpOff = getNumModesMip(cu.Y());
2574
17.3k
    static_vector<uint8_t, FAST_UDI_MAX_RDMODE_NUM> sortedMipModes(0);
2575
17.3k
    static_vector<double, FAST_UDI_MAX_RDMODE_NUM> sortedMipCost(0);
2576
17.3k
    for (uint8_t mode : { 0, 1, 2 })
2577
52.0k
    {
2578
52.0k
      uint8_t candMode = mode + uint8_t((mipHadCost[mode + transpOff] < mipHadCost[mode]) ? transpOff : 0);
2579
52.0k
      updateCandList(candMode, mipHadCost[candMode], sortedMipModes, sortedMipCost, 3);
2580
52.0k
    }
2581
2582
    // Append MIP mode to RD mode list
2583
17.3k
    const int modeListSize = int(tempRdModeList.size());
2584
34.6k
    for (int idx = 0; idx < 3; idx++)
2585
34.6k
    {
2586
34.6k
      const bool     isTransposed = (sortedMipModes[idx] >= transpOff ? true : false);
2587
34.6k
      const uint32_t mipIdx       = (isTransposed ? sortedMipModes[idx] - transpOff : sortedMipModes[idx]);
2588
34.6k
      const ModeInfo mipMode( true, isTransposed, 0, NOT_INTRA_SUBPARTITIONS, mipIdx );
2589
34.6k
      bool alreadyIncluded = false;
2590
138k
      for (int modeListIdx = 0; modeListIdx < modeListSize; modeListIdx++)
2591
121k
      {
2592
121k
        if (tempRdModeList[modeListIdx] == mipMode)
2593
17.3k
        {
2594
17.3k
          alreadyIncluded = true;
2595
17.3k
          break;
2596
17.3k
        }
2597
121k
      }
2598
2599
34.6k
      if (!alreadyIncluded)
2600
17.3k
      {
2601
17.3k
        tempRdModeList.push_back(mipMode);
2602
17.3k
        tempCandCostList.push_back(0);
2603
17.3k
        if( fastMip ) break;
2604
17.3k
      }
2605
34.6k
    }
2606
17.3k
  }
2607
2608
19.2k
  candModeList = tempRdModeList;
2609
19.2k
  candCostList = tempCandCostList;
2610
19.2k
  numModesForFullRD = int(candModeList.size());
2611
19.2k
}
2612
2613
void IntraSearch::xPreCheckMTS(TransformUnit &tu, std::vector<TrMode> *trModes, const int maxCand, PelUnitBuf *predBuf, const ComponentID& compID)
2614
14.1k
{
2615
14.1k
  if (compID == COMP_Y)
2616
14.1k
  {
2617
14.1k
    CodingStructure&  cs = *tu.cs;
2618
14.1k
    const CompArea& area = tu.blocks[compID];
2619
14.1k
    const CodingUnit& cu = *cs.getCU(area.pos(), CH_L,TREE_D);
2620
14.1k
    PelBuf piPred = cs.getPredBuf(area);
2621
14.1k
    PelBuf piResi = cs.getResiBuf(area);
2622
2623
14.1k
    initIntraPatternChType(*tu.cu, area);
2624
14.1k
    if (predBuf)
2625
12.6k
    {
2626
12.6k
      piPred.copyFrom(predBuf->Y());
2627
12.6k
    }
2628
1.53k
    else if (CU::isMIP(cu, CH_L))
2629
1.50k
    {
2630
1.50k
      initIntraMip(cu);
2631
1.50k
      predIntraMip(piPred, cu);
2632
1.50k
    }
2633
22
    else
2634
22
    {
2635
22
      predIntraAng(COMP_Y, piPred, cu);
2636
22
    }
2637
2638
    //===== get residual signal =====
2639
14.1k
    CPelBuf piOrg = cs.getOrgBuf(COMP_Y);
2640
14.1k
    piResi.subtract(piOrg, piPred);
2641
14.1k
    m_pcTrQuant->checktransformsNxN(tu, trModes, m_pcEncCfg->m_MTSIntraMaxCand, compID);
2642
14.1k
  }
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.1k
}
2649
2650
double IntraSearch::xTestISP(CodingStructure& cs, Partitioner& subTuPartitioner, double bestCostForISP, PartSplit ispType, bool& splitcbf, uint64_t& singleFracBits, Distortion& singleDistLuma, CUCtx& cuCtx)
2651
15.4k
{
2652
15.4k
  int  subTuCounter = 0;
2653
15.4k
  bool earlySkipISP = false;
2654
15.4k
  bool splitCbfLuma = false;
2655
15.4k
  CodingUnit& cu = *cs.cus[0];
2656
2657
15.4k
  Distortion singleDistTmpLumaSUM = 0;
2658
15.4k
  uint64_t   singleTmpFracBitsSUM = 0;
2659
15.4k
  double     singleCostTmpSUM = 0;
2660
15.4k
  cuCtx.isDQPCoded = true;
2661
15.4k
  cuCtx.isChromaQpAdjCoded = true;
2662
2663
15.4k
  do
2664
19.6k
  {
2665
19.6k
    Distortion singleDistTmpLuma = 0;
2666
19.6k
    uint64_t   singleTmpFracBits = 0;
2667
19.6k
    double     singleCostTmp = 0;
2668
19.6k
    TransformUnit& tmpTUcur = ((cs.tus.size() < (subTuCounter + 1)))
2669
19.6k
      ? cs.addTU(CS::getArea(cs, subTuPartitioner.currArea(), subTuPartitioner.chType,
2670
3.52k
        subTuPartitioner.treeType),
2671
3.52k
        subTuPartitioner.chType, cs.cus[0])
2672
19.6k
      : *cs.tus[subTuCounter];
2673
19.6k
    tmpTUcur.depth = subTuPartitioner.currTrDepth;
2674
2675
    // Encode TU
2676
19.6k
    xIntraCodingTUBlock(tmpTUcur, COMP_Y, false, singleDistTmpLuma, 0);
2677
19.6k
    cuCtx.mtsLastScanPos = false;
2678
2679
19.6k
    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
19.6k
    if (m_pcRdCost->calcRdCost(singleTmpFracBitsSUM, singleDistTmpLumaSUM + singleDistTmpLuma) > bestCostForISP)
2687
5.11k
    {
2688
5.11k
      earlySkipISP = true;
2689
5.11k
    }
2690
14.5k
    else
2691
14.5k
    {
2692
14.5k
      m_ispTestedModes[0].IspType = ispType;
2693
14.5k
      m_ispTestedModes[0].subTuCounter = subTuCounter;
2694
14.5k
      singleTmpFracBits = xGetIntraFracBitsQT(cs, subTuPartitioner, true, &cuCtx);
2695
14.5k
    }
2696
19.6k
    singleCostTmp = m_pcRdCost->calcRdCost(singleTmpFracBits, singleDistTmpLuma);
2697
2698
19.6k
    singleCostTmpSUM     += singleCostTmp;
2699
19.6k
    singleDistTmpLumaSUM += singleDistTmpLuma;
2700
19.6k
    singleTmpFracBitsSUM += singleTmpFracBits;
2701
2702
19.6k
    subTuCounter++;
2703
2704
19.6k
    splitCbfLuma |= TU::getCbfAtDepth( *cs.getTU(subTuPartitioner.currArea().lumaPos(), subTuPartitioner.chType, subTuCounter - 1), 
2705
19.6k
                                       COMP_Y, subTuPartitioner.currTrDepth);
2706
19.6k
    int nSubPartitions = m_ispTestedModes[cu.lfnstIdx].numTotalParts[cu.ispMode - 1];
2707
19.6k
    bool doStop = (m_pcEncCfg->m_ISP != 1) || (subTuCounter < nSubPartitions);
2708
19.6k
    if (doStop)
2709
19.6k
    {
2710
19.6k
      if (singleCostTmpSUM > bestCostForISP)
2711
13.0k
      {
2712
13.0k
        earlySkipISP = true;
2713
13.0k
        break;
2714
13.0k
      }
2715
6.65k
      if (subTuCounter < nSubPartitions)
2716
5.29k
      {
2717
5.29k
        double threshold = nSubPartitions == 2 ? 0.95 : subTuCounter == 1 ? 0.83 : 0.91;
2718
5.29k
        if (singleCostTmpSUM > bestCostForISP * threshold)
2719
1.08k
        {
2720
1.08k
          earlySkipISP = true;
2721
1.08k
          break;
2722
1.08k
        }
2723
5.29k
      }
2724
6.65k
    }
2725
19.6k
  } while (subTuPartitioner.nextPart(cs));
2726
15.4k
  singleDistLuma = singleDistTmpLumaSUM;
2727
15.4k
  singleFracBits = singleTmpFracBitsSUM;
2728
2729
15.4k
  splitcbf = splitCbfLuma;
2730
15.4k
  return earlySkipISP ? MAX_DOUBLE : singleCostTmpSUM;
2731
15.4k
}
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
13.9k
{
2735
13.9k
  if (speed)
2736
5.65k
  {
2737
5.65k
    if (mode >= 1)
2738
2.96k
    {
2739
2.96k
      if (m_ispTestedModes[0].splitIsFinished[1] && m_ispTestedModes[0].splitIsFinished[0])
2740
0
      {
2741
0
        testISP = false;
2742
0
        endISP = 0;
2743
0
      }
2744
2.96k
      else
2745
2.96k
      {
2746
2.96k
        if (m_pcEncCfg->m_ISP >= 2)
2747
2.96k
        {
2748
2.96k
          if (mode == 1) //best Hor||Ver
2749
2.68k
          {
2750
2.68k
            int bestDir = 0;
2751
8.04k
            for (int d = 0; d < 2; d++)
2752
5.36k
            {
2753
5.36k
              int d2 = d ? 0 : 1;
2754
5.36k
              if ((m_ispTestedModes[0].bestCost[d] <= m_ispTestedModes[0].bestCost[d2])
2755
5.07k
                && (m_ispTestedModes[0].bestCost[d] != MAX_DOUBLE))
2756
288
              {
2757
288
                bestDir = d + 1;
2758
288
                m_ispTestedModes[0].splitIsFinished[d2] = true;
2759
288
              }
2760
5.36k
            }
2761
2.68k
            m_ispTestedModes[0].bestModeSoFar = bestDir;
2762
2.68k
            if (m_ispTestedModes[0].bestModeSoFar <= 0)
2763
2.39k
            {
2764
2.39k
              m_ispTestedModes[0].splitIsFinished[1] = true;
2765
2.39k
              m_ispTestedModes[0].splitIsFinished[0] = true;
2766
2.39k
              testISP = false;
2767
2.39k
              endISP = 0;
2768
2.39k
            }
2769
2.68k
          }
2770
2.96k
          if (m_ispTestedModes[0].bestModeSoFar == 2)
2771
76
          {
2772
76
            noISP = 1;
2773
76
          }
2774
2.89k
          else
2775
2.89k
          {
2776
2.89k
            endISP = 1;
2777
2.89k
          }
2778
2.96k
        }
2779
2.96k
      }
2780
2.96k
    }
2781
5.65k
    if (testISP)
2782
3.25k
    {
2783
3.25k
      if (mode == 2)
2784
288
      {
2785
864
        for (int d = 0; d < 2; d++)
2786
576
        {
2787
576
          int d2 = d ? 0 : 1;
2788
576
          if (m_ispTestedModes[0].bestCost[d] == MAX_DOUBLE)
2789
265
          {
2790
265
            m_ispTestedModes[0].splitIsFinished[d] = true;
2791
265
          }
2792
576
          if ((m_ispTestedModes[0].bestCost[d2] < 1.3 * m_ispTestedModes[0].bestCost[d])
2793
311
            && (int(m_ispTestedModes[0].bestSplitSoFar) != (d + 1)))
2794
235
          {
2795
235
            if (d)
2796
197
            {
2797
197
              endISP = 1;
2798
197
            }
2799
38
            else
2800
38
            {
2801
38
              noISP = 1;
2802
38
            }
2803
235
            m_ispTestedModes[0].splitIsFinished[d] = true;
2804
235
          }
2805
576
        }
2806
288
      }
2807
2.96k
      else
2808
2.96k
      {
2809
2.96k
        if (m_ispTestedModes[0].splitIsFinished[0])
2810
38
        {
2811
38
          noISP = 1;
2812
38
        }
2813
2.96k
        if (m_ispTestedModes[0].splitIsFinished[1])
2814
250
        {
2815
250
          endISP = 1;
2816
250
        }
2817
2.96k
      }
2818
3.25k
    }
2819
5.65k
    if ((noISP == 1) && (endISP == 1))
2820
23
    {
2821
23
      endISP = 0;
2822
23
    }
2823
5.65k
  }
2824
8.29k
  else
2825
8.29k
  {
2826
8.29k
    bool stopFound = false;
2827
8.29k
    if (m_pcEncCfg->m_ISP >= 3)
2828
8.29k
    {
2829
8.29k
      if (mode)
2830
2.94k
      {
2831
2.94k
        if ((bestISP == 0) || ((bestPUMode.modeId != RdModeList[mode - 1].modeId)
2832
93
          && (bestPUMode.modeId != RdModeList[mode].modeId)))
2833
2.05k
        {
2834
2.05k
          stopFound = true;
2835
2.05k
        }
2836
2.94k
      }
2837
8.29k
    }
2838
8.29k
    if (cu.mipFlag || cu.multiRefIdx)
2839
175
    {
2840
175
      cu.mipFlag = false;
2841
175
      cu.multiRefIdx = 0;
2842
175
      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
175
    }
2854
8.29k
    if (stopFound)
2855
2.05k
    {
2856
2.05k
      testISP = false;
2857
2.05k
      endISP = 0;
2858
2.05k
      return 1;
2859
2.05k
    }
2860
6.24k
    if (!stopFound && (m_pcEncCfg->m_ISP >= 2) && (cu.intraDir[CH_L] == DC_IDX))
2861
905
    {
2862
905
      stopFound = true;
2863
905
      endISP = 0;
2864
905
      return 1;
2865
905
    }
2866
6.24k
  }
2867
10.9k
  return 0;
2868
13.9k
}
2869
2870
void IntraSearch::xSpeedUpIntra(double bestcost, int& EndMode, int& speedIntra, CodingUnit& cu)
2871
25.1k
{
2872
25.1k
  int bestIdxbefore = m_ispTestedModes[0].bestIntraMode;
2873
25.1k
  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.1k
  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.1k
  if (m_ispTestedModes[0].bestBefore[0] == -1)
2892
22.4k
  {
2893
22.4k
    speedIntra |= 7;
2894
22.4k
    if (m_pcEncCfg->m_FastIntraTools == 2)
2895
0
    {
2896
0
      EndMode = 1;
2897
0
    }
2898
22.4k
  }
2899
25.1k
  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.1k
}
2915
2916
} // namespace vvenc
2917
2918
//! \}
2919