demux_lavf: set stream network options if applicable

Normally, we pass libavformat demuxers a wrapped mpv stream. But in some
cases, such as HLS and RTSP, we let libavformat open the stream itself.
In these cases, set typical network properties like useragent according
to the mpv options.

(We still don't set it for the cases where libavformat opens other
streams on its own, e.g. when opening the companion .sub file for .idx
files - not sure if we maybe should always set these options.)
This commit is contained in:
wm4 2014-10-14 21:01:30 +02:00
parent ffd3ae1fad
commit 9241e1bf10
3 changed files with 50 additions and 31 deletions

View File

@ -706,10 +706,13 @@ static int demux_open_lavf(demuxer_t *demuxer, enum demux_check check)
"analyzeduration to %f\n", analyze_duration); "analyzeduration to %f\n", analyze_duration);
} }
AVDictionary *dopts = NULL;
if ((priv->avif->flags & AVFMT_NOFILE) || if ((priv->avif->flags & AVFMT_NOFILE) ||
demuxer->stream->type == STREAMTYPE_AVDEVICE || demuxer->stream->type == STREAMTYPE_AVDEVICE ||
matches_avinputformat_name(priv, "hls")) matches_avinputformat_name(priv, "hls"))
{ {
mp_setup_av_network_options(&dopts, demuxer->global, demuxer->log, opts);
// This might be incorrect. // This might be incorrect.
demuxer->seekable = true; demuxer->seekable = true;
} else { } else {
@ -727,8 +730,6 @@ static int demux_open_lavf(demuxer_t *demuxer, enum demux_check check)
avfc->pb = priv->pb; avfc->pb = priv->pb;
} }
AVDictionary *dopts = NULL;
if (matches_avinputformat_name(priv, "rtsp")) { if (matches_avinputformat_name(priv, "rtsp")) {
const char *transport = NULL; const char *transport = NULL;
switch (opts->network_rtsp_transport) { switch (opts->network_rtsp_transport) {

View File

@ -268,6 +268,13 @@ void mp_cancel_reset(struct mp_cancel *c);
char *mp_file_url_to_filename(void *talloc_ctx, bstr url); char *mp_file_url_to_filename(void *talloc_ctx, bstr url);
char *mp_file_get_path(void *talloc_ctx, bstr url); char *mp_file_get_path(void *talloc_ctx, bstr url);
// stream_lavf.c
struct AVDictionary;
void mp_setup_av_network_options(struct AVDictionary **dict,
struct mpv_global *global,
struct mp_log *log,
struct MPOpts *opts);
void stream_print_proto_list(struct mp_log *log); void stream_print_proto_list(struct mp_log *log);
#endif /* MPLAYER_STREAM_H */ #endif /* MPLAYER_STREAM_H */

View File

@ -143,6 +143,45 @@ static int interrupt_cb(void *ctx)
static const char * const prefix[] = { "lavf://", "ffmpeg://" }; static const char * const prefix[] = { "lavf://", "ffmpeg://" };
void mp_setup_av_network_options(AVDictionary **dict, struct mpv_global *global,
struct mp_log *log, struct MPOpts *opts)
{
void *temp = talloc_new(NULL);
// HTTP specific options (other protocols ignore them)
if (opts->network_useragent)
av_dict_set(dict, "user-agent", opts->network_useragent, 0);
if (opts->network_cookies_enabled) {
char *file = opts->network_cookies_file;
if (file && file[0])
file = mp_get_user_path(temp, global, file);
char *cookies = cookies_lavf(temp, log, file);
if (cookies && cookies[0])
av_dict_set(dict, "cookies", cookies, 0);
}
av_dict_set(dict, "tls_verify", opts->network_tls_verify ? "1" : "0", 0);
if (opts->network_tls_ca_file)
av_dict_set(dict, "ca_file", opts->network_tls_ca_file, 0);
char *cust_headers = talloc_strdup(temp, "");
if (opts->network_referrer) {
cust_headers = talloc_asprintf_append(cust_headers, "Referer: %s\r\n",
opts->network_referrer);
}
if (opts->network_http_header_fields) {
for (int n = 0; opts->network_http_header_fields[n]; n++) {
cust_headers = talloc_asprintf_append(cust_headers, "%s\r\n",
opts->network_http_header_fields[n]);
}
}
if (strlen(cust_headers))
av_dict_set(dict, "headers", cust_headers, 0);
av_dict_set(dict, "icy", "1", 0);
mp_set_avdict(dict, opts->stream_lavf_opts->avopts);
talloc_free(temp);
}
static int open_f(stream_t *stream) static int open_f(stream_t *stream)
{ {
struct MPOpts *opts = stream->opts; struct MPOpts *opts = stream->opts;
@ -186,35 +225,7 @@ static int open_f(stream_t *stream)
filename = talloc_asprintf(temp, "mmsh://%.*s", BSTR_P(b_filename)); filename = talloc_asprintf(temp, "mmsh://%.*s", BSTR_P(b_filename));
} }
// HTTP specific options (other protocols ignore them) mp_setup_av_network_options(&dict, stream->global, stream->log, opts);
if (opts->network_useragent)
av_dict_set(&dict, "user-agent", opts->network_useragent, 0);
if (opts->network_cookies_enabled) {
char *file = opts->network_cookies_file;
if (file && file[0])
file = mp_get_user_path(temp, stream->global, file);
char *cookies = cookies_lavf(temp, stream->log, file);
if (cookies && cookies[0])
av_dict_set(&dict, "cookies", cookies, 0);
}
av_dict_set(&dict, "tls_verify", opts->network_tls_verify ? "1" : "0", 0);
if (opts->network_tls_ca_file)
av_dict_set(&dict, "ca_file", opts->network_tls_ca_file, 0);
char *cust_headers = talloc_strdup(temp, "");
if (opts->network_referrer) {
cust_headers = talloc_asprintf_append(cust_headers, "Referer: %s\r\n",
opts->network_referrer);
}
if (opts->network_http_header_fields) {
for (int n = 0; opts->network_http_header_fields[n]; n++) {
cust_headers = talloc_asprintf_append(cust_headers, "%s\r\n",
opts->network_http_header_fields[n]);
}
}
if (strlen(cust_headers))
av_dict_set(&dict, "headers", cust_headers, 0);
av_dict_set(&dict, "icy", "1", 0);
mp_set_avdict(&dict, opts->stream_lavf_opts->avopts);
AVIOInterruptCB cb = { AVIOInterruptCB cb = {
.callback = interrupt_cb, .callback = interrupt_cb,