input.c 21 KB
Newer Older
1
2
/*****************************************************************************
 * input.c: input thread
Michel Kaempf's avatar
Michel Kaempf committed
3
4
 * Read an MPEG2 stream, demultiplex and parse it before sending it to
 * decoders.
5
 *****************************************************************************
6
 * Copyright (C) 1998-2001 VideoLAN
7
 * $Id: input.c,v 1.197 2002/05/21 01:40:17 sam Exp $
8
 *
9
 * Authors: Christophe Massiot <massiot@via.ecp.fr>
10
11
12
13
14
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
15
 * 
16
17
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18
19
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
20
 *
21
22
23
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
24
 *****************************************************************************/
Michel Kaempf's avatar
Michel Kaempf committed
25

26
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
27
 * Preamble
28
 *****************************************************************************/
29
30
31
32
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
Sam Hocevar's avatar
   
Sam Hocevar committed
33

Sam Hocevar's avatar
   
Sam Hocevar committed
34
35
#include <videolan/vlc.h>

36
#include <string.h>
Sam Hocevar's avatar
   
Sam Hocevar committed
37
38
#include <errno.h>

39
40
#ifdef HAVE_SYS_TIMES_H
#   include <sys/times.h>
41
#endif
42

Sam Hocevar's avatar
   
Sam Hocevar committed
43
#include "netutils.h"
44

Sam Hocevar's avatar
   
Sam Hocevar committed
45
#include "intf_playlist.h"
46

47
48
49
#include "stream_control.h"
#include "input_ext-intf.h"
#include "input_ext-dec.h"
50
#include "input_ext-plugins.h"
Michel Lespinasse's avatar
Yop,    
Michel Lespinasse committed
51

Sam Hocevar's avatar
   
Sam Hocevar committed
52
53
#include "interface.h"

54
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
55
 * Local prototypes
56
 *****************************************************************************/
Sam Hocevar's avatar
   
Sam Hocevar committed
57
static  int RunThread       ( input_thread_t *p_input );
Sam Hocevar's avatar
   
Sam Hocevar committed
58
59
static  int InitThread      ( input_thread_t *p_input );
static void ErrorThread     ( input_thread_t *p_input );
60
static void CloseThread     ( input_thread_t *p_input );
Sam Hocevar's avatar
   
Sam Hocevar committed
61
62
static void DestroyThread   ( input_thread_t *p_input );
static void EndThread       ( input_thread_t *p_input );
Michel Kaempf's avatar
Michel Kaempf committed
63

Sam Hocevar's avatar
   
Sam Hocevar committed
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
/*****************************************************************************
 * input_InitBank: initialize the input bank.
 *****************************************************************************/
void input_InitBank ( void )
{
    p_input_bank->i_count = 0;

    /* XXX: Workaround for old interface modules */
    p_input_bank->pp_input[0] = NULL;

    vlc_mutex_init( &p_input_bank->lock );
}

/*****************************************************************************
 * input_EndBank: empty the input bank.
 *****************************************************************************
 * This function ends all unused inputs and empties the bank in
 * case of success.
 *****************************************************************************/
void input_EndBank ( void )
{
Sam Hocevar's avatar
   
Sam Hocevar committed
85
86
    int i_input;

Sam Hocevar's avatar
   
Sam Hocevar committed
87
    /* Ask all remaining video outputs to die */
Sam Hocevar's avatar
   
Sam Hocevar committed
88
    for( i_input = 0; i_input < p_input_bank->i_count; i_input++ )
Sam Hocevar's avatar
   
Sam Hocevar committed
89
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
90
91
        input_StopThread(
                p_input_bank->pp_input[ i_input ], NULL );
Sam Hocevar's avatar
   
Sam Hocevar committed
92
        input_DestroyThread(
Sam Hocevar's avatar
   
Sam Hocevar committed
93
                p_input_bank->pp_input[ i_input ] );
Sam Hocevar's avatar
   
Sam Hocevar committed
94
95
96
97
98
    }

    vlc_mutex_destroy( &p_input_bank->lock );
}

