input.c 93.8 KB
Newer Older
1 2
/*****************************************************************************
 * input.c: input thread
3
 *****************************************************************************
4
 * Copyright (C) 1998-2007 the VideoLAN team
5
 * $Id$
6
 *
7
 * Authors: Christophe Massiot <massiot@via.ecp.fr>
8
 *          Laurent Aimar <fenrir@via.ecp.fr>
9 10 11 12 13
 *
 * 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.
14
 *
15 16
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
19
 *
20 21
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
Antoine Cellerier's avatar
Antoine Cellerier committed
22
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23
 *****************************************************************************/
Michel Kaempf's avatar
Michel Kaempf committed
24

25
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
26
 * Preamble
27
 *****************************************************************************/
28 29 30 31
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

32
#include <vlc_common.h>
33

34
#include <ctype.h>
Christophe Mutricy's avatar
Christophe Mutricy committed
35
#include <limits.h>
36
#include <assert.h>
37

38
#include "input_internal.h"
39

Clément Stenac's avatar
Clément Stenac committed
40 41
#include <vlc_sout.h>
#include "../stream_output/stream_output.h"
42

Clément Stenac's avatar
Clément Stenac committed
43 44 45
#include <vlc_interface.h>
#include <vlc_url.h>
#include <vlc_charset.h>
46

47 48 49 50
#ifdef HAVE_SYS_STAT_H
#   include <sys/stat.h>
#endif

51
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
52
 * Local prototypes
53
 *****************************************************************************/
54 55
static void Destructor( input_thread_t * p_input );

56
static  int Run  ( input_thread_t *p_input );
57
static  int RunAndDestroy  ( input_thread_t *p_input );
58

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
59
static input_thread_t * Create  ( vlc_object_t *, input_item_t *,
60
                                  const char *, bool, sout_instance_t * );
61
static  int             Init    ( input_thread_t *p_input );
62 63 64
static void             Error   ( input_thread_t *p_input );
static void             End     ( input_thread_t *p_input );
static void             MainLoop( input_thread_t *p_input );
65 66 67

static inline int ControlPopNoLock( input_thread_t *, int *, vlc_value_t * );
static void       ControlReduce( input_thread_t * );
68
static bool Control( input_thread_t *, int, vlc_value_t );
69

70 71
static int  UpdateFromAccess( input_thread_t * );
static int  UpdateFromDemux( input_thread_t * );
Michel Kaempf's avatar
Michel Kaempf committed
72

73
static void UpdateItemLength( input_thread_t *, int64_t i_length );
74

75
static void MRLSections( input_thread_t *, char *, int *, int *, int *, int *);
76 77

static input_source_t *InputSourceNew( input_thread_t *);
78
static int  InputSourceInit( input_thread_t *, input_source_t *,
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
79
                             const char *, const char *psz_forced_demux );
80
static void InputSourceClean( input_source_t * );
81 82
/* TODO */
//static void InputGetAttachments( input_thread_t *, input_source_t * );
83 84
static void SlaveDemux( input_thread_t *p_input );
static void SlaveSeek( input_thread_t *p_input );
85

86 87
static void InputMetaUser( input_thread_t *p_input, vlc_meta_t *p_meta );
static void InputUpdateMeta( input_thread_t *p_input, vlc_meta_t *p_meta );
88

89
static void DemuxMeta( input_thread_t *p_input, vlc_meta_t *p_meta, demux_t *p_demux );
90
static void AccessMeta( input_thread_t * p_input, vlc_meta_t *p_meta );
91 92 93
static void AppendAttachment( int *pi_attachment, input_attachment_t ***ppp_attachment,
                              int i_new, input_attachment_t **pp_new );

94
/*****************************************************************************
95 96
 * This function creates a new input, and returns a pointer
 * to its description. On error, it returns NULL.
97 98 99 100 101 102 103 104 105 106
 *
 * Variables for _public_ use:
 * * Get and Set:
 *  - state
 *  - rate,rate-slower, rate-faster
 *  - position, position-offset
 *  - time, time-offset
 *  - title,title-next,title-prev
 *  - chapter,chapter-next, chapter-prev
 *  - program, audio-es, video-es, spu-es
107
 *  - audio-delay, spu-delay
108 109 110 111
 *  - bookmark
 * * Get only:
 *  - length
 *  - bookmarks
112 113
 *  - seekable (if you can seek, it doesn't say if 'bar display' has be shown
 *    or not, for that check position != 0.0)
114
 *  - can-pause
115 116
 * * For intf callback upon changes
 *  - intf-change
117
 *  - rate-change for when playback rate changes
118 119
 * TODO explain when Callback is called
 * TODO complete this list (?)
120
 *****************************************************************************/
121
static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item,
122
                               const char *psz_header, bool b_quick,
123
                               sout_instance_t *p_sout )
