summaryrefslogtreecommitdiffstats
path: root/dom/media/platforms/wmf/MFMediaEngineDecoderModule.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dom/media/platforms/wmf/MFMediaEngineDecoderModule.cpp')
-rw-r--r--dom/media/platforms/wmf/MFMediaEngineDecoderModule.cpp174
1 files changed, 174 insertions, 0 deletions
diff --git a/dom/media/platforms/wmf/MFMediaEngineDecoderModule.cpp b/dom/media/platforms/wmf/MFMediaEngineDecoderModule.cpp
new file mode 100644
index 0000000000..13be162af5
--- /dev/null
+++ b/dom/media/platforms/wmf/MFMediaEngineDecoderModule.cpp
@@ -0,0 +1,174 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "MFMediaEngineDecoderModule.h"
+
+#include "MFTDecoder.h"
+#include "VideoUtils.h"
+#include "mozilla/MFMediaEngineParent.h"
+#include "mozilla/MFMediaEngineUtils.h"
+#include "mozilla/StaticPrefs_media.h"
+#include "mozilla/WindowsVersion.h"
+#include "mozilla/mscom/EnsureMTA.h"
+
+namespace mozilla {
+
+#define LOG(msg, ...) \
+ MOZ_LOG(gMFMediaEngineLog, LogLevel::Debug, (msg, ##__VA_ARGS__))
+
+/* static */
+void MFMediaEngineDecoderModule::Init() {
+ // TODO : Init any thing that media engine would need. Implement this when we
+ // start implementing media engine in following patches.
+}
+
+/* static */
+already_AddRefed<PlatformDecoderModule> MFMediaEngineDecoderModule::Create() {
+ RefPtr<MFMediaEngineDecoderModule> module = new MFMediaEngineDecoderModule();
+ return module.forget();
+}
+
+/* static */
+bool MFMediaEngineDecoderModule::SupportsConfig(const TrackInfo& aConfig) {
+ RefPtr<MFMediaEngineDecoderModule> module = new MFMediaEngineDecoderModule();
+ return module->SupportInternal(SupportDecoderParams(aConfig), nullptr) !=
+ media::DecodeSupport::Unsupported;
+}
+
+already_AddRefed<MediaDataDecoder>
+MFMediaEngineDecoderModule::CreateVideoDecoder(
+ const CreateDecoderParams& aParams) {
+ if (!aParams.mMediaEngineId ||
+ !StaticPrefs::media_wmf_media_engine_enabled()) {
+ return nullptr;
+ }
+ RefPtr<MFMediaEngineParent> mediaEngine =
+ MFMediaEngineParent::GetMediaEngineById(*aParams.mMediaEngineId);
+ if (!mediaEngine) {
+ LOG("Can't find media engine %" PRIu64 " for video decoder",
+ *aParams.mMediaEngineId);
+ return nullptr;
+ }
+ LOG("MFMediaEngineDecoderModule, CreateVideoDecoder");
+ RefPtr<MediaDataDecoder> decoder = mediaEngine->GetMediaEngineStream(
+ TrackInfo::TrackType::kVideoTrack, aParams);
+ return decoder.forget();
+}
+
+already_AddRefed<MediaDataDecoder>
+MFMediaEngineDecoderModule::CreateAudioDecoder(
+ const CreateDecoderParams& aParams) {
+ if (!aParams.mMediaEngineId ||
+ !StaticPrefs::media_wmf_media_engine_enabled()) {
+ return nullptr;
+ }
+ RefPtr<MFMediaEngineParent> mediaEngine =
+ MFMediaEngineParent::GetMediaEngineById(*aParams.mMediaEngineId);
+ if (!mediaEngine) {
+ LOG("Can't find media engine %" PRIu64 " for audio decoder",
+ *aParams.mMediaEngineId);
+ return nullptr;
+ }
+ LOG("MFMediaEngineDecoderModule, CreateAudioDecoder");
+ RefPtr<MediaDataDecoder> decoder = mediaEngine->GetMediaEngineStream(
+ TrackInfo::TrackType::kAudioTrack, aParams);
+ return decoder.forget();
+}
+
+media::DecodeSupportSet MFMediaEngineDecoderModule::SupportsMimeType(
+ const nsACString& aMimeType, DecoderDoctorDiagnostics* aDiagnostics) const {
+ UniquePtr<TrackInfo> trackInfo = CreateTrackInfoWithMIMEType(aMimeType);
+ if (!trackInfo) {
+ return media::DecodeSupport::Unsupported;
+ }
+ return SupportInternal(SupportDecoderParams(*trackInfo), aDiagnostics);
+}
+
+media::DecodeSupportSet MFMediaEngineDecoderModule::Supports(
+ const SupportDecoderParams& aParams,
+ DecoderDoctorDiagnostics* aDiagnostics) const {
+ if (!aParams.mMediaEngineId) {
+ return media::DecodeSupport::Unsupported;
+ }
+ return SupportInternal(aParams, aDiagnostics);
+}
+
+media::DecodeSupportSet MFMediaEngineDecoderModule::SupportInternal(
+ const SupportDecoderParams& aParams,
+ DecoderDoctorDiagnostics* aDiagnostics) const {
+ if (!StaticPrefs::media_wmf_media_engine_enabled()) {
+ return media::DecodeSupport::Unsupported;
+ }
+ bool supports = false;
+ WMFStreamType type = GetStreamTypeFromMimeType(aParams.MimeType());
+ if (type != WMFStreamType::Unknown) {
+ supports = CanCreateMFTDecoder(type);
+ }
+ MOZ_LOG(sPDMLog, LogLevel::Debug,
+ ("MFMediaEngine decoder %s requested type '%s'",
+ supports ? "supports" : "rejects", aParams.MimeType().get()));
+ return supports ? media::DecodeSupport::SoftwareDecode
+ : media::DecodeSupport::Unsupported;
+}
+
+static bool CreateMFTDecoderOnMTA(const WMFStreamType& aType) {
+ RefPtr<MFTDecoder> decoder = new MFTDecoder();
+ static std::unordered_map<WMFStreamType, bool> sResults;
+ if (auto rv = sResults.find(aType); rv != sResults.end()) {
+ return rv->second;
+ }
+
+ bool result = false;
+ switch (aType) {
+ case WMFStreamType::MP3:
+ result = SUCCEEDED(decoder->Create(CLSID_CMP3DecMediaObject));
+ break;
+ case WMFStreamType::AAC:
+ result = SUCCEEDED(decoder->Create(CLSID_CMSAACDecMFT));
+ break;
+ // Opus and vorbis are supported via extension.
+ // https://www.microsoft.com/en-us/p/web-media-extensions/9n5tdp8vcmhs
+ case WMFStreamType::OPUS:
+ result = SUCCEEDED(decoder->Create(CLSID_MSOpusDecoder));
+ break;
+ case WMFStreamType::VORBIS:
+ result = SUCCEEDED(decoder->Create(
+ MFT_CATEGORY_AUDIO_DECODER, MFAudioFormat_Vorbis, MFAudioFormat_PCM));
+ break;
+ case WMFStreamType::H264:
+ result = SUCCEEDED(decoder->Create(CLSID_CMSH264DecoderMFT));
+ break;
+ case WMFStreamType::VP8:
+ case WMFStreamType::VP9: {
+ static const uint32_t VPX_USABLE_BUILD = 16287;
+ if (IsWindowsBuildOrLater(VPX_USABLE_BUILD)) {
+ result = SUCCEEDED(decoder->Create(CLSID_CMSVPXDecMFT));
+ }
+ break;
+ }
+#ifdef MOZ_AV1
+ case WMFStreamType::AV1:
+ result = SUCCEEDED(decoder->Create(MFT_CATEGORY_VIDEO_DECODER,
+ MFVideoFormat_AV1, GUID_NULL));
+ break;
+#endif
+ default:
+ MOZ_ASSERT_UNREACHABLE("Unexpected type");
+ }
+ sResults.insert({aType, result});
+ return result;
+}
+
+bool MFMediaEngineDecoderModule::CanCreateMFTDecoder(
+ const WMFStreamType& aType) const {
+ // TODO : caching the result to prevent performing on MTA thread everytime.
+ bool canCreateDecoder = false;
+ mozilla::mscom::EnsureMTA(
+ [&]() { canCreateDecoder = CreateMFTDecoderOnMTA(aType); });
+ return canCreateDecoder;
+}
+
+#undef LOG
+
+} // namespace mozilla