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@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 */
55static 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 */
92static 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 */
115static 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
176EXIT_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
189EXIT_OPEN_FAIL:
190    free(pCtx);
191
192EXIT_ALLOC_FAIL:
193    return NULL;
194}
195
196/*
197 * [Decoder OPS] Finalize
198 */
199static 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
278EXIT:
279    return ret;
280}
281
282/*
283 * [Decoder OPS] Set Frame Tag
284 */
285static 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
303EXIT:
304    return ret;
305}
306
307/*
308 * [Decoder OPS] Get Frame Tag
309 */
310static 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
322EXIT:
323    return frameTag;
324}
325
326/*
327 * [Decoder OPS] Get Buffer Count
328 */
329static 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
341EXIT:
342    return bufferCount;
343}
344
345/*
346 * [Decoder OPS] Set Display Delay
347 */
348static 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
366EXIT:
367    return ret;
368}
369
370/*
371 * [Decoder OPS] Set I-Frame Decoding
372 */
373static 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
390EXIT:
391    return ret;
392}
393
394/*
395 * [Decoder OPS] Enable Packed PB
396 */
397static 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
413EXIT:
414    return ret;
415}
416
417/*
418 * [Decoder OPS] Enable Loop Filter
419 */
420static 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
436EXIT:
437    return ret;
438}
439
440/*
441 * [Decoder OPS] Enable Slice Mode
442 */
443static 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
459EXIT:
460    return ret;
461}
462
463/*
464 * [Decoder OPS] Enable SEI Parsing
465 */
466static 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
482EXIT:
483    return ret;
484}
485
486/*
487 * [Decoder OPS] Get Frame Packing information
488 */
489static 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
547EXIT:
548    return ret;
549}
550
551/*
552 * [Decoder Buffer OPS] Enable Cacheable (Input)
553 */
554static 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
570EXIT:
571    return ret;
572}
573
574/*
575 * [Decoder Buffer OPS] Enable Cacheable (Output)
576 */
577static 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
593EXIT:
594    return ret;
595}
596
597/*
598 * [Decoder Buffer OPS] Set Shareable Buffer (Input)
599 */
600static 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
613EXIT:
614    return ret;
615}
616
617/*
618 * [Decoder Buffer OPS] Set Shareable Buffer (Output)
619 */
620static 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
633EXIT:
634    return ret;
635}
636
637/*
638 * [Decoder Buffer OPS] Get Buffer (Input)
639 */
640static 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
663EXIT:
664    return ret;
665}
666
667/*
668 * [Decoder Buffer OPS] Get Buffer (Output)
669 */
670static 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
693EXIT:
694    return ret;
695}
696
697/*
698 * [Decoder Buffer OPS] Set Geometry (Input)
699 */
700static 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
734EXIT:
735    return ret;
736}
737
738/*
739 * [Decoder Buffer OPS] Set Geometry (Output)
740 */
741static 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
774EXIT:
775    return ret;
776}
777
778/*
779 * [Decoder Buffer OPS] Get Geometry (Output)
780 */
781static 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
826EXIT:
827    return ret;
828}
829
830/*
831 * [Decoder Buffer OPS] Setup (Input)
832 */
833static 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
929EXIT:
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 */
952static 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
1050EXIT:
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 */
1076static 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
1096EXIT:
1097    return ret;
1098}
1099
1100/*
1101 * [Decoder Buffer OPS] Run (Output)
1102 */
1103static 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
1123EXIT:
1124    return ret;
1125}
1126
1127/*
1128 * [Decoder Buffer OPS] Stop (Input)
1129 */
1130static 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
1155EXIT:
1156    return ret;
1157}
1158
1159/*
1160 * [Decoder Buffer OPS] Stop (Output)
1161 */
1162static 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
1189EXIT:
1190    return ret;
1191}
1192
1193/*
1194 * [Decoder Buffer OPS] Wait (Input)
1195 */
1196static 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
1231EXIT:
1232    return ret;
1233}
1234
1235static 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
1269EXIT:
1270    return ret;
1271}
1272
1273static 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
1308EXIT:
1309    return ret;
1310}
1311
1312static 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
1329EXIT:
1330    return ret;
1331}
1332
1333static 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
1350EXIT:
1351    return ret;
1352}
1353
1354/*
1355 * [Decoder Buffer OPS] Find (Input)
1356 */
1357static 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
1380EXIT:
1381    return nIndex;
1382}
1383
1384/*
1385 * [Decoder Buffer OPS] Find (Outnput)
1386 */
1387static 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
1410EXIT:
1411    return nIndex;
1412}
1413
1414/*
1415 * [Decoder Buffer OPS] Enqueue (Input)
1416 */
1417static 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    // FIXME: figure out why |pPrivate| may be NULL.
1487    if (pPrivate &&
1488            (((OMX_BUFFERHEADERTYPE *)pPrivate)->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) {
1489        buf.flags |= V4L2_BUF_FLAG_LAST_FRAME;
1490        ALOGV("%s: OMX_BUFFERFLAG_EOS => LAST_FRAME: 0x%x", __func__,
1491              !!(buf.flags & V4L2_BUF_FLAG_LAST_FRAME));
1492    }
1493
1494    pCtx->pInbuf[buf.index].pPrivate = pPrivate;
1495
1496    pthread_mutex_unlock(pMutex);
1497
1498    if (exynos_v4l2_qbuf(pCtx->hDec, &buf) != 0) {
1499        ALOGE("%s: Failed to enqueue input buffer", __func__);
1500        pthread_mutex_lock(pMutex);
1501        pCtx->pInbuf[buf.index].pPrivate = NULL;
1502        pCtx->pInbuf[buf.index].bQueued  = VIDEO_FALSE;
1503        pthread_mutex_unlock(pMutex);
1504        ret = VIDEO_ERROR_APIFAIL;
1505        goto EXIT;
1506    }
1507
1508EXIT:
1509    return ret;
1510}
1511
1512/*
1513 * [Decoder Buffer OPS] Enqueue (Output)
1514 */
1515static ExynosVideoErrorType MFC_Decoder_Enqueue_Outbuf(
1516    void          *pHandle,
1517    unsigned char *pBuffer[],
1518    unsigned int   dataSize[],
1519    int            nPlanes,
1520    void          *pPrivate)
1521{
1522    ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1523    ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
1524    pthread_mutex_t       *pMutex = NULL;
1525
1526    struct v4l2_plane  planes[VIDEO_DECODER_OUTBUF_PLANES];
1527    struct v4l2_buffer buf;
1528    int i, index;
1529
1530    if (pCtx == NULL) {
1531        ALOGE("%s: Video context info must be supplied", __func__);
1532        ret = VIDEO_ERROR_BADPARAM;
1533        goto EXIT;
1534    }
1535
1536    if (VIDEO_DECODER_OUTBUF_PLANES < nPlanes) {
1537        ALOGE("%s: Number of max planes : %d, nPlanes : %d", __func__,
1538                                    VIDEO_DECODER_OUTBUF_PLANES, nPlanes);
1539        ret = VIDEO_ERROR_BADPARAM;
1540        goto EXIT;
1541    }
1542
1543    memset(&buf, 0, sizeof(buf));
1544    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1545    buf.m.planes = planes;
1546    buf.length = VIDEO_DECODER_OUTBUF_PLANES;
1547
1548    pMutex = (pthread_mutex_t*)pCtx->pOutMutex;
1549    pthread_mutex_lock(pMutex);
1550    index = MFC_Decoder_Find_Outbuf(pCtx, pBuffer[0]);
1551    if (index == -1) {
1552        pthread_mutex_unlock(pMutex);
1553        ALOGE("%s: Failed to get index", __func__);
1554        ret = VIDEO_ERROR_NOBUFFERS;
1555        goto EXIT;
1556    }
1557    buf.index = index;
1558    pCtx->pOutbuf[buf.index].bQueued = VIDEO_TRUE;
1559
1560    if (pCtx->bShareOutbuf == VIDEO_TRUE) {
1561        buf.memory = pCtx->nMemoryType;
1562        for (i = 0; i < nPlanes; i++) {
1563            /* V4L2_MEMORY_USERPTR */
1564            buf.m.planes[i].m.userptr = (unsigned long)pBuffer[i];
1565            /* V4L2_MEMORY_DMABUF */
1566            buf.m.planes[i].m.fd = pCtx->pOutbuf[index].planes[i].fd;
1567            buf.m.planes[i].length = pCtx->pOutbuf[index].planes[i].allocSize;
1568            buf.m.planes[i].bytesused = dataSize[i];
1569            ALOGV("%s: shared outbuf(%d) plane=%d addr=%p fd=%d len=%d used=%d\n", __func__,
1570                  index, i,
1571                  buf.m.planes[i].m.userptr,
1572                  buf.m.planes[i].m.fd,
1573                  buf.m.planes[i].length,
1574                  buf.m.planes[i].bytesused);
1575        }
1576    } else {
1577        ALOGV("%s: non-shared outbuf(%d)\n", __func__, index);
1578        buf.memory = V4L2_MEMORY_MMAP;
1579    }
1580
1581    pCtx->pOutbuf[buf.index].pPrivate = pPrivate;
1582
1583    pthread_mutex_unlock(pMutex);
1584
1585    if (exynos_v4l2_qbuf(pCtx->hDec, &buf) != 0) {
1586        ALOGE("%s: Failed to enqueue output buffer", __func__);
1587        pthread_mutex_lock(pMutex);
1588        pCtx->pOutbuf[buf.index].pPrivate = NULL;
1589        pCtx->pOutbuf[buf.index].bQueued  = VIDEO_FALSE;
1590        pthread_mutex_unlock(pMutex);
1591        ret = VIDEO_ERROR_APIFAIL;
1592        goto EXIT;
1593    }
1594
1595EXIT:
1596    return ret;
1597}
1598
1599/*
1600 * [Decoder Buffer OPS] Dequeue (Input)
1601 */
1602static ExynosVideoBuffer *MFC_Decoder_Dequeue_Inbuf(void *pHandle)
1603{
1604    ExynosVideoDecContext *pCtx     = (ExynosVideoDecContext *)pHandle;
1605    ExynosVideoBuffer     *pInbuf   = NULL;
1606    pthread_mutex_t       *pMutex = NULL;
1607
1608    struct v4l2_buffer buf;
1609
1610    if (pCtx == NULL) {
1611        ALOGE("%s: Video context info must be supplied", __func__);
1612        goto EXIT;
1613    }
1614
1615    if (pCtx->bStreamonInbuf == VIDEO_FALSE) {
1616        pInbuf = NULL;
1617        goto EXIT;
1618    }
1619
1620    memset(&buf, 0, sizeof(buf));
1621
1622    buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1623
1624    if (pCtx->bShareInbuf == VIDEO_TRUE)
1625        buf.memory = pCtx->nMemoryType;
1626    else
1627        buf.memory = V4L2_MEMORY_MMAP;
1628
1629    if (exynos_v4l2_dqbuf(pCtx->hDec, &buf) != 0) {
1630        pInbuf = NULL;
1631        goto EXIT;
1632    }
1633
1634    pMutex = (pthread_mutex_t*)pCtx->pInMutex;
1635    pthread_mutex_lock(pMutex);
1636
1637    pInbuf = &pCtx->pInbuf[buf.index];
1638    pCtx->pInbuf[buf.index].bQueued = VIDEO_FALSE;
1639
1640    if (pCtx->bStreamonInbuf == VIDEO_FALSE)
1641        pInbuf = NULL;
1642
1643    pthread_mutex_unlock(pMutex);
1644
1645EXIT:
1646    return pInbuf;
1647}
1648
1649/*
1650 * [Decoder Buffer OPS] Dequeue (Output)
1651 */
1652static ExynosVideoBuffer *MFC_Decoder_Dequeue_Outbuf(void *pHandle)
1653{
1654    ExynosVideoDecContext *pCtx    = (ExynosVideoDecContext *)pHandle;
1655    ExynosVideoBuffer     *pOutbuf = NULL;
1656    pthread_mutex_t       *pMutex = NULL;
1657
1658    struct v4l2_buffer buf;
1659    int value, state;
1660
1661    if (pCtx == NULL) {
1662        ALOGE("%s: Video context info must be supplied", __func__);
1663        goto EXIT;
1664    }
1665
1666    if (pCtx->bStreamonOutbuf == VIDEO_FALSE) {
1667        pOutbuf = NULL;
1668        goto EXIT;
1669    }
1670
1671    memset(&buf, 0, sizeof(buf));
1672    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1673
1674    if (pCtx->bShareOutbuf == VIDEO_TRUE)
1675        buf.memory = pCtx->nMemoryType;
1676    else
1677        buf.memory = V4L2_MEMORY_MMAP;
1678
1679    /* HACK: pOutbuf return -1 means DECODING_ONLY for almost cases */
1680    if (exynos_v4l2_dqbuf(pCtx->hDec, &buf) != 0) {
1681        pOutbuf = NULL;
1682        goto EXIT;
1683    }
1684
1685    if (pCtx->bStreamonOutbuf == VIDEO_FALSE) {
1686        pOutbuf = NULL;
1687        goto EXIT;
1688    }
1689
1690    pMutex = (pthread_mutex_t*)pCtx->pOutMutex;
1691    pthread_mutex_lock(pMutex);
1692
1693    pOutbuf = &pCtx->pOutbuf[buf.index];
1694
1695    exynos_v4l2_g_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC51_VIDEO_DISPLAY_STATUS, &value);
1696
1697    switch (value) {
1698    case 0:
1699        pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DECODING_ONLY;
1700        break;
1701    case 1:
1702        pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DISPLAY_DECODING;
1703        break;
1704    case 2:
1705        pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DISPLAY_ONLY;
1706        break;
1707    case 3:
1708        exynos_v4l2_g_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC51_VIDEO_CHECK_STATE, &state);
1709        if (state == 1) /* Resolution is changed */
1710            pOutbuf->displayStatus = VIDEO_FRAME_STATUS_CHANGE_RESOL;
1711        else            /* Decoding is finished */
1712            pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DECODING_FINISHED;
1713        break;
1714    default:
1715        pOutbuf->displayStatus = VIDEO_FRAME_STATUS_UNKNOWN;
1716        break;
1717    }
1718
1719    switch (buf.flags & (0x7 << 3)) {
1720    case V4L2_BUF_FLAG_KEYFRAME:
1721        pOutbuf->frameType = VIDEO_FRAME_I;
1722        break;
1723    case V4L2_BUF_FLAG_PFRAME:
1724        pOutbuf->frameType = VIDEO_FRAME_P;
1725        break;
1726    case V4L2_BUF_FLAG_BFRAME:
1727        pOutbuf->frameType = VIDEO_FRAME_B;
1728        break;
1729    default:
1730        pOutbuf->frameType = VIDEO_FRAME_OTHERS;
1731        break;
1732    };
1733
1734    pOutbuf->bQueued = VIDEO_FALSE;
1735
1736    pthread_mutex_unlock(pMutex);
1737
1738EXIT:
1739    return pOutbuf;
1740}
1741
1742static ExynosVideoErrorType MFC_Decoder_Clear_Queued_Inbuf(void *pHandle)
1743{
1744    ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1745    ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
1746    int i;
1747
1748    if (pCtx == NULL) {
1749        ALOGE("%s: Video context info must be supplied", __func__);
1750        ret = VIDEO_ERROR_BADPARAM;
1751        goto EXIT;
1752    }
1753
1754    for (i = 0; i < pCtx->nInbufs; i++) {
1755        pCtx->pInbuf[i].bQueued = VIDEO_FALSE;
1756    }
1757
1758EXIT:
1759    return ret;
1760}
1761
1762static ExynosVideoErrorType MFC_Decoder_Clear_Queued_Outbuf(void *pHandle)
1763{
1764    ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1765    ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
1766    int i;
1767
1768    if (pCtx == NULL) {
1769        ALOGE("%s: Video context info must be supplied", __func__);
1770        ret = VIDEO_ERROR_BADPARAM;
1771        goto EXIT;
1772    }
1773
1774    for (i = 0; i < pCtx->nOutbufs; i++) {
1775        pCtx->pOutbuf[i].bQueued = VIDEO_FALSE;
1776    }
1777
1778EXIT:
1779    return ret;
1780}
1781
1782/*
1783 * [Decoder Buffer OPS] Cleanup Buffer (Input)
1784 */
1785static ExynosVideoErrorType MFC_Decoder_Cleanup_Buffer_Inbuf(void *pHandle)
1786{
1787    ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1788    ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
1789
1790    struct v4l2_requestbuffers req;
1791    int nBufferCount = 0;
1792
1793    if (pCtx == NULL) {
1794        ALOGE("%s: Video context info must be supplied", __func__);
1795        ret = VIDEO_ERROR_BADPARAM;
1796        goto EXIT;
1797    }
1798
1799    nBufferCount = 0; /* for clean-up */
1800
1801    memset(&req, 0, sizeof(req));
1802
1803    req.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1804    req.count = nBufferCount;
1805
1806    if (pCtx->bShareInbuf == VIDEO_TRUE)
1807        req.memory = pCtx->nMemoryType;
1808    else
1809        req.memory = V4L2_MEMORY_MMAP;
1810
1811    if (exynos_v4l2_reqbufs(pCtx->hDec, &req) != 0) {
1812        ret = VIDEO_ERROR_APIFAIL;
1813        goto EXIT;
1814    }
1815
1816    pCtx->nInbufs = (int)req.count;
1817
1818    if (pCtx->pInbuf != NULL) {
1819        free(pCtx->pInbuf);
1820        pCtx->pInbuf = NULL;
1821    }
1822
1823EXIT:
1824    return ret;
1825}
1826
1827/*
1828 * [Decoder Buffer OPS] Cleanup Buffer (Output)
1829 */
1830static ExynosVideoErrorType MFC_Decoder_Cleanup_Buffer_Outbuf(void *pHandle)
1831{
1832    ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1833    ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
1834
1835    struct v4l2_requestbuffers req;
1836    int nBufferCount = 0;
1837
1838    if (pCtx == NULL) {
1839        ALOGE("%s: Video context info must be supplied", __func__);
1840        ret = VIDEO_ERROR_BADPARAM;
1841        goto EXIT;
1842    }
1843
1844    nBufferCount = 0; /* for clean-up */
1845
1846    memset(&req, 0, sizeof(req));
1847
1848    req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1849    req.count = nBufferCount;
1850
1851    if (pCtx->bShareOutbuf == VIDEO_TRUE)
1852        req.memory = pCtx->nMemoryType;
1853    else
1854        req.memory = V4L2_MEMORY_MMAP;
1855
1856    if (exynos_v4l2_reqbufs(pCtx->hDec, &req) != 0) {
1857        ret = VIDEO_ERROR_APIFAIL;
1858        goto EXIT;
1859    }
1860
1861    pCtx->nOutbufs = (int)req.count;
1862
1863    if (pCtx->pOutbuf != NULL) {
1864        free(pCtx->pOutbuf);
1865        pCtx->pOutbuf = NULL;
1866    }
1867
1868EXIT:
1869    return ret;
1870}
1871
1872/*
1873 * [Decoder Buffer OPS] FindIndex (Output)
1874 */
1875static int MFC_Decoder_FindEmpty_Outbuf(void *pHandle)
1876{
1877    ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1878    int nIndex = -1;
1879
1880    if (pCtx == NULL) {
1881        ALOGE("%s: Video context info must be supplied", __func__);
1882        goto EXIT;
1883    }
1884
1885    for (nIndex = 0; nIndex < pCtx->nOutbufs; nIndex++) {
1886        if ((pCtx->pOutbuf[nIndex].bQueued == VIDEO_FALSE) &&
1887            (pCtx->pOutbuf[nIndex].bSlotUsed == VIDEO_FALSE))
1888            break;
1889    }
1890
1891    if (nIndex == pCtx->nOutbufs)
1892        nIndex = -1;
1893
1894EXIT:
1895    return nIndex;
1896}
1897
1898/*
1899 * [Decoder Buffer OPS] BufferIndexFree (Output)
1900 */
1901void MFC_Decoder_BufferIndexFree_Outbuf(void *pHandle, PrivateDataShareBuffer *pPDSB, int index)
1902{
1903    ExynosVideoDecContext *pCtx    = (ExynosVideoDecContext *)pHandle;
1904    int i, j;
1905
1906    ALOGV("De-queue buf.index:%d", index);
1907    ALOGV("pOutbuf fd:%d", pCtx->pOutbuf[index].planes[0].fd);
1908
1909    if (pCtx->pOutbuf[index].nIndexUseCnt == 0) {
1910        pCtx->pOutbuf[index].bSlotUsed = VIDEO_FALSE;
1911    }
1912
1913    for (i = 0; pPDSB->dpbFD[i].fd > -1; i++) {
1914        ALOGV("pPDSB->dpbFD[%d].fd:%d", i, pPDSB->dpbFD[i].fd);
1915        for (j = 0; pCtx->nOutbufs > j; j++)
1916            if (pPDSB->dpbFD[i].fd == pCtx->pOutbuf[j].planes[0].fd) {
1917                if (pCtx->pOutbuf[j].bQueued == VIDEO_FALSE) {
1918                    if (pCtx->pOutbuf[j].nIndexUseCnt > 0)
1919                        pCtx->pOutbuf[j].nIndexUseCnt--;
1920                } else if(pCtx->pOutbuf[j].bQueued == VIDEO_TRUE) {
1921                    if (pCtx->pOutbuf[j].nIndexUseCnt > 1) {
1922                        /* The buffer being used as the reference buffer came again. */
1923                        pCtx->pOutbuf[j].nIndexUseCnt--;
1924                    } else {
1925                        /* Reference DPB buffer is internally reused. */
1926                    }
1927                }
1928                ALOGV("dec FD:%d, pCtx->pOutbuf[%d].nIndexUseCnt:%d", pPDSB->dpbFD[i].fd, j, pCtx->pOutbuf[j].nIndexUseCnt);
1929                if ((pCtx->pOutbuf[j].nIndexUseCnt == 0) &&
1930                    (pCtx->pOutbuf[j].bQueued == VIDEO_FALSE)) {
1931                    pCtx->pOutbuf[j].bSlotUsed = VIDEO_FALSE;
1932                }
1933            }
1934    }
1935    memset((char *)pPDSB, -1, sizeof(PrivateDataShareBuffer));
1936
1937    return;
1938}
1939
1940/*
1941 * [Decoder Buffer OPS] ExtensionEnqueue (Output)
1942 */
1943static ExynosVideoErrorType MFC_Decoder_ExtensionEnqueue_Outbuf(
1944    void          *pHandle,
1945    unsigned char *pBuffer[],
1946    unsigned int  *pFd[],
1947    unsigned int   allocLen[],
1948    unsigned int   dataSize[],
1949    int            nPlanes,
1950    void          *pPrivate)
1951{
1952    ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1953    ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
1954    pthread_mutex_t       *pMutex = NULL;
1955
1956    struct v4l2_plane  planes[VIDEO_DECODER_OUTBUF_PLANES];
1957    struct v4l2_buffer buf;
1958    int state, index, i;
1959
1960    if (pCtx == NULL) {
1961        ALOGE("%s: Video context info must be supplied", __func__);
1962        ret = VIDEO_ERROR_BADPARAM;
1963        goto EXIT;
1964    }
1965
1966    if (VIDEO_DECODER_OUTBUF_PLANES < nPlanes) {
1967        ALOGE("%s: Number of max planes : %d, nPlanes : %d", __func__,
1968                                    VIDEO_DECODER_OUTBUF_PLANES, nPlanes);
1969        ret = VIDEO_ERROR_BADPARAM;
1970        goto EXIT;
1971    }
1972
1973    memset(&buf, 0, sizeof(buf));
1974    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1975    buf.m.planes = planes;
1976    buf.length = VIDEO_DECODER_OUTBUF_PLANES;
1977
1978    pMutex = (pthread_mutex_t*)pCtx->pOutMutex;
1979    pthread_mutex_lock(pMutex);
1980
1981    index = MFC_Decoder_Find_Outbuf(pCtx, pBuffer[0]);
1982    if (index == -1) {
1983        ALOGV("%s: Failed to find index", __func__);
1984        index = MFC_Decoder_FindEmpty_Outbuf(pCtx);
1985        if (index == -1) {
1986            pthread_mutex_unlock(pMutex);
1987            ALOGE("%s: Failed to get index", __func__);
1988            ret = VIDEO_ERROR_NOBUFFERS;
1989            goto EXIT;
1990        }
1991    }
1992
1993    buf.index = index;
1994    ALOGV("En-queue index:%d pCtx->pOutbuf[buf.index].bQueued:%d, pFd[0]:%d",
1995           index, pCtx->pOutbuf[buf.index].bQueued, pFd[0]);
1996    pCtx->pOutbuf[buf.index].bQueued = VIDEO_TRUE;
1997    pCtx->pOutbuf[buf.index].bSlotUsed = VIDEO_TRUE;
1998
1999    buf.memory = pCtx->nMemoryType;
2000    for (i = 0; i < nPlanes; i++) {
2001        /* V4L2_MEMORY_USERPTR */
2002        buf.m.planes[i].m.userptr = (unsigned long)pBuffer[i];
2003        /* V4L2_MEMORY_DMABUF */
2004        buf.m.planes[i].m.fd = pFd[i];
2005        buf.m.planes[i].length = allocLen[i];
2006        buf.m.planes[i].bytesused = dataSize[i];
2007
2008        /* Temporary storage for Dequeue */
2009        pCtx->pOutbuf[buf.index].planes[i].addr = (unsigned long)pBuffer[i];
2010        pCtx->pOutbuf[buf.index].planes[i].fd = (unsigned int)pFd[i];
2011        pCtx->pOutbuf[buf.index].planes[i].allocSize = allocLen[i];
2012
2013        ALOGV("%s: shared outbuf(%d) plane=%d addr=0x%x fd=%d len=%d used=%d\n",
2014              __func__, index, i,
2015              (void*)buf.m.planes[i].m.userptr, buf.m.planes[i].m.fd,
2016              buf.m.planes[i].length, buf.m.planes[i].bytesused);
2017    }
2018
2019    pCtx->pOutbuf[buf.index].pPrivate = pPrivate;
2020    pCtx->pOutbuf[buf.index].nIndexUseCnt++;
2021
2022    pthread_mutex_unlock(pMutex);
2023
2024    if (exynos_v4l2_qbuf(pCtx->hDec, &buf) != 0) {
2025        pthread_mutex_lock(pMutex);
2026        pCtx->pOutbuf[buf.index].nIndexUseCnt--;
2027        pCtx->pOutbuf[buf.index].pPrivate = NULL;
2028        pCtx->pOutbuf[buf.index].bQueued  = VIDEO_FALSE;
2029        if (pCtx->pOutbuf[buf.index].nIndexUseCnt == 0)
2030            pCtx->pOutbuf[buf.index].bSlotUsed = VIDEO_FALSE;
2031        exynos_v4l2_g_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC51_VIDEO_CHECK_STATE, &state);
2032        pthread_mutex_unlock(pMutex);
2033
2034        if (state == 1) {
2035            /* The case of Resolution is changed */
2036            ret = VIDEO_ERROR_WRONGBUFFERSIZE;
2037        } else {
2038            ALOGE("%s: Failed to enqueue output buffer", __func__);
2039            ret = VIDEO_ERROR_APIFAIL;
2040        }
2041        goto EXIT;
2042    }
2043
2044EXIT:
2045    return ret;
2046}
2047
2048/*
2049 * [Decoder Buffer OPS] ExtensionDequeue (Output)
2050 */
2051static ExynosVideoErrorType MFC_Decoder_ExtensionDequeue_Outbuf(
2052    void              *pHandle,
2053    ExynosVideoBuffer *pVideoBuffer)
2054{
2055    ExynosVideoDecContext  *pCtx    = (ExynosVideoDecContext *)pHandle;
2056    ExynosVideoErrorType    ret     = VIDEO_ERROR_NONE;
2057    pthread_mutex_t        *pMutex = NULL;
2058    ExynosVideoBuffer      *pOutbuf = NULL;
2059    PrivateDataShareBuffer *pPDSB  = NULL;
2060    struct v4l2_buffer buf;
2061    int value, state, i, j;
2062
2063    if (pCtx == NULL) {
2064        ALOGE("%s: Video context info must be supplied", __func__);
2065        ret = VIDEO_ERROR_BADPARAM;
2066        goto EXIT;
2067    }
2068
2069    if (pCtx->bStreamonOutbuf == VIDEO_FALSE) {
2070        pOutbuf = NULL;
2071        ret = VIDEO_ERROR_APIFAIL;
2072        goto EXIT;
2073    }
2074
2075    memset(&buf, 0, sizeof(buf));
2076    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2077
2078    if (pCtx->bShareOutbuf == VIDEO_TRUE)
2079        buf.memory = pCtx->nMemoryType;
2080    else
2081        buf.memory = V4L2_MEMORY_MMAP;
2082
2083    /* HACK: pOutbuf return -1 means DECODING_ONLY for almost cases */
2084    if (exynos_v4l2_dqbuf(pCtx->hDec, &buf) != 0) {
2085        pOutbuf = NULL;
2086        ret = VIDEO_ERROR_APIFAIL;
2087        goto EXIT;
2088    }
2089
2090    pMutex = (pthread_mutex_t*)pCtx->pOutMutex;
2091    pthread_mutex_lock(pMutex);
2092
2093    pOutbuf = &pCtx->pOutbuf[buf.index];
2094    exynos_v4l2_g_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC51_VIDEO_DISPLAY_STATUS, &value);
2095
2096    switch (value) {
2097    case 0:
2098        pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DECODING_ONLY;
2099        break;
2100    case 1:
2101        pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DISPLAY_DECODING;
2102        break;
2103    case 2:
2104        pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DISPLAY_ONLY;
2105        break;
2106    case 3:
2107        exynos_v4l2_g_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC51_VIDEO_CHECK_STATE, &state);
2108        if (state == 1) /* Resolution is changed */
2109            pOutbuf->displayStatus = VIDEO_FRAME_STATUS_CHANGE_RESOL;
2110        else            /* Decoding is finished */
2111            pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DECODING_FINISHED;
2112        break;
2113    default:
2114        pOutbuf->displayStatus = VIDEO_FRAME_STATUS_UNKNOWN;
2115        break;
2116    }
2117
2118    switch (buf.flags & (0x7 << 3)) {
2119    case V4L2_BUF_FLAG_KEYFRAME:
2120        pOutbuf->frameType = VIDEO_FRAME_I;
2121        break;
2122    case V4L2_BUF_FLAG_PFRAME:
2123        pOutbuf->frameType = VIDEO_FRAME_P;
2124        break;
2125    case V4L2_BUF_FLAG_BFRAME:
2126        pOutbuf->frameType = VIDEO_FRAME_B;
2127        break;
2128    default:
2129        pOutbuf->frameType = VIDEO_FRAME_OTHERS;
2130        break;
2131    };
2132
2133    pPDSB = ((PrivateDataShareBuffer *)pCtx->nPrivateDataShareAddress) + buf.index;
2134    if (pCtx->pOutbuf[buf.index].bQueued == VIDEO_TRUE) {
2135        memcpy(pVideoBuffer, pOutbuf, sizeof(ExynosVideoBuffer));
2136        memcpy((char *)(&(pVideoBuffer->PDSB)), (char *)pPDSB, sizeof(PrivateDataShareBuffer));
2137    } else {
2138        ret = VIDEO_ERROR_NOBUFFERS;
2139        ALOGV("%s :: %d", __FUNCTION__, __LINE__);
2140    }
2141
2142    pCtx->pOutbuf[buf.index].bQueued = VIDEO_FALSE;
2143    MFC_Decoder_BufferIndexFree_Outbuf(pHandle, pPDSB, buf.index);
2144
2145    pthread_mutex_unlock(pMutex);
2146
2147EXIT:
2148    return ret;
2149}
2150
2151/*
2152 * [Decoder Buffer OPS] Enable Dynamic DPB
2153 */
2154static ExynosVideoErrorType MFC_Decoder_Enable_DynamicDPB(void *pHandle)
2155{
2156    ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
2157    ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
2158
2159    if (pCtx == NULL) {
2160        ALOGE("%s: Video context info must be supplied", __func__);
2161        ret = VIDEO_ERROR_BADPARAM;
2162        goto EXIT;
2163    }
2164
2165    if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC_SET_DYNAMIC_DPB_MODE, 1) != 0) {
2166        ret = VIDEO_ERROR_APIFAIL;
2167        goto EXIT;
2168    }
2169
2170    if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC_SET_USER_SHARED_HANDLE, pCtx->nPrivateDataShareFD) != 0) {
2171        ret = VIDEO_ERROR_APIFAIL;
2172        goto EXIT;
2173    }
2174
2175EXIT:
2176    return ret;
2177}
2178
2179/*
2180 * [Decoder OPS] Common
2181 */
2182static ExynosVideoDecOps defDecOps = {
2183    .nSize                  = 0,
2184    .Init                   = MFC_Decoder_Init,
2185    .Finalize               = MFC_Decoder_Finalize,
2186    .Set_DisplayDelay       = MFC_Decoder_Set_DisplayDelay,
2187    .Set_IFrameDecoding     = MFC_Decoder_Set_IFrameDecoding,
2188    .Enable_PackedPB        = MFC_Decoder_Enable_PackedPB,
2189    .Enable_LoopFilter      = MFC_Decoder_Enable_LoopFilter,
2190    .Enable_SliceMode       = MFC_Decoder_Enable_SliceMode,
2191    .Get_ActualBufferCount  = MFC_Decoder_Get_ActualBufferCount,
2192    .Set_FrameTag           = MFC_Decoder_Set_FrameTag,
2193    .Get_FrameTag           = MFC_Decoder_Get_FrameTag,
2194    .Enable_SEIParsing      = MFC_Decoder_Enable_SEIParsing,
2195    .Get_FramePackingInfo   = MFC_Decoder_Get_FramePackingInfo,
2196};
2197
2198/*
2199 * [Decoder Buffer OPS] Input
2200 */
2201static ExynosVideoDecBufferOps defInbufOps = {
2202    .nSize                  = 0,
2203    .Enable_Cacheable       = MFC_Decoder_Enable_Cacheable_Inbuf,
2204    .Set_Shareable          = MFC_Decoder_Set_Shareable_Inbuf,
2205    .Get_Buffer             = NULL,
2206    .Set_Geometry           = MFC_Decoder_Set_Geometry_Inbuf,
2207    .Get_Geometry           = NULL,
2208    .Setup                  = MFC_Decoder_Setup_Inbuf,
2209    .Run                    = MFC_Decoder_Run_Inbuf,
2210    .Stop                   = MFC_Decoder_Stop_Inbuf,
2211    .Enqueue                = MFC_Decoder_Enqueue_Inbuf,
2212    .Enqueue_All            = NULL,
2213    .Dequeue                = MFC_Decoder_Dequeue_Inbuf,
2214    .Register               = MFC_Decoder_Register_Inbuf,
2215    .Clear_RegisteredBuffer = MFC_Decoder_Clear_RegisteredBuffer_Inbuf,
2216    .Clear_Queue            = MFC_Decoder_Clear_Queued_Inbuf,
2217    .Cleanup_Buffer         = MFC_Decoder_Cleanup_Buffer_Inbuf,
2218};
2219
2220/*
2221 * [Decoder Buffer OPS] Output
2222 */
2223static ExynosVideoDecBufferOps defOutbufOps = {
2224    .nSize                  = 0,
2225    .Enable_Cacheable       = MFC_Decoder_Enable_Cacheable_Outbuf,
2226    .Set_Shareable          = MFC_Decoder_Set_Shareable_Outbuf,
2227    .Get_Buffer             = MFC_Decoder_Get_Buffer_Outbuf,
2228    .Set_Geometry           = MFC_Decoder_Set_Geometry_Outbuf,
2229    .Get_Geometry           = MFC_Decoder_Get_Geometry_Outbuf,
2230    .Setup                  = MFC_Decoder_Setup_Outbuf,
2231    .Run                    = MFC_Decoder_Run_Outbuf,
2232    .Stop                   = MFC_Decoder_Stop_Outbuf,
2233    .Enqueue                = MFC_Decoder_Enqueue_Outbuf,
2234    .Enqueue_All            = NULL,
2235    .Dequeue                = MFC_Decoder_Dequeue_Outbuf,
2236    .Register               = MFC_Decoder_Register_Outbuf,
2237    .Clear_RegisteredBuffer = MFC_Decoder_Clear_RegisteredBuffer_Outbuf,
2238    .Clear_Queue            = MFC_Decoder_Clear_Queued_Outbuf,
2239    .Cleanup_Buffer         = MFC_Decoder_Cleanup_Buffer_Outbuf,
2240    .ExtensionEnqueue       = MFC_Decoder_ExtensionEnqueue_Outbuf,
2241    .ExtensionDequeue       = MFC_Decoder_ExtensionDequeue_Outbuf,
2242    .Enable_DynamicDPB      = MFC_Decoder_Enable_DynamicDPB,
2243};
2244
2245int Exynos_Video_Register_Decoder(
2246    ExynosVideoDecOps       *pDecOps,
2247    ExynosVideoDecBufferOps *pInbufOps,
2248    ExynosVideoDecBufferOps *pOutbufOps)
2249{
2250    ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
2251
2252    if ((pDecOps == NULL) || (pInbufOps == NULL) || (pOutbufOps == NULL)) {
2253        ret = VIDEO_ERROR_BADPARAM;
2254        goto EXIT;
2255    }
2256
2257    defDecOps.nSize = sizeof(defDecOps);
2258    defInbufOps.nSize = sizeof(defInbufOps);
2259    defOutbufOps.nSize = sizeof(defOutbufOps);
2260
2261    memcpy((char *)pDecOps + sizeof(pDecOps->nSize), (char *)&defDecOps + sizeof(defDecOps.nSize),
2262            pDecOps->nSize - sizeof(pDecOps->nSize));
2263
2264    memcpy((char *)pInbufOps + sizeof(pInbufOps->nSize), (char *)&defInbufOps + sizeof(defInbufOps.nSize),
2265            pInbufOps->nSize - sizeof(pInbufOps->nSize));
2266
2267    memcpy((char *)pOutbufOps + sizeof(pOutbufOps->nSize), (char *)&defOutbufOps + sizeof(defOutbufOps.nSize),
2268            pOutbufOps->nSize - sizeof(pOutbufOps->nSize));
2269
2270EXIT:
2271    return ret;
2272}
2273