Bug 1306314 - Use decryptor ID in WidevineAdapter to link decryptors with decoders. r=gerald
Store a mapping of decryptor ID to the CDM instance that the corresponding
WidevineDecryptor is using. This allows us to link GMPDecryptor instances
with the corresponding GMPVideoDecoder.
The CDM is stored inside the CDMWrapper, so that we destroy the CDM instance
when the last reference to the CDM is dropped.
MozReview-Commit-ID: FQYzh77yjoC
--- a/dom/media/gmp/widevine-adapter/WidevineAdapter.cpp
+++ b/dom/media/gmp/widevine-adapter/WidevineAdapter.cpp
@@ -8,24 +8,21 @@
#include "VideoUtils.h"
#include "WidevineDecryptor.h"
#include "WidevineUtils.h"
#include "WidevineVideoDecoder.h"
#include "gmp-api/gmp-entrypoints.h"
#include "gmp-api/gmp-decryption.h"
#include "gmp-api/gmp-video-codec.h"
#include "gmp-api/gmp-platform.h"
-#include "mozilla/StaticPtr.h"
static const GMPPlatformAPI* sPlatform = nullptr;
namespace mozilla {
-StaticRefPtr<CDMWrapper> sCDMWrapper;
-
GMPErr GMPGetCurrentTime(GMPTimestamp* aOutTime) {
return sPlatform->getcurrenttime(aOutTime);
}
// Call on main thread only.
GMPErr GMPSetTimerOnMainThread(GMPTask* aTask, int64_t aTimeoutMS) {
return sPlatform->settimer(aTask, aTimeoutMS);
}
@@ -86,59 +83,59 @@ WidevineAdapter::GMPInit(const GMPPlatfo
}
GMPErr
WidevineAdapter::GMPGetAPI(const char* aAPIName,
void* aHostAPI,
void** aPluginAPI,
uint32_t aDecryptorId)
{
- Log("WidevineAdapter::GMPGetAPI(%s, 0x%p, 0x%p) this=0x%p",
- aAPIName, aHostAPI, aPluginAPI, this);
+ Log("WidevineAdapter::GMPGetAPI(%s, 0x%p, 0x%p, %u) this=0x%p",
+ aAPIName, aHostAPI, aPluginAPI, this, aDecryptorId);
if (!strcmp(aAPIName, GMP_API_DECRYPTOR)) {
- if (sCDMWrapper) {
- // We only support one CDM instance per GMP process. Fail!
- Log("WidevineAdapter::GMPGetAPI() Tried to create more than once CDM per process! FAIL!");
+ if (WidevineDecryptor::GetInstance(aDecryptorId)) {
+ // We only support one CDM instance per PGMPDecryptor. Fail!
+ Log("WidevineAdapter::GMPGetAPI() Tried to create more than once CDM per IPDL actor! FAIL!");
return GMPQuotaExceededErr;
}
auto create = reinterpret_cast<decltype(::CreateCdmInstance)*>(
PR_FindFunctionSymbol(mLib, "CreateCdmInstance"));
if (!create) {
- Log("WidevineAdapter::GMPGetAPI(%s, 0x%p, 0x%p) this=0x%p FAILED to find CreateCdmInstance",
- aAPIName, aHostAPI, aPluginAPI, this);
+ Log("WidevineAdapter::GMPGetAPI(%s, 0x%p, 0x%p, %u) this=0x%p FAILED to find CreateCdmInstance",
+ aAPIName, aHostAPI, aPluginAPI, this, aDecryptorId);
return GMPGenericErr;
}
WidevineDecryptor* decryptor = new WidevineDecryptor();
auto cdm = reinterpret_cast<cdm::ContentDecryptionModule*>(
create(cdm::ContentDecryptionModule::kVersion,
kEMEKeySystemWidevine.get(),
kEMEKeySystemWidevine.Length(),
&GetCdmHost,
decryptor));
if (!cdm) {
- Log("WidevineAdapter::GMPGetAPI(%s, 0x%p, 0x%p) this=0x%p FAILED to create cdm",
- aAPIName, aHostAPI, aPluginAPI, this);
+ Log("WidevineAdapter::GMPGetAPI(%s, 0x%p, 0x%p, %u) this=0x%p FAILED to create cdm",
+ aAPIName, aHostAPI, aPluginAPI, this, aDecryptorId);
return GMPGenericErr;
}
Log("cdm: 0x%x", cdm);
- sCDMWrapper = new CDMWrapper(cdm);
- decryptor->SetCDM(RefPtr<CDMWrapper>(sCDMWrapper));
+ RefPtr<CDMWrapper> wrapper(new CDMWrapper(cdm));
+ decryptor->SetCDM(wrapper, aDecryptorId);
*aPluginAPI = decryptor;
} else if (!strcmp(aAPIName, GMP_API_VIDEO_DECODER)) {
- if (!sCDMWrapper) {
- Log("WidevineAdapter::GMPGetAPI(%s, 0x%p, 0x%p) this=0x%p No cdm for video decoder",
- aAPIName, aHostAPI, aPluginAPI, this);
+ RefPtr<CDMWrapper> wrapper = WidevineDecryptor::GetInstance(aDecryptorId);
+ if (!wrapper) {
+ Log("WidevineAdapter::GMPGetAPI(%s, 0x%p, 0x%p, %u) this=0x%p No cdm for video decoder",
+ aAPIName, aHostAPI, aPluginAPI, thiss, aDecryptorId);
return GMPGenericErr;
}
*aPluginAPI = new WidevineVideoDecoder(static_cast<GMPVideoHost*>(aHostAPI),
- RefPtr<CDMWrapper>(sCDMWrapper));
-
+ wrapper);
}
return *aPluginAPI ? GMPNoErr : GMPNotImplementedErr;
}
void
WidevineAdapter::GMPShutdown()
{
Log("WidevineAdapter::GMPShutdown()");
--- a/dom/media/gmp/widevine-adapter/WidevineDecryptor.cpp
+++ b/dom/media/gmp/widevine-adapter/WidevineDecryptor.cpp
@@ -11,33 +11,48 @@
#include <mozilla/SizePrintfMacros.h>
#include <stdarg.h>
using namespace cdm;
using namespace std;
namespace mozilla {
+static map<uint32_t, RefPtr<CDMWrapper>> sDecryptors;
+
+/* static */
+RefPtr<CDMWrapper>
+WidevineDecryptor::GetInstance(uint32_t aInstanceId)
+{
+ auto itr = sDecryptors.find(aInstanceId);
+ if (itr != sDecryptors.end()) {
+ return itr->second;
+ }
+ return nullptr;
+}
+
WidevineDecryptor::WidevineDecryptor()
: mCallback(nullptr)
{
Log("WidevineDecryptor created this=%p", this);
AddRef(); // Released in DecryptingComplete().
}
WidevineDecryptor::~WidevineDecryptor()
{
Log("WidevineDecryptor destroyed this=%p", this);
}
void
-WidevineDecryptor::SetCDM(RefPtr<CDMWrapper> aCDM)
+WidevineDecryptor::SetCDM(RefPtr<CDMWrapper> aCDM, uint32_t aInstanceId)
{
mCDM = aCDM;
+ mInstanceId = aInstanceId;
+ sDecryptors[mInstanceId] = aCDM;
}
void
WidevineDecryptor::Init(GMPDecryptorCallback* aCallback,
bool aDistinctiveIdentifierRequired,
bool aPersistentStateRequired)
{
Log("WidevineDecryptor::Init() this=%p distinctiveId=%d persistentState=%d",
@@ -205,17 +220,22 @@ WidevineDecryptor::Decrypt(GMPBuffer* aB
}
mCallback->Decrypted(aBuffer, ToGMPErr(rv));
}
void
WidevineDecryptor::DecryptingComplete()
{
Log("WidevineDecryptor::DecryptingComplete() this=%p", this);
+ // Drop our references to the CDMWrapper. When any other references
+ // held elsewhere are dropped (for example references held by a
+ // WidevineVideoDecoder, or a runnable), the CDMWrapper destroys
+ // the CDM.
mCDM = nullptr;
+ sDecryptors.erase(mInstanceId);
mCallback = nullptr;
Release();
}
class WidevineBuffer : public cdm::Buffer {
public:
explicit WidevineBuffer(size_t aSize) {
Log("WidevineBuffer(size=" PRIuSIZE ") created", aSize);
--- a/dom/media/gmp/widevine-adapter/WidevineDecryptor.h
+++ b/dom/media/gmp/widevine-adapter/WidevineDecryptor.h
@@ -19,17 +19,19 @@ class WidevineDecryptor : public GMPDecr
, public cdm::Host_8
{
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WidevineDecryptor)
WidevineDecryptor();
- void SetCDM(RefPtr<CDMWrapper> aCDM);
+ void SetCDM(RefPtr<CDMWrapper> aCDM, uint32_t aDecryptorId);
+
+ static RefPtr<CDMWrapper> GetInstance(uint32_t aDecryptorId);
// GMPDecryptor
void Init(GMPDecryptorCallback* aCallback,
bool aDistinctiveIdentifierRequired,
bool aPersistentStateRequired) override;
void CreateSession(uint32_t aCreateSessionToken,
uint32_t aPromiseId,
@@ -119,13 +121,14 @@ private:
~WidevineDecryptor();
RefPtr<CDMWrapper> mCDM;
cdm::ContentDecryptionModule_8* CDM() { return mCDM->GetCDM(); }
GMPDecryptorCallback* mCallback;
std::map<uint32_t, uint32_t> mPromiseIdToNewSessionTokens;
bool mDistinctiveIdentifierRequired = false;
bool mPersistentStateRequired = false;
+ uint32_t mInstanceId = 0;
};
} // namespace mozilla
#endif // WidevineDecryptor_h_