diff options
Diffstat (limited to 'demux')
-rw-r--r-- | demux/demux.c | 220 | ||||
-rw-r--r-- | demux/demux.h | 50 | ||||
-rw-r--r-- | demux/demux_cue.c | 23 | ||||
-rw-r--r-- | demux/demux_edl.c | 23 | ||||
-rw-r--r-- | demux/demux_lavf.c | 18 | ||||
-rw-r--r-- | demux/demux_libass.c | 61 | ||||
-rw-r--r-- | demux/demux_mf.c | 77 | ||||
-rw-r--r-- | demux/demux_mkv.c | 5 | ||||
-rw-r--r-- | demux/demux_mng.c | 31 | ||||
-rw-r--r-- | demux/demux_rawaudio.c | 7 | ||||
-rw-r--r-- | demux/demux_rawvideo.c | 7 | ||||
-rw-r--r-- | demux/demux_subreader.c | 9 | ||||
-rw-r--r-- | demux/extension.c | 101 |
13 files changed, 212 insertions, 420 deletions
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 @@ -255,21 +255,6 @@ static mng_bool demux_mng_settimer(mng_handle h_mng, mng_uint32 msecs) } /** - * \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 * \return \p 1 on success, \p 0 on error @@ -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 <stefan@blinkenarea.org>", .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 = "", |