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