• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
CbAvcEncDebugLog_OMX(uint32 * userData,AVCLogType type,char * string1,int val1,int val2)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 
CbAvcEncMalloc_OMX(void * userData,int32 size,int attribute)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 
CbAvcEncFree_OMX(void * userData,int mem)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 
CbAvcEncDPBAlloc_OMX(void * userData,uint frame_size_in_mbs,uint num_buffers)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 
CbAvcEncFrameUnbind_OMX(void * userData,int indx)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 
CbAvcEncFrameBind_OMX(void * userData,int indx,uint8 ** yuv)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
AvcEncoder_OMX()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
~AvcEncoder_OMX()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 */
AvcEncInit(OMX_VIDEO_PORTDEFINITIONTYPE aInputParam,OMX_CONFIG_ROTATIONTYPE aInputOrientationType,OMX_VIDEO_PORTDEFINITIONTYPE aEncodeParam,OMX_VIDEO_PARAM_AVCTYPE aEncodeAvcParam,OMX_VIDEO_PARAM_BITRATETYPE aRateControlType,OMX_VIDEO_PARAM_QUANTIZATIONTYPE aQuantType,OMX_VIDEO_PARAM_MOTIONVECTORTYPE aSearchRange,OMX_VIDEO_PARAM_INTRAREFRESHTYPE aIntraRefresh,OMX_VIDEO_PARAM_VBSMCTYPE aVbsmcType)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 
AvcEncodeSendInput(OMX_U8 * aInBuffer,OMX_U32 * aInBufSize,OMX_TICKS aInTimeStamp)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 */
AvcEncodeVideo(OMX_U8 * aOutBuffer,OMX_U32 * aOutputLength,OMX_BOOL * aBufferOverRun,OMX_U8 ** aOverBufferPointer,OMX_U8 * aInBuffer,OMX_U32 * aInBufSize,OMX_TICKS aInTimeStamp,OMX_TICKS * aOutTimeStamp,OMX_BOOL * aSyncFlag)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
AvcEncDeinit()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 
AVC_DPBAlloc(uint frame_size_in_mbs,uint num_buffers)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
AvcRequestIFrame()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
AvcUpdateBitRate(OMX_U32 aEncodedBitRate)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
AvcUpdateFrameRate(OMX_U32 aEncodeFramerate)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 /* ///////////////////////////////////////////////////////////////////////// */
AVC_FrameUnbind(int indx)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 /* ///////////////////////////////////////////////////////////////////////// */
AVC_FrameBind(int indx,uint8 ** yuv)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 
CopyToYUVIn(uint8 * YUV,int width,int height,int width_16,int height_16)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 
GetSpsPpsHeaderFlag()1093 OMX_BOOL AvcEncoder_OMX::GetSpsPpsHeaderFlag()
1094 {
1095     return iSpsPpsHeaderFlag;
1096 }
1097 
1098 
1099