]> git.sesse.net Git - vlc/blob - src/input/input.c
9fa1a742dc2d3664fc0b1b19f8b4d3961f7e2817
[vlc] / src / input / input.c
1 /*****************************************************************************
2  * input.c: input thread
3  * Read a stream, demultiplex and parse it before sending it to
4  * decoders.
5  *****************************************************************************
6  * Copyright (C) 1998-2004 VideoLAN
7  * $Id$
8  *
9  * Authors: Christophe Massiot <massiot@via.ecp.fr>
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., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
24  *****************************************************************************/
25
26 /*****************************************************************************
27  * Preamble
28  *****************************************************************************/
29 #include <stdlib.h>
30
31 #include <vlc/vlc.h>
32 #include <vlc/input.h>
33 #include <vlc/decoder.h>
34 #include <vlc/vout.h>
35
36 #ifdef HAVE_SYS_TIMES_H
37 #   include <sys/times.h>
38 #endif
39
40 #include "vlc_playlist.h"
41
42 #include "stream_output.h"
43
44 #include "vlc_interface.h"
45 #include "codecs.h"
46 #include "vlc_meta.h"
47 #include "../../modules/demux/util/sub.h"
48
49 /*****************************************************************************
50  * Local prototypes
51  *****************************************************************************/
52 struct input_thread_sys_t
53 {
54     /* subtitles */
55     int              i_sub;
56     subtitle_demux_t **sub;
57
58     int64_t          i_stop_time;
59 };
60
61 static  int RunThread       ( input_thread_t *p_input );
62 static  int InitThread      ( input_thread_t *p_input );
63 static void ErrorThread     ( input_thread_t *p_input );
64 static void EndThread       ( input_thread_t *p_input );
65
66 static void ParseOption     ( input_thread_t *p_input,
67                               const char *psz_option );
68
69 /*****************************************************************************
70  * Callbacks
71  *****************************************************************************/
72 static int PositionCallback( vlc_object_t *p_this, char const *psz_cmd,
73                              vlc_value_t oldval, vlc_value_t newval, void *p_data );
74 static int TimeCallback    ( vlc_object_t *p_this, char const *psz_cmd,
75                              vlc_value_t oldval, vlc_value_t newval, void *p_data );
76 static int StateCallback   ( vlc_object_t *p_this, char const *psz_cmd,
77                              vlc_value_t oldval, vlc_value_t newval, void *p_data );
78 static int RateCallback    ( vlc_object_t *p_this, char const *psz_cmd,
79                              vlc_value_t oldval, vlc_value_t newval, void *p_data );
80
81 /*****************************************************************************
82  * input_CreateThread: creates a new input thread
83  *****************************************************************************
84  * This function creates a new input, and returns a pointer
85  * to its description. On error, it returns NULL.
86  *****************************************************************************/
87 input_thread_t *__input_CreateThread( vlc_object_t *p_parent, char *psz_uri,
88                                       char **ppsz_options, int i_options )
89
90 {
91     input_thread_t *    p_input;                        /* thread descriptor */
92     vlc_value_t val;
93     int i;
94
95     /* Allocate descriptor */
96     p_input = vlc_object_create( p_parent, VLC_OBJECT_INPUT );
97     if( p_input == NULL )
98     {
99         msg_Err( p_parent, "out of memory" );
100         return NULL;
101     }
102
103     /* Parse input options */
104     for( i = 0; i < i_options; i++ )
105     {
106         msg_Dbg( p_input, "option: %s", ppsz_options[i] );
107         ParseOption( p_input, ppsz_options[i] );
108     }
109
110     /* Create a few object variables we'll need later on */
111     var_Create( p_input, "video", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
112     var_Create( p_input, "audio", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
113     var_Create( p_input, "audio-channel", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
114     var_Create( p_input, "spu-channel", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
115     var_Create( p_input, "sub-file", VLC_VAR_FILE | VLC_VAR_DOINHERIT );
116     var_Create( p_input, "sub-autodetect-file", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
117     var_Create( p_input, "sub-autodetect-fuzzy", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
118
119     var_Create( p_input, "sout", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
120     var_Create( p_input, "sout-all",   VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
121     var_Create( p_input, "sout-audio", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
122     var_Create( p_input, "sout-video", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
123     var_Create( p_input, "sout-keep",  VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
124
125     /* repeat variable */
126     var_Create( p_input, "input-repeat", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
127
128     /* start/stop time */
129     var_Create( p_input, "start-time", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
130     var_Create( p_input, "stop-time", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
131
132     /* decoders */
133     var_Create( p_input, "minimize-threads", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
134
135     /* play status */
136
137     /* position variable */
138     var_Create( p_input, "position",  VLC_VAR_FLOAT );  /* position 0.0->1.0 */
139     var_Create( p_input, "position-offset",  VLC_VAR_FLOAT );  /* relative */
140     val.f_float = 0.0;
141     var_Change( p_input, "position", VLC_VAR_SETVALUE, &val, NULL );
142     var_AddCallback( p_input, "position", PositionCallback, NULL );
143     var_AddCallback( p_input, "position-offset", PositionCallback, NULL );
144
145     /* time variable */
146     var_Create( p_input, "time",  VLC_VAR_TIME );
147     var_Create( p_input, "time-offset",  VLC_VAR_TIME );    /* relative */
148     val.i_time = 0;
149     var_Change( p_input, "time", VLC_VAR_SETVALUE, &val, NULL );
150     var_AddCallback( p_input, "time", TimeCallback, NULL );
151     var_AddCallback( p_input, "time-offset", TimeCallback, NULL );
152
153     /* length variable */
154     var_Create( p_input, "length",  VLC_VAR_TIME );
155     val.i_time = 0;
156     var_Change( p_input, "length", VLC_VAR_SETVALUE, &val, NULL );
157
158     /* rate variable */
159     var_Create( p_input, "rate", VLC_VAR_INTEGER );
160     var_Create( p_input, "rate-slower", VLC_VAR_VOID );
161     var_Create( p_input, "rate-faster", VLC_VAR_VOID );
162     val.i_int = DEFAULT_RATE;
163     var_Change( p_input, "rate", VLC_VAR_SETVALUE, &val, NULL );
164     var_AddCallback( p_input, "rate", RateCallback, NULL );
165     var_AddCallback( p_input, "rate-slower", RateCallback, NULL );
166     var_AddCallback( p_input, "rate-faster", RateCallback, NULL );
167
168     /* state variable */
169     var_Create( p_input, "state", VLC_VAR_INTEGER );
170     val.i_int = INIT_S;
171     var_Change( p_input, "state", VLC_VAR_SETVALUE, &val, NULL );
172     var_AddCallback( p_input, "state", StateCallback, NULL );
173
174     /* state variable */
175     var_Create( p_input, "demuxed-id3", VLC_VAR_BOOL );
176     val.b_bool = VLC_FALSE;
177     var_Change( p_input, "demuxed-id3", VLC_VAR_SETVALUE, &val, NULL );
178
179     /* Initialize thread properties */
180     p_input->b_eof      = 0;
181     p_input->p_sys      = NULL;
182
183     /* Set target */
184     p_input->psz_source = strdup( psz_uri );
185
186     /* Stream */
187     p_input->s = NULL;
188
189     /* es out */
190     p_input->p_es_out = NULL;
191
192     /* Demux */
193     p_input->p_demux   = NULL;
194     p_input->pf_demux  = NULL;
195     p_input->pf_rewind = NULL;
196     p_input->pf_demux_control = NULL;
197     p_input->i_cr_average = config_GetInt( p_input, "cr-average" );
198
199     /* Access */
200     p_input->p_access = NULL;
201
202     p_input->i_bufsize = 0;
203     p_input->i_mtu = 0;
204     p_input->i_pts_delay = DEFAULT_PTS_DELAY;
205
206     /* Initialize statistics */
207     p_input->c_loops                    = 0;
208     p_input->stream.c_packets_read      = 0;
209     p_input->stream.c_packets_trashed   = 0;
210
211     /* Set locks. */
212     vlc_mutex_init( p_input, &p_input->stream.stream_lock );
213     vlc_cond_init( p_input, &p_input->stream.stream_wait );
214     vlc_mutex_init( p_input, &p_input->stream.control.control_lock );
215
216     /* Initialize stream description */
217     p_input->stream.b_changed = 0;
218     p_input->stream.i_es_number = 0;
219     p_input->stream.i_selected_es_number = 0;
220     p_input->stream.i_pgrm_number = 0;
221     p_input->stream.i_new_status = p_input->stream.i_new_rate = 0;
222     p_input->stream.b_new_mute = MUTE_NO_CHANGE;
223     p_input->stream.i_mux_rate = 0;
224     p_input->stream.b_seekable = 0;
225     p_input->stream.p_sout = NULL;
226
227     /* no stream, no program, no area, no es */
228     p_input->stream.p_new_program = NULL;
229
230     p_input->stream.i_area_nb = 0;
231     p_input->stream.pp_areas = NULL;
232     p_input->stream.p_selected_area = NULL;
233     p_input->stream.p_new_area = NULL;
234
235     p_input->stream.pp_selected_es = NULL;
236     p_input->stream.p_removed_es = NULL;
237     p_input->stream.p_newly_selected_es = NULL;
238
239     /* By default there is one area in a stream */
240     input_AddArea( p_input, 0, 1 );
241     p_input->stream.p_selected_area = p_input->stream.pp_areas[0];
242
243     /* Initialize stream control properties. */
244     p_input->stream.control.i_status = INIT_S;
245     p_input->stream.control.i_rate = DEFAULT_RATE;
246     p_input->stream.control.b_mute = 0;
247     p_input->stream.control.b_grayscale = config_GetInt( p_input, "grayscale");
248
249     msg_Info( p_input, "playlist item `%s'", p_input->psz_source );
250
251     /* Initialize input info */
252     p_input->stream.p_info = NULL;
253     p_input->stream.p_info = input_InfoCategory( p_input, _("General") );
254     input_AddInfo( p_input->stream.p_info, _("Playlist Item"),
255                    p_input->psz_source );
256     vlc_object_attach( p_input, p_parent );
257
258     /* Create thread and wait for its readiness. */
259     if( vlc_thread_create( p_input, "input", RunThread,
260                            VLC_THREAD_PRIORITY_INPUT, VLC_TRUE ) )
261     {
262         msg_Err( p_input, "cannot create input thread" );
263         input_DelInfo( p_input );
264         free( p_input );
265         return NULL;
266     }
267
268     return p_input;
269 }
270
271 /*****************************************************************************
272  * input_StopThread: mark an input thread as zombie
273  *****************************************************************************
274  * This function should not return until the thread is effectively cancelled.
275  *****************************************************************************/
276 void input_StopThread( input_thread_t *p_input )
277 {
278     /* Make the thread exit from a possible vlc_cond_wait() */
279     vlc_mutex_lock( &p_input->stream.stream_lock );
280     /* Request thread destruction */
281     p_input->b_die = 1;
282
283     vlc_cond_signal( &p_input->stream.stream_wait );
284     vlc_mutex_unlock( &p_input->stream.stream_lock );
285 }
286
287 /*****************************************************************************
288  * input_DestroyThread: mark an input thread as zombie
289  *****************************************************************************
290  * This function should not return until the thread is effectively cancelled.
291  *****************************************************************************/
292 void input_DestroyThread( input_thread_t *p_input )
293 {
294     /* Join the thread */
295     vlc_thread_join( p_input );
296
297     /* Destroy Mutex locks */
298     vlc_mutex_destroy( &p_input->stream.control.control_lock );
299     vlc_cond_destroy( &p_input->stream.stream_wait );
300     vlc_mutex_destroy( &p_input->stream.stream_lock );
301 }
302
303 /*****************************************************************************
304  * RunThread: main thread loop
305  *****************************************************************************
306  * Thread in charge of processing the network packets and demultiplexing.
307  *****************************************************************************/
308 static int RunThread( input_thread_t *p_input )
309 {
310     vlc_value_t  val;
311     mtime_t      i_update_next = -1;
312
313     /* Signal right now, otherwise we'll get stuck in a peek */
314     vlc_thread_ready( p_input );
315
316     if( InitThread( p_input ) )
317     {
318         /* If we failed, wait before we are killed, and exit */
319         p_input->b_error = 1;
320
321         ErrorThread( p_input );
322
323         /* Tell we're dead */
324         p_input->b_dead = 1;
325
326         input_DelInfo( p_input );
327
328         return 0;
329     }
330
331     /* initialization is complete */
332     vlc_mutex_lock( &p_input->stream.stream_lock );
333     p_input->stream.b_changed        = 1;
334     p_input->stream.control.i_status = PLAYING_S;
335     vlc_mutex_unlock( &p_input->stream.stream_lock );
336
337     val.i_int = PLAYING_S;
338     var_Change( p_input, "state", VLC_VAR_SETVALUE, &val, NULL );
339
340     while( !p_input->b_die && !p_input->b_error && !p_input->b_eof )
341     {
342         unsigned int i, i_count;
343
344         p_input->c_loops++;
345
346         vlc_mutex_lock( &p_input->stream.stream_lock );
347
348         if( p_input->stream.p_new_program )
349         {
350             if( p_input->pf_set_program != NULL )
351             {
352
353                 /* Reinitialize buffer manager. */
354                 input_AccessReinit( p_input );
355
356                 p_input->pf_set_program( p_input,
357                                          p_input->stream.p_new_program );
358
359                 /* Escape all decoders for the stream discontinuity they
360                  * will encounter. */
361                 input_EscapeDiscontinuity( p_input );
362
363                 for( i = 0; i < p_input->stream.i_pgrm_number; i++ )
364                 {
365                     pgrm_descriptor_t * p_pgrm
366                                             = p_input->stream.pp_programs[i];
367
368                     /* Reinitialize synchro. */
369                     p_pgrm->i_synchro_state = SYNCHRO_REINIT;
370                 }
371             }
372             p_input->stream.p_new_program = NULL;
373         }
374
375         if( p_input->stream.p_new_area )
376         {
377             if( p_input->stream.b_seekable && p_input->pf_set_area != NULL )
378             {
379                 input_AccessReinit( p_input );
380
381                 p_input->pf_set_area( p_input, p_input->stream.p_new_area );
382
383                 /* Escape all decoders for the stream discontinuity they
384                  * will encounter. */
385                 input_EscapeDiscontinuity( p_input );
386
387                 for( i = 0; i < p_input->stream.i_pgrm_number; i++ )
388                 {
389                     pgrm_descriptor_t * p_pgrm
390                                             = p_input->stream.pp_programs[i];
391
392                     /* Reinitialize synchro. */
393                     p_pgrm->i_synchro_state = SYNCHRO_REINIT;
394                 }
395             }
396             p_input->stream.p_new_area = NULL;
397         }
398
399         if( p_input->stream.p_selected_area->i_seek != NO_SEEK )
400         {
401             if( p_input->stream.p_selected_area->i_size > 0 )
402             {
403                 unsigned int i;
404                 mtime_t      i_time;
405                 double f = (double)p_input->stream.p_selected_area->i_seek /
406                            (double)p_input->stream.p_selected_area->i_size;
407
408                 vlc_mutex_unlock( &p_input->stream.stream_lock );
409                 demux_Control( p_input, DEMUX_SET_POSITION, f );
410                 vlc_mutex_lock( &p_input->stream.stream_lock );
411
412                 /* Escape all decoders for the stream discontinuity they
413                  * will encounter. */
414                 input_EscapeDiscontinuity( p_input );
415
416                 for( i = 0; i < p_input->stream.i_pgrm_number; i++ )
417                 {
418                     pgrm_descriptor_t * p_pgrm=p_input->stream.pp_programs[i];
419
420                     /* Reinitialize synchro. */
421                     p_pgrm->i_synchro_state = SYNCHRO_REINIT;
422                 }
423
424                 vlc_mutex_unlock( &p_input->stream.stream_lock );
425                 if( !demux_Control( p_input, DEMUX_GET_TIME, &i_time ) )
426                 {
427                     int i;
428                     vlc_value_t val;
429
430                     /* Help in bar display */
431                     val.i_time = i_time;
432                     var_Change( p_input, "time", VLC_VAR_SETVALUE, &val, NULL );
433
434                     /* Seek subs */
435                     for( i = 0; i < p_input->p_sys->i_sub; i++ )
436                     {
437                         subtitle_Seek( p_input->p_sys->sub[i], i_time );
438                     }
439                 }
440                 vlc_mutex_lock( &p_input->stream.stream_lock );
441             }
442             p_input->stream.p_selected_area->i_seek = NO_SEEK;
443         }
444
445         if( p_input->stream.p_removed_es )
446         {
447             input_UnselectES( p_input, p_input->stream.p_removed_es );
448             p_input->stream.p_removed_es = NULL;
449         }
450
451         if( p_input->stream.p_newly_selected_es )
452         {
453             input_SelectES( p_input, p_input->stream.p_newly_selected_es );
454             p_input->stream.p_newly_selected_es = NULL;
455         }
456
457         if( p_input->stream.b_new_mute != MUTE_NO_CHANGE )
458         {
459             if( p_input->stream.b_new_mute )
460             {
461                 input_EscapeAudioDiscontinuity( p_input );
462             }
463
464             vlc_mutex_lock( &p_input->stream.control.control_lock );
465             p_input->stream.control.b_mute = p_input->stream.b_new_mute;
466             vlc_mutex_unlock( &p_input->stream.control.control_lock );
467
468             p_input->stream.b_new_mute = MUTE_NO_CHANGE;
469         }
470
471         vlc_mutex_unlock( &p_input->stream.stream_lock );
472
473         /* Read and demultiplex some data. */
474         i_count = p_input->pf_demux( p_input );
475
476         if( i_count == 0 )
477         {
478             vlc_value_t repeat;
479
480             var_Get( p_input, "input-repeat", &repeat );
481             if( repeat.i_int == 0 || p_input->stream.i_area_nb <= 0 )
482             {
483                 /* End of file - we do not set b_die because only the
484                  * playlist is allowed to do so. */
485                 msg_Info( p_input, "EOF reached" );
486                 p_input->b_eof = 1;
487             }
488             else
489             {
490                 msg_Dbg( p_input, "repeating the same input (%d)", repeat.i_int );
491                 if( repeat.i_int > 0 )
492                 {
493                     repeat.i_int--;
494                     var_Set( p_input, "input-repeat", repeat );
495                 }
496
497                 p_input->stream.p_new_area = p_input->stream.pp_areas[0];
498                 p_input->stream.p_new_area->i_seek = 0;
499             }
500         }
501         else if( i_count < 0 )
502         {
503             p_input->b_error = 1;
504         }
505
506         if( !p_input->b_error && !p_input->b_eof && i_update_next < mdate() )
507         {
508             int i;
509             mtime_t i_time;
510             mtime_t i_length;
511             double  d_pos;
512
513             /* update input status variables */
514             if( !demux_Control( p_input, DEMUX_GET_POSITION, &d_pos ) )
515             {
516                 val.f_float = (float)d_pos;
517                 var_Change( p_input, "position", VLC_VAR_SETVALUE, &val, NULL );
518             }
519             if( !demux_Control( p_input, DEMUX_GET_TIME, &i_time ) )
520             {
521                 val.i_time = i_time;
522                 var_Change( p_input, "time", VLC_VAR_SETVALUE, &val, NULL );
523             }
524             if( !demux_Control( p_input, DEMUX_GET_LENGTH, &i_length ) )
525             {
526                 val.i_time = i_length;
527                 var_Change( p_input, "length", VLC_VAR_SETVALUE, &val, NULL );
528             }
529
530             /* Check stop-time */
531             if( p_input->p_sys->i_stop_time > 0 && p_input->p_sys->i_stop_time < i_time )
532             {
533                 msg_Warn( p_input, "EOF reached because of stop-time" );
534                 p_input->b_eof = 1;
535             }
536
537             /* update subs */
538             for( i = 0; i < p_input->p_sys->i_sub; i++ )
539             {
540                 subtitle_Demux( p_input->p_sys->sub[i], i_time );
541             }
542
543             i_update_next = mdate() + I64C(150000);
544         }
545     }
546
547     if( p_input->b_error || p_input->b_eof )
548     {
549         ErrorThread( p_input );
550     }
551
552     EndThread( p_input );
553
554     return 0;
555 }
556
557 /*****************************************************************************
558  * InitThread: init the input Thread
559  *****************************************************************************/
560 static int InitThread( input_thread_t * p_input )
561 {
562     vlc_meta_t *meta;
563     float f_fps;
564     playlist_t *p_playlist;
565     mtime_t i_length;
566
567     /* Parse source string. Syntax : [[<access>][/<demux>]:][<source>] */
568     char * psz_parser = p_input->psz_dupsource = strdup(p_input->psz_source);
569     vlc_value_t val;
570     int64_t i_microsecondperframe;
571
572     subtitle_demux_t *p_sub_toselect = NULL;
573     char             *psz_sub_file = NULL;
574
575     /* Skip the plug-in names */
576     while( *psz_parser && *psz_parser != ':' )
577     {
578         psz_parser++;
579     }
580 #if defined( WIN32 ) || defined( UNDER_CE )
581     if( psz_parser - p_input->psz_dupsource == 1 )
582     {
583         msg_Warn( p_input, "drive letter %c: found in source string",
584                            p_input->psz_dupsource[0] ) ;
585         psz_parser = "";
586     }
587 #endif
588
589     if( !*psz_parser )
590     {
591         p_input->psz_access = p_input->psz_demux = "";
592         p_input->psz_name = p_input->psz_source;
593         free( p_input->psz_dupsource );
594         p_input->psz_dupsource = NULL;
595     }
596     else
597     {
598         *psz_parser++ = '\0';
599
600         /* let's skip '//' */
601         if( psz_parser[0] == '/' && psz_parser[1] == '/' )
602         {
603             psz_parser += 2 ;
604         }
605
606         p_input->psz_name = psz_parser ;
607
608         /* Come back to parse the access and demux plug-ins */
609         psz_parser = p_input->psz_dupsource;
610
611         if( !*psz_parser )
612         {
613             /* No access */
614             p_input->psz_access = "";
615         }
616         else if( *psz_parser == '/' )
617         {
618             /* No access */
619             p_input->psz_access = "";
620             psz_parser++;
621         }
622         else
623         {
624             p_input->psz_access = psz_parser;
625
626             while( *psz_parser && *psz_parser != '/' )
627             {
628                 psz_parser++;
629             }
630
631             if( *psz_parser == '/' )
632             {
633                 *psz_parser++ = '\0';
634             }
635         }
636
637         if( !*psz_parser )
638         {
639             /* No demux */
640             p_input->psz_demux = "";
641         }
642         else
643         {
644             p_input->psz_demux = psz_parser;
645         }
646     }
647
648     msg_Dbg( p_input, "access `%s', demux `%s', name `%s'",
649              p_input->psz_access, p_input->psz_demux, p_input->psz_name );
650
651     if( input_AccessInit( p_input ) == -1 )
652     {
653         free( p_input->psz_source );
654         if( p_input->psz_dupsource != NULL )
655         {
656             free( p_input->psz_dupsource );
657         }
658
659         return VLC_EGENERIC;
660     }
661
662     /* Initialize optional stream output. (before demuxer)*/
663     var_Get( p_input, "sout", &val );
664     if( val.psz_string != NULL )
665     {
666         if ( *val.psz_string && (p_input->stream.p_sout =
667              sout_NewInstance( p_input, val.psz_string )) == NULL )
668         {
669             msg_Err( p_input, "cannot start stream output instance, aborting" );
670             free( val.psz_string );
671
672             input_AccessEnd( p_input );
673             free( p_input->psz_source );
674             if( p_input->psz_dupsource != NULL )
675             {
676                 free( p_input->psz_dupsource );
677             }
678             return VLC_EGENERIC;
679         }
680         free( val.psz_string );
681     }
682
683     p_input->p_es_out = input_EsOutNew( p_input );
684     es_out_Control( p_input->p_es_out, ES_OUT_SET_ACTIVE, VLC_FALSE );
685     es_out_Control( p_input->p_es_out, ES_OUT_SET_MODE, ES_OUT_MODE_NONE );
686
687     /* Find and open appropriate access module */
688     p_input->p_access = module_Need( p_input, "access",
689                                      p_input->psz_access, VLC_TRUE );
690
691 #ifndef WIN32      /* Remove this gross hack from the win32 build as colons
692                     * are forbidden in filenames on Win32. */
693
694     /* Maybe we got something like: /Volumes/toto:titi/gabu.mpg */
695     if ( p_input->p_access == NULL
696           && (*p_input->psz_demux || *p_input->psz_access) )
697     {
698         p_input->psz_access = p_input->psz_demux = "";
699         p_input->psz_name = p_input->psz_source;
700         free( p_input->psz_dupsource);
701         p_input->psz_dupsource = NULL;
702
703         p_input->p_access = module_Need( p_input, "access",
704                                          p_input->psz_access, VLC_TRUE );
705     }
706 #endif
707
708     if( p_input->p_access == NULL )
709     {
710         msg_Err( p_input, "no suitable access module for `%s/%s://%s'",
711                  p_input->psz_access, p_input->psz_demux, p_input->psz_name );
712         if ( p_input->stream.p_sout != NULL )
713         {
714             sout_DeleteInstance( p_input->stream.p_sout );
715         }
716
717         input_AccessEnd( p_input );
718         free( p_input->psz_source );
719         if( p_input->psz_dupsource != NULL )
720         {
721             free( p_input->psz_dupsource );
722         }
723         input_EsOutDelete( p_input->p_es_out );
724         return VLC_EGENERIC;
725     }
726
727     /* Waiting for stream. */
728     if( p_input->i_mtu )
729     {
730         p_input->i_bufsize = p_input->i_mtu;
731     }
732     else
733     {
734         p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE;
735     }
736
737     /* If the desynchronisation requested by the user is < 0, we need to
738      * cache more data. */
739     var_Create( p_input, "audio-desync", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
740     var_Get( p_input, "audio-desync", &val );
741     if( val.i_int < 0 )
742         p_input->i_pts_delay -= (val.i_int * 1000);
743
744     if( p_input->p_current_data == NULL && p_input->pf_read != NULL )
745     {
746         while( !input_FillBuffer( p_input ) )
747         {
748             if( p_input->b_die || p_input->b_error || p_input->b_eof )
749             {
750                 module_Unneed( p_input, p_input->p_access );
751                 if ( p_input->stream.p_sout != NULL )
752                 {
753                     sout_DeleteInstance( p_input->stream.p_sout );
754                 }
755                 input_AccessEnd( p_input );
756                 free( p_input->psz_source );
757                 if( p_input->psz_dupsource != NULL )
758                 {
759                     free( p_input->psz_dupsource );
760                 }
761                 input_EsOutDelete( p_input->p_es_out );
762                 return VLC_EGENERIC;
763             }
764         }
765     }
766
767     /* Create the stream_t facilities */
768     p_input->s = input_StreamNew( p_input );
769     if( p_input->s == NULL )
770     {
771         /* should never occur yet */
772
773         msg_Err( p_input, "cannot create stream_t" );
774
775         module_Unneed( p_input, p_input->p_access );
776         if ( p_input->stream.p_sout != NULL )
777         {
778             sout_DeleteInstance( p_input->stream.p_sout );
779         }
780         input_AccessEnd( p_input );
781         free( p_input->psz_source );
782         if( p_input->psz_dupsource != NULL )
783         {
784             free( p_input->psz_dupsource );
785         }
786         input_EsOutDelete( p_input->p_es_out );
787         return VLC_EGENERIC;
788     }
789
790     /* Find and open appropriate demux module */
791     p_input->p_demux =
792         module_Need( p_input, "demux",
793                      (p_input->psz_demux && *p_input->psz_demux) ?
794                      p_input->psz_demux : "$demux",
795                      (p_input->psz_demux && *p_input->psz_demux) ?
796                      VLC_TRUE : VLC_FALSE );
797
798     if( p_input->p_demux == NULL )
799     {
800         msg_Err( p_input, "no suitable demux module for `%s/%s://%s'",
801                  p_input->psz_access, p_input->psz_demux, p_input->psz_name );
802
803         input_StreamDelete( p_input->s );
804         module_Unneed( p_input, p_input->p_access );
805         if ( p_input->stream.p_sout != NULL )
806         {
807             sout_DeleteInstance( p_input->stream.p_sout );
808         }
809         input_AccessEnd( p_input );
810         free( p_input->psz_source );
811         if( p_input->psz_dupsource != NULL )
812         {
813             free( p_input->psz_dupsource );
814         }
815         input_EsOutDelete( p_input->p_es_out );
816         return VLC_EGENERIC;
817     }
818
819     /* Init input_thread_sys_t */
820     p_input->p_sys = malloc( sizeof( input_thread_sys_t ) );
821     p_input->p_sys->i_sub = 0;
822     p_input->p_sys->sub   = NULL;
823
824     p_input->p_sys->i_stop_time = 0;
825
826     /* get meta informations */
827     if( !demux_Control( p_input, DEMUX_GET_META, &meta ) )
828     {
829         playlist_t *p_playlist = (playlist_t *)vlc_object_find( p_input,
830                                          VLC_OBJECT_PLAYLIST,  FIND_PARENT);
831         playlist_item_t *p_item = NULL;
832         input_info_category_t *p_cat;
833         int i;
834
835         if( p_playlist )
836         {
837             vlc_mutex_lock( &p_playlist->object_lock );
838             p_item = playlist_ItemGetByPos( p_playlist, -1 );
839             if( p_item )
840             {
841                 vlc_mutex_lock( &p_item->lock );
842             }
843             vlc_mutex_unlock( &p_playlist->object_lock );
844         }
845
846         msg_Dbg( p_input, "meta informations:" );
847         if( meta->i_meta > 0 )
848         {
849             p_cat = input_InfoCategory( p_input, _("File") );
850             for( i = 0; i < meta->i_meta; i++ )
851             {
852                 msg_Dbg( p_input, "  - '%s' = '%s'", _(meta->name[i]), meta->value[i] );
853                 if( !strcmp( meta->name[i], VLC_META_TITLE ) )
854                 {
855                     playlist_ItemSetName( p_item, meta->value[i] );
856                 }
857                 if( !strcmp( meta->name[i], VLC_META_AUTHOR ) )
858                 {
859                     playlist_ItemAddInfo( p_item, _("General"), _("Author"),
860                                             meta->value[i] );
861                 }
862                 input_AddInfo( p_cat, _(meta->name[i]), "%s", meta->value[i] );
863                 if( p_item )
864                 {
865                     playlist_ItemAddInfo( p_item, _("File"),
866                                           _(meta->name[i]), "%s", meta->value[i] );
867                 }
868             }
869         }
870         for( i = 0; i < meta->i_track; i++ )
871         {
872             vlc_meta_t *tk = meta->track[i];
873             int j;
874
875             msg_Dbg( p_input, "  - track[%d]:", i );
876             if( tk->i_meta > 0 )
877             {
878                 char *psz_cat = malloc( strlen(_("Stream")) + 10 );
879                 sprintf( psz_cat, "%s %d", _("Stream"), i );
880                 p_cat = input_InfoCategory( p_input, psz_cat );
881
882                 for( j = 0; j < tk->i_meta; j++ )
883                 {
884                     msg_Dbg( p_input, "     - '%s' = '%s'", _(tk->name[j]), tk->value[j] );
885                     input_AddInfo( p_cat, _(tk->name[j]), "%s", tk->value[j] );
886                     if( p_item )
887                     {
888                         playlist_ItemAddInfo( p_item, psz_cat,
889                                               _(tk->name[j]), "%s", tk->value[j] );
890                     }
891                 }
892             }
893         }
894
895         if( p_item )
896         {
897             vlc_mutex_unlock( &p_item->lock );
898         }
899         if( p_playlist ) vlc_object_release( p_playlist );
900
901         vlc_meta_Delete( meta );
902     }
903
904     /* get length */
905     if( !demux_Control( p_input, DEMUX_GET_LENGTH, &i_length ) && i_length > 0 )
906     {
907         input_info_category_t *p_cat = input_InfoCategory( p_input, _("File") );
908         p_playlist = (playlist_t*)vlc_object_find( p_input,
909                                                    VLC_OBJECT_PLAYLIST,
910                                                    FIND_PARENT );
911         if( p_playlist )
912         {
913             playlist_SetDuration( p_playlist, -1 , i_length );
914             val.b_bool = p_playlist->i_index;
915             var_Set( p_playlist, "item-change", val );
916             vlc_object_release( p_playlist );
917         }
918         if( p_cat )
919         {
920             char psz_buffer[MSTRTIME_MAX_SIZE];
921             input_AddInfo( p_cat, _("Duration"),
922                            msecstotimestr( psz_buffer, i_length / 1000 ) );
923         }
924
925         /* Set start time */
926         var_Get( p_input, "start-time", &val );
927         if(  val.i_int > 0 )
928         {
929             double f_pos = (double)( (int64_t)val.i_int * I64C(1000000) ) / (double)i_length;
930
931             if( f_pos >= 1.0 )
932             {
933                 msg_Warn( p_input, "invalid start-time, ignored (start-time >= media length)" );
934             }
935             else
936             {
937                 p_input->stream.p_selected_area->i_seek =
938                     (int64_t)( f_pos * (double)p_input->stream.p_selected_area->i_size );
939
940                 msg_Dbg( p_input, "start-time %ds (%2.2f)", val.i_int, f_pos );
941             }
942         }
943     }
944     /* Set stop-time and check validity */
945     var_Get( p_input, "stop-time", &val );
946     if( val.i_int > 0 )
947     {
948         vlc_value_t start;
949
950         var_Get( p_input, "start-time", &start );
951         if( start.i_int >= val.i_int )
952         {
953             msg_Warn( p_input, "invalid stop-time, ignored (stop-time < start-time)" );
954         }
955         else
956         {
957             p_input->p_sys->i_stop_time = (int64_t)val.i_int * I64C(1000000);
958             msg_Dbg( p_input, "stop-time %ds", val.i_int );
959         }
960     }
961
962     /* get fps */
963     if( demux_Control( p_input, DEMUX_GET_FPS, &f_fps ) || f_fps < 0.1 )
964     {
965         i_microsecondperframe = 0;
966     }
967     else
968     {
969         i_microsecondperframe = (int64_t)( (double)1000000.0 / (double)f_fps );
970     }
971
972     /* Look for and add subtitle files */
973     var_Get( p_input, "sub-file", &val );
974     if( val.psz_string && *val.psz_string )
975     {
976         subtitle_demux_t *p_sub;
977
978         msg_Dbg( p_input, "force subtitle: %s", val.psz_string );
979         if( ( p_sub = subtitle_New( p_input, strdup(val.psz_string),
980                                     i_microsecondperframe ) ) )
981         {
982             p_sub_toselect = p_sub;
983             TAB_APPEND( p_input->p_sys->i_sub, p_input->p_sys->sub, p_sub );
984         }
985     }
986     psz_sub_file = val.psz_string;
987
988     var_Get( p_input, "sub-autodetect-file", &val );
989     if( val.b_bool )
990     {
991         subtitle_demux_t *p_sub;
992         int i;
993         char **tmp = subtitles_Detect( p_input, "", p_input->psz_name );
994         char **tmp2 = tmp;
995         for( i = 0; *tmp2 != NULL; i++ )
996         {
997             if( psz_sub_file == NULL || strcmp( psz_sub_file, *tmp2 ) )
998             {
999                 if( ( p_sub = subtitle_New( p_input, *tmp2,
1000                                             i_microsecondperframe ) ) )
1001                 {
1002                     TAB_APPEND( p_input->p_sys->i_sub, p_input->p_sys->sub, p_sub );
1003                 }
1004             }
1005             free( *tmp2++ );
1006         }
1007         free( tmp );
1008     }
1009     if( psz_sub_file ) free( psz_sub_file );
1010
1011     es_out_Control( p_input->p_es_out, ES_OUT_SET_ACTIVE, VLC_TRUE );
1012     val.b_bool =  VLC_FALSE;
1013     if( p_input->stream.p_sout )
1014     {
1015         var_Get( p_input, "sout-all", &val );
1016     }
1017     es_out_Control( p_input->p_es_out, ES_OUT_SET_MODE,
1018                     val.b_bool ? ES_OUT_MODE_ALL : ES_OUT_MODE_AUTO );
1019     if( p_sub_toselect )
1020     {
1021         es_out_Control( p_input->p_es_out, ES_OUT_SET_ES,
1022                         p_sub_toselect->p_es, VLC_TRUE );
1023     }
1024
1025     return VLC_SUCCESS;
1026 }
1027
1028 /*****************************************************************************
1029  * ErrorThread: RunThread() error loop
1030  *****************************************************************************
1031  * This function is called when an error occured during thread main's loop.
1032  *****************************************************************************/
1033 static void ErrorThread( input_thread_t *p_input )
1034 {
1035     while( !p_input->b_die )
1036     {
1037         /* Sleep a while */
1038         msleep( INPUT_IDLE_SLEEP );
1039     }
1040 }
1041
1042 /*****************************************************************************
1043  * EndThread: end the input thread
1044  *****************************************************************************/
1045 static void EndThread( input_thread_t * p_input )
1046 {
1047     int i;
1048 #ifdef HAVE_SYS_TIMES_H
1049     /* Display statistics */
1050     struct tms  cpu_usage;
1051     times( &cpu_usage );
1052
1053     msg_Dbg( p_input, "%ld loops consuming user: %ld, system: %ld",
1054              p_input->c_loops, cpu_usage.tms_utime, cpu_usage.tms_stime );
1055 #else
1056     msg_Dbg( p_input, "%ld loops", p_input->c_loops );
1057 #endif
1058
1059     input_DumpStream( p_input );
1060
1061     /* Free demultiplexer's data */
1062     if( p_input->p_demux ) module_Unneed( p_input, p_input->p_demux );
1063
1064     /* Free all ES and destroy all decoder threads */
1065     input_EndStream( p_input );
1066
1067     /* Close optional stream output instance */
1068     if( p_input->stream.p_sout )
1069     {
1070         vlc_object_t *p_pl =
1071             vlc_object_find( p_input, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
1072         vlc_value_t keep;
1073
1074         if( var_Get( p_input, "sout-keep", &keep ) >= 0 && keep.b_bool && p_pl )
1075         {
1076             /* attach sout to the playlist */
1077             msg_Warn( p_input, "keeping sout" );
1078             vlc_object_detach( p_input->stream.p_sout );
1079             vlc_object_attach( p_input->stream.p_sout, p_pl );
1080         }
1081         else
1082         {
1083             msg_Warn( p_input, "destroying sout" );
1084             sout_DeleteInstance( p_input->stream.p_sout );
1085         }
1086         if( p_pl )
1087         {
1088             vlc_object_release( p_pl );
1089         }
1090     }
1091
1092     /* Destroy subtitles demuxers */
1093     if( p_input->p_sys )
1094     {
1095         for( i = 0; i < p_input->p_sys->i_sub; i++ )
1096         {
1097             subtitle_Close( p_input->p_sys->sub[i] );
1098         }
1099         if( p_input->p_sys->i_sub > 0 )
1100         {
1101             free( p_input->p_sys->sub );
1102         }
1103
1104         /* Free input_thread_sys_t */
1105         free( p_input->p_sys );
1106     }
1107
1108     /* Destroy the stream_t facilities */
1109     if( p_input->s ) input_StreamDelete( p_input->s );
1110
1111     /* Destroy es out */
1112     if( p_input->p_es_out ) input_EsOutDelete( p_input->p_es_out );
1113
1114     /* Close the access plug-in */
1115     if( p_input->p_access ) module_Unneed( p_input, p_input->p_access );
1116
1117     input_AccessEnd( p_input );
1118
1119     /* Free info structures XXX destroy es before 'cause vorbis */
1120     msg_Dbg( p_input, "freeing info structures...");
1121     input_DelInfo( p_input );
1122
1123     free( p_input->psz_source );
1124     if( p_input->psz_dupsource != NULL ) free( p_input->psz_dupsource );
1125
1126     /* Tell we're dead */
1127     p_input->b_dead = 1;
1128 }
1129
1130 /*****************************************************************************
1131  * ParseOption: parses the options for the input
1132  *****************************************************************************
1133  * This function parses the input (config) options and creates their associated
1134  * object variables.
1135  * Options are of the form "[no[-]]foo[=bar]" where foo is the option name and
1136  * bar is the value of the option.
1137  *****************************************************************************/
1138 static void ParseOption( input_thread_t *p_input, const char *psz_option )
1139 {
1140     char *psz_name = (char *)psz_option;
1141     char *psz_value = strchr( psz_option, '=' );
1142     int  i_name_len, i_type;
1143     vlc_bool_t b_isno = VLC_FALSE;
1144     vlc_value_t val;
1145
1146     if( psz_value ) i_name_len = psz_value - psz_option;
1147     else i_name_len = strlen( psz_option );
1148
1149     /* It's too much of an hassle to remove the ':' when we parse
1150      * the cmd line :) */
1151     if( i_name_len && *psz_name == ':' )
1152     {
1153         psz_name++;
1154         i_name_len--;
1155     }
1156
1157     if( i_name_len == 0 ) return;
1158
1159     psz_name = strndup( psz_name, i_name_len );
1160     if( psz_value ) psz_value++;
1161
1162     i_type = config_GetType( p_input, psz_name );
1163
1164     if( !i_type && !psz_value )
1165     {
1166         /* check for "no-foo" or "nofoo" */
1167         if( !strncmp( psz_name, "no-", 3 ) )
1168         {
1169             memmove( psz_name, psz_name + 3, strlen(psz_name) + 1 - 3 );
1170         }
1171         else if( !strncmp( psz_name, "no", 2 ) )
1172         {
1173             memmove( psz_name, psz_name + 2, strlen(psz_name) + 1 - 2 );
1174         }
1175         else goto cleanup;           /* Option doesn't exist */
1176
1177         b_isno = VLC_TRUE;
1178         i_type = config_GetType( p_input, psz_name );
1179
1180         if( !i_type ) goto cleanup;  /* Option doesn't exist */
1181     }
1182     else if( !i_type ) goto cleanup; /* Option doesn't exist */
1183
1184     if( ( i_type != VLC_VAR_BOOL ) &&
1185         ( !psz_value || !*psz_value ) ) goto cleanup; /* Invalid value */
1186
1187     /* Create the variable in the input object.
1188      * Children of the input object will be able to retreive this value
1189      * thanks to the inheritance property of the object variables. */
1190     var_Create( p_input, psz_name, i_type );
1191
1192     switch( i_type )
1193     {
1194     case VLC_VAR_BOOL:
1195         val.b_bool = !b_isno;
1196         break;
1197
1198     case VLC_VAR_INTEGER:
1199         val.i_int = atoi( psz_value );
1200         break;
1201
1202     case VLC_VAR_FLOAT:
1203         val.f_float = atof( psz_value );
1204         break;
1205
1206     case VLC_VAR_STRING:
1207     case VLC_VAR_MODULE:
1208     case VLC_VAR_FILE:
1209     case VLC_VAR_DIRECTORY:
1210         val.psz_string = psz_value;
1211         break;
1212
1213     default:
1214         goto cleanup;
1215         break;
1216     }
1217
1218     var_Set( p_input, psz_name, val );
1219
1220     msg_Dbg( p_input, "set input option: %s to %s", psz_name, psz_value );
1221
1222   cleanup:
1223     if( psz_name ) free( psz_name );
1224     return;
1225 }
1226
1227 /*****************************************************************************
1228  * Callbacks  (position, time, state, rate )
1229  *****************************************************************************/
1230 static int PositionCallback( vlc_object_t *p_this, char const *psz_cmd,
1231                              vlc_value_t oldval, vlc_value_t newval,
1232                              void *p_data )
1233 {
1234     input_thread_t *p_input = (input_thread_t *)p_this;
1235
1236     msg_Dbg( p_input, "cmd=%s old=%f new=%f", psz_cmd,
1237              oldval.f_float, newval.f_float );
1238
1239     if( !strcmp( psz_cmd, "position-offset" ) )
1240     {
1241         vlc_value_t val;
1242         var_Get( p_input, "position", &val );
1243
1244         newval.f_float += val.f_float;
1245     }
1246
1247     vlc_mutex_lock( &p_input->stream.stream_lock );
1248     p_input->stream.p_selected_area->i_seek =
1249         (int64_t)( newval.f_float *
1250                    (double)p_input->stream.p_selected_area->i_size );
1251
1252     if( p_input->stream.p_selected_area->i_seek < 0 )
1253     {
1254         p_input->stream.p_selected_area->i_seek = 0;
1255     }
1256     vlc_mutex_unlock( &p_input->stream.stream_lock );
1257
1258     return VLC_SUCCESS;
1259 }
1260
1261 static int TimeCallback( vlc_object_t *p_this, char const *psz_cmd,
1262                          vlc_value_t oldval, vlc_value_t newval, void *p_data )
1263 {
1264     input_thread_t *p_input = (input_thread_t *)p_this;
1265     vlc_value_t     val;
1266
1267     /* FIXME TODO FIXME */
1268     msg_Dbg( p_input, "cmd=%s old=%lld new=%lld", psz_cmd,
1269              oldval.i_time, newval.i_time );
1270
1271     var_Get( p_input, "length", &val );
1272     if( val.i_time > 0 )
1273     {
1274         val.f_float = (double)newval.i_time / (double)val.i_time;
1275         if( !strcmp( psz_cmd, "time-offset" ) )
1276         {
1277             var_Set( p_input, "position-offset", val );
1278         }
1279         else
1280         {
1281             var_Set( p_input, "position", val );
1282         }
1283     }
1284     else
1285     {
1286         msg_Warn( p_input, "TimeCallback: length <= 0 -> can't seek" );
1287     }
1288     return VLC_SUCCESS;
1289 }
1290
1291 static int StateCallback( vlc_object_t *p_this, char const *psz_cmd,
1292                           vlc_value_t oldval, vlc_value_t newval,
1293                           void *p_data )
1294 {
1295     input_thread_t *p_input = (input_thread_t *)p_this;
1296
1297     msg_Dbg( p_input, "cmd=%s old=%d new=%d",
1298              psz_cmd, oldval.i_int, newval.i_int );
1299
1300     switch( newval.i_int )
1301     {
1302         case PLAYING_S:
1303             input_SetStatus( p_input, INPUT_STATUS_PLAY );
1304             return VLC_SUCCESS;
1305         case PAUSE_S:
1306             input_SetStatus( p_input, INPUT_STATUS_PAUSE );
1307             return VLC_SUCCESS;
1308         case END_S:
1309             input_SetStatus( p_input, INPUT_STATUS_END );
1310             return VLC_SUCCESS;
1311         default:
1312             msg_Err( p_input, "cannot set new state (invalid)" );
1313             return VLC_EGENERIC;
1314     }
1315 }
1316
1317 static int RateCallback( vlc_object_t *p_this, char const *psz_cmd,
1318                          vlc_value_t oldval, vlc_value_t newval, void *p_data )
1319 {
1320     input_thread_t *p_input = (input_thread_t *)p_this;
1321
1322     if( !strcmp( psz_cmd, "rate-slower" ) )
1323     {
1324         input_SetStatus( p_input, INPUT_STATUS_SLOWER );
1325     }
1326     else if( !strcmp( psz_cmd, "rate-faster" ) )
1327     {
1328         input_SetStatus( p_input, INPUT_STATUS_FASTER );
1329     }
1330     else
1331     {
1332         msg_Dbg( p_input, "cmd=%s old=%d new=%d",
1333                  psz_cmd, oldval.i_int, newval.i_int );
1334         input_SetRate( p_input, newval.i_int );
1335     }
1336     return VLC_SUCCESS;
1337 }