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 An Open max test application .... 30 */ 31 32 #define LOG_TAG "OMX-VDEC-TEST" 33 34 #include <stdio.h> 35 #include <string.h> 36 #include <stdlib.h> 37 #include <unistd.h> 38 #include <fcntl.h> 39 #include <sys/types.h> 40 #include <sys/mman.h> 41 #include <time.h> 42 #include <sys/ioctl.h> 43 #include <errno.h> 44 #include <pthread.h> 45 #include <semaphore.h> 46 #include "OMX_QCOMExtns.h" 47 48 #ifdef _ANDROID_ 49 #include <binder/MemoryHeapBase.h> 50 51 extern "C"{ 52 #include<utils/Log.h> 53 } 54 #define DEBUG_PRINT 55 #define DEBUG_PRINT_ERROR 56 57 #else 58 #define DEBUG_PRINT printf 59 #define DEBUG_PRINT_ERROR printf 60 #endif /* _ANDROID_ */ 61 62 #include "OMX_Core.h" 63 #include "OMX_Component.h" 64 #include "OMX_QCOMExtns.h" 65 extern "C" { 66 #include "queue.h" 67 } 68 69 #include <linux/msm_mdp.h> 70 #include <linux/fb.h> 71 //#include "qutility.h" 72 73 #define DEBUG_PRINT(...) printf(__VA_ARGS__) 74 #define DEBUG_PRINT_ERROR(...) printf(__VA_ARGS__) 75 #define DEBUG_PRINT_LOW(...) printf(__VA_ARGS__) 76 77 /************************************************************************/ 78 /* #DEFINES */ 79 /************************************************************************/ 80 #define DELAY 66 81 #define false 0 82 #define true 1 83 #define VOP_START_CODE 0x000001B6 84 #define SHORT_HEADER_START_CODE 0x00008000 85 #define VC1_START_CODE 0x00000100 86 #define VC1_FRAME_START_CODE 0x0000010D 87 #define NUMBER_OF_ARBITRARYBYTES_READ (4 * 1024) 88 #define VC1_SEQ_LAYER_SIZE_WITHOUT_STRUCTC 32 89 #define VC1_SEQ_LAYER_SIZE_V1_WITHOUT_STRUCTC 16 90 91 #define CONFIG_VERSION_SIZE(param) \ 92 param.nVersion.nVersion = CURRENT_OMX_SPEC_VERSION;\ 93 param.nSize = sizeof(param); 94 95 #define FAILED(result) (result != OMX_ErrorNone) 96 97 #define SUCCEEDED(result) (result == OMX_ErrorNone) 98 #define SWAPBYTES(ptrA, ptrB) { char t = *ptrA; *ptrA = *ptrB; *ptrB = t;} 99 #define SIZE_NAL_FIELD_MAX 4 100 #define MDP_DEINTERLACE 0x80000000 101 102 /************************************************************************/ 103 /* GLOBAL DECLARATIONS */ 104 /************************************************************************/ 105 #ifdef _ANDROID_ 106 using namespace android; 107 #endif 108 109 typedef enum { 110 CODEC_FORMAT_H264 = 1, 111 CODEC_FORMAT_MP4, 112 CODEC_FORMAT_H263, 113 CODEC_FORMAT_VC1, 114 CODEC_FORMAT_MAX = CODEC_FORMAT_VC1 115 } codec_format; 116 117 typedef enum { 118 FILE_TYPE_DAT_PER_AU = 1, 119 FILE_TYPE_ARBITRARY_BYTES, 120 FILE_TYPE_COMMON_CODEC_MAX, 121 122 FILE_TYPE_START_OF_H264_SPECIFIC = 10, 123 FILE_TYPE_264_NAL_SIZE_LENGTH = FILE_TYPE_START_OF_H264_SPECIFIC, 124 125 FILE_TYPE_START_OF_MP4_SPECIFIC = 20, 126 FILE_TYPE_PICTURE_START_CODE = FILE_TYPE_START_OF_MP4_SPECIFIC, 127 128 FILE_TYPE_START_OF_VC1_SPECIFIC = 30, 129 FILE_TYPE_RCV = FILE_TYPE_START_OF_VC1_SPECIFIC, 130 FILE_TYPE_VC1 131 } file_type; 132 133 typedef enum { 134 GOOD_STATE = 0, 135 PORT_SETTING_CHANGE_STATE, 136 ERROR_STATE, 137 INVALID_STATE 138 } test_status; 139 140 typedef enum { 141 FREE_HANDLE_AT_LOADED = 1, 142 FREE_HANDLE_AT_IDLE, 143 FREE_HANDLE_AT_EXECUTING, 144 FREE_HANDLE_AT_PAUSE 145 } freeHandle_test; 146 147 static int (*Read_Buffer)(OMX_BUFFERHEADERTYPE *pBufHdr ); 148 149 FILE * inputBufferFile; 150 FILE * outputBufferFile; 151 FILE * seqFile; 152 int takeYuvLog = 0; 153 int displayWindow = 0; 154 int realtime_display = 0; 155 struct timeval t_avsync={0,0}; 156 157 Queue *etb_queue = NULL; 158 Queue *fbd_queue = NULL; 159 160 pthread_t ebd_thread_id; 161 pthread_t fbd_thread_id; 162 void* ebd_thread(void*); 163 void* fbd_thread(void*); 164 165 pthread_mutex_t etb_lock; 166 pthread_mutex_t fbd_lock; 167 pthread_mutex_t lock; 168 pthread_cond_t cond; 169 pthread_mutex_t elock; 170 pthread_cond_t econd; 171 pthread_cond_t fcond; 172 pthread_mutex_t eos_lock; 173 pthread_cond_t eos_cond; 174 175 sem_t etb_sem; 176 sem_t fbd_sem; 177 sem_t seq_sem; 178 sem_t in_flush_sem, out_flush_sem; 179 180 OMX_PARAM_PORTDEFINITIONTYPE portFmt; 181 OMX_PORT_PARAM_TYPE portParam; 182 OMX_ERRORTYPE error; 183 184 #define CLR_KEY 0xe8fd 185 #define COLOR_BLACK_RGBA_8888 0x00000000 186 #define FRAMEBUFFER_32 187 188 static int fb_fd = -1; 189 static struct fb_var_screeninfo vinfo; 190 static struct fb_fix_screeninfo finfo; 191 static int vid_buf_front_id; 192 int overlay_fb(struct OMX_BUFFERHEADERTYPE *pBufHdr); 193 void overlay_set(); 194 void overlay_unset(); 195 void render_fb(struct OMX_BUFFERHEADERTYPE *pBufHdr); 196 197 /************************************************************************/ 198 /* GLOBAL INIT */ 199 /************************************************************************/ 200 unsigned int input_buf_cnt = 0; 201 int height =0, width =0; 202 int sliceheight = 0, stride = 0; 203 int used_ip_buf_cnt = 0; 204 volatile int event_is_done = 0; 205 int ebd_cnt, fbd_cnt; 206 int bInputEosReached = 0; 207 int bOutputEosReached = 0; 208 char in_filename[512]; 209 char seq_file_name[512]; 210 unsigned char seq_enabled = 0, flush_in_progress = 0; 211 unsigned int cmd_data = 0, etb_count = 0;; 212 213 char curr_seq_command[100]; 214 int timeStampLfile = 0; 215 int timestampInterval = 33333; 216 codec_format codec_format_option; 217 file_type file_type_option; 218 freeHandle_test freeHandle_option; 219 int nalSize; 220 int sent_disabled = 0; 221 int waitForPortSettingsChanged = 1; 222 test_status currentStatus = GOOD_STATE; 223 224 //* OMX Spec Version supported by the wrappers. Version = 1.1 */ 225 const OMX_U32 CURRENT_OMX_SPEC_VERSION = 0x00000101; 226 OMX_COMPONENTTYPE* dec_handle = 0; 227 228 OMX_BUFFERHEADERTYPE **pInputBufHdrs = NULL; 229 OMX_BUFFERHEADERTYPE **pOutYUVBufHdrs= NULL; 230 231 int rcv_v1=0; 232 233 /* Performance related variable*/ 234 //QPERF_INIT(render_fb); 235 //QPERF_INIT(client_decode); 236 237 /************************************************************************/ 238 /* GLOBAL FUNC DECL */ 239 /************************************************************************/ 240 int Init_Decoder(); 241 int Play_Decoder(); 242 int run_tests(); 243 244 /**************************************************************************/ 245 /* STATIC DECLARATIONS */ 246 /**************************************************************************/ 247 static int video_playback_count = 1; 248 static int open_video_file (); 249 static int Read_Buffer_From_DAT_File(OMX_BUFFERHEADERTYPE *pBufHdr ); 250 static int Read_Buffer_ArbitraryBytes(OMX_BUFFERHEADERTYPE *pBufHdr); 251 static int Read_Buffer_From_Vop_Start_Code_File(OMX_BUFFERHEADERTYPE *pBufHdr); 252 static int Read_Buffer_From_Size_Nal(OMX_BUFFERHEADERTYPE *pBufHdr); 253 static int Read_Buffer_From_RCV_File_Seq_Layer(OMX_BUFFERHEADERTYPE *pBufHdr); 254 static int Read_Buffer_From_RCV_File(OMX_BUFFERHEADERTYPE *pBufHdr); 255 static int Read_Buffer_From_VC1_File(OMX_BUFFERHEADERTYPE *pBufHdr); 256 257 static OMX_ERRORTYPE Allocate_Buffer ( OMX_COMPONENTTYPE *dec_handle, 258 OMX_BUFFERHEADERTYPE ***pBufHdrs, 259 OMX_U32 nPortIndex, 260 long bufCntMin, long bufSize); 261 262 263 static OMX_ERRORTYPE EventHandler(OMX_IN OMX_HANDLETYPE hComponent, 264 OMX_IN OMX_PTR pAppData, 265 OMX_IN OMX_EVENTTYPE eEvent, 266 OMX_IN OMX_U32 nData1, OMX_IN OMX_U32 nData2, 267 OMX_IN OMX_PTR pEventData); 268 static OMX_ERRORTYPE EmptyBufferDone(OMX_IN OMX_HANDLETYPE hComponent, 269 OMX_IN OMX_PTR pAppData, 270 OMX_IN OMX_BUFFERHEADERTYPE* pBuffer); 271 static OMX_ERRORTYPE FillBufferDone(OMX_OUT OMX_HANDLETYPE hComponent, 272 OMX_OUT OMX_PTR pAppData, 273 OMX_OUT OMX_BUFFERHEADERTYPE* pBuffer); 274 275 static void do_freeHandle_and_clean_up(bool isDueToError); 276 277 /*static usecs_t get_time(void) 278 { 279 struct timeval tv; 280 gettimeofday(&tv, 0); 281 return ((usecs_t)tv.tv_usec) + 282 (((usecs_t)tv.tv_sec) * ((usecs_t)1000000)); 283 }*/ 284 285 286 void wait_for_event(void) 287 { 288 DEBUG_PRINT("Waiting for event\n"); 289 pthread_mutex_lock(&lock); 290 while (event_is_done == 0) { 291 pthread_cond_wait(&cond, &lock); 292 } 293 event_is_done = 0; 294 pthread_mutex_unlock(&lock); 295 DEBUG_PRINT("Running .... get the event\n"); 296 } 297 298 void event_complete(void ) 299 { 300 pthread_mutex_lock(&lock); 301 if (event_is_done == 0) { 302 event_is_done = 1; 303 pthread_cond_broadcast(&cond); 304 } 305 pthread_mutex_unlock(&lock); 306 } 307 int get_next_command(FILE *seq_file) 308 { 309 int i = -1; 310 do{ 311 i++; 312 if(fread(&curr_seq_command[i], 1, 1, seq_file) != 1) 313 return -1; 314 }while(curr_seq_command[i] != '\n'); 315 curr_seq_command[i] = 0; 316 printf("\n cmd_str = %s", curr_seq_command); 317 return 0; 318 } 319 320 void process_current_command(const char *seq_command) 321 { 322 char *data_str = NULL; 323 unsigned int data = 0, bufCnt = 0, i = 0; 324 int frameSize; 325 OMX_ERRORTYPE ret; 326 327 if(strstr(seq_command, "pause") == seq_command) 328 { 329 printf("\n\n $$$$$ PAUSE $$$$$"); 330 data_str = (char*)seq_command + strlen("pause") + 1; 331 data = atoi(data_str); 332 printf("\n After frame number %u", data); 333 cmd_data = data; 334 sem_wait(&seq_sem); 335 printf("\n Sending PAUSE cmd to OMX compt"); 336 OMX_SendCommand(dec_handle, OMX_CommandStateSet, OMX_StatePause,0); 337 wait_for_event(); 338 printf("\n EventHandler for PAUSE DONE"); 339 } 340 else if(strstr(seq_command, "sleep") == seq_command) 341 { 342 printf("\n\n $$$$$ SLEEP $$$$$"); 343 data_str = (char*)seq_command + strlen("sleep") + 1; 344 data = atoi(data_str); 345 printf("\n Sleep Time = %u ms", data); 346 usleep(data*1000); 347 } 348 else if(strstr(seq_command, "resume") == seq_command) 349 { 350 printf("\n\n $$$$$ RESUME $$$$$"); 351 printf("\n Immediate effect"); 352 printf("\n Sending PAUSE cmd to OMX compt"); 353 OMX_SendCommand(dec_handle, OMX_CommandStateSet, OMX_StateExecuting,0); 354 wait_for_event(); 355 printf("\n EventHandler for RESUME DONE"); 356 } 357 else if(strstr(seq_command, "flush") == seq_command) 358 { 359 printf("\n\n $$$$$ FLUSH $$$$$"); 360 data_str = (char*)seq_command + strlen("flush") + 1; 361 data = atoi(data_str); 362 printf("\n After frame number %u", data); 363 cmd_data = data; 364 sem_wait(&seq_sem); 365 printf("\n Sending FLUSH cmd to OMX compt"); 366 flush_in_progress = 1; 367 OMX_SendCommand(dec_handle, OMX_CommandFlush, OMX_ALL, 0); 368 wait_for_event(); 369 flush_in_progress = 0; 370 printf("\n EventHandler for FLUSH DONE"); 371 printf("\n Post EBD_thread flush sem"); 372 sem_post(&in_flush_sem); 373 printf("\n Post FBD_thread flush sem"); 374 sem_post(&out_flush_sem); 375 } 376 else 377 { 378 printf("\n\n $$$$$ INVALID CMD $$$$$"); 379 printf("\n seq_command[%s] is invalid", seq_command); 380 seq_enabled = 0; 381 } 382 } 383 384 void* ebd_thread(void* pArg) 385 { 386 while(currentStatus != INVALID_STATE) 387 { 388 int readBytes =0; 389 OMX_BUFFERHEADERTYPE* pBuffer = NULL; 390 391 if(flush_in_progress) 392 { 393 printf("\n EBD_thread flush wait start"); 394 sem_wait(&in_flush_sem); 395 printf("\n EBD_thread flush wait complete"); 396 } 397 398 sem_wait(&etb_sem); 399 pthread_mutex_lock(&etb_lock); 400 pBuffer = (OMX_BUFFERHEADERTYPE *) pop(etb_queue); 401 pthread_mutex_unlock(&etb_lock); 402 if(pBuffer == NULL) 403 { 404 DEBUG_PRINT_ERROR("Error - No etb pBuffer to dequeue\n"); 405 continue; 406 } 407 408 pBuffer->nOffset = 0; 409 if((readBytes = Read_Buffer(pBuffer)) > 0) { 410 pBuffer->nFilledLen = readBytes; 411 OMX_EmptyThisBuffer(dec_handle,pBuffer); 412 etb_count++; 413 if(cmd_data == etb_count) 414 { 415 sem_post(&seq_sem); 416 printf("\n Posted seq_sem"); 417 } 418 } 419 else 420 { 421 pBuffer->nFlags |= OMX_BUFFERFLAG_EOS; 422 bInputEosReached = true; 423 pBuffer->nFilledLen = readBytes; 424 OMX_EmptyThisBuffer(dec_handle,pBuffer); 425 DEBUG_PRINT("EBD::Either EOS or Some Error while reading file\n"); 426 etb_count++; 427 if(cmd_data == etb_count) 428 { 429 sem_post(&seq_sem); 430 printf("\n Posted seq_sem"); 431 } 432 break; 433 } 434 } 435 return NULL; 436 } 437 438 void* fbd_thread(void* pArg) 439 { 440 while(currentStatus != INVALID_STATE) 441 { 442 long current_avsync_time = 0, delta_time = 0; 443 int canDisplay = 1; 444 static int contigous_drop_frame = 0; 445 static long base_avsync_time = 0; 446 static long base_timestamp = 0; 447 long lipsync_time = 250000; 448 int bytes_written = 0; 449 OMX_BUFFERHEADERTYPE *pBuffer; 450 451 if(flush_in_progress) 452 { 453 printf("\n FBD_thread flush wait start"); 454 sem_wait(&out_flush_sem); 455 printf("\n FBD_thread flush wait complete"); 456 } 457 458 sem_wait(&fbd_sem); 459 DEBUG_PRINT("Inside %s fbd_cnt[%d] \n", __FUNCTION__, fbd_cnt); 460 461 fbd_cnt++; 462 pthread_mutex_lock(&fbd_lock); 463 pBuffer = (OMX_BUFFERHEADERTYPE *) pop(fbd_queue); 464 pthread_mutex_unlock(&fbd_lock); 465 if (pBuffer == NULL) 466 { 467 DEBUG_PRINT("Error - No pBuffer to dequeue\n"); 468 continue; 469 } 470 471 /********************************************* 472 Write the output of the decoder to the file. 473 *********************************************/ 474 475 if (sent_disabled) 476 { 477 DEBUG_PRINT("Ignoring FillBufferDone\n"); 478 continue; 479 } 480 481 if (realtime_display) 482 { 483 if(!gettimeofday(&t_avsync,NULL)) 484 { 485 current_avsync_time =(t_avsync.tv_sec*1000000)+t_avsync.tv_usec; 486 } 487 488 if (base_avsync_time != 0) 489 { 490 pthread_mutex_lock(&fbd_lock); 491 delta_time = (current_avsync_time - base_avsync_time) - ((long)pBuffer->nTimeStamp - base_timestamp); 492 if (delta_time < 0 ) 493 { 494 DEBUG_PRINT_ERROR("Sleep %d us. AV Sync time is left behind\n", 495 -delta_time); 496 usleep(-delta_time); 497 canDisplay = 1; 498 } 499 else if ((delta_time>lipsync_time) && (contigous_drop_frame < 6)) 500 { 501 DEBUG_PRINT_ERROR("Error - Drop the frame at the renderer. Video frame with ts %lu usec behind by %ld usec" 502 ", pBuffer->nFilledLen %u\n", 503 (unsigned long)pBuffer->nTimeStamp, delta_time, pBuffer->nFilledLen); 504 canDisplay = 0; 505 contigous_drop_frame++; 506 } 507 else 508 { 509 canDisplay = 1; 510 } 511 pthread_mutex_unlock(&fbd_lock); 512 } 513 else 514 { 515 base_avsync_time = current_avsync_time; 516 base_timestamp = (long)pBuffer->nTimeStamp; 517 } 518 } 519 520 if (!flush_in_progress && takeYuvLog) { 521 pthread_mutex_lock(&fbd_lock); 522 bytes_written = fwrite((const char *)pBuffer->pBuffer, 523 pBuffer->nFilledLen,1,outputBufferFile); 524 pthread_mutex_unlock(&fbd_lock); 525 if (bytes_written < 0) { 526 DEBUG_PRINT("\nFillBufferDone: Failed to write to the file\n"); 527 } 528 else { 529 DEBUG_PRINT("\nFillBufferDone: Wrote %d YUV bytes to the file\n", 530 bytes_written); 531 } 532 } 533 534 /********************************************************************/ 535 /* De-Initializing the open max and relasing the buffers and */ 536 /* closing the files.*/ 537 /********************************************************************/ 538 if (pBuffer->nFlags & OMX_BUFFERFLAG_EOS ) { 539 DEBUG_PRINT("***************************************************\n"); 540 DEBUG_PRINT("FillBufferDone: End Of Stream Reached\n"); 541 DEBUG_PRINT("***************************************************\n"); 542 pthread_mutex_lock(&eos_lock); 543 bOutputEosReached = true; 544 pthread_cond_broadcast(&eos_cond); 545 pthread_mutex_unlock(&eos_lock); 546 //QPERF_END(client_decode); 547 //QPERF_SET_ITERATION(client_decode, fbd_cnt); 548 DEBUG_PRINT("***************************************************\n"); 549 DEBUG_PRINT("FBD_THREAD bOutputEosReached %d\n",bOutputEosReached); 550 break; 551 } 552 OMX_FillThisBuffer(dec_handle, pBuffer); 553 } 554 return NULL; 555 } 556 557 OMX_ERRORTYPE EventHandler(OMX_IN OMX_HANDLETYPE hComponent, 558 OMX_IN OMX_PTR pAppData, 559 OMX_IN OMX_EVENTTYPE eEvent, 560 OMX_IN OMX_U32 nData1, OMX_IN OMX_U32 nData2, 561 OMX_IN OMX_PTR pEventData) 562 { 563 DEBUG_PRINT("Function %s \n", __FUNCTION__); 564 565 switch(eEvent) { 566 case OMX_EventCmdComplete: 567 DEBUG_PRINT("\n OMX_EventCmdComplete \n"); 568 // check nData1 for DISABLE event 569 if(OMX_CommandPortDisable == (OMX_COMMANDTYPE)nData1) 570 { 571 DEBUG_PRINT("*********************************************\n"); 572 DEBUG_PRINT("Recieved DISABLE Event Command Complete[%d]\n",nData2); 573 DEBUG_PRINT("*********************************************\n"); 574 sent_disabled = 0; 575 } 576 else if(OMX_CommandPortEnable == (OMX_COMMANDTYPE)nData1) 577 { 578 DEBUG_PRINT("*********************************************\n"); 579 DEBUG_PRINT("Recieved ENABLE Event Command Complete[%d]\n",nData2); 580 DEBUG_PRINT("*********************************************\n"); 581 } 582 currentStatus = GOOD_STATE; 583 event_complete(); 584 break; 585 586 case OMX_EventError: 587 DEBUG_PRINT("OMX_EventError \n"); 588 currentStatus = ERROR_STATE; 589 if (OMX_ErrorInvalidState == (OMX_ERRORTYPE)nData1 || 590 OMX_ErrorHardware == (OMX_ERRORTYPE)nData1) 591 { 592 DEBUG_PRINT("Invalid State or hardware error \n"); 593 currentStatus = INVALID_STATE; 594 if(event_is_done == 0) 595 { 596 DEBUG_PRINT("Event error in the middle of Decode \n"); 597 pthread_mutex_lock(&eos_lock); 598 bOutputEosReached = true; 599 pthread_cond_broadcast(&eos_cond); 600 pthread_mutex_unlock(&eos_lock); 601 602 } 603 } 604 605 event_complete(); 606 break; 607 case OMX_EventPortSettingsChanged: 608 DEBUG_PRINT("OMX_EventPortSettingsChanged port[%d]\n",nData1); 609 waitForPortSettingsChanged = 0; 610 currentStatus = PORT_SETTING_CHANGE_STATE; 611 // reset the event 612 event_complete(); 613 break; 614 615 default: 616 DEBUG_PRINT_ERROR("ERROR - Unknown Event \n"); 617 break; 618 } 619 return OMX_ErrorNone; 620 } 621 622 OMX_ERRORTYPE EmptyBufferDone(OMX_IN OMX_HANDLETYPE hComponent, 623 OMX_IN OMX_PTR pAppData, 624 OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) 625 { 626 int readBytes =0; int bufCnt=0; 627 OMX_ERRORTYPE result; 628 629 DEBUG_PRINT("Function %s cnt[%d]\n", __FUNCTION__, ebd_cnt); 630 ebd_cnt++; 631 632 633 if(bInputEosReached) { 634 DEBUG_PRINT("*****EBD:Input EoS Reached************\n"); 635 return OMX_ErrorNone; 636 } 637 638 pthread_mutex_lock(&etb_lock); 639 if(push(etb_queue, (void *) pBuffer) < 0) 640 { 641 DEBUG_PRINT_ERROR("Error in enqueue ebd data\n"); 642 return OMX_ErrorUndefined; 643 } 644 pthread_mutex_unlock(&etb_lock); 645 sem_post(&etb_sem); 646 647 return OMX_ErrorNone; 648 } 649 650 OMX_ERRORTYPE FillBufferDone(OMX_OUT OMX_HANDLETYPE hComponent, 651 OMX_OUT OMX_PTR pAppData, 652 OMX_OUT OMX_BUFFERHEADERTYPE* pBuffer) 653 { 654 DEBUG_PRINT("Inside %s callback_count[%d] \n", __FUNCTION__, fbd_cnt); 655 656 /* Test app will assume there is a dynamic port setting 657 * In case that there is no dynamic port setting, OMX will not call event cb, 658 * instead OMX will send empty this buffer directly and we need to clear an event here 659 */ 660 if(waitForPortSettingsChanged) 661 { 662 currentStatus = GOOD_STATE; 663 waitForPortSettingsChanged = 0; 664 665 event_complete(); 666 } 667 668 if(!sent_disabled) 669 { 670 pthread_mutex_lock(&fbd_lock); 671 if(push(fbd_queue, (void *)pBuffer) < 0) 672 { 673 DEBUG_PRINT_ERROR("Error in enqueueing fbd_data\n"); 674 return OMX_ErrorUndefined; 675 } 676 pthread_mutex_unlock(&fbd_lock); 677 sem_post(&fbd_sem); 678 } 679 return OMX_ErrorNone; 680 } 681 682 int main(int argc, char **argv) 683 { 684 int i=0; 685 int bufCnt=0; 686 int num=0; 687 int outputOption = 0; 688 int test_option = 0; 689 OMX_ERRORTYPE result; 690 691 if (argc < 2) 692 { 693 printf("To use it: ./mm-vdec-omx-test <clip location> \n"); 694 printf("Command line argument is also available\n"); 695 return -1; 696 } 697 698 strncpy(in_filename, argv[1], strlen(argv[1])+1); 699 700 if(argc > 5) 701 { 702 codec_format_option = (codec_format)atoi(argv[2]); 703 file_type_option = (file_type)atoi(argv[3]); 704 } 705 else 706 { 707 printf("Command line argument is available\n"); 708 printf("To use it: ./mm-vdec-omx-test <clip location> <codec_type> \n"); 709 printf(" <input_type: 1. per AU(.dat), 2. arbitrary, 3.per NAL/frame>\n"); 710 printf(" <output_type> <test_case> <size_nal if H264>\n\n\n"); 711 712 printf(" *********************************************\n"); 713 printf(" ENTER THE TEST CASE YOU WOULD LIKE TO EXECUTE\n"); 714 printf(" *********************************************\n"); 715 printf(" 1--> H264\n"); 716 printf(" 2--> MP4\n"); 717 printf(" 3--> H263\n"); 718 printf(" 4--> VC1\n"); 719 fflush(stdin); 720 scanf("%d", (int *)&codec_format_option); 721 fflush(stdin); 722 723 if (codec_format_option > CODEC_FORMAT_MAX) 724 { 725 printf(" Wrong test case...[%d] \n", codec_format_option); 726 return -1; 727 } 728 729 printf(" *********************************************\n"); 730 printf(" ENTER THE TEST CASE YOU WOULD LIKE TO EXECUTE\n"); 731 printf(" *********************************************\n"); 732 printf(" 1--> PER ACCESS UNIT CLIP (.dat). Clip only available for H264 and Mpeg4\n"); 733 printf(" 2--> ARBITRARY BYTES (need .264/.264c/.mv4/.263/.rcv/.vc1)\n"); 734 if (codec_format_option == CODEC_FORMAT_H264) 735 { 736 printf(" 3--> NAL LENGTH SIZE CLIP (.264c)\n"); 737 } 738 else if ( (codec_format_option == CODEC_FORMAT_MP4) || (codec_format_option == CODEC_FORMAT_H263) ) 739 { 740 printf(" 3--> MP4 VOP or H263 P0 SHORT HEADER START CODE CLIP (.m4v or .263)\n"); 741 } 742 else if (codec_format_option == CODEC_FORMAT_VC1) 743 { 744 printf(" 3--> VC1 clip Simple/Main Profile (.rcv)\n"); 745 printf(" 4--> VC1 clip Advance Profile (.vc1)\n"); 746 } 747 fflush(stdin); 748 scanf("%d", (int *)&file_type_option); 749 fflush(stdin); 750 } 751 752 if (file_type_option >= FILE_TYPE_COMMON_CODEC_MAX) 753 { 754 switch (codec_format_option) 755 { 756 case CODEC_FORMAT_H264: 757 file_type_option = (file_type)(FILE_TYPE_START_OF_H264_SPECIFIC + file_type_option - FILE_TYPE_COMMON_CODEC_MAX); 758 break; 759 case CODEC_FORMAT_MP4: 760 case CODEC_FORMAT_H263: 761 file_type_option = (file_type)(FILE_TYPE_START_OF_MP4_SPECIFIC + file_type_option - FILE_TYPE_COMMON_CODEC_MAX); 762 break; 763 case CODEC_FORMAT_VC1: 764 file_type_option = (file_type)(FILE_TYPE_START_OF_VC1_SPECIFIC + file_type_option - FILE_TYPE_COMMON_CODEC_MAX); 765 break; 766 default: 767 printf("Error: Unknown code %d\n", codec_format_option); 768 } 769 } 770 771 if(argc > 5) 772 { 773 outputOption = atoi(argv[4]); 774 test_option = atoi(argv[5]); 775 if (argc > 6) 776 { 777 nalSize = atoi(argv[6]); 778 } 779 else 780 { 781 nalSize = 0; 782 } 783 784 if(argc > 7) 785 { 786 displayWindow = atoi(argv[7]); 787 if(displayWindow > 0) 788 { 789 printf(" Curently display window 0 only supported; ignoring other values\n"); 790 displayWindow = 0; 791 } 792 } 793 else 794 { 795 displayWindow = 0; 796 } 797 798 if(file_type_option == FILE_TYPE_PICTURE_START_CODE || 799 file_type_option == FILE_TYPE_RCV || 800 (file_type_option == FILE_TYPE_VC1 && argc > 8)) 801 { 802 realtime_display = atoi(argv[8]); 803 } 804 805 if(realtime_display) 806 { 807 takeYuvLog = 0; 808 if(argc > 9) 809 { 810 int fps = atoi(argv[9]); 811 timestampInterval = 1000000/fps; 812 } 813 else if(argc > 10) 814 { 815 strncpy(seq_file_name, argv[10], strlen(argv[10])+1); 816 } 817 } 818 else 819 { 820 if(argc > 9) 821 { 822 strncpy(seq_file_name, argv[9], strlen(argv[9])+1); 823 } 824 } 825 height=144;width=176; // Assume Default as QCIF 826 sliceheight = 144; 827 stride = 176; 828 printf("Executing DynPortReconfig QCIF 144 x 176 \n"); 829 } 830 else 831 { 832 int fps = 30; 833 switch(file_type_option) 834 { 835 case FILE_TYPE_DAT_PER_AU: 836 case FILE_TYPE_ARBITRARY_BYTES: 837 case FILE_TYPE_264_NAL_SIZE_LENGTH: 838 case FILE_TYPE_PICTURE_START_CODE: 839 case FILE_TYPE_RCV: 840 case FILE_TYPE_VC1: 841 { 842 nalSize = 0; 843 if ((file_type_option == FILE_TYPE_264_NAL_SIZE_LENGTH) || 844 ((codec_format_option == CODEC_FORMAT_H264) && (file_type_option == FILE_TYPE_ARBITRARY_BYTES))) 845 { 846 printf(" Enter Nal length size [2 or 4] \n"); 847 if (file_type_option == FILE_TYPE_ARBITRARY_BYTES) 848 { 849 printf(" Enter 0 if it is a start code based clip\n"); 850 } 851 scanf("%d", &nalSize); 852 if ((file_type_option == FILE_TYPE_264_NAL_SIZE_LENGTH) && 853 (nalSize == 0)) 854 { 855 printf("Error - Can't pass NAL length size = 0\n"); 856 return -1; 857 } 858 } 859 860 height=144;width=176; // Assume Default as QCIF 861 printf("Executing DynPortReconfig QCIF 144 x 176 \n"); 862 break; 863 } 864 865 default: 866 { 867 printf(" Wrong test case...[%d] \n",file_type_option); 868 return -1; 869 } 870 } 871 872 printf(" *********************************************\n"); 873 printf(" Output buffer option:\n"); 874 printf(" *********************************************\n"); 875 printf(" 0 --> No display and no YUV log\n"); 876 printf(" 1 --> Diplay YUV\n"); 877 printf(" 2 --> Take YUV log\n"); 878 printf(" 3 --> Display YUV and take YUV log\n"); 879 fflush(stdin); 880 scanf("%d", &outputOption); 881 fflush(stdin); 882 883 printf(" *********************************************\n"); 884 printf(" ENTER THE TEST CASE YOU WOULD LIKE TO EXECUTE\n"); 885 printf(" *********************************************\n"); 886 printf(" 1 --> Play the clip till the end\n"); 887 printf(" 2 --> Run compliance test. Do NOT expect any display for most option. \n"); 888 printf(" Please only see \"TEST SUCCESSFULL\" to indidcate test pass\n"); 889 fflush(stdin); 890 scanf("%d", &test_option); 891 fflush(stdin); 892 893 printf(" *********************************************\n"); 894 printf(" ENTER THE PORTION OF DISPLAY TO USE\n"); 895 printf(" *********************************************\n"); 896 printf(" 0 --> Entire Screen\n"); 897 printf(" 1 --> 1/4 th of the screen starting from top left corner to middle \n"); 898 printf(" 2 --> 1/4 th of the screen starting from middle to top right corner \n"); 899 printf(" 3 --> 1/4 th of the screen starting from middle to bottom left \n"); 900 printf(" 4 --> 1/4 th of the screen starting from middle to bottom right \n"); 901 printf(" Please only see \"TEST SUCCESSFULL\" to indidcate test pass\n"); 902 fflush(stdin); 903 scanf("%d", &displayWindow); 904 fflush(stdin); 905 906 if(displayWindow > 0) 907 { 908 printf(" Curently display window 0 only supported; ignoring other values\n"); 909 displayWindow = 0; 910 } 911 912 if((file_type_option == FILE_TYPE_PICTURE_START_CODE) || 913 (file_type_option == FILE_TYPE_RCV) || 914 (file_type_option == FILE_TYPE_VC1)) 915 { 916 printf(" *********************************************\n"); 917 printf(" DO YOU WANT TEST APP TO RENDER in Real time \n"); 918 printf(" 0 --> NO\n 1 --> YES\n"); 919 printf(" Warning: For H264, it require one NAL per frame clip.\n"); 920 printf(" For Arbitrary bytes option, Real time display is not recommended\n"); 921 printf(" *********************************************\n"); 922 fflush(stdin); 923 scanf("%d", &realtime_display); 924 fflush(stdin); 925 } 926 927 928 if (realtime_display) 929 { 930 printf(" *********************************************\n"); 931 printf(" ENTER THE CLIP FPS\n"); 932 printf(" Exception: Timestamp extracted from clips will be used.\n"); 933 printf(" *********************************************\n"); 934 fflush(stdin); 935 scanf("%d", &fps); 936 fflush(stdin); 937 timestampInterval = 1000000/fps; 938 } 939 printf(" *********************************************\n"); 940 printf(" ENTER THE SEQ FILE NAME\n"); 941 printf(" *********************************************\n"); 942 fflush(stdin); 943 scanf("%[^\n]", (char *)&seq_file_name); 944 fflush(stdin); 945 } 946 947 if (outputOption == 0) 948 { 949 takeYuvLog = 0; 950 realtime_display = 0; 951 } 952 else if (outputOption == 1) 953 { 954 printf("Sorry, cannot display to screen\n"); 955 return -1; 956 } 957 else if (outputOption == 2) 958 { 959 takeYuvLog = 1; 960 realtime_display = 0; 961 } 962 else if (outputOption == 3) 963 { 964 printf("Sorry, cannot display to screen\n"); 965 return -1; 966 } 967 else 968 { 969 printf("Wrong option. Assume you want to take YUV log\n"); 970 takeYuvLog = 1; 971 realtime_display = 0; 972 } 973 974 if (test_option == 2) 975 { 976 printf(" *********************************************\n"); 977 printf(" ENTER THE COMPLIANCE TEST YOU WOULD LIKE TO EXECUTE\n"); 978 printf(" *********************************************\n"); 979 printf(" 1 --> Call Free Handle at the OMX_StateLoaded\n"); 980 printf(" 2 --> Call Free Handle at the OMX_StateIdle\n"); 981 printf(" 3 --> Call Free Handle at the OMX_StateExecuting\n"); 982 printf(" 4 --> Call Free Handle at the OMX_StatePause\n"); 983 fflush(stdin); 984 scanf("%d", (int *)&freeHandle_option); 985 fflush(stdin); 986 } 987 else 988 { 989 freeHandle_option = (freeHandle_test)0; 990 } 991 992 printf("Input values: inputfilename[%s]\n", in_filename); 993 printf("*******************************************************\n"); 994 pthread_cond_init(&cond, 0); 995 pthread_cond_init(&eos_cond, 0); 996 pthread_mutex_init(&eos_lock, 0); 997 pthread_mutex_init(&lock, 0); 998 pthread_mutex_init(&etb_lock, 0); 999 pthread_mutex_init(&fbd_lock, 0); 1000 if (-1 == sem_init(&etb_sem, 0, 0)) 1001 { 1002 printf("Error - sem_init failed %d\n", errno); 1003 } 1004 if (-1 == sem_init(&fbd_sem, 0, 0)) 1005 { 1006 printf("Error - sem_init failed %d\n", errno); 1007 } 1008 if (-1 == sem_init(&seq_sem, 0, 0)) 1009 { 1010 printf("Error - sem_init failed %d\n", errno); 1011 } 1012 if (-1 == sem_init(&in_flush_sem, 0, 0)) 1013 { 1014 printf("Error - sem_init failed %d\n", errno); 1015 } 1016 if (-1 == sem_init(&out_flush_sem, 0, 0)) 1017 { 1018 printf("Error - sem_init failed %d\n", errno); 1019 } 1020 etb_queue = alloc_queue(); 1021 if (etb_queue == NULL) 1022 { 1023 printf("\n Error in Creating etb_queue\n"); 1024 return -1; 1025 } 1026 1027 fbd_queue = alloc_queue(); 1028 if (fbd_queue == NULL) 1029 { 1030 printf("\n Error in Creating fbd_queue\n"); 1031 free_queue(etb_queue); 1032 return -1; 1033 } 1034 1035 if(0 != pthread_create(&fbd_thread_id, NULL, fbd_thread, NULL)) 1036 { 1037 printf("\n Error in Creating fbd_thread \n"); 1038 free_queue(etb_queue); 1039 free_queue(fbd_queue); 1040 return -1; 1041 } 1042 1043 run_tests(); 1044 pthread_cond_destroy(&cond); 1045 pthread_mutex_destroy(&lock); 1046 pthread_mutex_destroy(&etb_lock); 1047 pthread_mutex_destroy(&fbd_lock); 1048 pthread_cond_destroy(&eos_cond); 1049 pthread_mutex_destroy(&eos_lock); 1050 if (-1 == sem_destroy(&etb_sem)) 1051 { 1052 DEBUG_PRINT_ERROR("Error - sem_destroy failed %d\n", errno); 1053 } 1054 if (-1 == sem_destroy(&fbd_sem)) 1055 { 1056 DEBUG_PRINT_ERROR("Error - sem_destroy failed %d\n", errno); 1057 } 1058 if (-1 == sem_destroy(&seq_sem)) 1059 { 1060 DEBUG_PRINT_ERROR("Error - sem_destroy failed %d\n", errno); 1061 } 1062 if (-1 == sem_destroy(&in_flush_sem)) 1063 { 1064 DEBUG_PRINT_ERROR("Error - sem_destroy failed %d\n", errno); 1065 } 1066 if (-1 == sem_destroy(&out_flush_sem)) 1067 { 1068 DEBUG_PRINT_ERROR("Error - sem_destroy failed %d\n", errno); 1069 } 1070 //QPERF_TERMINATE(client_decode); 1071 return 0; 1072 } 1073 1074 int run_tests() 1075 { 1076 DEBUG_PRINT("Inside %s\n", __FUNCTION__); 1077 waitForPortSettingsChanged = 1; 1078 currentStatus = GOOD_STATE; 1079 1080 if(file_type_option == FILE_TYPE_DAT_PER_AU) { 1081 Read_Buffer = Read_Buffer_From_DAT_File; 1082 } 1083 else if(file_type_option == FILE_TYPE_ARBITRARY_BYTES) { 1084 Read_Buffer = Read_Buffer_ArbitraryBytes; 1085 } 1086 else if(codec_format_option == CODEC_FORMAT_H264) { 1087 Read_Buffer = Read_Buffer_From_Size_Nal; 1088 } 1089 else if((codec_format_option == CODEC_FORMAT_H263) || 1090 (codec_format_option == CODEC_FORMAT_MP4)) { 1091 Read_Buffer = Read_Buffer_From_Vop_Start_Code_File; 1092 } 1093 else if(file_type_option == FILE_TYPE_RCV) { 1094 Read_Buffer = Read_Buffer_From_RCV_File; 1095 } 1096 else if(file_type_option == FILE_TYPE_VC1) { 1097 Read_Buffer = Read_Buffer_From_VC1_File; 1098 } 1099 1100 DEBUG_PRINT("file_type_option %d!\n", file_type_option); 1101 1102 switch(file_type_option) 1103 { 1104 case FILE_TYPE_DAT_PER_AU: 1105 case FILE_TYPE_ARBITRARY_BYTES: 1106 case FILE_TYPE_264_NAL_SIZE_LENGTH: 1107 case FILE_TYPE_PICTURE_START_CODE: 1108 case FILE_TYPE_RCV: 1109 case FILE_TYPE_VC1: 1110 if(Init_Decoder()!= 0x00) 1111 { 1112 DEBUG_PRINT_ERROR("Error - Decoder Init failed\n"); 1113 return -1; 1114 } 1115 if(Play_Decoder() != 0x00) 1116 { 1117 return -1; 1118 } 1119 break; 1120 default: 1121 DEBUG_PRINT_ERROR("Error - Invalid Entry...%d\n",file_type_option); 1122 break; 1123 } 1124 1125 if(strlen(seq_file_name)) 1126 { 1127 seqFile = fopen (seq_file_name, "rb"); 1128 if (seqFile == NULL) 1129 { 1130 DEBUG_PRINT_ERROR("Error - Seq file %s could NOT be opened\n", 1131 seq_file_name); 1132 } 1133 else 1134 { 1135 DEBUG_PRINT("Seq file %s is opened \n", seq_file_name); 1136 seq_enabled = 1; 1137 } 1138 } 1139 1140 pthread_mutex_lock(&eos_lock); 1141 while (bOutputEosReached == false) 1142 { 1143 if(seq_enabled) 1144 { 1145 if(!get_next_command(seqFile)) 1146 { 1147 process_current_command(curr_seq_command); 1148 } 1149 else 1150 { 1151 printf("\n Error in get_next_cmd or EOF"); 1152 seq_enabled = 0; 1153 } 1154 } 1155 else 1156 { 1157 pthread_cond_wait(&eos_cond, &eos_lock); 1158 } 1159 } 1160 pthread_mutex_unlock(&eos_lock); 1161 1162 // Wait till EOS is reached... 1163 if(bOutputEosReached) 1164 { 1165 unsigned int bufCnt = 0; 1166 1167 DEBUG_PRINT("Moving the decoder to idle state \n"); 1168 OMX_SendCommand(dec_handle, OMX_CommandStateSet, OMX_StateIdle,0); 1169 wait_for_event(); 1170 if (currentStatus == INVALID_STATE) 1171 { 1172 do_freeHandle_and_clean_up(true); 1173 return 0; 1174 } 1175 1176 DEBUG_PRINT("Moving the decoder to loaded state \n"); 1177 OMX_SendCommand(dec_handle, OMX_CommandStateSet, OMX_StateLoaded,0); 1178 1179 DEBUG_PRINT("[OMX Vdec Test] - Deallocating i/p and o/p buffers \n"); 1180 for(bufCnt=0; bufCnt < input_buf_cnt; ++bufCnt) 1181 { 1182 OMX_FreeBuffer(dec_handle, 0, pInputBufHdrs[bufCnt]); 1183 } 1184 1185 for(bufCnt=0; bufCnt < portFmt.nBufferCountActual; ++bufCnt) 1186 { 1187 OMX_FreeBuffer(dec_handle, 1, pOutYUVBufHdrs[bufCnt]); 1188 } 1189 1190 fbd_cnt = 0; ebd_cnt=0; 1191 bInputEosReached = false; 1192 bOutputEosReached = false; 1193 1194 wait_for_event(); 1195 1196 DEBUG_PRINT("[OMX Vdec Test] - Free handle decoder\n"); 1197 OMX_ERRORTYPE result = OMX_FreeHandle(dec_handle); 1198 if (result != OMX_ErrorNone) 1199 { 1200 DEBUG_PRINT_ERROR("[OMX Vdec Test] - Terminate: OMX_FreeHandle error. Error code: %d\n", result); 1201 } 1202 dec_handle = NULL; 1203 1204 /* Deinit OpenMAX */ 1205 DEBUG_PRINT("[OMX Vdec Test] - Terminate: De-initializing OMX \n"); 1206 OMX_Deinit(); 1207 1208 DEBUG_PRINT("[OMX Vdec Test] - Terminate: closing all files\n"); 1209 if(inputBufferFile) 1210 { 1211 fclose(inputBufferFile); 1212 inputBufferFile = NULL; 1213 } 1214 1215 1216 if (takeYuvLog && outputBufferFile) { 1217 fclose(outputBufferFile); 1218 outputBufferFile = NULL; 1219 } 1220 1221 if(etb_queue) 1222 { 1223 free_queue(etb_queue); 1224 etb_queue = NULL; 1225 } 1226 if(fbd_queue) 1227 { 1228 free_queue(fbd_queue); 1229 fbd_queue = NULL; 1230 } 1231 1232 printf("*****************************************\n"); 1233 printf("******...TEST SUCCESSFULL...*******\n"); 1234 printf("*****************************************\n"); 1235 1236 } 1237 1238 return 0; 1239 } 1240 1241 int Init_Decoder() 1242 { 1243 DEBUG_PRINT("Inside %s \n", __FUNCTION__); 1244 OMX_ERRORTYPE omxresult; 1245 OMX_U32 total = 0; 1246 char vdecCompNames[50]; 1247 typedef OMX_U8* OMX_U8_PTR; 1248 char role[] ="video_decoder"; 1249 1250 static OMX_CALLBACKTYPE call_back = {&EventHandler, &EmptyBufferDone, &FillBufferDone}; 1251 1252 unsigned int i = 0; 1253 long bufCnt = 0; 1254 1255 /* Init. the OpenMAX Core */ 1256 DEBUG_PRINT("\nInitializing OpenMAX Core....\n"); 1257 omxresult = OMX_Init(); 1258 1259 if(OMX_ErrorNone != omxresult) { 1260 DEBUG_PRINT_ERROR("\n Failed to Init OpenMAX core"); 1261 return -1; 1262 } 1263 else { 1264 DEBUG_PRINT_ERROR("\nOpenMAX Core Init Done\n"); 1265 } 1266 1267 /* Query for video decoders*/ 1268 OMX_GetComponentsOfRole(role, &total, 0); 1269 DEBUG_PRINT("\nTotal components of role=%s :%d", role, total); 1270 1271 if(total) 1272 { 1273 /* Allocate memory for pointers to component name */ 1274 OMX_U8** vidCompNames = (OMX_U8**)malloc((sizeof(OMX_U8*))*total); 1275 1276 for (i = 0; i < total; ++i) { 1277 vidCompNames[i] = (OMX_U8*)malloc(sizeof(OMX_U8)*OMX_MAX_STRINGNAME_SIZE); 1278 } 1279 OMX_GetComponentsOfRole(role, &total, vidCompNames); 1280 DEBUG_PRINT("\nComponents of Role:%s\n", role); 1281 for (i = 0; i < total; ++i) { 1282 DEBUG_PRINT("\nComponent Name [%s]\n",vidCompNames[i]); 1283 free(vidCompNames[i]); 1284 } 1285 free(vidCompNames); 1286 } 1287 else { 1288 DEBUG_PRINT_ERROR("No components found with Role:%s", role); 1289 } 1290 1291 if (codec_format_option == CODEC_FORMAT_H264) 1292 { 1293 strncpy(vdecCompNames, "OMX.qcom.video.decoder.avc", 27); 1294 } 1295 else if (codec_format_option == CODEC_FORMAT_MP4) 1296 { 1297 strncpy(vdecCompNames, "OMX.qcom.video.decoder.mpeg4", 29); 1298 } 1299 else if (codec_format_option == CODEC_FORMAT_H263) 1300 { 1301 strncpy(vdecCompNames, "OMX.qcom.video.decoder.h263", 28); 1302 } 1303 else if (codec_format_option == CODEC_FORMAT_VC1) 1304 { 1305 strncpy(vdecCompNames, "OMX.qcom.video.decoder.vc1", 27); 1306 } 1307 else 1308 { 1309 DEBUG_PRINT_ERROR("Error: Unsupported codec %d\n", codec_format_option); 1310 return -1; 1311 } 1312 1313 omxresult = OMX_GetHandle((OMX_HANDLETYPE*)(&dec_handle), 1314 (OMX_STRING)vdecCompNames, NULL, &call_back); 1315 if (FAILED(omxresult)) { 1316 DEBUG_PRINT_ERROR("\nFailed to Load the component:%s\n", vdecCompNames); 1317 return -1; 1318 } 1319 else 1320 { 1321 DEBUG_PRINT("\nComponent %s is in LOADED state\n", vdecCompNames); 1322 } 1323 1324 QOMX_VIDEO_QUERY_DECODER_INSTANCES decoder_instances; 1325 omxresult = OMX_GetConfig(dec_handle, 1326 (OMX_INDEXTYPE)OMX_QcomIndexQueryNumberOfVideoDecInstance, 1327 &decoder_instances); 1328 DEBUG_PRINT("\n Number of decoder instances %d", 1329 decoder_instances.nNumOfInstances); 1330 1331 /* Get the port information */ 1332 CONFIG_VERSION_SIZE(portParam); 1333 omxresult = OMX_GetParameter(dec_handle, OMX_IndexParamVideoInit, 1334 (OMX_PTR)&portParam); 1335 1336 if(FAILED(omxresult)) { 1337 DEBUG_PRINT_ERROR("ERROR - Failed to get Port Param\n"); 1338 return -1; 1339 } 1340 else 1341 { 1342 DEBUG_PRINT("portParam.nPorts:%d\n", portParam.nPorts); 1343 DEBUG_PRINT("portParam.nStartPortNumber:%d\n", portParam.nStartPortNumber); 1344 } 1345 1346 DEBUG_PRINT("Set parameter immediately followed by getparameter"); 1347 omxresult = OMX_SetParameter(dec_handle, 1348 OMX_IndexParamPortDefinition, 1349 &portFmt); 1350 1351 if(OMX_ErrorNone != omxresult) 1352 { 1353 DEBUG_PRINT_ERROR("ERROR - Set parameter failed"); 1354 } 1355 1356 /* Set the compression format on i/p port */ 1357 if (codec_format_option == CODEC_FORMAT_H264) 1358 { 1359 portFmt.format.video.eCompressionFormat = OMX_VIDEO_CodingAVC; 1360 } 1361 else if (codec_format_option == CODEC_FORMAT_MP4) 1362 { 1363 portFmt.format.video.eCompressionFormat = OMX_VIDEO_CodingMPEG4; 1364 } 1365 else if (codec_format_option == CODEC_FORMAT_H263) 1366 { 1367 portFmt.format.video.eCompressionFormat = OMX_VIDEO_CodingH263; 1368 } 1369 else if (codec_format_option == CODEC_FORMAT_VC1) 1370 { 1371 portFmt.format.video.eCompressionFormat = OMX_VIDEO_CodingWMV; 1372 } 1373 else 1374 { 1375 DEBUG_PRINT_ERROR("Error: Unsupported codec %d\n", codec_format_option); 1376 } 1377 1378 1379 return 0; 1380 } 1381 1382 int Play_Decoder() 1383 { 1384 int i; 1385 unsigned int bufCnt; 1386 int frameSize=0; 1387 DEBUG_PRINT("Inside %s \n", __FUNCTION__); 1388 OMX_ERRORTYPE ret; 1389 1390 DEBUG_PRINT("sizeof[%d]\n", sizeof(OMX_BUFFERHEADERTYPE)); 1391 1392 /* open the i/p and o/p files based on the video file format passed */ 1393 if(open_video_file()) { 1394 DEBUG_PRINT_ERROR("Error in opening video file\n"); 1395 return -1; 1396 } 1397 1398 OMX_QCOM_PARAM_PORTDEFINITIONTYPE inputPortFmt; 1399 memset(&inputPortFmt, 0, sizeof(OMX_QCOM_PARAM_PORTDEFINITIONTYPE)); 1400 CONFIG_VERSION_SIZE(inputPortFmt); 1401 inputPortFmt.nPortIndex = 0; // input port 1402 switch (file_type_option) 1403 { 1404 case FILE_TYPE_DAT_PER_AU: 1405 case FILE_TYPE_PICTURE_START_CODE: 1406 case FILE_TYPE_RCV: 1407 case FILE_TYPE_VC1: 1408 { 1409 inputPortFmt.nFramePackingFormat = OMX_QCOM_FramePacking_OnlyOneCompleteFrame; 1410 break; 1411 } 1412 1413 case FILE_TYPE_ARBITRARY_BYTES: 1414 case FILE_TYPE_264_NAL_SIZE_LENGTH: 1415 { 1416 inputPortFmt.nFramePackingFormat = OMX_QCOM_FramePacking_Arbitrary; 1417 break; 1418 } 1419 1420 default: 1421 inputPortFmt.nFramePackingFormat = OMX_QCOM_FramePacking_Unspecified; 1422 } 1423 OMX_SetParameter(dec_handle,(OMX_INDEXTYPE)OMX_QcomIndexPortDefn, 1424 (OMX_PTR)&inputPortFmt); 1425 1426 /* Query the decoder outport's min buf requirements */ 1427 CONFIG_VERSION_SIZE(portFmt); 1428 1429 /* Port for which the Client needs to obtain info */ 1430 portFmt.nPortIndex = portParam.nStartPortNumber; 1431 1432 OMX_GetParameter(dec_handle,OMX_IndexParamPortDefinition,&portFmt); 1433 DEBUG_PRINT("\nDec: Min Buffer Count %d\n", portFmt.nBufferCountMin); 1434 DEBUG_PRINT("\nDec: Buffer Size %d\n", portFmt.nBufferSize); 1435 1436 if(OMX_DirInput != portFmt.eDir) { 1437 printf ("\nDec: Expect Input Port\n"); 1438 return -1; 1439 } 1440 1441 bufCnt = 0; 1442 portFmt.format.video.nFrameHeight = height; 1443 portFmt.format.video.nFrameWidth = width; 1444 OMX_SetParameter(dec_handle,OMX_IndexParamPortDefinition, 1445 (OMX_PTR)&portFmt); 1446 OMX_GetParameter(dec_handle,OMX_IndexParamPortDefinition, 1447 &portFmt); 1448 DEBUG_PRINT("\nDec: New Min Buffer Count %d", portFmt.nBufferCountMin); 1449 1450 1451 DEBUG_PRINT("\nVideo format, height = %d", portFmt.format.video.nFrameHeight); 1452 DEBUG_PRINT("\nVideo format, height = %d\n", portFmt.format.video.nFrameWidth); 1453 if(codec_format_option == CODEC_FORMAT_H264) 1454 { 1455 OMX_VIDEO_CONFIG_NALSIZE naluSize; 1456 naluSize.nNaluBytes = nalSize; 1457 DEBUG_PRINT("\n Nal length is %d index %d",nalSize,OMX_IndexConfigVideoNalSize); 1458 OMX_SetConfig(dec_handle,OMX_IndexConfigVideoNalSize,(OMX_PTR)&naluSize); 1459 DEBUG_PRINT("SETTING THE NAL SIZE to %d\n",naluSize.nNaluBytes); 1460 } 1461 DEBUG_PRINT("\nOMX_SendCommand Decoder -> IDLE\n"); 1462 OMX_SendCommand(dec_handle, OMX_CommandStateSet, OMX_StateIdle,0); 1463 1464 input_buf_cnt = portFmt.nBufferCountActual; 1465 DEBUG_PRINT("Transition to Idle State succesful...\n"); 1466 /* Allocate buffer on decoder's i/p port */ 1467 error = Allocate_Buffer(dec_handle, &pInputBufHdrs, portFmt.nPortIndex, 1468 portFmt.nBufferCountActual, portFmt.nBufferSize); 1469 if (error != OMX_ErrorNone) { 1470 DEBUG_PRINT_ERROR("Error - OMX_AllocateBuffer Input buffer error\n"); 1471 return -1; 1472 } 1473 else { 1474 DEBUG_PRINT("\nOMX_AllocateBuffer Input buffer success\n"); 1475 } 1476 1477 portFmt.nPortIndex = portParam.nStartPortNumber+1; 1478 /* Port for which the Client needs to obtain info */ 1479 1480 OMX_GetParameter(dec_handle,OMX_IndexParamPortDefinition,&portFmt); 1481 DEBUG_PRINT("nMin Buffer Count=%d", portFmt.nBufferCountMin); 1482 DEBUG_PRINT("nBuffer Size=%d", portFmt.nBufferSize); 1483 if(OMX_DirOutput != portFmt.eDir) { 1484 DEBUG_PRINT_ERROR("Error - Expect Output Port\n"); 1485 return -1; 1486 } 1487 1488 /* Allocate buffer on decoder's o/p port */ 1489 error = Allocate_Buffer(dec_handle, &pOutYUVBufHdrs, portFmt.nPortIndex, 1490 portFmt.nBufferCountActual, portFmt.nBufferSize); 1491 if (error != OMX_ErrorNone) { 1492 DEBUG_PRINT_ERROR("Error - OMX_AllocateBuffer Output buffer error\n"); 1493 return -1; 1494 } 1495 else 1496 { 1497 DEBUG_PRINT("OMX_AllocateBuffer Output buffer success\n"); 1498 } 1499 1500 wait_for_event(); 1501 if (currentStatus == INVALID_STATE) 1502 { 1503 do_freeHandle_and_clean_up(true); 1504 return -1; 1505 } 1506 1507 if (freeHandle_option == FREE_HANDLE_AT_IDLE) 1508 { 1509 OMX_STATETYPE state = OMX_StateInvalid; 1510 OMX_GetState(dec_handle, &state); 1511 if (state == OMX_StateIdle) 1512 { 1513 DEBUG_PRINT("Decoder is in OMX_StateIdle and trying to call OMX_FreeHandle \n"); 1514 do_freeHandle_and_clean_up(false); 1515 } 1516 else 1517 { 1518 DEBUG_PRINT_ERROR("Error - Decoder is in state %d and trying to call OMX_FreeHandle \n", state); 1519 do_freeHandle_and_clean_up(true); 1520 } 1521 return -1; 1522 } 1523 1524 1525 DEBUG_PRINT("OMX_SendCommand Decoder -> Executing\n"); 1526 OMX_SendCommand(dec_handle, OMX_CommandStateSet, OMX_StateExecuting,0); 1527 wait_for_event(); 1528 if (currentStatus == INVALID_STATE) 1529 { 1530 do_freeHandle_and_clean_up(true); 1531 return -1; 1532 } 1533 1534 for(bufCnt=0; bufCnt < portFmt.nBufferCountActual; ++bufCnt) { 1535 DEBUG_PRINT("OMX_FillThisBuffer on output buf no.%d\n",bufCnt); 1536 pOutYUVBufHdrs[bufCnt]->nOutputPortIndex = 1; 1537 pOutYUVBufHdrs[bufCnt]->nFlags &= ~OMX_BUFFERFLAG_EOS; 1538 ret = OMX_FillThisBuffer(dec_handle, pOutYUVBufHdrs[bufCnt]); 1539 if (OMX_ErrorNone != ret) { 1540 DEBUG_PRINT_ERROR("Error - OMX_FillThisBuffer failed with result %d\n", ret); 1541 } 1542 else { 1543 DEBUG_PRINT("OMX_FillThisBuffer success!\n"); 1544 } 1545 } 1546 1547 used_ip_buf_cnt = input_buf_cnt; 1548 1549 rcv_v1 = 0; 1550 1551 //QPERF_START(client_decode); 1552 if (codec_format_option == CODEC_FORMAT_VC1) 1553 { 1554 pInputBufHdrs[0]->nOffset = 0; 1555 if(file_type_option == FILE_TYPE_RCV) 1556 { 1557 frameSize = Read_Buffer_From_RCV_File_Seq_Layer(pInputBufHdrs[0]); 1558 pInputBufHdrs[0]->nFilledLen = frameSize; 1559 DEBUG_PRINT("After Read_Buffer_From_RCV_File_Seq_Layer, " 1560 "frameSize %d\n", frameSize); 1561 } 1562 else if(file_type_option == FILE_TYPE_VC1) 1563 { 1564 pInputBufHdrs[0]->nFilledLen = Read_Buffer(pInputBufHdrs[0]); 1565 DEBUG_PRINT_ERROR("After 1st Read_Buffer for VC1, " 1566 "pInputBufHdrs[0]->nFilledLen %d\n", pInputBufHdrs[0]->nFilledLen); 1567 } 1568 else 1569 { 1570 pInputBufHdrs[0]->nFilledLen = Read_Buffer(pInputBufHdrs[0]); 1571 DEBUG_PRINT("After Read_Buffer pInputBufHdrs[0]->nFilledLen %d\n", 1572 pInputBufHdrs[0]->nFilledLen); 1573 } 1574 1575 pInputBufHdrs[0]->nInputPortIndex = 0; 1576 pInputBufHdrs[0]->nOffset = 0; 1577 pInputBufHdrs[0]->nFlags = 0; 1578 1579 ret = OMX_EmptyThisBuffer(dec_handle, pInputBufHdrs[0]); 1580 if (ret != OMX_ErrorNone) 1581 { 1582 DEBUG_PRINT_ERROR("ERROR - OMX_EmptyThisBuffer failed with result %d\n", ret); 1583 do_freeHandle_and_clean_up(true); 1584 return -1; 1585 } 1586 else 1587 { 1588 etb_count++; 1589 DEBUG_PRINT("OMX_EmptyThisBuffer success!\n"); 1590 if(cmd_data == etb_count) 1591 { 1592 sem_post(&seq_sem); 1593 printf("\n Posted seq_sem"); 1594 } 1595 } 1596 i = 1; 1597 } 1598 else 1599 { 1600 i = 0; 1601 } 1602 1603 for (i; i < used_ip_buf_cnt;i++) { 1604 pInputBufHdrs[i]->nInputPortIndex = 0; 1605 pInputBufHdrs[i]->nOffset = 0; 1606 if((frameSize = Read_Buffer(pInputBufHdrs[i])) <= 0 ){ 1607 DEBUG_PRINT("NO FRAME READ\n"); 1608 pInputBufHdrs[i]->nFilledLen = frameSize; 1609 pInputBufHdrs[i]->nInputPortIndex = 0; 1610 pInputBufHdrs[i]->nFlags |= OMX_BUFFERFLAG_EOS;; 1611 bInputEosReached = true; 1612 1613 OMX_EmptyThisBuffer(dec_handle, pInputBufHdrs[i]); 1614 etb_count++; 1615 if(cmd_data == etb_count) 1616 { 1617 sem_post(&seq_sem); 1618 printf("\n Posted seq_sem"); 1619 } 1620 DEBUG_PRINT("File is small::Either EOS or Some Error while reading file\n"); 1621 break; 1622 } 1623 pInputBufHdrs[i]->nFilledLen = frameSize; 1624 pInputBufHdrs[i]->nInputPortIndex = 0; 1625 pInputBufHdrs[i]->nFlags = 0; 1626 //pBufHdr[bufCnt]->pAppPrivate = this; 1627 ret = OMX_EmptyThisBuffer(dec_handle, pInputBufHdrs[i]); 1628 if (OMX_ErrorNone != ret) { 1629 DEBUG_PRINT_ERROR("ERROR - OMX_EmptyThisBuffer failed with result %d\n", ret); 1630 do_freeHandle_and_clean_up(true); 1631 return -1; 1632 } 1633 else { 1634 DEBUG_PRINT("OMX_EmptyThisBuffer success!\n"); 1635 etb_count++; 1636 if(cmd_data == etb_count) 1637 { 1638 sem_post(&seq_sem); 1639 printf("\n Posted seq_sem"); 1640 } 1641 } 1642 } 1643 1644 if(0 != pthread_create(&ebd_thread_id, NULL, ebd_thread, NULL)) 1645 { 1646 printf("\n Error in Creating fbd_thread \n"); 1647 free_queue(etb_queue); 1648 free_queue(fbd_queue); 1649 return -1; 1650 } 1651 1652 // wait for event port settings changed event 1653 wait_for_event(); 1654 DEBUG_PRINT("RECIEVED EVENT PORT TO DETERMINE IF DYN PORT RECONFIGURATION NEEDED, currentStatus %d\n", 1655 currentStatus); 1656 if (currentStatus == INVALID_STATE) 1657 { 1658 DEBUG_PRINT_ERROR("Error - INVALID_STATE\n"); 1659 do_freeHandle_and_clean_up(true); 1660 return -1; 1661 } 1662 else if (currentStatus == PORT_SETTING_CHANGE_STATE) 1663 { 1664 DEBUG_PRINT("PORT_SETTING_CHANGE_STATE\n"); 1665 // Send DISABLE command 1666 sent_disabled = 1; 1667 OMX_SendCommand(dec_handle, OMX_CommandPortDisable, 1, 0); 1668 1669 DEBUG_PRINT("FREEING BUFFERS\n"); 1670 // Free output Buffer 1671 for(bufCnt=0; bufCnt < portFmt.nBufferCountActual; ++bufCnt) { 1672 OMX_FreeBuffer(dec_handle, 1, pOutYUVBufHdrs[bufCnt]); 1673 } 1674 1675 // wait for Disable event to come back 1676 wait_for_event(); 1677 if (currentStatus == INVALID_STATE) 1678 { 1679 do_freeHandle_and_clean_up(true); 1680 return -1; 1681 } 1682 DEBUG_PRINT("DISABLE EVENT RECD\n"); 1683 // GetParam and SetParam 1684 1685 // Send Enable command 1686 OMX_SendCommand(dec_handle, OMX_CommandPortEnable, 1, 0); 1687 // AllocateBuffers 1688 /* Allocate buffer on decoder's o/p port */ 1689 1690 portFmt.nPortIndex = 1; 1691 /* Port for which the Client needs to obtain info */ 1692 1693 OMX_GetParameter(dec_handle,OMX_IndexParamPortDefinition,&portFmt); 1694 DEBUG_PRINT("Min Buffer Count=%d", portFmt.nBufferCountMin); 1695 DEBUG_PRINT("Buffer Size=%d", portFmt.nBufferSize); 1696 if(OMX_DirOutput != portFmt.eDir) { 1697 DEBUG_PRINT_ERROR("Error - Expect Output Port\n"); 1698 return -1; 1699 } 1700 height = portFmt.format.video.nFrameHeight; 1701 width = portFmt.format.video.nFrameWidth; 1702 stride = portFmt.format.video.nStride; 1703 sliceheight = portFmt.format.video.nSliceHeight; 1704 1705 error = Allocate_Buffer(dec_handle, &pOutYUVBufHdrs, portFmt.nPortIndex, 1706 portFmt.nBufferCountActual, portFmt.nBufferSize); 1707 if (error != OMX_ErrorNone) { 1708 DEBUG_PRINT_ERROR("Error - OMX_AllocateBuffer Output buffer error\n"); 1709 return -1; 1710 } 1711 else 1712 { 1713 DEBUG_PRINT("OMX_AllocateBuffer Output buffer success\n"); 1714 } 1715 1716 // wait for enable event to come back 1717 wait_for_event(); 1718 if (currentStatus == INVALID_STATE) 1719 { 1720 do_freeHandle_and_clean_up(true); 1721 return -1; 1722 } 1723 DEBUG_PRINT("ENABLE EVENT HANDLER RECD\n"); 1724 1725 for(bufCnt=0; bufCnt < portFmt.nBufferCountActual; ++bufCnt) { 1726 DEBUG_PRINT("OMX_FillThisBuffer on output buf no.%d\n",bufCnt); 1727 pOutYUVBufHdrs[bufCnt]->nOutputPortIndex = 1; 1728 pOutYUVBufHdrs[bufCnt]->nFlags &= ~OMX_BUFFERFLAG_EOS; 1729 ret = OMX_FillThisBuffer(dec_handle, pOutYUVBufHdrs[bufCnt]); 1730 if (OMX_ErrorNone != ret) { 1731 DEBUG_PRINT_ERROR("ERROR - OMX_FillThisBuffer failed with result %d\n", ret); 1732 } 1733 else { 1734 DEBUG_PRINT("OMX_FillThisBuffer success!\n"); 1735 } 1736 } 1737 } 1738 1739 if (freeHandle_option == FREE_HANDLE_AT_EXECUTING) 1740 { 1741 OMX_STATETYPE state = OMX_StateInvalid; 1742 OMX_GetState(dec_handle, &state); 1743 if (state == OMX_StateExecuting) 1744 { 1745 DEBUG_PRINT("Decoder is in OMX_StateExecuting and trying to call OMX_FreeHandle \n"); 1746 do_freeHandle_and_clean_up(false); 1747 } 1748 else 1749 { 1750 DEBUG_PRINT_ERROR("Error - Decoder is in state %d and trying to call OMX_FreeHandle \n", state); 1751 do_freeHandle_and_clean_up(true); 1752 } 1753 return -1; 1754 } 1755 else if (freeHandle_option == FREE_HANDLE_AT_PAUSE) 1756 { 1757 OMX_SendCommand(dec_handle, OMX_CommandStateSet, OMX_StatePause,0); 1758 wait_for_event(); 1759 1760 OMX_STATETYPE state = OMX_StateInvalid; 1761 OMX_GetState(dec_handle, &state); 1762 if (state == OMX_StatePause) 1763 { 1764 DEBUG_PRINT("Decoder is in OMX_StatePause and trying to call OMX_FreeHandle \n"); 1765 do_freeHandle_and_clean_up(false); 1766 } 1767 else 1768 { 1769 DEBUG_PRINT_ERROR("Error - Decoder is in state %d and trying to call OMX_FreeHandle \n", state); 1770 do_freeHandle_and_clean_up(true); 1771 } 1772 return -1; 1773 } 1774 1775 return 0; 1776 } 1777 1778 static OMX_ERRORTYPE Allocate_Buffer ( OMX_COMPONENTTYPE *dec_handle, 1779 OMX_BUFFERHEADERTYPE ***pBufHdrs, 1780 OMX_U32 nPortIndex, 1781 long bufCntMin, long bufSize) 1782 { 1783 DEBUG_PRINT("Inside %s \n", __FUNCTION__); 1784 OMX_ERRORTYPE error=OMX_ErrorNone; 1785 long bufCnt=0; 1786 1787 DEBUG_PRINT("pBufHdrs = %x,bufCntMin = %d\n", pBufHdrs, bufCntMin); 1788 *pBufHdrs= (OMX_BUFFERHEADERTYPE **) 1789 malloc(sizeof(OMX_BUFFERHEADERTYPE)*bufCntMin); 1790 1791 for(bufCnt=0; bufCnt < bufCntMin; ++bufCnt) { 1792 DEBUG_PRINT("OMX_AllocateBuffer No %d \n", bufCnt); 1793 error = OMX_AllocateBuffer(dec_handle, &((*pBufHdrs)[bufCnt]), 1794 nPortIndex, NULL, bufSize); 1795 } 1796 1797 return error; 1798 } 1799 1800 static void do_freeHandle_and_clean_up(bool isDueToError) 1801 { 1802 unsigned int bufCnt = 0; 1803 1804 for(bufCnt=0; bufCnt < input_buf_cnt; ++bufCnt) 1805 { 1806 OMX_FreeBuffer(dec_handle, 0, pInputBufHdrs[bufCnt]); 1807 } 1808 1809 for(bufCnt=0; bufCnt < portFmt.nBufferCountActual; ++bufCnt) 1810 { 1811 OMX_FreeBuffer(dec_handle, 1, pOutYUVBufHdrs[bufCnt]); 1812 } 1813 1814 DEBUG_PRINT("[OMX Vdec Test] - Free handle decoder\n"); 1815 OMX_ERRORTYPE result = OMX_FreeHandle(dec_handle); 1816 if (result != OMX_ErrorNone) 1817 { 1818 DEBUG_PRINT_ERROR("[OMX Vdec Test] - OMX_FreeHandle error. Error code: %d\n", result); 1819 } 1820 dec_handle = NULL; 1821 1822 /* Deinit OpenMAX */ 1823 DEBUG_PRINT("[OMX Vdec Test] - De-initializing OMX \n"); 1824 OMX_Deinit(); 1825 1826 DEBUG_PRINT("[OMX Vdec Test] - closing all files\n"); 1827 if(inputBufferFile) 1828 { 1829 fclose(inputBufferFile); 1830 inputBufferFile = NULL; 1831 } 1832 1833 DEBUG_PRINT("[OMX Vdec Test] - after free inputfile\n"); 1834 1835 if (takeYuvLog && outputBufferFile) { 1836 fclose(outputBufferFile); 1837 outputBufferFile = NULL; 1838 } 1839 DEBUG_PRINT("[OMX Vdec Test] - after free outputfile\n"); 1840 1841 if(etb_queue) 1842 { 1843 free_queue(etb_queue); 1844 etb_queue = NULL; 1845 } 1846 DEBUG_PRINT("[OMX Vdec Test] - after free etb_queue \n"); 1847 if(fbd_queue) 1848 { 1849 free_queue(fbd_queue); 1850 fbd_queue = NULL; 1851 } 1852 DEBUG_PRINT("[OMX Vdec Test] - after free iftb_queue\n"); 1853 1854 1855 printf("*****************************************\n"); 1856 if (isDueToError) 1857 { 1858 printf("************...TEST FAILED...************\n"); 1859 } 1860 else 1861 { 1862 printf("**********...TEST SUCCESSFULL...*********\n"); 1863 } 1864 printf("*****************************************\n"); 1865 } 1866 1867 static int Read_Buffer_From_DAT_File(OMX_BUFFERHEADERTYPE *pBufHdr) 1868 { 1869 long frameSize=0; 1870 char temp_buffer[10]; 1871 char temp_byte; 1872 int bytes_read=0; 1873 int i=0; 1874 unsigned char *read_buffer=NULL; 1875 char c = '1'; //initialize to anything except '\0'(0) 1876 char inputFrameSize[10]; 1877 int count =0; 1878 int cnt = 0; 1879 memset(temp_buffer, 0, sizeof(temp_buffer)); 1880 1881 DEBUG_PRINT("Inside %s \n", __FUNCTION__); 1882 1883 while (cnt < 10) 1884 /* Check the input file format, may result in infinite loop */ 1885 { 1886 DEBUG_PRINT("loop[%d] count[%d]\n",cnt,count); 1887 count = fread(&inputFrameSize[cnt], 1, 1, inputBufferFile); 1888 if(inputFrameSize[cnt] == '\0' ) 1889 break; 1890 cnt++; 1891 } 1892 inputFrameSize[cnt]='\0'; 1893 frameSize = atoi(inputFrameSize); 1894 pBufHdr->nFilledLen = 0; 1895 1896 /* get the frame length */ 1897 fseek(inputBufferFile, -1, SEEK_CUR); 1898 bytes_read = fread(pBufHdr->pBuffer, 1, frameSize, inputBufferFile); 1899 1900 DEBUG_PRINT("Actual frame Size [%d] bytes_read using fread[%d]\n", 1901 frameSize, bytes_read); 1902 1903 if(bytes_read == 0 || bytes_read < frameSize ) { 1904 DEBUG_PRINT("Bytes read Zero After Read frame Size \n"); 1905 DEBUG_PRINT("Checking VideoPlayback Count:video_playback_count is:%d\n", 1906 video_playback_count); 1907 return 0; 1908 } 1909 pBufHdr->nTimeStamp = timeStampLfile; 1910 timeStampLfile += timestampInterval; 1911 return bytes_read; 1912 } 1913 1914 static int Read_Buffer_ArbitraryBytes(OMX_BUFFERHEADERTYPE *pBufHdr) 1915 { 1916 char temp_buffer[10]; 1917 char temp_byte; 1918 int bytes_read=0; 1919 int i=0; 1920 unsigned char *read_buffer=NULL; 1921 char c = '1'; //initialize to anything except '\0'(0) 1922 char inputFrameSize[10]; 1923 int count =0; char cnt =0; 1924 memset(temp_buffer, 0, sizeof(temp_buffer)); 1925 1926 DEBUG_PRINT("Inside %s \n", __FUNCTION__); 1927 1928 bytes_read = fread(pBufHdr->pBuffer, 1, NUMBER_OF_ARBITRARYBYTES_READ, inputBufferFile); 1929 1930 if(bytes_read == 0) { 1931 DEBUG_PRINT("Bytes read Zero After Read frame Size \n"); 1932 DEBUG_PRINT("Checking VideoPlayback Count:video_playback_count is:%d\n", 1933 video_playback_count); 1934 return 0; 1935 } 1936 pBufHdr->nTimeStamp = timeStampLfile; 1937 timeStampLfile += timestampInterval; 1938 return bytes_read; 1939 } 1940 1941 static int Read_Buffer_From_Vop_Start_Code_File(OMX_BUFFERHEADERTYPE *pBufHdr) 1942 { 1943 unsigned int readOffset = 0; 1944 int bytes_read = 0; 1945 unsigned int code = 0; 1946 pBufHdr->nFilledLen = 0; 1947 static unsigned int header_code = 0; 1948 1949 DEBUG_PRINT("Inside %s \n", __FUNCTION__); 1950 1951 do 1952 { 1953 //Start codes are always byte aligned. 1954 bytes_read = fread(&pBufHdr->pBuffer[readOffset],1, 1,inputBufferFile); 1955 if(!bytes_read) 1956 { 1957 DEBUG_PRINT("Bytes read Zero \n"); 1958 break; 1959 } 1960 code <<= 8; 1961 code |= (0x000000FF & pBufHdr->pBuffer[readOffset]); 1962 //VOP start code comparision 1963 if (readOffset>3) 1964 { 1965 if(!header_code ){ 1966 if( VOP_START_CODE == code) 1967 { 1968 header_code = VOP_START_CODE; 1969 } 1970 else if ( (0xFFFFFC00 & code) == SHORT_HEADER_START_CODE ) 1971 { 1972 header_code = SHORT_HEADER_START_CODE; 1973 } 1974 } 1975 if ((header_code == VOP_START_CODE) && (code == VOP_START_CODE)) 1976 { 1977 //Seek backwards by 4 1978 fseek(inputBufferFile, -4, SEEK_CUR); 1979 readOffset-=3; 1980 break; 1981 1982 } 1983 else if (( header_code == SHORT_HEADER_START_CODE ) && ( SHORT_HEADER_START_CODE == (code & 0xFFFFFC00))) 1984 { 1985 //Seek backwards by 4 1986 fseek(inputBufferFile, -4, SEEK_CUR); 1987 readOffset-=3; 1988 break; 1989 } 1990 } 1991 readOffset++; 1992 }while (1); 1993 pBufHdr->nTimeStamp = timeStampLfile; 1994 timeStampLfile += timestampInterval; 1995 return readOffset; 1996 } 1997 1998 static int Read_Buffer_From_Size_Nal(OMX_BUFFERHEADERTYPE *pBufHdr) 1999 { 2000 // NAL unit stream processing 2001 char temp_size[SIZE_NAL_FIELD_MAX]; 2002 int i = 0; 2003 int j = 0; 2004 unsigned int size = 0; // Need to make sure that uint32 has SIZE_NAL_FIELD_MAX (4) bytes 2005 unsigned int bytes_read = 0; 2006 2007 // read the "size_nal_field"-byte size field 2008 bytes_read = fread(pBufHdr->pBuffer + pBufHdr->nOffset, 1, nalSize, inputBufferFile); 2009 if (bytes_read == 0) 2010 { 2011 DEBUG_PRINT("Failed to read frame or it might be EOF\n"); 2012 return 0; 2013 } 2014 2015 for (i=0; i<SIZE_NAL_FIELD_MAX-nalSize; i++) 2016 { 2017 temp_size[SIZE_NAL_FIELD_MAX - 1 - i] = 0; 2018 } 2019 2020 /* Due to little endiannes, Reorder the size based on size_nal_field */ 2021 for (j=0; i<SIZE_NAL_FIELD_MAX; i++, j++) 2022 { 2023 temp_size[SIZE_NAL_FIELD_MAX - 1 - i] = pBufHdr->pBuffer[pBufHdr->nOffset + j]; 2024 } 2025 size = (unsigned int)(*((unsigned int *)(temp_size))); 2026 2027 // now read the data 2028 bytes_read = fread(pBufHdr->pBuffer + pBufHdr->nOffset + nalSize, 1, size, inputBufferFile); 2029 if (bytes_read != size) 2030 { 2031 DEBUG_PRINT_ERROR("Failed to read frame\n"); 2032 } 2033 2034 return bytes_read + nalSize; 2035 } 2036 2037 static int Read_Buffer_From_RCV_File_Seq_Layer(OMX_BUFFERHEADERTYPE *pBufHdr) 2038 { 2039 unsigned int readOffset = 0, size_struct_C = 0; 2040 unsigned int startcode = 0; 2041 pBufHdr->nFilledLen = 0; 2042 pBufHdr->nFlags = 0; 2043 2044 DEBUG_PRINT("Inside %s \n", __FUNCTION__); 2045 2046 fread(&startcode, 4, 1, inputBufferFile); 2047 2048 /* read size of struct C as it need not be 4 always*/ 2049 fread(&size_struct_C, 1, 4, inputBufferFile); 2050 2051 /* reseek to beginning of sequence header */ 2052 fseek(inputBufferFile, -8, SEEK_CUR); 2053 2054 if ((startcode & 0xFF000000) == 0xC5000000) 2055 { 2056 2057 DEBUG_PRINT("Read_Buffer_From_RCV_File_Seq_Layer size_struct_C: %d\n", size_struct_C); 2058 2059 readOffset = fread(pBufHdr->pBuffer, 1, VC1_SEQ_LAYER_SIZE_WITHOUT_STRUCTC + size_struct_C, inputBufferFile); 2060 } 2061 else if((startcode & 0xFF000000) == 0x85000000) 2062 { 2063 // .RCV V1 file 2064 2065 rcv_v1 = 1; 2066 2067 DEBUG_PRINT("Read_Buffer_From_RCV_File_Seq_Layer size_struct_C: %d\n", size_struct_C); 2068 2069 readOffset = fread(pBufHdr->pBuffer, 1, VC1_SEQ_LAYER_SIZE_V1_WITHOUT_STRUCTC + size_struct_C, inputBufferFile); 2070 } 2071 else 2072 { 2073 DEBUG_PRINT_ERROR("Error: Unknown VC1 clip format %x\n", startcode); 2074 } 2075 2076 #if 0 2077 { 2078 int i=0; 2079 printf("Read_Buffer_From_RCV_File, length %d readOffset %d\n", readOffset, readOffset); 2080 for (i=0; i<36; i++) 2081 { 2082 printf("0x%.2x ", pBufHdr->pBuffer[i]); 2083 if (i%16 == 15) { 2084 printf("\n"); 2085 } 2086 } 2087 printf("\n"); 2088 } 2089 #endif 2090 return readOffset; 2091 } 2092 2093 static int Read_Buffer_From_RCV_File(OMX_BUFFERHEADERTYPE *pBufHdr) 2094 { 2095 unsigned int readOffset = 0; 2096 unsigned int len = 0; 2097 unsigned int key = 0; 2098 DEBUG_PRINT("Inside %s \n", __FUNCTION__); 2099 2100 DEBUG_PRINT("Read_Buffer_From_RCV_File - nOffset %d\n", pBufHdr->nOffset); 2101 if(rcv_v1) 2102 { 2103 /* for the case of RCV V1 format, the frame header is only of 4 bytes and has 2104 only the frame size information */ 2105 readOffset = fread(&len, 1, 4, inputBufferFile); 2106 DEBUG_PRINT("Read_Buffer_From_RCV_File - framesize %d %x\n", len, len); 2107 2108 } 2109 else 2110 { 2111 /* for a regular RCV file, 3 bytes comprise the frame size and 1 byte for key*/ 2112 readOffset = fread(&len, 1, 3, inputBufferFile); 2113 DEBUG_PRINT("Read_Buffer_From_RCV_File - framesize %d %x\n", len, len); 2114 2115 readOffset = fread(&key, 1, 1, inputBufferFile); 2116 if ( (key & 0x80) == false) 2117 { 2118 DEBUG_PRINT("Read_Buffer_From_RCV_File - Non IDR frame key %x\n", key); 2119 } 2120 2121 } 2122 2123 if(!rcv_v1) 2124 { 2125 /* There is timestamp field only for regular RCV format and not for RCV V1 format*/ 2126 readOffset = fread(&pBufHdr->nTimeStamp, 1, 4, inputBufferFile); 2127 DEBUG_PRINT("Read_Buffer_From_RCV_File - timeStamp %d\n", pBufHdr->nTimeStamp); 2128 pBufHdr->nTimeStamp *= 1000; 2129 } 2130 else 2131 { 2132 pBufHdr->nTimeStamp = timeStampLfile; 2133 timeStampLfile += timestampInterval; 2134 } 2135 2136 if(len > pBufHdr->nAllocLen) 2137 { 2138 DEBUG_PRINT_ERROR("Error in sufficient buffer framesize %d, allocalen %d noffset %d\n",len,pBufHdr->nAllocLen, pBufHdr->nOffset); 2139 readOffset = fread(pBufHdr->pBuffer+pBufHdr->nOffset, 1, pBufHdr->nAllocLen - pBufHdr->nOffset , inputBufferFile); 2140 fseek(inputBufferFile, len - readOffset,SEEK_CUR); 2141 return readOffset; 2142 } 2143 else 2144 readOffset = fread(pBufHdr->pBuffer+pBufHdr->nOffset, 1, len, inputBufferFile); 2145 if (readOffset != len) 2146 { 2147 DEBUG_PRINT("EOS reach or Reading error %d, %s \n", readOffset, strerror( errno )); 2148 return 0; 2149 } 2150 2151 #if 0 2152 { 2153 int i=0; 2154 printf("Read_Buffer_From_RCV_File, length %d readOffset %d\n", len, readOffset); 2155 for (i=0; i<64; i++) 2156 { 2157 printf("0x%.2x ", pBufHdr->pBuffer[i]); 2158 if (i%16 == 15) { 2159 printf("\n"); 2160 } 2161 } 2162 printf("\n"); 2163 } 2164 #endif 2165 2166 return readOffset; 2167 } 2168 2169 static int Read_Buffer_From_VC1_File(OMX_BUFFERHEADERTYPE *pBufHdr) 2170 { 2171 static int timeStampLfile = 0; 2172 OMX_U8 *pBuffer = pBufHdr->pBuffer + pBufHdr->nOffset; 2173 DEBUG_PRINT("Inside %s \n", __FUNCTION__); 2174 2175 unsigned int readOffset = 0; 2176 int bytes_read = 0; 2177 unsigned int code = 0; 2178 2179 do 2180 { 2181 //Start codes are always byte aligned. 2182 bytes_read = fread(&pBuffer[readOffset],1, 1,inputBufferFile); 2183 if(!bytes_read) 2184 { 2185 DEBUG_PRINT("\n Bytes read Zero \n"); 2186 break; 2187 } 2188 code <<= 8; 2189 code |= (0x000000FF & pBufHdr->pBuffer[readOffset]); 2190 //VOP start code comparision 2191 if (readOffset>3) 2192 { 2193 if (VC1_FRAME_START_CODE == (code & 0xFFFFFFFF)) 2194 { 2195 //Seek backwards by 4 2196 fseek(inputBufferFile, -4, SEEK_CUR); 2197 readOffset-=3; 2198 2199 while(pBufHdr->pBuffer[readOffset-1] == 0) 2200 readOffset--; 2201 2202 break; 2203 } 2204 } 2205 readOffset++; 2206 }while (1); 2207 2208 pBufHdr->nTimeStamp = timeStampLfile; 2209 timeStampLfile += timestampInterval; 2210 2211 #if 0 2212 { 2213 int i=0; 2214 printf("Read_Buffer_From_VC1_File, readOffset %d\n", readOffset); 2215 for (i=0; i<64; i++) 2216 { 2217 printf("0x%.2x ", pBufHdr->pBuffer[i]); 2218 if (i%16 == 15) { 2219 printf("\n"); 2220 } 2221 } 2222 printf("\n"); 2223 } 2224 #endif 2225 2226 return readOffset; 2227 } 2228 2229 static int open_video_file () 2230 { 2231 int error_code = 0; 2232 char outputfilename[512]; 2233 DEBUG_PRINT("Inside %s filename=%s\n", __FUNCTION__, in_filename); 2234 2235 inputBufferFile = fopen (in_filename, "rb"); 2236 if (inputBufferFile == NULL) { 2237 DEBUG_PRINT_ERROR("Error - i/p file %s could NOT be opened\n", 2238 in_filename); 2239 error_code = -1; 2240 } 2241 else { 2242 DEBUG_PRINT("I/p file %s is opened \n", in_filename); 2243 } 2244 2245 if (takeYuvLog) { 2246 strcpy(outputfilename, "/data/misc/yuv"); 2247 outputBufferFile = fopen (outputfilename, "ab"); 2248 if (outputBufferFile == NULL) 2249 { 2250 DEBUG_PRINT_ERROR("ERROR - o/p file %s could NOT be opened\n", outputfilename); 2251 error_code = -1; 2252 } 2253 else 2254 { 2255 DEBUG_PRINT("O/p file %s is opened \n", outputfilename); 2256 } 2257 } 2258 return error_code; 2259 } 2260 2261 void swap_byte(char *pByte, int nbyte) 2262 { 2263 int i=0; 2264 2265 for (i=0; i<nbyte/2; i++) 2266 { 2267 pByte[i] ^= pByte[nbyte-i-1]; 2268 pByte[nbyte-i-1] ^= pByte[i]; 2269 pByte[i] ^= pByte[nbyte-i-1]; 2270 } 2271 } 2272 2273 int drawBG(void) 2274 { 2275 int result; 2276 unsigned int i; 2277 #ifdef FRAMEBUFFER_32 2278 long * p; 2279 #else 2280 short * p; 2281 #endif 2282 void *fb_buf = mmap (NULL, finfo.smem_len,PROT_READ|PROT_WRITE, MAP_SHARED, fb_fd, 0); 2283 2284 if (fb_buf == MAP_FAILED) 2285 { 2286 printf("ERROR: Framebuffer MMAP failed!\n"); 2287 close(fb_fd); 2288 return -1; 2289 } 2290 2291 vinfo.yoffset = 0; 2292 p = (long *)fb_buf; 2293 2294 for (i=0; i < vinfo.xres * vinfo.yres; i++) 2295 { 2296 #ifdef FRAMEBUFFER_32 2297 *p++ = COLOR_BLACK_RGBA_8888; 2298 #else 2299 *p++ = CLR_KEY; 2300 #endif 2301 } 2302 2303 if (ioctl(fb_fd, FBIOPAN_DISPLAY, &vinfo) < 0) 2304 { 2305 printf("ERROR: FBIOPAN_DISPLAY failed! line=%d\n", __LINE__); 2306 return -1; 2307 } 2308 2309 DEBUG_PRINT("drawBG success!\n"); 2310 return 0; 2311 } 2312 2313 void render_fb(struct OMX_BUFFERHEADERTYPE *pBufHdr) 2314 { 2315 unsigned int addr = 0; 2316 OMX_OTHER_EXTRADATATYPE *pExtraData = 0; 2317 OMX_QCOM_EXTRADATA_FRAMEINFO *pExtraFrameInfo = 0; 2318 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo = NULL; 2319 unsigned int destx, desty,destW, destH; 2320 #ifdef _ANDROID_ 2321 MemoryHeapBase *vheap = NULL; 2322 #endif 2323 2324 unsigned int end = (unsigned int)(pBufHdr->pBuffer + pBufHdr->nAllocLen); 2325 2326 struct mdp_blit_req *e; 2327 union { 2328 char dummy[sizeof(struct mdp_blit_req_list) + 2329 sizeof(struct mdp_blit_req) * 1]; 2330 struct mdp_blit_req_list list; 2331 } img; 2332 2333 if (fb_fd < 0) 2334 { 2335 DEBUG_PRINT_ERROR("Warning: /dev/fb0 is not opened!\n"); 2336 return; 2337 } 2338 2339 img.list.count = 1; 2340 e = &img.list.req[0]; 2341 2342 addr = (unsigned int)(pBufHdr->pBuffer + pBufHdr->nFilledLen); 2343 // align to a 4 byte boundary 2344 addr = (addr + 3) & (~3); 2345 2346 // read to the end of existing extra data sections 2347 pExtraData = (OMX_OTHER_EXTRADATATYPE*)addr; 2348 2349 while (addr < end && pExtraData->eType != (enum OMX_EXTRADATATYPE)OMX_ExtraDataFrameInfo) 2350 { 2351 addr += pExtraData->nSize; 2352 pExtraData = (OMX_OTHER_EXTRADATATYPE*)addr; 2353 } 2354 2355 if (pExtraData->eType != (enum OMX_EXTRADATATYPE)OMX_ExtraDataFrameInfo) 2356 { 2357 DEBUG_PRINT_ERROR("pExtraData->eType %d pExtraData->nSize %d\n",pExtraData->eType,pExtraData->nSize); 2358 } 2359 pExtraFrameInfo = (OMX_QCOM_EXTRADATA_FRAMEINFO *)pExtraData->data; 2360 2361 pPMEMInfo = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *) 2362 ((OMX_QCOM_PLATFORM_PRIVATE_LIST *) 2363 pBufHdr->pPlatformPrivate)->entryList->entry; 2364 #ifdef _ANDROID_ 2365 vheap = (MemoryHeapBase *)pPMEMInfo->pmem_fd; 2366 #endif 2367 2368 2369 DEBUG_PRINT_ERROR("DecWidth %d DecHeight %d\n",portFmt.format.video.nStride,portFmt.format.video.nSliceHeight); 2370 DEBUG_PRINT_ERROR("DispWidth %d DispHeight %d\n",portFmt.format.video.nFrameWidth,portFmt.format.video.nFrameHeight); 2371 2372 2373 2374 e->src.width = portFmt.format.video.nStride; 2375 e->src.height = portFmt.format.video.nSliceHeight; 2376 e->src.format = MDP_Y_CBCR_H2V2; 2377 e->src.offset = pPMEMInfo->offset; 2378 #ifdef _ANDROID_ 2379 e->src.memory_id = vheap->getHeapID(); 2380 #else 2381 e->src.memory_id = pPMEMInfo->pmem_fd; 2382 #endif 2383 2384 DEBUG_PRINT_ERROR("pmemOffset %d pmemID %d\n",e->src.offset,e->src.memory_id); 2385 2386 e->dst.width = vinfo.xres; 2387 e->dst.height = vinfo.yres; 2388 e->dst.format = MDP_RGB_565; 2389 e->dst.offset = 0; 2390 e->dst.memory_id = fb_fd; 2391 2392 e->transp_mask = 0xffffffff; 2393 DEBUG_PRINT("Frame interlace type %d!\n", pExtraFrameInfo->interlaceType); 2394 if(pExtraFrameInfo->interlaceType != OMX_QCOM_InterlaceFrameProgressive) 2395 { 2396 DEBUG_PRINT("Interlaced Frame!\n"); 2397 e->flags = MDP_DEINTERLACE; 2398 } 2399 else 2400 e->flags = 0; 2401 e->alpha = 0xff; 2402 2403 switch(displayWindow) 2404 { 2405 case 1: destx = 0; 2406 desty = 0; 2407 destW = vinfo.xres/2; 2408 destH = vinfo.yres/2; 2409 break; 2410 case 2: destx = vinfo.xres/2; 2411 desty = 0; 2412 destW = vinfo.xres/2; 2413 destH = vinfo.yres/2; 2414 break; 2415 2416 case 3: destx = 0; 2417 desty = vinfo.yres/2; 2418 destW = vinfo.xres/2; 2419 destH = vinfo.yres/2; 2420 break; 2421 case 4: destx = vinfo.xres/2; 2422 desty = vinfo.yres/2; 2423 destW = vinfo.xres/2; 2424 destH = vinfo.yres/2; 2425 break; 2426 case 0: 2427 default: 2428 destx = 0; 2429 desty = 0; 2430 destW = vinfo.xres; 2431 destH = vinfo.yres; 2432 } 2433 2434 2435 if(portFmt.format.video.nFrameWidth < destW) 2436 destW = portFmt.format.video.nFrameWidth ; 2437 2438 2439 if(portFmt.format.video.nFrameHeight < destH) 2440 destH = portFmt.format.video.nFrameHeight; 2441 2442 e->dst_rect.x = destx; 2443 e->dst_rect.y = desty; 2444 e->dst_rect.w = destW; 2445 e->dst_rect.h = destH; 2446 2447 //e->dst_rect.w = 800; 2448 //e->dst_rect.h = 480; 2449 2450 e->src_rect.x = 0; 2451 e->src_rect.y = 0; 2452 e->src_rect.w = portFmt.format.video.nFrameWidth; 2453 e->src_rect.h = portFmt.format.video.nFrameHeight; 2454 2455 //e->src_rect.w = portFmt.format.video.nStride; 2456 //e->src_rect.h = portFmt.format.video.nSliceHeight; 2457 2458 if (ioctl(fb_fd, MSMFB_BLIT, &img)) { 2459 DEBUG_PRINT_ERROR("MSMFB_BLIT ioctl failed!\n"); 2460 return; 2461 } 2462 2463 if (ioctl(fb_fd, FBIOPAN_DISPLAY, &vinfo) < 0) { 2464 DEBUG_PRINT_ERROR("FBIOPAN_DISPLAY failed! line=%d\n", __LINE__); 2465 return; 2466 } 2467 2468 DEBUG_PRINT("render_fb complete!\n"); 2469 } 2470 2471