- Revision
- 217045
- Author
- [email protected]
- Date
- 2017-05-18 07:05:15 -0700 (Thu, 18 May 2017)
Log Message
[GTK][GStreamer][MSE] Crash on youtube when MSE is enabled but gstreamer cant find the decoder element.
https://bugs.webkit.org/show_bug.cgi?id=167120
Patch by Vanessa Chipirrás Navalón <[email protected]> on 2017-05-18
Reviewed by Žan Doberšek.
This is because supportCodecs() doesn't check in runtime which plugins the player has.
So, a static function which returns a map with the plugins has been created. That map is later
used in the supportsCodecs() method to check if the requested codec matches any of the map.
* platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp:
(WebCore::MediaPlayerPrivateGStreamerBase::initializeGStreamerAndRegisterWebKitElements):
The declaration is moved into this class.
* platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp:
(WebCore::MediaPlayerPrivateGStreamer::isAvailable): This function calls the implementation of
initializeGstreamerAndRegisterWebKitElements function.
(WebCore::MediaPlayerPrivateGStreamer::load): Ditto
(WebCore::mimeTypeSet): Ditto
* platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.h: It is static type to expose
initializeGStreamerAndRegisterWebKitElements() function to be called from internal function
"which runs before MediaPlayerPrivateGStreamerBase initialization but needs to have GStreamer initialized".
* platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.cpp:
(WebCore::codecSet): It returns a map with the plugins has been created.
(WebCore::MediaPlayerPrivateGStreamerMSE::supportsCodecs): To check if the requested codec
matches any of the map from codecSet().
Modified Paths
Diff
Modified: trunk/Source/WebCore/ChangeLog (217044 => 217045)
--- trunk/Source/WebCore/ChangeLog 2017-05-18 12:56:46 UTC (rev 217044)
+++ trunk/Source/WebCore/ChangeLog 2017-05-18 14:05:15 UTC (rev 217045)
@@ -1,3 +1,30 @@
+2017-05-18 Vanessa Chipirrás Navalón <[email protected]>
+
+ [GTK][GStreamer][MSE] Crash on youtube when MSE is enabled but gstreamer cant find the decoder element.
+ https://bugs.webkit.org/show_bug.cgi?id=167120
+
+ Reviewed by Žan Doberšek.
+
+ This is because supportCodecs() doesn't check in runtime which plugins the player has.
+ So, a static function which returns a map with the plugins has been created. That map is later
+ used in the supportsCodecs() method to check if the requested codec matches any of the map.
+
+ * platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp:
+ (WebCore::MediaPlayerPrivateGStreamerBase::initializeGStreamerAndRegisterWebKitElements):
+ The declaration is moved into this class.
+ * platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp:
+ (WebCore::MediaPlayerPrivateGStreamer::isAvailable): This function calls the implementation of
+ initializeGstreamerAndRegisterWebKitElements function.
+ (WebCore::MediaPlayerPrivateGStreamer::load): Ditto
+ (WebCore::mimeTypeSet): Ditto
+ * platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.h: It is static type to expose
+ initializeGStreamerAndRegisterWebKitElements() function to be called from internal function
+ "which runs before MediaPlayerPrivateGStreamerBase initialization but needs to have GStreamer initialized".
+ * platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.cpp:
+ (WebCore::codecSet): It returns a map with the plugins has been created.
+ (WebCore::MediaPlayerPrivateGStreamerMSE::supportsCodecs): To check if the requested codec
+ matches any of the map from codecSet().
+
2017-05-18 Romain Bellessort <[email protected]>
[Readable Streams API] Align getDesiredSize with spec
Modified: trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp (217044 => 217045)
--- trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp 2017-05-18 12:56:46 UTC (rev 217044)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp 2017-05-18 14:05:15 UTC (rev 217045)
@@ -110,25 +110,9 @@
getSupportedTypes, supportsType, nullptr, nullptr, nullptr, supportsKeySystem);
}
-bool initializeGStreamerAndRegisterWebKitElements()
-{
- if (!initializeGStreamer())
- return false;
-
- registerWebKitGStreamerElements();
-
- GRefPtr<GstElementFactory> srcFactory = adoptGRef(gst_element_factory_find("webkitwebsrc"));
- if (!srcFactory) {
- GST_DEBUG_CATEGORY_INIT(webkit_media_player_debug, "webkitmediaplayer", 0, "WebKit media player");
- gst_element_register(nullptr, "webkitwebsrc", GST_RANK_PRIMARY + 100, WEBKIT_TYPE_WEB_SRC);
- }
-
- return true;
-}
-
bool MediaPlayerPrivateGStreamer::isAvailable()
{
- if (!initializeGStreamerAndRegisterWebKitElements())
+ if (!MediaPlayerPrivateGStreamerBase::initializeGStreamerAndRegisterWebKitElements())
return false;
GRefPtr<GstElementFactory> factory = adoptGRef(gst_element_factory_find("playbin"));
@@ -227,7 +211,7 @@
void MediaPlayerPrivateGStreamer::load(const String& urlString)
{
- if (!initializeGStreamerAndRegisterWebKitElements())
+ if (!MediaPlayerPrivateGStreamerBase::initializeGStreamerAndRegisterWebKitElements())
return;
URL url(URL(), urlString);
@@ -1776,7 +1760,7 @@
{
static NeverDestroyed<HashSet<String, ASCIICaseInsensitiveHash>> mimeTypes = []()
{
- initializeGStreamerAndRegisterWebKitElements();
+ MediaPlayerPrivateGStreamerBase::initializeGStreamerAndRegisterWebKitElements();
HashSet<String, ASCIICaseInsensitiveHash> set;
GList* audioDecoderFactories = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_DECODER | GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO, GST_RANK_MARGINAL);
Modified: trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp (217044 => 217045)
--- trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp 2017-05-18 12:56:46 UTC (rev 217044)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp 2017-05-18 14:05:15 UTC (rev 217045)
@@ -129,6 +129,22 @@
#endif
}
+bool MediaPlayerPrivateGStreamerBase::initializeGStreamerAndRegisterWebKitElements()
+{
+ if (!initializeGStreamer())
+ return false;
+
+ registerWebKitGStreamerElements();
+
+ GRefPtr<GstElementFactory> srcFactory = adoptGRef(gst_element_factory_find("webkitwebsrc"));
+ if (!srcFactory) {
+ GST_DEBUG_CATEGORY_INIT(webkit_media_player_debug, "webkitmediaplayer", 0, "WebKit media player");
+ gst_element_register(0, "webkitwebsrc", GST_RANK_PRIMARY + 100, WEBKIT_TYPE_WEB_SRC);
+ }
+
+ return true;
+}
+
static int greatestCommonDivisor(int a, int b)
{
while (b) {
Modified: trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.h (217044 => 217045)
--- trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.h 2017-05-18 12:56:46 UTC (rev 217044)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.h 2017-05-18 14:05:15 UTC (rev 217045)
@@ -75,7 +75,7 @@
bool ensureGstGLContext();
static GstContext* requestGLContext(const gchar* contextType, MediaPlayerPrivateGStreamerBase*);
#endif
-
+ static bool initializeGStreamerAndRegisterWebKitElements();
bool supportsMuting() const override { return true; }
void setMuted(bool) override;
bool muted() const;
Modified: trunk/Source/WebCore/platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.cpp (217044 => 217045)
--- trunk/Source/WebCore/platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.cpp 2017-05-18 12:56:46 UTC (rev 217044)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.cpp 2017-05-18 14:05:15 UTC (rev 217045)
@@ -48,7 +48,10 @@
#include <gst/pbutils/pbutils.h>
#include <gst/video/video.h>
#include <wtf/Condition.h>
+#include <wtf/HashSet.h>
#include <wtf/NeverDestroyed.h>
+#include <wtf/text/AtomicString.h>
+#include <wtf/text/AtomicStringHash.h>
static const char* dumpReadyState(WebCore::MediaPlayer::ReadyState readyState)
{
@@ -747,9 +750,84 @@
m_playbackPipeline->reattachTrack(appendPipeline->sourceBufferPrivate(), newTrack);
}
+const static HashSet<AtomicString>& codecSet()
+{
+ static NeverDestroyed<HashSet<AtomicString>> codecTypes = []()
+ {
+ MediaPlayerPrivateGStreamerBase::initializeGStreamerAndRegisterWebKitElements();
+ HashSet<AtomicString> set;
+
+ GList* audioDecoderFactories = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_DECODER | GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO, GST_RANK_MARGINAL);
+ GList* videoDecoderFactories = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_DECODER | GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO, GST_RANK_MARGINAL);
+
+ enum ElementType {
+ AudioDecoder = 0,
+ VideoDecoder
+ };
+ struct GstCapsWebKitMapping {
+ ElementType elementType;
+ const char* capsString;
+ Vector<AtomicString> webkitCodecs;
+ };
+
+ std::array<GstCapsWebKitMapping, 3> mapping = { {
+ { VideoDecoder, "video/x-h264, profile="" constrained-baseline, baseline }", { "x-h264" } },
+ { VideoDecoder, "video/x-h264, stream-format=avc", { "avc*"} },
+ { VideoDecoder, "video/mpeg, mpegversion=(int){1,2}, systemstream=(boolean)false", { "mpeg" } }
+ } };
+
+ for (auto& current : mapping) {
+ GList* factories = nullptr;
+ switch (current.elementType) {
+ case AudioDecoder:
+ factories = audioDecoderFactories;
+ break;
+ case VideoDecoder:
+ factories = videoDecoderFactories;
+ break;
+ default:
+ g_assert_not_reached();
+ break;
+ }
+
+ g_assert_nonnull(factories);
+
+ if (gstRegistryHasElementForMediaType(factories, current.capsString) && factories != nullptr) {
+ if (!current.webkitCodecs.isEmpty()) {
+ for (const auto& mimeType : current.webkitCodecs)
+ set.add(mimeType);
+ } else
+ set.add(AtomicString(current.capsString));
+ }
+ }
+
+ bool audioMpegSupported = false;
+ if (gstRegistryHasElementForMediaType(audioDecoderFactories, "audio/mpeg, mpegversion=(int)1, layer=(int)[1, 3]")) {
+ audioMpegSupported = true;
+ set.add(AtomicString("audio/mp3"));
+ }
+
+ if (gstRegistryHasElementForMediaType(audioDecoderFactories, "audio/mpeg, mpegversion=(int){2, 4}")) {
+ audioMpegSupported = true;
+ set.add(AtomicString("mp4a*"));
+ }
+
+ if (audioMpegSupported) {
+ set.add(AtomicString("audio/mpeg"));
+ set.add(AtomicString("audio/x-mpeg"));
+ }
+
+
+ gst_plugin_feature_list_free(audioDecoderFactories);
+ gst_plugin_feature_list_free(videoDecoderFactories);
+
+ return set;
+ }();
+ return codecTypes;
+}
+
bool MediaPlayerPrivateGStreamerMSE::supportsCodecs(const String& codecs)
{
- static Vector<const char*> supportedCodecs = { "avc*", "mp4a*", "mpeg", "x-h264" };
Vector<String> codecEntries;
codecs.split(',', false, codecEntries);
@@ -762,8 +840,8 @@
codec = codec.substring(slashIndex+1);
const char* codecData = codec.utf8().data();
- for (const auto& pattern : supportedCodecs) {
- isCodecSupported = !fnmatch(pattern, codecData, 0);
+ for (const auto& pattern : codecSet()) {
+ isCodecSupported = !fnmatch(pattern.string().utf8().data(), codecData, 0);
if (isCodecSupported)
break;
}