Title: [241585] trunk/Source/WebCore
Revision
241585
Author
[email protected]
Date
2019-02-15 06:24:21 -0800 (Fri, 15 Feb 2019)

Log Message

Decoding media-capabilities configuration initial support https://bugs.webkit.org/show_bug.cgi?id=191191

Reviewed by Xabier Rodriguez-Calvar.

This patch enables basic platform probing for GStreamer decoders,
optionally using Hardware decoding capabilities. The previous code
for decoders/demuxers probing partially duplicated between the MSE
player and its parent class was moved to a new module called
GStreamerRegistryScanner. There is one instance of it for the MSE player
and one for the parent class.

The scanner can check for the presence of the GstElement Hardware
metadata classifier in decoders and thus advise the
MediaEngineConfigurationFactoryGStreamer that hardware decoding is
supported or not. This is only a first step though. The scanner
should also probably attempt a NULL->READY transition on decoders
to validate specific input caps are supported. As this might
require changes in GStreamer, this part of the patch wasn't
included.

This patch is covered by the existing media tests.

* platform/GStreamer.cmake: New files.
* platform/graphics/MediaPlayer.cpp: Add support for converting
SupportsType enum to string.
(WebCore::convertEnumerationToString):
* platform/graphics/MediaPlayer.h: Ditto.
* platform/graphics/MediaPlayerEnums.h: Ditto.
* platform/graphics/gstreamer/GStreamerCommon.cpp: Move
gstRegistryHasElementForMediaType to GStreamerRegistryScanner.
* platform/graphics/gstreamer/GStreamerCommon.h: Ditto.
* platform/graphics/gstreamer/GStreamerRegistryScanner.cpp: Added.
(WebCore::GStreamerRegistryScanner::singleton):
(WebCore::GStreamerRegistryScanner::GStreamerRegistryScanner): Initialize
supported mime-types and codecs from the GStreamer registry.
(WebCore::GStreamerRegistryScanner::~GStreamerRegistryScanner): Free the element factories.
(WebCore::GStreamerRegistryScanner::gstRegistryHasElementForMediaType):
Check the input caps are supported, optionally using hardware
device.
(WebCore::GStreamerRegistryScanner::fillMimeTypeSetFromCapsMapping):
Moved from MediaPlayerPrivateGStreamer{,MSE}.
(WebCore::GStreamerRegistryScanner::initialize): Ditto.
(WebCore::GStreamerRegistryScanner::supportsCodec const): Ditto.
(WebCore::GStreamerRegistryScanner::supportsAllCodecs const): Ditto.
(WebCore::GStreamerRegistryScanner::isDecodingSupported const): Check
the given configuration is supported. For now hardware support is
checked for video configurations only as it is quite uncommon
anyway to have hardware-enabled audio decoders.
* platform/graphics/gstreamer/GStreamerRegistryScanner.h: Added.
(WebCore::GStreamerRegistryScanner::mimeTypeSet):
(WebCore::GStreamerRegistryScanner::supportsContainerType const):
(WebCore::GStreamerRegistryScanner::RegistryLookupResult::operator bool const):
* platform/graphics/gstreamer/MediaEngineConfigurationFactoryGStreamer.cpp: Added.
(WebCore::createMediaPlayerDecodingConfigurationGStreamer):
* platform/graphics/gstreamer/MediaEngineConfigurationFactoryGStreamer.h: Added.
* platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp:
Rely on new GStreamerRegistryScanner and add some debugging macros.
(WebCore::MediaPlayerPrivateGStreamer::getSupportedTypes):
(WebCore::MediaPlayerPrivateGStreamer::supportsType):
* platform/graphics/gstreamer/mse/AppendPipeline.cpp: Ditto. Also
plug qtdemux for AAC containers, this is an explicit consequence
of finer-grained codecs probing.
(WebCore::AppendPipeline::AppendPipeline):
(WebCore::AppendPipeline::parseDemuxerSrcPadCaps):
* platform/graphics/gstreamer/mse/GStreamerRegistryScannerMSE.cpp: Added.
(WebCore::GStreamerRegistryScannerMSE::singleton):
(WebCore::GStreamerRegistryScannerMSE::GStreamerRegistryScannerMSE):
* platform/graphics/gstreamer/mse/GStreamerRegistryScannerMSE.h: Added.
* platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.cpp:
Rely on new GStreamerRegistryScanner and add some debugging macros.
(WebCore::MediaPlayerPrivateGStreamerMSE::getSupportedTypes):
(WebCore::MediaPlayerPrivateGStreamerMSE::supportsType):
* platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.h:
* platform/mediacapabilities/MediaEngineConfigurationFactory.cpp:
(WebCore::factories): GStreamer support.

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (241584 => 241585)


--- trunk/Source/WebCore/ChangeLog	2019-02-15 13:49:48 UTC (rev 241584)
+++ trunk/Source/WebCore/ChangeLog	2019-02-15 14:24:21 UTC (rev 241585)
@@ -1,3 +1,82 @@
+2019-02-15  Philippe Normand  <[email protected]>
+
+        [GStreamer] Decoding media-capabilities configuration initial support
+        https://bugs.webkit.org/show_bug.cgi?id=191191
+
+        Reviewed by Xabier Rodriguez-Calvar.
+
+        This patch enables basic platform probing for GStreamer decoders,
+        optionally using Hardware decoding capabilities. The previous code
+        for decoders/demuxers probing partially duplicated between the MSE
+        player and its parent class was moved to a new module called
+        GStreamerRegistryScanner. There is one instance of it for the MSE player
+        and one for the parent class.
+
+        The scanner can check for the presence of the GstElement Hardware
+        metadata classifier in decoders and thus advise the
+        MediaEngineConfigurationFactoryGStreamer that hardware decoding is
+        supported or not. This is only a first step though. The scanner
+        should also probably attempt a NULL->READY transition on decoders
+        to validate specific input caps are supported. As this might
+        require changes in GStreamer, this part of the patch wasn't
+        included.
+
+        This patch is covered by the existing media tests.
+
+        * platform/GStreamer.cmake: New files.
+        * platform/graphics/MediaPlayer.cpp: Add support for converting
+        SupportsType enum to string.
+        (WebCore::convertEnumerationToString):
+        * platform/graphics/MediaPlayer.h: Ditto.
+        * platform/graphics/MediaPlayerEnums.h: Ditto.
+        * platform/graphics/gstreamer/GStreamerCommon.cpp: Move
+        gstRegistryHasElementForMediaType to GStreamerRegistryScanner.
+        * platform/graphics/gstreamer/GStreamerCommon.h: Ditto.
+        * platform/graphics/gstreamer/GStreamerRegistryScanner.cpp: Added.
+        (WebCore::GStreamerRegistryScanner::singleton):
+        (WebCore::GStreamerRegistryScanner::GStreamerRegistryScanner): Initialize
+        supported mime-types and codecs from the GStreamer registry.
+        (WebCore::GStreamerRegistryScanner::~GStreamerRegistryScanner): Free the element factories.
+        (WebCore::GStreamerRegistryScanner::gstRegistryHasElementForMediaType):
+        Check the input caps are supported, optionally using hardware
+        device.
+        (WebCore::GStreamerRegistryScanner::fillMimeTypeSetFromCapsMapping):
+        Moved from MediaPlayerPrivateGStreamer{,MSE}.
+        (WebCore::GStreamerRegistryScanner::initialize): Ditto.
+        (WebCore::GStreamerRegistryScanner::supportsCodec const): Ditto.
+        (WebCore::GStreamerRegistryScanner::supportsAllCodecs const): Ditto.
+        (WebCore::GStreamerRegistryScanner::isDecodingSupported const): Check
+        the given configuration is supported. For now hardware support is
+        checked for video configurations only as it is quite uncommon
+        anyway to have hardware-enabled audio decoders.
+        * platform/graphics/gstreamer/GStreamerRegistryScanner.h: Added.
+        (WebCore::GStreamerRegistryScanner::mimeTypeSet):
+        (WebCore::GStreamerRegistryScanner::supportsContainerType const):
+        (WebCore::GStreamerRegistryScanner::RegistryLookupResult::operator bool const):
+        * platform/graphics/gstreamer/MediaEngineConfigurationFactoryGStreamer.cpp: Added.
+        (WebCore::createMediaPlayerDecodingConfigurationGStreamer):
+        * platform/graphics/gstreamer/MediaEngineConfigurationFactoryGStreamer.h: Added.
+        * platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp:
+        Rely on new GStreamerRegistryScanner and add some debugging macros.
+        (WebCore::MediaPlayerPrivateGStreamer::getSupportedTypes):
+        (WebCore::MediaPlayerPrivateGStreamer::supportsType):
+        * platform/graphics/gstreamer/mse/AppendPipeline.cpp: Ditto. Also
+        plug qtdemux for AAC containers, this is an explicit consequence
+        of finer-grained codecs probing.
+        (WebCore::AppendPipeline::AppendPipeline):
+        (WebCore::AppendPipeline::parseDemuxerSrcPadCaps):
+        * platform/graphics/gstreamer/mse/GStreamerRegistryScannerMSE.cpp: Added.
+        (WebCore::GStreamerRegistryScannerMSE::singleton):
+        (WebCore::GStreamerRegistryScannerMSE::GStreamerRegistryScannerMSE):
+        * platform/graphics/gstreamer/mse/GStreamerRegistryScannerMSE.h: Added.
+        * platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.cpp:
+        Rely on new GStreamerRegistryScanner and add some debugging macros.
+        (WebCore::MediaPlayerPrivateGStreamerMSE::getSupportedTypes):
+        (WebCore::MediaPlayerPrivateGStreamerMSE::supportsType):
+        * platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.h:
+        * platform/mediacapabilities/MediaEngineConfigurationFactory.cpp:
+        (WebCore::factories): GStreamer support.
+
 2019-02-14  Joseph Pecoraro  <[email protected]>
 
         Web Inspector: Occasional crash under WebCore::CSSStyleSheet::item called from Inspector

