Coverage Report

Created: 2026-09-01 06:57

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