Coverage Report

Created: 2026-06-15 06:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/work/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
0
{
67
0
  const SPS&        sps        = *tu.cu->sps;
68
0
  const int         qpBdOffset = sps.getQpBDOffset();
69
0
  const bool        useJQP     = isChroma( compID ) && TU::getICTMode( tu, false ) == 2;
70
0
  const ComponentID jCbCr      = useJQP ? JOINT_CbCr : compID;
71
72
0
  int baseQp;
73
0
  int qpy        = tu.cu->qp;
74
  //bool skip      = tu.mtsIdx[compID] == MTS_SKIP;
75
76
0
  if( isLuma( compID ) )
77
0
  {
78
0
    baseQp = qpy + qpBdOffset;
79
0
  }
80
0
  else
81
0
  {
82
0
    const PPS &pps  = *tu.cu->pps;
83
0
    int
84
0
    chromaQpOffset  = pps.getQpOffset                    ( jCbCr );
85
0
    chromaQpOffset += tu.cu->slice->getSliceChromaQpDelta( jCbCr );
86
0
    chromaQpOffset += pps.getChromaQpOffsetListEntry( tu.cu->chromaQpAdj ).get( jCbCr );
87
88
0
    int qpi = Clip3( -qpBdOffset, MAX_QP, qpy );
89
0
    baseQp  = sps.getMappedChromaQpValue( jCbCr, qpi );
90
0
    baseQp  = Clip3( 0, MAX_QP + qpBdOffset, baseQp + chromaQpOffset + qpBdOffset );
91
0
  }
92
93
0
  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
0
  {
103
0
    Qps [0] = baseQp;
104
0
    pers[0] = baseQp / 6;
105
0
    rems[0] = baseQp - ( pers[0] << 2 ) - ( pers[0] << 1 );
106
0
  }
107
  //else
108
0
  {
109
0
    int internalMinusInputBitDepth = sps.getInternalMinusInputBitDepth();
110
0
    int baseQpTS                   = std::max( baseQp, 4 + 6 * internalMinusInputBitDepth );
111
0
    Qps [1] = baseQpTS;
112
0
    pers[1] = baseQpTS / 6;
113
0
    rems[1] = baseQpTS - ( pers[1] << 2 ) - ( pers[1] << 1 );;
114
0
  }
115
0
}
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
0
{
134
0
  const int    inputMinimum     = -( inputMaximum + 1 );
135
0
  const TCoeff transformMinimum = -( transformMaximum + 1 );
136
137
0
  if( rightShift > 0 )
138
0
  {
139
0
    const Intermediate_Int iAdd = (Intermediate_Int) 1 << ( rightShift - 1 );
140
0
    for( int y = 0; y <= maxY; y++ )
141
0
    {
142
0
      int n = y * width;
143
0
      for( int x = 0; x <= maxX; x++, n++ )
144
0
      {
145
0
        const TCoeff level = piQCoef[x + y * piQCfStride];
146
0
        if( level )
147
0
        {
148
0
          const int        scale     = UseScalingList ? piDequantCoef[n] * scaleQP   //
149
0
                                                      : scaleQP;
150
0
          const TCoeff     clipQCoef = TCoeff( Clip3<Intermediate_Int>( inputMinimum, inputMaximum, level ) );
151
0
          Intermediate_Int iCoeffQ   = ( Intermediate_Int( clipQCoef ) * scale + iAdd ) >> rightShift;
152
153
0
          piCoef[n] = TCoeff( Clip3<Intermediate_Int>( transformMinimum, transformMaximum, iCoeffQ ) );
154
0
        }
155
0
      }
156
0
    }
157
0
  }
158
0
  else   // rightshift <= 0
159
0
  {
160
0
    const int leftShift = -rightShift;
161
0
    for( int y = 0; y <= maxY; y++ )
162
0
    {
163
0
      int n = y * width;
164
0
      for( int x = 0; x <= maxX; x++, n++ )
165
0
      {
166
0
        const TCoeff level = piQCoef[x + y * piQCfStride];
167
0
        if( level )
168
0
        {
169
0
          const int              scale     = UseScalingList ? piDequantCoef[n] * scaleQP   //
170
0
                                                            : scaleQP;
171
0
          const TCoeff           clipQCoef = TCoeff( Clip3<Intermediate_Int>( inputMinimum, inputMaximum, level ) );
172
0
          const Intermediate_Int iCoeffQ   = ( Intermediate_Int( clipQCoef ) * scale ) * ( 1 << leftShift );
173
174
0
          piCoef[n] = TCoeff( Clip3<Intermediate_Int>( transformMinimum, transformMaximum, iCoeffQ ) );
175
0
        }
176
0
      }
177
0
    }
178
0
  }
179
0
}
Unexecuted instantiation: Quant.cpp:void vvdec::DeQuantImpl<short, false>(unsigned int, int, int, int, int const*, short const*, unsigned long, int*, int, int, int)
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
0
{
209
0
  DeQuantImpl<T, false>( width, maxX, maxY, scale, nullptr, piQCoef, piQCfStride, piCoef, rightShift, inputMaximum, transformMaximum );
210
0
}
Unexecuted instantiation: void vvdec::Quant::DeQuantCore<short>(unsigned int, int, int, int, short const*, unsigned long, int*, int, int, int)
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
22.7k
  : m_dequantCoefBuf( nullptr )
