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