mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-06-09 17:44:56 +09:00
AK: Remove the fallible constructor from BigEndianInputBitStream
This commit is contained in:
parent
839bec14af
commit
fa09152e23
Notes:
sideshowbarker
2024-07-17 23:00:03 +09:00
Author: https://github.com/timschumi
Commit: fa09152e23
Pull-request: https://github.com/SerenityOS/serenity/pull/17264
4 changed files with 64 additions and 69 deletions
|
@ -17,9 +17,9 @@ namespace AK {
|
||||||
/// in big-endian order from another stream.
|
/// in big-endian order from another stream.
|
||||||
class BigEndianInputBitStream : public Stream {
|
class BigEndianInputBitStream : public Stream {
|
||||||
public:
|
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
|
// ^Stream
|
||||||
|
@ -112,11 +112,6 @@ public:
|
||||||
ALWAYS_INLINE bool is_aligned_to_byte_boundary() const { return m_bit_offset == 0; }
|
ALWAYS_INLINE bool is_aligned_to_byte_boundary() const { return m_bit_offset == 0; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BigEndianInputBitStream(MaybeOwned<Stream> stream)
|
|
||||||
: m_stream(move(stream))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Optional<u8> m_current_byte;
|
Optional<u8> m_current_byte;
|
||||||
size_t m_bit_offset { 0 };
|
size_t m_bit_offset { 0 };
|
||||||
MaybeOwned<Stream> m_stream;
|
MaybeOwned<Stream> m_stream;
|
||||||
|
|
|
@ -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,
|
// 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.
|
// 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_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.
|
// 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));
|
||||||
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);
|
EXPECT_EQ(0b1111u, result);
|
||||||
result = MUST(bit_read_stream->read_bits(4));
|
result = MUST(bit_read_stream.read_bits(4));
|
||||||
EXPECT_EQ(0b1111u, result);
|
EXPECT_EQ(0b1111u, result);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
MUST(bit_write_stream->write_bits(0b0000u, 4));
|
MUST(bit_write_stream->write_bits(0b0000u, 4));
|
||||||
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);
|
EXPECT_EQ(0b0000u, result);
|
||||||
result = MUST(bit_read_stream->read_bits(4));
|
result = MUST(bit_read_stream.read_bits(4));
|
||||||
EXPECT_EQ(0b0000u, result);
|
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));
|
||||||
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);
|
EXPECT_EQ(0b1000u, result);
|
||||||
result = MUST(bit_read_stream->read_bits(4));
|
result = MUST(bit_read_stream.read_bits(4));
|
||||||
EXPECT_EQ(0b1000u, result);
|
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(0b1000u, 4));
|
||||||
MUST(bit_write_stream->write_bits(0b0100u, 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);
|
EXPECT_EQ(0b1000u, result);
|
||||||
result = MUST(bit_read_stream->read_bits(4));
|
result = MUST(bit_read_stream.read_bits(4));
|
||||||
EXPECT_EQ(0b0100u, result);
|
EXPECT_EQ(0b0100u, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test a pattern that spans multiple bytes.
|
// Test a pattern that spans multiple bytes.
|
||||||
{
|
{
|
||||||
MUST(bit_write_stream->write_bits(0b1101001000100001u, 16));
|
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);
|
EXPECT_EQ(0b1101001000100001u, result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,7 +60,7 @@ MaybeLoaderError FlacLoaderPlugin::initialize()
|
||||||
// 11.5 STREAM
|
// 11.5 STREAM
|
||||||
MaybeLoaderError FlacLoaderPlugin::parse_header()
|
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().
|
// A mixture of VERIFY and the non-crashing TRY().
|
||||||
#define FLAC_VERIFY(check, category, msg) \
|
#define FLAC_VERIFY(check, category, msg) \
|
||||||
|
@ -71,28 +71,28 @@ MaybeLoaderError FlacLoaderPlugin::parse_header()
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
// Magic number
|
// 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;
|
m_data_start_location += 4;
|
||||||
FLAC_VERIFY(flac == 0x664C6143, LoaderError::Category::Format, "Magic number must be 'flaC'"); // "flaC"
|
FLAC_VERIFY(flac == 0x664C6143, LoaderError::Category::Format, "Magic number must be 'flaC'"); // "flaC"
|
||||||
|
|
||||||
// Receive the streaminfo block
|
// 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");
|
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_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
|
// 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");
|
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");
|
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_min_frame_size = LOADER_TRY(streaminfo_data.read_bits<u32>(24));
|
||||||
m_max_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_sample_rate = LOADER_TRY(streaminfo_data.read_bits<u32>(20));
|
||||||
FLAC_VERIFY(m_sample_rate <= 655350, LoaderError::Category::Format, "Sample rate");
|
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) {
|
if (bits_per_sample == 8) {
|
||||||
// FIXME: Signed/Unsigned issues?
|
// FIXME: Signed/Unsigned issues?
|
||||||
m_sample_format = PcmSampleFormat::Uint8;
|
m_sample_format = PcmSampleFormat::Uint8;
|
||||||
|
@ -106,12 +106,12 @@ MaybeLoaderError FlacLoaderPlugin::parse_header()
|
||||||
FLAC_VERIFY(false, LoaderError::Category::Format, "Sample bit depth invalid");
|
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");
|
FLAC_VERIFY(m_total_samples > 0, LoaderError::Category::Format, "Number of samples is zero");
|
||||||
// Parse checksum into a buffer first
|
// Parse checksum into a buffer first
|
||||||
[[maybe_unused]] u128 md5_checksum;
|
[[maybe_unused]] u128 md5_checksum;
|
||||||
VERIFY(streaminfo_data->is_aligned_to_byte_boundary());
|
VERIFY(streaminfo_data.is_aligned_to_byte_boundary());
|
||||||
auto md5_bytes_read = LOADER_TRY(streaminfo_data->read(md5_checksum.bytes()));
|
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");
|
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) });
|
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;
|
[[maybe_unused]] u16 total_meta_blocks = meta_blocks_parsed;
|
||||||
FlacRawMetadataBlock block = streaminfo;
|
FlacRawMetadataBlock block = streaminfo;
|
||||||
while (!block.is_last_block) {
|
while (!block.is_last_block) {
|
||||||
block = TRY(next_meta_block(*bit_input));
|
block = TRY(next_meta_block(bit_input));
|
||||||
switch (block.type) {
|
switch (block.type) {
|
||||||
case (FlacMetadataBlockType::SEEKTABLE):
|
case (FlacMetadataBlockType::SEEKTABLE):
|
||||||
TRY(load_seektable(block));
|
TRY(load_seektable(block));
|
||||||
|
@ -150,30 +150,30 @@ MaybeLoaderError FlacLoaderPlugin::parse_header()
|
||||||
MaybeLoaderError FlacLoaderPlugin::load_picture(FlacRawMetadataBlock& block)
|
MaybeLoaderError FlacLoaderPlugin::load_picture(FlacRawMetadataBlock& block)
|
||||||
{
|
{
|
||||||
auto memory_stream = LOADER_TRY(FixedMemoryStream::construct(block.data.bytes()));
|
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 {};
|
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.
|
// Note: We are seeking before reading the value to ensure that we stayed inside buffer's size.
|
||||||
auto offset_before_seeking = memory_stream->offset();
|
auto offset_before_seeking = memory_stream->offset();
|
||||||
LOADER_TRY(memory_stream->seek(mime_string_length, SeekMode::FromCurrentPosition));
|
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 };
|
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();
|
offset_before_seeking = memory_stream->offset();
|
||||||
LOADER_TRY(memory_stream->seek(description_string_length, SeekMode::FromCurrentPosition));
|
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.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.width = LOADER_TRY(picture_block_bytes.read_bits(32));
|
||||||
picture.height = 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.color_depth = LOADER_TRY(picture_block_bytes.read_bits(32));
|
||||||
picture.colors = 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();
|
offset_before_seeking = memory_stream->offset();
|
||||||
LOADER_TRY(memory_stream->seek(picture_size, SeekMode::FromCurrentPosition));
|
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 } };
|
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)
|
MaybeLoaderError FlacLoaderPlugin::load_seektable(FlacRawMetadataBlock& block)
|
||||||
{
|
{
|
||||||
auto memory_stream = LOADER_TRY(FixedMemoryStream::construct(block.data.bytes()));
|
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) {
|
for (size_t i = 0; i < block.length / 18; ++i) {
|
||||||
// 11.14. SEEKPOINT
|
// 11.14. SEEKPOINT
|
||||||
FlacSeekPoint seekpoint {
|
FlacSeekPoint seekpoint {
|
||||||
.sample_index = LOADER_TRY(seektable_bytes->read_bits<u64>(64)),
|
.sample_index = LOADER_TRY(seektable_bytes.read_bits<u64>(64)),
|
||||||
.byte_offset = 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))
|
.num_samples = LOADER_TRY(seektable_bytes.read_bits<u16>(16))
|
||||||
};
|
};
|
||||||
m_seektable.append(seekpoint);
|
m_seektable.append(seekpoint);
|
||||||
}
|
}
|
||||||
|
@ -333,55 +333,55 @@ MaybeLoaderError FlacLoaderPlugin::next_frame(Span<Sample> target_vector)
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} 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
|
// TODO: Check the CRC-16 checksum (and others) by keeping track of read data
|
||||||
|
|
||||||
// 11.22. FRAME_HEADER
|
// 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");
|
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");
|
FLAC_VERIFY(reserved_bit == 0, LoaderError::Category::Format, "Reserved frame header bit");
|
||||||
// 11.22.2. BLOCKING STRATEGY
|
// 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");
|
FLAC_VERIFY(channel_type_num < 0b1011, LoaderError::Category::Format, "Channel assignment");
|
||||||
FlacFrameChannelType channel_type = (FlacFrameChannelType)channel_type_num;
|
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");
|
FLAC_VERIFY(reserved_bit == 0, LoaderError::Category::Format, "Reserved frame header end bit");
|
||||||
|
|
||||||
// 11.22.8. CODED NUMBER
|
// 11.22.8. CODED NUMBER
|
||||||
// FIXME: sample number can be 8-56 bits, frame number can be 8-48 bits
|
// 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
|
// Conditional header variables
|
||||||
// 11.22.9. BLOCK SIZE INT
|
// 11.22.9. BLOCK SIZE INT
|
||||||
if (sample_count == FLAC_BLOCKSIZE_AT_END_OF_HEADER_8) {
|
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) {
|
} 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
|
// 11.22.10. SAMPLE RATE INT
|
||||||
if (frame_sample_rate == FLAC_SAMPLERATE_AT_END_OF_HEADER_8) {
|
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) {
|
} 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) {
|
} 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
|
// 11.22.11. FRAME CRC
|
||||||
// TODO: check header checksum, see above
|
// 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);
|
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);
|
current_subframes.ensure_capacity(subframe_count);
|
||||||
|
|
||||||
for (u8 i = 0; i < subframe_count; ++i) {
|
for (u8 i = 0; i < subframe_count; ++i) {
|
||||||
FlacSubframeHeader new_subframe = TRY(next_subframe_header(*bit_stream, i));
|
FlacSubframeHeader new_subframe = TRY(next_subframe_header(bit_stream, i));
|
||||||
Vector<i32> subframe_samples = TRY(parse_subframe(new_subframe, *bit_stream));
|
Vector<i32> subframe_samples = TRY(parse_subframe(new_subframe, bit_stream));
|
||||||
current_subframes.unchecked_append(move(subframe_samples));
|
current_subframes.unchecked_append(move(subframe_samples));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 11.2. Overview ("The audio data is composed of...")
|
// 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
|
// 11.23. FRAME_FOOTER
|
||||||
// TODO: check checksum, see above
|
// 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);
|
dbgln_if(AFLACLOADER_DEBUG, "Subframe footer checksum: {}", footer_checksum);
|
||||||
|
|
||||||
Vector<i32> left;
|
Vector<i32> left;
|
||||||
|
|
|
@ -41,7 +41,7 @@ Result<NonnullOwnPtr<MP3LoaderPlugin>, LoaderError> MP3LoaderPlugin::create(Byte
|
||||||
|
|
||||||
MaybeLoaderError MP3LoaderPlugin::initialize()
|
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());
|
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));
|
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 granule_index = 0; granule_index < 2; granule_index++) {
|
||||||
for (size_t channel_index = 0; channel_index < header.channel_count(); channel_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));
|
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));
|
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) {
|
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);
|
reorder_samples(frame.channels[channel_index].granules[granule_index], frame.header.samplerate);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue