REGRESSION(r207879-207891): [GStreamer] Introduced many layout test failures and...
authoreocanha@igalia.com <eocanha@igalia.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 14 Dec 2016 11:16:23 +0000 (11:16 +0000)
committereocanha@igalia.com <eocanha@igalia.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 14 Dec 2016 11:16:23 +0000 (11:16 +0000)
https://bugs.webkit.org/show_bug.cgi?id=164022

Reviewed by Xabier Rodriguez-Calvar.

Source/WebCore:

Covered by existing tests.

* page/Settings.cpp:
Added new setting to disable GStreamer players, so the selection of
MockMediaPlayerMediaSource can be forced for some tests, just like
it's already being done for the AVFoundation player in Mac.
(WebCore::Settings::setGStreamerEnabled):
* page/Settings.h:
(WebCore::Settings::isGStreamerEnabled):
* platform/graphics/MediaPlayer.cpp:
(WebCore::buildMediaEnginesVector):
Don't register GStreamer players when they're disabled.
* platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp:
(WebCore::MediaPlayerPrivateGStreamer::durationMediaTime):
Use doubles instead of floats.
* platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h:
Use doubles instead of floats for m_durationAtEOS.
* platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp:
Don't reset m_sample on videoSink drain, it causes too many problems.
(WebCore::MediaPlayerPrivateGStreamerBase::createVideoSink):
* platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.h:
Removed unused methods.
* platform/graphics/gstreamer/VideoSinkGStreamer.cpp:
Keep releasing m_sample on drain, but don't report the event
externally via signal anymore. The base player private isn't
listening to it anymore.
(webkitVideoSinkEvent):
(webkit_video_sink_class_init):
* platform/graphics/gstreamer/mse/AppendPipeline.cpp:
(WebCore::AppendPipeline::parseDemuxerSrcPadCaps):
Check if the demuxer caps correspond to a supported codec.
(WebCore::AppendPipeline::didReceiveInitializationSegment):
Empty m_track is now legal and means unsupported codec.
(WebCore::AppendPipeline::connectDemuxerSrcPadToAppsinkFromAnyThread):
Warn about more than one stream, but "support" it by ignoring it using
a black hole probe.
(WebCore::AppendPipeline::connectDemuxerSrcPadToAppsink):
Also report the duration when it's detected for the first time. Invalid
stream types now mean that unsupported codecs have been detected.
Complete init segment processing in that case.
(WebCore::AppendPipeline::disconnectDemuxerSrcPadFromAppsinkFromAnyThread):
Disconnect black hole probe.
(WebCore::appendPipelineDemuxerBlackHolePadProbe): Ignore buffers.
(WebCore::appendPipelineDemuxerPadRemoved): New parameter used.
* platform/graphics/gstreamer/mse/AppendPipeline.h:
* platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.cpp:
(WebCore::MediaPlayerPrivateGStreamerMSE::supportsCodecs):
Check supported codecs by matching against wildcard expressions.
(WebCore::MediaPlayerPrivateGStreamerMSE::supportsType):
Check for supported codecs.
* platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.h:
New supportsCodecs() method.
* platform/graphics/gstreamer/mse/MediaSourceClientGStreamerMSE.cpp:
(WebCore::MediaSourceClientGStreamerMSE::resetParserState):
Implemented parser resetting by aborting the AppendPipeline.
* platform/graphics/gstreamer/mse/MediaSourceClientGStreamerMSE.h:
Added resetParserState().
* platform/graphics/gstreamer/mse/SourceBufferPrivateGStreamer.cpp:
(WebCore::SourceBufferPrivateGStreamer::resetParserState):
Implemented it.
* testing/Internals.cpp:
(WebCore::Internals::initializeMockMediaSource):
Disable the GStreamer players when initializing the mock media source,
like it's already done for the AVFoundation player to force the
selection of MockMediaPlayerMediaSource.

Source/WebKit2:

* Shared/WebPreferencesDefinitions.h:
New GStreamerEnabled preference, defaults to true.
* WebProcess/WebPage/WebPage.cpp: Ditto.
(WebKit::WebPage::updatePreferences):

Source/WTF:

* wtf/glib/GLibUtilities.h:
Added new macros to convert gulong to/from gpointer.

Tools:

* Scripts/webkitperl/FeatureList.pm:
  Re-enable MEDIA_SOURCE for the GTK+ port.

LayoutTests:

* media/media-source/media-source-resize-expected.txt:
Expect the resize event.
* media/media-source/media-source-resize.html:
The test now succeeds no matter if the dimension is reported after
processing the init-segment (GTK+ case) or after the media segment
is processed (Mac case).
* platform/gtk/TestExpectations:
Reenabled all the media/media-source tests except one.
* platform/gtk/media/media-source/media-source-resize-expected.txt:
Copied from LayoutTests/media/media-source/media-source-resize-expected.txt.
The right dimensions are received earlier than in Mac.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@209797 268f45cc-cd09-0410-ab3c-d52691b4dbfc