Michel Kaempf's avatar
Michel Kaempf committed
124
{
125
    static const char input_name[] = "input";
126
    input_thread_t *p_input = NULL;                 /* thread descriptor */
127 128
    vlc_value_t val;
    int i;
129

130
    /* Allocate descriptor */
131 132
    p_input = vlc_custom_create( p_parent, sizeof( *p_input ),
                                 VLC_OBJECT_INPUT, input_name );
133
    if( p_input == NULL )
134
        return NULL;
135 136 137 138 139 140 141 142 143 144 145 146 147

    /* Construct a nice name for the input timer */
    char psz_timer_name[255];
    char * psz_name = input_item_GetName( p_item );
    snprintf( psz_timer_name, sizeof(psz_timer_name),
              "input launching for '%s'", psz_name );
    free( psz_name );

    /* Start a timer to mesure how long it takes
     * to launch an input */
    stats_TimerStart( p_input, psz_timer_name,
        STATS_TIMER_INPUT_LAUNCHING );

Clément Stenac's avatar
Clément Stenac committed
148
    MALLOC_NULL( p_input->p, input_thread_private_t );
Rafaël Carré's avatar
Rafaël Carré committed
149
    memset( p_input->p, 0, sizeof( input_thread_private_t ) );
150 151 152

    /* One "randomly" selected input thread is responsible for computing
     * the global stats. Check if there is already someone doing this */
153
    if( p_input->p_libvlc->p_stats && !b_quick )
154
    {
155
        libvlc_priv_t *priv = libvlc_priv (p_input->p_libvlc);
156
        vlc_mutex_lock( &p_input->p_libvlc->p_stats->lock );
157 158
        if( priv->p_stats_computer == NULL )
            priv->p_stats_computer = p_input;
159
        vlc_mutex_unlock( &p_input->p_libvlc->p_stats->lock );
160 161
    }

162
    p_input->b_preparsing = b_quick;
163
    p_input->psz_header = psz_header ? strdup( psz_header ) : NULL;
164

165
    /* Init events */
166 167 168
    vlc_event_manager_t * p_em = &p_input->p->event_manager;
    vlc_event_manager_init_with_vlc_object( p_em, p_input );
    vlc_event_manager_register_event_type( p_em, vlc_InputStateChanged );
169
    vlc_event_manager_register_event_type( p_em, vlc_InputSelectedStreamChanged );
170

171
    /* Init Common fields */
172 173
    p_input->b_eof = false;
    p_input->b_can_pace_control = true;
Clément Stenac's avatar
Clément Stenac committed
174
    p_input->p->i_start = 0;
175
    p_input->i_time  = 0;
Clément Stenac's avatar
Clément Stenac committed
176
    p_input->p->i_stop  = 0;
177
    p_input->p->i_run  = 0;
Clément Stenac's avatar
Clément Stenac committed
178 179 180
    p_input->p->i_title = 0;
    p_input->p->title   = NULL;
    p_input->p->i_title_offset = p_input->p->i_seekpoint_offset = 0;
181
    p_input->i_state = INIT_S;
Clément Stenac's avatar
Clément Stenac committed
182
    p_input->p->i_rate  = INPUT_RATE_DEFAULT;
183 184
    TAB_INIT( p_input->p->i_bookmark, p_input->p->bookmark );
    TAB_INIT( p_input->p->i_attachment, p_input->p->attachment );
Clément Stenac's avatar
Clément Stenac committed
185 186
    p_input->p->p_es_out = NULL;
    p_input->p->p_sout  = NULL;
187
    p_input->p->b_out_pace_control = false;
188 189 190
    p_input->i_pts_delay = 0;

    /* Init Input fields */
Pierre's avatar
Pierre committed
191
    vlc_gc_incref( p_item ); /* Released in Destructor() */
Clément Stenac's avatar
Clément Stenac committed
192 193 194 195
    p_input->p->input.p_item = p_item;
    p_input->p->input.p_access = NULL;
    p_input->p->input.p_stream = NULL;
    p_input->p->input.p_demux  = NULL;
196
    p_input->p->input.b_title_demux = false;
Clément Stenac's avatar
Clément Stenac committed
197 198 199
    p_input->p->input.i_title  = 0;
    p_input->p->input.title    = NULL;
    p_input->p->input.i_title_offset = p_input->p->input.i_seekpoint_offset = 0;
200 201 202 203
    p_input->p->input.b_can_pace_control = true;
    p_input->p->input.b_can_rate_control = true;
    p_input->p->input.b_rescale_ts = true;
    p_input->p->input.b_eof = false;
Clément Stenac's avatar
Clément Stenac committed
204 205
    p_input->p->input.i_cr_average = 0;

206
    vlc_mutex_lock( &p_item->lock );
207 208

    if( !p_item->p_stats )
209 210
        p_item->p_stats = stats_NewInputStats( p_input );
    vlc_mutex_unlock( &p_item->lock );
211

212
    /* No slave */
Clément Stenac's avatar
Clément Stenac committed
213 214
    p_input->p->i_slave = 0;
    p_input->p->slave   = NULL;
215

216
    /* Init control buffer */
217
    vlc_mutex_init( &p_input->p->lock_control );
Clément Stenac's avatar
Clément Stenac committed
218
    p_input->p->i_control = 0;
219

220
    /* Parse input options */
221
    vlc_mutex_lock( &p_item->lock );
222
    assert( p_item->optflagc == p_item->i_options );
223
    for( i = 0; i < p_item->i_options; i++ )
224 225
        var_OptionParse( VLC_OBJECT(p_input), p_item->ppsz_options[i],
                         !!(p_item->optflagv[i] & VLC_INPUT_OPTION_TRUSTED) );
226
    vlc_mutex_unlock( &p_item->lock );
227

228 229
    /* Create Object Variables for private use only */
    input_ConfigVarInit( p_input );
Michel Kaempf's avatar
Michel Kaempf committed
230

231
    /* Create Objects variables for public Get and Set */
232
    input_ControlVarInit( p_input );
233

Clément Stenac's avatar
Clément Stenac committed
234
    p_input->p->input.i_cr_average = var_GetInteger( p_input, "cr-average" );
Gildas Bazin's avatar
Gildas Bazin committed
235

236
    if( !p_input->b_preparsing )
Gildas Bazin's avatar
Gildas Bazin committed
237
    {
238 239
        var_Get( p_input, "bookmarks", &val );
        if( val.psz_string )
Gildas Bazin's avatar
Gildas Bazin committed
240
        {
241 242 243 244
            /* FIXME: have a common cfg parsing routine used by sout and others */
            char *psz_parser, *psz_start, *psz_end;
            psz_parser = val.psz_string;
            while( (psz_start = strchr( psz_parser, '{' ) ) )
Gildas Bazin's avatar
Gildas Bazin committed
245
            {
246 247 248 249 250 251 252 253 254 255 256 257 258 259
                 seekpoint_t *p_seekpoint = vlc_seekpoint_New();
                 char backup;
                 psz_start++;
                 psz_end = strchr( psz_start, '}' );
                 if( !psz_end ) break;
                 psz_parser = psz_end + 1;
                 backup = *psz_parser;
                 *psz_parser = 0;
                 *psz_end = ',';
                 while( (psz_end = strchr( psz_start, ',' ) ) )
                 {
                     *psz_end = 0;
                     if( !strncmp( psz_start, "name=", 5 ) )
                     {
260
                         p_seekpoint->psz_name = strdup(psz_start + 5);
261 262 263 264 265 266 267
                     }
                     else if( !strncmp( psz_start, "bytes=", 6 ) )
                     {
                         p_seekpoint->i_byte_offset = atoll(psz_start + 6);
                     }
                     else if( !strncmp( psz_start, "time=", 5 ) )
                     {
268 269
                         p_seekpoint->i_time_offset = atoll(psz_start + 5) *
                                                        1000000;
270 271
                     }
                     psz_start = psz_end + 1;
Gildas Bazin's avatar
Gildas Bazin committed
272
                }
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
273
                msg_Dbg( p_input, "adding bookmark: %s, bytes=%"PRId64", time=%"PRId64,
274 275 276 277 278
                                  p_seekpoint->psz_name, p_seekpoint->i_byte_offset,
                                  p_seekpoint->i_time_offset );
                input_Control( p_input, INPUT_ADD_BOOKMARK, p_seekpoint );
                vlc_seekpoint_Delete( p_seekpoint );
                *psz_parser = backup;
Gildas Bazin's avatar
Gildas Bazin committed
279
            }
280
            free( val.psz_string );
Gildas Bazin's avatar
Gildas Bazin committed
281 282 283
        }
    }

284
    /* Remove 'Now playing' info as it is probably outdated */
285
    input_item_SetNowPlaying( p_item, NULL );
286

287 288 289 290
    /* */
    if( p_input->b_preparsing )
        p_input->i_flags |= OBJECT_FLAGS_QUIET | OBJECT_FLAGS_NOINTERACT;

291 292 293 294
    /* */
    if( p_sout )
        p_input->p->p_sout = p_sout;

295
    memset( &p_input->p->counters, 0, sizeof( p_input->p->counters ) );
296
    vlc_mutex_init( &p_input->p->counters.counters_lock );
297

298 299 300
    /* Attach only once we are ready */
    vlc_object_attach( p_input, p_parent );

301 302 303
    /* Set the destructor when we are sure we are initialized */
    vlc_object_set_destructor( p_input, (vlc_destructor_t)Destructor );

304 305 306
    return p_input;
}

