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