29 files changed:
LayoutTests/ChangeLog
LayoutTests/media/media-source/media-source-resize-expected.txt
LayoutTests/media/media-source/media-source-resize.html
LayoutTests/platform/gtk/TestExpectations
LayoutTests/platform/gtk/media/media-source/media-source-resize-expected.txt [new file with mode: 0644]
Source/WTF/ChangeLog
Source/WTF/wtf/glib/GLibUtilities.h
Source/WebCore/ChangeLog
Source/WebCore/page/Settings.cpp
Source/WebCore/page/Settings.h
Source/WebCore/platform/graphics/MediaPlayer.cpp
Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp
Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h
Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp
Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.h
Source/WebCore/platform/graphics/gstreamer/VideoSinkGStreamer.cpp
Source/WebCore/platform/graphics/gstreamer/mse/AppendPipeline.cpp
Source/WebCore/platform/graphics/gstreamer/mse/AppendPipeline.h
Source/WebCore/platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.cpp
Source/WebCore/platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.h
Source/WebCore/platform/graphics/gstreamer/mse/MediaSourceClientGStreamerMSE.cpp
Source/WebCore/platform/graphics/gstreamer/mse/MediaSourceClientGStreamerMSE.h
Source/WebCore/platform/graphics/gstreamer/mse/SourceBufferPrivateGStreamer.cpp
Source/WebCore/testing/Internals.cpp
Source/WebKit2/ChangeLog
Source/WebKit2/Shared/WebPreferencesDefinitions.h
Source/WebKit2/WebProcess/WebPage/WebPage.cpp
Tools/ChangeLog
Tools/Scripts/webkitperl/FeatureList.pm

index 7677308..31eccfd 100644 (file)
@@ -1,3 +1,22 @@
+2016-12-14  Enrique Ocaña González  <eocanha@igalia.com>
+
+        REGRESSION(r207879-207891): [GStreamer] Introduced many layout test failures and crashes, bots exiting early
+        https://bugs.webkit.org/show_bug.cgi?id=164022
+
+        Reviewed by Xabier Rodriguez-Calvar.
+
+        * media/media-source/media-source-resize-expected.txt:
+        Expect the resize event.
+        * media/media-source/media-source-resize.html:
+        The test now succeeds no matter if the dimension is reported after
+        processing the init-segment (GTK+ case) or after the media segment
+        is processed (Mac case).
+        * platform/gtk/TestExpectations:
+        Reenabled all the media/media-source tests except one.
+        * platform/gtk/media/media-source/media-source-resize-expected.txt:
+        Copied from LayoutTests/media/media-source/media-source-resize-expected.txt.
+        The right dimensions are received earlier than in Mac.
+
 2016-12-13  Yusuke Suzuki  <utatane.tea@gmail.com>
 
         ASSERTION FAILED: hasParserBlockingScript() seen with js/dom/modules/module-will-fire-beforeload.html
index 7df5566..06c86b3 100644 (file)
@@ -5,6 +5,7 @@ EVENT(sourceopen)
 RUN(source.duration = loader.duration())
 RUN(sourceBuffer = source.addSourceBuffer(loader.type()))
 RUN(sourceBuffer.appendBuffer(loader.initSegment()))
+EVENT(resize)
 EVENT(update)
 Append a media segment.
 RUN(sourceBuffer.appendBuffer(loader.mediaSegment(0)))
index a962d44..cf691e3 100644 (file)
@@ -32,6 +32,7 @@
         run('source.duration = loader.duration()');
         run('sourceBuffer = source.addSourceBuffer(loader.type())');
         waitForEventOn(sourceBuffer, 'update', sourceInitialized, false, true);
+        waitForEventOnce('resize', resize);
         run('sourceBuffer.appendBuffer(loader.initSegment())');
     }
 
     }
 
     function resize() {
-        testExpected('video.videoWidth', 640);
-        testExpected('video.videoHeight', 480);
-        endTest();
+        // First resize can be 0x0 (Mac) or 640x480 (GTK+)
+        if (video.videoWidth > 0 && video.videoHeight > 0) {
+            testExpected('video.videoWidth', 640);
+            testExpected('video.videoHeight', 480);
+            endTest();
+        }
     }
     </script>
 </head>
index 25245e7..4119c37 100644 (file)
@@ -231,9 +231,12 @@ webkit.org/b/61661 editing/pasteboard/drag-drop-list.html [ Failure ]
 # isProtocolHandlerRegistered() isn't supported yet.
 webkit.org/b/92749 fast/dom/NavigatorContentUtils/is-protocol-handler-registered.html [ Skip ]
 
-# Tests for MediaSource API. Feature is not totally functional.
+# Tests for MediaSource API. Webm is required by the tests but we don't support it.
 webkit.org/b/99065 imported/w3c/web-platform-tests/media-source/ [ Skip ]
 
+# We don't support multiple streams per sourcebuffer nor dynamic type changes (audio/video/text)
+webkit.org/b/165394 media/media-source/media-source-seek-detach-crash.html [ Skip ]
+
 # Encrypted Media Extensions are not enabled.
 webkit.org/b/99024 media/encrypted-media [ Skip ]
 webkit.org/b/99024 fast/events/constructors/media-key-event-constructor.html [ Timeout ]
@@ -2888,8 +2891,6 @@ webkit.org/b/160119 fast/css3-text/css3-text-decoration/repaint/underline-outsid
 
 webkit.org/b/160119 fast/css3-text/css3-text-justify/text-justify-last-line-simple-line-layout.html [ ImageOnlyFailure ]
 
-webkit.org/b/164022 media/media-source [ Skip ]
-
 #////////////////////////////////////////////////////////////////////////////////////////
 # End of tests failing due to THREADED COMPOSITOR enablement. Don't put random test
 # failures here. See the top of the file for where to put new expectations.
diff --git a/LayoutTests/platform/gtk/media/media-source/media-source-resize-expected.txt b/LayoutTests/platform/gtk/media/media-source/media-source-resize-expected.txt
new file mode 100644 (file)
index 0000000..5c4ffae
--- /dev/null
@@ -0,0 +1,12 @@
+This tests the ability of the SourceBuffer to reset the parser after an abort(). A SourceBuffer in this state should be able to accept a new initialization segment or a new media segment.
+
+RUN(video.src = URL.createObjectURL(source))
+EVENT(sourceopen)
+RUN(source.duration = loader.duration())
+RUN(sourceBuffer = source.addSourceBuffer(loader.type()))
+RUN(sourceBuffer.appendBuffer(loader.initSegment()))
+EVENT(resize)
+EXPECTED (video.videoWidth == '640') OK
+EXPECTED (video.videoHeight == '480') OK
+END OF TEST
+
index 89bbfff..f2ec842 100644 (file)
@@ -1,3 +1,13 @@
+2016-12-14  Enrique Ocaña González  <eocanha@igalia.com>
+
+        REGRESSION(r207879-207891): [GStreamer] Introduced many layout test failures and crashes, bots exiting early
+        https://bugs.webkit.org/show_bug.cgi?id=164022
+
+        Reviewed by Xabier Rodriguez-Calvar.
+
+        * wtf/glib/GLibUtilities.h:
+        Added new macros to convert gulong to/from gpointer.
+
 2016-12-14  Gavin Barraclough  <barraclough@apple.com>
 
         MarkedBlock::marksConveyLivenessDuringMarking should take into account collection scope
