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