Coverage Report

Created: 2026-07-16 06:32

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