Coverage Report

Created: 2026-07-25 07:06

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