1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 21:27:34 +00:00

LibVideo/PlaybackManager: Use a function to start the internal timer

In addition, this renames the internal timer to better suit its new
purpose since the playback state handlers were added. Not only is it
used to time frame presentations, but also to poll the queue when
seeking or buffering.
This commit is contained in:
Zaggy1024 2023-05-18 23:30:49 -05:00 committed by Andrew Kaster
parent 71d70df34f
commit e31f696ee6
2 changed files with 18 additions and 12 deletions

View file

@ -56,7 +56,7 @@ DecoderErrorOr<NonnullOwnPtr<PlaybackManager>> PlaybackManager::create(NonnullOw
auto frame_queue = DECODER_TRY_ALLOC(VideoFrameQueue::create()); auto frame_queue = DECODER_TRY_ALLOC(VideoFrameQueue::create());
auto playback_manager = DECODER_TRY_ALLOC(try_make<PlaybackManager>(demuxer, track, move(decoder), move(frame_queue))); auto playback_manager = DECODER_TRY_ALLOC(try_make<PlaybackManager>(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_state_update_timer = DECODER_TRY_ALLOC(Core::Timer::create_single_shot(0, [&self = *playback_manager] { self.timer_callback(); }));
playback_manager->m_decode_thread = DECODER_TRY_ALLOC(Threading::Thread::try_create([&self = *playback_manager] { playback_manager->m_decode_thread = DECODER_TRY_ALLOC(Threading::Thread::try_create([&self = *playback_manager] {
while (!self.m_stop_decoding.load()) while (!self.m_stop_decoding.load())
@ -176,7 +176,7 @@ void PlaybackManager::dispatch_state_change()
void PlaybackManager::timer_callback() void PlaybackManager::timer_callback()
{ {
TRY_OR_FATAL_ERROR(m_playback_handler->on_timer_callback()); TRY_OR_FATAL_ERROR(m_playback_handler->do_timed_state_update());
} }
void PlaybackManager::seek_to_timestamp(Time target_timestamp, SeekMode seek_mode) void PlaybackManager::seek_to_timestamp(Time target_timestamp, SeekMode seek_mode)
@ -204,6 +204,11 @@ Optional<FrameQueueItem> PlaybackManager::dequeue_one_frame()
return result.release_value(); return result.release_value();
} }
void PlaybackManager::set_state_update_timer(int delay_ms)
{
m_state_update_timer->start(delay_ms);
}
void PlaybackManager::restart_playback() void PlaybackManager::restart_playback()
{ {
seek_to_timestamp(Time::zero()); seek_to_timestamp(Time::zero());
@ -404,7 +409,7 @@ private:
ErrorOr<void> on_enter() override ErrorOr<void> on_enter() override
{ {
m_last_present_in_real_time = Time::now_monotonic(); m_last_present_in_real_time = Time::now_monotonic();
return on_timer_callback(); return do_timed_state_update();
} }
StringView name() override { return "Playing"sv; } StringView name() override { return "Playing"sv; }
@ -427,13 +432,13 @@ private:
return manager().m_last_present_in_media_time + (Time::now_monotonic() - m_last_present_in_real_time); return manager().m_last_present_in_media_time + (Time::now_monotonic() - m_last_present_in_real_time);
} }
ErrorOr<void> on_timer_callback() override ErrorOr<void> do_timed_state_update() override
{ {
auto set_presentation_timer = [&]() { auto set_presentation_timer = [&]() {
auto frame_time_ms = (manager().m_next_frame->timestamp() - current_time()).to_milliseconds(); auto frame_time_ms = (manager().m_next_frame->timestamp() - current_time()).to_milliseconds();
VERIFY(frame_time_ms <= NumericLimits<int>::max()); VERIFY(frame_time_ms <= NumericLimits<int>::max());
dbgln_if(PLAYBACK_MANAGER_DEBUG, "Time until next frame is {}ms", frame_time_ms); dbgln_if(PLAYBACK_MANAGER_DEBUG, "Time until next frame is {}ms", frame_time_ms);
manager().m_present_timer->start(max(static_cast<int>(frame_time_ms), 0)); manager().set_state_update_timer(max(static_cast<int>(frame_time_ms), 0));
}; };
if (manager().m_next_frame.has_value() && current_time() < manager().m_next_frame->timestamp()) { if (manager().m_next_frame.has_value() && current_time() < manager().m_next_frame->timestamp()) {
@ -547,20 +552,20 @@ class PlaybackManager::BufferingStateHandler : public PlaybackManager::ResumingS
ErrorOr<void> on_enter() override ErrorOr<void> on_enter() override
{ {
manager().m_present_timer->start(buffering_or_seeking_decode_wait_time); manager().set_state_update_timer(buffering_or_seeking_decode_wait_time);
return {}; return {};
} }
StringView name() override { return "Buffering"sv; } StringView name() override { return "Buffering"sv; }
ErrorOr<void> on_timer_callback() override ErrorOr<void> do_timed_state_update() override
{ {
auto buffer_is_full = manager().m_buffer_is_full.load(); auto buffer_is_full = manager().m_buffer_is_full.load();
dbgln_if(PLAYBACK_MANAGER_DEBUG, "Buffering timer callback has been called. Buffer is {}.", buffer_is_full ? "full, exiting"sv : "not full, waiting"sv); dbgln_if(PLAYBACK_MANAGER_DEBUG, "Buffering timer callback has been called. Buffer is {}.", buffer_is_full ? "full, exiting"sv : "not full, waiting"sv);
if (buffer_is_full) if (buffer_is_full)
return assume_next_state(); return assume_next_state();
manager().m_present_timer->start(buffering_or_seeking_decode_wait_time); manager().set_state_update_timer(buffering_or_seeking_decode_wait_time);
return {}; return {};
} }
@ -644,7 +649,7 @@ private:
} }
dbgln_if(PLAYBACK_MANAGER_DEBUG, "Frame queue is empty while seeking, waiting for buffer to fill."); dbgln_if(PLAYBACK_MANAGER_DEBUG, "Frame queue is empty while seeking, waiting for buffer to fill.");
manager().m_present_timer->start(buffering_or_seeking_decode_wait_time); manager().set_state_update_timer(buffering_or_seeking_decode_wait_time);
return {}; return {};
} }
@ -663,7 +668,7 @@ private:
} }
// We won't need this override when threaded, the queue can pause us in on_enter(). // We won't need this override when threaded, the queue can pause us in on_enter().
ErrorOr<void> on_timer_callback() override ErrorOr<void> do_timed_state_update() override
{ {
dbgln_if(PLAYBACK_MANAGER_DEBUG, "Seeking wait finished, attempting to dequeue until timestamp."); dbgln_if(PLAYBACK_MANAGER_DEBUG, "Seeking wait finished, attempting to dequeue until timestamp.");
return skip_samples_until_timestamp(); return skip_samples_until_timestamp();

View file

@ -161,6 +161,7 @@ private:
Optional<Time> seek_demuxer_to_most_recent_keyframe(Time timestamp, Optional<Time> earliest_available_sample = OptionalNone()); Optional<Time> seek_demuxer_to_most_recent_keyframe(Time timestamp, Optional<Time> earliest_available_sample = OptionalNone());
Optional<FrameQueueItem> dequeue_one_frame(); Optional<FrameQueueItem> dequeue_one_frame();
void set_state_update_timer(int delay_ms);
void decode_and_queue_one_sample(); void decode_and_queue_one_sample();
@ -179,7 +180,7 @@ private:
VideoFrameQueue m_frame_queue; VideoFrameQueue m_frame_queue;
RefPtr<Core::Timer> m_present_timer; RefPtr<Core::Timer> m_state_update_timer;
unsigned m_decoding_buffer_time_ms = 16; unsigned m_decoding_buffer_time_ms = 16;
RefPtr<Threading::Thread> m_decode_thread; RefPtr<Threading::Thread> m_decode_thread;
@ -216,7 +217,7 @@ private:
virtual Time current_time() const; virtual Time current_time() const;
virtual ErrorOr<void> on_timer_callback() { return {}; }; virtual ErrorOr<void> do_timed_state_update() { return {}; };
protected: protected:
template<class T, class... Args> template<class T, class... Args>