Coverage Report

Created: 2026-10-28 06:18

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/work/vvenc/source/Lib/EncoderLib/EncModeCtrl.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     EncModeCtrl.cpp
45
    \brief    Encoder controller for trying out specific modes
46
*/
47
48
#include "EncCu.h"
49
50
#include "EncModeCtrl.h"
51
#include "CommonLib/RdCost.h"
52
#include "CommonLib/CodingStructure.h"
53
#include "CommonLib/Picture.h"
54
#include "CommonLib/UnitTools.h"
55
#include "CommonLib/dtrace_next.h"
56
57
#include <cmath>
58
59
//! \ingroup EncoderLib
60
//! \{
61
62
namespace vvenc {
63
64
void CacheBlkInfoCtrl::create(int ctuSize)
65
5.97k
{
66
5.97k
  const unsigned numPos = MAX_CU_SIZE >> MIN_CU_LOG2;
67
5.97k
  const int maxSizeIdx  = MAX_CU_SIZE_IDX - MIN_CU_LOG2;
68
69
  //static constexpr size_t numCu = 7921;
70
71
5.97k
  size_t numCu = 0;
72
  
73
41.8k
  for( int wIdx = 0; wIdx < maxSizeIdx; wIdx++ )
74
35.8k
  {
75
250k
    for( int hIdx = 0; hIdx < maxSizeIdx; hIdx++ )
76
214k
    {
77
7.09M
      for( unsigned y = 0; y < numPos; y++ )
78
6.87M
      {
79
227M
        for( unsigned x = 0; x < numPos; x++ )
80
220M
        {
81
          // a block of width W might be offset of N * W + 1/2 W (bcs of TT), same for H
82
          // W = 1 << ( wIdx + 2 )
83
          // 1/2 W = 1 << ( wIdx + 1 )
84
          // remainder of (N+1/2)*W -> x & ( ( 1 << ( wIdx + 1 ) ) - 1 )
85
  
86
220M
          if( (x + (1 << (wIdx)) <= (ctuSize >> MIN_CU_LOG2))
87
154M
              && (y + (1 << (hIdx)) <= (ctuSize >> MIN_CU_LOG2))
88
108M
              && (((x << MIN_CU_LOG2) & ((1 << (wIdx + MIN_CU_LOG2 - 1)) - 1)) == 0)
89
71.7M
              && (((y << MIN_CU_LOG2) & ((1 << (hIdx + MIN_CU_LOG2 - 1)) - 1)) == 0) )
90
47.3M
          {
91
47.3M
            numCu++;
92
47.3M
          }
93
220M
        }
94
6.87M
      }
95
214k
    }
96
35.8k
  }
97
98
5.97k
  m_codedCUInfoBuf = new CodedCUInfo[numCu];
99
5.97k
  CodedCUInfo* cuInfo = m_codedCUInfoBuf;
100
101
41.8k
  for( int wIdx = 0; wIdx < maxSizeIdx; wIdx++ )
102
35.8k
  {
103
250k
    for( int hIdx = 0; hIdx < maxSizeIdx; hIdx++ )
104
214k
    {
105
7.09M
      for( unsigned y = 0; y < numPos; y++ )
106
6.87M
      {
107
227M
        for( unsigned x = 0; x < numPos; x++ )
108
220M
        {
109
          // a block of width W might be offset of N * W + 1/2 W (bcs of TT), same for H
110
          // W = 1 << ( wIdx + 2 )
111
          // 1/2 W = 1 << ( wIdx + 1 )
112
          // remainder of (N+1/2)*W -> x & ( ( 1 << ( wIdx + 1 ) ) - 1 )
113
114
220M
          if(( x + (1<<(wIdx)) <= ( ctuSize >> MIN_CU_LOG2 ) )
115
154M
            && ( y + (1<<(hIdx)) <= ( ctuSize >> MIN_CU_LOG2 ) )
116
108M
            && ( ( ( x << MIN_CU_LOG2 ) & ((1 << (wIdx + MIN_CU_LOG2 - 1)) - 1) ) == 0 )
117
71.7M
            && ( ( ( y << MIN_CU_LOG2 ) & ((1 << (hIdx + MIN_CU_LOG2 - 1)) - 1) ) == 0 ) )
118
47.3M
          {
119
47.3M
            m_codedCUInfo[wIdx][hIdx][x][y] = cuInfo++;
120
47.3M
            m_codedCUInfo[wIdx][hIdx][x][y]->poc       = -1;
121
47.3M
            m_codedCUInfo[wIdx][hIdx][x][y]->ctuRsAddr = -1;
122
47.3M
          }
123
172M
          else
124
172M
          {
125
172M
            m_codedCUInfo[wIdx][hIdx][x][y] = nullptr;
126
172M
          }
127
220M
        }
128
6.87M
      }
129
214k
    }
130
35.8k
  }
131
5.97k
}
132
133
void CacheBlkInfoCtrl::destroy()
134
5.97k
{
135
5.97k
  delete[] m_codedCUInfoBuf;
136
5.97k
  m_codedCUInfoBuf = nullptr;
137
5.97k
}
138
139
void CacheBlkInfoCtrl::init( const Slice &slice )
140
4.97k
{
141
4.97k
  m_pcv = slice.pps->pcv;
142
4.97k
}
143
144
void CacheBlkInfoCtrl::initBlk( const UnitArea& area, int poc )
145
166k
{
146
166k
  unsigned idx1, idx2, idx3, idx4;
147
166k
  getAreaIdxNew( area.Y(), *m_pcv, idx1, idx2, idx3, idx4 );
148
149
166k
  const int ctuRsAddr = getCtuAddr( area.lumaPos(), *m_pcv );
150
166k
  CodedCUInfo* cuInfo = m_codedCUInfo[idx1][idx2][idx3][idx4];
151
152
166k
  if( cuInfo->poc != poc || cuInfo->ctuRsAddr != ctuRsAddr )
153
119k
  {
154
119k
    GCC_WARNING_DISABLE_class_memaccess
155
119k
    memset( cuInfo, 0, sizeof( CodedCUInfo ) );
156
119k
    GCC_WARNING_RESET
157
158
119k
    cuInfo->poc       = poc;
159
119k
    cuInfo->ctuRsAddr = ctuRsAddr;
160
119k
  }
161
166k
}
162
163
CodedCUInfo& CacheBlkInfoCtrl::getBlkInfo( const UnitArea& area )
164
274k
{
165
274k
  unsigned idx1, idx2, idx3, idx4;
166
274k
  getAreaIdxNew( area.Y(), *m_pcv, idx1, idx2, idx3, idx4 );
167
//  DTRACE( g_trace_ctx, D_TMP, "%d loc %d %d %d %d\n", g_trace_ctx->getChannelCounter(D_TMP), idx1, idx2, idx3, idx4);
168
274k
  return *m_codedCUInfo[idx1][idx2][idx3][idx4];
169
274k
}
170
171
void CodedCUInfo::setMv( const RefPicList refPicList, const int iRefIdx, const Mv& rMv )
172
0
{
173
0
  if( iRefIdx >= MAX_STORED_CU_INFO_REFS ) return;
174
175
0
  saveMv [refPicList][iRefIdx] = rMv;
176
0
  validMv[refPicList][iRefIdx] = true;
177
0
}
178
179
bool CodedCUInfo::getMv( const RefPicList refPicList, const int iRefIdx, Mv& rMv ) const
180
0
{
181
0
  if( iRefIdx >= MAX_STORED_CU_INFO_REFS )
182
0
  {
183
0
    rMv = saveMv[refPicList][0];
184
0
    return false;
185
0
  }
186
187
0
  rMv = saveMv[refPicList][iRefIdx];
188
0
  return validMv[refPicList][iRefIdx];
189
0
}
190
191
uint8_t CacheBlkInfoCtrl::findBestSbt( const UnitArea& area, const uint32_t curPuSse )
192
0
{
193
0
  unsigned idx1, idx2, idx3, idx4;
194
0
  getAreaIdxNew( area.Y(), *m_pcv, idx1, idx2, idx3, idx4 );
195
0
  CodedCUInfo* pSbtSave = m_codedCUInfo[idx1][idx2][idx3][idx4];
196
197
0
  for( int i = 0; i < pSbtSave->numPuInfoStored; i++ )
198
0
  {
199
0
    if( curPuSse == pSbtSave->puSse[i] )
200
0
    {
201
0
      return pSbtSave->puSbt[i];
202
0
    }
203
0
  }
204
205
0
  return MAX_UCHAR;
206
0
}
207
208
bool CacheBlkInfoCtrl::saveBestSbt( const UnitArea& area, const uint32_t curPuSse, const uint8_t curPuSbt )
209
0
{
210
0
  unsigned idx1, idx2, idx3, idx4;
211
0
  getAreaIdxNew( area.Y(), *m_pcv, idx1, idx2, idx3, idx4 );
212
0
  CodedCUInfo* pSbtSave = m_codedCUInfo[idx1][idx2][idx3][idx4];
213
214
0
  if( pSbtSave->numPuInfoStored == SBT_NUM_SL )
215
0
  {
216
0
    return false;
217
0
  }
218
219
0
  pSbtSave->puSse[pSbtSave->numPuInfoStored] = curPuSse;
220
0
  pSbtSave->puSbt[pSbtSave->numPuInfoStored] = curPuSbt;
221
0
  pSbtSave->numPuInfoStored++;
222
223
0
  return true;
224
0
}
225
226
static bool isTheSameNbHood( const CodingUnit &cu, const CodingStructure& cs, const Partitioner &partitioner, int picW, int picH )
227
0
{
228
0
  if( cu.chType != partitioner.chType )
229
0
  {
230
0
    return false;
231
0
  }
232
233
0
  const PartitioningStack &ps = partitioner.getPartStack();
234
235
0
  int i = 1;
236
237
0
  for( ; i < ps.size(); i++ )
238
0
  {
239
0
    if( ps[i].split != CU::getSplitAtDepth( cu, i - 1 ) )
240
0
    {
241
0
      break;
242
0
    }
243
0
  }
244
245
0
  const UnitArea& cmnAnc = ps[i - 1].parts[ps[i - 1].idx];
246
0
  const UnitArea cuArea  = CS::getArea( cs, cu, partitioner.chType, partitioner.treeType );
247
248
0
  for( int i = 0; i < cmnAnc.blocks.size(); i++ )
249
0
  {
250
0
    if( i < cuArea.blocks.size() && cuArea.blocks[i].valid() && cuArea.blocks[i].pos() != cmnAnc.blocks[i].pos() )
251
0
    {
252
0
      return false;
253
0
    }
254
0
  }
255
256
0
  return true;
257
0
}
258
259
void BestEncInfoCache::create( const bool reuseCuResults, const ChromaFormat chFmt, const int ctuSize )
260
5.97k
{
261
5.97k
  m_reuseCuResults = reuseCuResults;
262
263
5.97k
  if( !m_reuseCuResults ) return;
264
265
0
  m_chFmt = chFmt;
266
0
  std::fill_n( &m_bestEncInfo[0][0][0][0], sizeof( m_bestEncInfo ) / sizeof( m_bestEncInfo[0][0][0][0] ), nullptr );
267
0
}
268
269
void BestEncInfoCache::destroy()
270
5.97k
{
271
5.97k
  if( !m_reuseCuResults ) return;
272
273
0
  std::fill_n( &m_bestEncInfo[0][0][0][0], sizeof( m_bestEncInfo ) / sizeof( m_bestEncInfo[0][0][0][0] ), nullptr );
274
0
  m_filledSlots.clear();
275
0
  m_entryArena.release();
276
0
  m_coeffArena.release();
277
0
  m_dmvrMvArena.release();
278
279
0
  m_pcv = nullptr;
280
0
}
281
282
void BestEncInfoCache::init( const Slice &slice )
283
4.97k
{
284
4.97k
  if( !m_reuseCuResults ) return;
285
286
  // A new CTU starts, and no result of the previous one can match its CUs.
287
0
  for( BestEncodingInfo** slot : m_filledSlots )
288
0
  {
289
0
    *slot = nullptr;
290
0
  }
291
0
  m_filledSlots.clear();
292
0
  m_entryArena.reset();
293
0
  m_coeffArena.reset();
294
0
  m_dmvrMvArena.reset();
295
296
0
  bool isInitialized = m_pcv;
297
298
0
  m_pcv = slice.pps->pcv;
299
300
0
  if( isInitialized ) return;
301
302
0
  m_dummyCS.pcv = m_pcv;
303
0
}
304
305
// Takes storage for the result of a CU with size indices wIdx and hIdx, set up the way the earlier
306
// fixed table of results was set up when it was created.
307
BestEncodingInfo* BestEncInfoCache::xNewEntry( const int wIdx, const int hIdx )
308
0
{
309
0
  BestEncodingInfo* encInfo = m_entryArena.take( 1 );
310
0
  encInfo->~BestEncodingInfo();
311
0
  new( encInfo ) BestEncodingInfo();
312
313
0
  const UnitArea area( m_chFmt, Area( 0, 0, 1 << ( wIdx + MIN_CU_LOG2 ), 1 << ( hIdx + MIN_CU_LOG2 ) ) );
314
315
0
  encInfo->cu.UnitArea::operator=( area );
316
0
  encInfo->tu.UnitArea::operator=( area );
317
318
0
  encInfo->cu.chType   = CH_L;
319
0
  encInfo->cu.treeType = TREE_D;
320
0
  encInfo->cu.modeType = MODE_TYPE_ALL;
321
0
  encInfo->cu.qp       = MAX_SCHAR;
322
0
  encInfo->tu.chType   = CH_L;
323
324
0
  if( hIdx >= 1 && wIdx >= 1 && ( wIdx + hIdx ) >= 3 )
325
0
  {
326
0
    const int dmvrSize = ( 1 << std::max( 0, ( wIdx + MIN_CU_LOG2 - DMVR_SUBCU_SIZE_LOG2 ) ) ) * ( 1 << std::max( 0, ( hIdx + MIN_CU_LOG2 - DMVR_SUBCU_SIZE_LOG2 ) ) );
327
0
    encInfo->cu.mvdL0SubPu = m_dmvrMvArena.take( dmvrSize );
328
0
  }
329
330
0
  TCoeffSig* coeff[MAX_NUM_TBLOCKS] = { 0, };
331
0
  for( int i = 0; i < area.blocks.size(); i++ )
332
0
  {
333
0
    coeff[i] = m_coeffArena.take( area.blocks[i].area() );
334
0
  }
335
336
0
  encInfo->tu.cs = &m_dummyCS;
337
0
  encInfo->tu.init( coeff );
338
339
0
  encInfo->poc      = -1;
340
0
  encInfo->testMode = EncTestMode();
341
0
  return encInfo;
342
0
}
343
344
bool BestEncInfoCache::setFromCs( const CodingStructure& cs, const EncTestMode& testMode, const Partitioner& partitioner )
345
104k
{
346
104k
  if( !m_reuseCuResults ) return false;
347
348
0
  if( cs.cus.size() != 1 || cs.tus.size() != 1 || partitioner.maxBTD <= 1 )
349
0
  {
350
0
    return false;
351
0
  }
352
353
0
  unsigned idx1, idx2, idx3, idx4;
354
0
  getAreaIdxNew( cs.area.Y(), *m_pcv, idx1, idx2, idx3, idx4 );
355
356
0
  BestEncodingInfo*& slot = m_bestEncInfo[idx1][idx2][idx3][idx4];
357
0
  if( !slot )
358
0
  {
359
0
    slot = xNewEntry( idx1, idx2 );
360
0
    m_filledSlots.push_back( &slot );
361
0
  }
362
0
  BestEncodingInfo& encInfo = *slot;
363
364
0
  encInfo.poc            =  cs.picture->poc;
365
0
  encInfo.cu.UnitArea::operator= ( *cs.cus.front() );
366
0
  encInfo.tu.UnitArea::operator= ( *cs.tus.front() );
367
0
  encInfo.cu             = *cs.cus.front();
368
0
  for( auto &blk : cs.tus.front()->blocks )
369
0
  {
370
0
    if( blk.valid() ) encInfo.tu.copyComponentFrom( *cs.tus.front(), blk.compID );
371
0
  }
372
0
  encInfo.testMode       = testMode;
373
0
  encInfo.dist           = cs.dist;
374
0
  encInfo.costEDO        = cs.costDbOffset;
375
376
0
  return true;
377
0
}
378
379
bool BestEncInfoCache::isReusingCuValid( const CodingStructure& cs, const Partitioner& partitioner, int qp )
380
271k
{
381
271k
  if( !m_reuseCuResults || partitioner.treeType == TREE_C || partitioner.maxBTD <= 1 )
382
271k
  {
383
271k
    return false; //if save & load is allowed for chroma CUs, we should check whether luma info (pred, recon, etc) is the same, which is quite complex
384
271k
  }
385
386
0
  unsigned idx1, idx2, idx3, idx4;
387
0
  getAreaIdxNew( cs.area.Y(), *m_pcv, idx1, idx2, idx3, idx4 );
388
389
0
  const BestEncodingInfo* stored = m_bestEncInfo[idx1][idx2][idx3][idx4];
390
0
  if( !stored )
391
0
  {
392
0
    return false;
393
0
  }
394
0
  const BestEncodingInfo& encInfo = *stored;
395
396
0
  if( encInfo.cu.treeType != partitioner.treeType || encInfo.cu.modeType != partitioner.modeType )
397
0
  {
398
0
    return false;
399
0
  }
400
0
  if( encInfo.cu.qp != qp )
401
0
    return false;
402
0
  if( cs.picture->poc != encInfo.poc 
403
0
    || CS::getArea( cs, cs.area, partitioner.chType, partitioner.treeType ) != CS::getArea( cs, encInfo.cu, partitioner.chType, partitioner.treeType ) 
404
0
    || !isTheSameNbHood( encInfo.cu, cs, partitioner, (cs.picture->Y().width), (cs.picture->Y().height))
405
0
    || CU::isIBC(encInfo.cu)
406
0
    || partitioner.currQgEnable() || cs.currQP[partitioner.chType] != encInfo.cu.qp
407
0
    )
408
0
  {
409
0
    return false;
410
0
  }
411
0
  else
412
0
  {
413
0
    return true;
414
0
  }
415
0
}
416
417
bool BestEncInfoCache::setCsFrom( CodingStructure& cs, EncTestMode& testMode, const Partitioner& partitioner ) const
418
0
{
419
0
  if( !m_reuseCuResults ) return false;
420
421
0
  unsigned idx1, idx2, idx3, idx4;
422
0
  getAreaIdxNew( cs.area.Y(), *m_pcv, idx1, idx2, idx3, idx4 );
423
424
0
  const BestEncodingInfo* stored = m_bestEncInfo[idx1][idx2][idx3][idx4];
425
0
  if( !stored )
426
0
  {
427
0
    return false;
428
0
  }
429
0
  const BestEncodingInfo& encInfo = *stored;
430
431
0
  if( cs.picture->poc != encInfo.poc 
432
0
    || CS::getArea( cs, cs.area, partitioner.chType, partitioner.treeType ) != CS::getArea( cs, encInfo.cu, partitioner.chType, partitioner.treeType ) 
433
0
    || !isTheSameNbHood( encInfo.cu, cs, partitioner, (cs.picture->Y().width), (cs.picture->Y().height))
434
0
    || partitioner.currQgEnable() || cs.currQP[partitioner.chType] != encInfo.cu.qp
435
0
    )
436
0
  {
437
0
    return false;
438
0
  }
439
440
0
  const UnitArea ua = CS::getArea( cs, cs.area, partitioner.chType, partitioner.treeType );
441
0
  CodingUnit     &cu = cs.addCU( ua, partitioner.chType );
442
0
  cu.treeType = partitioner.treeType;
443
0
  cu.modeType = partitioner.modeType;
444
0
  cu.initPuData();
445
0
  TransformUnit  &tu = cs.addTU( ua, partitioner.chType, &cu );
446
447
0
  cu          .repositionTo( encInfo.cu );
448
0
  cu          .repositionTo( encInfo.cu );
449
0
  tu          .repositionTo( encInfo.tu );
450
451
0
  cu          = encInfo.cu;
452
0
  cu          = encInfo.cu;
453
0
  for( auto &blk : tu.blocks )
454
0
  {
455
0
    if( blk.valid() ) tu.copyComponentFrom( encInfo.tu, blk.compID );
456
0
  }
457
458
0
  testMode    = encInfo.testMode;
459
0
  cs.dist     = encInfo.dist;
460
0
  cs.costDbOffset = encInfo.costEDO;
461
0
  return true;
462
0
}
463
464
465
//////////////////////////////////////////////////////////////////////////
466
// EncModeCtrl
467
//////////////////////////////////////////////////////////////////////////
468
void EncModeCtrl::init( const VVEncCfg& encCfg, RdCost* pRdCost )
469
5.97k
{
470
5.97k
  m_pcEncCfg = &encCfg;
471
5.97k
  m_pcRdCost = pRdCost;
472
5.97k
  comprCUCtx = nullptr;
473
474
5.97k
  CacheBlkInfoCtrl::create( encCfg.m_CTUSize );
475
5.97k
  BestEncInfoCache::create( encCfg.m_reuseCuResults, encCfg.m_internChromaFormat, encCfg.m_CTUSize );
476
5.97k
}
477
478
void EncModeCtrl::destroy()
479
5.97k
{
480
5.97k
  CacheBlkInfoCtrl::destroy();
481
5.97k
  BestEncInfoCache::destroy();
482
5.97k
}
483
484
void EncModeCtrl::initCTUEncoding( const Slice &slice, int tileIdx )
485
4.97k
{
486
4.97k
  CacheBlkInfoCtrl::init( slice );
487
4.97k
  BestEncInfoCache::init( slice );
488
489
4.97k
  CHECK( !m_ComprCUCtxList.empty(), "Mode list is not empty at the beginning of a CTU" );
490
491
4.97k
  if( m_pcEncCfg->m_fastQtBtEnc )
492
4.97k
  {
493
4.97k
    m_skipThresholdE0023FastEnc = ((slice.getMinPictureDistance() <= PICTURE_DISTANCE_TH) ? FAST_SKIP_DEPTH : SKIP_DEPTH);
494
4.97k
  }
495
0
  else
496
0
  {
497
0
    m_skipThresholdE0023FastEnc = SKIP_DEPTH;
498
0
  }
499
500
4.97k
  m_tileIdx = tileIdx;
501
4.97k
}
502
503
void EncModeCtrl::initCULevel( Partitioner &partitioner, const CodingStructure& cs, int  MergeSimpleFlag)
504
166k
{
505
  // Min/max depth
506
166k
  unsigned minDepth = 0;
507
166k
  unsigned maxDepth = cs.pcv->getMaxDepth( cs.slice->sliceType, partitioner.chType );
508
166k
  if( m_pcEncCfg->m_useFastLCTU )
509
166k
  {
510
166k
    partitioner.setMaxMinDepth(minDepth, maxDepth, cs, cs.picture->useQtbttSpeedUpMode, MergeSimpleFlag);
511
166k
  }
512
513
166k
  minDepth = std::max<unsigned>( minDepth, cs.pcv->getMinDepth( cs.slice->sliceType, partitioner.chType ) );
514
166k
  maxDepth = std::min<unsigned>( maxDepth, cs.pcv->getMaxDepth( cs.slice->sliceType, partitioner.chType ) );
515
516
166k
  m_ComprCUCtxList.push_back( ComprCUCtx( cs, minDepth, maxDepth ) );
517
166k
  comprCUCtx = &m_ComprCUCtxList.back();
518
519
166k
  const CodingUnit* cuLeft  = cs.getCURestricted( cs.area.blocks[partitioner.chType].pos().offset( -1, 0 ), cs.area.blocks[partitioner.chType].pos(), cs.slice->independentSliceIdx, m_tileIdx, partitioner.chType, partitioner.treeType );
520
166k
  const CodingUnit* cuAbove = cs.getCURestricted( cs.area.blocks[partitioner.chType].pos().offset( 0, -1 ), cs.area.blocks[partitioner.chType].pos(), cs.slice->independentSliceIdx, m_tileIdx, partitioner.chType, partitioner.treeType );
521
522
166k
  const bool qtBeforeBt = ( (  cuLeft  &&  cuAbove  && cuLeft ->qtDepth > partitioner.currQtDepth && cuAbove->qtDepth > partitioner.currQtDepth )
523
163k
                         || (  cuLeft  && !cuAbove  && cuLeft ->qtDepth > partitioner.currQtDepth )
524
160k
                         || ( !cuLeft  &&  cuAbove  && cuAbove->qtDepth > partitioner.currQtDepth )
525
157k
                         || ( !cuAbove && !cuLeft   && cs.area.lwidth() >= ( 32 << cs.slice->TLayer ) )
526
140k
                         || ( m_pcEncCfg->m_qtbttSpeedUp > 1 && partitioner.maxBTD < ( ( cs.slice->isIntra() && !cs.sps->IBC ) ? 3 : 2 ) ) )
527
26.3k
                         && ( cs.area.lwidth() > ( cs.pcv->getMinQtSize( *cs.slice, partitioner.chType ) << 1 ) );
528
529
  // set features
530
166k
  ComprCUCtx &cuECtx    = *comprCUCtx;
531
166k
  cuECtx.qtBeforeBt     = qtBeforeBt;
532
166k
  cuECtx.doTriHorzSplit = true;
533
166k
  cuECtx.doTriVertSplit = true;
534
166k
  cuECtx.doMoreSplits   = 3;
535
166k
  cuECtx.isReusingCu    = isReusingCuValid( cs, partitioner, cs.baseQP );
536
166k
  cuECtx.didHorzSplit   = partitioner.canSplit( CU_HORZ_SPLIT, cs );
537
166k
  cuECtx.didVertSplit   = partitioner.canSplit( CU_VERT_SPLIT, cs );
538
166k
  cuECtx.doHorChromaSplit = true;
539
166k
  cuECtx.doVerChromaSplit = true;
540
166k
  cuECtx.doQtChromaSplit  = true;
541
542
166k
  if( m_pcEncCfg->m_contentBasedFastQtbt && cs.pcv->getMaxMTTDepth(*cs.slice, partitioner.chType))
543
166k
  {
544
166k
    const CompArea& currArea = partitioner.currArea().Y();
545
166k
    int cuHeight  = currArea.height;
546
166k
    int cuWidth   = currArea.width;
547
548
166k
    const bool condIntraInter = m_pcEncCfg->m_IntraPeriod == 1 ? ( partitioner.currBtDepth == 0 ) : ( cuHeight > 32 && cuWidth > 32 );
549
550
166k
    if( cuWidth == cuHeight && condIntraInter )
551
37.2k
    {
552
37.2k
      const CPelBuf bufCurrArea = cs.getOrgBuf( partitioner.currArea().block( COMP_Y ) );
553
554
37.2k
      int grad[4];
555
37.2k
      g_pelBufOP.absGradientSums( bufCurrArea.buf, bufCurrArea.stride, cuWidth, cuHeight, grad );
556
557
37.2k
      cuECtx.grad_horVal = (double)grad[0];
558
37.2k
      cuECtx.grad_verVal = (double)grad[1];
559
37.2k
      cuECtx.grad_dowVal = (double)grad[2];
560
37.2k
      cuECtx.grad_dupVal = (double)grad[3];
561
37.2k
    }
562
166k
  }
563
166k
}
564
565
void EncModeCtrl::finishCULevel( Partitioner &partitioner )
566
166k
{
567
166k
  m_ComprCUCtxList.pop_back();
568
166k
  comprCUCtx = m_ComprCUCtxList.size() ? &m_ComprCUCtxList.back() : nullptr;
569
166k
}
570
571
bool EncModeCtrl::trySplit( const EncTestMode& encTestmode, const CodingStructure &cs, Partitioner& partitioner, const EncTestMode& lastTestmode )
572
403k
{
573
403k
  ComprCUCtx& cuECtx = *comprCUCtx;
574
575
403k
  const PartSplit implicitSplit = partitioner.getImplicitSplit( cs );
576
403k
  const bool isBoundary         = implicitSplit != CU_DONT_SPLIT;
577
578
403k
  if( ( m_pcEncCfg->m_IntraPeriod == 1 ) && ( partitioner.chType == CH_C ) && ( !cuECtx.doQtChromaSplit ) )
579
0
  {
580
0
    cuECtx.maxDepth         = partitioner.currDepth;
581
0
  }
582
583
403k
  if( isBoundary )
584
101k
  {
585
101k
    if( encTestmode.type != ETM_SPLIT_QT )
586
40.0k
    {
587
40.0k
      return getPartSplit( encTestmode ) == implicitSplit;
588
40.0k
    }
589
61.4k
    else
590
61.4k
    {
591
61.4k
      return partitioner.canSplit( CU_QUAD_SPLIT, cs );
592
61.4k
    }
593
101k
  }
594
595
302k
  const Slice&           slice       = *cs.slice;
596
302k
  const uint32_t         width       = partitioner.currArea().lumaSize().width;
597
302k
  const CodingStructure *bestCS      = cuECtx.bestCS;
598
302k
  const CodingUnit      *bestCU      = cuECtx.bestCU;
599
600
302k
  if( cuECtx.minDepth > partitioner.currQtDepth && partitioner.canSplit( CU_QUAD_SPLIT, cs ) )
601
0
  {
602
    // enforce QT
603
0
    return encTestmode.type == ETM_SPLIT_QT;
604
0
  }
605
302k
  else if( encTestmode.type == ETM_SPLIT_QT && cuECtx.maxDepth <= partitioner.currQtDepth )
606
1.81k
  {
607
    // don't check this QT depth
608
1.81k
    return false;
609
1.81k
  }
610
611
300k
  CHECK( ! isModeSplit( encTestmode ), "wrong method" );
612
613
  //////////////////////////////////////////////////////////////////////////
614
  // skip-history rule - don't split further if at least for three past levels
615
  //                     in the split tree it was found that skip is the best mode
616
  //////////////////////////////////////////////////////////////////////////
617
300k
  int skipScore = 0;
618
619
300k
  if ((!slice.isIntra() || slice.sps->IBC) && cuECtx.isBestNoSplitSkip )
620
0
  {
621
0
    for( int i = 2; i <= m_ComprCUCtxList.size(); i++ )
622
0
    {
623
0
      if( ( m_ComprCUCtxList.end() - i )->isBestNoSplitSkip )
624
0
      {
625
0
        skipScore += 1;
626
0
      }
627
0
      else
628
0
      {
629
0
        break;
630
0
      }
631
0
    }
632
0
  }
633
634
300k
  const PartSplit split = getPartSplit( encTestmode );
635
300k
  if( !partitioner.canSplit( split, cs ) || skipScore >= 2 || ( skipScore == 1 && m_ComprCUCtxList.size() == 2 ) )
636
75.7k
  {
637
75.7k
    if( split == CU_HORZ_SPLIT ) cuECtx.didHorzSplit = false;
638
75.7k
    if( split == CU_VERT_SPLIT ) cuECtx.didVertSplit = false;
639
75.7k
    if( split == CU_QUAD_SPLIT ) cuECtx.didQuadSplit = false;
640
75.7k
    return false;
641
75.7k
  }
642
643
224k
  if( isChroma( partitioner.chType ) && !cuECtx.doHorChromaSplit && ( split == CU_HORZ_SPLIT || split == CU_TRIH_SPLIT ) )
644
0
  {
645
0
    if( split == CU_HORZ_SPLIT )
646
0
    {
647
0
      cuECtx.didHorzSplit = false;
648
0
    }
649
650
0
    return false;
651
0
  }
652
653
224k
  if( isChroma( partitioner.chType ) && !cuECtx.doVerChromaSplit && ( split == CU_VERT_SPLIT || split == CU_TRIV_SPLIT ) )
654
0
  {
655
0
    if( split == CU_VERT_SPLIT )
656
0
    {
657
0
      cuECtx.didVertSplit = false;
658
0
    }
659
660
0
    return false;
661
0
  }
662
663
224k
  if( m_pcEncCfg->m_contentBasedFastQtbt )
664
224k
  {
665
224k
    const CompArea& currArea = partitioner.currArea().Y();
666
224k
    int cuHeight  = currArea.height;
667
224k
    int cuWidth   = currArea.width;
668
669
224k
    const bool condIntraInter = m_pcEncCfg->m_IntraPeriod == 1 ? ( partitioner.currBtDepth == 0 ) : ( cuHeight > 32 && cuWidth > 32 );
670
671
224k
    if( cuWidth == cuHeight && condIntraInter && split != CU_QUAD_SPLIT )
672
13.4k
    {
673
13.4k
      const double th1 = m_pcEncCfg->m_IntraPeriod == 1 ?  1.2              :  1.0;
674
13.4k
      const double th2 = m_pcEncCfg->m_IntraPeriod == 1 ? (1.2 / sqrt( 2 )) : (1.0 / sqrt( 2 ));
675
676
13.4k
      if( cuECtx.grad_horVal > th1 * cuECtx.grad_verVal && cuECtx.grad_horVal > th2 * cuECtx.grad_dowVal && cuECtx.grad_horVal > th2 * cuECtx.grad_dupVal && ( split == CU_HORZ_SPLIT || split == CU_TRIH_SPLIT ) )
677
0
      {
678
0
        return false;
679
0
      }
680
13.4k
      if( th2 * cuECtx.grad_dupVal < cuECtx.grad_verVal && th2 * cuECtx.grad_dowVal < cuECtx.grad_verVal && th1 * cuECtx.grad_horVal < cuECtx.grad_verVal && ( split == CU_VERT_SPLIT || split == CU_TRIV_SPLIT ) )
681
0
      {
682
0
        return false;
683
0
      }
684
13.4k
    }
685
686
224k
    if( m_pcEncCfg->m_IntraPeriod == 1 && cuWidth <= 32 && cuHeight <= 32 && bestCS && bestCS->tus.size() == 1 && bestCU && bestCU->depth == partitioner.currDepth && partitioner.currBtDepth > 1 && isLuma( partitioner.chType ) )
687
0
    {
688
0
      if( !bestCU->rootCbf )
689
0
      {
690
0
        return false;
691
0
      }
692
0
    }
693
224k
  }
694
695
224k
  if( m_pcEncCfg->m_qtbttSpeedUp > 1 )
696
224k
  {
697
224k
    const int availDepth = cs.pcv->getMaxMTTDepth( slice, partitioner.chType ) - partitioner.currMtDepth;
698
224k
    if( bestCU && bestCU->skip && availDepth <= ( 3 - m_skipThresholdE0023FastEnc ) && !isModeSplit( lastTestmode ) && split != CU_QUAD_SPLIT )
699
0
    {
700
0
      return false;
701
0
    }
702
224k
  }
703
224k
  if( bestCU && bestCU->skip && bestCU->mtDepth >= m_skipThresholdE0023FastEnc && !isModeSplit( lastTestmode ) )
704
0
  {
705
0
    return false;
706
0
  }
707
708
224k
  bool resetFeature = false;
709
710
224k
  switch( split )
711
224k
  {
712
27.3k
    case CU_QUAD_SPLIT:
713
27.3k
      {
714
27.3k
        if( !cuECtx.qtBeforeBt && bestCU )
715
24.4k
        {
716
24.4k
          unsigned maxBTD        = cs.pcv->getMaxMTTDepth( slice, partitioner.chType );
717
24.4k
          const CodingUnit *cuBR = bestCS->cus.back();
718
24.4k
          unsigned height        = partitioner.currArea().lumaSize().height;
719
720
24.4k
          if(((bestCU->btDepth == 0 && maxBTD >= ((slice.isIntra() && !slice.sps->IBC) ? 3 : 2))
721
119
            || (bestCU->btDepth == 1 && cuBR && cuBR->btDepth == 1 && maxBTD >= ((slice.isIntra() && !slice.sps->IBC) ? 4 : 3)))
722
24.2k
            && (width <= MAX_TB_SIZEY && height <= MAX_TB_SIZEY)
723
24.2k
            && cuECtx.didHorzSplit && cuECtx.didVertSplit )
724
18.4k
          {
725
18.4k
            return false;
726
18.4k
          }
727
24.4k
        }
728
8.95k
        if( bestCS )
729
8.95k
        {
730
8.95k
          if( m_pcEncCfg->m_useEarlyCU == 2 && bestCS->cost != MAX_DOUBLE && bestCU && bestCU->skip && cuECtx.nonSkipWasTested && bestCS->cus.size() == 1 )
731
0
          {
732
0
            return false;
733
0
          }
734
735
8.95k
          int stopSplit = (m_pcEncCfg->m_FastInferMerge >> 4) && (bestCS->slice->TLayer > 4);
736
8.95k
          int limitBLsize = stopSplit ? 2048 : 1024;
737
8.95k
          if((m_pcEncCfg->m_useEarlyCU == 1 || stopSplit) && bestCS->cost != MAX_DOUBLE && bestCU && bestCU->skip && partitioner.currArea().lumaSize().area() < limitBLsize )
738
0
          {
739
0
            return false;
740
0
          }
741
8.95k
        }
742
8.95k
      }
743
8.95k
      break;
744
68.8k
    case CU_HORZ_SPLIT:
745
132k
    case CU_VERT_SPLIT:
746
132k
      resetFeature = true;
747
132k
      break;
748
36.4k
    case CU_TRIH_SPLIT:
749
36.4k
      if( cuECtx.didHorzSplit && bestCU && bestCU->btDepth == partitioner.currBtDepth && !bestCU->rootCbf )
750
29.7k
      {
751
29.7k
        return false;
752
29.7k
      }
753
754
6.70k
      if( m_pcEncCfg->m_qtbttSpeedUp > 1 )
755
6.70k
      {
756
        //unsigned maxBTD = cs.pcv->getMaxMTTDepth( slice, partitioner.chType );
757
6.70k
        if( /*maxBTD == 1 && */cuECtx.didHorzSplit && cuECtx.didVertSplit && cuECtx.bestCostHorzSplit > cuECtx.bestCostVertSplit )
758
1.88k
        {
759
1.88k
          return false;
760
1.88k
        }
761
6.70k
      }
762
763
4.81k
      if( !cuECtx.doTriHorzSplit )
764
12
      {
765
12
        return false;
766
12
      }
767
768
4.80k
      if (m_pcEncCfg->m_fastTTSplit && cuECtx.bestCostHorzSplit < MAX_DOUBLE)
769
3.67k
      {
770
3.67k
        if (cuECtx.bestCostBeforeSplit < MAX_DOUBLE && (cuECtx.bestCostHorzSplit > m_pcEncCfg->m_fastTT_th * cuECtx.bestCostBeforeSplit))
771
3.05k
        {
772
3.05k
          return false;
773
3.05k
        }
774
627
        if (cuECtx.bestCostVertSplit < MAX_DOUBLE && (cuECtx.bestCostHorzSplit > m_pcEncCfg->m_fastTT_th * cuECtx.bestCostVertSplit))
775
0
        {
776
0
          return false;
777
0
        }
778
627
      }
779
1.75k
      break;
780
28.8k
    case CU_TRIV_SPLIT:
781
28.8k
      if( cuECtx.didVertSplit && bestCU && bestCU->btDepth == partitioner.currBtDepth && !bestCU->rootCbf )
782
24.7k
      {
783
24.7k
        return false;
784
24.7k
      }
785
786
4.09k
      if( m_pcEncCfg->m_qtbttSpeedUp > 1 )
787
4.09k
      {
788
        //unsigned maxBTD = cs.pcv->getMaxMTTDepth( slice, partitioner.chType );
789
4.09k
        if( /*maxBTD == 1 && */cuECtx.didHorzSplit && cuECtx.didVertSplit && cuECtx.bestCostHorzSplit < cuECtx.bestCostVertSplit )
790
2.34k
        {
791
2.34k
          return false;
792
2.34k
        }
793
4.09k
      }
794
795
1.74k
      if( !cuECtx.doTriVertSplit )
796
43
      {
797
43
        return false;
798
43
      }
799
800
1.70k
      if (m_pcEncCfg->m_fastTTSplit && cuECtx.bestCostVertSplit < MAX_DOUBLE)
801
641
      {
802
641
        if (cuECtx.bestCostBeforeSplit < MAX_DOUBLE && (cuECtx.bestCostVertSplit > m_pcEncCfg->m_fastTT_th * cuECtx.bestCostBeforeSplit))
803
434
        {
804
434
          return false;
805
434
        }
806
207
        if (cuECtx.bestCostHorzSplit < MAX_DOUBLE && (cuECtx.bestCostVertSplit > m_pcEncCfg->m_fastTT_th * cuECtx.bestCostHorzSplit))
807
0
        {
808
0
          return false;
809
0
        }
810
207
      }
811
1.27k
      break;
812
1.27k
    default:
813
0
      THROW( "Only CU split modes are governed by the EncModeCtrl" );
814
0
      return false;
815
0
      break;
816
224k
  }
817
818
144k
  switch( split )
819
144k
  {
820
68.8k
    case CU_HORZ_SPLIT:
821
70.5k
    case CU_TRIH_SPLIT:
822
70.5k
      if( cuECtx.qtBeforeBt && cuECtx.didQuadSplit )
823
2.39k
      {
824
2.39k
        if( cuECtx.maxQtSubDepth > partitioner.currQtDepth + 1 )
825
0
        {
826
0
          if( resetFeature ) cuECtx.didHorzSplit = false;
827
0
          return false;
828
0
        }
829
2.39k
      }
830
70.5k
      break;
831
70.5k
    case CU_VERT_SPLIT:
832
64.4k
    case CU_TRIV_SPLIT:
833
64.4k
      if( cuECtx.qtBeforeBt && cuECtx.didQuadSplit )
834
2.46k
      {
835
2.46k
        if( cuECtx.maxQtSubDepth > partitioner.currQtDepth + 1 )
836
0
        {
837
0
          if( resetFeature ) cuECtx.didVertSplit = false;
838
0
          return false;
839
0
        }
840
2.46k
      }
841
64.4k
      break;
842
64.4k
    default:
843
8.95k
      break;
844
144k
  }
845
846
144k
  if( split == CU_QUAD_SPLIT )
847
8.95k
  {
848
8.95k
    cuECtx.didQuadSplit = m_pcEncCfg->m_qtbttSpeedUp <= 1 || !!cuECtx.doMoreSplits;
849
8.95k
  }
850
851
144k
  return m_pcEncCfg->m_qtbttSpeedUp <= 1 || !!cuECtx.doMoreSplits;
852
144k
}
853
854
bool EncModeCtrl::tryMode( const EncTestMode& encTestmode, const CodingStructure &cs, Partitioner& partitioner )
855
169k
{
856
169k
  CHECK( isModeSplit( encTestmode ), "wrong method");
857
858
169k
  ComprCUCtx& cuECtx = m_ComprCUCtxList.back();
859
860
169k
  if( cuECtx.minDepth > partitioner.currQtDepth && partitioner.canSplit( CU_QUAD_SPLIT, cs ) )
861
0
  {
862
    // enforce QT
863
0
    return false;
864
0
  }
865
866
169k
  const Slice&           slice        = *cs.slice;
867
169k
  const uint32_t         numComp      = getNumberValidComponents( slice.sps->chromaFormatIdc );
868
169k
  const CodedCUInfo      &relatedCU   = getBlkInfo( partitioner.currArea() );
869
169k
  const Area             &lumaArea    = partitioner.currArea().Y();
870
169k
  const CodingStructure* bestCS       = cuECtx.bestCS;
871
169k
  const EncTestMode      bestMode     = bestCS ?cuECtx.bestMode : EncTestMode();
872
873
169k
  if( encTestmode.type == ETM_INTRA )
874
104k
  {
875
    // if this is removed, the IntraSearch::xIntraCodingLumaQT needs to be adapted to support Intra TU split
876
    // also isXXAvailable in IntraPrediction.cpp need to be fixed to check availability within the same CU without isDecomp
877
104k
    if (m_pcEncCfg->m_FastInferMerge && !slice.isIntra() && !slice.isIRAP() && !(cs.area.lwidth() == 4 && cs.area.lheight() == 4) && !partitioner.isConsIntra())
878
0
    {
879
0
      if (bestCS && (bestCS->slice->TLayer > (m_pcEncCfg->m_maxTLayer - (m_pcEncCfg->m_FastInferMerge & 7)))
880
0
        && (bestCS->bestParent != nullptr) && bestCS->bestParent->cus.size() && (bestCS->bestParent->cus[0]->skip))
881
0
      {
882
0
        return false;
883
0
      }
884
0
    }
885
886
104k
    if( lumaArea.width > cs.sps->getMaxTbSize() || lumaArea.height > cs.sps->getMaxTbSize() )
887
0
    {
888
0
      return false;
889
0
    }
890
891
104k
    if (m_pcEncCfg->m_usePbIntraFast && (!cs.slice->isIntra() || cs.slice->sps->IBC) && cuECtx.interHad == 0 && cuECtx.bestCU && !CU::isIntra(*cuECtx.bestCU))
892
0
    {
893
0
      return false;
894
0
    }
895
896
    // INTRA MODES
897
104k
    if (cs.sps->IBC && !cuECtx.bestTU)
898
75.7k
    {
899
     // return true;
900
75.7k
    }
901
29.1k
    else
902
29.1k
    if( partitioner.isConsIntra() && !cuECtx.bestTU )
903
0
    {
904
      //return true;
905
0
    }
906
29.1k
    else
907
29.1k
    if ( lumaArea.width == 4 && lumaArea.height == 4 && !slice.isIntra() && !cuECtx.bestTU )
908
0
    {
909
      //return true;
910
0
    }
911
29.1k
    else
912
29.1k
    if (!(slice.isIRAP() || bestMode.type == ETM_INTRA || !cuECtx.bestTU ||
913
0
      ((!m_pcEncCfg->m_bDisableIntraCUsInInterSlices) && (!relatedCU.isInter || !relatedCU.isIBC) && (
914
0
                                    ( cuECtx.bestTU->cbf[0] != 0 ) ||
915
0
           ( ( numComp > COMP_Cb ) && cuECtx.bestTU->cbf[1] != 0 ) ||
916
0
           ( ( numComp > COMP_Cr ) && cuECtx.bestTU->cbf[2] != 0 )  // avoid very complex intra if it is unlikely
917
0
         ) ) ) )
918
0
    {
919
0
      return false;
920
0
    }
921
29.1k
    else
922
29.1k
    if( cuECtx.bestCS && cuECtx.bestCU && cuECtx.interHad )
923
29.1k
    {
924
      // Get SATD threshold from best Inter-CU
925
29.1k
      if( !cs.slice->isIRAP() && m_pcEncCfg->m_usePbIntraFast )
926
0
      {
927
0
        const DFunc dfunc = DF_HAD;
928
0
        DistParam distParam = m_pcRdCost->setDistParam( cs.getOrgBuf( COMP_Y ), cuECtx.bestCS->getPredBuf( COMP_Y ), cs.sps->bitDepths[ CH_L ], dfunc );
929
0
        cuECtx.interHad = distParam.distFunc( distParam );
930
0
      }
931
29.1k
    }
932
104k
    if ((m_pcEncCfg->m_IBCFastMethod > 1) && !cs.slice->isIntra()//IBC_FAST_METHOD_NOINTRA_IBCCBF0
933
0
      && (bestMode.type == ETM_IBC || bestMode.type == ETM_IBC_MERGE)
934
0
      && (!cuECtx.bestCU->Y().valid() || cuECtx.bestTU->cbf[0] == 0)
935
0
      && (!cuECtx.bestCU->Cb().valid() || cuECtx.bestTU->cbf[1] == 0)
936
0
      && (!cuECtx.bestCU->Cr().valid() || cuECtx.bestTU->cbf[2] == 0))
937
0
    {
938
0
      return false;
939
0
    }
940
104k
    if (m_pcEncCfg->m_FastIntraTools)
941
104k
    {
942
104k
      if (relatedCU.relatedCuIsValid)
943
16.9k
      {
944
16.9k
        cuECtx.relatedCuIsValid = relatedCU.relatedCuIsValid;
945
16.9k
      }
946
104k
      if (relatedCU.isIntra)
947
28.0k
      {
948
28.0k
        cuECtx.isIntra = relatedCU.isIntra;
949
28.0k
      }
950
104k
    }
951
104k
  }
952
64.8k
  else if( isModeInter( encTestmode ) )
953
0
  {
954
    // INTER MODES (ME + MERGE/SKIP)
955
0
    CHECK( slice.isIntra(), "Inter-mode should not be in the I-Slice mode list!" );
956
957
    // --- Check if we can quit current mode using SAVE/LOAD coding history
958
959
0
    if( encTestmode.type == ETM_INTER_ME )
960
0
    {
961
0
      if( encTestmode.opts == ETO_STANDARD )
962
0
      {
963
0
        if (m_pcEncCfg->m_FastInferMerge)
964
0
        {
965
0
          if (bestCS && (bestCS->slice->TLayer > (m_pcEncCfg->m_maxTLayer - (m_pcEncCfg->m_FastInferMerge & 7)))
966
0
            && (bestCS->bestParent != nullptr) && bestCS->bestParent->cus.size() && (bestCS->bestParent->cus[0]->skip))
967
0
          {
968
0
            return false;
969
0
          }
970
0
        }
971
0
        if( relatedCU.isSkip || relatedCU.isIntra )
972
0
        {
973
0
          return false;
974
0
        }
975
0
      }
976
0
    }
977
0
  }
978
64.8k
  else if (encTestmode.type == ETM_IBC || encTestmode.type == ETM_IBC_MERGE)
979
64.8k
  {
980
64.8k
    if ((m_pcEncCfg->m_IBCFastMethod > 1) && !(slice.isIRAP() || bestMode.type == ETM_INTRA || !cuECtx.bestTU ||
981
0
      ((!m_pcEncCfg->m_bDisableIntraCUsInInterSlices) && (!relatedCU.isInter || !relatedCU.isIBC) && (
982
0
        (cuECtx.bestTU->cbf[0] != 0) ||
983
0
        ((numComp > COMP_Cb) && cuECtx.bestTU->cbf[1] != 0) ||
984
0
        ((numComp > COMP_Cr) && cuECtx.bestTU->cbf[2] != 0)  // avoid very complex intra if it is unlikely
985
0
        ))))
986
0
    {
987
0
      return false;
988
0
    }
989
64.8k
    if ((m_pcEncCfg->m_IBCFastMethod > 3) &&(lumaArea.width == 4 && lumaArea.height == 4 && !slice.isIntra()))
990
0
    {
991
0
      return false;
992
0
    }
993
    // IBC MODES
994
64.8k
    return slice.sps->IBC && (partitioner.currArea().lumaSize().width < 128 && partitioner.currArea().lumaSize().height < 128);
995
64.8k
  }
996
0
  else
997
0
  {
998
0
    THROW("problem");
999
0
    return false;
1000
0
  }
1001
1002
104k
  STAT_COUNT_CU_MODES( partitioner.chType == CH_L, g_cuCounters1D[CU_MODES_TRIED][0][!cs.slice->isIntra() + cs.slice->depth] );
1003
104k
  STAT_COUNT_CU_MODES( partitioner.chType == CH_L && !cs.slice->isIntra(), g_cuCounters2D[CU_MODES_TRIED][Log2( cs.area.lheight() )][Log2( cs.area.lwidth() )] );
1004
104k
  return true;
1005
169k
}
1006
1007
1008
void EncModeCtrl::beforeSplit( Partitioner& partitioner )
1009
104k
{
1010
104k
  ComprCUCtx&           cuECtx  = m_ComprCUCtxList.back();
1011
1012
104k
  if( ! cuECtx.bestCS )
1013
0
    return;
1014
1015
104k
  CodedCUInfo    &relatedCU   = getBlkInfo( partitioner.currArea() );
1016
104k
  const CodingUnit&  bestCU   = *cuECtx.bestCU;
1017
1018
104k
  cuECtx.bestNsPredMode       = cuECtx.bestMode;
1019
104k
  cuECtx.bestCostBeforeSplit  = cuECtx.bestCS->cost;
1020
1021
104k
  setFromCs( *cuECtx.bestCS, cuECtx.bestMode, partitioner );
1022
1023
104k
  if( bestCU.skip )
1024
0
  {
1025
0
    cuECtx.doMoreSplits--;
1026
0
  }
1027
1028
104k
  if( partitioner.modeType == MODE_TYPE_INTRA && partitioner.chType == CH_L )
1029
0
  {
1030
0
    return; //not set best coding mode for intra coding pass
1031
0
  }
1032
1033
  // assume the non-split modes are done and set the marks for the best found mode
1034
104k
  if( CU::isInter( bestCU ) )
1035
0
  {
1036
0
    relatedCU.isInter     = true;
1037
0
    relatedCU.isSkip     |= bestCU.skip;
1038
0
    relatedCU.isMMVDSkip |= bestCU.mmvdSkip;
1039
0
    relatedCU.BcwIdx      = bestCU.BcwIdx;
1040
0
  }
1041
104k
  else if (CU::isIBC(bestCU))
1042
0
  {
1043
0
    relatedCU.isIBC = true;
1044
0
    relatedCU.isSkip |= bestCU.skip;
1045
0
  }
1046
104k
  else if( CU::isIntra( bestCU ) )
1047
104k
  {
1048
104k
    relatedCU.isIntra     = true;
1049
104k
    if (m_pcEncCfg->m_FastIntraTools)
1050
104k
    {
1051
104k
      if ( cuECtx.intraWasTested && (!relatedCU.relatedCuIsValid || cuECtx.bestCS->cost < relatedCU.bestCost))
1052
32.4k
      {
1053
32.4k
        relatedCU.bestCost = cuECtx.bestCS->cost;
1054
32.4k
        relatedCU.relatedCuIsValid = true;
1055
32.4k
      }
1056
104k
    }
1057
104k
  }
1058
104k
  cuECtx.isBestNoSplitSkip = bestCU.skip;
1059
104k
}
1060
1061
1062
bool EncModeCtrl::useModeResult( const EncTestMode& encTestmode, CodingStructure*& tempCS, Partitioner& partitioner, const bool useEDO )
1063
219k
{
1064
219k
  ComprCUCtx& cuECtx = m_ComprCUCtxList.back();
1065
1066
1067
219k
  if(      encTestmode.type == ETM_SPLIT_BT_H )
1068
30.6k
  {
1069
30.6k
    cuECtx.bestCostHorzSplit = tempCS->cost;
1070
30.6k
  }
1071
189k
  else if( encTestmode.type == ETM_SPLIT_BT_V )
1072
30.2k
  {
1073
30.2k
    cuECtx.bestCostVertSplit = tempCS->cost;
1074
30.2k
  }
1075
158k
  else if( !isModeSplit( encTestmode ) && isModeInter( encTestmode ) && tempCS->cus.size() == 1 )
1076
0
  {
1077
0
    cuECtx.nonSkipWasTested |= !tempCS->cus.front()->skip;
1078
0
  }
1079
219k
  if (m_pcEncCfg->m_AMVRspeed && encTestmode.type == ETM_INTER_ME)
1080
0
  {
1081
0
    int imvMode = (encTestmode.opts & ETO_IMV) >> ETO_IMV_SHIFT;
1082
1083
0
    if (imvMode == 0)
1084
0
    {
1085
0
      if (tempCS->cost < cuECtx.bestCostNoImv )
1086
0
      {
1087
0
        cuECtx.bestCostNoImv = tempCS->cost;
1088
0
      }
1089
0
    }
1090
0
  }
1091
1092
219k
  if( encTestmode.type == ETM_SPLIT_QT )
1093
24.2k
  {
1094
24.2k
    int maxQtD = 0;
1095
24.2k
    for( const auto& cu : tempCS->cus )
1096
96.1k
    {
1097
96.1k
      maxQtD = std::max<int>( maxQtD, cu->qtDepth );
1098
96.1k
    }
1099
24.2k
    cuECtx.maxQtSubDepth = maxQtD;
1100
24.2k
  }
1101
1102
219k
  int maxMtD = tempCS->pcv->getMaxMTTDepth( *tempCS->slice, partitioner.chType ) + partitioner.currImplicitBtDepth;
1103
1104
219k
  if( encTestmode.type == ETM_SPLIT_BT_H )
1105
30.6k
  {
1106
30.6k
    if( tempCS->cus.size() > 2 )
1107
1.15k
    {
1108
1.15k
      int h_2   = tempCS->area.blocks[partitioner.chType].height / 2;
1109
1.15k
      int cu1_h = tempCS->cus.front()->blocks[partitioner.chType].height;
1110
1.15k
      int cu2_h = tempCS->cus.back() ->blocks[partitioner.chType].height;
1111
1112
1.15k
      cuECtx.doTriHorzSplit = cu1_h < h_2 || cu2_h < h_2 || partitioner.currMtDepth + 1 == maxMtD;
1113
1.15k
    }
1114
30.6k
  }
1115
189k
  else if( encTestmode.type == ETM_SPLIT_BT_V )
1116
30.2k
  {
1117
30.2k
    if( tempCS->cus.size() > 2 )
1118
1.32k
    {
1119
1.32k
      int w_2   = tempCS->area.blocks[partitioner.chType].width / 2;
1120
1.32k
      int cu1_w = tempCS->cus.front()->blocks[partitioner.chType].width;
1121
1.32k
      int cu2_w = tempCS->cus.back() ->blocks[partitioner.chType].width;
1122
1123
1.32k
      cuECtx.doTriVertSplit = cu1_w < w_2 || cu2_w < w_2 || partitioner.currMtDepth + 1 == maxMtD;
1124
1.32k
    }
1125
30.2k
  }
1126
1127
219k
  if( encTestmode.type == ETM_SPLIT_BT_V || encTestmode.type == ETM_SPLIT_BT_H || encTestmode.type == ETM_SPLIT_QT )
1128
85.1k
  {
1129
85.1k
    bool isAllSkip = true;
1130
1131
85.1k
    for( const auto& cu : tempCS->cus )
1132
191k
    {
1133
191k
      isAllSkip &= cu->skip;
1134
191k
    }
1135
1136
85.1k
    if( isAllSkip ) cuECtx.doMoreSplits--;
1137
85.1k
    if( isAllSkip && encTestmode.type == ETM_SPLIT_QT )
1138
0
                    cuECtx.doMoreSplits--;
1139
85.1k
  }
1140
1141
  // for now just a simple decision based on RD-cost or choose tempCS if bestCS is not yet coded
1142
219k
  if( tempCS->cost != MAX_DOUBLE && ( !cuECtx.bestCS || ( ( tempCS->cost + ( useEDO ? tempCS->costDbOffset : 0 ) ) < ( cuECtx.bestCS->cost + ( useEDO ? cuECtx.bestCS->costDbOffset : 0 ) ) ) ) )
1143
198k
  {
1144
198k
    cuECtx.bestCS   = tempCS;
1145
198k
    cuECtx.bestCU   = tempCS->cus[0];
1146
198k
    cuECtx.bestTU   = cuECtx.bestCU->firstTU;
1147
198k
    cuECtx.bestMode = encTestmode;
1148
1149
198k
    return true;
1150
198k
  }
1151
20.8k
  else
1152
20.8k
  {
1153
20.8k
    return false;
1154
20.8k
  }
1155
219k
}
1156
1157
} // namespace vvenc
1158
1159
//! \}
1160