diff --git a/Userland/Libraries/LibVideo/PlaybackManager.cpp b/Userland/Libraries/LibVideo/PlaybackManager.cpp index 777f654449..f854dd43a7 100644 --- a/Userland/Libraries/LibVideo/PlaybackManager.cpp +++ b/Userland/Libraries/LibVideo/PlaybackManager.cpp @@ -277,6 +277,61 @@ PlaybackManager& PlaybackManager::PlaybackStateHandler::manager() const return m_manager; } +class PlaybackManager::StartingStateHandler : public PlaybackManager::PlaybackStateHandler { +public: + StartingStateHandler(PlaybackManager& manager, bool playing) + : PlaybackStateHandler(manager) + , m_playing(playing) + { + } + ~StartingStateHandler() override = default; + +private: + ErrorOr on_enter() override + { + return on_timer_callback(); + } + + StringView name() override { return "Starting"sv; } + + ErrorOr on_timer_callback() override + { + // Once we're threaded, instead of checking for the count here we can just mutex + // in the queue until we display the first and then again for the second to store it. + if (manager().m_frame_queue->size() < 3) { + manager().m_decode_timer->start(0); + manager().start_timer(0); + return {}; + } + + auto frame_to_display = manager().m_frame_queue->dequeue(); + manager().m_last_present_in_media_time = frame_to_display.timestamp(); + if (manager().dispatch_frame_queue_item(move(frame_to_display))) + return {}; + + manager().m_next_frame.emplace(manager().m_frame_queue->dequeue()); + manager().m_decode_timer->start(0); + dbgln_if(PLAYBACK_MANAGER_DEBUG, "Displayed frame at {}ms, emplaced second frame at {}ms, finishing start now", manager().m_last_present_in_media_time.to_milliseconds(), manager().m_next_frame->timestamp().to_milliseconds()); + if (!m_playing) + return replace_handler_and_delete_this(); + return replace_handler_and_delete_this(); + } + + ErrorOr play() override + { + m_playing = true; + return {}; + } + bool is_playing() override { return m_playing; }; + ErrorOr pause() override + { + m_playing = false; + return {}; + } + + bool m_playing; +}; + class PlaybackManager::PlayingStateHandler : public PlaybackManager::PlaybackStateHandler { public: PlayingStateHandler(PlaybackManager& manager) @@ -320,7 +375,7 @@ private: manager().start_timer(max(static_cast(frame_time_ms), 0)); }; - if (manager().m_next_frame.has_value() && manager().m_next_frame->timestamp() < current_time()) { + if (manager().m_next_frame.has_value() && current_time() < manager().m_next_frame->timestamp()) { dbgln_if(PLAYBACK_MANAGER_DEBUG, "Current time {}ms is too early to present the next frame at {}ms, delaying", current_time().to_milliseconds(), manager().m_next_frame->timestamp().to_milliseconds()); set_presentation_timer(); return {}; @@ -600,7 +655,7 @@ private: auto start_timestamp = manager().seek_demuxer_to_most_recent_keyframe(Time::zero()); VERIFY(start_timestamp.has_value()); manager().m_last_present_in_media_time = start_timestamp.release_value(); - return replace_handler_and_delete_this(); + return replace_handler_and_delete_this(true); } bool is_playing() override { return false; }; }; diff --git a/Userland/Libraries/LibVideo/PlaybackManager.h b/Userland/Libraries/LibVideo/PlaybackManager.h index 5082049afe..f71cfbb726 100644 --- a/Userland/Libraries/LibVideo/PlaybackManager.h +++ b/Userland/Libraries/LibVideo/PlaybackManager.h @@ -114,6 +114,7 @@ public: private: class PlaybackStateHandler; + class StartingStateHandler; class PlayingStateHandler; class PausedStateHandler; class BufferingStateHandler;