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