99
/*****************************************************************************
100
 * input_CreateThread: creates a new input thread
101
 *****************************************************************************
102
103
104
105
 * This function creates a new input, and returns a pointer
 * to its description. On error, it returns NULL.
 * If pi_status is NULL, then the function will block until the thread is ready.
 * If not, it will be updated using one of the THREAD_* constants.
106
 *****************************************************************************/
Sam Hocevar's avatar
   
Sam Hocevar committed
107
input_thread_t *input_CreateThread ( playlist_item_t *p_item, int *pi_status )
Michel Kaempf's avatar
Michel Kaempf committed
108
{
109
110
    input_thread_t *    p_input;                        /* thread descriptor */

111
112
113
    /* Allocate descriptor */
    p_input = (input_thread_t *)malloc( sizeof(input_thread_t) );
    if( p_input == NULL )
Michel Kaempf's avatar
Michel Kaempf committed
114
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
115
116
        intf_ErrMsg( "input error: can't allocate input thread (%s)",
                     strerror(errno) );
Michel Kaempf's avatar
Michel Kaempf committed
117
118
        return( NULL );
    }
119
120

    /* Initialize thread properties */
Sam Hocevar's avatar
   
Sam Hocevar committed
121
122
123
    p_input->b_die      = 0;
    p_input->b_error    = 0;
    p_input->b_eof      = 0;
Sam Hocevar's avatar
   
Sam Hocevar committed
124
125

    /* Set target */
Christophe Massiot's avatar
Christophe Massiot committed
126
    p_input->psz_source = strdup( p_item->psz_name );
Sam Hocevar's avatar
   
Sam Hocevar committed
127

Sam Hocevar's avatar
   
Sam Hocevar committed
128
129
    /* Set status */
    p_input->i_status   = THREAD_CREATE;
Stéphane Borel's avatar
   
Stéphane Borel committed
130
131

    /* Demux */
Stéphane Borel's avatar
   
Stéphane Borel committed
132
    p_input->p_demux_module = NULL;
Stéphane Borel's avatar
   
Stéphane Borel committed
133
134
135
136
137
138
    p_input->pf_init    = NULL;
    p_input->pf_end     = NULL;
    p_input->pf_demux   = NULL;
    p_input->pf_rewind  = NULL;

    /* Access */
Stéphane Borel's avatar
   
Stéphane Borel committed
139
    p_input->p_access_module = NULL;
Stéphane Borel's avatar
   
Stéphane Borel committed
140
141
142
143
144
145
    p_input->pf_open        = NULL;
    p_input->pf_close       = NULL;
    p_input->pf_read        = NULL;
    p_input->pf_seek        = NULL;
    p_input->pf_set_area    = NULL;
    p_input->pf_set_program = NULL;
146
    
Sam Hocevar's avatar
   
Sam Hocevar committed
147
148
149
    p_input->i_bufsize = 0;
    p_input->i_mtu = 0;

150
151
152
153
154
155
156
157
158
    /* Initialize statistics */
    p_input->c_loops                    = 0;
    p_input->stream.c_packets_read      = 0;
    p_input->stream.c_packets_trashed   = 0;

    /* Set locks. */
    vlc_mutex_init( &p_input->stream.stream_lock );
    vlc_cond_init( &p_input->stream.stream_wait );
    vlc_mutex_init( &p_input->stream.control.control_lock );
Michel Kaempf's avatar
Michel Kaempf committed
159

160
    /* Initialize stream description */
Stéphane Borel's avatar
   
Stéphane Borel committed
161
    p_input->stream.b_changed = 0;
162
163
    p_input->stream.i_es_number = 0;
    p_input->stream.i_selected_es_number = 0;
164
    p_input->stream.i_pgrm_number = 0;
165
    p_input->stream.i_new_status = p_input->stream.i_new_rate = 0;
166
    p_input->stream.b_new_mute = MUTE_NO_CHANGE;
Christophe Massiot's avatar
Christophe Massiot committed
167
    p_input->stream.i_mux_rate = 0;
168
    p_input->stream.b_seekable = 0;
Michel Kaempf's avatar
Michel Kaempf committed
169

