/src/serenity/Userland/Libraries/LibMedia/Video/VP9/Decoder.h
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2021, Hunter Salyer <thefalsehonesty@gmail.com> |
3 | | * Copyright (c) 2022, Gregory Bertilson <zaggy1024@gmail.com> |
4 | | * |
5 | | * SPDX-License-Identifier: BSD-2-Clause |
6 | | */ |
7 | | |
8 | | #pragma once |
9 | | |
10 | | #include <AK/ByteBuffer.h> |
11 | | #include <AK/Error.h> |
12 | | #include <AK/NonnullOwnPtr.h> |
13 | | #include <AK/Queue.h> |
14 | | #include <AK/Span.h> |
15 | | #include <LibMedia/Color/CodingIndependentCodePoints.h> |
16 | | #include <LibMedia/DecoderError.h> |
17 | | #include <LibMedia/VideoDecoder.h> |
18 | | #include <LibMedia/VideoFrame.h> |
19 | | |
20 | | #include "Parser.h" |
21 | | |
22 | | namespace Media::Video::VP9 { |
23 | | |
24 | | class Decoder final : public VideoDecoder { |
25 | | friend class Parser; |
26 | | |
27 | | public: |
28 | | Decoder(); |
29 | 783 | ~Decoder() override { } |
30 | | /* (8.1) General */ |
31 | | DecoderErrorOr<void> receive_sample(Duration timestamp, ReadonlyBytes) override; |
32 | | |
33 | | DecoderErrorOr<NonnullOwnPtr<VideoFrame>> get_decoded_frame() override; |
34 | | |
35 | | void flush() override; |
36 | | |
37 | | private: |
38 | | typedef i32 Intermediate; |
39 | | |
40 | | // Based on the maximum size resulting from num_4x4_blocks_wide_lookup. |
41 | | static constexpr size_t maximum_block_dimensions = 64ULL; |
42 | | static constexpr size_t maximum_block_size = maximum_block_dimensions * maximum_block_dimensions; |
43 | | // Based on the maximum for TXSize. |
44 | | static constexpr size_t maximum_transform_size = 32ULL * 32ULL; |
45 | | |
46 | | DecoderErrorOr<void> decode_frame(Duration timestamp, ReadonlyBytes); |
47 | | template<typename T> |
48 | | DecoderErrorOr<void> create_video_frame(Duration timestamp, FrameContext const&); |
49 | | |
50 | | DecoderErrorOr<void> allocate_buffers(FrameContext const&); |
51 | | Vector<u16>& get_output_buffer(u8 plane); |
52 | | |
53 | | /* (8.4) Probability Adaptation Process */ |
54 | | u8 merge_prob(u8 pre_prob, u32 count_0, u32 count_1, u8 count_sat, u8 max_update_factor); |
55 | | u32 merge_probs(int const* tree, int index, u8* probs, u32* counts, u8 count_sat, u8 max_update_factor); |
56 | | DecoderErrorOr<void> adapt_coef_probs(FrameContext const&); |
57 | | DecoderErrorOr<void> adapt_non_coef_probs(FrameContext const&); |
58 | | void adapt_probs(int const* tree, u8* probs, u32* counts); |
59 | | u8 adapt_prob(u8 prob, u32 counts[2]); |
60 | | |
61 | | /* (8.5) Prediction Processes */ |
62 | | // (8.5.1) Intra prediction process |
63 | | DecoderErrorOr<void> predict_intra(u8 plane, BlockContext const& block_context, u32 x, u32 y, bool have_left, bool have_above, bool not_on_right, TransformSize transform_size, u32 block_index); |
64 | | |
65 | | DecoderErrorOr<void> prepare_referenced_frame(Gfx::Size<u32> frame_size, u8 reference_frame_index); |
66 | | |
67 | | // (8.5.1) Inter prediction process |
68 | | DecoderErrorOr<void> predict_inter(u8 plane, BlockContext const& block_context, u32 x, u32 y, u32 width, u32 height, u32 block_index); |
69 | | // (8.5.2.1) Motion vector selection process |
70 | | MotionVector select_motion_vector(u8 plane, BlockContext const&, ReferenceIndex, u32 block_index); |
71 | | // (8.5.2.2) Motion vector clamping process |
72 | | MotionVector clamp_motion_vector(u8 plane, BlockContext const&, u32 block_row, u32 block_column, MotionVector vector); |
73 | | // From (8.5.1) Inter prediction process, steps 2-5 |
74 | | DecoderErrorOr<void> predict_inter_block(u8 plane, BlockContext const&, ReferenceIndex, u32 block_row, u32 block_column, u32 x, u32 y, u32 width, u32 height, u32 block_index, Span<u16> block_buffer); |
75 | | |
76 | | /* (8.6) Reconstruction and Dequantization */ |
77 | | |
78 | | // Returns the quantizer index for the current block |
79 | | static u8 get_base_quantizer_index(SegmentFeatureStatus alternative_quantizer_feature, bool should_use_absolute_segment_base_quantizer, u8 base_quantizer_index); |
80 | | // Returns the quantizer value for the dc coefficient for a particular plane |
81 | | static u16 get_dc_quantizer(u8 bit_depth, u8 base, i8 delta); |
82 | | // Returns the quantizer value for the ac coefficient for a particular plane |
83 | | static u16 get_ac_quantizer(u8 bit_depth, u8 base, i8 delta); |
84 | | |
85 | | // (8.6.2) Reconstruct process |
86 | | DecoderErrorOr<void> reconstruct(u8 plane, BlockContext const&, u32 transform_block_x, u32 transform_block_y, TransformSize transform_block_size, TransformSet); |
87 | | template<u8 log2_of_block_size> |
88 | | DecoderErrorOr<void> reconstruct_templated(u8 plane, BlockContext const&, u32 transform_block_x, u32 transform_block_y, TransformSet); |
89 | | |
90 | | // (8.7) Inverse transform process |
91 | | template<u8 log2_of_block_size> |
92 | | DecoderErrorOr<void> inverse_transform_2d(BlockContext const&, Span<Intermediate> dequantized, TransformSet); |
93 | | |
94 | | // (8.7.1) 1D Transforms |
95 | | // (8.7.1.1) Butterfly functions |
96 | | |
97 | | inline i32 cos64(u8 angle); |
98 | | inline i32 sin64(u8 angle); |
99 | | // The function B( a, b, angle, 0 ) performs a butterfly rotation. |
100 | | inline void butterfly_rotation_in_place(Span<Intermediate> data, size_t index_a, size_t index_b, u8 angle, bool flip); |
101 | | // The function H( a, b, 0 ) performs a Hadamard rotation. |
102 | | inline void hadamard_rotation_in_place(Span<Intermediate> data, size_t index_a, size_t index_b, bool flip); |
103 | | // The function SB( a, b, angle, 0 ) performs a butterfly rotation. |
104 | | // Spec defines the source as array T, and the destination array as S. |
105 | | template<typename S, typename D> |
106 | | inline void butterfly_rotation(Span<S> source, Span<D> destination, size_t index_a, size_t index_b, u8 angle, bool flip); |
107 | | // The function SH( a, b ) performs a Hadamard rotation and rounding. |
108 | | // Spec defines the source array as S, and the destination array as T. |
109 | | template<typename S, typename D> |
110 | | inline void hadamard_rotation(Span<S> source, Span<D> destination, size_t index_a, size_t index_b); |
111 | | |
112 | | // (8.7.1.10) This process does an in-place Walsh-Hadamard transform of the array T (of length 4). |
113 | | inline DecoderErrorOr<void> inverse_walsh_hadamard_transform(Span<Intermediate> data, u8 log2_of_block_size, u8 shift); |
114 | | |
115 | | // (8.7.1.2) Inverse DCT array permutation process |
116 | | template<u8 log2_of_block_size> |
117 | | inline DecoderErrorOr<void> inverse_discrete_cosine_transform_array_permutation(Span<Intermediate> data); |
118 | | // (8.7.1.3) Inverse DCT process |
119 | | template<u8 log2_of_block_size> |
120 | | inline DecoderErrorOr<void> inverse_discrete_cosine_transform(Span<Intermediate> data); |
121 | | |
122 | | // (8.7.1.4) This process performs the in-place permutation of the array T of length 2 n which is required as the first step of |
123 | | // the inverse ADST. |
124 | | template<u8 log2_of_block_size> |
125 | | inline void inverse_asymmetric_discrete_sine_transform_input_array_permutation(Span<Intermediate> data); |
126 | | // (8.7.1.5) This process performs the in-place permutation of the array T of length 2 n which is required before the final |
127 | | // step of the inverse ADST. |
128 | | template<u8 log2_of_block_size> |
129 | | inline void inverse_asymmetric_discrete_sine_transform_output_array_permutation(Span<Intermediate> data); |
130 | | |
131 | | // (8.7.1.6) This process does an in-place transform of the array T to perform an inverse ADST. |
132 | | inline void inverse_asymmetric_discrete_sine_transform_4(Span<Intermediate> data); |
133 | | // (8.7.1.7) This process does an in-place transform of the array T using a higher precision array S for intermediate |
134 | | // results. |
135 | | inline DecoderErrorOr<void> inverse_asymmetric_discrete_sine_transform_8(Span<Intermediate> data); |
136 | | // (8.7.1.8) This process does an in-place transform of the array T using a higher precision array S for intermediate |
137 | | // results. |
138 | | inline DecoderErrorOr<void> inverse_asymmetric_discrete_sine_transform_16(Span<Intermediate> data); |
139 | | // (8.7.1.9) This process performs an in-place inverse ADST process on the array T of size 2 n for 2 ≤ n ≤ 4. |
140 | | template<u8 log2_of_block_size> |
141 | | inline DecoderErrorOr<void> inverse_asymmetric_discrete_sine_transform(Span<Intermediate> data); |
142 | | |
143 | | /* (8.10) Reference Frame Update Process */ |
144 | | DecoderErrorOr<void> update_reference_frames(FrameContext const&); |
145 | | |
146 | | NonnullOwnPtr<Parser> m_parser; |
147 | | |
148 | | Vector<u16> m_output_buffers[3]; |
149 | | |
150 | | Queue<NonnullOwnPtr<VideoFrame>, 1> m_video_frame_queue; |
151 | | }; |
152 | | |
153 | | } |