2 * This file was ported to MPlayer from xine CVS rtsp_session.c,v 1.9 2003/02/11 16:20:40
6 * Copyright (C) 2000-2002 the xine project
8 * This file is part of xine, a free video player.
10 * xine is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * xine is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
25 * high level interface to rtsp servers.
27 * 2006, Benjamin Zores and Vincent Mussard
28 * Support for MPEG-TS streaming through RFC compliant RTSP servers
31 #include <sys/types.h>
34 #include <sys/socket.h>
35 #include <netinet/in.h>
52 #include "rtsp_session.h"
53 #include "stream/network.h"
54 #include "stream/url.h"
55 #include "stream/rtp.h"
56 #include "stream/realrtsp/real.h"
57 #include "stream/realrtsp/rmff.h"
58 #include "stream/realrtsp/asmrp.h"
59 #include "stream/realrtsp/xbuffer.h"
65 #define RTSP_OPTIONS_PUBLIC "Public"
66 #define RTSP_OPTIONS_SERVER "Server"
67 #define RTSP_OPTIONS_LOCATION "Location"
68 #define RTSP_OPTIONS_REAL "RealChallenge1"
69 #define RTSP_SERVER_TYPE_REAL "Real"
70 #define RTSP_SERVER_TYPE_HELIX "Helix"
71 #define RTSP_SERVER_TYPE_UNKNOWN "unknown"
73 struct rtsp_session_s
{
75 struct real_rtsp_session_t
* real_session
;
76 struct rtp_rtsp_session_t
* rtp_session
;
80 * closes an rtsp connection
83 static void rtsp_close(rtsp_t
*s
) {
87 if (s
->server_state
== RTSP_PLAYING
)
88 rtsp_request_teardown (s
, NULL
);
92 if (s
->path
) free(s
->path
);
93 if (s
->host
) free(s
->host
);
94 if (s
->mrl
) free(s
->mrl
);
95 if (s
->session
) free(s
->session
);
96 if (s
->user_agent
) free(s
->user_agent
);
98 rtsp_unschedule_all(s
);
102 //rtsp_session_t *rtsp_session_start(char *mrl) {
103 rtsp_session_t
*rtsp_session_start(int fd
, char **mrl
, char *path
, char *host
,
104 int port
, int *redir
, uint32_t bandwidth
, char *user
, char *pass
) {
106 rtsp_session_t
*rtsp_session
= NULL
;
108 char *mrl_line
= NULL
;
111 rtsp_session
= malloc (sizeof (rtsp_session_t
));
112 rtsp_session
->s
= NULL
;
113 rtsp_session
->real_session
= NULL
;
114 rtsp_session
->rtp_session
= NULL
;
119 /* connect to server */
120 rtsp_session
->s
=rtsp_connect(fd
,*mrl
,path
,host
,port
,NULL
);
121 if (!rtsp_session
->s
)
123 mp_msg (MSGT_OPEN
, MSGL_ERR
,"rtsp_session: failed to connect to server %s\n", path
);
128 /* looking for server type */
129 if (rtsp_search_answers(rtsp_session
->s
,RTSP_OPTIONS_SERVER
))
130 server
=strdup(rtsp_search_answers(rtsp_session
->s
,RTSP_OPTIONS_SERVER
));
132 if (rtsp_search_answers(rtsp_session
->s
,RTSP_OPTIONS_REAL
))
133 server
=strdup(RTSP_SERVER_TYPE_REAL
);
135 server
=strdup(RTSP_SERVER_TYPE_UNKNOWN
);
137 if (strstr(server
,RTSP_SERVER_TYPE_REAL
) || strstr(server
,RTSP_SERVER_TYPE_HELIX
))
139 /* we are talking to a real server ... */
141 h
=real_setup_and_get_header(rtsp_session
->s
, bandwidth
, user
, pass
);
143 /* got an redirect? */
144 if (rtsp_search_answers(rtsp_session
->s
, RTSP_OPTIONS_LOCATION
))
147 mrl_line
=strdup(rtsp_search_answers(rtsp_session
->s
, RTSP_OPTIONS_LOCATION
));
148 mp_msg (MSGT_OPEN
, MSGL_INFO
,"rtsp_session: redirected to %s\n", mrl_line
);
149 rtsp_close(rtsp_session
->s
);
153 /* tell the caller to redirect, return url to redirect to in mrl */
157 // goto connect; /* *shudder* i made a design mistake somewhere */
160 mp_msg (MSGT_OPEN
, MSGL_ERR
,"rtsp_session: session can not be established.\n");
161 rtsp_close(rtsp_session
->s
);
168 rtsp_session
->real_session
= init_real_rtsp_session ();
169 if(!strncmp(h
->streams
[0]->mime_type
, "application/vnd.rn-rmadriver", h
->streams
[0]->mime_type_size
) ||
170 !strncmp(h
->streams
[0]->mime_type
, "application/smil", h
->streams
[0]->mime_type_size
)) {
171 rtsp_session
->real_session
->header_len
= 0;
172 rtsp_session
->real_session
->recv_size
= 0;
173 rtsp_session
->real_session
->rdt_rawdata
= 1;
174 mp_msg(MSGT_OPEN
, MSGL_V
, "smil-over-realrtsp playlist, switching to raw rdt mode\n");
176 rtsp_session
->real_session
->header_len
=
177 rmff_dump_header (h
, (char *) rtsp_session
->real_session
->header
, HEADER_SIZE
);
179 if (rtsp_session
->real_session
->header_len
< 0) {
180 mp_msg (MSGT_OPEN
, MSGL_ERR
,"rtsp_session: error while dumping RMFF headers, session can not be established.\n");
181 free_real_rtsp_session(rtsp_session
->real_session
);
182 rtsp_close(rtsp_session
->s
);
189 rtsp_session
->real_session
->recv
=
190 xbuffer_copyin (rtsp_session
->real_session
->recv
, 0,
191 rtsp_session
->real_session
->header
,
192 rtsp_session
->real_session
->header_len
);
194 rtsp_session
->real_session
->recv_size
=
195 rtsp_session
->real_session
->header_len
;
197 rtsp_session
->real_session
->recv_read
= 0;
198 } else /* not a Real server : try RTP instead */
202 /* look for the Public: field in response to RTSP OPTIONS */
203 if (!(public = rtsp_search_answers (rtsp_session
->s
, RTSP_OPTIONS_PUBLIC
)))
205 rtsp_close (rtsp_session
->s
);
212 /* check for minimalistic RTSP RFC compliance */
213 if (!strstr (public, RTSP_METHOD_DESCRIBE
)
214 || !strstr (public, RTSP_METHOD_SETUP
)
215 || !strstr (public, RTSP_METHOD_PLAY
)
216 || !strstr (public, RTSP_METHOD_TEARDOWN
))
218 mp_msg (MSGT_OPEN
, MSGL_ERR
,
219 "Remote server does not meet minimal RTSP 1.0 compliance.\n");
220 rtsp_close (rtsp_session
->s
);
227 rtsp_session
->rtp_session
= rtp_setup_and_play (rtsp_session
->s
);
229 /* neither a Real or an RTP server */
230 if (!rtsp_session
->rtp_session
)
232 mp_msg (MSGT_OPEN
, MSGL_ERR
, "rtsp_session: unsupported RTSP server. ");
233 mp_msg (MSGT_OPEN
, MSGL_ERR
, "Server type is '%s'.\n", server
);
234 rtsp_close (rtsp_session
->s
);
246 int rtsp_session_read (rtsp_session_t
*this, char *data
, int len
) {
248 if (this->real_session
) {
252 (char *) (this->real_session
->recv
+ this->real_session
->recv_read
);
253 int fill
= this->real_session
->recv_size
- this->real_session
->recv_read
;
255 if(this->real_session
->rdteof
)
257 if (len
< 0) return 0;
258 if (this->real_session
->recv_size
< 0) return -1;
259 while (to_copy
> fill
) {
261 memcpy(dest
, source
, fill
);
264 this->real_session
->recv_read
= 0;
265 this->real_session
->recv_size
=
266 real_get_rdt_chunk (this->s
, (char **)&(this->real_session
->recv
), this->real_session
->rdt_rawdata
);
267 if (this->real_session
->recv_size
< 0) {
268 this->real_session
->rdteof
= 1;
269 this->real_session
->recv_size
= 0;
271 source
= (char *) this->real_session
->recv
;
272 fill
= this->real_session
->recv_size
;
274 if (this->real_session
->recv_size
== 0) {
276 mp_msg (MSGT_OPEN
, MSGL_INFO
, "librtsp: %d of %d bytes provided\n", len
-to_copy
, len
);
282 memcpy(dest
, source
, to_copy
);
283 this->real_session
->recv_read
+= to_copy
;
286 mp_msg (MSGT_OPEN
, MSGL_INFO
, "librtsp: %d bytes provided\n", len
);
291 else if (this->rtp_session
)
295 l
= read_rtp_from_server (this->rtp_session
->rtp_socket
, data
, len
);
296 /* send RTSP and RTCP keepalive */
297 rtcp_send_rr (this->s
, this->rtp_session
);
300 rtsp_session_end (this);
308 void rtsp_session_end(rtsp_session_t
*session
) {
310 rtsp_close(session
->s
);
311 if (session
->real_session
)
312 free_real_rtsp_session (session
->real_session
);
313 if (session
->rtp_session
)
314 rtp_session_free (session
->rtp_session
);