From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from ffbox0-bg.ffmpeg.org (ffbox0-bg.ffmpeg.org [79.124.17.100]) by master.gitmailbox.com (Postfix) with ESMTPS id 167B0501A1 for ; Tue, 8 Jul 2025 19:14:31 +0000 (UTC) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.ffmpeg.org (Postfix) with ESMTP id 244E468E891; Tue, 8 Jul 2025 22:14:28 +0300 (EEST) Received: from mail-ej1-f41.google.com (mail-ej1-f41.google.com [209.85.218.41]) by ffbox0-bg.ffmpeg.org (Postfix) with ESMTPS id 6B15668E77C for ; Tue, 8 Jul 2025 22:14:21 +0300 (EEST) Received: by mail-ej1-f41.google.com with SMTP id a640c23a62f3a-ae0dd7ac1f5so895700866b.2 for ; Tue, 08 Jul 2025 12:14:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1752002061; x=1752606861; darn=ffmpeg.org; h=content-transfer-encoding:mime-version:message-id:date:subject:to :from:from:to:cc:subject:date:message-id:reply-to; bh=1SM4dubCgPYXb42UVON+miAIlvUTDyB9BTb4Faic/ug=; b=nXqwmD6z1TJoFQxlCc/rUfH5e3OlBxNo3EXPXOu1I90sE8ZrirARxHnsvxiTcOSBfB CzngaglwzFdQXxadOKK3mJjFBqi1JQL9J+TaDUrc/42YLUdXcDph3aJVCxZtBwhFRAyz NWKg7XDYPQZGchV2b71TYNd5QldYGaCq9uWyoraZjXCIpTzwzdnkluN65QwDlH+NLLeP ia1p57gc+1RHRCR2JIQKVnC7TJX+HvUbh8gawdN4HMU+o+15uDLxrW7/nRRVlCCu2Rnm C5ShTwWYsWwxFYIejfSC2IGTKTWpsZWlbjxpMwi4f7nEu4NGILxFwFL0xSRbow67TQwO ddFg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1752002061; x=1752606861; h=content-transfer-encoding:mime-version:message-id:date:subject:to :from:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=1SM4dubCgPYXb42UVON+miAIlvUTDyB9BTb4Faic/ug=; b=IyxLwukOTeQsU0v+KBnvuL9tZUOSyxV57gee5Vnp1crdAlzFosmWnlqlaSqDiT/mbB TkQJfTNpUVSlxjp5HAETvgPZSpDB8/ZThuzUBtdIs7AIKa2g+rWTfusmN3VLKfOAMk89 ilokrxVP5u1ZewqkRhviVcPcWKz2wntdhU1cxflrOjUCFjymmwL0j0Hb++I1pNyTd7Zx pXg8beL5+dVevDBF7Ha34N/0R7pQJnS9iqjgmLqDUix9mOkO26AdJEmea2/VA7war3Es ismj/T6+vc1ckLWdjtpfTqAyTF+i53TaIGF0h+sMEAljjiiHIN3x6X0cnskGTnGZD2a+ QdGQ== X-Gm-Message-State: AOJu0YyyhROmn+hwPkLiBVSjkVNHhwZUXIlr5pj+7rx7J/dJEVg2S4A0 pmWlhUbJLUKAHPFVmJle5Xo44YGHuS73N3jOrhVhGO+5uyEqX6MU4x8MBZ/nAfGe X-Gm-Gg: ASbGncvEGqGcadXVW1zDv+k+u3d9GchhFX+95bEK1WHpXE/bvt2WTG1pbM7yNjZTObL XiexlZTHmq90LIGoctgq3unOWD8la4Rf9JtODatCcq8gEyFxrvyddBaUuTCwjW9k7IwXanEXHKK 5/rqfZo5RPiy4qp94zIFIwXvKyMyB7KJhYS+bFOHgx29ji3EpbL8/yPyqDViBTKi9TZMut9ExTl IDnhDaGk2BISCxMgUvWfs65p2lKTZ1NH/iqysgBieftUeT0o4sgP1T4zOIxx2vT1lXDDwZ7tuZy 2SgxtD7o31+i++qECwz+AoD7SjxD7kSQ7jeAB+BHVZF5USTFXFhl8Ca0YC2FzDZlfhqKVWo/BEn GF08fZn6EWbNEjNRnEx/WyoYIAjZ+zwgT4VzzM2bzm8waUP4RV8H5B2nRo9yx55bFr9y8qq2uTg hun+cIvQ== X-Google-Smtp-Source: AGHT+IFdy5fTDlbsvfFZTcarK3x/IGRxVf62JLAGywFOoGUs4aft/CZotPBgFqZVN5fBiZBZO9mdCQ== X-Received: by 2002:a17:907:7285:b0:ae0:d4f2:dff3 with SMTP id a640c23a62f3a-ae6c953cae9mr24631666b.58.1752002060410; Tue, 08 Jul 2025 12:14:20 -0700 (PDT) Received: from localhost.localdomain (p200301023701fa00258573ace0251429.dip0.t-ipconnect.de. [2003:102:3701:fa00:2585:73ac:e025:1429]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-ae3f6b8d523sm948428266b.171.2025.07.08.12.14.19 for (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Tue, 08 Jul 2025 12:14:19 -0700 (PDT) From: Marvin Scholz To: ffmpeg-devel@ffmpeg.org Date: Tue, 8 Jul 2025 21:14:12 +0200 Message-Id: <20250708191412.68722-1-epirat07@gmail.com> X-Mailer: git-send-email 2.39.5 (Apple Git-154) MIME-Version: 1.0 Subject: [FFmpeg-devel] [RFC PATCH] avformat: remove HLS protocol X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Archived-At: List-Archive: List-Post: 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".