Coverage Report

Created: 2026-05-30 06:10

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
20.7k
{
66
20.7k
  const unsigned numPos = MAX_CU_SIZE >> MIN_CU_LOG2;
67
20.7k
  const int maxSizeIdx  = MAX_CU_SIZE_IDX - MIN_CU_LOG2;
68
69
  //static constexpr size_t numCu = 7921;
70
71
20.7k
  size_t numCu = 0;
72
  
73
145k
  for( int wIdx = 0; wIdx < maxSizeIdx; wIdx++ )
74
124k
  {
75
872k
    for( int hIdx = 0; hIdx < maxSizeIdx; hIdx++ )
76
747k
    {
77
24.6M
      for( unsigned y = 0; y < numPos; y++ )
78
23.9M
      {
79
789M
        for( unsigned x = 0; x < numPos; x++ )
80
765M
        {
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
765M
          if( (x + (1 << (wIdx)) <= (ctuSize >> MIN_CU_LOG2))
87
538M
              && (y + (1 << (hIdx)) <= (ctuSize >> MIN_CU_LOG2))
88
378M
              && (((x << MIN_CU_LOG2) & ((1 << (wIdx + MIN_CU_LOG2 - 1)) - 1)) == 0)
89
249M
              && (((y << MIN_CU_LOG2) & ((1 << (hIdx + MIN_CU_LOG2 - 1)) - 1)) == 0) )
90
164M
          {
91
164M
            numCu++;
92
164M
          }
93
765M
        }
94
23.9M
      }
95
747k
    }
96
124k
  }
97
98
20.7k
  m_codedCUInfoBuf = new CodedCUInfo[numCu];
99
20.7k
  CodedCUInfo* cuInfo = m_codedCUInfoBuf;
100
101
145k
  for( int wIdx = 0; wIdx < maxSizeIdx; wIdx++ )
102
124k
  {
103
872k
    for( int hIdx = 0; hIdx < maxSizeIdx; hIdx++ )
104
747k
    {
105
24.6M
      for( unsigned y = 0; y < numPos; y++ )
106
23.9M
      {
107
789M
        for( unsigned x = 0; x < numPos; x++ )
108
765M
        {
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
765M
          if(( x + (1<<(wIdx)) <= ( ctuSize >> MIN_CU_LOG2 ) )
115
538M
            && ( y + (1<<(hIdx)) <= ( ctuSize >> MIN_CU_LOG2 ) )
116
378M
            && ( ( ( x << MIN_CU_LOG2 ) & ((1 << (wIdx + MIN_CU_LOG2 - 1)) - 1) ) == 0 )
117
249M
            && ( ( ( y << MIN_CU_LOG2 ) & ((1 << (hIdx + MIN_CU_LOG2 - 1)) - 1) ) == 0 ) )
118
164M
          {
119
164M
            m_codedCUInfo[wIdx][hIdx][x][y] = cuInfo++;
120
164M
            m_codedCUInfo[wIdx][hIdx][x][y]->poc       = -1;
121
164M
            m_codedCUInfo[wIdx][hIdx][x][y]->ctuRsAddr = -1;
122
164M
          }
123
601M
          else
124
601M
          {
125
601M
            m_codedCUInfo[wIdx][hIdx][x][y] = nullptr;
126
601M
          }
127
765M
        }
128
23.9M
      }
129
747k
    }
130
124k
  }
131
20.7k
}
132
133
void CacheBlkInfoCtrl::destroy()
134
20.7k
{
135
20.7k
  delete[] m_codedCUInfoBuf;
136
20.7k
  m_codedCUInfoBuf = nullptr;
137
20.7k
}
138
139
void CacheBlkInfoCtrl::init( const Slice &slice )
140
4.05k
{
141
4.05k
  m_pcv = slice.pps->pcv;
142
4.05k
}
143
144
void CacheBlkInfoCtrl::initBlk( const UnitArea& area, int poc )
145
139k
{
146
139k
  unsigned idx1, idx2, idx3, idx4;
147
139k
  getAreaIdxNew( area.Y(), *m_pcv, idx1, idx2, idx3, idx4 );
148
149
139k
  const int ctuRsAddr = getCtuAddr( area.lumaPos(), *m_pcv );
150
139k
  CodedCUInfo* cuInfo = m_codedCUInfo[idx1][idx2][idx3][idx4];
151
152
139k
  if( cuInfo->poc != poc || cuInfo->ctuRsAddr != ctuRsAddr )
153
100k
  {
154
100k
    GCC_WARNING_DISABLE_class_memaccess
155
100k
    memset( cuInfo, 0, sizeof( CodedCUInfo ) );
156
100k
    GCC_WARNING_RESET
157
158
100k
    cuInfo->poc       = poc;
159
100k
    cuInfo->ctuRsAddr = ctuRsAddr;
160
100k
  }
161
139k
}
162
163
CodedCUInfo& CacheBlkInfoCtrl::getBlkInfo( const UnitArea& area )
164
230k
{
165
230k
  unsigned idx1, idx2, idx3, idx4;
166
230k
  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
230k
  return *m_codedCUInfo[idx1][idx2][idx3][idx4];
169
230k
}
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
20.7k
{
261
20.7k
  m_reuseCuResults = reuseCuResults;
262
263
20.7k
  if( !m_reuseCuResults ) return;
264
265
0
  const unsigned numPos = MAX_CU_SIZE >> MIN_CU_LOG2;
266
0
  const int maxSizeIdx  = MAX_CU_SIZE_IDX - MIN_CU_LOG2;
267
268
0
  static constexpr size_t yuvNom[4] = { 1, 3, 2, 3 };
269
0
  static constexpr size_t yuvDen[4] = { 0, 1, 0, 0 };
270
271
  // only true for 128x128 CTU
272
  //static constexpr size_t numCu = 7921;
273
  //static constexpr size_t numDmvrMv = 5439;
274
  //const size_t numCoeff = ( 1345600 * yuvNom[chFmt] ) >> yuvDen[chFmt];
275
276
0
  size_t numCu = 0;
277
0
  size_t numDmvrMv = 0;
278
0
  size_t numCoeff = 0;
279
  
280
0
  for( int wIdx = 0; wIdx < maxSizeIdx; wIdx++ )
281
0
  {
282
0
    for( int hIdx = 0; hIdx < maxSizeIdx; hIdx++ )
283
0
    {
284
0
      int dmvrSize = 0;
285
0
      if( hIdx >= 1 && wIdx >= 1 && (wIdx + hIdx) >= 3 )
286
0
      {
287
0
        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) ));
288
0
      }
289
  
290
0
      const UnitArea area( chFmt, Area( 0, 0, 1 << (wIdx + 2), 1 << (hIdx + 2) ) );
291
  
292
0
      for( unsigned x = 0; x < numPos; x++ )
