PDMFactory.cpp (29819B)
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 7 #include "PDMFactory.h" 8 9 #ifdef MOZ_AV1 10 # include "AOMDecoder.h" 11 #endif 12 #include "AgnosticDecoderModule.h" 13 #include "AudioTrimmer.h" 14 #include "BlankDecoderModule.h" 15 #include "DecoderDoctorDiagnostics.h" 16 #include "EMEDecoderModule.h" 17 #include "GMPDecoderModule.h" 18 #include "H264.h" 19 #include "MP4Decoder.h" 20 #include "MediaChangeMonitor.h" 21 #include "MediaInfo.h" 22 #include "VPXDecoder.h" 23 #include "VideoUtils.h" 24 #include "mozilla/ClearOnShutdown.h" 25 #include "mozilla/RemoteDecodeUtils.h" 26 #include "mozilla/RemoteDecoderModule.h" 27 #include "mozilla/RemoteMediaManagerChild.h" 28 #include "mozilla/SharedThreadPool.h" 29 #include "mozilla/StaticMutex.h" 30 #include "mozilla/StaticPrefs_media.h" 31 #include "mozilla/SyncRunnable.h" 32 #include "mozilla/TaskQueue.h" 33 #include "mozilla/gfx/gfxVars.h" 34 #include "mozilla/ipc/UtilityMediaServiceParent.h" 35 #include "nsIXULRuntime.h" // for BrowserTabsRemoteAutostart 36 #include "nsPrintfCString.h" 37 38 #ifdef XP_WIN 39 # include "WMFDecoderModule.h" 40 # ifdef MOZ_WMF_MEDIA_ENGINE 41 # include "MFMediaEngineDecoderModule.h" 42 # endif 43 # ifdef MOZ_WMF_CDM 44 # include "mozilla/CDMProxy.h" 45 # endif 46 #endif 47 #ifdef MOZ_FFMPEG 48 # include "FFmpegRuntimeLinker.h" 49 #endif 50 #ifdef MOZ_APPLEMEDIA 51 # include "AppleDecoderModule.h" 52 #endif 53 #ifdef MOZ_WIDGET_ANDROID 54 # include "AndroidDecoderModule.h" 55 #endif 56 #ifdef MOZ_OMX 57 # include "OmxDecoderModule.h" 58 #endif 59 #include <functional> 60 61 #include "FFVPXRuntimeLinker.h" 62 63 using DecodeSupport = mozilla::media::DecodeSupport; 64 using DecodeSupportSet = mozilla::media::DecodeSupportSet; 65 using MediaCodec = mozilla::media::MediaCodec; 66 using MediaCodecsSupport = mozilla::media::MediaCodecsSupport; 67 using MediaCodecsSupported = mozilla::media::MediaCodecsSupported; 68 using MCSInfo = mozilla::media::MCSInfo; 69 70 namespace mozilla { 71 72 #define PDM_INIT_LOG(msg, ...) \ 73 MOZ_LOG(sPDMLog, LogLevel::Debug, ("PDMInitializer, " msg, ##__VA_ARGS__)) 74 75 extern already_AddRefed<PlatformDecoderModule> CreateNullDecoderModule(); 76 77 MOZ_RUNINIT static StaticDataMutex<StaticRefPtr<PlatformDecoderModule>> 78 sForcedPDM("Forced PDM"); 79 80 class PDMInitializer final { 81 public: 82 // This function should only be executed ONCE per process. 83 static void InitPDMs(); 84 85 // Return true if we've finished PDMs initialization. 86 static bool HasInitializedPDMs(); 87 88 private: 89 static void InitGpuPDMs() { 90 #ifdef XP_WIN 91 WMFDecoderModule::Init(); 92 if (StaticPrefs::media_ffvpx_hw_enabled()) { 93 FFVPXRuntimeLinker::Init(); 94 } 95 #endif 96 } 97 98 static void InitRddPDMs() { 99 #ifdef XP_WIN 100 WMFDecoderModule::Init(); 101 #endif 102 #ifdef MOZ_APPLEMEDIA 103 AppleDecoderModule::Init(); 104 #endif 105 #ifdef MOZ_FFMPEG 106 if (StaticPrefs::media_rdd_ffmpeg_enabled()) { 107 FFmpegRuntimeLinker::Init(); 108 } 109 #endif 110 FFVPXRuntimeLinker::Init(); 111 } 112 113 static void InitUtilityPDMs() { 114 const ipc::SandboxingKind kind = GetCurrentSandboxingKind(); 115 #ifdef XP_WIN 116 if (kind == ipc::SandboxingKind::UTILITY_AUDIO_DECODING_WMF) { 117 WMFDecoderModule::Init(); 118 } 119 # ifdef MOZ_WMF_MEDIA_ENGINE 120 if (StaticPrefs::media_wmf_media_engine_enabled() && 121 kind == ipc::SandboxingKind::MF_MEDIA_ENGINE_CDM) { 122 MFMediaEngineDecoderModule::Init(); 123 } 124 # endif 125 #endif 126 #ifdef MOZ_APPLEMEDIA 127 if (kind == ipc::SandboxingKind::UTILITY_AUDIO_DECODING_APPLE_MEDIA) { 128 AppleDecoderModule::Init(); 129 } 130 #endif 131 if (kind == ipc::SandboxingKind::GENERIC_UTILITY) { 132 FFVPXRuntimeLinker::Init(); 133 } 134 #ifdef MOZ_FFMPEG 135 if (kind == ipc::SandboxingKind::GENERIC_UTILITY) { 136 FFmpegRuntimeLinker::Init(); 137 } 138 #endif 139 } 140 141 static void InitContentPDMs() { 142 #if !defined(MOZ_WIDGET_ANDROID) // Still required for video? 143 if (StaticPrefs::media_allow_audio_non_utility()) { 144 #endif // !defined(MOZ_WIDGET_ANDROID) 145 #ifdef XP_WIN 146 # ifdef MOZ_WMF 147 if (!StaticPrefs::media_rdd_process_enabled() || 148 !StaticPrefs::media_rdd_wmf_enabled()) { 149 WMFDecoderModule::Init(); 150 } 151 # endif 152 #endif 153 #ifdef MOZ_APPLEMEDIA 154 AppleDecoderModule::Init(); 155 #endif 156 #ifdef MOZ_OMX 157 OmxDecoderModule::Init(); 158 #endif 159 FFVPXRuntimeLinker::Init(); 160 #ifdef MOZ_FFMPEG 161 FFmpegRuntimeLinker::Init(); 162 #endif 163 #if !defined(MOZ_WIDGET_ANDROID) // Still required for video? 164 } 165 #endif // !defined(MOZ_WIDGET_ANDROID) 166 167 RemoteMediaManagerChild::Init(); 168 } 169 170 static void InitDefaultPDMs() { 171 #ifdef XP_WIN 172 WMFDecoderModule::Init(); 173 #endif 174 #ifdef MOZ_APPLEMEDIA 175 AppleDecoderModule::Init(); 176 #endif 177 #ifdef MOZ_OMX 178 OmxDecoderModule::Init(); 179 #endif 180 FFVPXRuntimeLinker::Init(); 181 #ifdef MOZ_FFMPEG 182 FFmpegRuntimeLinker::Init(); 183 #endif 184 } 185 186 static bool sHasInitializedPDMs; 187 static StaticMutex sMonitor MOZ_UNANNOTATED; 188 }; 189 190 bool PDMInitializer::sHasInitializedPDMs = false; 191 StaticMutex PDMInitializer::sMonitor; 192 193 /* static */ 194 void PDMInitializer::InitPDMs() { 195 StaticMutexAutoLock mon(sMonitor); 196 if (sHasInitializedPDMs) { 197 return; 198 } 199 if (XRE_IsGPUProcess()) { 200 PDM_INIT_LOG("Init PDMs in GPU process"); 201 InitGpuPDMs(); 202 } else if (XRE_IsRDDProcess()) { 203 PDM_INIT_LOG("Init PDMs in RDD process"); 204 InitRddPDMs(); 205 } else if (XRE_IsUtilityProcess()) { 206 PDM_INIT_LOG("Init PDMs in Utility process"); 207 InitUtilityPDMs(); 208 } else if (XRE_IsContentProcess()) { 209 PDM_INIT_LOG("Init PDMs in Content process"); 210 InitContentPDMs(); 211 } else { 212 MOZ_DIAGNOSTIC_ASSERT(XRE_IsParentProcess(), 213 "PDMFactory is only usable in the " 214 "Parent/GPU/RDD/Utility/Content process"); 215 PDM_INIT_LOG("Init PDMs in Chrome process"); 216 InitDefaultPDMs(); 217 } 218 sHasInitializedPDMs = true; 219 } 220 221 /* static */ 222 bool PDMInitializer::HasInitializedPDMs() { 223 StaticMutexAutoLock mon(sMonitor); 224 return sHasInitializedPDMs; 225 } 226 227 class SupportChecker { 228 public: 229 enum class Reason : uint8_t { 230 kSupported, 231 kVideoFormatNotSupported, 232 kAudioFormatNotSupported, 233 kUnknown, 234 }; 235 236 struct CheckResult { 237 explicit CheckResult(Reason aReason, 238 MediaResult aResult = MediaResult(NS_OK)) 239 : mReason(aReason), mMediaResult(std::move(aResult)) {} 240 CheckResult(const CheckResult& aOther) = default; 241 CheckResult(CheckResult&& aOther) = default; 242 CheckResult& operator=(const CheckResult& aOther) = default; 243 CheckResult& operator=(CheckResult&& aOther) = default; 244 245 Reason mReason; 246 MediaResult mMediaResult; 247 }; 248 249 template <class Func> 250 void AddToCheckList(Func&& aChecker) { 251 mCheckerList.AppendElement(std::forward<Func>(aChecker)); 252 } 253 254 void AddMediaFormatChecker(const TrackInfo& aTrackConfig) { 255 if (aTrackConfig.IsVideo()) { 256 auto mimeType = aTrackConfig.GetAsVideoInfo()->mMimeType; 257 RefPtr<MediaByteBuffer> extraData = 258 aTrackConfig.GetAsVideoInfo()->mExtraData; 259 AddToCheckList([mimeType, extraData]() { 260 #if defined(XP_WIN) || defined(XP_DARWIN) 261 if (MP4Decoder::IsH264(mimeType)) { 262 SPSData spsdata; 263 // WMF H.264 Video Decoder and Apple ATDecoder 264 // do not support YUV444 format. 265 if (H264::DecodeSPSFromExtraData(extraData, spsdata) && 266 (spsdata.profile_idc == 244 /* Hi444PP */ || 267 spsdata.chroma_format_idc == PDMFactory::kYUV444)) { 268 return CheckResult( 269 SupportChecker::Reason::kVideoFormatNotSupported, 270 MediaResult( 271 NS_ERROR_DOM_MEDIA_FATAL_ERR, 272 RESULT_DETAIL("Decoder may not have the capability " 273 "to handle the requested video format " 274 "with YUV444 chroma subsampling."))); 275 } 276 } 277 #endif 278 return CheckResult(SupportChecker::Reason::kSupported); 279 }); 280 } 281 } 282 283 SupportChecker::CheckResult Check() { 284 for (auto& checker : mCheckerList) { 285 auto result = checker(); 286 if (result.mReason != SupportChecker::Reason::kSupported) { 287 return result; 288 } 289 } 290 return CheckResult(SupportChecker::Reason::kSupported); 291 } 292 293 void Clear() { mCheckerList.Clear(); } 294 295 private: 296 nsTArray<std::function<CheckResult()>> mCheckerList; 297 }; // SupportChecker 298 299 PDMFactory::PDMFactory() { 300 EnsureInit(); 301 CreatePDMs(); 302 CreateNullPDM(); 303 } 304 305 PDMFactory::~PDMFactory() = default; 306 307 /* static */ 308 void PDMFactory::EnsureInit() { 309 if (PDMInitializer::HasInitializedPDMs()) { 310 return; 311 } 312 auto initalizationGfxVarsAndPreferences = []() { 313 MOZ_DIAGNOSTIC_ASSERT(NS_IsMainThread()); 314 // Ensure that all system variables are initialized. 315 gfx::gfxVars::Initialize(); 316 // Prime the preferences system from the main thread. 317 (void)BrowserTabsRemoteAutostart(); 318 }; 319 // There are some initialization needed to be done on the main thread. 320 if (!gfx::gfxVars::IsInitialized()) { 321 if (NS_IsMainThread()) { 322 initalizationGfxVarsAndPreferences(); 323 } else { 324 nsCOMPtr<nsIEventTarget> mainTarget = GetMainThreadSerialEventTarget(); 325 nsCOMPtr<nsIRunnable> runnable = 326 NS_NewRunnableFunction("PDMFactory::EnsureInit", 327 std::move(initalizationGfxVarsAndPreferences)); 328 SyncRunnable::DispatchToThread(mainTarget, runnable); 329 } 330 } 331 PDMInitializer::InitPDMs(); 332 } 333 334 RefPtr<PlatformDecoderModule::CreateDecoderPromise> PDMFactory::CreateDecoder( 335 const CreateDecoderParams& aParams) { 336 if (aParams.mUseNullDecoder.mUse) { 337 MOZ_ASSERT(mNullPDM); 338 return CreateDecoderWithPDM(mNullPDM, aParams); 339 } 340 bool isEncrypted = 341 mEMEPDM && (aParams.mConfig.mCrypto.IsEncrypted() || 342 aParams.mEncryptedCustomIdent == 343 CreateDecoderParams::EncryptedCustomIdent::True); 344 345 if (isEncrypted) { 346 return CreateDecoderWithPDM(mEMEPDM, aParams); 347 } 348 349 return CheckAndMaybeCreateDecoder(CreateDecoderParamsForAsync(aParams), 0); 350 } 351 352 RefPtr<PlatformDecoderModule::CreateDecoderPromise> 353 PDMFactory::CheckAndMaybeCreateDecoder(CreateDecoderParamsForAsync&& aParams, 354 uint32_t aIndex, 355 Maybe<MediaResult> aEarlierError) { 356 uint32_t i = aIndex; 357 auto params = SupportDecoderParams(aParams); 358 for (; i < mCurrentPDMs.Length(); i++) { 359 if (mCurrentPDMs[i]->Supports(params, nullptr /* diagnostic */).isEmpty()) { 360 continue; 361 } 362 RefPtr<PlatformDecoderModule::CreateDecoderPromise> p = 363 CreateDecoderWithPDM(mCurrentPDMs[i], aParams) 364 ->Then( 365 GetCurrentSerialEventTarget(), __func__, 366 [](RefPtr<MediaDataDecoder>&& aDecoder) { 367 return PlatformDecoderModule::CreateDecoderPromise:: 368 CreateAndResolve(std::move(aDecoder), __func__); 369 }, 370 [self = RefPtr{this}, i, params = std::move(aParams)]( 371 const MediaResult& aError) mutable { 372 // Try the next PDM. 373 return self->CheckAndMaybeCreateDecoder(std::move(params), 374 i + 1, Some(aError)); 375 }); 376 return p; 377 } 378 if (aEarlierError) { 379 return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject( 380 std::move(*aEarlierError), __func__); 381 } 382 return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject( 383 MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR, 384 nsPrintfCString("Error no decoder found for %s", 385 aParams.mConfig->mMimeType.get()) 386 .get()), 387 __func__); 388 } 389 390 RefPtr<PlatformDecoderModule::CreateDecoderPromise> 391 PDMFactory::CreateDecoderWithPDM(PlatformDecoderModule* aPDM, 392 const CreateDecoderParams& aParams) { 393 MOZ_ASSERT(aPDM); 394 MediaResult result = NS_OK; 395 396 SupportChecker supportChecker; 397 const TrackInfo& config = aParams.mConfig; 398 supportChecker.AddMediaFormatChecker(config); 399 400 auto checkResult = supportChecker.Check(); 401 if (checkResult.mReason != SupportChecker::Reason::kSupported) { 402 if (checkResult.mReason == 403 SupportChecker::Reason::kVideoFormatNotSupported) { 404 result = checkResult.mMediaResult; 405 } else if (checkResult.mReason == 406 SupportChecker::Reason::kAudioFormatNotSupported) { 407 result = checkResult.mMediaResult; 408 } 409 return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject( 410 result, __func__); 411 } 412 413 if (config.IsAudio()) { 414 if (MP4Decoder::IsAAC(config.mMimeType) && !aParams.mUseNullDecoder.mUse && 415 aParams.mWrappers.contains(media::Wrapper::MediaChangeMonitor)) { 416 // If AudioTrimmer is needed, MediaChangeMonitor will request it. 417 return MediaChangeMonitor::Create(this, aParams); 418 } 419 RefPtr<PlatformDecoderModule::CreateDecoderPromise> p; 420 p = aPDM->AsyncCreateDecoder(aParams)->Then( 421 GetCurrentSerialEventTarget(), __func__, 422 [params = CreateDecoderParamsForAsync(aParams)]( 423 RefPtr<MediaDataDecoder>&& aDecoder) { 424 RefPtr<MediaDataDecoder> decoder = std::move(aDecoder); 425 if (params.mWrappers.contains(media::Wrapper::AudioTrimmer)) { 426 decoder = new AudioTrimmer(decoder.forget()); 427 } 428 return PlatformDecoderModule::CreateDecoderPromise::CreateAndResolve( 429 decoder, __func__); 430 }, 431 [](const MediaResult& aError) { 432 return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject( 433 aError, __func__); 434 }); 435 return p; 436 } 437 438 if (!config.IsVideo()) { 439 return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject( 440 MediaResult( 441 NS_ERROR_DOM_MEDIA_FATAL_ERR, 442 RESULT_DETAIL( 443 "Decoder configuration error, expected audio or video.")), 444 __func__); 445 } 446 447 if ((MP4Decoder::IsH264(config.mMimeType) || 448 #ifdef MOZ_AV1 449 AOMDecoder::IsAV1(config.mMimeType) || 450 #endif 451 VPXDecoder::IsVPX(config.mMimeType) || 452 MP4Decoder::IsHEVC(config.mMimeType)) && 453 !aParams.mUseNullDecoder.mUse && 454 aParams.mWrappers.contains(media::Wrapper::MediaChangeMonitor)) { 455 return MediaChangeMonitor::Create(this, aParams); 456 } 457 return aPDM->AsyncCreateDecoder(aParams); 458 } 459 460 DecodeSupportSet PDMFactory::SupportsMimeType( 461 const nsACString& aMimeType) const { 462 UniquePtr<TrackInfo> trackInfo = CreateTrackInfoWithMIMEType(aMimeType); 463 if (!trackInfo) { 464 return DecodeSupportSet{}; 465 } 466 return Supports(SupportDecoderParams(*trackInfo), nullptr); 467 } 468 469 DecodeSupportSet PDMFactory::Supports( 470 const SupportDecoderParams& aParams, 471 DecoderDoctorDiagnostics* aDiagnostics) const { 472 if (mEMEPDM) { 473 return mEMEPDM->Supports(aParams, aDiagnostics); 474 } 475 476 RefPtr<PlatformDecoderModule> current = 477 GetDecoderModule(aParams, aDiagnostics); 478 479 if (!current) { 480 return DecodeSupportSet{}; 481 } 482 483 // We have a PDM - check for + return SW/HW support info 484 return current->Supports(aParams, aDiagnostics); 485 } 486 487 /* static */ 488 void PDMFactory::ForcePDM(PlatformDecoderModule* aPDM) { 489 auto forced = sForcedPDM.Lock(); 490 *forced = aPDM; 491 } 492 493 void PDMFactory::CreatePDMs() { 494 { 495 auto forced = sForcedPDM.Lock(); 496 if (*forced) { 497 StartupPDM(do_AddRef(*forced)); 498 return; 499 } 500 } 501 if (StaticPrefs::media_use_blank_decoder()) { 502 StartupPDM(BlankDecoderModule::Create()); 503 // The Blank PDM SupportsMimeType reports true for all codecs; the creation 504 // of its decoder is infallible. As such it will be used for all media, we 505 // can stop creating more PDM from this point. 506 return; 507 } 508 509 if (XRE_IsGPUProcess()) { 510 CreateGpuPDMs(); 511 } else if (XRE_IsRDDProcess()) { 512 CreateRddPDMs(); 513 } else if (XRE_IsUtilityProcess()) { 514 CreateUtilityPDMs(); 515 } else if (XRE_IsContentProcess()) { 516 CreateContentPDMs(); 517 } else { 518 MOZ_DIAGNOSTIC_ASSERT( 519 XRE_IsParentProcess(), 520 "PDMFactory is only usable in the Parent/GPU/RDD/Content process"); 521 CreateDefaultPDMs(); 522 } 523 } 524 525 void PDMFactory::CreateGpuPDMs() { 526 #ifdef XP_WIN 527 if (StaticPrefs::media_ffvpx_hw_enabled()) { 528 StartupPDM(FFVPXRuntimeLinker::CreateDecoder()); 529 } 530 if (StaticPrefs::media_wmf_enabled()) { 531 StartupPDM(WMFDecoderModule::Create()); 532 } 533 #endif 534 } 535 536 #if defined(MOZ_FFMPEG) 537 static DecoderDoctorDiagnostics::Flags GetFailureFlagBasedOnFFmpegStatus( 538 const FFmpegRuntimeLinker::LinkStatus& aStatus) { 539 switch (aStatus) { 540 case FFmpegRuntimeLinker::LinkStatus_INVALID_FFMPEG_CANDIDATE: 541 case FFmpegRuntimeLinker::LinkStatus_UNUSABLE_LIBAV57: 542 case FFmpegRuntimeLinker::LinkStatus_INVALID_LIBAV_CANDIDATE: 543 case FFmpegRuntimeLinker::LinkStatus_OBSOLETE_FFMPEG: 544 case FFmpegRuntimeLinker::LinkStatus_OBSOLETE_LIBAV: 545 case FFmpegRuntimeLinker::LinkStatus_INVALID_CANDIDATE: 546 return DecoderDoctorDiagnostics::Flags::LibAVCodecUnsupported; 547 default: 548 MOZ_DIAGNOSTIC_ASSERT( 549 aStatus == FFmpegRuntimeLinker::LinkStatus_NOT_FOUND, 550 "Only call this method when linker fails."); 551 return DecoderDoctorDiagnostics::Flags::FFmpegNotFound; 552 } 553 } 554 #endif 555 556 void PDMFactory::CreateRddPDMs() { 557 #ifdef XP_WIN 558 if (StaticPrefs::media_wmf_enabled() && 559 StaticPrefs::media_rdd_wmf_enabled()) { 560 StartupPDM(WMFDecoderModule::Create()); 561 } 562 #endif 563 #ifdef MOZ_APPLEMEDIA 564 if (StaticPrefs::media_rdd_applemedia_enabled()) { 565 StartupPDM(AppleDecoderModule::Create()); 566 } 567 #endif 568 StartupPDM(FFVPXRuntimeLinker::CreateDecoder()); 569 #ifdef MOZ_FFMPEG 570 if (StaticPrefs::media_ffmpeg_enabled() && 571 StaticPrefs::media_rdd_ffmpeg_enabled() && 572 !StartupPDM(FFmpegRuntimeLinker::CreateDecoder())) { 573 mFailureFlags += GetFailureFlagBasedOnFFmpegStatus( 574 FFmpegRuntimeLinker::LinkStatusCode()); 575 } 576 #endif 577 StartupPDM(AgnosticDecoderModule::Create(), 578 StaticPrefs::media_prefer_non_ffvpx()); 579 580 PDM_INIT_LOG("RDD PDM order:"); 581 int i = 0; 582 for (const auto& pdm : mCurrentPDMs) { 583 PDM_INIT_LOG("%d: %s", i++, pdm->Name()); 584 } 585 } 586 587 void PDMFactory::CreateUtilityPDMs() { 588 const ipc::SandboxingKind aKind = GetCurrentSandboxingKind(); 589 #ifdef XP_WIN 590 if (StaticPrefs::media_wmf_enabled() && 591 aKind == ipc::SandboxingKind::UTILITY_AUDIO_DECODING_WMF) { 592 StartupPDM(WMFDecoderModule::Create()); 593 } 594 #endif 595 #ifdef MOZ_APPLEMEDIA 596 if (aKind == ipc::SandboxingKind::UTILITY_AUDIO_DECODING_APPLE_MEDIA) { 597 StartupPDM(AppleDecoderModule::Create()); 598 } 599 #endif 600 if (aKind == ipc::SandboxingKind::GENERIC_UTILITY) { 601 StartupPDM(FFVPXRuntimeLinker::CreateDecoder()); 602 #ifdef MOZ_FFMPEG 603 if (StaticPrefs::media_ffmpeg_enabled() && 604 !StartupPDM(FFmpegRuntimeLinker::CreateDecoder())) { 605 mFailureFlags += GetFailureFlagBasedOnFFmpegStatus( 606 FFmpegRuntimeLinker::LinkStatusCode()); 607 } 608 #endif 609 #ifdef MOZ_WIDGET_ANDROID 610 if (StaticPrefs::media_utility_android_media_codec_enabled()) { 611 StartupPDM(AndroidDecoderModule::Create(), 612 StaticPrefs::media_android_media_codec_preferred()); 613 } 614 #endif 615 StartupPDM(AgnosticDecoderModule::Create(), 616 StaticPrefs::media_prefer_non_ffvpx()); 617 } 618 #ifdef MOZ_WMF_MEDIA_ENGINE 619 if (aKind == ipc::SandboxingKind::MF_MEDIA_ENGINE_CDM) { 620 if (StaticPrefs::media_wmf_media_engine_enabled()) { 621 StartupPDM(MFMediaEngineDecoderModule::Create()); 622 } 623 } 624 #endif 625 626 PDM_INIT_LOG("Utility PDM order:"); 627 int i = 0; 628 for (const auto& pdm : mCurrentPDMs) { 629 PDM_INIT_LOG("%d: %s", i++, pdm->Name()); 630 } 631 } 632 633 void PDMFactory::CreateContentPDMs() { 634 if (StaticPrefs::media_gpu_process_decoder()) { 635 StartupPDM(RemoteDecoderModule::Create(RemoteMediaIn::GpuProcess)); 636 } 637 638 if (StaticPrefs::media_rdd_process_enabled()) { 639 StartupPDM(RemoteDecoderModule::Create(RemoteMediaIn::RddProcess)); 640 } 641 642 if (StaticPrefs::media_utility_process_enabled()) { 643 #ifdef MOZ_APPLEMEDIA 644 StartupPDM( 645 RemoteDecoderModule::Create(RemoteMediaIn::UtilityProcess_AppleMedia)); 646 #endif 647 #ifdef XP_WIN 648 StartupPDM(RemoteDecoderModule::Create(RemoteMediaIn::UtilityProcess_WMF)); 649 #endif 650 // WMF and AppleMedia should be created before Generic because the order 651 // affects what decoder module would be chose first. 652 StartupPDM( 653 RemoteDecoderModule::Create(RemoteMediaIn::UtilityProcess_Generic)); 654 } 655 #ifdef MOZ_WMF_MEDIA_ENGINE 656 if (StaticPrefs::media_wmf_media_engine_enabled()) { 657 StartupPDM(RemoteDecoderModule::Create( 658 RemoteMediaIn::UtilityProcess_MFMediaEngineCDM)); 659 } 660 #endif 661 662 #if !defined(MOZ_WIDGET_ANDROID) // Still required for video? 663 if (StaticPrefs::media_allow_audio_non_utility()) { 664 #endif // !defined(MOZ_WIDGET_ANDROID) 665 #ifdef XP_WIN 666 if (StaticPrefs::media_wmf_enabled()) { 667 # ifdef MOZ_WMF 668 if (!StaticPrefs::media_rdd_process_enabled() || 669 !StaticPrefs::media_rdd_wmf_enabled()) { 670 if (!StartupPDM(WMFDecoderModule::Create())) { 671 mFailureFlags += DecoderDoctorDiagnostics::Flags::WMFFailedToLoad; 672 } 673 } 674 # endif 675 } else if (StaticPrefs::media_decoder_doctor_wmf_disabled_is_failure()) { 676 mFailureFlags += DecoderDoctorDiagnostics::Flags::WMFFailedToLoad; 677 } 678 #endif 679 680 #ifdef MOZ_APPLEMEDIA 681 StartupPDM(AppleDecoderModule::Create()); 682 #endif 683 #ifdef MOZ_OMX 684 if (StaticPrefs::media_omx_enabled()) { 685 StartupPDM(OmxDecoderModule::Create()); 686 } 687 #endif 688 StartupPDM(FFVPXRuntimeLinker::CreateDecoder()); 689 #ifdef MOZ_FFMPEG 690 if (StaticPrefs::media_ffmpeg_enabled() && 691 !StartupPDM(FFmpegRuntimeLinker::CreateDecoder())) { 692 mFailureFlags += GetFailureFlagBasedOnFFmpegStatus( 693 FFmpegRuntimeLinker::LinkStatusCode()); 694 } 695 #endif 696 697 StartupPDM(AgnosticDecoderModule::Create(), 698 StaticPrefs::media_prefer_non_ffvpx()); 699 #if !defined(MOZ_WIDGET_ANDROID) // Still required for video? 700 } 701 #endif // !defined(MOZ_WIDGET_ANDROID) 702 703 // Android still needs this, the actual decoder is remoted on java side 704 #ifdef MOZ_WIDGET_ANDROID 705 if (AndroidDecoderModule::IsJavaDecoderModuleAllowed()) { 706 StartupPDM(AndroidDecoderModule::Create(), 707 StaticPrefs::media_android_media_codec_preferred()); 708 } 709 #endif 710 711 if (StaticPrefs::media_gmp_decoder_enabled() && 712 !StartupPDM(GMPDecoderModule::Create(), 713 StaticPrefs::media_gmp_decoder_preferred())) { 714 mFailureFlags += DecoderDoctorDiagnostics::Flags::GMPPDMFailedToStartup; 715 } 716 PDM_INIT_LOG("Content PDM order:"); 717 int i = 0; 718 for (const auto& pdm : mCurrentPDMs) { 719 PDM_INIT_LOG("%d: %s", i++, pdm->Name()); 720 } 721 } 722 723 void PDMFactory::CreateDefaultPDMs() { 724 #ifdef XP_WIN 725 if (StaticPrefs::media_wmf_enabled()) { 726 if (!StartupPDM(WMFDecoderModule::Create())) { 727 mFailureFlags += DecoderDoctorDiagnostics::Flags::WMFFailedToLoad; 728 } 729 } else if (StaticPrefs::media_decoder_doctor_wmf_disabled_is_failure()) { 730 mFailureFlags += DecoderDoctorDiagnostics::Flags::WMFFailedToLoad; 731 } 732 #endif 733 734 #ifdef MOZ_APPLEMEDIA 735 StartupPDM(AppleDecoderModule::Create()); 736 #endif 737 #ifdef MOZ_OMX 738 if (StaticPrefs::media_omx_enabled()) { 739 StartupPDM(OmxDecoderModule::Create()); 740 } 741 #endif 742 StartupPDM(FFVPXRuntimeLinker::CreateDecoder()); 743 #ifdef MOZ_FFMPEG 744 if (StaticPrefs::media_ffmpeg_enabled() && 745 !StartupPDM(FFmpegRuntimeLinker::CreateDecoder())) { 746 mFailureFlags += GetFailureFlagBasedOnFFmpegStatus( 747 FFmpegRuntimeLinker::LinkStatusCode()); 748 } 749 #endif 750 #ifdef MOZ_WIDGET_ANDROID 751 if (AndroidDecoderModule::IsJavaDecoderModuleAllowed()) { 752 StartupPDM(AndroidDecoderModule::Create(), 753 StaticPrefs::media_android_media_codec_preferred()); 754 } 755 #endif 756 757 StartupPDM(AgnosticDecoderModule::Create(), 758 StaticPrefs::media_prefer_non_ffvpx()); 759 760 if (StaticPrefs::media_gmp_decoder_enabled() && 761 !StartupPDM(GMPDecoderModule::Create(), 762 StaticPrefs::media_gmp_decoder_preferred())) { 763 mFailureFlags += DecoderDoctorDiagnostics::Flags::GMPPDMFailedToStartup; 764 } 765 766 PDM_INIT_LOG("Default PDM order:"); 767 int i = 0; 768 for (const auto& pdm : mCurrentPDMs) { 769 PDM_INIT_LOG("%d: %s", i++, pdm->Name()); 770 } 771 } 772 773 void PDMFactory::CreateNullPDM() { 774 mNullPDM = CreateNullDecoderModule(); 775 MOZ_ASSERT(mNullPDM && NS_SUCCEEDED(mNullPDM->Startup())); 776 } 777 778 bool PDMFactory::StartupPDM(already_AddRefed<PlatformDecoderModule> aPDM, 779 bool aInsertAtBeginning) { 780 RefPtr<PlatformDecoderModule> pdm = aPDM; 781 if (pdm && NS_SUCCEEDED(pdm->Startup())) { 782 if (aInsertAtBeginning) { 783 mCurrentPDMs.InsertElementAt(0, pdm); 784 } else { 785 mCurrentPDMs.AppendElement(pdm); 786 } 787 return true; 788 } 789 return false; 790 } 791 792 already_AddRefed<PlatformDecoderModule> PDMFactory::GetDecoderModule( 793 const SupportDecoderParams& aParams, 794 DecoderDoctorDiagnostics* aDiagnostics) const { 795 if (aDiagnostics) { 796 // If libraries failed to load, the following loop over mCurrentPDMs 797 // will not even try to use them. So we record failures now. 798 aDiagnostics->SetFailureFlags(mFailureFlags); 799 } 800 801 RefPtr<PlatformDecoderModule> pdm; 802 for (const auto& current : mCurrentPDMs) { 803 if (!current->Supports(aParams, aDiagnostics).isEmpty()) { 804 pdm = current; 805 break; 806 } 807 } 808 return pdm.forget(); 809 } 810 811 void PDMFactory::SetCDMProxy(CDMProxy* aProxy) { 812 MOZ_ASSERT(aProxy); 813 814 #ifdef MOZ_WIDGET_ANDROID 815 if (IsWidevineKeySystem(aProxy->KeySystem()) && 816 AndroidDecoderModule::IsJavaDecoderModuleAllowed()) { 817 mEMEPDM = AndroidDecoderModule::Create(aProxy); 818 return; 819 } 820 #endif 821 #ifdef MOZ_WMF_CDM 822 if (IsPlayReadyKeySystemAndSupported(aProxy->KeySystem()) || 823 IsWidevineExperimentKeySystemAndSupported(aProxy->KeySystem()) || 824 (IsWidevineKeySystem(aProxy->KeySystem()) && 825 aProxy->IsHardwareDecryptionSupported()) || 826 IsWMFClearKeySystemAndSupported(aProxy->KeySystem())) { 827 mEMEPDM = RemoteDecoderModule::Create( 828 RemoteMediaIn::UtilityProcess_MFMediaEngineCDM); 829 return; 830 } 831 #endif 832 auto m = MakeRefPtr<PDMFactory>(); 833 mEMEPDM = MakeRefPtr<EMEDecoderModule>(aProxy, m); 834 } 835 836 StaticMutex PDMFactory::sSupportedMutex; 837 838 /* static */ 839 media::MediaCodecsSupported PDMFactory::Supported(bool aForceRefresh) { 840 StaticMutexAutoLock lock(sSupportedMutex); 841 842 static auto calculate = []() { 843 auto pdm = MakeRefPtr<PDMFactory>(); 844 MediaCodecsSupported supported; 845 // H264 and AAC depends on external framework that must be dynamically 846 // loaded. 847 // We currently only ship a single PDM per platform able to decode AAC or 848 // H264. As such we can assert that being able to create a H264 or AAC 849 // decoder indicates that with WMF on Windows or FFmpeg on Unixes is 850 // available. 851 // This logic will have to be revisited if a PDM supporting either codec 852 // will be added in addition to the WMF and FFmpeg PDM (such as OpenH264) 853 for (const auto& cd : MCSInfo::GetAllCodecDefinitions()) { 854 supported += MCSInfo::GetDecodeMediaCodecsSupported( 855 cd.codec, pdm->SupportsMimeType(nsCString(cd.mimeTypeString))); 856 } 857 #ifdef MOZ_WIDGET_ANDROID 858 if (AndroidDecoderModule::IsJavaDecoderModuleAllowed()) { 859 supported += AndroidDecoderModule::GetSupportedCodecs(); 860 } 861 #endif 862 return supported; 863 }; 864 865 static MediaCodecsSupported supported = calculate(); 866 if (aForceRefresh) { 867 supported = calculate(); 868 } 869 870 return supported; 871 } 872 873 /* static */ 874 DecodeSupportSet PDMFactory::SupportsMimeType( 875 const nsACString& aMimeType, const MediaCodecsSupported& aSupported, 876 RemoteMediaIn aLocation) { 877 const TrackSupportSet supports = 878 RemoteMediaManagerChild::GetTrackSupport(aLocation); 879 880 if (supports.contains(TrackSupport::DecodeVideo)) { 881 if (MP4Decoder::IsH264(aMimeType)) { 882 return MCSInfo::GetDecodeSupportSet(MediaCodec::H264, aSupported); 883 } 884 if (VPXDecoder::IsVP9(aMimeType)) { 885 return MCSInfo::GetDecodeSupportSet(MediaCodec::VP9, aSupported); 886 } 887 if (VPXDecoder::IsVP8(aMimeType)) { 888 return MCSInfo::GetDecodeSupportSet(MediaCodec::VP8, aSupported); 889 } 890 #ifdef MOZ_AV1 891 if (AOMDecoder::IsAV1(aMimeType)) { 892 return MCSInfo::GetDecodeSupportSet(MediaCodec::AV1, aSupported); 893 } 894 #endif 895 if (MP4Decoder::IsHEVC(aMimeType)) { 896 return MCSInfo::GetDecodeSupportSet(MediaCodec::HEVC, aSupported); 897 } 898 } 899 900 if (supports.contains(TrackSupport::DecodeAudio)) { 901 if (MP4Decoder::IsAAC(aMimeType)) { 902 return MCSInfo::GetDecodeSupportSet(MediaCodec::AAC, aSupported); 903 } 904 if (aMimeType.EqualsLiteral("audio/mpeg")) { 905 return MCSInfo::GetDecodeSupportSet(MediaCodec::MP3, aSupported); 906 } 907 if (aMimeType.EqualsLiteral("audio/opus")) { 908 return MCSInfo::GetDecodeSupportSet(MediaCodec::Opus, aSupported); 909 } 910 if (aMimeType.EqualsLiteral("audio/vorbis")) { 911 return MCSInfo::GetDecodeSupportSet(MediaCodec::Vorbis, aSupported); 912 } 913 if (aMimeType.EqualsLiteral("audio/flac")) { 914 return MCSInfo::GetDecodeSupportSet(MediaCodec::FLAC, aSupported); 915 } 916 if (IsWaveMimetype(aMimeType)) { 917 return MCSInfo::GetDecodeSupportSet(MediaCodec::Wave, aSupported); 918 } 919 } 920 return DecodeSupportSet{}; 921 } 922 923 /* static */ 924 bool PDMFactory::AllDecodersAreRemote() { 925 return StaticPrefs::media_rdd_process_enabled() && 926 StaticPrefs::media_rdd_opus_enabled() && 927 StaticPrefs::media_rdd_vorbis_enabled() && 928 StaticPrefs::media_rdd_vpx_enabled() && 929 #if defined(MOZ_WMF) 930 StaticPrefs::media_rdd_wmf_enabled() && 931 #endif 932 StaticPrefs::media_rdd_wav_enabled(); 933 } 934 935 #undef PDM_INIT_LOG 936 } // namespace mozilla