Coverage Report

Created: 2026-07-16 06:32

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
354M
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.08M
{
97
1.08M
  const Pel*  cb  = resCb.buf;
98
1.08M
  const Pel*  cr  = resCr.buf;
99
1.08M
  Pel*        c1  = resC1.buf;
100
1.08M
  Pel*        c2  = resC2.buf;
101
1.08M
  int64_t     d1  = 0;
102
1.08M
  int64_t     d2  = 0;
103
14.3M
  for( SizeType y = 0; y < resCb.height; y++, cb += resCb.stride, cr += resCr.stride, c1 += resC1.stride, c2 += resC2.stride )
104
13.3M
  {
105
190M
    for( SizeType x = 0; x < resCb.width; x++ )
106
177M
    {
107
177M
      int cbx = cb[x], crx = cr[x];
108
177M
      if      ( signedMode ==  1 )
109
44.3M
      {
110
44.3M
        c1[x] = Pel( ( 4*cbx + 2*crx ) / 5 );
111
44.3M
        d1   += square( cbx - c1[x] ) + square( crx - (c1[x]>>1) );
112
44.3M
      }
113
132M
      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
132M
      else if ( signedMode ==  2 )
119
44.3M
      {
120
44.3M
        c1[x] = Pel( ( cbx + crx ) / 2 );
121
44.3M
        d1   += square( cbx - c1[x] ) + square( crx - c1[x] );
122
44.3M
      }
123
88.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
88.6M
      else if ( signedMode ==  3 )
129
44.3M
      {
130
44.3M
        c2[x] = Pel( ( 4*crx + 2*cbx ) / 5 );
131
44.3M
        d1   += square( cbx - (c2[x]>>1) ) + square( crx - c2[x] );
132
44.3M
      }
133
44.3M
      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
44.3M
      else
139
44.3M
      {
140
44.3M
        d1   += square( cbx );
141
44.3M
        d2   += square( crx );
142
44.3M
      }
143
177M
    }
144
13.3M
  }
145
1.08M
  return std::make_pair(d1,d2);
146
1.08M
}
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
270k
{
97
270k
  const Pel*  cb  = resCb.buf;
98
270k
  const Pel*  cr  = resCr.buf;
99
270k
  Pel*        c1  = resC1.buf;
100
270k
  Pel*        c2  = resC2.buf;
101
270k
  int64_t     d1  = 0;
102
270k
  int64_t     d2  = 0;
103
3.59M
  for( SizeType y = 0; y < resCb.height; y++, cb += resCb.stride, cr += resCr.stride, c1 += resC1.stride, c2 += resC2.stride )
104
3.32M
  {
105
47.6M
    for( SizeType x = 0; x < resCb.width; x++ )
106
44.3M
    {
107
44.3M
      int cbx = cb[x], crx = cr[x];
108
44.3M
      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
44.3M
      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
44.3M
      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
44.3M
      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
44.3M
      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
44.3M
      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
44.3M
      else
139
44.3M
      {
140
44.3M
        d1   += square( cbx );
141
44.3M
        d2   += square( crx );
142
44.3M
      }
143
44.3M
    }
144
3.32M
  }
145
270k
  return std::make_pair(d1,d2);
146
270k
}
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
270k
{
97
270k
  const Pel*  cb  = resCb.buf;
98
270k
  const Pel*  cr  = resCr.buf;
99
270k
  Pel*        c1  = resC1.buf;
100
270k
  Pel*        c2  = resC2.buf;
101
270k
  int64_t     d1  = 0;
102
270k
  int64_t     d2  = 0;
103
3.59M
  for( SizeType y = 0; y < resCb.height; y++, cb += resCb.stride, cr += resCr.stride, c1 += resC1.stride, c2 += resC2.stride )
104
3.32M
  {
105
47.6M
    for( SizeType x = 0; x < resCb.width; x++ )
106
44.3M
    {
107
44.3M
      int cbx = cb[x], crx = cr[x];
108
44.3M
      if      ( signedMode ==  1 )
109
44.3M
      {
110
44.3M
        c1[x] = Pel( ( 4*cbx + 2*crx ) / 5 );
111
44.3M
        d1   += square( cbx - c1[x] ) + square( crx - (c1[x]>>1) );
112
44.3M
      }
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
44.3M
    }
144
3.32M
  }
145
270k
  return std::make_pair(d1,d2);
146
270k
}
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
270k
{
97
270k
  const Pel*  cb  = resCb.buf;
98
270k
  const Pel*  cr  = resCr.buf;
99
270k
  Pel*        c1  = resC1.buf;
100
270k
  Pel*        c2  = resC2.buf;
101
270k
  int64_t     d1  = 0;
102
270k
  int64_t     d2  = 0;
103
3.59M
  for( SizeType y = 0; y < resCb.height; y++, cb += resCb.stride, cr += resCr.stride, c1 += resC1.stride, c2 += resC2.stride )
104
3.32M
  {
105
47.6M
    for( SizeType x = 0; x < resCb.width; x++ )
106
44.3M
    {
107
44.3M
      int cbx = cb[x], crx = cr[x];
108
44.3M
      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
44.3M
      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
44.3M
      else if ( signedMode ==  2 )
119
44.3M
      {
120
44.3M
        c1[x] = Pel( ( cbx + crx ) / 2 );
121
44.3M
        d1   += square( cbx - c1[x] ) + square( crx - c1[x] );
122
44.3M
      }
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
44.3M
    }
144
3.32M
  }
145
270k
  return std::make_pair(d1,d2);
146
270k
}
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
270k
{
97
270k
  const Pel*  cb  = resCb.buf;
98
270k
  const Pel*  cr  = resCr.buf;
99
270k
  Pel*        c1  = resC1.buf;
100
270k
  Pel*        c2  = resC2.buf;
101
270k
  int64_t     d1  = 0;
102
270k
  int64_t     d2  = 0;
103
3.59M
  for( SizeType y = 0; y < resCb.height; y++, cb += resCb.stride, cr += resCr.stride, c1 += resC1.stride, c2 += resC2.stride )
104
3.32M
  {
105
47.6M
    for( SizeType x = 0; x < resCb.width; x++ )
106
44.3M
    {
107
44.3M
      int cbx = cb[x], crx = cr[x];
108
44.3M
      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
44.3M
      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
44.3M
      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
44.3M
      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
44.3M
      else if ( signedMode ==  3 )
129
44.3M
      {
130
44.3M
        c2[x] = Pel( ( 4*crx + 2*cbx ) / 5 );
131
44.3M
        d1   += square( cbx - (c2[x]>>1) ) + square( crx - c2[x] );
132
44.3M
      }
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
44.3M
    }
144
3.32M
  }
145
270k
  return std::make_pair(d1,d2);
146
270k
}
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
267k
{
150
267k
  Pel*  cb  = resCb.buf;
151
267k
  Pel*  cr  = resCr.buf;
152
3.55M
  for( SizeType y = 0; y < resCb.height; y++, cb += resCb.stride, cr += resCr.stride )
153
3.28M
  {
154
47.1M
    for( SizeType x = 0; x < resCb.width; x++ )
155
43.8M
    {
156
43.8M
      if      ( signedMode ==  1 )  { cr[x] =  cb[x] >> 1;  }
157
43.8M
      else if ( signedMode == -1 )  { cr[x] = -cb[x] >> 1;  }
158
43.8M
      else if ( signedMode ==  2 )  { cr[x] =  cb[x]; }
159
223k
      else if ( signedMode == -2 )  { cr[x] = -cb[x]; }
160
223k
      else if ( signedMode ==  3 )  { cb[x] =  cr[x] >> 1; }
161
0
      else if ( signedMode == -3 )  { cb[x] = -cr[x] >> 1; }
162
43.8M
    }
163
3.28M
  }
164
267k
}
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
265k
{
150
265k
  Pel*  cb  = resCb.buf;
151
265k
  Pel*  cr  = resCr.buf;
152
3.53M
  for( SizeType y = 0; y < resCb.height; y++, cb += resCb.stride, cr += resCr.stride )
153
3.26M
  {
154
46.9M
    for( SizeType x = 0; x < resCb.width; x++ )
155
43.6M
    {
156
43.6M
      if      ( signedMode ==  1 )  { cr[x] =  cb[x] >> 1;  }
157
43.6M
      else if ( signedMode == -1 )  { cr[x] = -cb[x] >> 1;  }
158
43.6M
      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
43.6M
    }
163
3.26M
  }
164
265k
}
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
1.79k
{
150
1.79k
  Pel*  cb  = resCb.buf;
151
1.79k
  Pel*  cr  = resCr.buf;
152
22.0k
  for( SizeType y = 0; y < resCb.height; y++, cb += resCb.stride, cr += resCr.stride )
153
20.2k
  {
154
243k
    for( SizeType x = 0; x < resCb.width; x++ )
155
223k
    {
156
223k
      if      ( signedMode ==  1 )  { cr[x] =  cb[x] >> 1;  }
157
223k
      else if ( signedMode == -1 )  { cr[x] = -cb[x] >> 1;  }
158
223k
      else if ( signedMode ==  2 )  { cr[x] =  cb[x]; }
159
223k
      else if ( signedMode == -2 )  { cr[x] = -cb[x]; }
160
223k
      else if ( signedMode ==  3 )  { cb[x] =  cr[x] >> 1; }
161
0
      else if ( signedMode == -3 )  { cb[x] = -cr[x] >> 1; }
162
223k
    }
163
20.2k
  }
164
1.79k
}
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.18M
{
168
1.18M
  const int8_t *trMat  = (size > 4) ? g_lfnstFwd8x8[mode][index][0] : g_lfnstFwd4x4[mode][index][0];
169
1.18M
  const int     trSize = (size > 4) ? 48 : 16;
170
1.18M
  int           coef;
171
1.18M
  int *         out = dst;
172
173
18.4M
  for (int j = 0; j < zeroOutSize; j++)
174
17.2M
  {
175
17.2M
    int *         srcPtr   = src;
176
17.2M
    const int8_t *trMatTmp = trMat;
177
17.2M
    coef                   = 0;
178
650M
    for (int i = 0; i < trSize; i++)
179
633M
    {
180
633M
      coef += *srcPtr++ * *trMatTmp++;
181
633M
    }
182
17.2M
    *out++ = (coef + 64) >> 7;
183
17.2M
    trMat += trSize;
184
17.2M
  }
185
186
1.18M
  ::memset(out, 0, (trSize - zeroOutSize) * sizeof(int));
187
1.18M
}
188
189
190
void xInvLfnstNxNCore(int *src, int *dst, const uint32_t mode, const uint32_t index, const uint32_t size, int zeroOutSize)
191
509k
{
192
509k
  int           maxLog2TrDynamicRange = 15;
193
509k
  const TCoeff  outputMinimum         = -(1 << maxLog2TrDynamicRange);
194
509k
  const TCoeff  outputMaximum         = (1 << maxLog2TrDynamicRange) - 1;
195
509k
  const int8_t *trMat                 = (size > 4) ? g_lfnstInv8x8[mode][index][0] : g_lfnstInv4x4[mode][index][0];
196
509k
  const int     trSize                = (size > 4) ? 48 : 16;
197
509k
  int           resi;
198
509k
  int *         out                   = dst;
199
200
18.8M
  for( int j = 0; j < trSize; j++, trMat += 16 )
201
18.3M
  {
202
18.3M
    resi = 0;
203
18.3M
    const int8_t* trMatTmp = trMat;
204
18.3M
    int*          srcPtr   = src;
205
206
278M
    for( int i = 0; i < zeroOutSize; i++ )
207
259M
    {
208
259M
      resi += *srcPtr++ * *trMatTmp++;
209
259M
    }
210
211
18.3M
    *out++ = Clip3( outputMinimum, outputMaximum, ( int ) ( resi + 64 ) >> 7 );
212
18.3M
  }
213
509k
}
214
215
// ====================================================================================================================
216
// TrQuant class member functions
217
// ====================================================================================================================
218
19.4k
TrQuant::TrQuant() : m_scalingListEnabled(false), m_quant( nullptr )
219
19.4k
{
220
  // allocate temporary buffers
221
19.4k
  m_plTempCoeff = ( TCoeff* ) xMalloc( TCoeff, MAX_TB_SIZEY * MAX_TB_SIZEY );
222
19.4k
  m_tmp         = ( TCoeff* ) xMalloc( TCoeff, MAX_TB_SIZEY * MAX_TB_SIZEY );
223
19.4k
  m_blk         = ( TCoeff* ) xMalloc( TCoeff, MAX_TB_SIZEY * MAX_TB_SIZEY );
224
225
136k
  for( int i = 0; i < NUM_TRAFO_MODES_MTS; i++ )
226
116k
  {
227
116k
    m_mtsCoeffs[i] = ( TCoeff* ) xMalloc( TCoeff, MAX_TB_SIZEY * MAX_TB_SIZEY );
228
116k
  }
229
230
19.4k
  {
231
19.4k
    m_invICT      = m_invICTMem + maxAbsIctMode;
232
19.4k
    m_invICT[ 0]  = invTransformCbCr< 0>;
233
19.4k
    m_invICT[ 1]  = invTransformCbCr< 1>;
234
19.4k
    m_invICT[-1]  = invTransformCbCr<-1>;
235
19.4k
    m_invICT[ 2]  = invTransformCbCr< 2>;
236
19.4k
    m_invICT[-2]  = invTransformCbCr<-2>;
237
19.4k
    m_invICT[ 3]  = invTransformCbCr< 3>;
238
19.4k
    m_invICT[-3]  = invTransformCbCr<-3>;
239
19.4k
    m_fwdICT      = m_fwdICTMem + maxAbsIctMode;
240
19.4k
    m_fwdICT[ 0]  = fwdTransformCbCr< 0>;
241
19.4k
    m_fwdICT[ 1]  = fwdTransformCbCr< 1>;
242
19.4k
    m_fwdICT[-1]  = fwdTransformCbCr<-1>;
243
19.4k
    m_fwdICT[ 2]  = fwdTransformCbCr< 2>;
244
19.4k
    m_fwdICT[-2]  = fwdTransformCbCr<-2>;
245
19.4k
    m_fwdICT[ 3]  = fwdTransformCbCr< 3>;
246
19.4k
    m_fwdICT[-3]  = fwdTransformCbCr<-3>;
247
19.4k
  }
248
249
19.4k
  m_invLfnstNxN = xInvLfnstNxNCore;
250
19.4k
  m_fwdLfnstNxN = xFwdLfnstNxNCore;
251
252
#if defined( TARGET_SIMD_X86 ) && ENABLE_SIMD_TRAFO
253
  initTrQuantX86();
254
#endif
255
19.4k
}
256
257
TrQuant::~TrQuant()
258
19.4k
{
259
19.4k
  if( m_quant )
260
19.4k
  {
261
19.4k
    delete m_quant;
262
19.4k
    m_quant = nullptr;
263
19.4k
  }
264
265
  // delete temporary buffers
266
19.4k
  if( m_plTempCoeff )
267
19.4k
  {
268
19.4k
    xFree( m_plTempCoeff );
269
19.4k
    m_plTempCoeff = nullptr;
270
19.4k
  }
271
272
19.4k
  if( m_blk )
273
19.4k
  {
274
19.4k
    xFree( m_blk );
275
19.4k
    m_blk = nullptr;
276
19.4k
  }
277
278
19.4k
  if( m_tmp )
279
19.4k
  {
280
19.4k
    xFree( m_tmp );
281
19.4k
    m_tmp = nullptr;
282
19.4k
  }
283
284
136k
  for( int i = 0; i < NUM_TRAFO_MODES_MTS; i++ )
285
116k
  {
286
116k
     xFree( m_mtsCoeffs[i] );
287
116k
  }
288
19.4k
}
289
290
void TrQuant::xDeQuant(const TransformUnit& tu,
291
                             CoeffBuf      &dstCoeff,
292
                       const ComponentID   &compID,
293
                       const QpParam       &cQP)
