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.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 <typeinfo>
53
#include <vector>
54
55
//! \ingroup EncoderLib
56
//! \{
57
58
namespace vvenc {
59
60
//////////////////////////////////////////////////////////////////////////
61
// Encoder modes to try out
62
//////////////////////////////////////////////////////////////////////////
63
64
65
enum EncTestModeType
66
{
67
  ETM_MERGE_SKIP,
68
  ETM_INTER_ME,
69
  ETM_INTER_IMV,
70
  ETM_INTRA,
71
  ETM_SPLIT_QT,
72
  ETM_SPLIT_BT_H,
73
  ETM_SPLIT_BT_V,
74
  ETM_SPLIT_TT_H,
75
  ETM_SPLIT_TT_V,
76
  ETM_RECO_CACHED,
77
  ETM_IBC,
78
  ETM_IBC_MERGE,
79
  ETM_INVALID
80
};
81
82
enum EncTestModeOpts
83
{
84
  ETO_STANDARD    =  0,                   // empty      (standard option)
85
  ETO_FORCE_MERGE =  1<<0,                // bit   0    (indicates forced merge)
86
  ETO_IMV_SHIFT   =  1,                   // bits  1-3  (imv parameter starts at bit 1)
87
  ETO_IMV         =  7<<ETO_IMV_SHIFT,    // bits  1-3  (imv parameter uses 3 bits)
88
  ETO_DUMMY       =  1<<5,                // bit   5    (dummy)
89
  ETO_INVALID     = 0xffffffff            // bits 0-31  (invalid option)
90
};
91
92
static inline void getAreaIdxNew(const Area& area, const PreCalcValues &pcv, unsigned& idx1, unsigned& idx2, unsigned& idx3, unsigned& idx4)
93
369k
{
94
369k
  idx1 = Log2( area.width  )-2;
95
369k
  idx2 = Log2( area.height )-2;
96
369k
  idx3 = (area.x & pcv.maxCUSizeMask) >> MIN_CU_LOG2;
97
369k
  idx4 = (area.y & pcv.maxCUSizeMask) >> MIN_CU_LOG2;
98
369k
}
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
93
369k
{
94
369k
  idx1 = Log2( area.width  )-2;
95
369k
  idx2 = Log2( area.height )-2;
96
369k
  idx3 = (area.x & pcv.maxCUSizeMask) >> MIN_CU_LOG2;
97
369k
  idx4 = (area.y & pcv.maxCUSizeMask) >> MIN_CU_LOG2;
98
369k
}
Unexecuted instantiation: IntraSearch.cpp:vvenc::getAreaIdxNew(vvenc::Area const&, vvenc::PreCalcValues const&, unsigned int&, unsigned int&, unsigned int&, unsigned int&)
99
100
struct EncTestMode
101
{
102
  EncTestMode()
103
1.69M
    : type( ETM_INVALID ), opts( ETO_INVALID  ), qp( -1  ), lossless( false ) {}
104
  EncTestMode( EncTestModeType _type )
105
0
    : type( _type       ), opts( ETO_STANDARD ), qp( -1  ), lossless( false ) {}
106
  EncTestMode( EncTestModeType _type, int _qp, bool _lossless )
107
0
    : type( _type       ), opts( ETO_STANDARD ), qp( _qp ), lossless( _lossless ) {}
108
  EncTestMode( EncTestModeType _type, EncTestModeOpts _opts, int _qp, bool _lossless )
109
481k
    : type( _type       ), opts( _opts        ), qp( _qp ), lossless( _lossless ) {}
110
111
  EncTestModeType type;
112
  EncTestModeOpts opts;
113
  int             qp;
114
  bool            lossless;
115
  double          maxCostAllowed;
116
};
117
118
119
inline bool isModeSplit( const EncTestMode& encTestmode )
120
528k
{
121
528k
  switch( encTestmode.type )
122
528k
  {
123
106k
  case ETM_SPLIT_QT     :
124
164k
  case ETM_SPLIT_BT_H   :
125
217k
  case ETM_SPLIT_BT_V   :
126
249k
  case ETM_SPLIT_TT_H   :
127
273k
  case ETM_SPLIT_TT_V   :
128
273k
    return true;
129
254k
  default:
130
254k
    return false;
131
528k
  }
132
528k
}
133
134
inline bool isModeNoSplit( const EncTestMode& encTestmode )
135
0
{
136
0
  return !isModeSplit( encTestmode );
137
0
}
138
139
inline bool isModeInter( const EncTestMode& encTestmode ) // perhaps remove
140
166k
{
141
166k
  return (   encTestmode.type == ETM_INTER_ME
142
166k
          || encTestmode.type == ETM_INTER_IMV
143
166k
          || encTestmode.type == ETM_MERGE_SKIP
144
166k
         );
145
166k
}
146
147
inline PartSplit getPartSplit( const EncTestMode& encTestmode )
148
668k
{
149
668k
  switch( encTestmode.type )
150
668k
  {
151
174k
  case ETM_SPLIT_QT     : return CU_QUAD_SPLIT;
152
222k
  case ETM_SPLIT_BT_H   : return CU_HORZ_SPLIT;
153
210k
  case ETM_SPLIT_BT_V   : return CU_VERT_SPLIT;
154
34.2k
  case ETM_SPLIT_TT_H   : return CU_TRIH_SPLIT;
155
26.9k
  case ETM_SPLIT_TT_V   : return CU_TRIV_SPLIT;
156
0
  default:                return CU_DONT_SPLIT;
157
668k
  }
158
668k
}
159
160
//////////////////////////////////////////////////////////////////////////
161
// EncModeCtrl controls if specific modes should be tested
162
//////////////////////////////////////////////////////////////////////////
163
164
struct ComprCUCtx
165
{
166
  ComprCUCtx()
167
581k
  {
168
581k
  }
169
170
  ComprCUCtx( const CodingStructure& cs, const uint32_t _minDepth, const uint32_t _maxDepth )
171
139k
    : minDepth      ( _minDepth  )
172
139k
    , maxDepth      ( _maxDepth  )
173
139k
    , bestCS        ( nullptr    )
174
139k
    , bestCU        ( nullptr    )
175
139k
    , bestTU        ( nullptr    )
176
139k
    , bestMode      ()
177
139k
    , bestCostBeforeSplit   (MAX_DOUBLE)
178
139k
    , bestCostVertSplit     (MAX_DOUBLE)
179
139k
    , bestCostHorzSplit     (MAX_DOUBLE)
180
139k
    , bestCostNoImv         (MAX_DOUBLE *.5)
181
139k
    , grad_horVal           (0)
182
139k
    , grad_verVal           (0)
183
139k
    , grad_dupVal           (0)
184
139k
    , grad_dowVal           (0)
185
139k
    , interHad              (MAX_DISTORTION)
186
139k
    , maxQtSubDepth         (0)
187
139k
    , isReusingCu           (false)
188
139k
    , qtBeforeBt            (false)
189
139k
    , doTriHorzSplit        (false)
190
139k
    , doTriVertSplit        (false)
191
139k
    , didQuadSplit          (false)
192
139k
    , didHorzSplit          (false)
193
139k
    , didVertSplit          (false)
194
139k
    , doHorChromaSplit      (false)
195
139k
    , doVerChromaSplit      (false)
196
139k
    , doQtChromaSplit       (false)
197
139k
    , isBestNoSplitSkip     (false)
198
139k
    , intraWasTested        (false)
199
139k
    , relatedCuIsValid      (false)
200
139k
    , isIntra               (false)
201
139k
    , nonSkipWasTested      (false)
202
139k
    , bestNsPredMode        (EncTestMode())
203
139k
  {
204
139k
  }
205
206
  unsigned          minDepth;
207
  unsigned          maxDepth;
208
  CodingStructure*  bestCS;
209
  CodingUnit*       bestCU;
210
  TransformUnit*    bestTU;
211
  EncTestMode       bestMode;
212
  double            bestCostBeforeSplit;
213
  double            bestCostVertSplit;
214
  double            bestCostHorzSplit;
215
  double            bestCostNoImv;
216
  double            grad_horVal;
217
  double            grad_verVal;
218
  double            grad_dupVal;
219
  double            grad_dowVal;
220
  Distortion        interHad;
221
  int               maxQtSubDepth;
222
  bool              isReusingCu;
223
  bool              qtBeforeBt;
224
  bool              doTriHorzSplit;
225
  bool              doTriVertSplit;
226
  int               doMoreSplits;
227
  bool              didQuadSplit;
228
  bool              didHorzSplit;
229
  bool              didVertSplit;
230
  bool              doHorChromaSplit;
231
  bool              doVerChromaSplit;
232
  bool              doQtChromaSplit;
233
  bool              isBestNoSplitSkip;
234
  bool              intraWasTested;
235
  bool              relatedCuIsValid;
236
  bool              isIntra;
237
  bool              nonSkipWasTested;
238
  EncTestMode       bestNsPredMode;
239
};
240
241
//////////////////////////////////////////////////////////////////////////
242
// some utility interfaces that expose some functionality that can be used without concerning about which particular controller is used
243
//////////////////////////////////////////////////////////////////////////
244
245
static const int MAX_STORED_CU_INFO_REFS = 4;
246
247
struct CodedCUInfo
248
{
249
  bool      relatedCuIsValid;
250
  bool      isInter;
251
  bool      isIntra;
252
  bool      isSkip;
253
  bool      isMMVDSkip;
254
  bool      isIBC;
255
  uint8_t   BcwIdx;
256
  uint8_t   numPuInfoStored;
257
  int       poc, ctuRsAddr;
258
  bool      validMv[NUM_REF_PIC_LIST_01][MAX_STORED_CU_INFO_REFS];
259
  Mv        saveMv [NUM_REF_PIC_LIST_01][MAX_STORED_CU_INFO_REFS];
260
  uint32_t  puSse  [SBT_NUM_SL];
261
  uint8_t   puSbt  [SBT_NUM_SL];
262
  double    bestCost;
263
264
  bool getMv  ( const RefPicList refPicList, const int iRefIdx,       Mv& rMv ) const;
265
  void setMv  ( const RefPicList refPicList, const int iRefIdx, const Mv& rMv );
266
};
267
268
class CacheBlkInfoCtrl
269
{
270
protected:
271
  // x in CTU, y in CTU, width, height
272
  CodedCUInfo*         m_codedCUInfo[6][6][MAX_CU_SIZE >> MIN_CU_LOG2][MAX_CU_SIZE >> MIN_CU_LOG2];
273
  CodedCUInfo*         m_codedCUInfoBuf;
274
  const PreCalcValues* m_pcv;
275
276
protected:
277
278
  void create   ( int ctuSize );
279
  void destroy  ();
280
  void init     ( const Slice &slice );
281
282
public:
283
20.7k
  CacheBlkInfoCtrl() : m_codedCUInfoBuf( nullptr ) {}
284
20.7k
  ~CacheBlkInfoCtrl () {}
285
286
  CodedCUInfo& getBlkInfo   ( const UnitArea& area );
287
  void         initBlk      ( const UnitArea& area, int poc );
288
289
  uint8_t      findBestSbt  ( const UnitArea& area, const uint32_t curPuSse );
290
  bool         saveBestSbt  ( const UnitArea& area, const uint32_t curPuSse, const uint8_t curPuSbt );
291
};
292
293
struct BestEncodingInfo
294
{ 
295
  CodingUnit      cu;
296
  TransformUnit   tu;
297
  EncTestMode     testMode;
298
  int             poc;
299
  Distortion      dist;
300
  double          costEDO;
301
};
302
303
class BestEncInfoCache
304
{
305
private:
306
  const PreCalcValues* m_pcv;
307
  BestEncodingInfo*    m_bestEncInfo[6][6][MAX_CU_SIZE >> MIN_CU_LOG2][MAX_CU_SIZE >> MIN_CU_LOG2];
308
  TCoeffSig*           m_pCoeff;
309
  BestEncodingInfo*    m_encInfoBuf;
310
  Mv*                  m_dmvrMvBuf;
311
  CodingStructure      m_dummyCS;
312
  XUCache              m_dummyCache;
313
314
protected:
315
  bool                 m_reuseCuResults;
316
  void create   ( const bool reuseCuResults, const ChromaFormat chFmt, int ctuSize );
317
  void destroy  ();
318
319
public:
320
20.7k
  BestEncInfoCache() : m_pcv( nullptr ), m_pCoeff( nullptr ), m_encInfoBuf( nullptr ), m_dmvrMvBuf( nullptr ), m_dummyCS( m_dummyCache, nullptr ) {}
321
20.7k
  ~BestEncInfoCache() {}
322
323
  void init             ( const Slice &slice );
324
  bool setCsFrom        (       CodingStructure& cs,       EncTestMode& testMode, const Partitioner& partitioner ) const;
325
  bool setFromCs        ( const CodingStructure& cs, const EncTestMode& testMode, const Partitioner& partitioner );
326
  bool isReusingCuValid ( const CodingStructure &cs, const Partitioner &partitioner, int qp );
327
};
328
329
//////////////////////////////////////////////////////////////////////////
330
// EncModeCtrl - allows and controls modes introduced by QTBT (inkl. multi-type-tree)
331
//                    - only 2Nx2N, no RQT, additional binary/triary CU splits
332
//////////////////////////////////////////////////////////////////////////
333
334
class EncModeCtrl: public CacheBlkInfoCtrl, public BestEncInfoCache
335
{
336
protected:
337
338
  const VVEncCfg*       m_pcEncCfg;
339
        RdCost*         m_pcRdCost;
340
  static_vector<ComprCUCtx, ( MAX_CU_DEPTH << 2 )> m_ComprCUCtxList;
341
  unsigned              m_skipThresholdE0023FastEnc;
342
  unsigned              m_tileIdx;
343
344
public:
345
  ComprCUCtx*           comprCUCtx;
346
347
20.7k
  ~EncModeCtrl    () { destroy(); }
348
349
  void init               ( const VVEncCfg& encCfg, RdCost *pRdCost );
350
  void destroy            ();
351
  void initCTUEncoding    ( const Slice &slice, int tileIdx );
352
  void initCULevel        ( Partitioner &partitioner, const CodingStructure& cs, int  MergeSimpleFlag );
353
  void finishCULevel      ( Partitioner &partitioner );
354
355
  bool tryMode            ( const EncTestMode& encTestmode, const CodingStructure &cs, Partitioner& partitioner );
356
  bool trySplit           ( const EncTestMode& encTestmode, const CodingStructure &cs, Partitioner& partitioner, const EncTestMode& lastTestmode );
357
  bool useModeResult      ( const EncTestMode& encTestmode, CodingStructure*& tempCS,  Partitioner& partitioner, const bool useEDO );
358
359
  void beforeSplit        ( Partitioner& partitioner );
360
};
361
362
} // namespace vvenc
363
364
//! \}
365