Coverage Report

Created: 2026-10-28 06:18

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/work/vvenc/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) 2019-2026, Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. & The VVenC Authors.
10
All rights reserved.
11
12
Redistribution and use in source and binary forms, with or without modification,
13
are permitted (subject to the limitations in the disclaimer below) provided that
14
the following conditions are met:
15
16
     * Redistributions of source code must retain the above copyright notice,
17
     this list of conditions and the following disclaimer.
18
19
     * Redistributions in binary form must reproduce the above copyright
20
     notice, this list of conditions and the following disclaimer in the
21
     documentation and/or other materials provided with the distribution.
22
23
     * Neither the name of the copyright holder nor the names of its
24
     contributors may be used to endorse or promote products derived from this
25
     software without specific prior written permission.
26
27
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY
28
THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
29
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
31
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
32
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
33
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
34
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
35
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
36
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38
POSSIBILITY OF SUCH DAMAGE.
39
40
41
------------------------------------------------------------------------------------------- */
42
43
44
/** \file     TrQuant.cpp
45
    \brief    transform and quantization class
46
*/
47
48
#include "TrQuant.h"
49
#include "TrQuant_EMT.h"
50
#include "QuantRDOQ.h"
51
#include "DepQuant.h"
52
#include "UnitTools.h"
53
#include "ContextModelling.h"
54
#include "CodingStructure.h"
55
#include "dtrace_buffer.h"
56
#include "TimeProfiler.h"
57
#include "SearchSpaceCounter.h"
58
59
#include <stdlib.h>
60
#include <memory.h>
61
62
//! \ingroup CommonLib
63
//! \{
64
65
namespace vvenc {
66
67
struct coeffGroupRDStats
68
{
69
  int    iNNZbeforePos0;
70
  double d64CodedLevelandDist; // distortion and level cost only
71
  double d64UncodedDist;    // all zero coded block distortion
72
  double d64SigCost;
73
  double d64SigCost_0;
74
};
75
76
FwdTrans *const fastFwdTrans[NUM_TRANS_TYPE][g_numTransformMatrixSizes] =
77
{
78
  { fastForwardDCT2_B2, fastForwardDCT2_B4, fastForwardDCT2_B8, fastForwardDCT2_B16, fastForwardDCT2_B32, fastForwardDCT2_B64 },
79
  { nullptr,            fastForwardDCT8_B4, fastForwardDCT8_B8, fastForwardDCT8_B16, fastForwardDCT8_B32, nullptr },
80
  { nullptr,            fastForwardDST7_B4, fastForwardDST7_B8, fastForwardDST7_B16, fastForwardDST7_B32, nullptr },
81
};
82
83
InvTrans *const fastInvTrans[NUM_TRANS_TYPE][g_numTransformMatrixSizes] =
84
{
85
  { fastInverseDCT2_B2, fastInverseDCT2_B4, fastInverseDCT2_B8, fastInverseDCT2_B16, fastInverseDCT2_B32, fastInverseDCT2_B64 },
86
  { nullptr,            fastInverseDCT8_B4, fastInverseDCT8_B8, fastInverseDCT8_B16, fastInverseDCT8_B32, nullptr },
87
  { nullptr,            fastInverseDST7_B4, fastInverseDST7_B8, fastInverseDST7_B16, fastInverseDST7_B32, nullptr },
88
};
89
90
//! \ingroup CommonLib
91
//! \{
92
93
461M
static inline int64_t square( const int d ) { return d * (int64_t)d; }
94
95
template<int signedMode> std::pair<int64_t,int64_t> fwdTransformCbCr( const PelBuf& resCb, const PelBuf& resCr, PelBuf& resC1, PelBuf& resC2 )
96
1.33M
{
97
1.33M
  const Pel*  cb  = resCb.buf;
98
1.33M
  const Pel*  cr  = resCr.buf;
99
1.33M
  Pel*        c1  = resC1.buf;
100
1.33M
  Pel*        c2  = resC2.buf;
101
1.33M
  int64_t     d1  = 0;
102
1.33M
  int64_t     d2  = 0;
103
18.2M
  for( SizeType y = 0; y < resCb.height; y++, cb += resCb.stride, cr += resCr.stride, c1 += resC1.stride, c2 += resC2.stride )
104
16.8M
  {
105
247M
    for( SizeType x = 0; x < resCb.width; x++ )
106
230M
    {
107
230M
      int cbx = cb[x], crx = cr[x];
108
230M
      if      ( signedMode ==  1 )
109
57.6M
      {
110
57.6M
        c1[x] = Pel( ( 4*cbx + 2*crx ) / 5 );
111
57.6M
        d1   += square( cbx - c1[x] ) + square( crx - (c1[x]>>1) );
112
57.6M
      }
113
173M
      else if ( signedMode == -1 )
114
0
      {
115
0
        c1[x] = Pel( ( 4*cbx - 2*crx ) / 5 );
116
0
        d1   += square( cbx - c1[x] ) + square( crx - (-c1[x]>>1) );
117
0
      }
118
173M
      else if ( signedMode ==  2 )
119
57.6M
      {
120
57.6M
        c1[x] = Pel( ( cbx + crx ) / 2 );
121
57.6M
        d1   += square( cbx - c1[x] ) + square( crx - c1[x] );
122
57.6M
      }
123
115M
      else if ( signedMode == -2 )
124
0
      {
125
0
        c1[x] = Pel( ( cbx - crx ) / 2 );
126
0
        d1   += square( cbx - c1[x] ) + square( crx + c1[x] );
127
0
      }
128
115M
      else if ( signedMode ==  3 )
129
57.6M
      {
130
57.6M
        c2[x] = Pel( ( 4*crx + 2*cbx ) / 5 );
131
57.6M
        d1   += square( cbx - (c2[x]>>1) ) + square( crx - c2[x] );
132
57.6M
      }
133
57.6M
      else if ( signedMode == -3 )
134
0
      {
135
0
        c2[x] = Pel( ( 4*crx - 2*cbx ) / 5 );
136
0
        d1   += square( cbx - (-c2[x]>>1) ) + square( crx - c2[x] );
137
0
      }
138
57.6M
      else
139
57.6M
      {
140
57.6M
        d1   += square( cbx );
141
57.6M
        d2   += square( crx );
142
57.6M
      }
143
230M
    }
144
16.8M
  }
145
1.33M
  return std::make_pair(d1,d2);
146
1.33M
}
std::__1::pair<long, long> vvenc::fwdTransformCbCr<0>(vvenc::AreaBuf<short> const&, vvenc::AreaBuf<short> const&, vvenc::AreaBuf<short>&, vvenc::AreaBuf<short>&)
Line
Count
Source
96
334k
{
97
334k
  const Pel*  cb  = resCb.buf;
98
334k
  const Pel*  cr  = resCr.buf;
99
334k
  Pel*        c1  = resC1.buf;
100
334k
  Pel*        c2  = resC2.buf;
101
334k
  int64_t     d1  = 0;
102
334k
  int64_t     d2  = 0;
103
4.55M
  for( SizeType y = 0; y < resCb.height; y++, cb += resCb.stride, cr += resCr.stride, c1 += resC1.stride, c2 += resC2.stride )
104
4.22M
  {
105
61.9M
    for( SizeType x = 0; x < resCb.width; x++ )
106
57.6M
    {
107
57.6M
      int cbx = cb[x], crx = cr[x];
108
57.6M
      if      ( signedMode ==  1 )
109
0
      {
110
0
        c1[x] = Pel( ( 4*cbx + 2*crx ) / 5 );
111
0
        d1   += square( cbx - c1[x] ) + square( crx - (c1[x]>>1) );
112
0
      }
113
57.6M
      else if ( signedMode == -1 )
114
0
      {
115
0
        c1[x] = Pel( ( 4*cbx - 2*crx ) / 5 );
116
0
        d1   += square( cbx - c1[x] ) + square( crx - (-c1[x]>>1) );
117
0
      }
118
57.6M
      else if ( signedMode ==  2 )
119
0
      {
120
0
        c1[x] = Pel( ( cbx + crx ) / 2 );
121
0
        d1   += square( cbx - c1[x] ) + square( crx - c1[x] );
122
0
      }
123
57.6M
      else if ( signedMode == -2 )
124
0
      {
125
0
        c1[x] = Pel( ( cbx - crx ) / 2 );
126
0
        d1   += square( cbx - c1[x] ) + square( crx + c1[x] );
127
0
      }
128
57.6M
      else if ( signedMode ==  3 )
129
0
      {
130
0
        c2[x] = Pel( ( 4*crx + 2*cbx ) / 5 );
131
0
        d1   += square( cbx - (c2[x]>>1) ) + square( crx - c2[x] );
132
0
      }
133
57.6M
      else if ( signedMode == -3 )
134
0
      {
135
0
        c2[x] = Pel( ( 4*crx - 2*cbx ) / 5 );
136
0
        d1   += square( cbx - (-c2[x]>>1) ) + square( crx - c2[x] );
137
0
      }
138
57.6M
      else
139
57.6M
      {
140
57.6M
        d1   += square( cbx );
141
57.6M
        d2   += square( crx );
142
57.6M
      }
143
57.6M
    }
144
4.22M
  }
145
334k
  return std::make_pair(d1,d2);
146
334k
}
std::__1::pair<long, long> vvenc::fwdTransformCbCr<1>(vvenc::AreaBuf<short> const&, vvenc::AreaBuf<short> const&, vvenc::AreaBuf<short>&, vvenc::AreaBuf<short>&)
Line
Count
Source
96
334k
{
97
334k
  const Pel*  cb  = resCb.buf;
98
334k
  const Pel*  cr  = resCr.buf;
99
334k
  Pel*        c1  = resC1.buf;
100
334k
  Pel*        c2  = resC2.buf;
101
334k
  int64_t     d1  = 0;
102
334k
  int64_t     d2  = 0;
103
4.55M
  for( SizeType y = 0; y < resCb.height; y++, cb += resCb.stride, cr += resCr.stride, c1 += resC1.stride, c2 += resC2.stride )
104
4.22M
  {
105
61.9M
    for( SizeType x = 0; x < resCb.width; x++ )
106
57.6M
    {
107
57.6M
      int cbx = cb[x], crx = cr[x];
108
57.6M
      if      ( signedMode ==  1 )
109
57.6M
      {
110
57.6M
        c1[x] = Pel( ( 4*cbx + 2*crx ) / 5 );
111
57.6M
        d1   += square( cbx - c1[x] ) + square( crx - (c1[x]>>1) );
112
57.6M
      }
113
0
      else if ( signedMode == -1 )
114
0
      {
115
0
        c1[x] = Pel( ( 4*cbx - 2*crx ) / 5 );
116
0
        d1   += square( cbx - c1[x] ) + square( crx - (-c1[x]>>1) );
117
0
      }
118
0
      else if ( signedMode ==  2 )
119
0
      {
120
0
        c1[x] = Pel( ( cbx + crx ) / 2 );
121
0
        d1   += square( cbx - c1[x] ) + square( crx - c1[x] );
122
0
      }
123
0
      else if ( signedMode == -2 )
124
0
      {
125
0
        c1[x] = Pel( ( cbx - crx ) / 2 );
126
0
        d1   += square( cbx - c1[x] ) + square( crx + c1[x] );
127
0
      }
128
0
      else if ( signedMode ==  3 )
129
0
      {
130
0
        c2[x] = Pel( ( 4*crx + 2*cbx ) / 5 );
131
0
        d1   += square( cbx - (c2[x]>>1) ) + square( crx - c2[x] );
132
0
      }
133
0
      else if ( signedMode == -3 )
134
0
      {
135
0
        c2[x] = Pel( ( 4*crx - 2*cbx ) / 5 );
136
0
        d1   += square( cbx - (-c2[x]>>1) ) + square( crx - c2[x] );
137
0
      }
138
0
      else
139
0
      {
140
0
        d1   += square( cbx );
141
0
        d2   += square( crx );
142
0
      }
143
57.6M
    }
144
4.22M
  }
145
334k
  return std::make_pair(d1,d2);
146
334k
}
Unexecuted instantiation: std::__1::pair<long, long> vvenc::fwdTransformCbCr<-1>(vvenc::AreaBuf<short> const&, vvenc::AreaBuf<short> const&, vvenc::AreaBuf<short>&, vvenc::AreaBuf<short>&)
std::__1::pair<long, long> vvenc::fwdTransformCbCr<2>(vvenc::AreaBuf<short> const&, vvenc::AreaBuf<short> const&, vvenc::AreaBuf<short>&, vvenc::AreaBuf<short>&)
Line
Count
Source
96
334k
{
97
334k
  const Pel*  cb  = resCb.buf;
98
334k
  const Pel*  cr  = resCr.buf;
99
334k
  Pel*        c1  = resC1.buf;
100
334k
  Pel*        c2  = resC2.buf;
101
334k
  int64_t     d1  = 0;
102
334k
  int64_t     d2  = 0;
103
4.55M
  for( SizeType y = 0; y < resCb.height; y++, cb += resCb.stride, cr += resCr.stride, c1 += resC1.stride, c2 += resC2.stride )
104
4.22M
  {
105
61.9M
    for( SizeType x = 0; x < resCb.width; x++ )
106
57.6M
    {
107
57.6M
      int cbx = cb[x], crx = cr[x];
108
57.6M
      if      ( signedMode ==  1 )
109
0
      {
110
0
        c1[x] = Pel( ( 4*cbx + 2*crx ) / 5 );
111
0
        d1   += square( cbx - c1[x] ) + square( crx - (c1[x]>>1) );
112
0
      }
113
57.6M
      else if ( signedMode == -1 )
114
0
      {
115
0
        c1[x] = Pel( ( 4*cbx - 2*crx ) / 5 );
116
0
        d1   += square( cbx - c1[x] ) + square( crx - (-c1[x]>>1) );
117
0
      }
118
57.6M
      else if ( signedMode ==  2 )
119
57.6M
      {
120
57.6M
        c1[x] = Pel( ( cbx + crx ) / 2 );
121
57.6M
        d1   += square( cbx - c1[x] ) + square( crx - c1[x] );
122
57.6M
      }
123
0
      else if ( signedMode == -2 )
124
0
      {
125
0
        c1[x] = Pel( ( cbx - crx ) / 2 );
126
0
        d1   += square( cbx - c1[x] ) + square( crx + c1[x] );
127
0
      }
128
0
      else if ( signedMode ==  3 )
129
0
      {
130
0
        c2[x] = Pel( ( 4*crx + 2*cbx ) / 5 );
131
0
        d1   += square( cbx - (c2[x]>>1) ) + square( crx - c2[x] );
132
0
      }
133
0
      else if ( signedMode == -3 )
134
0
      {
135
0
        c2[x] = Pel( ( 4*crx - 2*cbx ) / 5 );
136
0
        d1   += square( cbx - (-c2[x]>>1) ) + square( crx - c2[x] );
137
0
      }
138
0
      else
139
0
      {
140
0
        d1   += square( cbx );
141
0
        d2   += square( crx );
142
0
      }
143
57.6M
    }
144
4.22M
  }
145
334k
  return std::make_pair(d1,d2);
146
334k
}
Unexecuted instantiation: std::__1::pair<long, long> vvenc::fwdTransformCbCr<-2>(vvenc::AreaBuf<short> const&, vvenc::AreaBuf<short> const&, vvenc::AreaBuf<short>&, vvenc::AreaBuf<short>&)
std::__1::pair<long, long> vvenc::fwdTransformCbCr<3>(vvenc::AreaBuf<short> const&, vvenc::AreaBuf<short> const&, vvenc::AreaBuf<short>&, vvenc::AreaBuf<short>&)
Line
Count
Source
96
334k
{
97
334k
  const Pel*  cb  = resCb.buf;
98
334k
  const Pel*  cr  = resCr.buf;
99
334k
  Pel*        c1  = resC1.buf;
100
334k
  Pel*        c2  = resC2.buf;
101
334k
  int64_t     d1  = 0;
102
334k
  int64_t     d2  = 0;
103
4.55M
  for( SizeType y = 0; y < resCb.height; y++, cb += resCb.stride, cr += resCr.stride, c1 += resC1.stride, c2 += resC2.stride )
104
4.22M
  {
105
61.9M
    for( SizeType x = 0; x < resCb.width; x++ )
106
57.6M
    {
107
57.6M
      int cbx = cb[x], crx = cr[x];
108
57.6M
      if      ( signedMode ==  1 )
109
0
      {
110
0
        c1[x] = Pel( ( 4*cbx + 2*crx ) / 5 );
111
0
        d1   += square( cbx - c1[x] ) + square( crx - (c1[x]>>1) );
112
0
      }
113
57.6M
      else if ( signedMode == -1 )
114
0
      {
115
0
        c1[x] = Pel( ( 4*cbx - 2*crx ) / 5 );
116
0
        d1   += square( cbx - c1[x] ) + square( crx - (-c1[x]>>1) );
117
0
      }
118
57.6M
      else if ( signedMode ==  2 )
119
0
      {
120
0
        c1[x] = Pel( ( cbx + crx ) / 2 );
121
0
        d1   += square( cbx - c1[x] ) + square( crx - c1[x] );
122
0
      }
123
57.6M
      else if ( signedMode == -2 )
124
0
      {
125
0
        c1[x] = Pel( ( cbx - crx ) / 2 );
126
0
        d1   += square( cbx - c1[x] ) + square( crx + c1[x] );
127
0
      }
128
57.6M
      else if ( signedMode ==  3 )
129
57.6M
      {
130
57.6M
        c2[x] = Pel( ( 4*crx + 2*cbx ) / 5 );
131
57.6M
        d1   += square( cbx - (c2[x]>>1) ) + square( crx - c2[x] );
132
57.6M
      }
133
0
      else if ( signedMode == -3 )
134
0
      {
135
0
        c2[x] = Pel( ( 4*crx - 2*cbx ) / 5 );
136
0
        d1   += square( cbx - (-c2[x]>>1) ) + square( crx - c2[x] );
137
0
      }
138
0
      else
139
0
      {
140
0
        d1   += square( cbx );
141
0
        d2   += square( crx );
142
0
      }
143
57.6M
    }
144
4.22M
  }
145
334k
  return std::make_pair(d1,d2);
146
334k
}
Unexecuted instantiation: std::__1::pair<long, long> vvenc::fwdTransformCbCr<-3>(vvenc::AreaBuf<short> const&, vvenc::AreaBuf<short> const&, vvenc::AreaBuf<short>&, vvenc::AreaBuf<short>&)
147
148
template<int signedMode> void invTransformCbCr( PelBuf& resCb, PelBuf& resCr )
149
329k
{
150
329k
  Pel*  cb  = resCb.buf;
151
329k
  Pel*  cr  = resCr.buf;
152
4.49M
  for( SizeType y = 0; y < resCb.height; y++, cb += resCb.stride, cr += resCr.stride )
153
4.16M
  {
154
61.2M
    for( SizeType x = 0; x < resCb.width; x++ )
155
57.0M
    {
156
57.0M
      if      ( signedMode ==  1 )  { cr[x] =  cb[x] >> 1;  }
157
57.0M
      else if ( signedMode == -1 )  { cr[x] = -cb[x] >> 1;  }
158
57.0M
      else if ( signedMode ==  2 )  { cr[x] =  cb[x]; }
159
309k
      else if ( signedMode == -2 )  { cr[x] = -cb[x]; }
160
309k
      else if ( signedMode ==  3 )  { cb[x] =  cr[x] >> 1; }
161
0
      else if ( signedMode == -3 )  { cb[x] = -cr[x] >> 1; }
162
57.0M
    }
163
4.16M
  }
164
329k
}
Unexecuted instantiation: void vvenc::invTransformCbCr<0>(vvenc::AreaBuf<short>&, vvenc::AreaBuf<short>&)
Unexecuted instantiation: void vvenc::invTransformCbCr<1>(vvenc::AreaBuf<short>&, vvenc::AreaBuf<short>&)
Unexecuted instantiation: void vvenc::invTransformCbCr<-1>(vvenc::AreaBuf<short>&, vvenc::AreaBuf<short>&)
void vvenc::invTransformCbCr<2>(vvenc::AreaBuf<short>&, vvenc::AreaBuf<short>&)
Line
Count
Source
149
327k
{
150
327k
  Pel*  cb  = resCb.buf;
151
327k
  Pel*  cr  = resCr.buf;
152
4.46M
  for( SizeType y = 0; y < resCb.height; y++, cb += resCb.stride, cr += resCr.stride )
153
4.13M
  {
154
60.9M
    for( SizeType x = 0; x < resCb.width; x++ )
155
56.7M
    {
156
56.7M
      if      ( signedMode ==  1 )  { cr[x] =  cb[x] >> 1;  }
157
56.7M
      else if ( signedMode == -1 )  { cr[x] = -cb[x] >> 1;  }
158
56.7M
      else if ( signedMode ==  2 )  { cr[x] =  cb[x]; }
159
0
      else if ( signedMode == -2 )  { cr[x] = -cb[x]; }
160
0
      else if ( signedMode ==  3 )  { cb[x] =  cr[x] >> 1; }
161
0
      else if ( signedMode == -3 )  { cb[x] = -cr[x] >> 1; }
162
56.7M
    }
163
4.13M
  }
164
327k
}
Unexecuted instantiation: void vvenc::invTransformCbCr<-2>(vvenc::AreaBuf<short>&, vvenc::AreaBuf<short>&)
void vvenc::invTransformCbCr<3>(vvenc::AreaBuf<short>&, vvenc::AreaBuf<short>&)
Line
Count
Source
149
2.51k
{
150
2.51k
  Pel*  cb  = resCb.buf;
151
2.51k
  Pel*  cr  = resCr.buf;
152
30.6k
  for( SizeType y = 0; y < resCb.height; y++, cb += resCb.stride, cr += resCr.stride )
153
28.1k
  {
154
337k
    for( SizeType x = 0; x < resCb.width; x++ )
155
309k
    {
156
309k
      if      ( signedMode ==  1 )  { cr[x] =  cb[x] >> 1;  }
157
309k
      else if ( signedMode == -1 )  { cr[x] = -cb[x] >> 1;  }
158
309k
      else if ( signedMode ==  2 )  { cr[x] =  cb[x]; }
159
309k
      else if ( signedMode == -2 )  { cr[x] = -cb[x]; }
160
309k
      else if ( signedMode ==  3 )  { cb[x] =  cr[x] >> 1; }
161
0
      else if ( signedMode == -3 )  { cb[x] = -cr[x] >> 1; }
162
309k
    }
163
28.1k
  }
164
2.51k
}
Unexecuted instantiation: void vvenc::invTransformCbCr<-3>(vvenc::AreaBuf<short>&, vvenc::AreaBuf<short>&)
165
166
void xFwdLfnstNxNCore(int *src, int *dst, const uint32_t mode, const uint32_t index, const uint32_t size, int zeroOutSize)
167
1.49M
{
168
1.49M
  const int8_t *trMat  = (size > 4) ? g_lfnstFwd8x8[mode][index][0] : g_lfnstFwd4x4[mode][index][0];
169
1.49M
  const int     trSize = (size > 4) ? 48 : 16;
170
1.49M
  int           coef;
171
1.49M
  int *         out = dst;
172
173
23.2M
  for (int j = 0; j < zeroOutSize; j++)
174
21.7M
  {
175
21.7M
    int *         srcPtr   = src;
176
21.7M
    const int8_t *trMatTmp = trMat;
177
21.7M
    coef                   = 0;
178
833M
    for (int i = 0; i < trSize; i++)
179
811M
    {
180
811M
      coef += *srcPtr++ * *trMatTmp++;
181
811M
    }
182
21.7M
    *out++ = (coef + 64) >> 7;
183
21.7M
    trMat += trSize;
184
21.7M
  }
185
186
1.49M
  ::memset(out, 0, (trSize - zeroOutSize) * sizeof(int));
187
1.49M
}
188
189
190
void xInvLfnstNxNCore(int *src, int *dst, const uint32_t mode, const uint32_t index, const uint32_t size, int zeroOutSize)
191
629k
{
192
629k
  int           maxLog2TrDynamicRange = 15;
193
629k
  const TCoeff  outputMinimum         = -(1 << maxLog2TrDynamicRange);
194
629k
  const TCoeff  outputMaximum         = (1 << maxLog2TrDynamicRange) - 1;
195
629k
  const int8_t *trMat                 = (size > 4) ? g_lfnstInv8x8[mode][index][0] : g_lfnstInv4x4[mode][index][0];
196
629k
  const int     trSize                = (size > 4) ? 48 : 16;
197
629k
  int           resi;
198
629k
  int *         out                   = dst;
199
200
23.7M
  for( int j = 0; j < trSize; j++, trMat += 16 )
201
23.0M
  {
202
23.0M
    resi = 0;
203
23.0M
    const int8_t* trMatTmp = trMat;
204
23.0M
    int*          srcPtr   = src;
205
206
351M
    for( int i = 0; i < zeroOutSize; i++ )
207
328M
    {
208
328M
      resi += *srcPtr++ * *trMatTmp++;
209
328M
    }
210
211
23.0M
    *out++ = Clip3( outputMinimum, outputMaximum, ( int ) ( resi + 64 ) >> 7 );
212
23.0M
  }
213
629k
}
214
215
// ====================================================================================================================
216
// TrQuant class member functions
217
// ====================================================================================================================
218
5.97k
TrQuant::TrQuant( bool enableOpt ) : m_scalingListEnabled(false), m_quant( nullptr )
219
5.97k
{
220
  // allocate temporary buffers
221
5.97k
  m_plTempCoeff = ( TCoeff* ) xMalloc( TCoeff, MAX_TB_SIZEY * MAX_TB_SIZEY );
222
5.97k
  m_tmp         = ( TCoeff* ) xMalloc( TCoeff, MAX_TB_SIZEY * MAX_TB_SIZEY );
223
5.97k
  m_blk         = ( TCoeff* ) xMalloc( TCoeff, MAX_TB_SIZEY * MAX_TB_SIZEY );
224
225
41.8k
  for( int i = 0; i < NUM_TRAFO_MODES_MTS; i++ )
226
35.8k
  {
227
35.8k
    m_mtsCoeffs[i] = ( TCoeff* ) xMalloc( TCoeff, MAX_TB_SIZEY * MAX_TB_SIZEY );
228
35.8k
  }
229
230
5.97k
  {
231
5.97k
    m_invICT      = m_invICTMem + maxAbsIctMode;
232
5.97k
    m_invICT[ 0]  = invTransformCbCr< 0>;
233
5.97k
    m_invICT[ 1]  = invTransformCbCr< 1>;
234
5.97k
    m_invICT[-1]  = invTransformCbCr<-1>;
235
5.97k
    m_invICT[ 2]  = invTransformCbCr< 2>;
236
5.97k
    m_invICT[-2]  = invTransformCbCr<-2>;
237
5.97k
    m_invICT[ 3]  = invTransformCbCr< 3>;
238
5.97k
    m_invICT[-3]  = invTransformCbCr<-3>;
239
5.97k
    m_fwdICT      = m_fwdICTMem + maxAbsIctMode;
240
5.97k
    m_fwdICT[ 0]  = fwdTransformCbCr< 0>;
241
5.97k
    m_fwdICT[ 1]  = fwdTransformCbCr< 1>;
242
5.97k
    m_fwdICT[-1]  = fwdTransformCbCr<-1>;
243
5.97k
    m_fwdICT[ 2]  = fwdTransformCbCr< 2>;
244
5.97k
    m_fwdICT[-2]  = fwdTransformCbCr<-2>;
245
5.97k
    m_fwdICT[ 3]  = fwdTransformCbCr< 3>;
246
5.97k
    m_fwdICT[-3]  = fwdTransformCbCr<-3>;
247
5.97k
  }
248
249
5.97k
  m_invLfnstNxN = xInvLfnstNxNCore;
250
5.97k
  m_fwdLfnstNxN = xFwdLfnstNxNCore;
251
252
#if defined( TARGET_SIMD_X86 ) && ENABLE_SIMD_TRAFO
253
  if( enableOpt )
254
  {
255
    initTrQuantX86();
256
  }
257
#endif
258
5.97k
}
259
260
TrQuant::~TrQuant()
261
5.97k
{
262
5.97k
  if( m_quant )
263
5.97k
  {
264
5.97k
    delete m_quant;
265
5.97k
    m_quant = nullptr;
266
5.97k
  }
267
268
  // delete temporary buffers
269
5.97k
  if( m_plTempCoeff )
270
5.97k
  {
271
5.97k
    xFree( m_plTempCoeff );
272
5.97k
    m_plTempCoeff = nullptr;
273
5.97k
  }
274
275
5.97k
  if( m_blk )
276
5.97k
  {
277
5.97k
    xFree( m_blk );
278
5.97k
    m_blk = nullptr;
279
5.97k
  }
280
281
5.97k
  if( m_tmp )
282
5.97k
  {
283
5.97k
    xFree( m_tmp );
284
5.97k
    m_tmp = nullptr;
285
5.97k
  }
286
287
41.8k
  for( int i = 0; i < NUM_TRAFO_MODES_MTS; i++ )
288
35.8k
  {
289
35.8k
     xFree( m_mtsCoeffs[i] );
290
35.8k
  }
291
5.97k
}
292
293
void TrQuant::xDeQuant(const TransformUnit& tu,
294
                             CoeffBuf      &dstCoeff,
295
                       const ComponentID   &compID,
296
                       const QpParam       &cQP)
297
1.03M
{
298
1.03M
  PROFILER_SCOPE_AND_STAGE( 1, _TPROF, P_DEQUANT );
299
1.03M
  m_quant->dequant( tu, dstCoeff, compID, cQP );
300
1.03M
}
301
302
void TrQuant::init( const Quant* otherQuant,
303
                    const int  rdoq,
304
                    const bool bUseRDOQTS,
305
                    const bool scalingListsEnabled,
306
                    const bool bEnc,
307
                    const int  thrVal
308
)
309
5.97k
{
310
5.97k
  m_bEnc = bEnc;
311
312
5.97k
  delete m_quant;
313
5.97k
  m_quant = nullptr;
314
315
5.97k
  m_quant = new(std::nothrow) DepQuant( otherQuant, bEnc, scalingListsEnabled );
316
5.97k
  CHECK( !m_quant, "allocation failed" );
317
5.97k
  m_quant->init( rdoq, bUseRDOQTS, thrVal );
318
5.97k
}
319
320
321
void TrQuant::invTransformNxN( TransformUnit& tu, const ComponentID compID, PelBuf& pResi, const QpParam& cQP )
322
1.03M
{
323
1.03M
  const CompArea& area    = tu.blocks[compID];
324
1.03M
  const uint32_t uiWidth  = area.width;
325
1.03M
  const uint32_t uiHeight = area.height;
326
327
1.03M
  CHECK( uiWidth > tu.cs->sps->getMaxTbSize() || uiHeight > tu.cs->sps->getMaxTbSize(), "Maximal allowed transformation size exceeded!" );
328
329
1.03M
  {
330
1.03M
    CoeffBuf tempCoeff = CoeffBuf( m_plTempCoeff, area );
331
1.03M
    xDeQuant( tu, tempCoeff, compID, cQP );
332
333
1.03M
    DTRACE_COEFF_BUF( D_TCOEFF, tempCoeff, tu, tu.cu->predMode, compID );
334
335
1.03M
    if (tu.cs->sps->LFNST)
336
1.03M
    {
337
1.03M
      xInvLfnst(tu, compID);
338
1.03M
    }
339
1.03M
    if (tu.mtsIdx[compID] == MTS_SKIP)
340
59.7k
    {
341
59.7k
      xITransformSkip(tempCoeff, pResi, tu, compID);
342
59.7k
    }
343
971k
    else
344
971k
    {
345
971k
      xIT(tu, compID, tempCoeff, pResi);
346
971k
    }
347
1.03M
  }
348
349
  //DTRACE_BLOCK_COEFF(tu.getCoeffs(compID), tu, tu.cu->predMode, compID);
350
1.03M
  DTRACE_PEL_BUF( D_RESIDUALS, pResi, tu, tu.cu->predMode, compID);
351
1.03M
}
352
353
std::pair<int64_t,int64_t> TrQuant::fwdTransformICT( const TransformUnit& tu, const PelBuf& resCb, const PelBuf& resCr, PelBuf& resC1, PelBuf& resC2, int jointCbCr )
354
1.33M
{
355
1.33M
  CHECK( Size(resCb) != Size(resCr), "resCb and resCr have different sizes" );
356
1.33M
  CHECK( Size(resCb) != Size(resC1), "resCb and resC1 have different sizes" );
357
1.33M
  CHECK( Size(resCb) != Size(resC2), "resCb and resC2 have different sizes" );
358
1.33M
  return (*m_fwdICT[ TU::getICTMode(tu, jointCbCr) ])( resCb, resCr, resC1, resC2 );
359
1.33M
}
360
361
void TrQuant::invTransformICT( const TransformUnit& tu, PelBuf& resCb, PelBuf& resCr )
362
329k
{
363
329k
  CHECK( Size(resCb) != Size(resCr), "resCb and resCr have different sizes" );
364
329k
  (*m_invICT[ TU::getICTMode(tu) ])( resCb, resCr );
365
329k
}
366
367
std::vector<int> TrQuant::selectICTCandidates( const TransformUnit& tu, CompStorage* resCb, CompStorage* resCr )
368
334k
{
369
334k
  CHECK( !resCb[0].valid() || !resCr[0].valid(), "standard components are not valid" );
370
371
334k
  if( !CU::isIntra( *tu.cu ) )
372
0
  {
373
0
    int cbfMask = 3;
374
0
    fwdTransformICT( tu, resCb[0], resCr[0], resCb[cbfMask], resCr[cbfMask], cbfMask );
375
0
    std::vector<int> cbfMasksToTest;
376
0
    cbfMasksToTest.push_back( cbfMask );
377
0
    return cbfMasksToTest;
378
0
  }
379
380
334k
  std::pair<int64_t,int64_t> pairDist[4];
381
1.67M
  for( int cbfMask = 0; cbfMask < 4; cbfMask++ )
382
1.33M
  {
383
1.33M
    pairDist[cbfMask] = fwdTransformICT( tu, resCb[0], resCr[0], resCb[cbfMask], resCr[cbfMask], cbfMask );
384
1.33M
  }
385
386
334k
  std::vector<int> cbfMasksToTest;
387
334k
  int64_t minDist1  = std::min<int64_t>( pairDist[0].first, pairDist[0].second );
388
334k
  int64_t minDist2  = std::numeric_limits<int64_t>::max();
389
334k
  int     cbfMask1  = 0;
390
334k
  int     cbfMask2  = 0;
391
334k
  for( int cbfMask : { 1, 2, 3 } )
392
1.00M
  {
393
1.00M
    if( pairDist[cbfMask].first < minDist1 )
394
661k
    {
395
661k
      cbfMask2  = cbfMask1; minDist2  = minDist1;
396
661k
      cbfMask1  = cbfMask;  minDist1  = pairDist[cbfMask1].first;
397
661k
    }
398
342k
    else if( pairDist[cbfMask].first < minDist2 )
399
334k
    {
400
334k
      cbfMask2  = cbfMask;  minDist2  = pairDist[cbfMask2].first;
401
334k
    }
402
1.00M
  }
403
334k
  if( cbfMask1 )
404
334k
  {
405
334k
    cbfMasksToTest.push_back( cbfMask1 );
406
334k
  }
407
334k
  if( cbfMask2 && ( ( minDist2 < (9*minDist1)/8 ) || ( !cbfMask1 && minDist2 < (3*minDist1)/2 ) ) )
408
0
  {
409
0
    cbfMasksToTest.push_back( cbfMask2 );
410
0
  }
411
412
334k
  return cbfMasksToTest;
413
334k
}
414
415
416
417
// ------------------------------------------------------------------------------------------------
418
// Logical transform
419
// ------------------------------------------------------------------------------------------------
420
void TrQuant::xSetTrTypes( const TransformUnit& tu, const ComponentID compID, const int width, const int height, int &trTypeHor, int &trTypeVer )
421
3.36M
{
422
3.36M
  const bool isISP = CU::isIntra(*tu.cu) && tu.cu->ispMode && isLuma(compID);
423
3.36M
  if (isISP && tu.cu->lfnstIdx)
424
22.6k
  {
425
22.6k
    return;
426
22.6k
  }
427
3.34M
  if (!tu.cs->sps->MTS)
428
0
  {
429
0
    return;
430
0
  }
431
3.34M
  if (CU::isIntra(*tu.cu) && isLuma(compID) && ((tu.cs->sps->getUseImplicitMTS() && tu.cu->lfnstIdx == 0 && tu.cu->mipFlag == 0) || tu.cu->ispMode))
432
104k
  {
433
104k
    if (width >= 4 && width <= 16)
434
46.0k
      trTypeHor = DST7;
435
104k
    if (height >= 4 && height <= 16)
436
44.0k
      trTypeVer = DST7;
437
104k
  }
438
3.23M
  else if( tu.cs->sps->MTS && tu.cu->sbtInfo && isLuma(compID)/*isSBT*/ )
439
0
  {
440
0
    const uint8_t sbtIdx = CU::getSbtIdx( tu.cu->sbtInfo );
441
0
    const uint8_t sbtPos = CU::getSbtPos( tu.cu->sbtInfo );
442
443
0
    if( sbtIdx == SBT_VER_HALF || sbtIdx == SBT_VER_QUAD )
444
0
    {
445
0
      assert( tu.lwidth() <= MTS_INTER_MAX_CU_SIZE );
446
0
      if( tu.lheight() > MTS_INTER_MAX_CU_SIZE )
447
0
      {
448
0
        trTypeHor = trTypeVer = DCT2;
449
0
      }
450
0
      else
451
0
      {
452
0
        if( sbtPos == SBT_POS0 )  { trTypeHor = DCT8;  trTypeVer = DST7; }
453
0
        else                      { trTypeHor = DST7;  trTypeVer = DST7; }
454
0
      }
455
0
    }
456
0
    else
457
0
    {
458
0
      assert( tu.lheight() <= MTS_INTER_MAX_CU_SIZE );
459
0
      if( tu.lwidth() > MTS_INTER_MAX_CU_SIZE )
460
0
      {
461
0
        trTypeHor = trTypeVer = DCT2;
462
0
      }
463
0
      else
464
0
      {
465
0
        if( sbtPos == SBT_POS0 )  { trTypeHor = DST7;  trTypeVer = DCT8; }
466
0
        else                      { trTypeHor = DST7;  trTypeVer = DST7; }
467
0
      }
468
0
    }
469
0
  }
470
3.34M
  const bool isExplicitMTS = (CU::isIntra(*tu.cu) ? tu.cs->sps->MTS : tu.cs->sps->MTSInter && CU::isInter(*tu.cu)) && isLuma(compID);
471
3.34M
  if (isExplicitMTS)
472
249k
  {
473
249k
    if (tu.mtsIdx[compID] > MTS_SKIP)
474
0
    {
475
0
      int indHor = (tu.mtsIdx[compID] - MTS_DST7_DST7) & 1;
476
0
      int indVer = (tu.mtsIdx[compID] - MTS_DST7_DST7) >> 1;
477
0
      trTypeHor  = indHor ? DCT8 : DST7;
478
0
      trTypeVer  = indVer ? DCT8 : DST7;
479
0
    }
480
249k
  }
481
3.34M
}
482
483
484
void TrQuant::xT( const TransformUnit& tu, const ComponentID compID, const CPelBuf& resi, CoeffBuf& dstCoeff, const int width, const int height )
485
2.39M
{
486
2.39M
  PROFILER_SCOPE_AND_STAGE( 1, _TPROF, P_TRAFO );
487
488
2.39M
  const unsigned maxLog2TrDynamicRange  = tu.cs->sps->getMaxLog2TrDynamicRange();
489
2.39M
  const unsigned bitDepth               = tu.cs->sps->bitDepths[toChannelType( compID )];
490
2.39M
  const int      TRANSFORM_MATRIX_SHIFT = g_transformMatrixShift[TRANSFORM_FORWARD];
491
2.39M
  const uint32_t transformWidthIndex    = Log2(width ) - 1;  // nLog2WidthMinus1, since transform start from 2-point
492
2.39M
  const uint32_t transformHeightIndex   = Log2(height) - 1;  // nLog2HeightMinus1, since transform start from 2-point
493
494
2.39M
  int trTypeHor = DCT2;
495
2.39M
  int trTypeVer = DCT2;
496
497
2.39M
  xSetTrTypes( tu, compID, width, height, trTypeHor, trTypeVer );
498
499
2.39M
  int  skipWidth  = ( trTypeHor != DCT2 && width  == 32 ) ? 16 : width  > JVET_C0024_ZERO_OUT_TH ? width  - JVET_C0024_ZERO_OUT_TH : 0;
500
2.39M
  int  skipHeight = ( trTypeVer != DCT2 && height == 32 ) ? 16 : height > JVET_C0024_ZERO_OUT_TH ? height - JVET_C0024_ZERO_OUT_TH : 0;
501
502
2.39M
  if( tu.cu->lfnstIdx )
503
1.49M
  {
504
1.49M
    if ((width == 4 && height > 4) || (width > 4 && height == 4))
505
405k
    {
506
405k
      skipWidth  = width - 4;
507
405k
      skipHeight = height - 4;
508
405k
    }
509
1.08M
    else if ((width >= 8 && height >= 8))
510
995k
    {
511
995k
      skipWidth  = width - 8;
512
995k
      skipHeight = height - 8;
513
995k
    }
514
1.49M
  }
515
516
2.39M
  TCoeff* block = m_blk;
517
2.39M
  TCoeff* tmp   = m_tmp;
518
519
2.39M
  const Pel* resiBuf    = resi.buf;
520
2.39M
  const int  resiStride = resi.stride;
521
522
2.39M
#if ENABLE_SIMD_TRAFO
523
2.39M
  if( width & 3 )
524
0
#endif
525
0
  {
526
0
    for( int y = 0; y < height; y++ )
527
0
    {
528
0
      for( int x = 0; x < width; x++ )
529
0
      {
530
0
        block[( y * width ) + x] = resiBuf[( y * resiStride ) + x];
531
0
      }
532
0
    }
533
0
  }
534
2.39M
#if ENABLE_SIMD_TRAFO
535
2.39M
  else if( width & 7 )
536
439k
  {
537
439k
    g_tCoeffOps.cpyCoeff4( resiBuf, resiStride, block, width, height );
538
439k
  }
539
1.95M
  else
540
1.95M
  {
541
1.95M
    g_tCoeffOps.cpyCoeff8( resiBuf, resiStride, block, width, height );
542
1.95M
  }
543
2.39M
#endif //ENABLE_SIMD_TRAFO
544
545
2.39M
  if (width > 1 && height > 1)
546
2.39M
  {
547
2.39M
    const int shift_1st = ((Log2(width )) + bitDepth + TRANSFORM_MATRIX_SHIFT) - maxLog2TrDynamicRange;
548
2.39M
    const int shift_2nd =  (Log2(height))            + TRANSFORM_MATRIX_SHIFT;
549
2.39M
    CHECK( shift_1st < 0, "Negative shift" );
550
2.39M
    CHECK( shift_2nd < 0, "Negative shift" );
551
2.39M
    fastFwdTrans[trTypeHor][transformWidthIndex](block, tmp, shift_1st, height, 0, skipWidth);
552
2.39M
    fastFwdTrans[trTypeVer][transformHeightIndex](tmp, dstCoeff.buf, shift_2nd, width, skipWidth, skipHeight);
553
2.39M
  }
554
300
  else if (height == 1)   // 1-D horizontal transform
555
316
  {
556
316
    const int shift = ((Log2(width )) + bitDepth + TRANSFORM_MATRIX_SHIFT) - maxLog2TrDynamicRange;
557
316
    CHECK( shift < 0, "Negative shift" );
558
316
    fastFwdTrans[trTypeHor][transformWidthIndex](block, dstCoeff.buf, shift, 1, 0, skipWidth);
559
316
  }
560
18.4E
  else   // if (iWidth == 1) //1-D vertical transform
561
18.4E
  {
562
18.4E
    int shift = ((floorLog2(height)) + bitDepth + TRANSFORM_MATRIX_SHIFT) - maxLog2TrDynamicRange;
563
18.4E
    CHECK(shift < 0, "Negative shift");
564
18.4E
    CHECKD((transformHeightIndex < 0), "There is a problem with the height.");
565
18.4E
    fastFwdTrans[trTypeVer][transformHeightIndex](block, dstCoeff.buf, shift, 1, 0, skipHeight);
566
18.4E
  }
567
2.39M
}
568
569
570
void TrQuant::xIT( const TransformUnit& tu, const ComponentID compID, const CCoeffBuf& pCoeff, PelBuf& pResidual )
571
971k
{
572
971k
  PROFILER_SCOPE_AND_STAGE( 1, _TPROF, P_TRAFO );
573
574
971k
  const int      width                  = pCoeff.width;
575
971k
  const int      height                 = pCoeff.height;
576
971k
  const unsigned maxLog2TrDynamicRange  = tu.cs->sps->getMaxLog2TrDynamicRange();
577
971k
  const unsigned bitDepth               = tu.cs->sps->bitDepths[toChannelType( compID )];
578
971k
  const int      TRANSFORM_MATRIX_SHIFT = g_transformMatrixShift[TRANSFORM_INVERSE];
579
971k
  const TCoeff   clipMinimum            = -( 1 << maxLog2TrDynamicRange );
580
971k
  const TCoeff   clipMaximum            =  ( 1 << maxLog2TrDynamicRange ) - 1;
581
971k
  const uint32_t transformWidthIndex    = Log2(width )- 1;                                // nLog2WidthMinus1, since transform start from 2-point
582
971k
  const uint32_t transformHeightIndex   = Log2(height) - 1;                                // nLog2HeightMinus1, since transform start from 2-point
583
584
585
971k
  int trTypeHor = DCT2;
586
971k
  int trTypeVer = DCT2;
587
588
971k
  xSetTrTypes( tu, compID, width, height, trTypeHor, trTypeVer );
589
590
971k
  int skipWidth  = ( trTypeHor != DCT2 && width  == 32 ) ? 16 : width  > JVET_C0024_ZERO_OUT_TH ? width  - JVET_C0024_ZERO_OUT_TH : 0;
591
971k
  int skipHeight = ( trTypeVer != DCT2 && height == 32 ) ? 16 : height > JVET_C0024_ZERO_OUT_TH ? height - JVET_C0024_ZERO_OUT_TH : 0;
592
593
971k
  if (tu.cs->sps->LFNST && tu.cu->lfnstIdx)
594
629k
  {
595
629k
    if ((width == 4 && height > 4) || (width > 4 && height == 4))
596
172k
    {
597
172k
      skipWidth = width - 4;
598
172k
      skipHeight = height - 4;
599
172k
    }
600
456k
    else if ((width >= 8 && height >= 8))
601
407k
    {
602
407k
      skipWidth = width - 8;
603
407k
      skipHeight = height - 8;
604
407k
    }
605
629k
  }
606
607
971k
  TCoeff *block = m_blk;
608
971k
  TCoeff *tmp   = m_tmp;
609
971k
  if (width > 1 && height > 1)   // 2-D transform
610
971k
  {
611
971k
    const int shift_1st =   TRANSFORM_MATRIX_SHIFT + 1; // 1 has been added to shift_1st at the expense of shift_2nd
612
971k
    const int shift_2nd = ( TRANSFORM_MATRIX_SHIFT + maxLog2TrDynamicRange - 1 ) - bitDepth;
613
971k
    CHECK( shift_1st < 0, "Negative shift" );
614
971k
    CHECK( shift_2nd < 0, "Negative shift" );
615
971k
    fastInvTrans[trTypeVer][transformHeightIndex](pCoeff.buf, tmp, shift_1st, width, skipWidth, skipHeight, clipMinimum, clipMaximum);
616
971k
    fastInvTrans[trTypeHor][transformWidthIndex](tmp, block, shift_2nd, height, 0, skipWidth, clipMinimum, clipMaximum);
617
971k
  }
618
79
  else if (width == 1)   // 1-D vertical transform
619
0
  {
620
0
    int shift = (TRANSFORM_MATRIX_SHIFT + maxLog2TrDynamicRange - 1) - bitDepth;
621
0
    CHECK(shift < 0, "Negative shift");
622
0
    fastInvTrans[trTypeVer][transformHeightIndex](pCoeff.buf, block, shift + 1, 1, 0, skipHeight, clipMinimum, clipMaximum);
623
0
  }
624
79
  else   // if(iHeight == 1) //1-D horizontal transform
625
79
  {
626
79
    const int shift = (TRANSFORM_MATRIX_SHIFT + maxLog2TrDynamicRange - 1) - bitDepth;
627
79
    CHECK(shift < 0, "Negative shift");
628
79
    fastInvTrans[trTypeHor][transformWidthIndex](pCoeff.buf, block, shift + 1, 1, 0, skipWidth, clipMinimum, clipMaximum);
629
79
  }
630
631
971k
#if ENABLE_SIMD_TRAFO
632
971k
  if( width & 3 )
633
0
#endif //ENABLE_SIMD_TRAFO
634
0
  {
635
0
    Pel       *dst    = pResidual.buf;
636
0
    ptrdiff_t  stride = pResidual.stride;
637
638
0
    for( int y = 0; y < height; y++ )
639
0
    {
640
0
      for( int x = 0; x < width; x++ )
641
0
      {
642
0
        dst[x] = ( Pel ) *block++;
643
0
      }
644
645
0
      dst += stride;
646
0
    }
647
0
  }
648
971k
#if ENABLE_SIMD_TRAFO
649
971k
  else if( width & 7 )
650
202k
  {
651
202k
    g_tCoeffOps.cpyResi4( block, pResidual.buf, pResidual.stride, width, height );
652
202k
  }
653
768k
  else
654
768k
  {
655
768k
    g_tCoeffOps.cpyResi8( block, pResidual.buf, pResidual.stride, width, height );
656
768k
  }
657
971k
#endif //ENABLE_SIMD_TRAFO
658
971k
}
659
660
/** Wrapper function between HM interface and core NxN transform skipping
661
 */
662
void TrQuant::xITransformSkip(const CCoeffBuf& pCoeff,
663
  PelBuf& pResidual,
664
  const TransformUnit& tu,
665
  const ComponentID compID)
666
59.7k
{
667
59.7k
  const CompArea& area = tu.blocks[compID];
668
59.7k
  const int width = area.width;
669
59.7k
  const int height = area.height;
670
671
59.7k
#if ENABLE_SIMD_TRAFO
672
59.7k
  if( ( width & 3 ) == 0 )
673
59.7k
  {
674
    // the dequantized coefficients are within 16 bit, where the saturation of the SIMD copies equals the cast below
675
59.7k
    CHECKD( pCoeff.stride != width, "the coefficients have to be stored without padding" );
676
59.7k
    ( width & 7 ? g_tCoeffOps.cpyResi4 : g_tCoeffOps.cpyResi8 )( pCoeff.buf, pResidual.buf, pResidual.stride, width, height );
677
59.7k
    return;
678
59.7k
  }
679
0
#endif
680
681
0
  for (uint32_t y = 0; y < height; y++)
682
0
  {
683
0
    for (uint32_t x = 0; x < width; x++)
684
0
    {
685
0
      pResidual.at(x, y) = Pel(pCoeff.at(x, y));
686
0
    }
687
0
  }
688
0
}
689
690
void TrQuant::xQuant(TransformUnit& tu, const ComponentID compID, const CCoeffBuf& pSrc, TCoeff &uiAbsSum, const QpParam& cQP, const Ctx& ctx)
691
2.52M
{
692
2.52M
  PROFILER_SCOPE_AND_STAGE( 1, _TPROF, P_QUANT );
693
2.52M
  m_quant->quant( tu, compID, pSrc, uiAbsSum, cQP, ctx );
694
#if ENABLE_MEASURE_SEARCH_SPACE
695
696
  g_searchSpaceAcc.addQuant( tu, toChannelType( compID ) );
697
#endif
698
2.52M
}
699
700
701
void TrQuant::transformNxN(TransformUnit &tu, const ComponentID compID, const QpParam &cQP, TCoeff &uiAbsSum, const Ctx &ctx, const bool loadTr)
702
2.52M
{
703
2.52M
        CodingStructure &cs = *tu.cs;
704
2.52M
  const CompArea& rect      = tu.blocks[compID];
705
2.52M
  const uint32_t uiWidth        = rect.width;
706
2.52M
  const uint32_t uiHeight       = rect.height;
707
708
2.52M
  const CPelBuf resiBuf     = cs.getResiBuf(rect);
709
710
2.52M
  if( tu.noResidual )
711
0
  {
712
0
    uiAbsSum = 0;
713
0
    TU::setCbfAtDepth( tu, compID, tu.depth, uiAbsSum > 0 );
714
0
    return;
715
0
  }
716
2.52M
  if (tu.cu->bdpcmM[toChannelType(compID)])
717
123k
  {
718
123k
    tu.mtsIdx[compID] = MTS_SKIP;
719
123k
  }
720
721
2.52M
  uiAbsSum = 0;
722
2.52M
  CHECK( cs.sps->getMaxTbSize() < uiWidth, "Unsupported transformation size" );
723
724
2.52M
  CoeffBuf tempCoeff(loadTr ? m_mtsCoeffs[tu.mtsIdx[compID]] : m_plTempCoeff, rect);
725
2.52M
  if (!loadTr)
726
2.49M
  {
727
2.49M
    DTRACE_PEL_BUF( D_RESIDUALS, resiBuf, tu, tu.cu->predMode, compID );
728
2.49M
    if (tu.mtsIdx[compID] == MTS_SKIP)
729
123k
    {
730
123k
      xTransformSkip(tu, compID, resiBuf, tempCoeff.buf);
731
123k
    }
732
2.37M
    else
733
2.37M
    {
734
2.37M
      xT(tu, compID, resiBuf, tempCoeff, uiWidth, uiHeight);
735
2.37M
    }
736
2.49M
  }
737
2.52M
  if (cs.sps->LFNST)
738
2.52M
  {
739
2.52M
    xFwdLfnst(tu, compID, loadTr);
740
2.52M
  }
741
2.52M
  DTRACE_COEFF_BUF( D_TCOEFF, tempCoeff, tu, tu.cu->predMode, compID );
742
743
2.52M
  xQuant( tu, compID, tempCoeff, uiAbsSum, cQP, ctx );
744
745
2.52M
  DTRACE_COEFF_BUF( D_TCOEFF, tu.getCoeffs( compID ), tu, tu.cu->predMode, compID );
746
747
  // set coded block flag (CBF)
748
2.52M
  TU::setCbfAtDepth (tu, compID, tu.depth, uiAbsSum > 0);
749
2.52M
}
750
751
void TrQuant::checktransformsNxN( TransformUnit &tu, TrModeList *trModes, const int maxCand, const ComponentID compID)
752
21.0k
{
753
21.0k
  CodingStructure &cs     = *tu.cs;
754
21.0k
  const CompArea& rect    = tu.blocks[compID];
755
21.0k
  const uint32_t   width  = rect.width;
756
21.0k
  const uint32_t   height = rect.height;
757
758
21.0k
  const CPelBuf resiBuf = cs.getResiBuf(rect);
759
760
21.0k
  CHECK(cs.sps->getMaxTbSize() < width, "Unsupported transformation size");
761
21.0k
  int                           pos = 0;
762
21.0k
  TrCostList                    trCosts;
763
21.0k
  TrModeList::iterator          it      = trModes->begin();
764
21.0k
  const double                  facBB[] = { 1.2, 1.3, 1.3, 1.4, 1.5 };
765
63.1k
  while (it != trModes->end())
766
42.1k
  {
767
42.1k
    tu.mtsIdx[compID] = it->first;
768
42.1k
    CoeffBuf tempCoeff(m_mtsCoeffs[tu.mtsIdx[compID]], rect);
769
42.1k
    if (tu.noResidual)
770
0
    {
771
0
      int sumAbs = 0;
772
0
      trCosts.push_back(TrCost(sumAbs, pos++));
773
0
      it++;
774
0
      continue;
775
0
    }
776
42.1k
    if (tu.mtsIdx[compID] == MTS_SKIP)
777
21.0k
    {
778
21.0k
      xTransformSkip(tu, compID, resiBuf, tempCoeff.buf);
779
21.0k
    }
780
21.0k
    else
781
21.0k
    {
782
21.0k
      xT(tu, compID, resiBuf, tempCoeff, width, height);
783
21.0k
    }
784
785
42.1k
    int sumAbs = 0;
786
7.40M
    for (int pos = 0; pos < width * height; pos++)
787
7.36M
    {
788
7.36M
      sumAbs += abs(tempCoeff.buf[pos]);
789
7.36M
    }
790
791
42.1k
    double scaleSAD = 1.0;
792
42.1k
    if (tu.mtsIdx[compID] == MTS_SKIP && ((floorLog2(width) + floorLog2(height)) & 1) == 1)
793
8.85k
    {
794
8.85k
      scaleSAD = 1.0 / 1.414213562;   // compensate for not scaling transform skip coefficients by 1/sqrt(2)
795
8.85k
    }
796
42.1k
    if (tu.mtsIdx[compID] == MTS_SKIP)
797
21.0k
    {
798
21.0k
      int trShift = getTransformShift(tu.cu->slice->sps->bitDepths[CH_L], rect.size(), tu.cu->slice->sps->getMaxLog2TrDynamicRange());
799
21.0k
      scaleSAD *= pow(2, trShift);
800
21.0k
    }
801
42.1k
    trCosts.push_back(TrCost(int(std::min<double>(sumAbs * scaleSAD, std::numeric_limits<int>::max())), pos++));
802
42.1k
    it++;
803
42.1k
  }
804
805
21.0k
  int                           numTests = 0;
806
21.0k
  TrCostList::iterator          itC      = trCosts.begin();
807
21.0k
  const double                  fac      = facBB[std::max(0, floorLog2(std::max(width, height)) - 2)];
808
21.0k
  const double                  thr      = fac * trCosts.begin()->first;
809
21.0k
  const double                  thrTS    = trCosts.begin()->first;
810
63.1k
  while (itC != trCosts.end())
811
42.1k
  {
812
42.1k
    const bool testTr               = itC->first <= (trModes->at(itC->second).first == 1 ? thrTS : thr) && numTests <= maxCand;
813
42.1k
    trModes->at(itC->second).second = testTr;
814
42.1k
    numTests += testTr;
815
42.1k
    itC++;
816
42.1k
  }
817
21.0k
}
818
819
uint32_t TrQuant::xGetLFNSTIntraMode( const Area& tuArea, const uint32_t dirMode )
820
2.12M
{
821
2.12M
  if (dirMode < 2)
822
1.19M
  {
823
1.19M
    return dirMode;
824
1.19M
  }
825
826
930k
  static const int modeShift[] = { 0, 6, 10, 12, 14, 15 };
827
828
930k
  const int width  = int(tuArea.width);
829
930k
  const int height = int(tuArea.height);
830
831
930k
  if (width > height && dirMode < 2 + modeShift[floorLog2(width) - floorLog2(height)])
832
272
  {
833
272
    return dirMode + (VDIA_IDX - 1) + (NUM_EXT_LUMA_MODE >> 1);
834
272
  }
835
929k
  else if (height > width && dirMode > VDIA_IDX - modeShift[floorLog2(height) - floorLog2(width)])
836
85.8k
  {
837
85.8k
    return dirMode - (VDIA_IDX + 1) + (NUM_EXT_LUMA_MODE >> 1) + NUM_LUMA_MODE;
838
85.8k
  }
839
840
843k
  return dirMode;
841
930k
}
842
843
844
bool TrQuant::xGetTransposeFlag(uint32_t intraMode)
845
2.12M
{
846
2.12M
  return ((intraMode >= NUM_LUMA_MODE) && (intraMode >= (NUM_LUMA_MODE + (NUM_EXT_LUMA_MODE >> 1))))
847
2.12M
         || ((intraMode < NUM_LUMA_MODE) && (intraMode > DIA_IDX));
848
2.12M
}
849
850
851
void TrQuant::xInvLfnst(const TransformUnit &tu, const ComponentID compID)
852
1.03M
{
853
1.03M
  const CompArea &area     = tu.blocks[compID];
854
1.03M
  const uint32_t  width    = area.width;
855
1.03M
  const uint32_t  height   = area.height;
856
1.03M
  const uint32_t  lfnstIdx = tu.cu->lfnstIdx;
857
1.03M
  if (lfnstIdx && tu.mtsIdx[compID] != MTS_SKIP && (CU::isSepTree(*tu.cu) ? true : isLuma(compID)))
858
629k
  {
859
629k
    const CodingUnit& cu = *tu.cs->getCU(area.pos(), toChannelType(compID), TREE_D);
860
629k
    const bool         whge3 = width >= 8 && height >= 8;
861
629k
    const ScanElement *scan =
862
629k
      whge3
863
629k
        ? g_coefTopLeftDiagScan8x8[Log2(width)] 
864
629k
        : getScanOrder(SCAN_GROUPED_4x4, Log2(area.width), Log2(area.height));
865
629k
    uint32_t intraMode = CU::getFinalIntraMode(cu, toChannelType(compID));
866
867
629k
    if (CU::isLMCMode( cu.intraDir[toChannelType(compID)]))
868
104k
    {
869
104k
      intraMode = CU::getCoLocatedIntraLumaMode(cu);
870
104k
    }
871
629k
    if (CU::isMIP(cu, toChannelType(compID)))
872
6.03k
    {
873
6.03k
      intraMode = PLANAR_IDX;
874
6.03k
    }
875
629k
    CHECK(intraMode >= NUM_INTRA_MODE - 1, "Invalid intra mode");
876
877
629k
    if (lfnstIdx < 3)
878
629k
    {
879
629k
      if (tu.cu->ispMode && isLuma(compID))
880
8.71k
      {
881
8.71k
        intraMode = xGetLFNSTIntraMode(tu.cu->blocks[compID], intraMode);
882
8.71k
      }
883
620k
      else
884
620k
        intraMode = xGetLFNSTIntraMode(tu.blocks[compID], intraMode);
885
629k
      bool      transposeFlag = xGetTransposeFlag(intraMode);
886
629k
      const int sbSize        = whge3 ? 8 : 4;
887
629k
      bool      tu4x4Flag     = (width == 4 && height == 4);
888
629k
      bool      tu8x8Flag     = (width == 8 && height == 8);
889
629k
      TCoeff *  lfnstTemp;
890
629k
      TCoeff *  coeffTemp;
891
629k
      int       y;
892
629k
      lfnstTemp                  = m_tempInMatrix;   // inverse spectral rearrangement
893
629k
      coeffTemp                  = m_plTempCoeff;
894
629k
      TCoeff *           dst     = lfnstTemp;
895
629k
      const ScanElement *scanPtr = scan;
896
10.6M
      for (y = 0; y < 16; y++)
897
10.0M
      {
898
10.0M
        *dst++ = coeffTemp[scanPtr->idx];
899
10.0M
        scanPtr++;
900
10.0M
      }
901
902
629k
      m_invLfnstNxN( m_tempInMatrix, m_tempOutMatrix, g_lfnstLut[intraMode], lfnstIdx - 1, sbSize, ( tu4x4Flag || tu8x8Flag ) ? 8 : 16 );
903
904
629k
      lfnstTemp = m_tempOutMatrix;   // inverse spectral rearrangement
905
906
629k
      if (transposeFlag)
907
57.4k
      {
908
57.4k
        if (sbSize == 4)
909
10.2k
        {
910
51.4k
          for (y = 0; y < 4; y++)
911
41.1k
          {
912
41.1k
            coeffTemp[0] = lfnstTemp[0];
913
41.1k
            coeffTemp[1] = lfnstTemp[4];
914
41.1k
            coeffTemp[2] = lfnstTemp[8];
915
41.1k
            coeffTemp[3] = lfnstTemp[12];
916
41.1k
            lfnstTemp++;
917
41.1k
            coeffTemp += width;
918
41.1k
          }
919
10.2k
        }
920
47.1k
        else   // ( sbSize == 8 )
921
47.1k
        {
922
424k
          for (y = 0; y < 8; y++)
923
376k
          {
924
376k
            coeffTemp[0] = lfnstTemp[0];
925
376k
            coeffTemp[1] = lfnstTemp[8];
926
376k
            coeffTemp[2] = lfnstTemp[16];
927
376k
            coeffTemp[3] = lfnstTemp[24];
928
376k
            if (y < 4)
929
188k
            {
930
188k
              coeffTemp[4] = lfnstTemp[32];
931
188k
              coeffTemp[5] = lfnstTemp[36];
932
188k
              coeffTemp[6] = lfnstTemp[40];
933
188k
              coeffTemp[7] = lfnstTemp[44];
934
188k
            }
935
376k
            lfnstTemp++;
936
376k
            coeffTemp += width;
937
376k
          }
938
47.1k
        }
939
57.4k
      }
940
571k
      else
941
571k
      {
942
4.29M
        for (y = 0; y < sbSize; y++)
943
3.72M
        {
944
3.72M
          uint32_t uiStride = (y < 4) ? sbSize : 4;
945
3.72M
          ::memcpy(coeffTemp, lfnstTemp, uiStride * sizeof(TCoeff));
946
3.72M
          lfnstTemp += uiStride;
947
3.72M
          coeffTemp += width;
948
3.72M
        }
949
571k
      }
950
629k
    }
951
629k
  }
952
1.03M
}
953
954
955
void TrQuant::xFwdLfnst(const TransformUnit &tu, const ComponentID compID, const bool loadTr)
956
2.52M
{
957
2.52M
  const CompArea &area     = tu.blocks[compID];
958
2.52M
  const uint32_t  width    = area.width;
959
2.52M
  const uint32_t  height   = area.height;
960
2.52M
  const uint32_t  lfnstIdx = tu.cu->lfnstIdx;
961
2.52M
  if (lfnstIdx && tu.mtsIdx[compID] != MTS_SKIP && (CU::isSepTree(*tu.cu) ? true : isLuma(compID)))
962
1.49M
  {
963
1.49M
    const CodingUnit& cu = *tu.cs->getCU(area.pos(), toChannelType(compID), TREE_D);
964
1.49M
    const bool         whge3 = width >= 8 && height >= 8;
965
1.49M
    const ScanElement *scan =
966
1.49M
      whge3
967
1.49M
        ? g_coefTopLeftDiagScan8x8[Log2(width)] 
968
1.49M
        : getScanOrder(SCAN_GROUPED_4x4, Log2(area.width), Log2(area.height));   
969
1.49M
    uint32_t intraMode = CU::getFinalIntraMode(cu, toChannelType(compID));
970
971
1.49M
    if (CU::isLMCMode(cu.intraDir[toChannelType(compID)]))
972
131k
    {
973
131k
      intraMode = CU::getCoLocatedIntraLumaMode(cu);
974
131k
    }
975
1.49M
    if (CU::isMIP(cu, toChannelType(compID)))
976
10.1k
    {
977
10.1k
      intraMode = PLANAR_IDX;
978
10.1k
    }
979
1.49M
    CHECK(intraMode >= NUM_INTRA_MODE - 1, "Invalid intra mode");
980
981
1.49M
    if (lfnstIdx < 3)
982
1.49M
    {
983
1.49M
      if (tu.cu->ispMode && isLuma(compID))
984
13.9k
      {
985
13.9k
        intraMode = xGetLFNSTIntraMode(tu.cu->blocks[compID], intraMode);
986
13.9k
      }
987
1.47M
      else
988
1.47M
      {
989
1.47M
        intraMode = xGetLFNSTIntraMode(tu.blocks[compID], intraMode);
990
1.47M
      }
991
1.49M
      bool      transposeFlag = xGetTransposeFlag(intraMode);
992
1.49M
      const int sbSize        = whge3 ? 8 : 4;
993
1.49M
      bool      tu4x4Flag     = (width == 4 && height == 4);
994
1.49M
      bool      tu8x8Flag     = (width == 8 && height == 8);
995
1.49M
      TCoeff*   lfnstTemp;
996
1.49M
      TCoeff*   coeffTemp;
997
1.49M
      TCoeff*   tempCoeff     = loadTr ? m_mtsCoeffs[tu.mtsIdx[compID]] : m_plTempCoeff;
998
999
1.49M
      int y;
1000
1.49M
      lfnstTemp = m_tempInMatrix;   // forward low frequency non-separable transform
1001
1.49M
      coeffTemp = tempCoeff;
1002
1003
1.49M
      if (transposeFlag)
1004
321k
      {
1005
321k
        if (sbSize == 4)
1006
89.3k
        {
1007
446k
          for (y = 0; y < 4; y++)
1008
357k
          {
1009
357k
            lfnstTemp[0]  = coeffTemp[0];
1010
357k
            lfnstTemp[4]  = coeffTemp[1];
1011
357k
            lfnstTemp[8]  = coeffTemp[2];
1012
357k
            lfnstTemp[12] = coeffTemp[3];
1013
357k
            lfnstTemp++;
1014
357k
            coeffTemp += width;
1015
357k
          }
1016
89.3k
        }
1017
231k
        else   // ( sbSize == 8 )
1018
231k
        {
1019
2.08M
          for (y = 0; y < 8; y++)
1020
1.85M
          {
1021
1.85M
            lfnstTemp[0]  = coeffTemp[0];
1022
1.85M
            lfnstTemp[8]  = coeffTemp[1];
1023
1.85M
            lfnstTemp[16] = coeffTemp[2];
1024
1.85M
            lfnstTemp[24] = coeffTemp[3];
1025
1.85M
            if (y < 4)
1026
927k
            {
1027
927k
              lfnstTemp[32] = coeffTemp[4];
1028
927k
              lfnstTemp[36] = coeffTemp[5];
1029
927k
              lfnstTemp[40] = coeffTemp[6];
1030
927k
              lfnstTemp[44] = coeffTemp[7];
1031
927k
            }
1032
1.85M
            lfnstTemp++;
1033
1.85M
            coeffTemp += width;
1034
1.85M
          }
1035
231k
        }
1036
321k
      }
1037
1.17M
      else
1038
1.17M
      {
1039
8.91M
        for (y = 0; y < sbSize; y++)
1040
7.74M
        {
1041
7.74M
          uint32_t uiStride = (y < 4) ? sbSize : 4;
1042
7.74M
          ::memcpy(lfnstTemp, coeffTemp, uiStride * sizeof(TCoeff));
1043
7.74M
          lfnstTemp += uiStride;
1044
7.74M
          coeffTemp += width;
1045
7.74M
        }
1046
1.17M
      }
1047
1048
1.49M
      m_fwdLfnstNxN( m_tempInMatrix, m_tempOutMatrix, g_lfnstLut[intraMode], lfnstIdx - 1, sbSize, ( tu4x4Flag || tu8x8Flag ) ? 8 : 16 );
1049
1050
1.49M
      lfnstTemp                        = m_tempOutMatrix;   // forward spectral rearrangement
1051
1.49M
      coeffTemp                        = tempCoeff;
1052
1.49M
      const ScanElement *scanPtr       = scan;
1053
1.49M
      int                lfnstCoeffNum = (sbSize == 4) ? sbSize * sbSize : 48;
1054
57.2M
      for (y = 0; y < lfnstCoeffNum; y++)
1055
55.7M
      {
1056
55.7M
        coeffTemp[scanPtr->idx] = *lfnstTemp++;
1057
55.7M
        scanPtr++;
1058
55.7M
      }
1059
1.49M
    }
1060
1.49M
  }
1061
2.52M
}
1062
1063
void TrQuant::xTransformSkip(const TransformUnit& tu, const ComponentID& compID, const CPelBuf& resi, TCoeff* psCoeff)
1064
144k
{
1065
144k
  const CompArea& rect = tu.blocks[compID];
1066
144k
  const uint32_t width = rect.width;
1067
144k
  const uint32_t height = rect.height;
1068
1069
144k
#if ENABLE_SIMD_TRAFO
1070
144k
  if( ( width & 3 ) == 0 )
1071
144k
  {
1072
144k
    ( width & 7 ? g_tCoeffOps.cpyCoeff4 : g_tCoeffOps.cpyCoeff8 )( resi.buf, resi.stride, psCoeff, width, height );
1073
144k
    return;
1074
144k
  }
1075
0
#endif
1076
1077
0
  for (uint32_t y = 0, coefficientIndex = 0; y < height; y++)
1078
0
  {
1079
0
    for (uint32_t x = 0; x < width; x++, coefficientIndex++)
1080
0
    {
1081
0
      psCoeff[coefficientIndex] = TCoeff(resi.at(x, y));
1082
0
    }
1083
0
  }
1084
0
}
1085
} // namespace vvenc
1086
1087
//! \}
1088