Bug 1306314 - Use decryptor ID in WidevineAdapter to link decryptors with decoders. r=gerald
authorChris Pearce <cpearce@mozilla.com>
Fri, 11 Nov 2016 15:39:10 +1300
changeset 322420 6a563a098351b1c1b2e1e6c2f20ff732b1076b91
parent 322419 e183a3804fbbb6f25228daacf9cf217548ff0129
child 322421 b856b7987192e7e883b6e4d6de19de3e850c4cd9
push id21
push usermaklebus@msu.edu
push dateThu, 01 Dec 2016 06:22:08 +0000
reviewersgerald
bugs1306314
milestone52.0a1
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
dom/media/gmp/widevine-adapter/WidevineAdapter.cpp
dom/media/gmp/widevine-adapter/WidevineDecryptor.cpp
dom/media/gmp/widevine-adapter/WidevineDecryptor.h
--- 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_