From: Steven Liu <lingjiujianke-at-gmail.com@ffmpeg.org> To: FFmpeg development discussions and patches <ffmpeg-devel@ffmpeg.org> Subject: Re: [FFmpeg-devel] [RFC PATCH] avformat: remove HLS protocol Date: Wed, 9 Jul 2025 17:18:47 +0800 Message-ID: <CADxeRwmjh0shhh5=CGXJ7ZaNbckS+eCDfKwB37naXP6sdsnMrQ@mail.gmail.com> (raw) In-Reply-To: <20250708191412.68722-1-epirat07@gmail.com> Marvin Scholz <epirat07-at-gmail.com@ffmpeg.org> 于2025年7月9日周三 03:14写道: Hi Marvin, > > The use of this protocol was already discouraged and warned about > for years with the recommendation to use the HLS demuxer instead. What about make deprecated warning to users and remove it next major version? > --- > 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". _______________________________________________ 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".
next prev parent reply other threads:[~2025-07-09 9:19 UTC|newest] Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top 2025-07-08 19:14 Marvin Scholz 2025-07-08 20:59 ` Martin Storsjö 2025-07-08 21:01 ` Marton Balint 2025-07-09 9:18 ` Steven Liu [this message] 2025-07-09 13:28 ` Marvin Scholz 2025-07-09 15:32 ` Timo Rothenpieler 2025-07-09 20:42 ` Steven Liu
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to='CADxeRwmjh0shhh5=CGXJ7ZaNbckS+eCDfKwB37naXP6sdsnMrQ@mail.gmail.com' \ --to=lingjiujianke-at-gmail.com@ffmpeg.org \ --cc=ffmpeg-devel@ffmpeg.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
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