Title: [246194] trunk/Source/WebCore
Revision
246194
Author
[email protected]
Date
2019-06-07 01:59:59 -0700 (Fri, 07 Jun 2019)

Log Message

[GStreamer] AVC1 decoding capabilities probing support
https://bugs.webkit.org/show_bug.cgi?id=198569

Patch by Philippe Normand <[email protected]> on 2019-06-07
Reviewed by Xabier Rodriguez-Calvar.

When capabilities for an avc1 codec are requested, the registry scanner looks
for a compatible decoder for the given H.264 profile and level.

This new approach can be avoided by using the WEBKIT_GST_MAX_AVC1_RESOLUTION
environment variable. If supplied, the decoder capabilities won't be probed and
the codec will be advertised as supported if it complies with the contents of
the environment variable. The resolutions currently handled are specifically:
1080P, 720P and 480P. We don't handle framerate checking yet, so the implied
H.264 levels are assumed to be for 30FPS.

* platform/graphics/gstreamer/GStreamerRegistryScanner.cpp:
(WebCore::GStreamerRegistryScanner::isCodecSupported const):
(WebCore::GStreamerRegistryScanner::areInputCapsAccepted const):
(WebCore::GStreamerRegistryScanner::isAVC1CodecSupported const):
* platform/graphics/gstreamer/GStreamerRegistryScanner.h:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (246193 => 246194)


--- trunk/Source/WebCore/ChangeLog	2019-06-07 08:27:25 UTC (rev 246193)
+++ trunk/Source/WebCore/ChangeLog	2019-06-07 08:59:59 UTC (rev 246194)
@@ -1,3 +1,26 @@
+2019-06-07  Philippe Normand  <[email protected]>
+
+        [GStreamer] AVC1 decoding capabilities probing support
+        https://bugs.webkit.org/show_bug.cgi?id=198569
+
+        Reviewed by Xabier Rodriguez-Calvar.
+
+        When capabilities for an avc1 codec are requested, the registry scanner looks
+        for a compatible decoder for the given H.264 profile and level.
+
+        This new approach can be avoided by using the WEBKIT_GST_MAX_AVC1_RESOLUTION
+        environment variable. If supplied, the decoder capabilities won't be probed and
+        the codec will be advertised as supported if it complies with the contents of
+        the environment variable. The resolutions currently handled are specifically:
+        1080P, 720P and 480P. We don't handle framerate checking yet, so the implied
+        H.264 levels are assumed to be for 30FPS.
+
+        * platform/graphics/gstreamer/GStreamerRegistryScanner.cpp:
+        (WebCore::GStreamerRegistryScanner::isCodecSupported const):
+        (WebCore::GStreamerRegistryScanner::areInputCapsAccepted const):
+        (WebCore::GStreamerRegistryScanner::isAVC1CodecSupported const):
+        * platform/graphics/gstreamer/GStreamerRegistryScanner.h:
+
 2019-06-07  Joonghun Park  <[email protected]>
 
         Implement tab-size with units

Modified: trunk/Source/WebCore/platform/graphics/gstreamer/GStreamerRegistryScanner.cpp (246193 => 246194)


--- trunk/Source/WebCore/platform/graphics/gstreamer/GStreamerRegistryScanner.cpp	2019-06-07 08:27:25 UTC (rev 246193)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/GStreamerRegistryScanner.cpp	2019-06-07 08:59:59 UTC (rev 246194)
@@ -24,6 +24,7 @@
 #include "ContentType.h"
 #include "GStreamerCommon.h"
 #include <fnmatch.h>
+#include <gst/pbutils/codec-utils.h>
 #include <wtf/PrintStream.h>
 
 namespace WebCore {
@@ -66,7 +67,7 @@
     gst_plugin_feature_list_free(m_demuxerFactories);
 }
 
-GStreamerRegistryScanner::RegistryLookupResult GStreamerRegistryScanner::hasElementForMediaType(GList* elementFactories, const char* capsString, bool shouldCheckHardwareClassifier)
+GStreamerRegistryScanner::RegistryLookupResult GStreamerRegistryScanner::hasElementForMediaType(GList* elementFactories, const char* capsString, bool shouldCheckHardwareClassifier) const
 {
     GRefPtr<GstCaps> caps = adoptGRef(gst_caps_from_string(capsString));
     GList* candidates = gst_element_factory_list_filter(elementFactories, caps.get(), GST_PAD_SINK, false);
@@ -280,11 +281,15 @@
         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;
+    if (codec.startsWith("avc1"))
+        supported = isAVC1CodecSupported(codec, shouldCheckForHardwareUse);
+    else {
+        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;
+            }
         }
     }
 
