From 1ee2091b2d73808b245aeaf79e709ecc0017e65b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?kleines=20Filmr=C3=B6llchen?= Date: Tue, 14 Mar 2023 19:35:10 +0100 Subject: [PATCH] LibAudio: Support FLAC files with unknown amount of samples This is a special case of the sample count field in the header which we treated as a format error before. Now we just take care to check stream EOF before reading chunks. This makes the final FLAC spec test pass, making us one of the most compliant loaders! :^) --- Userland/Libraries/LibAudio/FlacLoader.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/Userland/Libraries/LibAudio/FlacLoader.cpp b/Userland/Libraries/LibAudio/FlacLoader.cpp index 56d5b442f6..11ae35f714 100644 --- a/Userland/Libraries/LibAudio/FlacLoader.cpp +++ b/Userland/Libraries/LibAudio/FlacLoader.cpp @@ -109,7 +109,11 @@ MaybeLoaderError FlacLoaderPlugin::parse_header() } m_total_samples = LOADER_TRY(streaminfo_data.read_bits(36)); - FLAC_VERIFY(m_total_samples > 0, LoaderError::Category::Format, "Number of samples is zero"); + if (m_total_samples == 0) { + // "A value of zero here means the number of total samples is unknown." + dbgln("FLAC Warning: File has unknown amount of samples, the loader will not stop before EOF"); + m_total_samples = NumericLimits::max(); + } VERIFY(streaminfo_data.is_aligned_to_byte_boundary()); LOADER_TRY(streaminfo_data.read_until_filled({ m_md5_checksum, sizeof(m_md5_checksum) })); @@ -129,7 +133,7 @@ MaybeLoaderError FlacLoaderPlugin::parse_header() break; case FlacMetadataBlockType::APPLICATION: // Note: Third-party library can encode specific data in this. - dbgln("Unknown 'Application' metadata block encountered."); + dbgln("FLAC Warning: Unknown 'Application' metadata block encountered."); [[fallthrough]]; case FlacMetadataBlockType::PADDING: // Note: A padding block is empty and does not need any treatment. @@ -330,14 +334,15 @@ bool FlacLoaderPlugin::should_insert_seekpoint_at(u64 sample_index) const ErrorOr>, LoaderError> FlacLoaderPlugin::load_chunks(size_t samples_to_read_from_input) { ssize_t remaining_samples = static_cast(m_total_samples - m_loaded_samples); - if (remaining_samples <= 0) + // The first condition is relevant for unknown-size streams (total samples = 0 in the header) + if (m_stream->is_eof() || remaining_samples <= 0) return Vector> {}; size_t samples_to_read = min(samples_to_read_from_input, remaining_samples); Vector> frames; size_t sample_index = 0; - while (sample_index < samples_to_read) { + while (!m_stream->is_eof() && sample_index < samples_to_read) { TRY(frames.try_append(TRY(next_frame()))); sample_index += m_current_frame->sample_count; }