Coverage Report

Created: 2026-10-28 06:18

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/work/vvdec/source/Lib/CommonLib/Contexts.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) 2018-2026, Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. & The VVdeC 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
/** \file     Contexts.h
44
 *  \brief    Classes providing probability descriptions and contexts (header)
45
 */
46
47
#pragma once
48
49
#include "CommonDef.h"
50
51
#include <array>
52
#include <vector>
53
54
namespace vvdec
55
{
56
57
static constexpr int     PROB_BITS   = 15;   // Nominal number of bits to represent probabilities
58
static constexpr int     PROB_BITS_0 = 10;   // Number of bits to represent 1st estimate
59
static constexpr int     PROB_BITS_1 = 14;   // Number of bits to represent 2nd estimate
60
static constexpr int     MASK_0      = ~(~0u << PROB_BITS_0) << (PROB_BITS - PROB_BITS_0);
61
static constexpr int     MASK_1      = ~(~0u << PROB_BITS_1) << (PROB_BITS - PROB_BITS_1);
62
static constexpr uint8_t DWS         = 8;   // 0x47 Default window sizes
63
static constexpr uint8_t CNU         = 35;
64
65
class ProbModelTables
66
{
67
protected:
68
  static const uint8_t      m_RenormTable_32  [ 32];          // Std         MP   MPI
69
};
70
71
class BinProbModel : public ProbModelTables
72
{
73
public:
74
  BinProbModel()
75
5.69M
  {
76
5.69M
    uint16_t half = 1 << (PROB_BITS - 1);
77
5.69M
    m_state[0]    = half;
78
5.69M
    m_state[1]    = half;
79
5.69M
    m_rate0 = 0;
80
5.69M
    m_rate1 = DWS;
81
5.69M
    m_delta0[0] = ((0xFFFFU) >> (16 - m_rate0));
82
5.69M
    m_delta0[1] = ((0xFFFFU) >> (16 - PROB_BITS));
83
5.69M
    m_delta1[0] = ((0xFFFFU) >> (16 - m_rate1));
84
5.69M
    m_delta1[1] = ((0xFFFFU) >> (16 - PROB_BITS));
85
5.69M
  }
86
5.69M
  ~BinProbModel() {}
87
public:
88
  void            init              ( int qp, int initId );
89
  void update(unsigned bin)
90
0
  {
91
0
//    m_state[0] -= (m_state[0] >> m_rate0) & MASK_0;
92
0
//    m_state[1] -= (m_state[1] >> m_rate1) & MASK_1;
93
0
//    m_state[0] += ( ( bin ? 0x7fffu : 0x0u ) >> m_rate0 ) & MASK_0;
94
0
//    m_state[1] += ( ( bin ? 0x7fffu : 0x0u ) >> m_rate1 ) & MASK_1;
95
0
    int delta0 = m_delta0[bin] - m_state[0];
96
0
    int delta1 = m_delta1[bin] - m_state[1];
97
0
    delta0 = delta0 >> m_rate0;
98
0
    delta1 = delta1 >> m_rate1;
99
0
    m_state[0] += delta0 *(1<< 5);
100
0
    m_state[1] += delta1 *2;
101
0
  }
102
  // Variant taking the pre-update state already loaded by lpsmps(). decodeBin() calls
103
  // m_Bitstream->readByteFlag() between lpsmps() and update(); m_Bitstream is a non-restrict
104
  // pointer the compiler must assume may alias m_state, forcing a reload of m_state[0]/[1] here.
105
  // Passing the cached values avoids that reload. Arithmetically identical (s0==m_state[0],
106
  // s1==m_state[1] at this point), hence bit-exact.
107
  void update( unsigned bin, unsigned s0, unsigned s1 )
108
0
  {
109
0
    int delta0 = m_delta0[bin] - (int)s0;
110
0
    int delta1 = m_delta1[bin] - (int)s1;
111
0
    delta0 = delta0 >> m_rate0;
112
0
    delta1 = delta1 >> m_rate1;
113
0
    m_state[0] = (uint16_t)( s0 + delta0 * ( 1 << 5 ) );
114
0
    m_state[1] = (uint16_t)( s1 + delta1 * 2 );
115
0
  }
116
  void setLog2WindowSize(uint8_t log2WindowSize)
117
0
  {
118
0
    m_rate0 = 2 + ((log2WindowSize >> 2) & 3);
119
0
    m_rate1 = 3 + m_rate0 + (log2WindowSize & 3);
120
0
    CHECK(m_rate1 > 9, "Second window size is too large!");
121
0
    m_rate0 += 5;
122
0
    m_rate1 += 1;
123
0
    m_delta0[0] = ((0xFFFFU) >> (16 - m_rate0));
124
0
    m_delta1[0] = ((0xFFFFU) >> (16 - m_rate1));
125
0
  }
126
public:
127
0
  uint8_t state() const { return (m_state[0] + m_state[1]) >> 8; }
128
0
  uint8_t mps() const { return state() >> 7; }
129
  uint8_t lps( unsigned range ) const
130
0
  {
131
0
    uint16_t q = state();
132
0
    if (q & 0x80)
133
0
      q = q ^ 0xff;
134
0
    return ((q >> 2) * (range >> 5) >> 1) + 4;
135
0
  }
136
  void lpsmps( unsigned range, unsigned& lps, unsigned& bin ) const
137
0
  {
138
0
    const uint16_t q = (m_state[0] + m_state[1]) >> 8;
139
0
    bin = q >> 7;
140
0
    
141
0
    lps = ((((q ^ (-static_cast<int>(bin) & 0xff)) >> 2) * (range >> 5)) >> 1) + 4;
142
0
143
0
    //if( q & 0x80 )
144
0
    //{
145
0
    //  CHECK( lps != ( ( ( ( q ^ 0xff ) >> 2 ) * ( range >> 5 ) >> 1 ) + 4 ), "" );
146
0
    //  lps = ( ( ( q ^ 0xff ) >> 2 ) * ( range >> 5 ) >> 1 ) + 4;
147
0
    //}
148
0
    //else
149
0
    //{
150
0
    //  CHECK( lps != ( ( ( q >> 2 ) * ( range >> 5 ) >> 1 ) + 4 ), "" );
151
0
    //  lps = ( ( q >> 2 ) * ( range >> 5 ) >> 1 ) + 4;
152
0
    //}
153
0
  }
154
  // Variant that also returns the raw state halves so the caller can feed them to
155
  // update(bin,s0,s1), avoiding the aliasing-forced reload of m_state[] in update().
156
  void lpsmps( unsigned range, unsigned& lps, unsigned& bin, unsigned& s0, unsigned& s1 ) const
157
0
  {
158
0
    s0 = m_state[0];
159
0
    s1 = m_state[1];
160
0
    const uint16_t q = ( s0 + s1 ) >> 8;
161
0
    bin = q >> 7;
162
0
    lps = ((((q ^ (-static_cast<int>(bin) & 0xff)) >> 2) * (range >> 5)) >> 1) + 4;
163
0
  }
164
0
  static uint8_t  getRenormBitsLPS  ( unsigned LPS )                    { return    m_RenormTable_32  [LPS>>3]; }
165
0
  static uint8_t  getRenormBitsRange( unsigned range )                  { return    1; }
166
private:
167
  uint16_t m_state[2];
168
  uint16_t m_rate0;
169
  uint16_t m_rate1;
170
  uint16_t m_delta0[2];
171
  uint16_t m_delta1[2];
172
};
173
174
175
class CtxSet
176
{
177
public:
178
1.14k
  CtxSet( uint16_t offset, uint16_t size ) : Offset( offset ), Size( size ) {}
179
  CtxSet( std::initializer_list<CtxSet> ctxSets );
180
181
  uint16_t operator()() const
182
0
  {
183
0
    return Offset;
184
0
  }
185
  uint16_t operator()( uint16_t inc ) const
186
0
  {
187
0
    CHECKD( inc >= Size, "Specified context increment (" << inc << ") exceed range of context set [0;" << Size - 1 << "]." );
188
189
0
    return Offset + inc;
190
0
  }
191
192
private:
193
  uint16_t Offset;
194
  uint16_t Size;
195
};
196
197
198
class ContextSetCfg
199
{
200
public:
201
  // context sets: specify offset and size
202
  static const CtxSet   SplitFlag;
203
  static const CtxSet   SplitQtFlag;
204
  static const CtxSet   SplitHvFlag;
205
  static const CtxSet   Split12Flag;
206
  static const CtxSet   ModeConsFlag;
207
  static const CtxSet   SkipFlag;
208
  static const CtxSet   MergeFlag;
209
  static const CtxSet   RegularMergeFlag;
210
  static const CtxSet   MergeIdx;
211
  static const CtxSet   PredMode;
212
  static const CtxSet   MultiRefLineIdx;
213
  static const CtxSet   IntraLumaPlanarFlag;
214
  static const CtxSet   CclmModeFlag;
215
  static const CtxSet   CclmModeIdx;
216
  static const CtxSet   IPredMode       [2];    // [ ChannelType ]
217
  static const CtxSet   MipFlag;
218
  static const CtxSet   DeltaQP;
219
  static const CtxSet   InterDir;
220
  static const CtxSet   RefPic;
221
  static const CtxSet   MmvdFlag;
222
  static const CtxSet   MmvdMergeIdx;
223
  static const CtxSet   MmvdStepMvpIdx;
224
  static const CtxSet   SubblockMergeFlag;
225
  static const CtxSet   AffineFlag;
226
  static const CtxSet   AffineType;
227
  static const CtxSet   AffMergeIdx;
228
  static const CtxSet   Mvd;
229
  static const CtxSet   BDPCMMode;
230
  static const CtxSet   QtRootCbf;
231
  static const CtxSet   ACTFlag;
232
  static const CtxSet   QtCbf           [3];    // [ channel ]
233
  static const CtxSet   SigCoeffGroup   [2];    // [ ChannelType ]
234
  static const CtxSet   LastX           [2];    // [ ChannelType ]
235
  static const CtxSet   LastY           [2];    // [ ChannelType ]
236
  static const CtxSet   SigFlag         [6];    // [ ChannelType + State ]
237
  static const CtxSet   ParFlag         [2];    // [ ChannelType ]
238
  static const CtxSet   GtxFlag         [4];    // [ ChannelType + x ]
239
  static const CtxSet   TsSigCoeffGroup;
240
  static const CtxSet   TsSigFlag;
241
  static const CtxSet   TsParFlag;
242
  static const CtxSet   TsGtxFlag;
243
  static const CtxSet   TsLrg1Flag;
244
  static const CtxSet   TsResidualSign;
245
  static const CtxSet   MVPIdx;
246
  static const CtxSet   SaoMergeFlag;
247
  static const CtxSet   SaoTypeIdx;
248
  static const CtxSet   MTSIndex;
249
  static const CtxSet   LFNSTIdx;
250
  static const CtxSet   RdpcmFlag;
251
  static const CtxSet   RdpcmDir;
252
  static const CtxSet   SbtFlag;
253
  static const CtxSet   SbtQuadFlag;
254
  static const CtxSet   SbtHorFlag;
255
  static const CtxSet   SbtPosFlag;
256
  static const CtxSet   ChromaQpAdjFlag;
257
  static const CtxSet   ChromaQpAdjIdc;
258
  static const CtxSet   ImvFlag;
259
  static const CtxSet   CcAlfFilterControlFlag;
260
  static const CtxSet   BcwIdx;
261
  static const CtxSet   ctbAlfFlag;
262
  static const CtxSet   ctbAlfAlternative;
263
  static const CtxSet   AlfUseTemporalFilt;
264
  static const CtxSet   CiipFlag;
265
  static const CtxSet   SmvdFlag;
266
  static const CtxSet   IBCFlag;
267
  static const CtxSet   ISPMode;
268
  static const CtxSet   JointCbCrFlag;
269
  static const unsigned NumberOfContexts;
270
271
  // combined sets for less complex copying
272
  // NOTE: The contained CtxSet's should directly follow each other in the initalization list;
273
  //       otherwise, you will copy more elements than you want !!!
274
  static const CtxSet   Sao;
275
  static const CtxSet   Alf;
276
277
public:
278
  static const std::vector<uint8_t>&  getInitTable( unsigned initId );
279
280
private:
281
  static std::array<std::vector<uint8_t>, NUMBER_OF_SLICE_TYPES + 1> sm_InitTables;
282
  static CtxSet addCtxSet( std::initializer_list<std::initializer_list<uint8_t> > initSet2d );
283
};
284
285
class Ctx : public ContextSetCfg
286
{
287
public:
288
15.2k
  Ctx() = default;
289
290
  void init( int qp, int initId );
291
292
0
  const BinProbModel& operator[]( unsigned ctxId ) const { return m_CtxBuffer[ctxId]; }
293
0
        BinProbModel& operator[]( unsigned ctxId )       { return m_CtxBuffer[ctxId]; }
294
295
private:
296
  static_vector<BinProbModel, 372> m_CtxBuffer{ ContextSetCfg::NumberOfContexts };
297
};
298
299
}