comparison stream/librtsp/rtsp_session.c @ 19271:64d82a45a05d

introduce new 'stream' directory for all stream layer related components and split them from libmpdemux
author ben
date Mon, 31 Jul 2006 17:39:17 +0000
parents libmpdemux/librtsp/rtsp_session.c@317e0fd394c5
children 81b239327a3e
comparison
equal deleted inserted replaced
19270:7d39b911f0bd 19271:64d82a45a05d
1 /*
2 * This file was ported to MPlayer from xine CVS rtsp_session.c,v 1.9 2003/02/11 16:20:40
3 */
4
5 /*
6 * Copyright (C) 2000-2002 the xine project
7 *
8 * This file is part of xine, a free video player.
9 *
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.
14 *
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.
19 *
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
23 *
24 *
25 * high level interface to rtsp servers.
26 *
27 * 2006, Benjamin Zores and Vincent Mussard
28 * Support for MPEG-TS streaming through RFC compliant RTSP servers
29 */
30
31 #include <sys/types.h>
32 #include "config.h"
33 #ifndef HAVE_WINSOCK2
34 #include <sys/socket.h>
35 #include <netinet/in.h>
36 #include <netdb.h>
37 #else
38 #include <winsock2.h>
39 #endif
40 #include <unistd.h>
41 #include <stdio.h>
42 #include <fcntl.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <inttypes.h>
46
47 #include "mp_msg.h"
48 #include "../rtp.h"
49 #include "rtsp.h"
50 #include "rtsp_rtp.h"
51 #include "rtsp_session.h"
52 #include "../realrtsp/real.h"
53 #include "../realrtsp/rmff.h"
54 #include "../realrtsp/asmrp.h"
55 #include "../realrtsp/xbuffer.h"
56
57 /*
58 #define LOG
59 */
60
61 #define RTSP_OPTIONS_PUBLIC "Public"
62 #define RTSP_OPTIONS_SERVER "Server"
63 #define RTSP_OPTIONS_LOCATION "Location"
64 #define RTSP_OPTIONS_REAL "RealChallenge1"
65 #define RTSP_SERVER_TYPE_REAL "Real"
66 #define RTSP_SERVER_TYPE_HELIX "Helix"
67 #define RTSP_SERVER_TYPE_UNKNOWN "unknown"
68
69 struct rtsp_session_s {
70 rtsp_t *s;
71 struct real_rtsp_session_t* real_session;
72 struct rtp_rtsp_session_t* rtp_session;
73 };
74
75 //rtsp_session_t *rtsp_session_start(char *mrl) {
76 rtsp_session_t *rtsp_session_start(int fd, char **mrl, char *path, char *host, int port, int *redir, uint32_t bandwidth) {
77
78 rtsp_session_t *rtsp_session = NULL;
79 char *server;
80 char *mrl_line = NULL;
81 rmff_header_t *h;
82
83 rtsp_session = malloc (sizeof (rtsp_session_t));
84 rtsp_session->s = NULL;
85 rtsp_session->real_session = NULL;
86 rtsp_session->rtp_session = NULL;
87
88 //connect:
89 *redir = 0;
90
91 /* connect to server */
92 rtsp_session->s=rtsp_connect(fd,*mrl,path,host,port,NULL);
93 if (!rtsp_session->s)
94 {
95 mp_msg (MSGT_OPEN, MSGL_ERR,"rtsp_session: failed to connect to server %s\n", path);
96 free(rtsp_session);
97 return NULL;
98 }
99
100 /* looking for server type */
101 if (rtsp_search_answers(rtsp_session->s,RTSP_OPTIONS_SERVER))
102 server=strdup(rtsp_search_answers(rtsp_session->s,RTSP_OPTIONS_SERVER));
103 else {
104 if (rtsp_search_answers(rtsp_session->s,RTSP_OPTIONS_REAL))
105 server=strdup(RTSP_SERVER_TYPE_REAL);
106 else
107 server=strdup(RTSP_SERVER_TYPE_UNKNOWN);
108 }
109 if (strstr(server,RTSP_SERVER_TYPE_REAL) || strstr(server,RTSP_SERVER_TYPE_HELIX))
110 {
111 /* we are talking to a real server ... */
112
113 h=real_setup_and_get_header(rtsp_session->s, bandwidth);
114 if (!h) {
115 /* got an redirect? */
116 if (rtsp_search_answers(rtsp_session->s, RTSP_OPTIONS_LOCATION))
117 {
118 free(mrl_line);
119 mrl_line=strdup(rtsp_search_answers(rtsp_session->s, RTSP_OPTIONS_LOCATION));
120 mp_msg (MSGT_OPEN, MSGL_INFO,"rtsp_session: redirected to %s\n", mrl_line);
121 rtsp_close(rtsp_session->s);
122 free(server);
123 free(*mrl);
124 free(rtsp_session);
125 /* tell the caller to redirect, return url to redirect to in mrl */
126 *mrl = mrl_line;
127 *redir = 1;
128 return NULL;
129 // goto connect; /* *shudder* i made a design mistake somewhere */
130 } else
131 {
132 mp_msg (MSGT_OPEN, MSGL_ERR,"rtsp_session: session can not be established.\n");
133 rtsp_close(rtsp_session->s);
134 free (server);
135 free(rtsp_session);
136 return NULL;
137 }
138 }
139
140 rtsp_session->real_session = init_real_rtsp_session ();
141 rtsp_session->real_session->header_len =
142 rmff_dump_header (h, (char *) rtsp_session->real_session->header, 1024);
143
144 rtsp_session->real_session->recv =
145 xbuffer_copyin (rtsp_session->real_session->recv, 0,
146 rtsp_session->real_session->header,
147 rtsp_session->real_session->header_len);
148
149 rtsp_session->real_session->recv_size =
150 rtsp_session->real_session->header_len;
151 rtsp_session->real_session->recv_read = 0;
152 } else /* not a Real server : try RTP instead */
153 {
154 char *public = NULL;
155
156 /* look for the Public: field in response to RTSP OPTIONS */
157 public = strdup (rtsp_search_answers (rtsp_session->s,
158 RTSP_OPTIONS_PUBLIC));
159 if (!public)
160 {
161 rtsp_close (rtsp_session->s);
162 free (server);
163 free (mrl_line);
164 free (rtsp_session);
165 return NULL;
166 }
167
168 /* check for minimalistic RTSP RFC compliance */
169 if (!strstr (public, RTSP_METHOD_DESCRIBE)
170 || !strstr (public, RTSP_METHOD_SETUP)
171 || !strstr (public, RTSP_METHOD_PLAY)
172 || !strstr (public, RTSP_METHOD_TEARDOWN))
173 {
174 free (public);
175 mp_msg (MSGT_OPEN, MSGL_ERR,
176 "Remote server does not meet minimal RTSP 1.0 compliance.\n");
177 rtsp_close (rtsp_session->s);
178 free (server);
179 free (mrl_line);
180 free (rtsp_session);
181 return NULL;
182 }
183
184 free (public);
185 rtsp_session->rtp_session = rtp_setup_and_play (rtsp_session->s);
186
187 /* neither a Real or an RTP server */
188 if (!rtsp_session->rtp_session)
189 {
190 mp_msg (MSGT_OPEN, MSGL_ERR, "rtsp_session: unsupported RTSP server. ");
191 mp_msg (MSGT_OPEN, MSGL_ERR, "Server type is '%s'.\n", server);
192 rtsp_close (rtsp_session->s);
193 free (server);
194 free (mrl_line);
195 free (rtsp_session);
196 return NULL;
197 }
198 }
199 free(server);
200
201 return rtsp_session;
202 }
203
204 int rtsp_session_read (rtsp_session_t *this, char *data, int len) {
205
206 if (this->real_session) {
207 int to_copy=len;
208 char *dest=data;
209 char *source =
210 (char *) (this->real_session->recv + this->real_session->recv_read);
211 int fill = this->real_session->recv_size - this->real_session->recv_read;
212
213 if (len < 0) return 0;
214 while (to_copy > fill) {
215
216 memcpy(dest, source, fill);
217 to_copy -= fill;
218 dest += fill;
219 this->real_session->recv_read = 0;
220 this->real_session->recv_size =
221 real_get_rdt_chunk (this->s, (char **)&(this->real_session->recv));
222 if (this->real_session->recv_size < 0)
223 return -1;
224 source = (char *) this->real_session->recv;
225 fill = this->real_session->recv_size;
226
227 if (this->real_session->recv_size == 0) {
228 #ifdef LOG
229 mp_msg (MSGT_OPEN, MSGL_INFO, "librtsp: %d of %d bytes provided\n", len-to_copy, len);
230 #endif
231 return len-to_copy;
232 }
233 }
234
235 memcpy(dest, source, to_copy);
236 this->real_session->recv_read += to_copy;
237
238 #ifdef LOG
239 mp_msg (MSGT_OPEN, MSGL_INFO, "librtsp: %d bytes provided\n", len);
240 #endif
241
242 return len;
243 }
244 else if (this->rtp_session)
245 {
246 int l = 0;
247
248 l = read_rtp_from_server (this->rtp_session->rtp_socket, data, len);
249 /* send RTSP and RTCP keepalive */
250 rtcp_send_rr (this->s, this->rtp_session);
251
252 if (l == 0)
253 rtsp_session_end (this);
254
255 return l;
256 }
257
258 return 0;
259 }
260
261 void rtsp_session_end(rtsp_session_t *session) {
262
263 rtsp_close(session->s);
264 if (session->real_session)
265 free_real_rtsp_session (session->real_session);
266 if (session->rtp_session)
267 rtp_session_free (session->rtp_session);
268 free(session);
269 }