1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 00:57:45 +00:00

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.
This commit is contained in:
Zaggy1024 2022-09-13 19:40:37 -05:00 committed by Andrew Kaster
parent 72efd9a5ff
commit da9ff31166
5 changed files with 369 additions and 278 deletions

View file

@ -0,0 +1,82 @@
/*
* Copyright (c) 2022, Gregory Bertilson <zaggy1024@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/Error.h>
#include <AK/Format.h>
#include <AK/SourceLocation.h>
#include <AK/String.h>
#include <errno.h>
namespace Video {
struct DecoderError;
template<typename T>
using DecoderErrorOr = ErrorOr<T, DecoderError>;
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<typename... Parameters>
static DecoderError format(DecoderErrorCategory category, CheckedFormatString<Parameters...>&& 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(); \
})
}

View file

@ -15,7 +15,7 @@ Decoder::Decoder()
{ {
} }
ErrorOr<void> Decoder::decode_frame(ByteBuffer const& frame_data) DecoderErrorOr<void> Decoder::decode_frame(ByteBuffer const& frame_data)
{ {
TRY(m_parser->parse_frame(frame_data)); TRY(m_parser->parse_frame(frame_data));
// TODO: // 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; return left_count + right_count;
} }
ErrorOr<void> Decoder::adapt_coef_probs() DecoderErrorOr<void> Decoder::adapt_coef_probs()
{ {
u8 update_factor; u8 update_factor;
if (m_parser->m_frame_is_intra || m_parser->m_last_frame_type != KeyFrame) if (m_parser->m_frame_is_intra || m_parser->m_last_frame_type != KeyFrame)
@ -96,7 +96,7 @@ ErrorOr<void> Decoder::adapt_coef_probs()
} \ } \
} while (0) } while (0)
ErrorOr<void> Decoder::adapt_non_coef_probs() DecoderErrorOr<void> Decoder::adapt_non_coef_probs()
{ {
auto& probs = *m_parser->m_probability_tables; auto& probs = *m_parser->m_probability_tables;
auto& counter = *m_parser->m_syntax_element_counter; 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); return merge_prob(prob, counts[0], counts[1], COUNT_SAT, MAX_UPDATE_FACTOR);
} }
ErrorOr<void> Decoder::predict_intra(size_t, u32, u32, bool, bool, bool, TXSize, u32) DecoderErrorOr<void> Decoder::predict_intra(size_t, u32, u32, bool, bool, bool, TXSize, u32)
{ {
// TODO: Implement // TODO: Implement
return Error::from_string_literal("predict_intra not implemented"); return DecoderError::not_implemented();
} }
ErrorOr<void> Decoder::predict_inter(size_t, u32, u32, u32, u32, u32) DecoderErrorOr<void> Decoder::predict_inter(size_t, u32, u32, u32, u32, u32)
{ {
// TODO: Implement // TODO: Implement
return Error::from_string_literal("predict_inter not implemented"); return DecoderError::not_implemented();
} }
ErrorOr<void> Decoder::reconstruct(size_t, u32, u32, TXSize) DecoderErrorOr<void> Decoder::reconstruct(size_t, u32, u32, TXSize)
{ {
// TODO: Implement // TODO: Implement
return Error::from_string_literal("reconstruct not implemented"); return DecoderError::not_implemented();
} }
ErrorOr<void> Decoder::update_reference_frames() DecoderErrorOr<void> Decoder::update_reference_frames()
{ {
for (auto i = 0; i < NUM_REF_FRAMES; i++) { for (auto i = 0; i < NUM_REF_FRAMES; i++) {
dbgln("updating frame {}? {}", i, (m_parser->m_refresh_frame_flags & (1 << i)) == 1); dbgln("updating frame {}? {}", i, (m_parser->m_refresh_frame_flags & (1 << i)) == 1);

View file

@ -7,9 +7,11 @@
#pragma once #pragma once
#include "Parser.h"
#include <AK/ByteBuffer.h> #include <AK/ByteBuffer.h>
#include <AK/Error.h> #include <AK/Error.h>
#include <LibVideo/DecoderError.h>
#include "Parser.h"
namespace Video::VP9 { namespace Video::VP9 {
@ -18,27 +20,27 @@ class Decoder {
public: public:
Decoder(); Decoder();
ErrorOr<void> decode_frame(ByteBuffer const&); DecoderErrorOr<void> decode_frame(ByteBuffer const&);
void dump_frame_info(); void dump_frame_info();
private: private:
/* (8.4) Probability Adaptation Process */ /* (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_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); u8 merge_probs(int const* tree, int index, u8* probs, u8* counts, u8 count_sat, u8 max_update_factor);
ErrorOr<void> adapt_coef_probs(); DecoderErrorOr<void> adapt_coef_probs();
ErrorOr<void> adapt_non_coef_probs(); DecoderErrorOr<void> adapt_non_coef_probs();
void adapt_probs(int const* tree, u8* probs, u8* counts); void adapt_probs(int const* tree, u8* probs, u8* counts);
u8 adapt_prob(u8 prob, u8 counts[2]); u8 adapt_prob(u8 prob, u8 counts[2]);
/* (8.5) Prediction Processes */ /* (8.5) Prediction Processes */
ErrorOr<void> 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<void> 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<void> predict_inter(size_t plane, u32 x, u32 y, u32 w, u32 h, u32 block_index); DecoderErrorOr<void> predict_inter(size_t plane, u32 x, u32 y, u32 w, u32 h, u32 block_index);
/* (8.6) Reconstruction and Dequantization */ /* (8.6) Reconstruction and Dequantization */
ErrorOr<void> reconstruct(size_t plane, u32 x, u32 y, TXSize size); DecoderErrorOr<void> reconstruct(size_t plane, u32 transform_block_x, u32 transform_block_y, TXSize transform_block_size);
/* (8.10) Reference Frame Update Process */ /* (8.10) Reference Frame Update Process */
ErrorOr<void> update_reference_frames(); DecoderErrorOr<void> update_reference_frames();
NonnullOwnPtr<Parser> m_parser; NonnullOwnPtr<Parser> m_parser;
}; };

View file

