Bug 1271242 - Remove GMPDecryptorCallback::SetCapabilities(). r=jwwang

Now that GMPParent detects whether gmp-clearkey can decode using AAC/H.264
using WMF before reporting gmp-clearkey's GMPParent can decode AAC/H.264, we
don't need the GMPDecryptorCallback::SetCapabilities() callback from the GMP to
signal to the PDMFactory that the GMP can decode. We can now trust what the
GMPService tells us.

So we can remove the "waiting for CDM caps" step in the state machine's startup
sequence. And all the plumbing. :)

If we need more caps, like for an decode-and-render path, we can declare those
as API strings in the info file.


MozReview-Commit-ID: E0QhU4cYhjo

--HG--
extra : rebase_source : 7d15ab6a45bac88c15c053f416d941b5fe0807b0
This commit is contained in:
Chris Pearce 2016-05-10 10:28:38 +12:00
parent eb7204d3b6
commit 46a1552995
18 changed files with 13 additions and 258 deletions

View File

@ -1657,19 +1657,7 @@ MediaDecoder::SetCDMProxy(CDMProxy* aProxy)
{
MOZ_ASSERT(NS_IsMainThread());
RefPtr<CDMProxy> proxy = aProxy;
{
CDMCaps::AutoLock caps(aProxy->Capabilites());
if (!caps.AreCapsKnown()) {
RefPtr<MediaDecoder> self = this;
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([=] () {
self->mCDMProxyPromiseHolder.ResolveIfExists(proxy, __func__);
});
caps.CallOnMainThreadWhenCapsAvailable(r);
return;
}
}
mCDMProxyPromiseHolder.ResolveIfExists(proxy, __func__);
mCDMProxyPromiseHolder.ResolveIfExists(aProxy, __func__);
}
#endif

View File

@ -302,15 +302,6 @@ CDMCallbackProxy::KeyStatusChanged(const nsCString& aSessionId,
}
}
void
CDMCallbackProxy::SetCaps(uint64_t aCaps)
{
MOZ_ASSERT(mProxy->IsOnGMPThread());
CDMCaps::AutoLock caps(mProxy->Capabilites());
caps.SetCaps(aCaps);
}
void
CDMCallbackProxy::Decrypted(uint32_t aId,
GMPErr aResult,

View File

@ -47,8 +47,6 @@ public:
const nsTArray<uint8_t>& aKeyId,
GMPMediaKeyStatus aStatus) override;
void SetCaps(uint64_t aCaps) override;
void Decrypted(uint32_t aId,
GMPErr aResult,
const nsTArray<uint8_t>& aDecryptedData) override;

View File

