]> git.sesse.net Git - vlc/blob - src/input/input.c
e9e8e42e55dc0ad247ffec83c39d261d3b79f81d
[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.230 2003/05/22 16:01:02 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
33 #include <string.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_control.h"
42 #include "input_ext-intf.h"
43 #include "input_ext-dec.h"
44 #include "input_ext-plugins.h"
45
46 #include "stream_output.h"
47 #include <vlc/vout.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, 0, 1 );
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 )
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_dupsource = strdup(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_dupsource == 1 )
382     {
383         msg_Warn( p_input, "drive letter %c: found in source string",
384                            p_input->psz_dupsource[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         free( p_input->psz_dupsource );
394         p_input->psz_dupsource = NULL;
395     }
396     else
397     {
398         *psz_parser++ = '\0';
399
400         /* let's skip '//' */
401         if( psz_parser[0] == '/' && psz_parser[1] == '/' )
402         {
403             psz_parser += 2 ;
404         }
405
406         p_input->psz_name = psz_parser ;
407
408         /* Come back to parse the access and demux plug-ins */
409         psz_parser = p_input->psz_dupsource;
410
411         if( !*psz_parser )
412         {
413             /* No access */
414             p_input->psz_access = "";
415         }
416         else if( *psz_parser == '/' )
417         {
418             /* No access */
419             p_input->psz_access = "";
420             psz_parser++;
421         }
422         else
423         {
424             p_input->psz_access = psz_parser;
425
426             while( *psz_parser && *psz_parser != '/' )
427             {
428                 psz_parser++;
429             }
430
431             if( *psz_parser == '/' )
432             {
433                 *psz_parser++ = '\0';
434             }
435         }
436
437         if( !*psz_parser )
438         {
439             /* No demux */
440             p_input->psz_demux = "";
441         }
442         else
443         {
444             p_input->psz_demux = psz_parser;
445         }
446     }
447
448     msg_Dbg( p_input, "access `%s', demux `%s', name `%s'",
449              p_input->psz_access, p_input->psz_demux, p_input->psz_name );
450
451     if( input_AccessInit( p_input ) == -1 )
452     {
453         return -1;
454     }
455
456     /* Find and open appropriate access module */
457     p_input->p_access = module_Need( p_input, "access",
458                                      p_input->psz_access );
459
460     if ( p_input->p_access == NULL
461           && (*p_input->psz_demux || *p_input->psz_access) )
462     {
463         /* Maybe we got something like :
464          * /Volumes/toto:titi/gabu.mpg */
465         p_input->psz_access = p_input->psz_demux = "";
466         p_input->psz_name = p_input->psz_source;
467         free( p_input->psz_dupsource);
468         p_input->psz_dupsource = NULL;
469
470         p_input->p_access = module_Need( p_input, "access",
471                                          p_input->psz_access );
472     }
473
474     if( p_input->p_access == NULL )
475     {
476         msg_Err( p_input, "no suitable access module for `%s/%s://%s'",
477                  p_input->psz_access, p_input->psz_demux, p_input->psz_name );
478         return -1;
479     }
480
481     /* Waiting for stream. */
482     if( p_input->i_mtu )
483     {
484         p_input->i_bufsize = p_input->i_mtu;
485     }
486     else
487     {
488         p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE;
489     }
490
491     /* If the desynchronisation requested by the user is < 0, we need to
492      * cache more data. */
493     if( p_input->p_vlc->i_desync < 0 )
494         p_input->i_pts_delay -= p_input->p_vlc->i_desync;
495
496     if( p_input->p_current_data == NULL && p_input->pf_read != NULL )
497     {
498         while( !input_FillBuffer( p_input ) )
499         {
500             if( p_input->b_die || p_input->b_error || p_input->b_eof )
501             {
502                 module_Unneed( p_input, p_input->p_access );
503                 return -1;
504             }
505         }
506     }
507
508     /* Find and open appropriate demux module */
509     p_input->p_demux = module_Need( p_input, "demux",
510                                     p_input->psz_demux );
511
512     if( p_input->p_demux == NULL )
513     {
514         msg_Err( p_input, "no suitable demux module for `%s/%s://%s'",
515                  p_input->psz_access, p_input->psz_demux, p_input->psz_name );
516         module_Unneed( p_input, p_input->p_access );
517         return -1;
518     }
519
520     /* Initialize optional stream output. */
521     psz_parser = config_GetPsz( p_input, "sout" );
522     if ( psz_parser != NULL )
523     {
524         if ( *psz_parser &&
525              (p_input->stream.p_sout = sout_NewInstance( p_input, psz_parser ))
526                == NULL )
527         {
528             msg_Err( p_input, "cannot start stream output instance, aborting" );
529             free( psz_parser );
530             module_Unneed( p_input, p_input->p_access );
531             module_Unneed( p_input, p_input->p_demux );
532             return -1;
533         }
534
535         free( psz_parser );
536     }
537
538     return 0;
539 }
540
541 /*****************************************************************************
542  * ErrorThread: RunThread() error loop
543  *****************************************************************************
544  * This function is called when an error occured during thread main's loop.
545  *****************************************************************************/
546 static void ErrorThread( input_thread_t *p_input )
547 {
548     while( !p_input->b_die )
549     {
550         /* Sleep a while */
551         msleep( INPUT_IDLE_SLEEP );
552     }
553 }
554
555 /*****************************************************************************
556  * EndThread: end the input thread
557  *****************************************************************************/
558 static void EndThread( input_thread_t * p_input )
559 {
560     vlc_object_t *p_object;
561
562 #ifdef HAVE_SYS_TIMES_H
563     /* Display statistics */
564     struct tms  cpu_usage;
565     times( &cpu_usage );
566
567     msg_Dbg( p_input, "%ld loops consuming user: %ld, system: %ld",
568              p_input->c_loops, cpu_usage.tms_utime, cpu_usage.tms_stime );
569 #else
570     msg_Dbg( p_input, "%ld loops", p_input->c_loops );
571 #endif
572
573     /* Free info structures */
574     msg_Dbg( p_input, "freeing info structures...");
575     input_DelInfo( p_input );
576
577     input_DumpStream( p_input );
578
579     /* Free all ES and destroy all decoder threads */
580     input_EndStream( p_input );
581
582     /* Close optional stream output instance */
583     if ( p_input->stream.p_sout != NULL )
584     {
585         sout_DeleteInstance( p_input->stream.p_sout );
586     }
587
588     /* Free demultiplexer's data */
589     module_Unneed( p_input, p_input->p_demux );
590
591     /* Close the access plug-in */
592     module_Unneed( p_input, p_input->p_access );
593
594     input_AccessEnd( p_input );
595
596     /* Close the video output that should have been re-attached
597      * to our object */
598     p_object = vlc_object_find( p_input, VLC_OBJECT_VOUT, FIND_CHILD );
599     if( p_object )
600     {
601         vlc_object_detach( p_object );
602         vlc_object_release( p_object );
603         vout_Destroy( (vout_thread_t *)p_object );
604     }
605
606     free( p_input->psz_source );
607     if ( p_input->psz_dupsource != NULL ) free( p_input->psz_dupsource );
608
609     /* Tell we're dead */
610     p_input->b_dead = 1;
611 }
612