293
0
      {
294
0
        for( unsigned y = 0; y < numPos; y++ )
295
0
        {
296
          // a block of width W might be offset of N * W + 1/2 W (bcs of TT), same for H
297
          // W = 1 << ( wIdx + 2 )
298
          // 1/2 W = 1 << ( wIdx + 1 )
299
          // remainder of (N+1/2)*W -> x & ( ( 1 << ( wIdx + 1 ) ) - 1 )
300
  
301
0
          if( (x + (1 << (wIdx)) <= (ctuSize >> MIN_CU_LOG2))
302
0
            && (y + (1 << (hIdx)) <= (ctuSize >> MIN_CU_LOG2))
303
0
            && (((x << MIN_CU_LOG2) & ((1 << (wIdx + MIN_CU_LOG2 - 1)) - 1)) == 0)
304
0
            && (((y << MIN_CU_LOG2) & ((1 << (hIdx + MIN_CU_LOG2 - 1)) - 1)) == 0) )
305
0
          {
306
0
            numCu++;
307
  
308
0
            numCoeff += area.Y().area();
309
  
310
  
311
            //numCu++;
312
0
            numDmvrMv += dmvrSize;
313
0
          }
314
0
        }
315
0
      }
316
0
    }
317
0
  }
318
  
319
  //std::cout << numCu << " " << numDmvrMv << " " << numCoeff << std::endl;
320
  
321
0
  numCoeff  *= yuvNom[chFmt];
322
0
  numCoeff >>= yuvDen[chFmt];
323
324
0
  m_encInfoBuf = new BestEncodingInfo[numCu];
325
0
  BestEncodingInfo* encInfo = m_encInfoBuf;
326
327
0
  m_dmvrMvBuf = new Mv[numDmvrMv];
328
0
  Mv* dmvrMv = m_dmvrMvBuf;
329
330
0
  m_pCoeff = new TCoeffSig[numCoeff];
331
0
  TCoeffSig* coeffPtr = m_pCoeff;
332
333
0
  for( int wIdx = 0; wIdx < maxSizeIdx; wIdx++ )
334
0
  {
335
0
    for( int hIdx = 0; hIdx < maxSizeIdx; hIdx++ )
336
0
    {
337
0
      int dmvrSize = 0;
338
0
      if( hIdx >= 1 && wIdx >= 1 && (wIdx + hIdx) >= 3 )
339
0
      {
340
0
        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) ));
341
0
      }
342
343
0
      const UnitArea area( chFmt, Area( 0, 0, 1 << (wIdx + 2), 1 << (hIdx + 2) ) );
344
345
0
      for( unsigned x = 0; x < numPos; x++ )
346
0
      {
347
0
        for( unsigned y = 0; y < numPos; y++ )
348
0
        {
349
          // a block of width W might be offset of N * W + 1/2 W (bcs of TT), same for H
350
          // W = 1 << ( wIdx + 2 )
351
          // 1/2 W = 1 << ( wIdx + 1 )
352
          // remainder of (N+1/2)*W -> x & ( ( 1 << ( wIdx + 1 ) ) - 1 )
353
354
0
          if(( x + (1<<(wIdx)) <= ( ctuSize >> MIN_CU_LOG2 ) )
355
0
            && ( y + (1<<(hIdx)) <= ( ctuSize >> MIN_CU_LOG2 ) )
356
0
            && ( ( ( x << MIN_CU_LOG2 )  & ((1 << (wIdx + MIN_CU_LOG2 - 1)) - 1) ) == 0 )
357
0
            && ( ( ( y << MIN_CU_LOG2 )  & ((1 << (hIdx + MIN_CU_LOG2 - 1)) - 1) ) == 0 ) )
358
0
          {
359
0
            m_bestEncInfo[wIdx][hIdx][x][y] = encInfo++;
360
361
0
            m_bestEncInfo[wIdx][hIdx][x][y]->cu.UnitArea::operator=( area );
362
0
            m_bestEncInfo[wIdx][hIdx][x][y]->tu.UnitArea::operator=( area );
363
364
0
            m_bestEncInfo[wIdx][hIdx][x][y]->cu.chType = CH_L;
365
0
            m_bestEncInfo[wIdx][hIdx][x][y]->cu.treeType = TREE_D;
366
0
            m_bestEncInfo[wIdx][hIdx][x][y]->cu.modeType = MODE_TYPE_ALL;
367
0
            m_bestEncInfo[wIdx][hIdx][x][y]->cu.qp = MAX_SCHAR;
368
0
            m_bestEncInfo[wIdx][hIdx][x][y]->tu.chType = CH_L;
369
370
0
            if( dmvrSize )
371
0
            {
372
0
              m_bestEncInfo[wIdx][hIdx][x][y]->cu.mvdL0SubPu = dmvrMv; 
373
0
              dmvrMv += dmvrSize;
374
0
            }
375
376
0
            TCoeffSig* coeff[MAX_NUM_TBLOCKS] = { 0, };
377
378
0
            const UnitArea& area = m_bestEncInfo[wIdx][hIdx][x][y]->tu;
379
380
0
            for( int i = 0; i < area.blocks.size(); i++ )
381
0
            {
382
0
              coeff[i] = coeffPtr; coeffPtr += area.blocks[i].area();
383
0
            }
384
385
0
            m_bestEncInfo[wIdx][hIdx][x][y]->tu.cs = &m_dummyCS;
386
0
            m_bestEncInfo[wIdx][hIdx][x][y]->tu.init( coeff );
387
388
0
            m_bestEncInfo[wIdx][hIdx][x][y]->poc      = -1;
389
0
            m_bestEncInfo[wIdx][hIdx][x][y]->testMode = EncTestMode();
390
0
          }
391
0
          else
392
0
          {
393
0
            m_bestEncInfo[wIdx][hIdx][x][y] = nullptr;
394
0
          }
395
0
        }
396
0
      }
397
0
    }
398
0
  }
