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