summaryrefslogtreecommitdiffstats
path: root/mplayer.c
diff options
context:
space:
mode:
Diffstat (limited to 'mplayer.c')
-rw-r--r--mplayer.c1302
1 files changed, 689 insertions, 613 deletions
diff --git a/mplayer.c b/mplayer.c
index dd9e9dc699..57edf9ee91 100644
--- a/mplayer.c
+++ b/mplayer.c
@@ -4,7 +4,9 @@
#include <stdio.h>
#include <stdlib.h>
+#include <stdbool.h>
#include "config.h"
+#include "talloc.h"
#if defined(__MINGW32__) || defined(__CYGWIN__)
#define _UWIN 1 /*disable Non-underscored versions of non-ANSI functions as otherwise int eof would conflict with eof()*/
@@ -43,6 +45,8 @@
#include "m_option.h"
#include "m_config.h"
+#include "mplayer.h"
+#include "access_mpcontext.h"
#include "m_property.h"
#include "cfg-mplayer-def.h"
@@ -51,6 +55,7 @@
#include "subreader.h"
+#include "mp_osd.h"
#include "libvo/video_out.h"
#include "libvo/font_load.h"
@@ -78,6 +83,7 @@
#include "input/input.h"
+const int under_mencoder = 0;
int slave_mode=0;
int player_idle_mode=0;
int quiet=0;
@@ -129,27 +135,15 @@ int import_initial_playtree_into_gui(play_tree_t* my_playtree, m_config_t* confi
#include "parser-cfg.h"
#include "parser-mpcmd.h"
-m_config_t* mconfig;
-
//**************************************************************************//
// Config file
//**************************************************************************//
static int cfg_inc_verbose(m_option_t *conf){ ++verbose; return 0;}
-static int cfg_include(m_option_t *conf, char *filename){
- return m_config_parse_config_file(mconfig, filename);
-}
-
#include "get_path.h"
//**************************************************************************//
-// XScreensaver
-//**************************************************************************//
-
-void xscreensaver_heartbeat(void);
-
-//**************************************************************************//
//**************************************************************************//
// Input media streaming & demultiplexer:
//**************************************************************************//
@@ -177,6 +171,8 @@ static int max_framesize=0;
#include "mixer.h"
#include "mp_core.h"
+#include "options.h"
+#include "defaultopts.h"
//**************************************************************************//
//**************************************************************************//
@@ -186,24 +182,6 @@ static int max_framesize=0;
int noconsolecontrols=0;
//**************************************************************************//
-// Not all functions in mplayer.c take the context as an argument yet
-static MPContext mpctx_s = {
- .osd_function = OSD_PLAY,
- .begin_skip = MP_NOPTS_VALUE,
- .play_tree_step = 1,
- .global_sub_pos = -1,
- .set_of_sub_pos = -1,
- .file_format = DEMUXER_TYPE_UNKNOWN,
- .loop_times = -1,
-#ifdef CONFIG_DVBIN
- .last_dvb_step = 1,
-#endif
-};
-
-static MPContext *mpctx = &mpctx_s;
-
-int fixed_vo=0;
-
// benchmark:
double video_time_usage=0;
double vout_time_usage=0;
@@ -217,8 +195,6 @@ int benchmark=0;
int auto_quality=0;
static int output_quality=0;
-float playback_speed=1.0;
-
int use_gui=0;
#ifdef CONFIG_GUI
@@ -246,10 +222,6 @@ static m_time_size_t end_at = { .type = END_AT_NONE, .pos = 0 };
// A/V sync:
int autosync=0; // 30 might be a good default value.
-// may be changed by GUI: (FIXME!)
-float rel_seek_secs=0;
-int abs_seek_pos=0;
-
// codecs:
char **audio_codec_list=NULL; // override audio codec
char **video_codec_list=NULL; // override video codec
@@ -261,15 +233,10 @@ extern char *demuxer_name; // override demuxer
extern char *audio_demuxer_name; // override audio demuxer
extern char *sub_demuxer_name; // override sub demuxer
-// streaming:
-int audio_id=-1;
-int video_id=-1;
-int dvdsub_id=-2;
int vobsub_id=-1;
char* audio_lang=NULL;
char* dvdsub_lang=NULL;
static char* spudec_ifo=NULL;
-char* filename=NULL; //"MI2-Trailer.avi";
int forced_subs_only=0;
int file_filter=1;
@@ -290,8 +257,6 @@ static char *stream_dump_name="stream.dump";
// 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;
float audio_delay=0;
static int ignore_start=0;
@@ -304,10 +269,6 @@ static int audio_output_format=-1; // AF_FORMAT_UNKNOWN
static int play_n_frames=-1;
static int play_n_frames_mf=-1;
-// screen info:
-char** video_driver_list=NULL;
-char** audio_driver_list=NULL;
-
// sub:
char *font_name=NULL;
char *sub_font_name=NULL;
@@ -335,9 +296,9 @@ char* current_module=NULL; // for debugging
#ifdef CONFIG_MENU
#include "m_struct.h"
#include "libmenu/menu.h"
-void vf_menu_pause_update(struct vf_instance_s* vf);
+void vf_menu_pause_update(struct vf_instance* vf);
extern vf_info_t vf_info_menu;
-static vf_info_t* libmenu_vfs[] = {
+static const vf_info_t* const libmenu_vfs[] = {
&vf_info_menu,
NULL
};
@@ -359,7 +320,6 @@ short edl_decision = 0; ///< 1 when an EDL operation has been made.
FILE* edl_fd = NULL; ///< fd to write to when in -edlout mode.
int use_filedir_conf;
-static unsigned int initialized_flags=0;
#include "mpcommon.h"
#include "command.h"
@@ -402,7 +362,15 @@ int mpctx_get_osd_function(MPContext *mpctx)
return mpctx->osd_function;
}
-static int is_valid_metadata_type (metadata_t type) {
+static float get_relative_time(struct MPContext *mpctx)
+{
+ unsigned int new_time = GetTimer();
+ unsigned int delta = new_time - mpctx->last_time;
+ mpctx->last_time = new_time;
+ return delta * 0.000001;
+}
+
+static int is_valid_metadata_type(struct MPContext *mpctx, metadata_t type) {
switch (type)
{
/* check for valid video stream */
@@ -446,7 +414,7 @@ static int is_valid_metadata_type (metadata_t type) {
return 1;
}
-static char *get_demuxer_info (char *tag) {
+static char *get_demuxer_info(struct MPContext *mpctx, char *tag) {
char **info = mpctx->demuxer->info;
int n;
@@ -460,19 +428,20 @@ static char *get_demuxer_info (char *tag) {
return info[2*n+1] ? strdup (info[2*n+1]) : NULL;
}
-char *get_metadata (metadata_t type) {
+char *get_metadata(struct MPContext *mpctx, metadata_t type)
+{
char *meta = NULL;
sh_audio_t * const sh_audio = mpctx->sh_audio;
sh_video_t * const sh_video = mpctx->sh_video;
- if (!is_valid_metadata_type (type))
+ if (!is_valid_metadata_type(mpctx, type))
return NULL;
switch (type)
{
case META_NAME:
{
- return strdup (mp_basename2 (filename));
+ return strdup (mp_basename2 (mpctx->filename));
}
case META_VIDEO_CODEC:
@@ -535,25 +504,25 @@ char *get_metadata (metadata_t type) {
/* check for valid demuxer */
case META_INFO_TITLE:
- return get_demuxer_info ("Title");
+ return get_demuxer_info(mpctx, "Title");
case META_INFO_ARTIST:
- return get_demuxer_info ("Artist");
+ return get_demuxer_info(mpctx, "Artist");
case META_INFO_ALBUM:
- return get_demuxer_info ("Album");
+ return get_demuxer_info(mpctx, "Album");
case META_INFO_YEAR:
- return get_demuxer_info ("Year");
+ return get_demuxer_info(mpctx, "Year");
case META_INFO_COMMENT:
- return get_demuxer_info ("Comment");
+ return get_demuxer_info(mpctx, "Comment");
case META_INFO_TRACK:
- return get_demuxer_info ("Track");
+ return get_demuxer_info(mpctx, "Track");
case META_INFO_GENRE:
- return get_demuxer_info ("Genre");
+ return get_demuxer_info(mpctx, "Genre");
default:
break;
@@ -576,13 +545,13 @@ static void mp_dvdnav_context_free(MPContext *ctx){
}
#endif
-void uninit_player(unsigned int mask){
- mask=initialized_flags&mask;
+void uninit_player(struct MPContext *mpctx, unsigned int mask){
+ mask=mpctx->initialized_flags&mask;
mp_msg(MSGT_CPLAYER,MSGL_DBG2,"\n*** uninit(0x%X)\n",mask);
if(mask&INITIALIZED_ACODEC){
- initialized_flags&=~INITIALIZED_ACODEC;
+ mpctx->initialized_flags&=~INITIALIZED_ACODEC;
current_module="uninit_acodec";
if(mpctx->sh_audio) uninit_audio(mpctx->sh_audio);
#ifdef CONFIG_GUI
@@ -593,7 +562,7 @@ void uninit_player(unsigned int mask){
}
if(mask&INITIALIZED_VCODEC){
- initialized_flags&=~INITIALIZED_VCODEC;
+ mpctx->initialized_flags&=~INITIALIZED_VCODEC;
current_module="uninit_vcodec";
if(mpctx->sh_video) uninit_video(mpctx->sh_video);
mpctx->sh_video=NULL;
@@ -603,7 +572,7 @@ void uninit_player(unsigned int mask){
}
if(mask&INITIALIZED_DEMUXER){
- initialized_flags&=~INITIALIZED_DEMUXER;
+ mpctx->initialized_flags&=~INITIALIZED_DEMUXER;
current_module="free_demuxer";
if(mpctx->demuxer){
mpctx->stream=mpctx->demuxer->stream;
@@ -614,16 +583,16 @@ void uninit_player(unsigned int mask){
// kill the cache process:
if(mask&INITIALIZED_STREAM){
- initialized_flags&=~INITIALIZED_STREAM;
+ mpctx->initialized_flags&=~INITIALIZED_STREAM;
current_module="uninit_stream";
if(mpctx->stream) free_stream(mpctx->stream);
mpctx->stream=NULL;
}
if(mask&INITIALIZED_VO){
- initialized_flags&=~INITIALIZED_VO;
+ mpctx->initialized_flags&=~INITIALIZED_VO;
current_module="uninit_vo";
- mpctx->video_out->uninit();
+ vo_destroy(mpctx->video_out);
mpctx->video_out=NULL;
#ifdef CONFIG_DVDNAV
mp_dvdnav_context_free(mpctx);
@@ -632,7 +601,7 @@ void uninit_player(unsigned int mask){
// Must be after libvo uninit, as few vo drivers (svgalib) have tty code.
if(mask&INITIALIZED_GETCH2){
- initialized_flags&=~INITIALIZED_GETCH2;
+ mpctx->initialized_flags&=~INITIALIZED_GETCH2;
current_module="uninit_getch2";
mp_msg(MSGT_CPLAYER,MSGL_DBG2,"\n[[[uninit getch2]]]\n");
// restore terminal:
@@ -640,51 +609,42 @@ void uninit_player(unsigned int mask){
}
if(mask&INITIALIZED_VOBSUB){
- initialized_flags&=~INITIALIZED_VOBSUB;
+ mpctx->initialized_flags&=~INITIALIZED_VOBSUB;
current_module="uninit_vobsub";
if(vo_vobsub) vobsub_close(vo_vobsub);
vo_vobsub=NULL;
}
if (mask&INITIALIZED_SPUDEC){
- initialized_flags&=~INITIALIZED_SPUDEC;
+ mpctx->initialized_flags&=~INITIALIZED_SPUDEC;
current_module="uninit_spudec";
spudec_free(vo_spudec);
vo_spudec=NULL;
}
if(mask&INITIALIZED_AO){
- initialized_flags&=~INITIALIZED_AO;
+ mpctx->initialized_flags&=~INITIALIZED_AO;
current_module="uninit_ao";
if (mpctx->edl_muted) mixer_mute(&mpctx->mixer);
- mpctx->audio_out->uninit(mpctx->eof?0:1); mpctx->audio_out=NULL;
+ mpctx->audio_out->uninit(mpctx->stop_play != AT_END_OF_FILE);
+ mpctx->audio_out=NULL;
}
#ifdef CONFIG_GUI
if(mask&INITIALIZED_GUI){
- initialized_flags&=~INITIALIZED_GUI;
+ mpctx->initialized_flags&=~INITIALIZED_GUI;
current_module="uninit_gui";
guiDone();
}
#endif
- if(mask&INITIALIZED_INPUT){
- initialized_flags&=~INITIALIZED_INPUT;
- current_module="uninit_input";
- mp_input_uninit();
-#ifdef CONFIG_MENU
- if (use_menu)
- menu_uninit();
-#endif
- }
-
current_module=NULL;
}
-void exit_player_with_rc(exit_reason_t how, int rc){
-
+void exit_player_with_rc(struct MPContext *mpctx, exit_reason_t how, int rc)
+{
if (mpctx->user_muted && !mpctx->edl_muted) mixer_mute(&mpctx->mixer);
- uninit_player(INITIALIZED_ALL);
+ uninit_player(mpctx, INITIALIZED_ALL);
#if defined(__MINGW32__) || defined(__CYGWIN__)
timeEndPeriod(1);
#endif
@@ -692,18 +652,25 @@ void exit_player_with_rc(exit_reason_t how, int rc){
#ifdef CONFIG_GUI
if ( !use_gui )
#endif
- vo_uninit(); // Close the X11 connection (if any is open).
+ vo_uninit(mpctx->x11_state); // Close the X11 connection (if any is open).
+#endif
+
+ current_module="uninit_input";
+ mp_input_uninit(mpctx->input);
+#ifdef CONFIG_MENU
+ if (use_menu)
+ menu_uninit();
#endif
#ifdef CONFIG_FREETYPE
current_module="uninit_font";
- if (sub_font && sub_font != vo_font) free_font_desc(sub_font);
- sub_font = NULL;
- if (vo_font) free_font_desc(vo_font);
+ if (mpctx->osd && mpctx->osd->sub_font != vo_font)
+ free_font_desc(mpctx->osd->sub_font);
+ free_font_desc(vo_font);
vo_font = NULL;
done_freetype();
#endif
- free_osd_list();
+ osd_free(mpctx->osd);
#ifdef CONFIG_ASS
ass_library_done(ass_library);
@@ -712,12 +679,13 @@ void exit_player_with_rc(exit_reason_t how, int rc){
current_module="exit_player";
// free mplayer config
- if(mconfig)
- m_config_free(mconfig);
+ if(mpctx->mconfig)
+ m_config_free(mpctx->mconfig);
if(mpctx->playtree)
play_tree_free(mpctx->playtree, 1);
+ talloc_free(mpctx->key_fifo);
if(edl_records != NULL) free(edl_records); // free mem allocated for EDL
switch(how) {
@@ -741,8 +709,9 @@ void exit_player_with_rc(exit_reason_t how, int rc){
exit(rc);
}
-void exit_player(exit_reason_t how){
- exit_player_with_rc(how, 1);
+static void exit_player(struct MPContext *mpctx, exit_reason_t how)
+{
+ exit_player_with_rc(mpctx, how, 1);
}
#ifndef __MINGW32__
@@ -763,7 +732,6 @@ static void exit_sighandler(int x){
if (!crash_debug || x != SIGTRAP)
#endif
++sig_count;
- if(initialized_flags==0 && sig_count>1) exit(1);
if(sig_count==5)
{
/* We're crashing bad and can't uninit cleanly :(
@@ -828,17 +796,20 @@ static void exit_sighandler(int x){
exit(1);
}
-void mp_input_register_options(m_config_t* cfg);
-
#include "cfg-mplayer.h"
-static void parse_cfgfiles( m_config_t* conf )
+static int cfg_include(m_option_t *conf, char *filename)
+{
+ return m_config_parse_config_file(conf->priv, filename);
+}
+
+static void parse_cfgfiles(struct MPContext *mpctx, m_config_t* conf)
{
char *conffile;
int conffile_fd;
if (!disable_system_conf &&
m_config_parse_config_file(conf, MPLAYER_CONFDIR "/mplayer.conf") < 0)
- exit_player(EXIT_NONE);
+ exit_player(mpctx, EXIT_NONE);
if ((conffile = get_path("")) == NULL) {
mp_msg(MSGT_CPLAYER,MSGL_WARN,MSGTR_NoHomeDir);
} else {
@@ -858,7 +829,7 @@ if ((conffile = get_path("")) == NULL) {
}
if (!disable_user_conf &&
m_config_parse_config_file(conf, conffile) < 0)
- exit_player(EXIT_NONE);
+ exit_player(mpctx, EXIT_NONE);
free(conffile);
}
}
@@ -896,7 +867,7 @@ static void load_per_extension_config (m_config_t* conf, const char *const file)
m_profile_t *p;
/* does filename actually have an extension ? */
- str = strrchr (filename, '.');
+ str = strrchr (file, '.');
if (!str)
return;
@@ -964,38 +935,39 @@ static void load_per_file_config (m_config_t* conf, const char *const file)
* cache filling) if the operation fails we use this function to check
* if it was interrupted by the user.
* The function returns a new value for eof. */
-static int libmpdemux_was_interrupted(int eof) {
+static int libmpdemux_was_interrupted(struct MPContext *mpctx, int stop_play)
+{
mp_cmd_t* cmd;
- if((cmd = mp_input_get_cmd(0,0,0)) != NULL) {
+ if((cmd = mp_input_get_cmd(mpctx->input, 0,0,0)) != NULL) {
switch(cmd->id) {
case MP_CMD_QUIT:
- exit_player_with_rc(EXIT_QUIT, (cmd->nargs > 0)? cmd->args[0].v.i : 0);
+ exit_player_with_rc(mpctx, EXIT_QUIT, (cmd->nargs > 0)? cmd->args[0].v.i : 0);
case MP_CMD_PLAY_TREE_STEP: {
- eof = (cmd->args[0].v.i > 0) ? PT_NEXT_ENTRY : PT_PREV_ENTRY;
+ stop_play = (cmd->args[0].v.i > 0) ? PT_NEXT_ENTRY : PT_PREV_ENTRY;
mpctx->play_tree_step = (cmd->args[0].v.i == 0) ? 1 : cmd->args[0].v.i;
} break;
case MP_CMD_PLAY_TREE_UP_STEP: {
- eof = (cmd->args[0].v.i > 0) ? PT_UP_NEXT : PT_UP_PREV;
+ stop_play = (cmd->args[0].v.i > 0) ? PT_UP_NEXT : PT_UP_PREV;
} break;
case MP_CMD_PLAY_ALT_SRC_STEP: {
- eof = (cmd->args[0].v.i > 0) ? PT_NEXT_SRC : PT_PREV_SRC;
+ stop_play = (cmd->args[0].v.i > 0) ? PT_NEXT_SRC : PT_PREV_SRC;
} break;
}
mp_cmd_free(cmd);
}
- return eof;
+ return stop_play;
}
#define mp_basename(s) (strrchr(s,'\\')==NULL?(mp_basename2(s)):(strrchr(s,'\\')+1))
-static int playtree_add_playlist(play_tree_t* entry)
+static int playtree_add_playlist(struct MPContext *mpctx, play_tree_t* entry)
{
- play_tree_add_bpf(entry,filename);
+ play_tree_add_bpf(entry,mpctx->filename);
#ifdef CONFIG_GUI
if (use_gui) {
if (entry) {
- import_playtree_playlist_into_gui(entry, mconfig);
+ import_playtree_playlist_into_gui(entry, mpctx->mconfig);
play_tree_free_list(entry,1);
}
} else
@@ -1025,7 +997,7 @@ static int playtree_add_playlist(play_tree_t* entry)
return PT_NEXT_SRC;
}
-void add_subtitles(char *filename, float fps, int noerr)
+void add_subtitles(struct MPContext *mpctx, char *filename, float fps, int noerr)
{
sub_data *subd;
#ifdef CONFIG_ASS
@@ -1070,7 +1042,7 @@ void add_subtitles(char *filename, float fps, int noerr)
}
// FIXME: if/when the GUI calls this, global sub numbering gets (potentially) broken.
-void update_set_of_subtitles(void)
+void update_set_of_subtitles(struct MPContext *mpctx)
// subdata was changed, set_of_sub... have to be updated.
{
sub_data ** const set_of_subtitles = mpctx->set_of_subtitles;
@@ -1091,10 +1063,11 @@ void update_set_of_subtitles(void)
}
}
-void init_vo_spudec(void) {
+void init_vo_spudec(struct MPContext *mpctx)
+{
if (vo_spudec)
spudec_free(vo_spudec);
- initialized_flags &= ~INITIALIZED_SPUDEC;
+ mpctx->initialized_flags &= ~INITIALIZED_SPUDEC;
vo_spudec = NULL;
if (spudec_ifo) {
unsigned int palette[16], width, height;
@@ -1128,7 +1101,7 @@ void init_vo_spudec(void) {
}
if (vo_spudec!=NULL)
- initialized_flags|=INITIALIZED_SPUDEC;
+ mpctx->initialized_flags|=INITIALIZED_SPUDEC;
}
/*
@@ -1183,15 +1156,25 @@ static void sadd_hhmmssf(char *buf, unsigned *pos, int len, float time) {
saddf(buf, pos, len, "%02d.%1d", ss, f1);
}
-/**
- * \brief print the status line
- * \param a_pos audio position
- * \param a_v A-V desynchronization
- * \param corr amount out A-V synchronization
- */
-static void print_status(float a_pos, float a_v, float corr)
+static void print_status(struct MPContext *mpctx, double a_pos, bool at_frame)
{
+ struct MPOpts *opts = &mpctx->opts;
sh_video_t * const sh_video = mpctx->sh_video;
+
+ if (mpctx->sh_audio && a_pos == MP_NOPTS_VALUE)
+ a_pos = playing_audio_pts(mpctx);
+ if (mpctx->sh_audio && sh_video && at_frame) {
+ mpctx->last_av_difference = a_pos - sh_video->pts - audio_delay;
+ if (mpctx->last_av_difference > 0.5 && drop_frame_cnt > 50
+ && !mpctx->drop_message_shown) {
+ mp_msg(MSGT_AVSYNC,MSGL_WARN,MSGTR_SystemTooSlow);
+ mpctx->drop_message_shown = true;
+ }
+ }
+ if (quiet)
+ return;
+
+
int width;
char *line;
unsigned pos = 0;
@@ -1226,7 +1209,8 @@ static void print_status(float a_pos, float a_v, float corr)
// A-V sync
if (mpctx->sh_audio && sh_video)
- saddf(line, &pos, width, "A-V:%7.3f ct:%7.3f ", a_v, corr);
+ saddf(line, &pos, width, "A-V:%7.3f ct:%7.3f ",
+ mpctx->last_av_difference, mpctx->total_avsync_change);
// Video stats
if (sh_video)
@@ -1238,9 +1222,9 @@ static void print_status(float a_pos, float a_v, float corr)
if (sh_video) {
if (sh_video->timer > 0.5)
saddf(line, &pos, width, "%2d%% %2d%% %4.1f%% ",
- (int)(100.0*video_time_usage*playback_speed/(double)sh_video->timer),
- (int)(100.0*vout_time_usage*playback_speed/(double)sh_video->timer),
- (100.0*audio_time_usage*playback_speed/(double)sh_video->timer));
+ (int)(100.0*video_time_usage*opts->playback_speed/(double)sh_video->timer),
+ (int)(100.0*vout_time_usage*opts->playback_speed/(double)sh_video->timer),
+ (100.0*audio_time_usage*opts->playback_speed/(double)sh_video->timer));
else
saddf(line, &pos, width, "??%% ??%% ??,?%% ");
} else if (mpctx->sh_audio) {
@@ -1262,8 +1246,8 @@ static void print_status(float a_pos, float a_v, float corr)
#endif
// other
- if (playback_speed != 1)
- saddf(line, &pos, width, "%4.2fx ", playback_speed);
+ if (opts->playback_speed != 1)
+ saddf(line, &pos, width, "%4.2fx ", opts->playback_speed);
// end
if (erase_to_end_of_line) {
@@ -1283,8 +1267,9 @@ static void print_status(float a_pos, float a_v, float corr)
* \param sh_audio describes the requested input format of the chain.
* \param ao_data describes the requested output format of the chain.
*/
-int build_afilter_chain(sh_audio_t *sh_audio, ao_data_t *ao_data)
+int build_afilter_chain(struct MPContext *mpctx, sh_audio_t *sh_audio, ao_data_t *ao_data)
{
+ struct MPOpts *opts = &mpctx->opts;
int new_srate;
int result;
if (!sh_audio)
@@ -1297,17 +1282,17 @@ int build_afilter_chain(sh_audio_t *sh_audio, ao_data_t *ao_data)
}
if(af_control_any_rev(sh_audio->afilter,
AF_CONTROL_PLAYBACK_SPEED | AF_CONTROL_SET,
- &playback_speed)) {
+ &opts->playback_speed)) {
new_srate = sh_audio->samplerate;
} else {
- new_srate = sh_audio->samplerate * playback_speed;
+ new_srate = sh_audio->samplerate * opts->playback_speed;
if (new_srate != ao_data->samplerate) {
// limits are taken from libaf/af_resample.c
if (new_srate < 8000)
new_srate = 8000;
if (new_srate > 192000)
new_srate = 192000;
- playback_speed = (float)new_srate / (float)sh_audio->samplerate;
+ opts->playback_speed = (float)new_srate / (float)sh_audio->samplerate;
}
}
result = init_audio_filters(sh_audio, new_srate,
@@ -1418,7 +1403,8 @@ static void clear_osd_msgs(void) {
*
*/
-static mp_osd_msg_t* get_osd_msg(void) {
+static mp_osd_msg_t* get_osd_msg(struct MPContext *mpctx)
+{
mp_osd_msg_t *msg,*prev,*last = NULL;
static unsigned last_update = 0;
unsigned now = GetTimerMS();
@@ -1432,8 +1418,7 @@ static mp_osd_msg_t* get_osd_msg(void) {
osd_visible = 0;
vo_osd_progbar_type = -1; // disable
vo_osd_changed(OSDTYPE_PROGBAR);
- if (mpctx->osd_function != OSD_PAUSE)
- mpctx->osd_function = OSD_PLAY;
+ mpctx->osd_function = mpctx->paused ? OSD_PAUSE : OSD_PLAY;
}
}
@@ -1477,7 +1462,7 @@ static mp_osd_msg_t* get_osd_msg(void) {
*
*/
-void set_osd_bar(int type,const char* name,double min,double max,double val) {
+void set_osd_bar(struct MPContext *mpctx, int type,const char* name,double min,double max,double val) {
if(osd_level < 1) return;
@@ -1503,18 +1488,16 @@ void set_osd_bar(int type,const char* name,double min,double max,double val) {
*
*/
-static void update_osd_msg(void) {
+static void update_osd_msg(struct MPContext *mpctx)
+{
mp_osd_msg_t *msg;
- static char osd_text[64] = "";
- static char osd_text_timer[64];
-
- // we need some mem for vo_osd_text
- vo_osd_text = (unsigned char*)osd_text;
+ struct osd_state *osd = mpctx->osd;
+ char osd_text_timer[64];
// Look if we have a msg
- if((msg = get_osd_msg())) {
- if(strcmp(osd_text,msg->msg)) {
- strncpy((char*)osd_text, msg->msg, 63);
+ if((msg = get_osd_msg(mpctx))) {
+ if (strcmp(osd->osd_text, msg->msg)) {
+ strncpy(osd->osd_text, msg->msg, 63);
if(mpctx->sh_video) vo_osd_changed(OSDTYPE_OSD); else
if(term_osd) mp_msg(MSGT_CPLAYER,MSGL_STATUS,"%s%s\n",term_osd_esc,msg->msg);
}
@@ -1553,16 +1536,16 @@ static void update_osd_msg(void) {
if(mpctx->osd_show_percentage)
mpctx->osd_show_percentage--;
- if(strcmp(osd_text,osd_text_timer)) {
- strncpy(osd_text, osd_text_timer, 63);
+ if (strcmp(osd->osd_text, osd_text_timer)) {
+ strncpy(osd->osd_text, osd_text_timer, 63);
vo_osd_changed(OSDTYPE_OSD);
}
return;
}
// Clear the term osd line
- if(term_osd && osd_text[0]) {
- osd_text[0] = 0;
+ if (term_osd && osd->osd_text[0]) {
+ osd->osd_text[0] = 0;
printf("%s\n",term_osd_esc);
}
}
@@ -1571,7 +1554,9 @@ static void update_osd_msg(void) {
// OSDMsgStack
-void reinit_audio_chain(void) {
+void reinit_audio_chain(struct MPContext *mpctx)
+{
+ struct MPOpts *opts = &mpctx->opts;
if(mpctx->sh_audio){
current_module="init_audio_codec";
mp_msg(MSGT_CPLAYER,MSGL_INFO,"==========================================================================\n");
@@ -1580,7 +1565,7 @@ if(mpctx->sh_audio){
mpctx->d_audio->id = -2;
return;
} else
- initialized_flags|=INITIALIZED_ACODEC;
+ mpctx->initialized_flags|=INITIALIZED_ACODEC;
mp_msg(MSGT_CPLAYER,MSGL_INFO,"==========================================================================\n");
@@ -1597,24 +1582,24 @@ if(mpctx->sh_audio){
// output:
&ao_data.samplerate, &ao_data.channels, &ao_data.format)){
mp_msg(MSGT_CPLAYER,MSGL_ERR,MSGTR_AudioFilterChainPreinitError);
- exit_player(EXIT_ERROR);
+ exit_player(mpctx, EXIT_ERROR);
}
#endif
current_module="ao2_init";
- if(!(mpctx->audio_out=init_best_audio_out(audio_driver_list,
+ if(!(mpctx->audio_out=init_best_audio_out(opts->audio_driver_list,
0, // plugin flag
ao_data.samplerate,
ao_data.channels,
ao_data.format,0))){
// FAILED:
mp_msg(MSGT_CPLAYER,MSGL_ERR,MSGTR_CannotInitAO);
- uninit_player(INITIALIZED_ACODEC); // close codec
+ uninit_player(mpctx, INITIALIZED_ACODEC); // close codec
mpctx->sh_audio=mpctx->d_audio->sh=NULL; // -> nosound
mpctx->d_audio->id = -2;
return;
} else {
// SUCCESS:
- initialized_flags|=INITIALIZED_AO;
+ mpctx->initialized_flags|=INITIALIZED_AO;
mp_msg(MSGT_CPLAYER,MSGL_INFO,"AO: [%s] %dHz %dch %s (%d bytes per sample)\n",
mpctx->audio_out->info->short_name,
ao_data.samplerate, ao_data.channels,
@@ -1627,10 +1612,10 @@ if(mpctx->sh_audio){
// init audio filters:
#if 1
current_module="af_init";
- if(!build_afilter_chain(mpctx->sh_audio, &ao_data)) {
+ if(!build_afilter_chain(mpctx, mpctx->sh_audio, &ao_data)) {
mp_msg(MSGT_CPLAYER,MSGL_ERR,MSGTR_NoMatchingFilter);
// mp_msg(MSGT_CPLAYER,MSGL_ERR,"Couldn't find matching filter / ao format! -> NOSOUND\n");
-// uninit_player(INITIALIZED_ACODEC|INITIALIZED_AO); // close codec & ao
+// uninit_player(mpctx, INITIALIZED_ACODEC|INITIALIZED_AO); // close codec & ao
// sh_audio=mpctx->d_audio->sh=NULL; // -> nosound
}
#endif
@@ -1647,8 +1632,10 @@ if(mpctx->sh_audio){
// Return pts value corresponding to the end point of audio written to the
// ao so far.
-static double written_audio_pts(sh_audio_t *sh_audio, demux_stream_t *d_audio)
+static double written_audio_pts(struct MPContext *mpctx)
{
+ sh_audio_t *sh_audio = mpctx->sh_audio;
+ demux_stream_t *d_audio = mpctx->d_audio;
double buffered_output;
// first calculate the end pts of audio that has been output by decoder
double a_pts = sh_audio->pts;
@@ -1691,31 +1678,31 @@ static double written_audio_pts(sh_audio_t *sh_audio, demux_stream_t *d_audio)
// Filters divide audio length by playback_speed, so multiply by it
// to get the length in original units without speedup or slowdown
- a_pts -= buffered_output * playback_speed / ao_data.bps;
+ a_pts -= buffered_output * mpctx->opts.playback_speed / ao_data.bps;
return a_pts;
}
// Return pts value corresponding to currently playing audio.
-double playing_audio_pts(sh_audio_t *sh_audio, demux_stream_t *d_audio,
- const ao_functions_t *audio_out)
+double playing_audio_pts(struct MPContext *mpctx)
{
- return written_audio_pts(sh_audio, d_audio) - playback_speed *
- audio_out->get_delay();
+ return written_audio_pts(mpctx) - mpctx->opts.playback_speed *
+ mpctx->audio_out->get_delay();
}
-static int check_framedrop(double frame_time) {
+static int check_framedrop(struct MPContext *mpctx, double frame_time) {
+ struct MPOpts *opts = &mpctx->opts;
// check for frame-drop:
current_module = "check_framedrop";
if (mpctx->sh_audio && !mpctx->d_audio->eof) {
static int dropped_frames;
- float delay = playback_speed*mpctx->audio_out->get_delay();
+ float delay = opts->playback_speed*mpctx->audio_out->get_delay();
float d = delay-mpctx->delay;
++total_frame_cnt;
// we should avoid dropping too many frames in sequence unless we
// are too late. and we allow 100ms A-V delay here:
- if (d < -dropped_frames*frame_time-0.100 &&
- mpctx->osd_function != OSD_PAUSE) {
+ if (d < -dropped_frames*frame_time-0.100 && !mpctx->paused
+ && !mpctx->update_video_immediately) {
++drop_frame_cnt;
++dropped_frames;
return frame_dropping;
@@ -1725,53 +1712,12 @@ static int check_framedrop(double frame_time) {
return 0;
}
-static int generate_video_frame(sh_video_t *sh_video, demux_stream_t *d_video)
-{
- unsigned char *start;
- int in_size;
- int hit_eof=0;
- double pts;
-
- while (1) {
- int drop_frame = check_framedrop(sh_video->frametime);
- void *decoded_frame;
- current_module = "decode video";
- // XXX Time used in this call is not counted in any performance
- // timer now, OSD is not updated correctly for filter-added frames
- if (vf_output_queued_frame(sh_video->vfilter))
- break;
- current_module = "video_read_frame";
- in_size = ds_get_packet_pts(d_video, &start, &pts);
- if (in_size < 0) {
- // try to extract last frames in case of decoder lag
- in_size = 0;
- pts = 1e300;
- hit_eof = 1;
- }
- if (in_size > max_framesize)
- max_framesize = in_size;
- current_module = "decode video";
- decoded_frame = decode_video(sh_video, start, in_size, drop_frame, pts);
- if (decoded_frame) {
- update_subtitles(sh_video, mpctx->d_sub, 0);
- update_teletext(sh_video, mpctx->demuxer, 0);
- update_osd_msg();
- current_module = "filter video";
- if (filter_video(sh_video, decoded_frame, sh_video->pts))
- break;
- } else if (drop_frame)
- return -1;
- if (hit_eof)
- return 0;
- }
- return 1;
-}
#ifdef HAVE_RTC
int rtc_fd = -1;
#endif
-static float timing_sleep(float time_frame)
+static float timing_sleep(struct MPContext *mpctx, float time_frame)
{
#ifdef HAVE_RTC
if (rtc_fd >= 0){
@@ -1781,7 +1727,7 @@ static float timing_sleep(float time_frame)
unsigned long rtc_ts;
if (read(rtc_fd, &rtc_ts, sizeof(rtc_ts)) <= 0)
mp_msg(MSGT_CPLAYER, MSGL_ERR, MSGTR_LinuxRTCReadError, strerror(errno));
- time_frame -= GetRelativeTime();
+ time_frame -= get_relative_time(mpctx);
}
} else
#endif
@@ -1792,14 +1738,14 @@ static float timing_sleep(float time_frame)
current_module = "sleep_timer";
while (time_frame > margin) {
usec_sleep(1000000 * (time_frame - margin));
- time_frame -= GetRelativeTime();
+ time_frame -= get_relative_time(mpctx);
}
if (softsleep){
current_module = "sleep_soft";
if (time_frame < 0)
mp_msg(MSGT_AVSYNC, MSGL_WARN, MSGTR_SoftsleepUnderflow);
while (time_frame > 0)
- time_frame-=GetRelativeTime(); // burn the CPU
+ time_frame -= get_relative_time(mpctx); // burn the CPU
}
}
return time_frame;
@@ -1836,6 +1782,7 @@ static mp_image_t * mp_dvdnav_copy_mpi(mp_image_t *to_mpi,
}
static void mp_dvdnav_reset_stream (MPContext *ctx) {
+ struct MPOpts *opts = &ctx->opts;
if (ctx->sh_video) {
/// clear video pts
ctx->d_video->pts = 0.0f;
@@ -1860,7 +1807,7 @@ static void mp_dvdnav_reset_stream (MPContext *ctx) {
resync_audio_stream(ctx->sh_audio);
}
- if (ctx->d_sub) dvdsub_id = -2;
+ if (ctx->d_sub) opts->sub_id = -2;
audio_delay = 0.0f;
@@ -1869,7 +1816,8 @@ static void mp_dvdnav_reset_stream (MPContext *ctx) {
}
/// Restore last decoded DVDNAV (still frame)
-static mp_image_t *mp_dvdnav_restore_smpi(int *in_size,
+static mp_image_t *mp_dvdnav_restore_smpi(struct MPContext *mpctx,
+ int *in_size,
unsigned char **start,
mp_image_t *decoded_frame)
{
@@ -1913,7 +1861,7 @@ static mp_image_t *mp_dvdnav_restore_smpi(int *in_size,
}
/// Save last decoded DVDNAV (still frame)
-static void mp_dvdnav_save_smpi(int in_size,
+static void mp_dvdnav_save_smpi(struct MPContext *mpctx, int in_size,
unsigned char *start,
mp_image_t *decoded_frame)
{
@@ -1934,72 +1882,44 @@ static void mp_dvdnav_save_smpi(int in_size,
}
#endif /* CONFIG_DVDNAV */
-static void adjust_sync_and_print_status(int between_frames, float timing_error)
+/* Modify video timing to match the audio timeline. There are two main
+ * reasons this is needed. First, video and audio can start from different
+ * positions at beginning of file or after a seek (MPlayer starts both
+ * immediately even if they have different pts). Second, the file can have
+ * audio timestamps that are inconsistent with the duration of the audio
+ * packets, for example two consecutive timestamp values differing by
+ * one second but only a packet with enough samples for half a second
+ * of playback between them.
+ */
+static void adjust_sync(struct MPContext *mpctx, double frame_time)
{
- current_module="av_sync";
+ struct MPOpts *opts = &mpctx->opts;
+ current_module = "av_sync";
- if(mpctx->sh_audio){
- double a_pts, v_pts;
-
- if (autosync)
- /*
- * If autosync is enabled, the value for delay must be calculated
- * a bit differently. It is set only to the difference between
- * the audio and video timers. Any attempt to include the real
- * or corrected delay causes the pts_correction code below to
- * try to correct for the changes in delay which autosync is
- * trying to measure. This keeps the two from competing, but still
- * allows the code to correct for PTS drift *only*. (Using a delay
- * value here, even a "corrected" one, would be incompatible with
- * autosync mode.)
- */
- a_pts = written_audio_pts(mpctx->sh_audio, mpctx->d_audio) - mpctx->delay;
- else
- a_pts = playing_audio_