1 /*-------------------------------------------------------------------------- 2 Copyright (c) 2010, 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 <string.h> 56 //#include <sys/stat.h> 57 #include "OMX_QCOMExtns.h" 58 #include "OMX_Core.h" 59 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 70 ////////////////////////// 71 // MACROS 72 ////////////////////////// 73 74 #define CHK(result) if (result != OMX_ErrorNone) { E("*************** error *************"); exit(0); } 75 #define TEST_LOG 76 #ifdef VENC_SYSLOG 77 #include "cutils/log.h" 78 /// Debug message macro 79 #define D(fmt, ...) ALOGE("venc_test Debug %s::%d "fmt"\n", \ 80 __FUNCTION__, __LINE__, \ 81 ## __VA_ARGS__) 82 83 /// Error message macro 84 #define E(fmt, ...) ALOGE("venc_test Error %s::%d "fmt"\n", \ 85 __FUNCTION__, __LINE__, \ 86 ## __VA_ARGS__) 87 88 #else 89 #ifdef TEST_LOG 90 #define D(fmt, ...) fprintf(stderr, "venc_test Debug %s::%d "fmt"\n", \ 91 __FUNCTION__, __LINE__, \ 92 ## __VA_ARGS__) 93 94 /// Error message macro 95 #define E(fmt, ...) fprintf(stderr, "venc_test Error %s::%d "fmt"\n", \ 96 __FUNCTION__, __LINE__, \ 97 ## __VA_ARGS__) 98 #else 99 #define D(fmt, ...) 100 #define E(fmt, ...) 101 #endif 102 103 #endif 104 105 ////////////////////////// 106 // CONSTANTS 107 ////////////////////////// 108 static const int MAX_MSG = 100; 109 //#warning do not hardcode these use port definition 110 static const int PORT_INDEX_IN = 0; 111 static const int PORT_INDEX_OUT = 1; 112 113 static const int NUM_IN_BUFFERS = 10; 114 static const int NUM_OUT_BUFFERS = 10; 115 116 unsigned int num_in_buffers = 0; 117 unsigned int num_out_buffers = 0; 118 119 ////////////////////////// 120 /* MPEG4 profile and level table*/ 121 static const unsigned int mpeg4_profile_level_table[][5]= 122 { 123 /*max mb per frame, max mb per sec, max bitrate, level, profile*/ 124 {99,1485,64000,OMX_VIDEO_MPEG4Level0,OMX_VIDEO_MPEG4ProfileSimple}, 125 {99,1485,128000,OMX_VIDEO_MPEG4Level1,OMX_VIDEO_MPEG4ProfileSimple}, 126 {396,5940,128000,OMX_VIDEO_MPEG4Level2,OMX_VIDEO_MPEG4ProfileSimple}, 127 {396,11880,384000,OMX_VIDEO_MPEG4Level3,OMX_VIDEO_MPEG4ProfileSimple}, 128 {1200,36000,4000000,OMX_VIDEO_MPEG4Level4a,OMX_VIDEO_MPEG4ProfileSimple}, 129 {1620,40500,8000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileSimple}, 130 {3600,108000,14000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileSimple}, 131 132 {99,2970,128000,OMX_VIDEO_MPEG4Level0,OMX_VIDEO_MPEG4ProfileAdvancedSimple}, 133 {99,2970,128000,OMX_VIDEO_MPEG4Level1,OMX_VIDEO_MPEG4ProfileAdvancedSimple}, 134 {396,5940,384000,OMX_VIDEO_MPEG4Level2,OMX_VIDEO_MPEG4ProfileAdvancedSimple}, 135 {396,11880,768000,OMX_VIDEO_MPEG4Level3,OMX_VIDEO_MPEG4ProfileAdvancedSimple}, 136 {792,23760,3000000,OMX_VIDEO_MPEG4Level4,OMX_VIDEO_MPEG4ProfileAdvancedSimple}, 137 {1620,48600,8000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileAdvancedSimple}, 138 {3600,108000,14000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileAdvancedSimple}, 139 {0 ,0 ,0 ,0 ,0 } 140 }; 141 142 /* H264 profile and level table*/ 143 static const unsigned int h264_profile_level_table[][5]= 144 { 145 /*max mb per frame, max mb per sec, max bitrate, level, profile*/ 146 {99,1485,64000,OMX_VIDEO_AVCLevel1,OMX_VIDEO_AVCProfileBaseline}, 147 {99,1485,128000,OMX_VIDEO_AVCLevel1b,OMX_VIDEO_AVCProfileBaseline}, 148 {396,3000,192000,OMX_VIDEO_AVCLevel11,OMX_VIDEO_AVCProfileBaseline}, 149 {396,6000,384000,OMX_VIDEO_AVCLevel12,OMX_VIDEO_AVCProfileBaseline}, 150 {396,11880,768000,OMX_VIDEO_AVCLevel13,OMX_VIDEO_AVCProfileBaseline}, 151 {396,11880,2000000,OMX_VIDEO_AVCLevel2,OMX_VIDEO_AVCProfileBaseline}, 152 {792,19800,4000000,OMX_VIDEO_AVCLevel21,OMX_VIDEO_AVCProfileBaseline}, 153 {1620,20250,4000000,OMX_VIDEO_AVCLevel22,OMX_VIDEO_AVCProfileBaseline}, 154 {1620,40500,10000000,OMX_VIDEO_AVCLevel3,OMX_VIDEO_AVCProfileBaseline}, 155 {3600,108000,14000000,OMX_VIDEO_AVCLevel31,OMX_VIDEO_AVCProfileBaseline}, 156 157 {99,1485,64000,OMX_VIDEO_AVCLevel1,OMX_VIDEO_AVCProfileHigh}, 158 {99,1485,160000,OMX_VIDEO_AVCLevel1b,OMX_VIDEO_AVCProfileHigh}, 159 {396,3000,240000,OMX_VIDEO_AVCLevel11,OMX_VIDEO_AVCProfileHigh}, 160 {396,6000,480000,OMX_VIDEO_AVCLevel12,OMX_VIDEO_AVCProfileHigh}, 161 {396,11880,960000,OMX_VIDEO_AVCLevel13,OMX_VIDEO_AVCProfileHigh}, 162 {396,11880,2500000,OMX_VIDEO_AVCLevel2,OMX_VIDEO_AVCProfileHigh}, 163 {792,19800,5000000,OMX_VIDEO_AVCLevel21,OMX_VIDEO_AVCProfileHigh}, 164 {1620,20250,5000000,OMX_VIDEO_AVCLevel22,OMX_VIDEO_AVCProfileHigh}, 165 {1620,40500,12500000,OMX_VIDEO_AVCLevel3,OMX_VIDEO_AVCProfileHigh}, 166 {3600,108000,17500000,OMX_VIDEO_AVCLevel31,OMX_VIDEO_AVCProfileHigh}, 167 {0 ,0 ,0 ,0 } 168 }; 169 170 /* H263 profile and level table*/ 171 static const unsigned int h263_profile_level_table[][5]= 172 { 173 /*max mb per frame, max mb per sec, max bitrate, level, profile*/ 174 {99,1485,64000,OMX_VIDEO_H263Level10,OMX_VIDEO_H263ProfileBaseline}, 175 {396,5940,128000,OMX_VIDEO_H263Level20,OMX_VIDEO_H263ProfileBaseline}, 176 {396,11880,384000,OMX_VIDEO_H263Level30,OMX_VIDEO_H263ProfileBaseline}, 177 {396,11880,2048000,OMX_VIDEO_H263Level40,OMX_VIDEO_H263ProfileBaseline}, 178 {99,1485,128000,OMX_VIDEO_H263Level45,OMX_VIDEO_H263ProfileBaseline}, 179 {396,19800,4096000,OMX_VIDEO_H263Level50,OMX_VIDEO_H263ProfileBaseline}, 180 {810,40500,8192000,OMX_VIDEO_H263Level60,OMX_VIDEO_H263ProfileBaseline}, 181 {1620,81000,16384000,OMX_VIDEO_H263Level70,OMX_VIDEO_H263ProfileBaseline}, 182 {0 , 0 , 0 , 0 } 183 }; 184 185 ////////////////////////// 186 // TYPES 187 ////////////////////////// 188 struct ProfileType 189 { 190 OMX_VIDEO_CODINGTYPE eCodec; 191 OMX_VIDEO_MPEG4LEVELTYPE eLevel; 192 OMX_VIDEO_CONTROLRATETYPE eControlRate; 193 OMX_VIDEO_AVCSLICEMODETYPE eSliceMode; 194 OMX_U32 nFrameWidth; 195 OMX_U32 nFrameHeight; 196 OMX_U32 nFrameBytes; 197 OMX_U32 nBitrate; 198 OMX_U32 nFramerate; 199 char* cInFileName; 200 char* cOutFileName; 201 }; 202 203 enum MsgId 204 { 205 MSG_ID_OUTPUT_FRAME_DONE, 206 MSG_ID_INPUT_FRAME_DONE, 207 MSG_ID_MAX 208 }; 209 union MsgData 210 { 211 struct 212 { 213 OMX_BUFFERHEADERTYPE* pBuffer; 214 } sBitstreamData; 215 }; 216 struct Msg 217 { 218 MsgId id; 219 MsgData data; 220 }; 221 struct MsgQ 222 { 223 Msg q[MAX_MSG]; 224 int head; 225 int size; 226 }; 227 228 enum Mode 229 { 230 MODE_PREVIEW, 231 MODE_DISPLAY, 232 MODE_PROFILE, 233 MODE_FILE_ENCODE, 234 MODE_LIVE_ENCODE 235 }; 236 237 ////////////////////////// 238 // MODULE VARS 239 ////////////////////////// 240 static pthread_mutex_t m_mutex; 241 static pthread_cond_t m_signal; 242 static MsgQ m_sMsgQ; 243 244 //#warning determine how many buffers we really have 245 OMX_STATETYPE m_eState = OMX_StateInvalid; 246 OMX_COMPONENTTYPE m_sComponent; 247 OMX_HANDLETYPE m_hHandle = NULL; 248 OMX_BUFFERHEADERTYPE* m_pOutBuffers[NUM_OUT_BUFFERS] = {NULL}; 249 OMX_BUFFERHEADERTYPE* m_pInBuffers[NUM_IN_BUFFERS] = {NULL}; 250 OMX_BOOL m_bInFrameFree[NUM_IN_BUFFERS]; 251 252 ProfileType m_sProfile; 253 254 static int m_nFramePlay = 0; 255 static int m_eMode = MODE_PREVIEW; 256 static int m_nInFd = -1; 257 static int m_nOutFd = -1; 258 static int m_nTimeStamp = 0; 259 static int m_nFrameIn = 0; // frames pushed to encoder 260 static int m_nFrameOut = 0; // frames returned by encoder 261 static int m_nAVCSliceMode = 0; 262 263 static bool m_bWatchDogKicked = false; 264 265 /* Statistics Logging */ 266 static long long tot_bufsize = 0; 267 int ebd_cnt=0, fbd_cnt=0; 268 269 ////////////////////////// 270 // MODULE FUNCTIONS 271 ////////////////////////// 272 273 void* PmemMalloc(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO* pMem, int nSize) 274 { 275 void *pvirt = NULL; 276 277 if (!pMem) 278 return NULL; 279 280 pMem->pmem_fd = open("/dev/pmem_adsp", O_RDWR | O_SYNC); 281 if ((int)(pMem->pmem_fd) < 0) 282 return NULL; 283 nSize = (nSize + 4095) & (~4095); 284 pMem->offset = 0; 285 pvirt = mmap(NULL, nSize, 286 PROT_READ | PROT_WRITE, 287 MAP_SHARED, pMem->pmem_fd, pMem->offset); 288 if (pvirt == (void*) MAP_FAILED) 289 { 290 close(pMem->pmem_fd); 291 pMem->pmem_fd = -1; 292 return NULL; 293 } 294 D("allocated pMem->fd = %d pvirt=0x%x, pMem->phys=0x%x, size = %d", pMem->pmem_fd, 295 pvirt, pMem->offset, nSize); 296 return pvirt; 297 } 298 299 int PmemFree(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO* pMem, void* pvirt, int nSize) 300 { 301 if (!pMem || !pvirt) 302 return -1; 303 304 nSize = (nSize + 4095) & (~4095); 305 munmap(pvirt, nSize); 306 close(pMem->pmem_fd); 307 pMem->pmem_fd = -1; 308 return 0; 309 } 310 311 void SetState(OMX_STATETYPE eState) 312 { 313 #define GOTO_STATE(eState) \ 314 case eState: \ 315 { \ 316 D("Going to state " # eState"..."); \ 317 OMX_SendCommand(m_hHandle, \ 318 OMX_CommandStateSet, \ 319 (OMX_U32) eState, \ 320 NULL); \ 321 while (m_eState != eState) \ 322 { \ 323 sleep(1); \ 324 } \ 325 D("Now in state " # eState); \ 326 break; \ 327 } 328 329 switch (eState) 330 { 331 GOTO_STATE(OMX_StateLoaded); 332 GOTO_STATE(OMX_StateIdle); 333 GOTO_STATE(OMX_StateExecuting); 334 GOTO_STATE(OMX_StateInvalid); 335 GOTO_STATE(OMX_StateWaitForResources); 336 GOTO_STATE(OMX_StatePause); 337 } 338 } 339 //////////////////////////////////////////////////////////////////////////////// 340 OMX_ERRORTYPE ConfigureEncoder() 341 { 342 OMX_ERRORTYPE result = OMX_ErrorNone; 343 unsigned const int *profile_tbl = NULL; 344 OMX_U32 mb_per_sec, mb_per_frame; 345 bool profile_level_found = false; 346 OMX_U32 eProfile,eLevel; 347 348 OMX_PARAM_PORTDEFINITIONTYPE portdef; // OMX_IndexParamPortDefinition 349 #ifdef QCOM_EXT 350 OMX_QCOM_PARAM_PORTDEFINITIONTYPE qPortDefnType; 351 #endif 352 353 portdef.nPortIndex = (OMX_U32) 0; // input 354 result = OMX_GetParameter(m_hHandle, 355 OMX_IndexParamPortDefinition, 356 &portdef); 357 E("\n OMX_IndexParamPortDefinition Get Paramter on input port"); 358 CHK(result); 359 portdef.format.video.nFrameWidth = m_sProfile.nFrameWidth; 360 portdef.format.video.nFrameHeight = m_sProfile.nFrameHeight; 361 362 E ("\n Height %d width %d bit rate %d",portdef.format.video.nFrameHeight 363 ,portdef.format.video.nFrameWidth,portdef.format.video.nBitrate); 364 result = OMX_SetParameter(m_hHandle, 365 OMX_IndexParamPortDefinition, 366 &portdef); 367 E("\n OMX_IndexParamPortDefinition Set Paramter on input port"); 368 CHK(result); 369 portdef.nPortIndex = (OMX_U32) 1; // output 370 result = OMX_GetParameter(m_hHandle, 371 OMX_IndexParamPortDefinition, 372 &portdef); 373 E("\n OMX_IndexParamPortDefinition Get Paramter on output port"); 374 CHK(result); 375 portdef.format.video.nFrameWidth = m_sProfile.nFrameWidth; 376 portdef.format.video.nFrameHeight = m_sProfile.nFrameHeight; 377 portdef.format.video.nBitrate = m_sProfile.nBitrate; 378 portdef.format.video.xFramerate = m_sProfile.nFramerate << 16; 379 result = OMX_SetParameter(m_hHandle, 380 OMX_IndexParamPortDefinition, 381 &portdef); 382 E("\n OMX_IndexParamPortDefinition Set Paramter on output port"); 383 CHK(result); 384 385 #ifdef QCOM_EXT 386 387 qPortDefnType.nPortIndex = PORT_INDEX_IN; 388 qPortDefnType.nMemRegion = OMX_QCOM_MemRegionEBI1; 389 qPortDefnType.nSize = sizeof(OMX_QCOM_PARAM_PORTDEFINITIONTYPE); 390 391 result = OMX_SetParameter(m_hHandle, 392 (OMX_INDEXTYPE)OMX_QcomIndexPortDefn, 393 &qPortDefnType); 394 395 #endif 396 //validate the ht,width,fps,bitrate and set the appropriate profile and level 397 if(m_sProfile.eCodec == OMX_VIDEO_CodingMPEG4) 398 { 399 profile_tbl = (unsigned int const *)mpeg4_profile_level_table; 400 } 401 else if(m_sProfile.eCodec == OMX_VIDEO_CodingAVC) 402 { 403 profile_tbl = (unsigned int const *)h264_profile_level_table; 404 } 405 else if(m_sProfile.eCodec == OMX_VIDEO_CodingH263) 406 { 407 profile_tbl = (unsigned int const *)h263_profile_level_table; 408 } 409 410 mb_per_frame = ((m_sProfile.nFrameHeight+15)>>4)* 411 ((m_sProfile.nFrameWidth+15)>>4); 412 413 mb_per_sec = mb_per_frame*(m_sProfile.nFramerate); 414 415 do{ 416 if(mb_per_frame <= (int)profile_tbl[0]) 417 { 418 if(mb_per_sec <= (int)profile_tbl[1]) 419 { 420 if(m_sProfile.nBitrate <= (int)profile_tbl[2]) 421 { 422 eLevel = (int)profile_tbl[3]; 423 eProfile = (int)profile_tbl[4]; 424 E("\n profile and level found \n"); 425 profile_level_found = true; 426 break; 427 } 428 } 429 } 430 profile_tbl = profile_tbl + 5; 431 }while(profile_tbl[0] != 0); 432 433 if ( profile_level_found != true ) 434 { 435 E("\n Error: Unsupported profile/level\n"); 436 return OMX_ErrorNone; 437 } 438 439 if (m_sProfile.eCodec == OMX_VIDEO_CodingH263) 440 { 441 D("Configuring H263..."); 442 443 OMX_VIDEO_PARAM_H263TYPE h263; 444 result = OMX_GetParameter(m_hHandle, 445 OMX_IndexParamVideoH263, 446 &h263); 447 CHK(result); 448 h263.nPortIndex = (OMX_U32) PORT_INDEX_OUT; 449 h263.nPFrames = m_sProfile.nFramerate * 2 - 1; // intra period 450 h263.nBFrames = 0; 451 h263.eProfile = (OMX_VIDEO_H263PROFILETYPE)eProfile; 452 h263.eLevel = (OMX_VIDEO_H263LEVELTYPE)eLevel; 453 h263.bPLUSPTYPEAllowed = OMX_FALSE; 454 h263.nAllowedPictureTypes = 2; 455 h263.bForceRoundingTypeToZero = OMX_TRUE; ///@todo determine what this should be 456 h263.nPictureHeaderRepetition = 0; ///@todo determine what this should be 457 h263.nGOBHeaderInterval = 0; ///@todo determine what this should be 458 result = OMX_SetParameter(m_hHandle, 459 OMX_IndexParamVideoH263, 460 &h263); 461 } 462 else 463 { 464 D("Configuring MP4/H264..."); 465 466 OMX_VIDEO_PARAM_PROFILELEVELTYPE profileLevel; // OMX_IndexParamVideoProfileLevelCurrent 467 profileLevel.eProfile = eProfile; 468 profileLevel.eLevel = eLevel; 469 result = OMX_SetParameter(m_hHandle, 470 OMX_IndexParamVideoProfileLevelCurrent, 471 &profileLevel); 472 E("\n OMX_IndexParamVideoProfileLevelCurrent Set Paramter port"); 473 CHK(result); 474 //profileLevel.eLevel = (OMX_U32) m_sProfile.eLevel; 475 result = OMX_GetParameter(m_hHandle, 476 OMX_IndexParamVideoProfileLevelCurrent, 477 &profileLevel); 478 E("\n OMX_IndexParamVideoProfileLevelCurrent Get Paramter port"); 479 D ("\n Profile = %d level = %d",profileLevel.eProfile,profileLevel.eLevel); 480 CHK(result); 481 482 /*OMX_VIDEO_PARAM_MPEG4TYPE mp4; 483 484 result = OMX_GetParameter(m_hHandle, 485 OMX_IndexParamVideoMpeg4, 486 &mp4); 487 E("\n OMX_IndexParamVideoMpeg4 Set Paramter port"); 488 CHK(result); 489 490 mp4.nTimeIncRes = m_sProfile.nFramerate * 2; 491 mp4.nPFrames = mp4.nTimeIncRes - 1; // intra period 492 493 result = OMX_SetParameter(m_hHandle, 494 OMX_IndexParamVideoMpeg4, 495 &mp4); 496 CHK(result);*/ 497 498 // OMX_VIDEO_PARAM_MPEG4TYPE mp4; // OMX_IndexParamVideoMpeg4 499 // result = OMX_GetParameter(m_hHandle, 500 // OMX_IndexParamVideoMpeg4, 501 // &mp4); 502 // CHK(result); 503 // mp4.nPortIndex = (OMX_U32) PORT_INDEX_OUT; 504 // mp4.eProfile = OMX_VIDEO_MPEG4ProfileSimple; 505 // mp4.eLevel = m_sProfile.eLevel; 506 // mp4.nSliceHeaderSpacing = 0; 507 // mp4.bSVH = OMX_FALSE; 508 // mp4.bGov = OMX_FALSE; 509 // mp4.nPFrames = m_sProfile.nFramerate * 2 - 1; // intra period 510 // mp4.bACPred = OMX_TRUE; 511 // mp4.nTimeIncRes = m_sProfile.nFramerate * 2; // delta = 2 @ 15 fps 512 // mp4.nAllowedPictureTypes = 2; // pframe and iframe 513 // result = OMX_SetParameter(m_hHandle, 514 // OMX_IndexParamVideoMpeg4, 515 // &mp4); 516 // CHK(result); 517 } 518 519 if (m_sProfile.eCodec == OMX_VIDEO_CodingAVC) 520 { 521 OMX_VIDEO_PARAM_AVCSLICEFMO avcslicefmo; 522 avcslicefmo.nPortIndex = (OMX_U32)PORT_INDEX_OUT; 523 result = OMX_GetParameter(m_hHandle, 524 OMX_IndexParamVideoSliceFMO, 525 &avcslicefmo); 526 E("\n OMX_IndexParamVideoSliceFMO Get Paramter port"); 527 CHK(result); 528 529 avcslicefmo.eSliceMode = m_sProfile.eSliceMode; 530 result = OMX_SetParameter(m_hHandle, 531 OMX_IndexParamVideoSliceFMO, 532 &avcslicefmo); 533 E("\n OMX_IndexParamVideoSliceFMO Set Paramter port"); 534 CHK(result); 535 } 536 537 OMX_VIDEO_PARAM_BITRATETYPE bitrate; // OMX_IndexParamVideoBitrate 538 bitrate.nPortIndex = (OMX_U32)PORT_INDEX_OUT; 539 result = OMX_GetParameter(m_hHandle, 540 OMX_IndexParamVideoBitrate, 541 &bitrate); 542 E("\n OMX_IndexParamVideoBitrate Get Paramter port"); 543 CHK(result); 544 bitrate.eControlRate = m_sProfile.eControlRate; 545 bitrate.nTargetBitrate = m_sProfile.nBitrate; 546 result = OMX_SetParameter(m_hHandle, 547 OMX_IndexParamVideoBitrate, 548 &bitrate); 549 E("\n OMX_IndexParamVideoBitrate Set Paramter port"); 550 CHK(result); 551 552 OMX_VIDEO_PARAM_PORTFORMATTYPE framerate; // OMX_IndexParamVidePortFormat 553 framerate.nPortIndex = 0; 554 result = OMX_GetParameter(m_hHandle, 555 OMX_IndexParamVideoPortFormat, 556 &framerate); 557 E("\n OMX_IndexParamVideoPortFormat Get Paramter port"); 558 CHK(result); 559 framerate.xFramerate = m_sProfile.nFramerate << 16; 560 result = OMX_SetParameter(m_hHandle, 561 OMX_IndexParamVideoPortFormat, 562 &framerate); 563 E("\n OMX_IndexParamVideoPortFormat Set Paramter port"); 564 CHK(result); 565 566 #if 1 567 OMX_CONFIG_FRAMERATETYPE enc_framerate; // OMX_IndexConfigVideoFramerate 568 enc_framerate.nPortIndex = (OMX_U32)PORT_INDEX_OUT; 569 result = OMX_GetConfig(m_hHandle, 570 OMX_IndexConfigVideoFramerate, 571 &enc_framerate); 572 E("\n OMX_IndexConfigVideoFramerate Get config port"); 573 CHK(result); 574 enc_framerate.xEncodeFramerate = m_sProfile.nFramerate << 16; 575 result = OMX_SetConfig(m_hHandle, 576 OMX_IndexConfigVideoFramerate, 577 &enc_framerate); 578 E("\n OMX_IndexConfigVideoFramerate Set config port"); 579 CHK(result); 580 #endif 581 return OMX_ErrorNone; 582 } 583 //////////////////////////////////////////////////////////////////////////////// 584 void SendMessage(MsgId id, MsgData* data) 585 { 586 pthread_mutex_lock(&m_mutex); 587 if (m_sMsgQ.size >= MAX_MSG) 588 { 589 E("main msg m_sMsgQ is full"); 590 return; 591 } 592 m_sMsgQ.q[(m_sMsgQ.head + m_sMsgQ.size) % MAX_MSG].id = id; 593 if (data) 594 m_sMsgQ.q[(m_sMsgQ.head + m_sMsgQ.size) % MAX_MSG].data = *data; 595 ++m_sMsgQ.size; 596 pthread_cond_signal(&m_signal); 597 pthread_mutex_unlock(&m_mutex); 598 } 599 //////////////////////////////////////////////////////////////////////////////// 600 void PopMessage(Msg* msg) 601 { 602 pthread_mutex_lock(&m_mutex); 603 while (m_sMsgQ.size == 0) 604 { 605 pthread_cond_wait(&m_signal, &m_mutex); 606 } 607 *msg = m_sMsgQ.q[m_sMsgQ.head]; 608 --m_sMsgQ.size; 609 m_sMsgQ.head = (m_sMsgQ.head + 1) % MAX_MSG; 610 pthread_mutex_unlock(&m_mutex); 611 } 612 //////////////////////////////////////////////////////////////////////////////// 613 OMX_ERRORTYPE EVT_CB(OMX_IN OMX_HANDLETYPE hComponent, 614 OMX_IN OMX_PTR pAppData, 615 OMX_IN OMX_EVENTTYPE eEvent, 616 OMX_IN OMX_U32 nData1, 617 OMX_IN OMX_U32 nData2, 618 OMX_IN OMX_PTR pEventData) 619 { 620 #define SET_STATE(eState) \ 621 case eState: \ 622 { \ 623 D("" # eState " complete"); \ 624 m_eState = eState; \ 625 break; \ 626 } 627 628 if (eEvent == OMX_EventCmdComplete) 629 { 630 if ((OMX_COMMANDTYPE) nData1 == OMX_CommandStateSet) 631 { 632 switch ((OMX_STATETYPE) nData2) 633 { 634 SET_STATE(OMX_StateLoaded); 635 SET_STATE(OMX_StateIdle); 636 SET_STATE(OMX_StateExecuting); 637 SET_STATE(OMX_StateInvalid); 638 SET_STATE(OMX_StateWaitForResources); 639 SET_STATE(OMX_StatePause); 640 default: 641 E("invalid state %d", (int) nData2); 642 } 643 } 644 } 645 646 else if (eEvent == OMX_EventError) 647 { 648 E("OMX_EventError"); 649 } 650 651 else 652 { 653 E("unexpected event %d", (int) eEvent); 654 } 655 return OMX_ErrorNone; 656 } 657 //////////////////////////////////////////////////////////////////////////////// 658 OMX_ERRORTYPE EBD_CB(OMX_IN OMX_HANDLETYPE hComponent, 659 OMX_IN OMX_PTR pAppData, 660 OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) 661 { 662 D("Got EBD callback ts=%lld", pBuffer->nTimeStamp); 663 664 for (int i = 0; i < num_in_buffers; i++) 665 { 666 // mark this buffer ready for use again 667 if (m_pInBuffers[i] == pBuffer) 668 { 669 670 D("Marked input buffer idx %d as free, buf %p", i, pBuffer->pBuffer); 671 m_bInFrameFree[i] = OMX_TRUE; 672 break; 673 } 674 } 675 676 if (m_eMode == MODE_LIVE_ENCODE) 677 { 678 CameraTest_ReleaseFrame(pBuffer->pBuffer, 679 ((OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO*)pBuffer->pAppPrivate)); 680 } 681 else 682 { 683 // wake up main thread and tell it to send next frame 684 MsgData data; 685 data.sBitstreamData.pBuffer = pBuffer; 686 SendMessage(MSG_ID_INPUT_FRAME_DONE, 687 &data); 688 689 } 690 return OMX_ErrorNone; 691 } 692 //////////////////////////////////////////////////////////////////////////////// 693 OMX_ERRORTYPE FBD_CB(OMX_OUT OMX_HANDLETYPE hComponent, 694 OMX_OUT OMX_PTR pAppData, 695 OMX_OUT OMX_BUFFERHEADERTYPE* pBuffer) 696 { 697 D("Got FBD callback ts=%lld", pBuffer->nTimeStamp); 698 699 static long long prevTime = 0; 700 long long currTime = GetTimeStamp(); 701 702 m_bWatchDogKicked = true; 703 704 /* Empty Buffers should not be counted */ 705 if(pBuffer->nFilledLen !=0) 706 { 707 /* Counting Buffers supplied from OpneMax Encoder */ 708 fbd_cnt++; 709 tot_bufsize += pBuffer->nFilledLen; 710 } 711 if (prevTime != 0) 712 { 713 long long currTime = GetTimeStamp(); 714 D("FBD_DELTA = %lld\n", currTime - prevTime); 715 } 716 prevTime = currTime; 717 718 if (m_eMode == MODE_PROFILE) 719 { 720 // if we are profiling we are not doing file I/O 721 // so just give back to encoder 722 if (OMX_FillThisBuffer(m_hHandle, pBuffer) != OMX_ErrorNone) 723 { 724 E("empty buffer failed for profiling"); 725 } 726 } 727 else 728 { 729 // wake up main thread and tell it to write to file 730 MsgData data; 731 data.sBitstreamData.pBuffer = pBuffer; 732 SendMessage(MSG_ID_OUTPUT_FRAME_DONE, 733 &data); 734 } 735 return OMX_ErrorNone; 736 } 737 //////////////////////////////////////////////////////////////////////////////// 738 OMX_ERRORTYPE VencTest_Initialize() 739 { 740 OMX_ERRORTYPE result = OMX_ErrorNone; 741 static OMX_CALLBACKTYPE sCallbacks = {EVT_CB, EBD_CB, FBD_CB}; 742 int i; 743 744 for (i = 0; i < num_in_buffers; i++) 745 { 746 m_pInBuffers[i] = NULL; 747 } 748 749 result = OMX_Init(); 750 CHK(result); 751 752 if (m_sProfile.eCodec == OMX_VIDEO_CodingMPEG4) 753 { 754 result = OMX_GetHandle(&m_hHandle, 755 "OMX.qcom.video.encoder.mpeg4", 756 NULL, 757 &sCallbacks); 758 // CHK(result); 759 } 760 else if (m_sProfile.eCodec == OMX_VIDEO_CodingH263) 761 { 762 result = OMX_GetHandle(&m_hHandle, 763 "OMX.qcom.video.encoder.h263", 764 NULL, 765 &sCallbacks); 766 CHK(result); 767 } 768 else 769 { 770 result = OMX_GetHandle(&m_hHandle, 771 "OMX.qcom.video.encoder.avc", 772 NULL, 773 &sCallbacks); 774 CHK(result); 775 } 776 777 778 result = ConfigureEncoder(); 779 CHK(result); 780 781 return result; 782 } 783 784 //////////////////////////////////////////////////////////////////////////////// 785 OMX_ERRORTYPE VencTest_RegisterYUVBuffer(OMX_BUFFERHEADERTYPE** ppBufferHeader, 786 OMX_U8 *pBuffer, 787 OMX_PTR pAppPrivate) 788 { 789 OMX_ERRORTYPE result = OMX_ErrorNone; 790 #if 0 791 D("register buffer"); 792 if ((result = OMX_AllocateBuffer(m_hHandle, 793 ppBufferHeader, 794 (OMX_U32) PORT_INDEX_IN, 795 pAppPrivate, 796 m_sProfile.nFrameBytes 797 )) != OMX_ErrorNone) 798 { 799 E("use buffer failed"); 800 } 801 else 802 { 803 E("Allocate Buffer Success %x", (*ppBufferHeader)->pBuffer); 804 } 805 #endif 806 D("register buffer"); 807 D("Calling UseBuffer for Input port"); 808 if ((result = OMX_UseBuffer(m_hHandle, 809 ppBufferHeader, 810 (OMX_U32) PORT_INDEX_IN, 811 pAppPrivate, 812 m_sProfile.nFrameBytes, 813 pBuffer)) != OMX_ErrorNone) 814 { 815 E("use buffer failed"); 816 } 817 818 return result; 819 } 820 //////////////////////////////////////////////////////////////////////////////// 821 OMX_ERRORTYPE VencTest_EncodeFrame(void* pYUVBuff, 822 long long nTimeStamp) 823 { 824 OMX_ERRORTYPE result = OMX_ErrorUndefined; 825 D("calling OMX empty this buffer"); 826 for (int i = 0; i < num_in_buffers; i++) 827 { 828 if (pYUVBuff == m_pInBuffers[i]->pBuffer) 829 { 830 m_pInBuffers[i]->nTimeStamp = nTimeStamp; 831 D("Sending Buffer - %x", m_pInBuffers[i]->pBuffer); 832 result = OMX_EmptyThisBuffer(m_hHandle, 833 m_pInBuffers[i]); 834 /* Counting Buffers supplied to OpenMax Encoder */ 835 if(OMX_ErrorNone == result) 836 ebd_cnt++; 837 CHK(result); 838 break; 839 } 840 } 841 return result; 842 } 843 //////////////////////////////////////////////////////////////////////////////// 844 OMX_ERRORTYPE VencTest_Exit(void) 845 { 846 int i; 847 OMX_ERRORTYPE result = OMX_ErrorNone; 848 D("trying to exit venc"); 849 850 D("going to idle state"); 851 SetState(OMX_StateIdle); 852 853 854 D("going to loaded state"); 855 //SetState(OMX_StateLoaded); 856 OMX_SendCommand(m_hHandle, 857 OMX_CommandStateSet, 858 (OMX_U32) OMX_StateLoaded, 859 NULL); 860 861 for (i = 0; i < num_in_buffers; i++) 862 { 863 D("free buffer"); 864 if (m_pInBuffers[i]->pBuffer) 865 { 866 // free(m_pInBuffers[i]->pBuffer); 867 result = OMX_FreeBuffer(m_hHandle, 868 PORT_INDEX_IN, 869 m_pInBuffers[i]); 870 CHK(result); 871 } 872 else 873 { 874 E("buffer %d is null", i); 875 result = OMX_ErrorUndefined; 876 CHK(result); 877 } 878 } 879 for (i = 0; i < num_out_buffers; i++) 880 { 881 D("free buffer"); 882 if (m_pOutBuffers[i]->pBuffer) 883 { 884 free(m_pOutBuffers[i]->pBuffer); 885 result = OMX_FreeBuffer(m_hHandle, 886 PORT_INDEX_OUT, 887 m_pOutBuffers[i]); 888 CHK(result); 889 890 } 891 else 892 { 893 E("buffer %d is null", i); 894 result = OMX_ErrorUndefined; 895 CHK(result); 896 } 897 } 898 899 while (m_eState != OMX_StateLoaded) 900 { 901 sleep(1); 902 } 903 D("component_deinit..."); 904 result = OMX_Deinit(); 905 CHK(result); 906 907 D("venc is exiting..."); 908 return result; 909 } 910 //////////////////////////////////////////////////////////////////////////////// 911 OMX_ERRORTYPE VencTest_ReadAndEmpty(OMX_BUFFERHEADERTYPE* pYUVBuffer) 912 { 913 OMX_ERRORTYPE result = OMX_ErrorNone; 914 #ifdef T_ARM 915 if (read(m_nInFd, 916 pYUVBuffer->pBuffer, 917 m_sProfile.nFrameBytes) != m_sProfile.nFrameBytes) 918 { 919 return OMX_ErrorUndefined; 920 } 921 #else 922 { 923 char * pInputbuf = (char *)(pYUVBuffer->pBuffer) ; 924 read(m_nInFd,pInputbuf,m_sProfile.nFrameBytes) ; 925 926 } 927 #endif 928 D("about to call VencTest_EncodeFrame..."); 929 pthread_mutex_lock(&m_mutex); 930 ++m_nFrameIn; 931 pYUVBuffer->nFilledLen = m_sProfile.nFrameBytes; 932 D("Called Buffer with Data filled length %d",pYUVBuffer->nFilledLen); 933 934 result = VencTest_EncodeFrame(pYUVBuffer->pBuffer, 935 m_nTimeStamp); 936 937 m_nTimeStamp += (1000000) / m_sProfile.nFramerate; 938 CHK(result); 939 pthread_mutex_unlock(&m_mutex); 940 return result; 941 } 942 //////////////////////////////////////////////////////////////////////////////// 943 void PreviewCallback(int nFD, 944 int nOffset, 945 void* pPhys, 946 void* pVirt, 947 long long nTimeStamp) 948 { 949 950 D("================= preview frame %d, phys=0x%x, nTimeStamp(millis)=%lld", 951 m_nFrameIn+1, pPhys, (nTimeStamp / 1000)); 952 953 if (m_nFrameIn == m_nFramePlay && 954 m_nFramePlay != 0) 955 { 956 // we will stop camera after last frame is encoded. 957 // for now just ignore input frames 958 959 CameraTest_ReleaseFrame(pPhys, pVirt); 960 return; 961 } 962 963 // see if we should stop 964 pthread_mutex_lock(&m_mutex); 965 ++m_nFrameIn; 966 pthread_mutex_unlock(&m_mutex); 967 968 969 if (m_eMode == MODE_LIVE_ENCODE) 970 { 971 972 OMX_ERRORTYPE result; 973 974 // register new camera buffers with encoder 975 int i; 976 for (i = 0; i < num_in_buffers; i++) 977 { 978 if (m_pInBuffers[i] != NULL && 979 m_pInBuffers[i]->pBuffer == pPhys) 980 { 981 break; 982 } 983 else if (m_pInBuffers[i] == NULL) 984 { 985 D("registering buffer..."); 986 result = VencTest_RegisterYUVBuffer(&m_pInBuffers[i], 987 (OMX_U8*) pPhys, 988 (OMX_PTR) pVirt); // store virt in app private field 989 D("register done"); 990 CHK(result); 991 break; 992 } 993 } 994 995 if (i == num_in_buffers) 996 { 997 E("There are more camera buffers than we thought"); 998 CHK(1); 999 } 1000 1001 // encode the yuv frame 1002 1003 D("StartEncodeTime=%lld", GetTimeStamp()); 1004 result = VencTest_EncodeFrame(pPhys, 1005 nTimeStamp); 1006 CHK(result); 1007 // FBTest_DisplayImage(nFD, nOffset); 1008 } 1009 else 1010 { 1011 // FBTest_DisplayImage(nFD, nOffset); 1012 CameraTest_ReleaseFrame(pPhys, pVirt); 1013 } 1014 } 1015 //////////////////////////////////////////////////////////////////////////////// 1016 void usage(char* filename) 1017 { 1018 char* fname = strrchr(filename, (int) '/'); 1019 fname = (fname == NULL) ? filename : fname; 1020 1021 fprintf(stderr, "usage: %s LIVE <QCIF|QVGA> <MP4|H263> <FPS> <BITRATE> <NFRAMES> <OUTFILE>\n", fname); 1022 fprintf(stderr, "usage: %s FILE <QCIF|QVGA> <MP4|H263 <FPS> <BITRATE> <NFRAMES> <INFILE> <OUTFILE> ", fname); 1023 fprintf(stderr, "<Rate Control - optional> <AVC Slice Mode - optional\n", fname); 1024 fprintf(stderr, "usage: %s PROFILE <QCIF|QVGA> <MP4|H263 <FPS> <BITRATE> <NFRAMES> <INFILE>\n", fname); 1025 fprintf(stderr, "usage: %s PREVIEW <QCIF|QVGA> <FPS> <NFRAMES>\n", fname); 1026 fprintf(stderr, "usage: %s DISPLAY <QCIF|QVGA> <FPS> <NFRAMES> <INFILE>\n", fname); 1027 fprintf(stderr, "\n BITRATE - bitrate in kbps\n"); 1028 fprintf(stderr, " FPS - frames per second\n"); 1029 fprintf(stderr, " NFRAMES - number of frames to play, 0 for infinite\n"); 1030 fprintf(stderr, " RateControl (Values 0 - 4 for RC_OFF, RC_CBR_CFR, RC_CBR_VFR, RC_VBR_CFR, RC_VBR_VFR\n"); 1031 exit(1); 1032 } 1033 //////////////////////////////////////////////////////////////////////////////// 1034 void parseArgs(int argc, char** argv) 1035 { 1036 1037 if (argc == 1) 1038 { 1039 usage(argv[0]); 1040 } 1041 else if (strcmp("PREVIEW", argv[1]) == 0 || 1042 strcmp("preview", argv[1]) == 0) 1043 { 1044 m_eMode = MODE_PREVIEW; 1045 if (argc != 5) 1046 { 1047 usage(argv[0]); 1048 } 1049 } 1050 else if (strcmp("DISPLAY", argv[1]) == 0 || 1051 strcmp("display", argv[1]) == 0) 1052 { 1053 m_eMode = MODE_DISPLAY; 1054 if (argc != 6) 1055 { 1056 usage(argv[0]); 1057 } 1058 m_sProfile.cInFileName = argv[5]; 1059 m_sProfile.cOutFileName = NULL; 1060 } 1061 else if (strcmp("LIVE", argv[1]) == 0 || 1062 strcmp("live", argv[1]) == 0) 1063 {//263 1064 m_eMode = MODE_LIVE_ENCODE; 1065 if (argc != 8) 1066 { 1067 usage(argv[0]); 1068 } 1069 m_sProfile.cInFileName = NULL; 1070 m_sProfile.cOutFileName = argv[7]; 1071 } 1072 else if (strcmp("FILE", argv[1]) == 0 || 1073 strcmp("file", argv[1]) == 0) 1074 {//263 1075 m_eMode = MODE_FILE_ENCODE; 1076 1077 if(argc < 9 || argc > 11) 1078 { 1079 usage(argv[0]); 1080 } 1081 else 1082 { 1083 if ((argc == 10)) 1084 { 1085 m_sProfile.eControlRate = OMX_Video_ControlRateVariable; 1086 int RC = atoi(argv[9]); 1087 1088 switch (RC) 1089 { 1090 case 0: 1091 m_sProfile.eControlRate = OMX_Video_ControlRateDisable ;//VENC_RC_NONE 1092 break; 1093 case 1: 1094 m_sProfile.eControlRate = OMX_Video_ControlRateConstant;//VENC_RC_CBR_CFR 1095 break; 1096 1097 case 2: 1098 m_sProfile.eControlRate = OMX_Video_ControlRateConstantSkipFrames;//VENC_RC_CBR_VFR 1099 break; 1100 1101 case 3: 1102 m_sProfile.eControlRate =OMX_Video_ControlRateVariable ;//VENC_RC_VBR_CFR 1103 break; 1104 1105 case 4: 1106 m_sProfile.eControlRate = OMX_Video_ControlRateVariableSkipFrames;//VENC_RC_VBR_VFR 1107 break; 1108 1109 default: 1110 E("invalid rate control selection"); 1111 m_sProfile.eControlRate = OMX_Video_ControlRateVariable; //VENC_RC_VBR_CFR 1112 break; 1113 } 1114 } 1115 1116 if (argc == 11) 1117 { 1118 if(!strcmp(argv[3], "H264") || !strcmp(argv[3], "h264")) 1119 { 1120 E("\nSetting AVCSliceMode ... "); 1121 int AVCSliceMode = atoi(argv[10]); 1122 switch(AVCSliceMode) 1123 { 1124 case 0: 1125 m_sProfile.eSliceMode = OMX_VIDEO_SLICEMODE_AVCDefault; 1126 break; 1127 1128 case 1: 1129 m_sProfile.eSliceMode = OMX_VIDEO_SLICEMODE_AVCMBSlice; 1130 break; 1131 1132 case 2: 1133 m_sProfile.eSliceMode = OMX_VIDEO_SLICEMODE_AVCByteSlice; 1134 break; 1135 1136 default: 1137 E("invalid Slice Mode"); 1138 m_sProfile.eSliceMode = OMX_VIDEO_SLICEMODE_AVCDefault; 1139 break; 1140 } 1141 } 1142 else 1143 { 1144 E("SliceMode support only for H.264 codec"); 1145 usage(argv[0]); 1146 } 1147 } 1148 } 1149 m_sProfile.cInFileName = argv[7]; 1150 m_sProfile.cOutFileName = argv[8]; 1151 } 1152 else if (strcmp("PROFILE", argv[1]) == 0 || 1153 strcmp("profile", argv[1]) == 0) 1154 {//263 1155 m_eMode = MODE_PROFILE; 1156 if (argc != 8) 1157 { 1158 usage(argv[0]); 1159 } 1160 m_sProfile.cInFileName = argv[7]; 1161 m_sProfile.cOutFileName = NULL; 1162 } 1163 else 1164 { 1165 usage(argv[0]); 1166 } 1167 1168 1169 if (strcmp("QCIF", argv[2]) == 0 || 1170 strcmp("qcif", argv[2]) == 0) 1171 { 1172 m_sProfile.nFrameWidth = 176; 1173 m_sProfile.nFrameHeight = 144; 1174 m_sProfile.nFrameBytes = 176*144*3/2; 1175 m_sProfile.eLevel = OMX_VIDEO_MPEG4Level0; 1176 } 1177 else if (strcmp("QVGA", argv[2]) == 0 || 1178 strcmp("qvga", argv[2]) == 0) 1179 { 1180 m_sProfile.nFrameWidth = 320; 1181 m_sProfile.nFrameHeight = 240; 1182 m_sProfile.nFrameBytes = 320*240*3/2; 1183 m_sProfile.eLevel = OMX_VIDEO_MPEG4Level1; 1184 } 1185 1186 1187 else if (strcmp("VGA", argv[2]) == 0 || 1188 strcmp("vga", argv[2]) == 0) 1189 { 1190 m_sProfile.nFrameWidth = 640; 1191 m_sProfile.nFrameHeight = 480; 1192 m_sProfile.nFrameBytes = 640*480*3/2; 1193 m_sProfile.eLevel = OMX_VIDEO_MPEG4Level1; 1194 } 1195 1196 else if (strcmp("WVGA", argv[2]) == 0 || 1197 strcmp("wvga", argv[2]) == 0) 1198 { 1199 m_sProfile.nFrameWidth = 800; 1200 m_sProfile.nFrameHeight = 480; 1201 m_sProfile.nFrameBytes = 800*480*3/2; 1202 m_sProfile.eLevel = OMX_VIDEO_MPEG4Level1; 1203 } 1204 else if (strcmp("CIF", argv[2]) == 0 || 1205 strcmp("CIF", argv[2]) == 0) 1206 { 1207 m_sProfile.nFrameWidth = 352; 1208 m_sProfile.nFrameHeight = 288; 1209 m_sProfile.nFrameBytes = 352*288*3/2; 1210 m_sProfile.eLevel = OMX_VIDEO_MPEG4Level1; 1211 } 1212 else if (strcmp("720", argv[2]) == 0 || 1213 strcmp("720", argv[2]) == 0) 1214 { 1215 m_sProfile.nFrameWidth = 1280; 1216 m_sProfile.nFrameHeight = 720; 1217 m_sProfile.nFrameBytes = 720*1280*3/2; 1218 m_sProfile.eLevel = OMX_VIDEO_MPEG4Level1; 1219 } 1220 else 1221 { 1222 usage(argv[0]); 1223 } 1224 1225 if (m_eMode == MODE_DISPLAY || 1226 m_eMode == MODE_PREVIEW) 1227 { 1228 m_sProfile.nFramerate = atoi(argv[3]); 1229 m_nFramePlay = atoi(argv[4]); 1230 1231 } 1232 else if (m_eMode == MODE_LIVE_ENCODE || 1233 m_eMode == MODE_FILE_ENCODE || 1234 m_eMode == MODE_PROFILE) 1235 {//263 1236 if ((!strcmp(argv[3], "MP4")) || (!strcmp(argv[3], "mp4"))) 1237 { 1238 m_sProfile.eCodec = OMX_VIDEO_CodingMPEG4; 1239 } 1240 else if ((!strcmp(argv[3], "H263")) || (!strcmp(argv[3], "h263"))) 1241 { 1242 m_sProfile.eCodec = OMX_VIDEO_CodingH263; 1243 } 1244 else if ((!strcmp(argv[3], "H264")) || (!strcmp(argv[3], "h264"))) 1245 { 1246 m_sProfile.eCodec = OMX_VIDEO_CodingAVC; 1247 } 1248 else 1249 { 1250 usage(argv[0]); 1251 } 1252 1253 m_sProfile.nFramerate = atoi(argv[4]); 1254 m_sProfile.nBitrate = atoi(argv[5]); 1255 // m_sProfile.eControlRate = OMX_Video_ControlRateVariable; 1256 m_nFramePlay = atoi(argv[6]); 1257 } 1258 } 1259 1260 1261 void* Watchdog(void* data) 1262 { 1263 while (1) 1264 { 1265 sleep(1000); 1266 if (m_bWatchDogKicked == true) 1267 m_bWatchDogKicked = false; 1268 else 1269 E("watchdog has not been kicked. we may have a deadlock"); 1270 } 1271 return NULL; 1272 } 1273 1274 int main(int argc, char** argv) 1275 { 1276 OMX_U8* pvirt = NULL; 1277 int result; 1278 float enc_time_sec=0.0,enc_time_usec=0.0; 1279 1280 m_nInFd = -1; 1281 m_nOutFd = -1; 1282 m_nTimeStamp = 0; 1283 m_nFrameIn = 0; 1284 m_nFrameOut = 0; 1285 1286 memset(&m_sMsgQ, 0, sizeof(MsgQ)); 1287 parseArgs(argc, argv); 1288 1289 D("fps=%d, bitrate=%d, width=%d, height=%d", 1290 m_sProfile.nFramerate, 1291 m_sProfile.nBitrate, 1292 m_sProfile.nFrameWidth, 1293 m_sProfile.nFrameHeight); 1294 1295 1296 //if (m_eMode != MODE_PREVIEW && m_eMode != MODE_DISPLAY) 1297 //{ 1298 // pthread_t wd; 1299 // pthread_create(&wd, NULL, Watchdog, NULL); 1300 //} 1301 1302 for (int x = 0; x < num_in_buffers; x++) 1303 { 1304 // mark all buffers as ready to use 1305 m_bInFrameFree[x] = OMX_TRUE; 1306 } 1307 1308 1309 if (m_eMode != MODE_PROFILE) 1310 { 1311 #if T_ARM 1312 m_nOutFd = open(m_sProfile.cOutFileName, O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU | S_IRWXG | S_IRWXO); 1313 #else 1314 m_nOutFd = open(m_sProfile.cOutFileName,0); 1315 #endif 1316 if (m_nOutFd < 0) 1317 { 1318 E("could not open output file %s", m_sProfile.cOutFileName); 1319 CHK(1); 1320 } 1321 } 1322 1323 pthread_mutex_init(&m_mutex, NULL); 1324 pthread_cond_init(&m_signal, NULL); 1325 1326 if (m_eMode != MODE_PREVIEW) 1327 { 1328 VencTest_Initialize(); 1329 } 1330 1331 //////////////////////////////////////// 1332 // Camera + Encode 1333 //////////////////////////////////////// 1334 if (m_eMode == MODE_LIVE_ENCODE) 1335 { 1336 CameraTest_Initialize(m_sProfile.nFramerate, 1337 m_sProfile.nFrameWidth, 1338 m_sProfile.nFrameHeight, 1339 PreviewCallback); 1340 CameraTest_Run(); 1341 } 1342 1343 if (m_eMode == MODE_FILE_ENCODE || 1344 m_eMode == MODE_PROFILE) 1345 { 1346 int i; 1347 #if T_ARM 1348 m_nInFd = open(m_sProfile.cInFileName, O_RDONLY); 1349 #else 1350 m_nInFd = open(m_sProfile.cInFileName,1); 1351 #endif 1352 if (m_nInFd < 0) 1353 { 1354 E("could not open input file"); 1355 CHK(1); 1356 } 1357 D("going to idle state"); 1358 //SetState(OMX_StateIdle); 1359 OMX_SendCommand(m_hHandle, 1360 OMX_CommandStateSet, 1361 (OMX_U32) OMX_StateIdle, 1362 NULL); 1363 1364 OMX_PARAM_PORTDEFINITIONTYPE portDef; 1365 1366 portDef.nPortIndex = 0; 1367 result = OMX_GetParameter(m_hHandle, OMX_IndexParamPortDefinition, &portDef); 1368 CHK(result); 1369 1370 D("allocating output buffers"); 1371 1372 D("allocating Input buffers"); 1373 num_in_buffers = portDef.nBufferCountActual; 1374 for (i = 0; i < portDef.nBufferCountActual; i++) 1375 { 1376 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO* pMem = new OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO; 1377 pvirt = (OMX_U8*)PmemMalloc(pMem, m_sProfile.nFrameBytes); 1378 1379 if(pvirt == NULL) 1380 { 1381 CHK(1); 1382 } 1383 result = VencTest_RegisterYUVBuffer(&m_pInBuffers[i], 1384 (OMX_U8*) pvirt, 1385 (OMX_PTR) pMem); 1386 CHK(result); 1387 } 1388 } 1389 else if (m_eMode == MODE_LIVE_ENCODE) 1390 { 1391 D("going to idle state"); 1392 //SetState(OMX_StateIdle); 1393 OMX_SendCommand(m_hHandle, 1394 OMX_CommandStateSet, 1395 (OMX_U32) OMX_StateIdle, 1396 NULL); 1397 } 1398 1399 int i; 1400 OMX_PARAM_PORTDEFINITIONTYPE portDef; 1401 1402 portDef.nPortIndex = 1; 1403 result = OMX_GetParameter(m_hHandle, OMX_IndexParamPortDefinition, &portDef); 1404 CHK(result); 1405 1406 D("allocating output buffers"); 1407 D("Calling UseBuffer for Output port"); 1408 num_out_buffers = portDef.nBufferCountActual; 1409 for (i = 0; i < portDef.nBufferCountActual; i++) 1410 { 1411 void* pBuff; 1412 1413 pBuff = malloc(portDef.nBufferSize); 1414 D("portDef.nBufferSize = %d ",portDef.nBufferSize); 1415 result = OMX_UseBuffer(m_hHandle, 1416 &m_pOutBuffers[i], 1417 (OMX_U32) PORT_INDEX_OUT, 1418 NULL, 1419 portDef.nBufferSize, 1420 (OMX_U8*) pBuff); 1421 CHK(result); 1422 } 1423 D("allocate done"); 1424 1425 // D("Going to state " # eState"..."); 1426 1427 while (m_eState != OMX_StateIdle) 1428 { 1429 sleep(1); 1430 } 1431 //D("Now in state " # eState); 1432 1433 1434 D("going to executing state"); 1435 SetState(OMX_StateExecuting); 1436 1437 for (i = 0; i < num_out_buffers; i++) 1438 { 1439 D("filling buffer %d", i); 1440 result = OMX_FillThisBuffer(m_hHandle, m_pOutBuffers[i]); 1441 //sleep(1000); 1442 CHK(result); 1443 } 1444 1445 if (m_eMode == MODE_FILE_ENCODE) 1446 { 1447 // encode the first frame to kick off the whole process 1448 VencTest_ReadAndEmpty(m_pInBuffers[0]); 1449 // FBTest_DisplayImage(((PmemBuffer*) m_pInBuffers[0]->pAppPrivate)->fd,0); 1450 } 1451 1452 if (m_eMode == MODE_PROFILE) 1453 { 1454 int i; 1455 1456 // read several frames into memory 1457 D("reading frames into memory"); 1458 for (i = 0; i < num_in_buffers; i++) 1459 { 1460 D("[%d] address 0x%x",i, m_pInBuffers[i]->pBuffer); 1461 read(m_nInFd, 1462 m_pInBuffers[i]->pBuffer, 1463 m_sProfile.nFrameBytes); 1464 1465 } 1466 1467 // FBTest_Initialize(m_sProfile.nFrameWidth, m_sProfile.nFrameHeight); 1468 1469 // loop over the mem-resident frames and encode them 1470 D("beging playing mem-resident frames..."); 1471 for (i = 0; m_nFramePlay == 0 || i < m_nFramePlay; i++) 1472 { 1473 int idx = i % num_in_buffers; 1474 if (m_bInFrameFree[idx] == OMX_FALSE) 1475 { 1476 int j; 1477 E("the expected buffer is not free, but lets find another"); 1478 1479 idx = -1; 1480 1481 // lets see if we can find another free buffer 1482 for (j = 0; j < num_in_buffers; j++) 1483 { 1484 if(m_bInFrameFree[j]) 1485 { 1486 idx = j; 1487 break; 1488 } 1489 } 1490 } 1491 1492 // if we have a free buffer let's encode it 1493 if (idx >= 0) 1494 { 1495 D("encode frame %d...m_pInBuffers[idx]->pBuffer=0x%x", i,m_pInBuffers[idx]->pBuffer); 1496 m_bInFrameFree[idx] = OMX_FALSE; 1497 VencTest_EncodeFrame(m_pInBuffers[idx]->pBuffer, 1498 m_nTimeStamp); 1499 D("display frame %d...", i); 1500 // FBTest_DisplayImage(((PmemBuffer*) m_pInBuffers[idx]->pAppPrivate)->fd,0); 1501 m_nTimeStamp += 1000000 / m_sProfile.nFramerate; 1502 } 1503 else 1504 { 1505 E("wow, no buffers are free, performance " 1506 "is not so good. lets just sleep some more"); 1507 1508 } 1509 D("sleep for %d microsec", 1000000/m_sProfile.nFramerate); 1510 sleep (1000000 / m_sProfile.nFramerate); 1511 } 1512 // FBTest_Exit(); 1513 } 1514 1515 Msg msg; 1516 bool bQuit = false; 1517 while ((m_eMode == MODE_FILE_ENCODE || m_eMode == MODE_LIVE_ENCODE) && 1518 !bQuit) 1519 { 1520 PopMessage(&msg); 1521 switch (msg.id) 1522 { 1523 ////////////////////////////////// 1524 // FRAME IS ENCODED 1525 ////////////////////////////////// 1526 case MSG_ID_INPUT_FRAME_DONE: 1527 /*pthread_mutex_lock(&m_mutex); 1528 ++m_nFrameOut; 1529 if (m_nFrameOut == m_nFramePlay && m_nFramePlay != 0) 1530 { 1531 bQuit = true; 1532 } 1533 pthread_mutex_unlock(&m_mutex);*/ 1534 1535 if (!bQuit && m_eMode == MODE_FILE_ENCODE) 1536 { 1537 D("pushing another frame down to encoder"); 1538 if (VencTest_ReadAndEmpty(msg.data.sBitstreamData.pBuffer)) 1539 { 1540 // we have read the last frame 1541 D("main is exiting..."); 1542 bQuit = true; 1543 } 1544 } 1545 break; 1546 case MSG_ID_OUTPUT_FRAME_DONE: 1547 D("================ writing frame %d = %d bytes to output file", 1548 m_nFrameOut+1, 1549 msg.data.sBitstreamData.pBuffer->nFilledLen); 1550 D("StopEncodeTime=%lld", GetTimeStamp()); 1551 1552 1553 write(m_nOutFd, 1554 msg.data.sBitstreamData.pBuffer->pBuffer, 1555 msg.data.sBitstreamData.pBuffer->nFilledLen); 1556 1557 1558 result = OMX_FillThisBuffer(m_hHandle, 1559 msg.data.sBitstreamData.pBuffer); 1560 1561 if (result != OMX_ErrorNone) 1562 { 1563 CHK(result); 1564 } 1565 1566 pthread_mutex_lock(&m_mutex); 1567 ++m_nFrameOut; 1568 if (m_nFrameOut == m_nFramePlay && m_nFramePlay != 0) 1569 { 1570 bQuit = true; 1571 } 1572 pthread_mutex_unlock(&m_mutex); 1573 break; 1574 1575 default: 1576 E("invalid msg id %d", (int) msg.id); 1577 } // end switch (msg.id) 1578 } // end while (!bQuit) 1579 1580 1581 if (m_eMode == MODE_LIVE_ENCODE) 1582 { 1583 CameraTest_Exit(); 1584 close(m_nOutFd); 1585 } 1586 else if (m_eMode == MODE_FILE_ENCODE || 1587 m_eMode == MODE_PROFILE) 1588 { 1589 // deallocate pmem buffers 1590 for (int i = 0; i < num_in_buffers; i++) 1591 { 1592 PmemFree((OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO*)m_pInBuffers[i]->pAppPrivate, 1593 m_pInBuffers[i]->pBuffer, 1594 m_sProfile.nFrameBytes); 1595 delete (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO*) m_pInBuffers[i]->pAppPrivate; 1596 } 1597 close(m_nInFd); 1598 1599 if (m_eMode == MODE_FILE_ENCODE) 1600 { 1601 close(m_nOutFd); 1602 } 1603 } 1604 1605 if (m_eMode != MODE_PREVIEW) 1606 { 1607 D("exit encoder test"); 1608 VencTest_Exit(); 1609 } 1610 1611 pthread_mutex_destroy(&m_mutex); 1612 pthread_cond_destroy(&m_signal); 1613 1614 /* Time Statistics Logging */ 1615 if(0 != m_sProfile.nFramerate) 1616 { 1617 enc_time_usec = m_nTimeStamp - (1000000 / m_sProfile.nFramerate); 1618 enc_time_sec =enc_time_usec/1000000; 1619 if(0 != enc_time_sec) 1620 { 1621 printf("Total Frame Rate: %f",ebd_cnt/enc_time_sec); 1622 printf("\nEncoder Bitrate :%lf Kbps",(tot_bufsize*8)/(enc_time_sec*1000)); 1623 } 1624 } 1625 else 1626 { 1627 printf("\n\n Encode Time is zero"); 1628 } 1629 printf("\nTotal Number of Frames :%d",ebd_cnt); 1630 printf("\nNumber of dropped frames during encoding:%d\n",ebd_cnt-fbd_cnt); 1631 /* End of Time Statistics Logging */ 1632 1633 D("main has exited"); 1634 return 0; 1635 } 1636