Changeset 270019 in webkit


Ignore:
Timestamp:
Nov 19, 2020 12:54:28 AM (3 years ago)
Author:
Carlos Garcia Campos
Message:

[GStreamer] GStreamerRegistryScanner cleanups and improvements
https://bugs.webkit.org/show_bug.cgi?id=219078

Reviewed by Philippe Normand.

We are creating the factories and keeping them alive forever, because GStreamerRegistryScanner is singleton. We
can just delete them after the initialization and then create the factories we need on demand when checking AV1
codecs. This patch includes some other minor fixes and cleanups (missing const, avoid using blackList, etc.)

  • platform/graphics/gstreamer/GStreamerRegistryScanner.cpp:

(WebCore::GStreamerRegistryScanner::ElementFactories::ElementFactories): Create the factories for the given types.
(WebCore::GStreamerRegistryScanner::ElementFactories::~ElementFactories): Destroy the factories.
(WebCore::GStreamerRegistryScanner::ElementFactories::elementFactoryTypeToString): Return a string for the given
factory type, used for logging.
(WebCore::GStreamerRegistryScanner::ElementFactories::factory const): Return the factory for the given type.
(WebCore::GStreamerRegistryScanner::ElementFactories::hasElementForMediaType const): Moved here now receiving a
factory type instead of the factory itself.
(WebCore::GStreamerRegistryScanner::GStreamerRegistryScanner): Create a ElementFactories for all the types and
pass it to the initializers.
(WebCore::GStreamerRegistryScanner::mimeTypeSet const): Use release assert and remove the return.
(WebCore::GStreamerRegistryScanner::isContainerTypeSupported const): Ditto.
(WebCore::GStreamerRegistryScanner::fillMimeTypeSetFromCapsMapping): It receives a ElementFactories now.
(WebCore::GStreamerRegistryScanner::initializeDecoders): Ditto.
(WebCore::GStreamerRegistryScanner::initializeEncoders): Ditto.
(WebCore::GStreamerRegistryScanner::isCodecSupported const): Make the received code name const.
(WebCore::GStreamerRegistryScanner::areAllCodecsSupported const): Use const references to iterate the codecs.
(WebCore::GStreamerRegistryScanner::isAVC1CodecSupported const): Create a ElementFactories for the appropriate
type and use to check if the given codec is supported.
(WebCore::GStreamerRegistryScanner::isConfigurationSupported const): Make mediaConfiguration parameter const.
(WebCore::GStreamerRegistryScanner::~GStreamerRegistryScanner): Deleted.
(WebCore::GStreamerRegistryScanner::mimeTypeSet): Deleted.
(WebCore::GStreamerRegistryScanner::hasElementForMediaType const): Deleted.

  • platform/graphics/gstreamer/GStreamerRegistryScanner.h:
