X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Frtsp.c;h=5aadc4430ab0f526238129502b12f06397aa3be7;hb=41ac093f7e315e3af17612f580c387b3688f4f43;hp=6d538cd1dc6f5c35288594d006ba0501db5fc72d;hpb=2912e87a6c9264d556734e2bf94a99c64cf9b102;p=ffmpeg diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c index 6d538cd1dc6..5aadc4430ab 100644 --- a/libavformat/rtsp.c +++ b/libavformat/rtsp.c @@ -22,8 +22,10 @@ #include "libavutil/base64.h" #include "libavutil/avstring.h" #include "libavutil/intreadwrite.h" +#include "libavutil/mathematics.h" #include "libavutil/parseutils.h" #include "libavutil/random_seed.h" +#include "libavutil/dict.h" #include "avformat.h" #include "avio_internal.h" @@ -42,9 +44,10 @@ #include "rdt.h" #include "rtpdec_formats.h" #include "rtpenc_chain.h" +#include "url.h" +#include "rtpenc.h" //#define DEBUG -//#define DEBUG_RTP_TCP /* Timeout values for socket poll, in ms, * and read_packet(), in seconds */ @@ -54,6 +57,36 @@ #define SDP_MAX_SIZE 16384 #define RECVBUF_SIZE 10 * RTP_MAX_PACKET_LENGTH +#define OFFSET(x) offsetof(RTSPState, x) +#define DEC AV_OPT_FLAG_DECODING_PARAM +#define ENC AV_OPT_FLAG_ENCODING_PARAM + +#define RTSP_FLAG_OPTS(name, longname) \ + { name, longname, OFFSET(rtsp_flags), AV_OPT_TYPE_FLAGS, {0}, INT_MIN, INT_MAX, DEC, "rtsp_flags" }, \ + { "filter_src", "Only receive packets from the negotiated peer IP", 0, AV_OPT_TYPE_CONST, {RTSP_FLAG_FILTER_SRC}, 0, 0, DEC, "rtsp_flags" } + +const AVOption ff_rtsp_options[] = { + { "initial_pause", "Don't start playing the stream immediately", OFFSET(initial_pause), AV_OPT_TYPE_INT, {0}, 0, 1, DEC }, + FF_RTP_FLAG_OPTS(RTSPState, rtp_muxer_flags), + { "rtsp_transport", "RTSP transport protocols", OFFSET(lower_transport_mask), AV_OPT_TYPE_FLAGS, {0}, INT_MIN, INT_MAX, DEC|ENC, "rtsp_transport" }, \ + { "udp", "UDP", 0, AV_OPT_TYPE_CONST, {1 << RTSP_LOWER_TRANSPORT_UDP}, 0, 0, DEC|ENC, "rtsp_transport" }, \ + { "tcp", "TCP", 0, AV_OPT_TYPE_CONST, {1 << RTSP_LOWER_TRANSPORT_TCP}, 0, 0, DEC|ENC, "rtsp_transport" }, \ + { "udp_multicast", "UDP multicast", 0, AV_OPT_TYPE_CONST, {1 << RTSP_LOWER_TRANSPORT_UDP_MULTICAST}, 0, 0, DEC, "rtsp_transport" }, + { "http", "HTTP tunneling", 0, AV_OPT_TYPE_CONST, {(1 << RTSP_LOWER_TRANSPORT_HTTP)}, 0, 0, DEC, "rtsp_transport" }, + RTSP_FLAG_OPTS("rtsp_flags", "RTSP flags"), + { NULL }, +}; + +static const AVOption sdp_options[] = { + RTSP_FLAG_OPTS("sdp_flags", "SDP flags"), + { NULL }, +}; + +static const AVOption rtp_options[] = { + RTSP_FLAG_OPTS("rtp_flags", "RTP flags"), + { NULL }, +}; + static void get_word_until_chars(char *buf, int buf_size, const char *sep, const char **pp) { @@ -131,8 +164,8 @@ static void init_rtp_handler(RTPDynamicProtocolHandler *handler, return; codec->codec_id = handler->codec_id; rtsp_st->dynamic_handler = handler; - if (handler->open) - rtsp_st->dynamic_protocol_context = handler->open(); + if (handler->alloc) + rtsp_st->dynamic_protocol_context = handler->alloc(); } /* parse the rtpmap description: /[/] */ @@ -281,11 +314,11 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, } break; case 's': - av_metadata_set2(&s->metadata, "title", p, 0); + av_dict_set(&s->metadata, "title", p, 0); break; case 'i': if (s->nb_streams == 0) { - av_metadata_set2(&s->metadata, "comment", p, 0); + av_dict_set(&s->metadata, "comment", p, 0); break; } break; @@ -324,9 +357,10 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, if (!strcmp(ff_rtp_enc_name(rtsp_st->sdp_payload_type), "MP2T")) { /* no corresponding stream */ } else { - st = av_new_stream(s, rt->nb_rtsp_streams - 1); + st = avformat_new_stream(s, NULL); if (!st) return; + st->id = rt->nb_rtsp_streams - 1; rtsp_st->stream_index = st->index; st->codec->codec_type = codec_type; if (rtsp_st->sdp_payload_type < RTP_PT_PRIVATE) { @@ -427,11 +461,6 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, } } -/** - * Parse the sdp description and allocate the rtp streams and the - * pollfd array used for udp ones. - */ - int ff_sdp_parse(AVFormatContext *s, const char *content) { RTSPState *rt = s->priv_data; @@ -495,7 +524,7 @@ void ff_rtsp_undo_setup(AVFormatContext *s) av_write_trailer(rtpctx); if (rt->lower_transport == RTSP_LOWER_TRANSPORT_TCP) { uint8_t *ptr; - url_close_dyn_buf(rtpctx->pb, &ptr); + avio_close_dyn_buf(rtpctx->pb, &ptr); av_free(ptr); } else { avio_close(rtpctx->pb); @@ -504,11 +533,11 @@ void ff_rtsp_undo_setup(AVFormatContext *s) } else if (rt->transport == RTSP_TRANSPORT_RDT && CONFIG_RTPDEC) ff_rdt_parse_close(rtsp_st->transport_priv); else if (CONFIG_RTPDEC) - rtp_parse_close(rtsp_st->transport_priv); + ff_rtp_parse_close(rtsp_st->transport_priv); } rtsp_st->transport_priv = NULL; if (rtsp_st->rtp_handle) - url_close(rtsp_st->rtp_handle); + ffurl_close(rtsp_st->rtp_handle); rtsp_st->rtp_handle = NULL; } } @@ -525,7 +554,7 @@ void ff_rtsp_close_streams(AVFormatContext *s) rtsp_st = rt->rtsp_streams[i]; if (rtsp_st) { if (rtsp_st->dynamic_handler && rtsp_st->dynamic_protocol_context) - rtsp_st->dynamic_handler->close( + rtsp_st->dynamic_handler->free( rtsp_st->dynamic_protocol_context); av_free(rtsp_st); } @@ -561,7 +590,7 @@ static int rtsp_open_transport_ctx(AVFormatContext *s, RTSPStream *rtsp_st) rtsp_st->dynamic_protocol_context, rtsp_st->dynamic_handler); else if (CONFIG_RTPDEC) - rtsp_st->transport_priv = rtp_parse_open(s, st, rtsp_st->rtp_handle, + rtsp_st->transport_priv = ff_rtp_parse_open(s, st, rtsp_st->rtp_handle, rtsp_st->sdp_payload_type, (rt->lower_transport == RTSP_LOWER_TRANSPORT_TCP || !s->max_delay) ? 0 : RTP_REORDER_QUEUE_DEFAULT_SIZE); @@ -570,9 +599,9 @@ static int rtsp_open_transport_ctx(AVFormatContext *s, RTSPStream *rtsp_st) return AVERROR(ENOMEM); } else if (rt->transport != RTSP_TRANSPORT_RDT && CONFIG_RTPDEC) { if (rtsp_st->dynamic_handler) { - rtp_parse_set_dynamic_protocol(rtsp_st->transport_priv, - rtsp_st->dynamic_protocol_context, - rtsp_st->dynamic_handler); + ff_rtp_parse_set_dynamic_protocol(rtsp_st->transport_priv, + rtsp_st->dynamic_protocol_context, + rtsp_st->dynamic_handler); } } @@ -743,9 +772,9 @@ static void rtsp_parse_rtp_info(RTSPState *rt, const char *p) if (!strcmp(key, "url")) av_strlcpy(url, value, sizeof(url)); else if (!strcmp(key, "seq")) - seq = strtol(value, NULL, 10); + seq = strtoul(value, NULL, 10); else if (!strcmp(key, "rtptime")) - rtptime = strtol(value, NULL, 10); + rtptime = strtoul(value, NULL, 10); if (*p == ',') { handle_rtp_info(rt, url, seq, rtptime); url[0] = '\0'; @@ -807,6 +836,13 @@ void ff_rtsp_parse_line(RTSPMessageHeader *reply, const char *buf, p += strspn(p, SPACE_CHARS); if (method && !strcmp(method, "PLAY")) rtsp_parse_rtp_info(rt, p); + } else if (av_stristart(p, "Public:", &p) && rt) { + if (strstr(p, "GET_PARAMETER") && + method && !strcmp(method, "OPTIONS")) + rt->get_parameter_supported = 1; + } else if (av_stristart(p, "x-Accept-Dynamic-Rate:", &p) && rt) { + p += strspn(p, SPACE_CHARS); + rt->accept_dynamic_rate = atoi(p); } } @@ -817,7 +853,7 @@ void ff_rtsp_skip_packet(AVFormatContext *s) int ret, len, len1; uint8_t buf[1024]; - ret = url_read_complete(rt->rtsp_hd, buf, 3); + ret = ffurl_read_complete(rt->rtsp_hd, buf, 3); if (ret != 3) return; len = AV_RB16(buf + 1); @@ -829,7 +865,7 @@ void ff_rtsp_skip_packet(AVFormatContext *s) len1 = len; if (len1 > sizeof(buf)) len1 = sizeof(buf); - ret = url_read_complete(rt->rtsp_hd, buf, len1); + ret = ffurl_read_complete(rt->rtsp_hd, buf, len1); if (ret != len1) return; len -= len1; @@ -854,10 +890,8 @@ int ff_rtsp_read_reply(AVFormatContext *s, RTSPMessageHeader *reply, for (;;) { q = buf; for (;;) { - ret = url_read_complete(rt->rtsp_hd, &ch, 1); -#ifdef DEBUG_RTP_TCP + ret = ffurl_read_complete(rt->rtsp_hd, &ch, 1); av_dlog(s, "ret=%d c=%02x [%c]\n", ret, ch, ch); -#endif if (ret != 1) return AVERROR_EOF; if (ch == '\n') @@ -902,7 +936,7 @@ int ff_rtsp_read_reply(AVFormatContext *s, RTSPMessageHeader *reply, if (content_length > 0) { /* leave some room for a trailing '\0' (useful for simple parsing) */ content = av_malloc(content_length + 1); - (void)url_read_complete(rt->rtsp_hd, content, content_length); + ffurl_read_complete(rt->rtsp_hd, content, content_length); content[content_length] = '\0'; } if (content_ptr) @@ -982,14 +1016,14 @@ static int ff_rtsp_send_cmd_with_content_async(AVFormatContext *s, av_dlog(s, "Sending:\n%s--\n", buf); - url_write(rt->rtsp_hd_out, out_buf, strlen(out_buf)); + ffurl_write(rt->rtsp_hd_out, out_buf, strlen(out_buf)); if (send_content_length > 0 && send_content) { if (rt->control_transport == RTSP_MODE_TUNNEL) { av_log(s, AV_LOG_ERROR, "tunneling of RTSP requests " "with content data not supported\n"); return AVERROR_PATCHWELCOME; } - url_write(rt->rtsp_hd_out, send_content, send_content_length); + ffurl_write(rt->rtsp_hd_out, send_content, send_content_length); } rt->last_cmd_time = av_gettime(); @@ -1047,9 +1081,6 @@ retry: return 0; } -/** - * @return 0 on success, <0 on error, 1 if protocol is unavailable. - */ int ff_rtsp_make_setup_request(AVFormatContext *s, const char *host, int port, int lower_transport, const char *real_challenge) { @@ -1075,7 +1106,7 @@ int ff_rtsp_make_setup_request(AVFormatContext *s, const char *host, int port, for (j = RTSP_RTP_PORT_MIN, i = 0; i < rt->nb_rtsp_streams; ++i) { char transport[2048]; - /** + /* * WMS serves all UDP data over a single connection, the RTX, which * isn't necessarily the first in the SDP but has to be the first * to be set up, else the second/third SETUP will fail with a 461. @@ -1115,25 +1146,17 @@ int ff_rtsp_make_setup_request(AVFormatContext *s, const char *host, int port, "?localport=%d", j); /* we will use two ports per rtp stream (rtp and rtcp) */ j += 2; - if (url_open(&rtsp_st->rtp_handle, buf, URL_RDWR) == 0) + if (ffurl_open(&rtsp_st->rtp_handle, buf, AVIO_FLAG_READ_WRITE) == 0) goto rtp_opened; } } -#if 0 - /* then try on any port */ - if (url_open(&rtsp_st->rtp_handle, "rtp://", URL_RDONLY) < 0) { - err = AVERROR_INVALIDDATA; - goto fail; - } -#else av_log(s, AV_LOG_ERROR, "Unable to open an input RTP port\n"); err = AVERROR(EIO); goto fail; -#endif rtp_opened: - port = rtp_get_local_rtp_port(rtsp_st->rtp_handle); + port = ff_rtp_get_local_rtp_port(rtsp_st->rtp_handle); have_port: snprintf(transport, sizeof(transport) - 1, "%s/UDP;", trans_pref); @@ -1148,7 +1171,7 @@ int ff_rtsp_make_setup_request(AVFormatContext *s, const char *host, int port, /* RTP/TCP */ else if (lower_transport == RTSP_LOWER_TRANSPORT_TCP) { - /** For WMS streams, the application streams are only used for + /* For WMS streams, the application streams are only used for * UDP. When trying to set it up for TCP streams, the server * will return an error. Therefore, we skip those streams. */ if (rt->server_type == RTSP_SERVER_WMS && @@ -1157,7 +1180,7 @@ int ff_rtsp_make_setup_request(AVFormatContext *s, const char *host, int port, continue; snprintf(transport, sizeof(transport) - 1, "%s/TCP;", trans_pref); - if (rt->server_type == RTSP_SERVER_WMS) + if (rt->transport != RTSP_TRANSPORT_RDT) av_strlcat(transport, "unicast;", sizeof(transport)); av_strlcatf(transport, sizeof(transport), "interleaved=%d-%d", @@ -1177,6 +1200,8 @@ int ff_rtsp_make_setup_request(AVFormatContext *s, const char *host, int port, snprintf(cmd, sizeof(cmd), "Transport: %s\r\n", transport); + if (rt->accept_dynamic_rate) + av_strlcat(cmd, "x-Dynamic-Rate: 0\r\n", sizeof(cmd)); if (i == 0 && rt->server_type == RTSP_SERVER_REAL && CONFIG_RTPDEC) { char real_res[41], real_csum[9]; ff_rdt_calc_response_and_checksum(real_res, real_csum, @@ -1225,19 +1250,19 @@ int ff_rtsp_make_setup_request(AVFormatContext *s, const char *host, int port, case RTSP_LOWER_TRANSPORT_UDP: { char url[1024], options[30] = ""; - if (rt->filter_source) + if (rt->rtsp_flags & RTSP_FLAG_FILTER_SRC) av_strlcpy(options, "?connect=1", sizeof(options)); /* Use source address if specified */ if (reply->transports[0].source[0]) { ff_url_join(url, sizeof(url), "rtp", NULL, reply->transports[0].source, - reply->transports[0].server_port_min, options); + reply->transports[0].server_port_min, "%s", options); } else { ff_url_join(url, sizeof(url), "rtp", NULL, host, - reply->transports[0].server_port_min, options); + reply->transports[0].server_port_min, "%s", options); } if (!(rt->server_type == RTSP_SERVER_WMS && i > 1) && - rtp_set_remote_url(rtsp_st->rtp_handle, url) < 0) { + ff_rtp_set_remote_url(rtsp_st->rtp_handle, url) < 0) { err = AVERROR_INVALIDDATA; goto fail; } @@ -1247,7 +1272,7 @@ int ff_rtsp_make_setup_request(AVFormatContext *s, const char *host, int port, */ if (!(rt->server_type == RTSP_SERVER_WMS && i > 1) && s->iformat && CONFIG_RTPDEC) - rtp_send_punch_packets(rtsp_st->rtp_handle); + ff_rtp_send_punch_packets(rtsp_st->rtp_handle); break; } case RTSP_LOWER_TRANSPORT_UDP_MULTICAST: { @@ -1268,7 +1293,7 @@ int ff_rtsp_make_setup_request(AVFormatContext *s, const char *host, int port, namebuf, sizeof(namebuf), NULL, 0, NI_NUMERICHOST); ff_url_join(url, sizeof(url), "rtp", NULL, namebuf, port, "?ttl=%d", ttl); - if (url_open(&rtsp_st->rtp_handle, url, URL_RDWR) < 0) { + if (ffurl_open(&rtsp_st->rtp_handle, url, AVIO_FLAG_READ_WRITE) < 0) { err = AVERROR_INVALIDDATA; goto fail; } @@ -1296,8 +1321,8 @@ fail: void ff_rtsp_close_connections(AVFormatContext *s) { RTSPState *rt = s->priv_data; - if (rt->rtsp_hd_out != rt->rtsp_hd) url_close(rt->rtsp_hd_out); - url_close(rt->rtsp_hd); + if (rt->rtsp_hd_out != rt->rtsp_hd) ffurl_close(rt->rtsp_hd_out); + ffurl_close(rt->rtsp_hd); rt->rtsp_hd = rt->rtsp_hd_out = NULL; } @@ -1315,8 +1340,17 @@ int ff_rtsp_connect(AVFormatContext *s) if (!ff_network_init()) return AVERROR(EIO); -redirect: + rt->control_transport = RTSP_MODE_PLAIN; + if (rt->lower_transport_mask & (1 << RTSP_LOWER_TRANSPORT_HTTP)) { + rt->lower_transport_mask = 1 << RTSP_LOWER_TRANSPORT_TCP; + rt->control_transport = RTSP_MODE_TUNNEL; + } + /* Only pass through valid flags from here */ + rt->lower_transport_mask &= (1 << RTSP_LOWER_TRANSPORT_NB) - 1; + +redirect: + lower_transport_mask = rt->lower_transport_mask; /* extract hostname and port */ av_url_split(NULL, 0, auth, sizeof(auth), host, sizeof(host), &port, path, sizeof(path), s->filename); @@ -1326,6 +1360,7 @@ redirect: if (port < 0) port = RTSP_DEFAULT_PORT; +#if FF_API_RTSP_URL_OPTIONS /* search for options */ option_list = strrchr(path, '?'); if (option_list) { @@ -1333,6 +1368,7 @@ redirect: * the options back into the same string. */ filename = option_list; while (option_list) { + int handled = 1; /* move the option pointer */ option = ++option_list; option_list = strchr(option_list, '&'); @@ -1350,7 +1386,7 @@ redirect: lower_transport_mask |= (1<< RTSP_LOWER_TRANSPORT_TCP); rt->control_transport = RTSP_MODE_TUNNEL; } else if (!strcmp(option, "filter_src")) { - rt->filter_source = 1; + rt->rtsp_flags |= RTSP_FLAG_FILTER_SRC; } else { /* Write options back into the buffer, using memmove instead * of strcpy since the strings may overlap. */ @@ -1358,10 +1394,16 @@ redirect: memmove(++filename, option, len); filename += len; if (option_list) *filename = '&'; + handled = 0; } + if (handled) + av_log(s, AV_LOG_WARNING, "Options passed via URL are " + "deprecated, use -rtsp_transport " + "and -rtsp_flags instead.\n"); } *filename = 0; } +#endif if (!lower_transport_mask) lower_transport_mask = (1 << RTSP_LOWER_TRANSPORT_NB) - 1; @@ -1395,7 +1437,7 @@ redirect: av_get_random_seed(), av_get_random_seed()); /* GET requests */ - if (url_alloc(&rt->rtsp_hd, httpname, URL_RDONLY) < 0) { + if (ffurl_alloc(&rt->rtsp_hd, httpname, AVIO_FLAG_READ) < 0) { err = AVERROR(EIO); goto fail; } @@ -1410,13 +1452,13 @@ redirect: ff_http_set_headers(rt->rtsp_hd, headers); /* complete the connection */ - if (url_connect(rt->rtsp_hd)) { + if (ffurl_connect(rt->rtsp_hd)) { err = AVERROR(EIO); goto fail; } /* POST requests */ - if (url_alloc(&rt->rtsp_hd_out, httpname, URL_WRONLY) < 0 ) { + if (ffurl_alloc(&rt->rtsp_hd_out, httpname, AVIO_FLAG_WRITE) < 0 ) { err = AVERROR(EIO); goto fail; } @@ -1452,14 +1494,14 @@ redirect: ff_http_init_auth_state(rt->rtsp_hd_out, rt->rtsp_hd); /* complete the connection */ - if (url_connect(rt->rtsp_hd_out)) { + if (ffurl_connect(rt->rtsp_hd_out)) { err = AVERROR(EIO); goto fail; } } else { /* open the tcp connection */ ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, host, port, NULL); - if (url_open(&rt->rtsp_hd, tcpname, URL_RDWR) < 0) { + if (ffurl_open(&rt->rtsp_hd, tcpname, AVIO_FLAG_READ_WRITE) < 0) { err = AVERROR(EIO); goto fail; } @@ -1467,7 +1509,7 @@ redirect: } rt->seq = 0; - tcp_fd = url_get_file_handle(rt->rtsp_hd); + tcp_fd = ffurl_get_file_handle(rt->rtsp_hd); if (!getpeername(tcp_fd, (struct sockaddr*) &peer, &peer_len)) { getnameinfo((struct sockaddr*) &peer, peer_len, host, sizeof(host), NULL, 0, NI_NUMERICHOST); @@ -1479,14 +1521,14 @@ redirect: cmd[0] = 0; if (rt->server_type == RTSP_SERVER_REAL) av_strlcat(cmd, - /** + /* * The following entries are required for proper * streaming from a Realmedia server. They are * interdependent in some way although we currently * don't quite understand how. Values were copied * from mplayer SVN r23589. - * @param CompanyID is a 16-byte ID in base64 - * @param ClientChallenge is a 16-byte ID in hex + * ClientChallenge is a 16-byte ID in hex + * CompanyID is a 16-byte ID in base64 */ "ClientChallenge: 9e26d33f2984236010ef6253fb1887f7\r\n" "PlayerStarttime: [28/03/2003:22:50:23 00:00]\r\n" @@ -1570,7 +1612,7 @@ static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st, return AVERROR(EAGAIN); max_p = 0; if (rt->rtsp_hd) { - tcp_fd = url_get_file_handle(rt->rtsp_hd); + tcp_fd = ffurl_get_file_handle(rt->rtsp_hd); p[max_p].fd = tcp_fd; p[max_p++].events = POLLIN; } else { @@ -1579,9 +1621,9 @@ static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st, for (i = 0; i < rt->nb_rtsp_streams; i++) { rtsp_st = rt->rtsp_streams[i]; if (rtsp_st->rtp_handle) { - p[max_p].fd = url_get_file_handle(rtsp_st->rtp_handle); + p[max_p].fd = ffurl_get_file_handle(rtsp_st->rtp_handle); p[max_p++].events = POLLIN; - p[max_p].fd = rtp_get_rtcp_file_handle(rtsp_st->rtp_handle); + p[max_p].fd = ff_rtp_get_rtcp_file_handle(rtsp_st->rtp_handle); p[max_p++].events = POLLIN; } } @@ -1593,7 +1635,7 @@ static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st, rtsp_st = rt->rtsp_streams[i]; if (rtsp_st->rtp_handle) { if (p[j].revents & POLLIN || p[j+1].revents & POLLIN) { - ret = url_read(rtsp_st->rtp_handle, buf, buf_size); + ret = ffurl_read(rtsp_st->rtp_handle, buf, buf_size); if (ret > 0) { *prtsp_st = rtsp_st; return ret; @@ -1636,7 +1678,7 @@ int ff_rtsp_fetch_packet(AVFormatContext *s, AVPacket *pkt) if (rt->transport == RTSP_TRANSPORT_RDT) { ret = ff_rdt_parse_packet(rt->cur_transport_priv, pkt, NULL, 0); } else - ret = rtp_parse_packet(rt->cur_transport_priv, pkt, NULL, 0); + ret = ff_rtp_parse_packet(rt->cur_transport_priv, pkt, NULL, 0); if (ret == 0) { rt->cur_transport_priv = NULL; return 0; @@ -1684,13 +1726,13 @@ int ff_rtsp_fetch_packet(AVFormatContext *s, AVPacket *pkt) case RTSP_LOWER_TRANSPORT_UDP_MULTICAST: len = udp_read_packet(s, &rtsp_st, rt->recvbuf, RECVBUF_SIZE, wait_end); if (len > 0 && rtsp_st->transport_priv && rt->transport == RTSP_TRANSPORT_RTP) - rtp_check_and_send_back_rr(rtsp_st->transport_priv, len); + ff_rtp_check_and_send_back_rr(rtsp_st->transport_priv, len); break; } if (len == AVERROR(EAGAIN) && first_queue_st && rt->transport == RTSP_TRANSPORT_RTP) { rtsp_st = first_queue_st; - ret = rtp_parse_packet(rtsp_st->transport_priv, pkt, NULL, 0); + ret = ff_rtp_parse_packet(rtsp_st->transport_priv, pkt, NULL, 0); goto end; } if (len < 0) @@ -1700,7 +1742,7 @@ int ff_rtsp_fetch_packet(AVFormatContext *s, AVPacket *pkt) if (rt->transport == RTSP_TRANSPORT_RDT) { ret = ff_rdt_parse_packet(rtsp_st->transport_priv, pkt, &rt->recvbuf, len); } else { - ret = rtp_parse_packet(rtsp_st->transport_priv, pkt, &rt->recvbuf, len); + ret = ff_rtp_parse_packet(rtsp_st->transport_priv, pkt, &rt->recvbuf, len); if (ret < 0) { /* Either bad packet, or a RTCP packet. Check if the * first_rtcp_ntp_time field was initialized. */ @@ -1804,9 +1846,10 @@ static int sdp_read_header(AVFormatContext *s, AVFormatParameters *ap) namebuf, sizeof(namebuf), NULL, 0, NI_NUMERICHOST); ff_url_join(url, sizeof(url), "rtp", NULL, namebuf, rtsp_st->sdp_port, - "?localport=%d&ttl=%d", rtsp_st->sdp_port, - rtsp_st->sdp_ttl); - if (url_open(&rtsp_st->rtp_handle, url, URL_RDWR) < 0) { + "?localport=%d&ttl=%d&connect=%d", rtsp_st->sdp_port, + rtsp_st->sdp_ttl, + rt->rtsp_flags & RTSP_FLAG_FILTER_SRC ? 1 : 0); + if (ffurl_open(&rtsp_st->rtp_handle, url, AVIO_FLAG_READ_WRITE) < 0) { err = AVERROR_INVALIDDATA; goto fail; } @@ -1827,14 +1870,22 @@ static int sdp_read_close(AVFormatContext *s) return 0; } +static const AVClass sdp_demuxer_class = { + .class_name = "SDP demuxer", + .item_name = av_default_item_name, + .option = sdp_options, + .version = LIBAVUTIL_VERSION_INT, +}; + AVInputFormat ff_sdp_demuxer = { - "sdp", - NULL_IF_CONFIG_SMALL("SDP"), - sizeof(RTSPState), - sdp_probe, - sdp_read_header, - ff_rtsp_fetch_packet, - sdp_read_close, + .name = "sdp", + .long_name = NULL_IF_CONFIG_SMALL("SDP"), + .priv_data_size = sizeof(RTSPState), + .read_probe = sdp_probe, + .read_header = sdp_read_header, + .read_packet = ff_rtsp_fetch_packet, + .read_close = sdp_read_close, + .priv_class = &sdp_demuxer_class }; #endif /* CONFIG_SDP_DEMUXER */ @@ -1862,12 +1913,12 @@ static int rtp_read_header(AVFormatContext *s, if (!ff_network_init()) return AVERROR(EIO); - ret = url_open(&in, s->filename, URL_RDONLY); + ret = ffurl_open(&in, s->filename, AVIO_FLAG_READ); if (ret) goto fail; while (1) { - ret = url_read(in, recvbuf, sizeof(recvbuf)); + ret = ffurl_read(in, recvbuf, sizeof(recvbuf)); if (ret == AVERROR(EAGAIN)) continue; if (ret < 0) @@ -1886,8 +1937,8 @@ static int rtp_read_header(AVFormatContext *s, payload_type = recvbuf[1] & 0x7f; break; } - getsockname(url_get_file_handle(in), (struct sockaddr*) &addr, &addrlen); - url_close(in); + getsockname(ffurl_get_file_handle(in), (struct sockaddr*) &addr, &addrlen); + ffurl_close(in); in = NULL; memset(&codec, 0, sizeof(codec)); @@ -1926,20 +1977,28 @@ static int rtp_read_header(AVFormatContext *s, fail: if (in) - url_close(in); + ffurl_close(in); ff_network_close(); return ret; } +static const AVClass rtp_demuxer_class = { + .class_name = "RTP demuxer", + .item_name = av_default_item_name, + .option = rtp_options, + .version = LIBAVUTIL_VERSION_INT, +}; + AVInputFormat ff_rtp_demuxer = { - "rtp", - NULL_IF_CONFIG_SMALL("RTP input format"), - sizeof(RTSPState), - rtp_probe, - rtp_read_header, - ff_rtsp_fetch_packet, - sdp_read_close, + .name = "rtp", + .long_name = NULL_IF_CONFIG_SMALL("RTP input format"), + .priv_data_size = sizeof(RTSPState), + .read_probe = rtp_probe, + .read_header = rtp_read_header, + .read_packet = ff_rtsp_fetch_packet, + .read_close = sdp_read_close, .flags = AVFMT_NOFILE, + .priv_class = &rtp_demuxer_class }; #endif /* CONFIG_RTP_DEMUXER */