summaryrefslogtreecommitdiffstats
path: root/demux
diff options
context:
space:
mode:
Diffstat (limited to 'demux')
-rw-r--r--demux/demux.c220
-rw-r--r--demux/demux.h50
-rw-r--r--demux/demux_cue.c23
-rw-r--r--demux/demux_edl.c23
-rw-r--r--demux/demux_lavf.c18
-rw-r--r--demux/demux_libass.c61
-rw-r--r--demux/demux_mf.c77
-rw-r--r--demux/demux_mkv.c5
-rw-r--r--demux/demux_mng.c31
-rw-r--r--demux/demux_rawaudio.c7
-rw-r--r--demux/demux_rawvideo.c7
-rw-r--r--demux/demux_subreader.c9
-rw-r--r--demux/extension.c101
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