Title: [217045] trunk/Source/WebCore
Revision
217045
Author
[email protected]
Date
2017-05-18 07:05:15 -0700 (Thu, 18 May 2017)

Log Message

[GTK][GStreamer][MSE] Crash on youtube when MSE is enabled but gstreamer cant find the decoder element.
https://bugs.webkit.org/show_bug.cgi?id=167120

Patch by Vanessa Chipirrás Navalón <[email protected]> on 2017-05-18
Reviewed by Žan Doberšek.

This is because supportCodecs() doesn't check in runtime which plugins the player has.
So, a static function which returns a map with the plugins has been created. That map is later
used in the supportsCodecs() method to check if the requested codec matches any of the map.

* platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp:
(WebCore::MediaPlayerPrivateGStreamerBase::initializeGStreamerAndRegisterWebKitElements):
The declaration is moved into this class.
* platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp:
(WebCore::MediaPlayerPrivateGStreamer::isAvailable): This function calls the implementation of
initializeGstreamerAndRegisterWebKitElements function.
(WebCore::MediaPlayerPrivateGStreamer::load): Ditto
(WebCore::mimeTypeSet): Ditto
* platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.h: It is static type to expose
initializeGStreamerAndRegisterWebKitElements() function to be called from internal function
"which runs before MediaPlayerPrivateGStreamerBase initialization but needs to have GStreamer initialized".
* platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.cpp:
(WebCore::codecSet): It returns a map with the plugins has been created.
(WebCore::MediaPlayerPrivateGStreamerMSE::supportsCodecs): To check if the requested codec
matches any of the map from codecSet().

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (217044 => 217045)


--- trunk/Source/WebCore/ChangeLog	2017-05-18 12:56:46 UTC (rev 217044)
+++ trunk/Source/WebCore/ChangeLog	2017-05-18 14:05:15 UTC (rev 217045)
@@ -1,3 +1,30 @@
+2017-05-18  Vanessa Chipirrás Navalón  <[email protected]>
+
+        [GTK][GStreamer][MSE] Crash on youtube when MSE is enabled but gstreamer cant find the decoder element.
+        https://bugs.webkit.org/show_bug.cgi?id=167120
+
+        Reviewed by Žan Doberšek.
+
+        This is because supportCodecs() doesn't check in runtime which plugins the player has.
+        So, a static function which returns a map with the plugins has been created. That map is later
+        used in the supportsCodecs() method to check if the requested codec matches any of the map.
+
+        * platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp:
+        (WebCore::MediaPlayerPrivateGStreamerBase::initializeGStreamerAndRegisterWebKitElements):
+        The declaration is moved into this class.
+        * platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp:
+        (WebCore::MediaPlayerPrivateGStreamer::isAvailable): This function calls the implementation of
+        initializeGstreamerAndRegisterWebKitElements function.
+        (WebCore::MediaPlayerPrivateGStreamer::load): Ditto
+        (WebCore::mimeTypeSet): Ditto
+        * platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.h: It is static type to expose
+        initializeGStreamerAndRegisterWebKitElements() function to be called from internal function
+        "which runs before MediaPlayerPrivateGStreamerBase initialization but needs to have GStreamer initialized".
+        * platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.cpp:
+        (WebCore::codecSet): It returns a map with the plugins has been created.
+        (WebCore::MediaPlayerPrivateGStreamerMSE::supportsCodecs): To check if the requested codec
+        matches any of the map from codecSet().
+
 2017-05-18  Romain Bellessort  <[email protected]>
 
         [Readable Streams API] Align getDesiredSize with spec

Modified: trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp (217044 => 217045)


--- trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp	2017-05-18 12:56:46 UTC (rev 217044)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp	2017-05-18 14:05:15 UTC (rev 217045)
@@ -110,25 +110,9 @@
             getSupportedTypes, supportsType, nullptr, nullptr, nullptr, supportsKeySystem);
 }
 
