X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Frtsp.c;h=60f13275e5e7e9dcdc69460061dddf6ea2daf184;hb=ac11d562e51a7764abc20447303ce95225d07a0b;hp=2e2b6c80588a5cb8e465bc74a6abb393d0cad4f9;hpb=15ba23150eff85095d484be5e66031cff5d2519c;p=ffmpeg diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c index 2e2b6c80588..60f13275e5e 100644 --- a/libavformat/rtsp.c +++ b/libavformat/rtsp.c @@ -19,9 +19,6 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -/* needed by inet_aton() */ -#define _SVID_SOURCE - #include "libavutil/base64.h" #include "libavutil/avstring.h" #include "libavutil/intreadwrite.h" @@ -37,8 +34,8 @@ #include "rtpdec.h" #include "rdt.h" -#include "rtp_asf.h" -#include "rtp_vorbis.h" +#include "rtpdec_asf.h" +#include "rtpdec_vorbis.h" //#define DEBUG //#define DEBUG_RTP_TCP @@ -250,8 +247,8 @@ static const AttrNameMap attr_names[]= /* parse the attribute line from the fmtp a line of an sdp resonse. This * is broken out as a function because it is used in rtp_h264.c, which is * forthcoming. */ -int rtsp_next_attr_and_value(const char **p, char *attr, int attr_size, - char *value, int value_size) +int ff_rtsp_next_attr_and_value(const char **p, char *attr, int attr_size, + char *value, int value_size) { skip_spaces(p); if (**p) { @@ -279,8 +276,8 @@ static void sdp_parse_fmtp(AVStream *st, const char *p) RTPPayloadData *rtp_payload_data = &rtsp_st->rtp_payload_data; /* loop on each attribute */ - while (rtsp_next_attr_and_value(&p, attr, sizeof(attr), - value, sizeof(value))) { + while (ff_rtsp_next_attr_and_value(&p, attr, sizeof(attr), + value, sizeof(value))) { /* grab the codec extra_data from the config parameter of the fmtp * line */ sdp_parse_fmtp_config(codec, rtsp_st->dynamic_protocol_context, @@ -359,7 +356,7 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, if (strcmp(buf1, "IP4") != 0) return; get_word_sep(buf1, sizeof(buf1), "/", &p); - if (inet_aton(buf1, &sdp_ip) == 0) + if (ff_inet_aton(buf1, &sdp_ip) == 0) return; ttl = 16; if (*p == '/') { @@ -572,7 +569,7 @@ static int sdp_parse(AVFormatContext *s, const char *content) } /* close and free RTSP streams */ -void rtsp_close_streams(AVFormatContext *s) +void ff_rtsp_close_streams(AVFormatContext *s) { RTSPState *rt = s->priv_data; int i; @@ -586,6 +583,8 @@ void rtsp_close_streams(AVFormatContext *s) AVFormatContext *rtpctx = rtsp_st->transport_priv; av_write_trailer(rtpctx); url_fclose(rtpctx->pb); + av_metadata_free(&rtpctx->streams[0]->metadata); + av_metadata_free(&rtpctx->metadata); av_free(rtpctx->streams[0]); av_free(rtpctx); } else if (rt->transport == RTSP_TRANSPORT_RDT) @@ -689,7 +688,7 @@ static int rtsp_open_transport_ctx(AVFormatContext *s, RTSPStream *rtsp_st) return 0; } -#if CONFIG_RTSP_DEMUXER +#if CONFIG_RTSP_DEMUXER || CONFIG_RTSP_MUXER static int rtsp_probe(AVProbeData *p) { if (av_strstart(p->filename, "rtsp:", NULL)) @@ -801,7 +800,7 @@ static void rtsp_parse_transport(RTSPMessageHeader *reply, const char *p) if (*p == '=') { p++; get_word_sep(buf, sizeof(buf), ";,", &p); - if (inet_aton(buf, &ipaddr)) + if (ff_inet_aton(buf, &ipaddr)) th->destination = ntohl(ipaddr.s_addr); } } @@ -817,7 +816,7 @@ static void rtsp_parse_transport(RTSPMessageHeader *reply, const char *p) } } -void rtsp_parse_line(RTSPMessageHeader *reply, const char *buf) +void ff_rtsp_parse_line(RTSPMessageHeader *reply, const char *buf) { const char *p; @@ -879,9 +878,9 @@ static void rtsp_skip_packet(AVFormatContext *s) } } -int rtsp_read_reply(AVFormatContext *s, RTSPMessageHeader *reply, - unsigned char **content_ptr, - int return_on_interleaved_data) +int ff_rtsp_read_reply(AVFormatContext *s, RTSPMessageHeader *reply, + unsigned char **content_ptr, + int return_on_interleaved_data) { RTSPState *rt = s->priv_data; char buf[4096], buf1[1024], *q; @@ -930,7 +929,7 @@ int rtsp_read_reply(AVFormatContext *s, RTSPMessageHeader *reply, get_word(buf1, sizeof(buf1), &p); reply->status_code = atoi(buf1); } else { - rtsp_parse_line(reply, p); + ff_rtsp_parse_line(reply, p); av_strlcat(rt->last_reply, p, sizeof(rt->last_reply)); av_strlcat(rt->last_reply, "\n", sizeof(rt->last_reply)); } @@ -966,10 +965,10 @@ int rtsp_read_reply(AVFormatContext *s, RTSPMessageHeader *reply, return 0; } -void rtsp_send_cmd_with_content_async(AVFormatContext *s, - const char *cmd, - const unsigned char *send_content, - int send_content_length) +void ff_rtsp_send_cmd_with_content_async(AVFormatContext *s, + const char *cmd, + const unsigned char *send_content, + int send_content_length) { RTSPState *rt = s->priv_data; char buf[4096], buf1[1024]; @@ -998,30 +997,30 @@ void rtsp_send_cmd_with_content_async(AVFormatContext *s, rt->last_cmd_time = av_gettime(); } -void rtsp_send_cmd_async(AVFormatContext *s, const char *cmd) +void ff_rtsp_send_cmd_async(AVFormatContext *s, const char *cmd) { - rtsp_send_cmd_with_content_async(s, cmd, NULL, 0); + ff_rtsp_send_cmd_with_content_async(s, cmd, NULL, 0); } -void rtsp_send_cmd(AVFormatContext *s, - const char *cmd, RTSPMessageHeader *reply, - unsigned char **content_ptr) +void ff_rtsp_send_cmd(AVFormatContext *s, + const char *cmd, RTSPMessageHeader *reply, + unsigned char **content_ptr) { - rtsp_send_cmd_async(s, cmd); + ff_rtsp_send_cmd_async(s, cmd); - rtsp_read_reply(s, reply, content_ptr, 0); + ff_rtsp_read_reply(s, reply, content_ptr, 0); } -void rtsp_send_cmd_with_content(AVFormatContext *s, - const char *cmd, - RTSPMessageHeader *reply, - unsigned char **content_ptr, - const unsigned char *send_content, - int send_content_length) +void ff_rtsp_send_cmd_with_content(AVFormatContext *s, + const char *cmd, + RTSPMessageHeader *reply, + unsigned char **content_ptr, + const unsigned char *send_content, + int send_content_length) { - rtsp_send_cmd_with_content_async(s, cmd, send_content, send_content_length); + ff_rtsp_send_cmd_with_content_async(s, cmd, send_content, send_content_length); - rtsp_read_reply(s, reply, content_ptr, 0); + ff_rtsp_read_reply(s, reply, content_ptr, 0); } /** @@ -1088,8 +1087,8 @@ static int make_setup_request(AVFormatContext *s, const char *host, int port, /* first try in specified port range */ if (RTSP_RTP_PORT_MIN != 0) { while (j <= RTSP_RTP_PORT_MAX) { - snprintf(buf, sizeof(buf), "rtp://%s?localport=%d", - host, j); + 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 (url_open(&rtsp_st->rtp_handle, buf, URL_RDWR) == 0) @@ -1160,7 +1159,7 @@ static int make_setup_request(AVFormatContext *s, const char *host, int port, "RealChallenge2: %s, sd=%s\r\n", rt->session_id, real_res, real_csum); } - rtsp_send_cmd(s, cmd, reply, NULL); + ff_rtsp_send_cmd(s, cmd, reply, NULL); if (reply->status_code == 461 /* Unsupported protocol */ && i == 0) { err = 1; goto fail; @@ -1199,8 +1198,8 @@ static int make_setup_request(AVFormatContext *s, const char *host, int port, char url[1024]; /* XXX: also use address if specified */ - snprintf(url, sizeof(url), "rtp://%s:%d", - host, reply->transports[0].server_port_min); + ff_url_join(url, sizeof(url), "rtp", NULL, host, + reply->transports[0].server_port_min, NULL); if (!(rt->server_type == RTSP_SERVER_WMS && i > 1) && rtp_set_remote_url(rtsp_st->rtp_handle, url) < 0) { err = AVERROR_INVALIDDATA; @@ -1228,8 +1227,8 @@ static int make_setup_request(AVFormatContext *s, const char *host, int port, port = rtsp_st->sdp_port; ttl = rtsp_st->sdp_ttl; } - snprintf(url, sizeof(url), "rtp://%s:%d?ttl=%d", - inet_ntoa(in), port, ttl); + ff_url_join(url, sizeof(url), "rtp", NULL, inet_ntoa(in), + port, "?ttl=%d", ttl); if (url_open(&rtsp_st->rtp_handle, url, URL_RDWR) < 0) { err = AVERROR_INVALIDDATA; goto fail; @@ -1280,7 +1279,7 @@ static int rtsp_read_play(AVFormatContext *s) rt->control_uri, (double)rt->seek_timestamp / AV_TIME_BASE); } - rtsp_send_cmd(s, cmd, reply, NULL); + ff_rtsp_send_cmd(s, cmd, reply, NULL); if (reply->status_code != RTSP_STATUS_OK) { return -1; } @@ -1311,7 +1310,7 @@ static int rtsp_setup_input_streams(AVFormatContext *s) "Require: com.real.retain-entity-for-setup\r\n", sizeof(cmd)); } - rtsp_send_cmd(s, cmd, reply, &content); + ff_rtsp_send_cmd(s, cmd, reply, &content); if (!content) return AVERROR_INVALIDDATA; if (reply->status_code != RTSP_STATUS_OK) { @@ -1349,7 +1348,7 @@ static int rtsp_setup_output_streams(AVFormatContext *s) return AVERROR_INVALIDDATA; } av_log(s, AV_LOG_INFO, "SDP:\n%s\n", sdp); - rtsp_send_cmd_with_content(s, cmd, reply, NULL, sdp, strlen(sdp)); + ff_rtsp_send_cmd_with_content(s, cmd, reply, NULL, sdp, strlen(sdp)); av_free(sdp); if (reply->status_code != RTSP_STATUS_OK) return AVERROR_INVALIDDATA; @@ -1376,7 +1375,7 @@ static int rtsp_setup_output_streams(AVFormatContext *s) return 0; } -int rtsp_connect(AVFormatContext *s) +int ff_rtsp_connect(AVFormatContext *s) { RTSPState *rt = s->priv_data; char host[1024], path[1024], tcpname[1024], cmd[2048], auth[128]; @@ -1386,6 +1385,9 @@ int rtsp_connect(AVFormatContext *s) RTSPMessageHeader reply1, *reply = &reply1; int lower_transport_mask = 0; char real_challenge[64]; + + if (!ff_network_init()) + return AVERROR(EIO); redirect: /* extract hostname and port */ url_split(NULL, 0, auth, sizeof(auth), @@ -1445,7 +1447,7 @@ redirect: } /* open the tcp connexion */ - snprintf(tcpname, sizeof(tcpname), "tcp://%s:%d", host, port); + ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, host, port, NULL); if (url_open(&rtsp_hd, tcpname, URL_RDWR) < 0) { err = AVERROR(EIO); goto fail; @@ -1476,7 +1478,7 @@ redirect: "CompanyID: KnKV4M4I/B2FjJ1TToLycw==\r\n" "GUID: 00000000-0000-0000-0000-000000000000\r\n", sizeof(cmd)); - rtsp_send_cmd(s, cmd, reply, NULL); + ff_rtsp_send_cmd(s, cmd, reply, NULL); if (reply->status_code != RTSP_STATUS_OK) { err = AVERROR_INVALIDDATA; goto fail; @@ -1520,7 +1522,7 @@ redirect: rt->seek_timestamp = 0; /* default is to start stream at position zero */ return 0; fail: - rtsp_close_streams(s); + ff_rtsp_close_streams(s); url_close(rt->rtsp_hd); if (reply->status_code >=300 && reply->status_code < 400 && s->iformat) { av_strlcpy(s->filename, reply->location, sizeof(s->filename)); @@ -1529,16 +1531,19 @@ redirect: s->filename); goto redirect; } + ff_network_close(); return err; } +#endif +#if CONFIG_RTSP_DEMUXER static int rtsp_read_header(AVFormatContext *s, AVFormatParameters *ap) { RTSPState *rt = s->priv_data; int ret; - ret = rtsp_connect(s); + ret = ff_rtsp_connect(s); if (ret) return ret; @@ -1546,7 +1551,7 @@ static int rtsp_read_header(AVFormatContext *s, /* do not start immediately */ } else { if (rtsp_read_play(s) < 0) { - rtsp_close_streams(s); + ff_rtsp_close_streams(s); url_close(rt->rtsp_hd); return AVERROR_INVALIDDATA; } @@ -1607,7 +1612,7 @@ static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st, if (tcp_fd != -1 && FD_ISSET(tcp_fd, &rfds)) { RTSPMessageHeader reply; - rtsp_read_reply(s, &reply, NULL, 0); + ff_rtsp_read_reply(s, &reply, NULL, 0); /* XXX: parse message */ if (rt->state != RTSP_STATE_STREAMING) return 0; @@ -1631,7 +1636,7 @@ redo: for (;;) { RTSPMessageHeader reply; - ret = rtsp_read_reply(s, &reply, NULL, 1); + ret = ff_rtsp_read_reply(s, &reply, NULL, 1); if (ret == -1) return -1; if (ret == 1) /* received '$' */ @@ -1747,7 +1752,7 @@ static int rtsp_read_packet(AVFormatContext *s, AVPacket *pkt) "SET_PARAMETER %s RTSP/1.0\r\n" "Unsubscribe: %s\r\n", rt->control_uri, rt->last_subscription); - rtsp_send_cmd(s, cmd, reply, NULL); + ff_rtsp_send_cmd(s, cmd, reply, NULL); if (reply->status_code != RTSP_STATUS_OK) return AVERROR_INVALIDDATA; rt->need_subscription = 1; @@ -1783,7 +1788,7 @@ static int rtsp_read_packet(AVFormatContext *s, AVPacket *pkt) } } av_strlcatf(cmd, sizeof(cmd), "%s\r\n", rt->last_subscription); - rtsp_send_cmd(s, cmd, reply, NULL); + ff_rtsp_send_cmd(s, cmd, reply, NULL); if (reply->status_code != RTSP_STATUS_OK) return AVERROR_INVALIDDATA; rt->need_subscription = 0; @@ -1805,9 +1810,9 @@ static int rtsp_read_packet(AVFormatContext *s, AVPacket *pkt) snprintf(cmd, sizeof(cmd) - 1, "GET_PARAMETER %s RTSP/1.0\r\n", rt->control_uri); - rtsp_send_cmd_async(s, cmd); + ff_rtsp_send_cmd_async(s, cmd); } else { - rtsp_send_cmd_async(s, "OPTIONS * RTSP/1.0\r\n"); + ff_rtsp_send_cmd_async(s, "OPTIONS * RTSP/1.0\r\n"); } } @@ -1829,7 +1834,7 @@ static int rtsp_read_pause(AVFormatContext *s) snprintf(cmd, sizeof(cmd), "PAUSE %s RTSP/1.0\r\n", rt->control_uri); - rtsp_send_cmd(s, cmd, reply, NULL); + ff_rtsp_send_cmd(s, cmd, reply, NULL); if (reply->status_code != RTSP_STATUS_OK) { return -1; } @@ -1878,10 +1883,11 @@ static int rtsp_read_close(AVFormatContext *s) snprintf(cmd, sizeof(cmd), "TEARDOWN %s RTSP/1.0\r\n", s->filename); - rtsp_send_cmd_async(s, cmd); + ff_rtsp_send_cmd_async(s, cmd); - rtsp_close_streams(s); + ff_rtsp_close_streams(s); url_close(rt->rtsp_hd); + ff_network_close(); return 0; } @@ -1929,6 +1935,9 @@ static int sdp_read_header(AVFormatContext *s, AVFormatParameters *ap) char *content; char url[1024]; + if (!ff_network_init()) + return AVERROR(EIO); + /* read the whole sdp file */ /* XXX: better loading */ content = av_malloc(SDP_MAX_SIZE); @@ -1946,11 +1955,10 @@ static int sdp_read_header(AVFormatContext *s, AVFormatParameters *ap) for (i = 0; i < rt->nb_rtsp_streams; i++) { rtsp_st = rt->rtsp_streams[i]; - snprintf(url, sizeof(url), "rtp://%s:%d?localport=%d&ttl=%d", - inet_ntoa(rtsp_st->sdp_ip), - rtsp_st->sdp_port, - rtsp_st->sdp_port, - rtsp_st->sdp_ttl); + ff_url_join(url, sizeof(url), "rtp", NULL, + inet_ntoa(rtsp_st->sdp_ip), 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) { err = AVERROR_INVALIDDATA; goto fail; @@ -1960,13 +1968,15 @@ static int sdp_read_header(AVFormatContext *s, AVFormatParameters *ap) } return 0; fail: - rtsp_close_streams(s); + ff_rtsp_close_streams(s); + ff_network_close(); return err; } static int sdp_read_close(AVFormatContext *s) { - rtsp_close_streams(s); + ff_rtsp_close_streams(s); + ff_network_close(); return 0; }