Skip to content

Commit

Permalink
[GStreamer][MSE] Take playbin's states lock when sending seek event
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=275566

Reviewed by NOBODY (OOPS!).

This fixes possible race between application (triggering another seek from 'seeked' event) and 'state chagne'
continuation (triggered by playbin).

Top level bin element does change the state as result of 'async-done' handling from previous seek request (see
gst_bin_continue_func in gstbin.c). Which may race with handling of 'async-start' posted by sinks on flushing seek. And
may leave the pipeline in inconsistent state and 'hanging' seek that never finishes.

By taking the states lock of top level bin element player will wait for possible state change continuation to complete
before sending next seek event.

Based on a patch by Eugene Mutavchi <[email protected]>.

* Source/WebCore/platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.cpp:
(WebCore::MediaPlayerPrivateGStreamerMSE::doSeek):
  • Loading branch information
calvaris committed Jun 19, 2024
1 parent 5d324a1 commit a5b17e9
Showing 1 changed file with 13 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -241,8 +241,19 @@ bool MediaPlayerPrivateGStreamerMSE::doSeek(const SeekTarget& target, float rate

// Important: In order to ensure correct propagation whether pre-roll has happened or not, we send the seek directly
// to the source element, rather than letting playbin do the routing.
gst_element_seek(m_source.get(), rate, GST_FORMAT_TIME, m_seekFlags,
GST_SEEK_TYPE_SET, toGstClockTime(target.time), GST_SEEK_TYPE_NONE, 0);
{
// Take the STATE_LOCK of the __pipeline__.
//
// gst_element_send_event() [which is called by gst_element_seek()] already takes the STATE_LOCK of the element
// in order to delay any state change attempts from other threads while the event is travelling the pipeline.
//
// Normally that would happen to both the pipeline and then recursively to the elements inside as they handle
// the seek event, but since we're sending the event directly to the source element we need to take the
// STATE_LOCK on the pipeline ourselves.
auto locker = GstStateLocker(pipeline());
gst_element_seek(m_source.get(), rate, GST_FORMAT_TIME, m_seekFlags,
GST_SEEK_TYPE_SET, toGstClockTime(target.time), GST_SEEK_TYPE_NONE, 0);
}
invalidateCachedPosition();

// Notify MediaSource and have new frames enqueued (when they're available).
Expand Down

0 comments on commit a5b17e9

Please sign in to comment.