summaryrefslogtreecommitdiff
path: root/mm-video-v4l2/vidc/vdec/test/omx_vdec_test.cpp
diff options
context:
space:
mode:
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.cpp4543
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
+}