Coverage Report

Created: 2026-09-01 06:57

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
340M
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.03M
{
97
1.03M
  const Pel*  cb  = resCb.buf;
98
1.03M
  const Pel*  cr  = resCr.buf;
99
1.03M
  Pel*        c1  = resC1.buf;
100
1.03M
  Pel*        c2  = resC2.buf;
101
1.03M
  int64_t     d1  = 0;
102
1.03M
  int64_t     d2  = 0;
103
13.8M
  for( SizeType y = 0; y < resCb.height; y++, cb += resCb.stride, cr += resCr.stride, c1 += resC1.stride, c2 += resC2.stride )
104
12.7M
  {
105
182M
    for( SizeType x = 0; x < resCb.width; x++ )
106
170M
    {
107
170M
      int cbx = cb[x], crx = cr[x];
108
170M
      if      ( signedMode ==  1 )
109
42.5M
      {
110
42.5M
        c1[x] = Pel( ( 4*cbx + 2*crx ) / 5 );
111
42.5M
        d1   += square( cbx - c1[x] ) + square( crx - (c1[x]>>1) );
112
42.5M
      }
113
127M
      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
127M
      else if ( signedMode ==  2 )
119
42.5M
      {
120
42.5M
        c1[x] = Pel( ( cbx + crx ) / 2 );
121
42.5M
        d1   += square( cbx - c1[x] ) + square( crx - c1[x] );
122
42.5M
      }
123
85.1M
      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
85.1M
      else if ( signedMode ==  3 )
129
42.5M
      {
130
42.5M
        c2[x] = Pel( ( 4*crx + 2*cbx ) / 5 );
131
42.5M
        d1   += square( cbx - (c2[x]>>1) ) + square( crx - c2[x] );
132
42.5M
      }
133
42.5M
      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
42.5M
      else
139
42.5M
      {
140
42.5M
        d1   += square( cbx );
141
42.5M
        d2   += square( crx );
142
42.5M
      }
143
170M
    }
144
12.7M
  }
145
1.03M
  return std::make_pair(d1,d2);
146
1.03M
}
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
257k
{
97
257k
  const Pel*  cb  = resCb.buf;
98
257k
  const Pel*  cr  = resCr.buf;
99
257k
  Pel*        c1  = resC1.buf;
100
257k
  Pel*        c2  = resC2.buf;
101
257k
  int64_t     d1  = 0;
102
257k
  int64_t     d2  = 0;
103
3.45M
  for( SizeType y = 0; y < resCb.height; y++, cb += resCb.stride, cr += resCr.stride, c1 += resC1.stride, c2 += resC2.stride )
104
3.19M
  {
105
45.7M
    for( SizeType x = 0; x < resCb.width; x++ )
106
42.5M
    {
107
42.5M
      int cbx = cb[x], crx = cr[x];
108
42.5M
      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
42.5M
      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
42.5M
      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
42.5M
      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
42.5M
      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
42.5M
      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
42.5M
      else
139
42.5M
      {
140
42.5M
        d1   += square( cbx );
141
42.5M
        d2   += square( crx );
142
42.5M
      }
143
42.5M
    }
144
3.19M
  }
145
257k
  return std::make_pair(d1,d2);
146
257k
}
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
257k
{
97
257k
  const Pel*  cb  = resCb.buf;
98
257k
  const Pel*  cr  = resCr.buf;
99
257k
  Pel*        c1  = resC1.buf;
100
257k
  Pel*        c2  = resC2.buf;
101
257k
  int64_t     d1  = 0;
102
257k
  int64_t     d2  = 0;
103
3.45M
  for( SizeType y = 0; y < resCb.height; y++, cb += resCb.stride, cr += resCr.stride, c1 += resC1.stride, c2 += resC2.stride )
104
3.19M
  {
105
45.7M
    for( SizeType x = 0; x < resCb.width; x++ )
106
42.5M
    {
107
42.5M
      int cbx = cb[x], crx = cr[x];
108
42.5M
      if      ( signedMode ==  1 )
109
42.5M
      {
110
42.5M
        c1[x] = Pel( ( 4*cbx + 2*crx ) / 5 );
111
42.5M
        d1   += square( cbx - c1[x] ) + square( crx - (c1[x]>>1) );
112
42.5M
      }
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
42.5M
    }
144
3.19M
  }
145
257k
  return std::make_pair(d1,d2);
146
257k
}
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
257k
{
97
257k
  const Pel*  cb  = resCb.buf;
98
257k
  const Pel*  cr  = resCr.buf;
99
257k
  Pel*        c1  = resC1.buf;
100
257k
  Pel*        c2  = resC2.buf;
101
257k
  int64_t     d1  = 0;
102
257k
  int64_t     d2  = 0;
103
3.45M
  for( SizeType y = 0; y < resCb.height; y++, cb += resCb.stride, cr += resCr.stride, c1 += resC1.stride, c2 += resC2.stride )
104
3.19M
  {
105
45.7M
    for( SizeType x = 0; x < resCb.width; x++ )
106
42.5M
    {
107
42.5M
      int cbx = cb[x], crx = cr[x];
108
42.5M
      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
42.5M
      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
42.5M
      else if ( signedMode ==  2 )
119
42.5M
      {
120
42.5M
        c1[x] = Pel( ( cbx + crx ) / 2 );
121
42.5M
        d1   += square( cbx - c1[x] ) + square( crx - c1[x] );
122
42.5M
      }
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
42.5M
    }
144
3.19M
  }
145
257k
  return std::make_pair(d1,d2);
146
257k
}
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
257k
{
97
257k
  const Pel*  cb  = resCb.buf;
98
257k
  const Pel*  cr  = resCr.buf;
99
257k
  Pel*        c1  = resC1.buf;
100
257k
  Pel*        c2  = resC2.buf;
101
257k
  int64_t     d1  = 0;
102
257k
  int64_t     d2  = 0;
103
3.45M
  for( SizeType y = 0; y < resCb.height; y++, cb += resCb.stride, cr += resCr.stride, c1 += resC1.stride, c2 += resC2.stride )
104
3.19M
  {
105
45.7M
    for( SizeType x = 0; x < resCb.width; x++ )
106
42.5M
    {
107
42.5M
      int cbx = cb[x], crx = cr[x];
108
42.5M
      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
42.5M
      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
42.5M
      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
42.5M
      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
42.5M
      else if ( signedMode ==  3 )
129
42.5M
      {
130
42.5M
        c2[x] = Pel( ( 4*crx + 2*cbx ) / 5 );
131
42.5M
        d1   += square( cbx - (c2[x]>>1) ) + square( crx - c2[x] );
132
42.5M
      }
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
42.5M
    }
144
3.19M
  }
145
257k
  return std::make_pair(d1,d2);
146
257k
}
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
254k
{
150
254k
  Pel*  cb  = resCb.buf;
151
254k
  Pel*  cr  = resCr.buf;
152
3.40M
  for( SizeType y = 0; y < resCb.height; y++, cb += resCb.stride, cr += resCr.stride )
153
3.14M
  {
154
45.1M
    for( SizeType x = 0; x < resCb.width; x++ )
155
42.0M
    {
156
42.0M
      if      ( signedMode ==  1 )  { cr[x] =  cb[x] >> 1;  }
157
42.0M
      else if ( signedMode == -1 )  { cr[x] = -cb[x] >> 1;  }
158
42.0M
      else if ( signedMode ==  2 )  { cr[x] =  cb[x]; }
159
263k
      else if ( signedMode == -2 )  { cr[x] = -cb[x]; }
160
263k
      else if ( signedMode ==  3 )  { cb[x] =  cr[x] >> 1; }
161
0
      else if ( signedMode == -3 )  { cb[x] = -cr[x] >> 1; }
162
42.0M
    }
163
3.14M
  }
164
254k
}
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
252k
{
150
252k
  Pel*  cb  = resCb.buf;
151
252k
  Pel*  cr  = resCr.buf;
152
3.37M
  for( SizeType y = 0; y < resCb.height; y++, cb += resCb.stride, cr += resCr.stride )
153
3.12M
  {
154
44.8M
    for( SizeType x = 0; x < resCb.width; x++ )
155
41.7M
    {
156
41.7M
      if      ( signedMode ==  1 )  { cr[x] =  cb[x] >> 1;  }
157
41.7M
      else if ( signedMode == -1 )  { cr[x] = -cb[x] >> 1;  }
158
41.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
41.7M
    }
163
3.12M
  }
164
252k
}
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.82k
{
150
1.82k
  Pel*  cb  = resCb.buf;
151
1.82k
  Pel*  cr  = resCr.buf;
152
24.2k
  for( SizeType y = 0; y < resCb.height; y++, cb += resCb.stride, cr += resCr.stride )
153
22.3k
  {
154
285k
    for( SizeType x = 0; x < resCb.width; x++ )
155
263k
    {
156
263k
      if      ( signedMode ==  1 )  { cr[x] =  cb[x] >> 1;  }
157
263k
      else if ( signedMode == -1 )  { cr[x] = -cb[x] >> 1;  }
158
263k
      else if ( signedMode ==  2 )  { cr[x] =  cb[x]; }
159
263k
      else if ( signedMode == -2 )  { cr[x] = -cb[x]; }
160
263k
      else if ( signedMode ==  3 )  { cb[x] =  cr[x] >> 1; }
161
0
      else if ( signedMode == -3 )  { cb[x] = -cr[x] >> 1; }
162
263k
    }
163
22.3k
  }
164
1.82k
}
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.13M
{
168
1.13M
  const int8_t *trMat  = (size > 4) ? g_lfnstFwd8x8[mode][index][0] : g_lfnstFwd4x4[mode][index][0];
169
1.13M
  const int     trSize = (size > 4) ? 48 : 16;
170
1.13M
  int           coef;
171
1.13M
  int *         out = dst;
172
173
17.5M
  for (int j = 0; j < zeroOutSize; j++)
174
16.4M
  {
175
16.4M
    int *         srcPtr   = src;
176
16.4M
    const int8_t *trMatTmp = trMat;
177
16.4M
    coef                   = 0;
178
621M
    for (int i = 0; i < trSize; i++)
179
605M
    {
180
605M
      coef += *srcPtr++ * *trMatTmp++;
181
605M
    }
182
16.4M
    *out++ = (coef + 64) >> 7;
183
16.4M
    trMat += trSize;
184
16.4M
  }
185
186
1.13M
  ::memset(out, 0, (trSize - zeroOutSize) * sizeof(int));
187
1.13M
}
188
189
190
void xInvLfnstNxNCore(int *src, int *dst, const uint32_t mode, const uint32_t index, const uint32_t size, int zeroOutSize)
191
484k
{
192
484k
  int           maxLog2TrDynamicRange = 15;
193
484k
  const TCoeff  outputMinimum         = -(1 << maxLog2TrDynamicRange);
194
484k
  const TCoeff  outputMaximum         = (1 << maxLog2TrDynamicRange) - 1;
195
484k
  const int8_t *trMat                 = (size > 4) ? g_lfnstInv8x8[mode][index][0] : g_lfnstInv4x4[mode][index][0];
196
484k
  const int     trSize                = (size > 4) ? 48 : 16;
197
484k
  int           resi;
198
484k
  int *         out                   = dst;
199
200
18.0M
  for( int j = 0; j < trSize; j++, trMat += 16 )
201
17.5M
  {
202
17.5M
    resi = 0;
203
17.5M
    const int8_t* trMatTmp = trMat;
204
17.5M
    int*          srcPtr   = src;
205
206
266M
    for( int i = 0; i < zeroOutSize; i++ )
207
249M
    {
208
249M
      resi += *srcPtr++ * *trMatTmp++;
209
249M
    }
210
211
17.5M
    *out++ = Clip3( outputMinimum, outputMaximum, ( int ) ( resi + 64 ) >> 7 );
212
17.5M
  }
213
484k
}
214
215
// ====================================================================================================================
216
// TrQuant class member functions
217
// ====================================================================================================================
218
18.6k
TrQuant::TrQuant() : m_scalingListEnabled(false), m_quant( nullptr )
219
18.6k
{
220
  // allocate temporary buffers
221
18.6k
  m_plTempCoeff = ( TCoeff* ) xMalloc( TCoeff, MAX_TB_SIZEY * MAX_TB_SIZEY );
222
18.6k
  m_tmp         = ( TCoeff* ) xMalloc( TCoeff, MAX_TB_SIZEY * MAX_TB_SIZEY );
223
18.6k
  m_blk         = ( TCoeff* ) xMalloc( TCoeff, MAX_TB_SIZEY * MAX_TB_SIZEY );
224
225
130k
  for( int i = 0; i < NUM_TRAFO_MODES_MTS; i++ )
226
111k
  {
227
111k
    m_mtsCoeffs[i] = ( TCoeff* ) xMalloc( TCoeff, MAX_TB_SIZEY * MAX_TB_SIZEY );
228
111k
  }
229
230
18.6k
  {
231
18.6k
    m_invICT      = m_invICTMem + maxAbsIctMode;
232
18.6k
    m_invICT[ 0]  = invTransformCbCr< 0>;
233
18.6k
    m_invICT[ 1]  = invTransformCbCr< 1>;
234
18.6k
    m_invICT[-1]  = invTransformCbCr<-1>;
235
18.6k
    m_invICT[ 2]  = invTransformCbCr< 2>;
236
18.6k
    m_invICT[-2]  = invTransformCbCr<-2>;
237
18.6k
    m_invICT[ 3]  = invTransformCbCr< 3>;
238
18.6k
    m_invICT[-3]  = invTransformCbCr<-3>;
239
18.6k
    m_fwdICT      = m_fwdICTMem + maxAbsIctMode;
240
18.6k
    m_fwdICT[ 0]  = fwdTransformCbCr< 0>;
241
18.6k
    m_fwdICT[ 1]  = fwdTransformCbCr< 1>;
242
18.6k
    m_fwdICT[-1]  = fwdTransformCbCr<-1>;
243
18.6k
    m_fwdICT[ 2]  = fwdTransformCbCr< 2>;
244
18.6k
    m_fwdICT[-2]  = fwdTransformCbCr<-2>;
245
18.6k
    m_fwdICT[ 3]  = fwdTransformCbCr< 3>;
246
18.6k
    m_fwdICT[-3]  = fwdTransformCbCr<-3>;
247
18.6k
  }
248
249
18.6k
  m_invLfnstNxN = xInvLfnstNxNCore;
250
18.6k
  m_fwdLfnstNxN = xFwdLfnstNxNCore;
251
252
#if defined( TARGET_SIMD_X86 ) && ENABLE_SIMD_TRAFO
253
  initTrQuantX86();
254
#endif
255
18.6k
}
256
257
TrQuant::~TrQuant()
258
18.6k
{
259
18.6k
  if( m_quant )
260
18.6k
  {
261
18.6k
    delete m_quant;
262
18.6k
    m_quant = nullptr;
263
18.6k
  }
264
265
  // delete temporary buffers
266
18.6k
  if( m_plTempCoeff )
267
18.6k
  {
268
18.6k
    xFree( m_plTempCoeff );
269
18.6k
    m_plTempCoeff = nullptr;
270
18.6k
  }
271
272
18.6k
  if( m_blk )
273
18.6k
  {
274
18.6k
    xFree( m_blk );
275
18.6k
    m_blk = nullptr;
276
18.6k
  }
277
278
18.6k
  if( m_tmp )
279
18.6k
  {
280
18.6k
    xFree( m_tmp );
281
18.6k
    m_tmp = nullptr;
282
18.6k
  }
283
284
130k
  for( int i = 0; i < NUM_TRAFO_MODES_MTS; i++ )
285
111k
  {
286
111k
     xFree( m_mtsCoeffs[i] );
287
111k
  }
288
18.6k
}
289
290
void TrQuant::xDeQuant(const TransformUnit& tu,
291
                             CoeffBuf      &dstCoeff,
292
                       const ComponentID   &compID,
293
                       const QpParam       &cQP)
