* [FFmpeg-devel] [RFC PATCH] avformat: remove HLS protocol
@ 2025-07-08 19:14 Marvin Scholz
2025-07-08 20:59 ` Martin Storsjö
0 siblings, 1 reply; 3+ messages in thread
From: Marvin Scholz @ 2025-07-08 19:14 UTC (permalink / raw)
To: ffmpeg-devel
The use of this protocol was already discouraged and warned about
for years with the recommendation to use the HLS demuxer instead.
---
doc/protocols.texi | 20 ---
libavformat/Makefile | 2 -
libavformat/hlsproto.c | 318 ----------------------------------------
libavformat/protocols.c | 1 -
4 files changed, 341 deletions(-)
delete mode 100644 libavformat/hlsproto.c
diff --git a/doc/protocols.texi b/doc/protocols.texi
index 969f4bf022..99aaf2e252 100644
--- a/doc/protocols.texi
+++ b/doc/protocols.texi
@@ -406,26 +406,6 @@ Gophers protocol.
The Gopher protocol with TLS encapsulation.
-@section hls
-
-Read Apple HTTP Live Streaming compliant segmented stream as
-a uniform one. The M3U8 playlists describing the segments can be
-remote HTTP resources or local files, accessed using the standard
-file protocol.
-The nested protocol is declared by specifying
-"+@var{proto}" after the hls URI scheme name, where @var{proto}
-is either "file" or "http".
-
-@example
-hls+http://host/path/to/remote/resource.m3u8
-hls+file://path/to/local/resource.m3u8
-@end example
-
-Using this protocol is discouraged - the hls demuxer should work
-just as well (if not, please report the issues) and is more complete.
-To use the hls demuxer instead, simply use the direct URLs to the
-m3u8 files.
-
@section http
HTTP (Hyper Text Transfer Protocol).
diff --git a/libavformat/Makefile b/libavformat/Makefile
index 816eb9be4a..2ef6311632 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -672,7 +672,6 @@ OBJS-$(CONFIG_VAPOURSYNTH_DEMUXER) += vapoursynth.o
# protocols I/O
OBJS-$(CONFIG_ANDROID_CONTENT_PROTOCOL) += file.o
OBJS-$(CONFIG_ASYNC_PROTOCOL) += async.o
-OBJS-$(CONFIG_APPLEHTTP_PROTOCOL) += hlsproto.o
OBJS-$(CONFIG_BLURAY_PROTOCOL) += bluray.o
OBJS-$(CONFIG_CACHE_PROTOCOL) += cache.o
OBJS-$(CONFIG_CONCAT_PROTOCOL) += concat.o
@@ -686,7 +685,6 @@ OBJS-$(CONFIG_FD_PROTOCOL) += file.o
OBJS-$(CONFIG_FTP_PROTOCOL) += ftp.o urldecode.o
OBJS-$(CONFIG_GOPHER_PROTOCOL) += gopher.o
OBJS-$(CONFIG_GOPHERS_PROTOCOL) += gopher.o
-OBJS-$(CONFIG_HLS_PROTOCOL) += hlsproto.o
OBJS-$(CONFIG_HTTP_PROTOCOL) += http.o httpauth.o urldecode.o
OBJS-$(CONFIG_HTTPPROXY_PROTOCOL) += http.o httpauth.o urldecode.o
OBJS-$(CONFIG_HTTPS_PROTOCOL) += http.o httpauth.o urldecode.o
diff --git a/libavformat/hlsproto.c b/libavformat/hlsproto.c
deleted file mode 100644
index 02f695c1db..0000000000
--- a/libavformat/hlsproto.c
+++ /dev/null
@@ -1,318 +0,0 @@
-/*
- * Apple HTTP Live Streaming Protocol Handler
- * Copyright (c) 2010 Martin Storsjo
- *
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-/**
- * @file
- * Apple HTTP Live Streaming Protocol Handler
- * https://www.rfc-editor.org/rfc/rfc8216.txt
- */
-
-#include "libavutil/avstring.h"
-#include "libavutil/mem.h"
-#include "libavutil/time.h"
-#include "avio_internal.h"
-#include "internal.h"
-#include "url.h"
-
-/*
- * An apple http stream consists of a playlist with media segment files,
- * played sequentially. There may be several playlists with the same
- * video content, in different bandwidth variants, that are played in
- * parallel (preferably only one bandwidth variant at a time). In this case,
- * the user supplied the url to a main playlist that only lists the variant
- * playlists.
- *
- * If the main playlist doesn't point at any variants, we still create
- * one anonymous toplevel variant for this, to maintain the structure.
- */
-
-struct segment {
- int64_t duration;
- char url[MAX_URL_SIZE];
-};
-
-struct variant {
- int bandwidth;
- char url[MAX_URL_SIZE];
-};
-
-typedef struct HLSContext {
- char playlisturl[MAX_URL_SIZE];
- int64_t target_duration;
- int start_seq_no;
- int finished;
- int n_segments;
- struct segment **segments;
- int n_variants;
- struct variant **variants;
- int cur_seq_no;
- URLContext *seg_hd;
- int64_t last_load_time;
-} HLSContext;
-
-static void free_segment_list(HLSContext *s)
-{
- int i;
- for (i = 0; i < s->n_segments; i++)
- av_freep(&s->segments[i]);
- av_freep(&s->segments);
- s->n_segments = 0;
-}
-
-static void free_variant_list(HLSContext *s)
-{
- int i;
- for (i = 0; i < s->n_variants; i++)
- av_freep(&s->variants[i]);
- av_freep(&s->variants);
- s->n_variants = 0;
-}
-
-struct variant_info {
- char bandwidth[20];
-};
-
-static void handle_variant_args(struct variant_info *info, const char *key,
- int key_len, char **dest, int *dest_len)
-{
- if (!strncmp(key, "BANDWIDTH=", key_len)) {
- *dest = info->bandwidth;
- *dest_len = sizeof(info->bandwidth);
- }
-}
-
-static int parse_playlist(URLContext *h, const char *url)
-{
- HLSContext *s = h->priv_data;
- AVIOContext *in;
- int ret = 0, is_segment = 0, is_variant = 0, bandwidth = 0;
- int64_t duration = 0;
- char line[1024];
- const char *ptr;
-
- if ((ret = ffio_open_whitelist(&in, url, AVIO_FLAG_READ,
- &h->interrupt_callback, NULL,
- h->protocol_whitelist, h->protocol_blacklist)) < 0)
- return ret;
-
- ff_get_chomp_line(in, line, sizeof(line));
- if (strcmp(line, "#EXTM3U")) {
- ret = AVERROR_INVALIDDATA;
- goto fail;
- }
-
- free_segment_list(s);
- s->finished = 0;
- while (!avio_feof(in)) {
- ff_get_chomp_line(in, line, sizeof(line));
- if (av_strstart(line, "#EXT-X-STREAM-INF:", &ptr)) {
- struct variant_info info = {{0}};
- is_variant = 1;
- ff_parse_key_value(ptr, (ff_parse_key_val_cb) handle_variant_args,
- &info);
- bandwidth = atoi(info.bandwidth);
- } else if (av_strstart(line, "#EXT-X-TARGETDURATION:", &ptr)) {
- s->target_duration = atoi(ptr) * AV_TIME_BASE;
- } else if (av_strstart(line, "#EXT-X-MEDIA-SEQUENCE:", &ptr)) {
- s->start_seq_no = atoi(ptr);
- } else if (av_strstart(line, "#EXT-X-ENDLIST", &ptr)) {
- s->finished = 1;
- } else if (av_strstart(line, "#EXTINF:", &ptr)) {
- is_segment = 1;
- duration = atof(ptr) * AV_TIME_BASE;
- } else if (av_strstart(line, "#", NULL)) {
- continue;
- } else if (line[0]) {
- if (is_segment) {
- struct segment *seg = av_malloc(sizeof(struct segment));
- if (!seg) {
- ret = AVERROR(ENOMEM);
- goto fail;
- }
- seg->duration = duration;
- ff_make_absolute_url(seg->url, sizeof(seg->url), url, line);
- dynarray_add(&s->segments, &s->n_segments, seg);
- is_segment = 0;
- } else if (is_variant) {
- struct variant *var = av_malloc(sizeof(struct variant));
- if (!var) {
- ret = AVERROR(ENOMEM);
- goto fail;
- }
- var->bandwidth = bandwidth;
- ff_make_absolute_url(var->url, sizeof(var->url), url, line);
- dynarray_add(&s->variants, &s->n_variants, var);
- is_variant = 0;
- }
- }
- }
- s->last_load_time = av_gettime_relative();
-
-fail:
- avio_close(in);
- return ret;
-}
-
-static int hls_close(URLContext *h)
-{
- HLSContext *s = h->priv_data;
-
- free_segment_list(s);
- free_variant_list(s);
- ffurl_closep(&s->seg_hd);
- return 0;
-}
-
-static int hls_open(URLContext *h, const char *uri, int flags)
-{
- HLSContext *s = h->priv_data;
- int ret, i;
- const char *nested_url;
-
- if (flags & AVIO_FLAG_WRITE)
- return AVERROR(ENOSYS);
-
- h->is_streamed = 1;
-
- if (av_strstart(uri, "hls+", &nested_url)) {
- av_strlcpy(s->playlisturl, nested_url, sizeof(s->playlisturl));
- } else if (av_strstart(uri, "hls://", &nested_url)) {
- av_log(h, AV_LOG_ERROR,
- "No nested protocol specified. Specify e.g. hls+http://%s\n",
- nested_url);
- ret = AVERROR(EINVAL);
- goto fail;
- } else {
- av_log(h, AV_LOG_ERROR, "Unsupported url %s\n", uri);
- ret = AVERROR(EINVAL);
- goto fail;
- }
- av_log(h, AV_LOG_WARNING,
- "Using the hls protocol is discouraged, please try using the "
- "hls demuxer instead. The hls demuxer should be more complete "
- "and work as well as the protocol implementation. (If not, "
- "please report it.) To use the demuxer, simply use %s as url.\n",
- s->playlisturl);
-
- if ((ret = parse_playlist(h, s->playlisturl)) < 0)
- goto fail;
-
- if (s->n_segments == 0 && s->n_variants > 0) {
- int max_bandwidth = 0, maxvar = -1;
- for (i = 0; i < s->n_variants; i++) {
- if (s->variants[i]->bandwidth > max_bandwidth || i == 0) {
- max_bandwidth = s->variants[i]->bandwidth;
- maxvar = i;
- }
- }
- av_strlcpy(s->playlisturl, s->variants[maxvar]->url,
- sizeof(s->playlisturl));
- if ((ret = parse_playlist(h, s->playlisturl)) < 0)
- goto fail;
- }
-
- if (s->n_segments == 0) {
- av_log(h, AV_LOG_WARNING, "Empty playlist\n");
- ret = AVERROR(EIO);
- goto fail;
- }
- s->cur_seq_no = s->start_seq_no;
- if (!s->finished && s->n_segments >= 3)
- s->cur_seq_no = s->start_seq_no + s->n_segments - 3;
-
- return 0;
-
-fail:
- hls_close(h);
- return ret;
-}
-
-static int hls_read(URLContext *h, uint8_t *buf, int size)
-{
- HLSContext *s = h->priv_data;
- const char *url;
- int ret;
- int64_t reload_interval;
-
-start:
- if (s->seg_hd) {
- ret = ffurl_read(s->seg_hd, buf, size);
- if (ret > 0)
- return ret;
- }
- if (s->seg_hd) {
- ffurl_closep(&s->seg_hd);
- s->cur_seq_no++;
- }
- reload_interval = s->n_segments > 0 ?
- s->segments[s->n_segments - 1]->duration :
- s->target_duration;
-retry:
- if (!s->finished) {
- int64_t now = av_gettime_relative();
- if (now - s->last_load_time >= reload_interval) {
- if ((ret = parse_playlist(h, s->playlisturl)) < 0)
- return ret;
- /* If we need to reload the playlist again below (if
- * there's still no more segments), switch to a reload
- * interval of half the target duration. */
- reload_interval = s->target_duration / 2;
- }
- }
- if (s->cur_seq_no < s->start_seq_no) {
- av_log(h, AV_LOG_WARNING,
- "skipping %d segments ahead, expired from playlist\n",
- s->start_seq_no - s->cur_seq_no);
- s->cur_seq_no = s->start_seq_no;
- }
- if (s->cur_seq_no - s->start_seq_no >= s->n_segments) {
- if (s->finished)
- return AVERROR_EOF;
- while (av_gettime_relative() - s->last_load_time < reload_interval) {
- if (ff_check_interrupt(&h->interrupt_callback))
- return AVERROR_EXIT;
- av_usleep(100*1000);
- }
- goto retry;
- }
- url = s->segments[s->cur_seq_no - s->start_seq_no]->url;
- av_log(h, AV_LOG_DEBUG, "opening %s\n", url);
- ret = ffurl_open_whitelist(&s->seg_hd, url, AVIO_FLAG_READ,
- &h->interrupt_callback, NULL,
- h->protocol_whitelist, h->protocol_blacklist, h);
- if (ret < 0) {
- if (ff_check_interrupt(&h->interrupt_callback))
- return AVERROR_EXIT;
- av_log(h, AV_LOG_WARNING, "Unable to open %s\n", url);
- s->cur_seq_no++;
- goto retry;
- }
- goto start;
-}
-
-const URLProtocol ff_hls_protocol = {
- .name = "hls",
- .url_open = hls_open,
- .url_read = hls_read,
- .url_close = hls_close,
- .flags = URL_PROTOCOL_FLAG_NESTED_SCHEME,
- .priv_data_size = sizeof(HLSContext),
-};
diff --git a/libavformat/protocols.c b/libavformat/protocols.c
index d394454d41..207b6bf8d9 100644
--- a/libavformat/protocols.c
+++ b/libavformat/protocols.c
@@ -39,7 +39,6 @@ extern const URLProtocol ff_file_protocol;
extern const URLProtocol ff_ftp_protocol;
extern const URLProtocol ff_gopher_protocol;
extern const URLProtocol ff_gophers_protocol;
-extern const URLProtocol ff_hls_protocol;
extern const URLProtocol ff_http_protocol;
extern const URLProtocol ff_httpproxy_protocol;
extern const URLProtocol ff_https_protocol;
--
2.39.5 (Apple Git-154)
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [FFmpeg-devel] [RFC PATCH] avformat: remove HLS protocol
2025-07-08 19:14 [FFmpeg-devel] [RFC PATCH] avformat: remove HLS protocol Marvin Scholz
@ 2025-07-08 20:59 ` Martin Storsjö
2025-07-08 21:01 ` Marton Balint
0 siblings, 1 reply; 3+ messages in thread
From: Martin Storsjö @ 2025-07-08 20:59 UTC (permalink / raw)
To: FFmpeg development discussions and patches
On Tue, 8 Jul 2025, Marvin Scholz wrote:
> The use of this protocol was already discouraged and warned about
> for years with the recommendation to use the HLS demuxer instead.
> ---
> doc/protocols.texi | 20 ---
> libavformat/Makefile | 2 -
> libavformat/hlsproto.c | 318 ----------------------------------------
> libavformat/protocols.c | 1 -
> 4 files changed, 341 deletions(-)
> delete mode 100644 libavformat/hlsproto.c
I'm ok with this removal.
I'll leave it up to others to clarify if it's ok to just remove it
outright or if we need to do some even further deprecation around it, etc.
(We've had an explicit warning discouraging the use of this since
9cb9c6c42dcd08746e0684eeacccf8b89b12e571 in 2012.)
// Martin
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [FFmpeg-devel] [RFC PATCH] avformat: remove HLS protocol
2025-07-08 20:59 ` Martin Storsjö
@ 2025-07-08 21:01 ` Marton Balint
0 siblings, 0 replies; 3+ messages in thread
From: Marton Balint @ 2025-07-08 21:01 UTC (permalink / raw)
To: FFmpeg development discussions and patches
On Tue, 8 Jul 2025, Martin Storsjö wrote:
> On Tue, 8 Jul 2025, Marvin Scholz wrote:
>
>> The use of this protocol was already discouraged and warned about
>> for years with the recommendation to use the HLS demuxer instead.
>> ---
>> doc/protocols.texi | 20 ---
>> libavformat/Makefile | 2 -
>> libavformat/hlsproto.c | 318 ----------------------------------------
>> libavformat/protocols.c | 1 -
>> 4 files changed, 341 deletions(-)
>> delete mode 100644 libavformat/hlsproto.c
>
> I'm ok with this removal.
>
> I'll leave it up to others to clarify if it's ok to just remove it outright
> or if we need to do some even further deprecation around it, etc. (We've had
> an explicit warning discouraging the use of this since
> 9cb9c6c42dcd08746e0684eeacccf8b89b12e571 in 2012.)
I think it is fine to simply remove it. Maybe add a changelog entry for
the removal.
Regards,
Marton
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2025-07-08 21:04 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-07-08 19:14 [FFmpeg-devel] [RFC PATCH] avformat: remove HLS protocol Marvin Scholz
2025-07-08 20:59 ` Martin Storsjö
2025-07-08 21:01 ` Marton Balint
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
This inbox may be cloned and mirrored by anyone:
git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git
# If you have public-inbox 1.1+ installed, you may
# initialize and index your mirror using the following commands:
public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
ffmpegdev@gitmailbox.com
public-inbox-index ffmpegdev
Example config snippet for mirrors.
AGPL code for this site: git clone https://public-inbox.org/public-inbox.git