307 308 309 310
/**
 * Input destructor (called when the object's refcount reaches 0).
 */
static void Destructor( input_thread_t * p_input )
311
{
312
    input_thread_private_t *priv = p_input->p;
313

314 315
    vlc_event_manager_fini( &p_input->p->event_manager );

316 317
    stats_TimerDump( p_input, STATS_TIMER_INPUT_LAUNCHING );
    stats_TimerClean( p_input, STATS_TIMER_INPUT_LAUNCHING );
318
#ifdef ENABLE_SOUT
319 320
    if( priv->p_sout )
        sout_DeleteInstance( priv->p_sout );
321
#endif
Pierre's avatar
Pierre committed
322 323
    vlc_gc_decref( p_input->p->input.p_item );

324 325
    vlc_mutex_destroy( &p_input->p->counters.counters_lock );

326 327
    vlc_mutex_destroy( &priv->lock_control );
    free( priv );
328
}
329

330
/**
331 332
 * Initialize an input thread and run it. You will need to monitor the
 * thread to clean up after it is done
333 334 335 336 337 338 339
 *
 * \param p_parent a vlc_object
 * \param p_item an input item
 * \return a pointer to the spawned input thread
 */
input_thread_t *__input_CreateThread( vlc_object_t *p_parent,
                                      input_item_t *p_item )
