55 */
66
77#include < LibMedia/Containers/Matroska/MatroskaDemuxer.h>
8+ #include < LibMedia/Demuxer.h>
89#include < LibMedia/FFmpeg/FFmpegDemuxer.h>
910#include < LibMedia/MutexedDemuxer.h>
1011#include < LibMedia/PlaybackStates/PausedStateHandler.h>
1516#include < LibMedia/Sinks/AudioMixingSink.h>
1617#include < LibMedia/Sinks/DisplayingVideoSink.h>
1718#include < LibMedia/Track.h>
19+ #include < LibThreading/Thread.h>
1820
1921#include " PlaybackManager.h"
2022
2123namespace Media {
2224
23- DecoderErrorOr<NonnullRefPtr<PlaybackManager>> PlaybackManager::try_create (ReadonlyBytes data )
25+ DecoderErrorOr<void > PlaybackManager::prepare_playback_from_media_data (ReadonlyBytes media_data, Core::EventLoop& main_thread_event_loop )
2426{
2527 auto inner_demuxer = TRY ([&] -> DecoderErrorOr<NonnullRefPtr<Demuxer>> {
26- auto matroska_result = Matroska::MatroskaDemuxer::from_data (data );
28+ auto matroska_result = Matroska::MatroskaDemuxer::from_data (media_data );
2729 if (!matroska_result.is_error ())
2830 return matroska_result.release_value ();
29- return TRY (FFmpeg::FFmpegDemuxer::from_data (data ));
31+ return TRY (FFmpeg::FFmpegDemuxer::from_data (media_data ));
3032 }());
3133 auto demuxer = DECODER_TRY_ALLOC (try_make_ref_counted<MutexedDemuxer>(inner_demuxer));
3234
33- // Create the weak wrapper.
34- auto weak_playback_manager = DECODER_TRY_ALLOC (try_make_ref_counted<WeakPlaybackManager>());
35-
3635 // Create the video tracks and their data providers.
3736 auto all_video_tracks = TRY (demuxer->get_tracks_for_type (TrackType::Video));
3837
@@ -41,7 +40,7 @@ DecoderErrorOr<NonnullRefPtr<PlaybackManager>> PlaybackManager::try_create(Reado
4140 supported_video_tracks.ensure_capacity (all_video_tracks.size ());
4241 supported_video_track_datas.ensure_capacity (all_video_tracks.size ());
4342 for (auto const & track : all_video_tracks) {
44- auto video_data_provider_result = VideoDataProvider::try_create (demuxer, track);
43+ auto video_data_provider_result = VideoDataProvider::try_create (main_thread_event_loop, demuxer, track);
4544 if (video_data_provider_result.is_error ())
4645 continue ;
4746 supported_video_tracks.append (track);
@@ -58,7 +57,7 @@ DecoderErrorOr<NonnullRefPtr<PlaybackManager>> PlaybackManager::try_create(Reado
5857 supported_audio_tracks.ensure_capacity (all_audio_tracks.size ());
5958 supported_audio_track_datas.ensure_capacity (all_audio_tracks.size ());
6059 for (auto const & track : all_audio_tracks) {
61- auto audio_data_provider_result = AudioDataProvider::try_create (demuxer, track);
60+ auto audio_data_provider_result = AudioDataProvider::try_create (main_thread_event_loop, demuxer, track);
6261 if (audio_data_provider_result.is_error ())
6362 continue ;
6463 auto audio_data_provider = audio_data_provider_result.release_value ();
@@ -71,41 +70,86 @@ DecoderErrorOr<NonnullRefPtr<PlaybackManager>> PlaybackManager::try_create(Reado
7170 if (supported_video_tracks.is_empty () && supported_audio_tracks.is_empty ())
7271 return DecoderError::with_description (DecoderErrorCategory::NotImplemented, " No supported video or audio tracks found" sv);
7372
74- RefPtr<AudioMixingSink> audio_sink = nullptr ;
75- if (!supported_audio_tracks.is_empty ())
76- audio_sink = DECODER_TRY_ALLOC (AudioMixingSink::try_create ());
77-
78- // Create the time provider.
79- auto time_provider = DECODER_TRY_ALLOC ([&] -> ErrorOr<NonnullRefPtr<MediaTimeProvider>> {
80- if (audio_sink)
81- return TRY (try_make_ref_counted<WrapperTimeProvider<AudioMixingSink>>(*audio_sink));
82- return TRY (try_make_ref_counted<GenericTimeProvider>());
83- }());
73+ auto preferred_video_track = demuxer->get_preferred_track_for_type (TrackType::Video).value_or ({});
74+ if (preferred_video_track.has_value () && !supported_video_tracks.contains_slow (*preferred_video_track))
75+ preferred_video_track = {};
76+ auto preferred_audio_track = demuxer->get_preferred_track_for_type (TrackType::Audio).value_or ({});
77+ if (preferred_audio_track.has_value () && !supported_audio_tracks.contains_slow (*preferred_audio_track))
78+ preferred_audio_track = {};
79+
80+ auto duration = demuxer->total_duration ().value_or (AK::Duration::zero ());
81+
82+ main_thread_event_loop.deferred_invoke ([playback_manager = NonnullRefPtr { *this }, 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] mutable {
83+ playback_manager->m_video_tracks .extend (move (video_tracks));
84+ playback_manager->m_video_track_datas .extend (move (video_track_datas));
85+ playback_manager->m_audio_tracks .extend (move (audio_tracks));
86+ playback_manager->m_audio_track_datas .extend (move (audio_track_datas));
87+ playback_manager->m_preferred_video_track = preferred_video_track;
88+ playback_manager->m_preferred_audio_track = preferred_audio_track;
89+ playback_manager->m_duration = move (duration);
90+
91+ playback_manager->set_up_error_handlers ();
92+
93+ if (!playback_manager->m_audio_tracks .is_empty ()) {
94+ playback_manager->m_audio_sink = MUST (AudioMixingSink::try_create ());
95+ }
96+
97+ if (auto audio_sink = playback_manager->m_audio_sink ) {
98+ VERIFY (playback_manager->current_time ().is_zero ());
99+ playback_manager->m_time_provider = make_ref_counted<WrapperTimeProvider<AudioMixingSink>>(*audio_sink);
100+ }
101+
102+ if (playback_manager->on_track_added ) {
103+ for (auto const & audio_track : playback_manager->m_audio_tracks )
104+ playback_manager->on_track_added (TrackType::Audio, audio_track);
105+ for (auto const & video_track : playback_manager->m_video_tracks )
106+ playback_manager->on_track_added (TrackType::Video, video_track);
107+ }
108+
109+ if (playback_manager->on_metadata_parsed )
110+ playback_manager->on_metadata_parsed ();
111+ });
112+
113+ return {};
114+ }
84115
85- auto playback_manager = DECODER_TRY_ALLOC ( adopt_nonnull_ref_or_enomem ( new (nothrow) PlaybackManager (demuxer, weak_playback_manager, time_provider, move (supported_video_tracks), move (supported_video_track_datas), audio_sink, move (supported_audio_tracks), move (supported_audio_track_datas))));
86- weak_playback_manager-> m_manager = playback_manager;
87- playback_manager-> set_up_error_handlers ( );
88- playback_manager->m_handler = DECODER_TRY_ALLOC (try_make <PausedStateHandler>(*playback_manager) );
116+ NonnullRefPtr<PlaybackManager> PlaybackManager::create ()
117+ {
118+ auto playback_manager = adopt_ref (* new (nothrow) PlaybackManager () );
119+ playback_manager->m_handler = make <PausedStateHandler>(*playback_manager);
89120 return playback_manager;
90121}
91122
92- PlaybackManager::PlaybackManager (NonnullRefPtr<MutexedDemuxer> const & demuxer, NonnullRefPtr<WeakPlaybackManager> const & weak_wrapper, NonnullRefPtr<MediaTimeProvider> const & time_provider, VideoTracks&& video_tracks, VideoTrackDatas&& video_track_datas, RefPtr<AudioMixingSink> const & audio_sink, AudioTracks&& audio_tracks, AudioTrackDatas&& audio_track_datas)
93- : m_demuxer(demuxer)
94- , m_weak_wrapper(weak_wrapper)
95- , m_time_provider(time_provider)
96- , m_video_tracks(video_tracks)
97- , m_video_track_datas(video_track_datas)
98- , m_audio_sink(audio_sink)
99- , m_audio_tracks(audio_tracks)
100- , m_audio_track_datas(audio_track_datas)
123+ PlaybackManager::PlaybackManager ()
124+ : m_weak_wrapper(make_ref_counted<WeakPlaybackManager>())
125+ , m_time_provider(make_ref_counted<GenericTimeProvider>())
101126{
127+ m_weak_wrapper->m_manager = this ;
102128}
103129
104130PlaybackManager::~PlaybackManager ()
105131{
106132 m_weak_wrapper->revoke ();
107133}
108134
135+ void PlaybackManager::add_media_source (ReadonlyBytes media_data)
136+ {
137+ auto thread = Threading::Thread::construct ([playback_manager = NonnullRefPtr { *this }, media_data, &main_thread_event_loop = Core::EventLoop::current ()] -> int {
138+ auto maybe_error = playback_manager->prepare_playback_from_media_data (media_data, main_thread_event_loop);
139+ if (maybe_error.is_error ()) {
140+ main_thread_event_loop.deferred_invoke ([playback_manager, error = maybe_error.release_error ()] mutable {
141+ if (playback_manager->on_unsupported_format_error )
142+ playback_manager->on_unsupported_format_error (move (error));
143+ });
144+ return 0 ;
145+ }
146+ return 0 ;
147+ });
148+
149+ thread->start ();
150+ thread->detach ();
151+ }
152+
109153void PlaybackManager::set_up_error_handlers ()
110154{
111155 for (auto const & video_track_data : m_video_track_datas) {
@@ -136,27 +180,6 @@ void PlaybackManager::dispatch_error(DecoderError&& error)
136180 on_error (move (error));
137181}
138182
139- AK::Duration PlaybackManager::duration () const
140- {
141- return m_demuxer->total_duration ().value_or (AK::Duration::zero ());
142- }
143-
144- Optional<Track> PlaybackManager::preferred_video_track ()
145- {
146- auto result = m_demuxer->get_preferred_track_for_type (TrackType::Video).value_or ({});
147- if (result.has_value () && !m_video_tracks.contains_slow (result.value ()))
148- return {};
149- return result;
150- }
151-
152- Optional<Track> PlaybackManager::preferred_audio_track ()
153- {
154- auto result = m_demuxer->get_preferred_track_for_type (TrackType::Audio).value_or ({});
155- if (result.has_value () && !m_audio_tracks.contains_slow (result.value ()))
156- return {};
157- return result;
158- }
159-
160183PlaybackManager::VideoTrackData& PlaybackManager::get_video_data_for_track (Track const & track)
161184{
162185 for (auto & track_data : m_video_track_datas) {
@@ -171,7 +194,7 @@ NonnullRefPtr<DisplayingVideoSink> PlaybackManager::get_or_create_the_displaying
171194{
172195 auto & track_data = get_video_data_for_track (track);
173196 if (track_data.display == nullptr ) {
174- track_data.display = MUST (Media::DisplayingVideoSink::try_create (m_time_provider));
197+ track_data.display = MUST (Media::DisplayingVideoSink::try_create (* m_time_provider));
175198 track_data.display ->set_provider (track, track_data.provider );
176199 track_data.provider ->start ();
177200 track_data.provider ->seek (m_time_provider->current_time (), SeekMode::Accurate);
0 commit comments