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