/* -*- 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 "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; 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) { Log("GetCdmHostFunc(%d, %p)", aHostInterfaceVersion, aUserData); WidevineDecryptor* decryptor = reinterpret_cast(aUserData); MOZ_ASSERT(decryptor); return static_cast(decryptor); } #define STRINGIFY(s) _STRINGIFY(s) #define _STRINGIFY(s) #s GMPErr WidevineAdapter::GMPInit(const GMPPlatformAPI* aPlatformAPI) { #ifdef ENABLE_WIDEVINE_LOG if (getenv("GMP_LOG_FILE")) { // Clear log file. FILE* f = fopen(getenv("GMP_LOG_FILE"), "w"); if (f) { fclose(f); } } #endif sPlatform = aPlatformAPI; if (!mLib) { return GMPGenericErr; } auto init = reinterpret_cast( PR_FindFunctionSymbol(mLib, STRINGIFY(INITIALIZE_CDM_MODULE))); if (!init) { return GMPGenericErr; } Log(STRINGIFY(INITIALIZE_CDM_MODULE)"()"); init(); return GMPNoErr; } GMPErr WidevineAdapter::GMPGetAPI(const char* aAPIName, void* aHostAPI, void** aPluginAPI, uint32_t aDecryptorId) { Log("WidevineAdapter::GMPGetAPI(%s, 0x%p, 0x%p, %u) this=0x%p", aAPIName, aHostAPI, aPluginAPI, this, aDecryptorId); if (!strcmp(aAPIName, GMP_API_DECRYPTOR)) { 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( PR_FindFunctionSymbol(mLib, "CreateCdmInstance")); if (!create) { 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( create(cdm::ContentDecryptionModule::kVersion, kEMEKeySystemWidevine.get(), kEMEKeySystemWidevine.Length(), &GetCdmHost, decryptor)); if (!cdm) { 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); RefPtr wrapper(new CDMWrapper(cdm, decryptor)); decryptor->SetCDM(wrapper, aDecryptorId); *aPluginAPI = decryptor; } else if (!strcmp(aAPIName, GMP_API_VIDEO_DECODER)) { RefPtr 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(aHostAPI), wrapper); } return *aPluginAPI ? GMPNoErr : GMPNotImplementedErr; } void WidevineAdapter::GMPShutdown() { Log("WidevineAdapter::GMPShutdown()"); decltype(::DeinitializeCdmModule)* deinit; deinit = (decltype(deinit))(PR_FindFunctionSymbol(mLib, "DeinitializeCdmModule")); if (deinit) { Log("DeinitializeCdmModule()"); deinit(); } } void WidevineAdapter::GMPSetNodeId(const char* aNodeId, uint32_t aLength) { } /* 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