summaryrefslogtreecommitdiffstats
path: root/demux
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2015-02-18 21:10:15 +0100
committerwm4 <wm4@nowhere>2015-02-18 21:12:57 +0100
commit37a0c9140ad85be8d184b626759f8d24ca69aa83 (patch)
tree46c7ebd10d569e317eb37fa7c4ac789146c6bd56 /demux
parentc7f450723ff3acfbea153e5cd2d73e5b016be539 (diff)
downloadmpv-37a0c9140ad85be8d184b626759f8d24ca69aa83.tar.bz2
mpv-37a0c9140ad85be8d184b626759f8d24ca69aa83.tar.xz
demux_lavf: reorganize hacks
An attempt to make format-specifics more declarative. (In my opinion, all of this should be either provided by libavformat, or should not be needed.) I'm still leaving many checks with matches_avinputformat_name(), because they're so specific. Also useful for the following commit.
Diffstat (limited to 'demux')
-rw-r--r--demux/demux_lavf.c137
1 files changed, 70 insertions, 67 deletions
diff --git a/demux/demux_lavf.c b/demux/demux_lavf.c
index 13f14d9fa1..98cb4df5e6 100644
--- a/demux/demux_lavf.c
+++ b/demux/demux_lavf.c
@@ -94,47 +94,77 @@ const struct m_sub_options demux_lavf_conf = {
},
};
-typedef struct lavf_priv {
- char *filename;
- const struct format_hack *format_hack;
- AVInputFormat *avif;
- AVFormatContext *avfc;
- AVIOContext *pb;
- int64_t last_pts;
- bool init_pts;
- struct sh_stream **streams; // NULL for unknown streams
- int num_streams;
- int cur_program;
- char *mime_type;
- bool merge_track_metadata;
-} lavf_priv_t;
-
struct format_hack {
const char *ff_name;
const char *mime_type;
int probescore;
float analyzeduration;
- bool max_probe; // use probescore only if max. probe size reached
+ bool max_probe : 1; // use probescore only if max. probe size reached
+ bool ignore : 1; // blacklisted
+ bool no_stream : 1; // do not wrap struct stream as AVIOContext
+ bool use_stream_ids : 1; // export the native stream IDs
+ // Do not confuse player's position estimation (position is into external
+ // segment, with e.g. HLS, player knows about the playlist main file only).
+ bool clear_filepos : 1;
};
+#define BLACKLIST(fmt) {fmt, .ignore = true}
+
static const struct format_hack format_hacks[] = {
// for webradios
{"aac", "audio/aacp", 25, 0.5},
{"aac", "audio/aac", 25, 0.5},
- // some mp3 files don't detect correctly
+
+ // some mp3 files don't detect correctly (usually id3v2 too large)
{"mp3", "audio/mpeg", 24, 0.5},
{"mp3", NULL, 24, .max_probe = true},
+
+ {"hls", .no_stream = true, .clear_filepos = true},
+ {"mpeg", .use_stream_ids = true},
+ {"mpegts", .use_stream_ids = true},
+
+ // Useless non-sense, sometimes breaks MLP2 subreader.c fallback
+ BLACKLIST("tty"),
+ // Image demuxers, disabled in favor of demux_mf (for now):
+ BLACKLIST("image"),
+ BLACKLIST("image2pipe"),
+ BLACKLIST("bmp_pipe"), BLACKLIST("dpx_pipe"), BLACKLIST("exr_pipe"),
+ BLACKLIST("j2k_pipe"), BLACKLIST("png_pipe"), BLACKLIST("tiff_pipe"),
+ BLACKLIST("jpeg_pipe"),
{0}
};
-static const char *const format_blacklist[] = {
- "tty", // Useless non-sense, sometimes breaks MLP2 subreader.c fallback
- // Image demuxers, disabled in favor of demux_mf:
- "image2", "image2pipe",
- "bmp_pipe", "dpx_pipe", "exr_pipe", "j2k_pipe", "png_pipe", "tiff_pipe",
- "jpeg_pipe",
- 0
-};
+typedef struct lavf_priv {
+ char *filename;
+ struct format_hack format_hack;
+ AVInputFormat *avif;
+ AVFormatContext *avfc;
+ AVIOContext *pb;
+ int64_t last_pts;
+ bool init_pts;
+ struct sh_stream **streams; // NULL for unknown streams
+ int num_streams;
+ int cur_program;
+ char *mime_type;
+ bool merge_track_metadata;
+} lavf_priv_t;
+
+// At least mp4 has name="mov,mp4,m4a,3gp,3g2,mj2", so we split the name
+// on "," in general.
+static bool matches_avinputformat_name(struct lavf_priv *priv,
+ const char *name)
+{
+ const char *avifname = priv->avif->name;
+ while (1) {
+ const char *next = strchr(avifname, ',');
+ if (!next)
+ return !strcmp(avifname, name);
+ int len = next - avifname;
+ if (len == strlen(name) && !memcmp(avifname, name, len))
+ return true;
+ avifname = next + 1;
+ }
+}
static int mp_read(void *opaque, uint8_t *buf, int size)
{
@@ -306,41 +336,34 @@ static int lavf_check_file(demuxer_t *demuxer, enum demux_check check)
MP_VERBOSE(demuxer, "Found '%s' at score=%d size=%d.\n",
priv->avif->name, score, avpd.buf_size);
- priv->format_hack = NULL;
for (int n = 0; format_hacks[n].ff_name; n++) {
const struct format_hack *entry = &format_hacks[n];
- if (strcmp(entry->ff_name, priv->avif->name) != 0)
+ if (!matches_avinputformat_name(priv, entry->ff_name))
continue;
if (entry->mime_type && strcasecmp(entry->mime_type, mime_type) != 0)
continue;
- priv->format_hack = entry;
+ priv->format_hack = *entry;
break;
}
if (score >= min_probe)
break;
- if (priv->format_hack) {
- if (score >= priv->format_hack->probescore &&
- (!priv->format_hack->max_probe || final_probe))
- break;
- }
+ if (priv->format_hack.probescore &&
+ score >= priv->format_hack.probescore &&
+ (!priv->format_hack.max_probe || final_probe))
+ break;
}
priv->avif = NULL;
- priv->format_hack = NULL;
+ priv->format_hack = (struct format_hack){0};
} while (!final_probe);
av_free(avpd.buf);
- if (priv->avif && !format) {
- for (int n = 0; format_blacklist[n]; n++) {
- if (strcmp(format_blacklist[n], priv->avif->name) == 0) {
- MP_VERBOSE(demuxer, "Format blacklisted.\n");
- priv->avif = NULL;
- break;
- }
- }
+ if (priv->avif && !format && priv->format_hack.ignore) {
+ MP_VERBOSE(demuxer, "Format blacklisted.\n");
+ priv->avif = NULL;
}
if (!priv->avif) {
@@ -355,23 +378,6 @@ success:
return 0;
}
-static bool matches_avinputformat_name(struct lavf_priv *priv,
- const char *name)
-{
- // At least mp4 has name="mov,mp4,m4a,3gp,3g2,mj2", so we split the name
- // on "," in general.
- const char *avifname = priv->avif->name;
- while (1) {
- const char *next = strchr(avifname, ',');
- if (!next)
- return !strcmp(avifname, name);
- int len = next - avifname;
- if (len == strlen(name) && !memcmp(avifname, name, len))
- return true;
- avifname = next + 1;
- }
-}
-
static uint8_t char2int(char c)
{
if (c >= '0' && c <= '9') return c - '0';
@@ -597,8 +603,7 @@ static void handle_stream(demuxer_t *demuxer, int i)
if (st->disposition & AV_DISPOSITION_DEFAULT)
sh->default_track = 1;
- if (matches_avinputformat_name(priv, "mpeg") ||
- matches_avinputformat_name(priv, "mpegts"))
+ if (priv->format_hack.use_stream_ids)
sh->demuxer_id = st->id;
AVDictionaryEntry *title = av_dict_get(st->metadata, "title", NULL, 0);
if (title && title->value)
@@ -708,8 +713,8 @@ static int demux_open_lavf(demuxer_t *demuxer, enum demux_check check)
lavfdopts->probesize);
}
- if (priv->format_hack && priv->format_hack->analyzeduration)
- analyze_duration = priv->format_hack->analyzeduration;
+ if (priv->format_hack.analyzeduration)
+ analyze_duration = priv->format_hack.analyzeduration;
if (lavfdopts->analyzeduration)
analyze_duration = lavfdopts->analyzeduration;
if (analyze_duration > 0) {
@@ -723,7 +728,7 @@ static int demux_open_lavf(demuxer_t *demuxer, enum demux_check check)
if ((priv->avif->flags & AVFMT_NOFILE) ||
demuxer->stream->type == STREAMTYPE_AVDEVICE ||
- matches_avinputformat_name(priv, "hls"))
+ priv->format_hack.no_stream)
{
mp_setup_av_network_options(&dopts, demuxer->global, demuxer->log, opts);
// This might be incorrect.
@@ -870,9 +875,7 @@ static int demux_lavf_fill_buffer(demuxer_t *demux)
}
av_free_packet(pkt);
- // Do not confuse player's position estimation (position is into segment,
- // player knows about the playlist main file only).
- if (matches_avinputformat_name(priv, "hls"))
+ if (priv->format_hack.clear_filepos)
dp->pos = -1;
demux_add_packet(stream, dp);