Sam Hocevar's avatar
   
Sam Hocevar committed
170
171
172
    /* no stream, no program, no area, no es */
    p_input->stream.p_new_program = NULL;

Stéphane Borel's avatar
   
Stéphane Borel committed
173
174
    p_input->stream.i_area_nb = 0;
    p_input->stream.pp_areas = NULL;
175
    p_input->stream.p_selected_area = NULL;
176
    p_input->stream.p_new_area = NULL;
Sam Hocevar's avatar
   
Sam Hocevar committed
177

Sam Hocevar's avatar
   
Sam Hocevar committed
178
179
180
181
    p_input->stream.pp_selected_es = NULL;
    p_input->stream.p_removed_es = NULL;
    p_input->stream.p_newly_selected_es = NULL;

Sam Hocevar's avatar
   
Sam Hocevar committed
182
    /* By default there is one area in a stream */
Stéphane Borel's avatar
   
Stéphane Borel committed
183
    input_AddArea( p_input );
184
    p_input->stream.p_selected_area = p_input->stream.pp_areas[0];
Stéphane Borel's avatar
   
Stéphane Borel committed
185

186
187
188
189
    /* Initialize stream control properties. */
    p_input->stream.control.i_status = PLAYING_S;
    p_input->stream.control.i_rate = DEFAULT_RATE;
    p_input->stream.control.b_mute = 0;
gbazin's avatar
   
gbazin committed
190
    p_input->stream.control.b_grayscale = config_GetIntVariable( "grayscale" );
191
    p_input->stream.control.i_smp = config_GetIntVariable( "vdec-smp" );
Michel Kaempf's avatar
Michel Kaempf committed
192

Christophe Massiot's avatar
Christophe Massiot committed
193
    intf_WarnMsg( 1, "input: playlist item `%s'", p_input->psz_source );
Sam Hocevar's avatar
   
Sam Hocevar committed
194

Sam Hocevar's avatar
   
Sam Hocevar committed
195
    /* Create thread. */
Sam Hocevar's avatar
   
Sam Hocevar committed
196
197
    if( vlc_thread_create( &p_input->thread_id, "input",
                           (vlc_thread_func_t)RunThread, (void *) p_input ) )
Michel Kaempf's avatar
Michel Kaempf committed
198
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
199
200
        intf_ErrMsg( "input error: can't create input thread (%s)",
                     strerror(errno) );
Michel Kaempf's avatar
Michel Kaempf committed
201
202
203
        free( p_input );
        return( NULL );
    }
204

Sam Hocevar's avatar
   
Sam Hocevar committed
205
#if 0
206
207
208
209
    /* If status is NULL, wait until the thread is created */
    if( pi_status == NULL )
    {
        do
210
        {
211
            msleep( THREAD_SLEEP );
212
        } while( (i_status != THREAD_READY) && (i_status != THREAD_ERROR)
Sam Hocevar's avatar
   
Sam Hocevar committed
213
                && (i_status != THREAD_FATAL) );
214
    }
Sam Hocevar's avatar
   
Sam Hocevar committed
215
216
#endif

Michel Kaempf's avatar
Michel Kaempf committed
217
218
219
    return( p_input );
}

220
/*****************************************************************************
Sam Hocevar's avatar
   
Sam Hocevar committed
221
 * input_StopThread: mark an input thread as zombie
222
 *****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
223
 * This function should not return until the thread is effectively cancelled.
224
 *****************************************************************************/
Sam Hocevar's avatar
   
Sam Hocevar committed
225
void input_StopThread( input_thread_t *p_input, int *pi_status )
Michel Kaempf's avatar
Michel Kaempf committed
226
{
Sam Hocevar's avatar
   
Sam Hocevar committed
227
228
    /* Make the thread exit from a possible vlc_cond_wait() */
    vlc_mutex_lock( &p_input->stream.stream_lock );
229

230
231
    /* Request thread destruction */
    p_input->b_die = 1;
Michel Kaempf's avatar
Michel Kaempf committed
232

233
234
235
    vlc_cond_signal( &p_input->stream.stream_wait );
    vlc_mutex_unlock( &p_input->stream.stream_lock );

236
    /* If status is NULL, wait until thread has been destroyed */
Sam Hocevar's avatar
   
Sam Hocevar committed
237
#if 0
238
239
240
241
242
    if( pi_status == NULL )
    {
        do
        {
            msleep( THREAD_SLEEP );
243
244
        } while ( (i_status != THREAD_OVER) && (i_status != THREAD_ERROR)
                  && (i_status != THREAD_FATAL) );
245
    }
Sam Hocevar's avatar
   
Sam Hocevar committed
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
#endif
}

