--- a/dom/media/gmp/ChromiumCDMAdapter.cpp
+++ b/dom/media/gmp/ChromiumCDMAdapter.cpp
@@ -24,18 +24,17 @@
#include <vector>
#else
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#endif
-// Declared in WidevineAdapter.cpp.
-extern const GMPPlatformAPI* sPlatform;
+const GMPPlatformAPI* sPlatform = nullptr;
namespace mozilla {
#ifdef XP_WIN
static void
InitializeHooks();
#endif
--- a/dom/media/gmp/GMPChild.cpp
+++ b/dom/media/gmp/GMPChild.cpp
@@ -18,17 +18,16 @@
#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 "base/command_line.h"
-#include "widevine-adapter/WidevineAdapter.h"
#include "ChromiumCDMAdapter.h"
#include "GMPLog.h"
using namespace mozilla::ipc;
#ifdef XP_WIN
#include <stdlib.h> // for _exit()
#include "WinUtils.h"
@@ -556,35 +555,31 @@ GMPChild::AnswerStartPlugin(const nsStri
mGMPLoader = MakeUnique<GMPLoader>();
#if defined(MOZ_GMP_SANDBOX)
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 || isChromium) {
+ if (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 = nullptr;
- if (isWidevine) {
- adapter = new WidevineAdapter();
- } else if (isChromium) {
+ if (isChromium) {
auto&& paths = MakeCDMHostVerificationPaths();
GMP_LOG("%s CDM host paths=%s", __func__, ToCString(paths).get());
adapter = new ChromiumCDMAdapter(Move(paths));
}
if (!mGMPLoader->Load(libPath.get(),
libPath.Length(),
platformAPI,
--- a/dom/media/gmp/GMPParent.cpp
+++ b/dom/media/gmp/GMPParent.cpp
@@ -37,17 +37,16 @@ using CrashReporter::GetIDFromMinidump;
#include "mozilla/Telemetry.h"
#ifdef XP_WIN
#include "WMFDecoderModule.h"
#endif
#include "mozilla/dom/WidevineCDMManifestBinding.h"
-#include "widevine-adapter/WidevineAdapter.h"
#include "ChromiumCDMAdapter.h"
namespace mozilla {
#undef LOG
#undef LOGD
extern LogModule* GetGMPLog();
deleted file mode 100644
--- a/dom/media/gmp/widevine-adapter/WidevineAdapter.cpp
+++ /dev/null
@@ -1,159 +0,0 @@
-/* -*- 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 "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"
-
-const GMPPlatformAPI* sPlatform = nullptr;
-
-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)
-{
- mLib = aLib;
-}
-
-void* GetCdmHost(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);
-}
-
-#define STRINGIFY(s) _STRINGIFY(s)
-#define _STRINGIFY(s) #s
-
-GMPErr
-WidevineAdapter::GMPInit(const GMPPlatformAPI* aPlatformAPI)
-{
- sPlatform = aPlatformAPI;
- if (!mLib) {
- return GMPGenericErr;
- }
-
- auto init = reinterpret_cast<decltype(::INITIALIZE_CDM_MODULE)*>(
- PR_FindFunctionSymbol(mLib, STRINGIFY(INITIALIZE_CDM_MODULE)));
- if (!init) {
- return GMPGenericErr;
- }
-
- CDM_LOG(STRINGIFY(INITIALIZE_CDM_MODULE)"()");
- init();
-
- return GMPNoErr;
-}
-
-GMPErr
-WidevineAdapter::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;
- }
- 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);
- return GMPGenericErr;
- }
-
- auto* decryptor = new WidevineDecryptor();
-
- auto cdm = reinterpret_cast<cdm::ContentDecryptionModule_8*>(
- create(cdm::ContentDecryptionModule_8::kVersion,
- kEMEKeySystemWidevine.get(),
- kEMEKeySystemWidevine.Length(),
- &GetCdmHost,
- decryptor));
- if (!cdm) {
- CDM_LOG("WidevineAdapter::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);
- }
- }
- return *aPluginAPI ? GMPNoErr : GMPNotImplementedErr;
-}
-
-void
-WidevineAdapter::GMPShutdown()
-{
- CDM_LOG("WidevineAdapter::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)
-{
- return aModuleVersion == CDM_MODULE_VERSION &&
- aInterfaceVersion == cdm::ContentDecryptionModule::kVersion &&
- aHostVersion == cdm::Host_8::kVersion;
-}
-
-} // namespace mozilla
deleted file mode 100644
--- a/dom/media/gmp/widevine-adapter/WidevineAdapter.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/* -*- 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_
-
-#include "GMPLoader.h"
-#include "prlink.h"
-#include "GMPUtils.h"
-
-struct GMPPlatformAPI;
-
-namespace mozilla {
-
-class WidevineAdapter : 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,
- void** aPluginAPI,
- uint32_t aDecryptorId) override;
- void GMPShutdown() override;
-
- 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_
deleted file mode 100644
--- a/dom/media/gmp/widevine-adapter/WidevineDecryptor.cpp
+++ /dev/null
@@ -1,489 +0,0 @@
-/* -*- 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 "WidevineDecryptor.h"
-
-#include "WidevineAdapter.h"
-#include "WidevineUtils.h"
-#include "WidevineFileIO.h"
-#include <stdarg.h>
-#include "base/time.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)
-{
- CDM_LOG("WidevineDecryptor created this=%p, instanceId=%u", this, mInstanceId);
- AddRef(); // Released in DecryptingComplete().
-}
-
-WidevineDecryptor::~WidevineDecryptor()
-{
- CDM_LOG("WidevineDecryptor destroyed this=%p, instanceId=%u", this, mInstanceId);
-}
-
-void
-WidevineDecryptor::SetCDM(RefPtr<CDMWrapper> aCDM, uint32_t aInstanceId)
-{
- mCDM = aCDM;
- mInstanceId = aInstanceId;
- sDecryptors[mInstanceId] = aCDM.forget();
-}
-
-void
-WidevineDecryptor::Init(GMPDecryptorCallback* aCallback,
- bool aDistinctiveIdentifierRequired,
- bool aPersistentStateRequired)
-{
- CDM_LOG("WidevineDecryptor::Init() this=%p distinctiveId=%d persistentState=%d",
- this, aDistinctiveIdentifierRequired, aPersistentStateRequired);
- MOZ_ASSERT(aCallback);
- mCallback = aCallback;
- MOZ_ASSERT(mCDM);
- mDistinctiveIdentifierRequired = aDistinctiveIdentifierRequired;
- mPersistentStateRequired = aPersistentStateRequired;
- if (CDM()) {
- CDM()->Initialize(aDistinctiveIdentifierRequired,
- aPersistentStateRequired);
- }
-}
-
-static SessionType
-ToCDMSessionType(GMPSessionType aSessionType)
-{
- switch (aSessionType) {
- case kGMPTemporySession: return kTemporary;
- case kGMPPersistentSession: return kPersistentLicense;
- case kGMPSessionInvalid: return kTemporary;
- // TODO: kPersistentKeyRelease
- }
- MOZ_ASSERT(false); // Not supposed to get here.
- return kTemporary;
-}
-
-void
-WidevineDecryptor::CreateSession(uint32_t aCreateSessionToken,
- uint32_t aPromiseId,
- const char* aInitDataType,
- uint32_t aInitDataTypeSize,
- const uint8_t* aInitData,
- uint32_t aInitDataSize,
- GMPSessionType aSessionType)
-{
- CDM_LOG("Decryptor::CreateSession(token=%d, pid=%d)", aCreateSessionToken, aPromiseId);
- InitDataType initDataType;
- if (!strcmp(aInitDataType, "cenc")) {
- initDataType = kCenc;
- } else if (!strcmp(aInitDataType, "webm")) {
- initDataType = kWebM;
- } else if (!strcmp(aInitDataType, "keyids")) {
- initDataType = kKeyIds;
- } else {
- // Invalid init data type
- const char* errorMsg = "Invalid init data type when creating session.";
- OnRejectPromise(aPromiseId, kNotSupportedError, 0, errorMsg, sizeof(errorMsg));
- return;
- }
- mPromiseIdToNewSessionTokens[aPromiseId] = aCreateSessionToken;
- CDM()->CreateSessionAndGenerateRequest(aPromiseId,
- ToCDMSessionType(aSessionType),
- initDataType,
- aInitData, aInitDataSize);
-}
-
-void
-WidevineDecryptor::LoadSession(uint32_t aPromiseId,
- const char* aSessionId,
- uint32_t aSessionIdLength)
-{
- CDM_LOG("Decryptor::LoadSession(pid=%d, %s)", aPromiseId, aSessionId);
- // TODO: session type??
- CDM()->LoadSession(aPromiseId, kPersistentLicense, aSessionId, aSessionIdLength);
-}
-
-void
-WidevineDecryptor::UpdateSession(uint32_t aPromiseId,
- const char* aSessionId,
- uint32_t aSessionIdLength,
- const uint8_t* aResponse,
- uint32_t aResponseSize)
-{
- CDM_LOG("Decryptor::UpdateSession(pid=%d, session=%s)", aPromiseId, aSessionId);
- CDM()->UpdateSession(aPromiseId, aSessionId, aSessionIdLength, aResponse, aResponseSize);
-}
-
-void
-WidevineDecryptor::CloseSession(uint32_t aPromiseId,
- const char* aSessionId,
- uint32_t aSessionIdLength)
-{
- CDM_LOG("Decryptor::CloseSession(pid=%d, session=%s)", aPromiseId, aSessionId);
- CDM()->CloseSession(aPromiseId, aSessionId, aSessionIdLength);
-}
-
-void
-WidevineDecryptor::RemoveSession(uint32_t aPromiseId,
- const char* aSessionId,
- uint32_t aSessionIdLength)
-{
- CDM_LOG("Decryptor::RemoveSession(%s)", aSessionId);
- CDM()->RemoveSession(aPromiseId, aSessionId, aSessionIdLength);
-}
-
-void
-WidevineDecryptor::SetServerCertificate(uint32_t aPromiseId,
- const uint8_t* aServerCert,
- uint32_t aServerCertSize)
-{
- CDM_LOG("Decryptor::SetServerCertificate()");
- CDM()->SetServerCertificate(aPromiseId, aServerCert, aServerCertSize);
-}
-
-void
-WidevineDecryptor::Decrypt(GMPBuffer* aBuffer,
- GMPEncryptedBufferMetadata* aMetadata)
-{
- if (!mCallback) {
- CDM_LOG("WidevineDecryptor::Decrypt() this=%p FAIL; !mCallback", this);
- return;
- }
- const GMPEncryptedBufferMetadata* crypto = aMetadata;
- InputBuffer sample;
- nsTArray<SubsampleEntry> subsamples;
- InitInputBuffer(crypto, aBuffer->Id(), aBuffer->Data(), aBuffer->Size(), sample, subsamples);
- WidevineDecryptedBlock decrypted;
- Status rv = CDM()->Decrypt(sample, &decrypted);
- CDM_LOG("Decryptor::Decrypt(timestamp=%" PRId64 ") rv=%d sz=%d",
- sample.timestamp, rv, decrypted.DecryptedBuffer()->Size());
- if (rv == kSuccess) {
- aBuffer->Resize(decrypted.DecryptedBuffer()->Size());
- memcpy(aBuffer->Data(),
- decrypted.DecryptedBuffer()->Data(),
- decrypted.DecryptedBuffer()->Size());
- }
- mCallback->Decrypted(aBuffer, ToGMPErr(rv));
-}
-
-void
-WidevineDecryptor::DecryptingComplete()
-{
- CDM_LOG("WidevineDecryptor::DecryptingComplete() this=%p, instanceId=%u",
- this, mInstanceId);
- // 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();
-}
-
-Buffer*
-WidevineDecryptor::Allocate(uint32_t aCapacity)
-{
- CDM_LOG("Decryptor::Allocate(capacity=%u)", aCapacity);
- return new WidevineBuffer(aCapacity);
-}
-
-class TimerTask : public GMPTask {
-public:
- TimerTask(WidevineDecryptor* aDecryptor,
- RefPtr<CDMWrapper> aCDM,
- void* aContext)
- : mDecryptor(aDecryptor)
- , mCDM(aCDM)
- , mContext(aContext)
- {
- }
- ~TimerTask() override = default;
- void Run() override {
- mCDM->GetCDM()->TimerExpired(mContext);
- }
- void Destroy() override { delete this; }
-private:
- RefPtr<WidevineDecryptor> mDecryptor;
- RefPtr<CDMWrapper> mCDM;
- void* mContext;
-};
-
-void
-WidevineDecryptor::SetTimer(int64_t aDelayMs, void* aContext)
-{
- CDM_LOG("Decryptor::SetTimer(delay_ms=%" PRId64 ", context=0x%p)", aDelayMs, aContext);
- if (mCDM) {
- GMPSetTimerOnMainThread(new TimerTask(this, mCDM, aContext), aDelayMs);
- }
-}
-
-Time
-WidevineDecryptor::GetCurrentWallTime()
-{
- return base::Time::Now().ToDoubleT();
-}
-
-void
-WidevineDecryptor::OnResolveNewSessionPromise(uint32_t aPromiseId,
- const char* aSessionId,
- uint32_t aSessionIdSize)
-{
- if (!mCallback) {
- CDM_LOG("Decryptor::OnResolveNewSessionPromise(aPromiseId=0x%d) FAIL; !mCallback", aPromiseId);
- return;
- }
-
- // This is laid out in the API. If we fail to load a session we should
- // call OnResolveNewSessionPromise with nullptr as the sessionId.
- // We can safely assume this means that we have failed to load a session
- // as the other methods specify calling 'OnRejectPromise' when they fail.
- if (!aSessionId) {
- CDM_LOG("Decryptor::OnResolveNewSessionPromise(aPromiseId=0x%d) Failed to load session", aPromiseId);
- mCallback->ResolveLoadSessionPromise(aPromiseId, false);
- return;
- }
-
- CDM_LOG("Decryptor::OnResolveNewSessionPromise(aPromiseId=0x%d)", aPromiseId);
- auto iter = mPromiseIdToNewSessionTokens.find(aPromiseId);
- if (iter == mPromiseIdToNewSessionTokens.end()) {
- CDM_LOG("FAIL: Decryptor::OnResolveNewSessionPromise(aPromiseId=%d) unknown aPromiseId", aPromiseId);
- return;
- }
- mCallback->SetSessionId(iter->second, aSessionId, aSessionIdSize);
- mCallback->ResolvePromise(aPromiseId);
- mPromiseIdToNewSessionTokens.erase(iter);
-}
-
-void
-WidevineDecryptor::OnResolvePromise(uint32_t aPromiseId)
-{
- if (!mCallback) {
- CDM_LOG("Decryptor::OnResolvePromise(aPromiseId=0x%d) FAIL; !mCallback", aPromiseId);
- return;
- }
- CDM_LOG("Decryptor::OnResolvePromise(aPromiseId=%d)", aPromiseId);
- mCallback->ResolvePromise(aPromiseId);
-}
-
-static GMPDOMException
-ToGMPDOMException(cdm::Error aError)
-{
- switch (aError) {
- case kNotSupportedError: return kGMPNotSupportedError;
- case kInvalidStateError: return kGMPInvalidStateError;
- case kInvalidAccessError:
- // Note: Chrome converts kInvalidAccessError to TypeError, since the
- // Chromium CDM API doesn't have a type error enum value. The EME spec
- // requires TypeError in some places, so we do the same conversion.
- // See bug 1313202.
- return kGMPTypeError;
- case kQuotaExceededError: return kGMPQuotaExceededError;
- case kUnknownError: return kGMPInvalidModificationError; // Note: Unique placeholder.
- case kClientError: return kGMPAbortError; // Note: Unique placeholder.
- case kOutputError: return kGMPSecurityError; // Note: Unique placeholder.
- };
- return kGMPTimeoutError; // Note: Unique placeholder.
-}
-
-void
-WidevineDecryptor::OnRejectPromise(uint32_t aPromiseId,
- Error aError,
- uint32_t aSystemCode,
- const char* aErrorMessage,
- uint32_t aErrorMessageSize)
-{
- if (!mCallback) {
- CDM_LOG("Decryptor::OnRejectPromise(aPromiseId=%d, err=%d, sysCode=%u, msg=%s) FAIL; !mCallback",
- aPromiseId, (int)aError, aSystemCode, aErrorMessage);
- return;
- }
- CDM_LOG("Decryptor::OnRejectPromise(aPromiseId=%d, err=%d, sysCode=%u, msg=%s)",
- aPromiseId, (int)aError, aSystemCode, aErrorMessage);
- mCallback->RejectPromise(aPromiseId,
- ToGMPDOMException(aError),
- !aErrorMessageSize ? "" : aErrorMessage,
- aErrorMessageSize);
-}
-
-static GMPSessionMessageType
-ToGMPMessageType(MessageType message_type)
-{
- switch (message_type) {
- case kLicenseRequest: return kGMPLicenseRequest;
- case kLicenseRenewal: return kGMPLicenseRenewal;
- case kLicenseRelease: return kGMPLicenseRelease;
- }
- return kGMPMessageInvalid;
-}
-
-void
-WidevineDecryptor::OnSessionMessage(const char* aSessionId,
- uint32_t aSessionIdSize,
- MessageType aMessageType,
- const char* aMessage,
- uint32_t aMessageSize,
- const char* aLegacyDestinationUrl,
- uint32_t aLegacyDestinationUrlLength)
-{
- if (!mCallback) {
- CDM_LOG("Decryptor::OnSessionMessage() FAIL; !mCallback");
- return;
- }
- CDM_LOG("Decryptor::OnSessionMessage()");
- mCallback->SessionMessage(aSessionId,
- aSessionIdSize,
- ToGMPMessageType(aMessageType),
- reinterpret_cast<const uint8_t*>(aMessage),
- aMessageSize);
-}
-
-static GMPMediaKeyStatus
-ToGMPKeyStatus(KeyStatus aStatus)
-{
- switch (aStatus) {
- case kUsable: return kGMPUsable;
- case kInternalError: return kGMPInternalError;
- case kExpired: return kGMPExpired;
- case kOutputRestricted: return kGMPOutputRestricted;
- case kOutputDownscaled: return kGMPOutputDownscaled;
- case kStatusPending: return kGMPStatusPending;
- case kReleased: return kGMPReleased;
- }
- return kGMPUnknown;
-}
-
-void
-WidevineDecryptor::OnSessionKeysChange(const char* aSessionId,
- uint32_t aSessionIdSize,
- bool aHasAdditionalUsableKey,
- const KeyInformation* aKeysInfo,
- uint32_t aKeysInfoCount)
-{
- if (!mCallback) {
- CDM_LOG("Decryptor::OnSessionKeysChange() FAIL; !mCallback");
- return;
- }
- CDM_LOG("Decryptor::OnSessionKeysChange()");
-
- nsTArray<GMPMediaKeyInfo> key_infos;
- for (uint32_t i = 0; i < aKeysInfoCount; i++) {
- key_infos.AppendElement(GMPMediaKeyInfo(aKeysInfo[i].key_id,
- aKeysInfo[i].key_id_size,
- ToGMPKeyStatus(aKeysInfo[i].status)));
- }
- mCallback->BatchedKeyStatusChanged(aSessionId, aSessionIdSize,
- key_infos.Elements(), key_infos.Length());
-}
-
-static GMPTimestamp
-ToGMPTime(Time aCDMTime)
-{
- return static_cast<GMPTimestamp>(aCDMTime * 1000);
-}
-
-void
-WidevineDecryptor::OnExpirationChange(const char* aSessionId,
- uint32_t aSessionIdSize,
- Time aNewExpiryTime)
-{
- if (!mCallback) {
- CDM_LOG("Decryptor::OnExpirationChange(sid=%s) t=%lf FAIL; !mCallback",
- aSessionId, aNewExpiryTime);
- return;
- }
- CDM_LOG("Decryptor::OnExpirationChange(sid=%s) t=%lf", aSessionId, aNewExpiryTime);
- mCallback->ExpirationChange(aSessionId, aSessionIdSize, ToGMPTime(aNewExpiryTime));
-}
-
-void
-WidevineDecryptor::OnSessionClosed(const char* aSessionId,
- uint32_t aSessionIdSize)
-{
- if (!mCallback) {
- CDM_LOG("Decryptor::OnSessionClosed(sid=%s) FAIL; !mCallback", aSessionId);
- return;
- }
- CDM_LOG("Decryptor::OnSessionClosed(sid=%s)", aSessionId);
- mCallback->SessionClosed(aSessionId, aSessionIdSize);
-}
-
-void
-WidevineDecryptor::OnLegacySessionError(const char* aSessionId,
- uint32_t aSessionIdLength,
- Error aError,
- uint32_t aSystemCode,
- const char* aErrorMessage,
- uint32_t aErrorMessageLength)
-{
- if (!mCallback) {
- CDM_LOG("Decryptor::OnLegacySessionError(sid=%s, error=%d) FAIL; !mCallback",
- aSessionId, (int)aError);
- return;
- }
- CDM_LOG("Decryptor::OnLegacySessionError(sid=%s, error=%d)", aSessionId, (int)aError);
- mCallback->SessionError(aSessionId,
- aSessionIdLength,
- ToGMPDOMException(aError),
- aSystemCode,
- aErrorMessage,
- aErrorMessageLength);
-}
-
-void
-WidevineDecryptor::SendPlatformChallenge(const char* aServiceId,
- uint32_t aServiceIdSize,
- const char* aChallenge,
- uint32_t aChallengeSize)
-{
- CDM_LOG("Decryptor::SendPlatformChallenge(service_id=%s)", aServiceId);
-}
-
-void
-WidevineDecryptor::EnableOutputProtection(uint32_t aDesiredProtectionMask)
-{
- CDM_LOG("Decryptor::EnableOutputProtection(mask=0x%x)", aDesiredProtectionMask);
-}
-
-void
-WidevineDecryptor::QueryOutputProtectionStatus()
-{
- CDM_LOG("Decryptor::QueryOutputProtectionStatus()");
-}
-
-void
-WidevineDecryptor::OnDeferredInitializationDone(StreamType aStreamType,
- Status aDecoderStatus)
-{
- CDM_LOG("Decryptor::OnDeferredInitializationDone()");
-}
-
-FileIO*
-WidevineDecryptor::CreateFileIO(FileIOClient* aClient)
-{
- CDM_LOG("Decryptor::CreateFileIO()");
- if (!mPersistentStateRequired) {
- return nullptr;
- }
- return new WidevineFileIO(aClient);
-}
-
-} // namespace mozilla
deleted file mode 100644
--- a/dom/media/gmp/widevine-adapter/WidevineDecryptor.h
+++ /dev/null
@@ -1,134 +0,0 @@
-/* -*- 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 WidevineDecryptor_h_
-#define WidevineDecryptor_h_
-
-#include "stddef.h"
-#include "content_decryption_module.h"
-#include "gmp-api/gmp-decryption.h"
-#include "mozilla/RefPtr.h"
-#include "WidevineUtils.h"
-#include <map>
-
-namespace mozilla {
-
-class WidevineDecryptor : public GMPDecryptor
- , public cdm::Host_8
-{
-public:
-
- NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WidevineDecryptor)
-
- WidevineDecryptor();
-
- 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,
- const char* aInitDataType,
- uint32_t aInitDataTypeSize,
- const uint8_t* aInitData,
- uint32_t aInitDataSize,
- GMPSessionType aSessionType) override;
-
- void LoadSession(uint32_t aPromiseId,
- const char* aSessionId,
- uint32_t aSessionIdLength) override;
-
- void UpdateSession(uint32_t aPromiseId,
- const char* aSessionId,
- uint32_t aSessionIdLength,
- const uint8_t* aResponse,
- uint32_t aResponseSize) override;
-
- void CloseSession(uint32_t aPromiseId,
- const char* aSessionId,
- uint32_t aSessionIdLength) override;
-
- void RemoveSession(uint32_t aPromiseId,
- const char* aSessionId,
- uint32_t aSessionIdLength) override;
-
- void SetServerCertificate(uint32_t aPromiseId,
- const uint8_t* aServerCert,
- uint32_t aServerCertSize) override;
-
- void Decrypt(GMPBuffer* aBuffer,
- GMPEncryptedBufferMetadata* aMetadata) override;
-
- void DecryptingComplete() override;
-
-
- // cdm::Host_8
- cdm::Buffer* Allocate(uint32_t aCapacity) override;
- void SetTimer(int64_t aDelayMs, void* aContext) override;
- cdm::Time GetCurrentWallTime() override;
- void OnResolveNewSessionPromise(uint32_t aPromiseId,
- const char* aSessionId,
- uint32_t aSessionIdSize) override;
- void OnResolvePromise(uint32_t aPromiseId) override;
- void OnRejectPromise(uint32_t aPromiseId,
- cdm::Error aError,
- uint32_t aSystemCode,
- const char* aErrorMessage,
- uint32_t aErrorMessageSize) override;
- void OnSessionMessage(const char* aSessionId,
- uint32_t aSessionIdSize,
- cdm::MessageType aMessageType,
- const char* aMessage,
- uint32_t aMessageSize,
- const char* aLegacyDestinationUrl,
- uint32_t aLegacyDestinationUrlLength) override;
- void OnSessionKeysChange(const char* aSessionId,
- uint32_t aSessionIdSize,
- bool aHasAdditionalUsableKey,
- const cdm::KeyInformation* aKeysInfo,
- uint32_t aKeysInfoCount) override;
- void OnExpirationChange(const char* aSessionId,
- uint32_t aSessionIdSize,
- cdm::Time aNewExpiryTime) override;
- void OnSessionClosed(const char* aSessionId,
- uint32_t aSessionIdSize) override;
- void OnLegacySessionError(const char* aSessionId,
- uint32_t aSessionId_length,
- cdm::Error aError,
- uint32_t aSystemCode,
- const char* aErrorMessage,
- uint32_t aErrorMessageLength) override;
- void SendPlatformChallenge(const char* aServiceId,
- uint32_t aServiceIdSize,
- const char* aChallenge,
- uint32_t aChallengeSize) override;
- void EnableOutputProtection(uint32_t aDesiredProtectionMask) override;
- void QueryOutputProtectionStatus() override;
- void OnDeferredInitializationDone(cdm::StreamType aStreamType,
- cdm::Status aDecoderStatus) override;
- cdm::FileIO* CreateFileIO(cdm::FileIOClient* aClient) override;
-
- GMPDecryptorCallback* Callback() const { return mCallback; }
- RefPtr<CDMWrapper> GetCDMWrapper() const { return mCDM; }
-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_
deleted file mode 100644
--- a/dom/media/gmp/widevine-adapter/WidevineDummyDecoder.cpp
+++ /dev/null
@@ -1,57 +0,0 @@
-#include "WidevineDummyDecoder.h"
-#include "WidevineUtils.h"
-
-using namespace cdm;
-
-namespace mozilla {
-WidevineDummyDecoder::WidevineDummyDecoder()
-{
- CDM_LOG("WidevineDummyDecoder created");
-}
-
-void WidevineDummyDecoder::InitDecode(const GMPVideoCodec & aCodecSettings,
- const uint8_t * aCodecSpecific,
- uint32_t aCodecSpecificLength,
- GMPVideoDecoderCallback * aCallback,
- int32_t aCoreCount)
-{
- CDM_LOG("WidevineDummyDecoder::InitDecode");
-
- mCallback = aCallback;
- mCallback->Error(GMPErr::GMPNotImplementedErr);
-}
-
-void WidevineDummyDecoder::Decode(GMPVideoEncodedFrame * aInputFrame,
- bool aMissingFrames,
- const uint8_t * aCodecSpecificInfo,
- uint32_t aCodecSpecificInfoLength,
- int64_t aRenderTimeMs)
-{
- CDM_LOG("WidevineDummyDecoder::Decode");
- mCallback->Error(GMPErr::GMPNotImplementedErr);
-}
-
-void WidevineDummyDecoder::Reset()
-{
- CDM_LOG("WidevineDummyDecoder::Reset");
- mCallback->Error(GMPErr::GMPNotImplementedErr);
-}
-
-void WidevineDummyDecoder::Drain()
-{
- CDM_LOG("WidevineDummyDecoder::Drain");
- mCallback->Error(GMPErr::GMPNotImplementedErr);
-}
-
-void WidevineDummyDecoder::DecodingComplete()
-{
- CDM_LOG("WidevineDummyDecoder::DecodingComplete");
-
- mCallback = nullptr;
- delete this;
-}
-
-WidevineDummyDecoder::~WidevineDummyDecoder() {
- CDM_LOG("WidevineDummyDecoder destroyed");
-}
-}
\ No newline at end of file
deleted file mode 100644
--- a/dom/media/gmp/widevine-adapter/WidevineDummyDecoder.h
+++ /dev/null
@@ -1,43 +0,0 @@
-#ifndef WidevineDummyDecoder_h_
-#define WidevineDummyDecoder_h_
-
-#include "stddef.h"
-#include "content_decryption_module.h"
-#include "gmp-api/gmp-video-decode.h"
-#include "gmp-api/gmp-video-host.h"
-#include "WidevineDecryptor.h"
-#include "WidevineVideoFrame.h"
-
-
-namespace mozilla {
-
-class WidevineDummyDecoder : public GMPVideoDecoder {
-public:
- WidevineDummyDecoder();
-
- void InitDecode(const GMPVideoCodec& aCodecSettings,
- const uint8_t* aCodecSpecific,
- uint32_t aCodecSpecificLength,
- GMPVideoDecoderCallback* aCallback,
- int32_t aCoreCount) override;
-
- void Decode(GMPVideoEncodedFrame* aInputFrame,
- bool aMissingFrames,
- const uint8_t* aCodecSpecificInfo,
- uint32_t aCodecSpecificInfoLength,
- int64_t aRenderTimeMs = -1) override;
-
- void Reset() override;
-
- void Drain() override;
-
- void DecodingComplete() override;
-
-private:
- ~WidevineDummyDecoder();
-
- GMPVideoDecoderCallback* mCallback;
-};
-}
-
-#endif
\ No newline at end of file
--- a/dom/media/gmp/widevine-adapter/WidevineFileIO.cpp
+++ b/dom/media/gmp/widevine-adapter/WidevineFileIO.cpp
@@ -1,22 +1,24 @@
#include "WidevineFileIO.h"
#include "WidevineUtils.h"
-#include "WidevineAdapter.h"
using namespace cdm;
+// Declared in ChromiumCDMAdapter.cpp.
+extern const GMPPlatformAPI* sPlatform;
+
namespace mozilla {
void
WidevineFileIO::Open(const char* aFilename, uint32_t aFilenameLength)
{
mName = std::string(aFilename, aFilename + aFilenameLength);
GMPRecord* record = nullptr;
- GMPErr err = GMPCreateRecord(aFilename, aFilenameLength, &record, static_cast<GMPRecordClient*>(this));
+ GMPErr err = sPlatform->createrecord(aFilename, aFilenameLength, &record, static_cast<GMPRecordClient*>(this));
if (GMP_FAILED(err)) {
CDM_LOG("WidevineFileIO::Open() '%s' GMPCreateRecord failed", mName.c_str());
mClient->OnOpenComplete(FileIOClient::kError);
return;
}
if (GMP_FAILED(record->Open())) {
CDM_LOG("WidevineFileIO::Open() '%s' record open failed", mName.c_str());
mClient->OnOpenComplete(FileIOClient::kError);
--- a/dom/media/gmp/widevine-adapter/WidevineUtils.cpp
+++ b/dom/media/gmp/widevine-adapter/WidevineUtils.cpp
@@ -1,15 +1,14 @@
/* -*- 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 "WidevineUtils.h"
-#include "WidevineDecryptor.h"
#include "gmp-api/gmp-errors.h"
#include <stdarg.h>
#include <stdio.h>
#include <inttypes.h>
namespace mozilla {
@@ -57,31 +56,16 @@ void InitInputBuffer(const GMPEncryptedB
}
}
aInputBuffer.data = aData;
aInputBuffer.data_size = aDataSize;
aInputBuffer.subsamples = aSubsamples.Elements();
aInputBuffer.timestamp = aTimestamp;
}
-CDMWrapper::CDMWrapper(cdm::ContentDecryptionModule_8* aCDM,
- WidevineDecryptor* aDecryptor)
- : mCDM(aCDM)
- , mDecryptor(aDecryptor)
-{
- MOZ_ASSERT(mCDM);
-}
-
-CDMWrapper::~CDMWrapper()
-{
- CDM_LOG("CDMWrapper destroying CDM=%p", mCDM);
- mCDM->Destroy();
- mCDM = nullptr;
-}
-
WidevineBuffer::WidevineBuffer(size_t aSize)
{
CDM_LOG("WidevineBuffer(size=%zu) created", aSize);
mBuffer.SetLength(aSize);
}
WidevineBuffer::~WidevineBuffer()
{
--- a/dom/media/gmp/widevine-adapter/WidevineUtils.h
+++ b/dom/media/gmp/widevine-adapter/WidevineUtils.h
@@ -34,31 +34,16 @@ LogModule* GetCDMLog();
CDM_LOG("ENSURE_GMP_SUCCESS FAILED %s:%d", __FILE__, __LINE__); \
return rv; \
} \
} \
GMPErr
ToGMPErr(cdm::Status aStatus);
-class WidevineDecryptor;
-
-class CDMWrapper {
-public:
- NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CDMWrapper)
-
- explicit CDMWrapper(cdm::ContentDecryptionModule_8* aCDM,
- WidevineDecryptor* aDecryptor);
- cdm::ContentDecryptionModule_8* GetCDM() const { return mCDM; }
-private:
- ~CDMWrapper();
- cdm::ContentDecryptionModule_8* mCDM;
- RefPtr<WidevineDecryptor> mDecryptor;
-};
-
void InitInputBuffer(const GMPEncryptedBufferMetadata* aCrypto,
int64_t aTimestamp,
const uint8_t* aData,
size_t aDataSize,
cdm::InputBuffer &aInputBuffer,
nsTArray<cdm::SubsampleEntry> &aSubsamples);
namespace gmp {
deleted file mode 100644
--- a/dom/media/gmp/widevine-adapter/WidevineVideoDecoder.cpp
+++ /dev/null
@@ -1,407 +0,0 @@
-/* -*- 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 "WidevineVideoDecoder.h"
-
-#include "WidevineUtils.h"
-#include "WidevineVideoFrame.h"
-#include "mozilla/Move.h"
-#include <inttypes.h>
-
-using namespace cdm;
-
-namespace mozilla {
-
-WidevineVideoDecoder::WidevineVideoDecoder(GMPVideoHost* aVideoHost,
- RefPtr<CDMWrapper> aCDMWrapper)
- : mVideoHost(aVideoHost)
- , mCDMWrapper(Move(aCDMWrapper))
- , mSentInput(false)
- , mCodecType(kGMPVideoCodecInvalid)
- , mReturnOutputCallDepth(0)
- , mDrainPending(false)
- , mResetInProgress(false)
-{
- // Expect to start with a CDM wrapper, will release it in DecodingComplete().
- MOZ_ASSERT(mCDMWrapper);
- CDM_LOG("WidevineVideoDecoder created this=%p", this);
-
- // Corresponding Release is in DecodingComplete().
- AddRef();
-}
-
-WidevineVideoDecoder::~WidevineVideoDecoder()
-{
- CDM_LOG("WidevineVideoDecoder destroyed this=%p", this);
-}
-
-static
-VideoDecoderConfig::VideoCodecProfile
-ToCDMH264Profile(uint8_t aProfile)
-{
- switch (aProfile) {
- case 66: return VideoDecoderConfig::kH264ProfileBaseline;
- case 77: return VideoDecoderConfig::kH264ProfileMain;
- case 88: return VideoDecoderConfig::kH264ProfileExtended;
- case 100: return VideoDecoderConfig::kH264ProfileHigh;
- case 110: return VideoDecoderConfig::kH264ProfileHigh10;
- case 122: return VideoDecoderConfig::kH264ProfileHigh422;
- case 144: return VideoDecoderConfig::kH264ProfileHigh444Predictive;
- }
- return VideoDecoderConfig::kUnknownVideoCodecProfile;
-}
-
-void
-WidevineVideoDecoder::InitDecode(const GMPVideoCodec& aCodecSettings,
- const uint8_t* aCodecSpecific,
- uint32_t aCodecSpecificLength,
- GMPVideoDecoderCallback* aCallback,
- int32_t aCoreCount)
-{
- mCallback = aCallback;
- VideoDecoderConfig config;
- mCodecType = aCodecSettings.mCodecType;
- if (mCodecType == kGMPVideoCodecH264) {
- config.codec = VideoDecoderConfig::kCodecH264;
- const GMPVideoCodecH264* h264 = (const GMPVideoCodecH264*)(aCodecSpecific);
- config.profile = ToCDMH264Profile(h264->mAVCC.mProfile);
- } else if (mCodecType == kGMPVideoCodecVP8) {
- config.codec = VideoDecoderConfig::kCodecVp8;
- config.profile = VideoDecoderConfig::kProfileNotNeeded;
- } else if (mCodecType == kGMPVideoCodecVP9) {
- config.codec = VideoDecoderConfig::kCodecVp9;
- config.profile = VideoDecoderConfig::kProfileNotNeeded;
- } else {
- mCallback->Error(GMPInvalidArgErr);
- return;
- }
- config.format = kYv12;
- config.coded_size = mCodedSize = Size(aCodecSettings.mWidth, aCodecSettings.mHeight);
- nsTArray<uint8_t> extraData;
- if (aCodecSpecificLength > 0) {
- // The first byte is the WebRTC packetization mode, which can be ignored.
- extraData.AppendElements(aCodecSpecific + 1, aCodecSpecificLength - 1);
- config.extra_data = extraData.Elements();
- config.extra_data_size = extraData.Length();
- }
- Status rv = CDM()->InitializeVideoDecoder(config);
- if (rv != kSuccess) {
- mCallback->Error(ToGMPErr(rv));
- return;
- }
- CDM_LOG("WidevineVideoDecoder::InitDecode() rv=%d", rv);
-}
-
-void
-WidevineVideoDecoder::Decode(GMPVideoEncodedFrame* aInputFrame,
- bool aMissingFrames,
- const uint8_t* aCodecSpecificInfo,
- uint32_t aCodecSpecificInfoLength,
- int64_t aRenderTimeMs)
-{
- // We should not be given new input if a drain has been initiated
- MOZ_ASSERT(!mDrainPending);
- // We may not get the same out of the CDM decoder as we put in, and there
- // may be some latency, i.e. we may need to input (say) 30 frames before
- // we receive output. So we need to store the durations of the frames input,
- // and retrieve them on output.
- mFrameDurations[aInputFrame->TimeStamp()] = aInputFrame->Duration();
-
- mSentInput = true;
- InputBuffer sample;
-
- const GMPEncryptedBufferMetadata* crypto = aInputFrame->GetDecryptionData();
- nsTArray<SubsampleEntry> subsamples;
- InitInputBuffer(crypto, aInputFrame->TimeStamp(),
- aInputFrame->Buffer(), aInputFrame->Size(),
- sample, subsamples);
-
- WidevineVideoFrame frame;
- Status rv = CDM()->DecryptAndDecodeFrame(sample, &frame);
- CDM_LOG("WidevineVideoDecoder::Decode(timestamp=%" PRId64 ") rv=%d",
- sample.timestamp, rv);
-
- // Destroy frame, so that the shmem is now free to be used to return
- // output to the Gecko process.
- aInputFrame->Destroy();
- aInputFrame = nullptr;
-
- if (rv == kSuccess || rv == kNoKey) {
- if (rv == kNoKey) {
- CDM_LOG("NoKey for sample at time=%" PRId64 "!", sample.timestamp);
- // Somehow our key became unusable. Typically this would happen when
- // a stream requires output protection, and the configuration changed
- // such that output protection is no longer available. For example, a
- // non-compliant monitor was attached. The JS player should notice the
- // key status changing to "output-restricted", and is supposed to switch
- // to a stream that doesn't require OP. In order to keep the playback
- // pipeline rolling, just output a black frame. See bug 1343140.
- if (!frame.InitToBlack(mCodedSize.width, mCodedSize.height,
- sample.timestamp)) {
- mCallback->Error(GMPDecodeErr);
- return;
- }
- }
- if (!ReturnOutput(frame)) {
- CDM_LOG("WidevineVideoDecoder::Decode() Failed in ReturnOutput()");
- mCallback->Error(GMPDecodeErr);
- return;
- }
- // A reset should only be started at most at level mReturnOutputCallDepth 1,
- // and if it's started it should be finished by that call by the time
- // the it returns, so it should always be false by this point.
- MOZ_ASSERT(!mResetInProgress);
- // Only request more data if we don't have pending samples.
- if (mFrameAllocationQueue.empty()) {
- MOZ_ASSERT(mCDMWrapper);
- mCallback->InputDataExhausted();
- }
- } else if (rv == kNeedMoreData) {
- MOZ_ASSERT(mCDMWrapper);
- mCallback->InputDataExhausted();
- } else {
- mCallback->Error(ToGMPErr(rv));
- }
- // Finish a drain if pending and we have no pending ReturnOutput calls on the
- // stack.
- if (mDrainPending && mReturnOutputCallDepth == 0) {
- Drain();
- }
-}
-
-// Util class to assist with counting mReturnOutputCallDepth.
-class CounterHelper {
-public:
- // RAII, increment counter
- explicit CounterHelper(int32_t& counter)
- : mCounter(counter)
- {
- mCounter++;
- }
-
- // RAII, decrement counter
- ~CounterHelper()
- {
- mCounter--;
- }
-
-private:
- int32_t& mCounter;
-};
-
-// Util class to make sure GMP frames are freed. Holds a GMPVideoi420Frame*
-// and will destroy it when the helper is destroyed unless the held frame
-// if forgotten with ForgetFrame.
-class FrameDestroyerHelper
-{
-public:
- explicit FrameDestroyerHelper(GMPVideoi420Frame*& frame) : frame(frame) { }
-
- // RAII, destroy frame if held.
- ~FrameDestroyerHelper()
- {
- if (frame) {
- frame->Destroy();
- }
- frame = nullptr;
- }
-
- // Forget the frame without destroying it.
- void ForgetFrame()
- {
- frame = nullptr;
- }
-
-private:
- GMPVideoi420Frame* frame;
-};
-
-
-// Special handing is needed around ReturnOutput as it spins the IPC message
-// queue when creating an empty frame and can end up with reentrant calls into
-// the class methods.
-bool
-WidevineVideoDecoder::ReturnOutput(WidevineVideoFrame& aCDMFrame)
-{
- MOZ_ASSERT(mReturnOutputCallDepth >= 0);
- CounterHelper counterHelper(mReturnOutputCallDepth);
- mFrameAllocationQueue.push_back(Move(aCDMFrame));
- if (mReturnOutputCallDepth > 1) {
- // In a reentrant call.
- return true;
- }
- while (!mFrameAllocationQueue.empty()) {
- MOZ_ASSERT(mReturnOutputCallDepth == 1);
- // If we're at call level 1 a reset should not have been started. A
- // reset may be received during CreateEmptyFrame below, but we should not
- // be in a reset at this stage -- this would indicate receiving decode
- // messages before completing our reset, which we should not.
- MOZ_ASSERT(!mResetInProgress);
- WidevineVideoFrame currentCDMFrame = Move(mFrameAllocationQueue.front());
- mFrameAllocationQueue.pop_front();
- GMPVideoFrame* f = nullptr;
- auto err = mVideoHost->CreateFrame(kGMPI420VideoFrame, &f);
- if (GMP_FAILED(err) || !f) {
- CDM_LOG("Failed to create i420 frame!\n");
- return false;
- }
- auto gmpFrame = static_cast<GMPVideoi420Frame*>(f);
- FrameDestroyerHelper frameDestroyerHelper(gmpFrame);
- Size size = currentCDMFrame.Size();
- const int32_t yStride = currentCDMFrame.Stride(VideoFrame::kYPlane);
- const int32_t uStride = currentCDMFrame.Stride(VideoFrame::kUPlane);
- const int32_t vStride = currentCDMFrame.Stride(VideoFrame::kVPlane);
- const int32_t halfHeight = size.height / 2;
- // This call can cause a shmem alloc, during this alloc other calls
- // may be made to this class and placed on the stack. ***WARNING***:
- // other IPC calls can happen during this call, resulting in calls
- // being made to the CDM. After this call state can have changed,
- // and should be reevaluated.
- err = gmpFrame->CreateEmptyFrame(size.width,
- size.height,
- yStride,
- uStride,
- vStride);
- // Assert possible reentrant calls or resets haven't altered level
- // unexpectedly.
- MOZ_ASSERT(mReturnOutputCallDepth == 1);
- ENSURE_GMP_SUCCESS(err, false);
-
- // If a reset started we need to dump the current frame and complete the
- // reset.
- if (mResetInProgress) {
- MOZ_ASSERT(mCDMWrapper);
- MOZ_ASSERT(mFrameAllocationQueue.empty());
- CompleteReset();
- return true;
- }
-
- err = gmpFrame->SetWidth(size.width);
- ENSURE_GMP_SUCCESS(err, false);
-
- err = gmpFrame->SetHeight(size.height);
- ENSURE_GMP_SUCCESS(err, false);
-
- Buffer* buffer = currentCDMFrame.FrameBuffer();
- uint8_t* outBuffer = gmpFrame->Buffer(kGMPYPlane);
- ENSURE_TRUE(outBuffer != nullptr, false);
- MOZ_ASSERT(gmpFrame->AllocatedSize(kGMPYPlane) >= yStride*size.height);
- memcpy(outBuffer,
- buffer->Data() + currentCDMFrame.PlaneOffset(VideoFrame::kYPlane),
- yStride * size.height);
-
- outBuffer = gmpFrame->Buffer(kGMPUPlane);
- ENSURE_TRUE(outBuffer != nullptr, false);
- MOZ_ASSERT(gmpFrame->AllocatedSize(kGMPUPlane) >= uStride * halfHeight);
- memcpy(outBuffer,
- buffer->Data() + currentCDMFrame.PlaneOffset(VideoFrame::kUPlane),
- uStride * halfHeight);
-
- outBuffer = gmpFrame->Buffer(kGMPVPlane);
- ENSURE_TRUE(outBuffer != nullptr, false);
- MOZ_ASSERT(gmpFrame->AllocatedSize(kGMPVPlane) >= vStride * halfHeight);
- memcpy(outBuffer,
- buffer->Data() + currentCDMFrame.PlaneOffset(VideoFrame::kVPlane),
- vStride * halfHeight);
-
- gmpFrame->SetTimestamp(currentCDMFrame.Timestamp());
-
- auto d = mFrameDurations.find(currentCDMFrame.Timestamp());
- if (d != mFrameDurations.end()) {
- gmpFrame->SetDuration(d->second);
- mFrameDurations.erase(d);
- }
-
- // Forget frame so it's not deleted, call back taking ownership.
- frameDestroyerHelper.ForgetFrame();
- mCallback->Decoded(gmpFrame);
- }
-
- return true;
-}
-
-void
-WidevineVideoDecoder::Reset()
-{
- CDM_LOG("WidevineVideoDecoder::Reset() mSentInput=%d", mSentInput);
- // We shouldn't reset if a drain is pending.
- MOZ_ASSERT(!mDrainPending);
- mResetInProgress = true;
- if (mSentInput) {
- CDM()->ResetDecoder(kStreamTypeVideo);
- }
- // Remove queued frames, but do not reset mReturnOutputCallDepth, let the
- // ReturnOutput calls unwind and decrement the counter as needed.
- mFrameAllocationQueue.clear();
- mFrameDurations.clear();
- // Only if no ReturnOutput calls are in progress can we complete, otherwise
- // ReturnOutput needs to finalize the reset.
- if (mReturnOutputCallDepth == 0) {
- CompleteReset();
- }
-}
-
-void
-WidevineVideoDecoder::CompleteReset()
-{
- mCallback->ResetComplete();
- mSentInput = false;
- mResetInProgress = false;
-}
-
-void
-WidevineVideoDecoder::Drain()
-{
- CDM_LOG("WidevineVideoDecoder::Drain()");
- if (mReturnOutputCallDepth > 0) {
- CDM_LOG("Drain call is reentrant, postponing drain");
- mDrainPending = true;
- return;
- }
-
- Status rv = kSuccess;
- while (rv == kSuccess) {
- WidevineVideoFrame frame;
- InputBuffer sample;
- Status rv = CDM()->DecryptAndDecodeFrame(sample, &frame);
- CDM_LOG("WidevineVideoDecoder::Drain(); DecryptAndDecodeFrame() rv=%d", rv);
- if (frame.Format() == kUnknownVideoFormat) {
- break;
- }
- if (rv == kSuccess) {
- if (!ReturnOutput(frame)) {
- CDM_LOG("WidevineVideoDecoder::Decode() Failed in ReturnOutput()");
- }
- }
- }
- // Shouldn't be reset while draining.
- MOZ_ASSERT(!mResetInProgress);
-
- CDM()->ResetDecoder(kStreamTypeVideo);
- mDrainPending = false;
- mCallback->DrainComplete();
-}
-
-void
-WidevineVideoDecoder::DecodingComplete()
-{
- CDM_LOG("WidevineVideoDecoder::DecodingComplete()");
-
- if (mCDMWrapper) {
- // mCallback will be null if the decoder has not been fully initialized.
- if (mCallback) {
- CDM()->DeinitializeDecoder(kStreamTypeVideo);
- } else {
- CDM_LOG("WideVineDecoder::DecodingComplete() Decoder was not fully initialized!");
- }
-
- mCDMWrapper = nullptr;
- }
-
- // Release that corresponds to AddRef() in constructor.
- Release();
-}
-
-} // namespace mozilla
deleted file mode 100644
--- a/dom/media/gmp/widevine-adapter/WidevineVideoDecoder.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/* -*- 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 WidevineVideoDecoder_h_
-#define WidevineVideoDecoder_h_
-
-#include "stddef.h"
-#include "content_decryption_module.h"
-#include "gmp-api/gmp-video-decode.h"
-#include "gmp-api/gmp-video-host.h"
-#include "MediaData.h"
-#include "nsISupportsImpl.h"
-#include "nsTArray.h"
-#include "WidevineDecryptor.h"
-#include "WidevineVideoFrame.h"
-#include <map>
-#include <deque>
-
-namespace mozilla {
-
-class WidevineVideoDecoder : public GMPVideoDecoder
-{
-public:
-
- NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WidevineVideoDecoder)
-
- WidevineVideoDecoder(GMPVideoHost* aVideoHost,
- RefPtr<CDMWrapper> aCDMWrapper);
- void InitDecode(const GMPVideoCodec& aCodecSettings,
- const uint8_t* aCodecSpecific,
- uint32_t aCodecSpecificLength,
- GMPVideoDecoderCallback* aCallback,
- int32_t aCoreCount) override;
- void Decode(GMPVideoEncodedFrame* aInputFrame,
- bool aMissingFrames,
- const uint8_t* aCodecSpecificInfo,
- uint32_t aCodecSpecificInfoLength,
- int64_t aRenderTimeMs = -1) override;
- void Reset() override;
- void Drain() override;
- void DecodingComplete() override;
-
-private:
-
- ~WidevineVideoDecoder();
-
- cdm::ContentDecryptionModule_8* CDM() const
- {
- // CDM should only be accessed before 'DecodingComplete'.
- MOZ_ASSERT(mCDMWrapper);
- // CDMWrapper ensure the CDM is non-null, no need to check again.
- return mCDMWrapper->GetCDM();
- }
-
- bool ReturnOutput(WidevineVideoFrame& aFrame);
- void CompleteReset();
-
- GMPVideoHost* mVideoHost;
- RefPtr<CDMWrapper> mCDMWrapper;
- GMPVideoDecoderCallback* mCallback = nullptr;
- std::map<uint64_t, uint64_t> mFrameDurations;
- bool mSentInput;
- GMPVideoCodecType mCodecType;
- // Frames waiting on allocation
- std::deque<WidevineVideoFrame> mFrameAllocationQueue;
- // Number of calls of ReturnOutput currently in progress.
- int32_t mReturnOutputCallDepth;
- // If we're waiting to drain. Used to prevent drain completing while
- // ReturnOutput calls are still on the stack.
- bool mDrainPending;
- // If a reset is being performed. Used to track if ReturnOutput should
- // dump current frame.
- bool mResetInProgress;
- cdm::Size mCodedSize;
-};
-
-} // namespace mozilla
-
-#endif // WidevineVideoDecoder_h_
--- a/dom/media/gmp/widevine-adapter/moz.build
+++ b/dom/media/gmp/widevine-adapter/moz.build
@@ -1,26 +1,21 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
SOURCES += [
- 'WidevineAdapter.cpp',
- 'WidevineDecryptor.cpp',
- 'WidevineDummyDecoder.cpp',
'WidevineFileIO.cpp',
'WidevineUtils.cpp',
- 'WidevineVideoDecoder.cpp',
'WidevineVideoFrame.cpp',
]
EXPORTS += [
- 'WidevineDecryptor.h',
'WidevineFileIO.h',
'WidevineUtils.h',
'WidevineVideoFrame.h'
]
FINAL_LIBRARY = 'xul'
LOCAL_INCLUDES += [