diff options
Diffstat (limited to 'mm-video-v4l2/vidc/vdec/test/omx_vdec_test.cpp')
-rw-r--r-- | mm-video-v4l2/vidc/vdec/test/omx_vdec_test.cpp | 4543 |
1 files changed, 4543 insertions, 0 deletions
diff --git a/mm-video-v4l2/vidc/vdec/test/omx_vdec_test.cpp b/mm-video-v4l2/vidc/vdec/test/omx_vdec_test.cpp new file mode 100644 index 00000000..a191ee28 --- /dev/null +++ b/mm-video-v4l2/vidc/vdec/test/omx_vdec_test.cpp @@ -0,0 +1,4543 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010 - 2013, The Linux Foundation. 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 The Linux Foundation 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 .... +*/ + +#define LOG_TAG "OMX-VDEC-TEST" + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <math.h> +#include <media/msm_media_info.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" +#include <sys/time.h> +#include <cutils/properties.h> + +#include <linux/android_pmem.h> + +#ifdef _ANDROID_ +#include <binder/MemoryHeapBase.h> + +extern "C"{ +#include<utils/Log.h> +} +#define DEBUG_PRINT +#define DEBUG_PRINT_ERROR ALOGE + +//#define __DEBUG_DIVX__ // Define this macro to print (through logcat) + // the kind of frames packed per buffer and + // timestamps adjustments for divx. + +//#define TEST_TS_FROM_SEI // Define this macro to calculate the timestamps + // from the SEI and VUI data for H264 + +#else +#include <glib.h> +#define strlcpy g_strlcpy + +#define ALOGE(fmt, args...) fprintf(stderr, fmt, ##args) +#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 <inttypes.h> +#include <linux/msm_mdp.h> +#include <linux/fb.h> + +/************************************************************************/ +/* #DEFINES */ +/************************************************************************/ +#define DELAY 66 +#define false 0 +#define true 1 +#define H264_START_CODE 0x00000001 +#define VOP_START_CODE 0x000001B6 +#define SHORT_HEADER_START_CODE 0x00008000 +#define MPEG2_FRAME_START_CODE 0x00000100 +#define MPEG2_SEQ_START_CODE 0x000001B3 +#define VC1_START_CODE 0x00000100 +#define VC1_FRAME_START_CODE 0x0000010D +#define VC1_FRAME_FIELD_CODE 0x0000010C +#define VC1_SEQUENCE_START_CODE 0x0000010F +#define VC1_ENTRY_POINT_START_CODE 0x0000010E +#define NUMBER_OF_ARBITRARYBYTES_READ (4 * 1024) +#define VC1_SEQ_LAYER_SIZE_WITHOUT_STRUCTC 32 +#define VC1_SEQ_LAYER_SIZE_V1_WITHOUT_STRUCTC 16 +static int previous_vc1_au = 0; +#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 + +#define ALLOCATE_BUFFER 0 + +#ifdef MAX_RES_720P +#define PMEM_DEVICE "/dev/pmem_adsp" +#elif MAX_RES_1080P_EBI +#define PMEM_DEVICE "/dev/pmem_adsp" +#elif MAX_RES_1080P +#define PMEM_DEVICE "/dev/pmem_smipool" +#endif + +//#define USE_EXTERN_PMEM_BUF + +/************************************************************************/ +/* GLOBAL DECLARATIONS */ +/************************************************************************/ +#ifdef _ANDROID_ +using namespace android; +#endif + +#ifdef _MSM8974_ +typedef unsigned short int uint16; +const uint16 CRC_INIT = 0xFFFF ; + +const uint16 crc_16_l_table[ 256 ] = { + 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, + 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, + 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, + 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, + 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, + 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, + 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, + 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, + 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, + 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, + 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, + 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, + 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, + 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, + 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, + 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, + 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, + 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, + 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, + 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, + 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, + 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, + 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, + 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, + 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, + 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, + 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, + 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, + 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, + 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, + 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, + 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 +}; + +#ifdef ANDROID_JELLYBEAN_MR1 +//Since this is unavailable on Android 4.2.2, defining it in terms of base 10 +static inline float log2f(const float& x) { + return log(x) / log(2); +} +#endif + +uint16 crc_16_l_step_nv12 (uint16 seed, const void *buf_ptr, + unsigned int byte_len, unsigned int height, unsigned int width) +{ + uint16 crc_16 = ~seed; + char *buf = (char *)buf_ptr; + char *byte_ptr = buf; + int i, j; + const unsigned int width_align = 32; + const unsigned int height_align = 32; + unsigned int stride = (width + width_align -1) & (~(width_align-1)); + unsigned int scan_lines = (height + height_align -1) & (~(height_align-1)); + for (i = 0; i < height; i++) { + for (j = 0; j < stride; j++) { + if (j < width) { + crc_16 = crc_16_l_table[ (crc_16 ^ *byte_ptr) & 0x00ff ] ^ (crc_16 >> 8); + } + byte_ptr++; + } + } + byte_ptr = buf + (scan_lines * stride); + for (i = scan_lines; i < scan_lines + height/2;i++) { + for (j = 0; j < stride; j++) { + if (j < width) { + crc_16 = crc_16_l_table[ (crc_16 ^ *byte_ptr) & 0x00ff ] ^ (crc_16 >> 8); + } + byte_ptr++; + } + } + return( ~crc_16 ); +} +#endif + +typedef enum { + CODEC_FORMAT_H264 = 1, + CODEC_FORMAT_MP4, + CODEC_FORMAT_H263, + CODEC_FORMAT_VC1, + CODEC_FORMAT_DIVX, + CODEC_FORMAT_MPEG2, +#ifdef _MSM8974_ + CODEC_FORMAT_VP8, + CODEC_FORMAT_HEVC, +#endif + CODEC_FORMAT_MAX +} 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_264_START_CODE_BASED, + + 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_START_OF_DIVX_SPECIFIC = 40, + FILE_TYPE_DIVX_4_5_6 = FILE_TYPE_START_OF_DIVX_SPECIFIC, + FILE_TYPE_DIVX_311, + + FILE_TYPE_START_OF_MPEG2_SPECIFIC = 50, + FILE_TYPE_MPEG2_START_CODE = FILE_TYPE_START_OF_MPEG2_SPECIFIC, + +#ifdef _MSM8974_ + FILE_TYPE_START_OF_VP8_SPECIFIC = 60, + FILE_TYPE_VP8_START_CODE = FILE_TYPE_START_OF_VP8_SPECIFIC, + FILE_TYPE_VP8 +#endif + +} file_type; + +typedef enum { + GOOD_STATE = 0, + PORT_SETTING_CHANGE_STATE, + ERROR_STATE +} test_status; + +typedef enum { + FREE_HANDLE_AT_LOADED = 1, + FREE_HANDLE_AT_IDLE, + FREE_HANDLE_AT_EXECUTING, + FREE_HANDLE_AT_PAUSE +} freeHandle_test; + +struct temp_egl { + int pmem_fd; + int offset; +}; + +static int (*Read_Buffer)(OMX_BUFFERHEADERTYPE *pBufHdr ); + +int inputBufferFileFd; + +FILE * outputBufferFile; +#ifdef _MSM8974_ +FILE * crcFile; +#endif +FILE * seqFile; +int takeYuvLog = 0; +int displayYuv = 0; +int displayWindow = 0; +int realtime_display = 0; +int num_frames_to_decode = 0; +int thumbnailMode = 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 eos_lock; +pthread_cond_t eos_cond; +pthread_mutex_t enable_lock; + +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; +OMX_COLOR_FORMATTYPE color_fmt; +static bool input_use_buffer = false,output_use_buffer = false; +QOMX_VIDEO_DECODER_PICTURE_ORDER picture_order; + +#ifdef MAX_RES_1080P +unsigned int color_fmt_type = 1; +#else +unsigned int color_fmt_type = 0; +#endif + +#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; +static char tempbuf[16]; +int overlay_fb(struct OMX_BUFFERHEADERTYPE *pBufHdr); +void overlay_set(); +void overlay_unset(); +void render_fb(struct OMX_BUFFERHEADERTYPE *pBufHdr); +int disable_output_port(); +int enable_output_port(); +int output_port_reconfig(); +void free_output_buffers(); +int open_display(); +void close_display(); +/************************************************************************/ +/* GLOBAL INIT */ +/************************************************************************/ +int input_buf_cnt = 0; +int height =0, width =0; +int sliceheight = 0, stride = 0; +int used_ip_buf_cnt = 0; +unsigned free_op_buf_cnt = 0; +volatile int event_is_done = 0; +int ebd_cnt= 0, fbd_cnt = 0; +int bInputEosReached = 0; +int bOutputEosReached = 0; +char in_filename[512]; +#ifdef _MSM8974_ +char crclogname[512]; +#endif +char seq_file_name[512]; +unsigned char seq_enabled = 0; +bool anti_flickering = true; +unsigned char flush_input_progress = 0, flush_output_progress = 0; +unsigned cmd_data = ~(unsigned)0, etb_count = 0; + +char curr_seq_command[100]; +OMX_S64 timeStampLfile = 0; +int fps = 30; +unsigned int timestampInterval = 33333; +codec_format codec_format_option; +file_type file_type_option; +freeHandle_test freeHandle_option; +int nalSize = 0; +int sent_disabled = 0; +int waitForPortSettingsChanged = 1; +test_status currentStatus = GOOD_STATE; +struct timeval t_start = {0, 0}, t_end = {0, 0}; + +//* 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; + +static OMX_BOOL use_external_pmem_buf = OMX_FALSE; + +int rcv_v1=0; +static struct temp_egl **p_eglHeaders = NULL; +static unsigned use_buf_virt_addr[32]; + +OMX_QCOM_PLATFORM_PRIVATE_LIST *pPlatformList = NULL; +OMX_QCOM_PLATFORM_PRIVATE_ENTRY *pPlatformEntry = NULL; +OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo = NULL; +OMX_CONFIG_RECTTYPE crop_rect = {0,0,0,0}; + +static int bHdrflag = 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_From_H264_Start_Code_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_Mpeg2_Start_Code(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); +#ifdef _MSM8974_ +static int Read_Buffer_From_VP8_File(OMX_BUFFERHEADERTYPE *pBufHdr); +#endif +static int Read_Buffer_From_VC1_File(OMX_BUFFERHEADERTYPE *pBufHdr); +static int Read_Buffer_From_DivX_4_5_6_File(OMX_BUFFERHEADERTYPE *pBufHdr); +static int Read_Buffer_From_DivX_311_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 use_input_buffer(OMX_COMPONENTTYPE *dec_handle, + OMX_BUFFERHEADERTYPE ***bufferHdr, + OMX_U32 nPortIndex, + OMX_U32 bufSize, + long bufcnt); + +static OMX_ERRORTYPE use_output_buffer(OMX_COMPONENTTYPE *dec_handle, + OMX_BUFFERHEADERTYPE ***bufferHdr, + OMX_U32 nPortIndex, + OMX_U32 bufSize, + long bufcnt); + +static OMX_ERRORTYPE use_output_buffer_multiple_fd(OMX_COMPONENTTYPE *dec_handle, + OMX_BUFFERHEADERTYPE ***bufferHdr, + OMX_U32 nPortIndex, + OMX_U32 bufSize, + long bufcnt); + +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); + +#ifndef USE_ION +static bool align_pmem_buffers(int pmem_fd, OMX_U32 buffer_size, + OMX_U32 alignment); +#endif +void getFreePmem(); +static int overlay_vsync_ctrl(int enable); + +static int clip2(int x) + { + x = x -1; + x = x | x >> 1; + x = x | x >> 2; + x = x | x >> 4; + x = x | x >> 16; + x = x + 1; + return x; + } +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; +} + +int process_current_command(const char *seq_command) +{ + char *data_str = NULL; + unsigned int data = 0, bufCnt = 0, i = 0; + int frameSize; + + 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); + if (!bOutputEosReached && !bInputEosReached) + { + 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 + seq_enabled = 0; + } + 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"); + printf("\n Sending RESUME 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); + if (previous_vc1_au) + { + printf("\n Flush not allowed on Field boundary"); + return 0; + } + cmd_data = data; + sem_wait(&seq_sem); + if (!bOutputEosReached && !bInputEosReached) + { + printf("\n Sending FLUSH cmd to OMX compt"); + flush_input_progress = 1; + flush_output_progress = 1; + OMX_SendCommand(dec_handle, OMX_CommandFlush, OMX_ALL, 0); + wait_for_event(); + 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 + seq_enabled = 0; + } + else if(strstr(seq_command, "disable_op") == seq_command) + { + printf("\n\n $$$$$ DISABLE OP PORT $$$$$"); + data_str = (char*)seq_command + strlen("disable_op") + 1; + data = atoi(data_str); + printf("\n After frame number %u", data); + cmd_data = data; + sem_wait(&seq_sem); + printf("\n Sending DISABLE OP cmd to OMX compt"); + if (disable_output_port() != 0) + { + printf("\n ERROR: While DISABLE OP..."); + do_freeHandle_and_clean_up(true); + return -1; + } + else + printf("\n EventHandler for DISABLE OP"); + } + else if(strstr(seq_command, "enable_op") == seq_command) + { + printf("\n\n $$$$$ ENABLE OP PORT $$$$$"); + data_str = (char*)seq_command + strlen("enable_op") + 1; + printf("\n Sending ENABLE OP cmd to OMX compt"); + if (enable_output_port() != 0) + { + printf("\n ERROR: While ENABLE OP..."); + do_freeHandle_and_clean_up(true); + return -1; + } + else + printf("\n EventHandler for ENABLE OP"); + } + else + { + printf("\n\n $$$$$ INVALID CMD $$$$$"); + printf("\n seq_command[%s] is invalid", seq_command); + seq_enabled = 0; + } + return 0; +} + +void PrintFramePackArrangement(OMX_QCOM_FRAME_PACK_ARRANGEMENT framePackingArrangement) +{ + printf("id (%d)\n", + framePackingArrangement.id); + printf("cancel_flag (%d)\n", + framePackingArrangement.cancel_flag); + printf("type (%d)\n", + framePackingArrangement.type); + printf("quincunx_sampling_flag (%d)\n", + framePackingArrangement.quincunx_sampling_flag); + printf("content_interpretation_type (%d)\n", + framePackingArrangement.content_interpretation_type); + printf("spatial_flipping_flag (%d)\n", + framePackingArrangement.spatial_flipping_flag); + printf("frame0_flipped_flag (%d)\n", + framePackingArrangement.frame0_flipped_flag); + printf("field_views_flag (%d)\n", + framePackingArrangement.field_views_flag); + printf("current_frame_is_frame0_flag (%d)\n", + framePackingArrangement.current_frame_is_frame0_flag); + printf("frame0_self_contained_flag (%d)\n", + framePackingArrangement.frame0_self_contained_flag); + printf("frame1_self_contained_flag (%d)\n", + framePackingArrangement.frame1_self_contained_flag); + printf("frame0_grid_position_x (%d)\n", + framePackingArrangement.frame0_grid_position_x); + printf("frame0_grid_position_y (%d)\n", + framePackingArrangement.frame0_grid_position_y); + printf("frame1_grid_position_x (%d)\n", + framePackingArrangement.frame1_grid_position_x); + printf("frame1_grid_position_y (%d)\n", + framePackingArrangement.frame1_grid_position_y); + printf("reserved_byte (%d)\n", + framePackingArrangement.reserved_byte); + printf("repetition_period (%d)\n", + framePackingArrangement.repetition_period); + printf("extension_flag (%d)\n", + framePackingArrangement.extension_flag); +} +void* ebd_thread(void* pArg) +{ + int signal_eos = 0; + while(currentStatus != ERROR_STATE) + { + int readBytes =0; + OMX_BUFFERHEADERTYPE* pBuffer = NULL; + + if(flush_input_progress) + { + DEBUG_PRINT("\n EBD_thread flush wait start"); + sem_wait(&in_flush_sem); + DEBUG_PRINT("\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; + } + + if (num_frames_to_decode && (etb_count >= num_frames_to_decode)) { + printf("\n Signal EOS %d frames decoded \n", num_frames_to_decode); + signal_eos = 1; + } + + pBuffer->nOffset = 0; + if(((readBytes = Read_Buffer(pBuffer)) > 0) && !signal_eos) { + pBuffer->nFilledLen = readBytes; + DEBUG_PRINT("%s: Timestamp sent(%lld)", __FUNCTION__, pBuffer->nTimeStamp); + OMX_EmptyThisBuffer(dec_handle,pBuffer); + etb_count++; + } + else + { + pBuffer->nFlags |= OMX_BUFFERFLAG_EOS; + bInputEosReached = true; + pBuffer->nFilledLen = readBytes; + DEBUG_PRINT("%s: Timestamp sent(%lld)", __FUNCTION__, pBuffer->nTimeStamp); + OMX_EmptyThisBuffer(dec_handle,pBuffer); + DEBUG_PRINT("EBD::Either EOS or Some Error while reading file\n"); + etb_count++; + break; + } + } + return NULL; +} + +void* fbd_thread(void* pArg) +{ + long unsigned act_time = 0, display_time = 0, render_time = 5e3, lipsync = 15e3; + struct timeval t_avsync = {0, 0}, base_avsync = {0, 0}; + float total_time = 0; + int canDisplay = 1, contigous_drop_frame = 0, bytes_written = 0, ret = 0; + OMX_S64 base_timestamp = 0, lastTimestamp = 0; + OMX_BUFFERHEADERTYPE *pBuffer = NULL, *pPrevBuff = NULL; + char value[PROPERTY_VALUE_MAX] = {0}; + OMX_U32 aspectratio_prop = 0; + pthread_mutex_lock(&eos_lock); +#ifdef _MSM8974_ + int stride,scanlines,stride_c,i; +#endif + DEBUG_PRINT("First Inside %s\n", __FUNCTION__); + property_get("vidc.vdec.debug.aspectratio", value, "0"); + aspectratio_prop = atoi(value); + while(currentStatus != ERROR_STATE && !bOutputEosReached) + { + pthread_mutex_unlock(&eos_lock); + DEBUG_PRINT("Inside %s\n", __FUNCTION__); + if(flush_output_progress) + { + DEBUG_PRINT("\n FBD_thread flush wait start"); + sem_wait(&out_flush_sem); + DEBUG_PRINT("\n FBD_thread flush wait complete"); + } + sem_wait(&fbd_sem); + pthread_mutex_lock(&enable_lock); + if (sent_disabled) + { + pthread_mutex_unlock(&enable_lock); + pthread_mutex_lock(&fbd_lock); + if (pPrevBuff != NULL ) { + if(push(fbd_queue, (void *)pBuffer)) + DEBUG_PRINT_ERROR("Error in enqueueing fbd_data\n"); + else + sem_post(&fbd_sem); + pPrevBuff = NULL; + } + if (free_op_buf_cnt == portFmt.nBufferCountActual) + free_output_buffers(); + pthread_mutex_unlock(&fbd_lock); + pthread_mutex_lock(&eos_lock); + continue; + } + pthread_mutex_unlock(&enable_lock); + if (anti_flickering) + pPrevBuff = pBuffer; + pthread_mutex_lock(&fbd_lock); + pBuffer = (OMX_BUFFERHEADERTYPE *)pop(fbd_queue); + pthread_mutex_unlock(&fbd_lock); + if (pBuffer == NULL) + { + if (anti_flickering) + pBuffer = pPrevBuff; + DEBUG_PRINT("Error - No pBuffer to dequeue\n"); + pthread_mutex_lock(&eos_lock); + continue; + } + else if (pBuffer->nFilledLen > 0) + { + if (!fbd_cnt) + { + gettimeofday(&t_start, NULL); + } + fbd_cnt++; + DEBUG_PRINT("%s: fbd_cnt(%d) Buf(%p) Timestamp(%lld)", + __FUNCTION__, fbd_cnt, pBuffer, pBuffer->nTimeStamp); + canDisplay = 1; + if (realtime_display) + { + if (pBuffer->nTimeStamp != (lastTimestamp + timestampInterval)) + { + DEBUG_PRINT("Unexpected timestamp[%lld]! Expected[%lld]\n", + pBuffer->nTimeStamp, lastTimestamp + timestampInterval); + } + lastTimestamp = pBuffer->nTimeStamp; + gettimeofday(&t_avsync, NULL); + if (!base_avsync.tv_sec && !base_avsync.tv_usec) + { + display_time = 0; + base_avsync = t_avsync; + base_timestamp = pBuffer->nTimeStamp; + DEBUG_PRINT("base_avsync Sec(%lu) uSec(%lu) base_timestamp(%lld)", + base_avsync.tv_sec, base_avsync.tv_usec, base_timestamp); + } + else + { + act_time = (t_avsync.tv_sec - base_avsync.tv_sec) * 1e6 + + t_avsync.tv_usec - base_avsync.tv_usec; + display_time = pBuffer->nTimeStamp - base_timestamp; + DEBUG_PRINT("%s: act_time(%lu) display_time(%lu)", + __FUNCTION__, act_time, display_time); + //Frame rcvd on time + if (((act_time + render_time) >= (display_time - lipsync) && + (act_time + render_time) <= (display_time + lipsync)) || + //Display late frame + (contigous_drop_frame > 5)) + display_time = 0; + else if ((act_time + render_time) < (display_time - lipsync)) + //Delaying early frame + display_time -= (lipsync + act_time + render_time); + else + { + //Dropping late frame + canDisplay = 0; + contigous_drop_frame++; + } + } + } + if (displayYuv && canDisplay) + { + if (display_time) + usleep(display_time); + ret = overlay_fb(pBuffer); + if (ret != 0) + { + printf("\nERROR in overlay_fb, disabling display!"); + close_display(); + displayYuv = 0; + } + usleep(render_time); + contigous_drop_frame = 0; + } + + if (takeYuvLog) + { + if (color_fmt == (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m) + { + printf("\n width: %d height: %d\n", crop_rect.nWidth, crop_rect.nHeight); + unsigned int stride = VENUS_Y_STRIDE(COLOR_FMT_NV12, portFmt.format.video.nFrameWidth); + unsigned int scanlines = VENUS_Y_SCANLINES(COLOR_FMT_NV12, portFmt.format.video.nFrameHeight); + char *temp = (char *) pBuffer->pBuffer; + int i = 0; + + temp += (stride * (int)crop_rect.nTop) + (int)crop_rect.nLeft; + for (i = 0; i < crop_rect.nHeight; i++) { + bytes_written = fwrite(temp, crop_rect.nWidth, 1, outputBufferFile); + temp += stride; + } + + temp = (char *)pBuffer->pBuffer + stride * scanlines; + temp += (stride * (int)crop_rect.nTop) + (int)crop_rect.nLeft; + for(i = 0; i < crop_rect.nHeight/2; i++) { + bytes_written += fwrite(temp, crop_rect.nWidth, 1, outputBufferFile); + temp += stride; + } + } + else + { + bytes_written = fwrite((const char *)pBuffer->pBuffer, + pBuffer->nFilledLen,1,outputBufferFile); + } + 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); + } + } +#ifdef _MSM8974_ + if (crcFile) { + uint16 crc_val; + crc_val = crc_16_l_step_nv12(CRC_INIT, pBuffer->pBuffer, + pBuffer->nFilledLen, height, width); + int num_bytes = fwrite(&crc_val, 1, sizeof(crc_val), crcFile); + if (num_bytes < sizeof(crc_val)) { + printf("Failed to write CRC value into file\n"); + } + } +#endif + if (pBuffer->nFlags & OMX_BUFFERFLAG_EXTRADATA) + { + OMX_OTHER_EXTRADATATYPE *pExtra; + DEBUG_PRINT(">> BUFFER WITH EXTRA DATA RCVD <<<"); + pExtra = (OMX_OTHER_EXTRADATATYPE *) + ((unsigned)(pBuffer->pBuffer + pBuffer->nOffset + + pBuffer->nFilledLen + 3)&(~3)); + while(pExtra && + (OMX_U8*)pExtra < (pBuffer->pBuffer + pBuffer->nAllocLen) && + pExtra->eType != OMX_ExtraDataNone ) + { + DEBUG_PRINT("ExtraData : pBuf(%p) BufTS(%lld) Type(%x) DataSz(%u)", + pBuffer, pBuffer->nTimeStamp, pExtra->eType, pExtra->nDataSize); + switch (pExtra->eType) + { + case OMX_ExtraDataInterlaceFormat: + { + OMX_STREAMINTERLACEFORMAT *pInterlaceFormat = (OMX_STREAMINTERLACEFORMAT *)pExtra->data; + DEBUG_PRINT("OMX_ExtraDataInterlaceFormat: Buf(%p) TSmp(%lld) IntPtr(%p) Fmt(%x)", + pBuffer->pBuffer, pBuffer->nTimeStamp, + pInterlaceFormat, pInterlaceFormat->nInterlaceFormats); + break; + } + case OMX_ExtraDataFrameInfo: + { + OMX_QCOM_EXTRADATA_FRAMEINFO *frame_info = (OMX_QCOM_EXTRADATA_FRAMEINFO *)pExtra->data; + DEBUG_PRINT("OMX_ExtraDataFrameInfo: Buf(%p) TSmp(%lld) PicType(%u) IntT(%u) ConMB(%u)", + pBuffer->pBuffer, pBuffer->nTimeStamp, frame_info->ePicType, + frame_info->interlaceType, frame_info->nConcealedMacroblocks); + if (aspectratio_prop) + DEBUG_PRINT_ERROR(" FrmRate(%u), AspRatioX(%u), AspRatioY(%u) DispWidth(%u) DispHeight(%u)", + frame_info->nFrameRate, frame_info->aspectRatio.aspectRatioX, + frame_info->aspectRatio.aspectRatioY, frame_info->displayAspectRatio.displayHorizontalSize, + frame_info->displayAspectRatio.displayVerticalSize); + else + DEBUG_PRINT(" FrmRate(%u), AspRatioX(%u), AspRatioY(%u) DispWidth(%u) DispHeight(%u)", + frame_info->nFrameRate, frame_info->aspectRatio.aspectRatioX, + frame_info->aspectRatio.aspectRatioY, frame_info->displayAspectRatio.displayHorizontalSize, + frame_info->displayAspectRatio.displayVerticalSize); + DEBUG_PRINT("PANSCAN numWindows(%d)", frame_info->panScan.numWindows); + for (int i = 0; i < frame_info->panScan.numWindows; i++) + { + DEBUG_PRINT("WINDOW Lft(%d) Tp(%d) Rgt(%d) Bttm(%d)", + frame_info->panScan.window[i].x, + frame_info->panScan.window[i].y, + frame_info->panScan.window[i].dx, + frame_info->panScan.window[i].dy); + } + break; + } + break; + case OMX_ExtraDataConcealMB: + { + OMX_U8 data = 0, *data_ptr = (OMX_U8 *)pExtra->data; + OMX_U32 concealMBnum = 0, bytes_cnt = 0; + while (bytes_cnt < pExtra->nDataSize) + { + data = *data_ptr; + while (data) + { + concealMBnum += (data&0x01); + data >>= 1; + } + data_ptr++; + bytes_cnt++; + } + DEBUG_PRINT("OMX_ExtraDataConcealMB: Buf(%p) TSmp(%lld) ConcealMB(%u)", + pBuffer->pBuffer, pBuffer->nTimeStamp, concealMBnum); + } + break; + case OMX_ExtraDataMP2ExtnData: + { + DEBUG_PRINT("\nOMX_ExtraDataMP2ExtnData"); + OMX_U8 data = 0, *data_ptr = (OMX_U8 *)pExtra->data; + OMX_U32 bytes_cnt = 0; + while (bytes_cnt < pExtra->nDataSize) + { + DEBUG_PRINT("\n MPEG-2 Extension Data Values[%d] = 0x%x", bytes_cnt, *data_ptr); + data_ptr++; + bytes_cnt++; + } + } + break; + case OMX_ExtraDataMP2UserData: + { + DEBUG_PRINT("\nOMX_ExtraDataMP2UserData"); + OMX_U8 data = 0, *data_ptr = (OMX_U8 *)pExtra->data; + OMX_U32 bytes_cnt = 0; + while (bytes_cnt < pExtra->nDataSize) + { + DEBUG_PRINT("\n MPEG-2 User Data Values[%d] = 0x%x", bytes_cnt, *data_ptr); + data_ptr++; + bytes_cnt++; + } + } + break; + default: + DEBUG_PRINT_ERROR("Unknown Extrata!"); + } + if (pExtra->nSize < (pBuffer->nAllocLen - (OMX_U32)pExtra)) + pExtra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) pExtra) + pExtra->nSize); + else + { + DEBUG_PRINT_ERROR("ERROR: Extradata pointer overflow buffer(%p) extra(%p)", + pBuffer, pExtra); + pExtra = NULL; + } + } + } + } + if(pBuffer->nFlags & QOMX_VIDEO_BUFFERFLAG_EOSEQ) + { + DEBUG_PRINT("\n"); + DEBUG_PRINT("***************************************************\n"); + DEBUG_PRINT("FillBufferDone: End Of Sequence Received\n"); + DEBUG_PRINT("***************************************************\n"); + } + if(pBuffer->nFlags & OMX_BUFFERFLAG_DATACORRUPT) + { + DEBUG_PRINT("\n"); + DEBUG_PRINT("***************************************************\n"); + DEBUG_PRINT("FillBufferDone: OMX_BUFFERFLAG_DATACORRUPT Received\n"); + DEBUG_PRINT("***************************************************\n"); + } + /********************************************************************/ + /* De-Initializing the open max and relasing the buffers and */ + /* closing the files.*/ + /********************************************************************/ + if (pBuffer->nFlags & OMX_BUFFERFLAG_EOS ) + { + OMX_QCOM_FRAME_PACK_ARRANGEMENT framePackingArrangement; + OMX_GetConfig(dec_handle, + (OMX_INDEXTYPE)OMX_QcomIndexConfigVideoFramePackingArrangement, + &framePackingArrangement); + PrintFramePackArrangement(framePackingArrangement); + + gettimeofday(&t_end, NULL); + total_time = ((float) ((t_end.tv_sec - t_start.tv_sec) * 1e6 + + t_end.tv_usec - t_start.tv_usec))/ 1e6; + //total frames is fbd_cnt - 1 since the start time is + //recorded after the first frame is decoded. + printf("\nAvg decoding frame rate=%f\n", (fbd_cnt - 1)/total_time); + + DEBUG_PRINT("***************************************************\n"); + DEBUG_PRINT("FillBufferDone: End Of Stream Reached\n"); + DEBUG_PRINT("***************************************************\n"); + pthread_mutex_lock(&eos_lock); + bOutputEosReached = true; + break; + } + + pthread_mutex_lock(&enable_lock); + if (flush_output_progress || sent_disabled) + { + pBuffer->nFilledLen = 0; + pBuffer->nFlags &= ~OMX_BUFFERFLAG_EXTRADATA; + pthread_mutex_lock(&fbd_lock); + if ( pPrevBuff != NULL ) { + if(push(fbd_queue, (void *)pPrevBuff)) + DEBUG_PRINT_ERROR("Error in enqueueing fbd_data\n"); + else + sem_post(&fbd_sem); + pPrevBuff = NULL; + } + if(push(fbd_queue, (void *)pBuffer) < 0) + { + DEBUG_PRINT_ERROR("Error in enqueueing fbd_data\n"); + } + else + sem_post(&fbd_sem); + pthread_mutex_unlock(&fbd_lock); + } + else + { + if (!anti_flickering) + pPrevBuff = pBuffer; + if (pPrevBuff) + { + pthread_mutex_lock(&fbd_lock); + pthread_mutex_lock(&eos_lock); + if (!bOutputEosReached) + { + if ( OMX_FillThisBuffer(dec_handle, pPrevBuff) == OMX_ErrorNone ) { + free_op_buf_cnt--; + } + } + pthread_mutex_unlock(&eos_lock); + pthread_mutex_unlock(&fbd_lock); + } + } + pthread_mutex_unlock(&enable_lock); + if(cmd_data <= fbd_cnt) + { + sem_post(&seq_sem); + printf("\n Posted seq_sem Frm(%d) Req(%d)", fbd_cnt, cmd_data); + cmd_data = ~(unsigned)0; + } + pthread_mutex_lock(&eos_lock); + } + if(seq_enabled) + { + seq_enabled = 0; + sem_post(&seq_sem); + printf("\n Posted seq_sem in EOS \n"); + } + pthread_cond_broadcast(&eos_cond); + pthread_mutex_unlock(&eos_lock); + 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"); + if(OMX_CommandPortDisable == (OMX_COMMANDTYPE)nData1) + { + DEBUG_PRINT("*********************************************\n"); + DEBUG_PRINT("Recieved DISABLE Event Command Complete[%d]\n",nData2); + DEBUG_PRINT("*********************************************\n"); + } + else if(OMX_CommandPortEnable == (OMX_COMMANDTYPE)nData1) + { + DEBUG_PRINT("*********************************************\n"); + DEBUG_PRINT("Recieved ENABLE Event Command Complete[%d]\n",nData2); + DEBUG_PRINT("*********************************************\n"); + if (currentStatus == PORT_SETTING_CHANGE_STATE) + currentStatus = GOOD_STATE; + pthread_mutex_lock(&enable_lock); + sent_disabled = 0; + pthread_mutex_unlock(&enable_lock); + } + else if(OMX_CommandFlush == (OMX_COMMANDTYPE)nData1) + { + DEBUG_PRINT("*********************************************\n"); + DEBUG_PRINT("Received FLUSH Event Command Complete[%d]\n",nData2); + DEBUG_PRINT("*********************************************\n"); + if (nData2 == 0) + flush_input_progress = 0; + else if (nData2 == 1) + flush_output_progress = 0; + } + if (!flush_input_progress && !flush_output_progress) + event_complete(); + break; + + case OMX_EventError: + printf("*********************************************\n"); + printf("Received OMX_EventError Event Command !\n"); + printf("*********************************************\n"); + currentStatus = ERROR_STATE; + if (OMX_ErrorInvalidState == (OMX_ERRORTYPE)nData1 || + OMX_ErrorHardware == (OMX_ERRORTYPE)nData1) + { + printf("Invalid State or hardware error \n"); + if(event_is_done == 0) + { + DEBUG_PRINT("Event error in the middle of Decode \n"); + pthread_mutex_lock(&eos_lock); + bOutputEosReached = true; + pthread_mutex_unlock(&eos_lock); + if(seq_enabled) + { + seq_enabled = 0; + sem_post(&seq_sem); + printf("\n Posted seq_sem in ERROR"); + } + } + } + if (waitForPortSettingsChanged) + { + waitForPortSettingsChanged = 0; + event_complete(); + } + break; + case OMX_EventPortSettingsChanged: + DEBUG_PRINT("OMX_EventPortSettingsChanged port[%d]\n", nData1); + if (nData2 == OMX_IndexConfigCommonOutputCrop) { + OMX_U32 outPortIndex = 1; + if (nData1 == outPortIndex) { + crop_rect.nPortIndex = outPortIndex; + OMX_ERRORTYPE ret = OMX_GetConfig(dec_handle, + OMX_IndexConfigCommonOutputCrop, &crop_rect); + if (FAILED(ret)) { + DEBUG_PRINT_ERROR("Failed to get crop rectangle\n"); + break; + } else + DEBUG_PRINT("Got Crop Rect: (%d, %d) (%d x %d)\n", + crop_rect.nLeft, crop_rect.nTop, crop_rect.nWidth, crop_rect.nHeight); + } + currentStatus = GOOD_STATE; + break; + } + +#ifdef _MSM8974_ + if (nData2 != OMX_IndexParamPortDefinition) + break; +#endif + currentStatus = PORT_SETTING_CHANGE_STATE; + if (waitForPortSettingsChanged) + { + waitForPortSettingsChanged = 0; + event_complete(); + } + else + { + pthread_mutex_lock(&eos_lock); + pthread_cond_broadcast(&eos_cond); + pthread_mutex_unlock(&eos_lock); + } + break; + + case OMX_EventBufferFlag: + DEBUG_PRINT("OMX_EventBufferFlag port[%d] flags[%x]\n", nData1, nData2); +#if 0 + // we should not set the bOutputEosReached here. in stead we wait until fbd_thread to + // check the flag so that all frames can be dumped for bit exactness check. + if (nData1 == 1 && (nData2 & OMX_BUFFERFLAG_EOS)) { + pthread_mutex_lock(&eos_lock); + bOutputEosReached = true; + pthread_mutex_unlock(&eos_lock); + if(seq_enabled) + { + seq_enabled = 0; + sem_post(&seq_sem); + printf("\n Posted seq_sem in OMX_EventBufferFlag"); + } + } + else + { + DEBUG_PRINT_ERROR("OMX_EventBufferFlag Event not handled\n"); + } +#endif + break; + case OMX_EventIndexsettingChanged: + DEBUG_PRINT("OMX_EventIndexSettingChanged Interlace mode[%x]\n", nData1); + 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) + { + waitForPortSettingsChanged = 0; + if(displayYuv) + overlay_set(); + event_complete(); + } + + pthread_mutex_lock(&fbd_lock); + free_op_buf_cnt++; + if(push(fbd_queue, (void *)pBuffer) < 0) + { + pthread_mutex_unlock(&fbd_lock); + 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; + int pic_order = 0; + OMX_ERRORTYPE result; + sliceheight = height = 144; + stride = width = 176; + + crop_rect.nLeft = 0; + crop_rect.nTop = 0; + crop_rect.nWidth = width; + crop_rect.nHeight = height; + + + if (argc < 2) + { + printf("To use it: ./mm-vdec-omx-test <clip location> \n"); + printf("Command line argument is also available\n"); + return -1; + } + + strlcpy(in_filename, argv[1], strlen(argv[1])+1); +#ifdef _MSM8974_ + strlcpy(crclogname, argv[1], strlen(argv[1])+1); + strcat(crclogname, ".crc"); +#endif + if(argc > 2) + { + codec_format_option = (codec_format)atoi(argv[2]); + // file_type, out_op, tst_op, nal_sz, disp_win, rt_dis, (fps), color, pic_order, num_frames_to_decode + int param[10] = {2, 1, 1, 0, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF}; + int next_arg = 3, idx = 0; + while (argc > next_arg && idx < 10) + { + if (strlen(argv[next_arg]) > 2) + { + strlcpy(seq_file_name, argv[next_arg],strlen(argv[next_arg]) + 1); + next_arg = argc; + } + else + param[idx++] = atoi(argv[next_arg++]); + } + idx = 0; + file_type_option = (file_type)param[idx++]; + if (codec_format_option == CODEC_FORMAT_H264 && file_type_option == 3) + { + nalSize = param[idx++]; + if (nalSize != 2 && nalSize != 4) + { + printf("Error - Can't pass NAL length size = %d\n", nalSize); + return -1; + } + } + outputOption = param[idx++]; + test_option = param[idx++]; + if ((outputOption == 1 || outputOption ==3) && test_option != 3) { + displayWindow = param[idx++]; + if (displayWindow > 0) + printf("Only entire display window supported! Ignoring value\n"); + realtime_display = param[idx++]; + } + if (realtime_display) + { + takeYuvLog = 0; + if(param[idx] != 0xFF) + { + fps = param[idx++]; + timestampInterval = 1e6 / fps; + } + } + color_fmt_type = (param[idx] != 0xFF)? param[idx++] : color_fmt_type; + if (test_option != 3) { + pic_order = (param[idx] != 0xFF)? param[idx++] : 0; + num_frames_to_decode = param[idx++]; + } + printf("Executing DynPortReconfig QCIF 144 x 176 \n"); + } + 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"); + printf(" 5--> DivX\n"); + printf(" 6--> MPEG2\n"); +#ifdef _MSM8974_ + printf(" 7--> VP8\n"); + printf(" 8--> HEVC\n"); +#endif + fflush(stdin); + fgets(tempbuf,sizeof(tempbuf),stdin); + sscanf(tempbuf,"%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/.m4v/.263/.rcv/.vc1/.m2v)\n"); + if (codec_format_option == CODEC_FORMAT_H264) + { + printf(" 3--> NAL LENGTH SIZE CLIP (.264c)\n"); + printf(" 4--> START CODE BASED CLIP (.264/.h264)\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"); + } + else if (codec_format_option == CODEC_FORMAT_DIVX) + { + printf(" 3--> DivX 4, 5, 6 clip (.cmp)\n"); +#ifdef MAX_RES_1080P + printf(" 4--> DivX 3.11 clip \n"); +#endif + } + else if (codec_format_option == CODEC_FORMAT_MPEG2) + { + printf(" 3--> MPEG2 START CODE CLIP (.m2v)\n"); + } +#ifdef _MSM8974_ + else if (codec_format_option == CODEC_FORMAT_VP8) + { + printf(" 61--> VP8 START CODE CLIP (.ivf)\n"); + } +#endif + fflush(stdin); + fgets(tempbuf,sizeof(tempbuf),stdin); + sscanf(tempbuf,"%d",&file_type_option); +#ifdef _MSM8974_ + if (codec_format_option == CODEC_FORMAT_VP8) + { + file_type_option = FILE_TYPE_VP8; + } +#endif + fflush(stdin); + if (codec_format_option == CODEC_FORMAT_H264 && file_type_option == 3) + { + printf(" Enter Nal length size [2 or 4] \n"); + fgets(tempbuf,sizeof(tempbuf),stdin); + sscanf(tempbuf,"%d",&nalSize); + if (nalSize != 2 && nalSize != 4) + { + printf("Error - Can't pass NAL length size = %d\n", nalSize); + 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); + fgets(tempbuf,sizeof(tempbuf),stdin); + sscanf(tempbuf,"%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 indicate test pass\n"); + printf(" 3 --> Thumbnail decode mode\n"); + fflush(stdin); + fgets(tempbuf,sizeof(tempbuf),stdin); + sscanf(tempbuf,"%d",&test_option); + fflush(stdin); + if (test_option == 3) + thumbnailMode = 1; + + if ((outputOption == 1 || outputOption == 3) && thumbnailMode == 0) + { + 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); + fgets(tempbuf,sizeof(tempbuf),stdin); + sscanf(tempbuf,"%d",&displayWindow); + fflush(stdin); + if(displayWindow > 0) + { + printf(" Curently display window 0 only supported; ignoring other values\n"); + displayWindow = 0; + } + } + + if ((outputOption == 1 || outputOption == 3) && thumbnailMode == 0) + { + 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); + fgets(tempbuf,sizeof(tempbuf),stdin); + sscanf(tempbuf,"%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); + fgets(tempbuf,sizeof(tempbuf),stdin); + sscanf(tempbuf,"%d",&fps); + fflush(stdin); + timestampInterval = 1000000/fps; + } + + printf(" *********************************************\n"); + printf(" ENTER THE COLOR FORMAT \n"); + printf(" 0 --> Semiplanar \n 1 --> Tile Mode\n"); + printf(" *********************************************\n"); + fflush(stdin); + fgets(tempbuf,sizeof(tempbuf),stdin); + sscanf(tempbuf,"%d",&color_fmt_type); + fflush(stdin); + + if (thumbnailMode != 1) { + printf(" *********************************************\n"); + printf(" Output picture order option: \n"); + printf(" *********************************************\n"); + printf(" 0 --> Display order\n 1 --> Decode order\n"); + fflush(stdin); + fgets(tempbuf,sizeof(tempbuf),stdin); + sscanf(tempbuf,"%d",&pic_order); + fflush(stdin); + + printf(" *********************************************\n"); + printf(" Number of frames to decode: \n"); + printf(" 0 ---> decode all frames: \n"); + printf(" *********************************************\n"); + fflush(stdin); + fgets(tempbuf,sizeof(tempbuf),stdin); + sscanf(tempbuf,"%d",&num_frames_to_decode); + 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_DIVX: + file_type_option = (file_type)(FILE_TYPE_START_OF_DIVX_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; + case CODEC_FORMAT_MPEG2: + file_type_option = (file_type)(FILE_TYPE_START_OF_MPEG2_SPECIFIC + file_type_option - FILE_TYPE_COMMON_CODEC_MAX); + break; +#ifdef _MSM8974_ + case CODEC_FORMAT_VP8: + break; +#endif + default: + printf("Error: Unknown code %d\n", codec_format_option); + } + } + + CONFIG_VERSION_SIZE(picture_order); + picture_order.eOutputPictureOrder = QOMX_VIDEO_DISPLAY_ORDER; + if (pic_order == 1) + picture_order.eOutputPictureOrder = QOMX_VIDEO_DECODE_ORDER; + + 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); + fgets(tempbuf,sizeof(tempbuf),stdin); + sscanf(tempbuf,"%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); + pthread_mutex_init(&enable_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) + { + if (open_display() != 0) + { + printf("\n Error opening display! Video won't be displayed..."); + displayYuv = 0; + } + } + + run_tests(); + pthread_cond_destroy(&cond); + pthread_mutex_destroy(&lock); + pthread_mutex_destroy(&etb_lock); + pthread_mutex_destroy(&fbd_lock); + pthread_mutex_destroy(&enable_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) + close_display(); + return 0; +} + +int run_tests() +{ + int cmd_error = 0; + DEBUG_PRINT("Inside %s\n", __FUNCTION__); + waitForPortSettingsChanged = 1; + + 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) { + if (file_type_option == FILE_TYPE_264_NAL_SIZE_LENGTH) { + Read_Buffer = Read_Buffer_From_Size_Nal; + } else if (file_type_option == FILE_TYPE_264_START_CODE_BASED) { + Read_Buffer = Read_Buffer_From_H264_Start_Code_File; + } else { + DEBUG_PRINT_ERROR("Invalid file_type_option(%d) for H264", file_type_option); + return -1; + } + } + 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 (codec_format_option == CODEC_FORMAT_MPEG2) { + Read_Buffer = Read_Buffer_From_Mpeg2_Start_Code; + } + else if(file_type_option == FILE_TYPE_DIVX_4_5_6) { + Read_Buffer = Read_Buffer_From_DivX_4_5_6_File; + } +#ifdef MAX_RES_1080P + else if(file_type_option == FILE_TYPE_DIVX_311) { + Read_Buffer = Read_Buffer_From_DivX_311_File; + } +#endif + else if(file_type_option == FILE_TYPE_RCV) { + Read_Buffer = Read_Buffer_From_RCV_File; + } +#ifdef _MSM8974_ + else if(file_type_option == FILE_TYPE_VP8) { + Read_Buffer = Read_Buffer_From_VP8_File; + } +#endif + 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_START_CODE_BASED: + case FILE_TYPE_264_NAL_SIZE_LENGTH: + case FILE_TYPE_PICTURE_START_CODE: + case FILE_TYPE_MPEG2_START_CODE: + case FILE_TYPE_RCV: + case FILE_TYPE_VC1: +#ifdef _MSM8974_ + case FILE_TYPE_VP8: +#endif + case FILE_TYPE_DIVX_4_5_6: +#ifdef MAX_RES_1080P + case FILE_TYPE_DIVX_311: +#endif + 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; + } + + anti_flickering = true; + 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); + return -1; + } + else + { + DEBUG_PRINT("Seq file %s is opened \n", seq_file_name); + seq_enabled = 1; + anti_flickering = false; + } + } + + pthread_mutex_lock(&eos_lock); + while (bOutputEosReached == false && cmd_error == 0) + { + if(seq_enabled) + { + pthread_mutex_unlock(&eos_lock); + if(!get_next_command(seqFile)) + cmd_error = process_current_command(curr_seq_command); + else + { + printf("\n Error in get_next_cmd or EOF"); + seq_enabled = 0; + } + pthread_mutex_lock(&eos_lock); + } + else + pthread_cond_wait(&eos_cond, &eos_lock); + + if (currentStatus == PORT_SETTING_CHANGE_STATE) + { + pthread_mutex_unlock(&eos_lock); + cmd_error = output_port_reconfig(); + pthread_mutex_lock(&eos_lock); + } + } + pthread_mutex_unlock(&eos_lock); + + // Wait till EOS is reached... + if(bOutputEosReached) + do_freeHandle_and_clean_up(currentStatus == ERROR_STATE); + 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); + if (vidCompNames == NULL) { + DEBUG_PRINT_ERROR("\nFailed to allocate vidCompNames\n"); + return -1; + } + + for (i = 0; i < total; ++i) { + vidCompNames[i] = (OMX_U8*)malloc(sizeof(OMX_U8)*OMX_MAX_STRINGNAME_SIZE); + if (vidCompNames[i] == NULL) { + DEBUG_PRINT_ERROR("\nFailed to allocate vidCompNames[%d]\n", i); + return -1; + } + } + 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) + { + strlcpy(vdecCompNames, "OMX.qcom.video.decoder.avc", 27); + //strlcpy(vdecCompNames, "OMX.SEC.qcom.video.decoder.avc", 31); + } + else if (codec_format_option == CODEC_FORMAT_MP4) + { + strlcpy(vdecCompNames, "OMX.qcom.video.decoder.mpeg4", 29); + } + else if (codec_format_option == CODEC_FORMAT_H263) + { + strlcpy(vdecCompNames, "OMX.qcom.video.decoder.h263", 28); + } + else if (codec_format_option == CODEC_FORMAT_VC1) + { + strlcpy(vdecCompNames, "OMX.qcom.video.decoder.vc1", 27); + } + else if (codec_format_option == CODEC_FORMAT_MPEG2) + { + strlcpy(vdecCompNames, "OMX.qcom.video.decoder.mpeg2", 29); + } + else if (file_type_option == FILE_TYPE_RCV) + { + strlcpy(vdecCompNames, "OMX.qcom.video.decoder.wmv", 27); + } + else if (file_type_option == FILE_TYPE_DIVX_4_5_6) + { + strlcpy(vdecCompNames, "OMX.qcom.video.decoder.divx", 28); + } +#ifdef _MSM8974_ + else if (codec_format_option == CODEC_FORMAT_VP8) + { + strlcpy(vdecCompNames, "OMX.qcom.video.decoder.vp8", 27); + } +#endif + else if (codec_format_option == CODEC_FORMAT_HEVC) + { + strlcpy(vdecCompNames, "OMX.qcom.video.decoder.hevc", 28); + } +#ifdef MAX_RES_1080P + else if (file_type_option == FILE_TYPE_DIVX_311) + { + strlcpy(vdecCompNames, "OMX.qcom.video.decoder.divx311", 31); + } +#endif + 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); + } + + /* 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 if (codec_format_option == CODEC_FORMAT_DIVX) + { + portFmt.format.video.eCompressionFormat = + (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx; + } + else if (codec_format_option == CODEC_FORMAT_MPEG2) + { + portFmt.format.video.eCompressionFormat = OMX_VIDEO_CodingMPEG2; + } + else if (codec_format_option == CODEC_FORMAT_HEVC) + { + portFmt.format.video.eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingHevc; + } + else + { + DEBUG_PRINT_ERROR("Error: Unsupported codec %d\n", codec_format_option); + } + + if (thumbnailMode == 1) { + QOMX_ENABLETYPE thumbNailMode; + thumbNailMode.bEnable = OMX_TRUE; + OMX_SetParameter(dec_handle,(OMX_INDEXTYPE)OMX_QcomIndexParamVideoSyncFrameDecodingMode, + (OMX_PTR)&thumbNailMode); + DEBUG_PRINT("Enabled Thumbnail mode\n"); + } + + return 0; +} + +int Play_Decoder() +{ + OMX_VIDEO_PARAM_PORTFORMATTYPE videoportFmt = {0}; + int i, bufCnt, index = 0; + int frameSize=0; + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_BUFFERHEADERTYPE* pBuffer = NULL; + DEBUG_PRINT("Inside %s \n", __FUNCTION__); + + /* 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_MPEG2_START_CODE: + case FILE_TYPE_264_START_CODE_BASED: + case FILE_TYPE_RCV: + case FILE_TYPE_VC1: +#ifdef MAX_RES_1080P + case FILE_TYPE_DIVX_311: +#endif + { + inputPortFmt.nFramePackingFormat = OMX_QCOM_FramePacking_OnlyOneCompleteFrame; + break; + } + + case FILE_TYPE_ARBITRARY_BYTES: + case FILE_TYPE_264_NAL_SIZE_LENGTH: + case FILE_TYPE_DIVX_4_5_6: + { + inputPortFmt.nFramePackingFormat = OMX_QCOM_FramePacking_Arbitrary; + break; + } +#ifdef _MSM8974_ + case FILE_TYPE_VP8: + { + inputPortFmt.nFramePackingFormat = OMX_QCOM_FramePacking_OnlyOneCompleteFrame; + break; + } +#endif + default: + inputPortFmt.nFramePackingFormat = OMX_QCOM_FramePacking_Unspecified; + } + OMX_SetParameter(dec_handle,(OMX_INDEXTYPE)OMX_QcomIndexPortDefn, + (OMX_PTR)&inputPortFmt); +#ifdef USE_EXTERN_PMEM_BUF + OMX_QCOM_PARAM_PORTDEFINITIONTYPE outPortFmt; + memset(&outPortFmt, 0, sizeof(OMX_QCOM_PARAM_PORTDEFINITIONTYPE)); + CONFIG_VERSION_SIZE(outPortFmt); + outPortFmt.nPortIndex = 1; // output port + outPortFmt.nCacheAttr = OMX_QCOM_CacheAttrNone; + outPortFmt.nMemRegion = OMX_QCOM_MemRegionSMI; + OMX_SetParameter(dec_handle,(OMX_INDEXTYPE)OMX_QcomIndexPortDefn, + (OMX_PTR)&outPortFmt); + + OMX_QCOM_PLATFORMPRIVATE_EXTN outPltPvtExtn; + memset(&outPltPvtExtn, 0, sizeof(OMX_QCOM_PLATFORMPRIVATE_EXTN)); + CONFIG_VERSION_SIZE(outPltPvtExtn); + outPltPvtExtn.nPortIndex = 1; // output port + outPltPvtExtn.type = OMX_QCOM_PLATFORM_PRIVATE_PMEM; + OMX_SetParameter(dec_handle,(OMX_INDEXTYPE)OMX_QcomIndexPlatformPvt, + (OMX_PTR)&outPltPvtExtn); + use_external_pmem_buf = OMX_TRUE; +#endif + QOMX_ENABLETYPE extra_data; + extra_data.bEnable = OMX_TRUE; +#if 0 + OMX_SetParameter(dec_handle,(OMX_INDEXTYPE)OMX_QcomIndexParamInterlaceExtraData, + (OMX_PTR)&extra_data); +#endif +#if 0 + OMX_SetParameter(dec_handle,(OMX_INDEXTYPE)OMX_QcomIndexParamConcealMBMapExtraData, + (OMX_PTR)&extra_data); +#endif +#if 1 + OMX_SetParameter(dec_handle,(OMX_INDEXTYPE)OMX_QcomIndexParamFrameInfoExtraData, + (OMX_PTR)&extra_data); +#endif +#ifdef TEST_TS_FROM_SEI + OMX_SetParameter(dec_handle,(OMX_INDEXTYPE)OMX_QcomIndexParamH264TimeInfo, + (OMX_PTR)&extra_data); +#endif +#if 0 + extra_data.bEnable = OMX_FALSE; + OMX_SetParameter(dec_handle,(OMX_INDEXTYPE)OMX_QcomIndexParamConcealMBMapExtraData, + (OMX_PTR)&extra_data); +#endif +#if 0 + extra_data.bEnable = OMX_TRUE; + OMX_SetParameter(dec_handle,(OMX_INDEXTYPE)OMX_QcomIndexEnableExtnUserData, + (OMX_PTR)&extra_data); +#endif + /* 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; + } +#ifdef MAX_RES_1080P + if( (codec_format_option == CODEC_FORMAT_DIVX) && + (file_type_option == FILE_TYPE_DIVX_311) ) { + + int off; + + if ( read(inputBufferFileFd, &width, 4 ) == -1 ) { + DEBUG_PRINT_ERROR("\nFailed to read width for divx\n"); + return -1; + } + + DEBUG_PRINT("\nWidth for DIVX = %d\n", width); + + if ( read(inputBufferFileFd, &height, 4 ) == -1 ) { + DEBUG_PRINT_ERROR("\nFailed to read height for divx\n"); + return -1; + } + + DEBUG_PRINT("\nHeight for DIVX = %u\n", height); + sliceheight = height; + stride = width; + } +#endif +#ifdef _MSM8974_ + if( (codec_format_option == CODEC_FORMAT_VC1) && + (file_type_option == FILE_TYPE_RCV) ) { + //parse struct_A data to get height and width information + unsigned int temp; + lseek64(inputBufferFileFd, 0, SEEK_SET); + if (read(inputBufferFileFd, &temp, 4) < 0) { + DEBUG_PRINT_ERROR("\nFailed to read vc1 data\n"); + return -1; + } + //Refer to Annex L of SMPTE 421M-2006 VC1 decoding standard + //We need to skip 12 bytes after 0xC5 in sequence layer data + //structure to read struct_A, which includes height and + //width information. + if ((temp & 0xFF000000) == 0xC5000000) { + lseek64(inputBufferFileFd, 12, SEEK_SET); + + if ( read(inputBufferFileFd, &height, 4 ) < -1 ) { + DEBUG_PRINT_ERROR("\nFailed to read height for vc-1\n"); + return -1; + } + if ( read(inputBufferFileFd, &width, 4 ) == -1 ) { + DEBUG_PRINT_ERROR("\nFailed to read width for vc-1\n"); + return -1; + } + lseek64(inputBufferFileFd, 0, SEEK_SET); + } + if ((temp & 0xFF000000) == 0x85000000) { + lseek64(inputBufferFileFd, 0, SEEK_SET); + } + DEBUG_PRINT("\n RCV clip width = %u height = %u \n",width, height); + } +#endif + crop_rect.nWidth = width; + crop_rect.nHeight = height; + + bufCnt = 0; + portFmt.format.video.nFrameHeight = height; + portFmt.format.video.nFrameWidth = width; + portFmt.format.video.xFramerate = fps; + 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); + CONFIG_VERSION_SIZE(videoportFmt); +#ifdef MAX_RES_720P + if(color_fmt_type == 0) + { + color_fmt = OMX_COLOR_FormatYUV420SemiPlanar; + } + else + { + color_fmt = (OMX_COLOR_FORMATTYPE) + QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka; + } +#elif _MSM8974_ + color_fmt = (OMX_COLOR_FORMATTYPE) + QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m; +#else + color_fmt = (OMX_COLOR_FORMATTYPE) + QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka; +#endif + + while (ret == OMX_ErrorNone) + { + videoportFmt.nPortIndex = 1; + videoportFmt.nIndex = index; + ret = OMX_GetParameter(dec_handle, OMX_IndexParamVideoPortFormat, + (OMX_PTR)&videoportFmt); + + if((ret == OMX_ErrorNone) && (videoportFmt.eColorFormat == + color_fmt)) + { + DEBUG_PRINT("\n Format[%u] supported by OMX Decoder", color_fmt); + break; + } + index++; + } + + if(ret == OMX_ErrorNone) + { + if(OMX_SetParameter(dec_handle, OMX_IndexParamVideoPortFormat, + (OMX_PTR)&videoportFmt) != OMX_ErrorNone) + { + DEBUG_PRINT_ERROR("\n Setting Tile format failed"); + return -1; + } + } + else + { + DEBUG_PRINT_ERROR("\n Error in retrieving supported color formats"); + return -1; + } + picture_order.nPortIndex = 1; + DEBUG_PRINT("\nSet picture order\n"); + if(OMX_SetParameter(dec_handle, + (OMX_INDEXTYPE)OMX_QcomIndexParamVideoDecoderPictureOrder, + (OMX_PTR)&picture_order) != OMX_ErrorNone) + { + printf("\n ERROR: Setting picture order!"); + return -1; + } + DEBUG_PRINT("\nVideo format: W x H (%d x %d)", + portFmt.format.video.nFrameWidth, + portFmt.format.video.nFrameHeight); + if(codec_format_option == CODEC_FORMAT_H264 || + codec_format_option == CODEC_FORMAT_HEVC) + { + 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"); + +#if ALLOCATE_BUFFER + // 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"); + } +#else + // Use buffer on decoder's i/p port + input_use_buffer = true; + DEBUG_PRINT_ERROR("\n before OMX_UseBuffer %p", &pInputBufHdrs); + error = use_input_buffer(dec_handle, + &pInputBufHdrs, + portFmt.nPortIndex, + portFmt.nBufferSize, + portFmt.nBufferCountActual); + if (error != OMX_ErrorNone) { + DEBUG_PRINT_ERROR("ERROR - OMX_UseBuffer Input buffer failed"); + return -1; + } + else { + DEBUG_PRINT("OMX_UseBuffer Input buffer success\n"); + } +#endif + 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; + } + + if (anti_flickering) { + ret = OMX_GetParameter(dec_handle,OMX_IndexParamPortDefinition,&portFmt); + if (ret != OMX_ErrorNone) { + DEBUG_PRINT_ERROR("%s: OMX_GetParameter failed: %d",__FUNCTION__, ret); + return -1; + } + portFmt.nBufferCountActual += 1; + ret = OMX_SetParameter(dec_handle,OMX_IndexParamPortDefinition,&portFmt); + if (ret != OMX_ErrorNone) { + DEBUG_PRINT_ERROR("%s: OMX_SetParameter failed: %d",__FUNCTION__, ret); + return -1; + } + } + +#ifndef USE_EGL_IMAGE_TEST_APP + if (use_external_pmem_buf) + { + DEBUG_PRINT_ERROR("\n Use External pmem buf: OMX_UseBuffer %p", &pInputBufHdrs); + error = use_output_buffer_multiple_fd(dec_handle, + &pOutYUVBufHdrs, + portFmt.nPortIndex, + portFmt.nBufferSize, + portFmt.nBufferCountActual); + } + else + { + /* Allocate buffer on decoder's o/p port */ + error = Allocate_Buffer(dec_handle, &pOutYUVBufHdrs, portFmt.nPortIndex, + portFmt.nBufferCountActual, portFmt.nBufferSize); + } + free_op_buf_cnt = portFmt.nBufferCountActual; + 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"); + } +#else + DEBUG_PRINT_ERROR("\n before OMX_UseBuffer %p", &pInputBufHdrs); + error = use_output_buffer(dec_handle, + &pOutYUVBufHdrs, + portFmt.nPortIndex, + portFmt.nBufferSize, + portFmt.nBufferCountActual); + free_op_buf_cnt = portFmt.nBufferCountActual; + if (error != OMX_ErrorNone) { + DEBUG_PRINT_ERROR("ERROR - OMX_UseBuffer Input buffer failed"); + return -1; + } + else { + DEBUG_PRINT("OMX_UseBuffer Input buffer success\n"); + } +#endif + wait_for_event(); + if (currentStatus == ERROR_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 == ERROR_STATE) + { + do_freeHandle_and_clean_up(true); + return -1; + } + if (pOutYUVBufHdrs == NULL) + { + DEBUG_PRINT_ERROR("Error - pOutYUVBufHdrs is NULL\n"); + return -1; + } + for(bufCnt=0; bufCnt < portFmt.nBufferCountActual; ++bufCnt) { + DEBUG_PRINT("OMX_FillThisBuffer on output buf no.%d\n",bufCnt); + if (pOutYUVBufHdrs[bufCnt] == NULL) + { + DEBUG_PRINT_ERROR("Error - pOutYUVBufHdrs[%d] is NULL\n", bufCnt); + return -1; + } + 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"); + free_op_buf_cnt--; + } + } + + 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) + { + bHdrflag = 1; + pInputBufHdrs[0]->nFilledLen = Read_Buffer(pInputBufHdrs[0]); + bHdrflag = 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; +#ifndef _MSM8974_ + pInputBufHdrs[0]->nFlags = 0; +#endif + 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"); + } + i = 1; +#ifdef _MSM8974_ + pInputBufHdrs[0]->nFlags = 0; +#endif + } + 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++; + 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; + DEBUG_PRINT("%s: Timestamp sent(%lld)", __FUNCTION__, pInputBufHdrs[i]->nTimeStamp); + 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(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 + DEBUG_PRINT("wait_for_event: dyn reconfig"); + wait_for_event(); + DEBUG_PRINT("wait_for_event: dyn reconfig rcvd, currentStatus %d\n", + currentStatus); + if (currentStatus == ERROR_STATE) + { + printf("Error - ERROR_STATE\n"); + do_freeHandle_and_clean_up(true); + return -1; + } + else if (currentStatus == PORT_SETTING_CHANGE_STATE) + { + if (output_port_reconfig() != 0) + return -1; + } + + 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 OMX_ERRORTYPE use_input_buffer ( OMX_COMPONENTTYPE *dec_handle, + OMX_BUFFERHEADERTYPE ***pBufHdrs, + OMX_U32 nPortIndex, + OMX_U32 bufSize, + long bufCntMin) +{ + DEBUG_PRINT("Inside %s \n", __FUNCTION__); + OMX_ERRORTYPE error=OMX_ErrorNone; + long bufCnt=0; + OMX_U8* pvirt = NULL; + + *pBufHdrs= (OMX_BUFFERHEADERTYPE **) + malloc(sizeof(OMX_BUFFERHEADERTYPE)* bufCntMin); + if(*pBufHdrs == NULL){ + DEBUG_PRINT_ERROR("\n m_inp_heap_ptr Allocation failed "); + return OMX_ErrorInsufficientResources; + } + + for(bufCnt=0; bufCnt < bufCntMin; ++bufCnt) { + // allocate input buffers + DEBUG_PRINT("OMX_UseBuffer No %d %d \n", bufCnt, bufSize); + pvirt = (OMX_U8*) malloc (bufSize); + if(pvirt == NULL){ + DEBUG_PRINT_ERROR("\n pvirt Allocation failed "); + return OMX_ErrorInsufficientResources; + } + error = OMX_UseBuffer(dec_handle, &((*pBufHdrs)[bufCnt]), + nPortIndex, NULL, bufSize, pvirt); + } + return error; +} + +static OMX_ERRORTYPE use_output_buffer ( OMX_COMPONENTTYPE *dec_handle, + OMX_BUFFERHEADERTYPE ***pBufHdrs, + OMX_U32 nPortIndex, + OMX_U32 bufSize, + long bufCntMin) +{ + DEBUG_PRINT("Inside %s \n", __FUNCTION__); + OMX_ERRORTYPE error=OMX_ErrorNone; + long bufCnt=0; + OMX_U8* pvirt = NULL; + + *pBufHdrs= (OMX_BUFFERHEADERTYPE **) + malloc(sizeof(OMX_BUFFERHEADERTYPE)* bufCntMin); + if(*pBufHdrs == NULL){ + DEBUG_PRINT_ERROR("\n m_inp_heap_ptr Allocation failed "); + return OMX_ErrorInsufficientResources; + } + output_use_buffer = true; + p_eglHeaders = (struct temp_egl **) + malloc(sizeof(struct temp_egl *)* bufCntMin); + if (!p_eglHeaders){ + DEBUG_PRINT_ERROR("\n EGL allocation failed"); + return OMX_ErrorInsufficientResources; + } + + for(bufCnt=0; bufCnt < bufCntMin; ++bufCnt) { + // allocate input buffers + DEBUG_PRINT("OMX_UseBuffer No %d %d \n", bufCnt, bufSize); + p_eglHeaders[bufCnt] = (struct temp_egl*) + malloc(sizeof(struct temp_egl)); + if(!p_eglHeaders[bufCnt]) { + DEBUG_PRINT_ERROR("\n EGL allocation failed"); + return OMX_ErrorInsufficientResources; + } + p_eglHeaders[bufCnt]->pmem_fd = open(PMEM_DEVICE,O_RDWR); + p_eglHeaders[bufCnt]->offset = 0; + if(p_eglHeaders[bufCnt]->pmem_fd < 0) { + DEBUG_PRINT_ERROR("\n open failed %s",PMEM_DEVICE); + return OMX_ErrorInsufficientResources; + } + +#ifndef USE_ION + /* TBD - this commenting is dangerous */ + align_pmem_buffers(p_eglHeaders[bufCnt]->pmem_fd, bufSize, + 8192); +#endif + DEBUG_PRINT_ERROR("\n allocation size %d pmem fd %d",bufSize,p_eglHeaders[bufCnt]->pmem_fd); + pvirt = (unsigned char *)mmap(NULL,bufSize,PROT_READ|PROT_WRITE, + MAP_SHARED,p_eglHeaders[bufCnt]->pmem_fd,0); + DEBUG_PRINT_ERROR("\n Virtaul Address %p Size %d",pvirt,bufSize); + if (pvirt == MAP_FAILED) { + DEBUG_PRINT_ERROR("\n mmap failed for buffers"); + return OMX_ErrorInsufficientResources; + } + use_buf_virt_addr[bufCnt] = (unsigned)pvirt; + error = OMX_UseEGLImage(dec_handle, &((*pBufHdrs)[bufCnt]), + nPortIndex, pvirt,(void *)p_eglHeaders[bufCnt]); + } + return error; +} + +static OMX_ERRORTYPE use_output_buffer_multiple_fd ( OMX_COMPONENTTYPE *dec_handle, + OMX_BUFFERHEADERTYPE ***pBufHdrs, + OMX_U32 nPortIndex, + OMX_U32 bufSize, + long bufCntMin) +{ + DEBUG_PRINT("Inside %s \n", __FUNCTION__); + OMX_ERRORTYPE error=OMX_ErrorNone; + long bufCnt=0; + OMX_U8* pvirt = NULL; + + *pBufHdrs= (OMX_BUFFERHEADERTYPE **) + malloc(sizeof(OMX_BUFFERHEADERTYPE)* bufCntMin); + if(*pBufHdrs == NULL){ + DEBUG_PRINT_ERROR("\n m_inp_heap_ptr Allocation failed "); + return OMX_ErrorInsufficientResources; + } + pPlatformList = (OMX_QCOM_PLATFORM_PRIVATE_LIST *) + malloc(sizeof(OMX_QCOM_PLATFORM_PRIVATE_LIST)* bufCntMin); + + if(pPlatformList == NULL){ + DEBUG_PRINT_ERROR("\n pPlatformList Allocation failed "); + return OMX_ErrorInsufficientResources; + } + + pPlatformEntry = (OMX_QCOM_PLATFORM_PRIVATE_ENTRY *) + malloc(sizeof(OMX_QCOM_PLATFORM_PRIVATE_ENTRY)* bufCntMin); + + if(pPlatformEntry == NULL){ + DEBUG_PRINT_ERROR("\n pPlatformEntry Allocation failed "); + return OMX_ErrorInsufficientResources; + } + + pPMEMInfo = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *) + malloc(sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO)* bufCntMin); + + if(pPMEMInfo == NULL){ + DEBUG_PRINT_ERROR("\n pPMEMInfo Allocation failed "); + return OMX_ErrorInsufficientResources; + } + + //output_use_buffer = true; + for(bufCnt=0; bufCnt < bufCntMin; ++bufCnt) { + // allocate input buffers + DEBUG_PRINT("OMX_UseBuffer_multiple_fd No %d %d \n", bufCnt, bufSize); + + pPlatformEntry[bufCnt].type = OMX_QCOM_PLATFORM_PRIVATE_PMEM; + pPlatformEntry[bufCnt].entry = &pPMEMInfo[bufCnt]; + // Initialize the Platform List + pPlatformList[bufCnt].nEntries = 1; + pPlatformList[bufCnt].entryList = &pPlatformEntry[bufCnt]; + pPMEMInfo[bufCnt].offset = 0; + pPMEMInfo[bufCnt].pmem_fd = open(PMEM_DEVICE,O_RDWR);; + if(pPMEMInfo[bufCnt].pmem_fd < 0) { + DEBUG_PRINT_ERROR("\n open failed %s",PMEM_DEVICE); + return OMX_ErrorInsufficientResources; + } +#ifndef USE_ION + /* TBD - this commenting is dangerous */ + align_pmem_buffers(pPMEMInfo[bufCnt].pmem_fd, bufSize, + 8192); +#endif + DEBUG_PRINT("\n allocation size %d pmem fd 0x%x",bufSize,pPMEMInfo[bufCnt].pmem_fd); + pvirt = (unsigned char *)mmap(NULL,bufSize,PROT_READ|PROT_WRITE, + MAP_SHARED,pPMEMInfo[bufCnt].pmem_fd,0); + getFreePmem(); + DEBUG_PRINT("\n Virtaul Address %p Size %d pmem_fd=0x%x",pvirt,bufSize,pPMEMInfo[bufCnt].pmem_fd); + if (pvirt == MAP_FAILED) { + DEBUG_PRINT_ERROR("\n mmap failed for buffers"); + return OMX_ErrorInsufficientResources; + } + use_buf_virt_addr[bufCnt] = (unsigned)pvirt; + error = OMX_UseBuffer(dec_handle, &((*pBufHdrs)[bufCnt]), + nPortIndex, &pPlatformList[bufCnt], bufSize, pvirt); + } + return error; +} +static void do_freeHandle_and_clean_up(bool isDueToError) +{ + int bufCnt = 0; + OMX_STATETYPE state = OMX_StateInvalid; + OMX_GetState(dec_handle, &state); + if (state == OMX_StateExecuting || state == OMX_StatePause) + { + DEBUG_PRINT("Requesting transition to Idle"); + OMX_SendCommand(dec_handle, OMX_CommandStateSet, OMX_StateIdle, 0); + wait_for_event(); + } + OMX_GetState(dec_handle, &state); + if (state == OMX_StateIdle) + { + DEBUG_PRINT("Requesting transition to Loaded"); + OMX_SendCommand(dec_handle, OMX_CommandStateSet, OMX_StateLoaded, 0); + for(bufCnt=0; bufCnt < input_buf_cnt; ++bufCnt) + { + if (pInputBufHdrs[bufCnt]->pBuffer && input_use_buffer) + { + free(pInputBufHdrs[bufCnt]->pBuffer); + pInputBufHdrs[bufCnt]->pBuffer = NULL; + DEBUG_PRINT_ERROR("\nFree(pInputBufHdrs[%d]->pBuffer)",bufCnt); + } + OMX_FreeBuffer(dec_handle, 0, pInputBufHdrs[bufCnt]); + } + if (pInputBufHdrs) + { + free(pInputBufHdrs); + pInputBufHdrs = NULL; + } + for(bufCnt = 0; bufCnt < portFmt.nBufferCountActual; ++bufCnt) { + if (output_use_buffer && p_eglHeaders) { + if(p_eglHeaders[bufCnt]) { + munmap (pOutYUVBufHdrs[bufCnt]->pBuffer, + pOutYUVBufHdrs[bufCnt]->nAllocLen); + close(p_eglHeaders[bufCnt]->pmem_fd); + p_eglHeaders[bufCnt]->pmem_fd = -1; + free(p_eglHeaders[bufCnt]); + p_eglHeaders[bufCnt] = NULL; + } + } + if (use_external_pmem_buf) + { + DEBUG_PRINT("Freeing in external pmem case: buffer=0x%x, pmem_fd=0x%d", + pOutYUVBufHdrs[bufCnt]->pBuffer, + pPMEMInfo[bufCnt].pmem_fd); + if (pOutYUVBufHdrs[bufCnt]->pBuffer) + { + munmap (pOutYUVBufHdrs[bufCnt]->pBuffer, + pOutYUVBufHdrs[bufCnt]->nAllocLen); + } + if (&pPMEMInfo[bufCnt]) + { + close(pPMEMInfo[bufCnt].pmem_fd); + pPMEMInfo[bufCnt].pmem_fd = -1; + } + } + OMX_FreeBuffer(dec_handle, 1, pOutYUVBufHdrs[bufCnt]); + } + if(p_eglHeaders) { + free(p_eglHeaders); + p_eglHeaders = NULL; + } + if (pPMEMInfo) + { + DEBUG_PRINT("Freeing in external pmem case:PMEM"); + free(pPMEMInfo); + pPMEMInfo = NULL; + } + if (pPlatformEntry) + { + DEBUG_PRINT("Freeing in external pmem case:ENTRY"); + free(pPlatformEntry); + pPlatformEntry = NULL; + } + if (pPlatformList) + { + DEBUG_PRINT("Freeing in external pmem case:LIST"); + free(pPlatformList); + pPlatformList = NULL; + } + 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] - 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(inputBufferFileFd != -1) + { + close(inputBufferFileFd); + inputBufferFileFd = -1; + } + + DEBUG_PRINT("[OMX Vdec Test] - after free inputfile\n"); + + if (takeYuvLog && outputBufferFile) { + fclose(outputBufferFile); + outputBufferFile = NULL; + } +#ifdef _MSM8974_ + if (crcFile) { + fclose(crcFile); + crcFile = NULL; + } +#endif + 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[12]; + 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 = read( inputBufferFileFd, &inputFrameSize[cnt], 1); + if(inputFrameSize[cnt] == '\0' ) + break; + cnt++; + } + inputFrameSize[cnt]='\0'; + frameSize = atoi(inputFrameSize); + pBufHdr->nFilledLen = 0; + + /* get the frame length */ + lseek64(inputBufferFileFd, -1, SEEK_CUR); + bytes_read = read(inputBufferFileFd, pBufHdr->pBuffer, frameSize); + + 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_From_H264_Start_Code_File(OMX_BUFFERHEADERTYPE *pBufHdr) +{ + int bytes_read = 0; + int cnt = 0; + unsigned int code = 0; + int naluType = 0; + int newFrame = 0; + char *dataptr = (char *)pBufHdr->pBuffer; + DEBUG_PRINT("Inside %s", __FUNCTION__); + do + { + newFrame = 0; + bytes_read = read(inputBufferFileFd, &dataptr[cnt], 1); + if (!bytes_read) + { + DEBUG_PRINT("\n%s: Bytes read Zero", __FUNCTION__); + break; + } + code <<= 8; + code |= (0x000000FF & dataptr[cnt]); + cnt++; + if ((cnt == 4) && (code != H264_START_CODE)) + { + DEBUG_PRINT_ERROR("\n%s: ERROR: Invalid start code found 0x%x", __FUNCTION__, code); + cnt = 0; + break; + } + if ((cnt > 4) && (code == H264_START_CODE)) + { + DEBUG_PRINT("%s: Found H264_START_CODE", __FUNCTION__); + bytes_read = read(inputBufferFileFd, &dataptr[cnt], 1); + if (!bytes_read) + { + DEBUG_PRINT("\n%s: Bytes read Zero", __FUNCTION__); + break; + } + DEBUG_PRINT("%s: READ Byte[%d] = 0x%x", __FUNCTION__, cnt, dataptr[cnt]); + naluType = dataptr[cnt] & 0x1F; + cnt++; + if ((naluType == 1) || (naluType == 5)) + { + DEBUG_PRINT("%s: Found AU", __FUNCTION__); + bytes_read = read(inputBufferFileFd, &dataptr[cnt], 1); + if (!bytes_read) + { + DEBUG_PRINT("\n%s: Bytes read Zero", __FUNCTION__); + break; + } + DEBUG_PRINT("%s: READ Byte[%d] = 0x%x", __FUNCTION__, cnt, dataptr[cnt]); + newFrame = (dataptr[cnt] & 0x80); + cnt++; + if (newFrame) + { + lseek64(inputBufferFileFd, -6, SEEK_CUR); + cnt -= 6; + DEBUG_PRINT("%s: Found a NAL unit (type 0x%x) of size = %d", __FUNCTION__, (dataptr[4] & 0x1F), cnt); + break; + } + else + { + DEBUG_PRINT("%s: Not a New Frame", __FUNCTION__); + } + } + else + { + lseek64(inputBufferFileFd, -5, SEEK_CUR); + cnt -= 5; + DEBUG_PRINT("%s: Found NAL unit (type 0x%x) of size = %d", __FUNCTION__, (dataptr[4] & 0x1F), cnt); + break; + } + } + } while (1); + +#ifdef TEST_TS_FROM_SEI + if (timeStampLfile == 0) + pBufHdr->nTimeStamp = 0; + else + pBufHdr->nTimeStamp = LLONG_MAX; +#else + pBufHdr->nTimeStamp = timeStampLfile; +#endif + timeStampLfile += timestampInterval; + + return cnt; +} + +static int Read_Buffer_ArbitraryBytes(OMX_BUFFERHEADERTYPE *pBufHdr) +{ + int bytes_read=0; + DEBUG_PRINT("Inside %s \n", __FUNCTION__); + bytes_read = read(inputBufferFileFd, pBufHdr->pBuffer, NUMBER_OF_ARBITRARYBYTES_READ); + 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; + } +#ifdef TEST_TS_FROM_SEI + if (timeStampLfile == 0) + pBufHdr->nTimeStamp = 0; + else + pBufHdr->nTimeStamp = LLONG_MAX; +#else + pBufHdr->nTimeStamp = timeStampLfile; +#endif + 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", __FUNCTION__); + + do + { + //Start codes are always byte aligned. + bytes_read = read(inputBufferFileFd, &pBufHdr->pBuffer[readOffset], 1); + if(bytes_read == 0 || bytes_read == -1) + { + 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 + lseek64(inputBufferFileFd, -4, SEEK_CUR); + readOffset-=3; + break; + } + else if (( header_code == SHORT_HEADER_START_CODE ) && ( SHORT_HEADER_START_CODE == (code & 0xFFFFFC00))) + { + //Seek backwards by 4 + lseek64(inputBufferFileFd, -4, SEEK_CUR); + readOffset-=3; + break; + } + } + readOffset++; + }while (1); + pBufHdr->nTimeStamp = timeStampLfile; + timeStampLfile += timestampInterval; + return readOffset; +} +static int Read_Buffer_From_Mpeg2_Start_Code(OMX_BUFFERHEADERTYPE *pBufHdr) +{ + unsigned int readOffset = 0; + int bytesRead = 0; + unsigned int code = 0; + pBufHdr->nFilledLen = 0; + static unsigned int firstParse = true; + unsigned int seenFrame = false; + + DEBUG_PRINT("Inside %s", __FUNCTION__); + + /* Read one byte at a time. Construct the code every byte in order to + * compare to the start codes. Keep looping until we've read in a complete + * frame, which can be either just a picture start code + picture, or can + * include the sequence header as well + */ + while (1) { + bytesRead = read(inputBufferFileFd, &pBufHdr->pBuffer[readOffset], 1); + + /* Exit the loop if we can't read any more bytes */ + if (bytesRead == 0 || bytesRead == -1) { + break; + } + + /* Construct the code one byte at a time */ + code <<= 8; + code |= (0x000000FF & pBufHdr->pBuffer[readOffset]); + + /* Can't compare the code to MPEG2 start codes until we've read the + * first four bytes + */ + if (readOffset >= 3) { + + /* If this is the first time we're reading from the file, then we + * need to throw away the system start code information at the + * beginning. We can just look for the first sequence header. + */ + if (firstParse) { + if (code == MPEG2_SEQ_START_CODE) { + /* Seek back by 4 bytes and reset code so that we can skip + * down to the common case below. + */ + lseek(inputBufferFileFd, -4, SEEK_CUR); + code = 0; + readOffset -= 3; + firstParse = false; + continue; + } + } + + /* If we have already parsed a frame and we see a sequence header, then + * the sequence header is part of the next frame so we seek back and + * break. + */ + if (code == MPEG2_SEQ_START_CODE) { + if (seenFrame) { + lseek(inputBufferFileFd, -4, SEEK_CUR); + readOffset -= 3; + break; + } + /* If we haven't seen a frame yet, then read in all the data until we + * either see another frame start code or sequence header start code. + */ + } else if (code == MPEG2_FRAME_START_CODE) { + if (!seenFrame) { + seenFrame = true; + } else { + lseek(inputBufferFileFd, -4, SEEK_CUR); + readOffset -= 3; + break; + } + } + } + + readOffset++; + } + + 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 = read(inputBufferFileFd, pBufHdr->pBuffer + pBufHdr->nOffset, nalSize); + if (bytes_read == 0 || bytes_read == -1) + { + 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 = read(inputBufferFileFd, pBufHdr->pBuffer + pBufHdr->nOffset + nalSize, size); + if (bytes_read != size) + { + DEBUG_PRINT_ERROR("Failed to read frame\n"); + } + + pBufHdr->nTimeStamp = timeStampLfile; + timeStampLfile += timestampInterval; + + 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; +#ifdef _MSM8974_ + pBufHdr->nFlags |= OMX_BUFFERFLAG_CODECCONFIG; +#else + pBufHdr->nFlags = 0; +#endif + + DEBUG_PRINT("Inside %s \n", __FUNCTION__); + + read(inputBufferFileFd, &startcode, 4); + + /* read size of struct C as it need not be 4 always*/ + read(inputBufferFileFd, &size_struct_C, 4); + +#ifndef _MSM8974_ + /* reseek to beginning of sequence header */ + lseek64(inputBufferFileFd, -8, SEEK_CUR); +#endif + if ((startcode & 0xFF000000) == 0xC5000000) + { + + DEBUG_PRINT("Read_Buffer_From_RCV_File_Seq_Layer size_struct_C: %d\n", size_struct_C); +#ifdef _MSM8974_ + readOffset = read(inputBufferFileFd, pBufHdr->pBuffer, size_struct_C); + lseek64(inputBufferFileFd, 24, SEEK_CUR); +#else + readOffset = read(inputBufferFileFd, pBufHdr->pBuffer, VC1_SEQ_LAYER_SIZE_WITHOUT_STRUCTC + size_struct_C); +#endif + } + 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); +#ifdef _MSM8974_ + readOffset = read(inputBufferFileFd, pBufHdr->pBuffer, size_struct_C); + lseek64(inputBufferFileFd, 8, SEEK_CUR); +#else + readOffset = read(inputBufferFileFd, pBufHdr->pBuffer, VC1_SEQ_LAYER_SIZE_V1_WITHOUT_STRUCTC + size_struct_C); +#endif + + } + 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 = read(inputBufferFileFd, &len, 4); + 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 = read(inputBufferFileFd, &len, 3); + DEBUG_PRINT("Read_Buffer_From_RCV_File - framesize %d %x\n", len, len); + + readOffset = read(inputBufferFileFd, &key, 1); + 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 = read(inputBufferFileFd, &pBufHdr->nTimeStamp, 4); + 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 = read(inputBufferFileFd, pBufHdr->pBuffer+pBufHdr->nOffset, + pBufHdr->nAllocLen - pBufHdr->nOffset); + + loff_t off = (len - readOffset)*1LL; + lseek64(inputBufferFileFd, off ,SEEK_CUR); + return readOffset; + } + else { + readOffset = read(inputBufferFileFd, pBufHdr->pBuffer+pBufHdr->nOffset, len); + } + 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, total_bytes = 0; + int startCode_cnt = 0; + int bSEQflag = 0; + int bEntryflag = 0; + unsigned int SEQbytes = 0; + int numStartcodes = 0; + + numStartcodes = bHdrflag?1:2; + + do + { + if (total_bytes == pBufHdr->nAllocLen) + { + DEBUG_PRINT_ERROR("Buffer overflow!"); + break; + } + //Start codes are always byte aligned. + bytes_read = read(inputBufferFileFd, &pBuffer[readOffset],1 ); + + if(!bytes_read) + { + DEBUG_PRINT("\n Bytes read Zero \n"); + break; + } + total_bytes++; + code <<= 8; + code |= (0x000000FF & pBufHdr->pBuffer[readOffset]); + + if(!bSEQflag && (code == VC1_SEQUENCE_START_CODE)) { + if(startCode_cnt) bSEQflag = 1; + } + + if(!bEntryflag && ( code == VC1_ENTRY_POINT_START_CODE)) { + if(startCode_cnt) bEntryflag = 1; + } + + if(code == VC1_FRAME_START_CODE || code == VC1_FRAME_FIELD_CODE) + { + startCode_cnt++ ; + } + + //VOP start code comparision + if(startCode_cnt == numStartcodes) + { + if (VC1_FRAME_START_CODE == (code & 0xFFFFFFFF) || + VC1_FRAME_FIELD_CODE == (code & 0xFFFFFFFF)) + { + previous_vc1_au = 0; + if(VC1_FRAME_FIELD_CODE == (code & 0xFFFFFFFF)) + { + previous_vc1_au = 1; + } + + if(!bHdrflag && (bSEQflag || bEntryflag)) { + lseek(inputBufferFileFd,-(SEQbytes+4),SEEK_CUR); + readOffset -= (SEQbytes+3); + } + else { + //Seek backwards by 4 + lseek64(inputBufferFileFd, -4, SEEK_CUR); + readOffset-=3; + } + + while(pBufHdr->pBuffer[readOffset-1] == 0) + readOffset--; + + break; + } + } + readOffset++; + if(bSEQflag || bEntryflag) { + SEQbytes++; + } + }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 Read_Buffer_From_DivX_4_5_6_File(OMX_BUFFERHEADERTYPE *pBufHdr) +{ +#define MAX_NO_B_FRMS 3 // Number of non-b-frames packed in each buffer +#define N_PREV_FRMS_B 1 // Number of previous non-b-frames packed + // with a set of consecutive b-frames +#define FRM_ARRAY_SIZE (MAX_NO_B_FRMS + N_PREV_FRMS_B) + char *p_buffer = NULL; + unsigned int offset_array[FRM_ARRAY_SIZE]; + int byte_cntr, pckt_end_idx; + unsigned int read_code = 0, bytes_read, byte_pos = 0, frame_type; + unsigned int i, b_frm_idx, b_frames_found = 0, vop_set_cntr = 0; + bool pckt_ready = false; +#ifdef __DEBUG_DIVX__ + char pckt_type[20]; + int pckd_frms = 0; + static unsigned long long int total_bytes = 0; + static unsigned long long int total_frames = 0; +#endif //__DEBUG_DIVX__ + + DEBUG_PRINT("Inside %s \n", __FUNCTION__); + + do { + p_buffer = (char *)pBufHdr->pBuffer + byte_pos; + + bytes_read = read(inputBufferFileFd, p_buffer, NUMBER_OF_ARBITRARYBYTES_READ); + byte_pos += bytes_read; + for (byte_cntr = 0; byte_cntr < bytes_read && !pckt_ready; byte_cntr++) { + read_code <<= 8; + ((char*)&read_code)[0] = p_buffer[byte_cntr]; + if (read_code == VOP_START_CODE) { + if (++byte_cntr < bytes_read) { + frame_type = p_buffer[byte_cntr]; + frame_type &= 0x000000C0; +#ifdef __DEBUG_DIVX__ + switch (frame_type) { + case 0x00: pckt_type[pckd_frms] = 'I'; break; + case 0x40: pckt_type[pckd_frms] = 'P'; break; + case 0x80: pckt_type[pckd_frms] = 'B'; break; + default: pckt_type[pckd_frms] = 'X'; + } + pckd_frms++; +#endif // __DEBUG_DIVX__ + offset_array[vop_set_cntr] = byte_pos - bytes_read + byte_cntr - 4; + if (frame_type == 0x80) { // B Frame found! + if (!b_frames_found) { + // Try to packet N_PREV_FRMS_B previous frames + // with the next consecutive B frames + i = N_PREV_FRMS_B; + while ((vop_set_cntr - i) < 0 && i > 0) i--; + b_frm_idx = vop_set_cntr - i; + if (b_frm_idx > 0) { + pckt_end_idx = b_frm_idx; + pckt_ready = true; +#ifdef __DEBUG_DIVX__ + pckt_type[b_frm_idx] = '\0'; + total_frames += b_frm_idx; +#endif //__DEBUG_DIVX__ + } + } + b_frames_found++; + } else if (b_frames_found) { + pckt_end_idx = vop_set_cntr; + pckt_ready = true; +#ifdef __DEBUG_DIVX__ + pckt_type[pckd_frms - 1] = '\0'; + total_frames += pckd_frms - 1; +#endif //__DEBUG_DIVX__ + } else if (vop_set_cntr == (FRM_ARRAY_SIZE -1)) { + pckt_end_idx = MAX_NO_B_FRMS; + pckt_ready = true; +#ifdef __DEBUG_DIVX__ + pckt_type[pckt_end_idx] = '\0'; + total_frames += pckt_end_idx; +#endif //__DEBUG_DIVX__ + } else + vop_set_cntr++; + } else { + // The vop start code was found in the last 4 bytes, + // seek backwards by 4 to include this start code + // with the next buffer. + lseek64(inputBufferFileFd, -4, SEEK_CUR); + byte_pos -= 4; +#ifdef __DEBUG_DIVX__ + pckd_frms--; +#endif //__DEBUG_DIVX__ + } + } + } + if (pckt_ready) { + loff_t off = (byte_pos - offset_array[pckt_end_idx]); + if ( lseek64(inputBufferFileFd, -1LL*off , SEEK_CUR) == -1 ){ + DEBUG_PRINT_ERROR("lseek64 with offset = %lld failed with errno %d" + ", current position =0x%llx", -1LL*off, + errno, lseek64(inputBufferFileFd, 0, SEEK_CUR)); + } + } + else { + char eofByte; + int ret = read(inputBufferFileFd, &eofByte, 1 ); + if ( ret == 0 ) { + offset_array[vop_set_cntr] = byte_pos; + pckt_end_idx = vop_set_cntr; + pckt_ready = true; +#ifdef __DEBUG_DIVX__ + pckt_type[pckd_frms] = '\0'; + total_frames += pckd_frms; +#endif //__DEBUG_DIVX__ + } + else if (ret == 1){ + if ( lseek64(inputBufferFileFd, -1, SEEK_CUR ) == -1 ){ + DEBUG_PRINT_ERROR("lseek64 failed with errno = %d, " + "current fileposition = %llx", + errno, + lseek64(inputBufferFileFd, 0, SEEK_CUR)); + } + } + else { + DEBUG_PRINT_ERROR("Error when checking for EOF"); + } + } + } while (!pckt_ready); + pBufHdr->nFilledLen = offset_array[pckt_end_idx]; + pBufHdr->nTimeStamp = timeStampLfile; + timeStampLfile += timestampInterval; +#ifdef __DEBUG_DIVX__ + total_bytes += pBufHdr->nFilledLen; + ALOGE("[DivX] Packet: Type[%s] Size[%u] TS[%lld] TB[%llx] NFrms[%lld]\n", + pckt_type, pBufHdr->nFilledLen, pBufHdr->nTimeStamp, + total_bytes, total_frames); +#endif //__DEBUG_DIVX__ + return pBufHdr->nFilledLen; +} + +static int Read_Buffer_From_DivX_311_File(OMX_BUFFERHEADERTYPE *pBufHdr) +{ + static OMX_S64 timeStampLfile = 0; + char *p_buffer = NULL; + bool pkt_ready = false; + unsigned int frame_type = 0; + unsigned int bytes_read = 0; + unsigned int frame_size = 0; + unsigned int num_bytes_size = 4; + unsigned int num_bytes_frame_type = 1; + unsigned int n_offset = pBufHdr->nOffset; + + DEBUG_PRINT("Inside %s \n", __FUNCTION__); + + pBufHdr->nTimeStamp = timeStampLfile; + + if (pBufHdr != NULL) + { + p_buffer = (char *)pBufHdr->pBuffer + pBufHdr->nOffset; + } + else + { + DEBUG_PRINT("\n ERROR:Read_Buffer_From_DivX_311_File: pBufHdr is NULL\n"); + return 0; + } + + if (p_buffer == NULL) + { + DEBUG_PRINT("\n ERROR:Read_Buffer_From_DivX_311_File: p_bufhdr is NULL\n"); + return 0; + } + + //Read first frame based on size + //DivX 311 frame - 4 byte header with size followed by the frame + + bytes_read = read(inputBufferFileFd, &frame_size, num_bytes_size); + + DEBUG_PRINT("Read_Buffer_From_DivX_311_File: Frame size = %d\n", frame_size); + n_offset += read(inputBufferFileFd, p_buffer, frame_size); + + pBufHdr->nTimeStamp = timeStampLfile; + + timeStampLfile += timestampInterval; + + //the packet is ready to be sent + DEBUG_PRINT("\nReturning Read Buffer from Divx 311: TS=[%ld], Offset=[%d]\n", + (long int)pBufHdr->nTimeStamp, + n_offset ); + + return n_offset; +} +#ifdef _MSM8974_ +static int Read_Buffer_From_VP8_File(OMX_BUFFERHEADERTYPE *pBufHdr) +{ + static OMX_S64 timeStampLfile = 0; + char *p_buffer = NULL; + bool pkt_ready = false; + unsigned int frame_type = 0; + unsigned int bytes_read = 0; + unsigned int frame_size = 0; + unsigned int num_bytes_size = 4; + unsigned int num_bytes_frame_type = 1; + unsigned long long time_stamp; + unsigned int n_offset = pBufHdr->nOffset; + static int ivf_header_read; + + if (pBufHdr != NULL) + { + p_buffer = (char *)pBufHdr->pBuffer + pBufHdr->nOffset; + } + else + { + DEBUG_PRINT("\n ERROR:Read_Buffer_From_DivX_311_File: pBufHdr is NULL\n"); + return 0; + } + + if (p_buffer == NULL) + { + DEBUG_PRINT("\n ERROR:Read_Buffer_From_DivX_311_File: p_bufhdr is NULL\n"); + return 0; + } + + if(ivf_header_read == 0) { + bytes_read = read(inputBufferFileFd, p_buffer, 32); + ivf_header_read = 1; + if(p_buffer[0] == 'D' && p_buffer[1] == 'K' && p_buffer[2] == 'I' && p_buffer[3] == 'F') + { + printf(" \n IVF header found \n "); + } else + { + printf(" \n No IVF header found \n "); + lseek(inputBufferFileFd, -32, SEEK_CUR); + } + } + bytes_read = read(inputBufferFileFd, &frame_size, 4); + bytes_read = read(inputBufferFileFd, &time_stamp, 8); + n_offset += read(inputBufferFileFd, p_buffer, frame_size); + pBufHdr->nTimeStamp = time_stamp; + return n_offset; +} +#endif +static int open_video_file () +{ + int error_code = 0; + char outputfilename[512]; + DEBUG_PRINT("Inside %s filename=%s\n", __FUNCTION__, in_filename); + + if ( (inputBufferFileFd = open( in_filename, O_RDONLY | O_LARGEFILE) ) == -1 ){ + DEBUG_PRINT_ERROR("Error - i/p file %s could NOT be opened errno = %d\n", + in_filename, errno); + error_code = -1; + } + else { + DEBUG_PRINT_ERROR("i/p file %s is opened \n", in_filename); + } + + if (takeYuvLog) { + strlcpy(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); + } + } +#ifdef _MSM8974_ + /*if (!crcFile) { + crcFile = fopen(crclogname, "ab"); + if (!crcFile) { + printf("Failed to open CRC file\n"); + error_code = -1; + } + }*/ +#endif + 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; +} + +static int overlay_vsync_ctrl(int enable) +{ + int ret; + int vsync_en = enable; + ret = ioctl(fb_fd, MSMFB_OVERLAY_VSYNC_CTRL, &vsync_en); + if (ret) + printf("\n MSMFB_OVERLAY_VSYNC_CTRL failed! (Line %d)\n", + __LINE__); + return ret; +} + + + +void overlay_set() +{ + overlayp = &overlay; + overlayp->src.width = stride; + overlayp->src.height = sliceheight; +#ifdef MAX_RES_720P + overlayp->src.format = MDP_Y_CRCB_H2V2; + if(color_fmt == (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka) + { + overlayp->src.format = MDP_Y_CRCB_H2V2_TILE; + } +#endif +#ifdef MAX_RES_1080P + overlayp->src.format = MDP_Y_CBCR_H2V2_TILE; +#endif +#ifdef _MSM8974_ + overlayp->src.format = MDP_Y_CBCR_H2V2_VENUS; +#endif + 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.h = (overlayp->dst_rect.w * height)/width; + overlayp->dst_rect.y = 0; + if (overlayp->dst_rect.h < vinfo.yres) + overlayp->dst_rect.y = (vinfo.yres - overlayp->dst_rect.h)/2; + else + overlayp->dst_rect.h = vinfo.yres; + } + else + { + overlayp->dst_rect.y = (vinfo.yres - height)/2; + overlayp->dst_rect.h = height; + } + + //Decimation + MDP Downscale + overlayp->horz_deci = 0; + overlayp->vert_deci = 0; + int minHorDeci = 0; + if(overlayp->src_rect.w > 2048) { + //If the client sends us something > what a layer mixer supports + //then it means it doesn't want to use split-pipe but wants us to + //decimate. A minimum decimation of 2 will ensure that the width is + //always within layer mixer limits. + minHorDeci = 2; + } + + float horDscale = ceilf((float)overlayp->src_rect.w / + (float)overlayp->dst_rect.w); + float verDscale = ceilf((float)overlayp->src_rect.h / + (float)overlayp->dst_rect.h); + + //Next power of 2, if not already + horDscale = powf(2.0f, ceilf(log2f(horDscale))); + verDscale = powf(2.0f, ceilf(log2f(verDscale))); + + //Since MDP can do 1/4 dscale and has better quality, split the task + //between decimator and MDP downscale + horDscale /= 4.0f; + verDscale /= 4.0f; + + if(horDscale < minHorDeci) + horDscale = minHorDeci; + if((int)horDscale) + overlayp->horz_deci = (int)log2f(horDscale); + + if((int)verDscale) + overlayp->vert_deci = (int)log2f(verDscale); + + printf("overlayp->src.width = %u \n", overlayp->src.width); + printf("overlayp->src.height = %u \n", overlayp->src.height); + printf("overlayp->src_rect.x = %u \n", overlayp->src_rect.x); + printf("overlayp->src_rect.y = %u \n", overlayp->src_rect.y); + printf("overlayp->src_rect.w = %u \n", overlayp->src_rect.w); + printf("overlayp->src_rect.h = %u \n", overlayp->src_rect.h); + 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); + printf("overlayp->vert_deci = %u \n", overlayp->vert_deci); + printf("overlayp->horz_deci = %u \n", overlayp->horz_deci); + + overlayp->z_order = 0; + overlayp->alpha = 0xff; + overlayp->transp_mask = 0xFFFFFFFF; + overlayp->flags = 0; + overlayp->is_fg = 0; + + overlayp->id = MSMFB_NEW_REQUEST; + + overlay_vsync_ctrl(OMX_TRUE); + drawBG(); + 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); + displayYuv = 2; +} + +int overlay_fb(struct OMX_BUFFERHEADERTYPE *pBufHdr) +{ + OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo = NULL; + struct msmfb_overlay_data ov_front; + memset(&ov_front, 0, sizeof(struct msmfb_overlay_data)); +#if defined(_ANDROID_) && !defined(USE_EGL_IMAGE_TEST_APP) && !defined(USE_EXTERN_PMEM_BUF) + MemoryHeapBase *vheap = NULL; +#endif + + DEBUG_PRINT("overlay_fb:"); + ov_front.id = overlayp->id; + if (pBufHdr->pPlatformPrivate == NULL) + { + ALOGE("overlay_fb: pPlatformPrivate is null"); + return -1; + } + pPMEMInfo = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *) + ((OMX_QCOM_PLATFORM_PRIVATE_LIST *) + pBufHdr->pPlatformPrivate)->entryList->entry; + if (pPMEMInfo == NULL) + { + + ALOGE("overlay_fb: pmem_info is null"); + return -1; + } +#if defined(_ANDROID_) && !defined(USE_EGL_IMAGE_TEST_APP) && !defined(USE_EXTERN_PMEM_BUF) + vheap = (MemoryHeapBase*)pPMEMInfo->pmem_fd; +#endif + + +#if defined(_ANDROID_) && !defined(USE_EGL_IMAGE_TEST_APP) && !defined(USE_EXTERN_PMEM_BUF) && !defined(_MSM8974_) + 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; + } + if (ioctl(fb_fd, FBIOPAN_DISPLAY, &vinfo) < 0) + { + printf("ERROR: FBIOPAN_DISPLAY failed! 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; +#if defined(_ANDROID_) && !defined(USE_EGL_IMAGE_TEST_APP) && !defined(USE_EXTERN_PMEM_BUF) + 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; +#if defined(_ANDROID_) && !defined(USE_EGL_IMAGE_TEST_APP) && !defined(USE_EXTERN_PMEM_BUF) + 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; +#if defined(_ANDROID_) && !defined(USE_EGL_IMAGE_TEST_APP) && !defined(USE_EXTERN_PMEM_BUF) + 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"); +} + +int disable_output_port() +{ + DEBUG_PRINT("DISABLING OP PORT\n"); + pthread_mutex_lock(&enable_lock); + sent_disabled = 1; + // Send DISABLE command + OMX_SendCommand(dec_handle, OMX_CommandPortDisable, 1, 0); + pthread_mutex_unlock(&enable_lock); + // wait for Disable event to come back + wait_for_event(); + if(p_eglHeaders) { + free(p_eglHeaders); + p_eglHeaders = NULL; + } + if (pPMEMInfo) + { + DEBUG_PRINT("Freeing in external pmem case:PMEM"); + free(pPMEMInfo); + pPMEMInfo = NULL; + } + if (pPlatformEntry) + { + DEBUG_PRINT("Freeing in external pmem case:ENTRY"); + free(pPlatformEntry); + pPlatformEntry = NULL; + } + if (pPlatformList) + { + DEBUG_PRINT("Freeing in external pmem case:LIST"); + free(pPlatformList); + pPlatformList = NULL; + } + if (currentStatus == ERROR_STATE) + { + do_freeHandle_and_clean_up(true); + return -1; + } + DEBUG_PRINT("OP PORT DISABLED!\n"); + return 0; +} + +int enable_output_port() +{ + int bufCnt = 0; + OMX_ERRORTYPE ret = OMX_ErrorNone; + DEBUG_PRINT("ENABLING OP PORT\n"); + // Send Enable command + OMX_SendCommand(dec_handle, OMX_CommandPortEnable, 1, 0); +#ifndef USE_EGL_IMAGE_TEST_APP + /* Allocate buffer on decoder's o/p port */ + portFmt.nPortIndex = 1; + + if (anti_flickering) { + ret = OMX_GetParameter(dec_handle,OMX_IndexParamPortDefinition,&portFmt); + if (ret != OMX_ErrorNone) { + DEBUG_PRINT_ERROR("%s: OMX_GetParameter failed: %d",__FUNCTION__, ret); + return -1; + } + portFmt.nBufferCountActual += 1; + ret = OMX_SetParameter(dec_handle,OMX_IndexParamPortDefinition,&portFmt); + if (ret != OMX_ErrorNone) { + DEBUG_PRINT_ERROR("%s: OMX_SetParameter failed: %d",__FUNCTION__, ret); + return -1; + } + } + + if (use_external_pmem_buf) + { + DEBUG_PRINT("Enable op port: calling use_buffer_mult_fd\n"); + error = use_output_buffer_multiple_fd(dec_handle, + &pOutYUVBufHdrs, + portFmt.nPortIndex, + portFmt.nBufferSize, + portFmt.nBufferCountActual); + } + else + { + 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"); + free_op_buf_cnt = portFmt.nBufferCountActual; + } +#else + error = use_output_buffer(dec_handle, + &pOutYUVBufHdrs, + portFmt.nPortIndex, + portFmt.nBufferSize, + portFmt.nBufferCountActual); + free_op_buf_cnt = portFmt.nBufferCountActual; + if (error != OMX_ErrorNone) { + DEBUG_PRINT_ERROR("ERROR - OMX_UseBuffer Input buffer failed"); + return -1; + } + else { + DEBUG_PRINT("OMX_UseBuffer Input buffer success\n"); + } + +#endif + // wait for enable event to come back + wait_for_event(); + if (currentStatus == ERROR_STATE) + { + do_freeHandle_and_clean_up(true); + return -1; + } + if (pOutYUVBufHdrs == NULL) + { + DEBUG_PRINT_ERROR("Error - pOutYUVBufHdrs is NULL\n"); + return -1; + } + for(bufCnt=0; bufCnt < portFmt.nBufferCountActual; ++bufCnt) { + DEBUG_PRINT("OMX_FillThisBuffer on output buf no.%d\n",bufCnt); + if (pOutYUVBufHdrs[bufCnt] == NULL) + { + DEBUG_PRINT_ERROR("Error - pOutYUVBufHdrs[%d] is NULL\n", bufCnt); + return -1; + } + 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"); + free_op_buf_cnt--; + } + } + DEBUG_PRINT("OP PORT ENABLED!\n"); + return 0; +} + +int output_port_reconfig() +{ + DEBUG_PRINT("PORT_SETTING_CHANGE_STATE\n"); + if (disable_output_port() != 0) + return -1; + + /* Port for which the Client needs to obtain info */ + portFmt.nPortIndex = 1; + 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; + + crop_rect.nWidth = width; + crop_rect.nHeight = height; + + if (displayYuv == 2) + { + DEBUG_PRINT("Reconfiguration at middle of playback..."); + close_display(); + if (open_display() != 0) + { + printf("\n Error opening display! Video won't be displayed..."); + displayYuv = 0; + } + } + + if (displayYuv) + overlay_set(); + + if (enable_output_port() != 0) + return -1; + DEBUG_PRINT("PORT_SETTING_CHANGE DONE!\n"); + return 0; +} + +void free_output_buffers() +{ + int index = 0; + OMX_BUFFERHEADERTYPE *pBuffer = (OMX_BUFFERHEADERTYPE *)pop(fbd_queue); + while (pBuffer) { + DEBUG_PRINT("\n pOutYUVBufHdrs %p p_eglHeaders %p output_use_buffer %d", + pOutYUVBufHdrs,p_eglHeaders,output_use_buffer); + if(pOutYUVBufHdrs && p_eglHeaders && output_use_buffer) + { + index = pBuffer - pOutYUVBufHdrs[0]; + DEBUG_PRINT("\n Index of free buffer %d",index); + DEBUG_PRINT("\n Address freed %p size freed %d",pBuffer->pBuffer, + pBuffer->nAllocLen); + munmap((void *)use_buf_virt_addr[index],pBuffer->nAllocLen); + if(p_eglHeaders[index]) + { + close(p_eglHeaders[index]->pmem_fd); + free(p_eglHeaders[index]); + p_eglHeaders[index] = NULL; + } + } + + if (pOutYUVBufHdrs && use_external_pmem_buf) + { + index = pBuffer - pOutYUVBufHdrs[0]; + DEBUG_PRINT("\n Address freed %p size freed %d,virt=0x%x,pmem_fd=0x%x", + pBuffer->pBuffer, + pBuffer->nAllocLen, + use_buf_virt_addr[index], + pPMEMInfo[index].pmem_fd); + munmap((void *)use_buf_virt_addr[index],pBuffer->nAllocLen); + getFreePmem(); + use_buf_virt_addr[index] = -1; + if (&pPMEMInfo[index]) + { + close(pPMEMInfo[index].pmem_fd); + pPMEMInfo[index].pmem_fd = -1; + } + } + DEBUG_PRINT("\n Free output buffer"); + OMX_FreeBuffer(dec_handle, 1, pBuffer); + pBuffer = (OMX_BUFFERHEADERTYPE *)pop(fbd_queue); + } +} + +#ifndef USE_ION +static bool align_pmem_buffers(int pmem_fd, OMX_U32 buffer_size, + OMX_U32 alignment) +{ + struct pmem_allocation allocation; + allocation.size = buffer_size; + allocation.align = clip2(alignment); + + if (allocation.align < 4096) + { + allocation.align = 4096; + } + if (ioctl(pmem_fd, PMEM_ALLOCATE_ALIGNED, &allocation) < 0) + { + DEBUG_PRINT_ERROR("\n Aligment failed with pmem driver"); + return false; + } + return true; +} +#endif + +int open_display() +{ +#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; + } + printf("Display xres = %d, yres = %d \n", vinfo.xres, vinfo.yres); + return 0; +} + +void close_display() +{ + overlay_unset(); + overlay_vsync_ctrl(OMX_FALSE); + close(fb_fd); + fb_fd = -1; +} + +void getFreePmem() +{ +#ifndef USE_ION + int ret = -1; + /*Open pmem device and query free pmem*/ + int pmem_fd = open (PMEM_DEVICE,O_RDWR); + + if(pmem_fd < 0) { + ALOGE("Unable to open pmem device"); + return; + } + struct pmem_freespace fs; + ret = ioctl(pmem_fd, PMEM_GET_FREE_SPACE, &fs); + if(ret) { + ALOGE("IOCTL to query pmem free space failed"); + goto freespace_query_failed; + } + ALOGE("Available free space %lx largest chunk %lx\n", fs.total, fs.largest); +freespace_query_failed: + close(pmem_fd); +#endif +} |