From 3269bd178020c5d821e8b2d1fd807a38d63e93ce Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 12 Jul 2013 21:58:11 +0200 Subject: demux: rewrite probing and demuxer initialization Get rid of the strange and messy reliance on DEMUXER_TYPE_ constants. Instead of having two open functions for the demuxer callbacks (which somehow are both optional, but you can also decide to implement both...), just have one function. This function takes a parameter that tells the demuxer how strictly it should check for the file headers. This is a nice simplification and allows more flexibility. Remove the file extension code. This literally did nothing (anymore). Change demux_lavf so that we check our other builtin demuxers first before libavformat tries to guess by file extension. --- DOCS/man/en/options.rst | 6 -- Makefile | 1 - core/mplayer.c | 6 +- core/options.c | 2 - core/options.h | 1 - core/timeline/tl_matroska.c | 2 +- demux/demux.c | 220 ++++++++++++++------------------------------ demux/demux.h | 50 ++++------ demux/demux_cue.c | 23 +++-- demux/demux_edl.c | 23 ++--- demux/demux_lavf.c | 18 ++-- demux/demux_libass.c | 61 ++++++------ demux/demux_mf.c | 77 +++++++--------- demux/demux_mkv.c | 5 +- demux/demux_mng.c | 31 +++---- demux/demux_rawaudio.c | 7 +- demux/demux_rawvideo.c | 7 +- demux/demux_subreader.c | 9 +- demux/extension.c | 101 -------------------- stream/stream_dvb.c | 3 +- stream/stream_mf.c | 2 +- stream/tv.c | 5 +- 22 files changed, 223 insertions(+), 437 deletions(-) delete mode 100644 demux/extension.c diff --git a/DOCS/man/en/options.rst b/DOCS/man/en/options.rst index d891766f6b..a6e5fee7ed 100644 --- a/DOCS/man/en/options.rst +++ b/DOCS/man/en/options.rst @@ -690,12 +690,6 @@ Stop at given absolute time. Use ``--length`` if the time should be relative to ``--start``. See ``--start`` for valid option values and examples. -``--no-extbased``, ``--extbased`` - ``--no-extbased`` disables extension-based demuxer selection. By default, - when the file type (demuxer) cannot be detected reliably (the file has no - header or it is not reliable enough), the filename extension is used to - select the demuxer. Always falls back on content-based demuxer selection. - ``--field-dominance=`` Set first field for interlaced content. Useful for deinterlacers that double the framerate: ``--vf=yadif=1`` and ``--vo=vdpau:deint``. diff --git a/Makefile b/Makefile index 3e0af2d55e..a1de600dcc 100644 --- a/Makefile +++ b/Makefile @@ -196,7 +196,6 @@ SOURCES = talloc.c \ demux/demux_rawaudio.c \ demux/demux_rawvideo.c \ demux/ebml.c \ - demux/extension.c \ demux/mf.c \ osdep/io.c \ osdep/numcores.c \ diff --git a/core/mplayer.c b/core/mplayer.c index ecaa9dd10b..de6b4132fd 100644 --- a/core/mplayer.c +++ b/core/mplayer.c @@ -2297,9 +2297,9 @@ int reinit_video_chain(struct MPContext *mpctx) goto no_video; } - mp_tmsg(MSGT_CPLAYER, MSGL_V, "[V] filefmt:%d fourcc:0x%X " + mp_tmsg(MSGT_CPLAYER, MSGL_V, "[V] fourcc:0x%X " "size:%dx%d fps:%5.3f\n", - mpctx->master_demuxer->file_format, mpctx->sh_video->format, + mpctx->sh_video->format, mpctx->sh_video->disp_w, mpctx->sh_video->disp_h, mpctx->sh_video->fps); if (opts->force_fps) @@ -2459,7 +2459,7 @@ static struct demux_packet *video_read_frame(struct MPContext *mpctx) double d = next_pts == MP_NOPTS_VALUE ? sh_video->last_pts - pts1 : next_pts - sh_video->last_pts; if (d >= 0) { - if (demuxer->file_format == DEMUXER_TYPE_TV) { + if (demuxer->type == DEMUXER_TYPE_TV) { if (d > 0) sh_video->fps = 1.0f / d; frame_time = d; diff --git a/core/options.c b/core/options.c index d676cb4948..2298d112b8 100644 --- a/core/options.c +++ b/core/options.c @@ -399,7 +399,6 @@ const m_option_t mp_opts[] = { OPT_STRING("demuxer", demuxer_name, 0), OPT_STRING("audio-demuxer", audio_demuxer_name, 0), OPT_STRING("sub-demuxer", sub_demuxer_name, 0), - OPT_FLAG("extbased", extension_parsing, 0), {"mf", (void *) mfopts_conf, CONF_TYPE_SUBCONFIG, 0,0,0, NULL}, #ifdef CONFIG_RADIO @@ -777,7 +776,6 @@ const struct MPOpts mp_default_opts = { .sub_visibility = 1, .sub_pos = 100, .sub_speed = 1.0, - .extension_parsing = 1, .audio_output_channels = MP_CHMAP_INIT_STEREO, .audio_output_format = -1, // AF_FORMAT_UNKNOWN .playback_speed = 1., diff --git a/core/options.h b/core/options.h index d46435bf9e..345835656b 100644 --- a/core/options.h +++ b/core/options.h @@ -152,7 +152,6 @@ typedef struct MPOpts { char *demuxer_name; char *audio_demuxer_name; char *sub_demuxer_name; - int extension_parsing; int mkv_subtitle_preroll; struct image_writer_opts *screenshot_image_opts; diff --git a/core/timeline/tl_matroska.c b/core/timeline/tl_matroska.c index 614ce0d6b7..f01160b60e 100644 --- a/core/timeline/tl_matroska.c +++ b/core/timeline/tl_matroska.c @@ -168,7 +168,7 @@ static bool check_file_seg(struct MPContext *mpctx, struct demuxer **sources, free_stream(s); return was_valid; } - if (d->file_format == DEMUXER_TYPE_MATROSKA) { + if (d->type == DEMUXER_TYPE_MATROSKA) { for (int i = 1; i < num_sources; i++) { if (sources[i]) continue; diff --git a/demux/demux.c b/demux/demux.c index 5a0e05d48f..61e0f2e9ef 100644 --- a/demux/demux.c +++ b/demux/demux.c @@ -224,46 +224,6 @@ struct demux_packet *demux_copy_packet(struct demux_packet *dp) return new; } -/** - * Get demuxer description structure for a given demuxer type - * - * @param file_format type of the demuxer - * @return structure for the demuxer, NULL if not found - */ -static const demuxer_desc_t *get_demuxer_desc_from_type(int file_format) -{ - int i; - - for (i = 0; demuxer_list[i]; i++) - if (file_format == demuxer_list[i]->type) - return demuxer_list[i]; - - return NULL; -} - - -static demuxer_t *new_demuxer(struct MPOpts *opts, stream_t *stream, int type) -{ - struct demuxer *d = talloc_zero(NULL, struct demuxer); - d->stream = stream; - d->stream_pts = MP_NOPTS_VALUE; - d->movi_start = stream->start_pos; - d->movi_end = stream->end_pos; - d->seekable = 1; - d->filepos = -1; - d->type = type; - d->opts = opts; - if (type) - if (!(d->desc = get_demuxer_desc_from_type(type))) - mp_msg(MSGT_DEMUXER, MSGL_ERR, - "BUG! Invalid demuxer type in new_demuxer(), " - "big troubles ahead.\n"); - if (stream->url) - d->filename = strdup(stream->url); - stream_seek(stream, stream->start_pos); - return d; -} - struct sh_stream *new_sh_stream(demuxer_t *demuxer, enum stream_type type) { if (demuxer->num_streams > MAX_SH_STREAMS) { @@ -356,7 +316,6 @@ void free_demuxer(demuxer_t *demuxer) // free streams: for (int n = 0; n < demuxer->num_streams; n++) free_sh_stream(demuxer->streams[n]); - free(demuxer->filename); talloc_free(demuxer); } @@ -546,8 +505,6 @@ void demuxer_help(void) mp_msg(MSGT_DEMUXER, MSGL_INFO, " demuxer: info: (comment)\n"); mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_DEMUXERS\n"); for (i = 0; demuxer_list[i]; i++) { - if (demuxer_list[i]->type >= DEMUXER_TYPE_END) // internal type - continue; if (demuxer_list[i]->comment && strlen(demuxer_list[i]->comment)) mp_msg(MSGT_DEMUXER, MSGL_INFO, "%10s %s (%s)\n", demuxer_list[i]->name, demuxer_list[i]->info, @@ -558,66 +515,51 @@ void demuxer_help(void) } } - -/** - * Get demuxer type for a given demuxer name - * - * @param demuxer_name string with demuxer name of demuxer number - * @param force will be set if demuxer should be forced. - * May be NULL. - * @return DEMUXER_TYPE_xxx, -1 if error or not found - */ -static int get_demuxer_type_from_name(char *demuxer_name, int *force) -{ - if (!demuxer_name || !demuxer_name[0]) - return DEMUXER_TYPE_UNKNOWN; - if (force) - *force = demuxer_name[0] == '+'; - if (demuxer_name[0] == '+') - demuxer_name = &demuxer_name[1]; - for (int i = 0; demuxer_list[i]; i++) { - if (demuxer_list[i]->type >= DEMUXER_TYPE_END) - // Can't select special demuxers from commandline - continue; - if (strcmp(demuxer_name, demuxer_list[i]->name) == 0) - return demuxer_list[i]->type; +static const char *d_level(enum demux_check level) +{ + switch (level) { + case DEMUX_CHECK_FORCE: return "force"; + case DEMUX_CHECK_UNSAFE: return "unsafe"; + case DEMUX_CHECK_REQUEST:return "request"; + case DEMUX_CHECK_NORMAL: return "normal"; } - - return -1; + abort(); } static struct demuxer *open_given_type(struct MPOpts *opts, const struct demuxer_desc *desc, - struct stream *stream, bool force, - struct demuxer_params *params) -{ - struct demuxer *demuxer; - int fformat = desc->type; - mp_msg(MSGT_DEMUXER, MSGL_V, "Trying demuxer: %s\n", desc->name); - demuxer = new_demuxer(opts, stream, desc->type); - demuxer->params = params; - if (!force) { - if (desc->check_file) - fformat = desc->check_file(demuxer) >= 0 ? fformat : 0; - } - if (fformat == 0) - goto fail; - if (fformat == desc->type) { + struct stream *stream, + struct demuxer_params *params, + enum demux_check check) +{ + struct demuxer *demuxer = talloc_ptrtype(NULL, demuxer); + *demuxer = (struct demuxer) { + .desc = desc, + .type = desc->type, + .stream = stream, + .stream_pts = MP_NOPTS_VALUE, + .movi_start = stream->start_pos, + .movi_end = stream->end_pos, + .seekable = 1, + .filepos = -1, + .opts = opts, + .filename = talloc_strdup(demuxer, stream->url), + }; + demuxer->params = params; // temporary during open() + stream_seek(stream, stream->start_pos); + + mp_msg(MSGT_DEMUXER, MSGL_V, "Trying demuxer: %s (force-level: %s)\n", + desc->name, d_level(check)); + + int ret = demuxer->desc->open(demuxer, check); + if (ret >= 0) { + demuxer->params = NULL; if (demuxer->filetype) mp_tmsg(MSGT_DEMUXER, MSGL_INFO, "Detected file format: %s (%s)\n", demuxer->filetype, desc->shortdesc); else mp_tmsg(MSGT_DEMUXER, MSGL_INFO, "Detected file format: %s\n", desc->shortdesc); - if (demuxer->desc->open) { - int ret = demuxer->desc->open(demuxer); - if (ret < 0) { - mp_tmsg(MSGT_DEMUXER, MSGL_ERR, "Opening as detected format " - "\"%s\" failed.\n", desc->shortdesc); - goto fail; - } - } - demuxer->file_format = fformat; if (stream_manages_timeline(demuxer->stream)) { // Incorrect, but fixes some behavior with DVD/BD demuxer->ts_resets_possible = false; @@ -628,81 +570,55 @@ static struct demuxer *open_given_type(struct MPOpts *opts, demuxer_sort_chapters(demuxer); demux_info_update(demuxer); return demuxer; - } else { - // demux_mov can return playlist instead of mov - if (fformat == DEMUXER_TYPE_PLAYLIST) - return demuxer; // handled in mplayer.c - /* Internal MPEG PS demuxer check can return other MPEG subtypes - * which don't have their own checks; recurse to try opening as - * the returned type instead. */ - free_demuxer(demuxer); - desc = get_demuxer_desc_from_type(fformat); - if (!desc) { - mp_msg(MSGT_DEMUXER, MSGL_ERR, - "BUG: recursion to nonexistent file format\n"); - return NULL; - } - return open_given_type(opts, desc, stream, false, params); } - fail: + free_demuxer(demuxer); return NULL; } +static const int d_normal[] = {DEMUX_CHECK_NORMAL, DEMUX_CHECK_UNSAFE, -1}; +static const int d_request[] = {DEMUX_CHECK_REQUEST, -1}; +static const int d_force[] = {DEMUX_CHECK_FORCE, -1}; + struct demuxer *demux_open(struct stream *stream, char *force_format, struct demuxer_params *params, struct MPOpts *opts) { - struct demuxer *demuxer = NULL; - const struct demuxer_desc *desc; + const int *check_levels = d_normal; + const struct demuxer_desc *check_desc = NULL; + if (!force_format) force_format = opts->demuxer_name; + if (!force_format) + force_format = stream->demuxer; - 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; - } - int file_format = 0; - if (demuxer_type) - file_format = demuxer_type; - - // If somebody requested a demuxer check it - if (file_format) { - desc = get_demuxer_desc_from_type(file_format); - if (!desc) - // should only happen with obsolete -demuxer 99 numeric format + if (force_format && force_format[0]) { + check_levels = d_request; + if (force_format[0] == '+') { + force_format += 1; + check_levels = d_force; + } + for (int n = 0; demuxer_list[n]; n++) { + if (strcmp(demuxer_list[n]->name, force_format) == 0) + check_desc = demuxer_list[n]; + } + if (!check_desc) { + mp_msg(MSGT_DEMUXER, MSGL_ERR, "Demuxer %s does not exist.\n", + force_format); return NULL; - return open_given_type(opts, desc, stream, force, params); - } - - // Test demuxers with safe file checks - for (int i = 0; (desc = demuxer_list[i]); i++) { - if (desc->safe_check) { - demuxer = open_given_type(opts, desc, stream, false, params); - if (demuxer) - return demuxer; } } - // Ok. We're over the stable detectable fileformats, the next ones are - // a bit fuzzy. So by default (extension_parsing==1) try extension-based - // detection first: - if (stream->url && opts->extension_parsing == 1) { - desc = get_demuxer_desc_from_type(demuxer_type_by_filename(stream->url)); - if (desc) - demuxer = open_given_type(opts, desc, stream, false, params); - if (demuxer) - return demuxer; - } - - // Finally try detection for demuxers with unsafe checks - for (int i = 0; (desc = demuxer_list[i]); i++) { - if (!desc->safe_check && desc->check_file) { - demuxer = open_given_type(opts, desc, stream, false, params); - if (demuxer) - return demuxer; + // Test demuxers from first to last, one pass for each check_levels[] entry + for (int pass = 0; check_levels[pass] != -1; pass++) { + enum demux_check level = check_levels[pass]; + for (int n = 0; demuxer_list[n]; n++) { + const struct demuxer_desc *desc = demuxer_list[n]; + if (!check_desc || desc == check_desc) { + struct demuxer *demuxer = open_given_type(opts, desc, stream, + params, level); + if (demuxer) + return demuxer; + } } } diff --git a/demux/demux.h b/demux/demux.h index f64a02dce1..34ff9fd596 100644 --- a/demux/demux.h +++ b/demux/demux.h @@ -36,24 +36,11 @@ struct MPOpts; #define MAX_PACK_BYTES 0x8000000 // 128 MiB enum demuxer_type { - DEMUXER_TYPE_UNKNOWN = 0, + DEMUXER_TYPE_GENERIC = 0, DEMUXER_TYPE_TV, - DEMUXER_TYPE_MF, - DEMUXER_TYPE_RAWAUDIO, - DEMUXER_TYPE_RAWVIDEO, DEMUXER_TYPE_MATROSKA, - DEMUXER_TYPE_LAVF, - DEMUXER_TYPE_MNG, DEMUXER_TYPE_EDL, DEMUXER_TYPE_CUE, - DEMUXER_TYPE_SUBREADER, - DEMUXER_TYPE_LIBASS, - - /* Values after this are for internal use and can not be selected - * as demuxer type by the user (-demuxer option). */ - DEMUXER_TYPE_END, - - DEMUXER_TYPE_PLAYLIST, }; enum timestamp_type { @@ -84,6 +71,22 @@ enum timestamp_type { #define SEEK_BACKWARD (1 << 3) #define SEEK_SUBPREROLL (1 << 4) +// Strictness of the demuxer open format check. +// demux.c will try by default: NORMAL, UNSAFE (in this order) +// Using "-demuxer format" will try REQUEST +// Using "-demuxer +format" will try FORCE +// REQUEST can be used as special value for raw demuxers which have no file +// header check; then they should fail if check!=FORCE && check!=REQUEST. +// +// In general, the list is sorted from weakest check to normal check. +// You can use relation operators to compare the check level. +enum demux_check { + DEMUX_CHECK_FORCE, // force format if possible + DEMUX_CHECK_UNSAFE, // risky/fuzzy detection + DEMUX_CHECK_REQUEST,// requested by user or stream implementation + DEMUX_CHECK_NORMAL, // normal, safe detection +}; + // demux_lavf can pass lavf buffers using FF_INPUT_BUFFER_PADDING_SIZE instead #define MP_INPUT_BUFFER_PADDING_SIZE 16 @@ -101,14 +104,10 @@ typedef struct demuxer_desc { const char *author; // Demuxer author(s) const char *comment; // Comment, printed with -demuxer help - enum demuxer_type type; - // If 1 detection is safe and fast, do it before file extension check - int safe_check; + enum demuxer_type type; // optional // Return 0 on success, otherwise -1 - int (*check_file)(struct demuxer *demuxer); - // Open the demuxer, return 0 on success, otherwise -1 - int (*open)(struct demuxer *demuxer); + int (*open)(struct demuxer *demuxer, enum demux_check check); // The following functions are all optional int (*fill_buffer)(struct demuxer *demuxer); // 0 on EOF, otherwise 1 void (*close)(struct demuxer *demuxer); @@ -160,15 +159,8 @@ typedef struct demuxer { int64_t movi_end; struct stream *stream; double stream_pts; // current stream pts, if applicable (e.g. dvd) - char *filename; // Needed by avs_check_file + char *filename; // same as stream->url enum demuxer_type type; - /* Normally the file_format field is just a copy of the type field above. - * There are 2 exceptions I noticed. Internal demux_avi may force - * ->type to DEMUXER_TYPE_AVI_[NI|NINI] while leaving ->file_format at - * DEMUXER_TYPE_AVI. Internal demux_mov may set ->type to - * DEMUXER_TYPE_PLAYLIST and also return that from the check function - * or not (looks potentially buggy). */ - enum demuxer_type file_format; int seekable; // flag /* Set if using absolute seeks for small movements is OK (no pts resets * that would make pts ambigious, preferably supports back/forward flags */ @@ -252,8 +244,6 @@ void demuxer_select_track(struct demuxer *demuxer, struct sh_stream *stream, bool selected); void demuxer_enable_autoselect(struct demuxer *demuxer); -int demuxer_type_by_filename(char *filename); - void demuxer_help(void); int demuxer_add_attachment(struct demuxer *demuxer, struct bstr name, diff --git a/demux/demux_cue.c b/demux/demux_cue.c index 43ef910868..db2f40ea57 100644 --- a/demux/demux_cue.c +++ b/demux/demux_cue.c @@ -29,21 +29,21 @@ bool mp_probe_cue(struct bstr s); #define PROBE_SIZE 512 -static int try_open_file(struct demuxer *demuxer) +static int try_open_file(struct demuxer *demuxer, enum demux_check check) { struct stream *s = demuxer->stream; - char buf[PROBE_SIZE]; - int len = stream_read(s, buf, sizeof(buf)); - if (len <= 0) - return -1; - if (!mp_probe_cue((struct bstr) { buf, len })) - return -1; - stream_seek(s, 0); + if (check >= DEMUX_CHECK_UNSAFE) { + char buf[PROBE_SIZE]; + int len = stream_read(s, buf, sizeof(buf)); + if (len <= 0) + return -1; + if (!mp_probe_cue((struct bstr) { buf, len })) + return -1; + stream_seek(s, 0); + } demuxer->file_contents = stream_read_complete(s, demuxer, 1000000); if (demuxer->file_contents.start == NULL) return -1; - if (!mp_probe_cue((struct bstr) { buf, len })) - return -1; return 0; } @@ -54,6 +54,5 @@ const struct demuxer_desc demuxer_desc_cue = { .author = "Uoti Urpala", .comment = "", .type = DEMUXER_TYPE_CUE, - .safe_check = true, - .check_file = try_open_file, // no separate .open + .open = try_open_file, }; diff --git a/demux/demux_edl.c b/demux/demux_edl.c index 44fa824193..0f4bf06dbf 100644 --- a/demux/demux_edl.c +++ b/demux/demux_edl.c @@ -23,17 +23,19 @@ #include "demux.h" #include "stream/stream.h" -static int try_open_file(struct demuxer *demuxer) +static int try_open_file(struct demuxer *demuxer, enum demux_check check) { struct stream *s = demuxer->stream; - const char header[] = "mplayer EDL file"; - const int len = sizeof(header) - 1; - char buf[len]; - if (stream_read(s, buf, len) < len) - return -1; - if (strncmp(buf, header, len)) - return -1; - stream_seek(s, 0); + if (check >= DEMUX_CHECK_UNSAFE) { + const char header[] = "mplayer EDL file"; + const int len = sizeof(header) - 1; + char buf[len]; + if (stream_read(s, buf, len) < len) + return -1; + if (strncmp(buf, header, len)) + return -1; + stream_seek(s, 0); + } demuxer->file_contents = stream_read_complete(s, demuxer, 1000000); if (demuxer->file_contents.start == NULL) return -1; @@ -47,6 +49,5 @@ const struct demuxer_desc demuxer_desc_edl = { .author = "Uoti Urpala", .comment = "", .type = DEMUXER_TYPE_EDL, - .safe_check = true, - .check_file = try_open_file, // no separate .open + .open = try_open_file, }; diff --git a/demux/demux_lavf.c b/demux/demux_lavf.c index 0e7690f606..88587f8ce0 100644 --- a/demux/demux_lavf.c +++ b/demux/demux_lavf.c @@ -185,7 +185,7 @@ static char *remove_prefix(char *s, const char **prefixes) static const char *prefixes[] = {"ffmpeg://", "lavf://", "avdevice://", "av://", NULL}; -static int lavf_check_file(demuxer_t *demuxer) +static int lavf_check_file(demuxer_t *demuxer, enum demux_check check) { struct MPOpts *opts = demuxer->opts; struct lavfdopts *lavfdopts = &opts->lavfdopts; @@ -258,7 +258,8 @@ static int lavf_check_file(demuxer_t *demuxer) min_probe = lavfdopts->probescore; AVProbeData avpd = { - .filename = priv->filename, + // Disable file-extension matching with normal checks + .filename = check <= DEMUX_CHECK_REQUEST ? priv->filename : NULL, .buf_size = 0, .buf = av_mallocz(PROBE_BUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE), }; @@ -493,18 +494,20 @@ static void add_metadata(demuxer_t *demuxer, AVDictionary *metadata) demux_info_add(demuxer, t->key, t->value); } -static int demux_open_lavf(demuxer_t *demuxer) +static int demux_open_lavf(demuxer_t *demuxer, enum demux_check check) { struct MPOpts *opts = demuxer->opts; struct lavfdopts *lavfdopts = &opts->lavfdopts; AVFormatContext *avfc; AVDictionaryEntry *t = NULL; - lavf_priv_t *priv = demuxer->priv; float analyze_duration = 0; int i; - // do not allow forcing the demuxer - if (!priv->avif) + if (lavf_check_file(demuxer, check) < 0) + return -1; + + lavf_priv_t *priv = demuxer->priv; + if (!priv) return -1; stream_seek(demuxer->stream, 0); @@ -904,9 +907,6 @@ const demuxer_desc_t demuxer_desc_lavf = { .shortdesc = "libavformat", .author = "Michael Niedermayer", .comment = "supports many formats, requires libavformat", - .type = DEMUXER_TYPE_LAVF, - .safe_check = 1, - .check_file = lavf_check_file, .fill_buffer = demux_lavf_fill_buffer, .open = demux_open_lavf, .close = demux_close_lavf, diff --git a/demux/demux_libass.c b/demux/demux_libass.c index 4dadb42b89..24e1b9e114 100644 --- a/demux/demux_libass.c +++ b/demux/demux_libass.c @@ -33,7 +33,7 @@ struct priv { ASS_Track *track; }; -static int d_check_file(struct demuxer *demuxer) +static int d_check_file(struct demuxer *demuxer, enum demux_check check) { const char *user_cp = demuxer->opts->sub_cp; struct stream *s = demuxer->stream; @@ -43,42 +43,45 @@ static int d_check_file(struct demuxer *demuxer) if (!lib) return -1; - // Probe by loading a part of the beginning of the file with libass. - // Incomplete scripts are usually ok, and we hope libass is not verbose - // when dealing with (from its perspective) completely broken binary - // garbage. - - bstr buf = stream_peek(s, PROBE_SIZE); - // Older versions of libass will overwrite the input buffer, and despite - // passing length, expect a 0 termination. - void *tmp = talloc_size(NULL, buf.len + 1); - memcpy(tmp, buf.start, buf.len); - buf.start = tmp; - buf.start[buf.len] = '\0'; - bstr cbuf = - mp_charset_guess_and_conv_to_utf8(buf, user_cp, MP_ICONV_ALLOW_CUTOFF); - if (cbuf.start == NULL) - cbuf = buf; - ASS_Track *track = ass_read_memory(lib, cbuf.start, cbuf.len, NULL); - if (cbuf.start != buf.start) - talloc_free(cbuf.start); - talloc_free(buf.start); - if (!track) - return -1; - ass_free_track(track); + if (check >= DEMUX_CHECK_UNSAFE) { + // Probe by loading a part of the beginning of the file with libass. + // Incomplete scripts are usually ok, and we hope libass is not verbose + // when dealing with (from its perspective) completely broken binary + // garbage. + + bstr buf = stream_peek(s, PROBE_SIZE); + // Older versions of libass will overwrite the input buffer, and despite + // passing length, expect a 0 termination. + void *tmp = talloc_size(NULL, buf.len + 1); + memcpy(tmp, buf.start, buf.len); + buf.start = tmp; + buf.start[buf.len] = '\0'; + bstr cbuf = mp_charset_guess_and_conv_to_utf8(buf, user_cp, + MP_ICONV_ALLOW_CUTOFF); + if (cbuf.start == NULL) + cbuf = buf; + ASS_Track *track = ass_read_memory(lib, cbuf.start, cbuf.len, NULL); + if (cbuf.start != buf.start) + talloc_free(cbuf.start); + talloc_free(buf.start); + if (!track) + return -1; + ass_free_track(track); + } // Actually load the full thing. - buf = stream_read_complete(s, NULL, 100000000); + bstr buf = stream_read_complete(s, NULL, 100000000); if (!buf.start) { mp_tmsg(MSGT_ASS, MSGL_ERR, "Refusing to load subtitle file " "larger than 100 MB: %s\n", demuxer->filename); return -1; } - cbuf = mp_charset_guess_and_conv_to_utf8(buf, user_cp, MP_ICONV_VERBOSE); + bstr cbuf = mp_charset_guess_and_conv_to_utf8(buf, user_cp, + MP_ICONV_VERBOSE); if (cbuf.start == NULL) cbuf = buf; - track = ass_read_memory(lib, cbuf.start, cbuf.len, NULL); + ASS_Track *track = ass_read_memory(lib, cbuf.start, cbuf.len, NULL); if (cbuf.start != buf.start) talloc_free(cbuf.start); talloc_free(buf.start); @@ -114,8 +117,6 @@ const struct demuxer_desc demuxer_desc_libass = { .shortdesc = "ASS/SSA subtitles (libass)", .author = "", .comment = "", - .safe_check = 1, - .type = DEMUXER_TYPE_LIBASS, - .check_file = d_check_file, + .open = d_check_file, .close = d_close, }; diff --git a/demux/demux_mf.c b/demux/demux_mf.c index 5e3469a0f1..33747f12d7 100644 --- a/demux/demux_mf.c +++ b/demux/demux_mf.c @@ -149,9 +149,9 @@ static const struct { {0} }; -static const char *probe_format(mf_t *mf) +static const char *probe_format(mf_t *mf, enum demux_check check) { - if (mf->nr_of_files < 1) + if (check > DEMUX_CHECK_REQUEST) return NULL; char *type = mf_type; if (!type || !type[0]) { @@ -159,47 +159,42 @@ static const char *probe_format(mf_t *mf) if (p) type = p + 1; } - if (!type || !type[0]) - return NULL; - int i; - for (i = 0; type2format[i].type; i++) { - if (strcasecmp(type, type2format[i].type) == 0) - break; + for (int i = 0; type2format[i].type; i++) { + if (type && strcasecmp(type, type2format[i].type) == 0) + return type2format[i].codec; } - return type2format[i].codec; -} - -static mf_t *open_mf(demuxer_t *demuxer) -{ - if (!demuxer->stream->url) - return NULL; - - if (strncmp(demuxer->stream->url, "mf://", 5) == 0) { - return open_mf_pattern(demuxer->stream->url + 5); - } else { - mf_t *mf = open_mf_single(demuxer->stream->url); - mf->streams = calloc(1, sizeof(struct stream *)); - mf->streams[0] = demuxer->stream; - return mf; + if (check == DEMUX_CHECK_REQUEST) { + if (!mf_type) { + mp_msg(MSGT_DEMUX, MSGL_ERR, + "[demux_mf] file type was not set! (try --mf-type=ext)\n"); + } else { + mp_msg(MSGT_DEMUX, MSGL_ERR, + "[demux_mf] --mf-type set to an unknown codec!\n"); + } } + return NULL; } -static int demux_check_file(demuxer_t *demuxer) -{ - if (demuxer->stream->type == STREAMTYPE_MF) - return 0; - mf_t *mf = open_mf(demuxer); - bool ok = mf && probe_format(mf); - free_mf(mf); - return ok ? 0 : -1; -} - -static int demux_open_mf(demuxer_t* demuxer) +static int demux_open_mf(demuxer_t* demuxer, enum demux_check check) { sh_video_t *sh_video = NULL; + mf_t *mf; + + if (strncmp(demuxer->stream->url, "mf://", 5) == 0 && + demuxer->stream->type == STREAMTYPE_MF) + { + mf = open_mf_pattern(demuxer->stream->url + 5); + } else { + mf = open_mf_single(demuxer->stream->url); + mf->streams = calloc(1, sizeof(struct stream *)); + mf->streams[0] = demuxer->stream; + } + + if (!mf || mf->nr_of_files < 1) + goto error; - mf_t *mf = open_mf(demuxer); - if (!mf) + const char *codec = probe_format(mf, check); + if (!codec) goto error; mf->curr_frame = 0; @@ -211,12 +206,7 @@ static int demux_open_mf(demuxer_t* demuxer) struct sh_stream *sh = new_sh_stream(demuxer, STREAM_VIDEO); sh_video = sh->video; - sh_video->gsh->codec = probe_format(mf); - if (!sh_video->gsh->codec) { - mp_msg(MSGT_DEMUX, MSGL_INFO, "[demux_mf] file type was not set! (try -mf type=ext)\n" ); - goto error; - } - + sh_video->gsh->codec = codec; sh_video->disp_w = 0; sh_video->disp_h = 0; sh_video->fps = mf_fps; @@ -259,9 +249,6 @@ const demuxer_desc_t demuxer_desc_mf = { .shortdesc = "MF", .author = "?", .comment = "multiframe?, pictures demuxer", - .type = DEMUXER_TYPE_MF, - .safe_check = 1, - .check_file = demux_check_file, .fill_buffer = demux_mf_fill_buffer, .open = demux_open_mf, .close = demux_close_mf, diff --git a/demux/demux_mkv.c b/demux/demux_mkv.c index a60172cce9..efc4c8f989 100644 --- a/demux/demux_mkv.c +++ b/demux/demux_mkv.c @@ -1751,7 +1751,7 @@ static int read_mkv_segment_header(demuxer_t *demuxer) return 0; } -static int demux_mkv_open(demuxer_t *demuxer) +static int demux_mkv_open(demuxer_t *demuxer, enum demux_check check) { stream_t *s = demuxer->stream; mkv_demuxer_t *mkv_d; @@ -2724,8 +2724,7 @@ const demuxer_desc_t demuxer_desc_matroska = { .author = "Aurelien Jacobs", .comment = "", .type = DEMUXER_TYPE_MATROSKA, - .safe_check = 1, // safe autodetect - .check_file = demux_mkv_open, + .open = demux_mkv_open, .fill_buffer = demux_mkv_fill_buffer, .close = mkv_free, .seek = demux_mkv_seek, diff --git a/demux/demux_mng.c b/demux/demux_mng.c index 824a668868..6c5bbc2e45 100644 --- a/demux/demux_mng.c +++ b/demux/demux_mng.c @@ -254,21 +254,6 @@ static mng_bool demux_mng_settimer(mng_handle h_mng, mng_uint32 msecs) return MNG_TRUE; } -/** - * \brief MPlayer callback: Check if stream contains MNG data. - * \param[in] demuxer demuxer structure - * \return demuxer type constant, \p 0 if unknown - */ -static int demux_mng_check_file(demuxer_t *demuxer) -{ - char buf[4]; - if (stream_read(demuxer->stream, buf, 4) != 4) - return -1; - if (memcmp(buf, "\x8AMNG", 4)) - return -1; - return 0; -} - /** * \brief MPlayer callback: Fill buffer from MNG stream. * \param[in] demuxer demuxer structure @@ -343,13 +328,24 @@ static int demux_mng_fill_buffer(demuxer_t * demuxer) return 1; } -static int demux_mng_open(demuxer_t * demuxer) +static int demux_mng_open(demuxer_t * demuxer, enum demux_check check) { mng_priv_t * mng_priv; mng_handle h_mng; mng_retcode mng_ret; sh_video_t * sh_video; + if (check > DEMUX_CHECK_REQUEST) + return -1; // check too unsafe + if (check > DEMUX_CHECK_FORCE) { + char buf[4]; + if (stream_read(demuxer->stream, buf, 4) != 4) + return -1; + if (memcmp(buf, "\x8AMNG", 4)) + return -1; + stream_seek(demuxer->stream, demuxer->stream->start_pos); + } + // create private data structure mng_priv = calloc(1, sizeof(mng_priv_t)); @@ -569,9 +565,6 @@ const demuxer_desc_t demuxer_desc_mng = { .shortdesc = "MNG", .author = "Stefan Schuermans ", .comment = "MNG files, using libmng", - .type = DEMUXER_TYPE_MNG, - .safe_check = 0, // unsafe autodetect (only checking magic at beginning of stream) - .check_file = demux_mng_check_file, .fill_buffer = demux_mng_fill_buffer, .open = demux_mng_open, .close = demux_mng_close, diff --git a/demux/demux_rawaudio.c b/demux/demux_rawaudio.c index 13bbbb341a..83a89e7c1c 100644 --- a/demux/demux_rawaudio.c +++ b/demux/demux_rawaudio.c @@ -43,11 +43,15 @@ const m_option_t demux_rawaudio_opts[] = { }; -static int demux_rawaudio_open(demuxer_t* demuxer) { +static int demux_rawaudio_open(demuxer_t* demuxer, enum demux_check check) +{ struct sh_stream *sh; sh_audio_t* sh_audio; WAVEFORMATEX* w; + if (check != DEMUX_CHECK_REQUEST && check != DEMUX_CHECK_FORCE) + return -1; + if ((format & AF_FORMAT_SPECIAL_MASK) != 0) return -1; @@ -115,7 +119,6 @@ const demuxer_desc_t demuxer_desc_rawaudio = { .shortdesc = "rawaudio", .author = "?", .comment = "", - .type = DEMUXER_TYPE_RAWAUDIO, .fill_buffer = demux_rawaudio_fill_buffer, .open = demux_rawaudio_open, .seek = demux_rawaudio_seek, diff --git a/demux/demux_rawvideo.c b/demux/demux_rawvideo.c index 488c13bdec..9f670f2879 100644 --- a/demux/demux_rawvideo.c +++ b/demux/demux_rawvideo.c @@ -56,10 +56,14 @@ const m_option_t demux_rawvideo_opts[] = { }; -static int demux_rawvideo_open(demuxer_t* demuxer) { +static int demux_rawvideo_open(demuxer_t* demuxer, enum demux_check check) +{ struct sh_stream *sh; sh_video_t* sh_video; + if (check != DEMUX_CHECK_REQUEST && check != DEMUX_CHECK_FORCE) + return -1; + if(!width || !height){ mp_msg(MSGT_DEMUX,MSGL_ERR,"rawvideo: width or height not specified!\n"); return -1; @@ -171,7 +175,6 @@ const demuxer_desc_t demuxer_desc_rawvideo = { .shortdesc = "rawvideo", .author = "?", .comment = "", - .type = DEMUXER_TYPE_RAWVIDEO, .fill_buffer = demux_rawvideo_fill_buffer, .open = demux_rawvideo_open, .seek = demux_rawvideo_seek, diff --git a/demux/demux_subreader.c b/demux/demux_subreader.c index 7758aa968c..24604978d5 100644 --- a/demux/demux_subreader.c +++ b/demux/demux_subreader.c @@ -1326,8 +1326,11 @@ static struct stream *read_probe_stream(struct stream *s, int max) #define PROBE_SIZE FFMIN(32 * 1024, STREAM_MAX_BUFFER_SIZE) -static int d_check_file(struct demuxer *demuxer) +static int d_open_file(struct demuxer *demuxer, enum demux_check check) { + if (check > DEMUX_CHECK_REQUEST) + return -1; + struct stream *ps = read_probe_stream(demuxer->stream, PROBE_SIZE); struct subreader sr; @@ -1393,9 +1396,7 @@ const struct demuxer_desc demuxer_desc_subreader = { .shortdesc = "Deprecated Subreader", .author = "", .comment = "", - .type = DEMUXER_TYPE_SUBREADER, - .safe_check = 1, - .check_file = d_check_file, + .open = d_open_file, .fill_buffer = d_fill_buffer, .seek = d_seek, .control = d_control, diff --git a/demux/extension.c b/demux/extension.c deleted file mode 100644 index 30cb592b9f..0000000000 --- a/demux/extension.c +++ /dev/null @@ -1,101 +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 -#include -#include - -#include "config.h" - -#include "stream/stream.h" -#include "demux.h" - -/* - * An autodetection based on the extension is not a good idea, but we don't care ;-) - * - * You should not add anything here where autodetection can be easily fixed except in - * order to speed up auto-detection, in particular for formats that are often streamed. - * In particular you should not normally add any DEMUXER_TYPE_LAVF, adding the - * format to preferred_list in demux/demuxer_lavf.c will usually achieve - * the same effect in a much more reliable way. - */ -static struct { - const char *extension; - int demuxer_type; -} extensions_table[] = { - { "vob", DEMUXER_TYPE_LAVF }, - { "m2v", DEMUXER_TYPE_LAVF }, - { "avi", DEMUXER_TYPE_LAVF }, - { "asx", DEMUXER_TYPE_LAVF }, - { "asf", DEMUXER_TYPE_LAVF }, - { "wmv", DEMUXER_TYPE_LAVF }, - { "wma", DEMUXER_TYPE_LAVF }, - { "rm", DEMUXER_TYPE_LAVF }, - { "rmvb", DEMUXER_TYPE_LAVF }, - { "ra", DEMUXER_TYPE_LAVF }, - { "y4m", DEMUXER_TYPE_LAVF }, - { "mp3", DEMUXER_TYPE_LAVF }, - { "wav", DEMUXER_TYPE_LAVF }, - { "flac", DEMUXER_TYPE_LAVF }, - { "fla", DEMUXER_TYPE_LAVF }, - { "ogg", DEMUXER_TYPE_LAVF }, - { "ogm", DEMUXER_TYPE_LAVF }, -// { "pls", DEMUXER_TYPE_PLAYLIST }, -// { "m3u", DEMUXER_TYPE_PLAYLIST }, - { "xm", DEMUXER_TYPE_LAVF }, - { "mod", DEMUXER_TYPE_LAVF }, - { "s3m", DEMUXER_TYPE_LAVF }, - { "it", DEMUXER_TYPE_LAVF }, - { "mid", DEMUXER_TYPE_LAVF }, - { "midi", DEMUXER_TYPE_LAVF }, - { "nsv", DEMUXER_TYPE_LAVF }, - { "nsa", DEMUXER_TYPE_LAVF }, - { "mpc", DEMUXER_TYPE_LAVF }, - { "302", DEMUXER_TYPE_LAVF }, - { "264", DEMUXER_TYPE_LAVF }, - { "26l", DEMUXER_TYPE_LAVF }, - { "ac3", DEMUXER_TYPE_LAVF }, - { "ape", DEMUXER_TYPE_LAVF }, - { "apl", DEMUXER_TYPE_LAVF }, - { "eac3",DEMUXER_TYPE_LAVF }, - { "mac", DEMUXER_TYPE_LAVF }, - { "str", DEMUXER_TYPE_LAVF }, - { "cdg", DEMUXER_TYPE_LAVF }, - -// At least the following are hacks against broken autodetection -// that should not be there - -}; - -int demuxer_type_by_filename(char* filename){ - int i; - char* extension=strrchr(filename,'.'); - mp_msg(MSGT_OPEN, MSGL_V, "Searching demuxer type for filename %s ext: %s\n",filename,extension); - if(extension) { - ++extension; -// mp_msg(MSGT_CPLAYER,MSGL_DBG2,"Extension: %s\n", extension ); - // Look for the extension in the extensions table - for( i=0 ; i<(sizeof(extensions_table)/sizeof(extensions_table[0])) ; i++ ) { - if( !strcasecmp(extension, extensions_table[i].extension) ) { - mp_msg(MSGT_OPEN, MSGL_V, "Trying demuxer %d based on filename extension\n",extensions_table[i].demuxer_type); - return extensions_table[i].demuxer_type; - } - } - } - return DEMUXER_TYPE_UNKNOWN; -} diff --git a/stream/stream_dvb.c b/stream/stream_dvb.c index 8fabfb4fc1..3847e26c75 100644 --- a/stream/stream_dvb.c +++ b/stream/stream_dvb.c @@ -739,7 +739,8 @@ static int dvb_open(stream_t *stream, int mode, void *opts) stream->close = dvbin_close; m_struct_free(&stream_opts, opts); - stream->demuxer = "lavf:mpegts"; + stream->demuxer = "lavf"; + stream->lavf_type = "mpegts"; return STREAM_OK; } diff --git a/stream/stream_mf.c b/stream/stream_mf.c index eef5d6fc4d..9354005ae4 100644 --- a/stream/stream_mf.c +++ b/stream/stream_mf.c @@ -32,7 +32,7 @@ static int mf_stream_open (stream_t *stream, int mode, void *opts) { stream->type = STREAMTYPE_MF; - stream->demuxer = "lavf"; + stream->demuxer = "mf"; return STREAM_OK; } diff --git a/stream/tv.c b/stream/tv.c index aa5383402f..9ddf3771ed 100644 --- a/stream/tv.c +++ b/stream/tv.c @@ -701,13 +701,16 @@ static int tv_uninit(tvi_handle_t *tvh) return res; } -static int demux_open_tv(demuxer_t *demuxer) +static int demux_open_tv(demuxer_t *demuxer, enum demux_check check) { tvi_handle_t *tvh; sh_video_t *sh_video; sh_audio_t *sh_audio = NULL; const tvi_functions_t *funcs; + if (check > DEMUX_CHECK_REQUEST || demuxer->stream->type != STREAMTYPE_TV) + return -1; + demuxer->priv=NULL; if(!(tvh=tv_begin(demuxer->stream->priv))) return -1; if (!tvh->functions->init(tvh->priv)) return -1; -- cgit v1.2.3