From fc70d88367e361b8e865427a8669276253dc32e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?kleines=20Filmr=C3=B6llchen?= Date: Tue, 27 Jun 2023 22:58:54 +0200 Subject: [PATCH] LibAudio: Handle unknown-sized streams better Especially FLAC had an issue here before, but the loader infrastructure itself wouldn't handle end of stream properly if the "available samples" information didn't match up. --- Userland/Libraries/LibAudio/FlacLoader.cpp | 3 ++- Userland/Libraries/LibAudio/Loader.cpp | 7 ++++++- Userland/Libraries/LibAudio/Loader.h | 9 ++++++++- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/Userland/Libraries/LibAudio/FlacLoader.cpp b/Userland/Libraries/LibAudio/FlacLoader.cpp index bab2308aaf..44cc133b84 100644 --- a/Userland/Libraries/LibAudio/FlacLoader.cpp +++ b/Userland/Libraries/LibAudio/FlacLoader.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -338,7 +339,7 @@ ErrorOr>, LoaderError> FlacLoaderPlugin::load_chunks(s { ssize_t remaining_samples = static_cast(m_total_samples - m_loaded_samples); // The first condition is relevant for unknown-size streams (total samples = 0 in the header) - if (m_stream->is_eof() || remaining_samples <= 0) + if (m_stream->is_eof() || (m_total_samples < NumericLimits::max() && remaining_samples <= 0)) return Vector> {}; size_t samples_to_read = min(samples_to_read_from_input, remaining_samples); diff --git a/Userland/Libraries/LibAudio/Loader.cpp b/Userland/Libraries/LibAudio/Loader.cpp index cf03768d25..3abcf7c7fe 100644 --- a/Userland/Libraries/LibAudio/Loader.cpp +++ b/Userland/Libraries/LibAudio/Loader.cpp @@ -68,6 +68,9 @@ ErrorOr, LoaderError> Loader::create_plugin(NonnullO LoaderSamples Loader::get_more_samples(size_t samples_to_read_from_input) { + if (m_plugin_at_end_of_stream) + return FixedArray {}; + size_t remaining_samples = total_samples() - loaded_samples(); size_t samples_to_read = min(remaining_samples, samples_to_read_from_input); auto samples = TRY(FixedArray::create(samples_to_read)); @@ -88,8 +91,10 @@ LoaderSamples Loader::get_more_samples(size_t samples_to_read_from_input) while (sample_index < samples_to_read) { auto chunk_data = TRY(m_plugin->load_chunks(samples_to_read - sample_index)); chunk_data.remove_all_matching([](auto& chunk) { return chunk.is_empty(); }); - if (chunk_data.is_empty()) + if (chunk_data.is_empty()) { + m_plugin_at_end_of_stream = true; break; + } for (auto& chunk : chunk_data) { if (sample_index < samples_to_read) { auto count = min(samples_to_read - sample_index, chunk.size()); diff --git a/Userland/Libraries/LibAudio/Loader.h b/Userland/Libraries/LibAudio/Loader.h index 3acde4fcc7..04dbc200d8 100644 --- a/Userland/Libraries/LibAudio/Loader.h +++ b/Userland/Libraries/LibAudio/Loader.h @@ -91,10 +91,15 @@ public: // Will only read less samples if we're at the end of the stream. LoaderSamples get_more_samples(size_t samples_to_read_from_input = 128 * KiB); - MaybeLoaderError reset() const { return m_plugin->reset(); } + MaybeLoaderError reset() const + { + m_plugin_at_end_of_stream = false; + return m_plugin->reset(); + } MaybeLoaderError seek(int const position) const { m_buffer.clear_with_capacity(); + m_plugin_at_end_of_stream = false; return m_plugin->seek(position); } @@ -114,6 +119,8 @@ private: explicit Loader(NonnullOwnPtr); mutable NonnullOwnPtr m_plugin; + // The plugin can signal an end of stream by returning no (or only empty) chunks. + mutable bool m_plugin_at_end_of_stream { false }; mutable Vector m_buffer; };