]> git.sesse.net Git - vlc/blob - modules/demux/livedotcom.cpp
17699c11ab7625544befbfa8989ed1069329db84
[vlc] / modules / demux / livedotcom.cpp
1 /*****************************************************************************
2  * live.cpp : live.com support.
3  *****************************************************************************
4  * Copyright (C) 2003 VideoLAN
5  * $Id: livedotcom.cpp,v 1.5 2003/11/07 22:56:02 gbazin Exp $
6  *
7  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
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  * Preamble
26  *****************************************************************************/
27 #include <stdlib.h>                                      /* malloc(), free() */
28
29 #include <vlc/vlc.h>
30 #include <vlc/input.h>
31
32 #include <codecs.h>                        /* BITMAPINFOHEADER, WAVEFORMATEX */
33 #include <iostream>
34
35 #if defined( WIN32 )
36 #   include <winsock2.h>
37 #endif
38
39 #include "BasicUsageEnvironment.hh"
40 #include "GroupsockHelper.hh"
41 #include "liveMedia.hh"
42
43 using namespace std;
44
45 /*****************************************************************************
46  * Module descriptor
47  *****************************************************************************/
48 static int  DemuxOpen ( vlc_object_t * );
49 static void DemuxClose( vlc_object_t * );
50
51 static int  AccessOpen ( vlc_object_t * );
52 static void AccessClose( vlc_object_t * );
53
54 #define CACHING_TEXT N_("Caching value in ms")
55 #define CACHING_LONGTEXT N_( \
56     "Allows you to modify the default caching value for rtsp streams. This " \
57     "value should be set in miliseconds units." )
58
59 vlc_module_begin();
60     set_description( _("live.com (RTSP/RTP/SDP) demuxer" ) );
61     set_capability( "demux", 50 );
62     set_callbacks( DemuxOpen, DemuxClose );
63     add_shortcut( "live" );
64
65     add_submodule();
66         set_description( _("RTSP/RTP describe") );
67         add_shortcut( "rtsp" );
68         set_capability( "access", 0 );
69         set_callbacks( AccessOpen, AccessClose );
70         add_category_hint( N_("RTSP"), NULL, VLC_TRUE );
71             add_bool( "rtsp-tcp", 0, NULL,
72                       "Use rtp over rtsp(tcp)",
73                       "Use rtp over rtsp(tcp)", VLC_TRUE );
74             add_integer( "rtsp-caching", 4 * DEFAULT_PTS_DELAY / 1000, NULL, CACHING_TEXT, CACHING_LONGTEXT, VLC_TRUE );
75 vlc_module_end();
76
77 /* TODO:
78  *  - Support PS/TS (need to rework the TS/PS demuxer a lot).
79  *  - Support X-QT/X-QUICKTIME generic codec.
80  *  - Handle PTS (for now I just use mdate())
81  *
82  *  - Check memory leak, delete/free.
83  *
84  */
85
86 /*****************************************************************************
87  * Local prototypes
88  *****************************************************************************/
89 struct access_sys_t
90 {
91     int     i_sdp;
92     char    *p_sdp;
93
94     int     i_pos;
95 };
96
97 typedef struct
98 {
99     input_thread_t *p_input;
100
101     es_format_t  fmt;
102     es_out_id_t  *p_es;
103
104     FramedSource *readSource;
105
106     uint8_t      buffer[65536];
107
108     char         waiting;
109
110     mtime_t      i_pts;
111 } live_track_t;
112
113 struct demux_sys_t
114 {
115     char         *p_sdp;    /* XXX mallocated */
116
117     MediaSession     *ms;
118     TaskScheduler    *scheduler;
119     UsageEnvironment *env ;
120     RTSPClient       *rtsp;
121
122     int              i_track;
123     live_track_t     **track;   /* XXX mallocated */
124     mtime_t          i_pcr;
125     mtime_t          i_pcr_start;
126
127     char             event;
128 };
129
130 static ssize_t Read   ( input_thread_t *, byte_t *, size_t );
131
132 static int     Demux  ( input_thread_t * );
133 static int     Control( input_thread_t *, int, va_list );
134
135
136
137 /*****************************************************************************
138  * AccessOpen:
139  *****************************************************************************/
140 static int  AccessOpen( vlc_object_t *p_this )
141 {
142     input_thread_t *p_input = (input_thread_t *)p_this;
143     access_sys_t   *p_sys;
144
145     TaskScheduler    *scheduler = NULL;
146     UsageEnvironment *env       = NULL;
147     RTSPClient       *rtsp      = NULL;
148
149     vlc_value_t      val;
150     char             *psz_url;
151
152     if( p_input->psz_access == NULL || strcasecmp( p_input->psz_access, "rtsp" ) )
153     {
154         msg_Warn( p_input, "RTSP access discarded" );
155         return VLC_EGENERIC;
156     }
157     if( ( scheduler = BasicTaskScheduler::createNew() ) == NULL )
158     {
159         msg_Err( p_input, "BasicTaskScheduler::createNew failed" );
160         return VLC_EGENERIC;
161     }
162     if( ( env = BasicUsageEnvironment::createNew(*scheduler) ) == NULL )
163     {
164         delete scheduler;
165         msg_Err( p_input, "BasicUsageEnvironment::createNew failed" );
166         return VLC_EGENERIC;
167     }
168     if( ( rtsp = RTSPClient::createNew(*env, 1/*verbose*/, "VLC Media Player" ) ) == NULL )
169     {
170         delete env;
171         delete scheduler;
172         msg_Err( p_input, "RTSPClient::createNew failed" );
173         return VLC_EGENERIC;
174     }
175
176     psz_url = (char*)malloc( strlen( p_input->psz_name ) + 8 );
177     sprintf( psz_url, "rtsp://%s", p_input->psz_name );
178
179     p_sys = (access_sys_t*)malloc( sizeof( access_sys_t ) );
180     p_sys->p_sdp = rtsp->describeURL( psz_url );
181
182     if( p_sys->p_sdp == NULL )
183     {
184         msg_Err( p_input, "describeURL failed (%s)", env->getResultMsg() );
185
186         free( psz_url );
187         delete env;
188         delete scheduler;
189         free( p_sys );
190         return VLC_EGENERIC;
191     }
192     free( psz_url );
193     p_sys->i_sdp = strlen( p_sys->p_sdp );
194     p_sys->i_pos = 0;
195
196     //fprintf( stderr, "sdp=%s\n", p_sys->p_sdp );
197
198     delete env;
199     delete scheduler;
200
201     var_Create( p_input, "rtsp-tcp", VLC_VAR_BOOL|VLC_VAR_DOINHERIT );
202     var_Get( p_input, "rtsp-tcp", &val );
203
204     p_input->p_access_data = p_sys;
205     p_input->i_mtu = 0;
206
207     /* Set exported functions */
208     p_input->pf_read = Read;
209     p_input->pf_seek = NULL;
210     p_input->pf_set_program = input_SetProgram;
211     p_input->pf_set_area = NULL;
212     p_input->p_private = NULL;
213
214     p_input->psz_demux = "live";
215
216     /* Finished to set some variable */
217     vlc_mutex_lock( &p_input->stream.stream_lock );
218     /* FIXME that's not true but eg over tcp, server send data too fast */
219     p_input->stream.b_pace_control = val.b_bool;
220     p_input->stream.p_selected_area->i_tell = 0;
221     p_input->stream.b_seekable = 1; /* Hack to display time */
222     p_input->stream.p_selected_area->i_size = 0;
223     p_input->stream.i_method = INPUT_METHOD_NETWORK;
224     vlc_mutex_unlock( &p_input->stream.stream_lock );
225
226     /* Update default_pts to a suitable value for RTSP access */
227     var_Create( p_input, "rtsp-caching", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
228     var_Get( p_input, "rtsp-caching", &val );
229     p_input->i_pts_delay = val.i_int * 1000;
230
231     return VLC_SUCCESS;
232 }
233
234 /*****************************************************************************
235  * AccessClose:
236  *****************************************************************************/
237 static void AccessClose( vlc_object_t *p_this )
238 {
239     input_thread_t *p_input = (input_thread_t *)p_this;
240     access_sys_t   *p_sys = p_input->p_access_data;
241
242     delete[] p_sys->p_sdp;
243     free( p_sys );
244 }
245
246 /*****************************************************************************
247  * Read:
248  *****************************************************************************/
249 static ssize_t Read ( input_thread_t *p_input, byte_t *p_buffer, size_t i_len )
250 {
251     access_sys_t   *p_sys   = p_input->p_access_data;
252     int            i_copy = __MIN( (int)i_len, p_sys->i_sdp - p_sys->i_pos );
253
254     if( i_copy > 0 )
255     {
256         memcpy( p_buffer, &p_sys->p_sdp[p_sys->i_pos], i_copy );
257         p_sys->i_pos += i_copy;
258     }
259     return i_copy;
260 }
261
262
263 /*****************************************************************************
264  * DemuxOpen:
265  *****************************************************************************/
266 static int  DemuxOpen ( vlc_object_t *p_this )
267 {
268     input_thread_t *p_input = (input_thread_t *)p_this;
269     demux_sys_t    *p_sys;
270
271     MediaSubsessionIterator *iter;
272     MediaSubsession *sub;
273
274     vlc_value_t val;
275
276     uint8_t *p_peek;
277
278     int     i_sdp;
279     int     i_sdp_max;
280     uint8_t *p_sdp;
281
282     /* See if it looks like a SDP
283        v, o, s fields are mandatory and in this order */
284     if( stream_Peek( p_input->s, &p_peek, 7 ) < 7 )
285     {
286         msg_Err( p_input, "cannot peek" );
287         return VLC_EGENERIC;
288     }
289     if( strncmp( (char*)p_peek, "v=0\r\n", 5 ) && strncmp( (char*)p_peek, "v=0\n", 4 ) &&
290         ( p_input->psz_access == NULL || strcasecmp( p_input->psz_access, "rtsp" ) ||
291           p_peek[0] < 'a' || p_peek[0] > 'z' || p_peek[1] != '=' ) )
292     {
293         msg_Warn( p_input, "SDP module discarded" );
294         return VLC_EGENERIC;
295     }
296
297     p_input->pf_demux = Demux;
298     p_input->pf_demux_control = Control;
299     p_input->p_demux_data = p_sys = (demux_sys_t*)malloc( sizeof( demux_sys_t ) );
300     p_sys->p_sdp = NULL;
301     p_sys->scheduler = NULL;
302     p_sys->env = NULL;
303     p_sys->ms = NULL;
304     p_sys->rtsp = NULL;
305     p_sys->i_track = 0;
306     p_sys->track   = NULL;
307     p_sys->i_pcr   = 0;
308     p_sys->i_pcr_start = 0;
309
310     /* Gather the complete sdp file */
311     i_sdp = 0;
312     i_sdp_max = 1000;
313     p_sdp = (uint8_t*)malloc( i_sdp_max );
314     for( ;; )
315     {
316         int i_read = stream_Read( p_input->s, &p_sdp[i_sdp], i_sdp_max - i_sdp - 1 );
317
318         if( i_read < 0 )
319         {
320             msg_Err( p_input, "failed to read SDP" );
321             free( p_sys );
322             return VLC_EGENERIC;
323         }
324
325         i_sdp += i_read;
326
327         if( i_read < i_sdp_max - i_sdp - 1 )
328         {
329             p_sdp[i_sdp] = '\0';
330             break;
331         }
332
333         i_sdp_max += 1000;
334         p_sdp = (uint8_t*)realloc( p_sdp, i_sdp_max );
335     }
336     p_sys->p_sdp = (char*)p_sdp;
337
338     fprintf( stderr, "sdp=%s\n", p_sys->p_sdp );
339
340     if( ( p_sys->scheduler = BasicTaskScheduler::createNew() ) == NULL )
341     {
342         msg_Err( p_input, "BasicTaskScheduler::createNew failed" );
343         goto error;
344     }
345     if( ( p_sys->env = BasicUsageEnvironment::createNew(*p_sys->scheduler) ) == NULL )
346     {
347         msg_Err( p_input, "BasicUsageEnvironment::createNew failed" );
348         goto error;
349     }
350     if( p_input->psz_access != NULL && !strcasecmp( p_input->psz_access, "rtsp" ) )
351     {
352         char *psz_url;
353         char *psz_options;
354
355         if( ( p_sys->rtsp = RTSPClient::createNew(*p_sys->env, 1/*verbose*/, "VLC Media Player" ) ) == NULL )
356         {
357             msg_Err( p_input, "RTSPClient::createNew failed (%s)", p_sys->env->getResultMsg() );
358             goto error;
359         }
360         psz_url = (char*)malloc( strlen( p_input->psz_name ) + 8 );
361         sprintf( psz_url, "rtsp://%s", p_input->psz_name );
362
363         psz_options = p_sys->rtsp->sendOptionsCmd( psz_url );
364         /* FIXME psz_options -> delete or free */
365         free( psz_url );
366     }
367     if( ( p_sys->ms = MediaSession::createNew(*p_sys->env, p_sys->p_sdp ) ) == NULL )
368     {
369         msg_Err( p_input, "MediaSession::createNew failed" );
370         goto error;
371     }
372
373     var_Create( p_input, "rtsp-tcp", VLC_VAR_BOOL|VLC_VAR_DOINHERIT );
374     var_Get( p_input, "rtsp-tcp", &val );
375
376     /* Initialise each media subsession */
377     iter = new MediaSubsessionIterator( *p_sys->ms );
378     while( ( sub = iter->next() ) != NULL )
379     {
380         unsigned int i_buffer = 0;
381
382         /* Value taken from mplayer */
383         if( !strcmp( sub->mediumName(), "audio" ) )
384         {
385             i_buffer = 100000;
386         }
387         else if( !strcmp( sub->mediumName(), "video" ) )
388         {
389             i_buffer = 2000000;
390         }
391         else
392         {
393             continue;
394         }
395
396         if( !sub->initiate() )
397         {
398             msg_Warn( p_input, "RTP subsession '%s/%s' failed(%s)", sub->mediumName(), sub->codecName(), p_sys->env->getResultMsg() );
399         }
400         else
401         {
402             int fd = sub->rtpSource()->RTPgs()->socketNum();
403
404             msg_Warn( p_input, "RTP subsession '%s/%s'", sub->mediumName(), sub->codecName() );
405
406             /* Increase the buffer size */
407             increaseReceiveBufferTo( *p_sys->env, fd, i_buffer );
408             /* Issue the SETUP */
409             if( p_sys->rtsp )
410             {
411                 p_sys->rtsp->setupMediaSubsession( *sub, False, val.b_bool ? True : False );
412             }
413         }
414     }
415
416     if( p_sys->rtsp )
417     {
418         /* The PLAY */
419         if( !p_sys->rtsp->playMediaSession( *p_sys->ms ) )
420         {
421             msg_Err( p_input, "PLAY failed %s", p_sys->env->getResultMsg() );
422             goto error;
423         }
424     }
425
426     /* Create all es struct */
427     iter->reset();
428     while( ( sub = iter->next() ) != NULL )
429     {
430         live_track_t *tk;
431
432         if( sub->readSource() == NULL )
433         {
434             continue;
435         }
436
437         tk = (live_track_t*)malloc( sizeof( live_track_t ) );
438         tk->p_input = p_input;
439         tk->waiting = 0;
440         tk->i_pts   = 0;
441
442         /* Value taken from mplayer */
443         if( !strcmp( sub->mediumName(), "audio" ) )
444         {
445             es_format_Init( &tk->fmt, AUDIO_ES, VLC_FOURCC( 'u', 'n', 'd', 'f' ) );
446             tk->fmt.audio.i_channels = sub->numChannels();
447             tk->fmt.audio.i_samplerate = sub->rtpSource()->timestampFrequency();
448
449             if( !strcmp( sub->codecName(), "MPA" ) ||
450                 !strcmp( sub->codecName(), "MPA-ROBUST" ) ||
451                 !strcmp( sub->codecName(), "X-MP3-DRAFT-00" ) )
452             {
453                 tk->fmt.i_codec = VLC_FOURCC( 'm', 'p', 'g', 'a' );
454                 tk->fmt.audio.i_samplerate = 0;
455             }
456             else if( !strcmp( sub->codecName(), "AC3" ) )
457             {
458                 tk->fmt.i_codec = VLC_FOURCC( 'a', '5', '2', ' ' );
459                 tk->fmt.audio.i_samplerate = 0;
460             }
461             else if( !strcmp( sub->codecName(), "L16" ) )
462             {
463                 tk->fmt.i_codec = VLC_FOURCC( 't', 'w', 'o', 's' );
464                 tk->fmt.audio.i_bitspersample = 16;
465             }
466             else if( !strcmp( sub->codecName(), "L8" ) )
467             {
468                 tk->fmt.i_codec = VLC_FOURCC( 'a', 'r', 'a', 'w' );
469                 tk->fmt.audio.i_bitspersample = 8;
470             }
471             else if( !strcmp( sub->codecName(), "PCMU" ) )
472             {
473                 tk->fmt.i_codec = VLC_FOURCC( 'u', 'l', 'a', 'w' );
474             }
475             else if( !strcmp( sub->codecName(), "PCMA" ) )
476             {
477                 tk->fmt.i_codec = VLC_FOURCC( 'a', 'l', 'a', 'w' );
478             }
479             else if( !strcmp( sub->codecName(), "MP4A-LATM" ) )
480             {
481                 unsigned int i_extra;
482                 uint8_t      *p_extra;
483
484                 tk->fmt.i_codec = VLC_FOURCC( 'm', 'p', '4', 'a' );
485
486                 if( ( p_extra = parseStreamMuxConfigStr( sub->fmtp_config(), i_extra ) ) )
487                 {
488                     tk->fmt.i_extra_type = ES_EXTRA_TYPE_WAVEFORMATEX;
489                     tk->fmt.i_extra = i_extra;
490                     tk->fmt.p_extra = malloc( sizeof( i_extra ) );
491                     memcpy( tk->fmt.p_extra, p_extra, i_extra );
492                     delete[] p_extra;
493                 }
494             }
495             else if( !strcmp( sub->codecName(), "MPEG4-GENERIC" ) )
496             {
497                 unsigned int i_extra;
498                 uint8_t      *p_extra;
499
500                 tk->fmt.i_codec = VLC_FOURCC( 'm', 'p', '4', 'a' );
501
502                 if( ( p_extra = parseGeneralConfigStr( sub->fmtp_config(), i_extra ) ) )
503                 {
504                     tk->fmt.i_extra_type = ES_EXTRA_TYPE_WAVEFORMATEX;
505                     tk->fmt.i_extra = i_extra;
506                     tk->fmt.p_extra = malloc( i_extra );
507                     memcpy( tk->fmt.p_extra, p_extra, i_extra );
508                     delete[] p_extra;
509                 }
510             }
511         }
512         else if( !strcmp( sub->mediumName(), "video" ) )
513         {
514             es_format_Init( &tk->fmt, VIDEO_ES, VLC_FOURCC( 'u', 'n', 'd', 'f' ) );
515             if( !strcmp( sub->codecName(), "MPV" ) )
516             {
517                 tk->fmt.i_codec = VLC_FOURCC( 'm', 'p', 'g', 'v' );
518             }
519             else if( !strcmp( sub->codecName(), "H263" ) ||
520                      !strcmp( sub->codecName(), "H263-1998" ) )
521             {
522                 tk->fmt.i_codec = VLC_FOURCC( 'h', '2', '6', '3' );
523             }
524             else if( !strcmp( sub->codecName(), "H261" ) )
525             {
526                 tk->fmt.i_codec = VLC_FOURCC( 'h', '2', '6', '1' );
527             }
528             else if( !strcmp( sub->codecName(), "JPEG" ) )
529             {
530                 tk->fmt.i_codec = VLC_FOURCC( 'J', 'P', 'E', 'G' );
531             }
532             else if( !strcmp( sub->codecName(), "MP4V-ES" ) )
533             {
534                 unsigned int i_extra;
535                 uint8_t      *p_extra;
536
537                 tk->fmt.i_codec = VLC_FOURCC( 'm', 'p', '4', 'v' );
538
539                 if( ( p_extra = parseGeneralConfigStr( sub->fmtp_config(), i_extra ) ) )
540                 {
541                     tk->fmt.i_extra_type = ES_EXTRA_TYPE_BITMAPINFOHEADER;
542                     tk->fmt.i_extra = i_extra;
543                     tk->fmt.p_extra = malloc( i_extra );
544                     memcpy( tk->fmt.p_extra, p_extra, i_extra );
545                     delete[] p_extra;
546                 }
547             }
548         }
549
550         if( tk->fmt.i_codec != VLC_FOURCC( 'u', 'n', 'd', 'f' ) )
551         {
552             tk->p_es = es_out_Add( p_input->p_es_out, &tk->fmt );
553         }
554
555         if( tk->p_es )
556         {
557             TAB_APPEND( p_sys->i_track, (void**)p_sys->track, (void*)tk );
558             tk->readSource = sub->readSource();
559         }
560         else
561         {
562             free( tk );
563         }
564     }
565
566
567     delete iter;
568
569     return VLC_SUCCESS;
570
571 error:
572     if( p_sys->ms )
573     {
574         Medium::close( p_sys->ms );
575     }
576     if( p_sys->rtsp )
577     {
578         Medium::close( p_sys->rtsp );
579     }
580     if( p_sys->env )
581     {
582         delete p_sys->env;
583     }
584     if( p_sys->scheduler )
585     {
586         delete p_sys->scheduler;
587     }
588     if( p_sys->p_sdp )
589     {
590         free( p_sys->p_sdp );
591     }
592     free( p_sys );
593     return VLC_EGENERIC;
594 }
595
596
597
598 /*****************************************************************************
599  * DemuxClose:
600  *****************************************************************************/
601 static void DemuxClose( vlc_object_t *p_this )
602 {
603     input_thread_t *p_input = (input_thread_t *)p_this;
604     demux_sys_t    *p_sys = p_input->p_demux_data;
605     int            i;
606
607     for( i = 0; i < p_sys->i_track; i++ )
608     {
609         live_track_t *tk = p_sys->track[i];
610
611         free( tk );
612     }
613     if( p_sys->i_track )
614     {
615         free( p_sys->track );
616     }
617
618     if( p_sys->rtsp && p_sys->ms )
619     {
620         /* TEARDOWN */
621         p_sys->rtsp->teardownMediaSession( *p_sys->ms );
622     }
623     Medium::close( p_sys->ms );
624     if( p_sys->rtsp )
625     {
626         Medium::close( p_sys->rtsp );
627     }
628
629     if( p_sys->env )
630     {
631         delete p_sys->env;
632     }
633     if( p_sys->scheduler )
634     {
635         delete p_sys->scheduler;
636     }
637     if( p_sys->p_sdp )
638     {
639         free( p_sys->p_sdp );
640     }
641     free( p_sys );
642 }
643
644
645 static void StreamRead( void *p_private, unsigned int i_size, struct timeval pts );
646 static void StreamClose( void *p_private );
647 static void TaskInterrupt( void *p_private );
648
649 /*****************************************************************************
650  * Demux:
651  *****************************************************************************/
652 static int  Demux   ( input_thread_t *p_input )
653 {
654     demux_sys_t    *p_sys = p_input->p_demux_data;
655     TaskToken      task;
656
657     mtime_t         i_pcr = 0;
658     int             i;
659
660     for( i = 0; i < p_sys->i_track; i++ )
661     {
662         live_track_t *tk = p_sys->track[i];
663
664         if( i_pcr == 0 )
665         {
666             i_pcr = tk->i_pts;
667         }
668         else if( tk->i_pts != 0 && i_pcr > tk->i_pts )
669         {
670             i_pcr = tk->i_pts ;
671         }
672     }
673     if( i_pcr != p_sys->i_pcr )
674     {
675         input_ClockManageRef( p_input,
676                               p_input->stream.p_selected_program,
677                               i_pcr * 9 / 100 );
678         p_sys->i_pcr = i_pcr;
679         if( p_sys->i_pcr_start <= 0 || p_sys->i_pcr_start > i_pcr )
680         {
681             p_sys->i_pcr_start = i_pcr;
682         }
683     }
684
685     /* First warm we want to read data */
686     p_sys->event = 0;
687     for( i = 0; i < p_sys->i_track; i++ )
688     {
689         live_track_t *tk = p_sys->track[i];
690
691         if( tk->waiting == 0 )
692         {
693             tk->waiting = 1;
694             tk->readSource->getNextFrame( tk->buffer, 65536,
695                                           StreamRead, tk,
696                                           StreamClose, tk );
697         }
698     }
699     /* Create a task that will be called if we wait more than 300ms */
700     task = p_sys->scheduler->scheduleDelayedTask( 300000, TaskInterrupt, p_input );
701
702     /* Do the read */
703     p_sys->scheduler->doEventLoop( &p_sys->event );
704
705     /* remove the task */
706     p_sys->scheduler->unscheduleDelayedTask( task );
707
708     return p_input->b_error ? 0 : 1;
709 }
710
711 static int    Control( input_thread_t *p_input, int i_query, va_list args )
712 {
713     demux_sys_t *p_sys = p_input->p_demux_data;
714     int64_t *pi64;
715
716     switch( i_query )
717     {
718         case DEMUX_GET_TIME:
719             pi64 = (int64_t*)va_arg( args, int64_t * );
720             *pi64 = p_sys->i_pcr - p_sys->i_pcr_start;
721             return VLC_SUCCESS;
722
723         default:
724             return demux_vaControlDefault( p_input, i_query, args );
725     }
726 }
727
728 /*****************************************************************************
729  *
730  *****************************************************************************/
731 static void StreamRead( void *p_private, unsigned int i_size, struct timeval pts )
732 {
733     live_track_t   *tk = (live_track_t*)p_private;
734     input_thread_t *p_input = tk->p_input;
735     demux_sys_t    *p_sys = p_input->p_demux_data;
736     pes_packet_t   *p_pes;
737     data_packet_t  *p_data;
738
739     mtime_t        i_pts = (mtime_t)pts.tv_sec * 1000000LL + (mtime_t)pts.tv_usec;
740
741 #if 0
742     fprintf( stderr, "StreamRead size=%d pts=%lld\n",
743              i_size,
744              pts.tv_sec * 1000000LL + pts.tv_usec );
745 #endif
746     /* Create a PES */
747     if( ( p_pes = input_NewPES( p_input->p_method_data ) ) == NULL )
748     {
749         return;
750     }
751     /* FIXME could i_size be > buffer size ? */
752     p_data = input_NewPacket( p_input->p_method_data, i_size );
753
754     memcpy( p_data->p_payload_start, tk->buffer, i_size );
755     p_data->p_payload_end = p_data->p_payload_start + i_size;
756
757     p_pes->p_first = p_pes->p_last = p_data;
758     p_pes->i_nb_data = 1;
759     p_pes->i_pes_size = i_size;
760     p_pes->i_rate = p_input->stream.control.i_rate;
761
762     if( i_pts != tk->i_pts )
763     {
764         p_pes->i_dts =
765         p_pes->i_pts = input_ClockGetTS( p_input,
766                                          p_input->stream.p_selected_program,
767                                          i_pts * 9 / 100 );
768     }
769     else
770     {
771         p_pes->i_dts = 0;
772         p_pes->i_pts = 0;
773     }
774     //fprintf( stderr, "tk -> dpts=%lld\n", i_pts - tk->i_pts );
775
776     es_out_Send( p_input->p_es_out, tk->p_es, p_pes );
777
778     /* warm that's ok */
779     p_sys->event = 0xff;
780
781     /* we have read data */
782     tk->waiting = 0;
783
784     tk->i_pts = i_pts;
785 }
786
787 /*****************************************************************************
788  *
789  *****************************************************************************/
790 static void StreamClose( void *p_private )
791 {
792     live_track_t   *tk = (live_track_t*)p_private;
793     input_thread_t *p_input = tk->p_input;
794     demux_sys_t    *p_sys = p_input->p_demux_data;
795
796     fprintf( stderr, "StreamClose\n" );
797
798     p_sys->event = 0xff;
799     p_input->b_error = VLC_TRUE;
800 }
801
802
803 /*****************************************************************************
804  *
805  *****************************************************************************/
806 static void TaskInterrupt( void *p_private )
807 {
808     input_thread_t *p_input = (input_thread_t*)p_private;
809
810     fprintf( stderr, "TaskInterrupt\n" );
811
812     /* Avoid lock */
813     p_input->p_demux_data->event = 0xff;
814 }
815