* commit '0c73a5a53cc97f4291bbe9e1e68226edf6161744': hls: Save and forward avio options Conflicts: libavformat/hls.c
Unified · Split
| @@ -182,6 +182,7 @@ typedef struct HLSContext { · 181 unmodified lines | ||
| 182 | 182 | char *user_agent; ///< holds HTTP user agent set as an AVOption to the HTTP protocol context |
| 183 | 183 | char *cookies; ///< holds HTTP cookie values set in either the initial response or as an AVOption to the HTTP protocol context |
| 184 | 184 | char *headers; ///< holds HTTP headers set as an AVOption to the HTTP protocol context |
| 185 | + AVDictionary *avio_opts; | |
| 185 | 186 | } HLSContext; |
| 186 | 187 | |
| 187 | 188 | static int read_chomp_line(AVIOContext *s, char *buf, int maxlen) |
| @@ -494,6 +495,53 @@ static int ensure_playlist(HLSContext *c, struct playlist **pls, const char *url · 306 unmodified lines | ||
| 494 | 495 | |
| 495 | 496 | /* pls = NULL => Master Playlist or parentless Media Playlist |
| 496 | 497 | * pls = !NULL => parented Media Playlist, playlist+variant allocated */ |
| 498 | +static int open_in(HLSContext *c, AVIOContext **in, const char *url) | |
| 499 | +{ | |
| 500 | + AVDictionary *tmp = NULL; | |
| 501 | + int ret; | |
| 502 | + | |
| 503 | + av_dict_copy(&tmp, c->avio_opts, 0); | |
| 504 | + | |
| 505 | + ret = avio_open2(in, url, AVIO_FLAG_READ, c->interrupt_callback, &tmp); | |
| 506 | + | |
| 507 | + av_dict_free(&tmp); | |
| 508 | + return ret; | |
| 509 | +} | |
| 510 | + | |
| 511 | +static int url_connect(struct playlist *pls, AVDictionary *opts, AVDictionary *opts2) | |
| 512 | +{ | |
| 513 | + AVDictionary *tmp = NULL; | |
| 514 | + int ret; | |
| 515 | + | |
| 516 | + av_dict_copy(&tmp, opts, 0); | |
| 517 | + av_dict_copy(&tmp, opts2, 0); | |
| 518 | + | |
| 519 | + av_opt_set_dict(pls->input, &tmp); | |
| 520 | + | |
| 521 | + if ((ret = ffurl_connect(pls->input, NULL)) < 0) { | |
| 522 | + ffurl_close(pls->input); | |
| 523 | + pls->input = NULL; | |
| 524 | + } | |
| 525 | + | |
| 526 | + av_dict_free(&tmp); | |
| 527 | + return ret; | |
| 528 | +} | |
| 529 | + | |
| 530 | +static int open_url(HLSContext *c, URLContext **uc, const char *url, AVDictionary *opts) | |
| 531 | +{ | |
| 532 | + AVDictionary *tmp = NULL; | |
| 533 | + int ret; | |
| 534 | + | |
| 535 | + av_dict_copy(&tmp, c->avio_opts, 0); | |
| 536 | + av_dict_copy(&tmp, opts, 0); | |
| 537 | + | |
| 538 | + ret = ffurl_open(uc, url, AVIO_FLAG_READ, c->interrupt_callback, &tmp); | |
| 539 | + | |
| 540 | + av_dict_free(&tmp); | |
| 541 | + | |
| 542 | + return ret; | |
| 543 | +} | |
| 544 | + | |
| 497 | 545 | static int parse_playlist(HLSContext *c, const char *url, |
| 498 | 546 | struct playlist *pls, AVIOContext *in) |
| 499 | 547 | { |
| @@ -513,6 +561,7 @@ static int parse_playlist(HLSContext *c, const char *url, · 13 unmodified lines | ||
| 513 | 561 | char tmp_str[MAX_URL_SIZE]; |
| 514 | 562 | |
| 515 | 563 | if (!in) { |
| 564 | +#if 1 | |
| 516 | 565 | AVDictionary *opts = NULL; |
| 517 | 566 | close_in = 1; |
| 518 | 567 | /* Some HLS servers don't like being sent the range header */ |
| @@ -528,6 +577,12 @@ static int parse_playlist(HLSContext *c, const char *url, · 9 unmodified lines | ||
| 528 | 577 | av_dict_free(&opts); |
| 529 | 578 | if (ret < 0) |
| 530 | 579 | return ret; |
| 580 | +#else | |
| 581 | + ret = open_in(c, &in, url); | |
| 582 | + if (ret < 0) | |
| 583 | + return ret; | |
| 584 | + close_in = 1; | |
| 585 | +#endif | |
| 531 | 586 | } |
| 532 | 587 | |
| 533 | 588 | if (av_opt_get(in, "location", AV_OPT_SEARCH_CHILDREN, &new_url) >= 0) |
| @@ -940,15 +995,13 @@ static int open_input(HLSContext *c, struct playlist *pls) · 406 unmodified lines | ||
| 940 | 995 | seg->url, seg->url_offset, pls->index); |
| 941 | 996 | |
| 942 | 997 | if (seg->key_type == KEY_NONE) { |
| 943 | − ret = ffurl_open(&pls->input, seg->url, AVIO_FLAG_READ, | |
| 944 | − &pls->parent->interrupt_callback, &opts); | |
| 945 | − | |
| 998 | + ret = open_url(pls->parent->priv_data, &pls->input, seg->url, opts); | |
| 946 | 999 | } else if (seg->key_type == KEY_AES_128) { |
| 1000 | +// HLSContext *c = var->parent->priv_data; | |
| 947 | 1001 | char iv[33], key[33], url[MAX_URL_SIZE]; |
| 948 | 1002 | if (strcmp(seg->key, pls->key_url)) { |
| 949 | 1003 | URLContext *uc; |
| 950 | − if (ffurl_open(&uc, seg->key, AVIO_FLAG_READ, | |
| 951 | − &pls->parent->interrupt_callback, &opts2) == 0) { | |
| 1004 | + if (open_url(pls->parent->priv_data, &uc, seg->key, opts2) == 0) { | |
| 952 | 1005 | if (ffurl_read_complete(uc, pls->key, sizeof(pls->key)) |
| 953 | 1006 | != sizeof(pls->key)) { |
| 954 | 1007 | av_log(NULL, AV_LOG_ERROR, "Unable to read key file %s\n", |
| @@ -970,15 +1023,14 @@ static int open_input(HLSContext *c, struct playlist *pls) · 15 unmodified lines | ||
| 970 | 1023 | snprintf(url, sizeof(url), "crypto+%s", seg->url); |
| 971 | 1024 | else |
| 972 | 1025 | snprintf(url, sizeof(url), "crypto:%s", seg->url); |
| 1026 | + | |
| 973 | 1027 | if ((ret = ffurl_alloc(&pls->input, url, AVIO_FLAG_READ, |
| 974 | 1028 | &pls->parent->interrupt_callback)) < 0) |
| 975 | 1029 | goto cleanup; |
| 976 | 1030 | av_opt_set(pls->input->priv_data, "key", key, 0); |
| 977 | 1031 | av_opt_set(pls->input->priv_data, "iv", iv, 0); |
| 978 | 1032 | |
| 979 | − if ((ret = ffurl_connect(pls->input, &opts)) < 0) { | |
| 980 | − ffurl_close(pls->input); | |
| 981 | − pls->input = NULL; | |
| 1033 | + if ((ret = url_connect(pls, c->avio_opts, opts)) < 0) { | |
| 982 | 1034 | goto cleanup; |
| 983 | 1035 | } |
| 984 | 1036 | ret = 0; |
| @@ -1254,6 +1306,26 @@ static int select_cur_seq_no(HLSContext *c, struct playlist *pls) · 269 unmodified lines | ||
| 1254 | 1306 | return pls->start_seq_no; |
| 1255 | 1307 | } |
| 1256 | 1308 | |
| 1309 | +static int save_avio_options(AVFormatContext *s) | |
| 1310 | +{ | |
| 1311 | + HLSContext *c = s->priv_data; | |
| 1312 | + const char *opts[] = { "headers", "user_agent", "user-agent", "cookies", NULL }, **opt = opts; | |
| 1313 | + uint8_t *buf; | |
| 1314 | + int ret = 0; | |
| 1315 | + | |
| 1316 | + while (*opt) { | |
| 1317 | + if (av_opt_get(s->pb, *opt, AV_OPT_SEARCH_CHILDREN, &buf) >= 0) { | |
| 1318 | + ret = av_dict_set(&c->avio_opts, *opt, buf, | |
| 1319 | + AV_DICT_DONT_STRDUP_VAL); | |
| 1320 | + if (ret < 0) | |
| 1321 | + return ret; | |
| 1322 | + } | |
| 1323 | + opt++; | |
| 1324 | + } | |
| 1325 | + | |
| 1326 | + return ret; | |
| 1327 | +} | |
| 1328 | + | |
| 1257 | 1329 | static int hls_read_header(AVFormatContext *s) |
| 1258 | 1330 | { |
| 1259 | 1331 | URLContext *u = (s->flags & AVFMT_FLAG_CUSTOM_IO) ? NULL : s->pb->opaque; |
| @@ -1281,6 +1353,12 @@ static int hls_read_header(AVFormatContext *s) · 21 unmodified lines | ||
| 1281 | 1353 | if ((ret = parse_playlist(c, s->filename, NULL, s->pb)) < 0) |
| 1282 | 1354 | goto fail; |
| 1283 | 1355 | |
| 1356 | + if ((ret = save_avio_options(s)) < 0) | |
| 1357 | + goto fail; | |
| 1358 | + | |
| 1359 | + /* Some HLS servers don't like being sent the range header */ | |
| 1360 | + av_dict_set(&c->avio_opts, "seekable", "0", 0); | |
| 1361 | + | |
| 1284 | 1362 | if (c->n_variants == 0) { |
| 1285 | 1363 | av_log(NULL, AV_LOG_WARNING, "Empty playlist\n"); |
| 1286 | 1364 | ret = AVERROR_EOF; |
| @@ -1631,6 +1709,9 @@ static int hls_close(AVFormatContext *s) · 344 unmodified lines | ||
| 1631 | 1709 | free_playlist_list(c); |
| 1632 | 1710 | free_variant_list(c); |
| 1633 | 1711 | free_rendition_list(c); |
| 1712 | + | |
| 1713 | + av_dict_free(&c->avio_opts); | |
| 1714 | + | |
| 1634 | 1715 | return 0; |
| 1635 | 1716 | } |
| 1636 | 1717 | |