Coverage Report

Created: 2026-10-17 06:56

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/work/vvdec/source/Lib/CommonLib/TrQuant.cpp
Line
Count
Source
1
/* -----------------------------------------------------------------------------
2
The copyright in this software is being made available under the Clear BSD
3
License, included below. No patent rights, trademark rights and/or 
4
other Intellectual Property Rights other than the copyrights concerning 
5
the Software are granted under this license.
6
7
The Clear BSD License
8
9
Copyright (c) 2018-2026, Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. & The VVdeC Authors.
10
All rights reserved.
11
12
Redistribution and use in source and binary forms, with or without modification,
13
are permitted (subject to the limitations in the disclaimer below) provided that
14
the following conditions are met:
15
16
     * Redistributions of source code must retain the above copyright notice,
17
     this list of conditions and the following disclaimer.
18
19
     * Redistributions in binary form must reproduce the above copyright
20
     notice, this list of conditions and the following disclaimer in the
21
     documentation and/or other materials provided with the distribution.
22
23
     * Neither the name of the copyright holder nor the names of its
24
     contributors may be used to endorse or promote products derived from this
25
     software without specific prior written permission.
26
27
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY
28
THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
29
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
31
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
32
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
33
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
34
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
35
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
36
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38
POSSIBILITY OF SUCH DAMAGE.
39
40
41
------------------------------------------------------------------------------------------- */
42
43
/** \file     TrQuant.cpp
44
    \brief    transform and quantization class
45
*/
46
47
#include "TrQuant.h"
48
#include "TrQuant_EMT.h"
49
50
#include "UnitTools.h"
51
#include "ContextModelling.h"
52
#include "CodingStructure.h"
53
#include "TimeProfiler.h"
54
#include "Quant.h"
55
#include "InterPrediction.h"
56
57
58
#include "dtrace_buffer.h"
59
60
#include <stdlib.h>
61
#include <limits>
62
#include <memory.h>
63
64
#include "Quant.h"
65
66
namespace vvdec
67
{
68
69
InvTrans *fastInvTrans[NUM_TRANS_TYPE][g_numTransformMatrixSizes] =
70
{
71
  { fastInverseDCT2_B2, fastInverseDCT2_B4, fastInverseDCT2_B8, fastInverseDCT2_B16, fastInverseDCT2_B32, fastInverseDCT2_B64 },
72
  { nullptr,            fastInverseDCT8_B4, fastInverseDCT8_B8, fastInverseDCT8_B16, fastInverseDCT8_B32, nullptr },
73
  { nullptr,            fastInverseDST7_B4, fastInverseDST7_B8, fastInverseDST7_B16, fastInverseDST7_B32, nullptr },
74
};
75
76
//! \ingroup CommonLib
77
//! \{
78
79
static void invLfnstNxNCore( int* src, int* dst, const uint32_t mode, const uint32_t index, const uint32_t size, int zeroOutSize )
80
0
{
81
0
  int             maxLog2TrDynamicRange =  15;
82
0
  const TCoeff    outputMinimum         = -( 1 << maxLog2TrDynamicRange );
83
0
  const TCoeff    outputMaximum         =  ( 1 << maxLog2TrDynamicRange ) - 1;
84
0
  const int8_t*   trMat                 =  ( size > 4 ) ? g_lfnst8x8[ mode ][ index ][ 0 ] : g_lfnst4x4[ mode ][ index ][ 0 ];
85
0
  const int       trSize                =  ( size > 4 ) ? 48 : 16;
86
0
  int             resi;
87
0
  int*            out                   =  dst;
88
89
0
  CHECK( index > 2, "wrong" );
90
91
0
  for( int j = 0; j < trSize; j++, trMat += 16 )
92
0
  {
93
0
    resi = 0;
94
0
    const int8_t* trMatTmp = trMat;
95
0
    int*          srcPtr   = src;
96
97
0
    for( int i = 0; i < zeroOutSize; i++ )
98
0
    {
99
0
      resi += *srcPtr++ * *trMatTmp++;
100
0
    }
101
102
0
    *out++ = Clip3( outputMinimum, outputMaximum, ( int ) ( resi + 64 ) >> 7 );
103
0
  }
104
0
}
105
106
0
static inline int64_t square( const int d ) { return d * (int64_t)d; }
107
108
template<int signedMode> void invTransformCbCr( PelBuf &resCb, PelBuf &resCr )
109
0
{
110
0
  Pel*  cb  = resCb.buf;
111
0
  Pel*  cr  = resCr.buf;
112
0
  for( SizeType y = 0; y < resCb.height; y++, cb += resCb.stride, cr += resCr.stride )
113
0
  {
114
0
    for( SizeType x = 0; x < resCb.width; x++ )
115
0
    {
116
0
      if      ( signedMode ==  1 )  { cr[x] =  cb[x] >> 1;  }
117
0
      else if ( signedMode == -1 )  { cr[x] = -cb[x] >> 1;  }
118
0
      else if ( signedMode ==  2 )  { cr[x] =  cb[x]; }
119
0
      else if ( signedMode == -2 )  { cr[x] = -cb[x]; }
120
0
      else if ( signedMode ==  3 )  { cb[x] =  cr[x] >> 1; }
121
0
      else if ( signedMode == -3 )  { cb[x] = -cr[x] >> 1; }
122
0
    }
123
0
  }
124
0
}
Unexecuted instantiation: void vvdec::invTransformCbCr<0>(vvdec::AreaBuf<short>&, vvdec::AreaBuf<short>&)
Unexecuted instantiation: void vvdec::invTransformCbCr<1>(vvdec::AreaBuf<short>&, vvdec::AreaBuf<short>&)
Unexecuted instantiation: void vvdec::invTransformCbCr<-1>(vvdec::AreaBuf<short>&, vvdec::AreaBuf<short>&)
Unexecuted instantiation: void vvdec::invTransformCbCr<2>(vvdec::AreaBuf<short>&, vvdec::AreaBuf<short>&)
Unexecuted instantiation: void vvdec::invTransformCbCr<-2>(vvdec::AreaBuf<short>&, vvdec::AreaBuf<short>&)
Unexecuted instantiation: void vvdec::invTransformCbCr<3>(vvdec::AreaBuf<short>&, vvdec::AreaBuf<short>&)
Unexecuted instantiation: void vvdec::invTransformCbCr<-3>(vvdec::AreaBuf<short>&, vvdec::AreaBuf<short>&)
125
126
// ====================================================================================================================
127
// TrQuant class member functions
128
// ====================================================================================================================
129
130
12.0k
TrQuant::TrQuant( class InterPrediction* ip, const TrQuant* other, bool enableOpt ) : Quant( other, enableOpt )
131
12.0k
{
132
  // allocate temporary buffers
133
12.0k
  m_invICT      = m_invICTMem + maxAbsIctMode;
134
12.0k
  m_invICT[ 0]  = invTransformCbCr< 0>;
135
12.0k
  m_invICT[ 1]  = invTransformCbCr< 1>;
136
12.0k
  m_invICT[-1]  = invTransformCbCr<-1>;
137
12.0k
  m_invICT[ 2]  = invTransformCbCr< 2>;
138
12.0k
  m_invICT[-2]  = invTransformCbCr<-2>;
139
12.0k
  m_invICT[ 3]  = invTransformCbCr< 3>;
140
12.0k
  m_invICT[-3]  = invTransformCbCr<-3>;
141
142
12.0k
  m_invLfnstNxN = invLfnstNxNCore;
143
144
12.0k
  static_assert( sizeof( ip->m_acYuvPred[0] ) > sizeof( TCoeff ) * ( MAX_TU_SIZE_FOR_PROFILE * MAX_TU_SIZE_FOR_PROFILE + MEMORY_ALIGN_DEF_SIZE ), "Buffer to small to be reused!" );
145
12.0k
  static_assert( sizeof( ip->m_acYuvPred[1] ) > sizeof( TCoeff ) * ( MAX_TU_SIZE_FOR_PROFILE * MAX_TU_SIZE_FOR_PROFILE + MEMORY_ALIGN_DEF_SIZE ), "Buffer to small to be reused!" );
146
12.0k
  static_assert( sizeof( ip->m_acYuvPred[2] ) > sizeof( TCoeff ) * ( MAX_TU_SIZE_FOR_PROFILE * MAX_TU_SIZE_FOR_PROFILE + MEMORY_ALIGN_DEF_SIZE ), "Buffer to small to be reused!" );
147
148
12.0k
  char* tmp  = ( char* ) ip->m_acYuvPred[0];
149
12.0k
  char* blk  = ( char* ) ip->m_acYuvPred[1];
150
12.0k
  char* dqnt = ( char* ) ip->m_acYuvPred[2];
151
152
12.0k
  m_tmp  = ( TCoeff* ) ( ( ptrdiff_t ) tmp  + ( MEMORY_ALIGN_DEF_SIZE - ( ( ptrdiff_t ) tmp  & ( MEMORY_ALIGN_DEF_SIZE - 1 ) ) ) );
153
12.0k
  m_blk  = ( TCoeff* ) ( ( ptrdiff_t ) blk  + ( MEMORY_ALIGN_DEF_SIZE - ( ( ptrdiff_t ) blk  & ( MEMORY_ALIGN_DEF_SIZE - 1 ) ) ) );
154
12.0k
  m_dqnt = ( TCoeff* ) ( ( ptrdiff_t ) dqnt + ( MEMORY_ALIGN_DEF_SIZE - ( ( ptrdiff_t ) dqnt & ( MEMORY_ALIGN_DEF_SIZE - 1 ) ) ) );
155
156
12.0k
  if( enableOpt )
157
12.0k
  {
158
#if defined( TARGET_SIMD_X86 ) && ENABLE_SIMD_TCOEFF_OPS
159
    initTrQuantX86();
160
#endif
161
#if defined( TARGET_SIMD_ARM ) && ENABLE_SIMD_TCOEFF_OPS
162
    initTrQuantARM();
163
#endif
164
12.0k
  }
165
12.0k
}
166
167
void TrQuant::invLfnstNxN( int* src, int* dst, const uint32_t mode, const uint32_t index, const uint32_t size, int zeroOutSize )
168
0
{
169
0
  m_invLfnstNxN( src, dst, mode, index, size, zeroOutSize );
170
0
}
171
172
void TrQuant::xDeQuant(const TransformUnit &tu,
173
                             CoeffBuf      &dstCoeff,
174
                       const ComponentID   &compID,
175
                       const QpParam       &cQP)
176
0
{
177
0
  PROFILER_SCOPE_AND_STAGE_EXT( 1, g_timeProfiler, P_PARSERESIDUALS, *tu.cu->cs, compID );
178
0
  dequant( tu, dstCoeff, compID, cQP );
179
0
}
180
181
void TrQuant::init( const Picture *pic )
182
0
{
183
0
  Quant::init( pic );
184
0
}
185
186
uint32_t TrQuant::getLFNSTIntraMode( int wideAngPredMode )
187
0
{
188
0
  uint32_t intraMode;
189
190
0
  if( wideAngPredMode < 0 )
191
0
  {
192
0
    intraMode = ( uint32_t ) ( wideAngPredMode + ( NUM_EXT_LUMA_MODE >> 1 ) + NUM_LUMA_MODE );
193
0
  }
194
0
  else if( wideAngPredMode >= NUM_LUMA_MODE )
195
0
  {
196
0
    intraMode = ( uint32_t ) ( wideAngPredMode + ( NUM_EXT_LUMA_MODE >> 1 ) );
197
0
  }
198
0
  else
199
0
  {
200
0
    intraMode = ( uint32_t ) wideAngPredMode;
201
0
  }
202
203
0
  return intraMode;
204
0
}
205
206
bool TrQuant::getTransposeFlag( uint32_t intraMode )
207
0
{
208
0
  return ( ( intraMode >= NUM_LUMA_MODE ) && ( intraMode >= ( NUM_LUMA_MODE + ( NUM_EXT_LUMA_MODE >> 1 ) ) ) ) ||
209
0
         ( ( intraMode <  NUM_LUMA_MODE ) && ( intraMode >  DIA_IDX ) );
210
0
}
211
212
void TrQuant::xInvLfnst( TransformUnit &tu, const ComponentID& compID )
213
0
{
214
0
  const CompArea& area     = tu.blocks[ compID ];
215
0
  const uint32_t  width    = area.width;
216
0
  const uint32_t  height   = area.height;
217
0
  const uint32_t  lfnstIdx = tu.cu->lfnstIdx();
218
219
0
  if( lfnstIdx && tu.mtsIdx( compID ) != MTS_SKIP && ( CU::isSepTree( *tu.cu ) ? true : isLuma( compID ) ) )
220
0
  {
221
0
    const bool whge3     = width >= 8 && height >= 8;
222
0
    const uint16_t* scan = whge3 ? g_coefTopLeftDiagScan8x8[ g_sizeIdxInfo.idxFrom( width ) ] : g_scanOrder[ SCAN_GROUPED_4x4 ][ g_sizeIdxInfo.idxFrom( width ) ][ g_sizeIdxInfo.idxFrom( height ) ];
223
0
    uint32_t intraMode   = 0;
224
225
0
    if( CU::isMIP( *tu.cu, toChannelType( compID ) ) )
226
0
    {
227
0
      intraMode = PLANAR_IDX;
228
0
    }
229
0
    else
230
0
    {
231
0
      intraMode = PU::isLMCMode( tu.cu->intraDir[toChannelType( compID )] ) ? PU::getCoLocatedIntraLumaMode( *tu.cu ) : PU::getFinalIntraMode( *tu.cu, toChannelType( compID ) );
232
0
    }
233
234
0
    CHECKD( intraMode > NUM_INTRA_MODE, "Invalid intra mode" );
235
0
    CHECKD( lfnstIdx >= 3, "Invalid LFNST index" );
236
237
0
    intraMode                     = getLFNSTIntraMode( PU::getWideAngIntraMode( tu, intraMode, compID ) );
238
0
    bool          transposeFlag   = getTransposeFlag( intraMode );
239
0
    const int     sbSize          = whge3 ? 8 : 4;
240
0
    bool          tu4x4Flag       = ( width == 4 && height == 4 );
241
0
    bool          tu8x8Flag       = ( width == 8 && height == 8 );
242
0
    TCoeff*       lfnstTemp;
243
0
    TCoeff*       coeffTemp;
244
0
    int y;
245
0
    lfnstTemp = m_tempInMatrix; // inverse spectral rearrangement
246
0
    coeffTemp = m_dqnt;
247
0
    TCoeff * dst = lfnstTemp;
248
0
    for( y = 0; y < 16; y++ )
249
0
    {
250
0
      *dst++ = coeffTemp[ scan[y] ];
251
0
    }
252
253
0
    m_invLfnstNxN( m_tempInMatrix, m_tempOutMatrix, g_lfnstLut[ intraMode ], lfnstIdx - 1, sbSize, ( tu4x4Flag || tu8x8Flag ) ? 8 : 16 );
254
255
0
    lfnstTemp = m_tempOutMatrix; // inverse spectral rearrangement
256
257
0
    if( transposeFlag )
258
0
    {
259
0
      if( sbSize == 4 )
260
0
      {
261
0
        for( y = 0; y < 4; y++ )
262
0
        {
263
0
          coeffTemp[ 0 ] = lfnstTemp[ 0 ];  coeffTemp[ 1 ] = lfnstTemp[  4 ];
264
0
          coeffTemp[ 2 ] = lfnstTemp[ 8 ];  coeffTemp[ 3 ] = lfnstTemp[ 12 ];
265
0
          lfnstTemp++;
266
0
          coeffTemp += width;
267
0
        }
268
0
      }
269
0
      else // ( sbSize == 8 )
270
0
      {
271
0
        for( y = 0; y < 8; y++ )
272
0
        {
273
0
          coeffTemp[ 0 ] = lfnstTemp[  0 ];  coeffTemp[ 1 ] = lfnstTemp[  8 ];
274
0
          coeffTemp[ 2 ] = lfnstTemp[ 16 ];  coeffTemp[ 3 ] = lfnstTemp[ 24 ];
275
0
          if( y < 4 )
276
0
          {
277
0
            coeffTemp[ 4 ] = lfnstTemp[ 32 ];  coeffTemp[ 5 ] = lfnstTemp[ 36 ];
278
0
            coeffTemp[ 6 ] = lfnstTemp[ 40 ];  coeffTemp[ 7 ] = lfnstTemp[ 44 ];
279
0
          }
280
0
          lfnstTemp++;
281
0
          coeffTemp += width;
282
0
        }
283
0
      }
284
0
    }
285
0
    else
286
0
    {
287
0
      for( y = 0; y < sbSize; y++ )
288
0
      {
289
0
        uint32_t uiStride = ( y < 4 ) ? sbSize : 4;
290
0
        ::memcpy( coeffTemp, lfnstTemp, uiStride * sizeof( TCoeff ) );
291
0
        lfnstTemp += uiStride;
292
0
        coeffTemp += width;
293
0
      }
294
0
    }
295
296
0
    tu.maxScanPosX[compID] = std::max<int>( tu.maxScanPosX[compID], std::min<int>( width  - 1, 7 ) );
297
0
    tu.maxScanPosY[compID] = std::max<int>( tu.maxScanPosY[compID], std::min<int>( height - 1, 7 ) );
298
0
  }
299
0
}
300
301
void TrQuant::invTransformNxN( TransformUnit &tu, const ComponentID &compID, PelBuf &pResi, const QpParam &cQP )
302
0
{
303
0
  CompArea &area    = tu.blocks[compID];
304
0
  uint32_t uiWidth  = area.width;
305
0
  uint32_t uiHeight = area.height;
306
307
0
  CoeffBuf coeff( m_dqnt, uiWidth, uiHeight );
308
0
  coeff.memset( 0 );
309
310
0
  xDeQuant( tu, coeff, compID, cQP );
311
312
0
  DTRACE_COEFF_BUF( D_TCOEFF, coeff, tu, tu.cu->predMode(), compID );
313
314
0
  if( tu.cu->sps->getUseLFNST() )
315
0
  {
316
0
    xInvLfnst( tu, compID );
317
0
  }
318
319
0
  if( tu.mtsIdx( compID )== 1 )
320
0
  {
321
0
    xITransformSkip( coeff, pResi, tu, compID );
322
0
  }
323
0
  else
324
0
  {
325
0
    xIT( tu, compID, coeff, pResi );
326
0
  }
327
328
0
  DTRACE_PEL_BUF( D_RESIDUALS, pResi, tu, tu.cu->predMode(), compID);
329
0
}
330
331
void TrQuant::invTransformICT( const TransformUnit &tu, PelBuf &resCb, PelBuf &resCr )
332
0
{
333
0
  CHECKD( Size(resCb) != Size(resCr), "resCb and resCr have different sizes" );
334
0
  ( *m_invICT[TU::getICTMode( tu, tu.cu->cs->picHeader->getJointCbCrSignFlag() )] )( resCb, resCr );
335
0
}
336
337
// ------------------------------------------------------------------------------------------------
338
// Logical transform
339
// ------------------------------------------------------------------------------------------------
340
341
void TrQuant::getTrTypes( const TransformUnit& tu, const ComponentID compID, int &trTypeHor, int &trTypeVer )
342
0
{
343
0
  const bool isCuIntra     = CU::isIntra( *tu.cu );
344
0
  const bool isCompLuma    = isLuma( compID );
345
0
  const bool isImplicitMTS = isCuIntra && isCompLuma && tu.cu->sps->getUseImplicitMTS() && tu.cu->lfnstIdx() == 0 && tu.cu->mipFlag() == 0;
346
0
  const bool isISP         = isCuIntra && isCompLuma && tu.cu->ispMode();
347
348
0
  if( isISP && tu.cu->lfnstIdx() )
349
0
  {
350
0
    return;
351
0
  }
352
353
0
  const int lwidth  = tu.lwidth();
354
0
  const int lheight = tu.lheight();
355
356
0
  if( !tu.cu->sps->getUseMTS() )
357
0
    return;
358
359
0
  if( isImplicitMTS || isISP )
360
0
  {
361
0
    bool widthDstOk   = lwidth  >= 4 && lwidth  <= 16;
362
0
    bool heightDstOk  = lheight >= 4 && lheight <= 16;
363
364
0
    if( widthDstOk )
365
0
      trTypeHor = DST7;
366
0
    if( heightDstOk )
367
0
      trTypeVer = DST7;
368
369
0
    return;
370
0
  }
371
372
0
  const bool isCuInter     = CU::isInter( *tu.cu ) && isCompLuma;
373
0
  const bool isExplicitMTS = isCuIntra ? tu.cu->sps->getUseIntraMTS() && isCompLuma : tu.cu->sps->getUseInterMTS() && isCuInter;
374
0
  const bool isSBT         = isCuInter && tu.cu->sbtInfo();
375
376
0
  if( isSBT )
377
0
  {
378
0
    const uint8_t sbtIdx = CU::getSbtIdx( *tu.cu );
379
0
    const uint8_t sbtPos = CU::getSbtPos( *tu.cu );
380
381
0
    if( sbtIdx == SBT_VER_HALF || sbtIdx == SBT_VER_QUAD )
382
0
    {
383
0
      CHECK( lwidth > MTS_INTER_MAX_CU_SIZE, "wrong" );
384
0
      if( lheight > MTS_INTER_MAX_CU_SIZE )
385
0
      {
386
0
        trTypeHor = trTypeVer = DCT2;
387
0
      }
388
0
      else
389
0
      {
390
0
        if( sbtPos == SBT_POS0 )  { trTypeHor = DCT8;  trTypeVer = DST7; }
391
0
        else                      { trTypeHor = DST7;  trTypeVer = DST7; }
392
0
      }
393
0
    }
394
0
    else
395
0
    {
396
0
      CHECK( lheight > MTS_INTER_MAX_CU_SIZE, "wrong" );
397
0
      if( lwidth > MTS_INTER_MAX_CU_SIZE )
398
0
      {
399
0
        trTypeHor = trTypeVer = DCT2;
400
0
      }
401
0
      else
402
0
      {
403
0
        if( sbtPos == SBT_POS0 )  { trTypeHor = DST7;  trTypeVer = DCT8; }
404
0
        else                      { trTypeHor = DST7;  trTypeVer = DST7; }
405
0
      }
406
0
    }
407
0
    return;
408
0
  }
409
0
  else if( isExplicitMTS )
410
0
  {
411
0
    if (tu.mtsIdx( compID ) > MTS_SKIP)
412
0
    {
413
0
      int indHor = (tu.mtsIdx( compID ) - MTS_DST7_DST7) & 1;
414
0
      int indVer = (tu.mtsIdx( compID ) - MTS_DST7_DST7) >> 1;
415
0
      trTypeHor = indHor ? DCT8 : DST7;
416
0
      trTypeVer = indVer ? DCT8 : DST7;
417
0
    }
418
0
  }
419
0
}
420
421
void TrQuant::xIT( const TransformUnit &tu, const ComponentID &compID, const CCoeffBuf &pCoeff, PelBuf &pResidual )
422
0
{
423
0
  const int      width                  = pCoeff.width;
424
0
  const int      height                 = pCoeff.height;
425
0
  const unsigned maxLog2TrDynamicRange  = tu.cu->sps->getMaxLog2TrDynamicRange( toChannelType( compID ) );
426
0
  const unsigned bitDepth               = tu.cu->sps->getBitDepth();
427
0
  const int      TRANSFORM_MATRIX_SHIFT = g_transformMatrixShift;
428
0
  const TCoeff   clipMinimum            = -( 1 << maxLog2TrDynamicRange );
429
0
  const TCoeff   clipMaximum            =  ( 1 << maxLog2TrDynamicRange ) - 1;
430
0
  const uint32_t transformWidthIndex    = getLog2(width ) - 1;                                // nLog2WidthMinus1, since transform start from 2-point
431
0
  const uint32_t transformHeightIndex   = getLog2(height) - 1;                                // nLog2HeightMinus1, since transform start from 2-point
432
433
0
  int trTypeHor = DCT2;
434
0
  int trTypeVer = DCT2;
435
436
0
  getTrTypes( tu, compID, trTypeHor, trTypeVer );
437
438
0
  if( tu.maxScanPosX[compID] == 0 && tu.maxScanPosY[compID] == 0 && trTypeHor == DCT2 && trTypeVer == DCT2 )
439
0
  {
440
0
    int dcVal = 0;
441
442
0
    if( width > 1 && height > 1 )
443
0
    {
444
0
      const int shift_1st = TRANSFORM_MATRIX_SHIFT + 1 + COM16_C806_TRANS_PREC;
445
0
      const int shift_2nd = ( TRANSFORM_MATRIX_SHIFT + maxLog2TrDynamicRange - 1 ) - bitDepth + COM16_C806_TRANS_PREC;
446
447
0
      dcVal = ( ( pCoeff.buf[0] * ( 1 << TRANSFORM_MATRIX_SHIFT ) ) + ( 1 << ( shift_1st - 1 ) ) ) >> shift_1st;
448
0
      dcVal = ( ( dcVal * ( 1 << TRANSFORM_MATRIX_SHIFT ) ) + ( 1 << ( shift_2nd - 1 ) ) ) >> shift_2nd;
449
0
    }
450
0
    else
451
0
    {
452
0
      const int shift = ( TRANSFORM_MATRIX_SHIFT + maxLog2TrDynamicRange ) - bitDepth + COM16_C806_TRANS_PREC;
453
0
      dcVal = ( ( pCoeff.buf[0] * ( 1 << TRANSFORM_MATRIX_SHIFT ) ) + ( 1 << ( shift - 1 ) ) ) >> shift;
454
0
    }
455
456
0
    pResidual.fill( dcVal );
457
0
    return;
458
0
  }
459
460
0
  const int skipWidth  = std::max<int>( ( trTypeHor != DCT2 && width  == 32 ) ? 16 : width  > JVET_C0024_ZERO_OUT_TH ? width  - JVET_C0024_ZERO_OUT_TH : 0, width  - tu.maxScanPosX[compID] - 1 );
461
0
  const int skipHeight = std::max<int>( ( trTypeVer != DCT2 && height == 32 ) ? 16 : height > JVET_C0024_ZERO_OUT_TH ? height - JVET_C0024_ZERO_OUT_TH : 0, height - tu.maxScanPosY[compID] - 1 );
462
463
0
  TCoeff *block = m_blk;
464
0
  int shiftlast;
465
466
0
  if( width > 1 && height > 1 ) //2-D transform
467
0
  {
468
0
    const int      shift_1st              =   TRANSFORM_MATRIX_SHIFT + 1 + COM16_C806_TRANS_PREC; // 1 has been added to shift_1st at the expense of shift_2nd
469
0
    const int      shift_2nd              = ( TRANSFORM_MATRIX_SHIFT + maxLog2TrDynamicRange - 1 ) - bitDepth + COM16_C806_TRANS_PREC;
470
0
    CHECK( shift_1st < 0, "Negative shift" );
471
0
    CHECK( shift_2nd < 0, "Negative shift" );
472
0
    TCoeff *tmp   = m_tmp;
473
0
    fastInvTrans[trTypeVer][transformHeightIndex](pCoeff.buf, tmp, shift_1st, width, skipWidth, skipHeight, true,  clipMinimum, clipMaximum);
474
0
    fastInvTrans[trTypeHor][transformWidthIndex] (tmp,      block, shift_2nd, height,         0, skipWidth, false, clipMinimum, clipMaximum);
475
0
    shiftlast = shift_2nd;
476
0
  }
477
0
  else if( width == 1 ) //1-D vertical transform
478
0
  {
479
0
    int shift = ( TRANSFORM_MATRIX_SHIFT + maxLog2TrDynamicRange - 1 ) - bitDepth + COM16_C806_TRANS_PREC;
480
0
    CHECK( shift < 0, "Negative shift" );
481
0
    CHECK( ( transformHeightIndex < 0 ), "There is a problem with the height." );
482
0
    fastInvTrans[trTypeVer][transformHeightIndex]( pCoeff.buf, block, shift + 1, 1, 0, skipHeight, false, clipMinimum, clipMaximum );
483
0
    shiftlast = shift + 1;
484
0
  }
485
0
  else //if(iHeight == 1) //1-D horizontal transform
486
0
  {
487
0
    const int      shift              = ( TRANSFORM_MATRIX_SHIFT + maxLog2TrDynamicRange - 1 ) - bitDepth + COM16_C806_TRANS_PREC;
488
0
    CHECK( shift < 0, "Negative shift" );
489
0
    CHECK( ( transformWidthIndex < 0 ), "There is a problem with the width." );
490
0
    fastInvTrans[trTypeHor][transformWidthIndex]( pCoeff.buf, block, shift + 1, 1, 0, skipWidth, false, clipMinimum, clipMaximum );
491
0
    shiftlast = shift + 1;
492
0
  }
493
494
0
  int round = 1 << ( shiftlast - 1 );
495
0
  g_tCoeffOps.cpyResiClip[getLog2( width )]( block, pResidual.buf, pResidual.stride, width, height, clipMinimum, clipMaximum, round, shiftlast );
496
0
}
497
498
/** Wrapper function between HM interface and core NxN transform skipping
499
 */
500
void TrQuant::xITransformSkip(const CCoeffBuf     &pCoeff,
501
                                    PelBuf        &pResidual,
502
                              const TransformUnit &tu,
503
                              const ComponentID   &compID)
504
0
{
505
0
  const CompArea &area  = tu.blocks[compID];
506
0
  const int width       = area.width;
507
0
  const int height      = area.height;
508
  
509
0
  for( int y = 0; y < height; y++ )
510
0
  {
511
0
    for( int x = 0; x < width; x++ )
512
0
    {
513
0
      pResidual.at( x, y ) = Pel( pCoeff.at( x, y ) );
514
0
    }
515
0
  }
516
0
}
517
518
}