Coverage Report

Created: 2026-08-13 07:23

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