294
796k
{
295
796k
  PROFILER_SCOPE_AND_STAGE( 1, _TPROF, P_DEQUANT );
296
796k
  m_quant->dequant( tu, dstCoeff, compID, cQP );
297
796k
}
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
18.6k
{
307
18.6k
  m_bEnc = bEnc;
308
309
18.6k
  delete m_quant;
310
18.6k
  m_quant = nullptr;
311
312
18.6k
  m_quant = new(std::nothrow) DepQuant( otherQuant, bEnc, scalingListsEnabled );
313
18.6k
  CHECK( !m_quant, "allocation failed" );
314
18.6k
  m_quant->init( rdoq, bUseRDOQTS, thrVal );
315
18.6k
}
316
317
318
void TrQuant::invTransformNxN( TransformUnit& tu, const ComponentID compID, PelBuf& pResi, const QpParam& cQP )
319
796k
{
320
796k
  const CompArea& area    = tu.blocks[compID];
321
796k
  const uint32_t uiWidth  = area.width;
322
796k
  const uint32_t uiHeight = area.height;
323
324
796k
  CHECK( uiWidth > tu.cs->sps->getMaxTbSize() || uiHeight > tu.cs->sps->getMaxTbSize(), "Maximal allowed transformation size exceeded!" );
325
326
796k
  {
327
796k
    CoeffBuf tempCoeff = CoeffBuf( m_plTempCoeff, area );
328
796k
    xDeQuant( tu, tempCoeff, compID, cQP );
329
330
796k
    DTRACE_COEFF_BUF( D_TCOEFF, tempCoeff, tu, tu.cu->predMode, compID );
331
332
796k
    if (tu.cs->sps->LFNST)
333
796k
    {
334
796k
      xInvLfnst(tu, compID);
335
796k
    }
336
796k
    if (tu.mtsIdx[compID] == MTS_SKIP)
337
46.8k
    {
338
46.8k
      xITransformSkip(tempCoeff, pResi, tu, compID);
339
46.8k
    }
340
749k
    else
341
749k
    {
342
749k
      xIT(tu, compID, tempCoeff, pResi);
343
749k
    }
344
796k
  }
345
346
  //DTRACE_BLOCK_COEFF(tu.getCoeffs(compID), tu, tu.cu->predMode, compID);
347
796k
  DTRACE_PEL_BUF( D_RESIDUALS, pResi, tu, tu.cu->predMode, compID);
348
796k
}
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.03M
{
352
1.03M
  CHECK( Size(resCb) != Size(resCr), "resCb and resCr have different sizes" );
353
1.03M
  CHECK( Size(resCb) != Size(resC1), "resCb and resC1 have different sizes" );
354
1.03M
  CHECK( Size(resCb) != Size(resC2), "resCb and resC2 have different sizes" );
355
1.03M
  return (*m_fwdICT[ TU::getICTMode(tu, jointCbCr) ])( resCb, resCr, resC1, resC2 );
356
1.03M
}
357
358
void TrQuant::invTransformICT( const TransformUnit& tu, PelBuf& resCb, PelBuf& resCr )
359
254k
{
360
254k
  CHECK( Size(resCb) != Size(resCr), "resCb and resCr have different sizes" );
361
254k
  (*m_invICT[ TU::getICTMode(tu) ])( resCb, resCr );
362
254k
}
363
364
std::vector<int> TrQuant::selectICTCandidates( const TransformUnit& tu, CompStorage* resCb, CompStorage* resCr )
365
257k
{
366
257k
  CHECK( !resCb[0].valid() || !resCr[0].valid(), "standard components are not valid" );
367
368
257k
  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
257k
  std::pair<int64_t,int64_t> pairDist[4];
378
1.28M
  for( int cbfMask = 0; cbfMask < 4; cbfMask++ )
379
1.03M
  {
380
1.03M
    pairDist[cbfMask] = fwdTransformICT( tu, resCb[0], resCr[0], resCb[cbfMask], resCr[cbfMask], cbfMask );
381
1.03M
  }
382
383
257k
  std::vector<int> cbfMasksToTest;
384
257k
  int64_t minDist1  = std::min<int64_t>( pairDist[0].first, pairDist[0].second );
385
257k
  int64_t minDist2  = std::numeric_limits<int64_t>::max();
386
257k
  int     cbfMask1  = 0;
387
257k
  int     cbfMask2  = 0;
388
257k
  for( int cbfMask : { 1, 2, 3 } )
389
773k
  {
390
773k
    if( pairDist[cbfMask].first < minDist1 )
391
510k
    {
392
510k
      cbfMask2  = cbfMask1; minDist2  = minDist1;
393
510k
      cbfMask1  = cbfMask;  minDist1  = pairDist[cbfMask1].first;
394
510k
    }
395
263k
    else if( pairDist[cbfMask].first < minDist2 )
396
257k
    {
397
257k
      cbfMask2  = cbfMask;  minDist2  = pairDist[cbfMask2].first;
398
257k
    }
399
773k
  }
400
257k
  if( cbfMask1 )
401
257k
  {
402
257k
    cbfMasksToTest.push_back( cbfMask1 );
403
257k
  }
404
257k
  if( cbfMask2 && ( ( minDist2 < (9*minDist1)/8 ) || ( !cbfMask1 && minDist2 < (3*minDist1)/2 ) ) )
405
0
  {
406
0
    cbfMasksToTest.push_back( cbfMask2 );
407
0
  }
408
409
257k
  return cbfMasksToTest;
410
257k
}
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.56M
{
419
2.56M
  const bool isISP = CU::isIntra(*tu.cu) && tu.cu->ispMode && isLuma(compID);
420
2.56M
  if (isISP && tu.cu->lfnstIdx)
421
18.1k
  {
422
18.1k
    return;
423
18.1k
  }
424
2.54M
  if (!tu.cs->sps->MTS)
425
0
  {
426
0
    return;
427
0
  }
428
2.54M
  if (CU::isIntra(*tu.cu) && isLuma(compID) && ((tu.cs->sps->getUseImplicitMTS() && tu.cu->lfnstIdx == 0 && tu.cu->mipFlag == 0) || tu.cu->ispMode))
429
79.2k
  {
430
79.2k
    if (width >= 4 && width <= 16)
431
35.9k
      trTypeHor = DST7;
432
79.2k
    if (height >= 4 && height <= 16)
433
34.4k
      trTypeVer = DST7;
434
79.2k
  }
435
2.46M
  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.54M
  const bool isExplicitMTS = (CU::isIntra(*tu.cu) ? tu.cs->sps->MTS : tu.cs->sps->MTSInter && CU::isInter(*tu.cu)) && isLuma(compID);
468
2.54M
  if (isExplicitMTS)
469
187k
  {
470
187k
    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
187k
  }
478
2.54M
}
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.81M
{
483
1.81M
  PROFILER_SCOPE_AND_STAGE( 1, _TPROF, P_TRAFO );
484
485
1.81M
  const unsigned maxLog2TrDynamicRange  = tu.cs->sps->getMaxLog2TrDynamicRange();
486
1.81M
  const unsigned bitDepth               = tu.cs->sps->bitDepths[toChannelType( compID )];
487
1.81M
  const int      TRANSFORM_MATRIX_SHIFT = g_transformMatrixShift[TRANSFORM_FORWARD];
488
1.81M
  const uint32_t transformWidthIndex    = Log2(width ) - 1;  // nLog2WidthMinus1, since transform start from 2-point
489
1.81M
  const uint32_t transformHeightIndex   = Log2(height) - 1;  // nLog2HeightMinus1, since transform start from 2-point
490
491
1.81M
  int trTypeHor = DCT2;
492
1.81M
  int trTypeVer = DCT2;
493
494
1.81M
  xSetTrTypes( tu, compID, width, height, trTypeHor, trTypeVer );
495
496
1.81M
  int  skipWidth  = ( trTypeHor != DCT2 && width  == 32 ) ? 16 : width  > JVET_C0024_ZERO_OUT_TH ? width  - JVET_C0024_ZERO_OUT_TH : 0;
497
1.81M
  int  skipHeight = ( trTypeVer != DCT2 && height == 32 ) ? 16 : height > JVET_C0024_ZERO_OUT_TH ? height - JVET_C0024_ZERO_OUT_TH : 0;
498
499
1.81M
  if( tu.cu->lfnstIdx )
500
1.13M
  {
501
1.13M
    if ((width == 4 && height > 4) || (width > 4 && height == 4))
502
323k
    {
503
323k
      skipWidth  = width - 4;
504
323k
      skipHeight = height - 4;
505
323k
    }
506
807k
    else if ((width >= 8 && height >= 8))
507
737k
    {
508
737k
      skipWidth  = width - 8;
509
737k
      skipHeight = height - 8;
510
737k
    }
511
1.13M
  }
512
513
1.81M
  TCoeff* block = m_blk;
514
1.81M
  TCoeff* tmp   = m_tmp;
515
516
1.81M
  const Pel* resiBuf    = resi.buf;
517
1.81M
  const int  resiStride = resi.stride;
518
519
1.81M
#if ENABLE_SIMD_TRAFO
520
1.81M
  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.81M
#if ENABLE_SIMD_TRAFO
532
1.81M
  else if( width & 7 )
533
346k
  {
534
346k
    g_tCoeffOps.cpyCoeff4( resiBuf, resiStride, block, width, height );
535
346k
  }
536
1.46M
  else
537
1.46M
  {
538
1.46M
    g_tCoeffOps.cpyCoeff8( resiBuf, resiStride, block, width, height );
539
1.46M
  }
540
1.81M
#endif //ENABLE_SIMD_TRAFO
541
542
1.81M
  if (width > 1 && height > 1)
543
1.81M
  {
544
1.81M
    const int shift_1st = ((Log2(width )) + bitDepth + TRANSFORM_MATRIX_SHIFT) - maxLog2TrDynamicRange;
545
1.81M
    const int shift_2nd =  (Log2(height))            + TRANSFORM_MATRIX_SHIFT;
546
1.81M
    CHECK( shift_1st < 0, "Negative shift" );
547
1.81M
    CHECK( shift_2nd < 0, "Negative shift" );
548
1.81M
    fastFwdTrans[trTypeHor][transformWidthIndex](block, tmp, shift_1st, height, 0, skipWidth);
549
1.81M
    fastFwdTrans[trTypeVer][transformHeightIndex](tmp, dstCoeff.buf, shift_2nd, width, skipWidth, skipHeight);
550
1.81M
  }
551
285
  else if (height == 1)   // 1-D horizontal transform
552
292
  {
553
292
    const int shift = ((Log2(width )) + bitDepth + TRANSFORM_MATRIX_SHIFT) - maxLog2TrDynamicRange;
554
292
    CHECK( shift < 0, "Negative shift" );
555
292
    fastFwdTrans[trTypeHor][transformWidthIndex](block, dstCoeff.buf, shift, 1, 0, skipWidth);
556
292
  }
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.81M
}
565
566
567
void TrQuant::xIT( const TransformUnit& tu, const ComponentID compID, const CCoeffBuf& pCoeff, PelBuf& pResidual )
568
749k
{
569
749k
  PROFILER_SCOPE_AND_STAGE( 1, _TPROF, P_TRAFO );
570
571
749k
  const int      width                  = pCoeff.width;
572
749k
  const int      height                 = pCoeff.height;
573
749k
  const unsigned maxLog2TrDynamicRange  = tu.cs->sps->getMaxLog2TrDynamicRange();
574
749k
  const unsigned bitDepth               = tu.cs->sps->bitDepths[toChannelType( compID )];
575
749k
  const int      TRANSFORM_MATRIX_SHIFT = g_transformMatrixShift[TRANSFORM_INVERSE];
576
749k
  const TCoeff   clipMinimum            = -( 1 << maxLog2TrDynamicRange );
577
749k
  const TCoeff   clipMaximum            =  ( 1 << maxLog2TrDynamicRange ) - 1;
578
749k
  const uint32_t transformWidthIndex    = Log2(width )- 1;                                // nLog2WidthMinus1, since transform start from 2-point
579
749k
  const uint32_t transformHeightIndex   = Log2(height) - 1;                                // nLog2HeightMinus1, since transform start from 2-point
580
581
582
749k
  int trTypeHor = DCT2;
583
749k
  int trTypeVer = DCT2;
584
585
749k
  xSetTrTypes( tu, compID, width, height, trTypeHor, trTypeVer );
586
587
749k
  int skipWidth  = ( trTypeHor != DCT2 && width  == 32 ) ? 16 : width  > JVET_C0024_ZERO_OUT_TH ? width  - JVET_C0024_ZERO_OUT_TH : 0;
588
749k
  int skipHeight = ( trTypeVer != DCT2 && height == 32 ) ? 16 : height > JVET_C0024_ZERO_OUT_TH ? height - JVET_C0024_ZERO_OUT_TH : 0;
589
590
749k
  if (tu.cs->sps->LFNST && tu.cu->lfnstIdx)
591
484k
  {
592
484k
    if ((width == 4 && height > 4) || (width > 4 && height == 4))
593
140k
    {
594
140k
      skipWidth = width - 4;
595
140k
      skipHeight = height - 4;
596
140k
    }
597
344k
    else if ((width >= 8 && height >= 8))
598
306k
    {
599
306k
      skipWidth = width - 8;
600
306k
      skipHeight = height - 8;
601
306k
    }
602
484k
  }
603
604
749k
  TCoeff *block = m_blk;
605
749k
  TCoeff *tmp   = m_tmp;
606
749k
  if (width > 1 && height > 1)   // 2-D transform
607
749k
  {
608
749k
    const int shift_1st =   TRANSFORM_MATRIX_SHIFT + 1; // 1 has been added to shift_1st at the expense of shift_2nd
609
749k
    const int shift_2nd = ( TRANSFORM_MATRIX_SHIFT + maxLog2TrDynamicRange - 1 ) - bitDepth;
610
749k
    CHECK( shift_1st < 0, "Negative shift" );
611
749k
    CHECK( shift_2nd < 0, "Negative shift" );
612
749k
    fastInvTrans[trTypeVer][transformHeightIndex](pCoeff.buf, tmp, shift_1st, width, skipWidth, skipHeight, clipMinimum, clipMaximum);
613
749k
    fastInvTrans[trTypeHor][transformWidthIndex](tmp, block, shift_2nd, height, 0, skipWidth, clipMinimum, clipMaximum);
614
749k
  }
615
73
  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
73
  else   // if(iHeight == 1) //1-D horizontal transform
622
73
  {
623
73
    const int shift = (TRANSFORM_MATRIX_SHIFT + maxLog2TrDynamicRange - 1) - bitDepth;
624
73
    CHECK(shift < 0, "Negative shift");
625
73
    fastInvTrans[trTypeHor][transformWidthIndex](pCoeff.buf, block, shift + 1, 1, 0, skipWidth, clipMinimum, clipMaximum);
626
73
  }
627
628
749k
#if ENABLE_SIMD_TRAFO
629
749k
  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
749k
#if ENABLE_SIMD_TRAFO
646
749k
  else if( width & 7 )
647
161k
  {
648
161k
    g_tCoeffOps.cpyResi4( block, pResidual.buf, pResidual.stride, width, height );
649
161k
  }
650
588k
  else
651
588k
  {
652
588k
    g_tCoeffOps.cpyResi8( block, pResidual.buf, pResidual.stride, width, height );
653
588k
  }
654
749k
#endif //ENABLE_SIMD_TRAFO
655
749k
}
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
46.8k
{
664
46.8k
  const CompArea& area = tu.blocks[compID];
665
46.8k
  const int width = area.width;
666
46.8k
  const int height = area.height;
667
668
469k
  for (uint32_t y = 0; y < height; y++)
669
422k
  {
670
4.68M
    for (uint32_t x = 0; x < width; x++)
671
4.25M
    {
672
4.25M
      pResidual.at(x, y) = Pel(pCoeff.at(x, y));
673
4.25M
    }
674
422k
  }
675
46.8k
}
676
677
void TrQuant::xQuant(TransformUnit& tu, const ComponentID compID, const CCoeffBuf& pSrc, TCoeff &uiAbsSum, const QpParam& cQP, const Ctx& ctx)
678
1.91M
{
679
1.91M
  PROFILER_SCOPE_AND_STAGE( 1, _TPROF, P_QUANT );
680
1.91M
  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
1.91M
}
686
687
688
void TrQuant::transformNxN(TransformUnit &tu, const ComponentID compID, const QpParam &cQP, TCoeff &uiAbsSum, const Ctx &ctx, const bool loadTr)
689
1.91M
{
690
1.91M
        CodingStructure &cs = *tu.cs;
691
1.91M
  const CompArea& rect      = tu.blocks[compID];
692
1.91M
  const uint32_t uiWidth        = rect.width;
693
1.91M
  const uint32_t uiHeight       = rect.height;
694
695
1.91M
  const CPelBuf resiBuf     = cs.getResiBuf(rect);
696
697
1.91M
  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
1.91M
  if (tu.cu->bdpcmM[toChannelType(compID)])
704
96.2k
  {
705
96.2k
    tu.mtsIdx[compID] = MTS_SKIP;
706
96.2k
  }
707
708
1.91M
  uiAbsSum = 0;
709
1.91M
  CHECK( cs.sps->getMaxTbSize() < uiWidth, "Unsupported transformation size" );
710
711
1.91M
  CoeffBuf tempCoeff(loadTr ? m_mtsCoeffs[tu.mtsIdx[compID]] : m_plTempCoeff, rect);
712
1.91M
  if (!loadTr)
713
1.89M
  {
714
1.89M
    DTRACE_PEL_BUF( D_RESIDUALS, resiBuf, tu, tu.cu->predMode, compID );
715
1.89M
    if (tu.mtsIdx[compID] == MTS_SKIP)
716
96.2k
    {
717
96.2k
      xTransformSkip(tu, compID, resiBuf, tempCoeff.buf);
718
96.2k
    }
719
1.79M
    else
720
1.79M
    {
721
1.79M
      xT(tu, compID, resiBuf, tempCoeff, uiWidth, uiHeight);
722
1.79M
    }
723
1.89M
  }
724
1.91M
  if (cs.sps->LFNST)
725
1.91M
  {
726
1.91M
    xFwdLfnst(tu, compID, loadTr);
727
1.91M
  }
728
1.91M
  DTRACE_COEFF_BUF( D_TCOEFF, tempCoeff, tu, tu.cu->predMode, compID );
729
730
1.91M
  xQuant( tu, compID, tempCoeff, uiAbsSum, cQP, ctx );
731
732
1.91M
  DTRACE_COEFF_BUF( D_TCOEFF, tu.getCoeffs( compID ), tu, tu.cu->predMode, compID );
733
734
  // set coded block flag (CBF)
735
1.91M
  TU::setCbfAtDepth (tu, compID, tu.depth, uiAbsSum > 0);
736
1.91M
}
737
738
void TrQuant::checktransformsNxN( TransformUnit &tu, std::vector<TrMode> *trModes, const int maxCand, const ComponentID compID)
739
16.8k
{
740
16.8k
  CodingStructure &cs     = *tu.cs;
741
16.8k
  const CompArea& rect    = tu.blocks[compID];
742
16.8k
  const uint32_t   width  = rect.width;
743
16.8k
  const uint32_t   height = rect.height;
744
745
16.8k
  const CPelBuf resiBuf = cs.getResiBuf(rect);
746
747
16.8k
  CHECK(cs.sps->getMaxTbSize() < width, "Unsupported transformation size");
748
16.8k
  int                           pos = 0;
749
16.8k
  std::vector<TrCost>           trCosts;
750
16.8k
  std::vector<TrMode>::iterator it      = trModes->begin();
751
16.8k
  const double                  facBB[] = { 1.2, 1.3, 1.3, 1.4, 1.5 };
752
50.6k
  while (it != trModes->end())
753
33.7k
  {
754
33.7k
    tu.mtsIdx[compID] = it->first;
755
33.7k
    CoeffBuf tempCoeff(m_mtsCoeffs[tu.mtsIdx[compID]], rect);
756
33.7k
    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
33.7k
    if (tu.mtsIdx[compID] == MTS_SKIP)
764
16.8k
    {
765
16.8k
      xTransformSkip(tu, compID, resiBuf, tempCoeff.buf);
766
16.8k
    }
767
16.8k
    else
768
16.8k
    {
769
16.8k
      xT(tu, compID, resiBuf, tempCoeff, width, height);
770
16.8k
    }
771
772
33.7k
    int sumAbs = 0;
773
5.98M
    for (int pos = 0; pos < width * height; pos++)
774
5.94M
    {
775
5.94M
      sumAbs += abs(tempCoeff.buf[pos]);
776
5.94M
    }
777
778
33.7k
    double scaleSAD = 1.0;
779
33.7k
    if (tu.mtsIdx[compID] == MTS_SKIP && ((floorLog2(width) + floorLog2(height)) & 1) == 1)
780
7.12k
    {
781
7.12k
      scaleSAD = 1.0 / 1.414213562;   // compensate for not scaling transform skip coefficients by 1/sqrt(2)
782
7.12k
    }
783
33.7k
    if (tu.mtsIdx[compID] == MTS_SKIP)
784
16.8k
    {
785
16.8k
      int trShift = getTransformShift(tu.cu->slice->sps->bitDepths[CH_L], rect.size(), tu.cu->slice->sps->getMaxLog2TrDynamicRange());
786
16.8k
      scaleSAD *= pow(2, trShift);
787
16.8k
    }
788
33.7k
    trCosts.push_back(TrCost(int(std::min<double>(sumAbs * scaleSAD, std::numeric_limits<int>::max())), pos++));
789
33.7k
    it++;
790
33.7k
  }
791
792
16.8k
  int                           numTests = 0;
793
16.8k
  std::vector<TrCost>::iterator itC      = trCosts.begin();
794
16.8k
  const double                  fac      = facBB[std::max(0, floorLog2(std::max(width, height)) - 2)];
795
16.8k
  const double                  thr      = fac * trCosts.begin()->first;
796
16.8k
  const double                  thrTS    = trCosts.begin()->first;
797
50.6k
  while (itC != trCosts.end())
798
33.7k
  {
799
33.7k
    const bool testTr               = itC->first <= (trModes->at(itC->second).first == 1 ? thrTS : thr) && numTests <= maxCand;
800
33.7k
    trModes->at(itC->second).second = testTr;
801
33.7k
    numTests += testTr;
802
33.7k
    itC++;
803
33.7k
  }
804
16.8k
}
805
806
uint32_t TrQuant::xGetLFNSTIntraMode( const Area& tuArea, const uint32_t dirMode )
807
1.61M
{
808
1.61M
  if (dirMode < 2)
809
911k
  {
810
911k
    return dirMode;
811
911k
  }
812
813
704k
  static const int modeShift[] = { 0, 6, 10, 12, 14, 15 };
814
815
704k
  const int width  = int(tuArea.width);
816
704k
  const int height = int(tuArea.height);
817
818
704k
  if (width > height && dirMode < 2 + modeShift[floorLog2(width) - floorLog2(height)])
819
176
  {
820
176
    return dirMode + (VDIA_IDX - 1) + (NUM_EXT_LUMA_MODE >> 1);
821
176
  }
822
704k
  else if (height > width && dirMode > VDIA_IDX - modeShift[floorLog2(height) - floorLog2(width)])
823
66.2k
  {
824
66.2k
    return dirMode - (VDIA_IDX + 1) + (NUM_EXT_LUMA_MODE >> 1) + NUM_LUMA_MODE;
825
66.2k
  }
826
827
637k
  return dirMode;
828
704k
}
829
830
831
bool TrQuant::xGetTransposeFlag(uint32_t intraMode)
832
1.61M
{
833
1.61M
  return ((intraMode >= NUM_LUMA_MODE) && (intraMode >= (NUM_LUMA_MODE + (NUM_EXT_LUMA_MODE >> 1))))
834
1.61M
         || ((intraMode < NUM_LUMA_MODE) && (intraMode > DIA_IDX));
835
1.61M
}
836
837
838
void TrQuant::xInvLfnst(const TransformUnit &tu, const ComponentID compID)
839
796k
{
840
796k
  const CompArea &area     = tu.blocks[compID];
841
796k
  const uint32_t  width    = area.width;
842
796k
  const uint32_t  height   = area.height;
843
796k
  const uint32_t  lfnstIdx = tu.cu->lfnstIdx;
844
796k
  if (lfnstIdx && tu.mtsIdx[compID] != MTS_SKIP && (CU::isSepTree(*tu.cu) ? true : isLuma(compID)))
845
484k
  {
846
484k
    const CodingUnit& cu = *tu.cs->getCU(area.pos(), toChannelType(compID), TREE_D);
847
484k
    const bool         whge3 = width >= 8 && height >= 8;
848
484k
    const ScanElement *scan =
849
484k
      whge3
850
484k
        ? g_coefTopLeftDiagScan8x8[Log2(width)] 
851
484k
        : getScanOrder(SCAN_GROUPED_4x4, Log2(area.width), Log2(area.height));
852
484k
    uint32_t intraMode = CU::getFinalIntraMode(cu, toChannelType(compID));
853
854
484k
    if (CU::isLMCMode( cu.intraDir[toChannelType(compID)]))
855
79.9k
    {
856
79.9k
      intraMode = CU::getCoLocatedIntraLumaMode(cu);
857
79.9k
    }
858
484k
    if (CU::isMIP(cu, toChannelType(compID)))
859
4.69k
    {
860
4.69k
      intraMode = PLANAR_IDX;
861
4.69k
    }
862
484k
    CHECK(intraMode >= NUM_INTRA_MODE - 1, "Invalid intra mode");
863
864
484k
    if (lfnstIdx < 3)
865
484k
    {
866
484k
      if (tu.cu->ispMode && isLuma(compID))
867
7.10k
      {
868
7.10k
        intraMode = xGetLFNSTIntraMode(tu.cu->blocks[compID], intraMode);
869
7.10k
      }
870
477k
      else
871
477k
        intraMode = xGetLFNSTIntraMode(tu.blocks[compID], intraMode);
872
484k
      bool      transposeFlag = xGetTransposeFlag(intraMode);
873
484k
      const int sbSize        = whge3 ? 8 : 4;
874
484k
      bool      tu4x4Flag     = (width == 4 && height == 4);
875
484k
      bool      tu8x8Flag     = (width == 8 && height == 8);
876
484k
      TCoeff *  lfnstTemp;
877
484k
      TCoeff *  coeffTemp;
878
484k
      int       y;
879
484k
      lfnstTemp                  = m_tempInMatrix;   // inverse spectral rearrangement
880
484k
      coeffTemp                  = m_plTempCoeff;
881
484k
      TCoeff *           dst     = lfnstTemp;
882
484k
      const ScanElement *scanPtr = scan;
883
8.24M
      for (y = 0; y < 16; y++)
884
7.75M
      {
885
7.75M
        *dst++ = coeffTemp[scanPtr->idx];
886
7.75M
        scanPtr++;
887
7.75M
      }
888
889
484k
      m_invLfnstNxN( m_tempInMatrix, m_tempOutMatrix, g_lfnstLut[intraMode], lfnstIdx - 1, sbSize, ( tu4x4Flag || tu8x8Flag ) ? 8 : 16 );
890
891
484k
      lfnstTemp = m_tempOutMatrix;   // inverse spectral rearrangement
892
893
484k
      if (transposeFlag)
894
44.6k
      {
895
44.6k
        if (sbSize == 4)
896
8.88k
        {
897
44.4k
          for (y = 0; y < 4; y++)
898
35.5k
          {
899
35.5k
            coeffTemp[0] = lfnstTemp[0];
900
35.5k
            coeffTemp[1] = lfnstTemp[4];
901
35.5k
            coeffTemp[2] = lfnstTemp[8];
902
35.5k
            coeffTemp[3] = lfnstTemp[12];
903
35.5k
            lfnstTemp++;
904
35.5k
            coeffTemp += width;
905
35.5k
          }
906
8.88k
        }
907
35.7k
        else   // ( sbSize == 8 )
908
35.7k
        {
909
322k
          for (y = 0; y < 8; y++)
910
286k
          {
911
286k
            coeffTemp[0] = lfnstTemp[0];
912
286k
            coeffTemp[1] = lfnstTemp[8];
913
286k
            coeffTemp[2] = lfnstTemp[16];
914
286k
            coeffTemp[3] = lfnstTemp[24];
915
286k
            if (y < 4)
916
143k
            {
917
143k
              coeffTemp[4] = lfnstTemp[32];
918
143k
              coeffTemp[5] = lfnstTemp[36];
919
143k
              coeffTemp[6] = lfnstTemp[40];
920
143k
              coeffTemp[7] = lfnstTemp[44];
921
143k
            }
922
286k
            lfnstTemp++;
923
286k
            coeffTemp += width;
924
286k
          }
925
35.7k
        }
926
44.6k
      }
927
440k
      else
928
440k
      {
929
3.28M
        for (y = 0; y < sbSize; y++)
930
2.84M
        {
931
2.84M
          uint32_t uiStride = (y < 4) ? sbSize : 4;
932
2.84M
          ::memcpy(coeffTemp, lfnstTemp, uiStride * sizeof(TCoeff));
933
2.84M
          lfnstTemp += uiStride;
934
2.84M
          coeffTemp += width;
935
2.84M
        }
936
440k
      }
937
484k
    }
938
484k
  }
939
796k
}
940
941
942
void TrQuant::xFwdLfnst(const TransformUnit &tu, const ComponentID compID, const bool loadTr)
943
1.91M
{
944
1.91M
  const CompArea &area     = tu.blocks[compID];
945
1.91M
  const uint32_t  width    = area.width;
946
1.91M
  const uint32_t  height   = area.height;
947
1.91M
  const uint32_t  lfnstIdx = tu.cu->lfnstIdx;
948
1.91M
  if (lfnstIdx && tu.mtsIdx[compID] != MTS_SKIP && (CU::isSepTree(*tu.cu) ? true : isLuma(compID)))
949
1.13M
  {
950
1.13M
    const CodingUnit& cu = *tu.cs->getCU(area.pos(), toChannelType(compID), TREE_D);
951
1.13M
    const bool         whge3 = width >= 8 && height >= 8;
952
1.13M
    const ScanElement *scan =
953
1.13M
      whge3
954
1.13M
        ? g_coefTopLeftDiagScan8x8[Log2(width)] 
955
1.13M
        : getScanOrder(SCAN_GROUPED_4x4, Log2(area.width), Log2(area.height));   
956
1.13M
    uint32_t intraMode = CU::getFinalIntraMode(cu, toChannelType(compID));
957
958
1.13M
    if (CU::isLMCMode(cu.intraDir[toChannelType(compID)]))
959
101k
    {
960
101k
      intraMode = CU::getCoLocatedIntraLumaMode(cu);
961
101k
    }
962
1.13M
    if (CU::isMIP(cu, toChannelType(compID)))
963
7.70k
    {
964
7.70k
      intraMode = PLANAR_IDX;
965
7.70k
    }
966
1.13M
    CHECK(intraMode >= NUM_INTRA_MODE - 1, "Invalid intra mode");
967
968
1.13M
    if (lfnstIdx < 3)
969
1.13M
    {
970
1.13M
      if (tu.cu->ispMode && isLuma(compID))
971
11.0k
      {
972
11.0k
        intraMode = xGetLFNSTIntraMode(tu.cu->blocks[compID], intraMode);
973
11.0k
      }
974
1.11M
      else
975
1.11M
      {
976
1.11M
        intraMode = xGetLFNSTIntraMode(tu.blocks[compID], intraMode);
977
1.11M
      }
978
1.13M
      bool      transposeFlag = xGetTransposeFlag(intraMode);
979
1.13M
      const int sbSize        = whge3 ? 8 : 4;
980
1.13M
      bool      tu4x4Flag     = (width == 4 && height == 4);
981
1.13M
      bool      tu8x8Flag     = (width == 8 && height == 8);
982
1.13M
      TCoeff*   lfnstTemp;
983
1.13M
      TCoeff*   coeffTemp;
984
1.13M
      TCoeff*   tempCoeff     = loadTr ? m_mtsCoeffs[tu.mtsIdx[compID]] : m_plTempCoeff;
985
986
1.13M
      int y;
987
1.13M
      lfnstTemp = m_tempInMatrix;   // forward low frequency non-separable transform
988
1.13M
      coeffTemp = tempCoeff;
989
990
1.13M
      if (transposeFlag)
991
239k
      {
992
239k
        if (sbSize == 4)
993
70.9k
        {
994
354k
          for (y = 0; y < 4; y++)
995
283k
          {
996
283k
            lfnstTemp[0]  = coeffTemp[0];
997
283k
            lfnstTemp[4]  = coeffTemp[1];
998
283k
            lfnstTemp[8]  = coeffTemp[2];
999
283k
            lfnstTemp[12] = coeffTemp[3];
1000
283k
            lfnstTemp++;
1001
283k
            coeffTemp += width;
1002
283k
          }
1003
70.9k
        }
1004
168k
        else   // ( sbSize == 8 )
1005
168k
        {
1006
1.51M
          for (y = 0; y < 8; y++)
1007
1.34M
          {
1008
1.34M
            lfnstTemp[0]  = coeffTemp[0];
1009
1.34M
            lfnstTemp[8]  = coeffTemp[1];
1010
1.34M
            lfnstTemp[16] = coeffTemp[2];
1011
1.34M
            lfnstTemp[24] = coeffTemp[3];
1012
1.34M
            if (y < 4)
1013
672k
            {
1014
672k
              lfnstTemp[32] = coeffTemp[4];
1015
672k
              lfnstTemp[36] = coeffTemp[5];
1016
672k
              lfnstTemp[40] = coeffTemp[6];
1017
672k
              lfnstTemp[44] = coeffTemp[7];
1018
672k
            }
1019
1.34M
            lfnstTemp++;
1020
1.34M
            coeffTemp += width;
1021
1.34M
          }
1022
168k
        }
1023
239k
      }
1024
891k
      else
1025
891k
      {
1026
6.73M
        for (y = 0; y < sbSize; y++)
1027
5.84M
        {
1028
5.84M
          uint32_t uiStride = (y < 4) ? sbSize : 4;
1029
5.84M
          ::memcpy(lfnstTemp, coeffTemp, uiStride * sizeof(TCoeff));
1030
5.84M
          lfnstTemp += uiStride;
1031
5.84M
          coeffTemp += width;
1032
5.84M
        }
1033
891k
      }
1034
1035
1.13M
      m_fwdLfnstNxN( m_tempInMatrix, m_tempOutMatrix, g_lfnstLut[intraMode], lfnstIdx - 1, sbSize, ( tu4x4Flag || tu8x8Flag ) ? 8 : 16 );
1036
1037
1.13M
      lfnstTemp                        = m_tempOutMatrix;   // forward spectral rearrangement
1038
1.13M
      coeffTemp                        = tempCoeff;
1039
1.13M
      const ScanElement *scanPtr       = scan;
1040
1.13M
      int                lfnstCoeffNum = (sbSize == 4) ? sbSize * sbSize : 48;
1041
42.8M
      for (y = 0; y < lfnstCoeffNum; y++)
1042
41.6M
      {
1043
41.6M
        coeffTemp[scanPtr->idx] = *lfnstTemp++;
1044
41.6M
        scanPtr++;
1045
41.6M
      }
1046
1.13M
    }
1047
1.13M
  }
1048
1.91M
}
1049
1050
void TrQuant::xTransformSkip(const TransformUnit& tu, const ComponentID& compID, const CPelBuf& resi, TCoeff* psCoeff)
1051
113k
{
1052
113k
  const CompArea& rect = tu.blocks[compID];
1053
113k
  const uint32_t width = rect.width;
1054
113k
  const uint32_t height = rect.height;
1055
1056
1.23M
  for (uint32_t y = 0, coefficientIndex = 0; y < height; y++)
1057
1.11M
  {
1058
13.3M
    for (uint32_t x = 0; x < width; x++, coefficientIndex++)
1059
12.1M
    {
1060
12.1M
      psCoeff[coefficientIndex] = TCoeff(resi.at(x, y));
1061
12.1M
    }
1062
1.11M
  }
1063
113k
}
1064
} // namespace vvenc
1065
1066
//! \}
1067