Source code
Revision control
Copy as Markdown
Other Tools
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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
#include "ClearKeyCDM.h"
#include "ClearKeyUtils.h"
using namespace cdm;
ClearKeyCDM::ClearKeyCDM(Host_10* aHost) {
mHost = aHost;
mSessionManager = new ClearKeySessionManager(mHost);
}
void ClearKeyCDM::Initialize(bool aAllowDistinctiveIdentifier,
bool aAllowPersistentState,
bool aUseHardwareSecureCodecs) {
mSessionManager->Init(aAllowDistinctiveIdentifier, aAllowPersistentState);
// We call mHost->OnInitialized() in the session manager once it has
// initialized.
}
void ClearKeyCDM::GetStatusForPolicy(uint32_t aPromiseId,
const Policy& aPolicy) {
// Pretend the device is HDCP 2.1 compliant.
const cdm::HdcpVersion kDeviceHdcpVersion = cdm::kHdcpVersion2_1;
if (aPolicy.min_hdcp_version <= kDeviceHdcpVersion) {
mHost->OnResolveKeyStatusPromise(aPromiseId, KeyStatus::kUsable);
} else {
mHost->OnResolveKeyStatusPromise(aPromiseId, KeyStatus::kOutputRestricted);
}
}
void ClearKeyCDM::SetServerCertificate(uint32_t aPromiseId,
const uint8_t* aServerCertificateData,
uint32_t aServerCertificateDataSize) {
mSessionManager->SetServerCertificate(aPromiseId, aServerCertificateData,
aServerCertificateDataSize);
}
void ClearKeyCDM::CreateSessionAndGenerateRequest(uint32_t aPromiseId,
SessionType aSessionType,
InitDataType aInitDataType,
const uint8_t* aInitData,
uint32_t aInitDataSize) {
mSessionManager->CreateSession(aPromiseId, aInitDataType, aInitData,
aInitDataSize, aSessionType);
}
void ClearKeyCDM::LoadSession(uint32_t aPromiseId, SessionType aSessionType,
const char* aSessionId, uint32_t aSessionIdSize) {
mSessionManager->LoadSession(aPromiseId, aSessionId, aSessionIdSize);
}
void ClearKeyCDM::UpdateSession(uint32_t aPromiseId, const char* aSessionId,
uint32_t aSessionIdSize,
const uint8_t* aResponse,
uint32_t aResponseSize) {
mSessionManager->UpdateSession(aPromiseId, aSessionId, aSessionIdSize,
aResponse, aResponseSize);
}
void ClearKeyCDM::CloseSession(uint32_t aPromiseId, const char* aSessionId,
uint32_t aSessionIdSize) {
mSessionManager->CloseSession(aPromiseId, aSessionId, aSessionIdSize);
}
void ClearKeyCDM::RemoveSession(uint32_t aPromiseId, const char* aSessionId,
uint32_t aSessionIdSize) {
mSessionManager->RemoveSession(aPromiseId, aSessionId, aSessionIdSize);
}
void ClearKeyCDM::TimerExpired(void* aContext) {
// Clearkey is not interested in timers, so this method has not been
// implemented.
assert(false);
}
Status ClearKeyCDM::Decrypt(const InputBuffer_2& aEncryptedBuffer,
DecryptedBlock* aDecryptedBuffer) {
if (mIsProtectionQueryEnabled) {
// Piggyback this check onto Decrypt calls. If Clearkey implements a timer
// based approach for firing events, we could instead trigger the check
// using that mechanism.
mSessionManager->QueryOutputProtectionStatusIfNeeded();
}
return mSessionManager->Decrypt(aEncryptedBuffer, aDecryptedBuffer);
}
Status ClearKeyCDM::InitializeAudioDecoder(
const AudioDecoderConfig_2& aAudioDecoderConfig) {
// Audio decoding is not supported by Clearkey because Widevine doesn't
// support it and Clearkey's raison d'etre is to provide test coverage
// for paths that Widevine will exercise in the wild.
return Status::kDecodeError;
}
Status ClearKeyCDM::InitializeVideoDecoder(
const VideoDecoderConfig_2& aVideoDecoderConfig) {
#ifdef ENABLE_WMF
mVideoDecoder = new VideoDecoder(mHost);
return mVideoDecoder->InitDecode(aVideoDecoderConfig);
#else
return Status::kDecodeError;
#endif
}
void ClearKeyCDM::DeinitializeDecoder(StreamType aDecoderType) {
#ifdef ENABLE_WMF
if (aDecoderType == StreamType::kStreamTypeVideo) {
mVideoDecoder->DecodingComplete();
mVideoDecoder = nullptr;
}
#endif
}
void ClearKeyCDM::ResetDecoder(StreamType aDecoderType) {
#ifdef ENABLE_WMF
if (aDecoderType == StreamType::kStreamTypeVideo) {
mVideoDecoder->Reset();
}
#endif
}
Status ClearKeyCDM::DecryptAndDecodeFrame(const InputBuffer_2& aEncryptedBuffer,
VideoFrame* aVideoFrame) {
#ifdef ENABLE_WMF
if (mIsProtectionQueryEnabled) {
// Piggyback this check onto Decrypt + Decode. If Clearkey implements a
// timer based approach for firing events, we could instead trigger the
// check using that mechanism.
mSessionManager->QueryOutputProtectionStatusIfNeeded();
}
return mVideoDecoder->Decode(aEncryptedBuffer, aVideoFrame);
#else
return Status::kDecodeError;
#endif
}
Status ClearKeyCDM::DecryptAndDecodeSamples(
const InputBuffer_2& aEncryptedBuffer, AudioFrames* aAudioFrame) {
// Audio decoding is not supported by Clearkey because Widevine doesn't
// support it and Clearkey's raison d'etre is to provide test coverage
// for paths that Widevine will exercise in the wild.
return Status::kDecodeError;
}
void ClearKeyCDM::OnPlatformChallengeResponse(
const PlatformChallengeResponse& aResponse) {
// This function should never be called and is not supported.
assert(false);
}
void ClearKeyCDM::OnQueryOutputProtectionStatus(
QueryResult aResult, uint32_t aLinkMask, uint32_t aOutputProtectionMask) {
// The higher level GMP machinery should not forward us query information
// unless we've requested it (even if mutiple CDMs exist at once and some
// others are reqeusting this info). If this assert fires we're violating
// that.
MOZ_ASSERT(mIsProtectionQueryEnabled,
"Should only receive a protection status "
"mIsProtectionQueryEnabled is true");
// The session manager handles the guts of this for ClearKey.
mSessionManager->OnQueryOutputProtectionStatus(aResult, aLinkMask,
aOutputProtectionMask);
}
void ClearKeyCDM::OnStorageId(uint32_t aVersion, const uint8_t* aStorageId,
uint32_t aStorageIdSize) {
// This function should never be called and is not supported.
assert(false);
}
void ClearKeyCDM::Destroy() {
mSessionManager->DecryptingComplete();
#ifdef ENABLE_WMF
// If we have called 'DeinitializeDecoder' mVideoDecoder will be null.
if (mVideoDecoder) {
mVideoDecoder->DecodingComplete();
}
#endif
delete this;
}
void ClearKeyCDM::EnableProtectionQuery() {
MOZ_ASSERT(!mIsProtectionQueryEnabled,
"Should not be called more than once per CDM");
mIsProtectionQueryEnabled = true;
}