1
0
mirror of https://github.com/mpv-player/mpv synced 2025-03-25 04:38:01 +00:00

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.
This commit is contained in:
wm4 2013-07-12 21:58:11 +02:00
parent 311d2f199a
commit 3269bd1780
22 changed files with 220 additions and 434 deletions

View File

@ -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=<auto|top|bottom>``
Set first field for interlaced content. Useful for deinterlacers that
double the framerate: ``--vf=yadif=1`` and ``--vo=vdpau:deint``.

View File

@ -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 \

View File

@ -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;

View File

@ -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.,

View File

@ -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;

View File

@ -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;

View File

@ -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)
static const char *d_level(enum demux_check level)
{
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;
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 stream *stream,
struct demuxer_params *params,
enum demux_check check)
{
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 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;
}
}
}

View File

@ -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,

View File

@ -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,
};

View File

@ -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,
};

View File

@ -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,

View File

@ -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.
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);
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,
};

View File

@ -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;
mf_t *mf = open_mf(demuxer);
if (!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;
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,

View File

@ -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,

View File

@ -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 <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,

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;