Modified: trunk/Source/WebCore/platform/GStreamer.cmake (241584 => 241585)


--- trunk/Source/WebCore/platform/GStreamer.cmake	2019-02-15 13:49:48 UTC (rev 241584)
+++ trunk/Source/WebCore/platform/GStreamer.cmake	2019-02-15 14:24:21 UTC (rev 241585)
@@ -10,7 +10,9 @@
         platform/graphics/gstreamer/GRefPtrGStreamer.cpp
         platform/graphics/gstreamer/GStreamerCommon.cpp
         platform/graphics/gstreamer/GstAllocatorFastMalloc.cpp
+        platform/graphics/gstreamer/GStreamerRegistryScanner.cpp
         platform/graphics/gstreamer/InbandTextTrackPrivateGStreamer.cpp
+        platform/graphics/gstreamer/MediaEngineConfigurationFactoryGStreamer.cpp
         platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp
         platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp
         platform/graphics/gstreamer/MediaSampleGStreamer.cpp
@@ -26,6 +28,7 @@
 
         platform/graphics/gstreamer/mse/AppendPipeline.cpp
         platform/graphics/gstreamer/mse/GStreamerMediaDescription.cpp
+        platform/graphics/gstreamer/mse/GStreamerRegistryScannerMSE.cpp
         platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.cpp
         platform/graphics/gstreamer/mse/MediaSourceClientGStreamerMSE.cpp
         platform/graphics/gstreamer/mse/MediaSourceGStreamer.cpp

Modified: trunk/Source/WebCore/platform/graphics/MediaPlayer.cpp (241584 => 241585)


--- trunk/Source/WebCore/platform/graphics/MediaPlayer.cpp	2019-02-15 13:49:48 UTC (rev 241584)
+++ trunk/Source/WebCore/platform/graphics/MediaPlayer.cpp	2019-02-15 14:24:21 UTC (rev 241585)
@@ -1618,6 +1618,20 @@
     return values[static_cast<size_t>(enumerationValue)];
 }
 
+String convertEnumerationToString(MediaPlayerEnums::SupportsType enumerationValue)
+{
+    static const NeverDestroyed<String> values[] = {
+        MAKE_STATIC_STRING_IMPL("IsNotSupported"),
+        MAKE_STATIC_STRING_IMPL("IsSupported"),
+        MAKE_STATIC_STRING_IMPL("MayBeSupported"),
+    };
+    static_assert(!static_cast<size_t>(MediaPlayerEnums::IsNotSupported), "MediaPlayerEnums::IsNotSupported is not 0 as expected");
+    static_assert(static_cast<size_t>(MediaPlayerEnums::IsSupported) == 1, "MediaPlayerEnums::IsSupported is not 1 as expected");
+    static_assert(static_cast<size_t>(MediaPlayerEnums::MayBeSupported) == 2, "MediaPlayerEnums::MayBeSupported is not 2 as expected");
+    ASSERT(static_cast<size_t>(enumerationValue) < WTF_ARRAY_LENGTH(values));
+    return values[static_cast<size_t>(enumerationValue)];
 }
 
+}
+
 #endif

Modified: trunk/Source/WebCore/platform/graphics/MediaPlayer.h (241584 => 241585)


--- trunk/Source/WebCore/platform/graphics/MediaPlayer.h	2019-02-15 13:49:48 UTC (rev 241584)
+++ trunk/Source/WebCore/platform/graphics/MediaPlayer.h	2019-02-15 14:24:21 UTC (rev 241585)
@@ -253,8 +253,8 @@
     void invalidate();
 
     // Media engine support.
-    enum SupportsType { IsNotSupported, IsSupported, MayBeSupported };
-    static MediaPlayer::SupportsType supportsType(const MediaEngineSupportParameters&);
+    using MediaPlayerEnums::SupportsType;
+    static SupportsType supportsType(const MediaEngineSupportParameters&);
     static void getSupportedTypes(HashSet<String, ASCIICaseInsensitiveHash>&);
     static bool isAvailable();
     static HashSet<RefPtr<SecurityOrigin>> originsInMediaCache(const String& path);

Modified: trunk/Source/WebCore/platform/graphics/MediaPlayerEnums.h (241584 => 241585)


--- trunk/Source/WebCore/platform/graphics/MediaPlayerEnums.h	2019-02-15 13:49:48 UTC (rev 241584)
+++ trunk/Source/WebCore/platform/graphics/MediaPlayerEnums.h	2019-02-15 14:24:21 UTC (rev 241585)
@@ -36,6 +36,7 @@
     enum MovieLoadType { Unknown, Download, StoredStream, LiveStream };
     enum Preload { None, MetaData, Auto };
     enum VideoGravity { VideoGravityResize, VideoGravityResizeAspect, VideoGravityResizeAspectFill };
+    enum SupportsType { IsNotSupported, IsSupported, MayBeSupported };
     enum {
         VideoFullscreenModeNone = 0,
         VideoFullscreenModeStandard = 1 << 0,
@@ -47,6 +48,7 @@
 WTF::String convertEnumerationToString(MediaPlayerEnums::ReadyState);
 WTF::String convertEnumerationToString(MediaPlayerEnums::NetworkState);
 WTF::String convertEnumerationToString(MediaPlayerEnums::Preload);
+WTF::String convertEnumerationToString(MediaPlayerEnums::SupportsType);
 
 } // namespace WebCore
 

