]> git.sesse.net Git - vlc/blob - src/input/input.c
* ./configure.ac.in: removed -W in favour of -Wtraditional.
[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-2002 VideoLAN
7  * $Id: input.c,v 1.218 2002/12/06 16:34:08 sam 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
33 #include <string.h>
34
35 #ifdef HAVE_SYS_TIMES_H
36 #   include <sys/times.h>
37 #endif
38
39 #include "netutils.h"
40 #include "vlc_playlist.h"
41
42 #include "stream_control.h"
43 #include "input_ext-intf.h"
44 #include "input_ext-dec.h"
45 #include "input_ext-plugins.h"
46
47 #include "stream_output.h"
48
49 #include "interface.h"
50
51 /*****************************************************************************
52  * Local prototypes
53  *****************************************************************************/
54 static  int RunThread       ( input_thread_t *p_input );
55 static  int InitThread      ( input_thread_t *p_input );
56 static void ErrorThread     ( input_thread_t *p_input );
57 static void EndThread       ( input_thread_t *p_input );
58
59 /*****************************************************************************
60  * input_CreateThread: creates a new input thread
61  *****************************************************************************
62  * This function creates a new input, and returns a pointer
63  * to its description. On error, it returns NULL.
64  *****************************************************************************/
65 input_thread_t *__input_CreateThread( vlc_object_t *p_parent,
66                                       playlist_item_t *p_item )
67 {
68     input_thread_t *    p_input;                        /* thread descriptor */
69     input_info_category_t * p_info;
70
71     /* Allocate descriptor */
72     p_input = vlc_object_create( p_parent, VLC_OBJECT_INPUT );
73     if( p_input == NULL )
74     {
75         msg_Err( p_parent, "out of memory" );
76         return NULL;
77     }
78
79     /* Initialize thread properties */
80     p_input->b_eof      = 0;
81
82     /* Set target */
83     p_input->psz_source = strdup( p_item->psz_uri );
84
85     /* Demux */
86     p_input->p_demux = NULL;
87
88     /* Access */
89     p_input->p_access = NULL;
90
91     p_input->i_bufsize = 0;
92     p_input->i_mtu = 0;
93
94     /* Initialize statistics */
95     p_input->c_loops                    = 0;
96     p_input->stream.c_packets_read      = 0;
97     p_input->stream.c_packets_trashed   = 0;
98
99     /* Set locks. */
100     vlc_mutex_init( p_input, &p_input->stream.stream_lock );
101     vlc_cond_init( p_input, &p_input->stream.stream_wait );
102     vlc_mutex_init( p_input, &p_input->stream.control.control_lock );
103
104     /* Initialize stream description */
105     p_input->stream.b_changed = 0;
106     p_input->stream.i_es_number = 0;
107     p_input->stream.i_selected_es_number = 0;
108     p_input->stream.i_pgrm_number = 0;
109     p_input->stream.i_new_status = p_input->stream.i_new_rate = 0;
110     p_input->stream.b_new_mute = MUTE_NO_CHANGE;
111     p_input->stream.i_mux_rate = 0;
112     p_input->stream.b_seekable = 0;
113     p_input->stream.p_sout = NULL;
114
115     /* no stream, no program, no area, no es */
116     p_input->stream.p_new_program = NULL;
117
118     p_input->stream.i_area_nb = 0;
119     p_input->stream.pp_areas = NULL;
120     p_input->stream.p_selected_area = NULL;
121     p_input->stream.p_new_area = NULL;
122
123     p_input->stream.pp_selected_es = NULL;
124     p_input->stream.p_removed_es = NULL;
125     p_input->stream.p_newly_selected_es = NULL;
126
127     /* By default there is one area in a stream */
128     input_AddArea( p_input );
129     p_input->stream.p_selected_area = p_input->stream.pp_areas[0];
130
131     /* Initialize stream control properties. */
132     p_input->stream.control.i_status = PLAYING_S;
133     p_input->stream.control.i_rate = DEFAULT_RATE;
134     p_input->stream.control.b_mute = 0;
135     p_input->stream.control.b_grayscale = config_GetInt( p_input, "grayscale" );
136
137     /* Initialize input info */
138     p_input->stream.p_info = malloc( sizeof( input_info_category_t ) );
139     if( !p_input->stream.p_info )
140     {
141         msg_Err( p_input, "No memory!" );
142         return NULL;
143     }
144     p_input->stream.p_info->psz_name = strdup("General") ;
145     p_input->stream.p_info->p_info = NULL;
146     p_input->stream.p_info->p_next = NULL;
147
148     msg_Info( p_input, "playlist item `%s'", p_input->psz_source );
149
150     p_info = input_InfoCategory( p_input, "General" );
151     input_AddInfo( p_info, "playlist item", p_input->psz_source );
152     vlc_object_attach( p_input, p_parent );
153
154     /* Create thread and wait for its readiness. */
155     if( vlc_thread_create( p_input, "input", RunThread,
156                            VLC_THREAD_PRIORITY_INPUT, VLC_TRUE ) )
157     {
158         msg_Err( p_input, "cannot create input thread" );
159         free( p_input );
160         return NULL;
161     }
162
163     return p_input;
164 }
165
166 /*****************************************************************************
167  * input_StopThread: mark an input thread as zombie
168  *****************************************************************************
169  * This function should not return until the thread is effectively cancelled.
170  *****************************************************************************/
171 void input_StopThread( input_thread_t *p_input )
172 {
173     /* Make the thread exit from a possible vlc_cond_wait() */
174     vlc_mutex_lock( &p_input->stream.stream_lock );
175     /* Request thread destruction */
176     p_input->b_die = 1;
177
178     vlc_cond_signal( &p_input->stream.stream_wait );
179     vlc_mutex_unlock( &p_input->stream.stream_lock );
180 }
181
182 /*****************************************************************************
183  * input_DestroyThread: mark an input thread as zombie
184  *****************************************************************************
185  * This function should not return until the thread is effectively cancelled.
186  *****************************************************************************/
187 void input_DestroyThread( input_thread_t *p_input )
188 {
189     /* Join the thread */
190     vlc_thread_join( p_input );
191
192     /* Destroy Mutex locks */
193     vlc_mutex_destroy( &p_input->stream.control.control_lock );
194     vlc_cond_destroy( &p_input->stream.stream_wait );
195     vlc_mutex_destroy( &p_input->stream.stream_lock );
196 }
197
198 /*****************************************************************************
199  * RunThread: main thread loop
200  *****************************************************************************
201  * Thread in charge of processing the network packets and demultiplexing.
202  *****************************************************************************/
203 static int RunThread( input_thread_t *p_input )
204 {
205     /* Signal right now, otherwise we'll get stuck in a peek */
206     vlc_thread_ready( p_input );
207
208     if( InitThread( p_input ) )
209     {
210         /* If we failed, wait before we are killed, and exit */
211         p_input->b_error = 1;
212         ErrorThread( p_input );
213         p_input->b_dead = 1;
214         return 0;
215     }
216
217     /* initialization is complete */
218     vlc_mutex_lock( &p_input->stream.stream_lock );
219     p_input->stream.b_changed = 1;
220     vlc_mutex_unlock( &p_input->stream.stream_lock );
221
222     while( !p_input->b_die && !p_input->b_error && !p_input->b_eof )
223     {
224         unsigned int i, i_count;
225
226         p_input->c_loops++;
227
228         vlc_mutex_lock( &p_input->stream.stream_lock );
229
230         if( p_input->stream.p_new_program )
231         {
232             if( p_input->pf_set_program != NULL )
233             {
234
235                 /* Reinitialize buffer manager. */
236                 input_AccessReinit( p_input );
237
238                 p_input->pf_set_program( p_input,
239                                          p_input->stream.p_new_program );
240
241                 /* Escape all decoders for the stream discontinuity they
242                  * will encounter. */
243                 input_EscapeDiscontinuity( p_input );
244
245                 for( i = 0; i < p_input->stream.i_pgrm_number; i++ )
246                 {
247                     pgrm_descriptor_t * p_pgrm
248                                             = p_input->stream.pp_programs[i];
249
250                     /* Reinitialize synchro. */
251                     p_pgrm->i_synchro_state = SYNCHRO_REINIT;
252                 }
253             }
254             p_input->stream.p_new_program = NULL;
255         }
256
257         if( p_input->stream.p_new_area )
258         {
259             if( p_input->stream.b_seekable && p_input->pf_set_area != NULL )
260             {
261                 input_AccessReinit( p_input );
262
263                 p_input->pf_set_area( p_input, p_input->stream.p_new_area );
264
265                 /* Escape all decoders for the stream discontinuity they
266                  * will encounter. */
267                 input_EscapeDiscontinuity( p_input );
268
269                 for( i = 0; i < p_input->stream.i_pgrm_number; i++ )
270                 {
271                     pgrm_descriptor_t * p_pgrm
272                                             = p_input->stream.pp_programs[i];
273
274                     /* Reinitialize synchro. */
275                     p_pgrm->i_synchro_state = SYNCHRO_REINIT;
276                 }
277             }
278             p_input->stream.p_new_area = NULL;
279         }
280
281         if( p_input->stream.p_selected_area->i_seek != NO_SEEK )
282         {
283             if( p_input->stream.b_seekable
284                  && p_input->pf_seek != NULL )
285             {
286                 off_t i_new_pos;
287
288                 /* Reinitialize buffer manager. */
289                 input_AccessReinit( p_input );
290
291                 i_new_pos = p_input->stream.p_selected_area->i_seek;
292                 vlc_mutex_unlock( &p_input->stream.stream_lock );
293                 p_input->pf_seek( p_input, i_new_pos );
294                 vlc_mutex_lock( &p_input->stream.stream_lock );
295
296                 /* Escape all decoders for the stream discontinuity they
297                  * will encounter. */
298                 input_EscapeDiscontinuity( p_input );
299
300                 for( i = 0; i < p_input->stream.i_pgrm_number; i++ )
301                 {
302                     pgrm_descriptor_t * p_pgrm
303                                             = p_input->stream.pp_programs[i];
304
305                     /* Reinitialize synchro. */
306                     p_pgrm->i_synchro_state = SYNCHRO_REINIT;
307                 }
308             }
309             p_input->stream.p_selected_area->i_seek = NO_SEEK;
310         }
311
312         if( p_input->stream.p_removed_es )
313         {
314             input_UnselectES( p_input, p_input->stream.p_removed_es );
315             p_input->stream.p_removed_es = NULL;
316         }
317
318         if( p_input->stream.p_newly_selected_es )
319         {
320             input_SelectES( p_input, p_input->stream.p_newly_selected_es );
321             p_input->stream.p_newly_selected_es = NULL;
322         }
323
324         if( p_input->stream.b_new_mute != MUTE_NO_CHANGE )
325         {
326             if( p_input->stream.b_new_mute )
327             {
328                 input_EscapeAudioDiscontinuity( p_input );
329             }
330
331             vlc_mutex_lock( &p_input->stream.control.control_lock );
332             p_input->stream.control.b_mute = p_input->stream.b_new_mute;
333             vlc_mutex_unlock( &p_input->stream.control.control_lock );
334
335             p_input->stream.b_new_mute = MUTE_NO_CHANGE;
336         }
337
338         vlc_mutex_unlock( &p_input->stream.stream_lock );
339
340         /* Read and demultiplex some data. */
341         i_count = p_input->pf_demux( p_input );
342
343         if( i_count == 0 && p_input->stream.b_seekable )
344         {
345             /* End of file - we do not set b_die because only the
346              * playlist is allowed to do so. */
347             msg_Info( p_input, "EOF reached" );
348             p_input->b_eof = 1;
349         }
350         else if( i_count < 0 )
351         {
352             p_input->b_error = 1;
353         }
354     }
355
356     if( p_input->b_error || p_input->b_eof )
357     {
358         ErrorThread( p_input );
359     }
360
361     EndThread( p_input );
362
363     return 0;
364 }
365
366 /*****************************************************************************
367  * InitThread: init the input Thread
368  *****************************************************************************/
369 static int InitThread( input_thread_t * p_input )
370 {
371     /* Parse source string. Syntax : [[<access>][/<demux>]:][<source>] */
372     char * psz_parser = p_input->psz_source;
373
374     /* Skip the plug-in names */
375     while( *psz_parser && *psz_parser != ':' )
376     {
377         psz_parser++;
378     }
379 #if defined( WIN32 ) || defined( UNDER_CE )
380     if( psz_parser - p_input->psz_source == 1 )
381     {
382         msg_Warn( p_input, "drive letter %c: found in source string",
383                            p_input->psz_source[0] ) ;
384         psz_parser = "";
385     }
386 #endif
387
388     if( !*psz_parser )
389     {
390         p_input->psz_access = p_input->psz_demux = "";
391         p_input->psz_name = p_input->psz_source;
392     }
393     else
394     {
395         *psz_parser++ = '\0';
396
397         /* let's skip '//' */
398         if( psz_parser[0] == '/' && psz_parser[1] == '/' )
399         {
400             psz_parser += 2 ;
401         }
402
403         p_input->psz_name = psz_parser ;
404
405         /* Come back to parse the access and demux plug-ins */
406         psz_parser = p_input->psz_source;
407
408         if( !*psz_parser )
409         {
410             /* No access */
411             p_input->psz_access = "";
412         }
413         else if( *psz_parser == '/' )
414         {
415             /* No access */
416             p_input->psz_access = "";
417             psz_parser++;
418         }
419         else
420         {
421             p_input->psz_access = psz_parser;
422
423             while( *psz_parser && *psz_parser != '/' )
424             {
425                 psz_parser++;
426             }
427
428             if( *psz_parser == '/' )
429             {
430                 *psz_parser++ = '\0';
431             }
432         }
433
434         if( !*psz_parser )
435         {
436             /* No demux */
437             p_input->psz_demux = "";
438         }
439         else
440         {
441             p_input->psz_demux = psz_parser;
442         }
443     }
444
445     msg_Dbg( p_input, "access `%s', demux `%s', name `%s'",
446              p_input->psz_access, p_input->psz_demux, p_input->psz_name );
447
448     if( input_AccessInit( p_input ) == -1 )
449     {
450         return -1;
451     }
452
453     /* Find and open appropriate access module */
454     p_input->p_access = module_Need( p_input, "access",
455                                      p_input->psz_access );
456
457     if( p_input->p_access == NULL )
458     {
459         msg_Err( p_input, "no suitable access module for `%s/%s://%s'",
460                  p_input->psz_access, p_input->psz_demux, p_input->psz_name );
461         return -1;
462     }
463
464     /* Waiting for stream. */
465     if( p_input->i_mtu )
466     {
467         p_input->i_bufsize = p_input->i_mtu;
468     }
469     else
470     {
471         p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE;
472     }
473
474     if( p_input->p_current_data == NULL && p_input->pf_read != NULL )
475     {
476         while( !input_FillBuffer( p_input ) )
477         {
478             if( p_input->b_die || p_input->b_error || p_input->b_eof )
479             {
480                 module_Unneed( p_input, p_input->p_access );
481                 return -1;
482             }
483         }
484     }
485
486     /* Find and open appropriate demux module */
487     p_input->p_demux = module_Need( p_input, "demux",
488                                     p_input->psz_demux );
489
490     if( p_input->p_demux== NULL )
491     {
492         msg_Err( p_input, "no suitable demux module for `%s/%s://%s'",
493                  p_input->psz_access, p_input->psz_demux, p_input->psz_name );
494         module_Unneed( p_input, p_input->p_access );
495         return -1;
496     }
497
498     /* Initialize optional stream output. */
499     psz_parser = config_GetPsz( p_input, "sout" );
500     if ( psz_parser != NULL )
501     {
502         if ( *psz_parser &&
503              (p_input->stream.p_sout = sout_NewInstance( p_input, psz_parser ))
504                == NULL )
505         {
506             msg_Err( p_input, "cannot start stream output instance, aborting" );
507             free( psz_parser );
508             module_Unneed( p_input, p_input->p_access );
509             module_Unneed( p_input, p_input->p_demux );
510             return -1;
511         }
512
513         free( psz_parser );
514     }
515
516     return 0;
517 }
518
519 /*****************************************************************************
520  * ErrorThread: RunThread() error loop
521  *****************************************************************************
522  * This function is called when an error occured during thread main's loop.
523  *****************************************************************************/
524 static void ErrorThread( input_thread_t *p_input )
525 {
526     while( !p_input->b_die )
527     {
528         /* Sleep a while */
529         msleep( INPUT_IDLE_SLEEP );
530     }
531 }
532
533 /*****************************************************************************
534  * EndThread: end the input thread
535  *****************************************************************************/
536 static void EndThread( input_thread_t * p_input )
537 {
538 #ifdef HAVE_SYS_TIMES_H
539     /* Display statistics */
540     struct tms  cpu_usage;
541     times( &cpu_usage );
542
543     msg_Dbg( p_input, "%d loops consuming user: %d, system: %d",
544              p_input->c_loops, cpu_usage.tms_utime, cpu_usage.tms_stime );
545 #else
546     msg_Dbg( p_input, "%d loops", p_input->c_loops );
547 #endif
548
549     /* Free info structures */
550     msg_Dbg( p_input, "freeing info structures...");
551     input_DelInfo( p_input );
552
553     input_DumpStream( p_input );
554
555     /* Free all ES and destroy all decoder threads */
556     input_EndStream( p_input );
557
558     /* Close optional stream output instance */
559     if ( p_input->stream.p_sout != NULL )
560     {
561         sout_DeleteInstance( p_input->stream.p_sout );
562     }
563
564     /* Free demultiplexer's data */
565     module_Unneed( p_input, p_input->p_demux );
566
567     /* Close the access plug-in */
568     module_Unneed( p_input, p_input->p_access );
569
570     input_AccessEnd( p_input );
571
572     free( p_input->psz_source );
573
574     /* Tell we're dead */
575     p_input->b_dead = 1;
576 }
577