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