AK: Remove the fallible constructor from BigEndianInputBitStream

This commit is contained in:
Tim Schumacher 2023-01-30 11:03:45 +01:00 committed by Linus Groh
parent 839bec14af
commit fa09152e23
4 changed files with 64 additions and 69 deletions

View file

@ -17,9 +17,9 @@ namespace AK {
/// in big-endian order from another stream.
class BigEndianInputBitStream : public Stream {
public:
static ErrorOr<NonnullOwnPtr<BigEndianInputBitStream>> construct(MaybeOwned<Stream> stream)
explicit BigEndianInputBitStream(MaybeOwned<Stream> stream)
: m_stream(move(stream))
{
return adopt_nonnull_own_or_enomem<BigEndianInputBitStream>(new BigEndianInputBitStream(move(stream)));
}
// ^Stream
@ -112,11 +112,6 @@ public:
ALWAYS_INLINE bool is_aligned_to_byte_boundary() const { return m_bit_offset == 0; }
private:
BigEndianInputBitStream(MaybeOwned<Stream> stream)
: m_stream(move(stream))
{
}
Optional<u8> m_current_byte;
size_t m_bit_offset { 0 };
MaybeOwned<Stream> m_stream;

View file

@ -72,23 +72,23 @@ TEST_CASE(big_endian_bit_stream_input_output_match)
// Note: The bit stream only ever reads from/writes to the underlying stream in one byte chunks,
// so testing with sizes that will not trigger a write will yield unexpected results.
auto bit_write_stream = MUST(BigEndianOutputBitStream::construct(MaybeOwned<AK::Stream>(*memory_stream)));
auto bit_read_stream = MUST(BigEndianInputBitStream::construct(MaybeOwned<AK::Stream>(*memory_stream)));
BigEndianInputBitStream bit_read_stream { MaybeOwned<AK::Stream>(*memory_stream) };
// Test two mirrored chunks of a fully mirrored pattern to check that we are not dropping bits.
{
MUST(bit_write_stream->write_bits(0b1111u, 4));
MUST(bit_write_stream->write_bits(0b1111u, 4));
auto result = MUST(bit_read_stream->read_bits(4));
auto result = MUST(bit_read_stream.read_bits(4));
EXPECT_EQ(0b1111u, result);
result = MUST(bit_read_stream->read_bits(4));
result = MUST(bit_read_stream.read_bits(4));
EXPECT_EQ(0b1111u, result);
}
{
MUST(bit_write_stream->write_bits(0b0000u, 4));
MUST(bit_write_stream->write_bits(0b0000u, 4));
auto result = MUST(bit_read_stream->read_bits(4));
auto result = MUST(bit_read_stream.read_bits(4));
EXPECT_EQ(0b0000u, result);
result = MUST(bit_read_stream->read_bits(4));
result = MUST(bit_read_stream.read_bits(4));
EXPECT_EQ(0b0000u, result);
}
@ -96,9 +96,9 @@ TEST_CASE(big_endian_bit_stream_input_output_match)
{
MUST(bit_write_stream->write_bits(0b1000u, 4));
MUST(bit_write_stream->write_bits(0b1000u, 4));
auto result = MUST(bit_read_stream->read_bits(4));
auto result = MUST(bit_read_stream.read_bits(4));
EXPECT_EQ(0b1000u, result);
result = MUST(bit_read_stream->read_bits(4));
result = MUST(bit_read_stream.read_bits(4));
EXPECT_EQ(0b1000u, result);
}
@ -106,16 +106,16 @@ TEST_CASE(big_endian_bit_stream_input_output_match)
{
MUST(bit_write_stream->write_bits(0b1000u, 4));
MUST(bit_write_stream->write_bits(0b0100u, 4));
auto result = MUST(bit_read_stream->read_bits(4));
auto result = MUST(bit_read_stream.read_bits(4));
EXPECT_EQ(0b1000u, result);
result = MUST(bit_read_stream->read_bits(4));
result = MUST(bit_read_stream.read_bits(4));
EXPECT_EQ(0b0100u, result);
}
// Test a pattern that spans multiple bytes.
{
MUST(bit_write_stream->write_bits(0b1101001000100001u, 16));
auto result = MUST(bit_read_stream->read_bits(16));
auto result = MUST(bit_read_stream.read_bits(16));
EXPECT_EQ(0b1101001000100001u, result);
}
}

View file

@ -60,7 +60,7 @@ MaybeLoaderError FlacLoaderPlugin::initialize()
// 11.5 STREAM
MaybeLoaderError FlacLoaderPlugin::parse_header()
{
auto bit_input = LOADER_TRY(BigEndianInputBitStream::construct(MaybeOwned<AK::Stream>(*m_stream)));
BigEndianInputBitStream bit_input { MaybeOwned<AK::Stream>(*m_stream) };
// A mixture of VERIFY and the non-crashing TRY().
#define FLAC_VERIFY(check, category, msg) \
@ -71,28 +71,28 @@ MaybeLoaderError FlacLoaderPlugin::parse_header()
} while (0)
// Magic number
u32 flac = LOADER_TRY(bit_input->read_bits<u32>(32));
u32 flac = LOADER_TRY(bit_input.read_bits<u32>(32));
m_data_start_location += 4;
FLAC_VERIFY(flac == 0x664C6143, LoaderError::Category::Format, "Magic number must be 'flaC'"); // "flaC"
// Receive the streaminfo block
auto streaminfo = TRY(next_meta_block(*bit_input));
auto streaminfo = TRY(next_meta_block(bit_input));
FLAC_VERIFY(streaminfo.type == FlacMetadataBlockType::STREAMINFO, LoaderError::Category::Format, "First block must be STREAMINFO");
auto streaminfo_data_memory = LOADER_TRY(FixedMemoryStream::construct(streaminfo.data.bytes()));
auto streaminfo_data = LOADER_TRY(BigEndianInputBitStream::construct(MaybeOwned<AK::Stream>(*streaminfo_data_memory)));
BigEndianInputBitStream streaminfo_data { MaybeOwned<AK::Stream>(*streaminfo_data_memory) };
// 11.10 METADATA_BLOCK_STREAMINFO
m_min_block_size = LOADER_TRY(streaminfo_data->read_bits<u16>(16));
m_min_block_size = LOADER_TRY(streaminfo_data.read_bits<u16>(16));
FLAC_VERIFY(m_min_block_size >= 16, LoaderError::Category::Format, "Minimum block size must be 16");
m_max_block_size = LOADER_TRY(streaminfo_data->read_bits<u16>(16));
m_max_block_size = LOADER_TRY(streaminfo_data.read_bits<u16>(16));
FLAC_VERIFY(m_max_block_size >= 16, LoaderError::Category::Format, "Maximum block size");
m_min_frame_size = LOADER_TRY(streaminfo_data->read_bits<u32>(24));
m_max_frame_size = LOADER_TRY(streaminfo_data->read_bits<u32>(24));
m_sample_rate = LOADER_TRY(streaminfo_data->read_bits<u32>(20));
m_min_frame_size = LOADER_TRY(streaminfo_data.read_bits<u32>(24));
m_max_frame_size = LOADER_TRY(streaminfo_data.read_bits<u32>(24));
m_sample_rate = LOADER_TRY(streaminfo_data.read_bits<u32>(20));
FLAC_VERIFY(m_sample_rate <= 655350, LoaderError::Category::Format, "Sample rate");
m_num_channels = LOADER_TRY(streaminfo_data->read_bits<u8>(3)) + 1; // 0 = one channel
m_num_channels = LOADER_TRY(streaminfo_data.read_bits<u8>(3)) + 1; // 0 = one channel
u8 bits_per_sample = LOADER_TRY(streaminfo_data->read_bits<u8>(5)) + 1;
u8 bits_per_sample = LOADER_TRY(streaminfo_data.read_bits<u8>(5)) + 1;
if (bits_per_sample == 8) {
// FIXME: Signed/Unsigned issues?
m_sample_format = PcmSampleFormat::Uint8;
@ -106,12 +106,12 @@ MaybeLoaderError FlacLoaderPlugin::parse_header()
FLAC_VERIFY(false, LoaderError::Category::Format, "Sample bit depth invalid");
}
m_total_samples = LOADER_TRY(streaminfo_data->read_bits<u64>(36));
m_total_samples = LOADER_TRY(streaminfo_data.read_bits<u64>(36));
FLAC_VERIFY(m_total_samples > 0, LoaderError::Category::Format, "Number of samples is zero");
// Parse checksum into a buffer first
[[maybe_unused]] u128 md5_checksum;
VERIFY(streaminfo_data->is_aligned_to_byte_boundary());
auto md5_bytes_read = LOADER_TRY(streaminfo_data->read(md5_checksum.bytes()));
VERIFY(streaminfo_data.is_aligned_to_byte_boundary());
auto md5_bytes_read = LOADER_TRY(streaminfo_data.read(md5_checksum.bytes()));
FLAC_VERIFY(md5_bytes_read.size() == md5_checksum.my_size(), LoaderError::Category::IO, "MD5 Checksum size");
md5_checksum.bytes().copy_to({ m_md5_checksum, sizeof(m_md5_checksum) });
@ -120,7 +120,7 @@ MaybeLoaderError FlacLoaderPlugin::parse_header()
[[maybe_unused]] u16 total_meta_blocks = meta_blocks_parsed;
FlacRawMetadataBlock block = streaminfo;
while (!block.is_last_block) {
block = TRY(next_meta_block(*bit_input));
block = TRY(next_meta_block(bit_input));
switch (block.type) {
case (FlacMetadataBlockType::SEEKTABLE):
TRY(load_seektable(block));
@ -150,30 +150,30 @@ MaybeLoaderError FlacLoaderPlugin::parse_header()
MaybeLoaderError FlacLoaderPlugin::load_picture(FlacRawMetadataBlock& block)
{
auto memory_stream = LOADER_TRY(FixedMemoryStream::construct(block.data.bytes()));
auto picture_block_bytes = LOADER_TRY(BigEndianInputBitStream::construct(MaybeOwned<AK::Stream>(*memory_stream)));
BigEndianInputBitStream picture_block_bytes { MaybeOwned<AK::Stream>(*memory_stream) };
PictureData picture {};
picture.type = static_cast<ID3PictureType>(LOADER_TRY(picture_block_bytes->read_bits(32)));
picture.type = static_cast<ID3PictureType>(LOADER_TRY(picture_block_bytes.read_bits(32)));
auto const mime_string_length = LOADER_TRY(picture_block_bytes->read_bits(32));
auto const mime_string_length = LOADER_TRY(picture_block_bytes.read_bits(32));
// Note: We are seeking before reading the value to ensure that we stayed inside buffer's size.
auto offset_before_seeking = memory_stream->offset();
LOADER_TRY(memory_stream->seek(mime_string_length, SeekMode::FromCurrentPosition));
picture.mime_string = { block.data.bytes().data() + offset_before_seeking, (size_t)mime_string_length };
auto const description_string_length = LOADER_TRY(picture_block_bytes->read_bits(32));
auto const description_string_length = LOADER_TRY(picture_block_bytes.read_bits(32));
offset_before_seeking = memory_stream->offset();
LOADER_TRY(memory_stream->seek(description_string_length, SeekMode::FromCurrentPosition));
picture.description_string = Vector<u32> { Span<u32> { reinterpret_cast<u32*>(block.data.bytes().data() + offset_before_seeking), (size_t)description_string_length } };
picture.width = LOADER_TRY(picture_block_bytes->read_bits(32));
picture.height = LOADER_TRY(picture_block_bytes->read_bits(32));
picture.width = LOADER_TRY(picture_block_bytes.read_bits(32));
picture.height = LOADER_TRY(picture_block_bytes.read_bits(32));
picture.color_depth = LOADER_TRY(picture_block_bytes->read_bits(32));
picture.colors = LOADER_TRY(picture_block_bytes->read_bits(32));
picture.color_depth = LOADER_TRY(picture_block_bytes.read_bits(32));
picture.colors = LOADER_TRY(picture_block_bytes.read_bits(32));
auto const picture_size = LOADER_TRY(picture_block_bytes->read_bits(32));
auto const picture_size = LOADER_TRY(picture_block_bytes.read_bits(32));
offset_before_seeking = memory_stream->offset();
LOADER_TRY(memory_stream->seek(picture_size, SeekMode::FromCurrentPosition));
picture.data = Vector<u8> { Span<u8> { block.data.bytes().data() + offset_before_seeking, (size_t)picture_size } };
@ -187,13 +187,13 @@ MaybeLoaderError FlacLoaderPlugin::load_picture(FlacRawMetadataBlock& block)
MaybeLoaderError FlacLoaderPlugin::load_seektable(FlacRawMetadataBlock& block)
{
auto memory_stream = LOADER_TRY(FixedMemoryStream::construct(block.data.bytes()));
auto seektable_bytes = LOADER_TRY(BigEndianInputBitStream::construct(MaybeOwned<AK::Stream>(*memory_stream)));
BigEndianInputBitStream seektable_bytes { MaybeOwned<AK::Stream>(*memory_stream) };
for (size_t i = 0; i < block.length / 18; ++i) {
// 11.14. SEEKPOINT
FlacSeekPoint seekpoint {
.sample_index = LOADER_TRY(seektable_bytes->read_bits<u64>(64)),
.byte_offset = LOADER_TRY(seektable_bytes->read_bits<u64>(64)),
.num_samples = LOADER_TRY(seektable_bytes->read_bits<u16>(16))
.sample_index = LOADER_TRY(seektable_bytes.read_bits<u64>(64)),
.byte_offset = LOADER_TRY(seektable_bytes.read_bits<u64>(64)),
.num_samples = LOADER_TRY(seektable_bytes.read_bits<u16>(16))
};
m_seektable.append(seekpoint);
}
@ -333,55 +333,55 @@ MaybeLoaderError FlacLoaderPlugin::next_frame(Span<Sample> target_vector)
} \
} while (0)
auto bit_stream = LOADER_TRY(BigEndianInputBitStream::construct(MaybeOwned<AK::Stream>(*m_stream)));
BigEndianInputBitStream bit_stream { MaybeOwned<AK::Stream>(*m_stream) };
// TODO: Check the CRC-16 checksum (and others) by keeping track of read data
// 11.22. FRAME_HEADER
u16 sync_code = LOADER_TRY(bit_stream->read_bits<u16>(14));
u16 sync_code = LOADER_TRY(bit_stream.read_bits<u16>(14));
FLAC_VERIFY(sync_code == 0b11111111111110, LoaderError::Category::Format, "Sync code");
bool reserved_bit = LOADER_TRY(bit_stream->read_bit());
bool reserved_bit = LOADER_TRY(bit_stream.read_bit());
FLAC_VERIFY(reserved_bit == 0, LoaderError::Category::Format, "Reserved frame header bit");
// 11.22.2. BLOCKING STRATEGY
[[maybe_unused]] bool blocking_strategy = LOADER_TRY(bit_stream->read_bit());
[[maybe_unused]] bool blocking_strategy = LOADER_TRY(bit_stream.read_bit());
u32 sample_count = TRY(convert_sample_count_code(LOADER_TRY(bit_stream->read_bits<u8>(4))));
u32 sample_count = TRY(convert_sample_count_code(LOADER_TRY(bit_stream.read_bits<u8>(4))));
u32 frame_sample_rate = TRY(convert_sample_rate_code(LOADER_TRY(bit_stream->read_bits<u8>(4))));
u32 frame_sample_rate = TRY(convert_sample_rate_code(LOADER_TRY(bit_stream.read_bits<u8>(4))));
u8 channel_type_num = LOADER_TRY(bit_stream->read_bits<u8>(4));
u8 channel_type_num = LOADER_TRY(bit_stream.read_bits<u8>(4));
FLAC_VERIFY(channel_type_num < 0b1011, LoaderError::Category::Format, "Channel assignment");
FlacFrameChannelType channel_type = (FlacFrameChannelType)channel_type_num;
PcmSampleFormat bit_depth = TRY(convert_bit_depth_code(LOADER_TRY(bit_stream->read_bits<u8>(3))));
PcmSampleFormat bit_depth = TRY(convert_bit_depth_code(LOADER_TRY(bit_stream.read_bits<u8>(3))));
reserved_bit = LOADER_TRY(bit_stream->read_bit());
reserved_bit = LOADER_TRY(bit_stream.read_bit());
FLAC_VERIFY(reserved_bit == 0, LoaderError::Category::Format, "Reserved frame header end bit");
// 11.22.8. CODED NUMBER
// FIXME: sample number can be 8-56 bits, frame number can be 8-48 bits
m_current_sample_or_frame = LOADER_TRY(read_utf8_char(*bit_stream));
m_current_sample_or_frame = LOADER_TRY(read_utf8_char(bit_stream));
// Conditional header variables
// 11.22.9. BLOCK SIZE INT
if (sample_count == FLAC_BLOCKSIZE_AT_END_OF_HEADER_8) {
sample_count = LOADER_TRY(bit_stream->read_bits<u32>(8)) + 1;
sample_count = LOADER_TRY(bit_stream.read_bits<u32>(8)) + 1;
} else if (sample_count == FLAC_BLOCKSIZE_AT_END_OF_HEADER_16) {
sample_count = LOADER_TRY(bit_stream->read_bits<u32>(16)) + 1;
sample_count = LOADER_TRY(bit_stream.read_bits<u32>(16)) + 1;
}
// 11.22.10. SAMPLE RATE INT
if (frame_sample_rate == FLAC_SAMPLERATE_AT_END_OF_HEADER_8) {
frame_sample_rate = LOADER_TRY(bit_stream->read_bits<u32>(8)) * 1000;
frame_sample_rate = LOADER_TRY(bit_stream.read_bits<u32>(8)) * 1000;
} else if (frame_sample_rate == FLAC_SAMPLERATE_AT_END_OF_HEADER_16) {
frame_sample_rate = LOADER_TRY(bit_stream->read_bits<u32>(16));
frame_sample_rate = LOADER_TRY(bit_stream.read_bits<u32>(16));
} else if (frame_sample_rate == FLAC_SAMPLERATE_AT_END_OF_HEADER_16X10) {
frame_sample_rate = LOADER_TRY(bit_stream->read_bits<u32>(16)) * 10;
frame_sample_rate = LOADER_TRY(bit_stream.read_bits<u32>(16)) * 10;
}
// 11.22.11. FRAME CRC
// TODO: check header checksum, see above
[[maybe_unused]] u8 checksum = LOADER_TRY(bit_stream->read_bits<u8>(8));
[[maybe_unused]] u8 checksum = LOADER_TRY(bit_stream.read_bits<u8>(8));
dbgln_if(AFLACLOADER_DEBUG, "Frame: {} samples, {}bit {}Hz, channeltype {:x}, {} number {}, header checksum {}", sample_count, pcm_bits_per_sample(bit_depth), frame_sample_rate, channel_type_num, blocking_strategy ? "sample" : "frame", m_current_sample_or_frame, checksum);
@ -397,17 +397,17 @@ MaybeLoaderError FlacLoaderPlugin::next_frame(Span<Sample> target_vector)
current_subframes.ensure_capacity(subframe_count);
for (u8 i = 0; i < subframe_count; ++i) {
FlacSubframeHeader new_subframe = TRY(next_subframe_header(*bit_stream, i));
Vector<i32> subframe_samples = TRY(parse_subframe(new_subframe, *bit_stream));
FlacSubframeHeader new_subframe = TRY(next_subframe_header(bit_stream, i));
Vector<i32> subframe_samples = TRY(parse_subframe(new_subframe, bit_stream));
current_subframes.unchecked_append(move(subframe_samples));
}
// 11.2. Overview ("The audio data is composed of...")
bit_stream->align_to_byte_boundary();
bit_stream.align_to_byte_boundary();
// 11.23. FRAME_FOOTER
// TODO: check checksum, see above
[[maybe_unused]] u16 footer_checksum = LOADER_TRY(bit_stream->read_bits<u16>(16));
[[maybe_unused]] u16 footer_checksum = LOADER_TRY(bit_stream.read_bits<u16>(16));
dbgln_if(AFLACLOADER_DEBUG, "Subframe footer checksum: {}", footer_checksum);
Vector<i32> left;

View file

@ -41,7 +41,7 @@ Result<NonnullOwnPtr<MP3LoaderPlugin>, LoaderError> MP3LoaderPlugin::create(Byte
MaybeLoaderError MP3LoaderPlugin::initialize()
{
m_bitstream = LOADER_TRY(BigEndianInputBitStream::construct(MaybeOwned<AK::Stream>(*m_stream)));
m_bitstream = LOADER_TRY(try_make<BigEndianInputBitStream>(MaybeOwned<AK::Stream>(*m_stream)));
TRY(synchronize());
@ -242,12 +242,12 @@ ErrorOr<MP3::MP3Frame, LoaderError> MP3LoaderPlugin::read_frame_data(MP3::Header
TRY(m_bit_reservoir.discard(old_reservoir_size - frame.main_data_begin));
auto reservoir_stream = TRY(BigEndianInputBitStream::construct(MaybeOwned<AK::Stream>(m_bit_reservoir)));
BigEndianInputBitStream reservoir_stream { MaybeOwned<AK::Stream>(m_bit_reservoir) };
for (size_t granule_index = 0; granule_index < 2; granule_index++) {
for (size_t channel_index = 0; channel_index < header.channel_count(); channel_index++) {
size_t scale_factor_size = TRY(read_scale_factors(frame, *reservoir_stream, granule_index, channel_index));
TRY(read_huffman_data(frame, *reservoir_stream, granule_index, channel_index, scale_factor_size));
size_t scale_factor_size = TRY(read_scale_factors(frame, reservoir_stream, granule_index, channel_index));
TRY(read_huffman_data(frame, reservoir_stream, granule_index, channel_index, scale_factor_size));
if (frame.channels[channel_index].granules[granule_index].block_type == MP3::BlockType::Short) {
reorder_samples(frame.channels[channel_index].granules[granule_index], frame.header.samplerate);