]> git.sesse.net Git - vlc/blob - src/input/input.c
e39ecfff1024cf7e9b0908ed078543a16048f90a
[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: input.c,v 1.279 2004/01/26 20:26:54 gbazin 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     vlc_value_t val;
89     int i,j;
90
91     /* Allocate descriptor */
92     p_input = vlc_object_create( p_parent, VLC_OBJECT_INPUT );
93     if( p_input == NULL )
94     {
95         msg_Err( p_parent, "out of memory" );
96         return NULL;
97     }
98
99     /* Parse input options */
100     for( i = 0 ; i < p_item->i_categories ; i++ )
101     {
102         if( !strncmp( p_item->pp_categories[i]->psz_name, _("Options"), 7 ) )
103         {
104             msg_Dbg( p_input,"Parsing %i options for item",
105                      p_item->pp_categories[i]->i_infos );
106             for( j = 0; j< p_item->pp_categories[i]->i_infos ; j++ )
107             {
108                 msg_Dbg( p_input,"Option : %s",
109                          p_item->pp_categories[i]->pp_infos[j]->psz_name);
110                 ParseOption( p_input,
111                              p_item->pp_categories[i]->pp_infos[j]->psz_value);
112             }
113             break;
114         }
115     }
116
117     /* Create a few object variables we'll need later on */
118     var_Create( p_input, "video", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
119     var_Create( p_input, "audio", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
120     var_Create( p_input, "audio-channel", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
121     var_Create( p_input, "spu-channel", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
122     var_Create( p_input, "sub-file", VLC_VAR_FILE | VLC_VAR_DOINHERIT );
123     var_Create( p_input, "sub-autodetect-file", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
124     var_Create( p_input, "sub-autodetect-fuzzy", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
125
126     var_Create( p_input, "sout", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
127     var_Create( p_input, "sout-all",   VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
128     var_Create( p_input, "sout-audio", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
129     var_Create( p_input, "sout-video", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
130     var_Create( p_input, "sout-keep",  VLC_VAR_BOOL | 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( p_item->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             /* End of file - we do not set b_die because only the
479              * playlist is allowed to do so. */
480             msg_Info( p_input, "EOF reached" );
481             p_input->b_eof = 1;
482         }
483         else if( i_count < 0 )
484         {
485             p_input->b_error = 1;
486         }
487
488         if( !p_input->b_error && !p_input->b_eof && i_update_next < mdate() )
489         {
490             int i;
491             mtime_t i_time;
492             mtime_t i_length;
493             double  d_pos;
494
495             /* update input status variables */
496             if( !demux_Control( p_input, DEMUX_GET_POSITION, &d_pos ) )
497             {
498                 val.f_float = (float)d_pos;
499                 var_Change( p_input, "position", VLC_VAR_SETVALUE, &val, NULL );
500             }
501             if( !demux_Control( p_input, DEMUX_GET_TIME, &i_time ) )
502             {
503                 val.i_time = i_time;
504                 var_Change( p_input, "time", VLC_VAR_SETVALUE, &val, NULL );
505             }
506             if( !demux_Control( p_input, DEMUX_GET_LENGTH, &i_length ) )
507             {
508                 val.i_time = i_length;
509                 var_Change( p_input, "length", VLC_VAR_SETVALUE, &val, NULL );
510             }
511
512             /* update subs */
513             for( i = 0; i < p_input->p_sys->i_sub; i++ )
514             {
515                 subtitle_Demux( p_input->p_sys->sub[i], i_time );
516             }
517
518             i_update_next = mdate() + I64C(150000);
519         }
520     }
521
522     if( p_input->b_error || p_input->b_eof )
523     {
524         ErrorThread( p_input );
525     }
526
527     EndThread( p_input );
528
529     return 0;
530 }
531
532 /*****************************************************************************
533  * InitThread: init the input Thread
534  *****************************************************************************/
535 static int InitThread( input_thread_t * p_input )
536 {
537     float f_fps;
538     playlist_t *p_playlist;
539     mtime_t i_length;
540
541     /* Parse source string. Syntax : [[<access>][/<demux>]:][<source>] */
542     char * psz_parser = p_input->psz_dupsource = strdup(p_input->psz_source);
543     vlc_value_t val;
544     int64_t i_microsecondperframe;
545
546     subtitle_demux_t *p_sub_toselect = NULL;
547
548     /* Skip the plug-in names */
549     while( *psz_parser && *psz_parser != ':' )
550     {
551         psz_parser++;
552     }
553 #if defined( WIN32 ) || defined( UNDER_CE )
554     if( psz_parser - p_input->psz_dupsource == 1 )
555     {
556         msg_Warn( p_input, "drive letter %c: found in source string",
557                            p_input->psz_dupsource[0] ) ;
558         psz_parser = "";
559     }
560 #endif
561
562     if( !*psz_parser )
563     {
564         p_input->psz_access = p_input->psz_demux = "";
565         p_input->psz_name = p_input->psz_source;
566         free( p_input->psz_dupsource );
567         p_input->psz_dupsource = NULL;
568     }
569     else
570     {
571         *psz_parser++ = '\0';
572
573         /* let's skip '//' */
574         if( psz_parser[0] == '/' && psz_parser[1] == '/' )
575         {
576             psz_parser += 2 ;
577         }
578
579         p_input->psz_name = psz_parser ;
580
581         /* Come back to parse the access and demux plug-ins */
582         psz_parser = p_input->psz_dupsource;
583
584         if( !*psz_parser )
585         {
586             /* No access */
587             p_input->psz_access = "";
588         }
589         else if( *psz_parser == '/' )
590         {
591             /* No access */
592             p_input->psz_access = "";
593             psz_parser++;
594         }
595         else
596         {
597             p_input->psz_access = psz_parser;
598
599             while( *psz_parser && *psz_parser != '/' )
600             {
601                 psz_parser++;
602             }
603
604             if( *psz_parser == '/' )
605             {
606                 *psz_parser++ = '\0';
607             }
608         }
609
610         if( !*psz_parser )
611         {
612             /* No demux */
613             p_input->psz_demux = "";
614         }
615         else
616         {
617             p_input->psz_demux = psz_parser;
618         }
619     }
620
621     msg_Dbg( p_input, "access `%s', demux `%s', name `%s'",
622              p_input->psz_access, p_input->psz_demux, p_input->psz_name );
623
624     if( input_AccessInit( p_input ) == -1 )
625     {
626         free( p_input->psz_source );
627         if( p_input->psz_dupsource != NULL )
628         {
629             free( p_input->psz_dupsource );
630         }
631
632         return VLC_EGENERIC;
633     }
634
635     /* Initialize optional stream output. (before demuxer)*/
636     var_Get( p_input, "sout", &val );
637     if( val.psz_string != NULL )
638     {
639         if ( *val.psz_string && (p_input->stream.p_sout =
640              sout_NewInstance( p_input, val.psz_string )) == NULL )
641         {
642             msg_Err( p_input, "cannot start stream output instance, aborting" );
643             free( val.psz_string );
644
645             input_AccessEnd( p_input );
646             free( p_input->psz_source );
647             if( p_input->psz_dupsource != NULL )
648             {
649                 free( p_input->psz_dupsource );
650             }
651             return VLC_EGENERIC;
652         }
653         free( val.psz_string );
654     }
655
656     p_input->p_es_out = input_EsOutNew( p_input );
657     es_out_Control( p_input->p_es_out, ES_OUT_SET_ACTIVE, VLC_FALSE );
658     es_out_Control( p_input->p_es_out, ES_OUT_SET_MODE, ES_OUT_MODE_NONE );
659
660     /* Find and open appropriate access module */
661     p_input->p_access = module_Need( p_input, "access",
662                                      p_input->psz_access );
663
664 #ifndef WIN32      /* Remove this gross hack from the win32 build as colons
665                     * are forbidden in filenames on Win32. */
666
667     /* Maybe we got something like: /Volumes/toto:titi/gabu.mpg */
668     if ( p_input->p_access == NULL
669           && (*p_input->psz_demux || *p_input->psz_access) )
670     {
671         p_input->psz_access = p_input->psz_demux = "";
672         p_input->psz_name = p_input->psz_source;
673         free( p_input->psz_dupsource);
674         p_input->psz_dupsource = NULL;
675
676         p_input->p_access = module_Need( p_input, "access",
677                                          p_input->psz_access );
678     }
679 #endif
680
681     if( p_input->p_access == NULL )
682     {
683         msg_Err( p_input, "no suitable access module for `%s/%s://%s'",
684                  p_input->psz_access, p_input->psz_demux, p_input->psz_name );
685         if ( p_input->stream.p_sout != NULL )
686         {
687             sout_DeleteInstance( p_input->stream.p_sout );
688         }
689
690         input_AccessEnd( p_input );
691         free( p_input->psz_source );
692         if( p_input->psz_dupsource != NULL )
693         {
694             free( p_input->psz_dupsource );
695         }
696         return VLC_EGENERIC;
697     }
698
699     /* Waiting for stream. */
700     if( p_input->i_mtu )
701     {
702         p_input->i_bufsize = p_input->i_mtu;
703     }
704     else
705     {
706         p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE;
707     }
708
709     /* If the desynchronisation requested by the user is < 0, we need to
710      * cache more data. */
711     var_Create( p_input, "audio-desync", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
712     var_Get( p_input, "audio-desync", &val );
713     if( val.i_int < 0 )
714         p_input->i_pts_delay -= (val.i_int * 1000);
715
716     if( p_input->p_current_data == NULL && p_input->pf_read != NULL )
717     {
718         while( !input_FillBuffer( p_input ) )
719         {
720             if( p_input->b_die || p_input->b_error || p_input->b_eof )
721             {
722                 module_Unneed( p_input, p_input->p_access );
723                 if ( p_input->stream.p_sout != NULL )
724                 {
725                     sout_DeleteInstance( p_input->stream.p_sout );
726                 }
727                 input_AccessEnd( p_input );
728                 free( p_input->psz_source );
729                 if( p_input->psz_dupsource != NULL )
730                 {
731                     free( p_input->psz_dupsource );
732                 }
733                 return VLC_EGENERIC;
734             }
735         }
736     }
737
738     /* Create the stream_t facilities */
739     p_input->s = stream_OpenInput( p_input );
740     if( p_input->s == NULL )
741     {
742         /* should never occur yet */
743
744         msg_Err( p_input, "cannot create stream_t" );
745
746         module_Unneed( p_input, p_input->p_access );
747         if ( p_input->stream.p_sout != NULL )
748         {
749             sout_DeleteInstance( p_input->stream.p_sout );
750         }
751         input_AccessEnd( p_input );
752         free( p_input->psz_source );
753         if( p_input->psz_dupsource != NULL )
754         {
755             free( p_input->psz_dupsource );
756         }
757         return VLC_EGENERIC;
758     }
759
760     /* Find and open appropriate demux module */
761     p_input->p_demux =
762         module_Need( p_input, "demux",
763                      (p_input->psz_demux && *p_input->psz_demux) ?
764                      p_input->psz_demux : "$demux" );
765
766     if( p_input->p_demux == NULL )
767     {
768         msg_Err( p_input, "no suitable demux module for `%s/%s://%s'",
769                  p_input->psz_access, p_input->psz_demux, p_input->psz_name );
770
771         stream_Release( p_input->s );
772         module_Unneed( p_input, p_input->p_access );
773         if ( p_input->stream.p_sout != NULL )
774         {
775             sout_DeleteInstance( p_input->stream.p_sout );
776         }
777         input_AccessEnd( p_input );
778         free( p_input->psz_source );
779         if( p_input->psz_dupsource != NULL )
780         {
781             free( p_input->psz_dupsource );
782         }
783         return VLC_EGENERIC;
784     }
785
786     /* Init input_thread_sys_t */
787     p_input->p_sys = malloc( sizeof( input_thread_sys_t ) );
788     p_input->p_sys->i_sub = 0;
789     p_input->p_sys->sub   = NULL;
790
791     /* get length */
792     if( !demux_Control( p_input, DEMUX_GET_LENGTH, &i_length ) && i_length > 0 )
793     {
794         p_playlist = (playlist_t*)vlc_object_find( p_input,
795                                                    VLC_OBJECT_PLAYLIST,
796                                                    FIND_PARENT );
797         if( p_playlist )
798         {
799             playlist_SetDuration( p_playlist, -1 , i_length );
800             val.b_bool = VLC_TRUE;
801             var_Set( p_playlist, "item-change", val );
802             vlc_object_release( p_playlist );
803         }
804     }
805
806
807     /* get fps */
808     if( demux_Control( p_input, DEMUX_GET_FPS, &f_fps ) || f_fps < 0.1 )
809     {
810         i_microsecondperframe = 0;
811     }
812     else
813     {
814         i_microsecondperframe = (int64_t)( (double)1000000.0 / (double)f_fps );
815     }
816
817     /* Look for and add subtitle files */
818     var_Get( p_input, "sub-file", &val );
819     if( val.psz_string && *val.psz_string )
820     {
821         subtitle_demux_t *p_sub;
822         if( ( p_sub = subtitle_New( p_input, strdup(val.psz_string),
823                                     i_microsecondperframe, 0 ) ) )
824         {
825             p_sub_toselect = p_sub;
826             TAB_APPEND( p_input->p_sys->i_sub, p_input->p_sys->sub, p_sub );
827         }
828     }
829     if( val.psz_string ) free( val.psz_string );
830
831     var_Get( p_input, "sub-autodetect-file", &val );
832     if( val.b_bool )
833     {
834         subtitle_demux_t *p_sub;
835         int i;
836         char **tmp = subtitles_Detect( p_input, "", p_input->psz_source );
837         char **tmp2 = tmp;
838         for( i = 0; *tmp2 != NULL; i++ )
839         {
840             if( ( p_sub = subtitle_New( p_input, *tmp2,
841                                         i_microsecondperframe, i ) ) )
842             {
843                 TAB_APPEND( p_input->p_sys->i_sub, p_input->p_sys->sub, p_sub );
844             }
845             free( *tmp2++ );
846         }
847         free( tmp );
848     }
849
850     es_out_Control( p_input->p_es_out, ES_OUT_SET_ACTIVE, VLC_TRUE );
851     val.b_bool =  VLC_FALSE;
852     if( p_input->stream.p_sout )
853     {
854         var_Get( p_input, "sout-all", &val );
855     }
856     es_out_Control( p_input->p_es_out, ES_OUT_SET_MODE,
857                     val.b_bool ? ES_OUT_MODE_ALL : ES_OUT_MODE_AUTO );
858     if( p_sub_toselect )
859     {
860         es_out_Control( p_input->p_es_out, ES_OUT_SET_ES,
861                         p_sub_toselect->p_es, VLC_TRUE );
862     }
863
864     return VLC_SUCCESS;
865 }
866
867 /*****************************************************************************
868  * ErrorThread: RunThread() error loop
869  *****************************************************************************
870  * This function is called when an error occured during thread main's loop.
871  *****************************************************************************/
872 static void ErrorThread( input_thread_t *p_input )
873 {
874     while( !p_input->b_die )
875     {
876         /* Sleep a while */
877         msleep( INPUT_IDLE_SLEEP );
878     }
879 }
880
881 /*****************************************************************************
882  * EndThread: end the input thread
883  *****************************************************************************/
884 static void EndThread( input_thread_t * p_input )
885 {
886     int i;
887 #ifdef HAVE_SYS_TIMES_H
888     /* Display statistics */
889     struct tms  cpu_usage;
890     times( &cpu_usage );
891
892     msg_Dbg( p_input, "%ld loops consuming user: %ld, system: %ld",
893              p_input->c_loops, cpu_usage.tms_utime, cpu_usage.tms_stime );
894 #else
895     msg_Dbg( p_input, "%ld loops", p_input->c_loops );
896 #endif
897
898     input_DumpStream( p_input );
899
900     /* Free demultiplexer's data */
901     if( p_input->p_demux ) module_Unneed( p_input, p_input->p_demux );
902
903     /* Free all ES and destroy all decoder threads */
904     input_EndStream( p_input );
905
906     /* Close optional stream output instance */
907     if( p_input->stream.p_sout )
908     {
909         vlc_object_t *p_pl =
910             vlc_object_find( p_input, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
911         vlc_value_t keep;
912
913         if( var_Get( p_input, "sout-keep", &keep ) >= 0 && keep.b_bool && p_pl )
914         {
915             /* attach sout to the playlist */
916             msg_Warn( p_input, "keeping sout" );
917             vlc_object_detach( p_input->stream.p_sout );
918             vlc_object_attach( p_input->stream.p_sout, p_pl );
919         }
920         else
921         {
922             msg_Warn( p_input, "destroying sout" );
923             sout_DeleteInstance( p_input->stream.p_sout );
924         }
925         if( p_pl )
926         {
927             vlc_object_release( p_pl );
928         }
929     }
930
931     /* Destroy subtitles demuxers */
932     if( p_input->p_sys )
933     {
934         for( i = 0; i < p_input->p_sys->i_sub; i++ )
935         {
936             subtitle_Close( p_input->p_sys->sub[i] );
937         }
938         if( p_input->p_sys->i_sub > 0 )
939         {
940             free( p_input->p_sys->sub );
941         }
942
943         /* Free input_thread_sys_t */
944         free( p_input->p_sys );
945     }
946
947     /* Destroy the stream_t facilities */
948     if( p_input->s ) stream_Release( p_input->s );
949
950     /* Destroy es out */
951     if( p_input->p_es_out ) input_EsOutDelete( p_input->p_es_out );
952
953     /* Close the access plug-in */
954     if( p_input->p_access ) module_Unneed( p_input, p_input->p_access );
955
956     input_AccessEnd( p_input );
957
958     /* Free info structures XXX destroy es before 'cause vorbis */
959     msg_Dbg( p_input, "freeing info structures...");
960     input_DelInfo( p_input );
961
962     free( p_input->psz_source );
963     if( p_input->psz_dupsource != NULL ) free( p_input->psz_dupsource );
964
965     /* Tell we're dead */
966     p_input->b_dead = 1;
967 }
968
969 /*****************************************************************************
970  * ParseOption: parses the options for the input
971  *****************************************************************************
972  * This function parses the input (config) options and creates their associated
973  * object variables.
974  * Options are of the form "[no[-]]foo[=bar]" where foo is the option name and
975  * bar is the value of the option.
976  *****************************************************************************/
977 static void ParseOption( input_thread_t *p_input, const char *psz_option )
978 {
979     char *psz_name = (char *)psz_option;
980     char *psz_value = strchr( psz_option, '=' );
981     int  i_name_len, i_type;
982     vlc_bool_t b_isno = VLC_FALSE;
983     vlc_value_t val;
984
985     if( psz_value ) i_name_len = psz_value - psz_option;
986     else i_name_len = strlen( psz_option );
987
988     /* It's too much of an hassle to remove the ':' when we parse
989      * the cmd line :) */
990     if( i_name_len && *psz_name == ':' )
991     {
992         psz_name++;
993         i_name_len--;
994     }
995
996     if( i_name_len == 0 ) return;
997
998     psz_name = strndup( psz_name, i_name_len );
999     if( psz_value ) psz_value++;
1000
1001     i_type = config_GetType( p_input, psz_name );
1002
1003     if( !i_type && !psz_value )
1004     {
1005         /* check for "no-foo" or "nofoo" */
1006         if( !strncmp( psz_name, "no-", 3 ) )
1007         {
1008             memmove( psz_name, psz_name + 3, strlen(psz_name) + 1 - 3 );
1009         }
1010         else if( !strncmp( psz_name, "no", 2 ) )
1011         {
1012             memmove( psz_name, psz_name + 2, strlen(psz_name) + 1 - 2 );
1013         }
1014         else goto cleanup;           /* Option doesn't exist */
1015
1016         b_isno = VLC_TRUE;
1017         i_type = config_GetType( p_input, psz_name );
1018
1019         if( !i_type ) goto cleanup;  /* Option doesn't exist */
1020     }
1021     else if( !i_type ) goto cleanup; /* Option doesn't exist */
1022
1023     if( ( i_type != VLC_VAR_BOOL ) &&
1024         ( !psz_value || !*psz_value ) ) goto cleanup; /* Invalid value */
1025
1026     /* Create the variable in the input object.
1027      * Children of the input object will be able to retreive this value
1028      * thanks to the inheritance property of the object variables. */
1029     var_Create( p_input, psz_name, i_type );
1030
1031     switch( i_type )
1032     {
1033     case VLC_VAR_BOOL:
1034         val.b_bool = !b_isno;
1035         break;
1036
1037     case VLC_VAR_INTEGER:
1038         val.i_int = atoi( psz_value );
1039         break;
1040
1041     case VLC_VAR_FLOAT:
1042         val.f_float = atof( psz_value );
1043         break;
1044
1045     case VLC_VAR_STRING:
1046     case VLC_VAR_MODULE:
1047     case VLC_VAR_FILE:
1048     case VLC_VAR_DIRECTORY:
1049         val.psz_string = psz_value;
1050         break;
1051
1052     default:
1053         goto cleanup;
1054         break;
1055     }
1056
1057     var_Set( p_input, psz_name, val );
1058
1059     msg_Dbg( p_input, "set input option: %s to %s", psz_name, psz_value );
1060
1061   cleanup:
1062     if( psz_name ) free( psz_name );
1063     return;
1064 }
1065
1066 /*****************************************************************************
1067  * Callbacks  (position, time, state, rate )
1068  *****************************************************************************/
1069 static int PositionCallback( vlc_object_t *p_this, char const *psz_cmd,
1070                              vlc_value_t oldval, vlc_value_t newval,
1071                              void *p_data )
1072 {
1073     input_thread_t *p_input = (input_thread_t *)p_this;
1074
1075     msg_Dbg( p_input, "cmd=%s old=%f new=%f", psz_cmd,
1076              oldval.f_float, newval.f_float );
1077
1078     if( !strcmp( psz_cmd, "position-offset" ) )
1079     {
1080         vlc_value_t val;
1081         var_Get( p_input, "position", &val );
1082
1083         newval.f_float += val.f_float;
1084     }
1085
1086     vlc_mutex_lock( &p_input->stream.stream_lock );
1087     p_input->stream.p_selected_area->i_seek =
1088         (int64_t)( newval.f_float *
1089                    (double)p_input->stream.p_selected_area->i_size );
1090
1091     if( p_input->stream.p_selected_area->i_seek < 0 )
1092     {
1093         p_input->stream.p_selected_area->i_seek = 0;
1094     }
1095     vlc_mutex_unlock( &p_input->stream.stream_lock );
1096
1097     return VLC_SUCCESS;
1098 }
1099
1100 static int TimeCallback( vlc_object_t *p_this, char const *psz_cmd,
1101                          vlc_value_t oldval, vlc_value_t newval, void *p_data )
1102 {
1103     input_thread_t *p_input = (input_thread_t *)p_this;
1104     vlc_value_t     val;
1105
1106     /* FIXME TODO FIXME */
1107     msg_Dbg( p_input, "cmd=%s old=%lld new=%lld", psz_cmd,
1108              oldval.i_time, newval.i_time );
1109
1110     var_Get( p_input, "length", &val );
1111     if( val.i_time > 0 )
1112     {
1113         val.f_float = (double)newval.i_time / (double)val.i_time;
1114         if( !strcmp( psz_cmd, "time-offset" ) )
1115         {
1116             var_Set( p_input, "position-offset", val );
1117         }
1118         else
1119         {
1120             var_Set( p_input, "position", val );
1121         }
1122     }
1123     else
1124     {
1125         msg_Warn( p_input, "TimeCallback: length <= 0 -> can't seek" );
1126     }
1127     return VLC_SUCCESS;
1128 }
1129
1130 static int StateCallback( vlc_object_t *p_this, char const *psz_cmd,
1131                           vlc_value_t oldval, vlc_value_t newval,
1132                           void *p_data )
1133 {
1134     input_thread_t *p_input = (input_thread_t *)p_this;
1135
1136     msg_Dbg( p_input, "cmd=%s old=%d new=%d",
1137              psz_cmd, oldval.i_int, newval.i_int );
1138
1139     switch( newval.i_int )
1140     {
1141         case PLAYING_S:
1142             input_SetStatus( p_input, INPUT_STATUS_PLAY );
1143             return VLC_SUCCESS;
1144         case PAUSE_S:
1145             input_SetStatus( p_input, INPUT_STATUS_PAUSE );
1146             return VLC_SUCCESS;
1147         case END_S:
1148             input_SetStatus( p_input, INPUT_STATUS_END );
1149             return VLC_SUCCESS;
1150         default:
1151             msg_Err( p_input, "cannot set new state (invalid)" );
1152             return VLC_EGENERIC;
1153     }
1154 }
1155
1156 static int RateCallback( vlc_object_t *p_this, char const *psz_cmd,
1157                          vlc_value_t oldval, vlc_value_t newval, void *p_data )
1158 {
1159     input_thread_t *p_input = (input_thread_t *)p_this;
1160
1161     if( !strcmp( psz_cmd, "rate-slower" ) )
1162     {
1163         input_SetStatus( p_input, INPUT_STATUS_SLOWER );
1164     }
1165     else if( !strcmp( psz_cmd, "rate-faster" ) )
1166     {
1167         input_SetStatus( p_input, INPUT_STATUS_FASTER );
1168     }
1169     else
1170     {
1171         msg_Dbg( p_input, "cmd=%s old=%d new=%d",
1172                  psz_cmd, oldval.i_int, newval.i_int );
1173         input_SetRate( p_input, newval.i_int );
1174     }
1175     return VLC_SUCCESS;
1176 }