Coverage Report

Created: 2026-04-01 07:49

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 <limits>
57
#include <memory.h>
58
59
namespace vvdec
60
{
61
62
// ====================================================================================================================
63
// QpParam constructor
64
// ====================================================================================================================
65
66
QpParam::QpParam( const TransformUnit& tu, const ComponentID& compID, const bool allowACTQpoffset )
67
0
{
68
0
  const SPS&        sps        = *tu.cu->sps;
69
0
  const int         qpBdOffset = sps.getQpBDOffset();
70
0
  const bool        useJQP     = isChroma( compID ) && TU::getICTMode( tu, false ) == 2;
71
0
  const ComponentID jCbCr      = useJQP ? JOINT_CbCr : compID;
72
73
0
  int baseQp;
74
0
  int qpy        = tu.cu->qp;
75
  //bool skip      = tu.mtsIdx[compID] == MTS_SKIP;
76
77
0
  if( isLuma( compID ) )
78
0
  {
79
0
    baseQp = qpy + qpBdOffset;
80
0
  }
81
0
  else
82
0
  {
83
0
    const PPS &pps  = *tu.cu->pps;
84
0
    int
85
0
    chromaQpOffset  = pps.getQpOffset                    ( jCbCr );
86
0
    chromaQpOffset += tu.cu->slice->getSliceChromaQpDelta( jCbCr );
87
0
    chromaQpOffset += pps.getChromaQpOffsetListEntry( tu.cu->chromaQpAdj ).get( jCbCr );
88
89
0
    int qpi = Clip3( -qpBdOffset, MAX_QP, qpy );
90
0
    baseQp  = sps.getMappedChromaQpValue( jCbCr, qpi );
91
0
    baseQp  = Clip3( 0, MAX_QP + qpBdOffset, baseQp + chromaQpOffset + qpBdOffset );
92
0
  }
93
94
0
  if( allowACTQpoffset && tu.cu->colorTransform() )
95
0
  {
96
0
    baseQp += DELTA_QP_ACT[jCbCr];
97
0
    baseQp  = Clip3( 0, MAX_QP + qpBdOffset, baseQp );
98
0
  }
99
100
  // TODO: ensure clip not needed for non-ACT
101
102
  //if( !skip )
103
0
  {
104
0
    Qps [0] = baseQp;
105
0
    pers[0] = baseQp / 6;
106
0
    rems[0] = baseQp - ( pers[0] << 2 ) - ( pers[0] << 1 );
107
0
  }
108
  //else
109
0
  {
110
0
    int internalMinusInputBitDepth = sps.getInternalMinusInputBitDepth();
111
0
    int baseQpTS                   = std::max( baseQp, 4 + 6 * internalMinusInputBitDepth );
112
0
    Qps [1] = baseQpTS;
113
0
    pers[1] = baseQpTS / 6;
114
0
    rems[1] = baseQpTS - ( pers[1] << 2 ) - ( pers[1] << 1 );;
115
0
  }
116
0
}
117
118
// ====================================================================================================================
119
// Quant class member functions
120
// ====================================================================================================================
121
122
static void DeQuantScalingCore( const int              maxX,
123
                         const int              restX,
124
                         const int              maxY,
125
                         const int              scaleQP,
126
                         const int              *piDequantCoef,
127
                         const TCoeffSig* 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
0
  int scale;
137
138
0
  if (rightShift>0)
139
0
  {
140
0
    const Intermediate_Int iAdd = (Intermediate_Int) 1 << (rightShift - 1);
141
0
    for( int y = 0, n = 0; y <= maxY; y++)
142
0
    {
143
0
      for( int x = 0; x <= maxX; x++, n++ )
144
0
      {
145
0
        const TCoeff level = piQCoef[x + y * piQCfStride];
146
        // new
147
0
        scale = piDequantCoef[n] * scaleQP;
148
149
0
        if( level )
150
0
        {
151
0
          const TCoeff           clipQCoef = TCoeff(Clip3<Intermediate_Int>(inputMinimum, inputMaximum, level));
152
0
          Intermediate_Int iCoeffQ   = (Intermediate_Int(clipQCoef) * scale + iAdd) >> rightShift;
153
0
          piCoef[n] = TCoeff(Clip3<Intermediate_Int>(transformMinimum,transformMaximum,iCoeffQ));
154
0
        }
155
0
      }
156
0
      n += restX;
157
0
    }
158
0
  }
159
0
  else  // rightshift <0
160
0
  {
161
0
    int leftShift = -rightShift;
162
0
    for( int y = 0, n = 0; y <= maxY; y++)
163
0
    {
164
0
      for( int x = 0; x <= maxX; x++, n++ )
165
0
      {
166
0
        const TCoeff level = piQCoef[x + y * piQCfStride];
167
        // new
168
0
        scale = piDequantCoef[n] * scaleQP;
169
170
0
        if( level )
171
0
        {
172
0
          const TCoeff           clipQCoef = TCoeff(Clip3<Intermediate_Int>(inputMinimum, inputMaximum, level));
173
0
          const Intermediate_Int iCoeffQ   = (Intermediate_Int(clipQCoef) * scale) *(1<<leftShift);
174
0
          piCoef[n] = TCoeff(Clip3<Intermediate_Int>(transformMinimum,transformMaximum,iCoeffQ));
175
0
        }
176
0
      }
177
0
      n += restX;
178
0
    }
179
0
  }
180
0
}
181
static void DeQuantScalingPCMCore(const int     maxX,
182
    const int     restX,
183
    const int     maxY,
184
    const int     scaleQP,
185
    const int     *piDequantCoef,
186
    TCoeff* const piQCoef,
187
    const size_t  piQCfStride,
188
    TCoeff* const piCoef,
189
    const int     rightShift,
190
    const int     inputMaximum,
191
    const TCoeff  transformMaximum )
192
0
{
193
0
  const int    inputMinimum     = -( inputMaximum + 1 );
194
0
  const TCoeff transformMinimum = -( transformMaximum + 1 );
195
0
  int scale;
196
0
  if (rightShift > 0)
197
0
  {
198
0
    const Intermediate_Int iAdd = (Intermediate_Int) 1 << (rightShift - 1);
199
0
    for( int y = 0, n = 0; y <= maxY; y++)
200
0
    {
201
0
      for( int x = 0; x <= maxX; x++, n++ )
202
0
      {
203
0
        const TCoeff level = piQCoef[x + y * piQCfStride];
204
0
        if( level )
205
0
        {
206
0
          scale = piDequantCoef[n] * scaleQP;
207
0
          const TCoeff           clipQCoef = TCoeff(Clip3<Intermediate_Int>(inputMinimum, inputMaximum, level));
208
0
          const Intermediate_Int iCoeffQ   = (Intermediate_Int(clipQCoef) * scale + iAdd) >> rightShift;
209
0
          piCoef[n] = TCoeff(Clip3<Intermediate_Int>(transformMinimum,transformMaximum,iCoeffQ));
210
0
        }
211
0
      }
212
0
      n += restX;
213
0
    }
214
0
  }
215
0
  else
216
0
  {
217
0
    int leftShift = -rightShift;
218
0
    for( int y = 0, n = 0; y <= maxY; y++)
219
0
    {
220
0
      for( int x = 0; x <= maxX; x++, n++ )
221
0
      {
222
0
        const TCoeff level = piQCoef[x + y * piQCfStride];
223
0
        if( level )
224
0
        {
225
0
          scale = piDequantCoef[n] * scaleQP;
226
0
          const TCoeff           clipQCoef = TCoeff(Clip3<Intermediate_Int>(inputMinimum, inputMaximum, level));
227
0
          const Intermediate_Int iCoeffQ   = (Intermediate_Int(clipQCoef) * scale) *(1<< leftShift);
228
0
          piCoef[n] = TCoeff(Clip3<Intermediate_Int>(transformMinimum,transformMaximum,iCoeffQ));
229
0
        }
230
0
      }
231
0
      n += restX;
232
0
    }
233
0
  }
234
0
}
235
static void DeQuantCore( const int              maxX,
236
                         const int              restX,
237
                         const int              maxY,
238
                         const int              scale,
239
                         const TCoeffSig* const piQCoef,
240
                         const size_t           piQCfStride,
241
                               TCoeff* const    piCoef,
242
                         const int              rightShift,
243
                         const int              inputMaximum,
244
                         const TCoeff           transformMaximum )
245
0
{
246
0
  const int    inputMinimum     = -( inputMaximum     + 1 );
247
0
  const TCoeff transformMinimum = -( transformMaximum + 1 );
248
249
0
  if (rightShift>0)
250
0
  {
251
0
    const Intermediate_Int iAdd = (Intermediate_Int) 1 << (rightShift - 1);
252
0
    for( int y = 0, n = 0; y <= maxY; y++)
253
0
    {
254
0
      for( int x = 0; x <= maxX; x++, n++ )
255
0
      {
256
0
        const TCoeff level = piQCoef[x + y * piQCfStride];
257
258
0
        if( level )
259
0
        {
260
0
          const TCoeff           clipQCoef = TCoeff(Clip3<Intermediate_Int>(inputMinimum, inputMaximum, level));
261
0
          Intermediate_Int iCoeffQ   = (Intermediate_Int(clipQCoef) * scale + iAdd) >> rightShift;
262
0
          piCoef[n] = TCoeff(Clip3<Intermediate_Int>(transformMinimum,transformMaximum,iCoeffQ));
263
0
        }
264
0
      }
265
0
      n += restX;
266
0
    }
267
0
  }
268
0
  else  // rightshift <0
269
0
  {
270
0
    int leftShift = -rightShift;
271
0
    for( int y = 0, n = 0; y <= maxY; y++)
272
0
    {
273
0
      for( int x = 0; x <= maxX; x++, n++ )
274
0
      {
275
0
        const TCoeff level = piQCoef[x + y * piQCfStride];
276
277
0
        if( level )
278
0
        {
279
0
          const TCoeff           clipQCoef = TCoeff(Clip3<Intermediate_Int>(inputMinimum, inputMaximum, level));
280
0
          const Intermediate_Int iCoeffQ   = (Intermediate_Int(clipQCoef) * scale) *(1<<leftShift);
281
282
0
          piCoef[n] = TCoeff(Clip3<Intermediate_Int>(transformMinimum,transformMaximum,iCoeffQ));
283
0
        }
284
0
      }
285
0
      n += restX;
286
0
    }
287
0
  }
288
0
}
289
290
static void DeQuantPCMCore( const int     maxX,
291
                            const int     restX,
292
                            const int     maxY,
293
                            const int     scale,
294
                            TCoeff* const piQCoef,
295
                            const size_t  piQCfStride,
296
                            TCoeff* const piCoef,
297
                            const int     rightShift,
298
                            const int     inputMaximum,
299
                            const TCoeff  transformMaximum )
300
0
{
301
0
  const int    inputMinimum     = -( inputMaximum + 1 );
302
0
  const TCoeff transformMinimum = -( transformMaximum + 1 );
303
304
0
  if (rightShift > 0)
305
0
  {
306
0
    const Intermediate_Int iAdd = (Intermediate_Int) 1 << (rightShift - 1);
307
0
    for( int y = 0, n = 0; y <= maxY; y++)
308
0
    {
309
0
      for( int x = 0; x <= maxX; x++, n++ )
310
0
      {
311
0
        const TCoeff level = piQCoef[x + y * piQCfStride];
312
0
        if( level )
313
0
        {
314
0
          const TCoeff           clipQCoef = TCoeff(Clip3<Intermediate_Int>(inputMinimum, inputMaximum, level));
315
0
          const Intermediate_Int iCoeffQ   = (Intermediate_Int(clipQCoef) * scale + iAdd) >> rightShift;
316
0
          piCoef[n] = TCoeff(Clip3<Intermediate_Int>(transformMinimum,transformMaximum,iCoeffQ));
317
0
        }
318
0
      }
319
0
      n += restX;
320
0
    }
321
0
  }
322
0
  else
323
0
  {
324
0
    int leftShift = -rightShift;
325
0
    for( int y = 0, n = 0; y <= maxY; y++)
326
0
    {
327
0
      for( int x = 0; x <= maxX; x++, n++ )
328
0
      {
329
0
        const TCoeff level = piQCoef[x + y * piQCfStride];
330
0
        if( level )
331
0
        {
332
0
          const TCoeff           clipQCoef = TCoeff(Clip3<Intermediate_Int>(inputMinimum, inputMaximum, level));
333
0
          const Intermediate_Int iCoeffQ   = (Intermediate_Int(clipQCoef) * scale) *(1<< leftShift);
334
335
0
          piCoef[n] = TCoeff(Clip3<Intermediate_Int>(transformMinimum,transformMaximum,iCoeffQ));
336
0
        }
337
0
      }
338
0
      n += restX;
339
0
    }
340
0
  }
341
0
}
342
343
0
Quant::Quant( const Quant* other ) : m_dequantCoefBuf( nullptr ), m_ownDequantCoeff( false )
344
0
{
345
0
  xInitScalingList( other );
346
347
0
  DeQuant    = DeQuantCore;
348
0
  DeQuantPCM = DeQuantPCMCore;
349
0
  DeQuantScaling    = DeQuantScalingCore;
350
0
  DeQuantScalingPCM = DeQuantScalingPCMCore;
351
352
0
#if ENABLE_SIMD_OPT_QUANT && defined( TARGET_SIMD_X86 )
353
354
0
  initQuantX86();
355
0
#endif
356
0
}
357
358
Quant::~Quant()
359
0
{
360
0
  xDestroyScalingList();
361
0
}
362
363
void invResDPCM( const TransformUnit &tu, const ComponentID &compID, CoeffBuf &dstBuf )
364
0
{
365
0
  const CompArea&    rect   = tu.blocks[compID];
366
0
  const int          wdt    = rect.width;
367
0
  const int          hgt    = rect.height;
368
0
  const CCoeffSigBuf coeffs = tu.cu->cs->getRecoBuf( tu.block( compID ) );
369
370
0
  const int    maxLog2TrDynamicRange = tu.cu->sps->getMaxLog2TrDynamicRange(toChannelType(compID));
371
0
  const TCoeff inputMinimum          = -(1 << maxLog2TrDynamicRange);
372
0
  const TCoeff inputMaximum          =  (1 << maxLog2TrDynamicRange) - 1;
373
374
0
  const TCoeffSig* coef = &coeffs.buf[0];
375
0
  TCoeff*          dst  = &dstBuf.buf[0];
376
377
0
  if( isLuma( compID ) ? tu.cu->bdpcmMode() == 1 : tu.cu->bdpcmModeChroma() == 1 )
378
0
  {
379
0
    for( int y = 0; y < hgt; y++ )
380
0
    {
381
0
      dst[0] = coef[0];
382
0
      for( int x = 1; x < wdt; x++ )
383
0
      {
384
0
        dst[x] = Clip3(inputMinimum, inputMaximum, dst[x - 1] + coef[x]);
385
0
      }
386
0
      coef += coeffs.stride;
387
0
      dst += dstBuf.stride;
388
0
    }
389
0
  }
390
0
  else
391
0
  {
392
0
    for( int x = 0; x < wdt; x++ )
393
0
    {
394
0
      dst[x] = coef[x];
395
0
    }
396
0
    for( int y = 0; y < hgt - 1; y++ )
397
0
    {
398
0
      for( int x = 0; x < wdt; x++ )
399
0
      {
400
0
        dst[dstBuf.stride + x] = Clip3(inputMinimum, inputMaximum, dst[x] + coef[coeffs.stride + x]);
401
0
      }
402
0
      coef += coeffs.stride;
403
0
      dst += dstBuf.stride;
404
0
    }
405
0
  }
406
0
}
407
408
static inline int getTransformShift( const int channelBitDepth, const Size size, const int maxLog2TrDynamicRange )
409
0
{
410
0
  return maxLog2TrDynamicRange - channelBitDepth - ( ( getLog2( size.width ) + getLog2( size.height ) ) >> 1 );
411
0
}
412
413
static inline int getScalingListType( const PredMode predMode, const ComponentID compID )
414
0
{
415
0
  return ( predMode == MODE_INTRA ? 0 : MAX_NUM_COMPONENT ) + compID;
416
0
}
417
418
419
void Quant::dequant( const TransformUnit& tu, CoeffBuf& dstCoeff, const ComponentID& compID, const QpParam& cQP )
420
0
{
421
0
  const SPS*             sps                   = tu.cu->sps;
422
0
  const CompArea&        area                  = tu.blocks[compID];
423
0
  const CCoeffSigBuf     coeffBuf              = tu.cu->cs->getRecoBuf( tu.block( compID ) );
424
0
  const TCoeffSig* const piQCoef               = coeffBuf.buf;
425
0
  const size_t           piQCfStride           = coeffBuf.stride;
426
0
        TCoeff* const    piCoef                = dstCoeff.buf;
427
0
  const int              maxLog2TrDynamicRange = sps->getMaxLog2TrDynamicRange( toChannelType( compID ) );
428
0
  const TCoeff           transformMaximum      =  ( 1 << maxLog2TrDynamicRange ) - 1;
429
0
  const bool             isTransformSkip       = ( tu.mtsIdx( compID ) == MTS_SKIP );
430
0
  setUseScalingList( tu.cu->slice->getExplicitScalingListUsed() );
431
0
  const bool             disableSMForLFNST     = tu.cu->slice->getExplicitScalingListUsed() ? sps->getDisableScalingMatrixForLfnstBlks() : false;
432
0
  const bool             isLfnstApplied        = tu.cu->lfnstIdx() > 0 && ( CU::isSepTree( *tu.cu ) ? true : isLuma( compID ) );
433
0
  const bool             disableSMForACT       = tu.cu->sps->getScalingMatrixForAlternativeColourSpaceDisabledFlag() && tu.cu->sps->getScalingMatrixDesignatedColourSpaceFlag() == tu.cu->colorTransform();
434
0
  const bool             enableScalingLists    = getUseScalingList( isTransformSkip, isLfnstApplied, disableSMForLFNST, disableSMForACT );
435
0
  const int              scalingListType       = getScalingListType( tu.cu->predMode(), compID );
436
0
  const int              channelBitDepth       = sps->getBitDepth();
437
438
0
  int maxX, maxY;
439
440
0
  if( ( tu.cu->bdpcmMode() && isLuma(compID) ) || ( tu.cu->bdpcmModeChroma() && isChroma(compID) ) )
441
0
  {
442
0
    invResDPCM( tu, compID, dstCoeff );
443
0
    maxX = area.width - 1;
444
0
    maxY = area.height - 1;
445
0
  }
446
0
  else
447
0
  {
448
0
    maxX = tu.maxScanPosX[compID];
449
0
    maxY = tu.maxScanPosY[compID];
450
0
  }
451
  
452
0
  CHECK(scalingListType >= SCALING_LIST_NUM, "Invalid scaling list");
453
454
  // Represents scaling through forward transform
455
0
  const bool bClipTransformShiftTo0 = false;// tu.mtsIdx[compID] != 1 && sps->getSpsRangeExtension().getExtendedPrecisionProcessingFlag();
456
0
  const int  originalTransformShift = getTransformShift(channelBitDepth, area.size(), maxLog2TrDynamicRange);
457
0
  const bool needSqrtAdjustment     = TU::needsBlockSizeTrafoScale( tu, compID );
458
0
  const int  iTransformShift        = (bClipTransformShiftTo0 ? std::max<int>(0, originalTransformShift) : originalTransformShift) + (needSqrtAdjustment?-1:0);
459
0
  const bool depQuant = tu.cu->slice->getDepQuantEnabledFlag() && ( tu.mtsIdx( compID ) != MTS_SKIP );
460
0
  const int  QP_per   = depQuant ? ( ( cQP.Qp( isTransformSkip ) + 1 ) / 6 )        : cQP.per( isTransformSkip );
461
0
  const int  QP_rem   = depQuant ? (   cQP.Qp( isTransformSkip ) + 1 - 6 * QP_per ) : cQP.rem( isTransformSkip );
462
0
  const int  rightShift = (IQUANT_SHIFT + ( depQuant ? 1 : 0 ) - ((isTransformSkip ? 0 : iTransformShift) + QP_per)) + (enableScalingLists ? LOG2_SCALING_LIST_NEUTRAL_VALUE : 0);
463
464
0
  {
465
0
    const uint32_t uiLog2TrWidth  = getLog2(area.width);
466
0
    const uint32_t uiLog2TrHeight = getLog2(area.height);
467
468
0
    int scale     = g_InvQuantScales[needSqrtAdjustment?1:0][QP_rem];
469
470
0
    const int scaleBits = ( IQUANT_SHIFT + 1 );
471
472
    //from the dequantisation equation:
473
    //iCoeffQ                         = Intermediate_Int((int64_t(clipQCoef) * scale + iAdd) >> rightShift);
474
    //(sizeof(Intermediate_Int) * 8)  =                    inputBitDepth   + scaleBits      - rightShift
475
0
    const uint32_t         targetInputBitDepth = std::min<uint32_t>((maxLog2TrDynamicRange + 1), (((sizeof(Intermediate_Int) * 8) + rightShift) - scaleBits));
476
0
    const Intermediate_Int inputMaximum        =  (1 << (targetInputBitDepth - 1)) - 1;
477
478
0
    const int restX = area.width - maxX - 1;
479
480
0
    if (!enableScalingLists)
481
0
    {
482
0
      if( ( tu.cu->bdpcmMode() && isLuma( compID ) ) || ( tu.cu->bdpcmModeChroma() && isChroma( compID ) ) )
483
0
      {
484
0
        TCoeff* dst = &dstCoeff.buf[0];
485
0
        DeQuantPCM(maxX,restX,maxY,scale,dst,dstCoeff.stride,piCoef,rightShift,inputMaximum,transformMaximum);
486
0
      }
487
0
      else
488
0
      {
489
0
        DeQuant(maxX,restX,maxY,scale,piQCoef,piQCfStride,piCoef,rightShift,inputMaximum,transformMaximum);
490
0
      }
491
0
    }
492
0
    else // Scaling Lists
493
0
    {
494
0
      int* piDequantCoef = getDequantCoeff( scalingListType, uiLog2TrWidth, uiLog2TrHeight );
495
0
      int  scaleQP       = g_InvQuantScales[needSqrtAdjustment ? 1 : 0][QP_rem];
496
0
      if( ( tu.cu->bdpcmMode() && isLuma(compID) ) || ( tu.cu->bdpcmModeChroma() && isChroma(compID) ) )
497
0
      {
498
0
        TCoeff* dst = &dstCoeff.buf[0];
499
0
        DeQuantScalingPCM(maxX,restX,maxY,scaleQP,piDequantCoef,dst,dstCoeff.stride,piCoef,rightShift,inputMaximum,transformMaximum);
500
0
      }
501
0
      else
502
0
      {
503
0
        DeQuantScaling(maxX,restX,maxY,scaleQP,piDequantCoef,piQCoef,piQCfStride,piCoef,rightShift,inputMaximum,transformMaximum);
504
0
      }
505
0
    }
506
0
  }
507
0
}
508
509
/** set quantized matrix coefficient for decode
510
 * \param scalingList quantized matrix address
511
 * \param format      chroma format
512
 */
513
void Quant::setScalingListDec( const ScalingList& scalingList )
514
0
{
515
0
  int scalingListId    = 0;
516
0
  int recScalingListId = 0;
517
0
  bool anyChange = false;
518
0
  for( uint32_t size = SCALING_LIST_FIRST_CODED; size <= SCALING_LIST_LAST_CODED; size++ )
519
0
  {
520
0
    for( uint32_t list = 0; list < SCALING_LIST_NUM; list++ )
521
0
    {
522
0
      if( size == SCALING_LIST_2x2 && list < 4 )   // skip 2x2 luma
523
0
      {
524
0
        continue;
525
0
      }
526
0
      scalingListId = g_scalingListId[size][list];
527
0
      anyChange |= xSetScalingListDec( scalingList, list, size, scalingListId );
528
0
    }
529
0
  }
530
0
  if( !anyChange ) return;
531
  // based on square result and apply downsample technology
532
0
  for( uint32_t sizew = 0; sizew <= SCALING_LIST_LAST_CODED; sizew++ )   // 7
533
0
  {
534
0
    for( uint32_t sizeh = 0; sizeh <= SCALING_LIST_LAST_CODED; sizeh++ )   // 7
535
0
    {
536
0
      if( sizew == sizeh || ( sizew == SCALING_LIST_1x1 && sizeh < SCALING_LIST_4x4 ) || ( sizeh == SCALING_LIST_1x1 && sizew < SCALING_LIST_4x4 ) )
537
0
      {
538
0
        continue;
539
0
      }
540
0
      for( uint32_t list = 0; list < SCALING_LIST_NUM; list++ )   // 9
541
0
      {
542
0
        int largerSide = ( sizew > sizeh ) ? sizew : sizeh;
543
0
        CHECK( largerSide < SCALING_LIST_4x4, "Rectangle Error!" );
544
0
        recScalingListId = g_scalingListId[largerSide][list];
545
0
        xSetRecScalingListDec( scalingList, list, sizew, sizeh, recScalingListId );
546
0
      }
547
0
    }
548
0
  }
549
0
}
550
551
/** set quantized matrix coefficient for decode
552
 * \param scalingList quantaized matrix address
553
 * \param listId List index
554
 * \param sizeId size index
555
 * \param qp Quantization parameter
556
 * \param format chroma format
557
 */
558
bool Quant::xSetScalingListDec(const ScalingList &scalingList, uint32_t listId, uint32_t sizeId, uint32_t scalingListId)
559
0
{
560
0
  const uint32_t width  = g_vvcScalingListSizeX[sizeId];
561
0
  const uint32_t height = g_vvcScalingListSizeX[sizeId];
562
#if defined( __SANITIZE_ADDRESS__ )   // work around a bug in GCC address-sanitizer, when building with -fsanitize=address, but without -fsanitize=undefined
563
  volatile
564
#endif
565
0
  const uint32_t ratio  = g_vvcScalingListSizeX[sizeId]/std::min(MAX_MATRIX_SIZE_NUM,(int)g_vvcScalingListSizeX[sizeId]);
566
567
0
  const int *coeff = scalingList.getScalingListAddress(scalingListId);
568
0
  int *dequantcoeff = getDequantCoeff(listId, sizeId, sizeId);
569
570
0
  return
571
0
  processScalingListDec(coeff,
572
0
                        dequantcoeff,
573
0
                        height, width, ratio,
574
0
                        std::min(MAX_MATRIX_SIZE_NUM, (int)g_vvcScalingListSizeX[sizeId]),
575
0
                        scalingList.getScalingListDC(scalingListId));
576
0
}
577
578
/** set quantized matrix coefficient for decode
579
* \param scalingList quantaized matrix address
580
* \param listId List index
581
* \param sizeId size index
582
* \param qp Quantization parameter
583
* \param format chroma format
584
*/
585
void Quant::xSetRecScalingListDec(const ScalingList &scalingList, uint32_t listId, uint32_t sizeIdw, uint32_t sizeIdh, uint32_t scalingListId)
586
0
{
587
0
  if (sizeIdw == sizeIdh) return;
588
589
0
  const uint32_t width  = g_vvcScalingListSizeX[sizeIdw];
590
0
  const uint32_t height = g_vvcScalingListSizeX[sizeIdh];
591
0
  const uint32_t largeSideId = (sizeIdw > sizeIdh) ? sizeIdw : sizeIdh;  //16
592
593
0
  const int *coeff = scalingList.getScalingListAddress(scalingListId);
594
0
  int *dequantcoeff = getDequantCoeff(listId, sizeIdw, sizeIdh);
595
596
0
  processScalingListDec(coeff,
597
0
                        dequantcoeff,
598
0
                        height, width, (largeSideId>3) ? 2 : 1,
599
0
                        (largeSideId >= 3 ? 8 : 4),
600
0
                        scalingList.getScalingListDC(scalingListId));
601
0
}
602
603
/** set quantized matrix coefficient for decode
604
 * \param coeff quantaized matrix address
605
 * \param dequantcoeff quantaized matrix address
606
 * \param invQuantScales IQ(QP%6))
607
 * \param height height
608
 * \param width width
609
 * \param ratio ratio for upscale
610
 * \param sizuNum matrix size
611
 * \param dc dc parameter
612
 */
613
bool Quant::processScalingListDec( const int *coeff, int *dequantcoeff, uint32_t height, uint32_t width, uint32_t ratio, int sizuNum, uint32_t dc)
614
0
{
615
0
  if (height != width)
616
0
  {
617
0
    const int hl2 = getLog2( height );
618
0
    const int wl2 = getLog2( width );
619
0
    const int sl2 = getLog2( sizuNum );
620
621
0
    const int loopH = std::min<int>( height, JVET_C0024_ZERO_OUT_TH );
622
0
    const int loopW = std::min<int>( width,  JVET_C0024_ZERO_OUT_TH );
623
    
624
0
    const int ratioWH = height > width   ? hl2 - wl2 : wl2 - hl2;
625
0
    const int ratioH  = height / sizuNum ? hl2 - sl2 : sl2 - hl2;
626
0
    const int ratioW  = width / sizuNum  ? wl2 - sl2 : sl2 - wl2;
627
628
0
    if( height > width )
629
0
    {
630
0
      for( uint32_t j = 0; j < loopH; j += ( 1 << ratioH ) )
631
0
      {
632
0
        for( uint32_t i = 0; i < loopW; i++ )
633
0
        {
634
0
          dequantcoeff[j * width + i] = coeff[sizuNum * ( j >> ratioH ) + ( ( i << ratioWH ) >> ratioH )];
635
0
        }
636
637
0
        const int* src = &dequantcoeff[j * width];
638
0
        for( int jj = 1; jj < ( 1 << ratioH ); jj++ )
639
0
        {
640
0
          memcpy( &dequantcoeff[( j + jj ) * width], src, loopW * sizeof( int ) );
641
0
        }
642
0
      }
643
0
    }
644
0
    else
645
0
    {
646
0
      for( uint32_t j = 0; j < loopH; j++ )
647
0
      {
648
0
        for( uint32_t i = 0; i < loopW; i += ( 1 << ratioW ) )
649
0
        {
650
0
          const int coeffi = coeff[sizuNum * ( ( j << ratioWH ) >> ratioW ) + ( i >> ratioW )];
651
0
          for( uint32_t ii = 0; ii < ( 1 << ratioW ); ii++ )
652
0
          {
653
0
            dequantcoeff[j * width + i + ii] = coeffi;
654
0
          }
655
0
        }
656
0
      }
657
0
    }
658
659
0
    const int largeOne = std::max( width, height );
660
0
    if( largeOne > 8 )
661
0
    {
662
0
      dequantcoeff[0] = dc;
663
0
    }
664
0
    return true;
665
0
  }
666
667
0
  bool anyChange = false;
668
669
0
  const int rl2   = getLog2( ratio );
670
0
  const int loopH = std::min<int>( height, JVET_C0024_ZERO_OUT_TH );
671
0
  const int loopW = std::min<int>( width, JVET_C0024_ZERO_OUT_TH );
672
673
0
  for( uint32_t j = 0; j < loopH; j += ( 1 << rl2 ) )
674
0
  {
675
0
    for( uint32_t i = 0; i < loopW; i += ( 1 << rl2 ) )
676
0
    {
677
0
      const int coeffi = coeff[sizuNum * ( j >> rl2 ) + ( i >> rl2 )];
678
0
      anyChange |= coeffi != dequantcoeff[j * width + i];
679
0
      for( uint32_t ii = 0; anyChange && ii < ( 1 << rl2 ); ii++ )
680
0
      {
681
0
        dequantcoeff[j * width + i + ii] = coeffi;
682
0
      }
683
0
    }
684
685
0
    const int* src = &dequantcoeff[j * width];
686
0
    for( int jj = 1; jj < ( 1 << rl2 ); jj++ )
687
0
    {
688
0
      memcpy( &dequantcoeff[( j + jj ) * width], src, loopW * sizeof( int ) );
689
0
    }
690
0
  }
691
692
0
  if( ratio > 1 )
693
0
  {
694
0
    anyChange |= dequantcoeff[0] != dc;
695
0
    dequantcoeff[0] = dc;
696
0
  }
697
698
0
  return anyChange;
699
0
}
700
701
static constexpr int g_numScalingListCoeffs = 96774;
702
703
/** initialization process of scaling list array
704
 */
705
void Quant::xInitScalingList( const Quant* other )
706
0
{
707
0
  if( other )
708
0
  {
709
0
    m_dequantCoefBuf  = other->m_dequantCoefBuf;
710
0
    m_ownDequantCoeff = false;
711
0
  }
712
0
  else
713
0
  {
714
0
    m_dequantCoefBuf  = new int[g_numScalingListCoeffs];
715
0
    m_ownDequantCoeff = true;
716
0
  }
717
718
0
  size_t numQuants = 0;
719
0
  for(uint32_t sizeIdX = 0; sizeIdX < SCALING_LIST_SIZE_NUM; sizeIdX++)
720
0
  {
721
0
    for(uint32_t sizeIdY = 0; sizeIdY < SCALING_LIST_SIZE_NUM; sizeIdY++)
722
0
    {
723
0
      for(uint32_t listId = 0; listId < SCALING_LIST_NUM; listId++)
724
0
      {
725
0
        m_dequantCoef [sizeIdX][sizeIdY][listId] = &m_dequantCoefBuf[numQuants];
726
0
        numQuants += g_vvcScalingListSizeX[sizeIdX] * g_vvcScalingListSizeX[sizeIdY];
727
0
      } // listID loop
728
0
    }
729
0
  }
730
731
0
  CHECK( numQuants != g_numScalingListCoeffs, "Incorrect size of scaling list entries number!" );
732
0
}
733
734
/** destroy quantization matrix array
735
 */
736
void Quant::xDestroyScalingList()
737
0
{
738
0
  if( m_ownDequantCoeff )
739
0
  {
740
0
    delete[] m_dequantCoefBuf;
741
0
  }
742
743
0
  m_ownDequantCoeff = false;
744
0
  m_dequantCoefBuf  = nullptr;
745
0
}
746
747
void Quant::init( const Picture *pic )
748
0
{
749
0
  const Slice* scalingListSlice = nullptr;
750
751
0
  for( const Slice* slice : pic->slices )
752
0
  {
753
0
    if( slice->getExplicitScalingListUsed() )
754
0
    {
755
0
      scalingListSlice = slice;
756
0
      break;
757
0
    }
758
0
  }
759
760
0
  const Slice* slice = scalingListSlice;
761
762
0
  if( slice && slice->getExplicitScalingListUsed() )
763
0
  {
764
0
    const std::shared_ptr<const APS> scalingListAPS = slice->getPicHeader()->getScalingListAPS();
765
0
    if( slice->getNalUnitLayerId() != scalingListAPS->getLayerId() )
766
0
    {
767
0
      CHECK( scalingListAPS->getLayerId() > slice->getNalUnitLayerId(), "Layer Id of APS cannot be greater than layer Id of VCL NAL unit the refer to it" );
768
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" );
769
0
      for( int i = 0; i < slice->getVPS()->getNumOutputLayerSets(); i++ )
770
0
      {
771
0
        bool isCurrLayerInOls = false;
772
0
        bool isRefLayerInOls = false;
773
0
        for( int j = slice->getVPS()->getNumLayersInOls(i) - 1; j >= 0; j-- )
774
0
        {
775
0
          if( slice->getVPS()->getLayerIdInOls(i, j) == slice->getNalUnitLayerId() )
776
0
          {
777
0
            isCurrLayerInOls = true;
778
0
          }
779
0
          if( slice->getVPS()->getLayerIdInOls(i, j) == scalingListAPS->getLayerId() )
780
0
          {
781
0
            isRefLayerInOls = true;
782
0
          }
783
0
        }
784
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" );
785
0
      }
786
0
    }
787
0
    const ScalingList& scalingList = scalingListAPS->getScalingList();
788
0
    if( m_ownDequantCoeff )
789
0
    {
790
0
      memset( m_dequantCoefBuf, 0, sizeof( int ) * g_numScalingListCoeffs );
791
0
      setScalingListDec( scalingList );
792
0
    }
793
0
    setUseScalingList(true);
794
0
  }
795
0
  else
796
0
  {
797
0
    setUseScalingList( false );
798
0
  }
799
0
}
800
801
}