18 #include <sys/utsname.h>
20 #include <sys/syscall.h>
24 #include <gst/gstbuffer.h>
34 m_pOpenCDMSystem(NULL),
35 m_pOpenCDMSession(NULL),
36 m_pOutputProtection(NULL),
40 timeBeforeCallback(0),
43 m_keyStatus(InternalError),
44 m_keyStateIndeterminate(false),
46 m_OCDMSessionCallbacks(),
48 m_drmHelper(drmHelper),
49 m_drmCallbacks(callbacks),
54 AAMPLOG_WARN(
"AAMPOCDMSessionAdapter :: enter ");
55 pthread_mutex_init(&decryptMutex, NULL);
57 AAMPLOG_WARN(
"AAMPOCDMSessionAdapter :: key process timeout is %d", drmHelper->keyProcessTimeout());
63 AAMPLOG_WARN(
"AAMPOCDMSessionAdapter :: exit ");
67 void AAMPOCDMSessionAdapter::initAampDRMSystem()
70 pthread_mutex_lock(&decryptMutex);
71 if (m_pOpenCDMSystem ==
nullptr) {
72 #ifdef USE_THUNDER_OCDM_API_0_2
73 m_pOpenCDMSystem = opencdm_create_system(m_keySystem.c_str());
75 m_pOpenCDMSystem = opencdm_create_system();
77 if (m_pOpenCDMSystem ==
nullptr) {
78 AAMPLOG_ERR(
"opencdm_create_system() FAILED");
81 pthread_mutex_unlock(&decryptMutex);
82 AAMPLOG_WARN(
"initAampDRMSystem :: exit ");
86 AAMPOCDMSessionAdapter::~AAMPOCDMSessionAdapter()
88 AAMPLOG_WARN(
"[HHH]OCDMSessionAdapter destructor called! keySystem %s", m_keySystem.c_str());
91 pthread_mutex_destroy(&decryptMutex);
93 if (m_pOpenCDMSystem) {
94 opencdm_destruct_system(m_pOpenCDMSystem);
95 m_pOpenCDMSystem = NULL;
98 if(m_pOutputProtection) {
99 m_pOutputProtection->Release();
105 uint32_t f_cbInitData, std::string &customData)
107 AAMPLOG_INFO(
"at %p, with %p, %p",
this , m_pOpenCDMSystem, m_pOpenCDMSession);
109 pthread_mutex_lock(&decryptMutex);
111 if (m_pOpenCDMSystem ==
nullptr)
113 AAMPLOG_WARN(
"OpenCDM system not present, unable to generate DRM session");
118 memset(&m_OCDMSessionCallbacks, 0,
sizeof(m_OCDMSessionCallbacks));
120 m_OCDMSessionCallbacks.process_challenge_callback = [](OpenCDMSession* session,
void* userData,
const char destUrl[],
const uint8_t challenge[],
const uint16_t challengeSize) {
123 logprintf(
"Duration for process_challenge_callback %lld",(userSession->timeBeforeCallback));
124 userSession->processOCDMChallenge(destUrl, challenge, challengeSize);
127 m_OCDMSessionCallbacks.key_update_callback = [](OpenCDMSession* session,
void* userData,
const uint8_t key[],
const uint8_t keySize) {
129 userSession->keyUpdateOCDM(key, keySize);
132 m_OCDMSessionCallbacks.error_message_callback = [](OpenCDMSession* session,
void* userData,
const char message[]) {
135 m_OCDMSessionCallbacks.keys_updated_callback = [](
const OpenCDMSession* session,
void* userData) {
137 userSession->keysUpdatedOCDM();
139 const unsigned char *customDataMessage = customData.empty() ?
nullptr:
reinterpret_cast<const unsigned char *
>(customData.c_str()) ;
140 const uint16_t customDataMessageLength = customData.length();
141 AAMPLOG_INFO(
"data length : %d: ", customDataMessageLength);
142 #ifdef USE_THUNDER_OCDM_API_0_2
143 OpenCDMError ocdmRet = opencdm_construct_session(m_pOpenCDMSystem, LicenseType::Temporary,
"video/mp4",
145 OpenCDMError ocdmRet = opencdm_construct_session(m_pOpenCDMSystem, m_keySystem.c_str(), LicenseType::Temporary,
"video/mp4",
148 const_cast<unsigned char*
>(f_pbInitData), f_cbInitData,
149 customDataMessage, customDataMessageLength,
150 &m_OCDMSessionCallbacks,
151 static_cast<void*
>(
this),
153 if (ocdmRet != ERROR_NONE)
155 AAMPLOG_ERR(
"Error constructing OCDM session. OCDM err=0x%x", ocdmRet);
160 pthread_mutex_unlock(&decryptMutex);
164 void AAMPOCDMSessionAdapter::processOCDMChallenge(
const char destUrl[],
const uint8_t challenge[],
const uint16_t challengeSize) {
166 AAMPLOG_INFO(
"at %p, with %p, %p",
this , m_pOpenCDMSystem, m_pOpenCDMSession);
168 const std::string challengeData(
reinterpret_cast<const char *
>(challenge), challengeSize);
169 const std::set<std::string> individualisationTypes = {
"individualization-request",
"3"};
170 const std::string delimiter(
":Type:");
171 const size_t delimiterPos = challengeData.find(delimiter);
172 const std::string messageType = challengeData.substr(0, delimiterPos);
176 if ((delimiterPos != std::string::npos) && (individualisationTypes.count(messageType) > 0))
178 AAMPLOG_WARN(
"processOCDMChallenge received message with type=%s", messageType.c_str());
182 m_drmCallbacks->individualization(challengeData.substr(delimiterPos + delimiter.length()));
188 m_challenge = challengeData;
189 AAMPLOG_WARN(
"processOCDMChallenge challenge = %s", m_challenge.c_str());
191 m_destUrl.assign(destUrl);
192 AAMPLOG_WARN(
"processOCDMChallenge destUrl = %s (default value used as drm server)", m_destUrl.c_str());
194 m_challengeReady.signal();
199 void AAMPOCDMSessionAdapter::keyUpdateOCDM(
const uint8_t key[],
const uint8_t keySize) {
200 AAMPLOG_INFO(
"at %p, with %p, %p",
this , m_pOpenCDMSystem, m_pOpenCDMSession);
201 if (m_pOpenCDMSession) {
202 m_keyStatus = opencdm_session_status(m_pOpenCDMSession, key, keySize);
203 m_keyStateIndeterminate =
false;
207 m_keyStored.assign(key, key+keySize);
208 m_keyStateIndeterminate =
true;
213 void AAMPOCDMSessionAdapter::keysUpdatedOCDM() {
214 AAMPLOG_INFO(
"at %p, with %p, %p",
this , m_pOpenCDMSystem, m_pOpenCDMSession);
215 m_keyStatusReady.signal();
221 AAMPLOG_INFO(
"at %p, with %p, %p",
this , m_pOpenCDMSystem, m_pOpenCDMSession);
226 if (m_challengeReady.wait(timeout) ==
true) {
227 if (m_challenge.empty() !=
true) {
228 std::string delimiter (
":Type:");
229 std::string requestType (m_challenge.substr(0, m_challenge.find(delimiter)));
230 if ( (requestType.size() != 0) && (requestType.size() != m_challenge.size()) ) {
231 (void) m_challenge.erase(0, m_challenge.find(delimiter) + delimiter.length());
234 result =
new DrmData(
reinterpret_cast<unsigned char*
>(
const_cast<char*
>(m_challenge.c_str())), m_challenge.length());
235 destinationURL.assign((m_destUrl.c_str()));
236 AAMPLOG_WARN(
"destinationURL is %s (default value used as drm server)", destinationURL.c_str());
240 AAMPLOG_WARN(
"Empty keyRequest");
243 AAMPLOG_WARN(
"Timed out waiting for keyRequest");
251 AAMPLOG_INFO(
"at %p, with %p, %p",
this , m_pOpenCDMSystem, m_pOpenCDMSession);
253 const uint8_t* keyMessage = NULL;
254 uint16_t keyMessageLength = 0;
256 OpenCDMError status = OpenCDMError::ERROR_NONE;
260 keyMessage = (
const uint8_t *)key->
getData().c_str();
266 AAMPLOG_INFO(
"Calling opencdm_session_update, key length=%u", keyMessageLength);
267 status = opencdm_session_update(m_pOpenCDMSession, keyMessage, keyMessageLength);
274 AAMPLOG_INFO(
"NULL key data provided, assuming external key acquisition");
277 if (status == OpenCDMError::ERROR_NONE) {
278 if (m_keyStatusReady.wait(timeout) ==
true) {
279 AAMPLOG_WARN(
"Key Status updated");
282 if (m_keyStateIndeterminate) {
283 m_keyStatus = opencdm_session_status(m_pOpenCDMSession, m_keyStored.data(), m_keyStored.size());
284 m_keyStateIndeterminate =
false;
285 AAMPLOG_WARN(
"Key arrived early, new state is %d", m_keyStatus);
287 #ifdef USE_THUNDER_OCDM_API_0_2
288 if (m_keyStatus == Usable) {
290 if (m_keyStatus == KeyStatus::Usable) {
292 AAMPLOG_WARN(
"processKey: Key Usable!");
296 #ifdef USE_THUNDER_OCDM_API_0_2
297 else if(m_keyStatus == HWError)
299 else if(m_keyStatus == KeyStatus::HWError)
303 AAMPLOG_WARN(
"processKey: Update() returned HWError.Restarting process...");
304 int systemResult = -1;
307 systemResult = system(
"pgrep WPEcdmi");
308 if(systemResult == 0)
310 systemResult = system(
"pkill -9 WPEcdmi");
311 if(systemResult != 0)
313 AAMPLOG_WARN(
"Unable to shutdown WPEcdmi process.%d", systemResult);
319 systemResult = system(
"pgrep WPEFramework");
320 if(systemResult == 0)
322 systemResult = system(
"pkill -9 WPEFramework");
323 if(systemResult != 0)
325 AAMPLOG_WARN(
"Unable to shutdown WPEFramework process.%d", systemResult);
333 if(kill(getpid(), SIGKILL) < 0)
335 AAMPLOG_WARN(
"Kill Failed = %d", errno);
339 #ifdef USE_THUNDER_OCDM_API_0_2
340 if(m_keyStatus == OutputRestricted)
342 if(m_keyStatus == KeyStatus::OutputRestricted)
345 AAMPLOG_WARN(
"processKey: Update() Output restricted keystatus: %d", (
int) m_keyStatus);
346 retValue = HDCP_OUTPUT_PROTECTION_FAILURE;
348 #ifdef USE_THUNDER_OCDM_API_0_2
349 else if(m_keyStatus == OutputRestrictedHDCP22)
351 else if(m_keyStatus == KeyStatus::OutputRestrictedHDCP22)
354 AAMPLOG_WARN(
"processKey: Update() Output Compliance error keystatus: %d\n", (
int) m_keyStatus);
355 retValue = HDCP_COMPLIANCE_CHECK_FAILURE;
359 AAMPLOG_WARN(
"processKey: Update() returned keystatus: %d\n", (
int) m_keyStatus);
360 retValue = (int) m_keyStatus;
365 m_keyStatusWait.signal();
372 if (m_eKeyState == state) {
375 if (!m_keyStatusWait.wait(timeout)) {
378 return m_eKeyState == state;
390 AAMPLOG_WARN(
"[HHH] clearDecryptContext.");
392 pthread_mutex_lock(&decryptMutex);
394 if (m_pOpenCDMSession) {
395 opencdm_session_close(m_pOpenCDMSession);
396 opencdm_destruct_session(m_pOpenCDMSession);
397 m_pOpenCDMSession = NULL;
400 pthread_mutex_unlock(&decryptMutex);
405 void AAMPOCDMSessionAdapter::setKeyId(
const std::vector<uint8_t>& keyId)
411 bool AAMPOCDMSessionAdapter::verifyOutputProtection()
413 if (m_drmHelper->isHdcp22Required() && m_pOutputProtection->
IsSourceUHD())
419 AAMPLOG_WARN(
"UHD source but not HDCP 2.2. FAILING decrypt");