1 /* -----------------------------------------------------------------------------
2 The copyright in this software is being made available under the 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 For any license concerning other Intellectual Property rights than the software,
8 especially patent licenses, a separate Agreement needs to be closed.
9 For more information please contact:
10 
11 Fraunhofer Heinrich Hertz Institute
12 Einsteinufer 37
13 10587 Berlin, Germany
14 www.hhi.fraunhofer.de/vvc
15 vvc@hhi.fraunhofer.de
16 
17 Copyright (c) 2018-2021, Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
18 All rights reserved.
19 
20 Redistribution and use in source and binary forms, with or without
21 modification, are permitted provided that the following conditions are met:
22 
23  * Redistributions of source code must retain the above copyright notice,
24    this list of conditions and the following disclaimer.
25  * Redistributions in binary form must reproduce the above copyright notice,
26    this list of conditions and the following disclaimer in the documentation
27    and/or other materials provided with the distribution.
28  * Neither the name of Fraunhofer nor the names of its contributors may
29    be used to endorse or promote products derived from this software without
30    specific prior written permission.
31 
32 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
33 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
34 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
35 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
36 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
37 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
38 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
39 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
40 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
41 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
42 THE POSSIBILITY OF SUCH DAMAGE.
43 
44 
45 ------------------------------------------------------------------------------------------- */
46 
47 /** \file     Quant.cpp
48     \brief    transform and quantization class
49 */
50 
51 #include "Quant.h"
52 
53 #include "UnitTools.h"
54 #include "ContextModelling.h"
55 #include "CodingStructure.h"
56 
57 #include "dtrace_buffer.h"
58 
59 #include <stdlib.h>
60 #include <limits>
61 #include <memory.h>
62 
63 namespace vvdec
64 {
65 
66 // ====================================================================================================================
67 // QpParam constructor
68 // ====================================================================================================================
69 
QpParam(const TransformUnit & tu,const ComponentID & compIDX,const bool allowACTQpoffset)70 QpParam::QpParam( const TransformUnit& tu, const ComponentID& compIDX, const bool allowACTQpoffset )
71 {
72   const ComponentID compID     = MAP_CHROMA( compIDX );
73   const ChannelType chType     = toChannelType( compID );
74   const SPS&        sps        = *tu.cu->sps;
75   const int         qpBdOffset = sps.getQpBDOffset( chType );
76   const bool        useJQP     = isChroma( compID ) && TU::getICTMode( tu, false ) == 2;
77   const ComponentID jCbCr      = useJQP ? JOINT_CbCr : compID;
78 
79   int baseQp;
80   int qpy        = tu.cu->qp;
81   //bool skip      = tu.mtsIdx[compID] == MTS_SKIP;
82 
83   if( isLuma( compID ) )
84   {
85     baseQp = qpy + qpBdOffset;
86   }
87   else
88   {
89     const PPS &pps  = *tu.cu->pps;
90     int
91     chromaQpOffset  = pps.getQpOffset                    ( jCbCr );
92     chromaQpOffset += tu.cu->slice->getSliceChromaQpDelta( jCbCr );
93     chromaQpOffset += pps.getChromaQpOffsetListEntry( tu.cu->chromaQpAdj ).u.offset[int( jCbCr ) - 1];
94 
95     int qpi = Clip3( -qpBdOffset, MAX_QP, qpy );
96     baseQp  = sps.getMappedChromaQpValue( jCbCr, qpi );
97     baseQp  = Clip3( 0, MAX_QP + qpBdOffset, baseQp + chromaQpOffset + qpBdOffset );
98   }
99 
100   if( allowACTQpoffset && tu.cu->colorTransform() )
101   {
102     baseQp += DELTA_QP_ACT[jCbCr];
103     baseQp  = Clip3( 0, MAX_QP + qpBdOffset, baseQp );
104   }
105 
106   // TODO: ensure clip not needed for non-ACT
107 
108   //if( !skip )
109   {
110     Qps [0] = baseQp;
111     pers[0] = baseQp / 6;
112     rems[0] = baseQp - ( pers[0] << 2 ) - ( pers[0] << 1 );
113   }
114   //else
115   {
116     int internalMinusInputBitDepth = sps.getInternalMinusInputBitDepth( chType );
117     int baseQpTS                   = std::max( baseQp, 4 + 6 * internalMinusInputBitDepth );
118     Qps [1] = baseQpTS;
119     pers[1] = baseQpTS / 6;
120     rems[1] = baseQpTS - ( pers[1] << 2 ) - ( pers[1] << 1 );;
121   }
122 }
123 
124 // ====================================================================================================================
125 // Quant class member functions
126 // ====================================================================================================================
127 
DeQuantCore(const int maxX,const int restX,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)128 static void DeQuantCore( const int              maxX,
129                          const int              restX,
130                          const int              maxY,
131                          const int              scale,
132                          const TCoeffSig* const piQCoef,
133                          const size_t           piQCfStride,
134                                TCoeff* const    piCoef,
135                          const int              rightShift,
136                          const int              inputMaximum,
137                          const TCoeff           transformMaximum )
138 {
139   const int    inputMinimum     = -( inputMaximum + 1 );
140   const TCoeff transformMinimum = -( transformMaximum );
141 
142   if (rightShift>0)
143   {
144     const Intermediate_Int iAdd = (Intermediate_Int) 1 << (rightShift - 1);
145 
146 
147     for( int y = 0, n = 0; y <= maxY; y++)
148     {
149       for( int x = 0; x <= maxX; x++, n++ )
150       {
151         const TCoeff level = piQCoef[x + y * piQCfStride];
152 
153         if( level )
154         {
155           const TCoeff           clipQCoef = TCoeff(Clip3<Intermediate_Int>(inputMinimum, inputMaximum, level));
156           Intermediate_Int iCoeffQ   = (Intermediate_Int(clipQCoef) * scale + iAdd) >> rightShift;
157           piCoef[n] = TCoeff(Clip3<Intermediate_Int>(transformMinimum,transformMaximum,iCoeffQ));
158         }
159       }
160       n += restX;
161     }
162   }
163   else  // rightshift <0
164   {
165     int leftShift = -rightShift;
166     for( int y = 0, n = 0; y <= maxY; y++)
167     {
168       for( int x = 0; x <= maxX; x++, n++ )
169       {
170         const TCoeff level = piQCoef[x + y * piQCfStride];
171 
172         if( level )
173         {
174           const TCoeff           clipQCoef = TCoeff(Clip3<Intermediate_Int>(inputMinimum, inputMaximum, level));
175           const Intermediate_Int iCoeffQ   = (Intermediate_Int(clipQCoef) * scale) << leftShift;
176 
177           piCoef[n] = TCoeff(Clip3<Intermediate_Int>(transformMinimum,transformMaximum,iCoeffQ));
178         }
179       }
180       n += restX;
181     }
182 
183   }
184 }
185 
DeQuantPCMCore(const int maxX,const int restX,const int maxY,const int scale,TCoeff * const piQCoef,const size_t piQCfStride,TCoeff * const piCoef,const int rightShift,const int inputMaximum,const TCoeff transformMaximum)186 static void DeQuantPCMCore( const int     maxX,
187                             const int     restX,
188                             const int     maxY,
189                             const int     scale,
190                             TCoeff* const piQCoef,
191                             const size_t  piQCfStride,
192                             TCoeff* const piCoef,
193                             const int     rightShift,
194                             const int     inputMaximum,
195                             const TCoeff  transformMaximum )
196 {
197   const int    inputMinimum     = -( inputMaximum + 1 );
198   const TCoeff transformMinimum = -( transformMaximum );
199 
200   if (rightShift > 0)
201   {
202     const Intermediate_Int iAdd = (Intermediate_Int) 1 << (rightShift - 1);
203     for( int y = 0, n = 0; y <= maxY; y++)
204     {
205       for( int x = 0; x <= maxX; x++, n++ )
206       {
207         const TCoeff level = piQCoef[x + y * piQCfStride];
208         if( level )
209         {
210           const TCoeff           clipQCoef = TCoeff(Clip3<Intermediate_Int>(inputMinimum, inputMaximum, level));
211           const Intermediate_Int iCoeffQ   = (Intermediate_Int(clipQCoef) * scale + iAdd) >> rightShift;
212 
213           piCoef[n] = TCoeff(Clip3<Intermediate_Int>(transformMinimum,transformMaximum,iCoeffQ));
214         }
215       }
216       n += restX;
217     }
218   }
219   else
220   {
221     int leftShift = -rightShift;
222     for( int y = 0, n = 0; y <= maxY; y++)
223     {
224       for( int x = 0; x <= maxX; x++, n++ )
225       {
226         const TCoeff level = piQCoef[x + y * piQCfStride];
227         if( level )
228         {
229           const TCoeff           clipQCoef = TCoeff(Clip3<Intermediate_Int>(inputMinimum, inputMaximum, level));
230           const Intermediate_Int iCoeffQ   = (Intermediate_Int(clipQCoef) * scale) << leftShift;
231 
232           piCoef[n] = TCoeff(Clip3<Intermediate_Int>(transformMinimum,transformMaximum,iCoeffQ));
233         }
234       }
235       n += restX;
236     }
237   }
238 }
239 
Quant()240 Quant::Quant()
241 {
242   xInitScalingList( nullptr );
243   DeQuant= DeQuantCore;
244   DeQuantPCM = DeQuantPCMCore;
245 #if   ENABLE_SIMD_OPT_QUANT && defined( TARGET_SIMD_X86 )
246   initQuantX86();
247 #endif
248 
249 }
250 
~Quant()251 Quant::~Quant()
252 {
253   xDestroyScalingList();
254 }
255 
invResDPCM(const TransformUnit & tu,const ComponentID & compID,CoeffBuf & dstBuf)256 void invResDPCM( const TransformUnit &tu, const ComponentID &compID, CoeffBuf &dstBuf )
257 {
258   const CompArea&    rect   = tu.blocks[compID];
259   const int          wdt    = rect.width;
260   const int          hgt    = rect.height;
261   const CCoeffSigBuf coeffs = tu.cu->cs->getRecoBuf( tu.block( compID ) );
262 
263   const int    maxLog2TrDynamicRange = tu.cu->sps->getMaxLog2TrDynamicRange(toChannelType(compID));
264   const TCoeff inputMinimum          = -(1 << maxLog2TrDynamicRange);
265   const TCoeff inputMaximum          =  (1 << maxLog2TrDynamicRange) - 1;
266 
267   const TCoeffSig* coef = &coeffs.buf[0];
268   TCoeff*          dst  = &dstBuf.buf[0];
269 
270   if( isLuma( compID ) ? tu.cu->bdpcmMode() == 1 : tu.cu->bdpcmModeChroma() == 1 )
271   {
272     for( int y = 0; y < hgt; y++ )
273     {
274       dst[0] = coef[0];
275       for( int x = 1; x < wdt; x++ )
276       {
277         dst[x] = Clip3(inputMinimum, inputMaximum, dst[x - 1] + coef[x]);
278       }
279       coef += coeffs.stride;
280       dst += dstBuf.stride;
281     }
282   }
283   else
284   {
285     for( int x = 0; x < wdt; x++ )
286     {
287       dst[x] = coef[x];
288     }
289     for( int y = 0; y < hgt - 1; y++ )
290     {
291       for( int x = 0; x < wdt; x++ )
292       {
293         dst[dstBuf.stride + x] = Clip3(inputMinimum, inputMaximum, dst[x] + coef[coeffs.stride + x]);
294       }
295       coef += coeffs.stride;
296       dst += dstBuf.stride;
297     }
298   }
299 }
300 
dequant(const TransformUnit & tu,CoeffBuf & dstCoeff,const ComponentID & compID,const QpParam & cQP)301 void Quant::dequant( const TransformUnit& tu, CoeffBuf& dstCoeff, const ComponentID& compID, const QpParam& cQP )
302 {
303   const SPS*             sps                   = tu.cu->sps;
304   const CompArea&        area                  = tu.blocks[compID];
305   const CCoeffSigBuf     coeffBuf              = tu.cu->cs->getRecoBuf( tu.block( compID ) );
306   const TCoeffSig* const piQCoef               = coeffBuf.buf;
307   const size_t           piQCfStride           = coeffBuf.stride;
308         TCoeff* const    piCoef                = dstCoeff.buf;
309   const int              maxLog2TrDynamicRange = sps->getMaxLog2TrDynamicRange( toChannelType( compID ) );
310   const TCoeff           transformMinimum      = -( 1 << maxLog2TrDynamicRange );
311   const TCoeff           transformMaximum      = ( 1 << maxLog2TrDynamicRange ) - 1;
312   const bool             isTransformSkip       = ( tu.mtsIdx( compID ) == MTS_SKIP );
313   setUseScalingList( tu.cu->slice->getExplicitScalingListUsed() );
314   const bool             disableSMForLFNST     = tu.cu->slice->getExplicitScalingListUsed() ? sps->getDisableScalingMatrixForLfnstBlks() : false;
315   const bool             isLfnstApplied        = tu.cu->lfnstIdx() > 0 && ( CU::isSepTree( *tu.cu ) ? true : isLuma( compID ) );
316   const bool             disableSMForACT       = tu.cu->sps->getScalingMatrixForAlternativeColourSpaceDisabledFlag() && tu.cu->sps->getScalingMatrixDesignatedColourSpaceFlag() == tu.cu->colorTransform();
317   const bool             enableScalingLists    = getUseScalingList( isTransformSkip, isLfnstApplied, disableSMForLFNST, disableSMForACT );
318   const int              scalingListType       = getScalingListType( tu.cu->predMode(), compID );
319   const int              channelBitDepth       = sps->getBitDepth( toChannelType( compID ) );
320 
321   int maxX, maxY;
322 
323 
324   if( ( tu.cu->bdpcmMode() && isLuma(compID) ) || ( tu.cu->bdpcmModeChroma() && isChroma(compID) ) )
325   {
326     invResDPCM( tu, compID, dstCoeff );
327     maxX = area.width - 1;
328     maxY = area.height - 1;
329   }
330   else
331   {
332     maxX = tu.maxScanPosX[compID];
333     maxY = tu.maxScanPosY[compID];
334   }
335 
336   CHECK(scalingListType >= SCALING_LIST_NUM, "Invalid scaling list");
337 
338   // Represents scaling through forward transform
339   const bool bClipTransformShiftTo0 = false;// tu.mtsIdx[compID] != 1 && sps->getSpsRangeExtension().getExtendedPrecisionProcessingFlag();
340   const int  originalTransformShift = getTransformShift(channelBitDepth, area.size(), maxLog2TrDynamicRange);
341   const bool needSqrtAdjustment     = TU::needsBlockSizeTrafoScale( tu, compID );
342   const int  iTransformShift        = (bClipTransformShiftTo0 ? std::max<int>(0, originalTransformShift) : originalTransformShift) + (needSqrtAdjustment?-1:0);
343   const bool depQuant = tu.cu->slice->getDepQuantEnabledFlag() && ( tu.mtsIdx( compID ) != MTS_SKIP );
344   const int  QP_per   = depQuant ? ( ( cQP.Qp( isTransformSkip ) + 1 ) / 6 )        : cQP.per( isTransformSkip );
345   const int  QP_rem   = depQuant ? (   cQP.Qp( isTransformSkip ) + 1 - 6 * QP_per ) : cQP.rem( isTransformSkip );
346   const int  rightShift = (IQUANT_SHIFT + ( depQuant ? 1 : 0 ) - ((isTransformSkip ? 0 : iTransformShift) + QP_per)) + (enableScalingLists ? LOG2_SCALING_LIST_NEUTRAL_VALUE : 0);
347 
348   {
349     const uint32_t uiLog2TrWidth  = getLog2(area.width);
350     const uint32_t uiLog2TrHeight = getLog2(area.height);
351 
352     int scale     = g_InvQuantScales[needSqrtAdjustment?1:0][QP_rem];
353 
354     const int scaleBits = ( IQUANT_SHIFT + 1 );
355 
356     //from the dequantisation equation:
357     //iCoeffQ                         = Intermediate_Int((int64_t(clipQCoef) * scale + iAdd) >> rightShift);
358     //(sizeof(Intermediate_Int) * 8)  =                    inputBitDepth   + scaleBits      - rightShift
359     const uint32_t         targetInputBitDepth = std::min<uint32_t>((maxLog2TrDynamicRange + 1), (((sizeof(Intermediate_Int) * 8) + rightShift) - scaleBits));
360     const Intermediate_Int inputMinimum        = -(1 << (targetInputBitDepth - 1));
361     const Intermediate_Int inputMaximum        =  (1 << (targetInputBitDepth - 1)) - 1;
362 
363     const int restX = area.width - maxX - 1;
364 
365     if (!enableScalingLists)
366     {
367       if( ( tu.cu->bdpcmMode() && isLuma( compID ) ) || ( tu.cu->bdpcmModeChroma() && isChroma( compID ) ) )
368       {
369         TCoeff* dst = &dstCoeff.buf[0];
370         DeQuantPCM(maxX,restX,maxY,scale,dst,dstCoeff.stride,piCoef,rightShift,inputMaximum,transformMaximum);
371 
372       }
373       else
374       {
375         DeQuant(maxX,restX,maxY,scale,piQCoef,piQCfStride,piCoef,rightShift,inputMaximum,transformMaximum);
376       }
377     }
378     else
379     {
380       int* piDequantCoef = getDequantCoeff( scalingListType, QP_rem, uiLog2TrWidth, uiLog2TrHeight );
381 
382       if( ( tu.cu->bdpcmMode() && isLuma(compID) ) || ( tu.cu->bdpcmModeChroma() && isChroma(compID) ) )
383       {
384         TCoeff* dst = &dstCoeff.buf[0];
385 
386         if (rightShift > 0)
387         {
388           const Intermediate_Int iAdd = (Intermediate_Int) 1 << (rightShift - 1);
389           for( int y = 0, n = 0; y <= maxY; y++)
390           {
391             for( int x = 0; x <= maxX; x++, n++ )
392             {
393               const TCoeff level = dst[x + y * dstCoeff.stride];
394 
395               if( level )
396               {
397                 scale = piDequantCoef[n];
398 
399                 const TCoeff           clipQCoef = TCoeff(Clip3<Intermediate_Int>(inputMinimum, inputMaximum, level));
400                 const Intermediate_Int iCoeffQ   = (Intermediate_Int(clipQCoef) * scale + iAdd) >> rightShift;
401 
402                 piCoef[n] = TCoeff(Clip3<Intermediate_Int>(transformMinimum,transformMaximum,iCoeffQ));
403               }
404             }
405             n += restX;
406           }
407         }
408         else
409         {
410           int leftShift = -rightShift;
411           for( int y = 0, n = 0; y <= maxY; y++)
412           {
413             for( int x = 0; x <= maxX; x++, n++ )
414             {
415               const TCoeff level = dst[x + y * dstCoeff.stride];
416 
417               if( level )
418               {
419                 scale = piDequantCoef[n];
420 
421                 const TCoeff           clipQCoef = TCoeff(Clip3<Intermediate_Int>(inputMinimum, inputMaximum, level));
422                 const Intermediate_Int iCoeffQ   = (Intermediate_Int(clipQCoef) * scale) << leftShift;
423 
424                 piCoef[n] = TCoeff(Clip3<Intermediate_Int>(transformMinimum,transformMaximum,iCoeffQ));
425               }
426             }
427             n += restX;
428           }
429         }
430       }
431       else
432       {
433         if (rightShift > 0)
434         {
435           const Intermediate_Int iAdd = (Intermediate_Int) 1 << (rightShift - 1);
436 
437           for( int y = 0, n = 0; y <= maxY; y++)
438           {
439             for( int x = 0; x <= maxX; x++, n++ )
440             {
441               const TCoeff level = piQCoef[x + y * piQCfStride];
442 
443               if( level )
444               {
445                 scale = piDequantCoef[n];
446 
447                 const TCoeff           clipQCoef = TCoeff(Clip3<Intermediate_Int>(inputMinimum, inputMaximum, level));
448                 Intermediate_Int iCoeffQ   = (Intermediate_Int(clipQCoef) * scale + iAdd) >> rightShift;
449 
450                 piCoef[n] = TCoeff(Clip3<Intermediate_Int>(transformMinimum,transformMaximum,iCoeffQ));
451               }
452             }
453             n += restX;
454           }
455         }
456         else
457         {
458           int leftShift = -rightShift;
459           for( int y = 0, n = 0; y <= maxY; y++)
460           {
461             for( int x = 0; x <= maxX; x++, n++ )
462             {
463               const TCoeff level = piQCoef[x + y * piQCfStride];
464 
465               if( level )
466               {
467                 scale = piDequantCoef[n];
468 
469                 const TCoeff           clipQCoef = TCoeff(Clip3<Intermediate_Int>(inputMinimum, inputMaximum, level));
470                 const Intermediate_Int iCoeffQ   = (Intermediate_Int(clipQCoef) * scale) << leftShift;
471 
472                 piCoef[n] = TCoeff(Clip3<Intermediate_Int>(transformMinimum,transformMaximum,iCoeffQ));
473               }
474             }
475             n += restX;
476           }
477         }
478       }
479     }
480   }
481 }
482 
483 /** set quantized matrix coefficient for decode
484  * \param scalingList quantized matrix address
485  * \param format      chroma format
486  */
setScalingListDec(ScalingList & scalingList)487 void Quant::setScalingListDec( ScalingList& scalingList )
488 {
489   const int minimumQp = 0;
490   const int maximumQp = SCALING_LIST_REM_NUM;
491 
492   int scalingListId    = 0;
493   int recScalingListId = 0;
494   for( uint32_t size = SCALING_LIST_FIRST_CODED; size <= SCALING_LIST_LAST_CODED; size++ )
495   {
496     for( uint32_t list = 0; list < SCALING_LIST_NUM; list++ )
497     {
498       if( size == SCALING_LIST_2x2 && list < 4 )   // skip 2x2 luma
499       {
500         continue;
501       }
502       scalingListId = g_scalingListId[size][list];
503       for( int qp = minimumQp; qp < maximumQp; qp++ )
504       {
505         xSetScalingListDec( scalingList, list, size, qp, scalingListId );
506       }
507     }
508   }
509   // based on square result and apply downsample technology
510   for( uint32_t sizew = 0; sizew <= SCALING_LIST_LAST_CODED; sizew++ )   // 7
511   {
512     for( uint32_t sizeh = 0; sizeh <= SCALING_LIST_LAST_CODED; sizeh++ )   // 7
513     {
514       if( sizew == sizeh || ( sizew == SCALING_LIST_1x1 && sizeh < SCALING_LIST_4x4 ) || ( sizeh == SCALING_LIST_1x1 && sizew < SCALING_LIST_4x4 ) )
515       {
516         continue;
517       }
518       for( uint32_t list = 0; list < SCALING_LIST_NUM; list++ )   // 9
519       {
520         int largerSide = ( sizew > sizeh ) ? sizew : sizeh;
521         CHECK( largerSide < SCALING_LIST_4x4, "Rectangle Error!" );
522         recScalingListId = g_scalingListId[largerSide][list];
523         for( int qp = minimumQp; qp < maximumQp; qp++ )
524         {
525           xSetRecScalingListDec( scalingList, list, sizew, sizeh, qp, recScalingListId );
526         }
527       }
528     }
529   }
530 }
531 
532 /** set quantized matrix coefficient for decode
533  * \param scalingList quantaized matrix address
534  * \param listId List index
535  * \param sizeId size index
536  * \param qp Quantization parameter
537  * \param format chroma format
538  */
xSetScalingListDec(const ScalingList & scalingList,uint32_t listId,uint32_t sizeId,int qp,uint32_t scalingListId)539 void Quant::xSetScalingListDec(const ScalingList &scalingList, uint32_t listId, uint32_t sizeId, int qp, uint32_t scalingListId)
540 {
541   uint32_t width  = g_vvcScalingListSizeX[sizeId];
542   uint32_t height = g_vvcScalingListSizeX[sizeId];
543   uint32_t ratio  = g_vvcScalingListSizeX[sizeId]/std::min(MAX_MATRIX_SIZE_NUM,(int)g_vvcScalingListSizeX[sizeId]);
544   int *dequantcoeff;
545   const int *coeff = scalingList.getScalingListAddress(scalingListId);
546 
547   dequantcoeff = getDequantCoeff(listId, qp, sizeId, sizeId);
548 
549   const int blockIsNotPowerOf4 = ( getLog2( width ) + getLog2( height ) ) & 1;
550   int invQuantScale = g_InvQuantScales[blockIsNotPowerOf4][qp];
551 
552   processScalingListDec(coeff,
553                         dequantcoeff,
554                         invQuantScale,
555                         height, width, ratio,
556                         std::min(MAX_MATRIX_SIZE_NUM, (int)g_vvcScalingListSizeX[sizeId]),
557                         scalingList.getScalingListDC(scalingListId));
558 }
559 
560 /** set quantized matrix coefficient for decode
561 * \param scalingList quantaized matrix address
562 * \param listId List index
563 * \param sizeId size index
564 * \param qp Quantization parameter
565 * \param format chroma format
566 */
xSetRecScalingListDec(const ScalingList & scalingList,uint32_t listId,uint32_t sizeIdw,uint32_t sizeIdh,int qp,uint32_t scalingListId)567 void Quant::xSetRecScalingListDec(const ScalingList &scalingList, uint32_t listId, uint32_t sizeIdw, uint32_t sizeIdh, int qp, uint32_t scalingListId)
568 {
569   if (sizeIdw == sizeIdh) return;
570   uint32_t width = g_vvcScalingListSizeX[sizeIdw];
571   uint32_t height = g_vvcScalingListSizeX[sizeIdh];
572   uint32_t largeSideId = (sizeIdw > sizeIdh) ? sizeIdw : sizeIdh;  //16
573 
574   const int *coeff = scalingList.getScalingListAddress(scalingListId);
575   int *dequantcoeff;
576   dequantcoeff = getDequantCoeff(listId, qp, sizeIdw, sizeIdh);
577   const int blockIsNotPowerOf4 = ( getLog2( width ) + getLog2( height ) ) & 1;
578   int invQuantScale = g_InvQuantScales[blockIsNotPowerOf4][qp];
579   processScalingListDec(coeff,
580                         dequantcoeff,
581                         invQuantScale,
582                         height, width, (largeSideId>3) ? 2 : 1,
583                         (largeSideId >= 3 ? 8 : 4),
584                         scalingList.getScalingListDC(scalingListId));
585 }
586 
587 /** set quantized matrix coefficient for decode
588  * \param coeff quantaized matrix address
589  * \param dequantcoeff quantaized matrix address
590  * \param invQuantScales IQ(QP%6))
591  * \param height height
592  * \param width width
593  * \param ratio ratio for upscale
594  * \param sizuNum matrix size
595  * \param dc dc parameter
596  */
processScalingListDec(const int * coeff,int * dequantcoeff,int invQuantScales,uint32_t height,uint32_t width,uint32_t ratio,int sizuNum,uint32_t dc)597 void Quant::processScalingListDec( const int *coeff, int *dequantcoeff, int invQuantScales, uint32_t height, uint32_t width, uint32_t ratio, int sizuNum, uint32_t dc)
598 {
599   if (height != width)
600   {
601     for (uint32_t j = 0; j<height; j++)
602     {
603       for (uint32_t i = 0; i<width; i++)
604       {
605         if (i >= JVET_C0024_ZERO_OUT_TH || j >= JVET_C0024_ZERO_OUT_TH)
606         {
607           dequantcoeff[j*width + i] = 0;
608           continue;
609         }
610         int ratioWH = height > width   ? height / width   : width   / height;
611         int ratioH  = height / sizuNum ? height / sizuNum : sizuNum / height;
612         int ratioW  = width / sizuNum  ? width  / sizuNum : sizuNum / width;
613         //sizeNum = 8/4
614         if (height > width)
615         {
616           dequantcoeff[j*width + i] = invQuantScales * coeff[sizuNum * (j / ratioH) + ((i * ratioWH) / ratioH)];
617         }
618         else //ratioH < ratioW
619         {
620           dequantcoeff[j*width + i] = invQuantScales * coeff[sizuNum * ((j * ratioWH) / ratioW) + (i / ratioW)];
621         }
622         int largeOne = std::max( width, height );
623         if( largeOne > 8 )
624         {
625           dequantcoeff[0] = invQuantScales * dc;
626         }
627       }
628     }
629     return;
630   }
631   for(uint32_t j=0;j<height;j++)
632   {
633     for(uint32_t i=0;i<width;i++)
634     {
635       dequantcoeff[j*width + i] = invQuantScales * coeff[sizuNum * (j / ratio) + i / ratio];
636     }
637   }
638 
639   if(ratio > 1)
640   {
641     dequantcoeff[0] = invQuantScales * dc;
642   }
643 }
644 
645 /** initialization process of scaling list array
646  */
xInitScalingList(const Quant * other)647 void Quant::xInitScalingList( const Quant* other )
648 {
649   size_t numQuants = 0;
650 
651   for(uint32_t sizeIdX = 0; sizeIdX < SCALING_LIST_SIZE_NUM; sizeIdX++)
652   {
653     for(uint32_t sizeIdY = 0; sizeIdY < SCALING_LIST_SIZE_NUM; sizeIdY++)
654     {
655       for(uint32_t qp = 0; qp < SCALING_LIST_REM_NUM; qp++)
656       {
657         for(uint32_t listId = 0; listId < SCALING_LIST_NUM; listId++)
658         {
659           m_dequantCoef [sizeIdX][sizeIdY][listId][qp] = &m_dequantCoefBuf[numQuants];
660           numQuants += g_vvcScalingListSizeX[sizeIdX] * g_vvcScalingListSizeX[sizeIdY];
661         } // listID loop
662       }
663     }
664   }
665 }
666 
667 /** destroy quantization matrix array
668  */
xDestroyScalingList()669 void Quant::xDestroyScalingList()
670 {
671 }
672 
init(const Picture * pic)673 void Quant::init( const Picture *pic )
674 {
675   const Slice* scalingListSlice = nullptr;
676 
677   for( const Slice* slice : pic->slices )
678   {
679     if( slice->getExplicitScalingListUsed() )
680     {
681       scalingListSlice = slice;
682       break;
683     }
684   }
685 
686   const Slice* slice = scalingListSlice;
687 
688   if( slice && slice->getExplicitScalingListUsed() )
689   {
690     std::shared_ptr<APS> scalingListAPS = slice->getPicHeader()->getScalingListAPS();
691     if( slice->getNalUnitLayerId() != scalingListAPS->getLayerId() )
692     {
693       CHECK( scalingListAPS->getLayerId() > slice->getNalUnitLayerId(), "Layer Id of APS cannot be greater than layer Id of VCL NAL unit the refer to it" );
694       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" );
695       for( int i = 0; i < slice->getVPS()->getNumOutputLayerSets(); i++ )
696       {
697         bool isCurrLayerInOls = false;
698         bool isRefLayerInOls = false;
699         for( int j = slice->getVPS()->getNumLayersInOls(i) - 1; j >= 0; j-- )
700         {
701           if( slice->getVPS()->getLayerIdInOls(i, j) == slice->getNalUnitLayerId() )
702           {
703             isCurrLayerInOls = true;
704           }
705           if( slice->getVPS()->getLayerIdInOls(i, j) == scalingListAPS->getLayerId() )
706           {
707             isRefLayerInOls = true;
708           }
709         }
710         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" );
711       }
712     }
713     ScalingList scalingList = scalingListAPS->getScalingList();
714     setScalingListDec(scalingList);
715     setUseScalingList(true);
716   }
717   else
718   {
719     setUseScalingList( false );
720   }
721 }
722 
723 }
724