WebKit Bugzilla
Attachment 362011 Details for
Bug 191191
: [GStreamer] Decoding media-capabilities configuration initial support
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
bug-191191-20190214144651.patch (text/plain), 58.73 KB, created by
Philippe Normand
on 2019-02-14 06:46:53 PST
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Philippe Normand
Created:
2019-02-14 06:46:53 PST
Size:
58.73 KB
patch
obsolete
>Subversion Revision: 241515 >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index d0130cd4537fc4e23d4bbf4803c171492908d917..f142e71ffa1e142bb1c02b53db93e956a715f58a 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,82 @@ >+2018-11-02 Philippe Normand <pnormand@igalia.com> >+ >+ [GStreamer] Decoding media-capabilities configuration initial support >+ https://bugs.webkit.org/show_bug.cgi?id=191191 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ 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 >+ GstRegistryScanner. 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 GstRegistryScanner. >+ * platform/graphics/gstreamer/GStreamerCommon.h: Ditto. >+ * platform/graphics/gstreamer/GstRegistryScanner.cpp: Added. >+ (WebCore::GstRegistryScanner::singleton): >+ (WebCore::GstRegistryScanner::GstRegistryScanner): Initialize >+ supported mime-types and codecs from the GStreamer registry. >+ (WebCore::GstRegistryScanner::~GstRegistryScanner): Free the element factories. >+ (WebCore::GstRegistryScanner::gstRegistryHasElementForMediaType): >+ Check the input caps are supported, optionally using hardware >+ device. >+ (WebCore::GstRegistryScanner::fillMimeTypeSetFromCapsMapping): >+ Moved from MediaPlayerPrivateGStreamer{,MSE}. >+ (WebCore::GstRegistryScanner::initialize): Ditto. >+ (WebCore::GstRegistryScanner::supportsCodec const): Ditto. >+ (WebCore::GstRegistryScanner::supportsAllCodecs const): Ditto. >+ (WebCore::GstRegistryScanner::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/GstRegistryScanner.h: Added. >+ (WebCore::GstRegistryScanner::mimeTypeSet): >+ (WebCore::GstRegistryScanner::supportsContainerType const): >+ (WebCore::GstRegistryScanner::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 GstRegistryScanner 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/GstRegistryScannerMSE.cpp: Added. >+ (WebCore::GstRegistryScannerMSE::singleton): >+ (WebCore::GstRegistryScannerMSE::GstRegistryScannerMSE): >+ * platform/graphics/gstreamer/mse/GstRegistryScannerMSE.h: Added. >+ * platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.cpp: >+ Rely on new GstRegistryScanner 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-13 Ryosuke Niwa <rniwa@webkit.org> > > Crash in DOMTimer::fired >diff --git a/Source/WebCore/platform/GStreamer.cmake b/Source/WebCore/platform/GStreamer.cmake >index 6a0e033c2a37187ddd5a678aa9006487652b5809..26d28ed0eb600c2971c9801f2dee0101fb05c35c 100644 >--- a/Source/WebCore/platform/GStreamer.cmake >+++ b/Source/WebCore/platform/GStreamer.cmake >@@ -10,7 +10,9 @@ if (ENABLE_VIDEO OR ENABLE_WEB_AUDIO) > platform/graphics/gstreamer/GRefPtrGStreamer.cpp > platform/graphics/gstreamer/GStreamerCommon.cpp > platform/graphics/gstreamer/GstAllocatorFastMalloc.cpp >+ platform/graphics/gstreamer/GstRegistryScanner.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 @@ if (ENABLE_VIDEO OR ENABLE_WEB_AUDIO) > > platform/graphics/gstreamer/mse/AppendPipeline.cpp > platform/graphics/gstreamer/mse/GStreamerMediaDescription.cpp >+ platform/graphics/gstreamer/mse/GstRegistryScannerMSE.cpp > platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.cpp > platform/graphics/gstreamer/mse/MediaSourceClientGStreamerMSE.cpp > platform/graphics/gstreamer/mse/MediaSourceGStreamer.cpp >diff --git a/Source/WebCore/platform/graphics/MediaPlayer.cpp b/Source/WebCore/platform/graphics/MediaPlayer.cpp >index b729154c9777b911f15c1227fe0cb485b6c29f1c..bda0711f6b55c26d48af638cc8b2f9a578eb778e 100644 >--- a/Source/WebCore/platform/graphics/MediaPlayer.cpp >+++ b/Source/WebCore/platform/graphics/MediaPlayer.cpp >@@ -1618,6 +1618,20 @@ String convertEnumerationToString(MediaPlayerEnums::Preload enumerationValue) > 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 >diff --git a/Source/WebCore/platform/graphics/MediaPlayer.h b/Source/WebCore/platform/graphics/MediaPlayer.h >index 41bcde24837cbb2ccc8146af78c2fdb6d6150e13..efc15ba1cb6586e2606a93b041330b9bd7fdd22f 100644 >--- a/Source/WebCore/platform/graphics/MediaPlayer.h >+++ b/Source/WebCore/platform/graphics/MediaPlayer.h >@@ -253,8 +253,8 @@ public: > 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); >diff --git a/Source/WebCore/platform/graphics/MediaPlayerEnums.h b/Source/WebCore/platform/graphics/MediaPlayerEnums.h >index 06f0ccd28d6ab9f43f61bef27eb1f30bde62dd46..950e0ed287eb321a49a5423e63131aa09270cb60 100644 >--- a/Source/WebCore/platform/graphics/MediaPlayerEnums.h >+++ b/Source/WebCore/platform/graphics/MediaPlayerEnums.h >@@ -36,6 +36,7 @@ public: > 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 @@ public: > WTF::String convertEnumerationToString(MediaPlayerEnums::ReadyState); > WTF::String convertEnumerationToString(MediaPlayerEnums::NetworkState); > WTF::String convertEnumerationToString(MediaPlayerEnums::Preload); >+WTF::String convertEnumerationToString(MediaPlayerEnums::SupportsType); > > } // namespace WebCore > >diff --git a/Source/WebCore/platform/graphics/gstreamer/GStreamerCommon.cpp b/Source/WebCore/platform/graphics/gstreamer/GStreamerCommon.cpp >index c32539b2df1f31a0dc9c8f4592db8f6a70a1eba5..17ca2b9ba2762177cf76f148487db9535f56869c 100644 >--- a/Source/WebCore/platform/graphics/gstreamer/GStreamerCommon.cpp >+++ b/Source/WebCore/platform/graphics/gstreamer/GStreamerCommon.cpp >@@ -302,16 +302,6 @@ uint64_t toGstUnsigned64Time(const MediaTime& mediaTime) > 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)) { >diff --git a/Source/WebCore/platform/graphics/gstreamer/GStreamerCommon.h b/Source/WebCore/platform/graphics/gstreamer/GStreamerCommon.h >index 5cb717d3bf41574bd96d0fc0cf150317a9e41989..4190d64fbe1af57532bc768626e7c8bc260f3d61 100644 >--- a/Source/WebCore/platform/graphics/gstreamer/GStreamerCommon.h >+++ b/Source/WebCore/platform/graphics/gstreamer/GStreamerCommon.h >@@ -216,7 +216,6 @@ private: > }; > > >-bool gstRegistryHasElementForMediaType(GList* elementFactories, const char* capsString); > void connectSimpleBusMessageCallback(GstElement* pipeline); > void disconnectSimpleBusMessageCallback(GstElement* pipeline); > >diff --git a/Source/WebCore/platform/graphics/gstreamer/GstRegistryScanner.cpp b/Source/WebCore/platform/graphics/gstreamer/GstRegistryScanner.cpp >new file mode 100644 >index 0000000000000000000000000000000000000000..b650cc0ebe3fc8f5571e4d14a55c236bfb37d500 >--- /dev/null >+++ b/Source/WebCore/platform/graphics/gstreamer/GstRegistryScanner.cpp >@@ -0,0 +1,330 @@ >+/* >+ * Copyright (C) 2018 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 "GstRegistryScanner.h" >+ >+#if USE(GSTREAMER) >+#include "ContentType.h" >+#include "GRefPtrGStreamer.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 >+ >+GstRegistryScanner& GstRegistryScanner::singleton() >+{ >+ static NeverDestroyed<GstRegistryScanner> sharedInstance; >+ return sharedInstance; >+} >+ >+GstRegistryScanner::GstRegistryScanner(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 >+} >+ >+GstRegistryScanner::~GstRegistryScanner() >+{ >+ 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); >+} >+ >+GstRegistryScanner::RegistryLookupResult GstRegistryScanner::gstRegistryHasElementForMediaType(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 != nullptr; 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 GstRegistryScanner::RegistryLookupResult { isSupported, isUsingHardware }; >+} >+ >+void GstRegistryScanner::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 (gstRegistryHasElementForMediaType(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 GstRegistryScanner::initialize() >+{ >+ if (gstRegistryHasElementForMediaType(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 = gstRegistryHasElementForMediaType(m_audioDecoderFactories, "audio/x-opus"); >+ if (opusSupported && (!m_isMediaSource || gstRegistryHasElementForMediaType(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 = gstRegistryHasElementForMediaType(m_audioDecoderFactories, "audio/x-vorbis"); >+ if (vorbisSupported && (!m_isMediaSource || gstRegistryHasElementForMediaType(m_audioParserFactories, "audio/x-vorbis"))) { >+ m_codecMap.add(AtomicString("vorbis"), false); >+ m_codecMap.add(AtomicString("x-vorbis"), false); >+ } >+ >+ if (gstRegistryHasElementForMediaType(m_demuxerFactories, "video/x-matroska")) { >+ auto vp8DecoderAvailable = gstRegistryHasElementForMediaType(m_videoDecoderFactories, "video/x-vp8", true); >+ auto vp9DecoderAvailable = gstRegistryHasElementForMediaType(m_videoDecoderFactories, "video/x-vp9", true); >+ >+ if (vp8DecoderAvailable || vp9DecoderAvailable) >+ m_mimeTypeSet.add(AtomicString("video/webm")); >+ >+ if (vp8DecoderAvailable) { >+ m_codecMap.add(AtomicString("vp8"), vp8DecoderAvailable.usingHardware); >+ m_codecMap.add(AtomicString("x-vp8"), vp8DecoderAvailable.usingHardware); >+ } >+ if (vp9DecoderAvailable) { >+ m_codecMap.add(AtomicString("vp9"), vp9DecoderAvailable.usingHardware); >+ m_codecMap.add(AtomicString("x-vp9"), vp9DecoderAvailable.usingHardware); >+ } >+ if (opusSupported) >+ m_mimeTypeSet.add(AtomicString("audio/webm")); >+ } >+ >+ auto h264DecoderAvailable = gstRegistryHasElementForMediaType(m_videoDecoderFactories, "video/x-h264, profile=(string){ constrained-baseline, baseline, high }", true); >+ if (h264DecoderAvailable && (!m_isMediaSource || gstRegistryHasElementForMediaType(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.usingHardware); >+ m_codecMap.add(AtomicString("avc*"), h264DecoderAvailable.usingHardware); >+ m_codecMap.add(AtomicString("mp4v*"), h264DecoderAvailable.usingHardware); >+ } >+ >+ 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 (gstRegistryHasElementForMediaType(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 (gstRegistryHasElementForMediaType(m_audioDecoderFactories, "audio/x-speex")) { >+ m_mimeTypeSet.add(AtomicString("audio/ogg")); >+ m_codecMap.add(AtomicString("speex"), false); >+ } >+ >+ if (gstRegistryHasElementForMediaType(m_videoDecoderFactories, "video/x-theora")) { >+ m_mimeTypeSet.add(AtomicString("video/ogg")); >+ m_codecMap.add(AtomicString("theora"), false); >+ } >+ } >+ >+ bool audioMpegSupported = false; >+ if (gstRegistryHasElementForMediaType(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 (gstRegistryHasElementForMediaType(m_audioDecoderFactories, "audio/mpeg, mpegversion=(int)2")) { >+ audioMpegSupported = true; >+ m_mimeTypeSet.add(AtomicString("audio/mp2")); >+ } >+ >+ audioMpegSupported |= supportsContainerType("audio/mp4"); >+ if (audioMpegSupported) { >+ m_mimeTypeSet.add(AtomicString("audio/mpeg")); >+ m_mimeTypeSet.add(AtomicString("audio/x-mpeg")); >+ } >+ >+ bool matroskaSupported = gstRegistryHasElementForMediaType(m_demuxerFactories, "video/x-matroska"); >+ if (matroskaSupported) { >+ m_mimeTypeSet.add(AtomicString("video/x-matroska")); >+ >+ if (gstRegistryHasElementForMediaType(m_videoDecoderFactories, "video/x-vp10")) >+ m_mimeTypeSet.add(AtomicString("video/webm")); >+ } >+ >+ if ((matroskaSupported || supportsContainerType("video/mp4")) && gstRegistryHasElementForMediaType(m_videoDecoderFactories, "video/x-av1")) >+ m_codecMap.add(AtomicString("av01*"), false); >+} >+ >+bool GstRegistryScanner::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 GstRegistryScanner::areAllCodecsSupported(const Vector<String>& codecs, bool shouldCheckForHardwareUse) const >+{ >+ for (String codec : codecs) { >+ if (!isCodecSupported(codec, shouldCheckForHardwareUse)) >+ return false; >+ } >+ >+ return true; >+} >+ >+GstRegistryScanner::RegistryLookupResult GstRegistryScanner::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 = supportsContainerType(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 = supportsContainerType(contentType.containerType()); >+ } >+ >+ return GstRegistryScanner::RegistryLookupResult { isSupported, isUsingHardware }; >+} >+ >+} >+#endif >diff --git a/Source/WebCore/platform/graphics/gstreamer/GstRegistryScanner.h b/Source/WebCore/platform/graphics/gstreamer/GstRegistryScanner.h >new file mode 100644 >index 0000000000000000000000000000000000000000..afeabf34ddb097ca649c15cda60ae4543253bb2e >--- /dev/null >+++ b/Source/WebCore/platform/graphics/gstreamer/GstRegistryScanner.h >@@ -0,0 +1,90 @@ >+/* >+ * Copyright (C) 2018 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 GstRegistryScanner { >+ friend NeverDestroyed<GstRegistryScanner>; >+public: >+ static GstRegistryScanner& singleton(); >+ >+ HashSet<String, ASCIICaseInsensitiveHash>& mimeTypeSet() { return m_mimeTypeSet; } >+ >+ bool supportsContainerType(String containerType) const { return m_mimeTypeSet.contains(containerType); } >+ >+ struct RegistryLookupResult { >+ bool supported; >+ bool usingHardware; >+ >+ operator bool() const { return supported; } >+ }; >+ RegistryLookupResult isDecodingSupported(MediaConfiguration&) const; >+ >+ bool isCodecSupported(String codec, bool usingHardware = false) const; >+ bool areAllCodecsSupported(const Vector<String>& codecs, bool shouldCheckForHardwareUse = false) const; >+ >+protected: >+ GstRegistryScanner(bool isMediaSource = false); >+ ~GstRegistryScanner(); >+ >+ 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 gstRegistryHasElementForMediaType(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) >diff --git a/Source/WebCore/platform/graphics/gstreamer/MediaEngineConfigurationFactoryGStreamer.cpp b/Source/WebCore/platform/graphics/gstreamer/MediaEngineConfigurationFactoryGStreamer.cpp >new file mode 100644 >index 0000000000000000000000000000000000000000..f773617c23184b290ba52e7c6437340eb607ef82 >--- /dev/null >+++ b/Source/WebCore/platform/graphics/gstreamer/MediaEngineConfigurationFactoryGStreamer.cpp >@@ -0,0 +1,66 @@ >+/* >+ * Copyright (C) 2018 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 "GstRegistryScanner.h" >+#include "MediaCapabilitiesInfo.h" >+#include "MediaDecodingConfiguration.h" >+#include "MediaPlayer.h" >+#include <wtf/Function.h> >+ >+#if ENABLE(MEDIA_SOURCE) >+#include "GstRegistryScannerMSE.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 ? GstRegistryScannerMSE::singleton() : GstRegistryScanner::singleton(); >+#else >+ if (isMediaSource) { >+ callback({ }); >+ return; >+ } >+ auto& scanner = GstRegistryScanner::singleton(); >+#endif >+ auto lookupResult = scanner.isDecodingSupported(configuration); >+ MediaCapabilitiesInfo info; >+ info.supported = lookupResult.supported; >+ info.powerEfficient = lookupResult.usingHardware; >+ >+ callback(WTFMove(info)); >+} >+ >+} >+#endif >diff --git a/Source/WebCore/platform/graphics/gstreamer/MediaEngineConfigurationFactoryGStreamer.h b/Source/WebCore/platform/graphics/gstreamer/MediaEngineConfigurationFactoryGStreamer.h >new file mode 100644 >index 0000000000000000000000000000000000000000..9e9ec2178a58792467856bb5a8f07aa53cf32451 >--- /dev/null >+++ b/Source/WebCore/platform/graphics/gstreamer/MediaEngineConfigurationFactoryGStreamer.h >@@ -0,0 +1,43 @@ >+/* >+ * Copyright (C) 2018 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 >diff --git a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp >index 4140c11b0ea4798e660d649580fecaad3c26d4c7..f61f85dff3714a779e23ca9d83ed55f7132bf2db 100644 >--- a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp >+++ b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp >@@ -29,6 +29,7 @@ > #if ENABLE(VIDEO) && USE(GSTREAMER) > > #include "GStreamerCommon.h" >+#include "GstRegistryScanner.h" > #include "HTTPHeaderNames.h" > #include "MIMETypeRegistry.h" > #include "MediaPlayer.h" >@@ -2228,137 +2229,10 @@ void MediaPlayerPrivateGStreamer::loadingFailed(MediaPlayer::NetworkState error) > 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=(string)high", {"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 = GstRegistryScanner::singleton(); >+ types = gstRegistryScanner.mimeTypeSet(); > } > > MediaPlayer::SupportsType MediaPlayerPrivateGStreamer::supportsType(const MediaEngineSupportParameters& parameters) >@@ -2378,30 +2252,18 @@ MediaPlayer::SupportsType MediaPlayerPrivateGStreamer::supportsType(const MediaE > 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 = GstRegistryScanner::singleton(); >+ if (gstRegistryScanner.supportsContainerType(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() >diff --git a/Source/WebCore/platform/graphics/gstreamer/mse/AppendPipeline.cpp b/Source/WebCore/platform/graphics/gstreamer/mse/AppendPipeline.cpp >index 2d9323811ff3ee96c40befb8e87bab04e014a42b..bc4156fe6bb484a598907a154374bcd34444363b 100644 >--- a/Source/WebCore/platform/graphics/gstreamer/mse/AppendPipeline.cpp >+++ b/Source/WebCore/platform/graphics/gstreamer/mse/AppendPipeline.cpp >@@ -27,6 +27,7 @@ > #include "GStreamerCommon.h" > #include "GStreamerEMEUtilities.h" > #include "GStreamerMediaDescription.h" >+#include "GstRegistryScannerMSE.h" > #include "MediaSampleGStreamer.h" > #include "InbandTextTrackPrivateGStreamer.h" > #include "MediaDescription.h" >@@ -141,7 +142,8 @@ AppendPipeline::AppendPipeline(Ref<MediaSourceClientGStreamerMSE> mediaSourceCli > }, 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 @@ void AppendPipeline::parseDemuxerSrcPadCaps(GstCaps* demuxerSrcPadCaps) > m_streamType = WebCore::MediaSourceStreamTypeGStreamer::Unknown; > > const char* originalMediaType = capsMediaType(m_demuxerSrcPadCaps.get()); >- if (!MediaPlayerPrivateGStreamerMSE::supportsCodec(originalMediaType)) { >+ auto& gstRegistryScanner = GstRegistryScannerMSE::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)) { >diff --git a/Source/WebCore/platform/graphics/gstreamer/mse/GstRegistryScannerMSE.cpp b/Source/WebCore/platform/graphics/gstreamer/mse/GstRegistryScannerMSE.cpp >new file mode 100644 >index 0000000000000000000000000000000000000000..18e490952824874e1fffd80dbcf0453eeec969a0 >--- /dev/null >+++ b/Source/WebCore/platform/graphics/gstreamer/mse/GstRegistryScannerMSE.cpp >@@ -0,0 +1,41 @@ >+/* >+ * Copyright (C) 2018 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 "GstRegistryScannerMSE.h" >+ >+#include <wtf/NeverDestroyed.h> >+ >+namespace WebCore { >+ >+GstRegistryScannerMSE& GstRegistryScannerMSE::singleton() >+{ >+ static NeverDestroyed<GstRegistryScannerMSE> sharedInstance; >+ return sharedInstance; >+} >+ >+GstRegistryScannerMSE::GstRegistryScannerMSE() >+ : GstRegistryScanner::GstRegistryScanner(true) >+{ >+} >+ >+} >+#endif >diff --git a/Source/WebCore/platform/graphics/gstreamer/mse/GstRegistryScannerMSE.h b/Source/WebCore/platform/graphics/gstreamer/mse/GstRegistryScannerMSE.h >new file mode 100644 >index 0000000000000000000000000000000000000000..d0fc997d609a893b4aabcdf356db0ba293c93004 >--- /dev/null >+++ b/Source/WebCore/platform/graphics/gstreamer/mse/GstRegistryScannerMSE.h >@@ -0,0 +1,40 @@ >+/* >+ * Copyright (C) 2018 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 "GstRegistryScanner.h" >+ >+#include <wtf/Forward.h> >+ >+namespace WebCore { >+ >+class GstRegistryScannerMSE : public GstRegistryScanner { >+ friend NeverDestroyed<GstRegistryScannerMSE>; >+public: >+ static GstRegistryScannerMSE& singleton(); >+protected: >+ GstRegistryScannerMSE(); >+}; >+ >+} // namespace WebCore >+ >+#endif // USE(GSTREAMER) >diff --git a/Source/WebCore/platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.cpp b/Source/WebCore/platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.cpp >index e5b443e6b2d72172f67127e16aab0c3f7e2cb840..1d7cba65f17b4ac980b401999864e1a20ab9d13f 100644 >--- a/Source/WebCore/platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.cpp >+++ b/Source/WebCore/platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.cpp >@@ -31,6 +31,7 @@ > #include "AppendPipeline.h" > #include "AudioTrackPrivateGStreamer.h" > #include "GStreamerCommon.h" >+#include "GstRegistryScannerMSE.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 @@ void MediaPlayerPrivateGStreamerMSE::durationChanged() > } > } > >-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,109 +702,10 @@ void MediaPlayerPrivateGStreamerMSE::trackDetected(RefPtr<AppendPipeline> append > m_playbackPipeline->reattachTrack(appendPipeline->sourceBufferPrivate(), newTrack, caps); > } > >-const static HashSet<AtomicString>& codecSet() >-{ >- 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=(string){ 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; >-} >- >-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) >+void MediaPlayerPrivateGStreamerMSE::getSupportedTypes(HashSet<String, ASCIICaseInsensitiveHash>& types) > { >- for (String codec : codecs) { >- if (!supportsCodec(codec)) >- return false; >- } >- >- return true; >+ auto& gstRegistryScanner = GstRegistryScannerMSE::singleton(); >+ types = gstRegistryScanner.mimeTypeSet(); > } > > MediaPlayer::SupportsType MediaPlayerPrivateGStreamerMSE::supportsType(const MediaEngineSupportParameters& parameters) >@@ -842,19 +719,21 @@ MediaPlayer::SupportsType MediaPlayerPrivateGStreamerMSE::supportsType(const Med > // 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 = GstRegistryScannerMSE::singleton(); > // Spec says we should not return "probably" if the codecs string is empty. >- if (mimeTypeCache().contains(containerType)) { >+ if (gstRegistryScanner.supportsContainerType(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) >diff --git a/Source/WebCore/platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.h b/Source/WebCore/platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.h >index 2dfa732fcbf26ba687f1a9814ab7663eef985474..87aa2ac088f6748467299f995ca5eb2c1e0d1469 100644 >--- a/Source/WebCore/platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.h >+++ b/Source/WebCore/platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.h >@@ -82,9 +82,6 @@ public: > 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&); >diff --git a/Source/WebCore/platform/mediacapabilities/MediaEngineConfigurationFactory.cpp b/Source/WebCore/platform/mediacapabilities/MediaEngineConfigurationFactory.cpp >index 329e294ca2f6019aca49f39a61178dd526691661..c94830dfd1ed5fa43194a9fe99543ed30d71102f 100644 >--- a/Source/WebCore/platform/mediacapabilities/MediaEngineConfigurationFactory.cpp >+++ b/Source/WebCore/platform/mediacapabilities/MediaEngineConfigurationFactory.cpp >@@ -39,6 +39,10 @@ > #include "MediaEngineConfigurationFactoryCocoa.h" > #endif > >+#if USE(GSTREAMER) >+#include "MediaEngineConfigurationFactoryGStreamer.h" >+#endif >+ > namespace WebCore { > > static bool& mockEnabled() >@@ -58,6 +62,9 @@ static const FactoryVector& factories() > static NeverDestroyed<FactoryVector> factories = makeNeverDestroyed(FactoryVector({ > #if PLATFORM(COCOA) > { &createMediaPlayerDecodingConfigurationCocoa, nullptr }, >+#endif >+#if USE(GSTREAMER) >+ { &createMediaPlayerDecodingConfigurationGStreamer, nullptr }, > #endif > })); > return factories;
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Flags:
calvaris
:
review+
calvaris
:
commit-queue-
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 191191
:
353693
|
353695
|
353700
|
353707
|
353714
|
353838
| 362011