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 ExynosVideoDecoder.c 20 * @brief 21 * @author Jinsung Yang (jsgood.yang@samsung.com) 22 * @version 1.0.0 23 * @history 24 * 2012.01.15: Initial Version 25 */ 26 27#include <stdio.h> 28#include <stdlib.h> 29#include <unistd.h> 30#include <string.h> 31#include <fcntl.h> 32 33#include <sys/types.h> 34#include <sys/stat.h> 35#include <sys/ioctl.h> 36#include <sys/mman.h> 37#include <pthread.h> 38 39#include <sys/poll.h> 40 41#include "ion.h" 42#include "ExynosVideoApi.h" 43#include "ExynosVideoDec.h" 44#include "OMX_Core.h" 45 46/* #define LOG_NDEBUG 0 */ 47#define LOG_TAG "ExynosVideoDecoder" 48#include <utils/Log.h> 49 50#define MAX_OUTPUTBUFFER_COUNT 32 51 52/* 53 * [Common] __CodingType_To_V4L2PixelFormat 54 */ 55static unsigned int __CodingType_To_V4L2PixelFormat(ExynosVideoCodingType codingType) 56{ 57 unsigned int pixelformat = V4L2_PIX_FMT_H264; 58 59 switch (codingType) { 60 case VIDEO_CODING_AVC: 61 pixelformat = V4L2_PIX_FMT_H264; 62 break; 63 case VIDEO_CODING_MPEG4: 64 pixelformat = V4L2_PIX_FMT_MPEG4; 65 break; 66 case VIDEO_CODING_VP8: 67 pixelformat = V4L2_PIX_FMT_VP8; 68 break; 69 case VIDEO_CODING_H263: 70 pixelformat = V4L2_PIX_FMT_H263; 71 break; 72 case VIDEO_CODING_VC1: 73 pixelformat = V4L2_PIX_FMT_VC1_ANNEX_G; 74 break; 75 case VIDEO_CODING_VC1_RCV: 76 pixelformat = V4L2_PIX_FMT_VC1_ANNEX_L; 77 break; 78 case VIDEO_CODING_MPEG2: 79 pixelformat = V4L2_PIX_FMT_MPEG2; 80 break; 81 default: 82 pixelformat = V4L2_PIX_FMT_H264; 83 break; 84 } 85 86 return pixelformat; 87} 88 89/* 90 * [Common] __ColorFormatType_To_V4L2PixelFormat 91 */ 92static unsigned int __ColorFormatType_To_V4L2PixelFormat(ExynosVideoColorFormatType colorFormatType) 93{ 94 unsigned int pixelformat = V4L2_PIX_FMT_NV12M; 95 96 switch (colorFormatType) { 97 case VIDEO_COLORFORMAT_NV12_TILED: 98 pixelformat = V4L2_PIX_FMT_NV12MT_16X16; 99 break; 100 case VIDEO_COLORFORMAT_NV21: 101 pixelformat = V4L2_PIX_FMT_NV21M; 102 break; 103 case VIDEO_COLORFORMAT_NV12: 104 default: 105 pixelformat = V4L2_PIX_FMT_NV12M; 106 break; 107 } 108 109 return pixelformat; 110} 111 112/* 113 * [Decoder OPS] Init 114 */ 115static void *MFC_Decoder_Init(int nMemoryType) 116{ 117 ExynosVideoDecContext *pCtx = NULL; 118 pthread_mutex_t *pMutex = NULL; 119 int needCaps = (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING); 120 121 pCtx = (ExynosVideoDecContext *)malloc(sizeof(*pCtx)); 122 if (pCtx == NULL) { 123 ALOGE("%s: Failed to allocate decoder context buffer", __func__); 124 goto EXIT_ALLOC_FAIL; 125 } 126 127 memset(pCtx, 0, sizeof(*pCtx)); 128 129 pCtx->hDec = exynos_v4l2_open_devname(VIDEO_DECODER_NAME, O_RDWR, 0); 130 if (pCtx->hDec < 0) { 131 ALOGE("%s: Failed to open decoder device", __func__); 132 goto EXIT_OPEN_FAIL; 133 } 134 135 if (!exynos_v4l2_querycap(pCtx->hDec, needCaps)) { 136 ALOGE("%s: Failed to querycap", __func__); 137 goto EXIT_QUERYCAP_FAIL; 138 } 139 140 pCtx->bStreamonInbuf = VIDEO_FALSE; 141 pCtx->bStreamonOutbuf = VIDEO_FALSE; 142 143 pCtx->nMemoryType = nMemoryType; 144 145 pMutex = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t)); 146 if (pMutex == NULL) { 147 ALOGE("%s: Failed to allocate mutex about input buffer", __func__); 148 goto EXIT_QUERYCAP_FAIL; 149 } 150 if (pthread_mutex_init(pMutex, NULL) != 0) { 151 free(pMutex); 152 goto EXIT_QUERYCAP_FAIL; 153 } 154 pCtx->pInMutex = (void*)pMutex; 155 156 pMutex = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t)); 157 if (pMutex == NULL) { 158 ALOGE("%s: Failed to allocate mutex about output buffer", __func__); 159 goto EXIT_QUERYCAP_FAIL; 160 } 161 if (pthread_mutex_init(pMutex, NULL) != 0) { 162 free(pMutex); 163 goto EXIT_QUERYCAP_FAIL; 164 } 165 pCtx->pOutMutex = (void*)pMutex; 166 167 pCtx->hIONHandle = (void*)ion_client_create(); 168 pCtx->nPrivateDataShareFD = ion_alloc((ion_client)pCtx->hIONHandle, 169 sizeof(PrivateDataShareBuffer) * VIDEO_BUFFER_MAX_NUM, 0, ION_HEAP_SYSTEM_MASK, ION_FLAG_CACHED); 170 pCtx->nPrivateDataShareAddress = 171 ion_map(pCtx->nPrivateDataShareFD, sizeof(PrivateDataShareBuffer) * VIDEO_BUFFER_MAX_NUM, 0); 172 memset(pCtx->nPrivateDataShareAddress, -1, sizeof(PrivateDataShareBuffer) * VIDEO_BUFFER_MAX_NUM); 173 174 return (void *)pCtx; 175 176EXIT_QUERYCAP_FAIL: 177 if (pCtx->pInMutex != NULL) { 178 pthread_mutex_destroy(pCtx->pInMutex); 179 free(pCtx->pInMutex); 180 } 181 182 if (pCtx->pOutMutex != NULL) { 183 pthread_mutex_destroy(pCtx->pOutMutex); 184 free(pCtx->pOutMutex); 185 } 186 187 close(pCtx->hDec); 188 189EXIT_OPEN_FAIL: 190 free(pCtx); 191 192EXIT_ALLOC_FAIL: 193 return NULL; 194} 195 196/* 197 * [Decoder OPS] Finalize 198 */ 199static ExynosVideoErrorType MFC_Decoder_Finalize(void *pHandle) 200{ 201 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle; 202 ExynosVideoPlane *pVideoPlane = NULL; 203 pthread_mutex_t *pMutex = NULL; 204 ExynosVideoErrorType ret = VIDEO_ERROR_NONE; 205 int i, j; 206 207 if (pCtx == NULL) { 208 ALOGE("%s: Video context info must be supplied", __func__); 209 ret = VIDEO_ERROR_BADPARAM; 210 goto EXIT; 211 } 212 213 ion_unmap(pCtx->nPrivateDataShareAddress, sizeof(PrivateDataShareBuffer) * VIDEO_BUFFER_MAX_NUM); 214 ion_free(pCtx->nPrivateDataShareFD); 215 ion_client_destroy((ion_client)pCtx->hIONHandle); 216 217 if (pCtx->pOutMutex != NULL) { 218 pMutex = (pthread_mutex_t*)pCtx->pOutMutex; 219 pthread_mutex_destroy(pMutex); 220 free(pMutex); 221 pCtx->pOutMutex = NULL; 222 } 223 224 if (pCtx->pInMutex != NULL) { 225 pMutex = (pthread_mutex_t*)pCtx->pInMutex; 226 pthread_mutex_destroy(pMutex); 227 free(pMutex); 228 pCtx->pInMutex = NULL; 229 } 230 231 if (pCtx->bShareInbuf == VIDEO_FALSE) { 232 for (i = 0; i < pCtx->nInbufs; i++) { 233 for (j = 0; j < VIDEO_DECODER_INBUF_PLANES; j++) { 234 pVideoPlane = &pCtx->pInbuf[i].planes[j]; 235 if (pVideoPlane->addr != NULL) { 236 munmap(pVideoPlane->addr, pVideoPlane->allocSize); 237 pVideoPlane->addr = NULL; 238 pVideoPlane->allocSize = 0; 239 pVideoPlane->dataSize = 0; 240 } 241 242 pCtx->pInbuf[i].pGeometry = NULL; 243 pCtx->pInbuf[i].bQueued = VIDEO_FALSE; 244 pCtx->pInbuf[i].bRegistered = VIDEO_FALSE; 245 } 246 } 247 } 248 249 if (pCtx->bShareOutbuf == VIDEO_FALSE) { 250 for (i = 0; i < pCtx->nOutbufs; i++) { 251 for (j = 0; j < VIDEO_DECODER_OUTBUF_PLANES; j++) { 252 pVideoPlane = &pCtx->pOutbuf[i].planes[j]; 253 if (pVideoPlane->addr != NULL) { 254 munmap(pVideoPlane->addr, pVideoPlane->allocSize); 255 pVideoPlane->addr = NULL; 256 pVideoPlane->allocSize = 0; 257 pVideoPlane->dataSize = 0; 258 } 259 260 pCtx->pOutbuf[i].pGeometry = NULL; 261 pCtx->pOutbuf[i].bQueued = VIDEO_FALSE; 262 pCtx->pOutbuf[i].bRegistered = VIDEO_FALSE; 263 } 264 } 265 } 266 267 if (pCtx->pInbuf != NULL) 268 free(pCtx->pInbuf); 269 270 if (pCtx->pOutbuf != NULL) 271 free(pCtx->pOutbuf); 272 273 if (pCtx->hDec > 0) 274 close(pCtx->hDec); 275 276 free(pCtx); 277 278EXIT: 279 return ret; 280} 281 282/* 283 * [Decoder OPS] Set Frame Tag 284 */ 285static ExynosVideoErrorType MFC_Decoder_Set_FrameTag( 286 void *pHandle, 287 int frameTag) 288{ 289 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle; 290 ExynosVideoErrorType ret = VIDEO_ERROR_NONE; 291 292 if (pCtx == NULL) { 293 ALOGE("%s: Video context info must be supplied", __func__); 294 ret = VIDEO_ERROR_BADPARAM; 295 goto EXIT; 296 } 297 298 if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG, frameTag) != 0) { 299 ret = VIDEO_ERROR_APIFAIL; 300 goto EXIT; 301 } 302 303EXIT: 304 return ret; 305} 306 307/* 308 * [Decoder OPS] Get Frame Tag 309 */ 310static int MFC_Decoder_Get_FrameTag(void *pHandle) 311{ 312 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle; 313 int frameTag = -1; 314 315 if (pCtx == NULL) { 316 ALOGE("%s: Video context info must be supplied", __func__); 317 goto EXIT; 318 } 319 320 exynos_v4l2_g_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG, &frameTag); 321 322EXIT: 323 return frameTag; 324} 325 326/* 327 * [Decoder OPS] Get Buffer Count 328 */ 329static int MFC_Decoder_Get_ActualBufferCount(void *pHandle) 330{ 331 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle; 332 int bufferCount = -1; 333 334 if (pCtx == NULL) { 335 ALOGE("%s: Video context info must be supplied", __func__); 336 goto EXIT; 337 } 338 339 exynos_v4l2_g_ctrl(pCtx->hDec, V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, &bufferCount); 340 341EXIT: 342 return bufferCount; 343} 344 345/* 346 * [Decoder OPS] Set Display Delay 347 */ 348static ExynosVideoErrorType MFC_Decoder_Set_DisplayDelay( 349 void *pHandle, 350 int delay) 351{ 352 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle; 353 ExynosVideoErrorType ret = VIDEO_ERROR_NONE; 354 355 if (pCtx == NULL) { 356 ALOGE("%s: Video context info must be supplied", __func__); 357 ret = VIDEO_ERROR_BADPARAM; 358 goto EXIT; 359 } 360 361 if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY, delay) != 0) { 362 ret = VIDEO_ERROR_APIFAIL; 363 goto EXIT; 364 } 365 366EXIT: 367 return ret; 368} 369 370/* 371 * [Decoder OPS] Set I-Frame Decoding 372 */ 373static ExynosVideoErrorType MFC_Decoder_Set_IFrameDecoding( 374 void *pHandle) 375{ 376 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle; 377 ExynosVideoErrorType ret = VIDEO_ERROR_NONE; 378 379 if (pCtx == NULL) { 380 ALOGE("%s: Video context info must be supplied", __func__); 381 ret = VIDEO_ERROR_BADPARAM; 382 goto EXIT; 383 } 384 385 if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC51_VIDEO_I_FRAME_DECODING, 1) != 0) { 386 ret = VIDEO_ERROR_APIFAIL; 387 goto EXIT; 388 } 389 390EXIT: 391 return ret; 392} 393 394/* 395 * [Decoder OPS] Enable Packed PB 396 */ 397static ExynosVideoErrorType MFC_Decoder_Enable_PackedPB(void *pHandle) 398{ 399 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle; 400 ExynosVideoErrorType ret = VIDEO_ERROR_NONE; 401 402 if (pCtx == NULL) { 403 ALOGE("%s: Video context info must be supplied", __func__); 404 ret = VIDEO_ERROR_BADPARAM; 405 goto EXIT; 406 } 407 408 if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC51_VIDEO_PACKED_PB, 1) != 0) { 409 ret = VIDEO_ERROR_APIFAIL; 410 goto EXIT; 411 } 412 413EXIT: 414 return ret; 415} 416 417/* 418 * [Decoder OPS] Enable Loop Filter 419 */ 420static ExynosVideoErrorType MFC_Decoder_Enable_LoopFilter(void *pHandle) 421{ 422 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle; 423 ExynosVideoErrorType ret = VIDEO_ERROR_NONE; 424 425 if (pCtx == NULL) { 426 ALOGE("%s: Video context info must be supplied", __func__); 427 ret = VIDEO_ERROR_BADPARAM; 428 goto EXIT; 429 } 430 431 if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER, 1) != 0) { 432 ret = VIDEO_ERROR_APIFAIL; 433 goto EXIT; 434 } 435 436EXIT: 437 return ret; 438} 439 440/* 441 * [Decoder OPS] Enable Slice Mode 442 */ 443static ExynosVideoErrorType MFC_Decoder_Enable_SliceMode(void *pHandle) 444{ 445 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle; 446 ExynosVideoErrorType ret = VIDEO_ERROR_NONE; 447 448 if (pCtx == NULL) { 449 ALOGE("%s: Video context info must be supplied", __func__); 450 ret = VIDEO_ERROR_BADPARAM; 451 goto EXIT; 452 } 453 454 if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE, 1) != 0) { 455 ret = VIDEO_ERROR_APIFAIL; 456 goto EXIT; 457 } 458 459EXIT: 460 return ret; 461} 462 463/* 464 * [Decoder OPS] Enable SEI Parsing 465 */ 466static ExynosVideoErrorType MFC_Decoder_Enable_SEIParsing(void *pHandle) 467{ 468 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle; 469 ExynosVideoErrorType ret = VIDEO_ERROR_NONE; 470 471 if (pCtx == NULL) { 472 ALOGE("%s: Video context info must be supplied", __func__); 473 ret = VIDEO_ERROR_BADPARAM; 474 goto EXIT; 475 } 476 477 if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_MPEG_VIDEO_H264_SEI_FRAME_PACKING, 1) != 0) { 478 ret = VIDEO_ERROR_APIFAIL; 479 goto EXIT; 480 } 481 482EXIT: 483 return ret; 484} 485 486/* 487 * [Decoder OPS] Get Frame Packing information 488 */ 489static ExynosVideoErrorType MFC_Decoder_Get_FramePackingInfo( 490 void *pHandle, 491 ExynosVideoFramePacking *pFramePacking) 492{ 493 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle; 494 ExynosVideoErrorType ret = VIDEO_ERROR_NONE; 495 496 struct v4l2_ext_control ext_ctrl[FRAME_PACK_SEI_INFO_NUM]; 497 struct v4l2_ext_controls ext_ctrls; 498 499 int seiAvailable, seiInfo, seiGridPos, i; 500 unsigned int seiArgmtId; 501 502 503 if ((pCtx == NULL) || (pFramePacking == NULL)) { 504 ALOGE("%s: Video context info or FramePacking pointer must be supplied", __func__); 505 ret = VIDEO_ERROR_BADPARAM; 506 goto EXIT; 507 } 508 509 memset(pFramePacking, 0, sizeof(*pFramePacking)); 510 memset(ext_ctrl, 0, (sizeof(struct v4l2_ext_control) * FRAME_PACK_SEI_INFO_NUM)); 511 512 ext_ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG; 513 ext_ctrls.count = FRAME_PACK_SEI_INFO_NUM; 514 ext_ctrls.controls = ext_ctrl; 515 ext_ctrl[0].id = V4L2_CID_MPEG_VIDEO_H264_SEI_FP_AVAIL; 516 ext_ctrl[1].id = V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRGMENT_ID; 517 ext_ctrl[2].id = V4L2_CID_MPEG_VIDEO_H264_SEI_FP_INFO; 518 ext_ctrl[3].id = V4L2_CID_MPEG_VIDEO_H264_SEI_FP_GRID_POS; 519 520 if (exynos_v4l2_g_ext_ctrl(pCtx->hDec, &ext_ctrls) != 0) { 521 ret = VIDEO_ERROR_APIFAIL; 522 goto EXIT; 523 } 524 525 seiAvailable = ext_ctrl[0].value; 526 seiArgmtId = ext_ctrl[1].value; 527 seiInfo = ext_ctrl[2].value; 528 seiGridPos = ext_ctrl[3].value; 529 530 pFramePacking->available = seiAvailable; 531 pFramePacking->arrangement_id = seiArgmtId; 532 533 pFramePacking->arrangement_cancel_flag = OPERATE_BIT(seiInfo, 0x1, 0); 534 pFramePacking->arrangement_type = OPERATE_BIT(seiInfo, 0x3f, 1); 535 pFramePacking->quincunx_sampling_flag = OPERATE_BIT(seiInfo, 0x1, 8); 536 pFramePacking->content_interpretation_type = OPERATE_BIT(seiInfo, 0x3f, 9); 537 pFramePacking->spatial_flipping_flag = OPERATE_BIT(seiInfo, 0x1, 15); 538 pFramePacking->frame0_flipped_flag = OPERATE_BIT(seiInfo, 0x1, 16); 539 pFramePacking->field_views_flag = OPERATE_BIT(seiInfo, 0x1, 17); 540 pFramePacking->current_frame_is_frame0_flag = OPERATE_BIT(seiInfo, 0x1, 18); 541 542 pFramePacking->frame0_grid_pos_x = OPERATE_BIT(seiGridPos, 0xf, 0); 543 pFramePacking->frame0_grid_pos_y = OPERATE_BIT(seiGridPos, 0xf, 4); 544 pFramePacking->frame1_grid_pos_x = OPERATE_BIT(seiGridPos, 0xf, 8); 545 pFramePacking->frame1_grid_pos_y = OPERATE_BIT(seiGridPos, 0xf, 12); 546 547EXIT: 548 return ret; 549} 550 551/* 552 * [Decoder Buffer OPS] Enable Cacheable (Input) 553 */ 554static ExynosVideoErrorType MFC_Decoder_Enable_Cacheable_Inbuf(void *pHandle) 555{ 556 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle; 557 ExynosVideoErrorType ret = VIDEO_ERROR_NONE; 558 559 if (pCtx == NULL) { 560 ALOGE("%s: Video context info must be supplied", __func__); 561 ret = VIDEO_ERROR_BADPARAM; 562 goto EXIT; 563 } 564 565 if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_CACHEABLE, 2) != 0) { 566 ret = VIDEO_ERROR_APIFAIL; 567 goto EXIT; 568 } 569 570EXIT: 571 return ret; 572} 573 574/* 575 * [Decoder Buffer OPS] Enable Cacheable (Output) 576 */ 577static ExynosVideoErrorType MFC_Decoder_Enable_Cacheable_Outbuf(void *pHandle) 578{ 579 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle; 580 ExynosVideoErrorType ret = VIDEO_ERROR_NONE; 581 582 if (pCtx == NULL) { 583 ALOGE("%s: Video context info must be supplied", __func__); 584 ret = VIDEO_ERROR_BADPARAM; 585 goto EXIT; 586 } 587 588 if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_CACHEABLE, 1) != 0) { 589 ret = VIDEO_ERROR_APIFAIL; 590 goto EXIT; 591 } 592 593EXIT: 594 return ret; 595} 596 597/* 598 * [Decoder Buffer OPS] Set Shareable Buffer (Input) 599 */ 600static ExynosVideoErrorType MFC_Decoder_Set_Shareable_Inbuf(void *pHandle) 601{ 602 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle; 603 ExynosVideoErrorType ret = VIDEO_ERROR_NONE; 604 605 if (pCtx == NULL) { 606 ALOGE("%s: Video context info must be supplied", __func__); 607 ret = VIDEO_ERROR_BADPARAM; 608 goto EXIT; 609 } 610 611 pCtx->bShareInbuf = VIDEO_TRUE; 612 613EXIT: 614 return ret; 615} 616 617/* 618 * [Decoder Buffer OPS] Set Shareable Buffer (Output) 619 */ 620static ExynosVideoErrorType MFC_Decoder_Set_Shareable_Outbuf(void *pHandle) 621{ 622 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle; 623 ExynosVideoErrorType ret = VIDEO_ERROR_NONE; 624 625 if (pCtx == NULL) { 626 ALOGE("%s: Video context info must be supplied", __func__); 627 ret = VIDEO_ERROR_BADPARAM; 628 goto EXIT; 629 } 630 631 pCtx->bShareOutbuf = VIDEO_TRUE; 632 633EXIT: 634 return ret; 635} 636 637/* 638 * [Decoder Buffer OPS] Get Buffer (Input) 639 */ 640static ExynosVideoErrorType MFC_Decoder_Get_Buffer_Inbuf( 641 void *pHandle, 642 int nIndex, 643 ExynosVideoBuffer **pBuffer) 644{ 645 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle; 646 ExynosVideoErrorType ret = VIDEO_ERROR_NONE; 647 648 if (pCtx == NULL) { 649 ALOGE("%s: Video context info must be supplied", __func__); 650 *pBuffer = NULL; 651 ret = VIDEO_ERROR_BADPARAM; 652 goto EXIT; 653 } 654 655 if (pCtx->nInbufs <= nIndex) { 656 *pBuffer = NULL; 657 ret = VIDEO_ERROR_BADPARAM; 658 goto EXIT; 659 } 660 661 *pBuffer = (ExynosVideoBuffer *)&pCtx->pInbuf[nIndex]; 662 663EXIT: 664 return ret; 665} 666 667/* 668 * [Decoder Buffer OPS] Get Buffer (Output) 669 */ 670static ExynosVideoErrorType MFC_Decoder_Get_Buffer_Outbuf( 671 void *pHandle, 672 int nIndex, 673 ExynosVideoBuffer **pBuffer) 674{ 675 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle; 676 ExynosVideoErrorType ret = VIDEO_ERROR_NONE; 677 678 if (pCtx == NULL) { 679 ALOGE("%s: Video context info must be supplied", __func__); 680 *pBuffer = NULL; 681 ret = VIDEO_ERROR_BADPARAM; 682 goto EXIT; 683 } 684 685 if (pCtx->nOutbufs <= nIndex) { 686 *pBuffer = NULL; 687 ret = VIDEO_ERROR_BADPARAM; 688 goto EXIT; 689 } 690 691 *pBuffer = (ExynosVideoBuffer *)&pCtx->pOutbuf[nIndex]; 692 693EXIT: 694 return ret; 695} 696 697/* 698 * [Decoder Buffer OPS] Set Geometry (Input) 699 */ 700static ExynosVideoErrorType MFC_Decoder_Set_Geometry_Inbuf( 701 void *pHandle, 702 ExynosVideoGeometry *bufferConf) 703{ 704 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle; 705 ExynosVideoErrorType ret = VIDEO_ERROR_NONE; 706 707 struct v4l2_format fmt; 708 709 if (pCtx == NULL) { 710 ALOGE("%s: Video context info must be supplied", __func__); 711 ret = VIDEO_ERROR_BADPARAM; 712 goto EXIT; 713 } 714 715 if (bufferConf == NULL) { 716 ALOGE("%s: Buffer geometry must be supplied", __func__); 717 ret = VIDEO_ERROR_BADPARAM; 718 goto EXIT; 719 } 720 721 memset(&fmt, 0, sizeof(fmt)); 722 723 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 724 fmt.fmt.pix_mp.pixelformat = __CodingType_To_V4L2PixelFormat(bufferConf->eCompressionFormat); 725 fmt.fmt.pix_mp.plane_fmt[0].sizeimage = bufferConf->nSizeImage; 726 727 if (exynos_v4l2_s_fmt(pCtx->hDec, &fmt) != 0) { 728 ret = VIDEO_ERROR_APIFAIL; 729 goto EXIT; 730 } 731 732 memcpy(&pCtx->inbufGeometry, bufferConf, sizeof(pCtx->inbufGeometry)); 733 734EXIT: 735 return ret; 736} 737 738/* 739 * [Decoder Buffer OPS] Set Geometry (Output) 740 */ 741static ExynosVideoErrorType MFC_Decoder_Set_Geometry_Outbuf( 742 void *pHandle, 743 ExynosVideoGeometry *bufferConf) 744{ 745 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle; 746 ExynosVideoErrorType ret = VIDEO_ERROR_NONE; 747 748 struct v4l2_format fmt; 749 750 if (pCtx == NULL) { 751 ALOGE("%s: Video context info must be supplied", __func__); 752 ret = VIDEO_ERROR_BADPARAM; 753 goto EXIT; 754 } 755 756 if (bufferConf == NULL) { 757 ALOGE("%s: Buffer geometry must be supplied", __func__); 758 ret = VIDEO_ERROR_BADPARAM; 759 goto EXIT; 760 } 761 762 memset(&fmt, 0, sizeof(fmt)); 763 764 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 765 fmt.fmt.pix_mp.pixelformat = __ColorFormatType_To_V4L2PixelFormat(bufferConf->eColorFormat); 766 767 if (exynos_v4l2_s_fmt(pCtx->hDec, &fmt) != 0) { 768 ret = VIDEO_ERROR_APIFAIL; 769 goto EXIT; 770 } 771 772 memcpy(&pCtx->outbufGeometry, bufferConf, sizeof(pCtx->outbufGeometry)); 773 774EXIT: 775 return ret; 776} 777 778/* 779 * [Decoder Buffer OPS] Get Geometry (Output) 780 */ 781static ExynosVideoErrorType MFC_Decoder_Get_Geometry_Outbuf( 782 void *pHandle, 783 ExynosVideoGeometry *bufferConf) 784{ 785 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle; 786 ExynosVideoErrorType ret = VIDEO_ERROR_NONE; 787 788 struct v4l2_format fmt; 789 struct v4l2_crop crop; 790 791 if (pCtx == NULL) { 792 ALOGE("%s: Video context info must be supplied", __func__); 793 ret = VIDEO_ERROR_BADPARAM; 794 goto EXIT; 795 } 796 797 if (bufferConf == NULL) { 798 ALOGE("%s: Buffer geometry must be supplied", __func__); 799 ret = VIDEO_ERROR_BADPARAM; 800 goto EXIT; 801 } 802 803 memset(&fmt, 0, sizeof(fmt)); 804 memset(&crop, 0, sizeof(crop)); 805 806 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 807 if (exynos_v4l2_g_fmt(pCtx->hDec, &fmt) != 0) { 808 ret = VIDEO_ERROR_APIFAIL; 809 goto EXIT; 810 } 811 812 crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 813 if (exynos_v4l2_g_crop(pCtx->hDec, &crop) != 0) { 814 ret = VIDEO_ERROR_APIFAIL; 815 goto EXIT; 816 } 817 818 bufferConf->nFrameWidth = fmt.fmt.pix_mp.width; 819 bufferConf->nFrameHeight = fmt.fmt.pix_mp.height; 820 821 bufferConf->cropRect.nTop = crop.c.top; 822 bufferConf->cropRect.nLeft = crop.c.left; 823 bufferConf->cropRect.nWidth = crop.c.width; 824 bufferConf->cropRect.nHeight = crop.c.height; 825 826EXIT: 827 return ret; 828} 829 830/* 831 * [Decoder Buffer OPS] Setup (Input) 832 */ 833static ExynosVideoErrorType MFC_Decoder_Setup_Inbuf( 834 void *pHandle, 835 unsigned int nBufferCount) 836{ 837 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle; 838 ExynosVideoPlane *pVideoPlane = NULL; 839 ExynosVideoErrorType ret = VIDEO_ERROR_NONE; 840 841 struct v4l2_requestbuffers req; 842 struct v4l2_buffer buf; 843 struct v4l2_plane planes[VIDEO_DECODER_INBUF_PLANES]; 844 int i; 845 846 if (pCtx == NULL) { 847 ALOGE("%s: Video context info must be supplied", __func__); 848 ret = VIDEO_ERROR_BADPARAM; 849 goto EXIT; 850 } 851 852 if (nBufferCount == 0) { 853 ALOGE("%s: Buffer count must be greater than 0", __func__); 854 ret = VIDEO_ERROR_BADPARAM; 855 goto EXIT; 856 } 857 858 ALOGV("%s: setting up inbufs (%d) shared=%s\n", __func__, nBufferCount, 859 pCtx->bShareInbuf ? "true" : "false"); 860 861 memset(&req, 0, sizeof(req)); 862 863 req.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 864 req.count = nBufferCount; 865 866 if (pCtx->bShareInbuf == VIDEO_TRUE) 867 req.memory = pCtx->nMemoryType; 868 else 869 req.memory = V4L2_MEMORY_MMAP; 870 871 if (exynos_v4l2_reqbufs(pCtx->hDec, &req) != 0) { 872 ret = VIDEO_ERROR_APIFAIL; 873 goto EXIT; 874 } 875 876 if (req.count != nBufferCount) { 877 ALOGE("%s: asked for %d, got %d\n", __func__, nBufferCount, req.count); 878 ret = VIDEO_ERROR_NOMEM; 879 goto EXIT; 880 } 881 882 pCtx->nInbufs = (int)req.count; 883 884 pCtx->pInbuf = malloc(sizeof(*pCtx->pInbuf) * pCtx->nInbufs); 885 if (pCtx->pInbuf == NULL) { 886 ALOGE("Failed to allocate input buffer context"); 887 ret = VIDEO_ERROR_NOMEM; 888 goto EXIT; 889 } 890 memset(pCtx->pInbuf, 0, sizeof(*pCtx->pInbuf) * pCtx->nInbufs); 891 892 memset(&buf, 0, sizeof(buf)); 893 894 if (pCtx->bShareInbuf == VIDEO_FALSE) { 895 buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 896 buf.memory = V4L2_MEMORY_MMAP; 897 buf.m.planes = planes; 898 buf.length = VIDEO_DECODER_INBUF_PLANES; 899 900 for (i = 0; i < pCtx->nInbufs; i++) { 901 buf.index = i; 902 if (exynos_v4l2_querybuf(pCtx->hDec, &buf) != 0) { 903 ret = VIDEO_ERROR_APIFAIL; 904 goto EXIT; 905 } 906 907 pVideoPlane = &pCtx->pInbuf[i].planes[0]; 908 909 pVideoPlane->addr = mmap(NULL, 910 buf.m.planes[0].length, PROT_READ | PROT_WRITE, 911 MAP_SHARED, pCtx->hDec, buf.m.planes[0].m.mem_offset); 912 913 if (pVideoPlane->addr == MAP_FAILED) { 914 ret = VIDEO_ERROR_MAPFAIL; 915 goto EXIT; 916 } 917 918 pVideoPlane->allocSize = buf.m.planes[0].length; 919 pVideoPlane->dataSize = 0; 920 921 pCtx->pInbuf[i].pGeometry = &pCtx->inbufGeometry; 922 pCtx->pInbuf[i].bQueued = VIDEO_FALSE; 923 pCtx->pInbuf[i].bRegistered = VIDEO_TRUE; 924 } 925 } 926 927 return ret; 928 929EXIT: 930 if ((pCtx != NULL) && (pCtx->pInbuf != NULL)) { 931 if (pCtx->bShareInbuf == VIDEO_FALSE) { 932 for (i = 0; i < pCtx->nInbufs; i++) { 933 pVideoPlane = &pCtx->pInbuf[i].planes[0]; 934 if (pVideoPlane->addr == MAP_FAILED) { 935 pVideoPlane->addr = NULL; 936 break; 937 } 938 939 munmap(pVideoPlane->addr, pVideoPlane->allocSize); 940 } 941 } 942 943 free(pCtx->pInbuf); 944 } 945 946 return ret; 947} 948 949/* 950 * [Decoder Buffer OPS] Setup (Output) 951 */ 952static ExynosVideoErrorType MFC_Decoder_Setup_Outbuf( 953 void *pHandle, 954 unsigned int nBufferCount) 955{ 956 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle; 957 ExynosVideoPlane *pVideoPlane = NULL; 958 ExynosVideoErrorType ret = VIDEO_ERROR_NONE; 959 960 struct v4l2_requestbuffers req; 961 struct v4l2_buffer buf; 962 struct v4l2_plane planes[VIDEO_DECODER_OUTBUF_PLANES]; 963 int i, j; 964 965 if (pCtx == NULL) { 966 ALOGE("%s: Video context info must be supplied", __func__); 967 ret = VIDEO_ERROR_BADPARAM; 968 goto EXIT; 969 } 970 971 if (nBufferCount == 0) { 972 nBufferCount = MAX_OUTPUTBUFFER_COUNT; 973 ALOGV("%s: Change buffer count %d", __func__, nBufferCount); 974 } 975 976 ALOGV("%s: setting up outbufs (%d) shared=%s\n", __func__, nBufferCount, 977 pCtx->bShareOutbuf ? "true" : "false"); 978 979 memset(&req, 0, sizeof(req)); 980 981 req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 982 req.count = nBufferCount; 983 984 if (pCtx->bShareOutbuf == VIDEO_TRUE) 985 req.memory = pCtx->nMemoryType; 986 else 987 req.memory = V4L2_MEMORY_MMAP; 988 989 if (exynos_v4l2_reqbufs(pCtx->hDec, &req) != 0) { 990 ret = VIDEO_ERROR_APIFAIL; 991 goto EXIT; 992 } 993 994 if (req.count != nBufferCount) { 995 ALOGE("%s: asked for %d, got %d\n", __func__, nBufferCount, req.count); 996 ret = VIDEO_ERROR_NOMEM; 997 goto EXIT; 998 } 999 1000 pCtx->nOutbufs = req.count; 1001 1002 pCtx->pOutbuf = malloc(sizeof(*pCtx->pOutbuf) * pCtx->nOutbufs); 1003 if (pCtx->pOutbuf == NULL) { 1004 ALOGE("Failed to allocate output buffer context"); 1005 ret = VIDEO_ERROR_NOMEM; 1006 goto EXIT; 1007 } 1008 memset(pCtx->pOutbuf, 0, sizeof(*pCtx->pOutbuf) * pCtx->nOutbufs); 1009 1010 memset(&buf, 0, sizeof(buf)); 1011 1012 if (pCtx->bShareOutbuf == VIDEO_FALSE) { 1013 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 1014 buf.memory = V4L2_MEMORY_MMAP; 1015 buf.m.planes = planes; 1016 buf.length = VIDEO_DECODER_OUTBUF_PLANES; 1017 1018 for (i = 0; i < pCtx->nOutbufs; i++) { 1019 buf.index = i; 1020 if (exynos_v4l2_querybuf(pCtx->hDec, &buf) != 0) { 1021 ret = VIDEO_ERROR_APIFAIL; 1022 goto EXIT; 1023 } 1024 1025 for (j = 0; j < VIDEO_DECODER_OUTBUF_PLANES; j++) { 1026 pVideoPlane = &pCtx->pOutbuf[i].planes[j]; 1027 pVideoPlane->addr = mmap(NULL, 1028 buf.m.planes[j].length, PROT_READ | PROT_WRITE, 1029 MAP_SHARED, pCtx->hDec, buf.m.planes[j].m.mem_offset); 1030 1031 if (pVideoPlane->addr == MAP_FAILED) { 1032 ret = VIDEO_ERROR_MAPFAIL; 1033 goto EXIT; 1034 } 1035 1036 pVideoPlane->allocSize = buf.m.planes[j].length; 1037 pVideoPlane->dataSize = 0; 1038 } 1039 1040 pCtx->pOutbuf[i].pGeometry = &pCtx->outbufGeometry; 1041 pCtx->pOutbuf[i].bQueued = VIDEO_FALSE; 1042 pCtx->pOutbuf[i].bSlotUsed = VIDEO_FALSE; 1043 pCtx->pOutbuf[i].nIndexUseCnt = 0; 1044 pCtx->pOutbuf[i].bRegistered = VIDEO_TRUE; 1045 } 1046 } 1047 1048 return ret; 1049 1050EXIT: 1051 if ((pCtx != NULL) && (pCtx->pOutbuf != NULL)) { 1052 if (pCtx->bShareOutbuf == VIDEO_FALSE) { 1053 for (i = 0; i < pCtx->nOutbufs; i++) { 1054 for (j = 0; j < VIDEO_DECODER_OUTBUF_PLANES; j++) { 1055 pVideoPlane = &pCtx->pOutbuf[i].planes[j]; 1056 if (pVideoPlane->addr == MAP_FAILED) { 1057 pVideoPlane->addr = NULL; 1058 break; 1059 } 1060 1061 munmap(pVideoPlane->addr, pVideoPlane->allocSize); 1062 } 1063 } 1064 } 1065 1066 free(pCtx->pOutbuf); 1067 pCtx->pOutbuf = NULL; 1068 } 1069 1070 return ret; 1071} 1072 1073/* 1074 * [Decoder Buffer OPS] Run (Input) 1075 */ 1076static ExynosVideoErrorType MFC_Decoder_Run_Inbuf(void *pHandle) 1077{ 1078 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle; 1079 ExynosVideoErrorType ret = VIDEO_ERROR_NONE; 1080 1081 if (pCtx == NULL) { 1082 ALOGE("%s: Video context info must be supplied", __func__); 1083 ret = VIDEO_ERROR_BADPARAM; 1084 goto EXIT; 1085 } 1086 1087 if (pCtx->bStreamonInbuf == VIDEO_FALSE) { 1088 if (exynos_v4l2_streamon(pCtx->hDec, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) != 0) { 1089 ALOGE("%s: Failed to streamon for input buffer", __func__); 1090 ret = VIDEO_ERROR_APIFAIL; 1091 goto EXIT; 1092 } 1093 pCtx->bStreamonInbuf = VIDEO_TRUE; 1094 } 1095 1096EXIT: 1097 return ret; 1098} 1099 1100/* 1101 * [Decoder Buffer OPS] Run (Output) 1102 */ 1103static ExynosVideoErrorType MFC_Decoder_Run_Outbuf(void *pHandle) 1104{ 1105 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle; 1106 ExynosVideoErrorType ret = VIDEO_ERROR_NONE; 1107 1108 if (pCtx == NULL) { 1109 ALOGE("%s: Video context info must be supplied", __func__); 1110 ret = VIDEO_ERROR_BADPARAM; 1111 goto EXIT; 1112 } 1113 1114 if (pCtx->bStreamonOutbuf == VIDEO_FALSE) { 1115 if (exynos_v4l2_streamon(pCtx->hDec, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) != 0) { 1116 ALOGE("%s: Failed to streamon for output buffer", __func__); 1117 ret = VIDEO_ERROR_APIFAIL; 1118 goto EXIT; 1119 } 1120 pCtx->bStreamonOutbuf = VIDEO_TRUE; 1121 } 1122 1123EXIT: 1124 return ret; 1125} 1126 1127/* 1128 * [Decoder Buffer OPS] Stop (Input) 1129 */ 1130static ExynosVideoErrorType MFC_Decoder_Stop_Inbuf(void *pHandle) 1131{ 1132 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle; 1133 ExynosVideoErrorType ret = VIDEO_ERROR_NONE; 1134 int i = 0; 1135 1136 if (pCtx == NULL) { 1137 ALOGE("%s: Video context info must be supplied", __func__); 1138 ret = VIDEO_ERROR_BADPARAM; 1139 goto EXIT; 1140 } 1141 1142 if (pCtx->bStreamonInbuf == VIDEO_TRUE) { 1143 if (exynos_v4l2_streamoff(pCtx->hDec, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) != 0) { 1144 ALOGE("%s: Failed to streamoff for input buffer", __func__); 1145 ret = VIDEO_ERROR_APIFAIL; 1146 goto EXIT; 1147 } 1148 pCtx->bStreamonInbuf = VIDEO_FALSE; 1149 } 1150 1151 for (i = 0; i < pCtx->nInbufs; i++) { 1152 pCtx->pInbuf[i].bQueued = VIDEO_FALSE; 1153 } 1154 1155EXIT: 1156 return ret; 1157} 1158 1159/* 1160 * [Decoder Buffer OPS] Stop (Output) 1161 */ 1162static ExynosVideoErrorType MFC_Decoder_Stop_Outbuf(void *pHandle) 1163{ 1164 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle; 1165 ExynosVideoErrorType ret = VIDEO_ERROR_NONE; 1166 int i = 0; 1167 1168 if (pCtx == NULL) { 1169 ALOGE("%s: Video context info must be supplied", __func__); 1170 ret = VIDEO_ERROR_BADPARAM; 1171 goto EXIT; 1172 } 1173 1174 if (pCtx->bStreamonOutbuf == VIDEO_TRUE) { 1175 if (exynos_v4l2_streamoff(pCtx->hDec, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) != 0) { 1176 ALOGE("%s: Failed to streamoff for output buffer", __func__); 1177 ret = VIDEO_ERROR_APIFAIL; 1178 goto EXIT; 1179 } 1180 pCtx->bStreamonOutbuf = VIDEO_FALSE; 1181 } 1182 1183 for (i = 0; i < pCtx->nOutbufs; i++) { 1184 pCtx->pOutbuf[i].bQueued = VIDEO_FALSE; 1185 pCtx->pOutbuf[i].bSlotUsed = VIDEO_FALSE; 1186 pCtx->pOutbuf[i].nIndexUseCnt = 0; 1187 } 1188 1189EXIT: 1190 return ret; 1191} 1192 1193/* 1194 * [Decoder Buffer OPS] Wait (Input) 1195 */ 1196static ExynosVideoErrorType MFC_Decoder_Wait_Inbuf(void *pHandle) 1197{ 1198 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle; 1199 ExynosVideoErrorType ret = VIDEO_ERROR_NONE; 1200 1201 struct pollfd poll_events; 1202 int poll_state; 1203 1204 if (pCtx == NULL) { 1205 ALOGE("%s: Video context info must be supplied", __func__); 1206 ret = VIDEO_ERROR_BADPARAM; 1207 goto EXIT; 1208 } 1209 1210 poll_events.fd = pCtx->hDec; 1211 poll_events.events = POLLOUT | POLLERR; 1212 poll_events.revents = 0; 1213 1214 do { 1215 poll_state = poll((struct pollfd*)&poll_events, 1, VIDEO_DECODER_POLL_TIMEOUT); 1216 if (poll_state > 0) { 1217 if (poll_events.revents & POLLOUT) { 1218 break; 1219 } else { 1220 ALOGE("%s: Poll return error", __func__); 1221 ret = VIDEO_ERROR_POLL; 1222 break; 1223 } 1224 } else if (poll_state < 0) { 1225 ALOGE("%s: Poll state error", __func__); 1226 ret = VIDEO_ERROR_POLL; 1227 break; 1228 } 1229 } while (poll_state == 0); 1230 1231EXIT: 1232 return ret; 1233} 1234 1235static ExynosVideoErrorType MFC_Decoder_Register_Inbuf( 1236 void *pHandle, 1237 ExynosVideoPlane *planes, 1238 int nPlanes) 1239{ 1240 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle; 1241 ExynosVideoErrorType ret = VIDEO_ERROR_NONE; 1242 int nIndex, plane; 1243 1244 if ((pCtx == NULL) || (planes == NULL) || (nPlanes != VIDEO_DECODER_INBUF_PLANES)) { 1245 ALOGE("%s: params must be supplied", __func__); 1246 ret = VIDEO_ERROR_BADPARAM; 1247 goto EXIT; 1248 } 1249 1250 for (nIndex = 0; nIndex < pCtx->nInbufs; nIndex++) { 1251 if (pCtx->pInbuf[nIndex].bRegistered == VIDEO_FALSE) { 1252 for (plane = 0; plane < nPlanes; plane++) { 1253 pCtx->pInbuf[nIndex].planes[plane].addr = planes[plane].addr; 1254 pCtx->pInbuf[nIndex].planes[plane].allocSize = planes[plane].allocSize; 1255 pCtx->pInbuf[nIndex].planes[plane].fd = planes[plane].fd; 1256 ALOGV("%s: registered buf %d (addr=%p alloc_sz=%ld fd=%d)\n", __func__, nIndex, 1257 planes[plane].addr, planes[plane].allocSize, planes[plane].fd); 1258 } 1259 pCtx->pInbuf[nIndex].bRegistered = VIDEO_TRUE; 1260 break; 1261 } 1262 } 1263 1264 if (nIndex == pCtx->nInbufs) { 1265 ALOGE("%s: can not find non-registered input buffer", __func__); 1266 ret = VIDEO_ERROR_NOBUFFERS; 1267 } 1268 1269EXIT: 1270 return ret; 1271} 1272 1273static ExynosVideoErrorType MFC_Decoder_Register_Outbuf( 1274 void *pHandle, 1275 ExynosVideoPlane *planes, 1276 int nPlanes) 1277{ 1278 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle; 1279 ExynosVideoErrorType ret = VIDEO_ERROR_NONE; 1280 int nIndex, plane; 1281 1282 if ((pCtx == NULL) || (planes == NULL) || (nPlanes != VIDEO_DECODER_OUTBUF_PLANES)) { 1283 ALOGE("%s: params must be supplied", __func__); 1284 ret = VIDEO_ERROR_BADPARAM; 1285 goto EXIT; 1286 } 1287 1288 for (nIndex = 0; nIndex < pCtx->nOutbufs; nIndex++) { 1289 if (pCtx->pOutbuf[nIndex].bRegistered == VIDEO_FALSE) { 1290 for (plane = 0; plane < nPlanes; plane++) { 1291 pCtx->pOutbuf[nIndex].planes[plane].addr = planes[plane].addr; 1292 pCtx->pOutbuf[nIndex].planes[plane].allocSize = planes[plane].allocSize; 1293 pCtx->pOutbuf[nIndex].planes[plane].fd = planes[plane].fd; 1294 } 1295 pCtx->pOutbuf[nIndex].bRegistered = VIDEO_TRUE; 1296 ALOGV("%s: registered buf %d 0:(addr=%p alloc_sz=%d fd=%d) 1:(addr=%p alloc_sz=%d fd=%d)\n", 1297 __func__, nIndex, planes[0].addr, planes[0].allocSize, planes[0].fd, 1298 planes[1].addr, planes[1].allocSize, planes[1].fd); 1299 break; 1300 } 1301 } 1302 1303 if (nIndex == pCtx->nOutbufs) { 1304 ALOGE("%s: can not find non-registered output buffer", __func__); 1305 ret = VIDEO_ERROR_NOBUFFERS; 1306 } 1307 1308EXIT: 1309 return ret; 1310} 1311 1312static ExynosVideoErrorType MFC_Decoder_Clear_RegisteredBuffer_Inbuf(void *pHandle) 1313{ 1314 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle; 1315 ExynosVideoErrorType ret = VIDEO_ERROR_NONE; 1316 int nIndex; 1317 1318 if (pCtx == NULL) { 1319 ALOGE("%s: Video context info must be supplied", __func__); 1320 ret = VIDEO_ERROR_BADPARAM; 1321 goto EXIT; 1322 } 1323 1324 for (nIndex = 0; nIndex < pCtx->nInbufs; nIndex++) { 1325 pCtx->pInbuf[nIndex].planes[0].addr = NULL; 1326 pCtx->pInbuf[nIndex].bRegistered = VIDEO_FALSE; 1327 } 1328 1329EXIT: 1330 return ret; 1331} 1332 1333static ExynosVideoErrorType MFC_Decoder_Clear_RegisteredBuffer_Outbuf(void *pHandle) 1334{ 1335 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle; 1336 ExynosVideoErrorType ret = VIDEO_ERROR_NONE; 1337 int nIndex; 1338 1339 if (pCtx == NULL) { 1340 ALOGE("%s: Video context info must be supplied", __func__); 1341 ret = VIDEO_ERROR_BADPARAM; 1342 goto EXIT; 1343 } 1344 1345 for (nIndex = 0; nIndex < pCtx->nOutbufs; nIndex++) { 1346 pCtx->pOutbuf[nIndex].planes[0].addr = NULL; 1347 pCtx->pOutbuf[nIndex].bRegistered = VIDEO_FALSE; 1348 } 1349 1350EXIT: 1351 return ret; 1352} 1353 1354/* 1355 * [Decoder Buffer OPS] Find (Input) 1356 */ 1357static int MFC_Decoder_Find_Inbuf( 1358 void *pHandle, 1359 unsigned char *pBuffer) 1360{ 1361 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle; 1362 int nIndex = -1; 1363 1364 if (pCtx == NULL) { 1365 ALOGE("%s: Video context info must be supplied", __func__); 1366 goto EXIT; 1367 } 1368 1369 for (nIndex = 0; nIndex < pCtx->nInbufs; nIndex++) { 1370 if (pCtx->pInbuf[nIndex].bQueued == VIDEO_FALSE) { 1371 if ((pBuffer == NULL) || 1372 (pCtx->pInbuf[nIndex].planes[0].addr == pBuffer)) 1373 break; 1374 } 1375 } 1376 1377 if (nIndex == pCtx->nInbufs) 1378 nIndex = -1; 1379 1380EXIT: 1381 return nIndex; 1382} 1383 1384/* 1385 * [Decoder Buffer OPS] Find (Outnput) 1386 */ 1387static int MFC_Decoder_Find_Outbuf( 1388 void *pHandle, 1389 unsigned char *pBuffer) 1390{ 1391 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle; 1392 int nIndex = -1; 1393 1394 if (pCtx == NULL) { 1395 ALOGE("%s: Video context info must be supplied", __func__); 1396 goto EXIT; 1397 } 1398 1399 for (nIndex = 0; nIndex < pCtx->nOutbufs; nIndex++) { 1400 if (pCtx->pOutbuf[nIndex].bQueued == VIDEO_FALSE) { 1401 if ((pBuffer == NULL) || 1402 (pCtx->pOutbuf[nIndex].planes[0].addr == pBuffer)) 1403 break; 1404 } 1405 } 1406 1407 if (nIndex == pCtx->nOutbufs) 1408 nIndex = -1; 1409 1410EXIT: 1411 return nIndex; 1412} 1413 1414/* 1415 * [Decoder Buffer OPS] Enqueue (Input) 1416 */ 1417static ExynosVideoErrorType MFC_Decoder_Enqueue_Inbuf( 1418 void *pHandle, 1419 unsigned char *pBuffer[], 1420 unsigned int dataSize[], 1421 int nPlanes, 1422 void *pPrivate) 1423{ 1424 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle; 1425 ExynosVideoErrorType ret = VIDEO_ERROR_NONE; 1426 pthread_mutex_t *pMutex = NULL; 1427 1428 struct v4l2_plane planes[VIDEO_DECODER_INBUF_PLANES]; 1429 struct v4l2_buffer buf; 1430 int index, i; 1431 1432 if (pCtx == NULL) { 1433 ALOGE("%s: Video context info must be supplied", __func__); 1434 ret = VIDEO_ERROR_BADPARAM; 1435 goto EXIT; 1436 } 1437 1438 if (VIDEO_DECODER_INBUF_PLANES < nPlanes) { 1439 ALOGE("%s: Number of max planes : %d, nPlanes : %d", __func__, 1440 VIDEO_DECODER_INBUF_PLANES, nPlanes); 1441 ret = VIDEO_ERROR_BADPARAM; 1442 goto EXIT; 1443 } 1444 1445 memset(&buf, 0, sizeof(buf)); 1446 1447 buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 1448 buf.m.planes = planes; 1449 buf.length = VIDEO_DECODER_INBUF_PLANES; 1450 1451 pMutex = (pthread_mutex_t*)pCtx->pInMutex; 1452 pthread_mutex_lock(pMutex); 1453 index = MFC_Decoder_Find_Inbuf(pCtx, pBuffer[0]); 1454 if (index == -1) { 1455 pthread_mutex_unlock(pMutex); 1456 ALOGE("%s: Failed to get index", __func__); 1457 ret = VIDEO_ERROR_NOBUFFERS; 1458 goto EXIT; 1459 } 1460 1461 buf.index = index; 1462 pCtx->pInbuf[buf.index].bQueued = VIDEO_TRUE; 1463 1464 if (pCtx->bShareInbuf == VIDEO_TRUE) { 1465 buf.memory = pCtx->nMemoryType; 1466 for (i = 0; i < nPlanes; i++) { 1467 /* V4L2_MEMORY_USERPTR */ 1468 buf.m.planes[i].m.userptr = (unsigned long)pBuffer[i]; 1469 /* V4L2_MEMORY_DMABUF */ 1470 buf.m.planes[i].m.fd = pCtx->pInbuf[index].planes[i].fd; 1471 buf.m.planes[i].length = pCtx->pInbuf[index].planes[i].allocSize; 1472 buf.m.planes[i].bytesused = dataSize[i]; 1473 ALOGV("%s: shared inbuf(%d) plane(%d) addr=%p fd=%d len=%d used=%d\n", __func__, 1474 index, i, 1475 buf.m.planes[i].m.userptr, 1476 buf.m.planes[i].m.fd, 1477 buf.m.planes[i].length, 1478 buf.m.planes[i].bytesused); 1479 } 1480 } else { 1481 buf.memory = V4L2_MEMORY_MMAP; 1482 for (i = 0; i < nPlanes; i++) 1483 buf.m.planes[i].bytesused = dataSize[i]; 1484 } 1485 1486 // FIXME: figure out why |pPrivate| may be NULL. 1487 if (pPrivate && 1488 (((OMX_BUFFERHEADERTYPE *)pPrivate)->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) { 1489 buf.flags |= V4L2_BUF_FLAG_LAST_FRAME; 1490 ALOGV("%s: OMX_BUFFERFLAG_EOS => LAST_FRAME: 0x%x", __func__, 1491 !!(buf.flags & V4L2_BUF_FLAG_LAST_FRAME)); 1492 } 1493 1494 pCtx->pInbuf[buf.index].pPrivate = pPrivate; 1495 1496 pthread_mutex_unlock(pMutex); 1497 1498 if (exynos_v4l2_qbuf(pCtx->hDec, &buf) != 0) { 1499 ALOGE("%s: Failed to enqueue input buffer", __func__); 1500 pthread_mutex_lock(pMutex); 1501 pCtx->pInbuf[buf.index].pPrivate = NULL; 1502 pCtx->pInbuf[buf.index].bQueued = VIDEO_FALSE; 1503 pthread_mutex_unlock(pMutex); 1504 ret = VIDEO_ERROR_APIFAIL; 1505 goto EXIT; 1506 } 1507 1508EXIT: 1509 return ret; 1510} 1511 1512/* 1513 * [Decoder Buffer OPS] Enqueue (Output) 1514 */ 1515static ExynosVideoErrorType MFC_Decoder_Enqueue_Outbuf( 1516 void *pHandle, 1517 unsigned char *pBuffer[], 1518 unsigned int dataSize[], 1519 int nPlanes, 1520 void *pPrivate) 1521{ 1522 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle; 1523 ExynosVideoErrorType ret = VIDEO_ERROR_NONE; 1524 pthread_mutex_t *pMutex = NULL; 1525 1526 struct v4l2_plane planes[VIDEO_DECODER_OUTBUF_PLANES]; 1527 struct v4l2_buffer buf; 1528 int i, index; 1529 1530 if (pCtx == NULL) { 1531 ALOGE("%s: Video context info must be supplied", __func__); 1532 ret = VIDEO_ERROR_BADPARAM; 1533 goto EXIT; 1534 } 1535 1536 if (VIDEO_DECODER_OUTBUF_PLANES < nPlanes) { 1537 ALOGE("%s: Number of max planes : %d, nPlanes : %d", __func__, 1538 VIDEO_DECODER_OUTBUF_PLANES, nPlanes); 1539 ret = VIDEO_ERROR_BADPARAM; 1540 goto EXIT; 1541 } 1542 1543 memset(&buf, 0, sizeof(buf)); 1544 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 1545 buf.m.planes = planes; 1546 buf.length = VIDEO_DECODER_OUTBUF_PLANES; 1547 1548 pMutex = (pthread_mutex_t*)pCtx->pOutMutex; 1549 pthread_mutex_lock(pMutex); 1550 index = MFC_Decoder_Find_Outbuf(pCtx, pBuffer[0]); 1551 if (index == -1) { 1552 pthread_mutex_unlock(pMutex); 1553 ALOGE("%s: Failed to get index", __func__); 1554 ret = VIDEO_ERROR_NOBUFFERS; 1555 goto EXIT; 1556 } 1557 buf.index = index; 1558 pCtx->pOutbuf[buf.index].bQueued = VIDEO_TRUE; 1559 1560 if (pCtx->bShareOutbuf == VIDEO_TRUE) { 1561 buf.memory = pCtx->nMemoryType; 1562 for (i = 0; i < nPlanes; i++) { 1563 /* V4L2_MEMORY_USERPTR */ 1564 buf.m.planes[i].m.userptr = (unsigned long)pBuffer[i]; 1565 /* V4L2_MEMORY_DMABUF */ 1566 buf.m.planes[i].m.fd = pCtx->pOutbuf[index].planes[i].fd; 1567 buf.m.planes[i].length = pCtx->pOutbuf[index].planes[i].allocSize; 1568 buf.m.planes[i].bytesused = dataSize[i]; 1569 ALOGV("%s: shared outbuf(%d) plane=%d addr=%p fd=%d len=%d used=%d\n", __func__, 1570 index, i, 1571 buf.m.planes[i].m.userptr, 1572 buf.m.planes[i].m.fd, 1573 buf.m.planes[i].length, 1574 buf.m.planes[i].bytesused); 1575 } 1576 } else { 1577 ALOGV("%s: non-shared outbuf(%d)\n", __func__, index); 1578 buf.memory = V4L2_MEMORY_MMAP; 1579 } 1580 1581 pCtx->pOutbuf[buf.index].pPrivate = pPrivate; 1582 1583 pthread_mutex_unlock(pMutex); 1584 1585 if (exynos_v4l2_qbuf(pCtx->hDec, &buf) != 0) { 1586 ALOGE("%s: Failed to enqueue output buffer", __func__); 1587 pthread_mutex_lock(pMutex); 1588 pCtx->pOutbuf[buf.index].pPrivate = NULL; 1589 pCtx->pOutbuf[buf.index].bQueued = VIDEO_FALSE; 1590 pthread_mutex_unlock(pMutex); 1591 ret = VIDEO_ERROR_APIFAIL; 1592 goto EXIT; 1593 } 1594 1595EXIT: 1596 return ret; 1597} 1598 1599/* 1600 * [Decoder Buffer OPS] Dequeue (Input) 1601 */ 1602static ExynosVideoBuffer *MFC_Decoder_Dequeue_Inbuf(void *pHandle) 1603{ 1604 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle; 1605 ExynosVideoBuffer *pInbuf = NULL; 1606 pthread_mutex_t *pMutex = NULL; 1607 1608 struct v4l2_buffer buf; 1609 1610 if (pCtx == NULL) { 1611 ALOGE("%s: Video context info must be supplied", __func__); 1612 goto EXIT; 1613 } 1614 1615 if (pCtx->bStreamonInbuf == VIDEO_FALSE) { 1616 pInbuf = NULL; 1617 goto EXIT; 1618 } 1619 1620 memset(&buf, 0, sizeof(buf)); 1621 1622 buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 1623 1624 if (pCtx->bShareInbuf == VIDEO_TRUE) 1625 buf.memory = pCtx->nMemoryType; 1626 else 1627 buf.memory = V4L2_MEMORY_MMAP; 1628 1629 if (exynos_v4l2_dqbuf(pCtx->hDec, &buf) != 0) { 1630 pInbuf = NULL; 1631 goto EXIT; 1632 } 1633 1634 pMutex = (pthread_mutex_t*)pCtx->pInMutex; 1635 pthread_mutex_lock(pMutex); 1636 1637 pInbuf = &pCtx->pInbuf[buf.index]; 1638 pCtx->pInbuf[buf.index].bQueued = VIDEO_FALSE; 1639 1640 if (pCtx->bStreamonInbuf == VIDEO_FALSE) 1641 pInbuf = NULL; 1642 1643 pthread_mutex_unlock(pMutex); 1644 1645EXIT: 1646 return pInbuf; 1647} 1648 1649/* 1650 * [Decoder Buffer OPS] Dequeue (Output) 1651 */ 1652static ExynosVideoBuffer *MFC_Decoder_Dequeue_Outbuf(void *pHandle) 1653{ 1654 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle; 1655 ExynosVideoBuffer *pOutbuf = NULL; 1656 pthread_mutex_t *pMutex = NULL; 1657 1658 struct v4l2_buffer buf; 1659 int value, state; 1660 1661 if (pCtx == NULL) { 1662 ALOGE("%s: Video context info must be supplied", __func__); 1663 goto EXIT; 1664 } 1665 1666 if (pCtx->bStreamonOutbuf == VIDEO_FALSE) { 1667 pOutbuf = NULL; 1668 goto EXIT; 1669 } 1670 1671 memset(&buf, 0, sizeof(buf)); 1672 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 1673 1674 if (pCtx->bShareOutbuf == VIDEO_TRUE) 1675 buf.memory = pCtx->nMemoryType; 1676 else 1677 buf.memory = V4L2_MEMORY_MMAP; 1678 1679 /* HACK: pOutbuf return -1 means DECODING_ONLY for almost cases */ 1680 if (exynos_v4l2_dqbuf(pCtx->hDec, &buf) != 0) { 1681 pOutbuf = NULL; 1682 goto EXIT; 1683 } 1684 1685 if (pCtx->bStreamonOutbuf == VIDEO_FALSE) { 1686 pOutbuf = NULL; 1687 goto EXIT; 1688 } 1689 1690 pMutex = (pthread_mutex_t*)pCtx->pOutMutex; 1691 pthread_mutex_lock(pMutex); 1692 1693 pOutbuf = &pCtx->pOutbuf[buf.index]; 1694 1695 exynos_v4l2_g_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC51_VIDEO_DISPLAY_STATUS, &value); 1696 1697 switch (value) { 1698 case 0: 1699 pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DECODING_ONLY; 1700 break; 1701 case 1: 1702 pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DISPLAY_DECODING; 1703 break; 1704 case 2: 1705 pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DISPLAY_ONLY; 1706 break; 1707 case 3: 1708 exynos_v4l2_g_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC51_VIDEO_CHECK_STATE, &state); 1709 if (state == 1) /* Resolution is changed */ 1710 pOutbuf->displayStatus = VIDEO_FRAME_STATUS_CHANGE_RESOL; 1711 else /* Decoding is finished */ 1712 pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DECODING_FINISHED; 1713 break; 1714 default: 1715 pOutbuf->displayStatus = VIDEO_FRAME_STATUS_UNKNOWN; 1716 break; 1717 } 1718 1719 switch (buf.flags & (0x7 << 3)) { 1720 case V4L2_BUF_FLAG_KEYFRAME: 1721 pOutbuf->frameType = VIDEO_FRAME_I; 1722 break; 1723 case V4L2_BUF_FLAG_PFRAME: 1724 pOutbuf->frameType = VIDEO_FRAME_P; 1725 break; 1726 case V4L2_BUF_FLAG_BFRAME: 1727 pOutbuf->frameType = VIDEO_FRAME_B; 1728 break; 1729 default: 1730 pOutbuf->frameType = VIDEO_FRAME_OTHERS; 1731 break; 1732 }; 1733 1734 pOutbuf->bQueued = VIDEO_FALSE; 1735 1736 pthread_mutex_unlock(pMutex); 1737 1738EXIT: 1739 return pOutbuf; 1740} 1741 1742static ExynosVideoErrorType MFC_Decoder_Clear_Queued_Inbuf(void *pHandle) 1743{ 1744 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle; 1745 ExynosVideoErrorType ret = VIDEO_ERROR_NONE; 1746 int i; 1747 1748 if (pCtx == NULL) { 1749 ALOGE("%s: Video context info must be supplied", __func__); 1750 ret = VIDEO_ERROR_BADPARAM; 1751 goto EXIT; 1752 } 1753 1754 for (i = 0; i < pCtx->nInbufs; i++) { 1755 pCtx->pInbuf[i].bQueued = VIDEO_FALSE; 1756 } 1757 1758EXIT: 1759 return ret; 1760} 1761 1762static ExynosVideoErrorType MFC_Decoder_Clear_Queued_Outbuf(void *pHandle) 1763{ 1764 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle; 1765 ExynosVideoErrorType ret = VIDEO_ERROR_NONE; 1766 int i; 1767 1768 if (pCtx == NULL) { 1769 ALOGE("%s: Video context info must be supplied", __func__); 1770 ret = VIDEO_ERROR_BADPARAM; 1771 goto EXIT; 1772 } 1773 1774 for (i = 0; i < pCtx->nOutbufs; i++) { 1775 pCtx->pOutbuf[i].bQueued = VIDEO_FALSE; 1776 } 1777 1778EXIT: 1779 return ret; 1780} 1781 1782/* 1783 * [Decoder Buffer OPS] Cleanup Buffer (Input) 1784 */ 1785static ExynosVideoErrorType MFC_Decoder_Cleanup_Buffer_Inbuf(void *pHandle) 1786{ 1787 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle; 1788 ExynosVideoErrorType ret = VIDEO_ERROR_NONE; 1789 1790 struct v4l2_requestbuffers req; 1791 int nBufferCount = 0; 1792 1793 if (pCtx == NULL) { 1794 ALOGE("%s: Video context info must be supplied", __func__); 1795 ret = VIDEO_ERROR_BADPARAM; 1796 goto EXIT; 1797 } 1798 1799 nBufferCount = 0; /* for clean-up */ 1800 1801 memset(&req, 0, sizeof(req)); 1802 1803 req.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 1804 req.count = nBufferCount; 1805 1806 if (pCtx->bShareInbuf == VIDEO_TRUE) 1807 req.memory = pCtx->nMemoryType; 1808 else 1809 req.memory = V4L2_MEMORY_MMAP; 1810 1811 if (exynos_v4l2_reqbufs(pCtx->hDec, &req) != 0) { 1812 ret = VIDEO_ERROR_APIFAIL; 1813 goto EXIT; 1814 } 1815 1816 pCtx->nInbufs = (int)req.count; 1817 1818 if (pCtx->pInbuf != NULL) { 1819 free(pCtx->pInbuf); 1820 pCtx->pInbuf = NULL; 1821 } 1822 1823EXIT: 1824 return ret; 1825} 1826 1827/* 1828 * [Decoder Buffer OPS] Cleanup Buffer (Output) 1829 */ 1830static ExynosVideoErrorType MFC_Decoder_Cleanup_Buffer_Outbuf(void *pHandle) 1831{ 1832 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle; 1833 ExynosVideoErrorType ret = VIDEO_ERROR_NONE; 1834 1835 struct v4l2_requestbuffers req; 1836 int nBufferCount = 0; 1837 1838 if (pCtx == NULL) { 1839 ALOGE("%s: Video context info must be supplied", __func__); 1840 ret = VIDEO_ERROR_BADPARAM; 1841 goto EXIT; 1842 } 1843 1844 nBufferCount = 0; /* for clean-up */ 1845 1846 memset(&req, 0, sizeof(req)); 1847 1848 req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 1849 req.count = nBufferCount; 1850 1851 if (pCtx->bShareOutbuf == VIDEO_TRUE) 1852 req.memory = pCtx->nMemoryType; 1853 else 1854 req.memory = V4L2_MEMORY_MMAP; 1855 1856 if (exynos_v4l2_reqbufs(pCtx->hDec, &req) != 0) { 1857 ret = VIDEO_ERROR_APIFAIL; 1858 goto EXIT; 1859 } 1860 1861 pCtx->nOutbufs = (int)req.count; 1862 1863 if (pCtx->pOutbuf != NULL) { 1864 free(pCtx->pOutbuf); 1865 pCtx->pOutbuf = NULL; 1866 } 1867 1868EXIT: 1869 return ret; 1870} 1871 1872/* 1873 * [Decoder Buffer OPS] FindIndex (Output) 1874 */ 1875static int MFC_Decoder_FindEmpty_Outbuf(void *pHandle) 1876{ 1877 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle; 1878 int nIndex = -1; 1879 1880 if (pCtx == NULL) { 1881 ALOGE("%s: Video context info must be supplied", __func__); 1882 goto EXIT; 1883 } 1884 1885 for (nIndex = 0; nIndex < pCtx->nOutbufs; nIndex++) { 1886 if ((pCtx->pOutbuf[nIndex].bQueued == VIDEO_FALSE) && 1887 (pCtx->pOutbuf[nIndex].bSlotUsed == VIDEO_FALSE)) 1888 break; 1889 } 1890 1891 if (nIndex == pCtx->nOutbufs) 1892 nIndex = -1; 1893 1894EXIT: 1895 return nIndex; 1896} 1897 1898/* 1899 * [Decoder Buffer OPS] BufferIndexFree (Output) 1900 */ 1901void MFC_Decoder_BufferIndexFree_Outbuf(void *pHandle, PrivateDataShareBuffer *pPDSB, int index) 1902{ 1903 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle; 1904 int i, j; 1905 1906 ALOGV("De-queue buf.index:%d", index); 1907 ALOGV("pOutbuf fd:%d", pCtx->pOutbuf[index].planes[0].fd); 1908 1909 if (pCtx->pOutbuf[index].nIndexUseCnt == 0) { 1910 pCtx->pOutbuf[index].bSlotUsed = VIDEO_FALSE; 1911 } 1912 1913 for (i = 0; pPDSB->dpbFD[i].fd > -1; i++) { 1914 ALOGV("pPDSB->dpbFD[%d].fd:%d", i, pPDSB->dpbFD[i].fd); 1915 for (j = 0; pCtx->nOutbufs > j; j++) 1916 if (pPDSB->dpbFD[i].fd == pCtx->pOutbuf[j].planes[0].fd) { 1917 if (pCtx->pOutbuf[j].bQueued == VIDEO_FALSE) { 1918 if (pCtx->pOutbuf[j].nIndexUseCnt > 0) 1919 pCtx->pOutbuf[j].nIndexUseCnt--; 1920 } else if(pCtx->pOutbuf[j].bQueued == VIDEO_TRUE) { 1921 if (pCtx->pOutbuf[j].nIndexUseCnt > 1) { 1922 /* The buffer being used as the reference buffer came again. */ 1923 pCtx->pOutbuf[j].nIndexUseCnt--; 1924 } else { 1925 /* Reference DPB buffer is internally reused. */ 1926 } 1927 } 1928 ALOGV("dec FD:%d, pCtx->pOutbuf[%d].nIndexUseCnt:%d", pPDSB->dpbFD[i].fd, j, pCtx->pOutbuf[j].nIndexUseCnt); 1929 if ((pCtx->pOutbuf[j].nIndexUseCnt == 0) && 1930 (pCtx->pOutbuf[j].bQueued == VIDEO_FALSE)) { 1931 pCtx->pOutbuf[j].bSlotUsed = VIDEO_FALSE; 1932 } 1933 } 1934 } 1935 memset((char *)pPDSB, -1, sizeof(PrivateDataShareBuffer)); 1936 1937 return; 1938} 1939 1940/* 1941 * [Decoder Buffer OPS] ExtensionEnqueue (Output) 1942 */ 1943static ExynosVideoErrorType MFC_Decoder_ExtensionEnqueue_Outbuf( 1944 void *pHandle, 1945 unsigned char *pBuffer[], 1946 unsigned int *pFd[], 1947 unsigned int allocLen[], 1948 unsigned int dataSize[], 1949 int nPlanes, 1950 void *pPrivate) 1951{ 1952 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle; 1953 ExynosVideoErrorType ret = VIDEO_ERROR_NONE; 1954 pthread_mutex_t *pMutex = NULL; 1955 1956 struct v4l2_plane planes[VIDEO_DECODER_OUTBUF_PLANES]; 1957 struct v4l2_buffer buf; 1958 int state, index, i; 1959 1960 if (pCtx == NULL) { 1961 ALOGE("%s: Video context info must be supplied", __func__); 1962 ret = VIDEO_ERROR_BADPARAM; 1963 goto EXIT; 1964 } 1965 1966 if (VIDEO_DECODER_OUTBUF_PLANES < nPlanes) { 1967 ALOGE("%s: Number of max planes : %d, nPlanes : %d", __func__, 1968 VIDEO_DECODER_OUTBUF_PLANES, nPlanes); 1969 ret = VIDEO_ERROR_BADPARAM; 1970 goto EXIT; 1971 } 1972 1973 memset(&buf, 0, sizeof(buf)); 1974 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 1975 buf.m.planes = planes; 1976 buf.length = VIDEO_DECODER_OUTBUF_PLANES; 1977 1978 pMutex = (pthread_mutex_t*)pCtx->pOutMutex; 1979 pthread_mutex_lock(pMutex); 1980 1981 index = MFC_Decoder_Find_Outbuf(pCtx, pBuffer[0]); 1982 if (index == -1) { 1983 ALOGV("%s: Failed to find index", __func__); 1984 index = MFC_Decoder_FindEmpty_Outbuf(pCtx); 1985 if (index == -1) { 1986 pthread_mutex_unlock(pMutex); 1987 ALOGE("%s: Failed to get index", __func__); 1988 ret = VIDEO_ERROR_NOBUFFERS; 1989 goto EXIT; 1990 } 1991 } 1992 1993 buf.index = index; 1994 ALOGV("En-queue index:%d pCtx->pOutbuf[buf.index].bQueued:%d, pFd[0]:%d", 1995 index, pCtx->pOutbuf[buf.index].bQueued, pFd[0]); 1996 pCtx->pOutbuf[buf.index].bQueued = VIDEO_TRUE; 1997 pCtx->pOutbuf[buf.index].bSlotUsed = VIDEO_TRUE; 1998 1999 buf.memory = pCtx->nMemoryType; 2000 for (i = 0; i < nPlanes; i++) { 2001 /* V4L2_MEMORY_USERPTR */ 2002 buf.m.planes[i].m.userptr = (unsigned long)pBuffer[i]; 2003 /* V4L2_MEMORY_DMABUF */ 2004 buf.m.planes[i].m.fd = pFd[i]; 2005 buf.m.planes[i].length = allocLen[i]; 2006 buf.m.planes[i].bytesused = dataSize[i]; 2007 2008 /* Temporary storage for Dequeue */ 2009 pCtx->pOutbuf[buf.index].planes[i].addr = (unsigned long)pBuffer[i]; 2010 pCtx->pOutbuf[buf.index].planes[i].fd = (unsigned int)pFd[i]; 2011 pCtx->pOutbuf[buf.index].planes[i].allocSize = allocLen[i]; 2012 2013 ALOGV("%s: shared outbuf(%d) plane=%d addr=0x%x fd=%d len=%d used=%d\n", 2014 __func__, index, i, 2015 (void*)buf.m.planes[i].m.userptr, buf.m.planes[i].m.fd, 2016 buf.m.planes[i].length, buf.m.planes[i].bytesused); 2017 } 2018 2019 pCtx->pOutbuf[buf.index].pPrivate = pPrivate; 2020 pCtx->pOutbuf[buf.index].nIndexUseCnt++; 2021 2022 pthread_mutex_unlock(pMutex); 2023 2024 if (exynos_v4l2_qbuf(pCtx->hDec, &buf) != 0) { 2025 pthread_mutex_lock(pMutex); 2026 pCtx->pOutbuf[buf.index].nIndexUseCnt--; 2027 pCtx->pOutbuf[buf.index].pPrivate = NULL; 2028 pCtx->pOutbuf[buf.index].bQueued = VIDEO_FALSE; 2029 if (pCtx->pOutbuf[buf.index].nIndexUseCnt == 0) 2030 pCtx->pOutbuf[buf.index].bSlotUsed = VIDEO_FALSE; 2031 exynos_v4l2_g_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC51_VIDEO_CHECK_STATE, &state); 2032 pthread_mutex_unlock(pMutex); 2033 2034 if (state == 1) { 2035 /* The case of Resolution is changed */ 2036 ret = VIDEO_ERROR_WRONGBUFFERSIZE; 2037 } else { 2038 ALOGE("%s: Failed to enqueue output buffer", __func__); 2039 ret = VIDEO_ERROR_APIFAIL; 2040 } 2041 goto EXIT; 2042 } 2043 2044EXIT: 2045 return ret; 2046} 2047 2048/* 2049 * [Decoder Buffer OPS] ExtensionDequeue (Output) 2050 */ 2051static ExynosVideoErrorType MFC_Decoder_ExtensionDequeue_Outbuf( 2052 void *pHandle, 2053 ExynosVideoBuffer *pVideoBuffer) 2054{ 2055 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle; 2056 ExynosVideoErrorType ret = VIDEO_ERROR_NONE; 2057 pthread_mutex_t *pMutex = NULL; 2058 ExynosVideoBuffer *pOutbuf = NULL; 2059 PrivateDataShareBuffer *pPDSB = NULL; 2060 struct v4l2_buffer buf; 2061 int value, state, i, j; 2062 2063 if (pCtx == NULL) { 2064 ALOGE("%s: Video context info must be supplied", __func__); 2065 ret = VIDEO_ERROR_BADPARAM; 2066 goto EXIT; 2067 } 2068 2069 if (pCtx->bStreamonOutbuf == VIDEO_FALSE) { 2070 pOutbuf = NULL; 2071 ret = VIDEO_ERROR_APIFAIL; 2072 goto EXIT; 2073 } 2074 2075 memset(&buf, 0, sizeof(buf)); 2076 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 2077 2078 if (pCtx->bShareOutbuf == VIDEO_TRUE) 2079 buf.memory = pCtx->nMemoryType; 2080 else 2081 buf.memory = V4L2_MEMORY_MMAP; 2082 2083 /* HACK: pOutbuf return -1 means DECODING_ONLY for almost cases */ 2084 if (exynos_v4l2_dqbuf(pCtx->hDec, &buf) != 0) { 2085 pOutbuf = NULL; 2086 ret = VIDEO_ERROR_APIFAIL; 2087 goto EXIT; 2088 } 2089 2090 pMutex = (pthread_mutex_t*)pCtx->pOutMutex; 2091 pthread_mutex_lock(pMutex); 2092 2093 pOutbuf = &pCtx->pOutbuf[buf.index]; 2094 exynos_v4l2_g_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC51_VIDEO_DISPLAY_STATUS, &value); 2095 2096 switch (value) { 2097 case 0: 2098 pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DECODING_ONLY; 2099 break; 2100 case 1: 2101 pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DISPLAY_DECODING; 2102 break; 2103 case 2: 2104 pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DISPLAY_ONLY; 2105 break; 2106 case 3: 2107 exynos_v4l2_g_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC51_VIDEO_CHECK_STATE, &state); 2108 if (state == 1) /* Resolution is changed */ 2109 pOutbuf->displayStatus = VIDEO_FRAME_STATUS_CHANGE_RESOL; 2110 else /* Decoding is finished */ 2111 pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DECODING_FINISHED; 2112 break; 2113 default: 2114 pOutbuf->displayStatus = VIDEO_FRAME_STATUS_UNKNOWN; 2115 break; 2116 } 2117 2118 switch (buf.flags & (0x7 << 3)) { 2119 case V4L2_BUF_FLAG_KEYFRAME: 2120 pOutbuf->frameType = VIDEO_FRAME_I; 2121 break; 2122 case V4L2_BUF_FLAG_PFRAME: 2123 pOutbuf->frameType = VIDEO_FRAME_P; 2124 break; 2125 case V4L2_BUF_FLAG_BFRAME: 2126 pOutbuf->frameType = VIDEO_FRAME_B; 2127 break; 2128 default: 2129 pOutbuf->frameType = VIDEO_FRAME_OTHERS; 2130 break; 2131 }; 2132 2133 pPDSB = ((PrivateDataShareBuffer *)pCtx->nPrivateDataShareAddress) + buf.index; 2134 if (pCtx->pOutbuf[buf.index].bQueued == VIDEO_TRUE) { 2135 memcpy(pVideoBuffer, pOutbuf, sizeof(ExynosVideoBuffer)); 2136 memcpy((char *)(&(pVideoBuffer->PDSB)), (char *)pPDSB, sizeof(PrivateDataShareBuffer)); 2137 } else { 2138 ret = VIDEO_ERROR_NOBUFFERS; 2139 ALOGV("%s :: %d", __FUNCTION__, __LINE__); 2140 } 2141 2142 pCtx->pOutbuf[buf.index].bQueued = VIDEO_FALSE; 2143 MFC_Decoder_BufferIndexFree_Outbuf(pHandle, pPDSB, buf.index); 2144 2145 pthread_mutex_unlock(pMutex); 2146 2147EXIT: 2148 return ret; 2149} 2150 2151/* 2152 * [Decoder Buffer OPS] Enable Dynamic DPB 2153 */ 2154static ExynosVideoErrorType MFC_Decoder_Enable_DynamicDPB(void *pHandle) 2155{ 2156 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle; 2157 ExynosVideoErrorType ret = VIDEO_ERROR_NONE; 2158 2159 if (pCtx == NULL) { 2160 ALOGE("%s: Video context info must be supplied", __func__); 2161 ret = VIDEO_ERROR_BADPARAM; 2162 goto EXIT; 2163 } 2164 2165 if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC_SET_DYNAMIC_DPB_MODE, 1) != 0) { 2166 ret = VIDEO_ERROR_APIFAIL; 2167 goto EXIT; 2168 } 2169 2170 if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC_SET_USER_SHARED_HANDLE, pCtx->nPrivateDataShareFD) != 0) { 2171 ret = VIDEO_ERROR_APIFAIL; 2172 goto EXIT; 2173 } 2174 2175EXIT: 2176 return ret; 2177} 2178 2179/* 2180 * [Decoder OPS] Common 2181 */ 2182static ExynosVideoDecOps defDecOps = { 2183 .nSize = 0, 2184 .Init = MFC_Decoder_Init, 2185 .Finalize = MFC_Decoder_Finalize, 2186 .Set_DisplayDelay = MFC_Decoder_Set_DisplayDelay, 2187 .Set_IFrameDecoding = MFC_Decoder_Set_IFrameDecoding, 2188 .Enable_PackedPB = MFC_Decoder_Enable_PackedPB, 2189 .Enable_LoopFilter = MFC_Decoder_Enable_LoopFilter, 2190 .Enable_SliceMode = MFC_Decoder_Enable_SliceMode, 2191 .Get_ActualBufferCount = MFC_Decoder_Get_ActualBufferCount, 2192 .Set_FrameTag = MFC_Decoder_Set_FrameTag, 2193 .Get_FrameTag = MFC_Decoder_Get_FrameTag, 2194 .Enable_SEIParsing = MFC_Decoder_Enable_SEIParsing, 2195 .Get_FramePackingInfo = MFC_Decoder_Get_FramePackingInfo, 2196}; 2197 2198/* 2199 * [Decoder Buffer OPS] Input 2200 */ 2201static ExynosVideoDecBufferOps defInbufOps = { 2202 .nSize = 0, 2203 .Enable_Cacheable = MFC_Decoder_Enable_Cacheable_Inbuf, 2204 .Set_Shareable = MFC_Decoder_Set_Shareable_Inbuf, 2205 .Get_Buffer = NULL, 2206 .Set_Geometry = MFC_Decoder_Set_Geometry_Inbuf, 2207 .Get_Geometry = NULL, 2208 .Setup = MFC_Decoder_Setup_Inbuf, 2209 .Run = MFC_Decoder_Run_Inbuf, 2210 .Stop = MFC_Decoder_Stop_Inbuf, 2211 .Enqueue = MFC_Decoder_Enqueue_Inbuf, 2212 .Enqueue_All = NULL, 2213 .Dequeue = MFC_Decoder_Dequeue_Inbuf, 2214 .Register = MFC_Decoder_Register_Inbuf, 2215 .Clear_RegisteredBuffer = MFC_Decoder_Clear_RegisteredBuffer_Inbuf, 2216 .Clear_Queue = MFC_Decoder_Clear_Queued_Inbuf, 2217 .Cleanup_Buffer = MFC_Decoder_Cleanup_Buffer_Inbuf, 2218}; 2219 2220/* 2221 * [Decoder Buffer OPS] Output 2222 */ 2223static ExynosVideoDecBufferOps defOutbufOps = { 2224 .nSize = 0, 2225 .Enable_Cacheable = MFC_Decoder_Enable_Cacheable_Outbuf, 2226 .Set_Shareable = MFC_Decoder_Set_Shareable_Outbuf, 2227 .Get_Buffer = MFC_Decoder_Get_Buffer_Outbuf, 2228 .Set_Geometry = MFC_Decoder_Set_Geometry_Outbuf, 2229 .Get_Geometry = MFC_Decoder_Get_Geometry_Outbuf, 2230 .Setup = MFC_Decoder_Setup_Outbuf, 2231 .Run = MFC_Decoder_Run_Outbuf, 2232 .Stop = MFC_Decoder_Stop_Outbuf, 2233 .Enqueue = MFC_Decoder_Enqueue_Outbuf, 2234 .Enqueue_All = NULL, 2235 .Dequeue = MFC_Decoder_Dequeue_Outbuf, 2236 .Register = MFC_Decoder_Register_Outbuf, 2237 .Clear_RegisteredBuffer = MFC_Decoder_Clear_RegisteredBuffer_Outbuf, 2238 .Clear_Queue = MFC_Decoder_Clear_Queued_Outbuf, 2239 .Cleanup_Buffer = MFC_Decoder_Cleanup_Buffer_Outbuf, 2240 .ExtensionEnqueue = MFC_Decoder_ExtensionEnqueue_Outbuf, 2241 .ExtensionDequeue = MFC_Decoder_ExtensionDequeue_Outbuf, 2242 .Enable_DynamicDPB = MFC_Decoder_Enable_DynamicDPB, 2243}; 2244 2245int Exynos_Video_Register_Decoder( 2246 ExynosVideoDecOps *pDecOps, 2247 ExynosVideoDecBufferOps *pInbufOps, 2248 ExynosVideoDecBufferOps *pOutbufOps) 2249{ 2250 ExynosVideoErrorType ret = VIDEO_ERROR_NONE; 2251 2252 if ((pDecOps == NULL) || (pInbufOps == NULL) || (pOutbufOps == NULL)) { 2253 ret = VIDEO_ERROR_BADPARAM; 2254 goto EXIT; 2255 } 2256 2257 defDecOps.nSize = sizeof(defDecOps); 2258 defInbufOps.nSize = sizeof(defInbufOps); 2259 defOutbufOps.nSize = sizeof(defOutbufOps); 2260 2261 memcpy((char *)pDecOps + sizeof(pDecOps->nSize), (char *)&defDecOps + sizeof(defDecOps.nSize), 2262 pDecOps->nSize - sizeof(pDecOps->nSize)); 2263 2264 memcpy((char *)pInbufOps + sizeof(pInbufOps->nSize), (char *)&defInbufOps + sizeof(defInbufOps.nSize), 2265 pInbufOps->nSize - sizeof(pInbufOps->nSize)); 2266 2267 memcpy((char *)pOutbufOps + sizeof(pOutbufOps->nSize), (char *)&defOutbufOps + sizeof(defOutbufOps.nSize), 2268 pOutbufOps->nSize - sizeof(pOutbufOps->nSize)); 2269 2270EXIT: 2271 return ret; 2272} 2273