mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 10:27:34 +00:00
LibVideo: Deduplicate logic for dispatching video frame queue items
Previously we had dispatch_decoder_error and on_decoder_error serving the same function, with one not handling the end of stream properly. There is also a new function to dispatch either an error or a frame to the owner of this playback manager, so that PlaybackStateHandlers don't have to duplicate this logic.
This commit is contained in:
parent
e813b8fd19
commit
2a228e8a6e
2 changed files with 28 additions and 20 deletions
|
@ -75,7 +75,7 @@ Time PlaybackManager::duration()
|
||||||
{
|
{
|
||||||
auto duration_result = m_demuxer->duration();
|
auto duration_result = m_demuxer->duration();
|
||||||
if (duration_result.is_error())
|
if (duration_result.is_error())
|
||||||
on_decoder_error(duration_result.release_error());
|
dispatch_decoder_error(duration_result.release_error());
|
||||||
return duration_result.release_value();
|
return duration_result.release_value();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,7 +89,7 @@ void PlaybackManager::dispatch_fatal_error(Error error)
|
||||||
m_event_handler.dispatch_event(event);
|
m_event_handler.dispatch_event(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlaybackManager::on_decoder_error(DecoderError error)
|
void PlaybackManager::dispatch_decoder_error(DecoderError error)
|
||||||
{
|
{
|
||||||
switch (error.category()) {
|
switch (error.category()) {
|
||||||
case DecoderErrorCategory::EndOfStream:
|
case DecoderErrorCategory::EndOfStream:
|
||||||
|
@ -104,6 +104,23 @@ void PlaybackManager::on_decoder_error(DecoderError error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PlaybackManager::dispatch_new_frame(RefPtr<Gfx::Bitmap> frame)
|
||||||
|
{
|
||||||
|
m_main_loop.post_event(m_event_handler, make<VideoFramePresentEvent>(frame));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PlaybackManager::dispatch_frame_queue_item(FrameQueueItem&& item)
|
||||||
|
{
|
||||||
|
if (item.is_error()) {
|
||||||
|
dispatch_decoder_error(item.release_error());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
dbgln_if(PLAYBACK_MANAGER_DEBUG, "Sent frame for presentation");
|
||||||
|
dispatch_new_frame(item.bitmap());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
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->on_timer_callback());
|
||||||
|
@ -120,7 +137,7 @@ Optional<Time> PlaybackManager::seek_demuxer_to_most_recent_keyframe(Time timest
|
||||||
// mutex so that seeking can't happen while that thread is getting a sample.
|
// mutex so that seeking can't happen while that thread is getting a sample.
|
||||||
auto result = m_demuxer->seek_to_most_recent_keyframe(m_selected_video_track, timestamp, move(earliest_available_sample));
|
auto result = m_demuxer->seek_to_most_recent_keyframe(m_selected_video_track, timestamp, move(earliest_available_sample));
|
||||||
if (result.is_error())
|
if (result.is_error())
|
||||||
on_decoder_error(result.release_error());
|
dispatch_decoder_error(result.release_error());
|
||||||
return result.release_value();
|
return result.release_value();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,16 +146,6 @@ void PlaybackManager::restart_playback()
|
||||||
seek_to_timestamp(Time::zero());
|
seek_to_timestamp(Time::zero());
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlaybackManager::dispatch_decoder_error(DecoderError error)
|
|
||||||
{
|
|
||||||
m_main_loop.post_event(m_event_handler, make<DecoderErrorEvent>(error));
|
|
||||||
}
|
|
||||||
|
|
||||||
void PlaybackManager::dispatch_new_frame(RefPtr<Gfx::Bitmap> frame)
|
|
||||||
{
|
|
||||||
m_main_loop.post_event(m_event_handler, make<VideoFramePresentEvent>(frame));
|
|
||||||
}
|
|
||||||
|
|
||||||
void PlaybackManager::start_timer(int milliseconds)
|
void PlaybackManager::start_timer(int milliseconds)
|
||||||
{
|
{
|
||||||
m_present_timer->start(milliseconds);
|
m_present_timer->start(milliseconds);
|
||||||
|
@ -341,7 +348,7 @@ private:
|
||||||
#endif
|
#endif
|
||||||
if (future_frame_item.has_value()) {
|
if (future_frame_item.has_value()) {
|
||||||
if (future_frame_item->is_error()) {
|
if (future_frame_item->is_error()) {
|
||||||
manager().on_decoder_error(future_frame_item.release_value().release_error());
|
manager().dispatch_decoder_error(future_frame_item.release_value().release_error());
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
manager().m_next_frame.emplace(future_frame_item.release_value());
|
manager().m_next_frame.emplace(future_frame_item.release_value());
|
||||||
|
@ -355,15 +362,16 @@ private:
|
||||||
auto now = Time::now_monotonic();
|
auto now = Time::now_monotonic();
|
||||||
manager().m_last_present_in_media_time += now - m_last_present_in_real_time;
|
manager().m_last_present_in_media_time += now - m_last_present_in_real_time;
|
||||||
m_last_present_in_real_time = now;
|
m_last_present_in_real_time = now;
|
||||||
manager().dispatch_new_frame(manager().m_next_frame.value().bitmap());
|
|
||||||
dbgln_if(PLAYBACK_MANAGER_DEBUG, "Sent frame for presentation");
|
if (manager().dispatch_frame_queue_item(manager().m_next_frame.release_value()))
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now that we've presented the current frame, we can throw whatever error is next in queue.
|
// Now that we've presented the current frame, we can throw whatever error is next in queue.
|
||||||
// This way, we always display a frame before the stream ends, and should also show any frames
|
// This way, we always display a frame before the stream ends, and should also show any frames
|
||||||
// we already had when a real error occurs.
|
// we already had when a real error occurs.
|
||||||
if (future_frame_item->is_error()) {
|
if (future_frame_item->is_error()) {
|
||||||
manager().on_decoder_error(future_frame_item.release_value().release_error());
|
manager().dispatch_decoder_error(future_frame_item.release_value().release_error());
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -498,7 +506,7 @@ private:
|
||||||
|
|
||||||
if (item.is_error()) {
|
if (item.is_error()) {
|
||||||
dbgln_if(PLAYBACK_MANAGER_DEBUG, "Encountered error while seeking: {}", item.error().description());
|
dbgln_if(PLAYBACK_MANAGER_DEBUG, "Encountered error while seeking: {}", item.error().description());
|
||||||
manager().on_decoder_error(item.release_error());
|
manager().dispatch_decoder_error(item.release_error());
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -106,8 +106,6 @@ public:
|
||||||
|
|
||||||
u64 number_of_skipped_frames() const { return m_skipped_frames; }
|
u64 number_of_skipped_frames() const { return m_skipped_frames; }
|
||||||
|
|
||||||
void on_decoder_error(DecoderError error);
|
|
||||||
|
|
||||||
Time current_playback_time();
|
Time current_playback_time();
|
||||||
Time duration();
|
Time duration();
|
||||||
|
|
||||||
|
@ -130,6 +128,8 @@ private:
|
||||||
|
|
||||||
void dispatch_decoder_error(DecoderError error);
|
void dispatch_decoder_error(DecoderError error);
|
||||||
void dispatch_new_frame(RefPtr<Gfx::Bitmap> frame);
|
void dispatch_new_frame(RefPtr<Gfx::Bitmap> frame);
|
||||||
|
// Returns whether we changed playback states. If so, any PlaybackStateHandler processing must cease.
|
||||||
|
[[nodiscard]] bool dispatch_frame_queue_item(FrameQueueItem&&);
|
||||||
void dispatch_fatal_error(Error);
|
void dispatch_fatal_error(Error);
|
||||||
|
|
||||||
Core::Object& m_event_handler;
|
Core::Object& m_event_handler;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue