]> git.sesse.net Git - vlc/blob - modules/demux/live555.cpp
Revert "live555: Don't put any INT64_C related hack here. We need to fix that properly."
[vlc] / modules / demux / live555.cpp
1 /*****************************************************************************
2  * live555.cpp : LIVE555 Streaming Media support.
3  *****************************************************************************
4  * Copyright (C) 2003-2007 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8  *          Derk-Jan Hartman <hartman at videolan. org>
9  *          Derk-Jan Hartman <djhartman at m2x .dot. nl> for M2X
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
24  *****************************************************************************/
25
26 /*****************************************************************************
27  * Preamble
28  *****************************************************************************/
29
30 #ifdef HAVE_CONFIG_H
31 # include "config.h"
32 #endif
33
34 #define __STDC_CONSTANT_MACROS 1
35 #include <inttypes.h>
36
37 #include <vlc/vlc.h>
38 #include <vlc_plugin.h>
39
40 #include <vlc_demux.h>
41 #include <vlc_interface.h>
42 #include <vlc_network.h>
43 #include <vlc_url.h>
44
45 #include <iostream>
46 #include <limits.h>
47
48
49 #if defined( WIN32 )
50 #   include <winsock2.h>
51 #endif
52
53 #include "UsageEnvironment.hh"
54 #include "BasicUsageEnvironment.hh"
55 #include "GroupsockHelper.hh"
56 #include "liveMedia.hh"
57
58 extern "C" {
59 #include "../access/mms/asf.h"  /* Who said ugly ? */
60 }
61
62 /* XXX Ugly workaround: Buggy Mac OS X headers fail to define them */
63 #ifndef INT64_C
64 # define INT64_C(v)   (v ## LL)
65 #endif
66 #ifndef UINT64_C
67 # define UINT64_C(v)   (v ## ULL)
68 #endif
69
70 using namespace std;
71
72 /*****************************************************************************
73  * Module descriptor
74  *****************************************************************************/
75 static int  Open ( vlc_object_t * );
76 static void Close( vlc_object_t * );
77
78 #define CACHING_TEXT N_("Caching value (ms)")
79 #define CACHING_LONGTEXT N_( \
80     "Allows you to modify the default caching value for RTSP streams. This " \
81     "value should be set in millisecond units." )
82
83 #define KASENNA_TEXT N_( "Kasenna RTSP dialect")
84 #define KASENNA_LONGTEXT N_( "Kasenna servers use an old and unstandard " \
85     "dialect of RTSP. When you set this parameter, VLC will try this dialect "\
86     "for communication. In this mode you cannot connect to normal RTSP servers." )
87
88 #define USER_TEXT N_("RTSP user name")
89 #define USER_LONGTEXT N_("Allows you to modify the user name that will " \
90     "be used for authenticating the connection.")
91 #define PASS_TEXT N_("RTSP password")
92 #define PASS_LONGTEXT N_("Allows you to modify the password that will be " \
93     "used for the connection.")
94
95 vlc_module_begin();
96     set_description( N_("RTP/RTSP/SDP demuxer (using Live555)" ) );
97     set_capability( "demux", 50 );
98     set_shortname( "RTP/RTSP");
99     set_callbacks( Open, Close );
100     add_shortcut( "live" );
101     add_shortcut( "livedotcom" );
102     set_category( CAT_INPUT );
103     set_subcategory( SUBCAT_INPUT_DEMUX );
104
105     add_submodule();
106         set_description( N_("RTSP/RTP access and demux") );
107         add_shortcut( "rtsp" );
108         add_shortcut( "sdp" );
109         set_capability( "access_demux", 0 );
110         set_callbacks( Open, Close );
111         add_bool( "rtsp-tcp", 0, NULL,
112                   N_("Use RTP over RTSP (TCP)"),
113                   N_("Use RTP over RTSP (TCP)"), true );
114         add_integer( "rtp-client-port", -1, NULL,
115                   N_("Client port"),
116                   N_("Port to use for the RTP source of the session"), true );
117         add_bool( "rtsp-http", 0, NULL,
118                   N_("Tunnel RTSP and RTP over HTTP"),
119                   N_("Tunnel RTSP and RTP over HTTP"), true );
120         add_integer( "rtsp-http-port", 80, NULL,
121                   N_("HTTP tunnel port"),
122                   N_("Port to use for tunneling the RTSP/RTP over HTTP."),
123                   true );
124         add_integer("rtsp-caching", 4 * DEFAULT_PTS_DELAY / 1000, NULL,
125                     CACHING_TEXT, CACHING_LONGTEXT, true );
126         add_bool(   "rtsp-kasenna", false, NULL, KASENNA_TEXT,
127                     KASENNA_LONGTEXT, true );
128         add_string( "rtsp-user", NULL, NULL, USER_TEXT,
129                     USER_LONGTEXT, true );
130         add_string( "rtsp-pwd", NULL, NULL, PASS_TEXT,
131                     PASS_LONGTEXT, true );
132 vlc_module_end();
133
134
135 /*****************************************************************************
136  * Local prototypes
137  *****************************************************************************/
138
139 typedef struct
140 {
141     demux_t         *p_demux;
142     MediaSubsession *sub;
143
144     es_format_t     fmt;
145     es_out_id_t     *p_es;
146
147     bool      b_muxed;
148     bool      b_quicktime;
149     bool      b_asf;
150     stream_t        *p_out_muxed;    /* for muxed stream */
151
152     uint8_t         *p_buffer;
153     unsigned int    i_buffer;
154
155     bool      b_rtcp_sync;
156     char            waiting;
157     int64_t         i_pts;
158     u_int32_t       i_start_seq;
159
160 } live_track_t;
161
162 struct timeout_thread_t
163 {
164     VLC_COMMON_MEMBERS
165
166     int64_t      i_remain;
167     bool   b_handle_keep_alive;
168     demux_sys_t  *p_sys;
169 };
170
171 struct demux_sys_t
172 {
173     char            *p_sdp;    /* XXX mallocated */
174     char            *psz_path; /* URL-encoded path */
175     vlc_url_t       url;
176
177     MediaSession     *ms;
178     TaskScheduler    *scheduler;
179     UsageEnvironment *env ;
180     RTSPClient       *rtsp;
181
182     /* */
183     int              i_track;
184     live_track_t     **track;   /* XXX mallocated */
185
186     /* Weird formats */
187     asf_header_t     asfh;
188     stream_t         *p_out_asf;
189     bool       b_real;
190
191     /* */
192     int64_t          i_pcr; /* The clock */
193     int64_t          i_npt; /* The current time in the stream */
194     int64_t          i_npt_length;
195     int64_t          i_npt_start;
196
197     /* timeout thread information */
198     int              i_timeout;     /* session timeout value in seconds */
199     bool       b_timeout_call;/* mark to send an RTSP call to prevent server timeout */
200     timeout_thread_t *p_timeout;    /* the actual thread that makes sure we don't timeout */
201
202     /* */
203     bool       b_multicast;   /* true if one of the tracks is multicasted */
204     bool       b_no_data;     /* true if we never receive any data */
205     int              i_no_data_ti;  /* consecutive number of TaskInterrupt */
206
207     char             event;
208 };
209
210 static int Demux  ( demux_t * );
211 static int Control( demux_t *, int, va_list );
212
213 static int Connect      ( demux_t * );
214 static int SessionsSetup( demux_t * );
215 static int Play         ( demux_t *);
216 static int ParseASF     ( demux_t * );
217 static int RollOverTcp  ( demux_t * );
218
219 static void StreamRead  ( void *, unsigned int, unsigned int,
220                           struct timeval, unsigned int );
221 static void StreamClose ( void * );
222 static void TaskInterrupt( void * );
223
224 static void TimeoutPrevention( timeout_thread_t * );
225
226 static unsigned char* parseH264ConfigStr( char const* configStr,
227                                           unsigned int& configSize );
228
229 /*****************************************************************************
230  * DemuxOpen:
231  *****************************************************************************/
232 static int  Open ( vlc_object_t *p_this )
233 {
234     demux_t     *p_demux = (demux_t*)p_this;
235     demux_sys_t *p_sys = NULL;
236
237     MediaSubsessionIterator *iter   = NULL;
238     MediaSubsession         *sub    = NULL;
239     int i, i_return;
240     int i_error = VLC_EGENERIC;
241
242     if( p_demux->s )
243     {
244         /* See if it looks like a SDP
245            v, o, s fields are mandatory and in this order */
246         const uint8_t *p_peek;
247         if( stream_Peek( p_demux->s, &p_peek, 7 ) < 7 ) return VLC_EGENERIC;
248
249         if( memcmp( p_peek, "v=0\r\n", 5 ) &&
250             memcmp( p_peek, "v=0\n", 4 ) &&
251             ( p_peek[0] < 'a' || p_peek[0] > 'z' || p_peek[1] != '=' ) )
252         {
253             return VLC_EGENERIC;
254         }
255     }
256     else
257     {
258         var_Create( p_demux, "rtsp-caching", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
259     }
260
261     p_demux->pf_demux  = Demux;
262     p_demux->pf_control= Control;
263     p_demux->p_sys     = p_sys = (demux_sys_t*)malloc( sizeof( demux_sys_t ) );
264     if( !p_sys ) return VLC_ENOMEM;
265
266     p_sys->p_sdp = NULL;
267     p_sys->scheduler = NULL;
268     p_sys->env = NULL;
269     p_sys->ms = NULL;
270     p_sys->rtsp = NULL;
271     p_sys->i_track = 0;
272     p_sys->track   = NULL;
273     p_sys->i_pcr = 0;
274     p_sys->i_npt = 0;
275     p_sys->i_npt_start = 0;
276     p_sys->i_npt_length = 0;
277     p_sys->p_out_asf = NULL;
278     p_sys->b_no_data = true;
279     p_sys->i_no_data_ti = 0;
280     p_sys->p_timeout = NULL;
281     p_sys->i_timeout = 0;
282     p_sys->b_timeout_call = false;
283     p_sys->b_multicast = false;
284     p_sys->b_real = false;
285     p_sys->psz_path = strdup( p_demux->psz_path );
286
287     /* parse URL for rtsp://[user:[passwd]@]serverip:port/options */
288     vlc_UrlParse( &p_sys->url, p_sys->psz_path, 0 );
289
290     if( ( p_sys->scheduler = BasicTaskScheduler::createNew() ) == NULL )
291     {
292         msg_Err( p_demux, "BasicTaskScheduler::createNew failed" );
293         goto error;
294     }
295     if( !( p_sys->env = BasicUsageEnvironment::createNew(*p_sys->scheduler) ) )
296     {
297         msg_Err( p_demux, "BasicUsageEnvironment::createNew failed" );
298         goto error;
299     }
300
301     if( strcasecmp( p_demux->psz_access, "sdp" ) )
302     {
303         char *p = p_sys->psz_path;
304         while( (p = strchr( p, ' ' )) != NULL ) *p = '+';
305     }
306
307     if( p_demux->s != NULL )
308     {
309         /* Gather the complete sdp file */
310         int     i_sdp       = 0;
311         int     i_sdp_max   = 1000;
312         uint8_t *p_sdp      = (uint8_t*) malloc( i_sdp_max );
313
314         if( !p_sdp )
315         {
316             i_error = VLC_ENOMEM;
317             goto error;
318         }
319
320         for( ;; )
321         {
322             int i_read = stream_Read( p_demux->s, &p_sdp[i_sdp],
323                                       i_sdp_max - i_sdp - 1 );
324
325             if( p_demux->b_die || p_demux->b_error )
326             {
327                 free( p_sdp );
328                 goto error;
329             }
330
331             if( i_read < 0 )
332             {
333                 msg_Err( p_demux, "failed to read SDP" );
334                 free( p_sdp );
335                 goto error;
336             }
337
338             i_sdp += i_read;
339
340             if( i_read < i_sdp_max - i_sdp - 1 )
341             {
342                 p_sdp[i_sdp] = '\0';
343                 break;
344             }
345
346             i_sdp_max += 1000;
347             p_sdp = (uint8_t*)realloc( p_sdp, i_sdp_max );
348         }
349         p_sys->p_sdp = (char*)p_sdp;
350     }
351     else if( ( p_demux->s == NULL ) &&
352              !strcasecmp( p_demux->psz_access, "sdp" ) )
353     {
354         /* sdp:// link from SAP */
355         p_sys->p_sdp = strdup( p_sys->psz_path );
356     }
357     else if( ( i_return = Connect( p_demux ) ) != VLC_SUCCESS )
358     {
359         msg_Err( p_demux, "Failed to connect with rtsp://%s", p_sys->psz_path );
360         goto error;
361     }
362
363     if( p_sys->p_sdp == NULL )
364     {
365         msg_Err( p_demux, "Failed to retrieve the RTSP Session Description" );
366         i_error = VLC_ENOMEM;
367         goto error;
368     }
369
370     if( ( i_return = SessionsSetup( p_demux ) ) != VLC_SUCCESS )
371     {
372         msg_Err( p_demux, "Nothing to play for rtsp://%s", p_sys->psz_path );
373         goto error;
374     }
375
376     if( p_sys->b_real ) goto error;
377
378     if( ( i_return = Play( p_demux ) ) != VLC_SUCCESS )
379         goto error;
380
381     if( p_sys->p_out_asf && ParseASF( p_demux ) )
382     {
383         msg_Err( p_demux, "cannot find a usable asf header" );
384         /* TODO Clean tracks */
385         goto error;
386     }
387
388     if( p_sys->i_track <= 0 )
389         goto error;
390
391     return VLC_SUCCESS;
392
393 error:
394     for( i = 0; i < p_sys->i_track; i++ )
395     {
396         live_track_t *tk = p_sys->track[i];
397
398         if( tk->b_muxed ) stream_DemuxDelete( tk->p_out_muxed );
399         es_format_Clean( &tk->fmt );
400         free( tk->p_buffer );
401         free( tk );
402     }
403
404     if( p_sys->i_track ) free( p_sys->track );
405     if( p_sys->p_out_asf ) stream_DemuxDelete( p_sys->p_out_asf );
406     if( p_sys->rtsp && p_sys->ms ) p_sys->rtsp->teardownMediaSession( *p_sys->ms );
407     if( p_sys->ms ) Medium::close( p_sys->ms );
408     if( p_sys->rtsp ) RTSPClient::close( p_sys->rtsp );
409     if( p_sys->env ) p_sys->env->reclaim();
410     if( p_sys->p_timeout )
411     {
412         vlc_object_kill( p_sys->p_timeout );
413         vlc_thread_join( p_sys->p_timeout );
414         vlc_object_detach( p_sys->p_timeout );
415         vlc_object_release( p_sys->p_timeout );
416     }
417     delete p_sys->scheduler;
418     free( p_sys->p_sdp );
419     free( p_sys->psz_path );
420
421     vlc_UrlClean( &p_sys->url );
422
423     free( p_sys );
424     return i_error;
425 }
426
427 /*****************************************************************************
428  * DemuxClose:
429  *****************************************************************************/
430 static void Close( vlc_object_t *p_this )
431 {
432     demux_t *p_demux = (demux_t*)p_this;
433     demux_sys_t *p_sys = p_demux->p_sys;
434     int i;
435
436     for( i = 0; i < p_sys->i_track; i++ )
437     {
438         live_track_t *tk = p_sys->track[i];
439
440         if( tk->b_muxed ) stream_DemuxDelete( tk->p_out_muxed );
441         es_format_Clean( &tk->fmt );
442         free( tk->p_buffer );
443         free( tk );
444     }
445
446     if( p_sys->i_track ) free( p_sys->track );
447     if( p_sys->p_out_asf ) stream_DemuxDelete( p_sys->p_out_asf );
448     if( p_sys->rtsp && p_sys->ms ) p_sys->rtsp->teardownMediaSession( *p_sys->ms );
449     if( p_sys->ms ) Medium::close( p_sys->ms );
450     if( p_sys->rtsp ) RTSPClient::close( p_sys->rtsp );
451     if( p_sys->env ) p_sys->env->reclaim();
452     if( p_sys->p_timeout )
453     {
454         vlc_object_kill( p_sys->p_timeout );
455         vlc_thread_join( p_sys->p_timeout );
456         vlc_object_detach( p_sys->p_timeout );
457         vlc_object_release( p_sys->p_timeout );
458     }
459     delete p_sys->scheduler;
460     free( p_sys->p_sdp );
461     free( p_sys->psz_path );
462
463     vlc_UrlClean( &p_sys->url );
464
465     free( p_sys );
466 }
467
468 /*****************************************************************************
469  * Connect: connects to the RTSP server to setup the session DESCRIBE
470  *****************************************************************************/
471 static int Connect( demux_t *p_demux )
472 {
473     demux_sys_t *p_sys = p_demux->p_sys;
474     Authenticator authenticator;
475     bool b_firstpass  = true;
476     char *psz_user    = NULL;
477     char *psz_pwd     = NULL;
478     char *psz_url     = NULL;
479     char *psz_options = NULL;
480     char *p_sdp       = NULL;
481     int  i_http_port  = 0;
482     int  i_ret        = VLC_SUCCESS;
483     int i_lefttries;
484
485     if( p_sys->url.i_port == 0 ) p_sys->url.i_port = 554;
486     if( p_sys->url.psz_username || p_sys->url.psz_password )
487     {
488         int err;
489         err = asprintf( &psz_url, "rtsp://%s:%d%s", p_sys->url.psz_host,
490                         p_sys->url.i_port, p_sys->url.psz_path );
491         if( err == -1 ) return VLC_ENOMEM;
492
493         psz_user = strdup( p_sys->url.psz_username );
494         psz_pwd  = strdup( p_sys->url.psz_password );
495     }
496     else
497     {
498         int err;
499         err = asprintf( &psz_url, "rtsp://%s", p_sys->psz_path );
500         if( err == -1 ) return VLC_ENOMEM;
501
502         psz_user = var_CreateGetString( p_demux, "rtsp-user" );
503         psz_pwd  = var_CreateGetString( p_demux, "rtsp-pwd" );
504     }
505
506     i_lefttries = 3;
507 createnew:
508     i_lefttries--;
509     if( p_demux->b_die || p_demux->b_error )
510     {
511         free( psz_user );
512         free( psz_pwd );
513         free( psz_url );
514         return VLC_EGENERIC;
515     }
516
517     if( var_CreateGetBool( p_demux, "rtsp-http" ) )
518         i_http_port = var_CreateGetInteger( p_demux, "rtsp-http-port" );
519
520     if( ( p_sys->rtsp = RTSPClient::createNew( *p_sys->env,
521           var_CreateGetInteger( p_demux, "verbose" ) > 1,
522           "VLC media player", i_http_port ) ) == NULL )
523     {
524         msg_Err( p_demux, "RTSPClient::createNew failed (%s)",
525                  p_sys->env->getResultMsg() );
526         free( psz_user );
527         free( psz_pwd );
528         free( psz_url );
529         return VLC_EGENERIC;
530     }
531
532     /* Kasenna enables KeepAlive by analysing the User-Agent string. 
533      * Appending _KA to the string should be enough to enable this feature, 
534      * however, there is a bug where the _KA doesn't get parsed from the 
535      * default User-Agent as created by VLC/Live555 code. This is probably due 
536      * to spaces in the string or the string being too long. Here we override
537      * the default string with a more compact version.
538      */
539     if( var_CreateGetBool( p_demux, "rtsp-kasenna" ))
540     {
541 #if LIVEMEDIA_LIBRARY_VERSION_INT > 1130457500
542         p_sys->rtsp->setUserAgentString( "VLC_MEDIA_PLAYER_KA" );
543 #endif
544     }
545
546 describe:
547     authenticator.setUsernameAndPassword( (const char*)psz_user,
548                                           (const char*)psz_pwd );
549
550     psz_options = p_sys->rtsp->sendOptionsCmd( psz_url, psz_user, psz_pwd,
551                                                &authenticator );
552     delete [] psz_options;
553
554     p_sdp = p_sys->rtsp->describeURL( psz_url, &authenticator,
555                          var_GetBool( p_demux, "rtsp-kasenna" ) );
556     if( p_sdp == NULL )
557     {
558         /* failure occurred */
559         int i_code = 0;
560         const char *psz_error = p_sys->env->getResultMsg();
561
562         if( var_GetBool( p_demux, "rtsp-http" ) )
563             sscanf( psz_error, "%*s %*s HTTP GET %*s HTTP/%*u.%*u %3u %*s",
564                     &i_code );
565         else
566         {
567             const char *psz_tmp = strstr( psz_error, "RTSP" );
568             if( psz_tmp )
569                 sscanf( psz_tmp, "RTSP/%*s%3u", &i_code );
570             else
571                 i_code = 0;
572         }
573         msg_Dbg( p_demux, "DESCRIBE failed with %d: %s", i_code, psz_error );
574
575         if( b_firstpass )
576         {   /* describeURL always returns an "RTSP/1.0 401 Unauthorized" the
577              * first time. This is a workaround to avoid asking for a
578              * user/passwd the first time the code passess here. */
579             i_code = 0;
580             b_firstpass = false;
581         }
582
583         if( i_code == 401 )
584         {
585             int i_result;
586             msg_Dbg( p_demux, "authentication failed" );
587
588             free( psz_user );
589             free( psz_pwd );
590             psz_user = psz_pwd = NULL;
591
592             i_result = intf_UserLoginPassword( p_demux, _("RTSP authentication"),
593                            _("Please enter a valid login name and a password."),
594                                                    &psz_user, &psz_pwd );
595             if( i_result == DIALOG_OK_YES )
596             {
597                 msg_Dbg( p_demux, "retrying with user=%s, pwd=%s",
598                          psz_user, psz_pwd );
599                 goto describe;
600             }
601         }
602         else if( (i_code != 0) && !var_GetBool( p_demux, "rtsp-http" ) )
603         {
604             /* Perhaps a firewall is being annoying. Try HTTP tunneling mode */
605             vlc_value_t val;
606             val.b_bool = true;
607             msg_Dbg( p_demux, "we will now try HTTP tunneling mode" );
608             var_Set( p_demux, "rtsp-http", val );
609             if( p_sys->rtsp ) RTSPClient::close( p_sys->rtsp );
610             p_sys->rtsp = NULL;
611             goto createnew;
612         }
613         else
614         {
615             msg_Dbg( p_demux, "connection timeout, retrying" );
616             if( p_sys->rtsp ) RTSPClient::close( p_sys->rtsp );
617             p_sys->rtsp = NULL;
618             if( i_lefttries > 0 )
619                 goto createnew;
620         }
621         i_ret = VLC_EGENERIC;
622     }
623
624     /* malloc-ated copy */
625     free( psz_url );
626     free( psz_user );
627     free( psz_pwd );
628
629     free( p_sys->p_sdp );
630     p_sys->p_sdp = NULL;
631     if( p_sdp ) p_sys->p_sdp = strdup( (char*)p_sdp );
632     delete[] p_sdp;
633
634     return i_ret;
635 }
636
637 /*****************************************************************************
638  * SessionsSetup: prepares the subsessions and does the SETUP
639  *****************************************************************************/
640 static int SessionsSetup( demux_t *p_demux )
641 {
642     demux_sys_t             *p_sys  = p_demux->p_sys;
643     MediaSubsessionIterator *iter   = NULL;
644     MediaSubsession         *sub    = NULL;
645
646     bool     b_rtsp_tcp = false;
647     int            i_client_port;
648     int            i_return = VLC_SUCCESS;
649     unsigned int   i_buffer = 0;
650     unsigned const thresh = 200000; /* RTP reorder threshold .2 second (default .1) */
651
652     b_rtsp_tcp    = var_CreateGetBool( p_demux, "rtsp-tcp" ) ||
653                     var_GetBool( p_demux, "rtsp-http" );
654     i_client_port = var_CreateGetInteger( p_demux, "rtp-client-port" );
655
656     /* Create the session from the SDP */
657     if( !( p_sys->ms = MediaSession::createNew( *p_sys->env, p_sys->p_sdp ) ) )
658     {
659         msg_Err( p_demux, "Could not create the RTSP Session: %s",
660             p_sys->env->getResultMsg() );
661         return VLC_EGENERIC;
662     }
663
664     /* Initialise each media subsession */
665     iter = new MediaSubsessionIterator( *p_sys->ms );
666     while( ( sub = iter->next() ) != NULL )
667     {
668         Boolean bInit;
669         live_track_t *tk;
670
671         if( p_demux->b_die || p_demux->b_error )
672         {
673             delete iter;
674             return VLC_EGENERIC;
675         }
676
677         /* Value taken from mplayer */
678         if( !strcmp( sub->mediumName(), "audio" ) )
679             i_buffer = 100000;
680         else if( !strcmp( sub->mediumName(), "video" ) )
681             i_buffer = 2000000;
682         else continue;
683
684         if( i_client_port != -1 )
685         {
686             sub->setClientPortNum( i_client_port );
687             i_client_port += 2;
688         }
689
690         if( strcasestr( sub->codecName(), "REAL" ) )
691         {
692             msg_Info( p_demux, "real codec detected, using real-RTSP instead" );
693             p_sys->b_real = true; /* This is a problem, we'll handle it later */
694             continue;
695         }
696
697         if( !strcmp( sub->codecName(), "X-ASF-PF" ) )
698             bInit = sub->initiate( 4 ); /* Constant ? */
699         else
700             bInit = sub->initiate();
701
702         if( !bInit )
703         {
704             msg_Warn( p_demux, "RTP subsession '%s/%s' failed (%s)",
705                       sub->mediumName(), sub->codecName(),
706                       p_sys->env->getResultMsg() );
707         }
708         else
709         {
710             if( sub->rtpSource() != NULL )
711             {
712                 int fd = sub->rtpSource()->RTPgs()->socketNum();
713
714                 /* Increase the buffer size */
715                 if( i_buffer > 0 )
716                     increaseReceiveBufferTo( *p_sys->env, fd, i_buffer );
717
718                 /* Increase the RTP reorder timebuffer just a bit */
719                 sub->rtpSource()->setPacketReorderingThresholdTime(thresh);
720             }
721             msg_Dbg( p_demux, "RTP subsession '%s/%s'", sub->mediumName(),
722                      sub->codecName() );
723
724             /* Issue the SETUP */
725             if( p_sys->rtsp )
726             {
727                 if( !( p_sys->rtsp->setupMediaSubsession( *sub, False,
728                                                    b_rtsp_tcp ? True : False ) ) )
729                 {
730                     /* if we get an unsupported transport error, toggle TCP use and try again */
731                     if( !strstr(p_sys->env->getResultMsg(), "461 Unsupported Transport")
732                      || !( p_sys->rtsp->setupMediaSubsession( *sub, False,
733                                                    b_rtsp_tcp ? False : True ) ) )
734                     {
735                         msg_Err( p_demux, "SETUP of'%s/%s' failed %s", sub->mediumName(),
736                                  sub->codecName(), p_sys->env->getResultMsg() );
737                         continue;
738                     }
739                 }
740             }
741
742             /* Check if we will receive data from this subsession for this track */
743             if( sub->readSource() == NULL ) continue;
744             if( !p_sys->b_multicast )
745             {
746                 /* Check, because we need diff. rollover behaviour for multicast */
747                 p_sys->b_multicast = IsMulticastAddress( sub->connectionEndpointAddress() );
748             }
749
750             tk = (live_track_t*)malloc( sizeof( live_track_t ) );
751             if( !tk )
752             {
753                 delete iter;
754                 return VLC_ENOMEM;
755             }
756             tk->p_demux     = p_demux;
757             tk->sub         = sub;
758             tk->p_es        = NULL;
759             tk->b_quicktime = false;
760             tk->b_asf       = false;
761             tk->b_muxed     = false;
762             tk->p_out_muxed = NULL;
763             tk->waiting     = 0;
764             tk->b_rtcp_sync = false;
765             tk->i_pts       = 0;
766             tk->i_buffer    = 65536;
767             tk->p_buffer    = (uint8_t *)malloc( 65536 );
768             if( !tk->p_buffer )
769             {
770                 delete iter;
771                 return VLC_ENOMEM;
772             }
773
774             /* Value taken from mplayer */
775             if( !strcmp( sub->mediumName(), "audio" ) )
776             {
777                 es_format_Init( &tk->fmt, AUDIO_ES, VLC_FOURCC('u','n','d','f') );
778                 tk->fmt.audio.i_channels = sub->numChannels();
779                 tk->fmt.audio.i_rate = sub->rtpTimestampFrequency();
780
781                 if( !strcmp( sub->codecName(), "MPA" ) ||
782                     !strcmp( sub->codecName(), "MPA-ROBUST" ) ||
783                     !strcmp( sub->codecName(), "X-MP3-DRAFT-00" ) )
784                 {
785                     tk->fmt.i_codec = VLC_FOURCC( 'm', 'p', 'g', 'a' );
786                     tk->fmt.audio.i_rate = 0;
787                 }
788                 else if( !strcmp( sub->codecName(), "AC3" ) )
789                 {
790                     tk->fmt.i_codec = VLC_FOURCC( 'a', '5', '2', ' ' );
791                     tk->fmt.audio.i_rate = 0;
792                 }
793                 else if( !strcmp( sub->codecName(), "L16" ) )
794                 {
795                     tk->fmt.i_codec = VLC_FOURCC( 't', 'w', 'o', 's' );
796                     tk->fmt.audio.i_bitspersample = 16;
797                 }
798                 else if( !strcmp( sub->codecName(), "L8" ) )
799                 {
800                     tk->fmt.i_codec = VLC_FOURCC( 'a', 'r', 'a', 'w' );
801                     tk->fmt.audio.i_bitspersample = 8;
802                 }
803                 else if( !strcmp( sub->codecName(), "PCMU" ) )
804                 {
805                     tk->fmt.i_codec = VLC_FOURCC( 'u', 'l', 'a', 'w' );
806                 }
807                 else if( !strcmp( sub->codecName(), "PCMA" ) )
808                 {
809                     tk->fmt.i_codec = VLC_FOURCC( 'a', 'l', 'a', 'w' );
810                 }
811                 else if( !strncmp( sub->codecName(), "G726", 4 ) )
812                 {
813                     tk->fmt.i_codec = VLC_FOURCC( 'g', '7', '2', '6' );
814                     tk->fmt.audio.i_rate = 8000;
815                     tk->fmt.audio.i_channels = 1;
816                     if( !strcmp( sub->codecName()+5, "40" ) )
817                         tk->fmt.i_bitrate = 40000;
818                     else if( !strcmp( sub->codecName()+5, "32" ) )
819                         tk->fmt.i_bitrate = 32000;
820                     else if( !strcmp( sub->codecName()+5, "24" ) )
821                         tk->fmt.i_bitrate = 24000;
822                     else if( !strcmp( sub->codecName()+5, "16" ) )
823                         tk->fmt.i_bitrate = 16000;
824                 }
825                 else if( !strcmp( sub->codecName(), "AMR" ) )
826                 {
827                     tk->fmt.i_codec = VLC_FOURCC( 's', 'a', 'm', 'r' );
828                 }
829                 else if( !strcmp( sub->codecName(), "AMR-WB" ) )
830                 {
831                     tk->fmt.i_codec = VLC_FOURCC( 's', 'a', 'w', 'b' );
832                 }
833                 else if( !strcmp( sub->codecName(), "MP4A-LATM" ) )
834                 {
835                     unsigned int i_extra;
836                     uint8_t      *p_extra;
837
838                     tk->fmt.i_codec = VLC_FOURCC( 'm', 'p', '4', 'a' );
839
840                     if( ( p_extra = parseStreamMuxConfigStr( sub->fmtp_config(),
841                                                              i_extra ) ) )
842                     {
843                         tk->fmt.i_extra = i_extra;
844                         tk->fmt.p_extra = malloc( i_extra );
845                         memcpy( tk->fmt.p_extra, p_extra, i_extra );
846                         delete[] p_extra;
847                     }
848                     /* Because the "faad" decoder does not handle the LATM data length field
849                        at the start of each returned LATM frame, tell the RTP source to omit it. */
850                     ((MPEG4LATMAudioRTPSource*)sub->rtpSource())->omitLATMDataLengthField();
851                 }
852                 else if( !strcmp( sub->codecName(), "MPEG4-GENERIC" ) )
853                 {
854                     unsigned int i_extra;
855                     uint8_t      *p_extra;
856
857                     tk->fmt.i_codec = VLC_FOURCC( 'm', 'p', '4', 'a' );
858
859                     if( ( p_extra = parseGeneralConfigStr( sub->fmtp_config(),
860                                                            i_extra ) ) )
861                     {
862                         tk->fmt.i_extra = i_extra;
863                         tk->fmt.p_extra = malloc( i_extra );
864                         memcpy( tk->fmt.p_extra, p_extra, i_extra );
865                         delete[] p_extra;
866                     }
867                 }
868                 else if( !strcmp( sub->codecName(), "X-ASF-PF" ) )
869                 {
870                     tk->b_asf = true;
871                     if( p_sys->p_out_asf == NULL )
872                         p_sys->p_out_asf = stream_DemuxNew( p_demux, "asf",
873                                                             p_demux->out );
874                 }
875                 else if( !strcmp( sub->codecName(), "X-QT" ) ||
876                          !strcmp( sub->codecName(), "X-QUICKTIME" ) )
877                 {
878                     tk->b_quicktime = true;
879                 }
880                 else if( !strcmp( sub->codecName(), "SPEEX" ) )
881                 {
882                     tk->fmt.i_codec = VLC_FOURCC( 's', 'p', 'x', 'r' );
883                     if ( sub->rtpTimestampFrequency() )
884                         tk->fmt.audio.i_rate = sub->rtpTimestampFrequency();
885                     else
886                     {
887                         msg_Warn( p_demux,"Using 8kHz as default sample rate." );
888                         tk->fmt.audio.i_rate = 8000;
889                     }
890                 }
891             }
892             else if( !strcmp( sub->mediumName(), "video" ) )
893             {
894                 es_format_Init( &tk->fmt, VIDEO_ES, VLC_FOURCC('u','n','d','f') );
895                 if( !strcmp( sub->codecName(), "MPV" ) )
896                 {
897                     tk->fmt.i_codec = VLC_FOURCC( 'm', 'p', 'g', 'v' );
898                 }
899                 else if( !strcmp( sub->codecName(), "H263" ) ||
900                          !strcmp( sub->codecName(), "H263-1998" ) ||
901                          !strcmp( sub->codecName(), "H263-2000" ) )
902                 {
903                     tk->fmt.i_codec = VLC_FOURCC( 'H', '2', '6', '3' );
904                 }
905                 else if( !strcmp( sub->codecName(), "H261" ) )
906                 {
907                     tk->fmt.i_codec = VLC_FOURCC( 'H', '2', '6', '1' );
908                 }
909                 else if( !strcmp( sub->codecName(), "H264" ) )
910                 {
911                     unsigned int i_extra = 0;
912                     uint8_t      *p_extra = NULL;
913
914                     tk->fmt.i_codec = VLC_FOURCC( 'h', '2', '6', '4' );
915                     tk->fmt.b_packetized = false;
916
917                     if((p_extra=parseH264ConfigStr( sub->fmtp_spropparametersets(),
918                                                     i_extra ) ) )
919                     {
920                         tk->fmt.i_extra = i_extra;
921                         tk->fmt.p_extra = malloc( i_extra );
922                         memcpy( tk->fmt.p_extra, p_extra, i_extra );
923
924                         delete[] p_extra;
925                     }
926                 }
927                 else if( !strcmp( sub->codecName(), "JPEG" ) )
928                 {
929                     tk->fmt.i_codec = VLC_FOURCC( 'M', 'J', 'P', 'G' );
930                 }
931                 else if( !strcmp( sub->codecName(), "MP4V-ES" ) )
932                 {
933                     unsigned int i_extra;
934                     uint8_t      *p_extra;
935
936                     tk->fmt.i_codec = VLC_FOURCC( 'm', 'p', '4', 'v' );
937
938                     if( ( p_extra = parseGeneralConfigStr( sub->fmtp_config(),
939                                                            i_extra ) ) )
940                     {
941                         tk->fmt.i_extra = i_extra;
942                         tk->fmt.p_extra = malloc( i_extra );
943                         memcpy( tk->fmt.p_extra, p_extra, i_extra );
944                         delete[] p_extra;
945                     }
946                 }
947                 else if( !strcmp( sub->codecName(), "X-QT" ) ||
948                          !strcmp( sub->codecName(), "X-QUICKTIME" ) ||
949                          !strcmp( sub->codecName(), "X-QDM" ) ||
950                          !strcmp( sub->codecName(), "X-SV3V-ES" )  ||
951                          !strcmp( sub->codecName(), "X-SORENSONVIDEO" ) )
952                 {
953                     tk->b_quicktime = true;
954                 }
955                 else if( !strcmp( sub->codecName(), "MP2T" ) )
956                 {
957                     tk->b_muxed = true;
958                     tk->p_out_muxed = stream_DemuxNew( p_demux, "ts", p_demux->out );
959                 }
960                 else if( !strcmp( sub->codecName(), "MP2P" ) ||
961                          !strcmp( sub->codecName(), "MP1S" ) )
962                 {
963                     tk->b_muxed = true;
964                     tk->p_out_muxed = stream_DemuxNew( p_demux, "ps",
965                                                        p_demux->out );
966                 }
967                 else if( !strcmp( sub->codecName(), "X-ASF-PF" ) )
968                 {
969                     tk->b_asf = true;
970                     if( p_sys->p_out_asf == NULL )
971                         p_sys->p_out_asf = stream_DemuxNew( p_demux, "asf",
972                                                             p_demux->out );;
973                 }
974             }
975
976             if( !tk->b_quicktime && !tk->b_muxed && !tk->b_asf )
977             {
978                 tk->p_es = es_out_Add( p_demux->out, &tk->fmt );
979             }
980
981             if( sub->rtcpInstance() != NULL )
982             {
983                 sub->rtcpInstance()->setByeHandler( StreamClose, tk );
984             }
985
986             if( tk->p_es || tk->b_quicktime || tk->b_muxed || tk->b_asf )
987             {
988                 /* Append */
989                 p_sys->track = (live_track_t**)realloc( p_sys->track, sizeof( live_track_t ) * ( p_sys->i_track + 1 ) );
990                 p_sys->track[p_sys->i_track++] = tk;
991             }
992             else
993             {
994                 /* BUG ??? */
995                 msg_Err( p_demux, "unusable RTSP track. this should not happen" );
996                 es_format_Clean( &tk->fmt );
997                 free( tk );
998             }
999         }
1000     }
1001     delete iter;
1002     if( p_sys->i_track <= 0 ) i_return = VLC_EGENERIC;
1003
1004 #if (LIVEMEDIA_LIBRARY_VERSION_INT >= 1199404800)
1005     /* Retrieve the starttime if possible */
1006     p_sys->i_npt_start = (int64_t)( p_sys->ms->playStartTime() * (double)1000000.0 );
1007 #else
1008     p_sys->i_npt_start = (int64_t) -1;
1009 #endif
1010     if( p_sys->i_npt_start < 0 )
1011         p_sys->i_npt_start = -1;
1012
1013 #if (LIVEMEDIA_LIBRARY_VERSION_INT >= 1199404800)
1014     /* Retrieve the duration if possible */
1015     p_sys->i_npt_length = (int64_t)( p_sys->ms->playEndTime() * (double)1000000.0 );
1016 #else
1017     p_sys->i_npt_length = (int64_t) -1;
1018 #endif
1019     if( p_sys->i_npt_length < 0 )
1020         p_sys->i_npt_length = -1;
1021
1022     msg_Dbg( p_demux, "setup start: %lld stop:%lld", p_sys->i_npt_start, p_sys->i_npt_length );
1023     return i_return;
1024 }
1025
1026 /*****************************************************************************
1027  * Play: starts the actual playback of the stream
1028  *****************************************************************************/
1029 static int Play( demux_t *p_demux )
1030 {
1031     demux_sys_t *p_sys = p_demux->p_sys;
1032     int i;
1033
1034     if( p_sys->rtsp )
1035     {
1036         /* The PLAY */
1037         if( !p_sys->rtsp->playMediaSession( *p_sys->ms, p_sys->i_npt_start, -1, 1 ) )
1038         {
1039             msg_Err( p_demux, "RTSP PLAY failed %s", p_sys->env->getResultMsg() );
1040             return VLC_EGENERIC;
1041         }
1042
1043         /* Retrieve the timeout value and set up a timeout prevention thread */
1044         p_sys->i_timeout = p_sys->rtsp->sessionTimeoutParameter();
1045         if( p_sys->i_timeout <= 0 )
1046             p_sys->i_timeout = 60; /* default value from RFC2326 */
1047
1048         /* start timeout-thread only on x-asf streams (wms), it has rtcp support but doesn't 
1049          * seem to use it for liveness/keep-alive, get_parameter seems to work for it. get_parameter
1050          * doesn't work with dss 5.5.4 & 5.5.5, they seems to work with rtcp */
1051         if( !p_sys->p_timeout && p_sys->p_out_asf )
1052         {
1053             msg_Dbg( p_demux, "We have a timeout of %d seconds",  p_sys->i_timeout );
1054             p_sys->p_timeout = (timeout_thread_t *)vlc_object_create( p_demux, sizeof(timeout_thread_t) );
1055             p_sys->p_timeout->p_sys = p_demux->p_sys; /* lol, object recursion :D */
1056             if( vlc_thread_create( p_sys->p_timeout, "liveMedia-timeout", TimeoutPrevention,
1057                                    VLC_THREAD_PRIORITY_LOW, true ) )
1058             {
1059                 msg_Err( p_demux, "cannot spawn liveMedia timeout thread" );
1060                 vlc_object_release( p_sys->p_timeout );
1061             }
1062             msg_Dbg( p_demux, "spawned timeout thread" );
1063             vlc_object_attach( p_sys->p_timeout, p_demux );
1064         }
1065     }
1066     p_sys->i_pcr = 0;
1067
1068 #if (LIVEMEDIA_LIBRARY_VERSION_INT >= 1195257600)
1069     for( i = 0; i < p_sys->i_track; i++ )
1070     {
1071         if( !p_sys->track[i]->b_rtcp_sync )
1072             p_sys->track[i]->i_pts = (int64_t) ( p_sys->track[i]->sub->rtpInfo.timestamp * (double)1000000.0 );
1073         p_sys->track[i]->i_start_seq = (int)p_sys->track[i]->sub->rtpInfo.seqNum;
1074         msg_Info( p_demux, "set startseq: %u", p_sys->track[i]->i_start_seq );
1075     }
1076 #endif
1077
1078 #if (LIVEMEDIA_LIBRARY_VERSION_INT >= 1199404800)
1079     /* Retrieve the starttime if possible */
1080     p_sys->i_npt_start = (int64_t)( p_sys->ms->playStartTime() * (double)1000000.0 );
1081 #else
1082     p_sys->i_npt_start = -1;
1083 #endif
1084     if( p_sys->i_npt_start < 0 )
1085     {
1086         p_sys->i_npt_start = -1;
1087         p_sys->i_npt = 0;
1088     }
1089     else
1090         p_sys->i_npt = p_sys->i_npt_start;
1091
1092 #if (LIVEMEDIA_LIBRARY_VERSION_INT >= 1199404800)
1093     /* Retrieve the duration if possible */
1094     p_sys->i_npt_length = (int64_t)( p_sys->ms->playEndTime() * (double)1000000.0 );
1095 #else
1096     p_sys->i_npt_length = -1;
1097 #endif
1098     if( p_sys->i_npt_length < 0 )
1099         p_sys->i_npt_length = -1;
1100
1101     msg_Dbg( p_demux, "play start: %lld stop:%lld", p_sys->i_npt_start, p_sys->i_npt_length );
1102     return VLC_SUCCESS;
1103 }
1104
1105
1106 /*****************************************************************************
1107  * Demux:
1108  *****************************************************************************/
1109 static int Demux( demux_t *p_demux )
1110 {
1111     demux_sys_t    *p_sys = p_demux->p_sys;
1112     TaskToken      task;
1113
1114     bool      b_send_pcr = true;
1115     int64_t         i_pcr = 0;
1116     int             i;
1117
1118     /* Check if we need to send the server a Keep-A-Live signal */
1119     if( p_sys->b_timeout_call && p_sys->rtsp && p_sys->ms )
1120     {
1121         char *psz_bye = NULL;
1122         p_sys->rtsp->getMediaSessionParameter( *p_sys->ms, NULL, psz_bye );
1123         p_sys->b_timeout_call = false;
1124     }
1125
1126
1127     for( i = 0; i < p_sys->i_track; i++ )
1128     {
1129         live_track_t *tk = p_sys->track[i];
1130
1131         if( tk->b_asf || tk->b_muxed )
1132             b_send_pcr = false;
1133 #if 0
1134         if( i_pcr == 0 )
1135         {
1136             i_pcr = tk->i_pts;
1137         }
1138         else if( tk->i_pts != 0 && i_pcr > tk->i_pts )
1139         {
1140             i_pcr = tk->i_pts ;
1141         }
1142 #endif
1143     }
1144     if( p_sys->i_pcr > 0 )
1145     {
1146         if( b_send_pcr )
1147             es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_sys->i_pcr );
1148     }
1149
1150     /* First warn we want to read data */
1151     p_sys->event = 0;
1152     for( i = 0; i < p_sys->i_track; i++ )
1153     {
1154         live_track_t *tk = p_sys->track[i];
1155
1156         if( tk->waiting == 0 )
1157         {
1158             tk->waiting = 1;
1159             tk->sub->readSource()->getNextFrame( tk->p_buffer, tk->i_buffer,
1160                                           StreamRead, tk, StreamClose, tk );
1161         }
1162     }
1163     /* Create a task that will be called if we wait more than 300ms */
1164     task = p_sys->scheduler->scheduleDelayedTask( 300000, TaskInterrupt, p_demux );
1165
1166     /* Do the read */
1167     p_sys->scheduler->doEventLoop( &p_sys->event );
1168
1169     /* remove the task */
1170     p_sys->scheduler->unscheduleDelayedTask( task );
1171
1172     /* Check for gap in pts value */
1173     for( i = 0; i < p_sys->i_track; i++ )
1174     {
1175         live_track_t *tk = p_sys->track[i];
1176
1177         if( !tk->b_muxed && !tk->b_rtcp_sync &&
1178             tk->sub->rtpSource() && tk->sub->rtpSource()->hasBeenSynchronizedUsingRTCP() )
1179         {
1180             msg_Dbg( p_demux, "tk->rtpSource->hasBeenSynchronizedUsingRTCP()" );
1181
1182             es_out_Control( p_demux->out, ES_OUT_RESET_PCR );
1183             tk->b_rtcp_sync = true;
1184             /* reset PCR */
1185             tk->i_pts = 0;
1186             p_sys->i_pcr = 0;
1187             i_pcr = 0;
1188         }
1189     }
1190
1191     if( p_sys->b_multicast && p_sys->b_no_data &&
1192         ( p_sys->i_no_data_ti > 120 ) )
1193     {
1194         /* FIXME Make this configurable
1195         msg_Err( p_demux, "no multicast data received in 36s, aborting" );
1196         return 0;
1197         */
1198     }
1199     else if( !p_sys->b_multicast && p_sys->b_no_data &&
1200              ( p_sys->i_no_data_ti > 34 ) )
1201     {
1202         bool b_rtsp_tcp = var_GetBool( p_demux, "rtsp-tcp" ) ||
1203                                 var_GetBool( p_demux, "rtsp-http" );
1204
1205         if( !b_rtsp_tcp && p_sys->rtsp && p_sys->ms )
1206         {
1207             msg_Warn( p_demux, "no data received in 10s. Switching to TCP" );
1208             if( RollOverTcp( p_demux ) )
1209             {
1210                 msg_Err( p_demux, "TCP rollover failed, aborting" );
1211                 return 0;
1212             }
1213         }
1214         else if( p_sys->i_no_data_ti > 34 )
1215         {
1216             msg_Err( p_demux, "no data received in 10s, aborting" );
1217             return 0;
1218         }
1219     }
1220     else if( !p_sys->b_multicast && p_sys->b_no_data && p_sys->i_no_data_ti > 34 )
1221     {
1222         /* EOF ? */
1223         msg_Warn( p_demux, "no data received in 10s, eof ?" );
1224         return 0;
1225     }
1226     return p_demux->b_error ? 0 : 1;
1227 }
1228
1229 /*****************************************************************************
1230  * Control:
1231  *****************************************************************************/
1232 static int Control( demux_t *p_demux, int i_query, va_list args )
1233 {
1234     demux_sys_t *p_sys = p_demux->p_sys;
1235     int64_t *pi64;
1236     double  *pf, f;
1237     bool *pb, *pb2, b_bool;
1238     int *pi_int;
1239
1240     switch( i_query )
1241     {
1242         case DEMUX_GET_TIME:
1243             pi64 = (int64_t*)va_arg( args, int64_t * );
1244             if( p_sys->i_npt > 0 )
1245             {
1246                 *pi64 = p_sys->i_npt;
1247                 return VLC_SUCCESS;
1248             }
1249             return VLC_EGENERIC;
1250
1251         case DEMUX_GET_LENGTH:
1252             pi64 = (int64_t*)va_arg( args, int64_t * );
1253             if( p_sys->i_npt_length > 0 )
1254             {
1255                 *pi64 = p_sys->i_npt_length;
1256                 return VLC_SUCCESS;
1257             }
1258             return VLC_EGENERIC;
1259
1260         case DEMUX_GET_POSITION:
1261             pf = (double*)va_arg( args, double* );
1262             if( p_sys->i_npt_length > 0 && p_sys->i_npt > 0 )
1263             {
1264                 *pf = (double)p_sys->i_npt / (double)p_sys->i_npt_length;
1265                 return VLC_SUCCESS;
1266             }
1267             return VLC_EGENERIC;
1268
1269         case DEMUX_SET_POSITION:
1270         {
1271             float time;
1272
1273             f = (double)va_arg( args, double );
1274             if( p_sys->rtsp && p_sys->i_npt_length > 0 )
1275             {
1276                 int i;
1277                 time = f * (double)p_sys->i_npt_length / (double)1000000.0;   /* in second */
1278                 if( !p_sys->rtsp->playMediaSession( *p_sys->ms, time, -1, 1 ) )
1279                 {
1280                     msg_Err( p_demux, "PLAY failed %s",
1281                         p_sys->env->getResultMsg() );
1282                     return VLC_EGENERIC;
1283                 }
1284                 es_out_Control( p_demux->out, ES_OUT_RESET_PCR );
1285                 p_sys->i_pcr = 0;
1286 #if (LIVEMEDIA_LIBRARY_VERSION_INT >= 1195257600)
1287                 /* Retrieve RTP-Info values */
1288                 for( i = 0; i < p_sys->i_track; i++ )
1289                 {
1290                     //if( !p_sys->track[i]->b_rtcp_sync )
1291                     p_sys->track[i]->b_rtcp_sync = false;
1292                     p_sys->track[i]->i_pts = (int64_t) ( p_sys->track[i]->sub->rtpInfo.timestamp * (double)1000000.0 );
1293                     p_sys->track[i]->i_start_seq = p_sys->track[i]->sub->rtpInfo.seqNum;
1294                     msg_Info( p_demux, "set pos startseq: %u", p_sys->track[i]->i_start_seq );
1295                 }
1296 #endif
1297 #if (LIVEMEDIA_LIBRARY_VERSION_INT >= 1199404800)
1298                 /* Retrieve the starttime if possible */
1299                 p_sys->i_npt_start = (int64_t)( p_sys->ms->playStartTime() * (double)1000000.0 );
1300 #else
1301                 p_sys->i_npt_start = -1;
1302 #endif
1303                 if( p_sys->i_npt_start < 0 )
1304                 {
1305                     p_sys->i_npt_start = -1;
1306                     p_sys->i_npt = 0;
1307                 }
1308                 else
1309                     p_sys->i_npt = p_sys->i_npt_start;
1310
1311 #if (LIVEMEDIA_LIBRARY_VERSION_INT >= 1199404800)
1312                 /* Retrieve the duration if possible */
1313                 p_sys->i_npt_length = (int64_t)( p_sys->ms->playEndTime() * (double)1000000.0 );
1314 #else
1315                 p_sys->i_npt_length = -1;
1316 #endif
1317                 if( p_sys->i_npt_length < 0 )
1318                     p_sys->i_npt_length = -1;
1319
1320                 msg_Dbg( p_demux, "seek start: %lld stop:%lld", p_sys->i_npt_start, p_sys->i_npt_length );
1321                 return VLC_SUCCESS;
1322             }
1323             return VLC_EGENERIC;
1324         }
1325         /* Special for access_demux */
1326         case DEMUX_CAN_PAUSE:
1327         case DEMUX_CAN_SEEK:
1328             pb = (bool*)va_arg( args, bool * );
1329             if( p_sys->rtsp && p_sys->i_npt_length )
1330                 /* Not always true, but will be handled in SET_PAUSE_STATE */
1331                 *pb = true;
1332             else
1333                 *pb = false;
1334             return VLC_SUCCESS;
1335
1336         case DEMUX_CAN_CONTROL_PACE:
1337             pb = (bool*)va_arg( args, bool * );
1338
1339 #if 1       /* Disable for now until we have a clock synchro algo
1340              * which works with something else than MPEG over UDP */
1341             *pb = false;
1342 #else
1343             *pb = true;
1344 #endif
1345             return VLC_SUCCESS;
1346
1347 #if 0
1348         case DEMUX_CAN_CONTROL_RATE:
1349             pb = (bool*)va_arg( args, bool * );
1350             pb2 = (bool*)va_arg( args, bool * );
1351
1352             *pb = p_sys->rtsp != NULL && p_sys->i_npt_length > 0 && !var_GetBool( p_demux, "rtsp-kasenna" );
1353             *pb2 = false;
1354             return VLC_SUCCESS;
1355
1356         case DEMUX_SET_RATE:
1357         {
1358             double f_scale;
1359
1360             if( !p_sys->rtsp || p_sys->i_npt_length <= 0 || var_GetBool( p_demux, "rtsp-kasenna" ) )
1361                 return VLC_EGENERIC;
1362
1363             /* TODO we might want to ensure that the new rate is different from
1364              * old rate after playMediaSession...
1365              * I have no idea how the server map the requested rate to the
1366              * ones it supports.
1367              * ex:
1368              *  current is x2 we request x1.5 if the server return x2 we will
1369              *  never succeed to return to x1.
1370              *  In this case we should retry with a lower rate until we have
1371              *  one (even x1).
1372              */
1373
1374             pi_int = (int*)va_arg( args, int * );
1375             f_scale = (double)INPUT_RATE_DEFAULT / (*p_int);
1376
1377             /* Passing -1 for the start and end time will mean liveMedia won't
1378             * create a Range: section for the RTSP message. The server should
1379             * pick up from the current position */
1380             if( !p_sys->rtsp->playMediaSession( *p_sys->ms, -1, -1, f_scale ) )
1381             {
1382                 msg_Err( p_demux, "PLAY with Scale %0.2f failed %s", f_scale,
1383                         p_sys->env->getResultMsg() );
1384                 return VLC_EGENERIC;
1385             }
1386             /* ReSync the stream */
1387             p_sys->i_npt_start = 0;
1388             p_sys->i_pcr = 0;
1389             es_out_Control( p_demux->out, ES_OUT_RESET_PCR );
1390
1391             *pi_int = (int)( INPUT_RATE_DEFAULT / p_sys->ms->scale() + 0.5 );
1392             return VLC_SUCCESS;
1393         }
1394 #endif
1395
1396         case DEMUX_SET_PAUSE_STATE:
1397         {
1398             double d_npt = (double) p_sys->i_npt / INT64_C(1000000);
1399             int i;
1400
1401             b_bool = (bool)va_arg( args, int );
1402             if( p_sys->rtsp == NULL )
1403                 return VLC_EGENERIC;
1404
1405             /* FIXME */
1406             if( ( b_bool && !p_sys->rtsp->pauseMediaSession( *p_sys->ms ) ) ||
1407                     ( !b_bool && !p_sys->rtsp->playMediaSession( *p_sys->ms,
1408                       d_npt > 0 ? d_npt : -1 ) ) )
1409             {
1410                     msg_Err( p_demux, "PLAY or PAUSE failed %s", p_sys->env->getResultMsg() );
1411                     return VLC_EGENERIC;
1412             }
1413
1414             /* When we Pause, we'll need the TimeoutPrevention thread to
1415              * handle sending the "Keep Alive" message to the server. 
1416              * Unfortunately Live555 isn't thread safe and so can't 
1417              * do this normally while the main Demux thread is handling
1418              * a live stream. We end up with the Timeout thread blocking
1419              * waiting for a response from the server. So when we PAUSE
1420              * we set a flag that the TimeoutPrevention function will check
1421              * and if it's set, it will trigger the GET_PARAMETER message */
1422             if( b_bool && p_sys->p_timeout != NULL )
1423                 p_sys->p_timeout->b_handle_keep_alive = true;
1424             else if( !b_bool && p_sys->p_timeout != NULL ) 
1425                 p_sys->p_timeout->b_handle_keep_alive = false;
1426
1427             es_out_Control( p_demux->out, ES_OUT_RESET_PCR );
1428             p_sys->i_pcr = 0;
1429 #if (LIVEMEDIA_LIBRARY_VERSION_INT >= 1195257600)
1430             for( i = 0; i < p_sys->i_track; i++ )
1431             {
1432                 if( !p_sys->track[i]->b_rtcp_sync )
1433                     p_sys->track[i]->i_pts = 0; // (int64_t) ( p_sys->track[i]->sub->rtpInfo.timestamp * (double)1000000.0 );
1434                 p_sys->track[i]->i_start_seq = p_sys->track[i]->sub->rtpInfo.seqNum;
1435                 msg_Info( p_demux, "set pause startseq: %u", p_sys->track[i]->i_start_seq );
1436             }
1437 #endif
1438 #if (LIVEMEDIA_LIBRARY_VERSION_INT >= 1199404800)
1439             /* Retrieve the starttime if possible */
1440             p_sys->i_npt_start = (int64_t)( p_sys->ms->playStartTime() * (double)1000000.0 );
1441 #else
1442             p_sys->i_npt_start = -1;
1443 #endif
1444             if( p_sys->i_npt_start < 0 )
1445             {
1446                 p_sys->i_npt_start = -1;
1447                 p_sys->i_npt = 0;
1448             }
1449             else
1450                 p_sys->i_npt = p_sys->i_npt_start;
1451
1452 #if (LIVEMEDIA_LIBRARY_VERSION_INT >= 1199404800)
1453             /* Retrieve the duration if possible */
1454             p_sys->i_npt_length = (int64_t)( p_sys->ms->playEndTime() * (double)1000000.0 );
1455 #else
1456             p_sys->i_npt_length = -1;
1457 #endif
1458             if( p_sys->i_npt_length < 0 )
1459                 p_sys->i_npt_length = -1;
1460
1461             msg_Dbg( p_demux, "pause start: %lld stop:%lld", p_sys->i_npt_start, p_sys->i_npt_length );
1462             return VLC_SUCCESS;
1463         }
1464         case DEMUX_GET_TITLE_INFO:
1465         case DEMUX_SET_TITLE:
1466         case DEMUX_SET_SEEKPOINT:
1467             return VLC_EGENERIC;
1468
1469         case DEMUX_GET_PTS_DELAY:
1470             pi64 = (int64_t*)va_arg( args, int64_t * );
1471             *pi64 = (int64_t)var_GetInteger( p_demux, "rtsp-caching" ) * 1000;
1472             return VLC_SUCCESS;
1473
1474         default:
1475             return VLC_EGENERIC;
1476     }
1477 }
1478
1479 /*****************************************************************************
1480  * RollOverTcp: reopen the rtsp into TCP mode
1481  * XXX: ugly, a lot of code are duplicated from Open()
1482  * This should REALLY be fixed
1483  *****************************************************************************/
1484 static int RollOverTcp( demux_t *p_demux )
1485 {
1486     demux_sys_t *p_sys = p_demux->p_sys;
1487     int i, i_return;
1488
1489     var_SetBool( p_demux, "rtsp-tcp", true );
1490
1491     /* We close the old RTSP session */
1492     for( i = 0; i < p_sys->i_track; i++ )
1493     {
1494         live_track_t *tk = p_sys->track[i];
1495
1496         if( tk->b_muxed ) stream_DemuxDelete( tk->p_out_muxed );
1497         es_format_Clean( &tk->fmt );
1498         free( tk->p_buffer );
1499         free( tk );
1500     }
1501     if( p_sys->i_track ) free( p_sys->track );
1502     if( p_sys->p_out_asf ) stream_DemuxDelete( p_sys->p_out_asf );
1503
1504     p_sys->rtsp->teardownMediaSession( *p_sys->ms );
1505     Medium::close( p_sys->ms );
1506     RTSPClient::close( p_sys->rtsp );
1507
1508     p_sys->ms = NULL;
1509     p_sys->rtsp = NULL;
1510     p_sys->track = NULL;
1511     p_sys->i_track = 0;
1512
1513     /* Reopen rtsp client */
1514     if( ( p_demux->s != NULL ) &&
1515         ( i_return = Connect( p_demux ) ) != VLC_SUCCESS )
1516     {
1517         msg_Err( p_demux, "Failed to connect with rtsp://%s",
1518                  p_sys->psz_path );
1519         goto error;
1520     }
1521
1522     if( p_sys->p_sdp == NULL )
1523     {
1524         msg_Err( p_demux, "Failed to retrieve the RTSP Session Description" );
1525         goto error;
1526     }
1527
1528     if( ( i_return = SessionsSetup( p_demux ) ) != VLC_SUCCESS )
1529     {
1530         msg_Err( p_demux, "Nothing to play for rtsp://%s", p_sys->psz_path );
1531         goto error;
1532     }
1533
1534     if( ( i_return = Play( p_demux ) ) != VLC_SUCCESS )
1535         goto error;
1536
1537     return VLC_SUCCESS;
1538
1539 error:
1540     return VLC_EGENERIC;
1541 }
1542
1543
1544 /*****************************************************************************
1545  *
1546  *****************************************************************************/
1547 static void StreamRead( void *p_private, unsigned int i_size,
1548                         unsigned int i_truncated_bytes, struct timeval pts,
1549                         unsigned int duration )
1550 {
1551     live_track_t   *tk = (live_track_t*)p_private;
1552     demux_t        *p_demux = tk->p_demux;
1553     demux_sys_t    *p_sys = p_demux->p_sys;
1554     block_t        *p_block;
1555
1556     //msg_Dbg( p_demux, "pts: %d", pts.tv_sec );
1557
1558     int64_t i_pts = (uint64_t)pts.tv_sec * UINT64_C(1000000) +
1559         (uint64_t)pts.tv_usec;
1560
1561     /* XXX Beurk beurk beurk Avoid having negative value XXX */
1562     i_pts &= UINT64_C(0x00ffffffffffffff);
1563
1564     if( tk->b_quicktime && tk->p_es == NULL )
1565     {
1566         QuickTimeGenericRTPSource *qtRTPSource =
1567             (QuickTimeGenericRTPSource*)tk->sub->rtpSource();
1568         QuickTimeGenericRTPSource::QTState &qtState = qtRTPSource->qtState;
1569         uint8_t *sdAtom = (uint8_t*)&qtState.sdAtom[4];
1570
1571         if( tk->fmt.i_cat == VIDEO_ES ) {
1572             if( qtState.sdAtomSize < 16 + 32 )
1573             {
1574                 /* invalid */
1575                 p_sys->event = 0xff;
1576                 tk->waiting = 0;
1577                 return;
1578             }
1579             tk->fmt.i_codec = VLC_FOURCC(sdAtom[0],sdAtom[1],sdAtom[2],sdAtom[3]);
1580             tk->fmt.video.i_width  = (sdAtom[28] << 8) | sdAtom[29];
1581             tk->fmt.video.i_height = (sdAtom[30] << 8) | sdAtom[31];
1582
1583             if( tk->fmt.i_codec == VLC_FOURCC('a', 'v', 'c', '1') )
1584             {
1585                 uint8_t *pos = (uint8_t*)qtRTPSource->qtState.sdAtom + 86;
1586                 uint8_t *endpos = (uint8_t*)qtRTPSource->qtState.sdAtom
1587                                   + qtRTPSource->qtState.sdAtomSize;
1588                 while (pos+8 < endpos) {
1589                     unsigned int atomLength = pos[0]<<24 | pos[1]<<16 | pos[2]<<8 | pos[3];
1590                     if( atomLength == 0 || atomLength > (unsigned int)(endpos-pos)) break;
1591                     if( memcmp(pos+4, "avcC", 4) == 0 &&
1592                         atomLength > 8 &&
1593                         atomLength <= INT_MAX )
1594                     {
1595                         tk->fmt.i_extra = atomLength-8;
1596                         tk->fmt.p_extra = malloc( tk->fmt.i_extra );
1597                         memcpy(tk->fmt.p_extra, pos+8, atomLength-8);
1598                         break;
1599                     }
1600                     pos += atomLength;
1601                 }
1602             }
1603             else
1604             {
1605                 tk->fmt.i_extra        = qtState.sdAtomSize - 16;
1606                 tk->fmt.p_extra        = malloc( tk->fmt.i_extra );
1607                 memcpy( tk->fmt.p_extra, &sdAtom[12], tk->fmt.i_extra );
1608             }
1609         }
1610         else {
1611             if( qtState.sdAtomSize < 4 )
1612             {
1613                 /* invalid */
1614                 p_sys->event = 0xff;
1615                 tk->waiting = 0;
1616                 return;
1617             }
1618             tk->fmt.i_codec = VLC_FOURCC(sdAtom[0],sdAtom[1],sdAtom[2],sdAtom[3]);
1619         }
1620         tk->p_es = es_out_Add( p_demux->out, &tk->fmt );
1621     }
1622
1623 #if 0
1624     fprintf( stderr, "StreamRead size=%d pts=%lld\n",
1625              i_size,
1626              pts.tv_sec * 1000000LL + pts.tv_usec );
1627 #endif
1628
1629     /* grow buffer if it looks like buffer is too small, but don't eat
1630      * up all the memory on strange streams */
1631     if( i_truncated_bytes > 0 && tk->i_buffer < 2000000 )
1632     {
1633         void *p_tmp;
1634         msg_Dbg( p_demux, "lost %d bytes", i_truncated_bytes );
1635         msg_Dbg( p_demux, "increasing buffer size to %d", tk->i_buffer * 2 );
1636         tk->i_buffer *= 2;
1637         p_tmp = realloc( tk->p_buffer, tk->i_buffer );
1638         if( p_tmp == NULL )
1639         {
1640             msg_Warn( p_demux, "realloc failed" );
1641         }
1642         else
1643         {
1644             tk->p_buffer = (uint8_t*)p_tmp;
1645         }
1646     }
1647     if( i_size > tk->i_buffer )
1648     {
1649         msg_Warn( p_demux, "buffer overflow" );
1650     }
1651     /* FIXME could i_size be > buffer size ? */
1652     if( tk->fmt.i_codec == VLC_FOURCC('s','a','m','r') ||
1653         tk->fmt.i_codec == VLC_FOURCC('s','a','w','b') )
1654     {
1655         AMRAudioSource *amrSource = (AMRAudioSource*)tk->sub->readSource();
1656
1657         p_block = block_New( p_demux, i_size + 1 );
1658         p_block->p_buffer[0] = amrSource->lastFrameHeader();
1659         memcpy( p_block->p_buffer + 1, tk->p_buffer, i_size );
1660     }
1661     else if( tk->fmt.i_codec == VLC_FOURCC('H','2','6','1') )
1662     {
1663 #if LIVEMEDIA_LIBRARY_VERSION_INT >= 1081468800
1664         H261VideoRTPSource *h261Source = (H261VideoRTPSource*)tk->sub->rtpSource();
1665         uint32_t header = h261Source->lastSpecialHeader();
1666 #else
1667         uint32_t header = 0;
1668         msg_Warn( p_demux, "need livemedia library >= \"2004.04.09\"" );
1669 #endif
1670         p_block = block_New( p_demux, i_size + 4 );
1671         memcpy( p_block->p_buffer, &header, 4 );
1672         memcpy( p_block->p_buffer + 4, tk->p_buffer, i_size );
1673
1674         if( tk->sub->rtpSource()->curPacketMarkerBit() )
1675             p_block->i_flags |= BLOCK_FLAG_END_OF_FRAME;
1676     }
1677     else if( tk->fmt.i_codec == VLC_FOURCC('h','2','6','4') )
1678     {
1679         if( (tk->p_buffer[0] & 0x1f) >= 24 )
1680             msg_Warn( p_demux, "unsupported NAL type for H264" );
1681
1682         /* Normal NAL type */
1683         p_block = block_New( p_demux, i_size + 4 );
1684         p_block->p_buffer[0] = 0x00;
1685         p_block->p_buffer[1] = 0x00;
1686         p_block->p_buffer[2] = 0x00;
1687         p_block->p_buffer[3] = 0x01;
1688         memcpy( &p_block->p_buffer[4], tk->p_buffer, i_size );
1689     }
1690     else if( tk->b_asf )
1691     {
1692         int i_copy = __MIN( p_sys->asfh.i_min_data_packet_size, (int)i_size );
1693         p_block = block_New( p_demux, p_sys->asfh.i_min_data_packet_size );
1694
1695         memcpy( p_block->p_buffer, tk->p_buffer, i_copy );
1696     }
1697     else
1698     {
1699         p_block = block_New( p_demux, i_size );
1700         memcpy( p_block->p_buffer, tk->p_buffer, i_size );
1701     }
1702
1703     /* Update NPT */
1704     //msg_Dbg( p_demux, "current %d, start_seq %u", (int)tk->sub->rtpSource()->curPacketRTPSeqNum(), tk->i_start_seq );
1705     if( (tk->fmt.i_cat == VIDEO_ES) && (p_sys->i_pcr < i_pts) &&
1706         (i_pts > 0) && (p_sys->i_pcr > 0) )
1707     {
1708         p_sys->i_npt += __MAX( 0, i_pts - p_sys->i_pcr );
1709         p_sys->i_pcr = i_pts;
1710         //msg_Dbg( p_demux, "npt update" );
1711     }
1712     else if( /*tk->fmt.i_cat == VIDEO_ES &&*/ p_sys->i_pcr < i_pts )
1713     {
1714         p_sys->i_pcr = i_pts;
1715     }
1716     //msg_Dbg( p_demux, "npt %lld", p_sys->i_npt );
1717
1718     if( (i_pts != tk->i_pts) && (!tk->b_muxed) )
1719     {
1720         p_block->i_pts = i_pts;
1721     }
1722     if( !tk->b_muxed )
1723     {
1724         /*FIXME: for h264 you should check that packetization-mode=1 in sdp-file */
1725         p_block->i_dts = ( tk->fmt.i_codec == VLC_FOURCC( 'm', 'p', 'g', 'v' ) ) ? 0 : i_pts;
1726     }
1727
1728     if( tk->b_muxed )
1729     {
1730         stream_DemuxSend( tk->p_out_muxed, p_block );
1731     }
1732     else if( tk->b_asf )
1733     {
1734         stream_DemuxSend( p_sys->p_out_asf, p_block );
1735     }
1736     else
1737     {
1738         es_out_Send( p_demux->out, tk->p_es, p_block );
1739     }
1740
1741     /* warn that's ok */
1742     p_sys->event = 0xff;
1743
1744     /* we have read data */
1745     tk->waiting = 0;
1746     p_demux->p_sys->b_no_data = false;
1747     p_demux->p_sys->i_no_data_ti = 0;
1748
1749     if( i_pts > 0 && !tk->b_muxed )
1750     {
1751         tk->i_pts = i_pts;
1752     }
1753 }
1754
1755 /*****************************************************************************
1756  *
1757  *****************************************************************************/
1758 static void StreamClose( void *p_private )
1759 {
1760     live_track_t   *tk = (live_track_t*)p_private;
1761     demux_t        *p_demux = tk->p_demux;
1762     demux_sys_t    *p_sys = p_demux->p_sys;
1763
1764     msg_Dbg( p_demux, "StreamClose" );
1765
1766     p_sys->event = 0xff;
1767     p_demux->b_error = true;
1768 }
1769
1770
1771 /*****************************************************************************
1772  *
1773  *****************************************************************************/
1774 static void TaskInterrupt( void *p_private )
1775 {
1776     demux_t *p_demux = (demux_t*)p_private;
1777
1778     p_demux->p_sys->i_no_data_ti++;
1779
1780     /* Avoid lock */
1781     p_demux->p_sys->event = 0xff;
1782 }
1783
1784 /*****************************************************************************
1785  *
1786  *****************************************************************************/
1787 static void TimeoutPrevention( timeout_thread_t *p_timeout )
1788 {
1789     p_timeout->b_die = false;
1790     p_timeout->i_remain = (int64_t)p_timeout->p_sys->i_timeout -2;
1791     p_timeout->i_remain *= 1000000;
1792
1793     vlc_thread_ready( p_timeout );
1794
1795     /* Avoid lock */
1796     while( !p_timeout->b_die )
1797     {
1798         if( p_timeout->i_remain <= 0 )
1799         {
1800             char *psz_bye = NULL;
1801             p_timeout->i_remain = (int64_t)p_timeout->p_sys->i_timeout -2;
1802             p_timeout->i_remain *= 1000000;
1803             msg_Dbg( p_timeout, "reset the timeout timer" );
1804             if( p_timeout->b_handle_keep_alive == true )
1805             {
1806 #if LIVEMEDIA_LIBRARY_VERSION_INT >= 1138089600
1807                 p_timeout->p_sys->rtsp->getMediaSessionParameter( *p_timeout->p_sys->ms, NULL, psz_bye );
1808 #endif
1809                 p_timeout->p_sys->b_timeout_call = false;
1810             }
1811             else
1812             {
1813                 p_timeout->p_sys->b_timeout_call = true;
1814             }
1815         }
1816         p_timeout->i_remain -= 200000;
1817         msleep( 200000 ); /* 200 ms */
1818     }
1819 }
1820
1821 /*****************************************************************************
1822  *
1823  *****************************************************************************/
1824 static int b64_decode( char *dest, char *src );
1825
1826 static int ParseASF( demux_t *p_demux )
1827 {
1828     demux_sys_t    *p_sys = p_demux->p_sys;
1829
1830     const char *psz_marker = "a=pgmpu:data:application/vnd.ms.wms-hdr.asfv1;base64,";
1831     char *psz_asf = strcasestr( p_sys->p_sdp, psz_marker );
1832     char *psz_end;
1833     block_t *p_header;
1834
1835     /* Parse the asf header */
1836     if( psz_asf == NULL )
1837         return VLC_EGENERIC;
1838
1839     psz_asf += strlen( psz_marker );
1840     psz_asf = strdup( psz_asf );    /* Duplicate it */
1841     psz_end = strchr( psz_asf, '\n' );
1842
1843     while( psz_end > psz_asf && ( *psz_end == '\n' || *psz_end == '\r' ) )
1844         *psz_end-- = '\0';
1845
1846     if( psz_asf >= psz_end )
1847     {
1848         free( psz_asf );
1849         return VLC_EGENERIC;
1850     }
1851
1852     /* Always smaller */
1853     p_header = block_New( p_demux, psz_end - psz_asf );
1854     p_header->i_buffer = b64_decode( (char*)p_header->p_buffer, psz_asf );
1855     //msg_Dbg( p_demux, "Size=%d Hdrb64=%s", p_header->i_buffer, psz_asf );
1856     if( p_header->i_buffer <= 0 )
1857     {
1858         free( psz_asf );
1859         return VLC_EGENERIC;
1860     }
1861
1862     /* Parse it to get packet size */
1863     asf_HeaderParse( &p_sys->asfh, p_header->p_buffer, p_header->i_buffer );
1864
1865     /* Send it to demuxer */
1866     stream_DemuxSend( p_sys->p_out_asf, p_header );
1867
1868     free( psz_asf );
1869     return VLC_SUCCESS;
1870 }
1871
1872
1873 static unsigned char* parseH264ConfigStr( char const* configStr,
1874                                           unsigned int& configSize )
1875 {
1876     char *dup, *psz;
1877     int i, i_records = 1;
1878
1879     if( configSize )
1880     configSize = 0;
1881
1882     if( configStr == NULL || *configStr == '\0' )
1883         return NULL;
1884
1885     psz = dup = strdup( configStr );
1886
1887     /* Count the number of comma's */
1888     for( psz = dup; *psz != '\0'; ++psz )
1889     {
1890         if( *psz == ',')
1891         {
1892             ++i_records;
1893             *psz = '\0';
1894         }
1895     }
1896
1897     unsigned char *cfg = new unsigned char[5 * strlen(dup)];
1898     psz = dup;
1899     for( i = 0; i < i_records; i++ )
1900     {
1901         cfg[configSize++] = 0x00;
1902         cfg[configSize++] = 0x00;
1903         cfg[configSize++] = 0x00;
1904         cfg[configSize++] = 0x01;
1905
1906         configSize += b64_decode( (char*)&cfg[configSize], psz );
1907         psz += strlen(psz)+1;
1908     }
1909
1910     free( dup );
1911     return cfg;
1912 }
1913
1914 /*char b64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";*/
1915 static int b64_decode( char *dest, char *src )
1916 {
1917     const char *dest_start = dest;
1918     int  i_level;
1919     int  last = 0;
1920     int  b64[256] = {
1921         -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,  /* 00-0F */
1922         -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,  /* 10-1F */
1923         -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,-1,-1,-1,63,  /* 20-2F */
1924         52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-1,-1,-1,  /* 30-3F */
1925         -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,  /* 40-4F */
1926         15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1,  /* 50-5F */
1927         -1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,  /* 60-6F */
1928         41,42,43,44,45,46,47,48,49,50,51,-1,-1,-1,-1,-1,  /* 70-7F */
1929         -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,  /* 80-8F */
1930         -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,  /* 90-9F */
1931         -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,  /* A0-AF */
1932         -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,  /* B0-BF */
1933         -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,  /* C0-CF */
1934         -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,  /* D0-DF */
1935         -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,  /* E0-EF */
1936         -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1   /* F0-FF */
1937         };
1938
1939     for( i_level = 0; *src != '\0'; src++ )
1940     {
1941         int  c;
1942
1943         c = b64[(unsigned int)*src];
1944         if( c == -1 )
1945         {
1946             continue;
1947         }
1948
1949         switch( i_level )
1950         {
1951             case 0:
1952                 i_level++;
1953                 break;
1954             case 1:
1955                 *dest++ = ( last << 2 ) | ( ( c >> 4)&0x03 );
1956                 i_level++;
1957                 break;
1958             case 2:
1959                 *dest++ = ( ( last << 4 )&0xf0 ) | ( ( c >> 2 )&0x0f );
1960                 i_level++;
1961                 break;
1962             case 3:
1963                 *dest++ = ( ( last &0x03 ) << 6 ) | c;
1964                 i_level = 0;
1965         }
1966         last = c;
1967     }
1968
1969     *dest = '\0';
1970
1971     return dest - dest_start;
1972 }