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