for callback invoke when resolution is changed
[platform/adaptation/ap_samsung/libomxil-e3250-v4l2.git] / exynos4 / libcodec / video / v4l2 / enc / ExynosVideoEncoder.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        ExynosVideoEncoder.c
20  * @brief
21  * @author      Hyeyeon Chung (hyeon.chung@samsung.com)
22  * @author      Jinsung Yang (jsgood.yang@samsung.com)
23  * @author      Yunji Kim (yunji.kim@samsung.com)
24  * @version     1.0.0
25  * @history
26  *   2012.02.09: Initial Version
27  */
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <unistd.h>
32 #include <string.h>
33 #include <fcntl.h>
34
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <sys/ioctl.h>
38 #include <sys/mman.h>
39 #include <pthread.h>
40
41 #include <sys/poll.h>
42
43 #include "ExynosVideoApi.h"
44 #include "ExynosVideoEnc.h"
45
46 /* #define LOG_NDEBUG 0 */
47 #define LOG_TAG "ExynosVideoEncoder"
48 #ifndef TIZEN_FEATURE_E3250 /* build env */
49 #include <utils/Log.h>
50 #else
51 #include "Exynos_OSAL_Log.h"
52 #endif
53
54 #define MAX_CTRL_NUM    91
55 #define H264_CTRL_NUM   91
56 #define MPEG4_CTRL_NUM  26
57 #define H263_CTRL_NUM   18
58
59 /* FIXME: build error related with kernel-header pkg */
60 #if 0
61 #ifndef V4L2_CID_MPEG_VIDEO_H264_PREPEND_SPSPPS_TO_IDR
62 #define V4L2_CID_MPEG_VIDEO_H264_PREPEND_SPSPPS_TO_IDR (V4L2_CID_MPEG_MFC_BASE + 46)
63 #endif
64 #endif
65 /*
66  * [Common] __CodingType_To_V4L2PixelFormat
67  */
68 static unsigned int __CodingType_To_V4L2PixelFormat(ExynosVideoCodingType codingType)
69 {
70     unsigned int pixelformat = V4L2_PIX_FMT_H264;
71
72     switch (codingType) {
73     case VIDEO_CODING_AVC:
74         pixelformat = V4L2_PIX_FMT_H264;
75         break;
76     case VIDEO_CODING_MPEG4:
77         pixelformat = V4L2_PIX_FMT_MPEG4;
78         break;
79     case VIDEO_CODING_VP8:
80         pixelformat = V4L2_PIX_FMT_VP8;
81         break;
82     case VIDEO_CODING_H263:
83         pixelformat = V4L2_PIX_FMT_H263;
84         break;
85     case VIDEO_CODING_VC1:
86         pixelformat = V4L2_PIX_FMT_VC1_ANNEX_G;
87         break;
88     case VIDEO_CODING_VC1_RCV:
89         pixelformat = V4L2_PIX_FMT_VC1_ANNEX_L;
90         break;
91     case VIDEO_CODING_MPEG2:
92         pixelformat = V4L2_PIX_FMT_MPEG2;
93         break;
94     default:
95         pixelformat = V4L2_PIX_FMT_H264;
96         break;
97     }
98
99     return pixelformat;
100 }
101
102 /*
103  * [Common] __ColorFormatType_To_V4L2PixelFormat
104  */
105 static unsigned int __ColorFormatType_To_V4L2PixelFormat(ExynosVideoColorFormatType colorFormatType)
106 {
107     unsigned int pixelformat = V4L2_PIX_FMT_NV12M;
108
109     switch (colorFormatType) {
110     case VIDEO_COLORFORMAT_NV12_TILED:
111 #ifdef EXYNOS_3250
112         pixelformat = V4L2_PIX_FMT_NV12MT_16X16;
113 #else
114         pixelformat = V4L2_PIX_FMT_NV12MT;
115 #endif
116         break;
117 #if 0
118     case VIDEO_COLORFORMAT_NV21:
119         pixelformat = V4L2_PIX_FMT_NV21M;
120         break;
121 #endif
122     case VIDEO_COLORFORMAT_NV12:
123     default:
124         pixelformat = V4L2_PIX_FMT_NV12M;
125         break;
126     }
127
128     return pixelformat;
129 }
130
131 /*
132  * [Encoder OPS] Init
133  */
134 static void *MFC_Encoder_Init(int nMemoryType)
135 {
136     ExynosVideoEncContext *pCtx     = NULL;
137     pthread_mutex_t       *pMutex   = NULL;
138     int needCaps = (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING);
139
140     pCtx = (ExynosVideoEncContext *)malloc(sizeof(*pCtx));
141     if (pCtx == NULL) {
142         ALOGE("%s: Failed to allocate encoder context buffer", __func__);
143         goto EXIT_ALLOC_FAIL;
144     }
145
146     memset(pCtx, 0, sizeof(*pCtx));
147
148     pCtx->hEnc = exynos_v4l2_open_devname(VIDEO_ENCODER_NAME, O_RDWR, 0);
149     if (pCtx->hEnc < 0) {
150         ALOGE("%s: Failed to open encoder device", __func__);
151         goto EXIT_OPEN_FAIL;
152     }
153
154     if (!exynos_v4l2_querycap(pCtx->hEnc, needCaps)) {
155         ALOGE("%s: Failed to querycap", __func__);
156         goto EXIT_QUERYCAP_FAIL;
157     }
158
159     pCtx->bStreamonInbuf = VIDEO_FALSE;
160     pCtx->bStreamonOutbuf = VIDEO_FALSE;
161
162     pCtx->nMemoryType = nMemoryType;
163
164     pMutex = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t));
165     if (pMutex == NULL) {
166         ALOGE("%s: Failed to allocate mutex about input buffer", __func__);
167         goto EXIT_QUERYCAP_FAIL;
168     }
169     if (pthread_mutex_init(pMutex, NULL) != 0) {
170         free(pMutex);
171         goto EXIT_QUERYCAP_FAIL;
172     }
173     pCtx->pInMutex = (void*)pMutex;
174
175     pMutex = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t));
176     if (pMutex == NULL) {
177         ALOGE("%s: Failed to allocate mutex about output buffer", __func__);
178         goto EXIT_QUERYCAP_FAIL;
179     }
180     if (pthread_mutex_init(pMutex, NULL) != 0) {
181         free(pMutex);
182         goto EXIT_QUERYCAP_FAIL;
183     }
184     pCtx->pOutMutex = (void*)pMutex;
185
186     return (void *)pCtx;
187
188 EXIT_QUERYCAP_FAIL:
189     if (pCtx->pInMutex != NULL) {
190         pthread_mutex_destroy(pCtx->pInMutex);
191         free(pCtx->pInMutex);
192     }
193
194     if (pCtx->pOutMutex != NULL) {
195         pthread_mutex_destroy(pCtx->pOutMutex);
196         free(pCtx->pOutMutex);
197     }
198
199     close(pCtx->hEnc);
200
201 EXIT_OPEN_FAIL:
202     free(pCtx);
203
204 EXIT_ALLOC_FAIL:
205     return NULL;
206 }
207
208 /*
209  * [Encoder OPS] Finalize
210  */
211 static ExynosVideoErrorType MFC_Encoder_Finalize(void *pHandle)
212 {
213     ExynosVideoEncContext *pCtx         = (ExynosVideoEncContext *)pHandle;
214     ExynosVideoPlane      *pVideoPlane  = NULL;
215     pthread_mutex_t       *pMutex       = NULL;
216     ExynosVideoErrorType   ret          = VIDEO_ERROR_NONE;
217     int i, j;
218
219     if (pCtx == NULL) {
220         ALOGE("%s: Video context info must be supplied", __func__);
221         ret = VIDEO_ERROR_BADPARAM;
222         goto EXIT;
223     }
224
225     if (pCtx->pOutMutex != NULL) {
226         pMutex = (pthread_mutex_t*)pCtx->pOutMutex;
227         pthread_mutex_destroy(pMutex);
228         free(pMutex);
229         pCtx->pOutMutex = NULL;
230     }
231
232     if (pCtx->pInMutex != NULL) {
233         pMutex = (pthread_mutex_t*)pCtx->pInMutex;
234         pthread_mutex_destroy(pMutex);
235         free(pMutex);
236         pCtx->pInMutex = NULL;
237     }
238
239     if (pCtx->bShareInbuf == VIDEO_FALSE) {
240         for (i = 0; i < pCtx->nInbufs; i++) {
241             for (j = 0; j < VIDEO_ENCODER_INBUF_PLANES; j++) {
242                 pVideoPlane = &pCtx->pInbuf[i].planes[j];
243                 if (pVideoPlane->addr != NULL) {
244                     munmap(pVideoPlane->addr, pVideoPlane->allocSize);
245                     pVideoPlane->addr = NULL;
246                     pVideoPlane->allocSize = 0;
247                     pVideoPlane->dataSize = 0;
248                 }
249
250                 pCtx->pInbuf[i].pGeometry = NULL;
251                 pCtx->pInbuf[i].bQueued = VIDEO_FALSE;
252                 pCtx->pInbuf[i].bRegistered = VIDEO_FALSE;
253             }
254         }
255     }
256
257     if (pCtx->bShareOutbuf == VIDEO_FALSE) {
258         for (i = 0; i < pCtx->nOutbufs; i++) {
259             for (j = 0; j < VIDEO_ENCODER_OUTBUF_PLANES; j++) {
260                 pVideoPlane = &pCtx->pOutbuf[i].planes[j];
261                 if (pVideoPlane->addr != NULL) {
262                     munmap(pVideoPlane->addr, pVideoPlane->allocSize);
263                     pVideoPlane->addr = NULL;
264                     pVideoPlane->allocSize = 0;
265                     pVideoPlane->dataSize = 0;
266                 }
267
268                 pCtx->pOutbuf[i].pGeometry = NULL;
269                 pCtx->pOutbuf[i].bQueued = VIDEO_FALSE;
270                 pCtx->pOutbuf[i].bRegistered = VIDEO_FALSE;
271             }
272         }
273     }
274
275     if (pCtx->pInbuf != NULL)
276         free(pCtx->pInbuf);
277
278     if (pCtx->pOutbuf != NULL)
279         free(pCtx->pOutbuf);
280
281     if (pCtx->hEnc > 0)
282         close(pCtx->hEnc);
283
284     free(pCtx);
285
286 EXIT:
287     return ret;
288 }
289
290 /*
291  * [Encoder OPS] Set Extended Control
292  */
293 static ExynosVideoErrorType MFC_Encoder_Set_EncParam (
294     void                *pHandle,
295     ExynosVideoEncParam *pEncParam)
296 {
297     ExynosVideoEncContext     *pCtx         = (ExynosVideoEncContext *)pHandle;
298     ExynosVideoEncInitParam   *pInitParam   = NULL;
299     ExynosVideoEncCommonParam *pCommonParam = NULL;
300
301     ExynosVideoErrorType       ret          = VIDEO_ERROR_NONE;
302
303     int i;
304     struct v4l2_ext_control  ext_ctrl[MAX_CTRL_NUM];
305     struct v4l2_ext_controls ext_ctrls;
306     int k = 0;
307
308     if ((pCtx == NULL) || (pEncParam == NULL)) {
309         ALOGE("%s: Video context info must be supplied", __func__);
310         ret = VIDEO_ERROR_BADPARAM;
311         goto EXIT;
312     }
313
314     pInitParam = &pEncParam->initParam;
315     pCommonParam = &pEncParam->commonParam;
316
317     /* common parameters */
318     ext_ctrl[k].id = V4L2_CID_MPEG_VIDEO_GOP_SIZE;
319     ext_ctrl[k++].value = pCommonParam->IDRPeriod;
320     ext_ctrl[k].id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE;
321     ext_ctrl[k++].value = pCommonParam->SliceMode;  /* 0: one, 1: fixed #mb, 3: fixed #bytes */
322     ext_ctrl[k].id = V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB;
323     ext_ctrl[k++].value = pCommonParam->RandomIntraMBRefresh;
324     ext_ctrl[k].id = V4L2_CID_MPEG_MFC51_VIDEO_PADDING;
325     ext_ctrl[k++].value = pCommonParam->PadControlOn;
326     ext_ctrl[k].id = V4L2_CID_MPEG_MFC51_VIDEO_PADDING_YUV;
327     ext_ctrl[k].value = pCommonParam->CrPadVal;
328     ext_ctrl[k].value |= (pCommonParam->CbPadVal << 8);
329     ext_ctrl[k++].value |= (pCommonParam->LumaPadVal << 16);
330     ext_ctrl[k].id = V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE;
331     ext_ctrl[k++].value = pCommonParam->EnableFRMRateControl;
332     ext_ctrl[k].id = V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE;
333     ext_ctrl[k++].value = pCommonParam->EnableMBRateControl;
334     ext_ctrl[k].id = V4L2_CID_MPEG_VIDEO_BITRATE;
335
336     /* FIXME temporary fix */
337     if (pCommonParam->Bitrate)
338         ext_ctrl[k++].value = pCommonParam->Bitrate;
339     else
340         ext_ctrl[k++].value = 1; /* just for testing Movie studio */
341
342     /* codec specific parameters */
343     switch (pEncParam->eCompressionFormat) {
344     case VIDEO_CODING_AVC:
345     {
346         ExynosVideoEncH264Param *pH264Param = &pEncParam->codecParam.h264;
347
348         /* common parameters but id is depends on codec */
349         ext_ctrl[k].id = V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP;
350         ext_ctrl[k++].value = pCommonParam->FrameQp;
351         ext_ctrl[k].id =  V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP;
352         ext_ctrl[k++].value = pCommonParam->FrameQp_P;
353         ext_ctrl[k].id =  V4L2_CID_MPEG_VIDEO_H264_MAX_QP;
354         ext_ctrl[k++].value = pCommonParam->QSCodeMax;
355         ext_ctrl[k].id = V4L2_CID_MPEG_VIDEO_H264_MIN_QP;
356         ext_ctrl[k++].value = pCommonParam->QSCodeMin;
357         ext_ctrl[k].id = V4L2_CID_MPEG_MFC51_VIDEO_RC_REACTION_COEFF;
358         ext_ctrl[k++].value = pCommonParam->CBRPeriodRf;
359
360         /* H.264 specific parameters */
361         switch (pCommonParam->SliceMode) {
362         case 0:
363             ext_ctrl[k].id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB;
364             ext_ctrl[k++].value = 1;  /* default */
365             ext_ctrl[k].id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES;
366             ext_ctrl[k++].value = 2800; /* based on MFC6.x */
367             break;
368         case 1:
369             ext_ctrl[k].id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB;
370             ext_ctrl[k++].value = pH264Param->SliceArgument;
371             ext_ctrl[k].id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES;
372             ext_ctrl[k++].value = 2800; /* based on MFC6.x */
373             break;
374         case 2: /* Fixed Byte number Slice mode */
375             ext_ctrl[k].id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB;
376             ext_ctrl[k++].value = 1; /* default */
377             ext_ctrl[k].id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES;
378             ext_ctrl[k++].value = pH264Param->SliceArgument;
379             break;
380         default:
381             break;
382         }
383
384         ext_ctrl[k].id = V4L2_CID_MPEG_VIDEO_H264_PROFILE;
385         ext_ctrl[k++].value = pH264Param->ProfileIDC;
386         ext_ctrl[k].id = V4L2_CID_MPEG_VIDEO_H264_LEVEL;
387         ext_ctrl[k++].value = pH264Param->LevelIDC;
388         ext_ctrl[k].id = V4L2_CID_MPEG_MFC51_VIDEO_H264_NUM_REF_PIC_FOR_P;
389         ext_ctrl[k++].value = pH264Param->NumberRefForPframes;
390         /*
391          * It should be set using h264Param->NumberBFrames after being handled by appl.
392          */
393         ext_ctrl[k].id =  V4L2_CID_MPEG_VIDEO_B_FRAMES;
394         ext_ctrl[k++].value = pH264Param->NumberBFrames;
395         ext_ctrl[k].id = V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE;
396         ext_ctrl[k++].value = pH264Param->LoopFilterDisable;
397         ext_ctrl[k].id = V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA;
398         ext_ctrl[k++].value = pH264Param->LoopFilterAlphaC0Offset;
399         ext_ctrl[k].id = V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA;
400         ext_ctrl[k++].value = pH264Param->LoopFilterBetaOffset;
401         ext_ctrl[k].id = V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE;
402         ext_ctrl[k++].value = pH264Param->SymbolMode;
403 #ifdef V4L2_CID_MPEG_MFC51_VIDEO_H264_INTERLACE
404         ext_ctrl[k].id = V4L2_CID_MPEG_MFC51_VIDEO_H264_INTERLACE;
405         ext_ctrl[k++].value = pH264Param->PictureInterlace;
406 #endif
407         ext_ctrl[k].id = V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM;
408         ext_ctrl[k++].value = pH264Param->Transform8x8Mode;
409 #ifdef V4L2_CID_MPEG_MFC51_VIDEO_H264_RC_FRAME_RATE
410         ext_ctrl[k].id = V4L2_CID_MPEG_MFC51_VIDEO_H264_RC_FRAME_RATE;
411         ext_ctrl[k++].value = pH264Param->FrameRate;
412 #endif
413         ext_ctrl[k].id =  V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP;
414         ext_ctrl[k++].value = pH264Param->FrameQp_B;
415
416         ext_ctrl[k].id =  V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_DARK;
417         ext_ctrl[k++].value = pH264Param->DarkDisable;
418         ext_ctrl[k].id =  V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_SMOOTH;
419         ext_ctrl[k++].value = pH264Param->SmoothDisable;
420         ext_ctrl[k].id =  V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_STATIC;
421         ext_ctrl[k++].value = pH264Param->StaticDisable;
422         ext_ctrl[k].id =  V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_ACTIVITY;
423         ext_ctrl[k++].value = pH264Param->ActivityDisable;
424
425         /* doesn't have to be set */
426         ext_ctrl[k].id = V4L2_CID_MPEG_VIDEO_GOP_CLOSURE;
427         ext_ctrl[k++].value = 1;
428         ext_ctrl[k].id = V4L2_CID_MPEG_VIDEO_H264_I_PERIOD;
429         ext_ctrl[k++].value = 10;
430         ext_ctrl[k].id = V4L2_CID_MPEG_VIDEO_VBV_SIZE;
431         ext_ctrl[k++].value = 0;
432         ext_ctrl[k].id = V4L2_CID_MPEG_VIDEO_HEADER_MODE;
433         ext_ctrl[k++].value = V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE; /* 0: seperated header, 1: header + first frame */
434         ext_ctrl[k].id =  V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE;
435         ext_ctrl[k++].value = 0;
436         ext_ctrl[k].id = V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC;
437         ext_ctrl[k++].value = V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_UNSPECIFIED;
438         ext_ctrl[k].id = V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_WIDTH;
439         ext_ctrl[k++].value = 0;
440         ext_ctrl[k].id =  V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_HEIGHT;
441         ext_ctrl[k++].value = 0;
442
443         /* Initial parameters : Frame Skip */
444         switch (pInitParam->FrameSkip) {
445         case VIDEO_FRAME_SKIP_MODE_LEVEL_LIMIT:
446
447             ext_ctrl[k].id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE;
448             ext_ctrl[k++].value = V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_LEVEL_LIMIT;
449             break;
450         case VIDEO_FRAME_SKIP_MODE_BUF_LIMIT:
451             ext_ctrl[k].id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE;
452             ext_ctrl[k++].value = V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT;
453             break;
454         default:
455             /* VIDEO_FRAME_SKIP_MODE_DISABLE (default) */
456             ext_ctrl[k].id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE;
457             ext_ctrl[k++].value = V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_DISABLED;
458             break;
459         }
460
461         /* SVC is not supported yet */
462         ext_ctrl[k].id =  V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING;
463         ext_ctrl[k++].value = 0;
464         ext_ctrl[k].id =  V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_TYPE;
465         ext_ctrl[k++].value = V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_B;
466         ext_ctrl[k].id =  V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER;
467         ext_ctrl[k++].value = 3;
468         ext_ctrl[k].id =  V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_QP;
469         ext_ctrl[k++].value = (0 << 16 | 0);
470         ext_ctrl[k].id =  V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_QP;
471         ext_ctrl[k++].value = (1 << 16 | 0);
472         ext_ctrl[k].id =  V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_QP;
473         ext_ctrl[k++].value = (2 << 16 | 0);
474         ext_ctrl[k].id =  V4L2_CID_MPEG_VIDEO_H264_SEI_FRAME_PACKING;
475         ext_ctrl[k++].value = 0;
476         ext_ctrl[k].id =  V4L2_CID_MPEG_VIDEO_H264_SEI_FP_CURRENT_FRAME_0;
477         ext_ctrl[k++].value = 0;
478 #ifdef V4L2_MPEG_VIDEO_H264_SEI_FP_TYPE_SIDE_BY_SIDE
479         ext_ctrl[k].id =  V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE;
480         ext_ctrl[k++].value = V4L2_MPEG_VIDEO_H264_SEI_FP_TYPE_SIDE_BY_SIDE;
481 #endif
482         /* FMO is not supported yet */
483         ext_ctrl[k].id =  V4L2_CID_MPEG_VIDEO_H264_FMO;
484         ext_ctrl[k++].value = 0;
485         ext_ctrl[k].id =  V4L2_CID_MPEG_VIDEO_H264_FMO_MAP_TYPE;
486         ext_ctrl[k++].value = V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_INTERLEAVED_SLICES;
487         ext_ctrl[k].id = V4L2_CID_MPEG_VIDEO_H264_FMO_SLICE_GROUP;
488         ext_ctrl[k++].value = 4;
489         ext_ctrl[k].id =  V4L2_CID_MPEG_VIDEO_H264_FMO_RUN_LENGTH;
490         ext_ctrl[k++].value = (0 << 30 | 0);
491         ext_ctrl[k].id =  V4L2_CID_MPEG_VIDEO_H264_FMO_RUN_LENGTH;
492         ext_ctrl[k++].value = (1 << 30 | 0);
493         ext_ctrl[k].id =  V4L2_CID_MPEG_VIDEO_H264_FMO_RUN_LENGTH;
494         ext_ctrl[k++].value = (2 << 30 | 0);
495         ext_ctrl[k].id =  V4L2_CID_MPEG_VIDEO_H264_FMO_RUN_LENGTH;
496         ext_ctrl[k++].value = (3 << 30 | 0);
497         ext_ctrl[k].id =  V4L2_CID_MPEG_VIDEO_H264_FMO_CHANGE_DIRECTION;
498         ext_ctrl[k++].value = V4L2_MPEG_VIDEO_H264_FMO_CHANGE_DIR_RIGHT;
499         ext_ctrl[k].id = V4L2_CID_MPEG_VIDEO_H264_FMO_CHANGE_RATE;
500         ext_ctrl[k++].value = 0;
501
502         /* ASO is not supported yet */
503         ext_ctrl[k].id =  V4L2_CID_MPEG_VIDEO_H264_ASO;
504         ext_ctrl[k++].value = 0;
505
506         for (i = 0; i < 32; i++) {
507             ext_ctrl[k].id =  V4L2_CID_MPEG_VIDEO_H264_ASO_SLICE_ORDER;
508             ext_ctrl[k++].value = (i << 16 | 0);
509         }
510
511         ext_ctrls.count = H264_CTRL_NUM;
512         break;
513     }
514
515     case VIDEO_CODING_MPEG4:
516     {
517         ExynosVideoEncMpeg4Param *pMpeg4Param = &pEncParam->codecParam.mpeg4;
518
519         /* common parameters but id is depends on codec */
520         ext_ctrl[k].id = V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP;
521         ext_ctrl[k++].value = pCommonParam->FrameQp;
522         ext_ctrl[k].id =  V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP;
523         ext_ctrl[k++].value = pCommonParam->FrameQp_P;
524         ext_ctrl[k].id =  V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP;
525         ext_ctrl[k++].value = pCommonParam->QSCodeMax;
526         ext_ctrl[k].id = V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP;
527         ext_ctrl[k++].value = pCommonParam->QSCodeMin;
528         ext_ctrl[k].id = V4L2_CID_MPEG_MFC51_VIDEO_RC_REACTION_COEFF;
529         ext_ctrl[k++].value = pCommonParam->CBRPeriodRf;
530
531         /* MPEG4 specific parameters */
532         switch (pCommonParam->SliceMode) {
533         case 0:
534             ext_ctrl[k].id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB;
535             ext_ctrl[k++].value = 1;  /* default */
536             ext_ctrl[k].id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES;
537             ext_ctrl[k++].value = 2800; /* based on MFC6.x */
538             break;
539         case 1:
540             ext_ctrl[k].id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB;
541             ext_ctrl[k++].value = pMpeg4Param->SliceArgument;
542             ext_ctrl[k].id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES;
543             ext_ctrl[k++].value = 2800; /* based on MFC6.x */
544             break;
545         case 2:
546             ext_ctrl[k].id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB;
547             ext_ctrl[k++].value = 1; /* default */
548             ext_ctrl[k].id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES;
549             ext_ctrl[k++].value = pMpeg4Param->SliceArgument;
550             break;
551         default:
552             break;
553         }
554
555         ext_ctrl[k].id = V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE;
556         ext_ctrl[k++].value = pMpeg4Param->ProfileIDC;
557         ext_ctrl[k].id = V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL;
558         ext_ctrl[k++].value = pMpeg4Param->LevelIDC;
559         ext_ctrl[k].id = V4L2_CID_MPEG_VIDEO_MPEG4_QPEL;
560         ext_ctrl[k++].value = pMpeg4Param->DisableQpelME;
561
562         /*
563          * It should be set using mpeg4Param->NumberBFrames after being handled by appl.
564          */
565         ext_ctrl[k].id =  V4L2_CID_MPEG_VIDEO_B_FRAMES;
566         ext_ctrl[k++].value = pMpeg4Param->NumberBFrames;
567 #ifdef V4L2_CID_MPEG_MFC51_VIDEO_MPEG4_VOP_TIME_RES
568         ext_ctrl[k].id = V4L2_CID_MPEG_MFC51_VIDEO_MPEG4_VOP_TIME_RES;
569         ext_ctrl[k++].value = pMpeg4Param->TimeIncreamentRes;
570 #endif
571 #ifdef V4L2_CID_MPEG_MFC51_VIDEO_MPEG4_VOP_FRM_DELTA
572         ext_ctrl[k].id = V4L2_CID_MPEG_MFC51_VIDEO_MPEG4_VOP_FRM_DELTA;
573         ext_ctrl[k++].value = pMpeg4Param->VopTimeIncreament;
574 #endif
575         ext_ctrl[k].id =  V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP;
576         ext_ctrl[k++].value = pMpeg4Param->FrameQp_B;
577         ext_ctrl[k].id = V4L2_CID_MPEG_VIDEO_VBV_SIZE;
578         ext_ctrl[k++].value = 0;
579         ext_ctrl[k].id = V4L2_CID_MPEG_VIDEO_HEADER_MODE;
580         ext_ctrl[k++].value = V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE;
581         ext_ctrl[k].id = V4L2_CID_MPEG_MFC51_VIDEO_RC_FIXED_TARGET_BIT;
582         ext_ctrl[k++].value = 1;
583
584         /* Initial parameters : Frame Skip */
585         switch (pInitParam->FrameSkip) {
586         case VIDEO_FRAME_SKIP_MODE_LEVEL_LIMIT:
587             ext_ctrl[k].id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE;
588             ext_ctrl[k++].value = V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_LEVEL_LIMIT;
589             break;
590         case VIDEO_FRAME_SKIP_MODE_BUF_LIMIT:
591             ext_ctrl[k].id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE;
592             ext_ctrl[k++].value = V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT;
593             break;
594         default:
595             /* VIDEO_FRAME_SKIP_MODE_DISABLE (default) */
596             ext_ctrl[k].id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE;
597             ext_ctrl[k++].value = V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_DISABLED;
598             break;
599         }
600
601         ext_ctrls.count = MPEG4_CTRL_NUM;
602         break;
603     }
604
605     case VIDEO_CODING_H263:
606     {
607         ExynosVideoEncH263Param *pH263Param = &pEncParam->codecParam.h263;
608
609         /* common parameters but id is depends on codec */
610         ext_ctrl[k].id = V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP;
611         ext_ctrl[k++].value = pCommonParam->FrameQp;
612         ext_ctrl[k].id =  V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP;
613         ext_ctrl[k++].value = pCommonParam->FrameQp_P;
614         ext_ctrl[k].id =  V4L2_CID_MPEG_VIDEO_H263_MAX_QP;
615         ext_ctrl[k++].value = pCommonParam->QSCodeMax;
616         ext_ctrl[k].id = V4L2_CID_MPEG_VIDEO_H263_MIN_QP;
617         ext_ctrl[k++].value = pCommonParam->QSCodeMin;
618         ext_ctrl[k].id = V4L2_CID_MPEG_MFC51_VIDEO_RC_REACTION_COEFF;
619         ext_ctrl[k++].value = pCommonParam->CBRPeriodRf;
620
621         /* H263 specific parameters */
622 #ifdef V4L2_CID_MPEG_MFC51_VIDEO_H263_RC_FRAME_RATE
623         ext_ctrl[k].id = V4L2_CID_MPEG_MFC51_VIDEO_H263_RC_FRAME_RATE;
624         ext_ctrl[k++].value = pH263Param->FrameRate;
625 #endif
626         ext_ctrl[k].id = V4L2_CID_MPEG_VIDEO_VBV_SIZE;
627         ext_ctrl[k++].value = 0;
628         ext_ctrl[k].id = V4L2_CID_MPEG_VIDEO_HEADER_MODE;
629         ext_ctrl[k++].value = V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE;
630         ext_ctrl[k].id = V4L2_CID_MPEG_MFC51_VIDEO_RC_FIXED_TARGET_BIT;
631         ext_ctrl[k++].value = 1;
632
633         /* Initial parameters : Frame Skip */
634         switch (pInitParam->FrameSkip) {
635         case VIDEO_FRAME_SKIP_MODE_LEVEL_LIMIT:
636             ext_ctrl[k].id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE;
637             ext_ctrl[k++].value = V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_LEVEL_LIMIT;
638             break;
639         case VIDEO_FRAME_SKIP_MODE_BUF_LIMIT:
640             ext_ctrl[k].id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE;
641             ext_ctrl[k++].value = V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT;
642             break;
643         default:
644             /* VIDEO_FRAME_SKIP_MODE_DISABLE (default) */
645             ext_ctrl[k].id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE;
646             ext_ctrl[k++].value = V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_DISABLED;
647             break;
648         }
649         ext_ctrls.count = H263_CTRL_NUM;
650         break;
651     }
652
653     default:
654         ALOGE("[%s] Undefined codec type",__func__);
655         ret = VIDEO_ERROR_BADPARAM;
656         goto EXIT;
657     }
658
659     ext_ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
660     ext_ctrls.controls = ext_ctrl;
661
662     if (exynos_v4l2_s_ext_ctrl(pCtx->hEnc, &ext_ctrls) != 0) {
663         ALOGE("%s: Failed to s_ext_ctrl", __func__);
664         ret = VIDEO_ERROR_APIFAIL;
665         goto EXIT;
666     }
667
668 EXIT:
669     return ret;
670 }
671
672 /*
673  * [Encoder OPS] Set Frame Tag
674  */
675 static ExynosVideoErrorType MFC_Encoder_Set_FrameTag(
676     void   *pHandle,
677     int     frameTag)
678 {
679     ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
680     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
681
682     if (pCtx == NULL) {
683         ALOGE("%s: Video context info must be supplied", __func__);
684         ret = VIDEO_ERROR_BADPARAM;
685         goto EXIT;
686     }
687 #ifdef V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG
688     if (exynos_v4l2_s_ctrl(pCtx->hEnc, V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG, frameTag) != 0) {
689         ALOGE("%s: Failed to s_ctrl", __func__);
690         ret = VIDEO_ERROR_APIFAIL;
691         goto EXIT;
692     }
693 #endif
694 EXIT:
695     return ret;
696 }
697
698 /*
699  * [Encoder OPS] Get Frame Tag
700  */
701 static int MFC_Encoder_Get_FrameTag(void *pHandle)
702 {
703     ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
704     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
705
706     int frameTag = -1;
707
708     if (pCtx == NULL) {
709         ALOGE("%s: Video context info must be supplied", __func__);
710         goto EXIT;
711     }
712 #ifdef V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG
713     if (exynos_v4l2_g_ctrl(pCtx->hEnc, V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG, &frameTag) != 0) {
714         ALOGE("%s: Failed to g_ctrl", __func__);
715         ret = VIDEO_ERROR_APIFAIL;
716         goto EXIT;
717     }
718 #endif
719 EXIT:
720     return frameTag;
721 }
722
723 /*
724  * [Encoder OPS] Set Frame Type
725  */
726 static ExynosVideoErrorType MFC_Encoder_Set_FrameType(
727     void                    *pHandle,
728     ExynosVideoFrameType     frameType)
729 {
730     ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
731     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
732
733     if (pCtx == NULL) {
734         ALOGE("%s: Video context info must be supplied", __func__);
735         ret = VIDEO_ERROR_BADPARAM;
736         goto EXIT;
737     }
738
739
740     if (exynos_v4l2_s_ctrl(pCtx->hEnc, V4L2_CID_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE, frameType) != 0) {
741         ALOGE("%s: Failed to s_ctrl", __func__);
742         ret = VIDEO_ERROR_APIFAIL;
743         goto EXIT;
744     }
745
746
747 EXIT:
748     return ret;
749 }
750
751 /*
752  * [Encoder OPS] Set Frame Rate
753  */
754 static ExynosVideoErrorType MFC_Encoder_Set_FrameRate(
755     void   *pHandle,
756     int     frameRate)
757 {
758     ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
759     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
760
761     if (pCtx == NULL) {
762         ALOGE("%s: Video context info must be supplied", __func__);
763         ret = VIDEO_ERROR_BADPARAM;
764         goto EXIT;
765     }
766 #ifdef V4L2_CID_MPEG_MFC51_VIDEO_FRAME_RATE_CH
767     if (exynos_v4l2_s_ctrl(pCtx->hEnc, V4L2_CID_MPEG_MFC51_VIDEO_FRAME_RATE_CH, frameRate) != 0) {
768         ALOGE("%s: Failed to s_ctrl", __func__);
769         ret = VIDEO_ERROR_APIFAIL;
770         goto EXIT;
771     }
772 #endif
773
774 EXIT:
775     return ret;
776 }
777
778 /*
779  * [Encoder OPS] Set Bit Rate
780  */
781 static ExynosVideoErrorType MFC_Encoder_Set_BitRate(
782     void   *pHandle,
783     int     bitRate)
784 {
785     ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
786     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
787
788     if (pCtx == NULL) {
789         ALOGE("%s: Video context info must be supplied", __func__);
790         ret = VIDEO_ERROR_BADPARAM;
791         goto EXIT;
792     }
793 #ifdef V4L2_CID_MPEG_MFC51_VIDEO_BIT_RATE_CH
794     if (exynos_v4l2_s_ctrl(pCtx->hEnc, V4L2_CID_MPEG_MFC51_VIDEO_BIT_RATE_CH, bitRate) != 0) {
795         ALOGE("%s: Failed to s_ctrl", __func__);
796         ret = VIDEO_ERROR_APIFAIL;
797         goto EXIT;
798     }
799 #endif
800 EXIT:
801     return ret;
802 }
803
804 /*
805  * [Encoder OPS] Set Frame Skip
806  */
807 static ExynosVideoErrorType MFC_Encoder_Set_FrameSkip(
808     void   *pHandle,
809     int     frameSkip)
810 {
811     ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
812     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
813
814     if (pCtx == NULL) {
815         ALOGE("%s: Video context info must be supplied", __func__);
816         ret = VIDEO_ERROR_BADPARAM;
817         goto EXIT;
818     }
819
820     if (exynos_v4l2_s_ctrl(pCtx->hEnc, V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE, frameSkip) != 0) {
821         ALOGE("%s: Failed to s_ctrl", __func__);
822         ret = VIDEO_ERROR_APIFAIL;
823         goto EXIT;
824     }
825
826 EXIT:
827     return ret;
828 }
829
830 /*
831  * [Encoder OPS] Set IDR Period
832  */
833 static ExynosVideoErrorType MFC_Encoder_Set_IDRPeriod(
834     void   *pHandle,
835     int     IDRPeriod)
836 {
837     ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
838     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
839
840     if (pCtx == NULL) {
841         ALOGE("%s: Video context info must be supplied", __func__);
842         ret = VIDEO_ERROR_BADPARAM;
843         goto EXIT;
844     }
845
846     if (exynos_v4l2_s_ctrl(pCtx->hEnc, V4L2_CID_MPEG_VIDEO_H264_I_PERIOD, IDRPeriod) != 0) {
847         ALOGE("%s: Failed to s_ctrl", __func__);
848         ret = VIDEO_ERROR_APIFAIL;
849         goto EXIT;
850     }
851
852 EXIT:
853     return ret;
854 }
855
856 /*
857  * [Encoder OPS] Enable Prepend SPS and PPS to every IDR Frames
858  */
859 static ExynosVideoErrorType MFC_Encoder_Enable_PrependSpsPpsToIdr(void *pHandle)
860 {
861     ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
862     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
863
864     if (pCtx == NULL) {
865         ALOGE("%s: Video context info must be supplied", __func__);
866         ret = VIDEO_ERROR_BADPARAM;
867         goto EXIT;
868     }
869 #ifdef V4L2_CID_MPEG_VIDEO_H264_PREPEND_SPSPPS_TO_IDR
870     if (exynos_v4l2_s_ctrl(pCtx->hEnc, V4L2_CID_MPEG_VIDEO_H264_PREPEND_SPSPPS_TO_IDR, 1) != 0) {
871         ALOGE("%s: Failed to s_ctrl", __func__);
872         ret = VIDEO_ERROR_APIFAIL;
873         goto EXIT;
874     }
875 #endif
876 EXIT:
877     return ret;
878 }
879
880 /*
881  * [Encoder Buffer OPS] Enable Cacheable (Input)
882  */
883 static ExynosVideoErrorType MFC_Encoder_Enable_Cacheable_Inbuf(void *pHandle)
884 {
885     ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
886     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
887
888     if (pCtx == NULL) {
889         ALOGE("%s: Video context info must be supplied", __func__);
890         ret = VIDEO_ERROR_BADPARAM;
891         goto EXIT;
892     }
893 #ifdef V4L2_CID_CACHEABLE
894     if (exynos_v4l2_s_ctrl(pCtx->hEnc, V4L2_CID_CACHEABLE, 2) != 0) {
895         ALOGE("%s: Failed V4L2_CID_CACHEABLE", __func__);
896         ret = VIDEO_ERROR_APIFAIL;
897         goto EXIT;
898     }
899 #endif
900 EXIT:
901     return ret;
902 }
903
904 /*
905  * [Encoder Buffer OPS] Enable Cacheable (Output)
906  */
907 static ExynosVideoErrorType MFC_Encoder_Enable_Cacheable_Outbuf(void *pHandle)
908 {
909     ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
910     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
911
912     if (pCtx == NULL) {
913         ALOGE("%s: Video context info must be supplied", __func__);
914         ret = VIDEO_ERROR_BADPARAM;
915         goto EXIT;
916     }
917 #ifdef V4L2_CID_CACHEABLE
918     if (exynos_v4l2_s_ctrl(pCtx->hEnc, V4L2_CID_CACHEABLE, 1) != 0) {
919         ALOGE("%s: Failed V4L2_CID_CACHEABLE", __func__);
920         ret = VIDEO_ERROR_APIFAIL;
921         goto EXIT;
922     }
923 #endif
924 EXIT:
925     return ret;
926 }
927
928 /*
929  * [Encoder Buffer OPS] Set Shareable Buffer (Input)
930  */
931 static ExynosVideoErrorType MFC_Encoder_Set_Shareable_Inbuf(void *pHandle)
932 {
933     ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
934     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
935
936     if (pCtx == NULL) {
937         ALOGE("%s: Video context info must be supplied", __func__);
938         ret = VIDEO_ERROR_BADPARAM;
939         goto EXIT;
940     }
941
942     pCtx->bShareInbuf = VIDEO_TRUE;
943
944 EXIT:
945     return ret;
946 }
947
948 /*
949  * [Encoder Buffer OPS] Set Shareable Buffer (Output)
950  */
951 static ExynosVideoErrorType MFC_Encoder_Set_Shareable_Outbuf(void *pHandle)
952 {
953     ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
954     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
955
956     if (pCtx == NULL) {
957         ALOGE("%s: Video context info must be supplied", __func__);
958         ret = VIDEO_ERROR_BADPARAM;
959         goto EXIT;
960     }
961
962     pCtx->bShareOutbuf = VIDEO_TRUE;
963
964 EXIT:
965     return ret;
966 }
967
968 /*
969  * [Encoder Buffer OPS] Get Buffer (Input)
970  */
971 static ExynosVideoErrorType MFC_Encoder_Get_Buffer_Inbuf(
972     void               *pHandle,
973     int                 nIndex,
974     ExynosVideoBuffer **pBuffer)
975 {
976     ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
977     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
978
979     if (pCtx == NULL) {
980         ALOGE("%s: Video context info must be supplied", __func__);
981         *pBuffer = NULL;
982         ret = VIDEO_ERROR_NOBUFFERS;
983         goto EXIT;
984     }
985
986     if (pCtx->nInbufs <= nIndex) {
987         *pBuffer = NULL;
988         ret = VIDEO_ERROR_BADPARAM;
989         goto EXIT;
990     }
991
992     *pBuffer = (ExynosVideoBuffer *)&pCtx->pInbuf[nIndex];
993
994 EXIT:
995     return ret;
996 }
997
998 /*
999  * [Encoder Buffer OPS] Get Buffer (Output)
1000  */
1001 static ExynosVideoErrorType MFC_Encoder_Get_Buffer_Outbuf(
1002     void               *pHandle,
1003     int                 nIndex,
1004     ExynosVideoBuffer **pBuffer)
1005 {
1006     ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
1007     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
1008
1009     if (pCtx == NULL) {
1010         ALOGE("%s: Video context info must be supplied", __func__);
1011         *pBuffer = NULL;
1012         ret = VIDEO_ERROR_NOBUFFERS;
1013         goto EXIT;
1014     }
1015
1016     if (pCtx->nOutbufs <= nIndex) {
1017         *pBuffer = NULL;
1018         ret = VIDEO_ERROR_BADPARAM;
1019         goto EXIT;
1020     }
1021
1022     *pBuffer = (ExynosVideoBuffer *)&pCtx->pOutbuf[nIndex];
1023
1024 EXIT:
1025     return ret;
1026 }
1027
1028 /*
1029  * [Encoder Buffer OPS] Set Geometry (Src)
1030  */
1031 static ExynosVideoErrorType MFC_Encoder_Set_Geometry_Inbuf(
1032     void                *pHandle,
1033     ExynosVideoGeometry *bufferConf)
1034 {
1035     ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
1036     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
1037
1038     struct v4l2_format fmt;
1039
1040     if (pCtx == NULL) {
1041         ALOGE("%s: Video context info must be supplied", __func__);
1042         ret = VIDEO_ERROR_BADPARAM;
1043         goto EXIT;
1044     }
1045
1046     if (bufferConf == NULL) {
1047         ALOGE("%s: Buffer geometry must be supplied", __func__);
1048         ret = VIDEO_ERROR_BADPARAM;
1049         goto EXIT;
1050     }
1051
1052     memset(&fmt, 0, sizeof(fmt));
1053
1054     fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1055     fmt.fmt.pix_mp.pixelformat = __ColorFormatType_To_V4L2PixelFormat(bufferConf->eColorFormat);
1056     fmt.fmt.pix_mp.width = bufferConf->nFrameWidth;
1057     fmt.fmt.pix_mp.height = bufferConf->nFrameHeight;
1058     fmt.fmt.pix_mp.num_planes = VIDEO_ENCODER_INBUF_PLANES;
1059
1060
1061     if (exynos_v4l2_s_fmt(pCtx->hEnc, &fmt) != 0) {
1062         ALOGE("%s: Failed to s_fmt", __func__);
1063         ret = VIDEO_ERROR_APIFAIL;
1064         goto EXIT;
1065     }
1066
1067     memcpy(&pCtx->inbufGeometry, bufferConf, sizeof(pCtx->inbufGeometry));
1068
1069 EXIT:
1070     return ret;
1071 }
1072
1073 /*
1074  * [Encoder Buffer OPS] Get Geometry (Src)
1075  */
1076 static ExynosVideoErrorType MFC_Encoder_Get_Geometry_Inbuf(
1077     void                *pHandle,
1078     ExynosVideoGeometry *bufferConf)
1079 {
1080     ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
1081     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
1082
1083     struct v4l2_format fmt;
1084
1085     if (pCtx == NULL) {
1086         ALOGE("%s: Video context info must be supplied", __func__);
1087         ret = VIDEO_ERROR_BADPARAM;
1088         goto EXIT;
1089     }
1090
1091     if (bufferConf == NULL) {
1092         ALOGE("%s: Buffer geometry must be supplied", __func__);
1093         ret = VIDEO_ERROR_BADPARAM;
1094         goto EXIT;
1095     }
1096
1097     memset(&fmt, 0, sizeof(fmt));
1098
1099     fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1100     if (exynos_v4l2_g_fmt(pCtx->hEnc, &fmt) != 0) {
1101         ALOGE("%s: Failed to g_fmt", __func__);
1102         ret = VIDEO_ERROR_APIFAIL;
1103         goto EXIT;
1104     }
1105
1106     bufferConf->nFrameHeight = fmt.fmt.pix_mp.width;
1107     bufferConf->nFrameHeight = fmt.fmt.pix_mp.height;
1108     bufferConf->nSizeImage = fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
1109
1110 EXIT:
1111     return ret;
1112 }
1113
1114 /*
1115  * [Encoder Buffer OPS] Set Geometry (Dst)
1116  */
1117 static ExynosVideoErrorType MFC_Encoder_Set_Geometry_Outbuf(
1118     void                *pHandle,
1119     ExynosVideoGeometry *bufferConf)
1120 {
1121     ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
1122     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
1123
1124     struct v4l2_format fmt;
1125
1126     if (pCtx == NULL) {
1127         ALOGE("%s: Video context info must be supplied", __func__);
1128         ret = VIDEO_ERROR_BADPARAM;
1129         goto EXIT;
1130     }
1131
1132     if (bufferConf == NULL) {
1133         ALOGE("%s: Buffer geometry must be supplied", __func__);
1134         ret = VIDEO_ERROR_BADPARAM;
1135         goto EXIT;
1136     }
1137
1138     memset(&fmt, 0, sizeof(fmt));
1139
1140     fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1141     fmt.fmt.pix_mp.pixelformat = __CodingType_To_V4L2PixelFormat(bufferConf->eCompressionFormat);
1142     fmt.fmt.pix_mp.plane_fmt[0].sizeimage = bufferConf->nSizeImage;
1143
1144     if (exynos_v4l2_s_fmt(pCtx->hEnc, &fmt) != 0) {
1145         ALOGE("%s: Failed to s_fmt", __func__);
1146         ret = VIDEO_ERROR_APIFAIL;
1147         goto EXIT;
1148     }
1149
1150     memcpy(&pCtx->outbufGeometry, bufferConf, sizeof(pCtx->outbufGeometry));
1151
1152 EXIT:
1153     return ret;
1154 }
1155
1156 /*
1157  * [Encoder Buffer OPS] Get Geometry (Dst)
1158  */
1159 static ExynosVideoErrorType MFC_Encoder_Get_Geometry_Outbuf(
1160     void                *pHandle,
1161     ExynosVideoGeometry *bufferConf)
1162 {
1163     ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
1164     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
1165
1166     struct v4l2_format fmt;
1167
1168     if (pCtx == NULL) {
1169         ALOGE("%s: Video context info must be supplied", __func__);
1170         ret = VIDEO_ERROR_BADPARAM;
1171         goto EXIT;
1172     }
1173
1174     if (bufferConf == NULL) {
1175         ALOGE("%s: Buffer geometry must be supplied", __func__);
1176         ret = VIDEO_ERROR_BADPARAM;
1177         goto EXIT;
1178     }
1179
1180     memset(&fmt, 0, sizeof(fmt));
1181
1182     fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1183     if (exynos_v4l2_g_fmt(pCtx->hEnc, &fmt) != 0) {
1184         ALOGE("%s: Failed to g_fmt", __func__);
1185         ret = VIDEO_ERROR_APIFAIL;
1186         goto EXIT;
1187     }
1188
1189
1190     bufferConf->nSizeImage = fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
1191
1192 EXIT:
1193     return ret;
1194 }
1195
1196 /*
1197  * [Encoder Buffer OPS] Setup (Src)
1198  */
1199 static ExynosVideoErrorType MFC_Encoder_Setup_Inbuf(
1200     void           *pHandle,
1201     unsigned int    nBufferCount)
1202 {
1203     ExynosVideoEncContext *pCtx         = (ExynosVideoEncContext *)pHandle;
1204     ExynosVideoPlane      *pVideoPlane  = NULL;
1205     ExynosVideoErrorType   ret          = VIDEO_ERROR_NONE;
1206
1207     struct v4l2_requestbuffers req;
1208     struct v4l2_buffer buf;
1209     struct v4l2_plane planes[VIDEO_ENCODER_INBUF_PLANES];
1210     int i, j;
1211
1212     if (pCtx == NULL) {
1213         ALOGE("%s: Video context info must be supplied", __func__);
1214         ret = VIDEO_ERROR_BADPARAM;
1215         goto EXIT;
1216     }
1217
1218     if (nBufferCount == 0) {
1219         ALOGE("%s: Buffer count must be greater than 0", __func__);
1220         ret = VIDEO_ERROR_BADPARAM;
1221         goto EXIT;
1222     }
1223
1224     memset(&req, 0, sizeof(req));
1225
1226     req.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1227     req.count = nBufferCount;
1228
1229     if (pCtx->bShareInbuf == VIDEO_TRUE)
1230         req.memory = pCtx->nMemoryType;
1231     else
1232         req.memory = V4L2_MEMORY_MMAP;
1233
1234     if (exynos_v4l2_reqbufs(pCtx->hEnc, &req) != 0) {
1235         ALOGE("Failed to require buffer");
1236         ret = VIDEO_ERROR_APIFAIL;
1237         goto EXIT;
1238     }
1239
1240     pCtx->nInbufs = (int)req.count;
1241
1242     pCtx->pInbuf = malloc(sizeof(*pCtx->pInbuf) * pCtx->nInbufs);
1243     if (pCtx->pInbuf == NULL) {
1244         ALOGE("%s: Failed to allocate input buffer context", __func__);
1245         ret = VIDEO_ERROR_NOMEM;
1246         goto EXIT;
1247     }
1248     memset(pCtx->pInbuf, 0, sizeof(*pCtx->pInbuf) * pCtx->nInbufs);
1249
1250     memset(&buf, 0, sizeof(buf));
1251
1252     if (pCtx->bShareInbuf == VIDEO_FALSE) {
1253         buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1254         buf.memory = V4L2_MEMORY_MMAP;
1255         buf.m.planes = planes;
1256         buf.length = VIDEO_ENCODER_INBUF_PLANES;
1257
1258         for (i = 0; i < pCtx->nInbufs; i++) {
1259             buf.index = i;
1260             if (exynos_v4l2_querybuf(pCtx->hEnc, &buf) != 0) {
1261                 ALOGE("%s: Failed to querybuf", __func__);
1262                 ret = VIDEO_ERROR_APIFAIL;
1263                 goto EXIT;
1264             }
1265
1266             for (j = 0; j < VIDEO_ENCODER_INBUF_PLANES; j++) {
1267                 pVideoPlane = &pCtx->pInbuf[i].planes[j];
1268                 pVideoPlane->addr = mmap(NULL,
1269                         buf.m.planes[j].length, PROT_READ | PROT_WRITE,
1270                         MAP_SHARED, pCtx->hEnc, buf.m.planes[j].m.mem_offset);
1271
1272                 if (pVideoPlane->addr == MAP_FAILED) {
1273                     ALOGE("%s: Failed to map", __func__);
1274                     ret = VIDEO_ERROR_MAPFAIL;
1275                     goto EXIT;
1276                 }
1277
1278                 pVideoPlane->allocSize = buf.m.planes[j].length;
1279                 pVideoPlane->dataSize = 0;
1280             }
1281
1282             pCtx->pInbuf[i].pGeometry = &pCtx->inbufGeometry;
1283             pCtx->pInbuf[i].bQueued = VIDEO_FALSE;
1284             pCtx->pInbuf[i].bRegistered = VIDEO_TRUE;
1285
1286         }
1287     } else {
1288         for (i = 0; i < pCtx->nInbufs; i++) {
1289             pCtx->pInbuf[i].pGeometry = &pCtx->inbufGeometry;
1290             pCtx->pInbuf[i].bQueued = VIDEO_FALSE;
1291             pCtx->pInbuf[i].bRegistered = VIDEO_FALSE;
1292         }
1293     }
1294
1295     return ret;
1296
1297 EXIT:
1298     if ((pCtx != NULL) && (pCtx->pInbuf != NULL)) {
1299         if (pCtx->bShareInbuf == VIDEO_FALSE) {
1300             for (i = 0; i < pCtx->nInbufs; i++) {
1301                 for (j = 0; j < VIDEO_ENCODER_INBUF_PLANES; j++) {
1302                     pVideoPlane = &pCtx->pInbuf[i].planes[j];
1303                     if (pVideoPlane->addr == MAP_FAILED) {
1304                         pVideoPlane->addr = NULL;
1305                         break;
1306                     }
1307
1308                     munmap(pVideoPlane->addr, pVideoPlane->allocSize);
1309                 }
1310             }
1311         }
1312
1313         free(pCtx->pInbuf);
1314     }
1315
1316     return ret;
1317 }
1318
1319 /*
1320  * [Encoder Buffer OPS] Setup (Dst)
1321  */
1322 static ExynosVideoErrorType MFC_Encoder_Setup_Outbuf(
1323     void           *pHandle,
1324     unsigned int    nBufferCount)
1325 {
1326     ExynosVideoEncContext *pCtx         = (ExynosVideoEncContext *)pHandle;
1327     ExynosVideoPlane      *pVideoPlane  = NULL;
1328     ExynosVideoErrorType   ret          = VIDEO_ERROR_NONE;
1329
1330     struct v4l2_requestbuffers req;
1331     struct v4l2_buffer buf;
1332     struct v4l2_plane planes[VIDEO_ENCODER_OUTBUF_PLANES];
1333     int i, j;
1334
1335     if (pCtx == NULL) {
1336         ALOGE("%s: Video context info must be supplied", __func__);
1337         ret = VIDEO_ERROR_BADPARAM;
1338         goto EXIT;
1339     }
1340
1341     if (nBufferCount == 0) {
1342         ALOGE("%s: Buffer count must be greater than 0", __func__);
1343         ret = VIDEO_ERROR_BADPARAM;
1344         goto EXIT;
1345     }
1346
1347     memset(&req, 0, sizeof(req));
1348
1349     req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1350     req.count = nBufferCount;
1351
1352     if (pCtx->bShareOutbuf == VIDEO_TRUE)
1353         req.memory = pCtx->nMemoryType;
1354     else
1355         req.memory = V4L2_MEMORY_MMAP;
1356
1357     if (exynos_v4l2_reqbufs(pCtx->hEnc, &req) != 0) {
1358         ALOGE("%s: Failed to reqbuf", __func__);
1359         ret = VIDEO_ERROR_APIFAIL;
1360         goto EXIT;
1361     }
1362
1363     pCtx->nOutbufs = req.count;
1364
1365     pCtx->pOutbuf = malloc(sizeof(*pCtx->pOutbuf) * pCtx->nOutbufs);
1366     if (pCtx->pOutbuf == NULL) {
1367         ALOGE("%s: Failed to allocate output buffer context", __func__);
1368         ret = VIDEO_ERROR_NOMEM;
1369         goto EXIT;
1370     }
1371     memset(pCtx->pOutbuf, 0, sizeof(*pCtx->pOutbuf) * pCtx->nOutbufs);
1372
1373     memset(&buf, 0, sizeof(buf));
1374
1375     if (pCtx->bShareOutbuf == VIDEO_FALSE) {
1376         buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1377         buf.memory = V4L2_MEMORY_MMAP;
1378         buf.m.planes = planes;
1379         buf.length = VIDEO_ENCODER_OUTBUF_PLANES;
1380
1381         for (i = 0; i < pCtx->nOutbufs; i++) {
1382             buf.index = i;
1383             if (exynos_v4l2_querybuf(pCtx->hEnc, &buf) != 0) {
1384                 ALOGE("%s: Failed to querybuf", __func__);
1385                 ret = VIDEO_ERROR_APIFAIL;
1386                 goto EXIT;
1387             }
1388
1389             for (j = 0; j < VIDEO_ENCODER_OUTBUF_PLANES; j++) {
1390                 pVideoPlane = &pCtx->pOutbuf[i].planes[j];
1391                 pVideoPlane->addr = mmap(NULL,
1392                         buf.m.planes[j].length, PROT_READ | PROT_WRITE,
1393                         MAP_SHARED, pCtx->hEnc, buf.m.planes[j].m.mem_offset);
1394
1395                 if (pVideoPlane->addr == MAP_FAILED) {
1396                     ALOGE("%s: Failed to map", __func__);
1397                     ret = VIDEO_ERROR_MAPFAIL;
1398                     goto EXIT;
1399                 }
1400
1401                 pVideoPlane->allocSize = buf.m.planes[j].length;
1402                 pVideoPlane->dataSize = 0;
1403             }
1404
1405             pCtx->pOutbuf[i].pGeometry = &pCtx->outbufGeometry;
1406             pCtx->pOutbuf[i].bQueued = VIDEO_FALSE;
1407             pCtx->pOutbuf[i].bRegistered = VIDEO_TRUE;
1408         }
1409     } else {
1410         for (i = 0; i < pCtx->nOutbufs; i++ ) {
1411             pCtx->pOutbuf[i].pGeometry = &pCtx->outbufGeometry;
1412             pCtx->pOutbuf[i].bQueued = VIDEO_FALSE;
1413             pCtx->pOutbuf[i].bRegistered = VIDEO_FALSE;
1414         }
1415     }
1416
1417     return ret;
1418
1419 EXIT:
1420     if ((pCtx != NULL) && (pCtx->pOutbuf != NULL)) {
1421         if (pCtx->bShareOutbuf == VIDEO_FALSE) {
1422             for (i = 0; i < pCtx->nOutbufs; i++) {
1423                 for (j = 0; j < VIDEO_ENCODER_OUTBUF_PLANES; j++) {
1424                     pVideoPlane = &pCtx->pOutbuf[i].planes[j];
1425                     if (pVideoPlane->addr == MAP_FAILED) {
1426                         pVideoPlane->addr = NULL;
1427                         break;
1428                     }
1429
1430                     munmap(pVideoPlane->addr, pVideoPlane->allocSize);
1431                 }
1432             }
1433         }
1434
1435         free(pCtx->pOutbuf);
1436     }
1437
1438     return ret;
1439 }
1440
1441 /*
1442  * [Encoder Buffer OPS] Run (src)
1443  */
1444 static ExynosVideoErrorType MFC_Encoder_Run_Inbuf(void *pHandle)
1445 {
1446     ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
1447     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
1448
1449     if (pCtx == NULL) {
1450         ALOGE("%s: Video context info must be supplied", __func__);
1451         ret = VIDEO_ERROR_BADPARAM;
1452         goto EXIT;
1453     }
1454
1455     if (pCtx->bStreamonInbuf == VIDEO_FALSE) {
1456         if (exynos_v4l2_streamon(pCtx->hEnc, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) != 0) {
1457             ALOGE("%s: Failed to streamon for input buffer", __func__);
1458             ret = VIDEO_ERROR_APIFAIL;
1459             goto EXIT;
1460         }
1461         pCtx->bStreamonInbuf = VIDEO_TRUE;
1462     }
1463
1464 EXIT:
1465     return ret;
1466 }
1467
1468 /*
1469  * [Encoder Buffer OPS] Run (Dst)
1470  */
1471 static ExynosVideoErrorType MFC_Encoder_Run_Outbuf(void *pHandle)
1472 {
1473     ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
1474     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
1475
1476     if (pCtx == NULL) {
1477         ALOGE("%s: Video context info must be supplied", __func__);
1478         ret = VIDEO_ERROR_BADPARAM;
1479         goto EXIT;
1480     }
1481
1482     if (pCtx->bStreamonOutbuf == VIDEO_FALSE) {
1483         if (exynos_v4l2_streamon(pCtx->hEnc, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) != 0) {
1484             ALOGE("%s: Failed to streamon for output buffer", __func__);
1485             ret = VIDEO_ERROR_APIFAIL;
1486             goto EXIT;
1487         }
1488         pCtx->bStreamonOutbuf = VIDEO_TRUE;
1489     }
1490
1491 EXIT:
1492     return ret;
1493 }
1494
1495 /*
1496  * [Encoder Buffer OPS] Stop (Src)
1497  */
1498 static ExynosVideoErrorType MFC_Encoder_Stop_Inbuf(void *pHandle)
1499 {
1500     ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
1501     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
1502     int i = 0;
1503
1504     if (pCtx == NULL) {
1505         ALOGE("%s: Video context info must be supplied", __func__);
1506         ret = VIDEO_ERROR_BADPARAM;
1507         goto EXIT;
1508     }
1509
1510     if (pCtx->bStreamonInbuf == VIDEO_TRUE) {
1511         if (exynos_v4l2_streamoff(pCtx->hEnc, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) != 0) {
1512             ALOGE("%s: Failed to streamoff for input buffer", __func__);
1513             ret = VIDEO_ERROR_APIFAIL;
1514             goto EXIT;
1515         }
1516         pCtx->bStreamonInbuf = VIDEO_FALSE;
1517     }
1518
1519     for (i = 0; i <  pCtx->nInbufs; i++) {
1520         pCtx->pInbuf[i].bQueued = VIDEO_FALSE;
1521     }
1522
1523 EXIT:
1524     return ret;
1525 }
1526
1527 /*
1528  * [Encoder Buffer OPS] Stop (Dst)
1529  */
1530 static ExynosVideoErrorType MFC_Encoder_Stop_Outbuf(void *pHandle)
1531 {
1532     ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
1533     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
1534     int i = 0;
1535
1536     if (pCtx == NULL) {
1537         ALOGE("%s: Video context info must be supplied", __func__);
1538         ret = VIDEO_ERROR_BADPARAM;
1539         goto EXIT;
1540     }
1541
1542     if (pCtx->bStreamonOutbuf == VIDEO_TRUE) {
1543         if (exynos_v4l2_streamoff(pCtx->hEnc, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) != 0) {
1544             ALOGE("%s: Failed to streamoff for output buffer", __func__);
1545             ret = VIDEO_ERROR_APIFAIL;
1546             goto EXIT;
1547         }
1548         pCtx->bStreamonOutbuf = VIDEO_FALSE;
1549     }
1550
1551     for (i = 0; i < pCtx->nOutbufs; i++) {
1552         pCtx->pOutbuf[i].bQueued = VIDEO_FALSE;
1553     }
1554
1555 EXIT:
1556     return ret;
1557 }
1558
1559 /*
1560  * [Encoder Buffer OPS] Wait (Src)
1561  */
1562 static ExynosVideoErrorType MFC_Encoder_Wait_Inbuf(void *pHandle)
1563 {
1564     ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
1565     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
1566
1567     struct pollfd poll_events;
1568     int poll_state;
1569
1570     if (pCtx == NULL) {
1571         ALOGE("%s: Video context info must be supplied", __func__);
1572         ret = VIDEO_ERROR_BADPARAM;
1573         goto EXIT;
1574     }
1575
1576     poll_events.fd = pCtx->hEnc;
1577     poll_events.events = POLLOUT | POLLERR;
1578     poll_events.revents = 0;
1579
1580     do {
1581         poll_state = poll((struct pollfd*)&poll_events, 1, VIDEO_ENCODER_POLL_TIMEOUT);
1582         if (poll_state > 0) {
1583             if (poll_events.revents & POLLOUT) {
1584                 break;
1585             } else {
1586                 ALOGE("%s: Poll return error", __func__);
1587                 ret = VIDEO_ERROR_POLL;
1588                 break;
1589             }
1590         } else if (poll_state < 0) {
1591             ALOGE("%s: Poll state error", __func__);
1592             ret = VIDEO_ERROR_POLL;
1593             break;
1594         }
1595     } while (poll_state == 0);
1596
1597 EXIT:
1598     return ret;
1599 }
1600
1601 /*
1602  * [Encoder Buffer OPS] Wait (Dst)
1603  */
1604 static ExynosVideoErrorType MFC_Encoder_Wait_Outbuf(void *pHandle)
1605 {
1606     ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
1607     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
1608
1609     struct pollfd poll_events;
1610     int poll_state;
1611     int bframe_count = 0; // FIXME
1612
1613     if (pCtx == NULL) {
1614         ALOGE("%s: Video context info must be supplied", __func__);
1615         ret = VIDEO_ERROR_BADPARAM;
1616         goto EXIT;
1617     }
1618
1619     poll_events.fd = pCtx->hEnc;
1620     poll_events.events = POLLIN | POLLERR;
1621     poll_events.revents = 0;
1622
1623     do {
1624         poll_state = poll((struct pollfd*)&poll_events, 1, VIDEO_ENCODER_POLL_TIMEOUT);
1625         if (poll_state > 0) {
1626             if (poll_events.revents & POLLIN) {
1627                 break;
1628             } else {
1629                 ALOGE("%s: Poll return error", __func__);
1630                 ret = VIDEO_ERROR_POLL;
1631                 break;
1632             }
1633         } else if (poll_state < 0) {
1634             ALOGE("%s: Poll state error", __func__);
1635             ret = VIDEO_ERROR_POLL;
1636             break;
1637         } else {
1638             bframe_count++; // FIXME
1639         }
1640     } while (poll_state == 0 && bframe_count < 5); // FIXME
1641
1642 EXIT:
1643     return ret;
1644 }
1645
1646 static ExynosVideoErrorType MFC_Encoder_Register_Inbuf(
1647     void             *pHandle,
1648     ExynosVideoPlane *planes,
1649     int               nPlanes)
1650 {
1651     ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
1652     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
1653     int nIndex;
1654
1655     if ((pCtx == NULL) || (planes == NULL) || (nPlanes != VIDEO_ENCODER_INBUF_PLANES)) {
1656         ALOGE("%s: input params must be supplied", __func__);
1657         ret = VIDEO_ERROR_BADPARAM;
1658         goto EXIT;
1659     }
1660
1661     for (nIndex = 0; nIndex < pCtx->nInbufs; nIndex++) {
1662         if (pCtx->pInbuf[nIndex].bRegistered == VIDEO_FALSE) {
1663             int plane;
1664             for (plane = 0; plane < nPlanes; plane++) {
1665                 pCtx->pInbuf[nIndex].planes[plane].addr = planes[plane].addr;
1666                 pCtx->pInbuf[nIndex].planes[plane].allocSize = planes[plane].allocSize;
1667                 pCtx->pInbuf[nIndex].planes[plane].fd = planes[plane].fd;
1668                 ALOGV("%s: addr = 0x%x", __func__, pCtx->pInbuf[nIndex].planes[plane].addr);
1669             }
1670             pCtx->pInbuf[nIndex].bRegistered = VIDEO_TRUE;
1671             break;
1672         }
1673     }
1674
1675     if (nIndex == pCtx->nInbufs) {
1676         ALOGE("%s: can not find non-registered input buffer", __func__);
1677         ret = VIDEO_ERROR_NOBUFFERS;
1678     }
1679
1680 EXIT:
1681     return ret;
1682 }
1683
1684 static ExynosVideoErrorType MFC_Encoder_Register_Outbuf(
1685     void             *pHandle,
1686     ExynosVideoPlane *planes,
1687     int               nPlanes)
1688 {
1689     ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
1690     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
1691     int nIndex;
1692
1693     if ((pCtx == NULL) || (planes == NULL) || (nPlanes != VIDEO_ENCODER_OUTBUF_PLANES)) {
1694         ALOGE("%s: params must be supplied", __func__);
1695         ret = VIDEO_ERROR_BADPARAM;
1696         goto EXIT;
1697     }
1698
1699     for (nIndex = 0; nIndex < pCtx->nOutbufs; nIndex++) {
1700         if (pCtx->pOutbuf[nIndex].bRegistered == VIDEO_FALSE) {
1701             int plane;
1702             for (plane = 0; plane < nPlanes; plane++) {
1703                 pCtx->pOutbuf[nIndex].planes[plane].addr = planes[plane].addr;
1704                 pCtx->pOutbuf[nIndex].planes[plane].allocSize = planes[plane].allocSize;
1705                 pCtx->pOutbuf[nIndex].planes[plane].fd = planes[plane].fd;
1706             }
1707             pCtx->pOutbuf[nIndex].bRegistered = VIDEO_TRUE;
1708             break;
1709         }
1710     }
1711
1712     if (nIndex == pCtx->nOutbufs) {
1713         ALOGE("%s: can not find non-registered output buffer", __func__);
1714         ret = VIDEO_ERROR_NOBUFFERS;
1715     }
1716
1717 EXIT:
1718     return ret;
1719 }
1720
1721 static ExynosVideoErrorType MFC_Encoder_Clear_RegisteredBuffer_Inbuf(void *pHandle)
1722 {
1723     ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
1724     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
1725     int nIndex = -1;
1726
1727     if (pCtx == NULL) {
1728         ALOGE("%s: Video context info must be supplied", __func__);
1729         ret = VIDEO_ERROR_BADPARAM;
1730         goto EXIT;
1731     }
1732
1733     for (nIndex = 0; nIndex < pCtx->nInbufs; nIndex++) {
1734             pCtx->pInbuf[nIndex].planes[0].addr = NULL;
1735             pCtx->pInbuf[nIndex].bRegistered = VIDEO_FALSE;
1736     }
1737
1738 EXIT:
1739     return ret;
1740 }
1741
1742 static ExynosVideoErrorType MFC_Encoder_Clear_RegisteredBuffer_Outbuf(void *pHandle)
1743 {
1744     ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
1745     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
1746     int nIndex = -1;
1747
1748     if (pCtx == NULL) {
1749         ALOGE("%s: Video context info must be supplied", __func__);
1750         ret = VIDEO_ERROR_BADPARAM;
1751         goto EXIT;
1752     }
1753
1754     for (nIndex = 0; nIndex < pCtx->nOutbufs; nIndex++) {
1755             pCtx->pOutbuf[nIndex].planes[0].addr = NULL;
1756             pCtx->pOutbuf[nIndex].bRegistered = VIDEO_FALSE;
1757     }
1758
1759 EXIT:
1760     return ret;
1761 }
1762
1763 /*
1764  * [Encoder Buffer OPS] Find (Input)
1765  */
1766 static int MFC_Encoder_Find_Inbuf(
1767     void          *pHandle,
1768     unsigned char *pBuffer)
1769 {
1770     ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
1771     int nIndex = -1;
1772
1773     if (pCtx == NULL) {
1774         ALOGE("%s: Video context info must be supplied", __func__);
1775         goto EXIT;
1776     }
1777
1778     for (nIndex = 0; nIndex < pCtx->nInbufs; nIndex++) {
1779         if (pCtx->pInbuf[nIndex].bQueued == VIDEO_FALSE) {
1780             if ((pBuffer == NULL) ||
1781                 (pCtx->pInbuf[nIndex].planes[0].addr == pBuffer))
1782                 break;
1783         }
1784     }
1785
1786     if (nIndex == pCtx->nInbufs)
1787         nIndex = -1;
1788
1789 EXIT:
1790     return nIndex;
1791 }
1792
1793 /*
1794  * [Encoder Buffer OPS] Find (Output)
1795  */
1796 static int MFC_Encoder_Find_Outbuf(
1797     void          *pHandle,
1798     unsigned char *pBuffer)
1799 {
1800     ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
1801     int nIndex = -1;
1802
1803     if (pCtx == NULL) {
1804         ALOGE("%s: Video context info must be supplied", __func__);
1805         goto EXIT;
1806     }
1807
1808     for (nIndex = 0; nIndex < pCtx->nOutbufs; nIndex++) {
1809         if (pCtx->pOutbuf[nIndex].bQueued == VIDEO_FALSE) {
1810             if ((pBuffer == NULL) ||
1811                 (pCtx->pOutbuf[nIndex].planes[0].addr == pBuffer))
1812                 break;
1813         }
1814     }
1815
1816     if (nIndex == pCtx->nOutbufs)
1817         nIndex = -1;
1818
1819 EXIT:
1820     return nIndex;
1821 }
1822
1823 /*
1824  * [Encoder Buffer OPS] Enqueue (Input)
1825  */
1826 static ExynosVideoErrorType MFC_Encoder_Enqueue_Inbuf(
1827     void          *pHandle,
1828     unsigned char *pBuffer[],
1829     unsigned int   dataSize[],
1830     int            nPlanes,
1831     void          *pPrivate)
1832 {
1833     ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
1834     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
1835     pthread_mutex_t       *pMutex = NULL;
1836
1837     struct v4l2_plane planes[VIDEO_ENCODER_INBUF_PLANES];
1838     struct v4l2_buffer buf;
1839     int index, 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     if (VIDEO_ENCODER_INBUF_PLANES < nPlanes) {
1848         ALOGE("%s: Number of max planes : %d, nPlanes : %d", __func__,
1849                                     VIDEO_ENCODER_INBUF_PLANES, nPlanes);
1850         ret = VIDEO_ERROR_BADPARAM;
1851         goto EXIT;
1852     }
1853
1854     memset(&planes,0,sizeof(planes));
1855     memset(&buf, 0, sizeof(buf));
1856
1857     buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1858     buf.m.planes = planes;
1859     buf.length = VIDEO_ENCODER_INBUF_PLANES;
1860
1861     pMutex = (pthread_mutex_t*)pCtx->pInMutex;
1862     pthread_mutex_lock(pMutex);
1863     index = MFC_Encoder_Find_Inbuf(pCtx, pBuffer[0]);
1864     if (index == -1) {
1865         pthread_mutex_unlock(pMutex);
1866         ALOGE("%s: Failed to get index", __func__);
1867         ret = VIDEO_ERROR_NOBUFFERS;
1868         goto EXIT;
1869     }
1870
1871     buf.index = index;
1872     pCtx->pInbuf[buf.index].bQueued = VIDEO_TRUE;
1873     pthread_mutex_unlock(pMutex);
1874
1875     if (pCtx->bShareInbuf == VIDEO_TRUE) {
1876         buf.memory = pCtx->nMemoryType;
1877
1878         for (i = 0; i < nPlanes; i++) {
1879             /* V4L2_MEMORY_USERPTR */
1880             buf.m.planes[i].m.userptr = (unsigned long)pBuffer[i];
1881             buf.m.planes[i].length = pCtx->pInbuf[index].planes[i].allocSize;
1882             /* V4L2_MEMORY_DMABUF */
1883 #ifdef TIZEN_FEATURE_E3250 /* #ifdef USE_DMA_BUF */
1884             buf.m.planes[i].m.fd = pCtx->pInbuf[buf.index].planes[i].fd;
1885             buf.m.planes[i].length = 0; /* kernel give the length */
1886 #endif
1887             buf.m.planes[i].bytesused = dataSize[i];
1888         }
1889     } else {
1890         buf.memory = V4L2_MEMORY_MMAP;
1891         for (i = 0; i < nPlanes; i++)
1892             buf.m.planes[i].bytesused = dataSize[i];
1893     }
1894
1895         ALOGE("call exynos_v4l2_qbuf(): %d", buf.m.planes[0].m.fd);
1896     if (exynos_v4l2_qbuf(pCtx->hEnc, &buf) != 0) {
1897         ALOGE("%s: Failed to enqueue input buffer", __func__);
1898         pCtx->pInbuf[buf.index].bQueued = VIDEO_FALSE;
1899         ret = VIDEO_ERROR_APIFAIL;
1900         goto EXIT;
1901     }
1902
1903     pCtx->pInbuf[buf.index].pPrivate = pPrivate;
1904
1905 EXIT:
1906     return ret;
1907 }
1908
1909 /*
1910  * [Encoder Buffer OPS] Enqueue (Output)
1911  */
1912 static ExynosVideoErrorType MFC_Encoder_Enqueue_Outbuf(
1913     void          *pHandle,
1914     unsigned char *pBuffer[],
1915     unsigned int   dataSize[],
1916     int            nPlanes,
1917     void          *pPrivate)
1918 {
1919     ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
1920     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
1921     pthread_mutex_t       *pMutex = NULL;
1922
1923     struct v4l2_plane planes[VIDEO_ENCODER_OUTBUF_PLANES];
1924     struct v4l2_buffer buf;
1925     int i, index;
1926
1927     if (pCtx == NULL) {
1928         ALOGE("%s: Video context info must be supplied", __func__);
1929         ret = VIDEO_ERROR_BADPARAM;
1930         goto EXIT;
1931     }
1932
1933     if (VIDEO_ENCODER_OUTBUF_PLANES < nPlanes) {
1934         ALOGE("%s: Number of max planes : %d, nPlanes : %d", __func__,
1935                                     VIDEO_ENCODER_OUTBUF_PLANES, nPlanes);
1936         ret = VIDEO_ERROR_BADPARAM;
1937         goto EXIT;
1938     }
1939
1940     memset(&buf, 0, sizeof(buf));
1941
1942     buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1943     buf.m.planes = planes;
1944     buf.length = VIDEO_ENCODER_OUTBUF_PLANES;
1945
1946     pMutex = (pthread_mutex_t*)pCtx->pOutMutex;
1947     pthread_mutex_lock(pMutex);
1948     index = MFC_Encoder_Find_Outbuf(pCtx, pBuffer[0]);
1949     if (index == -1) {
1950         pthread_mutex_unlock(pMutex);
1951         ALOGE("%s: Failed to get index", __func__);
1952         ret = VIDEO_ERROR_NOBUFFERS;
1953         goto EXIT;
1954     }
1955     buf.index = index;
1956     pCtx->pOutbuf[buf.index].bQueued = VIDEO_TRUE;
1957     pthread_mutex_unlock(pMutex);
1958
1959     if (pCtx->bShareOutbuf == VIDEO_TRUE) {
1960         buf.memory = pCtx->nMemoryType;
1961         for (i = 0; i < nPlanes; i++) {
1962             /* V4L2_MEMORY_USERPTR */
1963             buf.m.planes[i].m.userptr = (unsigned long)pBuffer[i];
1964             buf.m.planes[i].length = pCtx->pOutbuf[index].planes[i].allocSize;
1965             /* V4L2_MEMORY_DMABUF */
1966 #ifdef USE_DMA_BUF
1967             buf.m.planes[i].m.fd = pCtx->pOutbuf[index].planes[i].fd;
1968             buf.m.planes[i].length = 0; /* kernel give the length */
1969 #endif
1970             buf.m.planes[i].bytesused = dataSize[i];
1971         }
1972     } else {
1973         buf.memory = V4L2_MEMORY_MMAP;
1974     }
1975
1976     if (exynos_v4l2_qbuf(pCtx->hEnc, &buf) != 0) {
1977         ALOGE("%s: Failed to enqueue output buffer", __func__);
1978         pCtx->pOutbuf[buf.index].bQueued = VIDEO_FALSE;
1979         ret = VIDEO_ERROR_APIFAIL;
1980         goto EXIT;
1981     }
1982
1983     pCtx->pOutbuf[buf.index].pPrivate = pPrivate;
1984
1985 EXIT:
1986     return ret;
1987 }
1988
1989 /*
1990  * [Encoder Buffer OPS] Enqueue All (Output)
1991  */
1992 static ExynosVideoErrorType MFC_Encoder_Enqueue_All_Outbuf(void *pHandle)
1993 {
1994     ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
1995     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
1996
1997     unsigned char         *pBuffer[VIDEO_BUFFER_MAX_PLANES]  = {NULL, };
1998     unsigned int           dataSize[VIDEO_BUFFER_MAX_PLANES] = {0, };
1999
2000     int i;
2001
2002     if (pCtx == NULL) {
2003         ALOGE("%s: Video context info must be supplied", __func__);
2004         ret = VIDEO_ERROR_BADPARAM;
2005         goto EXIT;
2006     }
2007
2008     for (i = 0; i < pCtx->nOutbufs; i++) {
2009         ret = MFC_Encoder_Enqueue_Outbuf(pCtx, pBuffer, dataSize, 1, NULL);
2010         if (ret != VIDEO_ERROR_NONE)
2011             goto EXIT;
2012     }
2013
2014 EXIT:
2015     return ret;
2016 }
2017
2018 /*
2019  * [Encoder Buffer OPS] Dequeue (Input)
2020  */
2021 static ExynosVideoBuffer *MFC_Encoder_Dequeue_Inbuf(void *pHandle)
2022 {
2023     ExynosVideoEncContext *pCtx     = (ExynosVideoEncContext *)pHandle;
2024     ExynosVideoBuffer     *pInbuf   = NULL;
2025
2026     struct v4l2_buffer buf;
2027
2028     if (pCtx == NULL) {
2029         ALOGE("%s: Video context info must be supplied", __func__);
2030         goto EXIT;
2031     }
2032
2033     if (pCtx->bStreamonInbuf == VIDEO_FALSE) {
2034         pInbuf = NULL;
2035         goto EXIT;
2036     }
2037
2038     memset(&buf, 0, sizeof(buf));
2039
2040     buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
2041
2042     if (pCtx->bShareInbuf == VIDEO_TRUE)
2043         buf.memory = pCtx->nMemoryType;
2044     else
2045         buf.memory = V4L2_MEMORY_MMAP;
2046
2047     if (exynos_v4l2_dqbuf(pCtx->hEnc, &buf) != 0) {
2048         pInbuf = NULL;
2049         goto EXIT;
2050     }
2051
2052     pInbuf = &pCtx->pInbuf[buf.index];
2053     pCtx->pInbuf[buf.index].bQueued = VIDEO_FALSE;
2054
2055 EXIT:
2056     return pInbuf;
2057 }
2058
2059 /*
2060  * [Encoder Buffer OPS] Dequeue (Output)
2061  */
2062 static ExynosVideoBuffer *MFC_Encoder_Dequeue_Outbuf(void *pHandle)
2063 {
2064     ExynosVideoEncContext *pCtx    = (ExynosVideoEncContext *)pHandle;
2065     ExynosVideoBuffer     *pOutbuf = NULL;
2066
2067     struct v4l2_buffer buf;
2068     struct v4l2_plane  planes[VIDEO_ENCODER_OUTBUF_PLANES];
2069     int value;
2070
2071     if (pCtx == NULL) {
2072         ALOGE("%s: Video context info must be supplied", __func__);
2073         goto EXIT;
2074     }
2075
2076     if (pCtx->bStreamonOutbuf == VIDEO_FALSE) {
2077         pOutbuf = NULL;
2078         goto EXIT;
2079     }
2080
2081     memset(&buf, 0, sizeof(buf));
2082
2083     buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2084     buf.m.planes = planes;
2085     buf.length = 1;
2086
2087     if (pCtx->bShareOutbuf == VIDEO_TRUE)
2088         buf.memory = pCtx->nMemoryType;
2089     else
2090         buf.memory = V4L2_MEMORY_MMAP;
2091
2092     /* no error case for output buffer dequeue in encoder */
2093     if (exynos_v4l2_dqbuf(pCtx->hEnc, &buf) != 0) {
2094         goto EXIT;
2095     }
2096
2097     pOutbuf = &pCtx->pOutbuf[buf.index];
2098     pOutbuf->planes[0].dataSize = buf.m.planes[0].bytesused;
2099
2100     switch (buf.flags & (0x7 << 3)) {
2101     case V4L2_BUF_FLAG_KEYFRAME:
2102         pOutbuf->frameType = VIDEO_FRAME_I;
2103         break;
2104     case V4L2_BUF_FLAG_PFRAME:
2105         pOutbuf->frameType = VIDEO_FRAME_P;
2106         break;
2107     case V4L2_BUF_FLAG_BFRAME:
2108         pOutbuf->frameType = VIDEO_FRAME_B;
2109         break;
2110     default:
2111         ALOGI("%s: encoded frame type is = %d",__func__, (buf.flags & (0x7 << 3)));
2112         pOutbuf->frameType = VIDEO_FRAME_OTHERS;
2113         break;
2114     };
2115
2116     pOutbuf->bQueued = VIDEO_FALSE;
2117
2118 EXIT:
2119     return pOutbuf;
2120 }
2121
2122 static ExynosVideoErrorType MFC_Encoder_Clear_Queued_Inbuf(void *pHandle)
2123 {
2124     ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
2125     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
2126     int i = 0;
2127
2128     if (pCtx == NULL) {
2129         ALOGE("%s: Video context info must be supplied", __func__);
2130         ret = VIDEO_ERROR_BADPARAM;
2131         goto EXIT;
2132     }
2133
2134     for (i = 0; i <  pCtx->nInbufs; i++) {
2135         pCtx->pInbuf[i].bQueued = VIDEO_FALSE;
2136     }
2137
2138 EXIT:
2139     return ret;
2140 }
2141
2142 static ExynosVideoErrorType MFC_Encoder_Clear_Queued_Outbuf(void *pHandle)
2143 {
2144     ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
2145     ExynosVideoErrorType   ret  = VIDEO_ERROR_NONE;
2146     int i = 0;
2147
2148     if (pCtx == NULL) {
2149         ALOGE("%s: Video context info must be supplied", __func__);
2150         ret = VIDEO_ERROR_BADPARAM;
2151         goto EXIT;
2152     }
2153
2154     for (i = 0; i < pCtx->nOutbufs; i++) {
2155         pCtx->pOutbuf[i].bQueued = VIDEO_FALSE;
2156     }
2157
2158 EXIT:
2159     return ret;
2160 }
2161
2162 /*
2163  * [Encoder OPS] Common
2164  */
2165 static ExynosVideoEncOps defEncOps = {
2166     .nSize          = 0,
2167     .Init           = MFC_Encoder_Init,
2168     .Finalize       = MFC_Encoder_Finalize,
2169     .Set_EncParam   = MFC_Encoder_Set_EncParam,
2170     .Set_FrameType  = MFC_Encoder_Set_FrameType,
2171     .Set_FrameRate  = MFC_Encoder_Set_FrameRate,
2172     .Set_BitRate    = MFC_Encoder_Set_BitRate,
2173     .Set_FrameSkip  = MFC_Encoder_Set_FrameSkip,
2174     .Set_IDRPeriod  = MFC_Encoder_Set_IDRPeriod,
2175     .Set_FrameTag   = MFC_Encoder_Set_FrameTag,
2176     .Get_FrameTag   = MFC_Encoder_Get_FrameTag,
2177     .Enable_PrependSpsPpsToIdr = MFC_Encoder_Enable_PrependSpsPpsToIdr,
2178 };
2179
2180 /*
2181  * [Encoder Buffer OPS] Input
2182  */
2183 static ExynosVideoEncBufferOps defInbufOps = {
2184     .nSize                  = 0,
2185     .Enable_Cacheable       = MFC_Encoder_Enable_Cacheable_Inbuf,
2186     .Set_Shareable          = MFC_Encoder_Set_Shareable_Inbuf,
2187     .Get_Buffer             = MFC_Encoder_Get_Buffer_Inbuf,
2188     .Set_Geometry           = MFC_Encoder_Set_Geometry_Inbuf,
2189     .Get_Geometry           = MFC_Encoder_Get_Geometry_Inbuf,
2190     .Setup                  = MFC_Encoder_Setup_Inbuf,
2191     .Run                    = MFC_Encoder_Run_Inbuf,
2192     .Stop                   = MFC_Encoder_Stop_Inbuf,
2193     .Enqueue                = MFC_Encoder_Enqueue_Inbuf,
2194     .Enqueue_All            = NULL,
2195     .Dequeue                = MFC_Encoder_Dequeue_Inbuf,
2196     .Register               = MFC_Encoder_Register_Inbuf,
2197     .Clear_RegisteredBuffer = MFC_Encoder_Clear_RegisteredBuffer_Inbuf,
2198     .Clear_Queue            = MFC_Encoder_Clear_Queued_Inbuf,
2199 };
2200
2201 /*
2202  * [Encoder Buffer OPS] Output
2203  */
2204 static ExynosVideoEncBufferOps defOutbufOps = {
2205     .nSize                  = 0,
2206     .Enable_Cacheable       = MFC_Encoder_Enable_Cacheable_Outbuf,
2207     .Set_Shareable          = MFC_Encoder_Set_Shareable_Outbuf,
2208     .Get_Buffer             = MFC_Encoder_Get_Buffer_Outbuf,
2209     .Set_Geometry           = MFC_Encoder_Set_Geometry_Outbuf,
2210     .Get_Geometry           = MFC_Encoder_Get_Geometry_Outbuf,
2211     .Setup                  = MFC_Encoder_Setup_Outbuf,
2212     .Run                    = MFC_Encoder_Run_Outbuf,
2213     .Stop                   = MFC_Encoder_Stop_Outbuf,
2214     .Enqueue                = MFC_Encoder_Enqueue_Outbuf,
2215     .Enqueue_All            = NULL,
2216     .Dequeue                = MFC_Encoder_Dequeue_Outbuf,
2217     .Register               = MFC_Encoder_Register_Outbuf,
2218     .Clear_RegisteredBuffer = MFC_Encoder_Clear_RegisteredBuffer_Outbuf,
2219     .Clear_Queue            = MFC_Encoder_Clear_Queued_Outbuf,
2220 };
2221
2222 int Exynos_Video_Register_Encoder(
2223     ExynosVideoEncOps *pEncOps,
2224     ExynosVideoEncBufferOps *pInbufOps,
2225     ExynosVideoEncBufferOps *pOutbufOps)
2226 {
2227     ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
2228
2229     if ((pEncOps == NULL) || (pInbufOps == NULL) || (pOutbufOps == NULL)) {
2230         ret = VIDEO_ERROR_BADPARAM;
2231         goto EXIT;
2232     }
2233
2234     defEncOps.nSize = sizeof(defEncOps);
2235     defInbufOps.nSize = sizeof(defInbufOps);
2236     defOutbufOps.nSize = sizeof(defOutbufOps);
2237
2238     memcpy((char *)pEncOps + sizeof(pEncOps->nSize), (char *)&defEncOps + sizeof(defEncOps.nSize),
2239             pEncOps->nSize - sizeof(pEncOps->nSize));
2240
2241     memcpy((char *)pInbufOps + sizeof(pInbufOps->nSize), (char *)&defInbufOps + sizeof(defInbufOps.nSize),
2242             pInbufOps->nSize - sizeof(pInbufOps->nSize));
2243
2244     memcpy((char *)pOutbufOps + sizeof(pOutbufOps->nSize), (char *)&defOutbufOps + sizeof(defOutbufOps.nSize),
2245             pOutbufOps->nSize - sizeof(pOutbufOps->nSize));
2246
2247 EXIT:
2248     return ret;
2249 }