/* * Copyright (c) 2021, Hunter Salyer * Copyright (c) 2022, Gregory Bertilson * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include #include #include "Parser.h" namespace Video::VP9 { class Decoder { friend class Parser; public: Decoder(); /* (8.1) General */ DecoderErrorOr decode(Span); DecoderErrorOr decode(ByteBuffer const&); void dump_frame_info(); // FIXME: These functions should be replaced by a struct that contains // all the information needed to display a frame. Vector const& get_output_buffer_for_plane(u8 plane) const; Gfx::Size get_y_plane_size(); bool get_uv_subsampling_y(); bool get_uv_subsampling_x(); private: typedef i32 Intermediate; DecoderErrorOr decode_frame(Span); DecoderErrorOr allocate_buffers(); Vector& get_temp_buffer(u8 plane); Vector& get_output_buffer(u8 plane); /* (8.4) Probability Adaptation Process */ u8 merge_prob(u8 pre_prob, u8 count_0, u8 count_1, u8 count_sat, u8 max_update_factor); u8 merge_probs(int const* tree, int index, u8* probs, u8* counts, u8 count_sat, u8 max_update_factor); DecoderErrorOr adapt_coef_probs(); DecoderErrorOr adapt_non_coef_probs(); void adapt_probs(int const* tree, u8* probs, u8* counts); u8 adapt_prob(u8 prob, u8 counts[2]); /* (8.5) Prediction Processes */ // (8.5.1) Intra prediction process DecoderErrorOr predict_intra(u8 plane, u32 x, u32 y, bool have_left, bool have_above, bool not_on_right, TXSize tx_size, u32 block_index); // (8.5.1) Inter prediction process DecoderErrorOr predict_inter(u8 plane, u32 x, u32 y, u32 width, u32 height, u32 block_index); // (8.5.2.1) Motion vector selection process MotionVector select_motion_vector(u8 plane, u8 ref_list, u32 block_index); // (8.5.2.2) Motion vector clamping process MotionVector clamp_motion_vector(u8 plane, MotionVector vector); // (8.5.2.3) Motion vector scaling process DecoderErrorOr scale_motion_vector(u8 plane, u8 ref_list, u32 x, u32 y, MotionVector vector); // From (8.5.1) Inter prediction process, steps 2-5 DecoderErrorOr predict_inter_block(u8 plane, u8 ref_list, u32 x, u32 y, u32 width, u32 height, u32 block_index, Vector& buffer); /* (8.6) Reconstruction and Dequantization */ // FIXME: These should be inline or constexpr u16 dc_q(u8 b); u16 ac_q(u8 b); // Returns the quantizer index for the current block u8 get_qindex(); // Returns the quantizer value for the dc coefficient for a particular plane u16 get_dc_quant(u8 plane); // Returns the quantizer value for the ac coefficient for a particular plane u16 get_ac_quant(u8 plane); // (8.6.2) Reconstruct process DecoderErrorOr reconstruct(u8 plane, u32 transform_block_x, u32 transform_block_y, TXSize transform_block_size); // (8.7) Inverse transform process DecoderErrorOr inverse_transform_2d(Vector& dequantized, u8 log2_of_block_size); // (8.7.1) 1D Transforms // (8.7.1.1) Butterfly functions inline i32 cos64(u8 angle); inline i32 sin64(u8 angle); // The function B( a, b, angle, 0 ) performs a butterfly rotation. inline void butterfly_rotation_in_place(Vector& data, size_t index_a, size_t index_b, u8 angle, bool flip); // The function H( a, b, 0 ) performs a Hadamard rotation. inline void hadamard_rotation_in_place(Vector& data, size_t index_a, size_t index_b, bool flip); // The function SB( a, b, angle, 0 ) performs a butterfly rotation. // Spec defines the source as array T, and the destination array as S. template inline void butterfly_rotation(Vector& source, Vector& destination, size_t index_a, size_t index_b, u8 angle, bool flip); // The function SH( a, b ) performs a Hadamard rotation and rounding. // Spec defines the source array as S, and the destination array as T. template inline void hadamard_rotation(Vector& source, Vector& destination, size_t index_a, size_t index_b); template inline i32 round_2(T value, u8 bits); // Checks whether the value is representable by a signed integer with (8 + bit_depth) bits. inline bool check_intermediate_bounds(Intermediate value); // (8.7.1.10) This process does an in-place Walsh-Hadamard transform of the array T (of length 4). inline DecoderErrorOr inverse_walsh_hadamard_transform(Vector& data, u8 log2_of_block_size, u8 shift); // (8.7.1.2) Inverse DCT array permutation process inline DecoderErrorOr inverse_discrete_cosine_transform_array_permutation(Vector& data, u8 log2_of_block_size); // (8.7.1.3) Inverse DCT process inline DecoderErrorOr inverse_discrete_cosine_transform(Vector& data, u8 log2_of_block_size); // (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 // the inverse ADST. inline void inverse_asymmetric_discrete_sine_transform_input_array_permutation(Vector& data, Vector& temp, u8 log2_of_block_size); // (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 // step of the inverse ADST. inline void inverse_asymmetric_discrete_sine_transform_output_array_permutation(Vector& data, Vector& temp, u8 log2_of_block_size); // (8.7.1.6) This process does an in-place transform of the array T to perform an inverse ADST. inline void inverse_asymmetric_discrete_sine_transform_4(Vector& data); // (8.7.1.7) This process does an in-place transform of the array T using a higher precision array S for intermediate // results. inline DecoderErrorOr inverse_asymmetric_discrete_sine_transform_8(Vector& data); // (8.7.1.8) This process does an in-place transform of the array T using a higher precision array S for intermediate // results. inline DecoderErrorOr inverse_asymmetric_discrete_sine_transform_16(Vector& data); // (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. inline DecoderErrorOr inverse_asymmetric_discrete_sine_transform(Vector& data, u8 log2_of_block_size); /* (8.10) Reference Frame Update Process */ DecoderErrorOr update_reference_frames(); NonnullOwnPtr m_parser; struct { // FIXME: We may be able to consolidate some of these to reduce memory consumption. // FIXME: Create a new struct to store these buffers, specifying size and providing // helper functions to get values at coordinates. All *_at(row, column) // functions in Decoder.cpp and functions returning row * width + column // should be replaced if possible. Vector dequantized; Vector row_or_column; // predict_intra Vector above_row; Vector left_column; Vector predicted_samples; // transforms (dct, adst) Vector transform_temp; Vector adst_temp; // predict_inter Vector inter_horizontal; Vector inter_predicted; Vector inter_predicted_compound; Vector intermediate[3]; Vector output[3]; } m_buffers; }; }