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).
This commit is contained in:
wm4 2014-10-30 22:24:25 +01:00
parent 8c3baffadb
commit 56b852710a
1 changed files with 30 additions and 14 deletions

View File

@ -27,6 +27,17 @@
#define PROBE_SIZE (8 * 1024) #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 pl_parser {
struct mp_log *log; struct mp_log *log;
struct stream *s; struct stream *s;
@ -88,6 +99,22 @@ static int parse_ref_init(struct pl_parser *p)
bstr line = bstr_strip(pl_get_line(p)); bstr line = bstr_strip(pl_get_line(p));
if (!bstr_equals0(line, "[Reference]")) if (!bstr_equals0(line, "[Reference]"))
return -1; 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)) { while (!pl_eof(p)) {
line = bstr_strip(pl_get_line(p)); line = bstr_strip(pl_get_line(p));
if (bstr_case_startswith(line, bstr0("Ref"))) { if (bstr_case_startswith(line, bstr0("Ref"))) {
@ -153,15 +180,15 @@ static int parse_txt(struct pl_parser *p)
return 0; return 0;
} }
#define MIME_TYPES(...) \
.mime_types = (const char*const[]){__VA_ARGS__, NULL}
struct pl_format { struct pl_format {
const char *name; const char *name;
int (*parse)(struct pl_parser *p); int (*parse)(struct pl_parser *p);
const char *const *mime_types; const char *const *mime_types;
}; };
#define MIME_TYPES(...) \
.mime_types = (const char*const[]){__VA_ARGS__, NULL}
static const struct pl_format formats[] = { static const struct pl_format formats[] = {
{"m3u", parse_m3u, {"m3u", parse_m3u,
MIME_TYPES("audio/mpegurl", "audio/x-mpegurl", "application/x-mpegurl")}, MIME_TYPES("audio/mpegurl", "audio/x-mpegurl", "application/x-mpegurl")},
@ -172,17 +199,6 @@ static const struct pl_format formats[] = {
{"txt", parse_txt}, {"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) static const struct pl_format *probe_pl(struct pl_parser *p)
{ {
int64_t start = stream_tell(p->s); int64_t start = stream_tell(p->s);