]> git.sesse.net Git - vlc/blob - modules/access/rtsp/access.c
FSF address change.
[vlc] / modules / access / rtsp / access.c
1 /*****************************************************************************
2  * access.c: Real rtsp input
3  *****************************************************************************
4  * Copyright (C) 2005 VideoLAN
5  * $Id$
6  *
7  * Authors: Gildas Bazin <gbazin@videolan.org>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include <vlc/vlc.h>
28 #include <vlc/input.h>
29
30 #include "network.h"
31 #include "rtsp.h"
32 #include "real.h"
33
34 /*****************************************************************************
35  * Module descriptor
36  *****************************************************************************/
37 static int  Open ( vlc_object_t * );
38 static void Close( vlc_object_t * );
39
40 #define CACHING_TEXT N_("Caching value (ms)")
41 #define CACHING_LONGTEXT N_( \
42     "Allows you to modify the default caching value for RTSP streams. This " \
43     "value should be set in millisecond units." )
44
45 vlc_module_begin();
46     set_description( _("Real RTSP") );
47     set_shortname( _("Real RTSP") );
48     set_category( CAT_INPUT );
49     set_subcategory( SUBCAT_INPUT_ACCESS );
50     add_integer( "realrtsp-caching", 3000, NULL,
51                  CACHING_TEXT, CACHING_LONGTEXT, VLC_TRUE );
52     set_capability( "access2", 10 );
53     set_callbacks( Open, Close );
54     add_shortcut( "realrtsp" );
55     add_shortcut( "rtsp" );
56 vlc_module_end();
57
58
59 /*****************************************************************************
60  * Exported prototypes
61  *****************************************************************************/
62 static block_t *BlockRead( access_t * );
63 static int     Seek( access_t *, int64_t );
64 static int     Control( access_t *, int, va_list );
65
66 struct access_sys_t
67 {
68     vlc_bool_t b_seekable;
69     vlc_bool_t b_pace_control;
70
71     rtsp_client_t *p_rtsp;
72
73     int fd;
74
75     block_t *p_header;
76 };
77
78 /*****************************************************************************
79  * Network wrappers
80  *****************************************************************************/
81 static int RtspConnect( void *p_userdata, char *psz_server, int i_port )
82 {
83     access_t *p_access = (access_t *)p_userdata;
84     access_sys_t *p_sys = p_access->p_sys;
85
86     /* Open connection */
87     p_sys->fd = net_ConnectTCP( p_access, psz_server, i_port );
88     if( p_sys->fd < 0 )
89     {
90         msg_Err( p_access, "cannot connect to %s:%d", psz_server, i_port );
91         return VLC_EGENERIC;
92     }
93
94     return VLC_SUCCESS;
95 }
96
97 static int RtspDisconnect( void *p_userdata )
98 {
99     access_t *p_access = (access_t *)p_userdata;
100     access_sys_t *p_sys = p_access->p_sys;
101
102     net_Close( p_sys->fd );
103     return VLC_SUCCESS;
104 }
105
106 static int RtspRead( void *p_userdata, uint8_t *p_buffer, int i_buffer )
107 {
108     access_t *p_access = (access_t *)p_userdata;
109     access_sys_t *p_sys = p_access->p_sys;
110
111     return net_Read( p_access, p_sys->fd, 0, p_buffer, i_buffer, VLC_TRUE );
112 }
113
114 static int RtspReadLine( void *p_userdata, uint8_t *p_buffer, int i_buffer )
115 {
116     access_t *p_access = (access_t *)p_userdata;
117     access_sys_t *p_sys = p_access->p_sys;
118
119     char *psz = net_Gets( VLC_OBJECT(p_access), p_sys->fd, 0 );
120
121     //fprintf(stderr, "ReadLine: %s\n", psz);
122
123     if( psz ) strncpy( (char *)p_buffer, psz, i_buffer );
124     else *p_buffer = 0;
125
126     if( psz ) free( psz );
127     return 0;
128 }
129
130 static int RtspWrite( void *p_userdata, uint8_t *p_buffer, int i_buffer )
131 {
132     access_t *p_access = (access_t *)p_userdata;
133     access_sys_t *p_sys = p_access->p_sys;
134
135     //fprintf(stderr, "Write: %s", p_buffer);
136
137     net_Printf( VLC_OBJECT(p_access), p_sys->fd, 0, "%s", p_buffer );
138
139     return 0;
140 }
141
142 /*****************************************************************************
143  * Open: open the rtsp connection
144  *****************************************************************************/
145 static int Open( vlc_object_t *p_this )
146 {
147     access_t *p_access = (access_t *)p_this;
148     access_sys_t *p_sys;
149     char *psz_server = 0;
150     int i_result;
151
152     if( !p_access->b_force ) return VLC_EGENERIC;
153
154     p_access->pf_read = NULL;
155     p_access->pf_block = BlockRead;
156     p_access->pf_seek = Seek;
157     p_access->pf_control = Control;
158     p_access->info.i_update = 0;
159     p_access->info.i_size = 0;
160     p_access->info.i_pos = 0;
161     p_access->info.b_eof = VLC_FALSE;
162     p_access->info.i_title = 0;
163     p_access->info.i_seekpoint = 0;
164     p_access->p_sys = p_sys = malloc( sizeof( access_sys_t ) );
165     p_sys->p_rtsp = malloc( sizeof( rtsp_client_t) );
166
167     p_sys->p_header = 0;
168     p_sys->p_rtsp->p_userdata = p_access;
169     p_sys->p_rtsp->pf_connect = RtspConnect;
170     p_sys->p_rtsp->pf_disconnect = RtspDisconnect;
171     p_sys->p_rtsp->pf_read = RtspRead;
172     p_sys->p_rtsp->pf_read_line = RtspReadLine;
173     p_sys->p_rtsp->pf_write = RtspWrite;
174
175     i_result = rtsp_connect( p_sys->p_rtsp, p_access->psz_path, 0 );
176     if( i_result )
177     {
178         msg_Dbg( p_access, "could not connect to: %s", p_access->psz_path );
179         free( p_sys->p_rtsp );
180         p_sys->p_rtsp = 0;
181         goto error;
182     }
183
184     msg_Dbg( p_access, "rtsp connected" );
185
186     /* looking for server type */
187     if( rtsp_search_answers( p_sys->p_rtsp, "Server" ) )
188         psz_server = strdup( rtsp_search_answers( p_sys->p_rtsp, "Server" ) );
189     else
190     {
191         if( rtsp_search_answers( p_sys->p_rtsp, "RealChallenge1" ) )
192             psz_server = strdup("Real");
193         else
194             psz_server = strdup("unknown");
195     }
196
197     if( strstr( psz_server, "Real" ) || strstr( psz_server, "Helix" ) )
198     {
199         uint32_t bandwidth = 10485800;
200         rmff_header_t *h;
201
202         msg_Dbg( p_access, "found a real/helix rtsp server" );
203
204         if( !(h = real_setup_and_get_header( p_sys->p_rtsp, bandwidth )) )
205         {
206             /* Check if we got a redirect */
207             if( rtsp_search_answers( p_sys->p_rtsp, "Location" ) )
208             {
209                 msg_Dbg( p_access, "redirect: %s",
210                          rtsp_search_answers(p_sys->p_rtsp, "Location") );
211                 msg_Warn( p_access, "redirect not supported" );
212                 goto error;
213             }
214
215
216             msg_Err( p_access, "rtsp session can not be established" );
217             goto error;
218         }
219
220         p_sys->p_header = block_New( p_access, 4096 );
221         p_sys->p_header->i_buffer =
222             rmff_dump_header( h, p_sys->p_header->p_buffer, 1024 );
223         rmff_free_header( h );
224     }
225     else
226     {
227         msg_Dbg( p_access, "only real/helix rtsp servers supported for now" );
228         goto error;
229     }
230
231     /* Update default_pts to a suitable value for file access */
232     var_Create( p_access, "realrtsp-caching",
233                 VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
234
235     if( psz_server ) free( psz_server );
236     return VLC_SUCCESS;
237
238  error:
239     if( psz_server ) free( psz_server );
240     Close( p_this );
241     return VLC_EGENERIC;
242 }
243
244 /*****************************************************************************
245  * Close: close the target
246  *****************************************************************************/
247 static void Close( vlc_object_t * p_this )
248 {
249     access_t     *p_access = (access_t*)p_this;
250     access_sys_t *p_sys = p_access->p_sys;
251
252     if( p_sys->p_rtsp ) rtsp_close( p_sys->p_rtsp );
253     if( p_sys->p_rtsp ) free( p_sys->p_rtsp );
254     free( p_sys );
255 }
256
257 /*****************************************************************************
258  * Read: standard read on a file descriptor.
259  *****************************************************************************/
260 static block_t *BlockRead( access_t *p_access )
261 {
262     access_sys_t *p_sys = p_access->p_sys;
263     block_t *p_block;
264     rmff_pheader_t pheader;
265     int i_size;
266
267     if( p_sys->p_header )
268     {
269         p_block = p_sys->p_header;
270         p_sys->p_header = 0;
271         return p_block;
272     }
273
274     i_size = real_get_rdt_chunk_header( p_access->p_sys->p_rtsp, &pheader );
275     if( i_size <= 0 ) return 0;
276
277     p_block = block_New( p_access, i_size );
278     p_block->i_buffer = real_get_rdt_chunk( p_access->p_sys->p_rtsp, &pheader,
279                                             &p_block->p_buffer );
280
281     return p_block;
282 }
283
284 /*****************************************************************************
285  * Seek: seek to a specific location in a file
286  *****************************************************************************/
287 static int Seek( access_t *p_access, int64_t i_pos )
288 {
289     return VLC_SUCCESS;
290 }
291
292 /*****************************************************************************
293  * Control:
294  *****************************************************************************/
295 static int Control( access_t *p_access, int i_query, va_list args )
296 {
297     vlc_bool_t   *pb_bool;
298     int          *pi_int;
299     int64_t      *pi_64;
300
301     switch( i_query )
302     {
303         /* */
304         case ACCESS_CAN_SEEK:
305         case ACCESS_CAN_FASTSEEK:
306             pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t* );
307             *pb_bool = VLC_FALSE;//p_sys->b_seekable;
308             break;
309
310         case ACCESS_CAN_PAUSE:
311             pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t* );
312             *pb_bool = VLC_FALSE;
313             break;
314
315         case ACCESS_CAN_CONTROL_PACE:
316             pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t* );
317             *pb_bool = VLC_TRUE;//p_sys->b_pace_control;
318             break;
319
320         /* */
321         case ACCESS_GET_MTU:
322             pi_int = (int*)va_arg( args, int * );
323             *pi_int = 0;
324             break;
325
326         case ACCESS_GET_PTS_DELAY:
327             pi_64 = (int64_t*)va_arg( args, int64_t * );
328             *pi_64 = var_GetInteger( p_access, "realrtsp-caching" ) * 1000;
329             break;
330
331         /* */
332         case ACCESS_SET_PAUSE_STATE:
333             /* Nothing to do */
334             break;
335
336         case ACCESS_GET_TITLE_INFO:
337         case ACCESS_SET_TITLE:
338         case ACCESS_SET_SEEKPOINT:
339         case ACCESS_SET_PRIVATE_ID_STATE:
340         case ACCESS_GET_META:
341             return VLC_EGENERIC;
342
343         default:
344             msg_Warn( p_access, "unimplemented query in control" );
345             return VLC_EGENERIC;
346     }
347
348     return VLC_SUCCESS;
349 }