/*****************************************************************************
 * input_DestroyThread: mark an input thread as zombie
 *****************************************************************************
 * This function should not return until the thread is effectively cancelled.
 *****************************************************************************/
void input_DestroyThread( input_thread_t *p_input )
{
    /* Join the thread */
    vlc_thread_join( p_input->thread_id );

    /* Destroy Mutex locks */
    vlc_mutex_destroy( &p_input->stream.control.control_lock );
Sam Hocevar's avatar
   
Sam Hocevar committed
261
    vlc_cond_destroy( &p_input->stream.stream_wait );
Sam Hocevar's avatar
   
Sam Hocevar committed
262
263
264
265
    vlc_mutex_destroy( &p_input->stream.stream_lock );
    
    /* Free input structure */
    free( p_input );
Michel Kaempf's avatar
Michel Kaempf committed
266
267
}

268
/*****************************************************************************
269
 * RunThread: main thread loop
270
 *****************************************************************************
271
 * Thread in charge of processing the network packets and demultiplexing.
272
 *****************************************************************************/
Sam Hocevar's avatar
   
Sam Hocevar committed
273
static int RunThread( input_thread_t *p_input )
Michel Kaempf's avatar
Michel Kaempf committed
274
{
Sam Hocevar's avatar
   
Sam Hocevar committed
275
276
277
    if( InitThread( p_input ) )
    {
        /* If we failed, wait before we are killed, and exit */
Sam Hocevar's avatar
   
Sam Hocevar committed
278
        p_input->i_status = THREAD_ERROR;
Sam Hocevar's avatar
   
Sam Hocevar committed
279
280
281
        p_input->b_error = 1;
        ErrorThread( p_input );
        DestroyThread( p_input );
Sam Hocevar's avatar
   
Sam Hocevar committed
282
        return 0;
Sam Hocevar's avatar
   
Sam Hocevar committed
283
    }
Michel Kaempf's avatar
Michel Kaempf committed
284

Sam Hocevar's avatar
   
Sam Hocevar committed
285
286
    p_input->i_status = THREAD_READY;

287
    /* initialization is complete */
288
289
290
291
    vlc_mutex_lock( &p_input->stream.stream_lock );
    p_input->stream.b_changed = 1;
    vlc_mutex_unlock( &p_input->stream.stream_lock );

Sam Hocevar's avatar
   
Sam Hocevar committed
292
293
    while( !p_input->b_die && !p_input->b_error && !p_input->b_eof )
    {
Christophe Massiot's avatar
Christophe Massiot committed
294
        int i, i_count;
295

Sam Hocevar's avatar
   
Sam Hocevar committed
296
        p_input->c_loops++;
Sam Hocevar's avatar
   
Sam Hocevar committed
297

298
        vlc_mutex_lock( &p_input->stream.stream_lock );
299

300
301
302
303
304
        if( p_input->stream.p_new_program )
        {
            if( p_input->pf_set_program != NULL )
            {

Johan Bilien's avatar
   
Johan Bilien committed
305
306
307
                /* Reinitialize buffer manager. */
                input_AccessReinit( p_input );
                
308
309
310
                p_input->pf_set_program( p_input, 
                        p_input->stream.p_new_program );

311
312
313
314
                /* Escape all decoders for the stream discontinuity they
                 * will encounter. */
                input_EscapeDiscontinuity( p_input );

315
316
317
318
319
320
321
322
323
324
325
326
                for( i = 0; i < p_input->stream.i_pgrm_number; i++ )
                {
                    pgrm_descriptor_t * p_pgrm
                                            = p_input->stream.pp_programs[i];

                    /* Reinitialize synchro. */
                    p_pgrm->i_synchro_state = SYNCHRO_REINIT;
                }
            }
            p_input->stream.p_new_program = NULL;
        }
        
327
328
        if( p_input->stream.p_new_area )
        {
329
330
            if( p_input->stream.b_seekable && p_input->pf_set_area != NULL )
            {
331
                input_AccessReinit( p_input );
332
333
334

                p_input->pf_set_area( p_input, p_input->stream.p_new_area );

335
336
337
338
                /* Escape all decoders for the stream discontinuity they
                 * will encounter. */
                input_EscapeDiscontinuity( p_input );

339
340
341
342
343
344
345
346
347
                for( i = 0; i < p_input->stream.i_pgrm_number; i++ )
                {
                    pgrm_descriptor_t * p_pgrm
                                            = p_input->stream.pp_programs[i];

                    /* Reinitialize synchro. */
                    p_pgrm->i_synchro_state = SYNCHRO_REINIT;
                }
            }
348
349
350
            p_input->stream.p_new_area = NULL;
        }

351
        if( p_input->stream.p_selected_area->i_seek != NO_SEEK )
Sam Hocevar's avatar
   
Sam Hocevar committed
352
        {
353
354
            if( p_input->stream.b_seekable && p_input->pf_seek != NULL )
            {
355
356
357
358
359
360
                off_t i_new_pos;

                /* Reinitialize buffer manager. */
                input_AccessReinit( p_input );

                i_new_pos = p_input->stream.p_selected_area->i_seek;
Christophe Massiot's avatar
Christophe Massiot committed
361
362
363
                vlc_mutex_unlock( &p_input->stream.stream_lock );
                p_input->pf_seek( p_input, i_new_pos );
                vlc_mutex_lock( &p_input->stream.stream_lock );
364

365
366
367
368
                /* Escape all decoders for the stream discontinuity they
                 * will encounter. */
                input_EscapeDiscontinuity( p_input );

369
370
371
372
373
374
375
376
377
                for( i = 0; i < p_input->stream.i_pgrm_number; i++ )
                {
                    pgrm_descriptor_t * p_pgrm
                                            = p_input->stream.pp_programs[i];

                    /* Reinitialize synchro. */
                    p_pgrm->i_synchro_state = SYNCHRO_REINIT;
                }
            }
378
            p_input->stream.p_selected_area->i_seek = NO_SEEK;
Sam Hocevar's avatar
   
Sam Hocevar committed
379
        }
380

381
382
383
384
385
386
387
388
389
390
391
392
        if( p_input->stream.p_removed_es )
        {
            input_UnselectES( p_input, p_input->stream.p_removed_es );
            p_input->stream.p_removed_es = NULL;
        }

        if( p_input->stream.p_newly_selected_es )
        {
            input_SelectES( p_input, p_input->stream.p_newly_selected_es );
            p_input->stream.p_newly_selected_es = NULL;
        }

393
394
395
396
397
398
399
400
401
402
403
404
405
406
        if( p_input->stream.b_new_mute != MUTE_NO_CHANGE )
        {
            if( p_input->stream.b_new_mute )
            {
                input_EscapeAudioDiscontinuity( p_input );
            }

            vlc_mutex_lock( &p_input->stream.control.control_lock );
            p_input->stream.control.b_mute = p_input->stream.b_new_mute;
            vlc_mutex_unlock( &p_input->stream.control.control_lock );

            p_input->stream.b_new_mute = MUTE_NO_CHANGE;
        }

407
        vlc_mutex_unlock( &p_input->stream.stream_lock );
Sam Hocevar's avatar
   
Sam Hocevar committed
408

Christophe Massiot's avatar
Christophe Massiot committed
409
410
        /* Read and demultiplex some data. */
        i_count = p_input->pf_demux( p_input );
Sam Hocevar's avatar
   
Sam Hocevar committed
411

412
        if( i_count == 0 && p_input->stream.b_seekable )
Sam Hocevar's avatar
   
Sam Hocevar committed
413
        {
414
415
416
417
418
419
420
421
            /* End of file - we do not set b_die because only the
             * interface is allowed to do so. */
            intf_WarnMsg( 3, "input: EOF reached" );
            p_input->b_eof = 1;
        }
        else if( i_count < 0 )
        {
            p_input->b_error = 1;
422
423
424
        }
    }

Sam Hocevar's avatar
   
Sam Hocevar committed
425
    if( p_input->b_error || p_input->b_eof )
426
427
428
    {
        ErrorThread( p_input );
    }
429

430
    EndThread( p_input );
Sam Hocevar's avatar
   
Sam Hocevar committed
431
432

    DestroyThread( p_input );
Sam Hocevar's avatar
   
Sam Hocevar committed
433
434

    return 0;
435
436
}