294
836k
{
295
836k
  PROFILER_SCOPE_AND_STAGE( 1, _TPROF, P_DEQUANT );
296
836k
  m_quant->dequant( tu, dstCoeff, compID, cQP );
297
836k
}
298
299
void TrQuant::init( const Quant* otherQuant,
300
                    const int  rdoq,
301
                    const bool bUseRDOQTS,
302
                    const bool scalingListsEnabled,
303
                    const bool bEnc,
304
                    const int  thrVal
305
)
306
19.4k
{
307
19.4k
  m_bEnc = bEnc;
308
309
19.4k
  delete m_quant;
310
19.4k
  m_quant = nullptr;
311
312
19.4k
  m_quant = new(std::nothrow) DepQuant( otherQuant, bEnc, scalingListsEnabled );
313
19.4k
  CHECK( !m_quant, "allocation failed" );
314
19.4k
  m_quant->init( rdoq, bUseRDOQTS, thrVal );
315
19.4k
}
316
317
318
void TrQuant::invTransformNxN( TransformUnit& tu, const ComponentID compID, PelBuf& pResi, const QpParam& cQP )
319
836k
{
320
836k
  const CompArea& area    = tu.blocks[compID];
321
836k
  const uint32_t uiWidth  = area.width;
322
836k
  const uint32_t uiHeight = area.height;
323
324
836k
  CHECK( uiWidth > tu.cs->sps->getMaxTbSize() || uiHeight > tu.cs->sps->getMaxTbSize(), "Maximal allowed transformation size exceeded!" );
325
326
836k
  {
327
836k
    CoeffBuf tempCoeff = CoeffBuf( m_plTempCoeff, area );
328
836k
    xDeQuant( tu, tempCoeff, compID, cQP );
329
330
836k
    DTRACE_COEFF_BUF( D_TCOEFF, tempCoeff, tu, tu.cu->predMode, compID );
331
332
836k
    if (tu.cs->sps->LFNST)
333
836k
    {
334
836k
      xInvLfnst(tu, compID);
335
836k
    }
336
836k
    if (tu.mtsIdx[compID] == MTS_SKIP)
337
49.3k
    {
338
49.3k
      xITransformSkip(tempCoeff, pResi, tu, compID);
339
49.3k
    }
340
787k
    else
341
787k
    {
342
787k
      xIT(tu, compID, tempCoeff, pResi);
343
787k
    }
344
836k
  }
345
346
  //DTRACE_BLOCK_COEFF(tu.getCoeffs(compID), tu, tu.cu->predMode, compID);
347
836k
  DTRACE_PEL_BUF( D_RESIDUALS, pResi, tu, tu.cu->predMode, compID);
348
836k
}
349
350
std::pair<int64_t,int64_t> TrQuant::fwdTransformICT( const TransformUnit& tu, const PelBuf& resCb, const PelBuf& resCr, PelBuf& resC1, PelBuf& resC2, int jointCbCr )
351
1.08M
{
352
1.08M
  CHECK( Size(resCb) != Size(resCr), "resCb and resCr have different sizes" );
353
1.08M
  CHECK( Size(resCb) != Size(resC1), "resCb and resC1 have different sizes" );
354
1.08M
  CHECK( Size(resCb) != Size(resC2), "resCb and resC2 have different sizes" );
355
1.08M
  return (*m_fwdICT[ TU::getICTMode(tu, jointCbCr) ])( resCb, resCr, resC1, resC2 );
356
1.08M
}
357
358
void TrQuant::invTransformICT( const TransformUnit& tu, PelBuf& resCb, PelBuf& resCr )
359
267k
{
360
267k
  CHECK( Size(resCb) != Size(resCr), "resCb and resCr have different sizes" );
361
267k
  (*m_invICT[ TU::getICTMode(tu) ])( resCb, resCr );
362
267k
}
363
364
std::vector<int> TrQuant::selectICTCandidates( const TransformUnit& tu, CompStorage* resCb, CompStorage* resCr )
365
270k
{
366
270k
  CHECK( !resCb[0].valid() || !resCr[0].valid(), "standard components are not valid" );
367
368
270k
  if( !CU::isIntra( *tu.cu ) )
369
0
  {
370
0
    int cbfMask = 3;
371
0
    fwdTransformICT( tu, resCb[0], resCr[0], resCb[cbfMask], resCr[cbfMask], cbfMask );
372
0
    std::vector<int> cbfMasksToTest;
373
0
    cbfMasksToTest.push_back( cbfMask );
374
0
    return cbfMasksToTest;
375
0
  }
376
377
270k
  std::pair<int64_t,int64_t> pairDist[4];
378
1.35M
  for( int cbfMask = 0; cbfMask < 4; cbfMask++ )
379
1.08M
  {
380
1.08M
    pairDist[cbfMask] = fwdTransformICT( tu, resCb[0], resCr[0], resCb[cbfMask], resCr[cbfMask], cbfMask );
381
1.08M
  }
382
383
270k
  std::vector<int> cbfMasksToTest;
384
270k
  int64_t minDist1  = std::min<int64_t>( pairDist[0].first, pairDist[0].second );
385
270k
  int64_t minDist2  = std::numeric_limits<int64_t>::max();
386
270k
  int     cbfMask1  = 0;
387
270k
  int     cbfMask2  = 0;
388
270k
  for( int cbfMask : { 1, 2, 3 } )
389
812k
  {
390
812k
    if( pairDist[cbfMask].first < minDist1 )
391
536k
    {
392
536k
      cbfMask2  = cbfMask1; minDist2  = minDist1;
393
536k
      cbfMask1  = cbfMask;  minDist1  = pairDist[cbfMask1].first;
394
536k
    }
395
276k
    else if( pairDist[cbfMask].first < minDist2 )
396
270k
    {
397
270k
      cbfMask2  = cbfMask;  minDist2  = pairDist[cbfMask2].first;
398
270k
    }
399
812k
  }
400
270k
  if( cbfMask1 )
401
270k
  {
402
270k
    cbfMasksToTest.push_back( cbfMask1 );
403
270k
  }
404
270k
  if( cbfMask2 && ( ( minDist2 < (9*minDist1)/8 ) || ( !cbfMask1 && minDist2 < (3*minDist1)/2 ) ) )
405
0
  {
406
0
    cbfMasksToTest.push_back( cbfMask2 );
407
0
  }
408
409
270k
  return cbfMasksToTest;
410
270k
}
411
412
413
414
// ------------------------------------------------------------------------------------------------
415
// Logical transform
416
// ------------------------------------------------------------------------------------------------
417
void TrQuant::xSetTrTypes( const TransformUnit& tu, const ComponentID compID, const int width, const int height, int &trTypeHor, int &trTypeVer )
418
2.69M
{
419
2.69M
  const bool isISP = CU::isIntra(*tu.cu) && tu.cu->ispMode && isLuma(compID);
420
2.69M
  if (isISP && tu.cu->lfnstIdx)
421
19.2k
  {
422
19.2k
    return;
423
19.2k
  }
424
2.67M
  if (!tu.cs->sps->MTS)
425
0
  {
426
0
    return;
427
0
  }
428
2.67M
  if (CU::isIntra(*tu.cu) && isLuma(compID) && ((tu.cs->sps->getUseImplicitMTS() && tu.cu->lfnstIdx == 0 && tu.cu->mipFlag == 0) || tu.cu->ispMode))
429
84.1k
  {
430
84.1k
    if (width >= 4 && width <= 16)
431
38.5k
      trTypeHor = DST7;
432
84.1k
    if (height >= 4 && height <= 16)
433
37.3k
      trTypeVer = DST7;
434
84.1k
  }
435
2.59M
  else if( tu.cs->sps->MTS && tu.cu->sbtInfo && isLuma(compID)/*isSBT*/ )
436
0
  {
437
0
    const uint8_t sbtIdx = CU::getSbtIdx( tu.cu->sbtInfo );
438
0
    const uint8_t sbtPos = CU::getSbtPos( tu.cu->sbtInfo );
439
440
0
    if( sbtIdx == SBT_VER_HALF || sbtIdx == SBT_VER_QUAD )
441
0
    {
442
0
      assert( tu.lwidth() <= MTS_INTER_MAX_CU_SIZE );
443
0
      if( tu.lheight() > MTS_INTER_MAX_CU_SIZE )
444
0
      {
445
0
        trTypeHor = trTypeVer = DCT2;
446
0
      }
447
0
      else
448
0
      {
449
0
        if( sbtPos == SBT_POS0 )  { trTypeHor = DCT8;  trTypeVer = DST7; }
450
0
        else                      { trTypeHor = DST7;  trTypeVer = DST7; }
451
0
      }
452
0
    }
453
0
    else
454
0
    {
455
0
      assert( tu.lheight() <= MTS_INTER_MAX_CU_SIZE );
456
0
      if( tu.lwidth() > MTS_INTER_MAX_CU_SIZE )
457
0
      {
458
0
        trTypeHor = trTypeVer = DCT2;
459
0
      }
460
0
      else
461
0
      {
462
0
        if( sbtPos == SBT_POS0 )  { trTypeHor = DST7;  trTypeVer = DCT8; }
463
0
        else                      { trTypeHor = DST7;  trTypeVer = DST7; }
464
0
      }
465
0
    }
466
0
  }
467
2.67M
  const bool isExplicitMTS = (CU::isIntra(*tu.cu) ? tu.cs->sps->MTS : tu.cs->sps->MTSInter && CU::isInter(*tu.cu)) && isLuma(compID);
468
2.67M
  if (isExplicitMTS)
469
198k
  {
470
198k
    if (tu.mtsIdx[compID] > MTS_SKIP)
471
0
    {
472
0
      int indHor = (tu.mtsIdx[compID] - MTS_DST7_DST7) & 1;
473
0
      int indVer = (tu.mtsIdx[compID] - MTS_DST7_DST7) >> 1;
474
0
      trTypeHor  = indHor ? DCT8 : DST7;
475
0
      trTypeVer  = indVer ? DCT8 : DST7;
476
0
    }
477
198k
  }
478
2.67M
}
479
480
481
void TrQuant::xT( const TransformUnit& tu, const ComponentID compID, const CPelBuf& resi, CoeffBuf& dstCoeff, const int width, const int height )
482
1.91M
{
483
1.91M
  PROFILER_SCOPE_AND_STAGE( 1, _TPROF, P_TRAFO );
484
485
1.91M
  const unsigned maxLog2TrDynamicRange  = tu.cs->sps->getMaxLog2TrDynamicRange();
486
1.91M
  const unsigned bitDepth               = tu.cs->sps->bitDepths[toChannelType( compID )];
487
1.91M
  const int      TRANSFORM_MATRIX_SHIFT = g_transformMatrixShift[TRANSFORM_FORWARD];
488
1.91M
  const uint32_t transformWidthIndex    = Log2(width ) - 1;  // nLog2WidthMinus1, since transform start from 2-point
489
1.91M
  const uint32_t transformHeightIndex   = Log2(height) - 1;  // nLog2HeightMinus1, since transform start from 2-point
490
491
1.91M
  int trTypeHor = DCT2;
492
1.91M
  int trTypeVer = DCT2;
493
494
1.91M
  xSetTrTypes( tu, compID, width, height, trTypeHor, trTypeVer );
495
496
1.91M
  int  skipWidth  = ( trTypeHor != DCT2 && width  == 32 ) ? 16 : width  > JVET_C0024_ZERO_OUT_TH ? width  - JVET_C0024_ZERO_OUT_TH : 0;
497
1.91M
  int  skipHeight = ( trTypeVer != DCT2 && height == 32 ) ? 16 : height > JVET_C0024_ZERO_OUT_TH ? height - JVET_C0024_ZERO_OUT_TH : 0;
498
499
1.91M
  if( tu.cu->lfnstIdx )
500
1.18M
  {
501
1.18M
    if ((width == 4 && height > 4) || (width > 4 && height == 4))
502
342k
    {
503
342k
      skipWidth  = width - 4;
504
342k
      skipHeight = height - 4;
505
342k
    }
506
846k
    else if ((width >= 8 && height >= 8))
507
769k
    {
508
769k
      skipWidth  = width - 8;
509
769k
      skipHeight = height - 8;
510
769k
    }
511
1.18M
  }
512
513
1.91M
  TCoeff* block = m_blk;
514
1.91M
  TCoeff* tmp   = m_tmp;
515
516
1.91M
  const Pel* resiBuf    = resi.buf;
517
1.91M
  const int  resiStride = resi.stride;
518
519
1.91M
#if ENABLE_SIMD_TRAFO
520
1.91M
  if( width & 3 )
521
0
#endif
522
0
  {
523
0
    for( int y = 0; y < height; y++ )
524
0
    {
525
0
      for( int x = 0; x < width; x++ )
526
0
      {
527
0
        block[( y * width ) + x] = resiBuf[( y * resiStride ) + x];
528
0
      }
529
0
    }
530
0
  }
531
1.91M
#if ENABLE_SIMD_TRAFO
532
1.91M
  else if( width & 7 )
533
369k
  {
534
369k
    g_tCoeffOps.cpyCoeff4( resiBuf, resiStride, block, width, height );
535
369k
  }
536
1.54M
  else
537
1.54M
  {
538
1.54M
    g_tCoeffOps.cpyCoeff8( resiBuf, resiStride, block, width, height );
539
1.54M
  }
540
1.91M
#endif //ENABLE_SIMD_TRAFO
541
542
1.91M
  if (width > 1 && height > 1)
543
1.90M
  {
544
1.90M
    const int shift_1st = ((Log2(width )) + bitDepth + TRANSFORM_MATRIX_SHIFT) - maxLog2TrDynamicRange;
545
1.90M
    const int shift_2nd =  (Log2(height))            + TRANSFORM_MATRIX_SHIFT;
546
1.90M
    CHECK( shift_1st < 0, "Negative shift" );
547
1.90M
    CHECK( shift_2nd < 0, "Negative shift" );
548
1.90M
    fastFwdTrans[trTypeHor][transformWidthIndex](block, tmp, shift_1st, height, 0, skipWidth);
549
1.90M
    fastFwdTrans[trTypeVer][transformHeightIndex](tmp, dstCoeff.buf, shift_2nd, width, skipWidth, skipHeight);
550
1.90M
  }
551
325
  else if (height == 1)   // 1-D horizontal transform
552
344
  {
553
344
    const int shift = ((Log2(width )) + bitDepth + TRANSFORM_MATRIX_SHIFT) - maxLog2TrDynamicRange;
554
344
    CHECK( shift < 0, "Negative shift" );
555
344
    fastFwdTrans[trTypeHor][transformWidthIndex](block, dstCoeff.buf, shift, 1, 0, skipWidth);
556
344
  }
557
18.4E
  else   // if (iWidth == 1) //1-D vertical transform
558
18.4E
  {
559
18.4E
    int shift = ((floorLog2(height)) + bitDepth + TRANSFORM_MATRIX_SHIFT) - maxLog2TrDynamicRange;
560
18.4E
    CHECK(shift < 0, "Negative shift");
561
18.4E
    CHECKD((transformHeightIndex < 0), "There is a problem with the height.");
562
18.4E
    fastFwdTrans[trTypeVer][transformHeightIndex](block, dstCoeff.buf, shift, 1, 0, skipHeight);
563
18.4E
  }
564
1.91M
}
565
566
567
void TrQuant::xIT( const TransformUnit& tu, const ComponentID compID, const CCoeffBuf& pCoeff, PelBuf& pResidual )
568
787k
{
569
787k
  PROFILER_SCOPE_AND_STAGE( 1, _TPROF, P_TRAFO );
570
571
787k
  const int      width                  = pCoeff.width;
572
787k
  const int      height                 = pCoeff.height;
573
787k
  const unsigned maxLog2TrDynamicRange  = tu.cs->sps->getMaxLog2TrDynamicRange();
574
787k
  const unsigned bitDepth               = tu.cs->sps->bitDepths[toChannelType( compID )];
575
787k
  const int      TRANSFORM_MATRIX_SHIFT = g_transformMatrixShift[TRANSFORM_INVERSE];
576
787k
  const TCoeff   clipMinimum            = -( 1 << maxLog2TrDynamicRange );
577
787k
  const TCoeff   clipMaximum            =  ( 1 << maxLog2TrDynamicRange ) - 1;
578
787k
  const uint32_t transformWidthIndex    = Log2(width )- 1;                                // nLog2WidthMinus1, since transform start from 2-point
579
787k
  const uint32_t transformHeightIndex   = Log2(height) - 1;                                // nLog2HeightMinus1, since transform start from 2-point
580
581
582
787k
  int trTypeHor = DCT2;
583
787k
  int trTypeVer = DCT2;
584
585
787k
  xSetTrTypes( tu, compID, width, height, trTypeHor, trTypeVer );
586
587
787k
  int skipWidth  = ( trTypeHor != DCT2 && width  == 32 ) ? 16 : width  > JVET_C0024_ZERO_OUT_TH ? width  - JVET_C0024_ZERO_OUT_TH : 0;
588
787k
  int skipHeight = ( trTypeVer != DCT2 && height == 32 ) ? 16 : height > JVET_C0024_ZERO_OUT_TH ? height - JVET_C0024_ZERO_OUT_TH : 0;
589
590
787k
  if (tu.cs->sps->LFNST && tu.cu->lfnstIdx)
591
509k
  {
592
509k
    if ((width == 4 && height > 4) || (width > 4 && height == 4))
593
148k
    {
594
148k
      skipWidth = width - 4;
595
148k
      skipHeight = height - 4;
596
148k
    }
597
360k
    else if ((width >= 8 && height >= 8))
598
318k
    {
599
318k
      skipWidth = width - 8;
600
318k
      skipHeight = height - 8;
601
318k
    }
602
509k
  }
603
604
787k
  TCoeff *block = m_blk;
605
787k
  TCoeff *tmp   = m_tmp;
606
787k
  if (width > 1 && height > 1)   // 2-D transform
607
787k
  {
608
787k
    const int shift_1st =   TRANSFORM_MATRIX_SHIFT + 1; // 1 has been added to shift_1st at the expense of shift_2nd
609
787k
    const int shift_2nd = ( TRANSFORM_MATRIX_SHIFT + maxLog2TrDynamicRange - 1 ) - bitDepth;
610
787k
    CHECK( shift_1st < 0, "Negative shift" );
611
787k
    CHECK( shift_2nd < 0, "Negative shift" );
612
787k
    fastInvTrans[trTypeVer][transformHeightIndex](pCoeff.buf, tmp, shift_1st, width, skipWidth, skipHeight, clipMinimum, clipMaximum);
613
787k
    fastInvTrans[trTypeHor][transformWidthIndex](tmp, block, shift_2nd, height, 0, skipWidth, clipMinimum, clipMaximum);
614
787k
  }
615
86
  else if (width == 1)   // 1-D vertical transform
616
0
  {
617
0
    int shift = (TRANSFORM_MATRIX_SHIFT + maxLog2TrDynamicRange - 1) - bitDepth;
618
0
    CHECK(shift < 0, "Negative shift");
619
0
    fastInvTrans[trTypeVer][transformHeightIndex](pCoeff.buf, block, shift + 1, 1, 0, skipHeight, clipMinimum, clipMaximum);
620
0
  }
621
86
  else   // if(iHeight == 1) //1-D horizontal transform
622
86
  {
623
86
    const int shift = (TRANSFORM_MATRIX_SHIFT + maxLog2TrDynamicRange - 1) - bitDepth;
624
86
    CHECK(shift < 0, "Negative shift");
625
86
    fastInvTrans[trTypeHor][transformWidthIndex](pCoeff.buf, block, shift + 1, 1, 0, skipWidth, clipMinimum, clipMaximum);
626
86
  }
627
628
787k
#if ENABLE_SIMD_TRAFO
629
787k
  if( width & 3 )
630
0
#endif //ENABLE_SIMD_TRAFO
631
0
  {
632
0
    Pel       *dst    = pResidual.buf;
633
0
    ptrdiff_t  stride = pResidual.stride;
634
635
0
    for( int y = 0; y < height; y++ )
636
0
    {
637
0
      for( int x = 0; x < width; x++ )
638
0
      {
639
0
        dst[x] = ( Pel ) *block++;
640
0
      }
641
642
0
      dst += stride;
643
0
    }
644
0
  }
645
787k
#if ENABLE_SIMD_TRAFO
646
787k
  else if( width & 7 )
647
172k
  {
648
172k
    g_tCoeffOps.cpyResi4( block, pResidual.buf, pResidual.stride, width, height );
649
172k
  }
650
614k
  else
651
614k
  {
652
614k
    g_tCoeffOps.cpyResi8( block, pResidual.buf, pResidual.stride, width, height );
653
614k
  }
654
787k
#endif //ENABLE_SIMD_TRAFO
655
787k
}
656
657
/** Wrapper function between HM interface and core NxN transform skipping
658
 */
