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