437
/*****************************************************************************
Sam Hocevar's avatar
   
Sam Hocevar committed
438
 * InitThread: init the input Thread
439
 *****************************************************************************/
Sam Hocevar's avatar
   
Sam Hocevar committed
440
static int InitThread( input_thread_t * p_input )
Michel Kaempf's avatar
Michel Kaempf committed
441
{
Christophe Massiot's avatar
Christophe Massiot committed
442
443
    /* Parse source string. Syntax : [[<access>][/<demux>]:][<source>] */
    char * psz_parser = p_input->psz_source;
gbazin's avatar
   
gbazin committed
444

Christophe Massiot's avatar
Christophe Massiot committed
445
446
447
448
449
    /* Skip the plug-in names */
    while( *psz_parser && *psz_parser != ':' )
    {
        psz_parser++;
    }
gbazin's avatar
   
gbazin committed
450
#ifdef WIN32
gbazin's avatar
   
gbazin committed
451
    if( psz_parser - p_input->psz_source == 1 )
gbazin's avatar
   
gbazin committed
452
453
454
    {
        intf_WarnMsg( 2, "Drive letter %c: specified in source string",
                      p_input->psz_source ) ;
Stéphane Borel's avatar
   
Stéphane Borel committed
455
        psz_parser = "";
gbazin's avatar
   
gbazin committed
456
457
    }
#endif
Sam Hocevar's avatar
   
Sam Hocevar committed
458

Christophe Massiot's avatar
Christophe Massiot committed
459
    if( !*psz_parser )
460
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
461
        p_input->psz_access = p_input->psz_demux = "";
Christophe Massiot's avatar
Christophe Massiot committed
462
        p_input->psz_name = p_input->psz_source;
Michel Kaempf's avatar
Michel Kaempf committed
463
    }
