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