2 * Apple HTTP Live Streaming demuxer
3 * Copyright (c) 2010 Martin Storsjo
4 * Copyright (c) 2013 Anssi Hannula
5 * Copyright (c) 2021 Nachiket Tarate
7 * This file is part of FFmpeg.
9 * FFmpeg is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * FFmpeg is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with FFmpeg; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
26 * Apple HTTP Live Streaming demuxer
27 * https://www.rfc-editor.org/rfc/rfc8216.txt
30 #include "config_components.h"
32 #include "libavformat/http.h"
33 #include "libavutil/aes.h"
34 #include "libavutil/avstring.h"
35 #include "libavutil/avassert.h"
36 #include "libavutil/intreadwrite.h"
37 #include "libavutil/mathematics.h"
38 #include "libavutil/mem.h"
39 #include "libavutil/opt.h"
40 #include "libavutil/dict.h"
41 #include "libavutil/time.h"
45 #include "avio_internal.h"
49 #include "hls_sample_encryption.h"
51 #define INITIAL_BUFFER_SIZE 32768
53 #define MAX_FIELD_LEN 64
54 #define MAX_CHARACTERISTICS_LEN 512
56 #define MPEG_TIME_BASE 90000
57 #define MPEG_TIME_BASE_Q (AVRational){1, MPEG_TIME_BASE}
60 * An apple http stream consists of a playlist with media segment files,
61 * played sequentially. There may be several playlists with the same
62 * video content, in different bandwidth variants, that are played in
63 * parallel (preferably only one bandwidth variant at a time). In this case,
64 * the user supplied the url to a main playlist that only lists the variant
67 * If the main playlist doesn't point at any variants, we still create
68 * one anonymous toplevel variant for this, to maintain the structure.
83 enum KeyType key_type
;
85 /* associated Media Initialization Section, treated as a segment */
86 struct segment
*init_section
;
98 * Each playlist has its own demuxer. If it currently is active,
99 * it has an open AVIOContext too, and potentially an AVPacket
100 * containing the next packet from this stream.
103 char url
[MAX_URL_SIZE
];
105 uint8_t* read_buffer
;
108 AVIOContext
*input_next
;
109 int input_next_requested
;
110 AVFormatContext
*parent
;
112 AVFormatContext
*ctx
;
114 int has_noheader_flag
;
116 /* main demuxer streams associated with this playlist
117 * indexed by the subdemuxer stream indexes */
118 AVStream
**main_streams
;
122 enum PlaylistType type
;
123 int64_t target_duration
;
124 int64_t start_seq_no
;
125 int time_offset_flag
;
126 int64_t start_time_offset
;
128 struct segment
**segments
;
133 int m3u8_hold_counters
;
134 int64_t cur_seg_offset
;
135 int64_t last_load_time
;
137 /* Currently active Media Initialization Section */
138 struct segment
*cur_init_section
;
139 uint8_t *init_sec_buf
;
140 unsigned int init_sec_buf_size
;
141 unsigned int init_sec_data_len
;
142 unsigned int init_sec_buf_read_offset
;
144 char key_url
[MAX_URL_SIZE
];
147 /* ID3 timestamp handling (elementary audio streams have ID3 timestamps
148 * (and possibly other ID3 tags) in the beginning of each segment) */
149 int is_id3_timestamped
; /* -1: not yet known */
150 int64_t id3_mpegts_timestamp
; /* in mpegts tb */
151 int64_t id3_offset
; /* in stream original tb */
152 uint8_t* id3_buf
; /* temp buffer for id3 parsing */
153 unsigned int id3_buf_size
;
154 AVDictionary
*id3_initial
; /* data from first id3 tag */
155 int id3_found
; /* ID3 tag found at some point */
156 int id3_changed
; /* ID3 tag data has changed at some point */
157 ID3v2ExtraMeta
*id3_deferred_extra
; /* stored here until subdemuxer is opened */
159 HLSAudioSetupInfo audio_setup_info
;
161 int64_t seek_timestamp
;
163 int seek_stream_index
; /* into subdemuxer stream array */
165 /* Renditions associated with this playlist, if any.
166 * Alternative rendition playlists have a single rendition associated
167 * with them, and variant main Media Playlists may have
168 * multiple (playlist-less) renditions associated with them. */
170 struct rendition
**renditions
;
172 /* Media Initialization Sections (EXT-X-MAP) associated with this
173 * playlist, if any. */
175 struct segment
**init_sections
;
176 int is_subtitle
; /* Indicates if it's a subtitle playlist */
180 * Renditions are e.g. alternative subtitle or audio streams.
181 * The rendition may either be an external playlist or it may be
182 * contained in the main Media Playlist of the variant (in which case
186 enum AVMediaType type
;
187 struct playlist
*playlist
;
188 char group_id
[MAX_FIELD_LEN
];
189 char language
[MAX_FIELD_LEN
];
190 char name
[MAX_FIELD_LEN
];
197 /* every variant contains at least the main Media Playlist in index 0 */
199 struct playlist
**playlists
;
201 char audio_group
[MAX_FIELD_LEN
];
202 char video_group
[MAX_FIELD_LEN
];
203 char subtitles_group
[MAX_FIELD_LEN
];
206 typedef struct HLSContext
{
208 AVFormatContext
*ctx
;
210 struct variant
**variants
;
212 struct playlist
**playlists
;
214 struct rendition
**renditions
;
217 int m3u8_hold_counters
;
218 int live_start_index
;
221 int64_t first_timestamp
;
222 int64_t cur_timestamp
;
223 AVIOInterruptCB
*interrupt_callback
;
224 AVDictionary
*avio_opts
;
225 AVDictionary
*seg_format_opts
;
226 char *allowed_extensions
;
227 char *allowed_segment_extensions
;
234 AVIOContext
*playlist_pb
;
235 HLSCryptoContext crypto_ctx
;
238 static void free_segment_dynarray(struct segment
**segments
, int n_segments
)
241 for (i
= 0; i
< n_segments
; i
++) {
242 av_freep(&segments
[i
]->key
);
243 av_freep(&segments
[i
]->url
);
244 av_freep(&segments
[i
]);
248 static void free_segment_list(struct playlist
*pls
)
250 free_segment_dynarray(pls
->segments
, pls
->n_segments
);
251 av_freep(&pls
->segments
);
255 static void free_init_section_list(struct playlist
*pls
)
258 for (i
= 0; i
< pls
->n_init_sections
; i
++) {
259 av_freep(&pls
->init_sections
[i
]->key
);
260 av_freep(&pls
->init_sections
[i
]->url
);
261 av_freep(&pls
->init_sections
[i
]);
263 av_freep(&pls
->init_sections
);
264 pls
->n_init_sections
= 0;
267 static void free_playlist_list(HLSContext
*c
)
270 for (i
= 0; i
< c
->n_playlists
; i
++) {
271 struct playlist
*pls
= c
->playlists
[i
];
272 free_segment_list(pls
);
273 free_init_section_list(pls
);
274 av_freep(&pls
->main_streams
);
275 av_freep(&pls
->renditions
);
276 av_freep(&pls
->id3_buf
);
277 av_dict_free(&pls
->id3_initial
);
278 ff_id3v2_free_extra_meta(&pls
->id3_deferred_extra
);
279 av_freep(&pls
->init_sec_buf
);
280 av_packet_free(&pls
->pkt
);
281 av_freep(&pls
->pb
.pub
.buffer
);
282 ff_format_io_close(c
->ctx
, &pls
->input
);
283 pls
->input_read_done
= 0;
284 ff_format_io_close(c
->ctx
, &pls
->input_next
);
285 pls
->input_next_requested
= 0;
288 avformat_close_input(&pls
->ctx
);
292 av_freep(&c
->playlists
);
296 static void free_variant_list(HLSContext
*c
)
299 for (i
= 0; i
< c
->n_variants
; i
++) {
300 struct variant
*var
= c
->variants
[i
];
301 av_freep(&var
->playlists
);
304 av_freep(&c
->variants
);
308 static void free_rendition_list(HLSContext
*c
)
311 for (i
= 0; i
< c
->n_renditions
; i
++)
312 av_freep(&c
->renditions
[i
]);
313 av_freep(&c
->renditions
);
317 static struct playlist
*new_playlist(HLSContext
*c
, const char *url
,
320 struct playlist
*pls
= av_mallocz(sizeof(struct playlist
));
323 pls
->pkt
= av_packet_alloc();
328 ff_make_absolute_url(pls
->url
, sizeof(pls
->url
), base
, url
);
330 av_packet_free(&pls
->pkt
);
334 pls
->seek_timestamp
= AV_NOPTS_VALUE
;
336 pls
->is_id3_timestamped
= -1;
337 pls
->id3_mpegts_timestamp
= AV_NOPTS_VALUE
;
339 dynarray_add(&c
->playlists
, &c
->n_playlists
, pls
);
343 struct variant_info
{
345 /* variant group ids: */
346 char audio
[MAX_FIELD_LEN
];
347 char video
[MAX_FIELD_LEN
];
348 char subtitles
[MAX_FIELD_LEN
];
351 static struct variant
*new_variant(HLSContext
*c
, struct variant_info
*info
,
352 const char *url
, const char *base
)
355 struct playlist
*pls
;
357 pls
= new_playlist(c
, url
, base
);
361 var
= av_mallocz(sizeof(struct variant
));
366 var
->bandwidth
= atoi(info
->bandwidth
);
367 strcpy(var
->audio_group
, info
->audio
);
368 strcpy(var
->video_group
, info
->video
);
369 strcpy(var
->subtitles_group
, info
->subtitles
);
372 dynarray_add(&c
->variants
, &c
->n_variants
, var
);
373 dynarray_add(&var
->playlists
, &var
->n_playlists
, pls
);
377 static void handle_variant_args(struct variant_info
*info
, const char *key
,
378 int key_len
, char **dest
, int *dest_len
)
380 if (!strncmp(key
, "BANDWIDTH=", key_len
)) {
381 *dest
= info
->bandwidth
;
382 *dest_len
= sizeof(info
->bandwidth
);
383 } else if (!strncmp(key
, "AUDIO=", key_len
)) {
385 *dest_len
= sizeof(info
->audio
);
386 } else if (!strncmp(key
, "VIDEO=", key_len
)) {
388 *dest_len
= sizeof(info
->video
);
389 } else if (!strncmp(key
, "SUBTITLES=", key_len
)) {
390 *dest
= info
->subtitles
;
391 *dest_len
= sizeof(info
->subtitles
);
396 char uri
[MAX_URL_SIZE
];
401 static void handle_key_args(struct key_info
*info
, const char *key
,
402 int key_len
, char **dest
, int *dest_len
)
404 if (!strncmp(key
, "METHOD=", key_len
)) {
405 *dest
= info
->method
;
406 *dest_len
= sizeof(info
->method
);
407 } else if (!strncmp(key
, "URI=", key_len
)) {
409 *dest_len
= sizeof(info
->uri
);
410 } else if (!strncmp(key
, "IV=", key_len
)) {
412 *dest_len
= sizeof(info
->iv
);
416 struct init_section_info
{
417 char uri
[MAX_URL_SIZE
];
421 static struct segment
*new_init_section(struct playlist
*pls
,
422 struct init_section_info
*info
,
423 const char *url_base
)
426 char tmp_str
[MAX_URL_SIZE
], *ptr
= tmp_str
;
431 sec
= av_mallocz(sizeof(*sec
));
435 if (!av_strncasecmp(info
->uri
, "data:", 5)) {
438 ff_make_absolute_url(tmp_str
, sizeof(tmp_str
), url_base
, info
->uri
);
444 sec
->url
= av_strdup(ptr
);
450 if (info
->byterange
[0]) {
451 sec
->size
= strtoll(info
->byterange
, NULL
, 10);
452 ptr
= strchr(info
->byterange
, '@');
454 sec
->url_offset
= strtoll(ptr
+1, NULL
, 10);
456 /* the entire file is the init section */
460 dynarray_add(&pls
->init_sections
, &pls
->n_init_sections
, sec
);
465 static void handle_init_section_args(void *context
, const char *key
,
466 int key_len
, char **dest
, int *dest_len
)
468 struct init_section_info
*info
= context
;
469 if (!strncmp(key
, "URI=", key_len
)) {
471 *dest_len
= sizeof(info
->uri
);
472 } else if (!strncmp(key
, "BYTERANGE=", key_len
)) {
473 *dest
= info
->byterange
;
474 *dest_len
= sizeof(info
->byterange
);
478 struct rendition_info
{
480 char uri
[MAX_URL_SIZE
];
481 char group_id
[MAX_FIELD_LEN
];
482 char language
[MAX_FIELD_LEN
];
483 char assoc_language
[MAX_FIELD_LEN
];
484 char name
[MAX_FIELD_LEN
];
487 char characteristics
[MAX_CHARACTERISTICS_LEN
];
490 static struct rendition
*new_rendition(HLSContext
*c
, struct rendition_info
*info
,
491 const char *url_base
)
493 struct rendition
*rend
;
494 enum AVMediaType type
= AVMEDIA_TYPE_UNKNOWN
;
495 char *characteristic
;
499 if (!strcmp(info
->type
, "AUDIO"))
500 type
= AVMEDIA_TYPE_AUDIO
;
501 else if (!strcmp(info
->type
, "VIDEO"))
502 type
= AVMEDIA_TYPE_VIDEO
;
503 else if (!strcmp(info
->type
, "SUBTITLES"))
504 type
= AVMEDIA_TYPE_SUBTITLE
;
505 else if (!strcmp(info
->type
, "CLOSED-CAPTIONS"))
506 /* CLOSED-CAPTIONS is ignored since we do not support CEA-608 CC in
507 * AVC SEI RBSP anyway */
510 if (type
== AVMEDIA_TYPE_UNKNOWN
) {
511 av_log(c
->ctx
, AV_LOG_WARNING
, "Can't support the type: %s\n", info
->type
);
515 /* URI is mandatory for subtitles as per spec */
516 if (type
== AVMEDIA_TYPE_SUBTITLE
&& !info
->uri
[0]) {
517 av_log(c
->ctx
, AV_LOG_ERROR
, "The URI tag is REQUIRED for subtitle.\n");
521 rend
= av_mallocz(sizeof(struct rendition
));
525 dynarray_add(&c
->renditions
, &c
->n_renditions
, rend
);
528 strcpy(rend
->group_id
, info
->group_id
);
529 strcpy(rend
->language
, info
->language
);
530 strcpy(rend
->name
, info
->name
);
532 /* add the playlist if this is an external rendition */
534 rend
->playlist
= new_playlist(c
, info
->uri
, url_base
);
535 if (rend
->playlist
) {
536 if (type
== AVMEDIA_TYPE_SUBTITLE
) {
537 rend
->playlist
->is_subtitle
= 1;
538 rend
->playlist
->is_id3_timestamped
= 0;
540 dynarray_add(&rend
->playlist
->renditions
,
541 &rend
->playlist
->n_renditions
, rend
);
545 if (info
->assoc_language
[0]) {
546 size_t langlen
= strlen(rend
->language
);
547 if (langlen
< sizeof(rend
->language
) - 3) {
549 rend
->language
[langlen
] = ',';
550 assoc_len
= av_strlcpy(rend
->language
+ langlen
+ 1,
551 info
->assoc_language
,
552 sizeof(rend
->language
) - langlen
- 1);
553 if (langlen
+ assoc_len
+ 2 > sizeof(rend
->language
)) // truncation occurred
554 av_log(c
->ctx
, AV_LOG_WARNING
, "Truncated rendition language: %s\n",
555 info
->assoc_language
);
559 if (!strcmp(info
->defaultr
, "YES"))
560 rend
->disposition
|= AV_DISPOSITION_DEFAULT
;
561 if (!strcmp(info
->forced
, "YES"))
562 rend
->disposition
|= AV_DISPOSITION_FORCED
;
564 chr_ptr
= info
->characteristics
;
565 while ((characteristic
= av_strtok(chr_ptr
, ",", &saveptr
))) {
566 if (!strcmp(characteristic
, "public.accessibility.describes-music-and-sound"))
567 rend
->disposition
|= AV_DISPOSITION_HEARING_IMPAIRED
;
568 else if (!strcmp(characteristic
, "public.accessibility.describes-video"))
569 rend
->disposition
|= AV_DISPOSITION_VISUAL_IMPAIRED
;
577 static void handle_rendition_args(struct rendition_info
*info
, const char *key
,
578 int key_len
, char **dest
, int *dest_len
)
580 if (!strncmp(key
, "TYPE=", key_len
)) {
582 *dest_len
= sizeof(info
->type
);
583 } else if (!strncmp(key
, "URI=", key_len
)) {
585 *dest_len
= sizeof(info
->uri
);
586 } else if (!strncmp(key
, "GROUP-ID=", key_len
)) {
587 *dest
= info
->group_id
;
588 *dest_len
= sizeof(info
->group_id
);
589 } else if (!strncmp(key
, "LANGUAGE=", key_len
)) {
590 *dest
= info
->language
;
591 *dest_len
= sizeof(info
->language
);
592 } else if (!strncmp(key
, "ASSOC-LANGUAGE=", key_len
)) {
593 *dest
= info
->assoc_language
;
594 *dest_len
= sizeof(info
->assoc_language
);
595 } else if (!strncmp(key
, "NAME=", key_len
)) {
597 *dest_len
= sizeof(info
->name
);
598 } else if (!strncmp(key
, "DEFAULT=", key_len
)) {
599 *dest
= info
->defaultr
;
600 *dest_len
= sizeof(info
->defaultr
);
601 } else if (!strncmp(key
, "FORCED=", key_len
)) {
602 *dest
= info
->forced
;
603 *dest_len
= sizeof(info
->forced
);
604 } else if (!strncmp(key
, "CHARACTERISTICS=", key_len
)) {
605 *dest
= info
->characteristics
;
606 *dest_len
= sizeof(info
->characteristics
);
610 * - AUTOSELECT: client may autoselect based on e.g. system language
611 * - INSTREAM-ID: EIA-608 closed caption number ("CC1".."CC4")
615 /* used by parse_playlist to allocate a new variant+playlist when the
616 * playlist is detected to be a Media Playlist (not Master Playlist)
617 * and we have no parent Master Playlist (parsing of which would have
618 * allocated the variant and playlist already)
619 * *pls == NULL => Master Playlist or parentless Media Playlist
620 * *pls != NULL => parented Media Playlist, playlist+variant allocated */
621 static int ensure_playlist(HLSContext
*c
, struct playlist
**pls
, const char *url
)
625 if (!new_variant(c
, NULL
, url
, NULL
))
626 return AVERROR(ENOMEM
);
627 *pls
= c
->playlists
[c
->n_playlists
- 1];
631 static int open_url_keepalive(AVFormatContext
*s
, AVIOContext
**pb
,
632 const char *url
, AVDictionary
**options
)
634 #if !CONFIG_HTTP_PROTOCOL
635 return AVERROR_PROTOCOL_NOT_FOUND
;
638 URLContext
*uc
= ffio_geturlcontext(*pb
);
640 (*pb
)->eof_reached
= 0;
641 ret
= ff_http_do_new_request2(uc
, url
, options
);
643 ff_format_io_close(s
, pb
);
649 static int open_url(AVFormatContext
*s
, AVIOContext
**pb
, const char *url
,
650 AVDictionary
**opts
, AVDictionary
*opts2
, int *is_http_out
)
652 HLSContext
*c
= s
->priv_data
;
653 AVDictionary
*tmp
= NULL
;
654 const char *proto_name
= NULL
;
658 if (av_strstart(url
, "crypto", NULL
)) {
659 if (url
[6] == '+' || url
[6] == ':')
660 proto_name
= avio_find_protocol_name(url
+ 7);
661 } else if (av_strstart(url
, "data", NULL
)) {
662 if (url
[4] == '+' || url
[4] == ':')
663 proto_name
= avio_find_protocol_name(url
+ 5);
667 proto_name
= avio_find_protocol_name(url
);
670 return AVERROR_INVALIDDATA
;
672 // only http(s) & file are allowed
673 if (av_strstart(proto_name
, "file", NULL
)) {
674 if (strcmp(c
->allowed_extensions
, "ALL") && !av_match_ext(url
, c
->allowed_extensions
)) {
675 av_log(s
, AV_LOG_ERROR
,
676 "Filename extension of \'%s\' is not a common multimedia extension, blocked for security reasons.\n"
677 "If you wish to override this adjust allowed_extensions, you can set it to \'ALL\' to allow all\n",
679 return AVERROR_INVALIDDATA
;
681 } else if (av_strstart(proto_name
, "http", NULL
)) {
683 } else if (av_strstart(proto_name
, "data", NULL
)) {
686 return AVERROR_INVALIDDATA
;
688 if (!strncmp(proto_name
, url
, strlen(proto_name
)) && url
[strlen(proto_name
)] == ':')
690 else if (av_strstart(url
, "crypto", NULL
) && !strncmp(proto_name
, url
+ 7, strlen(proto_name
)) && url
[7 + strlen(proto_name
)] == ':')
692 else if (av_strstart(url
, "data", NULL
) && !strncmp(proto_name
, url
+ 5, strlen(proto_name
)) && url
[5 + strlen(proto_name
)] == ':')
694 else if (strcmp(proto_name
, "file") || !strncmp(url
, "file,", 5))
695 return AVERROR_INVALIDDATA
;
697 av_dict_copy(&tmp
, *opts
, 0);
698 av_dict_copy(&tmp
, opts2
, 0);
700 if (is_http
&& c
->http_persistent
&& *pb
) {
701 ret
= open_url_keepalive(c
->ctx
, pb
, url
, &tmp
);
702 if (ret
== AVERROR_EXIT
) {
705 } else if (ret
< 0) {
706 if (ret
!= AVERROR_EOF
)
707 av_log(s
, AV_LOG_WARNING
,
708 "keepalive request failed for '%s' with error: '%s' when opening url, retrying with new connection\n",
709 url
, av_err2str(ret
));
710 av_dict_copy(&tmp
, *opts
, 0);
711 av_dict_copy(&tmp
, opts2
, 0);
712 ret
= s
->io_open(s
, pb
, url
, AVIO_FLAG_READ
, &tmp
);
715 ret
= s
->io_open(s
, pb
, url
, AVIO_FLAG_READ
, &tmp
);
718 // update cookies on http response with setcookies.
719 char *new_cookies
= NULL
;
721 if (!(s
->flags
& AVFMT_FLAG_CUSTOM_IO
))
722 av_opt_get(*pb
, "cookies", AV_OPT_SEARCH_CHILDREN
, (uint8_t**)&new_cookies
);
725 av_dict_set(opts
, "cookies", new_cookies
, AV_DICT_DONT_STRDUP_VAL
);
731 *is_http_out
= is_http
;
736 static int test_segment(AVFormatContext
*s
, const AVInputFormat
*in_fmt
, struct playlist
*pls
, struct segment
*seg
)
738 HLSContext
*c
= s
->priv_data
;
742 if (!c
->extension_picky
)
745 if (strcmp(c
->allowed_segment_extensions
, "ALL"))
746 matchA
= av_match_ext (seg
->url
, c
->allowed_segment_extensions
)
747 + 2*(ff_match_url_ext(seg
->url
, c
->allowed_segment_extensions
) > 0);
750 av_log(s
, AV_LOG_ERROR
, "URL %s is not in allowed_segment_extensions, consider updating hls.c and submitting a patch to ffmpeg-devel, if this should be added\n", seg
->url
);
751 return AVERROR_INVALIDDATA
;
755 if (in_fmt
->extensions
) {
756 matchF
= av_match_ext( seg
->url
, in_fmt
->extensions
)
757 + 2*(ff_match_url_ext(seg
->url
, in_fmt
->extensions
) > 0);
758 // Youtube uses aac files with .ts extension
759 if(av_match_name("mp4", in_fmt
->name
) || av_match_name("aac", in_fmt
->name
)) {
760 matchF
|= av_match_ext( seg
->url
, "ts,m2t,m2ts,mts,mpg,m4s,mpeg,mpegts,cmfv,cmfa")
761 + 2*(ff_match_url_ext(seg
->url
, "ts,m2t,m2ts,mts,mpg,m4s,mpeg,mpegts,cmfv,cmfa") > 0);
763 } else if (!strcmp(in_fmt
->name
, "mpegts")) {
764 const char *str
= "ts,m2t,m2ts,mts,mpg,m4s,mpeg,mpegts"
765 ",html" // https://flash1.bogulus.cfd/
767 matchF
= av_match_ext( seg
->url
, str
)
768 + 2*(ff_match_url_ext(seg
->url
, str
) > 0);
769 } else if (!strcmp(in_fmt
->name
, "webvtt")) {
770 matchF
= av_match_ext( seg
->url
, "vtt,webvtt")
771 + 2*(ff_match_url_ext(seg
->url
, "vtt,webvtt") > 0);
774 if (!(matchA
& matchF
)) {
775 av_log(s
, AV_LOG_ERROR
, "detected format %s extension %s mismatches allowed extensions in url %s\n", in_fmt
->name
, in_fmt
->extensions
? in_fmt
->extensions
: "none", seg
->url
);
776 return AVERROR_INVALIDDATA
;
783 static int parse_playlist(HLSContext
*c
, const char *url
,
784 struct playlist
*pls
, AVIOContext
*in
)
786 int ret
= 0, is_segment
= 0, is_variant
= 0;
787 int64_t duration
= 0;
788 enum KeyType key_type
= KEY_NONE
;
791 char key
[MAX_URL_SIZE
] = "";
792 char line
[MAX_URL_SIZE
];
795 int64_t seg_offset
= 0;
796 int64_t seg_size
= -1;
797 uint8_t *new_url
= NULL
;
798 struct variant_info variant_info
;
799 char tmp_str
[MAX_URL_SIZE
];
800 struct segment
*cur_init_section
= NULL
;
801 int is_http
= av_strstart(url
, "http", NULL
);
802 struct segment
**prev_segments
= NULL
;
803 int prev_n_segments
= 0;
804 int64_t prev_start_seq_no
= -1;
806 if (is_http
&& !in
&& c
->http_persistent
&& c
->playlist_pb
) {
808 ret
= open_url_keepalive(c
->ctx
, &c
->playlist_pb
, url
, NULL
);
809 if (ret
== AVERROR_EXIT
) {
811 } else if (ret
< 0) {
812 if (ret
!= AVERROR_EOF
)
813 av_log(c
->ctx
, AV_LOG_WARNING
,
814 "keepalive request failed for '%s' with error: '%s' when parsing playlist\n",
815 url
, av_err2str(ret
));
821 AVDictionary
*opts
= NULL
;
822 av_dict_copy(&opts
, c
->avio_opts
, 0);
824 if (c
->http_persistent
)
825 av_dict_set(&opts
, "multiple_requests", "1", 0);
827 ret
= c
->ctx
->io_open(c
->ctx
, &in
, url
, AVIO_FLAG_READ
, &opts
);
832 if (is_http
&& c
->http_persistent
)
838 if (av_opt_get(in
, "location", AV_OPT_SEARCH_CHILDREN
, &new_url
) >= 0)
841 ff_get_chomp_line(in
, line
, sizeof(line
));
842 if (strcmp(line
, "#EXTM3U")) {
843 ret
= AVERROR_INVALIDDATA
;
848 prev_start_seq_no
= pls
->start_seq_no
;
849 prev_segments
= pls
->segments
;
850 prev_n_segments
= pls
->n_segments
;
851 pls
->segments
= NULL
;
855 pls
->type
= PLS_TYPE_UNSPECIFIED
;
857 while (!avio_feof(in
)) {
858 ff_get_chomp_line(in
, line
, sizeof(line
));
859 if (av_strstart(line
, "#EXT-X-STREAM-INF:", &ptr
)) {
861 memset(&variant_info
, 0, sizeof(variant_info
));
862 ff_parse_key_value(ptr
, (ff_parse_key_val_cb
) handle_variant_args
,
864 } else if (av_strstart(line
, "#EXT-X-KEY:", &ptr
)) {
865 struct key_info info
= {{0}};
866 ff_parse_key_value(ptr
, (ff_parse_key_val_cb
) handle_key_args
,
870 if (!strcmp(info
.method
, "AES-128"))
871 key_type
= KEY_AES_128
;
872 if (!strcmp(info
.method
, "SAMPLE-AES"))
873 key_type
= KEY_SAMPLE_AES
;
874 if (!av_strncasecmp(info
.iv
, "0x", 2)) {
875 ff_hex_to_data(iv
, info
.iv
+ 2);
878 av_strlcpy(key
, info
.uri
, sizeof(key
));
879 } else if (av_strstart(line
, "#EXT-X-MEDIA:", &ptr
)) {
880 struct rendition_info info
= {{0}};
881 ff_parse_key_value(ptr
, (ff_parse_key_val_cb
) handle_rendition_args
,
883 new_rendition(c
, &info
, url
);
884 } else if (av_strstart(line
, "#EXT-X-TARGETDURATION:", &ptr
)) {
886 ret
= ensure_playlist(c
, &pls
, url
);
889 t
= strtoll(ptr
, NULL
, 10);
890 if (t
< 0 || t
>= INT64_MAX
/ AV_TIME_BASE
) {
891 ret
= AVERROR_INVALIDDATA
;
894 pls
->target_duration
= t
* AV_TIME_BASE
;
895 } else if (av_strstart(line
, "#EXT-X-MEDIA-SEQUENCE:", &ptr
)) {
897 ret
= ensure_playlist(c
, &pls
, url
);
900 seq_no
= strtoull(ptr
, NULL
, 10);
901 if (seq_no
> INT64_MAX
/2) {
902 av_log(c
->ctx
, AV_LOG_DEBUG
, "MEDIA-SEQUENCE higher than "
903 "INT64_MAX/2, mask out the highest bit\n");
904 seq_no
&= INT64_MAX
/2;
906 pls
->start_seq_no
= seq_no
;
907 } else if (av_strstart(line
, "#EXT-X-PLAYLIST-TYPE:", &ptr
)) {
908 ret
= ensure_playlist(c
, &pls
, url
);
911 if (!strcmp(ptr
, "EVENT"))
912 pls
->type
= PLS_TYPE_EVENT
;
913 else if (!strcmp(ptr
, "VOD"))
914 pls
->type
= PLS_TYPE_VOD
;
915 } else if (av_strstart(line
, "#EXT-X-MAP:", &ptr
)) {
916 struct init_section_info info
= {{0}};
917 ret
= ensure_playlist(c
, &pls
, url
);
920 ff_parse_key_value(ptr
, handle_init_section_args
, &info
);
921 cur_init_section
= new_init_section(pls
, &info
, url
);
922 if (!cur_init_section
) {
923 ret
= AVERROR(ENOMEM
);
926 cur_init_section
->key_type
= key_type
;
928 memcpy(cur_init_section
->iv
, iv
, sizeof(iv
));
930 int64_t seq
= pls
->start_seq_no
+ pls
->n_segments
;
931 memset(cur_init_section
->iv
, 0, sizeof(cur_init_section
->iv
));
932 AV_WB64(cur_init_section
->iv
+ 8, seq
);
935 if (key_type
!= KEY_NONE
) {
936 ff_make_absolute_url(tmp_str
, sizeof(tmp_str
), url
, key
);
938 av_free(cur_init_section
);
939 ret
= AVERROR_INVALIDDATA
;
942 cur_init_section
->key
= av_strdup(tmp_str
);
943 if (!cur_init_section
->key
) {
944 av_free(cur_init_section
);
945 ret
= AVERROR(ENOMEM
);
949 cur_init_section
->key
= NULL
;
952 } else if (av_strstart(line
, "#EXT-X-START:", &ptr
)) {
953 const char *time_offset_value
= NULL
;
954 ret
= ensure_playlist(c
, &pls
, url
);
958 if (av_strstart(ptr
, "TIME-OFFSET=", &time_offset_value
)) {
959 float offset
= strtof(time_offset_value
, NULL
);
960 pls
->start_time_offset
= offset
* AV_TIME_BASE
;
961 pls
->time_offset_flag
= 1;
963 av_log(c
->ctx
, AV_LOG_WARNING
, "#EXT-X-START value is"
964 "invalid, it will be ignored");
967 } else if (av_strstart(line
, "#EXT-X-ENDLIST", &ptr
)) {
970 } else if (av_strstart(line
, "#EXTINF:", &ptr
)) {
972 duration
= atof(ptr
) * AV_TIME_BASE
;
973 } else if (av_strstart(line
, "#EXT-X-BYTERANGE:", &ptr
)) {
974 seg_size
= strtoll(ptr
, NULL
, 10);
975 ptr
= strchr(ptr
, '@');
977 seg_offset
= strtoll(ptr
+1, NULL
, 10);
978 } else if (av_strstart(line
, "#", NULL
)) {
979 av_log(c
->ctx
, AV_LOG_VERBOSE
, "Skip ('%s')\n", line
);
981 } else if (line
[0]) {
983 if (!new_variant(c
, &variant_info
, line
, url
)) {
984 ret
= AVERROR(ENOMEM
);
991 ret
= ensure_playlist(c
, &pls
, url
);
994 seg
= av_malloc(sizeof(struct segment
));
996 ret
= AVERROR(ENOMEM
);
1000 memcpy(seg
->iv
, iv
, sizeof(iv
));
1002 uint64_t seq
= pls
->start_seq_no
+ (uint64_t)pls
->n_segments
;
1003 memset(seg
->iv
, 0, sizeof(seg
->iv
));
1004 AV_WB64(seg
->iv
+ 8, seq
);
1007 if (key_type
!= KEY_NONE
) {
1008 ff_make_absolute_url(tmp_str
, sizeof(tmp_str
), url
, key
);
1010 ret
= AVERROR_INVALIDDATA
;
1014 seg
->key
= av_strdup(tmp_str
);
1017 ret
= AVERROR(ENOMEM
);
1024 ff_make_absolute_url(tmp_str
, sizeof(tmp_str
), url
, line
);
1026 ret
= AVERROR_INVALIDDATA
;
1032 seg
->url
= av_strdup(tmp_str
);
1036 ret
= AVERROR(ENOMEM
);
1040 ret
= test_segment(c
->ctx
, pls
->ctx
? pls
->ctx
->iformat
: NULL
, pls
, seg
);
1048 if (duration
< 0.001 * AV_TIME_BASE
) {
1049 av_log(c
->ctx
, AV_LOG_WARNING
, "Cannot get correct #EXTINF value of segment %s,"
1050 " set to default value to 1ms.\n", seg
->url
);
1051 duration
= 0.001 * AV_TIME_BASE
;
1053 seg
->duration
= duration
;
1054 seg
->key_type
= key_type
;
1055 dynarray_add(&pls
->segments
, &pls
->n_segments
, seg
);
1058 seg
->size
= seg_size
;
1059 if (seg_size
>= 0) {
1060 seg
->url_offset
= seg_offset
;
1061 seg_offset
+= seg_size
;
1064 seg
->url_offset
= 0;
1068 seg
->init_section
= cur_init_section
;
1072 if (prev_segments
) {
1073 if (pls
->start_seq_no
> prev_start_seq_no
&& c
->first_timestamp
!= AV_NOPTS_VALUE
) {
1074 int64_t prev_timestamp
= c
->first_timestamp
;
1076 int64_t diff
= pls
->start_seq_no
- prev_start_seq_no
;
1077 for (i
= 0; i
< prev_n_segments
&& i
< diff
; i
++) {
1078 c
->first_timestamp
+= prev_segments
[i
]->duration
;
1080 av_log(c
->ctx
, AV_LOG_DEBUG
, "Media sequence change (%"PRId64
" -> %"PRId64
")"
1081 " reflected in first_timestamp: %"PRId64
" -> %"PRId64
"\n",
1082 prev_start_seq_no
, pls
->start_seq_no
,
1083 prev_timestamp
, c
->first_timestamp
);
1084 } else if (pls
->start_seq_no
< prev_start_seq_no
) {
1085 av_log(c
->ctx
, AV_LOG_WARNING
, "Media sequence changed unexpectedly: %"PRId64
" -> %"PRId64
"\n",
1086 prev_start_seq_no
, pls
->start_seq_no
);
1088 free_segment_dynarray(prev_segments
, prev_n_segments
);
1089 av_freep(&prev_segments
);
1092 pls
->last_load_time
= av_gettime_relative();
1097 ff_format_io_close(c
->ctx
, &in
);
1098 c
->ctx
->ctx_flags
= c
->ctx
->ctx_flags
& ~(unsigned)AVFMTCTX_UNSEEKABLE
;
1099 if (!c
->n_variants
|| !c
->variants
[0]->n_playlists
||
1100 !(c
->variants
[0]->playlists
[0]->finished
||
1101 c
->variants
[0]->playlists
[0]->type
== PLS_TYPE_EVENT
))
1102 c
->ctx
->ctx_flags
|= AVFMTCTX_UNSEEKABLE
;
1106 static struct segment
*current_segment(struct playlist
*pls
)
1108 int64_t n
= pls
->cur_seq_no
- pls
->start_seq_no
;
1109 if (n
>= pls
->n_segments
)
1111 return pls
->segments
[n
];
1114 static struct segment
*next_segment(struct playlist
*pls
)
1116 int64_t n
= pls
->cur_seq_no
- pls
->start_seq_no
+ 1;
1117 if (n
>= pls
->n_segments
)
1119 return pls
->segments
[n
];
1122 static int read_from_url(struct playlist
*pls
, struct segment
*seg
,
1123 uint8_t *buf
, int buf_size
)
1127 /* limit read if the segment was only a part of a file */
1129 buf_size
= FFMIN(buf_size
, seg
->size
- pls
->cur_seg_offset
);
1131 ret
= avio_read(pls
->input
, buf
, buf_size
);
1133 pls
->cur_seg_offset
+= ret
;
1138 /* Parse the raw ID3 data and pass contents to caller */
1139 static void parse_id3(AVFormatContext
*s
, AVIOContext
*pb
,
1140 AVDictionary
**metadata
, int64_t *dts
, HLSAudioSetupInfo
*audio_setup_info
,
1141 ID3v2ExtraMetaAPIC
**apic
, ID3v2ExtraMeta
**extra_meta
)
1143 static const char id3_priv_owner_ts
[] = "com.apple.streaming.transportStreamTimestamp";
1144 static const char id3_priv_owner_audio_setup
[] = "com.apple.streaming.audioDescription";
1145 ID3v2ExtraMeta
*meta
;
1147 ff_id3v2_read_dict(pb
, metadata
, ID3v2_DEFAULT_MAGIC
, extra_meta
);
1148 for (meta
= *extra_meta
; meta
; meta
= meta
->next
) {
1149 if (!strcmp(meta
->tag
, "PRIV")) {
1150 ID3v2ExtraMetaPRIV
*priv
= &meta
->data
.priv
;
1151 if (priv
->datasize
== 8 && !av_strncasecmp(priv
->owner
, id3_priv_owner_ts
, 44)) {
1152 /* 33-bit MPEG timestamp */
1153 int64_t ts
= AV_RB64(priv
->data
);
1154 av_log(s
, AV_LOG_DEBUG
, "HLS ID3 audio timestamp %"PRId64
"\n", ts
);
1155 if ((ts
& ~((1ULL << 33) - 1)) == 0)
1158 av_log(s
, AV_LOG_ERROR
, "Invalid HLS ID3 audio timestamp %"PRId64
"\n", ts
);
1159 } else if (priv
->datasize
>= 8 && !av_strncasecmp(priv
->owner
, id3_priv_owner_audio_setup
, 36)) {
1160 ff_hls_senc_read_audio_setup_info(audio_setup_info
, priv
->data
, priv
->datasize
);
1162 } else if (!strcmp(meta
->tag
, "APIC") && apic
)
1163 *apic
= &meta
->data
.apic
;
1167 /* Check if the ID3 metadata contents have changed */
1168 static int id3_has_changed_values(struct playlist
*pls
, AVDictionary
*metadata
,
1169 ID3v2ExtraMetaAPIC
*apic
)
1171 const AVDictionaryEntry
*entry
= NULL
;
1172 const AVDictionaryEntry
*oldentry
;
1173 /* check that no keys have changed values */
1174 while ((entry
= av_dict_iterate(metadata
, entry
))) {
1175 oldentry
= av_dict_get(pls
->id3_initial
, entry
->key
, NULL
, AV_DICT_MATCH_CASE
);
1176 if (!oldentry
|| strcmp(oldentry
->value
, entry
->value
) != 0)
1180 /* check if apic appeared */
1181 if (apic
&& (pls
->ctx
->nb_streams
!= 2 || !pls
->ctx
->streams
[1]->attached_pic
.data
))
1185 int size
= pls
->ctx
->streams
[1]->attached_pic
.size
;
1186 if (size
!= apic
->buf
->size
- AV_INPUT_BUFFER_PADDING_SIZE
)
1189 if (memcmp(apic
->buf
->data
, pls
->ctx
->streams
[1]->attached_pic
.data
, size
) != 0)
1196 /* Parse ID3 data and handle the found data */
1197 static void handle_id3(AVIOContext
*pb
, struct playlist
*pls
)
1199 AVDictionary
*metadata
= NULL
;
1200 ID3v2ExtraMetaAPIC
*apic
= NULL
;
1201 ID3v2ExtraMeta
*extra_meta
= NULL
;
1202 int64_t timestamp
= AV_NOPTS_VALUE
;
1204 parse_id3(pls
->ctx
, pb
, &metadata
, ×tamp
, &pls
->audio_setup_info
, &apic
, &extra_meta
);
1206 if (timestamp
!= AV_NOPTS_VALUE
) {
1207 pls
->id3_mpegts_timestamp
= timestamp
;
1208 pls
->id3_offset
= 0;
1211 if (!pls
->id3_found
) {
1212 /* initial ID3 tags */
1213 av_assert0(!pls
->id3_deferred_extra
);
1216 /* get picture attachment and set text metadata */
1217 if (pls
->ctx
->nb_streams
)
1218 ff_id3v2_parse_apic(pls
->ctx
, extra_meta
);
1220 /* demuxer not yet opened, defer picture attachment */
1221 pls
->id3_deferred_extra
= extra_meta
;
1223 ff_id3v2_parse_priv_dict(&metadata
, extra_meta
);
1224 av_dict_copy(&pls
->ctx
->metadata
, metadata
, 0);
1225 pls
->id3_initial
= metadata
;
1228 if (!pls
->id3_changed
&& id3_has_changed_values(pls
, metadata
, apic
)) {
1229 avpriv_report_missing_feature(pls
->parent
, "Changing ID3 metadata in HLS audio elementary stream");
1230 pls
->id3_changed
= 1;
1232 av_dict_free(&metadata
);
1235 if (!pls
->id3_deferred_extra
)
1236 ff_id3v2_free_extra_meta(&extra_meta
);
1239 static void intercept_id3(struct playlist
*pls
, uint8_t *buf
,
1240 int buf_size
, int *len
)
1242 /* intercept id3 tags, we do not want to pass them to the raw
1243 * demuxer on all segment switches */
1245 int id3_buf_pos
= 0;
1247 struct segment
*seg
= current_segment(pls
);
1249 /* gather all the id3 tags */
1251 /* see if we can retrieve enough data for ID3 header */
1252 if (*len
< ID3v2_HEADER_SIZE
&& buf_size
>= ID3v2_HEADER_SIZE
) {
1253 bytes
= read_from_url(pls
, seg
, buf
+ *len
, ID3v2_HEADER_SIZE
- *len
);
1256 if (bytes
== ID3v2_HEADER_SIZE
- *len
)
1257 /* no EOF yet, so fill the caller buffer again after
1258 * we have stripped the ID3 tags */
1263 } else if (*len
<= 0) {
1270 if (*len
< ID3v2_HEADER_SIZE
)
1273 if (ff_id3v2_match(buf
, ID3v2_DEFAULT_MAGIC
)) {
1274 int64_t maxsize
= seg
->size
>= 0 ? seg
->size
: 1024*1024;
1275 int taglen
= ff_id3v2_tag_len(buf
);
1276 int tag_got_bytes
= FFMIN(taglen
, *len
);
1277 int remaining
= taglen
- tag_got_bytes
;
1279 if (taglen
> maxsize
) {
1280 av_log(pls
->parent
, AV_LOG_ERROR
, "Too large HLS ID3 tag (%d > %"PRId64
" bytes)\n",
1286 * Copy the id3 tag to our temporary id3 buffer.
1287 * We could read a small id3 tag directly without memcpy, but
1288 * we would still need to copy the large tags, and handling
1289 * both of those cases together with the possibility for multiple
1290 * tags would make the handling a bit complex.
1292 pls
->id3_buf
= av_fast_realloc(pls
->id3_buf
, &pls
->id3_buf_size
, id3_buf_pos
+ taglen
);
1295 memcpy(pls
->id3_buf
+ id3_buf_pos
, buf
, tag_got_bytes
);
1296 id3_buf_pos
+= tag_got_bytes
;
1298 /* strip the intercepted bytes */
1299 *len
-= tag_got_bytes
;
1300 memmove(buf
, buf
+ tag_got_bytes
, *len
);
1301 av_log(pls
->parent
, AV_LOG_DEBUG
, "Stripped %d HLS ID3 bytes\n", tag_got_bytes
);
1303 if (remaining
> 0) {
1304 /* read the rest of the tag in */
1305 if (read_from_url(pls
, seg
, pls
->id3_buf
+ id3_buf_pos
, remaining
) != remaining
)
1307 id3_buf_pos
+= remaining
;
1308 av_log(pls
->parent
, AV_LOG_DEBUG
, "Stripped additional %d HLS ID3 bytes\n", remaining
);
1312 /* no more ID3 tags */
1317 /* re-fill buffer for the caller unless EOF */
1318 if (*len
>= 0 && (fill_buf
|| *len
== 0)) {
1319 bytes
= read_from_url(pls
, seg
, buf
+ *len
, buf_size
- *len
);
1321 /* ignore error if we already had some data */
1329 /* Now parse all the ID3 tags */
1330 FFIOContext id3ioctx
;
1331 ffio_init_read_context(&id3ioctx
, pls
->id3_buf
, id3_buf_pos
);
1332 handle_id3(&id3ioctx
.pub
, pls
);
1335 if (pls
->is_id3_timestamped
== -1)
1336 pls
->is_id3_timestamped
= (pls
->id3_mpegts_timestamp
!= AV_NOPTS_VALUE
);
1339 static int read_key(HLSContext
*c
, struct playlist
*pls
, struct segment
*seg
)
1341 AVIOContext
*pb
= NULL
;
1343 int ret
= open_url(pls
->parent
, &pb
, seg
->key
, &c
->avio_opts
, NULL
, NULL
);
1345 av_log(pls
->parent
, AV_LOG_ERROR
, "Unable to open key file %s, %s\n",
1346 seg
->key
, av_err2str(ret
));
1350 ret
= avio_read(pb
, pls
->key
, sizeof(pls
->key
));
1351 ff_format_io_close(pls
->parent
, &pb
);
1352 if (ret
!= sizeof(pls
->key
)) {
1354 av_log(pls
->parent
, AV_LOG_ERROR
, "Unable to read key file %s, %s\n",
1355 seg
->key
, av_err2str(ret
));
1357 av_log(pls
->parent
, AV_LOG_ERROR
, "Unable to read key file %s, read bytes %d != %zu\n",
1358 seg
->key
, ret
, sizeof(pls
->key
));
1359 ret
= AVERROR_INVALIDDATA
;
1365 av_strlcpy(pls
->key_url
, seg
->key
, sizeof(pls
->key_url
));
1370 static int open_input(HLSContext
*c
, struct playlist
*pls
, struct segment
*seg
, AVIOContext
**in
)
1372 AVDictionary
*opts
= NULL
;
1376 if (c
->http_persistent
)
1377 av_dict_set(&opts
, "multiple_requests", "1", 0);
1379 if (seg
->size
>= 0) {
1380 /* try to restrict the HTTP request to the part we want
1381 * (if this is in fact a HTTP request) */
1382 av_dict_set_int(&opts
, "offset", seg
->url_offset
, 0);
1383 av_dict_set_int(&opts
, "end_offset", seg
->url_offset
+ seg
->size
, 0);
1386 av_log(pls
->parent
, AV_LOG_VERBOSE
, "HLS request for url '%s', offset %"PRId64
", playlist %d\n",
1387 seg
->url
, seg
->url_offset
, pls
->index
);
1389 if (seg
->key_type
== KEY_AES_128
|| seg
->key_type
== KEY_SAMPLE_AES
) {
1390 if (strcmp(seg
->key
, pls
->key_url
)) {
1391 ret
= read_key(c
, pls
, seg
);
1397 if (seg
->key_type
== KEY_AES_128
) {
1398 char iv
[33], key
[33], url
[MAX_URL_SIZE
];
1399 ff_data_to_hex(iv
, seg
->iv
, sizeof(seg
->iv
), 0);
1400 ff_data_to_hex(key
, pls
->key
, sizeof(pls
->key
), 0);
1401 if (strstr(seg
->url
, "://"))
1402 snprintf(url
, sizeof(url
), "crypto+%s", seg
->url
);
1404 snprintf(url
, sizeof(url
), "crypto:%s", seg
->url
);
1406 av_dict_set(&opts
, "key", key
, 0);
1407 av_dict_set(&opts
, "iv", iv
, 0);
1409 ret
= open_url(pls
->parent
, in
, url
, &c
->avio_opts
, opts
, &is_http
);
1415 ret
= open_url(pls
->parent
, in
, seg
->url
, &c
->avio_opts
, opts
, &is_http
);
1418 /* Seek to the requested position. If this was a HTTP request, the offset
1419 * should already be where want it to, but this allows e.g. local testing
1420 * without a HTTP server.
1422 * This is not done for HTTP at all as avio_seek() does internal bookkeeping
1423 * of file offset which is out-of-sync with the actual offset when "offset"
1424 * AVOption is used with http protocol, causing the seek to not be a no-op
1425 * as would be expected. Wrong offset received from the server will not be
1426 * noticed without the call, though.
1428 if (ret
== 0 && !is_http
&& seg
->url_offset
) {
1429 int64_t seekret
= avio_seek(*in
, seg
->url_offset
, SEEK_SET
);
1431 av_log(pls
->parent
, AV_LOG_ERROR
, "Unable to seek to offset %"PRId64
" of HLS segment '%s'\n", seg
->url_offset
, seg
->url
);
1433 ff_format_io_close(pls
->parent
, in
);
1438 av_dict_free(&opts
);
1439 pls
->cur_seg_offset
= 0;
1443 static int update_init_section(struct playlist
*pls
, struct segment
*seg
)
1445 static const int max_init_section_size
= 1024*1024;
1446 HLSContext
*c
= pls
->parent
->priv_data
;
1451 if (seg
->init_section
== pls
->cur_init_section
)
1454 pls
->cur_init_section
= NULL
;
1456 if (!seg
->init_section
)
1459 ret
= open_input(c
, pls
, seg
->init_section
, &pls
->input
);
1461 av_log(pls
->parent
, AV_LOG_WARNING
,
1462 "Failed to open an initialization section in playlist %d\n",
1467 if (seg
->init_section
->size
>= 0)
1468 sec_size
= seg
->init_section
->size
;
1469 else if ((urlsize
= avio_size(pls
->input
)) >= 0)
1472 sec_size
= max_init_section_size
;
1474 av_log(pls
->parent
, AV_LOG_DEBUG
,
1475 "Downloading an initialization section of size %"PRId64
"\n",
1478 sec_size
= FFMIN(sec_size
, max_init_section_size
);
1480 av_fast_malloc(&pls
->init_sec_buf
, &pls
->init_sec_buf_size
, sec_size
);
1482 ret
= read_from_url(pls
, seg
->init_section
, pls
->init_sec_buf
,
1483 pls
->init_sec_buf_size
);
1484 ff_format_io_close(pls
->parent
, &pls
->input
);
1489 pls
->cur_init_section
= seg
->init_section
;
1490 pls
->init_sec_data_len
= ret
;
1491 pls
->init_sec_buf_read_offset
= 0;
1493 /* spec says audio elementary streams do not have media initialization
1494 * sections, so there should be no ID3 timestamps */
1495 pls
->is_id3_timestamped
= 0;
1500 static int64_t default_reload_interval(struct playlist
*pls
)
1502 return pls
->n_segments
> 0 ?
1503 pls
->segments
[pls
->n_segments
- 1]->duration
:
1504 pls
->target_duration
;
1507 static int playlist_needed(struct playlist
*pls
)
1509 AVFormatContext
*s
= pls
->parent
;
1511 int stream_needed
= 0;
1514 /* If there is no context or streams yet, the playlist is needed */
1515 if ((!pls
->ctx
|| !pls
->n_main_streams
) && !pls
->is_subtitle
)
1518 /* check if any of the streams in the playlist are needed */
1519 for (i
= 0; i
< pls
->n_main_streams
; i
++) {
1520 if (pls
->main_streams
[i
]->discard
< AVDISCARD_ALL
) {
1526 /* If all streams in the playlist were discarded, the playlist is not
1527 * needed (regardless of whether whole programs are discarded or not). */
1531 /* Otherwise, check if all the programs (variants) this playlist is in are
1532 * discarded. Since all streams in the playlist are part of the same programs
1533 * we can just check the programs of the first stream. */
1535 first_st
= pls
->main_streams
[0]->index
;
1537 for (i
= 0; i
< s
->nb_programs
; i
++) {
1538 AVProgram
*program
= s
->programs
[i
];
1539 if (program
->discard
< AVDISCARD_ALL
) {
1540 for (j
= 0; j
< program
->nb_stream_indexes
; j
++) {
1541 if (program
->stream_index
[j
] == first_st
) {
1542 /* playlist is in an undiscarded program */
1549 /* some streams were not discarded but all the programs were */
1553 static int reload_playlist(struct playlist
*v
, HLSContext
*c
)
1556 int reload_count
= 0;
1558 v
->needed
= playlist_needed(v
);
1563 if (!v
->input
|| (c
->http_persistent
&& v
->input_read_done
)) {
1564 int64_t reload_interval
;
1566 /* Check that the playlist is still needed before opening a new
1568 v
->needed
= playlist_needed(v
);
1571 av_log(v
->parent
, AV_LOG_INFO
, "No longer receiving playlist %d ('%s')\n",
1576 /* If this is a live stream and the reload interval has elapsed since
1577 * the last playlist reload, reload the playlists now. */
1578 reload_interval
= default_reload_interval(v
);
1582 if (reload_count
> c
->max_reload
)
1585 av_gettime_relative() - v
->last_load_time
>= reload_interval
) {
1586 if ((ret
= parse_playlist(c
, v
->url
, v
, NULL
)) < 0) {
1587 if (ret
!= AVERROR_EXIT
)
1588 av_log(v
->parent
, AV_LOG_WARNING
, "Failed to reload playlist %d\n",
1592 /* If we need to reload the playlist again below (if
1593 * there's still no more segments), switch to a reload
1594 * interval of half the target duration. */
1595 reload_interval
= v
->target_duration
/ 2;
1597 if (v
->cur_seq_no
< v
->start_seq_no
) {
1598 av_log(v
->parent
, AV_LOG_WARNING
,
1599 "skipping %"PRId64
" segments ahead, expired from playlists\n",
1600 v
->start_seq_no
- v
->cur_seq_no
);
1601 v
->cur_seq_no
= v
->start_seq_no
;
1603 if (v
->cur_seq_no
> v
->last_seq_no
) {
1604 v
->last_seq_no
= v
->cur_seq_no
;
1605 v
->m3u8_hold_counters
= 0;
1606 } else if (v
->last_seq_no
== v
->cur_seq_no
) {
1607 v
->m3u8_hold_counters
++;
1608 if (v
->m3u8_hold_counters
>= c
->m3u8_hold_counters
) {
1612 av_log(v
->parent
, AV_LOG_WARNING
, "The m3u8 list sequence may have been wrapped.\n");
1614 if (v
->cur_seq_no
>= v
->start_seq_no
+ v
->n_segments
) {
1615 if (v
->finished
|| v
->is_subtitle
)
1617 while (av_gettime_relative() - v
->last_load_time
< reload_interval
) {
1618 if (ff_check_interrupt(c
->interrupt_callback
))
1619 return AVERROR_EXIT
;
1620 av_usleep(100*1000);
1622 /* Enough time has elapsed since the last reload */
1630 static int read_data_continuous(void *opaque
, uint8_t *buf
, int buf_size
)
1632 struct playlist
*v
= opaque
;
1633 HLSContext
*c
= v
->parent
->priv_data
;
1635 int just_opened
= 0;
1636 int segment_retries
= 0;
1637 struct segment
*seg
;
1639 if (c
->http_persistent
&& v
->input_read_done
) {
1640 ret
= reload_playlist(v
, c
);
1645 v
->input_read_done
= 0;
1648 ret
= reload_playlist(v
, c
);
1652 seg
= current_segment(v
);
1654 if (!v
->input
|| (c
->http_persistent
&& v
->input_read_done
)) {
1655 /* load/update Media Initialization Section, if any */
1656 ret
= update_init_section(v
, seg
);
1660 if (c
->http_multiple
== 1 && v
->input_next_requested
) {
1661 FFSWAP(AVIOContext
*, v
->input
, v
->input_next
);
1662 v
->cur_seg_offset
= 0;
1663 v
->input_next_requested
= 0;
1666 ret
= open_input(c
, v
, seg
, &v
->input
);
1669 if (ff_check_interrupt(c
->interrupt_callback
))
1670 return AVERROR_EXIT
;
1671 av_log(v
->parent
, AV_LOG_WARNING
, "Failed to open segment %"PRId64
" of playlist %d\n",
1674 if (segment_retries
>= c
->seg_max_retry
) {
1675 av_log(v
->parent
, AV_LOG_WARNING
, "Segment %"PRId64
" of playlist %d failed too many times, skipping\n",
1679 segment_retries
= 0;
1685 segment_retries
= 0;
1689 if (c
->http_multiple
== -1) {
1690 uint8_t *http_version_opt
= NULL
;
1691 int r
= av_opt_get(v
->input
, "http_version", AV_OPT_SEARCH_CHILDREN
, &http_version_opt
);
1693 c
->http_multiple
= (!strncmp((const char *)http_version_opt
, "1.1", 3) || !strncmp((const char *)http_version_opt
, "2.0", 3));
1694 av_freep(&http_version_opt
);
1698 seg
= next_segment(v
);
1699 if (c
->http_multiple
== 1 && !v
->input_next_requested
&&
1700 seg
&& seg
->key_type
== KEY_NONE
&& av_strstart(seg
->url
, "http", NULL
)) {
1701 ret
= open_input(c
, v
, seg
, &v
->input_next
);
1703 if (ff_check_interrupt(c
->interrupt_callback
))
1704 return AVERROR_EXIT
;
1705 av_log(v
->parent
, AV_LOG_WARNING
, "Failed to open segment %"PRId64
" of playlist %d\n",
1709 v
->input_next_requested
= 1;
1713 if (v
->init_sec_buf_read_offset
< v
->init_sec_data_len
) {
1714 /* Push init section out first before first actual segment */
1715 int copy_size
= FFMIN(v
->init_sec_data_len
- v
->init_sec_buf_read_offset
, buf_size
);
1716 memcpy(buf
, v
->init_sec_buf
, copy_size
);
1717 v
->init_sec_buf_read_offset
+= copy_size
;
1721 seg
= current_segment(v
);
1722 ret
= read_from_url(v
, seg
, buf
, buf_size
);
1724 if (just_opened
&& v
->is_id3_timestamped
!= 0) {
1725 /* Intercept ID3 tags here, elementary audio streams are required
1726 * to convey timestamps using them in the beginning of each segment. */
1727 intercept_id3(v
, buf
, buf_size
, &ret
);
1732 if (c
->http_persistent
&&
1733 seg
->key_type
== KEY_NONE
&& av_strstart(seg
->url
, "http", NULL
)) {
1734 v
->input_read_done
= 1;
1736 ff_format_io_close(v
->parent
, &v
->input
);
1740 c
->cur_seq_no
= v
->cur_seq_no
;
1745 static int read_data_subtitle_segment(void *opaque
, uint8_t *buf
, int buf_size
)
1747 struct playlist
*v
= opaque
;
1748 HLSContext
*c
= v
->parent
->priv_data
;
1750 struct segment
*seg
;
1752 if (!v
->needed
|| v
->cur_seq_no
- v
->start_seq_no
>= v
->n_segments
) {
1755 seg
= current_segment(v
);
1759 ret
= open_input(c
, v
, seg
, &v
->input
);
1761 if (ff_check_interrupt(c
->interrupt_callback
))
1762 return AVERROR_EXIT
;
1763 av_log(v
->parent
, AV_LOG_WARNING
, "Failed to open segment of playlist %d\n",
1769 return read_from_url(v
, seg
, buf
, buf_size
);
1772 static int nested_io_open(AVFormatContext
*s
, AVIOContext
**pb
, const char *url
,
1773 int flags
, AVDictionary
**opts
)
1775 av_log(s
, AV_LOG_ERROR
,
1776 "A HLS playlist item '%s' referred to an external file '%s'. "
1777 "Opening this file was forbidden for security reasons\n",
1779 return AVERROR(EPERM
);
1782 static int init_subtitle_context(struct playlist
*pls
)
1784 HLSContext
*c
= pls
->parent
->priv_data
;
1785 const AVInputFormat
*in_fmt
;
1786 AVDictionary
*opts
= NULL
;
1789 if (!(pls
->ctx
= avformat_alloc_context()))
1790 return AVERROR(ENOMEM
);
1792 pls
->read_buffer
= av_malloc(INITIAL_BUFFER_SIZE
);
1793 if (!pls
->read_buffer
) {
1794 avformat_free_context(pls
->ctx
);
1796 return AVERROR(ENOMEM
);
1799 ffio_init_context(&pls
->pb
, pls
->read_buffer
, INITIAL_BUFFER_SIZE
, 0, pls
,
1800 read_data_subtitle_segment
, NULL
, NULL
);
1801 pls
->pb
.pub
.seekable
= 0;
1802 pls
->ctx
->pb
= &pls
->pb
.pub
;
1803 pls
->ctx
->io_open
= nested_io_open
;
1805 ret
= ff_copy_whiteblacklists(pls
->ctx
, pls
->parent
);
1809 in_fmt
= av_find_input_format("webvtt");
1810 av_dict_copy(&opts
, c
->seg_format_opts
, 0);
1811 ret
= avformat_open_input(&pls
->ctx
, current_segment(pls
)->url
, in_fmt
, &opts
);
1812 av_dict_free(&opts
);
1817 static int read_subtitle_packet(struct playlist
*v
, AVPacket
*pkt
)
1819 HLSContext
*c
= v
->parent
->priv_data
;
1823 ret
= reload_playlist(v
, c
);
1827 if (v
->input
&& !v
->ctx
)
1828 ff_format_io_close(v
->parent
, &v
->input
);
1830 if (!v
->input
&& !v
->ctx
) {
1831 ret
= init_subtitle_context(v
);
1836 ret
= av_read_frame(v
->ctx
, v
->pkt
);
1840 ff_format_io_close(v
->parent
, &v
->input
);
1842 c
->cur_seq_no
= v
->cur_seq_no
;
1844 avformat_close_input(&v
->ctx
);
1849 static void add_renditions_to_variant(HLSContext
*c
, struct variant
*var
,
1850 enum AVMediaType type
, const char *group_id
)
1854 for (i
= 0; i
< c
->n_renditions
; i
++) {
1855 struct rendition
*rend
= c
->renditions
[i
];
1857 if (rend
->type
== type
&& !strcmp(rend
->group_id
, group_id
)) {
1860 /* rendition is an external playlist
1861 * => add the playlist to the variant */
1862 dynarray_add(&var
->playlists
, &var
->n_playlists
, rend
->playlist
);
1864 /* rendition is part of the variant main Media Playlist
1865 * => add the rendition to the main Media Playlist */
1866 dynarray_add(&var
->playlists
[0]->renditions
,
1867 &var
->playlists
[0]->n_renditions
,
1873 static void add_metadata_from_renditions(AVFormatContext
*s
, struct playlist
*pls
,
1874 enum AVMediaType type
)
1879 for (i
= 0; i
< pls
->n_main_streams
; i
++) {
1880 AVStream
*st
= pls
->main_streams
[i
];
1882 if (st
->codecpar
->codec_type
!= type
)
1885 for (; rend_idx
< pls
->n_renditions
; rend_idx
++) {
1886 struct rendition
*rend
= pls
->renditions
[rend_idx
];
1888 if (rend
->type
!= type
)
1891 if (rend
->language
[0])
1892 av_dict_set(&st
->metadata
, "language", rend
->language
, 0);
1894 av_dict_set(&st
->metadata
, "comment", rend
->name
, 0);
1896 st
->disposition
|= rend
->disposition
;
1898 if (rend_idx
>=pls
->n_renditions
)
1903 /* if timestamp was in valid range: returns 1 and sets seq_no
1904 * if not: returns 0 and sets seq_no to closest segment */
1905 static int find_timestamp_in_playlist(HLSContext
*c
, struct playlist
*pls
,
1906 int64_t timestamp
, int64_t *seq_no
,
1907 int64_t *seg_start_ts
)
1910 int64_t pos
= c
->first_timestamp
== AV_NOPTS_VALUE
?
1911 0 : c
->first_timestamp
;
1913 if (timestamp
< pos
) {
1914 *seq_no
= pls
->start_seq_no
;
1918 for (i
= 0; i
< pls
->n_segments
; i
++) {
1919 int64_t diff
= pos
+ pls
->segments
[i
]->duration
- timestamp
;
1921 *seq_no
= pls
->start_seq_no
+ i
;
1923 *seg_start_ts
= pos
;
1927 pos
+= pls
->segments
[i
]->duration
;
1930 *seq_no
= pls
->start_seq_no
+ pls
->n_segments
- 1;
1935 static int64_t select_cur_seq_no(HLSContext
*c
, struct playlist
*pls
)
1939 if (!pls
->finished
&& !c
->first_packet
&&
1940 av_gettime_relative() - pls
->last_load_time
>= default_reload_interval(pls
))
1941 /* reload the playlist since it was suspended */
1942 parse_playlist(c
, pls
->url
, pls
, NULL
);
1944 /* If playback is already in progress (we are just selecting a new
1945 * playlist) and this is a complete file, find the matching segment
1946 * by counting durations. */
1947 if (pls
->finished
&& c
->cur_timestamp
!= AV_NOPTS_VALUE
) {
1948 find_timestamp_in_playlist(c
, pls
, c
->cur_timestamp
, &seq_no
, NULL
);
1952 if (!pls
->finished
) {
1953 if (!c
->first_packet
&& /* we are doing a segment selection during playback */
1954 c
->cur_seq_no
>= pls
->start_seq_no
&&
1955 c
->cur_seq_no
< pls
->start_seq_no
+ pls
->n_segments
)
1956 /* While spec 3.4.3 says that we cannot assume anything about the
1957 * content at the same sequence number on different playlists,
1958 * in practice this seems to work and doing it otherwise would
1959 * require us to download a segment to inspect its timestamps. */
1960 return c
->cur_seq_no
;
1962 /* If this is a live stream, start live_start_index segments from the
1964 if (c
->live_start_index
< 0)
1965 seq_no
= pls
->start_seq_no
+ FFMAX(pls
->n_segments
+
1966 c
->live_start_index
, 0);
1968 seq_no
= pls
->start_seq_no
+ FFMIN(c
->live_start_index
,
1969 pls
->n_segments
- 1);
1971 /* If #EXT-X-START in playlist, need to recalculate */
1972 if (pls
->time_offset_flag
&& c
->prefer_x_start
) {
1973 int64_t start_timestamp
;
1974 int64_t playlist_duration
= 0;
1975 int64_t cur_timestamp
= c
->cur_timestamp
== AV_NOPTS_VALUE
? 0 :
1978 for (int i
= 0; i
< pls
->n_segments
; i
++)
1979 playlist_duration
+= pls
->segments
[i
]->duration
;
1981 /* If the absolute value of TIME-OFFSET exceeds
1982 * the duration of the playlist, it indicates either the end of the
1983 * playlist (if positive) or the beginning of the playlist (if
1985 if (pls
->start_time_offset
>=0 &&
1986 pls
->start_time_offset
> playlist_duration
)
1987 start_timestamp
= cur_timestamp
+ playlist_duration
;
1988 else if (pls
->start_time_offset
>= 0 &&
1989 pls
->start_time_offset
<= playlist_duration
)
1990 start_timestamp
= cur_timestamp
+ pls
->start_time_offset
;
1991 else if (pls
->start_time_offset
< 0 &&
1992 pls
->start_time_offset
< -playlist_duration
)
1993 start_timestamp
= cur_timestamp
;
1994 else if (pls
->start_time_offset
< 0 &&
1995 pls
->start_time_offset
> -playlist_duration
)
1996 start_timestamp
= cur_timestamp
+ playlist_duration
+
1997 pls
->start_time_offset
;
1999 start_timestamp
= cur_timestamp
;
2001 find_timestamp_in_playlist(c
, pls
, start_timestamp
, &seq_no
, NULL
);
2006 /* Otherwise just start on the first segment. */
2007 return pls
->start_seq_no
;
2010 static void add_stream_to_programs(AVFormatContext
*s
, struct playlist
*pls
, AVStream
*stream
)
2012 HLSContext
*c
= s
->priv_data
;
2016 for (i
= 0; i
< c
->n_variants
; i
++) {
2017 struct variant
*v
= c
->variants
[i
];
2019 for (j
= 0; j
< v
->n_playlists
; j
++) {
2020 if (v
->playlists
[j
] != pls
)
2023 av_program_add_stream_index(s
, i
, stream
->index
);
2026 bandwidth
= v
->bandwidth
;
2027 else if (bandwidth
!= v
->bandwidth
)
2028 bandwidth
= -1; /* stream in multiple variants with different bandwidths */
2033 av_dict_set_int(&stream
->metadata
, "variant_bitrate", bandwidth
, 0);
2036 static int set_stream_info_from_input_stream(AVStream
*st
, struct playlist
*pls
, AVStream
*ist
)
2040 err
= avcodec_parameters_copy(st
->codecpar
, ist
->codecpar
);
2044 if (pls
->is_id3_timestamped
) /* custom timestamps via id3 */
2045 avpriv_set_pts_info(st
, 33, 1, MPEG_TIME_BASE
);
2047 avpriv_set_pts_info(st
, ist
->pts_wrap_bits
, ist
->time_base
.num
, ist
->time_base
.den
);
2050 st
->disposition
= ist
->disposition
;
2052 av_dict_copy(&st
->metadata
, ist
->metadata
, 0);
2054 ffstream(st
)->need_context_update
= 1;
2059 /* add new subdemuxer streams to our context, if any */
2060 static int update_streams_from_subdemuxer(AVFormatContext
*s
, struct playlist
*pls
)
2064 while (pls
->n_main_streams
< pls
->ctx
->nb_streams
) {
2065 int ist_idx
= pls
->n_main_streams
;
2066 AVStream
*st
= avformat_new_stream(s
, NULL
);
2067 AVStream
*ist
= pls
->ctx
->streams
[ist_idx
];
2070 return AVERROR(ENOMEM
);
2072 st
->id
= pls
->index
;
2073 dynarray_add(&pls
->main_streams
, &pls
->n_main_streams
, st
);
2075 add_stream_to_programs(s
, pls
, st
);
2077 err
= set_stream_info_from_input_stream(st
, pls
, ist
);
2085 static void update_noheader_flag(AVFormatContext
*s
)
2087 HLSContext
*c
= s
->priv_data
;
2088 int flag_needed
= 0;
2091 for (i
= 0; i
< c
->n_playlists
; i
++) {
2092 struct playlist
*pls
= c
->playlists
[i
];
2094 if (pls
->has_noheader_flag
) {
2101 s
->ctx_flags
|= AVFMTCTX_NOHEADER
;
2103 s
->ctx_flags
&= ~AVFMTCTX_NOHEADER
;
2106 static int hls_close(AVFormatContext
*s
)
2108 HLSContext
*c
= s
->priv_data
;
2110 free_playlist_list(c
);
2111 free_variant_list(c
);
2112 free_rendition_list(c
);
2114 if (c
->crypto_ctx
.aes_ctx
)
2115 av_free(c
->crypto_ctx
.aes_ctx
);
2117 av_dict_free(&c
->avio_opts
);
2118 ff_format_io_close(c
->ctx
, &c
->playlist_pb
);
2123 static int hls_read_header(AVFormatContext
*s
)
2125 HLSContext
*c
= s
->priv_data
;
2127 int64_t highest_cur_seq_no
= 0;
2130 c
->interrupt_callback
= &s
->interrupt_callback
;
2132 c
->first_packet
= 1;
2133 c
->first_timestamp
= AV_NOPTS_VALUE
;
2134 c
->cur_timestamp
= AV_NOPTS_VALUE
;
2136 if ((ret
= ffio_copy_url_options(s
->pb
, &c
->avio_opts
)) < 0)
2139 /* XXX: Some HLS servers don't like being sent the range header,
2140 in this case, we need to set http_seekable = 0 to disable
2142 av_dict_set_int(&c
->avio_opts
, "seekable", c
->http_seekable
, 0);
2144 if ((ret
= parse_playlist(c
, s
->url
, NULL
, s
->pb
)) < 0)
2147 if (c
->n_variants
== 0) {
2148 av_log(s
, AV_LOG_WARNING
, "Empty playlist\n");
2151 /* If the playlist only contained playlists (Master Playlist),
2152 * parse each individual playlist. */
2153 if (c
->n_playlists
> 1 || c
->playlists
[0]->n_segments
== 0) {
2154 for (i
= 0; i
< c
->n_playlists
; i
++) {
2155 struct playlist
*pls
= c
->playlists
[i
];
2156 pls
->m3u8_hold_counters
= 0;
2157 if ((ret
= parse_playlist(c
, pls
->url
, pls
, NULL
)) < 0) {
2158 av_log(s
, AV_LOG_WARNING
, "parse_playlist error %s [%s]\n", av_err2str(ret
), pls
->url
);
2160 if (c
->n_playlists
> 1)
2167 for (i
= 0; i
< c
->n_variants
; i
++) {
2168 if (c
->variants
[i
]->playlists
[0]->n_segments
== 0) {
2169 av_log(s
, AV_LOG_WARNING
, "Empty segment [%s]\n", c
->variants
[i
]->playlists
[0]->url
);
2170 c
->variants
[i
]->playlists
[0]->broken
= 1;
2174 /* If this isn't a live stream, calculate the total duration of the
2176 if (c
->variants
[0]->playlists
[0]->finished
) {
2177 int64_t duration
= 0;
2178 for (i
= 0; i
< c
->variants
[0]->playlists
[0]->n_segments
; i
++)
2179 duration
+= c
->variants
[0]->playlists
[0]->segments
[i
]->duration
;
2180 s
->duration
= duration
;
2183 /* Associate renditions with variants */
2184 for (i
= 0; i
< c
->n_variants
; i
++) {
2185 struct variant
*var
= c
->variants
[i
];
2187 if (var
->audio_group
[0])
2188 add_renditions_to_variant(c
, var
, AVMEDIA_TYPE_AUDIO
, var
->audio_group
);
2189 if (var
->video_group
[0])
2190 add_renditions_to_variant(c
, var
, AVMEDIA_TYPE_VIDEO
, var
->video_group
);
2191 if (var
->subtitles_group
[0])
2192 add_renditions_to_variant(c
, var
, AVMEDIA_TYPE_SUBTITLE
, var
->subtitles_group
);
2195 /* Create a program for each variant */
2196 for (i
= 0; i
< c
->n_variants
; i
++) {
2197 struct variant
*v
= c
->variants
[i
];
2200 program
= av_new_program(s
, i
);
2202 return AVERROR(ENOMEM
);
2203 av_dict_set_int(&program
->metadata
, "variant_bitrate", v
->bandwidth
, 0);
2206 /* Select the starting segments */
2207 for (i
= 0; i
< c
->n_playlists
; i
++) {
2208 struct playlist
*pls
= c
->playlists
[i
];
2210 if (pls
->n_segments
== 0)
2213 pls
->cur_seq_no
= select_cur_seq_no(c
, pls
);
2214 highest_cur_seq_no
= FFMAX(highest_cur_seq_no
, pls
->cur_seq_no
);
2217 av_dict_set(&c
->seg_format_opts
, "prefer_hls_mpegts_pts", "1", 0);
2219 /* Open the demuxer for each playlist */
2220 for (i
= 0; i
< c
->n_playlists
; i
++) {
2221 struct playlist
*pls
= c
->playlists
[i
];
2222 const AVInputFormat
*in_fmt
= NULL
;
2224 AVDictionary
*options
= NULL
;
2225 struct segment
*seg
= NULL
;
2227 if (!(pls
->ctx
= avformat_alloc_context()))
2228 return AVERROR(ENOMEM
);
2230 if (pls
->n_segments
== 0)
2238 * If this is a live stream and this playlist looks like it is one segment
2239 * behind, try to sync it up so that every substream starts at the same
2240 * time position (so e.g. avformat_find_stream_info() will see packets from
2241 * all active streams within the first few seconds). This is not very generic,
2242 * though, as the sequence numbers are technically independent.
2244 if (!pls
->finished
&& pls
->cur_seq_no
== highest_cur_seq_no
- 1 &&
2245 highest_cur_seq_no
< pls
->start_seq_no
+ pls
->n_segments
) {
2246 pls
->cur_seq_no
= highest_cur_seq_no
;
2249 pls
->read_buffer
= av_malloc(INITIAL_BUFFER_SIZE
);
2250 if (!pls
->read_buffer
){
2251 avformat_free_context(pls
->ctx
);
2253 return AVERROR(ENOMEM
);
2256 if (pls
->is_subtitle
)
2257 ffio_init_context(&pls
->pb
, (unsigned char*)av_strdup("WEBVTT\n"), (int)strlen("WEBVTT\n"), 0, pls
,
2260 ffio_init_context(&pls
->pb
, pls
->read_buffer
, INITIAL_BUFFER_SIZE
, 0, pls
,
2261 read_data_continuous
, NULL
, NULL
);
2264 * If encryption scheme is SAMPLE-AES, try to read ID3 tags of
2265 * external audio track that contains audio setup information
2267 seg
= current_segment(pls
);
2268 if (seg
&& seg
->key_type
== KEY_SAMPLE_AES
&& pls
->n_renditions
> 0 &&
2269 pls
->renditions
[0]->type
== AVMEDIA_TYPE_AUDIO
) {
2270 uint8_t buf
[HLS_MAX_ID3_TAGS_DATA_LEN
];
2271 if ((ret
= avio_read(&pls
->pb
.pub
, buf
, HLS_MAX_ID3_TAGS_DATA_LEN
)) < 0) {
2272 /* Fail if error was not end of file */
2273 if (ret
!= AVERROR_EOF
) {
2274 avformat_free_context(pls
->ctx
);
2281 ff_format_io_close(pls
->parent
, &pls
->input
);
2283 pls
->input_read_done
= 0;
2284 ff_format_io_close(pls
->parent
, &pls
->input_next
);
2285 pls
->input_next
= NULL
;
2286 pls
->input_next_requested
= 0;
2287 pls
->cur_seg_offset
= 0;
2288 pls
->cur_init_section
= NULL
;
2289 /* Reset EOF flag */
2290 pls
->pb
.pub
.eof_reached
= 0;
2291 /* Clear any buffered data */
2292 pls
->pb
.pub
.buf_end
= pls
->pb
.pub
.buf_ptr
= pls
->pb
.pub
.buffer
;
2293 /* Reset the position */
2294 pls
->pb
.pub
.pos
= 0;
2298 * If encryption scheme is SAMPLE-AES and audio setup information is present in external audio track,
2299 * use that information to find the media format, otherwise probe input data
2301 seg
= current_segment(pls
);
2302 if (seg
&& seg
->key_type
== KEY_SAMPLE_AES
&& pls
->is_id3_timestamped
&&
2303 pls
->audio_setup_info
.codec_id
!= AV_CODEC_ID_NONE
) {
2304 av_assert1(pls
->audio_setup_info
.codec_id
== AV_CODEC_ID_AAC
||
2305 pls
->audio_setup_info
.codec_id
== AV_CODEC_ID_AC3
||
2306 pls
->audio_setup_info
.codec_id
== AV_CODEC_ID_EAC3
);
2307 // Keep this list in sync with ff_hls_senc_read_audio_setup_info()
2308 in_fmt
= av_find_input_format(pls
->audio_setup_info
.codec_id
== AV_CODEC_ID_AAC
? "aac" :
2309 pls
->audio_setup_info
.codec_id
== AV_CODEC_ID_AC3
? "ac3" : "eac3");
2311 pls
->ctx
->probesize
= s
->probesize
> 0 ? s
->probesize
: 1024 * 4;
2312 pls
->ctx
->max_analyze_duration
= s
->max_analyze_duration
> 0 ? s
->max_analyze_duration
: 4 * AV_TIME_BASE
;
2313 pls
->ctx
->interrupt_callback
= s
->interrupt_callback
;
2314 url
= av_strdup(pls
->segments
[0]->url
);
2315 ret
= av_probe_input_buffer(&pls
->pb
.pub
, &in_fmt
, url
, NULL
, 0, 0);
2317 for (int n
= 0; n
< pls
->n_segments
; n
++)
2319 ret
= test_segment(s
, in_fmt
, pls
, pls
->segments
[n
]);
2322 /* Free the ctx - it isn't initialized properly at this point,
2323 * so avformat_close_input shouldn't be called. If
2324 * avformat_open_input fails below, it frees and zeros the
2325 * context, so it doesn't need any special treatment like this. */
2326 av_log(s
, AV_LOG_ERROR
, "Error when loading first segment '%s'\n", url
);
2327 avformat_free_context(pls
->ctx
);
2335 seg
= current_segment(pls
);
2336 if (seg
&& seg
->key_type
== KEY_SAMPLE_AES
) {
2337 if (strstr(in_fmt
->name
, "mov")) {
2339 ff_data_to_hex(key
, pls
->key
, sizeof(pls
->key
), 0);
2340 av_dict_set(&options
, "decryption_key", key
, 0);
2341 } else if (!c
->crypto_ctx
.aes_ctx
) {
2342 c
->crypto_ctx
.aes_ctx
= av_aes_alloc();
2343 if (!c
->crypto_ctx
.aes_ctx
) {
2344 avformat_free_context(pls
->ctx
);
2346 return AVERROR(ENOMEM
);
2351 pls
->ctx
->pb
= &pls
->pb
.pub
;
2352 pls
->ctx
->io_open
= nested_io_open
;
2353 pls
->ctx
->flags
|= s
->flags
& ~AVFMT_FLAG_CUSTOM_IO
;
2355 if ((ret
= ff_copy_whiteblacklists(pls
->ctx
, s
)) < 0)
2358 av_dict_copy(&options
, c
->seg_format_opts
, 0);
2360 ret
= avformat_open_input(&pls
->ctx
, pls
->segments
[0]->url
, in_fmt
, &options
);
2361 av_dict_free(&options
);
2365 if (pls
->id3_deferred_extra
&& pls
->ctx
->nb_streams
== 1) {
2366 ff_id3v2_parse_apic(pls
->ctx
, pls
->id3_deferred_extra
);
2367 avformat_queue_attached_pictures(pls
->ctx
);
2368 ff_id3v2_parse_priv(pls
->ctx
, pls
->id3_deferred_extra
);
2369 ff_id3v2_free_extra_meta(&pls
->id3_deferred_extra
);
2372 if (pls
->is_id3_timestamped
== -1)
2373 av_log(s
, AV_LOG_WARNING
, "No expected HTTP requests have been made\n");
2376 * For ID3 timestamped raw audio streams we need to detect the packet
2377 * durations to calculate timestamps in fill_timing_for_id3_timestamped_stream(),
2378 * but for other streams we can rely on our user calling avformat_find_stream_info()
2379 * on us if they want to.
2381 if (pls
->is_id3_timestamped
|| (pls
->n_renditions
> 0 && pls
->renditions
[0]->type
== AVMEDIA_TYPE_AUDIO
)) {
2382 seg
= current_segment(pls
);
2383 if (seg
&& seg
->key_type
== KEY_SAMPLE_AES
&& pls
->audio_setup_info
.setup_data_length
> 0 &&
2384 pls
->ctx
->nb_streams
== 1)
2385 ret
= ff_hls_senc_parse_audio_setup_info(pls
->ctx
->streams
[0], &pls
->audio_setup_info
);
2387 ret
= avformat_find_stream_info(pls
->ctx
, NULL
);
2393 pls
->has_noheader_flag
= !!(pls
->ctx
->ctx_flags
& AVFMTCTX_NOHEADER
);
2395 /* Create new AVStreams for each stream in this playlist */
2396 ret
= update_streams_from_subdemuxer(s
, pls
);
2401 * Copy any metadata from playlist to main streams, but do not set
2404 if (pls
->n_main_streams
)
2405 av_dict_copy(&pls
->main_streams
[0]->metadata
, pls
->ctx
->metadata
, 0);
2407 if (pls
->is_subtitle
) {
2408 avformat_free_context(pls
->ctx
);
2411 pls
->main_streams
[0]->discard
= AVDISCARD_ALL
;
2414 add_metadata_from_renditions(s
, pls
, AVMEDIA_TYPE_AUDIO
);
2415 add_metadata_from_renditions(s
, pls
, AVMEDIA_TYPE_VIDEO
);
2416 add_metadata_from_renditions(s
, pls
, AVMEDIA_TYPE_SUBTITLE
);
2419 update_noheader_flag(s
);
2424 static int recheck_discard_flags(AVFormatContext
*s
, int first
)
2426 HLSContext
*c
= s
->priv_data
;
2430 /* Check if any new streams are needed */
2431 for (i
= 0; i
< c
->n_playlists
; i
++) {
2432 struct playlist
*pls
= c
->playlists
[i
];
2434 cur_needed
= playlist_needed(c
->playlists
[i
]);
2439 if (cur_needed
&& !pls
->needed
) {
2442 pls
->cur_seq_no
= select_cur_seq_no(c
, pls
);
2443 pls
->pb
.pub
.eof_reached
= 0;
2444 if (c
->cur_timestamp
!= AV_NOPTS_VALUE
) {
2446 pls
->seek_timestamp
= c
->cur_timestamp
;
2447 pls
->seek_flags
= AVSEEK_FLAG_ANY
;
2448 pls
->seek_stream_index
= -1;
2450 av_log(s
, AV_LOG_INFO
, "Now receiving playlist %d, segment %"PRId64
"\n", i
, pls
->cur_seq_no
);
2451 } else if (first
&& !cur_needed
&& pls
->needed
) {
2452 ff_format_io_close(pls
->parent
, &pls
->input
);
2453 pls
->input_read_done
= 0;
2454 ff_format_io_close(pls
->parent
, &pls
->input_next
);
2455 pls
->input_next_requested
= 0;
2456 if (pls
->is_subtitle
)
2457 avformat_close_input(&pls
->ctx
);
2460 av_log(s
, AV_LOG_INFO
, "No longer receiving playlist %d\n", i
);
2466 static void fill_timing_for_id3_timestamped_stream(struct playlist
*pls
)
2468 if (pls
->id3_offset
>= 0) {
2469 pls
->pkt
->dts
= pls
->id3_mpegts_timestamp
+
2470 av_rescale_q(pls
->id3_offset
,
2471 pls
->ctx
->streams
[pls
->pkt
->stream_index
]->time_base
,
2473 if (pls
->pkt
->duration
)
2474 pls
->id3_offset
+= pls
->pkt
->duration
;
2476 pls
->id3_offset
= -1;
2478 /* there have been packets with unknown duration
2479 * since the last id3 tag, should not normally happen */
2480 pls
->pkt
->dts
= AV_NOPTS_VALUE
;
2483 if (pls
->pkt
->duration
)
2484 pls
->pkt
->duration
= av_rescale_q(pls
->pkt
->duration
,
2485 pls
->ctx
->streams
[pls
->pkt
->stream_index
]->time_base
,
2488 pls
->pkt
->pts
= AV_NOPTS_VALUE
;
2491 static AVRational
get_timebase(struct playlist
*pls
)
2493 if (pls
->is_id3_timestamped
)
2494 return MPEG_TIME_BASE_Q
;
2496 return pls
->ctx
->streams
[pls
->pkt
->stream_index
]->time_base
;
2499 static int compare_ts_with_wrapdetect(int64_t ts_a
, struct playlist
*pls_a
,
2500 int64_t ts_b
, struct playlist
*pls_b
)
2502 int64_t scaled_ts_a
= av_rescale_q(ts_a
, get_timebase(pls_a
), MPEG_TIME_BASE_Q
);
2503 int64_t scaled_ts_b
= av_rescale_q(ts_b
, get_timebase(pls_b
), MPEG_TIME_BASE_Q
);
2505 return av_compare_mod(scaled_ts_a
, scaled_ts_b
, 1LL << 33);
2508 static int hls_read_packet(AVFormatContext
*s
, AVPacket
*pkt
)
2510 HLSContext
*c
= s
->priv_data
;
2511 int ret
, i
, minplaylist
= -1;
2513 recheck_discard_flags(s
, c
->first_packet
);
2514 c
->first_packet
= 0;
2516 for (i
= 0; i
< c
->n_playlists
; i
++) {
2517 struct playlist
*pls
= c
->playlists
[i
];
2518 /* Make sure we've got one buffered packet from each open playlist
2520 if (pls
->needed
&& !pls
->pkt
->data
) {
2524 struct segment
*seg
= NULL
;
2525 if (pls
->is_subtitle
)
2526 ret
= read_subtitle_packet(pls
, pls
->pkt
);
2528 ret
= av_read_frame(pls
->ctx
, pls
->pkt
);
2530 if (!avio_feof(&pls
->pb
.pub
) && ret
!= AVERROR_EOF
)
2534 /* stream_index check prevents matching picture attachments etc. */
2535 if (pls
->is_id3_timestamped
&& pls
->pkt
->stream_index
== 0) {
2536 /* audio elementary streams are id3 timestamped */
2537 fill_timing_for_id3_timestamped_stream(pls
);
2540 if (c
->first_timestamp
== AV_NOPTS_VALUE
&&
2541 pls
->pkt
->dts
!= AV_NOPTS_VALUE
)
2542 c
->first_timestamp
= av_rescale_q(pls
->pkt
->dts
,
2543 get_timebase(pls
), AV_TIME_BASE_Q
);
2546 seg
= current_segment(pls
);
2547 if (seg
&& seg
->key_type
== KEY_SAMPLE_AES
&& !strstr(pls
->ctx
->iformat
->name
, "mov")) {
2548 enum AVCodecID codec_id
= pls
->ctx
->streams
[pls
->pkt
->stream_index
]->codecpar
->codec_id
;
2549 memcpy(c
->crypto_ctx
.iv
, seg
->iv
, sizeof(seg
->iv
));
2550 memcpy(c
->crypto_ctx
.key
, pls
->key
, sizeof(pls
->key
));
2551 ff_hls_senc_decrypt_frame(codec_id
, &c
->crypto_ctx
, pls
->pkt
);
2554 if (pls
->seek_timestamp
== AV_NOPTS_VALUE
)
2557 if (pls
->seek_stream_index
< 0 ||
2558 pls
->seek_stream_index
== pls
->pkt
->stream_index
) {
2560 if (pls
->pkt
->dts
== AV_NOPTS_VALUE
) {
2561 pls
->seek_timestamp
= AV_NOPTS_VALUE
;
2565 tb
= get_timebase(pls
);
2566 ts_diff
= av_rescale_rnd(pls
->pkt
->dts
, AV_TIME_BASE
,
2567 tb
.den
, AV_ROUND_DOWN
) -
2568 pls
->seek_timestamp
;
2569 if (ts_diff
>= 0 && (pls
->seek_flags
& AVSEEK_FLAG_ANY
||
2570 pls
->pkt
->flags
& AV_PKT_FLAG_KEY
)) {
2571 pls
->seek_timestamp
= AV_NOPTS_VALUE
;
2575 av_packet_unref(pls
->pkt
);
2578 /* Check if this stream has the packet with the lowest dts */
2579 if (pls
->pkt
->data
) {
2580 struct playlist
*minpls
= minplaylist
< 0 ?
2581 NULL
: c
->playlists
[minplaylist
];
2582 if (minplaylist
< 0) {
2585 int64_t dts
= pls
->pkt
->dts
;
2586 int64_t mindts
= minpls
->pkt
->dts
;
2588 if (dts
== AV_NOPTS_VALUE
||
2589 (mindts
!= AV_NOPTS_VALUE
&& compare_ts_with_wrapdetect(dts
, pls
, mindts
, minpls
) < 0))
2595 /* If we got a packet, return it */
2596 if (minplaylist
>= 0) {
2597 struct playlist
*pls
= c
->playlists
[minplaylist
];
2601 ret
= update_streams_from_subdemuxer(s
, pls
);
2603 av_packet_unref(pls
->pkt
);
2607 // If sub-demuxer reports updated metadata, copy it to the first stream
2608 // and set its AVSTREAM_EVENT_FLAG_METADATA_UPDATED flag.
2609 if (pls
->ctx
->event_flags
& AVFMT_EVENT_FLAG_METADATA_UPDATED
) {
2610 if (pls
->n_main_streams
) {
2611 st
= pls
->main_streams
[0];
2612 av_dict_copy(&st
->metadata
, pls
->ctx
->metadata
, 0);
2613 st
->event_flags
|= AVSTREAM_EVENT_FLAG_METADATA_UPDATED
;
2615 pls
->ctx
->event_flags
&= ~AVFMT_EVENT_FLAG_METADATA_UPDATED
;
2618 /* check if noheader flag has been cleared by the subdemuxer */
2619 if (pls
->has_noheader_flag
&& !(pls
->ctx
->ctx_flags
& AVFMTCTX_NOHEADER
)) {
2620 pls
->has_noheader_flag
= 0;
2621 update_noheader_flag(s
);
2624 if (pls
->pkt
->stream_index
>= pls
->n_main_streams
) {
2625 av_log(s
, AV_LOG_ERROR
, "stream index inconsistency: index %d, %d main streams, %d subdemuxer streams\n",
2626 pls
->pkt
->stream_index
, pls
->n_main_streams
, pls
->ctx
->nb_streams
);
2627 av_packet_unref(pls
->pkt
);
2631 ist
= pls
->ctx
->streams
[pls
->pkt
->stream_index
];
2632 st
= pls
->main_streams
[pls
->pkt
->stream_index
];
2634 av_packet_move_ref(pkt
, pls
->pkt
);
2635 pkt
->stream_index
= st
->index
;
2637 if (pkt
->dts
!= AV_NOPTS_VALUE
)
2638 c
->cur_timestamp
= av_rescale_q(pkt
->dts
,
2642 /* There may be more situations where this would be useful, but this at least
2643 * handles newly probed codecs properly (i.e. request_probe by mpegts). */
2644 if (ist
->codecpar
->codec_id
!= st
->codecpar
->codec_id
) {
2645 ret
= set_stream_info_from_input_stream(st
, pls
, ist
);
2656 static int hls_read_seek(AVFormatContext
*s
, int stream_index
,
2657 int64_t timestamp
, int flags
)
2659 HLSContext
*c
= s
->priv_data
;
2660 struct playlist
*seek_pls
= NULL
;
2662 int stream_subdemuxer_index
;
2663 int64_t first_timestamp
, seek_timestamp
, duration
;
2664 int64_t seq_no
, seg_start_ts
;
2666 if ((flags
& AVSEEK_FLAG_BYTE
) || (c
->ctx
->ctx_flags
& AVFMTCTX_UNSEEKABLE
))
2667 return AVERROR(ENOSYS
);
2669 first_timestamp
= c
->first_timestamp
== AV_NOPTS_VALUE
?
2670 0 : c
->first_timestamp
;
2672 seek_timestamp
= av_rescale_rnd(timestamp
, AV_TIME_BASE
,
2673 s
->streams
[stream_index
]->time_base
.den
,
2676 duration
= s
->duration
== AV_NOPTS_VALUE
?
2679 if (0 < duration
&& duration
< seek_timestamp
- first_timestamp
)
2680 return AVERROR(EIO
);
2682 /* find the playlist with the specified stream */
2683 for (i
= 0; i
< c
->n_playlists
; i
++) {
2684 struct playlist
*pls
= c
->playlists
[i
];
2685 for (j
= 0; j
< pls
->n_main_streams
; j
++) {
2686 if (pls
->main_streams
[j
] == s
->streams
[stream_index
]) {
2688 stream_subdemuxer_index
= j
;
2693 /* check if the timestamp is valid for the playlist with the
2694 * specified stream index */
2695 if (!seek_pls
|| !find_timestamp_in_playlist(c
, seek_pls
, seek_timestamp
, &seq_no
, &seg_start_ts
))
2696 return AVERROR(EIO
);
2698 if (s
->streams
[stream_index
]->codecpar
->codec_type
== AVMEDIA_TYPE_VIDEO
&&
2699 flags
& AVSEEK_FLAG_BACKWARD
&& !(flags
& AVSEEK_FLAG_ANY
)) {
2700 /* Seeking to start of segment ensures we seek to a keyframe located
2701 * before the given timestamp. */
2702 seek_timestamp
= seg_start_ts
;
2705 /* set segment now so we do not need to search again below */
2706 seek_pls
->cur_seq_no
= seq_no
;
2707 seek_pls
->seek_stream_index
= stream_subdemuxer_index
;
2709 for (i
= 0; i
< c
->n_playlists
; i
++) {
2711 struct playlist
*pls
= c
->playlists
[i
];
2712 AVIOContext
*const pb
= &pls
->pb
.pub
;
2713 ff_format_io_close(pls
->parent
, &pls
->input
);
2714 pls
->input_read_done
= 0;
2715 ff_format_io_close(pls
->parent
, &pls
->input_next
);
2716 pls
->input_next_requested
= 0;
2717 av_packet_unref(pls
->pkt
);
2718 pb
->eof_reached
= 0;
2719 /* Clear any buffered data */
2720 pb
->buf_end
= pb
->buf_ptr
= pb
->buffer
;
2721 /* Reset the pos, to let the mpegts/mov demuxer know we've seeked. */
2723 /* Flush the packet queue of the subdemuxer. */
2725 ff_read_frame_flush(pls
->ctx
);
2726 if (pls
->is_subtitle
)
2727 avformat_close_input(&pls
->ctx
);
2729 /* Reset the init segment so it's re-fetched and served appropriately */
2730 pls
->cur_init_section
= NULL
;
2732 pls
->seek_timestamp
= seek_timestamp
;
2733 pls
->seek_flags
= flags
;
2735 if (pls
!= seek_pls
) {
2736 /* set closest segment seq_no for playlists not handled above */
2737 find_timestamp_in_playlist(c
, pls
, seek_timestamp
, &pls
->cur_seq_no
, NULL
);
2738 /* seek the playlist to the given position without taking
2739 * keyframes into account since this playlist does not have the
2740 * specified stream where we should look for the keyframes */
2741 pls
->seek_stream_index
= -1;
2742 pls
->seek_flags
|= AVSEEK_FLAG_ANY
;
2746 c
->cur_timestamp
= seek_timestamp
;
2751 static int hls_probe(const AVProbeData
*p
)
2753 /* Require #EXTM3U at the start, and either one of the ones below
2754 * somewhere for a proper match. */
2755 if (strncmp(p
->buf
, "#EXTM3U", 7))
2758 if (strstr(p
->buf
, "#EXT-X-STREAM-INF:") ||
2759 strstr(p
->buf
, "#EXT-X-TARGETDURATION:") ||
2760 strstr(p
->buf
, "#EXT-X-MEDIA-SEQUENCE:")) {
2762 int mime_ok
= p
->mime_type
&& !(
2763 av_strcasecmp(p
->mime_type
, "application/vnd.apple.mpegurl") &&
2764 av_strcasecmp(p
->mime_type
, "audio/mpegurl")
2767 int mime_x
= p
->mime_type
&& !(
2768 av_strcasecmp(p
->mime_type
, "audio/x-mpegurl") &&
2769 av_strcasecmp(p
->mime_type
, "application/x-mpegurl")
2774 !av_match_ext (p
->filename
, "m3u8,m3u") &&
2775 ff_match_url_ext(p
->filename
, "m3u8,m3u") <= 0) {
2776 av_log(NULL
, AV_LOG_ERROR
, "Not detecting m3u8/hls with non standard extension and non standard mime type\n");
2780 av_log(NULL
, AV_LOG_WARNING
, "mime type is not rfc8216 compliant\n");
2782 return AVPROBE_SCORE_MAX
;
2787 #define OFFSET(x) offsetof(HLSContext, x)
2788 #define FLAGS AV_OPT_FLAG_DECODING_PARAM
2789 static const AVOption hls_options
[] = {
2790 {"live_start_index", "segment index to start live streams at (negative values are from the end)",
2791 OFFSET(live_start_index
), AV_OPT_TYPE_INT
, {.i64
= -3}, INT_MIN
, INT_MAX
, FLAGS
},
2792 {"prefer_x_start", "prefer to use #EXT-X-START if it's in playlist instead of live_start_index",
2793 OFFSET(prefer_x_start
), AV_OPT_TYPE_BOOL
, { .i64
= 0 }, 0, 1, FLAGS
},
2794 {"allowed_extensions", "List of file extensions that hls is allowed to access",
2795 OFFSET(allowed_extensions
), AV_OPT_TYPE_STRING
,
2796 {.str
= "3gp,aac,avi,ac3,eac3,flac,mkv,m3u8,m4a,m4s,m4v,mpg,mov,mp2,mp3,mp4,mpeg,mpegts,ogg,ogv,oga,ts,vob,vtt,wav,webvtt"
2797 ",cmfv,cmfa" // Ticket11526 www.nicovideo.jp
2798 ",ec3" // part of Ticket11435 (Elisa Viihde (Finnish online recording service))
2799 ",fmp4" // https://github.com/yt-dlp/yt-dlp/issues/12700
2801 INT_MIN
, INT_MAX
, FLAGS
},
2802 {"allowed_segment_extensions", "List of file extensions that hls is allowed to access",
2803 OFFSET(allowed_segment_extensions
), AV_OPT_TYPE_STRING
,
2804 {.str
= "3gp,aac,avi,ac3,eac3,flac,mkv,m3u8,m4a,m4s,m4v,mpg,mov,mp2,mp3,mp4,mpeg,mpegts,ogg,ogv,oga,ts,vob,vtt,wav,webvtt"
2805 ",cmfv,cmfa" // Ticket11526 www.nicovideo.jp
2806 ",ec3" // part of Ticket11435 (Elisa Viihde (Finnish online recording service))
2807 ",fmp4" // https://github.com/yt-dlp/yt-dlp/issues/12700
2808 ",html" // https://flash1.bogulus.cfd/
2810 INT_MIN
, INT_MAX
, FLAGS
},
2811 {"extension_picky", "Be picky with all extensions matching",
2812 OFFSET(extension_picky
), AV_OPT_TYPE_BOOL
, {.i64
= 1}, 0, 1, FLAGS
},
2813 {"max_reload", "Maximum number of times a insufficient list is attempted to be reloaded",
2814 OFFSET(max_reload
), AV_OPT_TYPE_INT
, {.i64
= 100}, 0, INT_MAX
, FLAGS
},
2815 {"m3u8_hold_counters", "The maximum number of times to load m3u8 when it refreshes without new segments",
2816 OFFSET(m3u8_hold_counters
), AV_OPT_TYPE_INT
, {.i64
= 1000}, 0, INT_MAX
, FLAGS
},
2817 {"http_persistent", "Use persistent HTTP connections",
2818 OFFSET(http_persistent
), AV_OPT_TYPE_BOOL
, {.i64
= 1}, 0, 1, FLAGS
},
2819 {"http_multiple", "Use multiple HTTP connections for fetching segments",
2820 OFFSET(http_multiple
), AV_OPT_TYPE_BOOL
, {.i64
= -1}, -1, 1, FLAGS
},
2821 {"http_seekable", "Use HTTP partial requests, 0 = disable, 1 = enable, -1 = auto",
2822 OFFSET(http_seekable
), AV_OPT_TYPE_BOOL
, { .i64
= -1}, -1, 1, FLAGS
},
2823 {"seg_format_options", "Set options for segment demuxer",
2824 OFFSET(seg_format_opts
), AV_OPT_TYPE_DICT
, {.str
= NULL
}, 0, 0, FLAGS
},
2825 {"seg_max_retry", "Maximum number of times to reload a segment on error.",
2826 OFFSET(seg_max_retry
), AV_OPT_TYPE_INT
, {.i64
= 0}, 0, INT_MAX
, FLAGS
},
2830 static const AVClass hls_class
= {
2831 .class_name
= "hls demuxer",
2832 .item_name
= av_default_item_name
,
2833 .option
= hls_options
,
2834 .version
= LIBAVUTIL_VERSION_INT
,
2837 const FFInputFormat ff_hls_demuxer
= {
2839 .p
.long_name
= NULL_IF_CONFIG_SMALL("Apple HTTP Live Streaming"),
2840 .p
.priv_class
= &hls_class
,
2841 .p
.flags
= AVFMT_NOGENSEARCH
| AVFMT_TS_DISCONT
| AVFMT_NO_BYTE_SEEK
,
2842 .priv_data_size
= sizeof(HLSContext
),
2843 .flags_internal
= FF_INFMT_FLAG_INIT_CLEANUP
,
2844 .read_probe
= hls_probe
,
2845 .read_header
= hls_read_header
,
2846 .read_packet
= hls_read_packet
,
2847 .read_close
= hls_close
,
2848 .read_seek
= hls_read_seek
,