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

LibVideo/VP9: Convert the Parser to use AK/BitStream.h

This doesn't appear to have had a measurable impact on performance,
and behavior is the same.

With the tiles using independent BooleanDecoders with their own
backing BitStreams, we're even one step closer to threaded tiles!
This commit is contained in:
Zaggy1024 2023-02-11 19:35:26 -06:00 committed by Linus Groh
parent 6f39c44160
commit fb0c226da3
10 changed files with 499 additions and 581 deletions

View file

@ -0,0 +1,87 @@
/*
* Copyright (c) 2021, Hunter Salyer <thefalsehonesty@gmail.com>
* Copyright (c) 2022, Gregory Bertilson <zaggy1024@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <AK/BuiltinWrappers.h>
#include "BooleanDecoder.h"
namespace Video::VP9 {
/* 9.2.1 */
ErrorOr<BooleanDecoder> BooleanDecoder::initialize(MaybeOwned<BigEndianInputBitStream> bit_stream, size_t bytes)
{
VERIFY(bit_stream->is_aligned_to_byte_boundary());
auto value = TRY(bit_stream->read_value<u8>());
u8 range = 255;
u64 max_bits = (8 * bytes) - 8;
BooleanDecoder decoder { move(bit_stream), value, range, max_bits };
if (TRY(decoder.read_bool(128)))
return Error::from_string_literal("Range decoder marker was non-zero");
return decoder;
}
/* 9.2.2 */
ErrorOr<bool> BooleanDecoder::read_bool(u8 probability)
{
auto split = 1u + (((m_range - 1u) * probability) >> 8u);
bool return_bool;
if (m_value < split) {
m_range = split;
return_bool = false;
} else {
m_range -= split;
m_value -= split;
return_bool = true;
}
if (m_range < 128) {
u8 bits_to_shift_into_range = count_leading_zeroes(m_range);
if (bits_to_shift_into_range > m_bits_left)
return Error::from_string_literal("Range decoder is out of data");
m_range <<= bits_to_shift_into_range;
m_value = (m_value << bits_to_shift_into_range) | TRY(m_bit_stream->read_bits<u8>(bits_to_shift_into_range));
m_bits_left -= bits_to_shift_into_range;
}
return return_bool;
}
ErrorOr<u8> BooleanDecoder::read_literal(u8 bits)
{
u8 return_value = 0;
for (size_t i = 0; i < bits; i++) {
return_value = (2 * return_value) + TRY(read_bool(128));
}
return return_value;
}
size_t BooleanDecoder::bits_remaining() const
{
return m_bits_left;
}
/* 9.2.3 */
ErrorOr<void> BooleanDecoder::finish_decode()
{
while (m_bits_left > 0) {
auto padding_read_size = min(m_bits_left, 64);
auto padding_bits = TRY(m_bit_stream->read_bits(padding_read_size));
m_bits_left -= padding_read_size;
if (padding_bits != 0)
return Error::from_string_literal("Range decoder has non-zero padding element");
}
// 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.
return {};
}
}