1 /* 2 * Copyright (c) 2009-2012 Intel Corporation. All rights reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 18 //#define LOG_NDEBUG 0 19 #define LOG_TAG "OMXVideoDecoderAVCSecure" 20 #include <wrs_omxil_core/log.h> 21 #include "OMXVideoDecoderAVCSecure.h" 22 #include <time.h> 23 #include <signal.h> 24 #include <pthread.h> 25 #include <sys/mman.h> 26 #include <cutils/ashmem.h> 27 #include <OMX_IntelIndexExt.h> 28 #include <OMXComponentCodecBase.h> 29 30 #include "LogDumpHelper.h" 31 #include "VideoFrameInfo.h" 32 #include "ProtectedDataBuffer.h" 33 34 35 // Be sure to have an equal string in VideoDecoderHost.cpp (libmix) 36 static const char* AVC_MIME_TYPE = "video/avc"; 37 static const char* AVC_SECURE_MIME_TYPE = "video/avc-secure"; 38 39 #define INPORT_BUFFER_SIZE sizeof(ProtectedDataBuffer) 40 #define DATA_BUFFER_INITIAL_OFFSET 0 //1024 41 #define DATA_BUFFER_SIZE (8 * 1024 * 1024) 42 #define KEEP_ALIVE_INTERVAL 5 // seconds 43 #define DRM_KEEP_ALIVE_TIMER 1000000 44 #define WV_SESSION_ID 0x00000011 45 #define NALU_HEADER_LENGTH 1024 // THis should be changed to 4K 46 #define FLUSH_WAIT_INTERVAL (30 * 1000) //30 ms 47 48 #define DRM_SCHEME_NONE 0 49 #define DRM_SCHEME_WVC 1 50 #define DRM_SCHEME_CENC 2 51 #define DRM_SCHEME_PRASF 3 52 53 bool OMXVideoDecoderAVCSecure::EnableIEDSession(bool enable) 54 { 55 if (mDrmDevFd <= 0) { 56 ALOGE("invalid mDrmDevFd"); 57 return false; 58 } 59 int request = enable ? DRM_PSB_ENABLE_IED_SESSION : DRM_PSB_DISABLE_IED_SESSION; 60 int ret = drmCommandNone(mDrmDevFd, request); 61 return ret == 0; 62 } 63 64 OMXVideoDecoderAVCSecure::OMXVideoDecoderAVCSecure() 65 : mKeepAliveTimer(0), 66 mNumInportBuffers(0), 67 mSessionPaused(false){ 68 ALOGV("OMXVideoDecoderAVCSecure is constructed."); 69 if (drm_vendor_api_init(&drm_vendor_api)) { 70 ALOGE("drm_vendor_api_init failed"); 71 } 72 mVideoDecoder = createVideoDecoder(AVC_SECURE_MIME_TYPE); 73 if (!mVideoDecoder) { 74 ALOGE("createVideoDecoder failed for \"%s\"", AVC_SECURE_MIME_TYPE); 75 } 76 // Override default native buffer count defined in the base class 77 mNativeBufferCount = OUTPORT_NATIVE_BUFFER_COUNT; 78 79 BuildHandlerList(); 80 81 mDrmDevFd = open("/dev/card0", O_RDWR, 0); 82 if (mDrmDevFd <= 0) { 83 ALOGE("Failed to open drm device."); 84 } 85 } 86 87 OMXVideoDecoderAVCSecure::~OMXVideoDecoderAVCSecure() { 88 ALOGI("OMXVideoDecoderAVCSecure is destructed."); 89 if (drm_vendor_api_deinit(&drm_vendor_api)) { 90 ALOGE("drm_vendor_api_deinit failed"); 91 } 92 if (mDrmDevFd > 0) { 93 close(mDrmDevFd); 94 mDrmDevFd = 0; 95 } 96 } 97 98 OMX_ERRORTYPE OMXVideoDecoderAVCSecure::InitInputPortFormatSpecific(OMX_PARAM_PORTDEFINITIONTYPE *paramPortDefinitionInput) { 99 // OMX_PARAM_PORTDEFINITIONTYPE 100 paramPortDefinitionInput->nBufferCountActual = INPORT_ACTUAL_BUFFER_COUNT; 101 paramPortDefinitionInput->nBufferCountMin = INPORT_MIN_BUFFER_COUNT; 102 paramPortDefinitionInput->nBufferSize = INPORT_BUFFER_SIZE; 103 paramPortDefinitionInput->format.video.cMIMEType = (OMX_STRING)AVC_MIME_TYPE; 104 paramPortDefinitionInput->format.video.eCompressionFormat = OMX_VIDEO_CodingAVC; 105 106 // OMX_VIDEO_PARAM_AVCTYPE 107 memset(&mParamAvc, 0, sizeof(mParamAvc)); 108 SetTypeHeader(&mParamAvc, sizeof(mParamAvc)); 109 mParamAvc.nPortIndex = INPORT_INDEX; 110 // TODO: check eProfile/eLevel 111 mParamAvc.eProfile = OMX_VIDEO_AVCProfileHigh; //OMX_VIDEO_AVCProfileBaseline; 112 mParamAvc.eLevel = OMX_VIDEO_AVCLevel41; //OMX_VIDEO_AVCLevel1; 113 114 this->ports[INPORT_INDEX]->SetMemAllocator(MemAllocDataBuffer, MemFreeDataBuffer, this); 115 116 return OMX_ErrorNone; 117 } 118 119 OMX_ERRORTYPE OMXVideoDecoderAVCSecure::ProcessorInit(void) { 120 mSessionPaused = false; 121 if (drm_vendor_api.handle == NULL) { 122 return OMX_ErrorUndefined; 123 } 124 return OMXVideoDecoderBase::ProcessorInit(); 125 } 126 127 OMX_ERRORTYPE OMXVideoDecoderAVCSecure::ProcessorDeinit(void) { 128 129 WaitForFrameDisplayed(); 130 // Session should be torn down in ProcessorStop, delayed to ProcessorDeinit 131 // to allow remaining frames completely rendered. 132 ALOGI("Calling Drm_DestroySession."); 133 uint32_t ret = drm_vendor_api.drm_stop_playback(); 134 if (ret != DRM_WV_MOD_SUCCESS) { 135 ALOGE("drm_stop_playback failed: (0x%x)", ret); 136 } 137 EnableIEDSession(false); 138 return OMXVideoDecoderBase::ProcessorDeinit(); 139 } 140 141 OMX_ERRORTYPE OMXVideoDecoderAVCSecure::ProcessorStart(void) { 142 143 EnableIEDSession(true); 144 uint32_t ret = drm_vendor_api.drm_start_playback(); 145 if (ret != DRM_WV_MOD_SUCCESS) { 146 ALOGE("drm_start_playback failed: (0x%x)", ret); 147 } 148 149 mSessionPaused = false; 150 return OMXVideoDecoderBase::ProcessorStart(); 151 } 152 153 OMX_ERRORTYPE OMXVideoDecoderAVCSecure::ProcessorStop(void) { 154 if (mKeepAliveTimer != 0) { 155 timer_delete(mKeepAliveTimer); 156 mKeepAliveTimer = 0; 157 } 158 159 return OMXVideoDecoderBase::ProcessorStop(); 160 } 161 162 163 OMX_ERRORTYPE OMXVideoDecoderAVCSecure::ProcessorFlush(OMX_U32 portIndex) { 164 return OMXVideoDecoderBase::ProcessorFlush(portIndex); 165 } 166 167 OMX_ERRORTYPE OMXVideoDecoderAVCSecure::ProcessorProcess( 168 OMX_BUFFERHEADERTYPE ***pBuffers, 169 buffer_retain_t *retains, 170 OMX_U32 numberBuffers) { 171 172 int ret_value; 173 174 OMX_BUFFERHEADERTYPE *pInput = *pBuffers[INPORT_INDEX]; 175 native_handle_t *native_handle = (native_handle_t *)pInput->pBuffer; 176 ProtectedDataBuffer *dataBuffer = (ProtectedDataBuffer *) native_handle->data[1]; 177 178 // Check that we are dealing with the right buffer 179 if (dataBuffer->magic != PROTECTED_DATA_BUFFER_MAGIC) 180 { 181 if (pInput->nFlags & OMX_BUFFERFLAG_CODECCONFIG) 182 { 183 // Processing codec data, which is not in ProtectedDataBuffer format 184 ALOGV("%s: received AVC codec data (%" PRIu32 " bytes).", __FUNCTION__, pInput->nFilledLen); 185 DumpBuffer2("OMX: AVC codec data: ", pInput->pBuffer, pInput->nFilledLen); 186 return OMX_ErrorNone; 187 } 188 else 189 { 190 // Processing non-codec data, but this buffer is not in ProtectedDataBuffer format 191 ALOGE("%s: protected data buffer pointer %p doesn't have the right magic", __FUNCTION__, dataBuffer); 192 return OMX_ErrorBadParameter; 193 } 194 } 195 196 if((dataBuffer->drmScheme == DRM_SCHEME_WVC) && (!mKeepAliveTimer)){ 197 struct sigevent sev; 198 memset(&sev, 0, sizeof(sev)); 199 sev.sigev_notify = SIGEV_THREAD; 200 sev.sigev_value.sival_ptr = this; 201 sev.sigev_notify_function = KeepAliveTimerCallback; 202 203 ret_value = timer_create(CLOCK_REALTIME, &sev, &mKeepAliveTimer); 204 if (ret_value != 0) { 205 ALOGE("Failed to create timer."); 206 } else { 207 struct itimerspec its; 208 its.it_value.tv_sec = -1; // never expire 209 its.it_value.tv_nsec = 0; 210 its.it_interval.tv_sec = KEEP_ALIVE_INTERVAL; 211 its.it_interval.tv_nsec = 0; 212 213 ret_value = timer_settime(mKeepAliveTimer, TIMER_ABSTIME, &its, NULL); 214 if (ret_value != 0) { 215 ALOGE("Failed to set timer."); 216 } 217 } 218 } 219 220 if (dataBuffer->size == 0) { 221 // error occurs during decryption. 222 ALOGW("size of returned data buffer is 0, decryption fails."); 223 mVideoDecoder->flush(); 224 usleep(FLUSH_WAIT_INTERVAL); 225 OMX_BUFFERHEADERTYPE *pOutput = *pBuffers[OUTPORT_INDEX]; 226 pOutput->nFilledLen = 0; 227 // reset Data buffer size 228 dataBuffer->size = INPORT_BUFFER_SIZE; 229 this->ports[INPORT_INDEX]->FlushPort(); 230 this->ports[OUTPORT_INDEX]->FlushPort(); 231 return OMX_ErrorNone; 232 } 233 234 OMX_ERRORTYPE ret; 235 ret = OMXVideoDecoderBase::ProcessorProcess(pBuffers, retains, numberBuffers); 236 if (ret != OMX_ErrorNone) { 237 ALOGE("OMXVideoDecoderBase::ProcessorProcess failed. Result: %#x", ret); 238 return ret; 239 } 240 241 if (mSessionPaused && (retains[OUTPORT_INDEX] == BUFFER_RETAIN_GETAGAIN)) { 242 retains[OUTPORT_INDEX] = BUFFER_RETAIN_NOT_RETAIN; 243 OMX_BUFFERHEADERTYPE *pOutput = *pBuffers[OUTPORT_INDEX]; 244 pOutput->nFilledLen = 0; 245 this->ports[INPORT_INDEX]->FlushPort(); 246 this->ports[OUTPORT_INDEX]->FlushPort(); 247 } 248 249 return ret; 250 } 251 252 OMX_ERRORTYPE OMXVideoDecoderAVCSecure::ProcessorPause(void) { 253 return OMXVideoDecoderBase::ProcessorPause(); 254 } 255 256 OMX_ERRORTYPE OMXVideoDecoderAVCSecure::ProcessorResume(void) { 257 return OMXVideoDecoderBase::ProcessorResume(); 258 } 259 260 OMX_ERRORTYPE OMXVideoDecoderAVCSecure::PrepareConfigBuffer(VideoConfigBuffer *p) { 261 OMX_ERRORTYPE ret; 262 ret = OMXVideoDecoderBase::PrepareConfigBuffer(p); 263 CHECK_RETURN_VALUE("OMXVideoDecoderBase::PrepareConfigBuffer"); 264 p->flag |= WANT_SURFACE_PROTECTION; 265 return ret; 266 } 267 268 OMX_ERRORTYPE OMXVideoDecoderAVCSecure::PrepareWVCDecodeBuffer(OMX_BUFFERHEADERTYPE *buffer, buffer_retain_t *retain, VideoDecodeBuffer *p) 269 { 270 271 OMX_ERRORTYPE ret = OMX_ErrorNone; 272 (void) retain; // unused parameter 273 274 p->flag |= HAS_COMPLETE_FRAME; 275 276 if (buffer->nOffset != 0) { 277 ALOGW("buffer offset %u is not zero!!!", buffer->nOffset); 278 } 279 native_handle_t *native_handle = (native_handle_t *)buffer->pBuffer; 280 ProtectedDataBuffer *dataBuffer = (ProtectedDataBuffer *) native_handle->data[1]; 281 if (dataBuffer->clear) { 282 p->data = dataBuffer->data + buffer->nOffset; 283 p->size = buffer->nFilledLen; 284 } else { 285 dataBuffer->size = NALU_BUFFER_SIZE; 286 struct drm_wv_nalu_headers nalu_headers; 287 nalu_headers.p_enc_ciphertext = dataBuffer->data; 288 289 // TODO: NALU Buffer is supposed to be 4k but using 1k, fix it once chaabi fix is there 290 291 nalu_headers.hdrs_buf_len = NALU_HEADER_LENGTH; 292 nalu_headers.frame_size = buffer->nFilledLen; 293 // Make sure that NALU header frame size is 16 bytes aligned 294 nalu_headers.frame_size = (nalu_headers.frame_size + 0xF) & (~0xF); 295 // Use same video buffer to fill NALU headers returned by chaabi, 296 // Adding 4 because the first 4 bytes after databuffer will be used to store length of NALU headers 297 if((nalu_headers.frame_size + NALU_HEADER_LENGTH) > INPORT_BUFFER_SIZE){ 298 ALOGE("Not enough buffer for NALU headers"); 299 return OMX_ErrorOverflow; 300 } 301 302 nalu_headers.p_hdrs_buf = (uint8_t *)(dataBuffer->data + nalu_headers.frame_size + 4); 303 nalu_headers.parse_size = buffer->nFilledLen; 304 305 uint32_t res = drm_vendor_api.drm_wv_return_naluheaders(WV_SESSION_ID, &nalu_headers); 306 if (res == DRM_FAIL_FW_SESSION) { 307 ALOGW("Drm_WV_ReturnNALUHeaders failed. Session is disabled."); 308 mSessionPaused = true; 309 ret = OMX_ErrorNotReady; 310 } else if (res != 0) { 311 mSessionPaused = false; 312 ALOGE("Drm_WV_ReturnNALUHeaders failed. Error = %#x, frame_size: %d, len = %u", res, nalu_headers.frame_size, buffer->nFilledLen); 313 ret = OMX_ErrorHardware; 314 } else { 315 mSessionPaused = false; 316 317 // If chaabi returns 0 NALU headers fill the frame size to zero. 318 if (!nalu_headers.hdrs_buf_len) { 319 p->size = 0; 320 return ret; 321 } 322 else{ 323 // NALU headers are appended to encrypted video bitstream 324 // |...encrypted video bitstream (16 bytes aligned)...| 4 bytes of header size |...NALU headers..| 325 uint32_t *ptr = (uint32_t*)(dataBuffer->data + nalu_headers.frame_size); 326 *ptr = nalu_headers.hdrs_buf_len; 327 p->data = dataBuffer->data; 328 p->size = nalu_headers.frame_size; 329 p->flag |= IS_SECURE_DATA; 330 } 331 } 332 } 333 334 // reset Data size 335 dataBuffer->size = NALU_BUFFER_SIZE; 336 return ret; 337 } 338 OMX_ERRORTYPE OMXVideoDecoderAVCSecure::PrepareCENCDecodeBuffer(OMX_BUFFERHEADERTYPE *buffer, buffer_retain_t *retain, VideoDecodeBuffer *p) 339 { 340 OMX_ERRORTYPE ret = OMX_ErrorNone; 341 (void) retain; // unused parameter 342 343 // OMX_BUFFERFLAG_CODECCONFIG is an optional flag 344 // if flag is set, buffer will only contain codec data. 345 if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { 346 ALOGI("Received AVC codec data."); 347 // return ret; 348 } 349 p->flag |= HAS_COMPLETE_FRAME | IS_SUBSAMPLE_ENCRYPTION; 350 351 if (buffer->nOffset != 0) { 352 ALOGW("buffer offset %u is not zero!!!", buffer->nOffset); 353 } 354 355 native_handle_t *native_handle = (native_handle_t *)buffer->pBuffer; 356 ProtectedDataBuffer *dataBuffer = (ProtectedDataBuffer *) native_handle->data[1]; 357 358 p->data = dataBuffer->data; 359 p->size = sizeof(frame_info_t); 360 p->flag |= IS_SECURE_DATA; 361 return ret; 362 } 363 364 365 OMX_ERRORTYPE OMXVideoDecoderAVCSecure::PreparePRASFDecodeBuffer(OMX_BUFFERHEADERTYPE *buffer, buffer_retain_t *retain, VideoDecodeBuffer *p) 366 { 367 OMX_ERRORTYPE ret = OMX_ErrorNone; 368 (void) retain; // unused parameter 369 370 // OMX_BUFFERFLAG_CODECCONFIG is an optional flag 371 // if flag is set, buffer will only contain codec data. 372 if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { 373 ALOGV("PR: Received codec data."); 374 return ret; 375 } 376 p->flag |= HAS_COMPLETE_FRAME; 377 378 if (buffer->nOffset != 0) { 379 ALOGW("PR:buffer offset %u is not zero!!!", buffer->nOffset); 380 } 381 382 native_handle_t *native_handle = (native_handle_t *)buffer->pBuffer; 383 ProtectedDataBuffer *dataBuffer = (ProtectedDataBuffer *) native_handle->data[1]; 384 if (dataBuffer->clear) { 385 p->data = dataBuffer->data + buffer->nOffset; 386 p->size = buffer->nFilledLen; 387 } else { 388 dataBuffer->size = NALU_BUFFER_SIZE; 389 struct drm_nalu_headers nalu_headers; 390 nalu_headers.p_enc_ciphertext = dataBuffer->data; 391 392 // TODO: NALU Buffer is supposed to be 4k but using 1k, fix it once chaabi fix is there 393 nalu_headers.hdrs_buf_len = NALU_HEADER_LENGTH; 394 nalu_headers.frame_size = buffer->nFilledLen; 395 // Make sure that NALU header frame size is 16 bytes aligned 396 nalu_headers.frame_size = (nalu_headers.frame_size + 0xF) & (~0xF); 397 // Use same video buffer to fill NALU headers returned by chaabi, 398 // Adding 4 because the first 4 bytes after databuffer will be used to store length of NALU headers 399 if((nalu_headers.frame_size + NALU_HEADER_LENGTH) > INPORT_BUFFER_SIZE){ 400 ALOGE("Not enough buffer for NALU headers"); 401 return OMX_ErrorOverflow; 402 } 403 404 nalu_headers.p_hdrs_buf = (uint8_t *)(dataBuffer->data + nalu_headers.frame_size + 4); 405 nalu_headers.parse_size = buffer->nFilledLen; 406 407 uint32_t res = drm_vendor_api.drm_pr_return_naluheaders(dataBuffer->session_id, &nalu_headers); 408 409 if (res == DRM_FAIL_FW_SESSION || !nalu_headers.hdrs_buf_len) { 410 ALOGW("drm_ReturnNALUHeaders failed. Session is disabled."); 411 mSessionPaused = true; 412 ret = OMX_ErrorNotReady; 413 } else if (res != 0) { 414 mSessionPaused = false; 415 ALOGE("drm_pr_return_naluheaders failed. Error = %#x, frame_size: %d, len = %u", res, nalu_headers.frame_size, buffer->nFilledLen); 416 ret = OMX_ErrorHardware; 417 } else { 418 mSessionPaused = false; 419 420 // If chaabi returns 0 NALU headers fill the frame size to zero. 421 if (!nalu_headers.hdrs_buf_len) { 422 p->size = 0; 423 return ret; 424 } 425 else{ 426 // NALU headers are appended to encrypted video bitstream 427 // |...encrypted video bitstream (16 bytes aligned)...| 4 bytes of header size |...NALU headers..| 428 uint32_t *ptr = (uint32_t*)(dataBuffer->data + nalu_headers.frame_size); 429 *ptr = nalu_headers.hdrs_buf_len; 430 p->data = dataBuffer->data; 431 p->size = nalu_headers.frame_size; 432 p->flag |= IS_SECURE_DATA; 433 } 434 } 435 } 436 437 // reset Data size 438 dataBuffer->size = NALU_BUFFER_SIZE; 439 return ret; 440 } 441 442 OMX_ERRORTYPE OMXVideoDecoderAVCSecure::PrepareDecodeBuffer(OMX_BUFFERHEADERTYPE *buffer, buffer_retain_t *retain, VideoDecodeBuffer *p) { 443 OMX_ERRORTYPE ret; 444 445 ret = OMXVideoDecoderBase::PrepareDecodeNativeHandleBuffer(buffer, retain, p); 446 CHECK_RETURN_VALUE("OMXVideoDecoderBase::PrepareDecodeBuffer"); 447 448 if (buffer->nFilledLen == 0) { 449 return OMX_ErrorNone; 450 } 451 native_handle_t *native_handle = (native_handle_t *)buffer->pBuffer; 452 453 ProtectedDataBuffer *dataBuffer = (ProtectedDataBuffer *) native_handle->data[1]; 454 455 // Check that we are dealing with the right buffer 456 if (dataBuffer->magic != PROTECTED_DATA_BUFFER_MAGIC) 457 { 458 if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) 459 { 460 // Processing codec data, which is not in ProtectedDataBuffer format 461 ALOGI("%s: received AVC codec data (%" PRIu32 " bytes).", __FUNCTION__, buffer->nFilledLen); 462 DumpBuffer2("OMX: AVC codec data: ", buffer->pBuffer, buffer->nFilledLen) ; 463 return OMX_ErrorNone; 464 } 465 else 466 { 467 // Processing non-codec data, but this buffer is not in ProtectedDataBuffer format 468 ALOGE("%s: protected data buffer pointer %p doesn't have the right magic", __FUNCTION__, dataBuffer); 469 return OMX_ErrorBadParameter; 470 } 471 } 472 // End of magic check 473 474 if(dataBuffer->drmScheme == DRM_SCHEME_WVC){ 475 476 // OMX_BUFFERFLAG_CODECCONFIG is an optional flag 477 // if flag is set, buffer will only contain codec data. 478 mDrmScheme = DRM_SCHEME_WVC; 479 if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { 480 ALOGV("Received AVC codec data."); 481 return ret; 482 } 483 return PrepareWVCDecodeBuffer(buffer, retain, p); 484 } 485 else if(dataBuffer->drmScheme == DRM_SCHEME_CENC) { 486 mDrmScheme = DRM_SCHEME_CENC; 487 return PrepareCENCDecodeBuffer(buffer, retain, p); 488 } 489 else if(dataBuffer->drmScheme == DRM_SCHEME_PRASF) 490 { 491 mDrmScheme = DRM_SCHEME_PRASF; 492 return PreparePRASFDecodeBuffer(buffer, retain, p); 493 } 494 return ret; 495 } 496 497 OMX_ERRORTYPE OMXVideoDecoderAVCSecure::BuildHandlerList(void) { 498 OMXVideoDecoderBase::BuildHandlerList(); 499 AddHandler(OMX_IndexParamVideoAvc, GetParamVideoAvc, SetParamVideoAvc); 500 AddHandler(OMX_IndexParamVideoProfileLevelQuerySupported, GetParamVideoAVCProfileLevel, SetParamVideoAVCProfileLevel); 501 AddHandler(static_cast<OMX_INDEXTYPE>(OMX_IndexExtAllocateNativeHandle), GetExtAllocateNativeHandle, SetExtAllocateNativeHandle); 502 return OMX_ErrorNone; 503 } 504 505 OMX_ERRORTYPE OMXVideoDecoderAVCSecure::GetParamVideoAvc(OMX_PTR pStructure) { 506 OMX_ERRORTYPE ret; 507 OMX_VIDEO_PARAM_AVCTYPE *p = (OMX_VIDEO_PARAM_AVCTYPE *)pStructure; 508 CHECK_TYPE_HEADER(p); 509 CHECK_PORT_INDEX(p, INPORT_INDEX); 510 511 memcpy(p, &mParamAvc, sizeof(*p)); 512 return OMX_ErrorNone; 513 } 514 515 OMX_ERRORTYPE OMXVideoDecoderAVCSecure::SetParamVideoAvc(OMX_PTR pStructure) { 516 OMX_ERRORTYPE ret; 517 OMX_VIDEO_PARAM_AVCTYPE *p = (OMX_VIDEO_PARAM_AVCTYPE *)pStructure; 518 CHECK_TYPE_HEADER(p); 519 CHECK_PORT_INDEX(p, INPORT_INDEX); 520 CHECK_SET_PARAM_STATE(); 521 522 // TODO: do we need to check if port is enabled? 523 // TODO: see SetPortAvcParam implementation - Can we make simple copy???? 524 memcpy(&mParamAvc, p, sizeof(mParamAvc)); 525 return OMX_ErrorNone; 526 } 527 528 529 OMX_ERRORTYPE OMXVideoDecoderAVCSecure::GetParamVideoAVCProfileLevel(OMX_PTR pStructure) { 530 OMX_ERRORTYPE ret; 531 OMX_VIDEO_PARAM_PROFILELEVELTYPE *p = (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)pStructure; 532 CHECK_TYPE_HEADER(p); 533 CHECK_PORT_INDEX(p, INPORT_INDEX); 534 535 struct ProfileLevelTable { 536 OMX_U32 profile; 537 OMX_U32 level; 538 } plTable[] = { 539 {OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel42}, 540 {OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel42}, 541 {OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel42} 542 }; 543 544 OMX_U32 count = sizeof(plTable)/sizeof(ProfileLevelTable); 545 CHECK_ENUMERATION_RANGE(p->nProfileIndex,count); 546 547 p->eProfile = plTable[p->nProfileIndex].profile; 548 p->eLevel = plTable[p->nProfileIndex].level; 549 550 return OMX_ErrorNone; 551 } 552 553 OMX_ERRORTYPE OMXVideoDecoderAVCSecure::SetParamVideoAVCProfileLevel(OMX_PTR pStructure) { 554 ALOGW("SetParamVideoAVCProfileLevel is not supported."); 555 (void) pStructure; // unused parameter 556 return OMX_ErrorUnsupportedSetting; 557 } 558 559 560 OMX_ERRORTYPE OMXVideoDecoderAVCSecure::GetExtAllocateNativeHandle(OMX_PTR pStructure) { 561 (void) pStructure; // unused parameter 562 563 return OMX_ErrorNone; 564 565 } 566 567 OMX_ERRORTYPE OMXVideoDecoderAVCSecure::SetExtAllocateNativeHandle(OMX_PTR pStructure) { 568 OMX_ERRORTYPE ret; 569 android:: EnableAndroidNativeBuffersParams *p = (android::EnableAndroidNativeBuffersParams *)pStructure; 570 CHECK_TYPE_HEADER(p); 571 CHECK_SET_PARAM_STATE(); 572 573 return OMX_ErrorNone; 574 } 575 OMX_U8* OMXVideoDecoderAVCSecure::MemAllocDataBuffer(OMX_U32 nSizeBytes, OMX_PTR pUserData) { 576 OMXVideoDecoderAVCSecure* p = (OMXVideoDecoderAVCSecure *)pUserData; 577 if (p) { 578 return p->MemAllocDataBuffer(nSizeBytes); 579 } 580 ALOGE("NULL pUserData."); 581 return NULL; 582 } 583 584 void OMXVideoDecoderAVCSecure::MemFreeDataBuffer(OMX_U8 *pBuffer, OMX_PTR pUserData) { 585 OMXVideoDecoderAVCSecure* p = (OMXVideoDecoderAVCSecure *)pUserData; 586 if (p) { 587 p->MemFreeDataBuffer(pBuffer); 588 return; 589 } 590 ALOGE("NULL pUserData."); 591 } 592 593 OMX_U8* OMXVideoDecoderAVCSecure::MemAllocDataBuffer(OMX_U32 nSizeBytes) { 594 595 ALOGW_IF(nSizeBytes != INPORT_BUFFER_SIZE, 596 "%s: size of memory to allocate is %" PRIu32 ", but will allocate %zu", 597 __FUNCTION__, nSizeBytes, sizeof(ProtectedDataBuffer)); 598 599 if (mNumInportBuffers >= INPORT_ACTUAL_BUFFER_COUNT) 600 { 601 ALOGE("%s: cannot allocate buffer: number of inport buffers is %u, which is already at maximum", 602 __FUNCTION__, mNumInportBuffers); 603 return NULL; 604 } 605 606 607 int fd = ashmem_create_region("protectd-content-buffer", sizeof(ProtectedDataBuffer)); 608 if(fd < 0) { 609 ALOGE("Unable to create ashmem region"); 610 return NULL; 611 } 612 613 native_handle_t *native = native_handle_create(1, 2); 614 615 native->data[0] = fd; 616 ProtectedDataBuffer *pBuffer =(ProtectedDataBuffer *) mmap(NULL, sizeof(ProtectedDataBuffer), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 617 if (pBuffer == MAP_FAILED) { 618 ALOGE("%s: mmap failed", __FUNCTION__); 619 return NULL; 620 } 621 native->data[1] = (int) pBuffer; 622 // Use a random value as the buffer id 623 native->data[2] = rand(); 624 ++mNumInportBuffers; 625 626 Init_ProtectedDataBuffer(pBuffer); 627 628 pBuffer->size = INPORT_BUFFER_SIZE; 629 630 ALOGV("Allocating native=[%p] buffer = %#x, data = %#x data_end= %#x size=%d",(OMX_U8 *)native,(uint32_t)pBuffer, (uint32_t)pBuffer->data, (uint32_t)pBuffer->data + sizeof(ProtectedDataBuffer) ,sizeof(ProtectedDataBuffer)); 631 return (OMX_U8 *) native; 632 } 633 634 void OMXVideoDecoderAVCSecure::MemFreeDataBuffer(OMX_U8 *pBuffer) { 635 636 if (pBuffer == NULL) 637 { 638 ALOGE("%s: trying to free NULL pointer", __FUNCTION__); 639 return; 640 } 641 642 if (mNumInportBuffers == 0) 643 { 644 ALOGE("%s: allocated inport buffer count is already 0, cannot delete buffer %p", 645 __FUNCTION__, pBuffer); 646 return; 647 } 648 649 native_handle_t *native_handle = (native_handle_t *) pBuffer; 650 651 ProtectedDataBuffer *dataBuffer = (ProtectedDataBuffer *) native_handle->data[1]; 652 if (dataBuffer->magic != PROTECTED_DATA_BUFFER_MAGIC) 653 { 654 ALOGE("%s: attempting to free buffer with a wrong magic 0x%08x", __FUNCTION__, dataBuffer->magic); 655 return; 656 } 657 658 if (munmap(dataBuffer, sizeof(ProtectedDataBuffer)) != 0) { 659 ALOGE("%s: Faild to munmap %p",__FUNCTION__, dataBuffer); 660 return; 661 } 662 663 native_handle_close(native_handle); 664 native_handle_delete(native_handle); 665 ALOGV("Free databuffer %p with data = %p", dataBuffer, dataBuffer->data); 666 --mNumInportBuffers; 667 } 668 669 void OMXVideoDecoderAVCSecure::KeepAliveTimerCallback(sigval v) { 670 OMXVideoDecoderAVCSecure *p = (OMXVideoDecoderAVCSecure *)v.sival_ptr; 671 if (p) { 672 p->KeepAliveTimerCallback(); 673 } 674 } 675 676 void OMXVideoDecoderAVCSecure::KeepAliveTimerCallback() { 677 uint32_t timeout = DRM_KEEP_ALIVE_TIMER; 678 uint32_t sepres = drm_vendor_api.drm_keep_alive(WV_SESSION_ID, &timeout); 679 if (sepres != 0) { 680 ALOGE("Drm_KeepAlive failed. Result = %#x", sepres); 681 } 682 } 683 684 void OMXVideoDecoderAVCSecure::WaitForFrameDisplayed() { 685 if (mDrmDevFd <= 0) { 686 ALOGE("Invalid mDrmDevFd"); 687 return; 688 } 689 690 // Wait up to 200ms until both overlay planes are disabled 691 int status = 3; 692 int retry = 20; 693 while (retry--) { 694 for (int i = 0; i < 2; i++) { 695 if (status & (1 << i)) { 696 struct drm_psb_register_rw_arg arg; 697 memset(&arg, 0, sizeof(struct drm_psb_register_rw_arg)); 698 arg.get_plane_state_mask = 1; 699 arg.plane.type = DC_OVERLAY_PLANE; 700 arg.plane.index = i; 701 int ret = drmCommandWriteRead(mDrmDevFd, DRM_PSB_REGISTER_RW, &arg, sizeof(arg)); 702 if (ret != 0) { 703 ALOGE("Failed to query status of overlay plane %d, ret = %d", i, ret); 704 status &= ~(1 << i); 705 } else if (arg.plane.ctx == PSB_DC_PLANE_DISABLED) { 706 status &= ~(1 << i); 707 } 708 } 709 } 710 if (status == 0) { 711 break; 712 } 713 // Sleep 10ms then query again 714 usleep(10000); 715 } 716 717 if (status != 0) { 718 ALOGE("Overlay planes not disabled, status %d", status); 719 } 720 } 721 722 OMX_ERRORTYPE OMXVideoDecoderAVCSecure::SetMaxOutputBufferCount(OMX_PARAM_PORTDEFINITIONTYPE *p) { 723 OMX_ERRORTYPE ret; 724 CHECK_TYPE_HEADER(p); 725 CHECK_PORT_INDEX(p, OUTPORT_INDEX); 726 727 p->nBufferCountActual = OUTPORT_NATIVE_BUFFER_COUNT; 728 return OMXVideoDecoderBase::SetMaxOutputBufferCount(p); 729 } 730 DECLARE_OMX_COMPONENT("OMX.Intel.VideoDecoder.AVC.secure", "video_decoder.avc", OMXVideoDecoderAVCSecure); 731