42 #define INITIAL_BUFFER_SIZE 32768
44 #define MAX_FIELD_LEN 64
45 #define MAX_CHARACTERISTICS_LEN 512
47 #define MPEG_TIME_BASE 90000
48 #define MPEG_TIME_BASE_Q (AVRational){1, MPEG_TIME_BASE}
288 const char *
url,
const char *base)
314 int key_len,
char **dest,
int *dest_len)
316 if (!strncmp(key,
"BANDWIDTH=", key_len)) {
319 }
else if (!strncmp(key,
"AUDIO=", key_len)) {
321 *dest_len =
sizeof(info->
audio);
322 }
else if (!strncmp(key,
"VIDEO=", key_len)) {
324 *dest_len =
sizeof(info->
video);
325 }
else if (!strncmp(key,
"SUBTITLES=", key_len)) {
338 int key_len,
char **dest,
int *dest_len)
340 if (!strncmp(key,
"METHOD=", key_len)) {
342 *dest_len =
sizeof(info->
method);
343 }
else if (!strncmp(key,
"URI=", key_len)) {
345 *dest_len =
sizeof(info->
uri);
346 }
else if (!strncmp(key,
"IV=", key_len)) {
348 *dest_len =
sizeof(info->
iv);
365 const char *url_base)
369 char *characteristic;
373 if (!strcmp(info->
type,
"AUDIO"))
375 else if (!strcmp(info->
type,
"VIDEO"))
377 else if (!strcmp(info->
type,
"SUBTITLES"))
379 else if (!strcmp(info->
type,
"CLOSED-CAPTIONS"))
415 int langlen = strlen(rend->
language);
416 if (langlen <
sizeof(rend->
language) - 3) {
419 sizeof(rend->
language) - langlen - 2);
425 if (!strcmp(info->
forced,
"YES"))
429 while ((characteristic =
av_strtok(chr_ptr,
",", &saveptr))) {
430 if (!strcmp(characteristic,
"public.accessibility.describes-music-and-sound"))
432 else if (!strcmp(characteristic,
"public.accessibility.describes-video"))
442 int key_len,
char **dest,
int *dest_len)
444 if (!strncmp(key,
"TYPE=", key_len)) {
446 *dest_len =
sizeof(info->
type);
447 }
else if (!strncmp(key,
"URI=", key_len)) {
449 *dest_len =
sizeof(info->
uri);
450 }
else if (!strncmp(key,
"GROUP-ID=", key_len)) {
453 }
else if (!strncmp(key,
"LANGUAGE=", key_len)) {
456 }
else if (!strncmp(key,
"ASSOC-LANGUAGE=", key_len)) {
459 }
else if (!strncmp(key,
"NAME=", key_len)) {
461 *dest_len =
sizeof(info->
name);
462 }
else if (!strncmp(key,
"DEFAULT=", key_len)) {
465 }
else if (!strncmp(key,
"FORCED=", key_len)) {
467 *dest_len =
sizeof(info->
forced);
468 }
else if (!strncmp(key,
"CHARACTERISTICS=", key_len)) {
498 int ret = 0, is_segment = 0, is_variant = 0;
507 int64_t seg_offset = 0;
508 int64_t seg_size = -1;
535 if (strcmp(line,
"#EXTM3U")) {
547 if (
av_strstart(line,
"#EXT-X-STREAM-INF:", &ptr)) {
549 memset(&variant_info, 0,
sizeof(variant_info));
552 }
else if (
av_strstart(line,
"#EXT-X-KEY:", &ptr)) {
558 if (!strcmp(info.
method,
"AES-128"))
560 if (!strcmp(info.
method,
"SAMPLE-AES"))
562 if (!strncmp(info.
iv,
"0x", 2) || !strncmp(info.
iv,
"0X", 2)) {
567 }
else if (
av_strstart(line,
"#EXT-X-MEDIA:", &ptr)) {
572 }
else if (
av_strstart(line,
"#EXT-X-TARGETDURATION:", &ptr)) {
577 }
else if (
av_strstart(line,
"#EXT-X-MEDIA-SEQUENCE:", &ptr)) {
582 }
else if (
av_strstart(line,
"#EXT-X-PLAYLIST-TYPE:", &ptr)) {
586 if (!strcmp(ptr,
"EVENT"))
588 else if (!strcmp(ptr,
"VOD"))
590 }
else if (
av_strstart(line,
"#EXT-X-ENDLIST", &ptr)) {
596 }
else if (
av_strstart(line,
"#EXT-X-BYTERANGE:", &ptr)) {
597 seg_size = atoi(ptr);
598 ptr = strchr(ptr,
'@');
600 seg_offset = atoi(ptr+1);
603 }
else if (line[0]) {
628 memcpy(seg->
iv, iv,
sizeof(iv));
631 memset(seg->
iv, 0,
sizeof(seg->
iv));
659 seg->
size = seg_size;
662 seg_offset += seg_size;
713 static const char id3_priv_owner_ts[] =
"com.apple.streaming.transportStreamTimestamp";
717 for (meta = *extra_meta; meta; meta = meta->
next) {
718 if (!strcmp(meta->
tag,
"PRIV")) {
720 if (priv->
datasize == 8 && !strcmp(priv->
owner, id3_priv_owner_ts)) {
724 if ((ts & ~((1ULL << 33) - 1)) == 0)
729 }
else if (!strcmp(meta->
tag,
"APIC") && apic)
743 if (!oldentry || strcmp(oldentry->
value, entry->
value) != 0)
771 parse_id3(pls->
ctx, pb, &metadata, ×tamp, &apic, &extra_meta);
807 int buf_size,
int *
len)
829 }
else if (*len <= 0) {
841 int64_t maxsize = seg->
size >= 0 ? seg->
size : 1024*1024;
843 int tag_got_bytes =
FFMIN(taglen, *len);
844 int remaining = taglen - tag_got_bytes;
846 if (taglen > maxsize) {
862 memcpy(pls->
id3_buf + id3_buf_pos, buf, tag_got_bytes);
863 id3_buf_pos += tag_got_bytes;
866 *len -= tag_got_bytes;
867 memmove(buf, buf + tag_got_bytes, *len);
874 id3_buf_pos += remaining;
885 if (*len >= 0 && (fill_buf || *len == 0)) {
922 if (seg->
size >= 0) {
943 !=
sizeof(pls->
key)) {
956 iv[32] = key[32] =
'\0';
957 if (strstr(seg->
url,
"://"))
975 "SAMPLE-AES encryption is not supported yet\n");
1013 int just_opened = 0;
1020 int64_t reload_interval;
1058 "skipping %d segments ahead, expired from playlists\n",
1104 int variant_count = 0;
1107 for (i = 0; i < c->
n_variants && variant_count < 2; i++) {
1118 return variant_count >= 2;
1129 if (rend->
type == type && !strcmp(rend->
group_id, group_id)) {
1160 if (rend->
type != type)
1178 int64_t timestamp,
int *seq_no)
1184 if (timestamp < pos) {
1244 int ret = 0, i, j, stream_offset = 0;
1248 c->first_packet = 1;
1257 if (
c->user_agent && !strlen(
c->user_agent))
1263 if (
c->cookies && !strlen(
c->cookies))
1269 if (
c->headers && !strlen(
c->headers))
1276 if (
c->n_variants == 0) {
1283 if (
c->n_playlists > 1 ||
c->playlists[0]->n_segments == 0) {
1284 for (i = 0; i <
c->n_playlists; i++) {
1291 if (
c->variants[0]->playlists[0]->n_segments == 0) {
1299 if (
c->variants[0]->playlists[0]->finished) {
1301 for (i = 0; i <
c->variants[0]->playlists[0]->n_segments; i++)
1302 duration +=
c->variants[0]->playlists[0]->segments[i]->duration;
1307 for (i = 0; i <
c->n_variants; i++) {
1308 struct variant *var =
c->variants[i];
1319 for (i = 0; i <
c->n_playlists; i++) {
1403 for (i = 0; i <
c->n_variants; i++) {
1512 int64_t ts_b,
struct playlist *pls_b)
1523 int ret, i, minplaylist = -1;
1581 struct playlist *minpls = minplaylist < 0 ?
1583 if (minplaylist < 0) {
1586 int64_t dts = pls->
pkt.
dts;
1587 int64_t mindts = minpls->
pkt.
dts;
1597 if (minplaylist >= 0) {
1624 int64_t timestamp,
int flags)
1646 if (0 < duration && duration < seek_timestamp - first_timestamp)
1687 if (pls != seek_pls) {
1707 if (strncmp(p->
buf,
"#EXTM3U", 7))
1709 if (strstr(p->
buf,
"#EXT-X-STREAM-INF:") ||
1710 strstr(p->
buf,
"#EXT-X-TARGETDURATION:") ||
1711 strstr(p->
buf,
"#EXT-X-MEDIA-SEQUENCE:"))
1717 .
name =
"hls,applehttp",