340
{
341
    return __input_CreateThreadExtended( p_parent, p_item, NULL, NULL );
342 343
}

344 345 346 347
/* */
input_thread_t *__input_CreateThreadExtended( vlc_object_t *p_parent,
                                              input_item_t *p_item,
                                              const char *psz_log, sout_instance_t *p_sout )
348
{
349
    input_thread_t *p_input;
350

351
    p_input = Create( p_parent, p_item, psz_log, false, p_sout );
352 353 354
    if( !p_input )
        return NULL;

Sam Hocevar's avatar
Sam Hocevar committed
355
    /* Create thread and wait for its readiness. */
356
    if( vlc_thread_create( p_input, "input", Run,
357
                           VLC_THREAD_PRIORITY_INPUT, true ) )
Michel Kaempf's avatar
Michel Kaempf committed
358
    {
359
        input_ChangeState( p_input, ERROR_S );
360
        msg_Err( p_input, "cannot create input thread" );
361 362
        vlc_object_detach( p_input );
        vlc_object_release( p_input );
363
        return NULL;
Michel Kaempf's avatar
Michel Kaempf committed
364
    }
365

366
    return p_input;
Michel Kaempf's avatar
Michel Kaempf committed
367 368
}

369
/**
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
370
 * Initialize an input thread and run it. This thread will clean after itself,
371 372 373 374 375
 * you can forget about it. It can work either in blocking or non-blocking mode
 *
 * \param p_parent a vlc_object
 * \param p_item an input item
 * \param b_block should we block until read is finished ?
Clément Stenac's avatar
Clément Stenac committed
376
 * \return the input object id if non blocking, an error code else
377
 */
378
int __input_Read( vlc_object_t *p_parent, input_item_t *p_item,
379
                   bool b_block )
380
{
381
    input_thread_t *p_input;
382

383
    p_input = Create( p_parent, p_item, NULL, false, NULL );
384
    if( !p_input )
385 386
        return VLC_EGENERIC;

387
    if( b_block )
388
    {
389
        RunAndDestroy( p_input );
Clément Stenac's avatar
Clément Stenac committed
390
        return VLC_SUCCESS;
391
    }
392
    else
393
    {
394
        if( vlc_thread_create( p_input, "input", RunAndDestroy,
395
                               VLC_THREAD_PRIORITY_INPUT, true ) )
396
        {
397
            input_ChangeState( p_input, ERROR_S );
398
            msg_Err( p_input, "cannot create input thread" );
399
            vlc_object_release( p_input );
Clément Stenac's avatar
Clément Stenac committed
400
            return VLC_EGENERIC;
401
        }
402
    }
403
    return p_input->i_object_id;
404
}
405

406 407 408 409 410 411 412 413 414 415
/**
 * Initialize an input and initialize it to preparse the item
 * This function is blocking. It will only accept to parse files
 *
 * \param p_parent a vlc_object_t
 * \param p_item an input item
 * \return VLC_SUCCESS or an error
 */
int __input_Preparse( vlc_object_t *p_parent, input_item_t *p_item )
{
416
    input_thread_t *p_input;
417

418
    /* Allocate descriptor */
419
    p_input = Create( p_parent, p_item, NULL, true, NULL );
420 421 422
    if( !p_input )
        return VLC_EGENERIC;

423 424
    if( !Init( p_input ) )
        End( p_input );
425

426 427
    vlc_object_detach( p_input );
    vlc_object_release( p_input );
428 429 430 431

    return VLC_SUCCESS;
}

432 433 434 435 436
/**
 * Request a running input thread to stop and die
 *
 * \param the input thread to stop
 */
