Coverage Report

Created: 2026-10-17 06:56

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/work/vvenc/source/Lib/EncoderLib/EncModeCtrl.h
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
/** \file     EncModeCtrl.h
43
    \brief    Encoder controller for trying out specific modes
44
*/
45
46
#pragma once
47
48
#include "InterSearch.h"
49
#include "CommonLib/CommonDef.h"
50
#include "CommonLib/CodingStructure.h"
51
52
#include <memory>
53
#include <typeinfo>
54
#include <vector>
55
56
//! \ingroup EncoderLib
57
//! \{
58
59
namespace vvenc {
60
61
//////////////////////////////////////////////////////////////////////////
62
// Encoder modes to try out
63
//////////////////////////////////////////////////////////////////////////
64
65
66
enum EncTestModeType
67
{
68
  ETM_MERGE_SKIP,
69
  ETM_INTER_ME,
70
  ETM_INTER_IMV,
71
  ETM_INTRA,
72
  ETM_SPLIT_QT,
73
  ETM_SPLIT_BT_H,
74
  ETM_SPLIT_BT_V,
75
  ETM_SPLIT_TT_H,
76
  ETM_SPLIT_TT_V,
77
  ETM_RECO_CACHED,
78
  ETM_IBC,
79
  ETM_IBC_MERGE,
80
  ETM_INVALID
81
};
82
83
enum EncTestModeOpts
84
{
85
  ETO_STANDARD    =  0,                   // empty      (standard option)
86
  ETO_FORCE_MERGE =  1<<0,                // bit   0    (indicates forced merge)
87
  ETO_IMV_SHIFT   =  1,                   // bits  1-3  (imv parameter starts at bit 1)
88
  ETO_IMV         =  7<<ETO_IMV_SHIFT,    // bits  1-3  (imv parameter uses 3 bits)
89
  ETO_DUMMY       =  1<<5,                // bit   5    (dummy)
90
  ETO_INVALID     = 0xffffffff            // bits 0-31  (invalid option)
91
};
92
93
static inline void getAreaIdxNew(const Area& area, const PreCalcValues &pcv, unsigned& idx1, unsigned& idx2, unsigned& idx3, unsigned& idx4)
94
326k
{
95
326k
  idx1 = Log2( area.width  )-2;
96
326k
  idx2 = Log2( area.height )-2;
97
326k
  idx3 = (area.x & pcv.maxCUSizeMask) >> MIN_CU_LOG2;
98
326k
  idx4 = (area.y & pcv.maxCUSizeMask) >> MIN_CU_LOG2;
99
326k
}
Unexecuted instantiation: vvencimpl.cpp:vvenc::getAreaIdxNew(vvenc::Area const&, vvenc::PreCalcValues const&, unsigned int&, unsigned int&, unsigned int&, unsigned int&)
Unexecuted instantiation: EncLib.cpp:vvenc::getAreaIdxNew(vvenc::Area const&, vvenc::PreCalcValues const&, unsigned int&, unsigned int&, unsigned int&, unsigned int&)
Unexecuted instantiation: EncGOP.cpp:vvenc::getAreaIdxNew(vvenc::Area const&, vvenc::PreCalcValues const&, unsigned int&, unsigned int&, unsigned int&, unsigned int&)
Unexecuted instantiation: EncPicture.cpp:vvenc::getAreaIdxNew(vvenc::Area const&, vvenc::PreCalcValues const&, unsigned int&, unsigned int&, unsigned int&, unsigned int&)
Unexecuted instantiation: EncSlice.cpp:vvenc::getAreaIdxNew(vvenc::Area const&, vvenc::PreCalcValues const&, unsigned int&, unsigned int&, unsigned int&, unsigned int&)
Unexecuted instantiation: InterSearch.cpp:vvenc::getAreaIdxNew(vvenc::Area const&, vvenc::PreCalcValues const&, unsigned int&, unsigned int&, unsigned int&, unsigned int&)
Unexecuted instantiation: EncCu.cpp:vvenc::getAreaIdxNew(vvenc::Area const&, vvenc::PreCalcValues const&, unsigned int&, unsigned int&, unsigned int&, unsigned int&)
EncModeCtrl.cpp:vvenc::getAreaIdxNew(vvenc::Area const&, vvenc::PreCalcValues const&, unsigned int&, unsigned int&, unsigned int&, unsigned int&)
Line
Count
Source
94
326k
{
95
326k
  idx1 = Log2( area.width  )-2;
96
326k
  idx2 = Log2( area.height )-2;
97
326k
  idx3 = (area.x & pcv.maxCUSizeMask) >> MIN_CU_LOG2;
98
326k
  idx4 = (area.y & pcv.maxCUSizeMask) >> MIN_CU_LOG2;
99
326k
}
Unexecuted instantiation: IntraSearch.cpp:vvenc::getAreaIdxNew(vvenc::Area const&, vvenc::PreCalcValues const&, unsigned int&, unsigned int&, unsigned int&, unsigned int&)
100
101
struct EncTestMode
102
{
103
  EncTestMode()
104
732k
    : type( ETM_INVALID ), opts( ETO_INVALID  ), qp( -1  ), lossless( false ) {}
105
  EncTestMode( EncTestModeType _type )
106
0
    : type( _type       ), opts( ETO_STANDARD ), qp( -1  ), lossless( false ) {}
107
  EncTestMode( EncTestModeType _type, int _qp, bool _lossless )
108
0
    : type( _type       ), opts( ETO_STANDARD ), qp( _qp ), lossless( _lossless ) {}
109
  EncTestMode( EncTestModeType _type, EncTestModeOpts _opts, int _qp, bool _lossless )
110
425k
    : type( _type       ), opts( _opts        ), qp( _qp ), lossless( _lossless ) {}
111
112
  EncTestModeType type;
113
  EncTestModeOpts opts;
114
  int             qp;
115
  bool            lossless;
116
  double          maxCostAllowed;
117
};
118
119
120
inline bool isModeSplit( const EncTestMode& encTestmode )
121
465k
{
122
465k
  switch( encTestmode.type )
123
465k
  {
124
94.2k
  case ETM_SPLIT_QT     :
125
145k
  case ETM_SPLIT_BT_H   :
126
192k
  case ETM_SPLIT_BT_V   :
127
220k
  case ETM_SPLIT_TT_H   :
128
241k
  case ETM_SPLIT_TT_V   :
129
241k
    return true;
130
224k
  default:
131
224k
    return false;
132
465k
  }
133
465k
}
134
135
inline bool isModeNoSplit( const EncTestMode& encTestmode )
136
0
{
137
0
  return !isModeSplit( encTestmode );
138
0
}
139
140
inline bool isModeInter( const EncTestMode& encTestmode ) // perhaps remove
141
146k
{
142
146k
  return (   encTestmode.type == ETM_INTER_ME
143
146k
          || encTestmode.type == ETM_INTER_IMV
144
146k
          || encTestmode.type == ETM_MERGE_SKIP
145
146k
         );
146
146k
}
147
148
inline PartSplit getPartSplit( const EncTestMode& encTestmode )
149
590k
{
150
590k
  switch( encTestmode.type )
151
590k
  {
152
153k
  case ETM_SPLIT_QT     : return CU_QUAD_SPLIT;
153
195k
  case ETM_SPLIT_BT_H   : return CU_HORZ_SPLIT;
154
186k
  case ETM_SPLIT_BT_V   : return CU_VERT_SPLIT;
155
30.6k
  case ETM_SPLIT_TT_H   : return CU_TRIH_SPLIT;
156
23.9k
  case ETM_SPLIT_TT_V   : return CU_TRIV_SPLIT;
157
0
  default:                return CU_DONT_SPLIT;
158
590k
  }
159
590k
}
160
161
//////////////////////////////////////////////////////////////////////////
162
// EncModeCtrl controls if specific modes should be tested
163
//////////////////////////////////////////////////////////////////////////
164
165
struct ComprCUCtx
166
{
167
  ComprCUCtx()
168
129k
  {
169
129k
  }
170
171
  ComprCUCtx( const CodingStructure& cs, const uint32_t _minDepth, const uint32_t _maxDepth )
172
123k
    : minDepth      ( _minDepth  )
173
123k
    , maxDepth      ( _maxDepth  )
174
123k
    , bestCS        ( nullptr    )
175
123k
    , bestCU        ( nullptr    )
176
123k
    , bestTU        ( nullptr    )
177
123k
    , bestMode      ()
178
123k
    , bestCostBeforeSplit   (MAX_DOUBLE)
179
123k
    , bestCostVertSplit     (MAX_DOUBLE)
180
123k
    , bestCostHorzSplit     (MAX_DOUBLE)
181
123k
    , bestCostNoImv         (MAX_DOUBLE *.5)
182
123k
    , grad_horVal           (0)
183
123k
    , grad_verVal           (0)
184
123k
    , grad_dupVal           (0)
185
123k
    , grad_dowVal           (0)
186
123k
    , interHad              (MAX_DISTORTION)
187
123k
    , maxQtSubDepth         (0)
188
123k
    , isReusingCu           (false)
189
123k
    , qtBeforeBt            (false)
190
123k
    , doTriHorzSplit        (false)
191
123k
    , doTriVertSplit        (false)
192
123k
    , didQuadSplit          (false)
193
123k
    , didHorzSplit          (false)
194
123k
    , didVertSplit          (false)
195
123k
    , doHorChromaSplit      (false)
196
123k
    , doVerChromaSplit      (false)
197
123k
    , doQtChromaSplit       (false)
198
123k
    , isBestNoSplitSkip     (false)
199
123k
    , intraWasTested        (false)
200
123k
    , relatedCuIsValid      (false)
201
123k
    , isIntra               (false)
202
123k
    , nonSkipWasTested      (false)
203
123k
    , bestNsPredMode        (EncTestMode())
204
123k
  {
205
123k
  }
206
207
  unsigned          minDepth;
208
  unsigned          maxDepth;
209
  CodingStructure*  bestCS;
210
  CodingUnit*       bestCU;
211
  TransformUnit*    bestTU;
212
  EncTestMode       bestMode;
213
  double            bestCostBeforeSplit;
214
  double            bestCostVertSplit;
215
  double            bestCostHorzSplit;
216
  double            bestCostNoImv;
217
  double            grad_horVal;
218
  double            grad_verVal;
219
  double            grad_dupVal;
220
  double            grad_dowVal;
221
  Distortion        interHad;
222
  int               maxQtSubDepth;
223
  bool              isReusingCu;
224
  bool              qtBeforeBt;
225
  bool              doTriHorzSplit;
226
  bool              doTriVertSplit;
227
  int               doMoreSplits;
228
  bool              didQuadSplit;
229
  bool              didHorzSplit;
230
  bool              didVertSplit;
231
  bool              doHorChromaSplit;
232
  bool              doVerChromaSplit;
233
  bool              doQtChromaSplit;
234
  bool              isBestNoSplitSkip;
235
  bool              intraWasTested;
236
  bool              relatedCuIsValid;
237
  bool              isIntra;
238
  bool              nonSkipWasTested;
239
  EncTestMode       bestNsPredMode;
240
};
241
242
//////////////////////////////////////////////////////////////////////////
243
// some utility interfaces that expose some functionality that can be used without concerning about which particular controller is used
244
//////////////////////////////////////////////////////////////////////////
245
246
static const int MAX_STORED_CU_INFO_REFS = 4;
247
248
struct CodedCUInfo
249
{
250
  bool      relatedCuIsValid;
251
  bool      isInter;
252
  bool      isIntra;
253
  bool      isSkip;
254
  bool      isMMVDSkip;
255
  bool      isIBC;
256
  uint8_t   BcwIdx;
257
  uint8_t   numPuInfoStored;
258
  int       poc, ctuRsAddr;
259
  bool      validMv[NUM_REF_PIC_LIST_01][MAX_STORED_CU_INFO_REFS];
260
  Mv        saveMv [NUM_REF_PIC_LIST_01][MAX_STORED_CU_INFO_REFS];
261
  uint32_t  puSse  [SBT_NUM_SL];
262
  uint8_t   puSbt  [SBT_NUM_SL];
263
  double    bestCost;
264
265
  bool getMv  ( const RefPicList refPicList, const int iRefIdx,       Mv& rMv ) const;
266
  void setMv  ( const RefPicList refPicList, const int iRefIdx, const Mv& rMv );
267
};
268
269
class CacheBlkInfoCtrl
270
{
271
protected:
272
  // x in CTU, y in CTU, width, height
273
  CodedCUInfo*         m_codedCUInfo[6][6][MAX_CU_SIZE >> MIN_CU_LOG2][MAX_CU_SIZE >> MIN_CU_LOG2];
274
  CodedCUInfo*         m_codedCUInfoBuf;
275
  const PreCalcValues* m_pcv;
276
277
protected:
278
279
  void create   ( int ctuSize );
280
  void destroy  ();
281
  void init     ( const Slice &slice );
282
283
public:
284
4.62k
  CacheBlkInfoCtrl() : m_codedCUInfoBuf( nullptr ) {}
285
4.62k
  ~CacheBlkInfoCtrl () {}
286
287
  CodedCUInfo& getBlkInfo   ( const UnitArea& area );
288
  void         initBlk      ( const UnitArea& area, int poc );
289
290
  uint8_t      findBestSbt  ( const UnitArea& area, const uint32_t curPuSse );
291
  bool         saveBestSbt  ( const UnitArea& area, const uint32_t curPuSse, const uint8_t curPuSbt );
292
};
293
294
struct BestEncodingInfo
295
{ 
296
  CodingUnit      cu;
297
  TransformUnit   tu;
298
  EncTestMode     testMode;
299
  int             poc;
300
  Distortion      dist;
301
  double          costEDO;
302
};
303
304
// Hands out runs of T from chunks that are kept for reuse. Runs never move, so pointers into them
305
// stay valid until reset() makes all chunks available again.
306
template<typename T, size_t ChunkSize>
307
class ReusableChunkArena
308
{
309
public:
310
  T* take( const size_t n )
311
0
  {
312
0
    CHECK( n > ChunkSize, "Run larger than an arena chunk" );
313
0
    if( m_current < 0 || m_used + n > ChunkSize )
314
0
    {
315
0
      m_current++;
316
0
      if( m_current == ( int ) m_chunks.size() )
317
0
      {
318
0
        m_chunks.emplace_back( new T[ChunkSize] );
319
0
      }
320
0
      m_used = 0;
321
0
    }
322
0
    T* run  = m_chunks[m_current].get() + m_used;
323
0
    m_used += n;
324
0
    return run;
325
0
  }
Unexecuted instantiation: vvenc::ReusableChunkArena<vvenc::BestEncodingInfo, 256ul>::take(unsigned long)
Unexecuted instantiation: vvenc::ReusableChunkArena<vvenc::Mv, 4096ul>::take(unsigned long)
Unexecuted instantiation: vvenc::ReusableChunkArena<short, 131072ul>::take(unsigned long)
326
327
0
  void reset()   { m_current = -1; m_used = 0; }
Unexecuted instantiation: vvenc::ReusableChunkArena<vvenc::BestEncodingInfo, 256ul>::reset()
Unexecuted instantiation: vvenc::ReusableChunkArena<short, 131072ul>::reset()
Unexecuted instantiation: vvenc::ReusableChunkArena<vvenc::Mv, 4096ul>::reset()
328
0
  void release() { m_chunks.clear(); reset(); }
Unexecuted instantiation: vvenc::ReusableChunkArena<vvenc::BestEncodingInfo, 256ul>::release()
Unexecuted instantiation: vvenc::ReusableChunkArena<short, 131072ul>::release()
Unexecuted instantiation: vvenc::ReusableChunkArena<vvenc::Mv, 4096ul>::release()
329
330
private:
331
  std::vector<std::unique_ptr<T[]>> m_chunks;
332
  int    m_current = -1;
333
  size_t m_used    = 0;
334
};
335
336
class BestEncInfoCache
337
{
338
private:
339
  const PreCalcValues* m_pcv;
340
  // The stored result of every CU size and position inside the CTU being encoded, or null. A result
341
  // only matches a CU of the same picture and position, so none outlives the CTU it was stored for,
342
  // and init() empties the slots of the previous CTU and reuses their storage.
343
  BestEncodingInfo*    m_bestEncInfo[6][6][MAX_CU_SIZE >> MIN_CU_LOG2][MAX_CU_SIZE >> MIN_CU_LOG2];
344
  std::vector<BestEncodingInfo**>           m_filledSlots;
345
  ReusableChunkArena<BestEncodingInfo, 256> m_entryArena;
346
  ReusableChunkArena<TCoeffSig, 131072>     m_coeffArena;
347
  ReusableChunkArena<Mv, 4096>              m_dmvrMvArena;
348
  ChromaFormat         m_chFmt;
349
  CodingStructure      m_dummyCS;
350
  XUCache              m_dummyCache;
351
352
  BestEncodingInfo*    xNewEntry( const int wIdx, const int hIdx );
353
354
protected:
355
  bool                 m_reuseCuResults;
356
  void create   ( const bool reuseCuResults, const ChromaFormat chFmt, int ctuSize );
357
  void destroy  ();
358
359
public:
360
4.62k
  BestEncInfoCache() : m_pcv( nullptr ), m_chFmt( CHROMA_420 ), m_dummyCS( m_dummyCache, nullptr ) {}
361
4.62k
  ~BestEncInfoCache() {}
362
363
  void init             ( const Slice &slice );
364
  bool setCsFrom        (       CodingStructure& cs,       EncTestMode& testMode, const Partitioner& partitioner ) const;
365
  bool setFromCs        ( const CodingStructure& cs, const EncTestMode& testMode, const Partitioner& partitioner );
366
  bool isReusingCuValid ( const CodingStructure &cs, const Partitioner &partitioner, int qp );
367
};
368
369
//////////////////////////////////////////////////////////////////////////
370
// EncModeCtrl - allows and controls modes introduced by QTBT (inkl. multi-type-tree)
371
//                    - only 2Nx2N, no RQT, additional binary/triary CU splits
372
//////////////////////////////////////////////////////////////////////////
373
374
class EncModeCtrl: public CacheBlkInfoCtrl, public BestEncInfoCache
375
{
376
protected:
377
378
  const VVEncCfg*       m_pcEncCfg;
379
        RdCost*         m_pcRdCost;
380
  static_vector<ComprCUCtx, ( MAX_CU_DEPTH << 2 )> m_ComprCUCtxList;
381
  unsigned              m_skipThresholdE0023FastEnc;
382
  unsigned              m_tileIdx;
383
384
public:
385
  ComprCUCtx*           comprCUCtx;
386
387
4.62k
  ~EncModeCtrl    () { destroy(); }
388
389
  void init               ( const VVEncCfg& encCfg, RdCost *pRdCost );
390
  void destroy            ();
391
  void initCTUEncoding    ( const Slice &slice, int tileIdx );
392
  void initCULevel        ( Partitioner &partitioner, const CodingStructure& cs, int  MergeSimpleFlag );
393
  void finishCULevel      ( Partitioner &partitioner );
394
395
  bool tryMode            ( const EncTestMode& encTestmode, const CodingStructure &cs, Partitioner& partitioner );
396
  bool trySplit           ( const EncTestMode& encTestmode, const CodingStructure &cs, Partitioner& partitioner, const EncTestMode& lastTestmode );
397
  bool useModeResult      ( const EncTestMode& encTestmode, CodingStructure*& tempCS,  Partitioner& partitioner, const bool useEDO );
398
399
  void beforeSplit        ( Partitioner& partitioner );
400
};
401
402
} // namespace vvenc
403
404
//! \}
405