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