input.c 20 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
Christophe Massiot's avatar
Christophe Massiot committed
7
 * $Id: input.c,v 1.180 2002/03/01 00:33:18 massiot Exp $
8
 *
9
 * Authors: Christophe Massiot <massiot@via.ecp.fr>
Christophe Massiot's avatar
Christophe Massiot committed
10
 *          Alexis Guillard <alexis.guillard@bt.com>
11
12
13
14
15
 *
 * 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.
16
 * 
17
18
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
20
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
21
 *
22
23
24
 * 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.
25
 *****************************************************************************/
Michel Kaempf's avatar
Michel Kaempf committed
26

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

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

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

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

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

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

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

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

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

Sam Hocevar's avatar
   
Sam Hocevar committed
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
/*****************************************************************************
 * 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
86
87
    int i_input;

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

    vlc_mutex_destroy( &p_input_bank->lock );
}

100
/*****************************************************************************
101
 * input_CreateThread: creates a new input thread
102
 *****************************************************************************
103
104
105
106
 * 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.
107
 *****************************************************************************/
Sam Hocevar's avatar
   
Sam Hocevar committed
108
input_thread_t *input_CreateThread ( playlist_item_t *p_item, int *pi_status )
Michel Kaempf's avatar
Michel Kaempf committed
109
{
110
111
    input_thread_t *    p_input;                        /* thread descriptor */

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

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

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

Sam Hocevar's avatar
   
Sam Hocevar committed
129
130
    /* Set status */
    p_input->i_status   = THREAD_CREATE;
131
132
133
134
135
136
137
138
139
140
    
    /* 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
141

142
    /* Initialize stream description */
Stéphane Borel's avatar
   
Stéphane Borel committed
143
    p_input->stream.b_changed = 0;
144
145
    p_input->stream.i_es_number = 0;
    p_input->stream.i_selected_es_number = 0;
146
    p_input->stream.i_pgrm_number = 0;
147
    p_input->stream.i_new_status = p_input->stream.i_new_rate = 0;
148
    p_input->stream.b_new_mute = MUTE_NO_CHANGE;
Christophe Massiot's avatar
Christophe Massiot committed
149
    p_input->stream.i_mux_rate = 0;
Michel Kaempf's avatar
Michel Kaempf committed
150

Sam Hocevar's avatar
   
Sam Hocevar committed
151
152
153
    /* no stream, no program, no area, no es */
    p_input->stream.p_new_program = NULL;

Stéphane Borel's avatar
   
Stéphane Borel committed
154
155
    p_input->stream.i_area_nb = 0;
    p_input->stream.pp_areas = NULL;
156
    p_input->stream.p_selected_area = NULL;
157
    p_input->stream.p_new_area = NULL;
Sam Hocevar's avatar
   
Sam Hocevar committed
158

Sam Hocevar's avatar
   
Sam Hocevar committed
159
160
161
162
    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
163
    /* By default there is one area in a stream */
Stéphane Borel's avatar
   
Stéphane Borel committed
164
    input_AddArea( p_input );
165
    p_input->stream.p_selected_area = p_input->stream.pp_areas[0];
Stéphane Borel's avatar
   
Stéphane Borel committed
166

167
168
169
170
    /* 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
171
172
173
    p_input->stream.control.b_grayscale = config_GetIntVariable(
			                      VOUT_GRAYSCALE_VAR );
    p_input->stream.control.i_smp = config_GetIntVariable( VDEC_SMP_VAR );
Michel Kaempf's avatar
Michel Kaempf committed
174

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

Sam Hocevar's avatar
   
Sam Hocevar committed
177
    /* Create thread. */
Sam Hocevar's avatar
   
Sam Hocevar committed
178
179
    if( vlc_thread_create( &p_input->thread_id, "input",
                           (vlc_thread_func_t)RunThread, (void *) p_input ) )
Michel Kaempf's avatar
Michel Kaempf committed
180
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
181
182
        intf_ErrMsg( "input error: can't create input thread (%s)",
                     strerror(errno) );
Michel Kaempf's avatar
Michel Kaempf committed
183
184
185
        free( p_input );
        return( NULL );
    }
186

Sam Hocevar's avatar
   
Sam Hocevar committed
187
#if 0
188
189
190
191
    /* If status is NULL, wait until the thread is created */
    if( pi_status == NULL )
    {
        do
192
        {
193
            msleep( THREAD_SLEEP );
194
        } while( (i_status != THREAD_READY) && (i_status != THREAD_ERROR)
Sam Hocevar's avatar
   
Sam Hocevar committed
195
                && (i_status != THREAD_FATAL) );
196
    }
Sam Hocevar's avatar
   
Sam Hocevar committed
197
198
#endif

Michel Kaempf's avatar
Michel Kaempf committed
199
200
201
    return( p_input );
}

