1 /*-------------------------------------------------------------------------- 2 Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. 3 4 Redistribution and use in source and binary forms, with or without 5 modification, are permitted provided that the following conditions are met: 6 * Redistributions of source code must retain the above copyright 7 notice, this list of conditions and the following disclaimer. 8 * Redistributions in binary form must reproduce the above copyright 9 notice, this list of conditions and the following disclaimer in the 10 documentation and/or other materials provided with the distribution. 11 * Neither the name of Code Aurora nor 12 the names of its contributors may be used to endorse or promote 13 products derived from this software without specific prior written 14 permission. 15 16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 20 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 23 OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 25 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 26 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 --------------------------------------------------------------------------*/ 28 /*============================================================================ 29 V E N C _ T E S T. C P P 30 31 DESCRIPTION 32 33 This is the OMX test app . 34 35 REFERENCES 36 37 ============================================================================*/ 38 39 //usage 40 // FILE QVGA MP4 24 384000 100 enc_qvga.yuv QVGA_24.m4v 41 // FILE QCIF MP4 15 96000 0 foreman.qcif.yuv output_qcif.m4v 42 // FILE VGA MP4 24 1200000 218 enc_vga.yuv vga_output.m4v 43 #include <sys/types.h> 44 #include <sys/stat.h> 45 #include <string.h> 46 #include <unistd.h> 47 #include <stdlib.h> 48 #include <stdio.h> 49 #include <pthread.h> 50 #include <fcntl.h> 51 #include <sys/mman.h> 52 //#include <sys/time.h> 53 #include <time.h> 54 #include <sys/ioctl.h> 55 #include <limits.h> 56 #include <string.h> 57 //#include <sys/stat.h> 58 #include "OMX_QCOMExtns.h" 59 #include "OMX_Core.h" 60 61 #define QCOM_EXT 1 62 63 #include "OMX_Core.h" 64 #include "OMX_Video.h" 65 #include "OMX_Component.h" 66 #include "camera_test.h" 67 #include "fb_test.h" 68 #include "venc_util.h" 69 #include "extra_data_handler.h" 70 #ifdef USE_ION 71 #include <linux/msm_ion.h> 72 #endif 73 74 ////////////////////////// 75 // MACROS 76 ////////////////////////// 77 78 #define CHK(result) if (result != OMX_ErrorNone) { E("*************** error *************"); exit(0); } 79 #define TEST_LOG 80 #ifdef VENC_SYSLOG 81 #include "cutils/log.h" 82 /// Debug message macro 83 #define D(fmt, ...) LOGE("venc_test Debug %s::%d "fmt"\n", \ 84 __FUNCTION__, __LINE__, \ 85 ## __VA_ARGS__) 86 87 /// Error message macro 88 #define E(fmt, ...) LOGE("venc_test Error %s::%d "fmt"\n", \ 89 __FUNCTION__, __LINE__, \ 90 ## __VA_ARGS__) 91 92 #else 93 #ifdef TEST_LOG 94 #define D(fmt, ...) fprintf(stderr, "venc_test Debug %s::%d "fmt"\n", \ 95 __FUNCTION__, __LINE__, \ 96 ## __VA_ARGS__) 97 98 /// Error message macro 99 #define E(fmt, ...) fprintf(stderr, "venc_test Error %s::%d "fmt"\n", \ 100 __FUNCTION__, __LINE__, \ 101 ## __VA_ARGS__) 102 #else 103 #define D(fmt, ...) 104 #define E(fmt, ...) 105 #endif 106 107 #endif 108 109 ////////////////////////// 110 // CONSTANTS 111 ////////////////////////// 112 static const int MAX_MSG = 100; 113 //#warning do not hardcode these use port definition 114 static const int PORT_INDEX_IN = 0; 115 static const int PORT_INDEX_OUT = 1; 116 117 static const int NUM_IN_BUFFERS = 10; 118 static const int NUM_OUT_BUFFERS = 10; 119 120 unsigned int num_in_buffers = 0; 121 unsigned int num_out_buffers = 0; 122 123 ////////////////////////// 124 /* MPEG4 profile and level table*/ 125 static const unsigned int mpeg4_profile_level_table[][5]= 126 { 127 /*max mb per frame, max mb per sec, max bitrate, level, profile*/ 128 {99,1485,64000,OMX_VIDEO_MPEG4Level0,OMX_VIDEO_MPEG4ProfileSimple}, 129 {99,1485,64000,OMX_VIDEO_MPEG4Level1,OMX_VIDEO_MPEG4ProfileSimple}, 130 {396,5940,128000,OMX_VIDEO_MPEG4Level2,OMX_VIDEO_MPEG4ProfileSimple}, 131 {396,11880,384000,OMX_VIDEO_MPEG4Level3,OMX_VIDEO_MPEG4ProfileSimple}, 132 {1200,36000,4000000,OMX_VIDEO_MPEG4Level4a,OMX_VIDEO_MPEG4ProfileSimple}, 133 {1620,40500,8000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileSimple}, 134 {3600,108000,12000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileSimple}, 135 {0,0,0,0,0}, 136 137 {99,1485,128000,OMX_VIDEO_MPEG4Level0,OMX_VIDEO_MPEG4ProfileAdvancedSimple}, 138 {99,1485,128000,OMX_VIDEO_MPEG4Level1,OMX_VIDEO_MPEG4ProfileAdvancedSimple}, 139 {396,5940,384000,OMX_VIDEO_MPEG4Level2,OMX_VIDEO_MPEG4ProfileAdvancedSimple}, 140 {396,11880,768000,OMX_VIDEO_MPEG4Level3,OMX_VIDEO_MPEG4ProfileAdvancedSimple}, 141 {792,23760,3000000,OMX_VIDEO_MPEG4Level4,OMX_VIDEO_MPEG4ProfileAdvancedSimple}, 142 {1620,48600,8000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileAdvancedSimple}, 143 {0,0,0,0,0}, 144 }; 145 146 /* H264 profile and level table*/ 147 static const unsigned int h264_profile_level_table[][5]= 148 { 149 /*max mb per frame, max mb per sec, max bitrate, level, profile*/ 150 {99,1485,64000,OMX_VIDEO_AVCLevel1,OMX_VIDEO_AVCProfileBaseline}, 151 {99,1485,128000,OMX_VIDEO_AVCLevel1b,OMX_VIDEO_AVCProfileBaseline}, 152 {396,3000,192000,OMX_VIDEO_AVCLevel11,OMX_VIDEO_AVCProfileBaseline}, 153 {396,6000,384000,OMX_VIDEO_AVCLevel12,OMX_VIDEO_AVCProfileBaseline}, 154 {396,11880,768000,OMX_VIDEO_AVCLevel13,OMX_VIDEO_AVCProfileBaseline}, 155 {396,11880,2000000,OMX_VIDEO_AVCLevel2,OMX_VIDEO_AVCProfileBaseline}, 156 {792,19800,4000000,OMX_VIDEO_AVCLevel21,OMX_VIDEO_AVCProfileBaseline}, 157 {1620,20250,4000000,OMX_VIDEO_AVCLevel22,OMX_VIDEO_AVCProfileBaseline}, 158 {1620,40500,10000000,OMX_VIDEO_AVCLevel3,OMX_VIDEO_AVCProfileBaseline}, 159 {3600,108000,14000000,OMX_VIDEO_AVCLevel31,OMX_VIDEO_AVCProfileBaseline}, 160 {5120,216000,20000000,OMX_VIDEO_AVCLevel32,OMX_VIDEO_AVCProfileBaseline}, 161 {8192,245760,20000000,OMX_VIDEO_AVCLevel4,OMX_VIDEO_AVCProfileBaseline}, 162 {0,0,0,0,0}, 163 164 {99,1485,64000,OMX_VIDEO_AVCLevel1,OMX_VIDEO_AVCProfileHigh}, 165 {99,1485,160000,OMX_VIDEO_AVCLevel1b,OMX_VIDEO_AVCProfileHigh}, 166 {396,3000,240000,OMX_VIDEO_AVCLevel11,OMX_VIDEO_AVCProfileHigh}, 167 {396,6000,480000,OMX_VIDEO_AVCLevel12,OMX_VIDEO_AVCProfileHigh}, 168 {396,11880,960000,OMX_VIDEO_AVCLevel13,OMX_VIDEO_AVCProfileHigh}, 169 {396,11880,2500000,OMX_VIDEO_AVCLevel2,OMX_VIDEO_AVCProfileHigh}, 170 {792,19800,5000000,OMX_VIDEO_AVCLevel21,OMX_VIDEO_AVCProfileHigh}, 171 {1620,20250,5000000,OMX_VIDEO_AVCLevel22,OMX_VIDEO_AVCProfileHigh}, 172 {1620,40500,12500000,OMX_VIDEO_AVCLevel3,OMX_VIDEO_AVCProfileHigh}, 173 {3600,108000,17500000,OMX_VIDEO_AVCLevel31,OMX_VIDEO_AVCProfileHigh}, 174 {5120,216000,25000000,OMX_VIDEO_AVCLevel32,OMX_VIDEO_AVCProfileHigh}, 175 {8192,245760,25000000,OMX_VIDEO_AVCLevel4,OMX_VIDEO_AVCProfileHigh}, 176 {0,0,0,0,0}, 177 178 {99,1485,64000,OMX_VIDEO_AVCLevel1,OMX_VIDEO_AVCProfileMain}, 179 {99,1485,128000,OMX_VIDEO_AVCLevel1b,OMX_VIDEO_AVCProfileMain}, 180 {396,3000,192000,OMX_VIDEO_AVCLevel11,OMX_VIDEO_AVCProfileMain}, 181 {396,6000,384000,OMX_VIDEO_AVCLevel12,OMX_VIDEO_AVCProfileMain}, 182 {396,11880,768000,OMX_VIDEO_AVCLevel13,OMX_VIDEO_AVCProfileMain}, 183 {396,11880,2000000,OMX_VIDEO_AVCLevel2,OMX_VIDEO_AVCProfileMain}, 184 {792,19800,4000000,OMX_VIDEO_AVCLevel21,OMX_VIDEO_AVCProfileMain}, 185 {1620,20250,4000000,OMX_VIDEO_AVCLevel22,OMX_VIDEO_AVCProfileMain}, 186 {1620,40500,10000000,OMX_VIDEO_AVCLevel3,OMX_VIDEO_AVCProfileMain}, 187 {3600,108000,14000000,OMX_VIDEO_AVCLevel31,OMX_VIDEO_AVCProfileMain}, 188 {5120,216000,20000000,OMX_VIDEO_AVCLevel32,OMX_VIDEO_AVCProfileMain}, 189 {8192,245760,20000000,OMX_VIDEO_AVCLevel4,OMX_VIDEO_AVCProfileMain}, 190 {0,0,0,0,0} 191 192 }; 193 194 /* H263 profile and level table*/ 195 static const unsigned int h263_profile_level_table[][5]= 196 { 197 /*max mb per frame, max mb per sec, max bitrate, level, profile*/ 198 {99,1485,64000,OMX_VIDEO_H263Level10,OMX_VIDEO_H263ProfileBaseline}, 199 {396,5940,128000,OMX_VIDEO_H263Level20,OMX_VIDEO_H263ProfileBaseline}, 200 {396,11880,384000,OMX_VIDEO_H263Level30,OMX_VIDEO_H263ProfileBaseline}, 201 {396,11880,2048000,OMX_VIDEO_H263Level40,OMX_VIDEO_H263ProfileBaseline}, 202 {99,1485,128000,OMX_VIDEO_H263Level45,OMX_VIDEO_H263ProfileBaseline}, 203 {396,19800,4096000,OMX_VIDEO_H263Level50,OMX_VIDEO_H263ProfileBaseline}, 204 {810,40500,8192000,OMX_VIDEO_H263Level60,OMX_VIDEO_H263ProfileBaseline}, 205 {1620,81000,16384000,OMX_VIDEO_H263Level70,OMX_VIDEO_H263ProfileBaseline}, 206 {0,0,0,0,0} 207 }; 208 209 #define Log2(number, power) { OMX_U32 temp = number; power = 0; while( (0 == (temp & 0x1)) && power < 16) { temp >>=0x1; power++; } } 210 #define FractionToQ16(q,num,den) { OMX_U32 power; Log2(den,power); q = num << (16 - power); } 211 212 ////////////////////////// 213 // TYPES 214 ////////////////////////// 215 struct ProfileType 216 { 217 OMX_VIDEO_CODINGTYPE eCodec; 218 OMX_VIDEO_MPEG4LEVELTYPE eLevel; 219 OMX_VIDEO_CONTROLRATETYPE eControlRate; 220 OMX_VIDEO_AVCSLICEMODETYPE eSliceMode; 221 OMX_U32 nFrameWidth; 222 OMX_U32 nFrameHeight; 223 OMX_U32 nFrameBytes; 224 #ifdef BADGER 225 OMX_U32 nFramestride; 226 OMX_U32 nFrameScanlines; 227 OMX_U32 nFrameRead; 228 #endif 229 OMX_U32 nBitrate; 230 float nFramerate; 231 char* cInFileName; 232 char* cOutFileName; 233 OMX_U32 nUserProfile; 234 }; 235 236 enum MsgId 237 { 238 MSG_ID_OUTPUT_FRAME_DONE, 239 MSG_ID_INPUT_FRAME_DONE, 240 MSG_ID_MAX 241 }; 242 union MsgData 243 { 244 struct 245 { 246 OMX_BUFFERHEADERTYPE* pBuffer; 247 } sBitstreamData; 248 }; 249 struct Msg 250 { 251 MsgId id; 252 MsgData data; 253 }; 254 struct MsgQ 255 { 256 Msg q[MAX_MSG]; 257 int head; 258 int size; 259 }; 260 261 enum Mode 262 { 263 MODE_PREVIEW, 264 MODE_DISPLAY, 265 MODE_PROFILE, 266 MODE_FILE_ENCODE, 267 MODE_LIVE_ENCODE 268 }; 269 270 enum ResyncMarkerType 271 { 272 RESYNC_MARKER_NONE, ///< No resync marker 273 RESYNC_MARKER_BYTE, ///< BYTE Resync marker for MPEG4, H.264 274 RESYNC_MARKER_MB, ///< MB resync marker for MPEG4, H.264 275 RESYNC_MARKER_GOB ///< GOB resync marker for H.263 276 }; 277 278 union DynamicConfigData 279 { 280 OMX_VIDEO_CONFIG_BITRATETYPE bitrate; 281 OMX_CONFIG_FRAMERATETYPE framerate; 282 QOMX_VIDEO_INTRAPERIODTYPE intraperiod; 283 OMX_CONFIG_INTRAREFRESHVOPTYPE intravoprefresh; 284 OMX_CONFIG_ROTATIONTYPE rotation; 285 float f_framerate; 286 }; 287 288 struct DynamicConfig 289 { 290 bool pending; 291 unsigned frame_num; 292 OMX_INDEXTYPE config_param; 293 union DynamicConfigData config_data; 294 }; 295 296 #ifdef USE_ION 297 struct enc_ion 298 { 299 int ion_device_fd; 300 struct ion_allocation_data alloc_data; 301 struct ion_fd_data ion_alloc_fd; 302 }; 303 #endif 304 305 ////////////////////////// 306 // MODULE VARS 307 ////////////////////////// 308 static pthread_mutex_t m_mutex; 309 static pthread_cond_t m_signal; 310 static MsgQ m_sMsgQ; 311 312 //#warning determine how many buffers we really have 313 OMX_STATETYPE m_eState = OMX_StateInvalid; 314 OMX_COMPONENTTYPE m_sComponent; 315 OMX_HANDLETYPE m_hHandle = NULL; 316 OMX_BUFFERHEADERTYPE* m_pOutBuffers[NUM_OUT_BUFFERS] = {NULL}; 317 OMX_BUFFERHEADERTYPE* m_pInBuffers[NUM_IN_BUFFERS] = {NULL}; 318 OMX_BOOL m_bInFrameFree[NUM_IN_BUFFERS]; 319 320 ProfileType m_sProfile; 321 322 static int m_nFramePlay = 0; 323 static int m_eMode = MODE_PREVIEW; 324 static int m_nInFd = -1; 325 static int m_nOutFd = -1; 326 static int m_nTimeStamp = 0; 327 static int m_nFrameIn = 0; // frames pushed to encoder 328 static int m_nFrameOut = 0; // frames returned by encoder 329 static int m_nAVCSliceMode = 0; 330 static bool m_bWatchDogKicked = false; 331 FILE *m_pDynConfFile = NULL; 332 static struct DynamicConfig dynamic_config; 333 334 /* Statistics Logging */ 335 static long long tot_bufsize = 0; 336 int ebd_cnt=0, fbd_cnt=0; 337 338 #ifdef USE_ION 339 static const char* PMEM_DEVICE = "/dev/ion"; 340 #elif MAX_RES_720P 341 static const char* PMEM_DEVICE = "/dev/pmem_adsp"; 342 #elif MAX_RES_1080P_EBI 343 static const char* PMEM_DEVICE = "/dev/pmem_adsp"; 344 #elif MAX_RES_1080P 345 static const char* PMEM_DEVICE = "/dev/pmem_smipool"; 346 #else 347 #error PMEM_DEVICE cannot be determined. 348 #endif 349 350 #ifdef USE_ION 351 struct enc_ion ion_data; 352 #endif 353 ////////////////////////// 354 // MODULE FUNCTIONS 355 ////////////////////////// 356 357 void* PmemMalloc(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO* pMem, int nSize) 358 { 359 void *pvirt = NULL; 360 int rc = 0; 361 362 if (!pMem) 363 return NULL; 364 365 #ifdef USE_ION 366 ion_data.ion_device_fd = open (PMEM_DEVICE,O_RDONLY); 367 if(ion_data.ion_device_fd < 0) 368 { 369 E("\nERROR: ION Device open() Failed"); 370 return NULL; 371 } 372 nSize = (nSize + 4095) & (~4095); 373 ion_data.alloc_data.len = nSize; 374 ion_data.alloc_data.heap_id_mask = 0x1 << ION_CP_MM_HEAP_ID; 375 ion_data.alloc_data.align = 4096; 376 ion_data.alloc_data.flags = 0; 377 378 rc = ioctl(ion_data.ion_device_fd,ION_IOC_ALLOC,&ion_data.alloc_data); 379 if(rc || !ion_data.alloc_data.handle) { 380 E("\n ION ALLOC memory failed "); 381 ion_data.alloc_data.handle=NULL; 382 return NULL; 383 } 384 385 ion_data.ion_alloc_fd.handle = ion_data.alloc_data.handle; 386 rc = ioctl(ion_data.ion_device_fd,ION_IOC_MAP,&ion_data.ion_alloc_fd); 387 if(rc) { 388 E("\n ION MAP failed "); 389 ion_data.ion_alloc_fd.fd =-1; 390 ion_data.ion_alloc_fd.fd =-1; 391 return NULL; 392 } 393 pMem->pmem_fd = ion_data.ion_alloc_fd.fd; 394 #else 395 pMem->pmem_fd = open(PMEM_DEVICE, O_RDWR); 396 if ((int)(pMem->pmem_fd) < 0) 397 return NULL; 398 nSize = (nSize + 4095) & (~4095); 399 #endif 400 pMem->offset = 0; 401 pvirt = mmap(NULL, nSize, 402 PROT_READ | PROT_WRITE, 403 MAP_SHARED, pMem->pmem_fd, pMem->offset); 404 if (pvirt == (void*) MAP_FAILED) 405 { 406 close(pMem->pmem_fd); 407 pMem->pmem_fd = -1; 408 #ifdef USE_ION 409 if(ioctl(ion_data.ion_device_fd,ION_IOC_FREE, 410 &ion_data.alloc_data.handle)) { 411 E("ion recon buffer free failed"); 412 } 413 ion_data.alloc_data.handle = NULL; 414 ion_data.ion_alloc_fd.fd =-1; 415 close(ion_data.ion_device_fd); 416 ion_data.ion_device_fd =-1; 417 #endif 418 return NULL; 419 } 420 D("allocated pMem->fd = %d pvirt=0x%x, pMem->phys=0x%x, size = %d", pMem->pmem_fd, 421 pvirt, pMem->offset, nSize); 422 return pvirt; 423 } 424 425 int PmemFree(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO* pMem, void* pvirt, int nSize) 426 { 427 if (!pMem || !pvirt) 428 return -1; 429 430 nSize = (nSize + 4095) & (~4095); 431 munmap(pvirt, nSize); 432 close(pMem->pmem_fd); 433 pMem->pmem_fd = -1; 434 #ifdef USE_ION 435 if(ioctl(ion_data.ion_device_fd,ION_IOC_FREE, 436 &ion_data.alloc_data.handle)) { 437 E("ion recon buffer free failed"); 438 } 439 ion_data.alloc_data.handle = NULL; 440 ion_data.ion_alloc_fd.fd =-1; 441 close(ion_data.ion_device_fd); 442 ion_data.ion_device_fd =-1; 443 #endif 444 return 0; 445 } 446 void PrintFramePackArrangement(OMX_QCOM_FRAME_PACK_ARRANGEMENT framePackingArrangement) 447 { 448 printf("id (%d)\n", 449 framePackingArrangement.id); 450 printf("cancel_flag (%d)\n", 451 framePackingArrangement.cancel_flag); 452 printf("type (%d)\n", 453 framePackingArrangement.type); 454 printf("quincunx_sampling_flag (%d)\n", 455 framePackingArrangement.quincunx_sampling_flag); 456 printf("content_interpretation_type (%d)\n", 457 framePackingArrangement.content_interpretation_type); 458 printf("spatial_flipping_flag (%d)\n", 459 framePackingArrangement.spatial_flipping_flag); 460 printf("frame0_flipped_flag (%d)\n", 461 framePackingArrangement.frame0_flipped_flag); 462 printf("field_views_flag (%d)\n", 463 framePackingArrangement.field_views_flag); 464 printf("current_frame_is_frame0_flag (%d)\n", 465 framePackingArrangement.current_frame_is_frame0_flag); 466 printf("frame0_self_contained_flag (%d)\n", 467 framePackingArrangement.frame0_self_contained_flag); 468 printf("frame1_self_contained_flag (%d)\n", 469 framePackingArrangement.frame1_self_contained_flag); 470 printf("frame0_grid_position_x (%d)\n", 471 framePackingArrangement.frame0_grid_position_x); 472 printf("frame0_grid_position_y (%d)\n", 473 framePackingArrangement.frame0_grid_position_y); 474 printf("frame1_grid_position_x (%d)\n", 475 framePackingArrangement.frame1_grid_position_x); 476 printf("frame1_grid_position_y (%d)\n", 477 framePackingArrangement.frame1_grid_position_y); 478 printf("reserved_byte (%d)\n", 479 framePackingArrangement.reserved_byte); 480 printf("repetition_period (%d)\n", 481 framePackingArrangement.repetition_period); 482 printf("extension_flag (%d)\n", 483 framePackingArrangement.extension_flag); 484 } 485 void SetState(OMX_STATETYPE eState) 486 { 487 #define GOTO_STATE(eState) \ 488 case eState: \ 489 { \ 490 D("Going to state " # eState"..."); \ 491 OMX_SendCommand(m_hHandle, \ 492 OMX_CommandStateSet, \ 493 (OMX_U32) eState, \ 494 NULL); \ 495 while (m_eState != eState) \ 496 { \ 497 sleep(1); \ 498 } \ 499 D("Now in state " # eState); \ 500 break; \ 501 } 502 503 switch (eState) 504 { 505 GOTO_STATE(OMX_StateLoaded); 506 GOTO_STATE(OMX_StateIdle); 507 GOTO_STATE(OMX_StateExecuting); 508 GOTO_STATE(OMX_StateInvalid); 509 GOTO_STATE(OMX_StateWaitForResources); 510 GOTO_STATE(OMX_StatePause); 511 } 512 } 513 //////////////////////////////////////////////////////////////////////////////// 514 OMX_ERRORTYPE ConfigureEncoder() 515 { 516 OMX_ERRORTYPE result = OMX_ErrorNone; 517 unsigned const int *profile_tbl = (unsigned int const *)mpeg4_profile_level_table; 518 OMX_U32 mb_per_sec, mb_per_frame; 519 bool profile_level_found = false; 520 OMX_U32 eProfile,eLevel; 521 522 OMX_PARAM_PORTDEFINITIONTYPE portdef; // OMX_IndexParamPortDefinition 523 #ifdef QCOM_EXT 524 OMX_QCOM_PARAM_PORTDEFINITIONTYPE qPortDefnType; 525 #endif 526 portdef.nPortIndex = (OMX_U32) 0; // input 527 result = OMX_GetParameter(m_hHandle, 528 OMX_IndexParamPortDefinition, 529 &portdef); 530 E("\n OMX_IndexParamPortDefinition Get Paramter on input port"); 531 CHK(result); 532 portdef.format.video.nFrameWidth = m_sProfile.nFrameWidth; 533 portdef.format.video.nFrameHeight = m_sProfile.nFrameHeight; 534 535 E ("\n Height %d width %d bit rate %d",portdef.format.video.nFrameHeight 536 ,portdef.format.video.nFrameWidth,portdef.format.video.nBitrate); 537 result = OMX_SetParameter(m_hHandle, 538 OMX_IndexParamPortDefinition, 539 &portdef); 540 E("\n OMX_IndexParamPortDefinition Set Paramter on input port"); 541 CHK(result); 542 // once more to get proper buffer size 543 result = OMX_GetParameter(m_hHandle, 544 OMX_IndexParamPortDefinition, 545 &portdef); 546 E("\n OMX_IndexParamPortDefinition Get Paramter on input port, 2nd pass"); 547 CHK(result); 548 // update size accordingly 549 m_sProfile.nFrameBytes = portdef.nBufferSize; 550 portdef.nPortIndex = (OMX_U32) 1; // output 551 result = OMX_GetParameter(m_hHandle, 552 OMX_IndexParamPortDefinition, 553 &portdef); 554 E("\n OMX_IndexParamPortDefinition Get Paramter on output port"); 555 CHK(result); 556 portdef.format.video.nFrameWidth = m_sProfile.nFrameWidth; 557 portdef.format.video.nFrameHeight = m_sProfile.nFrameHeight; 558 portdef.format.video.nBitrate = m_sProfile.nBitrate; 559 FractionToQ16(portdef.format.video.xFramerate,(int) (m_sProfile.nFramerate * 2),2); 560 result = OMX_SetParameter(m_hHandle, 561 OMX_IndexParamPortDefinition, 562 &portdef); 563 E("\n OMX_IndexParamPortDefinition Set Paramter on output port"); 564 CHK(result); 565 566 #ifdef QCOM_EXT 567 568 qPortDefnType.nPortIndex = PORT_INDEX_IN; 569 qPortDefnType.nMemRegion = OMX_QCOM_MemRegionEBI1; 570 qPortDefnType.nSize = sizeof(OMX_QCOM_PARAM_PORTDEFINITIONTYPE); 571 572 result = OMX_SetParameter(m_hHandle, 573 (OMX_INDEXTYPE)OMX_QcomIndexPortDefn, 574 &qPortDefnType); 575 576 #endif 577 if (!m_sProfile.nUserProfile) // profile not set by user, go ahead with table calculation 578 { 579 //validate the ht,width,fps,bitrate and set the appropriate profile and level 580 if(m_sProfile.eCodec == OMX_VIDEO_CodingMPEG4) 581 { 582 profile_tbl = (unsigned int const *)mpeg4_profile_level_table; 583 } 584 else if(m_sProfile.eCodec == OMX_VIDEO_CodingAVC) 585 { 586 profile_tbl = (unsigned int const *)h264_profile_level_table; 587 } 588 else if(m_sProfile.eCodec == OMX_VIDEO_CodingH263) 589 { 590 profile_tbl = (unsigned int const *)h263_profile_level_table; 591 } 592 593 mb_per_frame = ((m_sProfile.nFrameHeight+15)>>4)* 594 ((m_sProfile.nFrameWidth+15)>>4); 595 596 mb_per_sec = mb_per_frame*(m_sProfile.nFramerate); 597 598 do{ 599 if(mb_per_frame <= (int)profile_tbl[0]) 600 { 601 if(mb_per_sec <= (int)profile_tbl[1]) 602 { 603 if(m_sProfile.nBitrate <= (int)profile_tbl[2]) 604 { 605 eLevel = (int)profile_tbl[3]; 606 eProfile = (int)profile_tbl[4]; 607 E("\n profile/level found: %d/%d\n",eProfile/eLevel); 608 profile_level_found = true; 609 break; 610 } 611 } 612 } 613 profile_tbl = profile_tbl + 5; 614 }while(profile_tbl[0] != 0); 615 616 if ( profile_level_found != true ) 617 { 618 E("\n Error: Unsupported profile/level\n"); 619 return OMX_ErrorNone; 620 } 621 } 622 else // Profile set by user! 623 { 624 eProfile = m_sProfile.nUserProfile; 625 eLevel = 0; 626 } 627 if (m_sProfile.eCodec == OMX_VIDEO_CodingH263) 628 { 629 D("Configuring H263..."); 630 631 OMX_VIDEO_PARAM_H263TYPE h263; 632 result = OMX_GetParameter(m_hHandle, 633 OMX_IndexParamVideoH263, 634 &h263); 635 CHK(result); 636 h263.nPortIndex = (OMX_U32) PORT_INDEX_OUT; 637 h263.nPFrames = m_sProfile.nFramerate * 2 - 1; // intra period 638 h263.nBFrames = 0; 639 h263.eProfile = (OMX_VIDEO_H263PROFILETYPE)eProfile; 640 h263.eLevel = (OMX_VIDEO_H263LEVELTYPE)eLevel; 641 h263.bPLUSPTYPEAllowed = OMX_FALSE; 642 h263.nAllowedPictureTypes = 2; 643 h263.bForceRoundingTypeToZero = OMX_TRUE; 644 h263.nPictureHeaderRepetition = 0; 645 h263.nGOBHeaderInterval = 1; 646 result = OMX_SetParameter(m_hHandle, 647 OMX_IndexParamVideoH263, 648 &h263); 649 } 650 else 651 { 652 D("Configuring MP4/H264..."); 653 654 OMX_VIDEO_PARAM_PROFILELEVELTYPE profileLevel; // OMX_IndexParamVideoProfileLevelCurrent 655 profileLevel.nPortIndex = (OMX_U32) PORT_INDEX_OUT; 656 profileLevel.eProfile = eProfile; 657 profileLevel.eLevel = eLevel; 658 result = OMX_SetParameter(m_hHandle, 659 OMX_IndexParamVideoProfileLevelCurrent, 660 &profileLevel); 661 E("\n OMX_IndexParamVideoProfileLevelCurrent Set Paramter port"); 662 CHK(result); 663 //profileLevel.eLevel = (OMX_U32) m_sProfile.eLevel; 664 result = OMX_GetParameter(m_hHandle, 665 OMX_IndexParamVideoProfileLevelCurrent, 666 &profileLevel); 667 E("\n OMX_IndexParamVideoProfileLevelCurrent Get Paramter port"); 668 D ("\n Profile = %d level = %d",profileLevel.eProfile,profileLevel.eLevel); 669 CHK(result); 670 671 if (m_sProfile.eCodec == OMX_VIDEO_CodingMPEG4) 672 { 673 OMX_VIDEO_PARAM_MPEG4TYPE mp4; // OMX_IndexParamVideoMpeg4 674 result = OMX_GetParameter(m_hHandle, 675 OMX_IndexParamVideoMpeg4, 676 &mp4); 677 CHK(result); 678 mp4.nPortIndex = (OMX_U32) PORT_INDEX_OUT; 679 mp4.nTimeIncRes = 1000; 680 result = OMX_SetParameter(m_hHandle, 681 OMX_IndexParamVideoMpeg4, 682 &mp4); 683 CHK(result); 684 } 685 } 686 if (m_sProfile.eCodec == OMX_VIDEO_CodingAVC) 687 { 688 #if 1 689 /////////////C A B A C ///A N D/////D E B L O C K I N G ///////////////// 690 691 OMX_VIDEO_PARAM_AVCTYPE avcdata; 692 avcdata.nPortIndex = (OMX_U32)PORT_INDEX_OUT; 693 result = OMX_GetParameter(m_hHandle, 694 OMX_IndexParamVideoAvc, 695 &avcdata); 696 CHK(result); 697 // TEST VALUES (CHANGE FOR DIFF CONFIG's) 698 avcdata.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable; 699 // avcdata.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterDisable; 700 // avcdata.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterDisableSliceBoundary; 701 avcdata.bEntropyCodingCABAC = OMX_FALSE; 702 // avcdata.bEntropyCodingCABAC = OMX_TRUE; 703 avcdata.nCabacInitIdc = 1; 704 /////////////////////////////////////////////// 705 706 result = OMX_SetParameter(m_hHandle, 707 OMX_IndexParamVideoAvc, 708 &avcdata); 709 CHK(result); 710 711 /////////////C A B A C ///A N D/////D E B L O C K I N G ///////////////// 712 #endif 713 } 714 715 OMX_VIDEO_PARAM_BITRATETYPE bitrate; // OMX_IndexParamVideoBitrate 716 bitrate.nPortIndex = (OMX_U32)PORT_INDEX_OUT; 717 result = OMX_GetParameter(m_hHandle, 718 OMX_IndexParamVideoBitrate, 719 &bitrate); 720 E("\n OMX_IndexParamVideoBitrate Get Paramter port"); 721 CHK(result); 722 bitrate.eControlRate = m_sProfile.eControlRate; 723 bitrate.nTargetBitrate = m_sProfile.nBitrate; 724 result = OMX_SetParameter(m_hHandle, 725 OMX_IndexParamVideoBitrate, 726 &bitrate); 727 E("\n OMX_IndexParamVideoBitrate Set Paramter port"); 728 CHK(result); 729 730 OMX_VIDEO_PARAM_PORTFORMATTYPE framerate; // OMX_IndexParamVidePortFormat 731 framerate.nPortIndex = 0; 732 result = OMX_GetParameter(m_hHandle, 733 OMX_IndexParamVideoPortFormat, 734 &framerate); 735 E("\n OMX_IndexParamVideoPortFormat Get Paramter port"); 736 CHK(result); 737 FractionToQ16(framerate.xFramerate,(int) (m_sProfile.nFramerate * 2),2); 738 result = OMX_SetParameter(m_hHandle, 739 OMX_IndexParamVideoPortFormat, 740 &framerate); 741 E("\n OMX_IndexParamVideoPortFormat Set Paramter port"); 742 CHK(result); 743 744 #if 1 745 ///////////////////I N T R A P E R I O D /////////////////// 746 747 QOMX_VIDEO_INTRAPERIODTYPE intra; 748 749 intra.nPortIndex = (OMX_U32) PORT_INDEX_OUT; // output 750 result = OMX_GetConfig(m_hHandle, 751 (OMX_INDEXTYPE) QOMX_IndexConfigVideoIntraperiod, 752 (OMX_PTR) &intra); 753 754 if (result == OMX_ErrorNone) 755 { 756 intra.nPFrames = (OMX_U32) (2 * m_sProfile.nFramerate - 1); //setting I 757 //frame interval to 758 //2 x framerate 759 intra.nIDRPeriod = 1; //every I frame is an IDR 760 intra.nPortIndex = (OMX_U32) PORT_INDEX_OUT; 761 result = OMX_SetConfig(m_hHandle, 762 (OMX_INDEXTYPE) QOMX_IndexConfigVideoIntraperiod, 763 (OMX_PTR) &intra); 764 } 765 else 766 { 767 E("failed to get state", 0, 0, 0); 768 } 769 770 771 ///////////////////I N T R A P E R I O D /////////////////// 772 #endif 773 774 #if 1 775 ///////////////////E R R O R C O R R E C T I O N /////////////////// 776 777 ResyncMarkerType eResyncMarkerType = RESYNC_MARKER_NONE; 778 unsigned long int nResyncMarkerSpacing = 0; 779 OMX_BOOL enableHEC = OMX_FALSE; 780 781 //For Testing ONLY 782 if (m_sProfile.eCodec == OMX_VIDEO_CodingMPEG4) 783 { 784 // MPEG4 785 // eResyncMarkerType = RESYNC_MARKER_BYTE; 786 // nResyncMarkerSpacing = 1920; 787 eResyncMarkerType = RESYNC_MARKER_MB; 788 nResyncMarkerSpacing = 50; 789 enableHEC = OMX_TRUE; 790 } 791 else if (m_sProfile.eCodec == OMX_VIDEO_CodingH263) 792 { 793 //H263 794 eResyncMarkerType = RESYNC_MARKER_GOB; 795 nResyncMarkerSpacing = 0; 796 } 797 else if (m_sProfile.eCodec == OMX_VIDEO_CodingAVC) 798 { 799 //H264 800 // eResyncMarkerType = RESYNC_MARKER_BYTE; 801 // nResyncMarkerSpacing = 1920; 802 803 //nResyncMarkerSpacing sets the slice size in venc_set_multislice_cfg 804 // 805 //As of 9/24/10, it is known that the firmware has a bitstream 806 //corruption issue when RateControl and multislice are enabled for 720P 807 //So, disabling multislice for 720P when ratecontrol is enabled until 808 //the firmware issue is resolved. 809 810 if ( ( (m_sProfile.nFrameWidth == 1280) && (m_sProfile.nFrameHeight = 720) ) && 811 (m_sProfile.eControlRate != OMX_Video_ControlRateDisable) ) 812 { 813 eResyncMarkerType = RESYNC_MARKER_NONE; 814 nResyncMarkerSpacing = 0; 815 } 816 else 817 { 818 eResyncMarkerType = RESYNC_MARKER_MB; 819 nResyncMarkerSpacing = 50; 820 } 821 } 822 823 OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrection; //OMX_IndexParamVideoErrorCorrection 824 errorCorrection.nPortIndex = (OMX_U32) PORT_INDEX_OUT; // output 825 result = OMX_GetParameter(m_hHandle, 826 (OMX_INDEXTYPE) OMX_IndexParamVideoErrorCorrection, 827 (OMX_PTR) &errorCorrection); 828 829 errorCorrection.bEnableRVLC = OMX_FALSE; 830 errorCorrection.bEnableDataPartitioning = OMX_FALSE; 831 832 if ((eResyncMarkerType == RESYNC_MARKER_BYTE) && 833 (m_sProfile.eCodec == OMX_VIDEO_CodingMPEG4)){ 834 errorCorrection.bEnableResync = OMX_TRUE; 835 errorCorrection.nResynchMarkerSpacing = nResyncMarkerSpacing; 836 errorCorrection.bEnableHEC = enableHEC; 837 } 838 else if ((eResyncMarkerType == RESYNC_MARKER_BYTE) && 839 (m_sProfile.eCodec == OMX_VIDEO_CodingAVC)){ 840 errorCorrection.bEnableResync = OMX_TRUE; 841 errorCorrection.nResynchMarkerSpacing = nResyncMarkerSpacing; 842 } 843 else if ((eResyncMarkerType == RESYNC_MARKER_GOB) && 844 (m_sProfile.eCodec == OMX_VIDEO_CodingH263)){ 845 errorCorrection.bEnableResync = OMX_FALSE; 846 errorCorrection.nResynchMarkerSpacing = nResyncMarkerSpacing; 847 errorCorrection.bEnableDataPartitioning = OMX_TRUE; 848 } 849 850 result = OMX_SetParameter(m_hHandle, 851 (OMX_INDEXTYPE) OMX_IndexParamVideoErrorCorrection, 852 (OMX_PTR) &errorCorrection); 853 CHK(result); 854 855 if (eResyncMarkerType == RESYNC_MARKER_MB){ 856 if (m_sProfile.eCodec == OMX_VIDEO_CodingAVC){ 857 OMX_VIDEO_PARAM_AVCTYPE avcdata; 858 avcdata.nPortIndex = (OMX_U32) PORT_INDEX_OUT; // output 859 result = OMX_GetParameter(m_hHandle, 860 OMX_IndexParamVideoAvc, 861 (OMX_PTR) &avcdata); 862 CHK(result); 863 if (result == OMX_ErrorNone) 864 { 865 avcdata.nSliceHeaderSpacing = nResyncMarkerSpacing; 866 result = OMX_SetParameter(m_hHandle, 867 OMX_IndexParamVideoAvc, 868 (OMX_PTR) &avcdata); 869 CHK(result); 870 871 } 872 } 873 else if(m_sProfile.eCodec == OMX_VIDEO_CodingMPEG4){ 874 OMX_VIDEO_PARAM_MPEG4TYPE mp4; 875 mp4.nPortIndex = (OMX_U32) PORT_INDEX_OUT; // output 876 result = OMX_GetParameter(m_hHandle, 877 OMX_IndexParamVideoMpeg4, 878 (OMX_PTR) &mp4); 879 CHK(result); 880 881 if (result == OMX_ErrorNone) 882 { 883 mp4.nSliceHeaderSpacing = nResyncMarkerSpacing; 884 result = OMX_SetParameter(m_hHandle, 885 OMX_IndexParamVideoMpeg4, 886 (OMX_PTR) &mp4); 887 CHK(result); 888 } 889 } 890 } 891 892 ///////////////////E R R O R C O R R E C T I O N /////////////////// 893 #endif 894 895 #if 1 896 ///////////////////I N T R A R E F R E S H/////////////////// 897 bool bEnableIntraRefresh = OMX_TRUE; 898 899 if (result == OMX_ErrorNone) 900 { 901 OMX_VIDEO_PARAM_INTRAREFRESHTYPE ir; // OMX_IndexParamVideoIntraRefresh 902 ir.nPortIndex = (OMX_U32) PORT_INDEX_OUT; // output 903 result = OMX_GetParameter(m_hHandle, 904 OMX_IndexParamVideoIntraRefresh, 905 (OMX_PTR) &ir); 906 if (result == OMX_ErrorNone) 907 { 908 if (bEnableIntraRefresh) 909 { 910 ir.eRefreshMode = OMX_VIDEO_IntraRefreshCyclic; 911 ir.nCirMBs = 5; 912 result = OMX_SetParameter(m_hHandle, 913 OMX_IndexParamVideoIntraRefresh, 914 (OMX_PTR) &ir); 915 CHK(result); 916 } 917 } 918 } 919 #endif 920 #if 1 921 ///////////////////FRAMEPACKING DATA/////////////////// 922 OMX_QCOM_FRAME_PACK_ARRANGEMENT framePackingArrangement; 923 FILE *m_pConfigFile; 924 char m_configFilename [128] = "/data/configFile.cfg"; 925 memset(&framePackingArrangement, 0, sizeof(framePackingArrangement)); 926 m_pConfigFile = fopen(m_configFilename, "r"); 927 if (m_pConfigFile != NULL) 928 { 929 //read all frame packing data 930 framePackingArrangement.nPortIndex = (OMX_U32)PORT_INDEX_OUT; 931 int totalSizeToRead = FRAME_PACK_SIZE * sizeof(OMX_U32); 932 char *pFramePack = (char *) &(framePackingArrangement.id); 933 while ( ( (fscanf(m_pConfigFile, "%d", pFramePack)) != EOF ) && 934 (totalSizeToRead != 0) ) 935 { 936 //printf("Addr = %p, Value read = %d, sizeToRead remaining=%d\n", 937 // pFramePack, *pFramePack, totalSizeToRead); 938 pFramePack += sizeof(OMX_U32); 939 totalSizeToRead -= sizeof(OMX_U32); 940 } 941 //close the file. 942 fclose(m_pConfigFile); 943 944 printf("Frame Packing data from config file:\n"); 945 PrintFramePackArrangement(framePackingArrangement); 946 } 947 else 948 { 949 D("\n Config file does not exist or could not be opened."); 950 //set the default values 951 framePackingArrangement.nPortIndex = (OMX_U32)PORT_INDEX_OUT; 952 framePackingArrangement.id = 123; 953 framePackingArrangement.cancel_flag = false; 954 framePackingArrangement.type = 3; 955 framePackingArrangement.quincunx_sampling_flag = false; 956 framePackingArrangement.content_interpretation_type = 0; 957 framePackingArrangement.spatial_flipping_flag = true; 958 framePackingArrangement.frame0_flipped_flag = false; 959 framePackingArrangement.field_views_flag = false; 960 framePackingArrangement.current_frame_is_frame0_flag = false; 961 framePackingArrangement.frame0_self_contained_flag = true; 962 framePackingArrangement.frame1_self_contained_flag = false; 963 framePackingArrangement.frame0_grid_position_x = 3; 964 framePackingArrangement.frame0_grid_position_y = 15; 965 framePackingArrangement.frame1_grid_position_x = 11; 966 framePackingArrangement.frame1_grid_position_y = 7; 967 framePackingArrangement.reserved_byte = 0; 968 framePackingArrangement.repetition_period = 16381; 969 framePackingArrangement.extension_flag = false; 970 971 printf("Frame Packing Defaults :\n"); 972 PrintFramePackArrangement(framePackingArrangement); 973 } 974 result = OMX_SetConfig(m_hHandle, 975 (OMX_INDEXTYPE)OMX_QcomIndexConfigVideoFramePackingArrangement, 976 (OMX_PTR) &framePackingArrangement); 977 CHK(result); 978 979 //////////////////////OMX_VIDEO_PARAM_INTRAREFRESHTYPE/////////////////// 980 #endif 981 982 OMX_CONFIG_FRAMERATETYPE enc_framerate; // OMX_IndexConfigVideoFramerate 983 enc_framerate.nPortIndex = (OMX_U32)PORT_INDEX_OUT; 984 result = OMX_GetConfig(m_hHandle, 985 OMX_IndexConfigVideoFramerate, 986 &enc_framerate); 987 CHK(result); 988 FractionToQ16(enc_framerate.xEncodeFramerate,(int) (m_sProfile.nFramerate * 2),2); 989 result = OMX_SetConfig(m_hHandle, 990 OMX_IndexConfigVideoFramerate, 991 &enc_framerate); 992 CHK(result); 993 return OMX_ErrorNone; 994 } 995 //////////////////////////////////////////////////////////////////////////////// 996 void SendMessage(MsgId id, MsgData* data) 997 { 998 pthread_mutex_lock(&m_mutex); 999 if (m_sMsgQ.size >= MAX_MSG) 1000 { 1001 E("main msg m_sMsgQ is full"); 1002 return; 1003 } 1004 m_sMsgQ.q[(m_sMsgQ.head + m_sMsgQ.size) % MAX_MSG].id = id; 1005 if (data) 1006 m_sMsgQ.q[(m_sMsgQ.head + m_sMsgQ.size) % MAX_MSG].data = *data; 1007 ++m_sMsgQ.size; 1008 pthread_cond_signal(&m_signal); 1009 pthread_mutex_unlock(&m_mutex); 1010 } 1011 //////////////////////////////////////////////////////////////////////////////// 1012 void PopMessage(Msg* msg) 1013 { 1014 pthread_mutex_lock(&m_mutex); 1015 while (m_sMsgQ.size == 0) 1016 { 1017 pthread_cond_wait(&m_signal, &m_mutex); 1018 } 1019 *msg = m_sMsgQ.q[m_sMsgQ.head]; 1020 --m_sMsgQ.size; 1021 m_sMsgQ.head = (m_sMsgQ.head + 1) % MAX_MSG; 1022 pthread_mutex_unlock(&m_mutex); 1023 } 1024 //////////////////////////////////////////////////////////////////////////////// 1025 OMX_ERRORTYPE EVT_CB(OMX_IN OMX_HANDLETYPE hComponent, 1026 OMX_IN OMX_PTR pAppData, 1027 OMX_IN OMX_EVENTTYPE eEvent, 1028 OMX_IN OMX_U32 nData1, 1029 OMX_IN OMX_U32 nData2, 1030 OMX_IN OMX_PTR pEventData) 1031 { 1032 #define SET_STATE(eState) \ 1033 case eState: \ 1034 { \ 1035 D("" # eState " complete"); \ 1036 m_eState = eState; \ 1037 break; \ 1038 } 1039 1040 if (eEvent == OMX_EventCmdComplete) 1041 { 1042 if ((OMX_COMMANDTYPE) nData1 == OMX_CommandStateSet) 1043 { 1044 switch ((OMX_STATETYPE) nData2) 1045 { 1046 SET_STATE(OMX_StateLoaded); 1047 SET_STATE(OMX_StateIdle); 1048 SET_STATE(OMX_StateExecuting); 1049 SET_STATE(OMX_StateInvalid); 1050 SET_STATE(OMX_StateWaitForResources); 1051 SET_STATE(OMX_StatePause); 1052 default: 1053 E("invalid state %d", (int) nData2); 1054 } 1055 } 1056 } 1057 1058 else if (eEvent == OMX_EventError) 1059 { 1060 E("OMX_EventError"); 1061 } 1062 1063 else 1064 { 1065 E("unexpected event %d", (int) eEvent); 1066 } 1067 return OMX_ErrorNone; 1068 } 1069 //////////////////////////////////////////////////////////////////////////////// 1070 OMX_ERRORTYPE EBD_CB(OMX_IN OMX_HANDLETYPE hComponent, 1071 OMX_IN OMX_PTR pAppData, 1072 OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) 1073 { 1074 D("Got EBD callback ts=%lld", pBuffer->nTimeStamp); 1075 1076 for (int i = 0; i < num_in_buffers; i++) 1077 { 1078 // mark this buffer ready for use again 1079 if (m_pInBuffers[i] == pBuffer) 1080 { 1081 1082 D("Marked input buffer idx %d as free, buf %p", i, pBuffer->pBuffer); 1083 m_bInFrameFree[i] = OMX_TRUE; 1084 break; 1085 } 1086 } 1087 1088 if (m_eMode == MODE_LIVE_ENCODE) 1089 { 1090 CameraTest_ReleaseFrame(pBuffer->pBuffer, 1091 ((OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO*)pBuffer->pAppPrivate)); 1092 } 1093 else 1094 { 1095 // wake up main thread and tell it to send next frame 1096 MsgData data; 1097 data.sBitstreamData.pBuffer = pBuffer; 1098 SendMessage(MSG_ID_INPUT_FRAME_DONE, 1099 &data); 1100 1101 } 1102 return OMX_ErrorNone; 1103 } 1104 //////////////////////////////////////////////////////////////////////////////// 1105 OMX_ERRORTYPE FBD_CB(OMX_OUT OMX_HANDLETYPE hComponent, 1106 OMX_OUT OMX_PTR pAppData, 1107 OMX_OUT OMX_BUFFERHEADERTYPE* pBuffer) 1108 { 1109 D("Got FBD callback ts=%lld", pBuffer->nTimeStamp); 1110 1111 static long long prevTime = 0; 1112 long long currTime = GetTimeStamp(); 1113 1114 m_bWatchDogKicked = true; 1115 1116 /* Empty Buffers should not be counted */ 1117 if(pBuffer->nFilledLen !=0) 1118 { 1119 /* Counting Buffers supplied from OpneMax Encoder */ 1120 fbd_cnt++; 1121 tot_bufsize += pBuffer->nFilledLen; 1122 } 1123 if (prevTime != 0) 1124 { 1125 long long currTime = GetTimeStamp(); 1126 D("FBD_DELTA = %lld\n", currTime - prevTime); 1127 } 1128 prevTime = currTime; 1129 1130 if (m_eMode == MODE_PROFILE) 1131 { 1132 // if we are profiling we are not doing file I/O 1133 // so just give back to encoder 1134 if (OMX_FillThisBuffer(m_hHandle, pBuffer) != OMX_ErrorNone) 1135 { 1136 E("empty buffer failed for profiling"); 1137 } 1138 } 1139 else 1140 { 1141 // wake up main thread and tell it to write to file 1142 MsgData data; 1143 data.sBitstreamData.pBuffer = pBuffer; 1144 SendMessage(MSG_ID_OUTPUT_FRAME_DONE, 1145 &data); 1146 } 1147 return OMX_ErrorNone; 1148 } 1149 //////////////////////////////////////////////////////////////////////////////// 1150 OMX_ERRORTYPE VencTest_Initialize() 1151 { 1152 OMX_ERRORTYPE result = OMX_ErrorNone; 1153 static OMX_CALLBACKTYPE sCallbacks = {EVT_CB, EBD_CB, FBD_CB}; 1154 int i; 1155 1156 for (i = 0; i < num_in_buffers; i++) 1157 { 1158 m_pInBuffers[i] = NULL; 1159 } 1160 1161 result = OMX_Init(); 1162 CHK(result); 1163 1164 if (m_sProfile.eCodec == OMX_VIDEO_CodingMPEG4) 1165 { 1166 result = OMX_GetHandle(&m_hHandle, 1167 "OMX.qcom.video.encoder.mpeg4", 1168 NULL, 1169 &sCallbacks); 1170 // CHK(result); 1171 } 1172 else if (m_sProfile.eCodec == OMX_VIDEO_CodingH263) 1173 { 1174 result = OMX_GetHandle(&m_hHandle, 1175 "OMX.qcom.video.encoder.h263", 1176 NULL, 1177 &sCallbacks); 1178 CHK(result); 1179 } 1180 else 1181 { 1182 result = OMX_GetHandle(&m_hHandle, 1183 "OMX.qcom.video.encoder.avc", 1184 NULL, 1185 &sCallbacks); 1186 CHK(result); 1187 } 1188 1189 1190 result = ConfigureEncoder(); 1191 CHK(result); 1192 1193 return result; 1194 } 1195 1196 //////////////////////////////////////////////////////////////////////////////// 1197 OMX_ERRORTYPE VencTest_RegisterYUVBuffer(OMX_BUFFERHEADERTYPE** ppBufferHeader, 1198 OMX_U8 *pBuffer, 1199 OMX_PTR pAppPrivate) 1200 { 1201 OMX_ERRORTYPE result = OMX_ErrorNone; 1202 #if 0 1203 D("register buffer"); 1204 if ((result = OMX_AllocateBuffer(m_hHandle, 1205 ppBufferHeader, 1206 (OMX_U32) PORT_INDEX_IN, 1207 pAppPrivate, 1208 m_sProfile.nFrameBytes 1209 )) != OMX_ErrorNone) 1210 { 1211 E("use buffer failed"); 1212 } 1213 else 1214 { 1215 E("Allocate Buffer Success %x", (*ppBufferHeader)->pBuffer); 1216 } 1217 #endif 1218 D("register buffer"); 1219 D("Calling UseBuffer for Input port"); 1220 if ((result = OMX_UseBuffer(m_hHandle, 1221 ppBufferHeader, 1222 (OMX_U32) PORT_INDEX_IN, 1223 pAppPrivate, 1224 m_sProfile.nFrameBytes, 1225 pBuffer)) != OMX_ErrorNone) 1226 { 1227 E("use buffer failed"); 1228 } 1229 1230 return result; 1231 } 1232 //////////////////////////////////////////////////////////////////////////////// 1233 OMX_ERRORTYPE VencTest_EncodeFrame(void* pYUVBuff, 1234 long long nTimeStamp) 1235 { 1236 OMX_ERRORTYPE result = OMX_ErrorUndefined; 1237 D("calling OMX empty this buffer"); 1238 for (int i = 0; i < num_in_buffers; i++) 1239 { 1240 if (pYUVBuff == m_pInBuffers[i]->pBuffer) 1241 { 1242 m_pInBuffers[i]->nTimeStamp = nTimeStamp; 1243 D("Sending Buffer - %x", m_pInBuffers[i]->pBuffer); 1244 result = OMX_EmptyThisBuffer(m_hHandle, 1245 m_pInBuffers[i]); 1246 /* Counting Buffers supplied to OpenMax Encoder */ 1247 if(OMX_ErrorNone == result) 1248 ebd_cnt++; 1249 CHK(result); 1250 break; 1251 } 1252 } 1253 return result; 1254 } 1255 //////////////////////////////////////////////////////////////////////////////// 1256 OMX_ERRORTYPE VencTest_Exit(void) 1257 { 1258 int i; 1259 OMX_ERRORTYPE result = OMX_ErrorNone; 1260 D("trying to exit venc"); 1261 1262 D("going to idle state"); 1263 SetState(OMX_StateIdle); 1264 1265 1266 D("going to loaded state"); 1267 //SetState(OMX_StateLoaded); 1268 OMX_SendCommand(m_hHandle, 1269 OMX_CommandStateSet, 1270 (OMX_U32) OMX_StateLoaded, 1271 NULL); 1272 1273 for (i = 0; i < num_in_buffers; i++) 1274 { 1275 D("free buffer"); 1276 if (m_pInBuffers[i]->pBuffer) 1277 { 1278 // free(m_pInBuffers[i]->pBuffer); 1279 result = OMX_FreeBuffer(m_hHandle, 1280 PORT_INDEX_IN, 1281 m_pInBuffers[i]); 1282 CHK(result); 1283 } 1284 else 1285 { 1286 E("buffer %d is null", i); 1287 result = OMX_ErrorUndefined; 1288 CHK(result); 1289 } 1290 } 1291 for (i = 0; i < num_out_buffers; i++) 1292 { 1293 D("free buffer"); 1294 if (m_pOutBuffers[i]->pBuffer) 1295 { 1296 free(m_pOutBuffers[i]->pBuffer); 1297 result = OMX_FreeBuffer(m_hHandle, 1298 PORT_INDEX_OUT, 1299 m_pOutBuffers[i]); 1300 CHK(result); 1301 1302 } 1303 else 1304 { 1305 E("buffer %d is null", i); 1306 result = OMX_ErrorUndefined; 1307 CHK(result); 1308 } 1309 } 1310 1311 while (m_eState != OMX_StateLoaded) 1312 { 1313 sleep(1); 1314 } 1315 D("component_deinit..."); 1316 result = OMX_Deinit(); 1317 CHK(result); 1318 1319 D("venc is exiting..."); 1320 return result; 1321 } 1322 //////////////////////////////////////////////////////////////////////////////// 1323 1324 void VencTest_ReadDynamicConfigMsg() 1325 { 1326 char frame_n[8], config[16], param[8]; 1327 char *dest = frame_n; 1328 bool end = false; 1329 int cntr, nparam = 0; 1330 memset(&dynamic_config, 0, sizeof(struct DynamicConfig)); 1331 do 1332 { 1333 cntr = -1; 1334 do 1335 { 1336 dest[++cntr] = fgetc(m_pDynConfFile); 1337 } while(dest[cntr] != ' ' && dest[cntr] != '\t' && dest[cntr] != '\n' && dest[cntr] != '\r' && !feof(m_pDynConfFile)); 1338 if (dest[cntr] == '\n' || dest[cntr] == '\r') 1339 end = true; 1340 dest[cntr] = NULL; 1341 if (dest == frame_n) 1342 dest = config; 1343 else if (dest == config) 1344 dest = param; 1345 else 1346 end = true; 1347 nparam++; 1348 } while (!end && !feof(m_pDynConfFile)); 1349 1350 if (nparam > 1) 1351 { 1352 dynamic_config.pending = true; 1353 dynamic_config.frame_num = atoi(frame_n); 1354 if (!strcmp(config, "bitrate")) 1355 { 1356 dynamic_config.config_param = OMX_IndexConfigVideoBitrate; 1357 dynamic_config.config_data.bitrate.nPortIndex = PORT_INDEX_OUT; 1358 dynamic_config.config_data.bitrate.nEncodeBitrate = strtoul(param, NULL, 10); 1359 } 1360 else if (!strcmp(config, "framerate")) 1361 { 1362 dynamic_config.config_param = OMX_IndexConfigVideoFramerate; 1363 dynamic_config.config_data.framerate.nPortIndex = PORT_INDEX_OUT; 1364 dynamic_config.config_data.f_framerate = atof(param); 1365 } 1366 else if (!strcmp(config, "iperiod")) 1367 { 1368 dynamic_config.config_param = (OMX_INDEXTYPE)QOMX_IndexConfigVideoIntraperiod; 1369 dynamic_config.config_data.intraperiod.nPortIndex = PORT_INDEX_OUT; 1370 dynamic_config.config_data.intraperiod.nPFrames = strtoul(param, NULL, 10) - 1; 1371 dynamic_config.config_data.intraperiod.nIDRPeriod = 1; // This value is ignored in OMX component 1372 } 1373 else if (!strcmp(config, "ivoprefresh")) 1374 { 1375 dynamic_config.config_param = OMX_IndexConfigVideoIntraVOPRefresh; 1376 dynamic_config.config_data.intravoprefresh.nPortIndex = PORT_INDEX_OUT; 1377 dynamic_config.config_data.intravoprefresh.IntraRefreshVOP = OMX_TRUE; 1378 } 1379 else if (!strcmp(config, "rotation")) 1380 { 1381 dynamic_config.config_param = OMX_IndexConfigCommonRotate; 1382 dynamic_config.config_data.rotation.nPortIndex = PORT_INDEX_OUT; 1383 dynamic_config.config_data.rotation.nRotation = strtoul(param, NULL, 10); 1384 } 1385 else 1386 { 1387 E("UNKNOWN CONFIG PARAMETER: %s!", config); 1388 dynamic_config.pending = false; 1389 } 1390 } 1391 else if (feof(m_pDynConfFile)) 1392 { 1393 fclose(m_pDynConfFile); 1394 m_pDynConfFile = NULL; 1395 } 1396 } 1397 1398 void VencTest_ProcessDynamicConfigurationFile() 1399 { 1400 do 1401 { 1402 if (dynamic_config.pending) 1403 { 1404 if(m_nFrameIn == dynamic_config.frame_num) 1405 { 1406 if (dynamic_config.config_param == OMX_IndexConfigVideoFramerate) 1407 { 1408 m_sProfile.nFramerate = dynamic_config.config_data.f_framerate; 1409 FractionToQ16(dynamic_config.config_data.framerate.xEncodeFramerate, 1410 (int)(m_sProfile.nFramerate * 2), 2); 1411 } 1412 if (OMX_SetConfig(m_hHandle, dynamic_config.config_param, 1413 &dynamic_config.config_data) != OMX_ErrorNone) 1414 E("ERROR: Setting dynamic config to OMX param[0x%x]", dynamic_config.config_param); 1415 dynamic_config.pending = false; 1416 } 1417 else if (m_nFrameIn > dynamic_config.frame_num) 1418 { 1419 E("WARNING: Config change requested in passed frame(%d)", dynamic_config.frame_num); 1420 dynamic_config.pending = false; 1421 } 1422 } 1423 if (!dynamic_config.pending) 1424 VencTest_ReadDynamicConfigMsg(); 1425 } while (!dynamic_config.pending && m_pDynConfFile); 1426 } 1427 1428 //////////////////////////////////////////////////////////////////////////////// 1429 OMX_ERRORTYPE VencTest_ReadAndEmpty(OMX_BUFFERHEADERTYPE* pYUVBuffer) 1430 { 1431 OMX_ERRORTYPE result = OMX_ErrorNone; 1432 #ifdef T_ARM 1433 #ifdef MAX_RES_720P 1434 if (read(m_nInFd, 1435 pYUVBuffer->pBuffer, 1436 m_sProfile.nFrameBytes) != m_sProfile.nFrameBytes) 1437 { 1438 return OMX_ErrorUndefined; 1439 } 1440 #elif BADGER 1441 int bytes; 1442 E("will read YUV now: %d bytes to buffer %p\n", m_sProfile.nFrameRead, pYUVBuffer->pBuffer); 1443 E("W: %d H: %d Str: %d scal: %d \n", m_sProfile.nFrameWidth, m_sProfile.nFrameHeight, 1444 m_sProfile.nFramestride, m_sProfile.nFrameScanlines); 1445 bytes = read(m_nInFd, pYUVBuffer->pBuffer, m_sProfile.nFrameRead); 1446 if (bytes != m_sProfile.nFrameRead) { 1447 E("read failed: %d != %d\n", read, m_sProfile.nFrameRead); 1448 return OMX_ErrorUndefined; 1449 } 1450 E("\n\nRead %d bytes\n\n\n", m_sProfile.nFrameRead); 1451 #else 1452 OMX_U32 bytestoread = m_sProfile.nFrameWidth*m_sProfile.nFrameHeight; 1453 // read Y first 1454 if (read(m_nInFd, 1455 pYUVBuffer->pBuffer, 1456 bytestoread) != bytestoread) 1457 return OMX_ErrorUndefined; 1458 1459 // check alignment for offset to C 1460 OMX_U32 offset_to_c = m_sProfile.nFrameWidth * m_sProfile.nFrameHeight; 1461 1462 const OMX_U32 C_2K = (1024*2), 1463 MASK_2K = C_2K-1, 1464 IMASK_2K = ~MASK_2K; 1465 1466 if (offset_to_c & MASK_2K) 1467 { 1468 // offset to C is not 2k aligned, adjustment is required 1469 offset_to_c = (offset_to_c & IMASK_2K) + C_2K; 1470 } 1471 1472 bytestoread = m_sProfile.nFrameWidth*m_sProfile.nFrameHeight/2; 1473 // read C 1474 if (read(m_nInFd, 1475 pYUVBuffer->pBuffer + offset_to_c, 1476 bytestoread)!= bytestoread) 1477 return OMX_ErrorUndefined; 1478 #endif 1479 #else 1480 { 1481 char * pInputbuf = (char *)(pYUVBuffer->pBuffer) ; 1482 read(m_nInFd,pInputbuf,m_sProfile.nFrameBytes) ; 1483 1484 } 1485 #endif 1486 if (m_pDynConfFile) 1487 VencTest_ProcessDynamicConfigurationFile(); 1488 D("about to call VencTest_EncodeFrame..."); 1489 pthread_mutex_lock(&m_mutex); 1490 ++m_nFrameIn; 1491 #ifdef BADGER 1492 pYUVBuffer->nFilledLen = m_sProfile.nFrameRead; 1493 #else 1494 pYUVBuffer->nFilledLen = m_sProfile.nFrameBytes; 1495 #endif 1496 D("Called Buffer with Data filled length %d",pYUVBuffer->nFilledLen); 1497 1498 result = VencTest_EncodeFrame(pYUVBuffer->pBuffer, 1499 m_nTimeStamp); 1500 1501 m_nTimeStamp += (1000000) / m_sProfile.nFramerate; 1502 CHK(result); 1503 pthread_mutex_unlock(&m_mutex); 1504 return result; 1505 } 1506 //////////////////////////////////////////////////////////////////////////////// 1507 void PreviewCallback(int nFD, 1508 int nOffset, 1509 void* pPhys, 1510 void* pVirt, 1511 long long nTimeStamp) 1512 { 1513 1514 D("================= preview frame %d, phys=0x%x, nTimeStamp(millis)=%lld", 1515 m_nFrameIn+1, pPhys, (nTimeStamp / 1000)); 1516 1517 if (m_nFrameIn == m_nFramePlay && 1518 m_nFramePlay != 0) 1519 { 1520 // we will stop camera after last frame is encoded. 1521 // for now just ignore input frames 1522 1523 CameraTest_ReleaseFrame(pPhys, pVirt); 1524 return; 1525 } 1526 1527 // see if we should stop 1528 pthread_mutex_lock(&m_mutex); 1529 ++m_nFrameIn; 1530 pthread_mutex_unlock(&m_mutex); 1531 1532 1533 if (m_eMode == MODE_LIVE_ENCODE) 1534 { 1535 1536 OMX_ERRORTYPE result; 1537 1538 // register new camera buffers with encoder 1539 int i; 1540 for (i = 0; i < num_in_buffers; i++) 1541 { 1542 if (m_pInBuffers[i] != NULL && 1543 m_pInBuffers[i]->pBuffer == pPhys) 1544 { 1545 break; 1546 } 1547 else if (m_pInBuffers[i] == NULL) 1548 { 1549 D("registering buffer..."); 1550 result = VencTest_RegisterYUVBuffer(&m_pInBuffers[i], 1551 (OMX_U8*) pPhys, 1552 (OMX_PTR) pVirt); // store virt in app private field 1553 D("register done"); 1554 CHK(result); 1555 break; 1556 } 1557 } 1558 1559 if (i == num_in_buffers) 1560 { 1561 E("There are more camera buffers than we thought"); 1562 CHK(1); 1563 } 1564 1565 // encode the yuv frame 1566 1567 D("StartEncodeTime=%lld", GetTimeStamp()); 1568 result = VencTest_EncodeFrame(pPhys, 1569 nTimeStamp); 1570 CHK(result); 1571 // FBTest_DisplayImage(nFD, nOffset); 1572 } 1573 else 1574 { 1575 // FBTest_DisplayImage(nFD, nOffset); 1576 CameraTest_ReleaseFrame(pPhys, pVirt); 1577 } 1578 } 1579 //////////////////////////////////////////////////////////////////////////////// 1580 void usage(char* filename) 1581 { 1582 char* fname = strrchr(filename, (int) '/'); 1583 fname = (fname == NULL) ? filename : fname; 1584 1585 fprintf(stderr, "usage: %s LIVE <QCIF|QVGA> <MP4|H263> <FPS> <BITRATE> <NFRAMES> <OUTFILE>\n", fname); 1586 fprintf(stderr, "usage: %s FILE <QCIF|QVGA> <MP4|H263 <FPS> <BITRATE> <NFRAMES> <INFILE> <OUTFILE> ", fname); 1587 fprintf(stderr, "<Dynamic config file - opt> <Rate Control - opt> <AVC Slice Mode - opt>\n", fname); 1588 fprintf(stderr, "usage: %s PROFILE <QCIF|QVGA> <MP4|H263 <FPS> <BITRATE> <NFRAMES> <INFILE>\n", fname); 1589 fprintf(stderr, "usage: %s PREVIEW <QCIF|QVGA> <FPS> <NFRAMES>\n", fname); 1590 fprintf(stderr, "usage: %s DISPLAY <QCIF|QVGA> <FPS> <NFRAMES> <INFILE>\n", fname); 1591 fprintf(stderr, "\n BITRATE - bitrate in kbps\n"); 1592 fprintf(stderr, " FPS - frames per second\n"); 1593 fprintf(stderr, " NFRAMES - number of frames to play, 0 for infinite\n"); 1594 fprintf(stderr, " RateControl (Values 0 - 4 for RC_OFF, RC_CBR_CFR, RC_CBR_VFR, RC_VBR_CFR, RC_VBR_VFR\n"); 1595 exit(1); 1596 } 1597 1598 bool parseWxH(char *str, OMX_U32 *width, OMX_U32 *height) 1599 { 1600 bool parseOK = false; 1601 const char delimiters[] = " x*,"; 1602 char *token, *dupstr, *temp; 1603 OMX_U32 w, h; 1604 1605 dupstr = strdup(str); 1606 token = strtok_r(dupstr, delimiters, &temp); 1607 if (token) 1608 { 1609 w = strtoul(token, NULL, 10); 1610 token = strtok_r(NULL, delimiters, &temp); 1611 if (token) 1612 { 1613 h = strtoul(token, NULL, 10); 1614 if (w != ULONG_MAX && h != ULONG_MAX) 1615 { 1616 #ifdef MAX_RES_720P 1617 if ((w * h >> 8) <= 3600) 1618 { 1619 parseOK = true; 1620 *width = w; 1621 *height = h; 1622 } 1623 #else 1624 if ((w * h >> 8) <= 8160) 1625 { 1626 parseOK = true; 1627 *width = w; 1628 *height = h; 1629 } 1630 #endif 1631 else 1632 E("\nInvalid dimensions %dx%d",w,h); 1633 } 1634 } 1635 } 1636 free(dupstr); 1637 return parseOK; 1638 } 1639 1640 //////////////////////////////////////////////////////////////////////////////// 1641 void parseArgs(int argc, char** argv) 1642 { 1643 int dyn_file_arg = argc; 1644 if (argc == 1) 1645 { 1646 usage(argv[0]); 1647 } 1648 else if (strcmp("PREVIEW", argv[1]) == 0 || 1649 strcmp("preview", argv[1]) == 0) 1650 { 1651 m_eMode = MODE_PREVIEW; 1652 if (argc != 5) 1653 { 1654 usage(argv[0]); 1655 } 1656 } 1657 else if (strcmp("DISPLAY", argv[1]) == 0 || 1658 strcmp("display", argv[1]) == 0) 1659 { 1660 m_eMode = MODE_DISPLAY; 1661 if (argc != 6) 1662 { 1663 usage(argv[0]); 1664 } 1665 m_sProfile.cInFileName = argv[5]; 1666 m_sProfile.cOutFileName = NULL; 1667 } 1668 else if (strcmp("LIVE", argv[1]) == 0 || 1669 strcmp("live", argv[1]) == 0) 1670 {//263 1671 m_eMode = MODE_LIVE_ENCODE; 1672 if (argc != 8) 1673 { 1674 usage(argv[0]); 1675 } 1676 m_sProfile.cInFileName = NULL; 1677 m_sProfile.cOutFileName = argv[7]; 1678 } 1679 else if (strcmp("FILE", argv[1]) == 0 || 1680 strcmp("file", argv[1]) == 0) 1681 {//263 1682 m_eMode = MODE_FILE_ENCODE; 1683 1684 if(argc < 9 || argc > 13) 1685 { 1686 usage(argv[0]); 1687 } 1688 else 1689 { 1690 if (argc > 9) 1691 dyn_file_arg = 9; 1692 1693 if (argc > 10) 1694 { 1695 m_sProfile.eControlRate = OMX_Video_ControlRateVariable; 1696 int RC = atoi(argv[10]); 1697 1698 switch (RC) 1699 { 1700 case 0: 1701 m_sProfile.eControlRate = OMX_Video_ControlRateDisable ;//VENC_RC_NONE 1702 break; 1703 case 1: 1704 m_sProfile.eControlRate = OMX_Video_ControlRateConstant;//VENC_RC_CBR_CFR 1705 break; 1706 1707 case 2: 1708 m_sProfile.eControlRate = OMX_Video_ControlRateConstantSkipFrames;//VENC_RC_CBR_VFR 1709 break; 1710 1711 case 3: 1712 m_sProfile.eControlRate =OMX_Video_ControlRateVariable ;//VENC_RC_VBR_CFR 1713 break; 1714 1715 case 4: 1716 m_sProfile.eControlRate = OMX_Video_ControlRateVariableSkipFrames;//VENC_RC_VBR_VFR 1717 break; 1718 1719 default: 1720 E("invalid rate control selection"); 1721 m_sProfile.eControlRate = OMX_Video_ControlRateVariable; //VENC_RC_VBR_CFR 1722 break; 1723 } 1724 } 1725 1726 if (argc > 11) 1727 { 1728 int profile_argi = 11; 1729 if(!strcmp(argv[3], "H264") || !strcmp(argv[3], "h264")) 1730 { 1731 profile_argi = 12; 1732 D("\nSetting AVCSliceMode ... "); 1733 int AVCSliceMode = atoi(argv[11]); 1734 switch(AVCSliceMode) 1735 { 1736 case 0: 1737 m_sProfile.eSliceMode = OMX_VIDEO_SLICEMODE_AVCDefault; 1738 break; 1739 1740 case 1: 1741 m_sProfile.eSliceMode = OMX_VIDEO_SLICEMODE_AVCMBSlice; 1742 break; 1743 1744 case 2: 1745 m_sProfile.eSliceMode = OMX_VIDEO_SLICEMODE_AVCByteSlice; 1746 break; 1747 1748 default: 1749 E("invalid Slice Mode"); 1750 m_sProfile.eSliceMode = OMX_VIDEO_SLICEMODE_AVCDefault; 1751 break; 1752 } 1753 } 1754 if (profile_argi < argc) 1755 { 1756 if (!strncmp(argv[profile_argi], "0x", 2) || !strncmp(argv[profile_argi], "0x", 2)) 1757 { 1758 m_sProfile.nUserProfile = strtoul(argv[profile_argi], NULL, 16); 1759 } 1760 else 1761 { 1762 m_sProfile.nUserProfile = strtoul(argv[profile_argi], NULL, 10); 1763 } 1764 if (!m_sProfile.nUserProfile || m_sProfile.nUserProfile == ULONG_MAX) 1765 { 1766 E("invalid specified Profile %s, using default", argv[profile_argi]); 1767 m_sProfile.nUserProfile = 0; 1768 } 1769 } 1770 } 1771 } 1772 m_sProfile.cInFileName = argv[7]; 1773 m_sProfile.cOutFileName = argv[8]; 1774 } 1775 else if (strcmp("PROFILE", argv[1]) == 0 || 1776 strcmp("profile", argv[1]) == 0) 1777 {//263 1778 m_eMode = MODE_PROFILE; 1779 if (argc != 8) 1780 { 1781 usage(argv[0]); 1782 } 1783 m_sProfile.cInFileName = argv[7]; 1784 m_sProfile.cOutFileName = NULL; 1785 } 1786 else 1787 { 1788 usage(argv[0]); 1789 } 1790 1791 1792 if (strcmp("QCIF", argv[2]) == 0 || 1793 strcmp("qcif", argv[2]) == 0) 1794 { 1795 m_sProfile.nFrameWidth = 176; 1796 m_sProfile.nFrameHeight = 144; 1797 m_sProfile.nFrameBytes = 176*144*3/2; 1798 m_sProfile.eLevel = OMX_VIDEO_MPEG4Level0; 1799 } 1800 else if (strcmp("QVGA", argv[2]) == 0 || 1801 strcmp("qvga", argv[2]) == 0) 1802 { 1803 m_sProfile.nFrameWidth = 320; 1804 m_sProfile.nFrameHeight = 240; 1805 m_sProfile.nFrameBytes = 320*240*3/2; 1806 m_sProfile.eLevel = OMX_VIDEO_MPEG4Level1; 1807 } 1808 1809 1810 else if (strcmp("VGA", argv[2]) == 0 || 1811 strcmp("vga", argv[2]) == 0) 1812 { 1813 m_sProfile.nFrameWidth = 640; 1814 m_sProfile.nFrameHeight = 480; 1815 m_sProfile.nFrameBytes = 640*480*3/2; 1816 m_sProfile.eLevel = OMX_VIDEO_MPEG4Level1; 1817 } 1818 1819 else if (strcmp("WVGA", argv[2]) == 0 || 1820 strcmp("wvga", argv[2]) == 0) 1821 { 1822 m_sProfile.nFrameWidth = 800; 1823 m_sProfile.nFrameHeight = 480; 1824 m_sProfile.nFrameBytes = 800*480*3/2; 1825 m_sProfile.eLevel = OMX_VIDEO_MPEG4Level1; 1826 } 1827 else if (strcmp("CIF", argv[2]) == 0 || 1828 strcmp("cif", argv[2]) == 0) 1829 { 1830 m_sProfile.nFrameWidth = 352; 1831 m_sProfile.nFrameHeight = 288; 1832 m_sProfile.nFrameBytes = 352*288*3/2; 1833 m_sProfile.eLevel = OMX_VIDEO_MPEG4Level1; 1834 } 1835 else if (strcmp("720", argv[2]) == 0) 1836 { 1837 m_sProfile.nFrameWidth = 1280; 1838 m_sProfile.nFrameHeight = 720; 1839 m_sProfile.nFrameBytes = 720*1280*3/2; 1840 m_sProfile.eLevel = OMX_VIDEO_MPEG4Level1; 1841 } 1842 else if (strcmp("1080", argv[2]) == 0) 1843 { 1844 m_sProfile.nFrameWidth = 1920; 1845 m_sProfile.nFrameHeight = 1080; 1846 m_sProfile.nFrameBytes = 1920*1080*3/2; 1847 m_sProfile.eLevel = OMX_VIDEO_MPEG4Level1; 1848 } 1849 else if (parseWxH(argv[2], &m_sProfile.nFrameWidth, &m_sProfile.nFrameHeight)) 1850 { 1851 m_sProfile.nFrameBytes = m_sProfile.nFrameWidth*m_sProfile.nFrameHeight*3/2; 1852 m_sProfile.eLevel = OMX_VIDEO_MPEG4Level1; 1853 } 1854 else 1855 { 1856 usage(argv[0]); 1857 } 1858 1859 #ifdef BADGER 1860 m_sProfile.nFramestride = (m_sProfile.nFrameWidth + 31) & (~31); 1861 m_sProfile.nFrameScanlines = (m_sProfile.nFrameHeight + 31) & (~31); 1862 m_sProfile.nFrameBytes = ((m_sProfile.nFramestride * m_sProfile.nFrameScanlines * 3/2) + 4095) & (~4095); 1863 E("stride: %d, Scanlines: %d, Size: %d", 1864 m_sProfile.nFramestride, m_sProfile.nFrameScanlines, m_sProfile.nFrameBytes); 1865 m_sProfile.nFrameRead = m_sProfile.nFramestride * m_sProfile.nFrameScanlines * 3/2; 1866 #endif 1867 if (m_eMode == MODE_DISPLAY || 1868 m_eMode == MODE_PREVIEW) 1869 { 1870 m_sProfile.nFramerate = atof(argv[3]); 1871 m_nFramePlay = atoi(argv[4]); 1872 1873 } 1874 else if (m_eMode == MODE_LIVE_ENCODE || 1875 m_eMode == MODE_FILE_ENCODE || 1876 m_eMode == MODE_PROFILE) 1877 { 1878 if ((!strcmp(argv[3], "MP4")) || (!strcmp(argv[3], "mp4"))) 1879 { 1880 m_sProfile.eCodec = OMX_VIDEO_CodingMPEG4; 1881 } 1882 else if ((!strcmp(argv[3], "H263")) || (!strcmp(argv[3], "h263"))) 1883 { 1884 m_sProfile.eCodec = OMX_VIDEO_CodingH263; 1885 } 1886 else if ((!strcmp(argv[3], "H264")) || (!strcmp(argv[3], "h264"))) 1887 { 1888 m_sProfile.eCodec = OMX_VIDEO_CodingAVC; 1889 } 1890 else 1891 { 1892 usage(argv[0]); 1893 } 1894 1895 m_sProfile.nFramerate = atof(argv[4]); 1896 m_sProfile.nBitrate = atoi(argv[5]); 1897 // m_sProfile.eControlRate = OMX_Video_ControlRateVariable; 1898 m_nFramePlay = atoi(argv[6]); 1899 if (dyn_file_arg < argc) 1900 { 1901 m_pDynConfFile = fopen(argv[dyn_file_arg], "r"); 1902 if (!m_pDynConfFile) 1903 E("ERROR: Cannot open dynamic config file: %s", argv[dyn_file_arg]); 1904 else 1905 { 1906 memset(&dynamic_config, 0, sizeof(struct DynamicConfig)); 1907 } 1908 } 1909 } 1910 } 1911 1912 void* Watchdog(void* data) 1913 { 1914 while (1) 1915 { 1916 sleep(1000); 1917 if (m_bWatchDogKicked == true) 1918 m_bWatchDogKicked = false; 1919 else 1920 E("watchdog has not been kicked. we may have a deadlock"); 1921 } 1922 return NULL; 1923 } 1924 1925 int main(int argc, char** argv) 1926 { 1927 OMX_U8* pvirt = NULL; 1928 int result; 1929 float enc_time_sec=0.0,enc_time_usec=0.0; 1930 1931 m_nInFd = -1; 1932 m_nOutFd = -1; 1933 m_nTimeStamp = 0; 1934 m_nFrameIn = 0; 1935 m_nFrameOut = 0; 1936 1937 memset(&m_sMsgQ, 0, sizeof(MsgQ)); 1938 parseArgs(argc, argv); 1939 1940 D("fps=%d, bitrate=%d, width=%d, height=%d", 1941 m_sProfile.nFramerate, 1942 m_sProfile.nBitrate, 1943 m_sProfile.nFrameWidth, 1944 m_sProfile.nFrameHeight); 1945 1946 1947 //if (m_eMode != MODE_PREVIEW && m_eMode != MODE_DISPLAY) 1948 //{ 1949 // pthread_t wd; 1950 // pthread_create(&wd, NULL, Watchdog, NULL); 1951 //} 1952 1953 for (int x = 0; x < num_in_buffers; x++) 1954 { 1955 // mark all buffers as ready to use 1956 m_bInFrameFree[x] = OMX_TRUE; 1957 } 1958 1959 1960 if (m_eMode != MODE_PROFILE) 1961 { 1962 #if T_ARM 1963 m_nOutFd = open(m_sProfile.cOutFileName, O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU | S_IRWXG | S_IRWXO); 1964 #else 1965 m_nOutFd = open(m_sProfile.cOutFileName,0); 1966 #endif 1967 if (m_nOutFd < 0) 1968 { 1969 E("could not open output file %s", m_sProfile.cOutFileName); 1970 CHK(1); 1971 } 1972 } 1973 1974 pthread_mutex_init(&m_mutex, NULL); 1975 pthread_cond_init(&m_signal, NULL); 1976 1977 if (m_eMode != MODE_PREVIEW) 1978 { 1979 VencTest_Initialize(); 1980 } 1981 1982 //////////////////////////////////////// 1983 // Camera + Encode 1984 //////////////////////////////////////// 1985 if (m_eMode == MODE_LIVE_ENCODE) 1986 { 1987 CameraTest_Initialize(m_sProfile.nFramerate, 1988 m_sProfile.nFrameWidth, 1989 m_sProfile.nFrameHeight, 1990 PreviewCallback); 1991 CameraTest_Run(); 1992 } 1993 1994 if (m_eMode == MODE_FILE_ENCODE || 1995 m_eMode == MODE_PROFILE) 1996 { 1997 int i; 1998 #if T_ARM 1999 m_nInFd = open(m_sProfile.cInFileName, O_RDONLY); 2000 #else 2001 m_nInFd = open(m_sProfile.cInFileName,1); 2002 #endif 2003 if (m_nInFd < 0) 2004 { 2005 E("could not open input file"); 2006 CHK(1); 2007 2008 } 2009 D("going to idle state"); 2010 //SetState(OMX_StateIdle); 2011 OMX_SendCommand(m_hHandle, 2012 OMX_CommandStateSet, 2013 (OMX_U32) OMX_StateIdle, 2014 NULL); 2015 2016 OMX_PARAM_PORTDEFINITIONTYPE portDef; 2017 2018 portDef.nPortIndex = 0; 2019 result = OMX_GetParameter(m_hHandle, OMX_IndexParamPortDefinition, &portDef); 2020 CHK(result); 2021 2022 D("allocating Input buffers"); 2023 num_in_buffers = portDef.nBufferCountActual; 2024 for (i = 0; i < portDef.nBufferCountActual; i++) 2025 { 2026 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO* pMem = new OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO; 2027 pvirt = (OMX_U8*)PmemMalloc(pMem, m_sProfile.nFrameBytes); 2028 2029 if(pvirt == NULL) 2030 { 2031 CHK(1); 2032 } 2033 result = VencTest_RegisterYUVBuffer(&m_pInBuffers[i], 2034 (OMX_U8*) pvirt, 2035 (OMX_PTR) pMem); 2036 CHK(result); 2037 } 2038 } 2039 else if (m_eMode == MODE_LIVE_ENCODE) 2040 { 2041 D("going to idle state"); 2042 //SetState(OMX_StateIdle); 2043 OMX_SendCommand(m_hHandle, 2044 OMX_CommandStateSet, 2045 (OMX_U32) OMX_StateIdle, 2046 NULL); 2047 } 2048 2049 int i; 2050 OMX_PARAM_PORTDEFINITIONTYPE portDef; 2051 2052 portDef.nPortIndex = 1; 2053 result = OMX_GetParameter(m_hHandle, OMX_IndexParamPortDefinition, &portDef); 2054 CHK(result); 2055 2056 D("allocating output buffers"); 2057 D("Calling UseBuffer for Output port"); 2058 num_out_buffers = portDef.nBufferCountActual; 2059 for (i = 0; i < portDef.nBufferCountActual; i++) 2060 { 2061 void* pBuff; 2062 2063 pBuff = malloc(portDef.nBufferSize); 2064 D("portDef.nBufferSize = %d ",portDef.nBufferSize); 2065 result = OMX_UseBuffer(m_hHandle, 2066 &m_pOutBuffers[i], 2067 (OMX_U32) PORT_INDEX_OUT, 2068 NULL, 2069 portDef.nBufferSize, 2070 (OMX_U8*) pBuff); 2071 CHK(result); 2072 } 2073 D("allocate done"); 2074 2075 // D("Going to state " # eState"..."); 2076 2077 while (m_eState != OMX_StateIdle) 2078 { 2079 sleep(1); 2080 } 2081 //D("Now in state " # eState); 2082 2083 2084 D("going to executing state"); 2085 SetState(OMX_StateExecuting); 2086 for (i = 0; i < num_out_buffers; i++) 2087 { 2088 D("filling buffer %d", i); 2089 result = OMX_FillThisBuffer(m_hHandle, m_pOutBuffers[i]); 2090 //sleep(1000); 2091 CHK(result); 2092 } 2093 2094 if (m_eMode == MODE_FILE_ENCODE) 2095 { 2096 // encode the first frame to kick off the whole process 2097 VencTest_ReadAndEmpty(m_pInBuffers[0]); 2098 // FBTest_DisplayImage(((PmemBuffer*) m_pInBuffers[0]->pAppPrivate)->fd,0); 2099 } 2100 2101 if (m_eMode == MODE_PROFILE) 2102 { 2103 int i; 2104 2105 // read several frames into memory 2106 D("reading frames into memory"); 2107 for (i = 0; i < num_in_buffers; i++) 2108 { 2109 D("[%d] address 0x%x",i, m_pInBuffers[i]->pBuffer); 2110 #ifdef MAX_RES_720P 2111 read(m_nInFd, 2112 m_pInBuffers[i]->pBuffer, 2113 m_sProfile.nFrameBytes); 2114 #else 2115 // read Y first 2116 read(m_nInFd, 2117 m_pInBuffers[i]->pBuffer, 2118 m_sProfile.nFrameWidth*m_sProfile.nFrameHeight); 2119 2120 // check alignment for offset to C 2121 OMX_U32 offset_to_c = m_sProfile.nFrameWidth * m_sProfile.nFrameHeight; 2122 2123 const OMX_U32 C_2K = (1024*2), 2124 MASK_2K = C_2K-1, 2125 IMASK_2K = ~MASK_2K; 2126 2127 if (offset_to_c & MASK_2K) 2128 { 2129 // offset to C is not 2k aligned, adjustment is required 2130 offset_to_c = (offset_to_c & IMASK_2K) + C_2K; 2131 } 2132 2133 // read C 2134 read(m_nInFd, 2135 m_pInBuffers[i]->pBuffer + offset_to_c, 2136 m_sProfile.nFrameWidth*m_sProfile.nFrameHeight/2); 2137 #endif 2138 2139 } 2140 2141 // FBTest_Initialize(m_sProfile.nFrameWidth, m_sProfile.nFrameHeight); 2142 2143 // loop over the mem-resident frames and encode them 2144 D("beging playing mem-resident frames..."); 2145 for (i = 0; m_nFramePlay == 0 || i < m_nFramePlay; i++) 2146 { 2147 int idx = i % num_in_buffers; 2148 if (m_bInFrameFree[idx] == OMX_FALSE) 2149 { 2150 int j; 2151 E("the expected buffer is not free, but lets find another"); 2152 2153 idx = -1; 2154 2155 // lets see if we can find another free buffer 2156 for (j = 0; j < num_in_buffers; j++) 2157 { 2158 if(m_bInFrameFree[j]) 2159 { 2160 idx = j; 2161 break; 2162 } 2163 } 2164 } 2165 2166 // if we have a free buffer let's encode it 2167 if (idx >= 0) 2168 { 2169 D("encode frame %d...m_pInBuffers[idx]->pBuffer=0x%x", i,m_pInBuffers[idx]->pBuffer); 2170 m_bInFrameFree[idx] = OMX_FALSE; 2171 VencTest_EncodeFrame(m_pInBuffers[idx]->pBuffer, 2172 m_nTimeStamp); 2173 D("display frame %d...", i); 2174 // FBTest_DisplayImage(((PmemBuffer*) m_pInBuffers[idx]->pAppPrivate)->fd,0); 2175 m_nTimeStamp += 1000000 / m_sProfile.nFramerate; 2176 } 2177 else 2178 { 2179 E("wow, no buffers are free, performance " 2180 "is not so good. lets just sleep some more"); 2181 2182 } 2183 D("sleep for %d microsec", 1000000/m_sProfile.nFramerate); 2184 sleep (1000000 / m_sProfile.nFramerate); 2185 } 2186 // FBTest_Exit(); 2187 } 2188 2189 Msg msg; 2190 bool bQuit = false; 2191 while ((m_eMode == MODE_FILE_ENCODE || m_eMode == MODE_LIVE_ENCODE) && 2192 !bQuit) 2193 { 2194 PopMessage(&msg); 2195 switch (msg.id) 2196 { 2197 ////////////////////////////////// 2198 // FRAME IS ENCODED 2199 ////////////////////////////////// 2200 case MSG_ID_INPUT_FRAME_DONE: 2201 /*pthread_mutex_lock(&m_mutex); 2202 ++m_nFrameOut; 2203 if (m_nFrameOut == m_nFramePlay && m_nFramePlay != 0) 2204 { 2205 bQuit = true; 2206 } 2207 pthread_mutex_unlock(&m_mutex);*/ 2208 2209 if (!bQuit && m_eMode == MODE_FILE_ENCODE) 2210 { 2211 D("pushing another frame down to encoder"); 2212 if (VencTest_ReadAndEmpty(msg.data.sBitstreamData.pBuffer)) 2213 { 2214 // we have read the last frame 2215 D("main is exiting..."); 2216 bQuit = true; 2217 } 2218 } 2219 break; 2220 case MSG_ID_OUTPUT_FRAME_DONE: 2221 D("================ writing frame %d = %d bytes to output file", 2222 m_nFrameOut+1, 2223 msg.data.sBitstreamData.pBuffer->nFilledLen); 2224 D("StopEncodeTime=%lld", GetTimeStamp()); 2225 2226 2227 write(m_nOutFd, 2228 msg.data.sBitstreamData.pBuffer->pBuffer, 2229 msg.data.sBitstreamData.pBuffer->nFilledLen); 2230 2231 2232 result = OMX_FillThisBuffer(m_hHandle, 2233 msg.data.sBitstreamData.pBuffer); 2234 2235 if (result != OMX_ErrorNone) 2236 { 2237 CHK(result); 2238 } 2239 2240 pthread_mutex_lock(&m_mutex); 2241 ++m_nFrameOut; 2242 if (m_nFrameOut == m_nFramePlay && m_nFramePlay != 0) 2243 { 2244 bQuit = true; 2245 } 2246 pthread_mutex_unlock(&m_mutex); 2247 break; 2248 2249 default: 2250 E("invalid msg id %d", (int) msg.id); 2251 } // end switch (msg.id) 2252 2253 /* // TO UNCOMMENT FOR PAUSE TESTINGS 2254 if(m_nFrameOut == 10) 2255 { 2256 E("\nGoing to Pause state\n"); 2257 SetState(OMX_StatePause); 2258 sleep(3); 2259 //REQUEST AN I FRAME AFTER PAUSE 2260 OMX_CONFIG_INTRAREFRESHVOPTYPE voprefresh; 2261 voprefresh.nPortIndex = (OMX_U32)PORT_INDEX_OUT; 2262 voprefresh.IntraRefreshVOP = OMX_TRUE; 2263 result = OMX_SetConfig(m_hHandle, 2264 OMX_IndexConfigVideoIntraVOPRefresh, 2265 &voprefresh); 2266 E("\n OMX_IndexConfigVideoIntraVOPRefresh Set Paramter port"); 2267 CHK(result); 2268 E("\nGoing to executing state\n"); 2269 SetState(OMX_StateExecuting); 2270 } 2271 */ 2272 } // end while (!bQuit) 2273 2274 2275 if (m_eMode == MODE_LIVE_ENCODE) 2276 { 2277 CameraTest_Exit(); 2278 close(m_nOutFd); 2279 } 2280 else if (m_eMode == MODE_FILE_ENCODE || 2281 m_eMode == MODE_PROFILE) 2282 { 2283 // deallocate pmem buffers 2284 for (int i = 0; i < num_in_buffers; i++) 2285 { 2286 PmemFree((OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO*)m_pInBuffers[i]->pAppPrivate, 2287 m_pInBuffers[i]->pBuffer, 2288 m_sProfile.nFrameBytes); 2289 delete (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO*) m_pInBuffers[i]->pAppPrivate; 2290 } 2291 close(m_nInFd); 2292 2293 if (m_eMode == MODE_FILE_ENCODE) 2294 { 2295 close(m_nOutFd); 2296 } 2297 if (m_pDynConfFile) 2298 { 2299 fclose(m_pDynConfFile); 2300 m_pDynConfFile = NULL; 2301 } 2302 } 2303 2304 if (m_eMode != MODE_PREVIEW) 2305 { 2306 D("exit encoder test"); 2307 VencTest_Exit(); 2308 } 2309 2310 pthread_mutex_destroy(&m_mutex); 2311 pthread_cond_destroy(&m_signal); 2312 2313 /* Time Statistics Logging */ 2314 if(0 != m_sProfile.nFramerate) 2315 { 2316 enc_time_usec = m_nTimeStamp - (1000000 / m_sProfile.nFramerate); 2317 enc_time_sec =enc_time_usec/1000000; 2318 if(0 != enc_time_sec) 2319 { 2320 printf("Total Frame Rate: %f",ebd_cnt/enc_time_sec); 2321 printf("\nEncoder Bitrate :%lf Kbps",(tot_bufsize*8)/(enc_time_sec*1000)); 2322 } 2323 } 2324 else 2325 { 2326 printf("\n\n Encode Time is zero"); 2327 } 2328 printf("\nTotal Number of Frames :%d",ebd_cnt); 2329 printf("\nNumber of dropped frames during encoding:%d\n",ebd_cnt-fbd_cnt); 2330 /* End of Time Statistics Logging */ 2331 2332 D("main has exited"); 2333 return 0; 2334 } 2335