input.c 94.4 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 )
Michel Kaempf's avatar
Michel Kaempf committed
134
    {
135
        msg_Err( p_parent, "out of memory" );
136
        return NULL;
Michel Kaempf's avatar
Michel Kaempf committed
137
    }
138 139 140 141 142 143 144 145 146 147 148 149 150

    /* 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
151
    MALLOC_NULL( p_input->p, input_thread_private_t );
Rafaël Carré's avatar
Rafaël Carré committed
152
    memset( p_input->p, 0, sizeof( input_thread_private_t ) );
153 154 155

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

165
    p_input->b_preparsing = b_quick;
166
    p_input->psz_header = psz_header ? strdup( psz_header ) : NULL;
167

168
    /* Init events */
169 170 171
    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 );
172

173
    /* Init Common fields */
174 175
    p_input->b_eof = false;
    p_input->b_can_pace_control = true;
Clément Stenac's avatar
Clément Stenac committed
176
    p_input->p->i_start = 0;
177
    p_input->i_time  = 0;
Clément Stenac's avatar
Clément Stenac committed
178
    p_input->p->i_stop  = 0;
179
    p_input->p->i_run  = 0;
Clément Stenac's avatar
Clément Stenac committed
180 181 182
    p_input->p->i_title = 0;
    p_input->p->title   = NULL;
    p_input->p->i_title_offset = p_input->p->i_seekpoint_offset = 0;
183
    p_input->i_state = INIT_S;
Clément Stenac's avatar
Clément Stenac committed
184
    p_input->p->i_rate  = INPUT_RATE_DEFAULT;
185 186
    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
187 188
    p_input->p->p_es_out = NULL;
    p_input->p->p_sout  = NULL;
189
    p_input->p->b_out_pace_control = false;
190 191 192
    p_input->i_pts_delay = 0;

    /* Init Input fields */
Pierre's avatar
Pierre committed
193
    vlc_gc_incref( p_item ); /* Released in Destructor() */
Clément Stenac's avatar
Clément Stenac committed
194 195 196 197
    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;
198
    p_input->p->input.b_title_demux = false;
Clément Stenac's avatar
Clément Stenac committed
199 200 201
    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;
202 203 204 205
    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
206 207
    p_input->p->input.i_cr_average = 0;

208
    vlc_mutex_lock( &p_item->lock );
209 210

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

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

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

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

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

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

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

238
    if( !p_input->b_preparsing )
Gildas Bazin's avatar
Gildas Bazin committed
239
    {
240 241
        var_Get( p_input, "bookmarks", &val );
        if( val.psz_string )
Gildas Bazin's avatar
Gildas Bazin committed
242
        {
243 244 245 246
            /* 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
247
            {
248 249 250 251 252 253 254 255 256 257 258 259 260 261
                 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 ) )
                     {
262
                         p_seekpoint->psz_name = strdup(psz_start + 5);
263 264 265 266 267 268 269
                     }
                     else if( !strncmp( psz_start, "bytes=", 6 ) )
                     {
                         p_seekpoint->i_byte_offset = atoll(psz_start + 6);
                     }
                     else if( !strncmp( psz_start, "time=", 5 ) )
                     {
270 271
                         p_seekpoint->i_time_offset = atoll(psz_start + 5) *
                                                        1000000;
272 273
                     }
                     psz_start = psz_end + 1;
Gildas Bazin's avatar
Gildas Bazin committed
274
                }
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
275
                msg_Dbg( p_input, "adding bookmark: %s, bytes=%"PRId64", time=%"PRId64,
276 277 278 279 280
                                  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
281
            }
282
            free( val.psz_string );
Gildas Bazin's avatar
Gildas Bazin committed
283 284 285
        }
    }

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

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

293 294 295 296
    /* */
    if( p_sout )
        p_input->p->p_sout = p_sout;

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

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

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

306 307 308
    return p_input;
}

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

316 317
    vlc_event_manager_fini( &p_input->p->event_manager );

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

326 327
    vlc_mutex_destroy( &p_input->p->counters.counters_lock );

328 329
    vlc_mutex_destroy( &priv->lock_control );
    free( priv );
330
}
331

332
/**
333 334
 * Initialize an input thread and run it. You will need to monitor the
 * thread to clean up after it is done
335 336 337 338 339 340 341
 *
 * \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 )
342
{
343
    return __input_CreateThreadExtended( p_parent, p_item, NULL, NULL );
344 345
}

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

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

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

368
    return p_input;
Michel Kaempf's avatar
Michel Kaempf committed
369 370
}

371
/**
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
372
 * Initialize an input thread and run it. This thread will clean after itself,
373 374 375 376 377
 * 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
378
 * \return the input object id if non blocking, an error code else
379
 */
