]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/rtsp.c
Localize the #define _SVID_SOURCE needed for inet_aton() to os_support.c
[ffmpeg] / libavformat / rtsp.c
index 2e2b6c80588a5cb8e465bc74a6abb393d0cad4f9..60f13275e5e7e9dcdc69460061dddf6ea2daf184 100644 (file)
@@ -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;
 }