exynos_omx: multi_thread: Remove hardcoded limit on the max of number of input buffer...
[GitHub/LineageOS/android_hardware_samsung_slsi_exynos5.git] / exynos_omx / codecs / exynos_codecs / video / exynos5 / mfc_v4l2 / enc / src / ExynosVideoEncoder.c
CommitLineData
20d3e6e3 1/*
20d3e6e3 2 *
38ef2572 3 * Copyright 2012 Samsung Electronics S.LSI Co. LTD
20d3e6e3 4 *
38ef2572 5 * Licensed under the Apache License, Version 2.0 (the "License");
20d3e6e3
JC
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>
30e79fb1 39#include <pthread.h>
20d3e6e3
JC
40
41#include <sys/poll.h>
42
43#include "ExynosVideoApi.h"
44#include "ExynosVideoEnc.h"
20d3e6e3
JC
45
46/* #define LOG_NDEBUG 0 */
47#define LOG_TAG "ExynosVideoEncoder"
48#include <utils/Log.h>
49
800a8d75
JC
50#define MAX_CTRL_NUM 91
51#define H264_CTRL_NUM 91
20d3e6e3
JC
52#define MPEG4_CTRL_NUM 26
53#define H263_CTRL_NUM 18
5b46229d 54#define MAX_INPUTBUFFER_COUNT 32
20d3e6e3
JC
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 */
c94beaeb 119static void *MFC_Encoder_Init(int nMemoryType)
20d3e6e3 120{
38ef2572
JC
121 ExynosVideoEncContext *pCtx = NULL;
122 pthread_mutex_t *pMutex = NULL;
20d3e6e3
JC
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) {
4a7b2d3c 127 ALOGE("%s: Failed to allocate encoder context buffer", __func__);
20d3e6e3
JC
128 goto EXIT_ALLOC_FAIL;
129 }
130
131 memset(pCtx, 0, sizeof(*pCtx));
132
38ef2572 133 pCtx->hEnc = exynos_v4l2_open_devname(VIDEO_ENCODER_NAME, O_RDWR, 0);
20d3e6e3 134 if (pCtx->hEnc < 0) {
4a7b2d3c 135 ALOGE("%s: Failed to open encoder device", __func__);
20d3e6e3
JC
136 goto EXIT_OPEN_FAIL;
137 }
138
139 if (!exynos_v4l2_querycap(pCtx->hEnc, needCaps)) {
4a7b2d3c 140 ALOGE("%s: Failed to querycap", __func__);
20d3e6e3
JC
141 goto EXIT_QUERYCAP_FAIL;
142 }
143
800a8d75
JC
144 pCtx->bStreamonInbuf = VIDEO_FALSE;
145 pCtx->bStreamonOutbuf = VIDEO_FALSE;
146
c94beaeb 147 pCtx->nMemoryType = nMemoryType;
1f0d5e30 148
38ef2572
JC
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
20d3e6e3
JC
171 return (void *)pCtx;
172
173EXIT_QUERYCAP_FAIL:
38ef2572
JC
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
20d3e6e3
JC
184 close(pCtx->hEnc);
185
186EXIT_OPEN_FAIL:
187 free(pCtx);
20d3e6e3
JC
188
189EXIT_ALLOC_FAIL:
190 return NULL;
191}
192
193/*
194 * [Encoder OPS] Finalize
195 */
196static ExynosVideoErrorType MFC_Encoder_Finalize(void *pHandle)
197{
38ef2572
JC
198 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
199 ExynosVideoPlane *pVideoPlane = NULL;
200 pthread_mutex_t *pMutex = NULL;
201 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
20d3e6e3
JC
202 int i, j;
203
204 if (pCtx == NULL) {
4a7b2d3c 205 ALOGE("%s: Video context info must be supplied", __func__);
20d3e6e3
JC
206 ret = VIDEO_ERROR_BADPARAM;
207 goto EXIT;
208 }
209
38ef2572
JC
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
20d3e6e3
JC
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;
38ef2572 237 pCtx->pInbuf[i].bRegistered = VIDEO_FALSE;
20d3e6e3
JC
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;
38ef2572 255 pCtx->pOutbuf[i].bRegistered = VIDEO_FALSE;
20d3e6e3
JC
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
20d3e6e3
JC
275/*
276 * [Encoder OPS] Set Extended Control
277 */
278static ExynosVideoErrorType MFC_Encoder_Set_EncParam (
38ef2572
JC
279 void *pHandle,
280 ExynosVideoEncParam *pEncParam)
20d3e6e3
JC
281{
282 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
38ef2572
JC
283 ExynosVideoEncInitParam *pInitParam = NULL;
284 ExynosVideoEncCommonParam *pCommonParam = NULL;
285
20d3e6e3 286 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
20d3e6e3
JC
287
288 int i;
289 struct v4l2_ext_control ext_ctrl[MAX_CTRL_NUM];
290 struct v4l2_ext_controls ext_ctrls;
291
38ef2572 292 if ((pCtx == NULL) || (pEncParam == NULL)) {
4a7b2d3c 293 ALOGE("%s: Video context info must be supplied", __func__);
20d3e6e3
JC
294 ret = VIDEO_ERROR_BADPARAM;
295 goto EXIT;
296 }
297
38ef2572
JC
298 pInitParam = &pEncParam->initParam;
299 pCommonParam = &pEncParam->commonParam;
300
20d3e6e3
JC
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;
800a8d75
JC
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;
20d3e6e3
JC
319
320 /* FIXME temporary fix */
321 if (pCommonParam->Bitrate)
800a8d75 322 ext_ctrl[7].value = pCommonParam->Bitrate;
20d3e6e3 323 else
800a8d75 324 ext_ctrl[7].value = 1; /* just for testing Movie studio */
20d3e6e3
JC
325
326 /* codec specific parameters */
327 switch (pEncParam->eCompressionFormat) {
328 case VIDEO_CODING_AVC:
38ef2572
JC
329 {
330 ExynosVideoEncH264Param *pH264Param = &pEncParam->codecParam.h264;
20d3e6e3
JC
331
332 /* common parameters but id is depends on codec */
800a8d75
JC
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;
20d3e6e3
JC
343
344 /* H.264 specific parameters */
38ef2572
JC
345 switch (pCommonParam->SliceMode) {
346 case 0:
800a8d75
JC
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 */
38ef2572
JC
351 break;
352 case 1:
800a8d75 353 ext_ctrl[13].id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB;
20d3e6e3 354 ext_ctrl[13].value = pH264Param->SliceArgument;
800a8d75
JC
355 ext_ctrl[14].id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES;
356 ext_ctrl[14].value = 2800; /* based on MFC6.x */
38ef2572
JC
357 break;
358 case 3:
800a8d75
JC
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;
38ef2572
JC
363 break;
364 default:
365 break;
20d3e6e3
JC
366 }
367
800a8d75
JC
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;
20d3e6e3
JC
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;
800a8d75
JC
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;
20d3e6e3
JC
403
404 /* doesn't have to be set */
800a8d75 405 ext_ctrl[31].id = V4L2_CID_MPEG_VIDEO_GOP_CLOSURE;
bad25634 406 ext_ctrl[31].value = 1;
800a8d75 407 ext_ctrl[32].id = V4L2_CID_MPEG_VIDEO_H264_I_PERIOD;
bad25634 408 ext_ctrl[32].value = 0;
800a8d75
JC
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;
20d3e6e3 420 ext_ctrl[38].value = 0;
20d3e6e3
JC
421
422 /* Initial parameters : Frame Skip */
38ef2572
JC
423 switch (pInitParam->FrameSkip) {
424 case VIDEO_FRAME_SKIP_MODE_LEVEL_LIMIT:
800a8d75
JC
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;
38ef2572
JC
427 break;
428 case VIDEO_FRAME_SKIP_MODE_BUF_LIMIT:
800a8d75
JC
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;
38ef2572
JC
431 break;
432 default:
433 /* VIDEO_FRAME_SKIP_MODE_DISABLE (default) */
800a8d75
JC
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;
38ef2572 436 break;
20d3e6e3
JC
437 }
438
439 /* SVC is not supported yet */
800a8d75
JC
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);
20d3e6e3 448 ext_ctrl[44].id = V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_QP;
800a8d75 449 ext_ctrl[44].value = (1 << 16 | 0);
20d3e6e3 450 ext_ctrl[45].id = V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_QP;
800a8d75 451 ext_ctrl[45].value = (2 << 16 | 0);
20d3e6e3 452
800a8d75
JC
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;
20d3e6e3 456 ext_ctrl[47].value = 0;
800a8d75
JC
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;
20d3e6e3
JC
459
460 /* FMO is not supported yet */
800a8d75
JC
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);
20d3e6e3 469 ext_ctrl[53].id = V4L2_CID_MPEG_VIDEO_H264_FMO_RUN_LENGTH;
800a8d75 470 ext_ctrl[53].value = (1 << 30 | 0);
20d3e6e3 471 ext_ctrl[54].id = V4L2_CID_MPEG_VIDEO_H264_FMO_RUN_LENGTH;
800a8d75 472 ext_ctrl[54].value = (2 << 30 | 0);
20d3e6e3 473 ext_ctrl[55].id = V4L2_CID_MPEG_VIDEO_H264_FMO_RUN_LENGTH;
800a8d75
JC
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;
20d3e6e3
JC
479
480 /* ASO is not supported yet */
800a8d75
JC
481 ext_ctrl[58].id = V4L2_CID_MPEG_VIDEO_H264_ASO;
482 ext_ctrl[58].value = 0;
20d3e6e3 483 for (i = 0; i < 32; i++) {
800a8d75
JC
484 ext_ctrl[59 + i].id = V4L2_CID_MPEG_VIDEO_H264_ASO_SLICE_ORDER;
485 ext_ctrl[59 + i].value = (i << 16 | 0);
20d3e6e3 486 }
38ef2572
JC
487
488 ext_ctrls.count = H264_CTRL_NUM;
20d3e6e3 489 break;
38ef2572 490 }
20d3e6e3
JC
491
492 case VIDEO_CODING_MPEG4:
38ef2572
JC
493 {
494 ExynosVideoEncMpeg4Param *pMpeg4Param = &pEncParam->codecParam.mpeg4;
20d3e6e3
JC
495
496 /* common parameters but id is depends on codec */
800a8d75
JC
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;
20d3e6e3
JC
507
508 /* MPEG4 specific parameters */
38ef2572
JC
509 switch (pCommonParam->SliceMode) {
510 case 0:
800a8d75
JC
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 */
38ef2572
JC
515 break;
516 case 1:
800a8d75 517 ext_ctrl[13].id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB;
20d3e6e3 518 ext_ctrl[13].value = pMpeg4Param->SliceArgument;
800a8d75
JC
519 ext_ctrl[14].id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES;
520 ext_ctrl[14].value = 2800; /* based on MFC6.x */
38ef2572
JC
521 break;
522 case 3:
800a8d75
JC
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;
38ef2572
JC
527 break;
528 default:
529 break;
20d3e6e3
JC
530 }
531
800a8d75
JC
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;
20d3e6e3
JC
538
539 /*
540 * It should be set using mpeg4Param->NumberBFrames after being handled by appl.
541 */
800a8d75
JC
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;
20d3e6e3 552 ext_ctrl[22].value = 0;
800a8d75
JC
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;
20d3e6e3
JC
557
558 /* Initial parameters : Frame Skip */
38ef2572
JC
559 switch (pInitParam->FrameSkip) {
560 case VIDEO_FRAME_SKIP_MODE_LEVEL_LIMIT:
20d3e6e3
JC
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;
38ef2572
JC
563 break;
564 case VIDEO_FRAME_SKIP_MODE_BUF_LIMIT:
20d3e6e3
JC
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;
38ef2572
JC
567 break;
568 default:
569 /* VIDEO_FRAME_SKIP_MODE_DISABLE (default) */
20d3e6e3
JC
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;
38ef2572 572 break;
20d3e6e3
JC
573 }
574
38ef2572 575 ext_ctrls.count = MPEG4_CTRL_NUM;
20d3e6e3 576 break;
38ef2572 577 }
20d3e6e3
JC
578
579 case VIDEO_CODING_H263:
38ef2572
JC
580 {
581 ExynosVideoEncH263Param *pH263Param = &pEncParam->codecParam.h263;
20d3e6e3
JC
582
583 /* common parameters but id is depends on codec */
800a8d75
JC
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;
20d3e6e3
JC
594
595 /* H263 specific parameters */
800a8d75
JC
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;
20d3e6e3
JC
604
605 /* Initial parameters : Frame Skip */
38ef2572
JC
606 switch (pInitParam->FrameSkip) {
607 case VIDEO_FRAME_SKIP_MODE_LEVEL_LIMIT:
20d3e6e3
JC
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;
38ef2572
JC
610 break;
611 case VIDEO_FRAME_SKIP_MODE_BUF_LIMIT:
20d3e6e3
JC
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;
38ef2572
JC
614 break;
615 default:
616 /* VIDEO_FRAME_SKIP_MODE_DISABLE (default) */
20d3e6e3
JC
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;
38ef2572 619 break;
20d3e6e3
JC
620 }
621
38ef2572 622 ext_ctrls.count = H263_CTRL_NUM;
20d3e6e3 623 break;
38ef2572 624 }
20d3e6e3
JC
625
626 default:
4a7b2d3c 627 ALOGE("[%s] Undefined codec type",__func__);
20d3e6e3
JC
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;
20d3e6e3 634
38ef2572 635 if (exynos_v4l2_s_ext_ctrl(pCtx->hEnc, &ext_ctrls) != 0) {
4a7b2d3c 636 ALOGE("%s: Failed to s_ext_ctrl", __func__);
20d3e6e3
JC
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(
38ef2572
JC
649 void *pHandle,
650 int frameTag)
20d3e6e3
JC
651{
652 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
653 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
654
655 if (pCtx == NULL) {
4a7b2d3c 656 ALOGE("%s: Video context info must be supplied", __func__);
20d3e6e3
JC
657 ret = VIDEO_ERROR_BADPARAM;
658 goto EXIT;
659 }
660
38ef2572 661 if (exynos_v4l2_s_ctrl(pCtx->hEnc, V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG, frameTag) != 0) {
4a7b2d3c 662 ALOGE("%s: Failed to s_ctrl", __func__);
20d3e6e3
JC
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) {
4a7b2d3c 682 ALOGE("%s: Video context info must be supplied", __func__);
20d3e6e3
JC
683 goto EXIT;
684 }
685
38ef2572 686 if (exynos_v4l2_g_ctrl(pCtx->hEnc, V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG, &frameTag) != 0) {
4a7b2d3c 687 ALOGE("%s: Failed to g_ctrl", __func__);
20d3e6e3
JC
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(
38ef2572
JC
700 void *pHandle,
701 ExynosVideoFrameType frameType)
20d3e6e3
JC
702{
703 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
704 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
705
706 if (pCtx == NULL) {
4a7b2d3c 707 ALOGE("%s: Video context info must be supplied", __func__);
20d3e6e3
JC
708 ret = VIDEO_ERROR_BADPARAM;
709 goto EXIT;
710 }
711
38ef2572 712 if (exynos_v4l2_s_ctrl(pCtx->hEnc, V4L2_CID_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE, frameType) != 0) {
4a7b2d3c 713 ALOGE("%s: Failed to s_ctrl", __func__);
20d3e6e3
JC
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(
38ef2572
JC
726 void *pHandle,
727 int frameRate)
20d3e6e3
JC
728{
729 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
730 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
731
732 if (pCtx == NULL) {
4a7b2d3c 733 ALOGE("%s: Video context info must be supplied", __func__);
20d3e6e3
JC
734 ret = VIDEO_ERROR_BADPARAM;
735 goto EXIT;
736 }
737
38ef2572 738 if (exynos_v4l2_s_ctrl(pCtx->hEnc, V4L2_CID_MPEG_MFC51_VIDEO_FRAME_RATE_CH, frameRate) != 0) {
4a7b2d3c 739 ALOGE("%s: Failed to s_ctrl", __func__);
20d3e6e3
JC
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(
38ef2572
JC
752 void *pHandle,
753 int bitRate)
20d3e6e3
JC
754{
755 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
756 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
757
758 if (pCtx == NULL) {
4a7b2d3c 759 ALOGE("%s: Video context info must be supplied", __func__);
20d3e6e3
JC
760 ret = VIDEO_ERROR_BADPARAM;
761 goto EXIT;
762 }
763
38ef2572 764 if (exynos_v4l2_s_ctrl(pCtx->hEnc, V4L2_CID_MPEG_MFC51_VIDEO_BIT_RATE_CH, bitRate) != 0) {
4a7b2d3c 765 ALOGE("%s: Failed to s_ctrl", __func__);
20d3e6e3
JC
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(
38ef2572
JC
778 void *pHandle,
779 int frameSkip)
20d3e6e3
JC
780{
781 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
782 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
783
784 if (pCtx == NULL) {
4a7b2d3c 785 ALOGE("%s: Video context info must be supplied", __func__);
20d3e6e3
JC
786 ret = VIDEO_ERROR_BADPARAM;
787 goto EXIT;
788 }
789
38ef2572 790 if (exynos_v4l2_s_ctrl(pCtx->hEnc, V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE, frameSkip) != 0) {
4a7b2d3c 791 ALOGE("%s: Failed to s_ctrl", __func__);
20d3e6e3
JC
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(
38ef2572
JC
804 void *pHandle,
805 int IDRPeriod)
20d3e6e3
JC
806{
807 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
808 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
809
810 if (pCtx == NULL) {
4a7b2d3c 811 ALOGE("%s: Video context info must be supplied", __func__);
20d3e6e3
JC
812 ret = VIDEO_ERROR_BADPARAM;
813 goto EXIT;
814 }
815
38ef2572 816 if (exynos_v4l2_s_ctrl(pCtx->hEnc, V4L2_CID_MPEG_VIDEO_H264_I_PERIOD, IDRPeriod) != 0) {
4a7b2d3c 817 ALOGE("%s: Failed to s_ctrl", __func__);
20d3e6e3
JC
818 ret = VIDEO_ERROR_APIFAIL;
819 goto EXIT;
820 }
821
822EXIT:
823 return ret;
824}
825
800a8d75
JC
826/*
827 * [Encoder Buffer OPS] Enable Cacheable (Input)
828 */
829static ExynosVideoErrorType MFC_Encoder_Enable_Cacheable_Inbuf(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
38ef2572
JC
840 if (exynos_v4l2_s_ctrl(pCtx->hEnc, V4L2_CID_CACHEABLE, 2) != 0) {
841 ALOGE("%s: Failed V4L2_CID_CACHEABLE", __func__);
800a8d75
JC
842 ret = VIDEO_ERROR_APIFAIL;
843 goto EXIT;
844 }
845
846EXIT:
847 return ret;
848}
849
850/*
851 * [Encoder Buffer OPS] Enable Cacheable (Output)
852 */
853static ExynosVideoErrorType MFC_Encoder_Enable_Cacheable_Outbuf(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
38ef2572
JC
864 if (exynos_v4l2_s_ctrl(pCtx->hEnc, V4L2_CID_CACHEABLE, 1) != 0) {
865 ALOGE("%s: Failed V4L2_CID_CACHEABLE", __func__);
800a8d75
JC
866 ret = VIDEO_ERROR_APIFAIL;
867 goto EXIT;
868 }
869
870EXIT:
871 return ret;
872}
20d3e6e3
JC
873
874/*
875 * [Encoder Buffer OPS] Set Shareable Buffer (Input)
876 */
877static ExynosVideoErrorType MFC_Encoder_Set_Shareable_Inbuf(void *pHandle)
878{
879 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
880 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
881
882 if (pCtx == NULL) {
4a7b2d3c 883 ALOGE("%s: Video context info must be supplied", __func__);
20d3e6e3
JC
884 ret = VIDEO_ERROR_BADPARAM;
885 goto EXIT;
886 }
887
888 pCtx->bShareInbuf = VIDEO_TRUE;
889
890EXIT:
891 return ret;
892}
893
894/*
895 * [Encoder Buffer OPS] Set Shareable Buffer (Output)
896 */
897static ExynosVideoErrorType MFC_Encoder_Set_Shareable_Outbuf(void *pHandle)
898{
899 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
900 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
901
902 if (pCtx == NULL) {
4a7b2d3c 903 ALOGE("%s: Video context info must be supplied", __func__);
20d3e6e3
JC
904 ret = VIDEO_ERROR_BADPARAM;
905 goto EXIT;
906 }
907
908 pCtx->bShareOutbuf = VIDEO_TRUE;
909
910EXIT:
911 return ret;
912}
913
914/*
38ef2572 915 * [Encoder Buffer OPS] Get Buffer (Input)
20d3e6e3 916 */
38ef2572
JC
917static ExynosVideoErrorType MFC_Encoder_Get_Buffer_Inbuf(
918 void *pHandle,
919 int nIndex,
920 ExynosVideoBuffer **pBuffer)
20d3e6e3
JC
921{
922 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
923 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
924
925 if (pCtx == NULL) {
4a7b2d3c 926 ALOGE("%s: Video context info must be supplied", __func__);
38ef2572 927 *pBuffer = NULL;
20d3e6e3
JC
928 ret = VIDEO_ERROR_NOBUFFERS;
929 goto EXIT;
930 }
931
38ef2572
JC
932 if (pCtx->nInbufs <= nIndex) {
933 *pBuffer = NULL;
934 ret = VIDEO_ERROR_BADPARAM;
935 goto EXIT;
936 }
937
938 *pBuffer = (ExynosVideoBuffer *)&pCtx->pInbuf[nIndex];
20d3e6e3
JC
939
940EXIT:
941 return ret;
942}
943
944/*
38ef2572 945 * [Encoder Buffer OPS] Get Buffer (Output)
20d3e6e3 946 */
38ef2572
JC
947static ExynosVideoErrorType MFC_Encoder_Get_Buffer_Outbuf(
948 void *pHandle,
949 int nIndex,
950 ExynosVideoBuffer **pBuffer)
20d3e6e3
JC
951{
952 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
953 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
954
955 if (pCtx == NULL) {
4a7b2d3c 956 ALOGE("%s: Video context info must be supplied", __func__);
38ef2572 957 *pBuffer = NULL;
20d3e6e3
JC
958 ret = VIDEO_ERROR_NOBUFFERS;
959 goto EXIT;
960 }
961
38ef2572
JC
962 if (pCtx->nOutbufs <= nIndex) {
963 *pBuffer = NULL;
964 ret = VIDEO_ERROR_BADPARAM;
965 goto EXIT;
966 }
967
968 *pBuffer = (ExynosVideoBuffer *)&pCtx->pOutbuf[nIndex];
20d3e6e3
JC
969
970EXIT:
971 return ret;
972}
973
974/*
975 * [Encoder Buffer OPS] Set Geometry (Src)
976 */
977static ExynosVideoErrorType MFC_Encoder_Set_Geometry_Inbuf(
38ef2572 978 void *pHandle,
20d3e6e3
JC
979 ExynosVideoGeometry *bufferConf)
980{
981 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
982 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
983
984 struct v4l2_format fmt;
985
986 if (pCtx == NULL) {
4a7b2d3c 987 ALOGE("%s: Video context info must be supplied", __func__);
20d3e6e3
JC
988 ret = VIDEO_ERROR_BADPARAM;
989 goto EXIT;
990 }
991
992 if (bufferConf == NULL) {
4a7b2d3c 993 ALOGE("%s: Buffer geometry must be supplied", __func__);
20d3e6e3
JC
994 ret = VIDEO_ERROR_BADPARAM;
995 goto EXIT;
996 }
997
998 memset(&fmt, 0, sizeof(fmt));
999
1000 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1001 fmt.fmt.pix_mp.pixelformat = __ColorFormatType_To_V4L2PixelFormat(bufferConf->eColorFormat);
1002 fmt.fmt.pix_mp.width = bufferConf->nFrameWidth;
1003 fmt.fmt.pix_mp.height = bufferConf->nFrameHeight;
1004 fmt.fmt.pix_mp.num_planes = VIDEO_ENCODER_INBUF_PLANES;
1005
38ef2572 1006 if (exynos_v4l2_s_fmt(pCtx->hEnc, &fmt) != 0) {
4a7b2d3c 1007 ALOGE("%s: Failed to s_fmt", __func__);
20d3e6e3
JC
1008 ret = VIDEO_ERROR_APIFAIL;
1009 goto EXIT;
1010 }
1011
38ef2572 1012 memcpy(&pCtx->inbufGeometry, bufferConf, sizeof(pCtx->inbufGeometry));
20d3e6e3
JC
1013
1014EXIT:
1015 return ret;
1016}
1017
1018/*
1019 * [Encoder Buffer OPS] Get Geometry (Src)
1020 */
1021static ExynosVideoErrorType MFC_Encoder_Get_Geometry_Inbuf(
38ef2572 1022 void *pHandle,
20d3e6e3
JC
1023 ExynosVideoGeometry *bufferConf)
1024{
1025 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
1026 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1027
1028 struct v4l2_format fmt;
1029
1030 if (pCtx == NULL) {
4a7b2d3c 1031 ALOGE("%s: Video context info must be supplied", __func__);
20d3e6e3
JC
1032 ret = VIDEO_ERROR_BADPARAM;
1033 goto EXIT;
1034 }
1035
1036 if (bufferConf == NULL) {
4a7b2d3c 1037 ALOGE("%s: Buffer geometry must be supplied", __func__);
20d3e6e3
JC
1038 ret = VIDEO_ERROR_BADPARAM;
1039 goto EXIT;
1040 }
1041
1042 memset(&fmt, 0, sizeof(fmt));
1043
1044 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
38ef2572 1045 if (exynos_v4l2_g_fmt(pCtx->hEnc, &fmt) != 0) {
4a7b2d3c 1046 ALOGE("%s: Failed to g_fmt", __func__);
20d3e6e3
JC
1047 ret = VIDEO_ERROR_APIFAIL;
1048 goto EXIT;
1049 }
1050
1051 bufferConf->nFrameHeight = fmt.fmt.pix_mp.width;
1052 bufferConf->nFrameHeight = fmt.fmt.pix_mp.height;
1053 bufferConf->nSizeImage = fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
1054
1055EXIT:
1056 return ret;
1057}
1058
1059/*
1060 * [Encoder Buffer OPS] Set Geometry (Dst)
1061 */
1062static ExynosVideoErrorType MFC_Encoder_Set_Geometry_Outbuf(
38ef2572 1063 void *pHandle,
20d3e6e3
JC
1064 ExynosVideoGeometry *bufferConf)
1065{
1066 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
1067 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1068
1069 struct v4l2_format fmt;
1070
1071 if (pCtx == NULL) {
4a7b2d3c 1072 ALOGE("%s: Video context info must be supplied", __func__);
20d3e6e3
JC
1073 ret = VIDEO_ERROR_BADPARAM;
1074 goto EXIT;
1075 }
1076
1077 if (bufferConf == NULL) {
4a7b2d3c 1078 ALOGE("%s: Buffer geometry must be supplied", __func__);
20d3e6e3
JC
1079 ret = VIDEO_ERROR_BADPARAM;
1080 goto EXIT;
1081 }
1082
1083 memset(&fmt, 0, sizeof(fmt));
1084
1085 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1086 fmt.fmt.pix_mp.pixelformat = __CodingType_To_V4L2PixelFormat(bufferConf->eCompressionFormat);
1087 fmt.fmt.pix_mp.plane_fmt[0].sizeimage = bufferConf->nSizeImage;
1088
38ef2572 1089 if (exynos_v4l2_s_fmt(pCtx->hEnc, &fmt) != 0) {
4a7b2d3c 1090 ALOGE("%s: Failed to s_fmt", __func__);
20d3e6e3
JC
1091 ret = VIDEO_ERROR_APIFAIL;
1092 goto EXIT;
1093 }
1094
38ef2572 1095 memcpy(&pCtx->outbufGeometry, bufferConf, sizeof(pCtx->outbufGeometry));
20d3e6e3
JC
1096
1097EXIT:
1098 return ret;
1099}
1100
1101/*
1102 * [Encoder Buffer OPS] Get Geometry (Dst)
1103 */
1104static ExynosVideoErrorType MFC_Encoder_Get_Geometry_Outbuf(
38ef2572 1105 void *pHandle,
20d3e6e3
JC
1106 ExynosVideoGeometry *bufferConf)
1107{
1108 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
1109 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1110
1111 struct v4l2_format fmt;
1112
1113 if (pCtx == NULL) {
4a7b2d3c 1114 ALOGE("%s: Video context info must be supplied", __func__);
20d3e6e3
JC
1115 ret = VIDEO_ERROR_BADPARAM;
1116 goto EXIT;
1117 }
1118
1119 if (bufferConf == NULL) {
4a7b2d3c 1120 ALOGE("%s: Buffer geometry must be supplied", __func__);
20d3e6e3
JC
1121 ret = VIDEO_ERROR_BADPARAM;
1122 goto EXIT;
1123 }
1124
1125 memset(&fmt, 0, sizeof(fmt));
1126
1127 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
38ef2572 1128 if (exynos_v4l2_g_fmt(pCtx->hEnc, &fmt) != 0) {
4a7b2d3c 1129 ALOGE("%s: Failed to g_fmt", __func__);
20d3e6e3
JC
1130 ret = VIDEO_ERROR_APIFAIL;
1131 goto EXIT;
1132 }
1133
1134 bufferConf->nSizeImage = fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
1135
1136EXIT:
1137 return ret;
1138}
1139
1140/*
1141 * [Encoder Buffer OPS] Setup (Src)
1142 */
1143static ExynosVideoErrorType MFC_Encoder_Setup_Inbuf(
38ef2572
JC
1144 void *pHandle,
1145 unsigned int nBufferCount)
20d3e6e3 1146{
38ef2572
JC
1147 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
1148 ExynosVideoPlane *pVideoPlane = NULL;
1149 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
20d3e6e3
JC
1150
1151 struct v4l2_requestbuffers req;
1152 struct v4l2_buffer buf;
1153 struct v4l2_plane planes[VIDEO_ENCODER_INBUF_PLANES];
1154 int i, j;
1155
1156 if (pCtx == NULL) {
4a7b2d3c 1157 ALOGE("%s: Video context info must be supplied", __func__);
20d3e6e3
JC
1158 ret = VIDEO_ERROR_BADPARAM;
1159 goto EXIT;
1160 }
1161
1162 if (nBufferCount == 0) {
5b46229d
SK
1163 nBufferCount = MAX_INPUTBUFFER_COUNT;
1164 ALOGV("%s: Change buffer count %d", __func__, nBufferCount);
20d3e6e3
JC
1165 }
1166
1167 memset(&req, 0, sizeof(req));
1168
1169 req.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1170 req.count = nBufferCount;
1171
1172 if (pCtx->bShareInbuf == VIDEO_TRUE)
1f0d5e30 1173 req.memory = pCtx->nMemoryType;
20d3e6e3
JC
1174 else
1175 req.memory = V4L2_MEMORY_MMAP;
1176
38ef2572 1177 if (exynos_v4l2_reqbufs(pCtx->hEnc, &req) != 0) {
4a7b2d3c 1178 ALOGE("Failed to require buffer");
20d3e6e3
JC
1179 ret = VIDEO_ERROR_APIFAIL;
1180 goto EXIT;
1181 }
1182
1183 pCtx->nInbufs = (int)req.count;
1184
1185 pCtx->pInbuf = malloc(sizeof(*pCtx->pInbuf) * pCtx->nInbufs);
1186 if (pCtx->pInbuf == NULL) {
38ef2572 1187 ALOGE("%s: Failed to allocate input buffer context", __func__);
20d3e6e3
JC
1188 ret = VIDEO_ERROR_NOMEM;
1189 goto EXIT;
1190 }
38ef2572 1191 memset(pCtx->pInbuf, 0, sizeof(*pCtx->pInbuf) * pCtx->nInbufs);
20d3e6e3
JC
1192
1193 memset(&buf, 0, sizeof(buf));
1194
1195 if (pCtx->bShareInbuf == VIDEO_FALSE) {
1196 buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1197 buf.memory = V4L2_MEMORY_MMAP;
1198 buf.m.planes = planes;
1199 buf.length = VIDEO_ENCODER_INBUF_PLANES;
1200
1201 for (i = 0; i < pCtx->nInbufs; i++) {
1202 buf.index = i;
38ef2572 1203 if (exynos_v4l2_querybuf(pCtx->hEnc, &buf) != 0) {
4a7b2d3c 1204 ALOGE("%s: Failed to querybuf", __func__);
20d3e6e3
JC
1205 ret = VIDEO_ERROR_APIFAIL;
1206 goto EXIT;
1207 }
1208
1209 for (j = 0; j < VIDEO_ENCODER_INBUF_PLANES; j++) {
1210 pVideoPlane = &pCtx->pInbuf[i].planes[j];
1211 pVideoPlane->addr = mmap(NULL,
1212 buf.m.planes[j].length, PROT_READ | PROT_WRITE,
1213 MAP_SHARED, pCtx->hEnc, buf.m.planes[j].m.mem_offset);
1214
1215 if (pVideoPlane->addr == MAP_FAILED) {
38ef2572 1216 ALOGE("%s: Failed to map", __func__);
20d3e6e3
JC
1217 ret = VIDEO_ERROR_MAPFAIL;
1218 goto EXIT;
1219 }
1220
1221 pVideoPlane->allocSize = buf.m.planes[j].length;
1222 pVideoPlane->dataSize = 0;
1223 }
1224
1225 pCtx->pInbuf[i].pGeometry = &pCtx->inbufGeometry;
1226 pCtx->pInbuf[i].bQueued = VIDEO_FALSE;
38ef2572 1227 pCtx->pInbuf[i].bRegistered = VIDEO_TRUE;
20d3e6e3
JC
1228
1229 }
1230 } else {
1231 for (i = 0; i < pCtx->nInbufs; i++) {
1232 pCtx->pInbuf[i].pGeometry = &pCtx->inbufGeometry;
1233 pCtx->pInbuf[i].bQueued = VIDEO_FALSE;
38ef2572 1234 pCtx->pInbuf[i].bRegistered = VIDEO_FALSE;
20d3e6e3
JC
1235 }
1236 }
38ef2572 1237
20d3e6e3
JC
1238 return ret;
1239
1240EXIT:
800a8d75
JC
1241 if ((pCtx != NULL) && (pCtx->pInbuf != NULL)) {
1242 if (pCtx->bShareInbuf == VIDEO_FALSE) {
1243 for (i = 0; i < pCtx->nInbufs; i++) {
1244 for (j = 0; j < VIDEO_ENCODER_INBUF_PLANES; j++) {
1245 pVideoPlane = &pCtx->pInbuf[i].planes[j];
1246 if (pVideoPlane->addr == MAP_FAILED) {
1247 pVideoPlane->addr = NULL;
1248 break;
1249 }
1250
1251 munmap(pVideoPlane->addr, pVideoPlane->allocSize);
20d3e6e3
JC
1252 }
1253 }
20d3e6e3 1254 }
800a8d75
JC
1255
1256 free(pCtx->pInbuf);
20d3e6e3
JC
1257 }
1258
1259 return ret;
1260}
1261
1262/*
1263 * [Encoder Buffer OPS] Setup (Dst)
1264 */
1265static ExynosVideoErrorType MFC_Encoder_Setup_Outbuf(
38ef2572
JC
1266 void *pHandle,
1267 unsigned int nBufferCount)
20d3e6e3 1268{
38ef2572
JC
1269 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
1270 ExynosVideoPlane *pVideoPlane = NULL;
1271 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
20d3e6e3
JC
1272
1273 struct v4l2_requestbuffers req;
1274 struct v4l2_buffer buf;
1275 struct v4l2_plane planes[VIDEO_ENCODER_OUTBUF_PLANES];
1276 int i, j;
1277
1278 if (pCtx == NULL) {
4a7b2d3c 1279 ALOGE("%s: Video context info must be supplied", __func__);
20d3e6e3
JC
1280 ret = VIDEO_ERROR_BADPARAM;
1281 goto EXIT;
1282 }
1283
1284 if (nBufferCount == 0) {
4a7b2d3c 1285 ALOGE("%s: Buffer count must be greater than 0", __func__);
20d3e6e3
JC
1286 ret = VIDEO_ERROR_BADPARAM;
1287 goto EXIT;
1288 }
1289
1290 memset(&req, 0, sizeof(req));
1291
1292 req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1293 req.count = nBufferCount;
1294
1295 if (pCtx->bShareOutbuf == VIDEO_TRUE)
1f0d5e30 1296 req.memory = pCtx->nMemoryType;
20d3e6e3
JC
1297 else
1298 req.memory = V4L2_MEMORY_MMAP;
1299
38ef2572 1300 if (exynos_v4l2_reqbufs(pCtx->hEnc, &req) != 0) {
4a7b2d3c 1301 ALOGE("%s: Failed to reqbuf", __func__);
20d3e6e3
JC
1302 ret = VIDEO_ERROR_APIFAIL;
1303 goto EXIT;
1304 }
1305
1306 pCtx->nOutbufs = req.count;
1307
1308 pCtx->pOutbuf = malloc(sizeof(*pCtx->pOutbuf) * pCtx->nOutbufs);
1309 if (pCtx->pOutbuf == NULL) {
38ef2572 1310 ALOGE("%s: Failed to allocate output buffer context", __func__);
20d3e6e3
JC
1311 ret = VIDEO_ERROR_NOMEM;
1312 goto EXIT;
1313 }
38ef2572 1314 memset(pCtx->pOutbuf, 0, sizeof(*pCtx->pOutbuf) * pCtx->nOutbufs);
20d3e6e3
JC
1315
1316 memset(&buf, 0, sizeof(buf));
1317
1318 if (pCtx->bShareOutbuf == VIDEO_FALSE) {
1319 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1320 buf.memory = V4L2_MEMORY_MMAP;
1321 buf.m.planes = planes;
1322 buf.length = VIDEO_ENCODER_OUTBUF_PLANES;
1323
1324 for (i = 0; i < pCtx->nOutbufs; i++) {
1325 buf.index = i;
38ef2572 1326 if (exynos_v4l2_querybuf(pCtx->hEnc, &buf) != 0) {
4a7b2d3c 1327 ALOGE("%s: Failed to querybuf", __func__);
20d3e6e3
JC
1328 ret = VIDEO_ERROR_APIFAIL;
1329 goto EXIT;
1330 }
1331
1332 for (j = 0; j < VIDEO_ENCODER_OUTBUF_PLANES; j++) {
1333 pVideoPlane = &pCtx->pOutbuf[i].planes[j];
1334 pVideoPlane->addr = mmap(NULL,
1335 buf.m.planes[j].length, PROT_READ | PROT_WRITE,
1336 MAP_SHARED, pCtx->hEnc, buf.m.planes[j].m.mem_offset);
1337
1338 if (pVideoPlane->addr == MAP_FAILED) {
38ef2572 1339 ALOGE("%s: Failed to map", __func__);
20d3e6e3
JC
1340 ret = VIDEO_ERROR_MAPFAIL;
1341 goto EXIT;
1342 }
1343
1344 pVideoPlane->allocSize = buf.m.planes[j].length;
1345 pVideoPlane->dataSize = 0;
1346 }
1347
1348 pCtx->pOutbuf[i].pGeometry = &pCtx->outbufGeometry;
1349 pCtx->pOutbuf[i].bQueued = VIDEO_FALSE;
38ef2572 1350 pCtx->pOutbuf[i].bRegistered = VIDEO_TRUE;
20d3e6e3
JC
1351 }
1352 } else {
800a8d75
JC
1353 for (i = 0; i < pCtx->nOutbufs; i++ ) {
1354 pCtx->pOutbuf[i].pGeometry = &pCtx->outbufGeometry;
1355 pCtx->pOutbuf[i].bQueued = VIDEO_FALSE;
38ef2572 1356 pCtx->pOutbuf[i].bRegistered = VIDEO_FALSE;
800a8d75 1357 }
20d3e6e3
JC
1358 }
1359
1360 return ret;
1361
1362EXIT:
800a8d75
JC
1363 if ((pCtx != NULL) && (pCtx->pOutbuf != NULL)) {
1364 if (pCtx->bShareOutbuf == VIDEO_FALSE) {
1365 for (i = 0; i < pCtx->nOutbufs; i++) {
1366 for (j = 0; j < VIDEO_ENCODER_OUTBUF_PLANES; j++) {
1367 pVideoPlane = &pCtx->pOutbuf[i].planes[j];
1368 if (pVideoPlane->addr == MAP_FAILED) {
1369 pVideoPlane->addr = NULL;
1370 break;
1371 }
20d3e6e3 1372
800a8d75
JC
1373 munmap(pVideoPlane->addr, pVideoPlane->allocSize);
1374 }
20d3e6e3 1375 }
20d3e6e3 1376 }
800a8d75
JC
1377
1378 free(pCtx->pOutbuf);
20d3e6e3
JC
1379 }
1380
1381 return ret;
1382}
1383
1384/*
1385 * [Encoder Buffer OPS] Run (src)
1386 */
1387static ExynosVideoErrorType MFC_Encoder_Run_Inbuf(void *pHandle)
1388{
1389 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
1390 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1391
1392 if (pCtx == NULL) {
4a7b2d3c 1393 ALOGE("%s: Video context info must be supplied", __func__);
20d3e6e3
JC
1394 ret = VIDEO_ERROR_BADPARAM;
1395 goto EXIT;
1396 }
1397
800a8d75 1398 if (pCtx->bStreamonInbuf == VIDEO_FALSE) {
38ef2572 1399 if (exynos_v4l2_streamon(pCtx->hEnc, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) != 0) {
800a8d75
JC
1400 ALOGE("%s: Failed to streamon for input buffer", __func__);
1401 ret = VIDEO_ERROR_APIFAIL;
1402 goto EXIT;
1403 }
1404 pCtx->bStreamonInbuf = VIDEO_TRUE;
20d3e6e3
JC
1405 }
1406
1407EXIT:
1408 return ret;
1409}
1410
1411/*
1412 * [Encoder Buffer OPS] Run (Dst)
1413 */
1414static ExynosVideoErrorType MFC_Encoder_Run_Outbuf(void *pHandle)
1415{
1416 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
1417 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1418
1419 if (pCtx == NULL) {
4a7b2d3c 1420 ALOGE("%s: Video context info must be supplied", __func__);
20d3e6e3
JC
1421 ret = VIDEO_ERROR_BADPARAM;
1422 goto EXIT;
1423 }
1424
800a8d75 1425 if (pCtx->bStreamonOutbuf == VIDEO_FALSE) {
38ef2572 1426 if (exynos_v4l2_streamon(pCtx->hEnc, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) != 0) {
800a8d75
JC
1427 ALOGE("%s: Failed to streamon for output buffer", __func__);
1428 ret = VIDEO_ERROR_APIFAIL;
1429 goto EXIT;
1430 }
1431 pCtx->bStreamonOutbuf = VIDEO_TRUE;
20d3e6e3
JC
1432 }
1433
1434EXIT:
1435 return ret;
1436}
1437
1438/*
1439 * [Encoder Buffer OPS] Stop (Src)
1440 */
1441static ExynosVideoErrorType MFC_Encoder_Stop_Inbuf(void *pHandle)
1442{
1443 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
1444 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
38ef2572 1445 int i = 0;
20d3e6e3
JC
1446
1447 if (pCtx == NULL) {
4a7b2d3c 1448 ALOGE("%s: Video context info must be supplied", __func__);
20d3e6e3
JC
1449 ret = VIDEO_ERROR_BADPARAM;
1450 goto EXIT;
1451 }
1452
800a8d75 1453 if (pCtx->bStreamonInbuf == VIDEO_TRUE) {
38ef2572 1454 if (exynos_v4l2_streamoff(pCtx->hEnc, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) != 0) {
800a8d75
JC
1455 ALOGE("%s: Failed to streamoff for input buffer", __func__);
1456 ret = VIDEO_ERROR_APIFAIL;
1457 goto EXIT;
1458 }
1459 pCtx->bStreamonInbuf = VIDEO_FALSE;
20d3e6e3
JC
1460 }
1461
38ef2572
JC
1462 for (i = 0; i < pCtx->nInbufs; i++) {
1463 pCtx->pInbuf[i].bQueued = VIDEO_FALSE;
1464 }
1465
20d3e6e3
JC
1466EXIT:
1467 return ret;
1468}
1469
1470/*
1471 * [Encoder Buffer OPS] Stop (Dst)
1472 */
1473static ExynosVideoErrorType MFC_Encoder_Stop_Outbuf(void *pHandle)
1474{
1475 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
1476 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
38ef2572 1477 int i = 0;
20d3e6e3
JC
1478
1479 if (pCtx == NULL) {
4a7b2d3c 1480 ALOGE("%s: Video context info must be supplied", __func__);
20d3e6e3
JC
1481 ret = VIDEO_ERROR_BADPARAM;
1482 goto EXIT;
1483 }
1484
800a8d75 1485 if (pCtx->bStreamonOutbuf == VIDEO_TRUE) {
38ef2572 1486 if (exynos_v4l2_streamoff(pCtx->hEnc, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) != 0) {
800a8d75
JC
1487 ALOGE("%s: Failed to streamoff for output buffer", __func__);
1488 ret = VIDEO_ERROR_APIFAIL;
1489 goto EXIT;
1490 }
1491 pCtx->bStreamonOutbuf = VIDEO_FALSE;
20d3e6e3
JC
1492 }
1493
38ef2572
JC
1494 for (i = 0; i < pCtx->nOutbufs; i++) {
1495 pCtx->pOutbuf[i].bQueued = VIDEO_FALSE;
1496 }
1497
20d3e6e3
JC
1498EXIT:
1499 return ret;
1500}
1501
1502/*
1503 * [Encoder Buffer OPS] Wait (Src)
1504 */
1505static ExynosVideoErrorType MFC_Encoder_Wait_Inbuf(void *pHandle)
1506{
1507 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
1508 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1509
1510 struct pollfd poll_events;
1511 int poll_state;
1512
1513 if (pCtx == NULL) {
4a7b2d3c 1514 ALOGE("%s: Video context info must be supplied", __func__);
20d3e6e3
JC
1515 ret = VIDEO_ERROR_BADPARAM;
1516 goto EXIT;
1517 }
1518
1519 poll_events.fd = pCtx->hEnc;
1520 poll_events.events = POLLOUT | POLLERR;
1521 poll_events.revents = 0;
1522
1523 do {
1524 poll_state = poll((struct pollfd*)&poll_events, 1, VIDEO_ENCODER_POLL_TIMEOUT);
1525 if (poll_state > 0) {
1526 if (poll_events.revents & POLLOUT) {
1527 break;
1528 } else {
4a7b2d3c 1529 ALOGE("%s: Poll return error", __func__);
20d3e6e3
JC
1530 ret = VIDEO_ERROR_POLL;
1531 break;
1532 }
1533 } else if (poll_state < 0) {
4a7b2d3c 1534 ALOGE("%s: Poll state error", __func__);
20d3e6e3
JC
1535 ret = VIDEO_ERROR_POLL;
1536 break;
1537 }
1538 } while (poll_state == 0);
1539
1540EXIT:
1541 return ret;
1542}
1543
1544/*
1545 * [Encoder Buffer OPS] Wait (Dst)
1546 */
1547static ExynosVideoErrorType MFC_Encoder_Wait_Outbuf(void *pHandle)
1548{
1549 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
1550 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1551
1552 struct pollfd poll_events;
1553 int poll_state;
1554 int bframe_count = 0; // FIXME
1555
1556 if (pCtx == NULL) {
4a7b2d3c 1557 ALOGE("%s: Video context info must be supplied", __func__);
20d3e6e3
JC
1558 ret = VIDEO_ERROR_BADPARAM;
1559 goto EXIT;
1560 }
1561
1562 poll_events.fd = pCtx->hEnc;
1563 poll_events.events = POLLIN | POLLERR;
1564 poll_events.revents = 0;
1565
1566 do {
1567 poll_state = poll((struct pollfd*)&poll_events, 1, VIDEO_ENCODER_POLL_TIMEOUT);
1568 if (poll_state > 0) {
1569 if (poll_events.revents & POLLIN) {
1570 break;
1571 } else {
4a7b2d3c 1572 ALOGE("%s: Poll return error", __func__);
20d3e6e3
JC
1573 ret = VIDEO_ERROR_POLL;
1574 break;
1575 }
1576 } else if (poll_state < 0) {
4a7b2d3c 1577 ALOGE("%s: Poll state error", __func__);
20d3e6e3
JC
1578 ret = VIDEO_ERROR_POLL;
1579 break;
1580 } else {
1581 bframe_count++; // FIXME
1582 }
1583 } while (poll_state == 0 && bframe_count < 5); // FIXME
1584
1585EXIT:
1586 return ret;
1587}
1588
38ef2572
JC
1589static ExynosVideoErrorType MFC_Encoder_Register_Inbuf(
1590 void *pHandle,
30e79fb1
SK
1591 ExynosVideoPlane *planes,
1592 int nPlanes)
38ef2572
JC
1593{
1594 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
1595 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1596 int nIndex;
1597
30e79fb1 1598 if ((pCtx == NULL) || (planes == NULL) || (nPlanes != VIDEO_ENCODER_INBUF_PLANES)) {
38ef2572
JC
1599 ALOGE("%s: input params must be supplied", __func__);
1600 ret = VIDEO_ERROR_BADPARAM;
1601 goto EXIT;
1602 }
1603
1604 for (nIndex = 0; nIndex < pCtx->nInbufs; nIndex++) {
1605 if (pCtx->pInbuf[nIndex].bRegistered == VIDEO_FALSE) {
30e79fb1
SK
1606 int plane;
1607 for (plane = 0; plane < nPlanes; plane++) {
1608 pCtx->pInbuf[nIndex].planes[plane].addr = planes[plane].addr;
1609 pCtx->pInbuf[nIndex].planes[plane].allocSize = planes[plane].allocSize;
1610 pCtx->pInbuf[nIndex].planes[plane].fd = planes[plane].fd;
1611 }
38ef2572
JC
1612 pCtx->pInbuf[nIndex].bRegistered = VIDEO_TRUE;
1613 break;
1614 }
1615 }
1616
1617 if (nIndex == pCtx->nInbufs) {
1618 ALOGE("%s: can not find non-registered input buffer", __func__);
1619 ret = VIDEO_ERROR_NOBUFFERS;
1620 }
1621
1622EXIT:
1623 return ret;
1624}
1625
1626static ExynosVideoErrorType MFC_Encoder_Register_Outbuf(
1627 void *pHandle,
30e79fb1
SK
1628 ExynosVideoPlane *planes,
1629 int nPlanes)
38ef2572
JC
1630{
1631 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
1632 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1633 int nIndex;
1634
30e79fb1
SK
1635 if ((pCtx == NULL) || (planes == NULL) || (nPlanes != VIDEO_ENCODER_OUTBUF_PLANES)) {
1636 ALOGE("%s: params must be supplied", __func__);
38ef2572
JC
1637 ret = VIDEO_ERROR_BADPARAM;
1638 goto EXIT;
1639 }
1640
1641 for (nIndex = 0; nIndex < pCtx->nOutbufs; nIndex++) {
1642 if (pCtx->pOutbuf[nIndex].bRegistered == VIDEO_FALSE) {
30e79fb1
SK
1643 int plane;
1644 for (plane = 0; plane < nPlanes; plane++) {
1645 pCtx->pOutbuf[nIndex].planes[plane].addr = planes[plane].addr;
1646 pCtx->pOutbuf[nIndex].planes[plane].allocSize = planes[plane].allocSize;
1647 pCtx->pOutbuf[nIndex].planes[plane].fd = planes[plane].fd;
1648 }
38ef2572
JC
1649 pCtx->pOutbuf[nIndex].bRegistered = VIDEO_TRUE;
1650 break;
1651 }
1652 }
1653
1654 if (nIndex == pCtx->nOutbufs) {
1655 ALOGE("%s: can not find non-registered output buffer", __func__);
1656 ret = VIDEO_ERROR_NOBUFFERS;
1657 }
1658
1659EXIT:
1660 return ret;
1661}
1662
1663static ExynosVideoErrorType MFC_Encoder_Clear_RegisteredBuffer_Inbuf(void *pHandle)
1664{
1665 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
1666 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1667 int nIndex = -1;
1668
1669 if (pCtx == NULL) {
1670 ALOGE("%s: Video context info must be supplied", __func__);
1671 ret = VIDEO_ERROR_BADPARAM;
1672 goto EXIT;
1673 }
1674
1675 for (nIndex = 0; nIndex < pCtx->nInbufs; nIndex++) {
30e79fb1
SK
1676 pCtx->pInbuf[nIndex].planes[0].addr = NULL;
1677 pCtx->pInbuf[nIndex].bRegistered = VIDEO_FALSE;
38ef2572
JC
1678 }
1679
1680EXIT:
1681 return ret;
1682}
1683
1684static ExynosVideoErrorType MFC_Encoder_Clear_RegisteredBuffer_Outbuf(void *pHandle)
1685{
1686 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
1687 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1688 int nIndex = -1;
1689
1690 if (pCtx == NULL) {
1691 ALOGE("%s: Video context info must be supplied", __func__);
1692 ret = VIDEO_ERROR_BADPARAM;
1693 goto EXIT;
1694 }
1695
1696 for (nIndex = 0; nIndex < pCtx->nOutbufs; nIndex++) {
30e79fb1
SK
1697 pCtx->pOutbuf[nIndex].planes[0].addr = NULL;
1698 pCtx->pOutbuf[nIndex].bRegistered = VIDEO_FALSE;
38ef2572
JC
1699 }
1700
1701EXIT:
1702 return ret;
1703}
1704
20d3e6e3 1705/*
30e79fb1 1706 * [Encoder Buffer OPS] Find (Input)
20d3e6e3
JC
1707 */
1708static int MFC_Encoder_Find_Inbuf(
38ef2572 1709 void *pHandle,
20d3e6e3
JC
1710 unsigned char *pBuffer)
1711{
1712 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
1713 int nIndex = -1;
1714
1715 if (pCtx == NULL) {
4a7b2d3c 1716 ALOGE("%s: Video context info must be supplied", __func__);
20d3e6e3
JC
1717 goto EXIT;
1718 }
1719
30e79fb1
SK
1720 for (nIndex = 0; nIndex < pCtx->nInbufs; nIndex++) {
1721 if (pCtx->pInbuf[nIndex].bQueued == VIDEO_FALSE) {
1722 if ((pBuffer == NULL) ||
1723 (pCtx->pInbuf[nIndex].planes[0].addr == pBuffer))
20d3e6e3
JC
1724 break;
1725 }
1726 }
1727
30e79fb1 1728 if (nIndex == pCtx->nInbufs)
20d3e6e3 1729 nIndex = -1;
20d3e6e3
JC
1730
1731EXIT:
1732 return nIndex;
1733}
1734
1735/*
30e79fb1 1736 * [Encoder Buffer OPS] Find (Outnput)
20d3e6e3
JC
1737 */
1738static int MFC_Encoder_Find_Outbuf(
38ef2572 1739 void *pHandle,
20d3e6e3
JC
1740 unsigned char *pBuffer)
1741{
1742 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
1743 int nIndex = -1;
1744
1745 if (pCtx == NULL) {
4a7b2d3c 1746 ALOGE("%s: Video context info must be supplied", __func__);
20d3e6e3
JC
1747 goto EXIT;
1748 }
1749
30e79fb1
SK
1750 for (nIndex = 0; nIndex < pCtx->nOutbufs; nIndex++) {
1751 if (pCtx->pOutbuf[nIndex].bQueued == VIDEO_FALSE) {
1752 if ((pBuffer == NULL) ||
1753 (pCtx->pOutbuf[nIndex].planes[0].addr == pBuffer))
20d3e6e3
JC
1754 break;
1755 }
1756 }
1757
30e79fb1 1758 if (nIndex == pCtx->nOutbufs)
20d3e6e3 1759 nIndex = -1;
20d3e6e3
JC
1760
1761EXIT:
1762 return nIndex;
1763}
1764
1765/*
30e79fb1 1766 * [Encoder Buffer OPS] Enqueue (Input)
20d3e6e3
JC
1767 */
1768static ExynosVideoErrorType MFC_Encoder_Enqueue_Inbuf(
38ef2572 1769 void *pHandle,
20d3e6e3
JC
1770 unsigned char *pBuffer[],
1771 unsigned int dataSize[],
1772 int nPlanes,
1773 void *pPrivate)
1774{
1775 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
1776 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
38ef2572 1777 pthread_mutex_t *pMutex = NULL;
20d3e6e3
JC
1778
1779 struct v4l2_plane planes[VIDEO_ENCODER_INBUF_PLANES];
1780 struct v4l2_buffer buf;
1781 int index, i;
1782
1783 if (pCtx == NULL) {
4a7b2d3c 1784 ALOGE("%s: Video context info must be supplied", __func__);
20d3e6e3
JC
1785 ret = VIDEO_ERROR_BADPARAM;
1786 goto EXIT;
1787 }
1788
38ef2572
JC
1789 if (VIDEO_ENCODER_INBUF_PLANES < nPlanes) {
1790 ALOGE("%s: Number of max planes : %d, nPlanes : %d", __func__,
1791 VIDEO_ENCODER_INBUF_PLANES, nPlanes);
1792 ret = VIDEO_ERROR_BADPARAM;
1793 goto EXIT;
1794 }
1795
20d3e6e3
JC
1796 memset(&buf, 0, sizeof(buf));
1797
1798 buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1799 buf.m.planes = planes;
1800 buf.length = VIDEO_ENCODER_INBUF_PLANES;
1801
30e79fb1
SK
1802 pMutex = (pthread_mutex_t*)pCtx->pInMutex;
1803 pthread_mutex_lock(pMutex);
38ef2572 1804 index = MFC_Encoder_Find_Inbuf(pCtx, pBuffer[0]);
20d3e6e3 1805 if (index == -1) {
30e79fb1
SK
1806 pthread_mutex_unlock(pMutex);
1807 ALOGE("%s: Failed to get index", __func__);
20d3e6e3
JC
1808 ret = VIDEO_ERROR_NOBUFFERS;
1809 goto EXIT;
1810 }
1811
1812 buf.index = index;
30e79fb1
SK
1813 pCtx->pInbuf[buf.index].bQueued = VIDEO_TRUE;
1814 pthread_mutex_unlock(pMutex);
20d3e6e3
JC
1815
1816 if (pCtx->bShareInbuf == VIDEO_TRUE) {
1f0d5e30 1817 buf.memory = pCtx->nMemoryType;
20d3e6e3 1818 for (i = 0; i < nPlanes; i++) {
30e79fb1 1819 /* V4L2_MEMORY_USERPTR */
20d3e6e3 1820 buf.m.planes[i].m.userptr = (unsigned long)pBuffer[i];
30e79fb1
SK
1821 /* V4L2_MEMORY_DMABUF */
1822 buf.m.planes[i].m.fd = pCtx->pInbuf[buf.index].planes[i].fd;
38ef2572 1823 buf.m.planes[i].length = pCtx->pInbuf[index].planes[i].allocSize;
20d3e6e3 1824 buf.m.planes[i].bytesused = dataSize[i];
20d3e6e3
JC
1825 }
1826 } else {
1827 buf.memory = V4L2_MEMORY_MMAP;
1828 for (i = 0; i < nPlanes; i++)
1829 buf.m.planes[i].bytesused = dataSize[i];
1830 }
1831
30e79fb1
SK
1832 if (exynos_v4l2_qbuf(pCtx->hEnc, &buf) != 0) {
1833 ALOGE("%s: Failed to enqueue input buffer", __func__);
1834 pCtx->pInbuf[buf.index].bQueued = VIDEO_FALSE;
20d3e6e3
JC
1835 ret = VIDEO_ERROR_APIFAIL;
1836 goto EXIT;
1837 }
30e79fb1
SK
1838
1839 pCtx->pInbuf[buf.index].pPrivate = pPrivate;
20d3e6e3
JC
1840
1841EXIT:
1842 return ret;
1843}
1844
1845/*
30e79fb1 1846 * [Encoder Buffer OPS] Enqueue (Output)
20d3e6e3
JC
1847 */
1848static ExynosVideoErrorType MFC_Encoder_Enqueue_Outbuf(
38ef2572 1849 void *pHandle,
20d3e6e3
JC
1850 unsigned char *pBuffer[],
1851 unsigned int dataSize[],
1852 int nPlanes,
1853 void *pPrivate)
1854{
1855 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
1856 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
38ef2572 1857 pthread_mutex_t *pMutex = NULL;
20d3e6e3
JC
1858
1859 struct v4l2_plane planes[VIDEO_ENCODER_OUTBUF_PLANES];
1860 struct v4l2_buffer buf;
1861 int i, index;
1862
1863 if (pCtx == NULL) {
4a7b2d3c 1864 ALOGE("%s: Video context info must be supplied", __func__);
20d3e6e3
JC
1865 ret = VIDEO_ERROR_BADPARAM;
1866 goto EXIT;
1867 }
1868
800a8d75
JC
1869 if (VIDEO_ENCODER_OUTBUF_PLANES < nPlanes) {
1870 ALOGE("%s: Number of max planes : %d, nPlanes : %d", __func__,
1871 VIDEO_ENCODER_OUTBUF_PLANES, nPlanes);
1872 ret = VIDEO_ERROR_BADPARAM;
1873 goto EXIT;
1874 }
1875
20d3e6e3 1876 memset(&buf, 0, sizeof(buf));
20d3e6e3
JC
1877 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1878 buf.m.planes = planes;
1879 buf.length = VIDEO_ENCODER_OUTBUF_PLANES;
1880
30e79fb1
SK
1881 pMutex = (pthread_mutex_t*)pCtx->pOutMutex;
1882 pthread_mutex_lock(pMutex);
38ef2572 1883 index = MFC_Encoder_Find_Outbuf(pCtx, pBuffer[0]);
20d3e6e3 1884 if (index == -1) {
30e79fb1 1885 pthread_mutex_unlock(pMutex);
38ef2572 1886 ALOGE("%s: Failed to get index", __func__);
20d3e6e3
JC
1887 ret = VIDEO_ERROR_NOBUFFERS;
1888 goto EXIT;
1889 }
20d3e6e3 1890 buf.index = index;
30e79fb1
SK
1891 pCtx->pOutbuf[buf.index].bQueued = VIDEO_TRUE;
1892 pthread_mutex_unlock(pMutex);
20d3e6e3
JC
1893
1894 if (pCtx->bShareOutbuf == VIDEO_TRUE) {
1f0d5e30 1895 buf.memory = pCtx->nMemoryType;
20d3e6e3 1896 for (i = 0; i < nPlanes; i++) {
30e79fb1
SK
1897 /* V4L2_MEMORY_USERPTR */
1898 buf.m.planes[i].m.userptr = (unsigned long)pBuffer[i];
1899 /* V4L2_MEMORY_DMABUF */
1900 buf.m.planes[i].m.fd = pCtx->pOutbuf[index].planes[i].fd;
38ef2572 1901 buf.m.planes[i].length = pCtx->pOutbuf[index].planes[i].allocSize;
20d3e6e3 1902 buf.m.planes[i].bytesused = dataSize[i];
20d3e6e3
JC
1903 }
1904 } else {
1905 buf.memory = V4L2_MEMORY_MMAP;
1906 }
1907
30e79fb1
SK
1908 if (exynos_v4l2_qbuf(pCtx->hEnc, &buf) != 0) {
1909 ALOGE("%s: Failed to enqueue output buffer", __func__);
1910 pCtx->pOutbuf[buf.index].bQueued = VIDEO_FALSE;
20d3e6e3
JC
1911 ret = VIDEO_ERROR_APIFAIL;
1912 goto EXIT;
1913 }
30e79fb1
SK
1914
1915 pCtx->pOutbuf[buf.index].pPrivate = pPrivate;
20d3e6e3
JC
1916
1917EXIT:
1918 return ret;
1919}
1920
800a8d75 1921/*
30e79fb1 1922 * [Encoder Buffer OPS] Enqueue All (Output)
800a8d75
JC
1923 */
1924static ExynosVideoErrorType MFC_Encoder_Enqueue_All_Outbuf(void *pHandle)
1925{
1926 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
1927 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1928
38ef2572
JC
1929 unsigned char *pBuffer[VIDEO_BUFFER_MAX_PLANES] = {NULL, };
1930 unsigned int dataSize[VIDEO_BUFFER_MAX_PLANES] = {0, };
1931
800a8d75
JC
1932 int i;
1933
1934 if (pCtx == NULL) {
1935 ALOGE("%s: Video context info must be supplied", __func__);
1936 ret = VIDEO_ERROR_BADPARAM;
1937 goto EXIT;
1938 }
1939
38ef2572
JC
1940 for (i = 0; i < pCtx->nOutbufs; i++) {
1941 ret = MFC_Encoder_Enqueue_Outbuf(pCtx, pBuffer, dataSize, 1, NULL);
1942 if (ret != VIDEO_ERROR_NONE)
1943 goto EXIT;
1944 }
800a8d75
JC
1945
1946EXIT:
1947 return ret;
1948}
1949
20d3e6e3 1950/*
30e79fb1 1951 * [Encoder Buffer OPS] Dequeue (Input)
20d3e6e3
JC
1952 */
1953static ExynosVideoBuffer *MFC_Encoder_Dequeue_Inbuf(void *pHandle)
1954{
38ef2572
JC
1955 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
1956 ExynosVideoBuffer *pInbuf = NULL;
20d3e6e3
JC
1957
1958 struct v4l2_buffer buf;
1959
1960 if (pCtx == NULL) {
4a7b2d3c 1961 ALOGE("%s: Video context info must be supplied", __func__);
20d3e6e3
JC
1962 goto EXIT;
1963 }
1964
800a8d75 1965 if (pCtx->bStreamonInbuf == VIDEO_FALSE) {
30e79fb1 1966 pInbuf = NULL;
800a8d75
JC
1967 goto EXIT;
1968 }
1969
20d3e6e3
JC
1970 memset(&buf, 0, sizeof(buf));
1971
1972 buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1973
1974 if (pCtx->bShareInbuf == VIDEO_TRUE)
1f0d5e30 1975 buf.memory = pCtx->nMemoryType;
20d3e6e3
JC
1976 else
1977 buf.memory = V4L2_MEMORY_MMAP;
1978
38ef2572 1979 if (exynos_v4l2_dqbuf(pCtx->hEnc, &buf) != 0) {
30e79fb1 1980 pInbuf = NULL;
20d3e6e3
JC
1981 goto EXIT;
1982 }
1983
38ef2572 1984 pInbuf = &pCtx->pInbuf[buf.index];
30e79fb1 1985 pCtx->pInbuf[buf.index].bQueued = VIDEO_FALSE;
38ef2572 1986
20d3e6e3 1987EXIT:
38ef2572 1988 return pInbuf;
20d3e6e3
JC
1989}
1990
1991/*
30e79fb1 1992 * [Encoder Buffer OPS] Dequeue (Output)
20d3e6e3
JC
1993 */
1994static ExynosVideoBuffer *MFC_Encoder_Dequeue_Outbuf(void *pHandle)
1995{
1996 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
1997 ExynosVideoBuffer *pOutbuf = NULL;
1998
1999 struct v4l2_buffer buf;
38ef2572 2000 struct v4l2_plane planes[VIDEO_ENCODER_OUTBUF_PLANES];
20d3e6e3
JC
2001 int value;
2002
2003 if (pCtx == NULL) {
4a7b2d3c 2004 ALOGE("%s: Video context info must be supplied", __func__);
20d3e6e3
JC
2005 goto EXIT;
2006 }
2007
800a8d75 2008 if (pCtx->bStreamonOutbuf == VIDEO_FALSE) {
30e79fb1 2009 pOutbuf = NULL;
20d3e6e3
JC
2010 goto EXIT;
2011 }
2012
2013 memset(&buf, 0, sizeof(buf));
20d3e6e3
JC
2014 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2015 buf.m.planes = planes;
2016 buf.length = 1;
2017
2018 if (pCtx->bShareOutbuf == VIDEO_TRUE)
1f0d5e30 2019 buf.memory = pCtx->nMemoryType;
20d3e6e3
JC
2020 else
2021 buf.memory = V4L2_MEMORY_MMAP;
2022
2023 /* no error case for output buffer dequeue in encoder */
38ef2572 2024 if (exynos_v4l2_dqbuf(pCtx->hEnc, &buf) != 0) {
800a8d75
JC
2025 goto EXIT;
2026 }
20d3e6e3
JC
2027
2028 pOutbuf = &pCtx->pOutbuf[buf.index];
2029 pOutbuf->planes[0].dataSize = buf.m.planes[0].bytesused;
2030
2031 switch (buf.flags & (0x7 << 3)) {
2032 case V4L2_BUF_FLAG_KEYFRAME:
2033 pOutbuf->frameType = VIDEO_FRAME_I;
2034 break;
2035 case V4L2_BUF_FLAG_PFRAME:
2036 pOutbuf->frameType = VIDEO_FRAME_P;
2037 break;
2038 case V4L2_BUF_FLAG_BFRAME:
2039 pOutbuf->frameType = VIDEO_FRAME_B;
2040 break;
2041 default:
4a7b2d3c 2042 ALOGI("%s: encoded frame type is = %d",__func__, (buf.flags & (0x7 << 3)));
20d3e6e3
JC
2043 pOutbuf->frameType = VIDEO_FRAME_OTHERS;
2044 break;
2045 };
2046
2047 pOutbuf->bQueued = VIDEO_FALSE;
2048
2049EXIT:
2050 return pOutbuf;
2051}
2052
38ef2572
JC
2053static ExynosVideoErrorType MFC_Encoder_Clear_Queued_Inbuf(void *pHandle)
2054{
2055 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
2056 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
2057 int i = 0;
2058
2059 if (pCtx == NULL) {
2060 ALOGE("%s: Video context info must be supplied", __func__);
2061 ret = VIDEO_ERROR_BADPARAM;
2062 goto EXIT;
2063 }
2064
30e79fb1 2065 for (i = 0; i < pCtx->nInbufs; i++) {
38ef2572
JC
2066 pCtx->pInbuf[i].bQueued = VIDEO_FALSE;
2067 }
2068
2069EXIT:
2070 return ret;
2071}
2072
2073static ExynosVideoErrorType MFC_Encoder_Clear_Queued_Outbuf(void *pHandle)
2074{
2075 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
2076 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
2077 int i = 0;
2078
2079 if (pCtx == NULL) {
2080 ALOGE("%s: Video context info must be supplied", __func__);
2081 ret = VIDEO_ERROR_BADPARAM;
2082 goto EXIT;
2083 }
2084
2085 for (i = 0; i < pCtx->nOutbufs; i++) {
2086 pCtx->pOutbuf[i].bQueued = VIDEO_FALSE;
2087 }
2088
2089EXIT:
2090 return ret;
2091}
2092
5b46229d
SK
2093
2094/*
2095 * [Encoder Buffer OPS] FindIndex (Input)
2096 */
2097static int MFC_Encoder_FindEmpty_Inbuf(void *pHandle)
2098{
2099 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
2100 int nIndex = -1;
2101
2102 if (pCtx == NULL) {
2103 ALOGE("%s: Video context info must be supplied", __func__);
2104 goto EXIT;
2105 }
2106
2107 for (nIndex = 0; nIndex < pCtx->nInbufs; nIndex++) {
2108 if (pCtx->pInbuf[nIndex].bQueued == VIDEO_FALSE) {
2109 break;
2110 }
2111 }
2112
2113 if (nIndex == pCtx->nInbufs)
2114 nIndex = -1;
2115
2116EXIT:
2117 return nIndex;
2118}
2119
2120/*
2121 * [Encoder Buffer OPS] ExtensionEnqueue (Input)
2122 */
2123static ExynosVideoErrorType MFC_Encoder_ExtensionEnqueue_Inbuf(
2124 void *pHandle,
2125 unsigned char *pBuffer[],
2126 unsigned int *pFd[],
2127 unsigned int allocLen[],
2128 unsigned int dataSize[],
2129 int nPlanes,
2130 void *pPrivate)
2131{
2132 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
2133 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
2134 pthread_mutex_t *pMutex = NULL;
2135
2136 struct v4l2_plane planes[VIDEO_ENCODER_INBUF_PLANES];
2137 struct v4l2_buffer buf;
2138 int index, i;
2139
2140 if (pCtx == NULL) {
2141 ALOGE("%s: Video context info must be supplied", __func__);
2142 ret = VIDEO_ERROR_BADPARAM;
2143 goto EXIT;
2144 }
2145
2146 if (VIDEO_ENCODER_INBUF_PLANES < nPlanes) {
2147 ALOGE("%s: Number of max planes : %d, nPlanes : %d", __func__,
2148 VIDEO_ENCODER_INBUF_PLANES, nPlanes);
2149 ret = VIDEO_ERROR_BADPARAM;
2150 goto EXIT;
2151 }
2152
2153 memset(&buf, 0, sizeof(buf));
2154
2155 buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
2156 buf.m.planes = planes;
2157 buf.length = VIDEO_ENCODER_INBUF_PLANES;
2158
2159 pMutex = (pthread_mutex_t*)pCtx->pInMutex;
2160 pthread_mutex_lock(pMutex);
2161 index = MFC_Encoder_FindEmpty_Inbuf(pCtx);
2162 if (index == -1) {
2163 pthread_mutex_unlock(pMutex);
2164 ALOGE("%s: Failed to get index", __func__);
2165 ret = VIDEO_ERROR_NOBUFFERS;
2166 goto EXIT;
2167 }
2168
2169 buf.index = index;
2170
2171 pCtx->pInbuf[buf.index].bQueued = VIDEO_TRUE;
2172 pthread_mutex_unlock(pMutex);
2173
2174 buf.memory = pCtx->nMemoryType;
2175 for (i = 0; i < nPlanes; i++) {
2176 /* V4L2_MEMORY_DMABUF */
2177 buf.m.planes[i].m.fd = (unsigned int)pFd[i];
2178 buf.m.planes[i].length = allocLen[i];
2179 buf.m.planes[i].bytesused = dataSize[i];
2180
2181 /* Temporary storage for Dequeue */
2182 pCtx->pInbuf[buf.index].planes[i].addr = (unsigned long)pBuffer[i];
2183 pCtx->pInbuf[buf.index].planes[i].fd = (unsigned int)pFd[i];
2184 pCtx->pInbuf[buf.index].planes[i].allocSize = allocLen[i];
2185 }
2186
2187 if (exynos_v4l2_qbuf(pCtx->hEnc, &buf) != 0) {
2188 ALOGE("%s: Failed to enqueue input buffer", __func__);
2189 pthread_mutex_lock(pMutex);
2190 pCtx->pInbuf[buf.index].bQueued = VIDEO_FALSE;
2191 pthread_mutex_unlock(pMutex);
2192 ret = VIDEO_ERROR_APIFAIL;
2193 goto EXIT;
2194 }
2195
2196 pCtx->pInbuf[buf.index].pPrivate = pPrivate;
2197
2198EXIT:
2199 return ret;
2200}
2201
2202/*
2203 * [Encoder Buffer OPS] ExtensionDequeue (Input)
2204 */
2205static ExynosVideoErrorType MFC_Encoder_ExtensionDequeue_Inbuf(void *pHandle, ExynosVideoBuffer *pVideoBuffer)
2206{
2207 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
2208 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
2209 pthread_mutex_t *pMutex = NULL;
2210
2211 struct v4l2_buffer buf;
2212
2213 if (pCtx == NULL) {
2214 ALOGE("%s: Video context info must be supplied", __func__);
2215 ret = VIDEO_ERROR_BADPARAM;
2216 goto EXIT;
2217 }
2218
2219 if (pCtx->bStreamonInbuf == VIDEO_FALSE) {
2220 ret = VIDEO_ERROR_APIFAIL;
2221 goto EXIT;
2222 }
2223
2224 memset(&buf, 0, sizeof(buf));
2225 buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
2226 buf.memory = pCtx->nMemoryType;
2227 if (exynos_v4l2_dqbuf(pCtx->hEnc, &buf) != 0) {
2228 ALOGE("%s: Failed to dequeue input buffer", __func__);
2229 ret = VIDEO_ERROR_APIFAIL;
2230 goto EXIT;
2231 }
2232
2233 memcpy(pVideoBuffer, &pCtx->pInbuf[buf.index], sizeof(ExynosVideoBuffer));
2234 pMutex = (pthread_mutex_t*)pCtx->pInMutex;
2235 pthread_mutex_lock(pMutex);
2236 pCtx->pInbuf[buf.index].bQueued = VIDEO_FALSE;
2237 pthread_mutex_unlock(pMutex);
2238
2239EXIT:
2240 return ret;
2241}
2242
2243
20d3e6e3
JC
2244/*
2245 * [Encoder OPS] Common
2246 */
2247static ExynosVideoEncOps defEncOps = {
38ef2572
JC
2248 .nSize = 0,
2249 .Init = MFC_Encoder_Init,
2250 .Finalize = MFC_Encoder_Finalize,
2251 .Set_EncParam = MFC_Encoder_Set_EncParam,
2252 .Set_FrameType = MFC_Encoder_Set_FrameType,
2253 .Set_FrameRate = MFC_Encoder_Set_FrameRate,
2254 .Set_BitRate = MFC_Encoder_Set_BitRate,
2255 .Set_FrameSkip = MFC_Encoder_Set_FrameSkip,
2256 .Set_IDRPeriod = MFC_Encoder_Set_IDRPeriod,
2257 .Set_FrameTag = MFC_Encoder_Set_FrameTag,
2258 .Get_FrameTag = MFC_Encoder_Get_FrameTag,
20d3e6e3
JC
2259};
2260
2261/*
2262 * [Encoder Buffer OPS] Input
2263 */
2264static ExynosVideoEncBufferOps defInbufOps = {
38ef2572
JC
2265 .nSize = 0,
2266 .Enable_Cacheable = MFC_Encoder_Enable_Cacheable_Inbuf,
2267 .Set_Shareable = MFC_Encoder_Set_Shareable_Inbuf,
2268 .Get_Buffer = NULL,
2269 .Set_Geometry = MFC_Encoder_Set_Geometry_Inbuf,
2270 .Get_Geometry = MFC_Encoder_Get_Geometry_Inbuf,
2271 .Setup = MFC_Encoder_Setup_Inbuf,
2272 .Run = MFC_Encoder_Run_Inbuf,
2273 .Stop = MFC_Encoder_Stop_Inbuf,
2274 .Enqueue = MFC_Encoder_Enqueue_Inbuf,
2275 .Enqueue_All = NULL,
2276 .Dequeue = MFC_Encoder_Dequeue_Inbuf,
2277 .Register = MFC_Encoder_Register_Inbuf,
2278 .Clear_RegisteredBuffer = MFC_Encoder_Clear_RegisteredBuffer_Inbuf,
2279 .Clear_Queue = MFC_Encoder_Clear_Queued_Inbuf,
5b46229d
SK
2280 .ExtensionEnqueue = MFC_Encoder_ExtensionEnqueue_Inbuf,
2281 .ExtensionDequeue = MFC_Encoder_ExtensionDequeue_Inbuf,
20d3e6e3
JC
2282};
2283
2284/*
2285 * [Encoder Buffer OPS] Output
2286 */
2287static ExynosVideoEncBufferOps defOutbufOps = {
38ef2572
JC
2288 .nSize = 0,
2289 .Enable_Cacheable = MFC_Encoder_Enable_Cacheable_Outbuf,
2290 .Set_Shareable = MFC_Encoder_Set_Shareable_Outbuf,
2291 .Get_Buffer = MFC_Encoder_Get_Buffer_Outbuf,
2292 .Set_Geometry = MFC_Encoder_Set_Geometry_Outbuf,
2293 .Get_Geometry = MFC_Encoder_Get_Geometry_Outbuf,
2294 .Setup = MFC_Encoder_Setup_Outbuf,
2295 .Run = MFC_Encoder_Run_Outbuf,
2296 .Stop = MFC_Encoder_Stop_Outbuf,
2297 .Enqueue = MFC_Encoder_Enqueue_Outbuf,
30e79fb1 2298 .Enqueue_All = NULL,
38ef2572
JC
2299 .Dequeue = MFC_Encoder_Dequeue_Outbuf,
2300 .Register = MFC_Encoder_Register_Outbuf,
2301 .Clear_RegisteredBuffer = MFC_Encoder_Clear_RegisteredBuffer_Outbuf,
2302 .Clear_Queue = MFC_Encoder_Clear_Queued_Outbuf,
20d3e6e3
JC
2303};
2304
2305int Exynos_Video_Register_Encoder(
2306 ExynosVideoEncOps *pEncOps,
2307 ExynosVideoEncBufferOps *pInbufOps,
2308 ExynosVideoEncBufferOps *pOutbufOps)
2309{
2310 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
2311
2312 if ((pEncOps == NULL) || (pInbufOps == NULL) || (pOutbufOps == NULL)) {
2313 ret = VIDEO_ERROR_BADPARAM;
2314 goto EXIT;
2315 }
2316
2317 defEncOps.nSize = sizeof(defEncOps);
2318 defInbufOps.nSize = sizeof(defInbufOps);
2319 defOutbufOps.nSize = sizeof(defOutbufOps);
2320
2321 memcpy((char *)pEncOps + sizeof(pEncOps->nSize), (char *)&defEncOps + sizeof(defEncOps.nSize),
2322 pEncOps->nSize - sizeof(pEncOps->nSize));
2323
2324 memcpy((char *)pInbufOps + sizeof(pInbufOps->nSize), (char *)&defInbufOps + sizeof(defInbufOps.nSize),
2325 pInbufOps->nSize - sizeof(pInbufOps->nSize));
2326
2327 memcpy((char *)pOutbufOps + sizeof(pOutbufOps->nSize), (char *)&defOutbufOps + sizeof(defOutbufOps.nSize),
2328 pOutbufOps->nSize - sizeof(pOutbufOps->nSize));
2329
2330EXIT:
2331 return ret;
2332}