Christophe Massiot's avatar
Christophe Massiot committed
464
465
466
    else
    {
        *psz_parser++ = '\0';
467

Xavier Marchesini's avatar
   
Xavier Marchesini committed
468
469
470
471
472
473
474
        /* let's skip '//' */
        if( psz_parser[0] == '/' && psz_parser[1] == '/' )
        {
            psz_parser += 2 ;
        } 

        p_input->psz_name = psz_parser ;
Sam Hocevar's avatar
   
Sam Hocevar committed
475

Christophe Massiot's avatar
Christophe Massiot committed
476
477
        /* Come back to parse the access and demux plug-ins */
        psz_parser = p_input->psz_source;
gbazin's avatar
   
gbazin committed
478

Stéphane Borel's avatar
   
Stéphane Borel committed
479
        if( !*psz_parser )
Christophe Massiot's avatar
Christophe Massiot committed
480
481
        {
            /* No access */
Sam Hocevar's avatar
   
Sam Hocevar committed
482
            p_input->psz_access = "";
Christophe Massiot's avatar
Christophe Massiot committed
483
484
485
486
        }
        else if( *psz_parser == '/' )
        {
            /* No access */
Sam Hocevar's avatar
   
Sam Hocevar committed
487
            p_input->psz_access = "";
Christophe Massiot's avatar
Christophe Massiot committed
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
            psz_parser++;
        }
        else
        {
            p_input->psz_access = psz_parser;

            while( *psz_parser && *psz_parser != '/' )
            {
                psz_parser++;
            }

            if( *psz_parser == '/' )
            {
                *psz_parser++ = '\0';
            }
        }
gbazin's avatar
   
gbazin committed
504

Christophe Massiot's avatar
Christophe Massiot committed
505
506
507
        if( !*psz_parser )
        {
            /* No demux */
Sam Hocevar's avatar
   
Sam Hocevar committed
508
            p_input->psz_demux = "";
Christophe Massiot's avatar
Christophe Massiot committed
509
510
511
512
513
        }
        else
        {
            p_input->psz_demux = psz_parser;
        }
Sam Hocevar's avatar
   
Sam Hocevar committed
514
    }
