mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 02:07:35 +00:00
LibVideo: Allow bit stream reads to throw errors
Errors are propagated to the user of the decoder so that they can be aware of specific places where a read failed.
This commit is contained in:
parent
af0584ea53
commit
b37ea6b414
10 changed files with 529 additions and 509 deletions
|
@ -42,10 +42,12 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
||||||
|
|
||||||
auto const& frame = block.frame(0);
|
auto const& frame = block.frame(0);
|
||||||
dbgln("Reading frame 0 from block @ {}", block.timestamp());
|
dbgln("Reading frame 0 from block @ {}", block.timestamp());
|
||||||
bool failed = !vp9_decoder.decode_frame(frame);
|
auto result = vp9_decoder.decode_frame(frame);
|
||||||
vp9_decoder.dump_frame_info();
|
vp9_decoder.dump_frame_info();
|
||||||
if (failed)
|
if (result.is_error()) {
|
||||||
|
outln("Error: {}", result.error().string_literal());
|
||||||
return 1;
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,24 +1,29 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021, Hunter Salyer <thefalsehonesty@gmail.com>
|
* Copyright (c) 2021, Hunter Salyer <thefalsehonesty@gmail.com>
|
||||||
|
* Copyright (c) 2022, Gregory Bertilson <zaggy1024@gmail.com>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <AK/Error.h>
|
||||||
|
|
||||||
#include "BitStream.h"
|
#include "BitStream.h"
|
||||||
|
|
||||||
namespace Video::VP9 {
|
namespace Video::VP9 {
|
||||||
|
|
||||||
u8 BitStream::read_byte()
|
ErrorOr<u8> BitStream::read_byte()
|
||||||
{
|
{
|
||||||
|
if (m_bytes_remaining < 1)
|
||||||
|
return Error::from_string_literal("read_byte: Out of data.");
|
||||||
VERIFY(m_bytes_remaining >= 1);
|
VERIFY(m_bytes_remaining >= 1);
|
||||||
m_bytes_remaining--;
|
m_bytes_remaining--;
|
||||||
return *(m_data_ptr++);
|
return *(m_data_ptr++);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BitStream::read_bit()
|
ErrorOr<bool> BitStream::read_bit()
|
||||||
{
|
{
|
||||||
if (!m_current_byte.has_value()) {
|
if (!m_current_byte.has_value()) {
|
||||||
m_current_byte = read_byte();
|
m_current_byte = TRY(read_byte());
|
||||||
m_current_bit_position = 7;
|
m_current_bit_position = 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,47 +33,49 @@ bool BitStream::read_bit()
|
||||||
return bit_value;
|
return bit_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 BitStream::read_f(size_t n)
|
ErrorOr<u8> BitStream::read_f(size_t n)
|
||||||
{
|
{
|
||||||
u8 result = 0;
|
u8 result = 0;
|
||||||
for (size_t i = 0; i < n; i++) {
|
for (size_t i = 0; i < n; i++) {
|
||||||
result = (2 * result) + read_bit();
|
result = (2 * result) + TRY(read_bit());
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 BitStream::read_f8()
|
ErrorOr<u8> BitStream::read_f8()
|
||||||
{
|
{
|
||||||
if (!m_current_byte.has_value())
|
if (!m_current_byte.has_value())
|
||||||
return read_byte();
|
return read_byte();
|
||||||
|
|
||||||
auto high_bits = m_current_byte.value() & ((1u << m_current_bit_position) - 1);
|
auto high_bits = m_current_byte.value() & ((1u << m_current_bit_position) - 1);
|
||||||
u8 remaining_bits = 7 - m_current_bit_position;
|
u8 remaining_bits = 7 - m_current_bit_position;
|
||||||
m_current_byte = read_byte();
|
m_current_byte = TRY(read_byte());
|
||||||
m_current_bit_position = 7;
|
m_current_bit_position = 7;
|
||||||
auto low_bits = (m_current_byte.value() >> (8u - remaining_bits)) & ((1u << remaining_bits) - 1);
|
auto low_bits = (m_current_byte.value() >> (8u - remaining_bits)) & ((1u << remaining_bits) - 1);
|
||||||
m_current_bit_position -= remaining_bits;
|
m_current_bit_position -= remaining_bits;
|
||||||
return (high_bits << remaining_bits) | low_bits;
|
return (high_bits << remaining_bits) | low_bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
u16 BitStream::read_f16()
|
ErrorOr<u16> BitStream::read_f16()
|
||||||
{
|
{
|
||||||
return (read_f8() << 8u) | read_f8();
|
return (TRY(read_f8()) << 8u) | TRY(read_f8());
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 9.2.1 */
|
/* 9.2.1 */
|
||||||
bool BitStream::init_bool(size_t bytes)
|
ErrorOr<void> BitStream::init_bool(size_t bytes)
|
||||||
{
|
{
|
||||||
if (bytes < 1)
|
if (bytes == 0)
|
||||||
return false;
|
return Error::from_string_literal("Range coder size cannot be zero.");
|
||||||
m_bool_value = read_f8();
|
m_bool_value = TRY(read_f8());
|
||||||
m_bool_range = 255;
|
m_bool_range = 255;
|
||||||
m_bool_max_bits = (8 * bytes) - 8;
|
m_bool_max_bits = (8 * bytes) - 8;
|
||||||
return !read_bool(128);
|
if (TRY(read_bool(128)))
|
||||||
|
return Error::from_string_literal("Range coder's first bool was non-zero.");
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 9.2.2 */
|
/* 9.2.2 */
|
||||||
bool BitStream::read_bool(u8 probability)
|
ErrorOr<bool> BitStream::read_bool(u8 probability)
|
||||||
{
|
{
|
||||||
auto split = 1u + (((m_bool_range - 1u) * probability) >> 8u);
|
auto split = 1u + (((m_bool_range - 1u) * probability) >> 8u);
|
||||||
bool return_bool;
|
bool return_bool;
|
||||||
|
@ -85,7 +92,7 @@ bool BitStream::read_bool(u8 probability)
|
||||||
while (m_bool_range < 128) {
|
while (m_bool_range < 128) {
|
||||||
bool new_bit;
|
bool new_bit;
|
||||||
if (m_bool_max_bits) {
|
if (m_bool_max_bits) {
|
||||||
new_bit = read_bit();
|
new_bit = TRY(read_bit());
|
||||||
m_bool_max_bits--;
|
m_bool_max_bits--;
|
||||||
} else {
|
} else {
|
||||||
new_bit = false;
|
new_bit = false;
|
||||||
|
@ -98,29 +105,31 @@ bool BitStream::read_bool(u8 probability)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 9.2.3 */
|
/* 9.2.3 */
|
||||||
bool BitStream::exit_bool()
|
ErrorOr<void> BitStream::exit_bool()
|
||||||
{
|
{
|
||||||
// FIXME: I'm not sure if this call to min is spec compliant, or if there is an issue elsewhere earlier in the parser.
|
// FIXME: I'm not sure if this call to min is spec compliant, or if there is an issue elsewhere earlier in the parser.
|
||||||
auto padding_element = read_f(min(m_bool_max_bits, (u64)bits_remaining()));
|
auto padding_element = TRY(read_f(min(m_bool_max_bits, (u64)bits_remaining())));
|
||||||
|
|
||||||
// FIXME: It is a requirement of bitstream conformance that enough padding bits are inserted to ensure that the final coded byte of a frame is not equal to a superframe marker.
|
// FIXME: It is a requirement of bitstream conformance that enough padding bits are inserted to ensure that the final coded byte of a frame is not equal to a superframe marker.
|
||||||
// A byte b is equal to a superframe marker if and only if (b & 0xe0)is equal to 0xc0, i.e. if the most significant 3 bits are equal to 0b110.
|
// A byte b is equal to a superframe marker if and only if (b & 0xe0)is equal to 0xc0, i.e. if the most significant 3 bits are equal to 0b110.
|
||||||
return padding_element == 0;
|
if (padding_element != 0)
|
||||||
|
return Error::from_string_literal("Range coder padding was non-zero.");
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 BitStream::read_literal(size_t n)
|
ErrorOr<u8> BitStream::read_literal(size_t n)
|
||||||
{
|
{
|
||||||
u8 return_value = 0;
|
u8 return_value = 0;
|
||||||
for (size_t i = 0; i < n; i++) {
|
for (size_t i = 0; i < n; i++) {
|
||||||
return_value = (2 * return_value) + read_bool(128);
|
return_value = (2 * return_value) + TRY(read_bool(128));
|
||||||
}
|
}
|
||||||
return return_value;
|
return return_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
i8 BitStream::read_s(size_t n)
|
ErrorOr<i8> BitStream::read_s(size_t n)
|
||||||
{
|
{
|
||||||
auto value = read_f(n);
|
auto value = TRY(read_f(n));
|
||||||
auto sign = read_bit();
|
auto sign = TRY(read_bit());
|
||||||
return sign ? -value : value;
|
return sign ? -value : value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021, Hunter Salyer <thefalsehonesty@gmail.com>
|
* Copyright (c) 2021, Hunter Salyer <thefalsehonesty@gmail.com>
|
||||||
|
* Copyright (c) 2022, Gregory Bertilson <zaggy1024@gmail.com>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -19,22 +20,22 @@ public:
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 read_byte();
|
ErrorOr<u8> read_byte();
|
||||||
bool read_bit();
|
ErrorOr<bool> read_bit();
|
||||||
|
|
||||||
/* (9.1) */
|
/* (9.1) */
|
||||||
u8 read_f(size_t n);
|
ErrorOr<u8> read_f(size_t n);
|
||||||
u8 read_f8();
|
ErrorOr<u8> read_f8();
|
||||||
u16 read_f16();
|
ErrorOr<u16> read_f16();
|
||||||
|
|
||||||
/* (9.2) */
|
/* (9.2) */
|
||||||
bool init_bool(size_t bytes);
|
ErrorOr<void> init_bool(size_t bytes);
|
||||||
bool read_bool(u8 probability);
|
ErrorOr<bool> read_bool(u8 probability);
|
||||||
bool exit_bool();
|
ErrorOr<void> exit_bool();
|
||||||
u8 read_literal(size_t n);
|
ErrorOr<u8> read_literal(size_t n);
|
||||||
|
|
||||||
/* (4.9.2) */
|
/* (4.9.2) */
|
||||||
i8 read_s(size_t n);
|
ErrorOr<i8> read_s(size_t n);
|
||||||
|
|
||||||
u64 get_position();
|
u64 get_position();
|
||||||
size_t bytes_remaining();
|
size_t bytes_remaining();
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021, Hunter Salyer <thefalsehonesty@gmail.com>
|
* Copyright (c) 2021, Hunter Salyer <thefalsehonesty@gmail.com>
|
||||||
|
* Copyright (c) 2022, Gregory Bertilson <zaggy1024@gmail.com>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -14,15 +15,16 @@ Decoder::Decoder()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Decoder::decode_frame(ByteBuffer const& frame_data)
|
ErrorOr<void> Decoder::decode_frame(ByteBuffer const& frame_data)
|
||||||
{
|
{
|
||||||
SAFE_CALL(m_parser->parse_frame(frame_data));
|
TRY(m_parser->parse_frame(frame_data));
|
||||||
// TODO:
|
// TODO:
|
||||||
// - #2
|
// - #2
|
||||||
// - #3
|
// - #3
|
||||||
// - #4
|
// - #4
|
||||||
SAFE_CALL(update_reference_frames());
|
TRY(update_reference_frames());
|
||||||
return true;
|
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void Decoder::dump_frame_info()
|
void Decoder::dump_frame_info()
|
||||||
|
@ -49,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Decoder::adapt_coef_probs()
|
ErrorOr<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)
|
||||||
|
@ -76,7 +78,7 @@ bool Decoder::adapt_coef_probs()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ADAPT_PROB_TABLE(name, size) \
|
#define ADAPT_PROB_TABLE(name, size) \
|
||||||
|
@ -94,7 +96,7 @@ bool Decoder::adapt_coef_probs()
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
bool Decoder::adapt_non_coef_probs()
|
ErrorOr<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;
|
||||||
|
@ -137,7 +139,7 @@ bool Decoder::adapt_non_coef_probs()
|
||||||
probs.mv_hp_prob()[i] = adapt_prob(probs.mv_hp_prob()[i], counter.m_counts_mv_hp[i]);
|
probs.mv_hp_prob()[i] = adapt_prob(probs.mv_hp_prob()[i], counter.m_counts_mv_hp[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void Decoder::adapt_probs(int const* tree, u8* probs, u8* counts)
|
void Decoder::adapt_probs(int const* tree, u8* probs, u8* counts)
|
||||||
|
@ -150,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Decoder::predict_intra(size_t, u32, u32, bool, bool, bool, TXSize, u32)
|
ErrorOr<void> Decoder::predict_intra(size_t, u32, u32, bool, bool, bool, TXSize, u32)
|
||||||
{
|
{
|
||||||
// TODO: Implement
|
// TODO: Implement
|
||||||
return true;
|
return Error::from_string_literal("predict_intra not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Decoder::predict_inter(size_t, u32, u32, u32, u32, u32)
|
ErrorOr<void> Decoder::predict_inter(size_t, u32, u32, u32, u32, u32)
|
||||||
{
|
{
|
||||||
// TODO: Implement
|
// TODO: Implement
|
||||||
return true;
|
return Error::from_string_literal("predict_inter not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Decoder::reconstruct(size_t, u32, u32, TXSize)
|
ErrorOr<void> Decoder::reconstruct(size_t, u32, u32, TXSize)
|
||||||
{
|
{
|
||||||
// TODO: Implement
|
// TODO: Implement
|
||||||
return true;
|
return Error::from_string_literal("reconstruct not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Decoder::update_reference_frames()
|
ErrorOr<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);
|
||||||
|
@ -179,7 +181,7 @@ bool Decoder::update_reference_frames()
|
||||||
// TODO: 1.3-1.7
|
// TODO: 1.3-1.7
|
||||||
}
|
}
|
||||||
// TODO: 2.1-2.2
|
// TODO: 2.1-2.2
|
||||||
return true;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021, Hunter Salyer <thefalsehonesty@gmail.com>
|
* Copyright (c) 2021, Hunter Salyer <thefalsehonesty@gmail.com>
|
||||||
|
* Copyright (c) 2022, Gregory Bertilson <zaggy1024@gmail.com>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -8,6 +9,7 @@
|
||||||
|
|
||||||
#include "Parser.h"
|
#include "Parser.h"
|
||||||
#include <AK/ByteBuffer.h>
|
#include <AK/ByteBuffer.h>
|
||||||
|
#include <AK/Error.h>
|
||||||
|
|
||||||
namespace Video::VP9 {
|
namespace Video::VP9 {
|
||||||
|
|
||||||
|
@ -16,27 +18,27 @@ class Decoder {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Decoder();
|
Decoder();
|
||||||
bool decode_frame(ByteBuffer const&);
|
ErrorOr<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);
|
||||||
bool adapt_coef_probs();
|
ErrorOr<void> adapt_coef_probs();
|
||||||
bool adapt_non_coef_probs();
|
ErrorOr<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 */
|
||||||
bool 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_intra(size_t plane, u32 x, u32 y, bool have_left, bool have_above, bool not_on_right, TXSize tx_size, u32 block_index);
|
||||||
bool predict_inter(size_t plane, u32 x, u32 y, u32 w, u32 h, u32 block_index);
|
ErrorOr<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 */
|
||||||
bool reconstruct(size_t plane, u32 x, u32 y, TXSize size);
|
ErrorOr<void> reconstruct(size_t plane, u32 x, u32 y, TXSize size);
|
||||||
|
|
||||||
/* (8.10) Reference Frame Update Process */
|
/* (8.10) Reference Frame Update Process */
|
||||||
bool update_reference_frames();
|
ErrorOr<void> update_reference_frames();
|
||||||
|
|
||||||
NonnullOwnPtr<Parser> m_parser;
|
NonnullOwnPtr<Parser> m_parser;
|
||||||
};
|
};
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021, Hunter Salyer <thefalsehonesty@gmail.com>
|
* Copyright (c) 2021, Hunter Salyer <thefalsehonesty@gmail.com>
|
||||||
|
* Copyright (c) 2022, Gregory Bertilson <zaggy1024@gmail.com>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -26,20 +27,20 @@ class Parser {
|
||||||
public:
|
public:
|
||||||
explicit Parser(Decoder&);
|
explicit Parser(Decoder&);
|
||||||
~Parser();
|
~Parser();
|
||||||
bool parse_frame(ByteBuffer const&);
|
ErrorOr<void> parse_frame(ByteBuffer const&);
|
||||||
void dump_info();
|
void dump_info();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FrameType read_frame_type()
|
ErrorOr<FrameType> read_frame_type()
|
||||||
{
|
{
|
||||||
if (m_bit_stream->read_bit())
|
if (TRY(m_bit_stream->read_bit()))
|
||||||
return NonKeyFrame;
|
return NonKeyFrame;
|
||||||
return KeyFrame;
|
return KeyFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
ColorRange read_color_range()
|
ErrorOr<ColorRange> read_color_range()
|
||||||
{
|
{
|
||||||
if (m_bit_stream->read_bit())
|
if (TRY(m_bit_stream->read_bit()))
|
||||||
return FullSwing;
|
return FullSwing;
|
||||||
return StudioSwing;
|
return StudioSwing;
|
||||||
}
|
}
|
||||||
|
@ -52,83 +53,83 @@ private:
|
||||||
|
|
||||||
/* (6.1) Frame Syntax */
|
/* (6.1) Frame Syntax */
|
||||||
bool trailing_bits();
|
bool trailing_bits();
|
||||||
bool refresh_probs();
|
ErrorOr<void> refresh_probs();
|
||||||
|
|
||||||
/* (6.2) Uncompressed Header Syntax */
|
/* (6.2) Uncompressed Header Syntax */
|
||||||
bool uncompressed_header();
|
ErrorOr<void> uncompressed_header();
|
||||||
bool frame_sync_code();
|
ErrorOr<void> frame_sync_code();
|
||||||
bool color_config();
|
ErrorOr<void> color_config();
|
||||||
bool frame_size();
|
ErrorOr<void> frame_size();
|
||||||
bool render_size();
|
ErrorOr<void> render_size();
|
||||||
bool frame_size_with_refs();
|
ErrorOr<void> frame_size_with_refs();
|
||||||
bool compute_image_size();
|
void compute_image_size();
|
||||||
bool read_interpolation_filter();
|
ErrorOr<void> read_interpolation_filter();
|
||||||
bool loop_filter_params();
|
ErrorOr<void> loop_filter_params();
|
||||||
bool quantization_params();
|
ErrorOr<void> quantization_params();
|
||||||
i8 read_delta_q();
|
ErrorOr<i8> read_delta_q();
|
||||||
bool segmentation_params();
|
ErrorOr<void> segmentation_params();
|
||||||
u8 read_prob();
|
ErrorOr<u8> read_prob();
|
||||||
bool tile_info();
|
ErrorOr<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();
|
||||||
bool setup_past_independence();
|
void setup_past_independence();
|
||||||
|
|
||||||
/* (6.3) Compressed Header Syntax */
|
/* (6.3) Compressed Header Syntax */
|
||||||
bool compressed_header();
|
ErrorOr<void> compressed_header();
|
||||||
bool read_tx_mode();
|
ErrorOr<void> read_tx_mode();
|
||||||
bool tx_mode_probs();
|
ErrorOr<void> tx_mode_probs();
|
||||||
u8 diff_update_prob(u8 prob);
|
ErrorOr<u8> diff_update_prob(u8 prob);
|
||||||
u8 decode_term_subexp();
|
ErrorOr<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);
|
||||||
bool read_coef_probs();
|
ErrorOr<void> read_coef_probs();
|
||||||
bool read_skip_prob();
|
ErrorOr<void> read_skip_prob();
|
||||||
bool read_inter_mode_probs();
|
ErrorOr<void> read_inter_mode_probs();
|
||||||
bool read_interp_filter_probs();
|
ErrorOr<void> read_interp_filter_probs();
|
||||||
bool read_is_inter_probs();
|
ErrorOr<void> read_is_inter_probs();
|
||||||
bool frame_reference_mode();
|
ErrorOr<void> frame_reference_mode();
|
||||||
bool frame_reference_mode_probs();
|
ErrorOr<void> frame_reference_mode_probs();
|
||||||
bool read_y_mode_probs();
|
ErrorOr<void> read_y_mode_probs();
|
||||||
bool read_partition_probs();
|
ErrorOr<void> read_partition_probs();
|
||||||
bool mv_probs();
|
ErrorOr<void> mv_probs();
|
||||||
u8 update_mv_prob(u8 prob);
|
ErrorOr<u8> update_mv_prob(u8 prob);
|
||||||
bool setup_compound_reference_mode();
|
void setup_compound_reference_mode();
|
||||||
|
|
||||||
/* (6.4) Decode Tiles Syntax */
|
/* (6.4) Decode Tiles Syntax */
|
||||||
bool decode_tiles();
|
ErrorOr<void> decode_tiles();
|
||||||
bool 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);
|
||||||
bool decode_tile();
|
ErrorOr<void> decode_tile();
|
||||||
bool clear_left_context();
|
void clear_left_context();
|
||||||
bool decode_partition(u32 row, u32 col, u8 block_subsize);
|
ErrorOr<void> decode_partition(u32 row, u32 col, u8 block_subsize);
|
||||||
bool decode_block(u32 row, u32 col, u8 subsize);
|
ErrorOr<void> decode_block(u32 row, u32 col, u8 subsize);
|
||||||
bool mode_info();
|
ErrorOr<void> mode_info();
|
||||||
bool intra_frame_mode_info();
|
ErrorOr<void> intra_frame_mode_info();
|
||||||
bool intra_segment_id();
|
ErrorOr<void> intra_segment_id();
|
||||||
bool read_skip();
|
ErrorOr<void> read_skip();
|
||||||
bool seg_feature_active(u8 feature);
|
bool seg_feature_active(u8 feature);
|
||||||
bool read_tx_size(bool allow_select);
|
ErrorOr<void> read_tx_size(bool allow_select);
|
||||||
bool inter_frame_mode_info();
|
ErrorOr<void> inter_frame_mode_info();
|
||||||
bool inter_segment_id();
|
ErrorOr<void> inter_segment_id();
|
||||||
u8 get_segment_id();
|
u8 get_segment_id();
|
||||||
bool read_is_inter();
|
ErrorOr<void> read_is_inter();
|
||||||
bool intra_block_mode_info();
|
ErrorOr<void> intra_block_mode_info();
|
||||||
bool inter_block_mode_info();
|
ErrorOr<void> inter_block_mode_info();
|
||||||
bool read_ref_frames();
|
ErrorOr<void> read_ref_frames();
|
||||||
bool assign_mv(bool is_compound);
|
ErrorOr<void> assign_mv(bool is_compound);
|
||||||
bool read_mv(u8 ref);
|
ErrorOr<void> read_mv(u8 ref);
|
||||||
i32 read_mv_component(u8 component);
|
ErrorOr<i32> read_mv_component(u8 component);
|
||||||
bool residual();
|
ErrorOr<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);
|
||||||
bool tokens(size_t plane, u32 x, u32 y, TXSize tx_size, u32 block_index);
|
ErrorOr<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);
|
||||||
u32 read_coef(Token token);
|
ErrorOr<i32> read_coef(Token token);
|
||||||
|
|
||||||
/* (6.5) Motion Vector Prediction */
|
/* (6.5) Motion Vector Prediction */
|
||||||
bool find_mv_refs(ReferenceFrame, int block);
|
ErrorOr<void> find_mv_refs(ReferenceFrame, int block);
|
||||||
bool find_best_ref_mvs(int ref_list);
|
ErrorOr<void> find_best_ref_mvs(int ref_list);
|
||||||
bool append_sub8x8_mvs(u8 block, u8 ref_list);
|
ErrorOr<void> append_sub8x8_mvs(u8 block, u8 ref_list);
|
||||||
bool use_mv_hp(MV const& delta_mv);
|
bool use_mv_hp(MV const& delta_mv);
|
||||||
|
|
||||||
u8 m_profile { 0 };
|
u8 m_profile { 0 };
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
namespace Video::VP9 {
|
namespace Video::VP9 {
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T TreeParser::parse_tree(SyntaxElementType type)
|
ErrorOr<T> TreeParser::parse_tree(SyntaxElementType type)
|
||||||
{
|
{
|
||||||
auto tree_selection = select_tree(type);
|
auto tree_selection = select_tree(type);
|
||||||
int value;
|
int value;
|
||||||
|
@ -21,7 +21,7 @@ T TreeParser::parse_tree(SyntaxElementType type)
|
||||||
auto tree = tree_selection.get_tree_value();
|
auto tree = tree_selection.get_tree_value();
|
||||||
int n = 0;
|
int n = 0;
|
||||||
do {
|
do {
|
||||||
n = tree[n + m_decoder.m_bit_stream->read_bool(select_tree_probability(type, n >> 1))];
|
n = tree[n + TRY(m_decoder.m_bit_stream->read_bool(select_tree_probability(type, n >> 1)))];
|
||||||
} while (n > 0);
|
} while (n > 0);
|
||||||
value = -n;
|
value = -n;
|
||||||
}
|
}
|
||||||
|
@ -29,17 +29,17 @@ T TreeParser::parse_tree(SyntaxElementType type)
|
||||||
return static_cast<T>(value);
|
return static_cast<T>(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template int TreeParser::parse_tree(SyntaxElementType);
|
template ErrorOr<int> TreeParser::parse_tree(SyntaxElementType);
|
||||||
template bool TreeParser::parse_tree(SyntaxElementType);
|
template ErrorOr<bool> TreeParser::parse_tree(SyntaxElementType);
|
||||||
template u8 TreeParser::parse_tree(SyntaxElementType);
|
template ErrorOr<u8> TreeParser::parse_tree(SyntaxElementType);
|
||||||
template u32 TreeParser::parse_tree(SyntaxElementType);
|
template ErrorOr<u32> TreeParser::parse_tree(SyntaxElementType);
|
||||||
template IntraMode TreeParser::parse_tree(SyntaxElementType);
|
template ErrorOr<IntraMode> TreeParser::parse_tree(SyntaxElementType);
|
||||||
template TXSize TreeParser::parse_tree(SyntaxElementType);
|
template ErrorOr<TXSize> TreeParser::parse_tree(SyntaxElementType);
|
||||||
template InterpolationFilter TreeParser::parse_tree(SyntaxElementType);
|
template ErrorOr<InterpolationFilter> TreeParser::parse_tree(SyntaxElementType);
|
||||||
template ReferenceMode TreeParser::parse_tree(SyntaxElementType);
|
template ErrorOr<ReferenceMode> TreeParser::parse_tree(SyntaxElementType);
|
||||||
template Token TreeParser::parse_tree(SyntaxElementType);
|
template ErrorOr<Token> TreeParser::parse_tree(SyntaxElementType);
|
||||||
template MvClass TreeParser::parse_tree(SyntaxElementType);
|
template ErrorOr<MvClass> TreeParser::parse_tree(SyntaxElementType);
|
||||||
template MvJoint TreeParser::parse_tree(SyntaxElementType);
|
template ErrorOr<MvJoint> TreeParser::parse_tree(SyntaxElementType);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Select a tree value based on the type of syntax element being parsed, as well as some parser state, as specified in section 9.3.1
|
* Select a tree value based on the type of syntax element being parsed, as well as some parser state, as specified in section 9.3.1
|
||||||
|
|
|
@ -43,7 +43,7 @@ public:
|
||||||
|
|
||||||
/* (9.3.3) */
|
/* (9.3.3) */
|
||||||
template<typename T = int>
|
template<typename T = int>
|
||||||
T parse_tree(SyntaxElementType type);
|
ErrorOr<T> parse_tree(SyntaxElementType type);
|
||||||
/* (9.3.1) */
|
/* (9.3.1) */
|
||||||
TreeSelection select_tree(SyntaxElementType type);
|
TreeSelection select_tree(SyntaxElementType type);
|
||||||
/* (9.3.2) */
|
/* (9.3.2) */
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021, Hunter Salyer <thefalsehonesty@gmail.com>
|
* Copyright (c) 2021, Hunter Salyer <thefalsehonesty@gmail.com>
|
||||||
|
* Copyright (c) 2022, Gregory Bertilson <zaggy1024@gmail.com>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -10,14 +11,6 @@
|
||||||
|
|
||||||
namespace Video::VP9 {
|
namespace Video::VP9 {
|
||||||
|
|
||||||
#define SAFE_CALL(call) \
|
|
||||||
do { \
|
|
||||||
if (!(call)) [[unlikely]] { \
|
|
||||||
dbgln("FAILED " #call); \
|
|
||||||
return false; \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
u8 clip_3(u8 x, u8 y, u8 z);
|
u8 clip_3(u8 x, u8 y, u8 z);
|
||||||
u8 round_2(u8 x, u8 n);
|
u8 round_2(u8 x, u8 n);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue