Add an RTSP muxer
[ffmpeg.git] / libavformat / rtsp.c
index 4ea35d8..23d56b6 100644 (file)
@@ -572,7 +572,7 @@ static int sdp_parse(AVFormatContext *s, const char *content)
 }
 
 /* close and free RTSP streams */
-static void rtsp_close_streams(AVFormatContext *s)
+void rtsp_close_streams(AVFormatContext *s)
 {
     RTSPState *rt = s->priv_data;
     int i;
@@ -586,6 +586,8 @@ static 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 +691,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))
@@ -879,30 +881,9 @@ static void rtsp_skip_packet(AVFormatContext *s)
     }
 }
 
-/**
- * Read a RTSP message from the server, or prepare to read data
- * packets if we're reading data interleaved over the TCP/RTSP
- * connection as well.
- *
- * @param s RTSP demuxer context
- * @param reply pointer where the RTSP message header will be stored
- * @param content_ptr pointer where the RTSP message body, if any, will
- *                    be stored (length is in reply)
- * @param return_on_interleaved_data whether the function may return if we
- *                   encounter a data marker ('$'), which precedes data
- *                   packets over interleaved TCP/RTSP connections. If this
- *                   is set, this function will return 1 after encountering
- *                   a '$'. If it is not set, the function will skip any
- *                   data packets (if they are encountered), until a reply
- *                   has been fully parsed. If no more data is available
- *                   without parsing a reply, it will return an error.
- *
- * @returns 1 if a data packets is ready to be received, -1 on error,
- *          and 0 on success.
- */
-static int rtsp_read_reply(AVFormatContext *s, RTSPMessageHeader *reply,
-                           unsigned char **content_ptr,
-                           int return_on_interleaved_data)
+int 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;
@@ -987,10 +968,10 @@ static int rtsp_read_reply(AVFormatContext *s, RTSPMessageHeader *reply,
     return 0;
 }
 
-static void rtsp_send_cmd_with_content_async(AVFormatContext *s,
-                                             const char *cmd,
-                                             const unsigned char *send_content,
-                                             int send_content_length)
+void 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];
@@ -1019,26 +1000,26 @@ static void rtsp_send_cmd_with_content_async(AVFormatContext *s,
     rt->last_cmd_time = av_gettime();
 }
 
-static void rtsp_send_cmd_async(AVFormatContext *s, const char *cmd)
+void rtsp_send_cmd_async(AVFormatContext *s, const char *cmd)
 {
     rtsp_send_cmd_with_content_async(s, cmd, NULL, 0);
 }
 
-static void rtsp_send_cmd(AVFormatContext *s,
-                          const char *cmd, RTSPMessageHeader *reply,
-                          unsigned char **content_ptr)
+void rtsp_send_cmd(AVFormatContext *s,
+                   const char *cmd, RTSPMessageHeader *reply,
+                   unsigned char **content_ptr)
 {
     rtsp_send_cmd_async(s, cmd);
 
     rtsp_read_reply(s, reply, content_ptr, 0);
 }
 
-static 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 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);
 
@@ -1166,7 +1147,7 @@ static int make_setup_request(AVFormatContext *s, const char *host, int port,
         if (s->oformat) {
             av_strlcat(transport, ";mode=receive", sizeof(transport));
         } else if (rt->server_type == RTSP_SERVER_REAL ||
-            rt->server_type == RTSP_SERVER_WMS)
+                   rt->server_type == RTSP_SERVER_WMS)
             av_strlcat(transport, ";mode=play", sizeof(transport));
         snprintf(cmd, sizeof(cmd),
                  "SETUP %s RTSP/1.0\r\n"
@@ -1397,7 +1378,7 @@ static int rtsp_setup_output_streams(AVFormatContext *s)
     return 0;
 }
 
-static int rtsp_connect(AVFormatContext *s)
+int rtsp_connect(AVFormatContext *s)
 {
     RTSPState *rt = s->priv_data;
     char host[1024], path[1024], tcpname[1024], cmd[2048], auth[128];
@@ -1515,7 +1496,7 @@ redirect:
     }
 
     if (s->iformat)
-    err = rtsp_setup_input_streams(s);
+        err = rtsp_setup_input_streams(s);
     else
         err = rtsp_setup_output_streams(s);
     if (err)
@@ -1543,7 +1524,7 @@ redirect:
  fail:
     rtsp_close_streams(s);
     url_close(rt->rtsp_hd);
-    if (reply->status_code >=300 && reply->status_code < 400) {
+    if (reply->status_code >=300 && reply->status_code < 400 && s->iformat) {
         av_strlcpy(s->filename, reply->location, sizeof(s->filename));
         av_log(s, AV_LOG_INFO, "Status %d: Redirecting to %s\n",
                reply->status_code,
@@ -1552,7 +1533,9 @@ redirect:
     }
     return err;
 }
+#endif
 
+#if CONFIG_RTSP_DEMUXER
 static int rtsp_read_header(AVFormatContext *s,
                             AVFormatParameters *ap)
 {