• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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