Location:
trunk/Source/WebCore
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r270018 r270019  
     12020-11-19  Carlos Garcia Campos  <cgarcia@igalia.com>
     2
     3        [GStreamer] GStreamerRegistryScanner cleanups and improvements
     4        https://bugs.webkit.org/show_bug.cgi?id=219078
     5
     6        Reviewed by Philippe Normand.
     7
     8        We are creating the factories and keeping them alive forever, because GStreamerRegistryScanner is singleton. We
     9        can just delete them after the initialization and then create the factories we need on demand when checking AV1
     10        codecs. This patch includes some other minor fixes and cleanups (missing const, avoid using blackList, etc.)
     11
     12        * platform/graphics/gstreamer/GStreamerRegistryScanner.cpp:
     13        (WebCore::GStreamerRegistryScanner::ElementFactories::ElementFactories): Create the factories for the given types.
     14        (WebCore::GStreamerRegistryScanner::ElementFactories::~ElementFactories): Destroy the factories.
     15        (WebCore::GStreamerRegistryScanner::ElementFactories::elementFactoryTypeToString): Return a string for the given
     16        factory type, used for logging.
     17        (WebCore::GStreamerRegistryScanner::ElementFactories::factory const): Return the factory for the given type.
     18        (WebCore::GStreamerRegistryScanner::ElementFactories::hasElementForMediaType const): Moved here now receiving a
     19        factory type instead of the factory itself.
     20        (WebCore::GStreamerRegistryScanner::GStreamerRegistryScanner): Create a ElementFactories for all the types and
     21        pass it to the initializers.
     22        (WebCore::GStreamerRegistryScanner::mimeTypeSet const): Use release assert and remove the return.
     23        (WebCore::GStreamerRegistryScanner::isContainerTypeSupported const): Ditto.
     24        (WebCore::GStreamerRegistryScanner::fillMimeTypeSetFromCapsMapping): It receives a ElementFactories now.
     25        (WebCore::GStreamerRegistryScanner::initializeDecoders): Ditto.
     26        (WebCore::GStreamerRegistryScanner::initializeEncoders): Ditto.
     27        (WebCore::GStreamerRegistryScanner::isCodecSupported const): Make the received code name const.
     28        (WebCore::GStreamerRegistryScanner::areAllCodecsSupported const): Use const references to iterate the codecs.
     29        (WebCore::GStreamerRegistryScanner::isAVC1CodecSupported const): Create a ElementFactories for the appropriate
     30        type and use to check if the given codec is supported.
     31        (WebCore::GStreamerRegistryScanner::isConfigurationSupported const): Make mediaConfiguration parameter const.
     32        (WebCore::GStreamerRegistryScanner::~GStreamerRegistryScanner): Deleted.
     33        (WebCore::GStreamerRegistryScanner::mimeTypeSet): Deleted.
     34        (WebCore::GStreamerRegistryScanner::hasElementForMediaType const): Deleted.
     35        * platform/graphics/gstreamer/GStreamerRegistryScanner.h:
     36
    1372020-11-17  Sergio Villar Senin  <svillar@igalia.com>
    238
  • trunk/Source/WebCore/platform/graphics/gstreamer/GStreamerRegistryScanner.cpp

    r269685 r270019  
    4040}
    4141
     42GStreamerRegistryScanner::ElementFactories::ElementFactories(OptionSet<ElementFactories::Type> types)
     43{
     44    if (types.contains(Type::AudioDecoder))
     45        audioDecoderFactories = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_DECODER | GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO, GST_RANK_MARGINAL);
     46    if (types.contains(Type::AudioParser))
     47        audioParserFactories = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_PARSER | GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO, GST_RANK_NONE);
     48    if (types.contains(Type::VideoDecoder))
     49        videoDecoderFactories = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_DECODER | GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO, GST_RANK_MARGINAL);
     50    if (types.contains(Type::VideoParser))
     51        videoParserFactories = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_PARSER | GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO, GST_RANK_MARGINAL);
     52    if (types.contains(Type::Demuxer))
     53        demuxerFactories = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_DEMUXER, GST_RANK_MARGINAL);
     54    if (types.contains(Type::AudioEncoder))
     55        audioEncoderFactories = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_ENCODER | GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO, GST_RANK_MARGINAL);
     56    if (types.contains(Type::VideoEncoder))
     57        videoEncoderFactories = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_ENCODER | GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO, GST_RANK_MARGINAL);
     58    if (types.contains(Type::Muxer))
     59        muxerFactories = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_MUXER, GST_RANK_MARGINAL);
     60}
     61
     62GStreamerRegistryScanner::ElementFactories::~ElementFactories()
     63{
     64    gst_plugin_feature_list_free(audioDecoderFactories);
     65    gst_plugin_feature_list_free(audioParserFactories);
     66    gst_plugin_feature_list_free(videoDecoderFactories);
     67    gst_plugin_feature_list_free(videoParserFactories);
     68    gst_plugin_feature_list_free(demuxerFactories);
     69    gst_plugin_feature_list_free(audioEncoderFactories);
     70    gst_plugin_feature_list_free(videoEncoderFactories);
     71    gst_plugin_feature_list_free(muxerFactories);
     72}
     73
     74const char* GStreamerRegistryScanner::ElementFactories::elementFactoryTypeToString(GStreamerRegistryScanner::ElementFactories::Type factoryType)
     75{
     76    switch (factoryType) {
     77    case Type::AudioParser:
     78        return "audio parser";
     79    case Type::AudioDecoder:
     80        return "audio decoder";
     81    case Type::VideoParser:
     82        return "video parser";
     83    case Type::VideoDecoder:
     84        return "video decoder";
     85    case Type::Demuxer:
     86        return "demuxer";
     87    case Type::AudioEncoder:
     88        return "audio encoder";
     89    case Type::VideoEncoder:
     90        return "video encoder";
     91    case Type::Muxer:
     92        return "muxer";
     93    case Type::All:
     94        break;
     95    }
     96
     97    RELEASE_ASSERT_NOT_REACHED();
     98}
     99
     100GList* GStreamerRegistryScanner::ElementFactories::factory(GStreamerRegistryScanner::ElementFactories::Type factoryType) const
     101{
     102    switch (factoryType) {
     103    case GStreamerRegistryScanner::ElementFactories::Type::AudioParser:
     104        return audioParserFactories;
     105    case GStreamerRegistryScanner::ElementFactories::Type::AudioDecoder:
     106        return audioDecoderFactories;
     107    case GStreamerRegistryScanner::ElementFactories::Type::VideoParser:
     108        return videoParserFactories;
     109    case GStreamerRegistryScanner::ElementFactories::Type::VideoDecoder:
     110        return videoDecoderFactories;
     111    case GStreamerRegistryScanner::ElementFactories::Type::Demuxer:
     112        return demuxerFactories;
     113    case GStreamerRegistryScanner::ElementFactories::Type::AudioEncoder:
     114        return audioEncoderFactories;
     115    case GStreamerRegistryScanner::ElementFactories::Type::VideoEncoder:
     116        return videoEncoderFactories;
     117    case GStreamerRegistryScanner::ElementFactories::Type::Muxer:
     118        return muxerFactories;
     119    case GStreamerRegistryScanner::ElementFactories::Type::All:
     120        break;
     121    }
     122
     123    RELEASE_ASSERT_NOT_REACHED();
     124}
     125
     126GStreamerRegistryScanner::RegistryLookupResult GStreamerRegistryScanner::ElementFactories::hasElementForMediaType(ElementFactories::Type factoryType, const char* capsString, ElementFactories::CheckHardwareClassifier shouldCheckHardwareClassifier, Optional<Vector<String>> disallowedList) const
     127{
     128    auto* elementFactories = factory(factoryType);
     129    if (!elementFactories)
     130        return { };
     131
     132    GstPadDirection padDirection = GST_PAD_SINK;
     133    if (factoryType == Type::AudioEncoder || factoryType == Type::VideoEncoder || factoryType == Type::Muxer)
     134        padDirection = GST_PAD_SRC;
     135
     136    GRefPtr<GstCaps> caps = adoptGRef(gst_caps_from_string(capsString));
     137    GList* candidates = gst_element_factory_list_filter(elementFactories, caps.get(), padDirection, false);
     138    bool isSupported = candidates;
     139    bool isUsingHardware = false;
     140
     141    if (disallowedList.hasValue() && !disallowedList->isEmpty()) {
     142        bool hasValidCandidate = false;
     143        for (GList* factories = candidates; factories; factories = g_list_next(factories)) {
     144            String name = String::fromUTF8(gst_plugin_feature_get_name(GST_PLUGIN_FEATURE_CAST(factories->data)));
     145            if (disallowedList->contains(name))
     146                continue;
     147            hasValidCandidate = true;
     148            break;
     149        }
     150        if (!hasValidCandidate) {
     151            GST_WARNING("All %s elements matching caps %" GST_PTR_FORMAT " are disallowed", elementFactoryTypeToString(factoryType), caps.get());
     152            isSupported = false;
     153            shouldCheckHardwareClassifier = CheckHardwareClassifier::No;
     154        }
     155    }
     156
     157    if (shouldCheckHardwareClassifier == CheckHardwareClassifier::Yes) {
     158        for (GList* factories = candidates; factories; factories = g_list_next(factories)) {
     159            auto* factory = reinterpret_cast<GstElementFactory*>(factories->data);
     160            String metadata = gst_element_factory_get_metadata(factory, GST_ELEMENT_METADATA_KLASS);
     161            auto components = metadata.split('/');
     162            if (components.contains("Hardware")) {
     163                isUsingHardware = true;
     164                break;
     165            }
     166        }
     167    }
     168
     169    gst_plugin_feature_list_free(candidates);
     170    GST_LOG("Lookup result for %s matching caps %" GST_PTR_FORMAT " : isSupported=%s, isUsingHardware=%s", elementFactoryTypeToString(factoryType), caps.get(), boolForPrinting(isSupported), boolForPrinting(isUsingHardware));
     171    return { isSupported, isUsingHardware };
     172}
     173
    42174GStreamerRegistryScanner::GStreamerRegistryScanner(bool isMediaSource)
    43175    : m_isMediaSource(isMediaSource)
    44176{
    45177    GST_DEBUG_CATEGORY_INIT(webkit_media_gst_registry_scanner_debug, "webkitregistryscanner", 0, "WebKit GStreamer registry scanner");
    46     m_audioDecoderFactories = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_DECODER | GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO, GST_RANK_MARGINAL);
    47     m_audioParserFactories = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_PARSER | GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO, GST_RANK_NONE);
    48     m_videoDecoderFactories = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_DECODER | GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO, GST_RANK_MARGINAL);
    49     m_videoParserFactories = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_PARSER | GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO, GST_RANK_MARGINAL);
    50     m_demuxerFactories = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_DEMUXER, GST_RANK_MARGINAL);
    51 
    52     m_audioEncoderFactories = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_ENCODER | GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO, GST_RANK_MARGINAL);
    53     m_videoEncoderFactories = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_ENCODER | GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO, GST_RANK_MARGINAL);
    54     m_muxerFactories = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_MUXER, GST_RANK_MARGINAL);
    55 
    56     initializeDecoders();
    57     initializeEncoders();
     178
     179    ElementFactories factories(ElementFactories::Type::All);
     180    initializeDecoders(factories);
     181    initializeEncoders(factories);
     182
    58183#ifndef GST_DISABLE_GST_DEBUG
    59184    GST_DEBUG("%s registry scanner initialized", m_isMediaSource ? "MSE" : "Regular playback");
     
    69194}
    70195
    71 GStreamerRegistryScanner::~GStreamerRegistryScanner()
    72 {
    73     gst_plugin_feature_list_free(m_audioDecoderFactories);
    74     gst_plugin_feature_list_free(m_audioParserFactories);
    75     gst_plugin_feature_list_free(m_videoDecoderFactories);
    76     gst_plugin_feature_list_free(m_videoParserFactories);
    77     gst_plugin_feature_list_free(m_demuxerFactories);
    78     gst_plugin_feature_list_free(m_audioEncoderFactories);
    79     gst_plugin_feature_list_free(m_videoEncoderFactories);
    80     gst_plugin_feature_list_free(m_muxerFactories);
    81 }
    82 
    83 const HashSet<String, ASCIICaseInsensitiveHash>& GStreamerRegistryScanner::mimeTypeSet(Configuration configuration)
     196const HashSet<String, ASCIICaseInsensitiveHash>& GStreamerRegistryScanner::mimeTypeSet(Configuration configuration) const
    84197{
    85198    switch (configuration) {
     
    89202        return m_encoderMimeTypeSet;
    90203    }
    91     ASSERT_NOT_REACHED();
    92     return m_decoderMimeTypeSet;
    93 }
    94 
    95 bool GStreamerRegistryScanner::isContainerTypeSupported(Configuration configuration, String containerType) const
     204    RELEASE_ASSERT_NOT_REACHED();
     205}
     206
     207bool GStreamerRegistryScanner::isContainerTypeSupported(Configuration configuration, const String& containerType) const
    96208{
    97209    switch (configuration) {
     
    101213        return m_encoderMimeTypeSet.contains(containerType);
    102214    }
    103     ASSERT_NOT_REACHED();
    104     return false;
    105 }
    106 
    107 GStreamerRegistryScanner::RegistryLookupResult GStreamerRegistryScanner::hasElementForMediaType(GList* elementFactories, const char* capsString, bool shouldCheckHardwareClassifier, Optional<Vector<String>> blackList) const
    108 {
    109     GstPadDirection padDirection = GST_PAD_SINK;
    110     if (elementFactories == m_audioEncoderFactories || elementFactories == m_videoEncoderFactories || elementFactories == m_muxerFactories)
    111         padDirection = GST_PAD_SRC;
    112     GRefPtr<GstCaps> caps = adoptGRef(gst_caps_from_string(capsString));
    113     GList* candidates = gst_element_factory_list_filter(elementFactories, caps.get(), padDirection, false);
    114     bool isSupported = candidates;
    115     bool isUsingHardware = false;
    116 
    117     const char* elementType = "";
    118     if (elementFactories == m_audioParserFactories)
    119         elementType = "audio parser";
    120     else if (elementFactories == m_audioDecoderFactories)
    121         elementType = "audio decoder";
    122     else if (elementFactories == m_videoParserFactories)
    123         elementType = "video parser";
    124     else if (elementFactories == m_videoDecoderFactories)
    125         elementType = "video decoder";
    126     else if (elementFactories == m_demuxerFactories)
    127         elementType = "demuxer";
    128     else if (elementFactories == m_audioEncoderFactories)
    129         elementType = "audio encoder";
    130     else if (elementFactories == m_videoEncoderFactories)
    131         elementType = "video encoder";
    132     else if (elementFactories == m_muxerFactories)
    133         elementType = "muxer";
    134     else
    135         ASSERT_NOT_REACHED();
    136 
    137     if (blackList.hasValue() && !blackList->isEmpty()) {
    138         bool hasValidCandidate = false;
    139         for (GList* factories = candidates; factories; factories = g_list_next(factories)) {
    140             String name(gst_plugin_feature_get_name(GST_PLUGIN_FEATURE_CAST(factories->data)));
    141             if (blackList->contains(name))
    142                 continue;
    143             hasValidCandidate = true;
    144             break;
    145         }
    146         if (!hasValidCandidate) {
    147             GST_WARNING("All %s elements matching caps %" GST_PTR_FORMAT " are blacklisted", elementType, caps.get());
    148             isSupported = false;
    149             shouldCheckHardwareClassifier = false;
    150         }
    151     }
    152 
    153     if (shouldCheckHardwareClassifier) {
    154         for (GList* factories = candidates; factories; factories = g_list_next(factories)) {
    155             auto* factory = reinterpret_cast<GstElementFactory*>(factories->data);
    156             String metadata = gst_element_factory_get_metadata(factory, GST_ELEMENT_METADATA_KLASS);
    157             auto components = metadata.split('/');
    158             if (components.contains("Hardware")) {
    159                 isUsingHardware = true;
    160                 break;
    161             }
    162         }
    163     }
    164 
    165     gst_plugin_feature_list_free(candidates);
    166     GST_LOG("Lookup result for %s matching caps %" GST_PTR_FORMAT " : isSupported=%s, isUsingHardware=%s", elementType, caps.get(), boolForPrinting(isSupported), boolForPrinting(isUsingHardware));
    167     return GStreamerRegistryScanner::RegistryLookupResult { isSupported, isUsingHardware };
    168 }
    169 
    170 void GStreamerRegistryScanner::fillMimeTypeSetFromCapsMapping(Vector<GstCapsWebKitMapping>& mapping)
    171 {
    172     for (auto& current : mapping) {
    173         GList* factories;
    174         switch (current.elementType) {
    175         case Demuxer:
    176             factories = m_demuxerFactories;
    177             break;
    178         case AudioDecoder:
    179             factories = m_audioDecoderFactories;
    180             break;
    181         case VideoDecoder:
    182             factories = m_videoDecoderFactories;
    183             break;
    184         }
    185 
    186         if (hasElementForMediaType(factories, current.capsString)) {
     215    RELEASE_ASSERT_NOT_REACHED();
     216}
     217
     218void GStreamerRegistryScanner::fillMimeTypeSetFromCapsMapping(const GStreamerRegistryScanner::ElementFactories& factories, const Vector<GstCapsWebKitMapping>& mapping)
     219{
     220    for (const auto& current : mapping) {
     221        if (factories.hasElementForMediaType(current.elementType, current.capsString)) {
    187222            if (!current.webkitCodecPatterns.isEmpty()) {
    188223                for (const auto& pattern : current.webkitCodecPatterns)
     
    198233}
    199234
    200 void GStreamerRegistryScanner::initializeDecoders()
    201 {
    202     if (hasElementForMediaType(m_audioDecoderFactories, "audio/mpeg, mpegversion=(int)4")) {
     235void GStreamerRegistryScanner::initializeDecoders(const GStreamerRegistryScanner::ElementFactories& factories)
     236{
     237    if (factories.hasElementForMediaType(ElementFactories::Type::AudioDecoder, "audio/mpeg, mpegversion=(int)4")) {
    203238        m_decoderMimeTypeSet.add(AtomString("audio/aac"));
    204239        m_decoderMimeTypeSet.add(AtomString("audio/mp4"));
     
    208243    }
    209244
    210     auto opusSupported = hasElementForMediaType(m_audioDecoderFactories, "audio/x-opus");
    211     if (opusSupported && (!m_isMediaSource || hasElementForMediaType(m_audioParserFactories, "audio/x-opus"))) {
     245    auto opusSupported = factories.hasElementForMediaType(ElementFactories::Type::AudioDecoder, "audio/x-opus");
     246    if (opusSupported && (!m_isMediaSource || factories.hasElementForMediaType(ElementFactories::Type::AudioParser, "audio/x-opus"))) {
    212247        m_decoderMimeTypeSet.add(AtomString("audio/opus"));
    213248        m_decoderCodecMap.add(AtomString("opus"), false);
     
    215250    }
    216251
    217     auto vorbisSupported = hasElementForMediaType(m_audioDecoderFactories, "audio/x-vorbis");
    218     if (vorbisSupported && (!m_isMediaSource || hasElementForMediaType(m_audioParserFactories, "audio/x-vorbis"))) {
     252    auto vorbisSupported = factories.hasElementForMediaType(ElementFactories::Type::AudioDecoder, "audio/x-vorbis");
     253    if (vorbisSupported && (!m_isMediaSource || factories.hasElementForMediaType(ElementFactories::Type::AudioParser, "audio/x-vorbis"))) {
    219254        m_decoderCodecMap.add(AtomString("vorbis"), false);
    220255        m_decoderCodecMap.add(AtomString("x-vorbis"), false);
    221256    }
    222257
    223     bool matroskaSupported = hasElementForMediaType(m_demuxerFactories, "video/x-matroska");
     258    bool matroskaSupported = factories.hasElementForMediaType(ElementFactories::Type::Demuxer, "video/x-matroska");
    224259    if (matroskaSupported) {
    225         auto vp8DecoderAvailable = hasElementForMediaType(m_videoDecoderFactories, "video/x-vp8", true);
    226         auto vp9DecoderAvailable = hasElementForMediaType(m_videoDecoderFactories, "video/x-vp9", true);
     260        auto vp8DecoderAvailable = factories.hasElementForMediaType(ElementFactories::Type::VideoDecoder, "video/x-vp8", ElementFactories::CheckHardwareClassifier::Yes);
     261        auto vp9DecoderAvailable = factories.hasElementForMediaType(ElementFactories::Type::VideoDecoder, "video/x-vp9", ElementFactories::CheckHardwareClassifier::Yes);
    227262
    228263        if (vp8DecoderAvailable || vp9DecoderAvailable)
     
    244279    }
    245280
    246     auto h264DecoderAvailable = hasElementForMediaType(m_videoDecoderFactories, "video/x-h264, profile=(string){ constrained-baseline, baseline, high }", true);
    247     if (h264DecoderAvailable && (!m_isMediaSource || hasElementForMediaType(m_videoParserFactories, "video/x-h264"))) {
     281    auto h264DecoderAvailable = factories.hasElementForMediaType(ElementFactories::Type::VideoDecoder, "video/x-h264, profile=(string){ constrained-baseline, baseline, high }", ElementFactories::CheckHardwareClassifier::Yes);
     282    if (h264DecoderAvailable && (!m_isMediaSource || factories.hasElementForMediaType(ElementFactories::Type::VideoParser, "video/x-h264"))) {
    248283        m_decoderMimeTypeSet.add(AtomString("video/mp4"));
    249284        m_decoderMimeTypeSet.add(AtomString("video/x-m4v"));
     
    253288    }
    254289
    255     Vector<String> av1DecodersBlacklist { "av1dec"_s };
    256     if ((matroskaSupported || isContainerTypeSupported(Configuration::Decoding, "video/mp4")) && hasElementForMediaType(m_videoDecoderFactories, "video/x-av1", false, makeOptional(WTFMove(av1DecodersBlacklist)))) {
     290    Vector<String> av1DecodersDisallowedList { "av1dec"_s };
     291    if ((matroskaSupported || isContainerTypeSupported(Configuration::Decoding, "video/mp4")) && factories.hasElementForMediaType(ElementFactories::Type::VideoDecoder, "video/x-av1", ElementFactories::CheckHardwareClassifier::No, makeOptional(WTFMove(av1DecodersDisallowedList)))) {
    257292        m_decoderCodecMap.add(AtomString("av01*"), false);
    258293        m_decoderCodecMap.add(AtomString("av1"), false);
     
    266301
    267302    Vector<GstCapsWebKitMapping> mapping = {
    268         {AudioDecoder, "audio/midi", {"audio/midi", "audio/riff-midi"}, { }},
    269         {AudioDecoder, "audio/x-ac3", { }, { }},
    270         {AudioDecoder, "audio/x-dts", { }, { }},
    271         {AudioDecoder, "audio/x-eac3", {"audio/x-ac3"}, { }},
    272         {AudioDecoder, "audio/x-flac", {"audio/x-flac", "audio/flac"}, { }},
    273         {AudioDecoder, "audio/x-sbc", { }, { }},
    274         {AudioDecoder, "audio/x-sid", { }, { }},
    275         {AudioDecoder, "audio/x-speex", {"audio/speex", "audio/x-speex"}, { }},
    276         {AudioDecoder, "audio/x-wavpack", {"audio/x-wavpack"}, { }},
    277         {VideoDecoder, "video/mpeg, mpegversion=(int){1,2}, systemstream=(boolean)false", {"video/mpeg"}, {"mpeg"}},
    278         {VideoDecoder, "video/mpegts", { }, { }},
    279         {VideoDecoder, "video/x-dirac", { }, { }},
    280         {VideoDecoder, "video/x-flash-video", {"video/flv", "video/x-flv"}, { }},
    281         {VideoDecoder, "video/x-h263", { }, { }},
    282         {VideoDecoder, "video/x-msvideocodec", {"video/x-msvideo"}, { }},
    283         {Demuxer, "application/vnd.rn-realmedia", { }, { }},
    284         {Demuxer, "application/x-3gp", { }, { }},
    285         {Demuxer, "application/x-hls", {"application/vnd.apple.mpegurl", "application/x-mpegurl"}, { }},
    286         {Demuxer, "application/x-pn-realaudio", { }, { }},
    287         {Demuxer, "audio/x-aiff", { }, { }},
    288         {Demuxer, "audio/x-wav", {"audio/x-wav", "audio/wav", "audio/vnd.wave"}, {"1"}},
    289         {Demuxer, "video/quicktime", { }, { }},
    290         {Demuxer, "video/quicktime, variant=(string)3gpp", {"video/3gpp"}, { }},
    291         {Demuxer, "video/x-ms-asf", { }, { }},
     303        { ElementFactories::Type::AudioDecoder, "audio/midi", { "audio/midi", "audio/riff-midi" }, { } },
     304        { ElementFactories::Type::AudioDecoder, "audio/x-ac3", { }, { } },
     305        { ElementFactories::Type::AudioDecoder, "audio/x-dts", { }, { } },
     306        { ElementFactories::Type::AudioDecoder, "audio/x-eac3", { "audio/x-ac3" }, { } },
     307        { ElementFactories::Type::AudioDecoder, "audio/x-flac", { "audio/x-flac", "audio/flac" }, { } },
     308        { ElementFactories::Type::AudioDecoder, "audio/x-sbc", { }, { } },
     309        { ElementFactories::Type::AudioDecoder, "audio/x-sid", { }, { } },
     310        { ElementFactories::Type::AudioDecoder, "audio/x-speex", { "audio/speex", "audio/x-speex" }, { } },
     311        { ElementFactories::Type::AudioDecoder, "audio/x-wavpack", { "audio/x-wavpack" }, { } },
     312        { ElementFactories::Type::VideoDecoder, "video/mpeg, mpegversion=(int){1,2}, systemstream=(boolean)false", { "video/mpeg" }, { "mpeg" } },
     313        { ElementFactories::Type::VideoDecoder, "video/mpegts", { }, { } },
     314        { ElementFactories::Type::VideoDecoder, "video/x-dirac", { }, { } },
     315        { ElementFactories::Type::VideoDecoder, "video/x-flash-video", { "video/flv", "video/x-flv" }, { } },
     316        { ElementFactories::Type::VideoDecoder, "video/x-h263", { }, { } },
     317        { ElementFactories::Type::VideoDecoder, "video/x-msvideocodec", { "video/x-msvideo" }, { } },
     318        { ElementFactories::Type::Demuxer, "application/vnd.rn-realmedia", { }, { } },
     319        { ElementFactories::Type::Demuxer, "application/x-3gp", { }, { } },
     320        { ElementFactories::Type::Demuxer, "application/x-hls", { "application/vnd.apple.mpegurl", "application/x-mpegurl" }, { } },
     321        { ElementFactories::Type::Demuxer, "application/x-pn-realaudio", { }, { } },
     322        { ElementFactories::Type::Demuxer, "audio/x-aiff", { }, { } },
     323        { ElementFactories::Type::Demuxer, "audio/x-wav", { "audio/x-wav", "audio/wav", "audio/vnd.wave" }, { "1" } },
     324        { ElementFactories::Type::Demuxer, "video/quicktime", { }, { } },
     325        { ElementFactories::Type::Demuxer, "video/quicktime, variant=(string)3gpp", { "video/3gpp" }, { } },
     326        { ElementFactories::Type::Demuxer, "video/x-ms-asf", { }, { } },
    292327    };
    293     fillMimeTypeSetFromCapsMapping(mapping);
    294 
    295     if (hasElementForMediaType(m_demuxerFactories, "application/ogg")) {
     328    fillMimeTypeSetFromCapsMapping(factories, mapping);
     329
     330    if (factories.hasElementForMediaType(ElementFactories::Type::Demuxer, "application/ogg")) {
    296331        m_decoderMimeTypeSet.add(AtomString("application/ogg"));
    297332
     
    301336        }
    302337
    303         if (hasElementForMediaType(m_audioDecoderFactories, "audio/x-speex")) {
     338        if (factories.hasElementForMediaType(ElementFactories::Type::AudioDecoder, "audio/x-speex")) {
    304339            m_decoderMimeTypeSet.add(AtomString("audio/ogg"));
    305340            m_decoderCodecMap.add(AtomString("speex"), false);
    306341        }
    307342
    308         if (hasElementForMediaType(m_videoDecoderFactories, "video/x-theora")) {
     343        if (factories.hasElementForMediaType(ElementFactories::Type::VideoDecoder, "video/x-theora")) {
    309344            m_decoderMimeTypeSet.add(AtomString("video/ogg"));
    310345            m_decoderCodecMap.add(AtomString("theora"), false);
     
    313348
    314349    bool audioMpegSupported = false;
    315     if (hasElementForMediaType(m_audioDecoderFactories, "audio/mpeg, mpegversion=(int)1, layer=(int)[1, 3]")) {
     350    if (factories.hasElementForMediaType(ElementFactories::Type::AudioDecoder, "audio/mpeg, mpegversion=(int)1, layer=(int)[1, 3]")) {
    316351        audioMpegSupported = true;
    317352        m_decoderMimeTypeSet.add(AtomString("audio/mp1"));
     
    322357    }
    323358
    324     if (hasElementForMediaType(m_audioDecoderFactories, "audio/mpeg, mpegversion=(int)2")) {
     359    if (factories.hasElementForMediaType(ElementFactories::Type::AudioDecoder, "audio/mpeg, mpegversion=(int)2")) {
    325360        audioMpegSupported = true;
    326361        m_decoderMimeTypeSet.add(AtomString("audio/mp2"));
     
    336371        m_decoderMimeTypeSet.add(AtomString("video/x-matroska"));
    337372
    338         if (hasElementForMediaType(m_videoDecoderFactories, "video/x-vp10"))
     373        if (factories.hasElementForMediaType(ElementFactories::Type::VideoDecoder, "video/x-vp10"))
    339374            m_decoderMimeTypeSet.add(AtomString("video/webm"));
    340375    }
    341376}
    342377
    343 void GStreamerRegistryScanner::initializeEncoders()
     378void GStreamerRegistryScanner::initializeEncoders(const GStreamerRegistryScanner::ElementFactories& factories)
    344379{
    345380    // MSE is about playback, which means decoding. No need to check for encoders then.
     
    347382        return;
    348383
    349     auto aacSupported = hasElementForMediaType(m_audioEncoderFactories, "audio/mpeg, mpegversion=(int)4");
    350     if (hasElementForMediaType(m_audioEncoderFactories, "audio/mpeg, mpegversion=(int)4")) {
     384    auto aacSupported = factories.hasElementForMediaType(ElementFactories::Type::AudioEncoder, "audio/mpeg, mpegversion=(int)4");
     385    if (factories.hasElementForMediaType(ElementFactories::Type::AudioEncoder, "audio/mpeg, mpegversion=(int)4")) {
    351386        m_encoderCodecMap.add(AtomString("mpeg"), false);
    352387        m_encoderCodecMap.add(AtomString("mp4a*"), false);
    353388    }
    354389
    355     auto opusSupported = hasElementForMediaType(m_audioEncoderFactories, "audio/x-opus");
     390    auto opusSupported = factories.hasElementForMediaType(ElementFactories::Type::AudioEncoder, "audio/x-opus");
    356391    if (opusSupported) {
    357392        m_encoderCodecMap.add(AtomString("opus"), false);
     
    359394    }
    360395
    361     auto vorbisSupported = hasElementForMediaType(m_audioEncoderFactories, "audio/x-vorbis");
     396    auto vorbisSupported = factories.hasElementForMediaType(ElementFactories::Type::AudioEncoder, "audio/x-vorbis");
    362397    if (vorbisSupported) {
    363398        m_encoderCodecMap.add(AtomString("vorbis"), false);
     
    365400    }
    366401
    367     Vector<String> av1EncodersBlacklist { "av1enc"_s };
    368     auto av1EncoderAvailable = hasElementForMediaType(m_videoEncoderFactories, "video/x-av1", true, makeOptional(WTFMove(av1EncodersBlacklist)));
     402    Vector<String> av1EncodersDisallowedList { "av1enc"_s };
     403    auto av1EncoderAvailable = factories.hasElementForMediaType(ElementFactories::Type::VideoEncoder, "video/x-av1", ElementFactories::CheckHardwareClassifier::Yes, makeOptional(WTFMove(av1EncodersDisallowedList)));
    369404    if (av1EncoderAvailable) {
    370405        m_encoderCodecMap.add(AtomString("av01*"), false);
     
    373408    }
    374409
    375     auto vp8EncoderAvailable = hasElementForMediaType(m_videoEncoderFactories, "video/x-vp8", true);
     410    auto vp8EncoderAvailable = factories.hasElementForMediaType(ElementFactories::Type::VideoEncoder, "video/x-vp8", ElementFactories::CheckHardwareClassifier::Yes);
    376411    if (vp8EncoderAvailable) {
    377412        m_encoderCodecMap.add(AtomString("vp8"), vp8EncoderAvailable.isUsingHardware);
     
    380415    }
    381416
    382     auto vp9EncoderAvailable = hasElementForMediaType(m_videoEncoderFactories, "video/x-vp9", true);
     417    auto vp9EncoderAvailable = factories.hasElementForMediaType(ElementFactories::Type::VideoEncoder, "video/x-vp9", ElementFactories::CheckHardwareClassifier::Yes);
    383418    if (vp9EncoderAvailable) {
    384419        m_encoderCodecMap.add(AtomString("vp9"), vp9EncoderAvailable.isUsingHardware);
     
    388423    }
    389424
    390     if (hasElementForMediaType(m_muxerFactories, "video/webm") && (vp8EncoderAvailable || vp9EncoderAvailable || av1EncoderAvailable))
     425    if (factories.hasElementForMediaType(ElementFactories::Type::Muxer, "video/webm") && (vp8EncoderAvailable || vp9EncoderAvailable || av1EncoderAvailable))
    391426        m_encoderMimeTypeSet.add(AtomString("video/webm"));
    392427
    393     if (hasElementForMediaType(m_muxerFactories, "audio/webm")) {
     428    if (factories.hasElementForMediaType(ElementFactories::Type::Muxer, "audio/webm")) {
    394429        if (opusSupported)
    395430            m_encoderMimeTypeSet.add(AtomString("audio/opus"));
     
    397432    }
    398433
    399     if (hasElementForMediaType(m_muxerFactories, "audio/ogg") && (vorbisSupported || opusSupported))
     434    if (factories.hasElementForMediaType(ElementFactories::Type::Muxer, "audio/ogg") && (vorbisSupported || opusSupported))
    400435        m_encoderMimeTypeSet.add(AtomString("audio/ogg"));
    401436
    402     auto h264EncoderAvailable = hasElementForMediaType(m_videoEncoderFactories, "video/x-h264, profile=(string){ constrained-baseline, baseline, high }", true);
     437    auto h264EncoderAvailable = factories.hasElementForMediaType(ElementFactories::Type::VideoEncoder, "video/x-h264, profile=(string){ constrained-baseline, baseline, high }", ElementFactories::CheckHardwareClassifier::Yes);
    403438    if (h264EncoderAvailable) {
    404439        m_encoderCodecMap.add(AtomString("x-h264"), h264EncoderAvailable.isUsingHardware);
     
    407442    }
    408443
    409     if (hasElementForMediaType(m_muxerFactories, "video/quicktime")) {
     444    if (factories.hasElementForMediaType(ElementFactories::Type::Muxer, "video/quicktime")) {
    410445        if (opusSupported)
    411446            m_encoderMimeTypeSet.add(AtomString("audio/opus"));
     
    422457}
    423458
    424 bool GStreamerRegistryScanner::isCodecSupported(Configuration configuration, String codec, bool shouldCheckForHardwareUse) const
     459bool GStreamerRegistryScanner::isCodecSupported(Configuration configuration, const String& codec, bool shouldCheckForHardwareUse) const
    425460{
    426461    // If the codec is named like a mimetype (eg: video/avc) remove the "video/" part.
    427462    size_t slashIndex = codec.find('/');
    428     if (slashIndex != WTF::notFound)
    429         codec = codec.substring(slashIndex + 1);
     463    String codecName = slashIndex != WTF::notFound ? codec.substring(slashIndex + 1) : codec;
    430464
    431465    bool supported = false;
    432     if (codec.startsWith("avc1"))
    433         supported = isAVC1CodecSupported(configuration, codec, shouldCheckForHardwareUse);
     466    if (codecName.startsWith("avc1"))
     467        supported = isAVC1CodecSupported(configuration, codecName, shouldCheckForHardwareUse);
    434468    else {
    435469        auto& codecMap = configuration == Configuration::Decoding ? m_decoderCodecMap : m_encoderCodecMap;
    436470        for (const auto& item : codecMap) {
    437             if (!fnmatch(item.key.string().utf8().data(), codec.utf8().data(), 0)) {
     471            if (!fnmatch(item.key.string().utf8().data(), codecName.utf8().data(), 0)) {
    438472                supported = shouldCheckForHardwareUse ? item.value : true;
    439473                if (supported)
     
    444478
    445479    const char* configLogString = configurationNameForLogging(configuration);
    446     GST_LOG("Checked %s %s codec \"%s\" supported %s", shouldCheckForHardwareUse ? "hardware" : "software", configLogString, codec.utf8().data(), boolForPrinting(supported));
     480    GST_LOG("Checked %s %s codec \"%s\" supported %s", shouldCheckForHardwareUse ? "hardware" : "software", configLogString, codecName.utf8().data(), boolForPrinting(supported));
    447481    return supported;
    448482}
     
    484518bool GStreamerRegistryScanner::areAllCodecsSupported(Configuration configuration, const Vector<String>& codecs, bool shouldCheckForHardwareUse) const
    485519{
    486     for (String codec : codecs) {
     520    for (const auto& codec : codecs) {
    487521        if (!isCodecSupported(configuration, codec, shouldCheckForHardwareUse))
    488522            return false;
     
    495529{
    496530    auto checkH264Caps = [&](const char* capsString) {
    497         bool supported = false;
    498         RegistryLookupResult lookupResult;
     531        OptionSet<ElementFactories::Type> factoryTypes;
    499532        switch (configuration) {
    500533        case Configuration::Decoding:
    501             lookupResult = hasElementForMediaType(m_videoDecoderFactories, capsString, true);
     534            factoryTypes.add(ElementFactories::Type::VideoDecoder);
    502535            break;
    503536        case Configuration::Encoding:
    504             lookupResult = hasElementForMediaType(m_videoEncoderFactories, capsString, true);
     537            factoryTypes.add(ElementFactories::Type::VideoEncoder);
    505538            break;
    506539        }
    507         supported = lookupResult;
    508         if (shouldCheckForHardwareUse)
    509             supported = lookupResult.isUsingHardware;
     540        auto lookupResult = ElementFactories(factoryTypes).hasElementForMediaType(factoryTypes.toSingleValue().value(), capsString, ElementFactories::CheckHardwareClassifier::Yes);
     541        bool supported = lookupResult && shouldCheckForHardwareUse ? lookupResult.isUsingHardware : true;
    510542        GST_DEBUG("%s decoding supported for codec %s: %s", shouldCheckForHardwareUse ? "Hardware" : "Software", codec.utf8().data(), boolForPrinting(supported));
    511543        return supported;
     
    590622}
    591623
    592 GStreamerRegistryScanner::RegistryLookupResult GStreamerRegistryScanner::isConfigurationSupported(Configuration configuration, MediaConfiguration& mediaConfiguration) const
     624GStreamerRegistryScanner::RegistryLookupResult GStreamerRegistryScanner::isConfigurationSupported(Configuration configuration, const MediaConfiguration& mediaConfiguration) const
    593625{
    594626    bool isSupported = false;
     
    619651    }
    620652
    621     return GStreamerRegistryScanner::RegistryLookupResult { isSupported, isUsingHardware };
     653    return { isSupported, isUsingHardware };
    622654}
    623655
  • trunk/Source/WebCore/platform/graphics/gstreamer/GStreamerRegistryScanner.h

    r268590 r270019  
    2828#include <wtf/HashMap.h>
    2929#include <wtf/HashSet.h>
     30#include <wtf/OptionSet.h>
    3031#include <wtf/text/AtomString.h>
    3132#include <wtf/text/AtomStringHash.h>
     
    4546    };
    4647
    47     const HashSet<String, ASCIICaseInsensitiveHash>& mimeTypeSet(Configuration);
    48     bool isContainerTypeSupported(Configuration, String containerType) const;
     48    const HashSet<String, ASCIICaseInsensitiveHash>& mimeTypeSet(Configuration) const;
     49    bool isContainerTypeSupported(Configuration, const String& containerType) const;
    4950
    5051    struct RegistryLookupResult {
    51         bool isSupported;
    52         bool isUsingHardware;
     52        bool isSupported { false };
     53        bool isUsingHardware { false };
    5354
    5455        operator bool() const { return isSupported; }
     
    5758    RegistryLookupResult isEncodingSupported(MediaConfiguration& mediaConfiguration) const { return isConfigurationSupported(Configuration::Encoding, mediaConfiguration); }
    5859
    59     bool isCodecSupported(Configuration, String codec, bool usingHardware = false) const;
     60    bool isCodecSupported(Configuration, const String& codec, bool usingHardware = false) const;
    6061    MediaPlayerEnums::SupportsType isContentTypeSupported(Configuration, const ContentType&, const Vector<ContentType>& contentTypesRequiringHardwareSupport) const;
    6162    bool areAllCodecsSupported(Configuration, const Vector<String>& codecs, bool shouldCheckForHardwareUse = false) const;
     
    6364protected:
    6465    GStreamerRegistryScanner(bool isMediaSource = false);
    65     ~GStreamerRegistryScanner();
     66    ~GStreamerRegistryScanner() = default;
    6667
    67     void initializeDecoders();
    68     void initializeEncoders();
     68    struct ElementFactories {
     69        enum class Type {
     70            AudioParser  = 1 << 0,
     71            AudioDecoder = 1 << 1,
     72            VideoParser  = 1 << 2,
     73            VideoDecoder = 1 << 3,
     74            Demuxer      = 1 << 4,
     75            AudioEncoder = 1 << 5,
     76            VideoEncoder = 1 << 6,
     77            Muxer        = 1 << 7,
     78            All          = (1 << 8) - 1
     79        };
    6980
    70     RegistryLookupResult isConfigurationSupported(Configuration, MediaConfiguration&) const;
     81        explicit ElementFactories(OptionSet<Type>);
     82        ~ElementFactories();
    7183
    72     enum ElementType {
    73         AudioDecoder = 0,
    74         VideoDecoder,
    75         Demuxer
     84        static const char* elementFactoryTypeToString(Type);
     85        GList* factory(Type) const;
     86
     87        enum class CheckHardwareClassifier { No, Yes };
     88        RegistryLookupResult hasElementForMediaType(Type, const char* capsString, CheckHardwareClassifier = CheckHardwareClassifier::No, Optional<Vector<String>> disallowedList = WTF::nullopt) const;
     89
     90        GList* audioDecoderFactories { nullptr };
     91        GList* audioParserFactories { nullptr };
     92        GList* videoDecoderFactories { nullptr };
     93        GList* videoParserFactories { nullptr };
     94        GList* demuxerFactories { nullptr };
     95        GList* audioEncoderFactories { nullptr };
     96        GList* videoEncoderFactories { nullptr };
     97        GList* muxerFactories { nullptr };
    7698    };
    7799
     100    void initializeDecoders(const ElementFactories&);
     101    void initializeEncoders(const ElementFactories&);
     102
     103    RegistryLookupResult isConfigurationSupported(Configuration, const MediaConfiguration&) const;
     104
    78105    struct GstCapsWebKitMapping {
    79         ElementType elementType;
     106        ElementFactories::Type elementType;
    80107        const char* capsString;
    81108        Vector<AtomString> webkitMimeTypes;
    82109        Vector<AtomString> webkitCodecPatterns;
    83110    };
    84     void fillMimeTypeSetFromCapsMapping(Vector<GstCapsWebKitMapping>&);
    85 
    86     RegistryLookupResult hasElementForMediaType(GList* elementFactories, const char* capsString, bool shouldCheckHardwareClassifier = false, Optional<Vector<String>> blackList = WTF::nullopt) const;
     111    void fillMimeTypeSetFromCapsMapping(const ElementFactories&, const Vector<GstCapsWebKitMapping>&);
    87112
    88113    bool isAVC1CodecSupported(Configuration, const String& codec, bool shouldCheckForHardwareUse) const;
     
    91116    const char* configurationNameForLogging(Configuration) const;
    92117
    93     bool m_isMediaSource;
    94     GList* m_audioDecoderFactories;
    95     GList* m_audioParserFactories;
    96     GList* m_videoDecoderFactories;
    97     GList* m_videoParserFactories;
    98     GList* m_demuxerFactories;
    99     GList* m_audioEncoderFactories;
    100     GList* m_videoEncoderFactories;
    101     GList* m_muxerFactories;
     118    bool m_isMediaSource { false };
    102119    HashSet<String, ASCIICaseInsensitiveHash> m_decoderMimeTypeSet;
    103120    HashMap<AtomString, bool> m_decoderCodecMap;
Note: See TracChangeset for help on using the changeset viewer.