tor-browser

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

MFMediaEngineDecoderModule.cpp (6676B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 #include "MFMediaEngineDecoderModule.h"
      6 
      7 #include "MFTDecoder.h"
      8 #include "VideoUtils.h"
      9 #include "mozilla/MFMediaEngineParent.h"
     10 #include "mozilla/MFMediaEngineUtils.h"
     11 #include "mozilla/RemoteDecoderModule.h"
     12 #include "mozilla/RemoteMediaManagerChild.h"
     13 #include "mozilla/StaticPrefs_media.h"
     14 #include "mozilla/WindowsVersion.h"
     15 #include "mozilla/gfx/gfxVars.h"
     16 #include "mozilla/mscom/EnsureMTA.h"
     17 
     18 namespace mozilla {
     19 
     20 #define LOG(msg, ...) \
     21  MOZ_LOG(gMFMediaEngineLog, LogLevel::Debug, (msg, ##__VA_ARGS__))
     22 
     23 /* static */
     24 void MFMediaEngineDecoderModule::Init() {
     25  // TODO : Init any thing that media engine would need. Implement this when we
     26  // start implementing media engine in following patches.
     27 }
     28 
     29 /* static */
     30 already_AddRefed<PlatformDecoderModule> MFMediaEngineDecoderModule::Create() {
     31  RefPtr<MFMediaEngineDecoderModule> module = new MFMediaEngineDecoderModule();
     32  return module.forget();
     33 }
     34 
     35 /* static */
     36 bool MFMediaEngineDecoderModule::SupportsConfig(const TrackInfo& aConfig) {
     37  RefPtr<PlatformDecoderModule> module = RemoteDecoderModule::Create(
     38      RemoteMediaIn::UtilityProcess_MFMediaEngineCDM);
     39  return !module->Supports(SupportDecoderParams(aConfig), nullptr).isEmpty();
     40 }
     41 
     42 already_AddRefed<MediaDataDecoder>
     43 MFMediaEngineDecoderModule::CreateVideoDecoder(
     44    const CreateDecoderParams& aParams) {
     45  if (!aParams.mMediaEngineId ||
     46      !StaticPrefs::media_wmf_media_engine_enabled()) {
     47    return nullptr;
     48  }
     49  RefPtr<MFMediaEngineParent> mediaEngine =
     50      MFMediaEngineParent::GetMediaEngineById(*aParams.mMediaEngineId);
     51  if (!mediaEngine) {
     52    LOG("Can't find media engine %" PRIu64 " for video decoder",
     53        *aParams.mMediaEngineId);
     54    return nullptr;
     55  }
     56  LOG("MFMediaEngineDecoderModule, CreateVideoDecoder");
     57  RefPtr<MediaDataDecoder> decoder = mediaEngine->GetMediaEngineStream(
     58      TrackInfo::TrackType::kVideoTrack, aParams);
     59  return decoder.forget();
     60 }
     61 
     62 already_AddRefed<MediaDataDecoder>
     63 MFMediaEngineDecoderModule::CreateAudioDecoder(
     64    const CreateDecoderParams& aParams) {
     65  if (!aParams.mMediaEngineId ||
     66      !StaticPrefs::media_wmf_media_engine_enabled()) {
     67    return nullptr;
     68  }
     69  RefPtr<MFMediaEngineParent> mediaEngine =
     70      MFMediaEngineParent::GetMediaEngineById(*aParams.mMediaEngineId);
     71  if (!mediaEngine) {
     72    LOG("Can't find media engine %" PRIu64 " for audio decoder",
     73        *aParams.mMediaEngineId);
     74    return nullptr;
     75  }
     76  LOG("MFMediaEngineDecoderModule, CreateAudioDecoder");
     77  RefPtr<MediaDataDecoder> decoder = mediaEngine->GetMediaEngineStream(
     78      TrackInfo::TrackType::kAudioTrack, aParams);
     79  return decoder.forget();
     80 }
     81 
     82 media::DecodeSupportSet MFMediaEngineDecoderModule::SupportsMimeType(
     83    const nsACString& aMimeType, DecoderDoctorDiagnostics* aDiagnostics) const {
     84  UniquePtr<TrackInfo> trackInfo = CreateTrackInfoWithMIMEType(aMimeType);
     85  if (!trackInfo) {
     86    return media::DecodeSupportSet{};
     87  }
     88  return SupportInternal(SupportDecoderParams(*trackInfo), aDiagnostics);
     89 }
     90 
     91 media::DecodeSupportSet MFMediaEngineDecoderModule::Supports(
     92    const SupportDecoderParams& aParams,
     93    DecoderDoctorDiagnostics* aDiagnostics) const {
     94  return SupportInternal(aParams, aDiagnostics);
     95 }
     96 
     97 media::DecodeSupportSet MFMediaEngineDecoderModule::SupportInternal(
     98    const SupportDecoderParams& aParams,
     99    DecoderDoctorDiagnostics* aDiagnostics) const {
    100  if (!StaticPrefs::media_wmf_media_engine_enabled()) {
    101    return media::DecodeSupportSet{};
    102  }
    103  // Only support hardware decoding.
    104  if (!gfx::gfxVars::CanUseHardwareVideoDecoding() &&
    105      !StaticPrefs::media_wmf_media_engine_bypass_gfx_blocklist()) {
    106    return media::DecodeSupportSet{};
    107  }
    108  bool supports = false;
    109  WMFStreamType type = GetStreamTypeFromMimeType(aParams.MimeType());
    110  if (type != WMFStreamType::Unknown) {
    111    supports = CanCreateMFTDecoder(type);
    112  }
    113  MOZ_LOG(sPDMLog, LogLevel::Debug,
    114          ("MFMediaEngine decoder %s requested type '%s'",
    115           supports ? "supports" : "rejects", aParams.MimeType().get()));
    116  if (!supports) {
    117    return media::DecodeSupportSet{};
    118  }
    119  return StreamTypeIsVideo(type) ? media::DecodeSupport::HardwareDecode
    120                                 : media::DecodeSupport::SoftwareDecode;
    121 }
    122 
    123 static bool CreateMFTDecoderOnMTA(const WMFStreamType& aType) {
    124  RefPtr<MFTDecoder> decoder = new MFTDecoder();
    125  static std::unordered_map<WMFStreamType, bool> sResults;
    126  if (auto rv = sResults.find(aType); rv != sResults.end()) {
    127    return rv->second;
    128  }
    129 
    130  bool result = false;
    131  switch (aType) {
    132    case WMFStreamType::MP3:
    133      result = SUCCEEDED(decoder->Create(CLSID_CMP3DecMediaObject));
    134      break;
    135    case WMFStreamType::AAC:
    136      result = SUCCEEDED(decoder->Create(CLSID_CMSAACDecMFT));
    137      break;
    138    // Opus and vorbis are supported via extension.
    139    // https://www.microsoft.com/en-us/p/web-media-extensions/9n5tdp8vcmhs
    140    case WMFStreamType::OPUS:
    141      result = SUCCEEDED(decoder->Create(CLSID_MSOpusDecoder));
    142      break;
    143    case WMFStreamType::VORBIS:
    144      result = SUCCEEDED(decoder->Create(
    145          MFT_CATEGORY_AUDIO_DECODER, MFAudioFormat_Vorbis, MFAudioFormat_PCM));
    146      break;
    147    case WMFStreamType::H264:
    148      result = SUCCEEDED(decoder->Create(CLSID_CMSH264DecoderMFT));
    149      break;
    150    case WMFStreamType::VP8:
    151    case WMFStreamType::VP9: {
    152      static const uint32_t VPX_USABLE_BUILD = 16287;
    153      if (IsWindows10BuildOrLater(VPX_USABLE_BUILD)) {
    154        result = SUCCEEDED(decoder->Create(CLSID_CMSVPXDecMFT));
    155      }
    156      break;
    157    }
    158 #ifdef MOZ_AV1
    159    case WMFStreamType::AV1:
    160      result = SUCCEEDED(decoder->Create(MFT_CATEGORY_VIDEO_DECODER,
    161                                         MFVideoFormat_AV1, GUID_NULL));
    162      break;
    163 #endif
    164    case WMFStreamType::HEVC:
    165      if (StaticPrefs::media_hevc_enabled()) {
    166        result =
    167            SUCCEEDED(decoder->Create(MFT_CATEGORY_VIDEO_DECODER,
    168                                      MFVideoFormat_HEVC, MFVideoFormat_NV12));
    169      }
    170      break;
    171    default:
    172      MOZ_ASSERT_UNREACHABLE("Unexpected type");
    173  }
    174  sResults.insert({aType, result});
    175  return result;
    176 }
    177 
    178 bool MFMediaEngineDecoderModule::CanCreateMFTDecoder(
    179    const WMFStreamType& aType) const {
    180  // TODO : caching the result to prevent performing on MTA thread everytime.
    181  bool canCreateDecoder = false;
    182  mozilla::mscom::EnsureMTA(
    183      [&]() { canCreateDecoder = CreateMFTDecoderOnMTA(aType); });
    184  return canCreateDecoder;
    185 }
    186 
    187 #undef LOG
    188 
    189 }  // namespace mozilla