mirror of
https://github.com/mpv-player/mpv
synced 2025-02-07 15:41:55 +00:00
Fixed playback bug in vo_dxr3 which would cause syncloss when playing ntsc movies on pal and vice versa (this does not affect mpeg playback as we still don't know how to set the internal fps registers) git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@4755 b3059339-0415-0410-9bf9-f77b7e298cf2
2869 lines
80 KiB
C
2869 lines
80 KiB
C
// AVI & MPEG Player v0.18 (C) 2000-2001. by A'rpi/ESP-team
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
|
|
#include <sys/ioctl.h>
|
|
#include <sys/mman.h>
|
|
#include <sys/types.h>
|
|
#include <sys/wait.h>
|
|
#include <sys/time.h>
|
|
#include <sys/stat.h>
|
|
|
|
#include <signal.h>
|
|
#include <time.h>
|
|
#include <fcntl.h>
|
|
|
|
#include "version.h"
|
|
#include "config.h"
|
|
|
|
#include "mp_msg.h"
|
|
|
|
#define HELP_MP_DEFINE_STATIC
|
|
#include "help_mp.h"
|
|
|
|
#include "cfgparser.h"
|
|
#include "cfg-mplayer-def.h"
|
|
|
|
#ifdef USE_SUB
|
|
#include "subreader.h"
|
|
#endif
|
|
|
|
#ifdef USE_LIBVO2
|
|
#include "libvo2/libvo2.h"
|
|
#else
|
|
#include "libvo/video_out.h"
|
|
extern void* mDisplay; // Display* mDisplay;
|
|
#endif
|
|
|
|
#ifdef USE_LIBVO2
|
|
#include "libvo2/sub.h"
|
|
#else
|
|
#include "libvo/sub.h"
|
|
#endif
|
|
|
|
#include "libao2/audio_out.h"
|
|
#include "libao2/audio_plugin.h"
|
|
|
|
#include "libmpeg2/mpeg2.h"
|
|
#include "libmpeg2/mpeg2_internal.h"
|
|
|
|
#include "codec-cfg.h"
|
|
|
|
#include "dvdauth.h"
|
|
#ifdef USE_DVDREAD
|
|
#include "spudec.h"
|
|
#endif
|
|
#include "vobsub.h"
|
|
|
|
#include "linux/getch2.h"
|
|
#include "linux/keycodes.h"
|
|
#include "linux/timer.h"
|
|
#include "linux/shmem.h"
|
|
|
|
#include "cpudetect.h"
|
|
|
|
#ifdef HAVE_LIRC
|
|
#include "lirc_mp.h"
|
|
#endif
|
|
|
|
#ifdef HAVE_NEW_GUI
|
|
#include "Gui/mplayer/play.h"
|
|
#endif
|
|
|
|
#ifdef HAVE_NEW_INPUT
|
|
#include "input/input.h"
|
|
#endif
|
|
|
|
int slave_mode=0;
|
|
int verbose=0;
|
|
int quiet=0;
|
|
|
|
#define ABS(x) (((x)>=0)?(x):(-(x)))
|
|
|
|
#ifdef HAVE_RTC
|
|
#include <linux/rtc.h>
|
|
#endif
|
|
|
|
#ifdef USE_TV
|
|
#include "libmpdemux/tv.h"
|
|
|
|
extern int tv_param_on;
|
|
extern tvi_handle_t *tv_handler;
|
|
#endif
|
|
|
|
//**************************************************************************//
|
|
// Playtree
|
|
//**************************************************************************//
|
|
#include "playtree.h"
|
|
|
|
play_tree_t* playtree;
|
|
|
|
#define PT_NEXT_ENTRY 1
|
|
#define PT_PREV_ENTRY -1
|
|
#define PT_NEXT_SRC 2
|
|
#define PT_PREV_SRC -2
|
|
#define PT_UP_NEXT 3
|
|
#define PT_UP_PREV -3
|
|
|
|
//**************************************************************************//
|
|
// Config
|
|
//**************************************************************************//
|
|
|
|
m_config_t* mconfig;
|
|
|
|
/**************************************************************************
|
|
Video accelerated architecture
|
|
**************************************************************************/
|
|
vo_vaa_t vo_vaa;
|
|
|
|
//**************************************************************************//
|
|
// Config file
|
|
//**************************************************************************//
|
|
|
|
static int cfg_inc_verbose(struct config *conf){ ++verbose; return 0;}
|
|
|
|
static int cfg_include(struct config *conf, char *filename){
|
|
return m_config_parse_config_file(mconfig, filename);
|
|
}
|
|
|
|
#include "get_path.c"
|
|
|
|
//**************************************************************************//
|
|
//**************************************************************************//
|
|
// Input media streaming & demultiplexer:
|
|
//**************************************************************************//
|
|
|
|
static int max_framesize=0;
|
|
|
|
#include "stream.h"
|
|
#include "demuxer.h"
|
|
#include "stheader.h"
|
|
#include "parse_es.h"
|
|
|
|
#include "dec_audio.h"
|
|
#include "dec_video.h"
|
|
|
|
#if 0
|
|
extern picture_t *picture; // exported from libmpeg2/decode.c
|
|
|
|
int frameratecode2framerate[16] = {
|
|
0,
|
|
// Official mpeg1/2 framerates:
|
|
24000*10000/1001, 24*10000,25*10000, 30000*10000/1001, 30*10000,50*10000,60000*10000/1001, 60*10000,
|
|
// libmpeg3's "Unofficial economy rates":
|
|
1*10000,5*10000,10*10000,12*10000,15*10000,0,0
|
|
};
|
|
#endif
|
|
|
|
//**************************************************************************//
|
|
//**************************************************************************//
|
|
|
|
// Common FIFO functions, and keyboard/event FIFO code
|
|
#include "fifo.c"
|
|
|
|
//**************************************************************************//
|
|
|
|
#ifdef USE_LIBVO2
|
|
static vo2_handle_t *video_out=NULL;
|
|
#else
|
|
static vo_functions_t *video_out=NULL;
|
|
#endif
|
|
static ao_functions_t *audio_out=NULL;
|
|
|
|
// benchmark:
|
|
double video_time_usage=0;
|
|
double vout_time_usage=0;
|
|
static double audio_time_usage=0;
|
|
static int total_time_usage_start=0;
|
|
static int benchmark=0;
|
|
|
|
// static int play_in_bg=0;
|
|
|
|
// options:
|
|
static int auto_quality=0;
|
|
static int output_quality=0;
|
|
|
|
int use_gui=0;
|
|
|
|
int osd_level=2;
|
|
|
|
// seek:
|
|
char *seek_to_sec=NULL;
|
|
off_t seek_to_byte=0;
|
|
off_t step_sec=0;
|
|
int loop_times=-1;
|
|
float rel_seek_secs=0;
|
|
int abs_seek_pos=0;
|
|
|
|
// codecs:
|
|
int has_audio=1;
|
|
int has_video=1;
|
|
char *audio_codec=NULL; // override audio codec
|
|
char *video_codec=NULL; // override video codec
|
|
int audio_family=-1; // override audio codec family
|
|
int video_family=-1; // override video codec family
|
|
|
|
// IMHO this stuff is no longer of use, or is there a special
|
|
// reason why dshow should be completely disabled? - atmos ::
|
|
// yes, people without working c++ compiler can disable it - A'rpi
|
|
#ifdef USE_DIRECTSHOW
|
|
int allow_dshow=1;
|
|
#else
|
|
int allow_dshow=0;
|
|
#endif
|
|
|
|
// streaming:
|
|
int audio_id=-1;
|
|
int video_id=-1;
|
|
int dvdsub_id=-1;
|
|
int vobsub_id=-1;
|
|
char* audio_lang=NULL;
|
|
char* dvdsub_lang=NULL;
|
|
static int vcd_track=0;
|
|
|
|
// cache2:
|
|
static int stream_cache_size=0;
|
|
#ifdef USE_STREAM_CACHE
|
|
extern int cache_fill_status;
|
|
#else
|
|
#define cache_fill_status 0
|
|
#endif
|
|
|
|
// dump:
|
|
static char *stream_dump_name="stream.dump";
|
|
static int stream_dump_type=0;
|
|
|
|
// A-V sync:
|
|
static float default_max_pts_correction=-1;//0.01f;
|
|
static float max_pts_correction=0;//default_max_pts_correction;
|
|
static float c_total=0;
|
|
static float audio_delay=0;
|
|
|
|
static int dapsync=0;
|
|
static int softsleep=0;
|
|
|
|
static float force_fps=0;
|
|
static int force_srate=0;
|
|
static int frame_dropping=0; // option 0=no drop 1= drop vo 2= drop decode
|
|
static int play_n_frames=-1;
|
|
|
|
// screen info:
|
|
char* video_driver=NULL; //"mga"; // default
|
|
char* audio_driver=NULL;
|
|
static int fullscreen=0;
|
|
static int vidmode=0;
|
|
int softzoom=0;
|
|
static int flip=-1;
|
|
// We need this opt_* because the values are then calculated so the options use the opt_*
|
|
// and before each file we reset the calculated value using this opt_* values
|
|
static int opt_screen_size_x=0;//SCREEN_SIZE_X;
|
|
static int opt_screen_size_y=0;//SCREEN_SIZE_Y;
|
|
static int screen_size_x=0;//SCREEN_SIZE_X;
|
|
static int screen_size_y=0;//SCREEN_SIZE_Y;
|
|
static int screen_size_xy=0;
|
|
static float movie_aspect=-1.0;
|
|
|
|
char* playlist_file;
|
|
|
|
// sub:
|
|
char *font_name=NULL;
|
|
float font_factor=0.75;
|
|
char *sub_name=NULL;
|
|
float sub_delay=0;
|
|
float sub_fps=0;
|
|
int sub_auto = 1;
|
|
char *vobsub_name=NULL;
|
|
/*DSP!!char *dsp=NULL;*/
|
|
|
|
extern char *vo_subdevice;
|
|
extern char *ao_subdevice;
|
|
|
|
static stream_t* stream=NULL;
|
|
|
|
static char* current_module=NULL; // for debugging
|
|
|
|
static unsigned int inited_flags=0;
|
|
#define INITED_VO 1
|
|
#define INITED_AO 2
|
|
#define INITED_GUI 4
|
|
#define INITED_GETCH2 8
|
|
#define INITED_LIRC 16
|
|
#define INITED_SPUDEC 32
|
|
#define INITED_STREAM 64
|
|
#define INITED_INPUT 128
|
|
#define INITED_ALL 0xFFFF
|
|
|
|
void uninit_player(unsigned int mask){
|
|
mask=inited_flags&mask;
|
|
#ifdef USE_DVDREAD
|
|
if (mask&INITED_SPUDEC){
|
|
inited_flags&=~INITED_SPUDEC;
|
|
current_module="uninit_spudec";
|
|
spudec_free(vo_spudec);
|
|
}
|
|
#endif
|
|
if(mask&INITED_VO){
|
|
inited_flags&=~INITED_VO;
|
|
current_module="uninit_vo";
|
|
#ifdef USE_LIBVO2
|
|
vo2_close(video_out);
|
|
#else
|
|
video_out->uninit();
|
|
#endif
|
|
}
|
|
|
|
if(mask&INITED_AO){
|
|
inited_flags&=~INITED_AO;
|
|
current_module="uninit_ao";
|
|
audio_out->uninit();
|
|
}
|
|
|
|
if(mask&INITED_GETCH2){
|
|
inited_flags&=~INITED_GETCH2;
|
|
current_module="uninit_getch2";
|
|
// restore terminal:
|
|
getch2_disable();
|
|
}
|
|
|
|
#ifdef HAVE_NEW_GUI
|
|
if(mask&INITED_GUI){
|
|
inited_flags&=~INITED_GUI;
|
|
current_module="uninit_gui";
|
|
mplDone();
|
|
}
|
|
#endif
|
|
|
|
if(mask&INITED_STREAM){
|
|
inited_flags&=~INITED_STREAM;
|
|
current_module="uninit_stream";
|
|
if(stream) free_stream(stream);
|
|
stream=NULL;
|
|
}
|
|
|
|
#ifdef HAVE_LIRC
|
|
if(mask&INITED_LIRC){
|
|
inited_flags&=~INITED_LIRC;
|
|
current_module="uninit_lirc";
|
|
lirc_mp_cleanup();
|
|
}
|
|
#endif
|
|
|
|
#ifdef HAVE_NEW_INPUT
|
|
if(mask&INITED_INPUT){
|
|
inited_flags&=INITED_INPUT;
|
|
current_module="uninit_input";
|
|
mp_input_uninit();
|
|
}
|
|
#endif
|
|
|
|
current_module=NULL;
|
|
|
|
}
|
|
|
|
void exit_player(char* how){
|
|
|
|
uninit_player(INITED_ALL);
|
|
|
|
current_module="exit_player";
|
|
|
|
if(how) mp_msg(MSGT_CPLAYER,MSGL_INFO,MSGTR_Exiting,how);
|
|
mp_msg(MSGT_CPLAYER,MSGL_DBG2,"max framesize was %d bytes\n",max_framesize);
|
|
|
|
exit(1);
|
|
}
|
|
|
|
void exit_sighandler(int x){
|
|
static int sig_count=0;
|
|
++sig_count;
|
|
if(sig_count==2) exit(1);
|
|
if(sig_count>2){
|
|
// can't stop :(
|
|
kill(getpid(),SIGKILL);
|
|
}
|
|
mp_msg(MSGT_CPLAYER,MSGL_FATAL,MSGTR_IntBySignal,x,
|
|
current_module?current_module:"unknown"
|
|
);
|
|
exit_player(NULL);
|
|
}
|
|
|
|
//extern void write_avi_header_1(FILE *f,int fcc,float fps,int width,int height);
|
|
|
|
extern void mp_register_options(m_config_t* cfg);
|
|
|
|
#include "mixer.h"
|
|
#include "cfg-mplayer.h"
|
|
|
|
void parse_cfgfiles( m_config_t* conf )
|
|
{
|
|
char *conffile;
|
|
int conffile_fd;
|
|
if (m_config_parse_config_file(conf, "/etc/mplayer.conf") < 0)
|
|
exit(1);
|
|
if ((conffile = get_path("")) == NULL) {
|
|
mp_msg(MSGT_CPLAYER,MSGL_WARN,MSGTR_NoHomeDir);
|
|
} else {
|
|
mkdir(conffile, 0777);
|
|
free(conffile);
|
|
if ((conffile = get_path("config")) == NULL) {
|
|
mp_msg(MSGT_CPLAYER,MSGL_ERR,MSGTR_GetpathProblem);
|
|
} else {
|
|
if ((conffile_fd = open(conffile, O_CREAT | O_EXCL | O_WRONLY, 0666)) != -1) {
|
|
mp_msg(MSGT_CPLAYER,MSGL_INFO,MSGTR_CreatingCfgFile, conffile);
|
|
write(conffile_fd, default_config, strlen(default_config));
|
|
close(conffile_fd);
|
|
}
|
|
if (m_config_parse_config_file(conf, conffile) < 0)
|
|
exit(1);
|
|
free(conffile);
|
|
}
|
|
}
|
|
}
|
|
|
|
int main(int argc,char* argv[], char *envp[]){
|
|
|
|
#ifdef USE_SUB
|
|
static subtitle* subtitles=NULL;
|
|
float sub_last_pts = -303;
|
|
#endif
|
|
|
|
static demuxer_t *demuxer=NULL;
|
|
|
|
static demux_stream_t *d_audio=NULL;
|
|
static demux_stream_t *d_video=NULL;
|
|
static demux_stream_t *d_dvdsub=NULL;
|
|
|
|
static sh_audio_t *sh_audio=NULL;
|
|
static sh_video_t *sh_video=NULL;
|
|
|
|
// for multifile support:
|
|
play_tree_iter_t* playtree_iter = NULL;
|
|
|
|
char* filename=NULL; //"MI2-Trailer.avi";
|
|
int file_format=DEMUXER_TYPE_UNKNOWN;
|
|
|
|
int delay_corrected=1;
|
|
char* title="MPlayer";
|
|
|
|
// movie info:
|
|
int out_fmt=0;
|
|
int eof=0;
|
|
|
|
int osd_visible=100;
|
|
int osd_function=OSD_PLAY;
|
|
int osd_last_pts=-303;
|
|
int osd_show_av_delay = 0;
|
|
int osd_show_sub_delay = 0;
|
|
|
|
int v_hw_equ_cap=0;
|
|
int v_bright=50;
|
|
int v_cont=50;
|
|
int v_hue=50;
|
|
int v_saturation=50;
|
|
/*
|
|
For future:
|
|
int v_red_intensity=0;
|
|
int v_green_intensity=0;
|
|
int v_blue_intensity=0;
|
|
*/
|
|
|
|
int vo_flags=0;
|
|
|
|
int rtc_fd=-1;
|
|
|
|
//float a_frame=0; // Audio
|
|
|
|
int i;
|
|
int use_stdin=0; //int f; // filedes
|
|
|
|
int gui_no_filename=0;
|
|
|
|
vo_tune_info_t vtune;
|
|
|
|
mp_msg_init(MSGL_STATUS);
|
|
|
|
mp_msg(MSGT_CPLAYER,MSGL_INFO,"%s",banner_text);
|
|
memset(&vtune,0,sizeof(vo_tune_info_t));
|
|
/* Test for cpu capabilities (and corresponding OS support) for optimizing */
|
|
#ifdef ARCH_X86
|
|
GetCpuCaps(&gCpuCaps);
|
|
mp_msg(MSGT_CPLAYER,MSGL_INFO,"CPUflags: Type: %d MMX: %d MMX2: %d 3DNow: %d 3DNow2: %d SSE: %d SSE2: %d\n",
|
|
gCpuCaps.cpuType,gCpuCaps.hasMMX,gCpuCaps.hasMMX2,
|
|
gCpuCaps.has3DNow, gCpuCaps.has3DNowExt,
|
|
gCpuCaps.hasSSE, gCpuCaps.hasSSE2);
|
|
#ifdef RUNTIME_CPUDETECT
|
|
mp_msg(MSGT_CPLAYER,MSGL_INFO,"Compiled with RUNTIME CPU Detection - warning, it's untested!\n");
|
|
#else
|
|
mp_msg(MSGT_CPLAYER,MSGL_INFO,"Compiled for x86 CPU with features:");
|
|
#ifdef HAVE_MMX
|
|
mp_msg(MSGT_CPLAYER,MSGL_INFO," MMX");
|
|
#endif
|
|
#ifdef HAVE_MMX2
|
|
mp_msg(MSGT_CPLAYER,MSGL_INFO," MMX2");
|
|
#endif
|
|
#ifdef HAVE_3DNOW
|
|
mp_msg(MSGT_CPLAYER,MSGL_INFO," 3DNow");
|
|
#endif
|
|
#ifdef HAVE_3DNOWEX
|
|
mp_msg(MSGT_CPLAYER,MSGL_INFO," 3DNowEx");
|
|
#endif
|
|
#ifdef HAVE_SSE
|
|
mp_msg(MSGT_CPLAYER,MSGL_INFO," SSE");
|
|
#endif
|
|
mp_msg(MSGT_CPLAYER,MSGL_INFO,"\n");
|
|
#endif
|
|
|
|
#endif
|
|
|
|
if ( argv[0] )
|
|
if(!strcmp(argv[0],"gmplayer") ||
|
|
(strrchr(argv[0],'/') && !strcmp(strrchr(argv[0],'/'),"/gmplayer") ) )
|
|
use_gui=1;
|
|
|
|
playtree = play_tree_new();
|
|
|
|
mconfig = m_config_new(playtree);
|
|
m_config_register_options(mconfig,mplayer_opts);
|
|
// TODO : add something to let modules register their options
|
|
mp_register_options(mconfig);
|
|
parse_cfgfiles(mconfig);
|
|
|
|
|
|
|
|
if(m_config_parse_command_line(mconfig, argc, argv, envp) < 0) exit(1); // error parsing cmdline
|
|
|
|
playtree = play_tree_cleanup(playtree);
|
|
if(playtree) {
|
|
playtree_iter = play_tree_iter_new(playtree,mconfig);
|
|
if(playtree_iter) {
|
|
if(play_tree_iter_step(playtree_iter,0,0) != PLAY_TREE_ITER_ENTRY) {
|
|
play_tree_iter_free(playtree_iter);
|
|
playtree_iter = NULL;
|
|
}
|
|
filename = play_tree_iter_get_file(playtree_iter,1);
|
|
}
|
|
}
|
|
|
|
#ifndef HAVE_NEW_GUI
|
|
if(use_gui){
|
|
mp_msg(MSGT_CPLAYER,MSGL_WARN,MSGTR_NoGui);
|
|
use_gui=0;
|
|
}
|
|
#else
|
|
if(use_gui && !vo_init()){
|
|
mp_msg(MSGT_CPLAYER,MSGL_WARN,MSGTR_GuiNeedsX);
|
|
use_gui=0;
|
|
}
|
|
#endif
|
|
|
|
#ifndef USE_LIBVO2
|
|
if(video_driver && strcmp(video_driver,"help")==0){
|
|
printf("Available video output drivers:\n");
|
|
i=0;
|
|
while (video_out_drivers[i]) {
|
|
const vo_info_t *info = video_out_drivers[i++]->get_info ();
|
|
printf("\t%s\t%s\n", info->short_name, info->name);
|
|
}
|
|
printf("\n");
|
|
exit(0);
|
|
}
|
|
#endif
|
|
if(audio_driver && strcmp(audio_driver,"help")==0){
|
|
printf("Available audio output drivers:\n");
|
|
i=0;
|
|
while (audio_out_drivers[i]) {
|
|
const ao_info_t *info = audio_out_drivers[i++]->info;
|
|
printf("\t%s\t%s\n", info->short_name, info->name);
|
|
}
|
|
printf("\n");
|
|
exit(0);
|
|
}
|
|
|
|
// check codec.conf
|
|
if(!parse_codec_cfg(get_path("codecs.conf"))){
|
|
if(!parse_codec_cfg(CONFDIR"/codecs.conf")){
|
|
mp_msg(MSGT_CPLAYER,MSGL_HINT,MSGTR_CopyCodecsConf);
|
|
// printf("Exit.\n");
|
|
exit(0); // From unknown reason a hangup occurs here :((((((
|
|
// kill(getpid(),SIGTERM);
|
|
// usleep(20000);
|
|
// kill(getpid(),SIGKILL);
|
|
}
|
|
}
|
|
|
|
if(audio_codec && strcmp(audio_codec,"help")==0){
|
|
printf("Available audio codecs:\n");
|
|
list_codecs(1);
|
|
printf("\n");
|
|
exit(0);
|
|
}
|
|
if(video_codec && strcmp(video_codec,"help")==0){
|
|
printf("Available video codecs:\n");
|
|
list_codecs(0);
|
|
printf("\n");
|
|
exit(0);
|
|
}
|
|
|
|
|
|
if(!filename && !vcd_track && !dvd_title && !tv_param_on){
|
|
if(!use_gui){
|
|
// no file/vcd/dvd -> show HELP:
|
|
printf("%s",help_text);
|
|
exit(0);
|
|
} else gui_no_filename=1;
|
|
}
|
|
|
|
// Many users forget to include command line in bugreports...
|
|
if(verbose){
|
|
printf("CommandLine:");
|
|
for(i=1;i<argc;i++)printf(" '%s'",argv[i]);
|
|
printf("\n");
|
|
}
|
|
|
|
mp_msg_init(verbose+MSGL_STATUS);
|
|
|
|
//------ load global data first ------
|
|
|
|
|
|
// check font
|
|
#ifdef USE_OSD
|
|
if(font_name){
|
|
vo_font=read_font_desc(font_name,font_factor,verbose>1);
|
|
if(!vo_font) mp_msg(MSGT_CPLAYER,MSGL_ERR,MSGTR_CantLoadFont,font_name);
|
|
} else {
|
|
// try default:
|
|
vo_font=read_font_desc(get_path("font/font.desc"),font_factor,verbose>1);
|
|
if(!vo_font)
|
|
vo_font=read_font_desc(DATADIR"/font/font.desc",font_factor,verbose>1);
|
|
}
|
|
#endif
|
|
|
|
// It's time to init the GUI code: (and fork() the GTK process)
|
|
#ifdef HAVE_NEW_GUI
|
|
if(use_gui){
|
|
appInit( argc,argv,envp,(void*)mDisplay );
|
|
inited_flags|=INITED_GUI;
|
|
mplShMem->Playing= (gui_no_filename) ? 0 : 1;
|
|
mplState();
|
|
}
|
|
#endif
|
|
|
|
#if defined(HAVE_LIRC) && ! defined(HAVE_NEW_INPUT)
|
|
lirc_mp_setup();
|
|
inited_flags|=INITED_LIRC;
|
|
#endif
|
|
|
|
#ifdef HAVE_RTC
|
|
if ((rtc_fd = open("/dev/rtc", O_RDONLY)) < 0)
|
|
perror ("Linux RTC init: open");
|
|
else {
|
|
unsigned long irqp;
|
|
|
|
/* if (ioctl(rtc_fd, RTC_IRQP_SET, _) < 0) { */
|
|
if (ioctl(rtc_fd, RTC_IRQP_READ, &irqp) < 0) {
|
|
perror ("Linux RTC init: ioctl (rtc_irqp_read)");
|
|
close (rtc_fd);
|
|
rtc_fd = -1;
|
|
} else if (ioctl(rtc_fd, RTC_PIE_ON, 0) < 0) {
|
|
/* variable only by the root */
|
|
perror ("Linux RTC init: ioctl (rtc_pie_on)");
|
|
close (rtc_fd);
|
|
rtc_fd = -1;
|
|
} else
|
|
printf("Using Linux's hardware RTC timing (%ldHz)\n", irqp);
|
|
}
|
|
#ifdef HAVE_NEW_GUI
|
|
// breaks DGA and SVGAlib and VESA drivers: --A'rpi
|
|
// and now ? -- Pontscho
|
|
if(use_gui) setuid( getuid() ); // strongly test, please check this.
|
|
#endif
|
|
if(rtc_fd<0)
|
|
#endif
|
|
printf("Using %s timing\n",softsleep?"software":"usleep()");
|
|
|
|
#ifdef USE_TERMCAP
|
|
if ( !use_gui ) load_termcap(NULL); // load key-codes
|
|
#endif
|
|
|
|
// ========== Init keyboard FIFO (connection to libvo) ============
|
|
make_pipe(&keyb_fifo_get,&keyb_fifo_put);
|
|
|
|
// Init input system
|
|
#ifdef HAVE_NEW_INPUT
|
|
current_module = "init_input";
|
|
mp_input_init();
|
|
if(keyb_fifo_get > 0)
|
|
mp_input_add_key_fd(keyb_fifo_get,1,NULL,NULL);
|
|
if(slave_mode)
|
|
mp_input_add_cmd_fd(0,1,NULL,NULL);
|
|
else
|
|
mp_input_add_key_fd(0,1,NULL,NULL);
|
|
inited_flags|=INITED_INPUT;
|
|
current_module = NULL;
|
|
#endif
|
|
|
|
|
|
//========= Catch terminate signals: ================
|
|
// terminate requests:
|
|
signal(SIGTERM,exit_sighandler); // kill
|
|
signal(SIGHUP,exit_sighandler); // kill -HUP / xterm closed
|
|
|
|
signal(SIGINT,exit_sighandler); // Interrupt from keyboard
|
|
|
|
signal(SIGQUIT,exit_sighandler); // Quit from keyboard
|
|
// fatal errors:
|
|
signal(SIGBUS,exit_sighandler); // bus error
|
|
signal(SIGSEGV,exit_sighandler); // segfault
|
|
signal(SIGILL,exit_sighandler); // illegal instruction
|
|
signal(SIGFPE,exit_sighandler); // floating point exc.
|
|
signal(SIGABRT,exit_sighandler); // abort()
|
|
|
|
// ******************* Now, let's see the per-file stuff ********************
|
|
|
|
play_next_file:
|
|
|
|
#ifdef HAVE_NEW_GUI
|
|
if ( use_gui ) {
|
|
|
|
#ifdef USE_DVDREAD
|
|
if ( mplShMem->DVDChanged )
|
|
{
|
|
mplShMem->DVDChanged=0;
|
|
mplShMem->Playing=1;
|
|
filename="/dev/dvd";
|
|
goto play_dvd;
|
|
}
|
|
#endif
|
|
|
|
if(filename && !mplShMem->FilenameChanged) strcpy( mplShMem->Filename,filename );
|
|
// mplShMem->Playing= (gui_no_filename) ? 0 : 1;
|
|
while(mplShMem->Playing!=1){
|
|
usleep(20000);
|
|
EventHandling();
|
|
}
|
|
|
|
play_dvd:
|
|
|
|
#ifdef USE_SUB
|
|
if ( mplShMem->SubtitleChanged || !mplShMem->FilenameChanged )
|
|
{
|
|
if ( mplShMem->Subtitlename[0] != 0 ) sub_name=mplShMem->Subtitlename;
|
|
mplShMem->SubtitleChanged=0;
|
|
}
|
|
#endif
|
|
|
|
if ( mplShMem->FilenameChanged || !filename )
|
|
{
|
|
filename=mplShMem->Filename;
|
|
mplShMem->FilenameChanged=0;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if(filename) mp_msg(MSGT_CPLAYER,MSGL_INFO,MSGTR_Playing, filename);
|
|
|
|
#ifdef USE_SUB_OLD
|
|
// check .sub
|
|
if(sub_name){
|
|
#if 0
|
|
int l=strlen(sub_name);
|
|
if ((l>4) && ((0==strcmp(&sub_name[l-4],".utf"))
|
|
||(0==strcmp(&sub_name[l-4],".UTF"))))
|
|
sub_utf8=1;
|
|
#endif
|
|
subtitles=sub_read_file(sub_name);
|
|
if(!subtitles || sub_num == 0) mp_msg(MSGT_CPLAYER,MSGL_ERR,MSGTR_CantLoadSub,sub_name);
|
|
}
|
|
if(!sub_name){
|
|
if(sub_auto && filename) { // auto load sub file ...
|
|
subtitles=sub_read_file( sub_filename( get_path("sub/"), filename ) );
|
|
}
|
|
#if 0
|
|
if(!subtitles) subtitles=sub_read_file(get_path("default.sub")); // try default
|
|
#endif
|
|
}
|
|
|
|
if(subtitles && stream_dump_type==3) list_sub_file(subtitles);
|
|
if(subtitles && stream_dump_type==4) dump_mpsub(subtitles, fps);
|
|
#endif
|
|
|
|
current_module="vobsub";
|
|
if (vobsub_name){
|
|
vo_vobsub=vobsub_open(vobsub_name);
|
|
if(vo_vobsub==NULL)
|
|
mp_msg(MSGT_CPLAYER,MSGL_ERR,MSGTR_CantLoadSub,vobsub_name);
|
|
}
|
|
|
|
stream=NULL;
|
|
demuxer=NULL;
|
|
d_audio=NULL;
|
|
d_video=NULL;
|
|
sh_audio=NULL;
|
|
sh_video=NULL;
|
|
|
|
#ifdef USE_LIBVO2
|
|
current_module="vo2_new";
|
|
video_out=vo2_new(video_driver);
|
|
current_module=NULL;
|
|
#else
|
|
// check video_out driver name:
|
|
if (video_driver)
|
|
if ((i = strcspn(video_driver, ":")) > 0)
|
|
{
|
|
size_t i2 = strlen(video_driver);
|
|
|
|
if (video_driver[i] == ':')
|
|
{
|
|
vo_subdevice = malloc(i2-i);
|
|
if (vo_subdevice != NULL)
|
|
strncpy(vo_subdevice, (char *)(video_driver+i+1), i2-i);
|
|
video_driver[i] = '\0';
|
|
}
|
|
// printf("video_driver: %s, subdevice: %s\n", video_driver, vo_subdevice);
|
|
}
|
|
if(!video_driver)
|
|
video_out=video_out_drivers[0];
|
|
else
|
|
for (i=0; video_out_drivers[i] != NULL; i++){
|
|
const vo_info_t *info = video_out_drivers[i]->get_info ();
|
|
if(strcmp(info->short_name,video_driver) == 0){
|
|
video_out = video_out_drivers[i];break;
|
|
}
|
|
}
|
|
#endif
|
|
if(!video_out){
|
|
mp_msg(MSGT_CPLAYER,MSGL_FATAL,MSGTR_InvalidVOdriver,video_driver?video_driver:"?");
|
|
exit_player(MSGTR_Exit_error);
|
|
}
|
|
if((i=video_out->preinit(vo_subdevice))!=0)
|
|
{
|
|
mp_msg(MSGT_CPLAYER,MSGL_FATAL,"error on vo preinit = %u\n",i);
|
|
exit_player(MSGTR_Exit_error);
|
|
}
|
|
// check audio_out driver name:
|
|
if (audio_driver)
|
|
if ((i = strcspn(audio_driver, ":")) > 0)
|
|
{
|
|
size_t i2 = strlen(audio_driver);
|
|
|
|
if (audio_driver[i] == ':')
|
|
{
|
|
ao_subdevice = malloc(i2-i);
|
|
if (ao_subdevice != NULL)
|
|
strncpy(ao_subdevice, (char *)(audio_driver+i+1), i2-i);
|
|
audio_driver[i] = '\0';
|
|
}
|
|
// printf("audio_driver: %s, subdevice: %s\n", audio_driver, ao_subdevice);
|
|
}
|
|
if(!audio_driver)
|
|
audio_out=audio_out_drivers[0];
|
|
else
|
|
for (i=0; audio_out_drivers[i] != NULL; i++){
|
|
const ao_info_t *info = audio_out_drivers[i]->info;
|
|
if(strcmp(info->short_name,audio_driver) == 0){
|
|
audio_out = audio_out_drivers[i];break;
|
|
}
|
|
}
|
|
if (!audio_out){
|
|
mp_msg(MSGT_CPLAYER,MSGL_FATAL,MSGTR_InvalidAOdriver,audio_driver);
|
|
exit_player(MSGTR_Exit_error);
|
|
}
|
|
/* Initailize audio plugin interface if used */
|
|
if(ao_plugin_cfg.plugin_list){
|
|
for (i=0; audio_out_drivers[i] != NULL; i++){
|
|
const ao_info_t *info = audio_out_drivers[i]->info;
|
|
if(strcmp(info->short_name,"plugin") == 0){
|
|
audio_out_drivers[i]->control(AOCONTROL_SET_PLUGIN_DRIVER,(int)audio_out);
|
|
audio_out = audio_out_drivers[i];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
current_module="open_stream";
|
|
stream=open_stream(filename,vcd_track,&file_format);
|
|
if(!stream) { // error...
|
|
uninit_player(inited_flags-(INITED_GUI+INITED_LIRC+INITED_INPUT));
|
|
goto goto_next_file_src;
|
|
}
|
|
inited_flags|=INITED_STREAM;
|
|
if(stream->type == STREAMTYPE_PLAYLIST) {
|
|
play_tree_t* entry;
|
|
// Handle playlist
|
|
mp_msg(MSGT_CPLAYER,MSGL_V,"Parsing playlist %s...\n",filename);
|
|
entry = parse_playtree(stream);
|
|
if(!entry) {
|
|
entry = playtree_iter->tree;
|
|
if(play_tree_iter_step(playtree_iter,1,0) != PLAY_TREE_ITER_ENTRY)
|
|
goto goto_next_file;
|
|
if(playtree_iter->tree == entry) { // Loop with a single file
|
|
if(play_tree_iter_up_step(playtree_iter,1,0) != PLAY_TREE_ITER_ENTRY)
|
|
goto goto_next_file;
|
|
}
|
|
play_tree_remove(entry,1,1);
|
|
uninit_player(inited_flags-(INITED_GUI+INITED_LIRC+INITED_INPUT));
|
|
goto goto_next_file_src;
|
|
}
|
|
play_tree_insert_entry(playtree_iter->tree,entry);
|
|
entry = playtree_iter->tree;
|
|
if(play_tree_iter_step(playtree_iter,1,0) != PLAY_TREE_ITER_ENTRY)
|
|
goto goto_next_file;
|
|
play_tree_remove(entry,1,1);
|
|
uninit_player(inited_flags-(INITED_GUI+INITED_LIRC+INITED_INPUT));
|
|
goto goto_next_file_src;
|
|
}
|
|
stream->start_pos+=seek_to_byte;
|
|
|
|
if(stream_dump_type==5){
|
|
unsigned char buf[4096];
|
|
int len;
|
|
FILE *f;
|
|
current_module="dump";
|
|
stream_reset(stream);
|
|
stream_seek(stream,stream->start_pos);
|
|
f=fopen(stream_dump_name,"wb");
|
|
if(!f){
|
|
mp_msg(MSGT_CPLAYER,MSGL_FATAL,MSGTR_CantOpenDumpfile);
|
|
exit_player(MSGTR_Exit_error);
|
|
}
|
|
while(!stream->eof){
|
|
len=stream_read(stream,buf,4096);
|
|
if(len>0) fwrite(buf,len,1,f);
|
|
}
|
|
fclose(f);
|
|
mp_msg(MSGT_CPLAYER,MSGL_INFO,MSGTR_CoreDumped);
|
|
exit_player(MSGTR_Exit_eof);
|
|
}
|
|
|
|
#ifdef USE_DVDREAD
|
|
current_module="dvd lang->id";
|
|
if(audio_lang && audio_id==-1) audio_id=dvd_aid_from_lang(stream,audio_lang);
|
|
if(dvdsub_lang && dvdsub_id==-1) dvdsub_id=dvd_sid_from_lang(stream,dvdsub_lang);
|
|
current_module=NULL;
|
|
#endif
|
|
|
|
// initial prefill: 20% later: 5% (should be set by -cacheopts)
|
|
if(stream_cache_size) stream_enable_cache(stream,stream_cache_size*1024,stream_cache_size*1024/5,stream_cache_size*1024/20);
|
|
|
|
#ifdef HAVE_NEW_INPUT
|
|
if(!slave_mode && filename && !use_stdin && !strcmp(filename,"-")) {
|
|
mp_input_rm_key_fd(0);
|
|
use_stdin = 1;
|
|
}
|
|
else if(!slave_mode && use_stdin && (!filename || strcmp(filename,"-"))) {
|
|
mp_input_add_key_fd(0,1,NULL,NULL);
|
|
use_stdin = 0;
|
|
}
|
|
#else
|
|
use_stdin=filename && (!strcmp(filename,"-"));
|
|
#endif
|
|
|
|
#ifdef HAVE_LIBCSS
|
|
current_module="libcss";
|
|
if (dvdimportkey) {
|
|
if (dvd_import_key(dvdimportkey)) {
|
|
mp_msg(MSGT_CPLAYER,MSGL_FATAL,MSGTR_ErrorDVDkey);
|
|
exit_player(MSGTR_Exit_error);
|
|
}
|
|
mp_msg(MSGT_CPLAYER,MSGL_INFO,MSGTR_CmdlineDVDkey);
|
|
}
|
|
if (dvd_auth_device) {
|
|
// if (dvd_auth(dvd_auth_device,f)) {
|
|
if (dvd_auth(dvd_auth_device,filename)) {
|
|
mp_msg(MSGT_CPLAYER,MSGL_FATAL,"Error in DVD auth...\n");
|
|
exit_player(MSGTR_Exit_error);
|
|
}
|
|
mp_msg(MSGT_CPLAYER,MSGL_INFO,MSGTR_DVDauthOk);
|
|
}
|
|
#endif
|
|
|
|
//============ Open & Sync stream and detect file format ===============
|
|
|
|
|
|
if(!has_audio) audio_id=-2; // do NOT read audio packets...
|
|
|
|
current_module="demux_open";
|
|
|
|
demuxer=demux_open(stream,file_format,audio_id,video_id,dvdsub_id);
|
|
if(!demuxer) goto goto_next_file; // exit_player(MSGTR_Exit_error); // ERROR
|
|
|
|
//file_format=demuxer->file_format;
|
|
|
|
d_audio=demuxer->audio;
|
|
d_video=demuxer->video;
|
|
d_dvdsub=demuxer->sub;
|
|
|
|
// DUMP STREAMS:
|
|
if((stream_dump_type)&&(stream_dump_type!=4)){
|
|
FILE *f;
|
|
demux_stream_t *ds=NULL;
|
|
current_module="dump";
|
|
// select stream to dump
|
|
switch(stream_dump_type){
|
|
case 1: ds=d_audio;break;
|
|
case 2: ds=d_video;break;
|
|
case 3: ds=d_dvdsub;break;
|
|
}
|
|
if(!ds){
|
|
mp_msg(MSGT_CPLAYER,MSGL_FATAL,MSGTR_DumpSelectedSteramMissing);
|
|
exit_player(MSGTR_Exit_error);
|
|
}
|
|
// disable other streams:
|
|
if(d_audio && d_audio!=ds) {ds_free_packs(d_audio); d_audio->id=-2; }
|
|
if(d_video && d_video!=ds) {ds_free_packs(d_video); d_video->id=-2; }
|
|
if(d_dvdsub && d_dvdsub!=ds) {ds_free_packs(d_dvdsub); d_dvdsub->id=-2; }
|
|
// let's dump it!
|
|
f=fopen(stream_dump_name,"wb");
|
|
if(!f){
|
|
mp_msg(MSGT_CPLAYER,MSGL_FATAL,MSGTR_CantOpenDumpfile);
|
|
exit_player(MSGTR_Exit_error);
|
|
}
|
|
while(!ds->eof){
|
|
unsigned char* start;
|
|
int in_size=ds_get_packet(ds,&start);
|
|
if( (demuxer->file_format==DEMUXER_TYPE_AVI || demuxer->file_format==DEMUXER_TYPE_ASF || demuxer->file_format==DEMUXER_TYPE_MOV)
|
|
&& stream_dump_type==2) fwrite(&in_size,1,4,f);
|
|
if(in_size>0) fwrite(start,in_size,1,f);
|
|
}
|
|
fclose(f);
|
|
mp_msg(MSGT_CPLAYER,MSGL_INFO,MSGTR_CoreDumped);
|
|
exit_player(MSGTR_Exit_eof);
|
|
}
|
|
|
|
sh_audio=d_audio->sh;
|
|
sh_video=d_video->sh;
|
|
|
|
#ifdef HAVE_NEW_GUI
|
|
#ifdef USE_DVDREAD
|
|
if ( use_gui && stream->type == STREAMTYPE_DVD )
|
|
{
|
|
dvd_priv_t * dvdp = stream->priv;
|
|
mplShMem->DVD.titles=dvdp->vmg_file->tt_srpt->nr_of_srpts;
|
|
mplShMem->DVD.chapters=dvdp->vmg_file->tt_srpt->title[dvd_title].nr_of_ptts;
|
|
mplShMem->DVD.angles=dvdp->vmg_file->tt_srpt->title[dvd_title].nr_of_angles;
|
|
mplShMem->DVD.nr_of_audio_channels=dvdp->nr_of_channels;
|
|
memcpy( mplShMem->DVD.audio_streams,dvdp->audio_streams,sizeof( dvdp->audio_streams ) );
|
|
mplShMem->DVD.nr_of_subtitles=dvdp->nr_of_subtitles;
|
|
memcpy( mplShMem->DVD.subtitles,dvdp->subtitles,sizeof( dvdp->subtitles ) );
|
|
mplShMem->DVD.current_title=dvd_title + 1;
|
|
mplShMem->DVD.current_chapter=dvd_chapter + 1;
|
|
mplShMem->DVD.current_angle=dvd_angle + 1;
|
|
mplShMem->Track=dvd_title + 1;
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
current_module="video_read_properties";
|
|
|
|
if(sh_video){
|
|
|
|
if(!video_read_properties(sh_video)) {
|
|
mp_msg(MSGT_CPLAYER,MSGL_ERR,"Video: can't read properties\n");
|
|
sh_video=d_video->sh=NULL;
|
|
} else {
|
|
mp_msg(MSGT_CPLAYER,MSGL_INFO,"[V] filefmt:%d fourcc:0x%X size:%dx%d fps:%5.2f ftime:=%6.4f\n",
|
|
demuxer->file_format,sh_video->format, sh_video->disp_w,sh_video->disp_h,
|
|
sh_video->fps,sh_video->frametime
|
|
);
|
|
|
|
vo_fps = sh_video->fps;
|
|
/* need to set fps here for output encoders to pick it up in their init */
|
|
if(force_fps){
|
|
sh_video->fps=force_fps;
|
|
sh_video->frametime=1.0f/sh_video->fps;
|
|
vo_fps = force_fps;
|
|
}
|
|
|
|
if(!sh_video->fps && !force_fps){
|
|
mp_msg(MSGT_CPLAYER,MSGL_ERR,MSGTR_FPSnotspecified);
|
|
sh_video=d_video->sh=NULL;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
fflush(stdout);
|
|
|
|
if(!sh_video && !sh_audio){
|
|
mp_msg(MSGT_CPLAYER,MSGL_FATAL,"No stream found\n");
|
|
goto goto_next_file; // exit_player(MSGTR_Exit_error);
|
|
}
|
|
|
|
if(!sh_video) goto init_audio;
|
|
|
|
#ifdef USE_DVDREAD
|
|
current_module="spudec";
|
|
vo_spudec=spudec_new_scaled(stream->type==STREAMTYPE_DVD?((dvd_priv_t *)(stream->priv))->cur_pgc->palette:NULL,
|
|
sh_video->disp_w, sh_video->disp_h);
|
|
if (vo_spudec!=NULL)
|
|
inited_flags|=INITED_SPUDEC;
|
|
current_module=NULL;
|
|
#endif
|
|
|
|
#ifdef USE_SUB
|
|
// after reading video params we should load subtitles because
|
|
// we know fps so now we can adjust subtitles time to ~6 seconds AST
|
|
// check .sub
|
|
current_module="read_subtitles_file";
|
|
if(sub_name){
|
|
#if 0
|
|
int l=strlen(sub_name);
|
|
if ((l>4) && ((0==strcmp(&sub_name[l-4],".utf"))
|
|
||(0==strcmp(&sub_name[l-4],".UTF"))))
|
|
sub_utf8=1;
|
|
#endif
|
|
subtitles=sub_read_file(sub_name, sh_video->fps);
|
|
if(!subtitles || sub_num == 0) mp_msg(MSGT_CPLAYER,MSGL_ERR,MSGTR_CantLoadSub,sub_name);
|
|
}
|
|
if(!sub_name){
|
|
if(sub_auto && filename) { // auto load sub file ...
|
|
subtitles=sub_read_file( sub_filename( get_path("sub/"), filename ),
|
|
sh_video->fps );
|
|
}
|
|
#if 0
|
|
if(!subtitles) subtitles=sub_read_file(get_path("default.sub"),
|
|
sh_video->fps); // try default
|
|
#endif
|
|
}
|
|
|
|
if(subtitles && stream_dump_type==3) list_sub_file(subtitles);
|
|
if(subtitles && stream_dump_type==4) dump_mpsub(subtitles, sh_video->fps);
|
|
#endif
|
|
|
|
//================== Init AUDIO (codec) ==========================
|
|
init_audio:
|
|
current_module="init_audio_codec";
|
|
|
|
/* display clip info */
|
|
demux_info_print(demuxer);
|
|
|
|
if(sh_audio){
|
|
// Go through the codec.conf and find the best codec...
|
|
sh_audio->codec=NULL;
|
|
if(audio_family!=-1) mp_msg(MSGT_CPLAYER,MSGL_INFO,MSGTR_TryForceAudioFmt,audio_family);
|
|
while(1){
|
|
sh_audio->codec=find_codec(sh_audio->format,NULL,sh_audio->codec,1);
|
|
if(!sh_audio->codec){
|
|
if(audio_family!=-1) {
|
|
sh_audio->codec=NULL; /* re-search */
|
|
mp_msg(MSGT_CPLAYER,MSGL_ERR,MSGTR_CantFindAfmtFallback);
|
|
audio_family=-1;
|
|
continue;
|
|
}
|
|
mp_msg(MSGT_CPLAYER,MSGL_ERR,MSGTR_CantFindAudioCodec,sh_audio->format);
|
|
mp_msg(MSGT_CPLAYER,MSGL_HINT, MSGTR_TryUpgradeCodecsConfOrRTFM,get_path("codecs.conf"));
|
|
sh_audio=d_audio->sh=NULL;
|
|
break;
|
|
}
|
|
if(audio_codec && strcmp(sh_audio->codec->name,audio_codec)) continue;
|
|
else if(audio_family!=-1 && sh_audio->codec->driver!=audio_family) continue;
|
|
mp_msg(MSGT_CPLAYER,MSGL_INFO,"%s audio codec: [%s] drv:%d (%s)\n",audio_codec?"Forcing":"Detected",sh_audio->codec->name,sh_audio->codec->driver,sh_audio->codec->info);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(sh_audio){
|
|
mp_msg(MSGT_CPLAYER,MSGL_V,"Initializing audio codec...\n");
|
|
if(!init_audio(sh_audio)){
|
|
mp_msg(MSGT_CPLAYER,MSGL_ERR,MSGTR_CouldntInitAudioCodec);
|
|
sh_audio=d_audio->sh=NULL;
|
|
#ifdef HAVE_NEW_GUI
|
|
if ( use_gui ) mplShMem->AudioType=0;
|
|
#endif
|
|
} else {
|
|
mp_msg(MSGT_CPLAYER,MSGL_INFO,"AUDIO: srate=%d chans=%d bps=%d sfmt=0x%X ratio: %d->%d\n",sh_audio->samplerate,sh_audio->channels,sh_audio->samplesize,
|
|
sh_audio->sample_format,sh_audio->i_bps,sh_audio->o_bps);
|
|
#ifdef HAVE_NEW_GUI
|
|
if ( use_gui ) mplShMem->AudioType=sh_audio->channels;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
//================== Init VIDEO (codec & libvo) ==========================
|
|
if(!sh_video)
|
|
goto main;
|
|
current_module="init_video_codec";
|
|
|
|
// Go through the codec.conf and find the best codec...
|
|
sh_video->codec=NULL;
|
|
if(video_family!=-1) mp_msg(MSGT_CPLAYER,MSGL_INFO,MSGTR_TryForceVideoFmt,video_family);
|
|
{ /* local vars */
|
|
short bestprio=-1;
|
|
struct codecs_st *bestcodec=NULL;
|
|
while(1){
|
|
sh_video->codec=find_codec(sh_video->format,
|
|
sh_video->bih?((unsigned int*) &sh_video->bih->biCompression):NULL,sh_video->codec,0);
|
|
if(!sh_video->codec/* && bestprio==-1*/){
|
|
if(video_family!=-1) {
|
|
//sh_video->codec=NULL; /* re-search */
|
|
mp_msg(MSGT_CPLAYER,MSGL_WARN,MSGTR_CantFindVfmtFallback);
|
|
video_family=-1;
|
|
continue;
|
|
}
|
|
if(bestprio==-1 || !video_codec) {
|
|
mp_msg(MSGT_CPLAYER,MSGL_ERR,MSGTR_CantFindVideoCodec,sh_video->format);
|
|
mp_msg(MSGT_CPLAYER,MSGL_HINT, MSGTR_TryUpgradeCodecsConfOrRTFM,get_path("codecs.conf"));
|
|
sh_video = d_video->sh = NULL;
|
|
goto main; // exit_player(MSGTR_Exit_error);
|
|
}
|
|
} else {
|
|
// is next line needed anymore? - atmos ::
|
|
if(!allow_dshow && sh_video->codec->driver==VFM_DSHOW) continue; // skip DShow
|
|
else if(video_codec && strcmp(sh_video->codec->name,video_codec)) continue;
|
|
else if(video_family!=-1 && sh_video->codec->driver!=video_family) continue;
|
|
else if(video_family==-1 && !video_codec && sh_video->codec->priority) {
|
|
if(sh_video->codec->priority > bestprio) {
|
|
//printf("\n\n!!! setting bestprio from %d to %d for %s!!!\n\n", bestprio, sh_video->codec->priority, sh_video->codec->name);
|
|
bestprio=sh_video->codec->priority;
|
|
bestcodec=sh_video->codec;
|
|
}
|
|
continue;
|
|
}
|
|
} /* sh_video->codec */
|
|
break;
|
|
}
|
|
if(bestprio!=-1) {
|
|
//printf("chose codec %s by priority.\n", bestcodec->name);
|
|
sh_video->codec=bestcodec;
|
|
}
|
|
|
|
} /* end local vars */
|
|
|
|
mp_msg(MSGT_CPLAYER,MSGL_INFO,"%s video codec: [%s] drv:%d prio:%d (%s)\n",video_codec?"Forcing":"Detected",sh_video->codec->name,sh_video->codec->driver,sh_video->codec->priority!=-1?sh_video->codec->priority:0,sh_video->codec->info);
|
|
|
|
for(i=0;i<CODECS_MAX_OUTFMT;i++){
|
|
// int ret;
|
|
out_fmt=sh_video->codec->outfmt[i];
|
|
if(out_fmt==(signed int)0xFFFFFFFF) continue;
|
|
#ifdef USE_LIBVO2
|
|
vo_flags=vo2_query_format(video_out);
|
|
#else
|
|
vo_flags=video_out->control(VOCTRL_QUERY_FORMAT, &out_fmt);
|
|
#endif
|
|
mp_msg(MSGT_CPLAYER,MSGL_DBG2,"vo_debug: query(%s) returned 0x%X\n",vo_format_name(out_fmt),vo_flags);
|
|
if(vo_flags) break;
|
|
}
|
|
if(i>=CODECS_MAX_OUTFMT){
|
|
mp_msg(MSGT_CPLAYER,MSGL_FATAL,MSGTR_VOincompCodec);
|
|
goto goto_next_file; // exit_player(MSGTR_Exit_error);
|
|
}
|
|
sh_video->outfmtidx=i;
|
|
|
|
if(flip==-1){
|
|
// autodetect flipping
|
|
flip=0;
|
|
if(sh_video->codec->outflags[i]&CODECS_FLAG_FLIP)
|
|
if(!(sh_video->codec->outflags[i]&CODECS_FLAG_NOFLIP))
|
|
flip=1;
|
|
}
|
|
|
|
mp_msg(MSGT_CPLAYER,MSGL_DBG2,"vo_debug1: out_fmt=%s\n",vo_format_name(out_fmt));
|
|
|
|
if(!init_video(sh_video,&vtune.pitch[0])){
|
|
mp_msg(MSGT_CPLAYER,MSGL_FATAL,MSGTR_CouldntInitVideoCodec);
|
|
goto goto_next_file; // exit_player(MSGTR_Exit_error);
|
|
}
|
|
|
|
if(auto_quality>0){
|
|
// Auto quality option enabled
|
|
output_quality=get_video_quality_max(sh_video);
|
|
if(auto_quality>output_quality) auto_quality=output_quality;
|
|
else output_quality=auto_quality;
|
|
mp_msg(MSGT_CPLAYER,MSGL_V,"AutoQ: setting quality to %d\n",output_quality);
|
|
set_video_quality(sh_video,output_quality);
|
|
}
|
|
|
|
// ========== Init display (sh_video->disp_w*sh_video->disp_h/out_fmt) ============
|
|
|
|
current_module="init_libvo";
|
|
|
|
#if 0 /* was X11_FULLSCREEN hack -> moved to libvo/vo_xv.c where it belongs ::atmos */
|
|
if(fullscreen){
|
|
if(vo_init()){
|
|
//if(verbose) printf("X11 running at %dx%d depth: %d\n",vo_screenwidth,vo_screenheight,vo_depthonscreen);
|
|
}
|
|
if(!screen_size_xy) screen_size_xy=vo_screenwidth; // scale with asp.ratio
|
|
}
|
|
#endif
|
|
|
|
// Set default VGA 1:1 aspect as fallback ::atmos
|
|
if(movie_aspect>-1.0) sh_video->aspect = movie_aspect; // cmdline overrides autodetect
|
|
// if(!sh_video->aspect) sh_video->aspect=1.0;
|
|
screen_size_x = opt_screen_size_x;
|
|
screen_size_y = opt_screen_size_y;
|
|
if(screen_size_xy||screen_size_x||screen_size_y){
|
|
if(screen_size_xy>0){
|
|
if(screen_size_xy<=8){
|
|
screen_size_x=screen_size_xy*sh_video->disp_w;
|
|
screen_size_y=screen_size_xy*sh_video->disp_h;
|
|
} else {
|
|
screen_size_x=screen_size_xy;
|
|
screen_size_y=screen_size_xy*sh_video->disp_h/sh_video->disp_w;
|
|
}
|
|
} else if(!vidmode){
|
|
if(!screen_size_x) screen_size_x=SCREEN_SIZE_X;
|
|
if(!screen_size_y) screen_size_y=SCREEN_SIZE_Y;
|
|
if(screen_size_x<=8) screen_size_x*=sh_video->disp_w;
|
|
if(screen_size_y<=8) screen_size_y*=sh_video->disp_h;
|
|
}
|
|
} else {
|
|
// check source format aspect, calculate prescale ::atmos
|
|
screen_size_x=sh_video->disp_w;
|
|
screen_size_y=sh_video->disp_h;
|
|
if(sh_video->aspect>0.01){
|
|
mp_msg(MSGT_CPLAYER,MSGL_INFO,"Movie-Aspect is %.2f:1 - prescaling to correct movie aspect.\n",
|
|
sh_video->aspect);
|
|
screen_size_x=(int)((float)sh_video->disp_h*sh_video->aspect);
|
|
screen_size_x+=screen_size_x%2; // round
|
|
if(screen_size_x<sh_video->disp_w){
|
|
screen_size_x=sh_video->disp_w;
|
|
screen_size_y=(int)((float)sh_video->disp_w*(1.0/sh_video->aspect));
|
|
screen_size_y+=screen_size_y%2; // round
|
|
}
|
|
} else {
|
|
mp_msg(MSGT_CPLAYER,MSGL_INFO,"Movie-Aspect is undefined - no prescaling applied.\n");
|
|
}
|
|
}
|
|
|
|
#ifndef USE_LIBVO2
|
|
{ const vo_info_t *info = video_out->get_info();
|
|
mp_msg(MSGT_CPLAYER,MSGL_INFO,"VO: [%s] %dx%d => %dx%d %s %s%s%s%s\n",info->short_name,
|
|
sh_video->disp_w,sh_video->disp_h,
|
|
screen_size_x,screen_size_y,
|
|
vo_format_name(out_fmt),
|
|
fullscreen?"fs ":"",
|
|
vidmode?"vm ":"",
|
|
softzoom?"zoom ":"",
|
|
(flip==1)?"flip ":""
|
|
// fullscreen|(vidmode<<1)|(softzoom<<2)|(flip<<3)
|
|
);
|
|
mp_msg(MSGT_CPLAYER,MSGL_V,"VO: Description: %s\n",info->name);
|
|
mp_msg(MSGT_CPLAYER,MSGL_V,"VO: Author: %s\n", info->author);
|
|
if(strlen(info->comment) > 0)
|
|
mp_msg(MSGT_CPLAYER,MSGL_V,"VO: Comment: %s\n", info->comment);
|
|
}
|
|
#endif
|
|
|
|
#ifdef HAVE_NEW_GUI
|
|
if ( use_gui )
|
|
{
|
|
mplResizeToMovieSize( sh_video->disp_w,sh_video->disp_h );
|
|
moviewidth=sh_video->disp_w;
|
|
movieheight=sh_video->disp_h;
|
|
mplShMem->StreamType=stream->type;
|
|
mplSetFileName( filename );
|
|
}
|
|
#endif
|
|
|
|
mp_msg(MSGT_CPLAYER,MSGL_V,"video_out->init(%dx%d->%dx%d,flags=%d,'%s',0x%X)\n",
|
|
sh_video->disp_w,sh_video->disp_h,
|
|
screen_size_x,screen_size_y,
|
|
fullscreen|(vidmode<<1)|(softzoom<<2)|(flip<<3),
|
|
title,out_fmt);
|
|
|
|
#ifdef USE_LIBVO2
|
|
if(!vo2_start(video_out,
|
|
sh_video->disp_w,sh_video->disp_h,out_fmt,0,
|
|
fullscreen|(vidmode<<1)|(softzoom<<2)|(flip<<3) )){
|
|
#else
|
|
if(video_out->config(sh_video->disp_w,sh_video->disp_h,
|
|
screen_size_x,screen_size_y,
|
|
fullscreen|(vidmode<<1)|(softzoom<<2)|(flip<<3),
|
|
title,out_fmt,&vtune)){
|
|
#endif
|
|
mp_msg(MSGT_CPLAYER,MSGL_FATAL,MSGTR_CannotInitVO);
|
|
goto goto_next_file; // exit_player(MSGTR_Exit_error);
|
|
}
|
|
inited_flags|=INITED_VO;
|
|
mp_msg(MSGT_CPLAYER,MSGL_V,"INFO: Video OUT driver init OK!\n");
|
|
if(video_out->control(VOCTRL_QUERY_VAA, &vo_vaa)==VO_NOTIMPL)
|
|
memset(&vo_vaa,0,sizeof(vo_vaa_t));
|
|
/*
|
|
get_hw_eq
|
|
*/
|
|
if(vo_vaa.get_video_eq)
|
|
{
|
|
vidix_video_eq_t veq;
|
|
if(vo_vaa.get_video_eq(&veq) == 0)
|
|
{
|
|
v_hw_equ_cap = veq.cap;
|
|
if(veq.cap & VEQ_CAP_BRIGHTNESS) v_bright = veq.brightness/10;
|
|
if(veq.cap & VEQ_CAP_CONTRAST) v_cont = veq.contrast/10;
|
|
if(veq.cap & VEQ_CAP_HUE) v_hue = veq.hue/10;
|
|
if(veq.cap & VEQ_CAP_SATURATION) v_saturation=veq.saturation/10;
|
|
/*
|
|
v_red_intensity=veq.red_intensity/10;
|
|
v_green_intensity=veq.green_intensity/10;
|
|
v_blue_intensity=veq.blue_intensity/10;
|
|
*/
|
|
}
|
|
}
|
|
init_video_vaa(sh_video->disp_w);
|
|
fflush(stdout);
|
|
|
|
//================== MAIN: ==========================
|
|
main:
|
|
if(!sh_video) osd_level = 0;
|
|
{
|
|
|
|
//int frame_corr_num=0; //
|
|
//float v_frame=0; // Video
|
|
float time_frame=0; // Timer
|
|
int force_redraw=0;
|
|
//float num_frames=0; // number of frames played
|
|
int grab_frames=0;
|
|
char osd_text_buffer[64];
|
|
int drop_frame=0;
|
|
int drop_frame_cnt=0;
|
|
int too_slow_frame_cnt=0;
|
|
int too_fast_frame_cnt=0;
|
|
// for auto-quality:
|
|
float AV_delay=0; // average of A-V timestamp differences
|
|
double cvideo_base_vtime;
|
|
double cvideo_base_vframe;
|
|
double vdecode_time;
|
|
unsigned int lastframeout_ts;
|
|
float time_frame_corr_avg=0;
|
|
|
|
//================ SETUP AUDIO ==========================
|
|
current_module="setup_audio";
|
|
|
|
if(sh_audio){
|
|
|
|
const ao_info_t *info=audio_out->info;
|
|
mp_msg(MSGT_CPLAYER,MSGL_INFO,"AO: [%s] %iHz %s %s\n",
|
|
info->short_name,
|
|
force_srate?force_srate:sh_audio->samplerate,
|
|
sh_audio->channels>1?"Stereo":"Mono",
|
|
audio_out_format_name(sh_audio->sample_format)
|
|
);
|
|
mp_msg(MSGT_CPLAYER,MSGL_V,"AO: Description: %s\nAO: Author: %s\n",
|
|
info->name,
|
|
info->author
|
|
);
|
|
if(strlen(info->comment) > 0)
|
|
mp_msg(MSGT_CPLAYER,MSGL_V,"AO: Comment: %s\n", info->comment);
|
|
if(!audio_out->init(force_srate?force_srate:sh_audio->samplerate,
|
|
sh_audio->channels,sh_audio->sample_format,0)){
|
|
mp_msg(MSGT_CPLAYER,MSGL_ERR,MSGTR_CannotInitAO);
|
|
sh_audio=d_audio->sh=NULL;
|
|
if(sh_video == NULL)
|
|
goto goto_next_file;
|
|
} else {
|
|
inited_flags|=INITED_AO;
|
|
}
|
|
|
|
// printf("Audio buffer size: %d bytes, delay: %5.3fs\n",audio_buffer_size,audio_buffer_delay);
|
|
|
|
// fixup audio buffer size:
|
|
// if(outburst<MAX_OUTBURST){
|
|
// sh_audio->a_buffer_size=sh_audio->audio_out_minsize+outburst;
|
|
// printf("Audio out buffer size reduced to %d bytes\n",sh_audio->a_buffer_size);
|
|
// }
|
|
|
|
// sh_audio->timer=-(audio_buffer_delay);
|
|
}
|
|
|
|
if(sh_video) sh_video->timer=0;
|
|
if(sh_audio) sh_audio->timer=-audio_delay;
|
|
|
|
if(!sh_audio){
|
|
mp_msg(MSGT_CPLAYER,MSGL_INFO,MSGTR_NoSound);
|
|
if(verbose) mp_msg(MSGT_CPLAYER,MSGL_V,"Freeing %d unused audio chunks\n",d_audio->packs);
|
|
ds_free_packs(d_audio); // free buffered chunks
|
|
d_audio->id=-2; // do not read audio chunks
|
|
if(audio_out) uninit_player(INITED_AO); // close device
|
|
}
|
|
if(!sh_video){
|
|
mp_msg(MSGT_CPLAYER,MSGL_INFO,"Video: no video!!!\n");
|
|
if(verbose) mp_msg(MSGT_CPLAYER,MSGL_V,"Freeing %d unused video chunks\n",d_video->packs);
|
|
ds_free_packs(d_video);
|
|
d_video->id=-2;
|
|
if(video_out) uninit_player(INITED_VO);
|
|
}
|
|
current_module=NULL;
|
|
|
|
if(demuxer->file_format!=DEMUXER_TYPE_AVI) pts_from_bps=0; // it must be 0 for mpeg/asf!
|
|
if(force_fps){
|
|
vo_fps = sh_video->fps=force_fps;
|
|
sh_video->frametime=1.0f/sh_video->fps;
|
|
mp_msg(MSGT_CPLAYER,MSGL_INFO,MSGTR_FPSforced,sh_video->fps,sh_video->frametime);
|
|
}
|
|
|
|
//==================== START PLAYING =======================
|
|
|
|
mp_msg(MSGT_CPLAYER,MSGL_INFO,MSGTR_StartPlaying);fflush(stdout);
|
|
|
|
if(!use_stdin && !slave_mode){
|
|
getch2_enable(); // prepare stdin for hotkeys...
|
|
inited_flags|=INITED_GETCH2;
|
|
}
|
|
|
|
InitTimer();
|
|
|
|
total_time_usage_start=GetTimer();
|
|
audio_time_usage=0; video_time_usage=0; vout_time_usage=0;
|
|
|
|
while(!eof){
|
|
// unsigned int aq_total_time=GetTimer();
|
|
float aq_sleep_time=0;
|
|
|
|
if(play_n_frames>=0){
|
|
--play_n_frames;
|
|
if(play_n_frames<0) eof = PT_NEXT_ENTRY;
|
|
}
|
|
|
|
/*========================== PLAY AUDIO ============================*/
|
|
while(sh_audio){
|
|
unsigned int t;
|
|
int playsize;
|
|
|
|
ao_data.pts=sh_audio->timer*90000.0;
|
|
playsize=audio_out->get_space();
|
|
|
|
if(!playsize) break; // buffer is full, do not block here!!!
|
|
|
|
if(playsize>MAX_OUTBURST) playsize=MAX_OUTBURST; // we shouldn't exceed it!
|
|
//if(playsize>outburst) playsize=outburst;
|
|
|
|
// Update buffer if needed
|
|
current_module="decode_audio"; // Enter AUDIO decoder module
|
|
t=GetTimer();
|
|
while(sh_audio->a_buffer_len<playsize && !d_audio->eof){
|
|
int ret=decode_audio(sh_audio,&sh_audio->a_buffer[sh_audio->a_buffer_len],
|
|
playsize-sh_audio->a_buffer_len,sh_audio->a_buffer_size-sh_audio->a_buffer_len);
|
|
if(ret>0) sh_audio->a_buffer_len+=ret;
|
|
else {
|
|
if(!sh_video)
|
|
eof = PT_NEXT_ENTRY;
|
|
break;
|
|
}
|
|
}
|
|
current_module=NULL; // Leave AUDIO decoder module
|
|
t=GetTimer()-t;audio_time_usage+=t*0.000001;
|
|
|
|
if(playsize>sh_audio->a_buffer_len) playsize=sh_audio->a_buffer_len;
|
|
|
|
playsize=audio_out->play(sh_audio->a_buffer,playsize,0);
|
|
|
|
if(playsize>0){
|
|
sh_audio->a_buffer_len-=playsize;
|
|
memcpy(sh_audio->a_buffer,&sh_audio->a_buffer[playsize],sh_audio->a_buffer_len);
|
|
sh_audio->timer+=playsize/(float)(sh_audio->o_bps);
|
|
}
|
|
|
|
break;
|
|
} // if(sh_audio)
|
|
|
|
/*========================== UPDATE TIMERS ============================*/
|
|
#if 0
|
|
if(alsa){
|
|
// Use system timer for sync, not audio card/driver
|
|
time_frame-=GetRelativeTime();
|
|
if(time_frame<-0.1 || time_frame>0.1){
|
|
time_frame=0;
|
|
} else {
|
|
while(time_frame>0.022){
|
|
usec_sleep(time_frame-0.022);
|
|
time_frame-=GetRelativeTime();
|
|
}
|
|
while(time_frame>0.007){
|
|
usec_sleep(1000); // sleeps 1 clock tick (10ms)!
|
|
time_frame-=GetRelativeTime();
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if(!sh_video) {
|
|
if(!quiet) mp_msg(MSGT_AVSYNC,MSGL_STATUS,"A:%6.1f %4.1f%% %d%% \r"
|
|
,sh_audio->timer-audio_out->get_delay()
|
|
,(sh_audio->timer>0.5)?100.0*audio_time_usage/(double)sh_audio->timer:0
|
|
,cache_fill_status
|
|
);
|
|
usec_sleep(sh_audio->a_buffer_len/(float)sh_audio->o_bps*1000000);
|
|
goto read_input;
|
|
}
|
|
|
|
/*========================== PLAY VIDEO ============================*/
|
|
|
|
vo_pts=sh_video->timer*90000.0;
|
|
vo_fps=sh_video->fps;
|
|
|
|
cvideo_base_vframe=sh_video->timer;
|
|
cvideo_base_vtime=video_time_usage;
|
|
|
|
if(1)
|
|
while(1){
|
|
|
|
float frame_time=0;
|
|
int blit_frame=0;
|
|
|
|
//-------------------- Decode a frame: -----------------------
|
|
vdecode_time=video_time_usage;
|
|
{ unsigned char* start=NULL;
|
|
int in_size;
|
|
// get it!
|
|
current_module="video_read_frame";
|
|
in_size=video_read_frame(sh_video,&frame_time,&start,force_fps);
|
|
if(in_size<0){ eof=1; break; }
|
|
if(in_size>max_framesize) max_framesize=in_size; // stats
|
|
// decode:
|
|
current_module="decode_video";
|
|
// printf("Decode! %p %d \n",start,in_size);
|
|
blit_frame=decode_video(video_out,sh_video,start,in_size,drop_frame);
|
|
}
|
|
vdecode_time=video_time_usage-vdecode_time;
|
|
//------------------------ frame decoded. --------------------
|
|
|
|
//------------------------ add OSD to frame contents ---------
|
|
#ifndef USE_LIBVO2
|
|
current_module="draw_osd";
|
|
video_out->draw_osd();
|
|
#endif
|
|
|
|
current_module="av_sync";
|
|
|
|
sh_video->timer+=frame_time;
|
|
time_frame+=frame_time; // for nosound
|
|
|
|
mp_dbg(MSGT_AVSYNC,MSGL_DBG2,"*** ftime=%5.3f ***\n",frame_time);
|
|
|
|
if(drop_frame){
|
|
|
|
if(sh_audio && !d_audio->eof){
|
|
float delay=audio_out->get_delay();
|
|
mp_dbg(MSGT_AVSYNC,MSGL_DBG2,"delay=%f\n",delay);
|
|
time_frame=sh_video->timer;
|
|
time_frame-=sh_audio->timer-delay;
|
|
if(time_frame>-2*frame_time) {
|
|
drop_frame=0; // stop dropping frames
|
|
mp_msg(MSGT_AVSYNC,MSGL_DBG2,"\nstop frame drop %.2f\n", time_frame);
|
|
}else{
|
|
++drop_frame_cnt;
|
|
if (verbose > 0 && drop_frame_cnt%10 == 0)
|
|
mp_msg(MSGT_AVSYNC,MSGL_DBG2,"\nstill dropping, %.2f\n", time_frame);
|
|
}
|
|
}
|
|
#ifdef HAVE_NEW_GUI
|
|
if(use_gui) EventHandling();
|
|
#endif
|
|
video_out->check_events(); // check events AST
|
|
} else {
|
|
// It's time to sleep...
|
|
current_module="sleep";
|
|
|
|
time_frame-=GetRelativeTime(); // reset timer
|
|
|
|
if(sh_audio && !d_audio->eof){
|
|
float delay=audio_out->get_delay();
|
|
mp_dbg(MSGT_AVSYNC,MSGL_DBG2,"delay=%f\n",delay);
|
|
|
|
if(!dapsync){
|
|
|
|
/* Arpi's AV-sync */
|
|
|
|
time_frame=sh_video->timer;
|
|
time_frame-=sh_audio->timer-delay;
|
|
|
|
// we are out of time... drop next frame!
|
|
if(time_frame<-2*frame_time){
|
|
static int drop_message=0;
|
|
drop_frame=frame_dropping; // tricky!
|
|
++drop_frame_cnt;
|
|
if(drop_frame_cnt>50 && AV_delay>0.5 && !drop_message){
|
|
drop_message=1;
|
|
mp_msg(MSGT_AVSYNC,MSGL_WARN,MSGTR_SystemTooSlow);
|
|
}
|
|
mp_msg(MSGT_AVSYNC,MSGL_DBG2,"\nframe drop %d, %.2f\n", drop_frame, time_frame);
|
|
}
|
|
|
|
} else {
|
|
|
|
/* DaP's AV-sync */
|
|
|
|
float SH_AV_delay;
|
|
/* SH_AV_delay = sh_video->timer - (sh_audio->timer - (float)((float)delay + sh_audio->a_buffer_len) / (float)sh_audio->o_bps); */
|
|
SH_AV_delay = sh_video->timer - (sh_audio->timer - (float)((float)delay) / (float)sh_audio->o_bps);
|
|
// printf ("audio slp req: %.3f TF: %.3f delta: %.3f (v: %.3f a: %.3f) | ", i, time_frame,
|
|
// i - time_frame, sh_video->timer, sh_audio->timer - (float)((float)delay / (float)sh_audio->o_bps));
|
|
if(SH_AV_delay<-2*frame_time){
|
|
static int drop_message=0;
|
|
drop_frame=frame_dropping; // tricky!
|
|
++drop_frame_cnt;
|
|
if(drop_frame_cnt>50 && AV_delay>0.5 && !drop_message){
|
|
drop_message=1;
|
|
mp_msg(MSGT_AVSYNC,MSGL_WARN,MSGTR_SystemTooSlow);
|
|
}
|
|
printf ("A-V SYNC: FRAMEDROP (SH_AV_delay=%.3f)!\n", SH_AV_delay);
|
|
mp_msg(MSGT_AVSYNC,MSGL_DBG2,"\nframe drop %d, %.2f\n", drop_frame, time_frame);
|
|
/* go into unlimited-TF cycle */
|
|
time_frame = SH_AV_delay;
|
|
} else {
|
|
#define SL_CORR_AVG_LEN 125
|
|
/* don't adjust under framedropping */
|
|
time_frame_corr_avg = (time_frame_corr_avg * (SL_CORR_AVG_LEN - 1) +
|
|
(SH_AV_delay - time_frame)) / SL_CORR_AVG_LEN;
|
|
#define UNEXP_CORR_MAX 0.1 /* limit of unexpected correction between two frames (percentage) */
|
|
#define UNEXP_CORR_WARN 1.0 /* warn limit of A-V lag (percentage) */
|
|
time_frame += time_frame_corr_avg;
|
|
// printf ("{%.3f - %.3f}\n", i - time_frame, frame_time + frame_time_corr_avg);
|
|
if (SH_AV_delay - time_frame < (frame_time + time_frame_corr_avg) * UNEXP_CORR_MAX &&
|
|
SH_AV_delay - time_frame > (frame_time + time_frame_corr_avg) * -UNEXP_CORR_MAX)
|
|
time_frame = SH_AV_delay;
|
|
else {
|
|
if (SH_AV_delay - time_frame > (frame_time + time_frame_corr_avg) * UNEXP_CORR_WARN ||
|
|
SH_AV_delay - time_frame < (frame_time + time_frame_corr_avg) * -UNEXP_CORR_WARN)
|
|
printf ("WARNING: A-V SYNC LAG TOO LARGE: %.3f {%.3f - %.3f} (too little UNEXP_CORR_MAX?)\n",
|
|
SH_AV_delay - time_frame, SH_AV_delay, time_frame);
|
|
time_frame += (frame_time + time_frame_corr_avg) * ((SH_AV_delay > time_frame) ?
|
|
UNEXP_CORR_MAX : -UNEXP_CORR_MAX);
|
|
}
|
|
} /* /start dropframe */
|
|
|
|
}
|
|
|
|
} else {
|
|
// NOSOUND:
|
|
if( (time_frame<-3*frame_time || time_frame>3*frame_time) || benchmark)
|
|
time_frame=0;
|
|
|
|
}
|
|
|
|
// if(verbose>1)printf("sleep: %5.3f a:%6.3f v:%6.3f \n",time_frame,sh_audio->timer,sh_video->timer);
|
|
|
|
aq_sleep_time+=time_frame;
|
|
|
|
#ifdef HAVE_NEW_GUI
|
|
if(use_gui){
|
|
EventHandling();
|
|
}
|
|
#endif
|
|
|
|
if(!(vo_flags&256)){ // flag 256 means: libvo driver does its timing (dvb card)
|
|
|
|
#ifdef HAVE_RTC
|
|
if(rtc_fd>=0){
|
|
// -------- RTC -----------
|
|
while (time_frame > 0.000) {
|
|
unsigned long long rtc_ts;
|
|
if (read (rtc_fd, &rtc_ts, sizeof(rtc_ts)) <= 0)
|
|
perror ("read (rtc_fd)");
|
|
time_frame-=GetRelativeTime();
|
|
}
|
|
} else
|
|
#endif
|
|
{
|
|
// -------- USLEEP + SOFTSLEEP -----------
|
|
float min=softsleep?0.021:0.005;
|
|
while(time_frame>min){
|
|
if(time_frame<=0.020)
|
|
usec_sleep(0); // sleeps 1 clock tick (10ms)!
|
|
else
|
|
usec_sleep(1000000*(time_frame-0.020));
|
|
time_frame-=GetRelativeTime();
|
|
}
|
|
if(softsleep){
|
|
if(time_frame<0) printf("Warning! softsleep underflow!\n");
|
|
while(time_frame>0) time_frame-=GetRelativeTime(); // burn the CPU
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
current_module="flip_page";
|
|
#ifdef USE_LIBVO2
|
|
if(blit_frame) vo2_flip(video_out,0);
|
|
#else
|
|
video_out->check_events();
|
|
if(blit_frame){
|
|
unsigned int t2=GetTimer();
|
|
|
|
float j;
|
|
#define FRAME_LAG_WARN 0.2
|
|
j = ((float)t2 - lastframeout_ts) / 1000000;
|
|
lastframeout_ts = GetTimer();
|
|
if (j < frame_time + frame_time * -FRAME_LAG_WARN)
|
|
too_fast_frame_cnt++;
|
|
/* printf ("PANIC: too fast frame (%.3f)!\n", j); */
|
|
else if (j > frame_time + frame_time * FRAME_LAG_WARN)
|
|
too_slow_frame_cnt++;
|
|
/* printf ("PANIC: too slow frame (%.3f)!\n", j); */
|
|
|
|
video_out->flip_page();
|
|
t2=GetTimer()-t2;vout_time_usage+=t2*0.000001f;
|
|
}
|
|
#endif
|
|
// usec_sleep(50000); // test only!
|
|
|
|
}
|
|
|
|
current_module=NULL;
|
|
|
|
if(eof) break;
|
|
if(force_redraw){
|
|
--force_redraw;
|
|
if(!force_redraw) osd_function=OSD_PLAY;
|
|
continue;
|
|
}
|
|
|
|
// printf("A:%6.1f V:%6.1f A-V:%7.3f frame=%5.2f \r",d_audio->pts,d_video->pts,d_audio->pts-d_video->pts,sh_audio->timer);
|
|
// fflush(stdout);
|
|
|
|
#if 1
|
|
/*================ A-V TIMESTAMP CORRECTION: =========================*/
|
|
if(sh_audio){
|
|
float a_pts=0;
|
|
float v_pts=0;
|
|
|
|
// unplayed bytes in our and soundcard/dma buffer:
|
|
float delay=audio_out->get_delay()+(float)sh_audio->a_buffer_len/(float)sh_audio->o_bps;
|
|
|
|
if(pts_from_bps){
|
|
#if 1
|
|
unsigned int samples=(sh_audio->audio.dwSampleSize)?
|
|
((ds_tell(d_audio)-sh_audio->a_in_buffer_len)/sh_audio->audio.dwSampleSize) :
|
|
(d_audio->pack_no); // <- used for VBR audio
|
|
samples+=sh_audio->audio.dwStart; // offset
|
|
a_pts=samples*(float)sh_audio->audio.dwScale/(float)sh_audio->audio.dwRate;
|
|
#else
|
|
if(sh_audio->audio.dwSampleSize)
|
|
a_pts=(ds_tell(d_audio)-sh_audio->a_in_buffer_len)/(float)sh_audio->wf->nAvgBytesPerSec;
|
|
else // VBR:
|
|
a_pts=d_audio->pack_no*(float)sh_audio->audio.dwScale/(float)sh_audio->audio.dwRate;
|
|
#endif
|
|
// v_pts=d_video->pack_no*(float)sh_video->video.dwScale/(float)sh_video->video.dwRate;
|
|
// printf("V_PTS: PTS: %8.3f BPS: %8.3f \n",d_video->pts,v_pts);
|
|
delay_corrected=1;
|
|
} else {
|
|
// PTS = (last timestamp) + (bytes after last timestamp)/(bytes per sec)
|
|
a_pts=d_audio->pts;
|
|
if(!delay_corrected) if(a_pts) delay_corrected=1;
|
|
//printf("*** %5.3f ***\n",a_pts);
|
|
a_pts+=(ds_tell_pts(d_audio)-sh_audio->a_in_buffer_len)/(float)sh_audio->i_bps;
|
|
// v_pts=d_video->pts-frame_time;
|
|
// v_pts=d_video->pts;
|
|
}
|
|
v_pts=d_video->pts;
|
|
|
|
mp_dbg(MSGT_AVSYNC,MSGL_DBG2,"### A:%8.3f (%8.3f) V:%8.3f A-V:%7.4f \n",a_pts,a_pts-audio_delay-delay,v_pts,(a_pts-delay-audio_delay)-v_pts);
|
|
|
|
if(delay_corrected){
|
|
float x;
|
|
AV_delay=(a_pts-delay-audio_delay)-v_pts;
|
|
x=AV_delay*0.1f;
|
|
if(x<-max_pts_correction) x=-max_pts_correction; else
|
|
if(x> max_pts_correction) x= max_pts_correction;
|
|
if(default_max_pts_correction>=0)
|
|
max_pts_correction=default_max_pts_correction;
|
|
else
|
|
max_pts_correction=sh_video->frametime*0.10; // +-10% of time
|
|
sh_audio->timer+=x; c_total+=x;
|
|
if(!quiet) mp_msg(MSGT_AVSYNC,MSGL_STATUS,"A:%6.1f V:%6.1f A-V:%7.3f ct:%7.3f %3d/%3d %2d%% %2d%% %4.1f%% %d %d %d%%\r",
|
|
a_pts-audio_delay-delay,v_pts,AV_delay,c_total,
|
|
(int)sh_video->num_frames,(int)sh_video->num_frames_decoded,
|
|
(sh_video->timer>0.5)?(int)(100.0*video_time_usage/(double)sh_video->timer):0,
|
|
(sh_video->timer>0.5)?(int)(100.0*vout_time_usage/(double)sh_video->timer):0,
|
|
(sh_video->timer>0.5)?(100.0*audio_time_usage/(double)sh_video->timer):0
|
|
,drop_frame_cnt
|
|
,output_quality
|
|
,cache_fill_status
|
|
);
|
|
fflush(stdout);
|
|
}
|
|
|
|
} else {
|
|
// No audio:
|
|
|
|
if(!quiet)
|
|
mp_msg(MSGT_AVSYNC,MSGL_STATUS,"V:%6.1f %3d %2d%% %2d%% %4.1f%% %d %d %d%%\r",d_video->pts,
|
|
(int)sh_video->num_frames,
|
|
(sh_video->timer>0.5)?(int)(100.0*video_time_usage/(double)sh_video->timer):0,
|
|
(sh_video->timer>0.5)?(int)(100.0*vout_time_usage/(double)sh_video->timer):0,
|
|
(sh_video->timer>0.5)?(100.0*audio_time_usage/(double)sh_video->timer):0
|
|
,drop_frame_cnt
|
|
,output_quality
|
|
,cache_fill_status
|
|
);
|
|
|
|
fflush(stdout);
|
|
|
|
}
|
|
#endif
|
|
|
|
/*Output quality adjustments:*/
|
|
if(auto_quality>0){
|
|
#if 0
|
|
/*If we took a long time decoding this frame, downgrade the quality.*/
|
|
if(output_quality>0&&
|
|
(video_time_usage-cvideo_base_vtime)*sh_video->timer>=
|
|
(0.95*sh_video->timer-(vout_time_usage+audio_time_usage))*
|
|
(sh_video->timer-cvideo_base_vframe-frame_correction)){
|
|
output_quality>>=1;
|
|
mp_msg(MSGT_AUTOQ,MSGL_DBG2,"Downgrading quality to %i.\n",output_quality);
|
|
set_video_quality(sh_video,output_quality);
|
|
} else
|
|
/*If we had plenty of extra time, upgrade the quality.*/
|
|
if(output_quality<auto_quality&&
|
|
vdecode_time<0.5*frame_time&&
|
|
(video_time_usage-cvideo_base_vtime)*sh_video->timer<
|
|
(0.67*sh_video->timer-(vout_time_usage+audio_time_usage))*
|
|
(sh_video->timer-cvideo_base_vframe-frame_correction)){
|
|
output_quality++;
|
|
mp_msg(MSGT_AUTOQ,MSGL_DBG2,"Upgrading quality to %i.\n",output_quality);
|
|
set_video_quality(sh_video,output_quality);
|
|
}
|
|
#else
|
|
// float total=0.000001f * (GetTimer()-aq_total_time);
|
|
// if(output_quality<auto_quality && aq_sleep_time>0.05f*total)
|
|
if(output_quality<auto_quality && aq_sleep_time>0)
|
|
++output_quality;
|
|
else
|
|
// if(output_quality>0 && aq_sleep_time<-0.05f*total)
|
|
if(output_quality>1 && aq_sleep_time<0)
|
|
--output_quality;
|
|
else
|
|
if(output_quality>0 && aq_sleep_time<-0.050f) // 50ms
|
|
output_quality=0;
|
|
// printf("total: %8.6f sleep: %8.6f q: %d\n",(0.000001f*aq_total_time),aq_sleep_time,output_quality);
|
|
set_video_quality(sh_video,output_quality);
|
|
#endif
|
|
}
|
|
|
|
read_input:
|
|
|
|
#ifdef USE_OSD
|
|
if(osd_visible){
|
|
if (!--osd_visible){ vo_osd_progbar_type=-1; // disable
|
|
if (osd_function != OSD_PAUSE)
|
|
osd_function = OSD_PLAY;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if(osd_function==OSD_PAUSE){
|
|
#ifdef HAVE_NEW_INPUT
|
|
mp_cmd_t* cmd;
|
|
#endif
|
|
#ifdef HAVE_NEW_GUI
|
|
int gui_pause_flag=0; // gany!
|
|
#endif
|
|
if(!quiet) {
|
|
mp_msg(MSGT_CPLAYER,MSGL_STATUS,"\n------ PAUSED -------\r");
|
|
fflush(stdout);
|
|
}
|
|
#ifdef HAVE_NEW_GUI
|
|
if(use_gui) mplShMem->Playing=2;
|
|
#endif
|
|
if (video_out && sh_video)
|
|
video_out->control(VOCTRL_PAUSE, NULL);
|
|
|
|
if (audio_out && sh_audio)
|
|
audio_out->pause(); // pause audio, keep data if possible
|
|
|
|
#ifdef HAVE_NEW_INPUT
|
|
while( (cmd = mp_input_get_cmd(20,1)) == NULL) {
|
|
#else /* HAVE_NEW_INPUT */
|
|
if(slave_mode) {
|
|
fd_set set;
|
|
struct timeval timeout;
|
|
while (1) {
|
|
usec_sleep(1000);
|
|
FD_ZERO (&set);
|
|
FD_SET (STDIN_FILENO, &set);
|
|
timeout.tv_sec = 0;
|
|
timeout.tv_usec = 1000;
|
|
if(1==select(FD_SETSIZE, &set, NULL, NULL, &timeout)) {
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
|
|
while(
|
|
#ifdef HAVE_LIRC
|
|
lirc_mp_getinput()<=0 &&
|
|
#endif
|
|
(use_stdin || getch2(20)<=0) && mplayer_get_key()<=0){
|
|
#endif
|
|
#ifndef USE_LIBVO2
|
|
if(sh_video && video_out) video_out->check_events();
|
|
#endif /* HAVE_NEW_INPUT */
|
|
#ifdef HAVE_NEW_GUI
|
|
if(use_gui){
|
|
EventHandling();
|
|
if(mplShMem->Playing!=2 || (rel_seek_secs || abs_seek_pos))
|
|
{ gui_pause_flag=1; break; } // end of pause or seek
|
|
}
|
|
#endif
|
|
#ifdef HAVE_NEW_INPUT
|
|
}
|
|
mp_cmd_free(cmd);
|
|
#else
|
|
if(use_stdin) usec_sleep(1000); // do not eat the CPU
|
|
}
|
|
}
|
|
#endif /* HAVE_NEW_INPUT */
|
|
osd_function=OSD_PLAY;
|
|
if (audio_out && sh_audio)
|
|
audio_out->resume(); // resume audio
|
|
if (video_out && sh_video)
|
|
video_out->control(VOCTRL_RESUME, NULL); // resume video
|
|
(void)GetRelativeTime(); // keep TF around FT in next cycle
|
|
#ifdef HAVE_NEW_GUI
|
|
if(use_gui && !gui_pause_flag) mplShMem->Playing=1; // play from keyboard
|
|
#endif
|
|
}
|
|
|
|
|
|
if(!force_redraw) break;
|
|
} // while(sh_video->timer<sh_audio->timer || force_redraw)
|
|
|
|
// skip some seconds... added by fly
|
|
|
|
if(step_sec>0) {
|
|
osd_function=OSD_FFW;
|
|
rel_seek_secs+=step_sec;
|
|
}
|
|
|
|
//================= Keyboard events, SEEKing ====================
|
|
|
|
#ifndef HAVE_NEW_INPUT
|
|
/* slave mode */
|
|
if(slave_mode) {
|
|
char buffer[1024];
|
|
fd_set set;
|
|
struct timeval timeout;
|
|
int arg;
|
|
|
|
FD_ZERO (&set);
|
|
FD_SET (STDIN_FILENO, &set);
|
|
timeout.tv_sec = 0;
|
|
timeout.tv_usec = 1000;
|
|
|
|
if(1 == select (FD_SETSIZE, &set, NULL, NULL, &timeout)) {
|
|
fgets(buffer, 1024, stdin);
|
|
if(!strcmp("play\n", buffer)) {
|
|
osd_function=OSD_PLAY;
|
|
} else if(!strcmp("stop\n", buffer)) {
|
|
osd_function=OSD_PAUSE;
|
|
} else if(!strncmp("seek ", buffer, 5)) {
|
|
sscanf(buffer+5, "%d", &arg);
|
|
rel_seek_secs = arg-d_video->pts;
|
|
} else if(!strncmp("skip ", buffer, 5)) {
|
|
sscanf(buffer+5, "%d", &arg);
|
|
rel_seek_secs = arg;
|
|
} else if(!strcmp("quit\n", buffer)) {
|
|
exit_player(MSGTR_Exit_quit);
|
|
}
|
|
} else {
|
|
osd_function=OSD_PLAY;
|
|
}
|
|
} else
|
|
|
|
/* interactive mode */
|
|
{ int c;
|
|
while(
|
|
#ifdef HAVE_LIRC
|
|
(c=lirc_mp_getinput())>0 ||
|
|
#endif
|
|
(!use_stdin && (c=getch2(0))>0) || (c=mplayer_get_key())>0) switch(c){
|
|
// seek 10 sec
|
|
case KEY_RIGHT:
|
|
osd_function=OSD_FFW;
|
|
rel_seek_secs+=10;break;
|
|
case KEY_LEFT:
|
|
osd_function=OSD_REW;
|
|
rel_seek_secs-=10;break;
|
|
// seek 1 min
|
|
case KEY_UP:
|
|
osd_function=OSD_FFW;
|
|
rel_seek_secs+=60;break;
|
|
case KEY_DOWN:
|
|
osd_function=OSD_REW;
|
|
rel_seek_secs-=60;break;
|
|
// seek 10 min
|
|
case KEY_PAGE_UP:
|
|
rel_seek_secs+=600;break;
|
|
case KEY_PAGE_DOWN:
|
|
rel_seek_secs-=600;break;
|
|
// delay correction:
|
|
case '+':
|
|
audio_delay+=0.1; // increase audio buffer delay
|
|
osd_show_av_delay = 9; // show the A-V delay in OSD
|
|
if(sh_audio) sh_audio->timer-=0.1;
|
|
break;
|
|
case '-':
|
|
audio_delay-=0.1; // decrease audio buffer delay
|
|
osd_show_av_delay = 9; // show the A-V delay in OSD
|
|
if(sh_audio) sh_audio->timer+=0.1;
|
|
break;
|
|
// quit
|
|
case KEY_ESC: // ESC
|
|
case 'q':
|
|
exit_player(MSGTR_Exit_quit);
|
|
case KEY_ENTER: // ESC
|
|
eof=1; // force jump to next file : quit if no next file
|
|
break;
|
|
case 'g': grab_frames=2;break;
|
|
// pause
|
|
case 'p':
|
|
case ' ':
|
|
osd_function=OSD_PAUSE;
|
|
break;
|
|
case KEY_HOME:
|
|
{
|
|
play_tree_iter_t* i = play_tree_iter_new_copy(playtree_iter);
|
|
if(play_tree_iter_up_step(i,1,0) == PLAY_TREE_ITER_ENTRY)
|
|
eof = PT_UP_NEXT;
|
|
play_tree_iter_free(i);
|
|
}
|
|
break;
|
|
case KEY_END:
|
|
{
|
|
play_tree_iter_t* i = play_tree_iter_new_copy(playtree_iter);
|
|
if(play_tree_iter_up_step(i,-1,0) == PLAY_TREE_ITER_ENTRY)
|
|
eof = PT_UP_PREV;
|
|
play_tree_iter_free(i);
|
|
}
|
|
break;
|
|
case '>':
|
|
{
|
|
play_tree_iter_t* i = play_tree_iter_new_copy(playtree_iter);
|
|
if(play_tree_iter_step(i,1,0) == PLAY_TREE_ITER_ENTRY)
|
|
eof = PT_NEXT_ENTRY;
|
|
play_tree_iter_free(i);
|
|
}
|
|
break;
|
|
case '<':
|
|
{
|
|
play_tree_iter_t* i = play_tree_iter_new_copy(playtree_iter);
|
|
if(play_tree_iter_step(i,-1,0) == PLAY_TREE_ITER_ENTRY)
|
|
eof = PT_PREV_ENTRY;
|
|
play_tree_iter_free(i);
|
|
}
|
|
break;
|
|
case KEY_INS:
|
|
if(playtree_iter->num_files > 1 && playtree_iter->file < playtree_iter->num_files)
|
|
eof = PT_NEXT_SRC;
|
|
break;
|
|
case KEY_DEL:
|
|
if(playtree_iter->num_files > 1 && playtree_iter->file > 1)
|
|
eof = PT_PREV_SRC;
|
|
break;
|
|
case 'o': // toggle OSD
|
|
if(sh_video)
|
|
osd_level=(osd_level+1)%3;
|
|
break;
|
|
case 'z':
|
|
sub_delay -= 0.1;
|
|
osd_show_sub_delay = 9; // show the subdelay in OSD
|
|
break;
|
|
case 'x':
|
|
sub_delay += 0.1;
|
|
osd_show_sub_delay = 9; // show the subdelay in OSD
|
|
break;
|
|
case '9':
|
|
case '0':
|
|
case '*':
|
|
case '/': {
|
|
if(c=='*' || c=='0'){
|
|
mixer_incvolume();
|
|
} else {
|
|
mixer_decvolume();
|
|
}
|
|
|
|
#ifdef USE_OSD
|
|
if(osd_level){
|
|
osd_visible=sh_video->fps; // 1 sec
|
|
vo_osd_progbar_type=OSD_VOLUME;
|
|
vo_osd_progbar_value=(mixer_getbothvolume()*256.0)/100.0;
|
|
//printf("volume: %d\n",vo_osd_progbar_value);
|
|
}
|
|
#endif
|
|
}
|
|
break;
|
|
case 'm':
|
|
mixer_usemaster=!mixer_usemaster;
|
|
break;
|
|
|
|
#if 0 // change to 1 for absolute seeking tests
|
|
case '1':
|
|
case '2':
|
|
case '3':
|
|
case '4':
|
|
case '5':
|
|
case '6':
|
|
case '7':
|
|
case '8':
|
|
rel_seek_secs=0.99*(float)(c-'1')/7.0;
|
|
abs_seek_pos=3;
|
|
printf("ABS seek to %5.3f \n",rel_seek_secs);
|
|
break;
|
|
#else
|
|
#ifndef USE_LIBVO2
|
|
/* User wants to have screen shot */
|
|
case 'S':
|
|
case 's':
|
|
video_out->control(VOCTRL_SCREENSHOT, NULL);
|
|
break;
|
|
#endif
|
|
// Contrast:
|
|
case '1':
|
|
case '2':
|
|
if(c=='2'){
|
|
if ( ++v_cont > 100 ) v_cont = 100;
|
|
} else {
|
|
--v_cont;
|
|
if(v_hw_equ_cap & VEQ_CAP_CONTRAST)
|
|
{
|
|
if(v_cont < -100) v_cont = -100;
|
|
}
|
|
else
|
|
{
|
|
if ( v_cont < 0 ) v_cont = 0;
|
|
}
|
|
}
|
|
if(set_video_colors(sh_video,"Contrast",v_cont)){
|
|
#ifdef USE_OSD
|
|
if(osd_level){
|
|
osd_visible=sh_video->fps; // 1 sec
|
|
vo_osd_progbar_type=OSD_CONTRAST;
|
|
vo_osd_progbar_value=((v_cont)<<8)/100;
|
|
if(v_hw_equ_cap) vo_osd_progbar_value = ((v_cont+100)<<8)/200;
|
|
}
|
|
#endif
|
|
}
|
|
break;
|
|
|
|
// Brightness:
|
|
case '3':
|
|
case '4':
|
|
if(c=='4'){
|
|
if ( ++v_bright > 100 ) v_bright = 100;
|
|
} else {
|
|
--v_bright;
|
|
if(v_hw_equ_cap & VEQ_CAP_BRIGHTNESS)
|
|
{
|
|
if(v_bright < -100) v_bright = -100;
|
|
}
|
|
else
|
|
{
|
|
if ( v_bright < 0 ) v_bright = 0;
|
|
}
|
|
}
|
|
if(set_video_colors(sh_video,"Brightness",v_bright)){
|
|
#ifdef USE_OSD
|
|
if(osd_level){
|
|
osd_visible=sh_video->fps; // 1 sec
|
|
vo_osd_progbar_type=OSD_BRIGHTNESS;
|
|
vo_osd_progbar_value=((v_bright)<<8)/100;
|
|
if(v_hw_equ_cap) vo_osd_progbar_value = ((v_bright+100)<<8)/200;
|
|
}
|
|
#endif
|
|
}
|
|
break;
|
|
|
|
// Hue:
|
|
case '5':
|
|
case '6':
|
|
if(c=='6'){
|
|
if ( ++v_hue > 100 ) v_hue = 100;
|
|
} else {
|
|
--v_hue;
|
|
if(v_hw_equ_cap & VEQ_CAP_HUE)
|
|
{
|
|
if(v_hue < -100) v_hue = -100;
|
|
}
|
|
else
|
|
{
|
|
if ( v_hue < 0 ) v_hue = 0;
|
|
}
|
|
}
|
|
if(set_video_colors(sh_video,"Hue",v_hue)){
|
|
#ifdef USE_OSD
|
|
if(osd_level){
|
|
osd_visible=sh_video->fps; // 1 sec
|
|
vo_osd_progbar_type=OSD_HUE;
|
|
vo_osd_progbar_value=((v_hue)<<8)/100;
|
|
if(v_hw_equ_cap) vo_osd_progbar_value = ((v_hue+100)<<8)/200;
|
|
}
|
|
#endif
|
|
}
|
|
break;
|
|
|
|
// Saturation:
|
|
case '7':
|
|
case '8':
|
|
if(c=='8'){
|
|
if ( ++v_saturation > 100 ) v_saturation = 100;
|
|
} else {
|
|
--v_saturation;
|
|
if(v_hw_equ_cap & VEQ_CAP_SATURATION)
|
|
{
|
|
if(v_saturation < -100) v_saturation = -100;
|
|
}
|
|
else
|
|
{
|
|
if ( v_saturation < 0 ) v_saturation = 0;
|
|
}
|
|
}
|
|
if(set_video_colors(sh_video,"Saturation",v_saturation)){
|
|
#ifdef USE_OSD
|
|
if(osd_level){
|
|
osd_visible=sh_video->fps; // 1 sec
|
|
vo_osd_progbar_type=OSD_SATURATION;
|
|
vo_osd_progbar_value=((v_saturation)<<8)/100;
|
|
if(v_hw_equ_cap) vo_osd_progbar_value = ((v_saturation+100)<<8)/200;
|
|
}
|
|
#endif
|
|
}
|
|
break;
|
|
#endif
|
|
|
|
case 'd':
|
|
frame_dropping=(frame_dropping+1)%3;
|
|
mp_msg(MSGT_CPLAYER,MSGL_V,"== drop: %d == \n",frame_dropping);
|
|
break;
|
|
|
|
#ifdef USE_TV
|
|
case 'h':
|
|
if (tv_param_on == 1)
|
|
tv_step_channel(tv_handler, TV_CHANNEL_HIGHER);
|
|
break;
|
|
case 'l':
|
|
if (tv_param_on == 1)
|
|
tv_step_channel(tv_handler, TV_CHANNEL_LOWER);
|
|
break;
|
|
case 'n':
|
|
if (tv_param_on == 1)
|
|
tv_step_norm(tv_handler);
|
|
break;
|
|
case 'b':
|
|
if (tv_param_on == 1)
|
|
tv_step_chanlist(tv_handler);
|
|
break;
|
|
#endif
|
|
|
|
case 'f':
|
|
video_out->control(VOCTRL_FULLSCREEN, 0);
|
|
break;
|
|
}
|
|
} // keyboard event handler
|
|
|
|
#else /* HAVE_NEW_INPUT */
|
|
{
|
|
mp_cmd_t* cmd;
|
|
while( (cmd = mp_input_get_cmd(0,0)) != NULL) {
|
|
switch(cmd->id) {
|
|
case MP_CMD_SEEK : {
|
|
int v,abs;
|
|
v = cmd->args[0].v.i;
|
|
abs = (cmd->nargs > 1) ? cmd->args[1].v.i : 0;
|
|
if(abs) {
|
|
abs_seek_pos = 3;
|
|
osd_function= (v > sh_video->timer) ? OSD_FFW : OSD_REW;
|
|
rel_seek_secs = v;
|
|
}
|
|
else {
|
|
rel_seek_secs+= v;
|
|
osd_function= (v > 0) ? OSD_FFW : OSD_REW;
|
|
}
|
|
} break;
|
|
case MP_CMD_AUDIO_DELAY : {
|
|
float v = cmd->args[0].v.f;
|
|
audio_delay += v;
|
|
osd_show_av_delay = 9;
|
|
if(sh_audio) sh_audio->timer+= v;
|
|
} break;
|
|
case MP_CMD_PAUSE : {
|
|
osd_function=OSD_PAUSE;
|
|
} break;
|
|
case MP_CMD_QUIT : {
|
|
exit_player(MSGTR_Exit_quit);
|
|
}
|
|
case MP_CMD_GRAB_FRAMES : {
|
|
grab_frames=2;
|
|
} break;
|
|
case MP_CMD_PLAY_TREE_STEP : {
|
|
int n = cmd->args[0].v.i > 0 ? 1 : -1;
|
|
play_tree_iter_t* i = play_tree_iter_new_copy(playtree_iter);
|
|
|
|
if(play_tree_iter_step(i,n,0) == PLAY_TREE_ITER_ENTRY)
|
|
eof = (n > 0) ? PT_NEXT_ENTRY : PT_PREV_ENTRY;
|
|
play_tree_iter_free(i);
|
|
} break;
|
|
case MP_CMD_PLAY_TREE_UP_STEP : {
|
|
int n = cmd->args[0].v.i > 0 ? 1 : -1;
|
|
play_tree_iter_t* i = play_tree_iter_new_copy(playtree_iter);
|
|
if(play_tree_iter_up_step(i,n,0) == PLAY_TREE_ITER_ENTRY)
|
|
eof = (n > 0) ? PT_UP_NEXT : PT_UP_PREV;
|
|
play_tree_iter_free(i);
|
|
} break;
|
|
case MP_CMD_PLAY_ALT_SRC_STEP : {
|
|
if(playtree_iter->num_files > 1) {
|
|
int v = cmd->args[0].v.i;
|
|
if(v > 0 && playtree_iter->file < playtree_iter->num_files)
|
|
eof = PT_NEXT_SRC;
|
|
else if(v < 0 && playtree_iter->file > 1)
|
|
eof = PT_PREV_SRC;
|
|
}
|
|
} break;
|
|
case MP_CMD_SUB_DELAY : {
|
|
int abs= cmd->args[1].v.i;
|
|
float v = cmd->args[0].v.f;
|
|
if(abs)
|
|
sub_delay = v;
|
|
else
|
|
sub_delay += v;
|
|
osd_show_sub_delay = 9; // show the subdelay in OSD
|
|
} break;
|
|
case MP_CMD_OSD :
|
|
if(sh_video) {
|
|
int v = cmd->args[0].v.i;
|
|
if(v < 0)
|
|
osd_level=(osd_level+1)%3;
|
|
else
|
|
osd_level= v > 2 ? 2 : v;
|
|
} break;
|
|
case MP_CMD_VOLUME : {
|
|
int v = cmd->args[0].v.i;
|
|
if(v > 0)
|
|
mixer_incvolume();
|
|
else
|
|
mixer_decvolume();
|
|
#ifdef USE_OSD
|
|
if(osd_level){
|
|
osd_visible=sh_video->fps; // 1 sec
|
|
vo_osd_progbar_type=OSD_VOLUME;
|
|
vo_osd_progbar_value=(mixer_getbothvolume()*256.0)/100.0;
|
|
}
|
|
#endif
|
|
} break;
|
|
case MP_CMD_MIXER_USEMASTER : {
|
|
mixer_usemaster=!mixer_usemaster;
|
|
} break;
|
|
case MP_CMD_CONTRAST : {
|
|
int v = cmd->args[0].v.i, abs = cmd->args[1].v.i;
|
|
if(abs)
|
|
v_cont = v > 100 ? 100 : v;
|
|
else {
|
|
if ( (v_cont += v) > 100 ) v_cont = 100;
|
|
}
|
|
if(v_cont < 0) v_cont = 0;
|
|
|
|
if(set_video_colors(sh_video,"Contrast",v_cont)){
|
|
#ifdef USE_OSD
|
|
if(osd_level){
|
|
osd_visible=sh_video->fps; // 1 sec
|
|
vo_osd_progbar_type=OSD_CONTRAST;
|
|
vo_osd_progbar_value=((v_cont)<<8)/100;
|
|
}
|
|
#endif
|
|
}
|
|
} break;
|
|
case MP_CMD_BRIGHTNESS : {
|
|
int v = cmd->args[0].v.i, abs = cmd->args[1].v.i;
|
|
if(abs)
|
|
v_bright = v > 100 ? 100 : v;
|
|
else {
|
|
if ( (v_bright += v) > 100 ) v_cont = 100;
|
|
}
|
|
if(v_hw_equ_cap & VEQ_CAP_BRIGHTNESS) {
|
|
if(v_bright < -100) v_bright = -100;
|
|
} else {
|
|
if ( v_bright < 0 ) v_bright = 0;
|
|
}
|
|
if(set_video_colors(sh_video,"Brightness",v_bright)){
|
|
#ifdef USE_OSD
|
|
if(osd_level){
|
|
osd_visible=sh_video->fps; // 1 sec
|
|
vo_osd_progbar_type=OSD_BRIGHTNESS;
|
|
vo_osd_progbar_value=((v_bright)<<8)/100;
|
|
}
|
|
#endif
|
|
}
|
|
} break;
|
|
case MP_CMD_HUE : {
|
|
int v = cmd->args[0].v.i, abs = cmd->args[1].v.i;
|
|
if(abs)
|
|
v_hue = v > 100 ? 100 : v;
|
|
else {
|
|
if ( (v_hue += v) > 100 ) v_hue = 100;
|
|
}
|
|
if(v_hw_equ_cap & VEQ_CAP_HUE) {
|
|
if(v_hue < -100) v_hue = -100;
|
|
} else {
|
|
if ( v_hue < 0 ) v_hue = 0;
|
|
}
|
|
if(set_video_colors(sh_video,"Hue",v_hue)){
|
|
#ifdef USE_OSD
|
|
if(osd_level){
|
|
osd_visible=sh_video->fps; // 1 sec
|
|
vo_osd_progbar_type=OSD_HUE;
|
|
vo_osd_progbar_value=((v_hue)<<8)/100;
|
|
}
|
|
#endif
|
|
}
|
|
} break;
|
|
case MP_CMD_SATURATION : {
|
|
int v = cmd->args[0].v.i, abs = cmd->args[1].v.i;
|
|
if(abs)
|
|
v_saturation = v > 100 ? 100 : v;
|
|
else {
|
|
if ( (v_saturation += v) > 100 ) v_saturation = 100;
|
|
}
|
|
if(v_hw_equ_cap & VEQ_CAP_SATURATION) {
|
|
if(v_saturation < -100) v_saturation = -100;
|
|
} else {
|
|
if ( v_saturation < 0 ) v_saturation = 0;
|
|
}
|
|
if(set_video_colors(sh_video,"Saturation",v_saturation)){
|
|
#ifdef USE_OSD
|
|
if(osd_level){
|
|
osd_visible=sh_video->fps; // 1 sec
|
|
vo_osd_progbar_type=OSD_SATURATION;
|
|
vo_osd_progbar_value=((v_saturation)<<8)/100;
|
|
}
|
|
#endif
|
|
}
|
|
} break;
|
|
case MP_CMD_FRAMEDROPPING : {
|
|
int v = cmd->args[0].v.i;
|
|
if(v < 0)
|
|
frame_dropping = (frame_dropping+1)%3;
|
|
else
|
|
frame_dropping = v > 2 ? 2 : v;
|
|
} break;
|
|
#ifdef USE_TV
|
|
case MP_CMD_TV_STEP_CHANNEL : {
|
|
if (tv_param_on == 1) {
|
|
int v = cmd->args[0].v.i;
|
|
if(v > 0)
|
|
tv_step_channel(tv_handler, TV_CHANNEL_HIGHER);
|
|
else
|
|
tv_step_channel(tv_handler, TV_CHANNEL_LOWER);
|
|
}
|
|
} break;
|
|
case MP_CMD_TV_STEP_NORM : {
|
|
if (tv_param_on == 1)
|
|
tv_step_norm(tv_handler);
|
|
} break;
|
|
case MP_CMD_TV_STEP_CHANNEL_LIST : {
|
|
if (tv_param_on == 1)
|
|
tv_step_chanlist(tv_handler);
|
|
} break;
|
|
case MP_CMD_VO_FULLSCREEN:
|
|
{
|
|
video_out->control(VOCTRL_FULLSCREEN, 0);
|
|
} break;
|
|
#endif
|
|
default :
|
|
printf("Received unknow cmd %s\n",cmd->name);
|
|
}
|
|
mp_cmd_free(cmd);
|
|
}
|
|
}
|
|
#endif
|
|
if (seek_to_sec) {
|
|
int a,b; float d;
|
|
|
|
if (sscanf(seek_to_sec, "%d:%d:%f", &a,&b,&d)==3)
|
|
rel_seek_secs += 3600*a +60*b +d ;
|
|
else if (sscanf(seek_to_sec, "%d:%f", &a, &d)==2)
|
|
rel_seek_secs += 60*a +d;
|
|
else if (sscanf(seek_to_sec, "%f", &d)==1)
|
|
rel_seek_secs += d;
|
|
|
|
seek_to_sec = NULL;
|
|
}
|
|
|
|
/* Looping. */
|
|
if(eof==1 && loop_times>=0) {
|
|
|
|
mp_msg(MSGT_CPLAYER,MSGL_V,"loop_times = %d, eof = %d\n", loop_times,eof);
|
|
|
|
if(loop_times>1) loop_times--; else
|
|
if(loop_times==1) loop_times=-1;
|
|
|
|
eof=0;
|
|
abs_seek_pos=3; rel_seek_secs=0; // seek to start of movie (0%)
|
|
|
|
}
|
|
|
|
if(rel_seek_secs || abs_seek_pos){
|
|
current_module="seek";
|
|
if(demux_seek(demuxer,rel_seek_secs,abs_seek_pos)){
|
|
// success:
|
|
/* FIXME there should be real seeking for vobsub */
|
|
if (vo_vobsub)
|
|
vobsub_reset(vo_vobsub);
|
|
|
|
if(sh_audio){
|
|
if(verbose){
|
|
float a_pts=d_audio->pts;
|
|
a_pts+=(ds_tell_pts(d_audio)-sh_audio->a_in_buffer_len)/(float)sh_audio->i_bps;
|
|
mp_msg(MSGT_AVSYNC,MSGL_V,"SEEK: A: %5.3f V: %5.3f A-V: %5.3f \n",a_pts,d_video->pts,a_pts-d_video->pts);
|
|
}
|
|
mp_msg(MSGT_AVSYNC,MSGL_STATUS,"A:%6.1f V:%6.1f A-V:%7.3f ct: ? \r",d_audio->pts,d_video->pts,0.0f);
|
|
} else {
|
|
mp_msg(MSGT_AVSYNC,MSGL_STATUS,"A: --- V:%6.1f \r",d_video->pts);
|
|
}
|
|
fflush(stdout);
|
|
|
|
if(sh_video){
|
|
current_module="seek_video_reset";
|
|
video_out->control(VOCTRL_RESET,NULL);
|
|
}
|
|
|
|
if(sh_audio){
|
|
current_module="seek_audio_reset";
|
|
audio_out->reset(); // stop audio, throwing away buffered data
|
|
}
|
|
#ifdef USE_OSD
|
|
// Set OSD:
|
|
if(osd_level){
|
|
int len=((demuxer->movi_end-demuxer->movi_start)>>8);
|
|
if (len>0){
|
|
osd_visible=sh_video->fps; // 1 sec
|
|
vo_osd_progbar_type=0;
|
|
vo_osd_progbar_value=(demuxer->filepos-demuxer->movi_start)/len;
|
|
}
|
|
}
|
|
#endif
|
|
if(sh_video) {
|
|
c_total=0;
|
|
max_pts_correction=0.1;
|
|
osd_visible=sh_video->fps; // to rewert to PLAY pointer after 1 sec
|
|
audio_time_usage=0; video_time_usage=0; vout_time_usage=0;
|
|
drop_frame_cnt=0;
|
|
too_slow_frame_cnt=0;
|
|
too_fast_frame_cnt=0;
|
|
|
|
#ifdef USE_DVDREAD
|
|
if(vo_spudec) spudec_reset(vo_spudec);
|
|
#endif
|
|
}
|
|
}
|
|
rel_seek_secs=0;
|
|
abs_seek_pos=0;
|
|
current_module=NULL;
|
|
}
|
|
|
|
#ifdef HAVE_NEW_GUI
|
|
if(use_gui){
|
|
if(demuxer->file_format==DEMUXER_TYPE_AVI && sh_video->video.dwLength>2){
|
|
// get pos from frame number / total frames
|
|
mplShMem->Position=(float)d_video->pack_no*100.0f/sh_video->video.dwLength;
|
|
} else {
|
|
// get pos from file position / filesize
|
|
int len=((demuxer->movi_end-demuxer->movi_start));
|
|
int pos=(demuxer->file_format==DEMUXER_TYPE_AVI)?demuxer->filepos:d_video->pos;
|
|
mplShMem->Position=(len<=0)?0:((float)(pos-demuxer->movi_start) / len * 100.0f);
|
|
}
|
|
mplShMem->TimeSec=d_video->pts;
|
|
if(mplShMem->Playing==0) break; // STOP
|
|
if(mplShMem->Playing==2) osd_function=OSD_PAUSE;
|
|
if ( mplShMem->VolumeChanged )
|
|
{
|
|
mixer_setvolume( mplShMem->Volume,mplShMem->Volume );
|
|
mplShMem->VolumeChanged=0;
|
|
#ifdef USE_OSD
|
|
if ( osd_level )
|
|
{
|
|
osd_visible=sh_video->fps; // 1 sec
|
|
vo_osd_progbar_type=OSD_VOLUME;
|
|
vo_osd_progbar_value=( ( mplShMem->Volume ) * 256.0 ) / 100.0;
|
|
}
|
|
#endif
|
|
}
|
|
mplShMem->Volume=(float)mixer_getbothvolume();
|
|
#ifdef USE_DVDREAD
|
|
if ( mplShMem->DVDChanged ) goto goto_next_file;
|
|
if ( stream->type == STREAMTYPE_DVD )
|
|
{
|
|
dvd_priv_t * dvdp = stream->priv;
|
|
mplShMem->DVD.current_chapter=dvdp->cur_cell + 1;
|
|
}
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
|
|
//================= Update OSD ====================
|
|
#ifdef USE_OSD
|
|
if(osd_level>=2){
|
|
int pts=d_video->pts;
|
|
if(pts==osd_last_pts-1) ++pts; else osd_last_pts=pts;
|
|
vo_osd_text=osd_text_buffer;
|
|
if (osd_show_sub_delay) {
|
|
sprintf(vo_osd_text, "Sub delay: %d ms",(int)(sub_delay*1000));
|
|
osd_show_sub_delay--;
|
|
} else
|
|
if (osd_show_av_delay) {
|
|
sprintf(vo_osd_text, "A-V delay: %d ms",(int)(audio_delay*1000));
|
|
osd_show_av_delay--;
|
|
} else
|
|
sprintf(vo_osd_text,"%c %02d:%02d:%02d",osd_function,pts/3600,(pts/60)%60,pts%60);
|
|
} else {
|
|
vo_osd_text=NULL;
|
|
}
|
|
// for(i=1;i<=11;i++) osd_text_buffer[10+i]=i;osd_text_buffer[10+i]=0;
|
|
// vo_osd_text=osd_text_buffer;
|
|
#endif
|
|
|
|
#ifdef USE_SUB
|
|
// find sub
|
|
if(subtitles && d_video->pts>0){
|
|
float pts=d_video->pts;
|
|
if(sub_fps==0) sub_fps=sh_video->fps;
|
|
current_module="find_sub";
|
|
if (pts > sub_last_pts || pts < sub_last_pts-1.0 ) {
|
|
find_sub(subtitles,sub_uses_time?(100*(pts+sub_delay)):((pts+sub_delay)*sub_fps)); // FIXME! frame counter...
|
|
sub_last_pts = pts;
|
|
}
|
|
current_module=NULL;
|
|
}
|
|
#endif
|
|
|
|
|
|
// VobSub subtitles
|
|
if(vo_vobsub){
|
|
current_module="vobsub";
|
|
vobsub_process(vo_vobsub,d_video->pts);
|
|
current_module=NULL;
|
|
}
|
|
|
|
#ifdef USE_DVDREAD
|
|
// DVD sub:
|
|
if(vo_flags & 0x08){
|
|
static vo_mpegpes_t packet;
|
|
static vo_mpegpes_t *pkg=&packet;
|
|
packet.timestamp=sh_video->timer*90000.0;
|
|
packet.id=0x20; /* Subpic */
|
|
while((packet.size=ds_get_packet_sub(d_dvdsub,&packet.data))>0){
|
|
mp_msg(MSGT_CPLAYER,MSGL_V,"\rDVD sub: len=%d v_pts=%5.3f s_pts=%5.3f \n",packet.size,d_video->pts,d_dvdsub->pts);
|
|
video_out->draw_frame(&pkg);
|
|
}
|
|
}else if(vo_spudec){
|
|
unsigned char* packet=NULL;
|
|
int len;
|
|
current_module="spudec";
|
|
while((len=ds_get_packet_sub(d_dvdsub,&packet))>0){
|
|
mp_msg(MSGT_CPLAYER,MSGL_V,"\rDVD sub: len=%d v_pts=%5.3f s_pts=%5.3f \n",len,d_video->pts,d_dvdsub->pts);
|
|
spudec_assemble(vo_spudec,packet,len,100*d_dvdsub->pts);
|
|
}
|
|
spudec_heartbeat(vo_spudec,100*d_video->pts);
|
|
current_module=NULL;
|
|
}
|
|
#endif
|
|
|
|
} // while(!eof)
|
|
|
|
mp_msg(MSGT_GLOBAL,MSGL_V,"EOF code: %d \n",eof);
|
|
|
|
}
|
|
|
|
goto_next_file: // don't jump here after ao/vo/getch initialization!
|
|
|
|
|
|
if(benchmark){
|
|
double tot=video_time_usage+vout_time_usage+audio_time_usage;
|
|
double total_time_usage;
|
|
total_time_usage_start=GetTimer()-total_time_usage_start;
|
|
total_time_usage = (float)total_time_usage_start*0.000001;
|
|
mp_msg(MSGT_CPLAYER,MSGL_INFO,"\nBENCHMARKs: V:%8.3fs VO:%8.3fs A:%8.3fs Sys:%8.3fs = %8.3fs\n",
|
|
video_time_usage,vout_time_usage,audio_time_usage,
|
|
total_time_usage-tot,total_time_usage);
|
|
if(total_time_usage>0.0)
|
|
mp_msg(MSGT_CPLAYER,MSGL_INFO,"BENCHMARK%%: V:%8.4f%% VO:%8.4f%% A:%8.4f%% Sys:%8.4f%% = %8.4f%%\n",
|
|
100.0*video_time_usage/total_time_usage,
|
|
100.0*vout_time_usage/total_time_usage,
|
|
100.0*audio_time_usage/total_time_usage,
|
|
100.0*(total_time_usage-tot)/total_time_usage,
|
|
100.0);
|
|
}
|
|
|
|
if(eof == PT_NEXT_ENTRY || eof == PT_PREV_ENTRY) {
|
|
eof = eof == PT_NEXT_ENTRY ? 1 : -1;
|
|
if(play_tree_iter_step(playtree_iter,eof,0) == PLAY_TREE_ITER_ENTRY) {
|
|
uninit_player(INITED_ALL-(INITED_GUI+INITED_LIRC+INITED_INPUT));
|
|
eof = 1;
|
|
} else {
|
|
play_tree_iter_free(playtree_iter);
|
|
playtree_iter = NULL;
|
|
}
|
|
} else if (eof == PT_UP_NEXT || eof == PT_UP_PREV) {
|
|
eof = eof == PT_UP_NEXT ? 1 : -1;
|
|
if(play_tree_iter_up_step(playtree_iter,eof,0) == PLAY_TREE_ITER_ENTRY) {
|
|
uninit_player(INITED_ALL-(INITED_GUI+INITED_LIRC+INITED_INPUT));
|
|
eof = 1;
|
|
} else {
|
|
play_tree_iter_free(playtree_iter);
|
|
playtree_iter = NULL;
|
|
}
|
|
}else { // NEXT PREV SRC
|
|
uninit_player(INITED_ALL-(INITED_GUI+INITED_LIRC+INITED_INPUT));
|
|
eof = eof == PT_PREV_SRC ? -1 : 1;
|
|
}
|
|
|
|
goto_next_file_src: // When we have multiple src for file
|
|
|
|
if(eof == 0) eof = 1;
|
|
|
|
#ifdef HAVE_NEW_GUI
|
|
if(use_gui)
|
|
{
|
|
#ifdef USE_DVDREAD
|
|
if ( !mplShMem->DVDChanged )
|
|
#endif
|
|
mplStop();
|
|
}
|
|
#endif
|
|
|
|
while(playtree_iter != NULL) {
|
|
filename = play_tree_iter_get_file(playtree_iter,eof);
|
|
if(filename == NULL) {
|
|
if( play_tree_iter_step(playtree_iter,eof,0) != PLAY_TREE_ITER_ENTRY) {
|
|
play_tree_iter_free(playtree_iter);
|
|
playtree_iter = NULL;
|
|
};
|
|
} else
|
|
break;
|
|
}
|
|
|
|
if(use_gui || playtree_iter != NULL
|
|
#if defined( HAVE_NEW_GUI ) && defined( USE_DVDREAD )
|
|
|| (mplShMem && mplShMem->DVDChanged)
|
|
#endif
|
|
){
|
|
|
|
current_module="uninit_vcodec";
|
|
if(sh_video) uninit_video(sh_video);
|
|
|
|
current_module="free_demuxer";
|
|
if(demuxer) free_demuxer(demuxer);
|
|
|
|
current_module="free_stream";
|
|
if(stream) free_stream(stream);
|
|
|
|
current_module="sub_free";
|
|
if ( subtitles )
|
|
{
|
|
sub_free( subtitles );
|
|
sub_name=NULL;
|
|
vo_sub=NULL;
|
|
}
|
|
|
|
video_out=NULL;
|
|
audio_out=NULL;
|
|
eof = 0;
|
|
goto play_next_file;
|
|
}
|
|
|
|
exit_player(MSGTR_Exit_eof);
|
|
|
|
return 1;
|
|
}
|