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