399
0
}
400
401
void BestEncInfoCache::destroy()
402
20.7k
{
403
20.7k
  if( !m_reuseCuResults ) return;
404
405
0
  delete[] m_encInfoBuf;
406
0
  m_encInfoBuf = nullptr;
407
408
0
  delete[] m_pCoeff;
409
0
  m_pCoeff = nullptr;
410
411
0
  delete[] m_dmvrMvBuf;
412
0
  m_dmvrMvBuf = nullptr;
413
414
0
  m_pcv = nullptr;
415
0
}
416
417
void BestEncInfoCache::init( const Slice &slice )
418
4.05k
{
419
4.05k
  if( !m_reuseCuResults ) return;
420
421
0
  bool isInitialized = m_pcv;
422
423
0
  m_pcv = slice.pps->pcv;
424
425
0
  if( isInitialized ) return;
426
427
0
  m_dummyCS.pcv = m_pcv;
428
0
}
429
430
bool BestEncInfoCache::setFromCs( const CodingStructure& cs, const EncTestMode& testMode, const Partitioner& partitioner )
431
88.1k
{
432
88.1k
  if( !m_reuseCuResults ) return false;
433
434
0
  if( cs.cus.size() != 1 || cs.tus.size() != 1 || partitioner.maxBTD <= 1 )
435
0
  {
436
0
    return false;
437
0
  }
438
439
0
  unsigned idx1, idx2, idx3, idx4;
440
0
  getAreaIdxNew( cs.area.Y(), *m_pcv, idx1, idx2, idx3, idx4 );
441
442
0
  BestEncodingInfo& encInfo = *m_bestEncInfo[idx1][idx2][idx3][idx4];
443
444
0
  encInfo.poc            =  cs.picture->poc;
445
0
  encInfo.cu.UnitArea::operator= ( *cs.cus.front() );
446
0
  encInfo.tu.UnitArea::operator= ( *cs.tus.front() );
447
0
  encInfo.cu             = *cs.cus.front();
448
0
  for( auto &blk : cs.tus.front()->blocks )
449
0
  {
450
0
    if( blk.valid() ) encInfo.tu.copyComponentFrom( *cs.tus.front(), blk.compID );
451
0
  }
452
0
  encInfo.testMode       = testMode;
453
0
  encInfo.dist           = cs.dist;
454
0
  encInfo.costEDO        = cs.costDbOffset;
455
456
0
  return true;
457
0
}
458
459
bool BestEncInfoCache::isReusingCuValid( const CodingStructure& cs, const Partitioner& partitioner, int qp )
460
227k
{
461
227k
  if( !m_reuseCuResults || partitioner.treeType == TREE_C || partitioner.maxBTD <= 1 )
462
227k
  {
463
227k
    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
464
227k
  }
465
466
0
  unsigned idx1, idx2, idx3, idx4;
467
0
  getAreaIdxNew( cs.area.Y(), *m_pcv, idx1, idx2, idx3, idx4 );
468
469
0
  BestEncodingInfo& encInfo = *m_bestEncInfo[idx1][idx2][idx3][idx4];
470
471
0
  if( encInfo.cu.treeType != partitioner.treeType || encInfo.cu.modeType != partitioner.modeType )
472
0
  {
473
0
    return false;
474
0
  }
475
0
  if( encInfo.cu.qp != qp )
476
0
    return false;
477
0
  if( cs.picture->poc != encInfo.poc 
478
0
    || CS::getArea( cs, cs.area, partitioner.chType, partitioner.treeType ) != CS::getArea( cs, encInfo.cu, partitioner.chType, partitioner.treeType ) 
479
0
    || !isTheSameNbHood( encInfo.cu, cs, partitioner, (cs.picture->Y().width), (cs.picture->Y().height))
480
0
    || CU::isIBC(encInfo.cu)
481
0
    || partitioner.currQgEnable() || cs.currQP[partitioner.chType] != encInfo.cu.qp
482
0
    )
483
0
  {
484
0
    return false;
485
0
  }
486
0
  else
487
0
  {
488
0
    return true;
489
0
  }
490
0
}
491
492
bool BestEncInfoCache::setCsFrom( CodingStructure& cs, EncTestMode& testMode, const Partitioner& partitioner ) const
493
0
{
494
0
  if( !m_reuseCuResults ) return false;
495
496
0
  unsigned idx1, idx2, idx3, idx4;
497
0
  getAreaIdxNew( cs.area.Y(), *m_pcv, idx1, idx2, idx3, idx4 );
498
499
0
  BestEncodingInfo& encInfo = *m_bestEncInfo[idx1][idx2][idx3][idx4];
500
501
0
  if( cs.picture->poc != encInfo.poc 
502
0
    || CS::getArea( cs, cs.area, partitioner.chType, partitioner.treeType ) != CS::getArea( cs, encInfo.cu, partitioner.chType, partitioner.treeType ) 
503
0
    || !isTheSameNbHood( encInfo.cu, cs, partitioner, (cs.picture->Y().width), (cs.picture->Y().height))
504
0
    || partitioner.currQgEnable() || cs.currQP[partitioner.chType] != encInfo.cu.qp
505
0
    )
506
0
  {
507
0
    return false;
508
0
  }
509
510
0
  const UnitArea ua = CS::getArea( cs, cs.area, partitioner.chType, partitioner.treeType );
511
0
  CodingUnit     &cu = cs.addCU( ua, partitioner.chType );
512
0
  cu.treeType = partitioner.treeType;
513
0
  cu.modeType = partitioner.modeType;
514
0
  cu.initPuData();
515
0
  TransformUnit  &tu = cs.addTU( ua, partitioner.chType, &cu );
516
517
0
  cu          .repositionTo( encInfo.cu );
518
0
  cu          .repositionTo( encInfo.cu );
519
0
  tu          .repositionTo( encInfo.tu );
520
521
0
  cu          = encInfo.cu;
522
0
  cu          = encInfo.cu;
523
0
  for( auto &blk : tu.blocks )
524
0
  {
525
0
    if( blk.valid() ) tu.copyComponentFrom( encInfo.tu, blk.compID );
526
0
  }
527
528
0
  testMode    = encInfo.testMode;
529
0
  cs.dist     = encInfo.dist;
530
0
  cs.costDbOffset = encInfo.costEDO;
531
0
  return true;
532
0
}
533
534
535
//////////////////////////////////////////////////////////////////////////
536
// EncModeCtrl
537
//////////////////////////////////////////////////////////////////////////
538
void EncModeCtrl::init( const VVEncCfg& encCfg, RdCost* pRdCost )
539
20.7k
{
540
20.7k
  m_pcEncCfg = &encCfg;
541
20.7k
  m_pcRdCost = pRdCost;
542
20.7k
  comprCUCtx = nullptr;
543
544
20.7k
  CacheBlkInfoCtrl::create( encCfg.m_CTUSize );
545
20.7k
  BestEncInfoCache::create( encCfg.m_reuseCuResults, encCfg.m_internChromaFormat, encCfg.m_CTUSize );
546
20.7k
}
547
548
void EncModeCtrl::destroy()
549
20.7k
{
550
20.7k
  CacheBlkInfoCtrl::destroy();
551
20.7k
  BestEncInfoCache::destroy();
552
20.7k
}
553
554
void EncModeCtrl::initCTUEncoding( const Slice &slice, int tileIdx )
555
4.05k
{
556
4.05k
  CacheBlkInfoCtrl::init( slice );
557
4.05k
  BestEncInfoCache::init( slice );
558
559
4.05k
  CHECK( !m_ComprCUCtxList.empty(), "Mode list is not empty at the beginning of a CTU" );
560
561
4.05k
  if( m_pcEncCfg->m_fastQtBtEnc )
562
4.05k
  {
563
4.05k
    m_skipThresholdE0023FastEnc = ((slice.getMinPictureDistance() <= PICTURE_DISTANCE_TH) ? FAST_SKIP_DEPTH : SKIP_DEPTH);
564
4.05k
  }
565
0
  else
566
0
  {
567
0
    m_skipThresholdE0023FastEnc = SKIP_DEPTH;
568
0
  }
569
570
4.05k
  m_tileIdx = tileIdx;
571
4.05k
}
572
573
void EncModeCtrl::initCULevel( Partitioner &partitioner, const CodingStructure& cs, int  MergeSimpleFlag)
574
139k
{
575
  // Min/max depth
576
139k
  unsigned minDepth = 0;
577
139k
  unsigned maxDepth = cs.pcv->getMaxDepth( cs.slice->sliceType, partitioner.chType );
578
139k
  if( m_pcEncCfg->m_useFastLCTU )
579
139k
  {
580
139k
    partitioner.setMaxMinDepth(minDepth, maxDepth, cs, cs.picture->useQtbttSpeedUpMode, MergeSimpleFlag);
581
139k
  }
582
583
139k
  minDepth = std::max<unsigned>( minDepth, cs.pcv->getMinDepth( cs.slice->sliceType, partitioner.chType ) );
584
139k
  maxDepth = std::min<unsigned>( maxDepth, cs.pcv->getMaxDepth( cs.slice->sliceType, partitioner.chType ) );
585
586
139k
  m_ComprCUCtxList.push_back( ComprCUCtx( cs, minDepth, maxDepth ) );
587
139k
  comprCUCtx = &m_ComprCUCtxList.back();
588
589
139k
  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 );