index 7357824..da22596 100644 (file)
 
 CString getCurrentExecutablePath();
 
+// These might be added to glib in the future, but in the meantime they're defined here.
+#ifndef GULONG_TO_POINTER
+#define GULONG_TO_POINTER(ul) ((gpointer) (gulong) (ul))
+#endif
+
+#ifndef GPOINTER_TO_ULONG
+#define GPOINTER_TO_ULONG(p) ((gulong) (p))
+#endif
+
 #endif
index 2c7144f..5566f39 100644 (file)
@@ -1,5 +1,78 @@
 2016-12-14  Enrique Ocaña González  <eocanha@igalia.com>
 
+        REGRESSION(r207879-207891): [GStreamer] Introduced many layout test failures and crashes, bots exiting early
+        https://bugs.webkit.org/show_bug.cgi?id=164022
+
+        Reviewed by Xabier Rodriguez-Calvar.
+
+        Covered by existing tests.
+
+        * page/Settings.cpp:
+        Added new setting to disable GStreamer players, so the selection of
+        MockMediaPlayerMediaSource can be forced for some tests, just like
+        it's already being done for the AVFoundation player in Mac.
+        (WebCore::Settings::setGStreamerEnabled):
+        * page/Settings.h:
+        (WebCore::Settings::isGStreamerEnabled):
+        * platform/graphics/MediaPlayer.cpp:
+        (WebCore::buildMediaEnginesVector):
+        Don't register GStreamer players when they're disabled.
+        * platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp:
+        (WebCore::MediaPlayerPrivateGStreamer::durationMediaTime):
+        Use doubles instead of floats.
+        * platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h:
+        Use doubles instead of floats for m_durationAtEOS.
+        * platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp:
+        Don't reset m_sample on videoSink drain, it causes too many problems.
+        (WebCore::MediaPlayerPrivateGStreamerBase::createVideoSink):
+        * platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.h:
+        Removed unused methods.
+        * platform/graphics/gstreamer/VideoSinkGStreamer.cpp:
+        Keep releasing m_sample on drain, but don't report the event
+        externally via signal anymore. The base player private isn't
+        listening to it anymore.
+        (webkitVideoSinkEvent):
+        (webkit_video_sink_class_init):
+        * platform/graphics/gstreamer/mse/AppendPipeline.cpp:
+        (WebCore::AppendPipeline::parseDemuxerSrcPadCaps):
+        Check if the demuxer caps correspond to a supported codec.
+        (WebCore::AppendPipeline::didReceiveInitializationSegment):
+        Empty m_track is now legal and means unsupported codec.
+        (WebCore::AppendPipeline::connectDemuxerSrcPadToAppsinkFromAnyThread):
+        Warn about more than one stream, but "support" it by ignoring it using
+        a black hole probe.
+        (WebCore::AppendPipeline::connectDemuxerSrcPadToAppsink):
+        Also report the duration when it's detected for the first time. Invalid
+        stream types now mean that unsupported codecs have been detected.
+        Complete init segment processing in that case.
+        (WebCore::AppendPipeline::disconnectDemuxerSrcPadFromAppsinkFromAnyThread):
+        Disconnect black hole probe.
+        (WebCore::appendPipelineDemuxerBlackHolePadProbe): Ignore buffers.
+        (WebCore::appendPipelineDemuxerPadRemoved): New parameter used.
+        * platform/graphics/gstreamer/mse/AppendPipeline.h:
+        * platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.cpp:
+        (WebCore::MediaPlayerPrivateGStreamerMSE::supportsCodecs):
+        Check supported codecs by matching against wildcard expressions.
+        (WebCore::MediaPlayerPrivateGStreamerMSE::supportsType):
+        Check for supported codecs.
+        * platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.h:
+        New supportsCodecs() method.
+        * platform/graphics/gstreamer/mse/MediaSourceClientGStreamerMSE.cpp:
+        (WebCore::MediaSourceClientGStreamerMSE::resetParserState):
+        Implemented parser resetting by aborting the AppendPipeline.
+        * platform/graphics/gstreamer/mse/MediaSourceClientGStreamerMSE.h:
+        Added resetParserState().
+        * platform/graphics/gstreamer/mse/SourceBufferPrivateGStreamer.cpp:
+        (WebCore::SourceBufferPrivateGStreamer::resetParserState):
+        Implemented it.
+        * testing/Internals.cpp:
+        (WebCore::Internals::initializeMockMediaSource):
+        Disable the GStreamer players when initializing the mock media source,
+        like it's already done for the AVFoundation player to force the
+        selection of MockMediaPlayerMediaSource.
+
+2016-12-14  Enrique Ocaña González  <eocanha@igalia.com>
+
         [GStreamer][MSE] Fix player private selection when MSE is enabled
         https://bugs.webkit.org/show_bug.cgi?id=164116
 
index 1dd02d4..6bb9d03 100644 (file)
@@ -83,6 +83,10 @@ bool Settings::gAVFoundationNSURLSessionEnabled = true;
 bool Settings::gQTKitEnabled = false;
 #endif
 
