24be4487c5841715033e20b53d5c2ceedf690bc4
[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     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;
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  * [Decoder Buffer OPS] Enable Cacheable (Input)
575  */
576 static ExynosVideoErrorType MFC_Decoder_Enable_Cacheable_Inbuf(void *pHandle)
577 {
578     ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
579     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
580
581     if (pCtx == NULL) {
582         ALOGE("%s: Video context info must be supplied", __func__);
583         ret = VIDEO_ERROR_BADPARAM;
584         goto EXIT;
585     }
586 #ifdef V4L2_CID_CACHEABLE
587     if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_CACHEABLE, 2) != 0) {
588         ret = VIDEO_ERROR_APIFAIL;
589         goto EXIT;
590     }
591 #endif
592 EXIT:
593     return ret;
594 }
595
596 /*
597  * [Decoder Buffer OPS] Enable Cacheable (Output)
598  */
599 static ExynosVideoErrorType MFC_Decoder_Enable_Cacheable_Outbuf(void *pHandle)
600 {
601     ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
602     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
603
604     if (pCtx == NULL) {
605         ALOGE("%s: Video context info must be supplied", __func__);
606         ret = VIDEO_ERROR_BADPARAM;
607         goto EXIT;
608     }
609 #ifdef V4L2_CID_CACHEABLE
610     if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_CACHEABLE, 1) != 0) {
611         ret = VIDEO_ERROR_APIFAIL;
612         goto EXIT;
613     }
614 #endif
615 EXIT:
616     return ret;
617 }
618
619 /*
620  * [Decoder Buffer OPS] Set Shareable Buffer (Input)
621  */
622 static ExynosVideoErrorType MFC_Decoder_Set_Shareable_Inbuf(void *pHandle)
623 {
624     ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
625     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
626
627     if (pCtx == NULL) {
628         ALOGE("%s: Video context info must be supplied", __func__);
629         ret = VIDEO_ERROR_BADPARAM;
630         goto EXIT;
631     }
632
633     pCtx->bShareInbuf = VIDEO_TRUE;
634
635 EXIT:
636     return ret;
637 }
638
639 /*
640  * [Decoder Buffer OPS] Set Shareable Buffer (Output)
641  */
642 static ExynosVideoErrorType MFC_Decoder_Set_Shareable_Outbuf(void *pHandle)
643 {
644     ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
645     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
646
647     if (pCtx == NULL) {
648         ALOGE("%s: Video context info must be supplied", __func__);
649         ret = VIDEO_ERROR_BADPARAM;
650         goto EXIT;
651     }
652
653     pCtx->bShareOutbuf = VIDEO_TRUE;
654
655 EXIT:
656     return ret;
657 }
658
659 /*
660  * [Decoder Buffer OPS] Get Buffer (Input)
661  */
662 static ExynosVideoErrorType MFC_Decoder_Get_Buffer_Inbuf(
663     void               *pHandle,
664     int                 nIndex,
665     ExynosVideoBuffer **pBuffer)
666 {
667     ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
668     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
669
670     if (pCtx == NULL) {
671         ALOGE("%s: Video context info must be supplied", __func__);
672         *pBuffer = NULL;
673         ret = VIDEO_ERROR_BADPARAM;
674         goto EXIT;
675     }
676
677     if (pCtx->nInbufs <= nIndex) {
678         *pBuffer = NULL;
679         ret = VIDEO_ERROR_BADPARAM;
680         goto EXIT;
681     }
682
683     *pBuffer = (ExynosVideoBuffer *)&pCtx->pInbuf[nIndex];
684
685 EXIT:
686     return ret;
687 }
688
689 /*
690  * [Decoder Buffer OPS] Get Buffer (Output)
691  */
692 static ExynosVideoErrorType MFC_Decoder_Get_Buffer_Outbuf(
693     void               *pHandle,
694     int                 nIndex,
695     ExynosVideoBuffer **pBuffer)
696 {
697     ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
698     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
699
700     if (pCtx == NULL) {
701         ALOGE("%s: Video context info must be supplied", __func__);
702         *pBuffer = NULL;
703         ret = VIDEO_ERROR_BADPARAM;
704         goto EXIT;
705     }
706
707     if (pCtx->nOutbufs <= nIndex) {
708         *pBuffer = NULL;
709         ret = VIDEO_ERROR_BADPARAM;
710         goto EXIT;
711     }
712
713     *pBuffer = (ExynosVideoBuffer *)&pCtx->pOutbuf[nIndex];
714
715 EXIT:
716     return ret;
717 }
718
719 /*
720  * [Decoder Buffer OPS] Set Geometry (Input)
721  */
722 static ExynosVideoErrorType MFC_Decoder_Set_Geometry_Inbuf(
723     void                *pHandle,
724     ExynosVideoGeometry *bufferConf)
725 {
726     ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
727     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
728
729     struct v4l2_format fmt;
730
731     if (pCtx == NULL) {
732         ALOGE("%s: Video context info must be supplied", __func__);
733         ret = VIDEO_ERROR_BADPARAM;
734         goto EXIT;
735     }
736
737     if (bufferConf == NULL) {
738         ALOGE("%s: Buffer geometry must be supplied", __func__);
739         ret = VIDEO_ERROR_BADPARAM;
740         goto EXIT;
741     }
742
743     memset(&fmt, 0, sizeof(fmt));
744
745     fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
746     fmt.fmt.pix_mp.pixelformat = __CodingType_To_V4L2PixelFormat(bufferConf->eCompressionFormat);
747     fmt.fmt.pix_mp.plane_fmt[0].sizeimage = bufferConf->nSizeImage;
748
749     if (exynos_v4l2_s_fmt(pCtx->hDec, &fmt) != 0) {
750         ret = VIDEO_ERROR_APIFAIL;
751         goto EXIT;
752     }
753
754     memcpy(&pCtx->inbufGeometry, bufferConf, sizeof(pCtx->inbufGeometry));
755
756 EXIT:
757     return ret;
758 }
759
760 /*
761  * [Decoder Buffer OPS] Set Geometry (Output)
762  */
763 static ExynosVideoErrorType MFC_Decoder_Set_Geometry_Outbuf(
764     void                *pHandle,
765     ExynosVideoGeometry *bufferConf)
766 {
767     ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
768     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
769
770     struct v4l2_format fmt;
771
772     if (pCtx == NULL) {
773         ALOGE("%s: Video context info must be supplied", __func__);
774         ret = VIDEO_ERROR_BADPARAM;
775         goto EXIT;
776     }
777
778     if (bufferConf == NULL) {
779         ALOGE("%s: Buffer geometry must be supplied", __func__);
780         ret = VIDEO_ERROR_BADPARAM;
781         goto EXIT;
782     }
783
784     memset(&fmt, 0, sizeof(fmt));
785
786     fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
787     fmt.fmt.pix_mp.pixelformat = __ColorFormatType_To_V4L2PixelFormat(bufferConf->eColorFormat);
788
789     if (exynos_v4l2_s_fmt(pCtx->hDec, &fmt) != 0) {
790         ret = VIDEO_ERROR_APIFAIL;
791         goto EXIT;
792     }
793
794     memcpy(&pCtx->outbufGeometry, bufferConf, sizeof(pCtx->outbufGeometry));
795
796 EXIT:
797     return ret;
798 }
799
800 /*
801  * [Decoder Buffer OPS] Get Geometry (Output)
802  */
803 static ExynosVideoErrorType MFC_Decoder_Get_Geometry_Outbuf(
804     void                *pHandle,
805     ExynosVideoGeometry *bufferConf)
806 {
807     ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
808     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
809
810     struct v4l2_format fmt;
811     struct v4l2_crop   crop;
812
813     if (pCtx == NULL) {
814         ALOGE("%s: Video context info must be supplied", __func__);
815         ret = VIDEO_ERROR_BADPARAM;
816         goto EXIT;
817     }
818
819     if (bufferConf == NULL) {
820         ALOGE("%s: Buffer geometry must be supplied", __func__);
821         ret = VIDEO_ERROR_BADPARAM;
822         goto EXIT;
823     }
824
825     memset(&fmt, 0, sizeof(fmt));
826     memset(&crop, 0, sizeof(crop));
827
828     fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
829
830     if (exynos_v4l2_g_fmt(pCtx->hDec, &fmt) != 0) {
831         ALOGE("%s: exynos_v4l2_g_fmt. ret = %d", __func__, ret);
832         ret = VIDEO_ERROR_APIFAIL;
833         goto EXIT;
834     }
835
836     crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
837
838     if (exynos_v4l2_g_crop(pCtx->hDec, &crop) != 0) {
839         ALOGE("%s: exynos_v4l2_g_crop. ret=%d", __func__, ret);
840         ret = VIDEO_ERROR_APIFAIL;
841         goto EXIT;
842     }
843
844     bufferConf->nFrameWidth = fmt.fmt.pix_mp.width;
845     bufferConf->nFrameHeight = fmt.fmt.pix_mp.height;
846
847     bufferConf->cropRect.nTop = crop.c.top;
848     bufferConf->cropRect.nLeft = crop.c.left;
849     bufferConf->cropRect.nWidth = crop.c.width;
850     bufferConf->cropRect.nHeight = crop.c.height;
851
852 EXIT:
853     return ret;
854 }
855
856 /*
857  * [Decoder Buffer OPS] Setup (Input)
858  */
859 static ExynosVideoErrorType MFC_Decoder_Setup_Inbuf(
860     void         *pHandle,
861     unsigned int  nBufferCount)
862 {
863     ExynosVideoDecContext *pCtx         = (ExynosVideoDecContext *)pHandle;
864     ExynosVideoPlane      *pVideoPlane  = NULL;
865     ExynosVideoErrorType   ret          = VIDEO_ERROR_NONE;
866
867     struct v4l2_requestbuffers req;
868     struct v4l2_buffer         buf;
869     struct v4l2_plane          planes[VIDEO_DECODER_INBUF_PLANES];
870     int i;
871
872     if (pCtx == NULL) {
873         ALOGE("%s: Video context info must be supplied", __func__);
874         ret = VIDEO_ERROR_BADPARAM;
875         goto EXIT;
876     }
877
878     if (nBufferCount == 0) {
879         ALOGE("%s: Buffer count must be greater than 0", __func__);
880         ret = VIDEO_ERROR_BADPARAM;
881         goto EXIT;
882     }
883
884     ALOGV("%s: setting up inbufs (%d) shared=%s\n", __func__, nBufferCount,
885           pCtx->bShareInbuf ? "true" : "false");
886
887     memset(&req, 0, sizeof(req));
888
889     req.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
890     req.count = nBufferCount;
891
892     if (pCtx->bShareInbuf == VIDEO_TRUE)
893         req.memory = pCtx->nMemoryType;
894     else
895         req.memory = V4L2_MEMORY_MMAP;
896
897     if (exynos_v4l2_reqbufs(pCtx->hDec, &req) != 0) {
898         ret = VIDEO_ERROR_APIFAIL;
899         goto EXIT;
900     }
901
902     if (req.count != nBufferCount) {
903         ALOGE("%s: asked for %d, got %d\n", __func__, nBufferCount, req.count);
904         ret = VIDEO_ERROR_NOMEM;
905         goto EXIT;
906     }
907
908     pCtx->nInbufs = (int)req.count;
909
910     pCtx->pInbuf = malloc(sizeof(*pCtx->pInbuf) * pCtx->nInbufs);
911     if (pCtx->pInbuf == NULL) {
912         ALOGE("Failed to allocate input buffer context");
913         ret = VIDEO_ERROR_NOMEM;
914         goto EXIT;
915     }
916     memset(pCtx->pInbuf, 0, sizeof(*pCtx->pInbuf) * pCtx->nInbufs);
917
918     memset(&buf, 0, sizeof(buf));
919
920     if (pCtx->bShareInbuf == VIDEO_FALSE) {
921         buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
922         buf.memory = V4L2_MEMORY_MMAP;
923         buf.m.planes = planes;
924         buf.length = VIDEO_DECODER_INBUF_PLANES;
925
926         ALOGV("[%s] INBUF V4L2_MEMORY_MMAP", __func__);
927         for (i = 0; i < pCtx->nInbufs; i++) {
928             buf.index = i;
929             if (exynos_v4l2_querybuf(pCtx->hDec, &buf) != 0) {
930                 ret = VIDEO_ERROR_APIFAIL;
931                 goto EXIT;
932             }
933
934             pVideoPlane = &pCtx->pInbuf[i].planes[0];
935
936             pVideoPlane->addr = mmap(NULL,
937                     buf.m.planes[0].length, PROT_READ | PROT_WRITE,
938                     MAP_SHARED, pCtx->hDec, buf.m.planes[0].m.mem_offset);
939
940             if (pVideoPlane->addr == MAP_FAILED) {
941                 ret = VIDEO_ERROR_MAPFAIL;
942                 goto EXIT;
943             }
944
945             pVideoPlane->allocSize = buf.m.planes[0].length;
946             pVideoPlane->dataSize = 0;
947
948             pCtx->pInbuf[i].pGeometry = &pCtx->inbufGeometry;
949             pCtx->pInbuf[i].bQueued = VIDEO_FALSE;
950             pCtx->pInbuf[i].bRegistered = VIDEO_TRUE;
951         }
952     }
953
954     return ret;
955
956 EXIT:
957     if ((pCtx != NULL) && (pCtx->pInbuf != NULL)) {
958         if (pCtx->bShareInbuf == VIDEO_FALSE) {
959             for (i = 0; i < pCtx->nInbufs; i++) {
960                 pVideoPlane = &pCtx->pInbuf[i].planes[0];
961                 if (pVideoPlane->addr == MAP_FAILED) {
962                     pVideoPlane->addr = NULL;
963                     break;
964                 }
965
966                 munmap(pVideoPlane->addr, pVideoPlane->allocSize);
967             }
968         }
969
970         free(pCtx->pInbuf);
971     }
972
973     return ret;
974 }
975
976 /*
977  * [Decoder Buffer OPS] Setup (Output)
978  */
979 static ExynosVideoErrorType MFC_Decoder_Setup_Outbuf(
980     void         *pHandle,
981     unsigned int  nBufferCount)
982 {
983     ExynosVideoDecContext *pCtx         = (ExynosVideoDecContext *)pHandle;
984     ExynosVideoPlane      *pVideoPlane  = NULL;
985     ExynosVideoErrorType   ret          = VIDEO_ERROR_NONE;
986
987     struct v4l2_requestbuffers req;
988     struct v4l2_buffer         buf;
989     struct v4l2_plane          planes[VIDEO_DECODER_OUTBUF_PLANES];
990     int i, j;
991
992     if (pCtx == NULL) {
993         ALOGE("%s: Video context info must be supplied", __func__);
994         ret = VIDEO_ERROR_BADPARAM;
995         goto EXIT;
996     }
997
998     if (nBufferCount == 0) {
999         ALOGE("%s: Buffer count must be greater than 0", __func__);
1000         ret = VIDEO_ERROR_BADPARAM;
1001         goto EXIT;
1002     }
1003
1004     ALOGV("%s: setting up outbufs (%d) shared=%s\n", __func__, nBufferCount,
1005           pCtx->bShareOutbuf ? "true" : "false");
1006
1007     memset(&req, 0, sizeof(req));
1008
1009     req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1010     req.count = nBufferCount;
1011
1012     if (pCtx->bShareOutbuf == VIDEO_TRUE)
1013         req.memory = pCtx->nMemoryType;
1014     else
1015         req.memory = V4L2_MEMORY_MMAP;
1016
1017     if (exynos_v4l2_reqbufs(pCtx->hDec, &req) != 0) {
1018         ret = VIDEO_ERROR_APIFAIL;
1019         goto EXIT;
1020     }
1021
1022     if (req.count != nBufferCount) {
1023         ALOGE("%s: asked for %d, got %d\n", __func__, nBufferCount, req.count);
1024         ret = VIDEO_ERROR_NOMEM;
1025         goto EXIT;
1026     }
1027
1028     pCtx->nOutbufs = req.count;
1029
1030     pCtx->pOutbuf = malloc(sizeof(*pCtx->pOutbuf) * pCtx->nOutbufs);
1031     if (pCtx->pOutbuf == NULL) {
1032         ALOGE("Failed to allocate output buffer context");
1033         ret = VIDEO_ERROR_NOMEM;
1034         goto EXIT;
1035     }
1036     memset(pCtx->pOutbuf, 0, sizeof(*pCtx->pOutbuf) * pCtx->nOutbufs);
1037
1038     memset(&buf, 0, sizeof(buf));
1039
1040     if (pCtx->bShareOutbuf == VIDEO_FALSE) {
1041         buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1042         buf.memory = V4L2_MEMORY_MMAP;
1043         buf.m.planes = planes;
1044         buf.length = VIDEO_DECODER_OUTBUF_PLANES;
1045
1046         ALOGV("[%s] OUTBUF V4L2_MEMORY_MMAP", __func__);
1047         for (i = 0; i < pCtx->nOutbufs; i++) {
1048             buf.index = i;
1049             if (exynos_v4l2_querybuf(pCtx->hDec, &buf) != 0) {
1050                 ret = VIDEO_ERROR_APIFAIL;
1051                 goto EXIT;
1052             }
1053
1054             for (j = 0; j < VIDEO_DECODER_OUTBUF_PLANES; j++) {
1055                 pVideoPlane = &pCtx->pOutbuf[i].planes[j];
1056                 pVideoPlane->addr = mmap(NULL,
1057                         buf.m.planes[j].length, PROT_READ | PROT_WRITE,
1058                         MAP_SHARED, pCtx->hDec, buf.m.planes[j].m.mem_offset);
1059
1060                 if (pVideoPlane->addr == MAP_FAILED) {
1061                     ret = VIDEO_ERROR_MAPFAIL;
1062                     goto EXIT;
1063                 }
1064
1065                 pVideoPlane->allocSize = buf.m.planes[j].length;
1066                 pVideoPlane->dataSize = 0;
1067
1068 #ifdef TIZEN_FEATURE_E3250 /* dmabuf */
1069 #if 0
1070                 if (pCtx->bufShareMethod == BUF_SHARE_FD) {
1071                     exynos_v4l2_expbuf(pCtx->hDec, &pVideoPlane->fd, buf.m.planes[j].m.mem_offset);
1072                     ALOGV("[%s] fd (%d) received from MFC", __func__, pVideoPlane->fd);
1073                 }
1074 #endif
1075 #endif
1076             }
1077
1078             pCtx->pOutbuf[i].pGeometry = &pCtx->outbufGeometry;
1079             pCtx->pOutbuf[i].bQueued = VIDEO_FALSE;
1080             pCtx->pOutbuf[i].bRegistered = VIDEO_TRUE;
1081         }
1082     }
1083
1084     return ret;
1085
1086 EXIT:
1087     if ((pCtx != NULL) && (pCtx->pOutbuf != NULL)) {
1088         if (pCtx->bShareOutbuf == VIDEO_FALSE) {
1089             for (i = 0; i < pCtx->nOutbufs; i++) {
1090                 for (j = 0; j < VIDEO_DECODER_OUTBUF_PLANES; j++) {
1091                     pVideoPlane = &pCtx->pOutbuf[i].planes[j];
1092                     if (pVideoPlane->addr == MAP_FAILED) {
1093                         pVideoPlane->addr = NULL;
1094                         break;
1095                     }
1096
1097                     munmap(pVideoPlane->addr, pVideoPlane->allocSize);
1098                 }
1099             }
1100         }
1101
1102         free(pCtx->pOutbuf);
1103     }
1104
1105     return ret;
1106 }
1107
1108 /*
1109  * [Decoder Buffer OPS] Run (Input)
1110  */
1111 static ExynosVideoErrorType MFC_Decoder_Run_Inbuf(void *pHandle)
1112 {
1113     ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1114     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
1115
1116     if (pCtx == NULL) {
1117         ALOGE("%s: Video context info must be supplied", __func__);
1118         ret = VIDEO_ERROR_BADPARAM;
1119         goto EXIT;
1120     }
1121
1122     if (pCtx->bStreamonInbuf == VIDEO_FALSE) {
1123         if (exynos_v4l2_streamon(pCtx->hDec, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) != 0) {
1124             ALOGE("%s: Failed to streamon for input buffer", __func__);
1125             ret = VIDEO_ERROR_APIFAIL;
1126             goto EXIT;
1127         }
1128         pCtx->bStreamonInbuf = VIDEO_TRUE;
1129     }
1130
1131 EXIT:
1132     return ret;
1133 }
1134
1135 /*
1136  * [Decoder Buffer OPS] Run (Output)
1137  */
1138 static ExynosVideoErrorType MFC_Decoder_Run_Outbuf(void *pHandle)
1139 {
1140     ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1141     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
1142
1143     if (pCtx == NULL) {
1144         ALOGE("%s: Video context info must be supplied", __func__);
1145         ret = VIDEO_ERROR_BADPARAM;
1146         goto EXIT;
1147     }
1148
1149     if (pCtx->bStreamonOutbuf == VIDEO_FALSE) {
1150         if (exynos_v4l2_streamon(pCtx->hDec, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) != 0) {
1151             ALOGE("%s: Failed to streamon for output buffer", __func__);
1152             ret = VIDEO_ERROR_APIFAIL;
1153             goto EXIT;
1154         }
1155         pCtx->bStreamonOutbuf = VIDEO_TRUE;
1156     }
1157
1158 EXIT:
1159     return ret;
1160 }
1161
1162 /*
1163  * [Decoder Buffer OPS] Stop (Input)
1164  */
1165 static ExynosVideoErrorType MFC_Decoder_Stop_Inbuf(void *pHandle)
1166 {
1167     ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1168     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
1169     int i = 0;
1170
1171     if (pCtx == NULL) {
1172         ALOGE("%s: Video context info must be supplied", __func__);
1173         ret = VIDEO_ERROR_BADPARAM;
1174         goto EXIT;
1175     }
1176
1177     if (pCtx->bStreamonInbuf == VIDEO_TRUE) {
1178         if (exynos_v4l2_streamoff(pCtx->hDec, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) != 0) {
1179             ALOGE("%s: Failed to streamoff for input buffer", __func__);
1180             ret = VIDEO_ERROR_APIFAIL;
1181             goto EXIT;
1182         }
1183         pCtx->bStreamonInbuf = VIDEO_FALSE;
1184     }
1185
1186     for (i = 0; i <  pCtx->nInbufs; i++) {
1187         pCtx->pInbuf[i].bQueued = VIDEO_FALSE;
1188     }
1189
1190 EXIT:
1191     return ret;
1192 }
1193
1194 /*
1195  * [Decoder Buffer OPS] Stop (Output)
1196  */
1197 static ExynosVideoErrorType MFC_Decoder_Stop_Outbuf(void *pHandle)
1198 {
1199     ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1200     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
1201     int i = 0;
1202
1203     if (pCtx == NULL) {
1204         ALOGE("%s: Video context info must be supplied", __func__);
1205         ret = VIDEO_ERROR_BADPARAM;
1206         goto EXIT;
1207     }
1208
1209     if (pCtx->bStreamonOutbuf == VIDEO_TRUE) {
1210         if (exynos_v4l2_streamoff(pCtx->hDec, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) != 0) {
1211             ALOGE("%s: Failed to streamoff for output buffer", __func__);
1212             ret = VIDEO_ERROR_APIFAIL;
1213             goto EXIT;
1214         }
1215         pCtx->bStreamonOutbuf = VIDEO_FALSE;
1216     }
1217
1218     for (i = 0; i < pCtx->nOutbufs; i++) {
1219         pCtx->pOutbuf[i].bQueued = VIDEO_FALSE;
1220     }
1221
1222 EXIT:
1223     return ret;
1224 }
1225
1226 #if 0
1227 /*
1228  * [Decoder Buffer OPS] Wait (Input)
1229  */
1230 static ExynosVideoErrorType MFC_Decoder_Wait_Inbuf(void *pHandle)
1231 {
1232     ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1233     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
1234
1235     struct pollfd poll_events;
1236     int poll_state;
1237
1238     if (pCtx == NULL) {
1239         ALOGE("%s: Video context info must be supplied", __func__);
1240         ret = VIDEO_ERROR_BADPARAM;
1241         goto EXIT;
1242     }
1243
1244     poll_events.fd = pCtx->hDec;
1245     poll_events.events = POLLOUT | POLLERR;
1246     poll_events.revents = 0;
1247
1248     do {
1249         poll_state = poll((struct pollfd*)&poll_events, 1, VIDEO_DECODER_POLL_TIMEOUT);
1250         if (poll_state > 0) {
1251             if (poll_events.revents & POLLOUT) {
1252                 break;
1253             } else {
1254                 ALOGE("%s: Poll return error", __func__);
1255                 ret = VIDEO_ERROR_POLL;
1256                 break;
1257             }
1258         } else if (poll_state < 0) {
1259             ALOGE("%s: Poll state error", __func__);
1260             ret = VIDEO_ERROR_POLL;
1261             break;
1262         }
1263     } while (poll_state == 0);
1264
1265 EXIT:
1266     return ret;
1267 }
1268 #endif
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
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 }