summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRonald S. Bultje <rsbultje@gmail.com>2009-03-21 20:46:36 +0000
committerRonald S. Bultje <rsbultje@gmail.com>2009-03-21 20:46:36 +0000
commit7e726132c23f4885c877189889c3f2171b1248de (patch)
tree9f00feab890ffde31dfc6badf4aafd6be35fc9d0
parent9c610b76676283219d941513ddeff625be953d83 (diff)
Allow (and parse) incoming server messages (notices) interleaved with TCP
data packets or in addition to UDP data packets, over the RTSP/TCP connection. See discussion in [PATCH] rtsp.c: read TCP server notifications/messages" thread on mailinglist. Originally committed as revision 18121 to svn://svn.ffmpeg.org/ffmpeg/trunk
-rw-r--r--libavformat/rtsp.c65
1 files changed, 51 insertions, 14 deletions
diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c
index e4866200f7..3907eb4b93 100644
--- a/libavformat/rtsp.c
+++ b/libavformat/rtsp.c
@@ -744,15 +744,36 @@ static void rtsp_skip_packet(AVFormatContext *s)
}
}
-static void
+/**
+ * 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 \p 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)
+ unsigned char **content_ptr, int return_on_interleaved_data)
{
RTSPState *rt = s->priv_data;
char buf[4096], buf1[1024], *q;
unsigned char ch;
const char *p;
- int content_length, line_count = 0;
+ int ret, content_length, line_count = 0;
unsigned char *content = NULL;
memset(reply, 0, sizeof(*reply));
@@ -762,12 +783,19 @@ rtsp_read_reply (AVFormatContext *s, RTSPMessageHeader *reply,
for(;;) {
q = buf;
for(;;) {
- if (url_readbuf(rt->rtsp_hd, &ch, 1) != 1)
- break;
+ ret = url_readbuf(rt->rtsp_hd, &ch, 1);
+#ifdef DEBUG_RTP_TCP
+ printf("ret=%d c=%02x [%c]\n", ret, ch, ch);
+#endif
+ if (ret != 1)
+ return -1;
if (ch == '\n')
break;
if (ch == '$') {
/* XXX: only parse it if first char on line ? */
+ if (return_on_interleaved_data) {
+ return 1;
+ } else
rtsp_skip_packet(s);
} else if (ch != '\r') {
if ((q - buf) < sizeof(buf) - 1)
@@ -809,6 +837,8 @@ rtsp_read_reply (AVFormatContext *s, RTSPMessageHeader *reply,
*content_ptr = content;
else
av_free(content);
+
+ return 0;
}
static void rtsp_send_cmd(AVFormatContext *s,
@@ -832,7 +862,7 @@ static void rtsp_send_cmd(AVFormatContext *s,
#endif
url_write(rt->rtsp_hd, buf, strlen(buf));
- rtsp_read_reply(s, reply, content_ptr);
+ rtsp_read_reply(s, reply, content_ptr, 0);
}
@@ -1277,14 +1307,14 @@ static int tcp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st,
#endif
redo:
for(;;) {
- ret = url_readbuf(rt->rtsp_hd, buf, 1);
-#ifdef DEBUG_RTP_TCP
- printf("ret=%d c=%02x [%c]\n", ret, buf[0], buf[0]);
-#endif
- if (ret != 1)
+ RTSPMessageHeader reply;
+
+ ret = rtsp_read_reply(s, &reply, NULL, 1);
+ if (ret == -1)
return -1;
- if (buf[0] == '$')
+ if (ret == 1) /* received '$' */
break;
+ /* XXX: parse message */
}
ret = url_readbuf(rt->rtsp_hd, buf, 3);
if (ret != 3)
@@ -1323,14 +1353,15 @@ static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st,
RTSPState *rt = s->priv_data;
RTSPStream *rtsp_st;
fd_set rfds;
- int fd, fd_max, n, i, ret;
+ int fd, fd_max, n, i, ret, tcp_fd;
struct timeval tv;
for(;;) {
if (url_interrupt_cb())
return AVERROR(EINTR);
FD_ZERO(&rfds);
- fd_max = -1;
+ tcp_fd = fd_max = url_get_file_handle(rt->rtsp_hd);
+ FD_SET(tcp_fd, &rfds);
for(i = 0; i < rt->nb_rtsp_streams; i++) {
rtsp_st = rt->rtsp_streams[i];
if (rtsp_st->rtp_handle) {
@@ -1359,6 +1390,12 @@ static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st,
}
}
}
+ if (FD_ISSET(tcp_fd, &rfds)) {
+ RTSPMessageHeader reply;
+
+ rtsp_read_reply(s, &reply, NULL, 0);
+ /* XXX: parse message */
+ }
}
}
}