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)
36static const char* AVC_MIME_TYPE = "video/avc";
37static 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
53bool 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
64OMXVideoDecoderAVCSecure::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
87OMXVideoDecoderAVCSecure::~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
98OMX_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
119OMX_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
127OMX_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
141OMX_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
153OMX_ERRORTYPE OMXVideoDecoderAVCSecure::ProcessorStop(void) {
154    if (mKeepAliveTimer != 0) {
155        timer_delete(mKeepAliveTimer);
156        mKeepAliveTimer = 0;
157    }
158
159    return OMXVideoDecoderBase::ProcessorStop();
160}
161
162
163OMX_ERRORTYPE OMXVideoDecoderAVCSecure::ProcessorFlush(OMX_U32 portIndex) {
164    return OMXVideoDecoderBase::ProcessorFlush(portIndex);
165}
166
167OMX_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
252OMX_ERRORTYPE OMXVideoDecoderAVCSecure::ProcessorPause(void) {
253    return OMXVideoDecoderBase::ProcessorPause();
254}
255
256OMX_ERRORTYPE OMXVideoDecoderAVCSecure::ProcessorResume(void) {
257    return OMXVideoDecoderBase::ProcessorResume();
258}
259
260OMX_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
268OMX_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}
338OMX_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
365OMX_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
442OMX_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
497OMX_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
505OMX_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
515OMX_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
529OMX_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
553OMX_ERRORTYPE OMXVideoDecoderAVCSecure::SetParamVideoAVCProfileLevel(OMX_PTR pStructure) {
554    ALOGW("SetParamVideoAVCProfileLevel is not supported.");
555    (void) pStructure; // unused parameter
556    return OMX_ErrorUnsupportedSetting;
557}
558
559
560OMX_ERRORTYPE OMXVideoDecoderAVCSecure::GetExtAllocateNativeHandle(OMX_PTR pStructure) {
561    (void) pStructure; // unused parameter
562
563    return OMX_ErrorNone;
564
565}
566
567OMX_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}
575OMX_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
584void 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
593OMX_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
634void 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
663    native_handle_close(native_handle);
664    native_handle_delete(native_handle);
665    ALOGV("Free databuffer %p with data = %p", dataBuffer, dataBuffer->data);
666    --mNumInportBuffers;
667}
668
669void OMXVideoDecoderAVCSecure::KeepAliveTimerCallback(sigval v) {
670    OMXVideoDecoderAVCSecure *p = (OMXVideoDecoderAVCSecure *)v.sival_ptr;
671    if (p) {
672        p->KeepAliveTimerCallback();
673    }
674}
675
676void OMXVideoDecoderAVCSecure::KeepAliveTimerCallback() {
677    uint32_t timeout = DRM_KEEP_ALIVE_TIMER;
678    uint32_t sepres =  drm_vendor_api.drm_keep_alive(WV_SESSION_ID, &timeout);
679    if (sepres != 0) {
680        ALOGE("Drm_KeepAlive failed. Result = %#x", sepres);
681    }
682}
683
684void OMXVideoDecoderAVCSecure::WaitForFrameDisplayed() {
685    if (mDrmDevFd <= 0) {
686        ALOGE("Invalid mDrmDevFd");
687        return;
688    }
689
690    // Wait up to 200ms until both overlay planes are disabled
691    int status = 3;
692    int retry = 20;
693    while (retry--) {
694        for (int i = 0; i < 2; i++) {
695            if (status & (1 << i)) {
696                struct drm_psb_register_rw_arg arg;
697                memset(&arg, 0, sizeof(struct drm_psb_register_rw_arg));
698                arg.get_plane_state_mask = 1;
699                arg.plane.type = DC_OVERLAY_PLANE;
700                arg.plane.index = i;
701                int ret = drmCommandWriteRead(mDrmDevFd, DRM_PSB_REGISTER_RW, &arg, sizeof(arg));
702                if (ret != 0) {
703                    ALOGE("Failed to query status of overlay plane %d, ret = %d", i, ret);
704                    status &= ~(1 << i);
705                } else if (arg.plane.ctx == PSB_DC_PLANE_DISABLED) {
706                    status &= ~(1 << i);
707                }
708            }
709        }
710        if (status == 0) {
711            break;
712        }
713        // Sleep 10ms then query again
714        usleep(10000);
715    }
716
717    if (status != 0) {
718        ALOGE("Overlay planes not disabled, status %d", status);
719    }
720}
721
722OMX_ERRORTYPE OMXVideoDecoderAVCSecure::SetMaxOutputBufferCount(OMX_PARAM_PORTDEFINITIONTYPE *p) {
723    OMX_ERRORTYPE ret;
724    CHECK_TYPE_HEADER(p);
725    CHECK_PORT_INDEX(p, OUTPORT_INDEX);
726
727    p->nBufferCountActual = OUTPORT_NATIVE_BUFFER_COUNT;
728    return OMXVideoDecoderBase::SetMaxOutputBufferCount(p);
729}
730DECLARE_OMX_COMPONENT("OMX.Intel.VideoDecoder.AVC.secure", "video_decoder.avc", OMXVideoDecoderAVCSecure);
731