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