/src/serenity/Userland/Libraries/LibMedia/Video/VP9/Decoder.cpp
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2021, Hunter Salyer <thefalsehonesty@gmail.com> |
3 | | * Copyright (c) 2022, Gregory Bertilson <zaggy1024@gmail.com> |
4 | | * |
5 | | * SPDX-License-Identifier: BSD-2-Clause |
6 | | */ |
7 | | |
8 | | #include <AK/IntegralMath.h> |
9 | | #include <AK/TypedTransfer.h> |
10 | | #include <LibGfx/Size.h> |
11 | | #include <LibMedia/Color/CodingIndependentCodePoints.h> |
12 | | |
13 | | #include "Context.h" |
14 | | #include "Decoder.h" |
15 | | #include "Utilities.h" |
16 | | |
17 | | #if defined(AK_COMPILER_GCC) |
18 | | # pragma GCC optimize("O3") |
19 | | #endif |
20 | | |
21 | | namespace Media::Video::VP9 { |
22 | | |
23 | | Decoder::Decoder() |
24 | 757 | : m_parser(make<Parser>(*this)) |
25 | 757 | { |
26 | 757 | } |
27 | | |
28 | | DecoderErrorOr<void> Decoder::receive_sample(Duration timestamp, ReadonlyBytes chunk_data) |
29 | 757 | { |
30 | 757 | auto superframe_sizes = m_parser->parse_superframe_sizes(chunk_data); |
31 | | |
32 | 757 | if (superframe_sizes.is_empty()) { |
33 | 235 | return decode_frame(timestamp, chunk_data); |
34 | 235 | } |
35 | | |
36 | 522 | size_t offset = 0; |
37 | | |
38 | 2.24k | for (auto superframe_size : superframe_sizes) { |
39 | 2.24k | auto checked_size = Checked<size_t>(superframe_size); |
40 | 2.24k | checked_size += offset; |
41 | 2.24k | if (checked_size.has_overflow() || checked_size.value() > chunk_data.size()) |
42 | 312 | return DecoderError::with_description(DecoderErrorCategory::Corrupted, "Superframe size invalid"sv); |
43 | 1.92k | auto frame_data = chunk_data.slice(offset, superframe_size); |
44 | 1.92k | TRY(decode_frame(timestamp, frame_data)); |
45 | 1.72k | offset = checked_size.value(); |
46 | 1.72k | } |
47 | | |
48 | 3 | return {}; |
49 | 522 | } |
50 | | |
51 | | DecoderErrorOr<void> Decoder::decode_frame(Duration timestamp, ReadonlyBytes frame_data) |
52 | 2.16k | { |
53 | | // 1. The syntax elements for the coded frame are extracted as specified in sections 6 and 7. The syntax |
54 | | // tables include function calls indicating when the block decode processes should be triggered. |
55 | 2.16k | auto frame_context = TRY(m_parser->parse_frame(frame_data)); |
56 | | |
57 | | // 2. If loop_filter_level is not equal to 0, the loop filter process as specified in section 8.8 is invoked once the |
58 | | // coded frame has been decoded. |
59 | | // FIXME: Implement loop filtering. |
60 | | |
61 | | // 3. If all of the following conditions are true, PrevSegmentIds[ row ][ col ] is set equal to |
62 | | // SegmentIds[ row ][ col ] for row = 0..MiRows-1, for col = 0..MiCols-1: |
63 | | // − show_existing_frame is equal to 0, |
64 | | // − segmentation_enabled is equal to 1, |
65 | | // − segmentation_update_map is equal to 1. |
66 | | // This is handled by update_reference_frames. |
67 | | |
68 | | // 4. The output process as specified in section 8.9 is invoked. |
69 | 1.80k | if (frame_context.shows_a_frame()) { |
70 | 1.04k | switch (frame_context.color_config.bit_depth) { |
71 | 1.01k | case 8: |
72 | 1.01k | TRY(create_video_frame<u8>(timestamp, frame_context)); |
73 | 1.01k | break; |
74 | 5 | case 10: |
75 | 23 | case 12: |
76 | 23 | TRY(create_video_frame<u16>(timestamp, frame_context)); |
77 | 23 | break; |
78 | 1.04k | } |
79 | 1.04k | } |
80 | | |
81 | | // 5. The reference frame update process as specified in section 8.10 is invoked. |
82 | 1.80k | TRY(update_reference_frames(frame_context)); |
83 | 1.80k | return {}; |
84 | 1.80k | } |
85 | | |
86 | | inline CodingIndependentCodePoints get_cicp_color_space(FrameContext const& frame_context) |
87 | 1.04k | { |
88 | 1.04k | ColorPrimaries color_primaries; |
89 | 1.04k | TransferCharacteristics transfer_characteristics; |
90 | 1.04k | MatrixCoefficients matrix_coefficients; |
91 | | |
92 | 1.04k | switch (frame_context.color_config.color_space) { |
93 | 938 | case ColorSpace::Unknown: |
94 | 938 | color_primaries = ColorPrimaries::Unspecified; |
95 | 938 | transfer_characteristics = TransferCharacteristics::Unspecified; |
96 | 938 | matrix_coefficients = MatrixCoefficients::Unspecified; |
97 | 938 | break; |
98 | 28 | case ColorSpace::Bt601: |
99 | 28 | color_primaries = ColorPrimaries::BT601; |
100 | 28 | transfer_characteristics = TransferCharacteristics::BT601; |
101 | 28 | matrix_coefficients = MatrixCoefficients::BT601; |
102 | 28 | break; |
103 | 24 | case ColorSpace::Bt709: |
104 | 24 | color_primaries = ColorPrimaries::BT709; |
105 | 24 | transfer_characteristics = TransferCharacteristics::BT709; |
106 | 24 | matrix_coefficients = MatrixCoefficients::BT709; |
107 | 24 | break; |
108 | 8 | case ColorSpace::Smpte170: |
109 | | // https://www.kernel.org/doc/html/v4.9/media/uapi/v4l/pixfmt-007.html#colorspace-smpte-170m-v4l2-colorspace-smpte170m |
110 | 8 | color_primaries = ColorPrimaries::BT601; |
111 | 8 | transfer_characteristics = TransferCharacteristics::BT709; |
112 | 8 | matrix_coefficients = MatrixCoefficients::BT601; |
113 | 8 | break; |
114 | 36 | case ColorSpace::Smpte240: |
115 | 36 | color_primaries = ColorPrimaries::SMPTE240; |
116 | 36 | transfer_characteristics = TransferCharacteristics::SMPTE240; |
117 | 36 | matrix_coefficients = MatrixCoefficients::SMPTE240; |
118 | 36 | break; |
119 | 7 | case ColorSpace::Bt2020: |
120 | 7 | color_primaries = ColorPrimaries::BT2020; |
121 | | // Bit depth doesn't actually matter to our transfer functions since we |
122 | | // convert in floats of range 0-1 (for now?), but just for correctness set |
123 | | // the TC to match the bit depth here. |
124 | 7 | if (frame_context.color_config.bit_depth == 12) |
125 | 0 | transfer_characteristics = TransferCharacteristics::BT2020BitDepth12; |
126 | 7 | else if (frame_context.color_config.bit_depth == 10) |
127 | 0 | transfer_characteristics = TransferCharacteristics::BT2020BitDepth10; |
128 | 7 | else |
129 | 7 | transfer_characteristics = TransferCharacteristics::BT709; |
130 | 7 | matrix_coefficients = MatrixCoefficients::BT2020NonConstantLuminance; |
131 | 7 | break; |
132 | 0 | case ColorSpace::RGB: |
133 | 0 | color_primaries = ColorPrimaries::BT709; |
134 | 0 | transfer_characteristics = TransferCharacteristics::Linear; |
135 | 0 | matrix_coefficients = MatrixCoefficients::Identity; |
136 | 0 | break; |
137 | 0 | case ColorSpace::Reserved: |
138 | 0 | VERIFY_NOT_REACHED(); |
139 | 0 | break; |
140 | 1.04k | } |
141 | | |
142 | 1.04k | return { color_primaries, transfer_characteristics, matrix_coefficients, frame_context.color_config.color_range }; |
143 | 1.04k | } |
144 | | |
145 | | template<typename T> |
146 | | DecoderErrorOr<void> Decoder::create_video_frame(Duration timestamp, FrameContext const& frame_context) |
147 | 1.04k | { |
148 | | // (8.9) Output process |
149 | | |
150 | | // FIXME: If show_existing_frame is set, output from FrameStore[frame_to_show_map_index] here instead. |
151 | 1.04k | if (frame_context.shows_existing_frame()) { |
152 | 0 | dbgln("FIXME: Show an existing reference frame."); |
153 | 0 | } |
154 | | |
155 | | // FIXME: The math isn't entirely accurate to spec. output_uv_size is probably incorrect for certain |
156 | | // sizes, as the spec seems to prefer that the halved sizes be ceiled. |
157 | 1.04k | u32 decoded_y_width = frame_context.decoded_size(false).width(); |
158 | 1.04k | auto decoded_uv_width = frame_context.decoded_size(true).width(); |
159 | | |
160 | 1.04k | Subsampling subsampling { frame_context.color_config.subsampling_x, frame_context.color_config.subsampling_y }; |
161 | 1.04k | auto output_y_size = frame_context.size().to_type<size_t>(); |
162 | 1.04k | auto output_uv_size = subsampling.subsampled_size(output_y_size); |
163 | | |
164 | 1.04k | auto frame = DECODER_TRY_ALLOC(SubsampledYUVFrame::try_create( |
165 | 1.04k | timestamp, |
166 | 1.04k | { output_y_size.width(), output_y_size.height() }, |
167 | 1.04k | frame_context.color_config.bit_depth, get_cicp_color_space(frame_context), |
168 | 1.04k | subsampling)); |
169 | 4.16k | for (u32 plane = 0; plane < 3; plane++) { |
170 | 3.12k | auto* buffer = frame->get_plane_data<T>(plane); |
171 | 3.12k | auto decoded_width = plane == 0 ? decoded_y_width : decoded_uv_width; |
172 | 3.12k | auto output_size = plane == 0 ? output_y_size : output_uv_size; |
173 | 3.12k | auto const* decoded_buffer = get_output_buffer(plane).data(); |
174 | | |
175 | 2.92M | for (u32 row = 0; row < output_size.height(); row++) { |
176 | 246M | for (u32 column = 0; column < output_size.width(); column++) |
177 | 243M | buffer[row * output_size.width() + column] = static_cast<T>(decoded_buffer[row * decoded_width + column]); |
178 | 2.92M | } |
179 | 3.12k | } |
180 | | |
181 | 1.04k | m_video_frame_queue.enqueue(move(frame)); |
182 | | |
183 | 1.04k | return {}; |
184 | 1.04k | } AK::ErrorOr<void, Media::DecoderError> Media::Video::VP9::Decoder::create_video_frame<unsigned char>(AK::Duration, Media::Video::VP9::FrameContext const&) Line | Count | Source | 147 | 1.01k | { | 148 | | // (8.9) Output process | 149 | | | 150 | | // FIXME: If show_existing_frame is set, output from FrameStore[frame_to_show_map_index] here instead. | 151 | 1.01k | if (frame_context.shows_existing_frame()) { | 152 | 0 | dbgln("FIXME: Show an existing reference frame."); | 153 | 0 | } | 154 | | | 155 | | // FIXME: The math isn't entirely accurate to spec. output_uv_size is probably incorrect for certain | 156 | | // sizes, as the spec seems to prefer that the halved sizes be ceiled. | 157 | 1.01k | u32 decoded_y_width = frame_context.decoded_size(false).width(); | 158 | 1.01k | auto decoded_uv_width = frame_context.decoded_size(true).width(); | 159 | | | 160 | 1.01k | Subsampling subsampling { frame_context.color_config.subsampling_x, frame_context.color_config.subsampling_y }; | 161 | 1.01k | auto output_y_size = frame_context.size().to_type<size_t>(); | 162 | 1.01k | auto output_uv_size = subsampling.subsampled_size(output_y_size); | 163 | | | 164 | 1.01k | auto frame = DECODER_TRY_ALLOC(SubsampledYUVFrame::try_create( | 165 | 1.01k | timestamp, | 166 | 1.01k | { output_y_size.width(), output_y_size.height() }, | 167 | 1.01k | frame_context.color_config.bit_depth, get_cicp_color_space(frame_context), | 168 | 1.01k | subsampling)); | 169 | 4.07k | for (u32 plane = 0; plane < 3; plane++) { | 170 | 3.05k | auto* buffer = frame->get_plane_data<T>(plane); | 171 | 3.05k | auto decoded_width = plane == 0 ? decoded_y_width : decoded_uv_width; | 172 | 3.05k | auto output_size = plane == 0 ? output_y_size : output_uv_size; | 173 | 3.05k | auto const* decoded_buffer = get_output_buffer(plane).data(); | 174 | | | 175 | 2.06M | for (u32 row = 0; row < output_size.height(); row++) { | 176 | 212M | for (u32 column = 0; column < output_size.width(); column++) | 177 | 210M | buffer[row * output_size.width() + column] = static_cast<T>(decoded_buffer[row * decoded_width + column]); | 178 | 2.06M | } | 179 | 3.05k | } | 180 | | | 181 | 1.01k | m_video_frame_queue.enqueue(move(frame)); | 182 | | | 183 | 1.01k | return {}; | 184 | 1.01k | } |
AK::ErrorOr<void, Media::DecoderError> Media::Video::VP9::Decoder::create_video_frame<unsigned short>(AK::Duration, Media::Video::VP9::FrameContext const&) Line | Count | Source | 147 | 23 | { | 148 | | // (8.9) Output process | 149 | | | 150 | | // FIXME: If show_existing_frame is set, output from FrameStore[frame_to_show_map_index] here instead. | 151 | 23 | if (frame_context.shows_existing_frame()) { | 152 | 0 | dbgln("FIXME: Show an existing reference frame."); | 153 | 0 | } | 154 | | | 155 | | // FIXME: The math isn't entirely accurate to spec. output_uv_size is probably incorrect for certain | 156 | | // sizes, as the spec seems to prefer that the halved sizes be ceiled. | 157 | 23 | u32 decoded_y_width = frame_context.decoded_size(false).width(); | 158 | 23 | auto decoded_uv_width = frame_context.decoded_size(true).width(); | 159 | | | 160 | 23 | Subsampling subsampling { frame_context.color_config.subsampling_x, frame_context.color_config.subsampling_y }; | 161 | 23 | auto output_y_size = frame_context.size().to_type<size_t>(); | 162 | 23 | auto output_uv_size = subsampling.subsampled_size(output_y_size); | 163 | | | 164 | 23 | auto frame = DECODER_TRY_ALLOC(SubsampledYUVFrame::try_create( | 165 | 23 | timestamp, | 166 | 23 | { output_y_size.width(), output_y_size.height() }, | 167 | 23 | frame_context.color_config.bit_depth, get_cicp_color_space(frame_context), | 168 | 23 | subsampling)); | 169 | 92 | for (u32 plane = 0; plane < 3; plane++) { | 170 | 69 | auto* buffer = frame->get_plane_data<T>(plane); | 171 | 69 | auto decoded_width = plane == 0 ? decoded_y_width : decoded_uv_width; | 172 | 69 | auto output_size = plane == 0 ? output_y_size : output_uv_size; | 173 | 69 | auto const* decoded_buffer = get_output_buffer(plane).data(); | 174 | | | 175 | 856k | for (u32 row = 0; row < output_size.height(); row++) { | 176 | 33.6M | for (u32 column = 0; column < output_size.width(); column++) | 177 | 32.7M | buffer[row * output_size.width() + column] = static_cast<T>(decoded_buffer[row * decoded_width + column]); | 178 | 856k | } | 179 | 69 | } | 180 | | | 181 | 23 | m_video_frame_queue.enqueue(move(frame)); | 182 | | | 183 | 23 | return {}; | 184 | 23 | } |
|
185 | | |
186 | | DecoderErrorOr<void> Decoder::allocate_buffers(FrameContext const& frame_context) |
187 | 2.05k | { |
188 | 8.22k | for (size_t plane = 0; plane < 3; plane++) { |
189 | 6.17k | auto size = frame_context.decoded_size(plane > 0); |
190 | | |
191 | 6.17k | auto& output_buffer = get_output_buffer(plane); |
192 | 6.17k | output_buffer.clear_with_capacity(); |
193 | 6.17k | DECODER_TRY_ALLOC(output_buffer.try_resize_and_keep_capacity(size.width() * size.height())); |
194 | 6.17k | } |
195 | 2.05k | return {}; |
196 | 2.05k | } |
197 | | |
198 | | Vector<u16>& Decoder::get_output_buffer(u8 plane) |
199 | 24.9M | { |
200 | 24.9M | return m_output_buffers[plane]; |
201 | 24.9M | } |
202 | | |
203 | | DecoderErrorOr<NonnullOwnPtr<VideoFrame>> Decoder::get_decoded_frame() |
204 | 0 | { |
205 | 0 | if (m_video_frame_queue.is_empty()) |
206 | 0 | return DecoderError::format(DecoderErrorCategory::NeedsMoreInput, "No video frame in queue."); |
207 | | |
208 | 0 | return m_video_frame_queue.dequeue(); |
209 | 0 | } |
210 | | |
211 | | void Decoder::flush() |
212 | 0 | { |
213 | 0 | m_video_frame_queue.clear(); |
214 | 0 | } |
215 | | |
216 | | template<typename T> |
217 | | static inline i32 rounded_right_shift(T value, u8 bits) |
218 | 2.66G | { |
219 | 2.66G | value = (value + static_cast<T>(1u << (bits - 1u))) >> bits; |
220 | 2.66G | return static_cast<i32>(value); |
221 | 2.66G | } Decoder.cpp:int Media::Video::VP9::rounded_right_shift<unsigned int>(unsigned int, unsigned char) Line | Count | Source | 218 | 1.86M | { | 219 | 1.86M | value = (value + static_cast<T>(1u << (bits - 1u))) >> bits; | 220 | 1.86M | return static_cast<i32>(value); | 221 | 1.86M | } |
Decoder.cpp:int Media::Video::VP9::rounded_right_shift<int>(int, unsigned char) Line | Count | Source | 218 | 641M | { | 219 | 641M | value = (value + static_cast<T>(1u << (bits - 1u))) >> bits; | 220 | 641M | return static_cast<i32>(value); | 221 | 641M | } |
Decoder.cpp:int Media::Video::VP9::rounded_right_shift<long>(long, unsigned char) Line | Count | Source | 218 | 2.01G | { | 219 | 2.01G | value = (value + static_cast<T>(1u << (bits - 1u))) >> bits; | 220 | 2.01G | return static_cast<i32>(value); | 221 | 2.01G | } |
|
222 | | |
223 | | u8 Decoder::merge_prob(u8 pre_prob, u32 count_0, u32 count_1, u8 count_sat, u8 max_update_factor) |
224 | 1.86M | { |
225 | 1.86M | auto total_decode_count = count_0 + count_1; |
226 | 1.86M | u8 prob = 128; |
227 | 1.86M | if (total_decode_count != 0) { |
228 | 131k | prob = static_cast<u8>(clip_3(1u, 255u, (count_0 * 256 + (total_decode_count >> 1)) / total_decode_count)); |
229 | 131k | } |
230 | 1.86M | auto count = min(total_decode_count, count_sat); |
231 | 1.86M | auto factor = (max_update_factor * count) / count_sat; |
232 | 1.86M | return rounded_right_shift(pre_prob * (256 - factor) + (prob * factor), 8); |
233 | 1.86M | } |
234 | | |
235 | | u32 Decoder::merge_probs(int const* tree, int index, u8* probs, u32* counts, u8 count_sat, u8 max_update_factor) |
236 | 1.83M | { |
237 | 1.83M | auto s = tree[index]; |
238 | 1.83M | auto left_count = (s <= 0) ? counts[-s] : merge_probs(tree, s, probs, counts, count_sat, max_update_factor); |
239 | 1.83M | auto r = tree[index + 1]; |
240 | 1.83M | auto right_count = (r <= 0) ? counts[-r] : merge_probs(tree, r, probs, counts, count_sat, max_update_factor); |
241 | 1.83M | probs[index >> 1] = merge_prob(probs[index >> 1], left_count, right_count, count_sat, max_update_factor); |
242 | 1.83M | return left_count + right_count; |
243 | 1.83M | } |
244 | | |
245 | | DecoderErrorOr<void> Decoder::adapt_coef_probs(FrameContext const& frame_context) |
246 | 1.04k | { |
247 | 1.04k | u8 update_factor; |
248 | 1.04k | if (!frame_context.is_inter_predicted() || m_parser->m_previous_frame_type != FrameType::KeyFrame) |
249 | 794 | update_factor = 112; |
250 | 253 | else |
251 | 253 | update_factor = 128; |
252 | | |
253 | 5.23k | for (size_t t = 0; t < 4; t++) { |
254 | 12.5k | for (size_t i = 0; i < 2; i++) { |
255 | 25.1k | for (size_t j = 0; j < 2; j++) { |
256 | 117k | for (size_t k = 0; k < 6; k++) { |
257 | 100k | size_t max_l = (k == 0) ? 3 : 6; |
258 | 653k | for (size_t l = 0; l < max_l; l++) { |
259 | 552k | auto& coef_probs = m_parser->m_probability_tables->coef_probs()[t][i][j][k][l]; |
260 | 552k | merge_probs(small_token_tree, 2, coef_probs, |
261 | 552k | frame_context.counter->m_counts_token[t][i][j][k][l], |
262 | 552k | 24, update_factor); |
263 | 552k | merge_probs(binary_tree, 0, coef_probs, |
264 | 552k | frame_context.counter->m_counts_more_coefs[t][i][j][k][l], |
265 | 552k | 24, update_factor); |
266 | 552k | } |
267 | 100k | } |
268 | 16.7k | } |
269 | 8.37k | } |
270 | 4.18k | } |
271 | | |
272 | 1.04k | return {}; |
273 | 1.04k | } |
274 | | |
275 | | #define ADAPT_PROB_TABLE(name, size) \ |
276 | 2.87k | do { \ |
277 | 15.0k | for (size_t i = 0; i < (size); i++) { \ |
278 | 12.2k | auto table = probs.name##_prob(); \ |
279 | 12.2k | table[i] = adapt_prob(table[i], counter.m_counts_##name[i]); \ |
280 | 12.2k | } \ |
281 | 2.87k | } while (0) |
282 | | |
283 | | #define ADAPT_TREE(tree_name, prob_name, count_name, size) \ |
284 | 3.21k | do { \ |
285 | 31.1k | for (size_t i = 0; i < (size); i++) { \ |
286 | 27.9k | adapt_probs(tree_name##_tree, probs.prob_name##_probs()[i], counter.m_counts_##count_name[i]); \ |
287 | 27.9k | } \ |
288 | 3.21k | } while (0) |
289 | | |
290 | | DecoderErrorOr<void> Decoder::adapt_non_coef_probs(FrameContext const& frame_context) |
291 | 719 | { |
292 | 719 | auto& probs = *m_parser->m_probability_tables; |
293 | 719 | auto& counter = *frame_context.counter; |
294 | 719 | ADAPT_PROB_TABLE(is_inter, IS_INTER_CONTEXTS); |
295 | 719 | ADAPT_PROB_TABLE(comp_mode, COMP_MODE_CONTEXTS); |
296 | 719 | ADAPT_PROB_TABLE(comp_ref, REF_CONTEXTS); |
297 | 4.31k | for (size_t i = 0; i < REF_CONTEXTS; i++) { |
298 | 10.7k | for (size_t j = 0; j < 2; j++) |
299 | 7.19k | probs.single_ref_prob()[i][j] = adapt_prob(probs.single_ref_prob()[i][j], counter.m_counts_single_ref[i][j]); |
300 | 3.59k | } |
301 | 719 | ADAPT_TREE(inter_mode, inter_mode, inter_mode, INTER_MODE_CONTEXTS); |
302 | 719 | ADAPT_TREE(intra_mode, y_mode, intra_mode, BLOCK_SIZE_GROUPS); |
303 | 719 | ADAPT_TREE(intra_mode, uv_mode, uv_mode, INTRA_MODES); |
304 | 719 | ADAPT_TREE(partition, partition, partition, PARTITION_CONTEXTS); |
305 | 719 | ADAPT_PROB_TABLE(skip, SKIP_CONTEXTS); |
306 | 719 | if (frame_context.interpolation_filter == Switchable) { |
307 | 340 | ADAPT_TREE(interp_filter, interp_filter, interp_filter, INTERP_FILTER_CONTEXTS); |
308 | 340 | } |
309 | 719 | if (frame_context.transform_mode == TransformMode::Select) { |
310 | 87 | for (size_t i = 0; i < TX_SIZE_CONTEXTS; i++) { |
311 | 58 | auto& tx_probs = probs.tx_probs(); |
312 | 58 | auto& tx_counts = counter.m_counts_tx_size; |
313 | 58 | adapt_probs(tx_size_8_tree, tx_probs[Transform_8x8][i], tx_counts[Transform_8x8][i]); |
314 | 58 | adapt_probs(tx_size_16_tree, tx_probs[Transform_16x16][i], tx_counts[Transform_16x16][i]); |
315 | 58 | adapt_probs(tx_size_32_tree, tx_probs[Transform_32x32][i], tx_counts[Transform_32x32][i]); |
316 | 58 | } |
317 | 29 | } |
318 | 719 | adapt_probs(mv_joint_tree, probs.mv_joint_probs(), counter.m_counts_mv_joint); |
319 | 2.15k | for (size_t i = 0; i < 2; i++) { |
320 | 1.43k | probs.mv_sign_prob()[i] = adapt_prob(probs.mv_sign_prob()[i], counter.m_counts_mv_sign[i]); |
321 | 1.43k | adapt_probs(mv_class_tree, probs.mv_class_probs()[i], counter.m_counts_mv_class[i]); |
322 | 1.43k | probs.mv_class0_bit_prob()[i] = adapt_prob(probs.mv_class0_bit_prob()[i], counter.m_counts_mv_class0_bit[i]); |
323 | 15.8k | for (size_t j = 0; j < MV_OFFSET_BITS; j++) |
324 | 14.3k | probs.mv_bits_prob()[i][j] = adapt_prob(probs.mv_bits_prob()[i][j], counter.m_counts_mv_bits[i][j]); |
325 | 4.31k | for (size_t j = 0; j < CLASS0_SIZE; j++) |
326 | 2.87k | adapt_probs(mv_fr_tree, probs.mv_class0_fr_probs()[i][j], counter.m_counts_mv_class0_fr[i][j]); |
327 | 1.43k | adapt_probs(mv_fr_tree, probs.mv_fr_probs()[i], counter.m_counts_mv_fr[i]); |
328 | 1.43k | if (frame_context.high_precision_motion_vectors_allowed) { |
329 | 650 | probs.mv_class0_hp_prob()[i] = adapt_prob(probs.mv_class0_hp_prob()[i], counter.m_counts_mv_class0_hp[i]); |
330 | 650 | probs.mv_hp_prob()[i] = adapt_prob(probs.mv_hp_prob()[i], counter.m_counts_mv_hp[i]); |
331 | 650 | } |
332 | 1.43k | } |
333 | 719 | return {}; |
334 | 719 | } |
335 | | |
336 | | void Decoder::adapt_probs(int const* tree, u8* probs, u32* counts) |
337 | 34.6k | { |
338 | 34.6k | merge_probs(tree, 0, probs, counts, COUNT_SAT, MAX_UPDATE_FACTOR); |
339 | 34.6k | } |
340 | | |
341 | | u8 Decoder::adapt_prob(u8 prob, u32 counts[2]) |
342 | 37.9k | { |
343 | 37.9k | return merge_prob(prob, counts[0], counts[1], COUNT_SAT, MAX_UPDATE_FACTOR); |
344 | 37.9k | } |
345 | | |
346 | | DecoderErrorOr<void> Decoder::predict_intra(u8 plane, BlockContext const& block_context, u32 x, u32 y, bool have_left, bool have_above, bool not_on_right, TransformSize tx_size, u32 block_index) |
347 | 16.2M | { |
348 | 16.2M | auto& frame_buffer = get_output_buffer(plane); |
349 | | |
350 | | // 8.5.1 Intra prediction process |
351 | | |
352 | | // The intra prediction process is invoked for intra coded blocks to predict a part of the block corresponding to a |
353 | | // transform block. When the transform size is smaller than the block size, this process can be invoked multiple |
354 | | // times within a single block for the same plane, and the invocations are in raster order within the block. |
355 | | |
356 | | // The variable mode is specified by: |
357 | | // 1. If plane is greater than 0, mode is set equal to uv_mode. |
358 | | // 2. Otherwise, if MiSize is greater than or equal to BLOCK_8X8, mode is set equal to y_mode. |
359 | | // 3. Otherwise, mode is set equal to sub_modes[ blockIdx ]. |
360 | 16.2M | PredictionMode mode; |
361 | 16.2M | if (plane > 0) |
362 | 6.45M | mode = block_context.uv_prediction_mode; |
363 | 9.77M | else if (block_context.size >= Block_8x8) |
364 | 8.88M | mode = block_context.y_prediction_mode(); |
365 | 896k | else |
366 | 896k | mode = block_context.sub_block_prediction_modes[block_index]; |
367 | | |
368 | | // The variable log2Size specifying the base 2 logarithm of the width of the transform block is set equal to txSz + 2. |
369 | 16.2M | u8 log2_of_block_size = tx_size + 2; |
370 | | // The variable size is set equal to 1 << log2Size. |
371 | 16.2M | u8 block_size = 1 << log2_of_block_size; |
372 | | |
373 | | // The variable maxX is set equal to (MiCols * 8) - 1. |
374 | | // The variable maxY is set equal to (MiRows * 8) - 1. |
375 | | // If plane is greater than 0, then: |
376 | | // − maxX is set equal to ((MiCols * 8) >> subsampling_x) - 1. |
377 | | // − maxY is set equal to ((MiRows * 8) >> subsampling_y) - 1. |
378 | 16.2M | auto output_size = block_context.frame_context.decoded_size(plane > 0); |
379 | 16.2M | auto max_x = output_size.width() - 1; |
380 | 16.2M | auto max_y = output_size.height() - 1; |
381 | | |
382 | 1.50G | auto const frame_buffer_at = [&](u32 row, u32 column) -> u16& { |
383 | 1.50G | return frame_buffer[row * output_size.width() + column]; |
384 | 1.50G | }; |
385 | | |
386 | | // The array aboveRow[ i ] for i = 0..size-1 is specified by: |
387 | | // .. |
388 | | // The array aboveRow[ i ] for i = size..2*size-1 is specified by: |
389 | | // .. |
390 | | // The array aboveRow[ i ] for i = -1 is specified by: |
391 | | // .. |
392 | | |
393 | | // NOTE: above_row is an array ranging from 0 to (2*block_size). |
394 | | // There are three sections to the array: |
395 | | // - [0] |
396 | | // - [1 .. block_size] |
397 | | // - [block_size + 1 .. block_size * 2] |
398 | | // The array indices must be offset by 1 to accommodate index -1. |
399 | 16.2M | Array<Intermediate, maximum_block_dimensions * 2 + 1> above_row; |
400 | 445M | auto above_row_at = [&](i32 index) -> Intermediate& { |
401 | 445M | return above_row[index + 1]; |
402 | 445M | }; |
403 | | |
404 | | // NOTE: This value is pre-calculated since it is reused in spec below. |
405 | | // Use this to replace spec text "(1<<(BitDepth-1))". |
406 | 16.2M | Intermediate half_sample_value = (1 << (block_context.frame_context.color_config.bit_depth - 1)); |
407 | | |
408 | | // The array aboveRow[ i ] for i = 0..size-1 is specified by: |
409 | 16.2M | if (!have_above) { |
410 | | // 1. If haveAbove is equal to 0, aboveRow[ i ] is set equal to (1<<(BitDepth-1)) - 1. |
411 | | // FIXME: Use memset? |
412 | 1.64M | for (auto i = 0u; i < block_size; i++) |
413 | 1.42M | above_row_at(i) = half_sample_value - 1; |
414 | 16.0M | } else { |
415 | | // 2. Otherwise, aboveRow[ i ] is set equal to CurrFrame[ plane ][ y-1 ][ Min(maxX, x+i) ]. |
416 | 115M | for (auto i = 0u; i < block_size; i++) |
417 | 99.9M | above_row_at(i) = frame_buffer_at(y - 1, min(max_x, x + i)); |
418 | 16.0M | } |
419 | | |
420 | | // The array aboveRow[ i ] for i = size..2*size-1 is specified by: |
421 | 16.2M | if (have_above && not_on_right && tx_size == Transform_4x4) { |
422 | | // 1. If haveAbove is equal to 1 and notOnRight is equal to 1 and txSz is equal to 0, |
423 | | // aboveRow[ i ] is set equal to CurrFrame[ plane ][ y-1 ][ Min(maxX, x+i) ]. |
424 | 54.0M | for (auto i = block_size; i < block_size * 2; i++) |
425 | 43.2M | above_row_at(i) = frame_buffer_at(y - 1, min(max_x, x + i)); |
426 | 10.8M | } else { |
427 | | // 2. Otherwise, aboveRow[ i ] is set equal to aboveRow[ size-1 ]. |
428 | 63.6M | for (auto i = block_size; i < block_size * 2; i++) |
429 | 58.2M | above_row_at(i) = above_row_at(block_size - 1); |
430 | 5.41M | } |
431 | | |
432 | | // The array aboveRow[ i ] for i = -1 is specified by: |
433 | 16.2M | if (have_above && have_left) { |
434 | | // 1. If haveAbove is equal to 1 and haveLeft is equal to 1, aboveRow[ -1 ] is set equal to |
435 | | // CurrFrame[ plane ][ y-1 ][ Min(maxX, x-1) ]. |
436 | 15.1M | above_row_at(-1) = frame_buffer_at(y - 1, min(max_x, x - 1)); |
437 | 15.1M | } else if (have_above) { |
438 | | // 2. Otherwise if haveAbove is equal to 1, aboveRow[ -1] is set equal to (1<<(BitDepth-1)) + 1. |
439 | 828k | above_row_at(-1) = half_sample_value + 1; |
440 | 828k | } else { |
441 | | // 3. Otherwise, aboveRow[ -1 ] is set equal to (1<<(BitDepth-1)) - 1 |
442 | 222k | above_row_at(-1) = half_sample_value - 1; |
443 | 222k | } |
444 | | |
445 | | // The array leftCol[ i ] for i = 0..size-1 is specified by: |
446 | 16.2M | Array<Intermediate, maximum_block_dimensions> left_column; |
447 | 16.2M | if (have_left) { |
448 | | // − If haveLeft is equal to 1, leftCol[ i ] is set equal to CurrFrame[ plane ][ Min(maxY, y+i) ][ x-1 ]. |
449 | 110M | for (auto i = 0u; i < block_size; i++) |
450 | 95.1M | left_column[i] = frame_buffer_at(min(max_y, y + i), x - 1); |
451 | 15.3M | } else { |
452 | | // − Otherwise, leftCol[ i ] is set equal to (1<<(BitDepth-1)) + 1. |
453 | 7.10M | for (auto i = 0u; i < block_size; i++) |
454 | 6.26M | left_column[i] = half_sample_value + 1; |
455 | 834k | } |
456 | | |
457 | | // A 2D array named pred containing the intra predicted samples is constructed as follows: |
458 | 16.2M | Array<Intermediate, maximum_block_size> predicted_samples; |
459 | 2.55G | auto const predicted_sample_at = [&](u32 row, u32 column) -> Intermediate& { |
460 | 2.55G | return predicted_samples[row * block_size + column]; |
461 | 2.55G | }; |
462 | | |
463 | | // FIXME: One of the two below should be a simple memcpy of 1D arrays. |
464 | 16.2M | switch (mode) { |
465 | 374k | case PredictionMode::VPred: |
466 | | // − If mode is equal to V_PRED, pred[ i ][ j ] is set equal to aboveRow[ j ] with j = 0..size-1 and i = 0..size-1 |
467 | | // (each row of the block is filled with a copy of aboveRow). |
468 | 2.39M | for (auto j = 0u; j < block_size; j++) { |
469 | 18.3M | for (auto i = 0u; i < block_size; i++) |
470 | 16.3M | predicted_sample_at(i, j) = above_row_at(j); |
471 | 2.02M | } |
472 | 374k | break; |
473 | 631k | case PredictionMode::HPred: |
474 | | // − Otherwise if mode is equal to H_PRED, pred[ i ][ j ] is set equal to leftCol[ i ] with j = 0..size-1 and i = |
475 | | // 0..size-1 (each column of the block is filled with a copy of leftCol). |
476 | 4.06M | for (auto j = 0u; j < block_size; j++) { |
477 | 31.7M | for (auto i = 0u; i < block_size; i++) |
478 | 28.3M | predicted_sample_at(i, j) = left_column[i]; |
479 | 3.43M | } |
480 | 631k | break; |
481 | 491k | case PredictionMode::D207Pred: |
482 | | // − Otherwise if mode is equal to D207_PRED, the following applies: |
483 | | // 1. pred[ size - 1 ][ j ] = leftCol[ size - 1] for j = 0..size-1 |
484 | 2.90M | for (auto j = 0u; j < block_size; j++) |
485 | 2.41M | predicted_sample_at(block_size - 1, j) = left_column[block_size - 1]; |
486 | | // 2. pred[ i ][ 0 ] = Round2( leftCol[ i ] + leftCol[ i + 1 ], 1 ) for i = 0..size-2 |
487 | 2.41M | for (auto i = 0u; i < block_size - 1u; i++) |
488 | 1.92M | predicted_sample_at(i, 0) = rounded_right_shift(left_column[i] + left_column[i + 1], 1); |
489 | | // 3. pred[ i ][ 1 ] = Round2( leftCol[ i ] + 2 * leftCol[ i + 1 ] + leftCol[ i + 2 ], 2 ) for i = 0..size-3 |
490 | 1.92M | for (auto i = 0u; i < block_size - 2u; i++) |
491 | 1.43M | predicted_sample_at(i, 1) = rounded_right_shift(left_column[i] + (2 * left_column[i + 1]) + left_column[i + 2], 2); |
492 | | // 4. pred[ size - 2 ][ 1 ] = Round2( leftCol[ size - 2 ] + 3 * leftCol[ size - 1 ], 2 ) |
493 | 491k | predicted_sample_at(block_size - 2, 1) = rounded_right_shift(left_column[block_size - 2] + (3 * left_column[block_size - 1]), 2); |
494 | | // 5. pred[ i ][ j ] = pred[ i + 1 ][ j - 2 ] for i = (size-2)..0, for j = 2..size-1 |
495 | | // NOTE – In the last step i iterates in reverse order. |
496 | 1.92M | for (auto i = block_size - 2u;;) { |
497 | 12.5M | for (auto j = 2u; j < block_size; j++) |
498 | 10.6M | predicted_sample_at(i, j) = predicted_sample_at(i + 1, j - 2); |
499 | 1.92M | if (i == 0) |
500 | 491k | break; |
501 | 1.43M | i--; |
502 | 1.43M | } |
503 | 491k | break; |
504 | 128k | case PredictionMode::D45Pred: |
505 | | // Otherwise if mode is equal to D45_PRED, |
506 | | // for i = 0..size-1, for j = 0..size-1. |
507 | 850k | for (auto i = 0u; i < block_size; i++) { |
508 | 7.00M | for (auto j = 0; j < block_size; j++) { |
509 | | // pred[ i ][ j ] is set equal to (i + j + 2 < size * 2) ? |
510 | 6.28M | if (i + j + 2 < block_size * 2) |
511 | | // Round2( aboveRow[ i + j ] + aboveRow[ i + j + 1 ] * 2 + aboveRow[ i + j + 2 ], 2 ) : |
512 | 6.15M | predicted_sample_at(i, j) = rounded_right_shift(above_row_at(i + j) + above_row_at(i + j + 1) * 2 + above_row_at(i + j + 2), 2); |
513 | 127k | else |
514 | | // aboveRow[ 2 * size - 1 ] |
515 | 127k | predicted_sample_at(i, j) = above_row_at(2 * block_size - 1); |
516 | 6.28M | } |
517 | 722k | } |
518 | 128k | break; |
519 | 128k | case PredictionMode::D63Pred: |
520 | | // Otherwise if mode is equal to D63_PRED, |
521 | 844k | for (auto i = 0u; i < block_size; i++) { |
522 | 6.80M | for (auto j = 0u; j < block_size; j++) { |
523 | | // i/2 + j |
524 | 6.08M | auto row_index = (i / 2) + j; |
525 | | // pred[ i ][ j ] is set equal to (i & 1) ? |
526 | 6.08M | if (i & 1) |
527 | | // Round2( aboveRow[ i/2 + j ] + aboveRow[ i/2 + j + 1 ] * 2 + aboveRow[ i/2 + j + 2 ], 2 ) : |
528 | 3.04M | predicted_sample_at(i, j) = rounded_right_shift(above_row_at(row_index) + above_row_at(row_index + 1) * 2 + above_row_at(row_index + 2), 2); |
529 | 3.04M | else |
530 | | // Round2( aboveRow[ i/2 + j ] + aboveRow[ i/2 + j + 1 ], 1 ) for i = 0..size-1, for j = 0..size-1. |
531 | 3.04M | predicted_sample_at(i, j) = rounded_right_shift(above_row_at(row_index) + above_row_at(row_index + 1), 1); |
532 | 6.08M | } |
533 | 715k | } |
534 | 128k | break; |
535 | 121k | case PredictionMode::D117Pred: |
536 | | // Otherwise if mode is equal to D117_PRED, the following applies: |
537 | | // 1. pred[ 0 ][ j ] = Round2( aboveRow[ j - 1 ] + aboveRow[ j ], 1 ) for j = 0..size-1 |
538 | 775k | for (auto j = 0; j < block_size; j++) |
539 | 653k | predicted_sample_at(0, j) = rounded_right_shift(above_row_at(j - 1) + above_row_at(j), 1); |
540 | | // 2. pred[ 1 ][ 0 ] = Round2( leftCol[ 0 ] + 2 * aboveRow[ -1 ] + aboveRow[ 0 ], 2 ) |
541 | 121k | predicted_sample_at(1, 0) = rounded_right_shift(left_column[0] + 2 * above_row_at(-1) + above_row_at(0), 2); |
542 | | // 3. pred[ 1 ][ j ] = Round2( aboveRow[ j - 2 ] + 2 * aboveRow[ j - 1 ] + aboveRow[ j ], 2 ) for j = 1..size-1 |
543 | 653k | for (auto j = 1; j < block_size; j++) |
544 | 532k | predicted_sample_at(1, j) = rounded_right_shift(above_row_at(j - 2) + 2 * above_row_at(j - 1) + above_row_at(j), 2); |
545 | | // 4. pred[ 2 ][ 0 ] = Round2( aboveRow[ -1 ] + 2 * leftCol[ 0 ] + leftCol[ 1 ], 2 ) |
546 | 121k | predicted_sample_at(2, 0) = rounded_right_shift(above_row_at(-1) + 2 * left_column[0] + left_column[1], 2); |
547 | | // 5. pred[ i ][ 0 ] = Round2( leftCol[ i - 3 ] + 2 * leftCol[ i - 2 ] + leftCol[ i - 1 ], 2 ) for i = 3..size-1 |
548 | 411k | for (auto i = 3u; i < block_size; i++) |
549 | 290k | predicted_sample_at(i, 0) = rounded_right_shift(left_column[i - 3] + 2 * left_column[i - 2] + left_column[i - 1], 2); |
550 | | // 6. pred[ i ][ j ] = pred[ i - 2 ][ j - 1 ] for i = 2..size-1, for j = 1..size-1 |
551 | 532k | for (auto i = 2u; i < block_size; i++) { |
552 | 3.95M | for (auto j = 1u; j < block_size; j++) |
553 | 3.54M | predicted_sample_at(i, j) = predicted_sample_at(i - 2, j - 1); |
554 | 411k | } |
555 | 121k | break; |
556 | 235k | case PredictionMode::D135Pred: |
557 | | // Otherwise if mode is equal to D135_PRED, the following applies: |
558 | | // 1. pred[ 0 ][ 0 ] = Round2( leftCol[ 0 ] + 2 * aboveRow[ -1 ] + aboveRow[ 0 ], 2 ) |
559 | 235k | predicted_sample_at(0, 0) = rounded_right_shift(left_column[0] + 2 * above_row_at(-1) + above_row_at(0), 2); |
560 | | // 2. pred[ 0 ][ j ] = Round2( aboveRow[ j - 2 ] + 2 * aboveRow[ j - 1 ] + aboveRow[ j ], 2 ) for j = 1..size-1 |
561 | 1.31M | for (auto j = 1; j < block_size; j++) |
562 | 1.08M | predicted_sample_at(0, j) = rounded_right_shift(above_row_at(j - 2) + 2 * above_row_at(j - 1) + above_row_at(j), 2); |
563 | | // 3. pred[ 1 ][ 0 ] = Round2( aboveRow [ -1 ] + 2 * leftCol[ 0 ] + leftCol[ 1 ], 2 ) for i = 1..size-1 |
564 | 235k | predicted_sample_at(1, 0) = rounded_right_shift(above_row_at(-1) + 2 * left_column[0] + left_column[1], 2); |
565 | | // 4. pred[ i ][ 0 ] = Round2( leftCol[ i - 2 ] + 2 * leftCol[ i - 1 ] + leftCol[ i ], 2 ) for i = 2..size-1 |
566 | 1.08M | for (auto i = 2u; i < block_size; i++) |
567 | 845k | predicted_sample_at(i, 0) = rounded_right_shift(left_column[i - 2] + 2 * left_column[i - 1] + left_column[i], 2); |
568 | | // 5. pred[ i ][ j ] = pred[ i - 1 ][ j - 1 ] for i = 1..size-1, for j = 1..size-1 |
569 | 1.31M | for (auto i = 1u; i < block_size; i++) { |
570 | 9.96M | for (auto j = 1; j < block_size; j++) |
571 | 8.88M | predicted_sample_at(i, j) = predicted_sample_at(i - 1, j - 1); |
572 | 1.08M | } |
573 | 235k | break; |
574 | 183k | case PredictionMode::D153Pred: |
575 | | // Otherwise if mode is equal to D153_PRED, the following applies: |
576 | | // 1. pred[ 0 ][ 0 ] = Round2( leftCol[ 0 ] + aboveRow[ -1 ], 1 ) |
577 | 183k | predicted_sample_at(0, 0) = rounded_right_shift(left_column[0] + above_row_at(-1), 1); |
578 | | // 2. pred[ i ][ 0 ] = Round2( leftCol[ i - 1] + leftCol[ i ], 1 ) for i = 1..size-1 |
579 | 1.00M | for (auto i = 1u; i < block_size; i++) |
580 | 824k | predicted_sample_at(i, 0) = rounded_right_shift(left_column[i - 1] + left_column[i], 1); |
581 | | // 3. pred[ 0 ][ 1 ] = Round2( leftCol[ 0 ] + 2 * aboveRow[ -1 ] + aboveRow[ 0 ], 2 ) |
582 | 183k | predicted_sample_at(0, 1) = rounded_right_shift(left_column[0] + 2 * above_row_at(-1) + above_row_at(0), 2); |
583 | | // 4. pred[ 1 ][ 1 ] = Round2( aboveRow[ -1 ] + 2 * leftCol [ 0 ] + leftCol [ 1 ], 2 ) |
584 | 183k | predicted_sample_at(1, 1) = rounded_right_shift(above_row_at(-1) + 2 * left_column[0] + left_column[1], 2); |
585 | | // 5. pred[ i ][ 1 ] = Round2( leftCol[ i - 2 ] + 2 * leftCol[ i - 1 ] + leftCol[ i ], 2 ) for i = 2..size-1 |
586 | 824k | for (auto i = 2u; i < block_size; i++) |
587 | 640k | predicted_sample_at(i, 1) = rounded_right_shift(left_column[i - 2] + 2 * left_column[i - 1] + left_column[i], 2); |
588 | | // 6. pred[ 0 ][ j ] = Round2( aboveRow[ j - 3 ] + 2 * aboveRow[ j - 2 ] + aboveRow[ j - 1 ], 2 ) for j = 2..size-1 |
589 | 824k | for (auto j = 2; j < block_size; j++) |
590 | 640k | predicted_sample_at(0, j) = rounded_right_shift(above_row_at(j - 3) + 2 * above_row_at(j - 2) + above_row_at(j - 1), 2); |
591 | | // 7. pred[ i ][ j ] = pred[ i - 1 ][ j - 2 ] for i = 1..size-1, for j = 2..size-1 |
592 | 1.00M | for (auto i = 1u; i < block_size; i++) { |
593 | 6.60M | for (auto j = 2u; j < block_size; j++) |
594 | 5.77M | predicted_sample_at(i, j) = predicted_sample_at(i - 1, j - 2); |
595 | 824k | } |
596 | 183k | break; |
597 | 231k | case PredictionMode::TmPred: |
598 | | // Otherwise if mode is equal to TM_PRED, |
599 | | // pred[ i ][ j ] is set equal to Clip1( aboveRow[ j ] + leftCol[ i ] - aboveRow[ -1 ] ) |
600 | | // for i = 0..size-1, for j = 0..size-1. |
601 | 1.54M | for (auto i = 0u; i < block_size; i++) { |
602 | 12.6M | for (auto j = 0u; j < block_size; j++) |
603 | 11.3M | predicted_sample_at(i, j) = clip_1(block_context.frame_context.color_config.bit_depth, above_row_at(j) + left_column[i] - above_row_at(-1)); |
604 | 1.31M | } |
605 | 231k | break; |
606 | 13.6M | case PredictionMode::DcPred: { |
607 | 13.6M | Intermediate average = 0; |
608 | | |
609 | 13.6M | if (have_left && have_above) { |
610 | | // Otherwise if mode is equal to DC_PRED and haveLeft is equal to 1 and haveAbove is equal to 1, |
611 | | // The variable avg (the average of the samples in union of aboveRow and leftCol) |
612 | | // is specified as follows: |
613 | | // sum = 0 |
614 | | // for ( k = 0; k < size; k++ ) { |
615 | | // sum += leftCol[ k ] |
616 | | // sum += aboveRow[ k ] |
617 | | // } |
618 | | // avg = (sum + size) >> (log2Size + 1) |
619 | 12.8M | Intermediate sum = 0; |
620 | 94.3M | for (auto k = 0u; k < block_size; k++) { |
621 | 81.4M | sum += left_column[k]; |
622 | 81.4M | sum += above_row_at(k); |
623 | 81.4M | } |
624 | 12.8M | average = (sum + block_size) >> (log2_of_block_size + 1); |
625 | 12.8M | } else if (have_left && !have_above) { |
626 | | // Otherwise if mode is equal to DC_PRED and haveLeft is equal to 1 and haveAbove is equal to 0, |
627 | | // The variable leftAvg is specified as follows: |
628 | | // sum = 0 |
629 | | // for ( k = 0; k < size; k++ ) { |
630 | | // sum += leftCol[ k ] |
631 | | // } |
632 | | // leftAvg = (sum + (1 << (log2Size - 1) ) ) >> log2Size |
633 | 139k | Intermediate sum = 0; |
634 | 1.05M | for (auto k = 0u; k < block_size; k++) |
635 | 915k | sum += left_column[k]; |
636 | 139k | average = (sum + (1 << (log2_of_block_size - 1))) >> log2_of_block_size; |
637 | 702k | } else if (!have_left && have_above) { |
638 | | // Otherwise if mode is equal to DC_PRED and haveLeft is equal to 0 and haveAbove is equal to 1, |
639 | | // The variable aboveAvg is specified as follows: |
640 | | // sum = 0 |
641 | | // for ( k = 0; k < size; k++ ) { |
642 | | // sum += aboveRow[ k ] |
643 | | // } |
644 | | // aboveAvg = (sum + (1 << (log2Size - 1) ) ) >> log2Size |
645 | 699k | Intermediate sum = 0; |
646 | 6.17M | for (auto k = 0u; k < block_size; k++) |
647 | 5.47M | sum += above_row_at(k); |
648 | 699k | average = (sum + (1 << (log2_of_block_size - 1))) >> log2_of_block_size; |
649 | 18.4E | } else { |
650 | | // Otherwise (mode is DC_PRED), |
651 | | // pred[ i ][ j ] is set equal to 1<<(BitDepth - 1) with i = 0..size-1 and j = 0..size-1. |
652 | 18.4E | average = 1 << (block_context.frame_context.color_config.bit_depth - 1); |
653 | 18.4E | } |
654 | | |
655 | | // pred[ i ][ j ] is set equal to avg with i = 0..size-1 and j = 0..size-1. |
656 | 101M | for (auto i = 0u; i < block_size; i++) { |
657 | 1.26G | for (auto j = 0u; j < block_size; j++) |
658 | 1.17G | predicted_sample_at(i, j) = average; |
659 | 87.8M | } |
660 | 13.6M | break; |
661 | 0 | } |
662 | 0 | default: |
663 | 0 | dbgln("Unknown prediction mode {}", static_cast<u8>(mode)); |
664 | 0 | VERIFY_NOT_REACHED(); |
665 | 16.2M | } |
666 | | |
667 | | // The current frame is updated as follows: |
668 | | // − CurrFrame[ plane ][ y + i ][ x + j ] is set equal to pred[ i ][ j ] for i = 0..size-1 and j = 0..size-1. |
669 | 16.2M | auto width_in_frame_buffer = min(static_cast<u32>(block_size), max_x - x + 1); |
670 | 16.2M | auto height_in_frame_buffer = min(static_cast<u32>(block_size), max_y - y + 1); |
671 | | |
672 | 117M | for (auto i = 0u; i < height_in_frame_buffer; i++) { |
673 | 1.35G | for (auto j = 0u; j < width_in_frame_buffer; j++) |
674 | 1.25G | frame_buffer_at(y + i, x + j) = predicted_sample_at(i, j); |
675 | 101M | } |
676 | | |
677 | 16.2M | return {}; |
678 | 16.2M | } |
679 | | |
680 | | MotionVector Decoder::select_motion_vector(u8 plane, BlockContext const& block_context, ReferenceIndex reference_index, u32 block_index) |
681 | 184k | { |
682 | | // The inputs to this process are: |
683 | | // − a variable plane specifying which plane is being predicted, |
684 | | // − a variable refList specifying that we should select the motion vector from BlockMvs[ refList ], |
685 | | // − a variable blockIdx, specifying how much of the block has already been predicted in units of 4x4 samples. |
686 | | // The output of this process is a 2 element array called mv containing the motion vector for this block. |
687 | | |
688 | | // The purpose of this process is to find the motion vector for this block. Motion vectors are specified for each |
689 | | // luma block, but a chroma block may cover more than one luma block due to subsampling. In this case, an |
690 | | // average motion vector is constructed for the chroma block. |
691 | | |
692 | | // The functions round_mv_comp_q2 and round_mv_comp_q4 perform division with rounding to the nearest |
693 | | // integer and are specified as: |
694 | 184k | auto round_mv_comp_q2 = [&](MotionVector in) { |
695 | | // return (value < 0 ? value - 1 : value + 1) / 2 |
696 | 0 | return MotionVector { |
697 | 0 | (in.row() < 0 ? in.row() - 1 : in.row() + 1) / 2, |
698 | 0 | (in.column() < 0 ? in.column() - 1 : in.column() + 1) / 2 |
699 | 0 | }; |
700 | 0 | }; |
701 | 184k | auto round_mv_comp_q4 = [&](MotionVector in) { |
702 | | // return (value < 0 ? value - 2 : value + 2) / 4 |
703 | 25.7k | return MotionVector { |
704 | 25.7k | (in.row() < 0 ? in.row() - 2 : in.row() + 2) / 4, |
705 | 25.7k | (in.column() < 0 ? in.column() - 2 : in.column() + 2) / 4 |
706 | 25.7k | }; |
707 | 25.7k | }; |
708 | | |
709 | 184k | auto vectors = block_context.sub_block_motion_vectors; |
710 | | |
711 | | // The motion vector array mv is derived as follows: |
712 | | // − If plane is equal to 0, or MiSize is greater than or equal to BLOCK_8X8, mv is set equal to |
713 | | // BlockMvs[ refList ][ blockIdx ]. |
714 | 184k | if (plane == 0 || block_context.size >= Block_8x8) |
715 | 158k | return vectors[block_index][reference_index]; |
716 | | // − Otherwise, if subsampling_x is equal to 0 and subsampling_y is equal to 0, mv is set equal to |
717 | | // BlockMvs[ refList ][ blockIdx ]. |
718 | 25.7k | if (!block_context.frame_context.color_config.subsampling_x && !block_context.frame_context.color_config.subsampling_y) |
719 | 0 | return vectors[block_index][reference_index]; |
720 | | // − Otherwise, if subsampling_x is equal to 0 and subsampling_y is equal to 1, mv[ comp ] is set equal to |
721 | | // round_mv_comp_q2( BlockMvs[ refList ][ blockIdx ][ comp ] + BlockMvs[ refList ][ blockIdx + 2 ][ comp ] ) |
722 | | // for comp = 0..1. |
723 | 25.7k | if (!block_context.frame_context.color_config.subsampling_x && block_context.frame_context.color_config.subsampling_y) |
724 | 0 | return round_mv_comp_q2(vectors[block_index][reference_index] + vectors[block_index + 2][reference_index]); |
725 | | // − Otherwise, if subsampling_x is equal to 1 and subsampling_y is equal to 0, mv[ comp ] is set equal to |
726 | | // round_mv_comp_q2( BlockMvs[ refList ][ blockIdx ][ comp ] + BlockMvs[ refList ][ blockIdx + 1 ][ comp ] ) |
727 | | // for comp = 0..1. |
728 | 25.7k | if (block_context.frame_context.color_config.subsampling_x && !block_context.frame_context.color_config.subsampling_y) |
729 | 0 | return round_mv_comp_q2(vectors[block_index][reference_index] + vectors[block_index + 1][reference_index]); |
730 | | // − Otherwise, (subsampling_x is equal to 1 and subsampling_y is equal to 1), mv[ comp ] is set equal to |
731 | | // round_mv_comp_q4( BlockMvs[ refList ][ 0 ][ comp ] + BlockMvs[ refList ][ 1 ][ comp ] + |
732 | | // BlockMvs[ refList ][ 2 ][ comp ] + BlockMvs[ refList ][ 3 ][ comp ] ) for comp = 0..1. |
733 | 25.7k | VERIFY(block_context.frame_context.color_config.subsampling_x && block_context.frame_context.color_config.subsampling_y); |
734 | 25.7k | return round_mv_comp_q4(vectors[0][reference_index] + vectors[1][reference_index] |
735 | 25.7k | + vectors[2][reference_index] + vectors[3][reference_index]); |
736 | 25.7k | } |
737 | | |
738 | | MotionVector Decoder::clamp_motion_vector(u8 plane, BlockContext const& block_context, u32 block_row, u32 block_column, MotionVector vector) |
739 | 184k | { |
740 | | // FIXME: This function is named very similarly to Parser::clamp_mv. Rename one or the other? |
741 | | |
742 | | // The purpose of this process is to change the motion vector into the appropriate precision for the current plane |
743 | | // and to clamp motion vectors that go too far off the edge of the frame. |
744 | | // The variables sx and sy are set equal to the subsampling for the current plane as follows: |
745 | | // − If plane is equal to 0, sx is set equal to 0 and sy is set equal to 0. |
746 | | // − Otherwise, sx is set equal to subsampling_x and sy is set equal to subsampling_y. |
747 | 184k | bool subsampling_x = plane > 0 ? block_context.frame_context.color_config.subsampling_x : false; |
748 | 184k | bool subsampling_y = plane > 0 ? block_context.frame_context.color_config.subsampling_y : false; |
749 | | |
750 | | // The output array clampedMv is specified by the following steps: |
751 | 184k | i32 blocks_high = num_8x8_blocks_high_lookup[block_context.size]; |
752 | | // Casts must be done here to prevent subtraction underflow from wrapping the values. |
753 | 184k | i32 mb_to_top_edge = -(static_cast<i32>(block_row * MI_SIZE) * 16) >> subsampling_y; |
754 | 184k | i32 mb_to_bottom_edge = (((static_cast<i32>(block_context.frame_context.rows()) - blocks_high - static_cast<i32>(block_row)) * MI_SIZE) * 16) >> subsampling_y; |
755 | | |
756 | 184k | i32 blocks_wide = num_8x8_blocks_wide_lookup[block_context.size]; |
757 | 184k | i32 mb_to_left_edge = -(static_cast<i32>(block_column * MI_SIZE) * 16) >> subsampling_x; |
758 | 184k | i32 mb_to_right_edge = (((static_cast<i32>(block_context.frame_context.columns()) - blocks_wide - static_cast<i32>(block_column)) * MI_SIZE) * 16) >> subsampling_x; |
759 | | |
760 | 184k | i32 subpel_left = (INTERP_EXTEND + ((blocks_wide * MI_SIZE) >> subsampling_x)) << SUBPEL_BITS; |
761 | 184k | i32 subpel_right = subpel_left - SUBPEL_SHIFTS; |
762 | 184k | i32 subpel_top = (INTERP_EXTEND + ((blocks_high * MI_SIZE) >> subsampling_y)) << SUBPEL_BITS; |
763 | 184k | i32 subpel_bottom = subpel_top - SUBPEL_SHIFTS; |
764 | 184k | return { |
765 | 184k | clip_3(mb_to_top_edge - subpel_top, mb_to_bottom_edge + subpel_bottom, (2 * vector.row()) >> subsampling_y), |
766 | 184k | clip_3(mb_to_left_edge - subpel_left, mb_to_right_edge + subpel_right, (2 * vector.column()) >> subsampling_x) |
767 | 184k | }; |
768 | 184k | } |
769 | | |
770 | | static constexpr i32 maximum_scaled_step = 80; |
771 | | |
772 | | DecoderErrorOr<void> Decoder::prepare_referenced_frame(Gfx::Size<u32> frame_size, u8 reference_frame_index) |
773 | 3.81k | { |
774 | 3.81k | ReferenceFrame& reference_frame = m_parser->m_reference_frames[reference_frame_index]; |
775 | | |
776 | | // 8.5.2.3 Motion vector scaling process |
777 | | // The inputs to this process are: |
778 | | // − a variable plane specifying which plane is being predicted, |
779 | | // − a variable refList specifying that we should scale to match reference frame ref_frame[ refList ], |
780 | | // − variables x and y specifying the location of the top left sample in the CurrFrame[ plane ] array of the region |
781 | | // to be predicted, |
782 | | // − a variable clampedMv specifying the clamped motion vector. |
783 | | // The outputs of this process are the variables startX and startY giving the reference block location in units of |
784 | | // 1/16 th of a sample, and variables xStep and yStep giving the step size in units of 1/16 th of a sample. |
785 | | // This process is responsible for computing the sampling locations in the reference frame based on the motion |
786 | | // vector. The sampling locations are also adjusted to compensate for any difference in the size of the reference |
787 | | // frame compared to the current frame. |
788 | | |
789 | | // It is a requirement of bitstream conformance that all the following conditions are satisfied: |
790 | | // − 2 * FrameWidth >= RefFrameWidth[ refIdx ] |
791 | | // − 2 * FrameHeight >= RefFrameHeight[ refIdx ] |
792 | | // − FrameWidth <= 16 * RefFrameWidth[ refIdx ] |
793 | | // − FrameHeight <= 16 * RefFrameHeight[ refIdx ] |
794 | 3.81k | if (!reference_frame.is_valid()) |
795 | 3 | return DecoderError::format(DecoderErrorCategory::Corrupted, "Attempted to use reference frame {} that has not been saved", reference_frame_index); |
796 | 3.81k | auto double_frame_size = frame_size.scaled(2); |
797 | 3.81k | if (double_frame_size.width() < reference_frame.size.width() || double_frame_size.height() < reference_frame.size.height()) |
798 | 4 | return DecoderError::format(DecoderErrorCategory::Corrupted, "Inter frame size is too small relative to reference frame {}", reference_frame_index); |
799 | 3.80k | if (!reference_frame.size.scaled(16).contains(frame_size)) |
800 | 2 | return DecoderError::format(DecoderErrorCategory::Corrupted, "Inter frame size is too large relative to reference frame {}", reference_frame_index); |
801 | | |
802 | | // FIXME: Convert all the operations in this function to vector operations supported by |
803 | | // MotionVector. |
804 | | |
805 | | // A variable xScale is set equal to (RefFrameWidth[ refIdx ] << REF_SCALE_SHIFT) / FrameWidth. |
806 | | // A variable yScale is set equal to (RefFrameHeight[ refIdx ] << REF_SCALE_SHIFT) / FrameHeight. |
807 | | // (xScale and yScale specify the size of the reference frame relative to the current frame in units where 16 is |
808 | | // equivalent to the reference frame having the same size.) |
809 | | // NOTE: This spec note above seems to be incorrect. The 1:1 scale value would be 16,384. |
810 | 3.80k | i32 x_scale = (reference_frame.size.width() << REF_SCALE_SHIFT) / frame_size.width(); |
811 | 3.80k | i32 y_scale = (reference_frame.size.height() << REF_SCALE_SHIFT) / frame_size.height(); |
812 | | |
813 | | // The output variable stepX is set equal to (16 * xScale) >> REF_SCALE_SHIFT. |
814 | | // The output variable stepY is set equal to (16 * yScale) >> REF_SCALE_SHIFT. |
815 | 3.80k | i32 scaled_step_x = (16 * x_scale) >> REF_SCALE_SHIFT; |
816 | 3.80k | i32 scaled_step_y = (16 * y_scale) >> REF_SCALE_SHIFT; |
817 | | |
818 | | // 5. The block inter prediction process in section 8.5.2.4 is invoked with plane, refList, startX, startY, stepX, |
819 | | // stepY, w, h as inputs and the output is assigned to the 2D array preds[ refList ]. |
820 | | |
821 | | // 8.5.2.4 Block inter prediction process |
822 | | // The inputs to this process are: |
823 | | // − a variable plane, |
824 | | // − a variable refList specifying that we should predict from ref_frame[ refList ], |
825 | | // − variables x and y giving the block location in units of 1/16 th of a sample, |
826 | | // − variables xStep and yStep giving the step size in units of 1/16 th of a sample. (These will be at most equal |
827 | | // to 80 due to the restrictions on scaling between reference frames.) |
828 | 3.80k | VERIFY(scaled_step_x <= maximum_scaled_step && scaled_step_y <= maximum_scaled_step); |
829 | | // − variables w and h giving the width and height of the block in units of samples |
830 | | // The output from this process is the 2D array named pred containing inter predicted samples. |
831 | | |
832 | 3.80k | reference_frame.x_scale = x_scale; |
833 | 3.80k | reference_frame.y_scale = x_scale; |
834 | 3.80k | reference_frame.scaled_step_x = scaled_step_x; |
835 | 3.80k | reference_frame.scaled_step_y = scaled_step_y; |
836 | | |
837 | 3.80k | return {}; |
838 | 3.80k | } |
839 | | |
840 | | DecoderErrorOr<void> Decoder::predict_inter_block(u8 plane, BlockContext const& block_context, ReferenceIndex reference_index, u32 block_row, u32 block_column, u32 x, u32 y, u32 width, u32 height, u32 block_index, Span<u16> block_buffer) |
841 | 184k | { |
842 | 184k | VERIFY(width <= maximum_block_dimensions && height <= maximum_block_dimensions); |
843 | | // 2. The motion vector selection process in section 8.5.2.1 is invoked with plane, refList, blockIdx as inputs |
844 | | // and the output being the motion vector mv. |
845 | 184k | auto motion_vector = select_motion_vector(plane, block_context, reference_index, block_index); |
846 | | |
847 | | // 3. The motion vector clamping process in section 8.5.2.2 is invoked with plane, mv as inputs and the output |
848 | | // being the clamped motion vector clampedMv |
849 | 184k | auto clamped_vector = clamp_motion_vector(plane, block_context, block_row, block_column, motion_vector); |
850 | | |
851 | | // 4. The motion vector scaling process in section 8.5.2.3 is invoked with plane, refList, x, y, clampedMv as |
852 | | // inputs and the output being the initial location startX, startY, and the step sizes stepX, stepY. |
853 | | |
854 | | // 8.5.2.3 Motion vector scaling process |
855 | | // The inputs to this process are: |
856 | | // − a variable plane specifying which plane is being predicted, |
857 | | // − a variable refList specifying that we should scale to match reference frame ref_frame[ refList ], |
858 | | // − variables x and y specifying the location of the top left sample in the CurrFrame[ plane ] array of the region |
859 | | // to be predicted, |
860 | | // − a variable clampedMv specifying the clamped motion vector. |
861 | | // The outputs of this process are the variables startX and startY giving the reference block location in units of |
862 | | // 1/16 th of a sample, and variables xStep and yStep giving the step size in units of 1/16 th of a sample. |
863 | | // This process is responsible for computing the sampling locations in the reference frame based on the motion |
864 | | // vector. The sampling locations are also adjusted to compensate for any difference in the size of the reference |
865 | | // frame compared to the current frame. |
866 | | |
867 | | // NOTE: Some of this is done in advance by Decoder::prepare_referenced_frame(). |
868 | | |
869 | | // A variable refIdx specifying which reference frame is being used is set equal to |
870 | | // ref_frame_idx[ ref_frame[ refList ] - LAST_FRAME ]. |
871 | 184k | auto reference_frame_index = block_context.frame_context.reference_frame_indices[block_context.reference_frame_types[reference_index] - ReferenceFrameType::LastFrame]; |
872 | 184k | auto const& reference_frame = m_parser->m_reference_frames[reference_frame_index]; |
873 | | |
874 | | // Scale values range from 8192 to 262144. |
875 | | // 16384 = 1:1, higher values indicate the reference frame is larger than the current frame. |
876 | 184k | auto x_scale = reference_frame.x_scale; |
877 | 184k | auto y_scale = reference_frame.y_scale; |
878 | | |
879 | | // The amount of subpixels between each sample of this block. Non-16 values will cause the output to be scaled. |
880 | 184k | auto scaled_step_x = reference_frame.scaled_step_x; |
881 | 184k | auto scaled_step_y = reference_frame.scaled_step_y; |
882 | | |
883 | | // The variable baseX is set equal to (x * xScale) >> REF_SCALE_SHIFT. |
884 | | // The variable baseY is set equal to (y * yScale) >> REF_SCALE_SHIFT. |
885 | | // (baseX and baseY specify the location of the block in the reference frame if a zero motion vector is used). |
886 | 184k | i32 base_x = (x * x_scale) >> REF_SCALE_SHIFT; |
887 | 184k | i32 base_y = (y * y_scale) >> REF_SCALE_SHIFT; |
888 | | |
889 | | // The variable lumaX is set equal to (plane > 0) ? x << subsampling_x : x. |
890 | | // The variable lumaY is set equal to (plane > 0) ? y << subsampling_y : y. |
891 | | // (lumaX and lumaY specify the location of the block to be predicted in the current frame in units of luma |
892 | | // samples.) |
893 | 184k | bool subsampling_x = plane > 0 ? block_context.frame_context.color_config.subsampling_x : false; |
894 | 184k | bool subsampling_y = plane > 0 ? block_context.frame_context.color_config.subsampling_y : false; |
895 | 184k | i32 luma_x = x << subsampling_x; |
896 | 184k | i32 luma_y = y << subsampling_y; |
897 | | |
898 | | // The variable fracX is set equal to ( (16 * lumaX * xScale) >> REF_SCALE_SHIFT) & SUBPEL_MASK. |
899 | | // The variable fracY is set equal to ( (16 * lumaY * yScale) >> REF_SCALE_SHIFT) & SUBPEL_MASK. |
900 | 184k | i32 frac_x = ((16 * luma_x * x_scale) >> REF_SCALE_SHIFT) & SUBPEL_MASK; |
901 | 184k | i32 frac_y = ((16 * luma_y * y_scale) >> REF_SCALE_SHIFT) & SUBPEL_MASK; |
902 | | |
903 | | // The variable dX is set equal to ( (clampedMv[ 1 ] * xScale) >> REF_SCALE_SHIFT) + fracX. |
904 | | // The variable dY is set equal to ( (clampedMv[ 0 ] * yScale) >> REF_SCALE_SHIFT) + fracY. |
905 | | // (dX and dY specify a scaled motion vector.) |
906 | 184k | i32 scaled_vector_x = ((clamped_vector.column() * x_scale) >> REF_SCALE_SHIFT) + frac_x; |
907 | 184k | i32 scaled_vector_y = ((clamped_vector.row() * y_scale) >> REF_SCALE_SHIFT) + frac_y; |
908 | | |
909 | | // The output variable startX is set equal to (baseX << SUBPEL_BITS) + dX. |
910 | | // The output variable startY is set equal to (baseY << SUBPEL_BITS) + dY. |
911 | 184k | i32 offset_scaled_block_x = (base_x << SUBPEL_BITS) + scaled_vector_x; |
912 | 184k | i32 offset_scaled_block_y = (base_y << SUBPEL_BITS) + scaled_vector_y; |
913 | | |
914 | | // A variable ref specifying the reference frame contents is set equal to FrameStore[ refIdx ]. |
915 | 184k | auto& reference_frame_buffer = reference_frame.frame_planes[plane]; |
916 | 184k | auto reference_frame_width = Subsampling::subsampled_size(subsampling_x, reference_frame.size.width()) + MV_BORDER * 2; |
917 | | |
918 | | // The variable lastX is set equal to ( (RefFrameWidth[ refIdx ] + subX) >> subX) - 1. |
919 | | // The variable lastY is set equal to ( (RefFrameHeight[ refIdx ] + subY) >> subY) - 1. |
920 | | // (lastX and lastY specify the coordinates of the bottom right sample of the reference plane.) |
921 | | // Ad-hoc: These variables are not needed, since the reference frame is expanded to contain the samples that |
922 | | // may be referenced by motion vectors on the edge of the frame. |
923 | | |
924 | | // The sub-sample interpolation is effected via two one-dimensional convolutions. First a horizontal filter is used |
925 | | // to build up a temporary array, and then this array is vertically filtered to obtain the final prediction. The |
926 | | // fractional parts of the motion vectors determine the filtering process. If the fractional part is zero, then the |
927 | | // filtering is equivalent to a straight sample copy. |
928 | | // The filtering is applied as follows: |
929 | | |
930 | 184k | constexpr auto sample_offset = 3; |
931 | | |
932 | 184k | auto subpixel_row_from_reference_row = [offset_scaled_block_y](u32 row) { |
933 | 184k | return (offset_scaled_block_y >> SUBPEL_BITS) + static_cast<i32>(row); |
934 | 184k | }; |
935 | 184k | auto reference_index_for_row = [reference_frame_width](i32 row) { |
936 | 184k | return static_cast<size_t>(MV_BORDER + row) * reference_frame_width; |
937 | 184k | }; |
938 | | |
939 | | // The variable intermediateHeight specifying the height required for the intermediate array is set equal to (((h - |
940 | | // 1) * yStep + 15) >> 4) + 8. |
941 | 184k | static constexpr auto maximum_intermediate_height = (((maximum_block_dimensions - 1) * maximum_scaled_step + 15) >> 4) + 8; |
942 | 184k | auto const intermediate_height = (((height - 1) * scaled_step_y + 15) >> 4) + 8; |
943 | 184k | VERIFY(intermediate_height <= maximum_intermediate_height); |
944 | | // Check our reference frame bounds before starting the loop. |
945 | 184k | auto const last_possible_reference_index = reference_index_for_row(subpixel_row_from_reference_row(intermediate_height - sample_offset)); |
946 | 184k | VERIFY(reference_frame_buffer.size() >= last_possible_reference_index); |
947 | | |
948 | 184k | VERIFY(block_buffer.size() >= static_cast<size_t>(width) * height); |
949 | | |
950 | 184k | auto const reference_block_x = MV_BORDER + (offset_scaled_block_x >> SUBPEL_BITS); |
951 | 184k | auto const reference_block_y = MV_BORDER + (offset_scaled_block_y >> SUBPEL_BITS); |
952 | 184k | auto const reference_subpixel_x = offset_scaled_block_x & SUBPEL_MASK; |
953 | 184k | auto const reference_subpixel_y = offset_scaled_block_y & SUBPEL_MASK; |
954 | | |
955 | | // OPTIMIZATION: If the fractional part of a component of the motion vector is 0, we want to do a fast path |
956 | | // skipping one or both of the convolutions. |
957 | 184k | bool const copy_x = reference_subpixel_x == 0; |
958 | 184k | bool const copy_y = reference_subpixel_y == 0; |
959 | 184k | bool const unscaled_x = scaled_step_x == 16; |
960 | 184k | bool const unscaled_y = scaled_step_y == 16; |
961 | | |
962 | | // The array intermediate is specified as follows: |
963 | | // Note: Height is specified by `intermediate_height`, width is specified by `width` |
964 | 184k | Array<u16, maximum_intermediate_height * maximum_block_dimensions> intermediate_buffer; |
965 | 184k | auto const bit_depth = block_context.frame_context.color_config.bit_depth; |
966 | 184k | auto const* reference_start = reference_frame_buffer.data() + reference_block_y * reference_frame_width + reference_block_x; |
967 | | |
968 | | // FIXME: We are using 16-bit products to vectorize the filter loops, but when filtering in a high bit-depth video, they will truncate. |
969 | | // Instead of hardcoding them, we should have the bit depth as a template parameter, and the accumulators can select a size based |
970 | | // on whether the bit depth > 8. |
971 | | // Note that we only get a benefit from this on the default CPU target. If we enable AVX2 here, we may want to specialize the |
972 | | // function for the CPU target and remove the cast to i16 so that it doesn't have to truncate on AVX2, where it can do the full |
973 | | // unrolled 32-bit product loops in one vector. |
974 | | |
975 | 184k | if (unscaled_x && unscaled_y && bit_depth == 8) { |
976 | 144k | if (copy_x && copy_y) { |
977 | | // We can memcpy here to avoid doing any real work. |
978 | 59.1k | auto const* reference_scan_line = &reference_frame_buffer[reference_block_y * reference_frame_width + reference_block_x]; |
979 | 59.1k | auto* destination_scan_line = block_buffer.data(); |
980 | | |
981 | 469k | for (auto row = 0u; row < height; row++) { |
982 | 409k | memcpy(destination_scan_line, reference_scan_line, width * sizeof(*destination_scan_line)); |
983 | 409k | reference_scan_line += reference_frame_width; |
984 | 409k | destination_scan_line += width; |
985 | 409k | } |
986 | | |
987 | 59.1k | return {}; |
988 | 59.1k | } |
989 | | |
990 | 85.0k | auto horizontal_convolution_unscaled = [](auto bit_depth, auto* destination, auto width, auto height, auto const* source, auto source_stride, auto filter, auto subpixel_x) { |
991 | 68.3k | source -= sample_offset; |
992 | 68.3k | auto const source_end_skip = source_stride - width; |
993 | | |
994 | 825k | for (auto row = 0u; row < height; row++) { |
995 | 9.16M | for (auto column = 0u; column < width; column++) { |
996 | 8.40M | i32 accumulated_samples = 0; |
997 | 75.6M | for (auto t = 0; t < 8; t++) { |
998 | 67.2M | auto sample = source[t]; |
999 | 67.2M | accumulated_samples += static_cast<i16>(subpel_filters[filter][subpixel_x][t] * sample); |
1000 | 67.2M | } |
1001 | | |
1002 | 8.40M | *destination = clip_1(bit_depth, rounded_right_shift(accumulated_samples, 7)); |
1003 | 8.40M | source++; |
1004 | 8.40M | destination++; |
1005 | 8.40M | } |
1006 | 757k | source += source_end_skip; |
1007 | 757k | } |
1008 | 68.3k | }; |
1009 | | |
1010 | 85.0k | if (copy_y) { |
1011 | 26.9k | horizontal_convolution_unscaled(bit_depth, block_buffer.data(), width, height, reference_start, reference_frame_width, block_context.interpolation_filter, reference_subpixel_x); |
1012 | 26.9k | return {}; |
1013 | 26.9k | } |
1014 | | |
1015 | 58.1k | auto vertical_convolution_unscaled = [](auto bit_depth, auto* destination, auto width, auto height, auto const* source, auto source_stride, auto filter, auto subpixel_y) { |
1016 | 58.1k | auto const source_end_skip = source_stride - width; |
1017 | | |
1018 | 457k | for (auto row = 0u; row < height; row++) { |
1019 | 5.22M | for (auto column = 0u; column < width; column++) { |
1020 | 4.82M | auto const* scan_column = source; |
1021 | 4.82M | i32 accumulated_samples = 0; |
1022 | 43.3M | for (auto t = 0; t < 8; t++) { |
1023 | 38.5M | auto sample = *scan_column; |
1024 | 38.5M | accumulated_samples += static_cast<i16>(subpel_filters[filter][subpixel_y][t] * sample); |
1025 | 38.5M | scan_column += source_stride; |
1026 | 38.5M | } |
1027 | 4.82M | *destination = clip_1(bit_depth, rounded_right_shift(accumulated_samples, 7)); |
1028 | 4.82M | source++; |
1029 | 4.82M | destination++; |
1030 | 4.82M | } |
1031 | 399k | source += source_end_skip; |
1032 | 399k | } |
1033 | 58.1k | }; |
1034 | | |
1035 | 58.1k | if (copy_x) { |
1036 | 16.7k | vertical_convolution_unscaled(bit_depth, block_buffer.data(), width, height, reference_start - (sample_offset * reference_frame_width), reference_frame_width, block_context.interpolation_filter, reference_subpixel_y); |
1037 | 16.7k | return {}; |
1038 | 16.7k | } |
1039 | | |
1040 | 41.3k | horizontal_convolution_unscaled(bit_depth, intermediate_buffer.data(), width, intermediate_height, reference_start - (sample_offset * reference_frame_width), reference_frame_width, block_context.interpolation_filter, reference_subpixel_x); |
1041 | 41.3k | vertical_convolution_unscaled(bit_depth, block_buffer.data(), width, height, intermediate_buffer.data(), width, block_context.interpolation_filter, reference_subpixel_y); |
1042 | 41.3k | return {}; |
1043 | 58.1k | } |
1044 | | |
1045 | | // NOTE: Accumulators below are 32-bit to allow high bit-depth videos to decode without overflows. |
1046 | | // These should be changed when the accumulators above are. |
1047 | | |
1048 | 40.4k | auto horizontal_convolution_scaled = [](auto bit_depth, auto* destination, auto width, auto height, auto const* source, auto source_stride, auto filter, auto subpixel_x, auto scale_x) { |
1049 | 40.4k | source -= sample_offset; |
1050 | | |
1051 | 511k | for (auto row = 0u; row < height; row++) { |
1052 | 470k | auto scan_subpixel = subpixel_x; |
1053 | 4.82M | for (auto column = 0u; column < width; column++) { |
1054 | 4.35M | auto const* scan_line = source + (scan_subpixel >> 4); |
1055 | 4.35M | i32 accumulated_samples = 0; |
1056 | 39.1M | for (auto t = 0; t < 8; t++) { |
1057 | 34.8M | auto sample = scan_line[t]; |
1058 | 34.8M | accumulated_samples += subpel_filters[filter][scan_subpixel & SUBPEL_MASK][t] * sample; |
1059 | 34.8M | } |
1060 | | |
1061 | 4.35M | *destination = clip_1(bit_depth, rounded_right_shift(accumulated_samples, 7)); |
1062 | 4.35M | destination++; |
1063 | 4.35M | scan_subpixel += scale_x; |
1064 | 4.35M | } |
1065 | 470k | source += source_stride; |
1066 | 470k | } |
1067 | 40.4k | }; |
1068 | | |
1069 | 40.4k | auto vertical_convolution_scaled = [](auto bit_depth, auto* destination, auto width, auto height, auto const* source, auto source_stride, auto filter, auto subpixel_y, auto scale_y) { |
1070 | 289k | for (auto row = 0u; row < height; row++) { |
1071 | 248k | auto const* source_column_base = source + (subpixel_y >> SUBPEL_BITS) * source_stride; |
1072 | | |
1073 | 4.75M | for (auto column = 0u; column < width; column++) { |
1074 | 4.50M | auto const* scan_column = source_column_base + column; |
1075 | 4.50M | i32 accumulated_samples = 0; |
1076 | 40.5M | for (auto t = 0; t < 8; t++) { |
1077 | 36.0M | auto sample = *scan_column; |
1078 | 36.0M | accumulated_samples += subpel_filters[filter][subpixel_y & SUBPEL_MASK][t] * sample; |
1079 | 36.0M | scan_column += source_stride; |
1080 | 36.0M | } |
1081 | | |
1082 | 4.50M | *destination = clip_1(bit_depth, rounded_right_shift(accumulated_samples, 7)); |
1083 | 4.50M | destination++; |
1084 | 4.50M | } |
1085 | 248k | subpixel_y += scale_y; |
1086 | 248k | } |
1087 | 40.4k | }; |
1088 | | |
1089 | 40.4k | horizontal_convolution_scaled(bit_depth, intermediate_buffer.data(), width, intermediate_height, reference_start - (sample_offset * reference_frame_width), reference_frame_width, block_context.interpolation_filter, offset_scaled_block_x & SUBPEL_MASK, scaled_step_x); |
1090 | 40.4k | vertical_convolution_scaled(bit_depth, block_buffer.data(), width, height, intermediate_buffer.data(), width, block_context.interpolation_filter, reference_subpixel_y, scaled_step_y); |
1091 | | |
1092 | 40.4k | return {}; |
1093 | 184k | } |
1094 | | |
1095 | | DecoderErrorOr<void> Decoder::predict_inter(u8 plane, BlockContext const& block_context, u32 x, u32 y, u32 width, u32 height, u32 block_index) |
1096 | 136k | { |
1097 | | // The inter prediction process is invoked for inter coded blocks. When MiSize is smaller than BLOCK_8X8, the |
1098 | | // prediction is done with a granularity of 4x4 samples, otherwise the whole plane is predicted at the same time. |
1099 | | // The inputs to this process are: |
1100 | | // − a variable plane specifying which plane is being predicted, |
1101 | | // − variables x and y specifying the location of the top left sample in the CurrFrame[ plane ] array of the region |
1102 | | // to be predicted, |
1103 | | // − variables w and h specifying the width and height of the region to be predicted, |
1104 | | // − a variable blockIdx, specifying how much of the block has already been predicted in units of 4x4 samples. |
1105 | | // The outputs of this process are inter predicted samples in the current frame CurrFrame. |
1106 | | |
1107 | | // The prediction arrays are formed by the following ordered steps: |
1108 | | // 1. The variable refList is set equal to 0. |
1109 | | // 2. through 5. |
1110 | 136k | Array<u16, maximum_block_size> predicted_buffer; |
1111 | 136k | auto predicted_span = predicted_buffer.span().trim(width * height); |
1112 | 136k | TRY(predict_inter_block(plane, block_context, ReferenceIndex::Primary, block_context.row, block_context.column, x, y, width, height, block_index, predicted_span)); |
1113 | 14.1M | auto predicted_buffer_at = [&](Span<u16> buffer, u32 row, u32 column) -> u16& { |
1114 | 14.1M | return buffer[row * width + column]; |
1115 | 14.1M | }; |
1116 | | |
1117 | | // 6. If isCompound is equal to 1, then the variable refList is set equal to 1 and steps 2, 3, 4 and 5 are repeated |
1118 | | // to form the prediction for the second reference. |
1119 | | // The inter predicted samples are then derived as follows: |
1120 | 136k | auto& frame_buffer = get_output_buffer(plane); |
1121 | 136k | VERIFY(!frame_buffer.is_empty()); |
1122 | 136k | auto frame_size = block_context.frame_context.decoded_size(plane > 0); |
1123 | 11.6M | auto frame_buffer_at = [&](u32 row, u32 column) -> u16& { |
1124 | 11.6M | return frame_buffer[row * frame_size.width() + column]; |
1125 | 11.6M | }; |
1126 | | |
1127 | 136k | auto width_in_frame_buffer = min(width, frame_size.width() - x); |
1128 | 136k | auto height_in_frame_buffer = min(height, frame_size.height() - y); |
1129 | | |
1130 | | // The variable isCompound is set equal to ref_frame[ 1 ] > NONE. |
1131 | | // − If isCompound is equal to 0, CurrFrame[ plane ][ y + i ][ x + j ] is set equal to preds[ 0 ][ i ][ j ] for i = 0..h-1 |
1132 | | // and j = 0..w-1. |
1133 | 136k | if (!block_context.is_compound()) { |
1134 | 712k | for (auto i = 0u; i < height_in_frame_buffer; i++) { |
1135 | 9.75M | for (auto j = 0u; j < width_in_frame_buffer; j++) |
1136 | 9.13M | frame_buffer_at(y + i, x + j) = predicted_buffer_at(predicted_span, i, j); |
1137 | 623k | } |
1138 | | |
1139 | 88.5k | return {}; |
1140 | 88.5k | } |
1141 | | |
1142 | | // − Otherwise, CurrFrame[ plane ][ y + i ][ x + j ] is set equal to Round2( preds[ 0 ][ i ][ j ] + preds[ 1 ][ i ][ j ], 1 ) |
1143 | | // for i = 0..h-1 and j = 0..w-1. |
1144 | 48.0k | Array<u16, maximum_block_size> second_predicted_buffer; |
1145 | 48.0k | auto second_predicted_span = second_predicted_buffer.span().trim(width * height); |
1146 | 48.0k | TRY(predict_inter_block(plane, block_context, ReferenceIndex::Secondary, block_context.row, block_context.column, x, y, width, height, block_index, second_predicted_span)); |
1147 | | |
1148 | 323k | for (auto i = 0u; i < height_in_frame_buffer; i++) { |
1149 | 2.78M | for (auto j = 0u; j < width_in_frame_buffer; j++) |
1150 | 2.51M | frame_buffer_at(y + i, x + j) = rounded_right_shift(predicted_buffer_at(predicted_span, i, j) + predicted_buffer_at(second_predicted_span, i, j), 1); |
1151 | 275k | } |
1152 | | |
1153 | 48.0k | return {}; |
1154 | 48.0k | } |
1155 | | |
1156 | | inline u16 dc_q(u8 bit_depth, u8 b) |
1157 | 33.6k | { |
1158 | | // The function dc_q( b ) is specified as dc_qlookup[ (BitDepth-8) >> 1 ][ Clip3( 0, 255, b ) ] where dc_lookup is |
1159 | | // defined as follows: |
1160 | 33.6k | constexpr u16 dc_qlookup[3][256] = { |
1161 | 33.6k | { 4, 8, 8, 9, 10, 11, 12, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 23, 24, 25, 26, 26, 27, 28, 29, 30, 31, 32, 32, 33, 34, 35, 36, 37, 38, 38, 39, 40, 41, 42, 43, 43, 44, 45, 46, 47, 48, 48, 49, 50, 51, 52, 53, 53, 54, 55, 56, 57, 57, 58, 59, 60, 61, 62, 62, 63, 64, 65, 66, 66, 67, 68, 69, 70, 70, 71, 72, 73, 74, 74, 75, 76, 77, 78, 78, 79, 80, 81, 81, 82, 83, 84, 85, 85, 87, 88, 90, 92, 93, 95, 96, 98, 99, 101, 102, 104, 105, 107, 108, 110, 111, 113, 114, 116, 117, 118, 120, 121, 123, 125, 127, 129, 131, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 161, 164, 166, 169, 172, 174, 177, 180, 182, 185, 187, 190, 192, 195, 199, 202, 205, 208, 211, 214, 217, 220, 223, 226, 230, 233, 237, 240, 243, 247, 250, 253, 257, 261, 265, 269, 272, 276, 280, 284, 288, 292, 296, 300, 304, 309, 313, 317, 322, 326, 330, 335, 340, 344, 349, 354, 359, 364, 369, 374, 379, 384, 389, 395, 400, 406, 411, 417, 423, 429, 435, 441, 447, 454, 461, 467, 475, 482, 489, 497, 505, 513, 522, 530, 539, 549, 559, 569, 579, 590, 602, 614, 626, 640, 654, 668, 684, 700, 717, 736, 755, 775, 796, 819, 843, 869, 896, 925, 955, 988, 1022, 1058, 1098, 1139, 1184, 1232, 1282, 1336 }, |
1162 | 33.6k | { 4, 9, 10, 13, 15, 17, 20, 22, 25, 28, 31, 34, 37, 40, 43, 47, 50, 53, 57, 60, 64, 68, 71, 75, 78, 82, 86, 90, 93, 97, 101, 105, 109, 113, 116, 120, 124, 128, 132, 136, 140, 143, 147, 151, 155, 159, 163, 166, 170, 174, 178, 182, 185, 189, 193, 197, 200, 204, 208, 212, 215, 219, 223, 226, 230, 233, 237, 241, 244, 248, 251, 255, 259, 262, 266, 269, 273, 276, 280, 283, 287, 290, 293, 297, 300, 304, 307, 310, 314, 317, 321, 324, 327, 331, 334, 337, 343, 350, 356, 362, 369, 375, 381, 387, 394, 400, 406, 412, 418, 424, 430, 436, 442, 448, 454, 460, 466, 472, 478, 484, 490, 499, 507, 516, 525, 533, 542, 550, 559, 567, 576, 584, 592, 601, 609, 617, 625, 634, 644, 655, 666, 676, 687, 698, 708, 718, 729, 739, 749, 759, 770, 782, 795, 807, 819, 831, 844, 856, 868, 880, 891, 906, 920, 933, 947, 961, 975, 988, 1001, 1015, 1030, 1045, 1061, 1076, 1090, 1105, 1120, 1137, 1153, 1170, 1186, 1202, 1218, 1236, 1253, 1271, 1288, 1306, 1323, 1342, 1361, 1379, 1398, 1416, 1436, 1456, 1476, 1496, 1516, 1537, 1559, 1580, 1601, 1624, 1647, 1670, 1692, 1717, 1741, 1766, 1791, 1817, 1844, 1871, 1900, 1929, 1958, 1990, 2021, 2054, 2088, 2123, 2159, 2197, 2236, 2276, 2319, 2363, 2410, 2458, 2508, 2561, 2616, 2675, 2737, 2802, 2871, 2944, 3020, 3102, 3188, 3280, 3375, 3478, 3586, 3702, 3823, 3953, 4089, 4236, 4394, 4559, 4737, 4929, 5130, 5347 }, |
1163 | 33.6k | { 4, 12, 18, 25, 33, 41, 50, 60, 70, 80, 91, 103, 115, 127, 140, 153, 166, 180, 194, 208, 222, 237, 251, 266, 281, 296, 312, 327, 343, 358, 374, 390, 405, 421, 437, 453, 469, 484, 500, 516, 532, 548, 564, 580, 596, 611, 627, 643, 659, 674, 690, 706, 721, 737, 752, 768, 783, 798, 814, 829, 844, 859, 874, 889, 904, 919, 934, 949, 964, 978, 993, 1008, 1022, 1037, 1051, 1065, 1080, 1094, 1108, 1122, 1136, 1151, 1165, 1179, 1192, 1206, 1220, 1234, 1248, 1261, 1275, 1288, 1302, 1315, 1329, 1342, 1368, 1393, 1419, 1444, 1469, 1494, 1519, 1544, 1569, 1594, 1618, 1643, 1668, 1692, 1717, 1741, 1765, 1789, 1814, 1838, 1862, 1885, 1909, 1933, 1957, 1992, 2027, 2061, 2096, 2130, 2165, 2199, 2233, 2267, 2300, 2334, 2367, 2400, 2434, 2467, 2499, 2532, 2575, 2618, 2661, 2704, 2746, 2788, 2830, 2872, 2913, 2954, 2995, 3036, 3076, 3127, 3177, 3226, 3275, 3324, 3373, 3421, 3469, 3517, 3565, 3621, 3677, 3733, 3788, 3843, 3897, 3951, 4005, 4058, 4119, 4181, 4241, 4301, 4361, 4420, 4479, 4546, 4612, 4677, 4742, 4807, 4871, 4942, 5013, 5083, 5153, 5222, 5291, 5367, 5442, 5517, 5591, 5665, 5745, 5825, 5905, 5984, 6063, 6149, 6234, 6319, 6404, 6495, 6587, 6678, 6769, 6867, 6966, 7064, 7163, 7269, 7376, 7483, 7599, 7715, 7832, 7958, 8085, 8214, 8352, 8492, 8635, 8788, 8945, 9104, 9275, 9450, 9639, 9832, 10031, 10245, 10465, 10702, 10946, 11210, 11482, 11776, 12081, 12409, 12750, 13118, 13501, 13913, 14343, 14807, 15290, 15812, 16356, 16943, 17575, 18237, 18949, 19718, 20521, 21387 } |
1164 | 33.6k | }; |
1165 | | |
1166 | 33.6k | return dc_qlookup[(bit_depth - 8) >> 1][clip_3<u8>(0, 255, b)]; |
1167 | 33.6k | } |
1168 | | |
1169 | | inline u16 ac_q(u8 bit_depth, u8 b) |
1170 | 33.6k | { |
1171 | | // The function ac_q( b ) is specified as ac_qlookup[ (BitDepth-8) >> 1 ][ Clip3( 0, 255, b ) ] where ac_lookup is |
1172 | | // defined as follows: |
1173 | 33.6k | constexpr u16 ac_qlookup[3][256] = { |
1174 | 33.6k | { 4, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 155, 158, 161, 164, 167, 170, 173, 176, 179, 182, 185, 188, 191, 194, 197, 200, 203, 207, 211, 215, 219, 223, 227, 231, 235, 239, 243, 247, 251, 255, 260, 265, 270, 275, 280, 285, 290, 295, 300, 305, 311, 317, 323, 329, 335, 341, 347, 353, 359, 366, 373, 380, 387, 394, 401, 408, 416, 424, 432, 440, 448, 456, 465, 474, 483, 492, 501, 510, 520, 530, 540, 550, 560, 571, 582, 593, 604, 615, 627, 639, 651, 663, 676, 689, 702, 715, 729, 743, 757, 771, 786, 801, 816, 832, 848, 864, 881, 898, 915, 933, 951, 969, 988, 1007, 1026, 1046, 1066, 1087, 1108, 1129, 1151, 1173, 1196, 1219, 1243, 1267, 1292, 1317, 1343, 1369, 1396, 1423, 1451, 1479, 1508, 1537, 1567, 1597, 1628, 1660, 1692, 1725, 1759, 1793, 1828 }, |
1175 | 33.6k | { 4, 9, 11, 13, 16, 18, 21, 24, 27, 30, 33, 37, 40, 44, 48, 51, 55, 59, 63, 67, 71, 75, 79, 83, 88, 92, 96, 100, 105, 109, 114, 118, 122, 127, 131, 136, 140, 145, 149, 154, 158, 163, 168, 172, 177, 181, 186, 190, 195, 199, 204, 208, 213, 217, 222, 226, 231, 235, 240, 244, 249, 253, 258, 262, 267, 271, 275, 280, 284, 289, 293, 297, 302, 306, 311, 315, 319, 324, 328, 332, 337, 341, 345, 349, 354, 358, 362, 367, 371, 375, 379, 384, 388, 392, 396, 401, 409, 417, 425, 433, 441, 449, 458, 466, 474, 482, 490, 498, 506, 514, 523, 531, 539, 547, 555, 563, 571, 579, 588, 596, 604, 616, 628, 640, 652, 664, 676, 688, 700, 713, 725, 737, 749, 761, 773, 785, 797, 809, 825, 841, 857, 873, 889, 905, 922, 938, 954, 970, 986, 1002, 1018, 1038, 1058, 1078, 1098, 1118, 1138, 1158, 1178, 1198, 1218, 1242, 1266, 1290, 1314, 1338, 1362, 1386, 1411, 1435, 1463, 1491, 1519, 1547, 1575, 1603, 1631, 1663, 1695, 1727, 1759, 1791, 1823, 1859, 1895, 1931, 1967, 2003, 2039, 2079, 2119, 2159, 2199, 2239, 2283, 2327, 2371, 2415, 2459, 2507, 2555, 2603, 2651, 2703, 2755, 2807, 2859, 2915, 2971, 3027, 3083, 3143, 3203, 3263, 3327, 3391, 3455, 3523, 3591, 3659, 3731, 3803, 3876, 3952, 4028, 4104, 4184, 4264, 4348, 4432, 4516, 4604, 4692, 4784, 4876, 4972, 5068, 5168, 5268, 5372, 5476, 5584, 5692, 5804, 5916, 6032, 6148, 6268, 6388, 6512, 6640, 6768, 6900, 7036, 7172, 7312 }, |
1176 | 33.6k | { 4, 13, 19, 27, 35, 44, 54, 64, 75, 87, 99, 112, 126, 139, 154, 168, 183, 199, 214, 230, 247, 263, 280, 297, 314, 331, 349, 366, 384, 402, 420, 438, 456, 475, 493, 511, 530, 548, 567, 586, 604, 623, 642, 660, 679, 698, 716, 735, 753, 772, 791, 809, 828, 846, 865, 884, 902, 920, 939, 957, 976, 994, 1012, 1030, 1049, 1067, 1085, 1103, 1121, 1139, 1157, 1175, 1193, 1211, 1229, 1246, 1264, 1282, 1299, 1317, 1335, 1352, 1370, 1387, 1405, 1422, 1440, 1457, 1474, 1491, 1509, 1526, 1543, 1560, 1577, 1595, 1627, 1660, 1693, 1725, 1758, 1791, 1824, 1856, 1889, 1922, 1954, 1987, 2020, 2052, 2085, 2118, 2150, 2183, 2216, 2248, 2281, 2313, 2346, 2378, 2411, 2459, 2508, 2556, 2605, 2653, 2701, 2750, 2798, 2847, 2895, 2943, 2992, 3040, 3088, 3137, 3185, 3234, 3298, 3362, 3426, 3491, 3555, 3619, 3684, 3748, 3812, 3876, 3941, 4005, 4069, 4149, 4230, 4310, 4390, 4470, 4550, 4631, 4711, 4791, 4871, 4967, 5064, 5160, 5256, 5352, 5448, 5544, 5641, 5737, 5849, 5961, 6073, 6185, 6297, 6410, 6522, 6650, 6778, 6906, 7034, 7162, 7290, 7435, 7579, 7723, 7867, 8011, 8155, 8315, 8475, 8635, 8795, 8956, 9132, 9308, 9484, 9660, 9836, 10028, 10220, 10412, 10604, 10812, 11020, 11228, 11437, 11661, 11885, 12109, 12333, 12573, 12813, 13053, 13309, 13565, 13821, 14093, 14365, 14637, 14925, 15213, 15502, 15806, 16110, 16414, 16734, 17054, 17390, 17726, 18062, 18414, 18766, 19134, 19502, 19886, 20270, 20670, 21070, 21486, 21902, 22334, 22766, 23214, 23662, 24126, 24590, 25070, 25551, 26047, 26559, 27071, 27599, 28143, 28687, 29247 } |
1177 | 33.6k | }; |
1178 | | |
1179 | 33.6k | return ac_qlookup[(bit_depth - 8) >> 1][clip_3<u8>(0, 255, b)]; |
1180 | 33.6k | } |
1181 | | |
1182 | | u8 Decoder::get_base_quantizer_index(SegmentFeatureStatus alternative_quantizer_feature, bool should_use_absolute_segment_base_quantizer, u8 base_quantizer_index) |
1183 | 16.8k | { |
1184 | | // The function get_qindex( ) returns the quantizer index for the current block and is specified by the following: |
1185 | | // − If seg_feature_active( SEG_LVL_ALT_Q ) is equal to 1 the following ordered steps apply: |
1186 | 16.8k | if (alternative_quantizer_feature.enabled) { |
1187 | | // 1. Set the variable data equal to FeatureData[ segment_id ][ SEG_LVL_ALT_Q ]. |
1188 | 1.90k | auto data = alternative_quantizer_feature.value; |
1189 | | |
1190 | | // 2. If segmentation_abs_or_delta_update is equal to 0, set data equal to base_q_idx + data |
1191 | 1.90k | if (!should_use_absolute_segment_base_quantizer) { |
1192 | 27 | data += base_quantizer_index; |
1193 | 27 | } |
1194 | | |
1195 | | // 3. Return Clip3( 0, 255, data ). |
1196 | 1.90k | return clip_3<u8>(0, 255, data); |
1197 | 1.90k | } |
1198 | | |
1199 | | // − Otherwise, return base_q_idx. |
1200 | 14.9k | return base_quantizer_index; |
1201 | 16.8k | } |
1202 | | |
1203 | | u16 Decoder::get_dc_quantizer(u8 bit_depth, u8 base, i8 delta) |
1204 | 33.6k | { |
1205 | | // NOTE: Delta is selected by the caller based on whether it is for the Y or UV planes. |
1206 | | |
1207 | | // The function get_dc_quant( plane ) returns the quantizer value for the dc coefficient for a particular plane and |
1208 | | // is derived as follows: |
1209 | | // − If plane is equal to 0, return dc_q( get_qindex( ) + delta_q_y_dc ). |
1210 | | // − Otherwise, return dc_q( get_qindex( ) + delta_q_uv_dc ). |
1211 | 33.6k | return dc_q(bit_depth, static_cast<u8>(base + delta)); |
1212 | 33.6k | } |
1213 | | |
1214 | | u16 Decoder::get_ac_quantizer(u8 bit_depth, u8 base, i8 delta) |
1215 | 33.6k | { |
1216 | | // NOTE: Delta is selected by the caller based on whether it is for the Y or UV planes. |
1217 | | |
1218 | | // The function get_ac_quant( plane ) returns the quantizer value for the ac coefficient for a particular plane and |
1219 | | // is derived as follows: |
1220 | | // − If plane is equal to 0, return ac_q( get_qindex( ) ). |
1221 | | // − Otherwise, return ac_q( get_qindex( ) + delta_q_uv_ac ). |
1222 | 33.6k | return ac_q(bit_depth, static_cast<u8>(base + delta)); |
1223 | 33.6k | } |
1224 | | |
1225 | | DecoderErrorOr<void> Decoder::reconstruct(u8 plane, BlockContext const& block_context, u32 transform_block_x, u32 transform_block_y, TransformSize transform_block_size, TransformSet transform_set) |
1226 | 8.55M | { |
1227 | | // 8.6.2 Reconstruct process |
1228 | | |
1229 | | // The variable n (specifying the base 2 logarithm of the width of the transform block) is set equal to 2 + txSz. |
1230 | 8.55M | u8 log2_of_block_size = 2u + transform_block_size; |
1231 | 8.55M | switch (log2_of_block_size) { |
1232 | 6.98M | case 2: |
1233 | 6.98M | return reconstruct_templated<2>(plane, block_context, transform_block_x, transform_block_y, transform_set); |
1234 | 1.01M | case 3: |
1235 | 1.01M | return reconstruct_templated<3>(plane, block_context, transform_block_x, transform_block_y, transform_set); |
1236 | 170k | case 4: |
1237 | 170k | return reconstruct_templated<4>(plane, block_context, transform_block_x, transform_block_y, transform_set); |
1238 | 382k | case 5: |
1239 | 382k | return reconstruct_templated<5>(plane, block_context, transform_block_x, transform_block_y, transform_set); |
1240 | 0 | default: |
1241 | 0 | VERIFY_NOT_REACHED(); |
1242 | 8.55M | } |
1243 | 8.55M | } |
1244 | | |
1245 | | template<u8 log2_of_block_size> |
1246 | | DecoderErrorOr<void> Decoder::reconstruct_templated(u8 plane, BlockContext const& block_context, u32 transform_block_x, u32 transform_block_y, TransformSet transform_set) |
1247 | 8.56M | { |
1248 | | // 8.6.2 Reconstruct process, continued: |
1249 | | |
1250 | | // The variable dqDenom is set equal to 2 if txSz is equal to Transform_32X32, otherwise dqDenom is set equal to 1. |
1251 | 8.56M | constexpr Intermediate dq_denominator = log2_of_block_size == 5 ? 2 : 1; |
1252 | | // The variable n0 (specifying the width of the transform block) is set equal to 1 << n. |
1253 | 8.56M | constexpr auto block_size = 1u << log2_of_block_size; |
1254 | | |
1255 | | // 1. Dequant[ i ][ j ] is set equal to ( Tokens[ i * n0 + j ] * get_ac_quant( plane ) ) / dqDenom |
1256 | | // for i = 0..(n0-1), for j = 0..(n0-1) |
1257 | 8.56M | Array<Intermediate, block_size * block_size> dequantized; |
1258 | 8.56M | auto quantizers = block_context.frame_context.segment_quantizers[block_context.segment_id]; |
1259 | 8.56M | Intermediate ac_quant = plane == 0 ? quantizers.y_ac_quantizer : quantizers.uv_ac_quantizer; |
1260 | 8.56M | auto const* tokens_raw = block_context.residual_tokens.data(); |
1261 | 620M | for (u32 i = 0; i < dequantized.size(); i++) { |
1262 | 611M | dequantized[i] = (tokens_raw[i] * ac_quant) / dq_denominator; |
1263 | 611M | } |
1264 | | |
1265 | | // 2. Dequant[ 0 ][ 0 ] is set equal to ( Tokens[ 0 ] * get_dc_quant( plane ) ) / dqDenom |
1266 | 8.56M | dequantized[0] = (block_context.residual_tokens[0] * (plane == 0 ? quantizers.y_dc_quantizer : quantizers.uv_dc_quantizer)) / dq_denominator; |
1267 | | |
1268 | | // It is a requirement of bitstream conformance that the values written into the Dequant array in steps 1 and 2 |
1269 | | // are representable by a signed integer with 8 + BitDepth bits. |
1270 | | // Note: Since bounds checks just ensure that we will not have resulting values that will overflow, it's non-fatal |
1271 | | // to allow these bounds to be violated. Therefore, we can avoid the performance cost here. |
1272 | | |
1273 | | // 3. Invoke the 2D inverse transform block process defined in section 8.7.2 with the variable n as input. |
1274 | | // The inverse transform outputs are stored back to the Dequant buffer. |
1275 | 8.56M | TRY(inverse_transform_2d<log2_of_block_size>(block_context, dequantized, transform_set)); |
1276 | | |
1277 | | // 4. CurrFrame[ plane ][ y + i ][ x + j ] is set equal to Clip1( CurrFrame[ plane ][ y + i ][ x + j ] + Dequant[ i ][ j ] ) |
1278 | | // for i = 0..(n0-1) and j = 0..(n0-1). |
1279 | 8.56M | auto& current_buffer = get_output_buffer(plane); |
1280 | 8.56M | auto frame_size = block_context.frame_context.decoded_size(plane > 0); |
1281 | 8.56M | auto width_in_frame_buffer = min(block_size, frame_size.width() - transform_block_x); |
1282 | 8.56M | auto height_in_frame_buffer = min(block_size, frame_size.height() - transform_block_y); |
1283 | | |
1284 | 59.4M | for (auto i = 0u; i < height_in_frame_buffer; i++) { |
1285 | 635M | for (auto j = 0u; j < width_in_frame_buffer; j++) { |
1286 | 584M | auto index = (transform_block_y + i) * frame_size.width() + transform_block_x + j; |
1287 | 584M | auto dequantized_value = dequantized[i * block_size + j]; |
1288 | 584M | current_buffer[index] = clip_1(block_context.frame_context.color_config.bit_depth, current_buffer[index] + dequantized_value); |
1289 | 584M | } |
1290 | 50.8M | } |
1291 | | |
1292 | 8.56M | return {}; |
1293 | 8.56M | } AK::ErrorOr<void, Media::DecoderError> Media::Video::VP9::Decoder::reconstruct_templated<(unsigned char)2>(unsigned char, Media::Video::VP9::BlockContext const&, unsigned int, unsigned int, Media::Video::VP9::TransformSet) Line | Count | Source | 1247 | 6.98M | { | 1248 | | // 8.6.2 Reconstruct process, continued: | 1249 | | | 1250 | | // The variable dqDenom is set equal to 2 if txSz is equal to Transform_32X32, otherwise dqDenom is set equal to 1. | 1251 | 6.98M | constexpr Intermediate dq_denominator = log2_of_block_size == 5 ? 2 : 1; | 1252 | | // The variable n0 (specifying the width of the transform block) is set equal to 1 << n. | 1253 | 6.98M | constexpr auto block_size = 1u << log2_of_block_size; | 1254 | | | 1255 | | // 1. Dequant[ i ][ j ] is set equal to ( Tokens[ i * n0 + j ] * get_ac_quant( plane ) ) / dqDenom | 1256 | | // for i = 0..(n0-1), for j = 0..(n0-1) | 1257 | 6.98M | Array<Intermediate, block_size * block_size> dequantized; | 1258 | 6.98M | auto quantizers = block_context.frame_context.segment_quantizers[block_context.segment_id]; | 1259 | 6.98M | Intermediate ac_quant = plane == 0 ? quantizers.y_ac_quantizer : quantizers.uv_ac_quantizer; | 1260 | 6.98M | auto const* tokens_raw = block_context.residual_tokens.data(); | 1261 | 118M | for (u32 i = 0; i < dequantized.size(); i++) { | 1262 | 111M | dequantized[i] = (tokens_raw[i] * ac_quant) / dq_denominator; | 1263 | 111M | } | 1264 | | | 1265 | | // 2. Dequant[ 0 ][ 0 ] is set equal to ( Tokens[ 0 ] * get_dc_quant( plane ) ) / dqDenom | 1266 | 6.98M | dequantized[0] = (block_context.residual_tokens[0] * (plane == 0 ? quantizers.y_dc_quantizer : quantizers.uv_dc_quantizer)) / dq_denominator; | 1267 | | | 1268 | | // It is a requirement of bitstream conformance that the values written into the Dequant array in steps 1 and 2 | 1269 | | // are representable by a signed integer with 8 + BitDepth bits. | 1270 | | // Note: Since bounds checks just ensure that we will not have resulting values that will overflow, it's non-fatal | 1271 | | // to allow these bounds to be violated. Therefore, we can avoid the performance cost here. | 1272 | | | 1273 | | // 3. Invoke the 2D inverse transform block process defined in section 8.7.2 with the variable n as input. | 1274 | | // The inverse transform outputs are stored back to the Dequant buffer. | 1275 | 6.98M | TRY(inverse_transform_2d<log2_of_block_size>(block_context, dequantized, transform_set)); | 1276 | | | 1277 | | // 4. CurrFrame[ plane ][ y + i ][ x + j ] is set equal to Clip1( CurrFrame[ plane ][ y + i ][ x + j ] + Dequant[ i ][ j ] ) | 1278 | | // for i = 0..(n0-1) and j = 0..(n0-1). | 1279 | 6.98M | auto& current_buffer = get_output_buffer(plane); | 1280 | 6.98M | auto frame_size = block_context.frame_context.decoded_size(plane > 0); | 1281 | 6.98M | auto width_in_frame_buffer = min(block_size, frame_size.width() - transform_block_x); | 1282 | 6.98M | auto height_in_frame_buffer = min(block_size, frame_size.height() - transform_block_y); | 1283 | | | 1284 | 34.8M | for (auto i = 0u; i < height_in_frame_buffer; i++) { | 1285 | 139M | for (auto j = 0u; j < width_in_frame_buffer; j++) { | 1286 | 111M | auto index = (transform_block_y + i) * frame_size.width() + transform_block_x + j; | 1287 | 111M | auto dequantized_value = dequantized[i * block_size + j]; | 1288 | 111M | current_buffer[index] = clip_1(block_context.frame_context.color_config.bit_depth, current_buffer[index] + dequantized_value); | 1289 | 111M | } | 1290 | 27.8M | } | 1291 | | | 1292 | 6.98M | return {}; | 1293 | 6.98M | } |
AK::ErrorOr<void, Media::DecoderError> Media::Video::VP9::Decoder::reconstruct_templated<(unsigned char)3>(unsigned char, Media::Video::VP9::BlockContext const&, unsigned int, unsigned int, Media::Video::VP9::TransformSet) Line | Count | Source | 1247 | 1.01M | { | 1248 | | // 8.6.2 Reconstruct process, continued: | 1249 | | | 1250 | | // The variable dqDenom is set equal to 2 if txSz is equal to Transform_32X32, otherwise dqDenom is set equal to 1. | 1251 | 1.01M | constexpr Intermediate dq_denominator = log2_of_block_size == 5 ? 2 : 1; | 1252 | | // The variable n0 (specifying the width of the transform block) is set equal to 1 << n. | 1253 | 1.01M | constexpr auto block_size = 1u << log2_of_block_size; | 1254 | | | 1255 | | // 1. Dequant[ i ][ j ] is set equal to ( Tokens[ i * n0 + j ] * get_ac_quant( plane ) ) / dqDenom | 1256 | | // for i = 0..(n0-1), for j = 0..(n0-1) | 1257 | 1.01M | Array<Intermediate, block_size * block_size> dequantized; | 1258 | 1.01M | auto quantizers = block_context.frame_context.segment_quantizers[block_context.segment_id]; | 1259 | 1.01M | Intermediate ac_quant = plane == 0 ? quantizers.y_ac_quantizer : quantizers.uv_ac_quantizer; | 1260 | 1.01M | auto const* tokens_raw = block_context.residual_tokens.data(); | 1261 | 66.1M | for (u32 i = 0; i < dequantized.size(); i++) { | 1262 | 65.1M | dequantized[i] = (tokens_raw[i] * ac_quant) / dq_denominator; | 1263 | 65.1M | } | 1264 | | | 1265 | | // 2. Dequant[ 0 ][ 0 ] is set equal to ( Tokens[ 0 ] * get_dc_quant( plane ) ) / dqDenom | 1266 | 1.01M | dequantized[0] = (block_context.residual_tokens[0] * (plane == 0 ? quantizers.y_dc_quantizer : quantizers.uv_dc_quantizer)) / dq_denominator; | 1267 | | | 1268 | | // It is a requirement of bitstream conformance that the values written into the Dequant array in steps 1 and 2 | 1269 | | // are representable by a signed integer with 8 + BitDepth bits. | 1270 | | // Note: Since bounds checks just ensure that we will not have resulting values that will overflow, it's non-fatal | 1271 | | // to allow these bounds to be violated. Therefore, we can avoid the performance cost here. | 1272 | | | 1273 | | // 3. Invoke the 2D inverse transform block process defined in section 8.7.2 with the variable n as input. | 1274 | | // The inverse transform outputs are stored back to the Dequant buffer. | 1275 | 1.01M | TRY(inverse_transform_2d<log2_of_block_size>(block_context, dequantized, transform_set)); | 1276 | | | 1277 | | // 4. CurrFrame[ plane ][ y + i ][ x + j ] is set equal to Clip1( CurrFrame[ plane ][ y + i ][ x + j ] + Dequant[ i ][ j ] ) | 1278 | | // for i = 0..(n0-1) and j = 0..(n0-1). | 1279 | 1.01M | auto& current_buffer = get_output_buffer(plane); | 1280 | 1.01M | auto frame_size = block_context.frame_context.decoded_size(plane > 0); | 1281 | 1.01M | auto width_in_frame_buffer = min(block_size, frame_size.width() - transform_block_x); | 1282 | 1.01M | auto height_in_frame_buffer = min(block_size, frame_size.height() - transform_block_y); | 1283 | | | 1284 | 9.15M | for (auto i = 0u; i < height_in_frame_buffer; i++) { | 1285 | 70.8M | for (auto j = 0u; j < width_in_frame_buffer; j++) { | 1286 | 62.7M | auto index = (transform_block_y + i) * frame_size.width() + transform_block_x + j; | 1287 | 62.7M | auto dequantized_value = dequantized[i * block_size + j]; | 1288 | 62.7M | current_buffer[index] = clip_1(block_context.frame_context.color_config.bit_depth, current_buffer[index] + dequantized_value); | 1289 | 62.7M | } | 1290 | 8.13M | } | 1291 | | | 1292 | 1.01M | return {}; | 1293 | 1.01M | } |
AK::ErrorOr<void, Media::DecoderError> Media::Video::VP9::Decoder::reconstruct_templated<(unsigned char)4>(unsigned char, Media::Video::VP9::BlockContext const&, unsigned int, unsigned int, Media::Video::VP9::TransformSet) Line | Count | Source | 1247 | 170k | { | 1248 | | // 8.6.2 Reconstruct process, continued: | 1249 | | | 1250 | | // The variable dqDenom is set equal to 2 if txSz is equal to Transform_32X32, otherwise dqDenom is set equal to 1. | 1251 | 170k | constexpr Intermediate dq_denominator = log2_of_block_size == 5 ? 2 : 1; | 1252 | | // The variable n0 (specifying the width of the transform block) is set equal to 1 << n. | 1253 | 170k | constexpr auto block_size = 1u << log2_of_block_size; | 1254 | | | 1255 | | // 1. Dequant[ i ][ j ] is set equal to ( Tokens[ i * n0 + j ] * get_ac_quant( plane ) ) / dqDenom | 1256 | | // for i = 0..(n0-1), for j = 0..(n0-1) | 1257 | 170k | Array<Intermediate, block_size * block_size> dequantized; | 1258 | 170k | auto quantizers = block_context.frame_context.segment_quantizers[block_context.segment_id]; | 1259 | 170k | Intermediate ac_quant = plane == 0 ? quantizers.y_ac_quantizer : quantizers.uv_ac_quantizer; | 1260 | 170k | auto const* tokens_raw = block_context.residual_tokens.data(); | 1261 | 43.7M | for (u32 i = 0; i < dequantized.size(); i++) { | 1262 | 43.6M | dequantized[i] = (tokens_raw[i] * ac_quant) / dq_denominator; | 1263 | 43.6M | } | 1264 | | | 1265 | | // 2. Dequant[ 0 ][ 0 ] is set equal to ( Tokens[ 0 ] * get_dc_quant( plane ) ) / dqDenom | 1266 | 170k | dequantized[0] = (block_context.residual_tokens[0] * (plane == 0 ? quantizers.y_dc_quantizer : quantizers.uv_dc_quantizer)) / dq_denominator; | 1267 | | | 1268 | | // It is a requirement of bitstream conformance that the values written into the Dequant array in steps 1 and 2 | 1269 | | // are representable by a signed integer with 8 + BitDepth bits. | 1270 | | // Note: Since bounds checks just ensure that we will not have resulting values that will overflow, it's non-fatal | 1271 | | // to allow these bounds to be violated. Therefore, we can avoid the performance cost here. | 1272 | | | 1273 | | // 3. Invoke the 2D inverse transform block process defined in section 8.7.2 with the variable n as input. | 1274 | | // The inverse transform outputs are stored back to the Dequant buffer. | 1275 | 170k | TRY(inverse_transform_2d<log2_of_block_size>(block_context, dequantized, transform_set)); | 1276 | | | 1277 | | // 4. CurrFrame[ plane ][ y + i ][ x + j ] is set equal to Clip1( CurrFrame[ plane ][ y + i ][ x + j ] + Dequant[ i ][ j ] ) | 1278 | | // for i = 0..(n0-1) and j = 0..(n0-1). | 1279 | 170k | auto& current_buffer = get_output_buffer(plane); | 1280 | 170k | auto frame_size = block_context.frame_context.decoded_size(plane > 0); | 1281 | 170k | auto width_in_frame_buffer = min(block_size, frame_size.width() - transform_block_x); | 1282 | 170k | auto height_in_frame_buffer = min(block_size, frame_size.height() - transform_block_y); | 1283 | | | 1284 | 2.89M | for (auto i = 0u; i < height_in_frame_buffer; i++) { | 1285 | 37.8M | for (auto j = 0u; j < width_in_frame_buffer; j++) { | 1286 | 35.1M | auto index = (transform_block_y + i) * frame_size.width() + transform_block_x + j; | 1287 | 35.1M | auto dequantized_value = dequantized[i * block_size + j]; | 1288 | 35.1M | current_buffer[index] = clip_1(block_context.frame_context.color_config.bit_depth, current_buffer[index] + dequantized_value); | 1289 | 35.1M | } | 1290 | 2.72M | } | 1291 | | | 1292 | 170k | return {}; | 1293 | 170k | } |
AK::ErrorOr<void, Media::DecoderError> Media::Video::VP9::Decoder::reconstruct_templated<(unsigned char)5>(unsigned char, Media::Video::VP9::BlockContext const&, unsigned int, unsigned int, Media::Video::VP9::TransformSet) Line | Count | Source | 1247 | 382k | { | 1248 | | // 8.6.2 Reconstruct process, continued: | 1249 | | | 1250 | | // The variable dqDenom is set equal to 2 if txSz is equal to Transform_32X32, otherwise dqDenom is set equal to 1. | 1251 | 382k | constexpr Intermediate dq_denominator = log2_of_block_size == 5 ? 2 : 1; | 1252 | | // The variable n0 (specifying the width of the transform block) is set equal to 1 << n. | 1253 | 382k | constexpr auto block_size = 1u << log2_of_block_size; | 1254 | | | 1255 | | // 1. Dequant[ i ][ j ] is set equal to ( Tokens[ i * n0 + j ] * get_ac_quant( plane ) ) / dqDenom | 1256 | | // for i = 0..(n0-1), for j = 0..(n0-1) | 1257 | 382k | Array<Intermediate, block_size * block_size> dequantized; | 1258 | 382k | auto quantizers = block_context.frame_context.segment_quantizers[block_context.segment_id]; | 1259 | 382k | Intermediate ac_quant = plane == 0 ? quantizers.y_ac_quantizer : quantizers.uv_ac_quantizer; | 1260 | 382k | auto const* tokens_raw = block_context.residual_tokens.data(); | 1261 | 391M | for (u32 i = 0; i < dequantized.size(); i++) { | 1262 | 391M | dequantized[i] = (tokens_raw[i] * ac_quant) / dq_denominator; | 1263 | 391M | } | 1264 | | | 1265 | | // 2. Dequant[ 0 ][ 0 ] is set equal to ( Tokens[ 0 ] * get_dc_quant( plane ) ) / dqDenom | 1266 | 382k | dequantized[0] = (block_context.residual_tokens[0] * (plane == 0 ? quantizers.y_dc_quantizer : quantizers.uv_dc_quantizer)) / dq_denominator; | 1267 | | | 1268 | | // It is a requirement of bitstream conformance that the values written into the Dequant array in steps 1 and 2 | 1269 | | // are representable by a signed integer with 8 + BitDepth bits. | 1270 | | // Note: Since bounds checks just ensure that we will not have resulting values that will overflow, it's non-fatal | 1271 | | // to allow these bounds to be violated. Therefore, we can avoid the performance cost here. | 1272 | | | 1273 | | // 3. Invoke the 2D inverse transform block process defined in section 8.7.2 with the variable n as input. | 1274 | | // The inverse transform outputs are stored back to the Dequant buffer. | 1275 | 382k | TRY(inverse_transform_2d<log2_of_block_size>(block_context, dequantized, transform_set)); | 1276 | | | 1277 | | // 4. CurrFrame[ plane ][ y + i ][ x + j ] is set equal to Clip1( CurrFrame[ plane ][ y + i ][ x + j ] + Dequant[ i ][ j ] ) | 1278 | | // for i = 0..(n0-1) and j = 0..(n0-1). | 1279 | 382k | auto& current_buffer = get_output_buffer(plane); | 1280 | 382k | auto frame_size = block_context.frame_context.decoded_size(plane > 0); | 1281 | 382k | auto width_in_frame_buffer = min(block_size, frame_size.width() - transform_block_x); | 1282 | 382k | auto height_in_frame_buffer = min(block_size, frame_size.height() - transform_block_y); | 1283 | | | 1284 | 12.5M | for (auto i = 0u; i < height_in_frame_buffer; i++) { | 1285 | 387M | for (auto j = 0u; j < width_in_frame_buffer; j++) { | 1286 | 375M | auto index = (transform_block_y + i) * frame_size.width() + transform_block_x + j; | 1287 | 375M | auto dequantized_value = dequantized[i * block_size + j]; | 1288 | 375M | current_buffer[index] = clip_1(block_context.frame_context.color_config.bit_depth, current_buffer[index] + dequantized_value); | 1289 | 375M | } | 1290 | 12.1M | } | 1291 | | | 1292 | 382k | return {}; | 1293 | 382k | } |
|
1294 | | |
1295 | | inline DecoderErrorOr<void> Decoder::inverse_walsh_hadamard_transform(Span<Intermediate> data, u8 log2_of_block_size, u8 shift) |
1296 | 7.24M | { |
1297 | | // The input to this process is a variable shift that specifies the amount of pre-scaling. |
1298 | | // This process does an in-place transform of the array T (of length 4) by the following ordered steps: |
1299 | 7.24M | if (1 << log2_of_block_size != 4) |
1300 | 0 | return DecoderError::corrupted("Block size was not 4"sv); |
1301 | | |
1302 | 7.24M | auto a = data[0] >> shift; |
1303 | 7.24M | auto c = data[1] >> shift; |
1304 | 7.24M | auto d = data[2] >> shift; |
1305 | 7.24M | auto b = data[3] >> shift; |
1306 | 7.24M | a += c; |
1307 | 7.24M | d -= b; |
1308 | 7.24M | auto average_of_a_and_d = (a - d) >> 1; |
1309 | 7.24M | b = average_of_a_and_d - b; |
1310 | 7.24M | c = average_of_a_and_d - c; |
1311 | 7.24M | a -= b; |
1312 | 7.24M | d += c; |
1313 | 7.24M | data[0] = a; |
1314 | 7.24M | data[1] = b; |
1315 | 7.24M | data[2] = c; |
1316 | 7.24M | data[3] = d; |
1317 | 7.24M | return {}; |
1318 | 7.24M | } |
1319 | | |
1320 | | inline i32 Decoder::cos64(u8 angle) |
1321 | 2.02G | { |
1322 | 2.02G | i32 const cos64_lookup[33] = { 16384, 16364, 16305, 16207, 16069, 15893, 15679, 15426, 15137, 14811, 14449, 14053, 13623, 13160, 12665, 12140, 11585, 11003, 10394, 9760, 9102, 8423, 7723, 7005, 6270, 5520, 4756, 3981, 3196, 2404, 1606, 804, 0 }; |
1323 | | |
1324 | | // 1. Set a variable angle2 equal to angle & 127. |
1325 | 2.02G | angle &= 127; |
1326 | | // 2. If angle2 is greater than or equal to 0 and less than or equal to 32, return cos64_lookup[ angle2 ]. |
1327 | 2.02G | if (angle <= 32) |
1328 | 900M | return cos64_lookup[angle]; |
1329 | | // 3. If angle2 is greater than 32 and less than or equal to 64, return cos64_lookup[ 64 - angle2 ] * -1. |
1330 | 1.12G | if (angle <= 64) |
1331 | 127M | return -cos64_lookup[64 - angle]; |
1332 | | // 4. If angle2 is greater than 64 and less than or equal to 96, return cos64_lookup[ angle2 - 64 ] * -1. |
1333 | 1.00G | if (angle <= 96) |
1334 | 128M | return -cos64_lookup[angle - 64]; |
1335 | | // 5. Otherwise (if angle2 is greater than 96 and less than 128), return cos64_lookup[ 128 - angle2 ]. |
1336 | 871M | return cos64_lookup[128 - angle]; |
1337 | 1.00G | } |
1338 | | |
1339 | | inline i32 Decoder::sin64(u8 angle) |
1340 | 1.02G | { |
1341 | 1.02G | if (angle < 32) |
1342 | 898M | angle += 128; |
1343 | 1.02G | return cos64(angle - 32u); |
1344 | 1.02G | } |
1345 | | |
1346 | | // (8.7.1.1) The function B( a, b, angle, 0 ) performs a butterfly rotation. |
1347 | | inline void Decoder::butterfly_rotation_in_place(Span<Intermediate> data, size_t index_a, size_t index_b, u8 angle, bool flip) |
1348 | 1.00G | { |
1349 | 1.00G | auto cos = cos64(angle); |
1350 | 1.00G | auto sin = sin64(angle); |
1351 | | // 1. The variable x is set equal to T[ a ] * cos64( angle ) - T[ b ] * sin64( angle ). |
1352 | 1.00G | i64 rotated_a = static_cast<i64>(data[index_a]) * cos - static_cast<i64>(data[index_b]) * sin; |
1353 | | // 2. The variable y is set equal to T[ a ] * sin64( angle ) + T[ b ] * cos64( angle ). |
1354 | 1.00G | i64 rotated_b = static_cast<i64>(data[index_a]) * sin + static_cast<i64>(data[index_b]) * cos; |
1355 | | // 3. T[ a ] is set equal to Round2( x, 14 ). |
1356 | 1.00G | data[index_a] = rounded_right_shift(rotated_a, 14); |
1357 | | // 4. T[ b ] is set equal to Round2( y, 14 ). |
1358 | 1.00G | data[index_b] = rounded_right_shift(rotated_b, 14); |
1359 | | |
1360 | | // The function B( a ,b, angle, 1 ) performs a butterfly rotation and flip specified by the following ordered steps: |
1361 | | // 1. The function B( a, b, angle, 0 ) is invoked. |
1362 | | // 2. The contents of T[ a ] and T[ b ] are exchanged. |
1363 | 1.00G | if (flip) |
1364 | 534M | swap(data[index_a], data[index_b]); |
1365 | | |
1366 | | // It is a requirement of bitstream conformance that the values saved into the array T by this function are |
1367 | | // representable by a signed integer using 8 + BitDepth bits of precision. |
1368 | | // Note: Since bounds checks just ensure that we will not have resulting values that will overflow, it's non-fatal |
1369 | | // to allow these bounds to be violated. Therefore, we can avoid the performance cost here. |
1370 | 1.00G | } |
1371 | | |
1372 | | // (8.7.1.1) The function H( a, b, 0 ) performs a Hadamard rotation. |
1373 | | inline void Decoder::hadamard_rotation_in_place(Span<Intermediate> data, size_t index_a, size_t index_b, bool flip) |
1374 | 1.86G | { |
1375 | | // The function H( a, b, 1 ) performs a Hadamard rotation with flipped indices and is specified as follows: |
1376 | | // 1. The function H( b, a, 0 ) is invoked. |
1377 | 1.86G | if (flip) |
1378 | 447M | swap(index_a, index_b); |
1379 | | |
1380 | | // The function H( a, b, 0 ) performs a Hadamard rotation specified by the following ordered steps: |
1381 | | |
1382 | | // 1. The variable x is set equal to T[ a ]. |
1383 | 1.86G | auto a_value = data[index_a]; |
1384 | | // 2. The variable y is set equal to T[ b ]. |
1385 | 1.86G | auto b_value = data[index_b]; |
1386 | | // 3. T[ a ] is set equal to x + y. |
1387 | 1.86G | data[index_a] = a_value + b_value; |
1388 | | // 4. T[ b ] is set equal to x - y. |
1389 | 1.86G | data[index_b] = a_value - b_value; |
1390 | | |
1391 | | // It is a requirement of bitstream conformance that the values saved into the array T by this function are |
1392 | | // representable by a signed integer using 8 + BitDepth bits of precision. |
1393 | | // Note: Since bounds checks just ensure that we will not have resulting values that will overflow, it's non-fatal |
1394 | | // to allow these bounds to be violated. Therefore, we can avoid the performance cost here. |
1395 | 1.86G | } |
1396 | | |
1397 | | template<u8 log2_of_block_size> |
1398 | | inline DecoderErrorOr<void> Decoder::inverse_discrete_cosine_transform_array_permutation(Span<Intermediate> data) |
1399 | 90.5M | { |
1400 | 90.5M | static_assert(log2_of_block_size >= 2 && log2_of_block_size <= 5, "Block size out of range."); |
1401 | | |
1402 | 90.5M | constexpr u8 block_size = 1 << log2_of_block_size; |
1403 | | |
1404 | | // This process performs an in-place permutation of the array T of length 2^n for 2 ≤ n ≤ 5 which is required before |
1405 | | // execution of the inverse DCT process. |
1406 | 90.5M | if (log2_of_block_size < 2 || log2_of_block_size > 5) |
1407 | 0 | return DecoderError::corrupted("Block size was out of range"sv); |
1408 | | |
1409 | | // 1.1. A temporary array named copyT is set equal to T. |
1410 | 90.5M | Array<Intermediate, block_size> data_copy; |
1411 | 90.5M | AK::TypedTransfer<Intermediate>::copy(data_copy.data(), data.data(), block_size); |
1412 | | |
1413 | | // 1.2. T[ i ] is set equal to copyT[ brev( n, i ) ] for i = 0..((1<<n) - 1). |
1414 | 1.24G | for (auto i = 0u; i < block_size; i++) |
1415 | 1.15G | data[i] = data_copy[brev<log2_of_block_size>(i)]; |
1416 | | |
1417 | 90.5M | return {}; |
1418 | 90.5M | } AK::ErrorOr<void, Media::DecoderError> Media::Video::VP9::Decoder::inverse_discrete_cosine_transform_array_permutation<(unsigned char)2>(AK::Span<int>) Line | Count | Source | 1399 | 46.3M | { | 1400 | 46.3M | static_assert(log2_of_block_size >= 2 && log2_of_block_size <= 5, "Block size out of range."); | 1401 | | | 1402 | 46.3M | constexpr u8 block_size = 1 << log2_of_block_size; | 1403 | | | 1404 | | // This process performs an in-place permutation of the array T of length 2^n for 2 ≤ n ≤ 5 which is required before | 1405 | | // execution of the inverse DCT process. | 1406 | 46.3M | if (log2_of_block_size < 2 || log2_of_block_size > 5) | 1407 | 0 | return DecoderError::corrupted("Block size was out of range"sv); | 1408 | | | 1409 | | // 1.1. A temporary array named copyT is set equal to T. | 1410 | 46.3M | Array<Intermediate, block_size> data_copy; | 1411 | 46.3M | AK::TypedTransfer<Intermediate>::copy(data_copy.data(), data.data(), block_size); | 1412 | | | 1413 | | // 1.2. T[ i ] is set equal to copyT[ brev( n, i ) ] for i = 0..((1<<n) - 1). | 1414 | 231M | for (auto i = 0u; i < block_size; i++) | 1415 | 184M | data[i] = data_copy[brev<log2_of_block_size>(i)]; | 1416 | | | 1417 | 46.3M | return {}; | 1418 | 46.3M | } |
AK::ErrorOr<void, Media::DecoderError> Media::Video::VP9::Decoder::inverse_discrete_cosine_transform_array_permutation<(unsigned char)3>(AK::Span<int>) Line | Count | Source | 1399 | 14.9M | { | 1400 | 14.9M | static_assert(log2_of_block_size >= 2 && log2_of_block_size <= 5, "Block size out of range."); | 1401 | | | 1402 | 14.9M | constexpr u8 block_size = 1 << log2_of_block_size; | 1403 | | | 1404 | | // This process performs an in-place permutation of the array T of length 2^n for 2 ≤ n ≤ 5 which is required before | 1405 | | // execution of the inverse DCT process. | 1406 | 14.9M | if (log2_of_block_size < 2 || log2_of_block_size > 5) | 1407 | 0 | return DecoderError::corrupted("Block size was out of range"sv); | 1408 | | | 1409 | | // 1.1. A temporary array named copyT is set equal to T. | 1410 | 14.9M | Array<Intermediate, block_size> data_copy; | 1411 | 14.9M | AK::TypedTransfer<Intermediate>::copy(data_copy.data(), data.data(), block_size); | 1412 | | | 1413 | | // 1.2. T[ i ] is set equal to copyT[ brev( n, i ) ] for i = 0..((1<<n) - 1). | 1414 | 134M | for (auto i = 0u; i < block_size; i++) | 1415 | 119M | data[i] = data_copy[brev<log2_of_block_size>(i)]; | 1416 | | | 1417 | 14.9M | return {}; | 1418 | 14.9M | } |
AK::ErrorOr<void, Media::DecoderError> Media::Video::VP9::Decoder::inverse_discrete_cosine_transform_array_permutation<(unsigned char)4>(AK::Span<int>) Line | Count | Source | 1399 | 4.82M | { | 1400 | 4.82M | static_assert(log2_of_block_size >= 2 && log2_of_block_size <= 5, "Block size out of range."); | 1401 | | | 1402 | 4.82M | constexpr u8 block_size = 1 << log2_of_block_size; | 1403 | | | 1404 | | // This process performs an in-place permutation of the array T of length 2^n for 2 ≤ n ≤ 5 which is required before | 1405 | | // execution of the inverse DCT process. | 1406 | 4.82M | if (log2_of_block_size < 2 || log2_of_block_size > 5) | 1407 | 0 | return DecoderError::corrupted("Block size was out of range"sv); | 1408 | | | 1409 | | // 1.1. A temporary array named copyT is set equal to T. | 1410 | 4.82M | Array<Intermediate, block_size> data_copy; | 1411 | 4.82M | AK::TypedTransfer<Intermediate>::copy(data_copy.data(), data.data(), block_size); | 1412 | | | 1413 | | // 1.2. T[ i ] is set equal to copyT[ brev( n, i ) ] for i = 0..((1<<n) - 1). | 1414 | 81.9M | for (auto i = 0u; i < block_size; i++) | 1415 | 77.1M | data[i] = data_copy[brev<log2_of_block_size>(i)]; | 1416 | | | 1417 | 4.82M | return {}; | 1418 | 4.82M | } |
AK::ErrorOr<void, Media::DecoderError> Media::Video::VP9::Decoder::inverse_discrete_cosine_transform_array_permutation<(unsigned char)5>(AK::Span<int>) Line | Count | Source | 1399 | 24.3M | { | 1400 | 24.3M | static_assert(log2_of_block_size >= 2 && log2_of_block_size <= 5, "Block size out of range."); | 1401 | | | 1402 | 24.3M | constexpr u8 block_size = 1 << log2_of_block_size; | 1403 | | | 1404 | | // This process performs an in-place permutation of the array T of length 2^n for 2 ≤ n ≤ 5 which is required before | 1405 | | // execution of the inverse DCT process. | 1406 | 24.3M | if (log2_of_block_size < 2 || log2_of_block_size > 5) | 1407 | 0 | return DecoderError::corrupted("Block size was out of range"sv); | 1408 | | | 1409 | | // 1.1. A temporary array named copyT is set equal to T. | 1410 | 24.3M | Array<Intermediate, block_size> data_copy; | 1411 | 24.3M | AK::TypedTransfer<Intermediate>::copy(data_copy.data(), data.data(), block_size); | 1412 | | | 1413 | | // 1.2. T[ i ] is set equal to copyT[ brev( n, i ) ] for i = 0..((1<<n) - 1). | 1414 | 799M | for (auto i = 0u; i < block_size; i++) | 1415 | 774M | data[i] = data_copy[brev<log2_of_block_size>(i)]; | 1416 | | | 1417 | 24.3M | return {}; | 1418 | 24.3M | } |
|
1419 | | |
1420 | | template<u8 log2_of_block_size> |
1421 | | ALWAYS_INLINE DecoderErrorOr<void> Decoder::inverse_discrete_cosine_transform(Span<Intermediate> data) |
1422 | 188M | { |
1423 | 188M | static_assert(log2_of_block_size >= 2 && log2_of_block_size <= 5, "Block size out of range."); |
1424 | | |
1425 | | // 2.1. The variable n0 is set equal to 1<<n. |
1426 | 188M | constexpr u8 block_size = 1 << log2_of_block_size; |
1427 | | |
1428 | | // 8.7.1.3 Inverse DCT process |
1429 | | |
1430 | | // 2.2. The variable n1 is set equal to 1<<(n-1). |
1431 | 188M | constexpr u8 half_block_size = block_size >> 1; |
1432 | | // 2.3 The variable n2 is set equal to 1<<(n-2). |
1433 | 188M | constexpr u8 quarter_block_size = half_block_size >> 1; |
1434 | | // 2.4 The variable n3 is set equal to 1<<(n-3). |
1435 | 188M | constexpr u8 eighth_block_size = quarter_block_size >> 1; |
1436 | | |
1437 | | // 2.5 If n is equal to 2, invoke B( 0, 1, 16, 1 ), otherwise recursively invoke the inverse DCT defined in this |
1438 | | // section with the variable n set equal to n - 1. |
1439 | | if constexpr (log2_of_block_size == 2) |
1440 | 90.5M | butterfly_rotation_in_place(data, 0, 1, 16, true); |
1441 | | else |
1442 | 97.9M | TRY(inverse_discrete_cosine_transform<log2_of_block_size - 1>(data)); |
1443 | | |
1444 | | // 2.6 Invoke B( n1+i, n0-1-i, 32-brev( 5, n1+i), 0 ) for i = 0..(n2-1). |
1445 | 677M | for (auto i = 0u; i < quarter_block_size; i++) { |
1446 | 488M | auto index = half_block_size + i; |
1447 | 488M | butterfly_rotation_in_place(data, index, block_size - 1 - i, 32 - brev<5>(index), false); |
1448 | 488M | } |
1449 | | |
1450 | | // 2.7 If n is greater than or equal to 3: |
1451 | 188M | if constexpr (log2_of_block_size >= 3) { |
1452 | | // a. Invoke H( n1+4*i+2*j, n1+1+4*i+2*j, j ) for i = 0..(n3-1), j = 0..1. |
1453 | 297M | for (auto i = 0u; i < eighth_block_size; i++) { |
1454 | 599M | for (auto j = 0u; j < 2; j++) { |
1455 | 399M | auto index = half_block_size + (4 * i) + (2 * j); |
1456 | 399M | hadamard_rotation_in_place(data, index, index + 1, j); |
1457 | 399M | } |
1458 | 200M | } |
1459 | 97.9M | } |
1460 | | |
1461 | | // 4. If n is equal to 5: |
1462 | 188M | if constexpr (log2_of_block_size == 5) { |
1463 | | // a. Invoke B( n0-n+3-n2*j-4*i, n1+n-4+n2*j+4*i, 28-16*i+56*j, 1 ) for i = 0..1, j = 0..1. |
1464 | 73.1M | for (auto i = 0u; i < 2; i++) { |
1465 | 145M | for (auto j = 0u; j < 2; j++) { |
1466 | 97.0M | auto index_a = block_size - log2_of_block_size + 3 - (quarter_block_size * j) - (4 * i); |
1467 | 97.0M | auto index_b = half_block_size + log2_of_block_size - 4 + (quarter_block_size * j) + (4 * i); |
1468 | 97.0M | auto angle = 28 - (16 * i) + (56 * j); |
1469 | 97.0M | butterfly_rotation_in_place(data, index_a, index_b, angle, true); |
1470 | 97.0M | } |
1471 | 48.6M | } |
1472 | | |
1473 | | // b. Invoke H( n1+n3*j+i, n1+n2-5+n3*j-i, j&1 ) for i = 0..1, j = 0..3. |
1474 | 73.2M | for (auto i = 0u; i < 2; i++) { |
1475 | 243M | for (auto j = 0u; j < 4; j++) { |
1476 | 195M | auto index_a = half_block_size + (eighth_block_size * j) + i; |
1477 | 195M | auto index_b = half_block_size + quarter_block_size - 5 + (eighth_block_size * j) - i; |
1478 | 195M | hadamard_rotation_in_place(data, index_a, index_b, (j & 1) != 0); |
1479 | 195M | } |
1480 | 48.7M | } |
1481 | 24.4M | } |
1482 | | |
1483 | | // 5. If n is greater than or equal to 4: |
1484 | 188M | if constexpr (log2_of_block_size >= 4) { |
1485 | | // a. Invoke B( n0-n+2-i-n2*j, n1+n-3+i+n2*j, 24+48*j, 1 ) for i = 0..(n==5), j = 0..1. |
1486 | 131M | for (auto i = 0u; i <= (log2_of_block_size == 5); i++) { |
1487 | 233M | for (auto j = 0u; j < 2; j++) { |
1488 | 155M | auto index_a = block_size - log2_of_block_size + 2 - i - (quarter_block_size * j); |
1489 | 155M | auto index_b = half_block_size + log2_of_block_size - 3 + i + (quarter_block_size * j); |
1490 | 155M | butterfly_rotation_in_place(data, index_a, index_b, 24 + (48 * j), true); |
1491 | 155M | } |
1492 | 77.9M | } |
1493 | | |
1494 | | // b. Invoke H( n1+n2*j+i, n1+n2-1+n2*j-i, j&1 ) for i = 0..(2n-7), j = 0..1. |
1495 | 209M | for (auto i = 0u; i < (2 * log2_of_block_size) - 6u; i++) { |
1496 | 467M | for (auto j = 0u; j < 2; j++) { |
1497 | 311M | auto index_a = half_block_size + (quarter_block_size * j) + i; |
1498 | 311M | auto index_b = half_block_size + quarter_block_size - 1 + (quarter_block_size * j) - i; |
1499 | 311M | hadamard_rotation_in_place(data, index_a, index_b, (j & 1) != 0); |
1500 | 311M | } |
1501 | 155M | } |
1502 | 53.6M | } |
1503 | | |
1504 | | // 6. If n is greater than or equal to 3: |
1505 | 188M | if constexpr (log2_of_block_size >= 3) { |
1506 | | // a. Invoke B( n0-n3-1-i, n1+n3+i, 16, 1 ) for i = 0..(n3-1). |
1507 | 297M | for (auto i = 0u; i < eighth_block_size; i++) { |
1508 | 199M | auto index_a = block_size - eighth_block_size - 1 - i; |
1509 | 199M | auto index_b = half_block_size + eighth_block_size + i; |
1510 | 199M | butterfly_rotation_in_place(data, index_a, index_b, 16, true); |
1511 | 199M | } |
1512 | 97.9M | } |
1513 | | |
1514 | | // 7. Invoke H( i, n0-1-i, 0 ) for i = 0..(n1-1). |
1515 | 1.17G | for (auto i = 0u; i < half_block_size; i++) |
1516 | 984M | hadamard_rotation_in_place(data, i, block_size - 1 - i, false); |
1517 | | |
1518 | 188M | return {}; |
1519 | 188M | } AK::ErrorOr<void, Media::DecoderError> Media::Video::VP9::Decoder::inverse_discrete_cosine_transform<(unsigned char)2>(AK::Span<int>) Line | Count | Source | 1422 | 90.5M | { | 1423 | 90.5M | static_assert(log2_of_block_size >= 2 && log2_of_block_size <= 5, "Block size out of range."); | 1424 | | | 1425 | | // 2.1. The variable n0 is set equal to 1<<n. | 1426 | 90.5M | constexpr u8 block_size = 1 << log2_of_block_size; | 1427 | | | 1428 | | // 8.7.1.3 Inverse DCT process | 1429 | | | 1430 | | // 2.2. The variable n1 is set equal to 1<<(n-1). | 1431 | 90.5M | constexpr u8 half_block_size = block_size >> 1; | 1432 | | // 2.3 The variable n2 is set equal to 1<<(n-2). | 1433 | 90.5M | constexpr u8 quarter_block_size = half_block_size >> 1; | 1434 | | // 2.4 The variable n3 is set equal to 1<<(n-3). | 1435 | 90.5M | constexpr u8 eighth_block_size = quarter_block_size >> 1; | 1436 | | | 1437 | | // 2.5 If n is equal to 2, invoke B( 0, 1, 16, 1 ), otherwise recursively invoke the inverse DCT defined in this | 1438 | | // section with the variable n set equal to n - 1. | 1439 | | if constexpr (log2_of_block_size == 2) | 1440 | 90.5M | butterfly_rotation_in_place(data, 0, 1, 16, true); | 1441 | | else | 1442 | | TRY(inverse_discrete_cosine_transform<log2_of_block_size - 1>(data)); | 1443 | | | 1444 | | // 2.6 Invoke B( n1+i, n0-1-i, 32-brev( 5, n1+i), 0 ) for i = 0..(n2-1). | 1445 | 181M | for (auto i = 0u; i < quarter_block_size; i++) { | 1446 | 90.4M | auto index = half_block_size + i; | 1447 | 90.4M | butterfly_rotation_in_place(data, index, block_size - 1 - i, 32 - brev<5>(index), false); | 1448 | 90.4M | } | 1449 | | | 1450 | | // 2.7 If n is greater than or equal to 3: | 1451 | | if constexpr (log2_of_block_size >= 3) { | 1452 | | // a. Invoke H( n1+4*i+2*j, n1+1+4*i+2*j, j ) for i = 0..(n3-1), j = 0..1. | 1453 | | for (auto i = 0u; i < eighth_block_size; i++) { | 1454 | | for (auto j = 0u; j < 2; j++) { | 1455 | | auto index = half_block_size + (4 * i) + (2 * j); | 1456 | | hadamard_rotation_in_place(data, index, index + 1, j); | 1457 | | } | 1458 | | } | 1459 | | } | 1460 | | | 1461 | | // 4. If n is equal to 5: | 1462 | | if constexpr (log2_of_block_size == 5) { | 1463 | | // a. Invoke B( n0-n+3-n2*j-4*i, n1+n-4+n2*j+4*i, 28-16*i+56*j, 1 ) for i = 0..1, j = 0..1. | 1464 | | for (auto i = 0u; i < 2; i++) { | 1465 | | for (auto j = 0u; j < 2; j++) { | 1466 | | auto index_a = block_size - log2_of_block_size + 3 - (quarter_block_size * j) - (4 * i); | 1467 | | auto index_b = half_block_size + log2_of_block_size - 4 + (quarter_block_size * j) + (4 * i); | 1468 | | auto angle = 28 - (16 * i) + (56 * j); | 1469 | | butterfly_rotation_in_place(data, index_a, index_b, angle, true); | 1470 | | } | 1471 | | } | 1472 | | | 1473 | | // b. Invoke H( n1+n3*j+i, n1+n2-5+n3*j-i, j&1 ) for i = 0..1, j = 0..3. | 1474 | | for (auto i = 0u; i < 2; i++) { | 1475 | | for (auto j = 0u; j < 4; j++) { | 1476 | | auto index_a = half_block_size + (eighth_block_size * j) + i; | 1477 | | auto index_b = half_block_size + quarter_block_size - 5 + (eighth_block_size * j) - i; | 1478 | | hadamard_rotation_in_place(data, index_a, index_b, (j & 1) != 0); | 1479 | | } | 1480 | | } | 1481 | | } | 1482 | | | 1483 | | // 5. If n is greater than or equal to 4: | 1484 | | if constexpr (log2_of_block_size >= 4) { | 1485 | | // a. Invoke B( n0-n+2-i-n2*j, n1+n-3+i+n2*j, 24+48*j, 1 ) for i = 0..(n==5), j = 0..1. | 1486 | | for (auto i = 0u; i <= (log2_of_block_size == 5); i++) { | 1487 | | for (auto j = 0u; j < 2; j++) { | 1488 | | auto index_a = block_size - log2_of_block_size + 2 - i - (quarter_block_size * j); | 1489 | | auto index_b = half_block_size + log2_of_block_size - 3 + i + (quarter_block_size * j); | 1490 | | butterfly_rotation_in_place(data, index_a, index_b, 24 + (48 * j), true); | 1491 | | } | 1492 | | } | 1493 | | | 1494 | | // b. Invoke H( n1+n2*j+i, n1+n2-1+n2*j-i, j&1 ) for i = 0..(2n-7), j = 0..1. | 1495 | | for (auto i = 0u; i < (2 * log2_of_block_size) - 6u; i++) { | 1496 | | for (auto j = 0u; j < 2; j++) { | 1497 | | auto index_a = half_block_size + (quarter_block_size * j) + i; | 1498 | | auto index_b = half_block_size + quarter_block_size - 1 + (quarter_block_size * j) - i; | 1499 | | hadamard_rotation_in_place(data, index_a, index_b, (j & 1) != 0); | 1500 | | } | 1501 | | } | 1502 | | } | 1503 | | | 1504 | | // 6. If n is greater than or equal to 3: | 1505 | | if constexpr (log2_of_block_size >= 3) { | 1506 | | // a. Invoke B( n0-n3-1-i, n1+n3+i, 16, 1 ) for i = 0..(n3-1). | 1507 | | for (auto i = 0u; i < eighth_block_size; i++) { | 1508 | | auto index_a = block_size - eighth_block_size - 1 - i; | 1509 | | auto index_b = half_block_size + eighth_block_size + i; | 1510 | | butterfly_rotation_in_place(data, index_a, index_b, 16, true); | 1511 | | } | 1512 | | } | 1513 | | | 1514 | | // 7. Invoke H( i, n0-1-i, 0 ) for i = 0..(n1-1). | 1515 | 272M | for (auto i = 0u; i < half_block_size; i++) | 1516 | 181M | hadamard_rotation_in_place(data, i, block_size - 1 - i, false); | 1517 | | | 1518 | 90.5M | return {}; | 1519 | 90.5M | } |
AK::ErrorOr<void, Media::DecoderError> Media::Video::VP9::Decoder::inverse_discrete_cosine_transform<(unsigned char)3>(AK::Span<int>) Line | Count | Source | 1422 | 44.2M | { | 1423 | 44.2M | static_assert(log2_of_block_size >= 2 && log2_of_block_size <= 5, "Block size out of range."); | 1424 | | | 1425 | | // 2.1. The variable n0 is set equal to 1<<n. | 1426 | 44.2M | constexpr u8 block_size = 1 << log2_of_block_size; | 1427 | | | 1428 | | // 8.7.1.3 Inverse DCT process | 1429 | | | 1430 | | // 2.2. The variable n1 is set equal to 1<<(n-1). | 1431 | 44.2M | constexpr u8 half_block_size = block_size >> 1; | 1432 | | // 2.3 The variable n2 is set equal to 1<<(n-2). | 1433 | 44.2M | constexpr u8 quarter_block_size = half_block_size >> 1; | 1434 | | // 2.4 The variable n3 is set equal to 1<<(n-3). | 1435 | 44.2M | constexpr u8 eighth_block_size = quarter_block_size >> 1; | 1436 | | | 1437 | | // 2.5 If n is equal to 2, invoke B( 0, 1, 16, 1 ), otherwise recursively invoke the inverse DCT defined in this | 1438 | | // section with the variable n set equal to n - 1. | 1439 | | if constexpr (log2_of_block_size == 2) | 1440 | | butterfly_rotation_in_place(data, 0, 1, 16, true); | 1441 | | else | 1442 | 44.2M | TRY(inverse_discrete_cosine_transform<log2_of_block_size - 1>(data)); | 1443 | | | 1444 | | // 2.6 Invoke B( n1+i, n0-1-i, 32-brev( 5, n1+i), 0 ) for i = 0..(n2-1). | 1445 | 132M | for (auto i = 0u; i < quarter_block_size; i++) { | 1446 | 88.2M | auto index = half_block_size + i; | 1447 | 88.2M | butterfly_rotation_in_place(data, index, block_size - 1 - i, 32 - brev<5>(index), false); | 1448 | 88.2M | } | 1449 | | | 1450 | | // 2.7 If n is greater than or equal to 3: | 1451 | 44.2M | if constexpr (log2_of_block_size >= 3) { | 1452 | | // a. Invoke H( n1+4*i+2*j, n1+1+4*i+2*j, j ) for i = 0..(n3-1), j = 0..1. | 1453 | 88.4M | for (auto i = 0u; i < eighth_block_size; i++) { | 1454 | 132M | for (auto j = 0u; j < 2; j++) { | 1455 | 88.3M | auto index = half_block_size + (4 * i) + (2 * j); | 1456 | 88.3M | hadamard_rotation_in_place(data, index, index + 1, j); | 1457 | 88.3M | } | 1458 | 44.1M | } | 1459 | 44.2M | } | 1460 | | | 1461 | | // 4. If n is equal to 5: | 1462 | | if constexpr (log2_of_block_size == 5) { | 1463 | | // a. Invoke B( n0-n+3-n2*j-4*i, n1+n-4+n2*j+4*i, 28-16*i+56*j, 1 ) for i = 0..1, j = 0..1. | 1464 | | for (auto i = 0u; i < 2; i++) { | 1465 | | for (auto j = 0u; j < 2; j++) { | 1466 | | auto index_a = block_size - log2_of_block_size + 3 - (quarter_block_size * j) - (4 * i); | 1467 | | auto index_b = half_block_size + log2_of_block_size - 4 + (quarter_block_size * j) + (4 * i); | 1468 | | auto angle = 28 - (16 * i) + (56 * j); | 1469 | | butterfly_rotation_in_place(data, index_a, index_b, angle, true); | 1470 | | } | 1471 | | } | 1472 | | | 1473 | | // b. Invoke H( n1+n3*j+i, n1+n2-5+n3*j-i, j&1 ) for i = 0..1, j = 0..3. | 1474 | | for (auto i = 0u; i < 2; i++) { | 1475 | | for (auto j = 0u; j < 4; j++) { | 1476 | | auto index_a = half_block_size + (eighth_block_size * j) + i; | 1477 | | auto index_b = half_block_size + quarter_block_size - 5 + (eighth_block_size * j) - i; | 1478 | | hadamard_rotation_in_place(data, index_a, index_b, (j & 1) != 0); | 1479 | | } | 1480 | | } | 1481 | | } | 1482 | | | 1483 | | // 5. If n is greater than or equal to 4: | 1484 | | if constexpr (log2_of_block_size >= 4) { | 1485 | | // a. Invoke B( n0-n+2-i-n2*j, n1+n-3+i+n2*j, 24+48*j, 1 ) for i = 0..(n==5), j = 0..1. | 1486 | | for (auto i = 0u; i <= (log2_of_block_size == 5); i++) { | 1487 | | for (auto j = 0u; j < 2; j++) { | 1488 | | auto index_a = block_size - log2_of_block_size + 2 - i - (quarter_block_size * j); | 1489 | | auto index_b = half_block_size + log2_of_block_size - 3 + i + (quarter_block_size * j); | 1490 | | butterfly_rotation_in_place(data, index_a, index_b, 24 + (48 * j), true); | 1491 | | } | 1492 | | } | 1493 | | | 1494 | | // b. Invoke H( n1+n2*j+i, n1+n2-1+n2*j-i, j&1 ) for i = 0..(2n-7), j = 0..1. | 1495 | | for (auto i = 0u; i < (2 * log2_of_block_size) - 6u; i++) { | 1496 | | for (auto j = 0u; j < 2; j++) { | 1497 | | auto index_a = half_block_size + (quarter_block_size * j) + i; | 1498 | | auto index_b = half_block_size + quarter_block_size - 1 + (quarter_block_size * j) - i; | 1499 | | hadamard_rotation_in_place(data, index_a, index_b, (j & 1) != 0); | 1500 | | } | 1501 | | } | 1502 | | } | 1503 | | | 1504 | | // 6. If n is greater than or equal to 3: | 1505 | 44.2M | if constexpr (log2_of_block_size >= 3) { | 1506 | | // a. Invoke B( n0-n3-1-i, n1+n3+i, 16, 1 ) for i = 0..(n3-1). | 1507 | 88.4M | for (auto i = 0u; i < eighth_block_size; i++) { | 1508 | 44.1M | auto index_a = block_size - eighth_block_size - 1 - i; | 1509 | 44.1M | auto index_b = half_block_size + eighth_block_size + i; | 1510 | 44.1M | butterfly_rotation_in_place(data, index_a, index_b, 16, true); | 1511 | 44.1M | } | 1512 | 44.2M | } | 1513 | | | 1514 | | // 7. Invoke H( i, n0-1-i, 0 ) for i = 0..(n1-1). | 1515 | 221M | for (auto i = 0u; i < half_block_size; i++) | 1516 | 176M | hadamard_rotation_in_place(data, i, block_size - 1 - i, false); | 1517 | | | 1518 | 44.2M | return {}; | 1519 | 44.2M | } |
AK::ErrorOr<void, Media::DecoderError> Media::Video::VP9::Decoder::inverse_discrete_cosine_transform<(unsigned char)4>(AK::Span<int>) Line | Count | Source | 1422 | 29.2M | { | 1423 | 29.2M | static_assert(log2_of_block_size >= 2 && log2_of_block_size <= 5, "Block size out of range."); | 1424 | | | 1425 | | // 2.1. The variable n0 is set equal to 1<<n. | 1426 | 29.2M | constexpr u8 block_size = 1 << log2_of_block_size; | 1427 | | | 1428 | | // 8.7.1.3 Inverse DCT process | 1429 | | | 1430 | | // 2.2. The variable n1 is set equal to 1<<(n-1). | 1431 | 29.2M | constexpr u8 half_block_size = block_size >> 1; | 1432 | | // 2.3 The variable n2 is set equal to 1<<(n-2). | 1433 | 29.2M | constexpr u8 quarter_block_size = half_block_size >> 1; | 1434 | | // 2.4 The variable n3 is set equal to 1<<(n-3). | 1435 | 29.2M | constexpr u8 eighth_block_size = quarter_block_size >> 1; | 1436 | | | 1437 | | // 2.5 If n is equal to 2, invoke B( 0, 1, 16, 1 ), otherwise recursively invoke the inverse DCT defined in this | 1438 | | // section with the variable n set equal to n - 1. | 1439 | | if constexpr (log2_of_block_size == 2) | 1440 | | butterfly_rotation_in_place(data, 0, 1, 16, true); | 1441 | | else | 1442 | 29.2M | TRY(inverse_discrete_cosine_transform<log2_of_block_size - 1>(data)); | 1443 | | | 1444 | | // 2.6 Invoke B( n1+i, n0-1-i, 32-brev( 5, n1+i), 0 ) for i = 0..(n2-1). | 1445 | 145M | for (auto i = 0u; i < quarter_block_size; i++) { | 1446 | 116M | auto index = half_block_size + i; | 1447 | 116M | butterfly_rotation_in_place(data, index, block_size - 1 - i, 32 - brev<5>(index), false); | 1448 | 116M | } | 1449 | | | 1450 | | // 2.7 If n is greater than or equal to 3: | 1451 | 29.2M | if constexpr (log2_of_block_size >= 3) { | 1452 | | // a. Invoke H( n1+4*i+2*j, n1+1+4*i+2*j, j ) for i = 0..(n3-1), j = 0..1. | 1453 | 87.6M | for (auto i = 0u; i < eighth_block_size; i++) { | 1454 | 175M | for (auto j = 0u; j < 2; j++) { | 1455 | 116M | auto index = half_block_size + (4 * i) + (2 * j); | 1456 | 116M | hadamard_rotation_in_place(data, index, index + 1, j); | 1457 | 116M | } | 1458 | 58.3M | } | 1459 | 29.2M | } | 1460 | | | 1461 | | // 4. If n is equal to 5: | 1462 | | if constexpr (log2_of_block_size == 5) { | 1463 | | // a. Invoke B( n0-n+3-n2*j-4*i, n1+n-4+n2*j+4*i, 28-16*i+56*j, 1 ) for i = 0..1, j = 0..1. | 1464 | | for (auto i = 0u; i < 2; i++) { | 1465 | | for (auto j = 0u; j < 2; j++) { | 1466 | | auto index_a = block_size - log2_of_block_size + 3 - (quarter_block_size * j) - (4 * i); | 1467 | | auto index_b = half_block_size + log2_of_block_size - 4 + (quarter_block_size * j) + (4 * i); | 1468 | | auto angle = 28 - (16 * i) + (56 * j); | 1469 | | butterfly_rotation_in_place(data, index_a, index_b, angle, true); | 1470 | | } | 1471 | | } | 1472 | | | 1473 | | // b. Invoke H( n1+n3*j+i, n1+n2-5+n3*j-i, j&1 ) for i = 0..1, j = 0..3. | 1474 | | for (auto i = 0u; i < 2; i++) { | 1475 | | for (auto j = 0u; j < 4; j++) { | 1476 | | auto index_a = half_block_size + (eighth_block_size * j) + i; | 1477 | | auto index_b = half_block_size + quarter_block_size - 5 + (eighth_block_size * j) - i; | 1478 | | hadamard_rotation_in_place(data, index_a, index_b, (j & 1) != 0); | 1479 | | } | 1480 | | } | 1481 | | } | 1482 | | | 1483 | | // 5. If n is greater than or equal to 4: | 1484 | 29.2M | if constexpr (log2_of_block_size >= 4) { | 1485 | | // a. Invoke B( n0-n+2-i-n2*j, n1+n-3+i+n2*j, 24+48*j, 1 ) for i = 0..(n==5), j = 0..1. | 1486 | 58.4M | for (auto i = 0u; i <= (log2_of_block_size == 5); i++) { | 1487 | 87.5M | for (auto j = 0u; j < 2; j++) { | 1488 | 58.3M | auto index_a = block_size - log2_of_block_size + 2 - i - (quarter_block_size * j); | 1489 | 58.3M | auto index_b = half_block_size + log2_of_block_size - 3 + i + (quarter_block_size * j); | 1490 | 58.3M | butterfly_rotation_in_place(data, index_a, index_b, 24 + (48 * j), true); | 1491 | 58.3M | } | 1492 | 29.1M | } | 1493 | | | 1494 | | // b. Invoke H( n1+n2*j+i, n1+n2-1+n2*j-i, j&1 ) for i = 0..(2n-7), j = 0..1. | 1495 | 87.6M | for (auto i = 0u; i < (2 * log2_of_block_size) - 6u; i++) { | 1496 | 175M | for (auto j = 0u; j < 2; j++) { | 1497 | 116M | auto index_a = half_block_size + (quarter_block_size * j) + i; | 1498 | 116M | auto index_b = half_block_size + quarter_block_size - 1 + (quarter_block_size * j) - i; | 1499 | 116M | hadamard_rotation_in_place(data, index_a, index_b, (j & 1) != 0); | 1500 | 116M | } | 1501 | 58.4M | } | 1502 | 29.2M | } | 1503 | | | 1504 | | // 6. If n is greater than or equal to 3: | 1505 | 29.2M | if constexpr (log2_of_block_size >= 3) { | 1506 | | // a. Invoke B( n0-n3-1-i, n1+n3+i, 16, 1 ) for i = 0..(n3-1). | 1507 | 87.6M | for (auto i = 0u; i < eighth_block_size; i++) { | 1508 | 58.3M | auto index_a = block_size - eighth_block_size - 1 - i; | 1509 | 58.3M | auto index_b = half_block_size + eighth_block_size + i; | 1510 | 58.3M | butterfly_rotation_in_place(data, index_a, index_b, 16, true); | 1511 | 58.3M | } | 1512 | 29.2M | } | 1513 | | | 1514 | | // 7. Invoke H( i, n0-1-i, 0 ) for i = 0..(n1-1). | 1515 | 263M | for (auto i = 0u; i < half_block_size; i++) | 1516 | 234M | hadamard_rotation_in_place(data, i, block_size - 1 - i, false); | 1517 | | | 1518 | 29.2M | return {}; | 1519 | 29.2M | } |
AK::ErrorOr<void, Media::DecoderError> Media::Video::VP9::Decoder::inverse_discrete_cosine_transform<(unsigned char)5>(AK::Span<int>) Line | Count | Source | 1422 | 24.4M | { | 1423 | 24.4M | static_assert(log2_of_block_size >= 2 && log2_of_block_size <= 5, "Block size out of range."); | 1424 | | | 1425 | | // 2.1. The variable n0 is set equal to 1<<n. | 1426 | 24.4M | constexpr u8 block_size = 1 << log2_of_block_size; | 1427 | | | 1428 | | // 8.7.1.3 Inverse DCT process | 1429 | | | 1430 | | // 2.2. The variable n1 is set equal to 1<<(n-1). | 1431 | 24.4M | constexpr u8 half_block_size = block_size >> 1; | 1432 | | // 2.3 The variable n2 is set equal to 1<<(n-2). | 1433 | 24.4M | constexpr u8 quarter_block_size = half_block_size >> 1; | 1434 | | // 2.4 The variable n3 is set equal to 1<<(n-3). | 1435 | 24.4M | constexpr u8 eighth_block_size = quarter_block_size >> 1; | 1436 | | | 1437 | | // 2.5 If n is equal to 2, invoke B( 0, 1, 16, 1 ), otherwise recursively invoke the inverse DCT defined in this | 1438 | | // section with the variable n set equal to n - 1. | 1439 | | if constexpr (log2_of_block_size == 2) | 1440 | | butterfly_rotation_in_place(data, 0, 1, 16, true); | 1441 | | else | 1442 | 24.4M | TRY(inverse_discrete_cosine_transform<log2_of_block_size - 1>(data)); | 1443 | | | 1444 | | // 2.6 Invoke B( n1+i, n0-1-i, 32-brev( 5, n1+i), 0 ) for i = 0..(n2-1). | 1445 | 217M | for (auto i = 0u; i < quarter_block_size; i++) { | 1446 | 193M | auto index = half_block_size + i; | 1447 | 193M | butterfly_rotation_in_place(data, index, block_size - 1 - i, 32 - brev<5>(index), false); | 1448 | 193M | } | 1449 | | | 1450 | | // 2.7 If n is greater than or equal to 3: | 1451 | 24.4M | if constexpr (log2_of_block_size >= 3) { | 1452 | | // a. Invoke H( n1+4*i+2*j, n1+1+4*i+2*j, j ) for i = 0..(n3-1), j = 0..1. | 1453 | 121M | for (auto i = 0u; i < eighth_block_size; i++) { | 1454 | 292M | for (auto j = 0u; j < 2; j++) { | 1455 | 194M | auto index = half_block_size + (4 * i) + (2 * j); | 1456 | 194M | hadamard_rotation_in_place(data, index, index + 1, j); | 1457 | 194M | } | 1458 | 97.4M | } | 1459 | 24.4M | } | 1460 | | | 1461 | | // 4. If n is equal to 5: | 1462 | 24.4M | if constexpr (log2_of_block_size == 5) { | 1463 | | // a. Invoke B( n0-n+3-n2*j-4*i, n1+n-4+n2*j+4*i, 28-16*i+56*j, 1 ) for i = 0..1, j = 0..1. | 1464 | 73.1M | for (auto i = 0u; i < 2; i++) { | 1465 | 145M | for (auto j = 0u; j < 2; j++) { | 1466 | 97.0M | auto index_a = block_size - log2_of_block_size + 3 - (quarter_block_size * j) - (4 * i); | 1467 | 97.0M | auto index_b = half_block_size + log2_of_block_size - 4 + (quarter_block_size * j) + (4 * i); | 1468 | 97.0M | auto angle = 28 - (16 * i) + (56 * j); | 1469 | 97.0M | butterfly_rotation_in_place(data, index_a, index_b, angle, true); | 1470 | 97.0M | } | 1471 | 48.6M | } | 1472 | | | 1473 | | // b. Invoke H( n1+n3*j+i, n1+n2-5+n3*j-i, j&1 ) for i = 0..1, j = 0..3. | 1474 | 73.2M | for (auto i = 0u; i < 2; i++) { | 1475 | 243M | for (auto j = 0u; j < 4; j++) { | 1476 | 195M | auto index_a = half_block_size + (eighth_block_size * j) + i; | 1477 | 195M | auto index_b = half_block_size + quarter_block_size - 5 + (eighth_block_size * j) - i; | 1478 | 195M | hadamard_rotation_in_place(data, index_a, index_b, (j & 1) != 0); | 1479 | 195M | } | 1480 | 48.7M | } | 1481 | 24.4M | } | 1482 | | | 1483 | | // 5. If n is greater than or equal to 4: | 1484 | 24.4M | if constexpr (log2_of_block_size >= 4) { | 1485 | | // a. Invoke B( n0-n+2-i-n2*j, n1+n-3+i+n2*j, 24+48*j, 1 ) for i = 0..(n==5), j = 0..1. | 1486 | 73.1M | for (auto i = 0u; i <= (log2_of_block_size == 5); i++) { | 1487 | 145M | for (auto j = 0u; j < 2; j++) { | 1488 | 97.1M | auto index_a = block_size - log2_of_block_size + 2 - i - (quarter_block_size * j); | 1489 | 97.1M | auto index_b = half_block_size + log2_of_block_size - 3 + i + (quarter_block_size * j); | 1490 | 97.1M | butterfly_rotation_in_place(data, index_a, index_b, 24 + (48 * j), true); | 1491 | 97.1M | } | 1492 | 48.7M | } | 1493 | | | 1494 | | // b. Invoke H( n1+n2*j+i, n1+n2-1+n2*j-i, j&1 ) for i = 0..(2n-7), j = 0..1. | 1495 | 122M | for (auto i = 0u; i < (2 * log2_of_block_size) - 6u; i++) { | 1496 | 292M | for (auto j = 0u; j < 2; j++) { | 1497 | 195M | auto index_a = half_block_size + (quarter_block_size * j) + i; | 1498 | 195M | auto index_b = half_block_size + quarter_block_size - 1 + (quarter_block_size * j) - i; | 1499 | 195M | hadamard_rotation_in_place(data, index_a, index_b, (j & 1) != 0); | 1500 | 195M | } | 1501 | 97.5M | } | 1502 | 24.4M | } | 1503 | | | 1504 | | // 6. If n is greater than or equal to 3: | 1505 | 24.4M | if constexpr (log2_of_block_size >= 3) { | 1506 | | // a. Invoke B( n0-n3-1-i, n1+n3+i, 16, 1 ) for i = 0..(n3-1). | 1507 | 121M | for (auto i = 0u; i < eighth_block_size; i++) { | 1508 | 97.2M | auto index_a = block_size - eighth_block_size - 1 - i; | 1509 | 97.2M | auto index_b = half_block_size + eighth_block_size + i; | 1510 | 97.2M | butterfly_rotation_in_place(data, index_a, index_b, 16, true); | 1511 | 97.2M | } | 1512 | 24.4M | } | 1513 | | | 1514 | | // 7. Invoke H( i, n0-1-i, 0 ) for i = 0..(n1-1). | 1515 | 415M | for (auto i = 0u; i < half_block_size; i++) | 1516 | 391M | hadamard_rotation_in_place(data, i, block_size - 1 - i, false); | 1517 | | | 1518 | 24.4M | return {}; | 1519 | 24.4M | } |
|
1520 | | |
1521 | | template<u8 log2_of_block_size> |
1522 | | inline void Decoder::inverse_asymmetric_discrete_sine_transform_input_array_permutation(Span<Intermediate> data) |
1523 | 1.90M | { |
1524 | | // The variable n0 is set equal to 1<<n. |
1525 | 1.90M | constexpr auto block_size = 1u << log2_of_block_size; |
1526 | | // The variable n1 is set equal to 1<<(n-1). |
1527 | | // We can iterate by 2 at a time instead of taking half block size. |
1528 | | |
1529 | | // A temporary array named copyT is set equal to T. |
1530 | 1.90M | Array<Intermediate, block_size> data_copy; |
1531 | 1.90M | AK::TypedTransfer<Intermediate>::copy(data_copy.data(), data.data(), block_size); |
1532 | | |
1533 | | // The values at even locations T[ 2 * i ] are set equal to copyT[ n0 - 1 - 2 * i ] for i = 0..(n1-1). |
1534 | | // The values at odd locations T[ 2 * i + 1 ] are set equal to copyT[ 2 * i ] for i = 0..(n1-1). |
1535 | 12.0M | for (auto i = 0u; i < block_size; i += 2) { |
1536 | 10.1M | data[i] = data_copy[block_size - 1 - i]; |
1537 | 10.1M | data[i + 1] = data_copy[i]; |
1538 | 10.1M | } |
1539 | 1.90M | } void Media::Video::VP9::Decoder::inverse_asymmetric_discrete_sine_transform_input_array_permutation<(unsigned char)3>(AK::Span<int>) Line | Count | Source | 1523 | 1.27M | { | 1524 | | // The variable n0 is set equal to 1<<n. | 1525 | 1.27M | constexpr auto block_size = 1u << log2_of_block_size; | 1526 | | // The variable n1 is set equal to 1<<(n-1). | 1527 | | // We can iterate by 2 at a time instead of taking half block size. | 1528 | | | 1529 | | // A temporary array named copyT is set equal to T. | 1530 | 1.27M | Array<Intermediate, block_size> data_copy; | 1531 | 1.27M | AK::TypedTransfer<Intermediate>::copy(data_copy.data(), data.data(), block_size); | 1532 | | | 1533 | | // The values at even locations T[ 2 * i ] are set equal to copyT[ n0 - 1 - 2 * i ] for i = 0..(n1-1). | 1534 | | // The values at odd locations T[ 2 * i + 1 ] are set equal to copyT[ 2 * i ] for i = 0..(n1-1). | 1535 | 6.39M | for (auto i = 0u; i < block_size; i += 2) { | 1536 | 5.11M | data[i] = data_copy[block_size - 1 - i]; | 1537 | 5.11M | data[i + 1] = data_copy[i]; | 1538 | 5.11M | } | 1539 | 1.27M | } |
void Media::Video::VP9::Decoder::inverse_asymmetric_discrete_sine_transform_input_array_permutation<(unsigned char)4>(AK::Span<int>) Line | Count | Source | 1523 | 630k | { | 1524 | | // The variable n0 is set equal to 1<<n. | 1525 | 630k | constexpr auto block_size = 1u << log2_of_block_size; | 1526 | | // The variable n1 is set equal to 1<<(n-1). | 1527 | | // We can iterate by 2 at a time instead of taking half block size. | 1528 | | | 1529 | | // A temporary array named copyT is set equal to T. | 1530 | 630k | Array<Intermediate, block_size> data_copy; | 1531 | 630k | AK::TypedTransfer<Intermediate>::copy(data_copy.data(), data.data(), block_size); | 1532 | | | 1533 | | // The values at even locations T[ 2 * i ] are set equal to copyT[ n0 - 1 - 2 * i ] for i = 0..(n1-1). | 1534 | | // The values at odd locations T[ 2 * i + 1 ] are set equal to copyT[ 2 * i ] for i = 0..(n1-1). | 1535 | 5.67M | for (auto i = 0u; i < block_size; i += 2) { | 1536 | 5.04M | data[i] = data_copy[block_size - 1 - i]; | 1537 | 5.04M | data[i + 1] = data_copy[i]; | 1538 | 5.04M | } | 1539 | 630k | } |
|
1540 | | |
1541 | | template<u8 log2_of_block_size> |
1542 | | inline void Decoder::inverse_asymmetric_discrete_sine_transform_output_array_permutation(Span<Intermediate> data) |
1543 | 1.91M | { |
1544 | 1.91M | auto block_size = 1u << log2_of_block_size; |
1545 | | |
1546 | | // A temporary array named copyT is set equal to T. |
1547 | 1.91M | Array<Intermediate, maximum_transform_size> data_copy; |
1548 | 1.91M | AK::TypedTransfer<Intermediate>::copy(data_copy.data(), data.data(), block_size); |
1549 | | |
1550 | | // The permutation depends on n as follows: |
1551 | 1.91M | if (log2_of_block_size == 4) { |
1552 | | // − If n is equal to 4, |
1553 | | // T[ 8*a + 4*b + 2*c + d ] is set equal to copyT[ 8*(d^c) + 4*(c^b) + 2*(b^a) + a ] for a = 0..1 |
1554 | | // and b = 0..1 and c = 0..1 and d = 0..1. |
1555 | 1.89M | for (auto a = 0u; a < 2; a++) |
1556 | 3.78M | for (auto b = 0u; b < 2; b++) |
1557 | 7.56M | for (auto c = 0u; c < 2; c++) |
1558 | 15.1M | for (auto d = 0u; d < 2; d++) |
1559 | 10.0M | data[(8 * a) + (4 * b) + (2 * c) + d] = data_copy[8 * (d ^ c) + 4 * (c ^ b) + 2 * (b ^ a) + a]; |
1560 | 1.28M | } else { |
1561 | 1.28M | VERIFY(log2_of_block_size == 3); |
1562 | | // − Otherwise (n is equal to 3), |
1563 | | // T[ 4*a + 2*b + c ] is set equal to copyT[ 4*(c^b) + 2*(b^a) + a ] for a = 0..1 and |
1564 | | // b = 0..1 and c = 0..1. |
1565 | 3.84M | for (auto a = 0u; a < 2; a++) |
1566 | 7.67M | for (auto b = 0u; b < 2; b++) |
1567 | 15.3M | for (auto c = 0u; c < 2; c++) |
1568 | 10.2M | data[4 * a + 2 * b + c] = data_copy[4 * (c ^ b) + 2 * (b ^ a) + a]; |
1569 | 1.28M | } |
1570 | 1.91M | } void Media::Video::VP9::Decoder::inverse_asymmetric_discrete_sine_transform_output_array_permutation<(unsigned char)3>(AK::Span<int>) Line | Count | Source | 1543 | 1.28M | { | 1544 | 1.28M | auto block_size = 1u << log2_of_block_size; | 1545 | | | 1546 | | // A temporary array named copyT is set equal to T. | 1547 | 1.28M | Array<Intermediate, maximum_transform_size> data_copy; | 1548 | 1.28M | AK::TypedTransfer<Intermediate>::copy(data_copy.data(), data.data(), block_size); | 1549 | | | 1550 | | // The permutation depends on n as follows: | 1551 | 1.28M | if (log2_of_block_size == 4) { | 1552 | | // − If n is equal to 4, | 1553 | | // T[ 8*a + 4*b + 2*c + d ] is set equal to copyT[ 8*(d^c) + 4*(c^b) + 2*(b^a) + a ] for a = 0..1 | 1554 | | // and b = 0..1 and c = 0..1 and d = 0..1. | 1555 | 0 | for (auto a = 0u; a < 2; a++) | 1556 | 0 | for (auto b = 0u; b < 2; b++) | 1557 | 0 | for (auto c = 0u; c < 2; c++) | 1558 | 0 | for (auto d = 0u; d < 2; d++) | 1559 | 0 | data[(8 * a) + (4 * b) + (2 * c) + d] = data_copy[8 * (d ^ c) + 4 * (c ^ b) + 2 * (b ^ a) + a]; | 1560 | 1.28M | } else { | 1561 | 1.28M | VERIFY(log2_of_block_size == 3); | 1562 | | // − Otherwise (n is equal to 3), | 1563 | | // T[ 4*a + 2*b + c ] is set equal to copyT[ 4*(c^b) + 2*(b^a) + a ] for a = 0..1 and | 1564 | | // b = 0..1 and c = 0..1. | 1565 | 3.84M | for (auto a = 0u; a < 2; a++) | 1566 | 7.67M | for (auto b = 0u; b < 2; b++) | 1567 | 15.3M | for (auto c = 0u; c < 2; c++) | 1568 | 10.2M | data[4 * a + 2 * b + c] = data_copy[4 * (c ^ b) + 2 * (b ^ a) + a]; | 1569 | 1.28M | } | 1570 | 1.28M | } |
void Media::Video::VP9::Decoder::inverse_asymmetric_discrete_sine_transform_output_array_permutation<(unsigned char)4>(AK::Span<int>) Line | Count | Source | 1543 | 630k | { | 1544 | 630k | auto block_size = 1u << log2_of_block_size; | 1545 | | | 1546 | | // A temporary array named copyT is set equal to T. | 1547 | 630k | Array<Intermediate, maximum_transform_size> data_copy; | 1548 | 630k | AK::TypedTransfer<Intermediate>::copy(data_copy.data(), data.data(), block_size); | 1549 | | | 1550 | | // The permutation depends on n as follows: | 1551 | 630k | if (log2_of_block_size == 4) { | 1552 | | // − If n is equal to 4, | 1553 | | // T[ 8*a + 4*b + 2*c + d ] is set equal to copyT[ 8*(d^c) + 4*(c^b) + 2*(b^a) + a ] for a = 0..1 | 1554 | | // and b = 0..1 and c = 0..1 and d = 0..1. | 1555 | 1.89M | for (auto a = 0u; a < 2; a++) | 1556 | 3.78M | for (auto b = 0u; b < 2; b++) | 1557 | 7.56M | for (auto c = 0u; c < 2; c++) | 1558 | 15.1M | for (auto d = 0u; d < 2; d++) | 1559 | 10.0M | data[(8 * a) + (4 * b) + (2 * c) + d] = data_copy[8 * (d ^ c) + 4 * (c ^ b) + 2 * (b ^ a) + a]; | 1560 | 18.4E | } else { | 1561 | 18.4E | VERIFY(log2_of_block_size == 3); | 1562 | | // − Otherwise (n is equal to 3), | 1563 | | // T[ 4*a + 2*b + c ] is set equal to copyT[ 4*(c^b) + 2*(b^a) + a ] for a = 0..1 and | 1564 | | // b = 0..1 and c = 0..1. | 1565 | 18.4E | for (auto a = 0u; a < 2; a++) | 1566 | 0 | for (auto b = 0u; b < 2; b++) | 1567 | 0 | for (auto c = 0u; c < 2; c++) | 1568 | 0 | data[4 * a + 2 * b + c] = data_copy[4 * (c ^ b) + 2 * (b ^ a) + a]; | 1569 | 18.4E | } | 1570 | 630k | } |
|
1571 | | |
1572 | | inline void Decoder::inverse_asymmetric_discrete_sine_transform_4(Span<Intermediate> data) |
1573 | 2.06M | { |
1574 | 2.06M | VERIFY(data.size() == 4); |
1575 | 2.06M | i64 const sinpi_1_9 = 5283; |
1576 | 2.06M | i64 const sinpi_2_9 = 9929; |
1577 | 2.06M | i64 const sinpi_3_9 = 13377; |
1578 | 2.06M | i64 const sinpi_4_9 = 15212; |
1579 | | |
1580 | | // Steps are derived from pseudocode in (8.7.1.6): |
1581 | | // s0 = SINPI_1_9 * T[ 0 ] |
1582 | 2.06M | i64 s0 = sinpi_1_9 * data[0]; |
1583 | | // s1 = SINPI_2_9 * T[ 0 ] |
1584 | 2.06M | i64 s1 = sinpi_2_9 * data[0]; |
1585 | | // s2 = SINPI_3_9 * T[ 1 ] |
1586 | 2.06M | i64 s2 = sinpi_3_9 * data[1]; |
1587 | | // s3 = SINPI_4_9 * T[ 2 ] |
1588 | 2.06M | i64 s3 = sinpi_4_9 * data[2]; |
1589 | | // s4 = SINPI_1_9 * T[ 2 ] |
1590 | 2.06M | i64 s4 = sinpi_1_9 * data[2]; |
1591 | | // s5 = SINPI_2_9 * T[ 3 ] |
1592 | 2.06M | i64 s5 = sinpi_2_9 * data[3]; |
1593 | | // s6 = SINPI_4_9 * T[ 3 ] |
1594 | 2.06M | i64 s6 = sinpi_4_9 * data[3]; |
1595 | | // v = T[ 0 ] - T[ 2 ] + T[ 3 ] |
1596 | | // s7 = SINPI_3_9 * v |
1597 | 2.06M | i64 s7 = sinpi_3_9 * (data[0] - data[2] + data[3]); |
1598 | | |
1599 | | // x0 = s0 + s3 + s5 |
1600 | 2.06M | auto x0 = s0 + s3 + s5; |
1601 | | // x1 = s1 - s4 - s6 |
1602 | 2.06M | auto x1 = s1 - s4 - s6; |
1603 | | // x2 = s7 |
1604 | 2.06M | auto x2 = s7; |
1605 | | // x3 = s2 |
1606 | 2.06M | auto x3 = s2; |
1607 | | |
1608 | | // s0 = x0 + x3 |
1609 | 2.06M | s0 = x0 + x3; |
1610 | | // s1 = x1 + x3 |
1611 | 2.06M | s1 = x1 + x3; |
1612 | | // s2 = x2 |
1613 | 2.06M | s2 = x2; |
1614 | | // s3 = x0 + x1 - x3 |
1615 | 2.06M | s3 = x0 + x1 - x3; |
1616 | | |
1617 | | // T[ 0 ] = Round2( s0, 14 ) |
1618 | 2.06M | data[0] = rounded_right_shift(s0, 14); |
1619 | | // T[ 1 ] = Round2( s1, 14 ) |
1620 | 2.06M | data[1] = rounded_right_shift(s1, 14); |
1621 | | // T[ 2 ] = Round2( s2, 14 ) |
1622 | 2.06M | data[2] = rounded_right_shift(s2, 14); |
1623 | | // T[ 3 ] = Round2( s3, 14 ) |
1624 | 2.06M | data[3] = rounded_right_shift(s3, 14); |
1625 | | |
1626 | | // (8.7.1.1) The inverse asymmetric discrete sine transforms also make use of an intermediate array named S. |
1627 | | // The values in this array require higher precision to avoid overflow. Using signed integers with 24 + |
1628 | | // BitDepth bits of precision is enough to avoid overflow. |
1629 | | // Note: Since bounds checks just ensure that we will not have resulting values that will overflow, it's non-fatal |
1630 | | // to allow these bounds to be violated. Therefore, we can avoid the performance cost here. |
1631 | 2.06M | } |
1632 | | |
1633 | | // The function SB( a, b, angle, 0 ) performs a butterfly rotation. |
1634 | | // Spec defines the source as array T, and the destination array as S. |
1635 | | template<typename S, typename D> |
1636 | | inline void Decoder::butterfly_rotation(Span<S> source, Span<D> destination, size_t index_a, size_t index_b, u8 angle, bool flip) |
1637 | 17.7M | { |
1638 | | // The function SB( a, b, angle, 0 ) performs a butterfly rotation according to the following ordered steps: |
1639 | 17.7M | auto cos = cos64(angle); |
1640 | 17.7M | auto sin = sin64(angle); |
1641 | | // Expand to the destination buffer's precision. |
1642 | 17.7M | D a = source[index_a]; |
1643 | 17.7M | D b = source[index_b]; |
1644 | | // 1. S[ a ] is set equal to T[ a ] * cos64( angle ) - T[ b ] * sin64( angle ). |
1645 | 17.7M | destination[index_a] = a * cos - b * sin; |
1646 | | // 2. S[ b ] is set equal to T[ a ] * sin64( angle ) + T[ b ] * cos64( angle ). |
1647 | 17.7M | destination[index_b] = a * sin + b * cos; |
1648 | | |
1649 | | // The function SB( a, b, angle, 1 ) performs a butterfly rotation and flip according to the following ordered steps: |
1650 | | // 1. The function SB( a, b, angle, 0 ) is invoked. |
1651 | | // 2. The contents of S[ a ] and S[ b ] are exchanged. |
1652 | 17.7M | if (flip) |
1653 | 17.7M | swap(destination[index_a], destination[index_b]); |
1654 | 17.7M | } |
1655 | | |
1656 | | // The function SH( a, b ) performs a Hadamard rotation and rounding. |
1657 | | // Spec defines the source array as S, and the destination array as T. |
1658 | | template<typename S, typename D> |
1659 | | inline void Decoder::hadamard_rotation(Span<S> source, Span<D> destination, size_t index_a, size_t index_b) |
1660 | 17.7M | { |
1661 | | // Keep the source buffer's precision until rounding. |
1662 | 17.7M | S a = source[index_a]; |
1663 | 17.7M | S b = source[index_b]; |
1664 | | // 1. T[ a ] is set equal to Round2( S[ a ] + S[ b ], 14 ). |
1665 | 17.7M | destination[index_a] = rounded_right_shift(a + b, 14); |
1666 | | // 2. T[ b ] is set equal to Round2( S[ a ] - S[ b ], 14 ). |
1667 | 17.7M | destination[index_b] = rounded_right_shift(a - b, 14); |
1668 | 17.7M | } |
1669 | | |
1670 | | inline DecoderErrorOr<void> Decoder::inverse_asymmetric_discrete_sine_transform_8(Span<Intermediate> data) |
1671 | 1.27M | { |
1672 | 1.27M | VERIFY(data.size() == 8); |
1673 | | // This process does an in-place transform of the array T using: |
1674 | | |
1675 | | // A higher precision array S for intermediate results. |
1676 | | // (8.7.1.1) NOTE - The values in array S require higher precision to avoid overflow. Using signed integers with |
1677 | | // 24 + BitDepth bits of precision is enough to avoid overflow. |
1678 | 1.27M | Array<i64, 8> high_precision_temp; |
1679 | | |
1680 | | // The following ordered steps apply: |
1681 | | |
1682 | | // 1. Invoke the ADST input array permutation process specified in section 8.7.1.4 with the input variable n set |
1683 | | // equal to 3. |
1684 | 1.27M | inverse_asymmetric_discrete_sine_transform_input_array_permutation<3>(data); |
1685 | | |
1686 | | // 2. Invoke SB( 2*i, 1+2*i, 30-8*i, 1 ) for i = 0..3. |
1687 | 6.39M | for (auto i = 0u; i < 4; i++) |
1688 | 5.11M | butterfly_rotation(data, high_precision_temp.span(), 2 * i, 1 + (2 * i), 30 - (8 * i), true); |
1689 | | |
1690 | | // 3. Invoke SH( i, 4+i ) for i = 0..3. |
1691 | 6.39M | for (auto i = 0u; i < 4; i++) |
1692 | 5.11M | hadamard_rotation(high_precision_temp.span(), data, i, 4 + i); |
1693 | | |
1694 | | // 4. Invoke SB( 4+3*i, 5+i, 24-16*i, 1 ) for i = 0..1. |
1695 | 3.83M | for (auto i = 0u; i < 2; i++) |
1696 | 2.56M | butterfly_rotation(data, high_precision_temp.span(), 4 + (3 * i), 5 + i, 24 - (16 * i), true); |
1697 | | // 5. Invoke SH( 4+i, 6+i ) for i = 0..1. |
1698 | 3.83M | for (auto i = 0u; i < 2; i++) |
1699 | 2.56M | hadamard_rotation(high_precision_temp.span(), data, 4 + i, 6 + i); |
1700 | | |
1701 | | // 6. Invoke H( i, 2+i, 0 ) for i = 0..1. |
1702 | 3.83M | for (auto i = 0u; i < 2; i++) |
1703 | 2.56M | hadamard_rotation_in_place(data, i, 2 + i, false); |
1704 | | |
1705 | | // 7. Invoke B( 2+4*i, 3+4*i, 16, 1 ) for i = 0..1. |
1706 | 3.83M | for (auto i = 0u; i < 2; i++) |
1707 | 2.56M | butterfly_rotation_in_place(data, 2 + (4 * i), 3 + (4 * i), 16, true); |
1708 | | |
1709 | | // 8. Invoke the ADST output array permutation process specified in section 8.7.1.5 with the input variable n |
1710 | | // set equal to 3. |
1711 | 1.27M | inverse_asymmetric_discrete_sine_transform_output_array_permutation<3>(data); |
1712 | | |
1713 | | // 9. Set T[ 1+2*i ] equal to -T[ 1+2*i ] for i = 0..3. |
1714 | 6.39M | for (auto i = 0u; i < 4; i++) { |
1715 | 5.12M | auto index = 1 + (2 * i); |
1716 | 5.12M | data[index] = -data[index]; |
1717 | 5.12M | } |
1718 | 1.27M | return {}; |
1719 | 1.27M | } |
1720 | | |
1721 | | inline DecoderErrorOr<void> Decoder::inverse_asymmetric_discrete_sine_transform_16(Span<Intermediate> data) |
1722 | 630k | { |
1723 | 630k | VERIFY(data.size() == 16); |
1724 | | // This process does an in-place transform of the array T using: |
1725 | | |
1726 | | // A higher precision array S for intermediate results. |
1727 | | // (8.7.1.1) The inverse asymmetric discrete sine transforms also make use of an intermediate array named S. |
1728 | | // The values in this array require higher precision to avoid overflow. Using signed integers with 24 + |
1729 | | // BitDepth bits of precision is enough to avoid overflow. |
1730 | 630k | Array<i64, 16> high_precision_temp; |
1731 | | |
1732 | | // The following ordered steps apply: |
1733 | | |
1734 | | // 1. Invoke the ADST input array permutation process specified in section 8.7.1.4 with the input variable n set |
1735 | | // equal to 4. |
1736 | 630k | inverse_asymmetric_discrete_sine_transform_input_array_permutation<4>(data); |
1737 | | |
1738 | | // 2. Invoke SB( 2*i, 1+2*i, 31-4*i, 1 ) for i = 0..7. |
1739 | 5.66M | for (auto i = 0u; i < 8; i++) |
1740 | 5.03M | butterfly_rotation(data, high_precision_temp.span(), 2 * i, 1 + (2 * i), 31 - (4 * i), true); |
1741 | | // 3. Invoke SH( i, 8+i ) for i = 0..7. |
1742 | 5.67M | for (auto i = 0u; i < 8; i++) |
1743 | 5.04M | hadamard_rotation(high_precision_temp.span(), data, i, 8 + i); |
1744 | | |
1745 | | // 4. Invoke SB( 8+2*i, 9+2*i, 28-16*i, 1 ) for i = 0..3. |
1746 | 3.15M | for (auto i = 0u; i < 4; i++) |
1747 | 2.52M | butterfly_rotation(data, high_precision_temp.span(), 8 + (2 * i), 9 + (2 * i), 128 + 28 - (16 * i), true); |
1748 | | // 5. Invoke SH( 8+i, 12+i ) for i = 0..3. |
1749 | 3.15M | for (auto i = 0u; i < 4; i++) |
1750 | 2.52M | hadamard_rotation(high_precision_temp.span(), data, 8 + i, 12 + i); |
1751 | | |
1752 | | // 6. Invoke H( i, 4+i, 0 ) for i = 0..3. |
1753 | 3.15M | for (auto i = 0u; i < 4; i++) |
1754 | 2.52M | hadamard_rotation_in_place(data, i, 4 + i, false); |
1755 | | |
1756 | | // 7. Invoke SB( 4+8*i+3*j, 5+8*i+j, 24-16*j, 1 ) for i = 0..1, for j = 0..1. |
1757 | 1.89M | for (auto i = 0u; i < 2; i++) |
1758 | 3.78M | for (auto j = 0u; j < 2; j++) |
1759 | 2.52M | butterfly_rotation(data, high_precision_temp.span(), 4 + (8 * i) + (3 * j), 5 + (8 * i) + j, 24 - (16 * j), true); |
1760 | | // 8. Invoke SH( 4+8*j+i, 6+8*j+i ) for i = 0..1, j = 0..1. |
1761 | 1.89M | for (auto i = 0u; i < 2; i++) |
1762 | 3.78M | for (auto j = 0u; j < 2; j++) |
1763 | 2.52M | hadamard_rotation(high_precision_temp.span(), data, 4 + (8 * j) + i, 6 + (8 * j) + i); |
1764 | | |
1765 | | // 9. Invoke H( 8*j+i, 2+8*j+i, 0 ) for i = 0..1, for j = 0..1. |
1766 | 1.89M | for (auto i = 0u; i < 2; i++) |
1767 | 3.78M | for (auto j = 0u; j < 2; j++) |
1768 | 2.52M | hadamard_rotation_in_place(data, (8 * j) + i, 2 + (8 * j) + i, false); |
1769 | | // 10. Invoke B( 2+4*j+8*i, 3+4*j+8*i, 48+64*(i^j), 0 ) for i = 0..1, for j = 0..1. |
1770 | 1.89M | for (auto i = 0u; i < 2; i++) |
1771 | 3.78M | for (auto j = 0u; j < 2; j++) |
1772 | 2.52M | butterfly_rotation_in_place(data, 2 + (4 * j) + (8 * i), 3 + (4 * j) + (8 * i), 48 + (64 * (i ^ j)), false); |
1773 | | |
1774 | | // 11. Invoke the ADST output array permutation process specified in section 8.7.1.5 with the input variable n |
1775 | | // set equal to 4. |
1776 | 630k | inverse_asymmetric_discrete_sine_transform_output_array_permutation<4>(data); |
1777 | | |
1778 | | // 12. Set T[ 1+12*j+2*i ] equal to -T[ 1+12*j+2*i ] for i = 0..1, for j = 0..1. |
1779 | 1.89M | for (auto i = 0u; i < 2; i++) { |
1780 | 3.78M | for (auto j = 0u; j < 2; j++) { |
1781 | 2.52M | auto index = 1 + (12 * j) + (2 * i); |
1782 | 2.52M | data[index] = -data[index]; |
1783 | 2.52M | } |
1784 | 1.26M | } |
1785 | 630k | return {}; |
1786 | 630k | } |
1787 | | |
1788 | | template<u8 log2_of_block_size> |
1789 | | inline DecoderErrorOr<void> Decoder::inverse_asymmetric_discrete_sine_transform(Span<Intermediate> data) |
1790 | 3.97M | { |
1791 | | // 8.7.1.9 Inverse ADST Process |
1792 | | |
1793 | | // This process performs an in-place inverse ADST process on the array T of size 2^n for 2 ≤ n ≤ 4. |
1794 | | if constexpr (log2_of_block_size < 2 || log2_of_block_size > 4) |
1795 | 0 | return DecoderError::corrupted("Block size was out of range"sv); |
1796 | | |
1797 | | // The process to invoke depends on n as follows: |
1798 | 2.06M | if constexpr (log2_of_block_size == 2) { |
1799 | | // − If n is equal to 2, invoke the Inverse ADST4 process specified in section 8.7.1.6. |
1800 | 2.06M | inverse_asymmetric_discrete_sine_transform_4(data); |
1801 | 2.06M | return {}; |
1802 | 2.06M | } |
1803 | 1.27M | if constexpr (log2_of_block_size == 3) { |
1804 | | // − Otherwise if n is equal to 3, invoke the Inverse ADST8 process specified in section 8.7.1.7. |
1805 | 1.27M | return inverse_asymmetric_discrete_sine_transform_8(data); |
1806 | 1.27M | } |
1807 | | // − Otherwise (n is equal to 4), invoke the Inverse ADST16 process specified in section 8.7.1.8. |
1808 | 0 | return inverse_asymmetric_discrete_sine_transform_16(data); |
1809 | 3.97M | } AK::ErrorOr<void, Media::DecoderError> Media::Video::VP9::Decoder::inverse_asymmetric_discrete_sine_transform<(unsigned char)2>(AK::Span<int>) Line | Count | Source | 1790 | 2.06M | { | 1791 | | // 8.7.1.9 Inverse ADST Process | 1792 | | | 1793 | | // This process performs an in-place inverse ADST process on the array T of size 2^n for 2 ≤ n ≤ 4. | 1794 | | if constexpr (log2_of_block_size < 2 || log2_of_block_size > 4) | 1795 | | return DecoderError::corrupted("Block size was out of range"sv); | 1796 | | | 1797 | | // The process to invoke depends on n as follows: | 1798 | 2.06M | if constexpr (log2_of_block_size == 2) { | 1799 | | // − If n is equal to 2, invoke the Inverse ADST4 process specified in section 8.7.1.6. | 1800 | 2.06M | inverse_asymmetric_discrete_sine_transform_4(data); | 1801 | 2.06M | return {}; | 1802 | 2.06M | } | 1803 | | if constexpr (log2_of_block_size == 3) { | 1804 | | // − Otherwise if n is equal to 3, invoke the Inverse ADST8 process specified in section 8.7.1.7. | 1805 | | return inverse_asymmetric_discrete_sine_transform_8(data); | 1806 | | } | 1807 | | // − Otherwise (n is equal to 4), invoke the Inverse ADST16 process specified in section 8.7.1.8. | 1808 | 2.06M | return inverse_asymmetric_discrete_sine_transform_16(data); | 1809 | 2.06M | } |
AK::ErrorOr<void, Media::DecoderError> Media::Video::VP9::Decoder::inverse_asymmetric_discrete_sine_transform<(unsigned char)3>(AK::Span<int>) Line | Count | Source | 1790 | 1.27M | { | 1791 | | // 8.7.1.9 Inverse ADST Process | 1792 | | | 1793 | | // This process performs an in-place inverse ADST process on the array T of size 2^n for 2 ≤ n ≤ 4. | 1794 | | if constexpr (log2_of_block_size < 2 || log2_of_block_size > 4) | 1795 | | return DecoderError::corrupted("Block size was out of range"sv); | 1796 | | | 1797 | | // The process to invoke depends on n as follows: | 1798 | | if constexpr (log2_of_block_size == 2) { | 1799 | | // − If n is equal to 2, invoke the Inverse ADST4 process specified in section 8.7.1.6. | 1800 | | inverse_asymmetric_discrete_sine_transform_4(data); | 1801 | | return {}; | 1802 | | } | 1803 | 1.27M | if constexpr (log2_of_block_size == 3) { | 1804 | | // − Otherwise if n is equal to 3, invoke the Inverse ADST8 process specified in section 8.7.1.7. | 1805 | 1.27M | return inverse_asymmetric_discrete_sine_transform_8(data); | 1806 | 1.27M | } | 1807 | | // − Otherwise (n is equal to 4), invoke the Inverse ADST16 process specified in section 8.7.1.8. | 1808 | 0 | return inverse_asymmetric_discrete_sine_transform_16(data); | 1809 | 1.27M | } |
AK::ErrorOr<void, Media::DecoderError> Media::Video::VP9::Decoder::inverse_asymmetric_discrete_sine_transform<(unsigned char)4>(AK::Span<int>) Line | Count | Source | 1790 | 630k | { | 1791 | | // 8.7.1.9 Inverse ADST Process | 1792 | | | 1793 | | // This process performs an in-place inverse ADST process on the array T of size 2^n for 2 ≤ n ≤ 4. | 1794 | | if constexpr (log2_of_block_size < 2 || log2_of_block_size > 4) | 1795 | | return DecoderError::corrupted("Block size was out of range"sv); | 1796 | | | 1797 | | // The process to invoke depends on n as follows: | 1798 | | if constexpr (log2_of_block_size == 2) { | 1799 | | // − If n is equal to 2, invoke the Inverse ADST4 process specified in section 8.7.1.6. | 1800 | | inverse_asymmetric_discrete_sine_transform_4(data); | 1801 | | return {}; | 1802 | | } | 1803 | | if constexpr (log2_of_block_size == 3) { | 1804 | | // − Otherwise if n is equal to 3, invoke the Inverse ADST8 process specified in section 8.7.1.7. | 1805 | | return inverse_asymmetric_discrete_sine_transform_8(data); | 1806 | | } | 1807 | | // − Otherwise (n is equal to 4), invoke the Inverse ADST16 process specified in section 8.7.1.8. | 1808 | 630k | return inverse_asymmetric_discrete_sine_transform_16(data); | 1809 | 630k | } |
Unexecuted instantiation: AK::ErrorOr<void, Media::DecoderError> Media::Video::VP9::Decoder::inverse_asymmetric_discrete_sine_transform<(unsigned char)5>(AK::Span<int>) |
1810 | | |
1811 | | template<u8 log2_of_block_size> |
1812 | | ALWAYS_INLINE DecoderErrorOr<void> Decoder::inverse_transform_2d(BlockContext const& block_context, Span<Intermediate> dequantized, TransformSet transform_set) |
1813 | 8.55M | { |
1814 | 8.55M | static_assert(log2_of_block_size >= 2 && log2_of_block_size <= 5); |
1815 | | |
1816 | | // This process performs a 2D inverse transform for an array of size 2^n by 2^n stored in the 2D array Dequant. |
1817 | | // The input to this process is a variable n (log2_of_block_size) that specifies the base 2 logarithm of the width of the transform. |
1818 | | |
1819 | | // 1. Set the variable n0 (block_size) equal to 1 << n. |
1820 | 8.55M | constexpr auto block_size = 1u << log2_of_block_size; |
1821 | | |
1822 | 8.55M | Array<Intermediate, block_size * block_size> row_array; |
1823 | 8.55M | Span<Intermediate> row = row_array.span().trim(block_size); |
1824 | | |
1825 | | // 2. The row transforms with i = 0..(n0-1) are applied as follows: |
1826 | 59.5M | for (auto i = 0u; i < block_size; i++) { |
1827 | | // 1. Set T[ j ] equal to Dequant[ i ][ j ] for j = 0..(n0-1). |
1828 | 662M | for (auto j = 0u; j < block_size; j++) |
1829 | 611M | row[j] = dequantized[i * block_size + j]; |
1830 | | |
1831 | | // 2. If Lossless is equal to 1, invoke the Inverse WHT process as specified in section 8.7.1.10 with shift equal |
1832 | | // to 2. |
1833 | 50.9M | if (block_context.frame_context.lossless) { |
1834 | 3.62M | TRY(inverse_walsh_hadamard_transform(row, log2_of_block_size, 2)); |
1835 | 47.3M | } else { |
1836 | 47.3M | switch (transform_set.second_transform) { |
1837 | 45.0M | case TransformType::DCT: |
1838 | | // Otherwise, if TxType is equal to DCT_DCT or TxType is equal to ADST_DCT, apply an inverse DCT as |
1839 | | // follows: |
1840 | | // 1. Invoke the inverse DCT permutation process as specified in section 8.7.1.2 with the input variable n. |
1841 | 45.0M | TRY(inverse_discrete_cosine_transform_array_permutation<log2_of_block_size>(row)); |
1842 | | // 2. Invoke the inverse DCT process as specified in section 8.7.1.3 with the input variable n. |
1843 | 45.0M | TRY(inverse_discrete_cosine_transform<log2_of_block_size>(row)); |
1844 | 45.0M | break; |
1845 | 2.30M | case TransformType::ADST: |
1846 | | // 4. Otherwise (TxType is equal to DCT_ADST or TxType is equal to ADST_ADST), invoke the inverse ADST |
1847 | | // process as specified in section 8.7.1.9 with input variable n. |
1848 | 2.30M | TRY(inverse_asymmetric_discrete_sine_transform<log2_of_block_size>(row)); |
1849 | 2.30M | break; |
1850 | 0 | default: |
1851 | 0 | return DecoderError::corrupted("Unknown tx_type"sv); |
1852 | 47.3M | } |
1853 | 47.3M | } |
1854 | | |
1855 | | // 5. Set Dequant[ i ][ j ] equal to T[ j ] for j = 0..(n0-1). |
1856 | 662M | for (auto j = 0u; j < block_size; j++) |
1857 | 611M | dequantized[i * block_size + j] = row[j]; |
1858 | 51.0M | } |
1859 | | |
1860 | 8.61M | Array<Intermediate, block_size * block_size> column_array; |
1861 | 8.61M | auto column = column_array.span().trim(block_size); |
1862 | | |
1863 | | // 3. The column transforms with j = 0..(n0-1) are applied as follows: |
1864 | 59.6M | for (auto j = 0u; j < block_size; j++) { |
1865 | | // 1. Set T[ i ] equal to Dequant[ i ][ j ] for i = 0..(n0-1). |
1866 | 661M | for (auto i = 0u; i < block_size; i++) |
1867 | 610M | column[i] = dequantized[i * block_size + j]; |
1868 | | |
1869 | | // 2. If Lossless is equal to 1, invoke the Inverse WHT process as specified in section 8.7.1.10 with shift equal |
1870 | | // to 0. |
1871 | 50.9M | if (block_context.frame_context.lossless) { |
1872 | 3.62M | TRY(inverse_walsh_hadamard_transform(column, log2_of_block_size, 0)); |
1873 | 47.3M | } else { |
1874 | 47.3M | switch (transform_set.first_transform) { |
1875 | 45.6M | case TransformType::DCT: |
1876 | | // Otherwise, if TxType is equal to DCT_DCT or TxType is equal to DCT_ADST, apply an inverse DCT as |
1877 | | // follows: |
1878 | | // 1. Invoke the inverse DCT permutation process as specified in section 8.7.1.2 with the input variable n. |
1879 | 45.6M | TRY(inverse_discrete_cosine_transform_array_permutation<log2_of_block_size>(column)); |
1880 | | // 2. Invoke the inverse DCT process as specified in section 8.7.1.3 with the input variable n. |
1881 | 45.6M | TRY(inverse_discrete_cosine_transform<log2_of_block_size>(column)); |
1882 | 45.6M | break; |
1883 | 1.67M | case TransformType::ADST: |
1884 | | // 4. Otherwise (TxType is equal to ADST_DCT or TxType is equal to ADST_ADST), invoke the inverse ADST |
1885 | | // process as specified in section 8.7.1.9 with input variable n. |
1886 | 1.67M | TRY(inverse_asymmetric_discrete_sine_transform<log2_of_block_size>(column)); |
1887 | 1.67M | break; |
1888 | 0 | default: |
1889 | 0 | VERIFY_NOT_REACHED(); |
1890 | 47.3M | } |
1891 | 47.3M | } |
1892 | | |
1893 | | // 5. If Lossless is equal to 1, set Dequant[ i ][ j ] equal to T[ i ] for i = 0..(n0-1). |
1894 | 662M | for (auto i = 0u; i < block_size; i++) |
1895 | 611M | dequantized[i * block_size + j] = column[i]; |
1896 | | |
1897 | | // 6. Otherwise (Lossless is equal to 0), set Dequant[ i ][ j ] equal to Round2( T[ i ], Min( 6, n + 2 ) ) |
1898 | | // for i = 0..(n0-1). |
1899 | 51.0M | if (!block_context.frame_context.lossless) { |
1900 | 643M | for (auto i = 0u; i < block_size; i++) { |
1901 | 596M | auto index = i * block_size + j; |
1902 | 596M | dequantized[index] = rounded_right_shift(dequantized[index], min(6, log2_of_block_size + 2)); |
1903 | 596M | } |
1904 | 47.3M | } |
1905 | 51.0M | } |
1906 | | |
1907 | 8.70M | return {}; |
1908 | 8.61M | } AK::ErrorOr<void, Media::DecoderError> Media::Video::VP9::Decoder::inverse_transform_2d<(unsigned char)2>(Media::Video::VP9::BlockContext const&, AK::Span<int>, Media::Video::VP9::TransformSet) Line | Count | Source | 1813 | 6.98M | { | 1814 | 6.98M | static_assert(log2_of_block_size >= 2 && log2_of_block_size <= 5); | 1815 | | | 1816 | | // This process performs a 2D inverse transform for an array of size 2^n by 2^n stored in the 2D array Dequant. | 1817 | | // The input to this process is a variable n (log2_of_block_size) that specifies the base 2 logarithm of the width of the transform. | 1818 | | | 1819 | | // 1. Set the variable n0 (block_size) equal to 1 << n. | 1820 | 6.98M | constexpr auto block_size = 1u << log2_of_block_size; | 1821 | | | 1822 | 6.98M | Array<Intermediate, block_size * block_size> row_array; | 1823 | 6.98M | Span<Intermediate> row = row_array.span().trim(block_size); | 1824 | | | 1825 | | // 2. The row transforms with i = 0..(n0-1) are applied as follows: | 1826 | 34.9M | for (auto i = 0u; i < block_size; i++) { | 1827 | | // 1. Set T[ j ] equal to Dequant[ i ][ j ] for j = 0..(n0-1). | 1828 | 139M | for (auto j = 0u; j < block_size; j++) | 1829 | 111M | row[j] = dequantized[i * block_size + j]; | 1830 | | | 1831 | | // 2. If Lossless is equal to 1, invoke the Inverse WHT process as specified in section 8.7.1.10 with shift equal | 1832 | | // to 2. | 1833 | 27.8M | if (block_context.frame_context.lossless) { | 1834 | 3.62M | TRY(inverse_walsh_hadamard_transform(row, log2_of_block_size, 2)); | 1835 | 24.2M | } else { | 1836 | 24.2M | switch (transform_set.second_transform) { | 1837 | 23.0M | case TransformType::DCT: | 1838 | | // Otherwise, if TxType is equal to DCT_DCT or TxType is equal to ADST_DCT, apply an inverse DCT as | 1839 | | // follows: | 1840 | | // 1. Invoke the inverse DCT permutation process as specified in section 8.7.1.2 with the input variable n. | 1841 | 23.0M | TRY(inverse_discrete_cosine_transform_array_permutation<log2_of_block_size>(row)); | 1842 | | // 2. Invoke the inverse DCT process as specified in section 8.7.1.3 with the input variable n. | 1843 | 23.0M | TRY(inverse_discrete_cosine_transform<log2_of_block_size>(row)); | 1844 | 23.0M | break; | 1845 | 1.19M | case TransformType::ADST: | 1846 | | // 4. Otherwise (TxType is equal to DCT_ADST or TxType is equal to ADST_ADST), invoke the inverse ADST | 1847 | | // process as specified in section 8.7.1.9 with input variable n. | 1848 | 1.19M | TRY(inverse_asymmetric_discrete_sine_transform<log2_of_block_size>(row)); | 1849 | 1.19M | break; | 1850 | 0 | default: | 1851 | 0 | return DecoderError::corrupted("Unknown tx_type"sv); | 1852 | 24.2M | } | 1853 | 24.2M | } | 1854 | | | 1855 | | // 5. Set Dequant[ i ][ j ] equal to T[ j ] for j = 0..(n0-1). | 1856 | 139M | for (auto j = 0u; j < block_size; j++) | 1857 | 111M | dequantized[i * block_size + j] = row[j]; | 1858 | 27.9M | } | 1859 | | | 1860 | 7.03M | Array<Intermediate, block_size * block_size> column_array; | 1861 | 7.03M | auto column = column_array.span().trim(block_size); | 1862 | | | 1863 | | // 3. The column transforms with j = 0..(n0-1) are applied as follows: | 1864 | 34.9M | for (auto j = 0u; j < block_size; j++) { | 1865 | | // 1. Set T[ i ] equal to Dequant[ i ][ j ] for i = 0..(n0-1). | 1866 | 139M | for (auto i = 0u; i < block_size; i++) | 1867 | 111M | column[i] = dequantized[i * block_size + j]; | 1868 | | | 1869 | | // 2. If Lossless is equal to 1, invoke the Inverse WHT process as specified in section 8.7.1.10 with shift equal | 1870 | | // to 0. | 1871 | 27.8M | if (block_context.frame_context.lossless) { | 1872 | 3.62M | TRY(inverse_walsh_hadamard_transform(column, log2_of_block_size, 0)); | 1873 | 24.2M | } else { | 1874 | 24.2M | switch (transform_set.first_transform) { | 1875 | 23.3M | case TransformType::DCT: | 1876 | | // Otherwise, if TxType is equal to DCT_DCT or TxType is equal to DCT_ADST, apply an inverse DCT as | 1877 | | // follows: | 1878 | | // 1. Invoke the inverse DCT permutation process as specified in section 8.7.1.2 with the input variable n. | 1879 | 23.3M | TRY(inverse_discrete_cosine_transform_array_permutation<log2_of_block_size>(column)); | 1880 | | // 2. Invoke the inverse DCT process as specified in section 8.7.1.3 with the input variable n. | 1881 | 23.3M | TRY(inverse_discrete_cosine_transform<log2_of_block_size>(column)); | 1882 | 23.3M | break; | 1883 | 872k | case TransformType::ADST: | 1884 | | // 4. Otherwise (TxType is equal to ADST_DCT or TxType is equal to ADST_ADST), invoke the inverse ADST | 1885 | | // process as specified in section 8.7.1.9 with input variable n. | 1886 | 872k | TRY(inverse_asymmetric_discrete_sine_transform<log2_of_block_size>(column)); | 1887 | 872k | break; | 1888 | 0 | default: | 1889 | 0 | VERIFY_NOT_REACHED(); | 1890 | 24.2M | } | 1891 | 24.2M | } | 1892 | | | 1893 | | // 5. If Lossless is equal to 1, set Dequant[ i ][ j ] equal to T[ i ] for i = 0..(n0-1). | 1894 | 139M | for (auto i = 0u; i < block_size; i++) | 1895 | 111M | dequantized[i * block_size + j] = column[i]; | 1896 | | | 1897 | | // 6. Otherwise (Lossless is equal to 0), set Dequant[ i ][ j ] equal to Round2( T[ i ], Min( 6, n + 2 ) ) | 1898 | | // for i = 0..(n0-1). | 1899 | 27.9M | if (!block_context.frame_context.lossless) { | 1900 | 121M | for (auto i = 0u; i < block_size; i++) { | 1901 | 97.0M | auto index = i * block_size + j; | 1902 | 97.0M | dequantized[index] = rounded_right_shift(dequantized[index], min(6, log2_of_block_size + 2)); | 1903 | 97.0M | } | 1904 | 24.2M | } | 1905 | 27.9M | } | 1906 | | | 1907 | 7.10M | return {}; | 1908 | 7.03M | } |
AK::ErrorOr<void, Media::DecoderError> Media::Video::VP9::Decoder::inverse_transform_2d<(unsigned char)3>(Media::Video::VP9::BlockContext const&, AK::Span<int>, Media::Video::VP9::TransformSet) Line | Count | Source | 1813 | 1.01M | { | 1814 | 1.01M | static_assert(log2_of_block_size >= 2 && log2_of_block_size <= 5); | 1815 | | | 1816 | | // This process performs a 2D inverse transform for an array of size 2^n by 2^n stored in the 2D array Dequant. | 1817 | | // The input to this process is a variable n (log2_of_block_size) that specifies the base 2 logarithm of the width of the transform. | 1818 | | | 1819 | | // 1. Set the variable n0 (block_size) equal to 1 << n. | 1820 | 1.01M | constexpr auto block_size = 1u << log2_of_block_size; | 1821 | | | 1822 | 1.01M | Array<Intermediate, block_size * block_size> row_array; | 1823 | 1.01M | Span<Intermediate> row = row_array.span().trim(block_size); | 1824 | | | 1825 | | // 2. The row transforms with i = 0..(n0-1) are applied as follows: | 1826 | 9.15M | for (auto i = 0u; i < block_size; i++) { | 1827 | | // 1. Set T[ j ] equal to Dequant[ i ][ j ] for j = 0..(n0-1). | 1828 | 73.2M | for (auto j = 0u; j < block_size; j++) | 1829 | 65.1M | row[j] = dequantized[i * block_size + j]; | 1830 | | | 1831 | | // 2. If Lossless is equal to 1, invoke the Inverse WHT process as specified in section 8.7.1.10 with shift equal | 1832 | | // to 2. | 1833 | 8.13M | if (block_context.frame_context.lossless) { | 1834 | 0 | TRY(inverse_walsh_hadamard_transform(row, log2_of_block_size, 2)); | 1835 | 8.13M | } else { | 1836 | 8.13M | switch (transform_set.second_transform) { | 1837 | 7.39M | case TransformType::DCT: | 1838 | | // Otherwise, if TxType is equal to DCT_DCT or TxType is equal to ADST_DCT, apply an inverse DCT as | 1839 | | // follows: | 1840 | | // 1. Invoke the inverse DCT permutation process as specified in section 8.7.1.2 with the input variable n. | 1841 | 7.39M | TRY(inverse_discrete_cosine_transform_array_permutation<log2_of_block_size>(row)); | 1842 | | // 2. Invoke the inverse DCT process as specified in section 8.7.1.3 with the input variable n. | 1843 | 7.39M | TRY(inverse_discrete_cosine_transform<log2_of_block_size>(row)); | 1844 | 7.39M | break; | 1845 | 742k | case TransformType::ADST: | 1846 | | // 4. Otherwise (TxType is equal to DCT_ADST or TxType is equal to ADST_ADST), invoke the inverse ADST | 1847 | | // process as specified in section 8.7.1.9 with input variable n. | 1848 | 742k | TRY(inverse_asymmetric_discrete_sine_transform<log2_of_block_size>(row)); | 1849 | 742k | break; | 1850 | 0 | default: | 1851 | 0 | return DecoderError::corrupted("Unknown tx_type"sv); | 1852 | 8.13M | } | 1853 | 8.13M | } | 1854 | | | 1855 | | // 5. Set Dequant[ i ][ j ] equal to T[ j ] for j = 0..(n0-1). | 1856 | 73.2M | for (auto j = 0u; j < block_size; j++) | 1857 | 65.1M | dequantized[i * block_size + j] = row[j]; | 1858 | 8.13M | } | 1859 | | | 1860 | 1.01M | Array<Intermediate, block_size * block_size> column_array; | 1861 | 1.01M | auto column = column_array.span().trim(block_size); | 1862 | | | 1863 | | // 3. The column transforms with j = 0..(n0-1) are applied as follows: | 1864 | 9.15M | for (auto j = 0u; j < block_size; j++) { | 1865 | | // 1. Set T[ i ] equal to Dequant[ i ][ j ] for i = 0..(n0-1). | 1866 | 73.2M | for (auto i = 0u; i < block_size; i++) | 1867 | 65.1M | column[i] = dequantized[i * block_size + j]; | 1868 | | | 1869 | | // 2. If Lossless is equal to 1, invoke the Inverse WHT process as specified in section 8.7.1.10 with shift equal | 1870 | | // to 0. | 1871 | 8.13M | if (block_context.frame_context.lossless) { | 1872 | 0 | TRY(inverse_walsh_hadamard_transform(column, log2_of_block_size, 0)); | 1873 | 8.13M | } else { | 1874 | 8.13M | switch (transform_set.first_transform) { | 1875 | 7.60M | case TransformType::DCT: | 1876 | | // Otherwise, if TxType is equal to DCT_DCT or TxType is equal to DCT_ADST, apply an inverse DCT as | 1877 | | // follows: | 1878 | | // 1. Invoke the inverse DCT permutation process as specified in section 8.7.1.2 with the input variable n. | 1879 | 7.60M | TRY(inverse_discrete_cosine_transform_array_permutation<log2_of_block_size>(column)); | 1880 | | // 2. Invoke the inverse DCT process as specified in section 8.7.1.3 with the input variable n. | 1881 | 7.60M | TRY(inverse_discrete_cosine_transform<log2_of_block_size>(column)); | 1882 | 7.60M | break; | 1883 | 537k | case TransformType::ADST: | 1884 | | // 4. Otherwise (TxType is equal to ADST_DCT or TxType is equal to ADST_ADST), invoke the inverse ADST | 1885 | | // process as specified in section 8.7.1.9 with input variable n. | 1886 | 537k | TRY(inverse_asymmetric_discrete_sine_transform<log2_of_block_size>(column)); | 1887 | 537k | break; | 1888 | 0 | default: | 1889 | 0 | VERIFY_NOT_REACHED(); | 1890 | 8.13M | } | 1891 | 8.13M | } | 1892 | | | 1893 | | // 5. If Lossless is equal to 1, set Dequant[ i ][ j ] equal to T[ i ] for i = 0..(n0-1). | 1894 | 73.2M | for (auto i = 0u; i < block_size; i++) | 1895 | 65.1M | dequantized[i * block_size + j] = column[i]; | 1896 | | | 1897 | | // 6. Otherwise (Lossless is equal to 0), set Dequant[ i ][ j ] equal to Round2( T[ i ], Min( 6, n + 2 ) ) | 1898 | | // for i = 0..(n0-1). | 1899 | 8.13M | if (!block_context.frame_context.lossless) { | 1900 | 73.2M | for (auto i = 0u; i < block_size; i++) { | 1901 | 65.1M | auto index = i * block_size + j; | 1902 | 65.1M | dequantized[index] = rounded_right_shift(dequantized[index], min(6, log2_of_block_size + 2)); | 1903 | 65.1M | } | 1904 | 8.13M | } | 1905 | 8.13M | } | 1906 | | | 1907 | 1.01M | return {}; | 1908 | 1.01M | } |
AK::ErrorOr<void, Media::DecoderError> Media::Video::VP9::Decoder::inverse_transform_2d<(unsigned char)4>(Media::Video::VP9::BlockContext const&, AK::Span<int>, Media::Video::VP9::TransformSet) Line | Count | Source | 1813 | 170k | { | 1814 | 170k | static_assert(log2_of_block_size >= 2 && log2_of_block_size <= 5); | 1815 | | | 1816 | | // This process performs a 2D inverse transform for an array of size 2^n by 2^n stored in the 2D array Dequant. | 1817 | | // The input to this process is a variable n (log2_of_block_size) that specifies the base 2 logarithm of the width of the transform. | 1818 | | | 1819 | | // 1. Set the variable n0 (block_size) equal to 1 << n. | 1820 | 170k | constexpr auto block_size = 1u << log2_of_block_size; | 1821 | | | 1822 | 170k | Array<Intermediate, block_size * block_size> row_array; | 1823 | 170k | Span<Intermediate> row = row_array.span().trim(block_size); | 1824 | | | 1825 | | // 2. The row transforms with i = 0..(n0-1) are applied as follows: | 1826 | 2.89M | for (auto i = 0u; i < block_size; i++) { | 1827 | | // 1. Set T[ j ] equal to Dequant[ i ][ j ] for j = 0..(n0-1). | 1828 | 46.3M | for (auto j = 0u; j < block_size; j++) | 1829 | 43.6M | row[j] = dequantized[i * block_size + j]; | 1830 | | | 1831 | | // 2. If Lossless is equal to 1, invoke the Inverse WHT process as specified in section 8.7.1.10 with shift equal | 1832 | | // to 2. | 1833 | 2.72M | if (block_context.frame_context.lossless) { | 1834 | 0 | TRY(inverse_walsh_hadamard_transform(row, log2_of_block_size, 2)); | 1835 | 2.72M | } else { | 1836 | 2.72M | switch (transform_set.second_transform) { | 1837 | 2.35M | case TransformType::DCT: | 1838 | | // Otherwise, if TxType is equal to DCT_DCT or TxType is equal to ADST_DCT, apply an inverse DCT as | 1839 | | // follows: | 1840 | | // 1. Invoke the inverse DCT permutation process as specified in section 8.7.1.2 with the input variable n. | 1841 | 2.35M | TRY(inverse_discrete_cosine_transform_array_permutation<log2_of_block_size>(row)); | 1842 | | // 2. Invoke the inverse DCT process as specified in section 8.7.1.3 with the input variable n. | 1843 | 2.35M | TRY(inverse_discrete_cosine_transform<log2_of_block_size>(row)); | 1844 | 2.35M | break; | 1845 | 368k | case TransformType::ADST: | 1846 | | // 4. Otherwise (TxType is equal to DCT_ADST or TxType is equal to ADST_ADST), invoke the inverse ADST | 1847 | | // process as specified in section 8.7.1.9 with input variable n. | 1848 | 368k | TRY(inverse_asymmetric_discrete_sine_transform<log2_of_block_size>(row)); | 1849 | 368k | break; | 1850 | 0 | default: | 1851 | 0 | return DecoderError::corrupted("Unknown tx_type"sv); | 1852 | 2.72M | } | 1853 | 2.72M | } | 1854 | | | 1855 | | // 5. Set Dequant[ i ][ j ] equal to T[ j ] for j = 0..(n0-1). | 1856 | 46.3M | for (auto j = 0u; j < block_size; j++) | 1857 | 43.6M | dequantized[i * block_size + j] = row[j]; | 1858 | 2.72M | } | 1859 | | | 1860 | 170k | Array<Intermediate, block_size * block_size> column_array; | 1861 | 170k | auto column = column_array.span().trim(block_size); | 1862 | | | 1863 | | // 3. The column transforms with j = 0..(n0-1) are applied as follows: | 1864 | 2.89M | for (auto j = 0u; j < block_size; j++) { | 1865 | | // 1. Set T[ i ] equal to Dequant[ i ][ j ] for i = 0..(n0-1). | 1866 | 46.3M | for (auto i = 0u; i < block_size; i++) | 1867 | 43.6M | column[i] = dequantized[i * block_size + j]; | 1868 | | | 1869 | | // 2. If Lossless is equal to 1, invoke the Inverse WHT process as specified in section 8.7.1.10 with shift equal | 1870 | | // to 0. | 1871 | 2.72M | if (block_context.frame_context.lossless) { | 1872 | 0 | TRY(inverse_walsh_hadamard_transform(column, log2_of_block_size, 0)); | 1873 | 2.72M | } else { | 1874 | 2.72M | switch (transform_set.first_transform) { | 1875 | 2.46M | case TransformType::DCT: | 1876 | | // Otherwise, if TxType is equal to DCT_DCT or TxType is equal to DCT_ADST, apply an inverse DCT as | 1877 | | // follows: | 1878 | | // 1. Invoke the inverse DCT permutation process as specified in section 8.7.1.2 with the input variable n. | 1879 | 2.46M | TRY(inverse_discrete_cosine_transform_array_permutation<log2_of_block_size>(column)); | 1880 | | // 2. Invoke the inverse DCT process as specified in section 8.7.1.3 with the input variable n. | 1881 | 2.46M | TRY(inverse_discrete_cosine_transform<log2_of_block_size>(column)); | 1882 | 2.46M | break; | 1883 | 262k | case TransformType::ADST: | 1884 | | // 4. Otherwise (TxType is equal to ADST_DCT or TxType is equal to ADST_ADST), invoke the inverse ADST | 1885 | | // process as specified in section 8.7.1.9 with input variable n. | 1886 | 262k | TRY(inverse_asymmetric_discrete_sine_transform<log2_of_block_size>(column)); | 1887 | 262k | break; | 1888 | 0 | default: | 1889 | 0 | VERIFY_NOT_REACHED(); | 1890 | 2.72M | } | 1891 | 2.72M | } | 1892 | | | 1893 | | // 5. If Lossless is equal to 1, set Dequant[ i ][ j ] equal to T[ i ] for i = 0..(n0-1). | 1894 | 46.3M | for (auto i = 0u; i < block_size; i++) | 1895 | 43.6M | dequantized[i * block_size + j] = column[i]; | 1896 | | | 1897 | | // 6. Otherwise (Lossless is equal to 0), set Dequant[ i ][ j ] equal to Round2( T[ i ], Min( 6, n + 2 ) ) | 1898 | | // for i = 0..(n0-1). | 1899 | 2.72M | if (!block_context.frame_context.lossless) { | 1900 | 46.3M | for (auto i = 0u; i < block_size; i++) { | 1901 | 43.6M | auto index = i * block_size + j; | 1902 | 43.6M | dequantized[index] = rounded_right_shift(dequantized[index], min(6, log2_of_block_size + 2)); | 1903 | 43.6M | } | 1904 | 2.72M | } | 1905 | 2.72M | } | 1906 | | | 1907 | 170k | return {}; | 1908 | 170k | } |
AK::ErrorOr<void, Media::DecoderError> Media::Video::VP9::Decoder::inverse_transform_2d<(unsigned char)5>(Media::Video::VP9::BlockContext const&, AK::Span<int>, Media::Video::VP9::TransformSet) Line | Count | Source | 1813 | 382k | { | 1814 | 382k | static_assert(log2_of_block_size >= 2 && log2_of_block_size <= 5); | 1815 | | | 1816 | | // This process performs a 2D inverse transform for an array of size 2^n by 2^n stored in the 2D array Dequant. | 1817 | | // The input to this process is a variable n (log2_of_block_size) that specifies the base 2 logarithm of the width of the transform. | 1818 | | | 1819 | | // 1. Set the variable n0 (block_size) equal to 1 << n. | 1820 | 382k | constexpr auto block_size = 1u << log2_of_block_size; | 1821 | | | 1822 | 382k | Array<Intermediate, block_size * block_size> row_array; | 1823 | 382k | Span<Intermediate> row = row_array.span().trim(block_size); | 1824 | | | 1825 | | // 2. The row transforms with i = 0..(n0-1) are applied as follows: | 1826 | 12.6M | for (auto i = 0u; i < block_size; i++) { | 1827 | | // 1. Set T[ j ] equal to Dequant[ i ][ j ] for j = 0..(n0-1). | 1828 | 403M | for (auto j = 0u; j < block_size; j++) | 1829 | 390M | row[j] = dequantized[i * block_size + j]; | 1830 | | | 1831 | | // 2. If Lossless is equal to 1, invoke the Inverse WHT process as specified in section 8.7.1.10 with shift equal | 1832 | | // to 2. | 1833 | 12.2M | if (block_context.frame_context.lossless) { | 1834 | 0 | TRY(inverse_walsh_hadamard_transform(row, log2_of_block_size, 2)); | 1835 | 12.2M | } else { | 1836 | 12.2M | switch (transform_set.second_transform) { | 1837 | 12.2M | case TransformType::DCT: | 1838 | | // Otherwise, if TxType is equal to DCT_DCT or TxType is equal to ADST_DCT, apply an inverse DCT as | 1839 | | // follows: | 1840 | | // 1. Invoke the inverse DCT permutation process as specified in section 8.7.1.2 with the input variable n. | 1841 | 12.2M | TRY(inverse_discrete_cosine_transform_array_permutation<log2_of_block_size>(row)); | 1842 | | // 2. Invoke the inverse DCT process as specified in section 8.7.1.3 with the input variable n. | 1843 | 12.2M | TRY(inverse_discrete_cosine_transform<log2_of_block_size>(row)); | 1844 | 12.2M | break; | 1845 | 0 | case TransformType::ADST: | 1846 | | // 4. Otherwise (TxType is equal to DCT_ADST or TxType is equal to ADST_ADST), invoke the inverse ADST | 1847 | | // process as specified in section 8.7.1.9 with input variable n. | 1848 | 0 | TRY(inverse_asymmetric_discrete_sine_transform<log2_of_block_size>(row)); | 1849 | 0 | break; | 1850 | 0 | default: | 1851 | 0 | return DecoderError::corrupted("Unknown tx_type"sv); | 1852 | 12.2M | } | 1853 | 12.2M | } | 1854 | | | 1855 | | // 5. Set Dequant[ i ][ j ] equal to T[ j ] for j = 0..(n0-1). | 1856 | 403M | for (auto j = 0u; j < block_size; j++) | 1857 | 390M | dequantized[i * block_size + j] = row[j]; | 1858 | 12.2M | } | 1859 | | | 1860 | 389k | Array<Intermediate, block_size * block_size> column_array; | 1861 | 389k | auto column = column_array.span().trim(block_size); | 1862 | | | 1863 | | // 3. The column transforms with j = 0..(n0-1) are applied as follows: | 1864 | 12.6M | for (auto j = 0u; j < block_size; j++) { | 1865 | | // 1. Set T[ i ] equal to Dequant[ i ][ j ] for i = 0..(n0-1). | 1866 | 402M | for (auto i = 0u; i < block_size; i++) | 1867 | 390M | column[i] = dequantized[i * block_size + j]; | 1868 | | | 1869 | | // 2. If Lossless is equal to 1, invoke the Inverse WHT process as specified in section 8.7.1.10 with shift equal | 1870 | | // to 0. | 1871 | 12.1M | if (block_context.frame_context.lossless) { | 1872 | 0 | TRY(inverse_walsh_hadamard_transform(column, log2_of_block_size, 0)); | 1873 | 12.1M | } else { | 1874 | 12.1M | switch (transform_set.first_transform) { | 1875 | 12.2M | case TransformType::DCT: | 1876 | | // Otherwise, if TxType is equal to DCT_DCT or TxType is equal to DCT_ADST, apply an inverse DCT as | 1877 | | // follows: | 1878 | | // 1. Invoke the inverse DCT permutation process as specified in section 8.7.1.2 with the input variable n. | 1879 | 12.2M | TRY(inverse_discrete_cosine_transform_array_permutation<log2_of_block_size>(column)); | 1880 | | // 2. Invoke the inverse DCT process as specified in section 8.7.1.3 with the input variable n. | 1881 | 12.2M | TRY(inverse_discrete_cosine_transform<log2_of_block_size>(column)); | 1882 | 12.2M | break; | 1883 | 0 | case TransformType::ADST: | 1884 | | // 4. Otherwise (TxType is equal to ADST_DCT or TxType is equal to ADST_ADST), invoke the inverse ADST | 1885 | | // process as specified in section 8.7.1.9 with input variable n. | 1886 | 0 | TRY(inverse_asymmetric_discrete_sine_transform<log2_of_block_size>(column)); | 1887 | 0 | break; | 1888 | 0 | default: | 1889 | 0 | VERIFY_NOT_REACHED(); | 1890 | 12.1M | } | 1891 | 12.1M | } | 1892 | | | 1893 | | // 5. If Lossless is equal to 1, set Dequant[ i ][ j ] equal to T[ i ] for i = 0..(n0-1). | 1894 | 402M | for (auto i = 0u; i < block_size; i++) | 1895 | 390M | dequantized[i * block_size + j] = column[i]; | 1896 | | | 1897 | | // 6. Otherwise (Lossless is equal to 0), set Dequant[ i ][ j ] equal to Round2( T[ i ], Min( 6, n + 2 ) ) | 1898 | | // for i = 0..(n0-1). | 1899 | 12.2M | if (!block_context.frame_context.lossless) { | 1900 | 402M | for (auto i = 0u; i < block_size; i++) { | 1901 | 390M | auto index = i * block_size + j; | 1902 | 390M | dequantized[index] = rounded_right_shift(dequantized[index], min(6, log2_of_block_size + 2)); | 1903 | 390M | } | 1904 | 12.2M | } | 1905 | 12.2M | } | 1906 | | | 1907 | 409k | return {}; | 1908 | 389k | } |
|
1909 | | |
1910 | | DecoderErrorOr<void> Decoder::update_reference_frames(FrameContext const& frame_context) |
1911 | 1.80k | { |
1912 | | // This process is invoked as the final step in decoding a frame. |
1913 | | // The inputs to this process are the samples in the current frame CurrFrame[ plane ][ x ][ y ]. |
1914 | | // The output from this process is an updated set of reference frames and previous motion vectors. |
1915 | | // The following ordered steps apply: |
1916 | | |
1917 | | // 1. For each value of i from 0 to NUM_REF_FRAMES - 1, the following applies if bit i of refresh_frame_flags |
1918 | | // is equal to 1 (i.e. if (refresh_frame_flags>>i)&1 is equal to 1): |
1919 | 16.2k | for (u8 i = 0; i < NUM_REF_FRAMES; i++) { |
1920 | 14.4k | if (frame_context.should_update_reference_frame_at_index(i)) { |
1921 | 7.45k | auto& reference_frame = m_parser->m_reference_frames[i]; |
1922 | | |
1923 | | // − RefFrameWidth[ i ] is set equal to FrameWidth. |
1924 | | // − RefFrameHeight[ i ] is set equal to FrameHeight. |
1925 | 7.45k | reference_frame.size = frame_context.size(); |
1926 | | // − RefSubsamplingX[ i ] is set equal to subsampling_x. |
1927 | 7.45k | reference_frame.subsampling_x = frame_context.color_config.subsampling_x; |
1928 | | // − RefSubsamplingY[ i ] is set equal to subsampling_y. |
1929 | 7.45k | reference_frame.subsampling_y = frame_context.color_config.subsampling_y; |
1930 | | // − RefBitDepth[ i ] is set equal to BitDepth. |
1931 | 7.45k | reference_frame.bit_depth = frame_context.color_config.bit_depth; |
1932 | | |
1933 | | // − FrameStore[ i ][ 0 ][ y ][ x ] is set equal to CurrFrame[ 0 ][ y ][ x ] for x = 0..FrameWidth-1, for y = |
1934 | | // 0..FrameHeight-1. |
1935 | | // − FrameStore[ i ][ plane ][ y ][ x ] is set equal to CurrFrame[ plane ][ y ][ x ] for plane = 1..2, for x = |
1936 | | // 0..((FrameWidth+subsampling_x) >> subsampling_x)-1, for y = 0..((FrameHeight+subsampling_y) >> |
1937 | | // subsampling_y)-1. |
1938 | | |
1939 | | // FIXME: Frame width is not equal to the buffer's stride. If we store the stride of the buffer with the reference |
1940 | | // frame, we can just copy the framebuffer data instead. Alternatively, we should crop the output framebuffer. |
1941 | 29.8k | for (auto plane = 0u; plane < 3; plane++) { |
1942 | 22.3k | auto width = frame_context.size().width(); |
1943 | 22.3k | auto height = frame_context.size().height(); |
1944 | 22.3k | auto stride = frame_context.decoded_size(plane > 0).width(); |
1945 | 22.3k | if (plane > 0) { |
1946 | 14.9k | width = Subsampling::subsampled_size(frame_context.color_config.subsampling_x, width); |
1947 | 14.9k | height = Subsampling::subsampled_size(frame_context.color_config.subsampling_y, height); |
1948 | 14.9k | } |
1949 | | |
1950 | 22.3k | auto const& original_buffer = get_output_buffer(plane); |
1951 | 22.3k | auto& frame_store_buffer = reference_frame.frame_planes[plane]; |
1952 | 22.3k | auto frame_store_width = width + MV_BORDER * 2; |
1953 | 22.3k | auto frame_store_height = height + MV_BORDER * 2; |
1954 | 22.3k | frame_store_buffer.resize_and_keep_capacity(frame_store_width * frame_store_height); |
1955 | | |
1956 | 22.3k | VERIFY(original_buffer.size() >= width * height); |
1957 | 28.6M | for (auto destination_y = 0u; destination_y < frame_store_height; destination_y++) { |
1958 | | // Offset the source row by the motion vector border and then clamp it to the range of 0...height. |
1959 | | // This will create an extended border on the top and bottom of the reference frame to avoid having to bounds check |
1960 | | // inter-prediction. |
1961 | 28.6M | auto source_y = min(destination_y >= MV_BORDER ? destination_y - MV_BORDER : 0, height - 1); |
1962 | 28.6M | auto const* source = &original_buffer[source_y * stride]; |
1963 | 28.6M | auto* destination = &frame_store_buffer[destination_y * frame_store_width + MV_BORDER]; |
1964 | 28.6M | AK::TypedTransfer<RemoveReference<decltype(*destination)>>::copy(destination, source, width); |
1965 | 28.6M | } |
1966 | | |
1967 | 28.6M | for (auto destination_y = 0u; destination_y < frame_store_height; destination_y++) { |
1968 | | // Stretch the leftmost samples out into the border. |
1969 | 28.6M | auto sample = frame_store_buffer[destination_y * frame_store_width + MV_BORDER]; |
1970 | | |
1971 | 3.69G | for (auto destination_x = 0u; destination_x < MV_BORDER; destination_x++) { |
1972 | 3.66G | frame_store_buffer[destination_y * frame_store_width + destination_x] = sample; |
1973 | 3.66G | } |
1974 | | |
1975 | | // Stretch the rightmost samples out into the border. |
1976 | 28.6M | sample = frame_store_buffer[destination_y * frame_store_width + MV_BORDER + width - 1]; |
1977 | | |
1978 | 3.69G | for (auto destination_x = MV_BORDER + width; destination_x < frame_store_width; destination_x++) { |
1979 | 3.66G | frame_store_buffer[destination_y * frame_store_width + destination_x] = sample; |
1980 | 3.66G | } |
1981 | 28.6M | } |
1982 | 22.3k | } |
1983 | 7.45k | } |
1984 | 14.4k | } |
1985 | | |
1986 | | // 2. If show_existing_frame is equal to 0, the following applies: |
1987 | 1.80k | if (!frame_context.shows_existing_frame()) { |
1988 | 1.80k | DECODER_TRY_ALLOC(m_parser->m_previous_block_contexts.try_resize_to_match_other_vector2d(frame_context.block_contexts())); |
1989 | | // − PrevRefFrames[ row ][ col ][ list ] is set equal to RefFrames[ row ][ col ][ list ] for row = 0..MiRows-1, |
1990 | | // for col = 0..MiCols-1, for list = 0..1. |
1991 | | // − PrevMvs[ row ][ col ][ list ][ comp ] is set equal to Mvs[ row ][ col ][ list ][ comp ] for row = 0..MiRows-1, |
1992 | | // for col = 0..MiCols-1, for list = 0..1, for comp = 0..1. |
1993 | | // And from decode_frame(): |
1994 | | // - If all of the following conditions are true, PrevSegmentIds[ row ][ col ] is set equal to |
1995 | | // SegmentIds[ row ][ col ] for row = 0..MiRows-1, for col = 0..MiCols-1: |
1996 | | // − show_existing_frame is equal to 0, |
1997 | | // − segmentation_enabled is equal to 1, |
1998 | | // − segmentation_update_map is equal to 1. |
1999 | 1.80k | bool keep_segment_ids = !frame_context.shows_existing_frame() && frame_context.segmentation_enabled && frame_context.use_full_segment_id_tree; |
2000 | 2.75M | frame_context.block_contexts().copy_to(m_parser->m_previous_block_contexts, [keep_segment_ids](FrameBlockContext context) { |
2001 | 2.75M | auto persistent_context = PersistentBlockContext(context); |
2002 | 2.75M | if (!keep_segment_ids) |
2003 | 1.91M | persistent_context.segment_id = 0; |
2004 | 2.75M | return persistent_context; |
2005 | 2.75M | }); |
2006 | 1.80k | } |
2007 | | |
2008 | 1.80k | return {}; |
2009 | 1.80k | } |
2010 | | |
2011 | | } |