Christophe Massiot's avatar
Christophe Massiot committed
515

Sam Hocevar's avatar
   
Sam Hocevar committed
516
    intf_WarnMsg( 2, "input: access `%s', demux `%s', name `%s'",
Christophe Massiot's avatar
Christophe Massiot committed
517
518
519
520
                  p_input->psz_access, p_input->psz_demux,
                  p_input->psz_name );

    if( input_AccessInit( p_input ) == -1 )
521
    {
Christophe Massiot's avatar
Christophe Massiot committed
522
        return( -1 );
523
    }
Christophe Massiot's avatar
Christophe Massiot committed
524
525
526
527
528
529
530

    /* Find and open appropriate access plug-in. */
    p_input->p_access_module = module_Need( MODULE_CAPABILITY_ACCESS,
                                 p_input->psz_access,
                                 (void *)p_input );

    if( p_input->p_access_module == NULL )
531
    {
Christophe Massiot's avatar
Christophe Massiot committed
532
533
534
535
        intf_ErrMsg( "input error: no suitable access plug-in for `%s/%s:%s'",
                     p_input->psz_access, p_input->psz_demux,
                     p_input->psz_name );
        return( -1 );
536
    }
Christophe Massiot's avatar
Christophe Massiot committed
537
538
539
540
541
542
543
544
545
546
547
548

#define f p_input->p_access_module->p_functions->access.functions.access
    p_input->pf_open          = f.pf_open;
    p_input->pf_close         = f.pf_close;
    p_input->pf_read          = f.pf_read;
    p_input->pf_set_area      = f.pf_set_area;
    p_input->pf_set_program   = f.pf_set_program;
    p_input->pf_seek          = f.pf_seek;
#undef f

    /* Waiting for stream. */
    if( p_input->i_mtu )
Christophe Massiot's avatar
Christophe Massiot committed
549
    {
Christophe Massiot's avatar
Christophe Massiot committed
550
        p_input->i_bufsize = p_input->i_mtu;
Christophe Massiot's avatar
Christophe Massiot committed
551
    }
552
553
    else
    {
Christophe Massiot's avatar
Christophe Massiot committed
554
        p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE;
555
    }
556

Sam Hocevar's avatar
   
Sam Hocevar committed
557
    if( p_input->p_current_data == NULL && p_input->pf_read != NULL )
558
    {
Christophe Massiot's avatar
Christophe Massiot committed
559
560
        while( !input_FillBuffer( p_input ) )
        {
561
            if( p_input->b_die || p_input->b_error || p_input->b_eof )
Christophe Massiot's avatar
Christophe Massiot committed
562
563
564
565
566
            {
                module_Unneed( p_input->p_access_module );
                return( -1 );
            }
        }
567
    }
Sam Hocevar's avatar
   
Sam Hocevar committed
568

Christophe Massiot's avatar
Christophe Massiot committed
569
570
571
572
    /* Find and open appropriate demux plug-in. */
    p_input->p_demux_module = module_Need( MODULE_CAPABILITY_DEMUX,
                                 p_input->psz_demux,
                                 (void *)p_input );
Sam Hocevar's avatar
   
Sam Hocevar committed
573

Christophe Massiot's avatar
Christophe Massiot committed
574
    if( p_input->p_demux_module == NULL )
575
    {
Christophe Massiot's avatar
Christophe Massiot committed
576
577
578
579
        intf_ErrMsg( "input error: no suitable demux plug-in for `%s/%s:%s'",
                     p_input->psz_access, p_input->psz_demux,
                     p_input->psz_name );
        module_Unneed( p_input->p_access_module );
580
581
582
        return( -1 );
    }

