Home | History | Annotate | Download | only in moorefield
      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 
     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 
     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 
     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 
     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 
    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 
    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 
    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 
    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 
    163 OMX_ERRORTYPE OMXVideoDecoderAVCSecure::ProcessorFlush(OMX_U32 portIndex) {
    164     return OMXVideoDecoderBase::ProcessorFlush(portIndex);
    165 }
    166 
    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 
    252 OMX_ERRORTYPE OMXVideoDecoderAVCSecure::ProcessorPause(void) {
    253     return OMXVideoDecoderBase::ProcessorPause();
    254 }
    255 
    256 OMX_ERRORTYPE OMXVideoDecoderAVCSecure::ProcessorResume(void) {
    257     return OMXVideoDecoderBase::ProcessorResume();
    258 }
    259 
    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 
    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 }
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    560 OMX_ERRORTYPE OMXVideoDecoderAVCSecure::GetExtAllocateNativeHandle(OMX_PTR pStructure) {
    561     (void) pStructure; // unused parameter
    562 
    563     return OMX_ErrorNone;
    564 
    565 }
    566 
    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 }
    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 
    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 
    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 
    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 
    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 
    669 void OMXVideoDecoderAVCSecure::KeepAliveTimerCallback(sigval v) {
    670     OMXVideoDecoderAVCSecure *p = (OMXVideoDecoderAVCSecure *)v.sival_ptr;
    671     if (p) {
    672         p->KeepAliveTimerCallback();
    673     }
    674 }
    675 
    676 void 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 
    684 void 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 
    722 OMX_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 }
    730 DECLARE_OMX_COMPONENT("OMX.Intel.VideoDecoder.AVC.secure", "video_decoder.avc", OMXVideoDecoderAVCSecure);
    731