summaryrefslogtreecommitdiffstats
path: root/demux
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2013-07-12 21:58:11 +0200
committerwm4 <wm4@nowhere>2013-07-12 22:16:26 +0200
commit3269bd178020c5d821e8b2d1fd807a38d63e93ce (patch)
tree474e0f7a712cc7002984ec1bdda7d445b5fd8c77 /demux
parent311d2f199a7b1f4d819cfb799a0f0f571596b91e (diff)
downloadmpv-3269bd178020c5d821e8b2d1fd807a38d63e93ce.tar.bz2
mpv-3269bd178020c5d821e8b2d1fd807a38d63e93ce.tar.xz
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.
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_f