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/. */
7 #include "PDMFactory.h"
10 # include "AOMDecoder.h"
12 #include "AgnosticDecoderModule.h"
13 #include "AudioTrimmer.h"
14 #include "BlankDecoderModule.h"
15 #include "DecoderDoctorDiagnostics.h"
16 #include "EMEDecoderModule.h"
17 #include "GMPDecoderModule.h"
19 #include "MP4Decoder.h"
20 #include "MediaChangeMonitor.h"
21 #include "MediaInfo.h"
22 #include "OpusDecoder.h"
23 #include "TheoraDecoder.h"
24 #include "VPXDecoder.h"
25 #include "VideoUtils.h"
26 #include "VorbisDecoder.h"
27 #include "WAVDecoder.h"
28 #include "mozilla/ClearOnShutdown.h"
29 #include "mozilla/RemoteDecodeUtils.h"
30 #include "mozilla/RemoteDecoderManagerChild.h"
31 #include "mozilla/RemoteDecoderModule.h"
32 #include "mozilla/SharedThreadPool.h"
33 #include "mozilla/StaticPrefs_media.h"
34 #include "mozilla/SyncRunnable.h"
35 #include "mozilla/TaskQueue.h"
36 #include "mozilla/gfx/gfxVars.h"
37 #include "nsIXULRuntime.h" // for BrowserTabsRemoteAutostart
38 #include "nsPrintfCString.h"
40 #include "mozilla/ipc/UtilityAudioDecoderParent.h"
43 # include "WMFDecoderModule.h"
44 # include "mozilla/WindowsVersion.h"
45 # ifdef MOZ_WMF_MEDIA_ENGINE
46 # include "MFMediaEngineDecoderModule.h"
49 # include "mozilla/CDMProxy.h"
53 # include "FFVPXRuntimeLinker.h"
56 # include "FFmpegRuntimeLinker.h"
59 # include "AppleDecoderModule.h"
61 #ifdef MOZ_WIDGET_ANDROID
62 # include "AndroidDecoderModule.h"
65 # include "OmxDecoderModule.h"
70 using DecodeSupport
= mozilla::media::DecodeSupport
;
71 using DecodeSupportSet
= mozilla::media::DecodeSupportSet
;
72 using MediaCodec
= mozilla::media::MediaCodec
;
73 using MediaCodecsSupport
= mozilla::media::MediaCodecsSupport
;
74 using MediaCodecsSupported
= mozilla::media::MediaCodecsSupported
;
75 using MCSInfo
= mozilla::media::MCSInfo
;
79 #define PDM_INIT_LOG(msg, ...) \
80 MOZ_LOG(sPDMLog, LogLevel::Debug, ("PDMInitializer, " msg, ##__VA_ARGS__))
82 extern already_AddRefed
<PlatformDecoderModule
> CreateNullDecoderModule();
84 class PDMInitializer final
{
86 // This function should only be executed ONCE per process.
87 static void InitPDMs();
89 // Return true if we've finished PDMs initialization.
90 static bool HasInitializedPDMs();
93 static void InitGpuPDMs() {
95 if (!IsWin7AndPre2000Compatible()) {
96 WMFDecoderModule::Init();
101 static void InitRddPDMs() {
103 if (!IsWin7AndPre2000Compatible()) {
104 WMFDecoderModule::Init();
107 #ifdef MOZ_APPLEMEDIA
108 AppleDecoderModule::Init();
111 FFVPXRuntimeLinker::Init();
114 if (StaticPrefs::media_rdd_ffmpeg_enabled()) {
115 FFmpegRuntimeLinker::Init();
120 static void InitUtilityPDMs() {
121 const ipc::SandboxingKind kind
= GetCurrentSandboxingKind();
123 if (!IsWin7AndPre2000Compatible() &&
124 kind
== ipc::SandboxingKind::UTILITY_AUDIO_DECODING_WMF
) {
125 WMFDecoderModule::Init();
127 # ifdef MOZ_WMF_MEDIA_ENGINE
128 if (IsWin10OrLater() && StaticPrefs::media_wmf_media_engine_enabled() &&
129 kind
== ipc::SandboxingKind::MF_MEDIA_ENGINE_CDM
) {
130 MFMediaEngineDecoderModule::Init();
134 #ifdef MOZ_APPLEMEDIA
135 if (kind
== ipc::SandboxingKind::UTILITY_AUDIO_DECODING_APPLE_MEDIA
) {
136 AppleDecoderModule::Init();
140 if (kind
== ipc::SandboxingKind::GENERIC_UTILITY
) {
141 FFVPXRuntimeLinker::Init();
145 if (StaticPrefs::media_utility_ffmpeg_enabled() &&
146 kind
== ipc::SandboxingKind::GENERIC_UTILITY
) {
147 FFmpegRuntimeLinker::Init();
152 static void InitContentPDMs() {
153 if (StaticPrefs::media_allow_audio_non_utility()) {
155 if (!IsWin7AndPre2000Compatible()) {
157 if (!StaticPrefs::media_rdd_process_enabled() ||
158 !StaticPrefs::media_rdd_wmf_enabled() ||
159 !StaticPrefs::media_utility_process_enabled() ||
160 !StaticPrefs::media_utility_wmf_enabled()) {
161 WMFDecoderModule::Init();
166 #ifdef MOZ_APPLEMEDIA
167 AppleDecoderModule::Init();
170 OmxDecoderModule::Init();
173 FFVPXRuntimeLinker::Init();
176 FFmpegRuntimeLinker::Init();
180 RemoteDecoderManagerChild::Init();
183 static void InitDefaultPDMs() {
185 if (!IsWin7AndPre2000Compatible()) {
186 WMFDecoderModule::Init();
189 #ifdef MOZ_APPLEMEDIA
190 AppleDecoderModule::Init();
193 OmxDecoderModule::Init();
196 FFVPXRuntimeLinker::Init();
199 FFmpegRuntimeLinker::Init();
203 static bool sHasInitializedPDMs
;
204 static StaticMutex sMonitor MOZ_UNANNOTATED
;
207 bool PDMInitializer::sHasInitializedPDMs
= false;
208 StaticMutex
PDMInitializer::sMonitor
;
211 void PDMInitializer::InitPDMs() {
212 StaticMutexAutoLock
mon(sMonitor
);
213 MOZ_DIAGNOSTIC_ASSERT(NS_IsMainThread());
214 MOZ_ASSERT(!sHasInitializedPDMs
);
215 if (XRE_IsGPUProcess()) {
216 PDM_INIT_LOG("Init PDMs in GPU process");
218 } else if (XRE_IsRDDProcess()) {
219 PDM_INIT_LOG("Init PDMs in RDD process");
221 } else if (XRE_IsUtilityProcess()) {
222 PDM_INIT_LOG("Init PDMs in Utility process");
224 } else if (XRE_IsContentProcess()) {
225 PDM_INIT_LOG("Init PDMs in Content process");
228 MOZ_DIAGNOSTIC_ASSERT(XRE_IsParentProcess(),
229 "PDMFactory is only usable in the "
230 "Parent/GPU/RDD/Utility/Content process");
231 PDM_INIT_LOG("Init PDMs in Chrome process");
234 sHasInitializedPDMs
= true;
238 bool PDMInitializer::HasInitializedPDMs() {
239 StaticMutexAutoLock
mon(sMonitor
);
240 return sHasInitializedPDMs
;
243 class SupportChecker
{
245 enum class Reason
: uint8_t {
247 kVideoFormatNotSupported
,
248 kAudioFormatNotSupported
,
253 explicit CheckResult(Reason aReason
,
254 MediaResult aResult
= MediaResult(NS_OK
))
255 : mReason(aReason
), mMediaResult(std::move(aResult
)) {}
256 CheckResult(const CheckResult
& aOther
) = default;
257 CheckResult(CheckResult
&& aOther
) = default;
258 CheckResult
& operator=(const CheckResult
& aOther
) = default;
259 CheckResult
& operator=(CheckResult
&& aOther
) = default;
262 MediaResult mMediaResult
;
265 template <class Func
>
266 void AddToCheckList(Func
&& aChecker
) {
267 mCheckerList
.AppendElement(std::forward
<Func
>(aChecker
));
270 void AddMediaFormatChecker(const TrackInfo
& aTrackConfig
) {
271 if (aTrackConfig
.IsVideo()) {
272 auto mimeType
= aTrackConfig
.GetAsVideoInfo()->mMimeType
;
273 RefPtr
<MediaByteBuffer
> extraData
=
274 aTrackConfig
.GetAsVideoInfo()->mExtraData
;
275 AddToCheckList([mimeType
, extraData
]() {
276 if (MP4Decoder::IsH264(mimeType
)) {
278 // WMF H.264 Video Decoder and Apple ATDecoder
279 // do not support YUV444 format.
280 // For consistency, all decoders should be checked.
281 if (H264::DecodeSPSFromExtraData(extraData
, spsdata
) &&
282 (spsdata
.profile_idc
== 244 /* Hi444PP */ ||
283 spsdata
.chroma_format_idc
== PDMFactory::kYUV444
)) {
285 SupportChecker::Reason::kVideoFormatNotSupported
,
287 NS_ERROR_DOM_MEDIA_FATAL_ERR
,
288 RESULT_DETAIL("Decoder may not have the capability "
289 "to handle the requested video format "
290 "with YUV444 chroma subsampling.")));
293 return CheckResult(SupportChecker::Reason::kSupported
);
298 SupportChecker::CheckResult
Check() {
299 for (auto& checker
: mCheckerList
) {
300 auto result
= checker();
301 if (result
.mReason
!= SupportChecker::Reason::kSupported
) {
305 return CheckResult(SupportChecker::Reason::kSupported
);
308 void Clear() { mCheckerList
.Clear(); }
311 nsTArray
<std::function
<CheckResult()>> mCheckerList
;
314 PDMFactory::PDMFactory() {
320 PDMFactory::~PDMFactory() = default;
323 void PDMFactory::EnsureInit() {
324 if (PDMInitializer::HasInitializedPDMs()) {
327 auto initalization
= []() {
328 MOZ_DIAGNOSTIC_ASSERT(NS_IsMainThread());
329 if (!PDMInitializer::HasInitializedPDMs()) {
330 // Ensure that all system variables are initialized.
331 gfx::gfxVars::Initialize();
332 // Prime the preferences system from the main thread.
333 Unused
<< BrowserTabsRemoteAutostart();
334 PDMInitializer::InitPDMs();
337 // If on the main thread, then initialize PDMs. Otherwise, do a sync-dispatch
339 if (NS_IsMainThread()) {
343 nsCOMPtr
<nsIEventTarget
> mainTarget
= GetMainThreadSerialEventTarget();
344 nsCOMPtr
<nsIRunnable
> runnable
= NS_NewRunnableFunction(
345 "PDMFactory::EnsureInit", std::move(initalization
));
346 SyncRunnable::DispatchToThread(mainTarget
, runnable
);
349 RefPtr
<PlatformDecoderModule::CreateDecoderPromise
> PDMFactory::CreateDecoder(
350 const CreateDecoderParams
& aParams
) {
351 if (aParams
.mUseNullDecoder
.mUse
) {
352 MOZ_ASSERT(mNullPDM
);
353 return CreateDecoderWithPDM(mNullPDM
, aParams
);
355 bool isEncrypted
= mEMEPDM
&& aParams
.mConfig
.mCrypto
.IsEncrypted();
358 return CreateDecoderWithPDM(mEMEPDM
, aParams
);
361 return CheckAndMaybeCreateDecoder(CreateDecoderParamsForAsync(aParams
), 0);
364 RefPtr
<PlatformDecoderModule::CreateDecoderPromise
>
365 PDMFactory::CheckAndMaybeCreateDecoder(CreateDecoderParamsForAsync
&& aParams
,
367 Maybe
<MediaResult
> aEarlierError
) {
369 auto params
= SupportDecoderParams(aParams
);
370 for (; i
< mCurrentPDMs
.Length(); i
++) {
371 if (mCurrentPDMs
[i
]->Supports(params
, nullptr /* diagnostic */) ==
372 media::DecodeSupport::Unsupported
) {
375 RefPtr
<PlatformDecoderModule::CreateDecoderPromise
> p
=
376 CreateDecoderWithPDM(mCurrentPDMs
[i
], aParams
)
378 GetCurrentSerialEventTarget(), __func__
,
379 [](RefPtr
<MediaDataDecoder
>&& aDecoder
) {
380 return PlatformDecoderModule::CreateDecoderPromise::
381 CreateAndResolve(std::move(aDecoder
), __func__
);
383 [self
= RefPtr
{this}, i
, params
= std::move(aParams
)](
384 const MediaResult
& aError
) mutable {
386 return self
->CheckAndMaybeCreateDecoder(std::move(params
),
387 i
+ 1, Some(aError
));
392 return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject(
393 std::move(*aEarlierError
), __func__
);
395 return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject(
396 MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR
,
397 nsPrintfCString("Error no decoder found for %s",
398 aParams
.mConfig
->mMimeType
.get())
403 RefPtr
<PlatformDecoderModule::CreateDecoderPromise
>
404 PDMFactory::CreateDecoderWithPDM(PlatformDecoderModule
* aPDM
,
405 const CreateDecoderParams
& aParams
) {
407 MediaResult result
= NS_OK
;
409 SupportChecker supportChecker
;
410 const TrackInfo
& config
= aParams
.mConfig
;
411 supportChecker
.AddMediaFormatChecker(config
);
413 auto checkResult
= supportChecker
.Check();
414 if (checkResult
.mReason
!= SupportChecker::Reason::kSupported
) {
415 if (checkResult
.mReason
==
416 SupportChecker::Reason::kVideoFormatNotSupported
) {
417 result
= checkResult
.mMediaResult
;
418 } else if (checkResult
.mReason
==
419 SupportChecker::Reason::kAudioFormatNotSupported
) {
420 result
= checkResult
.mMediaResult
;
422 return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject(
426 if (config
.IsAudio()) {
427 RefPtr
<PlatformDecoderModule::CreateDecoderPromise
> p
;
428 p
= aPDM
->AsyncCreateDecoder(aParams
)->Then(
429 GetCurrentSerialEventTarget(), __func__
,
430 [params
= CreateDecoderParamsForAsync(aParams
)](
431 RefPtr
<MediaDataDecoder
>&& aDecoder
) {
432 RefPtr
<MediaDataDecoder
> decoder
= std::move(aDecoder
);
433 if (!params
.mNoWrapper
.mDontUseWrapper
) {
435 new AudioTrimmer(decoder
.forget(), CreateDecoderParams(params
));
437 return PlatformDecoderModule::CreateDecoderPromise::CreateAndResolve(
440 [](const MediaResult
& aError
) {
441 return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject(
447 if (!config
.IsVideo()) {
448 return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject(
450 NS_ERROR_DOM_MEDIA_FATAL_ERR
,
452 "Decoder configuration error, expected audio or video.")),
456 if ((MP4Decoder::IsH264(config
.mMimeType
) ||
458 AOMDecoder::IsAV1(config
.mMimeType
) ||
460 VPXDecoder::IsVPX(config
.mMimeType
)) &&
461 !aParams
.mUseNullDecoder
.mUse
&& !aParams
.mNoWrapper
.mDontUseWrapper
) {
462 return MediaChangeMonitor::Create(this, aParams
);
464 return aPDM
->AsyncCreateDecoder(aParams
);
467 DecodeSupportSet
PDMFactory::SupportsMimeType(
468 const nsACString
& aMimeType
) const {
469 UniquePtr
<TrackInfo
> trackInfo
= CreateTrackInfoWithMIMEType(aMimeType
);
471 return DecodeSupport::Unsupported
;
473 return Supports(SupportDecoderParams(*trackInfo
), nullptr);
476 DecodeSupportSet
PDMFactory::Supports(
477 const SupportDecoderParams
& aParams
,
478 DecoderDoctorDiagnostics
* aDiagnostics
) const {
480 return mEMEPDM
->Supports(aParams
, aDiagnostics
);
483 RefPtr
<PlatformDecoderModule
> current
=
484 GetDecoderModule(aParams
, aDiagnostics
);
487 return DecodeSupport::Unsupported
;
490 // We have a PDM - check for + return SW/HW support info
491 return current
->Supports(aParams
, aDiagnostics
);
494 void PDMFactory::CreatePDMs() {
495 if (StaticPrefs::media_use_blank_decoder()) {
496 CreateAndStartupPDM
<BlankDecoderModule
>();
497 // The Blank PDM SupportsMimeType reports true for all codecs; the creation
498 // of its decoder is infallible. As such it will be used for all media, we
499 // can stop creating more PDM from this point.
503 if (XRE_IsGPUProcess()) {
505 } else if (XRE_IsRDDProcess()) {
507 } else if (XRE_IsUtilityProcess()) {
509 } else if (XRE_IsContentProcess()) {
512 MOZ_DIAGNOSTIC_ASSERT(
513 XRE_IsParentProcess(),
514 "PDMFactory is only usable in the Parent/GPU/RDD/Content process");
519 void PDMFactory::CreateGpuPDMs() {
521 if (StaticPrefs::media_wmf_enabled() && !IsWin7AndPre2000Compatible()) {
522 CreateAndStartupPDM
<WMFDecoderModule
>();
527 #if defined(MOZ_FFMPEG)
528 static DecoderDoctorDiagnostics::Flags
GetFailureFlagBasedOnFFmpegStatus(
529 const FFmpegRuntimeLinker::LinkStatus
& aStatus
) {
531 case FFmpegRuntimeLinker::LinkStatus_INVALID_FFMPEG_CANDIDATE
:
532 case FFmpegRuntimeLinker::LinkStatus_UNUSABLE_LIBAV57
:
533 case FFmpegRuntimeLinker::LinkStatus_INVALID_LIBAV_CANDIDATE
:
534 case FFmpegRuntimeLinker::LinkStatus_OBSOLETE_FFMPEG
:
535 case FFmpegRuntimeLinker::LinkStatus_OBSOLETE_LIBAV
:
536 case FFmpegRuntimeLinker::LinkStatus_INVALID_CANDIDATE
:
537 return DecoderDoctorDiagnostics::Flags::LibAVCodecUnsupported
;
539 MOZ_DIAGNOSTIC_ASSERT(
540 aStatus
== FFmpegRuntimeLinker::LinkStatus_NOT_FOUND
,
541 "Only call this method when linker fails.");
542 return DecoderDoctorDiagnostics::Flags::FFmpegNotFound
;
547 void PDMFactory::CreateRddPDMs() {
549 if (StaticPrefs::media_wmf_enabled() &&
550 StaticPrefs::media_rdd_wmf_enabled()) {
551 CreateAndStartupPDM
<WMFDecoderModule
>();
554 #ifdef MOZ_APPLEMEDIA
555 if (StaticPrefs::media_rdd_applemedia_enabled()) {
556 CreateAndStartupPDM
<AppleDecoderModule
>();
560 if (StaticPrefs::media_ffvpx_enabled() &&
561 StaticPrefs::media_rdd_ffvpx_enabled()) {
562 CreateAndStartupPDM
<FFVPXRuntimeLinker
>();
566 if (StaticPrefs::media_ffmpeg_enabled() &&
567 StaticPrefs::media_rdd_ffmpeg_enabled() &&
568 !CreateAndStartupPDM
<FFmpegRuntimeLinker
>()) {
569 mFailureFlags
+= GetFailureFlagBasedOnFFmpegStatus(
570 FFmpegRuntimeLinker::LinkStatusCode());
573 CreateAndStartupPDM
<AgnosticDecoderModule
>();
576 void PDMFactory::CreateUtilityPDMs() {
577 const ipc::SandboxingKind aKind
= GetCurrentSandboxingKind();
579 if (StaticPrefs::media_wmf_enabled() &&
580 StaticPrefs::media_utility_wmf_enabled() &&
581 aKind
== ipc::SandboxingKind::UTILITY_AUDIO_DECODING_WMF
) {
582 CreateAndStartupPDM
<WMFDecoderModule
>();
585 #ifdef MOZ_APPLEMEDIA
586 if (StaticPrefs::media_utility_applemedia_enabled() &&
587 aKind
== ipc::SandboxingKind::UTILITY_AUDIO_DECODING_APPLE_MEDIA
) {
588 CreateAndStartupPDM
<AppleDecoderModule
>();
591 if (aKind
== ipc::SandboxingKind::GENERIC_UTILITY
) {
593 if (StaticPrefs::media_ffvpx_enabled() &&
594 StaticPrefs::media_utility_ffvpx_enabled()) {
595 CreateAndStartupPDM
<FFVPXRuntimeLinker
>();
599 if (StaticPrefs::media_ffmpeg_enabled() &&
600 StaticPrefs::media_utility_ffmpeg_enabled() &&
601 !CreateAndStartupPDM
<FFmpegRuntimeLinker
>()) {
602 mFailureFlags
+= GetFailureFlagBasedOnFFmpegStatus(
603 FFmpegRuntimeLinker::LinkStatusCode());
606 #ifdef MOZ_WIDGET_ANDROID
607 if (StaticPrefs::media_utility_android_media_codec_enabled()) {
608 StartupPDM(AndroidDecoderModule::Create(),
609 StaticPrefs::media_android_media_codec_preferred());
612 CreateAndStartupPDM
<AgnosticDecoderModule
>();
614 #ifdef MOZ_WMF_MEDIA_ENGINE
615 if (aKind
== ipc::SandboxingKind::MF_MEDIA_ENGINE_CDM
) {
616 if (IsWin10OrLater() && StaticPrefs::media_wmf_media_engine_enabled()) {
617 CreateAndStartupPDM
<MFMediaEngineDecoderModule
>();
623 void PDMFactory::CreateContentPDMs() {
624 if (StaticPrefs::media_gpu_process_decoder()) {
625 CreateAndStartupPDM
<RemoteDecoderModule
>(RemoteDecodeIn::GpuProcess
);
628 if (StaticPrefs::media_rdd_process_enabled()) {
629 CreateAndStartupPDM
<RemoteDecoderModule
>(RemoteDecodeIn::RddProcess
);
632 if (StaticPrefs::media_utility_process_enabled()) {
633 #ifdef MOZ_APPLEMEDIA
634 CreateAndStartupPDM
<RemoteDecoderModule
>(
635 RemoteDecodeIn::UtilityProcess_AppleMedia
);
638 CreateAndStartupPDM
<RemoteDecoderModule
>(
639 RemoteDecodeIn::UtilityProcess_WMF
);
641 // WMF and AppleMedia should be created before Generic because the order
642 // affects what decoder module would be chose first.
643 CreateAndStartupPDM
<RemoteDecoderModule
>(
644 RemoteDecodeIn::UtilityProcess_Generic
);
646 #ifdef MOZ_WMF_MEDIA_ENGINE
647 if (StaticPrefs::media_wmf_media_engine_enabled()) {
648 CreateAndStartupPDM
<RemoteDecoderModule
>(
649 RemoteDecodeIn::UtilityProcess_MFMediaEngineCDM
);
653 #if !defined(MOZ_WIDGET_ANDROID)
654 if (StaticPrefs::media_allow_audio_non_utility()) {
655 #endif // !defined(MOZ_WIDGET_ANDROID)
657 if (StaticPrefs::media_wmf_enabled() && !IsWin7AndPre2000Compatible()) {
659 if (!StaticPrefs::media_rdd_process_enabled() ||
660 !StaticPrefs::media_rdd_wmf_enabled()) {
661 if (!CreateAndStartupPDM
<WMFDecoderModule
>()) {
662 mFailureFlags
+= DecoderDoctorDiagnostics::Flags::WMFFailedToLoad
;
666 } else if (StaticPrefs::media_decoder_doctor_wmf_disabled_is_failure()) {
667 mFailureFlags
+= DecoderDoctorDiagnostics::Flags::WMFFailedToLoad
;
671 #ifdef MOZ_APPLEMEDIA
672 CreateAndStartupPDM
<AppleDecoderModule
>();
675 if (StaticPrefs::media_omx_enabled()) {
676 CreateAndStartupPDM
<OmxDecoderModule
>();
680 if (StaticPrefs::media_ffvpx_enabled()) {
681 CreateAndStartupPDM
<FFVPXRuntimeLinker
>();
685 if (StaticPrefs::media_ffmpeg_enabled() &&
686 !CreateAndStartupPDM
<FFmpegRuntimeLinker
>()) {
687 mFailureFlags
+= GetFailureFlagBasedOnFFmpegStatus(
688 FFmpegRuntimeLinker::LinkStatusCode());
692 CreateAndStartupPDM
<AgnosticDecoderModule
>();
693 #if !defined(MOZ_WIDGET_ANDROID)
695 #endif // !defined(MOZ_WIDGET_ANDROID)
697 // Android still needs this, the actual decoder is remoted on java side
698 #ifdef MOZ_WIDGET_ANDROID
699 if (StaticPrefs::media_android_media_codec_enabled()) {
700 StartupPDM(AndroidDecoderModule::Create(),
701 StaticPrefs::media_android_media_codec_preferred());
705 // TODO: Should this be also under media_allow_audio_non_utility ?
706 if (StaticPrefs::media_gmp_decoder_enabled() &&
707 !StartupPDM(GMPDecoderModule::Create(),
708 StaticPrefs::media_gmp_decoder_preferred())) {
709 mFailureFlags
+= DecoderDoctorDiagnostics::Flags::GMPPDMFailedToStartup
;
713 void PDMFactory::CreateDefaultPDMs() {
715 if (StaticPrefs::media_wmf_enabled() && !IsWin7AndPre2000Compatible()) {
716 if (!CreateAndStartupPDM
<WMFDecoderModule
>()) {
717 mFailureFlags
+= DecoderDoctorDiagnostics::Flags::WMFFailedToLoad
;
719 } else if (StaticPrefs::media_decoder_doctor_wmf_disabled_is_failure()) {
720 mFailureFlags
+= DecoderDoctorDiagnostics::Flags::WMFFailedToLoad
;
724 #ifdef MOZ_APPLEMEDIA
725 CreateAndStartupPDM
<AppleDecoderModule
>();
728 if (StaticPrefs::media_omx_enabled()) {
729 CreateAndStartupPDM
<OmxDecoderModule
>();
733 if (StaticPrefs::media_ffvpx_enabled()) {
734 CreateAndStartupPDM
<FFVPXRuntimeLinker
>();
738 if (StaticPrefs::media_ffmpeg_enabled() &&
739 !CreateAndStartupPDM
<FFmpegRuntimeLinker
>()) {
740 mFailureFlags
+= GetFailureFlagBasedOnFFmpegStatus(
741 FFmpegRuntimeLinker::LinkStatusCode());
744 #ifdef MOZ_WIDGET_ANDROID
745 if (StaticPrefs::media_android_media_codec_enabled()) {
746 StartupPDM(AndroidDecoderModule::Create(),
747 StaticPrefs::media_android_media_codec_preferred());
751 CreateAndStartupPDM
<AgnosticDecoderModule
>();
753 if (StaticPrefs::media_gmp_decoder_enabled() &&
754 !StartupPDM(GMPDecoderModule::Create(),
755 StaticPrefs::media_gmp_decoder_preferred())) {
756 mFailureFlags
+= DecoderDoctorDiagnostics::Flags::GMPPDMFailedToStartup
;
760 void PDMFactory::CreateNullPDM() {
761 mNullPDM
= CreateNullDecoderModule();
762 MOZ_ASSERT(mNullPDM
&& NS_SUCCEEDED(mNullPDM
->Startup()));
765 bool PDMFactory::StartupPDM(already_AddRefed
<PlatformDecoderModule
> aPDM
,
766 bool aInsertAtBeginning
) {
767 RefPtr
<PlatformDecoderModule
> pdm
= aPDM
;
768 if (pdm
&& NS_SUCCEEDED(pdm
->Startup())) {
769 if (aInsertAtBeginning
) {
770 mCurrentPDMs
.InsertElementAt(0, pdm
);
772 mCurrentPDMs
.AppendElement(pdm
);
779 already_AddRefed
<PlatformDecoderModule
> PDMFactory::GetDecoderModule(
780 const SupportDecoderParams
& aParams
,
781 DecoderDoctorDiagnostics
* aDiagnostics
) const {
783 // If libraries failed to load, the following loop over mCurrentPDMs
784 // will not even try to use them. So we record failures now.
785 aDiagnostics
->SetFailureFlags(mFailureFlags
);
788 RefPtr
<PlatformDecoderModule
> pdm
;
789 for (const auto& current
: mCurrentPDMs
) {
790 if (current
->Supports(aParams
, aDiagnostics
) !=
791 media::DecodeSupport::Unsupported
) {
799 void PDMFactory::SetCDMProxy(CDMProxy
* aProxy
) {
802 #ifdef MOZ_WIDGET_ANDROID
803 if (IsWidevineKeySystem(aProxy
->KeySystem())) {
804 mEMEPDM
= AndroidDecoderModule::Create(aProxy
);
809 if (IsPlayReadyKeySystemAndSupported(aProxy
->KeySystem())) {
810 mEMEPDM
= RemoteDecoderModule::Create(
811 RemoteDecodeIn::UtilityProcess_MFMediaEngineCDM
);
815 auto m
= MakeRefPtr
<PDMFactory
>();
816 mEMEPDM
= MakeRefPtr
<EMEDecoderModule
>(aProxy
, m
);
820 media::MediaCodecsSupported
PDMFactory::Supported(bool aForceRefresh
) {
821 MOZ_ASSERT(NS_IsMainThread());
823 static auto calculate
= []() {
824 auto pdm
= MakeRefPtr
<PDMFactory
>();
825 MediaCodecsSupported supported
;
826 // H264 and AAC depends on external framework that must be dynamically
828 // We currently only ship a single PDM per platform able to decode AAC or
829 // H264. As such we can assert that being able to create a H264 or AAC
830 // decoder indicates that with WMF on Windows or FFmpeg on Unixes is
832 // This logic will have to be revisited if a PDM supporting either codec
833 // will be added in addition to the WMF and FFmpeg PDM (such as OpenH264)
834 for (const auto& cd
: MCSInfo::GetAllCodecDefinitions()) {
835 supported
+= MCSInfo::GetDecodeMediaCodecsSupported(
836 cd
.codec
, pdm
->SupportsMimeType(nsCString(cd
.mimeTypeString
)));
841 static MediaCodecsSupported supported
= calculate();
843 supported
= calculate();
850 DecodeSupportSet
PDMFactory::SupportsMimeType(
851 const nsACString
& aMimeType
, const MediaCodecsSupported
& aSupported
,
852 RemoteDecodeIn aLocation
) {
853 const TrackSupportSet supports
=
854 RemoteDecoderManagerChild::GetTrackSupport(aLocation
);
856 if (supports
.contains(TrackSupport::Video
)) {
857 if (MP4Decoder::IsH264(aMimeType
)) {
858 return MCSInfo::GetDecodeSupportSet(MediaCodec::H264
, aSupported
);
860 if (VPXDecoder::IsVP9(aMimeType
)) {
861 return MCSInfo::GetDecodeSupportSet(MediaCodec::VP9
, aSupported
);
863 if (VPXDecoder::IsVP8(aMimeType
)) {
864 return MCSInfo::GetDecodeSupportSet(MediaCodec::VP8
, aSupported
);
867 if (AOMDecoder::IsAV1(aMimeType
)) {
868 return MCSInfo::GetDecodeSupportSet(MediaCodec::AV1
, aSupported
);
871 if (TheoraDecoder::IsTheora(aMimeType
)) {
872 return MCSInfo::GetDecodeSupportSet(MediaCodec::Theora
, aSupported
);
876 if (supports
.contains(TrackSupport::Audio
)) {
877 if (MP4Decoder::IsAAC(aMimeType
)) {
878 return MCSInfo::GetDecodeSupportSet(MediaCodec::AAC
, aSupported
);
880 if (aMimeType
.EqualsLiteral("audio/mpeg")) {
881 return MCSInfo::GetDecodeSupportSet(MediaCodec::MP3
, aSupported
);
883 if (OpusDataDecoder::IsOpus(aMimeType
)) {
884 return MCSInfo::GetDecodeSupportSet(MediaCodec::Opus
, aSupported
);
886 if (VorbisDataDecoder::IsVorbis(aMimeType
)) {
887 return MCSInfo::GetDecodeSupportSet(MediaCodec::Vorbis
, aSupported
);
889 if (aMimeType
.EqualsLiteral("audio/flac")) {
890 return MCSInfo::GetDecodeSupportSet(MediaCodec::FLAC
, aSupported
);
892 if (WaveDataDecoder::IsWave(aMimeType
)) {
893 return MCSInfo::GetDecodeSupportSet(MediaCodec::Wave
, aSupported
);
896 return DecodeSupport::Unsupported
;
900 bool PDMFactory::AllDecodersAreRemote() {
901 return StaticPrefs::media_rdd_process_enabled() &&
902 #if defined(MOZ_FFVPX)
903 StaticPrefs::media_rdd_ffvpx_enabled() &&
905 StaticPrefs::media_rdd_opus_enabled() &&
906 StaticPrefs::media_rdd_theora_enabled() &&
907 StaticPrefs::media_rdd_vorbis_enabled() &&
908 StaticPrefs::media_rdd_vpx_enabled() &&
910 StaticPrefs::media_rdd_wmf_enabled() &&
912 StaticPrefs::media_rdd_wav_enabled();
916 } // namespace mozilla