WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
[patch]
Patch
bug-191191-20181102140401.patch (text/plain), 56.72 KB, created by
Philippe Normand
on 2018-11-02 07:04:03 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Philippe Normand
Created:
2018-11-02 07:04:03 PDT
Size:
56.72 KB
patch
obsolete
>Subversion Revision: 237727 >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index 3c9663735cd8b2d02efee2d37799d431bcce670a..9edb348eff55a68c2bbf41b2e2e92afc65e3c91c 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. >+ > 2018-11-02 Philippe Normand <pnormand@igalia.com> > > [GStreamer] Move elements registration to GStreamerCommon >diff --git a/Source/WebCore/platform/GStreamer.cmake b/Source/WebCore/platform/GStreamer.cmake >index d9a1fdb30c420f0981bfeef4dcdf4c96afdda25d..ba257ade68f8dfdba0545d1b12a96f2d2e855f58 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 e7e9052b80d137c6b7deb04c5cde0aa61e31956f..180fec8760aabf5d5282e13f101bf4288fd3f58d 100644 >--- a/Source/WebCore/platform/graphics/MediaPlayer.cpp >+++ b/Source/WebCore/platform/graphics/MediaPlayer.cpp >@@ -1603,6 +1603,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 01dd965e9a6d6c5ffd2679a31f5e1c50852683a3..da2130f0104a3efab6cc3599cf75c5895763afd8 100644 >--- a/Source/WebCore/platform/graphics/MediaPlayer.h >+++ b/Source/WebCore/platform/graphics/MediaPlayer.h >@@ -252,8 +252,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 52649bba7ab8c4d9ab7539ae329964838381fc99..c68aa96a223c92587362a78c10dd74c49183d1e9 100644 >--- a/Source/WebCore/platform/graphics/gstreamer/GStreamerCommon.cpp >+++ b/Source/WebCore/platform/graphics/gstreamer/GStreamerCommon.cpp >@@ -301,16 +301,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 110b6ee3b93c3c5da8f596cd09a0d845d1d2e04a..71605bf3029d77c57b4ba8a78ccfd13d3473e481 100644 >--- a/Source/WebCore/platform/graphics/gstreamer/GStreamerCommon.h >+++ b/Source/WebCore/platform/graphics/gstreamer/GStreamerCommon.h >@@ -117,7 +117,6 @@ private: > bool m_isValid { false }; > }; > >-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..b4ff5a1c8908841f6ef225a3f50bee76b567128d >--- /dev/null >+++ b/Source/WebCore/platform/graphics/gstreamer/GstRegistryScanner.cpp >@@ -0,0 +1,307 @@ >+/* >+ * 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) >+#include "GstRegistryScanner.h" >+ >+#include "ContentType.h" >+#include "GRefPtrGStreamer.h" >+#include <fnmatch.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_videoDecoderFactories = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_DECODER | 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 >+ 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_videoDecoderFactories); >+ gst_plugin_feature_list_free(m_demuxerFactories); >+} >+ >+GstRegistryScanner::RegistryLookupResult GstRegistryScanner::gstRegistryHasElementForMediaType(GList* elementFactories, const char* capsString, bool checkHardwareClassifier) >+{ >+ GRefPtr<GstCaps> caps = adoptGRef(gst_caps_from_string(capsString)); >+ GList* candidates = gst_element_factory_list_filter(elementFactories, caps.get(), GST_PAD_SINK, false); >+ bool supported = candidates; >+ bool usingHardware = false; >+ >+ if (checkHardwareClassifier) { >+ 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")) { >+ usingHardware = true; >+ break; >+ } >+ } >+ } >+ >+ gst_plugin_feature_list_free(candidates); >+ return GstRegistryScanner::RegistryLookupResult { supported, usingHardware }; >+} >+ >+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("mp4a*"), false); >+ } >+ >+ bool opusSupported = gstRegistryHasElementForMediaType(m_audioDecoderFactories, "audio/x-opus"); >+ if (opusSupported) { >+ m_mimeTypeSet.add(AtomicString("audio/opus")); >+ m_codecMap.add(AtomicString("opus"), false); >+ m_codecMap.add(AtomicString("x-opus"), false); >+ } >+ >+ bool vorbisSupported = gstRegistryHasElementForMediaType(m_audioDecoderFactories, "audio/x-vorbis"); >+ if (vorbisSupported) { >+ 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_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::supportsCodec(String codec, bool usingHardware) 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); >+ >+ GST_LOG("Checking codec \"%s\"", codec.utf8().data()); >+ for (const auto& item : m_codecMap) { >+ bool codecMatchesPattern = !fnmatch(item.key.string().utf8().data(), codec.utf8().data(), 0); >+ if (codecMatchesPattern) >+ return usingHardware ? item.value : true; >+ } >+ >+ GST_LOG("Unsupported"); >+ return false; >+} >+ >+bool GstRegistryScanner::supportsAllCodecs(const Vector<String>& codecs, bool usingHardware) const >+{ >+ for (String codec : codecs) { >+ if (!supportsCodec(codec, usingHardware)) >+ return false; >+ } >+ >+ return true; >+} >+ >+bool GstRegistryScanner::isDecodingSupported(MediaConfiguration& configuration, bool* usingHardware) const >+{ >+ bool decoderFound = false; >+ if (usingHardware) >+ *usingHardware = 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); >+ decoderFound = supportsContainerType(contentType.containerType()); >+ auto codecs = contentType.codecs(); >+ if (usingHardware && !codecs.isEmpty()) >+ *usingHardware = supportsAllCodecs(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); >+ decoderFound = supportsContainerType(contentType.containerType()); >+ } >+ >+ return decoderFound; >+} >+ >+} >+#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..e572343c24371bc0bdf349a93f0f46c18adcc00f >--- /dev/null >+++ b/Source/WebCore/platform/graphics/gstreamer/GstRegistryScanner.h >@@ -0,0 +1,87 @@ >+/* >+ * 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); } >+ >+ bool isDecodingSupported(MediaConfiguration&, bool* usingHardware = nullptr) const; >+ bool supportsCodec(String codec, bool usingHardware = false) const; >+ bool supportsAllCodecs(const Vector<String>& codecs, bool usingHardware = 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>&); >+ >+ struct RegistryLookupResult { >+ bool supported; >+ bool usingHardware; >+ >+ operator bool() const { return supported; } >+ }; >+ RegistryLookupResult gstRegistryHasElementForMediaType(GList* elementFactories, const char* capsString, bool checkHardwareClassifier = false); >+ >+private: >+ bool m_isMediaSource; >+ GList* m_audioDecoderFactories; >+ GList* m_videoDecoderFactories; >+ 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..a385e27e314b604837569c50186088ae21fb0bac >--- /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 >+ bool usingHardware = false; >+ MediaCapabilitiesInfo info; >+ info.supported = scanner.isDecodingSupported(configuration, &usingHardware); >+ info.powerEfficient = 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 fca92ed9fe78c0b49118bece728b1fdb00372d39..fcc432fcba91364a98d7a0b613f6dd41ef74b187 100644 >--- a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp >+++ b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp >@@ -30,6 +30,7 @@ > > #include "FileSystem.h" > #include "GStreamerCommon.h" >+#include "GstRegistryScanner.h" > #include "HTTPHeaderNames.h" > #include "MIMETypeRegistry.h" > #include "MediaPlayer.h" >@@ -2208,137 +2209,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) >@@ -2358,30 +2232,21 @@ 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(); >+ if (codecs.isEmpty()) >+ result = MediaPlayer::MayBeSupported; >+ else >+ result = gstRegistryScanner.supportsAllCodecs(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 839da62d77110de7a34ec2936b2e8cf55081153b..e5f8eb84b535dfc879dc553cf40074abab8a494c 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" >@@ -162,7 +163,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); >@@ -570,7 +572,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.supportsCodec(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 2cc3d1a7e090669dc373cc524838c34fb5586f70..5ac175b3bb23699e6ce10e6fa9075d7950c8d3f2 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" >@@ -42,7 +43,6 @@ > #include "URL.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,24 @@ 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 = gstRegistryScanner.supportsAllCodecs(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 2257e9e6830acb18c6f08f7186bf7758b72735d7..02aa1d15c7e11bb7f63a8fd69241f673507a2ee7 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); >- > #if ENABLE(ENCRYPTED_MEDIA) > void attemptToDecryptWithInstance(CDMInstance&) final; > #endif >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
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 191191
:
353693
|
353695
|
353700
|
353707
|
353714
|
353838
|
362011