|
|
|
@@ -590,7 +590,7 @@ static void update_options(char **dest, const char *name, void *src) |
|
|
|
} |
|
|
|
|
|
|
|
static int open_url(AVFormatContext *s, AVIOContext **pb, const char *url, |
|
|
|
AVDictionary *opts, AVDictionary *opts2) |
|
|
|
AVDictionary *opts, AVDictionary *opts2, int *is_http) |
|
|
|
{ |
|
|
|
HLSContext *c = s->priv_data; |
|
|
|
AVDictionary *tmp = NULL; |
|
|
|
@@ -631,6 +631,9 @@ static int open_url(AVFormatContext *s, AVIOContext **pb, const char *url, |
|
|
|
|
|
|
|
av_dict_free(&tmp); |
|
|
|
|
|
|
|
if (is_http) |
|
|
|
*is_http = av_strstart(proto_name, "http", NULL); |
|
|
|
|
|
|
|
return ret; |
|
|
|
} |
|
|
|
|
|
|
|
@@ -1072,6 +1075,7 @@ static int open_input(HLSContext *c, struct playlist *pls, struct segment *seg) |
|
|
|
{ |
|
|
|
AVDictionary *opts = NULL; |
|
|
|
int ret; |
|
|
|
int is_http = 0; |
|
|
|
|
|
|
|
// broker prior HTTP options that should be consistent across requests |
|
|
|
av_dict_set(&opts, "user-agent", c->user_agent, 0); |
|
|
|
@@ -1091,13 +1095,13 @@ static int open_input(HLSContext *c, struct playlist *pls, struct segment *seg) |
|
|
|
seg->url, seg->url_offset, pls->index); |
|
|
|
|
|
|
|
if (seg->key_type == KEY_NONE) { |
|
|
|
ret = open_url(pls->parent, &pls->input, seg->url, c->avio_opts, opts); |
|
|
|
ret = open_url(pls->parent, &pls->input, seg->url, c->avio_opts, opts, &is_http); |
|
|
|
} else if (seg->key_type == KEY_AES_128) { |
|
|
|
AVDictionary *opts2 = NULL; |
|
|
|
char iv[33], key[33], url[MAX_URL_SIZE]; |
|
|
|
if (strcmp(seg->key, pls->key_url)) { |
|
|
|
AVIOContext *pb; |
|
|
|
if (open_url(pls->parent, &pb, seg->key, c->avio_opts, opts) == 0) { |
|
|
|
if (open_url(pls->parent, &pb, seg->key, c->avio_opts, opts, NULL) == 0) { |
|
|
|
ret = avio_read(pb, pls->key, sizeof(pls->key)); |
|
|
|
if (ret != sizeof(pls->key)) { |
|
|
|
av_log(NULL, AV_LOG_ERROR, "Unable to read key file %s\n", |
|
|
|
@@ -1122,7 +1126,7 @@ static int open_input(HLSContext *c, struct playlist *pls, struct segment *seg) |
|
|
|
av_dict_set(&opts2, "key", key, 0); |
|
|
|
av_dict_set(&opts2, "iv", iv, 0); |
|
|
|
|
|
|
|
ret = open_url(pls->parent, &pls->input, url, opts2, opts); |
|
|
|
ret = open_url(pls->parent, &pls->input, url, opts2, opts, &is_http); |
|
|
|
|
|
|
|
av_dict_free(&opts2); |
|
|
|
|
|
|
|
@@ -1140,8 +1144,15 @@ static int open_input(HLSContext *c, struct playlist *pls, struct segment *seg) |
|
|
|
|
|
|
|
/* Seek to the requested position. If this was a HTTP request, the offset |
|
|
|
* should already be where want it to, but this allows e.g. local testing |
|
|
|
* without a HTTP server. */ |
|
|
|
if (ret == 0 && seg->key_type == KEY_NONE && seg->url_offset) { |
|
|
|
* without a HTTP server. |
|
|
|
* |
|
|
|
* This is not done for HTTP at all as avio_seek() does internal bookkeeping |
|
|
|
* of file offset which is out-of-sync with the actual offset when "offset" |
|
|
|
* AVOption is used with http protocol, causing the seek to not be a no-op |
|
|
|
* as would be expected. Wrong offset received from the server will not be |
|
|
|
* noticed without the call, though. |
|
|
|
*/ |
|
|
|
if (ret == 0 && !is_http && seg->key_type == KEY_NONE && seg->url_offset) { |
|
|
|
int64_t seekret = avio_seek(pls->input, seg->url_offset, SEEK_SET); |
|
|
|
if (seekret < 0) { |
|
|
|
av_log(pls->parent, AV_LOG_ERROR, "Unable to seek to offset %"PRId64" of HLS segment '%s'\n", seg->url_offset, seg->url); |
|
|
|
|