Coverage Report

Created: 2026-04-01 07:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/vvenc/source/Lib/EncoderLib/EncCu.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     EncCu.h
43
    \brief    Coding Unit (CU) encoder class (header)
44
*/
45
46
#pragma once
47
48
#include "vvenc/vvencCfg.h"
49
#include "CABACWriter.h"
50
#include "IntraSearch.h"
51
#include "InterSearch.h"
52
#include "EncModeCtrl.h"
53
#include "RateCtrl.h"
54
#include "CommonLib/CommonDef.h"
55
#include "CommonLib/Unit.h"
56
#include "CommonLib/UnitPartitioner.h"
57
#include "CommonLib/LoopFilter.h"
58
#include "DecoderLib/DecCu.h"
59
60
//! \ingroup EncoderLib
61
//! \{
62
63
namespace vvenc {
64
65
class EncModeCtrl;
66
struct EncTestMode;
67
class EncPicture;
68
69
// ====================================================================================================================
70
// Class definition
71
// ====================================================================================================================
72
  struct GeoMergeCombo
73
  {
74
    int    splitDir  =  0;
75
    int8_t mergeIdx0 = -1;
76
    int8_t mergeIdx1 = -1;
77
    double cost      = 0.0;
78
  };
79
80
  struct SmallerThanComboCost
81
  {
82
    inline bool operator()(const GeoMergeCombo &first, const GeoMergeCombo &second)
83
0
    {
84
0
      return (first.cost < second.cost);
85
0
    }
86
  };
87
88
  struct GeoComboCostList
89
  {
90
    std::vector<GeoMergeCombo> list;
91
0
    void                       sortByCost() { std::stable_sort(list.begin(), list.end(), SmallerThanComboCost()); };
92
  };
93
94
  class FastGeoCostList
95
  {
96
    using CostArray = double[GEO_NUM_PARTITION_MODE][2];
97
98
    int        m_maxNumGeoCand{ 0 };
99
    CostArray *m_singleDistList{ nullptr };
100
101
  public:
102
103
0
    FastGeoCostList() {}
104
    ~FastGeoCostList()
105
0
    {
106
0
      delete[] m_singleDistList;
107
0
      m_singleDistList = nullptr;
108
0
    }
109
110
    void init( int maxNumGeoCand )
111
0
    {
112
0
      if( m_maxNumGeoCand != maxNumGeoCand )
113
0
      {
114
0
        delete[] m_singleDistList;
115
0
        m_singleDistList = nullptr;
116
117
0
        CHECK( maxNumGeoCand > MRG_MAX_NUM_CANDS, "Too many candidates" );
118
0
        m_singleDistList = new CostArray[maxNumGeoCand];
119
0
        m_maxNumGeoCand  = maxNumGeoCand;
120
0
      }
121
0
    }
122
123
    void insert( int splitDir, int partIdx, int mergeIdx, double cost )
124
0
    {
125
0
      CHECKD( splitDir >= GEO_NUM_PARTITION_MODE, "geoIdx is too large" );
126
0
      CHECKD( mergeIdx >= m_maxNumGeoCand, "mergeIdx is too large" );
127
0
      CHECKD( partIdx >= 2, "partIdx is too large" );
128
129
0
      m_singleDistList[mergeIdx][splitDir][partIdx] = cost;
130
0
    }
131
132
    double getCost( const int splitDir, const int mergeCand0, const int mergeCand1 )
133
0
    {
134
0
      return m_singleDistList[mergeCand0][splitDir][0] + m_singleDistList[mergeCand1][splitDir][1];
135
0
    }
136
  };
137
138
139
140
  class MergeItem
141
  {
142
  private:
143
    PelStorage m_pelStorage;
144
    std::vector<MotionInfo> m_mvStorage;
145
146
  public:
147
148
    enum class MergeItemType
149
    {
150
      REGULAR,
151
      SBTMVP,
152
      AFFINE,
153
      MMVD,
154
      CIIP,
155
      GPM,
156
      IBC,
157
      NUM,
158
    };
159
160
    double        cost;
161
    std::array<MvField[3], 2>
162
                  mvField;
163
    int           mergeIdx;
164
    uint8_t       bcwIdx;
165
    uint8_t       interDir;
166
    bool          useAltHpelIf;
167
    int8_t        affineType;
168
    int8_t        numCiipIntra;
169
170
    bool          noResidual;
171
    bool          noBdofRefine;
172
173
    bool          lumaPredReady;
174
    bool          chromaPredReady;
175
176
    MergeItemType mergeItemType;
177
178
    MergeItem();
179
    ~MergeItem();
180
181
    void          create          (ChromaFormat chromaFormat, const Area& area);
182
    void          init            ();
183
    void          importMergeInfo (const MergeCtx&       mergeCtx, int _mergeIdx, MergeItemType _mergeItemType, CodingUnit& cu);
184
    void          importMergeInfo (const AffineMergeCtx& mergeCtx, int _mergeIdx, MergeItemType _mergeItemType, CodingUnit& cu);
185
    bool          exportMergeInfo (CodingUnit& cu, bool forceNoResidual) const;
186
0
    PelUnitBuf    getPredBuf      (const UnitArea& unitArea) { return m_pelStorage.getCompactBuf( unitArea ); }
187
0
    CMotionBuf    getMvBuf        (const UnitArea &unitArea) const { return CMotionBuf( m_mvStorage.data(), g_miScaling.scale( unitArea.lumaSize() ) ); }
188
0
    MotionBuf     getMvBuf        (const UnitArea &unitArea)       { return  MotionBuf( m_mvStorage.data(), g_miScaling.scale( unitArea.lumaSize() ) ); }
189
190
    static int getGpmUnfiedIndex( int splitDir, const MergeIdxPair &geoMergeIdx )
191
0
    {
192
0
      return ( splitDir << 8 ) | ( geoMergeIdx[ 0 ] << 4 ) | geoMergeIdx[ 1 ];
193
0
    }
194
195
    static void updateGpmIdx( int mergeIdx, uint8_t &splitDir, MergeIdxPair &geoMergeIdx )
196
0
    {
197
0
      splitDir       = ( mergeIdx >> 8 ) & 0xFF;
198
0
      geoMergeIdx[0] = ( mergeIdx >> 4 ) & 0xF;
199
0
      geoMergeIdx[1] =   mergeIdx        & 0xF;
200
0
    }
201
  };
202
203
  class MergeItemList
204
  {
205
  private:
206
    std::vector<MergeItem*>  m_mergeItems;
207
    std::vector<MergeItem*>  m_list;
208
    size_t                   m_maxTrackingNum = 0;
209
    size_t                   m_maxSize;
210
    size_t                   m_maxExtSize;
211
    size_t                   m_numExt;
212
213
  public:
214
    MergeItemList();
215
    ~MergeItemList();
216
217
    void          init                  (size_t maxListSize, size_t maxExtSize, ChromaFormat chromaFormat, SizeType ctuWidth, SizeType ctuHeight);
218
    MergeItem*    allocateNewMergeItem  ();
219
    bool          insertMergeItemToList (MergeItem* p);
220
    void          giveBackMergeItem     (MergeItem* p);
221
    void          resetList             (size_t maxTrackingNum);
222
    void          shrinkList            (size_t reduceTo);
223
    MergeItem*    getMergeItemInList    (size_t index);
224
0
    size_t        size                  () const { return m_list.size(); }
225
0
    size_t        capacity              () const { return m_maxTrackingNum; }
226
  };
227
228
using MergeBufVector = static_vector<PelUnitBuf, MRG_MAX_NUM_CANDS>;
229
230
/// CU encoder class
231
class EncCu
232
  : DecCu
233
{
234
private:
235
  struct CtxPair
236
  {
237
    Ctx start;
238
    Ctx best;
239
  };
240
241
  std::vector<CtxPair>  m_CtxBuffer;
242
  CtxPair*              m_CurrCtx;
243
  CtxCache*             m_CtxCache;
244
245
  //  Data : encoder control
246
247
  static const int maxCuDepth = ( MAX_CU_SIZE_IDX - MIN_CU_LOG2 ) << 1;
248
249
  int                   m_cuChromaQpOffsetIdxPlus1;
250
  int                   m_tempQpDiff;
251
  std::vector<int>*     m_globalCtuQpVector;
252
  XUCache               m_unitCache;
253
  std::mutex*           m_wppMutex;
254
  CodingStructure*      m_pTempCS[maxCuDepth];
255
  CodingStructure*      m_pBestCS[maxCuDepth];
256
  CodingStructure*      m_pTempCS2;
257
  CodingStructure*      m_pBestCS2;
258
  PelStorage            m_pOrgBuffer[maxCuDepth];
259
  PelStorage            m_pRspBuffer[maxCuDepth];
260
261
  //  Access channel
262
  const VVEncCfg*       m_pcEncCfg;
263
  IntraSearch           m_cIntraSearch;
264
  InterSearch           m_cInterSearch;
265
  RdCost                m_cRdCost;
266
  LoopFilter            m_cLoopFilter;
267
268
  CABACWriter*          m_CABACEstimator;
269
  EncModeCtrl           m_modeCtrl;
270
  TrQuant               m_cTrQuant;                          ///< transform & quantization
271
  RateCtrl*             m_pcRateCtrl;
272
273
  PelStorage            m_aTmpStorageLCU  [MAX_TMP_BUFS];     ///< used with CIIP, EDO, GEO
274
  PelStorage            m_acMergeTmpBuffer[MRG_MAX_NUM_CANDS];
275
276
  SortedPelUnitBufs<SORTED_BUFS>
277
                        m_SortedPelUnitBufs;
278
  FastGeoCostList       m_GeoCostList;
279
  static const MergeIdxPair
280
                        m_GeoModeTest[GEO_MAX_NUM_CANDS];
281
  double                m_mergeBestSATDCost;
282
283
  MotionInfo            m_subPuMiBuf[(MAX_CU_SIZE * MAX_CU_SIZE) >> (MIN_CU_LOG2 << 1)];
284
  
285
  Mv                    m_refinedMvdL0[MRG_MAX_NUM_CANDS][MAX_NUM_SUBCU_DMVR];
286
287
  double                m_sbtCostSave[2];
288
  // thread stuff
289
  Ctx*                  m_syncPicCtx;                        ///< context storage for state of contexts at the wavefront/WPP/entropy-coding-sync second CTU of tile-row used for estimation
290
  PelStorage            m_dbBuffer;
291
  
292
  Partitioner           m_partitioner;
293
294
  int                   m_bestBcwIdx[2];
295
  double                m_bestBcwCost[2];
296
297
  int                   m_MergeSimpleFlag;
298
  int                   m_tileIdx;
299
  int                   m_EDO;
300
301
  GeoComboCostList      m_comboList;
302
  MergeItemList         m_mergeItemList;
303
  std::array<Mv, MAX_NUM_SUBCU_DMVR>
304
                        m_subPuMvOffset[MRG_MAX_NUM_CANDS];
305
  Distortion            m_uiSadBestForQPA;
306
307
  static const double coefSquareCUsFasterFastMedium[2][5][2][2][2];
308
  static const double coefSquareCUsSlowSlower[2][5][2][5][2][2][2];
309
310
public:
311
  EncCu();
312
  virtual ~EncCu();
313
314
  void  init                  ( const VVEncCfg& encCfg, const SPS& sps, std::vector<int>* const globalCtuQpVector, Ctx* syncPicCtx, RateCtrl* pRateCtrl );
315
  void  setCtuEncRsrc         ( CABACWriter* cabacEstimator, CtxCache* ctxCache, ReuseUniMv* pReuseUniMv, BlkUniMvInfoBuffer* pBlkUniMvInfoBuffer, AffineProfList* pAffineProfList, IbcBvCand* pCachedBvs );
316
  void  destroy               ();
317
318
0
  std::vector<int>* getQpPtr  () const { return m_globalCtuQpVector; }
319
320
  void  initPic               ( Picture* pic );
321
  void  initSlice             ( const Slice* slice );
322
  void  setUpLambda           ( Slice& slice, const double dLambda, const int iQP, const bool setSliceLambda, const bool saveUnadjusted);
323
  void  updateLambda          ( const Slice& slice, const double ctuLambda, const int ctuQP, const int newQP, const bool saveUnadjusted);
324
325
  void encodeCtu              ( Picture* pic, int (&prevQP)[MAX_NUM_CH], uint32_t ctuXPosInCtus, uint32_t ctuYPosInCtus );
326
327
private:
328
  void  xCompressCtu          ( CodingStructure& cs, const UnitArea& area, const unsigned ctuRsAddr, const int prevQP[] );
329
330
  void xCalDebCost            ( CodingStructure& cs, Partitioner& partitioner );
331
  Distortion xGetDistortionDb ( CodingStructure& cs, CPelBuf& org, CPelBuf& reco, const CompArea& compArea, bool beforeDb );
332
333
  void xCompressCU            ( CodingStructure*& tempCS, CodingStructure*& bestCS, Partitioner& pm );
334
  bool xCheckBestMode         ( CodingStructure*& tempCS, CodingStructure*& bestCS, Partitioner& pm, const EncTestMode& encTestmode, const bool useEDO = false );
335
336
  void xCheckRDCostIntra      ( CodingStructure*& tempCS, CodingStructure*& bestCS, Partitioner& pm, const EncTestMode& encTestMode );
337
  void xCheckRDCostInter      ( CodingStructure*& tempCS, CodingStructure*& bestCS, Partitioner& pm, const EncTestMode& encTestMode );
338
  void xCheckRDCostInterIMV   ( CodingStructure*& tempCS, CodingStructure*& bestCS, Partitioner& pm, const EncTestMode& encTestMode );
339
  void xCheckRDCostUnifiedMerge
340
                              ( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &pm,       EncTestMode& encTestMode );
341
  void xCheckModeSplit        ( CodingStructure*& tempCS, CodingStructure*& bestCS, Partitioner& pm, const EncTestMode& encTestMode );
342
  void xCheckModeSplitInternal( CodingStructure*& tempCS, CodingStructure*& bestCS, Partitioner& pm, const EncTestMode& encTestMode, const ModeType modeTypeParent, bool& skipInterPass );
343
  void xReuseCachedResult     ( CodingStructure*& tempCS, CodingStructure*& bestCS, Partitioner& pm );
344
345
  void xCheckDQP              ( CodingStructure& cs, Partitioner& partitioner, bool bKeepCtx = false);
346
  void xEncodeDontSplit       ( CodingStructure& cs, Partitioner& partitioner);
347
348
  void xEncodeInterResidual   ( CodingStructure*& tempCS, CodingStructure*& bestCS, Partitioner& pm, const EncTestMode& encTestMode, 
349
                                int residualPass = 0, bool* bestHasNonResi = NULL, double* equBcwCost = NULL );
350
351
  bool xIsBcwSkip( const CodingUnit& cu )
352
0
  {
353
0
    if( cu.slice->sliceType != VVENC_B_SLICE )
354
0
    {
355
0
      return true;
356
0
    }
357
0
    return( (m_pcEncCfg->m_QP > 32) && ((cu.slice->TLayer >= 4)
358
0
            || ((cu.refIdx[0] >= 0 && cu.refIdx[1] >= 0)
359
0
              && (  abs(cu.slice->poc - cu.slice->getRefPOC(REF_PIC_LIST_0, cu.refIdx[0])) == 1
360
0
                ||  abs(cu.slice->poc - cu.slice->getRefPOC(REF_PIC_LIST_1, cu.refIdx[1])) == 1
361
0
               ) )                     ));
362
0
  }
363
364
  uint64_t xCalcPuMeBits                 ( const CodingUnit& cu);
365
  double   xCalcDistortion               ( CodingStructure *&cur_CS, ChannelType chType, int BitDepth, int imv);
366
  int      xCheckMMVDCand                ( MmvdIdx& mmvdMergeCand, int& bestDir, int tempNum, double& bestCostOffset, double& bestCostMerge, double bestCostList );
367
  void     xCheckRDCostIBCMode           ( CodingStructure*& tempCS, CodingStructure*& bestCS, Partitioner& pm, const EncTestMode& encTestMode );
368
  void     xCheckRDCostIBCModeMerge2Nx2N ( CodingStructure*& tempCS, CodingStructure*& bestCS, Partitioner& partitioner, const EncTestMode& encTestMode );
369
370
371
  CodingUnit* getCuForInterPrediction ( CodingStructure* cs, const EncTestMode& encTestMode );
372
  unsigned int updateRdCheckingNum    ( MergeItemList&, double threshold, unsigned int numMergeSatdCand );
373
374
  void    generateMergePrediction     ( const UnitArea& unitArea, MergeItem* mergeItem, CodingUnit& cu, bool luma, bool chroma,
375
                                        PelUnitBuf& dstBuf, bool finalRd, bool forceNoResidual, PelUnitBuf* predBuf1, PelUnitBuf* predBuf2 );
376
  double  calcLumaCost4MergePrediction( const TempCtx& ctxStart, const PelUnitBuf& predBuf, double lambda, CodingUnit& pu, DistParam& distParam );
377
  void    addRegularCandsToPruningList( const MergeCtx& mergeCtx, const UnitArea& localUnitArea, double sqrtLambdaForFirstPassIntra,
378
                                        const TempCtx& ctxStart, DistParam& distParam, CodingUnit& cu, bool* sameMv, MergeBufVector& regularPred );
379
  void    addCiipCandsToPruningList   ( const MergeCtx& mergeCtx, const UnitArea& localUnitArea, double sqrtLambdaForFirstPassIntra,
380
                                        const TempCtx& ctxStart, DistParam& distParam, CodingUnit& cu, bool* sameMv );
381
  void    addMmvdCandsToPruningList   ( const MergeCtx& mergeCtx, const UnitArea& localUnitArea, double sqrtLambdaForFirstPassIntra,
382
                                        const TempCtx& ctxStart, DistParam& distParam, CodingUnit& cu );
383
  void    addAffineCandsToPruningList ( AffineMergeCtx& affineMergeCtx, const UnitArea& localUnitArea, double sqrtLambdaForFirstPass,
384
                                        const TempCtx& ctxStart, DistParam& distParam, CodingUnit& cu );
385
  void    addGpmCandsToPruningList    ( const MergeCtx& mergeCtx, const UnitArea& localUnitArea, double sqrtLambdaForFirstPass,
386
                                        const TempCtx& ctxStart, const GeoComboCostList& comboList, MergeBufVector& geoBuffer, DistParam& distParam, CodingUnit& cu );
387
388
  bool    prepareGpmComboList         ( const MergeCtx& mergeCtx, const UnitArea& localUnitArea, double sqrtLambdaForFirstPass,
389
                                        GeoComboCostList& comboList, MergeBufVector& geoBuffer, CodingUnit& cu );
390
  // TODO: for now skip that
391
  //void    checkEarlySkip              ( const CodingStructure* bestCS, const Partitioner &partitioner );
392
};
393
394
} // namespace vvenc
395
396
//! \}
397