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
EnableIEDSession(bool enable)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
OMXVideoDecoderAVCSecure()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
~OMXVideoDecoderAVCSecure()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
InitInputPortFormatSpecific(OMX_PARAM_PORTDEFINITIONTYPE * paramPortDefinitionInput)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
ProcessorInit(void)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
ProcessorDeinit(void)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
ProcessorStart(void)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
ProcessorStop(void)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
ProcessorFlush(OMX_U32 portIndex)163 OMX_ERRORTYPE OMXVideoDecoderAVCSecure::ProcessorFlush(OMX_U32 portIndex) {
164 return OMXVideoDecoderBase::ProcessorFlush(portIndex);
165 }
166
ProcessorProcess(OMX_BUFFERHEADERTYPE *** pBuffers,buffer_retain_t * retains,OMX_U32 numberBuffers)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
ProcessorPause(void)252 OMX_ERRORTYPE OMXVideoDecoderAVCSecure::ProcessorPause(void) {
253 return OMXVideoDecoderBase::ProcessorPause();
254 }
255
ProcessorResume(void)256 OMX_ERRORTYPE OMXVideoDecoderAVCSecure::ProcessorResume(void) {
257 return OMXVideoDecoderBase::ProcessorResume();
258 }
259
PrepareConfigBuffer(VideoConfigBuffer * p)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
PrepareWVCDecodeBuffer(OMX_BUFFERHEADERTYPE * buffer,buffer_retain_t * retain,VideoDecodeBuffer * p)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 }
PrepareCENCDecodeBuffer(OMX_BUFFERHEADERTYPE * buffer,buffer_retain_t * retain,VideoDecodeBuffer * p)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
PreparePRASFDecodeBuffer(OMX_BUFFERHEADERTYPE * buffer,buffer_retain_t * retain,VideoDecodeBuffer * p)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
PrepareDecodeBuffer(OMX_BUFFERHEADERTYPE * buffer,buffer_retain_t * retain,VideoDecodeBuffer * p)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
BuildHandlerList(void)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
GetParamVideoAvc(OMX_PTR pStructure)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
SetParamVideoAvc(OMX_PTR pStructure)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
GetParamVideoAVCProfileLevel(OMX_PTR pStructure)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
SetParamVideoAVCProfileLevel(OMX_PTR pStructure)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
GetExtAllocateNativeHandle(OMX_PTR pStructure)560 OMX_ERRORTYPE OMXVideoDecoderAVCSecure::GetExtAllocateNativeHandle(OMX_PTR pStructure) {
561 (void) pStructure; // unused parameter
562
563 return OMX_ErrorNone;
564
565 }
566
SetExtAllocateNativeHandle(OMX_PTR pStructure)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 }
MemAllocDataBuffer(OMX_U32 nSizeBytes,OMX_PTR pUserData)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
MemFreeDataBuffer(OMX_U8 * pBuffer,OMX_PTR pUserData)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
MemAllocDataBuffer(OMX_U32 nSizeBytes)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
MemFreeDataBuffer(OMX_U8 * pBuffer)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
KeepAliveTimerCallback(sigval v)669 void OMXVideoDecoderAVCSecure::KeepAliveTimerCallback(sigval v) {
670 OMXVideoDecoderAVCSecure *p = (OMXVideoDecoderAVCSecure *)v.sival_ptr;
671 if (p) {
672 p->KeepAliveTimerCallback();
673 }
674 }
675
KeepAliveTimerCallback()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
WaitForFrameDisplayed()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
SetMaxOutputBufferCount(OMX_PARAM_PORTDEFINITIONTYPE * p)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