-bool initializeGStreamerAndRegisterWebKitElements()
-{
-    if (!initializeGStreamer())
-        return false;
-
-    registerWebKitGStreamerElements();
-
-    GRefPtr<GstElementFactory> srcFactory = adoptGRef(gst_element_factory_find("webkitwebsrc"));
-    if (!srcFactory) {
-        GST_DEBUG_CATEGORY_INIT(webkit_media_player_debug, "webkitmediaplayer", 0, "WebKit media player");
-        gst_element_register(nullptr, "webkitwebsrc", GST_RANK_PRIMARY + 100, WEBKIT_TYPE_WEB_SRC);
-    }
-
-    return true;
-}
-
 bool MediaPlayerPrivateGStreamer::isAvailable()
 {
-    if (!initializeGStreamerAndRegisterWebKitElements())
+    if (!MediaPlayerPrivateGStreamerBase::initializeGStreamerAndRegisterWebKitElements())
         return false;
 
     GRefPtr<GstElementFactory> factory = adoptGRef(gst_element_factory_find("playbin"));
@@ -227,7 +211,7 @@
 
 void MediaPlayerPrivateGStreamer::load(const String& urlString)
 {
-    if (!initializeGStreamerAndRegisterWebKitElements())
+    if (!MediaPlayerPrivateGStreamerBase::initializeGStreamerAndRegisterWebKitElements())
         return;
 
     URL url(URL(), urlString);
@@ -1776,7 +1760,7 @@
 {
     static NeverDestroyed<HashSet<String, ASCIICaseInsensitiveHash>> mimeTypes = []()
     {
-        initializeGStreamerAndRegisterWebKitElements();
+        MediaPlayerPrivateGStreamerBase::initializeGStreamerAndRegisterWebKitElements();
         HashSet<String, ASCIICaseInsensitiveHash> set;
 
         GList* audioDecoderFactories = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_DECODER | GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO, GST_RANK_MARGINAL);

Modified: trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp (217044 => 217045)


--- trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp	2017-05-18 12:56:46 UTC (rev 217044)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp	2017-05-18 14:05:15 UTC (rev 217045)
@@ -129,6 +129,22 @@
 #endif
 }
 
+bool MediaPlayerPrivateGStreamerBase::initializeGStreamerAndRegisterWebKitElements()
+{
+    if (!initializeGStreamer())
+        return false;
+
+    registerWebKitGStreamerElements();
+
+    GRefPtr<GstElementFactory> srcFactory = adoptGRef(gst_element_factory_find("webkitwebsrc"));
+    if (!srcFactory) {
+        GST_DEBUG_CATEGORY_INIT(webkit_media_player_debug, "webkitmediaplayer", 0, "WebKit media player");
+        gst_element_register(0, "webkitwebsrc", GST_RANK_PRIMARY + 100, WEBKIT_TYPE_WEB_SRC);
+    }
+
+    return true;
+}
+
 static int greatestCommonDivisor(int a, int b)
 {
     while (b) {

Modified: trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.h (217044 => 217045)


--- trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.h	2017-05-18 12:56:46 UTC (rev 217044)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.h	2017-05-18 14:05:15 UTC (rev 217045)
@@ -75,7 +75,7 @@
     bool ensureGstGLContext();
     static GstContext* requestGLContext(const gchar* contextType, MediaPlayerPrivateGStreamerBase*);
 #endif
-
+    static bool initializeGStreamerAndRegisterWebKitElements();
     bool supportsMuting() const override { return true; }
     void setMuted(bool) override;
     bool muted() const;

Modified: trunk/Source/WebCore/platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.cpp (217044 => 217045)


--- trunk/Source/WebCore/platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.cpp	2017-05-18 12:56:46 UTC (rev 217044)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.cpp	2017-05-18 14:05:15 UTC (rev 217045)
@@ -48,7 +48,10 @@
 #include <gst/pbutils/pbutils.h>
 #include <gst/video/video.h>
 #include <wtf/Condition.h>
+#include <wtf/HashSet.h>
 #include <wtf/NeverDestroyed.h>
+#include <wtf/text/AtomicString.h>
+#include <wtf/text/AtomicStringHash.h>
 
 static const char* dumpReadyState(WebCore::MediaPlayer::ReadyState readyState)
 {
@@ -747,9 +750,84 @@
         m_playbackPipeline->reattachTrack(appendPipeline->sourceBufferPrivate(), newTrack);
 }
 
+const static HashSet<AtomicString>& codecSet()
+{
+    static NeverDestroyed<HashSet<AtomicString>> codecTypes = []()
+    {
+        MediaPlayerPrivateGStreamerBase::initializeGStreamerAndRegisterWebKitElements();
+        HashSet<AtomicString> set;
+
+        GList* audioDecoderFactories = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_DECODER | GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO, GST_RANK_MARGINAL);
+        GList* videoDecoderFactories = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_DECODER | GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO, GST_RANK_MARGINAL);
+
+        enum ElementType {
+            AudioDecoder = 0,
+            VideoDecoder
+        };
+        struct GstCapsWebKitMapping {
+            ElementType elementType;
+            const char* capsString;
+            Vector<AtomicString> webkitCodecs;
+        };
+
+        std::array<GstCapsWebKitMapping, 3> mapping = { {
+            { VideoDecoder, "video/x-h264,  profile="" constrained-baseline, baseline }", { "x-h264" } },
+            { VideoDecoder, "video/x-h264, stream-format=avc", { "avc*"} },
+            { VideoDecoder, "video/mpeg, mpegversion=(int){1,2}, systemstream=(boolean)false", { "mpeg" } }
+        } };
+
+        for (auto& current : mapping) {
+            GList* factories = nullptr;
+            switch (current.elementType) {
+            case AudioDecoder:
+                factories = audioDecoderFactories;
+                break;
+            case VideoDecoder:
+                factories = videoDecoderFactories;
+                break;
+            default:
+                g_assert_not_reached();
+                break;
+            }
+
+            g_assert_nonnull(factories);
+
+            if (gstRegistryHasElementForMediaType(factories, current.capsString) && factories != nullptr) {
+                if (!current.webkitCodecs.isEmpty()) {
+                    for (const auto& mimeType : current.webkitCodecs)
+                        set.add(mimeType);
+                } else
+                    set.add(AtomicString(current.capsString));
+            }
+        }
+
+        bool audioMpegSupported = false;
+        if (gstRegistryHasElementForMediaType(audioDecoderFactories, "audio/mpeg, mpegversion=(int)1, layer=(int)[1, 3]")) {
+            audioMpegSupported = true;
+            set.add(AtomicString("audio/mp3"));
+        }
+
+        if (gstRegistryHasElementForMediaType(audioDecoderFactories, "audio/mpeg, mpegversion=(int){2, 4}")) {
+            audioMpegSupported = true;
+            set.add(AtomicString("mp4a*"));
+        }
+
+        if (audioMpegSupported) {
+            set.add(AtomicString("audio/mpeg"));
+            set.add(AtomicString("audio/x-mpeg"));
+        }
+
+
+        gst_plugin_feature_list_free(audioDecoderFactories);
+        gst_plugin_feature_list_free(videoDecoderFactories);
+
+        return set;
+    }();
+    return codecTypes;
+}
+
 bool MediaPlayerPrivateGStreamerMSE::supportsCodecs(const String& codecs)
 {
-    static Vector<const char*> supportedCodecs = { "avc*", "mp4a*", "mpeg", "x-h264" };
     Vector<String> codecEntries;
     codecs.split(',', false, codecEntries);
 
@@ -762,8 +840,8 @@
             codec = codec.substring(slashIndex+1);
 
         const char* codecData = codec.utf8().data();
-        for (const auto& pattern : supportedCodecs) {
-            isCodecSupported = !fnmatch(pattern, codecData, 0);
+        for (const auto& pattern : codecSet()) {
+            isCodecSupported = !fnmatch(pattern.string().utf8().data(), codecData, 0);
             if (isCodecSupported)
                 break;
         }
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to