| /*-------------------------------------------------------------------------- |
| Copyright (c) 2010, Code Aurora Forum. All rights reserved. |
| |
| Redistribution and use in source and binary forms, with or without |
| modification, are permitted provided that the following conditions are met: |
| * Redistributions of source code must retain the above copyright |
| notice, this list of conditions and the following disclaimer. |
| * Redistributions in binary form must reproduce the above copyright |
| notice, this list of conditions and the following disclaimer in the |
| documentation and/or other materials provided with the distribution. |
| * Neither the name of Code Aurora nor |
| the names of its contributors may be used to endorse or promote |
| products derived from this software without specific prior written |
| permission. |
| |
| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
| NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
| CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; |
| OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
| WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
| OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
| ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| --------------------------------------------------------------------------*/ |
| /* |
| An Open max test application .... |
| */ |
| |
| #include <stdio.h> |
| #include <string.h> |
| #include <stdlib.h> |
| #include <unistd.h> |
| #include <fcntl.h> |
| #include <sys/types.h> |
| #include <sys/mman.h> |
| #include <time.h> |
| #include <sys/ioctl.h> |
| #include <errno.h> |
| #include <pthread.h> |
| #include <semaphore.h> |
| #include "OMX_QCOMExtns.h" |
| |
| #ifdef _ANDROID_ |
| #include <binder/MemoryHeapBase.h> |
| |
| extern "C"{ |
| #include<utils/Log.h> |
| } |
| #define LOG_TAG "OMX-VDEC-TEST" |
| #define DEBUG_PRINT |
| #define DEBUG_PRINT_ERROR |
| |
| #else |
| #define DEBUG_PRINT printf |
| #define DEBUG_PRINT_ERROR printf |
| #endif /* _ANDROID_ */ |
| |
| #include "OMX_Core.h" |
| #include "OMX_Component.h" |
| #include "OMX_QCOMExtns.h" |
| extern "C" { |
| #include "queue.h" |
| } |
| |
| #include <linux/msm_mdp.h> |
| #include <linux/fb.h> |
| //#include "qutility.h" |
| |
| |
| /************************************************************************/ |
| /* #DEFINES */ |
| /************************************************************************/ |
| #define DELAY 66 |
| #define false 0 |
| #define true 1 |
| #define VOP_START_CODE 0x000001B6 |
| #define SHORT_HEADER_START_CODE 0x00008000 |
| #define VC1_START_CODE 0x00000100 |
| #define VC1_FRAME_START_CODE 0x0000010D |
| #define NUMBER_OF_ARBITRARYBYTES_READ (4 * 1024) |
| #define VC1_SEQ_LAYER_SIZE_WITHOUT_STRUCTC 32 |
| #define VC1_SEQ_LAYER_SIZE_V1_WITHOUT_STRUCTC 16 |
| |
| #define CONFIG_VERSION_SIZE(param) \ |
| param.nVersion.nVersion = CURRENT_OMX_SPEC_VERSION;\ |
| param.nSize = sizeof(param); |
| |
| #define FAILED(result) (result != OMX_ErrorNone) |
| |
| #define SUCCEEDED(result) (result == OMX_ErrorNone) |
| #define SWAPBYTES(ptrA, ptrB) { char t = *ptrA; *ptrA = *ptrB; *ptrB = t;} |
| #define SIZE_NAL_FIELD_MAX 4 |
| #define MDP_DEINTERLACE 0x80000000 |
| |
| /************************************************************************/ |
| /* GLOBAL DECLARATIONS */ |
| /************************************************************************/ |
| #ifdef _ANDROID_ |
| using namespace android; |
| #endif |
| |
| typedef enum { |
| CODEC_FORMAT_H264 = 1, |
| CODEC_FORMAT_MP4, |
| CODEC_FORMAT_H263, |
| CODEC_FORMAT_VC1, |
| CODEC_FORMAT_MAX = CODEC_FORMAT_VC1 |
| } codec_format; |
| |
| typedef enum { |
| FILE_TYPE_DAT_PER_AU = 1, |
| FILE_TYPE_ARBITRARY_BYTES, |
| FILE_TYPE_COMMON_CODEC_MAX, |
| |
| FILE_TYPE_START_OF_H264_SPECIFIC = 10, |
| FILE_TYPE_264_NAL_SIZE_LENGTH = FILE_TYPE_START_OF_H264_SPECIFIC, |
| |
| FILE_TYPE_START_OF_MP4_SPECIFIC = 20, |
| FILE_TYPE_PICTURE_START_CODE = FILE_TYPE_START_OF_MP4_SPECIFIC, |
| |
| FILE_TYPE_START_OF_VC1_SPECIFIC = 30, |
| FILE_TYPE_RCV = FILE_TYPE_START_OF_VC1_SPECIFIC, |
| FILE_TYPE_VC1 |
| } file_type; |
| |
| typedef enum { |
| GOOD_STATE = 0, |
| PORT_SETTING_CHANGE_STATE, |
| ERROR_STATE, |
| INVALID_STATE |
| } test_status; |
| |
| typedef enum { |
| FREE_HANDLE_AT_LOADED = 1, |
| FREE_HANDLE_AT_IDLE, |
| FREE_HANDLE_AT_EXECUTING, |
| FREE_HANDLE_AT_PAUSE |
| } freeHandle_test; |
| |
| static int (*Read_Buffer)(OMX_BUFFERHEADERTYPE *pBufHdr ); |
| |
| FILE * inputBufferFile; |
| FILE * outputBufferFile; |
| FILE * seqFile; |
| int takeYuvLog = 0; |
| int displayYuv = 0; |
| int displayWindow = 0; |
| int realtime_display = 0; |
| struct timeval t_avsync={0}; |
| |
| Queue *etb_queue = NULL; |
| Queue *fbd_queue = NULL; |
| |
| pthread_t ebd_thread_id; |
| pthread_t fbd_thread_id; |
| void* ebd_thread(void*); |
| void* fbd_thread(void*); |
| |
| pthread_mutex_t etb_lock; |
| pthread_mutex_t fbd_lock; |
| pthread_mutex_t lock; |
| pthread_cond_t cond; |
| pthread_mutex_t elock; |
| pthread_cond_t econd; |
| pthread_cond_t fcond; |
| pthread_mutex_t eos_lock; |
| pthread_cond_t eos_cond; |
| |
| sem_t etb_sem; |
| sem_t fbd_sem; |
| sem_t seq_sem; |
| sem_t in_flush_sem, out_flush_sem; |
| |
| OMX_PARAM_PORTDEFINITIONTYPE portFmt; |
| OMX_PORT_PARAM_TYPE portParam; |
| OMX_ERRORTYPE error; |
| |
| #define CLR_KEY 0xe8fd |
| #define COLOR_BLACK_RGBA_8888 0x00000000 |
| #define FRAMEBUFFER_32 |
| |
| static int fb_fd = -1; |
| static struct fb_var_screeninfo vinfo; |
| static struct fb_fix_screeninfo finfo; |
| static struct mdp_overlay overlay, *overlayp; |
| static struct msmfb_overlay_data ov_front; |
| static int vid_buf_front_id; |
| int overlay_fb(struct OMX_BUFFERHEADERTYPE *pBufHdr); |
| void overlay_set(); |
| void overlay_unset(); |
| void render_fb(struct OMX_BUFFERHEADERTYPE *pBufHdr); |
| |
| /************************************************************************/ |
| /* GLOBAL INIT */ |
| /************************************************************************/ |
| int input_buf_cnt = 0; |
| int height =0, width =0; |
| int sliceheight = 0, stride = 0; |
| int used_ip_buf_cnt = 0; |
| volatile int event_is_done = 0; |
| int ebd_cnt, fbd_cnt; |
| int bInputEosReached = 0; |
| int bOutputEosReached = 0; |
| char in_filename[512]; |
| char seq_file_name[512]; |
| unsigned char seq_enabled = 0, flush_in_progress = 0; |
| unsigned int cmd_data = 0, etb_count = 0;; |
| |
| char curr_seq_command[100]; |
| int timeStampLfile = 0; |
| int timestampInterval = 33333; |
| codec_format codec_format_option; |
| file_type file_type_option; |
| freeHandle_test freeHandle_option; |
| int nalSize; |
| int sent_disabled = 0; |
| int waitForPortSettingsChanged = 1; |
| test_status currentStatus = GOOD_STATE; |
| |
| //* OMX Spec Version supported by the wrappers. Version = 1.1 */ |
| const OMX_U32 CURRENT_OMX_SPEC_VERSION = 0x00000101; |
| OMX_COMPONENTTYPE* dec_handle = 0; |
| |
| OMX_BUFFERHEADERTYPE **pInputBufHdrs = NULL; |
| OMX_BUFFERHEADERTYPE **pOutYUVBufHdrs= NULL; |
| |
| int rcv_v1=0; |
| |
| /* Performance related variable*/ |
| //QPERF_INIT(render_fb); |
| //QPERF_INIT(client_decode); |
| |
| /************************************************************************/ |
| /* GLOBAL FUNC DECL */ |
| /************************************************************************/ |
| int Init_Decoder(); |
| int Play_Decoder(); |
| int run_tests(); |
| |
| /**************************************************************************/ |
| /* STATIC DECLARATIONS */ |
| /**************************************************************************/ |
| static int video_playback_count = 1; |
| static int open_video_file (); |
| static int Read_Buffer_From_DAT_File(OMX_BUFFERHEADERTYPE *pBufHdr ); |
| static int Read_Buffer_ArbitraryBytes(OMX_BUFFERHEADERTYPE *pBufHdr); |
| static int Read_Buffer_From_Vop_Start_Code_File(OMX_BUFFERHEADERTYPE *pBufHdr); |
| static int Read_Buffer_From_Size_Nal(OMX_BUFFERHEADERTYPE *pBufHdr); |
| static int Read_Buffer_From_RCV_File_Seq_Layer(OMX_BUFFERHEADERTYPE *pBufHdr); |
| static int Read_Buffer_From_RCV_File(OMX_BUFFERHEADERTYPE *pBufHdr); |
| static int Read_Buffer_From_VC1_File(OMX_BUFFERHEADERTYPE *pBufHdr); |
| |
| static OMX_ERRORTYPE Allocate_Buffer ( OMX_COMPONENTTYPE *dec_handle, |
| OMX_BUFFERHEADERTYPE ***pBufHdrs, |
| OMX_U32 nPortIndex, |
| long bufCntMin, long bufSize); |
| |
| |
| static OMX_ERRORTYPE EventHandler(OMX_IN OMX_HANDLETYPE hComponent, |
| OMX_IN OMX_PTR pAppData, |
| OMX_IN OMX_EVENTTYPE eEvent, |
| OMX_IN OMX_U32 nData1, OMX_IN OMX_U32 nData2, |
| OMX_IN OMX_PTR pEventData); |
| static OMX_ERRORTYPE EmptyBufferDone(OMX_IN OMX_HANDLETYPE hComponent, |
| OMX_IN OMX_PTR pAppData, |
| OMX_IN OMX_BUFFERHEADERTYPE* pBuffer); |
| static OMX_ERRORTYPE FillBufferDone(OMX_OUT OMX_HANDLETYPE hComponent, |
| OMX_OUT OMX_PTR pAppData, |
| OMX_OUT OMX_BUFFERHEADERTYPE* pBuffer); |
| |
| static void do_freeHandle_and_clean_up(bool isDueToError); |
| |
| /*static usecs_t get_time(void) |
| { |
| struct timeval tv; |
| gettimeofday(&tv, 0); |
| return ((usecs_t)tv.tv_usec) + |
| (((usecs_t)tv.tv_sec) * ((usecs_t)1000000)); |
| }*/ |
| |
| |
| void wait_for_event(void) |
| { |
| DEBUG_PRINT("Waiting for event\n"); |
| pthread_mutex_lock(&lock); |
| while (event_is_done == 0) { |
| pthread_cond_wait(&cond, &lock); |
| } |
| event_is_done = 0; |
| pthread_mutex_unlock(&lock); |
| DEBUG_PRINT("Running .... get the event\n"); |
| } |
| |
| void event_complete(void ) |
| { |
| pthread_mutex_lock(&lock); |
| if (event_is_done == 0) { |
| event_is_done = 1; |
| pthread_cond_broadcast(&cond); |
| } |
| pthread_mutex_unlock(&lock); |
| } |
| int get_next_command(FILE *seq_file) |
| { |
| int i = -1; |
| do{ |
| i++; |
| if(fread(&curr_seq_command[i], 1, 1, seq_file) != 1) |
| return -1; |
| }while(curr_seq_command[i] != '\n'); |
| curr_seq_command[i] = 0; |
| printf("\n cmd_str = %s", curr_seq_command); |
| return 0; |
| } |
| |
| void process_current_command(const char *seq_command) |
| { |
| char *data_str = NULL; |
| unsigned int data = 0, bufCnt = 0, i = 0; |
| int frameSize; |
| OMX_ERRORTYPE ret; |
| |
| if(strstr(seq_command, "pause") == seq_command) |
| { |
| printf("\n\n $$$$$ PAUSE $$$$$"); |
| data_str = (char*)seq_command + strlen("pause") + 1; |
| data = atoi(data_str); |
| printf("\n After frame number %u", data); |
| cmd_data = data; |
| sem_wait(&seq_sem); |
| printf("\n Sending PAUSE cmd to OMX compt"); |
| OMX_SendCommand(dec_handle, OMX_CommandStateSet, OMX_StatePause,0); |
| wait_for_event(); |
| printf("\n EventHandler for PAUSE DONE"); |
| } |
| else if(strstr(seq_command, "sleep") == seq_command) |
| { |
| printf("\n\n $$$$$ SLEEP $$$$$"); |
| data_str = (char*)seq_command + strlen("sleep") + 1; |
| data = atoi(data_str); |
| printf("\n Sleep Time = %u ms", data); |
| usleep(data*1000); |
| } |
| else if(strstr(seq_command, "resume") == seq_command) |
| { |
| printf("\n\n $$$$$ RESUME $$$$$"); |
| printf("\n Immediate effect", data); |
| printf("\n Sending PAUSE cmd to OMX compt"); |
| OMX_SendCommand(dec_handle, OMX_CommandStateSet, OMX_StateExecuting,0); |
| wait_for_event(); |
| printf("\n EventHandler for RESUME DONE"); |
| } |
| else if(strstr(seq_command, "flush") == seq_command) |
| { |
| printf("\n\n $$$$$ FLUSH $$$$$"); |
| data_str = (char*)seq_command + strlen("flush") + 1; |
| data = atoi(data_str); |
| printf("\n After frame number %u", data); |
| cmd_data = data; |
| sem_wait(&seq_sem); |
| printf("\n Sending FLUSH cmd to OMX compt"); |
| flush_in_progress = 1; |
| OMX_SendCommand(dec_handle, OMX_CommandFlush, OMX_ALL, 0); |
| wait_for_event(); |
| flush_in_progress = 0; |
| printf("\n EventHandler for FLUSH DONE"); |
| printf("\n Post EBD_thread flush sem"); |
| sem_post(&in_flush_sem); |
| printf("\n Post FBD_thread flush sem"); |
| sem_post(&out_flush_sem); |
| } |
| else |
| { |
| printf("\n\n $$$$$ INVALID CMD $$$$$"); |
| printf("\n seq_command[%s] is invalid", seq_command); |
| seq_enabled = 0; |
| } |
| } |
| |
| void* ebd_thread(void* pArg) |
| { |
| while(currentStatus != INVALID_STATE) |
| { |
| int readBytes =0; |
| OMX_BUFFERHEADERTYPE* pBuffer = NULL; |
| |
| if(flush_in_progress) |
| { |
| printf("\n EBD_thread flush wait start"); |
| sem_wait(&in_flush_sem); |
| printf("\n EBD_thread flush wait complete"); |
| } |
| |
| sem_wait(&etb_sem); |
| pthread_mutex_lock(&etb_lock); |
| pBuffer = (OMX_BUFFERHEADERTYPE *) pop(etb_queue); |
| pthread_mutex_unlock(&etb_lock); |
| if(pBuffer == NULL) |
| { |
| DEBUG_PRINT_ERROR("Error - No etb pBuffer to dequeue\n"); |
| continue; |
| } |
| |
| pBuffer->nOffset = 0; |
| if((readBytes = Read_Buffer(pBuffer)) > 0) { |
| pBuffer->nFilledLen = readBytes; |
| OMX_EmptyThisBuffer(dec_handle,pBuffer); |
| etb_count++; |
| if(cmd_data == etb_count) |
| { |
| sem_post(&seq_sem); |
| printf("\n Posted seq_sem"); |
| } |
| } |
| else |
| { |
| pBuffer->nFlags |= OMX_BUFFERFLAG_EOS; |
| bInputEosReached = true; |
| pBuffer->nFilledLen = readBytes; |
| OMX_EmptyThisBuffer(dec_handle,pBuffer); |
| DEBUG_PRINT("EBD::Either EOS or Some Error while reading file\n"); |
| etb_count++; |
| if(cmd_data == etb_count) |
| { |
| sem_post(&seq_sem); |
| printf("\n Posted seq_sem"); |
| } |
| break; |
| } |
| } |
| return NULL; |
| } |
| |
| void* fbd_thread(void* pArg) |
| { |
| while(currentStatus != INVALID_STATE) |
| { |
| long current_avsync_time = 0, delta_time = 0; |
| int canDisplay = 1; |
| static int contigous_drop_frame = 0; |
| static long base_avsync_time = 0; |
| static long base_timestamp = 0; |
| long lipsync_time = 250000; |
| int bytes_written = 0; |
| OMX_BUFFERHEADERTYPE *pBuffer; |
| |
| if(flush_in_progress) |
| { |
| printf("\n FBD_thread flush wait start"); |
| sem_wait(&out_flush_sem); |
| printf("\n FBD_thread flush wait complete"); |
| } |
| |
| sem_wait(&fbd_sem); |
| DEBUG_PRINT("Inside %s fbd_cnt[%d] \n", __FUNCTION__, fbd_cnt); |
| |
| fbd_cnt++; |
| pthread_mutex_lock(&fbd_lock); |
| pBuffer = (OMX_BUFFERHEADERTYPE *) pop(fbd_queue); |
| pthread_mutex_unlock(&fbd_lock); |
| if (pBuffer == NULL) |
| { |
| DEBUG_PRINT("Error - No pBuffer to dequeue\n"); |
| continue; |
| } |
| |
| /********************************************* |
| Write the output of the decoder to the file. |
| *********************************************/ |
| |
| if (sent_disabled) |
| { |
| DEBUG_PRINT("Ignoring FillBufferDone\n"); |
| continue; |
| } |
| |
| if (realtime_display) |
| { |
| if(!gettimeofday(&t_avsync,NULL)) |
| { |
| current_avsync_time =(t_avsync.tv_sec*1000000)+t_avsync.tv_usec; |
| } |
| |
| if (base_avsync_time != 0) |
| { |
| pthread_mutex_lock(&fbd_lock); |
| delta_time = (current_avsync_time - base_avsync_time) - ((long)pBuffer->nTimeStamp - base_timestamp); |
| if (delta_time < 0 ) |
| { |
| DEBUG_PRINT_ERROR("Sleep %d us. AV Sync time is left behind\n", |
| -delta_time); |
| usleep(-delta_time); |
| canDisplay = 1; |
| } |
| else if ((delta_time>lipsync_time) && (contigous_drop_frame < 6)) |
| { |
| DEBUG_PRINT_ERROR("Error - Drop the frame at the renderer. Video frame with ts %lu usec behind by %ld usec" |
| ", pBuffer->nFilledLen %u\n", |
| (unsigned long)pBuffer->nTimeStamp, delta_time, pBuffer->nFilledLen); |
| canDisplay = 0; |
| contigous_drop_frame++; |
| } |
| else |
| { |
| canDisplay = 1; |
| } |
| pthread_mutex_unlock(&fbd_lock); |
| } |
| else |
| { |
| base_avsync_time = current_avsync_time; |
| base_timestamp = (long)pBuffer->nTimeStamp; |
| } |
| } |
| |
| if (!flush_in_progress && displayYuv && canDisplay && pBuffer->nFilledLen > 0) |
| { |
| if(overlay_fb(pBuffer)) |
| break; |
| contigous_drop_frame = 0; |
| } |
| |
| if (!flush_in_progress && takeYuvLog) { |
| pthread_mutex_lock(&fbd_lock); |
| bytes_written = fwrite((const char *)pBuffer->pBuffer, |
| pBuffer->nFilledLen,1,outputBufferFile); |
| pthread_mutex_unlock(&fbd_lock); |
| if (bytes_written < 0) { |
| DEBUG_PRINT("\nFillBufferDone: Failed to write to the file\n"); |
| } |
| else { |
| DEBUG_PRINT("\nFillBufferDone: Wrote %d YUV bytes to the file\n", |
| bytes_written); |
| } |
| } |
| |
| /********************************************************************/ |
| /* De-Initializing the open max and relasing the buffers and */ |
| /* closing the files.*/ |
| /********************************************************************/ |
| if (pBuffer->nFlags & OMX_BUFFERFLAG_EOS ) { |
| DEBUG_PRINT("***************************************************\n"); |
| DEBUG_PRINT("FillBufferDone: End Of Stream Reached\n"); |
| DEBUG_PRINT("***************************************************\n"); |
| pthread_mutex_lock(&eos_lock); |
| bOutputEosReached = true; |
| pthread_cond_broadcast(&eos_cond); |
| pthread_mutex_unlock(&eos_lock); |
| //QPERF_END(client_decode); |
| //QPERF_SET_ITERATION(client_decode, fbd_cnt); |
| DEBUG_PRINT("***************************************************\n"); |
| DEBUG_PRINT("FBD_THREAD bOutputEosReached %d\n",bOutputEosReached); |
| break; |
| } |
| OMX_FillThisBuffer(dec_handle, pBuffer); |
| } |
| return NULL; |
| } |
| |
| OMX_ERRORTYPE EventHandler(OMX_IN OMX_HANDLETYPE hComponent, |
| OMX_IN OMX_PTR pAppData, |
| OMX_IN OMX_EVENTTYPE eEvent, |
| OMX_IN OMX_U32 nData1, OMX_IN OMX_U32 nData2, |
| OMX_IN OMX_PTR pEventData) |
| { |
| DEBUG_PRINT("Function %s \n", __FUNCTION__); |
| |
| switch(eEvent) { |
| case OMX_EventCmdComplete: |
| DEBUG_PRINT("\n OMX_EventCmdComplete \n"); |
| // check nData1 for DISABLE event |
| if(OMX_CommandPortDisable == (OMX_COMMANDTYPE)nData1) |
| { |
| DEBUG_PRINT("*********************************************\n"); |
| DEBUG_PRINT("Recieved DISABLE Event Command Complete[%d]\n",nData2); |
| DEBUG_PRINT("*********************************************\n"); |
| sent_disabled = 0; |
| } |
| else if(OMX_CommandPortEnable == (OMX_COMMANDTYPE)nData1) |
| { |
| DEBUG_PRINT("*********************************************\n"); |
| DEBUG_PRINT("Recieved ENABLE Event Command Complete[%d]\n",nData2); |
| DEBUG_PRINT("*********************************************\n"); |
| } |
| currentStatus = GOOD_STATE; |
| event_complete(); |
| break; |
| |
| case OMX_EventError: |
| DEBUG_PRINT("OMX_EventError \n"); |
| currentStatus = ERROR_STATE; |
| if (OMX_ErrorInvalidState == (OMX_ERRORTYPE)nData1 || |
| OMX_ErrorHardware == (OMX_ERRORTYPE)nData1) |
| { |
| DEBUG_PRINT("Invalid State or hardware error \n"); |
| currentStatus = INVALID_STATE; |
| if(event_is_done == 0) |
| { |
| DEBUG_PRINT("Event error in the middle of Decode \n"); |
| pthread_mutex_lock(&eos_lock); |
| bOutputEosReached = true; |
| pthread_cond_broadcast(&eos_cond); |
| pthread_mutex_unlock(&eos_lock); |
| |
| } |
| } |
| |
| event_complete(); |
| break; |
| case OMX_EventPortSettingsChanged: |
| DEBUG_PRINT("OMX_EventPortSettingsChanged port[%d]\n",nData1); |
| waitForPortSettingsChanged = 0; |
| currentStatus = PORT_SETTING_CHANGE_STATE; |
| // reset the event |
| event_complete(); |
| break; |
| |
| default: |
| DEBUG_PRINT_ERROR("ERROR - Unknown Event \n"); |
| break; |
| } |
| return OMX_ErrorNone; |
| } |
| |
| OMX_ERRORTYPE EmptyBufferDone(OMX_IN OMX_HANDLETYPE hComponent, |
| OMX_IN OMX_PTR pAppData, |
| OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) |
| { |
| int readBytes =0; int bufCnt=0; |
| OMX_ERRORTYPE result; |
| |
| DEBUG_PRINT("Function %s cnt[%d]\n", __FUNCTION__, ebd_cnt); |
| ebd_cnt++; |
| |
| |
| if(bInputEosReached) { |
| DEBUG_PRINT("*****EBD:Input EoS Reached************\n"); |
| return OMX_ErrorNone; |
| } |
| |
| pthread_mutex_lock(&etb_lock); |
| if(push(etb_queue, (void *) pBuffer) < 0) |
| { |
| DEBUG_PRINT_ERROR("Error in enqueue ebd data\n"); |
| return OMX_ErrorUndefined; |
| } |
| pthread_mutex_unlock(&etb_lock); |
| sem_post(&etb_sem); |
| |
| return OMX_ErrorNone; |
| } |
| |
| OMX_ERRORTYPE FillBufferDone(OMX_OUT OMX_HANDLETYPE hComponent, |
| OMX_OUT OMX_PTR pAppData, |
| OMX_OUT OMX_BUFFERHEADERTYPE* pBuffer) |
| { |
| DEBUG_PRINT("Inside %s callback_count[%d] \n", __FUNCTION__, fbd_cnt); |
| |
| /* Test app will assume there is a dynamic port setting |
| * In case that there is no dynamic port setting, OMX will not call event cb, |
| * instead OMX will send empty this buffer directly and we need to clear an event here |
| */ |
| if(waitForPortSettingsChanged) |
| { |
| currentStatus = GOOD_STATE; |
| waitForPortSettingsChanged = 0; |
| |
| if(displayYuv) |
| { |
| overlay_set(); |
| } |
| event_complete(); |
| } |
| |
| if(!sent_disabled) |
| { |
| pthread_mutex_lock(&fbd_lock); |
| if(push(fbd_queue, (void *)pBuffer) < 0) |
| { |
| DEBUG_PRINT_ERROR("Error in enqueueing fbd_data\n"); |
| return OMX_ErrorUndefined; |
| } |
| pthread_mutex_unlock(&fbd_lock); |
| sem_post(&fbd_sem); |
| } |
| return OMX_ErrorNone; |
| } |
| |
| int main(int argc, char **argv) |
| { |
| int i=0; |
| int bufCnt=0; |
| int num=0; |
| int outputOption = 0; |
| int test_option = 0; |
| OMX_ERRORTYPE result; |
| |
| if (argc < 2) |
| { |
| printf("To use it: ./mm-vdec-omx-test <clip location> \n"); |
| printf("Command line argument is also available\n"); |
| return -1; |
| } |
| |
| strncpy(in_filename, argv[1], strlen(argv[1])+1); |
| |
| if(argc > 5) |
| { |
| codec_format_option = (codec_format)atoi(argv[2]); |
| file_type_option = (file_type)atoi(argv[3]); |
| } |
| else |
| { |
| printf("Command line argument is available\n"); |
| printf("To use it: ./mm-vdec-omx-test <clip location> <codec_type> \n"); |
| printf(" <input_type: 1. per AU(.dat), 2. arbitrary, 3.per NAL/frame>\n"); |
| printf(" <output_type> <test_case> <size_nal if H264>\n\n\n"); |
| |
| printf(" *********************************************\n"); |
| printf(" ENTER THE TEST CASE YOU WOULD LIKE TO EXECUTE\n"); |
| printf(" *********************************************\n"); |
| printf(" 1--> H264\n"); |
| printf(" 2--> MP4\n"); |
| printf(" 3--> H263\n"); |
| printf(" 4--> VC1\n"); |
| fflush(stdin); |
| scanf("%d", &codec_format_option); |
| fflush(stdin); |
| |
| if (codec_format_option > CODEC_FORMAT_MAX) |
| { |
| printf(" Wrong test case...[%d] \n", codec_format_option); |
| return -1; |
| } |
| |
| printf(" *********************************************\n"); |
| printf(" ENTER THE TEST CASE YOU WOULD LIKE TO EXECUTE\n"); |
| printf(" *********************************************\n"); |
| printf(" 1--> PER ACCESS UNIT CLIP (.dat). Clip only available for H264 and Mpeg4\n"); |
| printf(" 2--> ARBITRARY BYTES (need .264/.264c/.mv4/.263/.rcv/.vc1)\n"); |
| if (codec_format_option == CODEC_FORMAT_H264) |
| { |
| printf(" 3--> NAL LENGTH SIZE CLIP (.264c)\n"); |
| } |
| else if ( (codec_format_option == CODEC_FORMAT_MP4) || (codec_format_option == CODEC_FORMAT_H263) ) |
| { |
| printf(" 3--> MP4 VOP or H263 P0 SHORT HEADER START CODE CLIP (.m4v or .263)\n"); |
| } |
| else if (codec_format_option == CODEC_FORMAT_VC1) |
| { |
| printf(" 3--> VC1 clip Simple/Main Profile (.rcv)\n"); |
| printf(" 4--> VC1 clip Advance Profile (.vc1)\n"); |
| } |
| fflush(stdin); |
| scanf("%d", &file_type_option); |
| fflush(stdin); |
| } |
| |
| if (file_type_option >= FILE_TYPE_COMMON_CODEC_MAX) |
| { |
| switch (codec_format_option) |
| { |
| case CODEC_FORMAT_H264: |
| file_type_option = (file_type)(FILE_TYPE_START_OF_H264_SPECIFIC + file_type_option - FILE_TYPE_COMMON_CODEC_MAX); |
| break; |
| case CODEC_FORMAT_MP4: |
| case CODEC_FORMAT_H263: |
| file_type_option = (file_type)(FILE_TYPE_START_OF_MP4_SPECIFIC + file_type_option - FILE_TYPE_COMMON_CODEC_MAX); |
| break; |
| case CODEC_FORMAT_VC1: |
| file_type_option = (file_type)(FILE_TYPE_START_OF_VC1_SPECIFIC + file_type_option - FILE_TYPE_COMMON_CODEC_MAX); |
| break; |
| default: |
| printf("Error: Unknown code %d\n", codec_format_option); |
| } |
| } |
| |
| if(argc > 5) |
| { |
| outputOption = atoi(argv[4]); |
| test_option = atoi(argv[5]); |
| if (argc > 6) |
| { |
| nalSize = atoi(argv[6]); |
| } |
| else |
| { |
| nalSize = 0; |
| } |
| |
| if(argc > 7) |
| { |
| displayWindow = atoi(argv[7]); |
| if(displayWindow > 0) |
| { |
| printf(" Curently display window 0 only supported; ignoring other values\n"); |
| displayWindow = 0; |
| } |
| } |
| else |
| { |
| displayWindow = 0; |
| } |
| |
| if((file_type_option == FILE_TYPE_PICTURE_START_CODE) || |
| (file_type_option == FILE_TYPE_RCV) || |
| (file_type_option == FILE_TYPE_VC1) && argc > 8) |
| { |
| realtime_display = atoi(argv[8]); |
| } |
| |
| if(realtime_display) |
| { |
| takeYuvLog = 0; |
| if(argc > 9) |
| { |
| int fps = atoi(argv[9]); |
| timestampInterval = 1000000/fps; |
| } |
| else if(argc > 10) |
| { |
| strncpy(seq_file_name, argv[10], strlen(argv[10])+1); |
| } |
| } |
| else |
| { |
| if(argc > 9) |
| { |
| strncpy(seq_file_name, argv[9], strlen(argv[9])+1); |
| } |
| } |
| height=144;width=176; // Assume Default as QCIF |
| sliceheight = 144; |
| stride = 176; |
| printf("Executing DynPortReconfig QCIF 144 x 176 \n"); |
| } |
| else |
| { |
| int fps = 30; |
| switch(file_type_option) |
| { |
| case FILE_TYPE_DAT_PER_AU: |
| case FILE_TYPE_ARBITRARY_BYTES: |
| case FILE_TYPE_264_NAL_SIZE_LENGTH: |
| case FILE_TYPE_PICTURE_START_CODE: |
| case FILE_TYPE_RCV: |
| case FILE_TYPE_VC1: |
| { |
| nalSize = 0; |
| if ((file_type_option == FILE_TYPE_264_NAL_SIZE_LENGTH) || |
| ((codec_format_option == CODEC_FORMAT_H264) && (file_type_option == FILE_TYPE_ARBITRARY_BYTES))) |
| { |
| printf(" Enter Nal length size [2 or 4] \n"); |
| if (file_type_option == FILE_TYPE_ARBITRARY_BYTES) |
| { |
| printf(" Enter 0 if it is a start code based clip\n"); |
| } |
| scanf("%d", &nalSize); |
| if ((file_type_option == FILE_TYPE_264_NAL_SIZE_LENGTH) && |
| (nalSize == 0)) |
| { |
| printf("Error - Can't pass NAL length size = 0\n"); |
| return -1; |
| } |
| } |
| |
| height=144;width=176; // Assume Default as QCIF |
| printf("Executing DynPortReconfig QCIF 144 x 176 \n"); |
| break; |
| } |
| |
| default: |
| { |
| printf(" Wrong test case...[%d] \n",file_type_option); |
| return -1; |
| } |
| } |
| |
| printf(" *********************************************\n"); |
| printf(" Output buffer option:\n"); |
| printf(" *********************************************\n"); |
| printf(" 0 --> No display and no YUV log\n"); |
| printf(" 1 --> Diplay YUV\n"); |
| printf(" 2 --> Take YUV log\n"); |
| printf(" 3 --> Display YUV and take YUV log\n"); |
| fflush(stdin); |
| scanf("%d", &outputOption); |
| fflush(stdin); |
| |
| printf(" *********************************************\n"); |
| printf(" ENTER THE TEST CASE YOU WOULD LIKE TO EXECUTE\n"); |
| printf(" *********************************************\n"); |
| printf(" 1 --> Play the clip till the end\n"); |
| printf(" 2 --> Run compliance test. Do NOT expect any display for most option. \n"); |
| printf(" Please only see \"TEST SUCCESSFULL\" to indidcate test pass\n"); |
| fflush(stdin); |
| scanf("%d", &test_option); |
| fflush(stdin); |
| |
| printf(" *********************************************\n"); |
| printf(" ENTER THE PORTION OF DISPLAY TO USE\n"); |
| printf(" *********************************************\n"); |
| printf(" 0 --> Entire Screen\n"); |
| printf(" 1 --> 1/4 th of the screen starting from top left corner to middle \n"); |
| printf(" 2 --> 1/4 th of the screen starting from middle to top right corner \n"); |
| printf(" 3 --> 1/4 th of the screen starting from middle to bottom left \n"); |
| printf(" 4 --> 1/4 th of the screen starting from middle to bottom right \n"); |
| printf(" Please only see \"TEST SUCCESSFULL\" to indidcate test pass\n"); |
| fflush(stdin); |
| scanf("%d", &displayWindow); |
| fflush(stdin); |
| |
| if(displayWindow > 0) |
| { |
| printf(" Curently display window 0 only supported; ignoring other values\n"); |
| displayWindow = 0; |
| } |
| |
| if((file_type_option == FILE_TYPE_PICTURE_START_CODE) || |
| (file_type_option == FILE_TYPE_RCV) || |
| (file_type_option == FILE_TYPE_VC1)) |
| { |
| printf(" *********************************************\n"); |
| printf(" DO YOU WANT TEST APP TO RENDER in Real time \n"); |
| printf(" 0 --> NO\n 1 --> YES\n"); |
| printf(" Warning: For H264, it require one NAL per frame clip.\n"); |
| printf(" For Arbitrary bytes option, Real time display is not recommended\n"); |
| printf(" *********************************************\n"); |
| fflush(stdin); |
| scanf("%d", &realtime_display); |
| fflush(stdin); |
| } |
| |
| |
| if (realtime_display) |
| { |
| printf(" *********************************************\n"); |
| printf(" ENTER THE CLIP FPS\n"); |
| printf(" Exception: Timestamp extracted from clips will be used.\n"); |
| printf(" *********************************************\n"); |
| fflush(stdin); |
| scanf("%d", &fps); |
| fflush(stdin); |
| timestampInterval = 1000000/fps; |
| } |
| printf(" *********************************************\n"); |
| printf(" ENTER THE SEQ FILE NAME\n"); |
| printf(" *********************************************\n"); |
| fflush(stdin); |
| scanf("%[^\n]", &seq_file_name); |
| fflush(stdin); |
| } |
| |
| if (outputOption == 0) |
| { |
| displayYuv = 0; |
| takeYuvLog = 0; |
| realtime_display = 0; |
| } |
| else if (outputOption == 1) |
| { |
| displayYuv = 1; |
| } |
| else if (outputOption == 2) |
| { |
| takeYuvLog = 1; |
| realtime_display = 0; |
| } |
| else if (outputOption == 3) |
| { |
| displayYuv = 1; |
| takeYuvLog = !realtime_display; |
| } |
| else |
| { |
| printf("Wrong option. Assume you want to see the YUV display\n"); |
| displayYuv = 1; |
| } |
| |
| if (test_option == 2) |
| { |
| printf(" *********************************************\n"); |
| printf(" ENTER THE COMPLIANCE TEST YOU WOULD LIKE TO EXECUTE\n"); |
| printf(" *********************************************\n"); |
| printf(" 1 --> Call Free Handle at the OMX_StateLoaded\n"); |
| printf(" 2 --> Call Free Handle at the OMX_StateIdle\n"); |
| printf(" 3 --> Call Free Handle at the OMX_StateExecuting\n"); |
| printf(" 4 --> Call Free Handle at the OMX_StatePause\n"); |
| fflush(stdin); |
| scanf("%d", &freeHandle_option); |
| fflush(stdin); |
| } |
| else |
| { |
| freeHandle_option = (freeHandle_test)0; |
| } |
| |
| printf("Input values: inputfilename[%s]\n", in_filename); |
| printf("*******************************************************\n"); |
| pthread_cond_init(&cond, 0); |
| pthread_cond_init(&eos_cond, 0); |
| pthread_mutex_init(&eos_lock, 0); |
| pthread_mutex_init(&lock, 0); |
| pthread_mutex_init(&etb_lock, 0); |
| pthread_mutex_init(&fbd_lock, 0); |
| if (-1 == sem_init(&etb_sem, 0, 0)) |
| { |
| printf("Error - sem_init failed %d\n", errno); |
| } |
| if (-1 == sem_init(&fbd_sem, 0, 0)) |
| { |
| printf("Error - sem_init failed %d\n", errno); |
| } |
| if (-1 == sem_init(&seq_sem, 0, 0)) |
| { |
| printf("Error - sem_init failed %d\n", errno); |
| } |
| if (-1 == sem_init(&in_flush_sem, 0, 0)) |
| { |
| printf("Error - sem_init failed %d\n", errno); |
| } |
| if (-1 == sem_init(&out_flush_sem, 0, 0)) |
| { |
| printf("Error - sem_init failed %d\n", errno); |
| } |
| etb_queue = alloc_queue(); |
| if (etb_queue == NULL) |
| { |
| printf("\n Error in Creating etb_queue\n"); |
| return -1; |
| } |
| |
| fbd_queue = alloc_queue(); |
| if (fbd_queue == NULL) |
| { |
| printf("\n Error in Creating fbd_queue\n"); |
| free_queue(etb_queue); |
| return -1; |
| } |
| |
| if(0 != pthread_create(&fbd_thread_id, NULL, fbd_thread, NULL)) |
| { |
| printf("\n Error in Creating fbd_thread \n"); |
| free_queue(etb_queue); |
| free_queue(fbd_queue); |
| return -1; |
| } |
| |
| if (displayYuv) |
| { |
| //QPERF_RESET(render_fb); |
| #ifdef _ANDROID_ |
| DEBUG_PRINT("\n Opening /dev/graphics/fb0"); |
| fb_fd = open("/dev/graphics/fb0", O_RDWR); |
| #else |
| DEBUG_PRINT("\n Opening /dev/fb0"); |
| fb_fd = open("/dev/fb0", O_RDWR); |
| #endif |
| if (fb_fd < 0) { |
| printf("[omx_vdec_test] - ERROR - can't open framebuffer!\n"); |
| return -1; |
| } |
| |
| DEBUG_PRINT("\n fb_fd = %d", fb_fd); |
| if (ioctl(fb_fd, FBIOGET_FSCREENINFO, &finfo) < 0) |
| { |
| printf("[omx_vdec_test] - ERROR - can't retrieve fscreenInfo!\n"); |
| close(fb_fd); |
| return -1; |
| } |
| if (ioctl(fb_fd, FBIOGET_VSCREENINFO, &vinfo) < 0) |
| { |
| printf("[omx_vdec_test] - ERROR - can't retrieve vscreenInfo!\n"); |
| close(fb_fd); |
| return -1; |
| } |
| } |
| |
| run_tests(); |
| pthread_cond_destroy(&cond); |
| pthread_mutex_destroy(&lock); |
| pthread_mutex_destroy(&etb_lock); |
| pthread_mutex_destroy(&fbd_lock); |
| pthread_cond_destroy(&eos_cond); |
| pthread_mutex_destroy(&eos_lock); |
| if (-1 == sem_destroy(&etb_sem)) |
| { |
| DEBUG_PRINT_ERROR("Error - sem_destroy failed %d\n", errno); |
| } |
| if (-1 == sem_destroy(&fbd_sem)) |
| { |
| DEBUG_PRINT_ERROR("Error - sem_destroy failed %d\n", errno); |
| } |
| if (-1 == sem_destroy(&seq_sem)) |
| { |
| DEBUG_PRINT_ERROR("Error - sem_destroy failed %d\n", errno); |
| } |
| if (-1 == sem_destroy(&in_flush_sem)) |
| { |
| DEBUG_PRINT_ERROR("Error - sem_destroy failed %d\n", errno); |
| } |
| if (-1 == sem_destroy(&out_flush_sem)) |
| { |
| DEBUG_PRINT_ERROR("Error - sem_destroy failed %d\n", errno); |
| } |
| if (displayYuv) |
| { |
| overlay_unset(); |
| close(fb_fd); |
| fb_fd = -1; |
| //QPERF_TERMINATE(render_fb); |
| } |
| //QPERF_TERMINATE(client_decode); |
| return 0; |
| } |
| |
| int run_tests() |
| { |
| DEBUG_PRINT("Inside %s\n", __FUNCTION__); |
| waitForPortSettingsChanged = 1; |
| currentStatus = GOOD_STATE; |
| |
| if(file_type_option == FILE_TYPE_DAT_PER_AU) { |
| Read_Buffer = Read_Buffer_From_DAT_File; |
| } |
| else if(file_type_option == FILE_TYPE_ARBITRARY_BYTES) { |
| Read_Buffer = Read_Buffer_ArbitraryBytes; |
| } |
| else if(codec_format_option == CODEC_FORMAT_H264) { |
| Read_Buffer = Read_Buffer_From_Size_Nal; |
| } |
| else if((codec_format_option == CODEC_FORMAT_H263) || |
| (codec_format_option == CODEC_FORMAT_MP4)) { |
| Read_Buffer = Read_Buffer_From_Vop_Start_Code_File; |
| } |
| else if(file_type_option == FILE_TYPE_RCV) { |
| Read_Buffer = Read_Buffer_From_RCV_File; |
| } |
| else if(file_type_option == FILE_TYPE_VC1) { |
| Read_Buffer = Read_Buffer_From_VC1_File; |
| } |
| |
| DEBUG_PRINT("file_type_option %d!\n", file_type_option); |
| |
| switch(file_type_option) |
| { |
| case FILE_TYPE_DAT_PER_AU: |
| case FILE_TYPE_ARBITRARY_BYTES: |
| case FILE_TYPE_264_NAL_SIZE_LENGTH: |
| case FILE_TYPE_PICTURE_START_CODE: |
| case FILE_TYPE_RCV: |
| case FILE_TYPE_VC1: |
| if(Init_Decoder()!= 0x00) |
| { |
| DEBUG_PRINT_ERROR("Error - Decoder Init failed\n"); |
| return -1; |
| } |
| if(Play_Decoder() != 0x00) |
| { |
| return -1; |
| } |
| break; |
| default: |
| DEBUG_PRINT_ERROR("Error - Invalid Entry...%d\n",file_type_option); |
| break; |
| } |
| |
| if(strlen(seq_file_name)) |
| { |
| seqFile = fopen (seq_file_name, "rb"); |
| if (seqFile == NULL) |
| { |
| DEBUG_PRINT_ERROR("Error - Seq file %s could NOT be opened\n", |
| seq_file_name); |
| } |
| else |
| { |
| DEBUG_PRINT("Seq file %s is opened \n", seq_file_name); |
| seq_enabled = 1; |
| } |
| } |
| |
| pthread_mutex_lock(&eos_lock); |
| while (bOutputEosReached == false) |
| { |
| if(seq_enabled) |
| { |
| if(!get_next_command(seqFile)) |
| { |
| process_current_command(curr_seq_command); |
| } |
| else |
| { |
| printf("\n Error in get_next_cmd or EOF"); |
| seq_enabled = 0; |
| } |
| } |
| else |
| { |
| pthread_cond_wait(&eos_cond, &eos_lock); |
| } |
| } |
| pthread_mutex_unlock(&eos_lock); |
| |
| // Wait till EOS is reached... |
| if(bOutputEosReached) |
| { |
| int bufCnt = 0; |
| |
| DEBUG_PRINT("Moving the decoder to idle state \n"); |
| OMX_SendCommand(dec_handle, OMX_CommandStateSet, OMX_StateIdle,0); |
| wait_for_event(); |
| if (currentStatus == INVALID_STATE) |
| { |
| do_freeHandle_and_clean_up(true); |
| return 0; |
| } |
| |
| DEBUG_PRINT("Moving the decoder to loaded state \n"); |
| OMX_SendCommand(dec_handle, OMX_CommandStateSet, OMX_StateLoaded,0); |
| |
| DEBUG_PRINT("[OMX Vdec Test] - Deallocating i/p and o/p buffers \n"); |
| for(bufCnt=0; bufCnt < input_buf_cnt; ++bufCnt) |
| { |
| OMX_FreeBuffer(dec_handle, 0, pInputBufHdrs[bufCnt]); |
| } |
| |
| for(bufCnt=0; bufCnt < portFmt.nBufferCountActual; ++bufCnt) |
| { |
| OMX_FreeBuffer(dec_handle, 1, pOutYUVBufHdrs[bufCnt]); |
| } |
| |
| fbd_cnt = 0; ebd_cnt=0; |
| bInputEosReached = false; |
| bOutputEosReached = false; |
| |
| wait_for_event(); |
| |
| DEBUG_PRINT("[OMX Vdec Test] - Free handle decoder\n"); |
| OMX_ERRORTYPE result = OMX_FreeHandle(dec_handle); |
| if (result != OMX_ErrorNone) |
| { |
| DEBUG_PRINT_ERROR("[OMX Vdec Test] - Terminate: OMX_FreeHandle error. Error code: %d\n", result); |
| } |
| dec_handle = NULL; |
| |
| /* Deinit OpenMAX */ |
| DEBUG_PRINT("[OMX Vdec Test] - Terminate: De-initializing OMX \n"); |
| OMX_Deinit(); |
| |
| DEBUG_PRINT("[OMX Vdec Test] - Terminate: closing all files\n"); |
| if(inputBufferFile) |
| { |
| fclose(inputBufferFile); |
| inputBufferFile = NULL; |
| } |
| |
| |
| if (takeYuvLog && outputBufferFile) { |
| fclose(outputBufferFile); |
| outputBufferFile = NULL; |
| } |
| |
| if(etb_queue) |
| { |
| free_queue(etb_queue); |
| etb_queue = NULL; |
| } |
| if(fbd_queue) |
| { |
| free_queue(fbd_queue); |
| fbd_queue = NULL; |
| } |
| |
| printf("*****************************************\n"); |
| printf("******...TEST SUCCESSFULL...*******\n"); |
| printf("*****************************************\n"); |
| |
| } |
| |
| return 0; |
| } |
| |
| int Init_Decoder() |
| { |
| DEBUG_PRINT("Inside %s \n", __FUNCTION__); |
| OMX_ERRORTYPE omxresult; |
| OMX_U32 total = 0; |
| char vdecCompNames[50]; |
| typedef OMX_U8* OMX_U8_PTR; |
| char *role ="video_decoder"; |
| |
| static OMX_CALLBACKTYPE call_back = {&EventHandler, &EmptyBufferDone, &FillBufferDone}; |
| |
| int i = 0; |
| long bufCnt = 0; |
| |
| /* Init. the OpenMAX Core */ |
| DEBUG_PRINT("\nInitializing OpenMAX Core....\n"); |
| omxresult = OMX_Init(); |
| |
| if(OMX_ErrorNone != omxresult) { |
| DEBUG_PRINT_ERROR("\n Failed to Init OpenMAX core"); |
| return -1; |
| } |
| else { |
| DEBUG_PRINT_ERROR("\nOpenMAX Core Init Done\n"); |
| } |
| |
| /* Query for video decoders*/ |
| OMX_GetComponentsOfRole(role, &total, 0); |
| DEBUG_PRINT("\nTotal components of role=%s :%d", role, total); |
| |
| if(total) |
| { |
| /* Allocate memory for pointers to component name */ |
| OMX_U8** vidCompNames = (OMX_U8**)malloc((sizeof(OMX_U8*))*total); |
| |
| for (i = 0; i < total; ++i) { |
| vidCompNames[i] = (OMX_U8*)malloc(sizeof(OMX_U8)*OMX_MAX_STRINGNAME_SIZE); |
| } |
| OMX_GetComponentsOfRole(role, &total, vidCompNames); |
| DEBUG_PRINT("\nComponents of Role:%s\n", role); |
| for (i = 0; i < total; ++i) { |
| DEBUG_PRINT("\nComponent Name [%s]\n",vidCompNames[i]); |
| free(vidCompNames[i]); |
| } |
| free(vidCompNames); |
| } |
| else { |
| DEBUG_PRINT_ERROR("No components found with Role:%s", role); |
| } |
| |
| if (codec_format_option == CODEC_FORMAT_H264) |
| { |
| strncpy(vdecCompNames, "OMX.qcom.video.decoder.avc", 27); |
| } |
| else if (codec_format_option == CODEC_FORMAT_MP4) |
| { |
| strncpy(vdecCompNames, "OMX.qcom.video.decoder.mpeg4", 29); |
| } |
| else if (codec_format_option == CODEC_FORMAT_H263) |
| { |
| strncpy(vdecCompNames, "OMX.qcom.video.decoder.h263", 28); |
| } |
| else if (codec_format_option == CODEC_FORMAT_VC1) |
| { |
| strncpy(vdecCompNames, "OMX.qcom.video.decoder.vc1", 27); |
| } |
| else |
| { |
| DEBUG_PRINT_ERROR("Error: Unsupported codec %d\n", codec_format_option); |
| return -1; |
| } |
| |
| omxresult = OMX_GetHandle((OMX_HANDLETYPE*)(&dec_handle), |
| (OMX_STRING)vdecCompNames, NULL, &call_back); |
| if (FAILED(omxresult)) { |
| DEBUG_PRINT_ERROR("\nFailed to Load the component:%s\n", vdecCompNames); |
| return -1; |
| } |
| else |
| { |
| DEBUG_PRINT("\nComponent %s is in LOADED state\n", vdecCompNames); |
| } |
| |
| QOMX_VIDEO_QUERY_DECODER_INSTANCES decoder_instances; |
| omxresult = OMX_GetConfig(dec_handle, |
| (OMX_INDEXTYPE)OMX_QcomIndexQueryNumberOfVideoDecInstance, |
| &decoder_instances); |
| DEBUG_PRINT("\n Number of decoder instances %d", |
| decoder_instances.nNumOfInstances); |
| |
| /* Get the port information */ |
| CONFIG_VERSION_SIZE(portParam); |
| omxresult = OMX_GetParameter(dec_handle, OMX_IndexParamVideoInit, |
| (OMX_PTR)&portParam); |
| |
| if(FAILED(omxresult)) { |
| DEBUG_PRINT_ERROR("ERROR - Failed to get Port Param\n"); |
| return -1; |
| } |
| else |
| { |
| DEBUG_PRINT("portParam.nPorts:%d\n", portParam.nPorts); |
| DEBUG_PRINT("portParam.nStartPortNumber:%d\n", portParam.nStartPortNumber); |
| } |
| |
| DEBUG_PRINT("Set parameter immediately followed by getparameter"); |
| omxresult = OMX_SetParameter(dec_handle, |
| OMX_IndexParamPortDefinition, |
| &portFmt); |
| |
| if(OMX_ErrorNone != omxresult) |
| { |
| DEBUG_PRINT_ERROR("ERROR - Set parameter failed"); |
| } |
| |
| /* Set the compression format on i/p port */ |
| if (codec_format_option == CODEC_FORMAT_H264) |
| { |
| portFmt.format.video.eCompressionFormat = OMX_VIDEO_CodingAVC; |
| } |
| else if (codec_format_option == CODEC_FORMAT_MP4) |
| { |
| portFmt.format.video.eCompressionFormat = OMX_VIDEO_CodingMPEG4; |
| } |
| else if (codec_format_option == CODEC_FORMAT_H263) |
| { |
| portFmt.format.video.eCompressionFormat = OMX_VIDEO_CodingH263; |
| } |
| else if (codec_format_option == CODEC_FORMAT_VC1) |
| { |
| portFmt.format.video.eCompressionFormat = OMX_VIDEO_CodingWMV; |
| } |
| else |
| { |
| DEBUG_PRINT_ERROR("Error: Unsupported codec %d\n", codec_format_option); |
| } |
| |
| |
| return 0; |
| } |
| |
| int Play_Decoder() |
| { |
| int i, bufCnt; |
| int frameSize=0; |
| DEBUG_PRINT("Inside %s \n", __FUNCTION__); |
| OMX_ERRORTYPE ret; |
| |
| DEBUG_PRINT("sizeof[%d]\n", sizeof(OMX_BUFFERHEADERTYPE)); |
| |
| /* open the i/p and o/p files based on the video file format passed */ |
| if(open_video_file()) { |
| DEBUG_PRINT_ERROR("Error in opening video file\n"); |
| return -1; |
| } |
| |
| OMX_QCOM_PARAM_PORTDEFINITIONTYPE inputPortFmt; |
| memset(&inputPortFmt, 0, sizeof(OMX_QCOM_PARAM_PORTDEFINITIONTYPE)); |
| CONFIG_VERSION_SIZE(inputPortFmt); |
| inputPortFmt.nPortIndex = 0; // input port |
| switch (file_type_option) |
| { |
| case FILE_TYPE_DAT_PER_AU: |
| case FILE_TYPE_PICTURE_START_CODE: |
| case FILE_TYPE_RCV: |
| case FILE_TYPE_VC1: |
| { |
| inputPortFmt.nFramePackingFormat = OMX_QCOM_FramePacking_OnlyOneCompleteFrame; |
| break; |
| } |
| |
| case FILE_TYPE_ARBITRARY_BYTES: |
| case FILE_TYPE_264_NAL_SIZE_LENGTH: |
| { |
| inputPortFmt.nFramePackingFormat = OMX_QCOM_FramePacking_Arbitrary; |
| break; |
| } |
| |
| default: |
| inputPortFmt.nFramePackingFormat = OMX_QCOM_FramePacking_Unspecified; |
| } |
| OMX_SetParameter(dec_handle,(OMX_INDEXTYPE)OMX_QcomIndexPortDefn, |
| (OMX_PTR)&inputPortFmt); |
| |
| /* Query the decoder outport's min buf requirements */ |
| CONFIG_VERSION_SIZE(portFmt); |
| |
| /* Port for which the Client needs to obtain info */ |
| portFmt.nPortIndex = portParam.nStartPortNumber; |
| |
| OMX_GetParameter(dec_handle,OMX_IndexParamPortDefinition,&portFmt); |
| DEBUG_PRINT("\nDec: Min Buffer Count %d\n", portFmt.nBufferCountMin); |
| DEBUG_PRINT("\nDec: Buffer Size %d\n", portFmt.nBufferSize); |
| |
| if(OMX_DirInput != portFmt.eDir) { |
| printf ("\nDec: Expect Input Port\n"); |
| return -1; |
| } |
| |
| bufCnt = 0; |
| portFmt.format.video.nFrameHeight = height; |
| portFmt.format.video.nFrameWidth = width; |
| OMX_SetParameter(dec_handle,OMX_IndexParamPortDefinition, |
| (OMX_PTR)&portFmt); |
| OMX_GetParameter(dec_handle,OMX_IndexParamPortDefinition, |
| &portFmt); |
| DEBUG_PRINT("\nDec: New Min Buffer Count %d", portFmt.nBufferCountMin); |
| |
| |
| DEBUG_PRINT("\nVideo format, height = %d", portFmt.format.video.nFrameHeight); |
| DEBUG_PRINT("\nVideo format, height = %d\n", portFmt.format.video.nFrameWidth); |
| if(codec_format_option == CODEC_FORMAT_H264) |
| { |
| OMX_VIDEO_CONFIG_NALSIZE naluSize; |
| naluSize.nNaluBytes = nalSize; |
| DEBUG_PRINT("\n Nal length is %d index %d",nalSize,OMX_IndexConfigVideoNalSize); |
| OMX_SetConfig(dec_handle,OMX_IndexConfigVideoNalSize,(OMX_PTR)&naluSize); |
| DEBUG_PRINT("SETTING THE NAL SIZE to %d\n",naluSize.nNaluBytes); |
| } |
| DEBUG_PRINT("\nOMX_SendCommand Decoder -> IDLE\n"); |
| OMX_SendCommand(dec_handle, OMX_CommandStateSet, OMX_StateIdle,0); |
| |
| input_buf_cnt = portFmt.nBufferCountActual; |
| DEBUG_PRINT("Transition to Idle State succesful...\n"); |
| /* Allocate buffer on decoder's i/p port */ |
| error = Allocate_Buffer(dec_handle, &pInputBufHdrs, portFmt.nPortIndex, |
| portFmt.nBufferCountActual, portFmt.nBufferSize); |
| if (error != OMX_ErrorNone) { |
| DEBUG_PRINT_ERROR("Error - OMX_AllocateBuffer Input buffer error\n"); |
| return -1; |
| } |
| else { |
| DEBUG_PRINT("\nOMX_AllocateBuffer Input buffer success\n"); |
| } |
| |
| portFmt.nPortIndex = portParam.nStartPortNumber+1; |
| /* Port for which the Client needs to obtain info */ |
| |
| OMX_GetParameter(dec_handle,OMX_IndexParamPortDefinition,&portFmt); |
| DEBUG_PRINT("nMin Buffer Count=%d", portFmt.nBufferCountMin); |
| DEBUG_PRINT("nBuffer Size=%d", portFmt.nBufferSize); |
| if(OMX_DirOutput != portFmt.eDir) { |
| DEBUG_PRINT_ERROR("Error - Expect Output Port\n"); |
| return -1; |
| } |
| |
| /* Allocate buffer on decoder's o/p port */ |
| error = Allocate_Buffer(dec_handle, &pOutYUVBufHdrs, portFmt.nPortIndex, |
| portFmt.nBufferCountActual, portFmt.nBufferSize); |
| if (error != OMX_ErrorNone) { |
| DEBUG_PRINT_ERROR("Error - OMX_AllocateBuffer Output buffer error\n"); |
| return -1; |
| } |
| else |
| { |
| DEBUG_PRINT("OMX_AllocateBuffer Output buffer success\n"); |
| } |
| |
| wait_for_event(); |
| if (currentStatus == INVALID_STATE) |
| { |
| do_freeHandle_and_clean_up(true); |
| return -1; |
| } |
| |
| if (freeHandle_option == FREE_HANDLE_AT_IDLE) |
| { |
| OMX_STATETYPE state = OMX_StateInvalid; |
| OMX_GetState(dec_handle, &state); |
| if (state == OMX_StateIdle) |
| { |
| DEBUG_PRINT("Decoder is in OMX_StateIdle and trying to call OMX_FreeHandle \n"); |
| do_freeHandle_and_clean_up(false); |
| } |
| else |
| { |
| DEBUG_PRINT_ERROR("Error - Decoder is in state %d and trying to call OMX_FreeHandle \n", state); |
| do_freeHandle_and_clean_up(true); |
| } |
| return -1; |
| } |
| |
| |
| DEBUG_PRINT("OMX_SendCommand Decoder -> Executing\n"); |
| OMX_SendCommand(dec_handle, OMX_CommandStateSet, OMX_StateExecuting,0); |
| wait_for_event(); |
| if (currentStatus == INVALID_STATE) |
| { |
| do_freeHandle_and_clean_up(true); |
| return -1; |
| } |
| |
| for(bufCnt=0; bufCnt < portFmt.nBufferCountActual; ++bufCnt) { |
| DEBUG_PRINT("OMX_FillThisBuffer on output buf no.%d\n",bufCnt); |
| pOutYUVBufHdrs[bufCnt]->nOutputPortIndex = 1; |
| pOutYUVBufHdrs[bufCnt]->nFlags &= ~OMX_BUFFERFLAG_EOS; |
| ret = OMX_FillThisBuffer(dec_handle, pOutYUVBufHdrs[bufCnt]); |
| if (OMX_ErrorNone != ret) { |
| DEBUG_PRINT_ERROR("Error - OMX_FillThisBuffer failed with result %d\n", ret); |
| } |
| else { |
| DEBUG_PRINT("OMX_FillThisBuffer success!\n"); |
| } |
| } |
| |
| used_ip_buf_cnt = input_buf_cnt; |
| |
| rcv_v1 = 0; |
| |
| //QPERF_START(client_decode); |
| if (codec_format_option == CODEC_FORMAT_VC1) |
| { |
| pInputBufHdrs[0]->nOffset = 0; |
| if(file_type_option == FILE_TYPE_RCV) |
| { |
| frameSize = Read_Buffer_From_RCV_File_Seq_Layer(pInputBufHdrs[0]); |
| pInputBufHdrs[0]->nFilledLen = frameSize; |
| DEBUG_PRINT("After Read_Buffer_From_RCV_File_Seq_Layer, " |
| "frameSize %d\n", frameSize); |
| } |
| else if(file_type_option == FILE_TYPE_VC1) |
| { |
| pInputBufHdrs[0]->nFilledLen = Read_Buffer(pInputBufHdrs[0]); |
| DEBUG_PRINT_ERROR("After 1st Read_Buffer for VC1, " |
| "pInputBufHdrs[0]->nFilledLen %d\n", pInputBufHdrs[0]->nFilledLen); |
| } |
| else |
| { |
| pInputBufHdrs[0]->nFilledLen = Read_Buffer(pInputBufHdrs[0]); |
| DEBUG_PRINT("After Read_Buffer pInputBufHdrs[0]->nFilledLen %d\n", |
| pInputBufHdrs[0]->nFilledLen); |
| } |
| |
| pInputBufHdrs[0]->nInputPortIndex = 0; |
| pInputBufHdrs[0]->nOffset = 0; |
| pInputBufHdrs[0]->nFlags = 0; |
| |
| ret = OMX_EmptyThisBuffer(dec_handle, pInputBufHdrs[0]); |
| if (ret != OMX_ErrorNone) |
| { |
| DEBUG_PRINT_ERROR("ERROR - OMX_EmptyThisBuffer failed with result %d\n", ret); |
| do_freeHandle_and_clean_up(true); |
| return -1; |
| } |
| else |
| { |
| etb_count++; |
| DEBUG_PRINT("OMX_EmptyThisBuffer success!\n"); |
| if(cmd_data == etb_count) |
| { |
| sem_post(&seq_sem); |
| printf("\n Posted seq_sem"); |
| } |
| } |
| i = 1; |
| } |
| else |
| { |
| i = 0; |
| } |
| |
| for (i; i < used_ip_buf_cnt;i++) { |
| pInputBufHdrs[i]->nInputPortIndex = 0; |
| pInputBufHdrs[i]->nOffset = 0; |
| if((frameSize = Read_Buffer(pInputBufHdrs[i])) <= 0 ){ |
| DEBUG_PRINT("NO FRAME READ\n"); |
| pInputBufHdrs[i]->nFilledLen = frameSize; |
| pInputBufHdrs[i]->nInputPortIndex = 0; |
| pInputBufHdrs[i]->nFlags |= OMX_BUFFERFLAG_EOS;; |
| bInputEosReached = true; |
| |
| OMX_EmptyThisBuffer(dec_handle, pInputBufHdrs[i]); |
| etb_count++; |
| if(cmd_data == etb_count) |
| { |
| sem_post(&seq_sem); |
| printf("\n Posted seq_sem"); |
| } |
| DEBUG_PRINT("File is small::Either EOS or Some Error while reading file\n"); |
| break; |
| } |
| pInputBufHdrs[i]->nFilledLen = frameSize; |
| pInputBufHdrs[i]->nInputPortIndex = 0; |
| pInputBufHdrs[i]->nFlags = 0; |
| //pBufHdr[bufCnt]->pAppPrivate = this; |
| ret = OMX_EmptyThisBuffer(dec_handle, pInputBufHdrs[i]); |
| if (OMX_ErrorNone != ret) { |
| DEBUG_PRINT_ERROR("ERROR - OMX_EmptyThisBuffer failed with result %d\n", ret); |
| do_freeHandle_and_clean_up(true); |
| return -1; |
| } |
| else { |
| DEBUG_PRINT("OMX_EmptyThisBuffer success!\n"); |
| etb_count++; |
| if(cmd_data == etb_count) |
| { |
| sem_post(&seq_sem); |
| printf("\n Posted seq_sem"); |
| } |
| } |
| } |
| |
| if(0 != pthread_create(&ebd_thread_id, NULL, ebd_thread, NULL)) |
| { |
| printf("\n Error in Creating fbd_thread \n"); |
| free_queue(etb_queue); |
| free_queue(fbd_queue); |
| return -1; |
| } |
| |
| // wait for event port settings changed event |
| wait_for_event(); |
| DEBUG_PRINT("RECIEVED EVENT PORT TO DETERMINE IF DYN PORT RECONFIGURATION NEEDED, currentStatus %d\n", |
| currentStatus); |
| if (currentStatus == INVALID_STATE) |
| { |
| DEBUG_PRINT_ERROR("Error - INVALID_STATE\n"); |
| do_freeHandle_and_clean_up(true); |
| return -1; |
| } |
| else if (currentStatus == PORT_SETTING_CHANGE_STATE) |
| { |
| DEBUG_PRINT("PORT_SETTING_CHANGE_STATE\n"); |
| // Send DISABLE command |
| sent_disabled = 1; |
| OMX_SendCommand(dec_handle, OMX_CommandPortDisable, 1, 0); |
| |
| DEBUG_PRINT("FREEING BUFFERS\n"); |
| // Free output Buffer |
| for(bufCnt=0; bufCnt < portFmt.nBufferCountActual; ++bufCnt) { |
| OMX_FreeBuffer(dec_handle, 1, pOutYUVBufHdrs[bufCnt]); |
| } |
| |
| // wait for Disable event to come back |
| wait_for_event(); |
| if (currentStatus == INVALID_STATE) |
| { |
| do_freeHandle_and_clean_up(true); |
| return -1; |
| } |
| DEBUG_PRINT("DISABLE EVENT RECD\n"); |
| // GetParam and SetParam |
| |
| // Send Enable command |
| OMX_SendCommand(dec_handle, OMX_CommandPortEnable, 1, 0); |
| // AllocateBuffers |
| /* Allocate buffer on decoder's o/p port */ |
| |
| portFmt.nPortIndex = 1; |
| /* Port for which the Client needs to obtain info */ |
| |
| OMX_GetParameter(dec_handle,OMX_IndexParamPortDefinition,&portFmt); |
| DEBUG_PRINT("Min Buffer Count=%d", portFmt.nBufferCountMin); |
| DEBUG_PRINT("Buffer Size=%d", portFmt.nBufferSize); |
| if(OMX_DirOutput != portFmt.eDir) { |
| DEBUG_PRINT_ERROR("Error - Expect Output Port\n"); |
| return -1; |
| } |
| height = portFmt.format.video.nFrameHeight; |
| width = portFmt.format.video.nFrameWidth; |
| stride = portFmt.format.video.nStride; |
| sliceheight = portFmt.format.video.nSliceHeight; |
| |
| error = Allocate_Buffer(dec_handle, &pOutYUVBufHdrs, portFmt.nPortIndex, |
| portFmt.nBufferCountActual, portFmt.nBufferSize); |
| if (error != OMX_ErrorNone) { |
| DEBUG_PRINT_ERROR("Error - OMX_AllocateBuffer Output buffer error\n"); |
| return -1; |
| } |
| else |
| { |
| DEBUG_PRINT("OMX_AllocateBuffer Output buffer success\n"); |
| } |
| |
| // wait for enable event to come back |
| wait_for_event(); |
| if (currentStatus == INVALID_STATE) |
| { |
| do_freeHandle_and_clean_up(true); |
| return -1; |
| } |
| DEBUG_PRINT("ENABLE EVENT HANDLER RECD\n"); |
| |
| for(bufCnt=0; bufCnt < portFmt.nBufferCountActual; ++bufCnt) { |
| DEBUG_PRINT("OMX_FillThisBuffer on output buf no.%d\n",bufCnt); |
| pOutYUVBufHdrs[bufCnt]->nOutputPortIndex = 1; |
| pOutYUVBufHdrs[bufCnt]->nFlags &= ~OMX_BUFFERFLAG_EOS; |
| ret = OMX_FillThisBuffer(dec_handle, pOutYUVBufHdrs[bufCnt]); |
| if (OMX_ErrorNone != ret) { |
| DEBUG_PRINT_ERROR("ERROR - OMX_FillThisBuffer failed with result %d\n", ret); |
| } |
| else { |
| DEBUG_PRINT("OMX_FillThisBuffer success!\n"); |
| } |
| } |
| |
| if(displayYuv) |
| { |
| overlay_set(); |
| } |
| } |
| |
| if (freeHandle_option == FREE_HANDLE_AT_EXECUTING) |
| { |
| OMX_STATETYPE state = OMX_StateInvalid; |
| OMX_GetState(dec_handle, &state); |
| if (state == OMX_StateExecuting) |
| { |
| DEBUG_PRINT("Decoder is in OMX_StateExecuting and trying to call OMX_FreeHandle \n"); |
| do_freeHandle_and_clean_up(false); |
| } |
| else |
| { |
| DEBUG_PRINT_ERROR("Error - Decoder is in state %d and trying to call OMX_FreeHandle \n", state); |
| do_freeHandle_and_clean_up(true); |
| } |
| return -1; |
| } |
| else if (freeHandle_option == FREE_HANDLE_AT_PAUSE) |
| { |
| OMX_SendCommand(dec_handle, OMX_CommandStateSet, OMX_StatePause,0); |
| wait_for_event(); |
| |
| OMX_STATETYPE state = OMX_StateInvalid; |
| OMX_GetState(dec_handle, &state); |
| if (state == OMX_StatePause) |
| { |
| DEBUG_PRINT("Decoder is in OMX_StatePause and trying to call OMX_FreeHandle \n"); |
| do_freeHandle_and_clean_up(false); |
| } |
| else |
| { |
| DEBUG_PRINT_ERROR("Error - Decoder is in state %d and trying to call OMX_FreeHandle \n", state); |
| do_freeHandle_and_clean_up(true); |
| } |
| return -1; |
| } |
| |
| return 0; |
| } |
| |
| static OMX_ERRORTYPE Allocate_Buffer ( OMX_COMPONENTTYPE *dec_handle, |
| OMX_BUFFERHEADERTYPE ***pBufHdrs, |
| OMX_U32 nPortIndex, |
| long bufCntMin, long bufSize) |
| { |
| DEBUG_PRINT("Inside %s \n", __FUNCTION__); |
| OMX_ERRORTYPE error=OMX_ErrorNone; |
| long bufCnt=0; |
| |
| DEBUG_PRINT("pBufHdrs = %x,bufCntMin = %d\n", pBufHdrs, bufCntMin); |
| *pBufHdrs= (OMX_BUFFERHEADERTYPE **) |
| malloc(sizeof(OMX_BUFFERHEADERTYPE)*bufCntMin); |
| |
| for(bufCnt=0; bufCnt < bufCntMin; ++bufCnt) { |
| DEBUG_PRINT("OMX_AllocateBuffer No %d \n", bufCnt); |
| error = OMX_AllocateBuffer(dec_handle, &((*pBufHdrs)[bufCnt]), |
| nPortIndex, NULL, bufSize); |
| } |
| |
| return error; |
| } |
| |
| static void do_freeHandle_and_clean_up(bool isDueToError) |
| { |
| int bufCnt = 0; |
| |
| for(bufCnt=0; bufCnt < input_buf_cnt; ++bufCnt) |
| { |
| OMX_FreeBuffer(dec_handle, 0, pInputBufHdrs[bufCnt]); |
| } |
| |
| for(bufCnt=0; bufCnt < portFmt.nBufferCountActual; ++bufCnt) |
| { |
| OMX_FreeBuffer(dec_handle, 1, pOutYUVBufHdrs[bufCnt]); |
| } |
| |
| DEBUG_PRINT("[OMX Vdec Test] - Free handle decoder\n"); |
| OMX_ERRORTYPE result = OMX_FreeHandle(dec_handle); |
| if (result != OMX_ErrorNone) |
| { |
| DEBUG_PRINT_ERROR("[OMX Vdec Test] - OMX_FreeHandle error. Error code: %d\n", result); |
| } |
| dec_handle = NULL; |
| |
| /* Deinit OpenMAX */ |
| DEBUG_PRINT("[OMX Vdec Test] - De-initializing OMX \n"); |
| OMX_Deinit(); |
| |
| DEBUG_PRINT("[OMX Vdec Test] - closing all files\n"); |
| if(inputBufferFile) |
| { |
| fclose(inputBufferFile); |
| inputBufferFile = NULL; |
| } |
| |
| DEBUG_PRINT("[OMX Vdec Test] - after free inputfile\n"); |
| |
| if (takeYuvLog && outputBufferFile) { |
| fclose(outputBufferFile); |
| outputBufferFile = NULL; |
| } |
| DEBUG_PRINT("[OMX Vdec Test] - after free outputfile\n"); |
| |
| if(etb_queue) |
| { |
| free_queue(etb_queue); |
| etb_queue = NULL; |
| } |
| DEBUG_PRINT("[OMX Vdec Test] - after free etb_queue \n"); |
| if(fbd_queue) |
| { |
| free_queue(fbd_queue); |
| fbd_queue = NULL; |
| } |
| DEBUG_PRINT("[OMX Vdec Test] - after free iftb_queue\n"); |
| |
| |
| printf("*****************************************\n"); |
| if (isDueToError) |
| { |
| printf("************...TEST FAILED...************\n"); |
| } |
| else |
| { |
| printf("**********...TEST SUCCESSFULL...*********\n"); |
| } |
| printf("*****************************************\n"); |
| } |
| |
| static int Read_Buffer_From_DAT_File(OMX_BUFFERHEADERTYPE *pBufHdr) |
| { |
| long frameSize=0; |
| char temp_buffer[10]; |
| char temp_byte; |
| int bytes_read=0; |
| int i=0; |
| unsigned char *read_buffer=NULL; |
| char c = '1'; //initialize to anything except '\0'(0) |
| char inputFrameSize[10]; |
| int count =0; char cnt =0; |
| memset(temp_buffer, 0, sizeof(temp_buffer)); |
| |
| DEBUG_PRINT("Inside %s \n", __FUNCTION__); |
| |
| while (cnt < 10) |
| /* Check the input file format, may result in infinite loop */ |
| { |
| DEBUG_PRINT("loop[%d] count[%d]\n",cnt,count); |
| count = fread(&inputFrameSize[cnt], 1, 1, inputBufferFile); |
| if(inputFrameSize[cnt] == '\0' ) |
| break; |
| cnt++; |
| } |
| inputFrameSize[cnt]='\0'; |
| frameSize = atoi(inputFrameSize); |
| pBufHdr->nFilledLen = 0; |
| |
| /* get the frame length */ |
| fseek(inputBufferFile, -1, SEEK_CUR); |
| bytes_read = fread(pBufHdr->pBuffer, 1, frameSize, inputBufferFile); |
| |
| DEBUG_PRINT("Actual frame Size [%d] bytes_read using fread[%d]\n", |
| frameSize, bytes_read); |
| |
| if(bytes_read == 0 || bytes_read < frameSize ) { |
| DEBUG_PRINT("Bytes read Zero After Read frame Size \n"); |
| DEBUG_PRINT("Checking VideoPlayback Count:video_playback_count is:%d\n", |
| video_playback_count); |
| return 0; |
| } |
| pBufHdr->nTimeStamp = timeStampLfile; |
| timeStampLfile += timestampInterval; |
| return bytes_read; |
| } |
| |
| static int Read_Buffer_ArbitraryBytes(OMX_BUFFERHEADERTYPE *pBufHdr) |
| { |
| char temp_buffer[10]; |
| char temp_byte; |
| int bytes_read=0; |
| int i=0; |
| unsigned char *read_buffer=NULL; |
| char c = '1'; //initialize to anything except '\0'(0) |
| char inputFrameSize[10]; |
| int count =0; char cnt =0; |
| memset(temp_buffer, 0, sizeof(temp_buffer)); |
| |
| DEBUG_PRINT("Inside %s \n", __FUNCTION__); |
| |
| bytes_read = fread(pBufHdr->pBuffer, 1, NUMBER_OF_ARBITRARYBYTES_READ, inputBufferFile); |
| |
| if(bytes_read == 0) { |
| DEBUG_PRINT("Bytes read Zero After Read frame Size \n"); |
| DEBUG_PRINT("Checking VideoPlayback Count:video_playback_count is:%d\n", |
| video_playback_count); |
| return 0; |
| } |
| pBufHdr->nTimeStamp = timeStampLfile; |
| timeStampLfile += timestampInterval; |
| return bytes_read; |
| } |
| |
| static int Read_Buffer_From_Vop_Start_Code_File(OMX_BUFFERHEADERTYPE *pBufHdr) |
| { |
| unsigned int readOffset = 0; |
| int bytes_read = 0; |
| unsigned int code = 0; |
| pBufHdr->nFilledLen = 0; |
| static unsigned int header_code = 0; |
| |
| DEBUG_PRINT("Inside %s \n", __FUNCTION__); |
| |
| do |
| { |
| //Start codes are always byte aligned. |
| bytes_read = fread(&pBufHdr->pBuffer[readOffset],1, 1,inputBufferFile); |
| if(!bytes_read) |
| { |
| DEBUG_PRINT("Bytes read Zero \n"); |
| break; |
| } |
| code <<= 8; |
| code |= (0x000000FF & pBufHdr->pBuffer[readOffset]); |
| //VOP start code comparision |
| if (readOffset>3) |
| { |
| if(!header_code ){ |
| if( VOP_START_CODE == code) |
| { |
| header_code = VOP_START_CODE; |
| } |
| else if ( (0xFFFFFC00 & code) == SHORT_HEADER_START_CODE ) |
| { |
| header_code = SHORT_HEADER_START_CODE; |
| } |
| } |
| if ((header_code == VOP_START_CODE) && (code == VOP_START_CODE)) |
| { |
| //Seek backwards by 4 |
| fseek(inputBufferFile, -4, SEEK_CUR); |
| readOffset-=3; |
| break; |
| |
| } |
| else if (( header_code == SHORT_HEADER_START_CODE ) && ( SHORT_HEADER_START_CODE == (code & 0xFFFFFC00))) |
| { |
| //Seek backwards by 4 |
| fseek(inputBufferFile, -4, SEEK_CUR); |
| readOffset-=3; |
| break; |
| } |
| } |
| readOffset++; |
| }while (1); |
| pBufHdr->nTimeStamp = timeStampLfile; |
| timeStampLfile += timestampInterval; |
| return readOffset; |
| } |
| |
| static int Read_Buffer_From_Size_Nal(OMX_BUFFERHEADERTYPE *pBufHdr) |
| { |
| // NAL unit stream processing |
| char temp_size[SIZE_NAL_FIELD_MAX]; |
| int i = 0; |
| int j = 0; |
| unsigned int size = 0; // Need to make sure that uint32 has SIZE_NAL_FIELD_MAX (4) bytes |
| int bytes_read = 0; |
| |
| // read the "size_nal_field"-byte size field |
| bytes_read = fread(pBufHdr->pBuffer + pBufHdr->nOffset, 1, nalSize, inputBufferFile); |
| if (bytes_read == 0) |
| { |
| DEBUG_PRINT("Failed to read frame or it might be EOF\n"); |
| return 0; |
| } |
| |
| for (i=0; i<SIZE_NAL_FIELD_MAX-nalSize; i++) |
| { |
| temp_size[SIZE_NAL_FIELD_MAX - 1 - i] = 0; |
| } |
| |
| /* Due to little endiannes, Reorder the size based on size_nal_field */ |
| for (j=0; i<SIZE_NAL_FIELD_MAX; i++, j++) |
| { |
| temp_size[SIZE_NAL_FIELD_MAX - 1 - i] = pBufHdr->pBuffer[pBufHdr->nOffset + j]; |
| } |
| size = (unsigned int)(*((unsigned int *)(temp_size))); |
| |
| // now read the data |
| bytes_read = fread(pBufHdr->pBuffer + pBufHdr->nOffset + nalSize, 1, size, inputBufferFile); |
| if (bytes_read != size) |
| { |
| DEBUG_PRINT_ERROR("Failed to read frame\n"); |
| } |
| |
| return bytes_read + nalSize; |
| } |
| |
| static int Read_Buffer_From_RCV_File_Seq_Layer(OMX_BUFFERHEADERTYPE *pBufHdr) |
| { |
| unsigned int readOffset = 0, size_struct_C = 0; |
| unsigned int startcode = 0; |
| pBufHdr->nFilledLen = 0; |
| pBufHdr->nFlags = 0; |
| |
| DEBUG_PRINT("Inside %s \n", __FUNCTION__); |
| |
| fread(&startcode, 4, 1, inputBufferFile); |
| |
| /* read size of struct C as it need not be 4 always*/ |
| fread(&size_struct_C, 1, 4, inputBufferFile); |
| |
| /* reseek to beginning of sequence header */ |
| fseek(inputBufferFile, -8, SEEK_CUR); |
| |
| if ((startcode & 0xFF000000) == 0xC5000000) |
| { |
| |
| DEBUG_PRINT("Read_Buffer_From_RCV_File_Seq_Layer size_struct_C: %d\n", size_struct_C); |
| |
| readOffset = fread(pBufHdr->pBuffer, 1, VC1_SEQ_LAYER_SIZE_WITHOUT_STRUCTC + size_struct_C, inputBufferFile); |
| } |
| else if((startcode & 0xFF000000) == 0x85000000) |
| { |
| // .RCV V1 file |
| |
| rcv_v1 = 1; |
| |
| DEBUG_PRINT("Read_Buffer_From_RCV_File_Seq_Layer size_struct_C: %d\n", size_struct_C); |
| |
| readOffset = fread(pBufHdr->pBuffer, 1, VC1_SEQ_LAYER_SIZE_V1_WITHOUT_STRUCTC + size_struct_C, inputBufferFile); |
| } |
| else |
| { |
| DEBUG_PRINT_ERROR("Error: Unknown VC1 clip format %x\n", startcode); |
| } |
| |
| #if 0 |
| { |
| int i=0; |
| printf("Read_Buffer_From_RCV_File, length %d readOffset %d\n", readOffset, readOffset); |
| for (i=0; i<36; i++) |
| { |
| printf("0x%.2x ", pBufHdr->pBuffer[i]); |
| if (i%16 == 15) { |
| printf("\n"); |
| } |
| } |
| printf("\n"); |
| } |
| #endif |
| return readOffset; |
| } |
| |
| static int Read_Buffer_From_RCV_File(OMX_BUFFERHEADERTYPE *pBufHdr) |
| { |
| unsigned int readOffset = 0; |
| unsigned int len = 0; |
| unsigned int key = 0; |
| DEBUG_PRINT("Inside %s \n", __FUNCTION__); |
| |
| DEBUG_PRINT("Read_Buffer_From_RCV_File - nOffset %d\n", pBufHdr->nOffset); |
| if(rcv_v1) |
| { |
| /* for the case of RCV V1 format, the frame header is only of 4 bytes and has |
| only the frame size information */ |
| readOffset = fread(&len, 1, 4, inputBufferFile); |
| DEBUG_PRINT("Read_Buffer_From_RCV_File - framesize %d %x\n", len, len); |
| |
| } |
| else |
| { |
| /* for a regular RCV file, 3 bytes comprise the frame size and 1 byte for key*/ |
| readOffset = fread(&len, 1, 3, inputBufferFile); |
| DEBUG_PRINT("Read_Buffer_From_RCV_File - framesize %d %x\n", len, len); |
| |
| readOffset = fread(&key, 1, 1, inputBufferFile); |
| if ( (key & 0x80) == false) |
| { |
| DEBUG_PRINT("Read_Buffer_From_RCV_File - Non IDR frame key %x\n", key); |
| } |
| |
| } |
| |
| if(!rcv_v1) |
| { |
| /* There is timestamp field only for regular RCV format and not for RCV V1 format*/ |
| readOffset = fread(&pBufHdr->nTimeStamp, 1, 4, inputBufferFile); |
| DEBUG_PRINT("Read_Buffer_From_RCV_File - timeStamp %d\n", pBufHdr->nTimeStamp); |
| pBufHdr->nTimeStamp *= 1000; |
| } |
| else |
| { |
| pBufHdr->nTimeStamp = timeStampLfile; |
| timeStampLfile += timestampInterval; |
| } |
| |
| if(len > pBufHdr->nAllocLen) |
| { |
| DEBUG_PRINT_ERROR("Error in sufficient buffer framesize %d, allocalen %d noffset %d\n",len,pBufHdr->nAllocLen, pBufHdr->nOffset); |
| readOffset = fread(pBufHdr->pBuffer+pBufHdr->nOffset, 1, pBufHdr->nAllocLen - pBufHdr->nOffset , inputBufferFile); |
| fseek(inputBufferFile, len - readOffset,SEEK_CUR); |
| return readOffset; |
| } |
| else |
| readOffset = fread(pBufHdr->pBuffer+pBufHdr->nOffset, 1, len, inputBufferFile); |
| if (readOffset != len) |
| { |
| DEBUG_PRINT("EOS reach or Reading error %d, %s \n", readOffset, strerror( errno )); |
| return 0; |
| } |
| |
| #if 0 |
| { |
| int i=0; |
| printf("Read_Buffer_From_RCV_File, length %d readOffset %d\n", len, readOffset); |
| for (i=0; i<64; i++) |
| { |
| printf("0x%.2x ", pBufHdr->pBuffer[i]); |
| if (i%16 == 15) { |
| printf("\n"); |
| } |
| } |
| printf("\n"); |
| } |
| #endif |
| |
| return readOffset; |
| } |
| |
| static int Read_Buffer_From_VC1_File(OMX_BUFFERHEADERTYPE *pBufHdr) |
| { |
| static int timeStampLfile = 0; |
| OMX_U8 *pBuffer = pBufHdr->pBuffer + pBufHdr->nOffset; |
| DEBUG_PRINT("Inside %s \n", __FUNCTION__); |
| |
| unsigned int readOffset = 0; |
| int bytes_read = 0; |
| unsigned int code = 0; |
| |
| do |
| { |
| //Start codes are always byte aligned. |
| bytes_read = fread(&pBuffer[readOffset],1, 1,inputBufferFile); |
| if(!bytes_read) |
| { |
| DEBUG_PRINT("\n Bytes read Zero \n"); |
| break; |
| } |
| code <<= 8; |
| code |= (0x000000FF & pBufHdr->pBuffer[readOffset]); |
| //VOP start code comparision |
| if (readOffset>3) |
| { |
| if (VC1_FRAME_START_CODE == (code & 0xFFFFFFFF)) |
| { |
| //Seek backwards by 4 |
| fseek(inputBufferFile, -4, SEEK_CUR); |
| readOffset-=3; |
| |
| while(pBufHdr->pBuffer[readOffset-1] == 0) |
| readOffset--; |
| |
| break; |
| } |
| } |
| readOffset++; |
| }while (1); |
| |
| pBufHdr->nTimeStamp = timeStampLfile; |
| timeStampLfile += timestampInterval; |
| |
| #if 0 |
| { |
| int i=0; |
| printf("Read_Buffer_From_VC1_File, readOffset %d\n", readOffset); |
| for (i=0; i<64; i++) |
| { |
| printf("0x%.2x ", pBufHdr->pBuffer[i]); |
| if (i%16 == 15) { |
| printf("\n"); |
| } |
| } |
| printf("\n"); |
| } |
| #endif |
| |
| return readOffset; |
| } |
| |
| static int open_video_file () |
| { |
| int error_code = 0; |
| char outputfilename[512]; |
| DEBUG_PRINT("Inside %s filename=%s\n", __FUNCTION__, in_filename); |
| |
| inputBufferFile = fopen (in_filename, "rb"); |
| if (inputBufferFile == NULL) { |
| DEBUG_PRINT_ERROR("Error - i/p file %s could NOT be opened\n", |
| in_filename); |
| error_code = -1; |
| } |
| else { |
| DEBUG_PRINT("I/p file %s is opened \n", in_filename); |
| } |
| |
| if (takeYuvLog) { |
| strncpy(outputfilename, "yuvframes.yuv", 14); |
| outputBufferFile = fopen (outputfilename, "ab"); |
| if (outputBufferFile == NULL) |
| { |
| DEBUG_PRINT_ERROR("ERROR - o/p file %s could NOT be opened\n", outputfilename); |
| error_code = -1; |
| } |
| else |
| { |
| DEBUG_PRINT("O/p file %s is opened \n", outputfilename); |
| } |
| } |
| return error_code; |
| } |
| |
| void swap_byte(char *pByte, int nbyte) |
| { |
| int i=0; |
| |
| for (i=0; i<nbyte/2; i++) |
| { |
| pByte[i] ^= pByte[nbyte-i-1]; |
| pByte[nbyte-i-1] ^= pByte[i]; |
| pByte[i] ^= pByte[nbyte-i-1]; |
| } |
| } |
| |
| int drawBG(void) |
| { |
| int result; |
| int i; |
| #ifdef FRAMEBUFFER_32 |
| long * p; |
| #else |
| short * p; |
| #endif |
| void *fb_buf = mmap (NULL, finfo.smem_len,PROT_READ|PROT_WRITE, MAP_SHARED, fb_fd, 0); |
| |
| if (fb_buf == MAP_FAILED) |
| { |
| printf("ERROR: Framebuffer MMAP failed!\n"); |
| close(fb_fd); |
| return -1; |
| } |
| |
| vinfo.yoffset = 0; |
| p = (long *)fb_buf; |
| |
| for (i=0; i < vinfo.xres * vinfo.yres; i++) |
| { |
| #ifdef FRAMEBUFFER_32 |
| *p++ = COLOR_BLACK_RGBA_8888; |
| #else |
| *p++ = CLR_KEY; |
| #endif |
| } |
| |
| if (ioctl(fb_fd, FBIOPAN_DISPLAY, &vinfo) < 0) |
| { |
| printf("ERROR: FBIOPAN_DISPLAY failed! line=%d\n", __LINE__); |
| return -1; |
| } |
| |
| DEBUG_PRINT("drawBG success!\n"); |
| return 0; |
| } |
| |
| void overlay_set() |
| { |
| overlayp = &overlay; |
| overlayp->src.width = stride; |
| overlayp->src.height = sliceheight; |
| overlayp->src.format = MDP_Y_CRCB_H2V2; |
| overlayp->src_rect.x = 0; |
| overlayp->src_rect.y = 0; |
| overlayp->src_rect.w = width; |
| overlayp->src_rect.h = height; |
| |
| if(width >= vinfo.xres) |
| { |
| overlayp->dst_rect.x = 0; |
| overlayp->dst_rect.w = vinfo.xres; |
| } |
| else |
| { |
| overlayp->dst_rect.x = (vinfo.xres - width)/2; |
| overlayp->dst_rect.w = width; |
| } |
| |
| if(height >= vinfo.yres) |
| { |
| overlayp->dst_rect.y = 0; |
| overlayp->dst_rect.h = vinfo.yres; |
| } |
| else |
| { |
| overlayp->dst_rect.y = (vinfo.yres - height)/2; |
| overlayp->dst_rect.h = height; |
| } |
| |
| overlayp->z_order = 0; |
| printf("overlayp->dst_rect.x = %u \n", overlayp->dst_rect.x); |
| printf("overlayp->dst_rect.y = %u \n", overlayp->dst_rect.y); |
| printf("overlayp->dst_rect.w = %u \n", overlayp->dst_rect.w); |
| printf("overlayp->dst_rect.h = %u \n", overlayp->dst_rect.h); |
| |
| overlayp->alpha = 0x0; |
| overlayp->transp_mask = 0xFFFFFFFF; |
| overlayp->flags = 0; |
| overlayp->is_fg = 1; |
| |
| overlayp->id = MSMFB_NEW_REQUEST; |
| vid_buf_front_id = ioctl(fb_fd, MSMFB_OVERLAY_SET, overlayp); |
| if (vid_buf_front_id < 0) |
| { |
| printf("ERROR: MSMFB_OVERLAY_SET failed! line=%d\n", __LINE__); |
| } |
| vid_buf_front_id = overlayp->id; |
| DEBUG_PRINT("\n vid_buf_front_id = %u", vid_buf_front_id); |
| drawBG(); |
| } |
| |
| int overlay_fb(struct OMX_BUFFERHEADERTYPE *pBufHdr) |
| { |
| OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo = NULL; |
| struct msmfb_overlay_data ov_front; |
| MemoryHeapBase *vheap = NULL; |
| ov_front.id = overlayp->id; |
| pPMEMInfo = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *) |
| ((OMX_QCOM_PLATFORM_PRIVATE_LIST *) |
| pBufHdr->pPlatformPrivate)->entryList->entry; |
| vheap = (MemoryHeapBase*)pPMEMInfo->pmem_fd; |
| |
| #ifdef _ANDROID_ |
| ov_front.data.memory_id = vheap->getHeapID(); |
| #else |
| ov_front.data.memory_id = pPMEMInfo->pmem_fd; |
| #endif |
| ov_front.data.offset = pPMEMInfo->offset; |
| |
| DEBUG_PRINT("\n ov_front.data.memory_id = %d", ov_front.data.memory_id); |
| DEBUG_PRINT("\n ov_front.data.offset = %u", ov_front.data.offset); |
| |
| if (ioctl(fb_fd, MSMFB_OVERLAY_PLAY, (void*)&ov_front)) |
| { |
| printf("\nERROR! MSMFB_OVERLAY_PLAY failed at frame (Line %d)\n", |
| __LINE__); |
| return -1; |
| } |
| DEBUG_PRINT("\nMSMFB_OVERLAY_PLAY successfull"); |
| return 0; |
| } |
| |
| void overlay_unset() |
| { |
| if (ioctl(fb_fd, MSMFB_OVERLAY_UNSET, &vid_buf_front_id)) |
| { |
| printf("\nERROR! MSMFB_OVERLAY_UNSET failed! (Line %d)\n", __LINE__); |
| } |
| } |
| |
| void render_fb(struct OMX_BUFFERHEADERTYPE *pBufHdr) |
| { |
| unsigned int addr = 0; |
| OMX_OTHER_EXTRADATATYPE *pExtraData = 0; |
| OMX_QCOM_EXTRADATA_FRAMEINFO *pExtraFrameInfo = 0; |
| OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo = NULL; |
| unsigned int destx, desty,destW, destH; |
| #ifdef _ANDROID_ |
| MemoryHeapBase *vheap = NULL; |
| #endif |
| |
| unsigned int end = (unsigned int)(pBufHdr->pBuffer + pBufHdr->nAllocLen); |
| |
| struct mdp_blit_req *e; |
| union { |
| char dummy[sizeof(struct mdp_blit_req_list) + |
| sizeof(struct mdp_blit_req) * 1]; |
| struct mdp_blit_req_list list; |
| } img; |
| |
| if (fb_fd < 0) |
| { |
| DEBUG_PRINT_ERROR("Warning: /dev/fb0 is not opened!\n"); |
| return; |
| } |
| |
| img.list.count = 1; |
| e = &img.list.req[0]; |
| |
| addr = (unsigned int)(pBufHdr->pBuffer + pBufHdr->nFilledLen); |
| // align to a 4 byte boundary |
| addr = (addr + 3) & (~3); |
| |
| // read to the end of existing extra data sections |
| pExtraData = (OMX_OTHER_EXTRADATATYPE*)addr; |
| |
| while (addr < end && pExtraData->eType != OMX_ExtraDataFrameInfo) |
| { |
| addr += pExtraData->nSize; |
| pExtraData = (OMX_OTHER_EXTRADATATYPE*)addr; |
| } |
| |
| if (pExtraData->eType != OMX_ExtraDataFrameInfo) |
| { |
| DEBUG_PRINT_ERROR("pExtraData->eType %d pExtraData->nSize %d\n",pExtraData->eType,pExtraData->nSize); |
| } |
| pExtraFrameInfo = (OMX_QCOM_EXTRADATA_FRAMEINFO *)pExtraData->data; |
| |
| pPMEMInfo = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *) |
| ((OMX_QCOM_PLATFORM_PRIVATE_LIST *) |
| pBufHdr->pPlatformPrivate)->entryList->entry; |
| #ifdef _ANDROID_ |
| vheap = (MemoryHeapBase *)pPMEMInfo->pmem_fd; |
| #endif |
| |
| |
| DEBUG_PRINT_ERROR("DecWidth %d DecHeight %d\n",portFmt.format.video.nStride,portFmt.format.video.nSliceHeight); |
| DEBUG_PRINT_ERROR("DispWidth %d DispHeight %d\n",portFmt.format.video.nFrameWidth,portFmt.format.video.nFrameHeight); |
| |
| |
| |
| e->src.width = portFmt.format.video.nStride; |
| e->src.height = portFmt.format.video.nSliceHeight; |
| e->src.format = MDP_Y_CBCR_H2V2; |
| e->src.offset = pPMEMInfo->offset; |
| #ifdef _ANDROID_ |
| e->src.memory_id = vheap->getHeapID(); |
| #else |
| e->src.memory_id = pPMEMInfo->pmem_fd; |
| #endif |
| |
| DEBUG_PRINT_ERROR("pmemOffset %d pmemID %d\n",e->src.offset,e->src.memory_id); |
| |
| e->dst.width = vinfo.xres; |
| e->dst.height = vinfo.yres; |
| e->dst.format = MDP_RGB_565; |
| e->dst.offset = 0; |
| e->dst.memory_id = fb_fd; |
| |
| e->transp_mask = 0xffffffff; |
| DEBUG_PRINT("Frame interlace type %d!\n", pExtraFrameInfo->interlaceType); |
| if(pExtraFrameInfo->interlaceType != OMX_QCOM_InterlaceFrameProgressive) |
| { |
| DEBUG_PRINT("Interlaced Frame!\n"); |
| e->flags = MDP_DEINTERLACE; |
| } |
| else |
| e->flags = 0; |
| e->alpha = 0xff; |
| |
| switch(displayWindow) |
| { |
| case 1: destx = 0; |
| desty = 0; |
| destW = vinfo.xres/2; |
| destH = vinfo.yres/2; |
| break; |
| case 2: destx = vinfo.xres/2; |
| desty = 0; |
| destW = vinfo.xres/2; |
| destH = vinfo.yres/2; |
| break; |
| |
| case 3: destx = 0; |
| desty = vinfo.yres/2; |
| destW = vinfo.xres/2; |
| destH = vinfo.yres/2; |
| break; |
| case 4: destx = vinfo.xres/2; |
| desty = vinfo.yres/2; |
| destW = vinfo.xres/2; |
| destH = vinfo.yres/2; |
| break; |
| case 0: |
| default: |
| destx = 0; |
| desty = 0; |
| destW = vinfo.xres; |
| destH = vinfo.yres; |
| } |
| |
| |
| if(portFmt.format.video.nFrameWidth < destW) |
| destW = portFmt.format.video.nFrameWidth ; |
| |
| |
| if(portFmt.format.video.nFrameHeight < destH) |
| destH = portFmt.format.video.nFrameHeight; |
| |
| e->dst_rect.x = destx; |
| e->dst_rect.y = desty; |
| e->dst_rect.w = destW; |
| e->dst_rect.h = destH; |
| |
| //e->dst_rect.w = 800; |
| //e->dst_rect.h = 480; |
| |
| e->src_rect.x = 0; |
| e->src_rect.y = 0; |
| e->src_rect.w = portFmt.format.video.nFrameWidth; |
| e->src_rect.h = portFmt.format.video.nFrameHeight; |
| |
| //e->src_rect.w = portFmt.format.video.nStride; |
| //e->src_rect.h = portFmt.format.video.nSliceHeight; |
| |
| if (ioctl(fb_fd, MSMFB_BLIT, &img)) { |
| DEBUG_PRINT_ERROR("MSMFB_BLIT ioctl failed!\n"); |
| return; |
| } |
| |
| if (ioctl(fb_fd, FBIOPAN_DISPLAY, &vinfo) < 0) { |
| DEBUG_PRINT_ERROR("FBIOPAN_DISPLAY failed! line=%d\n", __LINE__); |
| return; |
| } |
| |
| DEBUG_PRINT("render_fb complete!\n"); |
| } |
| |