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;