summaryrefslogtreecommitdiff
path: root/libavformat/hls.c
diff options
context:
space:
mode:
authorLuca Barbato <lu_zero@gentoo.org>2015-07-23 21:11:58 +0200
committerLuca Barbato <lu_zero@gentoo.org>2015-07-30 11:21:26 +0200
commit0c73a5a53cc97f4291bbe9e1e68226edf6161744 (patch)
tree361996a831f274e0f85c4923476ba799c3edaefb /libavformat/hls.c
parent5ae178539b91d25710b7bb322d156c31aea9f8bf (diff)
hls: Save and forward avio options
Make possible to send the custom headers and override the user agent. Reported-by: BenWonder
Diffstat (limited to 'libavformat/hls.c')
-rw-r--r--libavformat/hls.c93
1 files changed, 80 insertions, 13 deletions
diff --git a/libavformat/hls.c b/libavformat/hls.c
index 8b52a35508..467a4913a5 100644
--- a/libavformat/hls.c
+++ b/libavformat/hls.c
@@ -103,6 +103,7 @@ typedef struct HLSContext {
int64_t seek_timestamp;
int seek_flags;
AVIOInterruptCB *interrupt_callback;
+ AVDictionary *avio_opts;
} HLSContext;
static int read_chomp_line(AVIOContext *s, char *buf, int maxlen)
@@ -199,6 +200,51 @@ static void handle_key_args(struct key_info *info, const char *key,
}
}
+static int open_in(HLSContext *c, AVIOContext **in, const char *url)
+{
+ AVDictionary *tmp = NULL;
+ int ret;
+
+ av_dict_copy(&tmp, c->avio_opts, 0);
+
+ ret = avio_open2(in, url, AVIO_FLAG_READ, c->interrupt_callback, &tmp);
+
+ av_dict_free(&tmp);
+ return ret;
+}
+
+static int url_connect(struct variant *var, AVDictionary *opts)
+{
+ AVDictionary *tmp = NULL;
+ int ret;
+
+ av_dict_copy(&tmp, opts, 0);
+
+ av_opt_set_dict(var->input, &tmp);
+
+ if ((ret = ffurl_connect(var->input, NULL)) < 0) {
+ ffurl_close(var->input);
+ var->input = NULL;
+ }
+
+ av_dict_free(&tmp);
+ return ret;
+}
+
+static int open_url(HLSContext *c, URLContext **uc, const char *url)
+{
+ AVDictionary *tmp = NULL;
+ int ret;
+
+ av_dict_copy(&tmp, c->avio_opts, 0);
+
+ ret = ffurl_open(uc, url, AVIO_FLAG_READ, c->interrupt_callback, &tmp);
+
+ av_dict_free(&tmp);
+
+ return ret;
+}
+
static int parse_playlist(HLSContext *c, const char *url,
struct variant *var, AVIOContext *in)
{
@@ -214,10 +260,10 @@ static int parse_playlist(HLSContext *c, const char *url,
uint8_t *new_url = NULL;
if (!in) {
- close_in = 1;
- if ((ret = avio_open2(&in, url, AVIO_FLAG_READ,
- c->interrupt_callback, NULL)) < 0)
+ ret = open_in(c, &in, url);
+ if (ret < 0)
return ret;
+ close_in = 1;
}
if (av_opt_get(in, "location", AV_OPT_SEARCH_CHILDREN, &new_url) >= 0)
@@ -333,15 +379,14 @@ static int open_input(struct variant *var)
{
struct segment *seg = var->segments[var->cur_seq_no - var->start_seq_no];
if (seg->key_type == KEY_NONE) {
- return ffurl_open(&var->input, seg->url, AVIO_FLAG_READ,
- &var->parent->interrupt_callback, NULL);
+ return open_url(var->parent->priv_data, &var->input, seg->url);
} else if (seg->key_type == KEY_AES_128) {
+ HLSContext *c = var->parent->priv_data;
char iv[33], key[33], url[MAX_URL_SIZE];
int ret;
if (strcmp(seg->key, var->key_url)) {
URLContext *uc;
- if (ffurl_open(&uc, seg->key, AVIO_FLAG_READ,
- &var->parent->interrupt_callback, NULL) == 0) {
+ if (open_url(var->parent->priv_data, &uc, seg->key) == 0) {
if (ffurl_read_complete(uc, var->key, sizeof(var->key))
!= sizeof(var->key)) {
av_log(NULL, AV_LOG_ERROR, "Unable to read key file %s\n",
@@ -366,12 +411,8 @@ static int open_input(struct variant *var)
return ret;
av_opt_set(var->input->priv_data, "key", key, 0);
av_opt_set(var->input->priv_data, "iv", iv, 0);
- if ((ret = ffurl_connect(var->input, NULL)) < 0) {
- ffurl_close(var->input);
- var->input = NULL;
- return ret;
- }
- return 0;
+
+ return url_connect(var, c->avio_opts);
}
return AVERROR(ENOSYS);
}
@@ -449,6 +490,26 @@ reload:
goto restart;
}
+static int save_avio_options(AVFormatContext *s)
+{
+ HLSContext *c = s->priv_data;
+ const char *opts[] = { "headers", "user_agent", NULL }, **opt = opts;
+ uint8_t *buf;
+ int ret = 0;
+
+ while (*opt) {
+ if (av_opt_get(s->pb, *opt, AV_OPT_SEARCH_CHILDREN, &buf) >= 0) {
+ ret = av_dict_set(&c->avio_opts, *opt, buf,
+ AV_DICT_DONT_STRDUP_VAL);
+ if (ret < 0)
+ return ret;
+ }
+ opt++;
+ }
+
+ return ret;
+}
+
static int hls_read_header(AVFormatContext *s)
{
HLSContext *c = s->priv_data;
@@ -459,6 +520,9 @@ static int hls_read_header(AVFormatContext *s)
if ((ret = parse_playlist(c, s->filename, NULL, s->pb)) < 0)
goto fail;
+ if ((ret = save_avio_options(s)) < 0)
+ goto fail;
+
if (c->n_variants == 0) {
av_log(NULL, AV_LOG_WARNING, "Empty playlist\n");
ret = AVERROR_EOF;
@@ -712,6 +776,9 @@ static int hls_close(AVFormatContext *s)
HLSContext *c = s->priv_data;
free_variant_list(c);
+
+ av_dict_free(&c->avio_opts);
+
return 0;
}