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