LibMedia: Use direct references to main event loops
Pass direct Core::EventLoop references through media producer and playback plumbing that posts work back to the main thread. The browser process main loops stay alive for the process lifetime, so these paths no longer need weak event loop references. Update LibMedia tests to pass their stack event loop directly to the producer helpers.
This commit is contained in:
parent
b51fde39a2
commit
aad293dacc
11 changed files with 55 additions and 72 deletions
|
|
@ -12,21 +12,18 @@
|
|||
|
||||
namespace Audio {
|
||||
|
||||
#define TRY_OR_REJECT_AND_EXIT(expression) \
|
||||
({ \
|
||||
auto&& __temporary_result = (expression); \
|
||||
if (__temporary_result.is_error()) [[unlikely]] { \
|
||||
warnln("Failure in PulseAudio control thread: {}", __temporary_result.error().string_literal()); \
|
||||
auto event_loop = main_thread_event_loop->take(); \
|
||||
if (!event_loop) \
|
||||
return 1; \
|
||||
event_loop->deferred_invoke([promise = move(promise), error = __temporary_result.release_error()] mutable { \
|
||||
promise->reject(move(error)); \
|
||||
}); \
|
||||
internal_state->exit(); \
|
||||
return 1; \
|
||||
} \
|
||||
__temporary_result.release_value(); \
|
||||
#define TRY_OR_REJECT_AND_EXIT(expression) \
|
||||
({ \
|
||||
auto&& __temporary_result = (expression); \
|
||||
if (__temporary_result.is_error()) [[unlikely]] { \
|
||||
warnln("Failure in PulseAudio control thread: {}", __temporary_result.error().string_literal()); \
|
||||
main_thread_event_loop.deferred_invoke([promise = move(promise), error = __temporary_result.release_error()] mutable { \
|
||||
promise->reject(move(error)); \
|
||||
}); \
|
||||
internal_state->exit(); \
|
||||
return 1; \
|
||||
} \
|
||||
__temporary_result.release_value(); \
|
||||
})
|
||||
|
||||
NonnullRefPtr<PlaybackStream::CreatePromise> PlaybackStream::create(OutputState initial_output_state, u32 target_latency_ms, AudioDataRequestCallback&& data_request_callback)
|
||||
|
|
@ -43,9 +40,10 @@ NonnullRefPtr<PlaybackStream::CreatePromise> PlaybackStreamPulseAudio::create(Ou
|
|||
// Create an internal state for the control thread to hold on to.
|
||||
auto internal_state = MUST(adopt_nonnull_ref_or_enomem(new (nothrow) InternalState()));
|
||||
auto playback_stream = MUST(adopt_nonnull_ref_or_enomem(new (nothrow) PlaybackStreamPulseAudio(internal_state)));
|
||||
auto& main_thread_event_loop = Core::EventLoop::current();
|
||||
|
||||
// Create the control thread and start it.
|
||||
auto thread = MUST(Threading::Thread::try_create("Audio Control"sv, [=, main_thread_event_loop = Core::EventLoop::current_weak(), data_request_callback = move(data_request_callback)]() mutable {
|
||||
auto thread = MUST(Threading::Thread::try_create("Audio Control"sv, [=, &main_thread_event_loop, data_request_callback = move(data_request_callback)]() mutable {
|
||||
auto context = TRY_OR_REJECT_AND_EXIT(PulseAudioContext::the());
|
||||
internal_state->set_stream(TRY_OR_REJECT_AND_EXIT(context->create_stream(initial_state, target_latency_ms, [data_request_callback = move(data_request_callback)](PulseAudioStream&, Span<float> buffer) {
|
||||
return data_request_callback(buffer);
|
||||
|
|
@ -56,10 +54,7 @@ NonnullRefPtr<PlaybackStream::CreatePromise> PlaybackStreamPulseAudio::create(Ou
|
|||
TRY_OR_REJECT_AND_EXIT(internal_state->stream()->set_volume(1.0));
|
||||
|
||||
{
|
||||
auto event_loop = main_thread_event_loop->take();
|
||||
if (!event_loop)
|
||||
return 1;
|
||||
event_loop->deferred_invoke([promise = move(promise), playback_stream = move(playback_stream)] mutable {
|
||||
main_thread_event_loop.deferred_invoke([promise = move(promise), playback_stream = move(playback_stream)] mutable {
|
||||
promise->resolve(move(playback_stream));
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ DecoderErrorOr<NonnullRefPtr<Demuxer>> PlaybackManager::create_demuxer_for_strea
|
|||
return FFmpeg::FFmpegDemuxer::from_stream(stream);
|
||||
}
|
||||
|
||||
DecoderErrorOr<void> PlaybackManager::prepare_playback_from_demuxer(WeakPlaybackManager const& self, NonnullRefPtr<Demuxer> const& demuxer, NonnullRefPtr<Core::WeakEventLoopReference> const& main_thread_event_loop_reference)
|
||||
DecoderErrorOr<void> PlaybackManager::prepare_playback_from_demuxer(WeakPlaybackManager const& self, NonnullRefPtr<Demuxer> const& demuxer, Core::EventLoop& main_thread_event_loop)
|
||||
{
|
||||
// Create the video tracks and their producers.
|
||||
auto all_video_tracks = TRY(demuxer->get_tracks_for_type(TrackType::Video));
|
||||
|
|
@ -39,7 +39,7 @@ DecoderErrorOr<void> PlaybackManager::prepare_playback_from_demuxer(WeakPlayback
|
|||
supported_video_tracks.ensure_capacity(all_video_tracks.size());
|
||||
supported_video_track_datas.ensure_capacity(all_video_tracks.size());
|
||||
for (auto const& track : all_video_tracks) {
|
||||
auto video_producer_result = DecodedVideoProducer::try_create(main_thread_event_loop_reference, demuxer, track);
|
||||
auto video_producer_result = DecodedVideoProducer::try_create(main_thread_event_loop, demuxer, track);
|
||||
if (video_producer_result.is_error())
|
||||
continue;
|
||||
supported_video_tracks.append(track);
|
||||
|
|
@ -56,7 +56,7 @@ DecoderErrorOr<void> PlaybackManager::prepare_playback_from_demuxer(WeakPlayback
|
|||
supported_audio_tracks.ensure_capacity(all_audio_tracks.size());
|
||||
supported_audio_track_datas.ensure_capacity(all_audio_tracks.size());
|
||||
for (auto const& track : all_audio_tracks) {
|
||||
auto audio_producer_result = DecodedAudioProducer::try_create(main_thread_event_loop_reference, demuxer, track);
|
||||
auto audio_producer_result = DecodedAudioProducer::try_create(main_thread_event_loop, demuxer, track);
|
||||
if (audio_producer_result.is_error())
|
||||
continue;
|
||||
auto audio_producer = audio_producer_result.release_value();
|
||||
|
|
@ -79,8 +79,7 @@ DecoderErrorOr<void> PlaybackManager::prepare_playback_from_demuxer(WeakPlayback
|
|||
auto duration = demuxer->total_duration().value_or(AK::Duration::zero());
|
||||
auto start_time_realtime = demuxer->start_time_realtime();
|
||||
|
||||
auto main_thread_event_loop = main_thread_event_loop_reference->take();
|
||||
main_thread_event_loop->deferred_invoke([self, video_tracks = move(supported_video_tracks), video_track_datas = move(supported_video_track_datas), preferred_video_track, audio_tracks = move(supported_audio_tracks), audio_track_datas = move(supported_audio_track_datas), preferred_audio_track, duration, start_time_realtime] mutable {
|
||||
main_thread_event_loop.deferred_invoke([self, video_tracks = move(supported_video_tracks), video_track_datas = move(supported_video_track_datas), preferred_video_track, audio_tracks = move(supported_audio_tracks), audio_track_datas = move(supported_audio_track_datas), preferred_audio_track, duration, start_time_realtime] mutable {
|
||||
if (!self)
|
||||
return;
|
||||
|
||||
|
|
@ -167,12 +166,9 @@ PlaybackManager::~PlaybackManager()
|
|||
m_weak_link->revoke({});
|
||||
}
|
||||
|
||||
static void handle_media_init_error(WeakPlaybackManager self, NonnullRefPtr<Core::WeakEventLoopReference> const& main_thread_event_loop_reference, DecoderError error)
|
||||
static void handle_media_init_error(WeakPlaybackManager self, Core::EventLoop& main_thread_event_loop, DecoderError error)
|
||||
{
|
||||
auto main_thread_event_loop = main_thread_event_loop_reference->take();
|
||||
if (!main_thread_event_loop)
|
||||
return;
|
||||
main_thread_event_loop->deferred_invoke([self = move(self), error = move(error)] mutable {
|
||||
main_thread_event_loop.deferred_invoke([self = move(self), error = move(error)] mutable {
|
||||
if (!self)
|
||||
return;
|
||||
if (self->on_unsupported_format_error)
|
||||
|
|
@ -183,30 +179,30 @@ static void handle_media_init_error(WeakPlaybackManager self, NonnullRefPtr<Core
|
|||
void PlaybackManager::add_media_source(NonnullRefPtr<MediaStream> const& stream)
|
||||
{
|
||||
auto self = weak();
|
||||
auto main_thread_event_loop_reference = Core::EventLoop::current_weak();
|
||||
auto& main_thread_event_loop = Core::EventLoop::current();
|
||||
|
||||
Threading::ThreadPool::the().submit([self = move(self), stream, main_thread_event_loop_reference = move(main_thread_event_loop_reference)] mutable {
|
||||
Threading::ThreadPool::the().submit([self = move(self), stream, &main_thread_event_loop] mutable {
|
||||
auto demuxer_or_error = create_demuxer_for_stream(stream);
|
||||
if (demuxer_or_error.is_error()) {
|
||||
handle_media_init_error(move(self), move(main_thread_event_loop_reference), demuxer_or_error.release_error());
|
||||
handle_media_init_error(move(self), main_thread_event_loop, demuxer_or_error.release_error());
|
||||
return;
|
||||
}
|
||||
|
||||
auto maybe_error = prepare_playback_from_demuxer(self, demuxer_or_error.release_value(), main_thread_event_loop_reference);
|
||||
auto maybe_error = prepare_playback_from_demuxer(self, demuxer_or_error.release_value(), main_thread_event_loop);
|
||||
if (maybe_error.is_error())
|
||||
handle_media_init_error(move(self), move(main_thread_event_loop_reference), maybe_error.release_error());
|
||||
handle_media_init_error(move(self), main_thread_event_loop, maybe_error.release_error());
|
||||
});
|
||||
}
|
||||
|
||||
void PlaybackManager::add_media_source(NonnullRefPtr<Demuxer> const& demuxer)
|
||||
{
|
||||
auto self = weak();
|
||||
auto main_thread_event_loop_reference = Core::EventLoop::current_weak();
|
||||
auto& main_thread_event_loop = Core::EventLoop::current();
|
||||
|
||||
Threading::ThreadPool::the().submit([self = move(self), demuxer, main_thread_event_loop_reference = move(main_thread_event_loop_reference)] mutable {
|
||||
auto maybe_error = prepare_playback_from_demuxer(self, demuxer, main_thread_event_loop_reference);
|
||||
Threading::ThreadPool::the().submit([self = move(self), demuxer, &main_thread_event_loop] mutable {
|
||||
auto maybe_error = prepare_playback_from_demuxer(self, demuxer, main_thread_event_loop);
|
||||
if (maybe_error.is_error())
|
||||
handle_media_init_error(move(self), move(main_thread_event_loop_reference), maybe_error.release_error());
|
||||
handle_media_init_error(move(self), main_thread_event_loop, maybe_error.release_error());
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -151,7 +151,7 @@ private:
|
|||
}
|
||||
|
||||
static DecoderErrorOr<NonnullRefPtr<Demuxer>> create_demuxer_for_stream(NonnullRefPtr<MediaStream> const&);
|
||||
static DecoderErrorOr<void> prepare_playback_from_demuxer(WeakPlaybackManager const&, NonnullRefPtr<Demuxer> const&, NonnullRefPtr<Core::WeakEventLoopReference> const&);
|
||||
static DecoderErrorOr<void> prepare_playback_from_demuxer(WeakPlaybackManager const&, NonnullRefPtr<Demuxer> const&, Core::EventLoop&);
|
||||
|
||||
template<typename T, typename... Args>
|
||||
void replace_state_handler(Args&&... args);
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ namespace Media {
|
|||
|
||||
static constexpr int AUTO_SUSPEND_IDLE_TIMEOUT_MS = 10000;
|
||||
|
||||
DecoderErrorOr<NonnullRefPtr<DecodedAudioProducer>> DecodedAudioProducer::try_create(NonnullRefPtr<Core::WeakEventLoopReference> const& main_thread_event_loop, NonnullRefPtr<Demuxer> const& demuxer, Track const& track)
|
||||
DecoderErrorOr<NonnullRefPtr<DecodedAudioProducer>> DecodedAudioProducer::try_create(Core::EventLoop& main_thread_event_loop, NonnullRefPtr<Demuxer> const& demuxer, Track const& track)
|
||||
{
|
||||
auto converter = DECODER_TRY_ALLOC(FFmpeg::FFmpegAudioConverter::try_create());
|
||||
|
||||
|
|
@ -96,7 +96,7 @@ TimeRanges DecodedAudioProducer::buffered_time_ranges() const
|
|||
return m_thread_data->buffered_time_ranges();
|
||||
}
|
||||
|
||||
DecodedAudioProducer::ThreadData::ThreadData(NonnullRefPtr<Core::WeakEventLoopReference> const& main_thread_event_loop, NonnullRefPtr<Demuxer> const& demuxer, Track const& track, AK::Duration duration, NonnullOwnPtr<Audio::AudioConverter>&& converter)
|
||||
DecodedAudioProducer::ThreadData::ThreadData(Core::EventLoop& main_thread_event_loop, NonnullRefPtr<Demuxer> const& demuxer, Track const& track, AK::Duration duration, NonnullOwnPtr<Audio::AudioConverter>&& converter)
|
||||
: m_main_thread_event_loop(main_thread_event_loop)
|
||||
, m_demuxer(demuxer)
|
||||
, m_track(track)
|
||||
|
|
@ -336,10 +336,7 @@ void DecodedAudioProducer::ThreadData::invoke_on_main_thread_while_locked(Invoke
|
|||
{
|
||||
if (m_requested_state == RequestedState::Exit)
|
||||
return;
|
||||
auto event_loop = m_main_thread_event_loop->take();
|
||||
if (!event_loop.is_alive())
|
||||
return;
|
||||
event_loop->deferred_invoke([self = NonnullRefPtr(*this), invokee = move(invokee)] mutable {
|
||||
m_main_thread_event_loop.deferred_invoke([self = NonnullRefPtr(*this), invokee = move(invokee)] mutable {
|
||||
invokee(self);
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ public:
|
|||
using ErrorHandler = Function<void(DecoderError&&)>;
|
||||
using BlockEndTimeHandler = Function<void(AK::Duration)>;
|
||||
|
||||
static DecoderErrorOr<NonnullRefPtr<DecodedAudioProducer>> try_create(NonnullRefPtr<Core::WeakEventLoopReference> const& main_thread_event_loop, NonnullRefPtr<Demuxer> const& demuxer, Track const& track);
|
||||
static DecoderErrorOr<NonnullRefPtr<DecodedAudioProducer>> try_create(Core::EventLoop& main_thread_event_loop, NonnullRefPtr<Demuxer> const& demuxer, Track const& track);
|
||||
DecodedAudioProducer(NonnullRefPtr<ThreadData> const&);
|
||||
~DecodedAudioProducer();
|
||||
|
||||
|
|
@ -59,7 +59,7 @@ public:
|
|||
private:
|
||||
class ThreadData final : public AtomicRefCounted<ThreadData> {
|
||||
public:
|
||||
ThreadData(NonnullRefPtr<Core::WeakEventLoopReference> const& main_thread_event_loop, NonnullRefPtr<Demuxer> const&, Track const&, AK::Duration, NonnullOwnPtr<Audio::AudioConverter>&&);
|
||||
ThreadData(Core::EventLoop& main_thread_event_loop, NonnullRefPtr<Demuxer> const&, Track const&, AK::Duration, NonnullOwnPtr<Audio::AudioConverter>&&);
|
||||
~ThreadData();
|
||||
|
||||
void set_error_handler(ErrorHandler&&);
|
||||
|
|
@ -115,7 +115,7 @@ private:
|
|||
void note_consumer_activity_while_locked() const;
|
||||
void wait_for_queue_space_or_auto_suspend_while_locked();
|
||||
|
||||
NonnullRefPtr<Core::WeakEventLoopReference> m_main_thread_event_loop;
|
||||
Core::EventLoop& m_main_thread_event_loop;
|
||||
|
||||
mutable Sync::Mutex m_mutex;
|
||||
mutable Sync::ConditionVariable m_wait_condition { m_mutex };
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ namespace Media {
|
|||
|
||||
static constexpr int AUTO_SUSPEND_IDLE_TIMEOUT_MS = 10000;
|
||||
|
||||
DecoderErrorOr<NonnullRefPtr<DecodedVideoProducer>> DecodedVideoProducer::try_create(NonnullRefPtr<Core::WeakEventLoopReference> const& main_thread_event_loop, NonnullRefPtr<Demuxer> const& demuxer, Track const& track)
|
||||
DecoderErrorOr<NonnullRefPtr<DecodedVideoProducer>> DecodedVideoProducer::try_create(Core::EventLoop& main_thread_event_loop, NonnullRefPtr<Demuxer> const& demuxer, Track const& track)
|
||||
{
|
||||
TRY(demuxer->create_context_for_track(track));
|
||||
auto duration = TRY(demuxer->duration_of_track(track));
|
||||
|
|
@ -169,7 +169,7 @@ void DecodedVideoProducer::seek(AK::Duration timestamp)
|
|||
m_thread_data->seek(timestamp);
|
||||
}
|
||||
|
||||
DecodedVideoProducer::ThreadData::ThreadData(NonnullRefPtr<Core::WeakEventLoopReference> const& main_thread_event_loop, NonnullRefPtr<Demuxer> const& demuxer, Track const& track, AK::Duration duration)
|
||||
DecodedVideoProducer::ThreadData::ThreadData(Core::EventLoop& main_thread_event_loop, NonnullRefPtr<Demuxer> const& demuxer, Track const& track, AK::Duration duration)
|
||||
: m_main_thread_event_loop(main_thread_event_loop)
|
||||
, m_demuxer(demuxer)
|
||||
, m_track(track)
|
||||
|
|
@ -302,10 +302,7 @@ void DecodedVideoProducer::ThreadData::invoke_on_main_thread_while_locked(Invoke
|
|||
{
|
||||
if (m_requested_state == RequestedState::Exit)
|
||||
return;
|
||||
auto event_loop = m_main_thread_event_loop->take();
|
||||
if (!event_loop.is_alive())
|
||||
return;
|
||||
event_loop->deferred_invoke([self = NonnullRefPtr(*this), invokee = move(invokee)] mutable {
|
||||
m_main_thread_event_loop.deferred_invoke([self = NonnullRefPtr(*this), invokee = move(invokee)] mutable {
|
||||
invokee(self);
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ public:
|
|||
using ErrorHandler = Function<void(DecoderError&&)>;
|
||||
using FrameEndTimeHandler = Function<void(AK::Duration)>;
|
||||
|
||||
static DecoderErrorOr<NonnullRefPtr<DecodedVideoProducer>> try_create(NonnullRefPtr<Core::WeakEventLoopReference> const& main_thread_event_loop, NonnullRefPtr<Demuxer> const&, Track const&);
|
||||
static DecoderErrorOr<NonnullRefPtr<DecodedVideoProducer>> try_create(Core::EventLoop& main_thread_event_loop, NonnullRefPtr<Demuxer> const&, Track const&);
|
||||
|
||||
DecodedVideoProducer(NonnullRefPtr<ThreadData> const&);
|
||||
~DecodedVideoProducer();
|
||||
|
|
@ -60,7 +60,7 @@ public:
|
|||
private:
|
||||
class ThreadData final : public AtomicRefCounted<ThreadData> {
|
||||
public:
|
||||
ThreadData(NonnullRefPtr<Core::WeakEventLoopReference> const& main_thread_event_loop, NonnullRefPtr<Demuxer> const&, Track const&, AK::Duration);
|
||||
ThreadData(Core::EventLoop& main_thread_event_loop, NonnullRefPtr<Demuxer> const&, Track const&, AK::Duration);
|
||||
~ThreadData();
|
||||
|
||||
void set_error_handler(ErrorHandler&&);
|
||||
|
|
@ -114,7 +114,7 @@ private:
|
|||
void note_consumer_activity_while_locked() const;
|
||||
void wait_for_queue_space_or_auto_suspend_while_locked();
|
||||
|
||||
NonnullRefPtr<Core::WeakEventLoopReference> m_main_thread_event_loop;
|
||||
Core::EventLoop& m_main_thread_event_loop;
|
||||
|
||||
mutable Sync::Mutex m_mutex;
|
||||
mutable Sync::ConditionVariable m_wait_condition { m_mutex };
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ static constexpr size_t OUTPUT_BLOCK_QUEUE_CAPACITY = 4;
|
|||
class AudioPlaybackSink::OutputThreadData : public AtomicRefCounted<OutputThreadData> {
|
||||
public:
|
||||
OutputThreadData(PipelineStateChangeHandler on_state_changed)
|
||||
: m_main_thread_event_loop(Core::EventLoop::current_weak())
|
||||
: m_main_thread_event_loop(Core::EventLoop::current())
|
||||
, m_on_state_changed(move(on_state_changed))
|
||||
{
|
||||
}
|
||||
|
|
@ -36,7 +36,7 @@ public:
|
|||
|
||||
RefPtr<Audio::PlaybackStream> m_playback_stream;
|
||||
RefPtr<AudioProducer> m_input;
|
||||
NonnullRefPtr<Core::WeakEventLoopReference> m_main_thread_event_loop;
|
||||
Core::EventLoop& m_main_thread_event_loop;
|
||||
|
||||
mutable Sync::Mutex m_output_mutex;
|
||||
mutable Sync::ConditionVariable m_output_condition { m_output_mutex };
|
||||
|
|
@ -332,15 +332,13 @@ void AudioPlaybackSink::OutputThreadData::dispatch_state_if_changed(PipelineStat
|
|||
if (status == m_last_dispatched_status)
|
||||
return;
|
||||
m_last_dispatched_status = status;
|
||||
if (auto event_loop = m_main_thread_event_loop->take(); event_loop.is_alive()) {
|
||||
event_loop->deferred_invoke([self = NonnullRefPtr(*this), status, seek_id] {
|
||||
Sync::MutexLocker locker { self->m_output_mutex };
|
||||
if (self->m_seek_id != seek_id)
|
||||
return;
|
||||
if (self->m_on_state_changed)
|
||||
self->m_on_state_changed(status);
|
||||
});
|
||||
}
|
||||
m_main_thread_event_loop.deferred_invoke([self = NonnullRefPtr(*this), status, seek_id] {
|
||||
Sync::MutexLocker locker { self->m_output_mutex };
|
||||
if (self->m_seek_id != seek_id)
|
||||
return;
|
||||
if (self->m_on_state_changed)
|
||||
self->m_on_state_changed(status);
|
||||
});
|
||||
}
|
||||
|
||||
AK::Duration AudioPlaybackSink::current_time() const
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ TEST_CASE(audio_producer_underspecified_5_1_channel_map)
|
|||
auto tracks = TRY_OR_FAIL(demuxer->get_tracks_for_type(Media::TrackType::Audio));
|
||||
VERIFY(!tracks.is_empty());
|
||||
|
||||
auto producer = TRY_OR_FAIL(Media::DecodedAudioProducer::try_create(Core::EventLoop::current_weak(), demuxer, tracks[0]));
|
||||
auto producer = TRY_OR_FAIL(Media::DecodedAudioProducer::try_create(loop, demuxer, tracks[0]));
|
||||
|
||||
producer->start();
|
||||
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ static void decode_and_expect()
|
|||
|
||||
auto tracks = TRY_OR_FAIL(demuxer->get_tracks_for_type(Media::TrackType::Audio));
|
||||
VERIFY(!tracks.is_empty());
|
||||
auto producer = TRY_OR_FAIL(Media::DecodedAudioProducer::try_create(Core::EventLoop::current_weak(), demuxer, tracks[0]));
|
||||
auto producer = TRY_OR_FAIL(Media::DecodedAudioProducer::try_create(loop, demuxer, tracks[0]));
|
||||
|
||||
producer->set_error_handler([&](Media::DecoderError&&) {
|
||||
FAIL("An error occurred while decoding generated WAV data.");
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ static inline void decode_audio(StringView path, u32 sample_rate, u8 channel_cou
|
|||
}());
|
||||
auto tracks = TRY_OR_FAIL(demuxer->get_tracks_for_type(Media::TrackType::Audio));
|
||||
VERIFY(!tracks.is_empty());
|
||||
auto producer = TRY_OR_FAIL(Media::DecodedAudioProducer::try_create(Core::EventLoop::current_weak(), demuxer, tracks[0]));
|
||||
auto producer = TRY_OR_FAIL(Media::DecodedAudioProducer::try_create(loop, demuxer, tracks[0]));
|
||||
|
||||
producer->set_error_handler([&](Media::DecoderError&&) {
|
||||
FAIL("An error occurred while decoding.");
|
||||
|
|
|
|||
Loading…
Reference in a new issue