214
22.7k
  , m_ownDequantCoeff( false )
215
22.7k
{
216
22.7k
  xInitScalingList( other );
217
218
22.7k
  DeQuant           = DeQuantCore<TCoeffSig>;
219
22.7k
  DeQuantPCM        = DeQuantCore<TCoeff>;
220
22.7k
  DeQuantScaling    = DeQuantScalingCore<TCoeffSig>;
221
22.7k
  DeQuantScalingPCM = DeQuantScalingCore<TCoeff>;
222
223
22.7k
  if( enableOpt )
224
22.7k
  {
225
#if ENABLE_SIMD_OPT_QUANT && defined( TARGET_SIMD_X86 )
226
    initQuantX86();
227
#endif
228
22.7k
  }
229
22.7k
}
230
231
Quant::~Quant()
232
22.7k
{
233
22.7k
  xDestroyScalingList();
234
22.7k
}
235
236
void invResDPCM( const TransformUnit &tu, const ComponentID &compID, CoeffBuf &dstBuf )
237
0
{
238
0
  const CompArea&    rect   = tu.blocks[compID];
239
0
  const int          wdt    = rect.width;
240
0
  const int          hgt    = rect.height;
241
0
  const CCoeffSigBuf coeffs = tu.cu->cs->getRecoBuf( tu.block( compID ) );
242
243
0
  const int    maxLog2TrDynamicRange = tu.cu->sps->getMaxLog2TrDynamicRange(toChannelType(compID));
244
0
  const TCoeff inputMinimum          = -(1 << maxLog2TrDynamicRange);
245
0
  const TCoeff inputMaximum          =  (1 << maxLog2TrDynamicRange) - 1;
246
247
0
  const TCoeffSig* coef = &coeffs.buf[0];
248
0
  TCoeff*          dst  = &dstBuf.buf[0];
249
250
0
  if( isLuma( compID ) ? tu.cu->bdpcmMode() == 1 : tu.cu->bdpcmModeChroma() == 1 )
251
0
  {
252
0
    for( int y = 0; y < hgt; y++ )
253
0
    {
254
0
      dst[0] = coef[0];
255
0
      for( int x = 1; x < wdt; x++ )
256
0
      {
257
0
        dst[x] = Clip3(inputMinimum, inputMaximum, dst[x - 1] + coef[x]);
258
0
      }
259
0
      coef += coeffs.stride;
260
0
      dst += dstBuf.stride;
261
0
    }
262
0
  }
263
0
  else
264
0
  {
265
0
    for( int x = 0; x < wdt; x++ )
266
0
    {
267
0
      dst[x] = coef[x];
268
0
    }
269
0
    for( int y = 0; y < hgt - 1; y++ )
270
0
    {
271
0
      for( int x = 0; x < wdt; x++ )
272
0
      {
273
0
        dst[dstBuf.stride + x] = Clip3(inputMinimum, inputMaximum, dst[x] + coef[coeffs.stride + x]);
274
0
      }
275
0
      coef += coeffs.stride;
276
0
      dst += dstBuf.stride;
277
0
    }
278
0
  }
279
0
}
280
281
static inline int getTransformShift( const int channelBitDepth, const Size size, const int maxLog2TrDynamicRange )
282
0
{
283
0
  return maxLog2TrDynamicRange - channelBitDepth - ( ( getLog2( size.width ) + getLog2( size.height ) ) >> 1 );
284
0
}
285
286
static inline int getScalingListType( const PredMode predMode, const ComponentID compID )
287
0
{
288
0
  return ( predMode == MODE_INTRA ? 0 : MAX_NUM_COMPONENT ) + compID;
289
0
}
290
291
292
void Quant::dequant( const TransformUnit& tu, CoeffBuf& dstCoeff, const ComponentID& compID, const QpParam& cQP )
293
0
{
294
0
  const SPS*             sps                   = tu.cu->sps;
295
0
  const CompArea&        area                  = tu.blocks[compID];
296
0
  const CCoeffSigBuf     coeffBuf              = tu.cu->cs->getRecoBuf( tu.block( compID ) );
297
0
  const TCoeffSig* const piQCoef               = coeffBuf.buf;
298
0
  const size_t           piQCfStride           = coeffBuf.stride;
299
0
        TCoeff* const    piCoef                = dstCoeff.buf;
300
0
  const int              maxLog2TrDynamicRange = sps->getMaxLog2TrDynamicRange( toChannelType( compID ) );
301
0
  const TCoeff           transformMaximum      =  ( 1 << maxLog2TrDynamicRange ) - 1;
302
0
  const bool             isTransformSkip       = ( tu.mtsIdx( compID ) == MTS_SKIP );
303
0
  setUseScalingList( tu.cu->slice->getExplicitScalingListUsed() );
304
0
  const bool             disableSMForLFNST     = tu.cu->slice->getExplicitScalingListUsed() ? sps->getDisableScalingMatrixForLfnstBlks() : false;
305
0
  const bool             isLfnstApplied        = tu.cu->lfnstIdx() > 0 && ( CU::isSepTree( *tu.cu ) ? true : isLuma( compID ) );
306
0
  const bool             disableSMForACT       = tu.cu->sps->getScalingMatrixForAlternativeColourSpaceDisabledFlag() && tu.cu->sps->getScalingMatrixDesignatedColourSpaceFlag() == tu.cu->colorTransform();
307
0
  const bool             enableScalingLists    = getUseScalingList( isTransformSkip, isLfnstApplied, disableSMForLFNST, disableSMForACT );
308
0
  const int              scalingListType       = getScalingListType( tu.cu->predMode(), compID );
309
0
  const int              channelBitDepth       = sps->getBitDepth();
310
311
0
  int maxX, maxY;
312
313
0
  if( ( tu.cu->bdpcmMode() && isLuma(compID) ) || ( tu.cu->bdpcmModeChroma() && isChroma(compID) ) )
314
0
  {
315
0
    invResDPCM( tu, compID, dstCoeff );
316
0
    maxX = area.width - 1;
317
0
    maxY = area.height - 1;
318
0
  }
319
0
  else
320
0
  {
321
0
    maxX = tu.maxScanPosX[compID];
322
0
    maxY = tu.maxScanPosY[compID];
323
0
  }
324
325
0
  CHECK(scalingListType >= SCALING_LIST_NUM, "Invalid scaling list");
326
327
  // Represents scaling through forward transform
328
0
  const bool bClipTransformShiftTo0 = false;   // tu.mtsIdx[compID] != 1 && sps->getSpsRangeExtension().getExtendedPrecisionProcessingFlag();
329
0
  const int  originalTransformShift = getTransformShift( channelBitDepth, area.size(), maxLog2TrDynamicRange );
330
0
  const bool needSqrtAdjustment     = TU::needsBlockSizeTrafoScale( tu, compID );
331
0
  const int  iTransformShift        = ( bClipTransformShiftTo0 ? std::max<int>( 0, originalTransformShift ) : originalTransformShift )   //
332
0
                                      + ( needSqrtAdjustment ? -1 : 0 );
333
0
  const bool depQuant   = tu.cu->slice->getDepQuantEnabledFlag() && ( tu.mtsIdx( compID ) != MTS_SKIP );
334
0
  const int  QP_per     = depQuant ? ( ( cQP.Qp( isTransformSkip ) + 1 ) / 6 ) : cQP.per( isTransformSkip );
335
0
  const int  QP_rem     = depQuant ? ( cQP.Qp( isTransformSkip ) + 1 - 6 * QP_per ) : cQP.rem( isTransformSkip );
336
0
  const int  rightShift = IQUANT_SHIFT + ( depQuant ? 1 : 0 )                       //
337
0
                         - ( ( isTransformSkip ? 0 : iTransformShift ) + QP_per )   //
338
0
                         + ( enableScalingLists ? LOG2_SCALING_LIST_NEUTRAL_VALUE : 0 );
339
340
0
  const int scaleQP   = g_InvQuantScales[needSqrtAdjustment ? 1 : 0][QP_rem];
341
0
  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
0
  const uint32_t         targetInputBitDepth = std::min<uint32_t>( maxLog2TrDynamicRange + 1, sizeof( Intermediate_Int ) * 8 + rightShift - scaleBits );
347
0
  const Intermediate_Int inputMaximum        = ( 1 << ( targetInputBitDepth - 1 ) ) - 1;
348
349
0
  if( !enableScalingLists )
350
0
  {
351
0
    if( ( tu.cu->bdpcmMode() && isLuma( compID ) ) || ( tu.cu->bdpcmModeChroma() && isChroma( compID ) ) )
352
0
    {
353
0
      TCoeff* dst = &dstCoeff.buf[0];
354
0
      DeQuantPCM( area.width, maxX, maxY, scaleQP, dst, dstCoeff.stride, piCoef, rightShift, inputMaximum, transformMaximum );
355
0
    }
356
0
    else
357
0
    {
358
0
      DeQuant( area.width, maxX, maxY, scaleQP, piQCoef, piQCfStride, piCoef, rightShift, inputMaximum, transformMaximum );
359
0
    }
360
0
  }
361
0
  else   // Scaling Lists
362
0
  {
363
0
    const uint32_t uiLog2TrWidth  = getLog2( area.width );
364
0
    const uint32_t uiLog2TrHeight = getLog2( area.height );
365
0
    const int*     piDequantCoef  = getDequantCoeff( scalingListType, uiLog2TrWidth, uiLog2TrHeight );
366
0
    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
0
    else
372
0
    {
373
0
      DeQuantScaling( area.width, maxX, maxY, scaleQP, piDequantCoef, piQCoef, piQCfStride, piCoef, rightShift, inputMaximum, transformMaximum );
374
0
    }
375
0
  }
376
0
}
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
22.7k
{
576
22.7k
  if( other )
577
22.0k
  {
578
22.0k
    m_dequantCoefBuf  = other->m_dequantCoefBuf;
579
22.0k
    m_ownDequantCoeff = false;
580
22.0k
  }
581
712
  else
582
712
  {
583
712
    const size_t numScalingCoeffAlloc = g_numScalingListCoeffs + 4;   // +4 to prevent out of bounds read in SIMD code
584
712
    m_dequantCoefBuf  = new int[numScalingCoeffAlloc];
585
712
    m_ownDequantCoeff = true;
586
712
    std::fill_n( m_dequantCoefBuf, numScalingCoeffAlloc, 0 );
587
712
  }
588
589
22.7k
  size_t numQuants = 0;
590
182k
  for(uint32_t sizeIdX = 0; sizeIdX < SCALING_LIST_SIZE_NUM; sizeIdX++)
591
159k
  {
592
1.27M
    for(uint32_t sizeIdY = 0; sizeIdY < SCALING_LIST_SIZE_NUM; sizeIdY++)
593
1.11M
    {
594
7.81M
      for(uint32_t listId = 0; listId < SCALING_LIST_NUM; listId++)
595
6.69M
      {
596
6.69M
        m_dequantCoef [sizeIdX][sizeIdY][listId] = &m_dequantCoefBuf[numQuants];
597
6.69M
        numQuants += g_vvcScalingListSizeX[sizeIdX] * g_vvcScalingListSizeX[sizeIdY];
598
6.69M
      } // listID loop
599
1.11M
    }
600
159k
  }
601
602
22.7k
  CHECK( numQuants != g_numScalingListCoeffs, "Incorrect size of scaling list entries number!" );
603
22.7k
}
604
605
/** destroy quantization matrix array
606
 */
607
void Quant::xDestroyScalingList()
608
22.7k
{
609
22.7k
  if( m_ownDequantCoeff )
610
712
  {
611
712
    delete[] m_dequantCoefBuf;
612
712
  }
613
614
22.7k
  m_ownDequantCoeff = false;
615
22.7k
  m_dequantCoefBuf  = nullptr;
616
22.7k
}
617
618
void Quant::init( const Picture *pic )
619
0
{
620
0
  const Slice* scalingListSlice = nullptr;
621
622
0
  for( const Slice* slice : pic->slices )
623
0
  {
624
0
    if( slice->getExplicitScalingListUsed() )
625
0
    {
626
0
      scalingListSlice = slice;
627
0
      break;
628
0
    }
629
0
  }
630
631
0
  const Slice* slice = scalingListSlice;
632
633
0
  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
0
  else
667
0
  {
668
0
    setUseScalingList( false );
669
0
  }
670
0
}
671
672
}