590
139k
  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 );
591
592
139k
  const bool qtBeforeBt = ( (  cuLeft  &&  cuAbove  && cuLeft ->qtDepth > partitioner.currQtDepth && cuAbove->qtDepth > partitioner.currQtDepth )
593
137k
                         || (  cuLeft  && !cuAbove  && cuLeft ->qtDepth > partitioner.currQtDepth )
594
134k
                         || ( !cuLeft  &&  cuAbove  && cuAbove->qtDepth > partitioner.currQtDepth )
595
131k
                         || ( !cuAbove && !cuLeft   && cs.area.lwidth() >= ( 32 << cs.slice->TLayer ) )
596
117k
                         || ( m_pcEncCfg->m_qtbttSpeedUp > 1 && partitioner.maxBTD < ( ( cs.slice->isIntra() && !cs.sps->IBC ) ? 3 : 2 ) ) )
597
22.2k
                         && ( cs.area.lwidth() > ( cs.pcv->getMinQtSize( *cs.slice, partitioner.chType ) << 1 ) );
598
599
  // set features
600
139k
  ComprCUCtx &cuECtx    = *comprCUCtx;
601
139k
  cuECtx.qtBeforeBt     = qtBeforeBt;
602
139k
  cuECtx.doTriHorzSplit = true;
603
139k
  cuECtx.doTriVertSplit = true;
604
139k
  cuECtx.doMoreSplits   = 3;
605
139k
  cuECtx.isReusingCu    = isReusingCuValid( cs, partitioner, cs.baseQP );
606
139k
  cuECtx.didHorzSplit   = partitioner.canSplit( CU_HORZ_SPLIT, cs );
607
139k
  cuECtx.didVertSplit   = partitioner.canSplit( CU_VERT_SPLIT, cs );
608
139k
  cuECtx.doHorChromaSplit = true;
609
139k
  cuECtx.doVerChromaSplit = true;
610
139k
  cuECtx.doQtChromaSplit  = true;
611
612
139k
  if( m_pcEncCfg->m_contentBasedFastQtbt && cs.pcv->getMaxMTTDepth(*cs.slice, partitioner.chType))
613
139k
  {
614
139k
    const CompArea& currArea = partitioner.currArea().Y();
615
139k
    int cuHeight  = currArea.height;
616
139k
    int cuWidth   = currArea.width;
617
618
139k
    const bool condIntraInter = m_pcEncCfg->m_IntraPeriod == 1 ? ( partitioner.currBtDepth == 0 ) : ( cuHeight > 32 && cuWidth > 32 );
619
620
139k
    if( cuWidth == cuHeight && condIntraInter )
621
30.1k
    {
622
30.1k
      const CPelBuf bufCurrArea = cs.getOrgBuf( partitioner.currArea().block( COMP_Y ) );
623
624
30.1k
      Intermediate_Int horVal = 0;
625
30.1k
      Intermediate_Int verVal = 0;
626
30.1k
      Intermediate_Int dupVal = 0;
627
30.1k
      Intermediate_Int dowVal = 0;
628
629
30.1k
      unsigned j, k;
630
631
2.42M
      for( k = 0; k < cuHeight - 1; k++ )
632
2.39M
      {
633
218M
        for( j = 0; j < cuWidth - 1; j++ )
634
215M
        {
635
215M
          horVal += abs( bufCurrArea.at( j + 1, k     ) - bufCurrArea.at( j, k ) );
636
215M
          verVal += abs( bufCurrArea.at( j    , k + 1 ) - bufCurrArea.at( j, k ) );
637
215M
          dowVal += abs( bufCurrArea.at( j + 1, k )     - bufCurrArea.at( j, k + 1 ) );
638
215M
          dupVal += abs( bufCurrArea.at( j + 1, k + 1 ) - bufCurrArea.at( j, k ) );
639
215M
        }
640
2.39M
      }
641
642
30.1k
      cuECtx.grad_horVal = (double)horVal;
643
30.1k
      cuECtx.grad_verVal = (double)verVal;
644
30.1k
      cuECtx.grad_dowVal = (double)dowVal;
645
30.1k
      cuECtx.grad_dupVal = (double)dupVal;
646
30.1k
    }
647
139k
  }
648
139k
}
649
650
void EncModeCtrl::finishCULevel( Partitioner &partitioner )
651
139k
{
652
139k
  m_ComprCUCtxList.pop_back();
653
139k
  comprCUCtx = m_ComprCUCtxList.size() ? &m_ComprCUCtxList.back() : nullptr;
654
139k
}
655
656
bool EncModeCtrl::trySplit( const EncTestMode& encTestmode, const CodingStructure &cs, Partitioner& partitioner, const EncTestMode& lastTestmode )
657
339k
{
658
339k
  ComprCUCtx& cuECtx = *comprCUCtx;
659
660
339k
  const PartSplit implicitSplit = partitioner.getImplicitSplit( cs );
661
339k
  const bool isBoundary         = implicitSplit != CU_DONT_SPLIT;
662
663
339k
  if( ( m_pcEncCfg->m_IntraPeriod == 1 ) && ( partitioner.chType == CH_C ) && ( !cuECtx.doQtChromaSplit ) )
664
0
  {
665
0
    cuECtx.maxDepth         = partitioner.currDepth;
666
0
  }
667
668
339k
  if( isBoundary )
669
84.7k
  {
670
84.7k
    if( encTestmode.type != ETM_SPLIT_QT )
671
33.5k
    {
672
33.5k
      return getPartSplit( encTestmode ) == implicitSplit;
673
33.5k
    }
674
51.1k
    else
675
51.1k
    {
676
51.1k
      return partitioner.canSplit( CU_QUAD_SPLIT, cs );
677
51.1k
    }
678
84.7k
  }
679
680
254k
  const Slice&           slice       = *cs.slice;
681
254k
  const uint32_t         width       = partitioner.currArea().lumaSize().width;
682
254k
  const CodingStructure *bestCS      = cuECtx.bestCS;
683
254k
  const CodingUnit      *bestCU      = cuECtx.bestCU;
684
685
254k
  if( cuECtx.minDepth > partitioner.currQtDepth && partitioner.canSplit( CU_QUAD_SPLIT, cs ) )
686
0
  {
687
    // enforce QT
688
0
    return encTestmode.type == ETM_SPLIT_QT;
689
0
  }
690
254k
  else if( encTestmode.type == ETM_SPLIT_QT && cuECtx.maxDepth <= partitioner.currQtDepth )
691
1.34k
  {
692
    // don't check this QT depth
693
1.34k
    return false;
694
1.34k
  }
695
696
253k
  CHECK( ! isModeSplit( encTestmode ), "wrong method" );
697
698
  //////////////////////////////////////////////////////////////////////////
699
  // skip-history rule - don't split further if at least for three past levels
700
  //                     in the split tree it was found that skip is the best mode
701
  //////////////////////////////////////////////////////////////////////////
702
253k
  int skipScore = 0;
703
704
253k
  if ((!slice.isIntra() || slice.sps->IBC) && cuECtx.isBestNoSplitSkip )
705
0
  {
706
0
    for( int i = 2; i <= m_ComprCUCtxList.size(); i++ )
707
0
    {
708
0
      if( ( m_ComprCUCtxList.end() - i )->isBestNoSplitSkip )
709
0
      {
710
0
        skipScore += 1;
711
0
      }
712
0
      else
713
0
      {
714
0
        break;
715
0
      }
716
0
    }
717
0
  }
718
719
253k
  const PartSplit split = getPartSplit( encTestmode );
720
253k
  if( !partitioner.canSplit( split, cs ) || skipScore >= 2 || ( skipScore == 1 && m_ComprCUCtxList.size() == 2 ) )
721
64.3k
  {
722
64.3k
    if( split == CU_HORZ_SPLIT ) cuECtx.didHorzSplit = false;
723
64.3k
    if( split == CU_VERT_SPLIT ) cuECtx.didVertSplit = false;
724
64.3k
    if( split == CU_QUAD_SPLIT ) cuECtx.didQuadSplit = false;
725
64.3k
    return false;
726
64.3k
  }
727
728
188k
  if( isChroma( partitioner.chType ) && !cuECtx.doHorChromaSplit && ( split == CU_HORZ_SPLIT || split == CU_TRIH_SPLIT ) )
729
0
  {
730
0
    if( split == CU_HORZ_SPLIT )
731
0
    {
732
0
      cuECtx.didHorzSplit = false;
733
0
    }
734
735
0
    return false;
736
0
  }
737
738
188k
  if( isChroma( partitioner.chType ) && !cuECtx.doVerChromaSplit && ( split == CU_VERT_SPLIT || split == CU_TRIV_SPLIT ) )
739
0
  {
740
0
    if( split == CU_VERT_SPLIT )
741
0
    {
742
0
      cuECtx.didVertSplit = false;
743
0
    }
744
745
0
    return false;
746
0
  }
747
748
188k
  if( m_pcEncCfg->m_contentBasedFastQtbt )
749
188k
  {
750
188k
    const CompArea& currArea = partitioner.currArea().Y();
751
188k
    int cuHeight  = currArea.height;
752
188k
    int cuWidth   = currArea.width;
753
754
188k
    const bool condIntraInter = m_pcEncCfg->m_IntraPeriod == 1 ? ( partitioner.currBtDepth == 0 ) : ( cuHeight > 32 && cuWidth > 32 );
755
756
188k
    if( cuWidth == cuHeight && condIntraInter && split != CU_QUAD_SPLIT )
757
10.5k
    {
758
10.5k
      const double th1 = m_pcEncCfg->m_IntraPeriod == 1 ?  1.2              :  1.0;
759
10.5k
      const double th2 = m_pcEncCfg->m_IntraPeriod == 1 ? (1.2 / sqrt( 2 )) : (1.0 / sqrt( 2 ));
760
761
10.5k
      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 ) )
762
0
      {
763
0
        return false;
764
0
      }
765
10.5k
      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 ) )