Sam Hocevar's avatar
Sam Hocevar committed
437
void input_StopThread( input_thread_t *p_input )
Michel Kaempf's avatar
Michel Kaempf committed
438
{
439 440
    vlc_list_t *p_list;
    int i;
441

442
    /* Set die for input */
443 444
    vlc_object_kill( p_input );
    /* FIXME: seems to be duplicated in ControlPush(INPUT_CONTROL_SET_DIE) */
445

446
    /* We cannot touch p_input fields directly (we come from another thread),
447
     * so use the vlc_object_find way, it's perfectly safe */
448

449 450
    /* Set die for all access, stream, demux, etc */
    p_list = vlc_list_children( p_input );
451
    for( i = 0; i < p_list->i_count; i++ )
452
        vlc_object_kill( p_list->p_values[i].p_object );
453
    vlc_list_release( p_list );
Michel Kaempf's avatar
Michel Kaempf committed
454

455
    input_ControlPush( p_input, INPUT_CONTROL_SET_DIE, NULL );
456 457
}

458 459
sout_instance_t * input_DetachSout( input_thread_t *p_input )
{
460 461 462 463
    sout_instance_t *p_sout = p_input->p->p_sout;
    vlc_object_detach( p_sout );
    p_input->p->p_sout = NULL;
    return p_sout;
464 465
}

466
/*****************************************************************************
467
 * Run: main thread loop
468 469
 * This is the "normal" thread that spawns the input processing chain,
 * reads the stream, cleans up and waits
470
 *****************************************************************************/
471
static int Run( input_thread_t *p_input )
Michel Kaempf's avatar
Michel Kaempf committed
472
{
473
    /* Signal that the thread is launched */
Sam Hocevar's avatar
Sam Hocevar committed
474 475
    vlc_thread_ready( p_input );

476
    if( Init( p_input ) )
477 478
    {
        /* If we failed, wait before we are killed, and exit */
479
        p_input->b_error = true;
480

481
        Error( p_input );
482 483

        /* Tell we're dead */
484
        p_input->b_dead = true;
485

486
        return 0;
487
    }
Michel Kaempf's avatar
Michel Kaempf committed
488

489 490
    MainLoop( p_input );

Clément Stenac's avatar
Clément Stenac committed
491
    if( !p_input->b_eof && !p_input->b_error && p_input->p->input.b_eof )
492 493 494 495
    {
        /* We have finish to demux data but not to play them */
        while( !p_input->b_die )
        {
Clément Stenac's avatar
Clément Stenac committed
496
            if( input_EsOutDecodersEmpty( p_input->p->p_es_out ) )
497 498 499 500 501 502 503 504
                break;

            msg_Dbg( p_input, "waiting decoder fifos to empty" );

            msleep( INPUT_IDLE_SLEEP );
        }

        /* We have finished */
505
        p_input->b_eof = true;
506
        input_ChangeState( p_input, END_S );
507 508
    }

509
    /* Wait until we are asked to die */
510 511 512 513 514 515 516 517 518 519 520 521
    if( !p_input->b_die )
    {
        Error( p_input );
    }

    /* Clean up */
    End( p_input );

    return 0;
}

/*****************************************************************************
522
 * RunAndDestroy: main thread loop
523 524 525
 * This is the "just forget me" thread that spawns the input processing chain,
 * reads the stream, cleans up and releases memory
 *****************************************************************************/
526
static int RunAndDestroy( input_thread_t *p_input )
527 528 529 530
{
    /* Signal that the thread is launched */
    vlc_thread_ready( p_input );

531
    if( Init( p_input ) )
532
        goto exit;
533 534 535

    MainLoop( p_input );

Clément Stenac's avatar
Clément Stenac committed
536
    if( !p_input->b_eof && !p_input->b_error && p_input->p->input.b_eof )
537
    {
538
        /* We have finished demuxing data but not playing it */
539 540
        while( !p_input->b_die )
        {
Clément Stenac's avatar
Clément Stenac committed
541
            if( input_EsOutDecodersEmpty( p_input->p->p_es_out ) )
542 543 544 545 546 547
                break;

            msg_Dbg( p_input, "waiting decoder fifos to empty" );

            msleep( INPUT_IDLE_SLEEP );
        }
548

549
        /* We have finished */
550
        p_input->b_eof = true;
551 552 553 554 555
    }

    /* Clean up */
    End( p_input );

556
exit:
557
    /* Release memory */
558
    vlc_object_release( p_input );
559 560 561 562 563 564 565 566
    return 0;
}

/*****************************************************************************
 * Main loop: Fill buffers from access, and demux
 *****************************************************************************/
