input.c 97.7 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_strings.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 58
static  void* Run            ( vlc_object_t *p_this );
static  void* RunAndDestroy  ( vlc_object_t *p_this );
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
static void             WaitDie   ( input_thread_t *p_input );
64 65
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
 *  - can-record (if a stream can be recorded while playing)
117
 *  - teletext-es to get the index of spu track that is teletext --1 if no teletext)
118 119
 * * For intf callback upon changes
 *  - intf-change
120
 *  - rate-change for when playback rate changes
121 122
 * TODO explain when Callback is called
 * TODO complete this list (?)
123
 *****************************************************************************/
124
static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item,
125
                               const char *psz_header, bool b_quick,
126
                               sout_instance_t *p_sout )
Michel Kaempf's avatar
Michel Kaempf committed
127
{
128
    static const char input_name[] = "input";
129
    input_thread_t *p_input = NULL;                 /* thread descriptor */
130 131
    vlc_value_t val;
    int i;
132

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

    /* 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 );
144 145 146

    msg_Dbg( p_input, "Creating an input for '%s'", psz_name);

147 148 149 150 151 152 153
    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
154
    MALLOC_NULL( p_input->p, input_thread_private_t );
Rafaël Carré's avatar
Rafaël Carré committed
155
    memset( p_input->p, 0, sizeof( input_thread_private_t ) );
156 157 158

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

168
    p_input->b_preparsing = b_quick;
169
    p_input->psz_header = psz_header ? strdup( psz_header ) : NULL;
170

171
    /* Init events */
172 173 174
    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 );
175
    vlc_event_manager_register_event_type( p_em, vlc_InputSelectedStreamChanged );
176

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

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

213
    vlc_mutex_lock( &p_item->lock );
214 215

    if( !p_item->p_stats )
216 217
        p_item->p_stats = stats_NewInputStats( p_input );
    vlc_mutex_unlock( &p_item->lock );
218

219
    /* No slave */
Clément Stenac's avatar
Clément Stenac committed
220 221
    p_input->p->i_slave = 0;
    p_input->p->slave   = NULL;
222

223
    /* Init control buffer */
224
    vlc_mutex_init( &p_input->p->lock_control );
Clément Stenac's avatar
Clément Stenac committed
225
    p_input->p->i_control = 0;
226

227
    /* Parse input options */
228
    vlc_mutex_lock( &p_item->lock );
Pierre d'Herbemont's avatar
Pierre d'Herbemont committed
229
    assert( (int)p_item->optflagc == p_item->i_options );
230
    for( i = 0; i < p_item->i_options; i++ )
231 232
        var_OptionParse( VLC_OBJECT(p_input), p_item->ppsz_options[i],
                         !!(p_item->optflagv[i] & VLC_INPUT_OPTION_TRUSTED) );
233
    vlc_mutex_unlock( &p_item->lock );
234

235 236
    /* Create Object Variables for private use only */
    input_ConfigVarInit( p_input );
Michel Kaempf's avatar
Michel Kaempf committed
237

238
    /* Create Objects variables for public Get and Set */
239
    input_ControlVarInit( p_input );
240

241 242
    /* */
    p_input->p->pts_adjust.b_auto_adjust = var_GetBool( p_input, "auto-adjust-pts-delay" );
Clément Stenac's avatar
Clément Stenac committed
243
    p_input->p->input.i_cr_average = var_GetInteger( p_input, "cr-average" );
Gildas Bazin's avatar
Gildas Bazin committed
244

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

293
    /* Remove 'Now playing' info as it is probably outdated */
294
    input_item_SetNowPlaying( p_item, NULL );
295

296 297 298 299
    /* */
    if( p_input->b_preparsing )
        p_input->i_flags |= OBJECT_FLAGS_QUIET | OBJECT_FLAGS_NOINTERACT;

300 301 302 303
    /* */
    if( p_sout )
        p_input->p->p_sout = p_sout;

304
    memset( &p_input->p->counters, 0, sizeof( p_input->p->counters ) );
305
    vlc_mutex_init( &p_input->p->counters.counters_lock );
306

307 308 309
    /* Set the destructor when we are sure we are initialized */
    vlc_object_set_destructor( p_input, (vlc_destructor_t)Destructor );

310 311 312
    /* Attach only once we are ready */
    vlc_object_attach( p_input, p_parent );

313 314 315
    return p_input;
}

316 317 318 319
/**
 * Input destructor (called when the object's refcount reaches 0).
 */
static void Destructor( input_thread_t * p_input )
320
{
321
    input_thread_private_t *priv = p_input->p;
322

323 324 325 326 327 328
#ifndef NDEBUG
    char * psz_name = input_item_GetName( p_input->p->input.p_item );
    msg_Dbg( p_input, "Destroying the input for '%s'", psz_name);
    free( psz_name );
#endif

329 330
    vlc_event_manager_fini( &p_input->p->event_manager );

331 332
    stats_TimerDump( p_input, STATS_TIMER_INPUT_LAUNCHING );
    stats_TimerClean( p_input, STATS_TIMER_INPUT_LAUNCHING );
333
#ifdef ENABLE_SOUT
334 335
    if( priv->p_sout )
        sout_DeleteInstance( priv->p_sout );
336
#endif
Pierre's avatar
Pierre committed
337 338
    vlc_gc_decref( p_input->p->input.p_item );

339 340
    vlc_mutex_destroy( &p_input->p->counters.counters_lock );

341 342
    vlc_mutex_destroy( &priv->lock_control );
    free( priv );
343
}
344

