Coverage Report

Created: 2026-05-30 06:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/work/vvenc/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) 2019-2026, Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. & The VVenC 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
44
/** \file     Quant.cpp
45
    \brief    transform and quantization class
46
*/
47
48
#include "Quant.h"
49
#include "UnitTools.h"
50
#include "ContextModelling.h"
51
#include "CodingStructure.h"
52
#include "dtrace_buffer.h"
53
54
#include <stdlib.h>
55
#include <memory.h>
56
57
//! \ingroup CommonLib
58
//! \{
59
60
namespace vvenc {
61
62
// ====================================================================================================================
63
// Constants
64
// ====================================================================================================================
65
66
67
// ====================================================================================================================
68
// QpParam constructor
69
// ====================================================================================================================
70
 
71
QpParam::QpParam(const TransformUnit& tu, const ComponentID &compID, const bool allowACTQpoffset)
72
6.88M
{
73
6.88M
  const ChannelType chType = toChannelType( compID );
74
6.88M
  const SPS        &sps    = *tu.cu->cs->sps;
75
6.88M
  const int     qpBdOffset = sps.qpBDOffset[chType];
76
6.88M
  const bool useJQP        = isChroma( compID ) && abs( TU::getICTMode( tu ) ) == 2;
77
6.88M
  const ComponentID jCbCr  = useJQP ? COMP_JOINT_CbCr : compID;
78
  
79
6.88M
        int chromaQpOffset = 0;
80
81
6.88M
  if( isChroma( compID ) )
82
6.65M
  {
83
6.65M
    const PPS &pps  = *tu.cu->slice->pps;
84
6.65M
    chromaQpOffset  = pps.chromaQpOffset              [jCbCr];
85
6.65M
    chromaQpOffset += tu.cu->slice->sliceChromaQpDelta[jCbCr];
86
6.65M
    chromaQpOffset += pps.getChromaQpOffsetListEntry( tu.cu->chromaQpAdj ).u.offset[int( jCbCr ) - 1];
87
6.65M
  }
88
  
89
6.88M
  int baseQp;
90
6.88M
  int qpy        = tu.cu->qp;
91
  //bool skip      = tu.mtsIdx[compID] == MTS_SKIP;
92
93
6.88M
  if( isLuma( compID ) )
94
233k
  {
95
233k
    baseQp = tu.cu->qp + qpBdOffset;
96
233k
  }
97
6.65M
  else
98
6.65M
  {
99
6.65M
    int qpi = Clip3( -qpBdOffset, MAX_QP, qpy );
100
6.65M
    baseQp  = sps.chromaQpMappingTable.getMappedChromaQpValue( jCbCr, qpi );
101
6.65M
    baseQp  = Clip3( -qpBdOffset, MAX_QP, baseQp + chromaQpOffset ) + qpBdOffset;
102
6.65M
  }
103
104
6.88M
  if( allowACTQpoffset && tu.cu->colorTransform )
105
0
  {
106
0
    baseQp += DELTA_QP_ACT[jCbCr];
107
0
  }
108
109
6.88M
  baseQp = Clip3( 0, MAX_QP + qpBdOffset, baseQp );
110
111
  //if( !skip )
112
6.88M
  {
113
6.88M
    Qps [0] = baseQp;
114
6.88M
    pers[0] = baseQp / 6;
115
6.88M
    rems[0] = baseQp % 6;
116
6.88M
  }
117
  //else
118
6.88M
  {
119
6.88M
    int internalMinusInputBitDepth = sps.internalMinusInputBitDepth[chType];
120
6.88M
    int baseQpTS           = std::max( baseQp, 4 + 6 * internalMinusInputBitDepth );
121
122
6.88M
    Qps [1] = baseQpTS;
123
6.88M
    pers[1] = baseQpTS / 6;
124
6.88M
    rems[1] = baseQpTS % 6;
125
6.88M
  }
126
6.88M
}
127
128
129
// ====================================================================================================================
130
// Quant class member functions
131
// ====================================================================================================================
132
static void QuantCore(const TransformUnit tu, const ComponentID compID, const CCoeffBuf& piCoef,CoeffSigBuf piQCoef,TCoeff &uiAbsSum, int &lastScanPos,TCoeff *deltaU,const int defaultQuantisationCoefficient,const int iQBits,const int64_t iAdd,const TCoeff entropyCodingMinimum,const TCoeff entropyCodingMaximum,const bool signHiding, const TCoeff m_thrVal)
133
6.05k
{
134
6.05k
  CoeffCodingContext cctx( tu, compID, signHiding );
135
136
6.05k
  const CompArea &rect      = tu.blocks[compID];
137
6.05k
  const uint32_t uiWidth    = rect.width;
138
6.05k
  const uint32_t uiHeight   = rect.height;
139
140
  /* for 422 chroma blocks, the effective scaling applied during transformation is not a power of 2, hence it cannot be
141
  * implemented as a bit-shift (the quantised result will be sqrt(2) * larger than required). Alternatively, adjust the
142
  * uiLog2TrSize applied in iTransformShift, such that the result is 1/sqrt(2) the required result (i.e. smaller)
143
  * Then a QP+3 (sqrt(2)) or QP-3 (1/sqrt(2)) method could be used to get the required result
144
  */
145
146
6.05k
  const uint32_t log2CGSize         = cctx.log2CGSize();
147
148
6.05k
  uiAbsSum = 0;
149
150
6.05k
  const int iCGSize   = 1 << log2CGSize;
151
152
6.05k
  const uint32_t lfnstIdx = tu.cu->lfnstIdx;
153
6.05k
  const int iCGNum   = lfnstIdx > 0 ? 1 : std::min<int>(JVET_C0024_ZERO_OUT_TH, uiWidth) * std::min<int>(JVET_C0024_ZERO_OUT_TH, uiHeight) >> cctx.log2CGSize();
154
6.05k
  int       iScanPos = ( iCGNum << log2CGSize ) - 1;
155
156
6.05k
  if( lfnstIdx > 0 && ( ( uiWidth == 4 && uiHeight == 4 ) || ( uiWidth == 8 && uiHeight == 8 ) ) )
157
0
  {
158
0
    iScanPos = 7;
159
0
  }
160
161
  // Find first non-zero coeff
162
33.6k
  for( ; iScanPos > 0; iScanPos-- )
163
32.1k
  {
164
32.1k
    uint32_t uiBlkPos = cctx.blockPos( iScanPos );
165
32.1k
    if( piCoef.buf[uiBlkPos] )
166
4.57k
      break;
167
32.1k
  }
168
169
  //////////////////////////////////////////////////////////////////////////
170
  //  Loop over sub-sets (coefficient groups)
171
  //////////////////////////////////////////////////////////////////////////
172
  
173
6.05k
  TCoeff thres = 0, useThres = 0;
174
  
175
6.05k
  if( iQBits )
176
6.05k
    thres = TCoeff( ( int64_t( m_thrVal ) << ( iQBits - 1 ) ) );
177
0
  else
178
0
    thres = TCoeff( ( int64_t( m_thrVal >> 1 ) << iQBits ) );
179
180
6.05k
  useThres = thres / ( defaultQuantisationCoefficient << 2 );
181
182
6.05k
  const bool is4x4sbb = log2CGSize == 4 && cctx.log2CGWidth() == 2;
183
184
6.05k
  int subSetId = iScanPos >> log2CGSize;
185
7.03k
  for( ; subSetId >= 1; subSetId-- )
186
981
  {
187
981
    if( is4x4sbb && iScanPos >= 16 )
188
0
    {
189
0
      int  iScanPosinCG = iScanPos & ( iCGSize - 1 );
190
0
      bool allSmaller   = true;
191
192
0
      for( int xScanPosinCG = iScanPosinCG, xScanPos = iScanPos; allSmaller && xScanPosinCG >= 0; xScanPosinCG--, xScanPos-- )
193
0
      {
194
0
        const uint32_t uiBlkPos = cctx.blockPos( xScanPos );
195
0
        allSmaller &= abs( piCoef.buf[uiBlkPos] ) <= useThres;
196
0
      }
197
198
0
      if( allSmaller )
199
0
      {
200
0
        iScanPos    -= iScanPosinCG + 1;
201
0
        continue;
202
0
      }
203
0
      else
204
0
      {
205
0
        break;
206
0
      }
207
0
    }
208
981
  }
209
210
6.05k
  const int qBits8 = iQBits - 8;
211
6.05k
  piQCoef.memset( 0 );
212
213
96.3k
  for( int currPos = 0; currPos <= iScanPos; currPos++ )
214
90.3k
  {
215
90.3k
    const int uiBlockPos  = cctx.blockPos( currPos );
216
90.3k
    const TCoeff iLevel   = piCoef.buf[uiBlockPos];
217
90.3k
    const TCoeff iSign    = (iLevel < 0 ? -1: 1);
218
219
90.3k
    const int64_t  tmpLevel = (int64_t)abs(iLevel) * defaultQuantisationCoefficient;
220
90.3k
    const TCoeff quantisedMagnitude = TCoeff((tmpLevel + iAdd ) >> iQBits);
221
90.3k
    deltaU[uiBlockPos] = (TCoeff)((tmpLevel - ((int64_t)quantisedMagnitude<<iQBits) )>> qBits8);
222
223
90.3k
    uiAbsSum += quantisedMagnitude;
224
90.3k
    const TCoeff quantisedCoefficient = quantisedMagnitude * iSign;
225
226
90.3k
    piQCoef.buf[uiBlockPos] = Clip3<TCoeff>( entropyCodingMinimum, entropyCodingMaximum, quantisedCoefficient );
227
90.3k
  } // for n
228
229
6.05k
  lastScanPos = iScanPos;
230
6.05k
}
231
232
static void DeQuantCore(const int maxX,const int maxY,const int scale,const TCoeffSig* const piQCoef,const size_t piQCfStride,TCoeff   *const piCoef,const int rightShift,const int inputMaximum,const TCoeff transformMaximum)
233
51.0k
{
234
51.0k
  const int inputMinimum = -(inputMaximum+1);
235
51.0k
  const TCoeff transformMinimum = -(transformMaximum+1);
236
51.0k
  if (rightShift>0)
237
40.2k
  {
238
40.2k
    const Intermediate_Int iAdd = (Intermediate_Int) 1 << (rightShift - 1);
239
384k
    for( int y = 0, n = 0; y <= maxY; y++)
240
344k
    {
241
3.71M
      for( int x = 0; x <= maxX; x++, n++ )
242
3.36M
      {
243
3.36M
        const TCoeff           clipQCoef = TCoeff(Clip3<Intermediate_Int>(inputMinimum, inputMaximum, piQCoef[x + y * piQCfStride]));
244
3.36M
        Intermediate_Int iCoeffQ   = (Intermediate_Int(clipQCoef) * scale + iAdd) >> rightShift;
245
3.36M
        piCoef[n] = TCoeff(Clip3<Intermediate_Int>(transformMinimum,transformMaximum,iCoeffQ));
246
3.36M
      }
247
344k
    }
248
40.2k
  }
249
10.7k
  else  // rightshift <0
250
10.7k
  {
251
10.7k
    int leftShift = -rightShift;
252
130k
    for( int y = 0, n = 0; y <= maxY; y++)
253
119k
    {
254
1.45M
      for( int x = 0; x <= maxX; x++, n++ )
255
1.33M
      {
256
1.33M
        const TCoeff           clipQCoef = TCoeff(Clip3<Intermediate_Int>(inputMinimum, inputMaximum, piQCoef[x + y * piQCfStride]));
257
1.33M
        const Intermediate_Int iCoeffQ   = (Intermediate_Int(clipQCoef) * scale) * (1 << leftShift);
258
1.33M
        piCoef[n] = TCoeff(Clip3<Intermediate_Int>(transformMinimum,transformMaximum,iCoeffQ));
259
1.33M
      }
260
119k
    }
261
10.7k
  }
262
51.0k
}
263
264
static bool needRdoqCore( const TCoeff* pCoeff, size_t numCoeff, int quantCoeff, int64_t offset, int shift )
265
0
{
266
0
  for( int uiBlockPos = 0; uiBlockPos < numCoeff; uiBlockPos++ )
267
0
  {
268
0
    const TCoeff   iLevel = pCoeff[uiBlockPos];
269
0
    const int64_t  tmpLevel = ( int64_t ) std::abs( iLevel ) * quantCoeff;
270
0
    const TCoeff quantisedMagnitude = TCoeff( ( tmpLevel + offset ) >> shift );
271
272
0
    if( quantisedMagnitude != 0 )
273
0
    {
274
0
      return true;
275
0
    }
276
0
  } // for n
277
0
  return false;
278
0
}
279
280
281
20.7k
Quant::Quant( const Quant* other, bool useScalingLists ) : m_RDOQ( 0 ), m_useRDOQTS( false ), m_dLambda( 0.0 )
282
20.7k
{
283
20.7k
  xInitScalingList( other, useScalingLists );
284
20.7k
  xDeQuant  = DeQuantCore;
285
20.7k
  xQuant    = QuantCore;
286
20.7k
  xNeedRdoq = needRdoqCore;
287
#if defined( TARGET_SIMD_X86 ) && ENABLE_SIMD_OPT_QUANT
288
  initQuantX86();
289
#endif
290
291
20.7k
}
292
293
Quant::~Quant()
294
20.7k
{
295
20.7k
  xDestroyScalingList();
296
20.7k
}
297
298
void invResDPCM( const TransformUnit& tu, const ComponentID compID, CoeffSigBuf& dstBuf )
299
51.0k
{
300
51.0k
  const CompArea&    rect   = tu.blocks[compID];
301
51.0k
  const int          wdt    = rect.width;
302
51.0k
  const int          hgt    = rect.height;
303
51.0k
  const CCoeffSigBuf coeffs = tu.getCoeffs(compID);
304
305
51.0k
  const int      maxLog2TrDynamicRange = tu.cs->sps->getMaxLog2TrDynamicRange();
306
51.0k
  const TCoeff   inputMinimum          = -(1 << maxLog2TrDynamicRange);
307
51.0k
  const TCoeff   inputMaximum          =  (1 << maxLog2TrDynamicRange) - 1;
308
309
51.0k
  const TCoeffSig* coef = &coeffs.buf[0];
310
51.0k
        TCoeffSig* dst  = &dstBuf.buf[0];
311
312
51.0k
  if ( tu.cu->bdpcmM[toChannelType(compID)] == 1)
313
525
  {
314
7.64k
    for( int y = 0; y < hgt; y++ )
315
7.11k
    {
316
7.11k
      dst[0] = coef[0];
317
113k
      for( int x = 1; x < wdt; x++ )
318
106k
      {
319
106k
        dst[x] = Clip3(inputMinimum, inputMaximum, TCoeff( dst[x - 1] ) + TCoeff( coef[x] ));
320
106k
      }
321
7.11k
      coef += coeffs.stride;
322
7.11k
      dst += dstBuf.stride;
323
7.11k
    }
324
525
  }
325
50.5k
  else
326
50.5k
  {
327
536k
    for( int x = 0; x < wdt; x++ )
328
486k
    {
329
486k
      dst[x] = coef[x];
330
486k
    }
331
457k
    for( int y = 0; y < hgt - 1; y++ )
332
406k
    {
333
4.51M
      for( int x = 0; x < wdt; x++ )
334
4.10M
      {
335
4.10M
        dst[dstBuf.stride + x] = Clip3(inputMinimum, inputMaximum, TCoeff( dst[x] ) + TCoeff( coef[coeffs.stride + x] ));
336
4.10M
      }
337
406k
      coef += coeffs.stride;
338
406k
      dst += dstBuf.stride;
339
406k
    }
340
50.5k
  }
341
51.0k
}
342
343
void fwdResDPCM( TransformUnit& tu, const ComponentID compID )
344
6.05k
{
345
6.05k
  const CompArea& rect   = tu.blocks[compID];
346
6.05k
  const int       wdt    = rect.width;
347
6.05k
  const int       hgt    = rect.height;
348
6.05k
  CoeffSigBuf     coeffs = tu.getCoeffs(compID);
349
350
6.05k
  TCoeffSig* coef = &coeffs.buf[0];
351
6.05k
  if (tu.cu->bdpcmM[toChannelType(compID)] == 1)
352
0
  {
353
0
    for( int y = 0; y < hgt; y++ )
354
0
    {
355
0
      for( int x = wdt - 1; x > 0; x-- )
356
0
      {
357
0
        coef[x] -= coef[x - 1];
358
0
      }
359
0
      coef += coeffs.stride;
360
0
    }
361
0
  }
362
6.05k
  else
363
6.05k
  {
364
6.05k
    coef += coeffs.stride * (hgt - 1);
365
12.1k
    for( int y = 0; y < hgt - 1; y++ )
366
6.05k
    {
367
65.0k
      for ( int x = 0; x < wdt; x++ )
368
58.9k
      {
369
58.9k
        coef[x] -= coef[x - coeffs.stride];
370
58.9k
      }
371
6.05k
      coef -= coeffs.stride;
372
6.05k
    }
373
6.05k
  }
374
6.05k
}
375
376
// To minimize the distortion only. No rate is considered.
377
void Quant::xSignBitHidingHDQ( TCoeffSig* pQCoef, const TCoeff* pCoef, TCoeff* deltaU, const CoeffCodingContext& cctx, int& lastScanPos, const int maxLog2TrDynamicRange )
378
0
{
379
0
  const uint32_t groupSize = 1 << cctx.log2CGSize();
380
381
0
  const TCoeff entropyCodingMinimum = -(1 << maxLog2TrDynamicRange);
382
0
  const TCoeff entropyCodingMaximum =  (1 << maxLog2TrDynamicRange) - 1;
383
384
0
  int lastCG = -1;
385
0
  int absSum = 0 ;
386
0
  int n ;
387
388
0
  for( int subSet = lastScanPos >> cctx.log2CGSize(); subSet >= 0; subSet-- )
389
0
  {
390
0
    int  subPos = subSet << cctx.log2CGSize();
391
0
    int  firstNZPosInCG=groupSize , lastNZPosInCG=-1 ;
392
0
    absSum = 0 ;
393
394
0
    for(n = groupSize-1; n >= 0; --n )
395
0
    {
396
0
      if( pQCoef[ cctx.blockPos( n + subPos ) ] )
397
0
      {
398
0
        lastNZPosInCG = n;
399
0
        break;
400
0
      }
401
0
    }
402
403
0
    for(n = 0; n <groupSize; n++ )
404
0
    {
405
0
      if( pQCoef[ cctx.blockPos( n + subPos ) ] )
406
0
      {
407
0
        firstNZPosInCG = n;
408
0
        break;
409
0
      }
410
0
    }
411
412
0
    for(n = firstNZPosInCG; n <=lastNZPosInCG; n++ )
413
0
    {
414
0
      absSum += int(pQCoef[ cctx.blockPos( n + subPos ) ]);
415
0
    }
416
417
0
    if(lastNZPosInCG>=0 && lastCG==-1)
418
0
    {
419
0
      lastCG = 1 ;
420
0
    }
421
422
0
    if( lastNZPosInCG-firstNZPosInCG>=SBH_THRESHOLD )
423
0
    {
424
0
      uint32_t signbit = (pQCoef[cctx.blockPos(subPos+firstNZPosInCG)]>0?0:1) ;
425
0
      if( signbit!=(absSum&0x1) )  //compare signbit with sum_parity
426
0
      {
427
0
        TCoeff curCost    = std::numeric_limits<TCoeff>::max();
428
0
        TCoeff minCostInc = std::numeric_limits<TCoeff>::max();
429
0
        int minPos =-1, finalChange=0, curChange=0, minScanPos = -1;
430
431
0
        for( n = (lastCG==1?lastNZPosInCG:groupSize-1) ; n >= 0; --n )
432
0
        {
433
0
          uint32_t blkPos   = cctx.blockPos( n+subPos );
434
0
          if(pQCoef[ blkPos ] != 0 )
435
0
          {
436
0
            if(deltaU[blkPos]>0)
437
0
            {
438
0
              curCost = - deltaU[blkPos];
439
0
              curChange=1 ;
440
0
            }
441
0
            else
442
0
            {
443
              //curChange =-1;
444
0
              if(n==firstNZPosInCG && abs(pQCoef[blkPos])==1)
445
0
              {
446
0
                curCost = std::numeric_limits<TCoeff>::max();
447
0
              }
448
0
              else
449
0
              {
450
0
                curCost = deltaU[blkPos];
451
0
                curChange =-1;
452
0
              }
453
0
            }
454
0
          }
455
0
          else
456
0
          {
457
0
            if(n<firstNZPosInCG)
458
0
            {
459
0
              uint32_t thisSignBit = (pCoef[blkPos]>=0?0:1);
460
0
              if(thisSignBit != signbit )
461
0
              {
462
0
                curCost = std::numeric_limits<TCoeff>::max();
463
0
              }
464
0
              else
465
0
              {
466
0
                curCost = - (deltaU[blkPos])  ;
467
0
                curChange = 1 ;
468
0
              }
469
0
            }
470
0
            else
471
0
            {
472
0
              curCost = - (deltaU[blkPos])  ;
473
0
              curChange = 1 ;
474
0
            }
475
0
          }
476
477
0
          if( curCost<minCostInc)
478
0
          {
479
0
            minCostInc = curCost ;
480
0
            finalChange = curChange ;
481
0
            minPos = blkPos;
482
0
            minScanPos = n + subPos;
483
0
          }
484
0
        } //CG loop
485
486
0
        if(pQCoef[minPos] == entropyCodingMaximum || pQCoef[minPos] == entropyCodingMinimum)
487
0
        {
488
0
          finalChange = -1;
489
0
        }
490
491
0
        if(pCoef[minPos]>=0)
492
0
        {
493
0
          pQCoef[minPos] += finalChange ;
494
0
        }
495
0
        else
496
0
        {
497
0
          pQCoef[minPos] -= finalChange ;
498
0
        }
499
500
        // if changing lastScanPos element to 0, move the pointer to the new lastScanPos element
501
0
        if( minScanPos == lastScanPos && pQCoef[minPos] == 0 )
502
0
        {
503
0
          for( ; lastScanPos >= 0 && pQCoef[cctx.blockPos( lastScanPos )] == 0; lastScanPos-- );
504
0
        }
505
0
        else if( minScanPos > lastScanPos && pQCoef[minPos] != 0 )
506
0
        {
507
0
          lastScanPos = minPos;
508
0
        }
509
0
      } // Hide
510
0
    }
511
0
    if(lastCG==1)
512
0
    {
513
0
      lastCG=0 ;
514
0
    }
515
0
  } // TU loop
516
517
0
  return;
518
0
}
519
520
void Quant::dequant(const TransformUnit& tu,
521
                          CoeffBuf&      dstCoeff,
522
                    const ComponentID    compID,
523
                    const QpParam&       cQP)
524
51.0k
{
525
51.0k
  const SPS       *sps                  = tu.cs->sps;
526
51.0k
  const CompArea  &area                 = tu.blocks[compID];
527
51.0k
  const uint32_t  uiWidth               = area.width;
528
51.0k
  const uint32_t  uiHeight              = area.height;
529
51.0k
  TCoeff *const   piCoef                = dstCoeff.buf;
530
51.0k
  const uint32_t  numSamplesInBlock     = uiWidth * uiHeight;
531
51.0k
  const int       maxLog2TrDynamicRange = sps->getMaxLog2TrDynamicRange();
532
51.0k
  const TCoeff    transformMinimum      = -(1 << maxLog2TrDynamicRange);
533
51.0k
  const TCoeff    transformMaximum      =  (1 << maxLog2TrDynamicRange) - 1;
534
51.0k
  const bool      isTransformSkip       = tu.mtsIdx[compID] == MTS_SKIP;
535
51.0k
  const bool      isLfnstApplied        = tu.cu->lfnstIdx > 0 && (CU::isSepTree(*tu.cu) ? true : isLuma(compID));
536
51.0k
  const bool      enableScalingLists    = getUseScalingList(uiWidth, uiHeight, isTransformSkip, isLfnstApplied);
537
51.0k
  const int       scalingListType       = getScalingListType(tu.cu->predMode, compID);
538
51.0k
  const int       channelBitDepth       = sps->bitDepths[toChannelType(compID)];
539
540
51.0k
  const TCoeffSig *coef     = tu.getCoeffs( compID ).buf;
541
51.0k
  const ptrdiff_t  piStride = tu.getCoeffs( compID ).stride;
542
543
51.0k
  if( tu.cu->bdpcmM[toChannelType( compID )] )
544
51.0k
  {
545
51.0k
    CoeffSigBuf coefBuf( m_tmpBdpcm, uiWidth, uiHeight );
546
51.0k
    invResDPCM( tu, compID, coefBuf );
547
51.0k
    coef      = m_tmpBdpcm;
548
51.0k
  }
549
550
51.0k
  const TCoeffSig  *const piQCoef = coef;
551
51.0k
  CHECK(scalingListType >= SCALING_LIST_NUM, "Invalid scaling list");
552
553
  // Represents scaling through forward transform
554
51.0k
  const int  originalTransformShift = getTransformShift(channelBitDepth, area.size(), maxLog2TrDynamicRange);
555
51.0k
  const bool needSqrtAdjustment     = TU::needsSqrt2Scale( tu, compID );
556
51.0k
  const int  iTransformShift        = originalTransformShift + (needSqrtAdjustment?-1:0);
557
558
51.0k
  const int QP_per = cQP.per(isTransformSkip);
559
51.0k
  const int QP_rem = cQP.rem(isTransformSkip);
560
561
51.0k
  const int  rightShift = (IQUANT_SHIFT - ((isTransformSkip ? 0 : iTransformShift) + QP_per)) + (enableScalingLists ? LOG2_SCALING_LIST_NEUTRAL_VALUE : 0);
562
563
51.0k
  if(enableScalingLists)
564
0
  {
565
    //from the dequantization equation:
566
    //iCoeffQ                         = ((Intermediate_Int(clipQCoef) * piDequantCoef[deQuantIdx]) + iAdd ) >> rightShift
567
    //(sizeof(Intermediate_Int) * 8)  =              inputBitDepth    +    dequantCoefBits                   - rightShift
568
0
    const uint32_t             dequantCoefBits     = 1 + IQUANT_SHIFT + SCALING_LIST_BITS;
569
0
    const uint32_t             targetInputBitDepth = std::min<uint32_t>((maxLog2TrDynamicRange + 1), (((sizeof(Intermediate_Int) * 8) + rightShift) - dequantCoefBits));
570
571
0
    const Intermediate_Int inputMinimum        = -(1 << (targetInputBitDepth - 1));
572
0
    const Intermediate_Int inputMaximum        =  (1 << (targetInputBitDepth - 1)) - 1;
573
574
0
    const uint32_t uiLog2TrWidth  = Log2(uiWidth);
575
0
    const uint32_t uiLog2TrHeight = Log2(uiHeight);
576
0
    int* piDequantCoef            = getDequantCoeff(scalingListType, QP_rem, uiLog2TrWidth, uiLog2TrHeight);
577
578
0
    if(rightShift > 0)
579
0
    {
580
0
      const Intermediate_Int iAdd = (Intermediate_Int) 1 << (rightShift - 1);
581
0
      for( int n = 0; n < numSamplesInBlock; n++ )
582
0
      {
583
0
        const TCoeff           clipQCoef = TCoeff(Clip3<Intermediate_Int>(inputMinimum, inputMaximum, piQCoef[n]));
584
0
        const Intermediate_Int iCoeffQ   = ((Intermediate_Int(clipQCoef) * piDequantCoef[n]) + iAdd ) >> rightShift;
585
0
        piCoef[n] = TCoeff(Clip3<Intermediate_Int>(transformMinimum,transformMaximum,iCoeffQ));
586
0
      }
587
0
    }
588
0
    else
589
0
    {
590
0
      const int leftShift = -rightShift;
591
0
      for( int n = 0; n < numSamplesInBlock; n++ )
592
0
      {
593
0
        const TCoeff           clipQCoef = TCoeff(Clip3<Intermediate_Int>(inputMinimum, inputMaximum, piQCoef[n]));
594
0
        const Intermediate_Int iCoeffQ   = (Intermediate_Int(clipQCoef) * piDequantCoef[n]) << leftShift;
595
0
        piCoef[n] = TCoeff(Clip3<Intermediate_Int>(transformMinimum,transformMaximum,iCoeffQ));
596
0
      }
597
0
    }
598
0
  }
599
51.0k
  else
600
51.0k
  {
601
51.0k
    const int scale     = g_invQuantScales[needSqrtAdjustment?1:0][QP_rem];
602
51.0k
    const int scaleBits = ( IQUANT_SHIFT + 1 );
603
    //from the dequantisation equation:
604
    //iCoeffQ                         = Intermediate_Int((int64_t(clipQCoef) * scale + iAdd) >> rightShift);
605
    //(sizeof(Intermediate_Int) * 8)  =                    inputBitDepth   + scaleBits      - rightShift
606
51.0k
    const uint32_t             targetInputBitDepth = std::min<uint32_t>((maxLog2TrDynamicRange + 1), (((sizeof(Intermediate_Int) * 8) + rightShift) - scaleBits));
607
51.0k
    const Intermediate_Int inputMaximum        =  (1 << (targetInputBitDepth - 1)) - 1;
608
51.0k
    xDeQuant(uiWidth-1,uiHeight-1,scale,piQCoef,piStride,piCoef,rightShift,inputMaximum,transformMaximum);
609
51.0k
  }
610
51.0k
}
611
612
void Quant::init( int rdoq, bool bUseRDOQTS, int thrVal )
613
20.7k
{
614
615
  // TODO: pass to init() a single variable containing (quantization) flags,
616
  //       instead of variables that don't have to do with this class
617
618
20.7k
  m_RDOQ             = rdoq;
619
20.7k
  m_useRDOQTS        = bUseRDOQTS;
620
20.7k
  m_thrVal           = thrVal;
621
20.7k
}
622
623
/** set flat matrix value to quantized coefficient
624
 */
625
void Quant::setFlatScalingList(const int maxLog2TrDynamicRange[MAX_NUM_CH], const BitDepths &bitDepths )
626
20.7k
{
627
20.7k
  if( !m_scalingListEnabled ) return;
628
629
0
  const int minimumQp = 0;
630
0
  const int maximumQp = SCALING_LIST_REM_NUM;
631
632
0
  for(uint32_t sizeX = 0; sizeX < SCALING_LIST_SIZE_NUM; sizeX++)
633
0
  {
634
0
    for(uint32_t sizeY = 0; sizeY < SCALING_LIST_SIZE_NUM; sizeY++)
635
0
    {
636
0
      for(uint32_t list = 0; list < SCALING_LIST_NUM; list++)
637
0
      {
638
0
        for(int qp = minimumQp; qp < maximumQp; qp++)
639
0
        {
640
0
          xSetFlatScalingList( list, sizeX, sizeY, qp );
641
0
        }
642
0
      }
643
0
    }
644
0
  }
645
0
}
646
647
/** set flat matrix value to quantized coefficient
648
 * \param list List ID
649
 * \param size size index
650
 * \param qp Quantization parameter
651
 * \param format chroma format
652
 */
653
void Quant::xSetFlatScalingList(uint32_t list, uint32_t sizeX, uint32_t sizeY, int qp )
654
0
{
655
0
  uint32_t i,num = g_scalingListSizeX[sizeX]*g_scalingListSizeX[sizeY];
656
0
  int *quantcoeff;
657
0
  int *dequantcoeff;
658
659
0
  const bool blockIsNotPowerOf4 = ((Log2(g_scalingListSizeX[sizeX] * g_scalingListSizeX[sizeY])) & 1) == 1;
660
0
  int quantScales    = g_quantScales   [blockIsNotPowerOf4?1:0][qp];
661
0
  int invQuantScales = g_invQuantScales[blockIsNotPowerOf4?1:0][qp] << 4;
662
663
0
  quantcoeff   = getQuantCoeff(list, qp, sizeX, sizeY);
664
0
  dequantcoeff = getDequantCoeff(list, qp, sizeX, sizeY);
665
666
0
  for(i=0;i<num;i++)
667
0
  {
668
0
    *quantcoeff++ = quantScales;
669
0
    *dequantcoeff++ = invQuantScales;
670
0
  }
671
0
}
672
673
674
/** initialization process of scaling list array
675
 */
676
void Quant::xInitScalingList( const Quant* other, bool useScalingLists )
677
20.7k
{
678
20.7k
  m_isScalingListOwner = other == nullptr;
679
20.7k
  m_scalingListEnabled = useScalingLists;
680
681
166k
  for(uint32_t sizeIdX = 0; sizeIdX < SCALING_LIST_SIZE_NUM; sizeIdX++)
682
145k
  {
683
1.16M
    for(uint32_t sizeIdY = 0; sizeIdY < SCALING_LIST_SIZE_NUM; sizeIdY++)
684
1.01M
    {
685
7.12M
      for(uint32_t qp = 0; qp < SCALING_LIST_REM_NUM; qp++)
686
6.10M
      {
687
42.7M
        for(uint32_t listId = 0; listId < SCALING_LIST_NUM; listId++)
688
36.6M
        {
689
36.6M
          if( m_isScalingListOwner )
690
36.6M
          {
691
36.6M
            const size_t scalingListSize = g_scalingListSizeX[sizeIdX] * g_scalingListSizeX[sizeIdY];
692
693
36.6M
            m_quantCoef   [sizeIdX][sizeIdY][listId][qp] = useScalingLists ? new int[scalingListSize] : nullptr;
694
36.6M
            m_dequantCoef [sizeIdX][sizeIdY][listId][qp] = useScalingLists ? new int[scalingListSize] : nullptr;
695
36.6M
          }
696
0
          else
697
0
          {
698
0
            m_quantCoef   [sizeIdX][sizeIdY][listId][qp] = other->m_quantCoef   [sizeIdX][sizeIdY][listId][qp];
699
0
            m_dequantCoef [sizeIdX][sizeIdY][listId][qp] = other->m_dequantCoef [sizeIdX][sizeIdY][listId][qp];
700
0
          }
701
36.6M
        } // listID loop
702
6.10M
      }
703
1.01M
    }
704
145k
  }
705
20.7k
}
706
707
/** destroy quantization matrix array
708
 */
709
void Quant::xDestroyScalingList()
710
20.7k
{
711
20.7k
  if( !m_isScalingListOwner ) return;
712
713
166k
  for(uint32_t sizeIdX = 0; sizeIdX < SCALING_LIST_SIZE_NUM; sizeIdX++)
714
145k
  {
715
1.16M
    for(uint32_t sizeIdY = 0; sizeIdY < SCALING_LIST_SIZE_NUM; sizeIdY++)
716
1.01M
    {
717
7.12M
      for(uint32_t listId = 0; listId < SCALING_LIST_NUM; listId++)
718
6.10M
      {
719
42.7M
        for(uint32_t qp = 0; qp < SCALING_LIST_REM_NUM; qp++)
720
36.6M
        {
721
36.6M
          if(m_quantCoef[sizeIdX][sizeIdY][listId][qp])
722
0
          {
723
0
            delete [] m_quantCoef[sizeIdX][sizeIdY][listId][qp];
724
0
          }
725
36.6M
          if(m_dequantCoef[sizeIdX][sizeIdY][listId][qp])
726
0
          {
727
0
            delete [] m_dequantCoef[sizeIdX][sizeIdY][listId][qp];
728
0
          }
729
36.6M
        }
730
6.10M
      }
731
1.01M
    }
732
145k
  }
733
20.7k
}
734
735
void Quant::quant(TransformUnit& tu, const ComponentID compID, const CCoeffBuf& pSrc, TCoeff &uiAbsSum, const QpParam& cQP, const Ctx& ctx)
736
6.05k
{
737
6.05k
  const SPS &sps            = *tu.cs->sps;
738
6.05k
  const CompArea& rect      = tu.blocks[compID];
739
6.05k
  const uint32_t uiWidth    = rect.width;
740
6.05k
  const uint32_t uiHeight   = rect.height;
741
6.05k
  const int channelBitDepth = sps.bitDepths[toChannelType(compID)];
742
743
6.05k
  const CCoeffBuf&  piCoef  = pSrc;
744
6.05k
        CoeffSigBuf piQCoef = tu.getCoeffs(compID);
745
746
6.05k
  const bool useTransformSkip = tu.mtsIdx[compID] == MTS_SKIP;
747
6.05k
  const int  maxLog2TrDynamicRange = sps.getMaxLog2TrDynamicRange();
748
749
6.05k
  {
750
6.05k
    CoeffCodingContext cctx(tu, compID, tu.cs->slice->signDataHidingEnabled);
751
752
6.05k
    const TCoeff entropyCodingMinimum = -(1 << maxLog2TrDynamicRange);
753
6.05k
    const TCoeff entropyCodingMaximum =  (1 << maxLog2TrDynamicRange) - 1;
754
755
6.05k
    TCoeff deltaU[MAX_TB_SIZEY * MAX_TB_SIZEY];
756
6.05k
    int scalingListType           = getScalingListType(tu.cu->predMode, compID);
757
6.05k
    CHECK(scalingListType >= SCALING_LIST_NUM, "Invalid scaling list");
758
6.05k
    const uint32_t uiLog2TrWidth  = Log2(uiWidth);
759
6.05k
    const uint32_t uiLog2TrHeight = Log2(uiHeight);
760
6.05k
    int *piQuantCoeff             = getQuantCoeff(scalingListType, cQP.rem(useTransformSkip), uiLog2TrWidth, uiLog2TrHeight);
761
762
6.05k
    const bool isLfnstApplied     = tu.cu->lfnstIdx > 0 && (CU::isSepTree(*tu.cu) ? true : isLuma(compID));
763
6.05k
    const bool enableScalingLists = getUseScalingList(uiWidth, uiHeight, useTransformSkip, isLfnstApplied);
764
765
    // for blocks that where width*height != 4^N, the effective scaling applied during transformation cannot be
766
    // compensated by a bit-shift (the quantised result will be sqrt(2) * larger than required).
767
    // The quantScale table and shift is used to compensate for this.
768
6.05k
    const bool needSqrtAdjustment= TU::needsSqrt2Scale( tu, compID );
769
6.05k
    const int defaultQuantisationCoefficient    = g_quantScales[needSqrtAdjustment?1:0][cQP.rem(useTransformSkip)];
770
6.05k
    const int iTransformShift = getTransformShift(channelBitDepth, rect.size(), maxLog2TrDynamicRange) + ( needSqrtAdjustment?-1:0);
771
772
6.05k
    const int iQBits = QUANT_SHIFT + cQP.per(useTransformSkip) + (useTransformSkip ? 0 : iTransformShift);
773
    // QBits will be OK for any internal bit depth as the reduction in transform shift is balanced by an increase in Qp_per due to QpBDOffset
774
775
6.05k
    const int64_t iAdd = int64_t(tu.cs->slice->isIRAP() ? 171 : 85) << int64_t(iQBits - 9);
776
6.05k
    const int qBits8 = iQBits - 8;
777
778
6.05k
    int lastScanPos = -1;
779
780
6.05k
    if (!enableScalingLists)
781
6.05k
      xQuant(tu,compID,piCoef,piQCoef,uiAbsSum,lastScanPos,deltaU,defaultQuantisationCoefficient,iQBits,iAdd,entropyCodingMinimum,entropyCodingMaximum,cctx.signHiding(),m_thrVal);
782
0
    else
783
0
    {
784
0
      const uint32_t lfnstIdx = tu.cu->lfnstIdx;
785
0
      const int maxNumberOfCoeffs = lfnstIdx > 0 ? ( ( ( uiWidth == 4 && uiHeight == 4 ) || ( uiWidth == 8 && uiHeight == 8 ) ) ? 8 : 16 ) : piQCoef.area();
786
787
0
      piQCoef.memset( 0 );
788
0
      for (int uiScanPos = 0; uiScanPos < maxNumberOfCoeffs; uiScanPos++ )
789
0
      {
790
0
        const int uiBlockPos  = cctx.blockPos( uiScanPos );
791
0
        const TCoeff iLevel   = piCoef.buf[uiBlockPos];
792
0
        const TCoeff iSign    = (iLevel < 0 ? -1: 1);
793
794
0
        const int64_t  tmpLevel = (int64_t)abs(iLevel) * (enableScalingLists ? piQuantCoeff[uiBlockPos] : defaultQuantisationCoefficient);
795
0
        const TCoeff quantisedMagnitude = TCoeff((tmpLevel + iAdd ) >> iQBits);
796
0
        deltaU[uiBlockPos] = (TCoeff)((tmpLevel - ((int64_t)quantisedMagnitude<<iQBits) )>> qBits8);
797
798
0
        uiAbsSum += quantisedMagnitude;
799
0
        const TCoeff quantisedCoefficient = quantisedMagnitude * iSign;
800
801
0
        piQCoef.buf[uiBlockPos] = Clip3<TCoeff>( entropyCodingMinimum, entropyCodingMaximum, quantisedCoefficient );
802
0
      } // for n
803
0
    }
804
6.05k
    if (tu.cu->bdpcmM[toChannelType(compID)])
805
6.05k
    {
806
6.05k
      fwdResDPCM( tu, compID );
807
6.05k
    }
808
809
6.05k
    if( uiAbsSum )
810
3.63k
    {
811
7.26k
      for( int scanPos = lastScanPos; scanPos >= 0; scanPos-- )
812
7.26k
      {
813
7.26k
        unsigned blkPos = cctx.blockPos( scanPos );
814
7.26k
        if( piQCoef.buf[blkPos] )
815
3.63k
        {
816
3.63k
          lastScanPos = scanPos;
817
3.63k
          break;
818
3.63k
        }
819
7.26k
      }
820
821
3.63k
      if( cctx.signHiding() )
822
0
      {
823
0
        if( uiAbsSum >= 2 ) //this prevents TUs with only one coefficient of value 1 from being tested
824
0
        {
825
0
          xSignBitHidingHDQ( piQCoef.buf, piCoef.buf, deltaU, cctx, lastScanPos, maxLog2TrDynamicRange );
826
0
        }
827
0
      }
828
3.63k
    }
829
830
6.05k
    tu.lastPos[compID] = lastScanPos;
831
6.05k
  } //if RDOQ
832
  //return;
833
6.05k
}
834
835
bool Quant::xNeedRDOQ(TransformUnit& tu, const ComponentID compID, const CCoeffBuf& pSrc, const QpParam& cQP)
836
0
{
837
0
  const SPS &sps            = *tu.cs->sps;
838
0
  const CompArea& rect      = tu.blocks[compID];
839
0
  const uint32_t uiWidth    = rect.width;
840
0
  const uint32_t uiHeight   = rect.height;
841
0
  const uint32_t efHeight   = std::min<unsigned>( uiHeight, JVET_C0024_ZERO_OUT_TH );
842
0
  const uint32_t efArea     = uiWidth * efHeight;
843
0
  const int channelBitDepth = sps.bitDepths[toChannelType(compID)];
844
0
  const CCoeffBuf piCoef    = pSrc;
845
846
0
  const bool useTransformSkip      = tu.mtsIdx[compID] == MTS_SKIP;
847
0
  const int  maxLog2TrDynamicRange = sps.getMaxLog2TrDynamicRange();
848
849
0
  const int scalingListType     = getScalingListType( tu.cu->predMode, compID );
850
0
  CHECK( scalingListType >= SCALING_LIST_NUM, "Invalid scaling list" );
851
852
0
  const bool        isDq        = tu.cs->slice->depQuantEnabled && !useTransformSkip;
853
0
  const int         qpDQ        = isDq ? cQP.Qp( false ) + 1 : cQP.Qp( useTransformSkip );
854
0
  const int         qpPer       = isDq ? qpDQ / 6 : cQP.per( useTransformSkip );
855
0
  const int         qpRem       = isDq ? qpDQ - 6 * qpPer : cQP.rem( useTransformSkip );
856
857
0
  const uint32_t uiLog2TrWidth  = Log2( uiWidth );
858
0
  const uint32_t uiLog2TrHeight = Log2( uiHeight );
859
0
  int *piQuantCoeff             = getQuantCoeff( scalingListType, qpRem, uiLog2TrWidth, uiLog2TrHeight );
860
861
0
  const bool isLfnstApplied     = tu.cu->lfnstIdx > 0 && ( CU::isSepTree( *tu.cu ) ? true : isLuma( compID ) );
862
0
  const bool enableScalingLists = getUseScalingList( uiWidth, uiHeight, ( useTransformSkip != 0 ), isLfnstApplied );
863
864
0
  const bool needSqrtAdjustment = TU::needsSqrt2Scale( tu, compID );
865
0
  const int defaultQuantisationCoefficient
866
0
                                = g_quantScales[needSqrtAdjustment?1:0][qpRem];
867
0
  const int iTransformShift     = getTransformShift( channelBitDepth, rect.size(), maxLog2TrDynamicRange ) + ( needSqrtAdjustment ? -1 : 0 );
868
869
870
0
  const int iQBits              = QUANT_SHIFT + qpPer + iTransformShift;
871
872
  // QBits will be OK for any internal bit depth as the reduction in transform shift is balanced by an increase in Qp_per due to QpBDOffset
873
  // iAdd is different from the iAdd used in normal quantization
874
0
  const int64_t iAdd = int64_t( compID == COMP_Y ? 171 : 256 ) << ( iQBits - 9 );
875
876
0
  if( !enableScalingLists )
877
0
    return xNeedRdoq( piCoef.buf, efArea, defaultQuantisationCoefficient, iAdd, iQBits );
878
879
0
  for( int uiBlockPos = 0; uiBlockPos < efArea; uiBlockPos++ )
880
0
  {
881
0
    const TCoeff   iLevel           = piCoef.buf[uiBlockPos];
882
0
    const int64_t  tmpLevel         = ( int64_t ) std::abs( iLevel ) * piQuantCoeff[uiBlockPos];
883
0
    const TCoeff quantisedMagnitude = TCoeff( ( tmpLevel + iAdd ) >> iQBits );
884
885
0
    if( quantisedMagnitude != 0 )
886
0
    {
887
0
      return true;
888
0
    }
889
0
  } // for n
890
0
  return false;
891
0
}
892
893
} // namespace vvenc
894
895
//! \}
896