Home | History | Annotate | Download | only in src
      1 /*
      2  *
      3  * Copyright 2012 Samsung Electronics S.LSI Co. LTD
      4  *
      5  * Licensed under the Apache License, Version 2.0 (the "License");
      6  * you may not use this file except in compliance with the License.
      7  * You may obtain a copy of the License at
      8  *
      9  *      http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  * Unless required by applicable law or agreed to in writing, software
     12  * distributed under the License is distributed on an "AS IS" BASIS,
     13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  * See the License for the specific language governing permissions and
     15  * limitations under the License.
     16  */
     17 
     18 /*
     19  * @file        ExynosVideoDecoder.c
     20  * @brief
     21  * @author      Jinsung Yang (jsgood.yang (at) samsung.com)
     22  * @version     1.0.0
     23  * @history
     24  *   2012.01.15: Initial Version
     25  */
     26 
     27 #include <stdio.h>
     28 #include <stdlib.h>
     29 #include <unistd.h>
     30 #include <string.h>
     31 #include <fcntl.h>
     32 
     33 #include <sys/types.h>
     34 #include <sys/stat.h>
     35 #include <sys/ioctl.h>
     36 #include <sys/mman.h>
     37 #include <pthread.h>
     38 
     39 #include <sys/poll.h>
     40 
     41 #include "ion.h"
     42 #include "ExynosVideoApi.h"
     43 #include "ExynosVideoDec.h"
     44 #include "OMX_Core.h"
     45 
     46 /* #define LOG_NDEBUG 0 */
     47 #define LOG_TAG "ExynosVideoDecoder"
     48 #include <utils/Log.h>
     49 
     50 #define MAX_OUTPUTBUFFER_COUNT 32
     51 
     52 /*
     53  * [Common] __CodingType_To_V4L2PixelFormat
     54  */
     55 static unsigned int __CodingType_To_V4L2PixelFormat(ExynosVideoCodingType codingType)
     56 {
     57     unsigned int pixelformat = V4L2_PIX_FMT_H264;
     58 
     59     switch (codingType) {
     60     case VIDEO_CODING_AVC:
     61         pixelformat = V4L2_PIX_FMT_H264;
     62         break;
     63     case VIDEO_CODING_MPEG4:
     64         pixelformat = V4L2_PIX_FMT_MPEG4;
     65         break;
     66     case VIDEO_CODING_VP8:
     67         pixelformat = V4L2_PIX_FMT_VP8;
     68         break;
     69     case VIDEO_CODING_H263:
     70         pixelformat = V4L2_PIX_FMT_H263;
     71         break;
     72     case VIDEO_CODING_VC1:
     73         pixelformat = V4L2_PIX_FMT_VC1_ANNEX_G;
     74         break;
     75     case VIDEO_CODING_VC1_RCV:
     76         pixelformat = V4L2_PIX_FMT_VC1_ANNEX_L;
     77         break;
     78     case VIDEO_CODING_MPEG2:
     79         pixelformat = V4L2_PIX_FMT_MPEG2;
     80         break;
     81     default:
     82         pixelformat = V4L2_PIX_FMT_H264;
     83         break;
     84     }
     85 
     86     return pixelformat;
     87 }
     88 
     89 /*
     90  * [Common] __ColorFormatType_To_V4L2PixelFormat
     91  */
     92 static unsigned int __ColorFormatType_To_V4L2PixelFormat(ExynosVideoColorFormatType colorFormatType)
     93 {
     94     unsigned int pixelformat = V4L2_PIX_FMT_NV12M;
     95 
     96     switch (colorFormatType) {
     97     case VIDEO_COLORFORMAT_NV12_TILED:
     98         pixelformat = V4L2_PIX_FMT_NV12MT_16X16;
     99         break;
    100     case VIDEO_COLORFORMAT_NV21:
    101         pixelformat = V4L2_PIX_FMT_NV21M;
    102         break;
    103     case VIDEO_COLORFORMAT_NV12:
    104     default:
    105         pixelformat = V4L2_PIX_FMT_NV12M;
    106         break;
    107     }
    108 
    109     return pixelformat;
    110 }
    111 
    112 /*
    113  * [Decoder OPS] Init
    114  */
    115 static void *MFC_Decoder_Init(int nMemoryType)
    116 {
    117     ExynosVideoDecContext *pCtx     = NULL;
    118     pthread_mutex_t       *pMutex   = NULL;
    119     int                    needCaps = (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING);
    120 
    121     pCtx = (ExynosVideoDecContext *)malloc(sizeof(*pCtx));
    122     if (pCtx == NULL) {
    123         ALOGE("%s: Failed to allocate decoder context buffer", __func__);
    124         goto EXIT_ALLOC_FAIL;
    125     }
    126 
    127     memset(pCtx, 0, sizeof(*pCtx));
    128 
    129     pCtx->hDec = exynos_v4l2_open_devname(VIDEO_DECODER_NAME, O_RDWR, 0);
    130     if (pCtx->hDec < 0) {
    131         ALOGE("%s: Failed to open decoder device", __func__);
    132         goto EXIT_OPEN_FAIL;
    133     }
    134 
    135     if (!exynos_v4l2_querycap(pCtx->hDec, needCaps)) {
    136         ALOGE("%s: Failed to querycap", __func__);
    137         goto EXIT_QUERYCAP_FAIL;
    138     }
    139 
    140     pCtx->bStreamonInbuf = VIDEO_FALSE;
    141     pCtx->bStreamonOutbuf = VIDEO_FALSE;
    142 
    143     pCtx->nMemoryType = nMemoryType;
    144 
    145     pMutex = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t));
    146     if (pMutex == NULL) {
    147         ALOGE("%s: Failed to allocate mutex about input buffer", __func__);
    148         goto EXIT_QUERYCAP_FAIL;
    149     }
    150     if (pthread_mutex_init(pMutex, NULL) != 0) {
    151         free(pMutex);
    152         goto EXIT_QUERYCAP_FAIL;
    153     }
    154     pCtx->pInMutex = (void*)pMutex;
    155 
    156     pMutex = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t));
    157     if (pMutex == NULL) {
    158         ALOGE("%s: Failed to allocate mutex about output buffer", __func__);
    159         goto EXIT_QUERYCAP_FAIL;
    160     }
    161     if (pthread_mutex_init(pMutex, NULL) != 0) {
    162         free(pMutex);
    163         goto EXIT_QUERYCAP_FAIL;
    164     }
    165     pCtx->pOutMutex = (void*)pMutex;
    166 
    167     pCtx->hIONHandle = (void*)ion_client_create();
    168     pCtx->nPrivateDataShareFD = ion_alloc((ion_client)pCtx->hIONHandle,
    169               sizeof(PrivateDataShareBuffer) * VIDEO_BUFFER_MAX_NUM, 0, ION_HEAP_SYSTEM_MASK, ION_FLAG_CACHED);
    170     pCtx->nPrivateDataShareAddress =
    171               ion_map(pCtx->nPrivateDataShareFD, sizeof(PrivateDataShareBuffer) * VIDEO_BUFFER_MAX_NUM, 0);
    172     memset(pCtx->nPrivateDataShareAddress, -1, sizeof(PrivateDataShareBuffer) * VIDEO_BUFFER_MAX_NUM);
    173 
    174     return (void *)pCtx;
    175 
    176 EXIT_QUERYCAP_FAIL:
    177     if (pCtx->pInMutex != NULL) {
    178         pthread_mutex_destroy(pCtx->pInMutex);
    179         free(pCtx->pInMutex);
    180     }
    181 
    182     if (pCtx->pOutMutex != NULL) {
    183         pthread_mutex_destroy(pCtx->pOutMutex);
    184         free(pCtx->pOutMutex);
    185     }
    186 
    187     close(pCtx->hDec);
    188 
    189 EXIT_OPEN_FAIL:
    190     free(pCtx);
    191 
    192 EXIT_ALLOC_FAIL:
    193     return NULL;
    194 }
    195 
    196 /*
    197  * [Decoder OPS] Finalize
    198  */
    199 static ExynosVideoErrorType MFC_Decoder_Finalize(void *pHandle)
    200 {
    201     ExynosVideoDecContext *pCtx         = (ExynosVideoDecContext *)pHandle;
    202     ExynosVideoPlane      *pVideoPlane  = NULL;
    203     pthread_mutex_t       *pMutex       = NULL;
    204     ExynosVideoErrorType   ret          = VIDEO_ERROR_NONE;
    205     int i, j;
    206 
    207     if (pCtx == NULL) {
    208         ALOGE("%s: Video context info must be supplied", __func__);
    209         ret = VIDEO_ERROR_BADPARAM;
    210         goto EXIT;
    211     }
    212 
    213     ion_unmap(pCtx->nPrivateDataShareAddress, sizeof(PrivateDataShareBuffer) * VIDEO_BUFFER_MAX_NUM);
    214     ion_free(pCtx->nPrivateDataShareFD);
    215     ion_client_destroy((ion_client)pCtx->hIONHandle);
    216 
    217     if (pCtx->pOutMutex != NULL) {
    218         pMutex = (pthread_mutex_t*)pCtx->pOutMutex;
    219         pthread_mutex_destroy(pMutex);
    220         free(pMutex);
    221         pCtx->pOutMutex = NULL;
    222     }
    223 
    224     if (pCtx->pInMutex != NULL) {
    225         pMutex = (pthread_mutex_t*)pCtx->pInMutex;
    226         pthread_mutex_destroy(pMutex);
    227         free(pMutex);
    228         pCtx->pInMutex = NULL;
    229     }
    230 
    231     if (pCtx->bShareInbuf == VIDEO_FALSE) {
    232         for (i = 0; i < pCtx->nInbufs; i++) {
    233             for (j = 0; j < VIDEO_DECODER_INBUF_PLANES; j++) {
    234                 pVideoPlane = &pCtx->pInbuf[i].planes[j];
    235                 if (pVideoPlane->addr != NULL) {
    236                     munmap(pVideoPlane->addr, pVideoPlane->allocSize);
    237                     pVideoPlane->addr = NULL;
    238                     pVideoPlane->allocSize = 0;
    239                     pVideoPlane->dataSize = 0;
    240                 }
    241 
    242                 pCtx->pInbuf[i].pGeometry = NULL;
    243                 pCtx->pInbuf[i].bQueued = VIDEO_FALSE;
    244                 pCtx->pInbuf[i].bRegistered = VIDEO_FALSE;
    245             }
    246         }
    247     }
    248 
    249     if (pCtx->bShareOutbuf == VIDEO_FALSE) {
    250         for (i = 0; i < pCtx->nOutbufs; i++) {
    251             for (j = 0; j < VIDEO_DECODER_OUTBUF_PLANES; j++) {
    252                 pVideoPlane = &pCtx->pOutbuf[i].planes[j];
    253                 if (pVideoPlane->addr != NULL) {
    254                     munmap(pVideoPlane->addr, pVideoPlane->allocSize);
    255                     pVideoPlane->addr = NULL;
    256                     pVideoPlane->allocSize = 0;
    257                     pVideoPlane->dataSize = 0;
    258                 }
    259 
    260                 pCtx->pOutbuf[i].pGeometry = NULL;
    261                 pCtx->pOutbuf[i].bQueued = VIDEO_FALSE;
    262                 pCtx->pOutbuf[i].bRegistered = VIDEO_FALSE;
    263             }
    264         }
    265     }
    266 
    267     if (pCtx->pInbuf != NULL)
    268         free(pCtx->pInbuf);
    269 
    270     if (pCtx->pOutbuf != NULL)
    271         free(pCtx->pOutbuf);
    272 
    273     if (pCtx->hDec > 0)
    274         close(pCtx->hDec);
    275 
    276     free(pCtx);
    277 
    278 EXIT:
    279     return ret;
    280 }
    281 
    282 /*
    283  * [Decoder OPS] Set Frame Tag
    284  */
    285 static ExynosVideoErrorType MFC_Decoder_Set_FrameTag(
    286     void *pHandle,
    287     int   frameTag)
    288 {
    289     ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
    290     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
    291 
    292     if (pCtx == NULL) {
    293         ALOGE("%s: Video context info must be supplied", __func__);
    294         ret = VIDEO_ERROR_BADPARAM;
    295         goto EXIT;
    296     }
    297 
    298     if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG, frameTag) != 0) {
    299         ret = VIDEO_ERROR_APIFAIL;
    300         goto EXIT;
    301     }
    302 
    303 EXIT:
    304     return ret;
    305 }
    306 
    307 /*
    308  * [Decoder OPS] Get Frame Tag
    309  */
    310 static int MFC_Decoder_Get_FrameTag(void *pHandle)
    311 {
    312     ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
    313     int frameTag = -1;
    314 
    315     if (pCtx == NULL) {
    316         ALOGE("%s: Video context info must be supplied", __func__);
    317         goto EXIT;
    318     }
    319 
    320     exynos_v4l2_g_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG, &frameTag);
    321 
    322 EXIT:
    323     return frameTag;
    324 }
    325 
    326 /*
    327  * [Decoder OPS] Get Buffer Count
    328  */
    329 static int MFC_Decoder_Get_ActualBufferCount(void *pHandle)
    330 {
    331     ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
    332     int bufferCount = -1;
    333 
    334     if (pCtx == NULL) {
    335         ALOGE("%s: Video context info must be supplied", __func__);
    336         goto EXIT;
    337     }
    338 
    339     exynos_v4l2_g_ctrl(pCtx->hDec, V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, &bufferCount);
    340 
    341 EXIT:
    342     return bufferCount;
    343 }
    344 
    345 /*
    346  * [Decoder OPS] Set Display Delay
    347  */
    348 static ExynosVideoErrorType MFC_Decoder_Set_DisplayDelay(
    349     void *pHandle,
    350     int   delay)
    351 {
    352     ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
    353     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
    354 
    355     if (pCtx == NULL) {
    356         ALOGE("%s: Video context info must be supplied", __func__);
    357         ret = VIDEO_ERROR_BADPARAM;
    358         goto EXIT;
    359     }
    360 
    361     if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY, delay) != 0) {
    362         ret = VIDEO_ERROR_APIFAIL;
    363         goto EXIT;
    364     }
    365 
    366 EXIT:
    367     return ret;
    368 }
    369 
    370 /*
    371  * [Decoder OPS] Set I-Frame Decoding
    372  */
    373 static ExynosVideoErrorType MFC_Decoder_Set_IFrameDecoding(
    374     void *pHandle)
    375 {
    376     ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
    377     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
    378 
    379     if (pCtx == NULL) {
    380         ALOGE("%s: Video context info must be supplied", __func__);
    381         ret = VIDEO_ERROR_BADPARAM;
    382         goto EXIT;
    383     }
    384 
    385     if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC51_VIDEO_I_FRAME_DECODING, 1) != 0) {
    386         ret = VIDEO_ERROR_APIFAIL;
    387         goto EXIT;
    388     }
    389 
    390 EXIT:
    391     return ret;
    392 }
    393 
    394 /*
    395  * [Decoder OPS] Enable Packed PB
    396  */
    397 static ExynosVideoErrorType MFC_Decoder_Enable_PackedPB(void *pHandle)
    398 {
    399     ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
    400     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
    401 
    402     if (pCtx == NULL) {
    403         ALOGE("%s: Video context info must be supplied", __func__);
    404         ret = VIDEO_ERROR_BADPARAM;
    405         goto EXIT;
    406     }
    407 
    408     if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC51_VIDEO_PACKED_PB, 1) != 0) {
    409         ret = VIDEO_ERROR_APIFAIL;
    410         goto EXIT;
    411     }
    412 
    413 EXIT:
    414     return ret;
    415 }
    416 
    417 /*
    418  * [Decoder OPS] Enable Loop Filter
    419  */
    420 static ExynosVideoErrorType MFC_Decoder_Enable_LoopFilter(void *pHandle)
    421 {
    422     ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
    423     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
    424 
    425     if (pCtx == NULL) {
    426         ALOGE("%s: Video context info must be supplied", __func__);
    427         ret = VIDEO_ERROR_BADPARAM;
    428         goto EXIT;
    429     }
    430 
    431     if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER, 1) != 0) {
    432         ret = VIDEO_ERROR_APIFAIL;
    433         goto EXIT;
    434     }
    435 
    436 EXIT:
    437     return ret;
    438 }
    439 
    440 /*
    441  * [Decoder OPS] Enable Slice Mode
    442  */
    443 static ExynosVideoErrorType MFC_Decoder_Enable_SliceMode(void *pHandle)
    444 {
    445     ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
    446     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
    447 
    448     if (pCtx == NULL) {
    449         ALOGE("%s: Video context info must be supplied", __func__);
    450         ret = VIDEO_ERROR_BADPARAM;
    451         goto EXIT;
    452     }
    453 
    454     if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE, 1) != 0) {
    455         ret = VIDEO_ERROR_APIFAIL;
    456         goto EXIT;
    457     }
    458 
    459 EXIT:
    460     return ret;
    461 }
    462 
    463 /*
    464  * [Decoder OPS] Enable SEI Parsing
    465  */
    466 static ExynosVideoErrorType MFC_Decoder_Enable_SEIParsing(void *pHandle)
    467 {
    468     ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
    469     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
    470 
    471     if (pCtx == NULL) {
    472         ALOGE("%s: Video context info must be supplied", __func__);
    473         ret = VIDEO_ERROR_BADPARAM;
    474         goto EXIT;
    475     }
    476 
    477     if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_MPEG_VIDEO_H264_SEI_FRAME_PACKING, 1) != 0) {
    478         ret = VIDEO_ERROR_APIFAIL;
    479         goto EXIT;
    480     }
    481 
    482 EXIT:
    483     return ret;
    484 }
    485 
    486 /*
    487  * [Decoder OPS] Get Frame Packing information
    488  */
    489 static ExynosVideoErrorType MFC_Decoder_Get_FramePackingInfo(
    490     void                    *pHandle,
    491     ExynosVideoFramePacking *pFramePacking)
    492 {
    493     ExynosVideoDecContext   *pCtx = (ExynosVideoDecContext *)pHandle;
    494     ExynosVideoErrorType     ret  = VIDEO_ERROR_NONE;
    495 
    496     struct v4l2_ext_control  ext_ctrl[FRAME_PACK_SEI_INFO_NUM];
    497     struct v4l2_ext_controls ext_ctrls;
    498 
    499     int seiAvailable, seiInfo, seiGridPos, i;
    500     unsigned int seiArgmtId;
    501 
    502 
    503     if ((pCtx == NULL) || (pFramePacking == NULL)) {
    504         ALOGE("%s: Video context info or FramePacking pointer must be supplied", __func__);
    505         ret = VIDEO_ERROR_BADPARAM;
    506         goto EXIT;
    507     }
    508 
    509     memset(pFramePacking, 0, sizeof(*pFramePacking));
    510     memset(ext_ctrl, 0, (sizeof(struct v4l2_ext_control) * FRAME_PACK_SEI_INFO_NUM));
    511 
    512     ext_ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
    513     ext_ctrls.count = FRAME_PACK_SEI_INFO_NUM;
    514     ext_ctrls.controls = ext_ctrl;
    515     ext_ctrl[0].id =  V4L2_CID_MPEG_VIDEO_H264_SEI_FP_AVAIL;
    516     ext_ctrl[1].id =  V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRGMENT_ID;
    517     ext_ctrl[2].id =  V4L2_CID_MPEG_VIDEO_H264_SEI_FP_INFO;
    518     ext_ctrl[3].id =  V4L2_CID_MPEG_VIDEO_H264_SEI_FP_GRID_POS;
    519 
    520     if (exynos_v4l2_g_ext_ctrl(pCtx->hDec, &ext_ctrls) != 0) {
    521         ret = VIDEO_ERROR_APIFAIL;
    522         goto EXIT;
    523     }
    524 
    525     seiAvailable = ext_ctrl[0].value;
    526     seiArgmtId = ext_ctrl[1].value;
    527     seiInfo = ext_ctrl[2].value;
    528     seiGridPos = ext_ctrl[3].value;
    529 
    530     pFramePacking->available = seiAvailable;
    531     pFramePacking->arrangement_id = seiArgmtId;
    532 
    533     pFramePacking->arrangement_cancel_flag = OPERATE_BIT(seiInfo, 0x1, 0);
    534     pFramePacking->arrangement_type = OPERATE_BIT(seiInfo, 0x3f, 1);
    535     pFramePacking->quincunx_sampling_flag = OPERATE_BIT(seiInfo, 0x1, 8);
    536     pFramePacking->content_interpretation_type = OPERATE_BIT(seiInfo, 0x3f, 9);
    537     pFramePacking->spatial_flipping_flag = OPERATE_BIT(seiInfo, 0x1, 15);
    538     pFramePacking->frame0_flipped_flag = OPERATE_BIT(seiInfo, 0x1, 16);
    539     pFramePacking->field_views_flag = OPERATE_BIT(seiInfo, 0x1, 17);
    540     pFramePacking->current_frame_is_frame0_flag = OPERATE_BIT(seiInfo, 0x1, 18);
    541 
    542     pFramePacking->frame0_grid_pos_x = OPERATE_BIT(seiGridPos, 0xf, 0);
    543     pFramePacking->frame0_grid_pos_y = OPERATE_BIT(seiGridPos, 0xf, 4);
    544     pFramePacking->frame1_grid_pos_x = OPERATE_BIT(seiGridPos, 0xf, 8);
    545     pFramePacking->frame1_grid_pos_y = OPERATE_BIT(seiGridPos, 0xf, 12);
    546 
    547 EXIT:
    548     return ret;
    549 }
    550 
    551 /*
    552  * [Decoder Buffer OPS] Enable Cacheable (Input)
    553  */
    554 static ExynosVideoErrorType MFC_Decoder_Enable_Cacheable_Inbuf(void *pHandle)
    555 {
    556     ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
    557     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
    558 
    559     if (pCtx == NULL) {
    560         ALOGE("%s: Video context info must be supplied", __func__);
    561         ret = VIDEO_ERROR_BADPARAM;
    562         goto EXIT;
    563     }
    564 
    565     if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_CACHEABLE, 2) != 0) {
    566         ret = VIDEO_ERROR_APIFAIL;
    567         goto EXIT;
    568     }
    569 
    570 EXIT:
    571     return ret;
    572 }
    573 
    574 /*
    575  * [Decoder Buffer OPS] Enable Cacheable (Output)
    576  */
    577 static ExynosVideoErrorType MFC_Decoder_Enable_Cacheable_Outbuf(void *pHandle)
    578 {
    579     ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
    580     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
    581 
    582     if (pCtx == NULL) {
    583         ALOGE("%s: Video context info must be supplied", __func__);
    584         ret = VIDEO_ERROR_BADPARAM;
    585         goto EXIT;
    586     }
    587 
    588     if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_CACHEABLE, 1) != 0) {
    589         ret = VIDEO_ERROR_APIFAIL;
    590         goto EXIT;
    591     }
    592 
    593 EXIT:
    594     return ret;
    595 }
    596 
    597 /*
    598  * [Decoder Buffer OPS] Set Shareable Buffer (Input)
    599  */
    600 static ExynosVideoErrorType MFC_Decoder_Set_Shareable_Inbuf(void *pHandle)
    601 {
    602     ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
    603     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
    604 
    605     if (pCtx == NULL) {
    606         ALOGE("%s: Video context info must be supplied", __func__);
    607         ret = VIDEO_ERROR_BADPARAM;
    608         goto EXIT;
    609     }
    610 
    611     pCtx->bShareInbuf = VIDEO_TRUE;
    612 
    613 EXIT:
    614     return ret;
    615 }
    616 
    617 /*
    618  * [Decoder Buffer OPS] Set Shareable Buffer (Output)
    619  */
    620 static ExynosVideoErrorType MFC_Decoder_Set_Shareable_Outbuf(void *pHandle)
    621 {
    622     ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
    623     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
    624 
    625     if (pCtx == NULL) {
    626         ALOGE("%s: Video context info must be supplied", __func__);
    627         ret = VIDEO_ERROR_BADPARAM;
    628         goto EXIT;
    629     }
    630 
    631     pCtx->bShareOutbuf = VIDEO_TRUE;
    632 
    633 EXIT:
    634     return ret;
    635 }
    636 
    637 /*
    638  * [Decoder Buffer OPS] Get Buffer (Input)
    639  */
    640 static ExynosVideoErrorType MFC_Decoder_Get_Buffer_Inbuf(
    641     void               *pHandle,
    642     int                 nIndex,
    643     ExynosVideoBuffer **pBuffer)
    644 {
    645     ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
    646     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
    647 
    648     if (pCtx == NULL) {
    649         ALOGE("%s: Video context info must be supplied", __func__);
    650         *pBuffer = NULL;
    651         ret = VIDEO_ERROR_BADPARAM;
    652         goto EXIT;
    653     }
    654 
    655     if (pCtx->nInbufs <= nIndex) {
    656         *pBuffer = NULL;
    657         ret = VIDEO_ERROR_BADPARAM;
    658         goto EXIT;
    659     }
    660 
    661     *pBuffer = (ExynosVideoBuffer *)&pCtx->pInbuf[nIndex];
    662 
    663 EXIT:
    664     return ret;
    665 }
    666 
    667 /*
    668  * [Decoder Buffer OPS] Get Buffer (Output)
    669  */
    670 static ExynosVideoErrorType MFC_Decoder_Get_Buffer_Outbuf(
    671     void               *pHandle,
    672     int                 nIndex,
    673     ExynosVideoBuffer **pBuffer)
    674 {
    675     ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
    676     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
    677 
    678     if (pCtx == NULL) {
    679         ALOGE("%s: Video context info must be supplied", __func__);
    680         *pBuffer = NULL;
    681         ret = VIDEO_ERROR_BADPARAM;
    682         goto EXIT;
    683     }
    684 
    685     if (pCtx->nOutbufs <= nIndex) {
    686         *pBuffer = NULL;
    687         ret = VIDEO_ERROR_BADPARAM;
    688         goto EXIT;
    689     }
    690 
    691     *pBuffer = (ExynosVideoBuffer *)&pCtx->pOutbuf[nIndex];
    692 
    693 EXIT:
    694     return ret;
    695 }
    696 
    697 /*
    698  * [Decoder Buffer OPS] Set Geometry (Input)
    699  */
    700 static ExynosVideoErrorType MFC_Decoder_Set_Geometry_Inbuf(
    701     void                *pHandle,
    702     ExynosVideoGeometry *bufferConf)
    703 {
    704     ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
    705     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
    706 
    707     struct v4l2_format fmt;
    708 
    709     if (pCtx == NULL) {
    710         ALOGE("%s: Video context info must be supplied", __func__);
    711         ret = VIDEO_ERROR_BADPARAM;
    712         goto EXIT;
    713     }
    714 
    715     if (bufferConf == NULL) {
    716         ALOGE("%s: Buffer geometry must be supplied", __func__);
    717         ret = VIDEO_ERROR_BADPARAM;
    718         goto EXIT;
    719     }
    720 
    721     memset(&fmt, 0, sizeof(fmt));
    722 
    723     fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
    724     fmt.fmt.pix_mp.pixelformat = __CodingType_To_V4L2PixelFormat(bufferConf->eCompressionFormat);
    725     fmt.fmt.pix_mp.plane_fmt[0].sizeimage = bufferConf->nSizeImage;
    726 
    727     if (exynos_v4l2_s_fmt(pCtx->hDec, &fmt) != 0) {
    728         ret = VIDEO_ERROR_APIFAIL;
    729         goto EXIT;
    730     }
    731 
    732     memcpy(&pCtx->inbufGeometry, bufferConf, sizeof(pCtx->inbufGeometry));
    733 
    734 EXIT:
    735     return ret;
    736 }
    737 
    738 /*
    739  * [Decoder Buffer OPS] Set Geometry (Output)
    740  */
    741 static ExynosVideoErrorType MFC_Decoder_Set_Geometry_Outbuf(
    742     void                *pHandle,
    743     ExynosVideoGeometry *bufferConf)
    744 {
    745     ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
    746     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
    747 
    748     struct v4l2_format fmt;
    749 
    750     if (pCtx == NULL) {
    751         ALOGE("%s: Video context info must be supplied", __func__);
    752         ret = VIDEO_ERROR_BADPARAM;
    753         goto EXIT;
    754     }
    755 
    756     if (bufferConf == NULL) {
    757         ALOGE("%s: Buffer geometry must be supplied", __func__);
    758         ret = VIDEO_ERROR_BADPARAM;
    759         goto EXIT;
    760     }
    761 
    762     memset(&fmt, 0, sizeof(fmt));
    763 
    764     fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
    765     fmt.fmt.pix_mp.pixelformat = __ColorFormatType_To_V4L2PixelFormat(bufferConf->eColorFormat);
    766 
    767     if (exynos_v4l2_s_fmt(pCtx->hDec, &fmt) != 0) {
    768         ret = VIDEO_ERROR_APIFAIL;
    769         goto EXIT;
    770     }
    771 
    772     memcpy(&pCtx->outbufGeometry, bufferConf, sizeof(pCtx->outbufGeometry));
    773 
    774 EXIT:
    775     return ret;
    776 }
    777 
    778 /*
    779  * [Decoder Buffer OPS] Get Geometry (Output)
    780  */
    781 static ExynosVideoErrorType MFC_Decoder_Get_Geometry_Outbuf(
    782     void                *pHandle,
    783     ExynosVideoGeometry *bufferConf)
    784 {
    785     ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
    786     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
    787 
    788     struct v4l2_format fmt;
    789     struct v4l2_crop   crop;
    790 
    791     if (pCtx == NULL) {
    792         ALOGE("%s: Video context info must be supplied", __func__);
    793         ret = VIDEO_ERROR_BADPARAM;
    794         goto EXIT;
    795     }
    796 
    797     if (bufferConf == NULL) {
    798         ALOGE("%s: Buffer geometry must be supplied", __func__);
    799         ret = VIDEO_ERROR_BADPARAM;
    800         goto EXIT;
    801     }
    802 
    803     memset(&fmt, 0, sizeof(fmt));
    804     memset(&crop, 0, sizeof(crop));
    805 
    806     fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
    807     if (exynos_v4l2_g_fmt(pCtx->hDec, &fmt) != 0) {
    808         ret = VIDEO_ERROR_APIFAIL;
    809         goto EXIT;
    810     }
    811 
    812     crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
    813     if (exynos_v4l2_g_crop(pCtx->hDec, &crop) != 0) {
    814         ret = VIDEO_ERROR_APIFAIL;
    815         goto EXIT;
    816     }
    817 
    818     bufferConf->nFrameWidth = fmt.fmt.pix_mp.width;
    819     bufferConf->nFrameHeight = fmt.fmt.pix_mp.height;
    820 
    821     bufferConf->cropRect.nTop = crop.c.top;
    822     bufferConf->cropRect.nLeft = crop.c.left;
    823     bufferConf->cropRect.nWidth = crop.c.width;
    824     bufferConf->cropRect.nHeight = crop.c.height;
    825 
    826 EXIT:
    827     return ret;
    828 }
    829 
    830 /*
    831  * [Decoder Buffer OPS] Setup (Input)
    832  */
    833 static ExynosVideoErrorType MFC_Decoder_Setup_Inbuf(
    834     void         *pHandle,
    835     unsigned int  nBufferCount)
    836 {
    837     ExynosVideoDecContext *pCtx         = (ExynosVideoDecContext *)pHandle;
    838     ExynosVideoPlane      *pVideoPlane  = NULL;
    839     ExynosVideoErrorType   ret          = VIDEO_ERROR_NONE;
    840 
    841     struct v4l2_requestbuffers req;
    842     struct v4l2_buffer         buf;
    843     struct v4l2_plane          planes[VIDEO_DECODER_INBUF_PLANES];
    844     int i;
    845 
    846     if (pCtx == NULL) {
    847         ALOGE("%s: Video context info must be supplied", __func__);
    848         ret = VIDEO_ERROR_BADPARAM;
    849         goto EXIT;
    850     }
    851 
    852     if (nBufferCount == 0) {
    853         ALOGE("%s: Buffer count must be greater than 0", __func__);
    854         ret = VIDEO_ERROR_BADPARAM;
    855         goto EXIT;
    856     }
    857 
    858     ALOGV("%s: setting up inbufs (%d) shared=%s\n", __func__, nBufferCount,
    859           pCtx->bShareInbuf ? "true" : "false");
    860 
    861     memset(&req, 0, sizeof(req));
    862 
    863     req.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
    864     req.count = nBufferCount;
    865 
    866     if (pCtx->bShareInbuf == VIDEO_TRUE)
    867         req.memory = pCtx->nMemoryType;
    868     else
    869         req.memory = V4L2_MEMORY_MMAP;
    870 
    871     if (exynos_v4l2_reqbufs(pCtx->hDec, &req) != 0) {
    872         ret = VIDEO_ERROR_APIFAIL;
    873         goto EXIT;
    874     }
    875 
    876     if (req.count != nBufferCount) {
    877         ALOGE("%s: asked for %d, got %d\n", __func__, nBufferCount, req.count);
    878         ret = VIDEO_ERROR_NOMEM;
    879         goto EXIT;
    880     }
    881 
    882     pCtx->nInbufs = (int)req.count;
    883 
    884     pCtx->pInbuf = malloc(sizeof(*pCtx->pInbuf) * pCtx->nInbufs);
    885     if (pCtx->pInbuf == NULL) {
    886         ALOGE("Failed to allocate input buffer context");
    887         ret = VIDEO_ERROR_NOMEM;
    888         goto EXIT;
    889     }
    890     memset(pCtx->pInbuf, 0, sizeof(*pCtx->pInbuf) * pCtx->nInbufs);
    891 
    892     memset(&buf, 0, sizeof(buf));
    893 
    894     if (pCtx->bShareInbuf == VIDEO_FALSE) {
    895         buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
    896         buf.memory = V4L2_MEMORY_MMAP;
    897         buf.m.planes = planes;
    898         buf.length = VIDEO_DECODER_INBUF_PLANES;
    899 
    900         for (i = 0; i < pCtx->nInbufs; i++) {
    901             buf.index = i;
    902             if (exynos_v4l2_querybuf(pCtx->hDec, &buf) != 0) {
    903                 ret = VIDEO_ERROR_APIFAIL;
    904                 goto EXIT;
    905             }
    906 
    907             pVideoPlane = &pCtx->pInbuf[i].planes[0];
    908 
    909             pVideoPlane->addr = mmap(NULL,
    910                     buf.m.planes[0].length, PROT_READ | PROT_WRITE,
    911                     MAP_SHARED, pCtx->hDec, buf.m.planes[0].m.mem_offset);
    912 
    913             if (pVideoPlane->addr == MAP_FAILED) {
    914                 ret = VIDEO_ERROR_MAPFAIL;
    915                 goto EXIT;
    916             }
    917 
    918             pVideoPlane->allocSize = buf.m.planes[0].length;
    919             pVideoPlane->dataSize = 0;
    920 
    921             pCtx->pInbuf[i].pGeometry = &pCtx->inbufGeometry;
    922             pCtx->pInbuf[i].bQueued = VIDEO_FALSE;
    923             pCtx->pInbuf[i].bRegistered = VIDEO_TRUE;
    924         }
    925     }
    926 
    927     return ret;
    928 
    929 EXIT:
    930     if ((pCtx != NULL) && (pCtx->pInbuf != NULL)) {
    931         if (pCtx->bShareInbuf == VIDEO_FALSE) {
    932             for (i = 0; i < pCtx->nInbufs; i++) {
    933                 pVideoPlane = &pCtx->pInbuf[i].planes[0];
    934                 if (pVideoPlane->addr == MAP_FAILED) {
    935                     pVideoPlane->addr = NULL;
    936                     break;
    937                 }
    938 
    939                 munmap(pVideoPlane->addr, pVideoPlane->allocSize);
    940             }
    941         }
    942 
    943         free(pCtx->pInbuf);
    944     }
    945 
    946     return ret;
    947 }
    948 
    949 /*
    950  * [Decoder Buffer OPS] Setup (Output)
    951  */
    952 static ExynosVideoErrorType MFC_Decoder_Setup_Outbuf(
    953     void         *pHandle,
    954     unsigned int  nBufferCount)
    955 {
    956     ExynosVideoDecContext *pCtx         = (ExynosVideoDecContext *)pHandle;
    957     ExynosVideoPlane      *pVideoPlane  = NULL;
    958     ExynosVideoErrorType   ret          = VIDEO_ERROR_NONE;
    959 
    960     struct v4l2_requestbuffers req;
    961     struct v4l2_buffer         buf;
    962     struct v4l2_plane          planes[VIDEO_DECODER_OUTBUF_PLANES];
    963     int i, j;
    964 
    965     if (pCtx == NULL) {
    966         ALOGE("%s: Video context info must be supplied", __func__);
    967         ret = VIDEO_ERROR_BADPARAM;
    968         goto EXIT;
    969     }
    970 
    971     if (nBufferCount == 0) {
    972         nBufferCount = MAX_OUTPUTBUFFER_COUNT;
    973         ALOGV("%s: Change buffer count %d", __func__, nBufferCount);
    974     }
    975 
    976     ALOGV("%s: setting up outbufs (%d) shared=%s\n", __func__, nBufferCount,
    977           pCtx->bShareOutbuf ? "true" : "false");
    978 
    979     memset(&req, 0, sizeof(req));
    980 
    981     req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
    982     req.count = nBufferCount;
    983 
    984     if (pCtx->bShareOutbuf == VIDEO_TRUE)
    985         req.memory = pCtx->nMemoryType;
    986     else
    987         req.memory = V4L2_MEMORY_MMAP;
    988 
    989     if (exynos_v4l2_reqbufs(pCtx->hDec, &req) != 0) {
    990         ret = VIDEO_ERROR_APIFAIL;
    991         goto EXIT;
    992     }
    993 
    994     if (req.count != nBufferCount) {
    995         ALOGE("%s: asked for %d, got %d\n", __func__, nBufferCount, req.count);
    996         ret = VIDEO_ERROR_NOMEM;
    997         goto EXIT;
    998     }
    999 
   1000     pCtx->nOutbufs = req.count;
   1001 
   1002     pCtx->pOutbuf = malloc(sizeof(*pCtx->pOutbuf) * pCtx->nOutbufs);
   1003     if (pCtx->pOutbuf == NULL) {
   1004         ALOGE("Failed to allocate output buffer context");
   1005         ret = VIDEO_ERROR_NOMEM;
   1006         goto EXIT;
   1007     }
   1008     memset(pCtx->pOutbuf, 0, sizeof(*pCtx->pOutbuf) * pCtx->nOutbufs);
   1009 
   1010     memset(&buf, 0, sizeof(buf));
   1011 
   1012     if (pCtx->bShareOutbuf == VIDEO_FALSE) {
   1013         buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
   1014         buf.memory = V4L2_MEMORY_MMAP;
   1015         buf.m.planes = planes;
   1016         buf.length = VIDEO_DECODER_OUTBUF_PLANES;
   1017 
   1018         for (i = 0; i < pCtx->nOutbufs; i++) {
   1019             buf.index = i;
   1020             if (exynos_v4l2_querybuf(pCtx->hDec, &buf) != 0) {
   1021                 ret = VIDEO_ERROR_APIFAIL;
   1022                 goto EXIT;
   1023             }
   1024 
   1025             for (j = 0; j < VIDEO_DECODER_OUTBUF_PLANES; j++) {
   1026                 pVideoPlane = &pCtx->pOutbuf[i].planes[j];
   1027                 pVideoPlane->addr = mmap(NULL,
   1028                         buf.m.planes[j].length, PROT_READ | PROT_WRITE,
   1029                         MAP_SHARED, pCtx->hDec, buf.m.planes[j].m.mem_offset);
   1030 
   1031                 if (pVideoPlane->addr == MAP_FAILED) {
   1032                     ret = VIDEO_ERROR_MAPFAIL;
   1033                     goto EXIT;
   1034                 }
   1035 
   1036                 pVideoPlane->allocSize = buf.m.planes[j].length;
   1037                 pVideoPlane->dataSize = 0;
   1038             }
   1039 
   1040             pCtx->pOutbuf[i].pGeometry = &pCtx->outbufGeometry;
   1041             pCtx->pOutbuf[i].bQueued      = VIDEO_FALSE;
   1042             pCtx->pOutbuf[i].bSlotUsed    = VIDEO_FALSE;
   1043             pCtx->pOutbuf[i].nIndexUseCnt = 0;
   1044             pCtx->pOutbuf[i].bRegistered  = VIDEO_TRUE;
   1045         }
   1046     }
   1047 
   1048     return ret;
   1049 
   1050 EXIT:
   1051     if ((pCtx != NULL) && (pCtx->pOutbuf != NULL)) {
   1052         if (pCtx->bShareOutbuf == VIDEO_FALSE) {
   1053             for (i = 0; i < pCtx->nOutbufs; i++) {
   1054                 for (j = 0; j < VIDEO_DECODER_OUTBUF_PLANES; j++) {
   1055                     pVideoPlane = &pCtx->pOutbuf[i].planes[j];
   1056                     if (pVideoPlane->addr == MAP_FAILED) {
   1057                         pVideoPlane->addr = NULL;
   1058                         break;
   1059                     }
   1060 
   1061                     munmap(pVideoPlane->addr, pVideoPlane->allocSize);
   1062                 }
   1063             }
   1064         }
   1065 
   1066         free(pCtx->pOutbuf);
   1067         pCtx->pOutbuf = NULL;
   1068     }
   1069 
   1070     return ret;
   1071 }
   1072 
   1073 /*
   1074  * [Decoder Buffer OPS] Run (Input)
   1075  */
   1076 static ExynosVideoErrorType MFC_Decoder_Run_Inbuf(void *pHandle)
   1077 {
   1078     ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
   1079     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
   1080 
   1081     if (pCtx == NULL) {
   1082         ALOGE("%s: Video context info must be supplied", __func__);
   1083         ret = VIDEO_ERROR_BADPARAM;
   1084         goto EXIT;
   1085     }
   1086 
   1087     if (pCtx->bStreamonInbuf == VIDEO_FALSE) {
   1088         if (exynos_v4l2_streamon(pCtx->hDec, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) != 0) {
   1089             ALOGE("%s: Failed to streamon for input buffer", __func__);
   1090             ret = VIDEO_ERROR_APIFAIL;
   1091             goto EXIT;
   1092         }
   1093         pCtx->bStreamonInbuf = VIDEO_TRUE;
   1094     }
   1095 
   1096 EXIT:
   1097     return ret;
   1098 }
   1099 
   1100 /*
   1101  * [Decoder Buffer OPS] Run (Output)
   1102  */
   1103 static ExynosVideoErrorType MFC_Decoder_Run_Outbuf(void *pHandle)
   1104 {
   1105     ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
   1106     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
   1107 
   1108     if (pCtx == NULL) {
   1109         ALOGE("%s: Video context info must be supplied", __func__);
   1110         ret = VIDEO_ERROR_BADPARAM;
   1111         goto EXIT;
   1112     }
   1113 
   1114     if (pCtx->bStreamonOutbuf == VIDEO_FALSE) {
   1115         if (exynos_v4l2_streamon(pCtx->hDec, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) != 0) {
   1116             ALOGE("%s: Failed to streamon for output buffer", __func__);
   1117             ret = VIDEO_ERROR_APIFAIL;
   1118             goto EXIT;
   1119         }
   1120         pCtx->bStreamonOutbuf = VIDEO_TRUE;
   1121     }
   1122 
   1123 EXIT:
   1124     return ret;
   1125 }
   1126 
   1127 /*
   1128  * [Decoder Buffer OPS] Stop (Input)
   1129  */
   1130 static ExynosVideoErrorType MFC_Decoder_Stop_Inbuf(void *pHandle)
   1131 {
   1132     ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
   1133     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
   1134     int i = 0;
   1135 
   1136     if (pCtx == NULL) {
   1137         ALOGE("%s: Video context info must be supplied", __func__);
   1138         ret = VIDEO_ERROR_BADPARAM;
   1139         goto EXIT;
   1140     }
   1141 
   1142     if (pCtx->bStreamonInbuf == VIDEO_TRUE) {
   1143         if (exynos_v4l2_streamoff(pCtx->hDec, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) != 0) {
   1144             ALOGE("%s: Failed to streamoff for input buffer", __func__);
   1145             ret = VIDEO_ERROR_APIFAIL;
   1146             goto EXIT;
   1147         }
   1148         pCtx->bStreamonInbuf = VIDEO_FALSE;
   1149     }
   1150 
   1151     for (i = 0; i <  pCtx->nInbufs; i++) {
   1152         pCtx->pInbuf[i].bQueued = VIDEO_FALSE;
   1153     }
   1154 
   1155 EXIT:
   1156     return ret;
   1157 }
   1158 
   1159 /*
   1160  * [Decoder Buffer OPS] Stop (Output)
   1161  */
   1162 static ExynosVideoErrorType MFC_Decoder_Stop_Outbuf(void *pHandle)
   1163 {
   1164     ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
   1165     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
   1166     int i = 0;
   1167 
   1168     if (pCtx == NULL) {
   1169         ALOGE("%s: Video context info must be supplied", __func__);
   1170         ret = VIDEO_ERROR_BADPARAM;
   1171         goto EXIT;
   1172     }
   1173 
   1174     if (pCtx->bStreamonOutbuf == VIDEO_TRUE) {
   1175         if (exynos_v4l2_streamoff(pCtx->hDec, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) != 0) {
   1176             ALOGE("%s: Failed to streamoff for output buffer", __func__);
   1177             ret = VIDEO_ERROR_APIFAIL;
   1178             goto EXIT;
   1179         }
   1180         pCtx->bStreamonOutbuf = VIDEO_FALSE;
   1181     }
   1182 
   1183     for (i = 0; i < pCtx->nOutbufs; i++) {
   1184         pCtx->pOutbuf[i].bQueued      = VIDEO_FALSE;
   1185         pCtx->pOutbuf[i].bSlotUsed    = VIDEO_FALSE;
   1186         pCtx->pOutbuf[i].nIndexUseCnt = 0;
   1187     }
   1188 
   1189 EXIT:
   1190     return ret;
   1191 }
   1192 
   1193 /*
   1194  * [Decoder Buffer OPS] Wait (Input)
   1195  */
   1196 static ExynosVideoErrorType MFC_Decoder_Wait_Inbuf(void *pHandle)
   1197 {
   1198     ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
   1199     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
   1200 
   1201     struct pollfd poll_events;
   1202     int poll_state;
   1203 
   1204     if (pCtx == NULL) {
   1205         ALOGE("%s: Video context info must be supplied", __func__);
   1206         ret = VIDEO_ERROR_BADPARAM;
   1207         goto EXIT;
   1208     }
   1209 
   1210     poll_events.fd = pCtx->hDec;
   1211     poll_events.events = POLLOUT | POLLERR;
   1212     poll_events.revents = 0;
   1213 
   1214     do {
   1215         poll_state = poll((struct pollfd*)&poll_events, 1, VIDEO_DECODER_POLL_TIMEOUT);
   1216         if (poll_state > 0) {
   1217             if (poll_events.revents & POLLOUT) {
   1218                 break;
   1219             } else {
   1220                 ALOGE("%s: Poll return error", __func__);
   1221                 ret = VIDEO_ERROR_POLL;
   1222                 break;
   1223             }
   1224         } else if (poll_state < 0) {
   1225             ALOGE("%s: Poll state error", __func__);
   1226             ret = VIDEO_ERROR_POLL;
   1227             break;
   1228         }
   1229     } while (poll_state == 0);
   1230 
   1231 EXIT:
   1232     return ret;
   1233 }
   1234 
   1235 static ExynosVideoErrorType MFC_Decoder_Register_Inbuf(
   1236     void             *pHandle,
   1237     ExynosVideoPlane *planes,
   1238     int               nPlanes)
   1239 {
   1240     ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
   1241     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
   1242     int nIndex, plane;
   1243 
   1244     if ((pCtx == NULL) || (planes == NULL) || (nPlanes != VIDEO_DECODER_INBUF_PLANES)) {
   1245         ALOGE("%s: params must be supplied", __func__);
   1246         ret = VIDEO_ERROR_BADPARAM;
   1247         goto EXIT;
   1248     }
   1249 
   1250     for (nIndex = 0; nIndex < pCtx->nInbufs; nIndex++) {
   1251         if (pCtx->pInbuf[nIndex].bRegistered == VIDEO_FALSE) {
   1252             for (plane = 0; plane < nPlanes; plane++) {
   1253                 pCtx->pInbuf[nIndex].planes[plane].addr = planes[plane].addr;
   1254                 pCtx->pInbuf[nIndex].planes[plane].allocSize = planes[plane].allocSize;
   1255                 pCtx->pInbuf[nIndex].planes[plane].fd = planes[plane].fd;
   1256                 ALOGV("%s: registered buf %d (addr=%p alloc_sz=%ld fd=%d)\n", __func__, nIndex,
   1257                   planes[plane].addr, planes[plane].allocSize, planes[plane].fd);
   1258             }
   1259             pCtx->pInbuf[nIndex].bRegistered = VIDEO_TRUE;
   1260             break;
   1261         }
   1262     }
   1263 
   1264     if (nIndex == pCtx->nInbufs) {
   1265         ALOGE("%s: can not find non-registered input buffer", __func__);
   1266         ret = VIDEO_ERROR_NOBUFFERS;
   1267     }
   1268 
   1269 EXIT:
   1270     return ret;
   1271 }
   1272 
   1273 static ExynosVideoErrorType MFC_Decoder_Register_Outbuf(
   1274     void             *pHandle,
   1275     ExynosVideoPlane *planes,
   1276     int               nPlanes)
   1277 {
   1278     ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
   1279     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
   1280     int nIndex, plane;
   1281 
   1282     if ((pCtx == NULL) || (planes == NULL) || (nPlanes != VIDEO_DECODER_OUTBUF_PLANES)) {
   1283         ALOGE("%s: params must be supplied", __func__);
   1284         ret = VIDEO_ERROR_BADPARAM;
   1285         goto EXIT;
   1286     }
   1287 
   1288     for (nIndex = 0; nIndex < pCtx->nOutbufs; nIndex++) {
   1289         if (pCtx->pOutbuf[nIndex].bRegistered == VIDEO_FALSE) {
   1290             for (plane = 0; plane < nPlanes; plane++) {
   1291                 pCtx->pOutbuf[nIndex].planes[plane].addr = planes[plane].addr;
   1292                 pCtx->pOutbuf[nIndex].planes[plane].allocSize = planes[plane].allocSize;
   1293                 pCtx->pOutbuf[nIndex].planes[plane].fd = planes[plane].fd;
   1294             }
   1295             pCtx->pOutbuf[nIndex].bRegistered = VIDEO_TRUE;
   1296             ALOGV("%s: registered buf %d 0:(addr=%p alloc_sz=%d fd=%d) 1:(addr=%p alloc_sz=%d fd=%d)\n",
   1297                   __func__, nIndex, planes[0].addr, planes[0].allocSize, planes[0].fd,
   1298                   planes[1].addr, planes[1].allocSize, planes[1].fd);
   1299             break;
   1300         }
   1301     }
   1302 
   1303     if (nIndex == pCtx->nOutbufs) {
   1304         ALOGE("%s: can not find non-registered output buffer", __func__);
   1305         ret = VIDEO_ERROR_NOBUFFERS;
   1306     }
   1307 
   1308 EXIT:
   1309     return ret;
   1310 }
   1311 
   1312 static ExynosVideoErrorType MFC_Decoder_Clear_RegisteredBuffer_Inbuf(void *pHandle)
   1313 {
   1314     ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
   1315     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
   1316     int nIndex;
   1317 
   1318     if (pCtx == NULL) {
   1319         ALOGE("%s: Video context info must be supplied", __func__);
   1320         ret = VIDEO_ERROR_BADPARAM;
   1321         goto EXIT;
   1322     }
   1323 
   1324     for (nIndex = 0; nIndex < pCtx->nInbufs; nIndex++) {
   1325         pCtx->pInbuf[nIndex].planes[0].addr = NULL;
   1326         pCtx->pInbuf[nIndex].bRegistered = VIDEO_FALSE;
   1327     }
   1328 
   1329 EXIT:
   1330     return ret;
   1331 }
   1332 
   1333 static ExynosVideoErrorType MFC_Decoder_Clear_RegisteredBuffer_Outbuf(void *pHandle)
   1334 {
   1335     ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
   1336     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
   1337     int nIndex;
   1338 
   1339     if (pCtx == NULL) {
   1340         ALOGE("%s: Video context info must be supplied", __func__);
   1341         ret = VIDEO_ERROR_BADPARAM;
   1342         goto EXIT;
   1343     }
   1344 
   1345     for (nIndex = 0; nIndex < pCtx->nOutbufs; nIndex++) {
   1346         pCtx->pOutbuf[nIndex].planes[0].addr = NULL;
   1347         pCtx->pOutbuf[nIndex].bRegistered = VIDEO_FALSE;
   1348     }
   1349 
   1350 EXIT:
   1351     return ret;
   1352 }
   1353 
   1354 /*
   1355  * [Decoder Buffer OPS] Find (Input)
   1356  */
   1357 static int MFC_Decoder_Find_Inbuf(
   1358     void          *pHandle,
   1359     unsigned char *pBuffer)
   1360 {
   1361     ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
   1362     int nIndex = -1;
   1363 
   1364     if (pCtx == NULL) {
   1365         ALOGE("%s: Video context info must be supplied", __func__);
   1366         goto EXIT;
   1367     }
   1368 
   1369     for (nIndex = 0; nIndex < pCtx->nInbufs; nIndex++) {
   1370         if (pCtx->pInbuf[nIndex].bQueued == VIDEO_FALSE) {
   1371             if ((pBuffer == NULL) ||
   1372                 (pCtx->pInbuf[nIndex].planes[0].addr == pBuffer))
   1373                 break;
   1374         }
   1375     }
   1376 
   1377     if (nIndex == pCtx->nInbufs)
   1378         nIndex = -1;
   1379 
   1380 EXIT:
   1381     return nIndex;
   1382 }
   1383 
   1384 /*
   1385  * [Decoder Buffer OPS] Find (Outnput)
   1386  */
   1387 static int MFC_Decoder_Find_Outbuf(
   1388     void          *pHandle,
   1389     unsigned char *pBuffer)
   1390 {
   1391     ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
   1392     int nIndex = -1;
   1393 
   1394     if (pCtx == NULL) {
   1395         ALOGE("%s: Video context info must be supplied", __func__);
   1396         goto EXIT;
   1397     }
   1398 
   1399     for (nIndex = 0; nIndex < pCtx->nOutbufs; nIndex++) {
   1400         if (pCtx->pOutbuf[nIndex].bQueued == VIDEO_FALSE) {
   1401             if ((pBuffer == NULL) ||
   1402                 (pCtx->pOutbuf[nIndex].planes[0].addr == pBuffer))
   1403                 break;
   1404         }
   1405     }
   1406 
   1407     if (nIndex == pCtx->nOutbufs)
   1408         nIndex = -1;
   1409 
   1410 EXIT:
   1411     return nIndex;
   1412 }
   1413 
   1414 /*
   1415  * [Decoder Buffer OPS] Enqueue (Input)
   1416  */
   1417 static ExynosVideoErrorType MFC_Decoder_Enqueue_Inbuf(
   1418     void          *pHandle,
   1419     unsigned char *pBuffer[],
   1420     unsigned int   dataSize[],
   1421     int            nPlanes,
   1422     void          *pPrivate)
   1423 {
   1424     ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
   1425     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
   1426     pthread_mutex_t       *pMutex = NULL;
   1427 
   1428     struct v4l2_plane  planes[VIDEO_DECODER_INBUF_PLANES];
   1429     struct v4l2_buffer buf;
   1430     int index, i;
   1431 
   1432     if (pCtx == NULL) {
   1433         ALOGE("%s: Video context info must be supplied", __func__);
   1434         ret = VIDEO_ERROR_BADPARAM;
   1435         goto EXIT;
   1436     }
   1437 
   1438     if (VIDEO_DECODER_INBUF_PLANES < nPlanes) {
   1439         ALOGE("%s: Number of max planes : %d, nPlanes : %d", __func__,
   1440                                     VIDEO_DECODER_INBUF_PLANES, nPlanes);
   1441         ret = VIDEO_ERROR_BADPARAM;
   1442         goto EXIT;
   1443     }
   1444 
   1445     memset(&buf, 0, sizeof(buf));
   1446 
   1447     buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
   1448     buf.m.planes = planes;
   1449     buf.length = VIDEO_DECODER_INBUF_PLANES;
   1450 
   1451     pMutex = (pthread_mutex_t*)pCtx->pInMutex;
   1452     pthread_mutex_lock(pMutex);
   1453     index = MFC_Decoder_Find_Inbuf(pCtx, pBuffer[0]);
   1454     if (index == -1) {
   1455         pthread_mutex_unlock(pMutex);
   1456         ALOGE("%s: Failed to get index", __func__);
   1457         ret = VIDEO_ERROR_NOBUFFERS;
   1458         goto EXIT;
   1459     }
   1460 
   1461     buf.index = index;
   1462     pCtx->pInbuf[buf.index].bQueued = VIDEO_TRUE;
   1463 
   1464     if (pCtx->bShareInbuf == VIDEO_TRUE) {
   1465         buf.memory = pCtx->nMemoryType;
   1466         for (i = 0; i < nPlanes; i++) {
   1467             /* V4L2_MEMORY_USERPTR */
   1468             buf.m.planes[i].m.userptr = (unsigned long)pBuffer[i];
   1469             /* V4L2_MEMORY_DMABUF */
   1470             buf.m.planes[i].m.fd = pCtx->pInbuf[index].planes[i].fd;
   1471             buf.m.planes[i].length = pCtx->pInbuf[index].planes[i].allocSize;
   1472             buf.m.planes[i].bytesused = dataSize[i];
   1473             ALOGV("%s: shared inbuf(%d) plane(%d) addr=%p fd=%d len=%d used=%d\n", __func__,
   1474                   index, i,
   1475                   buf.m.planes[i].m.userptr,
   1476                   buf.m.planes[i].m.fd,
   1477                   buf.m.planes[i].length,
   1478                   buf.m.planes[i].bytesused);
   1479         }
   1480     } else {
   1481         buf.memory = V4L2_MEMORY_MMAP;
   1482         for (i = 0; i < nPlanes; i++)
   1483             buf.m.planes[i].bytesused = dataSize[i];
   1484     }
   1485 
   1486     if ((((OMX_BUFFERHEADERTYPE *)pPrivate)->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) {
   1487         buf.flags |= V4L2_BUF_FLAG_LAST_FRAME;
   1488         ALOGV("%s: OMX_BUFFERFLAG_EOS => LAST_FRAME: 0x%x", __func__,
   1489               !!(buf.flags & V4L2_BUF_FLAG_LAST_FRAME));
   1490     }
   1491 
   1492     pCtx->pInbuf[buf.index].pPrivate = pPrivate;
   1493 
   1494     pthread_mutex_unlock(pMutex);
   1495 
   1496     if (exynos_v4l2_qbuf(pCtx->hDec, &buf) != 0) {
   1497         ALOGE("%s: Failed to enqueue input buffer", __func__);
   1498         pthread_mutex_lock(pMutex);
   1499         pCtx->pInbuf[buf.index].pPrivate = NULL;
   1500         pCtx->pInbuf[buf.index].bQueued  = VIDEO_FALSE;
   1501         pthread_mutex_unlock(pMutex);
   1502         ret = VIDEO_ERROR_APIFAIL;
   1503         goto EXIT;
   1504     }
   1505 
   1506 EXIT:
   1507     return ret;
   1508 }
   1509 
   1510 /*
   1511  * [Decoder Buffer OPS] Enqueue (Output)
   1512  */
   1513 static ExynosVideoErrorType MFC_Decoder_Enqueue_Outbuf(
   1514     void          *pHandle,
   1515     unsigned char *pBuffer[],
   1516     unsigned int   dataSize[],
   1517     int            nPlanes,
   1518     void          *pPrivate)
   1519 {
   1520     ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
   1521     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
   1522     pthread_mutex_t       *pMutex = NULL;
   1523 
   1524     struct v4l2_plane  planes[VIDEO_DECODER_OUTBUF_PLANES];
   1525     struct v4l2_buffer buf;
   1526     int i, index;
   1527 
   1528     if (pCtx == NULL) {
   1529         ALOGE("%s: Video context info must be supplied", __func__);
   1530         ret = VIDEO_ERROR_BADPARAM;
   1531         goto EXIT;
   1532     }
   1533 
   1534     if (VIDEO_DECODER_OUTBUF_PLANES < nPlanes) {
   1535         ALOGE("%s: Number of max planes : %d, nPlanes : %d", __func__,
   1536                                     VIDEO_DECODER_OUTBUF_PLANES, nPlanes);
   1537         ret = VIDEO_ERROR_BADPARAM;
   1538         goto EXIT;
   1539     }
   1540 
   1541     memset(&buf, 0, sizeof(buf));
   1542     buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
   1543     buf.m.planes = planes;
   1544     buf.length = VIDEO_DECODER_OUTBUF_PLANES;
   1545 
   1546     pMutex = (pthread_mutex_t*)pCtx->pOutMutex;
   1547     pthread_mutex_lock(pMutex);
   1548     index = MFC_Decoder_Find_Outbuf(pCtx, pBuffer[0]);
   1549     if (index == -1) {
   1550         pthread_mutex_unlock(pMutex);
   1551         ALOGE("%s: Failed to get index", __func__);
   1552         ret = VIDEO_ERROR_NOBUFFERS;
   1553         goto EXIT;
   1554     }
   1555     buf.index = index;
   1556     pCtx->pOutbuf[buf.index].bQueued = VIDEO_TRUE;
   1557 
   1558     if (pCtx->bShareOutbuf == VIDEO_TRUE) {
   1559         buf.memory = pCtx->nMemoryType;
   1560         for (i = 0; i < nPlanes; i++) {
   1561             /* V4L2_MEMORY_USERPTR */
   1562             buf.m.planes[i].m.userptr = (unsigned long)pBuffer[i];
   1563             /* V4L2_MEMORY_DMABUF */
   1564             buf.m.planes[i].m.fd = pCtx->pOutbuf[index].planes[i].fd;
   1565             buf.m.planes[i].length = pCtx->pOutbuf[index].planes[i].allocSize;
   1566             buf.m.planes[i].bytesused = dataSize[i];
   1567             ALOGV("%s: shared outbuf(%d) plane=%d addr=%p fd=%d len=%d used=%d\n", __func__,
   1568                   index, i,
   1569                   buf.m.planes[i].m.userptr,
   1570                   buf.m.planes[i].m.fd,
   1571                   buf.m.planes[i].length,
   1572                   buf.m.planes[i].bytesused);
   1573         }
   1574     } else {
   1575         ALOGV("%s: non-shared outbuf(%d)\n", __func__, index);
   1576         buf.memory = V4L2_MEMORY_MMAP;
   1577     }
   1578 
   1579     pCtx->pOutbuf[buf.index].pPrivate = pPrivate;
   1580 
   1581     pthread_mutex_unlock(pMutex);
   1582 
   1583     if (exynos_v4l2_qbuf(pCtx->hDec, &buf) != 0) {
   1584         ALOGE("%s: Failed to enqueue output buffer", __func__);
   1585         pthread_mutex_lock(pMutex);
   1586         pCtx->pOutbuf[buf.index].pPrivate = NULL;
   1587         pCtx->pOutbuf[buf.index].bQueued  = VIDEO_FALSE;
   1588         pthread_mutex_unlock(pMutex);
   1589         ret = VIDEO_ERROR_APIFAIL;
   1590         goto EXIT;
   1591     }
   1592 
   1593 EXIT:
   1594     return ret;
   1595 }
   1596 
   1597 /*
   1598  * [Decoder Buffer OPS] Dequeue (Input)
   1599  */
   1600 static ExynosVideoBuffer *MFC_Decoder_Dequeue_Inbuf(void *pHandle)
   1601 {
   1602     ExynosVideoDecContext *pCtx     = (ExynosVideoDecContext *)pHandle;
   1603     ExynosVideoBuffer     *pInbuf   = NULL;
   1604     pthread_mutex_t       *pMutex = NULL;
   1605 
   1606     struct v4l2_buffer buf;
   1607 
   1608     if (pCtx == NULL) {
   1609         ALOGE("%s: Video context info must be supplied", __func__);
   1610         goto EXIT;
   1611     }
   1612 
   1613     if (pCtx->bStreamonInbuf == VIDEO_FALSE) {
   1614         pInbuf = NULL;
   1615         goto EXIT;
   1616     }
   1617 
   1618     memset(&buf, 0, sizeof(buf));
   1619 
   1620     buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
   1621 
   1622     if (pCtx->bShareInbuf == VIDEO_TRUE)
   1623         buf.memory = pCtx->nMemoryType;
   1624     else
   1625         buf.memory = V4L2_MEMORY_MMAP;
   1626 
   1627     if (exynos_v4l2_dqbuf(pCtx->hDec, &buf) != 0) {
   1628         pInbuf = NULL;
   1629         goto EXIT;
   1630     }
   1631 
   1632     pMutex = (pthread_mutex_t*)pCtx->pInMutex;
   1633     pthread_mutex_lock(pMutex);
   1634 
   1635     pInbuf = &pCtx->pInbuf[buf.index];
   1636     pCtx->pInbuf[buf.index].bQueued = VIDEO_FALSE;
   1637 
   1638     if (pCtx->bStreamonInbuf == VIDEO_FALSE)
   1639         pInbuf = NULL;
   1640 
   1641     pthread_mutex_unlock(pMutex);
   1642 
   1643 EXIT:
   1644     return pInbuf;
   1645 }
   1646 
   1647 /*
   1648  * [Decoder Buffer OPS] Dequeue (Output)
   1649  */
   1650 static ExynosVideoBuffer *MFC_Decoder_Dequeue_Outbuf(void *pHandle)
   1651 {
   1652     ExynosVideoDecContext *pCtx    = (ExynosVideoDecContext *)pHandle;
   1653     ExynosVideoBuffer     *pOutbuf = NULL;
   1654     pthread_mutex_t       *pMutex = NULL;
   1655 
   1656     struct v4l2_buffer buf;
   1657     int value, state;
   1658 
   1659     if (pCtx == NULL) {
   1660         ALOGE("%s: Video context info must be supplied", __func__);
   1661         goto EXIT;
   1662     }
   1663 
   1664     if (pCtx->bStreamonOutbuf == VIDEO_FALSE) {
   1665         pOutbuf = NULL;
   1666         goto EXIT;
   1667     }
   1668 
   1669     memset(&buf, 0, sizeof(buf));
   1670     buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
   1671 
   1672     if (pCtx->bShareOutbuf == VIDEO_TRUE)
   1673         buf.memory = pCtx->nMemoryType;
   1674     else
   1675         buf.memory = V4L2_MEMORY_MMAP;
   1676 
   1677     /* HACK: pOutbuf return -1 means DECODING_ONLY for almost cases */
   1678     if (exynos_v4l2_dqbuf(pCtx->hDec, &buf) != 0) {
   1679         pOutbuf = NULL;
   1680         goto EXIT;
   1681     }
   1682 
   1683     if (pCtx->bStreamonOutbuf == VIDEO_FALSE) {
   1684         pOutbuf = NULL;
   1685         goto EXIT;
   1686     }
   1687 
   1688     pMutex = (pthread_mutex_t*)pCtx->pOutMutex;
   1689     pthread_mutex_lock(pMutex);
   1690 
   1691     pOutbuf = &pCtx->pOutbuf[buf.index];
   1692 
   1693     exynos_v4l2_g_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC51_VIDEO_DISPLAY_STATUS, &value);
   1694 
   1695     switch (value) {
   1696     case 0:
   1697         pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DECODING_ONLY;
   1698         break;
   1699     case 1:
   1700         pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DISPLAY_DECODING;
   1701         break;
   1702     case 2:
   1703         pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DISPLAY_ONLY;
   1704         break;
   1705     case 3:
   1706         exynos_v4l2_g_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC51_VIDEO_CHECK_STATE, &state);
   1707         if (state == 1) /* Resolution is changed */
   1708             pOutbuf->displayStatus = VIDEO_FRAME_STATUS_CHANGE_RESOL;
   1709         else            /* Decoding is finished */
   1710             pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DECODING_FINISHED;
   1711         break;
   1712     default:
   1713         pOutbuf->displayStatus = VIDEO_FRAME_STATUS_UNKNOWN;
   1714         break;
   1715     }
   1716 
   1717     switch (buf.flags & (0x7 << 3)) {
   1718     case V4L2_BUF_FLAG_KEYFRAME:
   1719         pOutbuf->frameType = VIDEO_FRAME_I;
   1720         break;
   1721     case V4L2_BUF_FLAG_PFRAME:
   1722         pOutbuf->frameType = VIDEO_FRAME_P;
   1723         break;
   1724     case V4L2_BUF_FLAG_BFRAME:
   1725         pOutbuf->frameType = VIDEO_FRAME_B;
   1726         break;
   1727     default:
   1728         pOutbuf->frameType = VIDEO_FRAME_OTHERS;
   1729         break;
   1730     };
   1731 
   1732     pOutbuf->bQueued = VIDEO_FALSE;
   1733 
   1734     pthread_mutex_unlock(pMutex);
   1735 
   1736 EXIT:
   1737     return pOutbuf;
   1738 }
   1739 
   1740 static ExynosVideoErrorType MFC_Decoder_Clear_Queued_Inbuf(void *pHandle)
   1741 {
   1742     ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
   1743     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
   1744     int i;
   1745 
   1746     if (pCtx == NULL) {
   1747         ALOGE("%s: Video context info must be supplied", __func__);
   1748         ret = VIDEO_ERROR_BADPARAM;
   1749         goto EXIT;
   1750     }
   1751 
   1752     for (i = 0; i < pCtx->nInbufs; i++) {
   1753         pCtx->pInbuf[i].bQueued = VIDEO_FALSE;
   1754     }
   1755 
   1756 EXIT:
   1757     return ret;
   1758 }
   1759 
   1760 static ExynosVideoErrorType MFC_Decoder_Clear_Queued_Outbuf(void *pHandle)
   1761 {
   1762     ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
   1763     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
   1764     int i;
   1765 
   1766     if (pCtx == NULL) {
   1767         ALOGE("%s: Video context info must be supplied", __func__);
   1768         ret = VIDEO_ERROR_BADPARAM;
   1769         goto EXIT;
   1770     }
   1771 
   1772     for (i = 0; i < pCtx->nOutbufs; i++) {
   1773         pCtx->pOutbuf[i].bQueued = VIDEO_FALSE;
   1774     }
   1775 
   1776 EXIT:
   1777     return ret;
   1778 }
   1779 
   1780 /*
   1781  * [Decoder Buffer OPS] Cleanup Buffer (Input)
   1782  */
   1783 static ExynosVideoErrorType MFC_Decoder_Cleanup_Buffer_Inbuf(void *pHandle)
   1784 {
   1785     ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
   1786     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
   1787 
   1788     struct v4l2_requestbuffers req;
   1789     int nBufferCount = 0;
   1790 
   1791     if (pCtx == NULL) {
   1792         ALOGE("%s: Video context info must be supplied", __func__);
   1793         ret = VIDEO_ERROR_BADPARAM;
   1794         goto EXIT;
   1795     }
   1796 
   1797     nBufferCount = 0; /* for clean-up */
   1798 
   1799     memset(&req, 0, sizeof(req));
   1800 
   1801     req.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
   1802     req.count = nBufferCount;
   1803 
   1804     if (pCtx->bShareInbuf == VIDEO_TRUE)
   1805         req.memory = pCtx->nMemoryType;
   1806     else
   1807         req.memory = V4L2_MEMORY_MMAP;
   1808 
   1809     if (exynos_v4l2_reqbufs(pCtx->hDec, &req) != 0) {
   1810         ret = VIDEO_ERROR_APIFAIL;
   1811         goto EXIT;
   1812     }
   1813 
   1814     pCtx->nInbufs = (int)req.count;
   1815 
   1816     if (pCtx->pInbuf != NULL) {
   1817         free(pCtx->pInbuf);
   1818         pCtx->pInbuf = NULL;
   1819     }
   1820 
   1821 EXIT:
   1822     return ret;
   1823 }
   1824 
   1825 /*
   1826  * [Decoder Buffer OPS] Cleanup Buffer (Output)
   1827  */
   1828 static ExynosVideoErrorType MFC_Decoder_Cleanup_Buffer_Outbuf(void *pHandle)
   1829 {
   1830     ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
   1831     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
   1832 
   1833     struct v4l2_requestbuffers req;
   1834     int nBufferCount = 0;
   1835 
   1836     if (pCtx == NULL) {
   1837         ALOGE("%s: Video context info must be supplied", __func__);
   1838         ret = VIDEO_ERROR_BADPARAM;
   1839         goto EXIT;
   1840     }
   1841 
   1842     nBufferCount = 0; /* for clean-up */
   1843 
   1844     memset(&req, 0, sizeof(req));
   1845 
   1846     req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
   1847     req.count = nBufferCount;
   1848 
   1849     if (pCtx->bShareOutbuf == VIDEO_TRUE)
   1850         req.memory = pCtx->nMemoryType;
   1851     else
   1852         req.memory = V4L2_MEMORY_MMAP;
   1853 
   1854     if (exynos_v4l2_reqbufs(pCtx->hDec, &req) != 0) {
   1855         ret = VIDEO_ERROR_APIFAIL;
   1856         goto EXIT;
   1857     }
   1858 
   1859     pCtx->nOutbufs = (int)req.count;
   1860 
   1861     if (pCtx->pOutbuf != NULL) {
   1862         free(pCtx->pOutbuf);
   1863         pCtx->pOutbuf = NULL;
   1864     }
   1865 
   1866 EXIT:
   1867     return ret;
   1868 }
   1869 
   1870 /*
   1871  * [Decoder Buffer OPS] FindIndex (Output)
   1872  */
   1873 static int MFC_Decoder_FindEmpty_Outbuf(void *pHandle)
   1874 {
   1875     ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
   1876     int nIndex = -1;
   1877 
   1878     if (pCtx == NULL) {
   1879         ALOGE("%s: Video context info must be supplied", __func__);
   1880         goto EXIT;
   1881     }
   1882 
   1883     for (nIndex = 0; nIndex < pCtx->nOutbufs; nIndex++) {
   1884         if ((pCtx->pOutbuf[nIndex].bQueued == VIDEO_FALSE) &&
   1885             (pCtx->pOutbuf[nIndex].bSlotUsed == VIDEO_FALSE))
   1886             break;
   1887     }
   1888 
   1889     if (nIndex == pCtx->nOutbufs)
   1890         nIndex = -1;
   1891 
   1892 EXIT:
   1893     return nIndex;
   1894 }
   1895 
   1896 /*
   1897  * [Decoder Buffer OPS] BufferIndexFree (Output)
   1898  */
   1899 void MFC_Decoder_BufferIndexFree_Outbuf(void *pHandle, PrivateDataShareBuffer *pPDSB, int index)
   1900 {
   1901     ExynosVideoDecContext *pCtx    = (ExynosVideoDecContext *)pHandle;
   1902     int i, j;
   1903 
   1904     ALOGV("De-queue buf.index:%d", index);
   1905     ALOGV("pOutbuf fd:%d", pCtx->pOutbuf[index].planes[0].fd);
   1906 
   1907     if (pCtx->pOutbuf[index].nIndexUseCnt == 0) {
   1908         pCtx->pOutbuf[index].bSlotUsed = VIDEO_FALSE;
   1909     }
   1910 
   1911     for (i = 0; pPDSB->dpbFD[i].fd > -1; i++) {
   1912         ALOGV("pPDSB->dpbFD[%d].fd:%d", i, pPDSB->dpbFD[i].fd);
   1913         for (j = 0; pCtx->nOutbufs > j; j++)
   1914             if (pPDSB->dpbFD[i].fd == pCtx->pOutbuf[j].planes[0].fd) {
   1915                 if (pCtx->pOutbuf[j].bQueued == VIDEO_FALSE) {
   1916                     if (pCtx->pOutbuf[j].nIndexUseCnt > 0)
   1917                         pCtx->pOutbuf[j].nIndexUseCnt--;
   1918                 } else if(pCtx->pOutbuf[j].bQueued == VIDEO_TRUE) {
   1919                     if (pCtx->pOutbuf[j].nIndexUseCnt > 1) {
   1920                         /* The buffer being used as the reference buffer came again. */
   1921                         pCtx->pOutbuf[j].nIndexUseCnt--;
   1922                     } else {
   1923                         /* Reference DPB buffer is internally reused. */
   1924                     }
   1925                 }
   1926                 ALOGV("dec FD:%d, pCtx->pOutbuf[%d].nIndexUseCnt:%d", pPDSB->dpbFD[i].fd, j, pCtx->pOutbuf[j].nIndexUseCnt);
   1927                 if ((pCtx->pOutbuf[j].nIndexUseCnt == 0) &&
   1928                     (pCtx->pOutbuf[j].bQueued == VIDEO_FALSE)) {
   1929                     pCtx->pOutbuf[j].bSlotUsed = VIDEO_FALSE;
   1930                 }
   1931             }
   1932     }
   1933     memset((char *)pPDSB, -1, sizeof(PrivateDataShareBuffer));
   1934 
   1935     return;
   1936 }
   1937 
   1938 /*
   1939  * [Decoder Buffer OPS] ExtensionEnqueue (Output)
   1940  */
   1941 static ExynosVideoErrorType MFC_Decoder_ExtensionEnqueue_Outbuf(
   1942     void          *pHandle,
   1943     unsigned char *pBuffer[],
   1944     unsigned int  *pFd[],
   1945     unsigned int   allocLen[],
   1946     unsigned int   dataSize[],
   1947     int            nPlanes,
   1948     void          *pPrivate)
   1949 {
   1950     ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
   1951     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
   1952     pthread_mutex_t       *pMutex = NULL;
   1953 
   1954     struct v4l2_plane  planes[VIDEO_DECODER_OUTBUF_PLANES];
   1955     struct v4l2_buffer buf;
   1956     int state, index, i;
   1957 
   1958     if (pCtx == NULL) {
   1959         ALOGE("%s: Video context info must be supplied", __func__);
   1960         ret = VIDEO_ERROR_BADPARAM;
   1961         goto EXIT;
   1962     }
   1963 
   1964     if (VIDEO_DECODER_OUTBUF_PLANES < nPlanes) {
   1965         ALOGE("%s: Number of max planes : %d, nPlanes : %d", __func__,
   1966                                     VIDEO_DECODER_OUTBUF_PLANES, nPlanes);
   1967         ret = VIDEO_ERROR_BADPARAM;
   1968         goto EXIT;
   1969     }
   1970 
   1971     memset(&buf, 0, sizeof(buf));
   1972     buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
   1973     buf.m.planes = planes;
   1974     buf.length = VIDEO_DECODER_OUTBUF_PLANES;
   1975 
   1976     pMutex = (pthread_mutex_t*)pCtx->pOutMutex;
   1977     pthread_mutex_lock(pMutex);
   1978 
   1979     index = MFC_Decoder_Find_Outbuf(pCtx, pBuffer[0]);
   1980     if (index == -1) {
   1981         ALOGV("%s: Failed to find index", __func__);
   1982         index = MFC_Decoder_FindEmpty_Outbuf(pCtx);
   1983         if (index == -1) {
   1984             pthread_mutex_unlock(pMutex);
   1985             ALOGE("%s: Failed to get index", __func__);
   1986             ret = VIDEO_ERROR_NOBUFFERS;
   1987             goto EXIT;
   1988         }
   1989     }
   1990 
   1991     buf.index = index;
   1992     ALOGV("En-queue index:%d pCtx->pOutbuf[buf.index].bQueued:%d, pFd[0]:%d",
   1993            index, pCtx->pOutbuf[buf.index].bQueued, pFd[0]);
   1994     pCtx->pOutbuf[buf.index].bQueued = VIDEO_TRUE;
   1995     pCtx->pOutbuf[buf.index].bSlotUsed = VIDEO_TRUE;
   1996 
   1997     buf.memory = pCtx->nMemoryType;
   1998     for (i = 0; i < nPlanes; i++) {
   1999         /* V4L2_MEMORY_USERPTR */
   2000         buf.m.planes[i].m.userptr = (unsigned long)pBuffer[i];
   2001         /* V4L2_MEMORY_DMABUF */
   2002         buf.m.planes[i].m.fd = pFd[i];
   2003         buf.m.planes[i].length = allocLen[i];
   2004         buf.m.planes[i].bytesused = dataSize[i];
   2005 
   2006         /* Temporary storage for Dequeue */
   2007         pCtx->pOutbuf[buf.index].planes[i].addr = (unsigned long)pBuffer[i];
   2008         pCtx->pOutbuf[buf.index].planes[i].fd = (unsigned int)pFd[i];
   2009         pCtx->pOutbuf[buf.index].planes[i].allocSize = allocLen[i];
   2010 
   2011         ALOGV("%s: shared outbuf(%d) plane=%d addr=0x%x fd=%d len=%d used=%d\n",
   2012               __func__, index, i,
   2013               (void*)buf.m.planes[i].m.userptr, buf.m.planes[i].m.fd,
   2014               buf.m.planes[i].length, buf.m.planes[i].bytesused);
   2015     }
   2016 
   2017     pCtx->pOutbuf[buf.index].pPrivate = pPrivate;
   2018     pCtx->pOutbuf[buf.index].nIndexUseCnt++;
   2019 
   2020     pthread_mutex_unlock(pMutex);
   2021 
   2022     if (exynos_v4l2_qbuf(pCtx->hDec, &buf) != 0) {
   2023         pthread_mutex_lock(pMutex);
   2024         pCtx->pOutbuf[buf.index].nIndexUseCnt--;
   2025         pCtx->pOutbuf[buf.index].pPrivate = NULL;
   2026         pCtx->pOutbuf[buf.index].bQueued  = VIDEO_FALSE;
   2027         if (pCtx->pOutbuf[buf.index].nIndexUseCnt == 0)
   2028             pCtx->pOutbuf[buf.index].bSlotUsed = VIDEO_FALSE;
   2029         exynos_v4l2_g_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC51_VIDEO_CHECK_STATE, &state);
   2030         pthread_mutex_unlock(pMutex);
   2031 
   2032         if (state == 1) {
   2033             /* The case of Resolution is changed */
   2034             ret = VIDEO_ERROR_WRONGBUFFERSIZE;
   2035         } else {
   2036             ALOGE("%s: Failed to enqueue output buffer", __func__);
   2037             ret = VIDEO_ERROR_APIFAIL;
   2038         }
   2039         goto EXIT;
   2040     }
   2041 
   2042 EXIT:
   2043     return ret;
   2044 }
   2045 
   2046 /*
   2047  * [Decoder Buffer OPS] ExtensionDequeue (Output)
   2048  */
   2049 static ExynosVideoErrorType MFC_Decoder_ExtensionDequeue_Outbuf(
   2050     void              *pHandle,
   2051     ExynosVideoBuffer *pVideoBuffer)
   2052 {
   2053     ExynosVideoDecContext  *pCtx    = (ExynosVideoDecContext *)pHandle;
   2054     ExynosVideoErrorType    ret     = VIDEO_ERROR_NONE;
   2055     pthread_mutex_t        *pMutex = NULL;
   2056     ExynosVideoBuffer      *pOutbuf = NULL;
   2057     PrivateDataShareBuffer *pPDSB  = NULL;
   2058     struct v4l2_buffer buf;
   2059     int value, state, i, j;
   2060 
   2061     if (pCtx == NULL) {
   2062         ALOGE("%s: Video context info must be supplied", __func__);
   2063         ret = VIDEO_ERROR_BADPARAM;
   2064         goto EXIT;
   2065     }
   2066 
   2067     if (pCtx->bStreamonOutbuf == VIDEO_FALSE) {
   2068         pOutbuf = NULL;
   2069         ret = VIDEO_ERROR_APIFAIL;
   2070         goto EXIT;
   2071     }
   2072 
   2073     memset(&buf, 0, sizeof(buf));
   2074     buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
   2075 
   2076     if (pCtx->bShareOutbuf == VIDEO_TRUE)
   2077         buf.memory = pCtx->nMemoryType;
   2078     else
   2079         buf.memory = V4L2_MEMORY_MMAP;
   2080 
   2081     /* HACK: pOutbuf return -1 means DECODING_ONLY for almost cases */
   2082     if (exynos_v4l2_dqbuf(pCtx->hDec, &buf) != 0) {
   2083         pOutbuf = NULL;
   2084         ret = VIDEO_ERROR_APIFAIL;
   2085         goto EXIT;
   2086     }
   2087 
   2088     pMutex = (pthread_mutex_t*)pCtx->pOutMutex;
   2089     pthread_mutex_lock(pMutex);
   2090 
   2091     pOutbuf = &pCtx->pOutbuf[buf.index];
   2092     exynos_v4l2_g_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC51_VIDEO_DISPLAY_STATUS, &value);
   2093 
   2094     switch (value) {
   2095     case 0:
   2096         pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DECODING_ONLY;
   2097         break;
   2098     case 1:
   2099         pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DISPLAY_DECODING;
   2100         break;
   2101     case 2:
   2102         pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DISPLAY_ONLY;
   2103         break;
   2104     case 3:
   2105         exynos_v4l2_g_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC51_VIDEO_CHECK_STATE, &state);
   2106         if (state == 1) /* Resolution is changed */
   2107             pOutbuf->displayStatus = VIDEO_FRAME_STATUS_CHANGE_RESOL;
   2108         else            /* Decoding is finished */
   2109             pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DECODING_FINISHED;
   2110         break;
   2111     default:
   2112         pOutbuf->displayStatus = VIDEO_FRAME_STATUS_UNKNOWN;
   2113         break;
   2114     }
   2115 
   2116     switch (buf.flags & (0x7 << 3)) {
   2117     case V4L2_BUF_FLAG_KEYFRAME:
   2118         pOutbuf->frameType = VIDEO_FRAME_I;
   2119         break;
   2120     case V4L2_BUF_FLAG_PFRAME:
   2121         pOutbuf->frameType = VIDEO_FRAME_P;
   2122         break;
   2123     case V4L2_BUF_FLAG_BFRAME:
   2124         pOutbuf->frameType = VIDEO_FRAME_B;
   2125         break;
   2126     default:
   2127         pOutbuf->frameType = VIDEO_FRAME_OTHERS;
   2128         break;
   2129     };
   2130 
   2131     pPDSB = ((PrivateDataShareBuffer *)pCtx->nPrivateDataShareAddress) + buf.index;
   2132     if (pCtx->pOutbuf[buf.index].bQueued == VIDEO_TRUE) {
   2133         memcpy(pVideoBuffer, pOutbuf, sizeof(ExynosVideoBuffer));
   2134         memcpy((char *)(&(pVideoBuffer->PDSB)), (char *)pPDSB, sizeof(PrivateDataShareBuffer));
   2135     } else {
   2136         ret = VIDEO_ERROR_NOBUFFERS;
   2137         ALOGV("%s :: %d", __FUNCTION__, __LINE__);
   2138     }
   2139 
   2140     pCtx->pOutbuf[buf.index].bQueued = VIDEO_FALSE;
   2141     MFC_Decoder_BufferIndexFree_Outbuf(pHandle, pPDSB, buf.index);
   2142 
   2143     pthread_mutex_unlock(pMutex);
   2144 
   2145 EXIT:
   2146     return ret;
   2147 }
   2148 
   2149 /*
   2150  * [Decoder Buffer OPS] Enable Dynamic DPB
   2151  */
   2152 static ExynosVideoErrorType MFC_Decoder_Enable_DynamicDPB(void *pHandle)
   2153 {
   2154     ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
   2155     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
   2156 
   2157     if (pCtx == NULL) {
   2158         ALOGE("%s: Video context info must be supplied", __func__);
   2159         ret = VIDEO_ERROR_BADPARAM;
   2160         goto EXIT;
   2161     }
   2162 
   2163     if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC_SET_DYNAMIC_DPB_MODE, 1) != 0) {
   2164         ret = VIDEO_ERROR_APIFAIL;
   2165         goto EXIT;
   2166     }
   2167 
   2168     if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC_SET_USER_SHARED_HANDLE, pCtx->nPrivateDataShareFD) != 0) {
   2169         ret = VIDEO_ERROR_APIFAIL;
   2170         goto EXIT;
   2171     }
   2172 
   2173 EXIT:
   2174     return ret;
   2175 }
   2176 
   2177 /*
   2178  * [Decoder OPS] Common
   2179  */
   2180 static ExynosVideoDecOps defDecOps = {
   2181     .nSize                  = 0,
   2182     .Init                   = MFC_Decoder_Init,
   2183     .Finalize               = MFC_Decoder_Finalize,
   2184     .Set_DisplayDelay       = MFC_Decoder_Set_DisplayDelay,
   2185     .Set_IFrameDecoding     = MFC_Decoder_Set_IFrameDecoding,
   2186     .Enable_PackedPB        = MFC_Decoder_Enable_PackedPB,
   2187     .Enable_LoopFilter      = MFC_Decoder_Enable_LoopFilter,
   2188     .Enable_SliceMode       = MFC_Decoder_Enable_SliceMode,
   2189     .Get_ActualBufferCount  = MFC_Decoder_Get_ActualBufferCount,
   2190     .Set_FrameTag           = MFC_Decoder_Set_FrameTag,
   2191     .Get_FrameTag           = MFC_Decoder_Get_FrameTag,
   2192     .Enable_SEIParsing      = MFC_Decoder_Enable_SEIParsing,
   2193     .Get_FramePackingInfo   = MFC_Decoder_Get_FramePackingInfo,
   2194 };
   2195 
   2196 /*
   2197  * [Decoder Buffer OPS] Input
   2198  */
   2199 static ExynosVideoDecBufferOps defInbufOps = {
   2200     .nSize                  = 0,
   2201     .Enable_Cacheable       = MFC_Decoder_Enable_Cacheable_Inbuf,
   2202     .Set_Shareable          = MFC_Decoder_Set_Shareable_Inbuf,
   2203     .Get_Buffer             = NULL,
   2204     .Set_Geometry           = MFC_Decoder_Set_Geometry_Inbuf,
   2205     .Get_Geometry           = NULL,
   2206     .Setup                  = MFC_Decoder_Setup_Inbuf,
   2207     .Run                    = MFC_Decoder_Run_Inbuf,
   2208     .Stop                   = MFC_Decoder_Stop_Inbuf,
   2209     .Enqueue                = MFC_Decoder_Enqueue_Inbuf,
   2210     .Enqueue_All            = NULL,
   2211     .Dequeue                = MFC_Decoder_Dequeue_Inbuf,
   2212     .Register               = MFC_Decoder_Register_Inbuf,
   2213     .Clear_RegisteredBuffer = MFC_Decoder_Clear_RegisteredBuffer_Inbuf,
   2214     .Clear_Queue            = MFC_Decoder_Clear_Queued_Inbuf,
   2215     .Cleanup_Buffer         = MFC_Decoder_Cleanup_Buffer_Inbuf,
   2216 };
   2217 
   2218 /*
   2219  * [Decoder Buffer OPS] Output
   2220  */
   2221 static ExynosVideoDecBufferOps defOutbufOps = {
   2222     .nSize                  = 0,
   2223     .Enable_Cacheable       = MFC_Decoder_Enable_Cacheable_Outbuf,
   2224     .Set_Shareable          = MFC_Decoder_Set_Shareable_Outbuf,
   2225     .Get_Buffer             = MFC_Decoder_Get_Buffer_Outbuf,
   2226     .Set_Geometry           = MFC_Decoder_Set_Geometry_Outbuf,
   2227     .Get_Geometry           = MFC_Decoder_Get_Geometry_Outbuf,
   2228     .Setup                  = MFC_Decoder_Setup_Outbuf,
   2229     .Run                    = MFC_Decoder_Run_Outbuf,
   2230     .Stop                   = MFC_Decoder_Stop_Outbuf,
   2231     .Enqueue                = MFC_Decoder_Enqueue_Outbuf,
   2232     .Enqueue_All            = NULL,
   2233     .Dequeue                = MFC_Decoder_Dequeue_Outbuf,
   2234     .Register               = MFC_Decoder_Register_Outbuf,
   2235     .Clear_RegisteredBuffer = MFC_Decoder_Clear_RegisteredBuffer_Outbuf,
   2236     .Clear_Queue            = MFC_Decoder_Clear_Queued_Outbuf,
   2237     .Cleanup_Buffer         = MFC_Decoder_Cleanup_Buffer_Outbuf,
   2238     .ExtensionEnqueue       = MFC_Decoder_ExtensionEnqueue_Outbuf,
   2239     .ExtensionDequeue       = MFC_Decoder_ExtensionDequeue_Outbuf,
   2240     .Enable_DynamicDPB      = MFC_Decoder_Enable_DynamicDPB,
   2241 };
   2242 
   2243 int Exynos_Video_Register_Decoder(
   2244     ExynosVideoDecOps       *pDecOps,
   2245     ExynosVideoDecBufferOps *pInbufOps,
   2246     ExynosVideoDecBufferOps *pOutbufOps)
   2247 {
   2248     ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
   2249 
   2250     if ((pDecOps == NULL) || (pInbufOps == NULL) || (pOutbufOps == NULL)) {
   2251         ret = VIDEO_ERROR_BADPARAM;
   2252         goto EXIT;
   2253     }
   2254 
   2255     defDecOps.nSize = sizeof(defDecOps);
   2256     defInbufOps.nSize = sizeof(defInbufOps);
   2257     defOutbufOps.nSize = sizeof(defOutbufOps);
   2258 
   2259     memcpy((char *)pDecOps + sizeof(pDecOps->nSize), (char *)&defDecOps + sizeof(defDecOps.nSize),
   2260             pDecOps->nSize - sizeof(pDecOps->nSize));
   2261 
   2262     memcpy((char *)pInbufOps + sizeof(pInbufOps->nSize), (char *)&defInbufOps + sizeof(defInbufOps.nSize),
   2263             pInbufOps->nSize - sizeof(pInbufOps->nSize));
   2264 
   2265     memcpy((char *)pOutbufOps + sizeof(pOutbufOps->nSize), (char *)&defOutbufOps + sizeof(defOutbufOps.nSize),
   2266             pOutbufOps->nSize - sizeof(pOutbufOps->nSize));
   2267 
   2268 EXIT:
   2269     return ret;
   2270 }
   2271