]> git.sesse.net Git - vlc/blob - src/input/input.c
*Removed an occurance of former angle item in gtk.
[vlc] / src / input / input.c
1 /*****************************************************************************
2  * input.c: input thread
3  * Read an MPEG2 stream, demultiplex and parse it before sending it to
4  * decoders.
5  *****************************************************************************
6  * Copyright (C) 1998-2001 VideoLAN
7  * $Id: input.c,v 1.187 2002/03/06 01:20:56 stef Exp $
8  *
9  * Authors: Christophe Massiot <massiot@via.ecp.fr>
10  *          Alexis Guillard <alexis.guillard@bt.com>
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  * 
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
25  *****************************************************************************/
26
27 /*****************************************************************************
28  * Preamble
29  *****************************************************************************/
30 #include <stdlib.h>
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #include <fcntl.h>
34
35 #include <videolan/vlc.h>
36
37 #include <string.h>
38 #include <errno.h>
39
40 #ifdef HAVE_SYS_TIMES_H
41 #   include <sys/times.h>
42 #endif
43
44 #include "netutils.h"
45
46 #include "intf_playlist.h"
47
48 #include "stream_control.h"
49 #include "input_ext-intf.h"
50 #include "input_ext-dec.h"
51 #include "input_ext-plugins.h"
52
53 #include "interface.h"
54
55 /*****************************************************************************
56  * Local prototypes
57  *****************************************************************************/
58 static  int RunThread       ( input_thread_t *p_input );
59 static  int InitThread      ( input_thread_t *p_input );
60 static void ErrorThread     ( input_thread_t *p_input );
61 static void CloseThread     ( input_thread_t *p_input );
62 static void DestroyThread   ( input_thread_t *p_input );
63 static void EndThread       ( input_thread_t *p_input );
64
65 /*****************************************************************************
66  * input_InitBank: initialize the input bank.
67  *****************************************************************************/
68 void input_InitBank ( void )
69 {
70     p_input_bank->i_count = 0;
71
72     /* XXX: Workaround for old interface modules */
73     p_input_bank->pp_input[0] = NULL;
74
75     vlc_mutex_init( &p_input_bank->lock );
76 }
77
78 /*****************************************************************************
79  * input_EndBank: empty the input bank.
80  *****************************************************************************
81  * This function ends all unused inputs and empties the bank in
82  * case of success.
83  *****************************************************************************/
84 void input_EndBank ( void )
85 {
86     int i_input;
87
88     /* Ask all remaining video outputs to die */
89     for( i_input = 0; i_input < p_input_bank->i_count; i_input++ )
90     {
91         input_StopThread(
92                 p_input_bank->pp_input[ i_input ], NULL );
93         input_DestroyThread(
94                 p_input_bank->pp_input[ i_input ] );
95     }
96
97     vlc_mutex_destroy( &p_input_bank->lock );
98 }
99
100 /*****************************************************************************
101  * input_CreateThread: creates a new input thread
102  *****************************************************************************
103  * This function creates a new input, and returns a pointer
104  * to its description. On error, it returns NULL.
105  * If pi_status is NULL, then the function will block until the thread is ready.
106  * If not, it will be updated using one of the THREAD_* constants.
107  *****************************************************************************/
108 input_thread_t *input_CreateThread ( playlist_item_t *p_item, int *pi_status )
109 {
110     input_thread_t *    p_input;                        /* thread descriptor */
111
112     /* Allocate descriptor */
113     p_input = (input_thread_t *)malloc( sizeof(input_thread_t) );
114     if( p_input == NULL )
115     {
116         intf_ErrMsg( "input error: can't allocate input thread (%s)",
117                      strerror(errno) );
118         return( NULL );
119     }
120
121     /* Initialize thread properties */
122     p_input->b_die      = 0;
123     p_input->b_error    = 0;
124     p_input->b_eof      = 0;
125
126     /* Set target */
127     p_input->psz_source = strdup( p_item->psz_name );
128
129     /* Set status */
130     p_input->i_status   = THREAD_CREATE;
131
132     /* Demux */
133     p_input->p_demux_module = NULL;
134     p_input->pf_init    = NULL;
135     p_input->pf_end     = NULL;
136     p_input->pf_demux   = NULL;
137     p_input->pf_rewind  = NULL;
138
139     /* Access */
140     p_input->p_access_module = NULL;
141     p_input->pf_open        = NULL;
142     p_input->pf_close       = NULL;
143     p_input->pf_read        = NULL;
144     p_input->pf_seek        = NULL;
145     p_input->pf_set_area    = NULL;
146     p_input->pf_set_program = NULL;
147     
148     p_input->i_bufsize = 0;
149     p_input->i_mtu = 0;
150
151     /* Initialize statistics */
152     p_input->c_loops                    = 0;
153     p_input->stream.c_packets_read      = 0;
154     p_input->stream.c_packets_trashed   = 0;
155
156     /* Set locks. */
157     vlc_mutex_init( &p_input->stream.stream_lock );
158     vlc_cond_init( &p_input->stream.stream_wait );
159     vlc_mutex_init( &p_input->stream.control.control_lock );
160
161     /* Initialize stream description */
162     p_input->stream.b_changed = 0;
163     p_input->stream.i_es_number = 0;
164     p_input->stream.i_selected_es_number = 0;
165     p_input->stream.i_pgrm_number = 0;
166     p_input->stream.i_new_status = p_input->stream.i_new_rate = 0;
167     p_input->stream.b_new_mute = MUTE_NO_CHANGE;
168     p_input->stream.i_mux_rate = 0;
169
170     /* no stream, no program, no area, no es */
171     p_input->stream.p_new_program = NULL;
172
173     p_input->stream.i_area_nb = 0;
174     p_input->stream.pp_areas = NULL;
175     p_input->stream.p_selected_area = NULL;
176     p_input->stream.p_new_area = NULL;
177
178     p_input->stream.pp_selected_es = NULL;
179     p_input->stream.p_removed_es = NULL;
180     p_input->stream.p_newly_selected_es = NULL;
181
182     /* By default there is one area in a stream */
183     input_AddArea( p_input );
184     p_input->stream.p_selected_area = p_input->stream.pp_areas[0];
185
186     /* Initialize stream control properties. */
187     p_input->stream.control.i_status = PLAYING_S;
188     p_input->stream.control.i_rate = DEFAULT_RATE;
189     p_input->stream.control.b_mute = 0;
190     p_input->stream.control.b_grayscale = config_GetIntVariable(
191                                                   VOUT_GRAYSCALE_VAR );
192     p_input->stream.control.i_smp = config_GetIntVariable( VDEC_SMP_VAR );
193
194     intf_WarnMsg( 1, "input: playlist item `%s'", p_input->psz_source );
195
196     /* Create thread. */
197     if( vlc_thread_create( &p_input->thread_id, "input",
198                            (vlc_thread_func_t)RunThread, (void *) p_input ) )
199     {
200         intf_ErrMsg( "input error: can't create input thread (%s)",
201                      strerror(errno) );
202         free( p_input );
203         return( NULL );
204     }
205
206 #if 0
207     /* If status is NULL, wait until the thread is created */
208     if( pi_status == NULL )
209     {
210         do
211         {
212             msleep( THREAD_SLEEP );
213         } while( (i_status != THREAD_READY) && (i_status != THREAD_ERROR)
214                 && (i_status != THREAD_FATAL) );
215     }
216 #endif
217
218     return( p_input );
219 }
220
221 /*****************************************************************************
222  * input_StopThread: mark an input thread as zombie
223  *****************************************************************************
224  * This function should not return until the thread is effectively cancelled.
225  *****************************************************************************/
226 void input_StopThread( input_thread_t *p_input, int *pi_status )
227 {
228     /* Make the thread exit from a possible vlc_cond_wait() */
229     vlc_mutex_lock( &p_input->stream.stream_lock );
230
231     /* Request thread destruction */
232     p_input->b_die = 1;
233
234     vlc_cond_signal( &p_input->stream.stream_wait );
235     vlc_mutex_unlock( &p_input->stream.stream_lock );
236
237     /* If status is NULL, wait until thread has been destroyed */
238 #if 0
239     if( pi_status == NULL )
240     {
241         do
242         {
243             msleep( THREAD_SLEEP );
244         } while ( (i_status != THREAD_OVER) && (i_status != THREAD_ERROR)
245                   && (i_status != THREAD_FATAL) );
246     }
247 #endif
248 }
249
250 /*****************************************************************************
251  * input_DestroyThread: mark an input thread as zombie
252  *****************************************************************************
253  * This function should not return until the thread is effectively cancelled.
254  *****************************************************************************/
255 void input_DestroyThread( input_thread_t *p_input )
256 {
257     /* Join the thread */
258     vlc_thread_join( p_input->thread_id );
259
260     /* Destroy Mutex locks */
261     vlc_mutex_destroy( &p_input->stream.control.control_lock );
262     vlc_cond_destroy( &p_input->stream.stream_wait );
263     vlc_mutex_destroy( &p_input->stream.stream_lock );
264     
265     /* Free input structure */
266     free( p_input );
267 }
268
269 /*****************************************************************************
270  * RunThread: main thread loop
271  *****************************************************************************
272  * Thread in charge of processing the network packets and demultiplexing.
273  *****************************************************************************/
274 static int RunThread( input_thread_t *p_input )
275 {
276     if( InitThread( p_input ) )
277     {
278         /* If we failed, wait before we are killed, and exit */
279         p_input->i_status = THREAD_ERROR;
280         p_input->b_error = 1;
281         ErrorThread( p_input );
282         DestroyThread( p_input );
283         return 0;
284     }
285
286     p_input->i_status = THREAD_READY;
287
288     /* initialization is complete */
289     vlc_mutex_lock( &p_input->stream.stream_lock );
290     p_input->stream.b_changed = 1;
291     vlc_mutex_unlock( &p_input->stream.stream_lock );
292
293     while( !p_input->b_die && !p_input->b_error && !p_input->b_eof )
294     {
295         int i, i_count;
296
297         p_input->c_loops++;
298
299         vlc_mutex_lock( &p_input->stream.stream_lock );
300
301         if( p_input->stream.p_new_program )
302         {
303             if( p_input->pf_set_program != NULL )
304             {
305
306                 p_input->pf_set_program( p_input, 
307                         p_input->stream.p_new_program );
308
309                 for( i = 0; i < p_input->stream.i_pgrm_number; i++ )
310                 {
311                     pgrm_descriptor_t * p_pgrm
312                                             = p_input->stream.pp_programs[i];
313                     /* Escape all decoders for the stream discontinuity they
314                      * will encounter. */
315                     input_EscapeDiscontinuity( p_input, p_pgrm );
316
317                     /* Reinitialize synchro. */
318                     p_pgrm->i_synchro_state = SYNCHRO_REINIT;
319                 }
320             }
321             p_input->stream.p_new_program = NULL;
322         }
323         
324         if( p_input->stream.p_new_area )
325         {
326             if( p_input->stream.b_seekable && p_input->pf_set_area != NULL )
327             {
328
329                 p_input->pf_set_area( p_input, p_input->stream.p_new_area );
330
331                 for( i = 0; i < p_input->stream.i_pgrm_number; i++ )
332                 {
333                     pgrm_descriptor_t * p_pgrm
334                                             = p_input->stream.pp_programs[i];
335                     /* Escape all decoders for the stream discontinuity they
336                      * will encounter. */
337                     input_EscapeDiscontinuity( p_input, p_pgrm );
338
339                     /* Reinitialize synchro. */
340                     p_pgrm->i_synchro_state = SYNCHRO_REINIT;
341                 }
342             }
343             p_input->stream.p_new_area = NULL;
344         }
345
346         if( p_input->stream.p_selected_area->i_seek != NO_SEEK )
347         {
348             if( p_input->stream.b_seekable && p_input->pf_seek != NULL )
349             {
350                 off_t i_new_pos = p_input->stream.p_selected_area->i_seek;
351                 vlc_mutex_unlock( &p_input->stream.stream_lock );
352                 p_input->pf_seek( p_input, i_new_pos );
353                 vlc_mutex_lock( &p_input->stream.stream_lock );
354
355                 for( i = 0; i < p_input->stream.i_pgrm_number; i++ )
356                 {
357                     pgrm_descriptor_t * p_pgrm
358                                             = p_input->stream.pp_programs[i];
359                     /* Escape all decoders for the stream discontinuity they
360                      * will encounter. */
361                     input_EscapeDiscontinuity( p_input, p_pgrm );
362
363                     /* Reinitialize synchro. */
364                     p_pgrm->i_synchro_state = SYNCHRO_REINIT;
365                 }
366
367                 /* Reinitialize buffer manager. */
368                 input_AccessReinit( p_input );
369             }
370             p_input->stream.p_selected_area->i_seek = NO_SEEK;
371         }
372
373         if( p_input->stream.p_removed_es )
374         {
375             input_UnselectES( p_input, p_input->stream.p_removed_es );
376             p_input->stream.p_removed_es = NULL;
377         }
378
379         if( p_input->stream.p_newly_selected_es )
380         {
381             input_SelectES( p_input, p_input->stream.p_newly_selected_es );
382             p_input->stream.p_newly_selected_es = NULL;
383         }
384
385         if( p_input->stream.b_new_mute != MUTE_NO_CHANGE )
386         {
387             if( p_input->stream.b_new_mute )
388             {
389                 input_EscapeAudioDiscontinuity( p_input );
390             }
391
392             vlc_mutex_lock( &p_input->stream.control.control_lock );
393             p_input->stream.control.b_mute = p_input->stream.b_new_mute;
394             vlc_mutex_unlock( &p_input->stream.control.control_lock );
395
396             p_input->stream.b_new_mute = MUTE_NO_CHANGE;
397         }
398
399         vlc_mutex_unlock( &p_input->stream.stream_lock );
400
401         /* Read and demultiplex some data. */
402         i_count = p_input->pf_demux( p_input );
403
404         if( i_count == 0 && p_input->stream.b_seekable )
405         {
406             /* End of file - we do not set b_die because only the
407              * interface is allowed to do so. */
408             intf_WarnMsg( 3, "input: EOF reached" );
409             p_input->b_eof = 1;
410         }
411         else if( i_count < 0 )
412         {
413             p_input->b_error = 1;
414         }
415     }
416
417     if( p_input->b_error || p_input->b_eof )
418     {
419         ErrorThread( p_input );
420     }
421
422     EndThread( p_input );
423
424     DestroyThread( p_input );
425
426     return 0;
427 }
428
429 /*****************************************************************************
430  * InitThread: init the input Thread
431  *****************************************************************************/
432 static int InitThread( input_thread_t * p_input )
433 {
434     /* Parse source string. Syntax : [[<access>][/<demux>]:][<source>] */
435     char * psz_parser = p_input->psz_source;
436
437     /* Skip the plug-in names */
438     while( *psz_parser && *psz_parser != ':' )
439     {
440         psz_parser++;
441     }
442 #ifdef WIN32
443     if( psz_parser - p_input->psz_source == 1 )
444     {
445         intf_WarnMsg( 2, "Drive letter %c: specified in source string",
446                       p_input->psz_source ) ;
447         psz_parser = "";
448     }
449 #endif
450
451     if( !*psz_parser )
452     {
453         p_input->psz_access = p_input->psz_demux = NULL;
454         p_input->psz_name = p_input->psz_source;
455     }
456     else
457     {
458         *psz_parser++ = '\0';
459
460         p_input->psz_name = psz_parser;
461
462         /* Come back to parse the access and demux plug-ins */
463         psz_parser = p_input->psz_source;
464
465         if( !*psz_parser )
466         {
467             /* No access */
468             p_input->psz_access = NULL;
469         }
470         else if( *psz_parser == '/' )
471         {
472             /* No access */
473             p_input->psz_access = NULL;
474             psz_parser++;
475         }
476         else
477         {
478             p_input->psz_access = psz_parser;
479
480             while( *psz_parser && *psz_parser != '/' )
481             {
482                 psz_parser++;
483             }
484
485             if( *psz_parser == '/' )
486             {
487                 *psz_parser++ = '\0';
488             }
489         }
490
491         if( !*psz_parser )
492         {
493             /* No demux */
494             p_input->psz_demux = NULL;
495         }
496         else
497         {
498             p_input->psz_demux = psz_parser;
499         }
500     }
501
502     intf_WarnMsg( 2, "input: access=%s demux=%s name=%s",
503                   p_input->psz_access, p_input->psz_demux,
504                   p_input->psz_name );
505
506     if( input_AccessInit( p_input ) == -1 )
507     {
508         return( -1 );
509     }
510
511     /* Find and open appropriate access plug-in. */
512     p_input->p_access_module = module_Need( MODULE_CAPABILITY_ACCESS,
513                                  p_input->psz_access,
514                                  (void *)p_input );
515
516     if( p_input->p_access_module == NULL )
517     {
518         intf_ErrMsg( "input error: no suitable access plug-in for `%s/%s:%s'",
519                      p_input->psz_access, p_input->psz_demux,
520                      p_input->psz_name );
521         return( -1 );
522     }
523
524 #define f p_input->p_access_module->p_functions->access.functions.access
525     p_input->pf_open          = f.pf_open;
526     p_input->pf_close         = f.pf_close;
527     p_input->pf_read          = f.pf_read;
528     p_input->pf_set_area      = f.pf_set_area;
529     p_input->pf_set_program   = f.pf_set_program;
530     p_input->pf_seek          = f.pf_seek;
531 #undef f
532
533     /* Waiting for stream. */
534     if( p_input->i_mtu )
535     {
536         p_input->i_bufsize = p_input->i_mtu;
537     }
538     else
539     {
540         p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE;
541     }
542
543     if( p_input->p_current_data == NULL && p_input->pf_read != NULL )
544     {
545         while( !input_FillBuffer( p_input ) )
546         {
547             if( p_input->b_die || p_input->b_error )
548             {
549                 module_Unneed( p_input->p_access_module );
550                 return( -1 );
551             }
552         }
553     }
554
555     /* Find and open appropriate demux plug-in. */
556     p_input->p_demux_module = module_Need( MODULE_CAPABILITY_DEMUX,
557                                  p_input->psz_demux,
558                                  (void *)p_input );
559
560     if( p_input->p_demux_module == NULL )
561     {
562         intf_ErrMsg( "input error: no suitable demux plug-in for `%s/%s:%s'",
563                      p_input->psz_access, p_input->psz_demux,
564                      p_input->psz_name );
565         module_Unneed( p_input->p_access_module );
566         return( -1 );
567     }
568
569 #define f p_input->p_demux_module->p_functions->demux.functions.demux
570     p_input->pf_init          = f.pf_init;
571     p_input->pf_end           = f.pf_end;
572     p_input->pf_demux         = f.pf_demux;
573     p_input->pf_rewind        = f.pf_rewind;
574 #undef f
575
576     return( 0 );
577 }
578
579 /*****************************************************************************
580  * ErrorThread: RunThread() error loop
581  *****************************************************************************
582  * This function is called when an error occured during thread main's loop.
583  *****************************************************************************/
584 static void ErrorThread( input_thread_t *p_input )
585 {
586     while( !p_input->b_die )
587     {
588         /* Sleep a while */
589         msleep( INPUT_IDLE_SLEEP );
590     }
591 }
592
593 /*****************************************************************************
594  * EndThread: end the input thread
595  *****************************************************************************/
596 static void EndThread( input_thread_t * p_input )
597 {
598     /* Store status */
599     p_input->i_status = THREAD_END;
600
601     if( p_main->b_stats )
602     {
603 #ifdef HAVE_SYS_TIMES_H
604         /* Display statistics */
605         struct tms  cpu_usage;
606         times( &cpu_usage );
607
608         intf_StatMsg( "input stats: %d loops consuming user: %d, system: %d",
609                       p_input->c_loops,
610                       cpu_usage.tms_utime, cpu_usage.tms_stime );
611 #else
612         intf_StatMsg( "input stats: %d loops", p_input->c_loops );
613 #endif
614
615         input_DumpStream( p_input );
616     }
617
618     /* Free all ES and destroy all decoder threads */
619     input_EndStream( p_input );
620
621     /* Free demultiplexer's data */
622     p_input->pf_end( p_input );
623     module_Unneed( p_input->p_demux_module );
624
625     /* Close the access plug-in */
626     CloseThread( p_input );
627 }
628
629 /*****************************************************************************
630  * CloseThread: close the target
631  *****************************************************************************/
632 static void CloseThread( input_thread_t * p_input )
633 {
634     p_input->pf_close( p_input );
635     module_Unneed( p_input->p_access_module );
636
637     input_AccessEnd( p_input );
638
639     free( p_input->psz_source );
640 }
641
642 /*****************************************************************************
643  * DestroyThread: destroy the input thread
644  *****************************************************************************/
645 static void DestroyThread( input_thread_t * p_input )
646 {
647     /* Update status */
648     p_input->i_status = THREAD_OVER;
649 }
650