Branch: refs/heads/main
  Home:   https://github.com/WebKit/WebKit
  Commit: b1ff5913b21169adf6d94f74538d8ee90188abb6
      
https://github.com/WebKit/WebKit/commit/b1ff5913b21169adf6d94f74538d8ee90188abb6
  Author: Enrique Ocaña González <[email protected]>
  Date:   2025-09-26 (Fri, 26 Sep 2025)

  Changed paths:
    M Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp
    M Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h
    M 
Source/WebCore/platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.cpp

  Log Message:
  -----------
  [MSE][GStreamer] Support markEndOfStream() before appendBuffer()
https://bugs.webkit.org/show_bug.cgi?id=278726

Reviewed by Xabier Rodriguez-Calvar.

In the past, WebKit MSE couldn't complete playback when JavaScript
performs MediaSource.markEndOfStream() before appending any samples with
SourceBuffer.appendBuffer(). A previous patch added that support, but
still the error keeps happening under some circumstances downstream
(wpe-2.46, GStreamer 1.18) as well as upstream (where it was believed
not to happen in GStreamer 1.24).

This happens when the test case is exercised in a loop and the race
condition for an error occurs while errors are ignored, but the
GstMessage with the error takes a moment to propagate to the main thread
(when the errors are no longer ignored).

See: https://github.com/WebPlatformForEmbedded/WPEWebKit/issues/1558

This patch now applies the fix to any GStreamer version (because the
issue appears in all of them). When an EOS without buffers happens, the
pipeline goes to READY, and errors are ignored. The m_ignoreErrors flag
is kept enabled while the pipeline is being set to READY, but if any
error has been detected by the sync message handler, it stays enabled
until the last enqueued error is processed by the main thread. In any
case m_ignoreErrors is only changed from the main thread (in different
loop cycles in the worst case, but always from the main thread) and
doesn't need concurrent access protection.

As mentioned in the previous paragraph, a new sync error signal listener
has been added. This listener doesn't do any actual error processing,
just increases the m_queuedSyncErrors counter. The async message handler
will end up getting the error message anyway. That's where the message
will be ignored (if the m_ignoreErrors flag is set) and, ignored or not,
the m_queuedSyncErrors counter will be decremented. Note that this
counter is an Atomic, in order to support access from the (potentially)
non-main thread that handles the sync error signal, from the main thread
that ends up processing the error, and from the main thread that
processes setEosWithNoBuffers().

If an error has happened, an EOS in the pipeline is simulated by calling
didEnd(), the same method that would be called if such an EOS had
happened. This call usually triggers a pipeline teardown and the further
destruction of the player private. This may trigger a
gst_bus_set_flushing() call and cause the error message to never be
dispatched to the main thread. While this may mean that the
m_queuedSyncErrors counter is never decremented, this isn't a real
problem, since the player is being destructed anyway and nobody cares
about the count anymore.

* Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp:
(WebCore::MediaPlayerPrivateGStreamer::handleSyncErrorMessage): Detect errors 
as they happen, in the same thread where they were generated (often a non-main 
thread). The count of m_queuedSyncErrors is atomically increased to indicate 
the main thread that there are error messages pending to process. There's no 
need to forward the processing to the main thread, since the bus will 
eventually dispatch it asynchronously.
(WebCore::MediaPlayerPrivateGStreamer::handleMessage): If the last error is 
being processed while in a "ignore errors" state, reset the state to false. 
Also, exit early if we were in "ignore errors" state. In any case (early or 
standard exit), decrease the m_queuedSyncErrors count atomically.
(WebCore::MediaPlayerPrivateGStreamer::createGSTPlayBin): Process error 
messages synchronously with the handleSyncErrorMessage() handler.
* Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h: 
didEnd() is now protected, so it can be called by the subclass. Added the 
m_queuedSyncErrors atomic counter to signal how many errors are waiting to be 
processed by the main thread.
* 
Source/WebCore/platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.cpp:
(WebCore::MediaPlayerPrivateGStreamerMSE::setEosWithNoBuffers): Ignore the 
errors on all GStreamer versions by declaring m_ignoreErrors as true. If 
pending error messages are enqueued, report EOS by calling didEnd() 
(m_ignoreErrors will be reset when the last error is processed). If no pending 
error messages appeared, just reset the m_ignoreErrors flag here.

Canonical link: https://commits.webkit.org/300605@main



To unsubscribe from these emails, change your notification settings at 
https://github.com/WebKit/WebKit/settings/notifications
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to