LibMedia: Make Demuxer atomically ref-counted

We'll need to share the demuxer between multiple decoder providers, and
those will hold references to the demuxer from their own decoder
threads.
This commit is contained in:
Zaggy1024 2025-09-09 12:58:30 -05:00 committed by Jelle Raaijmakers
parent 27742ef26d
commit 523e7e2ffa
7 changed files with 21 additions and 20 deletions

View File

@ -13,19 +13,19 @@
namespace Media::Matroska {
DecoderErrorOr<NonnullOwnPtr<MatroskaDemuxer>> MatroskaDemuxer::from_file(StringView filename)
DecoderErrorOr<NonnullRefPtr<MatroskaDemuxer>> MatroskaDemuxer::from_file(StringView filename)
{
return make<MatroskaDemuxer>(TRY(Reader::from_file(filename)));
return make_ref_counted<MatroskaDemuxer>(TRY(Reader::from_file(filename)));
}
DecoderErrorOr<NonnullOwnPtr<MatroskaDemuxer>> MatroskaDemuxer::from_mapped_file(NonnullOwnPtr<Core::MappedFile> mapped_file)
DecoderErrorOr<NonnullRefPtr<MatroskaDemuxer>> MatroskaDemuxer::from_mapped_file(NonnullOwnPtr<Core::MappedFile> mapped_file)
{
return make<MatroskaDemuxer>(TRY(Reader::from_mapped_file(move(mapped_file))));
return make_ref_counted<MatroskaDemuxer>(TRY(Reader::from_mapped_file(move(mapped_file))));
}
DecoderErrorOr<NonnullOwnPtr<MatroskaDemuxer>> MatroskaDemuxer::from_data(ReadonlyBytes data)
DecoderErrorOr<NonnullRefPtr<MatroskaDemuxer>> MatroskaDemuxer::from_data(ReadonlyBytes data)
{
return make<MatroskaDemuxer>(TRY(Reader::from_data(data)));
return make_ref_counted<MatroskaDemuxer>(TRY(Reader::from_data(data)));
}
static TrackEntry::TrackType matroska_track_type_from_track_type(TrackType type)

View File

@ -17,10 +17,10 @@ class MatroskaDemuxer final : public Demuxer {
public:
// FIXME: We should instead accept some abstract data streaming type so that the demuxer
// can work with non-contiguous data.
static DecoderErrorOr<NonnullOwnPtr<MatroskaDemuxer>> from_file(StringView filename);
static DecoderErrorOr<NonnullOwnPtr<MatroskaDemuxer>> from_mapped_file(NonnullOwnPtr<Core::MappedFile> mapped_file);
static DecoderErrorOr<NonnullRefPtr<MatroskaDemuxer>> from_file(StringView filename);
static DecoderErrorOr<NonnullRefPtr<MatroskaDemuxer>> from_mapped_file(NonnullOwnPtr<Core::MappedFile> mapped_file);
static DecoderErrorOr<NonnullOwnPtr<MatroskaDemuxer>> from_data(ReadonlyBytes data);
static DecoderErrorOr<NonnullRefPtr<MatroskaDemuxer>> from_data(ReadonlyBytes data);
MatroskaDemuxer(Reader&& reader)
: m_reader(move(reader))

View File

@ -1,11 +1,12 @@
/*
* Copyright (c) 2022, Gregory Bertilson <zaggy1024@gmail.com>
* Copyright (c) 2022-2025, Gregory Bertilson <gregory@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/AtomicRefCounted.h>
#include <AK/NonnullOwnPtr.h>
#include <LibCore/EventReceiver.h>
@ -16,7 +17,7 @@
namespace Media {
class Demuxer {
class Demuxer : public AtomicRefCounted<Demuxer> {
public:
virtual ~Demuxer() = default;

View File

@ -28,10 +28,10 @@ FFmpegDemuxer::~FFmpegDemuxer()
avformat_close_input(&m_format_context);
}
ErrorOr<NonnullOwnPtr<FFmpegDemuxer>> FFmpegDemuxer::create(NonnullOwnPtr<SeekableStream> stream)
ErrorOr<NonnullRefPtr<FFmpegDemuxer>> FFmpegDemuxer::create(NonnullOwnPtr<SeekableStream> stream)
{
auto io_context = TRY(Media::FFmpeg::FFmpegIOContext::create(*stream));
auto demuxer = make<FFmpegDemuxer>(move(stream), move(io_context));
auto demuxer = make_ref_counted<FFmpegDemuxer>(move(stream), move(io_context));
// Open the container
demuxer->m_format_context = avformat_alloc_context();

View File

@ -20,7 +20,7 @@ namespace Media::FFmpeg {
class FFmpegDemuxer : public Demuxer {
public:
static ErrorOr<NonnullOwnPtr<FFmpegDemuxer>> create(NonnullOwnPtr<SeekableStream> stream);
static ErrorOr<NonnullRefPtr<FFmpegDemuxer>> create(NonnullOwnPtr<SeekableStream> stream);
FFmpegDemuxer(NonnullOwnPtr<SeekableStream> stream, NonnullOwnPtr<Media::FFmpeg::FFmpegIOContext>);
virtual ~FFmpegDemuxer() override;

View File

@ -41,8 +41,8 @@ DecoderErrorOr<NonnullOwnPtr<PlaybackManager>> PlaybackManager::from_stream(Nonn
return create(demuxer_or_error.release_value());
}
PlaybackManager::PlaybackManager(NonnullOwnPtr<Demuxer>& demuxer, Track video_track, NonnullOwnPtr<VideoDecoder>&& decoder, VideoFrameQueue&& frame_queue)
: m_demuxer(move(demuxer))
PlaybackManager::PlaybackManager(NonnullRefPtr<Demuxer> const& demuxer, Track video_track, NonnullOwnPtr<VideoDecoder>&& decoder, VideoFrameQueue&& frame_queue)
: m_demuxer(demuxer)
, m_selected_video_track(video_track)
, m_frame_queue(move(frame_queue))
, m_decoder(move(decoder))
@ -696,7 +696,7 @@ private:
PlaybackState get_state() const override { return PlaybackState::Stopped; }
};
DecoderErrorOr<NonnullOwnPtr<PlaybackManager>> PlaybackManager::create(NonnullOwnPtr<Demuxer> demuxer)
DecoderErrorOr<NonnullOwnPtr<PlaybackManager>> PlaybackManager::create(NonnullRefPtr<Demuxer> const& demuxer)
{
auto optional_track = TRY(demuxer->get_preferred_track_for_type(TrackType::Video));
if (!optional_track.has_value()) {

View File

@ -114,7 +114,7 @@ public:
static DecoderErrorOr<NonnullOwnPtr<PlaybackManager>> from_data(ReadonlyBytes data);
static DecoderErrorOr<NonnullOwnPtr<PlaybackManager>> from_stream(NonnullOwnPtr<SeekableStream> stream);
PlaybackManager(NonnullOwnPtr<Demuxer>& demuxer, Track video_track, NonnullOwnPtr<VideoDecoder>&& decoder, VideoFrameQueue&& frame_queue);
PlaybackManager(NonnullRefPtr<Demuxer> const& demuxer, Track video_track, NonnullOwnPtr<VideoDecoder>&& decoder, VideoFrameQueue&& frame_queue);
~PlaybackManager();
void resume_playback();
@ -153,7 +153,7 @@ private:
class SeekingStateHandler;
class StoppedStateHandler;
static DecoderErrorOr<NonnullOwnPtr<PlaybackManager>> create(NonnullOwnPtr<Demuxer> demuxer);
static DecoderErrorOr<NonnullOwnPtr<PlaybackManager>> create(NonnullRefPtr<Demuxer> const& demuxer);
void timer_callback();
// This must be called with m_demuxer_mutex locked!
@ -173,7 +173,7 @@ private:
AK::Duration m_last_present_in_media_time = AK::Duration::zero();
NonnullOwnPtr<Demuxer> m_demuxer;
NonnullRefPtr<Demuxer> m_demuxer;
Threading::Mutex m_decoder_mutex;
Track m_selected_video_track;