Commit ff42d015 authored by bellard's avatar bellard

fixed RTP/TCP client support


git-svn-id: file:///var/local/repositories/ffmpeg/trunk@2045 9553f0bf-9b14-0410-a0b8-cfaf0461ba5b
parent 70168737
...@@ -29,10 +29,12 @@ ...@@ -29,10 +29,12 @@
#endif #endif
//#define DEBUG //#define DEBUG
//#define DEBUG_RTP_TCP
typedef struct RTSPState { typedef struct RTSPState {
URLContext *rtsp_hd; /* RTSP TCP connexion handle */ 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 */ int seq; /* RTSP command sequence number */
char session_id[512]; char session_id[512];
enum RTSPProtocol protocol; enum RTSPProtocol protocol;
...@@ -55,7 +57,12 @@ int rtsp_abort_req = 0; ...@@ -55,7 +57,12 @@ int rtsp_abort_req = 0;
/* XXX: currently, the only way to change the protocols consists in /* XXX: currently, the only way to change the protocols consists in
changing this variable */ 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); 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 */ /* if non zero, then set a range for RTP ports */
int rtsp_rtp_port_min = 0; int rtsp_rtp_port_min = 0;
...@@ -365,7 +372,7 @@ static int sdp_parse(AVFormatContext *s, const char *content) ...@@ -365,7 +372,7 @@ static int sdp_parse(AVFormatContext *s, const char *content)
p++; p++;
/* get the content */ /* get the content */
q = buf; q = buf;
while (*p != '\n' && *p != '\0') { while (*p != '\n' && *p != '\r' && *p != '\0') {
if ((q - buf) < sizeof(buf) - 1) if ((q - buf) < sizeof(buf) - 1)
*q++ = *p; *q++ = *p;
p++; p++;
...@@ -427,10 +434,11 @@ static void rtsp_parse_transport(RTSPHeader *reply, const char *p) ...@@ -427,10 +434,11 @@ static void rtsp_parse_transport(RTSPHeader *reply, const char *p)
get_word_sep(profile, sizeof(profile), "/;,", &p); get_word_sep(profile, sizeof(profile), "/;,", &p);
lower_transport[0] = '\0'; lower_transport[0] = '\0';
if (*p == '/') { if (*p == '/') {
p++;
get_word_sep(lower_transport, sizeof(lower_transport), get_word_sep(lower_transport, sizeof(lower_transport),
";,", &p); ";,", &p);
} }
if (!strcmp(lower_transport, "TCP")) if (!strcasecmp(lower_transport, "TCP"))
th->protocol = RTSP_PROTOCOL_RTP_TCP; th->protocol = RTSP_PROTOCOL_RTP_TCP;
else else
th->protocol = RTSP_PROTOCOL_RTP_UDP; th->protocol = RTSP_PROTOCOL_RTP_UDP;
...@@ -526,13 +534,13 @@ static void rtsp_send_cmd(AVFormatContext *s, ...@@ -526,13 +534,13 @@ static void rtsp_send_cmd(AVFormatContext *s,
rt->seq++; rt->seq++;
pstrcpy(buf, sizeof(buf), cmd); 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); pstrcat(buf, sizeof(buf), buf1);
if (rt->session_id[0] != '\0' && !strstr(cmd, "\nIf-Match:")) { 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), buf1);
} }
pstrcat(buf, sizeof(buf), "\n"); pstrcat(buf, sizeof(buf), "\r\n");
#ifdef DEBUG #ifdef DEBUG
printf("Sending:\n%s--\n", buf); printf("Sending:\n%s--\n", buf);
#endif #endif
...@@ -626,8 +634,8 @@ static int rtsp_read_header(AVFormatContext *s, ...@@ -626,8 +634,8 @@ static int rtsp_read_header(AVFormatContext *s,
/* describe the stream */ /* describe the stream */
snprintf(cmd, sizeof(cmd), snprintf(cmd, sizeof(cmd),
"DESCRIBE %s RTSP/1.0\n" "DESCRIBE %s RTSP/1.0\r\n"
"Accept: application/sdp\n", "Accept: application/sdp\r\n",
s->filename); s->filename);
rtsp_send_cmd(s, cmd, reply, &content); rtsp_send_cmd(s, cmd, reply, &content);
if (!content) { if (!content) {
...@@ -708,10 +716,9 @@ static int rtsp_read_header(AVFormatContext *s, ...@@ -708,10 +716,9 @@ static int rtsp_read_header(AVFormatContext *s,
sizeof(transport) - strlen(transport) - 1, sizeof(transport) - strlen(transport) - 1,
"RTP/AVP/UDP;multicast"); "RTP/AVP/UDP;multicast");
} }
snprintf(cmd, sizeof(cmd), snprintf(cmd, sizeof(cmd),
"SETUP %s RTSP/1.0\n" "SETUP %s RTSP/1.0\r\n"
"Transport: %s\n", "Transport: %s\r\n",
rtsp_st->control_url, transport); rtsp_st->control_url, transport);
rtsp_send_cmd(s, cmd, reply, NULL); rtsp_send_cmd(s, cmd, reply, NULL);
if (reply->status_code != RTSP_STATUS_OK || if (reply->status_code != RTSP_STATUS_OK ||
...@@ -794,7 +801,8 @@ static int rtsp_read_header(AVFormatContext *s, ...@@ -794,7 +801,8 @@ static int rtsp_read_header(AVFormatContext *s,
/* start playing */ /* start playing */
snprintf(cmd, sizeof(cmd), snprintf(cmd, sizeof(cmd),
"PLAY %s RTSP/1.0\n", "PLAY %s RTSP/1.0\r\n"
"Range: npt=0-\r\n",
s->filename); s->filename);
rtsp_send_cmd(s, cmd, reply, NULL); rtsp_send_cmd(s, cmd, reply, NULL);
if (reply->status_code != RTSP_STATUS_OK) { if (reply->status_code != RTSP_STATUS_OK) {
...@@ -802,6 +810,7 @@ static int rtsp_read_header(AVFormatContext *s, ...@@ -802,6 +810,7 @@ static int rtsp_read_header(AVFormatContext *s,
goto fail; goto fail;
} }
#if 0
/* open TCP with bufferized input */ /* open TCP with bufferized input */
if (rt->protocol == RTSP_PROTOCOL_RTP_TCP) { if (rt->protocol == RTSP_PROTOCOL_RTP_TCP) {
if (url_fdopen(&rt->rtsp_gb, rt->rtsp_hd) < 0) { if (url_fdopen(&rt->rtsp_gb, rt->rtsp_hd) < 0) {
...@@ -809,6 +818,7 @@ static int rtsp_read_header(AVFormatContext *s, ...@@ -809,6 +818,7 @@ static int rtsp_read_header(AVFormatContext *s,
goto fail; goto fail;
} }
} }
#endif
return 0; return 0;
fail: fail:
...@@ -830,33 +840,46 @@ static int tcp_read_packet(AVFormatContext *s, ...@@ -830,33 +840,46 @@ static int tcp_read_packet(AVFormatContext *s,
AVPacket *pkt) AVPacket *pkt)
{ {
RTSPState *rt = s->priv_data; RTSPState *rt = s->priv_data;
ByteIOContext *rtsp_gb = &rt->rtsp_gb; int id, len, i, ret;
int c, id, len, i, ret;
AVStream *st; AVStream *st;
RTSPStream *rtsp_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: redo:
for(;;) { for(;;) {
c = url_fgetc(rtsp_gb); ret = url_read(rt->rtsp_hd, buf, 1);
if (c == URL_EOF) #ifdef DEBUG_RTP_TCP
printf("ret=%d c=%02x [%c]\n", ret, buf[0], buf[0]);
#endif
if (ret != 1)
return AVERROR_IO; return AVERROR_IO;
if (c == '$') if (buf[0] == '$')
break; break;
} }
id = get_byte(rtsp_gb); ret = url_read(rt->rtsp_hd, buf, 3);
len = get_be16(rtsp_gb); 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) if (len > RTP_MAX_PACKET_LENGTH || len < 12)
goto redo; goto redo;
/* get the data */ /* 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 */ /* find the matching stream */
for(i = 0; i < s->nb_streams; i++) { for(i = 0; i < s->nb_streams; i++) {
st = s->streams[i]; st = s->streams[i];
rtsp_st = st->priv_data; rtsp_st = st->priv_data;
if (i >= rtsp_st->interleaved_min && if (id >= rtsp_st->interleaved_min &&
i <= rtsp_st->interleaved_max) id <= rtsp_st->interleaved_max)
goto found; goto found;
} }
goto redo; goto redo;
...@@ -945,13 +968,14 @@ static int rtsp_read_close(AVFormatContext *s) ...@@ -945,13 +968,14 @@ static int rtsp_read_close(AVFormatContext *s)
int i; int i;
char cmd[1024]; char cmd[1024];
#if 0
/* NOTE: it is valid to flush the buffer here */ /* NOTE: it is valid to flush the buffer here */
if (rt->protocol == RTSP_PROTOCOL_RTP_TCP) { if (rt->protocol == RTSP_PROTOCOL_RTP_TCP) {
url_fclose(&rt->rtsp_gb); url_fclose(&rt->rtsp_gb);
} }
#endif
snprintf(cmd, sizeof(cmd), snprintf(cmd, sizeof(cmd),
"TEARDOWN %s RTSP/1.0\n", "TEARDOWN %s RTSP/1.0\r\n",
s->filename); s->filename);
rtsp_send_cmd(s, cmd, reply, NULL); rtsp_send_cmd(s, cmd, reply, NULL);
......
...@@ -312,7 +312,7 @@ int av_open_input_file(AVFormatContext **ic_ptr, const char *filename, ...@@ -312,7 +312,7 @@ int av_open_input_file(AVFormatContext **ic_ptr, const char *filename,
AVFormatParameters *ap) AVFormatParameters *ap)
{ {
AVFormatContext *ic = NULL; AVFormatContext *ic = NULL;
int err; int err, must_open_file;
char buf[PROBE_BUF_SIZE]; char buf[PROBE_BUF_SIZE];
AVProbeData probe_data, *pd = &probe_data; AVProbeData probe_data, *pd = &probe_data;
...@@ -331,7 +331,15 @@ int av_open_input_file(AVFormatContext **ic_ptr, const char *filename, ...@@ -331,7 +331,15 @@ int av_open_input_file(AVFormatContext **ic_ptr, const char *filename,
fmt = av_probe_input_format(pd, 0); fmt = av_probe_input_format(pd, 0);
} }
if (!fmt || !(fmt->flags & AVFMT_NOFILE)) { /* do not open file if the format does not need it. XXX: specific
hack needed to handle RTSP/TCP */
must_open_file = 1;
if ((fmt->flags & AVFMT_NOFILE) ||
(fmt == &rtp_demux && !strcmp(filename, "null"))) {
must_open_file = 0;
}
if (!fmt || must_open_file) {
/* if no file needed do not try to open one */ /* if no file needed do not try to open one */
if (url_fopen(&ic->pb, filename, URL_RDONLY) < 0) { if (url_fopen(&ic->pb, filename, URL_RDONLY) < 0) {
err = AVERROR_IO; err = AVERROR_IO;
...@@ -397,7 +405,7 @@ int av_open_input_file(AVFormatContext **ic_ptr, const char *filename, ...@@ -397,7 +405,7 @@ int av_open_input_file(AVFormatContext **ic_ptr, const char *filename,
*ic_ptr = ic; *ic_ptr = ic;
return 0; return 0;
fail1: fail1:
if (!fmt || !(fmt->flags & AVFMT_NOFILE)) { if (!fmt || must_open_file) {
url_fclose(&ic->pb); url_fclose(&ic->pb);
} }
fail: fail:
...@@ -664,7 +672,7 @@ int av_find_stream_info(AVFormatContext *ic) ...@@ -664,7 +672,7 @@ int av_find_stream_info(AVFormatContext *ic)
*/ */
void av_close_input_file(AVFormatContext *s) void av_close_input_file(AVFormatContext *s)
{ {
int i; int i, must_open_file;
if (s->iformat->read_close) if (s->iformat->read_close)
s->iformat->read_close(s); s->iformat->read_close(s);
...@@ -682,7 +690,12 @@ void av_close_input_file(AVFormatContext *s) ...@@ -682,7 +690,12 @@ void av_close_input_file(AVFormatContext *s)
} }
s->packet_buffer = NULL; s->packet_buffer = NULL;
} }
if (!(s->iformat->flags & AVFMT_NOFILE)) { must_open_file = 1;
if ((s->iformat->flags & AVFMT_NOFILE) ||
(s->iformat == &rtp_demux && !strcmp(s->filename, "null"))) {
must_open_file = 0;
}
if (must_open_file) {
url_fclose(&s->pb); url_fclose(&s->pb);
} }
av_freep(&s->priv_data); av_freep(&s->priv_data);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment