Commit | Line | Data |
---|---|---|
cd223e0b MS |
1 | /* |
2 | * Apple HTTP Live Streaming demuxer | |
3 | * Copyright (c) 2010 Martin Storsjo | |
4 | * | |
2912e87a | 5 | * This file is part of Libav. |
cd223e0b | 6 | * |
2912e87a | 7 | * Libav is free software; you can redistribute it and/or |
cd223e0b MS |
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 | * | |
2912e87a | 12 | * Libav is distributed in the hope that it will be useful, |
cd223e0b MS |
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 | |
2912e87a | 18 | * License along with Libav; if not, write to the Free Software |
cd223e0b MS |
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
20 | */ | |
21 | ||
22 | /** | |
23 | * @file | |
24 | * Apple HTTP Live Streaming demuxer | |
25 | * http://tools.ietf.org/html/draft-pantos-http-live-streaming | |
26 | */ | |
27 | ||
28 | #include "libavutil/avstring.h" | |
84465f21 | 29 | #include "libavutil/intreadwrite.h" |
0ebcdf5c | 30 | #include "libavutil/mathematics.h" |
84465f21 | 31 | #include "libavutil/opt.h" |
d2d67e42 | 32 | #include "libavutil/dict.h" |
896bb0d7 | 33 | #include "libavutil/time.h" |
cd223e0b MS |
34 | #include "avformat.h" |
35 | #include "internal.h" | |
6cc7f139 MS |
36 | #include "avio_internal.h" |
37 | ||
38 | #define INITIAL_BUFFER_SIZE 32768 | |
cd223e0b MS |
39 | |
40 | /* | |
41 | * An apple http stream consists of a playlist with media segment files, | |
42 | * played sequentially. There may be several playlists with the same | |
43 | * video content, in different bandwidth variants, that are played in | |
511cf612 | 44 | * parallel (preferably only one bandwidth variant at a time). In this case, |
cd223e0b MS |
45 | * the user supplied the url to a main playlist that only lists the variant |
46 | * playlists. | |
47 | * | |
48 | * If the main playlist doesn't point at any variants, we still create | |
49 | * one anonymous toplevel variant for this, to maintain the structure. | |
50 | */ | |
51 | ||
84465f21 MS |
52 | enum KeyType { |
53 | KEY_NONE, | |
54 | KEY_AES_128, | |
55 | }; | |
56 | ||
cd223e0b | 57 | struct segment { |
c4419103 | 58 | int64_t duration; |
cd223e0b | 59 | char url[MAX_URL_SIZE]; |
84465f21 MS |
60 | char key[MAX_URL_SIZE]; |
61 | enum KeyType key_type; | |
62 | uint8_t iv[16]; | |
cd223e0b MS |
63 | }; |
64 | ||
65 | /* | |
66 | * Each variant has its own demuxer. If it currently is active, | |
ae628ec1 | 67 | * it has an open AVIOContext too, and potentially an AVPacket |
cd223e0b MS |
68 | * containing the next packet from this stream. |
69 | */ | |
70 | struct variant { | |
71 | int bandwidth; | |
72 | char url[MAX_URL_SIZE]; | |
6cc7f139 MS |
73 | AVIOContext pb; |
74 | uint8_t* read_buffer; | |
81306fd4 | 75 | AVIOContext *input; |
6cc7f139 MS |
76 | AVFormatContext *parent; |
77 | int index; | |
cd223e0b MS |
78 | AVFormatContext *ctx; |
79 | AVPacket pkt; | |
80 | int stream_offset; | |
81 | ||
d3964da2 | 82 | int finished; |
c4419103 | 83 | int64_t target_duration; |
cd223e0b MS |
84 | int start_seq_no; |
85 | int n_segments; | |
86 | struct segment **segments; | |
6cc7f139 MS |
87 | int needed, cur_needed; |
88 | int cur_seq_no; | |
89 | int64_t last_load_time; | |
84465f21 MS |
90 | |
91 | char key_url[MAX_URL_SIZE]; | |
92 | uint8_t key[16]; | |
cd223e0b MS |
93 | }; |
94 | ||
65cd7bf3 | 95 | typedef struct HLSContext { |
9f61abc8 | 96 | AVFormatContext *ctx; |
cd223e0b MS |
97 | int n_variants; |
98 | struct variant **variants; | |
99 | int cur_seq_no; | |
6cc7f139 MS |
100 | int end_of_segment; |
101 | int first_packet; | |
795d9594 | 102 | int64_t first_timestamp; |
2b3d041c PI |
103 | int64_t seek_timestamp; |
104 | int seek_flags; | |
9957cdbf | 105 | AVIOInterruptCB *interrupt_callback; |
0c73a5a5 | 106 | AVDictionary *avio_opts; |
65cd7bf3 | 107 | } HLSContext; |
cd223e0b | 108 | |
ae628ec1 | 109 | static int read_chomp_line(AVIOContext *s, char *buf, int maxlen) |
cd223e0b MS |
110 | { |
111 | int len = ff_get_line(s, buf, maxlen); | |
efa7f420 | 112 | while (len > 0 && av_isspace(buf[len - 1])) |
cd223e0b MS |
113 | buf[--len] = '\0'; |
114 | return len; | |
115 | } | |
116 | ||
cd223e0b MS |
117 | static void free_segment_list(struct variant *var) |
118 | { | |
119 | int i; | |
120 | for (i = 0; i < var->n_segments; i++) | |
121 | av_free(var->segments[i]); | |
122 | av_freep(&var->segments); | |
123 | var->n_segments = 0; | |
124 | } | |
125 | ||
65cd7bf3 | 126 | static void free_variant_list(HLSContext *c) |
cd223e0b MS |
127 | { |
128 | int i; | |
129 | for (i = 0; i < c->n_variants; i++) { | |
130 | struct variant *var = c->variants[i]; | |
131 | free_segment_list(var); | |
ce70f28a | 132 | av_packet_unref(&var->pkt); |
6cc7f139 MS |
133 | av_free(var->pb.buffer); |
134 | if (var->input) | |
81306fd4 | 135 | ff_format_io_close(c->ctx, &var->input); |
cd223e0b MS |
136 | if (var->ctx) { |
137 | var->ctx->pb = NULL; | |
cd3716b9 | 138 | avformat_close_input(&var->ctx); |
cd223e0b MS |
139 | } |
140 | av_free(var); | |
141 | } | |
142 | av_freep(&c->variants); | |
143 | c->n_variants = 0; | |
144 | } | |
145 | ||
146 | /* | |
147 | * Used to reset a statically allocated AVPacket to a clean slate, | |
148 | * containing no data. | |
149 | */ | |
150 | static void reset_packet(AVPacket *pkt) | |
151 | { | |
152 | av_init_packet(pkt); | |
153 | pkt->data = NULL; | |
154 | } | |
155 | ||
65cd7bf3 | 156 | static struct variant *new_variant(HLSContext *c, int bandwidth, |
cd223e0b MS |
157 | const char *url, const char *base) |
158 | { | |
159 | struct variant *var = av_mallocz(sizeof(struct variant)); | |
160 | if (!var) | |
161 | return NULL; | |
162 | reset_packet(&var->pkt); | |
163 | var->bandwidth = bandwidth; | |
f1f60f52 | 164 | ff_make_absolute_url(var->url, sizeof(var->url), base, url); |
cd223e0b MS |
165 | dynarray_add(&c->variants, &c->n_variants, var); |
166 | return var; | |
167 | } | |
168 | ||
169 | struct variant_info { | |
170 | char bandwidth[20]; | |
171 | }; | |
172 | ||
173 | static void handle_variant_args(struct variant_info *info, const char *key, | |
174 | int key_len, char **dest, int *dest_len) | |
175 | { | |
2b0decf6 | 176 | if (!strncmp(key, "BANDWIDTH=", key_len)) { |
cd223e0b MS |
177 | *dest = info->bandwidth; |
178 | *dest_len = sizeof(info->bandwidth); | |
179 | } | |
180 | } | |
181 | ||
84465f21 MS |
182 | struct key_info { |
183 | char uri[MAX_URL_SIZE]; | |
184 | char method[10]; | |
185 | char iv[35]; | |
186 | }; | |
187 | ||
188 | static void handle_key_args(struct key_info *info, const char *key, | |
189 | int key_len, char **dest, int *dest_len) | |
190 | { | |
191 | if (!strncmp(key, "METHOD=", key_len)) { | |
192 | *dest = info->method; | |
193 | *dest_len = sizeof(info->method); | |
194 | } else if (!strncmp(key, "URI=", key_len)) { | |
195 | *dest = info->uri; | |
196 | *dest_len = sizeof(info->uri); | |
197 | } else if (!strncmp(key, "IV=", key_len)) { | |
198 | *dest = info->iv; | |
199 | *dest_len = sizeof(info->iv); | |
200 | } | |
201 | } | |
202 | ||
0c73a5a5 LB |
203 | static int open_in(HLSContext *c, AVIOContext **in, const char *url) |
204 | { | |
205 | AVDictionary *tmp = NULL; | |
206 | int ret; | |
207 | ||
208 | av_dict_copy(&tmp, c->avio_opts, 0); | |
209 | ||
9f61abc8 | 210 | ret = c->ctx->io_open(c->ctx, in, url, AVIO_FLAG_READ, &tmp); |
0c73a5a5 LB |
211 | |
212 | av_dict_free(&tmp); | |
213 | return ret; | |
214 | } | |
215 | ||
81306fd4 AK |
216 | static int open_url(AVFormatContext *s, AVIOContext **pb, const char *url, |
217 | const AVDictionary *opts) | |
0c73a5a5 LB |
218 | { |
219 | AVDictionary *tmp = NULL; | |
220 | int ret; | |
221 | ||
222 | av_dict_copy(&tmp, opts, 0); | |
223 | ||
81306fd4 | 224 | ret = s->io_open(s, pb, url, AVIO_FLAG_READ, &tmp); |
0c73a5a5 LB |
225 | |
226 | av_dict_free(&tmp); | |
227 | ||
228 | return ret; | |
229 | } | |
230 | ||
65cd7bf3 | 231 | static int parse_playlist(HLSContext *c, const char *url, |
ae628ec1 | 232 | struct variant *var, AVIOContext *in) |
cd223e0b | 233 | { |
c4419103 MS |
234 | int ret = 0, is_segment = 0, is_variant = 0, bandwidth = 0; |
235 | int64_t duration = 0; | |
84465f21 MS |
236 | enum KeyType key_type = KEY_NONE; |
237 | uint8_t iv[16] = ""; | |
238 | int has_iv = 0; | |
c41b9842 | 239 | char key[MAX_URL_SIZE] = ""; |
cd223e0b MS |
240 | char line[1024]; |
241 | const char *ptr; | |
242 | int close_in = 0; | |
8c929098 | 243 | uint8_t *new_url = NULL; |
cd223e0b MS |
244 | |
245 | if (!in) { | |
0c73a5a5 LB |
246 | ret = open_in(c, &in, url); |
247 | if (ret < 0) | |
cd223e0b | 248 | return ret; |
0c73a5a5 | 249 | close_in = 1; |
cd223e0b MS |
250 | } |
251 | ||
8c929098 MS |
252 | if (av_opt_get(in, "location", AV_OPT_SEARCH_CHILDREN, &new_url) >= 0) |
253 | url = new_url; | |
254 | ||
cd223e0b MS |
255 | read_chomp_line(in, line, sizeof(line)); |
256 | if (strcmp(line, "#EXTM3U")) { | |
257 | ret = AVERROR_INVALIDDATA; | |
258 | goto fail; | |
259 | } | |
260 | ||
d3964da2 | 261 | if (var) { |
cd223e0b | 262 | free_segment_list(var); |
d3964da2 MS |
263 | var->finished = 0; |
264 | } | |
66e5b1df | 265 | while (!in->eof_reached) { |
cd223e0b MS |
266 | read_chomp_line(in, line, sizeof(line)); |
267 | if (av_strstart(line, "#EXT-X-STREAM-INF:", &ptr)) { | |
268 | struct variant_info info = {{0}}; | |
269 | is_variant = 1; | |
270 | ff_parse_key_value(ptr, (ff_parse_key_val_cb) handle_variant_args, | |
271 | &info); | |
272 | bandwidth = atoi(info.bandwidth); | |
84465f21 MS |
273 | } else if (av_strstart(line, "#EXT-X-KEY:", &ptr)) { |
274 | struct key_info info = {{0}}; | |
275 | ff_parse_key_value(ptr, (ff_parse_key_val_cb) handle_key_args, | |
276 | &info); | |
277 | key_type = KEY_NONE; | |
278 | has_iv = 0; | |
279 | if (!strcmp(info.method, "AES-128")) | |
280 | key_type = KEY_AES_128; | |
281 | if (!strncmp(info.iv, "0x", 2) || !strncmp(info.iv, "0X", 2)) { | |
282 | ff_hex_to_data(iv, info.iv + 2); | |
283 | has_iv = 1; | |
284 | } | |
285 | av_strlcpy(key, info.uri, sizeof(key)); | |
cd223e0b | 286 | } else if (av_strstart(line, "#EXT-X-TARGETDURATION:", &ptr)) { |
d3964da2 MS |
287 | if (!var) { |
288 | var = new_variant(c, 0, url, NULL); | |
289 | if (!var) { | |
290 | ret = AVERROR(ENOMEM); | |
291 | goto fail; | |
292 | } | |
293 | } | |
c4419103 | 294 | var->target_duration = atoi(ptr) * AV_TIME_BASE; |
cd223e0b MS |
295 | } else if (av_strstart(line, "#EXT-X-MEDIA-SEQUENCE:", &ptr)) { |
296 | if (!var) { | |
297 | var = new_variant(c, 0, url, NULL); | |
298 | if (!var) { | |
299 | ret = AVERROR(ENOMEM); | |
300 | goto fail; | |
301 | } | |
302 | } | |
303 | var->start_seq_no = atoi(ptr); | |
304 | } else if (av_strstart(line, "#EXT-X-ENDLIST", &ptr)) { | |
d3964da2 MS |
305 | if (var) |
306 | var->finished = 1; | |
cd223e0b MS |
307 | } else if (av_strstart(line, "#EXTINF:", &ptr)) { |
308 | is_segment = 1; | |
c4419103 | 309 | duration = atof(ptr) * AV_TIME_BASE; |
cd223e0b MS |
310 | } else if (av_strstart(line, "#", NULL)) { |
311 | continue; | |
312 | } else if (line[0]) { | |
313 | if (is_variant) { | |
314 | if (!new_variant(c, bandwidth, line, url)) { | |
315 | ret = AVERROR(ENOMEM); | |
316 | goto fail; | |
317 | } | |
318 | is_variant = 0; | |
319 | bandwidth = 0; | |
320 | } | |
321 | if (is_segment) { | |
322 | struct segment *seg; | |
323 | if (!var) { | |
324 | var = new_variant(c, 0, url, NULL); | |
325 | if (!var) { | |
326 | ret = AVERROR(ENOMEM); | |
327 | goto fail; | |
328 | } | |
329 | } | |
330 | seg = av_malloc(sizeof(struct segment)); | |
331 | if (!seg) { | |
332 | ret = AVERROR(ENOMEM); | |
333 | goto fail; | |
334 | } | |
335 | seg->duration = duration; | |
84465f21 MS |
336 | seg->key_type = key_type; |
337 | if (has_iv) { | |
338 | memcpy(seg->iv, iv, sizeof(iv)); | |
339 | } else { | |
340 | int seq = var->start_seq_no + var->n_segments; | |
341 | memset(seg->iv, 0, sizeof(seg->iv)); | |
342 | AV_WB32(seg->iv + 12, seq); | |
343 | } | |
344 | ff_make_absolute_url(seg->key, sizeof(seg->key), url, key); | |
f1f60f52 | 345 | ff_make_absolute_url(seg->url, sizeof(seg->url), url, line); |
cd223e0b MS |
346 | dynarray_add(&var->segments, &var->n_segments, seg); |
347 | is_segment = 0; | |
348 | } | |
349 | } | |
350 | } | |
6cc7f139 | 351 | if (var) |
6df9d9b5 | 352 | var->last_load_time = av_gettime_relative(); |
cd223e0b MS |
353 | |
354 | fail: | |
8c929098 | 355 | av_free(new_url); |
cd223e0b | 356 | if (close_in) |
9f61abc8 | 357 | ff_format_io_close(c->ctx, &in); |
cd223e0b MS |
358 | return ret; |
359 | } | |
360 | ||
84465f21 MS |
361 | static int open_input(struct variant *var) |
362 | { | |
81306fd4 | 363 | HLSContext *c = var->parent->priv_data; |
84465f21 MS |
364 | struct segment *seg = var->segments[var->cur_seq_no - var->start_seq_no]; |
365 | if (seg->key_type == KEY_NONE) { | |
81306fd4 | 366 | return open_url(var->parent, &var->input, seg->url, c->avio_opts); |
84465f21 | 367 | } else if (seg->key_type == KEY_AES_128) { |
81306fd4 | 368 | AVDictionary *opts = NULL; |
84465f21 MS |
369 | char iv[33], key[33], url[MAX_URL_SIZE]; |
370 | int ret; | |
371 | if (strcmp(seg->key, var->key_url)) { | |
81306fd4 AK |
372 | AVIOContext *pb; |
373 | if (open_url(var->parent, &pb, seg->key, c->avio_opts) == 0) { | |
374 | ret = avio_read(pb, var->key, sizeof(var->key)); | |
375 | if (ret != sizeof(var->key)) { | |
84465f21 MS |
376 | av_log(NULL, AV_LOG_ERROR, "Unable to read key file %s\n", |
377 | seg->key); | |
378 | } | |
81306fd4 | 379 | ff_format_io_close(var->parent, &pb); |
84465f21 MS |
380 | } else { |
381 | av_log(NULL, AV_LOG_ERROR, "Unable to open key file %s\n", | |
382 | seg->key); | |
383 | } | |
384 | av_strlcpy(var->key_url, seg->key, sizeof(var->key_url)); | |
385 | } | |
386 | ff_data_to_hex(iv, seg->iv, sizeof(seg->iv), 0); | |
387 | ff_data_to_hex(key, var->key, sizeof(var->key), 0); | |
388 | iv[32] = key[32] = '\0'; | |
389 | if (strstr(seg->url, "://")) | |
390 | snprintf(url, sizeof(url), "crypto+%s", seg->url); | |
391 | else | |
392 | snprintf(url, sizeof(url), "crypto:%s", seg->url); | |
0c73a5a5 | 393 | |
81306fd4 AK |
394 | av_dict_copy(&opts, c->avio_opts, 0); |
395 | av_dict_set(&opts, "key", key, 0); | |
396 | av_dict_set(&opts, "iv", iv, 0); | |
397 | ||
398 | ret = open_url(var->parent, &var->input, url, opts); | |
399 | av_dict_free(&opts); | |
400 | return ret; | |
84465f21 MS |
401 | } |
402 | return AVERROR(ENOSYS); | |
403 | } | |
404 | ||
6cc7f139 MS |
405 | static int read_data(void *opaque, uint8_t *buf, int buf_size) |
406 | { | |
407 | struct variant *v = opaque; | |
65cd7bf3 | 408 | HLSContext *c = v->parent->priv_data; |
6cc7f139 MS |
409 | int ret, i; |
410 | ||
411 | restart: | |
412 | if (!v->input) { | |
356ae5f6 | 413 | /* If this is a live stream and the reload interval has elapsed since |
6cc7f139 | 414 | * the last playlist reload, reload the variant playlists now. */ |
356ae5f6 AU |
415 | int64_t reload_interval = v->n_segments > 0 ? |
416 | v->segments[v->n_segments - 1]->duration : | |
417 | v->target_duration; | |
356ae5f6 | 418 | |
617475a9 | 419 | reload: |
6cc7f139 | 420 | if (!v->finished && |
6df9d9b5 | 421 | av_gettime_relative() - v->last_load_time >= reload_interval) { |
617475a9 | 422 | if ((ret = parse_playlist(c, v->url, v, NULL)) < 0) |
6cc7f139 | 423 | return ret; |
617475a9 MS |
424 | /* If we need to reload the playlist again below (if |
425 | * there's still no more segments), switch to a reload | |
426 | * interval of half the target duration. */ | |
c4419103 | 427 | reload_interval = v->target_duration / 2; |
617475a9 | 428 | } |
6cc7f139 MS |
429 | if (v->cur_seq_no < v->start_seq_no) { |
430 | av_log(NULL, AV_LOG_WARNING, | |
431 | "skipping %d segments ahead, expired from playlists\n", | |
432 | v->start_seq_no - v->cur_seq_no); | |
433 | v->cur_seq_no = v->start_seq_no; | |
434 | } | |
435 | if (v->cur_seq_no >= v->start_seq_no + v->n_segments) { | |
436 | if (v->finished) | |
437 | return AVERROR_EOF; | |
6df9d9b5 | 438 | while (av_gettime_relative() - v->last_load_time < reload_interval) { |
9957cdbf | 439 | if (ff_check_interrupt(c->interrupt_callback)) |
6cc7f139 | 440 | return AVERROR_EXIT; |
896bb0d7 | 441 | av_usleep(100*1000); |
6cc7f139 MS |
442 | } |
443 | /* Enough time has elapsed since the last reload */ | |
444 | goto reload; | |
445 | } | |
446 | ||
84465f21 | 447 | ret = open_input(v); |
6cc7f139 MS |
448 | if (ret < 0) |
449 | return ret; | |
450 | } | |
81306fd4 | 451 | ret = avio_read(v->input, buf, buf_size); |
6cc7f139 MS |
452 | if (ret > 0) |
453 | return ret; | |
81306fd4 | 454 | ff_format_io_close(c->ctx, &v->input); |
6cc7f139 MS |
455 | v->cur_seq_no++; |
456 | ||
457 | c->end_of_segment = 1; | |
458 | c->cur_seq_no = v->cur_seq_no; | |
459 | ||
cdd2d73d MN |
460 | if (v->ctx && v->ctx->nb_streams && |
461 | v->parent->nb_streams >= v->stream_offset + v->ctx->nb_streams) { | |
a92a7ddc MS |
462 | v->needed = 0; |
463 | for (i = v->stream_offset; i < v->stream_offset + v->ctx->nb_streams; | |
464 | i++) { | |
465 | if (v->parent->streams[i]->discard < AVDISCARD_ALL) | |
466 | v->needed = 1; | |
467 | } | |
6cc7f139 MS |
468 | } |
469 | if (!v->needed) { | |
470 | av_log(v->parent, AV_LOG_INFO, "No longer receiving variant %d\n", | |
471 | v->index); | |
472 | return AVERROR_EOF; | |
473 | } | |
474 | goto restart; | |
475 | } | |
476 | ||
0c73a5a5 LB |
477 | static int save_avio_options(AVFormatContext *s) |
478 | { | |
479 | HLSContext *c = s->priv_data; | |
480 | const char *opts[] = { "headers", "user_agent", NULL }, **opt = opts; | |
481 | uint8_t *buf; | |
482 | int ret = 0; | |
483 | ||
484 | while (*opt) { | |
485 | if (av_opt_get(s->pb, *opt, AV_OPT_SEARCH_CHILDREN, &buf) >= 0) { | |
486 | ret = av_dict_set(&c->avio_opts, *opt, buf, | |
487 | AV_DICT_DONT_STRDUP_VAL); | |
488 | if (ret < 0) | |
489 | return ret; | |
490 | } | |
491 | opt++; | |
492 | } | |
493 | ||
494 | return ret; | |
495 | } | |
496 | ||
65cd7bf3 | 497 | static int hls_read_header(AVFormatContext *s) |
cd223e0b | 498 | { |
65cd7bf3 | 499 | HLSContext *c = s->priv_data; |
cd223e0b MS |
500 | int ret = 0, i, j, stream_offset = 0; |
501 | ||
9f61abc8 | 502 | c->ctx = s; |
9957cdbf MS |
503 | c->interrupt_callback = &s->interrupt_callback; |
504 | ||
cd223e0b MS |
505 | if ((ret = parse_playlist(c, s->filename, NULL, s->pb)) < 0) |
506 | goto fail; | |
507 | ||
0c73a5a5 LB |
508 | if ((ret = save_avio_options(s)) < 0) |
509 | goto fail; | |
510 | ||
cd223e0b MS |
511 | if (c->n_variants == 0) { |
512 | av_log(NULL, AV_LOG_WARNING, "Empty playlist\n"); | |
513 | ret = AVERROR_EOF; | |
514 | goto fail; | |
515 | } | |
516 | /* If the playlist only contained variants, parse each individual | |
517 | * variant playlist. */ | |
518 | if (c->n_variants > 1 || c->variants[0]->n_segments == 0) { | |
519 | for (i = 0; i < c->n_variants; i++) { | |
520 | struct variant *v = c->variants[i]; | |
521 | if ((ret = parse_playlist(c, v->url, v, NULL)) < 0) | |
522 | goto fail; | |
523 | } | |
524 | } | |
525 | ||
526 | if (c->variants[0]->n_segments == 0) { | |
527 | av_log(NULL, AV_LOG_WARNING, "Empty playlist\n"); | |
528 | ret = AVERROR_EOF; | |
529 | goto fail; | |
530 | } | |
531 | ||
532 | /* If this isn't a live stream, calculate the total duration of the | |
533 | * stream. */ | |
d3964da2 | 534 | if (c->variants[0]->finished) { |
b79c3df0 | 535 | int64_t duration = 0; |
cd223e0b MS |
536 | for (i = 0; i < c->variants[0]->n_segments; i++) |
537 | duration += c->variants[0]->segments[i]->duration; | |
c4419103 | 538 | s->duration = duration; |
cd223e0b MS |
539 | } |
540 | ||
cd223e0b MS |
541 | /* Open the demuxer for each variant */ |
542 | for (i = 0; i < c->n_variants; i++) { | |
543 | struct variant *v = c->variants[i]; | |
6cc7f139 | 544 | AVInputFormat *in_fmt = NULL; |
fe8e0394 | 545 | char bitrate_str[20]; |
c110cbf6 L |
546 | AVProgram *program; |
547 | ||
cd223e0b MS |
548 | if (v->n_segments == 0) |
549 | continue; | |
6cc7f139 | 550 | |
603b8bc2 AK |
551 | if (!(v->ctx = avformat_alloc_context())) { |
552 | ret = AVERROR(ENOMEM); | |
553 | goto fail; | |
554 | } | |
555 | ||
6cc7f139 MS |
556 | v->index = i; |
557 | v->needed = 1; | |
558 | v->parent = s; | |
559 | ||
560 | /* If this is a live stream with more than 3 segments, start at the | |
561 | * third last segment. */ | |
562 | v->cur_seq_no = v->start_seq_no; | |
563 | if (!v->finished && v->n_segments > 3) | |
564 | v->cur_seq_no = v->start_seq_no + v->n_segments - 3; | |
565 | ||
566 | v->read_buffer = av_malloc(INITIAL_BUFFER_SIZE); | |
567 | ffio_init_context(&v->pb, v->read_buffer, INITIAL_BUFFER_SIZE, 0, v, | |
568 | read_data, NULL, NULL); | |
569 | v->pb.seekable = 0; | |
570 | ret = av_probe_input_buffer(&v->pb, &in_fmt, v->segments[0]->url, | |
571 | NULL, 0, 0); | |
115a5730 MS |
572 | if (ret < 0) { |
573 | /* Free the ctx - it isn't initialized properly at this point, | |
574 | * so avformat_close_input shouldn't be called. If | |
575 | * avformat_open_input fails below, it frees and zeros the | |
576 | * context, so it doesn't need any special treatment like this. */ | |
577 | avformat_free_context(v->ctx); | |
578 | v->ctx = NULL; | |
6cc7f139 | 579 | goto fail; |
115a5730 | 580 | } |
603b8bc2 | 581 | v->ctx->pb = &v->pb; |
c11e33a3 | 582 | v->stream_offset = stream_offset; |
603b8bc2 | 583 | ret = avformat_open_input(&v->ctx, v->segments[0]->url, in_fmt, NULL); |
cd223e0b MS |
584 | if (ret < 0) |
585 | goto fail; | |
9696740a MN |
586 | |
587 | v->ctx->ctx_flags &= ~AVFMTCTX_NOHEADER; | |
588 | ret = avformat_find_stream_info(v->ctx, NULL); | |
589 | if (ret < 0) | |
590 | goto fail; | |
fe8e0394 | 591 | snprintf(bitrate_str, sizeof(bitrate_str), "%d", v->bandwidth); |
c110cbf6 L |
592 | |
593 | program = av_new_program(s, i); | |
594 | if (!program) | |
595 | goto fail; | |
596 | av_dict_set(&program->metadata, "variant_bitrate", bitrate_str, 0); | |
597 | ||
cd223e0b MS |
598 | /* Create new AVStreams for each stream in this variant */ |
599 | for (j = 0; j < v->ctx->nb_streams; j++) { | |
84ad31ff | 600 | AVStream *st = avformat_new_stream(s, NULL); |
82bf8c87 | 601 | AVStream *ist = v->ctx->streams[j]; |
cd223e0b MS |
602 | if (!st) { |
603 | ret = AVERROR(ENOMEM); | |
604 | goto fail; | |
605 | } | |
c110cbf6 | 606 | ff_program_add_stream_index(s, i, stream_offset + j); |
84ad31ff | 607 | st->id = i; |
82bf8c87 | 608 | avpriv_set_pts_info(st, ist->pts_wrap_bits, ist->time_base.num, ist->time_base.den); |
cd223e0b | 609 | avcodec_copy_context(st->codec, v->ctx->streams[j]->codec); |
5f85d49b | 610 | if (v->bandwidth) |
d2d67e42 | 611 | av_dict_set(&st->metadata, "variant_bitrate", bitrate_str, |
5f85d49b | 612 | 0); |
cd223e0b MS |
613 | } |
614 | stream_offset += v->ctx->nb_streams; | |
615 | } | |
cd223e0b | 616 | |
6cc7f139 | 617 | c->first_packet = 1; |
795d9594 | 618 | c->first_timestamp = AV_NOPTS_VALUE; |
2b3d041c | 619 | c->seek_timestamp = AV_NOPTS_VALUE; |
cd223e0b MS |
620 | |
621 | return 0; | |
622 | fail: | |
623 | free_variant_list(c); | |
624 | return ret; | |
625 | } | |
626 | ||
6cc7f139 | 627 | static int recheck_discard_flags(AVFormatContext *s, int first) |
cd223e0b | 628 | { |
65cd7bf3 | 629 | HLSContext *c = s->priv_data; |
6cc7f139 | 630 | int i, changed = 0; |
cd223e0b | 631 | |
6cc7f139 MS |
632 | /* Check if any new streams are needed */ |
633 | for (i = 0; i < c->n_variants; i++) | |
634 | c->variants[i]->cur_needed = 0;; | |
635 | ||
636 | for (i = 0; i < s->nb_streams; i++) { | |
637 | AVStream *st = s->streams[i]; | |
638 | struct variant *var = c->variants[s->streams[i]->id]; | |
639 | if (st->discard < AVDISCARD_ALL) | |
640 | var->cur_needed = 1; | |
cd223e0b | 641 | } |
6cc7f139 MS |
642 | for (i = 0; i < c->n_variants; i++) { |
643 | struct variant *v = c->variants[i]; | |
644 | if (v->cur_needed && !v->needed) { | |
645 | v->needed = 1; | |
646 | changed = 1; | |
647 | v->cur_seq_no = c->cur_seq_no; | |
648 | v->pb.eof_reached = 0; | |
649 | av_log(s, AV_LOG_INFO, "Now receiving variant %d\n", i); | |
650 | } else if (first && !v->cur_needed && v->needed) { | |
651 | if (v->input) | |
81306fd4 | 652 | ff_format_io_close(s, &v->input); |
6cc7f139 MS |
653 | v->needed = 0; |
654 | changed = 1; | |
655 | av_log(s, AV_LOG_INFO, "No longer receiving variant %d\n", i); | |
cd223e0b MS |
656 | } |
657 | } | |
6cc7f139 | 658 | return changed; |
cd223e0b MS |
659 | } |
660 | ||
65cd7bf3 | 661 | static int hls_read_packet(AVFormatContext *s, AVPacket *pkt) |
cd223e0b | 662 | { |
65cd7bf3 | 663 | HLSContext *c = s->priv_data; |
6cc7f139 | 664 | int ret, i, minvariant = -1; |
cd223e0b | 665 | |
6cc7f139 MS |
666 | if (c->first_packet) { |
667 | recheck_discard_flags(s, 1); | |
668 | c->first_packet = 0; | |
cd223e0b | 669 | } |
6cc7f139 | 670 | |
cd223e0b | 671 | start: |
6cc7f139 | 672 | c->end_of_segment = 0; |
cd223e0b MS |
673 | for (i = 0; i < c->n_variants; i++) { |
674 | struct variant *var = c->variants[i]; | |
cd223e0b MS |
675 | /* Make sure we've got one buffered packet from each open variant |
676 | * stream */ | |
6cc7f139 | 677 | if (var->needed && !var->pkt.data) { |
2b3d041c PI |
678 | while (1) { |
679 | int64_t ts_diff; | |
680 | AVStream *st; | |
681 | ret = av_read_frame(var->ctx, &var->pkt); | |
682 | if (ret < 0) { | |
683 | if (!var->pb.eof_reached) | |
684 | return ret; | |
685 | reset_packet(&var->pkt); | |
686 | break; | |
687 | } else { | |
e1d5b244 MS |
688 | if (c->first_timestamp == AV_NOPTS_VALUE && |
689 | var->pkt.dts != AV_NOPTS_VALUE) | |
690 | c->first_timestamp = av_rescale_q(var->pkt.dts, | |
691 | var->ctx->streams[var->pkt.stream_index]->time_base, | |
692 | AV_TIME_BASE_Q); | |
2b3d041c PI |
693 | } |
694 | ||
695 | if (c->seek_timestamp == AV_NOPTS_VALUE) | |
696 | break; | |
697 | ||
698 | if (var->pkt.dts == AV_NOPTS_VALUE) { | |
699 | c->seek_timestamp = AV_NOPTS_VALUE; | |
700 | break; | |
701 | } | |
702 | ||
703 | st = var->ctx->streams[var->pkt.stream_index]; | |
704 | ts_diff = av_rescale_rnd(var->pkt.dts, AV_TIME_BASE, | |
705 | st->time_base.den, AV_ROUND_DOWN) - | |
706 | c->seek_timestamp; | |
707 | if (ts_diff >= 0 && (c->seek_flags & AVSEEK_FLAG_ANY || | |
708 | var->pkt.flags & AV_PKT_FLAG_KEY)) { | |
709 | c->seek_timestamp = AV_NOPTS_VALUE; | |
710 | break; | |
711 | } | |
ce70f28a | 712 | av_packet_unref(&var->pkt); |
06205b5e | 713 | reset_packet(&var->pkt); |
cd223e0b MS |
714 | } |
715 | } | |
eb33ba04 MS |
716 | /* Check if this stream still is on an earlier segment number, or |
717 | * has the packet with the lowest dts */ | |
cd223e0b | 718 | if (var->pkt.data) { |
56c23370 MS |
719 | struct variant *minvar = minvariant < 0 ? |
720 | NULL : c->variants[minvariant]; | |
9d64f236 | 721 | if (minvariant < 0 || var->cur_seq_no < minvar->cur_seq_no) { |
cd223e0b | 722 | minvariant = i; |
9d64f236 MN |
723 | } else if (var->cur_seq_no == minvar->cur_seq_no) { |
724 | int64_t dts = var->pkt.dts; | |
725 | int64_t mindts = minvar->pkt.dts; | |
726 | AVStream *st = var->ctx->streams[var->pkt.stream_index]; | |
727 | AVStream *minst = minvar->ctx->streams[minvar->pkt.stream_index]; | |
728 | ||
729 | if (dts == AV_NOPTS_VALUE) { | |
730 | minvariant = i; | |
731 | } else if (mindts != AV_NOPTS_VALUE) { | |
732 | if (st->start_time != AV_NOPTS_VALUE) | |
733 | dts -= st->start_time; | |
734 | if (minst->start_time != AV_NOPTS_VALUE) | |
735 | mindts -= minst->start_time; | |
736 | ||
737 | if (av_compare_ts(dts, st->time_base, | |
738 | mindts, minst->time_base) < 0) | |
739 | minvariant = i; | |
740 | } | |
741 | } | |
cd223e0b MS |
742 | } |
743 | } | |
6cc7f139 MS |
744 | if (c->end_of_segment) { |
745 | if (recheck_discard_flags(s, 0)) | |
746 | goto start; | |
747 | } | |
cd223e0b MS |
748 | /* If we got a packet, return it */ |
749 | if (minvariant >= 0) { | |
750 | *pkt = c->variants[minvariant]->pkt; | |
751 | pkt->stream_index += c->variants[minvariant]->stream_offset; | |
752 | reset_packet(&c->variants[minvariant]->pkt); | |
cd223e0b MS |
753 | return 0; |
754 | } | |
6cc7f139 | 755 | return AVERROR_EOF; |
cd223e0b MS |
756 | } |
757 | ||
65cd7bf3 | 758 | static int hls_close(AVFormatContext *s) |
cd223e0b | 759 | { |
65cd7bf3 | 760 | HLSContext *c = s->priv_data; |
cd223e0b MS |
761 | |
762 | free_variant_list(c); | |
0c73a5a5 LB |
763 | |
764 | av_dict_free(&c->avio_opts); | |
765 | ||
cd223e0b MS |
766 | return 0; |
767 | } | |
768 | ||
65cd7bf3 | 769 | static int hls_read_seek(AVFormatContext *s, int stream_index, |
cd223e0b MS |
770 | int64_t timestamp, int flags) |
771 | { | |
65cd7bf3 | 772 | HLSContext *c = s->priv_data; |
6cc7f139 | 773 | int i, j, ret; |
cd223e0b | 774 | |
d3964da2 | 775 | if ((flags & AVSEEK_FLAG_BYTE) || !c->variants[0]->finished) |
cd223e0b MS |
776 | return AVERROR(ENOSYS); |
777 | ||
2b3d041c PI |
778 | c->seek_flags = flags; |
779 | c->seek_timestamp = stream_index < 0 ? timestamp : | |
780 | av_rescale_rnd(timestamp, AV_TIME_BASE, | |
781 | s->streams[stream_index]->time_base.den, | |
782 | flags & AVSEEK_FLAG_BACKWARD ? | |
783 | AV_ROUND_DOWN : AV_ROUND_UP); | |
c4419103 | 784 | timestamp = av_rescale_rnd(timestamp, AV_TIME_BASE, stream_index >= 0 ? |
0d8a33b1 MS |
785 | s->streams[stream_index]->time_base.den : |
786 | AV_TIME_BASE, flags & AVSEEK_FLAG_BACKWARD ? | |
787 | AV_ROUND_DOWN : AV_ROUND_UP); | |
2b3d041c PI |
788 | if (s->duration < c->seek_timestamp) { |
789 | c->seek_timestamp = AV_NOPTS_VALUE; | |
790 | return AVERROR(EIO); | |
791 | } | |
792 | ||
0d8a33b1 | 793 | ret = AVERROR(EIO); |
cd223e0b | 794 | for (i = 0; i < c->n_variants; i++) { |
0d8a33b1 | 795 | /* Reset reading */ |
cd223e0b | 796 | struct variant *var = c->variants[i]; |
c4419103 MS |
797 | int64_t pos = c->first_timestamp == AV_NOPTS_VALUE ? |
798 | 0 : c->first_timestamp; | |
81306fd4 AK |
799 | if (var->input) |
800 | ff_format_io_close(s, &var->input); | |
ce70f28a | 801 | av_packet_unref(&var->pkt); |
cd223e0b | 802 | reset_packet(&var->pkt); |
6cc7f139 | 803 | var->pb.eof_reached = 0; |
a4f97be1 MS |
804 | /* Clear any buffered data */ |
805 | var->pb.buf_end = var->pb.buf_ptr = var->pb.buffer; | |
806 | /* Reset the pos, to let the mpegts demuxer know we've seeked. */ | |
807 | var->pb.pos = 0; | |
cd223e0b | 808 | |
6cc7f139 MS |
809 | /* Locate the segment that contains the target timestamp */ |
810 | for (j = 0; j < var->n_segments; j++) { | |
811 | if (timestamp >= pos && | |
812 | timestamp < pos + var->segments[j]->duration) { | |
813 | var->cur_seq_no = var->start_seq_no + j; | |
814 | ret = 0; | |
815 | break; | |
816 | } | |
817 | pos += var->segments[j]->duration; | |
cd223e0b | 818 | } |
2b3d041c PI |
819 | if (ret) |
820 | c->seek_timestamp = AV_NOPTS_VALUE; | |
cd223e0b | 821 | } |
6cc7f139 | 822 | return ret; |
cd223e0b MS |
823 | } |
824 | ||
65cd7bf3 | 825 | static int hls_probe(AVProbeData *p) |
cd223e0b MS |
826 | { |
827 | /* Require #EXTM3U at the start, and either one of the ones below | |
828 | * somewhere for a proper match. */ | |
829 | if (strncmp(p->buf, "#EXTM3U", 7)) | |
830 | return 0; | |
831 | if (strstr(p->buf, "#EXT-X-STREAM-INF:") || | |
832 | strstr(p->buf, "#EXT-X-TARGETDURATION:") || | |
833 | strstr(p->buf, "#EXT-X-MEDIA-SEQUENCE:")) | |
834 | return AVPROBE_SCORE_MAX; | |
835 | return 0; | |
836 | } | |
837 | ||
2772258a | 838 | AVInputFormat ff_hls_demuxer = { |
c1df37e5 | 839 | .name = "hls,applehttp", |
6774247a | 840 | .long_name = NULL_IF_CONFIG_SMALL("Apple HTTP Live Streaming"), |
65cd7bf3 MS |
841 | .priv_data_size = sizeof(HLSContext), |
842 | .read_probe = hls_probe, | |
843 | .read_header = hls_read_header, | |
844 | .read_packet = hls_read_packet, | |
845 | .read_close = hls_close, | |
846 | .read_seek = hls_read_seek, | |
cd223e0b | 847 | }; |