- Revision
- 260506
- Author
- [email protected]
- Date
- 2020-04-22 04:36:27 -0700 (Wed, 22 Apr 2020)
Log Message
[GStreamer][MSE] Youtube 'live stream'/H264 URLs fail to play, VP8/9 URLs play OK
https://bugs.webkit.org/show_bug.cgi?id=209119
Reviewed by Xabier Rodriguez-Calvar.
Source/WebCore:
The fix consists of removing the initial avoiding of seeking and just
issuing the proper segment instead of seeking (seeks in GStreamer can't
be done before prerolling anyway). Appsrc doesn't make easy to emit our
own custom segment, so what I did was to use a segment fixer probe to
modify the original [0, infinity] segment issued by appsrc and use
a [startTime, stopTime] with proper values depending on the seek target
and rate.
Covered by existing tests.
* platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.cpp:
(WebCore::checkShouldDelaySeek): Don't hold seeks on startup, when changing from READY to PAUSED.
(WebCore::MediaPlayerPrivateGStreamerMSE::doSeek): Refactored seek delay condition. Also, don't do a regular
gst_element_seek() for initial seeks, just proceed with a special case in that situation.
* platform/graphics/gstreamer/mse/WebKitMediaSourceGStreamer.cpp:
(initialSeekSegmentFixerProbe): Probe that fixes the segment.
(webKitMediaSrcPrepareInitialSeek): Behave much like a regular seek, but also compute the right GstSegment, install
the segment fixer probe and setReadyForMoreSamples() on the SourceBufferPrivates.
* platform/graphics/gstreamer/mse/WebKitMediaSourceGStreamer.h:
LayoutTests:
Unskipped media/media-source/media-source-seek-redundant-append.html,
which passes now.
* platform/gtk/TestExpectations:
* platform/wpe/TestExpectations:
Modified Paths
Diff
Modified: trunk/LayoutTests/ChangeLog (260505 => 260506)
--- trunk/LayoutTests/ChangeLog 2020-04-22 10:19:30 UTC (rev 260505)
+++ trunk/LayoutTests/ChangeLog 2020-04-22 11:36:27 UTC (rev 260506)
@@ -1,3 +1,16 @@
+2020-04-22 Enrique Ocaña González <[email protected]>
+
+ [GStreamer][MSE] Youtube 'live stream'/H264 URLs fail to play, VP8/9 URLs play OK
+ https://bugs.webkit.org/show_bug.cgi?id=209119
+
+ Reviewed by Xabier Rodriguez-Calvar.
+
+ Unskipped media/media-source/media-source-seek-redundant-append.html,
+ which passes now.
+
+ * platform/gtk/TestExpectations:
+ * platform/wpe/TestExpectations:
+
2020-04-21 Sergio Villar Senin <[email protected]>
[WebXR] Test IDLs and stubs
Modified: trunk/LayoutTests/platform/gtk/TestExpectations (260505 => 260506)
--- trunk/LayoutTests/platform/gtk/TestExpectations 2020-04-22 10:19:30 UTC (rev 260505)
+++ trunk/LayoutTests/platform/gtk/TestExpectations 2020-04-22 11:36:27 UTC (rev 260506)
@@ -3325,8 +3325,6 @@
webkit.org/b/202736 http/tests/appcache/remove-cache.html [ Failure Timeout Pass ]
webkit.org/b/202736 [ Release ] http/wpt/cache-storage/quota-third-party.https.html [ Failure Timeout Pass ]
-webkit.org/b/206873 media/media-source/media-source-seek-redundant-append.html [ Timeout ]
-
webkit.org/b/206876 http/tests/security/storage-blocking-strengthened-private-browsing-plugin.html [ Timeout ]
webkit.org/b/207711 [ Release ] fast/history/page-cache-webdatabase-pending-transaction.html [ Timeout ]
Modified: trunk/LayoutTests/platform/wpe/TestExpectations (260505 => 260506)
--- trunk/LayoutTests/platform/wpe/TestExpectations 2020-04-22 10:19:30 UTC (rev 260505)
+++ trunk/LayoutTests/platform/wpe/TestExpectations 2020-04-22 11:36:27 UTC (rev 260506)
@@ -1499,8 +1499,6 @@
webkit.org/b/201268 accessibility/insert-newline.html [ Timeout ]
-webkit.org/b/206873 media/media-source/media-source-seek-redundant-append.html [ Timeout ]
-
webkit.org/b/207711 [ Debug ] fast/selectors/slow-style-sharing-with-long-cousin-list.html [ Timeout ]
webkit.org/b/207711 http/tests/cookies/double-quoted-value-with-semi-colon.html [ Failure Timeout ]
webkit.org/b/207711 [ Release ] fast/history/page-cache-webdatabase-pending-transaction.html [ Timeout ]
Modified: trunk/Source/WebCore/ChangeLog (260505 => 260506)
--- trunk/Source/WebCore/ChangeLog 2020-04-22 10:19:30 UTC (rev 260505)
+++ trunk/Source/WebCore/ChangeLog 2020-04-22 11:36:27 UTC (rev 260506)
@@ -1,3 +1,30 @@
+2020-04-22 Enrique Ocaña González <[email protected]>
+
+ [GStreamer][MSE] Youtube 'live stream'/H264 URLs fail to play, VP8/9 URLs play OK
+ https://bugs.webkit.org/show_bug.cgi?id=209119
+
+ Reviewed by Xabier Rodriguez-Calvar.
+
+ The fix consists of removing the initial avoiding of seeking and just
+ issuing the proper segment instead of seeking (seeks in GStreamer can't
+ be done before prerolling anyway). Appsrc doesn't make easy to emit our
+ own custom segment, so what I did was to use a segment fixer probe to
+ modify the original [0, infinity] segment issued by appsrc and use
+ a [startTime, stopTime] with proper values depending on the seek target
+ and rate.
+
+ Covered by existing tests.
+
+ * platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.cpp:
+ (WebCore::checkShouldDelaySeek): Don't hold seeks on startup, when changing from READY to PAUSED.
+ (WebCore::MediaPlayerPrivateGStreamerMSE::doSeek): Refactored seek delay condition. Also, don't do a regular
+ gst_element_seek() for initial seeks, just proceed with a special case in that situation.
+ * platform/graphics/gstreamer/mse/WebKitMediaSourceGStreamer.cpp:
+ (initialSeekSegmentFixerProbe): Probe that fixes the segment.
+ (webKitMediaSrcPrepareInitialSeek): Behave much like a regular seek, but also compute the right GstSegment, install
+ the segment fixer probe and setReadyForMoreSamples() on the SourceBufferPrivates.
+ * platform/graphics/gstreamer/mse/WebKitMediaSourceGStreamer.h:
+
2020-04-21 Sergio Villar Senin <[email protected]>
[WebXR] Test IDLs and stubs
Modified: trunk/Source/WebCore/platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.cpp (260505 => 260506)
--- trunk/Source/WebCore/platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.cpp 2020-04-22 10:19:30 UTC (rev 260505)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.cpp 2020-04-22 11:36:27 UTC (rev 260506)
@@ -241,6 +241,17 @@
}
}
+static bool checkShouldDelaySeek(GstStateChangeReturn getStateResult, GstState currentState, GstState newState)
+{
+ if (getStateResult != GST_STATE_CHANGE_ASYNC)
+ return false;
+ if (GST_STATE_TRANSITION(currentState, newState) == GST_STATE_CHANGE_PLAYING_TO_PAUSED)
+ return false;
+ if (currentState == GST_STATE_READY && newState >= GST_STATE_PAUSED)
+ return false;
+ return true;
+}
+
bool MediaPlayerPrivateGStreamerMSE::doSeek(const MediaTime& position, float rate, GstSeekFlags seekType)
{
// FIXME: Make a copy here because in some cases below it is modified. This
@@ -259,13 +270,11 @@
m_isSeeking = false;
return false;
}
- if ((getStateResult == GST_STATE_CHANGE_ASYNC
- && !(state == GST_STATE_PLAYING && newState == GST_STATE_PAUSED))
- || state < GST_STATE_PAUSED
- || m_isEndReached
- || !m_gstSeekCompleted) {
+
+ bool shouldDelaySeek = checkShouldDelaySeek(getStateResult, state, newState);
+ if (shouldDelaySeek || m_isEndReached || !m_gstSeekCompleted) {
CString reason = "Unknown reason";
- if (getStateResult == GST_STATE_CHANGE_ASYNC) {
+ if (shouldDelaySeek) {
reason = makeString("In async change ",
gst_element_state_get_name(state), " --> ",
gst_element_state_get_name(newState)).utf8();
@@ -347,20 +356,26 @@
GST_DEBUG_OBJECT(pipeline(), "Actual seek to %s, end time: %s, rate: %f", toString(startTime).utf8().data(), toString(endTime).utf8().data(), rate);
- // This will call notifySeekNeedsData() after some time to tell that the pipeline is ready for sample enqueuing.
- webKitMediaSrcPrepareSeek(WEBKIT_MEDIA_SRC(m_source.get()), seekTime);
+ m_gstSeekCompleted = false;
+ if (state < GST_STATE_PAUSED) {
+ // Special case of initial seek. We set the right segment instead of a seek.
+ webKitMediaSrcPrepareInitialSeek(WEBKIT_MEDIA_SRC(m_source.get()), rate, startTime, endTime);
+ notifySeekNeedsDataForTime(seekTime);
+ GST_DEBUG("Initial seek succeeded, returning true");
+ } else {
+ // This will call notifySeekNeedsData() after some time to tell that the pipeline is ready for sample enqueuing.
+ webKitMediaSrcPrepareSeek(WEBKIT_MEDIA_SRC(m_source.get()), seekTime);
- m_gstSeekCompleted = false;
- if (!gst_element_seek(m_pipeline.get(), rate, GST_FORMAT_TIME, seekType, GST_SEEK_TYPE_SET, toGstClockTime(startTime), GST_SEEK_TYPE_SET, toGstClockTime(endTime))) {
- webKitMediaSrcSetReadyForSamples(WEBKIT_MEDIA_SRC(m_source.get()), true);
- m_isSeeking = false;
- m_gstSeekCompleted = true;
- GST_DEBUG_OBJECT(pipeline(), "doSeek(): gst_element_seek() failed, returning false");
- return false;
+ if (!gst_element_seek(m_pipeline.get(), rate, GST_FORMAT_TIME, seekType, GST_SEEK_TYPE_SET, toGstClockTime(startTime), GST_SEEK_TYPE_SET, toGstClockTime(endTime))) {
+ webKitMediaSrcSetReadyForSamples(WEBKIT_MEDIA_SRC(m_source.get()), true);
+ m_isSeeking = false;
+ m_gstSeekCompleted = true;
+ GST_DEBUG("gst_element_seek() failed, returning false");
+ return false;
+ }
+ // The samples will be enqueued in notifySeekNeedsData().
+ GST_DEBUG("gst_element_seek() succeeded, returning true");
}
-
- // The samples will be enqueued in notifySeekNeedsData().
- GST_DEBUG_OBJECT(pipeline(), "doSeek(): gst_element_seek() succeeded, returning true");
return true;
}
Modified: trunk/Source/WebCore/platform/graphics/gstreamer/mse/WebKitMediaSourceGStreamer.cpp (260505 => 260506)
--- trunk/Source/WebCore/platform/graphics/gstreamer/mse/WebKitMediaSourceGStreamer.cpp 2020-04-22 10:19:30 UTC (rev 260505)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/mse/WebKitMediaSourceGStreamer.cpp 2020-04-22 11:36:27 UTC (rev 260506)
@@ -729,6 +729,55 @@
GST_OBJECT_UNLOCK(source);
}
+GstPadProbeReturn initialSeekSegmentFixerProbe(GstPad *pad, GstPadProbeInfo *info, gpointer userData)
+{
+ GstEvent* event = GST_PAD_PROBE_INFO_EVENT(info);
+ if (GST_EVENT_TYPE(event) == GST_EVENT_SEGMENT) {
+ const GstSegment* originalSegment = nullptr;
+ const GstSegment* fixedSegment = static_cast<GstSegment*>(userData);
+ gst_event_parse_segment(event, &originalSegment);
+ GST_DEBUG("Segment at %s: %" GST_SEGMENT_FORMAT ", replaced by %" GST_SEGMENT_FORMAT, GST_ELEMENT_NAME(GST_PAD_PARENT(pad)), originalSegment, fixedSegment);
+ gst_event_replace(reinterpret_cast<GstEvent**>(&info->data), gst_event_new_segment(fixedSegment));
+ return GST_PAD_PROBE_REMOVE;
+ }
+ return GST_PAD_PROBE_OK;
+}
+
+void webKitMediaSrcPrepareInitialSeek(WebKitMediaSrc* source, double rate, const MediaTime& startTime, const MediaTime& endTime)
+{
+ GST_OBJECT_LOCK(source);
+ MediaTime seekTime = (rate >= 0) ? startTime : endTime;
+ source->priv->seekTime = seekTime;
+ source->priv->appsrcSeekDataCount = 0;
+ source->priv->appsrcNeedDataCount = 0;
+
+ for (Stream* stream : source->priv->streams) {
+ stream->appsrcNeedDataFlag = false;
+ // Don't allow samples away from the seekTime to be enqueued.
+ stream->lastEnqueuedTime = seekTime;
+ }
+
+ // The pending action will be performed in enabledAppsrcSeekData().
+ source->priv->appsrcSeekDataNextAction = MediaSourceSeekToTime;
+
+ GUniquePtr<GstSegment> segment(gst_segment_new());
+ segment->format = GST_FORMAT_TIME;
+ gst_segment_do_seek(segment.get(), rate, GST_FORMAT_TIME,
+ static_cast<GstSeekFlags>(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE),
+ GST_SEEK_TYPE_SET, WebCore::toGstUnsigned64Time(startTime),
+ GST_SEEK_TYPE_SET, WebCore::toGstUnsigned64Time(endTime), nullptr);
+
+ for (Stream* stream : source->priv->streams) {
+ // This probe will fix the segment autogenerated by appsrc.
+ GRefPtr<GstPad> pad = adoptGRef(gst_element_get_static_pad(stream->appsrc, "src"));
+ gst_pad_add_probe(pad.get(), GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM,
+ initialSeekSegmentFixerProbe, gst_segment_copy(segment.get()), reinterpret_cast<GDestroyNotify>(gst_segment_free));
+ stream->sourceBuffer->setReadyForMoreSamples(true);
+ }
+
+ GST_OBJECT_UNLOCK(source);
+}
+
namespace WTF {
template <> GRefPtr<WebKitMediaSrc> adoptGRef(WebKitMediaSrc* ptr)
{
Modified: trunk/Source/WebCore/platform/graphics/gstreamer/mse/WebKitMediaSourceGStreamer.h (260505 => 260506)
--- trunk/Source/WebCore/platform/graphics/gstreamer/mse/WebKitMediaSourceGStreamer.h 2020-04-22 10:19:30 UTC (rev 260505)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/mse/WebKitMediaSourceGStreamer.h 2020-04-22 11:36:27 UTC (rev 260506)
@@ -73,6 +73,7 @@
void webKitMediaSrcSetMediaPlayerPrivate(WebKitMediaSrc*, WebCore::MediaPlayerPrivateGStreamerMSE*);
void webKitMediaSrcPrepareSeek(WebKitMediaSrc*, const MediaTime&);
+void webKitMediaSrcPrepareInitialSeek(WebKitMediaSrc*, double rate, const MediaTime& startTime, const MediaTime& endTime);
void webKitMediaSrcSetReadyForSamples(WebKitMediaSrc*, bool);
G_END_DECLS