1 /* ------------------------------------------------------------------ 2 * Copyright (C) 1998-2009 PacketVideo 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 * express or implied. 14 * See the License for the specific language governing permissions 15 * and limitations under the License. 16 * ------------------------------------------------------------------- 17 */ 18 19 #include "avc_enc.h" 20 21 22 #define MAX_SUPPORTED_LAYER 1 23 24 /* global static functions */ 25 26 void CbAvcEncDebugLog_OMX(uint32 *userData, AVCLogType type, char *string1, int val1, int val2) 27 { 28 OSCL_UNUSED_ARG(userData); 29 OSCL_UNUSED_ARG(type); 30 OSCL_UNUSED_ARG(string1); 31 OSCL_UNUSED_ARG(val1); 32 OSCL_UNUSED_ARG(val2); 33 34 return; 35 } 36 37 int CbAvcEncMalloc_OMX(void *userData, int32 size, int attribute) 38 { 39 OSCL_UNUSED_ARG(userData); 40 OSCL_UNUSED_ARG(attribute); 41 42 uint8 *mem; 43 44 mem = (uint8*) oscl_malloc(size); 45 46 return (int)mem; 47 } 48 49 void CbAvcEncFree_OMX(void *userData, int mem) 50 { 51 OSCL_UNUSED_ARG(userData); 52 53 oscl_free((void*)mem); 54 55 return; 56 } 57 58 59 int CbAvcEncDPBAlloc_OMX(void *userData, uint frame_size_in_mbs, uint num_buffers) 60 { 61 AvcEncoder_OMX* pAvcEnc = (AvcEncoder_OMX*) userData; 62 63 return pAvcEnc->AVC_DPBAlloc(frame_size_in_mbs, num_buffers); 64 } 65 66 67 void CbAvcEncFrameUnbind_OMX(void *userData, int indx) 68 { 69 AvcEncoder_OMX* pAvcEnc = (AvcEncoder_OMX*) userData; 70 71 pAvcEnc->AVC_FrameUnbind(indx); 72 73 return; 74 } 75 76 int CbAvcEncFrameBind_OMX(void *userData, int indx, uint8 **yuv) 77 { 78 AvcEncoder_OMX* pAvcEnc = (AvcEncoder_OMX*) userData; 79 80 return pAvcEnc->AVC_FrameBind(indx, yuv); 81 } 82 83 84 85 //Class constructor function 86 AvcEncoder_OMX::AvcEncoder_OMX() 87 { 88 iInitialized = OMX_FALSE; 89 iSpsPpsHeaderFlag = OMX_FALSE; 90 iReadyForNextFrame = OMX_TRUE; 91 92 oscl_memset((void *)&iAvcHandle, 0, sizeof(AVCHandle)); 93 94 iAvcHandle.CBAVC_DPBAlloc = &CbAvcEncDPBAlloc_OMX; 95 iAvcHandle.CBAVC_FrameBind = &CbAvcEncFrameBind_OMX; 96 iAvcHandle.CBAVC_FrameUnbind = &CbAvcEncFrameUnbind_OMX; 97 iAvcHandle.CBAVC_Free = &CbAvcEncFree_OMX; 98 iAvcHandle.CBAVC_Malloc = &CbAvcEncMalloc_OMX; 99 iAvcHandle.CBAVC_DebugLog = &CbAvcEncDebugLog_OMX; 100 iAvcHandle.userData = this; 101 102 ccRGBtoYUV = NULL; 103 iYUVIn = NULL; 104 iFramePtr = NULL; 105 iDPB = NULL; 106 iFrameUsed = NULL; 107 } 108 109 110 //Class destructor function 111 AvcEncoder_OMX::~AvcEncoder_OMX() 112 { 113 //In case encoder cleanup has not been done yet, do it here 114 AvcEncDeinit(); 115 } 116 117 118 /* Encoder Initialization routine */ 119 OMX_ERRORTYPE AvcEncoder_OMX::AvcEncInit(OMX_VIDEO_PORTDEFINITIONTYPE aInputParam, 120 OMX_CONFIG_ROTATIONTYPE aInputOrientationType, 121 OMX_VIDEO_PORTDEFINITIONTYPE aEncodeParam, 122 OMX_VIDEO_PARAM_AVCTYPE aEncodeAvcParam, 123 OMX_VIDEO_PARAM_BITRATETYPE aRateControlType, 124 OMX_VIDEO_PARAM_QUANTIZATIONTYPE aQuantType, 125 OMX_VIDEO_PARAM_MOTIONVECTORTYPE aSearchRange, 126 OMX_VIDEO_PARAM_INTRAREFRESHTYPE aIntraRefresh, 127 OMX_VIDEO_PARAM_VBSMCTYPE aVbsmcType) 128 { 129 130 AVCEncParams aEncOption; /* encoding options */ 131 132 uint32* slice_group = NULL; 133 int32 numTotalMBs; 134 int32 Ysize16; 135 int32 total_mb; 136 int32 run_length; 137 138 iSrcWidth = aInputParam.nFrameWidth; 139 iSrcHeight = aInputParam.nFrameHeight; 140 iFrameOrientation = aInputOrientationType.nRotation; 141 142 143 if ((OMX_COLOR_FormatYUV420Planar == aInputParam.eColorFormat) || 144 (OMX_COLOR_Format24bitRGB888 == aInputParam.eColorFormat) || 145 (OMX_COLOR_Format12bitRGB444 == aInputParam.eColorFormat) || 146 (OMX_COLOR_FormatYUV420SemiPlanar == aInputParam.eColorFormat)) 147 { 148 iVideoFormat = aInputParam.eColorFormat; 149 } 150 else 151 { 152 return OMX_ErrorUnsupportedSetting; 153 } 154 155 156 if (OMX_TRUE == iInitialized) 157 { 158 /* clean up before re-initialized */ 159 PVAVCCleanUpEncoder(&iAvcHandle); 160 iAvcHandle.AVCObject = NULL; 161 162 if (iYUVIn) 163 { 164 oscl_free(iYUVIn); 165 iYUVIn = NULL; 166 } 167 168 } 169 170 //Verify the input compression format 171 if (OMX_VIDEO_CodingUnused != aInputParam.eCompressionFormat) 172 { 173 //Input port must have no compression supported 174 return OMX_ErrorUnsupportedSetting; 175 } 176 177 // allocate iYUVIn 178 if ((iSrcWidth & 0xF) || (iSrcHeight & 0xF) || (OMX_COLOR_FormatYUV420Planar != iVideoFormat)) /* Not multiple of 16 */ 179 { 180 iYUVIn = (uint8*) oscl_malloc(((((iSrcWidth + 15) >> 4) * ((iSrcHeight + 15) >> 4)) * 3) << 7); 181 if (NULL == iYUVIn) 182 { 183 return OMX_ErrorInsufficientResources; 184 } 185 } 186 187 /* Initialize the color conversion */ 188 if (OMX_COLOR_Format24bitRGB888 == iVideoFormat) 189 { 190 ccRGBtoYUV = CCRGB24toYUV420::New(); 191 ccRGBtoYUV->Init(iSrcWidth, iSrcHeight, iSrcWidth, iSrcWidth, iSrcHeight, ((iSrcWidth + 15) >> 4) << 4, (iFrameOrientation == 180 ? CCBOTTOM_UP : 0)); 192 } 193 if (OMX_COLOR_Format12bitRGB444 == iVideoFormat) 194 { 195 ccRGBtoYUV = CCRGB12toYUV420::New(); 196 ccRGBtoYUV->Init(iSrcWidth, iSrcHeight, iSrcWidth, iSrcWidth, iSrcHeight, ((iSrcWidth + 15) >> 4) << 4, (iFrameOrientation == 180 ? CCBOTTOM_UP : 0)); 197 } 198 if (OMX_COLOR_FormatYUV420SemiPlanar == iVideoFormat) 199 { 200 ccRGBtoYUV = CCYUV420SEMItoYUV420::New(); 201 ccRGBtoYUV->Init(iSrcWidth, iSrcHeight, iSrcWidth, iSrcWidth , iSrcHeight, ((iSrcWidth + 15) >> 4) << 4, (iFrameOrientation == 180 ? CCBOTTOM_UP : 0)); 202 } 203 204 aEncOption.width = aEncodeParam.nFrameWidth; 205 aEncOption.height = aEncodeParam.nFrameHeight; 206 aEncOption.frame_rate = (uint32)(1000 * ((aEncodeParam.xFramerate >> 16) + (OsclFloat)(aEncodeParam.xFramerate & 0xFFFF) / (1 << 16))); 207 208 switch (aRateControlType.eControlRate) 209 { 210 case OMX_Video_ControlRateDisable: 211 { 212 aEncOption.rate_control = AVC_OFF; 213 aEncOption.bitrate = 48000; // default 214 } 215 break; 216 217 //Both the below cases have same body 218 case OMX_Video_ControlRateConstant: 219 case OMX_Video_ControlRateVariable: 220 { 221 aEncOption.rate_control = AVC_ON; 222 aEncOption.bitrate = aEncodeParam.nBitrate; 223 } 224 break; 225 226 default: 227 return OMX_ErrorUnsupportedSetting; 228 } 229 230 //Set the profile of encoder 231 switch (aEncodeAvcParam.eProfile) 232 { 233 case OMX_VIDEO_AVCProfileBaseline: 234 { 235 aEncOption.profile = AVC_BASELINE; 236 } 237 break; 238 239 case OMX_VIDEO_AVCProfileMain: 240 { 241 aEncOption.profile = AVC_MAIN; 242 } 243 break; 244 245 case OMX_VIDEO_AVCProfileExtended: 246 { 247 aEncOption.profile = AVC_EXTENDED; 248 } 249 break; 250 251 case OMX_VIDEO_AVCProfileHigh: 252 { 253 aEncOption.profile = AVC_HIGH; 254 } 255 break; 256 257 case OMX_VIDEO_AVCProfileHigh10: 258 { 259 aEncOption.profile = AVC_HIGH10; 260 } 261 break; 262 263 case OMX_VIDEO_AVCProfileHigh422: 264 { 265 aEncOption.profile = AVC_HIGH422; 266 } 267 break; 268 269 case OMX_VIDEO_AVCProfileHigh444: 270 { 271 aEncOption.profile = AVC_HIGH444; 272 } 273 break; 274 275 default: 276 { 277 aEncOption.profile = AVC_BASELINE; 278 } 279 break; 280 } 281 282 283 //Set the level of avc encoder 284 switch (aEncodeAvcParam.eLevel) 285 { 286 case OMX_VIDEO_AVCLevel1: 287 { 288 aEncOption.level = AVC_LEVEL1; 289 } 290 break; 291 case OMX_VIDEO_AVCLevel1b: 292 { 293 aEncOption.level = AVC_LEVEL1_B; 294 } 295 break; 296 case OMX_VIDEO_AVCLevel11: 297 { 298 aEncOption.level = AVC_LEVEL1_1; 299 } 300 break; 301 case OMX_VIDEO_AVCLevel12: 302 { 303 aEncOption.level = AVC_LEVEL1_2; 304 } 305 break; 306 case OMX_VIDEO_AVCLevel13: 307 { 308 aEncOption.level = AVC_LEVEL1_3; 309 } 310 break; 311 312 313 case OMX_VIDEO_AVCLevel2: 314 { 315 aEncOption.level = AVC_LEVEL2; 316 } 317 break; 318 case OMX_VIDEO_AVCLevel21: 319 { 320 aEncOption.level = AVC_LEVEL2_1; 321 } 322 break; 323 case OMX_VIDEO_AVCLevel22: 324 { 325 aEncOption.level = AVC_LEVEL2_2; 326 } 327 break; 328 329 330 case OMX_VIDEO_AVCLevel3: 331 { 332 aEncOption.level = AVC_LEVEL3; 333 } 334 break; 335 case OMX_VIDEO_AVCLevel31: 336 { 337 aEncOption.level = AVC_LEVEL3_1; 338 } 339 break; 340 case OMX_VIDEO_AVCLevel32: 341 { 342 aEncOption.level = AVC_LEVEL3_2; 343 } 344 break; 345 346 347 case OMX_VIDEO_AVCLevel4: 348 { 349 aEncOption.level = AVC_LEVEL4; 350 } 351 break; 352 case OMX_VIDEO_AVCLevel41: 353 { 354 aEncOption.level = AVC_LEVEL4_1; 355 } 356 break; 357 case OMX_VIDEO_AVCLevel42: 358 { 359 aEncOption.level = AVC_LEVEL4_2; 360 } 361 break; 362 363 364 case OMX_VIDEO_AVCLevel5: 365 { 366 aEncOption.level = AVC_LEVEL5; 367 } 368 break; 369 case OMX_VIDEO_AVCLevel51: 370 { 371 aEncOption.level = AVC_LEVEL5_1; 372 } 373 break; 374 375 default: 376 { 377 aEncOption.level = AVC_LEVEL5_1; 378 } 379 break; 380 } 381 382 aEncOption.initQP = aQuantType.nQpP; 383 384 aEncOption.init_CBP_removal_delay = 1600; //Default value 385 aEncOption.CPB_size = ((uint32)(2 * aEncOption.bitrate)); 386 if (OMX_VIDEO_PictureTypeI == aEncodeAvcParam.nAllowedPictureTypes) // I-only 387 { 388 aEncOption.idr_period = 1; 389 } 390 else 391 { 392 //IPPPPPPPPPP, no I frame for a long period of time 393 if (0xFFFFFFFF == aEncodeAvcParam.nPFrames) 394 { 395 aEncOption.idr_period = -1; 396 } 397 else 398 { 399 aEncOption.idr_period = aEncodeAvcParam.nPFrames + 1; 400 } 401 } 402 403 if ((OMX_VIDEO_IntraRefreshCyclic == aIntraRefresh.eRefreshMode) || 404 (OMX_VIDEO_IntraRefreshBoth == aIntraRefresh.eRefreshMode)) 405 { 406 aEncOption.intramb_refresh = aIntraRefresh.nCirMBs; 407 } 408 409 410 if ((OMX_VIDEO_IntraRefreshAdaptive == aIntraRefresh.eRefreshMode) || 411 (OMX_VIDEO_IntraRefreshBoth == aIntraRefresh.eRefreshMode)) 412 { 413 aEncOption.auto_scd = AVC_ON; 414 } 415 else 416 { 417 aEncOption.auto_scd = AVC_OFF; 418 } 419 420 aEncOption.out_of_band_param_set = AVC_ON; //Default value 421 422 /* default values */ 423 aEncOption.poc_type = 2; 424 aEncOption.log2_max_poc_lsb_minus_4 = 12; 425 aEncOption.delta_poc_zero_flag = 0; 426 aEncOption.offset_poc_non_ref = 0; 427 aEncOption.offset_top_bottom = 0; 428 aEncOption.num_ref_in_cycle = 0; 429 aEncOption.offset_poc_ref = NULL; 430 431 aEncOption.num_ref_frame = 1; //We only support this value 432 433 //Since FMO is disabled in our case, num of slice group is always 1 434 #if (defined(TEST_FULL_AVC_FRAME_MODE) || defined(TEST_FULL_AVC_FRAME_MODE_SC)) 435 aEncOption.num_slice_group = 4; 436 aEncOption.fmo_type = 6; 437 aEncOption.use_overrun_buffer = AVC_OFF; // since we are to be outputing full frame buffers 438 #else 439 aEncOption.num_slice_group = 1; 440 aEncOption.fmo_type = 0; //Disabled in this case 441 aEncOption.use_overrun_buffer = AVC_ON; 442 #endif 443 444 aEncOption.db_filter = AVC_ON; 445 446 if (OMX_VIDEO_AVCLoopFilterEnable == aEncodeAvcParam.eLoopFilterMode) 447 { 448 aEncOption.disable_db_idc = 0; 449 } 450 else if (OMX_VIDEO_AVCLoopFilterDisable == aEncodeAvcParam.eLoopFilterMode) 451 { 452 aEncOption.disable_db_idc = 1; 453 } 454 else if (OMX_VIDEO_AVCLoopFilterDisableSliceBoundary == aEncodeAvcParam.eLoopFilterMode) 455 { 456 aEncOption.disable_db_idc = 2; 457 } 458 else 459 { 460 return OMX_ErrorUnsupportedSetting; 461 } 462 463 aEncOption.alpha_offset = 0; 464 aEncOption.beta_offset = 0; 465 aEncOption.constrained_intra_pred = (OMX_TRUE == aEncodeAvcParam.bconstIpred) ? AVC_ON : AVC_OFF; 466 467 aEncOption.data_par = AVC_OFF; 468 aEncOption.fullsearch = AVC_OFF; 469 aEncOption.search_range = (aSearchRange.sXSearchRange <= aSearchRange.sYSearchRange ? aSearchRange.sXSearchRange : aSearchRange.sYSearchRange); 470 471 if (OMX_Video_MotionVectorPixel == aSearchRange.eAccuracy) 472 { 473 aEncOption.sub_pel = AVC_OFF; 474 } 475 else 476 { 477 aEncOption.sub_pel = AVC_ON; 478 } 479 480 if (aVbsmcType.b16x16 != OMX_TRUE) 481 { 482 return OMX_ErrorBadParameter; 483 } 484 485 aEncOption.submb_pred = AVC_OFF; // default for now, ignore aVbsmcType.8x16, 16x8, 8x8, etc. 486 aEncOption.rdopt_mode = AVC_OFF; 487 aEncOption.bidir_pred = AVC_OFF; 488 489 Ysize16 = (((aEncOption.width + 15) >> 4) << 4) * (((aEncOption.height + 15) >> 4) << 4); 490 numTotalMBs = Ysize16 >> 8; 491 slice_group = (uint*) oscl_malloc(sizeof(uint) * numTotalMBs); 492 493 int32 idx = 0; 494 int32 ii; 495 for (ii = 0; ii < numTotalMBs; ii++) 496 { 497 slice_group[ii] = idx++; 498 if (idx >= aEncOption.num_slice_group) 499 { 500 idx = 0; 501 } 502 } 503 aEncOption.slice_group = slice_group; 504 505 if (aEncOption.num_slice_group > 1) /* divide slice group equally */ 506 { 507 run_length = numTotalMBs / aEncOption.num_slice_group; 508 total_mb = 0; 509 for (idx = 0; idx < aEncOption.num_slice_group; idx++) 510 { 511 aEncOption.run_length_minus1[idx] = run_length - 1; 512 total_mb += run_length; 513 } 514 if (total_mb < numTotalMBs) 515 { 516 aEncOption.run_length_minus1[aEncOption.num_slice_group-1] += (numTotalMBs - total_mb); 517 } 518 } 519 520 /***** Initialize the encoder *****/ 521 if (AVCENC_SUCCESS != PVAVCEncInitialize(&iAvcHandle, &aEncOption, NULL, NULL)) 522 { 523 iInitialized = OMX_FALSE; 524 return OMX_ErrorBadParameter; 525 } 526 527 iIDR = OMX_TRUE; 528 iDispOrd = 0; 529 iInitialized = OMX_TRUE; 530 iReadyForNextFrame = OMX_TRUE; 531 532 oscl_free(slice_group); 533 534 return OMX_ErrorNone; 535 536 } 537 538 539 AVCEnc_Status AvcEncoder_OMX::AvcEncodeSendInput(OMX_U8* aInBuffer, 540 OMX_U32* aInBufSize, 541 OMX_TICKS aInTimeStamp) 542 { 543 AVCEnc_Status AvcStatus; 544 545 if (OMX_COLOR_FormatYUV420Planar == iVideoFormat) 546 { 547 /* Input Buffer Size Check 548 * Input buffer size should be equal to one frame, otherwise drop the frame 549 * as it is a corrupt data and don't encode it */ 550 if (*aInBufSize < (OMX_U32)((iSrcWidth * iSrcHeight * 3) >> 1)) 551 { 552 //Mark the inpur buffer consumed to indicate corrupt frame 553 *aInBufSize = 0; 554 return AVCENC_FAIL; 555 } 556 557 if (iYUVIn) /* iSrcWidth is not multiple of 4 or iSrcHeight is odd number */ 558 { 559 CopyToYUVIn(aInBuffer, iSrcWidth, iSrcHeight, 560 ((iSrcWidth + 15) >> 4) << 4, ((iSrcHeight + 15) >> 4) << 4); 561 iVideoIn = iYUVIn; 562 } 563 else /* otherwise, we can just use aVidIn->iSource */ 564 { 565 iVideoIn = aInBuffer; 566 } 567 } 568 else if (OMX_COLOR_Format12bitRGB444 == iVideoFormat) 569 { 570 if (*aInBufSize < (OMX_U32)(iSrcWidth * iSrcHeight * 2)) 571 { 572 //Mark the inpur buffer consumed to indicate corrupt frame 573 *aInBufSize = 0; 574 return AVCENC_FAIL; 575 } 576 ccRGBtoYUV->Convert((uint8*)aInBuffer, iYUVIn); 577 iVideoIn = iYUVIn; 578 } 579 else if (OMX_COLOR_Format24bitRGB888 == iVideoFormat) 580 { 581 if (*aInBufSize < (OMX_U32)(iSrcWidth * iSrcHeight * 3)) 582 { 583 //Mark the inpur buffer consumed to indicate corrupt frame 584 *aInBufSize = 0; 585 return AVCENC_FAIL; 586 } 587 ccRGBtoYUV->Convert((uint8*)aInBuffer, iYUVIn); 588 iVideoIn = iYUVIn; 589 } 590 else if (OMX_COLOR_FormatYUV420SemiPlanar == iVideoFormat) 591 { 592 if (*aInBufSize < (OMX_U32)(iSrcWidth * iSrcHeight * 3) >> 1) 593 { 594 //Mark the inpur buffer consumed to indicate corrupt frame 595 *aInBufSize = 0; 596 return AVCENC_FAIL; 597 } 598 ccRGBtoYUV->Convert((uint8*)aInBuffer, iYUVIn); 599 iVideoIn = iYUVIn; 600 } 601 602 /* assign with backward-P or B-Vop this timestamp must be re-ordered */ 603 // Encoder uses 32 bit timestamps internally - keep track of 64 bit value as well 604 iTimeStamp = Oscl_Int64_Utils::get_uint64_lower32(aInTimeStamp / 1000); //timestamp in millisec 605 iTimeStamp64 = aInTimeStamp; 606 607 iVidIn.height = ((iSrcHeight + 15) >> 4) << 4; 608 iVidIn.pitch = ((iSrcWidth + 15) >> 4) << 4; 609 iVidIn.coding_timestamp = iTimeStamp; 610 iVidIn.YCbCr[0] = (uint8*)iVideoIn; 611 iVidIn.YCbCr[1] = (uint8*)(iVideoIn + iVidIn.height * iVidIn.pitch); 612 iVidIn.YCbCr[2] = iVidIn.YCbCr[1] + ((iVidIn.height * iVidIn.pitch) >> 2); 613 iVidIn.disp_order = iDispOrd; 614 615 AvcStatus = PVAVCEncSetInput(&iAvcHandle, &iVidIn); 616 617 if (AVCENC_SUCCESS == AvcStatus) 618 { 619 iDispOrd++; 620 iReadyForNextFrame = OMX_FALSE; 621 return AvcStatus; 622 } 623 else if (AVCENC_NEW_IDR == AvcStatus) 624 { 625 iDispOrd++; 626 iIDR = OMX_TRUE; 627 iReadyForNextFrame = OMX_FALSE; 628 return AvcStatus; 629 } 630 else 631 { 632 return AvcStatus; 633 } 634 635 } 636 637 638 /*Encode routine */ 639 AVCEnc_Status AvcEncoder_OMX::AvcEncodeVideo(OMX_U8* aOutBuffer, 640 OMX_U32* aOutputLength, 641 OMX_BOOL* aBufferOverRun, 642 OMX_U8** aOverBufferPointer, 643 OMX_U8* aInBuffer, 644 OMX_U32* aInBufSize, 645 OMX_TICKS aInTimeStamp, 646 OMX_TICKS* aOutTimeStamp, 647 OMX_BOOL* aSyncFlag) 648 { 649 AVCEnc_Status AvcStatus; 650 AVCEnc_Status ReturnValue; 651 AVCEnc_Status SetInputStatus = AVCENC_SUCCESS; 652 AVCFrameIO recon; 653 uint Size; 654 int NALType = 0; 655 656 if (OMX_FALSE == iSpsPpsHeaderFlag) 657 { 658 Size = *aOutputLength; 659 AvcStatus = PVAVCEncodeNAL(&iAvcHandle, aOutBuffer, &Size, &NALType); 660 661 //No more SPS and PPS NAL's to come, mark the header flag as true 662 if (AVCENC_WRONG_STATE == AvcStatus) 663 { 664 *aOutputLength = 0; 665 iSpsPpsHeaderFlag = OMX_TRUE; 666 return AVCENC_WRONG_STATE; 667 } 668 669 switch (NALType) 670 { 671 case AVC_NALTYPE_SPS: 672 case AVC_NALTYPE_PPS: 673 { 674 *aOutputLength = Size; 675 //Mark the SPS and PPS buffers with the first input bufer timestamp 676 *aOutTimeStamp = aInTimeStamp; 677 return AVCENC_SUCCESS; 678 } 679 680 default: 681 { 682 //No more SPS and PPS NAL's to come, mark the header flag as true 683 *aOutputLength = 0; 684 iSpsPpsHeaderFlag = OMX_TRUE; 685 return AVCENC_FAIL; 686 } 687 } 688 } 689 690 691 if (OMX_TRUE == iReadyForNextFrame) 692 { 693 SetInputStatus = AvcEncodeSendInput(aInBuffer, aInBufSize, aInTimeStamp); 694 } 695 696 if ((AVCENC_SUCCESS == SetInputStatus) || (AVCENC_NEW_IDR == SetInputStatus)) //success 697 { 698 Size = *aOutputLength; 699 700 AvcStatus = PVAVCEncodeNAL(&iAvcHandle, (uint8*)aOutBuffer, &Size, &NALType); 701 702 if (AVCENC_SUCCESS == AvcStatus) 703 { 704 *aSyncFlag = iIDR; 705 //Calling the overrun buffer api to see whether overrun buffer has been used or not 706 *aOverBufferPointer = PVAVCEncGetOverrunBuffer(&iAvcHandle); 707 708 if (NULL != *aOverBufferPointer) 709 { 710 //Output data has been filled in the over run buffer, mark the flag as true 711 *aBufferOverRun = OMX_TRUE; 712 } 713 714 ReturnValue = AVCENC_SUCCESS; 715 } 716 else if (AVCENC_PICTURE_READY == AvcStatus) 717 { 718 //Calling the overrun buffer api to see whether overrun buffer has been used or not 719 *aOverBufferPointer = PVAVCEncGetOverrunBuffer(&iAvcHandle); 720 721 if (NULL != *aOverBufferPointer) 722 { 723 //Output data has been filled in the over run buffer, mark the flag as true 724 *aBufferOverRun = OMX_TRUE; 725 } 726 727 *aSyncFlag = iIDR; 728 if (iIDR == OMX_TRUE) 729 { 730 iIDR = OMX_FALSE; 731 } 732 733 ReturnValue = AVCENC_PICTURE_READY; 734 735 iReadyForNextFrame = OMX_TRUE; //ready to receive another set of input frame 736 737 AvcStatus = PVAVCEncGetRecon(&iAvcHandle, &recon); 738 if (AVCENC_SUCCESS == AvcStatus) 739 { 740 PVAVCEncReleaseRecon(&iAvcHandle, &recon); 741 } 742 } 743 else if (AVCENC_SKIPPED_PICTURE == AvcStatus) 744 { 745 *aOutputLength = 0; 746 iReadyForNextFrame = OMX_TRUE; //ready to receive another set of input frame 747 return AVCENC_SKIPPED_PICTURE; 748 } 749 else 750 { 751 *aOutputLength = 0; 752 iReadyForNextFrame = OMX_TRUE; //ready to receive another set of input frame 753 return AVCENC_FAIL; 754 } 755 756 *aOutputLength = Size; 757 *aOutTimeStamp = iTimeStamp64;//timestamp in microsec 758 759 return ReturnValue; 760 761 } 762 else if (AVCENC_SKIPPED_PICTURE == SetInputStatus) 763 { 764 *aOutputLength = 0; 765 return AVCENC_SKIPPED_PICTURE; 766 } 767 else 768 { 769 *aOutputLength = 0; 770 return AVCENC_FAIL; 771 } 772 } 773 774 775 //Deinitialize the avc encoder here and perform the cleanup and free operations 776 OMX_ERRORTYPE AvcEncoder_OMX::AvcEncDeinit() 777 { 778 if (OMX_TRUE == iInitialized) 779 { 780 PVAVCCleanUpEncoder(&iAvcHandle); 781 iAvcHandle.AVCObject = NULL; 782 783 iInitialized = OMX_FALSE; 784 iReadyForNextFrame = OMX_TRUE; 785 786 if (iYUVIn) 787 { 788 oscl_free(iYUVIn); 789 iYUVIn = NULL; 790 } 791 } 792 793 if (iFrameUsed) 794 { 795 oscl_free(iFrameUsed); 796 iFrameUsed = NULL; 797 } 798 799 if (ccRGBtoYUV) 800 { 801 OSCL_DELETE(ccRGBtoYUV); 802 ccRGBtoYUV = NULL; 803 } 804 805 if (iDPB) 806 { 807 oscl_free(iDPB); 808 iDPB = NULL; 809 } 810 811 if (iFramePtr) 812 { 813 oscl_free(iFramePtr); 814 iFramePtr = NULL; 815 } 816 817 return OMX_ErrorNone; 818 } 819 820 821 int AvcEncoder_OMX::AVC_DPBAlloc(uint frame_size_in_mbs, uint num_buffers) 822 { 823 int ii; 824 uint frame_size = (frame_size_in_mbs << 8) + (frame_size_in_mbs << 7); 825 826 if (iDPB) oscl_free(iDPB); // free previous one first 827 828 iDPB = (uint8*) oscl_malloc(sizeof(uint8) * frame_size * num_buffers); 829 if (iDPB == NULL) 830 { 831 return 0; 832 } 833 834 iNumFrames = num_buffers; 835 836 if (iFrameUsed) oscl_free(iFrameUsed); // free previous one 837 838 iFrameUsed = (bool*) oscl_malloc(sizeof(bool) * num_buffers); 839 if (iFrameUsed == NULL) 840 { 841 return 0; 842 } 843 844 if (iFramePtr) oscl_free(iFramePtr); // free previous one 845 iFramePtr = (uint8**) oscl_malloc(sizeof(uint8*) * num_buffers); 846 if (iFramePtr == NULL) 847 { 848 return 0; 849 } 850 851 iFramePtr[0] = iDPB; 852 iFrameUsed[0] = false; 853 854 for (ii = 1; ii < (int)num_buffers; ii++) 855 { 856 iFrameUsed[ii] = false; 857 iFramePtr[ii] = iFramePtr[ii-1] + frame_size; 858 } 859 860 return 1; 861 } 862 863 864 //Request for an I frame while encoding is in process 865 OMX_ERRORTYPE AvcEncoder_OMX::AvcRequestIFrame() 866 { 867 if (AVCENC_SUCCESS != PVAVCEncIDRRequest(&iAvcHandle)) 868 { 869 return OMX_ErrorUndefined; 870 } 871 872 return OMX_ErrorNone; 873 874 } 875 876 //Routine to update bitrate dynamically when encoding is in progress 877 OMX_BOOL AvcEncoder_OMX::AvcUpdateBitRate(OMX_U32 aEncodedBitRate) 878 { 879 int32 BitRate[2] = {0, 0}; 880 BitRate[0] = aEncodedBitRate; 881 882 if (AVCENC_SUCCESS != PVAVCEncUpdateBitRate(&iAvcHandle, BitRate[0])) 883 { 884 return OMX_FALSE; 885 } 886 887 return OMX_TRUE; 888 } 889 890 //Routine to update frame rate dynamically when encoding is in progress 891 OMX_BOOL AvcEncoder_OMX::AvcUpdateFrameRate(OMX_U32 aEncodeFramerate) 892 { 893 OMX_U32 EncFrameRate[2] = {0, 0}; 894 EncFrameRate[0] = aEncodeFramerate >> 16; 895 896 if (AVCENC_SUCCESS != PVAVCEncUpdateFrameRate(&iAvcHandle, (uint32)(1000*EncFrameRate[0]), 1000)) 897 { 898 return OMX_FALSE; 899 } 900 901 return OMX_TRUE; 902 903 } 904 905 906 907 /* ///////////////////////////////////////////////////////////////////////// */ 908 void AvcEncoder_OMX::AVC_FrameUnbind(int indx) 909 { 910 /*if (indx < iNumFrames) 911 { 912 iFrameUsed[indx] = false; 913 }*/ 914 915 OSCL_UNUSED_ARG(indx); 916 return ; 917 } 918 919 /* ///////////////////////////////////////////////////////////////////////// */ 920 int AvcEncoder_OMX::AVC_FrameBind(int indx, uint8** yuv) 921 { 922 /*if ((iFrameUsed[indx]==true) || (indx >= iNumFrames)) 923 { 924 return 0; // already in used 925 } 926 iFrameUsed[indx] = true;*/ 927 928 *yuv = iFramePtr[indx]; 929 return 1; 930 } 931 932 933 934 /* ///////////////////////////////////////////////////////////////////////// */ 935 /* Copy from YUV input to YUV frame inside AvcEnc lib */ 936 /* When input is not YUV, the color conv will write it directly to iVideoInOut. */ 937 /* ///////////////////////////////////////////////////////////////////////// */ 938 939 void AvcEncoder_OMX::CopyToYUVIn(uint8 *YUV, int width, int height, int width_16, int height_16) 940 { 941 uint8 *y, *u, *v, *yChan, *uChan, *vChan; 942 int y_ind, ilimit, jlimit, i, j, ioffset; 943 int size = width * height; 944 int size16 = width_16 * height_16; 945 946 /* do padding at the bottom first */ 947 /* do padding if input RGB size(height) is different from the output YUV size(height_16) */ 948 if (height < height_16 || width < width_16) /* if padding */ 949 { 950 int offset = (height < height_16) ? height : height_16; 951 952 offset = (offset * width_16); 953 954 if (width < width_16) 955 { 956 offset -= (width_16 - width); 957 } 958 959 yChan = (uint8*)(iYUVIn + offset); 960 oscl_memset(yChan, 16, size16 - offset); /* pad with zeros */ 961 962 uChan = (uint8*)(iYUVIn + size16 + (offset >> 2)); 963 oscl_memset(uChan, 128, (size16 - offset) >> 2); 964 965 vChan = (uint8*)(iYUVIn + size16 + (size16 >> 2) + (offset >> 2)); 966 oscl_memset(vChan, 128, (size16 - offset) >> 2); 967 } 968 969 /* then do padding on the top */ 970 yChan = (uint8*)iYUVIn; /* Normal order */ 971 uChan = (uint8*)(iYUVIn + size16); 972 vChan = (uint8*)(uChan + (size16 >> 2)); 973 974 u = (uint8*)(&(YUV[size])); 975 v = (uint8*)(&(YUV[size*5/4])); 976 977 /* To center the output */ 978 if (height_16 > height) /* output taller than input */ 979 { 980 if (width_16 >= width) /* output wider than or equal input */ 981 { 982 i = ((height_16 - height) >> 1) * width_16 + (((width_16 - width) >> 3) << 2); 983 /* make sure that (width_16-width)>>1 is divisible by 4 */ 984 j = ((height_16 - height) >> 2) * (width_16 >> 1) + (((width_16 - width) >> 4) << 2); 985 /* make sure that (width_16-width)>>2 is divisible by 4 */ 986 } 987 else /* output narrower than input */ 988 { 989 i = ((height_16 - height) >> 1) * width_16; 990 j = ((height_16 - height) >> 2) * (width_16 >> 1); 991 YUV += ((width - width_16) >> 1); 992 u += ((width - width_16) >> 2); 993 v += ((width - width_16) >> 2); 994 } 995 oscl_memset((uint8 *)yChan, 16, i); 996 yChan += i; 997 oscl_memset((uint8 *)uChan, 128, j); 998 uChan += j; 999 oscl_memset((uint8 *)vChan, 128, j); 1000 vChan += j; 1001 } 1002 else /* output shorter or equal input */ 1003 { 1004 if (width_16 >= width) /* output wider or equal input */ 1005 { 1006 i = (((width_16 - width) >> 3) << 2); 1007 /* make sure that (width_16-width)>>1 is divisible by 4 */ 1008 j = (((width_16 - width) >> 4) << 2); 1009 /* make sure that (width_16-width)>>2 is divisible by 4 */ 1010 YUV += (((height - height_16) >> 1) * width); 1011 u += (((height - height_16) >> 1) * width) >> 2; 1012 v += (((height - height_16) >> 1) * width) >> 2; 1013 } 1014 else /* output narrower than input */ 1015 { 1016 i = 0; 1017 j = 0; 1018 YUV += (((height - height_16) >> 1) * width + ((width - width_16) >> 1)); 1019 u += (((height - height_16) >> 1) * width + ((width - width_16) >> 1)) >> 2; 1020 v += (((height - height_16) >> 1) * width + ((width - width_16) >> 1)) >> 2; 1021 } 1022 oscl_memset((uint8 *)yChan, 16, i); 1023 yChan += i; 1024 oscl_memset((uint8 *)uChan, 128, j); 1025 uChan += j; 1026 oscl_memset((uint8 *)vChan, 128, j); 1027 vChan += j; 1028 } 1029 1030 /* Copy with cropping or zero-padding */ 1031 if (height < height_16) 1032 jlimit = height; 1033 else 1034 jlimit = height_16; 1035 1036 if (width < width_16) 1037 { 1038 ilimit = width; 1039 ioffset = width_16 - width; 1040 } 1041 else 1042 { 1043 ilimit = width_16; 1044 ioffset = 0; 1045 } 1046 1047 /* Copy Y */ 1048 /* Set up pointer for fast looping */ 1049 y = (uint8*)YUV; 1050 1051 if (width == width_16 && height == height_16) /* no need to pad */ 1052 { 1053 oscl_memcpy(yChan, y, size); 1054 } 1055 else 1056 { 1057 for (y_ind = 0; y_ind < (jlimit - 1) ; y_ind++) 1058 { 1059 oscl_memcpy(yChan, y, ilimit); 1060 oscl_memset(yChan + ilimit, 16, ioffset); /* pad with zero */ 1061 yChan += width_16; 1062 y += width; 1063 } 1064 oscl_memcpy(yChan, y, ilimit); /* last line no padding */ 1065 } 1066 /* Copy U and V */ 1067 /* Set up pointers for fast looping */ 1068 if (width == width_16 && height == height_16) /* no need to pad */ 1069 { 1070 oscl_memcpy(uChan, u, size >> 2); 1071 oscl_memcpy(vChan, v, size >> 2); 1072 } 1073 else 1074 { 1075 for (y_ind = 0; y_ind < (jlimit >> 1) - 1; y_ind++) 1076 { 1077 oscl_memcpy(uChan, u, ilimit >> 1); 1078 oscl_memcpy(vChan, v, ilimit >> 1); 1079 oscl_memset(uChan + (ilimit >> 1), 128, ioffset >> 1); 1080 oscl_memset(vChan + (ilimit >> 1), 128, ioffset >> 1); 1081 uChan += (width_16 >> 1); 1082 u += (width >> 1); 1083 vChan += (width_16 >> 1); 1084 v += (width >> 1); 1085 } 1086 oscl_memcpy(uChan, u, ilimit >> 1); /* last line no padding */ 1087 oscl_memcpy(vChan, v, ilimit >> 1); 1088 } 1089 1090 return ; 1091 } 1092 1093 OMX_BOOL AvcEncoder_OMX::GetSpsPpsHeaderFlag() 1094 { 1095 return iSpsPpsHeaderFlag; 1096 } 1097 1098 1099