@@ -302,6 +307,61 @@
     return true;
 }
 
+bool GStreamerRegistryScanner::isAVC1CodecSupported(const String& codec, bool shouldCheckForHardwareUse) const
+{
+    auto components = codec.split('.');
+    long int spsAsInteger = strtol(components[1].utf8().data(), nullptr, 16);
+    uint8_t sps[3];
+    sps[0] = spsAsInteger >> 16;
+    sps[1] = spsAsInteger >> 8;
+    sps[2] = spsAsInteger;
+
+    const char* profile = "" 3);
+    const char* level = gst_codec_utils_h264_get_level(sps, 3);
+    GST_DEBUG("Codec %s translates to H.264 profile %s and level %s", codec.utf8().data(), profile, level);
+
+    auto checkH264Caps = [&](const char* capsString) {
+        bool supported = false;
+        auto lookupResult = hasElementForMediaType(m_videoDecoderFactories, capsString, true);
+        supported = lookupResult;
+        if (shouldCheckForHardwareUse)
+            supported = lookupResult.isUsingHardware;
+        GST_DEBUG("%s decoding supported for codec %s: %s", shouldCheckForHardwareUse ? "Hardware" : "Software", codec.utf8().data(), boolForPrinting(supported));
+        return supported;
+    };
+
+    if (const char* maxVideoResolution = g_getenv("WEBKIT_GST_MAX_AVC1_RESOLUTION")) {
+        uint8_t levelAsInteger = gst_codec_utils_h264_get_level_idc(level);
+        GST_DEBUG("Maximum video resolution requested: %s, supplied codec level IDC: %u", maxVideoResolution, levelAsInteger);
+        uint8_t maxLevel = 0;
+        const char* maxLevelString = "";
+        if (!g_strcmp0(maxVideoResolution, "1080P")) {
+            maxLevel = 40;
+            maxLevelString = "4";
+        } else if (!g_strcmp0(maxVideoResolution, "720P")) {
+            maxLevel = 31;
+            maxLevelString = "3.1";
+        } else if (!g_strcmp0(maxVideoResolution, "480P")) {
+            maxLevel = 30;
+            maxLevelString = "3";
+        } else {
+            g_warning("Invalid value for WEBKIT_GST_MAX_AVC1_RESOLUTION. Currently supported, 1080P, 720P and 480P.");
+            return false;
+        }
+        if (levelAsInteger > maxLevel)
+            return false;
+        return checkH264Caps(makeString("video/x-h264, level=(string)", maxLevelString).utf8().data());
+    }
+
+    if (webkitGstCheckVersion(1, 17, 0)) {
+        GST_DEBUG("Checking video decoders for constrained caps");
+        return checkH264Caps(makeString("video/x-h264, level=(string)", level, ", profile="" profile).utf8().data());
+    }
+
+    GST_DEBUG("Falling back to unconstrained caps");
+    return checkH264Caps("video/x-h264");
+}
+
 GStreamerRegistryScanner::RegistryLookupResult GStreamerRegistryScanner::isDecodingSupported(MediaConfiguration& configuration) const
 {
     bool isSupported = false;

Modified: trunk/Source/WebCore/platform/graphics/gstreamer/GStreamerRegistryScanner.h (246193 => 246194)


--- trunk/Source/WebCore/platform/graphics/gstreamer/GStreamerRegistryScanner.h	2019-06-07 08:27:25 UTC (rev 246193)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/GStreamerRegistryScanner.h	2019-06-07 08:59:59 UTC (rev 246194)
@@ -72,8 +72,10 @@
     };
     void fillMimeTypeSetFromCapsMapping(Vector<GstCapsWebKitMapping>&);
 
-    RegistryLookupResult hasElementForMediaType(GList* elementFactories, const char* capsString, bool shouldCheckHardwareClassifier = false);
+    RegistryLookupResult hasElementForMediaType(GList* elementFactories, const char* capsString, bool shouldCheckHardwareClassifier = false) const;
 
+    bool isAVC1CodecSupported(const String& codec, bool shouldCheckForHardwareUse) const;
+
 private:
     bool m_isMediaSource;
     GList* m_audioDecoderFactories;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to