12636726c85c3f9d50f365b82e87d9e84f32fd28
[GitHub/LineageOS/android_hardware_samsung_slsi_exynos5.git] / exynos_omx / codecs / exynos_codecs / video / exynos5 / mfc_v4l2 / enc / src / ExynosVideoEncoder.c
1 /*
2 *
3 * Copyright 2012 Samsung Electronics S.LSI Co. LTD
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 /*
19 * @file ExynosVideoEncoder.c
20 * @brief
21 * @author Hyeyeon Chung (hyeon.chung@samsung.com)
22 * @author Jinsung Yang (jsgood.yang@samsung.com)
23 * @author Yunji Kim (yunji.kim@samsung.com)
24 * @version 1.0.0
25 * @history
26 * 2012.02.09: Initial Version
27 */
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <unistd.h>
32 #include <string.h>
33 #include <fcntl.h>
34
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <sys/ioctl.h>
38 #include <sys/mman.h>
39 #include <pthread.h>
40
41 #include <sys/poll.h>
42
43 #include "ExynosVideoApi.h"
44 #include "ExynosVideoEnc.h"
45
46 /* #define LOG_NDEBUG 0 */
47 #define LOG_TAG "ExynosVideoEncoder"
48 #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
55 /*
56 * [Common] __CodingType_To_V4L2PixelFormat
57 */
58 static unsigned int __CodingType_To_V4L2PixelFormat(ExynosVideoCodingType codingType)
59 {
60 unsigned int pixelformat = V4L2_PIX_FMT_H264;
61
62 switch (codingType) {
63 case VIDEO_CODING_AVC:
64 pixelformat = V4L2_PIX_FMT_H264;
65 break;
66 case VIDEO_CODING_MPEG4:
67 pixelformat = V4L2_PIX_FMT_MPEG4;
68 break;
69 case VIDEO_CODING_VP8:
70 pixelformat = V4L2_PIX_FMT_VP8;
71 break;
72 case VIDEO_CODING_H263:
73 pixelformat = V4L2_PIX_FMT_H263;
74 break;
75 case VIDEO_CODING_VC1:
76 pixelformat = V4L2_PIX_FMT_VC1_ANNEX_G;
77 break;
78 case VIDEO_CODING_VC1_RCV:
79 pixelformat = V4L2_PIX_FMT_VC1_ANNEX_L;
80 break;
81 case VIDEO_CODING_MPEG2:
82 pixelformat = V4L2_PIX_FMT_MPEG2;
83 break;
84 default:
85 pixelformat = V4L2_PIX_FMT_H264;
86 break;
87 }
88
89 return pixelformat;
90 }
91
92 /*
93 * [Common] __ColorFormatType_To_V4L2PixelFormat
94 */
95 static unsigned int __ColorFormatType_To_V4L2PixelFormat(ExynosVideoColorFormatType colorFormatType)
96 {
97 unsigned int pixelformat = V4L2_PIX_FMT_NV12M;
98
99 switch (colorFormatType) {
100 case VIDEO_COLORFORMAT_NV12_TILED:
101 pixelformat = V4L2_PIX_FMT_NV12MT_16X16;
102 break;
103 case VIDEO_COLORFORMAT_NV21:
104 pixelformat = V4L2_PIX_FMT_NV21M;
105 break;
106 case VIDEO_COLORFORMAT_NV12:
107 default:
108 pixelformat = V4L2_PIX_FMT_NV12M;
109 break;
110 }
111
112 return pixelformat;
113 }
114
115 /*
116 * [Encoder OPS] Init
117 */
118 static void *MFC_Encoder_Init(int nMemoryType)
119 {
120 ExynosVideoEncContext *pCtx = NULL;
121 pthread_mutex_t *pMutex = NULL;
122 int needCaps = (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING);
123
124 pCtx = (ExynosVideoEncContext *)malloc(sizeof(*pCtx));
125 if (pCtx == NULL) {
126 ALOGE("%s: Failed to allocate encoder context buffer", __func__);
127 goto EXIT_ALLOC_FAIL;
128 }
129
130 memset(pCtx, 0, sizeof(*pCtx));
131
132 pCtx->hEnc = exynos_v4l2_open_devname(VIDEO_ENCODER_NAME, O_RDWR, 0);
133 if (pCtx->hEnc < 0) {
134 ALOGE("%s: Failed to open encoder device", __func__);
135 goto EXIT_OPEN_FAIL;
136 }
137
138 if (!exynos_v4l2_querycap(pCtx->hEnc, needCaps)) {
139 ALOGE("%s: Failed to querycap", __func__);
140 goto EXIT_QUERYCAP_FAIL;
141 }
142
143 pCtx->bStreamonInbuf = VIDEO_FALSE;
144 pCtx->bStreamonOutbuf = VIDEO_FALSE;
145
146 pCtx->nMemoryType = nMemoryType;
147
148 pMutex = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t));
149 if (pMutex == NULL) {
150 ALOGE("%s: Failed to allocate mutex about input buffer", __func__);
151 goto EXIT_QUERYCAP_FAIL;
152 }
153 if (pthread_mutex_init(pMutex, NULL) != 0) {
154 free(pMutex);
155 goto EXIT_QUERYCAP_FAIL;
156 }
157 pCtx->pInMutex = (void*)pMutex;
158
159 pMutex = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t));
160 if (pMutex == NULL) {
161 ALOGE("%s: Failed to allocate mutex about output buffer", __func__);
162 goto EXIT_QUERYCAP_FAIL;
163 }
164 if (pthread_mutex_init(pMutex, NULL) != 0) {
165 free(pMutex);
166 goto EXIT_QUERYCAP_FAIL;
167 }
168 pCtx->pOutMutex = (void*)pMutex;
169
170 return (void *)pCtx;
171
172 EXIT_QUERYCAP_FAIL:
173 if (pCtx->pInMutex != NULL) {
174 pthread_mutex_destroy(pCtx->pInMutex);
175 free(pCtx->pInMutex);
176 }
177
178 if (pCtx->pOutMutex != NULL) {
179 pthread_mutex_destroy(pCtx->pOutMutex);
180 free(pCtx->pOutMutex);
181 }
182
183 close(pCtx->hEnc);
184
185 EXIT_OPEN_FAIL:
186 free(pCtx);
187
188 EXIT_ALLOC_FAIL:
189 return NULL;
190 }
191
192 /*
193 * [Encoder OPS] Finalize
194 */
195 static ExynosVideoErrorType MFC_Encoder_Finalize(void *pHandle)
196 {
197 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
198 ExynosVideoPlane *pVideoPlane = NULL;
199 pthread_mutex_t *pMutex = NULL;
200 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
201 int i, j;
202
203 if (pCtx == NULL) {
204 ALOGE("%s: Video context info must be supplied", __func__);
205 ret = VIDEO_ERROR_BADPARAM;
206 goto EXIT;
207 }
208
209 if (pCtx->pOutMutex != NULL) {
210 pMutex = (pthread_mutex_t*)pCtx->pOutMutex;
211 pthread_mutex_destroy(pMutex);
212 free(pMutex);
213 pCtx->pOutMutex = NULL;
214 }
215
216 if (pCtx->pInMutex != NULL) {
217 pMutex = (pthread_mutex_t*)pCtx->pInMutex;
218 pthread_mutex_destroy(pMutex);
219 free(pMutex);
220 pCtx->pInMutex = NULL;
221 }
222
223 if (pCtx->bShareInbuf == VIDEO_FALSE) {
224 for (i = 0; i < pCtx->nInbufs; i++) {
225 for (j = 0; j < VIDEO_ENCODER_INBUF_PLANES; j++) {
226 pVideoPlane = &pCtx->pInbuf[i].planes[j];
227 if (pVideoPlane->addr != NULL) {
228 munmap(pVideoPlane->addr, pVideoPlane->allocSize);
229 pVideoPlane->addr = NULL;
230 pVideoPlane->allocSize = 0;
231 pVideoPlane->dataSize = 0;
232 }
233
234 pCtx->pInbuf[i].pGeometry = NULL;
235 pCtx->pInbuf[i].bQueued = VIDEO_FALSE;
236 pCtx->pInbuf[i].bRegistered = VIDEO_FALSE;
237 }
238 }
239 }
240
241 if (pCtx->bShareOutbuf == VIDEO_FALSE) {
242 for (i = 0; i < pCtx->nOutbufs; i++) {
243 for (j = 0; j < VIDEO_ENCODER_OUTBUF_PLANES; j++) {
244 pVideoPlane = &pCtx->pOutbuf[i].planes[j];
245 if (pVideoPlane->addr != NULL) {
246 munmap(pVideoPlane->addr, pVideoPlane->allocSize);
247 pVideoPlane->addr = NULL;
248 pVideoPlane->allocSize = 0;
249 pVideoPlane->dataSize = 0;
250 }
251
252 pCtx->pOutbuf[i].pGeometry = NULL;
253 pCtx->pOutbuf[i].bQueued = VIDEO_FALSE;
254 pCtx->pOutbuf[i].bRegistered = VIDEO_FALSE;
255 }
256 }
257 }
258
259 if (pCtx->pInbuf != NULL)
260 free(pCtx->pInbuf);
261
262 if (pCtx->pOutbuf != NULL)
263 free(pCtx->pOutbuf);
264
265 if (pCtx->hEnc > 0)
266 close(pCtx->hEnc);
267
268 free(pCtx);
269
270 EXIT:
271 return ret;
272 }
273
274 /*
275 * [Encoder OPS] Set Extended Control
276 */
277 static ExynosVideoErrorType MFC_Encoder_Set_EncParam (
278 void *pHandle,
279 ExynosVideoEncParam *pEncParam)
280 {
281 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
282 ExynosVideoEncInitParam *pInitParam = NULL;
283 ExynosVideoEncCommonParam *pCommonParam = NULL;
284
285 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
286
287 int i;
288 struct v4l2_ext_control ext_ctrl[MAX_CTRL_NUM];
289 struct v4l2_ext_controls ext_ctrls;
290
291 if ((pCtx == NULL) || (pEncParam == NULL)) {
292 ALOGE("%s: Video context info must be supplied", __func__);
293 ret = VIDEO_ERROR_BADPARAM;
294 goto EXIT;
295 }
296
297 pInitParam = &pEncParam->initParam;
298 pCommonParam = &pEncParam->commonParam;
299
300 /* common parameters */
301 ext_ctrl[0].id = V4L2_CID_MPEG_VIDEO_GOP_SIZE;
302 ext_ctrl[0].value = pCommonParam->IDRPeriod;
303 ext_ctrl[1].id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE;
304 ext_ctrl[1].value = pCommonParam->SliceMode; /* 0: one, 1: fixed #mb, 3: fixed #bytes */
305 ext_ctrl[2].id = V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB;
306 ext_ctrl[2].value = pCommonParam->RandomIntraMBRefresh;
307 ext_ctrl[3].id = V4L2_CID_MPEG_MFC51_VIDEO_PADDING;
308 ext_ctrl[3].value = pCommonParam->PadControlOn;
309 ext_ctrl[4].id = V4L2_CID_MPEG_MFC51_VIDEO_PADDING_YUV;
310 ext_ctrl[4].value = pCommonParam->CrPadVal;
311 ext_ctrl[4].value |= (pCommonParam->CbPadVal << 8);
312 ext_ctrl[4].value |= (pCommonParam->LumaPadVal << 16);
313 ext_ctrl[5].id = V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE;
314 ext_ctrl[5].value = pCommonParam->EnableFRMRateControl;
315 ext_ctrl[6].id = V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE;
316 ext_ctrl[6].value = pCommonParam->EnableMBRateControl;
317 ext_ctrl[7].id = V4L2_CID_MPEG_VIDEO_BITRATE;
318
319 /* FIXME temporary fix */
320 if (pCommonParam->Bitrate)
321 ext_ctrl[7].value = pCommonParam->Bitrate;
322 else
323 ext_ctrl[7].value = 1; /* just for testing Movie studio */
324
325 /* codec specific parameters */
326 switch (pEncParam->eCompressionFormat) {
327 case VIDEO_CODING_AVC:
328 {
329 ExynosVideoEncH264Param *pH264Param = &pEncParam->codecParam.h264;
330
331 /* common parameters but id is depends on codec */
332 ext_ctrl[8].id = V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP;
333 ext_ctrl[8].value = pCommonParam->FrameQp;
334 ext_ctrl[9].id = V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP;
335 ext_ctrl[9].value = pCommonParam->FrameQp_P;
336 ext_ctrl[10].id = V4L2_CID_MPEG_VIDEO_H264_MAX_QP;
337 ext_ctrl[10].value = pCommonParam->QSCodeMax;
338 ext_ctrl[11].id = V4L2_CID_MPEG_VIDEO_H264_MIN_QP;
339 ext_ctrl[11].value = pCommonParam->QSCodeMin;
340 ext_ctrl[12].id = V4L2_CID_MPEG_MFC51_VIDEO_RC_REACTION_COEFF;
341 ext_ctrl[12].value = pCommonParam->CBRPeriodRf;
342
343 /* H.264 specific parameters */
344 switch (pCommonParam->SliceMode) {
345 case 0:
346 ext_ctrl[13].id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB;
347 ext_ctrl[13].value = 1; /* default */
348 ext_ctrl[14].id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES;
349 ext_ctrl[14].value = 2800; /* based on MFC6.x */
350 break;
351 case 1:
352 ext_ctrl[13].id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB;
353 ext_ctrl[13].value = pH264Param->SliceArgument;
354 ext_ctrl[14].id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES;
355 ext_ctrl[14].value = 2800; /* based on MFC6.x */
356 break;
357 case 3:
358 ext_ctrl[13].id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB;
359 ext_ctrl[13].value = 1; /* default */
360 ext_ctrl[14].id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES;
361 ext_ctrl[14].value = pH264Param->SliceArgument;
362 break;
363 default:
364 break;
365 }
366
367 ext_ctrl[15].id = V4L2_CID_MPEG_VIDEO_H264_PROFILE;
368 ext_ctrl[15].value = pH264Param->ProfileIDC;
369 ext_ctrl[16].id = V4L2_CID_MPEG_VIDEO_H264_LEVEL;
370 ext_ctrl[16].value = pH264Param->LevelIDC;
371 ext_ctrl[17].id = V4L2_CID_MPEG_MFC51_VIDEO_H264_NUM_REF_PIC_FOR_P;
372 ext_ctrl[17].value = pH264Param->NumberRefForPframes;
373 /*
374 * It should be set using h264Param->NumberBFrames after being handled by appl.
375 */
376 ext_ctrl[18].id = V4L2_CID_MPEG_VIDEO_B_FRAMES;
377 ext_ctrl[18].value = pH264Param->NumberBFrames;
378 ext_ctrl[19].id = V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE;
379 ext_ctrl[19].value = pH264Param->LoopFilterDisable;
380 ext_ctrl[20].id = V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA;
381 ext_ctrl[20].value = pH264Param->LoopFilterAlphaC0Offset;
382 ext_ctrl[21].id = V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA;
383 ext_ctrl[21].value = pH264Param->LoopFilterBetaOffset;
384 ext_ctrl[22].id = V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE;
385 ext_ctrl[22].value = pH264Param->SymbolMode;
386 ext_ctrl[23].id = V4L2_CID_MPEG_MFC51_VIDEO_H264_INTERLACE;
387 ext_ctrl[23].value = pH264Param->PictureInterlace;
388 ext_ctrl[24].id = V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM;
389 ext_ctrl[24].value = pH264Param->Transform8x8Mode;
390 ext_ctrl[25].id = V4L2_CID_MPEG_MFC51_VIDEO_H264_RC_FRAME_RATE;
391 ext_ctrl[25].value = pH264Param->FrameRate;
392 ext_ctrl[26].id = V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP;
393 ext_ctrl[26].value = pH264Param->FrameQp_B;
394 ext_ctrl[27].id = V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_DARK;
395 ext_ctrl[27].value = pH264Param->DarkDisable;
396 ext_ctrl[28].id = V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_SMOOTH;
397 ext_ctrl[28].value = pH264Param->SmoothDisable;
398 ext_ctrl[29].id = V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_STATIC;
399 ext_ctrl[29].value = pH264Param->StaticDisable;
400 ext_ctrl[30].id = V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_ACTIVITY;
401 ext_ctrl[30].value = pH264Param->ActivityDisable;
402
403 /* doesn't have to be set */
404 ext_ctrl[31].id = V4L2_CID_MPEG_VIDEO_GOP_CLOSURE;
405 ext_ctrl[31].value = 1;
406 ext_ctrl[32].id = V4L2_CID_MPEG_VIDEO_H264_I_PERIOD;
407 ext_ctrl[32].value = 0;
408 ext_ctrl[33].id = V4L2_CID_MPEG_VIDEO_VBV_SIZE;
409 ext_ctrl[33].value = 0;
410 ext_ctrl[34].id = V4L2_CID_MPEG_VIDEO_HEADER_MODE;
411 ext_ctrl[34].value = V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE; /* 0: seperated header, 1: header + first frame */
412 ext_ctrl[35].id = V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE;
413 ext_ctrl[35].value = 0;
414 ext_ctrl[36].id = V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC;
415 ext_ctrl[36].value = V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_UNSPECIFIED;
416 ext_ctrl[37].id = V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_WIDTH;
417 ext_ctrl[37].value = 0;
418 ext_ctrl[38].id = V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_HEIGHT;
419 ext_ctrl[38].value = 0;
420
421 /* Initial parameters : Frame Skip */
422 switch (pInitParam->FrameSkip) {
423 case VIDEO_FRAME_SKIP_MODE_LEVEL_LIMIT:
424 ext_ctrl[39].id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE;
425 ext_ctrl[39].value = V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_LEVEL_LIMIT;
426 break;
427 case VIDEO_FRAME_SKIP_MODE_BUF_LIMIT:
428 ext_ctrl[39].id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE;
429 ext_ctrl[39].value = V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT;
430 break;
431 default:
432 /* VIDEO_FRAME_SKIP_MODE_DISABLE (default) */
433 ext_ctrl[39].id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE;
434 ext_ctrl[39].value = V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_DISABLED;
435 break;
436 }
437
438 /* SVC is not supported yet */
439 ext_ctrl[40].id = V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING;
440 ext_ctrl[40].value = 0;
441 ext_ctrl[41].id = V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_TYPE;
442 ext_ctrl[41].value = V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_B;
443 ext_ctrl[42].id = V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER;
444 ext_ctrl[42].value = 3;
445 ext_ctrl[43].id = V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_QP;
446 ext_ctrl[43].value = (0 << 16 | 0);
447 ext_ctrl[44].id = V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_QP;
448 ext_ctrl[44].value = (1 << 16 | 0);
449 ext_ctrl[45].id = V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_QP;
450 ext_ctrl[45].value = (2 << 16 | 0);
451
452 ext_ctrl[46].id = V4L2_CID_MPEG_VIDEO_H264_SEI_FRAME_PACKING;
453 ext_ctrl[46].value = 0;
454 ext_ctrl[47].id = V4L2_CID_MPEG_VIDEO_H264_SEI_FP_CURRENT_FRAME_0;
455 ext_ctrl[47].value = 0;
456 ext_ctrl[48].id = V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE;
457 ext_ctrl[48].value = V4L2_MPEG_VIDEO_H264_SEI_FP_TYPE_SIDE_BY_SIDE;
458
459 /* FMO is not supported yet */
460 ext_ctrl[49].id = V4L2_CID_MPEG_VIDEO_H264_FMO;
461 ext_ctrl[49].value = 0;
462 ext_ctrl[50].id = V4L2_CID_MPEG_VIDEO_H264_FMO_MAP_TYPE;
463 ext_ctrl[50].value = V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_INTERLEAVED_SLICES;
464 ext_ctrl[51].id = V4L2_CID_MPEG_VIDEO_H264_FMO_SLICE_GROUP;
465 ext_ctrl[51].value = 4;
466 ext_ctrl[52].id = V4L2_CID_MPEG_VIDEO_H264_FMO_RUN_LENGTH;
467 ext_ctrl[52].value = (0 << 30 | 0);
468 ext_ctrl[53].id = V4L2_CID_MPEG_VIDEO_H264_FMO_RUN_LENGTH;
469 ext_ctrl[53].value = (1 << 30 | 0);
470 ext_ctrl[54].id = V4L2_CID_MPEG_VIDEO_H264_FMO_RUN_LENGTH;
471 ext_ctrl[54].value = (2 << 30 | 0);
472 ext_ctrl[55].id = V4L2_CID_MPEG_VIDEO_H264_FMO_RUN_LENGTH;
473 ext_ctrl[55].value = (3 << 30 | 0);
474 ext_ctrl[56].id = V4L2_CID_MPEG_VIDEO_H264_FMO_CHANGE_DIRECTION;
475 ext_ctrl[56].value = V4L2_MPEG_VIDEO_H264_FMO_CHANGE_DIR_RIGHT;
476 ext_ctrl[57].id = V4L2_CID_MPEG_VIDEO_H264_FMO_CHANGE_RATE;
477 ext_ctrl[57].value = 0;
478
479 /* ASO is not supported yet */
480 ext_ctrl[58].id = V4L2_CID_MPEG_VIDEO_H264_ASO;
481 ext_ctrl[58].value = 0;
482 for (i = 0; i < 32; i++) {
483 ext_ctrl[59 + i].id = V4L2_CID_MPEG_VIDEO_H264_ASO_SLICE_ORDER;
484 ext_ctrl[59 + i].value = (i << 16 | 0);
485 }
486
487 ext_ctrls.count = H264_CTRL_NUM;
488 break;
489 }
490
491 case VIDEO_CODING_MPEG4:
492 {
493 ExynosVideoEncMpeg4Param *pMpeg4Param = &pEncParam->codecParam.mpeg4;
494
495 /* common parameters but id is depends on codec */
496 ext_ctrl[8].id = V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP;
497 ext_ctrl[8].value = pCommonParam->FrameQp;
498 ext_ctrl[9].id = V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP;
499 ext_ctrl[9].value = pCommonParam->FrameQp_P;
500 ext_ctrl[10].id = V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP;
501 ext_ctrl[10].value = pCommonParam->QSCodeMax;
502 ext_ctrl[11].id = V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP;
503 ext_ctrl[11].value = pCommonParam->QSCodeMin;
504 ext_ctrl[12].id = V4L2_CID_MPEG_MFC51_VIDEO_RC_REACTION_COEFF;
505 ext_ctrl[12].value = pCommonParam->CBRPeriodRf;
506
507 /* MPEG4 specific parameters */
508 switch (pCommonParam->SliceMode) {
509 case 0:
510 ext_ctrl[13].id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB;
511 ext_ctrl[13].value = 1; /* default */
512 ext_ctrl[14].id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES;
513 ext_ctrl[14].value = 2800; /* based on MFC6.x */
514 break;
515 case 1:
516 ext_ctrl[13].id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB;
517 ext_ctrl[13].value = pMpeg4Param->SliceArgument;
518 ext_ctrl[14].id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES;
519 ext_ctrl[14].value = 2800; /* based on MFC6.x */
520 break;
521 case 3:
522 ext_ctrl[13].id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB;
523 ext_ctrl[13].value = 1; /* default */
524 ext_ctrl[14].id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES;
525 ext_ctrl[14].value = pMpeg4Param->SliceArgument;
526 break;
527 default:
528 break;
529 }
530
531 ext_ctrl[15].id = V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE;
532 ext_ctrl[15].value = pMpeg4Param->ProfileIDC;
533 ext_ctrl[16].id = V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL;
534 ext_ctrl[16].value = pMpeg4Param->LevelIDC;
535 ext_ctrl[17].id = V4L2_CID_MPEG_VIDEO_MPEG4_QPEL;
536 ext_ctrl[17].value = pMpeg4Param->DisableQpelME;
537
538 /*
539 * It should be set using mpeg4Param->NumberBFrames after being handled by appl.
540 */
541 ext_ctrl[18].id = V4L2_CID_MPEG_VIDEO_B_FRAMES;
542 ext_ctrl[18].value = pMpeg4Param->NumberBFrames;
543
544 ext_ctrl[19].id = V4L2_CID_MPEG_MFC51_VIDEO_MPEG4_VOP_TIME_RES;
545 ext_ctrl[19].value = pMpeg4Param->TimeIncreamentRes;
546 ext_ctrl[20].id = V4L2_CID_MPEG_MFC51_VIDEO_MPEG4_VOP_FRM_DELTA;
547 ext_ctrl[20].value = pMpeg4Param->VopTimeIncreament;
548 ext_ctrl[21].id = V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP;
549 ext_ctrl[21].value = pMpeg4Param->FrameQp_B;
550 ext_ctrl[22].id = V4L2_CID_MPEG_VIDEO_VBV_SIZE;
551 ext_ctrl[22].value = 0;
552 ext_ctrl[23].id = V4L2_CID_MPEG_VIDEO_HEADER_MODE;
553 ext_ctrl[23].value = V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE;
554 ext_ctrl[24].id = V4L2_CID_MPEG_MFC51_VIDEO_RC_FIXED_TARGET_BIT;
555 ext_ctrl[24].value = 1;
556
557 /* Initial parameters : Frame Skip */
558 switch (pInitParam->FrameSkip) {
559 case VIDEO_FRAME_SKIP_MODE_LEVEL_LIMIT:
560 ext_ctrl[25].id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE;
561 ext_ctrl[25].value = V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_LEVEL_LIMIT;
562 break;
563 case VIDEO_FRAME_SKIP_MODE_BUF_LIMIT:
564 ext_ctrl[25].id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE;
565 ext_ctrl[25].value = V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT;
566 break;
567 default:
568 /* VIDEO_FRAME_SKIP_MODE_DISABLE (default) */
569 ext_ctrl[25].id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE;
570 ext_ctrl[25].value = V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_DISABLED;
571 break;
572 }
573
574 ext_ctrls.count = MPEG4_CTRL_NUM;
575 break;
576 }
577
578 case VIDEO_CODING_H263:
579 {
580 ExynosVideoEncH263Param *pH263Param = &pEncParam->codecParam.h263;
581
582 /* common parameters but id is depends on codec */
583 ext_ctrl[8].id = V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP;
584 ext_ctrl[8].value = pCommonParam->FrameQp;
585 ext_ctrl[9].id = V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP;
586 ext_ctrl[9].value = pCommonParam->FrameQp_P;
587 ext_ctrl[10].id = V4L2_CID_MPEG_VIDEO_H263_MAX_QP;
588 ext_ctrl[10].value = pCommonParam->QSCodeMax;
589 ext_ctrl[11].id = V4L2_CID_MPEG_VIDEO_H263_MIN_QP;
590 ext_ctrl[11].value = pCommonParam->QSCodeMin;
591 ext_ctrl[12].id = V4L2_CID_MPEG_MFC51_VIDEO_RC_REACTION_COEFF;
592 ext_ctrl[12].value = pCommonParam->CBRPeriodRf;
593
594 /* H263 specific parameters */
595 ext_ctrl[13].id = V4L2_CID_MPEG_MFC51_VIDEO_H263_RC_FRAME_RATE;
596 ext_ctrl[13].value = pH263Param->FrameRate;
597 ext_ctrl[14].id = V4L2_CID_MPEG_VIDEO_VBV_SIZE;
598 ext_ctrl[14].value = 0;
599 ext_ctrl[15].id = V4L2_CID_MPEG_VIDEO_HEADER_MODE;
600 ext_ctrl[15].value = V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE;
601 ext_ctrl[16].id = V4L2_CID_MPEG_MFC51_VIDEO_RC_FIXED_TARGET_BIT;
602 ext_ctrl[16].value = 1;
603
604 /* Initial parameters : Frame Skip */
605 switch (pInitParam->FrameSkip) {
606 case VIDEO_FRAME_SKIP_MODE_LEVEL_LIMIT:
607 ext_ctrl[17].id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE;
608 ext_ctrl[17].value = V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_LEVEL_LIMIT;
609 break;
610 case VIDEO_FRAME_SKIP_MODE_BUF_LIMIT:
611 ext_ctrl[17].id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE;
612 ext_ctrl[17].value = V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT;
613 break;
614 default:
615 /* VIDEO_FRAME_SKIP_MODE_DISABLE (default) */
616 ext_ctrl[17].id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE;
617 ext_ctrl[17].value = V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_DISABLED;
618 break;
619 }
620
621 ext_ctrls.count = H263_CTRL_NUM;
622 break;
623 }
624
625 default:
626 ALOGE("[%s] Undefined codec type",__func__);
627 ret = VIDEO_ERROR_BADPARAM;
628 goto EXIT;
629 }
630
631 ext_ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
632 ext_ctrls.controls = ext_ctrl;
633
634 if (exynos_v4l2_s_ext_ctrl(pCtx->hEnc, &ext_ctrls) != 0) {
635 ALOGE("%s: Failed to s_ext_ctrl", __func__);
636 ret = VIDEO_ERROR_APIFAIL;
637 goto EXIT;
638 }
639
640 EXIT:
641 return ret;
642 }
643
644 /*
645 * [Encoder OPS] Set Frame Tag
646 */
647 static ExynosVideoErrorType MFC_Encoder_Set_FrameTag(
648 void *pHandle,
649 int frameTag)
650 {
651 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
652 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
653
654 if (pCtx == NULL) {
655 ALOGE("%s: Video context info must be supplied", __func__);
656 ret = VIDEO_ERROR_BADPARAM;
657 goto EXIT;
658 }
659
660 if (exynos_v4l2_s_ctrl(pCtx->hEnc, V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG, frameTag) != 0) {
661 ALOGE("%s: Failed to s_ctrl", __func__);
662 ret = VIDEO_ERROR_APIFAIL;
663 goto EXIT;
664 }
665
666 EXIT:
667 return ret;
668 }
669
670 /*
671 * [Encoder OPS] Get Frame Tag
672 */
673 static int MFC_Encoder_Get_FrameTag(void *pHandle)
674 {
675 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
676 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
677
678 int frameTag = -1;
679
680 if (pCtx == NULL) {
681 ALOGE("%s: Video context info must be supplied", __func__);
682 goto EXIT;
683 }
684
685 if (exynos_v4l2_g_ctrl(pCtx->hEnc, V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG, &frameTag) != 0) {
686 ALOGE("%s: Failed to g_ctrl", __func__);
687 ret = VIDEO_ERROR_APIFAIL;
688 goto EXIT;
689 }
690
691 EXIT:
692 return frameTag;
693 }
694
695 /*
696 * [Encoder OPS] Set Frame Type
697 */
698 static ExynosVideoErrorType MFC_Encoder_Set_FrameType(
699 void *pHandle,
700 ExynosVideoFrameType frameType)
701 {
702 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
703 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
704
705 if (pCtx == NULL) {
706 ALOGE("%s: Video context info must be supplied", __func__);
707 ret = VIDEO_ERROR_BADPARAM;
708 goto EXIT;
709 }
710
711 if (exynos_v4l2_s_ctrl(pCtx->hEnc, V4L2_CID_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE, frameType) != 0) {
712 ALOGE("%s: Failed to s_ctrl", __func__);
713 ret = VIDEO_ERROR_APIFAIL;
714 goto EXIT;
715 }
716
717 EXIT:
718 return ret;
719 }
720
721 /*
722 * [Encoder OPS] Set Frame Rate
723 */
724 static ExynosVideoErrorType MFC_Encoder_Set_FrameRate(
725 void *pHandle,
726 int frameRate)
727 {
728 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
729 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
730
731 if (pCtx == NULL) {
732 ALOGE("%s: Video context info must be supplied", __func__);
733 ret = VIDEO_ERROR_BADPARAM;
734 goto EXIT;
735 }
736
737 if (exynos_v4l2_s_ctrl(pCtx->hEnc, V4L2_CID_MPEG_MFC51_VIDEO_FRAME_RATE_CH, frameRate) != 0) {
738 ALOGE("%s: Failed to s_ctrl", __func__);
739 ret = VIDEO_ERROR_APIFAIL;
740 goto EXIT;
741 }
742
743 EXIT:
744 return ret;
745 }
746
747 /*
748 * [Encoder OPS] Set Bit Rate
749 */
750 static ExynosVideoErrorType MFC_Encoder_Set_BitRate(
751 void *pHandle,
752 int bitRate)
753 {
754 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
755 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
756
757 if (pCtx == NULL) {
758 ALOGE("%s: Video context info must be supplied", __func__);
759 ret = VIDEO_ERROR_BADPARAM;
760 goto EXIT;
761 }
762
763 if (exynos_v4l2_s_ctrl(pCtx->hEnc, V4L2_CID_MPEG_MFC51_VIDEO_BIT_RATE_CH, bitRate) != 0) {
764 ALOGE("%s: Failed to s_ctrl", __func__);
765 ret = VIDEO_ERROR_APIFAIL;
766 goto EXIT;
767 }
768
769 EXIT:
770 return ret;
771 }
772
773 /*
774 * [Encoder OPS] Set Frame Skip
775 */
776 static ExynosVideoErrorType MFC_Encoder_Set_FrameSkip(
777 void *pHandle,
778 int frameSkip)
779 {
780 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
781 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
782
783 if (pCtx == NULL) {
784 ALOGE("%s: Video context info must be supplied", __func__);
785 ret = VIDEO_ERROR_BADPARAM;
786 goto EXIT;
787 }
788
789 if (exynos_v4l2_s_ctrl(pCtx->hEnc, V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE, frameSkip) != 0) {
790 ALOGE("%s: Failed to s_ctrl", __func__);
791 ret = VIDEO_ERROR_APIFAIL;
792 goto EXIT;
793 }
794
795 EXIT:
796 return ret;
797 }
798
799 /*
800 * [Encoder OPS] Set IDR Period
801 */
802 static ExynosVideoErrorType MFC_Encoder_Set_IDRPeriod(
803 void *pHandle,
804 int IDRPeriod)
805 {
806 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
807 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
808
809 if (pCtx == NULL) {
810 ALOGE("%s: Video context info must be supplied", __func__);
811 ret = VIDEO_ERROR_BADPARAM;
812 goto EXIT;
813 }
814
815 if (exynos_v4l2_s_ctrl(pCtx->hEnc, V4L2_CID_MPEG_VIDEO_H264_I_PERIOD, IDRPeriod) != 0) {
816 ALOGE("%s: Failed to s_ctrl", __func__);
817 ret = VIDEO_ERROR_APIFAIL;
818 goto EXIT;
819 }
820
821 EXIT:
822 return ret;
823 }
824
825 /*
826 * [Encoder Buffer OPS] Enable Cacheable (Input)
827 */
828 static ExynosVideoErrorType MFC_Encoder_Enable_Cacheable_Inbuf(void *pHandle)
829 {
830 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
831 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
832
833 if (pCtx == NULL) {
834 ALOGE("%s: Video context info must be supplied", __func__);
835 ret = VIDEO_ERROR_BADPARAM;
836 goto EXIT;
837 }
838
839 if (exynos_v4l2_s_ctrl(pCtx->hEnc, V4L2_CID_CACHEABLE, 2) != 0) {
840 ALOGE("%s: Failed V4L2_CID_CACHEABLE", __func__);
841 ret = VIDEO_ERROR_APIFAIL;
842 goto EXIT;
843 }
844
845 EXIT:
846 return ret;
847 }
848
849 /*
850 * [Encoder Buffer OPS] Enable Cacheable (Output)
851 */
852 static ExynosVideoErrorType MFC_Encoder_Enable_Cacheable_Outbuf(void *pHandle)
853 {
854 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
855 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
856
857 if (pCtx == NULL) {
858 ALOGE("%s: Video context info must be supplied", __func__);
859 ret = VIDEO_ERROR_BADPARAM;
860 goto EXIT;
861 }
862
863 if (exynos_v4l2_s_ctrl(pCtx->hEnc, V4L2_CID_CACHEABLE, 1) != 0) {
864 ALOGE("%s: Failed V4L2_CID_CACHEABLE", __func__);
865 ret = VIDEO_ERROR_APIFAIL;
866 goto EXIT;
867 }
868
869 EXIT:
870 return ret;
871 }
872
873 /*
874 * [Encoder Buffer OPS] Set Shareable Buffer (Input)
875 */
876 static ExynosVideoErrorType MFC_Encoder_Set_Shareable_Inbuf(void *pHandle)
877 {
878 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
879 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
880
881 if (pCtx == NULL) {
882 ALOGE("%s: Video context info must be supplied", __func__);
883 ret = VIDEO_ERROR_BADPARAM;
884 goto EXIT;
885 }
886
887 pCtx->bShareInbuf = VIDEO_TRUE;
888
889 EXIT:
890 return ret;
891 }
892
893 /*
894 * [Encoder Buffer OPS] Set Shareable Buffer (Output)
895 */
896 static ExynosVideoErrorType MFC_Encoder_Set_Shareable_Outbuf(void *pHandle)
897 {
898 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
899 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
900
901 if (pCtx == NULL) {
902 ALOGE("%s: Video context info must be supplied", __func__);
903 ret = VIDEO_ERROR_BADPARAM;
904 goto EXIT;
905 }
906
907 pCtx->bShareOutbuf = VIDEO_TRUE;
908
909 EXIT:
910 return ret;
911 }
912
913 /*
914 * [Encoder Buffer OPS] Get Buffer (Input)
915 */
916 static ExynosVideoErrorType MFC_Encoder_Get_Buffer_Inbuf(
917 void *pHandle,
918 int nIndex,
919 ExynosVideoBuffer **pBuffer)
920 {
921 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
922 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
923
924 if (pCtx == NULL) {
925 ALOGE("%s: Video context info must be supplied", __func__);
926 *pBuffer = NULL;
927 ret = VIDEO_ERROR_NOBUFFERS;
928 goto EXIT;
929 }
930
931 if (pCtx->nInbufs <= nIndex) {
932 *pBuffer = NULL;
933 ret = VIDEO_ERROR_BADPARAM;
934 goto EXIT;
935 }
936
937 *pBuffer = (ExynosVideoBuffer *)&pCtx->pInbuf[nIndex];
938
939 EXIT:
940 return ret;
941 }
942
943 /*
944 * [Encoder Buffer OPS] Get Buffer (Output)
945 */
946 static ExynosVideoErrorType MFC_Encoder_Get_Buffer_Outbuf(
947 void *pHandle,
948 int nIndex,
949 ExynosVideoBuffer **pBuffer)
950 {
951 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
952 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
953
954 if (pCtx == NULL) {
955 ALOGE("%s: Video context info must be supplied", __func__);
956 *pBuffer = NULL;
957 ret = VIDEO_ERROR_NOBUFFERS;
958 goto EXIT;
959 }
960
961 if (pCtx->nOutbufs <= nIndex) {
962 *pBuffer = NULL;
963 ret = VIDEO_ERROR_BADPARAM;
964 goto EXIT;
965 }
966
967 *pBuffer = (ExynosVideoBuffer *)&pCtx->pOutbuf[nIndex];
968
969 EXIT:
970 return ret;
971 }
972
973 /*
974 * [Encoder Buffer OPS] Set Geometry (Src)
975 */
976 static ExynosVideoErrorType MFC_Encoder_Set_Geometry_Inbuf(
977 void *pHandle,
978 ExynosVideoGeometry *bufferConf)
979 {
980 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
981 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
982
983 struct v4l2_format fmt;
984
985 if (pCtx == NULL) {
986 ALOGE("%s: Video context info must be supplied", __func__);
987 ret = VIDEO_ERROR_BADPARAM;
988 goto EXIT;
989 }
990
991 if (bufferConf == NULL) {
992 ALOGE("%s: Buffer geometry must be supplied", __func__);
993 ret = VIDEO_ERROR_BADPARAM;
994 goto EXIT;
995 }
996
997 memset(&fmt, 0, sizeof(fmt));
998
999 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1000 fmt.fmt.pix_mp.pixelformat = __ColorFormatType_To_V4L2PixelFormat(bufferConf->eColorFormat);
1001 fmt.fmt.pix_mp.width = bufferConf->nFrameWidth;
1002 fmt.fmt.pix_mp.height = bufferConf->nFrameHeight;
1003 fmt.fmt.pix_mp.num_planes = VIDEO_ENCODER_INBUF_PLANES;
1004
1005 if (exynos_v4l2_s_fmt(pCtx->hEnc, &fmt) != 0) {
1006 ALOGE("%s: Failed to s_fmt", __func__);
1007 ret = VIDEO_ERROR_APIFAIL;
1008 goto EXIT;
1009 }
1010
1011 memcpy(&pCtx->inbufGeometry, bufferConf, sizeof(pCtx->inbufGeometry));
1012
1013 EXIT:
1014 return ret;
1015 }
1016
1017 /*
1018 * [Encoder Buffer OPS] Get Geometry (Src)
1019 */
1020 static ExynosVideoErrorType MFC_Encoder_Get_Geometry_Inbuf(
1021 void *pHandle,
1022 ExynosVideoGeometry *bufferConf)
1023 {
1024 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
1025 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1026
1027 struct v4l2_format fmt;
1028
1029 if (pCtx == NULL) {
1030 ALOGE("%s: Video context info must be supplied", __func__);
1031 ret = VIDEO_ERROR_BADPARAM;
1032 goto EXIT;
1033 }
1034
1035 if (bufferConf == NULL) {
1036 ALOGE("%s: Buffer geometry must be supplied", __func__);
1037 ret = VIDEO_ERROR_BADPARAM;
1038 goto EXIT;
1039 }
1040
1041 memset(&fmt, 0, sizeof(fmt));
1042
1043 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1044 if (exynos_v4l2_g_fmt(pCtx->hEnc, &fmt) != 0) {
1045 ALOGE("%s: Failed to g_fmt", __func__);
1046 ret = VIDEO_ERROR_APIFAIL;
1047 goto EXIT;
1048 }
1049
1050 bufferConf->nFrameHeight = fmt.fmt.pix_mp.width;
1051 bufferConf->nFrameHeight = fmt.fmt.pix_mp.height;
1052 bufferConf->nSizeImage = fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
1053
1054 EXIT:
1055 return ret;
1056 }
1057
1058 /*
1059 * [Encoder Buffer OPS] Set Geometry (Dst)
1060 */
1061 static ExynosVideoErrorType MFC_Encoder_Set_Geometry_Outbuf(
1062 void *pHandle,
1063 ExynosVideoGeometry *bufferConf)
1064 {
1065 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
1066 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1067
1068 struct v4l2_format fmt;
1069
1070 if (pCtx == NULL) {
1071 ALOGE("%s: Video context info must be supplied", __func__);
1072 ret = VIDEO_ERROR_BADPARAM;
1073 goto EXIT;
1074 }
1075
1076 if (bufferConf == NULL) {
1077 ALOGE("%s: Buffer geometry must be supplied", __func__);
1078 ret = VIDEO_ERROR_BADPARAM;
1079 goto EXIT;
1080 }
1081
1082 memset(&fmt, 0, sizeof(fmt));
1083
1084 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1085 fmt.fmt.pix_mp.pixelformat = __CodingType_To_V4L2PixelFormat(bufferConf->eCompressionFormat);
1086 fmt.fmt.pix_mp.plane_fmt[0].sizeimage = bufferConf->nSizeImage;
1087
1088 if (exynos_v4l2_s_fmt(pCtx->hEnc, &fmt) != 0) {
1089 ALOGE("%s: Failed to s_fmt", __func__);
1090 ret = VIDEO_ERROR_APIFAIL;
1091 goto EXIT;
1092 }
1093
1094 memcpy(&pCtx->outbufGeometry, bufferConf, sizeof(pCtx->outbufGeometry));
1095
1096 EXIT:
1097 return ret;
1098 }
1099
1100 /*
1101 * [Encoder Buffer OPS] Get Geometry (Dst)
1102 */
1103 static ExynosVideoErrorType MFC_Encoder_Get_Geometry_Outbuf(
1104 void *pHandle,
1105 ExynosVideoGeometry *bufferConf)
1106 {
1107 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
1108 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1109
1110 struct v4l2_format fmt;
1111
1112 if (pCtx == NULL) {
1113 ALOGE("%s: Video context info must be supplied", __func__);
1114 ret = VIDEO_ERROR_BADPARAM;
1115 goto EXIT;
1116 }
1117
1118 if (bufferConf == NULL) {
1119 ALOGE("%s: Buffer geometry must be supplied", __func__);
1120 ret = VIDEO_ERROR_BADPARAM;
1121 goto EXIT;
1122 }
1123
1124 memset(&fmt, 0, sizeof(fmt));
1125
1126 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1127 if (exynos_v4l2_g_fmt(pCtx->hEnc, &fmt) != 0) {
1128 ALOGE("%s: Failed to g_fmt", __func__);
1129 ret = VIDEO_ERROR_APIFAIL;
1130 goto EXIT;
1131 }
1132
1133 bufferConf->nSizeImage = fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
1134
1135 EXIT:
1136 return ret;
1137 }
1138
1139 /*
1140 * [Encoder Buffer OPS] Setup (Src)
1141 */
1142 static ExynosVideoErrorType MFC_Encoder_Setup_Inbuf(
1143 void *pHandle,
1144 unsigned int nBufferCount)
1145 {
1146 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
1147 ExynosVideoPlane *pVideoPlane = NULL;
1148 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1149
1150 struct v4l2_requestbuffers req;
1151 struct v4l2_buffer buf;
1152 struct v4l2_plane planes[VIDEO_ENCODER_INBUF_PLANES];
1153 int i, j;
1154
1155 if (pCtx == NULL) {
1156 ALOGE("%s: Video context info must be supplied", __func__);
1157 ret = VIDEO_ERROR_BADPARAM;
1158 goto EXIT;
1159 }
1160
1161 if (nBufferCount == 0) {
1162 ALOGE("%s: Buffer count must be greater than 0", __func__);
1163 ret = VIDEO_ERROR_BADPARAM;
1164 goto EXIT;
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)
1173 req.memory = pCtx->nMemoryType;
1174 else
1175 req.memory = V4L2_MEMORY_MMAP;
1176
1177 if (exynos_v4l2_reqbufs(pCtx->hEnc, &req) != 0) {
1178 ALOGE("Failed to require buffer");
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) {
1187 ALOGE("%s: Failed to allocate input buffer context", __func__);
1188 ret = VIDEO_ERROR_NOMEM;
1189 goto EXIT;
1190 }
1191 memset(pCtx->pInbuf, 0, sizeof(*pCtx->pInbuf) * pCtx->nInbufs);
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;
1203 if (exynos_v4l2_querybuf(pCtx->hEnc, &buf) != 0) {
1204 ALOGE("%s: Failed to querybuf", __func__);
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) {
1216 ALOGE("%s: Failed to map", __func__);
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;
1227 pCtx->pInbuf[i].bRegistered = VIDEO_TRUE;
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;
1234 pCtx->pInbuf[i].bRegistered = VIDEO_FALSE;
1235 }
1236 }
1237
1238 return ret;
1239
1240 EXIT:
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);
1252 }
1253 }
1254 }
1255
1256 free(pCtx->pInbuf);
1257 }
1258
1259 return ret;
1260 }
1261
1262 /*
1263 * [Encoder Buffer OPS] Setup (Dst)
1264 */
1265 static ExynosVideoErrorType MFC_Encoder_Setup_Outbuf(
1266 void *pHandle,
1267 unsigned int nBufferCount)
1268 {
1269 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
1270 ExynosVideoPlane *pVideoPlane = NULL;
1271 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
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) {
1279 ALOGE("%s: Video context info must be supplied", __func__);
1280 ret = VIDEO_ERROR_BADPARAM;
1281 goto EXIT;
1282 }
1283
1284 if (nBufferCount == 0) {
1285 ALOGE("%s: Buffer count must be greater than 0", __func__);
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)
1296 req.memory = pCtx->nMemoryType;
1297 else
1298 req.memory = V4L2_MEMORY_MMAP;
1299
1300 if (exynos_v4l2_reqbufs(pCtx->hEnc, &req) != 0) {
1301 ALOGE("%s: Failed to reqbuf", __func__);
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) {
1310 ALOGE("%s: Failed to allocate output buffer context", __func__);
1311 ret = VIDEO_ERROR_NOMEM;
1312 goto EXIT;
1313 }
1314 memset(pCtx->pOutbuf, 0, sizeof(*pCtx->pOutbuf) * pCtx->nOutbufs);
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;
1326 if (exynos_v4l2_querybuf(pCtx->hEnc, &buf) != 0) {
1327 ALOGE("%s: Failed to querybuf", __func__);
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) {
1339 ALOGE("%s: Failed to map", __func__);
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;
1350 pCtx->pOutbuf[i].bRegistered = VIDEO_TRUE;
1351 }
1352 } else {
1353 for (i = 0; i < pCtx->nOutbufs; i++ ) {
1354 pCtx->pOutbuf[i].pGeometry = &pCtx->outbufGeometry;
1355 pCtx->pOutbuf[i].bQueued = VIDEO_FALSE;
1356 pCtx->pOutbuf[i].bRegistered = VIDEO_FALSE;
1357 }
1358 }
1359
1360 return ret;
1361
1362 EXIT:
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 }
1372
1373 munmap(pVideoPlane->addr, pVideoPlane->allocSize);
1374 }
1375 }
1376 }
1377
1378 free(pCtx->pOutbuf);
1379 }
1380
1381 return ret;
1382 }
1383
1384 /*
1385 * [Encoder Buffer OPS] Run (src)
1386 */
1387 static ExynosVideoErrorType MFC_Encoder_Run_Inbuf(void *pHandle)
1388 {
1389 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
1390 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1391
1392 if (pCtx == NULL) {
1393 ALOGE("%s: Video context info must be supplied", __func__);
1394 ret = VIDEO_ERROR_BADPARAM;
1395 goto EXIT;
1396 }
1397
1398 if (pCtx->bStreamonInbuf == VIDEO_FALSE) {
1399 if (exynos_v4l2_streamon(pCtx->hEnc, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) != 0) {
1400 ALOGE("%s: Failed to streamon for input buffer", __func__);
1401 ret = VIDEO_ERROR_APIFAIL;
1402 goto EXIT;
1403 }
1404 pCtx->bStreamonInbuf = VIDEO_TRUE;
1405 }
1406
1407 EXIT:
1408 return ret;
1409 }
1410
1411 /*
1412 * [Encoder Buffer OPS] Run (Dst)
1413 */
1414 static ExynosVideoErrorType MFC_Encoder_Run_Outbuf(void *pHandle)
1415 {
1416 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
1417 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1418
1419 if (pCtx == NULL) {
1420 ALOGE("%s: Video context info must be supplied", __func__);
1421 ret = VIDEO_ERROR_BADPARAM;
1422 goto EXIT;
1423 }
1424
1425 if (pCtx->bStreamonOutbuf == VIDEO_FALSE) {
1426 if (exynos_v4l2_streamon(pCtx->hEnc, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) != 0) {
1427 ALOGE("%s: Failed to streamon for output buffer", __func__);
1428 ret = VIDEO_ERROR_APIFAIL;
1429 goto EXIT;
1430 }
1431 pCtx->bStreamonOutbuf = VIDEO_TRUE;
1432 }
1433
1434 EXIT:
1435 return ret;
1436 }
1437
1438 /*
1439 * [Encoder Buffer OPS] Stop (Src)
1440 */
1441 static ExynosVideoErrorType MFC_Encoder_Stop_Inbuf(void *pHandle)
1442 {
1443 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
1444 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1445 int i = 0;
1446
1447 if (pCtx == NULL) {
1448 ALOGE("%s: Video context info must be supplied", __func__);
1449 ret = VIDEO_ERROR_BADPARAM;
1450 goto EXIT;
1451 }
1452
1453 if (pCtx->bStreamonInbuf == VIDEO_TRUE) {
1454 if (exynos_v4l2_streamoff(pCtx->hEnc, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) != 0) {
1455 ALOGE("%s: Failed to streamoff for input buffer", __func__);
1456 ret = VIDEO_ERROR_APIFAIL;
1457 goto EXIT;
1458 }
1459 pCtx->bStreamonInbuf = VIDEO_FALSE;
1460 }
1461
1462 for (i = 0; i < pCtx->nInbufs; i++) {
1463 pCtx->pInbuf[i].bQueued = VIDEO_FALSE;
1464 }
1465
1466 EXIT:
1467 return ret;
1468 }
1469
1470 /*
1471 * [Encoder Buffer OPS] Stop (Dst)
1472 */
1473 static ExynosVideoErrorType MFC_Encoder_Stop_Outbuf(void *pHandle)
1474 {
1475 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
1476 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1477 int i = 0;
1478
1479 if (pCtx == NULL) {
1480 ALOGE("%s: Video context info must be supplied", __func__);
1481 ret = VIDEO_ERROR_BADPARAM;
1482 goto EXIT;
1483 }
1484
1485 if (pCtx->bStreamonOutbuf == VIDEO_TRUE) {
1486 if (exynos_v4l2_streamoff(pCtx->hEnc, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) != 0) {
1487 ALOGE("%s: Failed to streamoff for output buffer", __func__);
1488 ret = VIDEO_ERROR_APIFAIL;
1489 goto EXIT;
1490 }
1491 pCtx->bStreamonOutbuf = VIDEO_FALSE;
1492 }
1493
1494 for (i = 0; i < pCtx->nOutbufs; i++) {
1495 pCtx->pOutbuf[i].bQueued = VIDEO_FALSE;
1496 }
1497
1498 EXIT:
1499 return ret;
1500 }
1501
1502 /*
1503 * [Encoder Buffer OPS] Wait (Src)
1504 */
1505 static 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) {
1514 ALOGE("%s: Video context info must be supplied", __func__);
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 {
1529 ALOGE("%s: Poll return error", __func__);
1530 ret = VIDEO_ERROR_POLL;
1531 break;
1532 }
1533 } else if (poll_state < 0) {
1534 ALOGE("%s: Poll state error", __func__);
1535 ret = VIDEO_ERROR_POLL;
1536 break;
1537 }
1538 } while (poll_state == 0);
1539
1540 EXIT:
1541 return ret;
1542 }
1543
1544 /*
1545 * [Encoder Buffer OPS] Wait (Dst)
1546 */
1547 static 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) {
1557 ALOGE("%s: Video context info must be supplied", __func__);
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 {
1572 ALOGE("%s: Poll return error", __func__);
1573 ret = VIDEO_ERROR_POLL;
1574 break;
1575 }
1576 } else if (poll_state < 0) {
1577 ALOGE("%s: Poll state error", __func__);
1578 ret = VIDEO_ERROR_POLL;
1579 break;
1580 } else {
1581 bframe_count++; // FIXME
1582 }
1583 } while (poll_state == 0 && bframe_count < 5); // FIXME
1584
1585 EXIT:
1586 return ret;
1587 }
1588
1589 static ExynosVideoErrorType MFC_Encoder_Register_Inbuf(
1590 void *pHandle,
1591 ExynosVideoPlane *planes,
1592 int nPlanes)
1593 {
1594 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
1595 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1596 int nIndex;
1597
1598 if ((pCtx == NULL) || (planes == NULL) || (nPlanes != VIDEO_ENCODER_INBUF_PLANES)) {
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) {
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 }
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
1622 EXIT:
1623 return ret;
1624 }
1625
1626 static ExynosVideoErrorType MFC_Encoder_Register_Outbuf(
1627 void *pHandle,
1628 ExynosVideoPlane *planes,
1629 int nPlanes)
1630 {
1631 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
1632 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1633 int nIndex;
1634
1635 if ((pCtx == NULL) || (planes == NULL) || (nPlanes != VIDEO_ENCODER_OUTBUF_PLANES)) {
1636 ALOGE("%s: params must be supplied", __func__);
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) {
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 }
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
1659 EXIT:
1660 return ret;
1661 }
1662
1663 static 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++) {
1676 pCtx->pInbuf[nIndex].planes[0].addr = NULL;
1677 pCtx->pInbuf[nIndex].bRegistered = VIDEO_FALSE;
1678 }
1679
1680 EXIT:
1681 return ret;
1682 }
1683
1684 static 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++) {
1697 pCtx->pOutbuf[nIndex].planes[0].addr = NULL;
1698 pCtx->pOutbuf[nIndex].bRegistered = VIDEO_FALSE;
1699 }
1700
1701 EXIT:
1702 return ret;
1703 }
1704
1705 /*
1706 * [Encoder Buffer OPS] Find (Input)
1707 */
1708 static int MFC_Encoder_Find_Inbuf(
1709 void *pHandle,
1710 unsigned char *pBuffer)
1711 {
1712 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
1713 int nIndex = -1;
1714
1715 if (pCtx == NULL) {
1716 ALOGE("%s: Video context info must be supplied", __func__);
1717 goto EXIT;
1718 }
1719
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))
1724 break;
1725 }
1726 }
1727
1728 if (nIndex == pCtx->nInbufs)
1729 nIndex = -1;
1730
1731 EXIT:
1732 return nIndex;
1733 }
1734
1735 /*
1736 * [Encoder Buffer OPS] Find (Outnput)
1737 */
1738 static int MFC_Encoder_Find_Outbuf(
1739 void *pHandle,
1740 unsigned char *pBuffer)
1741 {
1742 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
1743 int nIndex = -1;
1744
1745 if (pCtx == NULL) {
1746 ALOGE("%s: Video context info must be supplied", __func__);
1747 goto EXIT;
1748 }
1749
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))
1754 break;
1755 }
1756 }
1757
1758 if (nIndex == pCtx->nOutbufs)
1759 nIndex = -1;
1760
1761 EXIT:
1762 return nIndex;
1763 }
1764
1765 /*
1766 * [Encoder Buffer OPS] Enqueue (Input)
1767 */
1768 static ExynosVideoErrorType MFC_Encoder_Enqueue_Inbuf(
1769 void *pHandle,
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;
1777 pthread_mutex_t *pMutex = NULL;
1778
1779 struct v4l2_plane planes[VIDEO_ENCODER_INBUF_PLANES];
1780 struct v4l2_buffer buf;
1781 int index, i;
1782
1783 if (pCtx == NULL) {
1784 ALOGE("%s: Video context info must be supplied", __func__);
1785 ret = VIDEO_ERROR_BADPARAM;
1786 goto EXIT;
1787 }
1788
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
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
1802 pMutex = (pthread_mutex_t*)pCtx->pInMutex;
1803 pthread_mutex_lock(pMutex);
1804 index = MFC_Encoder_Find_Inbuf(pCtx, pBuffer[0]);
1805 if (index == -1) {
1806 pthread_mutex_unlock(pMutex);
1807 ALOGE("%s: Failed to get index", __func__);
1808 ret = VIDEO_ERROR_NOBUFFERS;
1809 goto EXIT;
1810 }
1811
1812 buf.index = index;
1813 pCtx->pInbuf[buf.index].bQueued = VIDEO_TRUE;
1814 pthread_mutex_unlock(pMutex);
1815
1816 if (pCtx->bShareInbuf == VIDEO_TRUE) {
1817 buf.memory = pCtx->nMemoryType;
1818 for (i = 0; i < nPlanes; i++) {
1819 /* V4L2_MEMORY_USERPTR */
1820 buf.m.planes[i].m.userptr = (unsigned long)pBuffer[i];
1821 /* V4L2_MEMORY_DMABUF */
1822 buf.m.planes[i].m.fd = pCtx->pInbuf[buf.index].planes[i].fd;
1823 buf.m.planes[i].length = pCtx->pInbuf[index].planes[i].allocSize;
1824 buf.m.planes[i].bytesused = dataSize[i];
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
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;
1835 ret = VIDEO_ERROR_APIFAIL;
1836 goto EXIT;
1837 }
1838
1839 pCtx->pInbuf[buf.index].pPrivate = pPrivate;
1840
1841 EXIT:
1842 return ret;
1843 }
1844
1845 /*
1846 * [Encoder Buffer OPS] Enqueue (Output)
1847 */
1848 static ExynosVideoErrorType MFC_Encoder_Enqueue_Outbuf(
1849 void *pHandle,
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;
1857 pthread_mutex_t *pMutex = NULL;
1858
1859 struct v4l2_plane planes[VIDEO_ENCODER_OUTBUF_PLANES];
1860 struct v4l2_buffer buf;
1861 int i, index;
1862
1863 if (pCtx == NULL) {
1864 ALOGE("%s: Video context info must be supplied", __func__);
1865 ret = VIDEO_ERROR_BADPARAM;
1866 goto EXIT;
1867 }
1868
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
1876 memset(&buf, 0, sizeof(buf));
1877 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1878 buf.m.planes = planes;
1879 buf.length = VIDEO_ENCODER_OUTBUF_PLANES;
1880
1881 pMutex = (pthread_mutex_t*)pCtx->pOutMutex;
1882 pthread_mutex_lock(pMutex);
1883 index = MFC_Encoder_Find_Outbuf(pCtx, pBuffer[0]);
1884 if (index == -1) {
1885 pthread_mutex_unlock(pMutex);
1886 ALOGE("%s: Failed to get index", __func__);
1887 ret = VIDEO_ERROR_NOBUFFERS;
1888 goto EXIT;
1889 }
1890 buf.index = index;
1891 pCtx->pOutbuf[buf.index].bQueued = VIDEO_TRUE;
1892 pthread_mutex_unlock(pMutex);
1893
1894 if (pCtx->bShareOutbuf == VIDEO_TRUE) {
1895 buf.memory = pCtx->nMemoryType;
1896 for (i = 0; i < nPlanes; i++) {
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;
1901 buf.m.planes[i].length = pCtx->pOutbuf[index].planes[i].allocSize;
1902 buf.m.planes[i].bytesused = dataSize[i];
1903 }
1904 } else {
1905 buf.memory = V4L2_MEMORY_MMAP;
1906 }
1907
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;
1911 ret = VIDEO_ERROR_APIFAIL;
1912 goto EXIT;
1913 }
1914
1915 pCtx->pOutbuf[buf.index].pPrivate = pPrivate;
1916
1917 EXIT:
1918 return ret;
1919 }
1920
1921 /*
1922 * [Encoder Buffer OPS] Enqueue All (Output)
1923 */
1924 static ExynosVideoErrorType MFC_Encoder_Enqueue_All_Outbuf(void *pHandle)
1925 {
1926 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
1927 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1928
1929 unsigned char *pBuffer[VIDEO_BUFFER_MAX_PLANES] = {NULL, };
1930 unsigned int dataSize[VIDEO_BUFFER_MAX_PLANES] = {0, };
1931
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
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 }
1945
1946 EXIT:
1947 return ret;
1948 }
1949
1950 /*
1951 * [Encoder Buffer OPS] Dequeue (Input)
1952 */
1953 static ExynosVideoBuffer *MFC_Encoder_Dequeue_Inbuf(void *pHandle)
1954 {
1955 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
1956 ExynosVideoBuffer *pInbuf = NULL;
1957
1958 struct v4l2_buffer buf;
1959
1960 if (pCtx == NULL) {
1961 ALOGE("%s: Video context info must be supplied", __func__);
1962 goto EXIT;
1963 }
1964
1965 if (pCtx->bStreamonInbuf == VIDEO_FALSE) {
1966 pInbuf = NULL;
1967 goto EXIT;
1968 }
1969
1970 memset(&buf, 0, sizeof(buf));
1971
1972 buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1973
1974 if (pCtx->bShareInbuf == VIDEO_TRUE)
1975 buf.memory = pCtx->nMemoryType;
1976 else
1977 buf.memory = V4L2_MEMORY_MMAP;
1978
1979 if (exynos_v4l2_dqbuf(pCtx->hEnc, &buf) != 0) {
1980 pInbuf = NULL;
1981 goto EXIT;
1982 }
1983
1984 pInbuf = &pCtx->pInbuf[buf.index];
1985 pCtx->pInbuf[buf.index].bQueued = VIDEO_FALSE;
1986
1987 EXIT:
1988 return pInbuf;
1989 }
1990
1991 /*
1992 * [Encoder Buffer OPS] Dequeue (Output)
1993 */
1994 static ExynosVideoBuffer *MFC_Encoder_Dequeue_Outbuf(void *pHandle)
1995 {
1996 ExynosVideoEncContext *pCtx = (ExynosVideoEncContext *)pHandle;
1997 ExynosVideoBuffer *pOutbuf = NULL;
1998
1999 struct v4l2_buffer buf;
2000 struct v4l2_plane planes[VIDEO_ENCODER_OUTBUF_PLANES];
2001 int value;
2002
2003 if (pCtx == NULL) {
2004 ALOGE("%s: Video context info must be supplied", __func__);
2005 goto EXIT;
2006 }
2007
2008 if (pCtx->bStreamonOutbuf == VIDEO_FALSE) {
2009 pOutbuf = NULL;
2010 goto EXIT;
2011 }
2012
2013 memset(&buf, 0, sizeof(buf));
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)
2019 buf.memory = pCtx->nMemoryType;
2020 else
2021 buf.memory = V4L2_MEMORY_MMAP;
2022
2023 /* no error case for output buffer dequeue in encoder */
2024 if (exynos_v4l2_dqbuf(pCtx->hEnc, &buf) != 0) {
2025 goto EXIT;
2026 }
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:
2042 ALOGI("%s: encoded frame type is = %d",__func__, (buf.flags & (0x7 << 3)));
2043 pOutbuf->frameType = VIDEO_FRAME_OTHERS;
2044 break;
2045 };
2046
2047 pOutbuf->bQueued = VIDEO_FALSE;
2048
2049 EXIT:
2050 return pOutbuf;
2051 }
2052
2053 static 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
2065 for (i = 0; i < pCtx->nInbufs; i++) {
2066 pCtx->pInbuf[i].bQueued = VIDEO_FALSE;
2067 }
2068
2069 EXIT:
2070 return ret;
2071 }
2072
2073 static 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
2089 EXIT:
2090 return ret;
2091 }
2092
2093 /*
2094 * [Encoder OPS] Common
2095 */
2096 static ExynosVideoEncOps defEncOps = {
2097 .nSize = 0,
2098 .Init = MFC_Encoder_Init,
2099 .Finalize = MFC_Encoder_Finalize,
2100 .Set_EncParam = MFC_Encoder_Set_EncParam,
2101 .Set_FrameType = MFC_Encoder_Set_FrameType,
2102 .Set_FrameRate = MFC_Encoder_Set_FrameRate,
2103 .Set_BitRate = MFC_Encoder_Set_BitRate,
2104 .Set_FrameSkip = MFC_Encoder_Set_FrameSkip,
2105 .Set_IDRPeriod = MFC_Encoder_Set_IDRPeriod,
2106 .Set_FrameTag = MFC_Encoder_Set_FrameTag,
2107 .Get_FrameTag = MFC_Encoder_Get_FrameTag,
2108 };
2109
2110 /*
2111 * [Encoder Buffer OPS] Input
2112 */
2113 static ExynosVideoEncBufferOps defInbufOps = {
2114 .nSize = 0,
2115 .Enable_Cacheable = MFC_Encoder_Enable_Cacheable_Inbuf,
2116 .Set_Shareable = MFC_Encoder_Set_Shareable_Inbuf,
2117 .Get_Buffer = NULL,
2118 .Set_Geometry = MFC_Encoder_Set_Geometry_Inbuf,
2119 .Get_Geometry = MFC_Encoder_Get_Geometry_Inbuf,
2120 .Setup = MFC_Encoder_Setup_Inbuf,
2121 .Run = MFC_Encoder_Run_Inbuf,
2122 .Stop = MFC_Encoder_Stop_Inbuf,
2123 .Enqueue = MFC_Encoder_Enqueue_Inbuf,
2124 .Enqueue_All = NULL,
2125 .Dequeue = MFC_Encoder_Dequeue_Inbuf,
2126 .Register = MFC_Encoder_Register_Inbuf,
2127 .Clear_RegisteredBuffer = MFC_Encoder_Clear_RegisteredBuffer_Inbuf,
2128 .Clear_Queue = MFC_Encoder_Clear_Queued_Inbuf,
2129 };
2130
2131 /*
2132 * [Encoder Buffer OPS] Output
2133 */
2134 static ExynosVideoEncBufferOps defOutbufOps = {
2135 .nSize = 0,
2136 .Enable_Cacheable = MFC_Encoder_Enable_Cacheable_Outbuf,
2137 .Set_Shareable = MFC_Encoder_Set_Shareable_Outbuf,
2138 .Get_Buffer = MFC_Encoder_Get_Buffer_Outbuf,
2139 .Set_Geometry = MFC_Encoder_Set_Geometry_Outbuf,
2140 .Get_Geometry = MFC_Encoder_Get_Geometry_Outbuf,
2141 .Setup = MFC_Encoder_Setup_Outbuf,
2142 .Run = MFC_Encoder_Run_Outbuf,
2143 .Stop = MFC_Encoder_Stop_Outbuf,
2144 .Enqueue = MFC_Encoder_Enqueue_Outbuf,
2145 .Enqueue_All = NULL,
2146 .Dequeue = MFC_Encoder_Dequeue_Outbuf,
2147 .Register = MFC_Encoder_Register_Outbuf,
2148 .Clear_RegisteredBuffer = MFC_Encoder_Clear_RegisteredBuffer_Outbuf,
2149 .Clear_Queue = MFC_Encoder_Clear_Queued_Outbuf,
2150 };
2151
2152 int Exynos_Video_Register_Encoder(
2153 ExynosVideoEncOps *pEncOps,
2154 ExynosVideoEncBufferOps *pInbufOps,
2155 ExynosVideoEncBufferOps *pOutbufOps)
2156 {
2157 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
2158
2159 if ((pEncOps == NULL) || (pInbufOps == NULL) || (pOutbufOps == NULL)) {
2160 ret = VIDEO_ERROR_BADPARAM;
2161 goto EXIT;
2162 }
2163
2164 defEncOps.nSize = sizeof(defEncOps);
2165 defInbufOps.nSize = sizeof(defInbufOps);
2166 defOutbufOps.nSize = sizeof(defOutbufOps);
2167
2168 memcpy((char *)pEncOps + sizeof(pEncOps->nSize), (char *)&defEncOps + sizeof(defEncOps.nSize),
2169 pEncOps->nSize - sizeof(pEncOps->nSize));
2170
2171 memcpy((char *)pInbufOps + sizeof(pInbufOps->nSize), (char *)&defInbufOps + sizeof(defInbufOps.nSize),
2172 pInbufOps->nSize - sizeof(pInbufOps->nSize));
2173
2174 memcpy((char *)pOutbufOps + sizeof(pOutbufOps->nSize), (char *)&defOutbufOps + sizeof(defOutbufOps.nSize),
2175 pOutbufOps->nSize - sizeof(pOutbufOps->nSize));
2176
2177 EXIT:
2178 return ret;
2179 }