Modified: trunk/Source/WebCore/platform/graphics/gstreamer/GStreamerCommon.cpp (241584 => 241585)


--- trunk/Source/WebCore/platform/graphics/gstreamer/GStreamerCommon.cpp	2019-02-15 13:49:48 UTC (rev 241584)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/GStreamerCommon.cpp	2019-02-15 14:24:21 UTC (rev 241585)
@@ -302,16 +302,6 @@
     return time.timeValue();
 }
 
-bool gstRegistryHasElementForMediaType(GList* elementFactories, const char* capsString)
-{
-    GRefPtr<GstCaps> caps = adoptGRef(gst_caps_from_string(capsString));
-    GList* candidates = gst_element_factory_list_filter(elementFactories, caps.get(), GST_PAD_SINK, false);
-    bool result = candidates;
-
-    gst_plugin_feature_list_free(candidates);
-    return result;
-}
-
 static void simpleBusMessageCallback(GstBus*, GstMessage* message, GstBin* pipeline)
 {
     switch (GST_MESSAGE_TYPE(message)) {

Modified: trunk/Source/WebCore/platform/graphics/gstreamer/GStreamerCommon.h (241584 => 241585)


--- trunk/Source/WebCore/platform/graphics/gstreamer/GStreamerCommon.h	2019-02-15 13:49:48 UTC (rev 241584)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/GStreamerCommon.h	2019-02-15 14:24:21 UTC (rev 241585)
@@ -216,7 +216,6 @@
 };
 
 
-bool gstRegistryHasElementForMediaType(GList* elementFactories, const char* capsString);
 void connectSimpleBusMessageCallback(GstElement* pipeline);
 void disconnectSimpleBusMessageCallback(GstElement* pipeline);
 

Added: trunk/Source/WebCore/platform/graphics/gstreamer/GStreamerRegistryScanner.cpp (0 => 241585)


--- trunk/Source/WebCore/platform/graphics/gstreamer/GStreamerRegistryScanner.cpp	                        (rev 0)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/GStreamerRegistryScanner.cpp	2019-02-15 14:24:21 UTC (rev 241585)
@@ -0,0 +1,335 @@
+/*
+ * Copyright (C) 2019 Igalia S.L
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * aint with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "GStreamerRegistryScanner.h"
+
+#if USE(GSTREAMER)
+#include "ContentType.h"
+#include "GStreamerCommon.h"
+#include <fnmatch.h>
+#include <wtf/PrintStream.h>
+
+namespace WebCore {
+
+GST_DEBUG_CATEGORY_STATIC(webkit_media_gst_registry_scanner_debug);
+#define GST_CAT_DEFAULT webkit_media_gst_registry_scanner_debug
+
+GStreamerRegistryScanner& GStreamerRegistryScanner::singleton()
+{
+    static NeverDestroyed<GStreamerRegistryScanner> sharedInstance;
+    return sharedInstance;
+}
+
+GStreamerRegistryScanner::GStreamerRegistryScanner(bool isMediaSource)
+    : m_isMediaSource(isMediaSource)
+{
+    GST_DEBUG_CATEGORY_INIT(webkit_media_gst_registry_scanner_debug, "webkitregistryscanner", 0, "WebKit GStreamer registry scanner");
+    m_audioDecoderFactories = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_DECODER | GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO, GST_RANK_MARGINAL);
+    m_audioParserFactories = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_PARSER | GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO, GST_RANK_NONE);
+    m_videoDecoderFactories = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_DECODER | GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO, GST_RANK_MARGINAL);
+    m_videoParserFactories = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_PARSER | GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO, GST_RANK_MARGINAL);
+    m_demuxerFactories = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_DEMUXER, GST_RANK_MARGINAL);
+
+    initialize();
+#ifndef GST_DISABLE_GST_DEBUG
+    GST_DEBUG("%s registry scanner initialized", m_isMediaSource ? "MSE" : "Regular playback");
+    for (auto& mimeType : m_mimeTypeSet)
+        GST_DEBUG("Mime-type registered: %s", mimeType.utf8().data());
+    for (auto& item : m_codecMap)
+        GST_DEBUG("%s codec pattern registered: %s", item.value ? "Hardware" : "Software", item.key.string().utf8().data());
+#endif
+}
+
+GStreamerRegistryScanner::~GStreamerRegistryScanner()
+{
+    gst_plugin_feature_list_free(m_audioDecoderFactories);
+    gst_plugin_feature_list_free(m_audioParserFactories);
+    gst_plugin_feature_list_free(m_videoDecoderFactories);
+    gst_plugin_feature_list_free(m_videoParserFactories);
+    gst_plugin_feature_list_free(m_demuxerFactories);
+}
+
+GStreamerRegistryScanner::RegistryLookupResult GStreamerRegistryScanner::hasElementForMediaType(GList* elementFactories, const char* capsString, bool shouldCheckHardwareClassifier)
+{
+    GRefPtr<GstCaps> caps = adoptGRef(gst_caps_from_string(capsString));
+    GList* candidates = gst_element_factory_list_filter(elementFactories, caps.get(), GST_PAD_SINK, false);
+    bool isSupported = candidates;
+    bool isUsingHardware = false;
+
+    if (shouldCheckHardwareClassifier) {
+        for (GList* factories = candidates; factories; factories = g_list_next(factories)) {
+            auto* factory = reinterpret_cast<GstElementFactory*>(factories->data);
+            String metadata = gst_element_factory_get_metadata(factory, GST_ELEMENT_METADATA_KLASS);
+            auto components = metadata.split('/');
+            if (components.contains("Hardware")) {
+                isUsingHardware = true;
+                break;
+            }
+        }
+    }
+
+    gst_plugin_feature_list_free(candidates);
+#ifndef GST_DISABLE_GST_DEBUG
+    const char* elementType = "";
+    if (elementFactories == m_audioParserFactories)
+        elementType = "Audio parser";
+    else if (elementFactories == m_audioDecoderFactories)
+        elementType = "Audio decoder";
+    else if (elementFactories == m_videoParserFactories)
+        elementType = "Video parser";
+    else if (elementFactories == m_videoDecoderFactories)
+        elementType = "Video decoder";
+    else if (elementFactories == m_demuxerFactories)
+        elementType = "Demuxer";
+    else
+        ASSERT_NOT_REACHED();
+    GST_LOG("%s lookup result for caps %" GST_PTR_FORMAT " : isSupported=%s, isUsingHardware=%s", elementType, caps.get(), boolForPrinting(isSupported), boolForPrinting(isUsingHardware));
+#endif
+    return GStreamerRegistryScanner::RegistryLookupResult { isSupported, isUsingHardware };
+}
+
+void GStreamerRegistryScanner::fillMimeTypeSetFromCapsMapping(Vector<GstCapsWebKitMapping>& mapping)
+{
+    for (auto& current : mapping) {
+        GList* factories;
+        switch (current.elementType) {
+        case Demuxer:
+            factories = m_demuxerFactories;
+            break;
+        case AudioDecoder:
+            factories = m_audioDecoderFactories;
+            break;
+        case VideoDecoder:
+            factories = m_videoDecoderFactories;
+            break;
+        }
+
+        if (hasElementForMediaType(factories, current.capsString)) {
+            if (!current.webkitCodecPatterns.isEmpty()) {
+                for (const auto& pattern : current.webkitCodecPatterns)
+                    m_codecMap.add(pattern, false);
+            }
+            if (!current.webkitMimeTypes.isEmpty()) {
+                for (const auto& mimeType : current.webkitMimeTypes)
+                    m_mimeTypeSet.add(mimeType);
+            } else
+                m_mimeTypeSet.add(AtomicString(current.capsString));
+        }
+    }
+}
+
+void GStreamerRegistryScanner::initialize()
+{
+    if (hasElementForMediaType(m_audioDecoderFactories, "audio/mpeg, mpegversion=(int)4")) {
+        m_mimeTypeSet.add(AtomicString("audio/aac"));
+        m_mimeTypeSet.add(AtomicString("audio/mp4"));
+        m_mimeTypeSet.add(AtomicString("audio/x-m4a"));
+        m_codecMap.add(AtomicString("mpeg"), false);
+        m_codecMap.add(AtomicString("mp4a*"), false);
+    }
+
+    auto opusSupported = hasElementForMediaType(m_audioDecoderFactories, "audio/x-opus");
+    if (opusSupported && (!m_isMediaSource || hasElementForMediaType(m_audioParserFactories, "audio/x-opus"))) {
+        m_mimeTypeSet.add(AtomicString("audio/opus"));
+        m_codecMap.add(AtomicString("opus"), false);
+        m_codecMap.add(AtomicString("x-opus"), false);
+    }
+
+    auto vorbisSupported = hasElementForMediaType(m_audioDecoderFactories, "audio/x-vorbis");
+    if (vorbisSupported && (!m_isMediaSource || hasElementForMediaType(m_audioParserFactories, "audio/x-vorbis"))) {
+        m_codecMap.add(AtomicString("vorbis"), false);
+        m_codecMap.add(AtomicString("x-vorbis"), false);
+    }
+
+    if (hasElementForMediaType(m_demuxerFactories, "video/x-matroska")) {
+        auto vp8DecoderAvailable = hasElementForMediaType(m_videoDecoderFactories, "video/x-vp8", true);
+        auto vp9DecoderAvailable = hasElementForMediaType(m_videoDecoderFactories, "video/x-vp9", true);
+
+        if (vp8DecoderAvailable || vp9DecoderAvailable)
+            m_mimeTypeSet.add(AtomicString("video/webm"));
+
+        if (vp8DecoderAvailable) {
+            m_codecMap.add(AtomicString("vp8"), vp8DecoderAvailable.isUsingHardware);
+            m_codecMap.add(AtomicString("x-vp8"), vp8DecoderAvailable.isUsingHardware);
+        }
+        if (vp9DecoderAvailable) {
+            m_codecMap.add(AtomicString("vp9"), vp9DecoderAvailable.isUsingHardware);
+            m_codecMap.add(AtomicString("x-vp9"), vp9DecoderAvailable.isUsingHardware);
+        }
+        if (opusSupported)
+            m_mimeTypeSet.add(AtomicString("audio/webm"));
+    }
+
+    auto h264DecoderAvailable = hasElementForMediaType(m_videoDecoderFactories, "video/x-h264, profile="" constrained-baseline, baseline, high }", true);
+    if (h264DecoderAvailable && (!m_isMediaSource || hasElementForMediaType(m_videoParserFactories, "video/x-h264"))) {
+        m_mimeTypeSet.add(AtomicString("video/mp4"));
+        m_mimeTypeSet.add(AtomicString("video/x-m4v"));
+        m_codecMap.add(AtomicString("x-h264"), h264DecoderAvailable.isUsingHardware);
+        m_codecMap.add(AtomicString("avc*"), h264DecoderAvailable.isUsingHardware);
+        m_codecMap.add(AtomicString("mp4v*"), h264DecoderAvailable.isUsingHardware);
+    }
+
+    if (m_isMediaSource)
+        return;
+
+    // The mime-types initialized below are not supported by the MSE backend.
+
+    Vector<GstCapsWebKitMapping> mapping = {
+        {AudioDecoder, "audio/midi", {"audio/midi", "audio/riff-midi"}, { }},
+        {AudioDecoder, "audio/x-ac3", { }, { }},
+        {AudioDecoder, "audio/x-dts", { }, { }},
+        {AudioDecoder, "audio/x-eac3", {"audio/x-ac3"}, { }},
+        {AudioDecoder, "audio/x-flac", {"audio/x-flac", "audio/flac"}, { }},
+        {AudioDecoder, "audio/x-sbc", { }, { }},
+        {AudioDecoder, "audio/x-sid", { }, { }},
+        {AudioDecoder, "audio/x-speex", {"audio/speex", "audio/x-speex"}, { }},
+        {AudioDecoder, "audio/x-wavpack", {"audio/x-wavpack"}, { }},
+        {VideoDecoder, "video/mpeg, mpegversion=(int){1,2}, systemstream=(boolean)false", {"video/mpeg"}, {"mpeg"}},
+        {VideoDecoder, "video/mpegts", { }, { }},
+        {VideoDecoder, "video/x-dirac", { }, { }},
+        {VideoDecoder, "video/x-flash-video", {"video/flv", "video/x-flv"}, { }},
+        {VideoDecoder, "video/x-h263", { }, { }},
+        {VideoDecoder, "video/x-msvideocodec", {"video/x-msvideo"}, { }},
+        {Demuxer, "application/vnd.rn-realmedia", { }, { }},
+        {Demuxer, "application/x-3gp", { }, { }},
+        {Demuxer, "application/x-hls", {"application/vnd.apple.mpegurl", "application/x-mpegurl"}, { }},
+        {Demuxer, "application/x-pn-realaudio", { }, { }},
+        {Demuxer, "audio/x-aiff", { }, { }},
+        {Demuxer, "audio/x-wav", {"audio/x-wav", "audio/wav", "audio/vnd.wave"}, {"1"}},
+        {Demuxer, "video/quicktime", { }, { }},
+        {Demuxer, "video/quicktime, variant=(string)3gpp", {"video/3gpp"}, { }},
+        {Demuxer, "video/x-ms-asf", { }, { }},
+    };
+    fillMimeTypeSetFromCapsMapping(mapping);
+
+    if (hasElementForMediaType(m_demuxerFactories, "application/ogg")) {
+        m_mimeTypeSet.add(AtomicString("application/ogg"));
+
+        if (vorbisSupported) {
+            m_mimeTypeSet.add(AtomicString("audio/ogg"));
+            m_mimeTypeSet.add(AtomicString("audio/x-vorbis+ogg"));
+        }
+
+        if (hasElementForMediaType(m_audioDecoderFactories, "audio/x-speex")) {
+            m_mimeTypeSet.add(AtomicString("audio/ogg"));
+            m_codecMap.add(AtomicString("speex"), false);
+        }
+
+        if (hasElementForMediaType(m_videoDecoderFactories, "video/x-theora")) {
+            m_mimeTypeSet.add(AtomicString("video/ogg"));
+            m_codecMap.add(AtomicString("theora"), false);
+        }
+    }
+
+    bool audioMpegSupported = false;
+    if (hasElementForMediaType(m_audioDecoderFactories, "audio/mpeg, mpegversion=(int)1, layer=(int)[1, 3]")) {
+        audioMpegSupported = true;
+        m_mimeTypeSet.add(AtomicString("audio/mp1"));
+        m_mimeTypeSet.add(AtomicString("audio/mp3"));
+        m_mimeTypeSet.add(AtomicString("audio/x-mp3"));
+        m_codecMap.add(AtomicString("audio/mp3"), false);
+    }
+
+    if (hasElementForMediaType(m_audioDecoderFactories, "audio/mpeg, mpegversion=(int)2")) {
+        audioMpegSupported = true;
+        m_mimeTypeSet.add(AtomicString("audio/mp2"));
+    }
+
+    audioMpegSupported |= isContainerTypeSupported("audio/mp4");
+    if (audioMpegSupported) {
+        m_mimeTypeSet.add(AtomicString("audio/mpeg"));
+        m_mimeTypeSet.add(AtomicString("audio/x-mpeg"));
+    }
+
+    bool matroskaSupported = hasElementForMediaType(m_demuxerFactories, "video/x-matroska");
+    if (matroskaSupported) {
+        m_mimeTypeSet.add(AtomicString("video/x-matroska"));
+
+        if (hasElementForMediaType(m_videoDecoderFactories, "video/x-vp10"))
+            m_mimeTypeSet.add(AtomicString("video/webm"));
+    }
+
+    if ((matroskaSupported || isContainerTypeSupported("video/mp4")) && hasElementForMediaType(m_videoDecoderFactories, "video/x-av1"))
+        m_codecMap.add(AtomicString("av01*"), false);
+}
+
+bool GStreamerRegistryScanner::isCodecSupported(String codec, bool shouldCheckForHardwareUse) const
+{
+    // 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);
+
+    bool supported = false;
+    for (const auto& item : m_codecMap) {
+        if (!fnmatch(item.key.string().utf8().data(), codec.utf8().data(), 0)) {
+            supported = shouldCheckForHardwareUse ? item.value : true;
+            if (supported)
+                break;
+        }
+    }
+
+    GST_LOG("Checked %s codec \"%s\" supported %s", shouldCheckForHardwareUse ? "hardware" : "software", codec.utf8().data(), boolForPrinting(supported));
+    return supported;
+}
+
+bool GStreamerRegistryScanner::areAllCodecsSupported(const Vector<String>& codecs, bool shouldCheckForHardwareUse) const
+{
+    for (String codec : codecs) {
+        if (!isCodecSupported(codec, shouldCheckForHardwareUse))
+            return false;
+    }
+
+    return true;
+}
+
+GStreamerRegistryScanner::RegistryLookupResult GStreamerRegistryScanner::isDecodingSupported(MediaConfiguration& configuration) const
+{
+    bool isSupported = false;
+    bool isUsingHardware = false;
+
+    if (configuration.video) {
+        auto& videoConfiguration = configuration.video.value();
+        GST_DEBUG("Checking support for video configuration: \"%s\" size: %ux%u bitrate: %" G_GUINT64_FORMAT " framerate: %f",
+            videoConfiguration.contentType.utf8().data(),
+            videoConfiguration.width, videoConfiguration.height,
+            videoConfiguration.bitrate, videoConfiguration.framerate);
+
+        auto contentType = ContentType(videoConfiguration.contentType);
+        isSupported = isContainerTypeSupported(contentType.containerType());
+        auto codecs = contentType.codecs();
+        if (!codecs.isEmpty())
+            isUsingHardware = areAllCodecsSupported(codecs, true);
+    }
+
+    if (configuration.audio) {
+        auto& audioConfiguration = configuration.audio.value();
+        GST_DEBUG("Checking support for audio configuration: \"%s\" %s channels, bitrate: %" G_GUINT64_FORMAT " samplerate: %u",
+            audioConfiguration.contentType.utf8().data(), audioConfiguration.channels.utf8().data(),
+            audioConfiguration.bitrate, audioConfiguration.samplerate);
+        auto contentType = ContentType(audioConfiguration.contentType);
+        isSupported = isContainerTypeSupported(contentType.containerType());
+    }
+
+    return GStreamerRegistryScanner::RegistryLookupResult { isSupported, isUsingHardware };
+}
+
+}
+#endif

Added: trunk/Source/WebCore/platform/graphics/gstreamer/GStreamerRegistryScanner.h (0 => 241585)


--- trunk/Source/WebCore/platform/graphics/gstreamer/GStreamerRegistryScanner.h	                        (rev 0)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/GStreamerRegistryScanner.h	2019-02-15 14:24:21 UTC (rev 241585)
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2019 Igalia S.L
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * aint with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#pragma once
+
+#if USE(GSTREAMER)
+
+#include "MediaConfiguration.h"
+
+#include <wtf/Forward.h>
+#include <wtf/HashMap.h>
+#include <wtf/HashSet.h>
+#include <wtf/text/AtomicString.h>
+#include <wtf/text/AtomicStringHash.h>
+#include <wtf/text/StringHash.h>
+
+namespace WebCore {
+class ContentType;
+
+class GStreamerRegistryScanner {
+    friend NeverDestroyed<GStreamerRegistryScanner>;
+public:
+    static GStreamerRegistryScanner& singleton();
+
+    HashSet<String, ASCIICaseInsensitiveHash>& mimeTypeSet() { return m_mimeTypeSet; }
+
+    bool isContainerTypeSupported(String containerType) const { return m_mimeTypeSet.contains(containerType); }
+
+    struct RegistryLookupResult {
+        bool isSupported;
+        bool isUsingHardware;
+
+        operator bool() const { return isSupported; }
+    };
+    RegistryLookupResult isDecodingSupported(MediaConfiguration&) const;
+
+    bool isCodecSupported(String codec, bool usingHardware = false) const;
+    bool areAllCodecsSupported(const Vector<String>& codecs, bool shouldCheckForHardwareUse = false) const;
+
+protected:
+    GStreamerRegistryScanner(bool isMediaSource = false);
+    ~GStreamerRegistryScanner();
+
+    void initialize();
+
+    enum ElementType {
+        AudioDecoder = 0,
+        VideoDecoder,
+        Demuxer
+    };
+    struct GstCapsWebKitMapping {
+        ElementType elementType;
+        const char* capsString;
+        Vector<AtomicString> webkitMimeTypes;
+        Vector<AtomicString> webkitCodecPatterns;
+    };
+    void fillMimeTypeSetFromCapsMapping(Vector<GstCapsWebKitMapping>&);
+
+    RegistryLookupResult hasElementForMediaType(GList* elementFactories, const char* capsString, bool shouldCheckHardwareClassifier = false);
+
+private:
+    bool m_isMediaSource;
+    GList* m_audioDecoderFactories;
+    GList* m_audioParserFactories;
+    GList* m_videoDecoderFactories;
+    GList* m_videoParserFactories;
+    GList* m_demuxerFactories;
+    HashSet<String, ASCIICaseInsensitiveHash> m_mimeTypeSet;
+    HashMap<AtomicString, bool> m_codecMap;
+};
+
+} // namespace WebCore
+
+#endif // USE(GSTREAMER)

Added: trunk/Source/WebCore/platform/graphics/gstreamer/MediaEngineConfigurationFactoryGStreamer.cpp (0 => 241585)


--- trunk/Source/WebCore/platform/graphics/gstreamer/MediaEngineConfigurationFactoryGStreamer.cpp	                        (rev 0)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/MediaEngineConfigurationFactoryGStreamer.cpp	2019-02-15 14:24:21 UTC (rev 241585)
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2019 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials provided
+ *    with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "MediaEngineConfigurationFactoryGStreamer.h"
+
+#if USE(GSTREAMER)
+
+#include "GStreamerRegistryScanner.h"
+#include "MediaCapabilitiesInfo.h"
+#include "MediaDecodingConfiguration.h"
+#include "MediaPlayer.h"
+#include <wtf/Function.h>
+
+#if ENABLE(MEDIA_SOURCE)
+#include "GStreamerRegistryScannerMSE.h"
+#endif
+
+namespace WebCore {
+
+void createMediaPlayerDecodingConfigurationGStreamer(MediaDecodingConfiguration& configuration, WTF::Function<void(MediaCapabilitiesInfo&&)>&& callback)
+{
+    bool isMediaSource = configuration.type == MediaDecodingType::MediaSource;
+#if ENABLE(MEDIA_SOURCE)
+    auto& scanner = isMediaSource ? GStreamerRegistryScannerMSE::singleton() : GStreamerRegistryScanner::singleton();
+#else
+    if (isMediaSource) {
+        callback({ });
+        return;
+    }
+    auto& scanner = GStreamerRegistryScanner::singleton();
+#endif
+    auto lookupResult = scanner.isDecodingSupported(configuration);
+    MediaCapabilitiesInfo info;
+    info.supported = lookupResult.isSupported;
+    info.powerEfficient = lookupResult.isUsingHardware;
+
+    callback(WTFMove(info));
+}
+
+}
+#endif

Added: trunk/Source/WebCore/platform/graphics/gstreamer/MediaEngineConfigurationFactoryGStreamer.h (0 => 241585)


--- trunk/Source/WebCore/platform/graphics/gstreamer/MediaEngineConfigurationFactoryGStreamer.h	                        (rev 0)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/MediaEngineConfigurationFactoryGStreamer.h	2019-02-15 14:24:21 UTC (rev 241585)
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2019 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials provided
+ *    with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if USE(GSTREAMER)
+
+#include <wtf/Forward.h>
+
+namespace WebCore {
+
+struct MediaCapabilitiesInfo;
+struct MediaDecodingConfiguration;
+
+extern void createMediaPlayerDecodingConfigurationGStreamer(MediaDecodingConfiguration&, WTF::Function<void(MediaCapabilitiesInfo&&)>&&);
+
+}
+
+#endif

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


--- trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp	2019-02-15 13:49:48 UTC (rev 241584)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp	2019-02-15 14:24:21 UTC (rev 241585)
@@ -29,6 +29,7 @@
 #if ENABLE(VIDEO) && USE(GSTREAMER)
 
 #include "GStreamerCommon.h"
+#include "GStreamerRegistryScanner.h"
 #include "HTTPHeaderNames.h"
 #include "MIMETypeRegistry.h"
 #include "MediaPlayer.h"
@@ -2229,137 +2230,10 @@
     m_readyTimerHandler.stop();
 }
 
-static HashSet<String, ASCIICaseInsensitiveHash>& mimeTypeSet()
-{
-    static NeverDestroyed<HashSet<String, ASCIICaseInsensitiveHash>> mimeTypes = []()
-    {
-        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);
-        GList* videoDecoderFactories = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_DECODER | GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO, GST_RANK_MARGINAL);
-        GList* demuxerFactories = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_DEMUXER, GST_RANK_MARGINAL);
-
-        enum ElementType {
-            AudioDecoder = 0,
-            VideoDecoder,
-            Demuxer
-        };
-        struct GstCapsWebKitMapping {
-            ElementType elementType;
-            const char* capsString;
-            Vector<AtomicString> webkitMimeTypes;
-        };
-
-        Vector<GstCapsWebKitMapping> mapping = {
-            {AudioDecoder, "audio/midi", {"audio/midi", "audio/riff-midi"}},
-            {AudioDecoder, "audio/x-sbc", { }},
-            {AudioDecoder, "audio/x-sid", { }},
-            {AudioDecoder, "audio/x-flac", {"audio/x-flac", "audio/flac"}},
-            {AudioDecoder, "audio/x-wav", {"audio/x-wav", "audio/wav", "audio/vnd.wave"}},
-            {AudioDecoder, "audio/x-wavpack", {"audio/x-wavpack"}},
-            {AudioDecoder, "audio/x-speex", {"audio/speex", "audio/x-speex"}},
-            {AudioDecoder, "audio/x-ac3", { }},
-            {AudioDecoder, "audio/x-eac3", {"audio/x-ac3"}},
-            {AudioDecoder, "audio/x-dts", { }},
-            {VideoDecoder, "video/x-h264, profile="" {"video/mp4", "video/x-m4v"}},
-            {VideoDecoder, "video/x-msvideocodec", {"video/x-msvideo"}},
-            {VideoDecoder, "video/x-h263", { }},
-            {VideoDecoder, "video/mpegts", { }},
-            {VideoDecoder, "video/mpeg, mpegversion=(int){1,2}, systemstream=(boolean)false", {"video/mpeg"}},
-            {VideoDecoder, "video/x-dirac", { }},
-            {VideoDecoder, "video/x-flash-video", {"video/flv", "video/x-flv"}},
-            {Demuxer, "video/quicktime", { }},
-            {Demuxer, "video/quicktime, variant=(string)3gpp", {"video/3gpp"}},
-            {Demuxer, "application/x-3gp", { }},
-            {Demuxer, "video/x-ms-asf", { }},
-            {Demuxer, "audio/x-aiff", { }},
-            {Demuxer, "application/x-pn-realaudio", { }},
-            {Demuxer, "application/vnd.rn-realmedia", { }},
-            {Demuxer, "audio/x-wav", {"audio/x-wav", "audio/wav", "audio/vnd.wave"}},
-            {Demuxer, "application/x-hls", {"application/vnd.apple.mpegurl", "application/x-mpegurl"}}
-        };
-
-        for (auto& current : mapping) {
-            GList* factories = demuxerFactories;
-            if (current.elementType == AudioDecoder)
-                factories = audioDecoderFactories;
-            else if (current.elementType == VideoDecoder)
-                factories = videoDecoderFactories;
-
-            if (gstRegistryHasElementForMediaType(factories, current.capsString)) {
-                if (!current.webkitMimeTypes.isEmpty()) {
-                    for (const auto& mimeType : current.webkitMimeTypes)
-                        set.add(mimeType);
-                } else
-                    set.add(AtomicString(current.capsString));
-            }
-        }
-
-        bool opusSupported = false;
-        if (gstRegistryHasElementForMediaType(audioDecoderFactories, "audio/x-opus")) {
-            opusSupported = true;
-            set.add(AtomicString("audio/opus"));
-        }
-
-        bool vorbisSupported = false;
-        if (gstRegistryHasElementForMediaType(demuxerFactories, "application/ogg")) {
-            set.add(AtomicString("application/ogg"));
-
-            vorbisSupported = gstRegistryHasElementForMediaType(audioDecoderFactories, "audio/x-vorbis");
-            if (vorbisSupported) {
-                set.add(AtomicString("audio/ogg"));
-                set.add(AtomicString("audio/x-vorbis+ogg"));
-            }
-
-            if (gstRegistryHasElementForMediaType(videoDecoderFactories, "video/x-theora"))
-                set.add(AtomicString("video/ogg"));
-        }
-
-        bool audioMpegSupported = false;
-        if (gstRegistryHasElementForMediaType(audioDecoderFactories, "audio/mpeg, mpegversion=(int)1, layer=(int)[1, 3]")) {
-            audioMpegSupported = true;
-            set.add(AtomicString("audio/mp1"));
-            set.add(AtomicString("audio/mp3"));
-            set.add(AtomicString("audio/x-mp3"));
-        }
-
-        if (gstRegistryHasElementForMediaType(audioDecoderFactories, "audio/mpeg, mpegversion=(int){2, 4}")) {
-            audioMpegSupported = true;
-            set.add(AtomicString("audio/aac"));
-            set.add(AtomicString("audio/mp2"));
-            set.add(AtomicString("audio/mp4"));
-            set.add(AtomicString("audio/x-m4a"));
-        }
-
-        if (audioMpegSupported) {
-            set.add(AtomicString("audio/mpeg"));
-            set.add(AtomicString("audio/x-mpeg"));
-        }
-
-        if (gstRegistryHasElementForMediaType(demuxerFactories, "video/x-matroska")) {
-            set.add(AtomicString("video/x-matroska"));
-
-            if (gstRegistryHasElementForMediaType(videoDecoderFactories, "video/x-vp8")
-                || gstRegistryHasElementForMediaType(videoDecoderFactories, "video/x-vp9")
-                || gstRegistryHasElementForMediaType(videoDecoderFactories, "video/x-vp10"))
-                set.add(AtomicString("video/webm"));
-
-            if (vorbisSupported || opusSupported)
-                set.add(AtomicString("audio/webm"));
-        }
-
-        gst_plugin_feature_list_free(audioDecoderFactories);
-        gst_plugin_feature_list_free(videoDecoderFactories);
-        gst_plugin_feature_list_free(demuxerFactories);
-        return set;
-    }();
-    return mimeTypes;
-}
-
 void MediaPlayerPrivateGStreamer::getSupportedTypes(HashSet<String, ASCIICaseInsensitiveHash>& types)
 {
-    types = mimeTypeSet();
+    auto& gstRegistryScanner = GStreamerRegistryScanner::singleton();
+    types = gstRegistryScanner.mimeTypeSet();
 }
 
 MediaPlayer::SupportsType MediaPlayerPrivateGStreamer::supportsType(const MediaEngineSupportParameters& parameters)
@@ -2379,30 +2253,18 @@
     if (parameters.type.isEmpty())
         return result;
 
-    // Spec says we should not return "probably" if the codecs string is empty.
-    if (mimeTypeSet().contains(parameters.type.containerType()))
-        result = parameters.type.codecs().isEmpty() ? MediaPlayer::MayBeSupported : MediaPlayer::IsSupported;
-
+    GST_DEBUG("Checking mime-type \"%s\"", parameters.type.raw().utf8().data());
     auto containerType = parameters.type.containerType();
-    if (containerType == "video/mp4"_s || containerType == "video/webm"_s) {
-        if (mimeTypeSet().contains(containerType)) {
-            GList* videoDecoderFactories = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_DECODER | GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO, GST_RANK_MARGINAL);
-            bool av1DecoderFound = gstRegistryHasElementForMediaType(videoDecoderFactories, "video/x-av1"_s);
-            gst_plugin_feature_list_free(videoDecoderFactories);
-            for (auto& codec : parameters.type.codecs()) {
-                if (codec.startsWith("av01"_s)) {
-                    result = av1DecoderFound ? MediaPlayer::IsSupported : MediaPlayer::IsNotSupported;
-                    break;
-                }
-                if (codec.startsWith("av1"_s)) {
-                    result = MediaPlayer::IsNotSupported;
-                    break;
-                }
-            }
-        }
+    auto& gstRegistryScanner = GStreamerRegistryScanner::singleton();
+    if (gstRegistryScanner.isContainerTypeSupported(containerType)) {
+        // Spec says we should not return "probably" if the codecs string is empty.
+        Vector<String> codecs = parameters.type.codecs();
+        result = codecs.isEmpty() ? MediaPlayer::MayBeSupported : (gstRegistryScanner.areAllCodecsSupported(codecs) ? MediaPlayer::IsSupported : MediaPlayer::IsNotSupported);
     }
 
-    return extendedSupportsType(parameters, result);
+    auto finalResult = extendedSupportsType(parameters, result);
+    GST_DEBUG("Supported: %s", convertEnumerationToString(finalResult).utf8().data());
+    return finalResult;
 }
 
 void MediaPlayerPrivateGStreamer::setDownloadBuffering()

Modified: trunk/Source/WebCore/platform/graphics/gstreamer/mse/AppendPipeline.cpp (241584 => 241585)


--- trunk/Source/WebCore/platform/graphics/gstreamer/mse/AppendPipeline.cpp	2019-02-15 13:49:48 UTC (rev 241584)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/mse/AppendPipeline.cpp	2019-02-15 14:24:21 UTC (rev 241585)
@@ -27,6 +27,7 @@
 #include "GStreamerCommon.h"
 #include "GStreamerEMEUtilities.h"
 #include "GStreamerMediaDescription.h"
+#include "GStreamerRegistryScannerMSE.h"
 #include "MediaSampleGStreamer.h"
 #include "InbandTextTrackPrivateGStreamer.h"
 #include "MediaDescription.h"
@@ -141,7 +142,8 @@
     }, this, nullptr);
 
     const String& type = m_sourceBufferPrivate->type().containerType();
-    if (type.endsWith("mp4"))
+    GST_DEBUG("SourceBuffer containerType: %s", type.utf8().data());
+    if (type.endsWith("mp4") || type.endsWith("aac"))
         m_demux = gst_element_factory_make("qtdemux", nullptr);
     else if (type.endsWith("webm"))
         m_demux = gst_element_factory_make("matroskademux", nullptr);
@@ -379,7 +381,8 @@
     m_streamType = WebCore::MediaSourceStreamTypeGStreamer::Unknown;
 
     const char* originalMediaType = capsMediaType(m_demuxerSrcPadCaps.get());
-    if (!MediaPlayerPrivateGStreamerMSE::supportsCodec(originalMediaType)) {
+    auto& gstRegistryScanner = GStreamerRegistryScannerMSE::singleton();
+    if (!gstRegistryScanner.isCodecSupported(originalMediaType)) {
             m_presentationSize = WebCore::FloatSize();
             m_streamType = WebCore::MediaSourceStreamTypeGStreamer::Invalid;
     } else if (doCapsHaveType(m_demuxerSrcPadCaps.get(), GST_VIDEO_CAPS_TYPE_PREFIX)) {

Added: trunk/Source/WebCore/platform/graphics/gstreamer/mse/GStreamerRegistryScannerMSE.cpp (0 => 241585)


--- trunk/Source/WebCore/platform/graphics/gstreamer/mse/GStreamerRegistryScannerMSE.cpp	                        (rev 0)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/mse/GStreamerRegistryScannerMSE.cpp	2019-02-15 14:24:21 UTC (rev 241585)
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2019 Igalia S.L
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * aint with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+
+#if USE(GSTREAMER) && ENABLE(MEDIA_SOURCE)
+#include "GStreamerRegistryScannerMSE.h"
+
+#include <wtf/NeverDestroyed.h>
+
+namespace WebCore {
+
+GStreamerRegistryScannerMSE& GStreamerRegistryScannerMSE::singleton()
+{
+    static NeverDestroyed<GStreamerRegistryScannerMSE> sharedInstance;
+    return sharedInstance;
+}
+
+GStreamerRegistryScannerMSE::GStreamerRegistryScannerMSE()
+    : GStreamerRegistryScanner::GStreamerRegistryScanner(true)
+{
+}
+
+}
+#endif

Added: trunk/Source/WebCore/platform/graphics/gstreamer/mse/GStreamerRegistryScannerMSE.h (0 => 241585)


--- trunk/Source/WebCore/platform/graphics/gstreamer/mse/GStreamerRegistryScannerMSE.h	                        (rev 0)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/mse/GStreamerRegistryScannerMSE.h	2019-02-15 14:24:21 UTC (rev 241585)
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2019 Igalia S.L
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * aint with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#pragma once
+
+#if USE(GSTREAMER) && ENABLE(MEDIA_SOURCE)
+
+#include "GStreamerRegistryScanner.h"
+
+#include <wtf/Forward.h>
+
+namespace WebCore {
+
+class GStreamerRegistryScannerMSE : public GStreamerRegistryScanner {
+    friend NeverDestroyed<GStreamerRegistryScannerMSE>;
+public:
+    static GStreamerRegistryScannerMSE& singleton();
+protected:
+    GStreamerRegistryScannerMSE();
+};
+
+} // namespace WebCore
+
+#endif // USE(GSTREAMER)

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


--- trunk/Source/WebCore/platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.cpp	2019-02-15 13:49:48 UTC (rev 241584)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.cpp	2019-02-15 14:24:21 UTC (rev 241585)
@@ -31,6 +31,7 @@
 #include "AppendPipeline.h"
 #include "AudioTrackPrivateGStreamer.h"
 #include "GStreamerCommon.h"
+#include "GStreamerRegistryScannerMSE.h"
 #include "InbandTextTrackPrivateGStreamer.h"
 #include "MIMETypeRegistry.h"
 #include "MediaDescription.h"
@@ -41,7 +42,6 @@
 #include "TimeRanges.h"
 #include "VideoTrackPrivateGStreamer.h"
 
-#include <fnmatch.h>
 #include <gst/app/gstappsink.h>
 #include <gst/app/gstappsrc.h>
 #include <gst/gst.h>
@@ -682,30 +682,6 @@
     }
 }
 
-static HashSet<String, ASCIICaseInsensitiveHash>& mimeTypeCache()
-{
-    static NeverDestroyed<HashSet<String, ASCIICaseInsensitiveHash>> cache = []()
-    {
-        initializeGStreamerAndRegisterWebKitElements();
-        HashSet<String, ASCIICaseInsensitiveHash> set;
-        const char* mimeTypes[] = {
-            "video/mp4",
-            "audio/mp4",
-            "video/webm",
-            "audio/webm"
-        };
-        for (auto& type : mimeTypes)
-            set.add(type);
-        return set;
-    }();
-    return cache;
-}
-
-void MediaPlayerPrivateGStreamerMSE::getSupportedTypes(HashSet<String, ASCIICaseInsensitiveHash>& types)
-{
-    types = mimeTypeCache();
-}
-
 void MediaPlayerPrivateGStreamerMSE::trackDetected(RefPtr<AppendPipeline> appendPipeline, RefPtr<WebCore::TrackPrivateBase> newTrack, bool firstTrackDetected)
 {
     ASSERT(appendPipeline->track() == newTrack);
@@ -726,111 +702,12 @@
         m_playbackPipeline->reattachTrack(appendPipeline->sourceBufferPrivate(), newTrack, caps);
 }
 
-const static HashSet<AtomicString>& codecSet()
+void MediaPlayerPrivateGStreamerMSE::getSupportedTypes(HashSet<String, ASCIICaseInsensitiveHash>& types)
 {
-    static NeverDestroyed<HashSet<AtomicString>> codecTypes = []()
-    {
-        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;
-        };
-
-        GstCapsWebKitMapping mapping[] = {
-            { VideoDecoder, "video/x-h264,  profile="" constrained-baseline, baseline }", { "x-h264", "avc*" } },
-            { VideoDecoder, "video/mpeg, mpegversion=(int){1,2}, systemstream=(boolean)false", { "mpeg" } },
-            { VideoDecoder, "video/x-vp8", { "vp8", "x-vp8" } },
-            { VideoDecoder, "video/x-vp9", { "vp9", "x-vp9" } },
-            { AudioDecoder, "audio/x-vorbis", { "vorbis", "x-vorbis" } },
-            { AudioDecoder, "audio/x-opus", { "opus", "x-opus" } }
-        };
-
-        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;
+    auto& gstRegistryScanner = GStreamerRegistryScannerMSE::singleton();
+    types = gstRegistryScanner.mimeTypeSet();
 }
 
-bool MediaPlayerPrivateGStreamerMSE::supportsCodec(String codec)
-{
-    // 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);
-
-    for (const auto& pattern : codecSet()) {
-        bool codecMatchesPattern = !fnmatch(pattern.string().utf8().data(), codec.utf8().data(), 0);
-        if (codecMatchesPattern)
-            return true;
-    }
-
-    return false;
-}
-
-bool MediaPlayerPrivateGStreamerMSE::supportsAllCodecs(const Vector<String>& codecs)
-{
-    for (String codec : codecs) {
-        if (!supportsCodec(codec))
-            return false;
-    }
-
-    return true;
-}
-
 MediaPlayer::SupportsType MediaPlayerPrivateGStreamerMSE::supportsType(const MediaEngineSupportParameters& parameters)
 {
     MediaPlayer::SupportsType result = MediaPlayer::IsNotSupported;
@@ -842,19 +719,21 @@
     // YouTube TV provides empty types for some videos and we want to be selected as best media engine for them.
     if (containerType.isEmpty()) {
         result = MediaPlayer::MayBeSupported;
+        GST_DEBUG("mime-type \"%s\" supported: %s", parameters.type.raw().utf8().data(), convertEnumerationToString(result).utf8().data());
         return result;
     }
 
+    GST_DEBUG("Checking mime-type \"%s\"", parameters.type.raw().utf8().data());
+    auto& gstRegistryScanner = GStreamerRegistryScannerMSE::singleton();
     // Spec says we should not return "probably" if the codecs string is empty.
-    if (mimeTypeCache().contains(containerType)) {
+    if (gstRegistryScanner.isContainerTypeSupported(containerType)) {
         Vector<String> codecs = parameters.type.codecs();
-        if (codecs.isEmpty())
-            result = MediaPlayer::MayBeSupported;
-        else
-            result = supportsAllCodecs(codecs) ? MediaPlayer::IsSupported : MediaPlayer::IsNotSupported;
+        result = codecs.isEmpty() ? MediaPlayer::MayBeSupported : (gstRegistryScanner.areAllCodecsSupported(codecs) ? MediaPlayer::IsSupported : MediaPlayer::IsNotSupported);
     }
 
-    return extendedSupportsType(parameters, result);
+    auto finalResult = extendedSupportsType(parameters, result);
+    GST_DEBUG("Supported: %s", convertEnumerationToString(finalResult).utf8().data());
+    return finalResult;
 }
 
 void MediaPlayerPrivateGStreamerMSE::markEndOfStream(MediaSourcePrivate::EndOfStreamStatus status)

Modified: trunk/Source/WebCore/platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.h (241584 => 241585)


--- trunk/Source/WebCore/platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.h	2019-02-15 13:49:48 UTC (rev 241584)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.h	2019-02-15 14:24:21 UTC (rev 241585)
@@ -82,9 +82,6 @@
     void trackDetected(RefPtr<AppendPipeline>, RefPtr<WebCore::TrackPrivateBase>, bool firstTrackDetected);
     void notifySeekNeedsDataForTime(const MediaTime&);
 
-    static bool supportsCodec(String codec);
-    static bool supportsAllCodecs(const Vector<String>& codecs);
-
 private:
     static void getSupportedTypes(HashSet<String, ASCIICaseInsensitiveHash>&);
     static MediaPlayer::SupportsType supportsType(const MediaEngineSupportParameters&);

Modified: trunk/Source/WebCore/platform/mediacapabilities/MediaEngineConfigurationFactory.cpp (241584 => 241585)


--- trunk/Source/WebCore/platform/mediacapabilities/MediaEngineConfigurationFactory.cpp	2019-02-15 13:49:48 UTC (rev 241584)
+++ trunk/Source/WebCore/platform/mediacapabilities/MediaEngineConfigurationFactory.cpp	2019-02-15 14:24:21 UTC (rev 241585)
@@ -39,6 +39,10 @@
 #include "MediaEngineConfigurationFactoryCocoa.h"
 #endif
 
+#if USE(GSTREAMER)
+#include "MediaEngineConfigurationFactoryGStreamer.h"
+#endif
+
 namespace WebCore {
 
 static bool& mockEnabled()
@@ -59,6 +63,9 @@
 #if PLATFORM(COCOA)
         { &createMediaPlayerDecodingConfigurationCocoa, nullptr },
 #endif
+#if USE(GSTREAMER)
+        { &createMediaPlayerDecodingConfigurationGStreamer, nullptr },
+#endif
     }));
     return factories;
 }
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to