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
Notes: sideshowbarker 2024-07-17 06:08:13 +09:00
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));
// 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<void> Decoder::adapt_coef_probs()
DecoderErrorOr<void> 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<void> Decoder::adapt_coef_probs()
} \
} while (0)
ErrorOr<void> Decoder::adapt_non_coef_probs()
DecoderErrorOr<void> 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<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
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
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
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++) {
dbgln("updating frame {}? {}", i, (m_parser->m_refresh_frame_flags & (1 << i)) == 1);

View file

@ -7,9 +7,11 @@
#pragma once
#include "Parser.h"
#include <AK/ByteBuffer.h>
#include <AK/Error.h>
#include <LibVideo/DecoderError.h>
#include "Parser.h"
namespace Video::VP9 {
@ -18,27 +20,27 @@ class Decoder {
public:
Decoder();
ErrorOr<void> decode_frame(ByteBuffer const&);
DecoderErrorOr<void> 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<void> adapt_coef_probs();
ErrorOr<void> adapt_non_coef_probs();
DecoderErrorOr<void> adapt_coef_probs();
DecoderErrorOr<void> 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<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_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_inter(size_t plane, u32 x, u32 y, u32 w, u32 h, u32 block_index);
/* (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 */
ErrorOr<void> update_reference_frames();
DecoderErrorOr<void> update_reference_frames();
NonnullOwnPtr<Parser> m_parser;
};

View file

@ -12,6 +12,8 @@
namespace Video::VP9 {
#define TRY_READ(expression) DECODER_TRY(DecoderErrorCategory::Corrupted, expression)
Parser::Parser(Decoder& decoder)
: m_probability_tables(make<ProbabilityTables>())
, m_tree_parser(make<TreeParser>(*this))
@ -40,7 +42,7 @@ void Parser::cleanup_tile_allocations()
}
/* (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_syntax_element_counter = make<SyntaxElementCounter>();
@ -48,18 +50,18 @@ ErrorOr<void> 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<void> Parser::refresh_probs()
DecoderErrorOr<void> 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<void> Parser::refresh_probs()
return {};
}
/* (6.2) */
ErrorOr<void> Parser::uncompressed_header()
DecoderErrorOr<FrameType> 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<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)
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<void> 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<void> 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<void> 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<void> 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<void> Parser::frame_sync_code()
DecoderErrorOr<void> 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<void> Parser::color_config()
DecoderErrorOr<void> 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<ColorSpace>(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<void> 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<void> Parser::frame_size()
DecoderErrorOr<void> 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<void> Parser::render_size()
DecoderErrorOr<void> 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<void> Parser::render_size()
return {};
}
ErrorOr<void> Parser::frame_size_with_refs()
DecoderErrorOr<void> 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<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;
} 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<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_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<void> Parser::loop_filter_params()
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_uv_dc = TRY(read_delta_q());
auto delta_q_uv_ac = TRY(read_delta_q());
@ -327,44 +343,44 @@ ErrorOr<void> Parser::quantization_params()
return {};
}
ErrorOr<i8> Parser::read_delta_q()
DecoderErrorOr<i8> 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<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)
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<void> Parser::segmentation_params()
return {};
}
ErrorOr<u8> Parser::read_prob()
DecoderErrorOr<u8> 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<void> Parser::tile_info()
DecoderErrorOr<void> 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<void> Parser::compressed_header()
DecoderErrorOr<void> Parser::compressed_header()
{
TRY(read_tx_mode());
if (m_tx_mode == TXModeSelect)
@ -459,20 +475,20 @@ ErrorOr<void> Parser::compressed_header()
return {};
}
ErrorOr<void> Parser::read_tx_mode()
DecoderErrorOr<void> 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<TXMode>(tx_mode);
}
return {};
}
ErrorOr<void> Parser::tx_mode_probs()
DecoderErrorOr<void> 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<void> Parser::tx_mode_probs()
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) {
auto delta_prob = TRY(decode_term_subexp());
prob = inv_remap_prob(delta_prob, prob);
@ -500,19 +516,19 @@ ErrorOr<u8> Parser::diff_update_prob(u8 prob)
return prob;
}
ErrorOr<u8> Parser::decode_term_subexp()
DecoderErrorOr<u8> 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<void> Parser::read_coef_probs()
DecoderErrorOr<void> 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<void> Parser::read_coef_probs()
return {};
}
ErrorOr<void> Parser::read_skip_prob()
DecoderErrorOr<void> 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<void> Parser::read_inter_mode_probs()
DecoderErrorOr<void> 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<void> Parser::read_inter_mode_probs()
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 j = 0; j < SWITCHABLE_FILTERS - 1; j++)
@ -582,14 +598,14 @@ ErrorOr<void> Parser::read_interp_filter_probs()
return {};
}
ErrorOr<void> Parser::read_is_inter_probs()
DecoderErrorOr<void> 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<void> Parser::frame_reference_mode()
DecoderErrorOr<void> Parser::frame_reference_mode()
{
auto compound_reference_allowed = false;
for (size_t i = 2; i <= REFS_PER_FRAME; i++) {
@ -597,11 +613,11 @@ ErrorOr<void> 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<void> Parser::frame_reference_mode()
return {};
}
ErrorOr<void> Parser::frame_reference_mode_probs()
DecoderErrorOr<void> Parser::frame_reference_mode_probs()
{
if (m_reference_mode == ReferenceModeSelect) {
for (auto i = 0; i < COMP_MODE_CONTEXTS; i++) {
@ -638,7 +654,7 @@ ErrorOr<void> Parser::frame_reference_mode_probs()
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 j = 0; j < INTRA_MODES - 1; j++) {
@ -649,7 +665,7 @@ ErrorOr<void> Parser::read_y_mode_probs()
return {};
}
ErrorOr<void> Parser::read_partition_probs()
DecoderErrorOr<void> 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<void> Parser::read_partition_probs()
return {};
}
ErrorOr<void> Parser::mv_probs()
DecoderErrorOr<void> 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<void> Parser::mv_probs()
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))) {
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<void> Parser::decode_tiles()
DecoderErrorOr<void> Parser::decode_tiles()
{
auto tile_cols = 1 << m_tile_cols_log2;
auto tile_rows = 1 << m_tile_rows_log2;
@ -764,15 +780,15 @@ ErrorOr<void> 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<void> Parser::decode_tile()
DecoderErrorOr<void> 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<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)
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<void> Parser::decode_partition(u32 row, u32 col, u8 block_subsize)
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_col = col;
@ -902,7 +918,7 @@ ErrorOr<void> Parser::decode_block(u32 row, u32 col, u8 subsize)
return {};
}
ErrorOr<void> Parser::mode_info()
DecoderErrorOr<void> Parser::mode_info()
{
if (m_frame_is_intra)
TRY(intra_frame_mode_info());
@ -911,7 +927,7 @@ ErrorOr<void> Parser::mode_info()
return {};
}
ErrorOr<void> Parser::intra_frame_mode_info()
DecoderErrorOr<void> Parser::intra_frame_mode_info()
{
TRY(intra_segment_id());
TRY(read_skip());
@ -920,7 +936,7 @@ ErrorOr<void> 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<IntraMode>(SyntaxElementType::DefaultIntraMode));
m_default_intra_mode = TRY_READ(m_tree_parser->parse_tree<IntraMode>(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<void> 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<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 x = 0; x < m_num_4x4_w; 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_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 {};
}
ErrorOr<void> Parser::intra_segment_id()
DecoderErrorOr<void> Parser::intra_segment_id()
{
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
m_segment_id = 0;
return {};
}
ErrorOr<void> Parser::read_skip()
DecoderErrorOr<void> Parser::read_skip()
{
if (seg_feature_active(SEG_LVL_SKIP))
m_skip = true;
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 {};
}
@ -970,17 +986,17 @@ bool Parser::seg_feature_active(u8 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];
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
m_tx_size = min(m_max_tx_size, tx_mode_to_biggest_tx_size[m_tx_mode]);
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_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 {};
}
ErrorOr<void> Parser::inter_segment_id()
DecoderErrorOr<void> Parser::inter_segment_id()
{
if (!m_segmentation_enabled) {
m_segment_id = 0;
@ -1014,15 +1030,15 @@ ErrorOr<void> Parser::inter_segment_id()
return {};
}
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 {};
}
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)
m_segment_id = predicted_segment_id;
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++)
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<void> Parser::read_is_inter()
DecoderErrorOr<void> 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<bool>(SyntaxElementType::IsInter));
m_is_inter = TRY_READ(m_tree_parser->parse_tree<bool>(SyntaxElementType::IsInter));
return {};
}
ErrorOr<void> Parser::intra_block_mode_info()
DecoderErrorOr<void> 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<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)
block_sub_mode = m_y_mode;
} else {
@ -1068,7 +1084,7 @@ ErrorOr<void> 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<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 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<void> Parser::intra_block_mode_info()
}
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 {};
}
ErrorOr<void> Parser::inter_block_mode_info()
DecoderErrorOr<void> Parser::inter_block_mode_info()
{
TRY(read_ref_frames());
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)) {
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<InterpolationFilter>(SyntaxElementType::InterpFilter));
m_interp_filter = TRY_READ(m_tree_parser->parse_tree<InterpolationFilter>(SyntaxElementType::InterpFilter));
else
m_interp_filter = m_interpolation_filter;
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];
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<void> Parser::inter_block_mode_info()
return {};
}
ErrorOr<void> Parser::read_ref_frames()
DecoderErrorOr<void> Parser::read_ref_frames()
{
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]);
@ -1143,19 +1159,19 @@ ErrorOr<void> Parser::read_ref_frames()
}
ReferenceMode comp_mode;
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
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<bool>(SyntaxElementType::SingleRefP1));
auto single_ref_p1 = TRY_READ(m_tree_parser->parse_tree<bool>(SyntaxElementType::SingleRefP1));
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;
} else {
m_ref_frame[0] = LastFrame;
@ -1164,7 +1180,7 @@ ErrorOr<void> Parser::read_ref_frames()
return {};
}
ErrorOr<void> Parser::assign_mv(bool is_compound)
DecoderErrorOr<void> Parser::assign_mv(bool is_compound)
{
m_mv[1] = 0;
for (auto i = 0; i < 1 + is_compound; i++) {
@ -1181,11 +1197,11 @@ ErrorOr<void> Parser::assign_mv(bool is_compound)
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;
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)
diff_mv.set_row(TRY(read_mv_component(0)));
if (mv_joint == MvJointHnzvz || mv_joint == MvJointHnzvnz)
@ -1194,31 +1210,31 @@ ErrorOr<void> Parser::read_mv(u8 ref)
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_class = TRY(m_tree_parser->parse_tree<MvClass>(SyntaxElementType::MVClass));
auto mv_sign = TRY_READ(m_tree_parser->parse_tree<bool>(SyntaxElementType::MVSign));
auto mv_class = TRY_READ(m_tree_parser->parse_tree<MvClass>(SyntaxElementType::MVClass));
u32 mag;
if (mv_class == MvClass0) {
auto mv_class0_bit = TRY(m_tree_parser->parse_tree<u32>(SyntaxElementType::MVClass0Bit));
auto mv_class0_fr = TRY(m_tree_parser->parse_tree<u32>(SyntaxElementType::MVClass0FR));
auto mv_class0_hp = TRY(m_tree_parser->parse_tree<u32>(SyntaxElementType::MVClass0HP));
auto mv_class0_bit = TRY_READ(m_tree_parser->parse_tree<u32>(SyntaxElementType::MVClass0Bit));
auto mv_class0_fr = TRY_READ(m_tree_parser->parse_tree<u32>(SyntaxElementType::MVClass0FR));
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;
} else {
auto d = 0;
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;
}
mag = CLASS0_SIZE << (mv_class + 2);
auto mv_fr = TRY(m_tree_parser->parse_tree<u32>(SyntaxElementType::MVFR));
auto mv_hp = TRY(m_tree_parser->parse_tree<u32>(SyntaxElementType::MVHP));
auto mv_fr = TRY_READ(m_tree_parser->parse_tree<u32>(SyntaxElementType::MVFR));
auto mv_hp = TRY_READ(m_tree_parser->parse_tree<u32>(SyntaxElementType::MVHP));
mag += ((d << 3) | (mv_fr << 1) | mv_hp) + 1;
}
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);
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<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);
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];
m_tree_parser->set_tokens_variables(band, c, plane, tx_size, pos);
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)
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];
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<i32> Parser::read_coef(Token token)
DecoderErrorOr<i32> 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<void> Parser::find_mv_refs(ReferenceFrame, int)
DecoderErrorOr<void> Parser::find_mv_refs(ReferenceFrame, int)
{
// 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
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
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
VERIFY(false);
return true;
return DecoderError::not_implemented();
}
void Parser::dump_info()

View file

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