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