345
/**
346 347
 * Initialize an input thread and run it. You will need to monitor the
 * thread to clean up after it is done
348 349 350 351 352 353 354
 *
 * \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 )
355
{
356
    return __input_CreateThreadExtended( p_parent, p_item, NULL, NULL );
357 358
}

359 360 361 362
/* */
input_thread_t *__input_CreateThreadExtended( vlc_object_t *p_parent,
                                              input_item_t *p_item,
                                              const char *psz_log, sout_instance_t *p_sout )
363
{
364
    input_thread_t *p_input;
365

366
    p_input = Create( p_parent, p_item, psz_log, false, p_sout );
367 368 369
    if( !p_input )
        return NULL;

Sam Hocevar's avatar
Sam Hocevar committed
370
    /* Create thread and wait for its readiness. */
371
    if( vlc_thread_create( p_input, "input", Run,
372
                           VLC_THREAD_PRIORITY_INPUT, true ) )
Michel Kaempf's avatar
Michel Kaempf committed
373
    {
374
        input_ChangeState( p_input, ERROR_S );
375
        msg_Err( p_input, "cannot create input thread" );
376 377
        vlc_object_detach( p_input );
        vlc_object_release( p_input );
378
        return NULL;
Michel Kaempf's avatar
Michel Kaempf committed
379
    }
380

381
    return p_input;
Michel Kaempf's avatar
Michel Kaempf committed
382 383
}

384
/**
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
385
 * Initialize an input thread and run it. This thread will clean after itself,
386 387 388 389 390
 * 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
391
 * \return the input object id if non blocking, an error code else
392
 */
393
int __input_Read( vlc_object_t *p_parent, input_item_t *p_item,
394
                   bool b_block )
395
{
396
    input_thread_t *p_input;
397

398
    p_input = Create( p_parent, p_item, NULL, false, NULL );
399
    if( !p_input )
400 401
        return VLC_EGENERIC;

402
    if( b_block )
403
    {
404
        RunAndDestroy( VLC_OBJECT(p_input) );
Clément Stenac's avatar
Clément Stenac committed
405
        return VLC_SUCCESS;
406
    }
407
    else
408
    {
409
        if( vlc_thread_create( p_input, "input", RunAndDestroy,
410
                               VLC_THREAD_PRIORITY_INPUT, true ) )
411
        {
412
            input_ChangeState( p_input, ERROR_S );
413
            msg_Err( p_input, "cannot create input thread" );
414
            vlc_object_release( p_input );
Clément Stenac's avatar
Clément Stenac committed
415
            return VLC_EGENERIC;
416
        }
417
    }
418
    return p_input->i_object_id;
419
}
420

421 422 423 424 425 426 427 428 429 430
/**
 * 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 )
{
431
    input_thread_t *p_input;
432

433
    /* Allocate descriptor */
434
    p_input = Create( p_parent, p_item, NULL, true, NULL );
435 436 437
    if( !p_input )
        return VLC_EGENERIC;

438 439
    if( !Init( p_input ) )
        End( p_input );
440

441 442
    vlc_object_detach( p_input );
    vlc_object_release( p_input );
443 444 445 446

    return VLC_SUCCESS;
}

447 448 449 450 451
/**
 * Request a running input thread to stop and die
 *
 * \param the input thread to stop
 */
452
static void ObjectKillChildrens( input_thread_t *p_input, vlc_object_t *p_obj )
Michel Kaempf's avatar
Michel Kaempf committed
453
{
454 455
    vlc_list_t *p_list;
    int i;
456 457 458 459 460 461

    if( p_obj->i_object_type == VLC_OBJECT_VOUT ||
        p_obj->i_object_type == VLC_OBJECT_AOUT ||
        p_obj == VLC_OBJECT(p_input->p->p_sout) )
        return;

462
    vlc_object_kill( p_obj );
463

464
    p_list = vlc_list_children( p_obj );
465
    for( i = 0; i < p_list->i_count; i++ )
466
        ObjectKillChildrens( p_input, p_list->p_values[i].p_object );
467
    vlc_list_release( p_list );
468 469 470 471 472 473
}
void input_StopThread( input_thread_t *p_input )
{
    /* Set die for input and ALL of this childrens (even (grand-)grand-childrens)
     * It is needed here even if it is done in INPUT_CONTROL_SET_DIE handler to
     * unlock the control loop */
474
    ObjectKillChildrens( p_input, VLC_OBJECT(p_input) );
Michel Kaempf's avatar
Michel Kaempf committed
475

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

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

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

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

503
        WaitDie( p_input );
504 505

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

508
        return NULL;
509
    }
Michel Kaempf's avatar
Michel Kaempf committed
510

511 512
    MainLoop( p_input );

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

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

            msleep( INPUT_IDLE_SLEEP );
        }

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

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

    /* Clean up */
    End( p_input );

540
    return NULL;
541 542 543
}

/*****************************************************************************
544
 * RunAndDestroy: main thread loop
545 546 547
 * This is the "just forget me" thread that spawns the input processing chain,
 * reads the stream, cleans up and releases memory
 *****************************************************************************/
548
static void* RunAndDestroy( vlc_object_t *p_this )
549
{
550
    input_thread_t *p_input = (input_thread_t *)p_this;
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 640
                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" );
641
                    p_input->p->input.b_eof = true;
642 643
                }
                else
644
                {
Gildas Bazin's avatar
Gildas Bazin committed
645 646
                    msg_Dbg( p_input, "repeating the same input (%d)",
                             repeat.i_int );
647 648 649 650 651
                    if( repeat.i_int > 0 )
                    {
                        repeat.i_int--;
                        var_Set( p_input, "input-repeat", repeat );
                    }
652

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

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

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

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

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

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

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

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

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

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

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

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

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

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

856 857
    return VLC_SUCCESS;
}
858
#endif
859

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

864
    if( p_input->b_preparsing ) return;
865

866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896
    /* 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;
}
897

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

907 908 909
    /* Start title/chapter */

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