@ -12,6 +12,8 @@
namespace Video::VP9 { namespace Video::VP9 {
#define TRY_READ(expression) DECODER_TRY(DecoderErrorCategory::Corrupted, expression)
Parser::Parser(Decoder& decoder) Parser::Parser(Decoder& decoder)
: m_probability_tables(make<ProbabilityTables>()) : m_probability_tables(make<ProbabilityTables>())
, m_tree_parser(make<TreeParser>(*this)) , m_tree_parser(make<TreeParser>(*this))
@ -40,7 +42,7 @@ void Parser::cleanup_tile_allocations()
} }
/* (6.1) */ /* (6.1) */
ErrorOr<void> Parser::parse_frame(ByteBuffer const& frame_data) DecoderErrorOr<void> Parser::parse_frame(ByteBuffer const& frame_data)
{ {
m_bit_stream = make<BitStream>(frame_data.data(), frame_data.size()); m_bit_stream = make<BitStream>(frame_data.data(), frame_data.size());
m_syntax_element_counter = make<SyntaxElementCounter>(); m_syntax_element_counter = make<SyntaxElementCounter>();
@ -48,18 +50,18 @@ ErrorOr<void> Parser::parse_frame(ByteBuffer const& frame_data)
TRY(uncompressed_header()); TRY(uncompressed_header());
dbgln("Finished reading uncompressed header"); dbgln("Finished reading uncompressed header");
if (!trailing_bits()) 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) 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_probs(m_frame_context_idx);
m_probability_tables->load_probs2(m_frame_context_idx); m_probability_tables->load_probs2(m_frame_context_idx);
m_syntax_element_counter->clear_counts(); 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); dbgln("Reading compressed header with size {}", m_header_size_in_bytes);
TRY(compressed_header()); TRY(compressed_header());
dbgln("Finished reading compressed header"); dbgln("Finished reading compressed header");
TRY(m_bit_stream->exit_bool()); TRY_READ(m_bit_stream->exit_bool());
TRY(decode_tiles()); TRY(decode_tiles());
TRY(refresh_probs()); TRY(refresh_probs());
@ -77,7 +79,7 @@ bool Parser::trailing_bits()
return true; return true;
} }
ErrorOr<void> Parser::refresh_probs() DecoderErrorOr<void> Parser::refresh_probs()
{ {
if (!m_error_resilient_mode && !m_frame_parallel_decoding_mode) { if (!m_error_resilient_mode && !m_frame_parallel_decoding_mode) {
m_probability_tables->load_probs(m_frame_context_idx); m_probability_tables->load_probs(m_frame_context_idx);
@ -92,20 +94,34 @@ ErrorOr<void> Parser::refresh_probs()
return {}; return {};
} }
/* (6.2) */ DecoderErrorOr<FrameType> Parser::read_frame_type()
ErrorOr<void> Parser::uncompressed_header()
{ {
auto frame_marker = TRY(m_bit_stream->read_bits(2)); if (TRY_READ(m_bit_stream->read_bit()))
return NonKeyFrame;
return KeyFrame;
}
DecoderErrorOr<ColorRange> Parser::read_color_range()
{
if (TRY_READ(m_bit_stream->read_bit()))
return FullSwing;
return StudioSwing;
}
/* (6.2) */
DecoderErrorOr<void> Parser::uncompressed_header()
{
auto frame_marker = TRY_READ(m_bit_stream->read_bits(2));
if (frame_marker != 2) if (frame_marker != 2)
return Error::from_string_literal("uncompressed_header: Frame marker must be 2"); return DecoderError::corrupted("uncompressed_header: Frame marker must be 2"sv);
auto profile_low_bit = TRY(m_bit_stream->read_bit()); auto profile_low_bit = TRY_READ(m_bit_stream->read_bit());
auto profile_high_bit = TRY(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; m_profile = (profile_high_bit << 1u) + profile_low_bit;
if (m_profile == 3 && TRY(m_bit_stream->read_bit())) if (m_profile == 3 && TRY_READ(m_bit_stream->read_bit()))
return Error::from_string_literal("uncompressed_header: Profile 3 reserved bit was non-zero"); return DecoderError::corrupted("uncompressed_header: Profile 3 reserved bit was non-zero"sv);
auto show_existing_frame = TRY(m_bit_stream->read_bit()); auto show_existing_frame = TRY_READ(m_bit_stream->read_bit());
if (show_existing_frame) { 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_header_size_in_bytes = 0;
m_refresh_frame_flags = 0; m_refresh_frame_flags = 0;
m_loop_filter_level = 0; m_loop_filter_level = 0;
@ -114,8 +130,8 @@ ErrorOr<void> Parser::uncompressed_header()
m_last_frame_type = m_frame_type; m_last_frame_type = m_frame_type;
m_frame_type = TRY(read_frame_type()); m_frame_type = TRY(read_frame_type());
m_show_frame = TRY(m_bit_stream->read_bit()); m_show_frame = TRY_READ(m_bit_stream->read_bit());
m_error_resilient_mode = TRY(m_bit_stream->read_bit()); m_error_resilient_mode = TRY_READ(m_bit_stream->read_bit());
if (m_frame_type == KeyFrame) { if (m_frame_type == KeyFrame) {
TRY(frame_sync_code()); TRY(frame_sync_code());
@ -125,10 +141,10 @@ ErrorOr<void> Parser::uncompressed_header()
m_refresh_frame_flags = 0xFF; m_refresh_frame_flags = 0xFF;
m_frame_is_intra = true; m_frame_is_intra = true;
} else { } 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) { 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 { } else {
m_reset_frame_context = 0; m_reset_frame_context = 0;
} }
@ -144,30 +160,30 @@ ErrorOr<void> Parser::uncompressed_header()
m_bit_depth = 8; 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(frame_size());
TRY(render_size()); TRY(render_size());
} else { } 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++) { for (auto i = 0; i < 3; i++) {
m_ref_frame_idx[i] = TRY(m_bit_stream->read_bits(3)); m_ref_frame_idx[i] = TRY_READ(m_bit_stream->read_bits(3));
m_ref_frame_sign_bias[LastFrame + i] = TRY(m_bit_stream->read_bit()); m_ref_frame_sign_bias[LastFrame + i] = TRY_READ(m_bit_stream->read_bit());
} }
TRY(frame_size_with_refs()); 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()); TRY(read_interpolation_filter());
} }
} }
if (!m_error_resilient_mode) { if (!m_error_resilient_mode) {
m_refresh_frame_context = TRY(m_bit_stream->read_bit()); m_refresh_frame_context = TRY_READ(m_bit_stream->read_bit());
m_frame_parallel_decoding_mode = TRY(m_bit_stream->read_bit()); m_frame_parallel_decoding_mode = TRY_READ(m_bit_stream->read_bit());
} else { } else {
m_refresh_frame_context = false; m_refresh_frame_context = false;
m_frame_parallel_decoding_mode = true; 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) { if (m_frame_is_intra || m_error_resilient_mode) {
setup_past_independence(); setup_past_independence();
if (m_frame_type == KeyFrame || m_error_resilient_mode || m_reset_frame_context == 3) { if (m_frame_type == KeyFrame || m_error_resilient_mode || m_reset_frame_context == 3) {
@ -185,41 +201,41 @@ ErrorOr<void> Parser::uncompressed_header()
TRY(segmentation_params()); TRY(segmentation_params());
TRY(tile_info()); 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 {}; return {};
} }
ErrorOr<void> Parser::frame_sync_code() DecoderErrorOr<void> Parser::frame_sync_code()
{ {
if (TRY(m_bit_stream->read_f8()) != 0x49) if (TRY_READ(m_bit_stream->read_f8()) != 0x49)
return Error::from_string_literal("frame_sync_code: Byte 0 was not 0x49."); return DecoderError::corrupted("frame_sync_code: Byte 0 was not 0x49."sv);
if (TRY(m_bit_stream->read_f8()) != 0x83) if (TRY_READ(m_bit_stream->read_f8()) != 0x83)
return Error::from_string_literal("frame_sync_code: Byte 1 was not 0x83."); return DecoderError::corrupted("frame_sync_code: Byte 1 was not 0x83."sv);
if (TRY(m_bit_stream->read_f8()) != 0x42) if (TRY_READ(m_bit_stream->read_f8()) != 0x42)
return Error::from_string_literal("frame_sync_code: Byte 2 was not 0x42."); return DecoderError::corrupted("frame_sync_code: Byte 2 was not 0x42."sv);
return {}; return {};
} }
ErrorOr<void> Parser::color_config() DecoderErrorOr<void> Parser::color_config()
{ {
if (m_profile >= 2) { 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 { } else {
m_bit_depth = 8; 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); VERIFY(color_space <= RGB);
m_color_space = static_cast<ColorSpace>(color_space); m_color_space = static_cast<ColorSpace>(color_space);
if (color_space != RGB) { if (color_space != RGB) {
m_color_range = TRY(read_color_range()); m_color_range = TRY(read_color_range());
if (m_profile == 1 || m_profile == 3) { if (m_profile == 1 || m_profile == 3) {
m_subsampling_x = TRY(m_bit_stream->read_bit()); m_subsampling_x = TRY_READ(m_bit_stream->read_bit());
m_subsampling_y = TRY(m_bit_stream->read_bit()); m_subsampling_y = TRY_READ(m_bit_stream->read_bit());
if (TRY(m_bit_stream->read_bit())) if (TRY_READ(m_bit_stream->read_bit()))
return Error::from_string_literal("color_config: Subsampling reserved zero was set"); return DecoderError::corrupted("color_config: Subsampling reserved zero was set"sv);
} else { } else {
m_subsampling_x = true; m_subsampling_x = true;
m_subsampling_y = true; m_subsampling_y = true;
@ -229,26 +245,26 @@ ErrorOr<void> Parser::color_config()
if (m_profile == 1 || m_profile == 3) { if (m_profile == 1 || m_profile == 3) {
m_subsampling_x = false; m_subsampling_x = false;
m_subsampling_y = false; m_subsampling_y = false;
if (TRY(m_bit_stream->read_bit())) if (TRY_READ(m_bit_stream->read_bit()))
return Error::from_string_literal("color_config: RGB reserved zero was set"); return DecoderError::corrupted("color_config: RGB reserved zero was set"sv);
} }
} }
return {}; return {};
} }
ErrorOr<void> Parser::frame_size() DecoderErrorOr<void> Parser::frame_size()
{ {
m_frame_width = TRY(m_bit_stream->read_f16()) + 1; m_frame_width = TRY_READ(m_bit_stream->read_f16()) + 1;
m_frame_height = TRY(m_bit_stream->read_f16()) + 1; m_frame_height = TRY_READ(m_bit_stream->read_f16()) + 1;
compute_image_size(); compute_image_size();
return {}; return {};
} }
ErrorOr<void> Parser::render_size() DecoderErrorOr<void> Parser::render_size()
{ {
if (TRY(m_bit_stream->read_bit())) { if (TRY_READ(m_bit_stream->read_bit())) {
m_render_width = TRY(m_bit_stream->read_f16()) + 1; m_render_width = TRY_READ(m_bit_stream->read_f16()) + 1;
m_render_height = TRY(m_bit_stream->read_f16()) + 1; m_render_height = TRY_READ(m_bit_stream->read_f16()) + 1;
} else { } else {
m_render_width = m_frame_width; m_render_width = m_frame_width;
m_render_height = m_frame_height; m_render_height = m_frame_height;
@ -256,11 +272,11 @@ ErrorOr<void> Parser::render_size()
return {}; return {};
} }
ErrorOr<void> Parser::frame_size_with_refs() DecoderErrorOr<void> Parser::frame_size_with_refs()
{ {
bool found_ref; bool found_ref;
for (auto frame_index : m_ref_frame_idx) { 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) { if (found_ref) {
dbgln("Reading size from ref frame {}", frame_index); dbgln("Reading size from ref frame {}", frame_index);
m_frame_width = m_ref_frame_width[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; m_sb64_rows = (m_mi_rows + 7u) >> 3u;
} }
ErrorOr<void> Parser::read_interpolation_filter() DecoderErrorOr<void> Parser::read_interpolation_filter()
{ {
if (TRY(m_bit_stream->read_bit())) { if (TRY_READ(m_bit_stream->read_bit())) {
m_interpolation_filter = Switchable; m_interpolation_filter = Switchable;
} else { } 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 {}; return {};
} }
ErrorOr<void> Parser::loop_filter_params() DecoderErrorOr<void> Parser::loop_filter_params()
{ {
m_loop_filter_level = TRY(m_bit_stream->read_bits(6)); m_loop_filter_level = TRY_READ(m_bit_stream->read_bits(6));
m_loop_filter_sharpness = TRY(m_bit_stream->read_bits(3)); m_loop_filter_sharpness = TRY_READ(m_bit_stream->read_bits(3));
m_loop_filter_delta_enabled = TRY(m_bit_stream->read_bit()); m_loop_filter_delta_enabled = TRY_READ(m_bit_stream->read_bit());
if (m_loop_filter_delta_enabled) { 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) { for (auto& loop_filter_ref_delta : m_loop_filter_ref_deltas) {
if (TRY(m_bit_stream->read_bit())) if (TRY_READ(m_bit_stream->read_bit()))
loop_filter_ref_delta = TRY(m_bit_stream->read_s(6)); loop_filter_ref_delta = TRY_READ(m_bit_stream->read_s(6));
} }
for (auto& loop_filter_mode_delta : m_loop_filter_mode_deltas) { for (auto& loop_filter_mode_delta : m_loop_filter_mode_deltas) {
if (TRY(m_bit_stream->read_bit())) if (TRY_READ(m_bit_stream->read_bit()))
loop_filter_mode_delta = TRY(m_bit_stream->read_s(6)); loop_filter_mode_delta = TRY_READ(m_bit_stream->read_s(6));
} }
} }
} }
@ -317,9 +333,9 @@ ErrorOr<void> Parser::loop_filter_params()
return {}; return {};
} }
ErrorOr<void> Parser::quantization_params() DecoderErrorOr<void> 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_y_dc = TRY(read_delta_q());
auto delta_q_uv_dc = TRY(read_delta_q()); auto delta_q_uv_dc = TRY(read_delta_q());
auto delta_q_uv_ac = TRY(read_delta_q()); auto delta_q_uv_ac = TRY(read_delta_q());
@ -327,44 +343,44 @@ ErrorOr<void> Parser::quantization_params()
return {}; return {};
} }
ErrorOr<i8> Parser::read_delta_q() DecoderErrorOr<i8> Parser::read_delta_q()
{ {
if (TRY(m_bit_stream->read_bit())) if (TRY_READ(m_bit_stream->read_bit()))
return m_bit_stream->read_s(4); return TRY_READ(m_bit_stream->read_s(4));
return 0; return 0;
} }
ErrorOr<void> Parser::segmentation_params() DecoderErrorOr<void> 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) if (!m_segmentation_enabled)
return {}; 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) { if (m_segmentation_update_map) {
for (auto& segmentation_tree_prob : m_segmentation_tree_probs) for (auto& segmentation_tree_prob : m_segmentation_tree_probs)
segmentation_tree_prob = TRY(read_prob()); 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) for (auto& segmentation_pred_prob : m_segmentation_pred_prob)
segmentation_pred_prob = m_segmentation_temporal_update ? TRY(read_prob()) : 255; 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) if (!segmentation_update_data)
return {}; 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 i = 0; i < MAX_SEGMENTS; i++) {
for (auto j = 0; j < SEG_LVL_MAX; j++) { for (auto j = 0; j < SEG_LVL_MAX; j++) {
auto feature_value = 0; 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; m_feature_enabled[i][j] = feature_enabled;
if (feature_enabled) { if (feature_enabled) {
auto bits_to_read = segmentation_feature_bits[j]; 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 (segmentation_feature_signed[j]) {
if (TRY(m_bit_stream->read_bit())) if (TRY_READ(m_bit_stream->read_bit()))
feature_value = -feature_value; feature_value = -feature_value;
} }
} }
@ -375,27 +391,27 @@ ErrorOr<void> Parser::segmentation_params()
return {}; return {};
} }
ErrorOr<u8> Parser::read_prob() DecoderErrorOr<u8> Parser::read_prob()
{ {
if (TRY(m_bit_stream->read_bit())) if (TRY_READ(m_bit_stream->read_bit()))
return TRY(m_bit_stream->read_f8()); return TRY_READ(m_bit_stream->read_f8());
return 255; return 255;
} }
ErrorOr<void> Parser::tile_info() DecoderErrorOr<void> Parser::tile_info()
{ {
auto min_log2_tile_cols = calc_min_log2_tile_cols(); auto min_log2_tile_cols = calc_min_log2_tile_cols();
auto max_log2_tile_cols = calc_max_log2_tile_cols(); auto max_log2_tile_cols = calc_max_log2_tile_cols();
m_tile_cols_log2 = min_log2_tile_cols; m_tile_cols_log2 = min_log2_tile_cols;
while (m_tile_cols_log2 < max_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++; m_tile_cols_log2++;
else else
break; 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) { 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 {}; return {};
} }
@ -438,7 +454,7 @@ void Parser::setup_past_independence()
m_probability_tables->reset_probs(); m_probability_tables->reset_probs();
} }
ErrorOr<void> Parser::compressed_header() DecoderErrorOr<void> Parser::compressed_header()
{ {
TRY(read_tx_mode()); TRY(read_tx_mode());
if (m_tx_mode == TXModeSelect) if (m_tx_mode == TXModeSelect)
@ -459,20 +475,20 @@ ErrorOr<void> Parser::compressed_header()
return {}; return {};
} }
ErrorOr<void> Parser::read_tx_mode() DecoderErrorOr<void> Parser::read_tx_mode()
{ {
if (m_lossless) { if (m_lossless) {
m_tx_mode = Only_4x4; m_tx_mode = Only_4x4;
} else { } 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) 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<TXMode>(tx_mode); m_tx_mode = static_cast<TXMode>(tx_mode);
} }
return {}; return {};
} }
ErrorOr<void> Parser::tx_mode_probs() DecoderErrorOr<void> Parser::tx_mode_probs()
{ {
auto& tx_probs = m_probability_tables->tx_probs(); auto& tx_probs = m_probability_tables->tx_probs();
for (auto i = 0; i < TX_SIZE_CONTEXTS; i++) { for (auto i = 0; i < TX_SIZE_CONTEXTS; i++) {
@ -490,9 +506,9 @@ ErrorOr<void> Parser::tx_mode_probs()
return {}; return {};
} }
ErrorOr<u8> Parser::diff_update_prob(u8 prob) DecoderErrorOr<u8> 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) { if (update_prob) {
auto delta_prob = TRY(decode_term_subexp()); auto delta_prob = TRY(decode_term_subexp());
prob = inv_remap_prob(delta_prob, prob); prob = inv_remap_prob(delta_prob, prob);
@ -500,19 +516,19 @@ ErrorOr<u8> Parser::diff_update_prob(u8 prob)
return prob; return prob;
} }
ErrorOr<u8> Parser::decode_term_subexp() DecoderErrorOr<u8> Parser::decode_term_subexp()
{ {
if (TRY(m_bit_stream->read_literal(1)) == 0) if (TRY_READ(m_bit_stream->read_literal(1)) == 0)
return TRY(m_bit_stream->read_literal(4)); return TRY_READ(m_bit_stream->read_literal(4));
if (TRY(m_bit_stream->read_literal(1)) == 0) if (TRY_READ(m_bit_stream->read_literal(1)) == 0)
return TRY(m_bit_stream->read_literal(4)) + 16; return TRY_READ(m_bit_stream->read_literal(4)) + 16;
if (TRY(m_bit_stream->read_literal(1)) == 0) if (TRY_READ(m_bit_stream->read_literal(1)) == 0)
return TRY(m_bit_stream->read_literal(5)) + 32; 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) if (v < 65)
return v + 64; 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) 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); return m + (v >> 1u);
} }
ErrorOr<void> Parser::read_coef_probs() DecoderErrorOr<void> Parser::read_coef_probs()
{ {
m_max_tx_size = tx_mode_to_biggest_tx_size[m_tx_mode]; 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++) { 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) { if (update_probs == 1) {
for (auto i = 0; i < 2; i++) { for (auto i = 0; i < 2; i++) {
for (auto j = 0; j < 2; j++) { for (auto j = 0; j < 2; j++) {
@ -557,14 +573,14 @@ ErrorOr<void> Parser::read_coef_probs()
return {}; return {};
} }
ErrorOr<void> Parser::read_skip_prob() DecoderErrorOr<void> Parser::read_skip_prob()
{ {
for (auto i = 0; i < SKIP_CONTEXTS; i++) for (auto i = 0; i < SKIP_CONTEXTS; i++)
m_probability_tables->skip_prob()[i] = TRY(diff_update_prob(m_probability_tables->skip_prob()[i])); m_probability_tables->skip_prob()[i] = TRY(diff_update_prob(m_probability_tables->skip_prob()[i]));
return {}; return {};
} }
ErrorOr<void> Parser::read_inter_mode_probs() DecoderErrorOr<void> Parser::read_inter_mode_probs()
{ {
for (auto i = 0; i < INTER_MODE_CONTEXTS; i++) { for (auto i = 0; i < INTER_MODE_CONTEXTS; i++) {
for (auto j = 0; j < INTER_MODES - 1; j++) for (auto j = 0; j < INTER_MODES - 1; j++)
@ -573,7 +589,7 @@ ErrorOr<void> Parser::read_inter_mode_probs()
return {}; return {};
} }
ErrorOr<void> Parser::read_interp_filter_probs() DecoderErrorOr<void> Parser::read_interp_filter_probs()
{ {
for (auto i = 0; i < INTERP_FILTER_CONTEXTS; i++) { for (auto i = 0; i < INTERP_FILTER_CONTEXTS; i++) {
for (auto j = 0; j < SWITCHABLE_FILTERS - 1; j++) for (auto j = 0; j < SWITCHABLE_FILTERS - 1; j++)
@ -582,14 +598,14 @@ ErrorOr<void> Parser::read_interp_filter_probs()
return {}; return {};
} }
ErrorOr<void> Parser::read_is_inter_probs() DecoderErrorOr<void> Parser::read_is_inter_probs()
{ {
for (auto i = 0; i < IS_INTER_CONTEXTS; i++) 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])); m_probability_tables->is_inter_prob()[i] = TRY(diff_update_prob(m_probability_tables->is_inter_prob()[i]));
return {}; return {};
} }
ErrorOr<void> Parser::frame_reference_mode() DecoderErrorOr<void> Parser::frame_reference_mode()
{ {
auto compound_reference_allowed = false; auto compound_reference_allowed = false;
for (size_t i = 2; i <= REFS_PER_FRAME; i++) { for (size_t i = 2; i <= REFS_PER_FRAME; i++) {
@ -597,11 +613,11 @@ ErrorOr<void> Parser::frame_reference_mode()
compound_reference_allowed = true; compound_reference_allowed = true;
} }
if (compound_reference_allowed) { 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) { if (non_single_reference == 0) {
m_reference_mode = SingleReference; m_reference_mode = SingleReference;
} else { } 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) if (reference_select == 0)
m_reference_mode = CompoundReference; m_reference_mode = CompoundReference;
else else
@ -614,7 +630,7 @@ ErrorOr<void> Parser::frame_reference_mode()
return {}; return {};
} }
ErrorOr<void> Parser::frame_reference_mode_probs() DecoderErrorOr<void> Parser::frame_reference_mode_probs()
{ {
if (m_reference_mode == ReferenceModeSelect) { if (m_reference_mode == ReferenceModeSelect) {
for (auto i = 0; i < COMP_MODE_CONTEXTS; i++) { for (auto i = 0; i < COMP_MODE_CONTEXTS; i++) {
@ -638,7 +654,7 @@ ErrorOr<void> Parser::frame_reference_mode_probs()
return {}; return {};
} }
ErrorOr<void> Parser::read_y_mode_probs() DecoderErrorOr<void> Parser::read_y_mode_probs()
{ {
for (auto i = 0; i < BLOCK_SIZE_GROUPS; i++) { for (auto i = 0; i < BLOCK_SIZE_GROUPS; i++) {
for (auto j = 0; j < INTRA_MODES - 1; j++) { for (auto j = 0; j < INTRA_MODES - 1; j++) {
@ -649,7 +665,7 @@ ErrorOr<void> Parser::read_y_mode_probs()
return {}; return {};
} }
ErrorOr<void> Parser::read_partition_probs() DecoderErrorOr<void> Parser::read_partition_probs()
{ {
for (auto i = 0; i < PARTITION_CONTEXTS; i++) { for (auto i = 0; i < PARTITION_CONTEXTS; i++) {
for (auto j = 0; j < PARTITION_TYPES - 1; j++) { for (auto j = 0; j < PARTITION_TYPES - 1; j++) {
@ -660,7 +676,7 @@ ErrorOr<void> Parser::read_partition_probs()
return {}; return {};
} }
ErrorOr<void> Parser::mv_probs() DecoderErrorOr<void> Parser::mv_probs()
{ {
for (auto j = 0; j < MV_JOINTS - 1; j++) { for (auto j = 0; j < MV_JOINTS - 1; j++) {
auto& mv_joint_probs = m_probability_tables->mv_joint_probs(); auto& mv_joint_probs = m_probability_tables->mv_joint_probs();
@ -707,10 +723,10 @@ ErrorOr<void> Parser::mv_probs()
return {}; return {};
} }
ErrorOr<u8> Parser::update_mv_prob(u8 prob) DecoderErrorOr<u8> Parser::update_mv_prob(u8 prob)
{ {
if (TRY(m_bit_stream->read_bool(252))) { if (TRY_READ(m_bit_stream->read_bool(252))) {
return (TRY(m_bit_stream->read_literal(7)) << 1u) | 1u; return (TRY_READ(m_bit_stream->read_literal(7)) << 1u) | 1u;
} }
return prob; return prob;
} }
@ -751,7 +767,7 @@ void Parser::allocate_tile_data()
m_allocated_dimensions = dimensions; m_allocated_dimensions = dimensions;
} }
ErrorOr<void> Parser::decode_tiles() DecoderErrorOr<void> Parser::decode_tiles()
{ {
auto tile_cols = 1 << m_tile_cols_log2; auto tile_cols = 1 << m_tile_cols_log2;
auto tile_rows = 1 << m_tile_rows_log2; auto tile_rows = 1 << m_tile_rows_log2;
@ -764,15 +780,15 @@ ErrorOr<void> Parser::decode_tiles()
if (last_tile) if (last_tile)
tile_size = m_bit_stream->bytes_remaining(); tile_size = m_bit_stream->bytes_remaining();
else 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_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_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_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); 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(decode_tile());
TRY(m_bit_stream->exit_bool()); TRY_READ(m_bit_stream->exit_bool());
} }
} }
return {}; return {};
@ -806,7 +822,7 @@ u32 Parser::get_tile_offset(u32 tile_num, u32 mis, u32 tile_size_log2)
return min(offset, mis); return min(offset, mis);
} }
ErrorOr<void> Parser::decode_tile() DecoderErrorOr<void> Parser::decode_tile()
{ {
for (auto row = m_mi_row_start; row < m_mi_row_end; row += 8) { for (auto row = m_mi_row_start; row < m_mi_row_end; row += 8) {
clear_left_context(); clear_left_context();
@ -826,17 +842,17 @@ void Parser::clear_left_context()
clear_context(m_left_partition_context, m_sb64_rows * 8); clear_context(m_left_partition_context, m_sb64_rows * 8);
} }
ErrorOr<void> Parser::decode_partition(u32 row, u32 col, u8 block_subsize) DecoderErrorOr<void> Parser::decode_partition(u32 row, u32 col, u8 block_subsize)
{ {
if (row >= m_mi_rows || col >= m_mi_cols) 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_block_subsize = block_subsize;
m_num_8x8 = num_8x8_blocks_wide_lookup[block_subsize]; m_num_8x8 = num_8x8_blocks_wide_lookup[block_subsize];
auto half_block_8x8 = m_num_8x8 >> 1; auto half_block_8x8 = m_num_8x8 >> 1;
m_has_rows = (row + half_block_8x8) < m_mi_rows; m_has_rows = (row + half_block_8x8) < m_mi_rows;
m_has_cols = (col + half_block_8x8) < m_mi_cols; 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]; auto subsize = subsize_lookup[partition][block_subsize];
if (subsize < Block_8x8 || partition == PartitionNone) { if (subsize < Block_8x8 || partition == PartitionNone) {
TRY(decode_block(row, col, subsize)); TRY(decode_block(row, col, subsize));
@ -863,7 +879,7 @@ ErrorOr<void> Parser::decode_partition(u32 row, u32 col, u8 block_subsize)
return {}; return {};
} }
ErrorOr<void> Parser::decode_block(u32 row, u32 col, u8 subsize) DecoderErrorOr<void> Parser::decode_block(u32 row, u32 col, u8 subsize)
{ {
m_mi_row = row; m_mi_row = row;
m_mi_col = col; m_mi_col = col;
@ -902,7 +918,7 @@ ErrorOr<void> Parser::decode_block(u32 row, u32 col, u8 subsize)
return {}; return {};
} }
ErrorOr<void> Parser::mode_info() DecoderErrorOr<void> Parser::mode_info()
{ {
if (m_frame_is_intra) if (m_frame_is_intra)
TRY(intra_frame_mode_info()); TRY(intra_frame_mode_info());
@ -911,7 +927,7 @@ ErrorOr<void> Parser::mode_info()
return {}; return {};
} }
ErrorOr<void> Parser::intra_frame_mode_info() DecoderErrorOr<void> Parser::intra_frame_mode_info()
{ {
TRY(intra_segment_id()); TRY(intra_segment_id());
TRY(read_skip()); TRY(read_skip());
@ -920,7 +936,7 @@ ErrorOr<void> Parser::intra_frame_mode_info()
m_ref_frame[1] = None; m_ref_frame[1] = None;
m_is_inter = false; m_is_inter = false;
if (m_mi_size >= Block_8x8) { if (m_mi_size >= Block_8x8) {
m_default_intra_mode = TRY(m_tree_parser->parse_tree<IntraMode>(SyntaxElementType::DefaultIntraMode)); m_default_intra_mode = TRY_READ(m_tree_parser->parse_tree<IntraMode>(SyntaxElementType::DefaultIntraMode));
m_y_mode = m_default_intra_mode; m_y_mode = m_default_intra_mode;
for (auto& block_sub_mode : m_block_sub_modes) for (auto& block_sub_mode : m_block_sub_modes)
block_sub_mode = m_y_mode; block_sub_mode = m_y_mode;
@ -930,7 +946,7 @@ ErrorOr<void> Parser::intra_frame_mode_info()
for (auto idy = 0; idy < 2; idy += m_num_4x4_h) { for (auto idy = 0; idy < 2; idy += m_num_4x4_h) {
for (auto idx = 0; idx < 2; idx += m_num_4x4_w) { for (auto idx = 0; idx < 2; idx += m_num_4x4_w) {
m_tree_parser->set_default_intra_mode_variables(idx, idy); m_tree_parser->set_default_intra_mode_variables(idx, idy);
m_default_intra_mode = TRY(m_tree_parser->parse_tree<IntraMode>(SyntaxElementType::DefaultIntraMode)); m_default_intra_mode = TRY_READ(m_tree_parser->parse_tree<IntraMode>(SyntaxElementType::DefaultIntraMode));
for (auto y = 0; y < m_num_4x4_h; y++) { for (auto y = 0; y < m_num_4x4_h; y++) {
for (auto x = 0; x < m_num_4x4_w; x++) { for (auto x = 0; x < m_num_4x4_w; x++) {
auto index = (idy + y) * 2 + idx + x; auto index = (idy + y) * 2 + idx + x;
@ -943,25 +959,25 @@ ErrorOr<void> Parser::intra_frame_mode_info()
} }
m_y_mode = m_default_intra_mode; m_y_mode = m_default_intra_mode;
} }
m_uv_mode = TRY(m_tree_parser->parse_tree<u8>(SyntaxElementType::DefaultUVMode)); m_uv_mode = TRY_READ(m_tree_parser->parse_tree<u8>(SyntaxElementType::DefaultUVMode));
return {}; return {};
} }
ErrorOr<void> Parser::intra_segment_id() DecoderErrorOr<void> Parser::intra_segment_id()
{ {
if (m_segmentation_enabled && m_segmentation_update_map) if (m_segmentation_enabled && m_segmentation_update_map)
m_segment_id = TRY(m_tree_parser->parse_tree<u8>(SyntaxElementType::SegmentID)); m_segment_id = TRY_READ(m_tree_parser->parse_tree<u8>(SyntaxElementType::SegmentID));
else else
m_segment_id = 0; m_segment_id = 0;
return {}; return {};
} }
ErrorOr<void> Parser::read_skip() DecoderErrorOr<void> Parser::read_skip()
{ {
if (seg_feature_active(SEG_LVL_SKIP)) if (seg_feature_active(SEG_LVL_SKIP))
m_skip = true; m_skip = true;
else else
m_skip = TRY(m_tree_parser->parse_tree<bool>(SyntaxElementType::Skip)); m_skip = TRY_READ(m_tree_parser->parse_tree<bool>(SyntaxElementType::Skip));
return {}; return {};
} }
@ -970,17 +986,17 @@ bool Parser::seg_feature_active(u8 feature)
return m_segmentation_enabled && m_feature_enabled[m_segment_id][feature]; return m_segmentation_enabled && m_feature_enabled[m_segment_id][feature];
} }
ErrorOr<void> Parser::read_tx_size(bool allow_select) DecoderErrorOr<void> Parser::read_tx_size(bool allow_select)
{ {
m_max_tx_size = max_txsize_lookup[m_mi_size]; m_max_tx_size = max_txsize_lookup[m_mi_size];
if (allow_select && m_tx_mode == TXModeSelect && m_mi_size >= Block_8x8) if (allow_select && m_tx_mode == TXModeSelect && m_mi_size >= Block_8x8)
m_tx_size = TRY(m_tree_parser->parse_tree<TXSize>(SyntaxElementType::TXSize)); m_tx_size = TRY_READ(m_tree_parser->parse_tree<TXSize>(SyntaxElementType::TXSize));
else else
m_tx_size = min(m_max_tx_size, tx_mode_to_biggest_tx_size[m_tx_mode]); m_tx_size = min(m_max_tx_size, tx_mode_to_biggest_tx_size[m_tx_mode]);
return {}; return {};
} }
ErrorOr<void> Parser::inter_frame_mode_info() DecoderErrorOr<void> 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_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; 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<void> Parser::inter_frame_mode_info()
return {}; return {};
} }
ErrorOr<void> Parser::inter_segment_id() DecoderErrorOr<void> Parser::inter_segment_id()
{ {
if (!m_segmentation_enabled) { if (!m_segmentation_enabled) {
m_segment_id = 0; m_segment_id = 0;
@ -1014,15 +1030,15 @@ ErrorOr<void> Parser::inter_segment_id()
return {}; return {};
} }
if (!m_segmentation_temporal_update) { if (!m_segmentation_temporal_update) {
m_segment_id = TRY(m_tree_parser->parse_tree<u8>(SyntaxElementType::SegmentID)); m_segment_id = TRY_READ(m_tree_parser->parse_tree<u8>(SyntaxElementType::SegmentID));
return {}; return {};
} }
auto seg_id_predicted = TRY(m_tree_parser->parse_tree<bool>(SyntaxElementType::SegIDPredicted)); auto seg_id_predicted = TRY_READ(m_tree_parser->parse_tree<bool>(SyntaxElementType::SegIDPredicted));
if (seg_id_predicted) if (seg_id_predicted)
m_segment_id = predicted_segment_id; m_segment_id = predicted_segment_id;
else else
m_segment_id = TRY(m_tree_parser->parse_tree<u8>(SyntaxElementType::SegmentID)); m_segment_id = TRY_READ(m_tree_parser->parse_tree<u8>(SyntaxElementType::SegmentID));
for (size_t i = 0; i < num_8x8_blocks_wide_lookup[m_mi_size]; i++) 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; 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++) 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; return segment;
} }
ErrorOr<void> Parser::read_is_inter() DecoderErrorOr<void> Parser::read_is_inter()
{ {
if (seg_feature_active(SEG_LVL_REF_FRAME)) if (seg_feature_active(SEG_LVL_REF_FRAME))
m_is_inter = m_feature_data[m_segment_id][SEG_LVL_REF_FRAME] != IntraFrame; m_is_inter = m_feature_data[m_segment_id][SEG_LVL_REF_FRAME] != IntraFrame;
else else
m_is_inter = TRY(m_tree_parser->parse_tree<bool>(SyntaxElementType::IsInter)); m_is_inter = TRY_READ(m_tree_parser->parse_tree<bool>(SyntaxElementType::IsInter));
return {}; return {};
} }
ErrorOr<void> Parser::intra_block_mode_info() DecoderErrorOr<void> Parser::intra_block_mode_info()
{ {
m_ref_frame[0] = IntraFrame; m_ref_frame[0] = IntraFrame;
m_ref_frame[1] = None; m_ref_frame[1] = None;
if (m_mi_size >= Block_8x8) { if (m_mi_size >= Block_8x8) {
m_y_mode = TRY(m_tree_parser->parse_tree<u8>(SyntaxElementType::IntraMode)); m_y_mode = TRY_READ(m_tree_parser->parse_tree<u8>(SyntaxElementType::IntraMode));
for (auto& block_sub_mode : m_block_sub_modes) for (auto& block_sub_mode : m_block_sub_modes)
block_sub_mode = m_y_mode; block_sub_mode = m_y_mode;
} else { } else {
@ -1068,7 +1084,7 @@ ErrorOr<void> Parser::intra_block_mode_info()
u8 sub_intra_mode; u8 sub_intra_mode;
for (auto idy = 0; idy < 2; idy += m_num_4x4_h) { for (auto idy = 0; idy < 2; idy += m_num_4x4_h) {
for (auto idx = 0; idx < 2; idx += m_num_4x4_w) { for (auto idx = 0; idx < 2; idx += m_num_4x4_w) {
sub_intra_mode = TRY(m_tree_parser->parse_tree<u8>(SyntaxElementType::SubIntraMode)); sub_intra_mode = TRY_READ(m_tree_parser->parse_tree<u8>(SyntaxElementType::SubIntraMode));
for (auto y = 0; y < m_num_4x4_h; y++) { for (auto y = 0; y < m_num_4x4_h; y++) {
for (auto x = 0; x < m_num_4x4_w; x++) for (auto x = 0; x < m_num_4x4_w; x++)
m_block_sub_modes[(idy + y) * 2 + idx + x] = sub_intra_mode; m_block_sub_modes[(idy + y) * 2 + idx + x] = sub_intra_mode;
@ -1077,11 +1093,11 @@ ErrorOr<void> Parser::intra_block_mode_info()
} }
m_y_mode = sub_intra_mode; m_y_mode = sub_intra_mode;
} }
m_uv_mode = TRY(m_tree_parser->parse_tree<u8>(SyntaxElementType::UVMode)); m_uv_mode = TRY_READ(m_tree_parser->parse_tree<u8>(SyntaxElementType::UVMode));
return {}; return {};
} }
ErrorOr<void> Parser::inter_block_mode_info() DecoderErrorOr<void> Parser::inter_block_mode_info()
{ {
TRY(read_ref_frames()); TRY(read_ref_frames());
for (auto j = 0; j < 2; j++) { for (auto j = 0; j < 2; j++) {
@ -1094,11 +1110,11 @@ ErrorOr<void> Parser::inter_block_mode_info()
if (seg_feature_active(SEG_LVL_SKIP)) { if (seg_feature_active(SEG_LVL_SKIP)) {
m_y_mode = ZeroMv; m_y_mode = ZeroMv;
} else if (m_mi_size >= Block_8x8) { } 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; m_y_mode = NearestMv + inter_mode;
} }
if (m_interpolation_filter == Switchable) if (m_interpolation_filter == Switchable)
m_interp_filter = TRY(m_tree_parser->parse_tree<InterpolationFilter>(SyntaxElementType::InterpFilter)); m_interp_filter = TRY_READ(m_tree_parser->parse_tree<InterpolationFilter>(SyntaxElementType::InterpFilter));
else else
m_interp_filter = m_interpolation_filter; m_interp_filter = m_interpolation_filter;
if (m_mi_size < Block_8x8) { if (m_mi_size < Block_8x8) {
@ -1106,7 +1122,7 @@ ErrorOr<void> Parser::inter_block_mode_info()
m_num_4x4_h = num_4x4_blocks_high_lookup[m_mi_size]; 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 idy = 0; idy < 2; idy += m_num_4x4_h) {
for (auto idx = 0; idx < 2; idx += m_num_4x4_w) { 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; m_y_mode = NearestMv + inter_mode;
if (m_y_mode == NearestMv || m_y_mode == NearMv) { if (m_y_mode == NearestMv || m_y_mode == NearMv) {
for (auto j = 0; j < 1 + is_compound; j++) for (auto j = 0; j < 1 + is_compound; j++)
@ -1134,7 +1150,7 @@ ErrorOr<void> Parser::inter_block_mode_info()
return {}; return {};
} }
ErrorOr<void> Parser::read_ref_frames() DecoderErrorOr<void> Parser::read_ref_frames()
{ {
if (seg_feature_active(SEG_LVL_REF_FRAME)) { if (seg_feature_active(SEG_LVL_REF_FRAME)) {
m_ref_frame[0] = static_cast<ReferenceFrame>(m_feature_data[m_segment_id][SEG_LVL_REF_FRAME]); m_ref_frame[0] = static_cast<ReferenceFrame>(m_feature_data[m_segment_id][SEG_LVL_REF_FRAME]);
@ -1143,19 +1159,19 @@ ErrorOr<void> Parser::read_ref_frames()
} }
ReferenceMode comp_mode; ReferenceMode comp_mode;
if (m_reference_mode == ReferenceModeSelect) if (m_reference_mode == ReferenceModeSelect)
comp_mode = TRY(m_tree_parser->parse_tree<ReferenceMode>(SyntaxElementType::CompMode)); comp_mode = TRY_READ(m_tree_parser->parse_tree<ReferenceMode>(SyntaxElementType::CompMode));
else else
comp_mode = m_reference_mode; comp_mode = m_reference_mode;
if (comp_mode == CompoundReference) { if (comp_mode == CompoundReference) {
auto idx = m_ref_frame_sign_bias[m_comp_fixed_ref]; 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_fixed_ref;
m_ref_frame[!idx] = m_comp_var_ref[comp_ref]; m_ref_frame[!idx] = m_comp_var_ref[comp_ref];
return {}; return {};
} }
auto single_ref_p1 = TRY(m_tree_parser->parse_tree<bool>(SyntaxElementType::SingleRefP1)); auto single_ref_p1 = TRY_READ(m_tree_parser->parse_tree<bool>(SyntaxElementType::SingleRefP1));
if (single_ref_p1) { if (single_ref_p1) {
auto single_ref_p2 = TRY(m_tree_parser->parse_tree<bool>(SyntaxElementType::SingleRefP2)); auto single_ref_p2 = TRY_READ(m_tree_parser->parse_tree<bool>(SyntaxElementType::SingleRefP2));
m_ref_frame[0] = single_ref_p2 ? AltRefFrame : GoldenFrame; m_ref_frame[0] = single_ref_p2 ? AltRefFrame : GoldenFrame;
} else { } else {
m_ref_frame[0] = LastFrame; m_ref_frame[0] = LastFrame;
@ -1164,7 +1180,7 @@ ErrorOr<void> Parser::read_ref_frames()
return {}; return {};
} }
ErrorOr<void> Parser::assign_mv(bool is_compound) DecoderErrorOr<void> Parser::assign_mv(bool is_compound)
{ {
m_mv[1] = 0; m_mv[1] = 0;
for (auto i = 0; i < 1 + is_compound; i++) { for (auto i = 0; i < 1 + is_compound; i++) {
@ -1181,11 +1197,11 @@ ErrorOr<void> Parser::assign_mv(bool is_compound)
return {}; return {};
} }
ErrorOr<void> Parser::read_mv(u8 ref) DecoderErrorOr<void> 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; MV diff_mv;
auto mv_joint = TRY(m_tree_parser->parse_tree<MvJoint>(SyntaxElementType::MVJoint)); auto mv_joint = TRY_READ(m_tree_parser->parse_tree<MvJoint>(SyntaxElementType::MVJoint));
if (mv_joint == MvJointHzvnz || mv_joint == MvJointHnzvnz) if (mv_joint == MvJointHzvnz || mv_joint == MvJointHnzvnz)
diff_mv.set_row(TRY(read_mv_component(0))); diff_mv.set_row(TRY(read_mv_component(0)));
if (mv_joint == MvJointHnzvz || mv_joint == MvJointHnzvnz) if (mv_joint == MvJointHnzvz || mv_joint == MvJointHnzvnz)
@ -1194,31 +1210,31 @@ ErrorOr<void> Parser::read_mv(u8 ref)
return {}; return {};
} }
ErrorOr<i32> Parser::read_mv_component(u8) DecoderErrorOr<i32> Parser::read_mv_component(u8)
{ {
auto mv_sign = TRY(m_tree_parser->parse_tree<bool>(SyntaxElementType::MVSign)); auto mv_sign = TRY_READ(m_tree_parser->parse_tree<bool>(SyntaxElementType::MVSign));
auto mv_class = TRY(m_tree_parser->parse_tree<MvClass>(SyntaxElementType::MVClass)); auto mv_class = TRY_READ(m_tree_parser->parse_tree<MvClass>(SyntaxElementType::MVClass));
u32 mag; u32 mag;
if (mv_class == MvClass0) { if (mv_class == MvClass0) {
auto mv_class0_bit = TRY(m_tree_parser->parse_tree<u32>(SyntaxElementType::MVClass0Bit)); auto mv_class0_bit = TRY_READ(m_tree_parser->parse_tree<u32>(SyntaxElementType::MVClass0Bit));
auto mv_class0_fr = TRY(m_tree_parser->parse_tree<u32>(SyntaxElementType::MVClass0FR)); auto mv_class0_fr = TRY_READ(m_tree_parser->parse_tree<u32>(SyntaxElementType::MVClass0FR));
auto mv_class0_hp = TRY(m_tree_parser->parse_tree<u32>(SyntaxElementType::MVClass0HP)); auto mv_class0_hp = TRY_READ(m_tree_parser->parse_tree<u32>(SyntaxElementType::MVClass0HP));
mag = ((mv_class0_bit << 3) | (mv_class0_fr << 1) | mv_class0_hp) + 1; mag = ((mv_class0_bit << 3) | (mv_class0_fr << 1) | mv_class0_hp) + 1;
} else { } else {
auto d = 0; auto d = 0;
for (size_t i = 0; i < mv_class; i++) { for (size_t i = 0; i < mv_class; i++) {
auto mv_bit = TRY(m_tree_parser->parse_tree<bool>(SyntaxElementType::MVBit)); auto mv_bit = TRY_READ(m_tree_parser->parse_tree<bool>(SyntaxElementType::MVBit));
d |= mv_bit << i; d |= mv_bit << i;
} }
mag = CLASS0_SIZE << (mv_class + 2); mag = CLASS0_SIZE << (mv_class + 2);
auto mv_fr = TRY(m_tree_parser->parse_tree<u32>(SyntaxElementType::MVFR)); auto mv_fr = TRY_READ(m_tree_parser->parse_tree<u32>(SyntaxElementType::MVFR));
auto mv_hp = TRY(m_tree_parser->parse_tree<u32>(SyntaxElementType::MVHP)); auto mv_hp = TRY_READ(m_tree_parser->parse_tree<u32>(SyntaxElementType::MVHP));
mag += ((d << 3) | (mv_fr << 1) | mv_hp) + 1; mag += ((d << 3) | (mv_fr << 1) | mv_hp) + 1;
} }
return (mv_sign ? -1 : 1) * static_cast<i32>(mag); return (mv_sign ? -1 : 1) * static_cast<i32>(mag);
} }
ErrorOr<void> Parser::residual() DecoderErrorOr<void> Parser::residual()
{ {
auto block_size = m_mi_size < Block_8x8 ? Block_8x8 : static_cast<BlockSubsize>(m_mi_size); auto block_size = m_mi_size < Block_8x8 ? Block_8x8 : static_cast<BlockSubsize>(m_mi_size);
for (size_t plane = 0; plane < 3; plane++) { 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]; return ss_size_lookup[subsize][sub_x][sub_y];
} }
ErrorOr<bool> Parser::tokens(size_t plane, u32 start_x, u32 start_y, TXSize tx_size, u32 block_index) DecoderErrorOr<bool> 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); m_tree_parser->set_start_x_and_y(start_x, start_y);
size_t segment_eob = 16 << (tx_size << 1); size_t segment_eob = 16 << (tx_size << 1);
@ -1299,18 +1315,18 @@ ErrorOr<bool> 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]; auto band = (tx_size == TX_4x4) ? coefband_4x4[c] : coefband_8x8plus[c];
m_tree_parser->set_tokens_variables(band, c, plane, tx_size, pos); m_tree_parser->set_tokens_variables(band, c, plane, tx_size, pos);
if (check_eob) { if (check_eob) {
auto more_coefs = TRY(m_tree_parser->parse_tree<bool>(SyntaxElementType::MoreCoefs)); auto more_coefs = TRY_READ(m_tree_parser->parse_tree<bool>(SyntaxElementType::MoreCoefs));
if (!more_coefs) if (!more_coefs)
break; break;
} }
auto token = TRY(m_tree_parser->parse_tree<Token>(SyntaxElementType::Token)); auto token = TRY_READ(m_tree_parser->parse_tree<Token>(SyntaxElementType::Token));
m_token_cache[pos] = energy_class[token]; m_token_cache[pos] = energy_class[token];
if (token == ZeroToken) { if (token == ZeroToken) {
m_tokens[pos] = 0; m_tokens[pos] = 0;
check_eob = false; check_eob = false;
} else { } else {
i32 coef = TRY(read_coef(token)); 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; m_tokens[pos] = sign_bit ? -coef : coef;
check_eob = true; 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; return default_scan_32x32;
} }
ErrorOr<i32> Parser::read_coef(Token token) DecoderErrorOr<i32> Parser::read_coef(Token token)
{ {
auto cat = extra_bits[token][0]; auto cat = extra_bits[token][0];
auto num_extra = extra_bits[token][1]; auto num_extra = extra_bits[token][1];
auto coef = extra_bits[token][2]; auto coef = extra_bits[token][2];
if (token == DctValCat6) { if (token == DctValCat6) {
for (size_t e = 0; e < (u8)(m_bit_depth - 8); e++) { 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); coef += high_bit << (5 + m_bit_depth - e);
} }
} }
for (size_t e = 0; e < num_extra; 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); coef += coef_bit << (num_extra - 1 - e);
} }
return coef; return coef;
} }
ErrorOr<void> Parser::find_mv_refs(ReferenceFrame, int) DecoderErrorOr<void> Parser::find_mv_refs(ReferenceFrame, int)
{ {
// TODO: Implement // TODO: Implement
return Error::from_string_literal("find_mv_refs: Not implemented"); return DecoderError::not_implemented();
} }
ErrorOr<void> Parser::find_best_ref_mvs(int) DecoderErrorOr<void> Parser::find_best_ref_mvs(int)
{ {
// TODO: Implement // TODO: Implement
return Error::from_string_literal("find_best_ref_mvs: Not implemented"); return DecoderError::not_implemented();
} }
ErrorOr<void> Parser::append_sub8x8_mvs(u8, u8) DecoderErrorOr<void> Parser::append_sub8x8_mvs(u8, u8)
{ {
// TODO: Implement // TODO: Implement
return Error::from_string_literal("append_sub8x8_mvs: Not implemented"); return DecoderError::not_implemented();
} }
bool Parser::use_mv_hp(const MV&) DecoderErrorOr<bool> Parser::use_mv_hp(const MV&)
{ {
// TODO: Implement // TODO: Implement
VERIFY(false); return DecoderError::not_implemented();
return true;
} }
void Parser::dump_info() void Parser::dump_info()

View file

@ -7,14 +7,17 @@
#pragma once #pragma once
#include <AK/ByteBuffer.h>
#include <AK/OwnPtr.h>
#include <LibGfx/Forward.h>
#include <LibVideo/DecoderError.h>
#include "BitStream.h" #include "BitStream.h"
#include "LookupTables.h" #include "LookupTables.h"
#include "MV.h" #include "MV.h"
#include "ProbabilityTables.h" #include "ProbabilityTables.h"
#include "SyntaxElementCounter.h" #include "SyntaxElementCounter.h"
#include "TreeParser.h" #include "TreeParser.h"
#include <AK/ByteBuffer.h>
#include <AK/OwnPtr.h>
namespace Video::VP9 { namespace Video::VP9 {
@ -27,23 +30,12 @@ class Parser {
public: public:
explicit Parser(Decoder&); explicit Parser(Decoder&);
~Parser(); ~Parser();
ErrorOr<void> parse_frame(ByteBuffer const&); DecoderErrorOr<void> parse_frame(ByteBuffer const&);
void dump_info(); void dump_info();
private: private:
ErrorOr<FrameType> read_frame_type() DecoderErrorOr<FrameType> read_frame_type();
{ DecoderErrorOr<ColorRange> read_color_range();
if (TRY(m_bit_stream->read_bit()))
return NonKeyFrame;
return KeyFrame;
}
ErrorOr<ColorRange> read_color_range()
{
if (TRY(m_bit_stream->read_bit()))
return FullSwing;
return StudioSwing;
}
/* Utilities */ /* Utilities */
void clear_context(Vector<u8>& context, size_t size); void clear_context(Vector<u8>& context, size_t size);
@ -53,84 +45,84 @@ private:
/* (6.1) Frame Syntax */ /* (6.1) Frame Syntax */
bool trailing_bits(); bool trailing_bits();
ErrorOr<void> refresh_probs(); DecoderErrorOr<void> refresh_probs();
/* (6.2) Uncompressed Header Syntax */ /* (6.2) Uncompressed Header Syntax */
ErrorOr<void> uncompressed_header(); DecoderErrorOr<void> uncompressed_header();
ErrorOr<void> frame_sync_code(); DecoderErrorOr<void> frame_sync_code();
ErrorOr<void> color_config(); DecoderErrorOr<void> color_config();
ErrorOr<void> frame_size(); DecoderErrorOr<void> frame_size();
ErrorOr<void> render_size(); DecoderErrorOr<void> render_size();
ErrorOr<void> frame_size_with_refs(); DecoderErrorOr<void> frame_size_with_refs();
void compute_image_size(); void compute_image_size();
ErrorOr<void> read_interpolation_filter(); DecoderErrorOr<void> read_interpolation_filter();
ErrorOr<void> loop_filter_params(); DecoderErrorOr<void> loop_filter_params();
ErrorOr<void> quantization_params(); DecoderErrorOr<void> quantization_params();
ErrorOr<i8> read_delta_q(); DecoderErrorOr<i8> read_delta_q();
ErrorOr<void> segmentation_params(); DecoderErrorOr<void> segmentation_params();
ErrorOr<u8> read_prob(); DecoderErrorOr<u8> read_prob();
ErrorOr<void> tile_info(); DecoderErrorOr<void> tile_info();
u16 calc_min_log2_tile_cols(); u16 calc_min_log2_tile_cols();
u16 calc_max_log2_tile_cols(); u16 calc_max_log2_tile_cols();
void setup_past_independence(); void setup_past_independence();
/* (6.3) Compressed Header Syntax */ /* (6.3) Compressed Header Syntax */
ErrorOr<void> compressed_header(); DecoderErrorOr<void> compressed_header();
ErrorOr<void> read_tx_mode(); DecoderErrorOr<void> read_tx_mode();
ErrorOr<void> tx_mode_probs(); DecoderErrorOr<void> tx_mode_probs();
ErrorOr<u8> diff_update_prob(u8 prob); DecoderErrorOr<u8> diff_update_prob(u8 prob);
ErrorOr<u8> decode_term_subexp(); DecoderErrorOr<u8> decode_term_subexp();
u8 inv_remap_prob(u8 delta_prob, u8 prob); u8 inv_remap_prob(u8 delta_prob, u8 prob);
u8 inv_recenter_nonneg(u8 v, u8 m); u8 inv_recenter_nonneg(u8 v, u8 m);
ErrorOr<void> read_coef_probs(); DecoderErrorOr<void> read_coef_probs();
ErrorOr<void> read_skip_prob(); DecoderErrorOr<void> read_skip_prob();
ErrorOr<void> read_inter_mode_probs(); DecoderErrorOr<void> read_inter_mode_probs();
ErrorOr<void> read_interp_filter_probs(); DecoderErrorOr<void> read_interp_filter_probs();
ErrorOr<void> read_is_inter_probs(); DecoderErrorOr<void> read_is_inter_probs();
ErrorOr<void> frame_reference_mode(); DecoderErrorOr<void> frame_reference_mode();
ErrorOr<void> frame_reference_mode_probs(); DecoderErrorOr<void> frame_reference_mode_probs();
ErrorOr<void> read_y_mode_probs(); DecoderErrorOr<void> read_y_mode_probs();
ErrorOr<void> read_partition_probs(); DecoderErrorOr<void> read_partition_probs();
ErrorOr<void> mv_probs(); DecoderErrorOr<void> mv_probs();
ErrorOr<u8> update_mv_prob(u8 prob); DecoderErrorOr<u8> update_mv_prob(u8 prob);
void setup_compound_reference_mode(); void setup_compound_reference_mode();
/* (6.4) Decode Tiles Syntax */ /* (6.4) Decode Tiles Syntax */
ErrorOr<void> decode_tiles(); DecoderErrorOr<void> decode_tiles();
void clear_above_context(); void clear_above_context();
u32 get_tile_offset(u32 tile_num, u32 mis, u32 tile_size_log2); u32 get_tile_offset(u32 tile_num, u32 mis, u32 tile_size_log2);
ErrorOr<void> decode_tile(); DecoderErrorOr<void> decode_tile();
void clear_left_context(); void clear_left_context();
ErrorOr<void> decode_partition(u32 row, u32 col, u8 block_subsize); DecoderErrorOr<void> decode_partition(u32 row, u32 col, u8 block_subsize);
ErrorOr<void> decode_block(u32 row, u32 col, u8 subsize); DecoderErrorOr<void> decode_block(u32 row, u32 col, u8 subsize);
ErrorOr<void> mode_info(); DecoderErrorOr<void> mode_info();
ErrorOr<void> intra_frame_mode_info(); DecoderErrorOr<void> intra_frame_mode_info();
ErrorOr<void> intra_segment_id(); DecoderErrorOr<void> intra_segment_id();
ErrorOr<void> read_skip(); DecoderErrorOr<void> read_skip();
bool seg_feature_active(u8 feature); bool seg_feature_active(u8 feature);
ErrorOr<void> read_tx_size(bool allow_select); DecoderErrorOr<void> read_tx_size(bool allow_select);
ErrorOr<void> inter_frame_mode_info(); DecoderErrorOr<void> inter_frame_mode_info();
ErrorOr<void> inter_segment_id(); DecoderErrorOr<void> inter_segment_id();
u8 get_segment_id(); u8 get_segment_id();
ErrorOr<void> read_is_inter(); DecoderErrorOr<void> read_is_inter();
ErrorOr<void> intra_block_mode_info(); DecoderErrorOr<void> intra_block_mode_info();
ErrorOr<void> inter_block_mode_info(); DecoderErrorOr<void> inter_block_mode_info();
ErrorOr<void> read_ref_frames(); DecoderErrorOr<void> read_ref_frames();
ErrorOr<void> assign_mv(bool is_compound); DecoderErrorOr<void> assign_mv(bool is_compound);
ErrorOr<void> read_mv(u8 ref); DecoderErrorOr<void> read_mv(u8 ref);
ErrorOr<i32> read_mv_component(u8 component); DecoderErrorOr<i32> read_mv_component(u8 component);
ErrorOr<void> residual(); DecoderErrorOr<void> residual();
TXSize get_uv_tx_size(); TXSize get_uv_tx_size();
BlockSubsize get_plane_block_size(u32 subsize, u8 plane); BlockSubsize get_plane_block_size(u32 subsize, u8 plane);
ErrorOr<bool> tokens(size_t plane, u32 x, u32 y, TXSize tx_size, u32 block_index); DecoderErrorOr<bool> 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); u32 const* get_scan(size_t plane, TXSize tx_size, u32 block_index);
ErrorOr<i32> read_coef(Token token); DecoderErrorOr<i32> read_coef(Token token);
/* (6.5) Motion Vector Prediction */ /* (6.5) Motion Vector Prediction */
ErrorOr<void> find_mv_refs(ReferenceFrame, int block); DecoderErrorOr<void> find_mv_refs(ReferenceFrame, int block);
ErrorOr<void> find_best_ref_mvs(int ref_list); DecoderErrorOr<void> find_best_ref_mvs(int ref_list);
ErrorOr<void> append_sub8x8_mvs(u8 block, u8 ref_list); DecoderErrorOr<void> append_sub8x8_mvs(u8 block, u8 ref_list);
bool use_mv_hp(MV const& delta_mv); DecoderErrorOr<bool> use_mv_hp(MV const& delta_mv);
u8 m_profile { 0 }; u8 m_profile { 0 };
u8 m_frame_to_show_map_index { 0 }; u8 m_frame_to_show_map_index { 0 };