input.c 43.5 KB
Newer Older
1 2
/*****************************************************************************
 * input.c: input thread
3
 * Read a stream, demultiplex and parse it before sending it to
Michel Kaempf's avatar
Michel Kaempf committed
4
 * decoders.
5
 *****************************************************************************
6
 * Copyright (C) 1998-2004 VideoLAN
7
 * $Id$
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
#include <stdlib.h>
30

31
#include <vlc/vlc.h>
32
#include <vlc/input.h>
33
#include <vlc/decoder.h>
34
#include <vlc/vout.h>
35

36 37
#ifdef HAVE_SYS_TIMES_H
#   include <sys/times.h>
38
#endif
39

40
#include "vlc_playlist.h"
41

42 43
#include "stream_output.h"

44
#include "vlc_interface.h"
45
#include "codecs.h"
46
#include "vlc_meta.h"
47
#include "../../modules/demux/util/sub.h"
48

49
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
50
 * Local prototypes
51
 *****************************************************************************/
52 53 54 55 56
struct input_thread_sys_t
{
    /* subtitles */
    int              i_sub;
    subtitle_demux_t **sub;
57 58

    int64_t          i_stop_time;
59 60
};

61
static  int RunThread       ( input_thread_t *p_input );
62 63 64
static  int InitThread      ( input_thread_t *p_input );
static void ErrorThread     ( input_thread_t *p_input );
static void EndThread       ( input_thread_t *p_input );
Michel Kaempf's avatar
Michel Kaempf committed
65

66 67
static void ParseOption     ( input_thread_t *p_input,
                              const char *psz_option );
68

69 70 71 72 73 74 75 76 77 78 79
/*****************************************************************************
 * Callbacks
 *****************************************************************************/
static int PositionCallback( vlc_object_t *p_this, char const *psz_cmd,
                             vlc_value_t oldval, vlc_value_t newval, void *p_data );
static int TimeCallback    ( vlc_object_t *p_this, char const *psz_cmd,
                             vlc_value_t oldval, vlc_value_t newval, void *p_data );
static int StateCallback   ( vlc_object_t *p_this, char const *psz_cmd,
                             vlc_value_t oldval, vlc_value_t newval, void *p_data );
static int RateCallback    ( vlc_object_t *p_this, char const *psz_cmd,
                             vlc_value_t oldval, vlc_value_t newval, void *p_data );
80

81
/*****************************************************************************
82
 * input_CreateThread: creates a new input thread
83
 *****************************************************************************
84 85
 * This function creates a new input, and returns a pointer
 * to its description. On error, it returns NULL.
86
 *****************************************************************************/
87 88 89
input_thread_t *__input_CreateThread( vlc_object_t *p_parent, char *psz_uri,
                                      char **ppsz_options, int i_options )

