Reviewed-by: Steven Liu <lingjiujianke@gmail.com>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
... | ... |
@@ -247,6 +247,8 @@ DASH-templated name to used for the initialization segment. Default is "init-str |
247 | 247 |
DASH-templated name to used for the media segments. Default is "chunk-stream$RepresentationID$-$Number%05d$.m4s" |
248 | 248 |
@item -utc_timing_url @var{utc_url} |
249 | 249 |
URL of the page that will return the UTC timestamp in ISO format. Example: "https://time.akamai.com/?iso" |
250 |
+@item -http_user_agent @var{user_agent} |
|
251 |
+Override User-Agent field in HTTP header. Applicable only for HTTP output. |
|
250 | 252 |
@item -adaptation_sets @var{adaptation_sets} |
251 | 253 |
Assign streams to AdaptationSets. Syntax is "id=x,streams=a,b,c id=y,streams=d,e" with x and y being the IDs |
252 | 254 |
of the adaptation sets and a,b,c,d and e are the indices of the mapped streams. |
... | ... |
@@ -100,6 +100,7 @@ typedef struct DASHContext { |
100 | 100 |
const char *init_seg_name; |
101 | 101 |
const char *media_seg_name; |
102 | 102 |
const char *utc_timing_url; |
103 |
+ const char *user_agent; |
|
103 | 104 |
} DASHContext; |
104 | 105 |
|
105 | 106 |
static struct codec_string { |
... | ... |
@@ -210,6 +211,12 @@ static int flush_dynbuf(OutputStream *os, int *range_length) |
210 | 210 |
return avio_open_dyn_buf(&os->ctx->pb); |
211 | 211 |
} |
212 | 212 |
|
213 |
+static void set_http_options(AVDictionary **options, DASHContext *c) |
|
214 |
+{ |
|
215 |
+ if (c->user_agent) |
|
216 |
+ av_dict_set(options, "user_agent", c->user_agent, 0); |
|
217 |
+} |
|
218 |
+ |
|
213 | 219 |
static int flush_init_segment(AVFormatContext *s, OutputStream *os) |
214 | 220 |
{ |
215 | 221 |
DASHContext *c = s->priv_data; |
... | ... |
@@ -575,16 +582,19 @@ static int write_manifest(AVFormatContext *s, int final) |
575 | 575 |
int use_rename = proto && !strcmp(proto, "file"); |
576 | 576 |
static unsigned int warned_non_file = 0; |
577 | 577 |
AVDictionaryEntry *title = av_dict_get(s->metadata, "title", NULL, 0); |
578 |
+ AVDictionary *opts = NULL; |
|
578 | 579 |
|
579 | 580 |
if (!use_rename && !warned_non_file++) |
580 | 581 |
av_log(s, AV_LOG_ERROR, "Cannot use rename on non file protocol, this may lead to races and temporary partial files\n"); |
581 | 582 |
|
582 | 583 |
snprintf(temp_filename, sizeof(temp_filename), use_rename ? "%s.tmp" : "%s", s->filename); |
583 |
- ret = s->io_open(s, &out, temp_filename, AVIO_FLAG_WRITE, NULL); |
|
584 |
+ set_http_options(&opts, c); |
|
585 |
+ ret = s->io_open(s, &out, temp_filename, AVIO_FLAG_WRITE, &opts); |
|
584 | 586 |
if (ret < 0) { |
585 | 587 |
av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", temp_filename); |
586 | 588 |
return ret; |
587 | 589 |
} |
590 |
+ av_dict_free(&opts); |
|
588 | 591 |
avio_printf(out, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"); |
589 | 592 |
avio_printf(out, "<MPD xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" |
590 | 593 |
"\txmlns=\"urn:mpeg:dash:schema:mpd:2011\"\n" |
... | ... |
@@ -768,9 +778,11 @@ static int dash_init(AVFormatContext *s) |
768 | 768 |
ff_dash_fill_tmpl_params(os->initfile, sizeof(os->initfile), c->init_seg_name, i, 0, os->bit_rate, 0); |
769 | 769 |
} |
770 | 770 |
snprintf(filename, sizeof(filename), "%s%s", c->dirname, os->initfile); |
771 |
- ret = s->io_open(s, &os->out, filename, AVIO_FLAG_WRITE, NULL); |
|
771 |
+ set_http_options(&opts, c); |
|
772 |
+ ret = s->io_open(s, &os->out, filename, AVIO_FLAG_WRITE, &opts); |
|
772 | 773 |
if (ret < 0) |
773 | 774 |
return ret; |
775 |
+ av_dict_free(&opts); |
|
774 | 776 |
os->init_start_pos = 0; |
775 | 777 |
|
776 | 778 |
if (!strcmp(os->format_name, "mp4")) { |
... | ... |
@@ -974,12 +986,15 @@ static int dash_flush(AVFormatContext *s, int final, int stream) |
974 | 974 |
} |
975 | 975 |
|
976 | 976 |
if (!c->single_file) { |
977 |
+ AVDictionary *opts = NULL; |
|
977 | 978 |
ff_dash_fill_tmpl_params(filename, sizeof(filename), c->media_seg_name, i, os->segment_index, os->bit_rate, os->start_pts); |
978 | 979 |
snprintf(full_path, sizeof(full_path), "%s%s", c->dirname, filename); |
979 | 980 |
snprintf(temp_path, sizeof(temp_path), use_rename ? "%s.tmp" : "%s", full_path); |
980 |
- ret = s->io_open(s, &os->out, temp_path, AVIO_FLAG_WRITE, NULL); |
|
981 |
+ set_http_options(&opts, c); |
|
982 |
+ ret = s->io_open(s, &os->out, temp_path, AVIO_FLAG_WRITE, &opts); |
|
981 | 983 |
if (ret < 0) |
982 | 984 |
break; |
985 |
+ av_dict_free(&opts); |
|
983 | 986 |
if (!strcmp(os->format_name, "mp4")) |
984 | 987 |
write_styp(os->ctx->pb); |
985 | 988 |
} else { |
... | ... |
@@ -1190,6 +1205,7 @@ static const AVOption options[] = { |
1190 | 1190 |
{ "init_seg_name", "DASH-templated name to used for the initialization segment", OFFSET(init_seg_name), AV_OPT_TYPE_STRING, {.str = "init-stream$RepresentationID$.m4s"}, 0, 0, E }, |
1191 | 1191 |
{ "media_seg_name", "DASH-templated name to used for the media segments", OFFSET(media_seg_name), AV_OPT_TYPE_STRING, {.str = "chunk-stream$RepresentationID$-$Number%05d$.m4s"}, 0, 0, E }, |
1192 | 1192 |
{ "utc_timing_url", "URL of the page that will return the UTC timestamp in ISO format", OFFSET(utc_timing_url), AV_OPT_TYPE_STRING, { 0 }, 0, 0, E }, |
1193 |
+ { "http_user_agent", "override User-Agent field in HTTP header", OFFSET(user_agent), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E}, |
|
1193 | 1194 |
{ NULL }, |
1194 | 1195 |
}; |
1195 | 1196 |
|