Skip to content

Commit

Permalink
demux/demux_lavf: pass dummy filename when an HLS mimetype is detected
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Traneptora committed May 14, 2023
1 parent 9e716d6 commit acababe
Showing 1 changed file with 27 additions and 2 deletions.
29 changes: 27 additions & 2 deletions demux/demux_lavf.c
Expand Up @@ -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;
Expand Down Expand Up @@ -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),
};
Expand Down

0 comments on commit acababe

Please sign in to comment.