Coverage Report

Created: 2026-06-16 07:20

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/vvdec/source/Lib/CommonLib/Quant.cpp
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     Quant.cpp
44
    \brief    transform and quantization class
45
*/
46
47
#include "Quant.h"
48
49
#include "UnitTools.h"
50
#include "ContextModelling.h"
51
#include "CodingStructure.h"
52
53
#include "dtrace_buffer.h"
54
55
#include <stdlib.h>
56
#include <memory.h>
57
58
namespace vvdec
59
{
60
61
// ====================================================================================================================
62
// QpParam constructor
63
// ====================================================================================================================
64
65
QpParam::QpParam( const TransformUnit& tu, const ComponentID& compID, const bool allowACTQpoffset )
66
245k
{
67
245k
  const SPS&        sps        = *tu.cu->sps;
68
245k
  const int         qpBdOffset = sps.getQpBDOffset();
69
245k
  const bool        useJQP     = isChroma( compID ) && TU::getICTMode( tu, false ) == 2;
70
245k
  const ComponentID jCbCr      = useJQP ? JOINT_CbCr : compID;
71
72
245k
  int baseQp;
73
245k
  int qpy        = tu.cu->qp;
74
  //bool skip      = tu.mtsIdx[compID] == MTS_SKIP;
75
76
245k
  if( isLuma( compID ) )
77
49.4k
  {
78
49.4k
    baseQp = qpy + qpBdOffset;
79
49.4k
  }
80
195k
  else
81
195k
  {
82
195k
    const PPS &pps  = *tu.cu->pps;
83
195k
    int
84
195k
    chromaQpOffset  = pps.getQpOffset                    ( jCbCr );
85
195k
    chromaQpOffset += tu.cu->slice->getSliceChromaQpDelta( jCbCr );
86
195k
    chromaQpOffset += pps.getChromaQpOffsetListEntry( tu.cu->chromaQpAdj ).get( jCbCr );
87
88
195k
    int qpi = Clip3( -qpBdOffset, MAX_QP, qpy );
89
195k
    baseQp  = sps.getMappedChromaQpValue( jCbCr, qpi );
90
195k
    baseQp  = Clip3( 0, MAX_QP + qpBdOffset, baseQp + chromaQpOffset + qpBdOffset );
91
195k
  }
92
93
245k
  if( allowACTQpoffset && tu.cu->colorTransform() )
94
0
  {
95
0
    baseQp += DELTA_QP_ACT[jCbCr];
96
0
    baseQp  = Clip3( 0, MAX_QP + qpBdOffset, baseQp );
97
0
  }
98
99
  // TODO: ensure clip not needed for non-ACT
100
101
  //if( !skip )
102
245k
  {
103
245k
    Qps [0] = baseQp;
104
245k
    pers[0] = baseQp / 6;
105
245k
    rems[0] = baseQp - ( pers[0] << 2 ) - ( pers[0] << 1 );
106
245k
  }
107
  //else
108
245k
  {
109
245k
    int internalMinusInputBitDepth = sps.getInternalMinusInputBitDepth();
110
245k
    int baseQpTS                   = std::max( baseQp, 4 + 6 * internalMinusInputBitDepth );
111
245k
    Qps [1] = baseQpTS;
112
245k
    pers[1] = baseQpTS / 6;
113
245k
    rems[1] = baseQpTS - ( pers[1] << 2 ) - ( pers[1] << 1 );;
114
245k
  }
115
245k
}
116
117
// ====================================================================================================================
118
// Quant class member functions
119
// ====================================================================================================================
120
121
template<class T, bool UseScalingList>
122
static void DeQuantImpl( const SizeType width,
123
                         const int      maxX,
124
                         const int      maxY,
125
                         const int      scaleQP,
126
                         const int*     piDequantCoef,   // unused if UseScalingList == false
127
                         const T* const piQCoef,
128
                         const size_t   piQCfStride,
129
                         TCoeff* const  piCoef,
130
                         const int      rightShift,
131
                         const int      inputMaximum,
132
                         const TCoeff   transformMaximum )
133
20.1k
{
134
20.1k
  const int    inputMinimum     = -( inputMaximum + 1 );
135
20.1k
  const TCoeff transformMinimum = -( transformMaximum + 1 );
136
137
20.1k
  if( rightShift > 0 )
138
3.58k
  {
139
3.58k
    const Intermediate_Int iAdd = (Intermediate_Int) 1 << ( rightShift - 1 );
140
7.32k
    for( int y = 0; y <= maxY; y++ )
141
3.74k
    {
142
3.74k
      int n = y * width;
143
7.64k
      for( int x = 0; x <= maxX; x++, n++ )
144
3.90k
      {
145
3.90k
        const TCoeff level = piQCoef[x + y * piQCfStride];
146
3.90k
        if( level )
147
3.60k
        {
148
3.60k
          const int        scale     = UseScalingList ? piDequantCoef[n] * scaleQP   //
149
3.60k
                                                      : scaleQP;
150
3.60k
          const TCoeff     clipQCoef = TCoeff( Clip3<Intermediate_Int>( inputMinimum, inputMaximum, level ) );
151
3.60k
          Intermediate_Int iCoeffQ   = ( Intermediate_Int( clipQCoef ) * scale + iAdd ) >> rightShift;
152
153
3.60k
          piCoef[n] = TCoeff( Clip3<Intermediate_Int>( transformMinimum, transformMaximum, iCoeffQ ) );
154
3.60k
        }
155
3.90k
      }
156
3.74k
    }
157
3.58k
  }
158
16.5k
  else   // rightshift <= 0
159
16.5k
  {
160
16.5k
    const int leftShift = -rightShift;
161
40.3k
    for( int y = 0; y <= maxY; y++ )
162
23.7k
    {
163
23.7k
      int n = y * width;
164
53.9k
      for( int x = 0; x <= maxX; x++, n++ )
165
30.2k
      {
166
30.2k
        const TCoeff level = piQCoef[x + y * piQCfStride];
167
30.2k
        if( level )
168
19.7k
        {
169
19.7k
          const int              scale     = UseScalingList ? piDequantCoef[n] * scaleQP   //
170
19.7k
                                                            : scaleQP;
171
19.7k
          const TCoeff           clipQCoef = TCoeff( Clip3<Intermediate_Int>( inputMinimum, inputMaximum, level ) );
172
19.7k
          const Intermediate_Int iCoeffQ   = ( Intermediate_Int( clipQCoef ) * scale ) * ( 1 << leftShift );
173
174
19.7k
          piCoef[n] = TCoeff( Clip3<Intermediate_Int>( transformMinimum, transformMaximum, iCoeffQ ) );
175
19.7k
        }
176
30.2k
      }
177
23.7k
    }
178
16.5k
  }
179
20.1k
}
Quant.cpp:void vvdec::DeQuantImpl<short, false>(unsigned int, int, int, int, int const*, short const*, unsigned long, int*, int, int, int)
Line
Count
Source
133
20.1k
{
134
20.1k
  const int    inputMinimum     = -( inputMaximum + 1 );
135
20.1k
  const TCoeff transformMinimum = -( transformMaximum + 1 );
136
137
20.1k
  if( rightShift > 0 )
138
3.58k
  {
139
3.58k
    const Intermediate_Int iAdd = (Intermediate_Int) 1 << ( rightShift - 1 );
140
7.32k
    for( int y = 0; y <= maxY; y++ )
141
3.74k
    {
142
3.74k
      int n = y * width;
143
7.64k
      for( int x = 0; x <= maxX; x++, n++ )
144
3.90k
      {
145
3.90k
        const TCoeff level = piQCoef[x + y * piQCfStride];
146
3.90k
        if( level )
147
3.60k
        {
148
3.60k
          const int        scale     = UseScalingList ? piDequantCoef[n] * scaleQP   //
149
3.60k
                                                      : scaleQP;
150
3.60k
          const TCoeff     clipQCoef = TCoeff( Clip3<Intermediate_Int>( inputMinimum, inputMaximum, level ) );
151
3.60k
          Intermediate_Int iCoeffQ   = ( Intermediate_Int( clipQCoef ) * scale + iAdd ) >> rightShift;
152
153
3.60k
          piCoef[n] = TCoeff( Clip3<Intermediate_Int>( transformMinimum, transformMaximum, iCoeffQ ) );
154
3.60k
        }
155
3.90k
      }
156
3.74k
    }
157
3.58k
  }
158
16.5k
  else   // rightshift <= 0
159
16.5k
  {
160
16.5k
    const int leftShift = -rightShift;
161
40.3k
    for( int y = 0; y <= maxY; y++ )
162
23.7k
    {
163
23.7k
      int n = y * width;
164
53.9k
      for( int x = 0; x <= maxX; x++, n++ )
165
30.2k
      {
166
30.2k
        const TCoeff level = piQCoef[x + y * piQCfStride];
167
30.2k
        if( level )
168
19.7k
        {
169
19.7k
          const int              scale     = UseScalingList ? piDequantCoef[n] * scaleQP   //
170
19.7k
                                                            : scaleQP;
171
19.7k
          const TCoeff           clipQCoef = TCoeff( Clip3<Intermediate_Int>( inputMinimum, inputMaximum, level ) );
172
19.7k
          const Intermediate_Int iCoeffQ   = ( Intermediate_Int( clipQCoef ) * scale ) * ( 1 << leftShift );
173
174
19.7k
          piCoef[n] = TCoeff( Clip3<Intermediate_Int>( transformMinimum, transformMaximum, iCoeffQ ) );
175
19.7k
        }
176
30.2k
      }
177
23.7k
    }
178
16.5k
  }
179
20.1k
}
Unexecuted instantiation: Quant.cpp:void vvdec::DeQuantImpl<int, false>(unsigned int, int, int, int, int const*, int const*, unsigned long, int*, int, int, int)
Unexecuted instantiation: Quant.cpp:void vvdec::DeQuantImpl<short, true>(unsigned int, int, int, int, int const*, short const*, unsigned long, int*, int, int, int)
Unexecuted instantiation: Quant.cpp:void vvdec::DeQuantImpl<int, true>(unsigned int, int, int, int, int const*, int const*, unsigned long, int*, int, int, int)
180
181
template<class T>
182
void Quant::DeQuantScalingCore( const SizeType width,
183
                                const int      maxX,
184
                                const int      maxY,
185
                                const int      scaleQP,
186
                                const int*     piDequantCoef,
187
                                const T* const piQCoef,
188
                                const size_t   piQCfStride,
189
                                TCoeff* const  piCoef,
190
                                const int      rightShift,
191
                                const int      inputMaximum,
192
                                const TCoeff   transformMaximum )
193
0
{
194
0
  DeQuantImpl<T, true>( width, maxX, maxY, scaleQP, piDequantCoef, piQCoef, piQCfStride, piCoef, rightShift, inputMaximum, transformMaximum );
195
0
}
Unexecuted instantiation: void vvdec::Quant::DeQuantScalingCore<short>(unsigned int, int, int, int, int const*, short const*, unsigned long, int*, int, int, int)
Unexecuted instantiation: void vvdec::Quant::DeQuantScalingCore<int>(unsigned int, int, int, int, int const*, int const*, unsigned long, int*, int, int, int)
196
197
template<class T>
198
void Quant::DeQuantCore( const SizeType width,
199
                         const int      maxX,
200
                         const int      maxY,
201
                         const int      scale,
202
                         const T* const piQCoef,
203
                         const size_t   piQCfStride,
204
                         TCoeff* const  piCoef,
205
                         const int      rightShift,
206
                         const int      inputMaximum,
207
                         const TCoeff   transformMaximum )
208
20.0k
{
209
20.0k
  DeQuantImpl<T, false>( width, maxX, maxY, scale, nullptr, piQCoef, piQCfStride, piCoef, rightShift, inputMaximum, transformMaximum );
210
20.0k
}
void vvdec::Quant::DeQuantCore<short>(unsigned int, int, int, int, short const*, unsigned long, int*, int, int, int)
Line
Count
Source
208
20.0k
{
209
20.0k
  DeQuantImpl<T, false>( width, maxX, maxY, scale, nullptr, piQCoef, piQCfStride, piCoef, rightShift, inputMaximum, transformMaximum );
210
20.0k
}
Unexecuted instantiation: void vvdec::Quant::DeQuantCore<int>(unsigned int, int, int, int, int const*, unsigned long, int*, int, int, int)
211
212
Quant::Quant( const Quant* other, bool enableOpt )
213
59.8k
  : m_dequantCoefBuf( nullptr )
214
59.8k
  , m_ownDequantCoeff( false )
215
59.8k
{
216
59.8k
  xInitScalingList( other );
217
218
59.8k
  DeQuant           = DeQuantCore<TCoeffSig>;
219
59.8k
  DeQuantPCM        = DeQuantCore<TCoeff>;
220
59.8k
  DeQuantScaling    = DeQuantScalingCore<TCoeffSig>;
221
59.8k
  DeQuantScalingPCM = DeQuantScalingCore<TCoeff>;
222
223
59.8k
  if( enableOpt )
224
59.8k
  {
225
59.8k
#if ENABLE_SIMD_OPT_QUANT && defined( TARGET_SIMD_X86 )
226
59.8k
    initQuantX86();
227
59.8k
#endif
228
59.8k
  }
229
59.8k
}
230
231
Quant::~Quant()
232
59.8k
{
233
59.8k
  xDestroyScalingList();
234
59.8k
}
235
236
void invResDPCM( const TransformUnit &tu, const ComponentID &compID, CoeffBuf &dstBuf )
237
2.29k
{
238
2.29k
  const CompArea&    rect   = tu.blocks[compID];
239
2.29k
  const int          wdt    = rect.width;
240
2.29k
  const int          hgt    = rect.height;
241
2.29k
  const CCoeffSigBuf coeffs = tu.cu->cs->getRecoBuf( tu.block( compID ) );
242
243
2.29k
  const int    maxLog2TrDynamicRange = tu.cu->sps->getMaxLog2TrDynamicRange(toChannelType(compID));
244
2.29k
  const TCoeff inputMinimum          = -(1 << maxLog2TrDynamicRange);
245
2.29k
  const TCoeff inputMaximum          =  (1 << maxLog2TrDynamicRange) - 1;
246
247
2.29k
  const TCoeffSig* coef = &coeffs.buf[0];
248
2.29k
  TCoeff*          dst  = &dstBuf.buf[0];
249
250
2.29k
  if( isLuma( compID ) ? tu.cu->bdpcmMode() == 1 : tu.cu->bdpcmModeChroma() == 1 )
251
1.42k
  {
252
16.3k
    for( int y = 0; y < hgt; y++ )
253
14.9k
    {
254
14.9k
      dst[0] = coef[0];
255
170k
      for( int x = 1; x < wdt; x++ )
256
155k
      {
257
155k
        dst[x] = Clip3(inputMinimum, inputMaximum, dst[x - 1] + coef[x]);
258
155k
      }
259
14.9k
      coef += coeffs.stride;
260
14.9k
      dst += dstBuf.stride;
261
14.9k
    }
262
1.42k
  }
263
871
  else
264
871
  {
265
10.1k
    for( int x = 0; x < wdt; x++ )
266
9.30k
    {
267
9.30k
      dst[x] = coef[x];
268
9.30k
    }
269
9.17k
    for( int y = 0; y < hgt - 1; y++ )
270
8.30k
    {
271
103k
      for( int x = 0; x < wdt; x++ )
272
95.1k
      {
273
95.1k
        dst[dstBuf.stride + x] = Clip3(inputMinimum, inputMaximum, dst[x] + coef[coeffs.stride + x]);
274
95.1k
      }
275
8.30k
      coef += coeffs.stride;
276
8.30k
      dst += dstBuf.stride;
277
8.30k
    }
278
871
  }
279
2.29k
}
280
281
static inline int getTransformShift( const int channelBitDepth, const Size size, const int maxLog2TrDynamicRange )
282
79.8k
{
283
79.8k
  return maxLog2TrDynamicRange - channelBitDepth - ( ( getLog2( size.width ) + getLog2( size.height ) ) >> 1 );
284
79.8k
}
285
286
static inline int getScalingListType( const PredMode predMode, const ComponentID compID )
287
79.7k
{
288
79.7k
  return ( predMode == MODE_INTRA ? 0 : MAX_NUM_COMPONENT ) + compID;
289
79.7k
}
290
291
292
void Quant::dequant( const TransformUnit& tu, CoeffBuf& dstCoeff, const ComponentID& compID, const QpParam& cQP )
293
79.8k
{
294
79.8k
  const SPS*             sps                   = tu.cu->sps;
295
79.8k
  const CompArea&        area                  = tu.blocks[compID];
296
79.8k
  const CCoeffSigBuf     coeffBuf              = tu.cu->cs->getRecoBuf( tu.block( compID ) );
297
79.8k
  const TCoeffSig* const piQCoef               = coeffBuf.buf;
298
79.8k
  const size_t           piQCfStride           = coeffBuf.stride;
299
79.8k
        TCoeff* const    piCoef                = dstCoeff.buf;
300
79.8k
  const int              maxLog2TrDynamicRange = sps->getMaxLog2TrDynamicRange( toChannelType( compID ) );
301
79.8k
  const TCoeff           transformMaximum      =  ( 1 << maxLog2TrDynamicRange ) - 1;
302
79.8k
  const bool             isTransformSkip       = ( tu.mtsIdx( compID ) == MTS_SKIP );
303
79.8k
  setUseScalingList( tu.cu->slice->getExplicitScalingListUsed() );
304
79.8k
  const bool             disableSMForLFNST     = tu.cu->slice->getExplicitScalingListUsed() ? sps->getDisableScalingMatrixForLfnstBlks() : false;
305
18.4E
  const bool             isLfnstApplied        = tu.cu->lfnstIdx() > 0 && ( CU::isSepTree( *tu.cu ) ? true : isLuma( compID ) );
306
79.8k
  const bool             disableSMForACT       = tu.cu->sps->getScalingMatrixForAlternativeColourSpaceDisabledFlag() && tu.cu->sps->getScalingMatrixDesignatedColourSpaceFlag() == tu.cu->colorTransform();
307
79.8k
  const bool             enableScalingLists    = getUseScalingList( isTransformSkip, isLfnstApplied, disableSMForLFNST, disableSMForACT );
308
79.8k
  const int              scalingListType       = getScalingListType( tu.cu->predMode(), compID );
309
79.8k
  const int              channelBitDepth       = sps->getBitDepth();
310
311
79.8k
  int maxX, maxY;
312
313
79.8k
  if( ( tu.cu->bdpcmMode() && isLuma(compID) ) || ( tu.cu->bdpcmModeChroma() && isChroma(compID) ) )
314
2.29k
  {
315
2.29k
    invResDPCM( tu, compID, dstCoeff );
316
2.29k
    maxX = area.width - 1;
317
2.29k
    maxY = area.height - 1;
318
2.29k
  }
319
77.5k
  else
320
77.5k
  {
321
77.5k
    maxX = tu.maxScanPosX[compID];
322
77.5k
    maxY = tu.maxScanPosY[compID];
323
77.5k
  }
324
325
79.8k
  CHECK(scalingListType >= SCALING_LIST_NUM, "Invalid scaling list");
326
327
  // Represents scaling through forward transform
328
79.8k
  const bool bClipTransformShiftTo0 = false;   // tu.mtsIdx[compID] != 1 && sps->getSpsRangeExtension().getExtendedPrecisionProcessingFlag();
329
79.8k
  const int  originalTransformShift = getTransformShift( channelBitDepth, area.size(), maxLog2TrDynamicRange );
330
79.8k
  const bool needSqrtAdjustment     = TU::needsBlockSizeTrafoScale( tu, compID );
331
79.8k
  const int  iTransformShift        = ( bClipTransformShiftTo0 ? std::max<int>( 0, originalTransformShift ) : originalTransformShift )   //
332
79.8k
                                      + ( needSqrtAdjustment ? -1 : 0 );
333
79.8k
  const bool depQuant   = tu.cu->slice->getDepQuantEnabledFlag() && ( tu.mtsIdx( compID ) != MTS_SKIP );
334
79.8k
  const int  QP_per     = depQuant ? ( ( cQP.Qp( isTransformSkip ) + 1 ) / 6 ) : cQP.per( isTransformSkip );
335
79.8k
  const int  QP_rem     = depQuant ? ( cQP.Qp( isTransformSkip ) + 1 - 6 * QP_per ) : cQP.rem( isTransformSkip );
336
79.8k
  const int  rightShift = IQUANT_SHIFT + ( depQuant ? 1 : 0 )                       //
337
79.8k
                         - ( ( isTransformSkip ? 0 : iTransformShift ) + QP_per )   //
338
79.8k
                         + ( enableScalingLists ? LOG2_SCALING_LIST_NEUTRAL_VALUE : 0 );
339
340
79.8k
  const int scaleQP   = g_InvQuantScales[needSqrtAdjustment ? 1 : 0][QP_rem];
341
79.8k
  const int scaleBits = ( IQUANT_SHIFT + 1 );
342
343
  // from the dequantisation equation:
344
  // iCoeffQ                         = Intermediate_Int((int64_t(clipQCoef) * scale + iAdd) >> rightShift);
345
  //(sizeof(Intermediate_Int) * 8)  =                    inputBitDepth   + scaleBits      - rightShift
346
79.8k
  const uint32_t         targetInputBitDepth = std::min<uint32_t>( maxLog2TrDynamicRange + 1, sizeof( Intermediate_Int ) * 8 + rightShift - scaleBits );
347
79.8k
  const Intermediate_Int inputMaximum        = ( 1 << ( targetInputBitDepth - 1 ) ) - 1;
348
349
79.8k
  if( !enableScalingLists )
350
79.9k
  {
351
79.9k
    if( ( tu.cu->bdpcmMode() && isLuma( compID ) ) || ( tu.cu->bdpcmModeChroma() && isChroma( compID ) ) )
352
2.29k
    {
353
2.29k
      TCoeff* dst = &dstCoeff.buf[0];
354
2.29k
      DeQuantPCM( area.width, maxX, maxY, scaleQP, dst, dstCoeff.stride, piCoef, rightShift, inputMaximum, transformMaximum );
355
2.29k
    }
356
77.6k
    else
357
77.6k
    {
358
77.6k
      DeQuant( area.width, maxX, maxY, scaleQP, piQCoef, piQCfStride, piCoef, rightShift, inputMaximum, transformMaximum );
359
77.6k
    }
360
79.9k
  }
361
18.4E
  else   // Scaling Lists
362
18.4E
  {
363
18.4E
    const uint32_t uiLog2TrWidth  = getLog2( area.width );
364
18.4E
    const uint32_t uiLog2TrHeight = getLog2( area.height );
365
18.4E
    const int*     piDequantCoef  = getDequantCoeff( scalingListType, uiLog2TrWidth, uiLog2TrHeight );
366
18.4E
    if( ( tu.cu->bdpcmMode() && isLuma( compID ) ) || ( tu.cu->bdpcmModeChroma() && isChroma( compID ) ) )
367
0
    {
368
0
      TCoeff* dst = &dstCoeff.buf[0];
369
0
      DeQuantScalingPCM( area.width, maxX, maxY, scaleQP, piDequantCoef, dst, dstCoeff.stride, piCoef, rightShift, inputMaximum, transformMaximum );
370
0
    }
371
18.4E
    else
372
18.4E
    {
373
18.4E
      DeQuantScaling( area.width, maxX, maxY, scaleQP, piDequantCoef, piQCoef, piQCfStride, piCoef, rightShift, inputMaximum, transformMaximum );
374
18.4E
    }
375
18.4E
  }
376
79.8k
}
377
378
/** set quantized matrix coefficient for decode
379
 * \param scalingList quantized matrix address
380
 * \param format      chroma format
381
 */
382
void Quant::setScalingListDec( const ScalingList& scalingList )
383
0
{
384
0
  int scalingListId    = 0;
385
0
  int recScalingListId = 0;
386
0
  bool anyChange = false;
387
0
  for( uint32_t size = SCALING_LIST_FIRST_CODED; size <= SCALING_LIST_LAST_CODED; size++ )
388
0
  {
389
0
    for( uint32_t list = 0; list < SCALING_LIST_NUM; list++ )
390
0
    {
391
0
      if( size == SCALING_LIST_2x2 && list < 4 )   // skip 2x2 luma
392
0
      {
393
0
        continue;
394
0
      }
395
0
      scalingListId = g_scalingListId[size][list];
396
0
      anyChange |= xSetScalingListDec( scalingList, list, size, scalingListId );
397
0
    }
398
0
  }
399
0
  if( !anyChange ) return;
400
  // based on square result and apply downsample technology
401
0
  for( uint32_t sizew = 0; sizew <= SCALING_LIST_LAST_CODED; sizew++ )   // 7
402
0
  {
403
0
    for( uint32_t sizeh = 0; sizeh <= SCALING_LIST_LAST_CODED; sizeh++ )   // 7
404
0
    {
405
0
      if( sizew == sizeh || ( sizew == SCALING_LIST_1x1 && sizeh < SCALING_LIST_4x4 ) || ( sizeh == SCALING_LIST_1x1 && sizew < SCALING_LIST_4x4 ) )
406
0
      {
407
0
        continue;
408
0
      }
409
0
      for( uint32_t list = 0; list < SCALING_LIST_NUM; list++ )   // 9
410
0
      {
411
0
        int largerSide = ( sizew > sizeh ) ? sizew : sizeh;
412
0
        CHECK( largerSide < SCALING_LIST_4x4, "Rectangle Error!" );
413
0
        recScalingListId = g_scalingListId[largerSide][list];
414
0
        xSetRecScalingListDec( scalingList, list, sizew, sizeh, recScalingListId );
415
0
      }
416
0
    }
417
0
  }
418
0
}
419
420
/** set quantized matrix coefficient for decode
421
 * \param scalingList quantaized matrix address
422
 * \param listId List index
423
 * \param sizeId size index
424
 * \param qp Quantization parameter
425
 * \param format chroma format
426
 */
427
bool Quant::xSetScalingListDec(const ScalingList &scalingList, uint32_t listId, uint32_t sizeId, uint32_t scalingListId)
428
0
{
429
0
  const uint32_t width  = g_vvcScalingListSizeX[sizeId];
430
0
  const uint32_t height = g_vvcScalingListSizeX[sizeId];
431
#if defined( __SANITIZE_ADDRESS__ )   // work around a bug in GCC address-sanitizer, when building with -fsanitize=address, but without -fsanitize=undefined
432
  volatile
433
#endif
434
0
  const uint32_t ratio  = g_vvcScalingListSizeX[sizeId]/std::min(MAX_MATRIX_SIZE_NUM,(int)g_vvcScalingListSizeX[sizeId]);
435
436
0
  const int *coeff = scalingList.getScalingListAddress(scalingListId);
437
0
  int *dequantcoeff = getDequantCoeff(listId, sizeId, sizeId);
438
439
0
  return
440
0
  processScalingListDec(coeff,
441
0
                        dequantcoeff,
442
0
                        height, width, ratio,
443
0
                        std::min(MAX_MATRIX_SIZE_NUM, (int)g_vvcScalingListSizeX[sizeId]),
444
0
                        scalingList.getScalingListDC(scalingListId));
445
0
}
446
447
/** set quantized matrix coefficient for decode
448
* \param scalingList quantaized matrix address
449
* \param listId List index
450
* \param sizeId size index
451
* \param qp Quantization parameter
452
* \param format chroma format
453
*/
454
void Quant::xSetRecScalingListDec(const ScalingList &scalingList, uint32_t listId, uint32_t sizeIdw, uint32_t sizeIdh, uint32_t scalingListId)
455
0
{
456
0
  if (sizeIdw == sizeIdh) return;
457
458
0
  const uint32_t width  = g_vvcScalingListSizeX[sizeIdw];
459
0
  const uint32_t height = g_vvcScalingListSizeX[sizeIdh];
460
0
  const uint32_t largeSideId = (sizeIdw > sizeIdh) ? sizeIdw : sizeIdh;  //16
461
462
0
  const int *coeff = scalingList.getScalingListAddress(scalingListId);
463
0
  int *dequantcoeff = getDequantCoeff(listId, sizeIdw, sizeIdh);
464
465
0
  processScalingListDec(coeff,
466
0
                        dequantcoeff,
467
0
                        height, width, (largeSideId>3) ? 2 : 1,
468
0
                        (largeSideId >= 3 ? 8 : 4),
469
0
                        scalingList.getScalingListDC(scalingListId));
470
0
}
471
472
/** set quantized matrix coefficient for decode
473
 * \param coeff quantaized matrix address
474
 * \param dequantcoeff quantaized matrix address
475
 * \param invQuantScales IQ(QP%6))
476
 * \param height height
477
 * \param width width
478
 * \param ratio ratio for upscale
479
 * \param sizuNum matrix size
480
 * \param dc dc parameter
481
 */
482
bool Quant::processScalingListDec( const int *coeff, int *dequantcoeff, uint32_t height, uint32_t width, uint32_t ratio, int sizuNum, uint32_t dc)
483
0
{
484
0
  if (height != width)
485
0
  {
486
0
    const int hl2 = getLog2( height );
487
0
    const int wl2 = getLog2( width );
488
0
    const int sl2 = getLog2( sizuNum );
489
490
0
    const int loopH = std::min<int>( height, JVET_C0024_ZERO_OUT_TH );
491
0
    const int loopW = std::min<int>( width,  JVET_C0024_ZERO_OUT_TH );
492
493
0
    const int ratioWH = height > width   ? hl2 - wl2 : wl2 - hl2;
494
0
    const int ratioH  = height / sizuNum ? hl2 - sl2 : sl2 - hl2;
495
0
    const int ratioW  = width / sizuNum  ? wl2 - sl2 : sl2 - wl2;
496
497
0
    if( height > width )
498
0
    {
499
0
      for( uint32_t j = 0; j < loopH; j += ( 1 << ratioH ) )
500
0
      {
501
0
        for( uint32_t i = 0; i < loopW; i++ )
502
0
        {
503
0
          dequantcoeff[j * width + i] = coeff[sizuNum * ( j >> ratioH ) + ( ( i << ratioWH ) >> ratioH )];
504
0
        }
505
506
0
        const int* src = &dequantcoeff[j * width];
507
0
        for( int jj = 1; jj < ( 1 << ratioH ); jj++ )
508
0
        {
509
0
          memcpy( &dequantcoeff[( j + jj ) * width], src, loopW * sizeof( int ) );
510
0
        }
511
0
      }
512
0
    }
513
0
    else
514
0
    {
515
0
      for( uint32_t j = 0; j < loopH; j++ )
516
0
      {
517
0
        for( uint32_t i = 0; i < loopW; i += ( 1 << ratioW ) )
518
0
        {
519
0
          const int coeffi = coeff[sizuNum * ( ( j << ratioWH ) >> ratioW ) + ( i >> ratioW )];
520
0
          for( uint32_t ii = 0; ii < ( 1 << ratioW ); ii++ )
521
0
          {
522
0
            dequantcoeff[j * width + i + ii] = coeffi;
523
0
          }
524
0
        }
525
0
      }
526
0
    }
527
528
0
    const int largeOne = std::max( width, height );
529
0
    if( largeOne > 8 )
530
0
    {
531
0
      dequantcoeff[0] = dc;
532
0
    }
533
0
    return true;
534
0
  }
535
536
0
  bool anyChange = false;
537
538
0
  const int rl2   = getLog2( ratio );
539
0
  const int loopH = std::min<int>( height, JVET_C0024_ZERO_OUT_TH );
540
0
  const int loopW = std::min<int>( width, JVET_C0024_ZERO_OUT_TH );
541
542
0
  for( uint32_t j = 0; j < loopH; j += ( 1 << rl2 ) )
543
0
  {
544
0
    for( uint32_t i = 0; i < loopW; i += ( 1 << rl2 ) )
545
0
    {
546
0
      const int coeffi = coeff[sizuNum * ( j >> rl2 ) + ( i >> rl2 )];
547
0
      anyChange |= coeffi != dequantcoeff[j * width + i];
548
0
      for( uint32_t ii = 0; anyChange && ii < ( 1 << rl2 ); ii++ )
549
0
      {
550
0
        dequantcoeff[j * width + i + ii] = coeffi;
551
0
      }
552
0
    }
553
554
0
    const int* src = &dequantcoeff[j * width];
555
0
    for( int jj = 1; jj < ( 1 << rl2 ); jj++ )
556
0
    {
557
0
      memcpy( &dequantcoeff[( j + jj ) * width], src, loopW * sizeof( int ) );
558
0
    }
559
0
  }
560
561
0
  if( ratio > 1 )
562
0
  {
563
0
    anyChange |= dequantcoeff[0] != dc;
564
0
    dequantcoeff[0] = dc;
565
0
  }
566
567
0
  return anyChange;
568
0
}
569
570
static constexpr int g_numScalingListCoeffs = 96774;
571
572
/** initialization process of scaling list array
573
 */
574
void Quant::xInitScalingList( const Quant* other )
575
59.8k
{
576
59.8k
  if( other )
577
57.9k
  {
578
57.9k
    m_dequantCoefBuf  = other->m_dequantCoefBuf;
579
57.9k
    m_ownDequantCoeff = false;
580
57.9k
  }
581
1.87k
  else
582
1.87k
  {
583
1.87k
    const size_t numScalingCoeffAlloc = g_numScalingListCoeffs + 4;   // +4 to prevent out of bounds read in SIMD code
584
1.87k
    m_dequantCoefBuf  = new int[numScalingCoeffAlloc];
585
1.87k
    m_ownDequantCoeff = true;
586
1.87k
    std::fill_n( m_dequantCoefBuf, numScalingCoeffAlloc, 0 );
587
1.87k
  }
588
589
59.8k
  size_t numQuants = 0;
590
478k
  for(uint32_t sizeIdX = 0; sizeIdX < SCALING_LIST_SIZE_NUM; sizeIdX++)
591
418k
  {
592
3.35M
    for(uint32_t sizeIdY = 0; sizeIdY < SCALING_LIST_SIZE_NUM; sizeIdY++)
593
2.93M
    {
594
20.5M
      for(uint32_t listId = 0; listId < SCALING_LIST_NUM; listId++)
595
17.5M
      {
596
17.5M
        m_dequantCoef [sizeIdX][sizeIdY][listId] = &m_dequantCoefBuf[numQuants];
597
17.5M
        numQuants += g_vvcScalingListSizeX[sizeIdX] * g_vvcScalingListSizeX[sizeIdY];
598
17.5M
      } // listID loop
599
2.93M
    }
600
418k
  }
601
602
59.8k
  CHECK( numQuants != g_numScalingListCoeffs, "Incorrect size of scaling list entries number!" );
603
59.8k
}
604
605
/** destroy quantization matrix array
606
 */
607
void Quant::xDestroyScalingList()
608
59.8k
{
609
59.8k
  if( m_ownDequantCoeff )
610
1.87k
  {
611
1.87k
    delete[] m_dequantCoefBuf;
612
1.87k
  }
613
614
59.8k
  m_ownDequantCoeff = false;
615
59.8k
  m_dequantCoefBuf  = nullptr;
616
59.8k
}
617
618
void Quant::init( const Picture *pic )
619
22.8k
{
620
22.8k
  const Slice* scalingListSlice = nullptr;
621
622
22.8k
  for( const Slice* slice : pic->slices )
623
22.8k
  {
624
22.8k
    if( slice->getExplicitScalingListUsed() )
625
0
    {
626
0
      scalingListSlice = slice;
627
0
      break;
628
0
    }
629
22.8k
  }
630
631
22.8k
  const Slice* slice = scalingListSlice;
632
633
22.8k
  if( slice && slice->getExplicitScalingListUsed() )
634
0
  {
635
0
    const std::shared_ptr<const APS> scalingListAPS = slice->getPicHeader()->getScalingListAPS();
636
0
    if( slice->getNalUnitLayerId() != scalingListAPS->getLayerId() )
637
0
    {
638
0
      CHECK( scalingListAPS->getLayerId() > slice->getNalUnitLayerId(), "Layer Id of APS cannot be greater than layer Id of VCL NAL unit the refer to it" );
639
0
      CHECK( slice->getSPS()->getVPSId() == 0, "VPSId of the referred SPS cannot be 0 when layer Id of APS and layer Id of current slice are different" );
640
0
      for( int i = 0; i < slice->getVPS()->getNumOutputLayerSets(); i++ )
641
0
      {
642
0
        bool isCurrLayerInOls = false;
643
0
        bool isRefLayerInOls = false;
644
0
        for( int j = slice->getVPS()->getNumLayersInOls(i) - 1; j >= 0; j-- )
645
0
        {
646
0
          if( slice->getVPS()->getLayerIdInOls(i, j) == slice->getNalUnitLayerId() )
647
0
          {
648
0
            isCurrLayerInOls = true;
649
0
          }
650
0
          if( slice->getVPS()->getLayerIdInOls(i, j) == scalingListAPS->getLayerId() )
651
0
          {
652
0
            isRefLayerInOls = true;
653
0
          }
654
0
        }
655
0
        CHECK( isCurrLayerInOls && !isRefLayerInOls, "When VCL NAl unit in layer A refers to APS in layer B, all OLS that contains layer A shall also contains layer B" );
656
0
      }
657
0
    }
658
0
    const ScalingList& scalingList = scalingListAPS->getScalingList();
659
0
    if( m_ownDequantCoeff )
660
0
    {
661
0
      memset( m_dequantCoefBuf, 0, sizeof( int ) * g_numScalingListCoeffs );
662
0
      setScalingListDec( scalingList );
663
0
    }
664
0
    setUseScalingList(true);
665
0
  }
666
22.8k
  else
667
22.8k
  {
668
22.8k
    setUseScalingList( false );
669
22.8k
  }
670
22.8k
}
671
672
}