659
void TrQuant::xITransformSkip(const CCoeffBuf& pCoeff,
660
  PelBuf& pResidual,
661
  const TransformUnit& tu,
662
  const ComponentID compID)
663
49.3k
{
664
49.3k
  const CompArea& area = tu.blocks[compID];
665
49.3k
  const int width = area.width;
666
49.3k
  const int height = area.height;
667
668
490k
  for (uint32_t y = 0; y < height; y++)
669
441k
  {
670
4.88M
    for (uint32_t x = 0; x < width; x++)
671
4.43M
    {
672
4.43M
      pResidual.at(x, y) = Pel(pCoeff.at(x, y));
673
4.43M
    }
674
441k
  }
675
49.3k
}
676
677
void TrQuant::xQuant(TransformUnit& tu, const ComponentID compID, const CCoeffBuf& pSrc, TCoeff &uiAbsSum, const QpParam& cQP, const Ctx& ctx)
678
2.01M
{
679
2.01M
  PROFILER_SCOPE_AND_STAGE( 1, _TPROF, P_QUANT );
680
2.01M
  m_quant->quant( tu, compID, pSrc, uiAbsSum, cQP, ctx );
681
#if ENABLE_MEASURE_SEARCH_SPACE
682
683
  g_searchSpaceAcc.addQuant( tu, toChannelType( compID ) );
684
#endif
685
2.01M
}
686
687
688
void TrQuant::transformNxN(TransformUnit &tu, const ComponentID compID, const QpParam &cQP, TCoeff &uiAbsSum, const Ctx &ctx, const bool loadTr)
689
2.01M
{
690
2.01M
        CodingStructure &cs = *tu.cs;
691
2.01M
  const CompArea& rect      = tu.blocks[compID];
692
2.01M
  const uint32_t uiWidth        = rect.width;
693
2.01M
  const uint32_t uiHeight       = rect.height;
694
695
2.01M
  const CPelBuf resiBuf     = cs.getResiBuf(rect);
696
697
2.01M
  if( tu.noResidual )
698
0
  {
699
0
    uiAbsSum = 0;
700
0
    TU::setCbfAtDepth( tu, compID, tu.depth, uiAbsSum > 0 );
701
0
    return;
702
0
  }
703
2.01M
  if (tu.cu->bdpcmM[toChannelType(compID)])
704
101k
  {
705
101k
    tu.mtsIdx[compID] = MTS_SKIP;
706
101k
  }
707
708
2.01M
  uiAbsSum = 0;
709
2.01M
  CHECK( cs.sps->getMaxTbSize() < uiWidth, "Unsupported transformation size" );
710
711
2.01M
  CoeffBuf tempCoeff(loadTr ? m_mtsCoeffs[tu.mtsIdx[compID]] : m_plTempCoeff, rect);
712
2.01M
  if (!loadTr)
713
1.99M
  {
714
1.99M
    DTRACE_PEL_BUF( D_RESIDUALS, resiBuf, tu, tu.cu->predMode, compID );
715
1.99M
    if (tu.mtsIdx[compID] == MTS_SKIP)
716
101k
    {
717
101k
      xTransformSkip(tu, compID, resiBuf, tempCoeff.buf);
718
101k
    }
719
1.89M
    else
720
1.89M
    {
721
1.89M
      xT(tu, compID, resiBuf, tempCoeff, uiWidth, uiHeight);
722
1.89M
    }
723
1.99M
  }
724
2.01M
  if (cs.sps->LFNST)
725
2.01M
  {
726
2.01M
    xFwdLfnst(tu, compID, loadTr);
727
2.01M
  }
728
2.01M
  DTRACE_COEFF_BUF( D_TCOEFF, tempCoeff, tu, tu.cu->predMode, compID );
729
730
2.01M
  xQuant( tu, compID, tempCoeff, uiAbsSum, cQP, ctx );
731
732
2.01M
  DTRACE_COEFF_BUF( D_TCOEFF, tu.getCoeffs( compID ), tu, tu.cu->predMode, compID );
733
734
  // set coded block flag (CBF)
735
2.01M
  TU::setCbfAtDepth (tu, compID, tu.depth, uiAbsSum > 0);
736
2.01M
}
737
738
void TrQuant::checktransformsNxN( TransformUnit &tu, std::vector<TrMode> *trModes, const int maxCand, const ComponentID compID)
739
18.6k
{
740
18.6k
  CodingStructure &cs     = *tu.cs;
741
18.6k
  const CompArea& rect    = tu.blocks[compID];
742
18.6k
  const uint32_t   width  = rect.width;
743
18.6k
  const uint32_t   height = rect.height;
744
745
18.6k
  const CPelBuf resiBuf = cs.getResiBuf(rect);
746
747
18.6k
  CHECK(cs.sps->getMaxTbSize() < width, "Unsupported transformation size");
748
18.6k
  int                           pos = 0;
749
18.6k
  std::vector<TrCost>           trCosts;
750
18.6k
  std::vector<TrMode>::iterator it      = trModes->begin();
751
18.6k
  const double                  facBB[] = { 1.2, 1.3, 1.3, 1.4, 1.5 };
752
55.9k
  while (it != trModes->end())
753
37.2k
  {
754
37.2k
    tu.mtsIdx[compID] = it->first;
755
37.2k
    CoeffBuf tempCoeff(m_mtsCoeffs[tu.mtsIdx[compID]], rect);
756
37.2k
    if (tu.noResidual)
757
0
    {
758
0
      int sumAbs = 0;
759
0
      trCosts.push_back(TrCost(sumAbs, pos++));
760
0
      it++;
761
0
      continue;
762
0
    }
763
37.2k
    if (tu.mtsIdx[compID] == MTS_SKIP)
764
18.6k
    {
765
18.6k
      xTransformSkip(tu, compID, resiBuf, tempCoeff.buf);
766
18.6k
    }
767
18.6k
    else
768
18.6k
    {
769
18.6k
      xT(tu, compID, resiBuf, tempCoeff, width, height);
770
18.6k
    }
771
772
37.2k
    int sumAbs = 0;
773
6.61M
    for (int pos = 0; pos < width * height; pos++)
774
6.58M
    {
775
6.58M
      sumAbs += abs(tempCoeff.buf[pos]);
776
6.58M
    }
777
778
37.2k
    double scaleSAD = 1.0;
779
37.2k
    if (tu.mtsIdx[compID] == MTS_SKIP && ((floorLog2(width) + floorLog2(height)) & 1) == 1)
780
7.81k
    {
781
7.81k
      scaleSAD = 1.0 / 1.414213562;   // compensate for not scaling transform skip coefficients by 1/sqrt(2)
782
7.81k
    }
783
37.2k
    if (tu.mtsIdx[compID] == MTS_SKIP)
784
18.6k
    {
785
18.6k
      int trShift = getTransformShift(tu.cu->slice->sps->bitDepths[CH_L], rect.size(), tu.cu->slice->sps->getMaxLog2TrDynamicRange());
786
18.6k
      scaleSAD *= pow(2, trShift);
787
18.6k
    }
788
37.2k
    trCosts.push_back(TrCost(int(std::min<double>(sumAbs * scaleSAD, std::numeric_limits<int>::max())), pos++));
789
37.2k
    it++;
790
37.2k
  }
791
792
18.6k
  int                           numTests = 0;
793
18.6k
  std::vector<TrCost>::iterator itC      = trCosts.begin();
794
18.6k
  const double                  fac      = facBB[std::max(0, floorLog2(std::max(width, height)) - 2)];
795
18.6k
  const double                  thr      = fac * trCosts.begin()->first;
796
18.6k
  const double                  thrTS    = trCosts.begin()->first;
797
55.9k
  while (itC != trCosts.end())
798
37.2k
  {
799
37.2k
    const bool testTr               = itC->first <= (trModes->at(itC->second).first == 1 ? thrTS : thr) && numTests <= maxCand;
800
37.2k
    trModes->at(itC->second).second = testTr;
801
37.2k
    numTests += testTr;
802
37.2k
    itC++;
803
37.2k
  }
804
18.6k
}
805
806
uint32_t TrQuant::xGetLFNSTIntraMode( const Area& tuArea, const uint32_t dirMode )
807
1.69M
{
808
1.69M
  if (dirMode < 2)
809
954k
  {
810
954k
    return dirMode;
811
954k
  }
812
813
743k
  static const int modeShift[] = { 0, 6, 10, 12, 14, 15 };
814
815
743k
  const int width  = int(tuArea.width);
816
743k
  const int height = int(tuArea.height);
817
818
743k
  if (width > height && dirMode < 2 + modeShift[floorLog2(width) - floorLog2(height)])
819
226
  {
820
226
    return dirMode + (VDIA_IDX - 1) + (NUM_EXT_LUMA_MODE >> 1);
821
226
  }
822
743k
  else if (height > width && dirMode > VDIA_IDX - modeShift[floorLog2(height) - floorLog2(width)])
823
69.2k
  {
824
69.2k
    return dirMode - (VDIA_IDX + 1) + (NUM_EXT_LUMA_MODE >> 1) + NUM_LUMA_MODE;
825
69.2k
  }
826
827
674k
  return dirMode;
828
743k
}
829
830
831
bool TrQuant::xGetTransposeFlag(uint32_t intraMode)
832
1.69M
{
833
1.69M
  return ((intraMode >= NUM_LUMA_MODE) && (intraMode >= (NUM_LUMA_MODE + (NUM_EXT_LUMA_MODE >> 1))))
834
1.69M
         || ((intraMode < NUM_LUMA_MODE) && (intraMode > DIA_IDX));
835
1.69M
}
836
837
838
void TrQuant::xInvLfnst(const TransformUnit &tu, const ComponentID compID)
839
836k
{
840
836k
  const CompArea &area     = tu.blocks[compID];
841
836k
  const uint32_t  width    = area.width;
842
836k
  const uint32_t  height   = area.height;
843
836k
  const uint32_t  lfnstIdx = tu.cu->lfnstIdx;
844
836k
  if (lfnstIdx && tu.mtsIdx[compID] != MTS_SKIP && (CU::isSepTree(*tu.cu) ? true : isLuma(compID)))
845
509k
  {
846
509k
    const CodingUnit& cu = *tu.cs->getCU(area.pos(), toChannelType(compID), TREE_D);
847
509k
    const bool         whge3 = width >= 8 && height >= 8;
848
509k
    const ScanElement *scan =
849
509k
      whge3
850
509k
        ? g_coefTopLeftDiagScan8x8[Log2(width)] 
851
509k
        : getScanOrder(SCAN_GROUPED_4x4, Log2(area.width), Log2(area.height));
852
509k
    uint32_t intraMode = CU::getFinalIntraMode(cu, toChannelType(compID));
853
854
509k
    if (CU::isLMCMode( cu.intraDir[toChannelType(compID)]))
855
84.1k
    {
856
84.1k
      intraMode = CU::getCoLocatedIntraLumaMode(cu);
857
84.1k
    }
858
509k
    if (CU::isMIP(cu, toChannelType(compID)))
859
4.90k
    {
860
4.90k
      intraMode = PLANAR_IDX;
861
4.90k
    }
862
509k
    CHECK(intraMode >= NUM_INTRA_MODE - 1, "Invalid intra mode");
863
864
509k
    if (lfnstIdx < 3)
865
509k
    {
866
509k
      if (tu.cu->ispMode && isLuma(compID))
867
7.51k
      {
868
7.51k
        intraMode = xGetLFNSTIntraMode(tu.cu->blocks[compID], intraMode);
869
7.51k
      }
870
501k
      else
871
501k
        intraMode = xGetLFNSTIntraMode(tu.blocks[compID], intraMode);
872
509k
      bool      transposeFlag = xGetTransposeFlag(intraMode);
873
509k
      const int sbSize        = whge3 ? 8 : 4;
874
509k
      bool      tu4x4Flag     = (width == 4 && height == 4);
875
509k
      bool      tu8x8Flag     = (width == 8 && height == 8);
876
509k
      TCoeff *  lfnstTemp;
877
509k
      TCoeff *  coeffTemp;
878
509k
      int       y;
879
509k
      lfnstTemp                  = m_tempInMatrix;   // inverse spectral rearrangement
880
509k
      coeffTemp                  = m_plTempCoeff;
881
509k
      TCoeff *           dst     = lfnstTemp;
882
509k
      const ScanElement *scanPtr = scan;
883
8.65M
      for (y = 0; y < 16; y++)
884
8.14M
      {
885
8.14M
        *dst++ = coeffTemp[scanPtr->idx];
886
8.14M
        scanPtr++;
887
8.14M
      }
888
889
509k
      m_invLfnstNxN( m_tempInMatrix, m_tempOutMatrix, g_lfnstLut[intraMode], lfnstIdx - 1, sbSize, ( tu4x4Flag || tu8x8Flag ) ? 8 : 16 );
890
891
509k
      lfnstTemp = m_tempOutMatrix;   // inverse spectral rearrangement
892
893
509k
      if (transposeFlag)
894
46.8k
      {
895
46.8k
        if (sbSize == 4)
896
9.47k
        {
897
47.3k
          for (y = 0; y < 4; y++)
898
37.8k
          {
899
37.8k
            coeffTemp[0] = lfnstTemp[0];
900
37.8k
            coeffTemp[1] = lfnstTemp[4];
901
37.8k
            coeffTemp[2] = lfnstTemp[8];
902
37.8k
            coeffTemp[3] = lfnstTemp[12];
903
37.8k
            lfnstTemp++;
904
37.8k
            coeffTemp += width;
905
37.8k
          }
906
9.47k
        }
907
37.3k
        else   // ( sbSize == 8 )
908
37.3k
        {
909
336k
          for (y = 0; y < 8; y++)
910
298k
          {
911
298k
            coeffTemp[0] = lfnstTemp[0];
912
298k
            coeffTemp[1] = lfnstTemp[8];
913
298k
            coeffTemp[2] = lfnstTemp[16];
914
298k
            coeffTemp[3] = lfnstTemp[24];
915
298k
            if (y < 4)
916
149k
            {
917
149k
              coeffTemp[4] = lfnstTemp[32];
918
149k
              coeffTemp[5] = lfnstTemp[36];
919
149k
              coeffTemp[6] = lfnstTemp[40];
920
149k
              coeffTemp[7] = lfnstTemp[44];
921
149k
            }
922
298k
            lfnstTemp++;
923
298k
            coeffTemp += width;
924
298k
          }
925
37.3k
        }
926
46.8k
      }
927
462k
      else
928
462k
      {
929
3.43M
        for (y = 0; y < sbSize; y++)
930
2.97M
        {
931
2.97M
          uint32_t uiStride = (y < 4) ? sbSize : 4;
932
2.97M
          ::memcpy(coeffTemp, lfnstTemp, uiStride * sizeof(TCoeff));
933
2.97M
          lfnstTemp += uiStride;
934
2.97M
          coeffTemp += width;
935
2.97M
        }
936
462k
      }
937
509k
    }
938
509k
  }
939
836k
}
940
941
942
void TrQuant::xFwdLfnst(const TransformUnit &tu, const ComponentID compID, const bool loadTr)
943
2.01M
{
944
2.01M
  const CompArea &area     = tu.blocks[compID];
945
2.01M
  const uint32_t  width    = area.width;
946
2.01M
  const uint32_t  height   = area.height;
947
2.01M
  const uint32_t  lfnstIdx = tu.cu->lfnstIdx;
948
2.01M
  if (lfnstIdx && tu.mtsIdx[compID] != MTS_SKIP && (CU::isSepTree(*tu.cu) ? true : isLuma(compID)))
949
1.18M
  {
950
1.18M
    const CodingUnit& cu = *tu.cs->getCU(area.pos(), toChannelType(compID), TREE_D);
951
1.18M
    const bool         whge3 = width >= 8 && height >= 8;
952
1.18M
    const ScanElement *scan =
953
1.18M
      whge3
954
1.18M
        ? g_coefTopLeftDiagScan8x8[Log2(width)] 
955
1.18M
        : getScanOrder(SCAN_GROUPED_4x4, Log2(area.width), Log2(area.height));   
956
1.18M
    uint32_t intraMode = CU::getFinalIntraMode(cu, toChannelType(compID));
957
958
1.18M
    if (CU::isLMCMode(cu.intraDir[toChannelType(compID)]))
959
104k
    {
960
104k
      intraMode = CU::getCoLocatedIntraLumaMode(cu);
961
104k
    }
962
1.18M
    if (CU::isMIP(cu, toChannelType(compID)))
963
8.07k
    {
964
8.07k
      intraMode = PLANAR_IDX;
965
8.07k
    }
966
1.18M
    CHECK(intraMode >= NUM_INTRA_MODE - 1, "Invalid intra mode");
967
968
1.18M
    if (lfnstIdx < 3)
969
1.18M
    {
970
1.18M
      if (tu.cu->ispMode && isLuma(compID))
971
11.6k
      {
972
11.6k
        intraMode = xGetLFNSTIntraMode(tu.cu->blocks[compID], intraMode);
973
11.6k
      }
974
1.17M
      else
975
1.17M
      {
976
1.17M
        intraMode = xGetLFNSTIntraMode(tu.blocks[compID], intraMode);
977
1.17M
      }
978
1.18M
      bool      transposeFlag = xGetTransposeFlag(intraMode);
979
1.18M
      const int sbSize        = whge3 ? 8 : 4;
980
1.18M
      bool      tu4x4Flag     = (width == 4 && height == 4);
981
1.18M
      bool      tu8x8Flag     = (width == 8 && height == 8);
982
1.18M
      TCoeff*   lfnstTemp;
983
1.18M
      TCoeff*   coeffTemp;
984
1.18M
      TCoeff*   tempCoeff     = loadTr ? m_mtsCoeffs[tu.mtsIdx[compID]] : m_plTempCoeff;
985
986
1.18M
      int y;
987
1.18M
      lfnstTemp = m_tempInMatrix;   // forward low frequency non-separable transform
988
1.18M
      coeffTemp = tempCoeff;
989
990
1.18M
      if (transposeFlag)
991
255k
      {
992
255k
        if (sbSize == 4)
993
76.9k
        {
994
384k
          for (y = 0; y < 4; y++)
995
307k
          {
996
307k
            lfnstTemp[0]  = coeffTemp[0];
997
307k
            lfnstTemp[4]  = coeffTemp[1];
998
307k
            lfnstTemp[8]  = coeffTemp[2];
999
307k
            lfnstTemp[12] = coeffTemp[3];
1000
307k
            lfnstTemp++;
1001
307k
            coeffTemp += width;
1002
307k
          }
1003
76.9k
        }
1004
178k
        else   // ( sbSize == 8 )
1005
178k
        {
1006
1.61M
          for (y = 0; y < 8; y++)
1007
1.43M
          {
1008
1.43M
            lfnstTemp[0]  = coeffTemp[0];
1009
1.43M
            lfnstTemp[8]  = coeffTemp[1];
1010
1.43M
            lfnstTemp[16] = coeffTemp[2];
1011
1.43M
            lfnstTemp[24] = coeffTemp[3];
1012
1.43M
            if (y < 4)
1013
715k
            {
1014
715k
              lfnstTemp[32] = coeffTemp[4];
1015
715k
              lfnstTemp[36] = coeffTemp[5];
1016
715k
              lfnstTemp[40] = coeffTemp[6];
1017
715k
              lfnstTemp[44] = coeffTemp[7];
1018
715k
            }
1019
1.43M
            lfnstTemp++;
1020
1.43M
            coeffTemp += width;
1021
1.43M
          }
1022
178k
        }
1023
255k
      }
1024
933k
      else
1025
933k
      {
1026
7.03M
        for (y = 0; y < sbSize; y++)
1027
6.09M
        {
1028
6.09M
          uint32_t uiStride = (y < 4) ? sbSize : 4;
1029
6.09M
          ::memcpy(lfnstTemp, coeffTemp, uiStride * sizeof(TCoeff));
1030
6.09M
          lfnstTemp += uiStride;
1031
6.09M
          coeffTemp += width;
1032
6.09M
        }
1033
933k
      }
1034
1035
1.18M
      m_fwdLfnstNxN( m_tempInMatrix, m_tempOutMatrix, g_lfnstLut[intraMode], lfnstIdx - 1, sbSize, ( tu4x4Flag || tu8x8Flag ) ? 8 : 16 );
1036
1037
1.18M
      lfnstTemp                        = m_tempOutMatrix;   // forward spectral rearrangement
1038
1.18M
      coeffTemp                        = tempCoeff;
1039
1.18M
      const ScanElement *scanPtr       = scan;
1040
1.18M
      int                lfnstCoeffNum = (sbSize == 4) ? sbSize * sbSize : 48;
1041
44.8M
      for (y = 0; y < lfnstCoeffNum; y++)
1042
43.6M
      {
1043
43.6M
        coeffTemp[scanPtr->idx] = *lfnstTemp++;
1044
43.6M
        scanPtr++;
1045
43.6M
      }
1046
1.18M
    }
1047
1.18M
  }
1048
2.01M
}
1049
1050
void TrQuant::xTransformSkip(const TransformUnit& tu, const ComponentID& compID, const CPelBuf& resi, TCoeff* psCoeff)
1051
120k
{
1052
120k
  const CompArea& rect = tu.blocks[compID];
1053
120k
  const uint32_t width = rect.width;
1054
120k
  const uint32_t height = rect.height;
1055
1056
1.30M
  for (uint32_t y = 0, coefficientIndex = 0; y < height; y++)
1057
1.18M
  {
1058
14.1M
    for (uint32_t x = 0; x < width; x++, coefficientIndex++)
1059
12.9M
    {
1060
12.9M
      psCoeff[coefficientIndex] = TCoeff(resi.at(x, y));
1061
12.9M
    }
1062
1.18M
  }
1063
120k
}
1064
} // namespace vvenc
1065
1066
//! \}
1067