380
int __input_Read( vlc_object_t *p_parent, input_item_t *p_item,
381
                   bool b_block )
382
{
383
    input_thread_t *p_input;
384

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

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

408 409 410 411 412 413 414 415 416 417
/**
 * 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 )
{
418
    input_thread_t *p_input;
419

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

425 426
    if( !Init( p_input ) )
        End( p_input );
427

428 429
    vlc_object_detach( p_input );
    vlc_object_release( p_input );
430 431 432 433

    return VLC_SUCCESS;
}

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

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

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

451 452 453
    /* Set die for all access */
    p_list = vlc_list_find( p_input, VLC_OBJECT_ACCESS, FIND_CHILD );
    for( i = 0; i < p_list->i_count; i++ )
454
    {
455
        vlc_object_kill( p_list->p_values[i].p_object );
456
    }
457
    vlc_list_release( p_list );
458

459 460 461
    /* Set die for all stream */
    p_list = vlc_list_find( p_input, VLC_OBJECT_STREAM, FIND_CHILD );
    for( i = 0; i < p_list->i_count; i++ )
462
    {
463
        vlc_object_kill( p_list->p_values[i].p_object );
464
    }
465
    vlc_list_release( p_list );
466

467 468 469 470
    /* Set die for all demux */
    p_list = vlc_list_find( p_input, VLC_OBJECT_DEMUX, FIND_CHILD );
    for( i = 0; i < p_list->i_count; i++ )
    {
471
        vlc_object_kill( p_list->p_values[i].p_object );
472 473
    }
    vlc_list_release( p_list );
Michel Kaempf's avatar
Michel Kaempf committed
474

475
    input_ControlPush( p_input, INPUT_CONTROL_SET_DIE, NULL );
476 477
}

478 479
sout_instance_t * input_DetachSout( input_thread_t *p_input )
{
480 481 482 483
    sout_instance_t *p_sout = p_input->p->p_sout;
    vlc_object_detach( p_sout );
    p_input->p->p_sout = NULL;
    return p_sout;
484 485
}

486
/*****************************************************************************
487
 * Run: main thread loop
488 489
 * This is the "normal" thread that spawns the input processing chain,
 * reads the stream, cleans up and waits
490
 *****************************************************************************/
491
static int Run( input_thread_t *p_input )
Michel Kaempf's avatar
Michel Kaempf committed
492
{
493
    /* Signal that the thread is launched */
Sam Hocevar's avatar
Sam Hocevar committed
494 495
    vlc_thread_ready( p_input );

496
    if( Init( p_input ) )
497 498
    {
        /* If we failed, wait before we are killed, and exit */
499
        p_input->b_error = true;
500

501
        Error( p_input );
502 503

        /* Tell we're dead */
504
        p_input->b_dead = true;
505

506
        return 0;
507
    }
Michel Kaempf's avatar
Michel Kaempf committed
508

509 510
    MainLoop( p_input );

Clément Stenac's avatar
Clément Stenac committed
511
    if( !p_input->b_eof && !p_input->b_error && p_input->p->input.b_eof )
512 513 514 515
    {
        /* 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
516
            if( input_EsOutDecodersEmpty( p_input->p->p_es_out ) )
517 518 519 520 521 522 523 524
                break;

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

            msleep( INPUT_IDLE_SLEEP );
        }

        /* We have finished */
525
        p_input->b_eof = true;
526
        input_ChangeState( p_input, END_S );
527 528
    }

529
    /* Wait until we are asked to die */
530 531 532 533 534 535 536 537 538 539 540 541
    if( !p_input->b_die )
    {
        Error( p_input );
    }

    /* Clean up */
    End( p_input );

    return 0;
}

/*****************************************************************************
542
 * RunAndDestroy: main thread loop
543 544 545
 * This is the "just forget me" thread that spawns the input processing chain,
 * reads the stream, cleans up and releases memory
 *****************************************************************************/
546
static int RunAndDestroy( input_thread_t *p_input )
547 548 549 550
{
    /* Signal that the thread is launched */
    vlc_thread_ready( p_input );

551
    if( Init( p_input ) )
552
        goto exit;
553 554 555

    MainLoop( p_input );

Clément Stenac's avatar
Clément Stenac committed
556
    if( !p_input->b_eof && !p_input->b_error && p_input->p->input.b_eof )
557
    {
558
        /* We have finished demuxing data but not playing it */
559 560
        while( !p_input->b_die )
        {
Clément Stenac's avatar
Clément Stenac committed
561
            if( input_EsOutDecodersEmpty( p_input->p->p_es_out ) )
562 563 564 565 566 567
                break;

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

            msleep( INPUT_IDLE_SLEEP );
        }
568

569
        /* We have finished */
570
        p_input->b_eof = true;
571 572 573 574 575
    }

    /* Clean up */
    End( p_input );

576
exit:
577
    /* Release memory */
578
    vlc_object_release( p_input );
579 580 581 582 583 584 585 586
    return 0;
}

