Home | History | Annotate | Download | only in src
      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