+#if USE(GSTREAMER)
+bool Settings::gGStreamerEnabled = true;
+#endif
+
 bool Settings::gMockScrollbarsEnabled = false;
 bool Settings::gUsesOverlayScrollbars = false;
 bool Settings::gMockScrollAnimatorEnabled = false;
@@ -582,6 +586,17 @@ void Settings::setQTKitEnabled(bool enabled)
 }
 #endif
 
+#if USE(GSTREAMER)
+void Settings::setGStreamerEnabled(bool enabled)
+{
+    if (gGStreamerEnabled == enabled)
+        return;
+
+    gGStreamerEnabled = enabled;
+    HTMLMediaElement::resetMediaEngines();
+}
+#endif
+
 #if ENABLE(MEDIA_STREAM)
 bool Settings::mockCaptureDevicesEnabled()
 {
index 0a957ef..2c29916 100644 (file)
@@ -218,6 +218,11 @@ public:
     static bool isQTKitEnabled() { return false; }
 #endif
 
+#if USE(GSTREAMER)
+    WEBCORE_EXPORT static void setGStreamerEnabled(bool flag);
+    static bool isGStreamerEnabled() { return gGStreamerEnabled; }
+#endif
+
     static const unsigned defaultMaximumHTMLParserDOMTreeDepth = 512;
     static const unsigned defaultMaximumRenderTreeDepth = 512;
 
@@ -376,6 +381,10 @@ private:
     WEBCORE_EXPORT static bool gQTKitEnabled;
 #endif
 
+#if USE(GSTREAMER)
+    WEBCORE_EXPORT static bool gGStreamerEnabled;
+#endif
+
     static bool gMockScrollbarsEnabled;
     static bool gUsesOverlayScrollbars;
     static bool gMockScrollAnimatorEnabled;
index 0dc88c7..9aa6509 100644 (file)
@@ -225,15 +225,20 @@ static void buildMediaEnginesVector()
 
 
 #if ENABLE(MEDIA_STREAM) && USE(GSTREAMER) && USE(OPENWEBRTC)
-    MediaPlayerPrivateGStreamerOwr::registerMediaEngine(addMediaEngine);
+    if (Settings::isGStreamerEnabled())
+        MediaPlayerPrivateGStreamerOwr::registerMediaEngine(addMediaEngine);
 #endif
 
 #if defined(PlatformMediaEngineClassName)
-    PlatformMediaEngineClassName::registerMediaEngine(addMediaEngine);
+#if USE(GSTREAMER)
+    if (Settings::isGStreamerEnabled())
+#endif
+        PlatformMediaEngineClassName::registerMediaEngine(addMediaEngine);
 #endif
 
 #if ENABLE(VIDEO) && USE(GSTREAMER) && ENABLE(MEDIA_SOURCE) && ENABLE(VIDEO_TRACK)
-    MediaPlayerPrivateGStreamerMSE::registerMediaEngine(addMediaEngine);
+    if (Settings::isGStreamerEnabled())
+        MediaPlayerPrivateGStreamerMSE::registerMediaEngine(addMediaEngine);
 #endif
 
     haveMediaEnginesVector() = true;
index b66e29b..7b54f77 100644 (file)
@@ -427,7 +427,7 @@ MediaTime MediaPlayerPrivateGStreamer::durationMediaTime() const
         return { };
 
     if (m_durationAtEOS)
-        return MediaTime::createWithFloat(m_durationAtEOS);
+        return MediaTime::createWithDouble(m_durationAtEOS);
 
     // The duration query would fail on a not-prerolled pipeline.
     if (GST_STATE(m_pipeline.get()) < GST_STATE_PAUSED)
index 18cbaaf..27a6198 100644 (file)
@@ -180,7 +180,7 @@ protected:
     bool m_errorOccured;
     mutable bool m_isEndReached;
     mutable bool m_isStreaming;
-    mutable gfloat m_durationAtEOS;
+    mutable gdouble m_durationAtEOS;
     bool m_paused;
     float m_playbackRate;
     GstState m_requestedState;
index 3e7c254..2441ae1 100644 (file)
@@ -684,23 +684,11 @@ void MediaPlayerPrivateGStreamerBase::triggerRepaint(GstSample* sample)
 #endif
 }
 
-void MediaPlayerPrivateGStreamerBase::triggerDrain()
-{
-    WTF::GMutexLocker<GMutex> lock(m_sampleMutex);
-    m_videoSize = FloatSize();
-    m_sample = nullptr;
-}
-
 void MediaPlayerPrivateGStreamerBase::repaintCallback(MediaPlayerPrivateGStreamerBase* player, GstSample* sample)
 {
     player->triggerRepaint(sample);
 }
 
-void MediaPlayerPrivateGStreamerBase::drainCallback(MediaPlayerPrivateGStreamerBase* player)
-{
-    player->triggerDrain();
-}
-
 #if USE(GSTREAMER_GL)
 GstFlowReturn MediaPlayerPrivateGStreamerBase::newSampleCallback(GstElement* sink, MediaPlayerPrivateGStreamerBase* player)
 {
@@ -1036,7 +1024,6 @@ GstElement* MediaPlayerPrivateGStreamerBase::createVideoSink()
         m_usingFallbackVideoSink = true;
         m_videoSink = webkitVideoSinkNew();
         g_signal_connect_swapped(m_videoSink.get(), "repaint-requested", G_CALLBACK(repaintCallback), this);
-        g_signal_connect_swapped(m_videoSink.get(), "drain", G_CALLBACK(drainCallback), this);
     }
 
     GstElement* videoSink = nullptr;
index 3e8275d..5136b64 100644 (file)
@@ -166,12 +166,9 @@ protected:
 
     virtual bool handleSyncMessage(GstMessage*);
 
