Bug 1306314 - Use decryptor ID in WidevineAdapter to link decryptors with decoders. r=gerald draft
authorChris Pearce <cpearce@mozilla.com>
Fri, 11 Nov 2016 15:39:10 +1300
changeset 438367 772d4bead18a9b88e7f9ee30b0f169a192322e24
parent 438366 b153d8f7557c0bbf78ed04c01dd11b2400c324a7
child 438368 ebca24d2eeb4acd5fb14e0063cf2065c419853b1
push id35680
push usercpearce@mozilla.com
push dateMon, 14 Nov 2016 09:37:10 +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_