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