Changeset 246194 in webkit


Ignore:
Timestamp:
Jun 7, 2019 1:59:59 AM (5 years ago)
Author:
Philippe Normand
Message:

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

Patch by Philippe Normand <philn@igalia.com> 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:
Location:
trunk/Source/WebCore
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r246193 r246194  
     12019-06-07  Philippe Normand  <philn@igalia.com>
     2
     3        [GStreamer] AVC1 decoding capabilities probing support
     4        https://bugs.webkit.org/show_bug.cgi?id=198569
     5
     6        Reviewed by Xabier Rodriguez-Calvar.
     7
     8        When capabilities for an avc1 codec are requested, the registry scanner looks
     9        for a compatible decoder for the given H.264 profile and level.
     10
     11        This new approach can be avoided by using the WEBKIT_GST_MAX_AVC1_RESOLUTION
     12        environment variable. If supplied, the decoder capabilities won't be probed and
     13        the codec will be advertised as supported if it complies with the contents of
     14        the environment variable. The resolutions currently handled are specifically:
     15        1080P, 720P and 480P. We don't handle framerate checking yet, so the implied
     16        H.264 levels are assumed to be for 30FPS.
     17
     18        * platform/graphics/gstreamer/GStreamerRegistryScanner.cpp:
     19        (WebCore::GStreamerRegistryScanner::isCodecSupported const):
     20        (WebCore::GStreamerRegistryScanner::areInputCapsAccepted const):
     21        (WebCore::GStreamerRegistryScanner::isAVC1CodecSupported const):
     22        * platform/graphics/gstreamer/GStreamerRegistryScanner.h:
     23
    1242019-06-07  Joonghun Park  <jh718.park@samsung.com>
    225
  • trunk/Source/WebCore/platform/graphics/gstreamer/GStreamerRegistryScanner.cpp

    r244111 r246194  
    2525#include "GStreamerCommon.h"
    2626#include <fnmatch.h>
     27#include <gst/pbutils/codec-utils.h>
    2728#include <wtf/PrintStream.h>
    2829
     
    6768}
    6869
    69 GStreamerRegistryScanner::RegistryLookupResult GStreamerRegistryScanner::hasElementForMediaType(GList* elementFactories, const char* capsString, bool shouldCheckHardwareClassifier)
     70GStreamerRegistryScanner::RegistryLookupResult GStreamerRegistryScanner::hasElementForMediaType(GList* elementFactories, const char* capsString, bool shouldCheckHardwareClassifier) const
    7071{
    7172    GRefPtr<GstCaps> caps = adoptGRef(gst_caps_from_string(capsString));
     
    281282
    282283    bool supported = false;
    283     for (const auto& item : m_codecMap) {
    284         if (!fnmatch(item.key.string().utf8().data(), codec.utf8().data(), 0)) {
    285             supported = shouldCheckForHardwareUse ? item.value : true;
    286             if (supported)
    287                 break;
     284    if (codec.startsWith("avc1"))
     285        supported = isAVC1CodecSupported(codec, shouldCheckForHardwareUse);
     286    else {
     287        for (const auto& item : m_codecMap) {
     288            if (!fnmatch(item.key.string().utf8().data(), codec.utf8().data(), 0)) {
     289                supported = shouldCheckForHardwareUse ? item.value : true;
     290                if (supported)
     291                    break;
     292            }
    288293        }
    289294    }
     
    301306
    302307    return true;
     308}
     309
     310bool GStreamerRegistryScanner::isAVC1CodecSupported(const String& codec, bool shouldCheckForHardwareUse) const
     311{
     312    auto components = codec.split('.');
     313    long int spsAsInteger = strtol(components[1].utf8().data(), nullptr, 16);
     314    uint8_t sps[3];
     315    sps[0] = spsAsInteger >> 16;
     316    sps[1] = spsAsInteger >> 8;
     317    sps[2] = spsAsInteger;
     318
     319    const char* profile = gst_codec_utils_h264_get_profile(sps, 3);
     320    const char* level = gst_codec_utils_h264_get_level(sps, 3);
     321    GST_DEBUG("Codec %s translates to H.264 profile %s and level %s", codec.utf8().data(), profile, level);
     322
     323    auto checkH264Caps = [&](const char* capsString) {
     324        bool supported = false;
     325        auto lookupResult = hasElementForMediaType(m_videoDecoderFactories, capsString, true);
     326        supported = lookupResult;
     327        if (shouldCheckForHardwareUse)
     328            supported = lookupResult.isUsingHardware;
     329        GST_DEBUG("%s decoding supported for codec %s: %s", shouldCheckForHardwareUse ? "Hardware" : "Software", codec.utf8().data(), boolForPrinting(supported));
     330        return supported;
     331    };
     332
     333    if (const char* maxVideoResolution = g_getenv("WEBKIT_GST_MAX_AVC1_RESOLUTION")) {
     334        uint8_t levelAsInteger = gst_codec_utils_h264_get_level_idc(level);
     335        GST_DEBUG("Maximum video resolution requested: %s, supplied codec level IDC: %u", maxVideoResolution, levelAsInteger);
     336        uint8_t maxLevel = 0;
     337        const char* maxLevelString = "";
     338        if (!g_strcmp0(maxVideoResolution, "1080P")) {
     339            maxLevel = 40;
     340            maxLevelString = "4";
     341        } else if (!g_strcmp0(maxVideoResolution, "720P")) {
     342            maxLevel = 31;
     343            maxLevelString = "3.1";
     344        } else if (!g_strcmp0(maxVideoResolution, "480P")) {
     345            maxLevel = 30;
     346            maxLevelString = "3";
     347        } else {
     348            g_warning("Invalid value for WEBKIT_GST_MAX_AVC1_RESOLUTION. Currently supported, 1080P, 720P and 480P.");
     349            return false;
     350        }
     351        if (levelAsInteger > maxLevel)
     352            return false;
     353        return checkH264Caps(makeString("video/x-h264, level=(string)", maxLevelString).utf8().data());
     354    }
     355
     356    if (webkitGstCheckVersion(1, 17, 0)) {
     357        GST_DEBUG("Checking video decoders for constrained caps");
     358        return checkH264Caps(makeString("video/x-h264, level=(string)", level, ", profile=(string)", profile).utf8().data());
     359    }
     360
     361    GST_DEBUG("Falling back to unconstrained caps");
     362    return checkH264Caps("video/x-h264");
    303363}
    304364
  • trunk/Source/WebCore/platform/graphics/gstreamer/GStreamerRegistryScanner.h

    r241585 r246194  
    7373    void fillMimeTypeSetFromCapsMapping(Vector<GstCapsWebKitMapping>&);
    7474
    75     RegistryLookupResult hasElementForMediaType(GList* elementFactories, const char* capsString, bool shouldCheckHardwareClassifier = false);
     75    RegistryLookupResult hasElementForMediaType(GList* elementFactories, const char* capsString, bool shouldCheckHardwareClassifier = false) const;
     76
     77    bool isAVC1CodecSupported(const String& codec, bool shouldCheckForHardwareUse) const;
    7678
    7779private:
Note: See TracChangeset for help on using the changeset viewer.