Coverage Report

Created: 2026-04-01 07:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/vvenc/source/Lib/CommonLib/DepQuant.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
#pragma once
43
44
#include "CommonDef.h"
45
#include "Contexts.h"
46
#include "Slice.h"
47
#include "Unit.h"
48
#include "UnitPartitioner.h"
49
#include "QuantRDOQ2.h"
50
51
//! \ingroup CommonLib
52
//! \{
53
54
namespace vvenc {
55
56
namespace DQIntern
57
{
58
  /*================================================================================*/
59
  /*=====                                                                      =====*/
60
  /*=====   R A T E   E S T I M A T O R                                        =====*/
61
  /*=====                                                                      =====*/
62
  /*================================================================================*/
63
64
  struct NbInfoSbb
65
  {
66
    uint8_t   numInv;
67
    uint8_t   invInPos[5];
68
  };
69
  struct NbInfoOut
70
  {
71
    uint16_t  maxDist;
72
    uint16_t  num;
73
    uint16_t  outPos[5];
74
  };
75
  struct CoeffFracBits
76
  {
77
    int32_t   bits[6];
78
  };
79
80
  enum ScanPosType : int8_t { SCAN_ISCSBB = 0, SCAN_SOCSBB = 1, SCAN_EOCSBB = 2 };
81
82
  struct ScanInfo
83
  {
84
0
    ScanInfo() {}
85
    short         numSbb;
86
    short         scanIdx;
87
    short         rasterPos;
88
    short         sbbPos; // byte
89
    short         nextSbbRight;
90
    short         nextSbbBelow;
91
    int8_t        sbbSize;
92
    int8_t        insidePos;
93
    int8_t        nextInsidePos;
94
    ScanPosType   spt;
95
    int8_t        posX;
96
    int8_t        posY;
97
    int8_t        sigCtxOffsetNext;
98
    int8_t        gtxCtxOffsetNext;
99
    NbInfoSbb     currNbInfoSbb;
100
  };
101
102
  class Rom;
103
  struct TUParameters
104
  {
105
    TUParameters ( const Rom& rom, const unsigned width, const unsigned height, const ChannelType chType );
106
    ~TUParameters()
107
0
    {
108
0
      delete [] m_scanInfo;
109
0
    }
110
111
    ChannelType       m_chType;
112
    unsigned          m_width;
113
    unsigned          m_height;
114
    unsigned          m_numCoeff;
115
    unsigned          m_numSbb;
116
    unsigned          m_log2SbbWidth;
117
    unsigned          m_log2SbbHeight;
118
    unsigned          m_log2SbbSize;
119
    unsigned          m_sbbSize;
120
    unsigned          m_sbbMask;
121
    unsigned          m_widthInSbb;
122
    unsigned          m_heightInSbb;
123
    const ScanElement *m_scanSbbId2SbbPos;
124
    const ScanElement *m_scanId2BlkPos;
125
    const NbInfoSbb*  m_scanId2NbInfoSbb;
126
    const NbInfoOut*  m_scanId2NbInfoOut;
127
    ScanInfo*         m_scanInfo;
128
  private:
129
    void xSetScanInfo( ScanInfo& scanInfo, int scanIdx );
130
  };
131
132
  class Rom
133
  {
134
  public:
135
0
    Rom() : m_scansInitialized(false) {}
136
0
    ~Rom() { xUninitScanArrays(); }
137
0
    void                init        ()                       { xInitScanArrays(); }
138
0
    const NbInfoSbb*    getNbInfoSbb( int hd, int vd ) const { return m_scanId2NbInfoSbbArray[hd][vd]; }
139
0
    const NbInfoOut*    getNbInfoOut( int hd, int vd ) const { return m_scanId2NbInfoOutArray[hd][vd]; }
140
    const TUParameters* getTUPars   ( const CompArea& area, const ComponentID compID ) const
141
0
    {
142
0
      return m_tuParameters[Log2(area.width)][Log2(area.height)][toChannelType(compID)];
143
0
    }
144
  private:
145
    void  xInitScanArrays   ();
146
    void  xUninitScanArrays ();
147
  private:
148
    bool          m_scansInitialized;
149
    NbInfoSbb*    m_scanId2NbInfoSbbArray[ MAX_TU_SIZE_IDX ][ MAX_TU_SIZE_IDX ];
150
    NbInfoOut*    m_scanId2NbInfoOutArray[ MAX_TU_SIZE_IDX ][ MAX_TU_SIZE_IDX ];
151
    TUParameters* m_tuParameters         [ MAX_TU_SIZE_IDX ][ MAX_TU_SIZE_IDX ][ MAX_NUM_CH ];
152
  };
153
154
  class RateEstimator
155
  {
156
  public:
157
0
    RateEstimator () {}
158
0
    ~RateEstimator() {}
159
    void initCtx  ( const TUParameters& tuPars, const TransformUnit& tu, const ComponentID compID, const FracBitsAccess& fracBitsAccess );
160
161
0
    inline const BinFracBits *sigSbbFracBits() const { return m_sigSbbFracBits; }
162
    inline const BinFracBits *sigFlagBits(unsigned stateId) const
163
0
    {
164
0
      return m_sigFracBits[std::max(((int) stateId) - 1, 0)];
165
0
    }
166
0
    inline const CoeffFracBits *gtxFracBits() const { return m_gtxFracBits; }
167
    inline int32_t              lastOffset(unsigned scanIdx) const
168
0
    {
169
0
      return m_lastBitsX[m_scanId2Pos[scanIdx].x] + m_lastBitsY[m_scanId2Pos[scanIdx].y];
170
0
    }
171
172
  private:
173
    void  xSetLastCoeffOffset ( const FracBitsAccess& fracBitsAccess, const TUParameters& tuPars, const TransformUnit& tu, const ComponentID compID );
174
    void  xSetSigSbbFracBits  ( const FracBitsAccess& fracBitsAccess, ChannelType chType );
175
    void  xSetSigFlagBits     ( const FracBitsAccess& fracBitsAccess, ChannelType chType );
176
    void  xSetGtxFlagBits     ( const FracBitsAccess& fracBitsAccess, ChannelType chType );
177
178
  public:
179
    static const unsigned sm_numCtxSetsSig    = 3;
180
    static const unsigned sm_numCtxSetsGtx    = 2;
181
    static const unsigned sm_maxNumSigSbbCtx  = 2;
182
    static const unsigned sm_maxNumSigCtx     = 12;
183
    static const unsigned sm_maxNumGtxCtx     = 21;
184
185
  private:
186
    const ScanElement * m_scanId2Pos;
187
    int32_t             m_lastBitsX      [ MAX_TB_SIZEY ];
188
    int32_t             m_lastBitsY      [ MAX_TB_SIZEY ];
189
    BinFracBits         m_sigSbbFracBits [ sm_maxNumSigSbbCtx ];
190
    BinFracBits         m_sigFracBits    [ sm_numCtxSetsSig   ][ sm_maxNumSigCtx ];
191
    CoeffFracBits       m_gtxFracBits                          [ sm_maxNumGtxCtx ];
192
  };
193
194
  /*================================================================================*/
195
  /*=====                                                                      =====*/
196
  /*=====   P R E - Q U A N T I Z E R                                          =====*/
197
  /*=====                                                                      =====*/
198
  /*================================================================================*/
199
200
  struct PQData
201
  {
202
    TCoeff  absLevel;
203
    int64_t deltaDist;
204
  };
205
206
  class Quantizer
207
  {
208
  public:
209
0
    Quantizer() {}
210
0
    void   init            ( int dqThrVal ) { m_DqThrVal = dqThrVal; }
211
    void   dequantBlock    ( const TransformUnit& tu, const ComponentID compID, const QpParam& cQP, CoeffBuf& recCoeff, bool enableScalingLists, int* piDequantCoef ) const;
212
    void   initQuantBlock  ( const TransformUnit& tu, const ComponentID compID, const QpParam& cQP, const double lambda, int gValue = -1 );
213
    bool   preQuantCoeff   ( const TCoeff absCoeff, PQData *pqData, int quanCoeff ) const;
214
0
    TCoeff getLastThreshold() const { return m_thresLast; }
215
0
    TCoeff getSSbbThreshold() const { return m_thresSSbb; }
216
217
0
    int64_t getQScale      () const { return m_QScale; }
218
219
    // quantization
220
    int               m_DqThrVal;
221
    int               m_QShift;
222
    int64_t           m_QAdd;
223
    int64_t           m_QScale;
224
    TCoeff            m_maxQIdx;
225
    TCoeff            m_thresLast;
226
    TCoeff            m_thresSSbb;
227
    // distortion normalization
228
    int               m_DistShift;
229
    int64_t           m_DistAdd;
230
    int64_t           m_DistStepAdd;
231
    int64_t           m_DistOrgFact;
232
  };
233
234
0
#define RICEMAX 32
235
  extern const int32_t g_goRiceBits[4][RICEMAX];
236
237
  /*================================================================================*/
238
  /*=====                                                                      =====*/
239
  /*=====   T C Q   S T A T E                                                  =====*/
240
  /*=====                                                                      =====*/
241
  /*================================================================================*/
242
243
  struct StateMem;
244
245
  struct SbbCtx
246
  {
247
    uint8_t* sbbFlags;
248
    uint8_t* levels;
249
  };
250
251
  class CommonCtx
252
  {
253
  friend class DepQuant;
254
255
  public:
256
0
    CommonCtx() : m_currSbbCtx( m_allSbbCtx ), m_prevSbbCtx( m_currSbbCtx + 4 ) {}
257
258
0
    inline void swap() { std::swap( m_currSbbCtx, m_prevSbbCtx ); }
259
260
    inline void reset( const TUParameters& tuPars, const RateEstimator& rateEst )
261
0
    {
262
0
      m_nbInfo = tuPars.m_scanId2NbInfoOut;
263
0
      ::memcpy( m_sbbFlagBits, rateEst.sigSbbFracBits(), 2 * sizeof( BinFracBits ) );
264
0
      const int numSbb = tuPars.m_numSbb;
265
0
      const int chunkSize = numSbb + tuPars.m_numCoeff;
266
0
      uint8_t* nextMem = m_memory;
267
0
      for( int k = 0; k < 8; k++, nextMem += chunkSize )
268
0
      {
269
0
        m_allSbbCtx[k].sbbFlags = nextMem;
270
0
        m_allSbbCtx[k].levels = nextMem + numSbb;
271
0
      }
272
0
    }
273
274
    void update( const ScanInfo& scanInfo, const int prevId, int stateId, StateMem& curr );
275
276
    void getLevelPtrs( const ScanInfo& scanInfo, uint8_t*& levels0, uint8_t*& levels1, uint8_t*& levels2, uint8_t*& levels3 )
277
0
    {
278
0
      levels0 = m_currSbbCtx[0].levels + scanInfo.scanIdx;
279
0
      levels1 = m_currSbbCtx[1].levels + scanInfo.scanIdx;
280
0
      levels2 = m_currSbbCtx[2].levels + scanInfo.scanIdx;
281
0
      levels3 = m_currSbbCtx[3].levels + scanInfo.scanIdx;
282
0
    }
283
284
  private:
285
    const NbInfoOut* m_nbInfo;
286
    BinFracBits      m_sbbFlagBits[2];
287
    SbbCtx           m_allSbbCtx[8];
288
    SbbCtx*          m_currSbbCtx;
289
    SbbCtx*          m_prevSbbCtx;
290
    uint8_t          m_memory[8 * ( MAX_TB_SIZEY * MAX_TB_SIZEY + MLS_GRP_NUM )];
291
  };
292
293
  static constexpr int64_t rdCostInit = std::numeric_limits<int64_t>::max() >> 1;
294
295
  struct Decisions
296
  {
297
    int64_t   rdCost[4];
298
    TCoeffSig absLevel[4];
299
    int8_t    prevId[4];
300
  };
301
302
  struct StateMem
303
  {
304
    int64_t  rdCost[4];
305
    int16_t  remRegBins[4];
306
    int32_t  sbbBits0[4];
307
    int32_t  sbbBits1[4];
308
309
    uint8_t tplAcc[16][4];
310
    uint8_t sum1st[16][4];
311
    uint8_t absVal[16][4];
312
313
    struct
314
    {
315
      uint8_t sig[4];
316
      uint8_t cff[4];
317
    } ctx;
318
319
    uint8_t  numSig[4];
320
    int8_t   refSbbCtxId[4];
321
322
    int32_t  cffBits1[RateEstimator::sm_maxNumGtxCtx + 3];
323
324
    int8_t   m_goRicePar[4];
325
    int8_t   m_goRiceZero[4];
326
    const BinFracBits* m_sigFracBitsArray[4];
327
    const CoeffFracBits* m_gtxFracBitsArray;
328
329
    int      cffBitsCtxOffset;
330
    bool     anyRemRegBinsLt4;
331
    int      initRemRegBins;
332
  };
333
334
  static constexpr size_t StateMemSkipCpySize = offsetof( StateMem, sbbBits1 );
335
}
336
337
class DepQuant : public QuantRDOQ2, DQIntern::RateEstimator
338
{
339
public:
340
  DepQuant( const Quant* other, bool enc, bool useScalingLists );
341
  virtual ~DepQuant();
342
343
  virtual void quant  (       TransformUnit& tu, const ComponentID compID, const CCoeffBuf& pSrc, TCoeff &uiAbsSum, const QpParam& cQP, const Ctx& ctx );
344
  virtual void dequant( const TransformUnit& tu, CoeffBuf& dstCoeff, const ComponentID compID, const QpParam& cQP );
345
  
346
  virtual void init   ( int rdoq = 0, bool useRDOQTS = false, int dqThrVal = 8 );
347
348
private:
349
  void    xQuantDQ          ( TransformUnit& tu, const CCoeffBuf& srcCoeff, const ComponentID compID, const QpParam& cQP, const double lambda, const Ctx& ctx, TCoeff& absSum, bool enableScalingLists, int* quantCoeff );
350
  void    xDequantDQ        ( const TransformUnit& tu, CoeffBuf& recCoeff, const ComponentID compID, const QpParam& cQP, bool enableScalingLists, int* quantCoeff );
351
  void    xDecideAndUpdate  ( const TCoeff absCoeff, const DQIntern::ScanInfo& scanInfo, bool zeroOut, int quantCoeff);
352
  void    xDecide           ( const DQIntern::ScanInfo &scanInfo, const TCoeff absCoeff, const int lastOffset, DQIntern::Decisions &decisions, bool zeroOut, int quantCoeff );
353
354
  DQIntern::CommonCtx m_commonCtx;
355
  std::shared_ptr<DQIntern::Rom>
356
                      m_scansRom;
357
  DQIntern::Quantizer m_quant;
358
359
  DQIntern::Decisions m_trellis[MAX_TB_SIZEY * MAX_TB_SIZEY][2];
360
  DQIntern::StateMem  m_state_curr;
361
  DQIntern::StateMem  m_state_skip;
362
363
  // has to be called as a first check, assumes no decision has been made yet!!!
364
  void( *m_checkAllRdCosts )( const DQIntern::ScanPosType spt, const DQIntern::PQData* pqData, DQIntern::Decisions& decisions, const DQIntern::StateMem& state );
365
  // has to be called as a first check, assumes no decision has been made yet!!!
366
  void( *m_checkAllRdCostsOdd1 )( const DQIntern::ScanPosType spt, const int64_t pq_a_dist, const int64_t pq_b_dist, DQIntern::Decisions& decisions, const DQIntern::StateMem& state );
367
  void( *m_updateStatesEOS )( const DQIntern::ScanInfo& scanInfo, const DQIntern::Decisions& decisions, const DQIntern::StateMem& skip, DQIntern::StateMem& curr, DQIntern::CommonCtx& commonCtx );
368
  void( *m_updateStates )( const DQIntern::ScanInfo& scanInfo, const DQIntern::Decisions& decisions, DQIntern::StateMem& curr );
369
  void( *m_findFirstPos )( int& firstTestPos, const TCoeff* tCoeff, const DQIntern::TUParameters& tuPars, int defaultTh, bool zeroOutForThres, int zeroOutWidth, int zeroOutHeight );
370
371
#if defined(TARGET_SIMD_X86)  && ENABLE_SIMD_OPT_QUANT
372
  void initDepQuantX86();
373
  template <X86_VEXT vext>
374
  void _initDepQuantX86();
375
#endif
376
};
377
378
} // namespace vvenc
379
380
//! \}
381