static void MainLoop( input_thread_t *p_input )
{
567
    int64_t i_start_mdate = mdate();
568
    int64_t i_intf_update = 0;
569
    int i_updates = 0;
570

571 572 573
    /* Stop the timer */
    stats_TimerStop( p_input, STATS_TIMER_INPUT_LAUNCHING );

Clément Stenac's avatar
Clément Stenac committed
574
    while( !p_input->b_die && !p_input->b_error && !p_input->p->input.b_eof )
575
    {
576
        bool b_force_update = false;
577 578 579
        int i_ret;
        int i_type;
        vlc_value_t val;
580

581
        /* Do the read */
582
        if( p_input->i_state != PAUSE_S )
583
        {
584 585 586
            if( ( p_input->p->i_stop > 0 && p_input->i_time >= p_input->p->i_stop ) ||
                ( p_input->p->i_run > 0 && i_start_mdate+p_input->p->i_run < mdate() ) )
                i_ret = 0; /* EOF */
587
            else
588
                i_ret = p_input->p->input.p_demux->pf_demux(p_input->p->input.p_demux);
589

590 591 592
            if( i_ret > 0 )
            {
                /* TODO */
Clément Stenac's avatar
Clément Stenac committed
593 594
                if( p_input->p->input.b_title_demux &&
                    p_input->p->input.p_demux->info.i_update )
595
                {
596
                    i_ret = UpdateFromDemux( p_input );
597
                    b_force_update = true;
598
                }
Clément Stenac's avatar
Clément Stenac committed
599 600 601
                else if( !p_input->p->input.b_title_demux &&
                          p_input->p->input.p_access &&
                          p_input->p->input.p_access->info.i_update )
602
                {
603
                    i_ret = UpdateFromAccess( p_input );
604
                    b_force_update = true;
605 606
                }
            }
607 608

            if( i_ret == 0 )    /* EOF */
609 610
            {
                vlc_value_t repeat;
611

612 613 614 615 616 617
                var_Get( p_input, "input-repeat", &repeat );
                if( repeat.i_int == 0 )
                {
                    /* End of file - we do not set b_die because only the
                     * playlist is allowed to do so. */
                    msg_Dbg( p_input, "EOF reached" );
618
                    p_input->p->input.b_eof = true;
619 620
                }
                else
621
                {
Gildas Bazin's avatar
Gildas Bazin committed
622 623
                    msg_Dbg( p_input, "repeating the same input (%d)",
                             repeat.i_int );
624 625 626 627 628
                    if( repeat.i_int > 0 )
                    {
                        repeat.i_int--;
                        var_Set( p_input, "input-repeat", repeat );
                    }
629

630
                    /* Seek to start title/seekpoint */
Clément Stenac's avatar
Clément Stenac committed
631 632 633
                    val.i_int = p_input->p->input.i_title_start -
                        p_input->p->input.i_title_offset;
                    if( val.i_int < 0 || val.i_int >= p_input->p->input.i_title )
634 635 636 637
                        val.i_int = 0;
                    input_ControlPush( p_input,
                                       INPUT_CONTROL_SET_TITLE, &val );

Clément Stenac's avatar
Clément Stenac committed
638 639
                    val.i_int = p_input->p->input.i_seekpoint_start -
                        p_input->p->input.i_seekpoint_offset;
640 641 642 643 644
                    if( val.i_int > 0 /* TODO: check upper boundary */ )
                        input_ControlPush( p_input,
                                           INPUT_CONTROL_SET_SEEKPOINT, &val );

                    /* Seek to start position */
Clément Stenac's avatar
Clément Stenac committed
645
                    if( p_input->p->i_start > 0 )
646
                    {
Clément Stenac's avatar
Clément Stenac committed
647
                        val.i_time = p_input->p->i_start;
648 649 650 651 652 653 654 655 656
                        input_ControlPush( p_input, INPUT_CONTROL_SET_TIME,
                                           &val );
                    }
                    else
                    {
                        val.f_float = 0.0;
                        input_ControlPush( p_input, INPUT_CONTROL_SET_POSITION,
                                           &val );
                    }
657 658 659

                    /* */
                    i_start_mdate = mdate();
660 661
                }
            }
662 663
            else if( i_ret < 0 )
            {
664
                p_input->b_error = true;
665
            }
666

Clément Stenac's avatar
Clément Stenac committed
667
            if( i_ret > 0 && p_input->p->i_slave > 0 )
668 669 670
            {
                SlaveDemux( p_input );
            }
671
        }
672
        else
673
        {
674 675 676
            /* Small wait */
            msleep( 10*1000 );
        }
677

678
        /* Handle control */
Clément Stenac's avatar
Clément Stenac committed
679
        vlc_mutex_lock( &p_input->p->lock_control );
680 681 682 683 684
        ControlReduce( p_input );
        while( !ControlPopNoLock( p_input, &i_type, &val ) )
        {
            msg_Dbg( p_input, "control type=%d", i_type );
            if( Control( p_input, i_type, val ) )
685
                b_force_update = true;
686
        }
Clément Stenac's avatar
Clément Stenac committed
687
        vlc_mutex_unlock( &p_input->p->lock_control );
688

689
        if( b_force_update || i_intf_update < mdate() )
690 691 692 693 694
        {
            vlc_value_t val;
            double f_pos;
            int64_t i_time, i_length;
            /* update input status variables */
695
            if( !demux_Control( p_input->p->input.p_demux,
Gildas Bazin's avatar
Gildas Bazin committed
696
                                 DEMUX_GET_POSITION, &f_pos ) )
697 698 699 700
            {
                val.f_float = (float)f_pos;
                var_Change( p_input, "position", VLC_VAR_SETVALUE, &val, NULL );
            }
701
            if( !demux_Control( p_input->p->input.p_demux,
Gildas Bazin's avatar
Gildas Bazin committed
702
                                 DEMUX_GET_TIME, &i_time ) )
703 704 705 706 707
            {
                p_input->i_time = i_time;
                val.i_time = i_time;
                var_Change( p_input, "time", VLC_VAR_SETVALUE, &val, NULL );
            }
708
            if( !demux_Control( p_input->p->input.p_demux,
Gildas Bazin's avatar
Gildas Bazin committed
709
                                 DEMUX_GET_LENGTH, &i_length ) )
710 711 712 713 714
            {
                vlc_value_t old_val;
                var_Get( p_input, "length", &old_val );
                val.i_time = i_length;
                var_Change( p_input, "length", VLC_VAR_SETVALUE, &val, NULL );
715

716
                if( old_val.i_time != val.i_time )
717
                {
718
                    UpdateItemLength( p_input, i_length );
719 720
                }
            }
721

722
            var_SetBool( p_input, "intf-change", true );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
723
            i_intf_update = mdate() + INT64_C(150000);
724
        }
725 726 727
        /* 150ms * 8 = ~ 1 second */
        if( ++i_updates % 8 == 0 )
        {
Clément Stenac's avatar
Clément Stenac committed
728
            stats_ComputeInputStats( p_input, p_input->p->input.p_item->p_stats );
729
            /* Are we the thread responsible for computing global stats ? */
730
            if( libvlc_priv (p_input->p_libvlc)->p_stats_computer == p_input )
731
            {
732
                stats_ComputeGlobalStats( p_input->p_libvlc,
733
                                          p_input->p_libvlc->p_stats );
734 735
            }
        }
736
    }
737 738
}

