diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/Android.mk | 5 | ||||
-rw-r--r-- | test/decoder.mk | 13 | ||||
-rw-r--r-- | test/decoder/main.c | 3135 |
3 files changed, 3153 insertions, 0 deletions
diff --git a/test/Android.mk b/test/Android.mk new file mode 100644 index 0000000..7807003 --- /dev/null +++ b/test/Android.mk @@ -0,0 +1,5 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +# decoder +include $(LOCAL_PATH)/decoder.mk diff --git a/test/decoder.mk b/test/decoder.mk new file mode 100644 index 0000000..2aef0f9 --- /dev/null +++ b/test/decoder.mk @@ -0,0 +1,13 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := mpeg2dec +LOCAL_MODULE_TAGS := optional + +LOCAL_CFLAGS := -DPROFILE_ENABLE -DMD5_DISABLE -DARM -fPIC +LOCAL_C_INCLUDES += $(LOCAL_PATH)/../decoder $(LOCAL_PATH)/../common $(LOCAL_PATH)/decoder/ +LOCAL_SRC_FILES := decoder/main.c +LOCAL_STATIC_LIBRARIES := libmpeg2dec + +include $(BUILD_EXECUTABLE) diff --git a/test/decoder/main.c b/test/decoder/main.c new file mode 100644 index 0000000..5930bd1 --- /dev/null +++ b/test/decoder/main.c @@ -0,0 +1,3135 @@ +/****************************************************************************** + * + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ***************************************************************************** + * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore +*/ +/*****************************************************************************/ +/* */ +/* File Name : main.c */ +/* */ +/* Description : Contains an application that demonstrates use of HEVC*/ +/* decoder API */ +/* */ +/* List of Functions : */ +/* */ +/* Issues / Problems : None */ +/* */ +/* Revision History : */ +/* */ +/* DD MM YYYY Author(s) Changes */ +/* 07 09 2012 Harish Initial Version */ +/*****************************************************************************/ +/*****************************************************************************/ +/* File Includes */ +/*****************************************************************************/ +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#ifdef X86_MINGW +#include <signal.h> +#endif + +#ifndef IOS +#include <malloc.h> +#endif +#ifdef IOS_DISPLAY +#include "cast_types.h" +#else +#include "iv_datatypedef.h" +#endif + +#include "iv.h" +#include "ivd.h" +#include "impeg2d.h" +#include "ithread.h" + +#ifdef WINDOWS_TIMER +#include <windows.h> +#else +#include <sys/time.h> +#endif + +#define ALIGN8(x) ((((x) + 7) >> 3) << 3) +#define NUM_DISPLAY_BUFFERS 4 +#define DEFAULT_FPS 30 + + +#define ENABLE_DEGRADE 0 +#define MAX_DISP_BUFFERS 64 +#define EXTRA_DISP_BUFFERS 0 +#define STRLENGTH 1000 + +//#define TEST_FLUSH +#define FLUSH_FRM_CNT 100 + + +#ifdef IOS +#define PATHLENMAX 500 +char filename_with_path[PATHLENMAX]; +#endif + +#ifdef PROFILE_ENABLE +#ifdef WINDOWS_TIMER +typedef LARGE_INTEGER TIMER; +#else +typedef struct timeval TIMER; +#endif +#else +typedef WORD32 TIMER; +#endif + +#ifdef PROFILE_ENABLE +#ifdef WINDOWS_TIMER +#define GETTIME(timer) QueryPerformanceCounter(timer); +#else +#define GETTIME(timer) gettimeofday(timer,NULL); +#endif + +#ifdef WINDOWS_TIMER +#define ELAPSEDTIME(s_start_timer,s_end_timer, s_elapsed_time, frequency) \ +{ \ + TIMER s_temp_time; \ + s_temp_time.LowPart = s_end_timer.LowPart - s_start_timer.LowPart ; \ + s_elapsed_time = (UWORD32) ( ((DOUBLE)s_temp_time.LowPart / (DOUBLE)frequency.LowPart ) * 1000000); \ +} +#else +#define ELAPSEDTIME(s_start_timer,s_end_timer, s_elapsed_time, frequency) \ + s_elapsed_time = ((s_end_timer.tv_sec - s_start_timer.tv_sec) * 1000000) + (s_end_timer.tv_usec - s_start_timer.tv_usec); +#endif + +#else +#define GETTIME(timer) +#define ELAPSEDTIME(s_start_timer,s_end_timer, s_elapsed_time, frequency) +#endif + + +/* Function declarations */ +#ifndef MD5_DISABLE +void calc_md5_cksum(UWORD8 *pu1_inbuf, UWORD32 u4_stride, UWORD32 u4_width, UWORD32 u4_height, UWORD8 *pu1_cksum_p); +#else +#define calc_md5_cksum(a, b, c, d, e) +#endif +#ifdef SDL_DISPLAY +void* sdl_disp_init(UWORD32, UWORD32, WORD32, WORD32, WORD32, WORD32, WORD32, WORD32 *, WORD32 *); +void sdl_alloc_disp_buffers(void *); +void sdl_display(void *, WORD32); +void sdl_set_disp_buffers(void *, WORD32, UWORD8 **, UWORD8 **, UWORD8 **); +void sdl_disp_deinit(void *); +void sdl_disp_usleep(UWORD32); +IV_COLOR_FORMAT_T sdl_get_color_fmt(void); +UWORD32 sdl_get_stride(void); +#endif + +#ifdef INTEL_CE5300 +void* gdl_disp_init(UWORD32, UWORD32, WORD32, WORD32, WORD32, WORD32, WORD32, WORD32 *, WORD32 *); +void gdl_alloc_disp_buffers(void *); +void gdl_display(void *, WORD32); +void gdl_set_disp_buffers(void *, WORD32, UWORD8 **, UWORD8 **, UWORD8 **); +void gdl_disp_deinit(void *); +void gdl_disp_usleep(UWORD32); +IV_COLOR_FORMAT_T gdl_get_color_fmt(void); +UWORD32 gdl_get_stride(void); +#endif + +#ifdef FBDEV_DISPLAY +void* fbd_disp_init(UWORD32, UWORD32, WORD32, WORD32, WORD32, WORD32, WORD32, WORD32 *, WORD32 *); +void fbd_alloc_disp_buffers(void *); +void fbd_display(void *, WORD32); +void fbd_set_disp_buffers(void *, WORD32, UWORD8 **, UWORD8 **, UWORD8 **); +void fbd_disp_deinit(void *); +void fbd_disp_usleep(UWORD32); +IV_COLOR_FORMAT_T fbd_get_color_fmt(void); +UWORD32 fbd_get_stride(void); +#endif + +#ifdef IOS_DISPLAY +void* ios_disp_init(UWORD32, UWORD32, WORD32, WORD32, WORD32, WORD32, WORD32, WORD32 *, WORD32 *); +void ios_alloc_disp_buffers(void *); +void ios_display(void *, WORD32); +void ios_set_disp_buffers(void *, WORD32, UWORD8 **, UWORD8 **, UWORD8 **); +void ios_disp_deinit(void *); +void ios_disp_usleep(UWORD32); +IV_COLOR_FORMAT_T ios_get_color_fmt(void); +UWORD32 ios_get_stride(void); +#endif + +typedef struct +{ + UWORD32 u4_piclen_flag; + UWORD32 u4_file_save_flag; + UWORD32 u4_chksum_save_flag; + UWORD32 u4_max_frm_ts; + IV_COLOR_FORMAT_T e_output_chroma_format; + IVD_ARCH_T e_arch; + IVD_SOC_T e_soc; + UWORD32 dump_q_rd_idx; + UWORD32 dump_q_wr_idx; + WORD32 disp_q_wr_idx; + WORD32 disp_q_rd_idx; + + void *cocodec_obj; + UWORD32 share_disp_buf; + UWORD32 num_disp_buf; + UWORD32 b_pic_present; + WORD32 i4_degrade_type; + WORD32 i4_degrade_pics; + UWORD32 u4_num_cores; + UWORD32 disp_delay; + WORD32 trace_enable; + CHAR ac_trace_fname[STRLENGTH]; + CHAR ac_piclen_fname[STRLENGTH]; + CHAR ac_ip_fname[STRLENGTH]; + CHAR ac_op_fname[STRLENGTH]; + CHAR ac_op_chksum_fname[STRLENGTH]; + ivd_out_bufdesc_t s_disp_buffers[MAX_DISP_BUFFERS]; + iv_yuv_buf_t s_disp_frm_queue[MAX_DISP_BUFFERS]; + UWORD32 s_disp_frm_id_queue[MAX_DISP_BUFFERS]; + UWORD32 loopback; + UWORD32 display; + UWORD32 full_screen; + UWORD32 fps; + UWORD32 max_wd; + UWORD32 max_ht; + UWORD32 max_level; + + UWORD32 u4_strd; + + /* For signalling to display thread */ + UWORD32 u4_pic_wd; + UWORD32 u4_pic_ht; + + /* For IOS diplay */ + WORD32 i4_screen_wd; + WORD32 i4_screen_ht; + + //UWORD32 u4_output_present; + WORD32 quit; + WORD32 paused; + + + void *pv_disp_ctx; + void *display_thread_handle; + WORD32 display_thread_created; + volatile WORD32 display_init_done; + volatile WORD32 display_deinit_flag; + + void* (*disp_init)(UWORD32, UWORD32, WORD32, WORD32, WORD32, WORD32, WORD32, WORD32 *, WORD32 *); + void (*alloc_disp_buffers)(void *); + void (*display_buffer)(void *, WORD32); + void (*set_disp_buffers)(void *, WORD32, UWORD8 **, UWORD8 **, UWORD8 **); + void (*disp_deinit)(void *); + void (*disp_usleep)(UWORD32); + IV_COLOR_FORMAT_T(*get_color_fmt)(void); + UWORD32(*get_stride)(void); +}vid_dec_ctx_t; + + + +typedef enum +{ + INVALID, + HELP, + VERSION, + INPUT_FILE, + OUTPUT, + CHKSUM, + SAVE_OUTPUT, + SAVE_CHKSUM, + CHROMA_FORMAT, + NUM_FRAMES, + NUM_CORES, + + SHARE_DISPLAY_BUF, + LOOPBACK, + DISPLAY, + FULLSCREEN, + FPS, + TRACE, + MAX_WD, + MAX_HT, + MAX_LEVEL, + CONFIG, + + DEGRADE_TYPE, + DEGRADE_PICS, + ARCH, + SOC, + PICLEN, + PICLEN_FILE, +}ARGUMENT_T; + +typedef struct +{ + CHAR argument_shortname[4]; + CHAR argument_name[128]; + ARGUMENT_T argument; + CHAR description[512]; +}argument_t; + +static const argument_t argument_mapping[] = +{ + { "-h", "--help", HELP, + "Print this help\n" }, + { "-c", "--config", CONFIG, + "config file (Default: test.cfg)\n" }, + + { "-v", "--version", VERSION, + "Version information\n" }, + { "-i", "--input", INPUT_FILE, + "Input file\n" }, + { "-o", "--output", OUTPUT, + "Output file\n" }, + { "--", "--piclen", PICLEN, + "Flag to signal if the decoder has to use a file containing number of bytes in each picture to be fed in each call\n" }, + { "--", "--piclen_file", PICLEN_FILE, + "File containing number of bytes in each picture - each line containing one size\n" }, + { "--", "--chksum", CHKSUM, + "Output MD5 Checksum file\n" }, + { "-s", "--save_output", SAVE_OUTPUT, + "Save Output file\n" }, + { "--", "--save_chksum", SAVE_CHKSUM, + "Save Check sum file\n" }, + { "--", "--chroma_format", CHROMA_FORMAT, + "Output Chroma format Supported values YUV_420P, YUV_422ILE, RGB_565, YUV_420SP_UV, YUV_420SP_VU\n" }, + { "-n", "--num_frames", NUM_FRAMES, + "Number of frames to be decoded\n" }, + { "--", "--num_cores", NUM_CORES, + "Number of cores to be used\n" }, + { "--", "--share_display_buf", SHARE_DISPLAY_BUF, + "Enable shared display buffer mode\n" }, + + { "--", "--loopback", LOOPBACK, + "Enable playback in a loop\n" }, + { "--", "--display", DISPLAY, + "Enable display (uses SDL)\n" }, + { "--", "--fullscreen", FULLSCREEN, + "Enable full screen (Only for GDL and SDL)\n" }, + { "--", "--fps", FPS, + "FPS to be used for display \n" }, + { "-i", "--trace", TRACE, + "Trace file\n" }, + { "--", "--max_wd", MAX_WD, + "Maximum width (Default: 2560) \n" }, + { "--", "--max_ht", MAX_HT, + "Maximum height (Default: 1600)\n" }, + { "--", "--arch", ARCH, + "Set Architecture. Supported values ARM_NONEON, ARM_A9Q, ARM_A7, ARM_A5, ARM_NEONINTR, X86_GENERIC, X86_SSSE3, X86_SSE4 \n" }, + { "--", "--soc", SOC, + "Set SOC. Supported values GENERIC, HISI_37X \n" }, + +#if 0 + { "--", "--degrade_type", DEGRADE_TYPE, + "Degrade type : 0: No degrade 0th bit set : Disable SAO 1st bit set : Disable deblocking 2nd bit set : Faster inter prediction filters 3rd bit set : Fastest inter prediction filters\n" }, + { "--", "--degrade_pics", DEGRADE_PICS, + "Degrade pics : 0 : No degrade 1 : Only on non-reference frames 2 : Do not degrade every 4th or key frames 3 : All non-key frames 4 : All frames" }, + + { "--", "--max_level", MAX_LEVEL, + "Maximum Decoder Level (Default: 50)\n" }, +#endif +}; + +#define PEAK_WINDOW_SIZE 8 +#define MAX_FRAME_WIDTH 2560 +#define MAX_FRAME_HEIGHT 1600 +#define MAX_LEVEL_SUPPORTED 50 +#define MAX_REF_FRAMES 16 +#define MAX_REORDER_FRAMES 16 +#define DEFAULT_SHARE_DISPLAY_BUF 0 +#define STRIDE 0 +#define DEFAULT_NUM_CORES 1 + +#define DUMP_SINGLE_BUF 0 +#define IV_ISFATALERROR(x) (((x) >> IVD_FATALERROR) & 0x1) + +#define ivd_api_function impeg2d_api_function + +#ifdef IOS +char filename_trace[PATHLENMAX]; +#endif + +#if ANDROID_NDK +/*****************************************************************************/ +/* */ +/* Function Name : raise */ +/* */ +/* Description : Needed as a workaround when the application is built in */ +/* Android NDK. This is an exception to be called for divide*/ +/* by zero error */ +/* */ +/* Inputs : a */ +/* Globals : */ +/* Processing : None */ +/* */ +/* Outputs : */ +/* Returns : */ +/* */ +/* Issues : */ +/* */ +/* Revision History: */ +/* */ +/* DD MM YYYY Author(s) Changes */ +/* 07 09 2012 100189 Initial Version */ +/* */ +/*****************************************************************************/ +int raise(int a) +{ + printf("Divide by zero\n"); + return 0; +} +#endif + +#ifdef _WIN32 +/*****************************************************************************/ +/* Function to print library calls */ +/*****************************************************************************/ +/*****************************************************************************/ +/* */ +/* Function Name : memalign */ +/* */ +/* Description : Returns malloc data. Ideally should return aligned memory*/ +/* support alignment will be added later */ +/* */ +/* Inputs : alignment */ +/* size */ +/* Globals : */ +/* Processing : */ +/* */ +/* Outputs : */ +/* Returns : */ +/* */ +/* Issues : */ +/* */ +/* Revision History: */ +/* */ +/* DD MM YYYY Author(s) Changes */ +/* 07 09 2012 100189 Initial Version */ +/* */ +/*****************************************************************************/ + +void* app_aligned_malloc(WORD32 alignment, WORD32 size) +{ + return (void *)_aligned_malloc(size, alignment); +} + +void app_aligned_free(void *pv_buf) +{ + _aligned_free(pv_buf); + return; +} +#endif + +#if IOS +void* app_aligned_malloc(WORD32 alignment, WORD32 size) +{ + return malloc(size); +} + +void app_aligned_free(void *pv_buf) +{ + free(pv_buf); + return; +} +#endif + +#if (!defined(IOS)) && (!defined(_WIN32)) +void* app_aligned_malloc(WORD32 alignment, WORD32 size) +{ + return memalign(alignment, size); +} + +void app_aligned_free(void *pv_buf) +{ + free(pv_buf); + return; +} +#endif + +/*****************************************************************************/ +/* */ +/* Function Name : set_degrade */ +/* */ +/* Description : Control call to set degrade level */ +/* */ +/* */ +/* Inputs : codec_obj - Codec Handle */ +/* type - degrade level value between 0 to 4 */ +/* 0 : No degrade */ +/* 1st bit : Disable SAO */ +/* 2nd bit : Disable Deblock */ +/* 3rd bit : Faster MC for non-ref */ +/* 4th bit : Fastest MC for non-ref */ +/* pics - Pictures that are are degraded */ +/* 0 : No degrade */ +/* 1 : Non-ref pictures */ +/* 2 : Pictures at given interval are not degraded */ +/* 3 : All non-key pictures */ +/* 4 : All pictures */ +/* Globals : */ +/* Processing : Calls degrade control to the codec */ +/* */ +/* Outputs : */ +/* Returns : Control call return status */ +/* */ +/* Issues : */ +/* */ +/* Revision History: */ +/* */ +/* DD MM YYYY Author(s) Changes */ +/* 07 09 2012 100189 Initial Version */ +/* */ +/*****************************************************************************/ + +IV_API_CALL_STATUS_T set_degrade(void *codec_obj, UWORD32 type, WORD32 pics) +{ + IV_API_CALL_STATUS_T e_dec_status = IV_SUCCESS; +#if 0 + impeg2d_ctl_degrade_ip_t s_ctl_ip; + impeg2d_ctl_degrade_op_t s_ctl_op; + void *pv_api_ip, *pv_api_op; + + + s_ctl_ip.u4_size = sizeof(impeg2d_ctl_degrade_ip_t); + s_ctl_ip.i4_degrade_type = type; + s_ctl_ip.i4_nondegrade_interval = 4; + s_ctl_ip.i4_degrade_pics = pics; + + s_ctl_op.u4_size = sizeof(impeg2d_ctl_degrade_op_t); + + pv_api_ip = (void *)&s_ctl_ip; + pv_api_op = (void *)&s_ctl_op; + + s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL; + s_ctl_ip.e_sub_cmd = (IVD_CONTROL_API_COMMAND_TYPE_T)IMPEG2D_CMD_CTL_DEGRADE; + + e_dec_status = ivd_api_function((iv_obj_t *)codec_obj, pv_api_ip, pv_api_op); + + if(IV_SUCCESS != e_dec_status) + { + printf("Error in setting degrade level \n"); + } +#endif + ((void)(codec_obj)); + ((void)(type)); + ((void)(pics)); + return (e_dec_status); + +} + +/*****************************************************************************/ +/* */ +/* Function Name : enable_skipb_frames */ +/* */ +/* Description : Control call to enable skipping of b frames */ +/* */ +/* */ +/* Inputs : codec_obj : Codec handle */ +/* Globals : */ +/* Processing : Calls enable skip B frames control */ +/* */ +/* Outputs : */ +/* Returns : Control call return status */ +/* */ +/* Issues : */ +/* */ +/* Revision History: */ +/* */ +/* DD MM YYYY Author(s) Changes */ +/* 07 09 2012 100189 Initial Version */ +/* */ +/*****************************************************************************/ + +IV_API_CALL_STATUS_T enable_skipb_frames(void *codec_obj, + vid_dec_ctx_t *ps_app_ctx) +{ + ivd_ctl_set_config_ip_t s_ctl_ip; + ivd_ctl_set_config_op_t s_ctl_op; + IV_API_CALL_STATUS_T e_dec_status; + + s_ctl_ip.u4_disp_wd = ps_app_ctx->u4_strd; + s_ctl_ip.e_frm_skip_mode = IVD_SKIP_B; + + s_ctl_ip.e_frm_out_mode = IVD_DISPLAY_FRAME_OUT; + s_ctl_ip.e_vid_dec_mode = IVD_DECODE_FRAME; + s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL; + s_ctl_ip.e_sub_cmd = IVD_CMD_CTL_SETPARAMS; + s_ctl_ip.u4_size = sizeof(ivd_ctl_set_config_ip_t); + s_ctl_op.u4_size = sizeof(ivd_ctl_set_config_op_t); + + e_dec_status = ivd_api_function((iv_obj_t *)codec_obj, (void *)&s_ctl_ip, + (void *)&s_ctl_op); + + if(IV_SUCCESS != e_dec_status) + { + printf("Error in Enable SkipB frames \n"); + } + + return e_dec_status; +} +/*****************************************************************************/ +/* */ +/* Function Name : disable_skipb_frames */ +/* */ +/* Description : Control call to disable skipping of b frames */ +/* */ +/* */ +/* Inputs : codec_obj : Codec handle */ +/* Globals : */ +/* Processing : Calls disable B frame skip control */ +/* */ +/* Outputs : */ +/* Returns : Control call return status */ +/* */ +/* Issues : */ +/* */ +/* Revision History: */ +/* */ +/* DD MM YYYY Author(s) Changes */ +/* 07 09 2012 100189 Initial Version */ +/* */ +/*****************************************************************************/ + +IV_API_CALL_STATUS_T disable_skipb_frames(void *codec_obj, + vid_dec_ctx_t *ps_app_ctx) +{ + ivd_ctl_set_config_ip_t s_ctl_ip; + ivd_ctl_set_config_op_t s_ctl_op; + IV_API_CALL_STATUS_T e_dec_status; + + s_ctl_ip.u4_disp_wd = ps_app_ctx->u4_strd; + s_ctl_ip.e_frm_skip_mode = IVD_SKIP_NONE; + + s_ctl_ip.e_frm_out_mode = IVD_DISPLAY_FRAME_OUT; + s_ctl_ip.e_vid_dec_mode = IVD_DECODE_FRAME; + s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL; + s_ctl_ip.e_sub_cmd = IVD_CMD_CTL_SETPARAMS; + s_ctl_ip.u4_size = sizeof(ivd_ctl_set_config_ip_t); + s_ctl_op.u4_size = sizeof(ivd_ctl_set_config_op_t); + + e_dec_status = ivd_api_function((iv_obj_t *)codec_obj, (void *)&s_ctl_ip, + (void *)&s_ctl_op); + + if(IV_SUCCESS != e_dec_status) + { + printf("Error in Disable SkipB frames\n"); + } + + return e_dec_status; +} + +/*****************************************************************************/ +/* */ +/* Function Name : enable_skippb_frames */ +/* */ +/* Description : Control call to enable skipping of P & B frames */ +/* */ +/* */ +/* Inputs : codec_obj : Codec handle */ +/* Globals : */ +/* Processing : Calls enable skip P and B frames control */ +/* */ +/* Outputs : */ +/* Returns : Control call return status */ +/* */ +/* Issues : */ +/* */ +/* Revision History: */ +/* */ +/* DD MM YYYY Author(s) Changes */ +/* 07 09 2012 100189 Initial Version */ +/* */ +/*****************************************************************************/ + +IV_API_CALL_STATUS_T enable_skippb_frames(void *codec_obj, + vid_dec_ctx_t *ps_app_ctx) +{ + ivd_ctl_set_config_ip_t s_ctl_ip; + ivd_ctl_set_config_op_t s_ctl_op; + IV_API_CALL_STATUS_T e_dec_status; + + s_ctl_ip.u4_disp_wd = ps_app_ctx->u4_strd; + s_ctl_ip.e_frm_skip_mode = IVD_SKIP_PB; + + s_ctl_ip.e_frm_out_mode = IVD_DISPLAY_FRAME_OUT; + s_ctl_ip.e_vid_dec_mode = IVD_DECODE_FRAME; + s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL; + s_ctl_ip.e_sub_cmd = IVD_CMD_CTL_SETPARAMS; + s_ctl_ip.u4_size = sizeof(ivd_ctl_set_config_ip_t); + s_ctl_op.u4_size = sizeof(ivd_ctl_set_config_op_t); + + e_dec_status = ivd_api_function((iv_obj_t *)codec_obj, (void *)&s_ctl_ip, + (void *)&s_ctl_op); + if(IV_SUCCESS != e_dec_status) + { + printf("Error in Enable SkipPB frames\n"); + } + + return e_dec_status; +} + +/*****************************************************************************/ +/* */ +/* Function Name : disable_skippb_frames */ +/* */ +/* Description : Control call to disable skipping of P and B frames */ +/* */ +/* */ +/* Inputs : codec_obj : Codec handle */ +/* Globals : */ +/* Processing : Calls disable P and B frame skip control */ +/* */ +/* Outputs : */ +/* Returns : Control call return status */ +/* */ +/* Issues : */ +/* */ +/* Revision History: */ +/* */ +/* DD MM YYYY Author(s) Changes */ +/* 07 09 2012 100189 Initial Version */ +/* */ +/*****************************************************************************/ + +IV_API_CALL_STATUS_T disable_skippb_frames(void *codec_obj, + vid_dec_ctx_t *ps_app_ctx) +{ + ivd_ctl_set_config_ip_t s_ctl_ip; + ivd_ctl_set_config_op_t s_ctl_op; + IV_API_CALL_STATUS_T e_dec_status; + + s_ctl_ip.u4_disp_wd = ps_app_ctx->u4_strd; + s_ctl_ip.e_frm_skip_mode = IVD_SKIP_NONE; + + s_ctl_ip.e_frm_out_mode = IVD_DISPLAY_FRAME_OUT; + s_ctl_ip.e_vid_dec_mode = IVD_DECODE_FRAME; + s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL; + s_ctl_ip.e_sub_cmd = IVD_CMD_CTL_SETPARAMS; + s_ctl_ip.u4_size = sizeof(ivd_ctl_set_config_ip_t); + s_ctl_op.u4_size = sizeof(ivd_ctl_set_config_op_t); + + e_dec_status = ivd_api_function((iv_obj_t *)codec_obj, (void *)&s_ctl_ip, + (void *)&s_ctl_op); + if(IV_SUCCESS != e_dec_status) + { + printf("Error in Disable SkipPB frames\n"); + } + + return e_dec_status; +} + +/*****************************************************************************/ +/* */ +/* Function Name : release_disp_frame */ +/* */ +/* Description : Calls release display control - Used to signal to the */ +/* decoder that this particular buffer has been displayed */ +/* and that the codec is now free to write to this buffer */ +/* */ +/* */ +/* Inputs : codec_obj : Codec Handle */ +/* buf_id : Buffer Id of the buffer to be released */ +/* This id would have been returned earlier by */ +/* the codec */ +/* Globals : */ +/* Processing : Calls Release Display call */ +/* */ +/* Outputs : */ +/* Returns : Status of release display call */ +/* */ +/* Issues : */ +/* */ +/* Revision History: */ +/* */ +/* DD MM YYYY Author(s) Changes */ +/* 07 09 2012 100189 Initial Version */ +/* */ +/*****************************************************************************/ + +IV_API_CALL_STATUS_T release_disp_frame(void *codec_obj, UWORD32 buf_id) +{ + ivd_rel_display_frame_ip_t s_video_rel_disp_ip; + ivd_rel_display_frame_op_t s_video_rel_disp_op; + IV_API_CALL_STATUS_T e_dec_status; + + s_video_rel_disp_ip.e_cmd = IVD_CMD_REL_DISPLAY_FRAME; + s_video_rel_disp_ip.u4_size = sizeof(ivd_rel_display_frame_ip_t); + s_video_rel_disp_op.u4_size = sizeof(ivd_rel_display_frame_op_t); + s_video_rel_disp_ip.u4_disp_buf_id = buf_id; + + e_dec_status = ivd_api_function((iv_obj_t *)codec_obj, (void *)&s_video_rel_disp_ip, + (void *)&s_video_rel_disp_op); + if(IV_SUCCESS != e_dec_status) + { + printf("Error in Release Disp frame\n"); + } + + + return (e_dec_status); +} + +/*****************************************************************************/ +/* */ +/* Function Name : get_version */ +/* */ +/* Description : Control call to get codec version */ +/* */ +/* */ +/* Inputs : codec_obj : Codec handle */ +/* Globals : */ +/* Processing : Calls enable skip B frames control */ +/* */ +/* Outputs : */ +/* Returns : Control call return status */ +/* */ +/* Issues : */ +/* */ +/* Revision History: */ +/* */ +/* DD MM YYYY Author(s) Changes */ +/* 07 09 2012 100189 Initial Version */ +/* */ +/*****************************************************************************/ + +IV_API_CALL_STATUS_T get_version(void *codec_obj) +{ + ivd_ctl_getversioninfo_ip_t s_ctl_dec_ip; + ivd_ctl_getversioninfo_op_t s_ctl_dec_op; + UWORD8 au1_buf[512]; + IV_API_CALL_STATUS_T status; + s_ctl_dec_ip.e_cmd = IVD_CMD_VIDEO_CTL; + s_ctl_dec_ip.e_sub_cmd = IVD_CMD_CTL_GETVERSION; + s_ctl_dec_ip.u4_size = sizeof(ivd_ctl_getversioninfo_ip_t); + s_ctl_dec_op.u4_size = sizeof(ivd_ctl_getversioninfo_op_t); + s_ctl_dec_ip.pv_version_buffer = au1_buf; + s_ctl_dec_ip.u4_version_buffer_size = sizeof(au1_buf); + + status = ivd_api_function((iv_obj_t *)codec_obj, + (void *)&(s_ctl_dec_ip), + (void *)&(s_ctl_dec_op)); + + if(status != IV_SUCCESS) + { + printf("Error in Getting Version number e_dec_status = %d u4_error_code = %x\n", + status, s_ctl_dec_op.u4_error_code); + } + else + { + printf("Ittiam Decoder Version number: %s\n", + (char *)s_ctl_dec_ip.pv_version_buffer); + } + return status; +} +/*****************************************************************************/ +/* */ +/* Function Name : codec_exit */ +/* */ +/* Description : handles unrecoverable errors */ +/* Inputs : Error message */ +/* Globals : None */ +/* Processing : Prints error message to console and exits. */ +/* Outputs : Error mesage to the console */ +/* Returns : None */ +/* */ +/* Issues : */ +/* */ +/* Revision History: */ +/* */ +/* DD MM YYYY Author(s) Changes (Describe the changes made) */ +/* 07 06 2006 Sankar Creation */ +/* */ +/*****************************************************************************/ +void codec_exit(CHAR *pc_err_message) +{ + printf("%s\n", pc_err_message); + exit(-1); +} + +/*****************************************************************************/ +/* */ +/* Function Name : dump_output */ +/* */ +/* Description : Used to dump output YUV */ +/* Inputs : App context, disp output desc, File pointer */ +/* Globals : None */ +/* Processing : Dumps to a file */ +/* Returns : None */ +/* */ +/* Issues : */ +/* */ +/* Revision History: */ +/* */ +/* DD MM YYYY Author(s) Changes (Describe the changes made) */ +/* 07 06 2006 Sankar Creation */ +/* */ +/*****************************************************************************/ +void dump_output(vid_dec_ctx_t *ps_app_ctx, + iv_yuv_buf_t *ps_disp_frm_buf, + UWORD32 u4_disp_frm_id, + FILE *ps_op_file, + FILE *ps_op_chksum_file, + WORD32 i4_op_frm_ts, + UWORD32 file_save, + UWORD32 chksum_save) + +{ + + UWORD32 i; + iv_yuv_buf_t s_dump_disp_frm_buf; + UWORD32 u4_disp_id; + + memset(&s_dump_disp_frm_buf, 0, sizeof(iv_yuv_buf_t)); + + if(ps_app_ctx->share_disp_buf) + { + if(ps_app_ctx->dump_q_wr_idx == MAX_DISP_BUFFERS + ) + ps_app_ctx->dump_q_wr_idx = 0; + + if(ps_app_ctx->dump_q_rd_idx == MAX_DISP_BUFFERS + ) + ps_app_ctx->dump_q_rd_idx = 0; + + ps_app_ctx->s_disp_frm_queue[ps_app_ctx->dump_q_wr_idx] = + *ps_disp_frm_buf; + ps_app_ctx->s_disp_frm_id_queue[ps_app_ctx->dump_q_wr_idx] = + u4_disp_frm_id; + ps_app_ctx->dump_q_wr_idx++; + + if((WORD32)i4_op_frm_ts >= (WORD32)(ps_app_ctx->disp_delay - 1)) + { + s_dump_disp_frm_buf = + ps_app_ctx->s_disp_frm_queue[ps_app_ctx->dump_q_rd_idx]; + u4_disp_id = + ps_app_ctx->s_disp_frm_id_queue[ps_app_ctx->dump_q_rd_idx]; + ps_app_ctx->dump_q_rd_idx++; + } + else + { + return; + } + } + else + { + s_dump_disp_frm_buf = *ps_disp_frm_buf; + u4_disp_id = u4_disp_frm_id; + } + if(1 == ps_app_ctx->share_disp_buf) + release_disp_frame(ps_app_ctx->cocodec_obj, u4_disp_id); + + if(0 == file_save && 0 == chksum_save) + return; + + if(NULL == s_dump_disp_frm_buf.pv_y_buf) + return; + + if(ps_app_ctx->e_output_chroma_format == IV_YUV_420P) + { +#if DUMP_SINGLE_BUF + { + UWORD8 *buf = s_dump_disp_frm_buf.pv_y_buf - 24 - (s_dump_disp_frm_buf.u4_y_strd * 40); + + UWORD32 size = s_dump_disp_frm_buf.u4_y_strd * ((s_dump_disp_frm_buf.u4_y_ht + 80) + (s_dump_disp_frm_buf.u4_u_ht + 40)); + fwrite(buf, 1, size, ps_op_file); + + } +#else + if(0 != file_save) + { + UWORD8 *buf; + + buf = (UWORD8 *)s_dump_disp_frm_buf.pv_y_buf; + for(i = 0; i < s_dump_disp_frm_buf.u4_y_ht; i++) + { + fwrite(buf, 1, s_dump_disp_frm_buf.u4_y_wd, ps_op_file); + buf += s_dump_disp_frm_buf.u4_y_strd; + } + + buf = (UWORD8 *)s_dump_disp_frm_buf.pv_u_buf; + for(i = 0; i < s_dump_disp_frm_buf.u4_u_ht; i++) + { + fwrite(buf, 1, s_dump_disp_frm_buf.u4_u_wd, ps_op_file); + buf += s_dump_disp_frm_buf.u4_u_strd; + } + buf = (UWORD8 *)s_dump_disp_frm_buf.pv_v_buf; + for(i = 0; i < s_dump_disp_frm_buf.u4_v_ht; i++) + { + fwrite(buf, 1, s_dump_disp_frm_buf.u4_v_wd, ps_op_file); + buf += s_dump_disp_frm_buf.u4_v_strd; + } + + } + + if(0 != chksum_save) + { + UWORD8 au1_y_chksum[16]; + UWORD8 au1_u_chksum[16]; + UWORD8 au1_v_chksum[16]; + calc_md5_cksum((UWORD8 *)s_dump_disp_frm_buf.pv_y_buf, + s_dump_disp_frm_buf.u4_y_strd, + s_dump_disp_frm_buf.u4_y_wd, + s_dump_disp_frm_buf.u4_y_ht, + au1_y_chksum); + calc_md5_cksum((UWORD8 *)s_dump_disp_frm_buf.pv_u_buf, + s_dump_disp_frm_buf.u4_u_strd, + s_dump_disp_frm_buf.u4_u_wd, + s_dump_disp_frm_buf.u4_u_ht, + au1_u_chksum); + calc_md5_cksum((UWORD8 *)s_dump_disp_frm_buf.pv_v_buf, + s_dump_disp_frm_buf.u4_v_strd, + s_dump_disp_frm_buf.u4_v_wd, + s_dump_disp_frm_buf.u4_v_ht, + au1_v_chksum); + + fwrite(au1_y_chksum, sizeof(UWORD8), 16, ps_op_chksum_file); + fwrite(au1_u_chksum, sizeof(UWORD8), 16, ps_op_chksum_file); + fwrite(au1_v_chksum, sizeof(UWORD8), 16, ps_op_chksum_file); + } +#endif + } + else if((ps_app_ctx->e_output_chroma_format == IV_YUV_420SP_UV) + || (ps_app_ctx->e_output_chroma_format == IV_YUV_420SP_VU)) + { +#if DUMP_SINGLE_BUF + { + + UWORD8 *buf = s_dump_disp_frm_buf.pv_y_buf - 24 - (s_dump_disp_frm_buf.u4_y_strd * 40); + + UWORD32 size = s_dump_disp_frm_buf.u4_y_strd * ((s_dump_disp_frm_buf.u4_y_ht + 80) + (s_dump_disp_frm_buf.u4_u_ht + 40)); + fwrite(buf, 1, size, ps_op_file); + } +#else + { + UWORD8 *buf; + + buf = (UWORD8 *)s_dump_disp_frm_buf.pv_y_buf; + for(i = 0; i < s_dump_disp_frm_buf.u4_y_ht; i++) + { + fwrite(buf, 1, s_dump_disp_frm_buf.u4_y_wd, ps_op_file); + buf += s_dump_disp_frm_buf.u4_y_strd; + } + + buf = (UWORD8 *)s_dump_disp_frm_buf.pv_u_buf; + for(i = 0; i < s_dump_disp_frm_buf.u4_u_ht; i++) + { + fwrite(buf, 1, s_dump_disp_frm_buf.u4_u_wd, ps_op_file); + buf += s_dump_disp_frm_buf.u4_u_strd; + } + } +#endif + } + else if(ps_app_ctx->e_output_chroma_format == IV_RGBA_8888) + { + UWORD8 *buf; + + buf = (UWORD8 *)s_dump_disp_frm_buf.pv_y_buf; + for(i = 0; i < s_dump_disp_frm_buf.u4_y_ht; i++) + { + fwrite(buf, 1, s_dump_disp_frm_buf.u4_y_wd * 4, ps_op_file); + buf += s_dump_disp_frm_buf.u4_y_strd * 4; + } + } + else + { + UWORD8 *buf; + + buf = (UWORD8 *)s_dump_disp_frm_buf.pv_y_buf; + for(i = 0; i < s_dump_disp_frm_buf.u4_y_ht; i++) + { + fwrite(buf, 1, s_dump_disp_frm_buf.u4_y_strd * 2, ps_op_file); + buf += s_dump_disp_frm_buf.u4_y_strd * 2; + } + } + + fflush(ps_op_file); + fflush(ps_op_chksum_file); + +} + + +/*****************************************************************************/ +/* */ +/* Function Name : print_usage */ +/* */ +/* Description : Prints argument format */ +/* */ +/* */ +/* Inputs : */ +/* Globals : */ +/* Processing : Prints argument format */ +/* */ +/* Outputs : */ +/* Returns : */ +/* */ +/* Issues : */ +/* */ +/* Revision History: */ +/* */ +/* DD MM YYYY Author(s) Changes */ +/* 07 09 2012 100189 Initial Version */ +/* */ +/*****************************************************************************/ + +void print_usage(void) +{ + WORD32 i = 0; + WORD32 num_entries = sizeof(argument_mapping) / sizeof(argument_t); + printf("\nUsage:\n"); + while(i < num_entries) + { + printf("%-32s\t %s", argument_mapping[i].argument_name, + argument_mapping[i].description); + i++; + } +} + +/*****************************************************************************/ +/* */ +/* Function Name : get_argument */ +/* */ +/* Description : Gets argument for a given string */ +/* */ +/* */ +/* Inputs : name */ +/* Globals : */ +/* Processing : Searches the given string in the array and returns */ +/* appropriate argument ID */ +/* */ +/* Outputs : Argument ID */ +/* Returns : Argument ID */ +/* */ +/* Issues : */ +/* */ +/* Revision History: */ +/* */ +/* DD MM YYYY Author(s) Changes */ +/* 07 09 2012 100189 Initial Version */ +/* */ +/*****************************************************************************/ + +ARGUMENT_T get_argument(CHAR *name) +{ + WORD32 i = 0; + WORD32 num_entries = sizeof(argument_mapping) / sizeof(argument_t); + while(i < num_entries) + { + if((0 == strcmp(argument_mapping[i].argument_name, name)) || + ((0 == strcmp(argument_mapping[i].argument_shortname, name)) && + (0 != strcmp(argument_mapping[i].argument_shortname, "--")))) + { + return argument_mapping[i].argument; + } + i++; + } + return INVALID; +} + +/*****************************************************************************/ +/* */ +/* Function Name : get_argument */ +/* */ +/* Description : Gets argument for a given string */ +/* */ +/* */ +/* Inputs : name */ +/* Globals : */ +/* Processing : Searches the given string in the array and returns */ +/* appropriate argument ID */ +/* */ +/* Outputs : Argument ID */ +/* Returns : Argument ID */ +/* */ +/* Issues : */ +/* */ +/* Revision History: */ +/* */ +/* DD MM YYYY Author(s) Changes */ +/* 07 09 2012 100189 Initial Version */ +/* */ +/*****************************************************************************/ + +void parse_argument(vid_dec_ctx_t *ps_app_ctx, CHAR *argument, CHAR *value) +{ + ARGUMENT_T arg; + + arg = get_argument(argument); + switch(arg) + { + case HELP: + print_usage(); + exit(-1); + case VERSION: + break; + case INPUT_FILE: + sscanf(value, "%s", ps_app_ctx->ac_ip_fname); + //input_passed = 1; + break; + + case OUTPUT: + sscanf(value, "%s", ps_app_ctx->ac_op_fname); + break; + + case CHKSUM: + sscanf(value, "%s", ps_app_ctx->ac_op_chksum_fname); + break; + + case SAVE_OUTPUT: + sscanf(value, "%d", &ps_app_ctx->u4_file_save_flag); + break; + + case SAVE_CHKSUM: + sscanf(value, "%d", &ps_app_ctx->u4_chksum_save_flag); + break; + + case CHROMA_FORMAT: + if((strcmp(value, "YUV_420P")) == 0) + ps_app_ctx->e_output_chroma_format = IV_YUV_420P; + else if((strcmp(value, "YUV_422ILE")) == 0) + ps_app_ctx->e_output_chroma_format = IV_YUV_422ILE; + else if((strcmp(value, "RGB_565")) == 0) + ps_app_ctx->e_output_chroma_format = IV_RGB_565; + else if((strcmp(value, "RGBA_8888")) == 0) + ps_app_ctx->e_output_chroma_format = IV_RGBA_8888; + else if((strcmp(value, "YUV_420SP_UV")) == 0) + ps_app_ctx->e_output_chroma_format = IV_YUV_420SP_UV; + else if((strcmp(value, "YUV_420SP_VU")) == 0) + ps_app_ctx->e_output_chroma_format = IV_YUV_420SP_VU; + else + { + printf("\nInvalid colour format setting it to IV_YUV_420P\n"); + ps_app_ctx->e_output_chroma_format = IV_YUV_420P; + } + + break; + case NUM_FRAMES: + sscanf(value, "%d", &ps_app_ctx->u4_max_frm_ts); + break; + + case NUM_CORES: + sscanf(value, "%d", &ps_app_ctx->u4_num_cores); + break; + case DEGRADE_PICS: + sscanf(value, "%d", &ps_app_ctx->i4_degrade_pics); + ps_app_ctx->i4_degrade_pics = 0; + printf("degrade_pics is not supported. Setting it to zero"); + break; + case DEGRADE_TYPE: + sscanf(value, "%d", &ps_app_ctx->i4_degrade_type); + break; + case SHARE_DISPLAY_BUF: + sscanf(value, "%d", &ps_app_ctx->share_disp_buf); + break; + case LOOPBACK: + sscanf(value, "%d", &ps_app_ctx->loopback); + break; + case DISPLAY: +#if defined(SDL_DISPLAY) || defined(FBDEV_DISPLAY) || defined(INTEL_CE5300) || defined(IOS_DISPLAY) + sscanf(value, "%d", &ps_app_ctx->display); +#else + ps_app_ctx->display = 0; +#endif + break; + case FULLSCREEN: + sscanf(value, "%d", &ps_app_ctx->full_screen); + break; + case FPS: + sscanf(value, "%d", &ps_app_ctx->fps); + if(ps_app_ctx->fps <= 0) + ps_app_ctx->fps = DEFAULT_FPS; + break; + case MAX_WD: + sscanf(value, "%d", &ps_app_ctx->max_wd); + break; + case MAX_HT: + sscanf(value, "%d", &ps_app_ctx->max_ht); + break; + case MAX_LEVEL: + sscanf(value, "%d", &ps_app_ctx->max_level); + break; + case ARCH: + if((strcmp(value, "ARM_NONEON")) == 0) + ps_app_ctx->e_arch = ARCH_ARM_NONEON; + else if((strcmp(value, "ARM_A9Q")) == 0) + ps_app_ctx->e_arch = ARCH_ARM_A9Q; + else if((strcmp(value, "ARM_V8")) == 0) + ps_app_ctx->e_arch = ARCH_ARMV8_GENERIC; + else if((strcmp(value, "ARM_A7")) == 0) + ps_app_ctx->e_arch = ARCH_ARM_A7; + else if((strcmp(value, "ARM_A5")) == 0) + ps_app_ctx->e_arch = ARCH_ARM_A5; + else if((strcmp(value, "ARM_NEONINTR")) == 0) + ps_app_ctx->e_arch = ARCH_ARM_NEONINTR; + else if((strcmp(value, "X86_GENERIC")) == 0) + ps_app_ctx->e_arch = ARCH_X86_GENERIC; + else if((strcmp(value, "X86_SSSE3")) == 0) + ps_app_ctx->e_arch = ARCH_X86_SSSE3; + else if((strcmp(value, "X86_SSE42")) == 0) + ps_app_ctx->e_arch = ARCH_X86_SSE42; + else if((strcmp(value, "X86_AVX2")) == 0) + ps_app_ctx->e_arch = ARCH_X86_AVX2; + else if((strcmp(value, "MIPS_GENERIC")) == 0) + ps_app_ctx->e_arch = ARCH_MIPS_GENERIC; + else if((strcmp(value, "MIPS_32")) == 0) + ps_app_ctx->e_arch = ARCH_MIPS_32; + else + { + printf("\nInvalid Arch. Setting it to ARM_A9Q\n"); + ps_app_ctx->e_arch = ARCH_ARM_A9Q; + } + + break; + case SOC: + if((strcmp(value, "GENERIC")) == 0) + ps_app_ctx->e_soc = SOC_GENERIC; + else if((strcmp(value, "HISI_37X")) == 0) + ps_app_ctx->e_soc = SOC_HISI_37X; + else + { + ps_app_ctx->e_soc = atoi(value); +/* + printf("\nInvalid SOC. Setting it to GENERIC\n"); + ps_app_ctx->e_soc = SOC_GENERIC; +*/ + } + break; + case PICLEN: + sscanf(value, "%d", &ps_app_ctx->u4_piclen_flag); + break; + + case PICLEN_FILE: + sscanf(value, "%s", ps_app_ctx->ac_piclen_fname); + break; + + case INVALID: + default: + printf("Ignoring argument : %s\n", argument); + break; + } +} + +/*****************************************************************************/ +/* */ +/* Function Name : read_cfg_file */ +/* */ +/* Description : Reads arguments from a configuration file */ +/* */ +/* */ +/* Inputs : ps_app_ctx : Application context */ +/* fp_cfg_file : Configuration file handle */ +/* Globals : */ +/* Processing : Parses the arguments and fills in the application context*/ +/* */ +/* Outputs : Arguments parsed */ +/* Returns : None */ +/* */ +/* Issues : */ +/* */ +/* Revision History: */ +/* */ +/* DD MM YYYY Author(s) Changes */ +/* 07 09 2012 100189 Initial Version */ +/* */ +/*****************************************************************************/ + +void read_cfg_file(vid_dec_ctx_t *ps_app_ctx, FILE *fp_cfg_file) +{ + + CHAR line[STRLENGTH]; + CHAR description[STRLENGTH]; + CHAR value[STRLENGTH]; + CHAR argument[STRLENGTH]; + void *ret; + while(0 == feof(fp_cfg_file)) + { + line[0] = '\0'; + ret = fgets(line, STRLENGTH, fp_cfg_file); + if(NULL == ret) + break; + argument[0] = '\0'; + /* Reading Input File Name */ + sscanf(line, "%s %s %s", argument, value, description); + if(argument[0] == '\0') + continue; + + parse_argument(ps_app_ctx, argument, value); + } + + +} + +/*! +************************************************************************** +* \if Function name : dispq_producer_dequeue \endif +* +* \brief +* This function gets a free buffer index where display data can be written +* This is a blocking call and can be exited by setting quit to true in +* the application context +* +* \param[in] ps_app_ctx : Pointer to application context +* +* \return +* returns Next free buffer index for producer +* +* \author +* Ittiam +* +************************************************************************** +*/ +WORD32 dispq_producer_dequeue(vid_dec_ctx_t *ps_app_ctx) +{ + WORD32 idx; + + /* If there is no free buffer wait */ + + while(((ps_app_ctx->disp_q_wr_idx + 1) % NUM_DISPLAY_BUFFERS) == ps_app_ctx->disp_q_rd_idx) + { + + ithread_msleep(1); + + if(ps_app_ctx->quit) + return (-1); + } + + idx = ps_app_ctx->disp_q_wr_idx; + return (idx); +} + +/*! +************************************************************************** +* \if Function name : dispq_producer_queue \endif +* +* \brief +* This function adds buffer which can be displayed +* +* \param[in] ps_app_ctx : Pointer to application context +* +* \return +* returns Next free buffer index for producer +* +* \author +* Ittiam +* +************************************************************************** +*/ +WORD32 dispq_producer_queue(vid_dec_ctx_t *ps_app_ctx) +{ + ps_app_ctx->disp_q_wr_idx++; + if(ps_app_ctx->disp_q_wr_idx == NUM_DISPLAY_BUFFERS) + ps_app_ctx->disp_q_wr_idx = 0; + + return (0); +} +/*! +************************************************************************** +* \if Function name : dispq_consumer_dequeue \endif +* +* \brief +* This function gets a free buffer index where display data can be written +* This is a blocking call and can be exited by setting quit to true in +* the application context +* +* \param[in] ps_app_ctx : Pointer to application context +* +* \return +* returns Next free buffer index for producer +* +* \author +* Ittiam +* +************************************************************************** +*/ +WORD32 dispq_consumer_dequeue(vid_dec_ctx_t *ps_app_ctx) +{ + WORD32 idx; + + /* If there is no free buffer wait */ + + while(ps_app_ctx->disp_q_wr_idx == ps_app_ctx->disp_q_rd_idx) + { + + ithread_msleep(1); + + if(ps_app_ctx->quit) + return (-1); + } + + idx = ps_app_ctx->disp_q_rd_idx; + return (idx); +} + +/*! +************************************************************************** +* \if Function name : dispq_producer_queue \endif +* +* \brief +* This function adds buffer which can be displayed +* +* \param[in] ps_app_ctx : Pointer to application context +* +* \return +* returns Next free buffer index for producer +* +* \author +* Ittiam +* +************************************************************************** +*/ +WORD32 dispq_consumer_queue(vid_dec_ctx_t *ps_app_ctx) +{ + ps_app_ctx->disp_q_rd_idx++; + if(ps_app_ctx->disp_q_rd_idx == NUM_DISPLAY_BUFFERS) + ps_app_ctx->disp_q_rd_idx = 0; + + return (0); +} + +/*****************************************************************************/ +/* */ +/* Function Name : display_thread */ +/* */ +/* Description : Thread to display the frame */ +/* */ +/* */ +/* Inputs : pv_ctx : Application context */ +/* */ +/* Globals : */ +/* Processing : Wait for a buffer to get produced by decoder and display */ +/* that frame */ +/* */ +/* Outputs : */ +/* Returns : None */ +/* */ +/* Issues : Pause followed by quit is making some deadlock condn */ +/* If decoder was lagging initially and then fasten up, */ +/* display will also go at faster rate till it reaches */ +/* equilibrium wrt the initial time */ +/* */ +/* Revision History: */ +/* */ +/* DD MM YYYY Author(s) Changes */ +/* 07 05 2013 100578 Initial Version */ +/* */ +/*****************************************************************************/ + +WORD32 display_thread(void *pv_ctx) +{ + vid_dec_ctx_t *ps_app_ctx = (vid_dec_ctx_t *)pv_ctx; + + + UWORD32 frm_duration; /* in us */ + UWORD32 current_time; + UWORD32 expected_time; + TIMER s_end_timer; + TIMER s_first_frame_time; + UWORD32 first_frame_displayed; + +#ifdef WINDOWS_TIMER + TIMER frequency; +#endif + + +#ifdef WINDOWS_TIMER + QueryPerformanceFrequency(&frequency); +#endif + first_frame_displayed = 0; + expected_time = 0; + frm_duration = 1000000 / ps_app_ctx->fps; + + /* Init display and allocate display buffers */ + ps_app_ctx->pv_disp_ctx = (void *)ps_app_ctx->disp_init(ps_app_ctx->u4_pic_wd, + ps_app_ctx->u4_pic_ht, + ps_app_ctx->i4_screen_wd, + ps_app_ctx->i4_screen_ht, + ps_app_ctx->max_wd, + ps_app_ctx->max_ht, + ps_app_ctx->full_screen, + &ps_app_ctx->quit, + &ps_app_ctx->paused); + ps_app_ctx->alloc_disp_buffers(ps_app_ctx->pv_disp_ctx); + + ps_app_ctx->display_init_done = 1; + + while(1) + { + WORD32 rd_idx; + + rd_idx = dispq_consumer_dequeue(ps_app_ctx); + if(ps_app_ctx->quit) + break; + + ps_app_ctx->display_buffer(ps_app_ctx->pv_disp_ctx, rd_idx); + + if(0 == first_frame_displayed) + { + GETTIME(&s_first_frame_time); + first_frame_displayed = 1; + } + + /*********************************************************************/ + /* Sleep based on the expected time of arrival of current buffer and */ + /* the Current frame */ + /*********************************************************************/ + + GETTIME(&s_end_timer); + ELAPSEDTIME(s_first_frame_time, s_end_timer, current_time, frequency); + + /* time in micro second */ + expected_time += frm_duration; + + //printf("current_time %d expected_time %d diff %d \n", current_time, expected_time, (expected_time - current_time)); + /* sleep for the diff. in time */ + if(current_time < expected_time) + ps_app_ctx->disp_usleep((expected_time - current_time)); + else + expected_time += (current_time - expected_time); + + dispq_consumer_queue(ps_app_ctx); + + } + + + while(0 == ps_app_ctx->display_deinit_flag) + { + ps_app_ctx->disp_usleep(1000); + } + ps_app_ctx->disp_deinit(ps_app_ctx->pv_disp_ctx); + + /* destroy the display thread */ + ithread_exit(ps_app_ctx->display_thread_handle); + + return 0; +} + +void flush_output(iv_obj_t *codec_obj, + vid_dec_ctx_t *ps_app_ctx, + ivd_out_bufdesc_t *ps_out_buf, + UWORD8 *pu1_bs_buf, + UWORD32 *pu4_op_frm_ts, + FILE *ps_op_file, + FILE *ps_op_chksum_file, + UWORD32 u4_ip_frm_ts, + UWORD32 u4_bytes_remaining) +{ + WORD32 ret; + + do + { + + ivd_ctl_flush_ip_t s_ctl_ip; + ivd_ctl_flush_op_t s_ctl_op; + + if(*pu4_op_frm_ts >= (ps_app_ctx->u4_max_frm_ts + ps_app_ctx->disp_delay)) + break; + + s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL; + s_ctl_ip.e_sub_cmd = IVD_CMD_CTL_FLUSH; + s_ctl_ip.u4_size = sizeof(ivd_ctl_flush_ip_t); + s_ctl_op.u4_size = sizeof(ivd_ctl_flush_op_t); + ret = ivd_api_function((iv_obj_t *)codec_obj, (void *)&s_ctl_ip, + (void *)&s_ctl_op); + + if(ret != IV_SUCCESS) + { + printf("Error in Setting the decoder in flush mode\n"); + } + + if(IV_SUCCESS == ret) + { + ivd_video_decode_ip_t s_video_decode_ip; + ivd_video_decode_op_t s_video_decode_op; + + s_video_decode_ip.e_cmd = IVD_CMD_VIDEO_DECODE; + s_video_decode_ip.u4_ts = u4_ip_frm_ts; + s_video_decode_ip.pv_stream_buffer = pu1_bs_buf; + s_video_decode_ip.u4_num_Bytes = u4_bytes_remaining; + s_video_decode_ip.u4_size = sizeof(ivd_video_decode_ip_t); + s_video_decode_ip.s_out_buffer.u4_min_out_buf_size[0] = + ps_out_buf->u4_min_out_buf_size[0]; + s_video_decode_ip.s_out_buffer.u4_min_out_buf_size[1] = + ps_out_buf->u4_min_out_buf_size[1]; + s_video_decode_ip.s_out_buffer.u4_min_out_buf_size[2] = + ps_out_buf->u4_min_out_buf_size[2]; + + s_video_decode_ip.s_out_buffer.pu1_bufs[0] = + ps_out_buf->pu1_bufs[0]; + s_video_decode_ip.s_out_buffer.pu1_bufs[1] = + ps_out_buf->pu1_bufs[1]; + s_video_decode_ip.s_out_buffer.pu1_bufs[2] = + ps_out_buf->pu1_bufs[2]; + s_video_decode_ip.s_out_buffer.u4_num_bufs = + ps_out_buf->u4_num_bufs; + + s_video_decode_op.u4_size = sizeof(ivd_video_decode_op_t); + + /*****************************************************************************/ + /* API Call: Video Decode */ + /*****************************************************************************/ + ret = ivd_api_function((iv_obj_t *)codec_obj, (void *)&s_video_decode_ip, + (void *)&s_video_decode_op); + + if(1 == s_video_decode_op.u4_output_present) + { + dump_output(ps_app_ctx, &(s_video_decode_op.s_disp_frm_buf), + s_video_decode_op.u4_disp_buf_id, ps_op_file, + ps_op_chksum_file, + *pu4_op_frm_ts, ps_app_ctx->u4_file_save_flag, + ps_app_ctx->u4_chksum_save_flag); + + (*pu4_op_frm_ts)++; + } + } + }while(IV_SUCCESS == ret); + +} + +#ifdef X86_MINGW +void sigsegv_handler() +{ + printf("Segmentation fault, Exiting.. \n"); + exit(-1); +} +#endif + +UWORD32 default_get_stride(void) +{ + return 0; +} + + +IV_COLOR_FORMAT_T default_get_color_fmt(void) +{ + return IV_YUV_420P; +} +/*****************************************************************************/ +/* */ +/* Function Name : main */ +/* */ +/* Description : Application to demonstrate codec API */ +/* */ +/* */ +/* Inputs : argc - Number of arguments */ +/* argv[] - Arguments */ +/* Globals : */ +/* Processing : Shows how to use create, process, control and delete */ +/* */ +/* Outputs : Codec output in a file */ +/* Returns : */ +/* */ +/* Issues : Assumes both PROFILE_ENABLE to be */ +/* defined for multithread decode-display working */ +/* */ +/* Revision History: */ +/* */ +/* DD MM YYYY Author(s) Changes */ +/* 07 09 2012 100189 Initial Version */ +/* 09 05 2013 100578 Multithread decode-display */ +/*****************************************************************************/ +#ifdef IOS +int vdec_main(char *homedir, char *documentdir, int screen_wd, int screen_ht) +#else +int main(WORD32 argc, CHAR *argv[]) +#endif +{ + CHAR ac_cfg_fname[STRLENGTH]; + FILE *fp_cfg_file = NULL; + FILE *ps_piclen_file = NULL; + FILE *ps_ip_file = NULL; + FILE *ps_op_file = NULL; + FILE *ps_op_chksum_file = NULL; + WORD32 ret; + CHAR ac_error_str[STRLENGTH]; + vid_dec_ctx_t s_app_ctx; + UWORD8 *pu1_bs_buf; + + ivd_out_bufdesc_t *ps_out_buf; + UWORD32 u4_num_bytes_dec = 0; + UWORD32 file_pos = 0; + IV_API_CALL_STATUS_T e_dec_status; + UWORD32 u4_ip_frm_ts = 0, u4_op_frm_ts = 0; + + WORD32 u4_bytes_remaining = 0; + void *pv_mem_rec_location; + UWORD32 u4_num_mem_recs; + UWORD32 i; + UWORD32 u4_ip_buf_len; + UWORD32 frm_cnt = 0; + WORD32 total_bytes_comsumed; + +#ifdef PROFILE_ENABLE + UWORD32 u4_tot_cycles = 0; + UWORD32 u4_tot_fmt_cycles = 0; + UWORD32 peak_window[PEAK_WINDOW_SIZE]; + UWORD32 peak_window_idx = 0; + UWORD32 peak_avg_max = 0; +#ifdef INTEL_CE5300 + UWORD32 time_consumed = 0; + UWORD32 bytes_consumed = 0; +#endif +#endif +#ifdef WINDOWS_TIMER + TIMER frequency; +#endif + WORD32 width = 0, height = 0; + iv_obj_t *codec_obj; +#if defined(GPU_BUILD) && !defined(X86) +// int ioctl_init(); +// ioctl_init(); +#endif + +#ifdef X86_MINGW + //For getting printfs without any delay + setvbuf(stdout, NULL, _IONBF, 0); + setvbuf(stderr, NULL, _IONBF, 0); +#endif +#ifdef IOS + sprintf(filename_trace, "%s/iostrace.txt", homedir); + printf("\ntrace file name = %s", filename_trace); +#endif + +#ifdef X86_MINGW + { + signal(SIGSEGV, sigsegv_handler); + } +#endif + + +#ifndef IOS + /* Usage */ + if(argc < 2) + { + printf("Using test.cfg as configuration file \n"); + strcpy(ac_cfg_fname, "test.cfg"); + } + else if(argc == 2) + { + strcpy(ac_cfg_fname, argv[1]); + } + +#else + strcpy(ac_cfg_fname, "test.cfg"); + +#endif + + + /***********************************************************************/ + /* Initialize Application parameters */ + /***********************************************************************/ + + strcpy(s_app_ctx.ac_ip_fname, "\0"); + s_app_ctx.dump_q_wr_idx = 0; + s_app_ctx.dump_q_rd_idx = 0; + s_app_ctx.display_thread_created = 0; + s_app_ctx.disp_q_wr_idx = 0; + s_app_ctx.disp_q_rd_idx = 0; + s_app_ctx.disp_delay = 0; + s_app_ctx.loopback = 0; + s_app_ctx.display = 0; + s_app_ctx.full_screen = 0; + s_app_ctx.u4_piclen_flag = 0; + s_app_ctx.fps = DEFAULT_FPS; + file_pos = 0; + total_bytes_comsumed = 0; + u4_ip_frm_ts = 0; + u4_op_frm_ts = 0; +#ifdef PROFILE_ENABLE + memset(peak_window, 0, sizeof(WORD32) * PEAK_WINDOW_SIZE); +#endif + s_app_ctx.share_disp_buf = DEFAULT_SHARE_DISPLAY_BUF; + s_app_ctx.u4_num_cores = DEFAULT_NUM_CORES; + s_app_ctx.i4_degrade_type = 0; + s_app_ctx.i4_degrade_pics = 0; + s_app_ctx.max_wd = 0; + s_app_ctx.max_ht = 0; + s_app_ctx.max_level = 0; + s_app_ctx.e_arch = ARCH_ARM_A9Q; + s_app_ctx.e_soc = SOC_GENERIC; + + s_app_ctx.u4_strd = STRIDE; + + s_app_ctx.display_thread_handle = malloc(ithread_get_handle_size()); + s_app_ctx.quit = 0; + s_app_ctx.paused = 0; + //s_app_ctx.u4_output_present = 0; + + s_app_ctx.get_stride = &default_get_stride; + + s_app_ctx.get_color_fmt = &default_get_color_fmt; + + /* Set function pointers for display */ +#ifdef SDL_DISPLAY + s_app_ctx.disp_init = &sdl_disp_init; + s_app_ctx.alloc_disp_buffers = &sdl_alloc_disp_buffers; + s_app_ctx.display_buffer = &sdl_display; + s_app_ctx.set_disp_buffers = &sdl_set_disp_buffers; + s_app_ctx.disp_deinit = &sdl_disp_deinit; + s_app_ctx.disp_usleep = &sdl_disp_usleep; + s_app_ctx.get_color_fmt = &sdl_get_color_fmt; + s_app_ctx.get_stride = &sdl_get_stride; +#endif + +#ifdef FBDEV_DISPLAY + s_app_ctx.disp_init = &fbd_disp_init; + s_app_ctx.alloc_disp_buffers = &fbd_alloc_disp_buffers; + s_app_ctx.display_buffer = &fbd_display; + s_app_ctx.set_disp_buffers = &fbd_set_disp_buffers; + s_app_ctx.disp_deinit = &fbd_disp_deinit; + s_app_ctx.disp_usleep = &fbd_disp_usleep; + s_app_ctx.get_color_fmt = &fbd_get_color_fmt; + s_app_ctx.get_stride = &fbd_get_stride; +#endif + +#ifdef INTEL_CE5300 + s_app_ctx.disp_init = &gdl_disp_init; + s_app_ctx.alloc_disp_buffers = &gdl_alloc_disp_buffers; + s_app_ctx.display_buffer = &gdl_display; + s_app_ctx.set_disp_buffers = &gdl_set_disp_buffers; + s_app_ctx.disp_deinit = &gdl_disp_deinit; + s_app_ctx.disp_usleep = &gdl_disp_usleep; + s_app_ctx.get_color_fmt = &gdl_get_color_fmt; + s_app_ctx.get_stride = &gdl_get_stride; +#endif + +#ifdef IOS_DISPLAY + s_app_ctx.disp_init = &ios_disp_init; + s_app_ctx.alloc_disp_buffers = &ios_alloc_disp_buffers; + s_app_ctx.display_buffer = &ios_display; + s_app_ctx.set_disp_buffers = &ios_set_disp_buffers; + s_app_ctx.disp_deinit = &ios_disp_deinit; + s_app_ctx.disp_usleep = &ios_disp_usleep; + s_app_ctx.get_color_fmt = &ios_get_color_fmt; + s_app_ctx.get_stride = &ios_get_stride; +#endif + + s_app_ctx.display_deinit_flag = 0; + s_app_ctx.e_output_chroma_format = IV_YUV_420SP_UV; + /*************************************************************************/ + /* Parse arguments */ + /*************************************************************************/ + +#ifndef IOS + /* Read command line arguments */ + if(argc > 2) + { + for(i = 1; i < (UWORD32)argc; i += 2) + { + if(CONFIG == get_argument(argv[i])) + { + strcpy(ac_cfg_fname, argv[i + 1]); + if((fp_cfg_file = fopen(ac_cfg_fname, "r")) == NULL) + { + sprintf(ac_error_str, "Could not open Configuration file %s", + ac_cfg_fname); + codec_exit(ac_error_str); + } + read_cfg_file(&s_app_ctx, fp_cfg_file); + fclose(fp_cfg_file); + } + else + { + parse_argument(&s_app_ctx, argv[i], argv[i + 1]); + } + } + } + else + { + if((fp_cfg_file = fopen(ac_cfg_fname, "r")) == NULL) + { + sprintf(ac_error_str, "Could not open Configuration file %s", + ac_cfg_fname); + codec_exit(ac_error_str); + } + read_cfg_file(&s_app_ctx, fp_cfg_file); + fclose(fp_cfg_file); + } +#else + sprintf(filename_with_path, "%s/%s", homedir, ac_cfg_fname); + if((fp_cfg_file = fopen(filename_with_path, "r")) == NULL) + { + sprintf(ac_error_str, "Could not open Configuration file %s", + ac_cfg_fname); + codec_exit(ac_error_str); + + } + read_cfg_file(&s_app_ctx, fp_cfg_file); + fclose(fp_cfg_file); + +#endif +#ifdef PRINT_PICSIZE + /* If the binary is used for only getting number of bytes in each picture, then disable the following features */ + s_app_ctx.u4_piclen_flag = 0; + s_app_ctx.u4_file_save_flag = 0; + s_app_ctx.u4_chksum_save_flag = 0; + s_app_ctx.i4_degrade_pics = 0; + s_app_ctx.i4_degrade_type = 0; + s_app_ctx.loopback = 0; + s_app_ctx.share_disp_buf = 0; + s_app_ctx.display = 0; +#endif + + /* If display is enabled, then turn off shared mode and get color format that is supported by display */ + if(1 == s_app_ctx.display) + { + s_app_ctx.share_disp_buf = 0; + s_app_ctx.e_output_chroma_format = s_app_ctx.get_color_fmt(); + } + if(strcmp(s_app_ctx.ac_ip_fname, "\0") == 0) + { + printf("\nNo input file given for decoding\n"); + exit(-1); + } + + + /***********************************************************************/ + /* create the file object for input file */ + /***********************************************************************/ +#ifdef IOS + sprintf(filename_with_path, "%s/%s", homedir, s_app_ctx.ac_ip_fname); + ps_ip_file = fopen(filename_with_path, "rb"); +#else + ps_ip_file = fopen(s_app_ctx.ac_ip_fname, "rb"); +#endif + if(NULL == ps_ip_file) + { + sprintf(ac_error_str, "Could not open input file %s", + s_app_ctx.ac_ip_fname); + codec_exit(ac_error_str); + } + /***********************************************************************/ + /* create the file object for input file */ + /***********************************************************************/ + if(1 == s_app_ctx.u4_piclen_flag) + { +#ifdef IOS + sprintf(filename_with_path, "%s/%s", homedir, s_app_ctx.ac_piclen_fname); + ps_piclen_file = fopen(filename_with_path, "rb"); +#else + ps_piclen_file = fopen(s_app_ctx.ac_piclen_fname, "rb"); +#endif + if(NULL == ps_piclen_file) + { + sprintf(ac_error_str, "Could not open piclen file %s", + s_app_ctx.ac_piclen_fname); + codec_exit(ac_error_str); + } + } + + /***********************************************************************/ + /* create the file object for output file */ + /***********************************************************************/ + if(1 == s_app_ctx.u4_file_save_flag) + { +#ifdef IOS + sprintf(filename_with_path, "%s/%s", documentdir, s_app_ctx.ac_op_fname); + ps_op_file = fopen(filename_with_path, "wb"); +#else + ps_op_file = fopen(s_app_ctx.ac_op_fname, "wb"); +#endif + + if(NULL == ps_op_file) + { + sprintf(ac_error_str, "Could not open output file %s", + s_app_ctx.ac_op_fname); + codec_exit(ac_error_str); + } + } + + /***********************************************************************/ + /* create the file object for check sum file */ + /***********************************************************************/ + if(1 == s_app_ctx.u4_chksum_save_flag) + { +#if IOS + sprintf(filename_with_path, "%s/%s", documentdir, s_app_ctx.ac_op_chksum_fname); + ps_op_chksum_file = fopen(filename_with_path, "wb"); +#else + ps_op_chksum_file = fopen(s_app_ctx.ac_op_chksum_fname, "wb"); +#endif + if(NULL == ps_op_chksum_file) + { + sprintf(ac_error_str, "Could not open check sum file %s", + s_app_ctx.ac_op_chksum_fname); + codec_exit(ac_error_str); + } + } + /***********************************************************************/ + /* Create decoder instance */ + /***********************************************************************/ + { + + ps_out_buf = (ivd_out_bufdesc_t *)malloc(sizeof(ivd_out_bufdesc_t)); + + { + iv_num_mem_rec_ip_t s_no_of_mem_rec_query_ip; + iv_num_mem_rec_op_t s_no_of_mem_rec_query_op; + + s_no_of_mem_rec_query_ip.u4_size = sizeof(s_no_of_mem_rec_query_ip); + s_no_of_mem_rec_query_op.u4_size = sizeof(s_no_of_mem_rec_query_op); + s_no_of_mem_rec_query_ip.e_cmd = IV_CMD_GET_NUM_MEM_REC; + + /*****************************************************************************/ + /* API Call: Get Number of Mem Records */ + /*****************************************************************************/ + e_dec_status = ivd_api_function( + NULL, (void *)&s_no_of_mem_rec_query_ip, + (void *)&s_no_of_mem_rec_query_op); + if(IV_SUCCESS != e_dec_status) + { + sprintf(ac_error_str, "Error in get mem records"); + codec_exit(ac_error_str); + } + + u4_num_mem_recs = s_no_of_mem_rec_query_op.u4_num_mem_rec; + } + + pv_mem_rec_location = malloc(u4_num_mem_recs * sizeof(iv_mem_rec_t)); + if(pv_mem_rec_location == NULL) + { + sprintf(ac_error_str, "Allocation failure for mem_rec_location"); + codec_exit(ac_error_str); + + } + + { + impeg2d_fill_mem_rec_ip_t s_fill_mem_rec_ip; + impeg2d_fill_mem_rec_op_t s_fill_mem_rec_op; + iv_mem_rec_t *ps_mem_rec; + UWORD32 total_size; + + s_fill_mem_rec_ip.s_ivd_fill_mem_rec_ip_t.e_cmd = + IV_CMD_FILL_NUM_MEM_REC; + s_fill_mem_rec_ip.s_ivd_fill_mem_rec_ip_t.pv_mem_rec_location = + (iv_mem_rec_t *)pv_mem_rec_location; + s_fill_mem_rec_ip.s_ivd_fill_mem_rec_ip_t.u4_max_frm_wd = + (s_app_ctx.max_wd == 0) ? MAX_FRAME_WIDTH : s_app_ctx.max_wd; + s_fill_mem_rec_ip.s_ivd_fill_mem_rec_ip_t.u4_max_frm_ht = + (s_app_ctx.max_ht == 0) ? MAX_FRAME_HEIGHT : s_app_ctx.max_ht; + s_fill_mem_rec_ip.u4_share_disp_buf = s_app_ctx.share_disp_buf; + s_fill_mem_rec_ip.e_output_format = + (IV_COLOR_FORMAT_T)s_app_ctx.e_output_chroma_format; + + s_fill_mem_rec_ip.s_ivd_fill_mem_rec_ip_t.u4_size = + sizeof(impeg2d_fill_mem_rec_ip_t); + s_fill_mem_rec_op.s_ivd_fill_mem_rec_op_t.u4_size = + sizeof(impeg2d_fill_mem_rec_op_t); + + ps_mem_rec = (iv_mem_rec_t *)pv_mem_rec_location; + for(i = 0; i < u4_num_mem_recs; i++) + ps_mem_rec[i].u4_size = sizeof(iv_mem_rec_t); + + /*****************************************************************************/ + /* API Call: Fill Mem Records */ + /*****************************************************************************/ + + e_dec_status = ivd_api_function(NULL, + (void *)&s_fill_mem_rec_ip, + (void *)&s_fill_mem_rec_op); + + u4_num_mem_recs = + s_fill_mem_rec_op.s_ivd_fill_mem_rec_op_t.u4_num_mem_rec_filled; + + if(IV_SUCCESS != e_dec_status) + { + sprintf(ac_error_str, "Error in fill mem records: %x", s_fill_mem_rec_op.s_ivd_fill_mem_rec_op_t.u4_error_code); + codec_exit(ac_error_str); + } + + ps_mem_rec = (iv_mem_rec_t *)pv_mem_rec_location; + total_size = 0; + for(i = 0; i < u4_num_mem_recs; i++) + { + ps_mem_rec->pv_base = app_aligned_malloc(ps_mem_rec->u4_mem_alignment, + ps_mem_rec->u4_mem_size); + if(ps_mem_rec->pv_base == NULL) + { + sprintf(ac_error_str, + "\nAllocation failure for mem record id %d size %d\n", + i, ps_mem_rec->u4_mem_size); + codec_exit(ac_error_str); + + } + total_size += ps_mem_rec->u4_mem_size; + + ps_mem_rec++; + } + //printf("\nTotal memory for codec %d\n", total_size); + } + /*****************************************************************************/ + /* API Call: Initialize the Decoder */ + /*****************************************************************************/ + { + impeg2d_init_ip_t s_init_ip; + impeg2d_init_op_t s_init_op; + void *fxns = &ivd_api_function; + iv_mem_rec_t *mem_tab; + + mem_tab = (iv_mem_rec_t *)pv_mem_rec_location; + s_init_ip.s_ivd_init_ip_t.e_cmd = (IVD_API_COMMAND_TYPE_T)IV_CMD_INIT; + s_init_ip.s_ivd_init_ip_t.pv_mem_rec_location = mem_tab; + s_init_ip.s_ivd_init_ip_t.u4_frm_max_wd = (s_app_ctx.max_wd == 0) ? MAX_FRAME_WIDTH : s_app_ctx.max_wd; + s_init_ip.s_ivd_init_ip_t.u4_frm_max_ht = (s_app_ctx.max_ht == 0) ? MAX_FRAME_HEIGHT : s_app_ctx.max_ht; + + s_init_ip.u4_share_disp_buf = s_app_ctx.share_disp_buf; + + s_init_ip.s_ivd_init_ip_t.u4_num_mem_rec = u4_num_mem_recs; + s_init_ip.s_ivd_init_ip_t.e_output_format = + (IV_COLOR_FORMAT_T)s_app_ctx.e_output_chroma_format; + s_init_ip.s_ivd_init_ip_t.u4_size = sizeof(impeg2d_init_ip_t); + s_init_op.s_ivd_init_op_t.u4_size = sizeof(impeg2d_init_op_t); + + codec_obj = (iv_obj_t *)mem_tab[0].pv_base; + codec_obj->pv_fxns = fxns; + codec_obj->u4_size = sizeof(iv_obj_t); + + s_app_ctx.cocodec_obj = codec_obj; + + ret = ivd_api_function((iv_obj_t *)codec_obj, (void *)&s_init_ip, + (void *)&s_init_op); + if(ret != IV_SUCCESS) + { + sprintf(ac_error_str, "Error in Init %8x\n", + s_init_op.s_ivd_init_op_t.u4_error_code); + codec_exit(ac_error_str); + } + + /*****************************************************************************/ + /* Input and output buffer allocation */ + /*****************************************************************************/ + { + + ivd_ctl_getbufinfo_ip_t s_ctl_ip; + ivd_ctl_getbufinfo_op_t s_ctl_op; + + s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL; + s_ctl_ip.e_sub_cmd = IVD_CMD_CTL_GETBUFINFO; + s_ctl_ip.u4_size = sizeof(ivd_ctl_getbufinfo_ip_t); + s_ctl_op.u4_size = sizeof(ivd_ctl_getbufinfo_op_t); + ret = ivd_api_function((iv_obj_t *)codec_obj, (void *)&s_ctl_ip, + (void *)&s_ctl_op); + if(ret != IV_SUCCESS) + { + sprintf(ac_error_str, "Error in Get Buf Info %x", s_ctl_op.u4_error_code); + codec_exit(ac_error_str); + } + + /* Allocate input buffer */ + u4_ip_buf_len = s_ctl_op.u4_min_in_buf_size[0]; + pu1_bs_buf = (UWORD8 *)malloc(u4_ip_buf_len); + + if(pu1_bs_buf == NULL) + { + sprintf(ac_error_str, + "\nAllocation failure for input buffer of size %d", + u4_ip_buf_len); + codec_exit(ac_error_str); + } + s_app_ctx.num_disp_buf = s_ctl_op.u4_num_disp_bufs; + /* Allocate output buffer only if display buffers are not shared */ + /* Or if shared and output is 420P */ + if((0 == s_app_ctx.share_disp_buf) || (IV_YUV_420P == s_app_ctx.e_output_chroma_format)) + { + UWORD32 outlen; + ps_out_buf->u4_min_out_buf_size[0] = + s_ctl_op.u4_min_out_buf_size[0]; + ps_out_buf->u4_min_out_buf_size[1] = + s_ctl_op.u4_min_out_buf_size[1]; + ps_out_buf->u4_min_out_buf_size[2] = + s_ctl_op.u4_min_out_buf_size[2]; + + outlen = s_ctl_op.u4_min_out_buf_size[0]; + if(s_ctl_op.u4_min_num_out_bufs > 1) + outlen += s_ctl_op.u4_min_out_buf_size[1]; + + if(s_ctl_op.u4_min_num_out_bufs > 2) + outlen += s_ctl_op.u4_min_out_buf_size[2]; + + ps_out_buf->pu1_bufs[0] = (UWORD8 *)malloc(outlen); + if(ps_out_buf->pu1_bufs[0] == NULL) + { + sprintf(ac_error_str, + "\nAllocation failure for output buffer of size %d", + outlen); + codec_exit(ac_error_str); + } + + if(s_ctl_op.u4_min_num_out_bufs > 1) + ps_out_buf->pu1_bufs[1] = ps_out_buf->pu1_bufs[0] + + (s_ctl_op.u4_min_out_buf_size[0]); + + if(s_ctl_op.u4_min_num_out_bufs > 2) + ps_out_buf->pu1_bufs[2] = ps_out_buf->pu1_bufs[1] + + (s_ctl_op.u4_min_out_buf_size[1]); + + ps_out_buf->u4_num_bufs = s_ctl_op.u4_min_num_out_bufs; + } + + } + } + + } + + + /*************************************************************************/ + /* set num of cores */ + /*************************************************************************/ + { + + impeg2d_ctl_set_num_cores_ip_t s_ctl_set_cores_ip; + impeg2d_ctl_set_num_cores_op_t s_ctl_set_cores_op; + + s_ctl_set_cores_ip.e_cmd = IVD_CMD_VIDEO_CTL; + s_ctl_set_cores_ip.e_sub_cmd = (IVD_CONTROL_API_COMMAND_TYPE_T)IMPEG2D_CMD_CTL_SET_NUM_CORES; + s_ctl_set_cores_ip.u4_num_cores = s_app_ctx.u4_num_cores; + s_ctl_set_cores_ip.u4_size = sizeof(impeg2d_ctl_set_num_cores_ip_t); + s_ctl_set_cores_op.u4_size = sizeof(impeg2d_ctl_set_num_cores_op_t); + + ret = ivd_api_function((iv_obj_t *)codec_obj, (void *)&s_ctl_set_cores_ip, + (void *)&s_ctl_set_cores_op); + if(ret != IV_SUCCESS) + { + sprintf(ac_error_str, "\nError in setting number of cores"); + codec_exit(ac_error_str); + } + + } + /*************************************************************************/ + /* set processsor */ + /*************************************************************************/ + + { + + impeg2d_ctl_set_processor_ip_t s_ctl_set_num_processor_ip; + impeg2d_ctl_set_processor_op_t s_ctl_set_num_processor_op; + + s_ctl_set_num_processor_ip.e_cmd = IVD_CMD_VIDEO_CTL; + s_ctl_set_num_processor_ip.e_sub_cmd = (IVD_CONTROL_API_COMMAND_TYPE_T)IMPEG2D_CMD_CTL_SET_PROCESSOR; + s_ctl_set_num_processor_ip.u4_arch = s_app_ctx.e_arch; + s_ctl_set_num_processor_ip.u4_soc = s_app_ctx.e_soc; + s_ctl_set_num_processor_ip.u4_size = sizeof(impeg2d_ctl_set_processor_ip_t); + s_ctl_set_num_processor_op.u4_size = sizeof(impeg2d_ctl_set_processor_op_t); + + ret = ivd_api_function((iv_obj_t *)codec_obj, (void *)&s_ctl_set_num_processor_ip, + (void *)&s_ctl_set_num_processor_op); + if(ret != IV_SUCCESS) + { + sprintf(ac_error_str, "\nError in setting Processor type"); + codec_exit(ac_error_str); + } + + } + + + /*****************************************************************************/ + /* Decode header to get width and height and buffer sizes */ + /*****************************************************************************/ + { + + ivd_ctl_set_config_ip_t s_ctl_ip; + ivd_ctl_set_config_op_t s_ctl_op; + + ivd_video_decode_ip_t s_video_decode_ip; + ivd_video_decode_op_t s_video_decode_op; + + s_ctl_ip.u4_disp_wd = STRIDE; + if(1 == s_app_ctx.display) + s_ctl_ip.u4_disp_wd = s_app_ctx.get_stride(); + + s_ctl_ip.e_frm_skip_mode = IVD_SKIP_NONE; + s_ctl_ip.e_frm_out_mode = IVD_DISPLAY_FRAME_OUT; + s_ctl_ip.e_vid_dec_mode = IVD_DECODE_HEADER; + s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL; + s_ctl_ip.e_sub_cmd = IVD_CMD_CTL_SETPARAMS; + s_ctl_ip.u4_size = sizeof(ivd_ctl_set_config_ip_t); + s_ctl_op.u4_size = sizeof(ivd_ctl_set_config_op_t); + + ret = ivd_api_function((iv_obj_t *)codec_obj, (void *)&s_ctl_ip, + (void *)&s_ctl_op); + if(ret != IV_SUCCESS) + { + sprintf(ac_error_str, + "\nError in setting the codec in header decode mode"); + codec_exit(ac_error_str); + } + + do + { + WORD32 numbytes; + if(0 == s_app_ctx.u4_piclen_flag) + { + fseek(ps_ip_file, file_pos, SEEK_SET); + numbytes = u4_ip_buf_len; + } + else + { + WORD32 entries; + entries = fscanf(ps_piclen_file, "%d\n", &numbytes); + if(1 != entries) + numbytes = u4_ip_buf_len; + } + + u4_bytes_remaining = fread(pu1_bs_buf, sizeof(UWORD8), numbytes, + ps_ip_file); + + if(0 == u4_bytes_remaining) + { + sprintf(ac_error_str, "\nUnable to read from input file"); + codec_exit(ac_error_str); + } + + s_video_decode_ip.e_cmd = IVD_CMD_VIDEO_DECODE; + s_video_decode_ip.u4_ts = u4_ip_frm_ts; + s_video_decode_ip.pv_stream_buffer = pu1_bs_buf; + s_video_decode_ip.u4_num_Bytes = u4_bytes_remaining; + s_video_decode_ip.u4_size = sizeof(ivd_video_decode_ip_t); + s_video_decode_op.u4_size = sizeof(ivd_video_decode_op_t); + + /*****************************************************************************/ + /* API Call: Header Decode */ + /*****************************************************************************/ + ret = ivd_api_function((iv_obj_t *)codec_obj, (void *)&s_video_decode_ip, + (void *)&s_video_decode_op); + + if(ret != IV_SUCCESS) + { + sprintf(ac_error_str, "\nError in header decode %x", + s_video_decode_op.u4_error_code); + // codec_exit(ac_error_str); + } + + u4_num_bytes_dec = s_video_decode_op.u4_num_bytes_consumed; +#ifndef PROFILE_ENABLE + printf("%d\n", s_video_decode_op.u4_num_bytes_consumed); +#endif + file_pos += u4_num_bytes_dec; + total_bytes_comsumed += u4_num_bytes_dec; + }while(ret != IV_SUCCESS); + + /* copy pic_wd and pic_ht to initialize buffers */ + s_app_ctx.u4_pic_wd = s_video_decode_op.u4_pic_wd; + s_app_ctx.u4_pic_ht = s_video_decode_op.u4_pic_ht; + +#if IOS_DISPLAY + s_app_ctx.i4_screen_wd = screen_wd; + s_app_ctx.i4_screen_ht = screen_ht; +#endif + + /* Create display thread and wait for the display buffers to be initialized */ + if(1 == s_app_ctx.display) + { + if(0 == s_app_ctx.display_thread_created) + { + s_app_ctx.display_init_done = 0; + ithread_create(s_app_ctx.display_thread_handle, NULL, + (void *)&display_thread, (void *)&s_app_ctx); + s_app_ctx.display_thread_created = 1; + + while(1) + { + if(s_app_ctx.display_init_done) + break; + + ithread_msleep(1); + } + } + + s_app_ctx.u4_strd = s_app_ctx.get_stride(); + } + } + + /*************************************************************************/ + /* Get actual number of output buffers requried, which is dependent */ + /* on stream properties such as width, height and level etc */ + /* This is needed mainly for shared display mode */ + /*************************************************************************/ + //if(1 == s_app_ctx.share_disp_buf) + { + ivd_ctl_getbufinfo_ip_t s_ctl_ip; + ivd_ctl_getbufinfo_op_t s_ctl_op; + WORD32 outlen = 0; + + s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL; + s_ctl_ip.e_sub_cmd = IVD_CMD_CTL_GETBUFINFO; + s_ctl_ip.u4_size = sizeof(ivd_ctl_getbufinfo_ip_t); + s_ctl_op.u4_size = sizeof(ivd_ctl_getbufinfo_op_t); + ret = ivd_api_function((iv_obj_t *)codec_obj, (void *)&s_ctl_ip, + (void *)&s_ctl_op); + if(ret != IV_SUCCESS) + { + sprintf(ac_error_str, "Error in Get Buf Info %x", s_ctl_op.u4_error_code); + codec_exit(ac_error_str); + } + +#ifdef APP_EXTRA_BUFS + s_app_ctx.disp_delay = EXTRA_DISP_BUFFERS; + s_ctl_op.u4_num_disp_bufs += EXTRA_DISP_BUFFERS; +#endif + + /*****************************************************************************/ + /* API Call: Allocate display buffers for display buffer shared case */ + /*****************************************************************************/ + + for(i = 0; i < s_ctl_op.u4_num_disp_bufs; i++) + { + + s_app_ctx.s_disp_buffers[i].u4_min_out_buf_size[0] = + s_ctl_op.u4_min_out_buf_size[0]; + s_app_ctx.s_disp_buffers[i].u4_min_out_buf_size[1] = + s_ctl_op.u4_min_out_buf_size[1]; + s_app_ctx.s_disp_buffers[i].u4_min_out_buf_size[2] = + s_ctl_op.u4_min_out_buf_size[2]; + + outlen = s_ctl_op.u4_min_out_buf_size[0]; + if(s_ctl_op.u4_min_num_out_bufs > 1) + outlen += s_ctl_op.u4_min_out_buf_size[1]; + + if(s_ctl_op.u4_min_num_out_bufs > 2) + outlen += s_ctl_op.u4_min_out_buf_size[2]; + + s_app_ctx.s_disp_buffers[i].pu1_bufs[0] = (UWORD8 *)malloc(outlen); + + if(s_app_ctx.s_disp_buffers[i].pu1_bufs[0] == NULL) + { + sprintf(ac_error_str, + "\nAllocation failure for output buffer of size %d", + outlen); + codec_exit(ac_error_str); + } + + if(s_ctl_op.u4_min_num_out_bufs > 1) + s_app_ctx.s_disp_buffers[i].pu1_bufs[1] = + s_app_ctx.s_disp_buffers[i].pu1_bufs[0] + + (s_ctl_op.u4_min_out_buf_size[0]); + + if(s_ctl_op.u4_min_num_out_bufs > 2) + s_app_ctx.s_disp_buffers[i].pu1_bufs[2] = + s_app_ctx.s_disp_buffers[i].pu1_bufs[1] + + (s_ctl_op.u4_min_out_buf_size[1]); + + s_app_ctx.s_disp_buffers[i].u4_num_bufs = + s_ctl_op.u4_min_num_out_bufs; + } + s_app_ctx.num_disp_buf = s_ctl_op.u4_num_disp_bufs; + + /*****************************************************************************/ + /* API Call: Send the allocated display buffers to codec */ + /*****************************************************************************/ + if(1 == s_app_ctx.share_disp_buf) + { + ivd_set_display_frame_ip_t s_set_display_frame_ip; + ivd_set_display_frame_op_t s_set_display_frame_op; + + s_set_display_frame_ip.e_cmd = IVD_CMD_SET_DISPLAY_FRAME; + s_set_display_frame_ip.u4_size = sizeof(ivd_set_display_frame_ip_t); + s_set_display_frame_op.u4_size = sizeof(ivd_set_display_frame_op_t); + + s_set_display_frame_ip.num_disp_bufs = s_app_ctx.num_disp_buf; + + memcpy(&(s_set_display_frame_ip.s_disp_buffer), + &(s_app_ctx.s_disp_buffers), + s_ctl_op.u4_num_disp_bufs * sizeof(ivd_out_bufdesc_t)); + + ret = ivd_api_function((iv_obj_t *)codec_obj, + (void *)&s_set_display_frame_ip, + (void *)&s_set_display_frame_op); + + if(IV_SUCCESS != ret) + { + sprintf(ac_error_str, "Error in Set display frame"); + codec_exit(ac_error_str); + } + } + + + } + + /*************************************************************************/ + /* Get frame dimensions for display buffers such as x_offset,y_offset */ + /* etc. This information might be needed to set display buffer */ + /* offsets in case of shared display buffer mode */ + /*************************************************************************/ + { + + impeg2d_ctl_get_frame_dimensions_ip_t s_ctl_get_frame_dimensions_ip; + impeg2d_ctl_get_frame_dimensions_op_t s_ctl_get_frame_dimensions_op; + + s_ctl_get_frame_dimensions_ip.e_cmd = IVD_CMD_VIDEO_CTL; + s_ctl_get_frame_dimensions_ip.e_sub_cmd = + (IVD_CONTROL_API_COMMAND_TYPE_T)IMPEG2D_CMD_CTL_GET_BUFFER_DIMENSIONS; + s_ctl_get_frame_dimensions_ip.u4_size = + sizeof(impeg2d_ctl_get_frame_dimensions_ip_t); + s_ctl_get_frame_dimensions_op.u4_size = + sizeof(impeg2d_ctl_get_frame_dimensions_op_t); + + ret = ivd_api_function((iv_obj_t *)codec_obj, (void *)&s_ctl_get_frame_dimensions_ip, + (void *)&s_ctl_get_frame_dimensions_op); + if(IV_SUCCESS != ret) + { + sprintf(ac_error_str, "Error in Get buffer Dimensions"); + codec_exit(ac_error_str); + } + +/* + printf("Frame offsets due to padding\n"); + printf("s_ctl_get_frame_dimensions_op.x_offset[0] %d s_ctl_get_frame_dimensions_op.y_offset[0] %d\n", + s_ctl_get_frame_dimensions_op.u4_x_offset[0], + s_ctl_get_frame_dimensions_op.u4_y_offset[0]); +*/ + } + /*************************************************************************/ + /* Get VUI parameters */ + /*************************************************************************/ +#if 0 + { + + impeg2d_ctl_get_vui_params_ip_t s_ctl_get_vui_params_ip; + impeg2d_ctl_get_vui_params_op_t s_ctl_get_vui_params_op; + + s_ctl_get_vui_params_ip.e_cmd = IVD_CMD_VIDEO_CTL; + s_ctl_get_vui_params_ip.e_sub_cmd = + (IVD_CONTROL_API_COMMAND_TYPE_T)IMPEG2D_CMD_CTL_GET_VUI_PARAMS; + s_ctl_get_vui_params_ip.u4_size = + sizeof(impeg2d_ctl_get_vui_params_ip_t); + s_ctl_get_vui_params_op.u4_size = + sizeof(impeg2d_ctl_get_vui_params_op_t); + + ret = ivd_api_function((iv_obj_t *)codec_obj, (void *)&s_ctl_get_vui_params_ip, + (void *)&s_ctl_get_vui_params_op); + if(IV_SUCCESS != ret) + { + sprintf(ac_error_str, "Error in Get VUI params"); + //codec_exit(ac_error_str); + } + + } +#endif + + /*************************************************************************/ + /* Set the decoder in frame decode mode. It was set in header decode */ + /* mode earlier */ + /*************************************************************************/ + { + + ivd_ctl_set_config_ip_t s_ctl_ip; + ivd_ctl_set_config_op_t s_ctl_op; + + s_ctl_ip.u4_disp_wd = STRIDE; + if(1 == s_app_ctx.display) + s_ctl_ip.u4_disp_wd = s_app_ctx.get_stride(); + s_ctl_ip.e_frm_skip_mode = IVD_SKIP_NONE; + + s_ctl_ip.e_frm_out_mode = IVD_DISPLAY_FRAME_OUT; + s_ctl_ip.e_vid_dec_mode = IVD_DECODE_FRAME; + s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL; + s_ctl_ip.e_sub_cmd = IVD_CMD_CTL_SETPARAMS; + s_ctl_ip.u4_size = sizeof(ivd_ctl_set_config_ip_t); + + s_ctl_op.u4_size = sizeof(ivd_ctl_set_config_op_t); + + ret = ivd_api_function((iv_obj_t *)codec_obj, (void *)&s_ctl_ip, (void *)&s_ctl_op); + + if(IV_SUCCESS != ret) + { + sprintf(ac_error_str, "Error in Set Parameters"); + //codec_exit(ac_error_str); + } + + } + /*************************************************************************/ + /* If required disable deblocking and sao at given level */ + /*************************************************************************/ + set_degrade(codec_obj, s_app_ctx.i4_degrade_type, s_app_ctx.i4_degrade_pics); +#ifdef WINDOWS_TIMER + QueryPerformanceFrequency(&frequency); +#endif +#ifndef PRINT_PICSIZE + get_version(codec_obj); +#endif + while(u4_op_frm_ts < (s_app_ctx.u4_max_frm_ts + s_app_ctx.disp_delay)) + { + +#ifdef TEST_FLUSH + if(u4_ip_frm_ts == FLUSH_FRM_CNT) + { + ivd_ctl_flush_ip_t s_ctl_ip; + ivd_ctl_flush_op_t s_ctl_op; + + s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL; + s_ctl_ip.e_sub_cmd = IVD_CMD_CTL_FLUSH; + s_ctl_ip.u4_size = sizeof(ivd_ctl_flush_ip_t); + s_ctl_op.u4_size = sizeof(ivd_ctl_flush_op_t); + ret = ivd_api_function((iv_obj_t *)codec_obj, (void *)&s_ctl_ip, + (void *)&s_ctl_op); + + if(ret != IV_SUCCESS) + { + printf("Error in Setting the decoder in flush mode\n"); + } + file_pos = 0; + + fseek(ps_ip_file, file_pos, SEEK_SET); + + } +#endif + if(u4_ip_frm_ts < s_app_ctx.num_disp_buf && (1 == s_app_ctx.share_disp_buf)) + { + release_disp_frame(codec_obj, u4_ip_frm_ts); + } + + + /*************************************************************************/ + /* set num of cores */ + /*************************************************************************/ +#ifdef DYNAMIC_NUMCORES + { + + impeg2d_ctl_set_num_cores_ip_t s_ctl_set_cores_ip; + impeg2d_ctl_set_num_cores_op_t s_ctl_set_cores_op; + + s_ctl_set_cores_ip.e_cmd = IVD_CMD_VIDEO_CTL; + s_ctl_set_cores_ip.e_sub_cmd = IMPEG2D_CMD_CTL_SET_NUM_CORES; + s_ctl_set_cores_ip.u4_num_cores = 1 + 3 * (u4_ip_frm_ts % 2); + s_ctl_set_cores_ip.u4_size = sizeof(impeg2d_ctl_set_num_cores_ip_t); + s_ctl_set_cores_op.u4_size = sizeof(impeg2d_ctl_set_num_cores_op_t); + + ret = ivd_api_function((iv_obj_t *)codec_obj, (void *)&s_ctl_set_cores_ip, + (void *)&s_ctl_set_cores_op); + if(ret != IV_SUCCESS) + { + sprintf(ac_error_str, "\nError in setting number of cores"); + codec_exit(ac_error_str); + } + + } +#endif + /***********************************************************************/ + /* Seek the file to start of current frame, this is equavelent of */ + /* having a parcer which tells the start of current frame */ + /***********************************************************************/ + { + WORD32 numbytes; + + if(0 == s_app_ctx.u4_piclen_flag) + { + fseek(ps_ip_file, file_pos, SEEK_SET); + numbytes = u4_ip_buf_len; + } + else + { + WORD32 entries; + entries = fscanf(ps_piclen_file, "%d\n", &numbytes); + if(1 != entries) + numbytes = u4_ip_buf_len; + } + + u4_bytes_remaining = fread(pu1_bs_buf, sizeof(UWORD8), + numbytes, ps_ip_file); + + if(u4_bytes_remaining == 0) + { + if(1 == s_app_ctx.loopback) + { + file_pos = 0; + if(0 == s_app_ctx.u4_piclen_flag) + { + fseek(ps_ip_file, file_pos, SEEK_SET); + numbytes = u4_ip_buf_len; + } + else + { + WORD32 entries; + entries = fscanf(ps_piclen_file, "%d\n", &numbytes); + if(1 != entries) + numbytes = u4_ip_buf_len; + } + + + u4_bytes_remaining = fread(pu1_bs_buf, sizeof(UWORD8), + numbytes, ps_ip_file); + } + else + break; + } + } + + /*********************************************************************/ + /* Following calls can be enabled at diffent times */ + /*********************************************************************/ +#if ENABLE_DEGRADE + if(u4_op_frm_ts >= 10000) + disable_deblocking(codec_obj, 4); + + if(u4_op_frm_ts == 30000) + enable_deblocking(codec_obj); + + if(u4_op_frm_ts == 10000) + enable_skippb_frames(codec_obj); + + if(u4_op_frm_ts == 60000) + disable_skippb_frames(codec_obj); + + if(u4_op_frm_ts == 30000) + enable_skipb_frames(codec_obj); + + if(u4_op_frm_ts == 60000) + disable_skipb_frames(codec_obj); +#endif + + + { + ivd_video_decode_ip_t s_video_decode_ip; + ivd_video_decode_op_t s_video_decode_op; +#ifdef PROFILE_ENABLE + UWORD32 s_elapsed_time; + TIMER s_start_timer; + TIMER s_end_timer; +#endif + + + s_video_decode_ip.e_cmd = IVD_CMD_VIDEO_DECODE; + s_video_decode_ip.u4_ts = u4_ip_frm_ts; + s_video_decode_ip.pv_stream_buffer = pu1_bs_buf; + s_video_decode_ip.u4_num_Bytes = u4_bytes_remaining; + s_video_decode_ip.u4_size = sizeof(ivd_video_decode_ip_t); + s_video_decode_ip.s_out_buffer.u4_min_out_buf_size[0] = + ps_out_buf->u4_min_out_buf_size[0]; + s_video_decode_ip.s_out_buffer.u4_min_out_buf_size[1] = + ps_out_buf->u4_min_out_buf_size[1]; + s_video_decode_ip.s_out_buffer.u4_min_out_buf_size[2] = + ps_out_buf->u4_min_out_buf_size[2]; + + s_video_decode_ip.s_out_buffer.pu1_bufs[0] = + ps_out_buf->pu1_bufs[0]; + s_video_decode_ip.s_out_buffer.pu1_bufs[1] = + ps_out_buf->pu1_bufs[1]; + s_video_decode_ip.s_out_buffer.pu1_bufs[2] = + ps_out_buf->pu1_bufs[2]; + s_video_decode_ip.s_out_buffer.u4_num_bufs = + ps_out_buf->u4_num_bufs; + s_video_decode_op.u4_size = sizeof(ivd_video_decode_op_t); + + /* Get display buffer pointers */ + if(1 == s_app_ctx.display) + { + WORD32 wr_idx; + + wr_idx = dispq_producer_dequeue(&s_app_ctx); + + if(s_app_ctx.quit) + break; + + s_app_ctx.set_disp_buffers(s_app_ctx.pv_disp_ctx, wr_idx, + &s_video_decode_ip.s_out_buffer.pu1_bufs[0], + &s_video_decode_ip.s_out_buffer.pu1_bufs[1], + &s_video_decode_ip.s_out_buffer.pu1_bufs[2]); + } + + /*****************************************************************************/ + /* API Call: Video Decode */ + /*****************************************************************************/ + + GETTIME(&s_start_timer); + + ret = ivd_api_function((iv_obj_t *)codec_obj, (void *)&s_video_decode_ip, + (void *)&s_video_decode_op); + + + GETTIME(&s_end_timer); + ELAPSEDTIME(s_start_timer, s_end_timer, s_elapsed_time, frequency); +#ifdef PROFILE_ENABLE + { + UWORD32 peak_avg, id; + u4_tot_cycles += s_elapsed_time; + peak_window[peak_window_idx++] = s_elapsed_time; + if(peak_window_idx == PEAK_WINDOW_SIZE) + peak_window_idx = 0; + peak_avg = 0; + for(id = 0; id < PEAK_WINDOW_SIZE; id++) + { + peak_avg += peak_window[id]; + } + peak_avg /= PEAK_WINDOW_SIZE; + if(peak_avg > peak_avg_max) + peak_avg_max = peak_avg; + frm_cnt++; + + printf("FrameNum: %4d TimeTaken(microsec): %6d AvgTime: %6d PeakAvgTimeMax: %6d Output: %2d NumBytes: %6d \n", + frm_cnt, s_elapsed_time, u4_tot_cycles / frm_cnt, peak_avg_max, s_video_decode_op.u4_output_present, s_video_decode_op.u4_num_bytes_consumed); + + } +#ifdef INTEL_CE5300 + time_consumed += s_elapsed_time; + bytes_consumed += s_video_decode_op.u4_num_bytes_consumed; + if(!(frm_cnt % (s_app_ctx.fps))) + { + time_consumed = time_consumed / s_app_ctx.fps; + printf("Average decode time(micro sec) for the last second = %6d\n", time_consumed); + printf("Average bitrate(kb) for the last second = %6d\n", (bytes_consumed * 8) / 1024); + time_consumed = 0; + bytes_consumed = 0; + + } +#endif +#else + printf("%d\n", s_video_decode_op.u4_num_bytes_consumed); +#endif + + if(IV_SUCCESS != ret) + { + printf("Error in video Frame decode : ret %x Error %x\n", ret, + s_video_decode_op.u4_error_code); + if ((s_video_decode_op.u4_error_code & 0xFF) == IVD_RES_CHANGED) + { + ivd_ctl_reset_ip_t s_ctl_ip; + ivd_ctl_reset_op_t s_ctl_op; + + flush_output(codec_obj, &s_app_ctx, ps_out_buf, + pu1_bs_buf, &u4_op_frm_ts, + ps_op_file, ps_op_chksum_file, + u4_ip_frm_ts, u4_bytes_remaining); + + s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL; + s_ctl_ip.e_sub_cmd = IVD_CMD_CTL_RESET; + s_ctl_ip.u4_size = sizeof(ivd_ctl_reset_ip_t); + s_ctl_op.u4_size = sizeof(ivd_ctl_reset_op_t); + + ret = ivd_api_function((iv_obj_t *)codec_obj, (void *)&s_ctl_ip, + (void *)&s_ctl_op); + if(IV_SUCCESS != ret) + { + sprintf(ac_error_str, "Error in Reset"); + codec_exit(ac_error_str); + } + /*************************************************************************/ + /* set num of cores */ + /*************************************************************************/ + { + + impeg2d_ctl_set_num_cores_ip_t s_ctl_set_cores_ip; + impeg2d_ctl_set_num_cores_op_t s_ctl_set_cores_op; + + s_ctl_set_cores_ip.e_cmd = IVD_CMD_VIDEO_CTL; + s_ctl_set_cores_ip.e_sub_cmd = (IVD_CONTROL_API_COMMAND_TYPE_T)IMPEG2D_CMD_CTL_SET_NUM_CORES; + s_ctl_set_cores_ip.u4_num_cores = s_app_ctx.u4_num_cores; + s_ctl_set_cores_ip.u4_size = sizeof(impeg2d_ctl_set_num_cores_ip_t); + s_ctl_set_cores_op.u4_size = sizeof(impeg2d_ctl_set_num_cores_op_t); + + ret = ivd_api_function((iv_obj_t *)codec_obj, (void *)&s_ctl_set_cores_ip, + (void *)&s_ctl_set_cores_op); + if(ret != IV_SUCCESS) + { + sprintf(ac_error_str, "\nError in setting number of cores"); + codec_exit(ac_error_str); + } + + } + /*************************************************************************/ + /* set processsor */ + /*************************************************************************/ + + { + + impeg2d_ctl_set_processor_ip_t s_ctl_set_num_processor_ip; + impeg2d_ctl_set_processor_op_t s_ctl_set_num_processor_op; + + s_ctl_set_num_processor_ip.e_cmd = IVD_CMD_VIDEO_CTL; + s_ctl_set_num_processor_ip.e_sub_cmd = (IVD_CONTROL_API_COMMAND_TYPE_T)IMPEG2D_CMD_CTL_SET_PROCESSOR; + s_ctl_set_num_processor_ip.u4_arch = s_app_ctx.e_arch; + s_ctl_set_num_processor_ip.u4_soc = s_app_ctx.e_soc; + s_ctl_set_num_processor_ip.u4_size = sizeof(impeg2d_ctl_set_processor_ip_t); + s_ctl_set_num_processor_op.u4_size = sizeof(impeg2d_ctl_set_processor_op_t); + + ret = ivd_api_function((iv_obj_t *)codec_obj, (void *)&s_ctl_set_num_processor_ip, + (void *)&s_ctl_set_num_processor_op); + if(ret != IV_SUCCESS) + { + sprintf(ac_error_str, "\nError in setting Processor type"); + codec_exit(ac_error_str); + } + + } + + } + else if(IMPEG2D_UNSUPPORTED_DIMENSIONS + == (IMPEG2D_ERROR_CODES_T)s_video_decode_op.u4_error_code) + { + flush_output(codec_obj, &s_app_ctx, ps_out_buf, + pu1_bs_buf, &u4_op_frm_ts, + ps_op_file, ps_op_chksum_file, + u4_ip_frm_ts, u4_bytes_remaining); + + printf("Reinit codec with width %d and height %d\n", + s_video_decode_op.u4_pic_wd, + s_video_decode_op.u4_pic_ht); + + break; + } + } + + if((1 == s_app_ctx.display) && + (1 == s_video_decode_op.u4_output_present)) + { + dispq_producer_queue(&s_app_ctx); + } + + if(IV_B_FRAME == s_video_decode_op.e_pic_type) + s_app_ctx.b_pic_present |= 1; + + u4_num_bytes_dec = s_video_decode_op.u4_num_bytes_consumed; + + file_pos += u4_num_bytes_dec; + total_bytes_comsumed += u4_num_bytes_dec; + u4_ip_frm_ts++; + + + if(1 == s_video_decode_op.u4_output_present) + { + width = s_video_decode_op.s_disp_frm_buf.u4_y_wd; + height = s_video_decode_op.s_disp_frm_buf.u4_y_ht; + dump_output(&s_app_ctx, &(s_video_decode_op.s_disp_frm_buf), + s_video_decode_op.u4_disp_buf_id, ps_op_file, + ps_op_chksum_file, + u4_op_frm_ts, s_app_ctx.u4_file_save_flag, + s_app_ctx.u4_chksum_save_flag); + + u4_op_frm_ts++; + } + else + { + if((s_video_decode_op.u4_error_code >> IVD_FATALERROR) & 1) + { + printf("Fatal error\n"); + break; + } + } + + } + } + + /***********************************************************************/ + /* To get the last decoded frames, call process with NULL input */ + /***********************************************************************/ + flush_output(codec_obj, &s_app_ctx, ps_out_buf, + pu1_bs_buf, &u4_op_frm_ts, + ps_op_file, ps_op_chksum_file, + u4_ip_frm_ts, u4_bytes_remaining); + + /* set disp_end flag */ + s_app_ctx.quit = 1; + + +#ifdef PROFILE_ENABLE + printf("Summary\n"); + printf("Input filename : %s\n", s_app_ctx.ac_ip_fname); + printf("Output Width : %-4d\n", width); + printf("Output Height : %-4d\n", height); + + if(frm_cnt) + { + double avg = u4_tot_cycles / frm_cnt; + double bytes_avg = total_bytes_comsumed / frm_cnt; + double bitrate = (bytes_avg * 8 * s_app_ctx.fps) / 1000000; + printf("Bitrate @ %2d fps(mbps) : %-6.2f\n", s_app_ctx.fps, bitrate); + printf("Average decode time(micro sec) : %-6d\n", (WORD32)avg); + printf("Avg Peak decode time(%2d frames) : %-6d\n", PEAK_WINDOW_SIZE, (WORD32)peak_avg_max); + avg = (u4_tot_cycles + u4_tot_fmt_cycles) * 1.0 / frm_cnt; + + if(0 == s_app_ctx.share_disp_buf) + printf("FPS achieved (with format conv) : %-3.2f\n", 1000000 / avg); + else + printf("FPS achieved : %-3.2f\n", 1000000 / avg); + } +#endif + /***********************************************************************/ + /* Clear the decoder, close all the files, free all the memory */ + /***********************************************************************/ + if(1 == s_app_ctx.display) + { + s_app_ctx.display_deinit_flag = 1; + /* wait for display to finish */ + if(s_app_ctx.display_thread_created) + { + ithread_join(s_app_ctx.display_thread_handle, NULL); + } + free(s_app_ctx.display_thread_handle); + } + + { + iv_retrieve_mem_rec_ip_t s_retrieve_dec_ip; + iv_retrieve_mem_rec_op_t s_retrieve_dec_op; + s_retrieve_dec_ip.pv_mem_rec_location = (iv_mem_rec_t *)pv_mem_rec_location; + + s_retrieve_dec_ip.e_cmd = IV_CMD_RETRIEVE_MEMREC; + s_retrieve_dec_ip.u4_size = sizeof(iv_retrieve_mem_rec_ip_t); + s_retrieve_dec_op.u4_size = sizeof(iv_retrieve_mem_rec_op_t); + + ret = ivd_api_function((iv_obj_t *)codec_obj, (void *)&s_retrieve_dec_ip, + (void *)&s_retrieve_dec_op); + + if(IV_SUCCESS != ret) + { + sprintf(ac_error_str, "Error in Retrieve Memrec"); + codec_exit(ac_error_str); + } + + { + iv_mem_rec_t *ps_mem_rec; + UWORD16 u2_i; + + u4_num_mem_recs = s_retrieve_dec_op.u4_num_mem_rec_filled; + + ps_mem_rec = s_retrieve_dec_ip.pv_mem_rec_location; + + for(u2_i = 0; u2_i < u4_num_mem_recs; u2_i++) + { + app_aligned_free(ps_mem_rec->pv_base); + ps_mem_rec++; + } + free(s_retrieve_dec_ip.pv_mem_rec_location); + } + + } + /***********************************************************************/ + /* Close all the files and free all the memory */ + /***********************************************************************/ + { + fclose(ps_ip_file); + + if(1 == s_app_ctx.u4_file_save_flag) + { + fclose(ps_op_file); + } + if(1 == s_app_ctx.u4_chksum_save_flag) + { + fclose(ps_op_chksum_file); + } + + } + + if(0 == s_app_ctx.share_disp_buf) + { + free(ps_out_buf->pu1_bufs[0]); + } + + for(i = 0; i < s_app_ctx.num_disp_buf; i++) + { + free(s_app_ctx.s_disp_buffers[i].pu1_bufs[0]); + } + + free(ps_out_buf); + free(pu1_bs_buf); + + return (0); +} |