Coverage Report

Created: 2026-04-01 07:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/vvenc/source/Lib/CommonLib/DepQuant.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
#include "DepQuant.h"
44
#include "TrQuant.h"
45
#include "CodingStructure.h"
46
#include "UnitTools.h"
47
48
#include <bitset>
49
50
//! \ingroup CommonLib
51
//! \{
52
53
namespace vvenc {
54
55
56
namespace DQIntern
57
{
58
  void Rom::xInitScanArrays()
59
0
  {
60
0
    if( m_scansInitialized )
61
0
    {
62
0
      return;
63
0
    }
64
0
    ::memset( m_scanId2NbInfoSbbArray, 0, sizeof(m_scanId2NbInfoSbbArray) );
65
0
    ::memset( m_scanId2NbInfoOutArray, 0, sizeof(m_scanId2NbInfoOutArray) );
66
0
    ::memset( m_tuParameters,          0, sizeof(m_tuParameters) );
67
68
0
    uint32_t raster2id[ MAX_CU_SIZE * MAX_CU_SIZE ];
69
0
    ::memset(raster2id, 0, sizeof(raster2id));
70
71
0
    for( int hd = 0; hd < MAX_TU_SIZE_IDX; hd++ )
72
0
    {
73
0
      for( int vd = 0; vd < MAX_TU_SIZE_IDX; vd++ )
74
0
      {
75
0
        if( (hd == 0 && vd <= 1) || (hd <= 1 && vd == 0) )
76
0
        {
77
0
          continue;
78
0
        }
79
0
        const uint32_t      blockWidth    = (1 << hd);
80
0
        const uint32_t      blockHeight   = (1 << vd);
81
0
        const uint32_t      log2CGWidth   = g_log2SbbSize[hd][vd][0];
82
0
        const uint32_t      log2CGHeight  = g_log2SbbSize[hd][vd][1];
83
0
        const uint32_t      groupWidth    = 1 << log2CGWidth;
84
0
        const uint32_t      groupHeight   = 1 << log2CGHeight;
85
0
        const uint32_t      groupSize     = groupWidth * groupHeight;
86
0
        const SizeType      blkWidthIdx   = Log2( blockWidth );
87
0
        const SizeType      blkHeightIdx  = Log2( blockHeight );
88
0
        const ScanElement * scanId2RP     = getScanOrder( SCAN_GROUPED_4x4, blkWidthIdx, blkHeightIdx );
89
0
        NbInfoSbb*&         sId2NbSbb     = m_scanId2NbInfoSbbArray[hd][vd];
90
0
        NbInfoOut*&         sId2NbOut     = m_scanId2NbInfoOutArray[hd][vd];
91
        // consider only non-zero-out region
92
0
        const uint32_t      blkWidthNZOut = std::min<unsigned>( JVET_C0024_ZERO_OUT_TH, blockWidth  );
93
0
        const uint32_t      blkHeightNZOut= std::min<unsigned>( JVET_C0024_ZERO_OUT_TH, blockHeight );
94
0
        const uint32_t      totalValues   = blkWidthNZOut * blkHeightNZOut;
95
96
0
        sId2NbSbb = new NbInfoSbb[ totalValues ];
97
0
        sId2NbOut = new NbInfoOut[ totalValues ];
98
99
0
        for( uint32_t scanId = 0; scanId < totalValues; scanId++ )
100
0
        {
101
0
          raster2id[scanId2RP[scanId].idx] = scanId;
102
0
          sId2NbSbb[scanId].numInv = 0;
103
0
        }
104
105
0
        for( unsigned scanId = 0; scanId < totalValues; scanId++ )
106
0
        {
107
0
          const int posX = scanId2RP[scanId].x;
108
0
          const int posY = scanId2RP[scanId].y;
109
0
          const int rpos = scanId2RP[scanId].idx;
110
0
          {
111
            //===== inside subband neighbours =====
112
0
            const int      begSbb = scanId - ( scanId & (groupSize-1) ); // first pos in current subblock
113
0
            int            cpos[5];
114
115
0
            cpos[0] = ( posX + 1 < blkWidthNZOut                              ? ( raster2id[rpos+1           ] < groupSize + begSbb ? raster2id[rpos+1           ] - begSbb : 0 ) : 0 );
116
0
            cpos[1] = ( posX + 2 < blkWidthNZOut                              ? ( raster2id[rpos+2           ] < groupSize + begSbb ? raster2id[rpos+2           ] - begSbb : 0 ) : 0 );
117
0
            cpos[2] = ( posX + 1 < blkWidthNZOut && posY + 1 < blkHeightNZOut ? ( raster2id[rpos+1+blockWidth] < groupSize + begSbb ? raster2id[rpos+1+blockWidth] - begSbb : 0 ) : 0 );
118
0
            cpos[3] = ( posY + 1 < blkHeightNZOut                             ? ( raster2id[rpos+  blockWidth] < groupSize + begSbb ? raster2id[rpos+  blockWidth] - begSbb : 0 ) : 0 );
119
0
            cpos[4] = ( posY + 2 < blkHeightNZOut                             ? ( raster2id[rpos+2*blockWidth] < groupSize + begSbb ? raster2id[rpos+2*blockWidth] - begSbb : 0 ) : 0 );
120
121
0
            int num = 0;
122
0
            int inPos[5] = { 0, };
123
124
0
            while( true )
125
0
            {
126
0
              int nk = -1;
127
0
              for( int k = 0; k < 5; k++ )
128
0
              {
129
0
                if( cpos[k] != 0 && ( nk < 0 || cpos[k] < cpos[nk] ) )
130
0
                {
131
0
                  nk = k;
132
0
                }
133
0
              }
134
0
              if( nk < 0 )
135
0
              {
136
0
                break;
137
0
              }
138
0
              inPos[ num++ ] = uint8_t( cpos[nk] );
139
0
              cpos[nk] = 0;
140
0
            }
141
0
            for( int k = num; k < 5; k++ )
142
0
            {
143
0
              inPos[k] = 0;
144
0
            }
145
0
            for( int k = 0; k < num; k++ )
146
0
            {
147
0
              CHECK( sId2NbSbb[begSbb + inPos[k]].numInv >= 5, "" );
148
0
              sId2NbSbb[begSbb + inPos[k]].invInPos[sId2NbSbb[begSbb + inPos[k]].numInv++] = scanId & ( groupSize - 1 );
149
0
            }
150
0
          }
151
0
          {
152
            //===== outside subband neighbours =====
153
0
            NbInfoOut&     nbOut  = sId2NbOut[ scanId ];
154
0
            const int      begSbb = scanId - ( scanId & (groupSize-1) ); // first pos in current subblock
155
0
            int            cpos[5];
156
157
0
            cpos[0] = ( posX + 1 < blkWidthNZOut                              ? ( raster2id[rpos+1           ] >= groupSize + begSbb ? raster2id[rpos+1           ] : 0 ) : 0 );
158
0
            cpos[1] = ( posX + 2 < blkWidthNZOut                              ? ( raster2id[rpos+2           ] >= groupSize + begSbb ? raster2id[rpos+2           ] : 0 ) : 0 );
159
0
            cpos[2] = ( posX + 1 < blkWidthNZOut && posY + 1 < blkHeightNZOut ? ( raster2id[rpos+1+blockWidth] >= groupSize + begSbb ? raster2id[rpos+1+blockWidth] : 0 ) : 0 );
160
0
            cpos[3] = ( posY + 1 < blkHeightNZOut                             ? ( raster2id[rpos+  blockWidth] >= groupSize + begSbb ? raster2id[rpos+  blockWidth] : 0 ) : 0 );
161
0
            cpos[4] = ( posY + 2 < blkHeightNZOut                             ? ( raster2id[rpos+2*blockWidth] >= groupSize + begSbb ? raster2id[rpos+2*blockWidth] : 0 ) : 0 );
162
163
0
            for( nbOut.num = 0; true; )
164
0
            {
165
0
              int nk = -1;
166
0
              for( int k = 0; k < 5; k++ )
167
0
              {
168
0
                if( cpos[k] != 0 && ( nk < 0 || cpos[k] < cpos[nk] ) )
169
0
                {
170
0
                  nk = k;
171
0
                }
172
0
              }
173
0
              if( nk < 0 )
174
0
              {
175
0
                break;
176
0
              }
177
0
              nbOut.outPos[ nbOut.num++ ] = uint16_t( cpos[nk] );
178
0
              cpos[nk] = 0;
179
0
            }
180
0
            for( int k = nbOut.num; k < 5; k++ )
181
0
            {
182
0
              nbOut.outPos[k] = 0;
183
0
            }
184
0
            nbOut.maxDist = ( scanId == 0 ? 0 : sId2NbOut[scanId-1].maxDist );
185
0
            for( int k = 0; k < nbOut.num; k++ )
186
0
            {
187
0
              if( nbOut.outPos[k] > nbOut.maxDist )
188
0
              {
189
0
                nbOut.maxDist = nbOut.outPos[k];
190
0
              }
191
0
            }
192
0
          }
193
0
        }
194
195
        // make it relative
196
0
        for( unsigned scanId = 0; scanId < totalValues; scanId++ )
197
0
        {
198
0
          NbInfoOut& nbOut  = sId2NbOut[scanId];
199
0
          const int  begSbb = scanId - ( scanId & (groupSize-1) ); // first pos in current subblock
200
0
          for( int k = 0; k < nbOut.num; k++ )
201
0
          {
202
0
            CHECK(begSbb > nbOut.outPos[k], "Position must be past sub block begin");
203
0
            nbOut.outPos[k] -= begSbb;
204
0
          }
205
0
          nbOut.maxDist -= scanId;
206
0
        }
207
208
0
        for( int chId = 0; chId < MAX_NUM_CH; chId++ )
209
0
        {
210
0
          m_tuParameters[hd][vd][chId] = new TUParameters( *this, blockWidth, blockHeight, ChannelType(chId) );
211
0
        }
212
0
      }
213
0
    }
214
0
    m_scansInitialized = true;
215
0
  }
216
217
  void Rom::xUninitScanArrays()
218
0
  {
219
0
    if( !m_scansInitialized )
220
0
    {
221
0
      return;
222
0
    }
223
0
    for( int hd = 0; hd < MAX_TU_SIZE_IDX; hd++ )
224
0
    {
225
0
      for( int vd = 0; vd < MAX_TU_SIZE_IDX; vd++ )
226
0
      {
227
0
        NbInfoSbb*& sId2NbSbb = m_scanId2NbInfoSbbArray[hd][vd];
228
0
        NbInfoOut*& sId2NbOut = m_scanId2NbInfoOutArray[hd][vd];
229
0
        if( sId2NbSbb )
230
0
        {
231
0
          delete [] sId2NbSbb;
232
0
        }
233
0
        if( sId2NbOut )
234
0
        {
235
0
          delete [] sId2NbOut;
236
0
        }
237
0
        for( int chId = 0; chId < MAX_NUM_CH; chId++ )
238
0
        {
239
0
          TUParameters*& tuPars = m_tuParameters[hd][vd][chId];
240
0
          if( tuPars )
241
0
          {
242
0
            delete tuPars;
243
0
          }
244
0
        }
245
0
      }
246
0
    }
247
0
    m_scansInitialized = false;
248
0
  }
249
250
251
  TUParameters::TUParameters( const Rom& rom, const unsigned width, const unsigned height, const ChannelType chType )
252
0
  {
253
0
    m_chType              = chType;
254
0
    m_width               = width;
255
0
    m_height              = height;
256
0
    const uint32_t nonzeroWidth  = std::min<uint32_t>(JVET_C0024_ZERO_OUT_TH, m_width);
257
0
    const uint32_t nonzeroHeight = std::min<uint32_t>(JVET_C0024_ZERO_OUT_TH, m_height);
258
0
    m_numCoeff                   = nonzeroWidth * nonzeroHeight;
259
0
    m_log2SbbWidth        = g_log2SbbSize[ Log2(m_width) ][ Log2(m_height) ][0];
260
0
    m_log2SbbHeight       = g_log2SbbSize[ Log2(m_width) ][ Log2(m_height) ][1];
261
0
    m_log2SbbSize         = m_log2SbbWidth + m_log2SbbHeight;
262
0
    m_sbbSize             = ( 1 << m_log2SbbSize );
263
0
    m_sbbMask             = m_sbbSize - 1;
264
0
    m_widthInSbb  = nonzeroWidth >> m_log2SbbWidth;
265
0
    m_heightInSbb = nonzeroHeight >> m_log2SbbHeight;
266
0
    m_numSbb              = m_widthInSbb * m_heightInSbb;
267
0
    SizeType        hsbb  = Log2( m_widthInSbb  );
268
0
    SizeType        vsbb  = Log2( m_heightInSbb );
269
0
    SizeType        hsId  = Log2( m_width  );
270
0
    SizeType        vsId  = Log2( m_height );
271
0
    m_scanSbbId2SbbPos    = getScanOrder( SCAN_UNGROUPED   , hsbb , vsbb );
272
0
    m_scanId2BlkPos       = getScanOrder( SCAN_GROUPED_4x4 , hsId , vsId );
273
0
    int log2W             = Log2( m_width  );
274
0
    int log2H             = Log2( m_height );
275
0
    m_scanId2NbInfoSbb    = rom.getNbInfoSbb( log2W, log2H );
276
0
    m_scanId2NbInfoOut    = rom.getNbInfoOut( log2W, log2H );
277
0
    m_scanInfo            = new ScanInfo[ m_numCoeff ];
278
0
    for( int scanIdx = 0; scanIdx < m_numCoeff; scanIdx++ )
279
0
    {
280
0
      xSetScanInfo( m_scanInfo[scanIdx], scanIdx );
281
0
    }
282
0
  }
283
284
285
  void TUParameters::xSetScanInfo( ScanInfo& scanInfo, int scanIdx )
286
0
  {
287
0
    scanInfo.sbbSize    = m_sbbSize;
288
0
    scanInfo.numSbb     = m_numSbb;
289
0
    scanInfo.scanIdx    = scanIdx;
290
0
    scanInfo.rasterPos  = m_scanId2BlkPos[scanIdx].idx;
291
0
    scanInfo.sbbPos     = m_scanSbbId2SbbPos[scanIdx >> m_log2SbbSize].idx;
292
0
    scanInfo.insidePos  = scanIdx & m_sbbMask;
293
0
    scanInfo.spt        = SCAN_ISCSBB;
294
0
    if(  scanInfo.insidePos == m_sbbMask && scanIdx > scanInfo.sbbSize && scanIdx < m_numCoeff - 1 )
295
0
      scanInfo.spt      = SCAN_SOCSBB;
296
0
    else if( scanInfo.insidePos == 0 && scanIdx > 0 && scanIdx < m_numCoeff - m_sbbSize )
297
0
      scanInfo.spt      = SCAN_EOCSBB;
298
0
    scanInfo.posX = m_scanId2BlkPos[scanIdx].x;
299
0
    scanInfo.posY = m_scanId2BlkPos[scanIdx].y;
300
0
    if( scanIdx )
301
0
    {
302
0
      const int nextScanIdx = scanIdx - 1;
303
0
      const int diag        = m_scanId2BlkPos[nextScanIdx].x + m_scanId2BlkPos[nextScanIdx].y;
304
0
      if( m_chType == CH_L )
305
0
      {
306
0
        scanInfo.sigCtxOffsetNext = ( diag < 2 ? 8 : diag < 5 ?  4 : 0 );
307
0
        scanInfo.gtxCtxOffsetNext = ( diag < 1 ? 16 : diag < 3 ? 11 : diag < 10 ? 6 : 1 );
308
0
      }
309
0
      else
310
0
      {
311
0
        scanInfo.sigCtxOffsetNext = ( diag < 2 ? 4 : 0 );
312
0
        scanInfo.gtxCtxOffsetNext = ( diag < 1 ? 6 : 1 );
313
0
      }
314
0
      scanInfo.nextInsidePos      = nextScanIdx & m_sbbMask;
315
0
      scanInfo.currNbInfoSbb      = m_scanId2NbInfoSbb[ scanIdx ];
316
0
      if( scanInfo.insidePos == 0 )
317
0
      {
318
0
        const int nextSbbPos  = m_scanSbbId2SbbPos[nextScanIdx >> m_log2SbbSize].idx;
319
0
        const int nextSbbPosY = nextSbbPos               / m_widthInSbb;
320
0
        const int nextSbbPosX = nextSbbPos - nextSbbPosY * m_widthInSbb;
321
0
        scanInfo.nextSbbRight = ( nextSbbPosX < m_widthInSbb  - 1 ? nextSbbPos + 1            : 0 );
322
0
        scanInfo.nextSbbBelow = ( nextSbbPosY < m_heightInSbb - 1 ? nextSbbPos + m_widthInSbb : 0 );
323
0
      }
324
0
    }
325
0
  }
326
327
  void RateEstimator::initCtx( const TUParameters& tuPars, const TransformUnit& tu, const ComponentID compID, const FracBitsAccess& fracBitsAccess )
328
0
  {
329
0
    m_scanId2Pos = tuPars.m_scanId2BlkPos;
330
0
    xSetSigSbbFracBits  ( fracBitsAccess, tuPars.m_chType );
331
0
    xSetSigFlagBits     ( fracBitsAccess, tuPars.m_chType );
332
0
    xSetGtxFlagBits     ( fracBitsAccess, tuPars.m_chType );
333
0
    xSetLastCoeffOffset ( fracBitsAccess, tuPars, tu, compID );
334
0
  }
335
336
  void RateEstimator::xSetLastCoeffOffset( const FracBitsAccess& fracBitsAccess, const TUParameters& tuPars, const TransformUnit& tu, const ComponentID compID )
337
0
  {
338
0
    const ChannelType chType = ( compID == COMP_Y ? CH_L : CH_C );
339
0
    int32_t cbfDeltaBits = 0;
340
0
    if( compID == COMP_Y && !CU::isIntra(*tu.cu) && !tu.depth )
341
0
    {
342
0
      const BinFracBits bits  = fracBitsAccess.getFracBitsArray( Ctx::QtRootCbf() );
343
0
      cbfDeltaBits            = int32_t( bits.intBits[1] ) - int32_t( bits.intBits[0] );
344
0
    }
345
0
    else
346
0
    {
347
0
      BinFracBits bits;
348
0
      bool prevLumaCbf           = false;
349
0
      bool lastCbfIsInferred     = false;
350
0
      bool useIntraSubPartitions = tu.cu->ispMode && isLuma(chType);
351
0
      if( useIntraSubPartitions )
352
0
      {
353
0
        bool rootCbfSoFar = false;
354
0
        bool isLastSubPartition = CU::isISPLast(*tu.cu, tu.Y(), compID);
355
0
        uint32_t nTus = tu.cu->ispMode == HOR_INTRA_SUBPARTITIONS ? tu.cu->lheight() >> Log2(tu.lheight()) : tu.cu->lwidth() >> Log2(tu.lwidth());
356
0
        if( isLastSubPartition )
357
0
        {
358
0
          TransformUnit* tuPointer = tu.cu->firstTU;
359
0
          for( int tuIdx = 0; tuIdx < nTus - 1; tuIdx++ )
360
0
          {
361
0
            rootCbfSoFar |= TU::getCbfAtDepth(*tuPointer, COMP_Y, tu.depth);
362
0
            tuPointer     = tuPointer->next;
363
0
          }
364
0
          if( !rootCbfSoFar )
365
0
          {
366
0
            lastCbfIsInferred = true;
367
0
          }
368
0
        }
369
0
        if( !lastCbfIsInferred )
370
0
        {
371
0
          prevLumaCbf = TU::getPrevTuCbfAtDepth(tu, compID, tu.depth);
372
0
        }
373
0
        bits = fracBitsAccess.getFracBitsArray(Ctx::QtCbf[compID](DeriveCtx::CtxQtCbf(compID, prevLumaCbf, true)));
374
0
      }
375
0
      else
376
0
      {
377
0
        bits = fracBitsAccess.getFracBitsArray(Ctx::QtCbf[compID](DeriveCtx::CtxQtCbf(compID, tu.cbf[COMP_Cb])));
378
0
      }
379
0
      cbfDeltaBits = lastCbfIsInferred ? 0 : int32_t(bits.intBits[1]) - int32_t(bits.intBits[0]);
380
0
    }
381
382
0
    static const unsigned prefixCtx[] = { 0, 0, 0, 3, 6, 10, 15, 21 };
383
0
    uint32_t              ctxBits  [ LAST_SIGNIFICANT_GROUPS ];
384
0
    for( unsigned xy = 0; xy < 2; xy++ )
385
0
    {
386
0
      int32_t             bitOffset   = ( xy ? cbfDeltaBits : 0 );
387
0
      int32_t*            lastBits    = ( xy ? m_lastBitsY : m_lastBitsX );
388
0
      const unsigned      size        = ( xy ? tuPars.m_height : tuPars.m_width );
389
0
      const unsigned      log2Size    = Log2( size );
390
0
      const bool          useYCtx     = ( xy != 0 );
391
0
      const CtxSet&       ctxSetLast  = ( useYCtx ? Ctx::LastY : Ctx::LastX )[ chType ];
392
0
      const unsigned      lastShift   = ( compID == COMP_Y ? (log2Size+1)>>2 : Clip3<unsigned>(0,2,size>>3) );
393
0
      const unsigned      lastOffset  = ( compID == COMP_Y ? ( prefixCtx[log2Size] ) : 0 );
394
0
      uint32_t            sumFBits    = 0;
395
0
      unsigned            maxCtxId    = g_uiGroupIdx[std::min<unsigned>(JVET_C0024_ZERO_OUT_TH, size) - 1];
396
0
      for( unsigned ctxId = 0; ctxId < maxCtxId; ctxId++ )
397
0
      {
398
0
        const BinFracBits bits  = fracBitsAccess.getFracBitsArray( ctxSetLast( lastOffset + ( ctxId >> lastShift ) ) );
399
0
        ctxBits[ ctxId ]        = sumFBits + bits.intBits[0] + ( ctxId>3 ? ((ctxId-2)>>1)<<SCALE_BITS : 0 ) + bitOffset;
400
0
        sumFBits               +=            bits.intBits[1];
401
0
      }
402
0
      ctxBits  [ maxCtxId ]     = sumFBits + ( maxCtxId>3 ? ((maxCtxId-2)>>1)<<SCALE_BITS : 0 ) + bitOffset;
403
0
      for (unsigned pos = 0; pos < std::min<unsigned>(JVET_C0024_ZERO_OUT_TH, size); pos++)
404
0
      {
405
0
        lastBits[ pos ]         = ctxBits[ g_uiGroupIdx[ pos ] ];
406
0
      }
407
0
    }
408
0
  }
409
410
  void RateEstimator::xSetSigSbbFracBits( const FracBitsAccess& fracBitsAccess, ChannelType chType )
411
0
  {
412
0
    const CtxSet& ctxSet = Ctx::SigCoeffGroup[ chType ];
413
0
    for( unsigned ctxId = 0; ctxId < sm_maxNumSigSbbCtx; ctxId++ )
414
0
    {
415
0
      m_sigSbbFracBits[ ctxId ] = fracBitsAccess.getFracBitsArray( ctxSet( ctxId ) );
416
0
    }
417
0
  }
418
419
  void RateEstimator::xSetSigFlagBits( const FracBitsAccess& fracBitsAccess, ChannelType chType )
420
0
  {
421
0
    for( unsigned ctxSetId = 0; ctxSetId < sm_numCtxSetsSig; ctxSetId++ )
422
0
    {
423
0
      BinFracBits*    bits    = m_sigFracBits [ ctxSetId ];
424
0
      const CtxSet&   ctxSet  = Ctx::SigFlag  [ chType + 2*ctxSetId ];
425
0
      const unsigned  numCtx  = ( chType == CH_L ? 12 : 8 );
426
0
      for( unsigned ctxId = 0; ctxId < numCtx; ctxId++ )
427
0
      {
428
0
        bits[ ctxId ] = fracBitsAccess.getFracBitsArray( ctxSet( ctxId ) );
429
0
      }
430
0
    }
431
0
  }
432
433
  void RateEstimator::xSetGtxFlagBits( const FracBitsAccess& fracBitsAccess, ChannelType chType )
434
0
  {
435
0
    const CtxSet&   ctxSetPar   = Ctx::ParFlag [     chType ];
436
0
    const CtxSet&   ctxSetGt1   = Ctx::GtxFlag [ 2 + chType ];
437
0
    const CtxSet&   ctxSetGt2   = Ctx::GtxFlag [     chType ];
438
0
    const unsigned  numCtx      = ( chType == CH_L ? 21 : 11 );
439
0
    for( unsigned ctxId = 0; ctxId < numCtx; ctxId++ )
440
0
    {
441
0
      BinFracBits     fbPar = fracBitsAccess.getFracBitsArray( ctxSetPar( ctxId ) );
442
0
      BinFracBits     fbGt1 = fracBitsAccess.getFracBitsArray( ctxSetGt1( ctxId ) );
443
0
      BinFracBits     fbGt2 = fracBitsAccess.getFracBitsArray( ctxSetGt2( ctxId ) );
444
0
      CoeffFracBits&  cb    = m_gtxFracBits[ ctxId ];
445
0
      int32_t         par0  = (1<<SCALE_BITS) + int32_t(fbPar.intBits[0]);
446
0
      int32_t         par1  = (1<<SCALE_BITS) + int32_t(fbPar.intBits[1]);
447
0
      cb.bits[0] = 0;
448
0
      cb.bits[1] = fbGt1.intBits[0] + (1 << SCALE_BITS);
449
0
      cb.bits[2] = fbGt1.intBits[1] + par0 + fbGt2.intBits[0];
450
0
      cb.bits[3] = fbGt1.intBits[1] + par1 + fbGt2.intBits[0];
451
0
      cb.bits[4] = fbGt1.intBits[1] + par0 + fbGt2.intBits[1];
452
0
      cb.bits[5] = fbGt1.intBits[1] + par1 + fbGt2.intBits[1];
453
0
    }
454
0
  }
455
456
  void CommonCtx::update( const ScanInfo& scanInfo, const int prevId, int stateId, StateMem& curr )
457
0
  {
458
0
    uint8_t*    sbbFlags  = m_currSbbCtx[stateId].sbbFlags;
459
0
    uint8_t*    levels    = m_currSbbCtx[stateId].levels;
460
0
    uint16_t    maxDist   = m_nbInfo[scanInfo.scanIdx - 1].maxDist;
461
0
    uint16_t    sbbSize   = scanInfo.sbbSize;
462
0
    std::size_t setCpSize = ( maxDist > sbbSize ? maxDist - sbbSize : 0 ) * sizeof( uint8_t );
463
0
    if( prevId >= 0 )
464
0
    {
465
0
      ::memcpy( sbbFlags, m_prevSbbCtx[prevId].sbbFlags, scanInfo.numSbb * sizeof( uint8_t ) );
466
0
      ::memcpy( levels + scanInfo.scanIdx + sbbSize, m_prevSbbCtx[prevId].levels + scanInfo.scanIdx + sbbSize, setCpSize );
467
0
    }
468
0
    else
469
0
    {
470
0
      ::memset( sbbFlags, 0, scanInfo.numSbb * sizeof( uint8_t ) );
471
0
      ::memset( levels + scanInfo.scanIdx + sbbSize, 0, setCpSize );
472
0
    }
473
0
    sbbFlags[scanInfo.sbbPos] = !!curr.numSig[stateId];
474
475
0
    const int       sigNSbb = ( ( scanInfo.nextSbbRight ? sbbFlags[scanInfo.nextSbbRight] : false ) || ( scanInfo.nextSbbBelow ? sbbFlags[scanInfo.nextSbbBelow] : false ) ? 1 : 0 );
476
0
    curr.refSbbCtxId[stateId] = stateId;
477
0
    const BinFracBits sbbBits = m_sbbFlagBits[sigNSbb];
478
479
0
    curr.sbbBits0[stateId] = sbbBits.intBits[0];
480
0
    curr.sbbBits1[stateId] = sbbBits.intBits[1];
481
482
0
    if( sigNSbb || ( ( scanInfo.nextSbbRight && scanInfo.nextSbbBelow ) ? sbbFlags[scanInfo.nextSbbBelow + 1] : false ) )
483
0
    {
484
0
      const int         scanBeg = scanInfo.scanIdx - scanInfo.sbbSize;
485
0
      const NbInfoOut* nbOut = m_nbInfo + scanBeg;
486
0
      const uint8_t* absLevels = levels + scanBeg;
487
488
0
      for( int id = 0; id < scanInfo.sbbSize; id++, nbOut++ )
489
0
      {
490
0
        if( nbOut->num )
491
0
        {
492
0
          TCoeff sumAbs = 0, sumAbs1 = 0, sumNum = 0;
493
0
#define UPDATE(k) {TCoeff t=absLevels[nbOut->outPos[k]]; sumAbs+=t; sumAbs1+=std::min<TCoeff>(4+(t&1),t); sumNum+=!!t; }
494
0
          switch( nbOut->num )
495
0
          {
496
0
          default:
497
0
          case 5:
498
0
            UPDATE( 4 );
499
0
          case 4:
500
0
            UPDATE( 3 );
501
0
          case 3:
502
0
            UPDATE( 2 );
503
0
          case 2:
504
0
            UPDATE( 1 );
505
0
          case 1:
506
0
            UPDATE( 0 );
507
0
          }
508
0
#undef UPDATE
509
0
          curr.tplAcc[id][stateId] = ( sumNum << 5 ) | sumAbs1;
510
0
          curr.sum1st[id][stateId] = ( uint8_t ) std::min( 255, sumAbs );
511
0
        }
512
0
      }
513
0
    }
514
0
  }
515
516
  void Quantizer::initQuantBlock(const TransformUnit& tu, const ComponentID compID, const QpParam& cQP, const double lambda, int gValue)
517
0
  {
518
0
    CHECKD( lambda <= 0.0, "Lambda must be greater than 0" );
519
520
0
    const int         qpDQ                  = cQP.Qp(tu.mtsIdx[compID]==MTS_SKIP) + 1;
521
0
    const int         qpPer                 = qpDQ / 6;
522
0
    const int         qpRem                 = qpDQ - 6 * qpPer;
523
0
    const SPS&        sps                   = *tu.cs->sps;
524
0
    const CompArea&   area                  = tu.blocks[ compID ];
525
0
    const ChannelType chType                = toChannelType( compID );
526
0
    const int         channelBitDepth       = sps.bitDepths[ chType ];
527
0
    const int         maxLog2TrDynamicRange = sps.getMaxLog2TrDynamicRange();
528
0
    const int         nomTransformShift     = getTransformShift( channelBitDepth, area.size(), maxLog2TrDynamicRange );
529
0
    const bool    needsSqrt2ScaleAdjustment = TU::needsSqrt2Scale(tu, compID);
530
0
    const int         transformShift        = nomTransformShift + (needsSqrt2ScaleAdjustment?-1:0);
531
    // quant parameters
532
0
    m_QShift                    = QUANT_SHIFT  - 1 + qpPer + transformShift;
533
0
    m_QAdd                      = -( ( 3 << m_QShift ) >> 1 );
534
0
    Intermediate_Int  invShift  = IQUANT_SHIFT + 1 - qpPer - transformShift;
535
0
    m_QScale                    = g_quantScales[needsSqrt2ScaleAdjustment?1:0][ qpRem ];
536
0
    const unsigned    qIdxBD    = std::min<unsigned>( maxLog2TrDynamicRange + 1, 8*sizeof(Intermediate_Int) + invShift - IQUANT_SHIFT - 1 );
537
0
    m_maxQIdx                   = ( 1 << (qIdxBD-1) ) - 4;
538
0
    if( m_QShift )
539
0
      m_thresLast               = TCoeff((int64_t(m_DqThrVal) << (m_QShift-1)));
540
0
    else
541
0
      m_thresLast               = TCoeff((int64_t(m_DqThrVal>>1) << m_QShift));
542
0
    m_thresSSbb                 = TCoeff((int64_t(3) << m_QShift));
543
    // distortion calculation parameters
544
0
    const int64_t qScale        = (gValue==-1) ? m_QScale : gValue;
545
0
    const int nomDShift =
546
0
      SCALE_BITS - 2 * (nomTransformShift + DISTORTION_PRECISION_ADJUSTMENT(channelBitDepth)) + m_QShift + (needsSqrt2ScaleAdjustment ? 1 : 0);
547
0
    const double  qScale2       = double( qScale * qScale );
548
0
    const double  nomDistFactor = ( nomDShift < 0 ? 1.0/(double(int64_t(1)<<(-nomDShift))*qScale2*lambda) : double(int64_t(1)<<nomDShift)/(qScale2*lambda) );
549
0
    const uint32_t pow2dfShift   = (uint32_t)( nomDistFactor * qScale2 ) + 1;
550
0
    const int     dfShift       = ceilLog2( pow2dfShift );
551
0
    m_DistShift                 = 62 + m_QShift - 2*maxLog2TrDynamicRange - dfShift;
552
0
    m_DistAdd                   = (int64_t(1) << m_DistShift) >> 1;
553
0
    m_DistStepAdd               = ((m_DistShift+m_QShift)>=64 ? (int64_t)( nomDistFactor * pow(2,m_DistShift+m_QShift) + .5 ) : (int64_t)( nomDistFactor * double(int64_t(1)<<(m_DistShift+m_QShift)) + .5 ));
554
0
    m_DistOrgFact               = (int64_t)( nomDistFactor * double(int64_t(1)<<(m_DistShift+1       )) + .5 );
555
0
  }
556
557
  void Quantizer::dequantBlock( const TransformUnit& tu, const ComponentID compID, const QpParam& cQP, CoeffBuf& recCoeff, bool enableScalingLists, int* piDequantCoef) const
558
0
  {
559
560
    //----- set basic parameters -----
561
0
    const CompArea&     area      = tu.blocks[ compID ];
562
0
    const int           numCoeff  = area.area();
563
0
    const SizeType      hsId      = Log2( area.width );
564
0
    const SizeType      vsId      = Log2( area.height );
565
0
    const ScanElement  *scan      = getScanOrder( SCAN_GROUPED_4x4, hsId, vsId );
566
0
    const TCoeffSig*    qCoeff    = tu.getCoeffs( compID ).buf;
567
0
          TCoeff*       tCoeff    = recCoeff.buf;
568
569
    //----- reset coefficients and get last scan index -----
570
0
    ::memset( tCoeff, 0, numCoeff * sizeof( TCoeff ) );
571
0
    int lastScanIdx = tu.lastPos[compID];
572
0
    if( lastScanIdx < 0 )
573
0
    {
574
0
      return;
575
0
    }
576
577
    //----- set dequant parameters -----
578
0
    const int         qpDQ                  = cQP.Qp(tu.mtsIdx[compID]==MTS_SKIP) + 1;
579
0
    const int         qpPer                 = qpDQ / 6;
580
0
    const int         qpRem                 = qpDQ - 6 * qpPer;
581
0
    const SPS&        sps                   = *tu.cs->sps;
582
0
    const ChannelType chType                = toChannelType( compID );
583
0
    const int         channelBitDepth       = sps.bitDepths[ chType ];
584
0
    const int         maxLog2TrDynamicRange = sps.getMaxLog2TrDynamicRange();
585
0
    const TCoeff      minTCoeff             = -( 1 << maxLog2TrDynamicRange );
586
0
    const TCoeff      maxTCoeff             =  ( 1 << maxLog2TrDynamicRange ) - 1;
587
0
    const int         nomTransformShift     = getTransformShift( channelBitDepth, area.size(), maxLog2TrDynamicRange );
588
0
    const bool    needsSqrt2ScaleAdjustment = TU::needsSqrt2Scale(tu, compID);
589
0
    const int         transformShift        = nomTransformShift + (needsSqrt2ScaleAdjustment?-1:0);
590
0
    Intermediate_Int  shift                 = IQUANT_SHIFT + 1 - qpPer - transformShift + (enableScalingLists ? LOG2_SCALING_LIST_NEUTRAL_VALUE : 0);
591
0
    Intermediate_Int  invQScale             = g_invQuantScales[needsSqrt2ScaleAdjustment?1:0][ qpRem ];
592
0
    Intermediate_Int  add                   = (shift < 0) ? 0 : ((1 << shift) >> 1);
593
    //----- dequant coefficients -----
594
0
    for( int state = 0, scanIdx = lastScanIdx; scanIdx >= 0; scanIdx-- )
595
0
    {
596
0
      const unsigned   rasterPos = scan[scanIdx].idx;
597
0
      const TCoeffSig& level     = qCoeff[ rasterPos ];
598
0
      if( level )
599
0
      {
600
0
        if (enableScalingLists)
601
0
          invQScale = piDequantCoef[rasterPos];//scalingfactor*levelScale
602
0
        if (shift < 0 && (enableScalingLists || scanIdx == lastScanIdx))
603
0
        {
604
0
          invQScale <<= -shift;
605
0
        }
606
0
        Intermediate_Int qIdx = 2 * level + (level > 0 ? -(state>>1) : (state>>1));
607
0
        int64_t  nomTCoeff          = ((int64_t)qIdx * (int64_t)invQScale + add) >> ((shift < 0) ? 0 : shift);
608
0
        tCoeff[rasterPos]           = (TCoeff)Clip3<int64_t>(minTCoeff, maxTCoeff, nomTCoeff);
609
0
      }
610
0
      state = ( 32040 >> ((state<<2)+((level&1)<<1)) ) & 3;   // the 16-bit value "32040" represent the state transition table
611
0
    }
612
0
  }
613
614
  bool Quantizer::preQuantCoeff( const TCoeff absCoeff, PQData* pqData, int quanCoeff ) const
615
0
  {
616
0
    int64_t scaledOrg = int64_t( absCoeff ) * quanCoeff;
617
0
    TCoeff  qIdx      = TCoeff( ( scaledOrg + m_QAdd ) >> m_QShift );
618
619
0
    if( qIdx < 0 )
620
0
    {
621
0
      int64_t scaledAdd = m_DistStepAdd - scaledOrg * m_DistOrgFact;
622
0
      PQData& pq_a      = pqData[1];
623
0
      PQData& pq_b      = pqData[2];
624
625
0
      pq_a.deltaDist    = ( ( scaledAdd + 0 * m_DistStepAdd ) * 1 + m_DistAdd ) >> m_DistShift;
626
0
      pq_a.absLevel     = 1;
627
628
0
      pq_b.deltaDist    = ( ( scaledAdd + 1 * m_DistStepAdd ) * 2 + m_DistAdd ) >> m_DistShift;
629
0
      pq_b.absLevel     = 1;
630
      
631
0
      return true;
632
0
    }
633
     
634
0
    qIdx              = std::max<TCoeff>( 1, std::min<TCoeff>( m_maxQIdx, qIdx ) );
635
0
    int64_t scaledAdd = qIdx * m_DistStepAdd - scaledOrg * m_DistOrgFact;
636
637
0
    PQData& pq_a      = pqData[( qIdx + 0 ) & 3];
638
0
    PQData& pq_b      = pqData[( qIdx + 1 ) & 3];
639
0
    PQData& pq_c      = pqData[( qIdx + 2 ) & 3];
640
0
    PQData& pq_d      = pqData[( qIdx + 3 ) & 3];
641
642
0
    pq_a.deltaDist    = ( ( scaledAdd + 0 * m_DistStepAdd ) * ( qIdx + 0 ) + m_DistAdd ) >> m_DistShift;
643
0
    pq_a.absLevel     = ( qIdx + 1 ) >> 1;
644
645
0
    pq_b.deltaDist    = ( ( scaledAdd + 1 * m_DistStepAdd ) * ( qIdx + 1 ) + m_DistAdd ) >> m_DistShift;
646
0
    pq_b.absLevel     = ( qIdx + 2 ) >> 1;
647
648
0
    pq_c.deltaDist    = ( ( scaledAdd + 2 * m_DistStepAdd ) * ( qIdx + 2 ) + m_DistAdd ) >> m_DistShift;
649
0
    pq_c.absLevel     = ( qIdx + 3 ) >> 1;
650
651
0
    pq_d.deltaDist    = ( ( scaledAdd + 3 * m_DistStepAdd ) * ( qIdx + 3 ) + m_DistAdd ) >> m_DistShift;
652
0
    pq_d.absLevel     = ( qIdx + 4 ) >> 1;
653
654
0
    return false;
655
0
  }
656
657
  const int32_t g_goRiceBits[4][RICEMAX] =
658
  {
659
    { 32768,  65536,  98304, 131072, 163840, 196608, 262144, 262144, 327680, 327680, 327680, 327680, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752},
660
    { 65536,  65536,  98304,  98304, 131072, 131072, 163840, 163840, 196608, 196608, 229376, 229376, 294912, 294912, 294912, 294912, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984},
661
    { 98304,  98304,  98304,  98304, 131072, 131072, 131072, 131072, 163840, 163840, 163840, 163840, 196608, 196608, 196608, 196608, 229376, 229376, 229376, 229376, 262144, 262144, 262144, 262144, 327680, 327680, 327680, 327680, 327680, 327680, 327680, 327680},
662
    {131072, 131072, 131072, 131072, 131072, 131072, 131072, 131072, 163840, 163840, 163840, 163840, 163840, 163840, 163840, 163840, 196608, 196608, 196608, 196608, 196608, 196608, 196608, 196608, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376}
663
  };
664
665
  static inline void initStates( const int stateId, DQIntern::StateMem& state )
666
0
  {
667
0
    state.rdCost[stateId]         = DQIntern::rdCostInit;
668
0
    state.ctx.cff[stateId]        =  0;
669
0
    state.ctx.sig[stateId]        =  0;
670
0
    state.numSig[stateId]         =  0;
671
0
    state.refSbbCtxId[stateId]    = -1;
672
0
    state.remRegBins[stateId]     =  4;
673
0
    state.cffBitsCtxOffset        =  0;
674
0
    state.m_goRicePar[stateId]    =  0;
675
0
    state.m_goRiceZero[stateId]   =  0;
676
0
    state.sbbBits0[stateId]       =  0;
677
0
    state.sbbBits1[stateId]       =  0;
678
0
  }
679
680
  template<bool rrgEnsured = false>
681
  static inline void checkRdCosts( const int stateId, const DQIntern::ScanPosType spt, const DQIntern::PQData& pqDataA, const DQIntern::PQData& pqDataB, DQIntern::Decisions& decisions, int idxAZ, int idxB, const DQIntern::StateMem& state )
682
0
  {
683
0
    const int32_t* goRiceTab = DQIntern::g_goRiceBits[state.m_goRicePar[stateId]];
684
0
    int64_t         rdCostA = state.rdCost[stateId] + pqDataA.deltaDist;
685
0
    int64_t         rdCostB = state.rdCost[stateId] + pqDataB.deltaDist;
686
0
    int64_t         rdCostZ = state.rdCost[stateId];
687
688
0
    if( rrgEnsured || state.remRegBins[stateId] >= 4 )
689
0
    {
690
0
      const CoeffFracBits& cffBits = state.m_gtxFracBitsArray[state.ctx.cff[stateId]];
691
0
      const BinFracBits    sigBits = state.m_sigFracBitsArray[stateId][state.ctx.sig[stateId]];
692
693
0
      if( pqDataA.absLevel < 4 )
694
0
        rdCostA += cffBits.bits[pqDataA.absLevel];
695
0
      else
696
0
      {
697
0
        const unsigned value = ( pqDataA.absLevel - 4 ) >> 1;
698
0
        rdCostA += cffBits.bits[pqDataA.absLevel - ( value << 1 )] + goRiceTab[std::min<unsigned>( value, RICEMAX - 1 )];
699
0
      }
700
701
0
      if( pqDataB.absLevel < 4 )
702
0
        rdCostB += cffBits.bits[pqDataB.absLevel];
703
0
      else
704
0
      {
705
0
        const unsigned value = ( pqDataB.absLevel - 4 ) >> 1;
706
0
        rdCostB += cffBits.bits[pqDataB.absLevel - ( value << 1 )] + goRiceTab[std::min<unsigned>( value, RICEMAX - 1 )];
707
0
      }
708
709
0
      if( spt == SCAN_ISCSBB )
710
0
      {
711
0
        rdCostA += sigBits.intBits[1];
712
0
        rdCostB += sigBits.intBits[1];
713
0
        rdCostZ += sigBits.intBits[0];
714
0
      }
715
0
      else if( spt == SCAN_SOCSBB )
716
0
      {
717
0
        rdCostA += state.sbbBits1[stateId] + sigBits.intBits[1];
718
0
        rdCostB += state.sbbBits1[stateId] + sigBits.intBits[1];
719
0
        rdCostZ += state.sbbBits1[stateId] + sigBits.intBits[0];
720
0
      }
721
0
      else if( state.numSig[stateId] )
722
0
      {
723
0
        rdCostA += sigBits.intBits[1];
724
0
        rdCostB += sigBits.intBits[1];
725
0
        rdCostZ += sigBits.intBits[0];
726
0
      }
727
0
      else
728
0
      {
729
0
        rdCostZ = rdCostInit;
730
0
      }
731
0
    }
732
0
    else
733
0
    {
734
0
      rdCostA += ( 1 << SCALE_BITS ) + goRiceTab[pqDataA.absLevel <= state.m_goRiceZero[stateId] ? pqDataA.absLevel - 1 : std::min<int>( pqDataA.absLevel, RICEMAX - 1 )];
735
0
      rdCostB += ( 1 << SCALE_BITS ) + goRiceTab[pqDataB.absLevel <= state.m_goRiceZero[stateId] ? pqDataB.absLevel - 1 : std::min<int>( pqDataB.absLevel, RICEMAX - 1 )];
736
0
      rdCostZ += goRiceTab[state.m_goRiceZero[stateId]];
737
0
    }
738
739
0
    if( rdCostA < rdCostZ && rdCostA < decisions.rdCost[idxAZ] )
740
0
    {
741
0
      decisions.rdCost[idxAZ] = rdCostA;
742
0
      decisions.absLevel[idxAZ] = pqDataA.absLevel;
743
0
      decisions.prevId[idxAZ] = stateId;
744
0
    }
745
0
    else if( rdCostZ < decisions.rdCost[idxAZ] )
746
0
    {
747
0
      decisions.rdCost[idxAZ] = rdCostZ;
748
0
      decisions.absLevel[idxAZ] = 0;
749
0
      decisions.prevId[idxAZ] = stateId;
750
0
    }
751
752
0
    if( rdCostB < decisions.rdCost[idxB] )
753
0
    {
754
0
      decisions.rdCost[idxB] = rdCostB;
755
0
      decisions.absLevel[idxB] = pqDataB.absLevel;
756
0
      decisions.prevId[idxB] = stateId;
757
0
    }
758
0
  }
Unexecuted instantiation: DepQuant.cpp:void vvenc::DQIntern::checkRdCosts<true>(int, vvenc::DQIntern::ScanPosType, vvenc::DQIntern::PQData const&, vvenc::DQIntern::PQData const&, vvenc::DQIntern::Decisions&, int, int, vvenc::DQIntern::StateMem const&)
Unexecuted instantiation: DepQuant.cpp:void vvenc::DQIntern::checkRdCosts<false>(int, vvenc::DQIntern::ScanPosType, vvenc::DQIntern::PQData const&, vvenc::DQIntern::PQData const&, vvenc::DQIntern::Decisions&, int, int, vvenc::DQIntern::StateMem const&)
759
760
  void checkAllRdCosts( const DQIntern::ScanPosType spt, const DQIntern::PQData* pqData, DQIntern::Decisions& decisions, const DQIntern::StateMem& state )
761
0
  {
762
0
    checkRdCosts<true>( 0, spt, pqData[0], pqData[2], decisions, 0, 2, state );
763
0
    checkRdCosts<true>( 1, spt, pqData[0], pqData[2], decisions, 2, 0, state );
764
0
    checkRdCosts<true>( 2, spt, pqData[3], pqData[1], decisions, 1, 3, state );
765
0
    checkRdCosts<true>( 3, spt, pqData[3], pqData[1], decisions, 3, 1, state );
766
0
  }
767
768
  template<bool rrgEnsured = false>
769
  static void checkRdCostsOdd1( const int stateId, const ScanPosType spt, const int64_t deltaDist, Decisions& decisions, int idxA, int idxZ, const StateMem& state )
770
0
  {
771
0
    int64_t         rdCostA = state.rdCost[stateId] + deltaDist;
772
0
    int64_t         rdCostZ = state.rdCost[stateId];
773
774
0
    if( rrgEnsured || state.remRegBins[stateId] >= 4 )
775
0
    {
776
0
      const BinFracBits sigBits = state.m_sigFracBitsArray[stateId][state.ctx.sig[stateId]];
777
778
0
      rdCostA += state.cffBits1[state.ctx.cff[stateId]];
779
780
0
      if( spt == SCAN_ISCSBB )
781
0
      {
782
0
        rdCostA += sigBits.intBits[1];
783
0
        rdCostZ += sigBits.intBits[0];
784
0
      }
785
0
      else if( spt == SCAN_SOCSBB )
786
0
      {
787
0
        rdCostA += state.sbbBits1[stateId] + sigBits.intBits[1];
788
0
        rdCostZ += state.sbbBits1[stateId] + sigBits.intBits[0];
789
0
      }
790
0
      else if( state.numSig[stateId] )
791
0
      {
792
0
        rdCostA += sigBits.intBits[1];
793
0
        rdCostZ += sigBits.intBits[0];
794
0
      }
795
0
      else
796
0
      {
797
0
        rdCostZ = rdCostInit;
798
0
      }
799
0
    }
800
0
    else
801
0
    {
802
0
      const int32_t* goRiceTab = g_goRiceBits[state.m_goRicePar[stateId]];
803
804
0
      rdCostA += ( 1 << SCALE_BITS ) + goRiceTab[0];
805
0
      rdCostZ += goRiceTab[state.m_goRiceZero[stateId]];
806
0
    }
807
808
0
    if( rdCostA < decisions.rdCost[idxA] )
809
0
    {
810
0
      decisions.rdCost[idxA] = rdCostA;
811
0
      decisions.absLevel[idxA] = 1;
812
0
      decisions.prevId[idxA] = stateId;
813
0
    }
814
815
0
    if( rdCostZ < decisions.rdCost[idxZ] )
816
0
    {
817
0
      decisions.rdCost[idxZ] = rdCostZ;
818
0
      decisions.absLevel[idxZ] = 0;
819
0
      decisions.prevId[idxZ] = stateId;
820
0
    }
821
0
  }
Unexecuted instantiation: DepQuant.cpp:void vvenc::DQIntern::checkRdCostsOdd1<true>(int, vvenc::DQIntern::ScanPosType, long, vvenc::DQIntern::Decisions&, int, int, vvenc::DQIntern::StateMem const&)
Unexecuted instantiation: DepQuant.cpp:void vvenc::DQIntern::checkRdCostsOdd1<false>(int, vvenc::DQIntern::ScanPosType, long, vvenc::DQIntern::Decisions&, int, int, vvenc::DQIntern::StateMem const&)
822
823
  static void checkAllRdCostsOdd1( const DQIntern::ScanPosType spt, const int64_t pq_a_dist, const int64_t pq_b_dist, DQIntern::Decisions& decisions, const DQIntern::StateMem& state )
824
0
  {
825
0
    checkRdCostsOdd1<true>( 0, spt, pq_b_dist, decisions, 2, 0, state );
826
0
    checkRdCostsOdd1<true>( 1, spt, pq_b_dist, decisions, 0, 2, state );
827
0
    checkRdCostsOdd1<true>( 2, spt, pq_a_dist, decisions, 3, 1, state );
828
0
    checkRdCostsOdd1<true>( 3, spt, pq_a_dist, decisions, 1, 3, state );
829
0
  }
830
831
  static inline void checkRdCostStart( int32_t lastOffset, const PQData& pqData, Decisions& decisions, int idx, const StateMem& state )
832
0
  {
833
0
    const CoeffFracBits& cffBits = state.m_gtxFracBitsArray[0];
834
835
0
    int64_t rdCost = pqData.deltaDist + lastOffset;
836
0
    if( pqData.absLevel < 4 )
837
0
    {
838
0
      rdCost += cffBits.bits[pqData.absLevel];
839
0
    }
840
0
    else
841
0
    {
842
0
      const unsigned value = ( pqData.absLevel - 4 ) >> 1;
843
0
      rdCost += cffBits.bits[pqData.absLevel - ( value << 1 )] + g_goRiceBits[0][value < RICEMAX ? value : RICEMAX - 1];
844
0
    }
845
846
0
    if( rdCost < decisions.rdCost[idx] )
847
0
    {
848
0
      decisions.rdCost[idx]   = rdCost;
849
0
      decisions.absLevel[idx] = pqData.absLevel;
850
0
      decisions.prevId[idx]   = -1;
851
0
    }
852
0
  }
853
854
  static inline void checkRdCostSkipSbb( const int stateId, Decisions& decisions, int idx, const StateMem& state )
855
0
  {
856
0
    int64_t rdCost = state.rdCost[stateId] + state.sbbBits0[stateId];
857
0
    if( rdCost < decisions.rdCost[idx] )
858
0
    {
859
0
      decisions.rdCost[idx]   = rdCost;
860
0
      decisions.absLevel[idx] = 0;
861
0
      decisions.prevId[idx]   = 4 | stateId;
862
0
    }
863
0
  }
864
865
  static inline void checkRdCostSkipSbbZeroOut( const int stateId, Decisions& decisions, int idx, const StateMem& state )
866
0
  {
867
0
    int64_t rdCost          = state.rdCost[stateId] + state.sbbBits0[stateId];
868
0
    decisions.rdCost[idx]   = rdCost;
869
0
    decisions.absLevel[idx] = 0;
870
0
    decisions.prevId[idx]   = 4 | stateId;
871
0
  }
872
873
  static inline void setRiceParam( const int stateId, const ScanInfo& scanInfo, StateMem& state, bool ge4 )
874
0
  {
875
0
    if( state.remRegBins[stateId] < 4 || ge4 )
876
0
    {
877
0
      TCoeff  sumAbs = state.sum1st[scanInfo.insidePos][stateId];
878
0
      int sumSub     = state.remRegBins[stateId] < 4 ? 0 : 4 * 5;
879
0
      int sumAll     = std::max( std::min( 31, ( int ) sumAbs - sumSub ), 0 );
880
0
      state.m_goRicePar[stateId]
881
0
                     = g_auiGoRiceParsCoeff[sumAll];
882
883
0
      if( state.remRegBins[stateId] < 4 )
884
0
      {
885
0
        state.m_goRiceZero[stateId] = g_auiGoRicePosCoeff0( stateId, state.m_goRicePar[stateId] );
886
0
      }
887
0
    }
888
0
  }
889
890
  static void update1State( int stateId, const DQIntern::ScanInfo& scanInfo, const DQIntern::Decisions& decisions, DQIntern::StateMem& curr, DQIntern::StateMem& prev )
891
0
  {
892
0
    curr.rdCost[stateId] = decisions.rdCost[stateId];
893
0
    if( decisions.prevId[stateId] > -2 )
894
0
    {
895
0
      if( decisions.prevId[stateId] >= 0 )
896
0
      {
897
0
        const int prevId          = decisions.prevId[stateId];
898
0
        curr.numSig[stateId]      = prev.numSig[prevId] + !!decisions.absLevel[stateId];
899
0
        curr.refSbbCtxId[stateId] = prev.refSbbCtxId[prevId];
900
0
        curr.sbbBits0[stateId]    = prev.sbbBits0[prevId];
901
0
        curr.sbbBits1[stateId]    = prev.sbbBits1[prevId];
902
0
        curr.remRegBins[stateId]  = prev.remRegBins[prevId] - 1;
903
904
0
        if( curr.remRegBins[stateId] >= 4 )
905
0
        {
906
0
          curr.remRegBins[stateId] -= ( decisions.absLevel[stateId] < 2 ? decisions.absLevel[stateId] : 3 );
907
0
        }
908
909
0
        for( int i = 0; i < 16; i++ )
910
0
        {
911
0
          curr.tplAcc[i][stateId] = prev.tplAcc[i][prevId];
912
0
          curr.sum1st[i][stateId] = prev.sum1st[i][prevId];
913
0
          curr.absVal[i][stateId] = prev.absVal[i][prevId];
914
0
        }
915
0
      }
916
0
      else
917
0
      {
918
0
        curr.numSig[stateId]      =  1;
919
0
        curr.refSbbCtxId[stateId] = -1;
920
0
        curr.remRegBins[stateId]  = prev.initRemRegBins;
921
0
        curr.remRegBins[stateId] -= ( decisions.absLevel[stateId] < 2 ? decisions.absLevel[stateId] : 3 );
922
923
0
        for( int i = 0; i < 16; i++ )
924
0
        {
925
0
          curr.tplAcc[i][stateId] = 0;
926
0
          curr.sum1st[i][stateId] = 0;
927
0
          curr.absVal[i][stateId] = 0;
928
0
        }
929
0
      }
930
931
0
      if( decisions.absLevel[stateId] )
932
0
      {
933
0
        curr.absVal[scanInfo.insidePos][stateId] = ( uint8_t ) std::min<TCoeff>( 126 + ( decisions.absLevel[stateId] & 1 ), decisions.absLevel[stateId] );
934
935
0
        if( scanInfo.currNbInfoSbb.numInv )
936
0
        {
937
0
          int min4_or_5 = std::min<TCoeff>( 4 + ( decisions.absLevel[stateId] & 1 ), decisions.absLevel[stateId] );
938
939
0
          auto adds8 = []( uint8_t a, uint8_t b )
940
0
          {
941
0
            uint8_t c = a + b;
942
0
            if( c < a ) c = -1;
943
0
            return c;
944
0
          };
945
946
0
          auto update_deps = [&]( int k )
947
0
          {
948
0
            curr.tplAcc[scanInfo.currNbInfoSbb.invInPos[k]][stateId] += 32 + min4_or_5;
949
0
            curr.sum1st[scanInfo.currNbInfoSbb.invInPos[k]][stateId] = adds8( curr.sum1st[scanInfo.currNbInfoSbb.invInPos[k]][stateId], decisions.absLevel[stateId] );
950
0
          };
951
952
0
          switch( scanInfo.currNbInfoSbb.numInv )
953
0
          {
954
0
          default:
955
0
          case 5:
956
0
            update_deps( 4 );
957
0
          case 4:
958
0
            update_deps( 3 );
959
0
          case 3:
960
0
            update_deps( 2 );
961
0
          case 2:
962
0
            update_deps( 1 );
963
0
          case 1:
964
0
            update_deps( 0 );
965
0
          }
966
0
        }
967
0
      }
968
969
0
      if( curr.remRegBins[stateId] >= 4 )
970
0
      {
971
0
        TCoeff  sumAbs1 = curr.tplAcc[scanInfo.nextInsidePos][stateId] & 31;
972
0
        TCoeff  sumNum  = curr.tplAcc[scanInfo.nextInsidePos][stateId] >> 5u;
973
0
        int sumGt1 = sumAbs1 - sumNum;
974
975
0
        curr.ctx.sig[stateId] = scanInfo.sigCtxOffsetNext + std::min( ( sumAbs1 + 1 ) >> 1, 3 );
976
0
        curr.ctx.cff[stateId] = scanInfo.gtxCtxOffsetNext + std::min( sumGt1, 4 );
977
0
      }
978
0
      else
979
0
      {
980
0
        curr.anyRemRegBinsLt4 = true;
981
0
      }
982
0
    }
983
0
  }
984
985
  static void update1StateEOS( const int stateId, const DQIntern::ScanInfo& scanInfo, const DQIntern::Decisions& decisions, const DQIntern::StateMem& skip, DQIntern::StateMem& curr, DQIntern::StateMem& prev, DQIntern::CommonCtx& commonCtx )
986
0
  {
987
0
    curr.rdCost[stateId] = decisions.rdCost[stateId];
988
989
0
    if( decisions.prevId[stateId] > -2 )
990
0
    {
991
0
      if( decisions.prevId[stateId] >= 4 )
992
0
      {
993
0
        CHECK( decisions.absLevel[stateId] != 0, "cannot happen" );
994
995
0
        const int prevId          = decisions.prevId[stateId] - 4;
996
0
        curr.numSig    [stateId]  = 0;
997
0
        curr.remRegBins[stateId]  = skip.remRegBins[prevId];
998
0
        curr.refSbbCtxId[stateId] = prevId;
999
1000
0
        for( int i = 0; i < 16; i++ )
1001
0
        {
1002
0
          curr.absVal[i][stateId] = 0;
1003
0
        }
1004
0
      }
1005
0
      else if( decisions.prevId[stateId] >= 0 )
1006
0
      {
1007
0
        const int prevId          = decisions.prevId[stateId];
1008
0
        curr.numSig[stateId]      = prev.numSig[prevId] + !!decisions.absLevel[stateId];
1009
0
        curr.refSbbCtxId[stateId] = prev.refSbbCtxId[prevId];
1010
0
        curr.remRegBins[stateId]  = prev.remRegBins[prevId] - 1;
1011
1012
0
        if( curr.remRegBins[stateId] >= 4 )
1013
0
        {
1014
0
          curr.remRegBins[stateId] -= ( decisions.absLevel[stateId] < 2 ? decisions.absLevel[stateId] : 3 );
1015
0
        }
1016
1017
0
        for( int i = 0; i < 16; i++ )
1018
0
        {
1019
0
          curr.absVal[i][stateId] = prev.absVal[i][prevId];
1020
0
        }
1021
0
      }
1022
0
      else
1023
0
      {
1024
0
        curr.numSig[stateId]      =  1;
1025
0
        curr.refSbbCtxId[stateId] = -1;
1026
0
        curr.remRegBins[stateId]  = prev.initRemRegBins;
1027
0
        curr.remRegBins[stateId] -= ( decisions.absLevel[stateId] < 2 ? decisions.absLevel[stateId] : 3 );
1028
1029
0
        for( int i = 0; i < 16; i++ )
1030
0
        {
1031
0
          curr.absVal[i][stateId] = 0;
1032
0
        }
1033
0
      }
1034
1035
0
      curr.absVal[scanInfo.insidePos][stateId] = ( uint8_t ) std::min<TCoeff>( 126 + ( decisions.absLevel[stateId] & 1 ), decisions.absLevel[stateId] );
1036
1037
0
      uint8_t* levels[4];
1038
0
      commonCtx.getLevelPtrs( scanInfo, levels[0], levels[1], levels[2], levels[3] );
1039
0
      for( int i = 0; i < 16; i++ )
1040
0
      {
1041
        // save abs levels to commonCtx
1042
0
        levels[stateId][i] = curr.absVal[i][stateId];
1043
        // clean the SBB ctx
1044
0
        curr.tplAcc[i][stateId] = 0;
1045
0
        curr.sum1st[i][stateId] = 0;
1046
0
        curr.absVal[i][stateId] = 0;
1047
0
      }
1048
1049
0
      commonCtx.update( scanInfo, curr.refSbbCtxId[stateId], stateId, curr );
1050
1051
0
      curr.numSig[stateId] = 0;
1052
1053
0
      if( curr.remRegBins[stateId] >= 4 )
1054
0
      {
1055
0
        TCoeff  sumAbs1 = curr.tplAcc[scanInfo.nextInsidePos][stateId] & 31;
1056
0
        TCoeff  sumNum  = curr.tplAcc[scanInfo.nextInsidePos][stateId] >> 5u;
1057
0
        int sumGt1 = sumAbs1 - sumNum;
1058
1059
0
        curr.ctx.sig[stateId] = scanInfo.sigCtxOffsetNext + std::min( ( sumAbs1 + 1 ) >> 1, 3 );
1060
0
        curr.ctx.cff[stateId] = scanInfo.gtxCtxOffsetNext + std::min( sumGt1, 4 );
1061
0
      }
1062
0
      else
1063
0
      {
1064
0
        curr.anyRemRegBinsLt4 = true;
1065
0
      }
1066
0
    }
1067
0
  }
1068
1069
  static void updateStates( const DQIntern::ScanInfo& scanInfo, const DQIntern::Decisions& decisions, DQIntern::StateMem& curr )
1070
0
  {
1071
0
    DQIntern::StateMem prev = curr;
1072
0
    curr.anyRemRegBinsLt4   = false;
1073
1074
0
    update1State( 0, scanInfo, decisions, curr, prev );
1075
0
    update1State( 1, scanInfo, decisions, curr, prev );
1076
0
    update1State( 2, scanInfo, decisions, curr, prev );
1077
0
    update1State( 3, scanInfo, decisions, curr, prev );
1078
1079
0
    curr.cffBitsCtxOffset = scanInfo.gtxCtxOffsetNext;
1080
0
  }
1081
1082
  static void updateStatesEOS( const DQIntern::ScanInfo& scanInfo, const DQIntern::Decisions& decisions, const DQIntern::StateMem& skip, DQIntern::StateMem& curr, DQIntern::CommonCtx& commonCtx )
1083
0
  {
1084
0
    DQIntern::StateMem prev = curr;
1085
0
    curr.anyRemRegBinsLt4   = false;
1086
1087
0
    update1StateEOS( 0, scanInfo, decisions, skip, curr, prev, commonCtx );
1088
0
    update1StateEOS( 1, scanInfo, decisions, skip, curr, prev, commonCtx );
1089
0
    update1StateEOS( 2, scanInfo, decisions, skip, curr, prev, commonCtx );
1090
0
    update1StateEOS( 3, scanInfo, decisions, skip, curr, prev, commonCtx );
1091
1092
0
    curr.cffBitsCtxOffset = scanInfo.gtxCtxOffsetNext;
1093
0
  }
1094
}; // namespace DQIntern
1095
1096
static const DQIntern::Decisions startDec[2] =
1097
{
1098
  DQIntern::Decisions
1099
  {
1100
    { DQIntern::rdCostInit >> 2, DQIntern::rdCostInit >> 2, DQIntern::rdCostInit >> 2, DQIntern::rdCostInit >> 2 },
1101
    { -1, -1, -1, -1 },
1102
    { -2, -2, -2, -2 },
1103
  },
1104
  DQIntern::Decisions
1105
  {
1106
    { DQIntern::rdCostInit >> 2, DQIntern::rdCostInit >> 2, DQIntern::rdCostInit >> 2, DQIntern::rdCostInit >> 2 },
1107
    { 0, 0, 0, 0 },
1108
    { 4, 5, 6, 7 },
1109
  }
1110
};
1111
1112
void DepQuant::xQuantDQ( TransformUnit& tu, const CCoeffBuf& srcCoeff, const ComponentID compID, const QpParam& cQP, const double lambda, const Ctx& ctx, TCoeff& absSum, bool enableScalingLists, int* quantCoeff )
1113
0
{
1114
0
  using namespace DQIntern;
1115
  
1116
  //===== reset / pre-init =====
1117
0
  const TUParameters& tuPars  = *m_scansRom->getTUPars( tu.blocks[compID], compID );
1118
0
  m_quant.initQuantBlock    ( tu, compID, cQP, lambda );
1119
0
  TCoeffSig*    qCoeff      = tu.getCoeffs( compID ).buf;
1120
0
  const TCoeff* tCoeff      = srcCoeff.buf;
1121
0
  const int     numCoeff    = tu.blocks[compID].area();
1122
0
  ::memset( qCoeff, 0x00, numCoeff * sizeof( TCoeffSig ) );
1123
0
  absSum                    = 0;
1124
1125
0
  const CompArea& area      = tu.blocks[ compID ];
1126
0
  const uint32_t  width     = area.width;
1127
0
  const uint32_t  height    = area.height;
1128
0
  const uint32_t  lfnstIdx  = tu.cu->lfnstIdx;
1129
  //===== scaling matrix ====
1130
  //const int         qpDQ = cQP.Qp + 1;
1131
  //const int         qpPer = qpDQ / 6;
1132
  //const int         qpRem = qpDQ - 6 * qpPer;
1133
1134
  //TCoeff thresTmp = thres;
1135
0
  bool zeroOut = false;
1136
0
  bool zeroOutforThres = false;
1137
0
  int effWidth = tuPars.m_width, effHeight = tuPars.m_height;
1138
0
  if( ( tu.mtsIdx[compID] > MTS_SKIP || ( tu.cs->sps->MTS && tu.cu->sbtInfo != 0 && tuPars.m_height <= 32 && tuPars.m_width <= 32 ) ) && compID == COMP_Y )
1139
0
  {
1140
0
    effHeight = ( tuPars.m_height == 32 ) ? 16 : tuPars.m_height;
1141
0
    effWidth  = ( tuPars.m_width  == 32 ) ? 16 : tuPars.m_width;
1142
0
    zeroOut   = ( effHeight < tuPars.m_height || effWidth < tuPars.m_width );
1143
0
  }
1144
0
  zeroOutforThres = zeroOut || ( 32 < tuPars.m_height || 32 < tuPars.m_width );
1145
  //===== find first test position =====
1146
0
  int firstTestPos = std::min<int>( tuPars.m_width, JVET_C0024_ZERO_OUT_TH ) * std::min<int>( tuPars.m_height, JVET_C0024_ZERO_OUT_TH ) - 1;
1147
0
  if( lfnstIdx > 0 && tu.mtsIdx[compID] != MTS_SKIP && width >= 4 && height >= 4 )
1148
0
  {
1149
0
    firstTestPos = ( ( width == 4 && height == 4 ) || ( width == 8 && height == 8 ) )  ? 7 : 15 ;
1150
0
  }
1151
1152
0
  const TCoeff defaultQuantisationCoefficient = (TCoeff)m_quant.getQScale();
1153
0
  const TCoeff thres = m_quant.getLastThreshold();
1154
0
  const int zeroOutWidth  = ( tuPars.m_width  == 32 && zeroOut ) ? 16 : 32;
1155
0
  const int zeroOutHeight = ( tuPars.m_height == 32 && zeroOut ) ? 16 : 32;
1156
1157
0
  if( enableScalingLists )
1158
0
  {
1159
0
    for( ; firstTestPos >= 0; firstTestPos-- )
1160
0
    {
1161
0
      if( zeroOutforThres && ( tuPars.m_scanId2BlkPos[firstTestPos].x >= zeroOutWidth || tuPars.m_scanId2BlkPos[firstTestPos].y >= zeroOutHeight ) ) continue;
1162
1163
0
      const TCoeff thresTmp = TCoeff( thres / ( 4 * quantCoeff[tuPars.m_scanId2BlkPos[firstTestPos].idx] ) );
1164
1165
0
      if( abs( tCoeff[tuPars.m_scanId2BlkPos[firstTestPos].idx] ) > thresTmp ) break;
1166
0
    }
1167
0
  }
1168
0
  else
1169
0
  {
1170
0
    const TCoeff defaultTh = TCoeff( thres / ( defaultQuantisationCoefficient << 2 ) );
1171
1172
0
    if( m_findFirstPos )
1173
0
    {
1174
0
      m_findFirstPos( firstTestPos, tCoeff, tuPars, defaultTh, zeroOutforThres, zeroOutWidth, zeroOutHeight );
1175
0
    }
1176
1177
0
    for( ; firstTestPos >= 0; firstTestPos-- )
1178
0
    {
1179
0
      if( zeroOutforThres && ( tuPars.m_scanId2BlkPos[firstTestPos].x >= zeroOutWidth || tuPars.m_scanId2BlkPos[firstTestPos].y >= zeroOutHeight ) ) continue;
1180
0
      if( abs( tCoeff[tuPars.m_scanId2BlkPos[firstTestPos].idx] ) > defaultTh ) break;
1181
0
    }
1182
0
  }
1183
1184
0
  if( firstTestPos < 0 )
1185
0
  {
1186
0
    tu.lastPos[compID] = -1;
1187
0
    return;
1188
0
  }
1189
1190
  //===== real init =====
1191
0
  RateEstimator::initCtx( tuPars, tu, compID, ctx.getFracBitsAcess() );
1192
0
  m_commonCtx.reset( tuPars, *this );
1193
0
  for( int k = 0; k < 4; k++ )
1194
0
  {
1195
0
    DQIntern::initStates( k, m_state_curr );
1196
0
    DQIntern::initStates( k, m_state_skip );
1197
0
    m_state_curr.m_sigFracBitsArray[k] = RateEstimator::sigFlagBits(k);
1198
0
  }
1199
1200
0
  m_state_curr.m_gtxFracBitsArray = RateEstimator::gtxFracBits();
1201
  //memset( m_state_curr.tplAcc, 0, sizeof( m_state_curr.tplAcc ) ); // will be set in updateStates{,EOS} before first access
1202
0
  memset( m_state_curr.sum1st, 0, sizeof( m_state_curr.sum1st ) );   // will be accessed in setRiceParam before updateState{,EOS}
1203
  //memset( m_state_curr.absVal, 0, sizeof( m_state_curr.absVal ) ); // will be set in updateStates{,EOS} before first access
1204
1205
0
  const int numCtx = isLuma( compID ) ? 21 : 11;
1206
0
  const CoeffFracBits* const cffBits = gtxFracBits();
1207
0
  for( int i = 0; i < numCtx; i++ )
1208
0
  {
1209
0
    m_state_curr.cffBits1[i] = cffBits[i].bits[1];
1210
0
  }
1211
1212
0
  int effectWidth  = std::min( 32, effWidth );
1213
0
  int effectHeight = std::min( 32, effHeight );
1214
0
  m_state_curr.initRemRegBins   = ( effectWidth * effectHeight * MAX_TU_LEVEL_CTX_CODED_BIN_CONSTRAINT ) / 16;
1215
0
  m_state_curr.anyRemRegBinsLt4 = true; // for the first coeff use scalar impl., because it check against the init state, which
1216
                                        // prohibits some paths
1217
1218
  //===== populate trellis =====
1219
0
  for( int scanIdx = firstTestPos; scanIdx >= 0; scanIdx-- )
1220
0
  {
1221
0
    const ScanInfo& scanInfo = tuPars.m_scanInfo[ scanIdx ];
1222
0
    if( enableScalingLists )
1223
0
    {
1224
0
      m_quant.initQuantBlock( tu, compID, cQP, lambda, quantCoeff[scanInfo.rasterPos] );
1225
0
      xDecideAndUpdate( abs( tCoeff[scanInfo.rasterPos] ), scanInfo, zeroOut && ( scanInfo.posX >= effWidth || scanInfo.posY >= effHeight ), quantCoeff[scanInfo.rasterPos] );
1226
0
    }
1227
0
    else
1228
0
      xDecideAndUpdate( abs( tCoeff[scanInfo.rasterPos] ), scanInfo, zeroOut && ( scanInfo.posX >= effWidth || scanInfo.posY >= effHeight ), defaultQuantisationCoefficient );
1229
0
  }
1230
1231
  //===== find best path =====
1232
0
  int       prevId      = -1;
1233
0
  int64_t   minPathCost =  0;
1234
0
  for( int8_t stateId = 0; stateId < 4; stateId++ )
1235
0
  {
1236
0
    int64_t pathCost = m_trellis[0][0].rdCost[stateId];
1237
0
    if( pathCost < minPathCost )
1238
0
    {
1239
0
      prevId      = stateId;
1240
0
      minPathCost = pathCost;
1241
0
    }
1242
0
  }
1243
1244
  //===== backward scanning =====
1245
0
  int scanIdx = 0;
1246
0
  for( ; prevId >= 0; scanIdx++ )
1247
0
  {
1248
0
    TCoeffSig absLevel = m_trellis[scanIdx][prevId >> 2].absLevel[prevId & 3];
1249
0
    int32_t blkpos     = tuPars.m_scanId2BlkPos[scanIdx].idx;
1250
0
    qCoeff[ blkpos ]   = TCoeffSig( tCoeff[blkpos] < 0 ? -absLevel : absLevel );
1251
0
    absSum            += absLevel;
1252
0
    prevId             = m_trellis[scanIdx][prevId >> 2].prevId[prevId & 3];
1253
0
  }
1254
1255
0
  tu.lastPos[compID] = scanIdx - 1;
1256
0
}
1257
1258
void DepQuant::xDecide( const DQIntern::ScanInfo& scanInfo, const TCoeff absCoeff, const int lastOffset, DQIntern::Decisions& decisions, bool zeroOut, int quantCoeff )
1259
0
{
1260
0
  using namespace DQIntern;
1261
1262
0
  ::memcpy( &decisions, startDec, sizeof( Decisions ) );
1263
1264
0
  StateMem& skip = m_state_skip;
1265
1266
0
  if( zeroOut )
1267
0
  {
1268
0
    if( scanInfo.spt == SCAN_EOCSBB )
1269
0
    {
1270
0
      checkRdCostSkipSbbZeroOut( 0, decisions, 0, skip );
1271
0
      checkRdCostSkipSbbZeroOut( 1, decisions, 1, skip );
1272
0
      checkRdCostSkipSbbZeroOut( 2, decisions, 2, skip );
1273
0
      checkRdCostSkipSbbZeroOut( 3, decisions, 3, skip );
1274
0
    }
1275
0
    return;
1276
0
  }
1277
1278
0
  StateMem& prev = m_state_curr;
1279
1280
  /// start inline prequant
1281
0
  int64_t scaledOrg = int64_t( absCoeff ) * quantCoeff;
1282
0
  TCoeff  qIdx      = TCoeff( ( scaledOrg + m_quant.m_QAdd ) >> m_quant.m_QShift );
1283
1284
0
  if( qIdx < 0 )
1285
0
  {
1286
0
    int64_t scaledAdd = m_quant.m_DistStepAdd - scaledOrg * m_quant.m_DistOrgFact;
1287
0
    int64_t pq_a_dist = ( ( scaledAdd + 0 * m_quant.m_DistStepAdd ) * 1 + m_quant.m_DistAdd ) >> m_quant.m_DistShift;
1288
0
    int64_t pq_b_dist = ( ( scaledAdd + 1 * m_quant.m_DistStepAdd ) * 2 + m_quant.m_DistAdd ) >> m_quant.m_DistShift;
1289
    /// stop inline prequant
1290
1291
0
    if( prev.anyRemRegBinsLt4 )
1292
0
    {
1293
0
      setRiceParam( 0, scanInfo, prev, false );
1294
0
      checkRdCostsOdd1( 0, scanInfo.spt, pq_b_dist, decisions, 2, 0, prev );
1295
1296
0
      setRiceParam( 1, scanInfo, prev, false );
1297
0
      checkRdCostsOdd1( 1, scanInfo.spt, pq_b_dist, decisions, 0, 2, prev );
1298
1299
0
      setRiceParam( 2, scanInfo, prev, false );
1300
0
      checkRdCostsOdd1( 2, scanInfo.spt, pq_a_dist, decisions, 3, 1, prev );
1301
1302
0
      setRiceParam( 3, scanInfo, prev, false );
1303
0
      checkRdCostsOdd1( 3, scanInfo.spt, pq_a_dist, decisions, 1, 3, prev );
1304
0
    }
1305
0
    else
1306
0
    {
1307
      // has to be called as a first check, assumes no decision has been made yet
1308
0
      m_checkAllRdCostsOdd1( scanInfo.spt, pq_a_dist, pq_b_dist, decisions, prev );
1309
0
    }
1310
1311
0
    checkRdCostStart( lastOffset, PQData{ 1, pq_b_dist }, decisions, 2, prev );
1312
0
  }
1313
0
  else
1314
0
  {
1315
    /// start inline prequant
1316
0
    qIdx = std::max<TCoeff>( 1, std::min<TCoeff>( m_quant.m_maxQIdx, qIdx ) );
1317
0
    int64_t scaledAdd = qIdx * m_quant.m_DistStepAdd - scaledOrg * m_quant.m_DistOrgFact;
1318
1319
0
    PQData  pqData[4];
1320
1321
0
    PQData& pq_a = pqData[( qIdx + 0 ) & 3];
1322
0
    PQData& pq_b = pqData[( qIdx + 1 ) & 3];
1323
0
    PQData& pq_c = pqData[( qIdx + 2 ) & 3];
1324
0
    PQData& pq_d = pqData[( qIdx + 3 ) & 3];
1325
1326
0
    pq_a.deltaDist = ( ( scaledAdd + 0 * m_quant.m_DistStepAdd ) * ( qIdx + 0 ) + m_quant.m_DistAdd ) >> m_quant.m_DistShift;
1327
0
    pq_a.absLevel = ( qIdx + 1 ) >> 1;
1328
1329
0
    pq_b.deltaDist = ( ( scaledAdd + 1 * m_quant.m_DistStepAdd ) * ( qIdx + 1 ) + m_quant.m_DistAdd ) >> m_quant.m_DistShift;
1330
0
    pq_b.absLevel = ( qIdx + 2 ) >> 1;
1331
1332
0
    pq_c.deltaDist = ( ( scaledAdd + 2 * m_quant.m_DistStepAdd ) * ( qIdx + 2 ) + m_quant.m_DistAdd ) >> m_quant.m_DistShift;
1333
0
    pq_c.absLevel = ( qIdx + 3 ) >> 1;
1334
1335
0
    pq_d.deltaDist = ( ( scaledAdd + 3 * m_quant.m_DistStepAdd ) * ( qIdx + 3 ) + m_quant.m_DistAdd ) >> m_quant.m_DistShift;
1336
0
    pq_d.absLevel = ( qIdx + 4 ) >> 1;
1337
    /// stop inline prequant
1338
1339
0
    bool cff02ge4 = pqData[0].absLevel >= 4/* || pqData[2].absLevel >= 4 */;
1340
0
    bool cff13ge4 = /* pqData[1].absLevel >= 4 || */ pqData[3].absLevel >= 4;
1341
1342
0
    if( cff02ge4 || cff13ge4 || prev.anyRemRegBinsLt4 )
1343
0
    {
1344
0
      if( prev.anyRemRegBinsLt4 || cff02ge4 )
1345
0
      {
1346
0
        setRiceParam( 0, scanInfo, prev, cff02ge4 );
1347
0
        setRiceParam( 1, scanInfo, prev, cff02ge4 );
1348
0
      }
1349
1350
0
      if( prev.anyRemRegBinsLt4 || cff13ge4 )
1351
0
      {
1352
0
        setRiceParam( 2, scanInfo, prev, cff13ge4 );
1353
0
        setRiceParam( 3, scanInfo, prev, cff13ge4 );
1354
0
      }
1355
1356
0
      checkRdCosts( 0, scanInfo.spt, pqData[0], pqData[2], decisions, 0, 2, prev );
1357
0
      checkRdCosts( 1, scanInfo.spt, pqData[0], pqData[2], decisions, 2, 0, prev );
1358
0
      checkRdCosts( 2, scanInfo.spt, pqData[3], pqData[1], decisions, 1, 3, prev );
1359
0
      checkRdCosts( 3, scanInfo.spt, pqData[3], pqData[1], decisions, 3, 1, prev );
1360
0
    }
1361
0
    else
1362
0
    {
1363
      // has to be called as a first check, assumes no decision has been made yet
1364
0
      m_checkAllRdCosts( scanInfo.spt, pqData, decisions, prev );
1365
0
    }
1366
1367
0
    checkRdCostStart( lastOffset, pqData[0], decisions, 0, prev );
1368
0
    checkRdCostStart( lastOffset, pqData[2], decisions, 2, prev );
1369
0
  }
1370
1371
0
  if( scanInfo.spt == SCAN_EOCSBB )
1372
0
  {
1373
0
    checkRdCostSkipSbb( 0, decisions, 0, skip );
1374
0
    checkRdCostSkipSbb( 1, decisions, 1, skip );
1375
0
    checkRdCostSkipSbb( 2, decisions, 2, skip );
1376
0
    checkRdCostSkipSbb( 3, decisions, 3, skip );
1377
0
  }
1378
0
}
1379
1380
void DepQuant::xDecideAndUpdate( const TCoeff absCoeff, const DQIntern::ScanInfo& scanInfo, bool zeroOut, int quantCoeff )
1381
0
{
1382
0
  using namespace DQIntern;
1383
1384
0
  Decisions* decisions = &m_trellis[scanInfo.scanIdx][0];
1385
1386
0
  xDecide( scanInfo, absCoeff, lastOffset( scanInfo.scanIdx ), *decisions, zeroOut, quantCoeff );
1387
1388
0
  if( scanInfo.scanIdx )
1389
0
  {
1390
0
    if( scanInfo.spt == SCAN_SOCSBB )
1391
0
    {
1392
0
      memcpy( &m_state_skip, &m_state_curr, DQIntern::StateMemSkipCpySize );
1393
0
    }
1394
1395
0
    if( scanInfo.insidePos == 0 )
1396
0
    {
1397
0
      m_commonCtx.swap();
1398
0
      m_updateStatesEOS( scanInfo, *decisions, m_state_skip, m_state_curr, m_commonCtx );
1399
0
      ::memcpy( decisions + 1, decisions, sizeof( Decisions ) );
1400
0
    }
1401
0
    else if( !zeroOut )
1402
0
    {
1403
0
      m_updateStates( scanInfo, *decisions, m_state_curr );
1404
0
    }
1405
0
  }
1406
0
}
1407
1408
void DepQuant::xDequantDQ( const TransformUnit& tu,  CoeffBuf& recCoeff, const ComponentID compID, const QpParam& cQP, bool enableScalingLists, int* piDequantCoef )
1409
0
{
1410
0
  m_quant.dequantBlock( tu, compID, cQP, recCoeff, enableScalingLists, piDequantCoef );
1411
0
}
1412
1413
0
DepQuant::DepQuant( const Quant* other, bool enc, bool useScalingLists ) : QuantRDOQ2( other, useScalingLists ), RateEstimator(), m_commonCtx()
1414
0
{
1415
0
  const DepQuant* dq = dynamic_cast<const DepQuant*>( other );
1416
0
  CHECK( other && !dq, "The DepQuant cast must be successfull!" );
1417
1418
0
  if( !dq )
1419
0
  {
1420
0
    m_scansRom = std::make_shared<DQIntern::Rom>();
1421
0
    m_scansRom->init();
1422
0
  }
1423
0
  else
1424
0
  {
1425
0
    m_scansRom = dq->m_scansRom;
1426
0
  }
1427
1428
0
  for( int t = 0; t < ( MAX_TB_SIZEY * MAX_TB_SIZEY ); t++ )
1429
0
  {
1430
0
    memcpy( m_trellis[t], startDec, sizeof( startDec ) );
1431
0
  }
1432
1433
0
  m_checkAllRdCosts     = DQIntern::checkAllRdCosts;
1434
0
  m_checkAllRdCostsOdd1 = DQIntern::checkAllRdCostsOdd1;
1435
0
  m_updateStatesEOS     = DQIntern::updateStatesEOS;
1436
0
  m_updateStates        = DQIntern::updateStates;
1437
0
  m_findFirstPos        = nullptr;
1438
1439
0
#if defined( TARGET_SIMD_X86 ) && ENABLE_SIMD_OPT_QUANT
1440
0
  initDepQuantX86();
1441
0
#endif
1442
0
}
1443
1444
DepQuant::~DepQuant()
1445
0
{
1446
0
}
1447
1448
void DepQuant::quant( TransformUnit& tu, const ComponentID compID, const CCoeffBuf& pSrc, TCoeff& uiAbsSum, const QpParam& cQP, const Ctx& ctx )
1449
0
{
1450
0
  if( tu.cs->picture->useSelectiveRdoq && !xNeedRDOQ( tu, compID, pSrc, cQP ) )
1451
0
  {
1452
0
    tu.lastPos[compID] = -1;
1453
0
    uiAbsSum           =  0;
1454
0
  }
1455
0
  else if( tu.cs->slice->depQuantEnabled && tu.mtsIdx[compID] != MTS_SKIP )
1456
0
  {
1457
    //===== scaling matrix ====
1458
0
    const int         qpDQ            = cQP.Qp(tu.mtsIdx[compID]==MTS_SKIP) + 1;
1459
0
    const int         qpPer           = qpDQ / 6;
1460
0
    const int         qpRem           = qpDQ - 6 * qpPer;
1461
0
    const CompArea    &rect           = tu.blocks[compID];
1462
0
    const int         width           = rect.width;
1463
0
    const int         height          = rect.height;
1464
0
    uint32_t          scalingListType = getScalingListType(tu.cu->predMode, compID);
1465
0
    CHECK(scalingListType >= SCALING_LIST_NUM, "Invalid scaling list");
1466
0
    const uint32_t    log2TrWidth     = Log2(width);
1467
0
    const uint32_t    log2TrHeight    = Log2(height);
1468
0
    const bool isLfnstApplied         = tu.cu->lfnstIdx > 0 && (CU::isSepTree(*tu.cu) ? true : isLuma(compID));
1469
0
    const bool enableScalingLists     = getUseScalingList(width, height, (tu.mtsIdx[compID] == MTS_SKIP), isLfnstApplied);
1470
0
    xQuantDQ( tu, pSrc, compID, cQP, Quant::m_dLambda, ctx, uiAbsSum, enableScalingLists, Quant::getQuantCoeff(scalingListType, qpRem, log2TrWidth, log2TrHeight) );
1471
0
  }
1472
0
  else
1473
0
  {
1474
0
    QuantRDOQ2::quant( tu, compID, pSrc, uiAbsSum, cQP, ctx );
1475
0
  }
1476
0
}
1477
1478
void DepQuant::dequant( const TransformUnit& tu, CoeffBuf& dstCoeff, const ComponentID compID, const QpParam& cQP )
1479
0
{
1480
0
  if( tu.cs->slice->depQuantEnabled && (tu.mtsIdx[compID] != MTS_SKIP) )
1481
0
  {
1482
0
    const int         qpDQ            = cQP.Qp(tu.mtsIdx[compID]==MTS_SKIP) + 1;
1483
0
    const int         qpPer           = qpDQ / 6;
1484
0
    const int         qpRem           = qpDQ - 6 * qpPer;
1485
0
    const CompArea    &rect           = tu.blocks[compID];
1486
0
    const int         width           = rect.width;
1487
0
    const int         height          = rect.height;
1488
0
    uint32_t          scalingListType = getScalingListType(tu.cu->predMode, compID);
1489
0
    CHECK(scalingListType >= SCALING_LIST_NUM, "Invalid scaling list");
1490
0
    const uint32_t    log2TrWidth    = Log2(width);
1491
0
    const uint32_t    log2TrHeight   = Log2(height);
1492
0
    const bool isLfnstApplied        = tu.cu->lfnstIdx > 0 && (CU::isSepTree(*tu.cu) ? true : isLuma(compID));
1493
0
    const bool enableScalingLists    = getUseScalingList(width, height, (tu.mtsIdx[compID] == MTS_SKIP), isLfnstApplied);
1494
0
    xDequantDQ( tu, dstCoeff, compID, cQP, enableScalingLists, Quant::getDequantCoeff(scalingListType, qpRem, log2TrWidth, log2TrHeight) );
1495
0
  }
1496
0
  else
1497
0
  {
1498
0
    QuantRDOQ::dequant( tu, dstCoeff, compID, cQP );
1499
0
  }
1500
0
}
1501
1502
void DepQuant::init( int rdoq, bool useRDOQTS, int thrVal )
1503
0
{
1504
0
  QuantRDOQ2::init( rdoq, useRDOQTS, thrVal );
1505
0
  m_quant.init( thrVal );
1506
0
}
1507
1508
} // namespace vvenc
1509
1510
//! \}
1511