Bug 1315850 - Add ChromiumAdapter which we can use instead of WidevineAdapter. r=gerald
We currently use an adapter object to adapt plugins that don't conform to the
GMP interface to the GMP interface.
We use the WidevineAdapter to talk to the CDM from the two GMP IPDL protocols.
We will be using a single protocol to talk to the Chromium CDM, so we need a
new adapter which handles that.
MozReview-Commit-ID: F7hnZ9oo9mJ
copy from dom/media/gmp/widevine-adapter/WidevineAdapter.cpp
copy to dom/media/gmp/ChromiumCDMAdapter.cpp
--- a/dom/media/gmp/widevine-adapter/WidevineAdapter.cpp
+++ b/dom/media/gmp/ChromiumCDMAdapter.cpp
@@ -1,66 +1,51 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-#include "WidevineAdapter.h"
+#include "ChromiumCDMAdapter.h"
#include "content_decryption_module.h"
#include "VideoUtils.h"
-#include "WidevineDecryptor.h"
-#include "WidevineDummyDecoder.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 "WidevineUtils.h"
+#include "GMPLog.h"
-static const GMPPlatformAPI* sPlatform = nullptr;
+// Declared in WidevineAdapter.cpp.
+extern const GMPPlatformAPI* sPlatform;
namespace mozilla {
-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);
-}
-
-GMPErr GMPCreateRecord(const char* aRecordName,
- uint32_t aRecordNameSize,
- GMPRecord** aOutRecord,
- GMPRecordClient* aClient)
-{
- return sPlatform->createrecord(aRecordName, aRecordNameSize, aOutRecord, aClient);
-}
-
void
-WidevineAdapter::SetAdaptee(PRLibrary* aLib)
+ChromiumCDMAdapter::SetAdaptee(PRLibrary* aLib)
{
mLib = aLib;
}
-void* GetCdmHost(int aHostInterfaceVersion, void* aUserData)
+void*
+ChromiumCdmHost(int aHostInterfaceVersion, void* aUserData)
{
- CDM_LOG("GetCdmHostFunc(%d, %p)", aHostInterfaceVersion, aUserData);
- WidevineDecryptor* decryptor = reinterpret_cast<WidevineDecryptor*>(aUserData);
- MOZ_ASSERT(decryptor);
- return static_cast<cdm::Host_8*>(decryptor);
+ CDM_LOG("ChromiumCdmHostFunc(%d, %p)", aHostInterfaceVersion, aUserData);
+ if (aHostInterfaceVersion != cdm::Host_8::kVersion) {
+ return nullptr;
+ }
+ return static_cast<cdm::Host_8*>(aUserData);
}
#define STRINGIFY(s) _STRINGIFY(s)
#define _STRINGIFY(s) #s
GMPErr
-WidevineAdapter::GMPInit(const GMPPlatformAPI* aPlatformAPI)
+ChromiumCDMAdapter::GMPInit(const GMPPlatformAPI* aPlatformAPI)
{
+ CDM_LOG("ChromiumCDMAdapter::GMPInit");
sPlatform = aPlatformAPI;
if (!mLib) {
return GMPGenericErr;
}
auto init = reinterpret_cast<decltype(::INITIALIZE_CDM_MODULE)*>(
PR_FindFunctionSymbol(mLib, STRINGIFY(INITIALIZE_CDM_MODULE)));
if (!init) {
@@ -69,91 +54,80 @@ WidevineAdapter::GMPInit(const GMPPlatfo
CDM_LOG(STRINGIFY(INITIALIZE_CDM_MODULE)"()");
init();
return GMPNoErr;
}
GMPErr
-WidevineAdapter::GMPGetAPI(const char* aAPIName,
- void* aHostAPI,
- void** aPluginAPI,
- uint32_t aDecryptorId)
+ChromiumCDMAdapter::GMPGetAPI(const char* aAPIName,
+ void* aHostAPI,
+ void** aPluginAPI,
+ uint32_t aDecryptorId)
{
- CDM_LOG("WidevineAdapter::GMPGetAPI(%s, 0x%p, 0x%p, %u) this=0x%p",
- aAPIName, aHostAPI, aPluginAPI, aDecryptorId, this);
- if (!strcmp(aAPIName, GMP_API_DECRYPTOR)) {
- if (WidevineDecryptor::GetInstance(aDecryptorId)) {
- // We only support one CDM instance per PGMPDecryptor. Fail!
- CDM_LOG("WidevineAdapter::GMPGetAPI() Tried to create more than once CDM per IPDL actor! FAIL!");
- return GMPQuotaExceededErr;
- }
+ CDM_LOG("ChromiumCDMAdapter::GMPGetAPI(%s, 0x%p, 0x%p, %u) this=0x%p",
+ aAPIName,
+ aHostAPI,
+ aPluginAPI,
+ aDecryptorId,
+ this);
+ if (!strcmp(aAPIName, CHROMIUM_CDM_API)) {
auto create = reinterpret_cast<decltype(::CreateCdmInstance)*>(
PR_FindFunctionSymbol(mLib, "CreateCdmInstance"));
if (!create) {
- CDM_LOG("WidevineAdapter::GMPGetAPI(%s, 0x%p, 0x%p, %u) this=0x%p FAILED to find CreateCdmInstance",
- aAPIName, aHostAPI, aPluginAPI, aDecryptorId, this);
+ CDM_LOG("ChromiumCDMAdapter::GMPGetAPI(%s, 0x%p, 0x%p, %u) this=0x%p "
+ "FAILED to find CreateCdmInstance",
+ aAPIName,
+ aHostAPI,
+ aPluginAPI,
+ aDecryptorId,
+ this);
return GMPGenericErr;
}
- auto* decryptor = new WidevineDecryptor();
-
auto cdm = reinterpret_cast<cdm::ContentDecryptionModule*>(
create(cdm::ContentDecryptionModule::kVersion,
kEMEKeySystemWidevine.get(),
kEMEKeySystemWidevine.Length(),
- &GetCdmHost,
- decryptor));
+ &ChromiumCdmHost,
+ aHostAPI));
if (!cdm) {
- CDM_LOG("WidevineAdapter::GMPGetAPI(%s, 0x%p, 0x%p, %u) this=0x%p FAILED to create cdm",
- aAPIName, aHostAPI, aPluginAPI, aDecryptorId, this);
+ CDM_LOG("ChromiumCDMAdapter::GMPGetAPI(%s, 0x%p, 0x%p, %u) this=0x%p "
+ "FAILED to create cdm",
+ aAPIName,
+ aHostAPI,
+ aPluginAPI,
+ aDecryptorId,
+ this);
return GMPGenericErr;
}
CDM_LOG("cdm: 0x%p", cdm);
- RefPtr<CDMWrapper> wrapper(new CDMWrapper(cdm, decryptor));
- decryptor->SetCDM(wrapper, aDecryptorId);
- *aPluginAPI = decryptor;
-
- } else if (!strcmp(aAPIName, GMP_API_VIDEO_DECODER)) {
- RefPtr<CDMWrapper> wrapper = WidevineDecryptor::GetInstance(aDecryptorId);
-
- // There is a possible race condition, where the decryptor will be destroyed
- // before we are able to create the video decoder, so we create a dummy
- // decoder to avoid crashing.
- if (!wrapper) {
- CDM_LOG("WidevineAdapter::GMPGetAPI(%s, 0x%p, 0x%p, %u) this=0x%p No cdm for video decoder. Using a DummyDecoder",
- aAPIName, aHostAPI, aPluginAPI, aDecryptorId, this);
-
- *aPluginAPI = new WidevineDummyDecoder();
- } else {
- *aPluginAPI = new WidevineVideoDecoder(static_cast<GMPVideoHost*>(aHostAPI),
- wrapper);
- }
+ *aPluginAPI = cdm;
}
return *aPluginAPI ? GMPNoErr : GMPNotImplementedErr;
}
void
-WidevineAdapter::GMPShutdown()
+ChromiumCDMAdapter::GMPShutdown()
{
- CDM_LOG("WidevineAdapter::GMPShutdown()");
+ CDM_LOG("ChromiumCDMAdapter::GMPShutdown()");
decltype(::DeinitializeCdmModule)* deinit;
deinit = (decltype(deinit))(PR_FindFunctionSymbol(mLib, "DeinitializeCdmModule"));
if (deinit) {
CDM_LOG("DeinitializeCdmModule()");
deinit();
}
}
/* static */
bool
-WidevineAdapter::Supports(int32_t aModuleVersion,
- int32_t aInterfaceVersion,
- int32_t aHostVersion)
+ChromiumCDMAdapter::Supports(int32_t aModuleVersion,
+ int32_t aInterfaceVersion,
+ int32_t aHostVersion)
{
return aModuleVersion == CDM_MODULE_VERSION &&
aInterfaceVersion == cdm::ContentDecryptionModule::kVersion &&
aHostVersion == cdm::Host_8::kVersion;
}
} // namespace mozilla
copy from dom/media/gmp/widevine-adapter/WidevineAdapter.h
copy to dom/media/gmp/ChromiumCDMAdapter.h
--- a/dom/media/gmp/widevine-adapter/WidevineAdapter.h
+++ b/dom/media/gmp/ChromiumCDMAdapter.h
@@ -1,25 +1,26 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-#ifndef WidevineAdapter_h_
-#define WidevineAdapter_h_
+#ifndef ChromiumAdapter_h_
+#define ChromiumAdapter_h_
#include "GMPLoader.h"
#include "prlink.h"
#include "GMPUtils.h"
struct GMPPlatformAPI;
namespace mozilla {
-class WidevineAdapter : public gmp::GMPAdapter {
+class ChromiumCDMAdapter : public gmp::GMPAdapter
+{
public:
void SetAdaptee(PRLibrary* aLib) override;
// These are called in place of the corresponding GMP API functions.
GMPErr GMPInit(const GMPPlatformAPI* aPlatformAPI) override;
GMPErr GMPGetAPI(const char* aAPIName,
void* aHostAPI,
@@ -30,26 +31,11 @@ public:
static bool Supports(int32_t aModuleVersion,
int32_t aInterfaceVersion,
int32_t aHostVersion);
private:
PRLibrary* mLib = nullptr;
};
-GMPErr GMPCreateThread(GMPThread** aThread);
-GMPErr GMPRunOnMainThread(GMPTask* aTask);
-GMPErr GMPCreateMutex(GMPMutex** aMutex);
-
-// Call on main thread only.
-GMPErr GMPCreateRecord(const char* aRecordName,
- uint32_t aRecordNameSize,
- GMPRecord** aOutRecord,
- GMPRecordClient* aClient);
-
-// Call on main thread only.
-GMPErr GMPSetTimerOnMainThread(GMPTask* aTask, int64_t aTimeoutMS);
-
-GMPErr GMPGetCurrentTime(GMPTimestamp* aOutTime);
-
} // namespace mozilla
-#endif // WidevineAdapter_h_
+#endif // ChromiumAdapter_h_
--- a/dom/media/gmp/ChromiumCDMChild.cpp
+++ b/dom/media/gmp/ChromiumCDMChild.cpp
@@ -9,16 +9,23 @@
namespace mozilla {
namespace gmp {
ChromiumCDMChild::ChromiumCDMChild(GMPContentChild* aPlugin)
: mPlugin(aPlugin)
{
}
+void
+ChromiumCDMChild::Init(cdm::ContentDecryptionModule_8* aCDM)
+{
+ mCDM = aCDM;
+ MOZ_ASSERT(mCDM);
+}
+
mozilla::ipc::IPCResult
ChromiumCDMChild::RecvInit(const bool& aAllowDistinctiveIdentifier,
const bool& aAllowPersistentState)
{
return IPC_OK();
}
mozilla::ipc::IPCResult
--- a/dom/media/gmp/ChromiumCDMChild.h
+++ b/dom/media/gmp/ChromiumCDMChild.h
@@ -15,16 +15,17 @@ class GMPContentChild;
class ChromiumCDMChild : public PChromiumCDMChild
{
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ChromiumCDMChild);
explicit ChromiumCDMChild(GMPContentChild* aPlugin);
+ void Init(cdm::ContentDecryptionModule_8* aCDM);
protected:
~ChromiumCDMChild() {}
ipc::IPCResult RecvInit(const bool& aAllowDistinctiveIdentifier,
const bool& aAllowPersistentState) override;
ipc::IPCResult RecvSetServerCertificate(
const uint32_t& aPromiseId,
nsTArray<uint8_t>&& aServerCert) override;
@@ -44,15 +45,16 @@ protected:
ipc::IPCResult RecvInitializeVideoDecoder(
const CDMVideoDecoderConfig& aConfig) override;
ipc::IPCResult RecvDeinitializeVideoDecoder() override;
ipc::IPCResult RecvResetVideoDecoder() override;
ipc::IPCResult RecvDecryptAndDecodeFrame(
const CDMInputBuffer& aBuffer) override;
ipc::IPCResult RecvDestroy() override;
- GMPContentChild* mPlugin;
+ GMPContentChild* mPlugin = nullptr;
+ cdm::ContentDecryptionModule_8* mCDM = nullptr;
};
} // namespace gmp
} // namespace mozilla
#endif // ChromiumCDMChild_h_
--- a/dom/media/gmp/GMPChild.cpp
+++ b/dom/media/gmp/GMPChild.cpp
@@ -18,16 +18,17 @@
#include "gmp-video-encode.h"
#include "GMPPlatform.h"
#include "mozilla/ipc/CrashReporterClient.h"
#include "mozilla/ipc/ProcessChild.h"
#include "GMPUtils.h"
#include "prio.h"
#include "base/task.h"
#include "widevine-adapter/WidevineAdapter.h"
+#include "ChromiumCDMAdapter.h"
using namespace mozilla::ipc;
#ifdef XP_WIN
#include <stdlib.h> // for _exit()
#else
#include <unistd.h> // for _exit()
#endif
@@ -341,29 +342,36 @@ GMPChild::AnswerStartPlugin(const nsStri
if (!mGMPLoader->CanSandbox()) {
LOGD("%s Can't sandbox GMP, failing", __FUNCTION__);
delete platformAPI;
return IPC_FAIL_NO_REASON(this);
}
#endif
bool isWidevine = aAdapter.EqualsLiteral("widevine");
+ bool isChromium = aAdapter.EqualsLiteral("chromium");
#if defined(MOZ_GMP_SANDBOX) && defined(XP_MACOSX)
MacSandboxPluginType pluginType = MacSandboxPluginType_GMPlugin_Default;
- if (isWidevine) {
+ if (isWidevine || isChromium) {
pluginType = MacSandboxPluginType_GMPlugin_EME_Widevine;
}
if (!SetMacSandboxInfo(pluginType)) {
NS_WARNING("Failed to set Mac GMP sandbox info");
delete platformAPI;
return IPC_FAIL_NO_REASON(this);
}
#endif
- GMPAdapter* adapter = (isWidevine) ? new WidevineAdapter() : nullptr;
+ GMPAdapter* adapter = nullptr;
+ if (isWidevine) {
+ adapter = new WidevineAdapter();
+ } else if (isChromium) {
+ adapter = new ChromiumCDMAdapter();
+ }
+
if (!mGMPLoader->Load(libPath.get(),
libPath.Length(),
platformAPI,
adapter)) {
NS_WARNING("Failed to load GMP");
delete platformAPI;
return IPC_FAIL_NO_REASON(this);
}
--- a/dom/media/gmp/GMPContentChild.cpp
+++ b/dom/media/gmp/GMPContentChild.cpp
@@ -158,17 +158,28 @@ GMPContentChild::RecvPGMPVideoEncoderCon
vec->Init(static_cast<GMPVideoEncoder*>(ve));
return IPC_OK();
}
mozilla::ipc::IPCResult
GMPContentChild::RecvPChromiumCDMConstructor(PChromiumCDMChild* aActor)
{
- // TODO: Implement.
+ ChromiumCDMChild* child = static_cast<ChromiumCDMChild*>(aActor);
+ cdm::Host_8* host = child;
+
+ void* cdm = nullptr;
+ GMPErr err = mGMPChild->GetAPI(CHROMIUM_CDM_API, host, &cdm);
+ if (err != GMPNoErr || !cdm) {
+ NS_WARNING("GMPGetAPI call failed trying to get CDM.");
+ return IPC_FAIL_NO_REASON(this);
+ }
+
+ child->Init(static_cast<cdm::ContentDecryptionModule_8*>(cdm));
+
return IPC_OK();
}
void
GMPContentChild::CloseActive()
{
// Invalidate and remove any remaining API objects.
const ManagedContainer<PGMPDecryptorChild>& decryptors =
--- a/dom/media/gmp/moz.build
+++ b/dom/media/gmp/moz.build
@@ -64,16 +64,17 @@ EXPORTS += [
'GMPVideoEncoderProxy.h',
'GMPVideoHost.h',
'GMPVideoi420FrameImpl.h',
'GMPVideoPlaneImpl.h',
'widevine-adapter/content_decryption_module.h',
]
UNIFIED_SOURCES += [
+ 'ChromiumCDMAdapter.cpp',
'ChromiumCDMChild.cpp',
'ChromiumCDMParent.cpp',
'DecryptJob.cpp',
'GMPCDMCallbackProxy.cpp',
'GMPCDMProxy.cpp',
'GMPChild.cpp',
'GMPContentChild.cpp',
'GMPContentParent.cpp',
--- a/dom/media/gmp/widevine-adapter/WidevineAdapter.cpp
+++ b/dom/media/gmp/widevine-adapter/WidevineAdapter.cpp
@@ -10,17 +10,17 @@
#include "WidevineDummyDecoder.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"
-static const GMPPlatformAPI* sPlatform = nullptr;
+const GMPPlatformAPI* sPlatform = nullptr;
namespace mozilla {
GMPErr GMPGetCurrentTime(GMPTimestamp* aOutTime) {
return sPlatform->getcurrenttime(aOutTime);
}
// Call on main thread only.