766
0
      {
767
0
        return false;
768
0
      }
769
10.5k
    }
770
771
188k
    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 ) )
772
0
    {
773
0
      if( !bestCU->rootCbf )
774
0
      {
775
0
        return false;
776
0
      }
777
0
    }
778
188k
  }
779
780
188k
  if( m_pcEncCfg->m_qtbttSpeedUp > 1 )
781
188k
  {
782
188k
    const int availDepth = cs.pcv->getMaxMTTDepth( slice, partitioner.chType ) - partitioner.currMtDepth;
783
188k
    if( bestCU && bestCU->skip && availDepth <= ( 3 - m_skipThresholdE0023FastEnc ) && !isModeSplit( lastTestmode ) && split != CU_QUAD_SPLIT )
784
0
    {
785
0
      return false;
786
0
    }
787
188k
  }
788
188k
  if( bestCU && bestCU->skip && bestCU->mtDepth >= m_skipThresholdE0023FastEnc && !isModeSplit( lastTestmode ) )
789
0
  {
790
0
    return false;
791
0
  }
792
793
188k
  bool resetFeature = false;
794
795
188k
  switch( split )
796
188k
  {
797
22.4k
    case CU_QUAD_SPLIT:
798
22.4k
      {
799
22.4k
        if( !cuECtx.qtBeforeBt && bestCU )
800
19.9k
        {
801
19.9k
          unsigned maxBTD        = cs.pcv->getMaxMTTDepth( slice, partitioner.chType );
802
19.9k
          const CodingUnit *cuBR = bestCS->cus.back();
803
19.9k
          unsigned height        = partitioner.currArea().lumaSize().height;
804
805
19.9k
          if(((bestCU->btDepth == 0 && maxBTD >= ((slice.isIntra() && !slice.sps->IBC) ? 3 : 2))
806
96
            || (bestCU->btDepth == 1 && cuBR && cuBR->btDepth == 1 && maxBTD >= ((slice.isIntra() && !slice.sps->IBC) ? 4 : 3)))
807
19.8k
            && (width <= MAX_TB_SIZEY && height <= MAX_TB_SIZEY)
808
19.8k
            && cuECtx.didHorzSplit && cuECtx.didVertSplit )
809
15.2k
          {
810
15.2k
            return false;
811
15.2k
          }
812
19.9k
        }
813
7.13k
        if( bestCS )
814
7.13k
        {
815
7.13k
          if( m_pcEncCfg->m_useEarlyCU == 2 && bestCS->cost != MAX_DOUBLE && bestCU && bestCU->skip && cuECtx.nonSkipWasTested && bestCS->cus.size() == 1 )
816
0
          {
817
0
            return false;
818
0
          }
819
820
7.13k
          int stopSplit = (m_pcEncCfg->m_FastInferMerge >> 4) && (bestCS->slice->TLayer > 4);
821
7.13k
          int limitBLsize = stopSplit ? 2048 : 1024;
822
7.13k
          if((m_pcEncCfg->m_useEarlyCU == 1 || stopSplit) && bestCS->cost != MAX_DOUBLE && bestCU && bestCU->skip && partitioner.currArea().lumaSize().area() < limitBLsize )
823
0
          {
824
0
            return false;
825
0
          }
826
7.13k
        }
827
7.13k
      }
828
7.13k
      break;
829
57.8k
    case CU_HORZ_SPLIT:
830
110k
    case CU_VERT_SPLIT:
831
110k
      resetFeature = true;
832
110k
      break;
833
30.9k
    case CU_TRIH_SPLIT:
834
30.9k
      if( cuECtx.didHorzSplit && bestCU && bestCU->btDepth == partitioner.currBtDepth && !bestCU->rootCbf )
835
25.1k
      {
836
25.1k
        return false;
837
25.1k
      }
838
839
5.83k
      if( m_pcEncCfg->m_qtbttSpeedUp > 1 )
840
5.83k
      {
841
        //unsigned maxBTD = cs.pcv->getMaxMTTDepth( slice, partitioner.chType );
842
5.83k
        if( /*maxBTD == 1 && */cuECtx.didHorzSplit && cuECtx.didVertSplit && cuECtx.bestCostHorzSplit > cuECtx.bestCostVertSplit )
843
1.64k
        {
844
1.64k
          return false;
845
1.64k
        }
846
5.83k
      }
847
848
4.19k
      if( !cuECtx.doTriHorzSplit )
849
13
      {
850
13
        return false;
851
13
      }
852
853
4.17k
      if (m_pcEncCfg->m_fastTTSplit && cuECtx.bestCostHorzSplit < MAX_DOUBLE)
854
3.12k
      {
855
3.12k
        if (cuECtx.bestCostBeforeSplit < MAX_DOUBLE && (cuECtx.bestCostHorzSplit > m_pcEncCfg->m_fastTT_th * cuECtx.bestCostBeforeSplit))
856
2.55k
        {
857
2.55k
          return false;
858
2.55k
        }
859
565
        if (cuECtx.bestCostVertSplit < MAX_DOUBLE && (cuECtx.bestCostHorzSplit > m_pcEncCfg->m_fastTT_th * cuECtx.bestCostVertSplit))
860
0
        {
861
0
          return false;
862
0
        }
863
565
      }
864
1.62k
      break;
865
24.4k
    case CU_TRIV_SPLIT:
866
24.4k
      if( cuECtx.didVertSplit && bestCU && bestCU->btDepth == partitioner.currBtDepth && !bestCU->rootCbf )
867
20.8k
      {
868
20.8k
        return false;
869
20.8k
      }
870
871
3.59k
      if( m_pcEncCfg->m_qtbttSpeedUp > 1 )
872
3.59k
      {
873
        //unsigned maxBTD = cs.pcv->getMaxMTTDepth( slice, partitioner.chType );
874
3.59k
        if( /*maxBTD == 1 && */cuECtx.didHorzSplit && cuECtx.didVertSplit && cuECtx.bestCostHorzSplit < cuECtx.bestCostVertSplit )
875
1.97k
        {
876
1.97k
          return false;
877
1.97k
        }
878
3.59k
      }
879
880
1.62k
      if( !cuECtx.doTriVertSplit )
881
51
      {
882
51
        return false;
883
51
      }
884
885
1.56k
      if (m_pcEncCfg->m_fastTTSplit && cuECtx.bestCostVertSplit < MAX_DOUBLE)
886
561
      {
887
561
        if (cuECtx.bestCostBeforeSplit < MAX_DOUBLE && (cuECtx.bestCostVertSplit > m_pcEncCfg->m_fastTT_th * cuECtx.bestCostBeforeSplit))
888
364
        {
889
364
          return false;
890
364
        }
891
197
        if (cuECtx.bestCostHorzSplit < MAX_DOUBLE && (cuECtx.bestCostVertSplit > m_pcEncCfg->m_fastTT_th * cuECtx.bestCostHorzSplit))
892
0
        {
893
0
          return false;
894
0
        }
895
197
      }
896
1.20k
      break;
897
1.20k
    default:
898
0
      THROW( "Only CU split modes are governed by the EncModeCtrl" );
899
0
      return false;
900
0
      break;
901
188k
  }
