From cde59e913f2c1c2cca27d10daddb54b4de6cc90a Mon Sep 17 00:00:00 2001 From: wm4 Date: Sun, 19 Aug 2012 18:11:53 +0200 Subject: core: move implementation for -audiofile to the frontend This should behave as before, with the same set of caveats. --- Makefile | 1 - libmpdemux/demux_demuxers.c | 175 -------------------------------------------- libmpdemux/demuxer.c | 153 ++++++-------------------------------- libmpdemux/demuxer.h | 9 +-- mplayer.c | 102 ++++++++++++++++++++++++++ timeline/tl_matroska.c | 2 +- 6 files changed, 129 insertions(+), 313 deletions(-) delete mode 100644 libmpdemux/demux_demuxers.c diff --git a/Makefile b/Makefile index 99b310d8d2..495a42824e 100644 --- a/Makefile +++ b/Makefile @@ -227,7 +227,6 @@ SRCS_COMMON = asxparser.c \ libmpdemux/demuxer.c \ libmpdemux/demux_asf.c \ libmpdemux/demux_avi.c \ - libmpdemux/demux_demuxers.c \ libmpdemux/demux_edl.c \ libmpdemux/demux_cue.c \ libmpdemux/demux_lavf.c \ diff --git a/libmpdemux/demux_demuxers.c b/libmpdemux/demux_demuxers.c deleted file mode 100644 index b66bf57bdb..0000000000 --- a/libmpdemux/demux_demuxers.c +++ /dev/null @@ -1,175 +0,0 @@ -/* - * This file is part of MPlayer. - * - * MPlayer is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * MPlayer is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with MPlayer; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "config.h" -#include "mp_msg.h" - -#include -#include -#include "stream/stream.h" -#include "demuxer.h" -#include "stheader.h" -#include "talloc.h" - -typedef struct dd_priv { - demuxer_t* vd; - demuxer_t* ad; - demuxer_t* sd; -} dd_priv_t; - -extern const demuxer_desc_t demuxer_desc_demuxers; - -demuxer_t* new_demuxers_demuxer(demuxer_t* vd, demuxer_t* ad, demuxer_t* sd) { - demuxer_t* ret; - dd_priv_t* priv; - - ret = talloc_zero(NULL, struct demuxer); - - priv = malloc(sizeof(dd_priv_t)); - priv->vd = vd; - priv->ad = ad; - priv->sd = sd; - ret->priv = priv; - - ret->type = ret->file_format = DEMUXER_TYPE_DEMUXERS; - // Video is the most important :-) - ret->stream = vd->stream; - ret->seekable = vd->seekable && ad->seekable && sd->seekable; - ret->stream_pts = MP_NOPTS_VALUE; - - ret->video = vd->video; - ret->audio = ad->audio; - ret->sub = sd->sub; - if (sd && sd != vd && sd != ad) sd->sub->non_interleaved = 1; - - // without these, demux_demuxers_fill_buffer will never be called, - // but they break the demuxer-specific code in video.c -#if 0 - if (vd) vd->video->demuxer = ret; - if (ad) ad->audio->demuxer = ret; - if (sd) sd->sub->demuxer = ret; - - // HACK?, necessary for subtitle (and audio and video when implemented) switching - memcpy(ret->v_streams, vd->v_streams, sizeof(ret->v_streams)); - memcpy(ret->a_streams, ad->a_streams, sizeof(ret->a_streams)); - memcpy(ret->s_streams, sd->s_streams, sizeof(ret->s_streams)); -#endif - - ret->desc = &demuxer_desc_demuxers; - - return ret; -} - -static int demux_demuxers_fill_buffer(demuxer_t *demux,demux_stream_t *ds) { - dd_priv_t* priv; - - priv=demux->priv; - - // HACK: make sure the subtitles get properly interleaved if with -subfile - if (priv->sd && priv->sd->sub != ds && - priv->sd != priv->vd && priv->sd != priv->ad) - ds_get_next_pts(priv->sd->sub); - if(priv->vd && priv->vd->video == ds) - return demux_fill_buffer(priv->vd,ds); - else if(priv->ad && priv->ad->audio == ds) - return demux_fill_buffer(priv->ad,ds); - else if(priv->sd && priv->sd->sub == ds) - return demux_fill_buffer(priv->sd,ds); - - mp_tmsg(MSGT_DEMUX,MSGL_WARN,"fill_buffer error: bad demuxer: not vd, ad or sd.\n"); - return 0; -} - -static void demux_demuxers_seek(demuxer_t *demuxer,float rel_seek_secs,float audio_delay,int flags) { - dd_priv_t* priv; - float pos; - priv=demuxer->priv; - - priv->ad->stream->eof = 0; - priv->sd->stream->eof = 0; - - // Seek video - demux_seek(priv->vd,rel_seek_secs,audio_delay,flags); - // Get the new pos - pos = demuxer->video->pts; - if (pos == MP_NOPTS_VALUE) { - demux_fill_buffer(priv->vd, demuxer->video); - if (demuxer->video->first) - pos = demuxer->video->first->pts; - } - - if(priv->ad != priv->vd && demuxer->audio->sh) { - sh_audio_t* sh = demuxer->audio->sh; - demux_seek(priv->ad,pos,audio_delay,1); - // In case the demuxer don't set pts - if(!demuxer->audio->pts) - demuxer->audio->pts = pos-((ds_tell_pts(demuxer->audio)-sh->a_in_buffer_len)/(float)sh->i_bps); - } - - if(priv->sd != priv->vd) - demux_seek(priv->sd,pos,audio_delay,1); - -} - -static void demux_close_demuxers(demuxer_t* demuxer) { - dd_priv_t* priv = demuxer->priv; - stream_t *s; - - if(priv->vd) - free_demuxer(priv->vd); - if(priv->ad && priv->ad != priv->vd) { - // That's a hack to free the audio file stream - // It's ok atm but we shouldn't free that here - s = priv->ad->stream; - free_demuxer(priv->ad); - free_stream(s); - } if(priv->sd && priv->sd != priv->vd && priv->sd != priv->ad) { - s = priv->sd->stream; - free_demuxer(priv->sd); - free_stream(s); - } - - free(priv); -} - - -static int demux_demuxers_control(demuxer_t *demuxer,int cmd, void *arg){ - dd_priv_t* priv = demuxer->priv; - switch (cmd) { - case DEMUXER_CTRL_GET_TIME_LENGTH: - case DEMUXER_CTRL_GET_PERCENT_POS: - return demux_control(priv->vd, cmd, arg); - } - return DEMUXER_CTRL_NOTIMPL; -} - -const demuxer_desc_t demuxer_desc_demuxers = { - "Demuxers demuxer", - "", // Not selectable - "", - "?", - "internal use only", - DEMUXER_TYPE_DEMUXERS, - 0, // no autodetect - NULL, - demux_demuxers_fill_buffer, - NULL, - demux_close_demuxers, - demux_demuxers_seek, - demux_demuxers_control -}; diff --git a/libmpdemux/demuxer.c b/libmpdemux/demuxer.c index 13f5fab268..798f701305 100644 --- a/libmpdemux/demuxer.c +++ b/libmpdemux/demuxer.c @@ -419,9 +419,6 @@ void free_demuxer(demuxer_t *demuxer) demuxer->desc->shortdesc, demuxer); if (demuxer->desc->close) demuxer->desc->close(demuxer); - // Very ugly hack to make it behave like old implementation - if (demuxer->desc->type == DEMUXER_TYPE_DEMUXERS) - goto skip_streamfree; // free streams: for (i = 0; i < MAX_A_STREAMS; i++) if (demuxer->a_streams[i]) @@ -436,7 +433,6 @@ void free_demuxer(demuxer_t *demuxer) free_demuxer_stream(demuxer->audio); free_demuxer_stream(demuxer->video); free_demuxer_stream(demuxer->sub); - skip_streamfree: free(demuxer->filename); talloc_free(demuxer); } @@ -888,6 +884,11 @@ static struct demuxer *open_given_type(struct MPOpts *opts, demuxer = demux2; } demuxer->file_format = fformat; + opts->correct_pts = opts->user_correct_pts; + if (opts->correct_pts < 0) + opts->correct_pts = + demux_control(demuxer, DEMUXER_CTRL_CORRECT_PTS, + NULL) == DEMUXER_CTRL_OK; return demuxer; } else { // demux_mov can return playlist instead of mov @@ -911,16 +912,25 @@ static struct demuxer *open_given_type(struct MPOpts *opts, return NULL; } -static struct demuxer *demux_open_stream(struct MPOpts *opts, - struct stream *stream, - int file_format, bool force, - int audio_id, int video_id, int sub_id, - char *filename, - struct demuxer_params *params) +struct demuxer *demux_open_withparams(struct MPOpts *opts, + struct stream *stream, int file_format, + char *force_format, int audio_id, + int video_id, int sub_id, char *filename, + struct demuxer_params *params) { struct demuxer *demuxer = NULL; const struct demuxer_desc *desc; + int force = 0; + int demuxer_type; + if ((demuxer_type = get_demuxer_type_from_name(force_format, &force)) < 0) { + mp_msg(MSGT_DEMUXER, MSGL_ERR, "Demuxer %s does not exist.\n", + force_format); + return NULL; + } + if (demuxer_type) + file_format = demuxer_type; + // Some code (e.g. dvd stuff, network code, or extension.c) explicitly // request certain file formats. The list of formats are always handled by // libavformat. @@ -986,129 +996,10 @@ struct demuxer *demux_open(struct MPOpts *opts, stream_t *vs, int file_format, int audio_id, int video_id, int sub_id, char *filename) { - return demux_open_withparams(opts, vs, file_format, audio_id, video_id, - sub_id, filename, NULL); + return demux_open_withparams(opts, vs, file_format, opts->demuxer_name, + audio_id, video_id, sub_id, filename, NULL); } -struct demuxer *demux_open_withparams(struct MPOpts *opts, stream_t *vs, - int file_format, int audio_id, int video_id, int dvdsub_id, - char *filename, struct demuxer_params *params) -{ - stream_t *as = NULL, *ss = NULL; - demuxer_t *vd, *ad = NULL, *sd = NULL; - demuxer_t *res; - int afmt = DEMUXER_TYPE_UNKNOWN, sfmt = DEMUXER_TYPE_UNKNOWN; - int demuxer_type; - int audio_demuxer_type = 0, sub_demuxer_type = 0; - int demuxer_force = 0, audio_demuxer_force = 0, sub_demuxer_force = 0; - - if ((demuxer_type = - get_demuxer_type_from_name(opts->demuxer_name, &demuxer_force)) < 0) { - mp_msg(MSGT_DEMUXER, MSGL_ERR, "-demuxer %s does not exist.\n", - opts->demuxer_name); - return NULL; - } - if ((audio_demuxer_type = - get_demuxer_type_from_name(opts->audio_demuxer_name, - &audio_demuxer_force)) < 0) { - mp_msg(MSGT_DEMUXER, MSGL_ERR, "-audio-demuxer %s does not exist.\n", - opts->audio_demuxer_name); - if (opts->audio_stream) - return NULL; - } - if ((sub_demuxer_type = - get_demuxer_type_from_name(opts->sub_demuxer_name, - &sub_demuxer_force)) < 0) { - mp_msg(MSGT_DEMUXER, MSGL_ERR, "-sub-demuxer %s does not exist.\n", - opts->sub_demuxer_name); - if (opts->sub_stream) - return NULL; - } - - if (opts->audio_stream) { - as = open_stream(opts->audio_stream, 0, &afmt); - if (!as) { - mp_tmsg(MSGT_DEMUXER, MSGL_ERR, "Cannot open audio stream: %s\n", - opts->audio_stream); - return NULL; - } - if (opts->audio_stream_cache) { - if (!stream_enable_cache - (as, opts->audio_stream_cache * 1024, - opts->audio_stream_cache * 1024 * - (opts->stream_cache_min_percent / 100.0), - opts->audio_stream_cache * 1024 * - (opts->stream_cache_seek_min_percent / 100.0))) { - free_stream(as); - mp_msg(MSGT_DEMUXER, MSGL_ERR, - "Can't enable audio stream cache\n"); - return NULL; - } - } - } - if (opts->sub_stream) { - ss = open_stream(opts->sub_stream, 0, &sfmt); - if (!ss) { - mp_tmsg(MSGT_DEMUXER, MSGL_ERR, "Cannot open subtitle stream: %s\n", - opts->sub_stream); - return NULL; - } - } - - vd = demux_open_stream(opts, vs, demuxer_type ? demuxer_type : file_format, - demuxer_force, opts->audio_stream ? -2 : audio_id, - video_id, opts->sub_stream ? -2 : dvdsub_id, - filename, params); - if (!vd) { - if (as) - free_stream(as); - if (ss) - free_stream(ss); - return NULL; - } - if (as) { - ad = demux_open_stream(opts, as, - audio_demuxer_type ? audio_demuxer_type : afmt, - audio_demuxer_force, audio_id, -2, -2, - opts->audio_stream, params); - if (!ad) { - mp_tmsg(MSGT_DEMUXER, MSGL_WARN, "Failed to open audio demuxer: %s\n", - opts->audio_stream); - free_stream(as); - } else if (ad->audio->sh - && ((sh_audio_t *) ad->audio->sh)->format == 0x55) // MP3 - opts->hr_mp3_seek = 1; // Enable high res seeking - } - if (ss) { - sd = demux_open_stream(opts, ss, - sub_demuxer_type ? sub_demuxer_type : sfmt, - sub_demuxer_force, -2, -2, dvdsub_id, - opts->sub_stream, params); - if (!sd) { - mp_tmsg(MSGT_DEMUXER, MSGL_WARN, - "Failed to open subtitle demuxer: %s\n", opts->sub_stream); - free_stream(ss); - } - } - - if (ad && sd) - res = new_demuxers_demuxer(vd, ad, sd); - else if (ad) - res = new_demuxers_demuxer(vd, ad, vd); - else if (sd) - res = new_demuxers_demuxer(vd, vd, sd); - else - res = vd; - - opts->correct_pts = opts->user_correct_pts; - if (opts->correct_pts < 0) - opts->correct_pts = - demux_control(vd ? vd : res, DEMUXER_CTRL_CORRECT_PTS, - NULL) == DEMUXER_CTRL_OK; - return res; -} - - void demux_flush(demuxer_t *demuxer) { ds_free_packs(demuxer->video); diff --git a/libmpdemux/demuxer.h b/libmpdemux/demuxer.h index 50ab0525c4..cf81ce988c 100644 --- a/libmpdemux/demuxer.h +++ b/libmpdemux/demuxer.h @@ -72,7 +72,6 @@ enum demuxer_type { * as demuxer type by the user (-demuxer option). */ DEMUXER_TYPE_END, - DEMUXER_TYPE_DEMUXERS, DEMUXER_TYPE_PLAYLIST, }; @@ -352,14 +351,14 @@ struct demuxer *demux_open(struct MPOpts *opts, struct stream *stream, char *filename); struct demuxer *demux_open_withparams(struct MPOpts *opts, - struct stream *stream, int file_format, int aid, int vid, int sid, - char *filename, struct demuxer_params *params); + struct stream *stream, int file_format, + char *force_format, int audio_id, + int video_id, int sub_id, char *filename, + struct demuxer_params *params); void demux_flush(struct demuxer *demuxer); int demux_seek(struct demuxer *demuxer, float rel_seek_secs, float audio_delay, int flags); -struct demuxer *new_demuxers_demuxer(struct demuxer *vd, struct demuxer *ad, - struct demuxer *sd); // AVI demuxer params: extern int index_mode; // -1=untouched 0=don't use index 1=use (generate) index diff --git a/mplayer.c b/mplayer.c index e7565adfc5..06a57b597f 100644 --- a/mplayer.c +++ b/mplayer.c @@ -2754,6 +2754,33 @@ static int seek(MPContext *mpctx, struct seek_params seek, return -1; } + // If audio or demuxer subs come from different files, seek them too: + bool have_external_tracks = false; + for (int type = 0; type < STREAM_TYPE_COUNT; type++) { + struct track *track = mpctx->current_track[type]; + have_external_tracks |= track && track->is_external && track->demuxer; + } + if (have_external_tracks) { + double main_new_pos = MP_NOPTS_VALUE; + if (seek.type == MPSEEK_ABSOLUTE) + main_new_pos = seek.amount - mpctx->video_offset; + for (int type = 0; type < STREAM_TYPE_COUNT; type++) { + struct demux_stream *ds = mpctx->demuxer->ds[type]; + if (ds->sh && main_new_pos == MP_NOPTS_VALUE) { + demux_fill_buffer(mpctx->demuxer, ds); + if (ds->first) + main_new_pos = ds->first->pts; + } + } + assert(main_new_pos != MP_NOPTS_VALUE); + for (int type = 0; type < STREAM_TYPE_COUNT; type++) { + struct track *track = mpctx->current_track[type]; + if (track && track->is_external && track->demuxer) + demux_seek(track->demuxer, main_new_pos, audio_delay, + SEEK_ABSOLUTE); + } + } + if (need_reset) reinit_audio_chain(mpctx); /* If we just reinitialized audio it doesn't need to be reset, @@ -3498,6 +3525,79 @@ static void open_subtitles_from_options(struct MPContext *mpctx) } } +static void open_external_file(struct MPContext *mpctx, char *filename, + char *demuxer_name, int stream_cache, + enum stream_type filter) +{ + if (!filename) + return; + int format = 0; + struct stream *stream = open_stream(filename, &mpctx->opts, &format); + if (!stream) + goto err_out; + if (stream_cache) { + if (!stream_enable_cache(stream, stream_cache * 1024, + stream_cache * 1024 * + (mpctx->opts.stream_cache_min_percent / 100.0), + stream_cache * 1024 * + (mpctx->opts.stream_cache_seek_min_percent / 100.0))) + { + free_stream(stream); + mp_msg(MSGT_CPLAYER, MSGL_ERR, + "Can't enable external file stream cache\n"); + return; + } + } + // deal with broken demuxers: preselect streams + int vs = -2, as = -2, ss = -2; + switch (filter) { + case STREAM_VIDEO: vs = -1; break; + case STREAM_AUDIO: as = -1; break; + case STREAM_SUB: ss = -1; break; + } + vs = -1; // avi can't go without video + struct demuxer *demuxer = + demux_open_withparams(&mpctx->opts, stream, format, demuxer_name, + as, vs, ss, filename, NULL); + if (!demuxer) { + free_stream(stream); + goto err_out; + } + int num_added = 0; + for (int n = 0; n < demuxer->num_streams; n++) { + struct sh_stream *stream = demuxer->streams[n]; + if (stream->type == filter) { + struct track *t = add_stream_track(mpctx, stream, false); + t->is_external = true; + } + } + if (num_added == 0) { + mp_msg(MSGT_CPLAYER, MSGL_WARN, "No streams added from file %s.\n", + filename); + } + MP_TARRAY_APPEND(NULL, mpctx->sources, mpctx->num_sources, demuxer); + return; + +err_out: + mp_msg(MSGT_CPLAYER, MSGL_ERR, "Can not open external file %s.\n", + filename); +} + +static void open_audiofiles_from_options(struct MPContext *mpctx) +{ + struct MPOpts *opts = &mpctx->opts; + open_external_file(mpctx, opts->audio_stream, opts->audio_demuxer_name, + opts->audio_stream_cache, STREAM_AUDIO); +} + +// Just for -subfile. open_subtitles_from_options handles -sub text sub files. +static void open_subfiles_from_options(struct MPContext *mpctx) +{ + struct MPOpts *opts = &mpctx->opts; + open_external_file(mpctx, opts->sub_stream, opts->sub_demuxer_name, + 0, STREAM_SUB); +} + static void print_timeline(struct MPContext *mpctx) { if (mpctx->timeline) { @@ -3714,6 +3814,8 @@ goto_enable_cache: open_subtitles_from_options(mpctx); open_vobsubs_from_options(mpctx); + open_audiofiles_from_options(mpctx); + open_subfiles_from_options(mpctx); mpctx->current_track[STREAM_VIDEO] = select_track(mpctx, STREAM_VIDEO, mpctx->opts.video_id, NULL, true); diff --git a/timeline/tl_matroska.c b/timeline/tl_matroska.c index 46c6d80ae4..4edc8d494e 100644 --- a/timeline/tl_matroska.c +++ b/timeline/tl_matroska.c @@ -141,7 +141,7 @@ static int find_ordered_chapter_sources(struct MPContext *mpctx, if (!s) continue; struct demuxer *d = demux_open_withparams(&mpctx->opts, s, - DEMUXER_TYPE_MATROSKA, mpctx->opts.audio_id, + DEMUXER_TYPE_MATROSKA, NULL, mpctx->opts.audio_id, mpctx->opts.video_id, mpctx->opts.sub_id, filenames[i], &(struct demuxer_params){.matroska_wanted_uids = uid_map}); -- cgit v1.2.3