tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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