Christophe Massiot's avatar
Christophe Massiot committed
583
584
585
586
587
588
589
#define f p_input->p_demux_module->p_functions->demux.functions.demux
    p_input->pf_init          = f.pf_init;
    p_input->pf_end           = f.pf_end;
    p_input->pf_demux         = f.pf_demux;
    p_input->pf_rewind        = f.pf_rewind;
#undef f

Sam Hocevar's avatar
   
Sam Hocevar committed
590
    return( 0 );
Michel Kaempf's avatar
Michel Kaempf committed
591
592
}

593
/*****************************************************************************
594
 * ErrorThread: RunThread() error loop
595
 *****************************************************************************
596
 * This function is called when an error occured during thread main's loop.
597
 *****************************************************************************/
598
static void ErrorThread( input_thread_t *p_input )
Michel Kaempf's avatar
Michel Kaempf committed
599
{
600
    while( !p_input->b_die )
Michel Kaempf's avatar
Michel Kaempf committed
601
    {
602
603
        /* Sleep a while */
        msleep( INPUT_IDLE_SLEEP );
Michel Kaempf's avatar
Michel Kaempf committed
604
605
606
    }
}

607
/*****************************************************************************
608
 * EndThread: end the input thread
609
 *****************************************************************************/
610
static void EndThread( input_thread_t * p_input )
611
{
612
    /* Store status */
Sam Hocevar's avatar
   
Sam Hocevar committed
613
    p_input->i_status = THREAD_END;
Sam Hocevar's avatar
Sam Hocevar committed
614

615
    if( p_main->b_stats )
Sam Hocevar's avatar
   
Sam Hocevar committed
616
    {
617
#ifdef HAVE_SYS_TIMES_H
618
619
        /* Display statistics */
        struct tms  cpu_usage;
Sam Hocevar's avatar
   
Sam Hocevar committed
620
621
        times( &cpu_usage );

622
623
624
        intf_StatMsg( "input stats: %d loops consuming user: %d, system: %d",
                      p_input->c_loops,
                      cpu_usage.tms_utime, cpu_usage.tms_stime );
625
626
627
#else
        intf_StatMsg( "input stats: %d loops", p_input->c_loops );
#endif
628
629

        input_DumpStream( p_input );
Sam Hocevar's avatar
   
Sam Hocevar committed
630
631
632
633
634
635
636
    }

    /* Free all ES and destroy all decoder threads */
    input_EndStream( p_input );

    /* Free demultiplexer's data */
    p_input->pf_end( p_input );
Christophe Massiot's avatar
Christophe Massiot committed
637
    module_Unneed( p_input->p_demux_module );
Sam Hocevar's avatar
   
Sam Hocevar committed
638

Christophe Massiot's avatar
Christophe Massiot committed
639
    /* Close the access plug-in */
Sam Hocevar's avatar
   
Sam Hocevar committed
640
641
642
643
644
645
646
647
    CloseThread( p_input );
}

/*****************************************************************************
 * CloseThread: close the target
 *****************************************************************************/
static void CloseThread( input_thread_t * p_input )
{
Christophe Massiot's avatar
Christophe Massiot committed
648
649
    p_input->pf_close( p_input );
    module_Unneed( p_input->p_access_module );
Sam Hocevar's avatar
   
Sam Hocevar committed
650

Christophe Massiot's avatar
Christophe Massiot committed
651
652
653
    input_AccessEnd( p_input );

    free( p_input->psz_source );
Sam Hocevar's avatar
   
Sam Hocevar committed
654
655
656
657
658
659
660
}

/*****************************************************************************
 * DestroyThread: destroy the input thread
 *****************************************************************************/
static void DestroyThread( input_thread_t * p_input )
{
661
    /* Update status */
Sam Hocevar's avatar
   
Sam Hocevar committed
662
    p_input->i_status = THREAD_OVER;
Sam Hocevar's avatar
Sam Hocevar committed
663
}
664