diff options
Diffstat (limited to 'dom/media/platforms/wmf/MFMediaEngineDecoderModule.cpp')
-rw-r--r-- | dom/media/platforms/wmf/MFMediaEngineDecoderModule.cpp | 174 |
1 files changed, 174 insertions, 0 deletions
diff --git a/dom/media/platforms/wmf/MFMediaEngineDecoderModule.cpp b/dom/media/platforms/wmf/MFMediaEngineDecoderModule.cpp new file mode 100644 index 0000000000..13be162af5 --- /dev/null +++ b/dom/media/platforms/wmf/MFMediaEngineDecoderModule.cpp @@ -0,0 +1,174 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "MFMediaEngineDecoderModule.h" + +#include "MFTDecoder.h" +#include "VideoUtils.h" +#include "mozilla/MFMediaEngineParent.h" +#include "mozilla/MFMediaEngineUtils.h" +#include "mozilla/StaticPrefs_media.h" +#include "mozilla/WindowsVersion.h" +#include "mozilla/mscom/EnsureMTA.h" + +namespace mozilla { + +#define LOG(msg, ...) \ + MOZ_LOG(gMFMediaEngineLog, LogLevel::Debug, (msg, ##__VA_ARGS__)) + +/* static */ +void MFMediaEngineDecoderModule::Init() { + // TODO : Init any thing that media engine would need. Implement this when we + // start implementing media engine in following patches. +} + +/* static */ +already_AddRefed<PlatformDecoderModule> MFMediaEngineDecoderModule::Create() { + RefPtr<MFMediaEngineDecoderModule> module = new MFMediaEngineDecoderModule(); + return module.forget(); +} + +/* static */ +bool MFMediaEngineDecoderModule::SupportsConfig(const TrackInfo& aConfig) { + RefPtr<MFMediaEngineDecoderModule> module = new MFMediaEngineDecoderModule(); + return module->SupportInternal(SupportDecoderParams(aConfig), nullptr) != + media::DecodeSupport::Unsupported; +} + +already_AddRefed<MediaDataDecoder> +MFMediaEngineDecoderModule::CreateVideoDecoder( + const CreateDecoderParams& aParams) { + if (!aParams.mMediaEngineId || + !StaticPrefs::media_wmf_media_engine_enabled()) { + return nullptr; + } + RefPtr<MFMediaEngineParent> mediaEngine = + MFMediaEngineParent::GetMediaEngineById(*aParams.mMediaEngineId); + if (!mediaEngine) { + LOG("Can't find media engine %" PRIu64 " for video decoder", + *aParams.mMediaEngineId); + return nullptr; + } + LOG("MFMediaEngineDecoderModule, CreateVideoDecoder"); + RefPtr<MediaDataDecoder> decoder = mediaEngine->GetMediaEngineStream( + TrackInfo::TrackType::kVideoTrack, aParams); + return decoder.forget(); +} + +already_AddRefed<MediaDataDecoder> +MFMediaEngineDecoderModule::CreateAudioDecoder( + const CreateDecoderParams& aParams) { + if (!aParams.mMediaEngineId || + !StaticPrefs::media_wmf_media_engine_enabled()) { + return nullptr; + } + RefPtr<MFMediaEngineParent> mediaEngine = + MFMediaEngineParent::GetMediaEngineById(*aParams.mMediaEngineId); + if (!mediaEngine) { + LOG("Can't find media engine %" PRIu64 " for audio decoder", + *aParams.mMediaEngineId); + return nullptr; + } + LOG("MFMediaEngineDecoderModule, CreateAudioDecoder"); + RefPtr<MediaDataDecoder> decoder = mediaEngine->GetMediaEngineStream( + TrackInfo::TrackType::kAudioTrack, aParams); + return decoder.forget(); +} + +media::DecodeSupportSet MFMediaEngineDecoderModule::SupportsMimeType( + const nsACString& aMimeType, DecoderDoctorDiagnostics* aDiagnostics) const { + UniquePtr<TrackInfo> trackInfo = CreateTrackInfoWithMIMEType(aMimeType); + if (!trackInfo) { + return media::DecodeSupport::Unsupported; + } + return SupportInternal(SupportDecoderParams(*trackInfo), aDiagnostics); +} + +media::DecodeSupportSet MFMediaEngineDecoderModule::Supports( + const SupportDecoderParams& aParams, + DecoderDoctorDiagnostics* aDiagnostics) const { + if (!aParams.mMediaEngineId) { + return media::DecodeSupport::Unsupported; + } + return SupportInternal(aParams, aDiagnostics); +} + +media::DecodeSupportSet MFMediaEngineDecoderModule::SupportInternal( + const SupportDecoderParams& aParams, + DecoderDoctorDiagnostics* aDiagnostics) const { + if (!StaticPrefs::media_wmf_media_engine_enabled()) { + return media::DecodeSupport::Unsupported; + } + bool supports = false; + WMFStreamType type = GetStreamTypeFromMimeType(aParams.MimeType()); + if (type != WMFStreamType::Unknown) { + supports = CanCreateMFTDecoder(type); + } + MOZ_LOG(sPDMLog, LogLevel::Debug, + ("MFMediaEngine decoder %s requested type '%s'", + supports ? "supports" : "rejects", aParams.MimeType().get())); + return supports ? media::DecodeSupport::SoftwareDecode + : media::DecodeSupport::Unsupported; +} + +static bool CreateMFTDecoderOnMTA(const WMFStreamType& aType) { + RefPtr<MFTDecoder> decoder = new MFTDecoder(); + static std::unordered_map<WMFStreamType, bool> sResults; + if (auto rv = sResults.find(aType); rv != sResults.end()) { + return rv->second; + } + + bool result = false; + switch (aType) { + case WMFStreamType::MP3: + result = SUCCEEDED(decoder->Create(CLSID_CMP3DecMediaObject)); + break; + case WMFStreamType::AAC: + result = SUCCEEDED(decoder->Create(CLSID_CMSAACDecMFT)); + break; + // Opus and vorbis are supported via extension. + // https://www.microsoft.com/en-us/p/web-media-extensions/9n5tdp8vcmhs + case WMFStreamType::OPUS: + result = SUCCEEDED(decoder->Create(CLSID_MSOpusDecoder)); + break; + case WMFStreamType::VORBIS: + result = SUCCEEDED(decoder->Create( + MFT_CATEGORY_AUDIO_DECODER, MFAudioFormat_Vorbis, MFAudioFormat_PCM)); + break; + case WMFStreamType::H264: + result = SUCCEEDED(decoder->Create(CLSID_CMSH264DecoderMFT)); + break; + case WMFStreamType::VP8: + case WMFStreamType::VP9: { + static const uint32_t VPX_USABLE_BUILD = 16287; + if (IsWindowsBuildOrLater(VPX_USABLE_BUILD)) { + result = SUCCEEDED(decoder->Create(CLSID_CMSVPXDecMFT)); + } + break; + } +#ifdef MOZ_AV1 + case WMFStreamType::AV1: + result = SUCCEEDED(decoder->Create(MFT_CATEGORY_VIDEO_DECODER, + MFVideoFormat_AV1, GUID_NULL)); + break; +#endif + default: + MOZ_ASSERT_UNREACHABLE("Unexpected type"); + } + sResults.insert({aType, result}); + return result; +} + +bool MFMediaEngineDecoderModule::CanCreateMFTDecoder( + const WMFStreamType& aType) const { + // TODO : caching the result to prevent performing on MTA thread everytime. + bool canCreateDecoder = false; + mozilla::mscom::EnsureMTA( + [&]() { canCreateDecoder = CreateMFTDecoderOnMTA(aType); }); + return canCreateDecoder; +} + +#undef LOG + +} // namespace mozilla |