902
903
120k
  switch( split )
904
120k
  {
905
57.8k
    case CU_HORZ_SPLIT:
906
59.4k
    case CU_TRIH_SPLIT:
907
59.4k
      if( cuECtx.qtBeforeBt && cuECtx.didQuadSplit )
908
2.00k
      {
909
2.00k
        if( cuECtx.maxQtSubDepth > partitioner.currQtDepth + 1 )
910
0
        {
911
0
          if( resetFeature ) cuECtx.didHorzSplit = false;
912
0
          return false;
913
0
        }
914
2.00k
      }
915
59.4k
      break;
916
59.4k
    case CU_VERT_SPLIT:
917
54.2k
    case CU_TRIV_SPLIT:
918
54.2k
      if( cuECtx.qtBeforeBt && cuECtx.didQuadSplit )
919
2.08k
      {
920
2.08k
        if( cuECtx.maxQtSubDepth > partitioner.currQtDepth + 1 )
921
0
        {
922
0
          if( resetFeature ) cuECtx.didVertSplit = false;
923
0
          return false;
924
0
        }
925
2.08k
      }
926
54.2k
      break;
927
54.2k
    default:
928
7.13k
      break;
929
120k
  }
930
931
120k
  if( split == CU_QUAD_SPLIT )
932
7.13k
  {
933
7.13k
    cuECtx.didQuadSplit = m_pcEncCfg->m_qtbttSpeedUp <= 1 || !!cuECtx.doMoreSplits;
934
7.13k
  }
935
936
120k
  return m_pcEncCfg->m_qtbttSpeedUp <= 1 || !!cuECtx.doMoreSplits;
