From b689213642724e46b03ab78246c43d7d397c9a09 Mon Sep 17 00:00:00 2001 From: Fabrice Bellard Date: Tue, 15 Jul 2003 16:57:35 +0000 Subject: fixed RTP/TCP client support Originally committed as revision 2045 to svn://svn.ffmpeg.org/ffmpeg/trunk --- libavformat/rtsp.c | 76 +++++++++++++++++++++++++++++++++++------------------- 1 file changed, 50 insertions(+), 26 deletions(-) (limited to 'libavformat/rtsp.c') diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c index e6108cc..601f20d 100644 --- a/libavformat/rtsp.c +++ b/libavformat/rtsp.c @@ -29,10 +29,12 @@ #endif //#define DEBUG +//#define DEBUG_RTP_TCP typedef struct RTSPState { URLContext *rtsp_hd; /* RTSP TCP connexion handle */ - ByteIOContext rtsp_gb; + /* XXX: currently we use unbuffered input */ + // ByteIOContext rtsp_gb; int seq; /* RTSP command sequence number */ char session_id[512]; enum RTSPProtocol protocol; @@ -55,7 +57,12 @@ int rtsp_abort_req = 0; /* XXX: currently, the only way to change the protocols consists in changing this variable */ +#if 1 int rtsp_default_protocols = (1 << RTSP_PROTOCOL_RTP_TCP) | (1 << RTSP_PROTOCOL_RTP_UDP) | (1 << RTSP_PROTOCOL_RTP_UDP_MULTICAST); +#else +/* try it if a proxy is used */ +int rtsp_default_protocols = (1 << RTSP_PROTOCOL_RTP_TCP); +#endif /* if non zero, then set a range for RTP ports */ int rtsp_rtp_port_min = 0; @@ -365,7 +372,7 @@ static int sdp_parse(AVFormatContext *s, const char *content) p++; /* get the content */ q = buf; - while (*p != '\n' && *p != '\0') { + while (*p != '\n' && *p != '\r' && *p != '\0') { if ((q - buf) < sizeof(buf) - 1) *q++ = *p; p++; @@ -427,10 +434,11 @@ static void rtsp_parse_transport(RTSPHeader *reply, const char *p) get_word_sep(profile, sizeof(profile), "/;,", &p); lower_transport[0] = '\0'; if (*p == '/') { + p++; get_word_sep(lower_transport, sizeof(lower_transport), ";,", &p); } - if (!strcmp(lower_transport, "TCP")) + if (!strcasecmp(lower_transport, "TCP")) th->protocol = RTSP_PROTOCOL_RTP_TCP; else th->protocol = RTSP_PROTOCOL_RTP_UDP; @@ -526,13 +534,13 @@ static void rtsp_send_cmd(AVFormatContext *s, rt->seq++; pstrcpy(buf, sizeof(buf), cmd); - snprintf(buf1, sizeof(buf1), "CSeq: %d\n", rt->seq); + snprintf(buf1, sizeof(buf1), "CSeq: %d\r\n", rt->seq); pstrcat(buf, sizeof(buf), buf1); if (rt->session_id[0] != '\0' && !strstr(cmd, "\nIf-Match:")) { - snprintf(buf1, sizeof(buf1), "Session: %s\n", rt->session_id); + snprintf(buf1, sizeof(buf1), "Session: %s\r\n", rt->session_id); pstrcat(buf, sizeof(buf), buf1); } - pstrcat(buf, sizeof(buf), "\n"); + pstrcat(buf, sizeof(buf), "\r\n"); #ifdef DEBUG printf("Sending:\n%s--\n", buf); #endif @@ -626,8 +634,8 @@ static int rtsp_read_header(AVFormatContext *s, /* describe the stream */ snprintf(cmd, sizeof(cmd), - "DESCRIBE %s RTSP/1.0\n" - "Accept: application/sdp\n", + "DESCRIBE %s RTSP/1.0\r\n" + "Accept: application/sdp\r\n", s->filename); rtsp_send_cmd(s, cmd, reply, &content); if (!content) { @@ -708,10 +716,9 @@ static int rtsp_read_header(AVFormatContext *s, sizeof(transport) - strlen(transport) - 1, "RTP/AVP/UDP;multicast"); } - snprintf(cmd, sizeof(cmd), - "SETUP %s RTSP/1.0\n" - "Transport: %s\n", + "SETUP %s RTSP/1.0\r\n" + "Transport: %s\r\n", rtsp_st->control_url, transport); rtsp_send_cmd(s, cmd, reply, NULL); if (reply->status_code != RTSP_STATUS_OK || @@ -794,7 +801,8 @@ static int rtsp_read_header(AVFormatContext *s, /* start playing */ snprintf(cmd, sizeof(cmd), - "PLAY %s RTSP/1.0\n", + "PLAY %s RTSP/1.0\r\n" + "Range: npt=0-\r\n", s->filename); rtsp_send_cmd(s, cmd, reply, NULL); if (reply->status_code != RTSP_STATUS_OK) { @@ -802,6 +810,7 @@ static int rtsp_read_header(AVFormatContext *s, goto fail; } +#if 0 /* open TCP with bufferized input */ if (rt->protocol == RTSP_PROTOCOL_RTP_TCP) { if (url_fdopen(&rt->rtsp_gb, rt->rtsp_hd) < 0) { @@ -809,6 +818,7 @@ static int rtsp_read_header(AVFormatContext *s, goto fail; } } +#endif return 0; fail: @@ -830,33 +840,46 @@ static int tcp_read_packet(AVFormatContext *s, AVPacket *pkt) { RTSPState *rt = s->priv_data; - ByteIOContext *rtsp_gb = &rt->rtsp_gb; - int c, id, len, i, ret; + int id, len, i, ret; AVStream *st; RTSPStream *rtsp_st; - char buf[RTP_MAX_PACKET_LENGTH]; + uint8_t buf[RTP_MAX_PACKET_LENGTH]; +#ifdef DEBUG_RTP_TCP + printf("tcp_read_packet:\n"); +#endif redo: for(;;) { - c = url_fgetc(rtsp_gb); - if (c == URL_EOF) + ret = url_read(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) return AVERROR_IO; - if (c == '$') + if (buf[0] == '$') break; } - id = get_byte(rtsp_gb); - len = get_be16(rtsp_gb); + ret = url_read(rt->rtsp_hd, buf, 3); + if (ret != 3) + return AVERROR_IO; + id = buf[0]; + len = (buf[1] << 8) | buf[2]; +#ifdef DEBUG_RTP_TCP + printf("id=%d len=%d\n", id, len); +#endif if (len > RTP_MAX_PACKET_LENGTH || len < 12) goto redo; /* get the data */ - get_buffer(rtsp_gb, buf, len); - + ret = url_read(rt->rtsp_hd, buf, len); + if (ret != len) + return AVERROR_IO; + /* find the matching stream */ for(i = 0; i < s->nb_streams; i++) { st = s->streams[i]; rtsp_st = st->priv_data; - if (i >= rtsp_st->interleaved_min && - i <= rtsp_st->interleaved_max) + if (id >= rtsp_st->interleaved_min && + id <= rtsp_st->interleaved_max) goto found; } goto redo; @@ -945,13 +968,14 @@ static int rtsp_read_close(AVFormatContext *s) int i; char cmd[1024]; +#if 0 /* NOTE: it is valid to flush the buffer here */ if (rt->protocol == RTSP_PROTOCOL_RTP_TCP) { url_fclose(&rt->rtsp_gb); } - +#endif snprintf(cmd, sizeof(cmd), - "TEARDOWN %s RTSP/1.0\n", + "TEARDOWN %s RTSP/1.0\r\n", s->filename); rtsp_send_cmd(s, cmd, reply, NULL); -- cgit v1.1