Michel Kaempf's avatar
Michel Kaempf committed
90
{
91
    input_thread_t *    p_input;                        /* thread descriptor */
92
    vlc_value_t val;
93
    int i;
94

95
    /* Allocate descriptor */
96
    p_input = vlc_object_create( p_parent, VLC_OBJECT_INPUT );
97
    if( p_input == NULL )
Michel Kaempf's avatar
Michel Kaempf committed
98
    {
99
        msg_Err( p_parent, "out of memory" );
100
        return NULL;
Michel Kaempf's avatar
Michel Kaempf committed
101
    }
102

103
    /* Parse input options */
104
    for( i = 0; i < i_options; i++ )
105
    {
106 107
        msg_Dbg( p_input, "option: %s", ppsz_options[i] );
        ParseOption( p_input, ppsz_options[i] );
108 109
    }

110 111 112 113 114
    /* Create a few object variables we'll need later on */
    var_Create( p_input, "video", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
    var_Create( p_input, "audio", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
    var_Create( p_input, "audio-channel", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
    var_Create( p_input, "spu-channel", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
115 116
    var_Create( p_input, "sub-file", VLC_VAR_FILE | VLC_VAR_DOINHERIT );
    var_Create( p_input, "sub-autodetect-file", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
117
    var_Create( p_input, "sub-autodetect-fuzzy", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
118 119

    var_Create( p_input, "sout", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
120
    var_Create( p_input, "sout-all",   VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
121 122
    var_Create( p_input, "sout-audio", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
    var_Create( p_input, "sout-video", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
123 124
    var_Create( p_input, "sout-keep",  VLC_VAR_BOOL | VLC_VAR_DOINHERIT );

125 126 127
    /* repeat variable */
    var_Create( p_input, "input-repeat", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );

128 129 130 131
    /* start/stop time */
    var_Create( p_input, "start-time", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
    var_Create( p_input, "stop-time", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );

132 133 134
    /* decoders */
    var_Create( p_input, "minimize-threads", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );

135 136 137
    /* play status */

    /* position variable */
138 139
    var_Create( p_input, "position",  VLC_VAR_FLOAT );  /* position 0.0->1.0 */
    var_Create( p_input, "position-offset",  VLC_VAR_FLOAT );  /* relative */
140 141 142
    val.f_float = 0.0;
    var_Change( p_input, "position", VLC_VAR_SETVALUE, &val, NULL );
    var_AddCallback( p_input, "position", PositionCallback, NULL );
143
    var_AddCallback( p_input, "position-offset", PositionCallback, NULL );
144 145 146

    /* time variable */
    var_Create( p_input, "time",  VLC_VAR_TIME );
147
    var_Create( p_input, "time-offset",  VLC_VAR_TIME );    /* relative */
148 149 150
    val.i_time = 0;
    var_Change( p_input, "time", VLC_VAR_SETVALUE, &val, NULL );
    var_AddCallback( p_input, "time", TimeCallback, NULL );
151
    var_AddCallback( p_input, "time-offset", TimeCallback, NULL );
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173

    /* length variable */
    var_Create( p_input, "length",  VLC_VAR_TIME );
    val.i_time = 0;
    var_Change( p_input, "length", VLC_VAR_SETVALUE, &val, NULL );

    /* rate variable */
    var_Create( p_input, "rate", VLC_VAR_INTEGER );
    var_Create( p_input, "rate-slower", VLC_VAR_VOID );
    var_Create( p_input, "rate-faster", VLC_VAR_VOID );
    val.i_int = DEFAULT_RATE;
    var_Change( p_input, "rate", VLC_VAR_SETVALUE, &val, NULL );
    var_AddCallback( p_input, "rate", RateCallback, NULL );
    var_AddCallback( p_input, "rate-slower", RateCallback, NULL );
    var_AddCallback( p_input, "rate-faster", RateCallback, NULL );

    /* state variable */
    var_Create( p_input, "state", VLC_VAR_INTEGER );
    val.i_int = INIT_S;
    var_Change( p_input, "state", VLC_VAR_SETVALUE, &val, NULL );
    var_AddCallback( p_input, "state", StateCallback, NULL );

174 175 176 177
    /* state variable */
    var_Create( p_input, "demuxed-id3", VLC_VAR_BOOL );
    val.b_bool = VLC_FALSE;
    var_Change( p_input, "demuxed-id3", VLC_VAR_SETVALUE, &val, NULL );
178

179
    /* Initialize thread properties */
180
    p_input->b_eof      = 0;
181
    p_input->p_sys      = NULL;
182 183

    /* Set target */
184
    p_input->psz_source = strdup( psz_uri );
185

186 187 188
    /* Stream */
    p_input->s = NULL;

189 190 191
    /* es out */
    p_input->p_es_out = NULL;

192
    /* Demux */
193 194 195 196
    p_input->p_demux   = NULL;
    p_input->pf_demux  = NULL;
    p_input->pf_rewind = NULL;
    p_input->pf_demux_control = NULL;
197
    p_input->i_cr_average = config_GetInt( p_input, "cr-average" );
198 199

    /* Access */
200
    p_input->p_access = NULL;
201

202 203
    p_input->i_bufsize = 0;
    p_input->i_mtu = 0;
204
    p_input->i_pts_delay = DEFAULT_PTS_DELAY;
205

206 207 208 209 210 211
    /* Initialize statistics */
    p_input->c_loops                    = 0;
    p_input->stream.c_packets_read      = 0;
    p_input->stream.c_packets_trashed   = 0;

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

216
    /* Initialize stream description */
217
    p_input->stream.b_changed = 0;
218 219
    p_input->stream.i_es_number = 0;
    p_input->stream.i_selected_es_number = 0;
220
    p_input->stream.i_pgrm_number = 0;
221
    p_input->stream.i_new_status = p_input->stream.i_new_rate = 0;
222
    p_input->stream.b_new_mute = MUTE_NO_CHANGE;
Christophe Massiot's avatar
Christophe Massiot committed
223
    p_input->stream.i_mux_rate = 0;
224
    p_input->stream.b_seekable = 0;
225
    p_input->stream.p_sout = NULL;
Michel Kaempf's avatar
Michel Kaempf committed
226

227 228 229
    /* no stream, no program, no area, no es */
    p_input->stream.p_new_program = NULL;

230 231
    p_input->stream.i_area_nb = 0;
    p_input->stream.pp_areas = NULL;
232
    p_input->stream.p_selected_area = NULL;
233
    p_input->stream.p_new_area = NULL;
234

235 236 237 238
    p_input->stream.pp_selected_es = NULL;
    p_input->stream.p_removed_es = NULL;
    p_input->stream.p_newly_selected_es = NULL;

239
    /* By default there is one area in a stream */
240
    input_AddArea( p_input, 0, 1 );
241
    p_input->stream.p_selected_area = p_input->stream.pp_areas[0];
242

243
    /* Initialize stream control properties. */
244
    p_input->stream.control.i_status = INIT_S;
245 246
    p_input->stream.control.i_rate = DEFAULT_RATE;
    p_input->stream.control.b_mute = 0;
247
    p_input->stream.control.b_grayscale = config_GetInt( p_input, "grayscale");
248

249
    msg_Info( p_input, "playlist item `%s'", p_input->psz_source );
Michel Kaempf's avatar
Michel Kaempf committed
250

251 252 253 254 255
    /* Initialize input info */
    p_input->stream.p_info = NULL;
    p_input->stream.p_info = input_InfoCategory( p_input, _("General") );
    input_AddInfo( p_input->stream.p_info, _("Playlist Item"),
                   p_input->psz_source );
256
    vlc_object_attach( p_input, p_parent );
257

Sam Hocevar's avatar
Sam Hocevar committed
258
    /* Create thread and wait for its readiness. */
259 260
    if( vlc_thread_create( p_input, "input", RunThread,
                           VLC_THREAD_PRIORITY_INPUT, VLC_TRUE ) )
Michel Kaempf's avatar
Michel Kaempf committed
261
    {
262
        msg_Err( p_input, "cannot create input thread" );
263
        input_DelInfo( p_input );
Michel Kaempf's avatar
Michel Kaempf committed
264
        free( p_input );
265
        return NULL;
Michel Kaempf's avatar
Michel Kaempf committed
266
    }
267

268
    return p_input;
Michel Kaempf's avatar
Michel Kaempf committed
269 270
}

271
/*****************************************************************************
272
 * input_StopThread: mark an input thread as zombie
273
 *****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
274
 * This function should not return until the thread is effectively cancelled.
275
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
276
void input_StopThread( input_thread_t *p_input )
Michel Kaempf's avatar
Michel Kaempf committed
277
{
278 279
    /* Make the thread exit from a possible vlc_cond_wait() */
    vlc_mutex_lock( &p_input->stream.stream_lock );
280 281
    /* Request thread destruction */
    p_input->b_die = 1;
Michel Kaempf's avatar
Michel Kaempf committed
282

283 284
    vlc_cond_signal( &p_input->stream.stream_wait );
    vlc_mutex_unlock( &p_input->stream.stream_lock );
285 286 287 288 289 290 291 292 293 294
}

/*****************************************************************************
 * 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 */
295
    vlc_thread_join( p_input );
296 297 298

    /* Destroy Mutex locks */
    vlc_mutex_destroy( &p_input->stream.control.control_lock );
299
    vlc_cond_destroy( &p_input->stream.stream_wait );
300
    vlc_mutex_destroy( &p_input->stream.stream_lock );
Michel Kaempf's avatar
Michel Kaempf committed
301 302
}

303
/*****************************************************************************
304
 * RunThread: main thread loop
305
 *****************************************************************************
306
 * Thread in charge of processing the network packets and demultiplexing.
307
 *****************************************************************************/
308
static int RunThread( input_thread_t *p_input )
Michel Kaempf's avatar
Michel Kaempf committed
309
{
310 311 312
    vlc_value_t  val;
    mtime_t      i_update_next = -1;

Sam Hocevar's avatar
Sam Hocevar committed
313 314 315
    /* Signal right now, otherwise we'll get stuck in a peek */
    vlc_thread_ready( p_input );

316 317 318 319
    if( InitThread( p_input ) )
    {
        /* If we failed, wait before we are killed, and exit */
        p_input->b_error = 1;
320

321
        ErrorThread( p_input );
322 323 324 325

        /* Tell we're dead */
        p_input->b_dead = 1;

326 327
        input_DelInfo( p_input );

328
        return 0;
329
    }
Michel Kaempf's avatar
Michel Kaempf committed
330

331
    /* initialization is complete */
332
    vlc_mutex_lock( &p_input->stream.stream_lock );
333 334
    p_input->stream.b_changed        = 1;
    p_input->stream.control.i_status = PLAYING_S;
335 336
    vlc_mutex_unlock( &p_input->stream.stream_lock );

337 338 339
    val.i_int = PLAYING_S;
    var_Change( p_input, "state", VLC_VAR_SETVALUE, &val, NULL );

340 341
    while( !p_input->b_die && !p_input->b_error && !p_input->b_eof )
    {
342
        unsigned int i, i_count;
343

344
        p_input->c_loops++;
345

346
        vlc_mutex_lock( &p_input->stream.stream_lock );
347

348 349 350 351 352
        if( p_input->stream.p_new_program )
        {
            if( p_input->pf_set_program != NULL )
            {

353 354
                /* Reinitialize buffer manager. */
                input_AccessReinit( p_input );
355 356

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

359 360 361 362
                /* Escape all decoders for the stream discontinuity they
                 * will encounter. */
                input_EscapeDiscontinuity( p_input );

363 364 365 366 367 368 369 370 371 372 373
                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;
        }
374

375 376
        if( p_input->stream.p_new_area )
        {
377 378
            if( p_input->stream.b_seekable && p_input->pf_set_area != NULL )
            {
379
                input_AccessReinit( p_input );
380 381 382

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

383 384 385 386
                /* Escape all decoders for the stream discontinuity they
                 * will encounter. */
                input_EscapeDiscontinuity( p_input );

387 388 389 390 391 392 393 394 395
                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;
                }
            }
396 397 398
            p_input->stream.p_new_area = NULL;
        }

399
        if( p_input->stream.p_selected_area->i_seek != NO_SEEK )
400
        {
401
            if( p_input->stream.p_selected_area->i_size > 0 )
402
            {
403
                unsigned int i;
404
                mtime_t      i_time;
405 406
                double f = (double)p_input->stream.p_selected_area->i_seek /
                           (double)p_input->stream.p_selected_area->i_size;
407

Christophe Massiot's avatar
Christophe Massiot committed
408
                vlc_mutex_unlock( &p_input->stream.stream_lock );
409
                demux_Control( p_input, DEMUX_SET_POSITION, f );
Christophe Massiot's avatar
Christophe Massiot committed
410
                vlc_mutex_lock( &p_input->stream.stream_lock );
411

412 413 414 415
                /* Escape all decoders for the stream discontinuity they
                 * will encounter. */
                input_EscapeDiscontinuity( p_input );

416 417
                for( i = 0; i < p_input->stream.i_pgrm_number; i++ )
                {
418
                    pgrm_descriptor_t * p_pgrm=p_input->stream.pp_programs[i];
419 420 421 422

                    /* Reinitialize synchro. */
                    p_pgrm->i_synchro_state = SYNCHRO_REINIT;
                }
423

Laurent Aimar's avatar
Laurent Aimar committed
424
                vlc_mutex_unlock( &p_input->stream.stream_lock );
425 426 427 428 429 430 431 432 433 434 435 436 437 438 439
                if( !demux_Control( p_input, DEMUX_GET_TIME, &i_time ) )
                {
                    int i;
                    vlc_value_t val;

                    /* Help in bar display */
                    val.i_time = i_time;
                    var_Change( p_input, "time", VLC_VAR_SETVALUE, &val, NULL );

                    /* Seek subs */
                    for( i = 0; i < p_input->p_sys->i_sub; i++ )
                    {
                        subtitle_Seek( p_input->p_sys->sub[i], i_time );
                    }
                }
Laurent Aimar's avatar
Laurent Aimar committed
440
                vlc_mutex_lock( &p_input->stream.stream_lock );
441
            }
442
            p_input->stream.p_selected_area->i_seek = NO_SEEK;
443
        }
444

445 446 447 448 449 450 451 452 453 454 455 456
        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;
        }

457 458 459 460 461 462 463 464 465 466 467 468 469 470
        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;
        }

471
        vlc_mutex_unlock( &p_input->stream.stream_lock );
472

Christophe Massiot's avatar
Christophe Massiot committed
473 474
        /* Read and demultiplex some data. */
        i_count = p_input->pf_demux( p_input );
475

476
        if( i_count == 0 )
477
        {
478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499
            vlc_value_t repeat;

            var_Get( p_input, "input-repeat", &repeat );
            if( repeat.i_int == 0 || p_input->stream.i_area_nb <= 0 )
            {
                /* End of file - we do not set b_die because only the
                 * playlist is allowed to do so. */
                msg_Info( p_input, "EOF reached" );
                p_input->b_eof = 1;
            }
            else
            {
                msg_Dbg( p_input, "repeating the same input (%d)", repeat.i_int );
                if( repeat.i_int > 0 )
                {
                    repeat.i_int--;
                    var_Set( p_input, "input-repeat", repeat );
                }

                p_input->stream.p_new_area = p_input->stream.pp_areas[0];
                p_input->stream.p_new_area->i_seek = 0;
            }
500 501 502 503
        }
        else if( i_count < 0 )
        {
            p_input->b_error = 1;
504
        }
505 506 507

        if( !p_input->b_error && !p_input->b_eof && i_update_next < mdate() )
        {
508 509 510 511
            int i;
            mtime_t i_time;
            mtime_t i_length;
            double  d_pos;
512 513

            /* update input status variables */
514
            if( !demux_Control( p_input, DEMUX_GET_POSITION, &d_pos ) )
515
            {
516
                val.f_float = (float)d_pos;
517 518
                var_Change( p_input, "position", VLC_VAR_SETVALUE, &val, NULL );
            }
519
            if( !demux_Control( p_input, DEMUX_GET_TIME, &i_time ) )
520
            {
521
                val.i_time = i_time;
522 523
                var_Change( p_input, "time", VLC_VAR_SETVALUE, &val, NULL );
            }
524
            if( !demux_Control( p_input, DEMUX_GET_LENGTH, &i_length ) )
525
            {
526
                val.i_time = i_length;
527 528 529
                var_Change( p_input, "length", VLC_VAR_SETVALUE, &val, NULL );
            }

530 531 532 533 534 535 536
            /* Check stop-time */
            if( p_input->p_sys->i_stop_time > 0 && p_input->p_sys->i_stop_time < i_time )
            {
                msg_Warn( p_input, "EOF reached because of stop-time" );
                p_input->b_eof = 1;
            }

537 538 539 540 541 542
            /* update subs */
            for( i = 0; i < p_input->p_sys->i_sub; i++ )
            {
                subtitle_Demux( p_input->p_sys->sub[i], i_time );
            }

543
            i_update_next = mdate() + I64C(150000);
544
        }
545 546
    }

547
    if( p_input->b_error || p_input->b_eof )
548 549 550
    {
        ErrorThread( p_input );
    }
551

552
    EndThread( p_input );
553

554
    return 0;
555 556
}

557
/*****************************************************************************
558
 * InitThread: init the input Thread
559
 *****************************************************************************/
560
static int InitThread( input_thread_t * p_input )
Michel Kaempf's avatar
Michel Kaempf committed
561
{
562
    vlc_meta_t *meta;
563
    float f_fps;
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
564 565
    playlist_t *p_playlist;
    mtime_t i_length;
566

Christophe Massiot's avatar
Christophe Massiot committed
567
    /* Parse source string. Syntax : [[<access>][/<demux>]:][<source>] */
568
    char * psz_parser = p_input->psz_dupsource = strdup(p_input->psz_source);
569
    vlc_value_t val;
570
    int64_t i_microsecondperframe;
571

572
    subtitle_demux_t *p_sub_toselect = NULL;
573
    char             *psz_sub_file = NULL;
574

Christophe Massiot's avatar
Christophe Massiot committed
575 576 577 578 579
    /* Skip the plug-in names */
    while( *psz_parser && *psz_parser != ':' )
    {
        psz_parser++;
    }
580
#if defined( WIN32 ) || defined( UNDER_CE )
Christophe Massiot's avatar
Christophe Massiot committed
581
    if( psz_parser - p_input->psz_dupsource == 1 )
582
    {
583
        msg_Warn( p_input, "drive letter %c: found in source string",
Christophe Massiot's avatar
Christophe Massiot committed
584
                           p_input->psz_dupsource[0] ) ;
585
        psz_parser = "";
586 587
    }
#endif
588

Christophe Massiot's avatar
Christophe Massiot committed
589
    if( !*psz_parser )
590
    {
591
        p_input->psz_access = p_input->psz_demux = "";
Christophe Massiot's avatar
Christophe Massiot committed
592
        p_input->psz_name = p_input->psz_source;
Christophe Massiot's avatar
Christophe Massiot committed
593
        free( p_input->psz_dupsource );
594
        p_input->psz_dupsource = NULL;
Michel Kaempf's avatar
Michel Kaempf committed
595
    }
Christophe Massiot's avatar
Christophe Massiot committed
596 597 598
    else
    {
        *psz_parser++ = '\0';
599

600 601 602 603
        /* let's skip '//' */
        if( psz_parser[0] == '/' && psz_parser[1] == '/' )
        {
            psz_parser += 2 ;
604
        }
605 606

        p_input->psz_name = psz_parser ;
607

Christophe Massiot's avatar
Christophe Massiot committed
608
        /* Come back to parse the access and demux plug-ins */
Christophe Massiot's avatar
Christophe Massiot committed
609
        psz_parser = p_input->psz_dupsource;
610

611
        if( !*psz_parser )
Christophe Massiot's avatar
Christophe Massiot committed
612 613
        {
            /* No access */
614
            p_input->psz_access = "";
Christophe Massiot's avatar
Christophe Massiot committed
615 616 617 618
        }
        else if( *psz_parser == '/' )
        {
            /* No access */
619
            p_input->psz_access = "";
Christophe Massiot's avatar
Christophe Massiot committed
620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635
            psz_parser++;
        }
        else
        {
            p_input->psz_access = psz_parser;

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

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

Christophe Massiot's avatar
Christophe Massiot committed
637 638 639
        if( !*psz_parser )
        {
            /* No demux */
640
            p_input->psz_demux = "";
Christophe Massiot's avatar
Christophe Massiot committed
641 642 643 644 645
        }
        else
        {
            p_input->psz_demux = psz_parser;
        }
Sam Hocevar's avatar
Sam Hocevar committed
646
    }
Christophe Massiot's avatar
Christophe Massiot committed
647

648 649
    msg_Dbg( p_input, "access `%s', demux `%s', name `%s'",
             p_input->psz_access, p_input->psz_demux, p_input->psz_name );
Christophe Massiot's avatar
Christophe Massiot committed
650 651

    if( input_AccessInit( p_input ) == -1 )
652
    {
653 654 655 656 657 658
        free( p_input->psz_source );
        if( p_input->psz_dupsource != NULL )
        {
            free( p_input->psz_dupsource );
        }

659 660 661 662 663 664 665 666 667 668 669 670
        return VLC_EGENERIC;
    }

    /* Initialize optional stream output. (before demuxer)*/
    var_Get( p_input, "sout", &val );
    if( val.psz_string != NULL )
    {
        if ( *val.psz_string && (p_input->stream.p_sout =
             sout_NewInstance( p_input, val.psz_string )) == NULL )
        {
            msg_Err( p_input, "cannot start stream output instance, aborting" );
            free( val.psz_string );
671 672 673 674 675 676 677

            input_AccessEnd( p_input );
            free( p_input->psz_source );
            if( p_input->psz_dupsource != NULL )
            {
                free( p_input->psz_dupsource );
            }
678 679 680
            return VLC_EGENERIC;
        }
        free( val.psz_string );
681
    }
Christophe Massiot's avatar
Christophe Massiot committed
682

683
    p_input->p_es_out = input_EsOutNew( p_input );
684 685
    es_out_Control( p_input->p_es_out, ES_OUT_SET_ACTIVE, VLC_FALSE );
    es_out_Control( p_input->p_es_out, ES_OUT_SET_MODE, ES_OUT_MODE_NONE );
686

687
    /* Find and open appropriate access module */
688
    p_input->p_access = module_Need( p_input, "access",
689
                                     p_input->psz_access, VLC_TRUE );
Christophe Massiot's avatar
Christophe Massiot committed
690

691 692 693 694
#ifndef WIN32      /* Remove this gross hack from the win32 build as colons
                    * are forbidden in filenames on Win32. */

    /* Maybe we got something like: /Volumes/toto:titi/gabu.mpg */
695 696 697 698 699 700 701 702 703
    if ( p_input->p_access == NULL
          && (*p_input->psz_demux || *p_input->psz_access) )
    {
        p_input->psz_access = p_input->psz_demux = "";
        p_input->psz_name = p_input->psz_source;
        free( p_input->psz_dupsource);
        p_input->psz_dupsource = NULL;

        p_input->p_access = module_Need( p_input, "access",
704
                                         p_input->psz_access, VLC_TRUE );
705
    }
706
#endif
707

708
    if( p_input->p_access == NULL )
709
    {
710
        msg_Err( p_input, "no suitable access module for `%s/%s://%s'",
711
                 p_input->psz_access, p_input->psz_demux, p_input->psz_name );
712 713 714 715
        if ( p_input->stream.p_sout != NULL )
        {
            sout_DeleteInstance( p_input->stream.p_sout );
        }
716 717 718 719 720 721 722

        input_AccessEnd( p_input );
        free( p_input->psz_source );
        if( p_input->psz_dupsource != NULL )
        {
            free( p_input->psz_dupsource );
        }
723
        input_EsOutDelete( p_input->p_es_out );
724
        return VLC_EGENERIC;
725
    }
Christophe Massiot's avatar
Christophe Massiot committed
726 727 728

    /* Waiting for stream. */
    if( p_input->i_mtu )
Christophe Massiot's avatar
Christophe Massiot committed
729
    {
Christophe Massiot's avatar
Christophe Massiot committed
730
        p_input->i_bufsize = p_input->i_mtu;
Christophe Massiot's avatar
Christophe Massiot committed
731
    }
732 733
    else
    {
Christophe Massiot's avatar
Christophe Massiot committed
734
        p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE;
735
    }
736

737 738
    /* If the desynchronisation requested by the user is < 0, we need to
     * cache more data. */
739 740 741 742
    var_Create( p_input, "audio-desync", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
    var_Get( p_input, "audio-desync", &val );
    if( val.i_int < 0 )
        p_input->i_pts_delay -= (val.i_int * 1000);
743

744
    if( p_input->p_current_data == NULL && p_input->pf_read != NULL )
745
    {
Christophe Massiot's avatar
Christophe Massiot committed
746 747
        while( !input_FillBuffer( p_input ) )
        {
748
            if( p_input->b_die || p_input->b_error || p_input->b_eof )
Christophe Massiot's avatar
Christophe Massiot committed
749
            {
750
                module_Unneed( p_input, p_input->p_access );
751 752 753 754
                if ( p_input->stream.p_sout != NULL )
                {
                    sout_DeleteInstance( p_input->stream.p_sout );
                }
755 756 757 758 759 760
                input_AccessEnd( p_input );
                free( p_input->psz_source );
                if( p_input->psz_dupsource != NULL )
                {
                    free( p_input->psz_dupsource );
                }
761
                input_EsOutDelete( p_input->p_es_out );
762
                return VLC_EGENERIC;
Christophe Massiot's avatar
Christophe Massiot committed
763 764
            }
        }
765
    }
766

767
    /* Create the stream_t facilities */
768
    p_input->s = input_StreamNew( p_input );
769 770
    if( p_input->s == NULL )
    {
Clément Stenac's avatar
Clément Stenac committed
771
        /* should never occur yet */
772

Clément Stenac's avatar
Clément Stenac committed
773
        msg_Err( p_input, "cannot create stream_t" );
774

775 776 777 778 779
        module_Unneed( p_input, p_input->p_access );
        if ( p_input->stream.p_sout != NULL )
        {
            sout_DeleteInstance( p_input->stream.p_sout );
        }
780 781 782 783 784 785
        input_AccessEnd( p_input );
        free( p_input->psz_source );
        if( p_input->psz_dupsource != NULL )
        {
            free( p_input->psz_dupsource );
        }
786
        input_EsOutDelete( p_input->p_es_out );
787 788 789
        return VLC_EGENERIC;
    }

790
    /* Find and open appropriate demux module */
791 792 793
    p_input->p_demux =
        module_Need( p_input, "demux",
                     (p_input->psz_demux && *p_input->psz_demux) ?
794 795 796
                     p_input->psz_demux : "$demux",
                     (p_input->psz_demux && *p_input->psz_demux) ?
                     VLC_TRUE : VLC_FALSE );
797

798
    if( p_input->p_demux == NULL )
799
    {
800
        msg_Err( p_input, "no suitable demux module for `%s/%s://%s'",
801
                 p_input->psz_access, p_input->psz_demux, p_input->psz_name );
802

803
        input_StreamDelete( p_input->s );
804
        module_Unneed( p_input, p_input->p_access );
805
        if ( p_input->stream.p_sout != NULL )
806
        {
807
            sout_DeleteInstance( p_input->stream.p_sout );
808
        }
809 810 811 812 813 814
        input_AccessEnd( p_input );
        free( p_input->psz_source );
        if( p_input->psz_dupsource != NULL )
        {
            free( p_input->psz_dupsource );
        }
815
        input_EsOutDelete( p_input->p_es_out );
816
        return VLC_EGENERIC;
817 818
    }

819 820 821 822 823
    /* Init input_thread_sys_t */
    p_input->p_sys = malloc( sizeof( input_thread_sys_t ) );
    p_input->p_sys->i_sub = 0;
    p_input->p_sys->sub   = NULL;

824 825
    p_input->p_sys->i_stop_time = 0;

826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852
    /* get meta informations */
    if( !demux_Control( p_input, DEMUX_GET_META, &meta ) )
    {
        playlist_t *p_playlist = (playlist_t *)vlc_object_find( p_input,
                                         VLC_OBJECT_PLAYLIST,  FIND_PARENT);
        playlist_item_t *p_item = NULL;
        input_info_category_t *p_cat;
        int i;

        if( p_playlist )
        {
            vlc_mutex_lock( &p_playlist->object_lock );
            p_item = playlist_ItemGetByPos( p_playlist, -1 );
            if( p_item )
            {
                vlc_mutex_lock( &p_item->lock );
            }
            vlc_mutex_unlock( &p_playlist->object_lock );
        }

        msg_Dbg( p_input, "meta informations:" );
        if( meta->i_meta > 0 )
        {
            p_cat = input_InfoCategory( p_input, _("File") );
            for( i = 0; i < meta->i_meta; i++ )
            {
                msg_Dbg( p_input, "  - '%s' = '%s'", _(meta->name[i]), meta->value[i] );
853 854 855 856 857 858 859 860 861
                if( !strcmp( meta->name[i], VLC_META_TITLE ) )
                {
                    playlist_ItemSetName( p_item, meta->value[i] );
                }
                if( !strcmp( meta->name[i], VLC_META_AUTHOR ) )
                {
                    playlist_ItemAddInfo( p_item, _("General"), _("Author"),
                                            meta->value[i] );
                }
862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903
                input_AddInfo( p_cat, _(meta->name[i]), "%s", meta->value[i] );
                if( p_item )
                {
                    playlist_ItemAddInfo( p_item, _("File"),
                                          _(meta->name[i]), "%s", meta->value[i] );
                }
            }
        }
        for( i = 0; i < meta->i_track; i++ )
        {
            vlc_meta_t *tk = meta->track[i];
            int j;

            msg_Dbg( p_input, "  - track[%d]:", i );
            if( tk->i_meta > 0 )
            {
                char *psz_cat = malloc( strlen(_("Stream")) + 10 );
                sprintf( psz_cat, "%s %d", _("Stream"), i );
                p_cat = input_InfoCategory( p_input, psz_cat );

                for( j = 0; j < tk->i_meta; j++ )
                {
                    msg_Dbg( p_input, "     - '%s' = '%s'", _(tk->name[j]), tk->value[j] );
                    input_AddInfo( p_cat, _(tk->name[j]), "%s", tk->value[j] );
                    if( p_item )
                    {
                        playlist_ItemAddInfo( p_item, psz_cat,
                                              _(tk->name[j]), "%s", tk->value[j] );
                    }
                }
            }
        }

        if( p_item )
        {
            vlc_mutex_unlock( &p_item->lock );
        }
        if( p_playlist ) vlc_object_release( p_playlist );

        vlc_meta_Delete( meta );
    }

Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
904 905 906
    /* get length */
    if( !demux_Control( p_input, DEMUX_GET_LENGTH, &i_length ) && i_length > 0 )
    {
907
        input_info_category_t *p_cat = input_InfoCategory( p_input, _("File") );
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
908 909 910 911 912
        p_playlist = (playlist_t*)vlc_object_find( p_input,
                                                   VLC_OBJECT_PLAYLIST,
                                                   FIND_PARENT );
        if( p_playlist )
        {
913
            playlist_SetDuration( p_playlist, -1 , i_length );
914
            val.b_bool = p_playlist->i_index;
915
            var_Set( p_playlist, "item-change", val );
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
916 917
            vlc_object_release( p_playlist );
        }
918 919 920 921 922 923
        if( p_cat )
        {
            char psz_buffer[MSTRTIME_MAX_SIZE];
            input_AddInfo( p_cat, _("Duration"),
                           msecstotimestr( psz_buffer, i_length / 1000 ) );
        }
924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942

        /* Set start time */
        var_Get( p_input, "start-time", &val );
        if(  val.i_int > 0 )
        {
            double f_pos = (double)( (int64_t)val.i_int * I64C(1000000) ) / (double)i_length;

            if( f_pos >= 1.0 )
            {
                msg_Warn( p_input, "invalid start-time, ignored (start-time >= media length)" );
            }
            else
            {
                p_input->stream.p_selected_area->i_seek =
                    (int64_t)( f_pos * (double)p_input->stream.p_selected_area->i_size );

                msg_Dbg( p_input, "start-time %ds (%2.2f)", val.i_int, f_pos );
            }
        }
943
    }
944 945 946 947 948
    /* Set stop-time and check validity */
    var_Get( p_input, "stop-time", &val );
    if( val.i_int > 0 )
    {
        vlc_value_t start;
949

950 951 952 953 954 955 956 957 958 959 960
        var_Get( p_input, "start-time", &start );
        if( start.i_int >= val.i_int )
        {
            msg_Warn( p_input, "invalid stop-time, ignored (stop-time < start-time)" );
        }
        else
        {
            p_input->p_sys->i_stop_time = (int64_t)val.i_int * I64C(1000000);
            msg_Dbg( p_input, "stop-time %ds", val.i_int );
        }
    }
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
961

962 963 964 965 966 967 968 969 970 971
    /* get fps */
    if( demux_Control( p_input, DEMUX_GET_FPS, &f_fps ) || f_fps < 0.1 )
    {
        i_microsecondperframe = 0;
    }
    else
    {
        i_microsecondperframe = (int64_t)( (double)1000000.0 / (double)f_fps );
    }

972
    /* Look for and add subtitle files */
973 974 975
    var_Get( p_input, "sub-file", &val );
    if( val.psz_string && *val.psz_string )
    {
976
        subtitle_demux_t *p_sub;
Laurent Aimar's avatar
Laurent Aimar committed
977 978

        msg_Dbg( p_input, "force subtitle: %s", val.psz_string );
Clément Stenac's avatar
Clément Stenac committed
979
        if( ( p_sub = subtitle_New( p_input, strdup(val.psz_string),
Derk-Jan Hartman's avatar
Derk-Jan Hartman committed
980
                                    i_microsecondperframe ) ) )
981
        {
982
            p_sub_toselect = p_sub;
983 984 985
            TAB_APPEND( p_input->p_sys->i_sub, p_input->p_sys->sub, p_sub );
        }
    }
986
    psz_sub_file = val.psz_string;
987

988 989
    var_Get( p_input, "sub-autodetect-file", &val );
    if( val.b_bool )
990
    {
991
        subtitle_demux_t *p_sub;
992
        int i;
993
        char **tmp = subtitles_Detect( p_input, "", p_input->psz_name );
994
        char **tmp2 = tmp;
995
        for( i = 0; *tmp2 != NULL; i++ )
996
        {
997
            if( psz_sub_file == NULL || strcmp( psz_sub_file, *tmp2 ) )
998
            {
999 1000 1001 1002 1003
                if( ( p_sub = subtitle_New( p_input, *tmp2,
                                            i_microsecondperframe ) ) )
                {
                    TAB_APPEND( p_input->p_sys->i_sub, p_input->p_sys->sub, p_sub );
                }
1004
            }
1005
            free( *tmp2++ );
1006
        }
1007
        free( tmp );
1008
    }
1009
    if( psz_sub_file ) free( psz_sub_file );
1010