xref: /aosp_15_r20/external/libgav1/src/reconstruction.cc (revision 095378508e87ed692bf8dfeb34008b65b3735891)
1 // Copyright 2019 The libgav1 Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "src/reconstruction.h"
16 
17 #include <algorithm>
18 #include <cassert>
19 #include <cstdint>
20 
21 #include "src/utils/common.h"
22 
23 namespace libgav1 {
24 namespace {
25 
26 // Maps TransformType to dsp::Transform1d for the row transforms.
27 constexpr dsp::Transform1d kRowTransform[kNumTransformTypes] = {
28     dsp::kTransform1dDct,      dsp::kTransform1dAdst,
29     dsp::kTransform1dDct,      dsp::kTransform1dAdst,
30     dsp::kTransform1dAdst,     dsp::kTransform1dDct,
31     dsp::kTransform1dAdst,     dsp::kTransform1dAdst,
32     dsp::kTransform1dAdst,     dsp::kTransform1dIdentity,
33     dsp::kTransform1dIdentity, dsp::kTransform1dDct,
34     dsp::kTransform1dIdentity, dsp::kTransform1dAdst,
35     dsp::kTransform1dIdentity, dsp::kTransform1dAdst};
36 
37 // Maps TransformType to dsp::Transform1d for the column transforms.
38 constexpr dsp::Transform1d kColumnTransform[kNumTransformTypes] = {
39     dsp::kTransform1dDct,  dsp::kTransform1dDct,
40     dsp::kTransform1dAdst, dsp::kTransform1dAdst,
41     dsp::kTransform1dDct,  dsp::kTransform1dAdst,
42     dsp::kTransform1dAdst, dsp::kTransform1dAdst,
43     dsp::kTransform1dAdst, dsp::kTransform1dIdentity,
44     dsp::kTransform1dDct,  dsp::kTransform1dIdentity,
45     dsp::kTransform1dAdst, dsp::kTransform1dIdentity,
46     dsp::kTransform1dAdst, dsp::kTransform1dIdentity};
47 
GetTransform1dSize(int size_log2)48 dsp::Transform1dSize GetTransform1dSize(int size_log2) {
49   return static_cast<dsp::Transform1dSize>(size_log2 - 2);
50 }
51 
52 // Returns the number of rows to process based on |non_zero_coeff_count|. The
53 // transform loops process either 4 or a multiple of 8 rows. Use the
54 // TransformClass derived from |tx_type| to determine the scan order.
55 template <int tx_width>
GetNumRows(TransformType tx_type,int tx_height,int non_zero_coeff_count)56 int GetNumRows(TransformType tx_type, int tx_height, int non_zero_coeff_count) {
57   const TransformClass tx_class = GetTransformClass(tx_type);
58 
59   switch (tx_class) {
60     case kTransformClass2D:
61       if (tx_width == 4) {
62         if (non_zero_coeff_count <= 13) return 4;
63         if (non_zero_coeff_count <= 29) return 8;
64       }
65       if (tx_width == 8) {
66         if (non_zero_coeff_count <= 10) return 4;
67         if ((non_zero_coeff_count <= 14) & (tx_height > 8)) return 4;
68         if (non_zero_coeff_count <= 43) return 8;
69         if ((non_zero_coeff_count <= 107) & (tx_height > 16)) return 16;
70         if ((non_zero_coeff_count <= 171) & (tx_height > 16)) return 24;
71       }
72       if (tx_width == 16) {
73         if (non_zero_coeff_count <= 10) return 4;
74         if ((non_zero_coeff_count <= 14) & (tx_height > 16)) return 4;
75         if (non_zero_coeff_count <= 36) return 8;
76         if ((non_zero_coeff_count <= 44) & (tx_height > 16)) return 8;
77         if ((non_zero_coeff_count <= 151) & (tx_height > 16)) return 16;
78         if ((non_zero_coeff_count <= 279) & (tx_height > 16)) return 24;
79       }
80       if (tx_width == 32) {
81         if (non_zero_coeff_count <= 10) return 4;
82         if (non_zero_coeff_count <= 36) return 8;
83         if ((non_zero_coeff_count <= 136) & (tx_height > 16)) return 16;
84         if ((non_zero_coeff_count <= 300) & (tx_height > 16)) return 24;
85       }
86       break;
87 
88     case kTransformClassHorizontal:
89       if (non_zero_coeff_count <= 4) return 4;
90       if (non_zero_coeff_count <= 8) return 8;
91       if ((non_zero_coeff_count <= 16) & (tx_height > 16)) return 16;
92       if ((non_zero_coeff_count <= 24) & (tx_height > 16)) return 24;
93       break;
94 
95     default:
96       assert(tx_class == kTransformClassVertical);
97       if (tx_width == 4) {
98         if (non_zero_coeff_count <= 16) return 4;
99         if (non_zero_coeff_count <= 32) return 8;
100       }
101       if (tx_width == 8) {
102         if (non_zero_coeff_count <= 32) return 4;
103         if (non_zero_coeff_count <= 64) return 8;
104         // There's no need to check tx_height since the maximum values for
105         // smaller sizes are: 8x8: 63, 8x16: 127.
106         if (non_zero_coeff_count <= 128) return 16;
107         if (non_zero_coeff_count <= 192) return 24;
108       }
109       if (tx_width == 16) {
110         if (non_zero_coeff_count <= 64) return 4;
111         if (non_zero_coeff_count <= 128) return 8;
112         // There's no need to check tx_height since the maximum values for
113         // smaller sizes are: 16x8: 127, 16x16: 255.
114         if (non_zero_coeff_count <= 256) return 16;
115         if (non_zero_coeff_count <= 384) return 24;
116       }
117       if (tx_width == 32) {
118         if (non_zero_coeff_count <= 128) return 4;
119         if (non_zero_coeff_count <= 256) return 8;
120         // There's no need to check tx_height since the maximum values for
121         // smaller sizes are: 32x8 is 255, 32x16 is 511.
122         if ((non_zero_coeff_count <= 512)) return 16;
123         if ((non_zero_coeff_count <= 768)) return 24;
124       }
125       break;
126   }
127   return (tx_width >= 16) ? std::min(tx_height, 32) : tx_height;
128 }
129 
130 }  // namespace
131 
132 template <typename Residual, typename Pixel>
Reconstruct(const dsp::Dsp & dsp,TransformType tx_type,TransformSize tx_size,bool lossless,Residual * const buffer,int start_x,int start_y,Array2DView<Pixel> * frame,int non_zero_coeff_count)133 void Reconstruct(const dsp::Dsp& dsp, TransformType tx_type,
134                  TransformSize tx_size, bool lossless, Residual* const buffer,
135                  int start_x, int start_y, Array2DView<Pixel>* frame,
136                  int non_zero_coeff_count) {
137   static_assert(sizeof(Residual) == 2 || sizeof(Residual) == 4, "");
138   const int tx_width_log2 = kTransformWidthLog2[tx_size];
139   const int tx_height_log2 = kTransformHeightLog2[tx_size];
140 
141   int tx_height = (non_zero_coeff_count == 1) ? 1 : kTransformHeight[tx_size];
142   if (tx_height > 4) {
143     static constexpr int (*kGetNumRows[])(TransformType tx_type, int tx_height,
144                                           int non_zero_coeff_count) = {
145         &GetNumRows<4>, &GetNumRows<8>, &GetNumRows<16>, &GetNumRows<32>,
146         &GetNumRows<32>};
147     tx_height = kGetNumRows[tx_width_log2 - 2](tx_type, tx_height,
148                                                non_zero_coeff_count);
149   }
150   assert(tx_height <= 32);
151 
152   // Row transform.
153   const dsp::Transform1dSize row_transform_size =
154       GetTransform1dSize(tx_width_log2);
155   const dsp::Transform1d row_transform =
156       lossless ? dsp::kTransform1dWht : kRowTransform[tx_type];
157   const dsp::InverseTransformAddFunc row_transform_func =
158       dsp.inverse_transforms[row_transform][row_transform_size][dsp::kRow];
159   assert(row_transform_func != nullptr);
160 
161   row_transform_func(tx_type, tx_size, tx_height, buffer, start_x, start_y,
162                      frame);
163 
164   // Column transform.
165   const dsp::Transform1dSize column_transform_size =
166       GetTransform1dSize(tx_height_log2);
167   const dsp::Transform1d column_transform =
168       lossless ? dsp::kTransform1dWht : kColumnTransform[tx_type];
169   const dsp::InverseTransformAddFunc column_transform_func =
170       dsp.inverse_transforms[column_transform][column_transform_size]
171                             [dsp::kColumn];
172   assert(column_transform_func != nullptr);
173 
174   column_transform_func(tx_type, tx_size, tx_height, buffer, start_x, start_y,
175                         frame);
176 }
177 
178 template void Reconstruct(const dsp::Dsp& dsp, TransformType tx_type,
179                           TransformSize tx_size, bool lossless, int16_t* buffer,
180                           int start_x, int start_y, Array2DView<uint8_t>* frame,
181                           int non_zero_coeff_count);
182 #if LIBGAV1_MAX_BITDEPTH >= 10
183 template void Reconstruct(const dsp::Dsp& dsp, TransformType tx_type,
184                           TransformSize tx_size, bool lossless, int32_t* buffer,
185                           int start_x, int start_y,
186                           Array2DView<uint16_t>* frame,
187                           int non_zero_coeff_count);
188 #endif
189 
190 }  // namespace libgav1
191