/*****************************************************************************
 * Main loop: Fill buffers from access, and demux
 *****************************************************************************/
static void MainLoop( input_thread_t *p_input )
{
587
    int64_t i_start_mdate = mdate();
588
    int64_t i_intf_update = 0;
589
    int i_updates = 0;
590

591 592 593
    /* Stop the timer */
    stats_TimerStop( p_input, STATS_TIMER_INPUT_LAUNCHING );

Clément Stenac's avatar
Clément Stenac committed
594
    while( !p_input->b_die && !p_input->b_error && !p_input->p->input.b_eof )
595
    {
596
        bool b_force_update = false;
597 598 599
        int i_ret;
        int i_type;
        vlc_value_t val;
600

601
        /* Do the read */
602
        if( p_input->i_state != PAUSE_S )
603
        {
604 605 606
            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 */
607
            else
608
                i_ret = p_input->p->input.p_demux->pf_demux(p_input->p->input.p_demux);
609

610 611 612
            if( i_ret > 0 )
            {
                /* TODO */
Clément Stenac's avatar
Clément Stenac committed
613 614
                if( p_input->p->input.b_title_demux &&
                    p_input->p->input.p_demux->info.i_update )
615
                {
616
                    i_ret = UpdateFromDemux( p_input );
617
                    b_force_update = true;
618
                }
Clément Stenac's avatar
Clément Stenac committed
619 620 621
                else if( !p_input->p->input.b_title_demux &&
                          p_input->p->input.p_access &&
                          p_input->p->input.p_access->info.i_update )
622
                {
623
                    i_ret = UpdateFromAccess( p_input );
624
                    b_force_update = true;
625 626
                }
            }
627 628

            if( i_ret == 0 )    /* EOF */
629 630
            {
                vlc_value_t repeat;
631

632 633 634 635 636 637
                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" );
638
                    p_input->p->input.b_eof = true;
639 640
                }
                else
641
                {
Gildas Bazin's avatar
Gildas Bazin committed
642 643
                    msg_Dbg( p_input, "repeating the same input (%d)",
                             repeat.i_int );
644 645 646 647 648
                    if( repeat.i_int > 0 )
                    {
                        repeat.i_int--;
                        var_Set( p_input, "input-repeat", repeat );
                    }
649

650
                    /* Seek to start title/seekpoint */
Clément Stenac's avatar
Clément Stenac committed
651 652 653
                    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 )
654 655 656 657
                        val.i_int = 0;
                    input_ControlPush( p_input,
                                       INPUT_CONTROL_SET_TITLE, &val );

Clément Stenac's avatar
Clément Stenac committed
658 659
                    val.i_int = p_input->p->input.i_seekpoint_start -
                        p_input->p->input.i_seekpoint_offset;
660 661 662 663 664
                    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
665
                    if( p_input->p->i_start > 0 )
666
                    {
Clément Stenac's avatar
Clément Stenac committed
667
                        val.i_time = p_input->p->i_start;
668 669 670 671 672 673 674 675 676
                        input_ControlPush( p_input, INPUT_CONTROL_SET_TIME,
                                           &val );
                    }
                    else
                    {
                        val.f_float = 0.0;
                        input_ControlPush( p_input, INPUT_CONTROL_SET_POSITION,
                                           &val );
                    }
677 678 679

                    /* */
                    i_start_mdate = mdate();
680 681
                }
            }
682 683
            else if( i_ret < 0 )
            {
684
                p_input->b_error = true;
685
            }
686

Clément Stenac's avatar
Clément Stenac committed
687
            if( i_ret > 0 && p_input->p->i_slave > 0 )
688 689 690
            {
                SlaveDemux( p_input );
            }
691
        }
692
        else
693
        {
694 695 696
            /* Small wait */
            msleep( 10*1000 );
        }
697

698
        /* Handle control */
Clément Stenac's avatar
Clément Stenac committed
699
        vlc_mutex_lock( &p_input->p->lock_control );
700 701 702 703 704
        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 ) )
705
                b_force_update = true;
706
        }
Clément Stenac's avatar
Clément Stenac committed
707
        vlc_mutex_unlock( &p_input->p->lock_control );
