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