summaryrefslogtreecommitdiffstats
path: root/demux
diff options
context:
space:
mode:
authorLeo Izen <leo.izen@gmail.com>2023-05-12 16:01:28 -0400
committerLeo Izen <leo.izen@gmail.com>2023-05-14 16:28:29 -0400
commitacababec208ec4f26c1462228a9ec1d4aac2c815 (patch)
treefe7f3af4463a3a33d96b51d2c3bc5999dd553076 /demux
parent9e716d63033c31d01cf9fca1e55e5388b6a8bba3 (diff)
downloadmpv-acababec208ec4f26c1462228a9ec1d4aac2c815.tar.bz2
mpv-acababec208ec4f26c1462228a9ec1d4aac2c815.tar.xz
demux/demux_lavf: pass dummy filename when an HLS mimetype is detected
Pass "dummy.m3u8" filename to work around FFmpeg commit 6b1f68ccb04d791f0250e05687c346a99ff47ea1 which broke their HLS demuxer and its ability to probe. Since the above commit, libavformat will check the filename of the file to be probed and reject it if it doesn't end with a valid HLS extension i.e. m3u8,hls,m3u (never mind that .hls is not a valid HLS extension). In addition to a bug with query strings, this also breaks mpv functionality as mpv explicitly doesn't tell libavformat the filename when probing, in order to properly detect the file based only on their contents. The [HLS specification](https://www.rfc-editor.org/rfc/rfc8216.txt) aka RFC 8216, specifies in section 4 that "Each Playlist file MUST be identifiable either by the path component of its URI or by HTTP Content-Type." Notably, it does not require both, so this FFmpeg commit is noncompliant. We work around this noncompliance by checking the MIME type ourselves. If the mimetype matches one of the valid HLS mimetypes (and also application/x-mpegurl, a legacy pre-standardization type), then we pass "dummy.m3u8" to libavformat in order to work around its overly strict checking of filenames. Without this patch, we are unable to play many HLS streams, including a few from the ytdl hook. This patch restores those ability to play those streams when built against FFmpeg master. Do note that if the server sends an invalid content-type header then we cannot implement this workaround so those streams will still fail to play.
Diffstat (limited to 'demux')
-rw-r--r--demux/demux_lavf.c29
1 files changed, 27 insertions, 2 deletions
diff --git a/demux/demux_lavf.c b/demux/demux_lavf.c
index ee08b4df6c..d34cb1ecfa 100644
--- a/demux/demux_lavf.c
+++ b/demux/demux_lavf.c
@@ -423,6 +423,17 @@ static char *remove_prefix(char *s, const char *const *prefixes)
static const char *const prefixes[] =
{"ffmpeg://", "lavf://", "avdevice://", "av://", NULL};
+/*
+ * https://www.rfc-editor.org/rfc/rfc8216.txt
+ *
+ * application/x-mpegurl is a legacy mimetype in Apple's HLS docs
+ */
+static const char *const hls_mime_types[] = {
+ "application/x-mpegurl",
+ "application/vnd.apple.mpegurl",
+ "audio/mpegurl",
+};
+
static int lavf_check_file(demuxer_t *demuxer, enum demux_check check)
{
lavf_priv_t *priv = demuxer->priv;
@@ -466,9 +477,23 @@ static int lavf_check_file(demuxer_t *demuxer, enum demux_check check)
}
}
+ bool matches_hls_mime = 0;
+ for (int i = 0; i < MP_ARRAY_SIZE(hls_mime_types); i++) {
+ if (!strcasecmp(mime_type, hls_mime_types[i])) {
+ matches_hls_mime = 1;
+ break;
+ }
+ }
+
AVProbeData avpd = {
- // Disable file-extension matching with normal checks
- .filename = check <= DEMUX_CHECK_REQUEST ? priv->filename : "",
+ /*
+ * Disable file-extension matching with normal checks,
+ * unless it's an HLS mimetype.
+ *
+ * The HLS check works around a regression introduced by FFmpeg commit
+ * 6b1f68ccb04d791f0250e05687c346a99ff47ea1 that is unlikely to be reverted.
+ */
+ .filename = matches_hls_mime ? "dummy.m3u8" : (check <= DEMUX_CHECK_REQUEST ? priv->filename : ""),
.buf_size = 0,
.buf = av_mallocz(PROBE_BUF_SIZE + AV_INPUT_BUFFER_PADDING_SIZE),
};