summaryrefslogtreecommitdiffstats
path: root/dom/media
diff options
context:
space:
mode:
Diffstat (limited to 'dom/media')
-rw-r--r--dom/media/AudioConverter.cpp103
-rw-r--r--dom/media/MediaPrefs.h1
-rw-r--r--dom/media/eme/CDMProxy.h4
-rw-r--r--dom/media/eme/MediaKeys.cpp2
-rw-r--r--dom/media/eme/MediaKeys.h2
-rw-r--r--dom/media/eme/mediadrm/MediaDrmCDMProxy.cpp2
-rw-r--r--dom/media/eme/mediadrm/MediaDrmCDMProxy.h3
-rw-r--r--dom/media/gmp/ChromiumCDMParent.cpp5
-rw-r--r--dom/media/gmp/ChromiumCDMParent.h3
-rw-r--r--dom/media/gmp/ChromiumCDMProxy.cpp72
-rw-r--r--dom/media/gmp/ChromiumCDMProxy.h9
-rw-r--r--dom/media/ipc/VideoDecoderParent.cpp5
-rw-r--r--dom/media/platforms/PDMFactory.cpp3
-rw-r--r--dom/media/platforms/PDMFactory.h3
-rw-r--r--dom/media/platforms/wmf/WMFDecoderModule.cpp79
15 files changed, 170 insertions, 126 deletions
diff --git a/dom/media/AudioConverter.cpp b/dom/media/AudioConverter.cpp
index 32a5e9a..50e2bb9 100644
--- a/dom/media/AudioConverter.cpp
+++ b/dom/media/AudioConverter.cpp
@@ -5,8 +5,8 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "AudioConverter.h"
-#include <string.h>
#include <speex/speex_resampler.h>
+#include <string.h>
#include <cmath>
/*
@@ -131,24 +131,26 @@ static inline int16_t clipTo15(int32_t aX) {
size_t AudioConverter::DownmixAudio(void* aOut, const void* aIn,
size_t aFrames) const {
- MOZ_ASSERT(mIn.Format() == AudioConfig::FORMAT_S16 ||
- mIn.Format() == AudioConfig::FORMAT_FLT);
- MOZ_ASSERT(mIn.Channels() >= mOut.Channels());
- MOZ_ASSERT(mIn.Layout() == AudioConfig::ChannelLayout(mIn.Channels()),
- "Can only downmix input data in SMPTE layout");
- MOZ_ASSERT(mOut.Layout() == AudioConfig::ChannelLayout(2) ||
- mOut.Layout() == AudioConfig::ChannelLayout(1));
+ MOZ_DIAGNOSTIC_ASSERT(mIn.Format() == AudioConfig::FORMAT_S16 ||
+ mIn.Format() == AudioConfig::FORMAT_FLT);
+ MOZ_DIAGNOSTIC_ASSERT(mIn.Channels() >= mOut.Channels());
+ MOZ_DIAGNOSTIC_ASSERT(
+ mIn.Layout() == AudioConfig::ChannelLayout(mIn.Channels()),
+ "Can only downmix input data in SMPTE layout");
+ MOZ_DIAGNOSTIC_ASSERT(mOut.Layout() == AudioConfig::ChannelLayout(2) ||
+ mOut.Layout() == AudioConfig::ChannelLayout(1));
- uint32_t channels = mIn.Channels();
+ uint32_t inChannels = mIn.Channels();
+ uint32_t outChannels = mOut.Channels();
- if (channels == 1 && mOut.Channels() == 1) {
+ if (inChannels == outChannels) {
if (aOut != aIn) {
memmove(aOut, aIn, FramesOutToBytes(aFrames));
}
return aFrames;
}
- if (channels > 2) {
+ if (inChannels > 2) {
if (mIn.Format() == AudioConfig::FORMAT_FLT) {
// Downmix matrix. Per-row normalization 1 for rows 3,4 and 2 for rows
// 5-8.
@@ -193,14 +195,16 @@ size_t AudioConverter::DownmixAudio(void* aOut, const void* aIn,
for (uint32_t i = 0; i < aFrames; i++) {
float sampL = 0.0;
float sampR = 0.0;
- for (uint32_t j = 0; j < channels; j++) {
- sampL +=
- in[i * mIn.Channels() + j] * dmatrix[mIn.Channels() - 3][j][0];
- sampR +=
- in[i * mIn.Channels() + j] * dmatrix[mIn.Channels() - 3][j][1];
+ for (uint32_t j = 0; j < inChannels; j++) {
+ sampL += in[i * inChannels + j] * dmatrix[inChannels - 3][j][0];
+ sampR += in[i * inChannels + j] * dmatrix[inChannels - 3][j][1];
+ }
+ if (outChannels == 2) {
+ *out++ = sampL;
+ *out++ = sampR;
+ } else {
+ *out++ = (sampL + sampR) * 0.5;
}
- *out++ = sampL;
- *out++ = sampR;
}
} else if (mIn.Format() == AudioConfig::FORMAT_S16) {
// Downmix matrix. Per-row normalization 1 for rows 3,4 and 2 for rows
@@ -240,45 +244,46 @@ size_t AudioConverter::DownmixAudio(void* aOut, const void* aIn,
for (uint32_t i = 0; i < aFrames; i++) {
int32_t sampL = 0;
int32_t sampR = 0;
- for (uint32_t j = 0; j < channels; j++) {
- sampL += in[i * channels + j] * dmatrix[channels - 3][j][0];
- sampR += in[i * channels + j] * dmatrix[channels - 3][j][1];
+ for (uint32_t j = 0; j < inChannels; j++) {
+ sampL += in[i * inChannels + j] * dmatrix[inChannels - 3][j][0];
+ sampR += in[i * inChannels + j] * dmatrix[inChannels - 3][j][1];
+ }
+ sampL = clipTo15((sampL + 8192) >> 14);
+ sampR = clipTo15((sampR + 8192) >> 14);
+ if (outChannels == 2) {
+ *out++ = sampL;
+ *out++ = sampR;
+ } else {
+ *out++ = (sampL + sampR) * 0.5;
}
- *out++ = clipTo15((sampL + 8192) >> 14);
- *out++ = clipTo15((sampR + 8192) >> 14);
}
} else {
MOZ_DIAGNOSTIC_ASSERT(false, "Unsupported data type");
}
-
- // If we are to continue downmixing to mono, start working on the output
- // buffer.
- aIn = aOut;
- channels = 2;
+ return aFrames;
}
- if (mOut.Channels() == 1) {
- if (mIn.Format() == AudioConfig::FORMAT_FLT) {
- const float* in = static_cast<const float*>(aIn);
- float* out = static_cast<float*>(aOut);
- for (size_t fIdx = 0; fIdx < aFrames; ++fIdx) {
- float sample = 0.0;
- // The sample of the buffer would be interleaved.
- sample = (in[fIdx * channels] + in[fIdx * channels + 1]) * 0.5;
- *out++ = sample;
- }
- } else if (mIn.Format() == AudioConfig::FORMAT_S16) {
- const int16_t* in = static_cast<const int16_t*>(aIn);
- int16_t* out = static_cast<int16_t*>(aOut);
- for (size_t fIdx = 0; fIdx < aFrames; ++fIdx) {
- int32_t sample = 0.0;
- // The sample of the buffer would be interleaved.
- sample = (in[fIdx * channels] + in[fIdx * channels + 1]) * 0.5;
- *out++ = sample;
- }
- } else {
- MOZ_DIAGNOSTIC_ASSERT(false, "Unsupported data type");
+ MOZ_DIAGNOSTIC_ASSERT(inChannels == 2 && outChannels == 1);
+ if (mIn.Format() == AudioConfig::FORMAT_FLT) {
+ const float* in = static_cast<const float*>(aIn);
+ float* out = static_cast<float*>(aOut);
+ for (size_t fIdx = 0; fIdx < aFrames; ++fIdx) {
+ float sample = 0.0;
+ // The sample of the buffer would be interleaved.
+ sample = (in[fIdx * inChannels] + in[fIdx * inChannels + 1]) * 0.5;
+ *out++ = sample;
}
+ } else if (mIn.Format() == AudioConfig::FORMAT_S16) {
+ const int16_t* in = static_cast<const int16_t*>(aIn);
+ int16_t* out = static_cast<int16_t*>(aOut);
+ for (size_t fIdx = 0; fIdx < aFrames; ++fIdx) {
+ int32_t sample = 0.0;
+ // The sample of the buffer would be interleaved.
+ sample = (in[fIdx * inChannels] + in[fIdx * inChannels + 1]) * 0.5;
+ *out++ = sample;
+ }
+ } else {
+ MOZ_DIAGNOSTIC_ASSERT(false, "Unsupported data type");
}
return aFrames;
}
diff --git a/dom/media/MediaPrefs.h b/dom/media/MediaPrefs.h
index 7f8191c..01db78a 100644
--- a/dom/media/MediaPrefs.h
+++ b/dom/media/MediaPrefs.h
@@ -154,7 +154,6 @@ class MediaPrefs final {
DECL_MEDIA_PREF("media.wmf.skip-blacklist", PDMWMFSkipBlacklist, bool, false);
DECL_MEDIA_PREF("media.decoder-doctor.wmf-disabled-is-failure",
DecoderDoctorWMFDisabledIsFailure, bool, false);
- DECL_MEDIA_PREF("media.wmf.vp9.enabled", PDMWMFVP9DecoderEnabled, bool, true);
#endif
DECL_MEDIA_PREF("media.decoder.recycle.enabled", MediaDecoderCheckRecycling,
bool, false);
diff --git a/dom/media/eme/CDMProxy.h b/dom/media/eme/CDMProxy.h
index 53e3a37..d0f7181 100644
--- a/dom/media/eme/CDMProxy.h
+++ b/dom/media/eme/CDMProxy.h
@@ -82,7 +82,7 @@ class CDMProxy {
// Main thread only.
CDMProxy(dom::MediaKeys* aKeys, const nsAString& aKeySystem,
bool aDistinctiveIdentifierRequired, bool aPersistentStateRequired,
- nsIEventTarget* aMainThread)
+ nsISerialEventTarget* aMainThread)
: mKeys(aKeys),
mKeySystem(aKeySystem),
mCapabilites("CDMProxy::mCDMCaps"),
@@ -272,7 +272,7 @@ class CDMProxy {
const bool mPersistentStateRequired;
// The main thread associated with the root document.
- const nsCOMPtr<nsIEventTarget> mMainThread;
+ const nsCOMPtr<nsISerialEventTarget> mMainThread;
};
} // namespace mozilla
diff --git a/dom/media/eme/MediaKeys.cpp b/dom/media/eme/MediaKeys.cpp
index 0434418..de2953a 100644
--- a/dom/media/eme/MediaKeys.cpp
+++ b/dom/media/eme/MediaKeys.cpp
@@ -307,7 +307,7 @@ class MediaKeysGMPCrashHelper : public GMPCrashHelper {
};
already_AddRefed<CDMProxy> MediaKeys::CreateCDMProxy(
- nsIEventTarget* aMainThread) {
+ nsISerialEventTarget* aMainThread) {
RefPtr<CDMProxy> proxy;
#ifdef MOZ_WIDGET_ANDROID
if (IsWidevineKeySystem(mKeySystem)) {
diff --git a/dom/media/eme/MediaKeys.h b/dom/media/eme/MediaKeys.h
index 8661d54..128c968 100644
--- a/dom/media/eme/MediaKeys.h
+++ b/dom/media/eme/MediaKeys.h
@@ -148,7 +148,7 @@ class MediaKeys final : public nsISupports,
// Instantiate CDMProxy instance.
// It could be MediaDrmCDMProxy (Widevine on Fennec) or ChromiumCDMProxy (the
// rest).
- already_AddRefed<CDMProxy> CreateCDMProxy(nsIEventTarget* aMainThread);
+ already_AddRefed<CDMProxy> CreateCDMProxy(nsISerialEventTarget* aMainThread);
// Removes promise from mPromises, and returns it.
already_AddRefed<DetailedPromise> RetrievePromise(PromiseId aId);
diff --git a/dom/media/eme/mediadrm/MediaDrmCDMProxy.cpp b/dom/media/eme/mediadrm/MediaDrmCDMProxy.cpp
index f8a81e8..3bb8678 100644
--- a/dom/media/eme/mediadrm/MediaDrmCDMProxy.cpp
+++ b/dom/media/eme/mediadrm/MediaDrmCDMProxy.cpp
@@ -28,7 +28,7 @@ MediaDrmCDMProxy::MediaDrmCDMProxy(dom::MediaKeys* aKeys,
const nsAString& aKeySystem,
bool aDistinctiveIdentifierRequired,
bool aPersistentStateRequired,
- nsIEventTarget* aMainThread)
+ nsISerialEventTarget* aMainThread)
: CDMProxy(aKeys, aKeySystem, aDistinctiveIdentifierRequired,
aPersistentStateRequired, aMainThread),
mCDM(nullptr),
diff --git a/dom/media/eme/mediadrm/MediaDrmCDMProxy.h b/dom/media/eme/mediadrm/MediaDrmCDMProxy.h
index cc0d4f2..92463ed 100644
--- a/dom/media/eme/mediadrm/MediaDrmCDMProxy.h
+++ b/dom/media/eme/mediadrm/MediaDrmCDMProxy.h
@@ -31,7 +31,8 @@ class MediaDrmCDMProxy : public CDMProxy {
MediaDrmCDMProxy(dom::MediaKeys* aKeys, const nsAString& aKeySystem,
bool aDistinctiveIdentifierRequired,
- bool aPersistentStateRequired, nsIEventTarget* aMainThread);
+ bool aPersistentStateRequired,
+ nsISerialEventTarget* aMainThread);
void Init(PromiseId aPromiseId, const nsAString& aOrigin,
const nsAString& aTopLevelOrigin,
diff --git a/dom/media/gmp/ChromiumCDMParent.cpp b/dom/media/gmp/ChromiumCDMParent.cpp
index 5d4534f..5d8a3e2 100644
--- a/dom/media/gmp/ChromiumCDMParent.cpp
+++ b/dom/media/gmp/ChromiumCDMParent.cpp
@@ -61,8 +61,6 @@ RefPtr<ChromiumCDMParent::InitPromise> ChromiumCDMParent::Init(
!aMainThread ? "true" : "false")),
__func__);
}
- mCDMCallback = aCDMCallback;
- mMainThread = aMainThread;
RefPtr<ChromiumCDMParent::InitPromise> promise =
mInitPromise.Ensure(__func__);
@@ -70,7 +68,7 @@ RefPtr<ChromiumCDMParent::InitPromise> ChromiumCDMParent::Init(
SendInit(aAllowDistinctiveIdentifier, aAllowPersistentState)
->Then(
AbstractThread::GetCurrent(), __func__,
- [self](bool aSuccess) {
+ [self, aCDMCallback](bool aSuccess) {
if (!aSuccess) {
GMP_LOG(
"ChromiumCDMParent::Init() failed with callback from "
@@ -84,6 +82,7 @@ RefPtr<ChromiumCDMParent::InitPromise> ChromiumCDMParent::Init(
}
GMP_LOG(
"ChromiumCDMParent::Init() succeeded with callback from child");
+ self->mCDMCallback = aCDMCallback;
self->mInitPromise.ResolveIfExists(true /* unused */, __func__);
},
[self](ResponseRejectReason aReason) {
diff --git a/dom/media/gmp/ChromiumCDMParent.h b/dom/media/gmp/ChromiumCDMParent.h
index fd7dcc2..61dfc92 100644
--- a/dom/media/gmp/ChromiumCDMParent.h
+++ b/dom/media/gmp/ChromiumCDMParent.h
@@ -179,9 +179,6 @@ class ChromiumCDMParent final : public PChromiumCDMParent,
// life time of this object, but never more than one active at once.
uint32_t mMaxRefFrames = 0;
ReorderQueue mReorderQueue;
-
- // The main thread associated with the root document. Must be set in Init().
- nsCOMPtr<nsIEventTarget> mMainThread;
};
} // namespace gmp
diff --git a/dom/media/gmp/ChromiumCDMProxy.cpp b/dom/media/gmp/ChromiumCDMProxy.cpp
index f00b4bc..4af9473 100644
--- a/dom/media/gmp/ChromiumCDMProxy.cpp
+++ b/dom/media/gmp/ChromiumCDMProxy.cpp
@@ -22,17 +22,18 @@ ChromiumCDMProxy::ChromiumCDMProxy(dom::MediaKeys* aKeys,
GMPCrashHelper* aCrashHelper,
bool aDistinctiveIdentifierRequired,
bool aPersistentStateRequired,
- nsIEventTarget* aMainThread)
+ nsISerialEventTarget* aMainThread)
: CDMProxy(aKeys, aKeySystem, aDistinctiveIdentifierRequired,
aPersistentStateRequired, aMainThread),
mCrashHelper(aCrashHelper),
mCDMMutex("ChromiumCDMProxy"),
mGMPThread(GetGMPAbstractThread()) {
MOZ_ASSERT(NS_IsMainThread());
- MOZ_COUNT_CTOR(ChromiumCDMProxy);
}
-ChromiumCDMProxy::~ChromiumCDMProxy() { MOZ_COUNT_DTOR(ChromiumCDMProxy); }
+ChromiumCDMProxy::~ChromiumCDMProxy() {
+ EME_LOG("ChromiumCDMProxy::~ChromiumCDMProxy(this=%p)", this);
+}
void ChromiumCDMProxy::Init(PromiseId aPromiseId, const nsAString& aOrigin,
const nsAString& aTopLevelOrigin,
@@ -90,13 +91,25 @@ void ChromiumCDMProxy::Init(PromiseId aPromiseId, const nsAString& aOrigin,
cdm->Init(self->mCallback.get(),
self->mDistinctiveIdentifierRequired,
self->mPersistentStateRequired, self->mMainThread)
- ->Then(thread, __func__,
+ ->Then(self->mMainThread, __func__,
[self, aPromiseId, cdm](bool /* unused */) {
// CDM init succeeded
{
MutexAutoLock lock(self->mCDMMutex);
self->mCDM = cdm;
}
+ if (self->mIsShutdown) {
+ self->RejectPromise(
+ aPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
+ NS_LITERAL_CSTRING(
+ "ChromiumCDMProxy shutdown during "
+ "ChromiumCDMProxy::Init"));
+ // If shutdown happened while waiting to init, we
+ // need to explicitly shutdown the CDM to avoid it
+ // referencing this proxy which is on its way out.
+ self->ShutdownCDMIfExists();
+ return;
+ }
self->OnCDMCreated(aPromiseId);
},
[self, aPromiseId](MediaResult aResult) {
@@ -118,13 +131,6 @@ void ChromiumCDMProxy::OnCDMCreated(uint32_t aPromiseId) {
EME_LOG("ChromiumCDMProxy::OnCDMCreated(pid=%u) isMainThread=%d this=%p",
aPromiseId, NS_IsMainThread(), this);
- if (!NS_IsMainThread()) {
- mMainThread->Dispatch(NewRunnableMethod<PromiseId>(
- "ChromiumCDMProxy::OnCDMCreated", this,
- &ChromiumCDMProxy::OnCDMCreated, aPromiseId),
- NS_DISPATCH_NORMAL);
- return;
- }
MOZ_ASSERT(NS_IsMainThread());
if (mKeys.IsNull()) {
return;
@@ -141,6 +147,29 @@ void ChromiumCDMProxy::OnCDMCreated(uint32_t aPromiseId) {
}
}
+void ChromiumCDMProxy::ShutdownCDMIfExists() {
+ EME_LOG(
+ "ChromiumCDMProxy::ShutdownCDMIfExists(this=%p) mCDM=%p, mIsShutdown=%s",
+ this, mCDM.get(), mIsShutdown ? "true" : "false");
+ MOZ_ASSERT(NS_IsMainThread());
+ MOZ_ASSERT(mGMPThread);
+ MOZ_ASSERT(mIsShutdown,
+ "Should only shutdown the CDM if the proxy is shutting down");
+ RefPtr<gmp::ChromiumCDMParent> cdm;
+ {
+ MutexAutoLock lock(mCDMMutex);
+ cdm.swap(mCDM);
+ }
+ if (cdm) {
+ // We need to keep this proxy alive until the parent has finished its
+ // Shutdown (as it may still try to use the proxy until then).
+ RefPtr<ChromiumCDMProxy> self(this);
+ nsCOMPtr<nsIRunnable> task = NS_NewRunnableFunction(
+ "ChromiumCDMProxy::Shutdown", [self, cdm]() { cdm->Shutdown(); });
+ mGMPThread->Dispatch(task.forget());
+ }
+}
+
#ifdef DEBUG
bool ChromiumCDMProxy::IsOnOwnerThread() {
return mGMPThread->IsCurrentThreadIn();
@@ -294,21 +323,14 @@ void ChromiumCDMProxy::RemoveSession(const nsAString& aSessionId,
void ChromiumCDMProxy::Shutdown() {
MOZ_ASSERT(NS_IsMainThread());
- EME_LOG("ChromiumCDMProxy::Shutdown()");
- mKeys.Clear();
- RefPtr<gmp::ChromiumCDMParent> cdm;
- {
- MutexAutoLock lock(mCDMMutex);
- cdm.swap(mCDM);
- }
- if (cdm) {
- // We need to keep this proxy alive until the parent has finished its
- // Shutdown (as it may still try to use the proxy until then).
- RefPtr<ChromiumCDMProxy> self(this);
- nsCOMPtr<nsIRunnable> task = NS_NewRunnableFunction(
- "ChromiumCDMProxy::Shutdown", [self, cdm]() { cdm->Shutdown(); });
- mGMPThread->Dispatch(task.forget());
+ EME_LOG("ChromiumCDMProxy::Shutdown(this=%p) mCDM=%p, mIsShutdown=%s", this,
+ mCDM.get(), mIsShutdown ? "true" : "false");
+ if (mIsShutdown) {
+ return;
}
+ mIsShutdown = true;
+ mKeys.Clear();
+ ShutdownCDMIfExists();
}
void ChromiumCDMProxy::RejectPromise(PromiseId aId, nsresult aCode,
diff --git a/dom/media/gmp/ChromiumCDMProxy.h b/dom/media/gmp/ChromiumCDMProxy.h
index 13fa28b..9200969 100644
--- a/dom/media/gmp/ChromiumCDMProxy.h
+++ b/dom/media/gmp/ChromiumCDMProxy.h
@@ -7,8 +7,8 @@
#ifndef ChromiumCDMProxy_h_
#define ChromiumCDMProxy_h_
-#include "mozilla/CDMProxy.h"
#include "mozilla/AbstractThread.h"
+#include "mozilla/CDMProxy.h"
#include "ChromiumCDMParent.h"
namespace mozilla {
@@ -23,7 +23,7 @@ class ChromiumCDMProxy : public CDMProxy {
ChromiumCDMProxy(dom::MediaKeys* aKeys, const nsAString& aKeySystem,
GMPCrashHelper* aCrashHelper,
bool aAllowDistinctiveIdentifier, bool aAllowPersistentState,
- nsIEventTarget* aMainThread);
+ nsISerialEventTarget* aMainThread);
void Init(PromiseId aPromiseId, const nsAString& aOrigin,
const nsAString& aTopLevelOrigin,
@@ -108,9 +108,14 @@ class ChromiumCDMProxy : public CDMProxy {
private:
void OnCDMCreated(uint32_t aPromiseId);
+ void ShutdownCDMIfExists();
~ChromiumCDMProxy();
+ // True if Shutdown() has been called. Should only be read and written on
+ // main thread.
+ bool mIsShutdown = false;
+
GMPCrashHelper* mCrashHelper;
Mutex mCDMMutex;
diff --git a/dom/media/ipc/VideoDecoderParent.cpp b/dom/media/ipc/VideoDecoderParent.cpp
index 6c95f31..24eb234 100644
--- a/dom/media/ipc/VideoDecoderParent.cpp
+++ b/dom/media/ipc/VideoDecoderParent.cpp
@@ -11,6 +11,7 @@
#include "mozilla/layers/VideoBridgeChild.h"
#include "mozilla/layers/ImageClient.h"
#include "MediaInfo.h"
+#include "PDMFactory.h"
#include "VideoDecoderManagerParent.h"
#ifdef XP_WIN
#include "WMFDecoderModule.h"
@@ -61,9 +62,11 @@ VideoDecoderParent::VideoDecoderParent(
mKnowsCompositor->IdentifyTextureHost(aIdentifier);
#ifdef XP_WIN
+ // Ensure everything is properly initialized on the right thread.
+ PDMFactory::EnsureInit();
+
// TODO: Ideally we wouldn't hardcode the WMF PDM, and we'd use the normal PDM
// factory logic for picking a decoder.
- WMFDecoderModule::Init();
RefPtr<WMFDecoderModule> pdm(new WMFDecoderModule());
pdm->Startup();
diff --git a/dom/media/platforms/PDMFactory.cpp b/dom/media/platforms/PDMFactory.cpp
index 2211a1a..c8e7df2 100644
--- a/dom/media/platforms/PDMFactory.cpp
+++ b/dom/media/platforms/PDMFactory.cpp
@@ -152,7 +152,8 @@ PDMFactory::PDMFactory() {
PDMFactory::~PDMFactory() {}
-void PDMFactory::EnsureInit() const {
+/* static */
+void PDMFactory::EnsureInit() {
{
StaticMutexAutoLock mon(sMonitor);
if (sInstance) {
diff --git a/dom/media/platforms/PDMFactory.h b/dom/media/platforms/PDMFactory.h
index fb6065b..fcd89dc 100644
--- a/dom/media/platforms/PDMFactory.h
+++ b/dom/media/platforms/PDMFactory.h
@@ -45,6 +45,8 @@ class PDMFactory final {
// This is called on the decode task queue.
void SetCDMProxy(CDMProxy* aProxy);
+ static void EnsureInit();
+
static constexpr int kYUV400 = 0;
static constexpr int kYUV420 = 1;
static constexpr int kYUV422 = 2;
@@ -72,7 +74,6 @@ class PDMFactory final {
bool mFFmpegFailedToLoad = false;
bool mGMPPDMFailedToStartup = false;
- void EnsureInit() const;
template <class T>
friend class StaticAutoPtr;
static StaticAutoPtr<PDMFactoryImpl> sInstance;
diff --git a/dom/media/platforms/wmf/WMFDecoderModule.cpp b/dom/media/platforms/wmf/WMFDecoderModule.cpp
index 8db98b4..98b70b0 100644
--- a/dom/media/platforms/wmf/WMFDecoderModule.cpp
+++ b/dom/media/platforms/wmf/WMFDecoderModule.cpp
@@ -5,6 +5,9 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "WMFDecoderModule.h"
+#include <algorithm>
+#include <vector>
+#include "DriverCrashGuard.h"
#include "GfxDriverInfo.h"
#include "MFTDecoder.h"
#include "MP4Decoder.h"
@@ -22,22 +25,23 @@
#include "mozilla/StaticMutex.h"
#include "mozilla/WindowsVersion.h"
#include "mozilla/gfx/gfxVars.h"
+#include "mozilla/mscom/EnsureMTA.h"
#include "nsAutoPtr.h"
#include "nsComponentManagerUtils.h"
#include "nsIGfxInfo.h"
#include "nsIWindowsRegKey.h"
+#include "nsIXULRuntime.h"
#include "nsServiceManagerUtils.h"
#include "nsWindowsHelpers.h"
#include "prsystem.h"
#include "nsIXULRuntime.h"
-#include "mozilla/mscom/EnsureMTA.h"
extern const GUID CLSID_WebmMfVpxDec;
-extern const GUID CLSID_AMDWebmMfVp9Dec;
namespace mozilla {
static Atomic<bool> sDXVAEnabled(false);
+static Atomic<bool> sUsableVPXMFT(false);
WMFDecoderModule::~WMFDecoderModule() {
if (mWMFInitialized) {
@@ -46,22 +50,54 @@ WMFDecoderModule::~WMFDecoderModule() {
}
}
+static bool CanCreateMFTDecoder(const GUID& aGuid) {
+ // The IMFTransform interface used by MFTDecoder is documented to require to
+ // run on an MTA thread.
+ // https://msdn.microsoft.com/en-us/library/windows/desktop/ee892371(v=vs.85).aspx#components
+ // Note: our normal SharedThreadPool task queues are initialized to MTA, but
+ // the main thread (which calls in here from our CanPlayType implementation)
+ // is not.
+ bool canCreateDecoder = false;
+ mozilla::mscom::EnsureMTA([&]() -> void {
+ if (FAILED(wmf::MFStartup())) {
+ return;
+ }
+ RefPtr<MFTDecoder> decoder(new MFTDecoder());
+ canCreateDecoder = SUCCEEDED(decoder->Create(aGuid));
+ wmf::MFShutdown();
+ });
+ return canCreateDecoder;
+}
+
/* static */
void WMFDecoderModule::Init() {
+ MOZ_DIAGNOSTIC_ASSERT(NS_IsMainThread());
+ bool testForVPx;
if (XRE_IsContentProcess()) {
// If we're in the content process and the UseGPUDecoder pref is set, it
// means that we've given up on the GPU process (it's been crashing) so we
// should disable DXVA
sDXVAEnabled = !MediaPrefs::PDMUseGPUDecoder();
+ // We need to test for VPX in the content process as the GPUDecoderModule
+ // directly calls WMFDecoderModule::Supports in the content process.
+ // This unnecessary requirement will be fixed in bug 1534815.
+ testForVPx = true;
} else if (XRE_IsGPUProcess()) {
// Always allow DXVA in the GPU process.
- sDXVAEnabled = true;
+ testForVPx = sDXVAEnabled = true;
} else {
// Only allow DXVA in the UI process if we aren't in e10s Firefox
- sDXVAEnabled = !mozilla::BrowserTabsRemoteAutostart();
+ testForVPx = sDXVAEnabled = !mozilla::BrowserTabsRemoteAutostart();
}
sDXVAEnabled = sDXVAEnabled && gfx::gfxVars::CanUseHardwareVideoDecoding();
+ testForVPx = testForVPx && gfx::gfxVars::CanUseHardwareVideoDecoding();
+ if (testForVPx && gfxPrefs::PDMWMFVP9DecoderEnabled()) {
+ gfx::WMFVPXVideoCrashGuard guard;
+ if (!guard.Crashed()) {
+ sUsableVPXMFT = CanCreateMFTDecoder(CLSID_WebmMfVpxDec);
+ }
+ }
}
/* static */
@@ -122,25 +158,6 @@ already_AddRefed<MediaDataDecoder> WMFDecoderModule::CreateAudioDecoder(
return decoder.forget();
}
-static bool CanCreateMFTDecoder(const GUID& aGuid) {
- // The IMFTransform interface used by MFTDecoder is documented to require to
- // run on an MTA thread.
- // https://msdn.microsoft.com/en-us/library/windows/desktop/ee892371(v=vs.85).aspx#components
- // Note: our normal SharedThreadPool task queues are initialized to MTA, but
- // the main thread (which calls in here from our CanPlayType implementation)
- // is not.
- bool canCreateDecoder = false;
- mozilla::mscom::EnsureMTA([&]() -> void {
- if (FAILED(wmf::MFStartup())) {
- return;
- }
- RefPtr<MFTDecoder> decoder(new MFTDecoder());
- canCreateDecoder = SUCCEEDED(decoder->Create(aGuid));
- wmf::MFShutdown();
- });
- return canCreateDecoder;
-}
-
template <const GUID& aGuid>
static bool CanCreateWMFDecoder() {
static StaticMutex sMutex;
@@ -188,18 +205,12 @@ bool WMFDecoderModule::Supports(const TrackInfo& aTrackInfo,
CanCreateWMFDecoder<CLSID_CMP3DecMediaObject>()) {
return true;
}
- if (MediaPrefs::PDMWMFVP9DecoderEnabled()) {
+ if (sUsableVPXMFT) {
static const uint32_t VP8_USABLE_BUILD = 16287;
- if (VPXDecoder::IsVP8(aTrackInfo.mMimeType) &&
- IsWindowsBuildOrLater(VP8_USABLE_BUILD) &&
- CanCreateWMFDecoder<CLSID_WebmMfVpxDec>()) {
- return true;
- }
- if (VPXDecoder::IsVP9(aTrackInfo.mMimeType) &&
- ((gfxPrefs::PDMWMFAMDVP9DecoderEnabled() &&
- CanCreateWMFDecoder<CLSID_AMDWebmMfVp9Dec>()) ||
- CanCreateWMFDecoder<CLSID_WebmMfVpxDec>())) {
- return true;
+ if ((VPXDecoder::IsVP8(aTrackInfo.mMimeType) &&
+ IsWindowsBuildOrLater(VP8_USABLE_BUILD)) ||
+ VPXDecoder::IsVP9(aTrackInfo.mMimeType)) {
+ return CanCreateWMFDecoder<CLSID_WebmMfVpxDec>();
}
}