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