937
120k
}
938
939
bool EncModeCtrl::tryMode( const EncTestMode& encTestmode, const CodingStructure &cs, Partitioner& partitioner )
940
142k
{
941
142k
  CHECK( isModeSplit( encTestmode ), "wrong method");
942
943
142k
  ComprCUCtx& cuECtx = m_ComprCUCtxList.back();
944
945
142k
  if( cuECtx.minDepth > partitioner.currQtDepth && partitioner.canSplit( CU_QUAD_SPLIT, cs ) )
946
0
  {
947
    // enforce QT
948
0
    return false;
949
0
  }
950
951
142k
  const Slice&           slice        = *cs.slice;
952
142k
  const uint32_t         numComp      = getNumberValidComponents( slice.sps->chromaFormatIdc );
953
142k
  const CodedCUInfo      &relatedCU   = getBlkInfo( partitioner.currArea() );
954
142k
  const Area             &lumaArea    = partitioner.currArea().Y();
955
142k
  const CodingStructure* bestCS       = cuECtx.bestCS;
956
142k
  const EncTestMode      bestMode     = bestCS ?cuECtx.bestMode : EncTestMode();
957
958
142k
  if( encTestmode.type == ETM_INTRA )
959
88.1k
  {
960
    // if this is removed, the IntraSearch::xIntraCodingLumaQT needs to be adapted to support Intra TU split
961
    // also isXXAvailable in IntraPrediction.cpp need to be fixed to check availability within the same CU without isDecomp
962
88.1k
    if (m_pcEncCfg->m_FastInferMerge && !slice.isIntra() && !slice.isIRAP() && !(cs.area.lwidth() == 4 && cs.area.lheight() == 4) && !partitioner.isConsIntra())
963
0
    {
964
0
      if (bestCS && (bestCS->slice->TLayer > (m_pcEncCfg->m_maxTLayer - (m_pcEncCfg->m_FastInferMerge & 7)))
965
0
        && (bestCS->bestParent != nullptr) && bestCS->bestParent->cus.size() && (bestCS->bestParent->cus[0]->skip))
966
0
      {
967
0
        return false;
968
0
      }
969
0
    }
970
971
88.1k
    if( lumaArea.width > cs.sps->getMaxTbSize() || lumaArea.height > cs.sps->getMaxTbSize() )
972
0
    {
973
0
      return false;
974
0
    }
975
976
88.1k
    if (m_pcEncCfg->m_usePbIntraFast && (!cs.slice->isIntra() || cs.slice->sps->IBC) && cuECtx.interHad == 0 && cuECtx.bestCU && !CU::isIntra(*cuECtx.bestCU))
977
0
    {
978
0
      return false;
979
0
    }
980
981
    // INTRA MODES
982
88.1k
    if (cs.sps->IBC && !cuECtx.bestTU)
983
63.7k
    {
984
     // return true;
985
63.7k
    }
986
24.3k
    else
987
24.3k
    if( partitioner.isConsIntra() && !cuECtx.bestTU )
988
0
    {
989
      //return true;
990
0
    }
991
24.3k
    else
992
24.3k
    if ( lumaArea.width == 4 && lumaArea.height == 4 && !slice.isIntra() && !cuECtx.bestTU )
993
0
    {
994
      //return true;
995
0
    }
996
24.3k
    else
997
24.3k
    if (!(slice.isIRAP() || bestMode.type == ETM_INTRA || !cuECtx.bestTU ||
998
0
      ((!m_pcEncCfg->m_bDisableIntraCUsInInterSlices) && (!relatedCU.isInter || !relatedCU.isIBC) && (
999
0
                                    ( cuECtx.bestTU->cbf[0] != 0 ) ||
1000
0
           ( ( numComp > COMP_Cb ) && cuECtx.bestTU->cbf[1] != 0 ) ||
1001
0
           ( ( numComp > COMP_Cr ) && cuECtx.bestTU->cbf[2] != 0 )  // avoid very complex intra if it is unlikely
1002
0
         ) ) ) )
1003
0
    {
1004
0
      return false;
1005
0
    }
1006
24.3k
    else
1007
24.3k
    if( cuECtx.bestCS && cuECtx.bestCU && cuECtx.interHad )
1008
24.3k
    {
1009
      // Get SATD threshold from best Inter-CU
1010
24.3k
      if( !cs.slice->isIRAP() && m_pcEncCfg->m_usePbIntraFast )
1011
0
      {
1012
0
        const DFunc dfunc = DF_HAD;
1013
0
        DistParam distParam = m_pcRdCost->setDistParam( cs.getOrgBuf( COMP_Y ), cuECtx.bestCS->getPredBuf( COMP_Y ), cs.sps->bitDepths[ CH_L ], dfunc );
1014
0
        cuECtx.interHad = distParam.distFunc( distParam );
1015
0
      }
1016
24.3k
    }
1017
88.1k
    if ((m_pcEncCfg->m_IBCFastMethod > 1) && !cs.slice->isIntra()//IBC_FAST_METHOD_NOINTRA_IBCCBF0
1018
0
      && (bestMode.type == ETM_IBC || bestMode.type == ETM_IBC_MERGE)
1019
0
      && (!cuECtx.bestCU->Y().valid() || cuECtx.bestTU->cbf[0] == 0)
1020
0
      && (!cuECtx.bestCU->Cb().valid() || cuECtx.bestTU->cbf[1] == 0)
1021
0
      && (!cuECtx.bestCU->Cr().valid() || cuECtx.bestTU->cbf[2] == 0))
1022
0
    {
1023
0
      return false;
1024
0
    }
1025
88.1k
    if (m_pcEncCfg->m_FastIntraTools)
1026
88.1k
    {
1027
88.1k
      if (relatedCU.relatedCuIsValid)
1028
14.2k
      {
1029
14.2k
        cuECtx.relatedCuIsValid = relatedCU.relatedCuIsValid;
1030
14.2k
      }
1031
88.1k
      if (relatedCU.isIntra)
1032
23.6k
      {
1033
23.6k
        cuECtx.isIntra = relatedCU.isIntra;
1034
23.6k
      }
1035
88.1k
    }
1036
88.1k
  }
1037
54.3k
  else if( isModeInter( encTestmode ) )
1038
0
  {
1039
    // INTER MODES (ME + MERGE/SKIP)
1040
0
    CHECK( slice.isIntra(), "Inter-mode should not be in the I-Slice mode list!" );
1041
1042
    // --- Check if we can quit current mode using SAVE/LOAD coding history
1043
1044
0
    if( encTestmode.type == ETM_INTER_ME )
1045
0
    {
1046
0
      if( encTestmode.opts == ETO_STANDARD )
1047
0
      {
1048
0
        if (m_pcEncCfg->m_FastInferMerge)
1049
0
        {
1050
0
          if (bestCS && (bestCS->slice->TLayer > (m_pcEncCfg->m_maxTLayer - (m_pcEncCfg->m_FastInferMerge & 7)))
1051
0
            && (bestCS->bestParent != nullptr) && bestCS->bestParent->cus.size() && (bestCS->bestParent->cus[0]->skip))
1052
0
          {
1053
0
            return false;
1054
0
          }
1055
0
        }
1056
0
        if( relatedCU.isSkip || relatedCU.isIntra )
1057
0
        {
1058
0
          return false;
1059
0
        }
1060
0
      }
1061
0
    }
1062
0
  }
1063
54.3k
  else if (encTestmode.type == ETM_IBC || encTestmode.type == ETM_IBC_MERGE)
1064
54.3k
  {
1065
54.3k
    if ((m_pcEncCfg->m_IBCFastMethod > 1) && !(slice.isIRAP() || bestMode.type == ETM_INTRA || !cuECtx.bestTU ||
1066
0
      ((!m_pcEncCfg->m_bDisableIntraCUsInInterSlices) && (!relatedCU.isInter || !relatedCU.isIBC) && (
1067
0
        (cuECtx.bestTU->cbf[0] != 0) ||
1068
0
        ((numComp > COMP_Cb) && cuECtx.bestTU->cbf[1] != 0) ||
1069
0
        ((numComp > COMP_Cr) && cuECtx.bestTU->cbf[2] != 0)  // avoid very complex intra if it is unlikely
1070
0
        ))))
1071
0
    {
1072
0
      return false;
1073
0
    }
1074
54.3k
    if ((m_pcEncCfg->m_IBCFastMethod > 3) &&(lumaArea.width == 4 && lumaArea.height == 4 && !slice.isIntra()))
1075
0
    {
1076
0
      return false;
1077
0
    }
1078
    // IBC MODES
1079
54.3k
    return slice.sps->IBC && (partitioner.currArea().lumaSize().width < 128 && partitioner.currArea().lumaSize().height < 128);
1080
54.3k
  }
1081
0
  else
1082
0
  {
1083
0
    THROW("problem");
1084
0
    return false;
1085
0
  }
1086
1087
88.1k
  STAT_COUNT_CU_MODES( partitioner.chType == CH_L, g_cuCounters1D[CU_MODES_TRIED][0][!cs.slice->isIntra() + cs.slice->depth] );
1088
88.1k
  STAT_COUNT_CU_MODES( partitioner.chType == CH_L && !cs.slice->isIntra(), g_cuCounters2D[CU_MODES_TRIED][Log2( cs.area.lheight() )][Log2( cs.area.lwidth() )] );
1089
88.1k
  return true;
1090
142k
}
1091
1092
1093
void EncModeCtrl::beforeSplit( Partitioner& partitioner )
1094
88.1k
{
1095
88.1k
  ComprCUCtx&           cuECtx  = m_ComprCUCtxList.back();
1096
1097
88.1k
  if( ! cuECtx.bestCS )
1098
0
    return;
1099
1100
88.1k
  CodedCUInfo    &relatedCU   = getBlkInfo( partitioner.currArea() );
1101
88.1k
  const CodingUnit&  bestCU   = *cuECtx.bestCU;
1102
1103
88.1k
  cuECtx.bestNsPredMode       = cuECtx.bestMode;
1104
88.1k
  cuECtx.bestCostBeforeSplit  = cuECtx.bestCS->cost;
1105
1106
88.1k
  setFromCs( *cuECtx.bestCS, cuECtx.bestMode, partitioner );
1107
1108
88.1k
  if( bestCU.skip )
1109
0
  {
1110
0
    cuECtx.doMoreSplits--;
1111
0
  }
1112
1113
88.1k
  if( partitioner.modeType == MODE_TYPE_INTRA && partitioner.chType == CH_L )
1114
0
  {
1115
0
    return; //not set best coding mode for intra coding pass
1116
0
  }
1117
1118
  // assume the non-split modes are done and set the marks for the best found mode
1119
88.1k
  if( CU::isInter( bestCU ) )
1120
0
  {
1121
0
    relatedCU.isInter     = true;
1122
0
    relatedCU.isSkip     |= bestCU.skip;
1123
0
    relatedCU.isMMVDSkip |= bestCU.mmvdSkip;
1124
0
    relatedCU.BcwIdx      = bestCU.BcwIdx;
1125
0
  }
1126
88.1k
  else if (CU::isIBC(bestCU))
1127
0
  {
1128
0
    relatedCU.isIBC = true;
1129
0
    relatedCU.isSkip |= bestCU.skip;
1130
0
  }
1131
88.1k
  else if( CU::isIntra( bestCU ) )
1132
88.1k
  {
1133
88.1k
    relatedCU.isIntra     = true;
1134
88.1k
    if (m_pcEncCfg->m_FastIntraTools)
1135
88.1k
    {
1136
88.1k
      if ( cuECtx.intraWasTested && (!relatedCU.relatedCuIsValid || cuECtx.bestCS->cost < relatedCU.bestCost))
1137
27.1k
      {
1138
27.1k
        relatedCU.bestCost = cuECtx.bestCS->cost;
1139
27.1k
        relatedCU.relatedCuIsValid = true;
1140
27.1k
      }
1141
88.1k
    }
1142
88.1k
  }
1143
88.1k
  cuECtx.isBestNoSplitSkip = bestCU.skip;
1144
88.1k
}
1145
1146
1147
bool EncModeCtrl::useModeResult( const EncTestMode& encTestmode, CodingStructure*& tempCS, Partitioner& partitioner, const bool useEDO )
1148
184k
{
1149
184k
  ComprCUCtx& cuECtx = m_ComprCUCtxList.back();
1150
1151
1152
184k
  if(      encTestmode.type == ETM_SPLIT_BT_H )
1153
25.8k
  {
1154
25.8k
    cuECtx.bestCostHorzSplit = tempCS->cost;
1155
25.8k
  }
1156
158k
  else if( encTestmode.type == ETM_SPLIT_BT_V )
1157
25.4k
  {
1158
25.4k
    cuECtx.bestCostVertSplit = tempCS->cost;
1159
25.4k
  }
1160
132k
  else if( !isModeSplit( encTestmode ) && isModeInter( encTestmode ) && tempCS->cus.size() == 1 )
1161
0
  {
1162
0
    cuECtx.nonSkipWasTested |= !tempCS->cus.front()->skip;
1163
0
  }
1164
184k
  if (m_pcEncCfg->m_AMVRspeed && encTestmode.type == ETM_INTER_ME)
1165
0
  {
1166
0
    int imvMode = (encTestmode.opts & ETO_IMV) >> ETO_IMV_SHIFT;
1167
1168
0
    if (imvMode == 0)
1169
0
    {
1170
0
      if (tempCS->cost < cuECtx.bestCostNoImv )
1171
0
      {
1172
0
        cuECtx.bestCostNoImv = tempCS->cost;
1173
0
      }
1174
0
    }
1175
0
  }
1176
1177
184k
  if( encTestmode.type == ETM_SPLIT_QT )
1178
20.0k
  {
1179
20.0k
    int maxQtD = 0;
1180
20.0k
    for( const auto& cu : tempCS->cus )
1181
80.4k
    {
1182
80.4k
      maxQtD = std::max<int>( maxQtD, cu->qtDepth );
1183
80.4k
    }
1184
20.0k
    cuECtx.maxQtSubDepth = maxQtD;
1185
20.0k
  }
1186
1187
184k
  int maxMtD = tempCS->pcv->getMaxMTTDepth( *tempCS->slice, partitioner.chType ) + partitioner.currImplicitBtDepth;
1188
1189
184k
  if( encTestmode.type == ETM_SPLIT_BT_H )
1190
25.8k
  {
1191
25.8k
    if( tempCS->cus.size() > 2 )
1192
1.06k
    {
1193
1.06k
      int h_2   = tempCS->area.blocks[partitioner.chType].height / 2;
1194
1.06k
      int cu1_h = tempCS->cus.front()->blocks[partitioner.chType].height;
1195
1.06k
      int cu2_h = tempCS->cus.back() ->blocks[partitioner.chType].height;
1196
1197
1.06k
      cuECtx.doTriHorzSplit = cu1_h < h_2 || cu2_h < h_2 || partitioner.currMtDepth + 1 == maxMtD;
1198
1.06k
    }
1199
25.8k
  }
1200
158k
  else if( encTestmode.type == ETM_SPLIT_BT_V )
1201
25.4k
  {
1202
25.4k
    if( tempCS->cus.size() > 2 )
1203
1.11k
    {
1204
1.11k
      int w_2   = tempCS->area.blocks[partitioner.chType].width / 2;
1205
1.11k
      int cu1_w = tempCS->cus.front()->blocks[partitioner.chType].width;
1206
1.11k
      int cu2_w = tempCS->cus.back() ->blocks[partitioner.chType].width;
1207
1208
1.11k
      cuECtx.doTriVertSplit = cu1_w < w_2 || cu2_w < w_2 || partitioner.currMtDepth + 1 == maxMtD;
1209
1.11k
    }
1210
25.4k
  }
1211
1212
184k
  if( encTestmode.type == ETM_SPLIT_BT_V || encTestmode.type == ETM_SPLIT_BT_H || encTestmode.type == ETM_SPLIT_QT )
1213
71.3k
  {
1214
71.3k
    bool isAllSkip = true;
1215
1216
71.3k
    for( const auto& cu : tempCS->cus )
1217
161k
    {
1218
161k
      isAllSkip &= cu->skip;
1219
161k
    }
1220
1221
71.3k
    if( isAllSkip ) cuECtx.doMoreSplits--;
1222
71.3k
    if( isAllSkip && encTestmode.type == ETM_SPLIT_QT )
1223
0
                    cuECtx.doMoreSplits--;
1224
71.3k
  }
1225
1226
  // for now just a simple decision based on RD-cost or choose tempCS if bestCS is not yet coded
1227
184k
  if( tempCS->cost != MAX_DOUBLE && ( !cuECtx.bestCS || ( ( tempCS->cost + ( useEDO ? tempCS->costDbOffset : 0 ) ) < ( cuECtx.bestCS->cost + ( useEDO ? cuECtx.bestCS->costDbOffset : 0 ) ) ) ) )
1228
166k
  {
1229
166k
    cuECtx.bestCS   = tempCS;
1230
166k
    cuECtx.bestCU   = tempCS->cus[0];
1231
166k
    cuECtx.bestTU   = cuECtx.bestCU->firstTU;
1232
166k
    cuECtx.bestMode = encTestmode;
1233
1234
166k
    return true;
1235
166k
  }
1236
17.5k
  else
1237
17.5k
  {
1238
17.5k
    return false;
1239
17.5k
  }
1240
184k
}
1241
1242
} // namespace vvenc
1243
1244
//! \}
1245