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