-    void triggerDrain();
-
     void triggerRepaint(GstSample*);
     void repaint();
 
-    static void drainCallback(MediaPlayerPrivateGStreamerBase*);
     static void repaintCallback(MediaPlayerPrivateGStreamerBase*, GstSample*);
 
     void notifyPlayerOfVolumeChange();
index d181ecf..1fae7c7 100644 (file)
@@ -58,7 +58,6 @@ GST_DEBUG_CATEGORY_STATIC(webkitVideoSinkDebug);
 
 enum {
     REPAINT_REQUESTED,
-    DRAIN,
     LAST_SIGNAL
 };
 
@@ -355,21 +354,6 @@ static gboolean webkitVideoSinkProposeAllocation(GstBaseSink* baseSink, GstQuery
     return TRUE;
 }
 
-static gboolean webkitVideoSinkQuery(GstBaseSink* baseSink, GstQuery* query)
-{
-    WebKitVideoSink* sink = WEBKIT_VIDEO_SINK(baseSink);
-
-    switch (GST_QUERY_TYPE(query)) {
-    case GST_QUERY_DRAIN:
-        GST_OBJECT_LOCK(sink);
-        g_signal_emit(sink, webkitVideoSinkSignals[DRAIN], 0);
-        GST_OBJECT_UNLOCK(sink);
-        return TRUE;
-    default:
-        return GST_CALL_PARENT_WITH_DEFAULT(GST_BASE_SINK_CLASS, query, (baseSink, query), TRUE);
-    }
-}
-
 static gboolean webkitVideoSinkEvent(GstBaseSink* baseSink, GstEvent* event)
 {
     switch (GST_EVENT_TYPE(event)) {
@@ -377,11 +361,7 @@ static gboolean webkitVideoSinkEvent(GstBaseSink* baseSink, GstEvent* event)
         WebKitVideoSink* sink = WEBKIT_VIDEO_SINK(baseSink);
         sink->priv->scheduler.drain();
 
-        GST_DEBUG_OBJECT(sink, "Flush-start, emitting DRAIN signal and releasing m_sample");
-
-        GST_OBJECT_LOCK(sink);
-        g_signal_emit(sink, webkitVideoSinkSignals[DRAIN], 0);
-        GST_OBJECT_UNLOCK(sink);
+        GST_DEBUG_OBJECT(sink, "Flush-start, releasing m_sample");
         }
         FALLTHROUGH;
     default:
@@ -410,7 +390,6 @@ static void webkit_video_sink_class_init(WebKitVideoSinkClass* klass)
     baseSinkClass->start = webkitVideoSinkStart;
     baseSinkClass->set_caps = webkitVideoSinkSetCaps;
     baseSinkClass->propose_allocation = webkitVideoSinkProposeAllocation;
-    baseSinkClass->query = webkitVideoSinkQuery;
     baseSinkClass->event = webkitVideoSinkEvent;
 
     webkitVideoSinkSignals[REPAINT_REQUESTED] = g_signal_new("repaint-requested",
@@ -423,16 +402,6 @@ static void webkit_video_sink_class_init(WebKitVideoSinkClass* klass)
             G_TYPE_NONE, // Return type
             1, // Only one parameter
             GST_TYPE_SAMPLE);
-
-    webkitVideoSinkSignals[DRAIN] = g_signal_new("drain",
-        G_TYPE_FROM_CLASS(klass),
-        static_cast<GSignalFlags>(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
-        0, // Class offset.
-        0, // Accumulator.
-        0, // Accumulator data.
-        g_cclosure_marshal_generic,
-        G_TYPE_NONE, // Return type.
-        0); // No parameters.
 }
 
 
index 597964e..ce0d51b 100644 (file)
@@ -39,6 +39,7 @@
 #include <gst/pbutils/pbutils.h>
 #include <gst/video/video.h>
 #include <wtf/Condition.h>
+#include <wtf/glib/GLibUtilities.h>
 
 namespace WebCore {
 
@@ -74,6 +75,7 @@ static GstPadProbeReturn appendPipelineAppsrcDataLeaving(GstPad*, GstPadProbeInf
 #if !LOG_DISABLED
 static GstPadProbeReturn appendPipelinePadProbeDebugInformation(GstPad*, GstPadProbeInfo*, struct PadProbeInformation*);
 #endif
+static GstPadProbeReturn appendPipelineDemuxerBlackHolePadProbe(GstPad*, GstPadProbeInfo*, gpointer);
 static GstFlowReturn appendPipelineAppsinkNewSample(GstElement*, AppendPipeline*);
 static void appendPipelineAppsinkEOS(GstElement*, AppendPipeline*);
 
@@ -530,7 +532,10 @@ void AppendPipeline::parseDemuxerSrcPadCaps(GstCaps* demuxerSrcPadCaps)
 
         const gchar* originalMediaType = gst_structure_get_string(structure, "original-media-type");
 
-        if (g_str_has_prefix(originalMediaType, "video/")) {
+        if (!MediaPlayerPrivateGStreamerMSE::supportsCodecs(originalMediaType)) {
+            m_presentationSize = WebCore::FloatSize();
+            m_streamType = WebCore::MediaSourceStreamTypeGStreamer::Invalid;
+        } else if (g_str_has_prefix(originalMediaType, "video/")) {
             int width = 0;
             int height = 0;
             float finalHeight = 0;
@@ -560,7 +565,10 @@ void AppendPipeline::parseDemuxerSrcPadCaps(GstCaps* demuxerSrcPadCaps)
         const char* structureName = gst_structure_get_name(structure);
         GstVideoInfo info;
 
-        if (g_str_has_prefix(structureName, "video/") && gst_video_info_from_caps(&info, demuxerSrcPadCaps)) {
+        if (!MediaPlayerPrivateGStreamerMSE::supportsCodecs(structureName)) {
+            m_presentationSize = WebCore::FloatSize();
+            m_streamType = WebCore::MediaSourceStreamTypeGStreamer::Invalid;
+        } else if (g_str_has_prefix(structureName, "video/") && gst_video_info_from_caps(&info, demuxerSrcPadCaps)) {
             float width, height;
 
             width = info.width;
@@ -704,8 +712,9 @@ void AppendPipeline::didReceiveInitializationSegment()
 
     WebCore::SourceBufferPrivateClient::InitializationSegment initializationSegment;
 
-    GST_DEBUG("Notifying SourceBuffer for track %s", m_track->id().string().utf8().data());
+    GST_DEBUG("Notifying SourceBuffer for track %s", (m_track) ? m_track->id().string().utf8().data() : nullptr);
     initializationSegment.duration = m_mediaSourceClient->duration();
+
     switch (m_streamType) {
     case Audio: {
         WebCore::SourceBufferPrivateClient::InitializationSegment::AudioTrackInformation info;
@@ -722,8 +731,7 @@ void AppendPipeline::didReceiveInitializationSegment()
         break;
     }
     default:
-        GST_ERROR("Unsupported or unknown stream type");
-        ASSERT_NOT_REACHED();
+        GST_ERROR("Unsupported stream type or codec");
         break;
     }
 
@@ -871,6 +879,13 @@ void AppendPipeline::connectDemuxerSrcPadToAppsinkFromAnyThread(GstPad* demuxerS
 
     GST_DEBUG("connecting to appsink");
 
+    if (m_demux->numsrcpads > 1) {
+        GST_WARNING("Only one stream per SourceBuffer is allowed! Ignoring stream %d by adding a black hole probe.", m_demux->numsrcpads);
+        gulong probeId = gst_pad_add_probe(demuxerSrcPad, GST_PAD_PROBE_TYPE_BUFFER, reinterpret_cast<GstPadProbeCallback>(appendPipelineDemuxerBlackHolePadProbe), nullptr, nullptr);
+        g_object_set_data(G_OBJECT(demuxerSrcPad), "blackHoleProbeId", GULONG_TO_POINTER(probeId));
+        return;
+    }
+
     GRefPtr<GstPad> appsinkSinkPad = adoptGRef(gst_element_get_static_pad(m_appsink.get(), "sink"));
 
     // Only one stream per demuxer is supported.
@@ -959,7 +974,8 @@ void AppendPipeline::connectDemuxerSrcPadToAppsink(GstPad* demuxerSrcPad)
     }
 #endif
 
-    if (m_initialDuration > m_mediaSourceClient->duration())
+    if (m_initialDuration > m_mediaSourceClient->duration()
+        || (m_mediaSourceClient->duration().isInvalid() && m_initialDuration > MediaTime::zeroTime()))
         m_mediaSourceClient->durationChanged(m_initialDuration);
 
     m_oldTrack = m_track;
@@ -978,6 +994,18 @@ void AppendPipeline::connectDemuxerSrcPadToAppsink(GstPad* demuxerSrcPad)
     case WebCore::MediaSourceStreamTypeGStreamer::Text:
         m_track = WebCore::InbandTextTrackPrivateGStreamer::create(id(), sinkSinkPad.get());
         break;
+    case WebCore::MediaSourceStreamTypeGStreamer::Invalid:
+        {
+            GUniquePtr<gchar> strcaps(gst_caps_to_string(caps.get()));
+            GST_DEBUG("Unsupported track codec: %s", strcaps.get());
+        }
+        // This is going to cause an error which will detach the SourceBuffer and tear down this
+        // AppendPipeline, so we need the padAddRemove lock released before continuing.
+        m_track = nullptr;
+        m_padAddRemoveCondition.notifyOne();
+        locker.unlockEarly();
+        didReceiveInitializationSegment();
+        return;
     default:
         // No useful data, but notify anyway to complete the append operation.
         GST_DEBUG("Received all pending samples (no data)");
@@ -988,11 +1016,22 @@ void AppendPipeline::connectDemuxerSrcPadToAppsink(GstPad* demuxerSrcPad)
     m_padAddRemoveCondition.notifyOne();
 }
 
-void AppendPipeline::disconnectDemuxerSrcPadFromAppsinkFromAnyThread()
+void AppendPipeline::disconnectDemuxerSrcPadFromAppsinkFromAnyThread(GstPad* demuxerSrcPad)
 {
+    // Must be done in the thread we were called from (usually streaming thread).
+    if (!gst_pad_is_linked(demuxerSrcPad)) {
+        gulong probeId = GPOINTER_TO_ULONG(g_object_get_data(G_OBJECT(demuxerSrcPad), "blackHoleProbeId"));
+        if (probeId) {
+            GST_DEBUG("Disconnecting black hole probe.");
+            g_object_set_data(G_OBJECT(demuxerSrcPad), "blackHoleProbeId", nullptr);
+            gst_pad_remove_probe(demuxerSrcPad, probeId);
+        } else
+            GST_WARNING("Not disconnecting demuxer src pad because it wasn't linked");
+        return;
+    }
+
     GST_DEBUG("Disconnecting appsink");
 
-    // Must be done in the thread we were called from (usually streaming thread).
 #if ENABLE(LEGACY_ENCRYPTED_MEDIA)
     if (m_decryptor) {
         gst_element_unlink(m_decryptor.get(), m_appsink.get());
@@ -1036,6 +1075,14 @@ static GstPadProbeReturn appendPipelinePadProbeDebugInformation(GstPad*, GstPadP
 }
 #endif
 
+static GstPadProbeReturn appendPipelineDemuxerBlackHolePadProbe(GstPad*, GstPadProbeInfo* info, gpointer)
+{
+    ASSERT(GST_PAD_PROBE_INFO_TYPE(info) & GST_PAD_PROBE_TYPE_BUFFER);
+    GstBuffer* buffer = GST_PAD_PROBE_INFO_BUFFER(info);
+    GST_TRACE("buffer of size %" G_GSIZE_FORMAT " ignored", gst_buffer_get_size(buffer));
+    return GST_PAD_PROBE_DROP;
+}
+
 static void appendPipelineAppsrcNeedData(GstAppSrc*, guint, AppendPipeline* appendPipeline)
 {
     appendPipeline->reportAppsrcNeedDataReceived();
@@ -1046,9 +1093,9 @@ static void appendPipelineDemuxerPadAdded(GstElement*, GstPad* demuxerSrcPad, Ap
     appendPipeline->connectDemuxerSrcPadToAppsinkFromAnyThread(demuxerSrcPad);
 }
 
-static void appendPipelineDemuxerPadRemoved(GstElement*, GstPad*, AppendPipeline* appendPipeline)
+static void appendPipelineDemuxerPadRemoved(GstElement*, GstPad* demuxerSrcPad, AppendPipeline* appendPipeline)
 {
-    appendPipeline->disconnectDemuxerSrcPadFromAppsinkFromAnyThread();
+    appendPipeline->disconnectDemuxerSrcPadFromAppsinkFromAnyThread(demuxerSrcPad);
 }
 
 static GstFlowReturn appendPipelineAppsinkNewSample(GstElement* appsink, AppendPipeline* appendPipeline)
index c8a48ca..0248315 100644 (file)
@@ -77,7 +77,7 @@ public:
     RefPtr<WebCore::TrackPrivateBase> track() { return m_track; }
     WebCore::MediaSourceStreamTypeGStreamer streamType() { return m_streamType; }
 
-    void disconnectDemuxerSrcPadFromAppsinkFromAnyThread();
+    void disconnectDemuxerSrcPadFromAppsinkFromAnyThread(GstPad*);
     void connectDemuxerSrcPadToAppsinkFromAnyThread(GstPad*);
     void connectDemuxerSrcPadToAppsink(GstPad*);
 
index 76aee72..13b26f4 100644 (file)
@@ -41,6 +41,7 @@
 #include "URL.h"
 #include "VideoTrackPrivateGStreamer.h"
 
+#include <fnmatch.h>
 #include <gst/app/gstappsink.h>
 #include <gst/app/gstappsrc.h>
 #include <gst/gst.h>
@@ -749,6 +750,32 @@ void MediaPlayerPrivateGStreamerMSE::trackDetected(RefPtr<AppendPipeline> append
         m_playbackPipeline->reattachTrack(appendPipeline->sourceBufferPrivate(), newTrack);
 }
 
+bool MediaPlayerPrivateGStreamerMSE::supportsCodecs(const String& codecs)
+{
+    static Vector<const char*> supportedCodecs = { "avc*", "mp4a*", "mpeg", "x-h264" };
+    Vector<String> codecEntries;
+    codecs.split(',', false, codecEntries);
+
+    for (String codec : codecEntries) {
+        bool isCodecSupported = false;
+
+        // If the codec is named like a mimetype (eg: video/avc) remove the "video/" part.
+        size_t slashIndex = codec.find('/');
+        if (slashIndex != WTF::notFound)
+            codec = codec.substring(slashIndex+1);
+
+        const char* codecData = codec.utf8().data();
+        for (const auto& pattern : supportedCodecs) {
+            if (isCodecSupported = !fnmatch(pattern, codecData, 0))
+                break;
+        }
+        if (!isCodecSupported)
+            return false;
+    }
+
+    return true;
+}
+
 MediaPlayer::SupportsType MediaPlayerPrivateGStreamerMSE::supportsType(const MediaEngineSupportParameters& parameters)
 {
     MediaPlayer::SupportsType result = MediaPlayer::IsNotSupported;
@@ -766,8 +793,12 @@ MediaPlayer::SupportsType MediaPlayerPrivateGStreamerMSE::supportsType(const Med
     }
 
     // Spec says we should not return "probably" if the codecs string is empty.
-    if (mimeTypeCache().contains(parameters.type))
-        result = parameters.codecs.isEmpty() ? MediaPlayer::MayBeSupported : MediaPlayer::IsSupported;
+    if (mimeTypeCache().contains(parameters.type)) {
+        if (parameters.codecs.isEmpty())
+            result = MediaPlayer::MayBeSupported;
+        else
+            result = supportsCodecs(parameters.codecs) ? MediaPlayer::IsSupported : MediaPlayer::IsNotSupported;
+    }
 
     return extendedSupportsType(parameters, result);
 }
index 040439f..0d3ebb9 100644 (file)
@@ -87,6 +87,8 @@ public:
     void trackDetected(RefPtr<AppendPipeline>, RefPtr<WebCore::TrackPrivateBase> oldTrack, RefPtr<WebCore::TrackPrivateBase> newTrack);
     void notifySeekNeedsDataForTime(const MediaTime&);
 
+    static bool supportsCodecs(const String& codecs);
+
 private:
     static void getSupportedTypes(HashSet<String, ASCIICaseInsensitiveHash>&);
     static MediaPlayer::SupportsType supportsType(const MediaEngineSupportParameters&);
index 96fc65b..ac8e787 100644 (file)
@@ -104,6 +104,22 @@ void MediaSourceClientGStreamerMSE::abort(RefPtr<SourceBufferPrivateGStreamer> s
     appendPipeline->abort();
 }
 
+void MediaSourceClientGStreamerMSE::resetParserState(RefPtr<SourceBufferPrivateGStreamer> sourceBufferPrivate)
+{
+    ASSERT(WTF::isMainThread());
+
+    GST_DEBUG("resetting parser state");
+
+    if (!m_playerPrivate)
+        return;
+
+    RefPtr<AppendPipeline> appendPipeline = m_playerPrivate->m_appendPipelinesMap.get(sourceBufferPrivate);
+
+    ASSERT(appendPipeline);
+
+    appendPipeline->abort();
+}
+
 bool MediaSourceClientGStreamerMSE::append(RefPtr<SourceBufferPrivateGStreamer> sourceBufferPrivate, const unsigned char* data, unsigned length)
 {
     ASSERT(WTF::isMainThread());
index 618736b..c3d4ac7 100644 (file)
@@ -47,6 +47,7 @@ public:
 
     // From SourceBufferPrivateGStreamer.
     void abort(RefPtr<SourceBufferPrivateGStreamer>);
+    void resetParserState(RefPtr<SourceBufferPrivateGStreamer>);
     bool append(RefPtr<SourceBufferPrivateGStreamer>, const unsigned char*, unsigned);
     void removedFromMediaSource(RefPtr<SourceBufferPrivateGStreamer>);
     void flush(AtomicString);
index c701e03..7f545ee 100644 (file)
@@ -86,7 +86,7 @@ void SourceBufferPrivateGStreamer::abort()
 
 void SourceBufferPrivateGStreamer::resetParserState()
 {
-    notImplemented();
+    m_client->resetParserState(this);
 }
 
 void SourceBufferPrivateGStreamer::removedFromMediaSource()
index 2863c7d..3b72b89 100644 (file)
@@ -2693,6 +2693,9 @@ void Internals::initializeMockMediaSource()
 #if USE(AVFOUNDATION)
     WebCore::Settings::setAVFoundationEnabled(false);
 #endif
+#if USE(GSTREAMER)
+    WebCore::Settings::setGStreamerEnabled(false);
+#endif
     MediaPlayerFactorySupport::callRegisterMediaEngine(MockMediaPlayerMediaSource::registerMediaEngine);
 }
 
index 42d3e5a..5af27b5 100644 (file)
@@ -1,3 +1,15 @@
+2016-12-14  Enrique Ocaña González  <eocanha@igalia.com>
+
+        REGRESSION(r207879-207891): [GStreamer] Introduced many layout test failures and crashes, bots exiting early
+        https://bugs.webkit.org/show_bug.cgi?id=164022
+
+        Reviewed by Xabier Rodriguez-Calvar.
+
+        * Shared/WebPreferencesDefinitions.h:
+        New GStreamerEnabled preference, defaults to true.
+        * WebProcess/WebPage/WebPage.cpp: Ditto.
+        (WebKit::WebPage::updatePreferences):
+
 2016-12-13  Commit Queue  <commit-queue@webkit.org>
 
         Unreviewed, rolling out r209792.
index cd53a65..490a3a1 100644 (file)
     macro(AllowFileAccessFromFileURLs, allowFileAccessFromFileURLs, Bool, bool, false, "", "") \
     macro(AVFoundationEnabled, isAVFoundationEnabled, Bool, bool, true, "", "") \
     macro(AVFoundationNSURLSessionEnabled, isAVFoundationNSURLSessionEnabled, Bool, bool, true, "", "") \
+    macro(GStreamerEnabled, isGStreamerEnabled, Bool, bool, true, "", "") \
     macro(RequiresUserGestureForMediaPlayback, requiresUserGestureForMediaPlayback, Bool, bool, false, "", "") \
     macro(RequiresUserGestureForVideoPlayback, requiresUserGestureForVideoPlayback, Bool, bool, false, "", "") \
     macro(RequiresUserGestureForAudioPlayback, requiresUserGestureForAudioPlayback, Bool, bool, DEFAULT_REQUIRES_USER_GESTURE_FOR_AUDIO_PLAYBACK, "", "") \
index 0e204a1..02950a2 100644 (file)
@@ -3020,6 +3020,10 @@ void WebPage::updatePreferences(const WebPreferencesStore& store)
     settings.setAVFoundationNSURLSessionEnabled(store.getBoolValueForKey(WebPreferencesKey::isAVFoundationNSURLSessionEnabledKey()));
 #endif
 
+#if USE(GSTREAMER)
+    settings.setGStreamerEnabled(store.getBoolValueForKey(WebPreferencesKey::isGStreamerEnabledKey()));
+#endif
+
 #if PLATFORM(COCOA)
     settings.setQTKitEnabled(store.getBoolValueForKey(WebPreferencesKey::isQTKitEnabledKey()));
 #endif
index 69672c2..12cf00a 100644 (file)
@@ -1,3 +1,13 @@
+2016-12-14  Enrique Ocaña González  <eocanha@igalia.com>
+
+        REGRESSION(r207879-207891): [GStreamer] Introduced many layout test failures and crashes, bots exiting early
+        https://bugs.webkit.org/show_bug.cgi?id=164022
+
+        Reviewed by Xabier Rodriguez-Calvar.
+
+        * Scripts/webkitperl/FeatureList.pm:
+          Re-enable MEDIA_SOURCE for the GTK+ port.
+
 2016-12-13  Alex Christensen  <achristensen@webkit.org>
 
         Fix CMake build.
index 09d5b4d..1db9d09 100644 (file)
@@ -334,7 +334,7 @@ my @features = (
       define => "ENABLE_MEDIA_CAPTURE", default => isEfl(), value => \$mediaCaptureSupport },
 
     { option => "media-source", desc => "Toggle Media Source support",
-      define => "ENABLE_MEDIA_SOURCE", default => 0, value => \$mediaSourceSupport },
+      define => "ENABLE_MEDIA_SOURCE", default => isGtk(), value => \$mediaSourceSupport },
 
     { option => "media-statistics", desc => "Toggle Media Statistics support",
       define => "ENABLE_MEDIA_STATISTICS", default => 0, value => \$mediaStatisticsSupport },