/src/serenity/Userland/Libraries/LibMedia/Video/VP9/Parser.cpp
Line | Count | Source (jump to first uncovered line) |
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/MemoryStream.h> |
9 | | #include <LibGfx/Point.h> |
10 | | #include <LibGfx/Size.h> |
11 | | #include <LibThreading/WorkerThread.h> |
12 | | |
13 | | #include "Context.h" |
14 | | #include "Decoder.h" |
15 | | #include "Parser.h" |
16 | | #include "Utilities.h" |
17 | | |
18 | | #if defined(AK_COMPILER_GCC) |
19 | | # pragma GCC optimize("O3") |
20 | | #endif |
21 | | |
22 | | // Beware, threading is unstable in Serenity with smp=on, and performs worse than with it off. |
23 | | #define VP9_TILE_THREADING |
24 | | |
25 | | namespace Media::Video::VP9 { |
26 | | |
27 | 109k | #define TRY_READ(expression) DECODER_TRY(DecoderErrorCategory::Corrupted, expression) |
28 | | |
29 | | Parser::Parser(Decoder& decoder) |
30 | 783 | : m_decoder(decoder) |
31 | 783 | { |
32 | 783 | } |
33 | | |
34 | | Parser::~Parser() |
35 | 783 | { |
36 | 783 | } |
37 | | |
38 | | Vector<size_t> Parser::parse_superframe_sizes(ReadonlyBytes frame_data) |
39 | 783 | { |
40 | 783 | if (frame_data.size() < 1) |
41 | 0 | return {}; |
42 | | |
43 | | // The decoder determines the presence of a superframe by: |
44 | | // 1. parsing the final byte of the chunk and checking that the superframe_marker equals 0b110, |
45 | | |
46 | | // If the checks in steps 1 and 3 both pass, then the chunk is determined to contain a superframe and each |
47 | | // frame in the superframe is passed to the decoding process in turn. |
48 | | // Otherwise, the chunk is determined to not contain a superframe, and the whole chunk is passed to the |
49 | | // decoding process. |
50 | | |
51 | | // NOTE: Reading from span data will be quicker than spinning up a BitStream. |
52 | 783 | u8 superframe_byte = frame_data[frame_data.size() - 1]; |
53 | | |
54 | | // NOTE: We have to read out of the byte from the little end first, hence the padding bits in the masks below. |
55 | 783 | u8 superframe_marker = superframe_byte & 0b1110'0000; |
56 | 783 | if (superframe_marker == 0b1100'0000) { |
57 | 538 | u8 bytes_per_framesize = ((superframe_byte >> 3) & 0b11) + 1; |
58 | 538 | u8 frames_in_superframe = (superframe_byte & 0b111) + 1; |
59 | | // 2. setting the total size of the superframe_index SzIndex equal to 2 + NumFrames * SzBytes, |
60 | 538 | size_t index_size = 2 + bytes_per_framesize * frames_in_superframe; |
61 | | |
62 | 538 | if (index_size > frame_data.size()) |
63 | 0 | return {}; |
64 | | |
65 | 538 | auto superframe_header_data = frame_data.data() + frame_data.size() - index_size; |
66 | | |
67 | 538 | u8 start_superframe_byte = *(superframe_header_data++); |
68 | | // 3. checking that the first byte of the superframe_index matches the final byte. |
69 | 538 | if (superframe_byte != start_superframe_byte) |
70 | 42 | return {}; |
71 | | |
72 | 496 | Vector<size_t> result; |
73 | 4.45k | for (u8 i = 0; i < frames_in_superframe; i++) { |
74 | 3.96k | size_t frame_size = 0; |
75 | 7.92k | for (u8 j = 0; j < bytes_per_framesize; j++) |
76 | 3.96k | frame_size |= (static_cast<size_t>(*(superframe_header_data++)) << (j * 8)); |
77 | 3.96k | result.append(frame_size); |
78 | 3.96k | } |
79 | 496 | return result; |
80 | 538 | } |
81 | | |
82 | 245 | return {}; |
83 | 783 | } |
84 | | |
85 | | /* (6.1) */ |
86 | | DecoderErrorOr<FrameContext> Parser::parse_frame(ReadonlyBytes frame_data) |
87 | 2.25k | { |
88 | 2.25k | if (!m_probability_tables) |
89 | 783 | m_probability_tables = DECODER_TRY_ALLOC(try_make<ProbabilityTables>()); |
90 | | |
91 | | // NOTE: m_reusable_frame_block_contexts does not need to retain any data between frame decodes. |
92 | | // This is only stored so that we don't need to allocate a frame's block contexts on each |
93 | | // call to this function, since it will rarely change sizes. |
94 | 2.25k | auto frame_context = DECODER_TRY_ALLOC(FrameContext::create(frame_data, m_reusable_frame_block_contexts)); |
95 | 2.25k | TRY(uncompressed_header(frame_context)); |
96 | | // FIXME: This should not be an error. Spec says that we consume padding bits until the end of the sample. |
97 | 2.19k | if (frame_context.header_size_in_bytes == 0) |
98 | 12 | return DecoderError::corrupted("Frame header is zero-sized"sv); |
99 | 2.18k | m_probability_tables->load_probs(frame_context.probability_context_index); |
100 | 2.18k | m_probability_tables->load_probs2(frame_context.probability_context_index); |
101 | | |
102 | 2.18k | TRY(compressed_header(frame_context)); |
103 | | |
104 | 2.15k | TRY(m_decoder.allocate_buffers(frame_context)); |
105 | | |
106 | 2.15k | TRY(decode_tiles(frame_context)); |
107 | 1.88k | TRY(refresh_probs(frame_context)); |
108 | | |
109 | 0 | m_previous_frame_type = frame_context.type; |
110 | 1.88k | m_previous_frame_size = frame_context.size(); |
111 | 1.88k | m_previous_show_frame = frame_context.shows_a_frame(); |
112 | 1.88k | m_previous_color_config = frame_context.color_config; |
113 | 1.88k | m_previous_loop_filter_ref_deltas = frame_context.loop_filter_reference_deltas; |
114 | 1.88k | m_previous_loop_filter_mode_deltas = frame_context.loop_filter_mode_deltas; |
115 | | |
116 | 1.88k | if (frame_context.segmentation_enabled) { |
117 | 646 | m_previous_should_use_absolute_segment_base_quantizer = frame_context.should_use_absolute_segment_base_quantizer; |
118 | 646 | m_previous_segmentation_features = frame_context.segmentation_features; |
119 | 646 | } |
120 | | |
121 | 1.88k | return frame_context; |
122 | 1.88k | } |
123 | | |
124 | | DecoderErrorOr<void> Parser::refresh_probs(FrameContext const& frame_context) |
125 | 1.88k | { |
126 | 1.88k | if (!frame_context.error_resilient_mode && !frame_context.parallel_decoding_mode) { |
127 | 1.06k | m_probability_tables->load_probs(frame_context.probability_context_index); |
128 | 1.06k | TRY(m_decoder.adapt_coef_probs(frame_context)); |
129 | 1.06k | if (frame_context.is_inter_predicted()) { |
130 | 741 | m_probability_tables->load_probs2(frame_context.probability_context_index); |
131 | 741 | TRY(m_decoder.adapt_non_coef_probs(frame_context)); |
132 | 741 | } |
133 | 1.06k | } |
134 | 1.88k | if (frame_context.should_replace_probability_context) |
135 | 472 | m_probability_tables->save_probs(frame_context.probability_context_index); |
136 | 1.88k | return {}; |
137 | 1.88k | } |
138 | | |
139 | | DecoderErrorOr<VideoFullRangeFlag> Parser::read_video_full_range_flag(BigEndianInputBitStream& bit_stream) |
140 | 902 | { |
141 | 902 | if (TRY_READ(bit_stream.read_bit())) |
142 | 61 | return VideoFullRangeFlag::Full; |
143 | 841 | return VideoFullRangeFlag::Studio; |
144 | 902 | } |
145 | | |
146 | | template<Signed T = i8> |
147 | | static ErrorOr<T> read_signed(BigEndianInputBitStream& bit_stream, u8 bits) |
148 | 1.87k | { |
149 | 1.87k | auto value_unsigned = static_cast<T>(TRY(bit_stream.read_bits(bits))); |
150 | 1.87k | if (TRY(bit_stream.read_bit())) |
151 | 1.42k | return -value_unsigned; |
152 | 453 | return value_unsigned; |
153 | 1.87k | } |
154 | | |
155 | | static DecoderErrorOr<i8> read_delta_q(BigEndianInputBitStream& bit_stream) |
156 | 6.57k | { |
157 | 6.57k | if (TRY_READ(bit_stream.read_bit())) |
158 | 6.57k | return TRY_READ(read_signed(bit_stream, 4)); |
159 | 5.62k | return 0; |
160 | 6.57k | } |
161 | | |
162 | | struct QuantizationParameters { |
163 | | u8 base_quantizer_index { 0 }; |
164 | | i8 y_dc_quantizer_index_delta { 0 }; |
165 | | i8 uv_dc_quantizer_index_delta { 0 }; |
166 | | i8 uv_ac_quantizer_index_delta { 0 }; |
167 | | }; |
168 | | |
169 | | static DecoderErrorOr<QuantizationParameters> quantization_params(BigEndianInputBitStream& bit_stream) |
170 | 2.19k | { |
171 | 2.19k | QuantizationParameters result; |
172 | 2.19k | result.base_quantizer_index = TRY_READ(bit_stream.read_bits(8)); |
173 | 2.19k | result.y_dc_quantizer_index_delta = TRY(read_delta_q(bit_stream)); |
174 | 2.19k | result.uv_dc_quantizer_index_delta = TRY(read_delta_q(bit_stream)); |
175 | 2.19k | result.uv_ac_quantizer_index_delta = TRY(read_delta_q(bit_stream)); |
176 | 0 | return result; |
177 | 2.19k | } |
178 | | |
179 | | /* (6.2) */ |
180 | | DecoderErrorOr<void> Parser::uncompressed_header(FrameContext& frame_context) |
181 | 2.25k | { |
182 | 2.25k | frame_context.color_config = m_previous_color_config; |
183 | | |
184 | 2.25k | auto frame_marker = TRY_READ(frame_context.bit_stream.read_bits(2)); |
185 | 2.25k | if (frame_marker != 2) |
186 | 44 | return DecoderError::corrupted("uncompressed_header: Frame marker must be 2"sv); |
187 | | |
188 | 2.20k | auto profile_low_bit = TRY_READ(frame_context.bit_stream.read_bit()); |
189 | 2.20k | auto profile_high_bit = TRY_READ(frame_context.bit_stream.read_bit()); |
190 | 0 | frame_context.profile = (profile_high_bit << 1u) + profile_low_bit; |
191 | 2.20k | if (frame_context.profile == 3 && TRY_READ(frame_context.bit_stream.read_bit())) |
192 | 0 | return DecoderError::corrupted("uncompressed_header: Profile 3 reserved bit was non-zero"sv); |
193 | | |
194 | 2.20k | if (TRY_READ(frame_context.bit_stream.read_bit())) { |
195 | 8 | frame_context.set_existing_frame_to_show(TRY_READ(frame_context.bit_stream.read_bits(3))); |
196 | 0 | return {}; |
197 | 8 | } |
198 | | |
199 | 2.20k | bool is_keyframe = !TRY_READ(frame_context.bit_stream.read_bit()); |
200 | | |
201 | 2.20k | if (!TRY_READ(frame_context.bit_stream.read_bit())) |
202 | 610 | frame_context.set_frame_hidden(); |
203 | | |
204 | 2.20k | frame_context.error_resilient_mode = TRY_READ(frame_context.bit_stream.read_bit()); |
205 | | |
206 | 0 | FrameType type; |
207 | | |
208 | 2.20k | Gfx::Size<u32> frame_size; |
209 | 2.20k | Gfx::Size<u32> render_size; |
210 | 2.20k | u8 reference_frames_to_update_flags = 0xFF; // Save frame to all reference indices by default. |
211 | | |
212 | 2.20k | enum class ResetProbabilities : u8 { |
213 | 2.20k | No = 0, |
214 | | // 1 also means No here, but we don't need to do anything with the No case. |
215 | 2.20k | OnlyCurrent = 2, |
216 | 2.20k | All = 3, |
217 | 2.20k | }; |
218 | 2.20k | ResetProbabilities reset_frame_context = ResetProbabilities::All; |
219 | | |
220 | 2.20k | if (is_keyframe) { |
221 | 891 | type = FrameType::KeyFrame; |
222 | 891 | TRY(frame_sync_code(frame_context.bit_stream)); |
223 | 888 | frame_context.color_config = TRY(parse_color_config(frame_context.bit_stream, frame_context.profile)); |
224 | 888 | frame_size = TRY(parse_frame_size(frame_context.bit_stream)); |
225 | 888 | render_size = TRY(parse_render_size(frame_context.bit_stream, frame_size)); |
226 | 1.30k | } else { |
227 | 1.30k | if (!frame_context.shows_a_frame() && TRY_READ(frame_context.bit_stream.read_bit())) { |
228 | 15 | type = FrameType::IntraOnlyFrame; |
229 | 1.29k | } else { |
230 | 1.29k | type = FrameType::InterFrame; |
231 | 1.29k | reset_frame_context = ResetProbabilities::No; |
232 | 1.29k | } |
233 | | |
234 | 1.30k | if (!frame_context.error_resilient_mode) |
235 | 842 | reset_frame_context = static_cast<ResetProbabilities>(TRY_READ(frame_context.bit_stream.read_bits(2))); |
236 | | |
237 | 1.30k | if (type == FrameType::IntraOnlyFrame) { |
238 | 15 | TRY(frame_sync_code(frame_context.bit_stream)); |
239 | | |
240 | 14 | if (frame_context.profile == 0) { |
241 | 0 | frame_context.color_config = ColorConfig(); |
242 | 14 | } else { |
243 | 14 | frame_context.color_config = TRY(parse_color_config(frame_context.bit_stream, frame_context.profile)); |
244 | 14 | } |
245 | | |
246 | 14 | reference_frames_to_update_flags = TRY_READ(frame_context.bit_stream.read_bits(8)); |
247 | 14 | frame_size = TRY(parse_frame_size(frame_context.bit_stream)); |
248 | 14 | render_size = TRY(parse_render_size(frame_context.bit_stream, frame_size)); |
249 | 1.29k | } else { |
250 | 1.29k | reference_frames_to_update_flags = TRY_READ(frame_context.bit_stream.read_bits(NUM_REF_FRAMES)); |
251 | 5.17k | for (auto i = 0; i < REFS_PER_FRAME; i++) { |
252 | 3.88k | frame_context.reference_frame_indices[i] = TRY_READ(frame_context.bit_stream.read_bits(LOG2_OF_NUM_REF_FRAMES)); |
253 | 3.88k | frame_context.reference_frame_sign_biases[ReferenceFrameType::LastFrame + i] = TRY_READ(frame_context.bit_stream.read_bit()); |
254 | 3.88k | } |
255 | 1.29k | frame_size = TRY(parse_frame_size_with_refs(frame_context.bit_stream, frame_context.reference_frame_indices)); |
256 | 1.29k | render_size = TRY(parse_render_size(frame_context.bit_stream, frame_size)); |
257 | 1.29k | frame_context.high_precision_motion_vectors_allowed = TRY_READ(frame_context.bit_stream.read_bit()); |
258 | 1.29k | frame_context.interpolation_filter = TRY(read_interpolation_filter(frame_context.bit_stream)); |
259 | 5.16k | for (auto i = 0; i < REFS_PER_FRAME; i++) { |
260 | 3.87k | TRY(m_decoder.prepare_referenced_frame(frame_size, frame_context.reference_frame_indices[i])); |
261 | 3.87k | } |
262 | 1.29k | } |
263 | 1.30k | } |
264 | | |
265 | 2.19k | bool should_replace_probability_context = false; |
266 | 2.19k | bool parallel_decoding_mode = true; |
267 | 2.19k | if (!frame_context.error_resilient_mode) { |
268 | 1.63k | should_replace_probability_context = TRY_READ(frame_context.bit_stream.read_bit()); |
269 | 1.63k | parallel_decoding_mode = TRY_READ(frame_context.bit_stream.read_bit()); |
270 | 1.63k | } |
271 | | |
272 | 2.19k | u8 probability_context_index = TRY_READ(frame_context.bit_stream.read_bits(2)); |
273 | 0 | switch (reset_frame_context) { |
274 | 923 | case ResetProbabilities::All: |
275 | 923 | setup_past_independence(); |
276 | 4.61k | for (auto i = 0; i < 4; i++) { |
277 | 3.69k | m_probability_tables->save_probs(i); |
278 | 3.69k | } |
279 | 923 | probability_context_index = 0; |
280 | 923 | break; |
281 | 662 | case ResetProbabilities::OnlyCurrent: |
282 | 662 | setup_past_independence(); |
283 | 662 | m_probability_tables->save_probs(probability_context_index); |
284 | 662 | probability_context_index = 0; |
285 | 662 | break; |
286 | 608 | default: |
287 | 608 | break; |
288 | 2.19k | } |
289 | | |
290 | 2.19k | frame_context.type = type; |
291 | 2.19k | DECODER_TRY_ALLOC(frame_context.set_size(frame_size)); |
292 | 0 | frame_context.render_size = render_size; |
293 | 2.19k | TRY(compute_image_size(frame_context)); |
294 | | |
295 | 0 | frame_context.reference_frames_to_update_flags = reference_frames_to_update_flags; |
296 | 2.19k | frame_context.parallel_decoding_mode = parallel_decoding_mode; |
297 | | |
298 | 2.19k | frame_context.should_replace_probability_context = should_replace_probability_context; |
299 | 2.19k | frame_context.probability_context_index = probability_context_index; |
300 | | |
301 | 2.19k | TRY(loop_filter_params(frame_context)); |
302 | 2.19k | auto quantization_parameters = TRY(quantization_params(frame_context.bit_stream)); |
303 | 2.19k | TRY(segmentation_params(frame_context)); |
304 | 0 | precalculate_quantizers(frame_context, quantization_parameters); |
305 | | |
306 | 2.19k | TRY(parse_tile_counts(frame_context)); |
307 | | |
308 | 2.19k | frame_context.header_size_in_bytes = TRY_READ(frame_context.bit_stream.read_bits(16)); |
309 | | |
310 | 0 | frame_context.bit_stream.align_to_byte_boundary(); |
311 | 2.19k | return {}; |
312 | 2.19k | } |
313 | | |
314 | | DecoderErrorOr<void> Parser::frame_sync_code(BigEndianInputBitStream& bit_stream) |
315 | 906 | { |
316 | 1.81k | if (TRY_READ(bit_stream.read_bits(24)) != 0x498342) { |
317 | 4 | return DecoderError::corrupted("frame sync code was not 0x498342."sv); |
318 | 4 | } |
319 | 902 | return {}; |
320 | 906 | } |
321 | | |
322 | | DecoderErrorOr<ColorConfig> Parser::parse_color_config(BigEndianInputBitStream& bit_stream, u8 profile) |
323 | 902 | { |
324 | | // (6.2.2) color_config( ) |
325 | 902 | u8 bit_depth; |
326 | 902 | if (profile >= 2) { |
327 | 96 | bit_depth = TRY_READ(bit_stream.read_bit()) ? 12 : 10; |
328 | 806 | } else { |
329 | 806 | bit_depth = 8; |
330 | 806 | } |
331 | | |
332 | 902 | auto color_space = static_cast<ColorSpace>(TRY_READ(bit_stream.read_bits(3))); |
333 | 902 | if (color_space == ColorSpace::Reserved) |
334 | 0 | return DecoderError::corrupted("color_config: Color space reserved value was set"sv); |
335 | | |
336 | 902 | VERIFY(color_space <= ColorSpace::RGB); |
337 | | |
338 | 902 | VideoFullRangeFlag video_full_range_flag; |
339 | 902 | bool subsampling_x, subsampling_y; |
340 | | |
341 | 902 | if (color_space != ColorSpace::RGB) { |
342 | 902 | video_full_range_flag = TRY(read_video_full_range_flag(bit_stream)); |
343 | 902 | if (profile == 1 || profile == 3) { |
344 | 109 | subsampling_x = TRY_READ(bit_stream.read_bit()); |
345 | 109 | subsampling_y = TRY_READ(bit_stream.read_bit()); |
346 | 109 | if (TRY_READ(bit_stream.read_bit())) |
347 | 0 | return DecoderError::corrupted("color_config: Subsampling reserved zero was set"sv); |
348 | 793 | } else { |
349 | 793 | subsampling_x = true; |
350 | 793 | subsampling_y = true; |
351 | 793 | } |
352 | 902 | } else { |
353 | 0 | video_full_range_flag = VideoFullRangeFlag::Full; |
354 | 0 | if (profile == 1 || profile == 3) { |
355 | 0 | subsampling_x = false; |
356 | 0 | subsampling_y = false; |
357 | 0 | if (TRY_READ(bit_stream.read_bit())) |
358 | 0 | return DecoderError::corrupted("color_config: RGB reserved zero was set"sv); |
359 | 0 | } else { |
360 | | // FIXME: Spec does not specify the subsampling value here. Is this an error or should we set a default? |
361 | 0 | return DecoderError::corrupted("color_config: Invalid subsampling value for profile 0 or 2"sv); |
362 | 0 | } |
363 | 0 | } |
364 | | |
365 | 902 | return ColorConfig { bit_depth, color_space, video_full_range_flag, subsampling_x, subsampling_y }; |
366 | 902 | } |
367 | | |
368 | | DecoderErrorOr<Gfx::Size<u32>> Parser::parse_frame_size(BigEndianInputBitStream& bit_stream) |
369 | 1.03k | { |
370 | 1.03k | return Gfx::Size<u32> { TRY_READ(bit_stream.read_bits(16)) + 1, TRY_READ(bit_stream.read_bits(16)) + 1 }; |
371 | 1.03k | } |
372 | | |
373 | | DecoderErrorOr<Gfx::Size<u32>> Parser::parse_render_size(BigEndianInputBitStream& bit_stream, Gfx::Size<u32> frame_size) |
374 | 2.19k | { |
375 | | // FIXME: This function should save this bit as a value in the FrameContext. The bit can be |
376 | | // used in files where the pixel aspect ratio changes between samples in the video. |
377 | | // If the bit is set, the pixel aspect ratio should be recalculated, whereas if only |
378 | | // the frame size has changed and the render size is unadjusted, then the pixel aspect |
379 | | // ratio should be retained and the new render size determined based on that. |
380 | | // See the Firefox source code here: |
381 | | // https://searchfox.org/mozilla-central/source/dom/media/platforms/wrappers/MediaChangeMonitor.cpp#268-276 |
382 | 2.19k | if (!TRY_READ(bit_stream.read_bit())) |
383 | 1.04k | return frame_size; |
384 | 1.14k | return Gfx::Size<u32> { TRY_READ(bit_stream.read_bits(16)) + 1, TRY_READ(bit_stream.read_bits(16)) + 1 }; |
385 | 1.14k | } |
386 | | |
387 | | DecoderErrorOr<Gfx::Size<u32>> Parser::parse_frame_size_with_refs(BigEndianInputBitStream& bit_stream, Array<u8, 3> const& reference_indices) |
388 | 1.29k | { |
389 | 1.29k | Optional<Gfx::Size<u32>> size; |
390 | 2.37k | for (auto frame_index : reference_indices) { |
391 | 2.37k | if (TRY_READ(bit_stream.read_bit())) { |
392 | 1.15k | if (!m_reference_frames[frame_index].is_valid()) |
393 | 0 | return DecoderError::corrupted("Frame size referenced a frame that does not exist"sv); |
394 | 1.15k | size.emplace(m_reference_frames[frame_index].size); |
395 | 1.15k | break; |
396 | 1.15k | } |
397 | 2.37k | } |
398 | | |
399 | 1.29k | if (size.has_value()) |
400 | 1.15k | return size.value(); |
401 | | |
402 | 136 | return TRY(parse_frame_size(bit_stream)); |
403 | 136 | } |
404 | | |
405 | | DecoderErrorOr<void> Parser::compute_image_size(FrameContext& frame_context) |
406 | 2.19k | { |
407 | | // 7.2.6 Compute image size semantics |
408 | | // When compute_image_size is invoked, the following ordered steps occur: |
409 | | // 1. If this is the first time compute_image_size is invoked, or if either FrameWidth or FrameHeight have |
410 | | // changed in value compared to the previous time this function was invoked, then the segmentation map is |
411 | | // cleared to all zeros by setting SegmentId[ row ][ col ] equal to 0 for row = 0..MiRows-1 and col = |
412 | | // 0..MiCols-1. |
413 | | // FIXME: What does this mean? SegmentIds is scoped to one frame, so it will not contain values here. It's |
414 | | // also suspicious that spec refers to this as SegmentId rather than SegmentIds (plural). Is this |
415 | | // supposed to refer to PrevSegmentIds? |
416 | 2.19k | bool first_invoke = m_is_first_compute_image_size_invoke; |
417 | 2.19k | m_is_first_compute_image_size_invoke = false; |
418 | 2.19k | bool same_size = m_previous_frame_size == frame_context.size(); |
419 | | |
420 | | // 2. The variable UsePrevFrameMvs is set equal to 1 if all of the following conditions are true: |
421 | | // a. This is not the first time compute_image_size is invoked. |
422 | | // b. Both FrameWidth and FrameHeight have the same value compared to the previous time this function |
423 | | // was invoked. |
424 | | // c. show_frame was equal to 1 the previous time this function was invoked. |
425 | | // d. error_resilient_mode is equal to 0. |
426 | | // e. FrameIsIntra is equal to 0. |
427 | | // Otherwise, UsePrevFrameMvs is set equal to 0. |
428 | 2.19k | frame_context.use_previous_frame_motion_vectors = !first_invoke && same_size && m_previous_show_frame && !frame_context.error_resilient_mode && frame_context.is_inter_predicted(); |
429 | 2.19k | return {}; |
430 | 2.19k | } |
431 | | |
432 | | DecoderErrorOr<InterpolationFilter> Parser::read_interpolation_filter(BigEndianInputBitStream& bit_stream) |
433 | 1.29k | { |
434 | 1.29k | if (TRY_READ(bit_stream.read_bit())) { |
435 | 967 | return InterpolationFilter::Switchable; |
436 | 967 | } |
437 | 327 | return literal_to_type[TRY_READ(bit_stream.read_bits(2))]; |
438 | 327 | } |
439 | | |
440 | | DecoderErrorOr<void> Parser::loop_filter_params(FrameContext& frame_context) |
441 | 2.19k | { |
442 | | // FIXME: These should be moved to their own struct to return here. |
443 | 2.19k | frame_context.loop_filter_level = TRY_READ(frame_context.bit_stream.read_bits(6)); |
444 | 2.19k | frame_context.loop_filter_sharpness = TRY_READ(frame_context.bit_stream.read_bits(3)); |
445 | 2.19k | frame_context.loop_filter_delta_enabled = TRY_READ(frame_context.bit_stream.read_bit()); |
446 | | |
447 | 0 | auto reference_deltas = m_previous_loop_filter_ref_deltas; |
448 | 2.19k | auto mode_deltas = m_previous_loop_filter_mode_deltas; |
449 | 2.19k | if (frame_context.loop_filter_delta_enabled && TRY_READ(frame_context.bit_stream.read_bit())) { |
450 | 944 | for (auto& loop_filter_ref_delta : reference_deltas) { |
451 | 944 | if (TRY_READ(frame_context.bit_stream.read_bit())) |
452 | 868 | loop_filter_ref_delta = TRY_READ(read_signed(frame_context.bit_stream, 6)); |
453 | 944 | } |
454 | 472 | for (auto& loop_filter_mode_delta : mode_deltas) { |
455 | 472 | if (TRY_READ(frame_context.bit_stream.read_bit())) |
456 | 56 | loop_filter_mode_delta = TRY_READ(read_signed(frame_context.bit_stream, 6)); |
457 | 472 | } |
458 | 236 | } |
459 | 2.19k | frame_context.loop_filter_reference_deltas = reference_deltas; |
460 | 2.19k | frame_context.loop_filter_mode_deltas = mode_deltas; |
461 | | |
462 | 2.19k | return {}; |
463 | 2.19k | } |
464 | | |
465 | | DecoderErrorOr<void> Parser::segmentation_params(FrameContext& frame_context) |
466 | 2.19k | { |
467 | 2.19k | frame_context.segmentation_enabled = TRY_READ(frame_context.bit_stream.read_bit()); |
468 | 2.19k | if (!frame_context.segmentation_enabled) |
469 | 1.49k | return {}; |
470 | | |
471 | 692 | frame_context.should_use_absolute_segment_base_quantizer = m_previous_should_use_absolute_segment_base_quantizer; |
472 | 692 | frame_context.segmentation_features = m_previous_segmentation_features; |
473 | | |
474 | 692 | if (TRY_READ(frame_context.bit_stream.read_bit())) { |
475 | 60 | frame_context.use_full_segment_id_tree = true; |
476 | 60 | for (auto& segmentation_tree_prob : frame_context.full_segment_id_tree_probabilities) |
477 | 420 | segmentation_tree_prob = TRY(read_prob(frame_context.bit_stream)); |
478 | | |
479 | 60 | if (TRY_READ(frame_context.bit_stream.read_bit())) { |
480 | 13 | frame_context.use_predicted_segment_id_tree = true; |
481 | 13 | for (auto& segmentation_pred_prob : frame_context.predicted_segment_id_tree_probabilities) |
482 | 39 | segmentation_pred_prob = TRY(read_prob(frame_context.bit_stream)); |
483 | 13 | } |
484 | 60 | } |
485 | | |
486 | 692 | auto segmentation_update_data = (TRY_READ(frame_context.bit_stream.read_bit())); |
487 | | |
488 | 692 | if (!segmentation_update_data) |
489 | 52 | return {}; |
490 | | |
491 | 640 | frame_context.should_use_absolute_segment_base_quantizer = TRY_READ(frame_context.bit_stream.read_bit()); |
492 | 5.76k | for (auto segment_id = 0; segment_id < MAX_SEGMENTS; segment_id++) { |
493 | 25.6k | for (auto feature_id = 0; feature_id < to_underlying(SegmentFeature::Sentinel); feature_id++) { |
494 | 20.4k | auto& feature = frame_context.segmentation_features[segment_id][feature_id]; |
495 | 20.4k | feature.enabled = TRY_READ(frame_context.bit_stream.read_bit()); |
496 | 20.4k | if (feature.enabled) { |
497 | 4.64k | auto bits_to_read = segmentation_feature_bits[feature_id]; |
498 | 4.64k | feature.value = TRY_READ(frame_context.bit_stream.read_bits(bits_to_read)); |
499 | 4.64k | if (segmentation_feature_signed[feature_id]) { |
500 | 2.89k | if (TRY_READ(frame_context.bit_stream.read_bit())) |
501 | 1.52k | feature.value = -feature.value; |
502 | 2.89k | } |
503 | 4.64k | } |
504 | 20.4k | } |
505 | 5.12k | } |
506 | | |
507 | 640 | return {}; |
508 | 640 | } |
509 | | |
510 | | DecoderErrorOr<u8> Parser::read_prob(BigEndianInputBitStream& bit_stream) |
511 | 459 | { |
512 | 459 | if (TRY_READ(bit_stream.read_bit())) |
513 | 459 | return TRY_READ(bit_stream.read_bits(8)); |
514 | 281 | return 255; |
515 | 459 | } |
516 | | |
517 | | void Parser::precalculate_quantizers(FrameContext& frame_context, QuantizationParameters quantization_parameters) |
518 | 2.19k | { |
519 | 2.19k | frame_context.lossless = quantization_parameters.base_quantizer_index == 0 |
520 | 2.19k | && quantization_parameters.y_dc_quantizer_index_delta == 0 |
521 | 2.19k | && quantization_parameters.uv_dc_quantizer_index_delta == 0 |
522 | 2.19k | && quantization_parameters.uv_ac_quantizer_index_delta == 0; |
523 | | |
524 | | // Pre-calculate the quantizers so that the decoder doesn't have to do it repeatedly. |
525 | 19.7k | for (u8 segment_id = 0; segment_id < MAX_SEGMENTS; segment_id++) { |
526 | 17.5k | auto alternative_quantizer_feature = frame_context.get_segment_feature(segment_id, SegmentFeature::AlternativeQuantizerBase); |
527 | 17.5k | auto base = Decoder::get_base_quantizer_index(alternative_quantizer_feature, frame_context.should_use_absolute_segment_base_quantizer, quantization_parameters.base_quantizer_index); |
528 | | |
529 | | // The function get_ac_quant( plane ) returns the quantizer value for the ac coefficient for a particular plane and |
530 | | // is derived as follows: |
531 | | // − If plane is equal to 0, return ac_q( get_qindex( ) ). |
532 | | // − Otherwise, return ac_q( get_qindex( ) + delta_q_uv_ac ). |
533 | 17.5k | auto& current_quantizers = frame_context.segment_quantizers[segment_id]; |
534 | 17.5k | current_quantizers.y_ac_quantizer = Decoder::get_ac_quantizer(frame_context.color_config.bit_depth, base, 0); |
535 | 17.5k | current_quantizers.uv_ac_quantizer = Decoder::get_ac_quantizer(frame_context.color_config.bit_depth, base, quantization_parameters.uv_ac_quantizer_index_delta); |
536 | | |
537 | | // The function get_dc_quant( plane ) returns the quantizer value for the dc coefficient for a particular plane and |
538 | | // is derived as follows: |
539 | | // − If plane is equal to 0, return dc_q( get_qindex( ) + delta_q_y_dc ). |
540 | | // − Otherwise, return dc_q( get_qindex( ) + delta_q_uv_dc ). |
541 | 17.5k | current_quantizers.y_dc_quantizer = Decoder::get_dc_quantizer(frame_context.color_config.bit_depth, base, quantization_parameters.y_dc_quantizer_index_delta); |
542 | 17.5k | current_quantizers.uv_dc_quantizer = Decoder::get_dc_quantizer(frame_context.color_config.bit_depth, base, quantization_parameters.uv_dc_quantizer_index_delta); |
543 | 17.5k | } |
544 | 2.19k | } |
545 | | |
546 | | static u16 calc_min_log2_of_tile_columns(u32 superblock_columns) |
547 | 2.19k | { |
548 | 2.19k | auto min_log_2 = 0u; |
549 | 2.21k | while ((u32)(MAX_TILE_WIDTH_B64 << min_log_2) < superblock_columns) |
550 | 24 | min_log_2++; |
551 | 2.19k | return min_log_2; |
552 | 2.19k | } |
553 | | |
554 | | static u16 calc_max_log2_tile_cols(u32 superblock_columns) |
555 | 2.19k | { |
556 | 2.19k | u16 max_log_2 = 1; |
557 | 3.33k | while ((superblock_columns >> max_log_2) >= MIN_TILE_WIDTH_B64) |
558 | 1.14k | max_log_2++; |
559 | 2.19k | return max_log_2 - 1; |
560 | 2.19k | } |
561 | | |
562 | | DecoderErrorOr<void> Parser::parse_tile_counts(FrameContext& frame_context) |
563 | 2.19k | { |
564 | 2.19k | auto superblock_columns = frame_context.superblock_columns(); |
565 | | |
566 | 2.19k | auto log2_of_tile_columns = calc_min_log2_of_tile_columns(superblock_columns); |
567 | 2.19k | auto log2_of_tile_columns_maximum = calc_max_log2_tile_cols(superblock_columns); |
568 | 2.22k | while (log2_of_tile_columns < log2_of_tile_columns_maximum) { |
569 | 975 | if (TRY_READ(frame_context.bit_stream.read_bit())) |
570 | 29 | log2_of_tile_columns++; |
571 | 946 | else |
572 | 946 | break; |
573 | 975 | } |
574 | | |
575 | 2.19k | u16 log2_of_tile_rows = TRY_READ(frame_context.bit_stream.read_bit()); |
576 | 2.19k | if (log2_of_tile_rows > 0) { |
577 | 16 | log2_of_tile_rows += TRY_READ(frame_context.bit_stream.read_bit()); |
578 | 16 | } |
579 | 2.19k | frame_context.log2_of_tile_counts = Gfx::Size<u16>(log2_of_tile_columns, log2_of_tile_rows); |
580 | 2.19k | return {}; |
581 | 2.19k | } |
582 | | |
583 | | void Parser::setup_past_independence() |
584 | 1.58k | { |
585 | 1.58k | m_previous_block_contexts.reset(); |
586 | 1.58k | m_previous_loop_filter_ref_deltas[ReferenceFrameType::None] = 1; |
587 | 1.58k | m_previous_loop_filter_ref_deltas[ReferenceFrameType::LastFrame] = 0; |
588 | 1.58k | m_previous_loop_filter_ref_deltas[ReferenceFrameType::GoldenFrame] = -1; |
589 | 1.58k | m_previous_loop_filter_ref_deltas[ReferenceFrameType::AltRefFrame] = -1; |
590 | 1.58k | m_previous_loop_filter_mode_deltas.fill(0); |
591 | 1.58k | m_previous_should_use_absolute_segment_base_quantizer = false; |
592 | 1.58k | for (auto& segment_levels : m_previous_segmentation_features) |
593 | 12.6k | segment_levels.fill({ false, 0 }); |
594 | 1.58k | m_probability_tables->reset_probs(); |
595 | 1.58k | } |
596 | | |
597 | | DecoderErrorOr<void> Parser::compressed_header(FrameContext& frame_context) |
598 | 2.18k | { |
599 | 2.18k | auto decoder = TRY(frame_context.create_range_decoder(frame_context.header_size_in_bytes)); |
600 | | |
601 | 0 | frame_context.transform_mode = read_tx_mode(decoder, frame_context); |
602 | 2.15k | if (frame_context.transform_mode == TransformMode::Select) |
603 | 387 | tx_mode_probs(decoder); |
604 | 2.15k | read_coef_probs(decoder, frame_context.transform_mode); |
605 | 2.15k | read_skip_prob(decoder); |
606 | 2.15k | if (frame_context.is_inter_predicted()) { |
607 | 1.26k | read_inter_mode_probs(decoder); |
608 | 1.26k | if (frame_context.interpolation_filter == Switchable) |
609 | 951 | read_interp_filter_probs(decoder); |
610 | 1.26k | read_is_inter_probs(decoder); |
611 | 1.26k | frame_reference_mode(frame_context, decoder); |
612 | 1.26k | frame_reference_mode_probs(decoder, frame_context); |
613 | 1.26k | read_y_mode_probs(decoder); |
614 | 1.26k | read_partition_probs(decoder); |
615 | 1.26k | mv_probs(decoder, frame_context); |
616 | 1.26k | } |
617 | 2.15k | TRY_READ(decoder.finish_decode()); |
618 | 0 | return {}; |
619 | 2.15k | } |
620 | | |
621 | | TransformMode Parser::read_tx_mode(BooleanDecoder& decoder, FrameContext const& frame_context) |
622 | 2.15k | { |
623 | 2.15k | if (frame_context.lossless) { |
624 | 1.24k | return TransformMode::Only_4x4; |
625 | 1.24k | } |
626 | | |
627 | 915 | auto tx_mode = decoder.read_literal(2); |
628 | 915 | if (tx_mode == to_underlying(TransformMode::Allow_32x32)) |
629 | 465 | tx_mode += decoder.read_literal(1); |
630 | 915 | return static_cast<TransformMode>(tx_mode); |
631 | 2.15k | } |
632 | | |
633 | | void Parser::tx_mode_probs(BooleanDecoder& decoder) |
634 | 387 | { |
635 | 387 | auto& tx_probs = m_probability_tables->tx_probs(); |
636 | 1.16k | for (auto i = 0; i < TX_SIZE_CONTEXTS; i++) { |
637 | 1.54k | for (auto j = 0; j < TX_SIZES - 3; j++) |
638 | 774 | tx_probs[Transform_8x8][i][j] = diff_update_prob(decoder, tx_probs[Transform_8x8][i][j]); |
639 | 774 | } |
640 | 1.16k | for (auto i = 0; i < TX_SIZE_CONTEXTS; i++) { |
641 | 2.32k | for (auto j = 0; j < TX_SIZES - 2; j++) |
642 | 1.54k | tx_probs[Transform_16x16][i][j] = diff_update_prob(decoder, tx_probs[Transform_16x16][i][j]); |
643 | 774 | } |
644 | 1.16k | for (auto i = 0; i < TX_SIZE_CONTEXTS; i++) { |
645 | 3.09k | for (auto j = 0; j < TX_SIZES - 1; j++) |
646 | 2.32k | tx_probs[Transform_32x32][i][j] = diff_update_prob(decoder, tx_probs[Transform_32x32][i][j]); |
647 | 774 | } |
648 | 387 | } |
649 | | |
650 | | u8 Parser::diff_update_prob(BooleanDecoder& decoder, u8 prob) |
651 | 259k | { |
652 | 259k | auto update_prob = decoder.read_bool(252); |
653 | 259k | if (update_prob) { |
654 | 13.8k | auto delta_prob = decode_term_subexp(decoder); |
655 | 13.8k | prob = inv_remap_prob(delta_prob, prob); |
656 | 13.8k | } |
657 | 259k | return prob; |
658 | 259k | } |
659 | | |
660 | | u8 Parser::decode_term_subexp(BooleanDecoder& decoder) |
661 | 13.8k | { |
662 | 13.8k | if (decoder.read_literal(1) == 0) |
663 | 5.25k | return decoder.read_literal(4); |
664 | 8.57k | if (decoder.read_literal(1) == 0) |
665 | 2.10k | return decoder.read_literal(4) + 16; |
666 | 6.46k | if (decoder.read_literal(1) == 0) |
667 | 812 | return decoder.read_literal(5) + 32; |
668 | | |
669 | 5.65k | auto v = decoder.read_literal(7); |
670 | 5.65k | if (v < 65) |
671 | 215 | return v + 64; |
672 | 5.43k | return (v << 1u) - 1 + decoder.read_literal(1); |
673 | 5.65k | } |
674 | | |
675 | | u8 Parser::inv_remap_prob(u8 delta_prob, u8 prob) |
676 | 13.8k | { |
677 | 13.8k | u8 m = prob - 1; |
678 | 13.8k | auto v = inv_map_table[delta_prob]; |
679 | 13.8k | if ((m << 1u) <= 255) |
680 | 8.89k | return 1 + inv_recenter_nonneg(v, m); |
681 | 4.92k | return 255 - inv_recenter_nonneg(v, 254 - m); |
682 | 13.8k | } |
683 | | |
684 | | u8 Parser::inv_recenter_nonneg(u8 v, u8 m) |
685 | 13.8k | { |
686 | 13.8k | if (v > 2 * m) |
687 | 8.40k | return v; |
688 | 5.41k | if (v & 1u) |
689 | 2.84k | return m - ((v + 1u) >> 1u); |
690 | 2.57k | return m + (v >> 1u); |
691 | 5.41k | } |
692 | | |
693 | | void Parser::read_coef_probs(BooleanDecoder& decoder, TransformMode transform_mode) |
694 | 2.15k | { |
695 | 2.15k | auto max_tx_size = tx_mode_to_biggest_tx_size[to_underlying(transform_mode)]; |
696 | 5.87k | for (u8 transform_size = 0; transform_size <= max_tx_size; transform_size++) { |
697 | 3.71k | auto update_probs = decoder.read_literal(1); |
698 | 3.71k | if (update_probs == 1) { |
699 | 639 | for (auto i = 0; i < 2; i++) { |
700 | 1.27k | for (auto j = 0; j < 2; j++) { |
701 | 5.96k | for (auto k = 0; k < 6; k++) { |
702 | 5.11k | auto max_l = (k == 0) ? 3 : 6; |
703 | 33.2k | for (auto l = 0; l < max_l; l++) { |
704 | 112k | for (auto m = 0; m < 3; m++) { |
705 | 84.3k | auto& prob = m_probability_tables->coef_probs()[transform_size][i][j][k][l][m]; |
706 | 84.3k | prob = diff_update_prob(decoder, prob); |
707 | 84.3k | } |
708 | 28.1k | } |
709 | 5.11k | } |
710 | 852 | } |
711 | 426 | } |
712 | 213 | } |
713 | 3.71k | } |
714 | 2.15k | } |
715 | | |
716 | | void Parser::read_skip_prob(BooleanDecoder& decoder) |
717 | 2.15k | { |
718 | 8.63k | for (auto i = 0; i < SKIP_CONTEXTS; i++) |
719 | 6.47k | m_probability_tables->skip_prob()[i] = diff_update_prob(decoder, m_probability_tables->skip_prob()[i]); |
720 | 2.15k | } |
721 | | |
722 | | void Parser::read_inter_mode_probs(BooleanDecoder& decoder) |
723 | 1.26k | { |
724 | 10.1k | for (auto i = 0; i < INTER_MODE_CONTEXTS; i++) { |
725 | 35.4k | for (auto j = 0; j < INTER_MODES - 1; j++) |
726 | 26.6k | m_probability_tables->inter_mode_probs()[i][j] = diff_update_prob(decoder, m_probability_tables->inter_mode_probs()[i][j]); |
727 | 8.86k | } |
728 | 1.26k | } |
729 | | |
730 | | void Parser::read_interp_filter_probs(BooleanDecoder& decoder) |
731 | 951 | { |
732 | 4.75k | for (auto i = 0; i < INTERP_FILTER_CONTEXTS; i++) { |
733 | 11.4k | for (auto j = 0; j < SWITCHABLE_FILTERS - 1; j++) |
734 | 7.60k | m_probability_tables->interp_filter_probs()[i][j] = diff_update_prob(decoder, m_probability_tables->interp_filter_probs()[i][j]); |
735 | 3.80k | } |
736 | 951 | } |
737 | | |
738 | | void Parser::read_is_inter_probs(BooleanDecoder& decoder) |
739 | 1.26k | { |
740 | 6.33k | for (auto i = 0; i < IS_INTER_CONTEXTS; i++) |
741 | 5.06k | m_probability_tables->is_inter_prob()[i] = diff_update_prob(decoder, m_probability_tables->is_inter_prob()[i]); |
742 | 1.26k | } |
743 | | |
744 | | static void setup_compound_reference_mode(FrameContext& frame_context) |
745 | 933 | { |
746 | 933 | ReferenceFrameType fixed_reference; |
747 | 933 | ReferenceFramePair variable_references; |
748 | 933 | if (frame_context.reference_frame_sign_biases[ReferenceFrameType::LastFrame] == frame_context.reference_frame_sign_biases[ReferenceFrameType::GoldenFrame]) { |
749 | 690 | fixed_reference = ReferenceFrameType::AltRefFrame; |
750 | 690 | variable_references = { ReferenceFrameType::LastFrame, ReferenceFrameType::GoldenFrame }; |
751 | 690 | } else if (frame_context.reference_frame_sign_biases[ReferenceFrameType::LastFrame] == frame_context.reference_frame_sign_biases[ReferenceFrameType::AltRefFrame]) { |
752 | 12 | fixed_reference = ReferenceFrameType::GoldenFrame; |
753 | 12 | variable_references = { ReferenceFrameType::LastFrame, ReferenceFrameType::AltRefFrame }; |
754 | 231 | } else { |
755 | 231 | fixed_reference = ReferenceFrameType::LastFrame; |
756 | 231 | variable_references = { ReferenceFrameType::GoldenFrame, ReferenceFrameType::AltRefFrame }; |
757 | 231 | } |
758 | 933 | frame_context.fixed_reference_type = fixed_reference; |
759 | 933 | frame_context.variable_reference_types = variable_references; |
760 | 933 | } |
761 | | |
762 | | void Parser::frame_reference_mode(FrameContext& frame_context, BooleanDecoder& decoder) |
763 | 1.26k | { |
764 | 1.26k | auto compound_reference_allowed = false; |
765 | 3.80k | for (size_t i = 2; i <= REFS_PER_FRAME; i++) { |
766 | 2.53k | if (frame_context.reference_frame_sign_biases[i] != frame_context.reference_frame_sign_biases[1]) |
767 | 1.38k | compound_reference_allowed = true; |
768 | 2.53k | } |
769 | 1.26k | ReferenceMode reference_mode; |
770 | 1.26k | if (compound_reference_allowed) { |
771 | 1.10k | auto non_single_reference = decoder.read_literal(1); |
772 | 1.10k | if (non_single_reference == 0) { |
773 | 171 | reference_mode = SingleReference; |
774 | 933 | } else { |
775 | 933 | auto reference_select = decoder.read_literal(1); |
776 | 933 | if (reference_select == 0) |
777 | 227 | reference_mode = CompoundReference; |
778 | 706 | else |
779 | 706 | reference_mode = ReferenceModeSelect; |
780 | 933 | } |
781 | 1.10k | } else { |
782 | 163 | reference_mode = SingleReference; |
783 | 163 | } |
784 | 1.26k | frame_context.reference_mode = reference_mode; |
785 | 1.26k | if (reference_mode != SingleReference) |
786 | 933 | setup_compound_reference_mode(frame_context); |
787 | 1.26k | } |
788 | | |
789 | | void Parser::frame_reference_mode_probs(BooleanDecoder& decoder, FrameContext const& frame_context) |
790 | 1.26k | { |
791 | 1.26k | if (frame_context.reference_mode == ReferenceModeSelect) { |
792 | 4.23k | for (auto i = 0; i < COMP_MODE_CONTEXTS; i++) { |
793 | 3.53k | auto& comp_mode_prob = m_probability_tables->comp_mode_prob(); |
794 | 3.53k | comp_mode_prob[i] = diff_update_prob(decoder, comp_mode_prob[i]); |
795 | 3.53k | } |
796 | 706 | } |
797 | 1.26k | if (frame_context.reference_mode != CompoundReference) { |
798 | 6.24k | for (auto i = 0; i < REF_CONTEXTS; i++) { |
799 | 5.20k | auto& single_ref_prob = m_probability_tables->single_ref_prob(); |
800 | 5.20k | single_ref_prob[i][0] = diff_update_prob(decoder, single_ref_prob[i][0]); |
801 | 5.20k | single_ref_prob[i][1] = diff_update_prob(decoder, single_ref_prob[i][1]); |
802 | 5.20k | } |
803 | 1.04k | } |
804 | 1.26k | if (frame_context.reference_mode != SingleReference) { |
805 | 5.59k | for (auto i = 0; i < REF_CONTEXTS; i++) { |
806 | 4.66k | auto& comp_ref_prob = m_probability_tables->comp_ref_prob(); |
807 | 4.66k | comp_ref_prob[i] = diff_update_prob(decoder, comp_ref_prob[i]); |
808 | 4.66k | } |
809 | 933 | } |
810 | 1.26k | } |
811 | | |
812 | | void Parser::read_y_mode_probs(BooleanDecoder& decoder) |
813 | 1.26k | { |
814 | 6.33k | for (auto i = 0; i < BLOCK_SIZE_GROUPS; i++) { |
815 | 50.6k | for (auto j = 0; j < INTRA_MODES - 1; j++) { |
816 | 45.6k | auto& y_mode_probs = m_probability_tables->y_mode_probs(); |
817 | 45.6k | y_mode_probs[i][j] = diff_update_prob(decoder, y_mode_probs[i][j]); |
818 | 45.6k | } |
819 | 5.06k | } |
820 | 1.26k | } |
821 | | |
822 | | void Parser::read_partition_probs(BooleanDecoder& decoder) |
823 | 1.26k | { |
824 | 21.5k | for (auto i = 0; i < PARTITION_CONTEXTS; i++) { |
825 | 81.0k | for (auto j = 0; j < PARTITION_TYPES - 1; j++) { |
826 | 60.8k | auto& partition_probs = m_probability_tables->partition_probs(); |
827 | 60.8k | partition_probs[i][j] = diff_update_prob(decoder, partition_probs[i][j]); |
828 | 60.8k | } |
829 | 20.2k | } |
830 | 1.26k | } |
831 | | |
832 | | void Parser::mv_probs(BooleanDecoder& decoder, FrameContext const& frame_context) |
833 | 1.26k | { |
834 | 5.06k | for (auto j = 0; j < MV_JOINTS - 1; j++) { |
835 | 3.80k | auto& mv_joint_probs = m_probability_tables->mv_joint_probs(); |
836 | 3.80k | mv_joint_probs[j] = update_mv_prob(decoder, mv_joint_probs[j]); |
837 | 3.80k | } |
838 | | |
839 | 3.80k | for (auto i = 0; i < 2; i++) { |
840 | 2.53k | auto& mv_sign_prob = m_probability_tables->mv_sign_prob(); |
841 | 2.53k | mv_sign_prob[i] = update_mv_prob(decoder, mv_sign_prob[i]); |
842 | 27.8k | for (auto j = 0; j < MV_CLASSES - 1; j++) { |
843 | 25.3k | auto& mv_class_probs = m_probability_tables->mv_class_probs(); |
844 | 25.3k | mv_class_probs[i][j] = update_mv_prob(decoder, mv_class_probs[i][j]); |
845 | 25.3k | } |
846 | 2.53k | auto& mv_class0_bit_prob = m_probability_tables->mv_class0_bit_prob(); |
847 | 2.53k | mv_class0_bit_prob[i] = update_mv_prob(decoder, mv_class0_bit_prob[i]); |
848 | 27.8k | for (auto j = 0; j < MV_OFFSET_BITS; j++) { |
849 | 25.3k | auto& mv_bits_prob = m_probability_tables->mv_bits_prob(); |
850 | 25.3k | mv_bits_prob[i][j] = update_mv_prob(decoder, mv_bits_prob[i][j]); |
851 | 25.3k | } |
852 | 2.53k | } |
853 | | |
854 | 3.80k | for (auto i = 0; i < 2; i++) { |
855 | 7.60k | for (auto j = 0; j < CLASS0_SIZE; j++) { |
856 | 20.2k | for (auto k = 0; k < MV_FR_SIZE - 1; k++) { |
857 | 15.2k | auto& mv_class0_fr_probs = m_probability_tables->mv_class0_fr_probs(); |
858 | 15.2k | mv_class0_fr_probs[i][j][k] = update_mv_prob(decoder, mv_class0_fr_probs[i][j][k]); |
859 | 15.2k | } |
860 | 5.06k | } |
861 | 10.1k | for (auto k = 0; k < MV_FR_SIZE - 1; k++) { |
862 | 7.60k | auto& mv_fr_probs = m_probability_tables->mv_fr_probs(); |
863 | 7.60k | mv_fr_probs[i][k] = update_mv_prob(decoder, mv_fr_probs[i][k]); |
864 | 7.60k | } |
865 | 2.53k | } |
866 | | |
867 | 1.26k | if (frame_context.high_precision_motion_vectors_allowed) { |
868 | 2.39k | for (auto i = 0; i < 2; i++) { |
869 | 1.59k | auto& mv_class0_hp_prob = m_probability_tables->mv_class0_hp_prob(); |
870 | 1.59k | auto& mv_hp_prob = m_probability_tables->mv_hp_prob(); |
871 | 1.59k | mv_class0_hp_prob[i] = update_mv_prob(decoder, mv_class0_hp_prob[i]); |
872 | 1.59k | mv_hp_prob[i] = update_mv_prob(decoder, mv_hp_prob[i]); |
873 | 1.59k | } |
874 | 798 | } |
875 | 1.26k | } |
876 | | |
877 | | u8 Parser::update_mv_prob(BooleanDecoder& decoder, u8 prob) |
878 | 85.5k | { |
879 | 85.5k | if (decoder.read_bool(252)) { |
880 | 2.62k | return (decoder.read_literal(7) << 1u) | 1u; |
881 | 2.62k | } |
882 | 82.9k | return prob; |
883 | 85.5k | } |
884 | | |
885 | | static u32 get_tile_offset(u32 tile_start, u32 frame_size_in_blocks, u32 tile_size_log2) |
886 | 8.78k | { |
887 | 8.78k | u32 superblocks = blocks_ceiled_to_superblocks(frame_size_in_blocks); |
888 | 8.78k | u32 offset = superblocks_to_blocks((tile_start * superblocks) >> tile_size_log2); |
889 | 8.78k | return min(offset, frame_size_in_blocks); |
890 | 8.78k | } |
891 | | |
892 | | DecoderErrorOr<void> Parser::decode_tiles(FrameContext& frame_context) |
893 | 2.15k | { |
894 | 2.15k | auto log2_dimensions = frame_context.log2_of_tile_counts; |
895 | 2.15k | auto tile_cols = 1u << log2_dimensions.width(); |
896 | 2.15k | auto tile_rows = 1u << log2_dimensions.height(); |
897 | | |
898 | 2.15k | PartitionContext above_partition_context = DECODER_TRY_ALLOC(PartitionContext::create(superblocks_to_blocks(frame_context.superblock_columns()))); |
899 | 2.15k | NonZeroTokens above_non_zero_tokens = DECODER_TRY_ALLOC(create_non_zero_tokens(blocks_to_sub_blocks(frame_context.columns()), frame_context.color_config.subsampling_x)); |
900 | 2.15k | SegmentationPredictionContext above_segmentation_ids = DECODER_TRY_ALLOC(SegmentationPredictionContext::create(frame_context.columns())); |
901 | | |
902 | | // FIXME: To implement tiled decoding, we'll need to pre-parse the tile positions and sizes into a 2D vector of ReadonlyBytes, |
903 | | // then run through each column of tiles in top to bottom order afterward. Each column can be sent to a worker thread |
904 | | // for execution. Each worker thread will want to create a set of above contexts sized to its tile width, then provide |
905 | | // those to each tile as it decodes them. |
906 | 0 | Vector<Vector<TileContext, 1>, 4> tile_workloads; |
907 | 2.15k | DECODER_TRY_ALLOC(tile_workloads.try_ensure_capacity(tile_cols)); |
908 | 4.34k | for (auto tile_col = 0u; tile_col < tile_cols; tile_col++) { |
909 | 2.19k | tile_workloads.append({}); |
910 | 2.19k | DECODER_TRY_ALLOC(tile_workloads[tile_col].try_ensure_capacity(tile_rows)); |
911 | 2.19k | } |
912 | | |
913 | 4.26k | for (auto tile_row = 0u; tile_row < tile_rows; tile_row++) { |
914 | 4.31k | for (auto tile_col = 0u; tile_col < tile_cols; tile_col++) { |
915 | 2.19k | auto last_tile = (tile_row == tile_rows - 1) && (tile_col == tile_cols - 1); |
916 | 2.19k | size_t tile_size; |
917 | 2.19k | if (last_tile) |
918 | 2.15k | tile_size = frame_context.stream->remaining(); |
919 | 46 | else |
920 | 46 | tile_size = TRY_READ(frame_context.bit_stream.read_bits(32)); |
921 | | |
922 | 2.19k | auto rows_start = get_tile_offset(tile_row, frame_context.rows(), log2_dimensions.height()); |
923 | 2.19k | auto rows_end = get_tile_offset(tile_row + 1, frame_context.rows(), log2_dimensions.height()); |
924 | 2.19k | auto columns_start = get_tile_offset(tile_col, frame_context.columns(), log2_dimensions.width()); |
925 | 2.19k | auto columns_end = get_tile_offset(tile_col + 1, frame_context.columns(), log2_dimensions.width()); |
926 | | |
927 | 2.19k | auto width = columns_end - columns_start; |
928 | 2.19k | auto above_partition_context_for_tile = above_partition_context.span().slice(columns_start, superblocks_to_blocks(blocks_ceiled_to_superblocks(width))); |
929 | 2.19k | auto above_non_zero_tokens_view = create_non_zero_tokens_view(above_non_zero_tokens, blocks_to_sub_blocks(columns_start), blocks_to_sub_blocks(columns_end - columns_start), frame_context.color_config.subsampling_x); |
930 | 2.19k | auto above_segmentation_ids_for_tile = safe_slice(above_segmentation_ids.span(), columns_start, columns_end - columns_start); |
931 | | |
932 | 2.19k | tile_workloads[tile_col].append(TRY(TileContext::try_create(frame_context, tile_size, rows_start, rows_end, columns_start, columns_end, above_partition_context_for_tile, above_non_zero_tokens_view, above_segmentation_ids_for_tile))); |
933 | 2.16k | } |
934 | 2.15k | } |
935 | | |
936 | 2.16k | auto decode_tile_column = [this, tile_rows](auto& column_workloads) -> DecoderErrorOr<void> { |
937 | 2.16k | VERIFY(column_workloads.size() == tile_rows); |
938 | 4.06k | for (auto tile_row = 0u; tile_row < tile_rows; tile_row++) |
939 | 2.16k | TRY(decode_tile(column_workloads[tile_row])); |
940 | 1.90k | return {}; |
941 | 2.16k | }; |
942 | | |
943 | 2.11k | #ifdef VP9_TILE_THREADING |
944 | 2.11k | auto const worker_count = tile_cols - 1; |
945 | | |
946 | 2.11k | if (m_worker_threads.size() < worker_count) { |
947 | 45 | m_worker_threads.clear(); |
948 | 45 | m_worker_threads.ensure_capacity(worker_count); |
949 | 90 | for (auto i = 0u; i < worker_count; i++) |
950 | 45 | m_worker_threads.append(DECODER_TRY_ALLOC(Threading::WorkerThread<DecoderError>::create("Decoder Worker"sv))); |
951 | 45 | } |
952 | 2.11k | VERIFY(m_worker_threads.size() >= worker_count); |
953 | | |
954 | | // Start tile column decoding tasks in thread workers starting from the second column. |
955 | 2.16k | for (auto tile_col = 1u; tile_col < tile_cols; tile_col++) { |
956 | 45 | auto& column_workload = tile_workloads[tile_col]; |
957 | 45 | m_worker_threads[tile_col - 1]->start_task([&decode_tile_column, &column_workload]() -> DecoderErrorOr<void> { |
958 | 45 | return decode_tile_column(column_workload); |
959 | 45 | }); |
960 | 45 | } |
961 | | |
962 | | // Decode the first column in this thread. |
963 | 2.11k | auto result = decode_tile_column(tile_workloads[0]); |
964 | | |
965 | 2.11k | for (auto& worker_thread : m_worker_threads) { |
966 | 45 | auto task_result = worker_thread->wait_until_task_is_finished(); |
967 | 45 | if (!result.is_error() && task_result.is_error()) |
968 | 8 | result = move(task_result); |
969 | 45 | } |
970 | | |
971 | 2.11k | if (result.is_error()) |
972 | 230 | return result; |
973 | | #else |
974 | | for (auto& column_workloads : tile_workloads) |
975 | | TRY(decode_tile_column(column_workloads)); |
976 | | #endif |
977 | | |
978 | | // Sum up all tile contexts' syntax element counters after all decodes have finished. |
979 | 1.89k | for (auto& tile_contexts : tile_workloads) { |
980 | 1.89k | for (auto& tile_context : tile_contexts) { |
981 | 1.89k | *frame_context.counter += *tile_context.counter; |
982 | 1.89k | } |
983 | 1.89k | } |
984 | | |
985 | 1.88k | return {}; |
986 | 2.11k | } |
987 | | |
988 | | DecoderErrorOr<void> Parser::decode_tile(TileContext& tile_context) |
989 | 2.16k | { |
990 | 75.5k | for (auto row = tile_context.rows_start; row < tile_context.rows_end; row += 8) { |
991 | 73.3k | clear_left_context(tile_context); |
992 | 321k | for (auto col = tile_context.columns_start; col < tile_context.columns_end; col += 8) { |
993 | 247k | TRY(decode_partition(tile_context, row, col, Block_64x64)); |
994 | 247k | } |
995 | 73.3k | } |
996 | 2.14k | TRY_READ(tile_context.decoder.finish_decode()); |
997 | 0 | return {}; |
998 | 2.14k | } |
999 | | |
1000 | | void Parser::clear_left_context(TileContext& tile_context) |
1001 | 73.3k | { |
1002 | 73.3k | for (auto& context_for_plane : tile_context.left_non_zero_tokens) |
1003 | 220k | context_for_plane.fill_with(false); |
1004 | 73.3k | tile_context.left_segmentation_ids.fill_with(0); |
1005 | 73.3k | tile_context.left_partition_context.fill_with(0); |
1006 | 73.3k | } |
1007 | | |
1008 | | DecoderErrorOr<void> Parser::decode_partition(TileContext& tile_context, u32 row, u32 column, BlockSubsize subsize) |
1009 | 897k | { |
1010 | 897k | if (row >= tile_context.frame_context.rows() || column >= tile_context.frame_context.columns()) |
1011 | 127k | return {}; |
1012 | 770k | u8 num_8x8 = num_8x8_blocks_wide_lookup[subsize]; |
1013 | 770k | auto half_block_8x8 = num_8x8 >> 1; |
1014 | 770k | bool has_rows = (row + half_block_8x8) < tile_context.frame_context.rows(); |
1015 | 770k | bool has_cols = (column + half_block_8x8) < tile_context.frame_context.columns(); |
1016 | 770k | u32 row_in_tile = row - tile_context.rows_start; |
1017 | 770k | u32 column_in_tile = column - tile_context.columns_start; |
1018 | 770k | auto partition = TreeParser::parse_partition(tile_context.decoder, *m_probability_tables, *tile_context.counter, has_rows, has_cols, subsize, num_8x8, tile_context.above_partition_context, tile_context.left_partition_context.span(), row_in_tile, column_in_tile, !tile_context.frame_context.is_inter_predicted()); |
1019 | | |
1020 | 770k | auto child_subsize = subsize_lookup[partition][subsize]; |
1021 | 770k | if (child_subsize < Block_8x8 || partition == PartitionNone) { |
1022 | 526k | TRY(decode_block(tile_context, row, column, child_subsize)); |
1023 | 526k | } else if (partition == PartitionHorizontal) { |
1024 | 21.5k | TRY(decode_block(tile_context, row, column, child_subsize)); |
1025 | 21.5k | if (has_rows) |
1026 | 11.5k | TRY(decode_block(tile_context, row + half_block_8x8, column, child_subsize)); |
1027 | 222k | } else if (partition == PartitionVertical) { |
1028 | 60.3k | TRY(decode_block(tile_context, row, column, child_subsize)); |
1029 | 60.3k | if (has_cols) |
1030 | 10.1k | TRY(decode_block(tile_context, row, column + half_block_8x8, child_subsize)); |
1031 | 162k | } else { |
1032 | 162k | TRY(decode_partition(tile_context, row, column, child_subsize)); |
1033 | 162k | TRY(decode_partition(tile_context, row, column + half_block_8x8, child_subsize)); |
1034 | 162k | TRY(decode_partition(tile_context, row + half_block_8x8, column, child_subsize)); |
1035 | 162k | TRY(decode_partition(tile_context, row + half_block_8x8, column + half_block_8x8, child_subsize)); |
1036 | 162k | } |
1037 | 770k | if (subsize == Block_8x8 || partition != PartitionSplit) { |
1038 | 608k | auto above_context = 15 >> b_width_log2_lookup[child_subsize]; |
1039 | 608k | auto left_context = 15 >> b_height_log2_lookup[child_subsize]; |
1040 | 2.91M | for (size_t i = 0; i < num_8x8; i++) { |
1041 | 2.30M | tile_context.above_partition_context[column_in_tile + i] = above_context; |
1042 | 2.30M | tile_context.left_partition_context[row_in_tile + i] = left_context; |
1043 | 2.30M | } |
1044 | 608k | } |
1045 | 770k | return {}; |
1046 | 770k | } |
1047 | | |
1048 | | size_t Parser::get_image_index(FrameContext const& frame_context, u32 row, u32 column) const |
1049 | 0 | { |
1050 | 0 | VERIFY(row < frame_context.rows() && column < frame_context.columns()); |
1051 | 0 | return row * frame_context.columns() + column; |
1052 | 0 | } |
1053 | | |
1054 | | DecoderErrorOr<void> Parser::decode_block(TileContext& tile_context, u32 row, u32 column, BlockSubsize subsize) |
1055 | 630k | { |
1056 | 630k | auto above_context = row > 0 ? tile_context.frame_block_contexts().at(row - 1, column) : FrameBlockContext(); |
1057 | 630k | auto left_context = column > tile_context.columns_start ? tile_context.frame_block_contexts().at(row, column - 1) : FrameBlockContext(); |
1058 | 630k | auto block_context = BlockContext::create(tile_context, row, column, subsize); |
1059 | | |
1060 | 630k | mode_info(block_context, above_context, left_context); |
1061 | 630k | auto had_residual_tokens = TRY(residual(block_context, above_context.is_available, left_context.is_available)); |
1062 | 629k | if (block_context.is_inter_predicted() && subsize >= Block_8x8 && !had_residual_tokens) |
1063 | 18.3k | block_context.should_skip_residuals = true; |
1064 | | |
1065 | 2.92M | for (size_t y = 0; y < block_context.contexts_view.height(); y++) { |
1066 | 14.7M | for (size_t x = 0; x < block_context.contexts_view.width(); x++) { |
1067 | 12.4M | auto sub_block_context = FrameBlockContext { true, block_context.should_skip_residuals, block_context.transform_size, block_context.y_prediction_mode(), block_context.sub_block_prediction_modes, block_context.interpolation_filter, block_context.reference_frame_types, block_context.sub_block_motion_vectors, block_context.segment_id }; |
1068 | 12.4M | block_context.contexts_view.at(y, x) = sub_block_context; |
1069 | 12.4M | VERIFY(block_context.frame_block_contexts().at(row + y, column + x).transform_size == sub_block_context.transform_size); |
1070 | 12.4M | } |
1071 | 2.29M | } |
1072 | 629k | return {}; |
1073 | 629k | } |
1074 | | |
1075 | | void Parser::mode_info(BlockContext& block_context, FrameBlockContext above_context, FrameBlockContext left_context) |
1076 | 630k | { |
1077 | 630k | if (block_context.frame_context.is_inter_predicted()) |
1078 | 38.1k | inter_frame_mode_info(block_context, above_context, left_context); |
1079 | 591k | else |
1080 | 591k | intra_frame_mode_info(block_context, above_context, left_context); |
1081 | 630k | } |
1082 | | |
1083 | | void Parser::intra_frame_mode_info(BlockContext& block_context, FrameBlockContext above_context, FrameBlockContext left_context) |
1084 | 591k | { |
1085 | 591k | block_context.reference_frame_types = { ReferenceFrameType::None, ReferenceFrameType::None }; |
1086 | 591k | VERIFY(!block_context.is_inter_predicted()); |
1087 | 591k | set_intra_segment_id(block_context); |
1088 | 591k | block_context.should_skip_residuals = read_should_skip_residuals(block_context, above_context, left_context); |
1089 | 591k | block_context.transform_size = read_tx_size(block_context, above_context, left_context, true); |
1090 | | // FIXME: This if statement is also present in parse_default_intra_mode. The selection of parameters for |
1091 | | // the probability table lookup should be inlined here. |
1092 | 591k | if (block_context.size >= Block_8x8) { |
1093 | 421k | auto mode = TreeParser::parse_default_intra_mode(block_context.decoder, *m_probability_tables, block_context.size, above_context, left_context, block_context.sub_block_prediction_modes, 0, 0); |
1094 | 421k | for (auto& block_sub_mode : block_context.sub_block_prediction_modes) |
1095 | 1.68M | block_sub_mode = mode; |
1096 | 421k | } else { |
1097 | 169k | auto size_in_sub_blocks = block_context.get_size_in_sub_blocks(); |
1098 | 484k | for (auto idy = 0; idy < 2; idy += size_in_sub_blocks.height()) { |
1099 | 871k | for (auto idx = 0; idx < 2; idx += size_in_sub_blocks.width()) { |
1100 | 556k | auto sub_mode = TreeParser::parse_default_intra_mode(block_context.decoder, *m_probability_tables, block_context.size, above_context, left_context, block_context.sub_block_prediction_modes, idx, idy); |
1101 | | |
1102 | 1.16M | for (auto y = 0; y < size_in_sub_blocks.height(); y++) { |
1103 | 1.28M | for (auto x = 0; x < size_in_sub_blocks.width(); x++) { |
1104 | 679k | auto index = (idy + y) * 2 + idx + x; |
1105 | 679k | block_context.sub_block_prediction_modes[index] = sub_mode; |
1106 | 679k | } |
1107 | 606k | } |
1108 | 556k | } |
1109 | 314k | } |
1110 | 169k | } |
1111 | 591k | block_context.uv_prediction_mode = TreeParser::parse_default_uv_mode(block_context.decoder, *m_probability_tables, block_context.y_prediction_mode()); |
1112 | 591k | } |
1113 | | |
1114 | | void Parser::set_intra_segment_id(BlockContext& block_context) |
1115 | 591k | { |
1116 | 591k | if (block_context.frame_context.segmentation_enabled && block_context.frame_context.use_full_segment_id_tree) |
1117 | 161k | block_context.segment_id = TreeParser::parse_segment_id(block_context.decoder, block_context.frame_context.full_segment_id_tree_probabilities); |
1118 | 430k | else |
1119 | 430k | block_context.segment_id = 0; |
1120 | 591k | } |
1121 | | |
1122 | | bool Parser::read_should_skip_residuals(BlockContext& block_context, FrameBlockContext above_context, FrameBlockContext left_context) |
1123 | 630k | { |
1124 | 630k | if (block_context.get_segment_feature(SegmentFeature::SkipResidualsOverride).enabled) |
1125 | 195k | return true; |
1126 | 434k | return TreeParser::parse_skip(block_context.decoder, *m_probability_tables, block_context.counter, above_context, left_context); |
1127 | 630k | } |
1128 | | |
1129 | | TransformSize Parser::read_tx_size(BlockContext& block_context, FrameBlockContext above_context, FrameBlockContext left_context, bool allow_select) |
1130 | 630k | { |
1131 | 630k | auto max_tx_size = max_txsize_lookup[block_context.size]; |
1132 | 630k | if (allow_select && block_context.frame_context.transform_mode == TransformMode::Select && block_context.size >= Block_8x8) |
1133 | 23.4k | return (TreeParser::parse_tx_size(block_context.decoder, *m_probability_tables, block_context.counter, max_tx_size, above_context, left_context)); |
1134 | 606k | return min(max_tx_size, tx_mode_to_biggest_tx_size[to_underlying(block_context.frame_context.transform_mode)]); |
1135 | 630k | } |
1136 | | |
1137 | | void Parser::inter_frame_mode_info(BlockContext& block_context, FrameBlockContext above_context, FrameBlockContext left_context) |
1138 | 38.1k | { |
1139 | 38.1k | set_inter_segment_id(block_context); |
1140 | 38.1k | block_context.should_skip_residuals = read_should_skip_residuals(block_context, above_context, left_context); |
1141 | 38.1k | auto is_inter = read_is_inter(block_context, above_context, left_context); |
1142 | 38.1k | block_context.transform_size = read_tx_size(block_context, above_context, left_context, !block_context.should_skip_residuals || !is_inter); |
1143 | 38.1k | if (is_inter) { |
1144 | 28.8k | inter_block_mode_info(block_context, above_context, left_context); |
1145 | 28.8k | } else { |
1146 | 9.35k | intra_block_mode_info(block_context); |
1147 | 9.35k | } |
1148 | 38.1k | } |
1149 | | |
1150 | | void Parser::set_inter_segment_id(BlockContext& block_context) |
1151 | 38.1k | { |
1152 | 38.1k | if (!block_context.frame_context.segmentation_enabled) { |
1153 | 37.3k | block_context.segment_id = 0; |
1154 | 37.3k | return; |
1155 | 37.3k | } |
1156 | 779 | auto predicted_segment_id = get_segment_id(block_context); |
1157 | 779 | if (!block_context.frame_context.use_full_segment_id_tree) { |
1158 | 23 | block_context.segment_id = predicted_segment_id; |
1159 | 23 | return; |
1160 | 23 | } |
1161 | 756 | if (!block_context.frame_context.use_predicted_segment_id_tree) { |
1162 | 756 | block_context.segment_id = TreeParser::parse_segment_id(block_context.decoder, block_context.frame_context.full_segment_id_tree_probabilities); |
1163 | 756 | return; |
1164 | 756 | } |
1165 | | |
1166 | 0 | auto above_segmentation_id = block_context.tile_context.above_segmentation_ids[block_context.row - block_context.tile_context.rows_start]; |
1167 | 0 | auto left_segmentation_id = block_context.tile_context.left_segmentation_ids[block_context.column - block_context.tile_context.columns_start]; |
1168 | 0 | auto seg_id_predicted = TreeParser::parse_segment_id_predicted(block_context.decoder, block_context.frame_context.predicted_segment_id_tree_probabilities, above_segmentation_id, left_segmentation_id); |
1169 | 0 | if (seg_id_predicted) |
1170 | 0 | block_context.segment_id = predicted_segment_id; |
1171 | 0 | else |
1172 | 0 | block_context.segment_id = TreeParser::parse_segment_id(block_context.decoder, block_context.frame_context.full_segment_id_tree_probabilities); |
1173 | | |
1174 | | // (7.4.1) AboveSegPredContext[ i ] only needs to be set to 0 for i = 0..MiCols-1. |
1175 | | // This is taken care of by the slicing in BlockContext. |
1176 | 0 | block_context.above_segmentation_ids.fill(seg_id_predicted); |
1177 | | // (7.4.1) LeftSegPredContext[ i ] only needs to be set to 0 for i = 0..MiRows-1. |
1178 | | // This is taken care of by the slicing in BlockContext. |
1179 | 0 | block_context.left_segmentation_ids.fill(seg_id_predicted); |
1180 | 0 | } |
1181 | | |
1182 | | u8 Parser::get_segment_id(BlockContext const& block_context) |
1183 | 779 | { |
1184 | 779 | auto bw = num_8x8_blocks_wide_lookup[block_context.size]; |
1185 | 779 | auto bh = num_8x8_blocks_high_lookup[block_context.size]; |
1186 | 779 | auto xmis = min(block_context.frame_context.columns() - block_context.column, (u32)bw); |
1187 | 779 | auto ymis = min(block_context.frame_context.rows() - block_context.row, (u32)bh); |
1188 | 779 | u8 segment = 7; |
1189 | 2.56k | for (size_t y = 0; y < ymis; y++) { |
1190 | 9.32k | for (size_t x = 0; x < xmis; x++) { |
1191 | 7.54k | segment = min(segment, m_previous_block_contexts.index_at(block_context.row + y, block_context.column + x)); |
1192 | 7.54k | } |
1193 | 1.78k | } |
1194 | 779 | return segment; |
1195 | 779 | } |
1196 | | |
1197 | | bool Parser::read_is_inter(BlockContext& block_context, FrameBlockContext above_context, FrameBlockContext left_context) |
1198 | 38.1k | { |
1199 | 38.1k | auto reference_frame_override_feature = block_context.get_segment_feature(SegmentFeature::ReferenceFrameOverride); |
1200 | 38.1k | if (reference_frame_override_feature.enabled) |
1201 | 411 | return reference_frame_override_feature.value != ReferenceFrameType::None; |
1202 | 37.7k | return TreeParser::parse_block_is_inter_predicted(block_context.decoder, *m_probability_tables, block_context.counter, above_context, left_context); |
1203 | 38.1k | } |
1204 | | |
1205 | | void Parser::intra_block_mode_info(BlockContext& block_context) |
1206 | 9.35k | { |
1207 | 9.35k | block_context.reference_frame_types = { ReferenceFrameType::None, ReferenceFrameType::None }; |
1208 | 9.35k | VERIFY(!block_context.is_inter_predicted()); |
1209 | 9.35k | auto& sub_modes = block_context.sub_block_prediction_modes; |
1210 | 9.35k | if (block_context.size >= Block_8x8) { |
1211 | 8.48k | auto mode = TreeParser::parse_intra_mode(block_context.decoder, *m_probability_tables, block_context.counter, block_context.size); |
1212 | 8.48k | for (auto& block_sub_mode : sub_modes) |
1213 | 33.9k | block_sub_mode = mode; |
1214 | 8.48k | } else { |
1215 | 870 | auto size_in_sub_blocks = block_context.get_size_in_sub_blocks(); |
1216 | 2.29k | for (auto idy = 0; idy < 2; idy += size_in_sub_blocks.height()) { |
1217 | 3.59k | for (auto idx = 0; idx < 2; idx += size_in_sub_blocks.width()) { |
1218 | 2.17k | auto sub_intra_mode = TreeParser::parse_sub_intra_mode(block_context.decoder, *m_probability_tables, block_context.counter); |
1219 | 4.97k | for (auto y = 0; y < size_in_sub_blocks.height(); y++) { |
1220 | 6.28k | for (auto x = 0; x < size_in_sub_blocks.width(); x++) |
1221 | 3.48k | sub_modes[(idy + y) * 2 + idx + x] = sub_intra_mode; |
1222 | 2.80k | } |
1223 | 2.17k | } |
1224 | 1.42k | } |
1225 | 870 | } |
1226 | 9.35k | block_context.uv_prediction_mode = TreeParser::parse_uv_mode(block_context.decoder, *m_probability_tables, block_context.counter, block_context.y_prediction_mode()); |
1227 | 9.35k | } |
1228 | | |
1229 | | static void select_best_reference_motion_vectors(BlockContext& block_context, MotionVectorPair reference_motion_vectors, BlockMotionVectorCandidates& candidates, ReferenceIndex); |
1230 | | |
1231 | | void Parser::inter_block_mode_info(BlockContext& block_context, FrameBlockContext above_context, FrameBlockContext left_context) |
1232 | 28.8k | { |
1233 | 28.8k | read_ref_frames(block_context, above_context, left_context); |
1234 | 28.8k | VERIFY(block_context.is_inter_predicted()); |
1235 | | |
1236 | 28.8k | BlockMotionVectorCandidates motion_vector_candidates; |
1237 | 28.8k | auto reference_motion_vectors = find_reference_motion_vectors(block_context, block_context.reference_frame_types.primary, -1); |
1238 | 28.8k | select_best_reference_motion_vectors(block_context, reference_motion_vectors, motion_vector_candidates, ReferenceIndex::Primary); |
1239 | 28.8k | if (block_context.is_compound()) { |
1240 | 11.8k | auto reference_motion_vectors = find_reference_motion_vectors(block_context, block_context.reference_frame_types.secondary, -1); |
1241 | 11.8k | select_best_reference_motion_vectors(block_context, reference_motion_vectors, motion_vector_candidates, ReferenceIndex::Secondary); |
1242 | 11.8k | } |
1243 | | |
1244 | 28.8k | if (block_context.get_segment_feature(SegmentFeature::SkipResidualsOverride).enabled) { |
1245 | 0 | block_context.y_prediction_mode() = PredictionMode::ZeroMv; |
1246 | 28.8k | } else if (block_context.size >= Block_8x8) { |
1247 | 22.6k | block_context.y_prediction_mode() = TreeParser::parse_inter_mode(block_context.decoder, *m_probability_tables, block_context.counter, block_context.mode_context[block_context.reference_frame_types.primary]); |
1248 | 22.6k | } |
1249 | 28.8k | if (block_context.frame_context.interpolation_filter == Switchable) |
1250 | 18.3k | block_context.interpolation_filter = TreeParser::parse_interpolation_filter(block_context.decoder, *m_probability_tables, block_context.counter, above_context, left_context); |
1251 | 10.4k | else |
1252 | 10.4k | block_context.interpolation_filter = block_context.frame_context.interpolation_filter; |
1253 | 28.8k | if (block_context.size < Block_8x8) { |
1254 | 6.20k | auto size_in_sub_blocks = block_context.get_size_in_sub_blocks(); |
1255 | 16.8k | for (auto idy = 0; idy < 2; idy += size_in_sub_blocks.height()) { |
1256 | 26.5k | for (auto idx = 0; idx < 2; idx += size_in_sub_blocks.width()) { |
1257 | 15.9k | block_context.y_prediction_mode() = TreeParser::parse_inter_mode(block_context.decoder, *m_probability_tables, block_context.counter, block_context.mode_context[block_context.reference_frame_types.primary]); |
1258 | 15.9k | if (block_context.y_prediction_mode() == PredictionMode::NearestMv || block_context.y_prediction_mode() == PredictionMode::NearMv) { |
1259 | 8.76k | select_best_sub_block_reference_motion_vectors(block_context, motion_vector_candidates, idy * 2 + idx, ReferenceIndex::Primary); |
1260 | 8.76k | if (block_context.is_compound()) |
1261 | 4.51k | select_best_sub_block_reference_motion_vectors(block_context, motion_vector_candidates, idy * 2 + idx, ReferenceIndex::Secondary); |
1262 | 8.76k | } |
1263 | 15.9k | auto new_motion_vector_pair = get_motion_vector(block_context, motion_vector_candidates); |
1264 | 35.4k | for (auto y = 0; y < size_in_sub_blocks.height(); y++) { |
1265 | 44.3k | for (auto x = 0; x < size_in_sub_blocks.width(); x++) { |
1266 | 24.8k | auto sub_block_index = (idy + y) * 2 + idx + x; |
1267 | 24.8k | block_context.sub_block_motion_vectors[sub_block_index] = new_motion_vector_pair; |
1268 | 24.8k | } |
1269 | 19.5k | } |
1270 | 15.9k | } |
1271 | 10.6k | } |
1272 | 6.20k | return; |
1273 | 6.20k | } |
1274 | 22.6k | auto new_motion_vector_pair = get_motion_vector(block_context, motion_vector_candidates); |
1275 | 113k | for (auto block = 0; block < 4; block++) |
1276 | 90.4k | block_context.sub_block_motion_vectors[block] = new_motion_vector_pair; |
1277 | 22.6k | } |
1278 | | |
1279 | | void Parser::read_ref_frames(BlockContext& block_context, FrameBlockContext above_context, FrameBlockContext left_context) |
1280 | 28.8k | { |
1281 | 28.8k | auto reference_frame_override_feature = block_context.get_segment_feature(SegmentFeature::ReferenceFrameOverride); |
1282 | 28.8k | if (reference_frame_override_feature.enabled) { |
1283 | 45 | block_context.reference_frame_types = { static_cast<ReferenceFrameType>(reference_frame_override_feature.value), ReferenceFrameType::None }; |
1284 | 45 | return; |
1285 | 45 | } |
1286 | | |
1287 | 28.7k | ReferenceMode compound_mode = block_context.frame_context.reference_mode; |
1288 | 28.7k | auto fixed_reference = block_context.frame_context.fixed_reference_type; |
1289 | 28.7k | if (compound_mode == ReferenceModeSelect) |
1290 | 13.3k | compound_mode = TreeParser::parse_comp_mode(block_context.decoder, *m_probability_tables, block_context.counter, fixed_reference, above_context, left_context); |
1291 | 28.7k | if (compound_mode == CompoundReference) { |
1292 | 11.8k | auto variable_references = block_context.frame_context.variable_reference_types; |
1293 | | |
1294 | 11.8k | auto fixed_reference_index = ReferenceIndex::Primary; |
1295 | 11.8k | auto variable_reference_index = ReferenceIndex::Secondary; |
1296 | 11.8k | if (block_context.frame_context.reference_frame_sign_biases[fixed_reference]) |
1297 | 6.69k | swap(fixed_reference_index, variable_reference_index); |
1298 | | |
1299 | 11.8k | auto variable_reference_selection = TreeParser::parse_comp_ref(block_context.decoder, *m_probability_tables, block_context.counter, fixed_reference, variable_references, variable_reference_index, above_context, left_context); |
1300 | | |
1301 | 11.8k | block_context.reference_frame_types[fixed_reference_index] = fixed_reference; |
1302 | 11.8k | block_context.reference_frame_types[variable_reference_index] = variable_references[variable_reference_selection]; |
1303 | 11.8k | return; |
1304 | 11.8k | } |
1305 | | |
1306 | | // FIXME: Maybe consolidate this into a tree. Context is different between part 1 and 2 but still, it would look nice here. |
1307 | 16.9k | ReferenceFrameType primary_type = ReferenceFrameType::LastFrame; |
1308 | 16.9k | auto single_ref_p1 = TreeParser::parse_single_ref_part_1(block_context.decoder, *m_probability_tables, block_context.counter, above_context, left_context); |
1309 | 16.9k | if (single_ref_p1) { |
1310 | 6.36k | auto single_ref_p2 = TreeParser::parse_single_ref_part_2(block_context.decoder, *m_probability_tables, block_context.counter, above_context, left_context); |
1311 | 6.36k | primary_type = single_ref_p2 ? ReferenceFrameType::AltRefFrame : ReferenceFrameType::GoldenFrame; |
1312 | 6.36k | } |
1313 | 16.9k | block_context.reference_frame_types = { primary_type, ReferenceFrameType::None }; |
1314 | 16.9k | } |
1315 | | |
1316 | | // assign_mv( isCompound ) in the spec. |
1317 | | MotionVectorPair Parser::get_motion_vector(BlockContext const& block_context, BlockMotionVectorCandidates const& candidates) |
1318 | 38.5k | { |
1319 | 38.5k | MotionVectorPair result; |
1320 | 55.2k | auto read_one = [&](ReferenceIndex index) -> void { |
1321 | 55.2k | switch (block_context.y_prediction_mode()) { |
1322 | 19.8k | case PredictionMode::NewMv: |
1323 | 19.8k | result[index] = read_motion_vector(block_context, candidates, index); |
1324 | 19.8k | break; |
1325 | 23.1k | case PredictionMode::NearestMv: |
1326 | 23.1k | result[index] = candidates[index].nearest_vector; |
1327 | 23.1k | break; |
1328 | 7.76k | case PredictionMode::NearMv: |
1329 | 7.76k | result[index] = candidates[index].near_vector; |
1330 | 7.76k | break; |
1331 | 4.46k | default: |
1332 | 4.46k | result[index] = {}; |
1333 | 4.46k | break; |
1334 | 55.2k | } |
1335 | 55.2k | return; |
1336 | 55.2k | }; |
1337 | 38.5k | read_one(ReferenceIndex::Primary); |
1338 | 38.5k | if (block_context.is_compound()) |
1339 | 16.7k | read_one(ReferenceIndex::Secondary); |
1340 | 38.5k | return result; |
1341 | 38.5k | } |
1342 | | |
1343 | | // use_mv_hp( deltaMv ) in the spec. |
1344 | | static bool should_use_high_precision_motion_vector(MotionVector const& delta_vector) |
1345 | 46.2k | { |
1346 | 46.2k | return (abs(delta_vector.row()) >> 3) < COMPANDED_MVREF_THRESH && (abs(delta_vector.column()) >> 3) < COMPANDED_MVREF_THRESH; |
1347 | 46.2k | } |
1348 | | |
1349 | | // read_mv( ref ) in the spec. |
1350 | | MotionVector Parser::read_motion_vector(BlockContext const& block_context, BlockMotionVectorCandidates const& candidates, ReferenceIndex reference_index) |
1351 | 19.8k | { |
1352 | 19.8k | auto use_high_precision = block_context.frame_context.high_precision_motion_vectors_allowed && should_use_high_precision_motion_vector(candidates[reference_index].best_vector); |
1353 | 19.8k | MotionVector delta_vector; |
1354 | 19.8k | auto joint = TreeParser::parse_motion_vector_joint(block_context.decoder, *m_probability_tables, block_context.counter); |
1355 | 19.8k | if ((joint & MotionVectorNonZeroRow) != 0) |
1356 | 8.96k | delta_vector.set_row(read_single_motion_vector_component(block_context.decoder, block_context.counter, 0, use_high_precision)); |
1357 | 19.8k | if ((joint & MotionVectorNonZeroColumn) != 0) |
1358 | 11.3k | delta_vector.set_column(read_single_motion_vector_component(block_context.decoder, block_context.counter, 1, use_high_precision)); |
1359 | | |
1360 | 19.8k | return candidates[reference_index].best_vector + delta_vector; |
1361 | 19.8k | } |
1362 | | |
1363 | | // read_mv_component( comp ) in the spec. |
1364 | | i32 Parser::read_single_motion_vector_component(BooleanDecoder& decoder, SyntaxElementCounter& counter, u8 component, bool use_high_precision) |
1365 | 20.2k | { |
1366 | 20.2k | auto mv_sign = TreeParser::parse_motion_vector_sign(decoder, *m_probability_tables, counter, component); |
1367 | 20.2k | auto mv_class = TreeParser::parse_motion_vector_class(decoder, *m_probability_tables, counter, component); |
1368 | 20.2k | u32 magnitude; |
1369 | 20.2k | if (mv_class == MvClass0) { |
1370 | 16.6k | auto mv_class0_bit = TreeParser::parse_motion_vector_class0_bit(decoder, *m_probability_tables, counter, component); |
1371 | 16.6k | auto mv_class0_fr = TreeParser::parse_motion_vector_class0_fr(decoder, *m_probability_tables, counter, component, mv_class0_bit); |
1372 | 16.6k | auto mv_class0_hp = TreeParser::parse_motion_vector_class0_hp(decoder, *m_probability_tables, counter, component, use_high_precision); |
1373 | 16.6k | magnitude = ((mv_class0_bit << 3) | (mv_class0_fr << 1) | mv_class0_hp) + 1; |
1374 | 16.6k | } else { |
1375 | 3.64k | u32 bits = 0; |
1376 | 16.2k | for (u8 i = 0; i < mv_class; i++) { |
1377 | 12.6k | auto mv_bit = TreeParser::parse_motion_vector_bit(decoder, *m_probability_tables, counter, component, i); |
1378 | 12.6k | bits |= mv_bit << i; |
1379 | 12.6k | } |
1380 | 3.64k | magnitude = CLASS0_SIZE << (mv_class + 2); |
1381 | 3.64k | auto mv_fr = TreeParser::parse_motion_vector_fr(decoder, *m_probability_tables, counter, component); |
1382 | 3.64k | auto mv_hp = TreeParser::parse_motion_vector_hp(decoder, *m_probability_tables, counter, component, use_high_precision); |
1383 | 3.64k | magnitude += ((bits << 3) | (mv_fr << 1) | mv_hp) + 1; |
1384 | 3.64k | } |
1385 | 20.2k | return (mv_sign ? -1 : 1) * static_cast<i32>(magnitude); |
1386 | 20.2k | } |
1387 | | |
1388 | | static TransformSize get_uv_transform_size(TransformSize transform_size, BlockSubsize size_for_plane) |
1389 | 1.88M | { |
1390 | 1.88M | return min(transform_size, max_txsize_lookup[size_for_plane]); |
1391 | 1.88M | } |
1392 | | |
1393 | | static TransformSet select_transform_type(BlockContext const& block_context, u8 plane, TransformSize transform_size, u32 block_index) |
1394 | 12.8M | { |
1395 | 12.8M | if (plane > 0 || transform_size == Transform_32x32) |
1396 | 6.91M | return TransformSet { TransformType::DCT, TransformType::DCT }; |
1397 | 5.88M | if (transform_size == Transform_4x4) { |
1398 | 5.18M | if (block_context.frame_context.lossless || block_context.is_inter_predicted()) |
1399 | 861k | return TransformSet { TransformType::DCT, TransformType::DCT }; |
1400 | | |
1401 | 4.32M | return mode_to_txfm_map[to_underlying(block_context.size < Block_8x8 ? block_context.sub_block_prediction_modes[block_index] : block_context.y_prediction_mode())]; |
1402 | 5.18M | } |
1403 | | |
1404 | 704k | return mode_to_txfm_map[to_underlying(block_context.y_prediction_mode())]; |
1405 | 5.88M | } |
1406 | | |
1407 | | DecoderErrorOr<bool> Parser::residual(BlockContext& block_context, bool has_block_above, bool has_block_left) |
1408 | 630k | { |
1409 | 630k | bool block_had_non_zero_tokens = false; |
1410 | 630k | Array<u8, 1024> token_cache; |
1411 | 2.52M | for (u8 plane = 0; plane < 3; plane++) { |
1412 | 1.89M | auto plane_subsampling_x = (plane > 0) ? block_context.frame_context.color_config.subsampling_x : false; |
1413 | 1.89M | auto plane_subsampling_y = (plane > 0) ? block_context.frame_context.color_config.subsampling_y : false; |
1414 | 1.89M | auto plane_size = get_subsampled_block_size(block_context.size, plane_subsampling_x, plane_subsampling_y); |
1415 | 1.89M | if (plane_size == Block_Invalid) { |
1416 | 20 | return DecoderError::corrupted("Invalid block size"sv); |
1417 | 20 | } |
1418 | 1.88M | auto transform_size = get_uv_transform_size(block_context.transform_size, plane_size); |
1419 | 1.88M | auto transform_size_in_sub_blocks = transform_size_to_sub_blocks(transform_size); |
1420 | 1.88M | auto block_size_in_sub_blocks = block_size_to_sub_blocks(plane_size); |
1421 | | |
1422 | 1.88M | auto base_x_in_pixels = (blocks_to_pixels(block_context.column)) >> plane_subsampling_x; |
1423 | 1.88M | auto base_y_in_pixels = (blocks_to_pixels(block_context.row)) >> plane_subsampling_y; |
1424 | 1.88M | if (block_context.is_inter_predicted()) { |
1425 | 86.4k | if (block_context.size < Block_8x8) { |
1426 | 43.4k | for (auto y = 0; y < block_size_in_sub_blocks.height(); y++) { |
1427 | 62.0k | for (auto x = 0; x < block_size_in_sub_blocks.width(); x++) { |
1428 | 37.2k | TRY(m_decoder.predict_inter(plane, block_context, base_x_in_pixels + sub_blocks_to_pixels(x), base_y_in_pixels + sub_blocks_to_pixels(y), sub_blocks_to_pixels(1), sub_blocks_to_pixels(1), (y * block_size_in_sub_blocks.width()) + x)); |
1429 | 37.2k | } |
1430 | 24.8k | } |
1431 | 67.8k | } else { |
1432 | 67.8k | TRY(m_decoder.predict_inter(plane, block_context, base_x_in_pixels, base_y_in_pixels, sub_blocks_to_pixels(block_size_in_sub_blocks.width()), sub_blocks_to_pixels(block_size_in_sub_blocks.height()), 0)); |
1433 | 67.8k | } |
1434 | 86.4k | } |
1435 | | |
1436 | 1.88M | auto frame_right_in_pixels = (blocks_to_pixels(block_context.frame_context.columns())) >> plane_subsampling_x; |
1437 | 1.88M | auto frame_bottom_in_pixels = (blocks_to_pixels(block_context.frame_context.rows())) >> plane_subsampling_y; |
1438 | | |
1439 | 1.88M | auto sub_block_index = 0; |
1440 | 6.26M | for (u32 y = 0; y < block_size_in_sub_blocks.height(); y += transform_size_in_sub_blocks) { |
1441 | 27.4M | for (u32 x = 0; x < block_size_in_sub_blocks.width(); x += transform_size_in_sub_blocks) { |
1442 | 23.0M | auto transform_x_in_px = base_x_in_pixels + sub_blocks_to_pixels(x); |
1443 | 23.0M | auto transform_y_in_px = base_y_in_pixels + sub_blocks_to_pixels(y); |
1444 | | |
1445 | 23.0M | auto sub_block_had_non_zero_tokens = false; |
1446 | 23.0M | if (transform_x_in_px < frame_right_in_pixels && transform_y_in_px < frame_bottom_in_pixels) { |
1447 | 20.9M | if (!block_context.is_inter_predicted()) |
1448 | 20.3M | TRY(m_decoder.predict_intra(plane, block_context, transform_x_in_px, transform_y_in_px, has_block_left || x > 0, has_block_above || y > 0, (x + transform_size_in_sub_blocks) < block_size_in_sub_blocks.width(), transform_size, sub_block_index)); |
1449 | 20.9M | if (!block_context.should_skip_residuals) { |
1450 | 12.8M | auto transform_set = select_transform_type(block_context, plane, transform_size, sub_block_index); |
1451 | 12.8M | sub_block_had_non_zero_tokens = tokens(block_context, plane, x, y, transform_size, transform_set, token_cache); |
1452 | 12.8M | block_had_non_zero_tokens = block_had_non_zero_tokens || sub_block_had_non_zero_tokens; |
1453 | 12.8M | TRY(m_decoder.reconstruct(plane, block_context, transform_x_in_px, transform_y_in_px, transform_size, transform_set)); |
1454 | 12.8M | } |
1455 | 20.9M | } |
1456 | | |
1457 | 23.0M | auto& above_sub_block_tokens = block_context.above_non_zero_tokens[plane]; |
1458 | 23.0M | auto transform_right_in_sub_blocks = min(x + transform_size_in_sub_blocks, above_sub_block_tokens.size()); |
1459 | 53.5M | for (size_t inside_x = x; inside_x < transform_right_in_sub_blocks; inside_x++) |
1460 | 30.4M | above_sub_block_tokens[inside_x] = sub_block_had_non_zero_tokens; |
1461 | | |
1462 | 23.0M | auto& left_sub_block_context = block_context.left_non_zero_tokens[plane]; |
1463 | 23.0M | auto transform_bottom_in_sub_blocks = min(y + transform_size_in_sub_blocks, left_sub_block_context.size()); |
1464 | 55.9M | for (size_t inside_y = y; inside_y < transform_bottom_in_sub_blocks; inside_y++) |
1465 | 32.8M | left_sub_block_context[inside_y] = sub_block_had_non_zero_tokens; |
1466 | | |
1467 | 23.0M | sub_block_index++; |
1468 | 23.0M | } |
1469 | 4.37M | } |
1470 | 1.88M | } |
1471 | 629k | return block_had_non_zero_tokens; |
1472 | 630k | } |
1473 | | |
1474 | | static u16 const* get_scan(TransformSize transform_size, TransformSet transform_set) |
1475 | 12.8M | { |
1476 | 12.8M | constexpr TransformSet adst_dct { TransformType::ADST, TransformType::DCT }; |
1477 | 12.8M | constexpr TransformSet dct_adst { TransformType::DCT, TransformType::ADST }; |
1478 | | |
1479 | 12.8M | if (transform_size == Transform_4x4) { |
1480 | 10.9M | if (transform_set == adst_dct) |
1481 | 90.8k | return row_scan_4x4; |
1482 | 10.8M | if (transform_set == dct_adst) |
1483 | 167k | return col_scan_4x4; |
1484 | 10.6M | return default_scan_4x4; |
1485 | 10.8M | } |
1486 | 1.86M | if (transform_size == Transform_8x8) { |
1487 | 959k | if (transform_set == adst_dct) |
1488 | 25.1k | return row_scan_8x8; |
1489 | 934k | if (transform_set == dct_adst) |
1490 | 39.9k | return col_scan_8x8; |
1491 | 894k | return default_scan_8x8; |
1492 | 934k | } |
1493 | 903k | if (transform_size == Transform_16x16) { |
1494 | 284k | if (transform_set == adst_dct) |
1495 | 5.46k | return row_scan_16x16; |
1496 | 279k | if (transform_set == dct_adst) |
1497 | 9.86k | return col_scan_16x16; |
1498 | 269k | return default_scan_16x16; |
1499 | 279k | } |
1500 | 618k | return default_scan_32x32; |
1501 | 903k | } |
1502 | | |
1503 | | bool Parser::tokens(BlockContext& block_context, size_t plane, u32 sub_block_column, u32 sub_block_row, TransformSize transform_size, TransformSet transform_set, Array<u8, 1024> token_cache) |
1504 | 12.8M | { |
1505 | 12.8M | block_context.residual_tokens.fill(0); |
1506 | | |
1507 | 12.8M | auto const* scan = get_scan(transform_size, transform_set); |
1508 | | |
1509 | 12.8M | auto check_for_more_coefficients = true; |
1510 | 12.8M | u16 coef_index = 0; |
1511 | 12.8M | u16 transform_pixel_count = 16 << (transform_size << 1); |
1512 | 25.6M | for (; coef_index < transform_pixel_count; coef_index++) { |
1513 | 25.5M | auto band = (transform_size == Transform_4x4) ? coefband_4x4[coef_index] : coefband_8x8plus[coef_index]; |
1514 | 25.5M | auto token_position = scan[coef_index]; |
1515 | 25.5M | TokensContext tokens_context; |
1516 | 25.5M | if (coef_index == 0) |
1517 | 12.8M | tokens_context = TreeParser::get_context_for_first_token(block_context.above_non_zero_tokens, block_context.left_non_zero_tokens, transform_size, plane, sub_block_column, sub_block_row, block_context.is_inter_predicted(), band); |
1518 | 12.7M | else |
1519 | 12.7M | tokens_context = TreeParser::get_context_for_other_tokens(token_cache, transform_size, transform_set, plane, token_position, block_context.is_inter_predicted(), band); |
1520 | | |
1521 | 25.5M | if (check_for_more_coefficients && !TreeParser::parse_more_coefficients(block_context.decoder, *m_probability_tables, block_context.counter, tokens_context)) |
1522 | 12.7M | break; |
1523 | | |
1524 | 12.8M | auto token = TreeParser::parse_token(block_context.decoder, *m_probability_tables, block_context.counter, tokens_context); |
1525 | 12.8M | token_cache[token_position] = energy_class[token]; |
1526 | | |
1527 | 12.8M | i32 coef; |
1528 | 12.8M | if (token == ZeroToken) { |
1529 | 6.17M | coef = 0; |
1530 | 6.17M | check_for_more_coefficients = false; |
1531 | 6.68M | } else { |
1532 | 6.68M | coef = read_coef(block_context.decoder, block_context.frame_context.color_config.bit_depth, token); |
1533 | 6.68M | check_for_more_coefficients = true; |
1534 | 6.68M | } |
1535 | 12.8M | block_context.residual_tokens[token_position] = coef; |
1536 | 12.8M | } |
1537 | | |
1538 | 12.8M | return coef_index > 0; |
1539 | 12.8M | } |
1540 | | |
1541 | | i32 Parser::read_coef(BooleanDecoder& decoder, u8 bit_depth, Token token) |
1542 | 6.68M | { |
1543 | 6.68M | auto cat = extra_bits[token][0]; |
1544 | 6.68M | auto num_extra = extra_bits[token][1]; |
1545 | 6.68M | i32 coef = extra_bits[token][2]; |
1546 | 6.68M | if (token == DctValCat6) { |
1547 | 249k | for (size_t e = 0; e < (u8)(bit_depth - 8); e++) { |
1548 | 87.5k | auto high_bit = decoder.read_bool(255); |
1549 | 87.5k | coef += high_bit << (5 + bit_depth - e); |
1550 | 87.5k | } |
1551 | 161k | } |
1552 | 9.91M | for (size_t e = 0; e < num_extra; e++) { |
1553 | 3.23M | auto coef_bit = decoder.read_bool(cat_probs[cat][e]); |
1554 | 3.23M | coef += coef_bit << (num_extra - 1 - e); |
1555 | 3.23M | } |
1556 | 6.68M | bool sign_bit = decoder.read_literal(1); |
1557 | 6.68M | coef = sign_bit ? -coef : coef; |
1558 | 6.68M | return coef; |
1559 | 6.68M | } |
1560 | | |
1561 | | // is_inside( candidateR, candidateC ) in the spec. |
1562 | | static bool motion_vector_is_inside_tile(TileContext const& tile_context, MotionVector vector) |
1563 | 850k | { |
1564 | 850k | if (vector.row() < 0) |
1565 | 359k | return false; |
1566 | 490k | if (vector.column() < 0) |
1567 | 189k | return false; |
1568 | 300k | u32 row_positive = vector.row(); |
1569 | 300k | u32 column_positive = vector.column(); |
1570 | 300k | return row_positive < tile_context.frame_context.rows() && column_positive >= tile_context.columns_start && column_positive < tile_context.columns_end; |
1571 | 490k | } |
1572 | | |
1573 | | // add_mv_ref_list( refList ) in the spec. |
1574 | | static void add_motion_vector_to_list_deduped(MotionVector const& vector, Vector<MotionVector, 2>& list) |
1575 | 181k | { |
1576 | 181k | if (list.size() >= 2) |
1577 | 49.4k | return; |
1578 | 131k | if (list.size() == 1 && vector == list[0]) |
1579 | 55.1k | return; |
1580 | | |
1581 | 76.7k | list.append(vector); |
1582 | 76.7k | } |
1583 | | |
1584 | | // get_block_mv( candidateR, candidateC, refList, usePrev ) in the spec. |
1585 | | MotionVectorCandidate Parser::get_motion_vector_from_current_or_previous_frame(BlockContext const& block_context, MotionVector candidate_vector, ReferenceIndex reference_index, bool use_prev) |
1586 | 500k | { |
1587 | 500k | if (use_prev) { |
1588 | 78.4k | auto const& prev_context = m_previous_block_contexts.at(candidate_vector.row(), candidate_vector.column()); |
1589 | 78.4k | return { prev_context.ref_frames[reference_index], prev_context.primary_motion_vector_pair[reference_index] }; |
1590 | 78.4k | } |
1591 | | |
1592 | 421k | auto const& current_context = block_context.frame_block_contexts().at(candidate_vector.row(), candidate_vector.column()); |
1593 | 421k | return { current_context.ref_frames[reference_index], current_context.primary_motion_vector_pair()[reference_index] }; |
1594 | 500k | } |
1595 | | |
1596 | | // if_same_ref_frame_add_mv( candidateR, candidateC, refFrame, usePrev ) in the spec. |
1597 | | void Parser::add_motion_vector_if_reference_frame_type_is_same(BlockContext const& block_context, MotionVector candidate_vector, ReferenceFrameType ref_frame, Vector<MotionVector, 2>& list, bool use_prev) |
1598 | 106k | { |
1599 | 213k | for (auto i = 0u; i < 2; i++) { |
1600 | 166k | auto candidate = get_motion_vector_from_current_or_previous_frame(block_context, candidate_vector, static_cast<ReferenceIndex>(i), use_prev); |
1601 | 166k | if (candidate.type == ref_frame) { |
1602 | 59.9k | add_motion_vector_to_list_deduped(candidate.vector, list); |
1603 | 59.9k | return; |
1604 | 59.9k | } |
1605 | 166k | } |
1606 | 106k | } |
1607 | | |
1608 | | // scale_mv( refList, refFrame ) in the spec. |
1609 | | static void apply_sign_bias_to_motion_vector(FrameContext const& frame_context, MotionVectorCandidate& candidate, ReferenceFrameType ref_frame) |
1610 | 75.5k | { |
1611 | 75.5k | if (frame_context.reference_frame_sign_biases[candidate.type] != frame_context.reference_frame_sign_biases[ref_frame]) |
1612 | 58.5k | candidate.vector *= -1; |
1613 | 75.5k | } |
1614 | | |
1615 | | // if_diff_ref_frame_add_mv( candidateR, candidateC, refFrame, usePrev ) in the spec. |
1616 | | void Parser::add_motion_vector_if_reference_frame_type_is_different(BlockContext const& block_context, MotionVector candidate_vector, ReferenceFrameType ref_frame, Vector<MotionVector, 2>& list, bool use_prev) |
1617 | 166k | { |
1618 | 166k | auto first_candidate = get_motion_vector_from_current_or_previous_frame(block_context, candidate_vector, ReferenceIndex::Primary, use_prev); |
1619 | 166k | if (first_candidate.type > ReferenceFrameType::None && first_candidate.type != ref_frame) { |
1620 | 54.4k | apply_sign_bias_to_motion_vector(block_context.frame_context, first_candidate, ref_frame); |
1621 | 54.4k | add_motion_vector_to_list_deduped(first_candidate.vector, list); |
1622 | 54.4k | } |
1623 | | |
1624 | 166k | auto second_candidate = get_motion_vector_from_current_or_previous_frame(block_context, candidate_vector, ReferenceIndex::Secondary, use_prev); |
1625 | 166k | auto mvs_are_same = first_candidate.vector == second_candidate.vector; |
1626 | 166k | if (second_candidate.type > ReferenceFrameType::None && second_candidate.type != ref_frame && !mvs_are_same) { |
1627 | 21.1k | apply_sign_bias_to_motion_vector(block_context.frame_context, second_candidate, ref_frame); |
1628 | 21.1k | add_motion_vector_to_list_deduped(second_candidate.vector, list); |
1629 | 21.1k | } |
1630 | 166k | } |
1631 | | |
1632 | | // This function handles both clamp_mv_row( mvec, border ) and clamp_mv_col( mvec, border ) in the spec. |
1633 | | static MotionVector clamp_motion_vector(BlockContext const& block_context, MotionVector vector, i32 border) |
1634 | 266k | { |
1635 | 266k | i32 blocks_high = num_8x8_blocks_high_lookup[block_context.size]; |
1636 | | // Casts must be done here to prevent subtraction underflow from wrapping the values. |
1637 | 266k | i32 mb_to_top_edge = -8 * (static_cast<i32>(block_context.row) * MI_SIZE); |
1638 | 266k | i32 mb_to_bottom_edge = 8 * ((static_cast<i32>(block_context.frame_context.rows()) - blocks_high - static_cast<i32>(block_context.row)) * MI_SIZE); |
1639 | | |
1640 | 266k | i32 blocks_wide = num_8x8_blocks_wide_lookup[block_context.size]; |
1641 | 266k | i32 mb_to_left_edge = -8 * (static_cast<i32>(block_context.column) * MI_SIZE); |
1642 | 266k | i32 mb_to_right_edge = 8 * ((static_cast<i32>(block_context.frame_context.columns()) - blocks_wide - static_cast<i32>(block_context.column)) * MI_SIZE); |
1643 | | |
1644 | 266k | return { |
1645 | 266k | clip_3(mb_to_top_edge - border, mb_to_bottom_edge + border, vector.row()), |
1646 | 266k | clip_3(mb_to_left_edge - border, mb_to_right_edge + border, vector.column()) |
1647 | 266k | }; |
1648 | 266k | } |
1649 | | |
1650 | | // 6.5.1 Find MV refs syntax |
1651 | | // find_mv_refs( refFrame, block ) in the spec. |
1652 | | MotionVectorPair Parser::find_reference_motion_vectors(BlockContext& block_context, ReferenceFrameType reference_frame, i32 block) |
1653 | 53.9k | { |
1654 | | // FIXME: We should be able to change behavior based on the reference motion vector that will be selected. |
1655 | | // If block_context.y_prediction_mode() != NearMv, then we only need the first motion vector that is added to our result. |
1656 | | // This behavior should combine this function with select_best_reference_motion_vectors(). When that is done, check whether |
1657 | | // the motion vector clamping in that function is always a larger area than in this function. If so, we can drop that call. |
1658 | 53.9k | bool different_ref_found = false; |
1659 | 53.9k | u8 context_counter = 0; |
1660 | | |
1661 | 53.9k | Vector<MotionVector, 2> list; |
1662 | | |
1663 | 53.9k | MotionVector base_coordinates = MotionVector(block_context.row, block_context.column); |
1664 | | |
1665 | 161k | for (auto i = 0u; i < 2; i++) { |
1666 | 107k | auto offset_vector = mv_ref_blocks[block_context.size][i]; |
1667 | 107k | auto candidate = base_coordinates + offset_vector; |
1668 | | |
1669 | 107k | if (motion_vector_is_inside_tile(block_context.tile_context, candidate)) { |
1670 | 60.2k | different_ref_found = true; |
1671 | 60.2k | auto context = block_context.frame_block_contexts().at(candidate.row(), candidate.column()); |
1672 | 60.2k | context_counter += mode_2_counter[to_underlying(context.y_mode)]; |
1673 | | |
1674 | 102k | for (auto i = 0u; i < 2; i++) { |
1675 | 87.8k | auto reference_index = static_cast<ReferenceIndex>(i); |
1676 | 87.8k | if (context.ref_frames[reference_index] == reference_frame) { |
1677 | | // This section up until add_mv_ref_list() is defined in spec as get_sub_block_mv(). |
1678 | 45.8k | constexpr u8 idx_n_column_to_subblock[4][2] = { |
1679 | 45.8k | { 1, 2 }, |
1680 | 45.8k | { 1, 3 }, |
1681 | 45.8k | { 3, 2 }, |
1682 | 45.8k | { 3, 3 } |
1683 | 45.8k | }; |
1684 | 45.8k | auto index = block >= 0 ? idx_n_column_to_subblock[block][offset_vector.column() == 0] : 3; |
1685 | | |
1686 | 45.8k | add_motion_vector_to_list_deduped(context.sub_block_motion_vectors[index][reference_index], list); |
1687 | 45.8k | break; |
1688 | 45.8k | } |
1689 | 87.8k | } |
1690 | 60.2k | } |
1691 | 107k | } |
1692 | 53.9k | block_context.mode_context[reference_frame] = counter_to_context[context_counter]; |
1693 | | |
1694 | 377k | for (auto i = 2u; i < MVREF_NEIGHBORS; i++) { |
1695 | 323k | MotionVector candidate = base_coordinates + mv_ref_blocks[block_context.size][i]; |
1696 | 323k | if (motion_vector_is_inside_tile(block_context.tile_context, candidate)) { |
1697 | 86.8k | different_ref_found = true; |
1698 | 86.8k | add_motion_vector_if_reference_frame_type_is_same(block_context, candidate, reference_frame, list, false); |
1699 | 86.8k | } |
1700 | 323k | } |
1701 | 53.9k | if (block_context.frame_context.use_previous_frame_motion_vectors) |
1702 | 19.6k | add_motion_vector_if_reference_frame_type_is_same(block_context, base_coordinates, reference_frame, list, true); |
1703 | | |
1704 | 53.9k | if (different_ref_found) { |
1705 | 470k | for (auto i = 0u; i < MVREF_NEIGHBORS; i++) { |
1706 | 418k | MotionVector candidate = base_coordinates + mv_ref_blocks[block_context.size][i]; |
1707 | 418k | if (motion_vector_is_inside_tile(block_context.tile_context, candidate)) |
1708 | 147k | add_motion_vector_if_reference_frame_type_is_different(block_context, candidate, reference_frame, list, false); |
1709 | 418k | } |
1710 | 52.3k | } |
1711 | 53.9k | if (block_context.frame_context.use_previous_frame_motion_vectors) |
1712 | 19.6k | add_motion_vector_if_reference_frame_type_is_different(block_context, base_coordinates, reference_frame, list, true); |
1713 | | |
1714 | 130k | for (auto i = 0u; i < list.size(); i++) { |
1715 | | // clamp_mv_ref( i ) in the spec. |
1716 | 76.7k | list[i] = clamp_motion_vector(block_context, list[i], MV_BORDER); |
1717 | 76.7k | } |
1718 | | |
1719 | 53.9k | MotionVectorPair result; |
1720 | 130k | for (auto i = 0u; i < list.size(); i++) |
1721 | 76.7k | result[static_cast<ReferenceIndex>(i)] = list[i]; |
1722 | 53.9k | result.primary = clamp_motion_vector(block_context, result.primary, MV_BORDER); |
1723 | 53.9k | result.secondary = clamp_motion_vector(block_context, result.secondary, MV_BORDER); |
1724 | 53.9k | return result; |
1725 | 53.9k | } |
1726 | | |
1727 | | // find_best_ref_mvs( refList ) in the spec. |
1728 | | static void select_best_reference_motion_vectors(BlockContext& block_context, MotionVectorPair reference_motion_vectors, BlockMotionVectorCandidates& candidates, ReferenceIndex reference_index) |
1729 | 40.6k | { |
1730 | 81.3k | auto adjust_and_clamp_vector = [&](MotionVector& vector) { |
1731 | 81.3k | auto delta_row = vector.row(); |
1732 | 81.3k | auto delta_column = vector.column(); |
1733 | 81.3k | if (!block_context.frame_context.high_precision_motion_vectors_allowed || !should_use_high_precision_motion_vector(vector)) { |
1734 | 51.1k | if ((delta_row & 1) != 0) |
1735 | 295 | delta_row += delta_row > 0 ? -1 : 1; |
1736 | 51.1k | if ((delta_column & 1) != 0) |
1737 | 335 | delta_column += delta_column > 0 ? -1 : 1; |
1738 | 51.1k | } |
1739 | 81.3k | vector = { delta_row, delta_column }; |
1740 | 81.3k | vector = clamp_motion_vector(block_context, vector, (BORDERINPIXELS - INTERP_EXTEND) << 3); |
1741 | 81.3k | }; |
1742 | 40.6k | adjust_and_clamp_vector(reference_motion_vectors.primary); |
1743 | 40.6k | adjust_and_clamp_vector(reference_motion_vectors.secondary); |
1744 | | |
1745 | 40.6k | candidates[reference_index].nearest_vector = reference_motion_vectors.primary; |
1746 | 40.6k | candidates[reference_index].near_vector = reference_motion_vectors.secondary; |
1747 | 40.6k | candidates[reference_index].best_vector = reference_motion_vectors.primary; |
1748 | 40.6k | } |
1749 | | |
1750 | | // append_sub8x8_mvs( block, refList ) in the spec. |
1751 | | void Parser::select_best_sub_block_reference_motion_vectors(BlockContext& block_context, BlockMotionVectorCandidates& candidates, i32 block, ReferenceIndex reference_index) |
1752 | 13.2k | { |
1753 | 13.2k | Array<MotionVector, 2> sub_8x8_mvs; |
1754 | 13.2k | MotionVectorPair reference_motion_vectors = find_reference_motion_vectors(block_context, block_context.reference_frame_types[reference_index], block); |
1755 | 13.2k | auto destination_index = 0; |
1756 | 13.2k | if (block == 0) { |
1757 | 5.23k | sub_8x8_mvs[destination_index++] = reference_motion_vectors.primary; |
1758 | 5.23k | sub_8x8_mvs[destination_index++] = reference_motion_vectors.secondary; |
1759 | 8.05k | } else if (block <= 2) { |
1760 | 6.55k | sub_8x8_mvs[destination_index++] = block_context.sub_block_motion_vectors[0][reference_index]; |
1761 | 6.55k | } else { |
1762 | 1.49k | sub_8x8_mvs[destination_index++] = block_context.sub_block_motion_vectors[2][reference_index]; |
1763 | 3.64k | for (auto index = 1; index >= 0 && destination_index < 2; index--) { |
1764 | 2.15k | auto block_vector = block_context.sub_block_motion_vectors[index][reference_index]; |
1765 | 2.15k | if (block_vector != sub_8x8_mvs[0]) |
1766 | 918 | sub_8x8_mvs[destination_index++] = block_vector; |
1767 | 2.15k | } |
1768 | 1.49k | } |
1769 | | |
1770 | 25.0k | for (auto n = 0u; n < 2 && destination_index < 2; n++) { |
1771 | 11.7k | auto ref_list_vector = reference_motion_vectors[static_cast<ReferenceIndex>(n)]; |
1772 | 11.7k | if (ref_list_vector != sub_8x8_mvs[0]) |
1773 | 4.84k | sub_8x8_mvs[destination_index++] = ref_list_vector; |
1774 | 11.7k | } |
1775 | | |
1776 | 13.2k | if (destination_index < 2) |
1777 | 2.29k | sub_8x8_mvs[destination_index++] = {}; |
1778 | 13.2k | candidates[reference_index].nearest_vector = sub_8x8_mvs[0]; |
1779 | 13.2k | candidates[reference_index].near_vector = sub_8x8_mvs[1]; |
1780 | 13.2k | } |
1781 | | |
1782 | | } |