202
/*****************************************************************************
Sam Hocevar's avatar
   
Sam Hocevar committed
203
 * input_StopThread: mark an input thread as zombie
204
 *****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
205
 * This function should not return until the thread is effectively cancelled.
206
 *****************************************************************************/
Sam Hocevar's avatar
   
Sam Hocevar committed
207
void input_StopThread( input_thread_t *p_input, int *pi_status )
Michel Kaempf's avatar
Michel Kaempf committed
208
{
Sam Hocevar's avatar
   
Sam Hocevar committed
209
210
    /* Make the thread exit from a possible vlc_cond_wait() */
    vlc_mutex_lock( &p_input->stream.stream_lock );
211

212
213
    /* Request thread destruction */
    p_input->b_die = 1;
Michel Kaempf's avatar
Michel Kaempf committed
214

215
216
217
    vlc_cond_signal( &p_input->stream.stream_wait );
    vlc_mutex_unlock( &p_input->stream.stream_lock );

218
    /* If status is NULL, wait until thread has been destroyed */
Sam Hocevar's avatar
   
Sam Hocevar committed
219
#if 0
220
221
222
223
224
    if( pi_status == NULL )
    {
        do
        {
            msleep( THREAD_SLEEP );
225
226
        } while ( (i_status != THREAD_OVER) && (i_status != THREAD_ERROR)
                  && (i_status != THREAD_FATAL) );
227
    }
Sam Hocevar's avatar
   
Sam Hocevar committed
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
#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
243
    vlc_cond_destroy( &p_input->stream.stream_wait );
Sam Hocevar's avatar
   
Sam Hocevar committed
244
245
246
247
    vlc_mutex_destroy( &p_input->stream.stream_lock );
    
    /* Free input structure */
    free( p_input );
Michel Kaempf's avatar
Michel Kaempf committed
248
249
}

250
/*****************************************************************************
251
 * RunThread: main thread loop
252
 *****************************************************************************
253
 * Thread in charge of processing the network packets and demultiplexing.
254
 *****************************************************************************/
Sam Hocevar's avatar
   
Sam Hocevar committed
255
static int RunThread( input_thread_t *p_input )
Michel Kaempf's avatar
Michel Kaempf committed
256
{
Sam Hocevar's avatar
   
Sam Hocevar committed
257
258
259
    if( InitThread( p_input ) )
    {
        /* If we failed, wait before we are killed, and exit */
Sam Hocevar's avatar
   
Sam Hocevar committed
260
        p_input->i_status = THREAD_ERROR;
Sam Hocevar's avatar
   
Sam Hocevar committed
261
262
263
        p_input->b_error = 1;
        ErrorThread( p_input );
        DestroyThread( p_input );
Sam Hocevar's avatar
   
Sam Hocevar committed
264
        return 0;
Sam Hocevar's avatar
   
Sam Hocevar committed
265
    }
Michel Kaempf's avatar
Michel Kaempf committed
266

Sam Hocevar's avatar
   
Sam Hocevar committed
267
268
    p_input->i_status = THREAD_READY;

269
    /* initialization is complete */
270
271
272
273
    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
274
275
    while( !p_input->b_die && !p_input->b_error && !p_input->b_eof )
    {
Christophe Massiot's avatar
Christophe Massiot committed
276
        int i, i_count;
277

Sam Hocevar's avatar
   
Sam Hocevar committed
278
        p_input->c_loops++;
Sam Hocevar's avatar
   
Sam Hocevar committed
279

280
        vlc_mutex_lock( &p_input->stream.stream_lock );
281

282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
        if( p_input->stream.p_new_program )
        {
            if( p_input->pf_set_program != NULL )
            {

                p_input->pf_set_program( p_input, 
                        p_input->stream.p_new_program );

                for( i = 0; i < p_input->stream.i_pgrm_number; i++ )
                {
                    pgrm_descriptor_t * p_pgrm
                                            = p_input->stream.pp_programs[i];
                    /* Escape all decoders for the stream discontinuity they
                     * will encounter. */
                    input_EscapeDiscontinuity( p_input, p_pgrm );

                    /* Reinitialize synchro. */
                    p_pgrm->i_synchro_state = SYNCHRO_REINIT;
                }
            }
            p_input->stream.p_new_program = NULL;
        }
        
305
306
        if( p_input->stream.p_new_area )
        {
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
            if( p_input->stream.b_seekable && p_input->pf_set_area != NULL )
            {

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

                for( i = 0; i < p_input->stream.i_pgrm_number; i++ )
                {
                    pgrm_descriptor_t * p_pgrm
                                            = p_input->stream.pp_programs[i];
                    /* Escape all decoders for the stream discontinuity they
                     * will encounter. */
                    input_EscapeDiscontinuity( p_input, p_pgrm );

                    /* Reinitialize synchro. */
                    p_pgrm->i_synchro_state = SYNCHRO_REINIT;
                }
            }
324
325
326
            p_input->stream.p_new_area = NULL;
        }

327
        if( p_input->stream.p_selected_area->i_seek != NO_SEEK )
Sam Hocevar's avatar
   
Sam Hocevar committed
328
        {
329
330
            if( p_input->stream.b_seekable && p_input->pf_seek != NULL )
            {
Christophe Massiot's avatar
Christophe Massiot committed
331
332
333
334
                off_t i_new_pos = p_input->stream.p_selected_area->i_seek;
                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 );
335
336
337
338
339
340
341
342
343
344
345
346

                for( i = 0; i < p_input->stream.i_pgrm_number; i++ )
                {
                    pgrm_descriptor_t * p_pgrm
                                            = p_input->stream.pp_programs[i];
                    /* Escape all decoders for the stream discontinuity they
                     * will encounter. */
                    input_EscapeDiscontinuity( p_input, p_pgrm );

                    /* Reinitialize synchro. */
                    p_pgrm->i_synchro_state = SYNCHRO_REINIT;
                }
Christophe Massiot's avatar
Christophe Massiot committed
347
348
349

                /* Reinitialize buffer manager. */
                input_AccessReinit( p_input );
350
            }
351
            p_input->stream.p_selected_area->i_seek = NO_SEEK;
Sam Hocevar's avatar
   
Sam Hocevar committed
352
        }
353

354
355
356
357
358
359
360
361
362
363
364
365
        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;
        }

