]> git.sesse.net Git - vlc/blob - modules/demux/sgimb.c
Fixes malloc's parameter
[vlc] / modules / demux / sgimb.c
1 /*****************************************************************************
2  * sgimb.c: a meta demux to parse sgimb referrer files
3  *****************************************************************************
4  * Copyright (C) 2004 VideoLAN
5  * $Id$
6  *
7  * Authors: Derk-Jan Hartman <hartman at videolan dot 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., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * This is a metademux for the Kasenna MediaBase metafile format.
26  * Kasenna MediaBase first returns this file when you are trying to access
27  * their MPEG streams (MIME: application/x-sgimb). Very few applications
28  * understand this format and the format is not really documented on the net.
29  * Following a typical MediaBase file. Notice the sgi prefix of all the elements.
30  * This stems from the fact that the MediaBase servers were first introduced by SGI?????.
31  *
32  * sgiNameServerHost=host.name.tld
33  * Stream="xdma://host.name.tld/demo/a_very_cool.mpg"
34  * sgiMovieName=/demo/a_very_cool.mpg
35  * sgiAuxState=1
36  * sgiFormatName=PARTNER_41_MPEG-4
37  * sgiBitrate=1630208
38  * sgiDuration=378345000
39  * sgiQTFileBegin
40  * rtsptext
41  * rtsp://host.name.tld/demo/a_very_cool.mpg
42  * sgiQTFileEnd
43  * sgiApplicationName=MediaBaseURL
44  * sgiElapsedTime=0
45  * sgiServerVersion=6.1.2
46  * sgiRtspPort=554
47  * AutoStart=True
48  * sgiUserAccount=pid=1724&time=1078527309&displayText=You%20are%20logged%20as%20guest&
49  * sgiUserPassword=
50  *
51  *****************************************************************************/
52
53
54 /*****************************************************************************
55  * Preamble
56  *****************************************************************************/
57 #include <stdlib.h>                                      /* malloc(), free() */
58
59 #include <vlc/vlc.h>
60 #include <vlc/input.h>
61 #include <vlc_playlist.h>
62
63 /*****************************************************************************
64  * Module descriptor
65  *****************************************************************************/
66 static int  Activate  ( vlc_object_t * );
67 static void Deactivate( vlc_object_t * );
68
69 vlc_module_begin();
70     set_description( _("Kasenna MediaBase metademux") );
71     set_capability( "demux2", 170 );
72     set_callbacks( Activate, Deactivate );
73     add_shortcut( "sgimb" );
74 vlc_module_end();
75
76 /*****************************************************************************
77  * Local prototypes
78  *****************************************************************************/
79 #define MAX_LINE 1024
80
81 struct demux_sys_t
82 {
83     char        *psz_uri;       /* Stream= or sgiQTFileBegin rtsp link */
84     char        *psz_server;    /* sgiNameServerHost= */
85     char        *psz_location;  /* sgiMovieName= */
86     char        *psz_name;      /* sgiShowingName= */
87     char        *psz_user;      /* sgiUserAccount= */
88     char        *psz_password;  /* sgiUserPassword= */
89     char        *psz_mcast_ip;  /* sgiMulticastAddress= */
90     int         i_mcast_port;   /* sgiMulticastPort= */
91     int         i_packet_size;  /* sgiPacketSize= */
92     mtime_t     i_duration;     /* sgiDuration= */
93     int         i_port;         /* sgiRtspPort= */
94     int         i_sid;          /* sgiSid= */
95     vlc_bool_t  b_rtsp_kasenna; /* kasenna style RTSP */
96 };
97
98 static int Demux ( demux_t *p_demux );
99 static int Control( demux_t *p_demux, int i_query, va_list args );
100
101 /*****************************************************************************
102  * Activate: initializes m3u demux structures
103  *****************************************************************************/
104 static int Activate( vlc_object_t * p_this )
105 {
106     demux_t *p_demux = (demux_t *)p_this;
107     demux_sys_t *p_sys;
108     byte_t *p_peek;
109     int i_size;
110
111     /* Lets check the content to see if this is a sgi mediabase file */
112     i_size = stream_Peek( p_demux->s, &p_peek, MAX_LINE );
113     i_size -= sizeof("sgiNameServerHost=") - 1;
114     if ( i_size > 0 )
115     {
116         while ( i_size && strncasecmp( p_peek, "sgiNameServerHost=",
117                                        sizeof("sgiNameServerHost=") - 1 ) )
118         {
119             p_peek++;
120             i_size--;
121         }
122         if ( !strncasecmp( p_peek, "sgiNameServerHost=",
123                            sizeof("sgiNameServerHost=") -1 ) )
124         {
125             p_demux->pf_demux = Demux;
126             p_demux->pf_control = Control;
127
128             p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) );
129             p_sys->psz_uri = NULL;
130             p_sys->psz_server = NULL;
131             p_sys->psz_location = NULL;
132             p_sys->psz_name = NULL;
133             p_sys->psz_user = NULL;
134             p_sys->psz_password = NULL;
135             p_sys->psz_mcast_ip = NULL;
136             p_sys->i_mcast_port = 0;
137             p_sys->i_packet_size = 0;
138             p_sys->i_duration = 0;
139             p_sys->i_port = 0;
140             p_sys->b_rtsp_kasenna = VLC_FALSE;
141
142             return VLC_SUCCESS;
143         }
144     }
145     return VLC_EGENERIC;
146 }
147
148 /*****************************************************************************
149  * Deactivate: frees unused data
150  *****************************************************************************/
151 static void Deactivate( vlc_object_t *p_this )
152 {
153     demux_t *p_demux = (demux_t*)p_this;
154     demux_sys_t *p_sys = p_demux->p_sys;
155     if( p_sys->psz_uri )
156         free( p_sys->psz_uri );
157     if( p_sys->psz_server )
158         free( p_sys->psz_server );
159     if( p_sys->psz_location )
160         free( p_sys->psz_location );
161     if( p_sys->psz_name )
162         free( p_sys->psz_name );
163     if( p_sys->psz_user )
164         free( p_sys->psz_user );
165     if( p_sys->psz_password )
166         free( p_sys->psz_password );
167     if( p_sys->psz_mcast_ip )
168         free( p_sys->psz_mcast_ip );
169     free( p_demux->p_sys );
170     return;
171 }
172
173 static int ParseLine ( demux_t *p_demux, char *psz_line )
174 {
175     char        *psz_bol;
176     demux_sys_t *p_sys = p_demux->p_sys;
177
178     psz_bol = psz_line;
179
180     /* Remove unnecessary tabs or spaces at the beginning of line */
181     while( *psz_bol == ' ' || *psz_bol == '\t' ||
182            *psz_bol == '\n' || *psz_bol == '\r' )
183     {
184         psz_bol++;
185     }
186
187     if( !strncasecmp( psz_bol, "rtsp://", sizeof("rtsp://") - 1 ) )
188     {
189         /* We found the link, it was inside a sgiQTFileBegin */
190         p_sys->psz_uri = strdup( psz_bol );
191     }
192     else if( !strncasecmp( psz_bol, "Stream=\"", sizeof("Stream=\"") - 1 ) )
193     {
194         psz_bol += sizeof("Stream=\"") - 1;
195         if ( !psz_bol )
196             return 0;
197         strrchr( psz_bol, '"' )[0] = '\0';
198         /* We cheat around xdma. for some reason xdma links work different then rtsp */
199         if( !strncasecmp( psz_bol, "xdma://", sizeof("xdma://") - 1 ) )
200         {
201             psz_bol[0] = 'r';
202             psz_bol[1] = 't';
203             psz_bol[2] = 's';
204             psz_bol[3] = 'p';
205         }
206         p_sys->psz_uri = strdup( psz_bol );
207     }
208     else if( !strncasecmp( psz_bol, "sgiNameServerHost=", sizeof("sgiNameServerHost=") - 1 ) )
209     {
210         psz_bol += sizeof("sgiNameServerHost=") - 1;
211         p_sys->psz_server = strdup( psz_bol );
212     }
213     else if( !strncasecmp( psz_bol, "sgiMovieName=", sizeof("sgiMovieName=") - 1 ) )
214     {
215         psz_bol += sizeof("sgiMovieName=") - 1;
216         p_sys->psz_location = strdup( psz_bol );
217     }
218     else if( !strncasecmp( psz_bol, "sgiUserAccount=", sizeof("sgiUserAccount=") - 1 ) )
219     {
220         psz_bol += sizeof("sgiUserAccount=") - 1;
221         p_sys->psz_user = strdup( psz_bol );
222     }
223     else if( !strncasecmp( psz_bol, "sgiUserPassword=", sizeof("sgiUserPassword=") - 1 ) )
224     {
225         psz_bol += sizeof("sgiUserPassword=") - 1;
226         p_sys->psz_password = strdup( psz_bol );
227     }
228     else if( !strncasecmp( psz_bol, "sgiShowingName=", sizeof("sgiShowingName=") - 1 ) )
229     {
230         psz_bol += sizeof("sgiShowingName=") - 1;
231         p_sys->psz_name = strdup( psz_bol );
232     }
233     else if( !strncasecmp( psz_bol, "sgiFormatName=", sizeof("sgiFormatName=") - 1 ) )
234     {
235         psz_bol += sizeof("sgiFormatName=") - 1;
236         if( !strcasestr( psz_bol, "MPEG-4") ) /*not mpeg4 */
237             p_sys->b_rtsp_kasenna = VLC_TRUE;
238     }
239     else if( !strncasecmp( psz_bol, "sgiMulticastAddress=", sizeof("sgiMulticastAddress=") - 1 ) )
240     {
241         psz_bol += sizeof("sgiMulticastAddress=") - 1;
242         p_sys->psz_mcast_ip = strdup( psz_bol );
243     }
244     else if( !strncasecmp( psz_bol, "sgiMulticastPort=", sizeof("sgiMulticastPort=") - 1 ) )
245     {
246         psz_bol += sizeof("sgiMulticastPort=") - 1;
247         p_sys->i_mcast_port = (int) strtol( psz_bol, NULL, 0 );
248     }
249     else if( !strncasecmp( psz_bol, "sgiPacketSize=", sizeof("sgiPacketSize=") - 1 ) )
250     {
251         psz_bol += sizeof("sgiPacketSize=") - 1;
252         p_sys->i_packet_size = (int) strtol( psz_bol, NULL, 0 );
253     }
254     else if( !strncasecmp( psz_bol, "sgiDuration=", sizeof("sgiDuration=") - 1 ) )
255     {
256         psz_bol += sizeof("sgiDuration=") - 1;
257         p_sys->i_duration = (mtime_t) strtol( psz_bol, NULL, 0 );
258     }
259     else if( !strncasecmp( psz_bol, "sgiRtspPort=", sizeof("sgiRtspPort=") - 1 ) )
260     {
261         psz_bol += sizeof("sgiRtspPort=") - 1;
262         p_sys->i_port = (int) strtol( psz_bol, NULL, 0 );
263     }else
264     {
265         /* This line isn't really important */
266         return 0;
267     }
268     return VLC_SUCCESS;
269 }
270
271 /*****************************************************************************
272  * Demux: reads and demuxes data packets
273  *****************************************************************************
274  * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
275  *****************************************************************************/
276 static int Demux ( demux_t *p_demux )
277 {
278     demux_sys_t     *p_sys = p_demux->p_sys;
279     playlist_t      *p_playlist;
280     playlist_item_t *p_item;
281     
282     char            *psz_line;
283     int             i_position;
284
285     p_playlist = (playlist_t *) vlc_object_find( p_demux, VLC_OBJECT_PLAYLIST,
286                                                  FIND_ANYWHERE );
287     if( !p_playlist )
288     {
289         msg_Err( p_demux, "can't find playlist" );
290         return -1;
291     }
292
293     p_playlist->pp_items[p_playlist->i_index]->b_autodeletion = VLC_TRUE;
294     i_position = p_playlist->i_index + 1;
295
296     while( ( psz_line = stream_ReadLine( p_demux->s ) ) )
297     {
298         ParseLine( p_demux, psz_line );
299         if( psz_line ) free( psz_line );
300     }
301
302     if( p_sys->psz_mcast_ip )
303     {
304         char *temp;
305
306         temp = (char *)malloc( sizeof("udp://@000.000.000.000:123456789" ) );
307         sprintf( temp, "udp://@" "%s:%i", p_sys->psz_mcast_ip, p_sys->i_mcast_port );
308         if( p_sys->psz_uri ) free( p_sys->psz_uri );
309         p_sys->psz_uri = strdup( temp );
310         free( temp );
311     }
312     else if( p_sys->psz_uri == NULL )
313     {
314         if( p_sys->psz_server && p_sys->psz_location )
315         {
316             char *temp;
317             
318             temp = (char *)malloc( sizeof("rtsp/live://" ":" "123456789") +
319                                        strlen( p_sys->psz_server ) + strlen( p_sys->psz_location ) );
320             sprintf( temp, "rtsp/live://" "%s:%i%s",
321                      p_sys->psz_server, p_sys->i_port > 0 ? p_sys->i_port : 554, p_sys->psz_location );
322             
323             p_sys->psz_uri = strdup( temp );
324             free( temp );
325         }
326     }
327
328     p_item = playlist_ItemNew( p_playlist, p_sys->psz_uri,
329                       p_sys->psz_name ? p_sys->psz_name : p_sys->psz_uri );
330
331     if( !p_item || !p_item->input.psz_uri )
332     {
333         msg_Err( p_demux, "A valid playlistitem could not be created" );
334         return VLC_EGENERIC;
335     }
336
337     if( p_sys->i_packet_size && p_sys->psz_mcast_ip )
338     {
339         char *psz_option;
340         p_sys->i_packet_size += 1000;
341         asprintf( &psz_option, "mtu=%i", p_sys->i_packet_size );
342         playlist_ItemAddOption( p_item, psz_option );
343         free( psz_option );
344     }
345     if( !p_sys->psz_mcast_ip )
346     {
347         char *psz_option;
348         asprintf( &psz_option, "rtsp-caching=10000" );
349         playlist_ItemAddOption( p_item, psz_option );
350         free( psz_option );
351     }
352     if( !p_sys->psz_mcast_ip && p_sys->b_rtsp_kasenna )
353     {
354         char *psz_option;
355         asprintf( &psz_option, "rtsp-kasenna" );
356         playlist_ItemAddOption( p_item, psz_option );
357         free( psz_option );
358     }
359
360     playlist_ItemSetDuration( p_item, p_sys->i_duration );
361     playlist_AddItem( p_playlist, p_item, PLAYLIST_INSERT, i_position );
362
363     vlc_object_release( p_playlist );
364     return VLC_SUCCESS;
365 }
366
367 static int Control( demux_t *p_demux, int i_query, va_list args )
368 {
369     return VLC_EGENERIC;
370 }
371