diff --git a/Libraries/LibMedia/Audio/FFmpegLoader.cpp b/Libraries/LibMedia/Audio/FFmpegLoader.cpp index bd0b55d6c10..4ce6768670c 100644 --- a/Libraries/LibMedia/Audio/FFmpegLoader.cpp +++ b/Libraries/LibMedia/Audio/FFmpegLoader.cpp @@ -31,11 +31,11 @@ FFmpegIOContext::~FFmpegIOContext() avio_context_free(&m_avio_context); } -ErrorOr, LoaderError> FFmpegIOContext::create(AK::SeekableStream& stream) +ErrorOr> FFmpegIOContext::create(AK::SeekableStream& stream) { auto* avio_buffer = av_malloc(PAGE_SIZE); if (avio_buffer == nullptr) - return LoaderError { LoaderError::Category::IO, "Failed to allocate AVIO buffer" }; + return Error::from_string_literal("Failed to allocate AVIO buffer"); // This AVIOContext explains to avformat how to interact with our stream auto* avio_context = avio_alloc_context( @@ -79,7 +79,7 @@ ErrorOr, LoaderError> FFmpegIOContext::create(AK: }); if (avio_context == nullptr) { av_free(avio_buffer); - return LoaderError { LoaderError::Category::IO, "Failed to allocate AVIO context" }; + return Error::from_string_literal("Failed to allocate AVIO context"); } return make(avio_context); @@ -103,7 +103,7 @@ FFmpegLoaderPlugin::~FFmpegLoaderPlugin() avformat_close_input(&m_format_context); } -ErrorOr, LoaderError> FFmpegLoaderPlugin::create(NonnullOwnPtr stream) +ErrorOr> FFmpegLoaderPlugin::create(NonnullOwnPtr stream) { auto io_context = TRY(FFmpegIOContext::create(*stream)); auto loader = make(move(stream), move(io_context)); @@ -111,19 +111,19 @@ ErrorOr, LoaderError> FFmpegLoaderPlugin::create(Non return loader; } -MaybeLoaderError FFmpegLoaderPlugin::initialize() +ErrorOr FFmpegLoaderPlugin::initialize() { // Open the container m_format_context = avformat_alloc_context(); if (m_format_context == nullptr) - return LoaderError { LoaderError::Category::IO, "Failed to allocate format context" }; + return Error::from_string_literal("Failed to allocate format context"); m_format_context->pb = m_io_context->avio_context(); if (avformat_open_input(&m_format_context, nullptr, nullptr, nullptr) < 0) - return LoaderError { LoaderError::Category::IO, "Failed to open input for format parsing" }; + return Error::from_string_literal("Failed to open input for format parsing"); // Read stream info; doing this is required for headerless formats like MPEG if (avformat_find_stream_info(m_format_context, nullptr) < 0) - return LoaderError { LoaderError::Category::IO, "Failed to find stream info" }; + return Error::from_string_literal("Failed to find stream info"); #ifdef USE_CONSTIFIED_POINTERS AVCodec const* codec {}; @@ -133,42 +133,42 @@ MaybeLoaderError FFmpegLoaderPlugin::initialize() // Find the best stream to play within the container int best_stream_index = av_find_best_stream(m_format_context, AVMediaType::AVMEDIA_TYPE_AUDIO, -1, -1, &codec, 0); if (best_stream_index == AVERROR_STREAM_NOT_FOUND) - return LoaderError { LoaderError::Category::Format, "No audio stream found in container" }; + return Error::from_string_literal("No audio stream found in container"); if (best_stream_index == AVERROR_DECODER_NOT_FOUND) - return LoaderError { LoaderError::Category::Format, "No suitable decoder found for stream" }; + return Error::from_string_literal("No suitable decoder found for stream"); if (best_stream_index < 0) - return LoaderError { LoaderError::Category::Format, "Failed to find an audio stream" }; + return Error::from_string_literal("Failed to find an audio stream"); m_audio_stream = m_format_context->streams[best_stream_index]; // Set up the context to decode the audio stream m_codec_context = avcodec_alloc_context3(codec); if (m_codec_context == nullptr) - return LoaderError { LoaderError::Category::IO, "Failed to allocate the codec context" }; + return Error::from_string_literal("Failed to allocate the codec context"); if (avcodec_parameters_to_context(m_codec_context, m_audio_stream->codecpar) < 0) - return LoaderError { LoaderError::Category::IO, "Failed to copy codec parameters" }; + return Error::from_string_literal("Failed to copy codec parameters"); m_codec_context->pkt_timebase = m_audio_stream->time_base; m_codec_context->thread_count = AK::min(static_cast(Core::System::hardware_concurrency()), 4); if (avcodec_open2(m_codec_context, codec, nullptr) < 0) - return LoaderError { LoaderError::Category::IO, "Failed to open input for decoding" }; + return Error::from_string_literal("Failed to open input for decoding"); // This is an initial estimate of the total number of samples in the stream. // During decoding, we might need to increase the number as more frames come in. double duration_in_seconds = static_cast(m_audio_stream->duration) * time_base(); if (duration_in_seconds < 0) - return LoaderError { LoaderError::Category::Format, "Negative stream duration" }; + return Error::from_string_literal("Negative stream duration"); m_total_samples = AK::round_to(sample_rate() * duration_in_seconds); // Allocate packet (logical chunk of data) and frame (video / audio frame) buffers m_packet = av_packet_alloc(); if (m_packet == nullptr) - return LoaderError { LoaderError::Category::IO, "Failed to allocate packet" }; + return Error::from_string_literal("Failed to allocate packet"); m_frame = av_frame_alloc(); if (m_frame == nullptr) - return LoaderError { LoaderError::Category::IO, "Failed to allocate frame" }; + return Error::from_string_literal("Failed to allocate frame"); return {}; } @@ -253,7 +253,7 @@ static ErrorOr> extract_samples_from_frame(AVFrame& frame) return samples; } -ErrorOr>, LoaderError> FFmpegLoaderPlugin::load_chunks(size_t samples_to_read_from_input) +ErrorOr>> FFmpegLoaderPlugin::load_chunks(size_t samples_to_read_from_input) { Vector> chunks {}; @@ -263,7 +263,7 @@ ErrorOr>, LoaderError> FFmpegLoaderPlugin::load_chunks if (read_frame_error < 0) { if (read_frame_error == AVERROR_EOF) break; - return LoaderError { LoaderError::Category::IO, "Failed to read frame" }; + return Error::from_string_literal("Failed to read frame"); } if (m_packet->stream_index != m_audio_stream->index) { av_packet_unref(m_packet); @@ -272,7 +272,7 @@ ErrorOr>, LoaderError> FFmpegLoaderPlugin::load_chunks // Send the packet to the decoder if (avcodec_send_packet(m_codec_context, m_packet) < 0) - return LoaderError { LoaderError::Category::IO, "Failed to send packet" }; + return Error::from_string_literal("Failed to send packet"); av_packet_unref(m_packet); // Ask the decoder for a new frame. We might not have sent enough data yet @@ -282,7 +282,7 @@ ErrorOr>, LoaderError> FFmpegLoaderPlugin::load_chunks continue; if (receive_frame_error == AVERROR_EOF) break; - return LoaderError { LoaderError::Category::IO, "Failed to receive frame" }; + return Error::from_string_literal("Failed to receive frame"); } chunks.append(TRY(extract_samples_from_frame(*m_frame))); @@ -298,18 +298,18 @@ ErrorOr>, LoaderError> FFmpegLoaderPlugin::load_chunks return chunks; } -MaybeLoaderError FFmpegLoaderPlugin::reset() +ErrorOr FFmpegLoaderPlugin::reset() { return seek(0); } -MaybeLoaderError FFmpegLoaderPlugin::seek(int sample_index) +ErrorOr FFmpegLoaderPlugin::seek(int sample_index) { auto sample_position_in_seconds = static_cast(sample_index) / sample_rate(); auto sample_timestamp = AK::round_to(sample_position_in_seconds / time_base()); if (av_seek_frame(m_format_context, m_audio_stream->index, sample_timestamp, AVSEEK_FLAG_ANY) < 0) - return LoaderError { LoaderError::Category::IO, "Failed to seek" }; + return Error::from_string_literal("Failed to seek"); avcodec_flush_buffers(m_codec_context); m_loaded_samples = sample_index; diff --git a/Libraries/LibMedia/Audio/FFmpegLoader.h b/Libraries/LibMedia/Audio/FFmpegLoader.h index 652d3dd56e0..51ca96d6d5e 100644 --- a/Libraries/LibMedia/Audio/FFmpegLoader.h +++ b/Libraries/LibMedia/Audio/FFmpegLoader.h @@ -22,7 +22,7 @@ public: explicit FFmpegIOContext(AVIOContext*); ~FFmpegIOContext(); - static ErrorOr, LoaderError> create(AK::SeekableStream& stream); + static ErrorOr> create(AK::SeekableStream& stream); AVIOContext* avio_context() const { return m_avio_context; } @@ -36,12 +36,12 @@ public: virtual ~FFmpegLoaderPlugin(); static bool sniff(SeekableStream& stream); - static ErrorOr, LoaderError> create(NonnullOwnPtr); + static ErrorOr> create(NonnullOwnPtr); - virtual ErrorOr>, LoaderError> load_chunks(size_t samples_to_read_from_input) override; + virtual ErrorOr>> load_chunks(size_t samples_to_read_from_input) override; - virtual MaybeLoaderError reset() override; - virtual MaybeLoaderError seek(int sample_index) override; + virtual ErrorOr reset() override; + virtual ErrorOr seek(int sample_index) override; virtual int loaded_samples() override { return m_loaded_samples; } virtual int total_samples() override { return m_total_samples; } @@ -51,7 +51,7 @@ public: virtual ByteString format_name() override; private: - MaybeLoaderError initialize(); + ErrorOr initialize(); double time_base() const; AVStream* m_audio_stream; diff --git a/Libraries/LibMedia/Audio/Loader.cpp b/Libraries/LibMedia/Audio/Loader.cpp index 4d9f1c9851d..2271ab5e97c 100644 --- a/Libraries/LibMedia/Audio/Loader.cpp +++ b/Libraries/LibMedia/Audio/Loader.cpp @@ -24,28 +24,28 @@ Loader::Loader(NonnullOwnPtr plugin) struct LoaderPluginInitializer { bool (*sniff)(SeekableStream&); - ErrorOr, LoaderError> (*create)(NonnullOwnPtr); + ErrorOr> (*create)(NonnullOwnPtr); }; static constexpr LoaderPluginInitializer s_initializers[] = { { FFmpegLoaderPlugin::sniff, FFmpegLoaderPlugin::create }, }; -ErrorOr, LoaderError> Loader::create(StringView path) +ErrorOr> Loader::create(StringView path) { auto stream = TRY(Core::MappedFile::map(path, Core::MappedFile::Mode::ReadOnly)); auto plugin = TRY(Loader::create_plugin(move(stream))); return adopt_ref(*new (nothrow) Loader(move(plugin))); } -ErrorOr, LoaderError> Loader::create(ReadonlyBytes buffer) +ErrorOr> Loader::create(ReadonlyBytes buffer) { auto stream = TRY(try_make(buffer)); auto plugin = TRY(Loader::create_plugin(move(stream))); return adopt_ref(*new (nothrow) Loader(move(plugin))); } -ErrorOr, LoaderError> Loader::create_plugin(NonnullOwnPtr stream) +ErrorOr> Loader::create_plugin(NonnullOwnPtr stream) { for (auto const& loader : s_initializers) { if (loader.sniff(*stream)) { @@ -55,17 +55,17 @@ ErrorOr, LoaderError> Loader::create_plugin(NonnullO TRY(stream->seek(0, SeekMode::SetPosition)); } - return LoaderError { "No loader plugin available" }; + return Error::from_string_literal("No loader plugin available"); } -LoaderSamples Loader::get_more_samples(size_t samples_to_read_from_input) +ErrorOr Loader::get_more_samples(size_t samples_to_read_from_input) { if (m_plugin_at_end_of_stream && m_buffer.is_empty()) - return FixedArray {}; + return Samples {}; 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)); + auto samples = TRY(Samples::create(samples_to_read)); size_t sample_index = 0; diff --git a/Libraries/LibMedia/Audio/Loader.h b/Libraries/LibMedia/Audio/Loader.h index 04093787dd6..8d16713e40e 100644 --- a/Libraries/LibMedia/Audio/Loader.h +++ b/Libraries/LibMedia/Audio/Loader.h @@ -6,9 +6,9 @@ #pragma once -#include "LoaderError.h" #include "Sample.h" #include "SampleFormats.h" +#include #include #include #include @@ -33,8 +33,7 @@ constexpr u64 const maximum_seekpoint_distance_ms = 1000; // That means: The actual achieved seek position must not be more than this amount of time before the requested seek position. constexpr u64 const seek_tolerance_ms = 5000; -using LoaderSamples = ErrorOr, LoaderError>; -using MaybeLoaderError = ErrorOr; +using Samples = FixedArray; class LoaderPlugin { public: @@ -47,11 +46,11 @@ public: // The chunks are returned in a vector, so the loader can simply add chunks until the requested sample amount is reached. // The sample count MAY be surpassed, but only as little as possible. It CAN be undershot when the end of the stream is reached. // If the loader has no chunking limitations (e.g. WAV), it may return a single exact-sized chunk. - virtual ErrorOr>, LoaderError> load_chunks(size_t samples_to_read_from_input) = 0; + virtual ErrorOr>> load_chunks(size_t samples_to_read_from_input) = 0; - virtual MaybeLoaderError reset() = 0; + virtual ErrorOr reset() = 0; - virtual MaybeLoaderError seek(int const sample_index) = 0; + virtual ErrorOr seek(int const sample_index) = 0; // total_samples() and loaded_samples() should be independent // of the number of channels. @@ -75,18 +74,18 @@ protected: class Loader : public RefCounted { public: - static ErrorOr, LoaderError> create(StringView path); - static ErrorOr, LoaderError> create(ReadonlyBytes buffer); + static ErrorOr> create(StringView path); + static ErrorOr> create(ReadonlyBytes buffer); // 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); + ErrorOr get_more_samples(size_t samples_to_read_from_input = 128 * KiB); - MaybeLoaderError reset() const + ErrorOr reset() const { m_plugin_at_end_of_stream = false; return m_plugin->reset(); } - MaybeLoaderError seek(int const position) const + ErrorOr seek(int const position) const { m_buffer.clear_with_capacity(); m_plugin_at_end_of_stream = false; @@ -102,7 +101,7 @@ public: PcmSampleFormat pcm_format() const { return m_plugin->pcm_format(); } private: - static ErrorOr, LoaderError> create_plugin(NonnullOwnPtr stream); + static ErrorOr> create_plugin(NonnullOwnPtr stream); explicit Loader(NonnullOwnPtr); diff --git a/Libraries/LibMedia/Audio/LoaderError.h b/Libraries/LibMedia/Audio/LoaderError.h deleted file mode 100644 index 252fe7a3cc6..00000000000 --- a/Libraries/LibMedia/Audio/LoaderError.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (c) 2021, kleines Filmröllchen . - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include -#include -#include - -namespace Audio { - -struct LoaderError { - - enum class Category : u32 { - // The error category is unknown. - Unknown = 0, - IO, - // The read file doesn't follow the file format. - Format, - // Equivalent to an ASSERT(), except non-crashing. - Internal, - // The loader encountered something in the format that is not yet implemented. - Unimplemented, - }; - Category category { Category::Unknown }; - // Binary index: where in the file the error occurred. - size_t index { 0 }; - DeprecatedFlyString description { ByteString::empty() }; - - constexpr LoaderError() = default; - LoaderError(Category category, size_t index, DeprecatedFlyString description) - : category(category) - , index(index) - , description(move(description)) - { - } - LoaderError(DeprecatedFlyString description) - : description(move(description)) - { - } - LoaderError(Category category, DeprecatedFlyString description) - : category(category) - , description(move(description)) - { - } - - LoaderError(LoaderError&) = default; - LoaderError(LoaderError&&) = default; - - LoaderError(Error&& error) - { - if (error.is_errno()) { - auto code = error.code(); - description = ByteString::formatted("{} ({})", strerror(code), code); - if (code == EBADF || code == EBUSY || code == EEXIST || code == EIO || code == EISDIR || code == ENOENT || code == ENOMEM || code == EPIPE) - category = Category::IO; - } else { - description = error.string_literal(); - } - } -}; - -} - -namespace AK { - -template<> -struct Formatter : Formatter { - ErrorOr format(FormatBuilder& builder, Audio::LoaderError const& error) - { - StringView category; - switch (error.category) { - case Audio::LoaderError::Category::Unknown: - category = "Unknown"sv; - break; - case Audio::LoaderError::Category::IO: - category = "I/O"sv; - break; - case Audio::LoaderError::Category::Format: - category = "Format"sv; - break; - case Audio::LoaderError::Category::Internal: - category = "Internal"sv; - break; - case Audio::LoaderError::Category::Unimplemented: - category = "Unimplemented"sv; - break; - } - return Formatter::format(builder, "{} error: {} (at {})"sv, category, error.description, error.index); - } -}; - -} diff --git a/Libraries/LibWeb/Platform/AudioCodecPlugin.cpp b/Libraries/LibWeb/Platform/AudioCodecPlugin.cpp index c58de962438..49c36c3468f 100644 --- a/Libraries/LibWeb/Platform/AudioCodecPlugin.cpp +++ b/Libraries/LibWeb/Platform/AudioCodecPlugin.cpp @@ -32,7 +32,7 @@ ErrorOr> AudioCodecPlugin::read_samples_from_loader(Au { auto buffer_or_error = loader.get_more_samples(samples_to_load); if (buffer_or_error.is_error()) { - dbgln("Error while loading samples: {}", buffer_or_error.error().description); + dbgln("Error while loading samples: {}", buffer_or_error.error()); return Error::from_string_literal("Error while loading samples"); } diff --git a/Utilities/abench.cpp b/Utilities/abench.cpp index bc4ab9c4ddc..1b41dc08977 100644 --- a/Utilities/abench.cpp +++ b/Utilities/abench.cpp @@ -29,7 +29,7 @@ ErrorOr serenity_main(Main::Arguments args) auto maybe_loader = Audio::Loader::create(path); if (maybe_loader.is_error()) { - warnln("Failed to load audio file: {}", maybe_loader.error().description); + warnln("Failed to load audio file: {}", maybe_loader.error()); return 1; } auto loader = maybe_loader.release_value(); @@ -50,7 +50,7 @@ ErrorOr serenity_main(Main::Arguments args) if (samples.value().size() == 0) break; } else { - warnln("Error while loading audio: {}", samples.error().description); + warnln("Error while loading audio: {}", samples.error()); return 1; } } else