LibMedia: Make demuxers thread-safe and remove MutexedDemuxer
This commit is contained in:
parent
4261d73781
commit
9a421ffe9f
10 changed files with 18 additions and 115 deletions
|
|
@ -86,6 +86,7 @@ static Track track_from_track_entry(TrackEntry const& track_entry)
|
|||
DecoderErrorOr<void> MatroskaDemuxer::create_context_for_track(Track const& track, NonnullRefPtr<IncrementallyPopulatedStream::Cursor> const& stream_cursor)
|
||||
{
|
||||
auto iterator = TRY(m_reader.create_sample_iterator(stream_cursor, track.identifier()));
|
||||
Threading::MutexLocker locker(m_track_statuses_mutex);
|
||||
VERIFY(m_track_statuses.set(track, TrackStatus(move(iterator))) == HashSetResult::InsertedNewEntry);
|
||||
return {};
|
||||
}
|
||||
|
|
@ -116,6 +117,7 @@ DecoderErrorOr<Optional<Track>> MatroskaDemuxer::get_preferred_track_for_type(Tr
|
|||
|
||||
DecoderErrorOr<MatroskaDemuxer::TrackStatus*> MatroskaDemuxer::get_track_status(Track const& track)
|
||||
{
|
||||
Threading::MutexLocker locker(m_track_statuses_mutex);
|
||||
return &m_track_statuses.get(track).release_value();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
#include <LibMedia/Demuxer.h>
|
||||
#include <LibMedia/Export.h>
|
||||
#include <LibMedia/IncrementallyPopulatedStream.h>
|
||||
#include <LibThreading/Mutex.h>
|
||||
|
||||
#include "Reader.h"
|
||||
|
||||
|
|
@ -57,6 +58,7 @@ private:
|
|||
|
||||
Reader m_reader;
|
||||
|
||||
mutable Threading::Mutex m_track_statuses_mutex;
|
||||
HashMap<Track, TrackStatus> m_track_statuses;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ class DisplayingVideoSink;
|
|||
class FrameQueueItem;
|
||||
class IncrementallyPopulatedStream;
|
||||
class MediaTimeProvider;
|
||||
class MutexedDemuxer;
|
||||
class PlaybackManager;
|
||||
class Track;
|
||||
class VideoDataProvider;
|
||||
|
|
|
|||
|
|
@ -1,96 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2022, Gregory Bertilson <zaggy1024@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/Forward.h>
|
||||
#include <LibMedia/DecoderError.h>
|
||||
#include <LibThreading/MutexProtected.h>
|
||||
|
||||
#include "Demuxer.h"
|
||||
|
||||
namespace Media {
|
||||
|
||||
class MutexedDemuxer final : public Demuxer {
|
||||
public:
|
||||
MutexedDemuxer(NonnullRefPtr<Demuxer> demuxer)
|
||||
: m_demuxer(move(demuxer))
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~MutexedDemuxer() override
|
||||
{
|
||||
m_demuxer.with_locked([](auto& demuxer) {
|
||||
auto to_destroy = move(demuxer);
|
||||
});
|
||||
}
|
||||
|
||||
virtual DecoderErrorOr<void> create_context_for_track(Track const& track, NonnullRefPtr<IncrementallyPopulatedStream::Cursor> const& stream_cursor) override
|
||||
{
|
||||
return m_demuxer.with_locked([&](auto& demuxer) {
|
||||
return demuxer->create_context_for_track(track, stream_cursor);
|
||||
});
|
||||
}
|
||||
|
||||
virtual DecoderErrorOr<Vector<Track>> get_tracks_for_type(TrackType type) override
|
||||
{
|
||||
return m_demuxer.with_locked([&](auto& demuxer) {
|
||||
return demuxer->get_tracks_for_type(type);
|
||||
});
|
||||
}
|
||||
virtual DecoderErrorOr<Optional<Track>> get_preferred_track_for_type(TrackType type) override
|
||||
{
|
||||
return m_demuxer.with_locked([&](auto& demuxer) {
|
||||
return demuxer->get_preferred_track_for_type(type);
|
||||
});
|
||||
}
|
||||
|
||||
virtual DecoderErrorOr<CodedFrame> get_next_sample_for_track(Track const& track) override
|
||||
{
|
||||
return m_demuxer.with_locked([&](auto& demuxer) {
|
||||
return demuxer->get_next_sample_for_track(track);
|
||||
});
|
||||
}
|
||||
|
||||
virtual DecoderErrorOr<CodecID> get_codec_id_for_track(Track const& track) override
|
||||
{
|
||||
return m_demuxer.with_locked([&](auto& demuxer) {
|
||||
return demuxer->get_codec_id_for_track(track);
|
||||
});
|
||||
}
|
||||
|
||||
virtual DecoderErrorOr<ReadonlyBytes> get_codec_initialization_data_for_track(Track const& track) override
|
||||
{
|
||||
return m_demuxer.with_locked([&](auto& demuxer) {
|
||||
return demuxer->get_codec_initialization_data_for_track(track);
|
||||
});
|
||||
}
|
||||
|
||||
virtual DecoderErrorOr<DemuxerSeekResult> seek_to_most_recent_keyframe(Track const& track, AK::Duration timestamp, DemuxerSeekOptions seek_options = DemuxerSeekOptions::None) override
|
||||
{
|
||||
return m_demuxer.with_locked([&](auto& demuxer) {
|
||||
return demuxer->seek_to_most_recent_keyframe(track, timestamp, seek_options);
|
||||
});
|
||||
}
|
||||
|
||||
virtual DecoderErrorOr<AK::Duration> duration_of_track(Track const& track) override
|
||||
{
|
||||
return m_demuxer.with_locked([&](auto& demuxer) {
|
||||
return demuxer->duration_of_track(track);
|
||||
});
|
||||
}
|
||||
virtual DecoderErrorOr<AK::Duration> total_duration() override
|
||||
{
|
||||
return m_demuxer.with_locked([&](auto& demuxer) {
|
||||
return demuxer->total_duration();
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
Threading::MutexProtected<NonnullRefPtr<Demuxer>> m_demuxer;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -7,7 +7,6 @@
|
|||
#include <LibMedia/Containers/Matroska/MatroskaDemuxer.h>
|
||||
#include <LibMedia/Demuxer.h>
|
||||
#include <LibMedia/FFmpeg/FFmpegDemuxer.h>
|
||||
#include <LibMedia/MutexedDemuxer.h>
|
||||
#include <LibMedia/PlaybackStates/PausedStateHandler.h>
|
||||
#include <LibMedia/Providers/AudioDataProvider.h>
|
||||
#include <LibMedia/Providers/GenericTimeProvider.h>
|
||||
|
|
@ -24,12 +23,11 @@ namespace Media {
|
|||
|
||||
DecoderErrorOr<void> PlaybackManager::prepare_playback_from_media_data(NonnullRefPtr<IncrementallyPopulatedStream> stream, NonnullRefPtr<Core::WeakEventLoopReference> const& main_thread_event_loop_reference)
|
||||
{
|
||||
auto inner_demuxer = TRY([&] -> DecoderErrorOr<NonnullRefPtr<Demuxer>> {
|
||||
auto demuxer = TRY([&] -> DecoderErrorOr<NonnullRefPtr<Demuxer>> {
|
||||
if (Matroska::Reader::is_matroska_or_webm(stream->create_cursor()))
|
||||
return Matroska::MatroskaDemuxer::from_stream(stream->create_cursor());
|
||||
return FFmpeg::FFmpegDemuxer::from_stream(stream->create_cursor());
|
||||
}());
|
||||
auto demuxer = DECODER_TRY_ALLOC(try_make_ref_counted<MutexedDemuxer>(inner_demuxer));
|
||||
|
||||
// Create the video tracks and their data providers.
|
||||
auto all_video_tracks = TRY(demuxer->get_tracks_for_type(TrackType::Video));
|
||||
|
|
|
|||
|
|
@ -7,9 +7,9 @@
|
|||
#include <AK/Debug.h>
|
||||
#include <LibCore/EventLoop.h>
|
||||
#include <LibMedia/Audio/SampleSpecification.h>
|
||||
#include <LibMedia/Demuxer.h>
|
||||
#include <LibMedia/FFmpeg/FFmpegAudioConverter.h>
|
||||
#include <LibMedia/FFmpeg/FFmpegAudioDecoder.h>
|
||||
#include <LibMedia/MutexedDemuxer.h>
|
||||
#include <LibMedia/Sinks/AudioSink.h>
|
||||
#include <LibThreading/Mutex.h>
|
||||
#include <LibThreading/Thread.h>
|
||||
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
namespace Media {
|
||||
|
||||
DecoderErrorOr<NonnullRefPtr<AudioDataProvider>> AudioDataProvider::try_create(NonnullRefPtr<Core::WeakEventLoopReference> const& main_thread_event_loop, NonnullRefPtr<MutexedDemuxer> const& demuxer, NonnullRefPtr<IncrementallyPopulatedStream> const& stream, Track const& track)
|
||||
DecoderErrorOr<NonnullRefPtr<AudioDataProvider>> AudioDataProvider::try_create(NonnullRefPtr<Core::WeakEventLoopReference> const& main_thread_event_loop, NonnullRefPtr<Demuxer> const& demuxer, NonnullRefPtr<IncrementallyPopulatedStream> const& stream, Track const& track)
|
||||
{
|
||||
auto codec_id = TRY(demuxer->get_codec_id_for_track(track));
|
||||
auto const& sample_specification = track.audio_data().sample_specification;
|
||||
|
|
@ -80,7 +80,7 @@ void AudioDataProvider::seek(AK::Duration timestamp, SeekCompletionHandler&& com
|
|||
m_thread_data->seek(timestamp, move(completion_handler));
|
||||
}
|
||||
|
||||
AudioDataProvider::ThreadData::ThreadData(NonnullRefPtr<Core::WeakEventLoopReference> const& main_thread_event_loop, NonnullRefPtr<MutexedDemuxer> const& demuxer, NonnullRefPtr<IncrementallyPopulatedStream::Cursor> const& stream_cursor, Track const& track, NonnullOwnPtr<AudioDecoder>&& decoder, NonnullOwnPtr<Audio::AudioConverter>&& converter)
|
||||
AudioDataProvider::ThreadData::ThreadData(NonnullRefPtr<Core::WeakEventLoopReference> const& main_thread_event_loop, NonnullRefPtr<Demuxer> const& demuxer, NonnullRefPtr<IncrementallyPopulatedStream::Cursor> const& stream_cursor, Track const& track, NonnullOwnPtr<AudioDecoder>&& decoder, NonnullOwnPtr<Audio::AudioConverter>&& converter)
|
||||
: m_main_thread_event_loop(main_thread_event_loop)
|
||||
, m_demuxer(demuxer)
|
||||
, m_stream_cursor(stream_cursor)
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ public:
|
|||
using BlockEndTimeHandler = Function<void(AK::Duration)>;
|
||||
using SeekCompletionHandler = Function<void()>;
|
||||
|
||||
static DecoderErrorOr<NonnullRefPtr<AudioDataProvider>> try_create(NonnullRefPtr<Core::WeakEventLoopReference> const& main_thread_event_loop, NonnullRefPtr<MutexedDemuxer> const& demuxer, NonnullRefPtr<IncrementallyPopulatedStream> const&, Track const& track);
|
||||
static DecoderErrorOr<NonnullRefPtr<AudioDataProvider>> try_create(NonnullRefPtr<Core::WeakEventLoopReference> const& main_thread_event_loop, NonnullRefPtr<Demuxer> const& demuxer, NonnullRefPtr<IncrementallyPopulatedStream> const&, Track const& track);
|
||||
AudioDataProvider(NonnullRefPtr<ThreadData> const&);
|
||||
~AudioDataProvider();
|
||||
|
||||
|
|
@ -54,7 +54,7 @@ public:
|
|||
private:
|
||||
class ThreadData final : public AtomicRefCounted<ThreadData> {
|
||||
public:
|
||||
ThreadData(NonnullRefPtr<Core::WeakEventLoopReference> const& main_thread_event_loop, NonnullRefPtr<MutexedDemuxer> const&, NonnullRefPtr<IncrementallyPopulatedStream::Cursor> const&, Track const&, NonnullOwnPtr<AudioDecoder>&&, NonnullOwnPtr<Audio::AudioConverter>&&);
|
||||
ThreadData(NonnullRefPtr<Core::WeakEventLoopReference> const& main_thread_event_loop, NonnullRefPtr<Demuxer> const&, NonnullRefPtr<IncrementallyPopulatedStream::Cursor> const&, Track const&, NonnullOwnPtr<AudioDecoder>&&, NonnullOwnPtr<Audio::AudioConverter>&&);
|
||||
~ThreadData();
|
||||
|
||||
void set_error_handler(ErrorHandler&&);
|
||||
|
|
@ -101,7 +101,7 @@ private:
|
|||
mutable Threading::ConditionVariable m_wait_condition { m_mutex };
|
||||
RequestedState m_requested_state { RequestedState::None };
|
||||
|
||||
NonnullRefPtr<MutexedDemuxer> m_demuxer;
|
||||
NonnullRefPtr<Demuxer> m_demuxer;
|
||||
NonnullRefPtr<IncrementallyPopulatedStream::Cursor> m_stream_cursor;
|
||||
Track m_track;
|
||||
NonnullOwnPtr<AudioDecoder> m_decoder;
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@
|
|||
*/
|
||||
|
||||
#include <LibCore/EventLoop.h>
|
||||
#include <LibMedia/Demuxer.h>
|
||||
#include <LibMedia/FFmpeg/FFmpegVideoDecoder.h>
|
||||
#include <LibMedia/MutexedDemuxer.h>
|
||||
#include <LibMedia/Providers/MediaTimeProvider.h>
|
||||
#include <LibMedia/Sinks/VideoSink.h>
|
||||
#include <LibMedia/VideoDecoder.h>
|
||||
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
namespace Media {
|
||||
|
||||
DecoderErrorOr<NonnullRefPtr<VideoDataProvider>> VideoDataProvider::try_create(NonnullRefPtr<Core::WeakEventLoopReference> const& main_thread_event_loop, NonnullRefPtr<MutexedDemuxer> const& demuxer, NonnullRefPtr<IncrementallyPopulatedStream> const& stream, Track const& track, RefPtr<MediaTimeProvider> const& time_provider)
|
||||
DecoderErrorOr<NonnullRefPtr<VideoDataProvider>> VideoDataProvider::try_create(NonnullRefPtr<Core::WeakEventLoopReference> const& main_thread_event_loop, NonnullRefPtr<Demuxer> const& demuxer, NonnullRefPtr<IncrementallyPopulatedStream> const& stream, Track const& track, RefPtr<MediaTimeProvider> const& time_provider)
|
||||
{
|
||||
auto codec_id = TRY(demuxer->get_codec_id_for_track(track));
|
||||
auto codec_initialization_data = TRY(demuxer->get_codec_initialization_data_for_track(track));
|
||||
|
|
@ -88,7 +88,7 @@ void VideoDataProvider::seek(AK::Duration timestamp, SeekMode seek_mode, SeekCom
|
|||
m_thread_data->seek(timestamp, seek_mode, move(completion_handler));
|
||||
}
|
||||
|
||||
VideoDataProvider::ThreadData::ThreadData(NonnullRefPtr<Core::WeakEventLoopReference> const& main_thread_event_loop, NonnullRefPtr<MutexedDemuxer> const& demuxer, NonnullRefPtr<IncrementallyPopulatedStream::Cursor> const& stream_cursor, Track const& track, NonnullOwnPtr<VideoDecoder>&& decoder, RefPtr<MediaTimeProvider> const& time_provider)
|
||||
VideoDataProvider::ThreadData::ThreadData(NonnullRefPtr<Core::WeakEventLoopReference> const& main_thread_event_loop, NonnullRefPtr<Demuxer> const& demuxer, NonnullRefPtr<IncrementallyPopulatedStream::Cursor> const& stream_cursor, Track const& track, NonnullOwnPtr<VideoDecoder>&& decoder, RefPtr<MediaTimeProvider> const& time_provider)
|
||||
: m_main_thread_event_loop(main_thread_event_loop)
|
||||
, m_demuxer(demuxer)
|
||||
, m_stream_cursor(stream_cursor)
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ public:
|
|||
using SeekCompletionHandler = Function<void(AK::Duration)>;
|
||||
using FramesQueueIsFullHandler = Function<void()>;
|
||||
|
||||
static DecoderErrorOr<NonnullRefPtr<VideoDataProvider>> try_create(NonnullRefPtr<Core::WeakEventLoopReference> const& main_thread_event_loop, NonnullRefPtr<MutexedDemuxer> const&, NonnullRefPtr<IncrementallyPopulatedStream> const&, Track const&, RefPtr<MediaTimeProvider> const& = nullptr);
|
||||
static DecoderErrorOr<NonnullRefPtr<VideoDataProvider>> try_create(NonnullRefPtr<Core::WeakEventLoopReference> const& main_thread_event_loop, NonnullRefPtr<Demuxer> const&, NonnullRefPtr<IncrementallyPopulatedStream> const&, Track const&, RefPtr<MediaTimeProvider> const& = nullptr);
|
||||
|
||||
VideoDataProvider(NonnullRefPtr<ThreadData> const&);
|
||||
~VideoDataProvider();
|
||||
|
|
@ -58,7 +58,7 @@ public:
|
|||
private:
|
||||
class ThreadData final : public AtomicRefCounted<ThreadData> {
|
||||
public:
|
||||
ThreadData(NonnullRefPtr<Core::WeakEventLoopReference> const& main_thread_event_loop, NonnullRefPtr<MutexedDemuxer> const&, NonnullRefPtr<IncrementallyPopulatedStream::Cursor> const&, Track const&, NonnullOwnPtr<VideoDecoder>&&, RefPtr<MediaTimeProvider> const&);
|
||||
ThreadData(NonnullRefPtr<Core::WeakEventLoopReference> const& main_thread_event_loop, NonnullRefPtr<Demuxer> const&, NonnullRefPtr<IncrementallyPopulatedStream::Cursor> const&, Track const&, NonnullOwnPtr<VideoDecoder>&&, RefPtr<MediaTimeProvider> const&);
|
||||
~ThreadData();
|
||||
|
||||
void set_error_handler(ErrorHandler&&);
|
||||
|
|
@ -105,7 +105,7 @@ private:
|
|||
mutable Threading::ConditionVariable m_wait_condition { m_mutex };
|
||||
RequestedState m_requested_state { RequestedState::None };
|
||||
|
||||
NonnullRefPtr<MutexedDemuxer> m_demuxer;
|
||||
NonnullRefPtr<Demuxer> m_demuxer;
|
||||
NonnullRefPtr<IncrementallyPopulatedStream::Cursor> m_stream_cursor;
|
||||
Track m_track;
|
||||
NonnullOwnPtr<VideoDecoder> m_decoder;
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@
|
|||
#include <LibMedia/Containers/Matroska/Reader.h>
|
||||
#include <LibMedia/Demuxer.h>
|
||||
#include <LibMedia/FFmpeg/FFmpegDemuxer.h>
|
||||
#include <LibMedia/MutexedDemuxer.h>
|
||||
#include <LibMedia/Providers/AudioDataProvider.h>
|
||||
#include <LibMedia/VideoDecoder.h>
|
||||
#include <LibMedia/VideoFrame.h>
|
||||
|
|
@ -72,13 +71,12 @@ static inline void decode_audio(StringView path, u32 sample_rate, u8 channel_cou
|
|||
|
||||
auto file = MUST(Core::File::open(path, Core::File::OpenMode::Read));
|
||||
auto stream = Media::IncrementallyPopulatedStream::create_from_buffer(MUST(file->read_until_eof()));
|
||||
auto inner_demuxer = MUST([&] -> Media::DecoderErrorOr<NonnullRefPtr<Media::Demuxer>> {
|
||||
auto demuxer = MUST([&] -> Media::DecoderErrorOr<NonnullRefPtr<Media::Demuxer>> {
|
||||
auto matroska_result = Media::Matroska::MatroskaDemuxer::from_stream(stream->create_cursor());
|
||||
if (!matroska_result.is_error())
|
||||
return matroska_result.release_value();
|
||||
return Media::FFmpeg::FFmpegDemuxer::from_stream(stream->create_cursor());
|
||||
}());
|
||||
auto demuxer = make_ref_counted<Media::MutexedDemuxer>(inner_demuxer);
|
||||
auto track = TRY_OR_FAIL(demuxer->get_preferred_track_for_type(Media::TrackType::Audio));
|
||||
VERIFY(track.has_value());
|
||||
auto provider = TRY_OR_FAIL(Media::AudioDataProvider::try_create(Core::EventLoop::current_weak(), demuxer, stream, track.release_value()));
|
||||
|
|
|
|||
Loading…
Reference in a new issue