MediaCodecsSupport.h (9356B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim:set ts=2 sw=2 sts=2 et cindent: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 #ifndef DOM_MEDIA_PLATFORMS_MEDIACODECSSUPPORT_H_ 7 #define DOM_MEDIA_PLATFORMS_MEDIACODECSSUPPORT_H_ 8 #include <array> 9 10 #include "mozilla/ClearOnShutdown.h" 11 #include "mozilla/EnumSet.h" 12 #include "mozilla/StaticMutex.h" 13 #include "nsString.h" 14 #include "nsTHashMap.h" 15 #include "nsThreadUtils.h" 16 17 namespace mozilla::media { 18 // List of codecs we support, used in the below macros 19 // to generate MediaCodec and MediaCodecSupports enums. 20 #define CODEC_LIST \ 21 X(H264) \ 22 X(VP8) \ 23 X(VP9) \ 24 X(AV1) \ 25 X(HEVC) \ 26 X(AAC) \ 27 X(FLAC) \ 28 X(MP3) \ 29 X(Opus) \ 30 X(Vorbis) \ 31 X(Wave) 32 33 // Generate MediaCodec enum with the names of each codec we support. 34 // Example: MediaCodec::H264 35 enum class MediaCodec : int { 36 #define X(name) name, 37 CODEC_LIST 38 #undef X 39 SENTINEL 40 }; 41 using MediaCodecSet = EnumSet<MediaCodec, uint64_t>; 42 43 // Helper macros used to create codec-specific SW/HW de/encode enums below. 44 #define SW_DECODE(codec) codec##SoftwareDecode 45 #define HW_DECODE(codec) codec##HardwareDecode 46 #define SW_ENCODE(codec) codec##SoftwareEncode 47 #define HW_ENCODE(codec) codec##HardwareEncode 48 49 // For codec which we can do hardware de/encoding once user installs the free 50 // platform extension, eg. AV1 on Windows 51 #define LACK_HW_EXTENSION(codec) codec##LackOfExtension 52 53 // Generate the MediaCodecsSupport enum, containing 54 // codec-specific SW/HW decode/encode information. 55 // Entries for HW audio decode/encode should never be set as we 56 // don't support HW audio decode/encode, but they are included 57 // for debug purposes / check for erroneous PDM return values. 58 // Example: MediaCodecsSupport::AACSoftwareDecode 59 enum class MediaCodecsSupport : int { 60 #define X(name) \ 61 SW_DECODE(name), HW_DECODE(name), SW_ENCODE(name), HW_ENCODE(name), \ 62 LACK_HW_EXTENSION(name), 63 CODEC_LIST 64 #undef X 65 SENTINEL 66 }; 67 #undef SW_DECODE 68 #undef HW_DECODE 69 #undef SW_ENCODE 70 #undef HW_ENCODE 71 #undef CODEC_LIST // end of macros! 72 73 // Enumset containing per-codec SW/HW support 74 using MediaCodecsSupported = EnumSet<MediaCodecsSupport, uint64_t>; 75 76 // Codec-agnostic SW/HW decode support information. 77 enum class DecodeSupport : int { 78 SoftwareDecode, 79 HardwareDecode, 80 UnsureDueToLackOfExtension, 81 }; 82 using DecodeSupportSet = EnumSet<DecodeSupport, uint64_t>; 83 84 // Codec-agnostic SW/HW decode support information. 85 enum class EncodeSupport : int { 86 SoftwareEncode, 87 HardwareEncode, 88 UnsureDueToLackOfExtension, 89 }; 90 using EncodeSupportSet = EnumSet<EncodeSupport, uint64_t>; 91 92 // CodecDefinition stores information needed to convert / index 93 // codec support information between types. See: GetAllCodecDefinitions() 94 struct CodecDefinition { 95 MediaCodec codec = MediaCodec::SENTINEL; 96 const char* commonName = "Undefined codec name"; 97 const char* mimeTypeString = "Undefined MIME type string"; 98 MediaCodecsSupport swDecodeSupport = MediaCodecsSupport::SENTINEL; 99 MediaCodecsSupport hwDecodeSupport = MediaCodecsSupport::SENTINEL; 100 MediaCodecsSupport swEncodeSupport = MediaCodecsSupport::SENTINEL; 101 MediaCodecsSupport hwEncodeSupport = MediaCodecsSupport::SENTINEL; 102 MediaCodecsSupport lackOfHWExtenstion = MediaCodecsSupport::SENTINEL; 103 }; 104 105 // Singleton class used to collect, manage, and report codec support data. 106 class MCSInfo final { 107 public: 108 // Gets the codec support from current PDMFactory and PEMFactory 109 // configuration. 110 static MediaCodecsSupported GetSupportFromFactory(bool aForceRefresh = false); 111 112 // Add codec support information to our aggregated list of supported codecs. 113 // Incoming support info is merged with the current support info. 114 // This is because different PDMs may report different codec support 115 // information, so merging their results allows us to maintain a 116 // cumulative support list without overwriting any existing data. 117 static void AddSupport(const MediaCodecsSupported& aSupport); 118 119 // Return a cumulative list of codec support information. 120 // Each call to AddSupport adds to or updates this list. 121 // This support information can be used to create user-readable strings 122 // to report codec support information in about:support. 123 static MediaCodecsSupported GetSupport(); 124 125 // Reset codec support information saved from calls to AddSupport(). 126 static void ResetSupport(); 127 128 // Query a MediaCodecsSupported EnumSet for codec-specific SW/HW support enums 129 // and return general support information as stored in a DecodeSupportSet. 130 // 131 // Example input: 132 // 133 // aCodec: MediaCodec::H264 134 // aDecode: MediaCodecsSupport { 135 // MediaCodecsSupport::AACSoftwareDecode 136 // MediaCodecsSupport::H264HardwareDecode, 137 // MediaCodecsSupport::H264SoftwareDecode, 138 // MediaCodecsSupport::VP8SoftwareDecode, 139 // } 140 // 141 // Example output: 142 // 143 // DecodeSupportSet { 144 // DecodeSupport::SoftwareDecode, 145 // DecodeSupport::HardwareDecode 146 // } 147 // 148 static DecodeSupportSet GetDecodeSupportSet( 149 const MediaCodec& aCodec, const MediaCodecsSupported& aSupported); 150 static EncodeSupportSet GetEncodeSupportSet( 151 const MediaCodec& aCodec, const MediaCodecsSupported& aSupported); 152 153 // Return codec-specific SW/HW support enums for a given codec. 154 // The DecodeSupportSet argument is used which codec-specific SW/HW 155 // support values are returned, if any. 156 // 157 // Example input: 158 // aCodec: MediaCodec::VP8 159 // aSupportSet: DecodeSupportSet {DecodeSupport::SoftwareDecode} 160 // 161 // Example output: 162 // MediaCodecsSupported {MediaCodecsSupport::VP8SoftwareDecode} 163 // 164 static MediaCodecsSupported GetDecodeMediaCodecsSupported( 165 const MediaCodec& aCodec, const DecodeSupportSet& aSupportSet); 166 static MediaCodecsSupported GetEncodeMediaCodecsSupported( 167 const MediaCodec& aCodec, const EncodeSupportSet& aSupportSet); 168 169 // Generate a plaintext description for the SW/HW support information 170 // contained in a MediaCodecsSupported EnumSet. 171 // 172 // Example input: 173 // MediaCodecsSupported { 174 // MediaCodecsSupport::H264SoftwareDecode, 175 // MediaCodecsSupport::H264HardwareDecode, 176 // MediaCodecsSupport::VP8SoftwareDecode 177 // } 178 // 179 // Example output (returned via argument aCodecString) 180 // 181 // "SW H264 decode\n 182 // HW H264 decode\n 183 // SW VP8 decode"_ns 184 // 185 static void GetMediaCodecsSupportedString( 186 nsCString& aSupportString, const MediaCodecsSupported& aSupportedCodecs); 187 188 // Returns a MediaCodec enum representing the given MIME type string. 189 // 190 // Example input: 191 // "audio/flac"_ns 192 // 193 // Example output: 194 // MediaCodec::FLAC 195 // 196 static MediaCodec GetMediaCodecFromMimeType(const nsACString& aMimeType); 197 198 // Returns array of hardcoded codec definitions. 199 static std::array<CodecDefinition, 13> GetAllCodecDefinitions(); 200 201 // Parses an array of MIME type strings and returns a MediaCodecSet. 202 static MediaCodecSet GetMediaCodecSetFromMimeTypes( 203 const nsTArray<nsCString>& aCodecStrings); 204 205 // Returns a MediaCodecsSupport enum corresponding to the provided 206 // codec type and decode support level requested. 207 static MediaCodecsSupport GetMediaCodecsSupportEnum( 208 const MediaCodec& aCodec, const DecodeSupport& aSupport); 209 static MediaCodecsSupport GetMediaCodecsSupportEnum( 210 const MediaCodec& aCodec, const EncodeSupport& aSupport); 211 212 // Returns true if SW/HW decode enum for a given codec is present in the args. 213 static bool SupportsSoftwareDecode( 214 const MediaCodecsSupported& aSupportedCodecs, const MediaCodec& aCodec); 215 static bool SupportsHardwareDecode( 216 const MediaCodecsSupported& aSupportedCodecs, const MediaCodec& aCodec); 217 218 // Returns true if SW/HW encode enum for a given codec is present in the args. 219 static bool SupportsSoftwareEncode( 220 const MediaCodecsSupported& aSupportedCodecs, const MediaCodec& aCodec); 221 static bool SupportsHardwareEncode( 222 const MediaCodecsSupported& aSupportedCodecs, const MediaCodec& aCodec); 223 224 MCSInfo(MCSInfo const&) = delete; 225 void operator=(MCSInfo const&) = delete; 226 ~MCSInfo() = default; 227 228 private: 229 MCSInfo(); 230 static MCSInfo* GetInstance(); 231 232 // Returns a codec definition by MIME type name ("media/vp9") 233 // or "common" name ("VP9") 234 static CodecDefinition GetCodecDefinition(const MediaCodec& aCodec); 235 236 UniquePtr<nsTHashMap<MediaCodecsSupport, CodecDefinition>> mHashTableMCS; 237 UniquePtr<nsTHashMap<const char*, CodecDefinition>> mHashTableString; 238 UniquePtr<nsTHashMap<MediaCodec, CodecDefinition>> mHashTableCodec; 239 MediaCodecsSupported mSupport; 240 }; 241 } // namespace mozilla::media 242 243 namespace mozilla { 244 // Used for IPDL serialization. 245 // The 'value' has to be the biggest enum from MediaCodecsSupport. 246 template <typename T> 247 struct MaxEnumValue; 248 template <> 249 struct MaxEnumValue<media::MediaCodecsSupport> { 250 static constexpr unsigned int value = 251 static_cast<unsigned int>(media::MediaCodecsSupport::SENTINEL); 252 }; 253 } // namespace mozilla 254 255 #endif /* MediaCodecsSupport_h_ */