2 * Apple HTTP Live Streaming demuxer
3 * Copyright (c) 2010 Martin Storsjo
4 * Copyright (c) 2013 Anssi Hannula
6 * This file is part of FFmpeg.
8 * FFmpeg is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * FFmpeg is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with FFmpeg; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 * Apple HTTP Live Streaming demuxer
26 * http://tools.ietf.org/html/draft-pantos-http-live-streaming
29 #include "libavutil/avstring.h"
30 #include "libavutil/avassert.h"
31 #include "libavutil/intreadwrite.h"
32 #include "libavutil/mathematics.h"
33 #include "libavutil/opt.h"
34 #include "libavutil/dict.h"
35 #include "libavutil/time.h"
38 #include "avio_internal.h"
41 #define INITIAL_BUFFER_SIZE 32768
43 #define MAX_FIELD_LEN 64
44 #define MAX_CHARACTERISTICS_LEN 512
46 #define MPEG_TIME_BASE 90000
47 #define MPEG_TIME_BASE_Q (AVRational){1, MPEG_TIME_BASE}
50 * An apple http stream consists of a playlist with media segment files,
51 * played sequentially. There may be several playlists with the same
52 * video content, in different bandwidth variants, that are played in
53 * parallel (preferably only one bandwidth variant at a time). In this case,
54 * the user supplied the url to a main playlist that only lists the variant
57 * If the main playlist doesn't point at any variants, we still create
58 * one anonymous toplevel variant for this, to maintain the structure.
73 enum KeyType key_type
;
75 /* associated Media Initialization Section, treated as a segment */
76 struct segment
*init_section
;
88 * Each playlist has its own demuxer. If it currently is active,
89 * it has an open AVIOContext too, and potentially an AVPacket
90 * containing the next packet from this stream.
93 char url
[MAX_URL_SIZE
];
97 AVFormatContext
*parent
;
101 int has_noheader_flag
;
103 /* main demuxer streams associated with this playlist
104 * indexed by the subdemuxer stream indexes */
105 AVStream
**main_streams
;
109 enum PlaylistType type
;
110 int64_t target_duration
;
113 struct segment
**segments
;
114 int needed
, cur_needed
;
116 int64_t cur_seg_offset
;
117 int64_t last_load_time
;
119 /* Currently active Media Initialization Section */
120 struct segment
*cur_init_section
;
121 uint8_t *init_sec_buf
;
122 unsigned int init_sec_buf_size
;
123 unsigned int init_sec_data_len
;
124 unsigned int init_sec_buf_read_offset
;
126 char key_url
[MAX_URL_SIZE
];
129 /* ID3 timestamp handling (elementary audio streams have ID3 timestamps
130 * (and possibly other ID3 tags) in the beginning of each segment) */
131 int is_id3_timestamped
; /* -1: not yet known */
132 int64_t id3_mpegts_timestamp
; /* in mpegts tb */
133 int64_t id3_offset
; /* in stream original tb */
134 uint8_t* id3_buf
; /* temp buffer for id3 parsing */
135 unsigned int id3_buf_size
;
136 AVDictionary
*id3_initial
; /* data from first id3 tag */
137 int id3_found
; /* ID3 tag found at some point */
138 int id3_changed
; /* ID3 tag data has changed at some point */
139 ID3v2ExtraMeta
*id3_deferred_extra
; /* stored here until subdemuxer is opened */
141 int64_t seek_timestamp
;
143 int seek_stream_index
; /* into subdemuxer stream array */
145 /* Renditions associated with this playlist, if any.
146 * Alternative rendition playlists have a single rendition associated
147 * with them, and variant main Media Playlists may have
148 * multiple (playlist-less) renditions associated with them. */
150 struct rendition
**renditions
;
152 /* Media Initialization Sections (EXT-X-MAP) associated with this
153 * playlist, if any. */
155 struct segment
**init_sections
;
159 * Renditions are e.g. alternative subtitle or audio streams.
160 * The rendition may either be an external playlist or it may be
161 * contained in the main Media Playlist of the variant (in which case
165 enum AVMediaType type
;
166 struct playlist
*playlist
;
167 char group_id
[MAX_FIELD_LEN
];
168 char language
[MAX_FIELD_LEN
];
169 char name
[MAX_FIELD_LEN
];
176 /* every variant contains at least the main Media Playlist in index 0 */
178 struct playlist
**playlists
;
180 char audio_group
[MAX_FIELD_LEN
];
181 char video_group
[MAX_FIELD_LEN
];
182 char subtitles_group
[MAX_FIELD_LEN
];
185 typedef struct HLSContext
{
187 AVFormatContext
*ctx
;
189 struct variant
**variants
;
191 struct playlist
**playlists
;
193 struct rendition
**renditions
;
196 int live_start_index
;
198 int64_t first_timestamp
;
199 int64_t cur_timestamp
;
200 AVIOInterruptCB
*interrupt_callback
;
201 char *user_agent
; ///< holds HTTP user agent set as an AVOption to the HTTP protocol context
202 char *cookies
; ///< holds HTTP cookie values set in either the initial response or as an AVOption to the HTTP protocol context
203 char *headers
; ///< holds HTTP headers set as an AVOption to the HTTP protocol context
204 char *http_proxy
; ///< holds the address of the HTTP proxy server
205 AVDictionary
*avio_opts
;
206 int strict_std_compliance
;
207 char *allowed_extensions
;
211 static int read_chomp_line(AVIOContext
*s
, char *buf
, int maxlen
)
213 int len
= ff_get_line(s
, buf
, maxlen
);
214 while (len
> 0 && av_isspace(buf
[len
- 1]))
219 static void free_segment_list(struct playlist
*pls
)
222 for (i
= 0; i
< pls
->n_segments
; i
++) {
223 av_freep(&pls
->segments
[i
]->key
);
224 av_freep(&pls
->segments
[i
]->url
);
225 av_freep(&pls
->segments
[i
]);
227 av_freep(&pls
->segments
);
231 static void free_init_section_list(struct playlist
*pls
)
234 for (i
= 0; i
< pls
->n_init_sections
; i
++) {
235 av_freep(&pls
->init_sections
[i
]->key
);
236 av_freep(&pls
->init_sections
[i
]->url
);
237 av_freep(&pls
->init_sections
[i
]);
239 av_freep(&pls
->init_sections
);
240 pls
->n_init_sections
= 0;
243 static void free_playlist_list(HLSContext
*c
)
246 for (i
= 0; i
< c
->n_playlists
; i
++) {
247 struct playlist
*pls
= c
->playlists
[i
];
248 free_segment_list(pls
);
249 free_init_section_list(pls
);
250 av_freep(&pls
->main_streams
);
251 av_freep(&pls
->renditions
);
252 av_freep(&pls
->id3_buf
);
253 av_dict_free(&pls
->id3_initial
);
254 ff_id3v2_free_extra_meta(&pls
->id3_deferred_extra
);
255 av_freep(&pls
->init_sec_buf
);
256 av_packet_unref(&pls
->pkt
);
257 av_freep(&pls
->pb
.buffer
);
259 ff_format_io_close(c
->ctx
, &pls
->input
);
262 avformat_close_input(&pls
->ctx
);
266 av_freep(&c
->playlists
);
267 av_freep(&c
->cookies
);
268 av_freep(&c
->user_agent
);
269 av_freep(&c
->headers
);
270 av_freep(&c
->http_proxy
);
274 static void free_variant_list(HLSContext
*c
)
277 for (i
= 0; i
< c
->n_variants
; i
++) {
278 struct variant
*var
= c
->variants
[i
];
279 av_freep(&var
->playlists
);
282 av_freep(&c
->variants
);
286 static void free_rendition_list(HLSContext
*c
)
289 for (i
= 0; i
< c
->n_renditions
; i
++)
290 av_freep(&c
->renditions
[i
]);
291 av_freep(&c
->renditions
);
296 * Used to reset a statically allocated AVPacket to a clean slate,
297 * containing no data.
299 static void reset_packet(AVPacket
*pkt
)
305 static struct playlist
*new_playlist(HLSContext
*c
, const char *url
,
308 struct playlist
*pls
= av_mallocz(sizeof(struct playlist
));
311 reset_packet(&pls
->pkt
);
312 ff_make_absolute_url(pls
->url
, sizeof(pls
->url
), base
, url
);
313 pls
->seek_timestamp
= AV_NOPTS_VALUE
;
315 pls
->is_id3_timestamped
= -1;
316 pls
->id3_mpegts_timestamp
= AV_NOPTS_VALUE
;
318 dynarray_add(&c
->playlists
, &c
->n_playlists
, pls
);
322 struct variant_info
{
324 /* variant group ids: */
325 char audio
[MAX_FIELD_LEN
];
326 char video
[MAX_FIELD_LEN
];
327 char subtitles
[MAX_FIELD_LEN
];
330 static struct variant
*new_variant(HLSContext
*c
, struct variant_info
*info
,
331 const char *url
, const char *base
)
334 struct playlist
*pls
;
336 pls
= new_playlist(c
, url
, base
);
340 var
= av_mallocz(sizeof(struct variant
));
345 var
->bandwidth
= atoi(info
->bandwidth
);
346 strcpy(var
->audio_group
, info
->audio
);
347 strcpy(var
->video_group
, info
->video
);
348 strcpy(var
->subtitles_group
, info
->subtitles
);
351 dynarray_add(&c
->variants
, &c
->n_variants
, var
);
352 dynarray_add(&var
->playlists
, &var
->n_playlists
, pls
);
356 static void handle_variant_args(struct variant_info
*info
, const char *key
,
357 int key_len
, char **dest
, int *dest_len
)
359 if (!strncmp(key
, "BANDWIDTH=", key_len
)) {
360 *dest
= info
->bandwidth
;
361 *dest_len
= sizeof(info
->bandwidth
);
362 } else if (!strncmp(key
, "AUDIO=", key_len
)) {
364 *dest_len
= sizeof(info
->audio
);
365 } else if (!strncmp(key
, "VIDEO=", key_len
)) {
367 *dest_len
= sizeof(info
->video
);
368 } else if (!strncmp(key
, "SUBTITLES=", key_len
)) {
369 *dest
= info
->subtitles
;
370 *dest_len
= sizeof(info
->subtitles
);
375 char uri
[MAX_URL_SIZE
];
380 static void handle_key_args(struct key_info
*info
, const char *key
,
381 int key_len
, char **dest
, int *dest_len
)
383 if (!strncmp(key
, "METHOD=", key_len
)) {
384 *dest
= info
->method
;
385 *dest_len
= sizeof(info
->method
);
386 } else if (!strncmp(key
, "URI=", key_len
)) {
388 *dest_len
= sizeof(info
->uri
);
389 } else if (!strncmp(key
, "IV=", key_len
)) {
391 *dest_len
= sizeof(info
->iv
);
395 struct init_section_info
{
396 char uri
[MAX_URL_SIZE
];
400 static struct segment
*new_init_section(struct playlist
*pls
,
401 struct init_section_info
*info
,
402 const char *url_base
)
406 char tmp_str
[MAX_URL_SIZE
];
411 sec
= av_mallocz(sizeof(*sec
));
415 ff_make_absolute_url(tmp_str
, sizeof(tmp_str
), url_base
, info
->uri
);
416 sec
->url
= av_strdup(tmp_str
);
422 if (info
->byterange
[0]) {
423 sec
->size
= strtoll(info
->byterange
, NULL
, 10);
424 ptr
= strchr(info
->byterange
, '@');
426 sec
->url_offset
= strtoll(ptr
+1, NULL
, 10);
428 /* the entire file is the init section */
432 dynarray_add(&pls
->init_sections
, &pls
->n_init_sections
, sec
);
437 static void handle_init_section_args(struct init_section_info
*info
, const char *key
,
438 int key_len
, char **dest
, int *dest_len
)
440 if (!strncmp(key
, "URI=", key_len
)) {
442 *dest_len
= sizeof(info
->uri
);
443 } else if (!strncmp(key
, "BYTERANGE=", key_len
)) {
444 *dest
= info
->byterange
;
445 *dest_len
= sizeof(info
->byterange
);
449 struct rendition_info
{
451 char uri
[MAX_URL_SIZE
];
452 char group_id
[MAX_FIELD_LEN
];
453 char language
[MAX_FIELD_LEN
];
454 char assoc_language
[MAX_FIELD_LEN
];
455 char name
[MAX_FIELD_LEN
];
458 char characteristics
[MAX_CHARACTERISTICS_LEN
];
461 static struct rendition
*new_rendition(HLSContext
*c
, struct rendition_info
*info
,
462 const char *url_base
)
464 struct rendition
*rend
;
465 enum AVMediaType type
= AVMEDIA_TYPE_UNKNOWN
;
466 char *characteristic
;
470 if (!strcmp(info
->type
, "AUDIO"))
471 type
= AVMEDIA_TYPE_AUDIO
;
472 else if (!strcmp(info
->type
, "VIDEO"))
473 type
= AVMEDIA_TYPE_VIDEO
;
474 else if (!strcmp(info
->type
, "SUBTITLES"))
475 type
= AVMEDIA_TYPE_SUBTITLE
;
476 else if (!strcmp(info
->type
, "CLOSED-CAPTIONS"))
477 /* CLOSED-CAPTIONS is ignored since we do not support CEA-608 CC in
478 * AVC SEI RBSP anyway */
481 if (type
== AVMEDIA_TYPE_UNKNOWN
)
484 /* URI is mandatory for subtitles as per spec */
485 if (type
== AVMEDIA_TYPE_SUBTITLE
&& !info
->uri
[0])
488 /* TODO: handle subtitles (each segment has to parsed separately) */
489 if (c
->strict_std_compliance
> FF_COMPLIANCE_EXPERIMENTAL
)
490 if (type
== AVMEDIA_TYPE_SUBTITLE
)
493 rend
= av_mallocz(sizeof(struct rendition
));
497 dynarray_add(&c
->renditions
, &c
->n_renditions
, rend
);
500 strcpy(rend
->group_id
, info
->group_id
);
501 strcpy(rend
->language
, info
->language
);
502 strcpy(rend
->name
, info
->name
);
504 /* add the playlist if this is an external rendition */
506 rend
->playlist
= new_playlist(c
, info
->uri
, url_base
);
508 dynarray_add(&rend
->playlist
->renditions
,
509 &rend
->playlist
->n_renditions
, rend
);
512 if (info
->assoc_language
[0]) {
513 int langlen
= strlen(rend
->language
);
514 if (langlen
< sizeof(rend
->language
) - 3) {
515 rend
->language
[langlen
] = ',';
516 strncpy(rend
->language
+ langlen
+ 1, info
->assoc_language
,
517 sizeof(rend
->language
) - langlen
- 2);
521 if (!strcmp(info
->defaultr
, "YES"))
522 rend
->disposition
|= AV_DISPOSITION_DEFAULT
;
523 if (!strcmp(info
->forced
, "YES"))
524 rend
->disposition
|= AV_DISPOSITION_FORCED
;
526 chr_ptr
= info
->characteristics
;
527 while ((characteristic
= av_strtok(chr_ptr
, ",", &saveptr
))) {
528 if (!strcmp(characteristic
, "public.accessibility.describes-music-and-sound"))
529 rend
->disposition
|= AV_DISPOSITION_HEARING_IMPAIRED
;
530 else if (!strcmp(characteristic
, "public.accessibility.describes-video"))
531 rend
->disposition
|= AV_DISPOSITION_VISUAL_IMPAIRED
;
539 static void handle_rendition_args(struct rendition_info
*info
, const char *key
,
540 int key_len
, char **dest
, int *dest_len
)
542 if (!strncmp(key
, "TYPE=", key_len
)) {
544 *dest_len
= sizeof(info
->type
);
545 } else if (!strncmp(key
, "URI=", key_len
)) {
547 *dest_len
= sizeof(info
->uri
);
548 } else if (!strncmp(key
, "GROUP-ID=", key_len
)) {
549 *dest
= info
->group_id
;
550 *dest_len
= sizeof(info
->group_id
);
551 } else if (!strncmp(key
, "LANGUAGE=", key_len
)) {
552 *dest
= info
->language
;
553 *dest_len
= sizeof(info
->language
);
554 } else if (!strncmp(key
, "ASSOC-LANGUAGE=", key_len
)) {
555 *dest
= info
->assoc_language
;
556 *dest_len
= sizeof(info
->assoc_language
);
557 } else if (!strncmp(key
, "NAME=", key_len
)) {
559 *dest_len
= sizeof(info
->name
);
560 } else if (!strncmp(key
, "DEFAULT=", key_len
)) {
561 *dest
= info
->defaultr
;
562 *dest_len
= sizeof(info
->defaultr
);
563 } else if (!strncmp(key
, "FORCED=", key_len
)) {
564 *dest
= info
->forced
;
565 *dest_len
= sizeof(info
->forced
);
566 } else if (!strncmp(key
, "CHARACTERISTICS=", key_len
)) {
567 *dest
= info
->characteristics
;
568 *dest_len
= sizeof(info
->characteristics
);
572 * - AUTOSELECT: client may autoselect based on e.g. system language
573 * - INSTREAM-ID: EIA-608 closed caption number ("CC1".."CC4")
577 /* used by parse_playlist to allocate a new variant+playlist when the
578 * playlist is detected to be a Media Playlist (not Master Playlist)
579 * and we have no parent Master Playlist (parsing of which would have
580 * allocated the variant and playlist already)
581 * *pls == NULL => Master Playlist or parentless Media Playlist
582 * *pls != NULL => parented Media Playlist, playlist+variant allocated */
583 static int ensure_playlist(HLSContext
*c
, struct playlist
**pls
, const char *url
)
587 if (!new_variant(c
, NULL
, url
, NULL
))
588 return AVERROR(ENOMEM
);
589 *pls
= c
->playlists
[c
->n_playlists
- 1];
593 static void update_options(char **dest
, const char *name
, void *src
)
596 av_opt_get(src
, name
, AV_OPT_SEARCH_CHILDREN
, (uint8_t**)dest
);
597 if (*dest
&& !strlen(*dest
))
601 static int open_url(AVFormatContext
*s
, AVIOContext
**pb
, const char *url
,
602 AVDictionary
*opts
, AVDictionary
*opts2
, int *is_http
)
604 HLSContext
*c
= s
->priv_data
;
605 AVDictionary
*tmp
= NULL
;
606 const char *proto_name
= NULL
;
609 av_dict_copy(&tmp
, opts
, 0);
610 av_dict_copy(&tmp
, opts2
, 0);
612 if (av_strstart(url
, "crypto", NULL
)) {
613 if (url
[6] == '+' || url
[6] == ':')
614 proto_name
= avio_find_protocol_name(url
+ 7);
618 proto_name
= avio_find_protocol_name(url
);
621 return AVERROR_INVALIDDATA
;
623 // only http(s) & file are allowed
624 if (av_strstart(proto_name
, "file", NULL
)) {
625 if (strcmp(c
->allowed_extensions
, "ALL") && !av_match_ext(url
, c
->allowed_extensions
)) {
626 av_log(s
, AV_LOG_ERROR
,
627 "Filename extension of \'%s\' is not a common multimedia extension, blocked for security reasons.\n"
628 "If you wish to override this adjust allowed_extensions, you can set it to \'ALL\' to allow all\n",
630 return AVERROR_INVALIDDATA
;
632 } else if (av_strstart(proto_name
, "http", NULL
)) {
635 return AVERROR_INVALIDDATA
;
637 if (!strncmp(proto_name
, url
, strlen(proto_name
)) && url
[strlen(proto_name
)] == ':')
639 else if (av_strstart(url
, "crypto", NULL
) && !strncmp(proto_name
, url
+ 7, strlen(proto_name
)) && url
[7 + strlen(proto_name
)] == ':')
641 else if (strcmp(proto_name
, "file") || !strncmp(url
, "file,", 5))
642 return AVERROR_INVALIDDATA
;
644 ret
= s
->io_open(s
, pb
, url
, AVIO_FLAG_READ
, &tmp
);
646 // update cookies on http response with setcookies.
647 void *u
= (s
->flags
& AVFMT_FLAG_CUSTOM_IO
) ? NULL
: s
->pb
;
648 update_options(&c
->cookies
, "cookies", u
);
649 av_dict_set(&opts
, "cookies", c
->cookies
, 0);
655 *is_http
= av_strstart(proto_name
, "http", NULL
);
660 static int parse_playlist(HLSContext
*c
, const char *url
,
661 struct playlist
*pls
, AVIOContext
*in
)
663 int ret
= 0, is_segment
= 0, is_variant
= 0;
664 int64_t duration
= 0;
665 enum KeyType key_type
= KEY_NONE
;
668 char key
[MAX_URL_SIZE
] = "";
669 char line
[MAX_URL_SIZE
];
672 int64_t seg_offset
= 0;
673 int64_t seg_size
= -1;
674 uint8_t *new_url
= NULL
;
675 struct variant_info variant_info
;
676 char tmp_str
[MAX_URL_SIZE
];
677 struct segment
*cur_init_section
= NULL
;
681 AVDictionary
*opts
= NULL
;
683 /* Some HLS servers don't like being sent the range header */
684 av_dict_set(&opts
, "seekable", "0", 0);
686 // broker prior HTTP options that should be consistent across requests
687 av_dict_set(&opts
, "user-agent", c
->user_agent
, 0);
688 av_dict_set(&opts
, "cookies", c
->cookies
, 0);
689 av_dict_set(&opts
, "headers", c
->headers
, 0);
690 av_dict_set(&opts
, "http_proxy", c
->http_proxy
, 0);
692 ret
= c
->ctx
->io_open(c
->ctx
, &in
, url
, AVIO_FLAG_READ
, &opts
);
697 ret
= open_in(c
, &in
, url
);
704 if (av_opt_get(in
, "location", AV_OPT_SEARCH_CHILDREN
, &new_url
) >= 0)
707 read_chomp_line(in
, line
, sizeof(line
));
708 if (strcmp(line
, "#EXTM3U")) {
709 ret
= AVERROR_INVALIDDATA
;
714 free_segment_list(pls
);
716 pls
->type
= PLS_TYPE_UNSPECIFIED
;
718 while (!avio_feof(in
)) {
719 read_chomp_line(in
, line
, sizeof(line
));
720 if (av_strstart(line
, "#EXT-X-STREAM-INF:", &ptr
)) {
722 memset(&variant_info
, 0, sizeof(variant_info
));
723 ff_parse_key_value(ptr
, (ff_parse_key_val_cb
) handle_variant_args
,
725 } else if (av_strstart(line
, "#EXT-X-KEY:", &ptr
)) {
726 struct key_info info
= {{0}};
727 ff_parse_key_value(ptr
, (ff_parse_key_val_cb
) handle_key_args
,
731 if (!strcmp(info
.method
, "AES-128"))
732 key_type
= KEY_AES_128
;
733 if (!strcmp(info
.method
, "SAMPLE-AES"))
734 key_type
= KEY_SAMPLE_AES
;
735 if (!strncmp(info
.iv
, "0x", 2) || !strncmp(info
.iv
, "0X", 2)) {
736 ff_hex_to_data(iv
, info
.iv
+ 2);
739 av_strlcpy(key
, info
.uri
, sizeof(key
));
740 } else if (av_strstart(line
, "#EXT-X-MEDIA:", &ptr
)) {
741 struct rendition_info info
= {{0}};
742 ff_parse_key_value(ptr
, (ff_parse_key_val_cb
) handle_rendition_args
,
744 new_rendition(c
, &info
, url
);
745 } else if (av_strstart(line
, "#EXT-X-TARGETDURATION:", &ptr
)) {
747 ret
= ensure_playlist(c
, &pls
, url
);
750 t
= strtoll(ptr
, NULL
, 10);
751 if (t
< 0 || t
>= INT64_MAX
/ AV_TIME_BASE
) {
752 ret
= AVERROR_INVALIDDATA
;
755 pls
->target_duration
= t
* AV_TIME_BASE
;
756 } else if (av_strstart(line
, "#EXT-X-MEDIA-SEQUENCE:", &ptr
)) {
757 ret
= ensure_playlist(c
, &pls
, url
);
760 pls
->start_seq_no
= atoi(ptr
);
761 } else if (av_strstart(line
, "#EXT-X-PLAYLIST-TYPE:", &ptr
)) {
762 ret
= ensure_playlist(c
, &pls
, url
);
765 if (!strcmp(ptr
, "EVENT"))
766 pls
->type
= PLS_TYPE_EVENT
;
767 else if (!strcmp(ptr
, "VOD"))
768 pls
->type
= PLS_TYPE_VOD
;
769 } else if (av_strstart(line
, "#EXT-X-MAP:", &ptr
)) {
770 struct init_section_info info
= {{0}};
771 ret
= ensure_playlist(c
, &pls
, url
);
774 ff_parse_key_value(ptr
, (ff_parse_key_val_cb
) handle_init_section_args
,
776 cur_init_section
= new_init_section(pls
, &info
, url
);
777 } else if (av_strstart(line
, "#EXT-X-ENDLIST", &ptr
)) {
780 } else if (av_strstart(line
, "#EXTINF:", &ptr
)) {
782 duration
= atof(ptr
) * AV_TIME_BASE
;
783 } else if (av_strstart(line
, "#EXT-X-BYTERANGE:", &ptr
)) {
784 seg_size
= strtoll(ptr
, NULL
, 10);
785 ptr
= strchr(ptr
, '@');
787 seg_offset
= strtoll(ptr
+1, NULL
, 10);
788 } else if (av_strstart(line
, "#", NULL
)) {
790 } else if (line
[0]) {
792 if (!new_variant(c
, &variant_info
, line
, url
)) {
793 ret
= AVERROR(ENOMEM
);
801 if (!new_variant(c
, 0, url
, NULL
)) {
802 ret
= AVERROR(ENOMEM
);
805 pls
= c
->playlists
[c
->n_playlists
- 1];
807 seg
= av_malloc(sizeof(struct segment
));
809 ret
= AVERROR(ENOMEM
);
813 memcpy(seg
->iv
, iv
, sizeof(iv
));
815 int seq
= pls
->start_seq_no
+ pls
->n_segments
;
816 memset(seg
->iv
, 0, sizeof(seg
->iv
));
817 AV_WB32(seg
->iv
+ 12, seq
);
820 if (key_type
!= KEY_NONE
) {
821 ff_make_absolute_url(tmp_str
, sizeof(tmp_str
), url
, key
);
822 seg
->key
= av_strdup(tmp_str
);
825 ret
= AVERROR(ENOMEM
);
832 ff_make_absolute_url(tmp_str
, sizeof(tmp_str
), url
, line
);
833 seg
->url
= av_strdup(tmp_str
);
837 ret
= AVERROR(ENOMEM
);
841 if (duration
< 0.001 * AV_TIME_BASE
) {
842 av_log(c
->ctx
, AV_LOG_WARNING
, "Cannot get correct #EXTINF value of segment %s,"
843 " set to default value to 1ms.\n", seg
->url
);
844 duration
= 0.001 * AV_TIME_BASE
;
846 seg
->duration
= duration
;
847 seg
->key_type
= key_type
;
848 dynarray_add(&pls
->segments
, &pls
->n_segments
, seg
);
851 seg
->size
= seg_size
;
853 seg
->url_offset
= seg_offset
;
854 seg_offset
+= seg_size
;
861 seg
->init_section
= cur_init_section
;
866 pls
->last_load_time
= av_gettime_relative();
871 ff_format_io_close(c
->ctx
, &in
);
875 static struct segment
*current_segment(struct playlist
*pls
)
877 return pls
->segments
[pls
->cur_seq_no
- pls
->start_seq_no
];
880 enum ReadFromURLMode
{
885 static int read_from_url(struct playlist
*pls
, struct segment
*seg
,
886 uint8_t *buf
, int buf_size
,
887 enum ReadFromURLMode mode
)
891 /* limit read if the segment was only a part of a file */
893 buf_size
= FFMIN(buf_size
, seg
->size
- pls
->cur_seg_offset
);
895 if (mode
== READ_COMPLETE
) {
896 ret
= avio_read(pls
->input
, buf
, buf_size
);
898 av_log(NULL
, AV_LOG_ERROR
, "Could not read complete segment.\n");
900 ret
= avio_read(pls
->input
, buf
, buf_size
);
903 pls
->cur_seg_offset
+= ret
;
908 /* Parse the raw ID3 data and pass contents to caller */
909 static void parse_id3(AVFormatContext
*s
, AVIOContext
*pb
,
910 AVDictionary
**metadata
, int64_t *dts
,
911 ID3v2ExtraMetaAPIC
**apic
, ID3v2ExtraMeta
**extra_meta
)
913 static const char id3_priv_owner_ts
[] = "com.apple.streaming.transportStreamTimestamp";
914 ID3v2ExtraMeta
*meta
;
916 ff_id3v2_read_dict(pb
, metadata
, ID3v2_DEFAULT_MAGIC
, extra_meta
);
917 for (meta
= *extra_meta
; meta
; meta
= meta
->next
) {
918 if (!strcmp(meta
->tag
, "PRIV")) {
919 ID3v2ExtraMetaPRIV
*priv
= meta
->data
;
920 if (priv
->datasize
== 8 && !strcmp(priv
->owner
, id3_priv_owner_ts
)) {
921 /* 33-bit MPEG timestamp */
922 int64_t ts
= AV_RB64(priv
->data
);
923 av_log(s
, AV_LOG_DEBUG
, "HLS ID3 audio timestamp %"PRId64
"\n", ts
);
924 if ((ts
& ~((1ULL << 33) - 1)) == 0)
927 av_log(s
, AV_LOG_ERROR
, "Invalid HLS ID3 audio timestamp %"PRId64
"\n", ts
);
929 } else if (!strcmp(meta
->tag
, "APIC") && apic
)
934 /* Check if the ID3 metadata contents have changed */
935 static int id3_has_changed_values(struct playlist
*pls
, AVDictionary
*metadata
,
936 ID3v2ExtraMetaAPIC
*apic
)
938 AVDictionaryEntry
*entry
= NULL
;
939 AVDictionaryEntry
*oldentry
;
940 /* check that no keys have changed values */
941 while ((entry
= av_dict_get(metadata
, "", entry
, AV_DICT_IGNORE_SUFFIX
))) {
942 oldentry
= av_dict_get(pls
->id3_initial
, entry
->key
, NULL
, AV_DICT_MATCH_CASE
);
943 if (!oldentry
|| strcmp(oldentry
->value
, entry
->value
) != 0)
947 /* check if apic appeared */
948 if (apic
&& (pls
->ctx
->nb_streams
!= 2 || !pls
->ctx
->streams
[1]->attached_pic
.data
))
952 int size
= pls
->ctx
->streams
[1]->attached_pic
.size
;
953 if (size
!= apic
->buf
->size
- AV_INPUT_BUFFER_PADDING_SIZE
)
956 if (memcmp(apic
->buf
->data
, pls
->ctx
->streams
[1]->attached_pic
.data
, size
) != 0)
963 /* Parse ID3 data and handle the found data */
964 static void handle_id3(AVIOContext
*pb
, struct playlist
*pls
)
966 AVDictionary
*metadata
= NULL
;
967 ID3v2ExtraMetaAPIC
*apic
= NULL
;
968 ID3v2ExtraMeta
*extra_meta
= NULL
;
969 int64_t timestamp
= AV_NOPTS_VALUE
;
971 parse_id3(pls
->ctx
, pb
, &metadata
, ×tamp
, &apic
, &extra_meta
);
973 if (timestamp
!= AV_NOPTS_VALUE
) {
974 pls
->id3_mpegts_timestamp
= timestamp
;
978 if (!pls
->id3_found
) {
979 /* initial ID3 tags */
980 av_assert0(!pls
->id3_deferred_extra
);
983 /* get picture attachment and set text metadata */
984 if (pls
->ctx
->nb_streams
)
985 ff_id3v2_parse_apic(pls
->ctx
, &extra_meta
);
987 /* demuxer not yet opened, defer picture attachment */
988 pls
->id3_deferred_extra
= extra_meta
;
990 av_dict_copy(&pls
->ctx
->metadata
, metadata
, 0);
991 pls
->id3_initial
= metadata
;
994 if (!pls
->id3_changed
&& id3_has_changed_values(pls
, metadata
, apic
)) {
995 avpriv_report_missing_feature(pls
->ctx
, "Changing ID3 metadata in HLS audio elementary stream");
996 pls
->id3_changed
= 1;
998 av_dict_free(&metadata
);
1001 if (!pls
->id3_deferred_extra
)
1002 ff_id3v2_free_extra_meta(&extra_meta
);
1005 static void intercept_id3(struct playlist
*pls
, uint8_t *buf
,
1006 int buf_size
, int *len
)
1008 /* intercept id3 tags, we do not want to pass them to the raw
1009 * demuxer on all segment switches */
1011 int id3_buf_pos
= 0;
1013 struct segment
*seg
= current_segment(pls
);
1015 /* gather all the id3 tags */
1017 /* see if we can retrieve enough data for ID3 header */
1018 if (*len
< ID3v2_HEADER_SIZE
&& buf_size
>= ID3v2_HEADER_SIZE
) {
1019 bytes
= read_from_url(pls
, seg
, buf
+ *len
, ID3v2_HEADER_SIZE
- *len
, READ_COMPLETE
);
1022 if (bytes
== ID3v2_HEADER_SIZE
- *len
)
1023 /* no EOF yet, so fill the caller buffer again after
1024 * we have stripped the ID3 tags */
1029 } else if (*len
<= 0) {
1036 if (*len
< ID3v2_HEADER_SIZE
)
1039 if (ff_id3v2_match(buf
, ID3v2_DEFAULT_MAGIC
)) {
1040 int64_t maxsize
= seg
->size
>= 0 ? seg
->size
: 1024*1024;
1041 int taglen
= ff_id3v2_tag_len(buf
);
1042 int tag_got_bytes
= FFMIN(taglen
, *len
);
1043 int remaining
= taglen
- tag_got_bytes
;
1045 if (taglen
> maxsize
) {
1046 av_log(pls
->ctx
, AV_LOG_ERROR
, "Too large HLS ID3 tag (%d > %"PRId64
" bytes)\n",
1052 * Copy the id3 tag to our temporary id3 buffer.
1053 * We could read a small id3 tag directly without memcpy, but
1054 * we would still need to copy the large tags, and handling
1055 * both of those cases together with the possibility for multiple
1056 * tags would make the handling a bit complex.
1058 pls
->id3_buf
= av_fast_realloc(pls
->id3_buf
, &pls
->id3_buf_size
, id3_buf_pos
+ taglen
);
1061 memcpy(pls
->id3_buf
+ id3_buf_pos
, buf
, tag_got_bytes
);
1062 id3_buf_pos
+= tag_got_bytes
;
1064 /* strip the intercepted bytes */
1065 *len
-= tag_got_bytes
;
1066 memmove(buf
, buf
+ tag_got_bytes
, *len
);
1067 av_log(pls
->ctx
, AV_LOG_DEBUG
, "Stripped %d HLS ID3 bytes\n", tag_got_bytes
);
1069 if (remaining
> 0) {
1070 /* read the rest of the tag in */
1071 if (read_from_url(pls
, seg
, pls
->id3_buf
+ id3_buf_pos
, remaining
, READ_COMPLETE
) != remaining
)
1073 id3_buf_pos
+= remaining
;
1074 av_log(pls
->ctx
, AV_LOG_DEBUG
, "Stripped additional %d HLS ID3 bytes\n", remaining
);
1078 /* no more ID3 tags */
1083 /* re-fill buffer for the caller unless EOF */
1084 if (*len
>= 0 && (fill_buf
|| *len
== 0)) {
1085 bytes
= read_from_url(pls
, seg
, buf
+ *len
, buf_size
- *len
, READ_NORMAL
);
1087 /* ignore error if we already had some data */
1095 /* Now parse all the ID3 tags */
1096 AVIOContext id3ioctx
;
1097 ffio_init_context(&id3ioctx
, pls
->id3_buf
, id3_buf_pos
, 0, NULL
, NULL
, NULL
, NULL
);
1098 handle_id3(&id3ioctx
, pls
);
1101 if (pls
->is_id3_timestamped
== -1)
1102 pls
->is_id3_timestamped
= (pls
->id3_mpegts_timestamp
!= AV_NOPTS_VALUE
);
1105 static int open_input(HLSContext
*c
, struct playlist
*pls
, struct segment
*seg
)
1107 AVDictionary
*opts
= NULL
;
1111 // broker prior HTTP options that should be consistent across requests
1112 av_dict_set(&opts
, "user-agent", c
->user_agent
, 0);
1113 av_dict_set(&opts
, "cookies", c
->cookies
, 0);
1114 av_dict_set(&opts
, "headers", c
->headers
, 0);
1115 av_dict_set(&opts
, "http_proxy", c
->http_proxy
, 0);
1116 av_dict_set(&opts
, "seekable", "0", 0);
1118 if (seg
->size
>= 0) {
1119 /* try to restrict the HTTP request to the part we want
1120 * (if this is in fact a HTTP request) */
1121 av_dict_set_int(&opts
, "offset", seg
->url_offset
, 0);
1122 av_dict_set_int(&opts
, "end_offset", seg
->url_offset
+ seg
->size
, 0);
1125 av_log(pls
->parent
, AV_LOG_VERBOSE
, "HLS request for url '%s', offset %"PRId64
", playlist %d\n",
1126 seg
->url
, seg
->url_offset
, pls
->index
);
1128 if (seg
->key_type
== KEY_NONE
) {
1129 ret
= open_url(pls
->parent
, &pls
->input
, seg
->url
, c
->avio_opts
, opts
, &is_http
);
1130 } else if (seg
->key_type
== KEY_AES_128
) {
1131 AVDictionary
*opts2
= NULL
;
1132 char iv
[33], key
[33], url
[MAX_URL_SIZE
];
1133 if (strcmp(seg
->key
, pls
->key_url
)) {
1135 if (open_url(pls
->parent
, &pb
, seg
->key
, c
->avio_opts
, opts
, NULL
) == 0) {
1136 ret
= avio_read(pb
, pls
->key
, sizeof(pls
->key
));
1137 if (ret
!= sizeof(pls
->key
)) {
1138 av_log(NULL
, AV_LOG_ERROR
, "Unable to read key file %s\n",
1141 ff_format_io_close(pls
->parent
, &pb
);
1143 av_log(NULL
, AV_LOG_ERROR
, "Unable to open key file %s\n",
1146 av_strlcpy(pls
->key_url
, seg
->key
, sizeof(pls
->key_url
));
1148 ff_data_to_hex(iv
, seg
->iv
, sizeof(seg
->iv
), 0);
1149 ff_data_to_hex(key
, pls
->key
, sizeof(pls
->key
), 0);
1150 iv
[32] = key
[32] = '\0';
1151 if (strstr(seg
->url
, "://"))
1152 snprintf(url
, sizeof(url
), "crypto+%s", seg
->url
);
1154 snprintf(url
, sizeof(url
), "crypto:%s", seg
->url
);
1156 av_dict_copy(&opts2
, c
->avio_opts
, 0);
1157 av_dict_set(&opts2
, "key", key
, 0);
1158 av_dict_set(&opts2
, "iv", iv
, 0);
1160 ret
= open_url(pls
->parent
, &pls
->input
, url
, opts2
, opts
, &is_http
);
1162 av_dict_free(&opts2
);
1168 } else if (seg
->key_type
== KEY_SAMPLE_AES
) {
1169 av_log(pls
->parent
, AV_LOG_ERROR
,
1170 "SAMPLE-AES encryption is not supported yet\n");
1171 ret
= AVERROR_PATCHWELCOME
;
1174 ret
= AVERROR(ENOSYS
);
1176 /* Seek to the requested position. If this was a HTTP request, the offset
1177 * should already be where want it to, but this allows e.g. local testing
1178 * without a HTTP server.
1180 * This is not done for HTTP at all as avio_seek() does internal bookkeeping
1181 * of file offset which is out-of-sync with the actual offset when "offset"
1182 * AVOption is used with http protocol, causing the seek to not be a no-op
1183 * as would be expected. Wrong offset received from the server will not be
1184 * noticed without the call, though.
1186 if (ret
== 0 && !is_http
&& seg
->key_type
== KEY_NONE
&& seg
->url_offset
) {
1187 int64_t seekret
= avio_seek(pls
->input
, seg
->url_offset
, SEEK_SET
);
1189 av_log(pls
->parent
, AV_LOG_ERROR
, "Unable to seek to offset %"PRId64
" of HLS segment '%s'\n", seg
->url_offset
, seg
->url
);
1191 ff_format_io_close(pls
->parent
, &pls
->input
);
1196 av_dict_free(&opts
);
1197 pls
->cur_seg_offset
= 0;
1201 static int update_init_section(struct playlist
*pls
, struct segment
*seg
)
1203 static const int max_init_section_size
= 1024*1024;
1204 HLSContext
*c
= pls
->parent
->priv_data
;
1209 if (seg
->init_section
== pls
->cur_init_section
)
1212 pls
->cur_init_section
= NULL
;
1214 if (!seg
->init_section
)
1217 ret
= open_input(c
, pls
, seg
->init_section
);
1219 av_log(pls
->parent
, AV_LOG_WARNING
,
1220 "Failed to open an initialization section in playlist %d\n",
1225 if (seg
->init_section
->size
>= 0)
1226 sec_size
= seg
->init_section
->size
;
1227 else if ((urlsize
= avio_size(pls
->input
)) >= 0)
1230 sec_size
= max_init_section_size
;
1232 av_log(pls
->parent
, AV_LOG_DEBUG
,
1233 "Downloading an initialization section of size %"PRId64
"\n",
1236 sec_size
= FFMIN(sec_size
, max_init_section_size
);
1238 av_fast_malloc(&pls
->init_sec_buf
, &pls
->init_sec_buf_size
, sec_size
);
1240 ret
= read_from_url(pls
, seg
->init_section
, pls
->init_sec_buf
,
1241 pls
->init_sec_buf_size
, READ_COMPLETE
);
1242 ff_format_io_close(pls
->parent
, &pls
->input
);
1247 pls
->cur_init_section
= seg
->init_section
;
1248 pls
->init_sec_data_len
= ret
;
1249 pls
->init_sec_buf_read_offset
= 0;
1251 /* spec says audio elementary streams do not have media initialization
1252 * sections, so there should be no ID3 timestamps */
1253 pls
->is_id3_timestamped
= 0;
1258 static int64_t default_reload_interval(struct playlist
*pls
)
1260 return pls
->n_segments
> 0 ?
1261 pls
->segments
[pls
->n_segments
- 1]->duration
:
1262 pls
->target_duration
;
1265 static int read_data(void *opaque
, uint8_t *buf
, int buf_size
)
1267 struct playlist
*v
= opaque
;
1268 HLSContext
*c
= v
->parent
->priv_data
;
1270 int just_opened
= 0;
1271 int reload_count
= 0;
1278 int64_t reload_interval
;
1279 struct segment
*seg
;
1281 /* Check that the playlist is still needed before opening a new
1283 if (v
->ctx
&& v
->ctx
->nb_streams
) {
1285 for (i
= 0; i
< v
->n_main_streams
; i
++) {
1286 if (v
->main_streams
[i
]->discard
< AVDISCARD_ALL
) {
1293 av_log(v
->parent
, AV_LOG_INFO
, "No longer receiving playlist %d\n",
1298 /* If this is a live stream and the reload interval has elapsed since
1299 * the last playlist reload, reload the playlists now. */
1300 reload_interval
= default_reload_interval(v
);
1304 if (reload_count
> c
->max_reload
)
1307 av_gettime_relative() - v
->last_load_time
>= reload_interval
) {
1308 if ((ret
= parse_playlist(c
, v
->url
, v
, NULL
)) < 0) {
1309 av_log(v
->parent
, AV_LOG_WARNING
, "Failed to reload playlist %d\n",
1313 /* If we need to reload the playlist again below (if
1314 * there's still no more segments), switch to a reload
1315 * interval of half the target duration. */
1316 reload_interval
= v
->target_duration
/ 2;
1318 if (v
->cur_seq_no
< v
->start_seq_no
) {
1319 av_log(NULL
, AV_LOG_WARNING
,
1320 "skipping %d segments ahead, expired from playlists\n",
1321 v
->start_seq_no
- v
->cur_seq_no
);
1322 v
->cur_seq_no
= v
->start_seq_no
;
1324 if (v
->cur_seq_no
>= v
->start_seq_no
+ v
->n_segments
) {
1327 while (av_gettime_relative() - v
->last_load_time
< reload_interval
) {
1328 if (ff_check_interrupt(c
->interrupt_callback
))
1329 return AVERROR_EXIT
;
1330 av_usleep(100*1000);
1332 /* Enough time has elapsed since the last reload */
1336 seg
= current_segment(v
);
1338 /* load/update Media Initialization Section, if any */
1339 ret
= update_init_section(v
, seg
);
1343 ret
= open_input(c
, v
, seg
);
1345 if (ff_check_interrupt(c
->interrupt_callback
))
1346 return AVERROR_EXIT
;
1347 av_log(v
->parent
, AV_LOG_WARNING
, "Failed to open segment of playlist %d\n",
1355 if (v
->init_sec_buf_read_offset
< v
->init_sec_data_len
) {
1356 /* Push init section out first before first actual segment */
1357 int copy_size
= FFMIN(v
->init_sec_data_len
- v
->init_sec_buf_read_offset
, buf_size
);
1358 memcpy(buf
, v
->init_sec_buf
, copy_size
);
1359 v
->init_sec_buf_read_offset
+= copy_size
;
1363 ret
= read_from_url(v
, current_segment(v
), buf
, buf_size
, READ_NORMAL
);
1365 if (just_opened
&& v
->is_id3_timestamped
!= 0) {
1366 /* Intercept ID3 tags here, elementary audio streams are required
1367 * to convey timestamps using them in the beginning of each segment. */
1368 intercept_id3(v
, buf
, buf_size
, &ret
);
1373 ff_format_io_close(v
->parent
, &v
->input
);
1376 c
->cur_seq_no
= v
->cur_seq_no
;
1381 static void add_renditions_to_variant(HLSContext
*c
, struct variant
*var
,
1382 enum AVMediaType type
, const char *group_id
)
1386 for (i
= 0; i
< c
->n_renditions
; i
++) {
1387 struct rendition
*rend
= c
->renditions
[i
];
1389 if (rend
->type
== type
&& !strcmp(rend
->group_id
, group_id
)) {
1392 /* rendition is an external playlist
1393 * => add the playlist to the variant */
1394 dynarray_add(&var
->playlists
, &var
->n_playlists
, rend
->playlist
);
1396 /* rendition is part of the variant main Media Playlist
1397 * => add the rendition to the main Media Playlist */
1398 dynarray_add(&var
->playlists
[0]->renditions
,
1399 &var
->playlists
[0]->n_renditions
,
1405 static void add_metadata_from_renditions(AVFormatContext
*s
, struct playlist
*pls
,
1406 enum AVMediaType type
)
1411 for (i
= 0; i
< pls
->n_main_streams
; i
++) {
1412 AVStream
*st
= pls
->main_streams
[i
];
1414 if (st
->codecpar
->codec_type
!= type
)
1417 for (; rend_idx
< pls
->n_renditions
; rend_idx
++) {
1418 struct rendition
*rend
= pls
->renditions
[rend_idx
];
1420 if (rend
->type
!= type
)
1423 if (rend
->language
[0])
1424 av_dict_set(&st
->metadata
, "language", rend
->language
, 0);
1426 av_dict_set(&st
->metadata
, "comment", rend
->name
, 0);
1428 st
->disposition
|= rend
->disposition
;
1430 if (rend_idx
>=pls
->n_renditions
)
1435 /* if timestamp was in valid range: returns 1 and sets seq_no
1436 * if not: returns 0 and sets seq_no to closest segment */
1437 static int find_timestamp_in_playlist(HLSContext
*c
, struct playlist
*pls
,
1438 int64_t timestamp
, int *seq_no
)
1441 int64_t pos
= c
->first_timestamp
== AV_NOPTS_VALUE
?
1442 0 : c
->first_timestamp
;
1444 if (timestamp
< pos
) {
1445 *seq_no
= pls
->start_seq_no
;
1449 for (i
= 0; i
< pls
->n_segments
; i
++) {
1450 int64_t diff
= pos
+ pls
->segments
[i
]->duration
- timestamp
;
1452 *seq_no
= pls
->start_seq_no
+ i
;
1455 pos
+= pls
->segments
[i
]->duration
;
1458 *seq_no
= pls
->start_seq_no
+ pls
->n_segments
- 1;
1463 static int select_cur_seq_no(HLSContext
*c
, struct playlist
*pls
)
1467 if (!pls
->finished
&& !c
->first_packet
&&
1468 av_gettime_relative() - pls
->last_load_time
>= default_reload_interval(pls
))
1469 /* reload the playlist since it was suspended */
1470 parse_playlist(c
, pls
->url
, pls
, NULL
);
1472 /* If playback is already in progress (we are just selecting a new
1473 * playlist) and this is a complete file, find the matching segment
1474 * by counting durations. */
1475 if (pls
->finished
&& c
->cur_timestamp
!= AV_NOPTS_VALUE
) {
1476 find_timestamp_in_playlist(c
, pls
, c
->cur_timestamp
, &seq_no
);
1480 if (!pls
->finished
) {
1481 if (!c
->first_packet
&& /* we are doing a segment selection during playback */
1482 c
->cur_seq_no
>= pls
->start_seq_no
&&
1483 c
->cur_seq_no
< pls
->start_seq_no
+ pls
->n_segments
)
1484 /* While spec 3.4.3 says that we cannot assume anything about the
1485 * content at the same sequence number on different playlists,
1486 * in practice this seems to work and doing it otherwise would
1487 * require us to download a segment to inspect its timestamps. */
1488 return c
->cur_seq_no
;
1490 /* If this is a live stream, start live_start_index segments from the
1492 if (c
->live_start_index
< 0)
1493 return pls
->start_seq_no
+ FFMAX(pls
->n_segments
+ c
->live_start_index
, 0);
1495 return pls
->start_seq_no
+ FFMIN(c
->live_start_index
, pls
->n_segments
- 1);
1498 /* Otherwise just start on the first segment. */
1499 return pls
->start_seq_no
;
1502 static int save_avio_options(AVFormatContext
*s
)
1504 HLSContext
*c
= s
->priv_data
;
1505 static const char *opts
[] = {
1506 "headers", "http_proxy", "user_agent", "user-agent", "cookies", NULL
};
1507 const char **opt
= opts
;
1512 if (av_opt_get(s
->pb
, *opt
, AV_OPT_SEARCH_CHILDREN
| AV_OPT_ALLOW_NULL
, &buf
) >= 0) {
1513 ret
= av_dict_set(&c
->avio_opts
, *opt
, buf
,
1514 AV_DICT_DONT_STRDUP_VAL
);
1524 static int nested_io_open(AVFormatContext
*s
, AVIOContext
**pb
, const char *url
,
1525 int flags
, AVDictionary
**opts
)
1527 av_log(s
, AV_LOG_ERROR
,
1528 "A HLS playlist item '%s' referred to an external file '%s'. "
1529 "Opening this file was forbidden for security reasons\n",
1531 return AVERROR(EPERM
);
1534 static void add_stream_to_programs(AVFormatContext
*s
, struct playlist
*pls
, AVStream
*stream
)
1536 HLSContext
*c
= s
->priv_data
;
1540 for (i
= 0; i
< c
->n_variants
; i
++) {
1541 struct variant
*v
= c
->variants
[i
];
1543 for (j
= 0; j
< v
->n_playlists
; j
++) {
1544 if (v
->playlists
[j
] != pls
)
1547 av_program_add_stream_index(s
, i
, stream
->index
);
1550 bandwidth
= v
->bandwidth
;
1551 else if (bandwidth
!= v
->bandwidth
)
1552 bandwidth
= -1; /* stream in multiple variants with different bandwidths */
1557 av_dict_set_int(&stream
->metadata
, "variant_bitrate", bandwidth
, 0);
1560 static int set_stream_info_from_input_stream(AVStream
*st
, struct playlist
*pls
, AVStream
*ist
)
1564 err
= avcodec_parameters_copy(st
->codecpar
, ist
->codecpar
);
1568 if (pls
->is_id3_timestamped
) /* custom timestamps via id3 */
1569 avpriv_set_pts_info(st
, 33, 1, MPEG_TIME_BASE
);
1571 avpriv_set_pts_info(st
, ist
->pts_wrap_bits
, ist
->time_base
.num
, ist
->time_base
.den
);
1573 st
->internal
->need_context_update
= 1;
1578 /* add new subdemuxer streams to our context, if any */
1579 static int update_streams_from_subdemuxer(AVFormatContext
*s
, struct playlist
*pls
)
1583 while (pls
->n_main_streams
< pls
->ctx
->nb_streams
) {
1584 int ist_idx
= pls
->n_main_streams
;
1585 AVStream
*st
= avformat_new_stream(s
, NULL
);
1586 AVStream
*ist
= pls
->ctx
->streams
[ist_idx
];
1589 return AVERROR(ENOMEM
);
1591 st
->id
= pls
->index
;
1592 dynarray_add(&pls
->main_streams
, &pls
->n_main_streams
, st
);
1594 add_stream_to_programs(s
, pls
, st
);
1596 err
= set_stream_info_from_input_stream(st
, pls
, ist
);
1604 static void update_noheader_flag(AVFormatContext
*s
)
1606 HLSContext
*c
= s
->priv_data
;
1607 int flag_needed
= 0;
1610 for (i
= 0; i
< c
->n_playlists
; i
++) {
1611 struct playlist
*pls
= c
->playlists
[i
];
1613 if (pls
->has_noheader_flag
) {
1620 s
->ctx_flags
|= AVFMTCTX_NOHEADER
;
1622 s
->ctx_flags
&= ~AVFMTCTX_NOHEADER
;
1625 static int hls_read_header(AVFormatContext
*s
)
1627 void *u
= (s
->flags
& AVFMT_FLAG_CUSTOM_IO
) ? NULL
: s
->pb
;
1628 HLSContext
*c
= s
->priv_data
;
1630 int highest_cur_seq_no
= 0;
1633 c
->interrupt_callback
= &s
->interrupt_callback
;
1634 c
->strict_std_compliance
= s
->strict_std_compliance
;
1636 c
->first_packet
= 1;
1637 c
->first_timestamp
= AV_NOPTS_VALUE
;
1638 c
->cur_timestamp
= AV_NOPTS_VALUE
;
1641 // get the previous user agent & set back to null if string size is zero
1642 update_options(&c
->user_agent
, "user-agent", u
);
1644 // get the previous cookies & set back to null if string size is zero
1645 update_options(&c
->cookies
, "cookies", u
);
1647 // get the previous headers & set back to null if string size is zero
1648 update_options(&c
->headers
, "headers", u
);
1650 // get the previous http proxt & set back to null if string size is zero
1651 update_options(&c
->http_proxy
, "http_proxy", u
);
1654 if ((ret
= parse_playlist(c
, s
->filename
, NULL
, s
->pb
)) < 0)
1657 if ((ret
= save_avio_options(s
)) < 0)
1660 /* Some HLS servers don't like being sent the range header */
1661 av_dict_set(&c
->avio_opts
, "seekable", "0", 0);
1663 if (c
->n_variants
== 0) {
1664 av_log(NULL
, AV_LOG_WARNING
, "Empty playlist\n");
1668 /* If the playlist only contained playlists (Master Playlist),
1669 * parse each individual playlist. */
1670 if (c
->n_playlists
> 1 || c
->playlists
[0]->n_segments
== 0) {
1671 for (i
= 0; i
< c
->n_playlists
; i
++) {
1672 struct playlist
*pls
= c
->playlists
[i
];
1673 if ((ret
= parse_playlist(c
, pls
->url
, pls
, NULL
)) < 0)
1678 if (c
->variants
[0]->playlists
[0]->n_segments
== 0) {
1679 av_log(NULL
, AV_LOG_WARNING
, "Empty playlist\n");
1684 /* If this isn't a live stream, calculate the total duration of the
1686 if (c
->variants
[0]->playlists
[0]->finished
) {
1687 int64_t duration
= 0;
1688 for (i
= 0; i
< c
->variants
[0]->playlists
[0]->n_segments
; i
++)
1689 duration
+= c
->variants
[0]->playlists
[0]->segments
[i
]->duration
;
1690 s
->duration
= duration
;
1693 /* Associate renditions with variants */
1694 for (i
= 0; i
< c
->n_variants
; i
++) {
1695 struct variant
*var
= c
->variants
[i
];
1697 if (var
->audio_group
[0])
1698 add_renditions_to_variant(c
, var
, AVMEDIA_TYPE_AUDIO
, var
->audio_group
);
1699 if (var
->video_group
[0])
1700 add_renditions_to_variant(c
, var
, AVMEDIA_TYPE_VIDEO
, var
->video_group
);
1701 if (var
->subtitles_group
[0])
1702 add_renditions_to_variant(c
, var
, AVMEDIA_TYPE_SUBTITLE
, var
->subtitles_group
);
1705 /* Create a program for each variant */
1706 for (i
= 0; i
< c
->n_variants
; i
++) {
1707 struct variant
*v
= c
->variants
[i
];
1710 program
= av_new_program(s
, i
);
1713 av_dict_set_int(&program
->metadata
, "variant_bitrate", v
->bandwidth
, 0);
1716 /* Select the starting segments */
1717 for (i
= 0; i
< c
->n_playlists
; i
++) {
1718 struct playlist
*pls
= c
->playlists
[i
];
1720 if (pls
->n_segments
== 0)
1723 pls
->cur_seq_no
= select_cur_seq_no(c
, pls
);
1724 highest_cur_seq_no
= FFMAX(highest_cur_seq_no
, pls
->cur_seq_no
);
1727 /* Open the demuxer for each playlist */
1728 for (i
= 0; i
< c
->n_playlists
; i
++) {
1729 struct playlist
*pls
= c
->playlists
[i
];
1730 AVInputFormat
*in_fmt
= NULL
;
1733 if (!(pls
->ctx
= avformat_alloc_context())) {
1734 ret
= AVERROR(ENOMEM
);
1738 if (pls
->n_segments
== 0)
1746 * If this is a live stream and this playlist looks like it is one segment
1747 * behind, try to sync it up so that every substream starts at the same
1748 * time position (so e.g. avformat_find_stream_info() will see packets from
1749 * all active streams within the first few seconds). This is not very generic,
1750 * though, as the sequence numbers are technically independent.
1752 if (!pls
->finished
&& pls
->cur_seq_no
== highest_cur_seq_no
- 1 &&
1753 highest_cur_seq_no
< pls
->start_seq_no
+ pls
->n_segments
) {
1754 pls
->cur_seq_no
= highest_cur_seq_no
;
1757 pls
->read_buffer
= av_malloc(INITIAL_BUFFER_SIZE
);
1758 if (!pls
->read_buffer
){
1759 ret
= AVERROR(ENOMEM
);
1760 avformat_free_context(pls
->ctx
);
1764 ffio_init_context(&pls
->pb
, pls
->read_buffer
, INITIAL_BUFFER_SIZE
, 0, pls
,
1765 read_data
, NULL
, NULL
);
1766 pls
->pb
.seekable
= 0;
1767 url
= av_strdup(pls
->segments
[0]->url
);
1768 ret
= av_probe_input_buffer(&pls
->pb
, &in_fmt
, url
, NULL
, 0, 0);
1771 /* Free the ctx - it isn't initialized properly at this point,
1772 * so avformat_close_input shouldn't be called. If
1773 * avformat_open_input fails below, it frees and zeros the
1774 * context, so it doesn't need any special treatment like this. */
1775 av_log(s
, AV_LOG_ERROR
, "Error when loading first segment '%s'\n", pls
->segments
[0]->url
);
1776 avformat_free_context(pls
->ctx
);
1780 pls
->ctx
->pb
= &pls
->pb
;
1781 pls
->ctx
->io_open
= nested_io_open
;
1783 if ((ret
= ff_copy_whiteblacklists(pls
->ctx
, s
)) < 0)
1786 ret
= avformat_open_input(&pls
->ctx
, pls
->segments
[0]->url
, in_fmt
, NULL
);
1790 if (pls
->id3_deferred_extra
&& pls
->ctx
->nb_streams
== 1) {
1791 ff_id3v2_parse_apic(pls
->ctx
, &pls
->id3_deferred_extra
);
1792 avformat_queue_attached_pictures(pls
->ctx
);
1793 ff_id3v2_free_extra_meta(&pls
->id3_deferred_extra
);
1794 pls
->id3_deferred_extra
= NULL
;
1797 if (pls
->is_id3_timestamped
== -1)
1798 av_log(s
, AV_LOG_WARNING
, "No expected HTTP requests have been made\n");
1801 * For ID3 timestamped raw audio streams we need to detect the packet
1802 * durations to calculate timestamps in fill_timing_for_id3_timestamped_stream(),
1803 * but for other streams we can rely on our user calling avformat_find_stream_info()
1804 * on us if they want to.
1806 if (pls
->is_id3_timestamped
) {
1807 ret
= avformat_find_stream_info(pls
->ctx
, NULL
);
1812 pls
->has_noheader_flag
= !!(pls
->ctx
->ctx_flags
& AVFMTCTX_NOHEADER
);
1814 /* Create new AVStreams for each stream in this playlist */
1815 ret
= update_streams_from_subdemuxer(s
, pls
);
1819 add_metadata_from_renditions(s
, pls
, AVMEDIA_TYPE_AUDIO
);
1820 add_metadata_from_renditions(s
, pls
, AVMEDIA_TYPE_VIDEO
);
1821 add_metadata_from_renditions(s
, pls
, AVMEDIA_TYPE_SUBTITLE
);
1824 update_noheader_flag(s
);
1828 free_playlist_list(c
);
1829 free_variant_list(c
);
1830 free_rendition_list(c
);
1834 static int recheck_discard_flags(AVFormatContext
*s
, int first
)
1836 HLSContext
*c
= s
->priv_data
;
1839 /* Check if any new streams are needed */
1840 for (i
= 0; i
< c
->n_playlists
; i
++)
1841 c
->playlists
[i
]->cur_needed
= 0;
1843 for (i
= 0; i
< s
->nb_streams
; i
++) {
1844 AVStream
*st
= s
->streams
[i
];
1845 struct playlist
*pls
= c
->playlists
[s
->streams
[i
]->id
];
1846 if (st
->discard
< AVDISCARD_ALL
)
1847 pls
->cur_needed
= 1;
1849 for (i
= 0; i
< c
->n_playlists
; i
++) {
1850 struct playlist
*pls
= c
->playlists
[i
];
1851 if (pls
->cur_needed
&& !pls
->needed
) {
1854 pls
->cur_seq_no
= select_cur_seq_no(c
, pls
);
1855 pls
->pb
.eof_reached
= 0;
1856 if (c
->cur_timestamp
!= AV_NOPTS_VALUE
) {
1858 pls
->seek_timestamp
= c
->cur_timestamp
;
1859 pls
->seek_flags
= AVSEEK_FLAG_ANY
;
1860 pls
->seek_stream_index
= -1;
1862 av_log(s
, AV_LOG_INFO
, "Now receiving playlist %d, segment %d\n", i
, pls
->cur_seq_no
);
1863 } else if (first
&& !pls
->cur_needed
&& pls
->needed
) {
1865 ff_format_io_close(pls
->parent
, &pls
->input
);
1868 av_log(s
, AV_LOG_INFO
, "No longer receiving playlist %d\n", i
);
1874 static void fill_timing_for_id3_timestamped_stream(struct playlist
*pls
)
1876 if (pls
->id3_offset
>= 0) {
1877 pls
->pkt
.dts
= pls
->id3_mpegts_timestamp
+
1878 av_rescale_q(pls
->id3_offset
,
1879 pls
->ctx
->streams
[pls
->pkt
.stream_index
]->time_base
,
1881 if (pls
->pkt
.duration
)
1882 pls
->id3_offset
+= pls
->pkt
.duration
;
1884 pls
->id3_offset
= -1;
1886 /* there have been packets with unknown duration
1887 * since the last id3 tag, should not normally happen */
1888 pls
->pkt
.dts
= AV_NOPTS_VALUE
;
1891 if (pls
->pkt
.duration
)
1892 pls
->pkt
.duration
= av_rescale_q(pls
->pkt
.duration
,
1893 pls
->ctx
->streams
[pls
->pkt
.stream_index
]->time_base
,
1896 pls
->pkt
.pts
= AV_NOPTS_VALUE
;
1899 static AVRational
get_timebase(struct playlist
*pls
)
1901 if (pls
->is_id3_timestamped
)
1902 return MPEG_TIME_BASE_Q
;
1904 return pls
->ctx
->streams
[pls
->pkt
.stream_index
]->time_base
;
1907 static int compare_ts_with_wrapdetect(int64_t ts_a
, struct playlist
*pls_a
,
1908 int64_t ts_b
, struct playlist
*pls_b
)
1910 int64_t scaled_ts_a
= av_rescale_q(ts_a
, get_timebase(pls_a
), MPEG_TIME_BASE_Q
);
1911 int64_t scaled_ts_b
= av_rescale_q(ts_b
, get_timebase(pls_b
), MPEG_TIME_BASE_Q
);
1913 return av_compare_mod(scaled_ts_a
, scaled_ts_b
, 1LL << 33);
1916 static int hls_read_packet(AVFormatContext
*s
, AVPacket
*pkt
)
1918 HLSContext
*c
= s
->priv_data
;
1919 int ret
, i
, minplaylist
= -1;
1921 recheck_discard_flags(s
, c
->first_packet
);
1922 c
->first_packet
= 0;
1924 for (i
= 0; i
< c
->n_playlists
; i
++) {
1925 struct playlist
*pls
= c
->playlists
[i
];
1926 /* Make sure we've got one buffered packet from each open playlist
1928 if (pls
->needed
&& !pls
->pkt
.data
) {
1932 ret
= av_read_frame(pls
->ctx
, &pls
->pkt
);
1934 if (!avio_feof(&pls
->pb
) && ret
!= AVERROR_EOF
)
1936 reset_packet(&pls
->pkt
);
1939 /* stream_index check prevents matching picture attachments etc. */
1940 if (pls
->is_id3_timestamped
&& pls
->pkt
.stream_index
== 0) {
1941 /* audio elementary streams are id3 timestamped */
1942 fill_timing_for_id3_timestamped_stream(pls
);
1945 if (c
->first_timestamp
== AV_NOPTS_VALUE
&&
1946 pls
->pkt
.dts
!= AV_NOPTS_VALUE
)
1947 c
->first_timestamp
= av_rescale_q(pls
->pkt
.dts
,
1948 get_timebase(pls
), AV_TIME_BASE_Q
);
1951 if (pls
->seek_timestamp
== AV_NOPTS_VALUE
)
1954 if (pls
->seek_stream_index
< 0 ||
1955 pls
->seek_stream_index
== pls
->pkt
.stream_index
) {
1957 if (pls
->pkt
.dts
== AV_NOPTS_VALUE
) {
1958 pls
->seek_timestamp
= AV_NOPTS_VALUE
;
1962 tb
= get_timebase(pls
);
1963 ts_diff
= av_rescale_rnd(pls
->pkt
.dts
, AV_TIME_BASE
,
1964 tb
.den
, AV_ROUND_DOWN
) -
1965 pls
->seek_timestamp
;
1966 if (ts_diff
>= 0 && (pls
->seek_flags
& AVSEEK_FLAG_ANY
||
1967 pls
->pkt
.flags
& AV_PKT_FLAG_KEY
)) {
1968 pls
->seek_timestamp
= AV_NOPTS_VALUE
;
1972 av_packet_unref(&pls
->pkt
);
1973 reset_packet(&pls
->pkt
);
1976 /* Check if this stream has the packet with the lowest dts */
1977 if (pls
->pkt
.data
) {
1978 struct playlist
*minpls
= minplaylist
< 0 ?
1979 NULL
: c
->playlists
[minplaylist
];
1980 if (minplaylist
< 0) {
1983 int64_t dts
= pls
->pkt
.dts
;
1984 int64_t mindts
= minpls
->pkt
.dts
;
1986 if (dts
== AV_NOPTS_VALUE
||
1987 (mindts
!= AV_NOPTS_VALUE
&& compare_ts_with_wrapdetect(dts
, pls
, mindts
, minpls
) < 0))
1993 /* If we got a packet, return it */
1994 if (minplaylist
>= 0) {
1995 struct playlist
*pls
= c
->playlists
[minplaylist
];
1999 ret
= update_streams_from_subdemuxer(s
, pls
);
2001 av_packet_unref(&pls
->pkt
);
2002 reset_packet(&pls
->pkt
);
2006 /* check if noheader flag has been cleared by the subdemuxer */
2007 if (pls
->has_noheader_flag
&& !(pls
->ctx
->ctx_flags
& AVFMTCTX_NOHEADER
)) {
2008 pls
->has_noheader_flag
= 0;
2009 update_noheader_flag(s
);
2012 if (pls
->pkt
.stream_index
>= pls
->n_main_streams
) {
2013 av_log(s
, AV_LOG_ERROR
, "stream index inconsistency: index %d, %d main streams, %d subdemuxer streams\n",
2014 pls
->pkt
.stream_index
, pls
->n_main_streams
, pls
->ctx
->nb_streams
);
2015 av_packet_unref(&pls
->pkt
);
2016 reset_packet(&pls
->pkt
);
2020 ist
= pls
->ctx
->streams
[pls
->pkt
.stream_index
];
2021 st
= pls
->main_streams
[pls
->pkt
.stream_index
];
2024 pkt
->stream_index
= st
->index
;
2025 reset_packet(&c
->playlists
[minplaylist
]->pkt
);
2027 if (pkt
->dts
!= AV_NOPTS_VALUE
)
2028 c
->cur_timestamp
= av_rescale_q(pkt
->dts
,
2032 /* There may be more situations where this would be useful, but this at least
2033 * handles newly probed codecs properly (i.e. request_probe by mpegts). */
2034 if (ist
->codecpar
->codec_id
!= st
->codecpar
->codec_id
) {
2035 ret
= set_stream_info_from_input_stream(st
, pls
, ist
);
2037 av_packet_unref(pkt
);
2047 static int hls_close(AVFormatContext
*s
)
2049 HLSContext
*c
= s
->priv_data
;
2051 free_playlist_list(c
);
2052 free_variant_list(c
);
2053 free_rendition_list(c
);
2055 av_dict_free(&c
->avio_opts
);
2060 static int hls_read_seek(AVFormatContext
*s
, int stream_index
,
2061 int64_t timestamp
, int flags
)
2063 HLSContext
*c
= s
->priv_data
;
2064 struct playlist
*seek_pls
= NULL
;
2067 int stream_subdemuxer_index
;
2068 int64_t first_timestamp
, seek_timestamp
, duration
;
2070 if ((flags
& AVSEEK_FLAG_BYTE
) ||
2071 !(c
->variants
[0]->playlists
[0]->finished
|| c
->variants
[0]->playlists
[0]->type
== PLS_TYPE_EVENT
))
2072 return AVERROR(ENOSYS
);
2074 first_timestamp
= c
->first_timestamp
== AV_NOPTS_VALUE
?
2075 0 : c
->first_timestamp
;
2077 seek_timestamp
= av_rescale_rnd(timestamp
, AV_TIME_BASE
,
2078 s
->streams
[stream_index
]->time_base
.den
,
2079 flags
& AVSEEK_FLAG_BACKWARD
?
2080 AV_ROUND_DOWN
: AV_ROUND_UP
);
2082 duration
= s
->duration
== AV_NOPTS_VALUE
?
2085 if (0 < duration
&& duration
< seek_timestamp
- first_timestamp
)
2086 return AVERROR(EIO
);
2088 /* find the playlist with the specified stream */
2089 for (i
= 0; i
< c
->n_playlists
; i
++) {
2090 struct playlist
*pls
= c
->playlists
[i
];
2091 for (j
= 0; j
< pls
->n_main_streams
; j
++) {
2092 if (pls
->main_streams
[j
] == s
->streams
[stream_index
]) {
2094 stream_subdemuxer_index
= j
;
2099 /* check if the timestamp is valid for the playlist with the
2100 * specified stream index */
2101 if (!seek_pls
|| !find_timestamp_in_playlist(c
, seek_pls
, seek_timestamp
, &seq_no
))
2102 return AVERROR(EIO
);
2104 /* set segment now so we do not need to search again below */
2105 seek_pls
->cur_seq_no
= seq_no
;
2106 seek_pls
->seek_stream_index
= stream_subdemuxer_index
;
2108 for (i
= 0; i
< c
->n_playlists
; i
++) {
2110 struct playlist
*pls
= c
->playlists
[i
];
2112 ff_format_io_close(pls
->parent
, &pls
->input
);
2113 av_packet_unref(&pls
->pkt
);
2114 reset_packet(&pls
->pkt
);
2115 pls
->pb
.eof_reached
= 0;
2116 /* Clear any buffered data */
2117 pls
->pb
.buf_end
= pls
->pb
.buf_ptr
= pls
->pb
.buffer
;
2118 /* Reset the pos, to let the mpegts demuxer know we've seeked. */
2120 /* Flush the packet queue of the subdemuxer. */
2121 ff_read_frame_flush(pls
->ctx
);
2123 pls
->seek_timestamp
= seek_timestamp
;
2124 pls
->seek_flags
= flags
;
2126 if (pls
!= seek_pls
) {
2127 /* set closest segment seq_no for playlists not handled above */
2128 find_timestamp_in_playlist(c
, pls
, seek_timestamp
, &pls
->cur_seq_no
);
2129 /* seek the playlist to the given position without taking
2130 * keyframes into account since this playlist does not have the
2131 * specified stream where we should look for the keyframes */
2132 pls
->seek_stream_index
= -1;
2133 pls
->seek_flags
|= AVSEEK_FLAG_ANY
;
2137 c
->cur_timestamp
= seek_timestamp
;
2142 static int hls_probe(AVProbeData
*p
)
2144 /* Require #EXTM3U at the start, and either one of the ones below
2145 * somewhere for a proper match. */
2146 if (strncmp(p
->buf
, "#EXTM3U", 7))
2149 if (strstr(p
->buf
, "#EXT-X-STREAM-INF:") ||
2150 strstr(p
->buf
, "#EXT-X-TARGETDURATION:") ||
2151 strstr(p
->buf
, "#EXT-X-MEDIA-SEQUENCE:"))
2152 return AVPROBE_SCORE_MAX
;
2156 #define OFFSET(x) offsetof(HLSContext, x)
2157 #define FLAGS AV_OPT_FLAG_DECODING_PARAM
2158 static const AVOption hls_options
[] = {
2159 {"live_start_index", "segment index to start live streams at (negative values are from the end)",
2160 OFFSET(live_start_index
), AV_OPT_TYPE_INT
, {.i64
= -3}, INT_MIN
, INT_MAX
, FLAGS
},
2161 {"allowed_extensions", "List of file extensions that hls is allowed to access",
2162 OFFSET(allowed_extensions
), AV_OPT_TYPE_STRING
,
2163 {.str
= "3gp,aac,avi,flac,mkv,m3u8,m4a,m4s,m4v,mpg,mov,mp2,mp3,mp4,mpeg,mpegts,ogg,ogv,oga,ts,vob,wav"},
2164 INT_MIN
, INT_MAX
, FLAGS
},
2165 {"max_reload", "Maximum number of times a insufficient list is attempted to be reloaded",
2166 OFFSET(max_reload
), AV_OPT_TYPE_INT
, {.i64
= 1000}, 0, INT_MAX
, FLAGS
},
2170 static const AVClass hls_class
= {
2171 .class_name
= "hls,applehttp",
2172 .item_name
= av_default_item_name
,
2173 .option
= hls_options
,
2174 .version
= LIBAVUTIL_VERSION_INT
,
2177 AVInputFormat ff_hls_demuxer
= {
2178 .name
= "hls,applehttp",
2179 .long_name
= NULL_IF_CONFIG_SMALL("Apple HTTP Live Streaming"),
2180 .priv_class
= &hls_class
,
2181 .priv_data_size
= sizeof(HLSContext
),
2182 .read_probe
= hls_probe
,
2183 .read_header
= hls_read_header
,
2184 .read_packet
= hls_read_packet
,
2185 .read_close
= hls_close
,
2186 .read_seek
= hls_read_seek
,