Mercurial > mplayer.hg
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 } |