708

709
        if( b_force_update || i_intf_update < mdate() )
710 711 712 713 714
        {
            vlc_value_t val;
            double f_pos;
            int64_t i_time, i_length;
            /* update input status variables */
715
            if( !demux_Control( p_input->p->input.p_demux,
Gildas Bazin's avatar
Gildas Bazin committed
716
                                 DEMUX_GET_POSITION, &f_pos ) )
717 718 719 720
            {
                val.f_float = (float)f_pos;
                var_Change( p_input, "position", VLC_VAR_SETVALUE, &val, NULL );
            }
721
            if( !demux_Control( p_input->p->input.p_demux,
Gildas Bazin's avatar
Gildas Bazin committed
722
                                 DEMUX_GET_TIME, &i_time ) )
723 724 725 726 727
            {
                p_input->i_time = i_time;
                val.i_time = i_time;
                var_Change( p_input, "time", VLC_VAR_SETVALUE, &val, NULL );
            }
728
            if( !demux_Control( p_input->p->input.p_demux,
Gildas Bazin's avatar
Gildas Bazin committed
729
                                 DEMUX_GET_LENGTH, &i_length ) )
730 731 732 733 734
            {
                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 );
735

736
                if( old_val.i_time != val.i_time )
737
                {
738
                    UpdateItemLength( p_input, i_length );
739 740
                }
            }
741

742
            var_SetBool( p_input, "intf-change", true );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
743
            i_intf_update = mdate() + INT64_C(150000);
744
        }
745 746 747
        /* 150ms * 8 = ~ 1 second */
        if( ++i_updates % 8 == 0 )
        {
Clément Stenac's avatar
Clément Stenac committed
748
            stats_ComputeInputStats( p_input, p_input->p->input.p_item->p_stats );
749
            /* Are we the thread responsible for computing global stats ? */
750
            if( libvlc_priv (p_input->p_libvlc)->p_stats_computer == p_input )
751
            {
752
                stats_ComputeGlobalStats( p_input->p_libvlc,
753
                                          p_input->p_libvlc->p_stats );
754 755
            }
        }
756
    }
757 758
}

759
static void InitStatistics( input_thread_t * p_input )
Michel Kaempf's avatar
Michel Kaempf committed
760
{
761
    if( p_input->b_preparsing ) return;
762

763 764 765
    /* Prepare statistics */
#define INIT_COUNTER( c, type, compute ) p_input->p->counters.p_##c = \
 stats_CounterCreate( p_input, VLC_VAR_##type, STATS_##compute);
766
    if( libvlc_stats (p_input) )
767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786
    {
        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;
787
    }
788
}
789

790
#ifdef ENABLE_SOUT
791 792 793 794 795 796 797 798 799
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 ) )
800
    {
801 802
        /* Check the validity of the provided sout */
        if( p_input->p->p_sout )
Clément Stenac's avatar
Clément Stenac committed
803
        {
804
            if( strcmp( p_input->p->p_sout->psz_sout, psz ) )
805
            {
806
                msg_Dbg( p_input, "destroying unusable sout" );
807

808 809
                sout_DeleteInstance( p_input->p->p_sout );
                p_input->p->p_sout = NULL;
810
            }
811
        }
812

813 814 815 816 817 818 819 820 821 822 823 824 825
        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
826
            {
827 828 829 830 831
                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
832
            }
833
        }
834
        if( libvlc_stats (p_input) )
835
        {
836 837 838 839 840 841
            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;
842
        }
843
    }
844
    else if( p_input->p->p_sout )
845
    {
846 847 848 849
        msg_Dbg( p_input, "destroying useless sout" );

        sout_DeleteInstance( p_input->p->p_sout );
        p_input->p->p_sout = NULL;
850
    }
851
    free( psz );
852

853 854
    return VLC_SUCCESS;
}
855
#endif
856

857 858 859
static void InitTitle( input_thread_t * p_input )
{
    vlc_value_t val;
860

861
    if( p_input->b_preparsing ) return;
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
    /* 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;
}
894

895 896 897 898 899 900 901
static void StartTitle( input_thread_t * p_input )
{
    double f_fps;
    vlc_value_t val;
    int i, i_delay;
    char *psz;
    char *psz_subtitle;
902
    int64_t i_length;
903

904 905 906
    /* Start title/chapter */

    if( p_input->b_preparsing )
907
    {
908 909
        p_input->p->i_start = 0;
        return;
910
    }
911 912 913 914 915 916 917 918 919 920 921 922

    val.i_int = p_input->p->input.i_title_start -
                p_input->p->input.i_title_offset