From da9ff3116681800d0d6ed7c6a1e62c5b91df1264 Mon Sep 17 00:00:00 2001 From: Zaggy1024 Date: Tue, 13 Sep 2022 19:40:37 -0500 Subject: [PATCH] LibVideo: Make new DecoderError class to report useful errors This allows runtime strings, so we can format the errors to make them more helpful. Errors in the VP9 decoder will now print out a function, filename and line number for where a read or bitstream requirement has failed. The DecoderErrorCategory enum will classify the errors so library users can show general user-friendly error messages, while providing the debug information separately. Any non-DecoderErrorOr<> results can be wrapped by DECODER_TRY to return from decoder functions. This will also add the extra information mentioned above to the error message. --- Userland/Libraries/LibVideo/DecoderError.h | 82 ++++ Userland/Libraries/LibVideo/VP9/Decoder.cpp | 20 +- Userland/Libraries/LibVideo/VP9/Decoder.h | 18 +- Userland/Libraries/LibVideo/VP9/Parser.cpp | 393 ++++++++++---------- Userland/Libraries/LibVideo/VP9/Parser.h | 134 ++++--- 5 files changed, 369 insertions(+), 278 deletions(-) create mode 100644 Userland/Libraries/LibVideo/DecoderError.h diff --git a/Userland/Libraries/LibVideo/DecoderError.h b/Userland/Libraries/LibVideo/DecoderError.h new file mode 100644 index 0000000000..bfde7e7edb --- /dev/null +++ b/Userland/Libraries/LibVideo/DecoderError.h @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2022, Gregory Bertilson + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include +#include +#include + +namespace Video { + +struct DecoderError; + +template +using DecoderErrorOr = ErrorOr; + +enum class DecoderErrorCategory : u32 { + Unknown, + IO, + // The input is corrupted. + Corrupted, + // The input uses features that are not yet implemented. + NotImplemented, +}; + +struct DecoderError { +public: + static DecoderError with_description(DecoderErrorCategory category, StringView description) + { + return DecoderError(category, description); + } + + template + static DecoderError format(DecoderErrorCategory category, CheckedFormatString&& format_string, Parameters const&... parameters) + { + AK::VariadicFormatParams variadic_format_params { parameters... }; + return DecoderError::with_description(category, String::vformatted(format_string.view(), variadic_format_params)); + } + + static DecoderError corrupted(StringView description, SourceLocation location = SourceLocation::current()) + { + return DecoderError::format(DecoderErrorCategory::Corrupted, "{}: {}", location, description); + } + + static DecoderError not_implemented(SourceLocation location = SourceLocation::current()) + { + return DecoderError::format(DecoderErrorCategory::NotImplemented, "{} is not implemented", location.function_name()); + } + + DecoderErrorCategory category() { return m_category; } + StringView description() { return m_description; } + StringView string_literal() { return m_description; } + +private: + DecoderError(DecoderErrorCategory category, String description) + : m_category(category) + , m_description(move(description)) + { + } + + DecoderErrorCategory m_category { DecoderErrorCategory::Unknown }; + String m_description; +}; + +#define DECODER_TRY(category, expression) \ + ({ \ + auto _result = ((expression)); \ + if (_result.is_error()) [[unlikely]] { \ + auto _error_string = _result.release_error().string_literal(); \ + return DecoderError::format( \ + ((category)), "{}: {}", \ + SourceLocation::current(), _error_string); \ + } \ + _result.release_value(); \ + }) + +} diff --git a/Userland/Libraries/LibVideo/VP9/Decoder.cpp b/Userland/Libraries/LibVideo/VP9/Decoder.cpp index 093d5c0805..e6b539010b 100644 --- a/Userland/Libraries/LibVideo/VP9/Decoder.cpp +++ b/Userland/Libraries/LibVideo/VP9/Decoder.cpp @@ -15,7 +15,7 @@ Decoder::Decoder() { } -ErrorOr Decoder::decode_frame(ByteBuffer const& frame_data) +DecoderErrorOr Decoder::decode_frame(ByteBuffer const& frame_data) { TRY(m_parser->parse_frame(frame_data)); // TODO: @@ -51,7 +51,7 @@ u8 Decoder::merge_probs(int const* tree, int index, u8* probs, u8* counts, u8 co return left_count + right_count; } -ErrorOr Decoder::adapt_coef_probs() +DecoderErrorOr Decoder::adapt_coef_probs() { u8 update_factor; if (m_parser->m_frame_is_intra || m_parser->m_last_frame_type != KeyFrame) @@ -96,7 +96,7 @@ ErrorOr Decoder::adapt_coef_probs() } \ } while (0) -ErrorOr Decoder::adapt_non_coef_probs() +DecoderErrorOr Decoder::adapt_non_coef_probs() { auto& probs = *m_parser->m_probability_tables; auto& counter = *m_parser->m_syntax_element_counter; @@ -152,25 +152,25 @@ u8 Decoder::adapt_prob(u8 prob, u8 counts[2]) return merge_prob(prob, counts[0], counts[1], COUNT_SAT, MAX_UPDATE_FACTOR); } -ErrorOr Decoder::predict_intra(size_t, u32, u32, bool, bool, bool, TXSize, u32) +DecoderErrorOr Decoder::predict_intra(size_t, u32, u32, bool, bool, bool, TXSize, u32) { // TODO: Implement - return Error::from_string_literal("predict_intra not implemented"); + return DecoderError::not_implemented(); } -ErrorOr Decoder::predict_inter(size_t, u32, u32, u32, u32, u32) +DecoderErrorOr Decoder::predict_inter(size_t, u32, u32, u32, u32, u32) { // TODO: Implement - return Error::from_string_literal("predict_inter not implemented"); + return DecoderError::not_implemented(); } -ErrorOr Decoder::reconstruct(size_t, u32, u32, TXSize) +DecoderErrorOr Decoder::reconstruct(size_t, u32, u32, TXSize) { // TODO: Implement - return Error::from_string_literal("reconstruct not implemented"); + return DecoderError::not_implemented(); } -ErrorOr Decoder::update_reference_frames() +DecoderErrorOr Decoder::update_reference_frames() { for (auto i = 0; i < NUM_REF_FRAMES; i++) { dbgln("updating frame {}? {}", i, (m_parser->m_refresh_frame_flags & (1 << i)) == 1); diff --git a/Userland/Libraries/LibVideo/VP9/Decoder.h b/Userland/Libraries/LibVideo/VP9/Decoder.h index 20aa8e80fe..b73b6017aa 100644 --- a/Userland/Libraries/LibVideo/VP9/Decoder.h +++ b/Userland/Libraries/LibVideo/VP9/Decoder.h @@ -7,9 +7,11 @@ #pragma once -#include "Parser.h" #include #include +#include + +#include "Parser.h" namespace Video::VP9 { @@ -18,27 +20,27 @@ class Decoder { public: Decoder(); - ErrorOr decode_frame(ByteBuffer const&); + DecoderErrorOr decode_frame(ByteBuffer const&); void dump_frame_info(); private: /* (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); - ErrorOr adapt_coef_probs(); - ErrorOr adapt_non_coef_probs(); + 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 */ - ErrorOr predict_intra(size_t plane, u32 x, u32 y, bool have_left, bool have_above, bool not_on_right, TXSize tx_size, u32 block_index); - ErrorOr predict_inter(size_t plane, u32 x, u32 y, u32 w, u32 h, u32 block_index); + DecoderErrorOr predict_intra(size_t plane, u32 x, u32 y, bool have_left, bool have_above, bool not_on_right, TXSize tx_size, u32 block_index); + DecoderErrorOr predict_inter(size_t plane, u32 x, u32 y, u32 w, u32 h, u32 block_index); /* (8.6) Reconstruction and Dequantization */ - ErrorOr reconstruct(size_t plane, u32 x, u32 y, TXSize size); + DecoderErrorOr reconstruct(size_t plane, u32 transform_block_x, u32 transform_block_y, TXSize transform_block_size); /* (8.10) Reference Frame Update Process */ - ErrorOr update_reference_frames(); + DecoderErrorOr update_reference_frames(); NonnullOwnPtr m_parser; }; diff --git a/Userland/Libraries/LibVideo/VP9/Parser.cpp b/Userland/Libraries/LibVideo/VP9/Parser.cpp index fcbf9e4d64..3de4ab0dba 100644 --- a/Userland/Libraries/LibVideo/VP9/Parser.cpp +++ b/Userland/Libraries/LibVideo/VP9/Parser.cpp @@ -12,6 +12,8 @@ namespace Video::VP9 { +#define TRY_READ(expression) DECODER_TRY(DecoderErrorCategory::Corrupted, expression) + Parser::Parser(Decoder& decoder) : m_probability_tables(make()) , m_tree_parser(make(*this)) @@ -40,7 +42,7 @@ void Parser::cleanup_tile_allocations() } /* (6.1) */ -ErrorOr Parser::parse_frame(ByteBuffer const& frame_data) +DecoderErrorOr Parser::parse_frame(ByteBuffer const& frame_data) { m_bit_stream = make(frame_data.data(), frame_data.size()); m_syntax_element_counter = make(); @@ -48,18 +50,18 @@ ErrorOr Parser::parse_frame(ByteBuffer const& frame_data) TRY(uncompressed_header()); dbgln("Finished reading uncompressed header"); if (!trailing_bits()) - return Error::from_string_literal("parse_frame: Trailing bits were non-zero"); + return DecoderError::corrupted("Trailing bits were non-zero"sv); if (m_header_size_in_bytes == 0) - return Error::from_string_literal("parse_frame: Frame header is zero-sized"); + return DecoderError::corrupted("Frame header is zero-sized"sv); m_probability_tables->load_probs(m_frame_context_idx); m_probability_tables->load_probs2(m_frame_context_idx); m_syntax_element_counter->clear_counts(); - TRY(m_bit_stream->init_bool(m_header_size_in_bytes)); + TRY_READ(m_bit_stream->init_bool(m_header_size_in_bytes)); dbgln("Reading compressed header with size {}", m_header_size_in_bytes); TRY(compressed_header()); dbgln("Finished reading compressed header"); - TRY(m_bit_stream->exit_bool()); + TRY_READ(m_bit_stream->exit_bool()); TRY(decode_tiles()); TRY(refresh_probs()); @@ -77,7 +79,7 @@ bool Parser::trailing_bits() return true; } -ErrorOr Parser::refresh_probs() +DecoderErrorOr Parser::refresh_probs() { if (!m_error_resilient_mode && !m_frame_parallel_decoding_mode) { m_probability_tables->load_probs(m_frame_context_idx); @@ -92,20 +94,34 @@ ErrorOr Parser::refresh_probs() return {}; } -/* (6.2) */ -ErrorOr Parser::uncompressed_header() +DecoderErrorOr Parser::read_frame_type() { - auto frame_marker = TRY(m_bit_stream->read_bits(2)); + if (TRY_READ(m_bit_stream->read_bit())) + return NonKeyFrame; + return KeyFrame; +} + +DecoderErrorOr Parser::read_color_range() +{ + if (TRY_READ(m_bit_stream->read_bit())) + return FullSwing; + return StudioSwing; +} + +/* (6.2) */ +DecoderErrorOr Parser::uncompressed_header() +{ + auto frame_marker = TRY_READ(m_bit_stream->read_bits(2)); if (frame_marker != 2) - return Error::from_string_literal("uncompressed_header: Frame marker must be 2"); - auto profile_low_bit = TRY(m_bit_stream->read_bit()); - auto profile_high_bit = TRY(m_bit_stream->read_bit()); + return DecoderError::corrupted("uncompressed_header: Frame marker must be 2"sv); + auto profile_low_bit = TRY_READ(m_bit_stream->read_bit()); + auto profile_high_bit = TRY_READ(m_bit_stream->read_bit()); m_profile = (profile_high_bit << 1u) + profile_low_bit; - if (m_profile == 3 && TRY(m_bit_stream->read_bit())) - return Error::from_string_literal("uncompressed_header: Profile 3 reserved bit was non-zero"); - auto show_existing_frame = TRY(m_bit_stream->read_bit()); + if (m_profile == 3 && TRY_READ(m_bit_stream->read_bit())) + return DecoderError::corrupted("uncompressed_header: Profile 3 reserved bit was non-zero"sv); + auto show_existing_frame = TRY_READ(m_bit_stream->read_bit()); if (show_existing_frame) { - m_frame_to_show_map_index = TRY(m_bit_stream->read_bits(3)); + m_frame_to_show_map_index = TRY_READ(m_bit_stream->read_bits(3)); m_header_size_in_bytes = 0; m_refresh_frame_flags = 0; m_loop_filter_level = 0; @@ -114,8 +130,8 @@ ErrorOr Parser::uncompressed_header() m_last_frame_type = m_frame_type; m_frame_type = TRY(read_frame_type()); - m_show_frame = TRY(m_bit_stream->read_bit()); - m_error_resilient_mode = TRY(m_bit_stream->read_bit()); + m_show_frame = TRY_READ(m_bit_stream->read_bit()); + m_error_resilient_mode = TRY_READ(m_bit_stream->read_bit()); if (m_frame_type == KeyFrame) { TRY(frame_sync_code()); @@ -125,10 +141,10 @@ ErrorOr Parser::uncompressed_header() m_refresh_frame_flags = 0xFF; m_frame_is_intra = true; } else { - m_frame_is_intra = !m_show_frame && TRY(m_bit_stream->read_bit()); + m_frame_is_intra = !m_show_frame && TRY_READ(m_bit_stream->read_bit()); if (!m_error_resilient_mode) { - m_reset_frame_context = TRY(m_bit_stream->read_bits(2)); + m_reset_frame_context = TRY_READ(m_bit_stream->read_bits(2)); } else { m_reset_frame_context = 0; } @@ -144,30 +160,30 @@ ErrorOr Parser::uncompressed_header() m_bit_depth = 8; } - m_refresh_frame_flags = TRY(m_bit_stream->read_f8()); + m_refresh_frame_flags = TRY_READ(m_bit_stream->read_f8()); TRY(frame_size()); TRY(render_size()); } else { - m_refresh_frame_flags = TRY(m_bit_stream->read_f8()); + m_refresh_frame_flags = TRY_READ(m_bit_stream->read_f8()); for (auto i = 0; i < 3; i++) { - m_ref_frame_idx[i] = TRY(m_bit_stream->read_bits(3)); - m_ref_frame_sign_bias[LastFrame + i] = TRY(m_bit_stream->read_bit()); + m_ref_frame_idx[i] = TRY_READ(m_bit_stream->read_bits(3)); + m_ref_frame_sign_bias[LastFrame + i] = TRY_READ(m_bit_stream->read_bit()); } TRY(frame_size_with_refs()); - m_allow_high_precision_mv = TRY(m_bit_stream->read_bit()); + m_allow_high_precision_mv = TRY_READ(m_bit_stream->read_bit()); TRY(read_interpolation_filter()); } } if (!m_error_resilient_mode) { - m_refresh_frame_context = TRY(m_bit_stream->read_bit()); - m_frame_parallel_decoding_mode = TRY(m_bit_stream->read_bit()); + m_refresh_frame_context = TRY_READ(m_bit_stream->read_bit()); + m_frame_parallel_decoding_mode = TRY_READ(m_bit_stream->read_bit()); } else { m_refresh_frame_context = false; m_frame_parallel_decoding_mode = true; } - m_frame_context_idx = TRY(m_bit_stream->read_bits(2)); + m_frame_context_idx = TRY_READ(m_bit_stream->read_bits(2)); if (m_frame_is_intra || m_error_resilient_mode) { setup_past_independence(); if (m_frame_type == KeyFrame || m_error_resilient_mode || m_reset_frame_context == 3) { @@ -185,41 +201,41 @@ ErrorOr Parser::uncompressed_header() TRY(segmentation_params()); TRY(tile_info()); - m_header_size_in_bytes = TRY(m_bit_stream->read_f16()); + m_header_size_in_bytes = TRY_READ(m_bit_stream->read_f16()); return {}; } -ErrorOr Parser::frame_sync_code() +DecoderErrorOr Parser::frame_sync_code() { - if (TRY(m_bit_stream->read_f8()) != 0x49) - return Error::from_string_literal("frame_sync_code: Byte 0 was not 0x49."); - if (TRY(m_bit_stream->read_f8()) != 0x83) - return Error::from_string_literal("frame_sync_code: Byte 1 was not 0x83."); - if (TRY(m_bit_stream->read_f8()) != 0x42) - return Error::from_string_literal("frame_sync_code: Byte 2 was not 0x42."); + if (TRY_READ(m_bit_stream->read_f8()) != 0x49) + return DecoderError::corrupted("frame_sync_code: Byte 0 was not 0x49."sv); + if (TRY_READ(m_bit_stream->read_f8()) != 0x83) + return DecoderError::corrupted("frame_sync_code: Byte 1 was not 0x83."sv); + if (TRY_READ(m_bit_stream->read_f8()) != 0x42) + return DecoderError::corrupted("frame_sync_code: Byte 2 was not 0x42."sv); return {}; } -ErrorOr Parser::color_config() +DecoderErrorOr Parser::color_config() { if (m_profile >= 2) { - m_bit_depth = TRY(m_bit_stream->read_bit()) ? 12 : 10; + m_bit_depth = TRY_READ(m_bit_stream->read_bit()) ? 12 : 10; } else { m_bit_depth = 8; } - auto color_space = TRY(m_bit_stream->read_bits(3)); + auto color_space = TRY_READ(m_bit_stream->read_bits(3)); VERIFY(color_space <= RGB); m_color_space = static_cast(color_space); if (color_space != RGB) { m_color_range = TRY(read_color_range()); if (m_profile == 1 || m_profile == 3) { - m_subsampling_x = TRY(m_bit_stream->read_bit()); - m_subsampling_y = TRY(m_bit_stream->read_bit()); - if (TRY(m_bit_stream->read_bit())) - return Error::from_string_literal("color_config: Subsampling reserved zero was set"); + m_subsampling_x = TRY_READ(m_bit_stream->read_bit()); + m_subsampling_y = TRY_READ(m_bit_stream->read_bit()); + if (TRY_READ(m_bit_stream->read_bit())) + return DecoderError::corrupted("color_config: Subsampling reserved zero was set"sv); } else { m_subsampling_x = true; m_subsampling_y = true; @@ -229,26 +245,26 @@ ErrorOr Parser::color_config() if (m_profile == 1 || m_profile == 3) { m_subsampling_x = false; m_subsampling_y = false; - if (TRY(m_bit_stream->read_bit())) - return Error::from_string_literal("color_config: RGB reserved zero was set"); + if (TRY_READ(m_bit_stream->read_bit())) + return DecoderError::corrupted("color_config: RGB reserved zero was set"sv); } } return {}; } -ErrorOr Parser::frame_size() +DecoderErrorOr Parser::frame_size() { - m_frame_width = TRY(m_bit_stream->read_f16()) + 1; - m_frame_height = TRY(m_bit_stream->read_f16()) + 1; + m_frame_width = TRY_READ(m_bit_stream->read_f16()) + 1; + m_frame_height = TRY_READ(m_bit_stream->read_f16()) + 1; compute_image_size(); return {}; } -ErrorOr Parser::render_size() +DecoderErrorOr Parser::render_size() { - if (TRY(m_bit_stream->read_bit())) { - m_render_width = TRY(m_bit_stream->read_f16()) + 1; - m_render_height = TRY(m_bit_stream->read_f16()) + 1; + if (TRY_READ(m_bit_stream->read_bit())) { + m_render_width = TRY_READ(m_bit_stream->read_f16()) + 1; + m_render_height = TRY_READ(m_bit_stream->read_f16()) + 1; } else { m_render_width = m_frame_width; m_render_height = m_frame_height; @@ -256,11 +272,11 @@ ErrorOr Parser::render_size() return {}; } -ErrorOr Parser::frame_size_with_refs() +DecoderErrorOr Parser::frame_size_with_refs() { bool found_ref; for (auto frame_index : m_ref_frame_idx) { - found_ref = TRY(m_bit_stream->read_bit()); + found_ref = TRY_READ(m_bit_stream->read_bit()); if (found_ref) { dbgln("Reading size from ref frame {}", frame_index); m_frame_width = m_ref_frame_width[frame_index]; @@ -286,30 +302,30 @@ void Parser::compute_image_size() m_sb64_rows = (m_mi_rows + 7u) >> 3u; } -ErrorOr Parser::read_interpolation_filter() +DecoderErrorOr Parser::read_interpolation_filter() { - if (TRY(m_bit_stream->read_bit())) { + if (TRY_READ(m_bit_stream->read_bit())) { m_interpolation_filter = Switchable; } else { - m_interpolation_filter = literal_to_type[TRY(m_bit_stream->read_bits(2))]; + m_interpolation_filter = literal_to_type[TRY_READ(m_bit_stream->read_bits(2))]; } return {}; } -ErrorOr Parser::loop_filter_params() +DecoderErrorOr Parser::loop_filter_params() { - m_loop_filter_level = TRY(m_bit_stream->read_bits(6)); - m_loop_filter_sharpness = TRY(m_bit_stream->read_bits(3)); - m_loop_filter_delta_enabled = TRY(m_bit_stream->read_bit()); + m_loop_filter_level = TRY_READ(m_bit_stream->read_bits(6)); + m_loop_filter_sharpness = TRY_READ(m_bit_stream->read_bits(3)); + m_loop_filter_delta_enabled = TRY_READ(m_bit_stream->read_bit()); if (m_loop_filter_delta_enabled) { - if (TRY(m_bit_stream->read_bit())) { + if (TRY_READ(m_bit_stream->read_bit())) { for (auto& loop_filter_ref_delta : m_loop_filter_ref_deltas) { - if (TRY(m_bit_stream->read_bit())) - loop_filter_ref_delta = TRY(m_bit_stream->read_s(6)); + if (TRY_READ(m_bit_stream->read_bit())) + loop_filter_ref_delta = TRY_READ(m_bit_stream->read_s(6)); } for (auto& loop_filter_mode_delta : m_loop_filter_mode_deltas) { - if (TRY(m_bit_stream->read_bit())) - loop_filter_mode_delta = TRY(m_bit_stream->read_s(6)); + if (TRY_READ(m_bit_stream->read_bit())) + loop_filter_mode_delta = TRY_READ(m_bit_stream->read_s(6)); } } } @@ -317,9 +333,9 @@ ErrorOr Parser::loop_filter_params() return {}; } -ErrorOr Parser::quantization_params() +DecoderErrorOr Parser::quantization_params() { - auto base_q_idx = TRY(m_bit_stream->read_f8()); + auto base_q_idx = TRY_READ(m_bit_stream->read_f8()); auto delta_q_y_dc = TRY(read_delta_q()); auto delta_q_uv_dc = TRY(read_delta_q()); auto delta_q_uv_ac = TRY(read_delta_q()); @@ -327,44 +343,44 @@ ErrorOr Parser::quantization_params() return {}; } -ErrorOr Parser::read_delta_q() +DecoderErrorOr Parser::read_delta_q() { - if (TRY(m_bit_stream->read_bit())) - return m_bit_stream->read_s(4); + if (TRY_READ(m_bit_stream->read_bit())) + return TRY_READ(m_bit_stream->read_s(4)); return 0; } -ErrorOr Parser::segmentation_params() +DecoderErrorOr Parser::segmentation_params() { - m_segmentation_enabled = TRY(m_bit_stream->read_bit()); + m_segmentation_enabled = TRY_READ(m_bit_stream->read_bit()); if (!m_segmentation_enabled) return {}; - m_segmentation_update_map = TRY(m_bit_stream->read_bit()); + m_segmentation_update_map = TRY_READ(m_bit_stream->read_bit()); if (m_segmentation_update_map) { for (auto& segmentation_tree_prob : m_segmentation_tree_probs) segmentation_tree_prob = TRY(read_prob()); - m_segmentation_temporal_update = TRY(m_bit_stream->read_bit()); + m_segmentation_temporal_update = TRY_READ(m_bit_stream->read_bit()); for (auto& segmentation_pred_prob : m_segmentation_pred_prob) segmentation_pred_prob = m_segmentation_temporal_update ? TRY(read_prob()) : 255; } - auto segmentation_update_data = (TRY(m_bit_stream->read_bit())); + auto segmentation_update_data = (TRY_READ(m_bit_stream->read_bit())); if (!segmentation_update_data) return {}; - m_segmentation_abs_or_delta_update = TRY(m_bit_stream->read_bit()); + m_segmentation_abs_or_delta_update = TRY_READ(m_bit_stream->read_bit()); for (auto i = 0; i < MAX_SEGMENTS; i++) { for (auto j = 0; j < SEG_LVL_MAX; j++) { auto feature_value = 0; - auto feature_enabled = TRY(m_bit_stream->read_bit()); + auto feature_enabled = TRY_READ(m_bit_stream->read_bit()); m_feature_enabled[i][j] = feature_enabled; if (feature_enabled) { auto bits_to_read = segmentation_feature_bits[j]; - feature_value = TRY(m_bit_stream->read_bits(bits_to_read)); + feature_value = TRY_READ(m_bit_stream->read_bits(bits_to_read)); if (segmentation_feature_signed[j]) { - if (TRY(m_bit_stream->read_bit())) + if (TRY_READ(m_bit_stream->read_bit())) feature_value = -feature_value; } } @@ -375,27 +391,27 @@ ErrorOr Parser::segmentation_params() return {}; } -ErrorOr Parser::read_prob() +DecoderErrorOr Parser::read_prob() { - if (TRY(m_bit_stream->read_bit())) - return TRY(m_bit_stream->read_f8()); + if (TRY_READ(m_bit_stream->read_bit())) + return TRY_READ(m_bit_stream->read_f8()); return 255; } -ErrorOr Parser::tile_info() +DecoderErrorOr Parser::tile_info() { auto min_log2_tile_cols = calc_min_log2_tile_cols(); auto max_log2_tile_cols = calc_max_log2_tile_cols(); m_tile_cols_log2 = min_log2_tile_cols; while (m_tile_cols_log2 < max_log2_tile_cols) { - if (TRY(m_bit_stream->read_bit())) + if (TRY_READ(m_bit_stream->read_bit())) m_tile_cols_log2++; else break; } - m_tile_rows_log2 = TRY(m_bit_stream->read_bit()); + m_tile_rows_log2 = TRY_READ(m_bit_stream->read_bit()); if (m_tile_rows_log2) { - m_tile_rows_log2 += TRY(m_bit_stream->read_bit()); + m_tile_rows_log2 += TRY_READ(m_bit_stream->read_bit()); } return {}; } @@ -438,7 +454,7 @@ void Parser::setup_past_independence() m_probability_tables->reset_probs(); } -ErrorOr Parser::compressed_header() +DecoderErrorOr Parser::compressed_header() { TRY(read_tx_mode()); if (m_tx_mode == TXModeSelect) @@ -459,20 +475,20 @@ ErrorOr Parser::compressed_header() return {}; } -ErrorOr Parser::read_tx_mode() +DecoderErrorOr Parser::read_tx_mode() { if (m_lossless) { m_tx_mode = Only_4x4; } else { - auto tx_mode = TRY(m_bit_stream->read_literal(2)); + auto tx_mode = TRY_READ(m_bit_stream->read_literal(2)); if (tx_mode == Allow_32x32) - tx_mode += TRY(m_bit_stream->read_literal(1)); + tx_mode += TRY_READ(m_bit_stream->read_literal(1)); m_tx_mode = static_cast(tx_mode); } return {}; } -ErrorOr Parser::tx_mode_probs() +DecoderErrorOr Parser::tx_mode_probs() { auto& tx_probs = m_probability_tables->tx_probs(); for (auto i = 0; i < TX_SIZE_CONTEXTS; i++) { @@ -490,9 +506,9 @@ ErrorOr Parser::tx_mode_probs() return {}; } -ErrorOr Parser::diff_update_prob(u8 prob) +DecoderErrorOr Parser::diff_update_prob(u8 prob) { - auto update_prob = TRY(m_bit_stream->read_bool(252)); + auto update_prob = TRY_READ(m_bit_stream->read_bool(252)); if (update_prob) { auto delta_prob = TRY(decode_term_subexp()); prob = inv_remap_prob(delta_prob, prob); @@ -500,19 +516,19 @@ ErrorOr Parser::diff_update_prob(u8 prob) return prob; } -ErrorOr Parser::decode_term_subexp() +DecoderErrorOr Parser::decode_term_subexp() { - if (TRY(m_bit_stream->read_literal(1)) == 0) - return TRY(m_bit_stream->read_literal(4)); - if (TRY(m_bit_stream->read_literal(1)) == 0) - return TRY(m_bit_stream->read_literal(4)) + 16; - if (TRY(m_bit_stream->read_literal(1)) == 0) - return TRY(m_bit_stream->read_literal(5)) + 32; + if (TRY_READ(m_bit_stream->read_literal(1)) == 0) + return TRY_READ(m_bit_stream->read_literal(4)); + if (TRY_READ(m_bit_stream->read_literal(1)) == 0) + return TRY_READ(m_bit_stream->read_literal(4)) + 16; + if (TRY_READ(m_bit_stream->read_literal(1)) == 0) + return TRY_READ(m_bit_stream->read_literal(5)) + 32; - auto v = TRY(m_bit_stream->read_literal(7)); + auto v = TRY_READ(m_bit_stream->read_literal(7)); if (v < 65) return v + 64; - return (v << 1u) - 1 + TRY(m_bit_stream->read_literal(1)); + return (v << 1u) - 1 + TRY_READ(m_bit_stream->read_literal(1)); } u8 Parser::inv_remap_prob(u8 delta_prob, u8 prob) @@ -533,11 +549,11 @@ u8 Parser::inv_recenter_nonneg(u8 v, u8 m) return m + (v >> 1u); } -ErrorOr Parser::read_coef_probs() +DecoderErrorOr Parser::read_coef_probs() { m_max_tx_size = tx_mode_to_biggest_tx_size[m_tx_mode]; for (u8 tx_size = 0; tx_size <= m_max_tx_size; tx_size++) { - auto update_probs = TRY(m_bit_stream->read_literal(1)); + auto update_probs = TRY_READ(m_bit_stream->read_literal(1)); if (update_probs == 1) { for (auto i = 0; i < 2; i++) { for (auto j = 0; j < 2; j++) { @@ -557,14 +573,14 @@ ErrorOr Parser::read_coef_probs() return {}; } -ErrorOr Parser::read_skip_prob() +DecoderErrorOr Parser::read_skip_prob() { for (auto i = 0; i < SKIP_CONTEXTS; i++) m_probability_tables->skip_prob()[i] = TRY(diff_update_prob(m_probability_tables->skip_prob()[i])); return {}; } -ErrorOr Parser::read_inter_mode_probs() +DecoderErrorOr Parser::read_inter_mode_probs() { for (auto i = 0; i < INTER_MODE_CONTEXTS; i++) { for (auto j = 0; j < INTER_MODES - 1; j++) @@ -573,7 +589,7 @@ ErrorOr Parser::read_inter_mode_probs() return {}; } -ErrorOr Parser::read_interp_filter_probs() +DecoderErrorOr Parser::read_interp_filter_probs() { for (auto i = 0; i < INTERP_FILTER_CONTEXTS; i++) { for (auto j = 0; j < SWITCHABLE_FILTERS - 1; j++) @@ -582,14 +598,14 @@ ErrorOr Parser::read_interp_filter_probs() return {}; } -ErrorOr Parser::read_is_inter_probs() +DecoderErrorOr Parser::read_is_inter_probs() { for (auto i = 0; i < IS_INTER_CONTEXTS; i++) m_probability_tables->is_inter_prob()[i] = TRY(diff_update_prob(m_probability_tables->is_inter_prob()[i])); return {}; } -ErrorOr Parser::frame_reference_mode() +DecoderErrorOr Parser::frame_reference_mode() { auto compound_reference_allowed = false; for (size_t i = 2; i <= REFS_PER_FRAME; i++) { @@ -597,11 +613,11 @@ ErrorOr Parser::frame_reference_mode() compound_reference_allowed = true; } if (compound_reference_allowed) { - auto non_single_reference = TRY(m_bit_stream->read_literal(1)); + auto non_single_reference = TRY_READ(m_bit_stream->read_literal(1)); if (non_single_reference == 0) { m_reference_mode = SingleReference; } else { - auto reference_select = TRY(m_bit_stream->read_literal(1)); + auto reference_select = TRY_READ(m_bit_stream->read_literal(1)); if (reference_select == 0) m_reference_mode = CompoundReference; else @@ -614,7 +630,7 @@ ErrorOr Parser::frame_reference_mode() return {}; } -ErrorOr Parser::frame_reference_mode_probs() +DecoderErrorOr Parser::frame_reference_mode_probs() { if (m_reference_mode == ReferenceModeSelect) { for (auto i = 0; i < COMP_MODE_CONTEXTS; i++) { @@ -638,7 +654,7 @@ ErrorOr Parser::frame_reference_mode_probs() return {}; } -ErrorOr Parser::read_y_mode_probs() +DecoderErrorOr Parser::read_y_mode_probs() { for (auto i = 0; i < BLOCK_SIZE_GROUPS; i++) { for (auto j = 0; j < INTRA_MODES - 1; j++) { @@ -649,7 +665,7 @@ ErrorOr Parser::read_y_mode_probs() return {}; } -ErrorOr Parser::read_partition_probs() +DecoderErrorOr Parser::read_partition_probs() { for (auto i = 0; i < PARTITION_CONTEXTS; i++) { for (auto j = 0; j < PARTITION_TYPES - 1; j++) { @@ -660,7 +676,7 @@ ErrorOr Parser::read_partition_probs() return {}; } -ErrorOr Parser::mv_probs() +DecoderErrorOr Parser::mv_probs() { for (auto j = 0; j < MV_JOINTS - 1; j++) { auto& mv_joint_probs = m_probability_tables->mv_joint_probs(); @@ -707,10 +723,10 @@ ErrorOr Parser::mv_probs() return {}; } -ErrorOr Parser::update_mv_prob(u8 prob) +DecoderErrorOr Parser::update_mv_prob(u8 prob) { - if (TRY(m_bit_stream->read_bool(252))) { - return (TRY(m_bit_stream->read_literal(7)) << 1u) | 1u; + if (TRY_READ(m_bit_stream->read_bool(252))) { + return (TRY_READ(m_bit_stream->read_literal(7)) << 1u) | 1u; } return prob; } @@ -751,7 +767,7 @@ void Parser::allocate_tile_data() m_allocated_dimensions = dimensions; } -ErrorOr Parser::decode_tiles() +DecoderErrorOr Parser::decode_tiles() { auto tile_cols = 1 << m_tile_cols_log2; auto tile_rows = 1 << m_tile_rows_log2; @@ -764,15 +780,15 @@ ErrorOr Parser::decode_tiles() if (last_tile) tile_size = m_bit_stream->bytes_remaining(); else - tile_size = TRY(m_bit_stream->read_bits(32)); + tile_size = TRY_READ(m_bit_stream->read_bits(32)); m_mi_row_start = get_tile_offset(tile_row, m_mi_rows, m_tile_rows_log2); m_mi_row_end = get_tile_offset(tile_row + 1, m_mi_rows, m_tile_rows_log2); m_mi_col_start = get_tile_offset(tile_col, m_mi_cols, m_tile_cols_log2); m_mi_col_end = get_tile_offset(tile_col + 1, m_mi_cols, m_tile_cols_log2); - TRY(m_bit_stream->init_bool(tile_size)); + TRY_READ(m_bit_stream->init_bool(tile_size)); TRY(decode_tile()); - TRY(m_bit_stream->exit_bool()); + TRY_READ(m_bit_stream->exit_bool()); } } return {}; @@ -806,7 +822,7 @@ u32 Parser::get_tile_offset(u32 tile_num, u32 mis, u32 tile_size_log2) return min(offset, mis); } -ErrorOr Parser::decode_tile() +DecoderErrorOr Parser::decode_tile() { for (auto row = m_mi_row_start; row < m_mi_row_end; row += 8) { clear_left_context(); @@ -826,17 +842,17 @@ void Parser::clear_left_context() clear_context(m_left_partition_context, m_sb64_rows * 8); } -ErrorOr Parser::decode_partition(u32 row, u32 col, u8 block_subsize) +DecoderErrorOr Parser::decode_partition(u32 row, u32 col, u8 block_subsize) { if (row >= m_mi_rows || col >= m_mi_cols) - return Error::from_string_literal("decode_partition: Row or column were outside valid ranges"); + return DecoderError::corrupted("Row or column were outside valid ranges"sv); m_block_subsize = block_subsize; m_num_8x8 = num_8x8_blocks_wide_lookup[block_subsize]; auto half_block_8x8 = m_num_8x8 >> 1; m_has_rows = (row + half_block_8x8) < m_mi_rows; m_has_cols = (col + half_block_8x8) < m_mi_cols; - auto partition = TRY(m_tree_parser->parse_tree(SyntaxElementType::Partition)); + auto partition = TRY_READ(m_tree_parser->parse_tree(SyntaxElementType::Partition)); auto subsize = subsize_lookup[partition][block_subsize]; if (subsize < Block_8x8 || partition == PartitionNone) { TRY(decode_block(row, col, subsize)); @@ -863,7 +879,7 @@ ErrorOr Parser::decode_partition(u32 row, u32 col, u8 block_subsize) return {}; } -ErrorOr Parser::decode_block(u32 row, u32 col, u8 subsize) +DecoderErrorOr Parser::decode_block(u32 row, u32 col, u8 subsize) { m_mi_row = row; m_mi_col = col; @@ -902,7 +918,7 @@ ErrorOr Parser::decode_block(u32 row, u32 col, u8 subsize) return {}; } -ErrorOr Parser::mode_info() +DecoderErrorOr Parser::mode_info() { if (m_frame_is_intra) TRY(intra_frame_mode_info()); @@ -911,7 +927,7 @@ ErrorOr Parser::mode_info() return {}; } -ErrorOr Parser::intra_frame_mode_info() +DecoderErrorOr Parser::intra_frame_mode_info() { TRY(intra_segment_id()); TRY(read_skip()); @@ -920,7 +936,7 @@ ErrorOr Parser::intra_frame_mode_info() m_ref_frame[1] = None; m_is_inter = false; if (m_mi_size >= Block_8x8) { - m_default_intra_mode = TRY(m_tree_parser->parse_tree(SyntaxElementType::DefaultIntraMode)); + m_default_intra_mode = TRY_READ(m_tree_parser->parse_tree(SyntaxElementType::DefaultIntraMode)); m_y_mode = m_default_intra_mode; for (auto& block_sub_mode : m_block_sub_modes) block_sub_mode = m_y_mode; @@ -930,7 +946,7 @@ ErrorOr Parser::intra_frame_mode_info() for (auto idy = 0; idy < 2; idy += m_num_4x4_h) { for (auto idx = 0; idx < 2; idx += m_num_4x4_w) { m_tree_parser->set_default_intra_mode_variables(idx, idy); - m_default_intra_mode = TRY(m_tree_parser->parse_tree(SyntaxElementType::DefaultIntraMode)); + m_default_intra_mode = TRY_READ(m_tree_parser->parse_tree(SyntaxElementType::DefaultIntraMode)); for (auto y = 0; y < m_num_4x4_h; y++) { for (auto x = 0; x < m_num_4x4_w; x++) { auto index = (idy + y) * 2 + idx + x; @@ -943,25 +959,25 @@ ErrorOr Parser::intra_frame_mode_info() } m_y_mode = m_default_intra_mode; } - m_uv_mode = TRY(m_tree_parser->parse_tree(SyntaxElementType::DefaultUVMode)); + m_uv_mode = TRY_READ(m_tree_parser->parse_tree(SyntaxElementType::DefaultUVMode)); return {}; } -ErrorOr Parser::intra_segment_id() +DecoderErrorOr Parser::intra_segment_id() { if (m_segmentation_enabled && m_segmentation_update_map) - m_segment_id = TRY(m_tree_parser->parse_tree(SyntaxElementType::SegmentID)); + m_segment_id = TRY_READ(m_tree_parser->parse_tree(SyntaxElementType::SegmentID)); else m_segment_id = 0; return {}; } -ErrorOr Parser::read_skip() +DecoderErrorOr Parser::read_skip() { if (seg_feature_active(SEG_LVL_SKIP)) m_skip = true; else - m_skip = TRY(m_tree_parser->parse_tree(SyntaxElementType::Skip)); + m_skip = TRY_READ(m_tree_parser->parse_tree(SyntaxElementType::Skip)); return {}; } @@ -970,17 +986,17 @@ bool Parser::seg_feature_active(u8 feature) return m_segmentation_enabled && m_feature_enabled[m_segment_id][feature]; } -ErrorOr Parser::read_tx_size(bool allow_select) +DecoderErrorOr Parser::read_tx_size(bool allow_select) { m_max_tx_size = max_txsize_lookup[m_mi_size]; if (allow_select && m_tx_mode == TXModeSelect && m_mi_size >= Block_8x8) - m_tx_size = TRY(m_tree_parser->parse_tree(SyntaxElementType::TXSize)); + m_tx_size = TRY_READ(m_tree_parser->parse_tree(SyntaxElementType::TXSize)); else m_tx_size = min(m_max_tx_size, tx_mode_to_biggest_tx_size[m_tx_mode]); return {}; } -ErrorOr Parser::inter_frame_mode_info() +DecoderErrorOr Parser::inter_frame_mode_info() { m_left_ref_frame[0] = m_available_l ? m_ref_frames[m_mi_row * m_mi_cols + (m_mi_col - 1)] : IntraFrame; m_above_ref_frame[0] = m_available_u ? m_ref_frames[(m_mi_row - 1) * m_mi_cols + m_mi_col] : IntraFrame; @@ -1002,7 +1018,7 @@ ErrorOr Parser::inter_frame_mode_info() return {}; } -ErrorOr Parser::inter_segment_id() +DecoderErrorOr Parser::inter_segment_id() { if (!m_segmentation_enabled) { m_segment_id = 0; @@ -1014,15 +1030,15 @@ ErrorOr Parser::inter_segment_id() return {}; } if (!m_segmentation_temporal_update) { - m_segment_id = TRY(m_tree_parser->parse_tree(SyntaxElementType::SegmentID)); + m_segment_id = TRY_READ(m_tree_parser->parse_tree(SyntaxElementType::SegmentID)); return {}; } - auto seg_id_predicted = TRY(m_tree_parser->parse_tree(SyntaxElementType::SegIDPredicted)); + auto seg_id_predicted = TRY_READ(m_tree_parser->parse_tree(SyntaxElementType::SegIDPredicted)); if (seg_id_predicted) m_segment_id = predicted_segment_id; else - m_segment_id = TRY(m_tree_parser->parse_tree(SyntaxElementType::SegmentID)); + m_segment_id = TRY_READ(m_tree_parser->parse_tree(SyntaxElementType::SegmentID)); for (size_t i = 0; i < num_8x8_blocks_wide_lookup[m_mi_size]; i++) m_above_seg_pred_context[m_mi_col + i] = seg_id_predicted; for (size_t i = 0; i < num_8x8_blocks_high_lookup[m_mi_size]; i++) @@ -1045,21 +1061,21 @@ u8 Parser::get_segment_id() return segment; } -ErrorOr Parser::read_is_inter() +DecoderErrorOr Parser::read_is_inter() { if (seg_feature_active(SEG_LVL_REF_FRAME)) m_is_inter = m_feature_data[m_segment_id][SEG_LVL_REF_FRAME] != IntraFrame; else - m_is_inter = TRY(m_tree_parser->parse_tree(SyntaxElementType::IsInter)); + m_is_inter = TRY_READ(m_tree_parser->parse_tree(SyntaxElementType::IsInter)); return {}; } -ErrorOr Parser::intra_block_mode_info() +DecoderErrorOr Parser::intra_block_mode_info() { m_ref_frame[0] = IntraFrame; m_ref_frame[1] = None; if (m_mi_size >= Block_8x8) { - m_y_mode = TRY(m_tree_parser->parse_tree(SyntaxElementType::IntraMode)); + m_y_mode = TRY_READ(m_tree_parser->parse_tree(SyntaxElementType::IntraMode)); for (auto& block_sub_mode : m_block_sub_modes) block_sub_mode = m_y_mode; } else { @@ -1068,7 +1084,7 @@ ErrorOr Parser::intra_block_mode_info() u8 sub_intra_mode; for (auto idy = 0; idy < 2; idy += m_num_4x4_h) { for (auto idx = 0; idx < 2; idx += m_num_4x4_w) { - sub_intra_mode = TRY(m_tree_parser->parse_tree(SyntaxElementType::SubIntraMode)); + sub_intra_mode = TRY_READ(m_tree_parser->parse_tree(SyntaxElementType::SubIntraMode)); for (auto y = 0; y < m_num_4x4_h; y++) { for (auto x = 0; x < m_num_4x4_w; x++) m_block_sub_modes[(idy + y) * 2 + idx + x] = sub_intra_mode; @@ -1077,11 +1093,11 @@ ErrorOr Parser::intra_block_mode_info() } m_y_mode = sub_intra_mode; } - m_uv_mode = TRY(m_tree_parser->parse_tree(SyntaxElementType::UVMode)); + m_uv_mode = TRY_READ(m_tree_parser->parse_tree(SyntaxElementType::UVMode)); return {}; } -ErrorOr Parser::inter_block_mode_info() +DecoderErrorOr Parser::inter_block_mode_info() { TRY(read_ref_frames()); for (auto j = 0; j < 2; j++) { @@ -1094,11 +1110,11 @@ ErrorOr Parser::inter_block_mode_info() if (seg_feature_active(SEG_LVL_SKIP)) { m_y_mode = ZeroMv; } else if (m_mi_size >= Block_8x8) { - auto inter_mode = TRY(m_tree_parser->parse_tree(SyntaxElementType::InterMode)); + auto inter_mode = TRY_READ(m_tree_parser->parse_tree(SyntaxElementType::InterMode)); m_y_mode = NearestMv + inter_mode; } if (m_interpolation_filter == Switchable) - m_interp_filter = TRY(m_tree_parser->parse_tree(SyntaxElementType::InterpFilter)); + m_interp_filter = TRY_READ(m_tree_parser->parse_tree(SyntaxElementType::InterpFilter)); else m_interp_filter = m_interpolation_filter; if (m_mi_size < Block_8x8) { @@ -1106,7 +1122,7 @@ ErrorOr Parser::inter_block_mode_info() m_num_4x4_h = num_4x4_blocks_high_lookup[m_mi_size]; for (auto idy = 0; idy < 2; idy += m_num_4x4_h) { for (auto idx = 0; idx < 2; idx += m_num_4x4_w) { - auto inter_mode = TRY(m_tree_parser->parse_tree(SyntaxElementType::InterMode)); + auto inter_mode = TRY_READ(m_tree_parser->parse_tree(SyntaxElementType::InterMode)); m_y_mode = NearestMv + inter_mode; if (m_y_mode == NearestMv || m_y_mode == NearMv) { for (auto j = 0; j < 1 + is_compound; j++) @@ -1134,7 +1150,7 @@ ErrorOr Parser::inter_block_mode_info() return {}; } -ErrorOr Parser::read_ref_frames() +DecoderErrorOr Parser::read_ref_frames() { if (seg_feature_active(SEG_LVL_REF_FRAME)) { m_ref_frame[0] = static_cast(m_feature_data[m_segment_id][SEG_LVL_REF_FRAME]); @@ -1143,19 +1159,19 @@ ErrorOr Parser::read_ref_frames() } ReferenceMode comp_mode; if (m_reference_mode == ReferenceModeSelect) - comp_mode = TRY(m_tree_parser->parse_tree(SyntaxElementType::CompMode)); + comp_mode = TRY_READ(m_tree_parser->parse_tree(SyntaxElementType::CompMode)); else comp_mode = m_reference_mode; if (comp_mode == CompoundReference) { auto idx = m_ref_frame_sign_bias[m_comp_fixed_ref]; - auto comp_ref = TRY(m_tree_parser->parse_tree(SyntaxElementType::CompRef)); + auto comp_ref = TRY_READ(m_tree_parser->parse_tree(SyntaxElementType::CompRef)); m_ref_frame[idx] = m_comp_fixed_ref; m_ref_frame[!idx] = m_comp_var_ref[comp_ref]; return {}; } - auto single_ref_p1 = TRY(m_tree_parser->parse_tree(SyntaxElementType::SingleRefP1)); + auto single_ref_p1 = TRY_READ(m_tree_parser->parse_tree(SyntaxElementType::SingleRefP1)); if (single_ref_p1) { - auto single_ref_p2 = TRY(m_tree_parser->parse_tree(SyntaxElementType::SingleRefP2)); + auto single_ref_p2 = TRY_READ(m_tree_parser->parse_tree(SyntaxElementType::SingleRefP2)); m_ref_frame[0] = single_ref_p2 ? AltRefFrame : GoldenFrame; } else { m_ref_frame[0] = LastFrame; @@ -1164,7 +1180,7 @@ ErrorOr Parser::read_ref_frames() return {}; } -ErrorOr Parser::assign_mv(bool is_compound) +DecoderErrorOr Parser::assign_mv(bool is_compound) { m_mv[1] = 0; for (auto i = 0; i < 1 + is_compound; i++) { @@ -1181,11 +1197,11 @@ ErrorOr Parser::assign_mv(bool is_compound) return {}; } -ErrorOr Parser::read_mv(u8 ref) +DecoderErrorOr Parser::read_mv(u8 ref) { - m_use_hp = m_allow_high_precision_mv && use_mv_hp(m_best_mv[ref]); + m_use_hp = m_allow_high_precision_mv && TRY(use_mv_hp(m_best_mv[ref])); MV diff_mv; - auto mv_joint = TRY(m_tree_parser->parse_tree(SyntaxElementType::MVJoint)); + auto mv_joint = TRY_READ(m_tree_parser->parse_tree(SyntaxElementType::MVJoint)); if (mv_joint == MvJointHzvnz || mv_joint == MvJointHnzvnz) diff_mv.set_row(TRY(read_mv_component(0))); if (mv_joint == MvJointHnzvz || mv_joint == MvJointHnzvnz) @@ -1194,31 +1210,31 @@ ErrorOr Parser::read_mv(u8 ref) return {}; } -ErrorOr Parser::read_mv_component(u8) +DecoderErrorOr Parser::read_mv_component(u8) { - auto mv_sign = TRY(m_tree_parser->parse_tree(SyntaxElementType::MVSign)); - auto mv_class = TRY(m_tree_parser->parse_tree(SyntaxElementType::MVClass)); + auto mv_sign = TRY_READ(m_tree_parser->parse_tree(SyntaxElementType::MVSign)); + auto mv_class = TRY_READ(m_tree_parser->parse_tree(SyntaxElementType::MVClass)); u32 mag; if (mv_class == MvClass0) { - auto mv_class0_bit = TRY(m_tree_parser->parse_tree(SyntaxElementType::MVClass0Bit)); - auto mv_class0_fr = TRY(m_tree_parser->parse_tree(SyntaxElementType::MVClass0FR)); - auto mv_class0_hp = TRY(m_tree_parser->parse_tree(SyntaxElementType::MVClass0HP)); + auto mv_class0_bit = TRY_READ(m_tree_parser->parse_tree(SyntaxElementType::MVClass0Bit)); + auto mv_class0_fr = TRY_READ(m_tree_parser->parse_tree(SyntaxElementType::MVClass0FR)); + auto mv_class0_hp = TRY_READ(m_tree_parser->parse_tree(SyntaxElementType::MVClass0HP)); mag = ((mv_class0_bit << 3) | (mv_class0_fr << 1) | mv_class0_hp) + 1; } else { auto d = 0; for (size_t i = 0; i < mv_class; i++) { - auto mv_bit = TRY(m_tree_parser->parse_tree(SyntaxElementType::MVBit)); + auto mv_bit = TRY_READ(m_tree_parser->parse_tree(SyntaxElementType::MVBit)); d |= mv_bit << i; } mag = CLASS0_SIZE << (mv_class + 2); - auto mv_fr = TRY(m_tree_parser->parse_tree(SyntaxElementType::MVFR)); - auto mv_hp = TRY(m_tree_parser->parse_tree(SyntaxElementType::MVHP)); + auto mv_fr = TRY_READ(m_tree_parser->parse_tree(SyntaxElementType::MVFR)); + auto mv_hp = TRY_READ(m_tree_parser->parse_tree(SyntaxElementType::MVHP)); mag += ((d << 3) | (mv_fr << 1) | mv_hp) + 1; } return (mv_sign ? -1 : 1) * static_cast(mag); } -ErrorOr Parser::residual() +DecoderErrorOr Parser::residual() { auto block_size = m_mi_size < Block_8x8 ? Block_8x8 : static_cast(m_mi_size); for (size_t plane = 0; plane < 3; plane++) { @@ -1287,7 +1303,7 @@ BlockSubsize Parser::get_plane_block_size(u32 subsize, u8 plane) return ss_size_lookup[subsize][sub_x][sub_y]; } -ErrorOr Parser::tokens(size_t plane, u32 start_x, u32 start_y, TXSize tx_size, u32 block_index) +DecoderErrorOr Parser::tokens(size_t plane, u32 start_x, u32 start_y, TXSize tx_size, u32 block_index) { m_tree_parser->set_start_x_and_y(start_x, start_y); size_t segment_eob = 16 << (tx_size << 1); @@ -1299,18 +1315,18 @@ ErrorOr Parser::tokens(size_t plane, u32 start_x, u32 start_y, TXSize tx_s auto band = (tx_size == TX_4x4) ? coefband_4x4[c] : coefband_8x8plus[c]; m_tree_parser->set_tokens_variables(band, c, plane, tx_size, pos); if (check_eob) { - auto more_coefs = TRY(m_tree_parser->parse_tree(SyntaxElementType::MoreCoefs)); + auto more_coefs = TRY_READ(m_tree_parser->parse_tree(SyntaxElementType::MoreCoefs)); if (!more_coefs) break; } - auto token = TRY(m_tree_parser->parse_tree(SyntaxElementType::Token)); + auto token = TRY_READ(m_tree_parser->parse_tree(SyntaxElementType::Token)); m_token_cache[pos] = energy_class[token]; if (token == ZeroToken) { m_tokens[pos] = 0; check_eob = false; } else { i32 coef = TRY(read_coef(token)); - auto sign_bit = TRY(m_bit_stream->read_literal(1)); + auto sign_bit = TRY_READ(m_bit_stream->read_literal(1)); m_tokens[pos] = sign_bit ? -coef : coef; check_eob = true; } @@ -1358,47 +1374,46 @@ u32 const* Parser::get_scan(size_t plane, TXSize tx_size, u32 block_index) return default_scan_32x32; } -ErrorOr Parser::read_coef(Token token) +DecoderErrorOr Parser::read_coef(Token token) { auto cat = extra_bits[token][0]; auto num_extra = extra_bits[token][1]; auto coef = extra_bits[token][2]; if (token == DctValCat6) { for (size_t e = 0; e < (u8)(m_bit_depth - 8); e++) { - auto high_bit = TRY(m_bit_stream->read_bool(255)); + auto high_bit = TRY_READ(m_bit_stream->read_bool(255)); coef += high_bit << (5 + m_bit_depth - e); } } for (size_t e = 0; e < num_extra; e++) { - auto coef_bit = TRY(m_bit_stream->read_bool(cat_probs[cat][e])); + auto coef_bit = TRY_READ(m_bit_stream->read_bool(cat_probs[cat][e])); coef += coef_bit << (num_extra - 1 - e); } return coef; } -ErrorOr Parser::find_mv_refs(ReferenceFrame, int) +DecoderErrorOr Parser::find_mv_refs(ReferenceFrame, int) { // TODO: Implement - return Error::from_string_literal("find_mv_refs: Not implemented"); + return DecoderError::not_implemented(); } -ErrorOr Parser::find_best_ref_mvs(int) +DecoderErrorOr Parser::find_best_ref_mvs(int) { // TODO: Implement - return Error::from_string_literal("find_best_ref_mvs: Not implemented"); + return DecoderError::not_implemented(); } -ErrorOr Parser::append_sub8x8_mvs(u8, u8) +DecoderErrorOr Parser::append_sub8x8_mvs(u8, u8) { // TODO: Implement - return Error::from_string_literal("append_sub8x8_mvs: Not implemented"); + return DecoderError::not_implemented(); } -bool Parser::use_mv_hp(const MV&) +DecoderErrorOr Parser::use_mv_hp(const MV&) { // TODO: Implement - VERIFY(false); - return true; + return DecoderError::not_implemented(); } void Parser::dump_info() diff --git a/Userland/Libraries/LibVideo/VP9/Parser.h b/Userland/Libraries/LibVideo/VP9/Parser.h index 95ff4a0734..50a6dd059f 100644 --- a/Userland/Libraries/LibVideo/VP9/Parser.h +++ b/Userland/Libraries/LibVideo/VP9/Parser.h @@ -7,14 +7,17 @@ #pragma once +#include +#include +#include +#include + #include "BitStream.h" #include "LookupTables.h" #include "MV.h" #include "ProbabilityTables.h" #include "SyntaxElementCounter.h" #include "TreeParser.h" -#include -#include namespace Video::VP9 { @@ -27,23 +30,12 @@ class Parser { public: explicit Parser(Decoder&); ~Parser(); - ErrorOr parse_frame(ByteBuffer const&); + DecoderErrorOr parse_frame(ByteBuffer const&); void dump_info(); private: - ErrorOr read_frame_type() - { - if (TRY(m_bit_stream->read_bit())) - return NonKeyFrame; - return KeyFrame; - } - - ErrorOr read_color_range() - { - if (TRY(m_bit_stream->read_bit())) - return FullSwing; - return StudioSwing; - } + DecoderErrorOr read_frame_type(); + DecoderErrorOr read_color_range(); /* Utilities */ void clear_context(Vector& context, size_t size); @@ -53,84 +45,84 @@ private: /* (6.1) Frame Syntax */ bool trailing_bits(); - ErrorOr refresh_probs(); + DecoderErrorOr refresh_probs(); /* (6.2) Uncompressed Header Syntax */ - ErrorOr uncompressed_header(); - ErrorOr frame_sync_code(); - ErrorOr color_config(); - ErrorOr frame_size(); - ErrorOr render_size(); - ErrorOr frame_size_with_refs(); + DecoderErrorOr uncompressed_header(); + DecoderErrorOr frame_sync_code(); + DecoderErrorOr color_config(); + DecoderErrorOr frame_size(); + DecoderErrorOr render_size(); + DecoderErrorOr frame_size_with_refs(); void compute_image_size(); - ErrorOr read_interpolation_filter(); - ErrorOr loop_filter_params(); - ErrorOr quantization_params(); - ErrorOr read_delta_q(); - ErrorOr segmentation_params(); - ErrorOr read_prob(); - ErrorOr tile_info(); + DecoderErrorOr read_interpolation_filter(); + DecoderErrorOr loop_filter_params(); + DecoderErrorOr quantization_params(); + DecoderErrorOr read_delta_q(); + DecoderErrorOr segmentation_params(); + DecoderErrorOr read_prob(); + DecoderErrorOr tile_info(); u16 calc_min_log2_tile_cols(); u16 calc_max_log2_tile_cols(); void setup_past_independence(); /* (6.3) Compressed Header Syntax */ - ErrorOr compressed_header(); - ErrorOr read_tx_mode(); - ErrorOr tx_mode_probs(); - ErrorOr diff_update_prob(u8 prob); - ErrorOr decode_term_subexp(); + DecoderErrorOr compressed_header(); + DecoderErrorOr read_tx_mode(); + DecoderErrorOr tx_mode_probs(); + DecoderErrorOr diff_update_prob(u8 prob); + DecoderErrorOr decode_term_subexp(); u8 inv_remap_prob(u8 delta_prob, u8 prob); u8 inv_recenter_nonneg(u8 v, u8 m); - ErrorOr read_coef_probs(); - ErrorOr read_skip_prob(); - ErrorOr read_inter_mode_probs(); - ErrorOr read_interp_filter_probs(); - ErrorOr read_is_inter_probs(); - ErrorOr frame_reference_mode(); - ErrorOr frame_reference_mode_probs(); - ErrorOr read_y_mode_probs(); - ErrorOr read_partition_probs(); - ErrorOr mv_probs(); - ErrorOr update_mv_prob(u8 prob); + DecoderErrorOr read_coef_probs(); + DecoderErrorOr read_skip_prob(); + DecoderErrorOr read_inter_mode_probs(); + DecoderErrorOr read_interp_filter_probs(); + DecoderErrorOr read_is_inter_probs(); + DecoderErrorOr frame_reference_mode(); + DecoderErrorOr frame_reference_mode_probs(); + DecoderErrorOr read_y_mode_probs(); + DecoderErrorOr read_partition_probs(); + DecoderErrorOr mv_probs(); + DecoderErrorOr update_mv_prob(u8 prob); void setup_compound_reference_mode(); /* (6.4) Decode Tiles Syntax */ - ErrorOr decode_tiles(); + DecoderErrorOr decode_tiles(); void clear_above_context(); u32 get_tile_offset(u32 tile_num, u32 mis, u32 tile_size_log2); - ErrorOr decode_tile(); + DecoderErrorOr decode_tile(); void clear_left_context(); - ErrorOr decode_partition(u32 row, u32 col, u8 block_subsize); - ErrorOr decode_block(u32 row, u32 col, u8 subsize); - ErrorOr mode_info(); - ErrorOr intra_frame_mode_info(); - ErrorOr intra_segment_id(); - ErrorOr read_skip(); + DecoderErrorOr decode_partition(u32 row, u32 col, u8 block_subsize); + DecoderErrorOr decode_block(u32 row, u32 col, u8 subsize); + DecoderErrorOr mode_info(); + DecoderErrorOr intra_frame_mode_info(); + DecoderErrorOr intra_segment_id(); + DecoderErrorOr read_skip(); bool seg_feature_active(u8 feature); - ErrorOr read_tx_size(bool allow_select); - ErrorOr inter_frame_mode_info(); - ErrorOr inter_segment_id(); + DecoderErrorOr read_tx_size(bool allow_select); + DecoderErrorOr inter_frame_mode_info(); + DecoderErrorOr inter_segment_id(); u8 get_segment_id(); - ErrorOr read_is_inter(); - ErrorOr intra_block_mode_info(); - ErrorOr inter_block_mode_info(); - ErrorOr read_ref_frames(); - ErrorOr assign_mv(bool is_compound); - ErrorOr read_mv(u8 ref); - ErrorOr read_mv_component(u8 component); - ErrorOr residual(); + DecoderErrorOr read_is_inter(); + DecoderErrorOr intra_block_mode_info(); + DecoderErrorOr inter_block_mode_info(); + DecoderErrorOr read_ref_frames(); + DecoderErrorOr assign_mv(bool is_compound); + DecoderErrorOr read_mv(u8 ref); + DecoderErrorOr read_mv_component(u8 component); + DecoderErrorOr residual(); TXSize get_uv_tx_size(); BlockSubsize get_plane_block_size(u32 subsize, u8 plane); - ErrorOr tokens(size_t plane, u32 x, u32 y, TXSize tx_size, u32 block_index); + DecoderErrorOr tokens(size_t plane, u32 x, u32 y, TXSize tx_size, u32 block_index); u32 const* get_scan(size_t plane, TXSize tx_size, u32 block_index); - ErrorOr read_coef(Token token); + DecoderErrorOr read_coef(Token token); /* (6.5) Motion Vector Prediction */ - ErrorOr find_mv_refs(ReferenceFrame, int block); - ErrorOr find_best_ref_mvs(int ref_list); - ErrorOr append_sub8x8_mvs(u8 block, u8 ref_list); - bool use_mv_hp(MV const& delta_mv); + DecoderErrorOr find_mv_refs(ReferenceFrame, int block); + DecoderErrorOr find_best_ref_mvs(int ref_list); + DecoderErrorOr append_sub8x8_mvs(u8 block, u8 ref_list); + DecoderErrorOr use_mv_hp(MV const& delta_mv); u8 m_profile { 0 }; u8 m_frame_to_show_map_index { 0 };