]> git.sesse.net Git - vlc/blob - modules/access/rtsp/access.c
Access strings (Refs:#438)
[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     "Default caching value for RTSP streams. This " \
43     "value should be set in milliseconds." )
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     add_shortcut( "pnm" );
57 vlc_module_end();
58
59
60 /*****************************************************************************
61  * Exported prototypes
62  *****************************************************************************/
63 static block_t *BlockRead( access_t * );
64 static int     Seek( access_t *, int64_t );
65 static int     Control( access_t *, int, va_list );
66
67 struct access_sys_t
68 {
69     vlc_bool_t b_seekable;
70     vlc_bool_t b_pace_control;
71
72     rtsp_client_t *p_rtsp;
73
74     int fd;
75
76     block_t *p_header;
77 };
78
79 /*****************************************************************************
80  * Network wrappers
81  *****************************************************************************/
82 static int RtspConnect( void *p_userdata, char *psz_server, int i_port )
83 {
84     access_t *p_access = (access_t *)p_userdata;
85     access_sys_t *p_sys = p_access->p_sys;
86
87     /* Open connection */
88     p_sys->fd = net_ConnectTCP( p_access, psz_server, i_port );
89     if( p_sys->fd < 0 )
90     {
91         msg_Err( p_access, "cannot connect to %s:%d", psz_server, i_port );
92         return VLC_EGENERIC;
93     }
94
95     return VLC_SUCCESS;
96 }
97
98 static int RtspDisconnect( void *p_userdata )
99 {
100     access_t *p_access = (access_t *)p_userdata;
101     access_sys_t *p_sys = p_access->p_sys;
102
103     net_Close( p_sys->fd );
104     return VLC_SUCCESS;
105 }
106
107 static int RtspRead( void *p_userdata, uint8_t *p_buffer, int i_buffer )
108 {
109     access_t *p_access = (access_t *)p_userdata;
110     access_sys_t *p_sys = p_access->p_sys;
111
112     return net_Read( p_access, p_sys->fd, 0, p_buffer, i_buffer, VLC_TRUE );
113 }
114
115 static int RtspReadLine( void *p_userdata, uint8_t *p_buffer, int i_buffer )
116 {
117     access_t *p_access = (access_t *)p_userdata;
118     access_sys_t *p_sys = p_access->p_sys;
119
120     char *psz = net_Gets( VLC_OBJECT(p_access), p_sys->fd, 0 );
121
122     //fprintf(stderr, "ReadLine: %s\n", psz);
123
124     if( psz ) strncpy( (char *)p_buffer, psz, i_buffer );
125     else *p_buffer = 0;
126
127     if( psz ) free( psz );
128     return 0;
129 }
130
131 static int RtspWrite( void *p_userdata, uint8_t *p_buffer, int i_buffer )
132 {
133     access_t *p_access = (access_t *)p_userdata;
134     access_sys_t *p_sys = p_access->p_sys;
135
136     //fprintf(stderr, "Write: %s", p_buffer);
137
138     net_Printf( VLC_OBJECT(p_access), p_sys->fd, 0, "%s", p_buffer );
139
140     return 0;
141 }
142
143 /*****************************************************************************
144  * Open: open the rtsp connection
145  *****************************************************************************/
146 static int Open( vlc_object_t *p_this )
147 {
148     access_t *p_access = (access_t *)p_this;
149     access_sys_t *p_sys;
150     char *psz_server = 0;
151     int i_result;
152
153     if( !p_access->b_force ) return VLC_EGENERIC;
154
155     p_access->pf_read = NULL;
156     p_access->pf_block = BlockRead;
157     p_access->pf_seek = Seek;
158     p_access->pf_control = Control;
159     p_access->info.i_update = 0;
160     p_access->info.i_size = 0;
161     p_access->info.i_pos = 0;
162     p_access->info.b_eof = VLC_FALSE;
163     p_access->info.i_title = 0;
164     p_access->info.i_seekpoint = 0;
165     p_access->p_sys = p_sys = malloc( sizeof( access_sys_t ) );
166     p_sys->p_rtsp = malloc( sizeof( rtsp_client_t) );
167
168     p_sys->p_header = 0;
169     p_sys->p_rtsp->p_userdata = p_access;
170     p_sys->p_rtsp->pf_connect = RtspConnect;
171     p_sys->p_rtsp->pf_disconnect = RtspDisconnect;
172     p_sys->p_rtsp->pf_read = RtspRead;
173     p_sys->p_rtsp->pf_read_line = RtspReadLine;
174     p_sys->p_rtsp->pf_write = RtspWrite;
175
176     i_result = rtsp_connect( p_sys->p_rtsp, p_access->psz_path, 0 );
177     if( i_result )
178     {
179         msg_Dbg( p_access, "could not connect to: %s", p_access->psz_path );
180         free( p_sys->p_rtsp );
181         p_sys->p_rtsp = 0;
182         goto error;
183     }
184
185     msg_Dbg( p_access, "rtsp connected" );
186
187     /* looking for server type */
188     if( rtsp_search_answers( p_sys->p_rtsp, "Server" ) )
189         psz_server = strdup( rtsp_search_answers( p_sys->p_rtsp, "Server" ) );
190     else
191     {
192         if( rtsp_search_answers( p_sys->p_rtsp, "RealChallenge1" ) )
193             psz_server = strdup("Real");
194         else
195             psz_server = strdup("unknown");
196     }
197
198     if( strstr( psz_server, "Real" ) || strstr( psz_server, "Helix" ) )
199     {
200         uint32_t bandwidth = 10485800;
201         rmff_header_t *h;
202
203         msg_Dbg( p_access, "found a real/helix rtsp server" );
204
205         if( !(h = real_setup_and_get_header( p_sys->p_rtsp, bandwidth )) )
206         {
207             /* Check if we got a redirect */
208             if( rtsp_search_answers( p_sys->p_rtsp, "Location" ) )
209             {
210                 msg_Dbg( p_access, "redirect: %s",
211                          rtsp_search_answers(p_sys->p_rtsp, "Location") );
212                 msg_Warn( p_access, "redirect not supported" );
213                 goto error;
214             }
215
216
217             msg_Err( p_access, "rtsp session can not be established" );
218             goto error;
219         }
220
221         p_sys->p_header = block_New( p_access, 4096 );
222         p_sys->p_header->i_buffer =
223             rmff_dump_header( h, p_sys->p_header->p_buffer, 1024 );
224         rmff_free_header( h );
225     }
226     else
227     {
228         msg_Dbg( p_access, "only real/helix rtsp servers supported for now" );
229         goto error;
230     }
231
232     /* Update default_pts to a suitable value for file access */
233     var_Create( p_access, "realrtsp-caching",
234                 VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
235
236     if( psz_server ) free( psz_server );
237     return VLC_SUCCESS;
238
239  error:
240     if( psz_server ) free( psz_server );
241     Close( p_this );
242     return VLC_EGENERIC;
243 }
244
245 /*****************************************************************************
246  * Close: close the target
247  *****************************************************************************/
248 static void Close( vlc_object_t * p_this )
249 {
250     access_t     *p_access = (access_t*)p_this;
251     access_sys_t *p_sys = p_access->p_sys;
252
253     if( p_sys->p_rtsp ) rtsp_close( p_sys->p_rtsp );
254     if( p_sys->p_rtsp ) free( p_sys->p_rtsp );
255     free( p_sys );
256 }
257
258 /*****************************************************************************
259  * Read: standard read on a file descriptor.
260  *****************************************************************************/
261 static block_t *BlockRead( access_t *p_access )
262 {
263     access_sys_t *p_sys = p_access->p_sys;
264     block_t *p_block;
265     rmff_pheader_t pheader;
266     int i_size;
267
268     if( p_sys->p_header )
269     {
270         p_block = p_sys->p_header;
271         p_sys->p_header = 0;
272         return p_block;
273     }
274
275     i_size = real_get_rdt_chunk_header( p_access->p_sys->p_rtsp, &pheader );
276     if( i_size <= 0 ) return 0;
277
278     p_block = block_New( p_access, i_size );
279     p_block->i_buffer = real_get_rdt_chunk( p_access->p_sys->p_rtsp, &pheader,
280                                             &p_block->p_buffer );
281
282     return p_block;
283 }
284
285 /*****************************************************************************
286  * Seek: seek to a specific location in a file
287  *****************************************************************************/
288 static int Seek( access_t *p_access, int64_t i_pos )
289 {
290     return VLC_SUCCESS;
291 }
292
293 /*****************************************************************************
294  * Control:
295  *****************************************************************************/
296 static int Control( access_t *p_access, int i_query, va_list args )
297 {
298     vlc_bool_t   *pb_bool;
299     int          *pi_int;
300     int64_t      *pi_64;
301
302     switch( i_query )
303     {
304         /* */
305         case ACCESS_CAN_SEEK:
306         case ACCESS_CAN_FASTSEEK:
307             pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t* );
308             *pb_bool = VLC_FALSE;//p_sys->b_seekable;
309             break;
310
311         case ACCESS_CAN_PAUSE:
312             pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t* );
313             *pb_bool = VLC_FALSE;
314             break;
315
316         case ACCESS_CAN_CONTROL_PACE:
317             pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t* );
318             *pb_bool = VLC_TRUE;//p_sys->b_pace_control;
319             break;
320
321         /* */
322         case ACCESS_GET_MTU:
323             pi_int = (int*)va_arg( args, int * );
324             *pi_int = 0;
325             break;
326
327         case ACCESS_GET_PTS_DELAY:
328             pi_64 = (int64_t*)va_arg( args, int64_t * );
329             *pi_64 = var_GetInteger( p_access, "realrtsp-caching" ) * 1000;
330             break;
331
332         /* */
333         case ACCESS_SET_PAUSE_STATE:
334             /* Nothing to do */
335             break;
336
337         case ACCESS_GET_TITLE_INFO:
338         case ACCESS_SET_TITLE:
339         case ACCESS_SET_SEEKPOINT:
340         case ACCESS_SET_PRIVATE_ID_STATE:
341         case ACCESS_GET_META:
342             return VLC_EGENERIC;
343
344         default:
345             msg_Warn( p_access, "unimplemented query in control" );
346             return VLC_EGENERIC;
347     }
348
349     return VLC_SUCCESS;
350 }