input.c 94.2 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
#include <vlc_playlist.h>
47

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

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

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

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

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

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

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

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

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

87 88
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 );
89

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

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

131
    /* Allocate descriptor */
132 133
    p_input = vlc_custom_create( p_parent, sizeof( *p_input ),
                                 VLC_OBJECT_INPUT, input_name );
134
    if( p_input == NULL )
Michel Kaempf's avatar
Michel Kaempf committed
135
    {
136
        msg_Err( p_parent, "out of memory" );
137
        return NULL;
Michel Kaempf's avatar
Michel Kaempf committed
138
    }
139 140 141 142 143 144 145 146 147 148 149 150 151

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

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

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

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

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

204
    vlc_mutex_lock( &p_item->lock );
205 206

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

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

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

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

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

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

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

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

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

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

289 290 291 292
    /* */
    if( p_sout )
        p_input->p->p_sout = p_sout;

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

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

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

302 303 304
    return p_input;
}

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

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

320 321
    vlc_mutex_destroy( &p_input->p->counters.counters_lock );

322 323
    vlc_mutex_destroy( &priv->lock_control );
    free( priv );
324
}
325

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

340 341 342 343
/* */
input_thread_t *__input_CreateThreadExtended( vlc_object_t *p_parent,
                                              input_item_t *p_item,
                                              const char *psz_log, sout_instance_t *p_sout )
344
{
345
    input_thread_t *p_input;
346

347
    p_input = Create( p_parent, p_item, psz_log, false, p_sout );
348 349 350
    if( !p_input )
        return NULL;

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

362
    return p_input;
Michel Kaempf's avatar
Michel Kaempf committed
363 364
}

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

379
    p_input = Create( p_parent, p_item, NULL, false, NULL );
380
    if( !p_input )
381 382
        return VLC_EGENERIC;

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

402 403 404 405 406 407 408 409 410 411
/**
 * 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 )
{
412
    input_thread_t *p_input;
413

414
    /* Allocate descriptor */
415
    p_input = Create( p_parent, p_item, NULL, true, NULL );
416 417 418
    if( !p_input )
        return VLC_EGENERIC;

419 420
    if( !Init( p_input ) )
        End( p_input );
421

422 423
    vlc_object_detach( p_input );
    vlc_object_release( p_input );
424 425 426 427

    return VLC_SUCCESS;
}

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

438
    /* Set die for input */
439 440
    vlc_object_kill( p_input );
    /* FIXME: seems to be duplicated in ControlPush(INPUT_CONTROL_SET_DIE) */
441

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

445 446 447
    /* 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++ )
448
    {
449
        vlc_object_kill( p_list->p_values[i].p_object );
450
    }
451
    vlc_list_release( p_list );
452

453 454 455
    /* 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++ )
456
    {
457
        vlc_object_kill( p_list->p_values[i].p_object );
458
    }
459
    vlc_list_release( p_list );
460

461 462 463 464
    /* 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++ )
    {
465
        vlc_object_kill( p_list->p_values[i].p_object );
466 467
    }
    vlc_list_release( p_list );
Michel Kaempf's avatar
Michel Kaempf committed
468

469
    input_ControlPush( p_input, INPUT_CONTROL_SET_DIE, NULL );
470 471
}

472 473
sout_instance_t * input_DetachSout( input_thread_t *p_input )
{
474 475 476 477
    sout_instance_t *p_sout = p_input->p->p_sout;
    vlc_object_detach( p_sout );
    p_input->p->p_sout = NULL;
    return p_sout;
478 479
}

480
/*****************************************************************************
481
 * Run: main thread loop
482 483
 * This is the "normal" thread that spawns the input processing chain,
 * reads the stream, cleans up and waits
484
 *****************************************************************************/
485
static int Run( input_thread_t *p_input )
Michel Kaempf's avatar
Michel Kaempf committed
486
{
487
    /* Signal that the thread is launched */
Sam Hocevar's avatar
Sam Hocevar committed
488 489
    vlc_thread_ready( p_input );

490
    if( Init( p_input ) )
491 492
    {
        /* If we failed, wait before we are killed, and exit */
493
        p_input->b_error = true;
494 495 496 497 498 499 500 501 502

        /* FIXME: we don't want to depend on the playlist */
        playlist_t * p_playlist = vlc_object_find( p_input,
            VLC_OBJECT_PLAYLIST, FIND_PARENT );
        if( p_playlist )
        {
            playlist_Signal( p_playlist );
            vlc_object_release( p_playlist );
        }
503

504
        Error( p_input );
505 506

        /* Tell we're dead */
507
        p_input->b_dead = true;
508

509
        return 0;
510
    }
Michel Kaempf's avatar
Michel Kaempf committed
511

512 513
    MainLoop( p_input );

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

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

            msleep( INPUT_IDLE_SLEEP );
        }

        /* We have finished */
528
        p_input->b_eof = true;
529
        playlist_Signal( libvlc_priv (p_input->p_libvlc)->p_playlist );
530 531
    }

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

    /* Clean up */
    End( p_input );

    return 0;
}

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

554
    if( Init( p_input ) )
555
        goto exit;
556 557 558

    MainLoop( p_input );

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

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

            msleep( INPUT_IDLE_SLEEP );
        }
571

572
        /* We have finished */
573
        p_input->b_eof = true;
574 575 576 577 578
    }

    /* Clean up */
    End( p_input );

579
exit:
580
    /* Release memory */
581
    vlc_object_release( p_input );
582 583 584 585 586 587 588 589
    return 0;
}

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

594 595 596
    /* Stop the timer */
    stats_TimerStop( p_input, STATS_TIMER_INPUT_LAUNCHING );

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

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

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

            if( i_ret == 0 )    /* EOF */
632 633
            {
                vlc_value_t repeat;
634

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

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

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

                    /* */
                    i_start_mdate = mdate();
684 685
                }
            }
686 687
            else if( i_ret < 0 )
            {
688
                p_input->b_error = true;
689
            }
690

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

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

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

740
                if( old_val.i_time != val.i_time )
741
                {
742
                    UpdateItemLength( p_input, i_length );
743 744
                }
            }
745

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

763
static void InitStatistics( input_thread_t * p_input )
Michel Kaempf's avatar
Michel Kaempf committed
764
{
765
    if( p_input->b_preparsing ) return;
766

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

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

812 813
                sout_DeleteInstance( p_input->p->p_sout );
                p_input->p->p_sout = NULL;
814
            }
815
        }
816

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

        sout_DeleteInstance( p_input->p->p_sout );
        p_input->p->p_sout = NULL;
854
    }
855
    free( psz );
856

857 858
    return VLC_SUCCESS;
}
859
#endif
860

861 862 863
static void InitTitle( input_thread_t * p_input )
{
    vlc_value_t val;
864

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

899 900 901 902 903 904 905
static void StartTitle( input_thread_t * p_input )
{
    double f_fps;
    vlc_value_t val;
    int i, i_delay;
    char *psz;
    char *psz_subtitle;
906
    int64_t i_length;
907

908 909 910
    /* Start title/chapter */

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