From f9a65c1502d53438186a3ed17782c4b61673de3c Mon Sep 17 00:00:00 2001 From: Zaggy1024 Date: Sun, 12 Feb 2023 02:00:59 -0600 Subject: [PATCH] LibVideo: Check whether it's time to present frames before doing so Previously, we assumed the timer was hitting at the correct time. This meant that if we changed states and the previous state handler had prepared a next frame, we would immediately display it without checking the timestamp. --- .../Libraries/LibVideo/PlaybackManager.cpp | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/Userland/Libraries/LibVideo/PlaybackManager.cpp b/Userland/Libraries/LibVideo/PlaybackManager.cpp index e29e95db47b..777f654449a 100644 --- a/Userland/Libraries/LibVideo/PlaybackManager.cpp +++ b/Userland/Libraries/LibVideo/PlaybackManager.cpp @@ -313,6 +313,19 @@ private: ErrorOr on_timer_callback() override { + auto set_presentation_timer = [&]() { + auto frame_time_ms = (manager().m_next_frame->timestamp() - current_time()).to_milliseconds(); + VERIFY(frame_time_ms <= NumericLimits::max()); + dbgln_if(PLAYBACK_MANAGER_DEBUG, "Time until next frame is {}ms", frame_time_ms); + manager().start_timer(max(static_cast(frame_time_ms), 0)); + }; + + if (manager().m_next_frame.has_value() && manager().m_next_frame->timestamp() < current_time()) { + 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 {}; + } + Optional future_frame_item; bool should_present_frame = false; @@ -381,11 +394,7 @@ private: // The future frame item becomes the next one to present. manager().m_next_frame.emplace(future_frame_item.release_value()); - - auto frame_time_ms = (manager().m_next_frame->timestamp() - current_time()).to_milliseconds(); - VERIFY(frame_time_ms <= NumericLimits::max()); - dbgln_if(PLAYBACK_MANAGER_DEBUG, "Time until next frame is {}ms", frame_time_ms); - manager().start_timer(max(static_cast(frame_time_ms), 0)); + set_presentation_timer(); return {}; }