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