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