summaryrefslogtreecommitdiffstats
path: root/media/gmp-clearkey/0.1/ClearKeyCDM.cpp
blob: 10ec6d3fe2754a65010b3394a943e09b558e6f90 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
/* -*- 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
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#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;
}