1 /*
2 * Apple HTTP Live Streaming Protocol Handler
3 * Copyright (c) 2010 Martin Storsjo
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 /**
23 * @file
24 * Apple HTTP Live Streaming Protocol Handler
25 * http://tools.ietf.org/html/draft-pantos-http-live-streaming
26 */
27
34
35 /*
36 * An apple http stream consists of a playlist with media segment files,
37 * played sequentially. There may be several playlists with the same
38 * video content, in different bandwidth variants, that are played in
39 * parallel (preferably only one bandwidth variant at a time). In this case,
40 * the user supplied the url to a main playlist that only lists the variant
41 * playlists.
42 *
43 * If the main playlist doesn't point at any variants, we still create
44 * one anonymous toplevel variant for this, to maintain the structure.
45 */
46
50 };
51
55 };
56
70
72 {
77 }
78
80 {
81 int i;
86 }
87
89 {
90 int i;
95 }
96
99 };
100
102 int key_len, char **dest, int *dest_len)
103 {
104 if (!strncmp(key, "BANDWIDTH=", key_len)) {
107 }
108 }
109
111 {
114 int ret = 0, is_segment = 0, is_variant = 0, bandwidth = 0;
117 const char *ptr;
118
122
124 if (strcmp(line, "#EXTM3U")) {
126 goto fail;
127 }
128
133 if (
av_strstart(line,
"#EXT-X-STREAM-INF:", &ptr)) {
135 is_variant = 1;
137 &info);
139 }
else if (
av_strstart(line,
"#EXT-X-TARGETDURATION:", &ptr)) {
141 }
else if (
av_strstart(line,
"#EXT-X-MEDIA-SEQUENCE:", &ptr)) {
143 }
else if (
av_strstart(line,
"#EXT-X-ENDLIST", &ptr)) {
146 is_segment = 1;
149 continue;
150 } else if (line[0]) {
151 if (is_segment) {
153 if (!seg) {
155 goto fail;
156 }
160 is_segment = 0;
161 } else if (is_variant) {
163 if (!var) {
165 goto fail;
166 }
170 is_variant = 0;
171 }
172 }
173 }
175
176 fail:
179 }
180
182 {
184
188 return 0;
189 }
190
192 {
195 const char *nested_url;
196
199
201
204 }
else if (
av_strstart(uri,
"hls://", &nested_url)) {
206 "No nested protocol specified. Specify e.g. hls+http://%s\n",
207 nested_url);
209 goto fail;
210 } else {
213 goto fail;
214 }
216 "Using the hls protocol is discouraged, please try using the "
217 "hls demuxer instead. The hls demuxer should be more complete "
218 "and work as well as the protocol implementation. (If not, "
219 "please report it.) To use the demuxer, simply use %s as url.\n",
221
223 goto fail;
224
226 int max_bandwidth = 0, maxvar = -1;
230 maxvar = i;
231 }
232 }
236 goto fail;
237 }
238
242 goto fail;
243 }
247
248 return 0;
249
250 fail:
253 }
254
256 {
260 int64_t reload_interval;
261
265 if (ret > 0)
267 }
272 }
276 retry:
282 /* If we need to reload the playlist again below (if
283 * there's still no more segments), switch to a reload
284 * interval of half the target duration. */
286 }
287 }
290 "skipping %d segments ahead, expired from playlist\n",
293 }
301 }
302 goto retry;
303 }
308 if (ret < 0) {
313 goto retry;
314 }
316 }
317
325 };