diff --git a/Userland/Libraries/LibVideo/PlaybackManager.cpp b/Userland/Libraries/LibVideo/PlaybackManager.cpp index d8973e155e..875ac95d7e 100644 --- a/Userland/Libraries/LibVideo/PlaybackManager.cpp +++ b/Userland/Libraries/LibVideo/PlaybackManager.cpp @@ -53,27 +53,45 @@ DecoderErrorOr> PlaybackManager::create(NonnullOw dbgln_if(PLAYBACK_MANAGER_DEBUG, "Selecting video track number {}", track.identifier()); auto decoder = DECODER_TRY_ALLOC(try_make()); - auto frame_queue = DECODER_TRY_ALLOC(try_make()); + auto frame_queue = DECODER_TRY_ALLOC(VideoFrameQueue::create()); auto playback_manager = DECODER_TRY_ALLOC(try_make(demuxer, track, move(decoder), move(frame_queue))); playback_manager->m_present_timer = DECODER_TRY_ALLOC(Core::Timer::create_single_shot(0, [&self = *playback_manager] { self.timer_callback(); })); - playback_manager->m_decode_timer = DECODER_TRY_ALLOC(Core::Timer::create_single_shot(0, [&self = *playback_manager] { self.on_decode_timer(); })); + + playback_manager->m_decode_thread = DECODER_TRY_ALLOC(Threading::Thread::try_create([&self = *playback_manager] { + while (!self.m_stop_decoding.load()) + self.decode_and_queue_one_sample(); + + dbgln_if(PLAYBACK_MANAGER_DEBUG, "Media Decoder thread ended."); + return 0; + }, + "Media Decoder"sv)); playback_manager->m_playback_handler = make(*playback_manager, false, Time::zero(), SeekMode::Fast); DECODER_TRY_ALLOC(playback_manager->m_playback_handler->on_enter()); + playback_manager->m_decode_thread->start(); + return playback_manager; } -PlaybackManager::PlaybackManager(NonnullOwnPtr& demuxer, Track video_track, NonnullOwnPtr&& decoder, NonnullOwnPtr&& frame_queue) +PlaybackManager::PlaybackManager(NonnullOwnPtr& demuxer, Track video_track, NonnullOwnPtr&& decoder, VideoFrameQueue&& frame_queue) : m_demuxer(move(demuxer)) , m_selected_video_track(video_track) - , m_decoder(move(decoder)) , m_frame_queue(move(frame_queue)) + , m_decoder(move(decoder)) + , m_decode_wait_condition(m_decode_wait_mutex) { } -PlaybackManager::~PlaybackManager() = default; +PlaybackManager::~PlaybackManager() +{ + m_stop_decoding.exchange(true); + m_decode_wait_condition.broadcast(); + dbgln_if(PLAYBACK_MANAGER_DEBUG, "Waiting for decode thread to end..."); + (void)m_decode_thread->join(); + dbgln_if(PLAYBACK_MANAGER_DEBUG, "Successfully destroyed PlaybackManager."); +} void PlaybackManager::resume_playback() { @@ -96,7 +114,10 @@ Time PlaybackManager::current_playback_time() Time PlaybackManager::duration() { - auto duration_result = m_demuxer->duration(); + auto duration_result = ({ + auto demuxer_locker = Threading::MutexLocker(m_demuxer_mutex); + m_demuxer->duration(); + }); if (duration_result.is_error()) dispatch_decoder_error(duration_result.release_error()); return duration_result.release_value(); @@ -142,7 +163,7 @@ bool PlaybackManager::dispatch_frame_queue_item(FrameQueueItem&& item) return true; } - dbgln_if(PLAYBACK_MANAGER_DEBUG, "Sent frame for presentation with timestamp {}ms", item.timestamp().to_milliseconds()); + dbgln_if(PLAYBACK_MANAGER_DEBUG, "Sent frame for presentation with timestamp {}ms, late by {}ms", item.timestamp().to_milliseconds(), (current_playback_time() - item.timestamp()).to_milliseconds()); dispatch_new_frame(item.bitmap()); return false; } @@ -165,112 +186,139 @@ void PlaybackManager::seek_to_timestamp(Time target_timestamp, SeekMode seek_mod Optional