189 lines
6.5 KiB
C++
189 lines
6.5 KiB
C++
/* 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/gfx/gfxVars.h"
|
|
#include "mozilla/MFMediaEngineParent.h"
|
|
#include "mozilla/MFMediaEngineUtils.h"
|
|
#include "mozilla/RemoteDecoderManagerChild.h"
|
|
#include "mozilla/RemoteDecoderModule.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<PlatformDecoderModule> module = RemoteDecoderModule::Create(
|
|
RemoteDecodeIn::UtilityProcess_MFMediaEngineCDM);
|
|
return !module->Supports(SupportDecoderParams(aConfig), nullptr).isEmpty();
|
|
}
|
|
|
|
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::DecodeSupportSet{};
|
|
}
|
|
return SupportInternal(SupportDecoderParams(*trackInfo), aDiagnostics);
|
|
}
|
|
|
|
media::DecodeSupportSet MFMediaEngineDecoderModule::Supports(
|
|
const SupportDecoderParams& aParams,
|
|
DecoderDoctorDiagnostics* aDiagnostics) const {
|
|
return SupportInternal(aParams, aDiagnostics);
|
|
}
|
|
|
|
media::DecodeSupportSet MFMediaEngineDecoderModule::SupportInternal(
|
|
const SupportDecoderParams& aParams,
|
|
DecoderDoctorDiagnostics* aDiagnostics) const {
|
|
if (!StaticPrefs::media_wmf_media_engine_enabled()) {
|
|
return media::DecodeSupportSet{};
|
|
}
|
|
// Only support hardware decoding.
|
|
if (!gfx::gfxVars::CanUseHardwareVideoDecoding() &&
|
|
!StaticPrefs::media_wmf_media_engine_bypass_gfx_blocklist()) {
|
|
return media::DecodeSupportSet{};
|
|
}
|
|
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()));
|
|
if (!supports) {
|
|
return media::DecodeSupportSet{};
|
|
}
|
|
return StreamTypeIsVideo(type) ? media::DecodeSupport::HardwareDecode
|
|
: media::DecodeSupport::SoftwareDecode;
|
|
}
|
|
|
|
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 (IsWindows10BuildOrLater(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
|
|
case WMFStreamType::HEVC:
|
|
if (StaticPrefs::media_hevc_enabled()) {
|
|
result =
|
|
SUCCEEDED(decoder->Create(MFT_CATEGORY_VIDEO_DECODER,
|
|
MFVideoFormat_HEVC, MFVideoFormat_NV12));
|
|
}
|
|
break;
|
|
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
|