X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Frtsp.c;h=c186b998fc3a10e3ed68798652afbcfca870cb88;hb=3acadc89f495366a1c7de234b33df7464fd64acd;hp=14ac510828a1ace2e1f0e4f33d4281e27d65b7a5;hpb=b12eacb3837cad2daaeda1f77ceb1045bca68789;p=ffmpeg diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c index 14ac510828a..c186b998fc3 100644 --- a/libavformat/rtsp.c +++ b/libavformat/rtsp.c @@ -74,8 +74,10 @@ { "data", "Data", 0, AV_OPT_TYPE_CONST, {.i64 = 1 << AVMEDIA_TYPE_DATA}, 0, 0, DEC, "allowed_media_types" }, \ { "subtitle", "Subtitle", 0, AV_OPT_TYPE_CONST, {.i64 = 1 << AVMEDIA_TYPE_SUBTITLE}, 0, 0, DEC, "allowed_media_types" } -#define RTSP_REORDERING_OPTS() \ - { "reorder_queue_size", "set number of packets to buffer for handling of reordered packets", OFFSET(reordering_queue_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, DEC } +#define COMMON_OPTS() \ + { "reorder_queue_size", "set number of packets to buffer for handling of reordered packets", OFFSET(reordering_queue_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, DEC }, \ + { "buffer_size", "Underlying protocol send/receive buffer size", OFFSET(buffer_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, DEC|ENC } \ + const AVOption ff_rtsp_options[] = { { "initial_pause", "do not start playing the stream immediately", OFFSET(initial_pause), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, DEC }, @@ -93,7 +95,7 @@ const AVOption ff_rtsp_options[] = { { "max_port", "set maximum local UDP port", OFFSET(rtp_port_max), AV_OPT_TYPE_INT, {.i64 = RTSP_RTP_PORT_MAX}, 0, 65535, DEC|ENC }, { "timeout", "set maximum timeout (in seconds) to wait for incoming connections (-1 is infinite, imply flag listen)", OFFSET(initial_timeout), AV_OPT_TYPE_INT, {.i64 = -1}, INT_MIN, INT_MAX, DEC }, { "stimeout", "set timeout (in microseconds) of socket TCP I/O operations", OFFSET(stimeout), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC }, - RTSP_REORDERING_OPTS(), + COMMON_OPTS(), { "user-agent", "override User-Agent header", OFFSET(user_agent), AV_OPT_TYPE_STRING, {.str = LIBAVFORMAT_IDENT}, 0, 0, DEC }, { NULL }, }; @@ -103,16 +105,28 @@ static const AVOption sdp_options[] = { { "custom_io", "use custom I/O", 0, AV_OPT_TYPE_CONST, {.i64 = RTSP_FLAG_CUSTOM_IO}, 0, 0, DEC, "rtsp_flags" }, { "rtcp_to_source", "send RTCP packets to the source address of received packets", 0, AV_OPT_TYPE_CONST, {.i64 = RTSP_FLAG_RTCP_TO_SOURCE}, 0, 0, DEC, "rtsp_flags" }, RTSP_MEDIATYPE_OPTS("allowed_media_types", "set media types to accept from the server"), - RTSP_REORDERING_OPTS(), + COMMON_OPTS(), { NULL }, }; static const AVOption rtp_options[] = { RTSP_FLAG_OPTS("rtp_flags", "set RTP flags"), - RTSP_REORDERING_OPTS(), + COMMON_OPTS(), { NULL }, }; + +static AVDictionary *map_to_opts(RTSPState *rt) +{ + AVDictionary *opts = NULL; + char buf[256]; + + snprintf(buf, sizeof(buf), "%d", rt->buffer_size); + av_dict_set(&opts, "buffer_size", buf, 0); + + return opts; +} + static void get_word_until_chars(char *buf, int buf_size, const char *sep, const char **pp) { @@ -160,11 +174,15 @@ static void rtsp_parse_range_npt(const char *p, int64_t *start, int64_t *end) *end = AV_NOPTS_VALUE; get_word_sep(buf, sizeof(buf), "-", &p); - av_parse_time(start, buf, 1); + if (av_parse_time(start, buf, 1) < 0) { + av_log(NULL, AV_LOG_ERROR, "Invalid interval start specification '%s'\n", buf); + return; + } if (*p == '-') { p++; get_word_sep(buf, sizeof(buf), "-", &p); - av_parse_time(end, buf, 1); + if (av_parse_time(end, buf, 1) < 0) + av_log(NULL, AV_LOG_ERROR, "Invalid interval end specification '%s'\n", buf); } } @@ -784,7 +802,7 @@ int ff_rtsp_open_transport_ctx(AVFormatContext *s, RTSPStream *rtsp_st) if (!st) s->ctx_flags |= AVFMTCTX_NOHEADER; - if (CONFIG_RTSP_MUXER && s->oformat) { + if (CONFIG_RTSP_MUXER && s->oformat && st) { int ret = ff_rtp_chain_mux_open((AVFormatContext **)&rtsp_st->transport_priv, s, st, rtsp_st->rtp_handle, RTSP_TCP_MAX_PACKET_SIZE, @@ -796,7 +814,7 @@ int ff_rtsp_open_transport_ctx(AVFormatContext *s, RTSPStream *rtsp_st) st->time_base = ((AVFormatContext*)rtsp_st->transport_priv)->streams[0]->time_base; } else if (rt->transport == RTSP_TRANSPORT_RAW) { return 0; // Don't need to open any parser here - } else if (CONFIG_RTPDEC && rt->transport == RTSP_TRANSPORT_RDT) + } else if (CONFIG_RTPDEC && rt->transport == RTSP_TRANSPORT_RDT && st) rtsp_st->transport_priv = ff_rdt_parse_open(s, st->index, rtsp_st->dynamic_protocol_context, rtsp_st->dynamic_handler); @@ -1436,12 +1454,18 @@ int ff_rtsp_make_setup_request(AVFormatContext *s, const char *host, int port, /* first try in specified port range */ while (j <= rt->rtp_port_max) { + AVDictionary *opts = map_to_opts(rt); + ff_url_join(buf, sizeof(buf), "rtp", NULL, host, -1, "?localport=%d", j); /* we will use two ports per rtp stream (rtp and rtcp) */ j += 2; - if (!ffurl_open(&rtsp_st->rtp_handle, buf, AVIO_FLAG_READ_WRITE, - &s->interrupt_callback, NULL)) + err = ffurl_open(&rtsp_st->rtp_handle, buf, AVIO_FLAG_READ_WRITE, + &s->interrupt_callback, &opts); + + av_dict_free(&opts); + + if (!err) goto rtp_opened; } av_log(s, AV_LOG_ERROR, "Unable to open an input RTP port\n"); @@ -2239,6 +2263,8 @@ static int sdp_read_header(AVFormatContext *s) /* read the whole sdp file */ /* XXX: better loading */ content = av_malloc(SDP_MAX_SIZE); + if (!content) + return AVERROR(ENOMEM); size = avio_read(s->pb, content, SDP_MAX_SIZE - 1); if (size <= 0) { av_free(content); @@ -2256,6 +2282,8 @@ static int sdp_read_header(AVFormatContext *s) rtsp_st = rt->rtsp_streams[i]; if (!(rt->rtsp_flags & RTSP_FLAG_CUSTOM_IO)) { + AVDictionary *opts = map_to_opts(rt); + getnameinfo((struct sockaddr*) &rtsp_st->sdp_ip, sizeof(rtsp_st->sdp_ip), namebuf, sizeof(namebuf), NULL, 0, NI_NUMERICHOST); ff_url_join(url, sizeof(url), "rtp", NULL, @@ -2271,8 +2299,12 @@ static int sdp_read_header(AVFormatContext *s) append_source_addrs(url, sizeof(url), "block", rtsp_st->nb_exclude_source_addrs, rtsp_st->exclude_source_addrs); - if (ffurl_open(&rtsp_st->rtp_handle, url, AVIO_FLAG_READ_WRITE, - &s->interrupt_callback, NULL) < 0) { + err = ffurl_open(&rtsp_st->rtp_handle, url, AVIO_FLAG_READ_WRITE, + &s->interrupt_callback, &opts); + + av_dict_free(&opts); + + if (err < 0) { err = AVERROR_INVALIDDATA; goto fail; }