From 56b852710ad0b6b1466427549db0792ee67318aa Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 30 Oct 2014 22:24:25 +0100 Subject: demux_playlist: redirect ASF streaming to mmsh:// I'm not sure if this could be done in libavformat instead. Probably not, because libavformat doesn't seem to have any mechanism for trying one protocol and reverting (or redirecting) to another one if needed. This commit is sort of a hack too, because it redirects the URL by pretending the http:// link is a playlist containing the mmsh:// link. The list of mime types is borrowed from MPlayer (which has completely different code to handle this). --- demux/demux_playlist.c | 44 ++++++++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/demux/demux_playlist.c b/demux/demux_playlist.c index 9f533e1b8e..905778e058 100644 --- a/demux/demux_playlist.c +++ b/demux/demux_playlist.c @@ -27,6 +27,17 @@ #define PROBE_SIZE (8 * 1024) +static bool check_mimetype(struct stream *s, const char *const *list) +{ + if (s->mime_type) { + for (int n = 0; list && list[n]; n++) { + if (strcmp(s->mime_type, list[n]) == 0) + return true; + } + } + return false; +} + struct pl_parser { struct mp_log *log; struct stream *s; @@ -88,6 +99,22 @@ static int parse_ref_init(struct pl_parser *p) bstr line = bstr_strip(pl_get_line(p)); if (!bstr_equals0(line, "[Reference]")) return -1; + + // ASF http streaming redirection - this is needed because ffmpeg http:// + // and mmsh:// can not automatically switch automatically between each + // others. Both protocols use http - MMSH requires special http headers + // to "activate" it, and will in other cases return this playlist. + static const char *const mmsh_types[] = {"audio/x-ms-wax", + "audio/x-ms-wma", "video/x-ms-asf", "video/x-ms-afs", "video/x-ms-wmv", + "video/x-ms-wma", "application/x-mms-framed", + "application/vnd.ms.wms-hdr.asfv1", NULL}; + bstr burl = bstr0(p->s->url); + if (bstr_eatstart0(&burl, "http://") && check_mimetype(p->s, mmsh_types)) { + MP_INFO(p, "Redirectiong to mmsh://\n"); + playlist_add_file(p->pl, talloc_asprintf(p, "mmsh://%.*s", BSTR_P(burl))); + return 0; + } + while (!pl_eof(p)) { line = bstr_strip(pl_get_line(p)); if (bstr_case_startswith(line, bstr0("Ref"))) { @@ -153,15 +180,15 @@ static int parse_txt(struct pl_parser *p) return 0; } +#define MIME_TYPES(...) \ + .mime_types = (const char*const[]){__VA_ARGS__, NULL} + struct pl_format { const char *name; int (*parse)(struct pl_parser *p); const char *const *mime_types; }; -#define MIME_TYPES(...) \ - .mime_types = (const char*const[]){__VA_ARGS__, NULL} - static const struct pl_format formats[] = { {"m3u", parse_m3u, MIME_TYPES("audio/mpegurl", "audio/x-mpegurl", "application/x-mpegurl")}, @@ -172,17 +199,6 @@ static const struct pl_format formats[] = { {"txt", parse_txt}, }; -static bool check_mimetype(struct stream *s, const char *const *list) -{ - if (s->mime_type) { - for (int n = 0; list && list[n]; n++) { - if (strcmp(s->mime_type, list[n]) == 0) - return true; - } - } - return false; -} - static const struct pl_format *probe_pl(struct pl_parser *p) { int64_t start = stream_tell(p->s); -- cgit v1.2.3