MFMediaEngineDecoderModule.cpp (6676B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 #include "MFMediaEngineDecoderModule.h" 6 7 #include "MFTDecoder.h" 8 #include "VideoUtils.h" 9 #include "mozilla/MFMediaEngineParent.h" 10 #include "mozilla/MFMediaEngineUtils.h" 11 #include "mozilla/RemoteDecoderModule.h" 12 #include "mozilla/RemoteMediaManagerChild.h" 13 #include "mozilla/StaticPrefs_media.h" 14 #include "mozilla/WindowsVersion.h" 15 #include "mozilla/gfx/gfxVars.h" 16 #include "mozilla/mscom/EnsureMTA.h" 17 18 namespace mozilla { 19 20 #define LOG(msg, ...) \ 21 MOZ_LOG(gMFMediaEngineLog, LogLevel::Debug, (msg, ##__VA_ARGS__)) 22 23 /* static */ 24 void MFMediaEngineDecoderModule::Init() { 25 // TODO : Init any thing that media engine would need. Implement this when we 26 // start implementing media engine in following patches. 27 } 28 29 /* static */ 30 already_AddRefed<PlatformDecoderModule> MFMediaEngineDecoderModule::Create() { 31 RefPtr<MFMediaEngineDecoderModule> module = new MFMediaEngineDecoderModule(); 32 return module.forget(); 33 } 34 35 /* static */ 36 bool MFMediaEngineDecoderModule::SupportsConfig(const TrackInfo& aConfig) { 37 RefPtr<PlatformDecoderModule> module = RemoteDecoderModule::Create( 38 RemoteMediaIn::UtilityProcess_MFMediaEngineCDM); 39 return !module->Supports(SupportDecoderParams(aConfig), nullptr).isEmpty(); 40 } 41 42 already_AddRefed<MediaDataDecoder> 43 MFMediaEngineDecoderModule::CreateVideoDecoder( 44 const CreateDecoderParams& aParams) { 45 if (!aParams.mMediaEngineId || 46 !StaticPrefs::media_wmf_media_engine_enabled()) { 47 return nullptr; 48 } 49 RefPtr<MFMediaEngineParent> mediaEngine = 50 MFMediaEngineParent::GetMediaEngineById(*aParams.mMediaEngineId); 51 if (!mediaEngine) { 52 LOG("Can't find media engine %" PRIu64 " for video decoder", 53 *aParams.mMediaEngineId); 54 return nullptr; 55 } 56 LOG("MFMediaEngineDecoderModule, CreateVideoDecoder"); 57 RefPtr<MediaDataDecoder> decoder = mediaEngine->GetMediaEngineStream( 58 TrackInfo::TrackType::kVideoTrack, aParams); 59 return decoder.forget(); 60 } 61 62 already_AddRefed<MediaDataDecoder> 63 MFMediaEngineDecoderModule::CreateAudioDecoder( 64 const CreateDecoderParams& aParams) { 65 if (!aParams.mMediaEngineId || 66 !StaticPrefs::media_wmf_media_engine_enabled()) { 67 return nullptr; 68 } 69 RefPtr<MFMediaEngineParent> mediaEngine = 70 MFMediaEngineParent::GetMediaEngineById(*aParams.mMediaEngineId); 71 if (!mediaEngine) { 72 LOG("Can't find media engine %" PRIu64 " for audio decoder", 73 *aParams.mMediaEngineId); 74 return nullptr; 75 } 76 LOG("MFMediaEngineDecoderModule, CreateAudioDecoder"); 77 RefPtr<MediaDataDecoder> decoder = mediaEngine->GetMediaEngineStream( 78 TrackInfo::TrackType::kAudioTrack, aParams); 79 return decoder.forget(); 80 } 81 82 media::DecodeSupportSet MFMediaEngineDecoderModule::SupportsMimeType( 83 const nsACString& aMimeType, DecoderDoctorDiagnostics* aDiagnostics) const { 84 UniquePtr<TrackInfo> trackInfo = CreateTrackInfoWithMIMEType(aMimeType); 85 if (!trackInfo) { 86 return media::DecodeSupportSet{}; 87 } 88 return SupportInternal(SupportDecoderParams(*trackInfo), aDiagnostics); 89 } 90 91 media::DecodeSupportSet MFMediaEngineDecoderModule::Supports( 92 const SupportDecoderParams& aParams, 93 DecoderDoctorDiagnostics* aDiagnostics) const { 94 return SupportInternal(aParams, aDiagnostics); 95 } 96 97 media::DecodeSupportSet MFMediaEngineDecoderModule::SupportInternal( 98 const SupportDecoderParams& aParams, 99 DecoderDoctorDiagnostics* aDiagnostics) const { 100 if (!StaticPrefs::media_wmf_media_engine_enabled()) { 101 return media::DecodeSupportSet{}; 102 } 103 // Only support hardware decoding. 104 if (!gfx::gfxVars::CanUseHardwareVideoDecoding() && 105 !StaticPrefs::media_wmf_media_engine_bypass_gfx_blocklist()) { 106 return media::DecodeSupportSet{}; 107 } 108 bool supports = false; 109 WMFStreamType type = GetStreamTypeFromMimeType(aParams.MimeType()); 110 if (type != WMFStreamType::Unknown) { 111 supports = CanCreateMFTDecoder(type); 112 } 113 MOZ_LOG(sPDMLog, LogLevel::Debug, 114 ("MFMediaEngine decoder %s requested type '%s'", 115 supports ? "supports" : "rejects", aParams.MimeType().get())); 116 if (!supports) { 117 return media::DecodeSupportSet{}; 118 } 119 return StreamTypeIsVideo(type) ? media::DecodeSupport::HardwareDecode 120 : media::DecodeSupport::SoftwareDecode; 121 } 122 123 static bool CreateMFTDecoderOnMTA(const WMFStreamType& aType) { 124 RefPtr<MFTDecoder> decoder = new MFTDecoder(); 125 static std::unordered_map<WMFStreamType, bool> sResults; 126 if (auto rv = sResults.find(aType); rv != sResults.end()) { 127 return rv->second; 128 } 129 130 bool result = false; 131 switch (aType) { 132 case WMFStreamType::MP3: 133 result = SUCCEEDED(decoder->Create(CLSID_CMP3DecMediaObject)); 134 break; 135 case WMFStreamType::AAC: 136 result = SUCCEEDED(decoder->Create(CLSID_CMSAACDecMFT)); 137 break; 138 // Opus and vorbis are supported via extension. 139 // https://www.microsoft.com/en-us/p/web-media-extensions/9n5tdp8vcmhs 140 case WMFStreamType::OPUS: 141 result = SUCCEEDED(decoder->Create(CLSID_MSOpusDecoder)); 142 break; 143 case WMFStreamType::VORBIS: 144 result = SUCCEEDED(decoder->Create( 145 MFT_CATEGORY_AUDIO_DECODER, MFAudioFormat_Vorbis, MFAudioFormat_PCM)); 146 break; 147 case WMFStreamType::H264: 148 result = SUCCEEDED(decoder->Create(CLSID_CMSH264DecoderMFT)); 149 break; 150 case WMFStreamType::VP8: 151 case WMFStreamType::VP9: { 152 static const uint32_t VPX_USABLE_BUILD = 16287; 153 if (IsWindows10BuildOrLater(VPX_USABLE_BUILD)) { 154 result = SUCCEEDED(decoder->Create(CLSID_CMSVPXDecMFT)); 155 } 156 break; 157 } 158 #ifdef MOZ_AV1 159 case WMFStreamType::AV1: 160 result = SUCCEEDED(decoder->Create(MFT_CATEGORY_VIDEO_DECODER, 161 MFVideoFormat_AV1, GUID_NULL)); 162 break; 163 #endif 164 case WMFStreamType::HEVC: 165 if (StaticPrefs::media_hevc_enabled()) { 166 result = 167 SUCCEEDED(decoder->Create(MFT_CATEGORY_VIDEO_DECODER, 168 MFVideoFormat_HEVC, MFVideoFormat_NV12)); 169 } 170 break; 171 default: 172 MOZ_ASSERT_UNREACHABLE("Unexpected type"); 173 } 174 sResults.insert({aType, result}); 175 return result; 176 } 177 178 bool MFMediaEngineDecoderModule::CanCreateMFTDecoder( 179 const WMFStreamType& aType) const { 180 // TODO : caching the result to prevent performing on MTA thread everytime. 181 bool canCreateDecoder = false; 182 mozilla::mscom::EnsureMTA( 183 [&]() { canCreateDecoder = CreateMFTDecoderOnMTA(aType); }); 184 return canCreateDecoder; 185 } 186 187 #undef LOG 188 189 } // namespace mozilla