366
367
368
369
370
371
372
373
374
375
376
377
378
379
        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;
        }

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

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

385
        if( i_count == 0 && p_input->stream.b_seekable )
Sam Hocevar's avatar
   
Sam Hocevar committed
386
        {
387
388
389
390
391
392
393
394
            /* 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;
395
396
397
        }
    }

Sam Hocevar's avatar
   
Sam Hocevar committed
398
    if( p_input->b_error || p_input->b_eof )
399
400
401
    {
        ErrorThread( p_input );
    }
402

403
    EndThread( p_input );
Sam Hocevar's avatar
   
Sam Hocevar committed
404
405

    DestroyThread( p_input );
Sam Hocevar's avatar
   
Sam Hocevar committed
406
407

    return 0;
408
409
}

410
/*****************************************************************************
Sam Hocevar's avatar
   
Sam Hocevar committed
411
 * InitThread: init the input Thread
412
 *****************************************************************************/
Sam Hocevar's avatar
   
Sam Hocevar committed
413
static int InitThread( input_thread_t * p_input )
Michel Kaempf's avatar
Michel Kaempf committed
414
{
Christophe Massiot's avatar
Christophe Massiot committed
415
416
    /* Parse source string. Syntax : [[<access>][/<demux>]:][<source>] */
    char * psz_parser = p_input->psz_source;
gbazin's avatar
   
gbazin committed
417

Christophe Massiot's avatar
Christophe Massiot committed
418
419
420
421
422
    /* Skip the plug-in names */
    while( *psz_parser && *psz_parser != ':' )
    {
        psz_parser++;
    }
Sam Hocevar's avatar
   
Sam Hocevar committed
423

Christophe Massiot's avatar
Christophe Massiot committed
424
    if( !*psz_parser )
425
    {
Christophe Massiot's avatar
Christophe Massiot committed
426
427
        p_input->psz_access = p_input->psz_demux = NULL;
        p_input->psz_name = p_input->psz_source;
Michel Kaempf's avatar
Michel Kaempf committed
428
    }
Christophe Massiot's avatar
Christophe Massiot committed
429
430
431
    else
    {
        *psz_parser++ = '\0';
432

Christophe Massiot's avatar
Christophe Massiot committed
433
        p_input->psz_name = psz_parser;
Sam Hocevar's avatar
   
Sam Hocevar committed
434

Christophe Massiot's avatar
Christophe Massiot committed
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
        /* Come back to parse the access and demux plug-ins */
        psz_parser = p_input->psz_source;
        if( !*psz_parser )
        {
            /* No access */
            p_input->psz_access = NULL;
        }
        else if( *psz_parser == '/' )
        {
            /* No access */
            p_input->psz_access = NULL;
            psz_parser++;
        }
        else
        {
            p_input->psz_access = psz_parser;

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

            if( *psz_parser == '/' )
            {
                *psz_parser++ = '\0';
            }
        }

        if( !*psz_parser )
        {
            /* No demux */
            p_input->psz_demux = NULL;
        }
        else
        {
            p_input->psz_demux = psz_parser;
        }
Sam Hocevar's avatar
   
Sam Hocevar committed
472
    }
Christophe Massiot's avatar
Christophe Massiot committed
473
474
475
476
477
478

    intf_WarnMsg( 2, "input: access=%s demux=%s name=%s",
                  p_input->psz_access, p_input->psz_demux,
                  p_input->psz_name );

    if( input_AccessInit( p_input ) == -1 )
479
    {
Christophe Massiot's avatar
Christophe Massiot committed
480
        return( -1 );
481
    }
Christophe Massiot's avatar
Christophe Massiot committed
482
483
484
485
486
487
488

    /* 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 )
489
    {
Christophe Massiot's avatar
Christophe Massiot committed
490
491
492
493
        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 );
494
    }
Christophe Massiot's avatar
Christophe Massiot committed
495
496
497
498
499
500
501
502
503
504
505
506

#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
507
    {
Christophe Massiot's avatar
Christophe Massiot committed
508
        p_input->i_bufsize = p_input->i_mtu;
Christophe Massiot's avatar
Christophe Massiot committed
509
    }
510
511
    else
    {
Christophe Massiot's avatar
Christophe Massiot committed
512
        p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE;
513
    }
514

Christophe Massiot's avatar
Christophe Massiot committed
515
    if( p_input->p_current_data == NULL )
516
    {
Christophe Massiot's avatar
Christophe Massiot committed
517
518
519
520
521
522
523
524
        while( !input_FillBuffer( p_input ) )
        {
            if( p_input->b_die || p_input->b_error )
            {
                module_Unneed( p_input->p_access_module );
                return( -1 );
            }
        }
525
    }
Sam Hocevar's avatar
   
Sam Hocevar committed
526

Christophe Massiot's avatar
Christophe Massiot committed
527
528
529
530
    /* 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
531

Christophe Massiot's avatar
Christophe Massiot committed
532
    if( p_input->p_demux_module == NULL )
533
    {
Christophe Massiot's avatar
Christophe Massiot committed
534
535
536
537
        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 );
538
539
540
        return( -1 );
    }

Christophe Massiot's avatar
Christophe Massiot committed
541
542
543
544
545
546
547
#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
548
    return( 0 );
Michel Kaempf's avatar
Michel Kaempf committed
549
550
}

551
/*****************************************************************************
552
 * ErrorThread: RunThread() error loop
553
 *****************************************************************************
554
 * This function is called when an error occured during thread main's loop.
555
 *****************************************************************************/
556
static void ErrorThread( input_thread_t *p_input )
Michel Kaempf's avatar
Michel Kaempf committed
557
{
558
    while( !p_input->b_die )
Michel Kaempf's avatar
Michel Kaempf committed
559
    {
560
561
        /* Sleep a while */
        msleep( INPUT_IDLE_SLEEP );
Michel Kaempf's avatar
Michel Kaempf committed
562
563
564
    }
}

565
/*****************************************************************************
566
 * EndThread: end the input thread
567
 *****************************************************************************/
568
static void EndThread( input_thread_t * p_input )
569
{
570
    /* Store status */
Sam Hocevar's avatar
   
Sam Hocevar committed
571
    p_input->i_status = THREAD_END;
Sam Hocevar's avatar
Sam Hocevar committed
572

573
    if( p_main->b_stats )
Sam Hocevar's avatar
   
Sam Hocevar committed
574
    {
575
#ifdef HAVE_SYS_TIMES_H
576
577
        /* Display statistics */
        struct tms  cpu_usage;
Sam Hocevar's avatar
   
Sam Hocevar committed
578
579
        times( &cpu_usage );

580
581
582
        intf_StatMsg( "input stats: %d loops consuming user: %d, system: %d",
                      p_input->c_loops,
                      cpu_usage.tms_utime, cpu_usage.tms_stime );
583
584
585
#else
        intf_StatMsg( "input stats: %d loops", p_input->c_loops );
#endif
586
587

        input_DumpStream( p_input );
Sam Hocevar's avatar
   
Sam Hocevar committed
588
589
590
591
592
593
594
    }

    /* 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
595
    module_Unneed( p_input->p_demux_module );
Sam Hocevar's avatar
   
Sam Hocevar committed
596

Christophe Massiot's avatar
Christophe Massiot committed
597
    /* Close the access plug-in */
Sam Hocevar's avatar
   
Sam Hocevar committed
598
599
600
601
602
603
604
605
    CloseThread( p_input );
}

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

Christophe Massiot's avatar
Christophe Massiot committed
609
610
611
    input_AccessEnd( p_input );

    free( p_input->psz_source );
Sam Hocevar's avatar
   
Sam Hocevar committed
612
613
614
615
616
617
618
}

/*****************************************************************************
 * DestroyThread: destroy the input thread
 *****************************************************************************/
static void DestroyThread( input_thread_t * p_input )
{
619
    /* Update status */
Sam Hocevar's avatar
   
Sam Hocevar committed
620
    p_input->i_status = THREAD_OVER;
Sam Hocevar's avatar
Sam Hocevar committed
621
}
622