739
static void InitStatistics( input_thread_t * p_input )
Michel Kaempf's avatar
Michel Kaempf committed
740
{
741
    if( p_input->b_preparsing ) return;
742

743 744 745
    /* Prepare statistics */
#define INIT_COUNTER( c, type, compute ) p_input->p->counters.p_##c = \
 stats_CounterCreate( p_input, VLC_VAR_##type, STATS_##compute);
746
    if( libvlc_stats (p_input) )
747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766
    {
        INIT_COUNTER( read_bytes, INTEGER, COUNTER );
        INIT_COUNTER( read_packets, INTEGER, COUNTER );
        INIT_COUNTER( demux_read, INTEGER, COUNTER );
        INIT_COUNTER( input_bitrate, FLOAT, DERIVATIVE );
        INIT_COUNTER( demux_bitrate, FLOAT, DERIVATIVE );
        INIT_COUNTER( played_abuffers, INTEGER, COUNTER );
        INIT_COUNTER( lost_abuffers, INTEGER, COUNTER );
        INIT_COUNTER( displayed_pictures, INTEGER, COUNTER );
        INIT_COUNTER( lost_pictures, INTEGER, COUNTER );
        INIT_COUNTER( decoded_audio, INTEGER, COUNTER );
        INIT_COUNTER( decoded_video, INTEGER, COUNTER );
        INIT_COUNTER( decoded_sub, INTEGER, COUNTER );
        p_input->p->counters.p_sout_send_bitrate = NULL;
        p_input->p->counters.p_sout_sent_packets = NULL;
        p_input->p->counters.p_sout_sent_bytes = NULL;
        if( p_input->p->counters.p_demux_bitrate )
            p_input->p->counters.p_demux_bitrate->update_interval = 1000000;
        if( p_input->p->counters.p_input_bitrate )
            p_input->p->counters.p_input_bitrate->update_interval = 1000000;
767
    }
768
}
769

770
#ifdef ENABLE_SOUT
771 772 773 774 775 776 777 778 779
static int InitSout( input_thread_t * p_input )
{
    char *psz;

    if( p_input->b_preparsing ) return VLC_SUCCESS;

    /* Find a usable sout and attach it to p_input */
    psz = var_GetNonEmptyString( p_input, "sout" );
    if( psz && strncasecmp( p_input->p->input.p_item->psz_uri, "vlc:", 4 ) )
780
    {
781 782
        /* Check the validity of the provided sout */
        if( p_input->p->p_sout )
Clément Stenac's avatar
Clément Stenac committed
783
        {
784
            if( strcmp( p_input->p->p_sout->psz_sout, psz ) )
785
            {
786
                msg_Dbg( p_input, "destroying unusable sout" );
787

788 789
                sout_DeleteInstance( p_input->p->p_sout );
                p_input->p->p_sout = NULL;
790
            }
791
        }
792

793 794 795 796 797 798 799 800 801 802 803 804 805
        if( p_input->p->p_sout )
        {
            /* Reuse it */
            msg_Dbg( p_input, "sout keep: reusing sout" );
            msg_Dbg( p_input, "sout keep: you probably want to use "
                              "gather stream_out" );
            vlc_object_attach( p_input->p->p_sout, p_input );
        }
        else
        {
            /* Create a new one */
            p_input->p->p_sout = sout_NewInstance( p_input, psz );
            if( !p_input->p->p_sout )
Clément Stenac's avatar
Clément Stenac committed
806
            {
807 808 809 810 811
                input_ChangeState( p_input, ERROR_S );
                msg_Err( p_input, "cannot start stream output instance, " \
                                  "aborting" );
                free( psz );
                return VLC_EGENERIC;
Clément Stenac's avatar
Clément Stenac committed
812
            }
813
        }
814
        if( libvlc_stats (p_input) )
815
        {
816 817 818 819 820 821
            INIT_COUNTER( sout_sent_packets, INTEGER, COUNTER );
            INIT_COUNTER (sout_sent_bytes, INTEGER, COUNTER );
            INIT_COUNTER( sout_send_bitrate, FLOAT, DERIVATIVE );
            if( p_input->p->counters.p_sout_send_bitrate )
                 p_input->p->counters.p_sout_send_bitrate->update_interval =
                         1000000;
822
        }
823
    }
824
    else if( p_input->p->p_sout )
825
    {
826 827 828 829
        msg_Dbg( p_input, "destroying useless sout" );

        sout_DeleteInstance( p_input->p->p_sout );
        p_input->p->p_sout = NULL;
830
    }
831
    free( psz );
832

833 834
    return VLC_SUCCESS;
}
835
#endif
836

837 838 839
static void InitTitle( input_thread_t * p_input )
{
    vlc_value_t val;
840

841
    if( p_input->b_preparsing ) return;
842

843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873
    /* Create global title (from master) */
    p_input->p->i_title = p_input->p->input.i_title;
    p_input->p->title   = p_input->p->input.title;
    p_input->p->i_title_offset = p_input->p->input.i_title_offset;
    p_input->p->i_seekpoint_offset = p_input->p->input.i_seekpoint_offset;
    if( p_input->p->i_title > 0 )
    {
        /* Setup variables */
        input_ControlVarNavigation( p_input );
        input_ControlVarTitle( p_input, 0 );
    }

    /* Global flag */
    p_input->b_can_pace_control = p_input->p->input.b_can_pace_control;
    p_input->p->b_can_pause        = p_input->p->input.b_can_pause;
    p_input->p->b_can_rate_control = p_input->p->input.b_can_rate_control;

    /* Fix pts delay */
    if( p_input->i_pts_delay < 0 )
        p_input->i_pts_delay = 0;

    /* If the desynchronisation requested by the user is < 0, we need to
     * cache more data. */
    var_Get( p_input, "audio-desync", &val );
    if( val.i_int < 0 ) p_input->i_pts_delay -= (val.i_int * 1000);

    /* Update cr_average depending on the caching */
    p_input->p->input.i_cr_average *= (10 * p_input->i_pts_delay / 200000);
    p_input->p->input.i_cr_average /= 10;
    if( p_input->p->input.i_cr_average < 10 ) p_input->p->input.i_cr_average = 10;
}
874

875 876 877 878 879 880 881
static void StartTitle( input_thread_t * p_input )
{
    double f_fps;
    vlc_value_t val;
    int i, i_delay;
    char *psz;
    char *psz_subtitle;
882
    int64_t i_length;
883

884 885 886
    /* Start title/chapter */

    if( p_input->b_preparsing )
887
    {
888 889
        p_input->p->i_start = 0;
        return;
890
    }
891 892 893 894 895 896 897 898 899 900 901 902

    val.i_int = p_input->p->input.i_title_start -
                p_input->p->input.i_title_offset;
    if( val.i_int > 0 && val.i_int < p_input->p->input.i_title )
        input_ControlPush( p_input, INPUT_CONTROL_SET_TITLE, &val );
    val.i_int = p_input->p->input.i_seekpoint_start -
                p_input->p->input.i_seekpoint_offset;
    if( val.i_int > 0 /* TODO: check upper boundary */ )
        input_ControlPush( p_input, INPUT_CONTROL_SET_SEEKPOINT, &val );

    /* Start time*/
    /* Set start time */
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
903 904 905
    p_input->p->i_start = INT64_C(1000000) * var_GetInteger( p_input, "start-time" );
    p_input->p->i_stop  = INT64_C(1000000) * var_GetInteger( p_input, "stop-time" );
    p_input->p->i_run   = INT64_C(1000000) * var_GetInteger( p_input, "run-time" );
906
    i_length = var_GetTime( p_input, "length" );
907
    if( p_input->p->i_run < 0 )
908
    {
909 910
        msg_Warn( p_input, "invalid run-time ignored" );
        p_input->p->i_run = 0;
Rafaël Carré's avatar
Rafaël Carré committed
911
    }
912

913
    if( p_input->p->i_start > 0 )
914
    {
915
        if( p_input->p->i_start >= i_length )