@ -13,7 +13,6 @@ namespace mozilla {
CDMCaps::CDMCaps()
: mMonitor("CDMCaps")
, mCaps(0)
{
}
@ -33,13 +32,6 @@ CDMCaps::Unlock()
mMonitor.Unlock();
}
bool
CDMCaps::HasCap(uint64_t aCap)
{
mMonitor.AssertCurrentThreadOwns();
return (mCaps & aCap) == aCap;
}
CDMCaps::AutoLock::AutoLock(CDMCaps& aInstance)
: mData(aInstance)
{
@ -51,56 +43,6 @@ CDMCaps::AutoLock::~AutoLock()
mData.Unlock();
}
static void
TestCap(uint64_t aFlag,
uint64_t aCaps,
const nsACString& aCapName,
nsACString& aCapStr)
{
if (!(aFlag & aCaps)) {
return;
}
if (!aCapStr.IsEmpty()) {
aCapStr.AppendLiteral(",");
}
aCapStr.Append(aCapName);
}
nsCString
CapsToString(uint64_t aCaps)
{
nsCString capsStr;
TestCap(GMP_EME_CAP_DECRYPT_AUDIO, aCaps, NS_LITERAL_CSTRING("DecryptAudio"), capsStr);
TestCap(GMP_EME_CAP_DECRYPT_VIDEO, aCaps, NS_LITERAL_CSTRING("DecryptVideo"), capsStr);
TestCap(GMP_EME_CAP_DECRYPT_AND_DECODE_AUDIO, aCaps, NS_LITERAL_CSTRING("DecryptAndDecodeAudio"), capsStr);
TestCap(GMP_EME_CAP_DECRYPT_AND_DECODE_VIDEO, aCaps, NS_LITERAL_CSTRING("DecryptAndDecodeVideo"), capsStr);
return capsStr;
}
void
CDMCaps::AutoLock::SetCaps(uint64_t aCaps)
{
EME_LOG("SetCaps() %s", CapsToString(aCaps).get());
mData.mMonitor.AssertCurrentThreadOwns();
mData.mCaps = aCaps;
for (size_t i = 0; i < mData.mWaitForCaps.Length(); i++) {
NS_DispatchToMainThread(mData.mWaitForCaps[i], NS_DISPATCH_NORMAL);
}
mData.mWaitForCaps.Clear();
}
void
CDMCaps::AutoLock::CallOnMainThreadWhenCapsAvailable(nsIRunnable* aContinuation)
{
mData.mMonitor.AssertCurrentThreadOwns();
if (mData.mCaps) {
NS_DispatchToMainThread(aContinuation, NS_DISPATCH_NORMAL);
MOZ_ASSERT(mData.mWaitForCaps.IsEmpty());
} else {
mData.mWaitForCaps.AppendElement(aContinuation);
}
}
bool
CDMCaps::AutoLock::IsKeyUsable(const CencKeyId& aKeyId)
{
@ -177,49 +119,6 @@ CDMCaps::AutoLock::NotifyWhenKeyIdUsable(const CencKeyId& aKey,
mData.mWaitForKeys.AppendElement(WaitForKeys(aKey, aListener));
}
bool
CDMCaps::AutoLock::AreCapsKnown()
{
mData.mMonitor.AssertCurrentThreadOwns();
return mData.mCaps != 0;
}
bool
CDMCaps::AutoLock::CanRenderAudio()
{
return mData.HasCap(GMP_EME_CAP_RENDER_AUDIO);
}
bool
CDMCaps::AutoLock::CanRenderVideo()
{
return mData.HasCap(GMP_EME_CAP_RENDER_VIDEO);
}
bool
CDMCaps::AutoLock::CanDecryptAndDecodeAudio()
{
return mData.HasCap(GMP_EME_CAP_DECRYPT_AND_DECODE_AUDIO);
}
bool
CDMCaps::AutoLock::CanDecryptAndDecodeVideo()
{
return mData.HasCap(GMP_EME_CAP_DECRYPT_AND_DECODE_VIDEO);
}
bool
CDMCaps::AutoLock::CanDecryptAudio()
{
return mData.HasCap(GMP_EME_CAP_DECRYPT_AUDIO);
}
bool
CDMCaps::AutoLock::CanDecryptVideo()
{
return mData.HasCap(GMP_EME_CAP_DECRYPT_VIDEO);
}
void
CDMCaps::AutoLock::GetKeyStatusesForSession(const nsAString& aSessionId,
nsTArray<KeyStatus>& aOutKeyStatuses)

View File

@ -18,8 +18,8 @@
namespace mozilla {
// CDM capabilities; what keys a CDMProxy can use, and whether it can decrypt, or
// decrypt-and-decode on a per stream basis. Must be locked to access state.
// CDM capabilities; what keys a CDMProxy can use.
// Must be locked to access state.
class CDMCaps {
public:
CDMCaps();
@ -55,10 +55,6 @@ public:
explicit AutoLock(CDMCaps& aKeyCaps);
~AutoLock();
// Returns true if the capabilities of the CDM are known, i.e. they have
// been reported by the CDM to Gecko.
bool AreCapsKnown();
bool IsKeyUsable(const CencKeyId& aKeyId);
// Returns true if key status changed,
@ -75,21 +71,6 @@ public:
// Returns true if a key status was changed.
bool RemoveKeysForSession(const nsString& aSessionId);
// Sets the capabilities of the CDM. aCaps is the logical OR of the
// GMP_EME_CAP_* flags from gmp-decryption.h.
void SetCaps(uint64_t aCaps);
bool CanRenderAudio();
bool CanRenderVideo();
bool CanDecryptAndDecodeAudio();
bool CanDecryptAndDecodeVideo();
bool CanDecryptAudio();
bool CanDecryptVideo();
void CallOnMainThreadWhenCapsAvailable(nsIRunnable* aContinuation);
// Notifies the SamplesWaitingForKey when key become usable.
void NotifyWhenKeyIdUsable(const CencKeyId& aKey,
SamplesWaitingForKey* aSamplesWaiting);
@ -101,7 +82,6 @@ public:
private:
void Lock();
void Unlock();
bool HasCap(uint64_t);
struct WaitForKeys {
WaitForKeys(const CencKeyId& aKeyId,
@ -119,9 +99,6 @@ private:
nsTArray<WaitForKeys> mWaitForKeys;
nsTArray<nsCOMPtr<nsIRunnable>> mWaitForCaps;
uint64_t mCaps;
// It is not safe to copy this object.
CDMCaps(const CDMCaps&) = delete;
CDMCaps& operator=(const CDMCaps&) = delete;

View File

@ -193,7 +193,7 @@ GMPDecryptorChild::Decrypted(GMPBuffer* aBuffer, GMPErr aResult)
void
GMPDecryptorChild::SetCapabilities(uint64_t aCaps)
{
CALL_ON_GMP_THREAD(SendSetCaps, aCaps);
// Deprecated.
}
void

View File

@ -343,19 +343,6 @@ GMPDecryptorParent::RecvKeyStatusChanged(const nsCString& aSessionId,
return true;
}
bool
GMPDecryptorParent::RecvSetCaps(const uint64_t& aCaps)
{
LOGD(("GMPDecryptorParent[%p]::RecvSetCaps(caps=0x%llx)", this, aCaps));
if (!mIsOpen) {
NS_WARNING("Trying to use a dead GMP decrypter!");
return false;
}
mCallback->SetCaps(aCaps);
return true;
}
bool
GMPDecryptorParent::RecvDecrypted(const uint32_t& aId,
const GMPErr& aErr,

View File

@ -102,8 +102,6 @@ private:
const GMPErr& aErr,
InfallibleTArray<uint8_t>&& aBuffer) override;
bool RecvSetCaps(const uint64_t& aCaps) override;
bool RecvShutdown() override;
void ActorDestroy(ActorDestroyReason aWhy) override;

View File

@ -48,8 +48,6 @@ public:
const nsTArray<uint8_t>& aKeyId,
GMPMediaKeyStatus aStatus) = 0;
virtual void SetCaps(uint64_t aCaps) = 0;
virtual void Decrypted(uint32_t aId,
GMPErr aResult,
const nsTArray<uint8_t>& aDecryptedData) = 0;

View File

@ -81,8 +81,6 @@ parent:
async KeyStatusChanged(nsCString aSessionId, uint8_t[] aKey,
GMPMediaKeyStatus aStatus);
async SetCaps(uint64_t aCaps);
async Decrypted(uint32_t aId, GMPErr aResult, uint8_t[] aBuffer);
async Shutdown();

View File

@ -105,32 +105,6 @@ enum GMPMediaKeyStatus {
// Time in milliseconds, as offset from epoch, 1 Jan 1970.
typedef int64_t GMPTimestamp;
// Capability definitions. The capabilities of the EME GMP are reported
// to Gecko by calling the GMPDecryptorCallback::SetCapabilities()
// callback and specifying the logical OR of the GMP_EME_CAP_* flags below.
//
// Note the DECRYPT and the DECRYPT_AND_DECODE are mutually exclusive;
// only one mode should be reported for each stream type, but different
// modes can be reported for different stream types.
//
// Note: Gecko does not currently support the caps changing at runtime.
// Set them once per plugin initialization, during the startup of
// the GMPDecryptor.
// Capability; CDM can decrypt encrypted buffers and return still
// compressed buffers back to Gecko for decompression there.
#define GMP_EME_CAP_DECRYPT_AUDIO (uint64_t(1) << 0)
#define GMP_EME_CAP_DECRYPT_VIDEO (uint64_t(1) << 1)
// Capability; CDM can decrypt and then decode encrypted buffers,
// and return decompressed samples to Gecko for playback.
#define GMP_EME_CAP_DECRYPT_AND_DECODE_AUDIO (uint64_t(1) << 2)
#define GMP_EME_CAP_DECRYPT_AND_DECODE_VIDEO (uint64_t(1) << 3)
// Capability; CDM can decrypt and then decode and render encrypted buffers
#define GMP_EME_CAP_RENDER_AUDIO (uint64_t(1) << 4)
#define GMP_EME_CAP_RENDER_VIDEO (uint64_t(1) << 5)
// Callbacks to be called from the CDM. Threadsafe.
class GMPDecryptorCallback {
public:
@ -212,12 +186,7 @@ public:
uint32_t aKeyIdLength,
GMPMediaKeyStatus aStatus) = 0;
// The CDM must report its capabilites of this CDM. aCaps should be a
// logical OR of the GMP_EME_CAP_* flags. The CDM *MUST* call this
// function and report whether it can decrypt and/or decode. Without
// this, Gecko does not know how to use the CDM and will not send
// samples to the CDM to decrypt or decrypt-and-decode mode. Note a
// CDM cannot change modes once playback has begun.
// DEPRECATED; this function has no affect.
virtual void SetCapabilities(uint64_t aCaps) = 0;
// Returns decrypted buffer to Gecko, or reports failure.
@ -258,13 +227,6 @@ public:
// Sets the callback to use with the decryptor to return results
// to Gecko.
//
// The CDM must also call GMPDecryptorCallback::SetCapabilities()
// exactly once during start up, to inform Gecko whether to use the CDM
// in decrypt or decrypt-and-decode mode.
//
// Note: GMPDecryptorCallback::SetCapabilities() must be called before
// Gecko will send any samples for decryption to the GMP.
virtual void Init(GMPDecryptorCallback* aCallback) = 0;
// Initiates the creation of a session given |aType| and |aInitData|, and

View File

@ -39,8 +39,6 @@ WidevineDecryptor::Init(GMPDecryptorCallback* aCallback)
{
MOZ_ASSERT(aCallback);
mCallback = aCallback;
mCallback->SetCapabilities(GMP_EME_CAP_DECRYPT_AND_DECODE_VIDEO |
GMP_EME_CAP_DECRYPT_AUDIO);
}
static SessionType

View File

@ -1349,7 +1349,6 @@ class GMPStorageTest : public GMPDecryptorProxyCallback
void KeyStatusChanged(const nsCString& aSessionId,
const nsTArray<uint8_t>& aKeyId,
GMPMediaKeyStatus aStatus) override { }
void SetCaps(uint64_t aCaps) override {}
void Decrypted(uint32_t aId,
GMPErr aResult,
const nsTArray<uint8_t>& aDecryptedData) override { }

View File

@ -385,16 +385,8 @@ PDMFactory::GetDecoder(const nsACString& aMimeType,
void
PDMFactory::SetCDMProxy(CDMProxy* aProxy)
{
bool cdmDecodesAudio;
bool cdmDecodesVideo;
{
CDMCaps::AutoLock caps(aProxy->Capabilites());
cdmDecodesAudio = caps.CanDecryptAndDecodeAudio();
cdmDecodesVideo = caps.CanDecryptAndDecodeVideo();
}
RefPtr<PDMFactory> m = new PDMFactory();
mEMEPDM = new EMEDecoderModule(aProxy, m, cdmDecodesAudio, cdmDecodesVideo);
mEMEPDM = new EMEDecoderModule(aProxy, m);
}
#endif

View File

@ -205,14 +205,9 @@ EMEMediaDataDecoderProxy::Shutdown()
return rv;
}
EMEDecoderModule::EMEDecoderModule(CDMProxy* aProxy,
PDMFactory* aPDM,
bool aCDMDecodesAudio,
bool aCDMDecodesVideo)
EMEDecoderModule::EMEDecoderModule(CDMProxy* aProxy, PDMFactory* aPDM)
: mProxy(aProxy)
, mPDM(aPDM)
, mCDMDecodesAudio(aCDMDecodesAudio)
, mCDMDecodesVideo(aCDMDecodesVideo)
{
}
@ -246,7 +241,8 @@ EMEDecoderModule::CreateVideoDecoder(const VideoInfo& aConfig,
{
MOZ_ASSERT(aConfig.mCrypto.mValid);
if (mCDMDecodesVideo) {
if (SupportsMimeType(aConfig.mMimeType, nullptr)) {
// GMP decodes. Assume that means it can decrypt too.
RefPtr<MediaDataDecoderProxy> wrapper = CreateDecoderWrapper(aCallback, mProxy, aVideoTaskQueue);
wrapper->SetProxyTarget(new EMEVideoDecoder(mProxy,
aConfig,
@ -284,7 +280,8 @@ EMEDecoderModule::CreateAudioDecoder(const AudioInfo& aConfig,
{
MOZ_ASSERT(aConfig.mCrypto.mValid);
if (mCDMDecodesAudio) {
if (SupportsMimeType(aConfig.mMimeType, nullptr)) {
// GMP decodes. Assume that means it can decrypt too.
RefPtr<MediaDataDecoderProxy> wrapper = CreateDecoderWrapper(aCallback, mProxy, aAudioTaskQueue);
wrapper->SetProxyTarget(new EMEAudioDecoder(mProxy,
aConfig,

View File

@ -19,10 +19,7 @@ class EMEDecoderModule : public PlatformDecoderModule {
private:
public:
EMEDecoderModule(CDMProxy* aProxy,
PDMFactory* aPDM,
bool aCDMDecodesAudio,
bool aCDMDecodesVideo);
EMEDecoderModule(CDMProxy* aProxy, PDMFactory* aPDM);
virtual ~EMEDecoderModule();
@ -56,8 +53,6 @@ private:
RefPtr<PDMFactory> mPDM;
// We run the PDM on its own task queue.
RefPtr<TaskQueue> mTaskQueue;
bool mCDMDecodesAudio;
bool mCDMDecodesVideo;
};
} // namespace mozilla

View File

@ -24,11 +24,6 @@
#include "ClearKeyStorage.h"
#include "ClearKeyPersistence.h"
#include "gmp-task-utils.h"
#if defined(ENABLE_WMF)
#include "WMFUtils.h"
#include <versionhelpers.h>
#endif
#include <assert.h>
using namespace std;
@ -50,28 +45,11 @@ ClearKeySessionManager::~ClearKeySessionManager()
CK_LOGD("ClearKeySessionManager dtor %p", this);
}
static bool
CanDecode()
{
return
#if defined(ENABLE_WMF)
wmf::EnsureLibs() ||
#endif
false;
}
void
ClearKeySessionManager::Init(GMPDecryptorCallback* aCallback)
{
CK_LOGD("ClearKeySessionManager::Init");
mCallback = aCallback;
if (!CanDecode()) {
mCallback->SetCapabilities(GMP_EME_CAP_DECRYPT_AUDIO |
GMP_EME_CAP_DECRYPT_VIDEO);
} else {
mCallback->SetCapabilities(GMP_EME_CAP_DECRYPT_AND_DECODE_AUDIO |
GMP_EME_CAP_DECRYPT_AND_DECODE_VIDEO);
}
ClearKeyPersistence::EnsureInitialized();
}

View File

@ -63,7 +63,7 @@ GMPGetAPI(const char* aApiName, void* aHostAPI, void** aPluginAPI)
}
#if defined(ENABLE_WMF)
else if (!strcmp(aApiName, GMP_API_AUDIO_DECODER) &&
wmf::EnsureLibs()) {
wmf::EnsureLibs()) {
*aPluginAPI = new AudioDecoder(static_cast<GMPAudioHost*>(aHostAPI));
} else if (!strcmp(aApiName, GMP_API_VIDEO_DECODER) &&
wmf::EnsureLibs()) {