input: ensure that viewpoint structs are read only from callbacks
[vlc.git] / src / input / input.c
1 /*****************************************************************************
2  * input.c: input thread
3  *****************************************************************************
4  * Copyright (C) 1998-2007 VLC authors and VideoLAN
5  * $Id$
6  *
7  * Authors: Christophe Massiot <massiot@via.ecp.fr>
8  *          Laurent Aimar <fenrir@via.ecp.fr>
9  *
10  * This program is free software; you can redistribute it and/or modify it
11  * under the terms of the GNU Lesser General Public License as published by
12  * the Free Software Foundation; either version 2.1 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public License
21  * along with this program; if not, write to the Free Software Foundation,
22  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
32 #include <vlc_common.h>
33
34 #include <limits.h>
35 #include <assert.h>
36 #include <sys/stat.h>
37
38 #include "input_internal.h"
39 #include "event.h"
40 #include "es_out.h"
41 #include "es_out_timeshift.h"
42 #include "demux.h"
43 #include "item.h"
44 #include "resource.h"
45 #include "stream.h"
46
47 #include <vlc_aout.h>
48 #include <vlc_sout.h>
49 #include <vlc_dialog.h>
50 #include <vlc_url.h>
51 #include <vlc_charset.h>
52 #include <vlc_fs.h>
53 #include <vlc_strings.h>
54 #include <vlc_modules.h>
55 #include <vlc_stream.h>
56 #include <vlc_stream_extractor.h>
57
58 /*****************************************************************************
59  * Local prototypes
60  *****************************************************************************/
61 static  void *Run( void * );
62 static  void *Preparse( void * );
63
64 static input_thread_t * Create  ( vlc_object_t *, input_item_t *,
65                                   const char *, bool, input_resource_t * );
66 static  int             Init    ( input_thread_t *p_input );
67 static void             End     ( input_thread_t *p_input );
68 static void             MainLoop( input_thread_t *p_input, bool b_interactive );
69
70 static inline int ControlPop( input_thread_t *, int *, vlc_value_t *, mtime_t i_deadline, bool b_postpone_seek );
71 static void       ControlRelease( int i_type, vlc_value_t val );
72 static bool       ControlIsSeekRequest( int i_type );
73 static bool       Control( input_thread_t *, int, vlc_value_t );
74 static void       ControlPause( input_thread_t *, mtime_t );
75
76 static int  UpdateTitleSeekpointFromDemux( input_thread_t * );
77 static void UpdateGenericFromDemux( input_thread_t * );
78 static void UpdateTitleListfromDemux( input_thread_t * );
79
80 static void MRLSections( const char *, int *, int *, int *, int *);
81
82 static input_source_t *InputSourceNew( input_thread_t *, const char *,
83                                        const char *psz_forced_demux,
84                                        bool b_in_can_fail );
85 static void InputSourceDestroy( input_source_t * );
86 static void InputSourceMeta( input_thread_t *, input_source_t *, vlc_meta_t * );
87
88 /* TODO */
89 //static void InputGetAttachments( input_thread_t *, input_source_t * );
90 static void SlaveDemux( input_thread_t *p_input );
91 static void SlaveSeek( input_thread_t *p_input );
92
93 static void InputMetaUser( input_thread_t *p_input, vlc_meta_t *p_meta );
94 static void InputUpdateMeta( input_thread_t *p_input, demux_t *p_demux );
95 static void InputGetExtraFiles( input_thread_t *p_input,
96                                 int *pi_list, char ***pppsz_list,
97                                 const char **psz_access, const char *psz_path );
98
99 static void AppendAttachment( int *pi_attachment, input_attachment_t ***ppp_attachment,
100                               const demux_t ***ppp_attachment_demux,
101                               int i_new, input_attachment_t **pp_new, const demux_t *p_demux );
102
103 #define SLAVE_ADD_NOFLAG    0
104 #define SLAVE_ADD_FORCED    (1<<0)
105 #define SLAVE_ADD_CANFAIL   (1<<1)
106 #define SLAVE_ADD_SET_TIME  (1<<2)
107
108 static int input_SlaveSourceAdd( input_thread_t *, enum slave_type,
109                                  const char *, unsigned );
110 static char *input_SubtitleFile2Uri( input_thread_t *, const char * );
111 static void input_ChangeState( input_thread_t *p_input, int i_state ); /* TODO fix name */
112
113 #undef input_Create
114 /**
115  * Create a new input_thread_t.
116  *
117  * You need to call input_Start on it when you are done
118  * adding callback on the variables/events you want to monitor.
119  *
120  * \param p_parent a vlc_object
121  * \param p_item an input item
122  * \param psz_log an optional prefix for this input logs
123  * \param p_resource an optional input ressource
124  * \return a pointer to the spawned input thread
125  */
126 input_thread_t *input_Create( vlc_object_t *p_parent,
127                               input_item_t *p_item,
128                               const char *psz_log, input_resource_t *p_resource )
129 {
130     return Create( p_parent, p_item, psz_log, false, p_resource );
131 }
132
133 #undef input_Read
134 /**
135  * Initialize an input thread and run it until it stops by itself.
136  *
137  * \param p_parent a vlc_object
138  * \param p_item an input item
139  * \return an error code, VLC_SUCCESS on success
140  */
141 int input_Read( vlc_object_t *p_parent, input_item_t *p_item )
142 {
143     input_thread_t *p_input = Create( p_parent, p_item, NULL, false, NULL );
144     if( !p_input )
145         return VLC_EGENERIC;
146
147     if( !Init( p_input ) )
148     {
149         MainLoop( p_input, false );
150         End( p_input );
151     }
152
153     vlc_object_release( p_input );
154     return VLC_SUCCESS;
155 }
156
157 input_thread_t *input_CreatePreparser( vlc_object_t *parent,
158                                        input_item_t *item )
159 {
160     return Create( parent, item, NULL, true, NULL );
161 }
162
163 /**
164  * Start a input_thread_t created by input_Create.
165  *
166  * You must not start an already running input_thread_t.
167  *
168  * \param the input thread to start
169  */
170 int input_Start( input_thread_t *p_input )
171 {
172     input_thread_private_t *priv = input_priv(p_input);
173     void *(*func)(void *) = Run;
174
175     if( priv->b_preparsing )
176         func = Preparse;
177
178     assert( !priv->is_running );
179     /* Create thread and wait for its readiness. */
180     priv->is_running = !vlc_clone( &priv->thread, func, priv,
181                                    VLC_THREAD_PRIORITY_INPUT );
182     if( !priv->is_running )
183     {
184         input_ChangeState( p_input, ERROR_S );
185         msg_Err( p_input, "cannot create input thread" );
186         return VLC_EGENERIC;
187     }
188     return VLC_SUCCESS;
189 }
190
191 /**
192  * Request a running input thread to stop and die
193  *
194  * \param p_input the input thread to stop
195  */
196 void input_Stop( input_thread_t *p_input )
197 {
198     input_thread_private_t *sys = input_priv(p_input);
199
200     vlc_mutex_lock( &sys->lock_control );
201     /* Discard all pending controls */
202     for( int i = 0; i < sys->i_control; i++ )
203     {
204         input_control_t *ctrl = &sys->control[i];
205         ControlRelease( ctrl->i_type, ctrl->val );
206     }
207     sys->i_control = 0;
208     sys->is_stopped = true;
209     vlc_cond_signal( &sys->wait_control );
210     vlc_mutex_unlock( &sys->lock_control );
211     vlc_interrupt_kill( &sys->interrupt );
212 }
213
214 /**
215  * Close an input
216  *
217  * It does not call input_Stop itself.
218  */
219 void input_Close( input_thread_t *p_input )
220 {
221     if( input_priv(p_input)->is_running )
222         vlc_join( input_priv(p_input)->thread, NULL );
223     vlc_interrupt_deinit( &input_priv(p_input)->interrupt );
224     vlc_object_release( p_input );
225 }
226
227 /**
228  * Input destructor (called when the object's refcount reaches 0).
229  */
230 static void input_Destructor( vlc_object_t *obj )
231 {
232     input_thread_t *p_input = (input_thread_t *)obj;
233     input_thread_private_t *priv = input_priv(p_input);
234 #ifndef NDEBUG
235     char * psz_name = input_item_GetName( priv->p_item );
236     msg_Dbg( p_input, "Destroying the input for '%s'", psz_name);
237     free( psz_name );
238 #endif
239
240     if( priv->p_es_out_display )
241         es_out_Delete( priv->p_es_out_display );
242
243     if( priv->p_resource )
244         input_resource_Release( priv->p_resource );
245     if( priv->p_resource_private )
246         input_resource_Release( priv->p_resource_private );
247
248     input_item_Release( priv->p_item );
249
250     vlc_mutex_destroy( &priv->counters.counters_lock );
251
252     for( int i = 0; i < priv->i_control; i++ )
253     {
254         input_control_t *p_ctrl = &priv->control[i];
255         ControlRelease( p_ctrl->i_type, p_ctrl->val );
256     }
257
258     vlc_cond_destroy( &priv->wait_control );
259     vlc_mutex_destroy( &priv->lock_control );
260 }
261
262 /**
263  * Get the item from an input thread
264  * FIXME it does not increase ref count of the item.
265  * if it is used after p_input is destroyed nothing prevent it from
266  * being freed.
267  */
268 input_item_t *input_GetItem( input_thread_t *p_input )
269 {
270     assert( p_input != NULL );
271     return input_priv(p_input)->p_item;
272 }
273
274 /*****************************************************************************
275  * This function creates a new input, and returns a pointer
276  * to its description. On error, it returns NULL.
277  *
278  * XXX Do not forget to update vlc_input.h if you add new variables.
279  *****************************************************************************/
280 static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item,
281                                const char *psz_header, bool b_preparsing,
282                                input_resource_t *p_resource )
283 {
284     /* Allocate descriptor */
285     input_thread_private_t *priv;
286
287     priv = vlc_custom_create( p_parent, sizeof( *priv ), "input" );
288     if( unlikely(priv == NULL) )
289         return NULL;
290
291     input_thread_t *p_input = &priv->input;
292
293     char * psz_name = input_item_GetName( p_item );
294     msg_Dbg( p_input, "Creating an input for %s'%s'",
295              b_preparsing ? "preparsing " : "", psz_name);
296     free( psz_name );
297
298     /* Parse input options */
299     input_item_ApplyOptions( VLC_OBJECT(p_input), p_item );
300
301     p_input->obj.header = psz_header ? strdup( psz_header ) : NULL;
302
303     /* Init Common fields */
304     priv->b_preparsing = b_preparsing;
305     priv->b_can_pace_control = true;
306     priv->i_start = 0;
307     priv->i_time  = 0;
308     priv->i_stop  = 0;
309     priv->i_title = 0;
310     priv->title = NULL;
311     priv->i_title_offset = input_priv(p_input)->i_seekpoint_offset = 0;
312     priv->i_state = INIT_S;
313     priv->is_running = false;
314     priv->is_stopped = false;
315     priv->b_recording = false;
316     priv->i_rate = INPUT_RATE_DEFAULT;
317     memset( &priv->bookmark, 0, sizeof(priv->bookmark) );
318     TAB_INIT( priv->i_bookmark, priv->pp_bookmark );
319     TAB_INIT( priv->i_attachment, priv->attachment );
320     priv->attachment_demux = NULL;
321     priv->p_sout   = NULL;
322     priv->b_out_pace_control = false;
323
324     priv->viewpoint_changed = false;
325     /* Fetch the viewpoint from the mediaplayer or the playlist if any */
326     vlc_viewpoint_t *p_viewpoint = var_InheritAddress( p_input, "viewpoint" );
327     if (p_viewpoint != NULL)
328         priv->viewpoint = *p_viewpoint;
329     else
330         vlc_viewpoint_init( &priv->viewpoint );
331
332     input_item_Hold( p_item ); /* Released in Destructor() */
333     priv->p_item = p_item;
334
335     /* Init Input fields */
336     priv->master = NULL;
337     vlc_mutex_lock( &p_item->lock );
338
339     if( !p_item->p_stats )
340         p_item->p_stats = stats_NewInputStats( p_input );
341
342     /* setup the preparse depth of the item
343      * if we are preparsing, use the i_preparse_depth of the parent item */
344     if( !priv->b_preparsing )
345     {
346         char *psz_rec = var_InheritString( p_parent, "recursive" );
347
348         if( psz_rec != NULL )
349         {
350             if ( !strcasecmp( psz_rec, "none" ) )
351                 p_item->i_preparse_depth = 0;
352             else if ( !strcasecmp( psz_rec, "collapse" ) )
353                 p_item->i_preparse_depth = 1;
354             else
355                 p_item->i_preparse_depth = -1; /* default is expand */
356             free (psz_rec);
357         } else
358             p_item->i_preparse_depth = -1;
359     }
360     else
361         p_input->obj.flags |= OBJECT_FLAGS_QUIET | OBJECT_FLAGS_NOINTERACT;
362
363     /* Make sure the interaction option is honored */
364     if( !var_InheritBool( p_input, "interact" ) )
365         p_input->obj.flags |= OBJECT_FLAGS_NOINTERACT;
366     else if( p_item->b_preparse_interact )
367     {
368         /* If true, this item was asked explicitly to interact with the user
369          * (via libvlc_MetadataRequest). Sub items created from this input won't
370          * have this flag and won't interact with the user */
371         p_input->obj.flags &= ~OBJECT_FLAGS_NOINTERACT;
372     }
373
374     vlc_mutex_unlock( &p_item->lock );
375
376     /* No slave */
377     priv->i_slave = 0;
378     priv->slave   = NULL;
379
380     /* */
381     if( p_resource )
382     {
383         priv->p_resource_private = NULL;
384         priv->p_resource = input_resource_Hold( p_resource );
385     }
386     else
387     {
388         priv->p_resource_private = input_resource_New( VLC_OBJECT( p_input ) );
389         priv->p_resource = input_resource_Hold( priv->p_resource_private );
390     }
391     input_resource_SetInput( priv->p_resource, p_input );
392
393     /* Init control buffer */
394     vlc_mutex_init( &priv->lock_control );
395     vlc_cond_init( &priv->wait_control );
396     priv->i_control = 0;
397     vlc_interrupt_init(&priv->interrupt);
398
399     /* Create Object Variables for private use only */
400     input_ConfigVarInit( p_input );
401
402     /* Create Objects variables for public Get and Set */
403     input_ControlVarInit( p_input );
404
405     /* */
406     if( !priv->b_preparsing )
407     {
408         char *psz_bookmarks = var_GetNonEmptyString( p_input, "bookmarks" );
409         if( psz_bookmarks )
410         {
411             /* FIXME: have a common cfg parsing routine used by sout and others */
412             char *psz_parser, *psz_start, *psz_end;
413             psz_parser = psz_bookmarks;
414             while( (psz_start = strchr( psz_parser, '{' ) ) )
415             {
416                  seekpoint_t *p_seekpoint;
417                  char backup;
418                  psz_start++;
419                  psz_end = strchr( psz_start, '}' );
420                  if( !psz_end ) break;
421                  psz_parser = psz_end + 1;
422                  backup = *psz_parser;
423                  *psz_parser = 0;
424                  *psz_end = ',';
425
426                  p_seekpoint = vlc_seekpoint_New();
427
428                  if( unlikely( p_seekpoint == NULL ) )
429                      break;
430
431                  while( (psz_end = strchr( psz_start, ',' ) ) )
432                  {
433                      *psz_end = 0;
434                      if( !strncmp( psz_start, "name=", 5 ) )
435                      {
436                          free( p_seekpoint->psz_name );
437
438                          p_seekpoint->psz_name = strdup(psz_start + 5);
439                      }
440                      else if( !strncmp( psz_start, "time=", 5 ) )
441                      {
442                          p_seekpoint->i_time_offset = atof(psz_start + 5) *
443                                                         CLOCK_FREQ;
444                      }
445                      psz_start = psz_end + 1;
446                 }
447                 msg_Dbg( p_input, "adding bookmark: %s, time=%"PRId64,
448                                   p_seekpoint->psz_name,
449                                   p_seekpoint->i_time_offset );
450                 input_Control( p_input, INPUT_ADD_BOOKMARK, p_seekpoint );
451                 vlc_seekpoint_Delete( p_seekpoint );
452                 *psz_parser = backup;
453             }
454             free( psz_bookmarks );
455         }
456     }
457
458     /* Remove 'Now playing' info as it is probably outdated */
459     input_item_SetNowPlaying( p_item, NULL );
460     input_item_SetESNowPlaying( p_item, NULL );
461     input_SendEventMeta( p_input );
462
463     /* */
464     memset( &priv->counters, 0, sizeof( priv->counters ) );
465     vlc_mutex_init( &priv->counters.counters_lock );
466
467     priv->p_es_out_display = input_EsOutNew( p_input, priv->i_rate );
468     priv->p_es_out = NULL;
469
470     /* Set the destructor when we are sure we are initialized */
471     vlc_object_set_destructor( p_input, input_Destructor );
472
473     return p_input;
474 }
475
476 /*****************************************************************************
477  * Run: main thread loop
478  * This is the "normal" thread that spawns the input processing chain,
479  * reads the stream, cleans up and waits
480  *****************************************************************************/
481 static void *Run( void *data )
482 {
483     input_thread_private_t *priv = data;
484     input_thread_t *p_input = &priv->input;
485
486     vlc_interrupt_set(&priv->interrupt);
487
488     if( !Init( p_input ) )
489     {
490         if( priv->b_can_pace_control && priv->b_out_pace_control )
491         {
492             /* We don't want a high input priority here or we'll
493              * end-up sucking up all the CPU time */
494             vlc_set_priority( priv->thread, VLC_THREAD_PRIORITY_LOW );
495         }
496
497         MainLoop( p_input, true ); /* FIXME it can be wrong (like with VLM) */
498
499         /* Clean up */
500         End( p_input );
501     }
502
503     input_SendEventDead( p_input );
504     return NULL;
505 }
506
507 static void *Preparse( void *data )
508 {
509     input_thread_private_t *priv = data;
510     input_thread_t *p_input = &priv->input;
511
512     vlc_interrupt_set(&priv->interrupt);
513
514     if( !Init( p_input ) )
515     {   /* if the demux is a playlist, call Mainloop that will call
516          * demux_Demux in order to fetch sub items */
517         bool b_is_playlist = false;
518
519         if ( input_item_ShouldPreparseSubItems( priv->p_item )
520           && demux_Control( priv->master->p_demux, DEMUX_IS_PLAYLIST,
521                             &b_is_playlist ) )
522             b_is_playlist = false;
523         if( b_is_playlist )
524             MainLoop( p_input, false );
525         End( p_input );
526     }
527
528     input_SendEventDead( p_input );
529     return NULL;
530 }
531
532 bool input_Stopped( input_thread_t *input )
533 {
534     input_thread_private_t *sys = input_priv(input);
535     bool ret;
536
537     vlc_mutex_lock( &sys->lock_control );
538     ret = sys->is_stopped;
539     vlc_mutex_unlock( &sys->lock_control );
540     return ret;
541 }
542
543 /*****************************************************************************
544  * Main loop: Fill buffers from access, and demux
545  *****************************************************************************/
546
547 /**
548  * MainLoopDemux
549  * It asks the demuxer to demux some data
550  */
551 static void MainLoopDemux( input_thread_t *p_input, bool *pb_changed )
552 {
553     int i_ret;
554     demux_t *p_demux = input_priv(p_input)->master->p_demux;
555
556     *pb_changed = false;
557
558     if( input_priv(p_input)->i_stop > 0 && input_priv(p_input)->i_time >= input_priv(p_input)->i_stop )
559         i_ret = VLC_DEMUXER_EOF;
560     else
561         i_ret = demux_Demux( p_demux );
562
563     i_ret = i_ret > 0 ? VLC_DEMUXER_SUCCESS : ( i_ret < 0 ? VLC_DEMUXER_EGENERIC : VLC_DEMUXER_EOF);
564
565     if( i_ret == VLC_DEMUXER_SUCCESS )
566     {
567         if( demux_TestAndClearFlags( p_demux, INPUT_UPDATE_TITLE_LIST ) )
568             UpdateTitleListfromDemux( p_input );
569
570         if( input_priv(p_input)->master->b_title_demux )
571         {
572             i_ret = UpdateTitleSeekpointFromDemux( p_input );
573             *pb_changed = true;
574         }
575
576         UpdateGenericFromDemux( p_input );
577     }
578
579     if( i_ret == VLC_DEMUXER_EOF )
580     {
581         msg_Dbg( p_input, "EOF reached" );
582         input_priv(p_input)->master->b_eof = true;
583         es_out_Eos(input_priv(p_input)->p_es_out);
584     }
585     else if( i_ret == VLC_DEMUXER_EGENERIC )
586     {
587         input_ChangeState( p_input, ERROR_S );
588     }
589     else if( input_priv(p_input)->i_slave > 0 )
590         SlaveDemux( p_input );
591 }
592
593 static int MainLoopTryRepeat( input_thread_t *p_input )
594 {
595     int i_repeat = var_GetInteger( p_input, "input-repeat" );
596     if( i_repeat <= 0 )
597         return VLC_EGENERIC;
598
599     vlc_value_t val;
600
601     msg_Dbg( p_input, "repeating the same input (%d)", i_repeat );
602     if( i_repeat > 0 )
603     {
604         i_repeat--;
605         var_SetInteger( p_input, "input-repeat", i_repeat );
606     }
607
608     /* Seek to start title/seekpoint */
609     val.i_int = input_priv(p_input)->master->i_title_start -
610         input_priv(p_input)->master->i_title_offset;
611     if( val.i_int < 0 || val.i_int >= input_priv(p_input)->master->i_title )
612         val.i_int = 0;
613     input_ControlPush( p_input,
614                        INPUT_CONTROL_SET_TITLE, &val );
615
616     val.i_int = input_priv(p_input)->master->i_seekpoint_start -
617         input_priv(p_input)->master->i_seekpoint_offset;
618     if( val.i_int > 0 /* TODO: check upper boundary */ )
619         input_ControlPush( p_input,
620                            INPUT_CONTROL_SET_SEEKPOINT, &val );
621
622     /* Seek to start position */
623     if( input_priv(p_input)->i_start > 0 )
624     {
625         val.i_int = input_priv(p_input)->i_start;
626         input_ControlPush( p_input, INPUT_CONTROL_SET_TIME, &val );
627     }
628     else
629     {
630         val.f_float = 0.f;
631         input_ControlPush( p_input, INPUT_CONTROL_SET_POSITION, &val );
632     }
633
634     return VLC_SUCCESS;
635 }
636
637 /**
638  * Update timing infos and statistics.
639  */
640 static void MainLoopStatistics( input_thread_t *p_input )
641 {
642     double f_position = 0.0;
643     mtime_t i_time = 0;
644     mtime_t i_length = 0;
645
646     /* update input status variables */
647     if( demux_Control( input_priv(p_input)->master->p_demux,
648                        DEMUX_GET_POSITION, &f_position ) )
649         f_position = 0.0;
650
651     if( demux_Control( input_priv(p_input)->master->p_demux,
652                        DEMUX_GET_TIME, &i_time ) )
653         i_time = 0;
654     input_priv(p_input)->i_time = i_time;
655
656     if( demux_Control( input_priv(p_input)->master->p_demux,
657                        DEMUX_GET_LENGTH, &i_length ) )
658         i_length = 0;
659
660     es_out_SetTimes( input_priv(p_input)->p_es_out, f_position, i_time, i_length );
661
662     /* update current bookmark */
663     vlc_mutex_lock( &input_priv(p_input)->p_item->lock );
664     input_priv(p_input)->bookmark.i_time_offset = i_time;
665     vlc_mutex_unlock( &input_priv(p_input)->p_item->lock );
666
667     stats_ComputeInputStats( p_input, input_priv(p_input)->p_item->p_stats );
668     input_SendEventStatistics( p_input );
669 }
670
671 /**
672  * MainLoop
673  * The main input loop.
674  */
675 static void MainLoop( input_thread_t *p_input, bool b_interactive )
676 {
677     mtime_t i_intf_update = 0;
678     mtime_t i_last_seek_mdate = 0;
679
680     if( b_interactive && var_InheritBool( p_input, "start-paused" ) )
681         ControlPause( p_input, mdate() );
682
683     bool b_pause_after_eof = b_interactive &&
684                            var_InheritBool( p_input, "play-and-pause" );
685     bool b_paused_at_eof = false;
686
687     demux_t *p_demux = input_priv(p_input)->master->p_demux;
688     const bool b_can_demux = p_demux->pf_demux != NULL;
689
690     while( !input_Stopped( p_input ) && input_priv(p_input)->i_state != ERROR_S )
691     {
692         mtime_t i_wakeup = -1;
693         bool b_paused = input_priv(p_input)->i_state == PAUSE_S;
694         /* FIXME if input_priv(p_input)->i_state == PAUSE_S the access/access_demux
695          * is paused -> this may cause problem with some of them
696          * The same problem can be seen when seeking while paused */
697         if( b_paused )
698             b_paused = !es_out_GetBuffering( input_priv(p_input)->p_es_out )
699                     || input_priv(p_input)->master->b_eof;
700
701         if( !b_paused )
702         {
703             if( !input_priv(p_input)->master->b_eof )
704             {
705                 bool b_force_update = false;
706
707                 MainLoopDemux( p_input, &b_force_update );
708
709                 if( b_can_demux )
710                     i_wakeup = es_out_GetWakeup( input_priv(p_input)->p_es_out );
711                 if( b_force_update )
712                     i_intf_update = 0;
713
714                 b_paused_at_eof = false;
715             }
716             else if( !es_out_GetEmpty( input_priv(p_input)->p_es_out ) )
717             {
718                 msg_Dbg( p_input, "waiting decoder fifos to empty" );
719                 i_wakeup = mdate() + INPUT_IDLE_SLEEP;
720             }
721             /* Pause after eof only if the input is pausable.
722              * This way we won't trigger timeshifting for nothing */
723             else if( b_pause_after_eof && input_priv(p_input)->b_can_pause )
724             {
725                 if( b_paused_at_eof )
726                     break;
727
728                 vlc_value_t val = { .i_int = PAUSE_S };
729
730                 msg_Dbg( p_input, "pausing at EOF (pause after each)");
731                 Control( p_input, INPUT_CONTROL_SET_STATE, val );
732
733                 b_paused = true;
734                 b_paused_at_eof = true;
735             }
736             else
737             {
738                 if( MainLoopTryRepeat( p_input ) )
739                     break;
740             }
741
742             /* Update interface and statistics */
743             mtime_t now = mdate();
744             if( now >= i_intf_update )
745             {
746                 MainLoopStatistics( p_input );
747                 i_intf_update = now + INT64_C(250000);
748             }
749         }
750
751         /* Handle control */
752         for( ;; )
753         {
754             mtime_t i_deadline = i_wakeup;
755
756             /* Postpone seeking until ES buffering is complete or at most
757              * 125 ms. */
758             bool b_postpone = es_out_GetBuffering( input_priv(p_input)->p_es_out )
759                             && !input_priv(p_input)->master->b_eof;
760             if( b_postpone )
761             {
762                 mtime_t now = mdate();
763
764                 /* Recheck ES buffer level every 20 ms when seeking */
765                 if( now < i_last_seek_mdate + INT64_C(125000)
766                  && (i_deadline < 0 || i_deadline > now + INT64_C(20000)) )
767                     i_deadline = now + INT64_C(20000);
768                 else
769                     b_postpone = false;
770             }
771
772             int i_type;
773             vlc_value_t val;
774
775             if( ControlPop( p_input, &i_type, &val, i_deadline, b_postpone ) )
776             {
777                 if( b_postpone )
778                     continue;
779                 break; /* Wake-up time reached */
780             }
781
782 #ifndef NDEBUG
783             msg_Dbg( p_input, "control type=%d", i_type );
784 #endif
785             if( Control( p_input, i_type, val ) )
786             {
787                 if( ControlIsSeekRequest( i_type ) )
788                     i_last_seek_mdate = mdate();
789                 i_intf_update = 0;
790             }
791
792             /* Update the wakeup time */
793             if( i_wakeup != 0 )
794                 i_wakeup = es_out_GetWakeup( input_priv(p_input)->p_es_out );
795         }
796     }
797 }
798
799 static void InitStatistics( input_thread_t *p_input )
800 {
801     input_thread_private_t *priv = input_priv(p_input);
802
803     if( priv->b_preparsing ) return;
804
805     /* Prepare statistics */
806 #define INIT_COUNTER( c, compute ) priv->counters.p_##c = \
807  stats_CounterCreate( STATS_##compute);
808     if( libvlc_stats( p_input ) )
809     {
810         INIT_COUNTER( read_bytes, COUNTER );
811         INIT_COUNTER( read_packets, COUNTER );
812         INIT_COUNTER( demux_read, COUNTER );
813         INIT_COUNTER( input_bitrate, DERIVATIVE );
814         INIT_COUNTER( demux_bitrate, DERIVATIVE );
815         INIT_COUNTER( demux_corrupted, COUNTER );
816         INIT_COUNTER( demux_discontinuity, COUNTER );
817         INIT_COUNTER( played_abuffers, COUNTER );
818         INIT_COUNTER( lost_abuffers, COUNTER );
819         INIT_COUNTER( displayed_pictures, COUNTER );
820         INIT_COUNTER( lost_pictures, COUNTER );
821         INIT_COUNTER( decoded_audio, COUNTER );
822         INIT_COUNTER( decoded_video, COUNTER );
823         INIT_COUNTER( decoded_sub, COUNTER );
824         priv->counters.p_sout_send_bitrate = NULL;
825         priv->counters.p_sout_sent_packets = NULL;
826         priv->counters.p_sout_sent_bytes = NULL;
827     }
828 }
829
830 #ifdef ENABLE_SOUT
831 static int InitSout( input_thread_t * p_input )
832 {
833     input_thread_private_t *priv = input_priv(p_input);
834
835     if( priv->b_preparsing )
836         return VLC_SUCCESS;
837
838     /* Find a usable sout and attach it to p_input */
839     char *psz = var_GetNonEmptyString( p_input, "sout" );
840     if( psz && strncasecmp( priv->p_item->psz_uri, "vlc:", 4 ) )
841     {
842         priv->p_sout  = input_resource_RequestSout( priv->p_resource, NULL, psz );
843         if( priv->p_sout == NULL )
844         {
845             input_ChangeState( p_input, ERROR_S );
846             msg_Err( p_input, "cannot start stream output instance, " \
847                               "aborting" );
848             free( psz );
849             return VLC_EGENERIC;
850         }
851         if( libvlc_stats( p_input ) )
852         {
853             INIT_COUNTER( sout_sent_packets, COUNTER );
854             INIT_COUNTER( sout_sent_bytes, COUNTER );
855             INIT_COUNTER( sout_send_bitrate, DERIVATIVE );
856         }
857     }
858     else
859     {
860         input_resource_RequestSout( priv->p_resource, NULL, NULL );
861     }
862     free( psz );
863
864     return VLC_SUCCESS;
865 }
866 #endif
867
868 static void InitTitle( input_thread_t * p_input )
869 {
870     input_thread_private_t *priv = input_priv(p_input);
871     input_source_t *p_master = priv->master;
872
873     if( priv->b_preparsing )
874         return;
875
876     vlc_mutex_lock( &priv->p_item->lock );
877     /* Create global title (from master) */
878     priv->i_title = p_master->i_title;
879     priv->title   = p_master->title;
880     priv->i_title_offset = p_master->i_title_offset;
881     priv->i_seekpoint_offset = p_master->i_seekpoint_offset;
882     if( priv->i_title > 0 )
883     {
884         /* Setup variables */
885         input_ControlVarNavigation( p_input );
886         input_SendEventTitle( p_input, 0 );
887     }
888
889     /* Global flag */
890     priv->b_can_pace_control = p_master->b_can_pace_control;
891     priv->b_can_pause        = p_master->b_can_pause;
892     priv->b_can_rate_control = p_master->b_can_rate_control;
893     vlc_mutex_unlock( &priv->p_item->lock );
894 }
895
896 static void StartTitle( input_thread_t * p_input )
897 {
898     input_thread_private_t *priv = input_priv(p_input);
899     vlc_value_t val;
900
901     /* Start title/chapter */
902     val.i_int = priv->master->i_title_start - priv->master->i_title_offset;
903     if( val.i_int > 0 && val.i_int < priv->master->i_title )
904         input_ControlPush( p_input, INPUT_CONTROL_SET_TITLE, &val );
905
906     val.i_int = priv->master->i_seekpoint_start -
907                 priv->master->i_seekpoint_offset;
908     if( val.i_int > 0 /* TODO: check upper boundary */ )
909         input_ControlPush( p_input, INPUT_CONTROL_SET_SEEKPOINT, &val );
910
911     /* Start/stop/run time */
912     priv->i_start = llroundf(1000000.f
913                                      * var_GetFloat( p_input, "start-time" ));
914     priv->i_stop  = llroundf(1000000.f
915                                      * var_GetFloat( p_input, "stop-time" ));
916     if( priv->i_stop <= 0 )
917     {
918         priv->i_stop = llroundf(1000000.f
919                                      * var_GetFloat( p_input, "run-time" ));
920         if( priv->i_stop < 0 )
921         {
922             msg_Warn( p_input, "invalid run-time ignored" );
923             priv->i_stop = 0;
924         }
925         else
926             priv->i_stop += priv->i_start;
927     }
928
929     if( priv->i_start > 0 )
930     {
931         vlc_value_t s;
932
933         msg_Dbg( p_input, "starting at time: %"PRId64"s",
934                  priv->i_start / CLOCK_FREQ );
935
936         s.i_int = priv->i_start;
937         input_ControlPush( p_input, INPUT_CONTROL_SET_TIME, &s );
938     }
939     if( priv->i_stop > 0 && priv->i_stop <= priv->i_start )
940     {
941         msg_Warn( p_input, "invalid stop-time ignored" );
942         priv->i_stop = 0;
943     }
944     priv->b_fast_seek = var_GetBool( p_input, "input-fast-seek" );
945 }
946
947 static int SlaveCompare(const void *a, const void *b)
948 {
949     const input_item_slave_t *p_slave0 = *((const input_item_slave_t **) a);
950     const input_item_slave_t *p_slave1 = *((const input_item_slave_t **) b);
951
952     if( p_slave0 == NULL || p_slave1 == NULL )
953     {
954         /* Put NULL (or rejected) subs at the end */
955         return p_slave0 == NULL ? 1 : p_slave1 == NULL ? -1 : 0;
956     }
957
958     if( p_slave0->i_priority > p_slave1->i_priority )
959         return -1;
960
961     if( p_slave0->i_priority < p_slave1->i_priority )
962         return 1;
963
964     return 0;
965 }
966
967 static bool SlaveExists( input_item_slave_t **pp_slaves, int i_slaves,
968                          const char *psz_uri)
969 {
970     for( int i = 0; i < i_slaves; i++ )
971     {
972         if( pp_slaves[i] != NULL
973          && !strcmp( pp_slaves[i]->psz_uri, psz_uri ) )
974             return true;
975     }
976     return false;
977 }
978
979 static void SetSubtitlesOptions( input_thread_t *p_input )
980 {
981     /* Get fps and set it if not already set */
982     const float f_fps = input_priv(p_input)->master->f_fps;
983     if( f_fps > 1.f )
984     {
985         var_Create( p_input, "sub-original-fps", VLC_VAR_FLOAT );
986         var_SetFloat( p_input, "sub-original-fps", f_fps );
987
988         float f_requested_fps = var_CreateGetFloat( p_input, "sub-fps" );
989         if( f_requested_fps != f_fps )
990         {
991             var_Create( p_input, "sub-fps", VLC_VAR_FLOAT|
992                                             VLC_VAR_DOINHERIT );
993             var_SetFloat( p_input, "sub-fps", f_requested_fps );
994         }
995     }
996
997     const int i_delay = var_CreateGetInteger( p_input, "sub-delay" );
998     if( i_delay != 0 )
999         var_SetInteger( p_input, "spu-delay", (mtime_t)i_delay * 100000 );
1000 }
1001
1002 static void GetVarSlaves( input_thread_t *p_input,
1003                           input_item_slave_t ***ppp_slaves, int *p_slaves )
1004 {
1005     char *psz = var_GetNonEmptyString( p_input, "input-slave" );
1006     if( !psz )
1007         return;
1008
1009     input_item_slave_t **pp_slaves = *ppp_slaves;
1010     int i_slaves = *p_slaves;
1011
1012     char *psz_org = psz;
1013     while( psz && *psz )
1014     {
1015         while( *psz == ' ' || *psz == '#' )
1016             psz++;
1017
1018         char *psz_delim = strchr( psz, '#' );
1019         if( psz_delim )
1020             *psz_delim++ = '\0';
1021
1022         if( *psz == 0 )
1023             break;
1024
1025         char *uri = strstr(psz, "://")
1026                                    ? strdup( psz ) : vlc_path2uri( psz, NULL );
1027         psz = psz_delim;
1028         if( uri == NULL )
1029             continue;
1030
1031         input_item_slave_t *p_slave =
1032             input_item_slave_New( uri, SLAVE_TYPE_AUDIO, SLAVE_PRIORITY_USER );
1033         free( uri );
1034
1035         if( unlikely( p_slave == NULL ) )
1036             break;
1037         TAB_APPEND(i_slaves, pp_slaves, p_slave);
1038     }
1039     free( psz_org );
1040
1041     *ppp_slaves = pp_slaves; /* in case of realloc */
1042     *p_slaves = i_slaves;
1043 }
1044
1045 static void LoadSlaves( input_thread_t *p_input )
1046 {
1047     input_item_slave_t **pp_slaves;
1048     int i_slaves;
1049     TAB_INIT( i_slaves, pp_slaves );
1050
1051     /* Look for and add slaves */
1052
1053     char *psz_subtitle = var_GetNonEmptyString( p_input, "sub-file" );
1054     if( psz_subtitle != NULL )
1055     {
1056         msg_Dbg( p_input, "forced subtitle: %s", psz_subtitle );
1057         char *psz_uri = input_SubtitleFile2Uri( p_input, psz_subtitle );
1058         free( psz_subtitle );
1059         psz_subtitle = NULL;
1060         if( psz_uri != NULL )
1061         {
1062             input_item_slave_t *p_slave =
1063                 input_item_slave_New( psz_uri, SLAVE_TYPE_SPU,
1064                                       SLAVE_PRIORITY_USER );
1065             free( psz_uri );
1066             if( p_slave )
1067             {
1068                 TAB_APPEND(i_slaves, pp_slaves, p_slave);
1069                 psz_subtitle = p_slave->psz_uri;
1070             }
1071         }
1072     }
1073
1074     if( var_GetBool( p_input, "sub-autodetect-file" ) )
1075     {
1076         /* Add local subtitles */
1077         char *psz_autopath = var_GetNonEmptyString( p_input, "sub-autodetect-path" );
1078
1079         if( subtitles_Detect( p_input, psz_autopath, input_priv(p_input)->p_item->psz_uri,
1080                               &pp_slaves, &i_slaves ) == VLC_SUCCESS )
1081         {
1082             /* check that we did not add the subtitle through sub-file */
1083             if( psz_subtitle != NULL )
1084             {
1085                 for( int i = 1; i < i_slaves; i++ )
1086                 {
1087                     input_item_slave_t *p_curr = pp_slaves[i];
1088                     if( p_curr != NULL
1089                      && !strcmp( psz_subtitle, p_curr->psz_uri ) )
1090                     {
1091                         /* reject current sub */
1092                         input_item_slave_Delete( p_curr );
1093                         pp_slaves[i] = NULL;
1094                     }
1095                 }
1096             }
1097         }
1098         free( psz_autopath );
1099     }
1100
1101     /* Add slaves found by the directory demuxer or via libvlc */
1102     input_item_t *p_item = input_priv(p_input)->p_item;
1103     vlc_mutex_lock( &p_item->lock );
1104
1105     /* Move item slaves to local pp_slaves */
1106     for( int i = 0; i < p_item->i_slaves; i++ )
1107     {
1108         input_item_slave_t *p_slave = p_item->pp_slaves[i];
1109         if( !SlaveExists( pp_slaves, i_slaves, p_slave->psz_uri ) )
1110             TAB_APPEND(i_slaves, pp_slaves, p_slave);
1111         else
1112             input_item_slave_Delete( p_slave );
1113     }
1114     /* Slaves that are successfully loaded will be added back to the item */
1115     TAB_CLEAN( p_item->i_slaves, p_item->pp_slaves );
1116     vlc_mutex_unlock( &p_item->lock );
1117
1118     /* Add slaves from the "input-slave" option */
1119     GetVarSlaves( p_input, &pp_slaves, &i_slaves );
1120
1121     if( i_slaves > 0 )
1122         qsort( pp_slaves, i_slaves, sizeof (input_item_slave_t*),
1123                SlaveCompare );
1124
1125     /* add all detected slaves */
1126     bool p_forced[2] = {};
1127     static_assert( SLAVE_TYPE_AUDIO <= 1 && SLAVE_TYPE_SPU <= 1,
1128                    "slave type size mismatch");
1129     for( int i = 0; i < i_slaves && pp_slaves[i] != NULL; i++ )
1130     {
1131         input_item_slave_t *p_slave = pp_slaves[i];
1132         /* Slaves added via options should not fail */
1133         unsigned i_flags = p_slave->i_priority != SLAVE_PRIORITY_USER
1134                            ? SLAVE_ADD_CANFAIL : SLAVE_ADD_NOFLAG;
1135
1136         if( !p_forced[p_slave->i_type]
1137          && ( p_slave->b_forced || p_slave->i_priority == SLAVE_PRIORITY_USER ) )
1138             i_flags |= SLAVE_ADD_FORCED;
1139
1140         if( input_SlaveSourceAdd( p_input, p_slave->i_type, p_slave->psz_uri,
1141                                   i_flags ) == VLC_SUCCESS )
1142         {
1143             input_item_AddSlave( input_priv(p_input)->p_item, p_slave );
1144             p_forced[p_slave->i_type] = true;
1145         }
1146         else
1147             input_item_slave_Delete( p_slave );
1148     }
1149     TAB_CLEAN( i_slaves, pp_slaves );
1150
1151     /* Load subtitles from attachments */
1152     int i_attachment = 0;
1153     input_attachment_t **pp_attachment = NULL;
1154
1155     vlc_mutex_lock( &input_priv(p_input)->p_item->lock );
1156     for( int i = 0; i < input_priv(p_input)->i_attachment; i++ )
1157     {
1158         const input_attachment_t *a = input_priv(p_input)->attachment[i];
1159         if( !strcmp( a->psz_mime, "application/x-srt" ) )
1160             TAB_APPEND( i_attachment, pp_attachment,
1161                         vlc_input_attachment_New( a->psz_name, NULL,
1162                                                   a->psz_description, NULL, 0 ) );
1163     }
1164     vlc_mutex_unlock( &input_priv(p_input)->p_item->lock );
1165
1166     if( i_attachment > 0 )
1167         var_Create( p_input, "sub-description", VLC_VAR_STRING );
1168     for( int i = 0; i < i_attachment; i++ )
1169     {
1170         input_attachment_t *a = pp_attachment[i];
1171         if( !a )
1172             continue;
1173         char *psz_mrl;
1174         if( a->psz_name[0] &&
1175             asprintf( &psz_mrl, "attachment://%s", a->psz_name ) >= 0 )
1176         {
1177             var_SetString( p_input, "sub-description", a->psz_description ? a->psz_description : "");
1178
1179             input_SlaveSourceAdd( p_input, SLAVE_TYPE_SPU, psz_mrl,
1180                                   SLAVE_ADD_NOFLAG );
1181             free( psz_mrl );
1182             /* Don't update item slaves for attachements */
1183         }
1184         vlc_input_attachment_Delete( a );
1185     }
1186     free( pp_attachment );
1187     if( i_attachment > 0 )
1188         var_Destroy( p_input, "sub-description" );
1189 }
1190
1191 static void UpdatePtsDelay( input_thread_t *p_input )
1192 {
1193     input_thread_private_t *p_sys = input_priv(p_input);
1194
1195     /* Get max pts delay from input source */
1196     mtime_t i_pts_delay = p_sys->master->i_pts_delay;
1197     for( int i = 0; i < p_sys->i_slave; i++ )
1198         i_pts_delay = __MAX( i_pts_delay, p_sys->slave[i]->i_pts_delay );
1199
1200     if( i_pts_delay < 0 )
1201         i_pts_delay = 0;
1202
1203     /* Take care of audio/spu delay */
1204     const mtime_t i_audio_delay = var_GetInteger( p_input, "audio-delay" );
1205     const mtime_t i_spu_delay   = var_GetInteger( p_input, "spu-delay" );
1206     const mtime_t i_extra_delay = __MIN( i_audio_delay, i_spu_delay );
1207     if( i_extra_delay < 0 )
1208         i_pts_delay -= i_extra_delay;
1209
1210     /* Update cr_average depending on the caching */
1211     const int i_cr_average = var_GetInteger( p_input, "cr-average" ) * i_pts_delay / DEFAULT_PTS_DELAY;
1212
1213     /* */
1214     es_out_SetDelay( input_priv(p_input)->p_es_out_display, AUDIO_ES, i_audio_delay );
1215     es_out_SetDelay( input_priv(p_input)->p_es_out_display, SPU_ES, i_spu_delay );
1216     es_out_SetJitter( input_priv(p_input)->p_es_out, i_pts_delay, 0, i_cr_average );
1217 }
1218
1219 static void InitPrograms( input_thread_t * p_input )
1220 {
1221     int i_es_out_mode;
1222     vlc_list_t list;
1223
1224     /* Compute correct pts_delay */
1225     UpdatePtsDelay( p_input );
1226
1227     /* Set up es_out */
1228     i_es_out_mode = ES_OUT_MODE_AUTO;
1229     if( input_priv(p_input)->p_sout )
1230     {
1231         char *prgms;
1232
1233         if( (prgms = var_GetNonEmptyString( p_input, "programs" )) != NULL )
1234         {
1235             char *buf;
1236
1237             TAB_INIT( list.i_count, list.p_values );
1238             for( const char *prgm = strtok_r( prgms, ",", &buf );
1239                  prgm != NULL;
1240                  prgm = strtok_r( NULL, ",", &buf ) )
1241             {
1242                 vlc_value_t val = { .i_int = atoi( prgm ) };
1243                 TAB_APPEND(list.i_count, list.p_values, val);
1244             }
1245
1246             if( list.i_count > 0 )
1247                 i_es_out_mode = ES_OUT_MODE_PARTIAL;
1248                 /* Note : we should remove the "program" callback. */
1249
1250             free( prgms );
1251         }
1252         else if( var_GetBool( p_input, "sout-all" ) )
1253         {
1254             i_es_out_mode = ES_OUT_MODE_ALL;
1255         }
1256     }
1257     es_out_SetMode( input_priv(p_input)->p_es_out, i_es_out_mode );
1258
1259     /* Inform the demuxer about waited group (needed only for DVB) */
1260     if( i_es_out_mode == ES_OUT_MODE_ALL )
1261     {
1262         demux_Control( input_priv(p_input)->master->p_demux, DEMUX_SET_GROUP, -1, NULL );
1263     }
1264     else if( i_es_out_mode == ES_OUT_MODE_PARTIAL )
1265     {
1266         demux_Control( input_priv(p_input)->master->p_demux, DEMUX_SET_GROUP, -1,
1267                        &list );
1268         TAB_CLEAN( list.i_count, list.p_values );
1269     }
1270     else
1271     {
1272         demux_Control( input_priv(p_input)->master->p_demux, DEMUX_SET_GROUP,
1273                        es_out_GetGroupForced( input_priv(p_input)->p_es_out ), NULL );
1274     }
1275 }
1276
1277 static int Init( input_thread_t * p_input )
1278 {
1279     input_thread_private_t *priv = input_priv(p_input);
1280     input_source_t *master;
1281
1282     if( var_Type( p_input->obj.parent, "meta-file" ) )
1283     {
1284         msg_Dbg( p_input, "Input is a meta file: disabling unneeded options" );
1285         var_SetString( p_input, "sout", "" );
1286         var_SetBool( p_input, "sout-all", false );
1287         var_SetString( p_input, "input-slave", "" );
1288         var_SetInteger( p_input, "input-repeat", 0 );
1289         var_SetString( p_input, "sub-file", "" );
1290         var_SetBool( p_input, "sub-autodetect-file", false );
1291     }
1292
1293     InitStatistics( p_input );
1294 #ifdef ENABLE_SOUT
1295     if( InitSout( p_input ) )
1296         goto error;
1297 #endif
1298
1299     /* Create es out */
1300     priv->p_es_out = input_EsOutTimeshiftNew( p_input, priv->p_es_out_display,
1301                                               priv->i_rate );
1302     if( priv->p_es_out == NULL )
1303         goto error;
1304
1305     /* */
1306     input_ChangeState( p_input, OPENING_S );
1307     input_SendEventCache( p_input, 0.0 );
1308
1309     /* */
1310     master = InputSourceNew( p_input, priv->p_item->psz_uri, NULL, false );
1311     if( master == NULL )
1312         goto error;
1313     priv->master = master;
1314
1315     InitTitle( p_input );
1316
1317     /* Load master infos */
1318     /* Init length */
1319     mtime_t i_length;
1320     if( demux_Control( master->p_demux, DEMUX_GET_LENGTH, &i_length ) )
1321         i_length = 0;
1322     if( i_length <= 0 )
1323         i_length = input_item_GetDuration( priv->p_item );
1324     input_SendEventLength( p_input, i_length );
1325
1326     input_SendEventPosition( p_input, 0.0, 0 );
1327
1328     if( !priv->b_preparsing )
1329     {
1330         StartTitle( p_input );
1331         SetSubtitlesOptions( p_input );
1332         LoadSlaves( p_input );
1333         InitPrograms( p_input );
1334
1335         double f_rate = var_InheritFloat( p_input, "rate" );
1336         if( f_rate != 0.0 && f_rate != 1.0 )
1337         {
1338             vlc_value_t val = { .i_int = INPUT_RATE_DEFAULT / f_rate };
1339             input_ControlPush( p_input, INPUT_CONTROL_SET_RATE, &val );
1340         }
1341     }
1342
1343     if( !priv->b_preparsing && priv->p_sout )
1344     {
1345         priv->b_out_pace_control = priv->p_sout->i_out_pace_nocontrol > 0;
1346
1347         msg_Dbg( p_input, "starting in %ssync mode",
1348                  priv->b_out_pace_control ? "a" : "" );
1349     }
1350
1351     vlc_meta_t *p_meta = vlc_meta_New();
1352     if( p_meta != NULL )
1353     {
1354         /* Get meta data from users */
1355         InputMetaUser( p_input, p_meta );
1356
1357         /* Get meta data from master input */
1358         InputSourceMeta( p_input, master, p_meta );
1359
1360         /* And from slave */
1361         for( int i = 0; i < priv->i_slave; i++ )
1362             InputSourceMeta( p_input, priv->slave[i], p_meta );
1363
1364         es_out_ControlSetMeta( priv->p_es_out, p_meta );
1365         vlc_meta_Delete( p_meta );
1366     }
1367
1368     msg_Dbg( p_input, "`%s' successfully opened",
1369              input_priv(p_input)->p_item->psz_uri );
1370
1371     /* initialization is complete */
1372     input_ChangeState( p_input, PLAYING_S );
1373
1374     return VLC_SUCCESS;
1375
1376 error:
1377     input_ChangeState( p_input, ERROR_S );
1378
1379     if( input_priv(p_input)->p_es_out )
1380         es_out_Delete( input_priv(p_input)->p_es_out );
1381     es_out_SetMode( input_priv(p_input)->p_es_out_display, ES_OUT_MODE_END );
1382     if( input_priv(p_input)->p_resource )
1383     {
1384         if( input_priv(p_input)->p_sout )
1385             input_resource_RequestSout( input_priv(p_input)->p_resource,
1386                                          input_priv(p_input)->p_sout, NULL );
1387         input_resource_SetInput( input_priv(p_input)->p_resource, NULL );
1388         if( input_priv(p_input)->p_resource_private )
1389             input_resource_Terminate( input_priv(p_input)->p_resource_private );
1390     }
1391
1392     if( !priv->b_preparsing && libvlc_stats( p_input ) )
1393     {
1394 #define EXIT_COUNTER( c ) do { if( input_priv(p_input)->counters.p_##c ) \
1395                                    stats_CounterClean( input_priv(p_input)->counters.p_##c );\
1396                                input_priv(p_input)->counters.p_##c = NULL; } while(0)
1397         EXIT_COUNTER( read_bytes );
1398         EXIT_COUNTER( read_packets );
1399         EXIT_COUNTER( demux_read );
1400         EXIT_COUNTER( input_bitrate );
1401         EXIT_COUNTER( demux_bitrate );
1402         EXIT_COUNTER( demux_corrupted );
1403         EXIT_COUNTER( demux_discontinuity );
1404         EXIT_COUNTER( played_abuffers );
1405         EXIT_COUNTER( lost_abuffers );
1406         EXIT_COUNTER( displayed_pictures );
1407         EXIT_COUNTER( lost_pictures );
1408         EXIT_COUNTER( decoded_audio );
1409         EXIT_COUNTER( decoded_video );
1410         EXIT_COUNTER( decoded_sub );
1411
1412         if( input_priv(p_input)->p_sout )
1413         {
1414             EXIT_COUNTER( sout_sent_packets );
1415             EXIT_COUNTER( sout_sent_bytes );
1416             EXIT_COUNTER( sout_send_bitrate );
1417         }
1418 #undef EXIT_COUNTER
1419     }
1420
1421     /* Mark them deleted */
1422     input_priv(p_input)->p_es_out = NULL;
1423     input_priv(p_input)->p_sout = NULL;
1424
1425     return VLC_EGENERIC;
1426 }
1427
1428 /*****************************************************************************
1429  * End: end the input thread
1430  *****************************************************************************/
1431 static void End( input_thread_t * p_input )
1432 {
1433     input_thread_private_t *priv = input_priv(p_input);
1434
1435     /* We are at the end */
1436     input_ChangeState( p_input, END_S );
1437
1438     /* Clean control variables */
1439     input_ControlVarStop( p_input );
1440
1441     /* Stop es out activity */
1442     es_out_SetMode( priv->p_es_out, ES_OUT_MODE_NONE );
1443
1444     /* Delete slave */
1445     for( int i = 0; i < priv->i_slave; i++ )
1446         InputSourceDestroy( priv->slave[i] );
1447     free( priv->slave );
1448
1449     /* Clean up master */
1450     InputSourceDestroy( priv->master );
1451     priv->i_title = 0;
1452     priv->title = NULL;
1453     priv->i_title_offset = 0;
1454     priv->i_seekpoint_offset = 0;
1455
1456     /* Unload all modules */
1457     if( priv->p_es_out )
1458         es_out_Delete( priv->p_es_out );
1459     es_out_SetMode( priv->p_es_out_display, ES_OUT_MODE_END );
1460
1461     if( !priv->b_preparsing )
1462     {
1463 #define CL_CO( c ) \
1464 do { \
1465     stats_CounterClean( priv->counters.p_##c ); \
1466     priv->counters.p_##c = NULL; \
1467 } while (0)
1468
1469         if( libvlc_stats( p_input ) )
1470         {
1471             /* make sure we are up to date */
1472             stats_ComputeInputStats( p_input, priv->p_item->p_stats );
1473             CL_CO( read_bytes );
1474             CL_CO( read_packets );
1475             CL_CO( demux_read );
1476             CL_CO( input_bitrate );
1477             CL_CO( demux_bitrate );
1478             CL_CO( demux_corrupted );
1479             CL_CO( demux_discontinuity );
1480             CL_CO( played_abuffers );
1481             CL_CO( lost_abuffers );
1482             CL_CO( displayed_pictures );
1483             CL_CO( lost_pictures );
1484             CL_CO( decoded_audio) ;
1485             CL_CO( decoded_video );
1486             CL_CO( decoded_sub) ;
1487         }
1488
1489         /* Close optional stream output instance */
1490         if( priv->p_sout )
1491         {
1492             CL_CO( sout_sent_packets );
1493             CL_CO( sout_sent_bytes );
1494             CL_CO( sout_send_bitrate );
1495         }
1496 #undef CL_CO
1497     }
1498
1499     vlc_mutex_lock( &priv->p_item->lock );
1500     if( priv->i_attachment > 0 )
1501     {
1502         for( int i = 0; i < priv->i_attachment; i++ )
1503             vlc_input_attachment_Delete( priv->attachment[i] );
1504         TAB_CLEAN( priv->i_attachment, priv->attachment );
1505         free( priv->attachment_demux);
1506         priv->attachment_demux = NULL;
1507     }
1508
1509     /* clean bookmarks */
1510     for( int i = 0; i < priv->i_bookmark; ++i )
1511         vlc_seekpoint_Delete( priv->pp_bookmark[i] );
1512     TAB_CLEAN( priv->i_bookmark, priv->pp_bookmark );
1513
1514     vlc_mutex_unlock( &input_priv(p_input)->p_item->lock );
1515
1516     /* */
1517     input_resource_RequestSout( input_priv(p_input)->p_resource,
1518                                  input_priv(p_input)->p_sout, NULL );
1519     input_resource_SetInput( input_priv(p_input)->p_resource, NULL );
1520     if( input_priv(p_input)->p_resource_private )
1521         input_resource_Terminate( input_priv(p_input)->p_resource_private );
1522 }
1523
1524 /*****************************************************************************
1525  * Control
1526  *****************************************************************************/
1527 void input_ControlPush( input_thread_t *p_input,
1528                         int i_type, vlc_value_t *p_val )
1529 {
1530     input_thread_private_t *sys = input_priv(p_input);
1531
1532     vlc_mutex_lock( &sys->lock_control );
1533     if( sys->is_stopped || sys->i_control >= INPUT_CONTROL_FIFO_SIZE )
1534     {
1535         if( sys->is_stopped )
1536             msg_Dbg( p_input, "input control stopped, trashing type=%d",
1537                      i_type );
1538         else
1539             msg_Err( p_input, "input control fifo overflow, trashing type=%d",
1540                      i_type );
1541         if( p_val )
1542             ControlRelease( i_type, *p_val );
1543     }
1544     else
1545     {
1546         input_control_t c;
1547         c.i_type = i_type;
1548         if( p_val )
1549             c.val = *p_val;
1550         else
1551             memset( &c.val, 0, sizeof(c.val) );
1552
1553         sys->control[sys->i_control++] = c;
1554
1555         vlc_cond_signal( &sys->wait_control );
1556     }
1557     vlc_mutex_unlock( &sys->lock_control );
1558 }
1559
1560 static int ControlGetReducedIndexLocked( input_thread_t *p_input )
1561 {
1562     const int i_lt = input_priv(p_input)->control[0].i_type;
1563     int i;
1564     for( i = 1; i < input_priv(p_input)->i_control; i++ )
1565     {
1566         const int i_ct = input_priv(p_input)->control[i].i_type;
1567
1568         if( i_lt == i_ct &&
1569             ( i_ct == INPUT_CONTROL_SET_STATE ||
1570               i_ct == INPUT_CONTROL_SET_RATE ||
1571               i_ct == INPUT_CONTROL_SET_POSITION ||
1572               i_ct == INPUT_CONTROL_SET_TIME ||
1573               i_ct == INPUT_CONTROL_SET_PROGRAM ||
1574               i_ct == INPUT_CONTROL_SET_TITLE ||
1575               i_ct == INPUT_CONTROL_SET_SEEKPOINT ||
1576               i_ct == INPUT_CONTROL_SET_BOOKMARK ) )
1577         {
1578             continue;
1579         }
1580         else
1581         {
1582             /* TODO but that's not that important
1583                 - merge SET_X with SET_X_CMD
1584                 - ignore SET_SEEKPOINT/SET_POSITION/SET_TIME before a SET_TITLE
1585                 - ignore SET_SEEKPOINT/SET_POSITION/SET_TIME before another among them
1586                 - ?
1587                 */
1588             break;
1589         }
1590     }
1591     return i - 1;
1592 }
1593
1594
1595 static inline int ControlPop( input_thread_t *p_input,
1596                               int *pi_type, vlc_value_t *p_val,
1597                               mtime_t i_deadline, bool b_postpone_seek )
1598 {
1599     input_thread_private_t *p_sys = input_priv(p_input);
1600
1601     vlc_mutex_lock( &p_sys->lock_control );
1602     while( p_sys->i_control <= 0 ||
1603            ( b_postpone_seek && ControlIsSeekRequest( p_sys->control[0].i_type ) ) )
1604     {
1605         if( p_sys->is_stopped )
1606         {
1607             vlc_mutex_unlock( &p_sys->lock_control );
1608             return VLC_EGENERIC;
1609         }
1610
1611         if( i_deadline >= 0 )
1612         {
1613             if( vlc_cond_timedwait( &p_sys->wait_control, &p_sys->lock_control,
1614                                     i_deadline ) )
1615             {
1616                 vlc_mutex_unlock( &p_sys->lock_control );
1617                 return VLC_EGENERIC;
1618             }
1619         }
1620         else
1621             vlc_cond_wait( &p_sys->wait_control, &p_sys->lock_control );
1622     }
1623
1624     /* */
1625     const int i_index = ControlGetReducedIndexLocked( p_input );
1626
1627     for( int i = 0; i < i_index; ++i )
1628     {
1629         /* Release Reduced controls */
1630         ControlRelease( p_sys->control[i].i_type, p_sys->control[i].val );
1631     }
1632
1633     /* */
1634     *pi_type = p_sys->control[i_index].i_type;
1635     *p_val   = p_sys->control[i_index].val;
1636
1637     p_sys->i_control -= i_index + 1;
1638     if( p_sys->i_control > 0 )
1639         memmove( &p_sys->control[0], &p_sys->control[i_index+1],
1640                  sizeof(*p_sys->control) * p_sys->i_control );
1641     vlc_mutex_unlock( &p_sys->lock_control );
1642
1643     return VLC_SUCCESS;
1644 }
1645 static bool ControlIsSeekRequest( int i_type )
1646 {
1647     switch( i_type )
1648     {
1649     case INPUT_CONTROL_SET_POSITION:
1650     case INPUT_CONTROL_SET_TIME:
1651     case INPUT_CONTROL_SET_TITLE:
1652     case INPUT_CONTROL_SET_TITLE_NEXT:
1653     case INPUT_CONTROL_SET_TITLE_PREV:
1654     case INPUT_CONTROL_SET_SEEKPOINT:
1655     case INPUT_CONTROL_SET_SEEKPOINT_NEXT:
1656     case INPUT_CONTROL_SET_SEEKPOINT_PREV:
1657     case INPUT_CONTROL_SET_BOOKMARK:
1658     case INPUT_CONTROL_NAV_ACTIVATE:
1659     case INPUT_CONTROL_NAV_UP:
1660     case INPUT_CONTROL_NAV_DOWN:
1661     case INPUT_CONTROL_NAV_LEFT:
1662     case INPUT_CONTROL_NAV_RIGHT:
1663     case INPUT_CONTROL_NAV_POPUP:
1664     case INPUT_CONTROL_NAV_MENU:
1665         return true;
1666     default:
1667         return false;
1668     }
1669 }
1670
1671 static void ControlRelease( int i_type, vlc_value_t val )
1672 {
1673     switch( i_type )
1674     {
1675     case INPUT_CONTROL_ADD_SUBTITLE:
1676         free( val.psz_string );
1677         break;
1678     case INPUT_CONTROL_ADD_SLAVE:
1679         if( val.p_address )
1680             input_item_slave_Delete( val.p_address );
1681         break;
1682     case INPUT_CONTROL_SET_VIEWPOINT:
1683     case INPUT_CONTROL_SET_INITIAL_VIEWPOINT:
1684     case INPUT_CONTROL_UPDATE_VIEWPOINT:
1685         free( val.p_address );
1686         break;
1687
1688     default:
1689         break;
1690     }
1691 }
1692
1693 /* Pause input */
1694 static void ControlPause( input_thread_t *p_input, mtime_t i_control_date )
1695 {
1696     int i_state = PAUSE_S;
1697
1698     if( input_priv(p_input)->b_can_pause )
1699     {
1700         demux_t *p_demux = input_priv(p_input)->master->p_demux;
1701
1702         if( demux_Control( p_demux, DEMUX_SET_PAUSE_STATE, true ) )
1703         {
1704             msg_Warn( p_input, "cannot set pause state" );
1705             return;
1706         }
1707     }
1708
1709     /* */
1710     if( es_out_SetPauseState( input_priv(p_input)->p_es_out, input_priv(p_input)->b_can_pause,
1711                               true, i_control_date ) )
1712     {
1713         msg_Warn( p_input, "cannot set pause state at es_out level" );
1714         return;
1715     }
1716
1717     /* Switch to new state */
1718     input_ChangeState( p_input, i_state );
1719 }
1720
1721 static void ControlUnpause( input_thread_t *p_input, mtime_t i_control_date )
1722 {
1723     if( input_priv(p_input)->b_can_pause )
1724     {
1725         demux_t *p_demux = input_priv(p_input)->master->p_demux;
1726
1727         if( demux_Control( p_demux, DEMUX_SET_PAUSE_STATE, false ) )
1728         {
1729             msg_Err( p_input, "cannot resume" );
1730             input_ChangeState( p_input, ERROR_S );
1731             return;
1732         }
1733     }
1734
1735     /* Switch to play */
1736     input_ChangeState( p_input, PLAYING_S );
1737     es_out_SetPauseState( input_priv(p_input)->p_es_out, false, false, i_control_date );
1738 }
1739
1740 static bool Control( input_thread_t *p_input,
1741                      int i_type, vlc_value_t val )
1742 {
1743     const mtime_t i_control_date = mdate();
1744     /* FIXME b_force_update is abused, it should be carefully checked */
1745     bool b_force_update = false;
1746
1747     if( !p_input )
1748         return b_force_update;
1749
1750     switch( i_type )
1751     {
1752         case INPUT_CONTROL_SET_POSITION:
1753         {
1754             if( input_priv(p_input)->b_recording )
1755             {
1756                 msg_Err( p_input, "INPUT_CONTROL_SET_POSITION ignored while recording" );
1757                 break;
1758             }
1759
1760             float f_pos = val.f_float;
1761             if( f_pos < 0.f )
1762                 f_pos = 0.f;
1763             else if( f_pos > 1.f )
1764                 f_pos = 1.f;
1765             /* Reset the decoders states and clock sync (before calling the demuxer */
1766             es_out_SetTime( input_priv(p_input)->p_es_out, -1 );
1767             if( demux_Control( input_priv(p_input)->master->p_demux, DEMUX_SET_POSITION,
1768                                (double) f_pos, !input_priv(p_input)->b_fast_seek ) )
1769             {
1770                 msg_Err( p_input, "INPUT_CONTROL_SET_POSITION "
1771                          "%2.1f%% failed", (double)(f_pos * 100.f) );
1772             }
1773             else
1774             {
1775                 if( input_priv(p_input)->i_slave > 0 )
1776                     SlaveSeek( p_input );
1777                 input_priv(p_input)->master->b_eof = false;
1778
1779                 b_force_update = true;
1780             }
1781             break;
1782         }
1783
1784         case INPUT_CONTROL_SET_TIME:
1785         {
1786             int64_t i_time;
1787             int i_ret;
1788
1789             if( input_priv(p_input)->b_recording )
1790             {
1791                 msg_Err( p_input, "INPUT_CONTROL_SET_TIME ignored while recording" );
1792                 break;
1793             }
1794
1795             i_time = val.i_int;
1796             if( i_time < 0 )
1797                 i_time = 0;
1798
1799             /* Reset the decoders states and clock sync (before calling the demuxer */
1800             es_out_SetTime( input_priv(p_input)->p_es_out, -1 );
1801
1802             i_ret = demux_Control( input_priv(p_input)->master->p_demux,
1803                                    DEMUX_SET_TIME, i_time,
1804                                    !input_priv(p_input)->b_fast_seek );
1805             if( i_ret )
1806             {
1807                 int64_t i_length;
1808
1809                 /* Emulate it with a SET_POS */
1810                 if( !demux_Control( input_priv(p_input)->master->p_demux,
1811                                     DEMUX_GET_LENGTH, &i_length ) && i_length > 0 )
1812                 {
1813                     double f_pos = (double)i_time / (double)i_length;
1814                     i_ret = demux_Control( input_priv(p_input)->master->p_demux,
1815                                             DEMUX_SET_POSITION, f_pos,
1816                                             !input_priv(p_input)->b_fast_seek );
1817                 }
1818             }
1819             if( i_ret )
1820             {
1821                 msg_Warn( p_input, "INPUT_CONTROL_SET_TIME %"PRId64
1822                          " failed or not possible", i_time );
1823             }
1824             else
1825             {
1826                 if( input_priv(p_input)->i_slave > 0 )
1827                     SlaveSeek( p_input );
1828                 input_priv(p_input)->master->b_eof = false;
1829
1830                 b_force_update = true;
1831             }
1832             break;
1833         }
1834
1835         case INPUT_CONTROL_SET_STATE:
1836             switch( val.i_int )
1837             {
1838                 case PLAYING_S:
1839                     if( input_priv(p_input)->i_state == PAUSE_S )
1840                     {
1841                         ControlUnpause( p_input, i_control_date );
1842                         b_force_update = true;
1843                     }
1844                     break;
1845                 case PAUSE_S:
1846                     if( input_priv(p_input)->i_state == PLAYING_S )
1847                     {
1848                         ControlPause( p_input, i_control_date );
1849                         b_force_update = true;
1850                     }
1851                     break;
1852                 default:
1853                     msg_Err( p_input, "invalid INPUT_CONTROL_SET_STATE" );
1854             }
1855             break;
1856
1857         case INPUT_CONTROL_SET_RATE:
1858         {
1859             /* Get rate and direction */
1860             int i_rate = abs( val.i_int );
1861             int i_rate_sign = val.i_int < 0 ? -1 : 1;
1862
1863             /* Check rate bound */
1864             if( i_rate < INPUT_RATE_MIN )
1865             {
1866                 msg_Dbg( p_input, "cannot set rate faster" );
1867                 i_rate = INPUT_RATE_MIN;
1868             }
1869             else if( i_rate > INPUT_RATE_MAX )
1870             {
1871                 msg_Dbg( p_input, "cannot set rate slower" );
1872                 i_rate = INPUT_RATE_MAX;
1873             }
1874
1875             /* Apply direction */
1876             if( i_rate_sign < 0 )
1877             {
1878                 if( input_priv(p_input)->master->b_rescale_ts )
1879                 {
1880                     msg_Dbg( p_input, "cannot set negative rate" );
1881                     i_rate = input_priv(p_input)->i_rate;
1882                     assert( i_rate > 0 );
1883                 }
1884                 else
1885                 {
1886                     i_rate *= i_rate_sign;
1887                 }
1888             }
1889
1890             if( i_rate != INPUT_RATE_DEFAULT &&
1891                 ( ( !input_priv(p_input)->b_can_rate_control && !input_priv(p_input)->master->b_rescale_ts ) ||
1892                   ( input_priv(p_input)->p_sout && !input_priv(p_input)->b_out_pace_control ) ) )
1893             {
1894                 msg_Dbg( p_input, "cannot change rate" );
1895                 i_rate = INPUT_RATE_DEFAULT;
1896             }
1897             if( i_rate != input_priv(p_input)->i_rate &&
1898                 !input_priv(p_input)->b_can_pace_control && input_priv(p_input)->b_can_rate_control )
1899             {
1900                 if( !input_priv(p_input)->master->b_rescale_ts )
1901                     es_out_Control( input_priv(p_input)->p_es_out, ES_OUT_RESET_PCR );
1902
1903                 if( demux_Control( input_priv(p_input)->master->p_demux, DEMUX_SET_RATE,
1904                                    &i_rate ) )
1905                 {
1906                     msg_Warn( p_input, "ACCESS/DEMUX_SET_RATE failed" );
1907                     i_rate = input_priv(p_input)->i_rate;
1908                 }
1909             }
1910
1911             /* */
1912             if( i_rate != input_priv(p_input)->i_rate )
1913             {
1914                 input_priv(p_input)->i_rate = i_rate;
1915                 input_SendEventRate( p_input, i_rate );
1916
1917                 if( input_priv(p_input)->master->b_rescale_ts )
1918                 {
1919                     const int i_rate_source = (input_priv(p_input)->b_can_pace_control || input_priv(p_input)->b_can_rate_control ) ? i_rate : INPUT_RATE_DEFAULT;
1920                     es_out_SetRate( input_priv(p_input)->p_es_out, i_rate_source, i_rate );
1921                 }
1922
1923                 b_force_update = true;
1924             }
1925             break;
1926         }
1927
1928         case INPUT_CONTROL_SET_PROGRAM:
1929             /* No need to force update, es_out does it if needed */
1930             es_out_Control( input_priv(p_input)->p_es_out,
1931                             ES_OUT_SET_GROUP, val.i_int );
1932
1933             demux_Control( input_priv(p_input)->master->p_demux, DEMUX_SET_GROUP, val.i_int,
1934                             NULL );
1935             break;
1936
1937         case INPUT_CONTROL_SET_ES:
1938             /* No need to force update, es_out does it if needed */
1939             es_out_Control( input_priv(p_input)->p_es_out_display,
1940                             ES_OUT_SET_ES_BY_ID, (int)val.i_int );
1941
1942             demux_Control( input_priv(p_input)->master->p_demux, DEMUX_SET_ES, (int)val.i_int );
1943             break;
1944
1945         case INPUT_CONTROL_RESTART_ES:
1946             es_out_Control( input_priv(p_input)->p_es_out_display,
1947                             ES_OUT_RESTART_ES_BY_ID, (int)val.i_int );
1948             break;
1949
1950         case INPUT_CONTROL_SET_VIEWPOINT:
1951         case INPUT_CONTROL_SET_INITIAL_VIEWPOINT:
1952         case INPUT_CONTROL_UPDATE_VIEWPOINT:
1953         {
1954             input_thread_private_t *priv = input_priv(p_input);
1955             const vlc_viewpoint_t *p_vp = val.p_address;
1956
1957             if ( i_type == INPUT_CONTROL_SET_INITIAL_VIEWPOINT )
1958             {
1959
1960                 /* Set the initial viewpoint if it had not been changed by the
1961                  * user. */
1962                 if( !priv->viewpoint_changed )
1963                     priv->viewpoint = *p_vp;
1964                 /* Update viewpoints of aout and every vouts in all cases. */
1965             }
1966             else if ( i_type == INPUT_CONTROL_SET_VIEWPOINT)
1967             {
1968                 priv->viewpoint_changed = true;
1969                 priv->viewpoint = *p_vp;
1970             }
1971             else
1972             {
1973                 priv->viewpoint_changed = true;
1974                 priv->viewpoint.yaw   += p_vp->yaw;
1975                 priv->viewpoint.pitch += p_vp->pitch;
1976                 priv->viewpoint.roll  += p_vp->roll;
1977                 priv->viewpoint.fov   += p_vp->fov;
1978             }
1979
1980             vlc_viewpoint_clip( &priv->viewpoint );
1981
1982             vout_thread_t **pp_vout;
1983             size_t i_vout;
1984             input_resource_HoldVouts( priv->p_resource, &pp_vout, &i_vout );
1985
1986             for( size_t i = 0; i < i_vout; ++i )
1987             {
1988                 var_SetAddress( pp_vout[i], "viewpoint", &priv->viewpoint );
1989                 /* This variable can only be read from callbacks */
1990                 var_Change( pp_vout[i], "viewpoint", VLC_VAR_SETVALUE,
1991                             &(vlc_value_t) { .p_address = NULL }, NULL );
1992                 vlc_object_release( pp_vout[i] );
1993             }
1994             free( pp_vout );
1995
1996             audio_output_t *p_aout = input_resource_HoldAout( priv->p_resource );
1997             if( p_aout )
1998             {
1999
2000                 var_SetAddress( p_aout, "viewpoint", &priv->viewpoint );
2001                 /* This variable can only be read from callbacks */
2002                 var_Change( p_aout, "viewpoint", VLC_VAR_SETVALUE,
2003                             &(vlc_value_t) { .p_address = NULL }, NULL );
2004                 vlc_object_release( p_aout );
2005             }
2006             break;
2007         }
2008
2009         case INPUT_CONTROL_SET_AUDIO_DELAY:
2010             input_SendEventAudioDelay( p_input, val.i_int );
2011             UpdatePtsDelay( p_input );
2012             break;
2013
2014         case INPUT_CONTROL_SET_SPU_DELAY:
2015             input_SendEventSubtitleDelay( p_input, val.i_int );
2016             UpdatePtsDelay( p_input );
2017             break;
2018
2019         case INPUT_CONTROL_SET_TITLE:
2020         case INPUT_CONTROL_SET_TITLE_NEXT:
2021         case INPUT_CONTROL_SET_TITLE_PREV:
2022         {
2023             if( input_priv(p_input)->b_recording )
2024             {
2025                 msg_Err( p_input, "INPUT_CONTROL_SET_TITLE(*) ignored while recording" );
2026                 break;
2027             }
2028             if( input_priv(p_input)->master->i_title <= 0 )
2029                 break;
2030
2031             int i_title = demux_GetTitle( input_priv(p_input)->master->p_demux );
2032             if( i_type == INPUT_CONTROL_SET_TITLE_PREV )
2033                 i_title--;
2034             else if( i_type == INPUT_CONTROL_SET_TITLE_NEXT )
2035                 i_title++;
2036             else
2037                 i_title = val.i_int;
2038             if( i_title < 0 || i_title >= input_priv(p_input)->master->i_title )
2039                 break;
2040
2041             es_out_SetTime( input_priv(p_input)->p_es_out, -1 );
2042             demux_Control( input_priv(p_input)->master->p_demux,
2043                            DEMUX_SET_TITLE, i_title );
2044             input_SendEventTitle( p_input, i_title );
2045             break;
2046         }
2047         case INPUT_CONTROL_SET_SEEKPOINT:
2048         case INPUT_CONTROL_SET_SEEKPOINT_NEXT:
2049         case INPUT_CONTROL_SET_SEEKPOINT_PREV:
2050         {
2051             if( input_priv(p_input)->b_recording )
2052             {
2053                 msg_Err( p_input, "INPUT_CONTROL_SET_SEEKPOINT(*) ignored while recording" );
2054                 break;
2055             }
2056             if( input_priv(p_input)->master->i_title <= 0 )
2057                 break;
2058
2059             demux_t *p_demux = input_priv(p_input)->master->p_demux;
2060
2061             int i_title = demux_GetTitle( p_demux );
2062             int i_seekpoint = demux_GetSeekpoint( p_demux );
2063
2064             if( i_type == INPUT_CONTROL_SET_SEEKPOINT_PREV )
2065             {
2066                 int64_t i_seekpoint_time = input_priv(p_input)->master->title[i_title]->seekpoint[i_seekpoint]->i_time_offset;
2067                 int64_t i_input_time = var_GetInteger( p_input, "time" );
2068                 if( i_seekpoint_time >= 0 && i_input_time >= 0 )
2069                 {
2070                     if( i_input_time < i_seekpoint_time + 3000000 )
2071                         i_seekpoint--;
2072                 }
2073                 else
2074                     i_seekpoint--;
2075             }
2076             else if( i_type == INPUT_CONTROL_SET_SEEKPOINT_NEXT )
2077                 i_seekpoint++;
2078             else
2079                 i_seekpoint = val.i_int;
2080             if( i_seekpoint < 0
2081              || i_seekpoint >= input_priv(p_input)->master->title[i_title]->i_seekpoint )
2082                 break;
2083
2084             es_out_SetTime( input_priv(p_input)->p_es_out, -1 );
2085             demux_Control( input_priv(p_input)->master->p_demux,
2086                            DEMUX_SET_SEEKPOINT, i_seekpoint );
2087             input_SendEventSeekpoint( p_input, i_title, i_seekpoint );
2088             break;
2089         }
2090
2091         case INPUT_CONTROL_ADD_SUBTITLE:
2092             if( val.psz_string )
2093             {
2094                 char *psz_uri = input_SubtitleFile2Uri( p_input, val.psz_string );
2095                 if( psz_uri != NULL )
2096                 {
2097                     input_SlaveSourceAdd( p_input, SLAVE_TYPE_SPU, psz_uri,
2098                                           SLAVE_ADD_FORCED );
2099                     free( psz_uri );
2100                 }
2101             }
2102             break;
2103
2104         case INPUT_CONTROL_ADD_SLAVE:
2105             if( val.p_address )
2106             {
2107                 input_item_slave_t *p_item_slave  = val.p_address;
2108                 unsigned i_flags = SLAVE_ADD_CANFAIL | SLAVE_ADD_SET_TIME;
2109                 if( p_item_slave->b_forced )
2110                     i_flags |= SLAVE_ADD_FORCED;
2111
2112                 if( input_SlaveSourceAdd( p_input, p_item_slave->i_type,
2113                                           p_item_slave->psz_uri, i_flags )
2114                                           == VLC_SUCCESS )
2115                 {
2116                     /* Update item slaves */
2117                     input_item_AddSlave( input_priv(p_input)->p_item, p_item_slave );
2118                     /* The slave is now owned by the item */
2119                     val.p_address = NULL;
2120                 }
2121             }
2122             break;
2123
2124         case INPUT_CONTROL_SET_RECORD_STATE:
2125             if( !!input_priv(p_input)->b_recording != !!val.b_bool )
2126             {
2127                 if( input_priv(p_input)->master->b_can_stream_record )
2128                 {
2129                     if( demux_Control( input_priv(p_input)->master->p_demux,
2130                                        DEMUX_SET_RECORD_STATE, val.b_bool ) )
2131                         val.b_bool = false;
2132                 }
2133                 else
2134                 {
2135                     if( es_out_SetRecordState( input_priv(p_input)->p_es_out_display, val.b_bool ) )
2136                         val.b_bool = false;
2137                 }
2138                 input_priv(p_input)->b_recording = val.b_bool;
2139
2140                 input_SendEventRecord( p_input, val.b_bool );
2141
2142                 b_force_update = true;
2143             }
2144             break;
2145
2146         case INPUT_CONTROL_SET_FRAME_NEXT:
2147             if( input_priv(p_input)->i_state == PAUSE_S )
2148             {
2149                 es_out_SetFrameNext( input_priv(p_input)->p_es_out );
2150             }
2151             else if( input_priv(p_input)->i_state == PLAYING_S )
2152             {
2153                 ControlPause( p_input, i_control_date );
2154             }
2155             else
2156             {
2157                 msg_Err( p_input, "invalid state for frame next" );
2158             }
2159             b_force_update = true;
2160             break;
2161
2162         case INPUT_CONTROL_SET_BOOKMARK:
2163         {
2164             mtime_t time_offset = -1;
2165
2166             vlc_mutex_lock( &input_priv(p_input)->p_item->lock );
2167             if( val.i_int >= 0 && val.i_int < input_priv(p_input)->i_bookmark )
2168             {
2169                 const seekpoint_t *p_bookmark = input_priv(p_input)->pp_bookmark[val.i_int];
2170                 time_offset = p_bookmark->i_time_offset;
2171             }
2172             vlc_mutex_unlock( &input_priv(p_input)->p_item->lock );
2173
2174             if( time_offset < 0 )
2175             {
2176                 msg_Err( p_input, "invalid bookmark %"PRId64, val.i_int );
2177                 break;
2178             }
2179
2180             val.i_int = time_offset;
2181             b_force_update = Control( p_input, INPUT_CONTROL_SET_TIME, val );
2182             break;
2183         }
2184
2185         case INPUT_CONTROL_NAV_ACTIVATE:
2186         case INPUT_CONTROL_NAV_UP:
2187         case INPUT_CONTROL_NAV_DOWN:
2188         case INPUT_CONTROL_NAV_LEFT:
2189         case INPUT_CONTROL_NAV_RIGHT:
2190         case INPUT_CONTROL_NAV_POPUP:
2191         case INPUT_CONTROL_NAV_MENU:
2192             demux_Control( input_priv(p_input)->master->p_demux, i_type
2193                            - INPUT_CONTROL_NAV_ACTIVATE + DEMUX_NAV_ACTIVATE );
2194             break;
2195
2196         default:
2197             msg_Err( p_input, "not yet implemented" );
2198             break;
2199     }
2200
2201     ControlRelease( i_type, val );
2202     return b_force_update;
2203 }
2204
2205 /*****************************************************************************
2206  * UpdateTitleSeekpoint
2207  *****************************************************************************/
2208 static int UpdateTitleSeekpoint( input_thread_t *p_input,
2209                                  int i_title, int i_seekpoint )
2210 {
2211     int i_title_end = input_priv(p_input)->master->i_title_end -
2212                         input_priv(p_input)->master->i_title_offset;
2213     int i_seekpoint_end = input_priv(p_input)->master->i_seekpoint_end -
2214                             input_priv(p_input)->master->i_seekpoint_offset;
2215
2216     if( i_title_end >= 0 && i_seekpoint_end >= 0 )
2217     {
2218         if( i_title > i_title_end ||
2219             ( i_title == i_title_end && i_seekpoint > i_seekpoint_end ) )
2220             return VLC_DEMUXER_EOF;
2221     }
2222     else if( i_seekpoint_end >= 0 )
2223     {
2224         if( i_seekpoint > i_seekpoint_end )
2225             return VLC_DEMUXER_EOF;
2226     }
2227     else if( i_title_end >= 0 )
2228     {
2229         if( i_title > i_title_end )
2230             return VLC_DEMUXER_EOF;
2231     }
2232     return VLC_DEMUXER_SUCCESS;
2233 }
2234 /*****************************************************************************
2235  * Update*FromDemux:
2236  *****************************************************************************/
2237 static int UpdateTitleSeekpointFromDemux( input_thread_t *p_input )
2238 {
2239     demux_t *p_demux = input_priv(p_input)->master->p_demux;
2240
2241     /* TODO event-like */
2242     if( demux_TestAndClearFlags( p_demux, INPUT_UPDATE_TITLE ) )
2243         input_SendEventTitle( p_input, demux_GetTitle( p_demux ) );
2244
2245     if( demux_TestAndClearFlags( p_demux, INPUT_UPDATE_SEEKPOINT ) )
2246         input_SendEventSeekpoint( p_input, demux_GetTitle( p_demux ),
2247                                   demux_GetSeekpoint( p_demux ) );
2248
2249     return UpdateTitleSeekpoint( p_input,
2250                                  demux_GetTitle( p_demux ),
2251                                  demux_GetSeekpoint( p_demux ) );
2252 }
2253
2254 static void UpdateGenericFromDemux( input_thread_t *p_input )
2255 {
2256     demux_t *p_demux = input_priv(p_input)->master->p_demux;
2257
2258     if( demux_TestAndClearFlags( p_demux, INPUT_UPDATE_META ) )
2259         InputUpdateMeta( p_input, p_demux );
2260
2261     {
2262         double quality;
2263         double strength;
2264
2265         if( !demux_Control( p_demux, DEMUX_GET_SIGNAL, &quality, &strength ) )
2266             input_SendEventSignal( p_input, quality, strength );
2267     }
2268 }
2269
2270 static void UpdateTitleListfromDemux( input_thread_t *p_input )
2271 {
2272     input_source_t *in = input_priv(p_input)->master;
2273
2274     /* Delete the preexisting titles */
2275     if( in->i_title > 0 )
2276     {
2277         for( int i = 0; i < in->i_title; i++ )
2278             vlc_input_title_Delete( in->title[i] );
2279         TAB_CLEAN( in->i_title, in->title );
2280         in->b_title_demux = false;
2281     }
2282
2283     /* Get the new title list */
2284     if( demux_Control( in->p_demux, DEMUX_GET_TITLE_INFO,
2285                        &in->title, &in->i_title,
2286                        &in->i_title_offset, &in->i_seekpoint_offset ) )
2287         TAB_INIT( in->i_title, in->title );
2288     else
2289         in->b_title_demux = true;
2290
2291     InitTitle( p_input );
2292 }
2293
2294 static int
2295 InputStreamHandleAnchor( input_source_t *source, stream_t **stream,
2296                          char const *anchor )
2297 {
2298     char const* extra;
2299     if( stream_extractor_AttachParsed( stream, anchor, &extra ) )
2300     {
2301         msg_Err( source, "unable to attach stream-extractors for %s",
2302             (*stream)->psz_url );
2303
2304         return VLC_EGENERIC;
2305     }
2306
2307     if( vlc_stream_directory_Attach( stream, NULL ) )
2308         msg_Dbg( source, "attachment of directory-extractor failed for %s",
2309             (*stream)->psz_url );
2310
2311     MRLSections( extra ? extra : "",
2312         &source->i_title_start, &source->i_title_end,
2313         &source->i_seekpoint_start, &source->i_seekpoint_end );
2314
2315     return VLC_SUCCESS;
2316 }
2317
2318 static demux_t *InputDemuxNew( input_thread_t *p_input, input_source_t *p_source,
2319                                const char *psz_access, const char *psz_demux,
2320                                const char *psz_path, const char *psz_anchor )
2321 {
2322     input_thread_private_t *priv = input_priv(p_input );
2323     demux_t *p_demux = NULL;
2324
2325     /* first, try to create an access demux */
2326     p_demux = demux_NewAdvanced( VLC_OBJECT( p_source ), p_input,
2327                                  psz_access, psz_demux, psz_path,
2328                                  NULL, priv->p_es_out, priv->b_preparsing );
2329     if( p_demux )
2330     {
2331         MRLSections( psz_anchor,
2332             &p_source->i_title_start, &p_source->i_title_end,
2333             &p_source->i_seekpoint_start, &p_source->i_seekpoint_end );
2334
2335         return p_demux;
2336     }
2337
2338     /* not an access-demux: create the underlying access stream */
2339     char *psz_base_mrl;
2340
2341     if( asprintf( &psz_base_mrl, "%s://%s", psz_access, psz_path ) < 0 )
2342         return NULL;
2343
2344     char *psz_filters = var_InheritString( p_source, "stream-filter" );
2345     stream_t* p_stream = stream_AccessNew( VLC_OBJECT( p_source ), p_input,
2346                                            priv->b_preparsing,
2347                                            psz_base_mrl );
2348     FREENULL( psz_base_mrl );
2349
2350     if( p_stream == NULL )
2351         goto error;
2352
2353     /* attach explicit stream filters to stream */
2354     if( psz_filters )
2355         p_stream = stream_FilterChainNew( p_stream, psz_filters );
2356
2357     FREENULL( psz_filters );
2358
2359     /* handle anchors */
2360     if( InputStreamHandleAnchor( p_source, &p_stream, psz_anchor ) )
2361         goto error;
2362
2363     /* attach conditional record stream-filter */
2364     if( var_InheritBool( p_source, "input-record-native" ) )
2365         p_stream = stream_FilterChainNew( p_stream, "record" );
2366
2367     /* create a regular demux with the access stream created */
2368     p_demux = demux_NewAdvanced( VLC_OBJECT( p_source ), p_input,
2369                                  psz_access, psz_demux, psz_path,
2370                                  p_stream, priv->p_es_out,
2371                                  priv->b_preparsing );
2372     if( p_demux )
2373         return p_demux;
2374
2375 error:
2376     free( psz_base_mrl );
2377     free( psz_filters );
2378
2379     if( p_stream )
2380         vlc_stream_Delete( p_stream );
2381
2382     return NULL;
2383 }
2384
2385 /*****************************************************************************
2386  * InputSourceNew:
2387  *****************************************************************************/
2388 static input_source_t *InputSourceNew( input_thread_t *p_input,
2389                                        const char *psz_mrl,
2390                                        const char *psz_forced_demux,
2391                                        bool b_in_can_fail )
2392 {
2393     input_source_t *in = vlc_custom_create( p_input, sizeof( *in ),
2394                                             "input source" );
2395     if( unlikely(in == NULL) )
2396         return NULL;
2397
2398     const char *psz_access, *psz_demux, *psz_path, *psz_anchor = NULL;
2399
2400     assert( psz_mrl );
2401     char *psz_dup = strdup( psz_mrl );
2402     char *psz_demux_var = NULL;
2403
2404     if( psz_dup == NULL )
2405     {
2406         vlc_object_release( in );
2407         return NULL;
2408     }
2409
2410     /* Split uri */
2411     input_SplitMRL( &psz_access, &psz_demux, &psz_path, &psz_anchor, psz_dup );
2412
2413     if( psz_demux == NULL || psz_demux[0] == '\0' )
2414         psz_demux = psz_demux_var = var_InheritString( in, "demux" );
2415
2416     if( psz_forced_demux != NULL )
2417         psz_demux = psz_forced_demux;
2418
2419     if( psz_demux == NULL )
2420         psz_demux = "any";
2421
2422     msg_Dbg( p_input, "`%s' gives access `%s' demux `%s' path `%s'",
2423              psz_mrl, psz_access, psz_demux, psz_path );
2424
2425     if( input_priv(p_input)->master == NULL /* XXX ugly */)
2426     {   /* On master stream only, use input-list */
2427         char *str = var_InheritString( p_input, "input-list" );
2428         if( str != NULL )
2429         {
2430             char *list;
2431
2432             var_Create( p_input, "concat-list", VLC_VAR_STRING );
2433             if( likely(asprintf( &list, "%s://%s,%s", psz_access, psz_path,
2434                                  str ) >= 0) )
2435             {
2436                  var_SetString( p_input, "concat-list", list );
2437                  free( list );
2438             }
2439             free( str );
2440             psz_access = "concat";
2441         }
2442     }
2443
2444     if( strcasecmp( psz_access, "concat" ) )
2445     {   /* Autodetect extra files if none specified */
2446         int count;
2447         char **tab;
2448
2449         TAB_INIT( count, tab );
2450         InputGetExtraFiles( p_input, &count, &tab, &psz_access, psz_path );
2451         if( count > 0 )
2452         {
2453             char *list = NULL;
2454
2455             for( int i = 0; i < count; i++ )
2456             {
2457                 char *str;
2458                 if( asprintf( &str, "%s,%s", list ? list : psz_mrl,
2459                               tab[i] ) < 0 )
2460                     break;
2461
2462                 free( tab[i] );
2463                 free( list );
2464                 list = str;
2465             }
2466
2467             var_Create( p_input, "concat-list", VLC_VAR_STRING );
2468             if( likely(list != NULL) )
2469             {
2470                 var_SetString( p_input, "concat-list", list );
2471                 free( list );
2472             }
2473         }
2474         TAB_CLEAN( count, tab );
2475     }
2476
2477     in->p_demux = InputDemuxNew( p_input, in, psz_access, psz_demux,
2478                                  psz_path, psz_anchor );
2479
2480     free( psz_demux_var );
2481     free( psz_dup );
2482
2483     if( in->p_demux == NULL )
2484     {
2485         if( !b_in_can_fail && !input_Stopped( p_input ) )
2486             vlc_dialog_display_error( p_input, _("Your input can't be opened"),
2487                                       _("VLC is unable to open the MRL '%s'."
2488                                       " Check the log for details."), psz_mrl );
2489         vlc_object_release( in );
2490         return NULL;
2491     }
2492
2493     char *psz_demux_chain = var_GetNonEmptyString(p_input, "demux-filter");
2494     if( psz_demux_chain != NULL ) /* add the chain of demux filters */
2495     {
2496         in->p_demux = demux_FilterChainNew( in->p_demux, psz_demux_chain );
2497         free( psz_demux_chain );
2498
2499         if( in->p_demux == NULL )
2500         {
2501             msg_Err(p_input, "Failed to create demux filter");
2502             vlc_object_release( in );
2503             return NULL;
2504         }
2505     }
2506
2507     /* Get infos from (access_)demux */
2508     bool b_can_seek;
2509     if( demux_Control( in->p_demux, DEMUX_CAN_SEEK, &b_can_seek ) )
2510         b_can_seek = false;
2511     var_SetBool( p_input, "can-seek", b_can_seek );
2512
2513     if( demux_Control( in->p_demux, DEMUX_CAN_CONTROL_PACE,
2514                        &in->b_can_pace_control ) )
2515         in->b_can_pace_control = false;
2516
2517     assert( in->p_demux->pf_demux != NULL || !in->b_can_pace_control );
2518
2519     if( !in->b_can_pace_control )
2520     {
2521         if( demux_Control( in->p_demux, DEMUX_CAN_CONTROL_RATE,
2522                            &in->b_can_rate_control ) )
2523         {
2524             in->b_can_rate_control = false;
2525             in->b_rescale_ts = true;
2526         }
2527         else
2528             in->b_rescale_ts = !in->b_can_rate_control;
2529     }
2530     else
2531     {
2532         in->b_can_rate_control = true;
2533         in->b_rescale_ts = true;
2534     }
2535
2536     demux_Control( in->p_demux, DEMUX_CAN_PAUSE, &in->b_can_pause );
2537
2538     var_SetBool( p_input, "can-pause", in->b_can_pause || !in->b_can_pace_control ); /* XXX temporary because of es_out_timeshift*/
2539     var_SetBool( p_input, "can-rate", !in->b_can_pace_control || in->b_can_rate_control ); /* XXX temporary because of es_out_timeshift*/
2540     var_SetBool( p_input, "can-rewind", !in->b_rescale_ts && !in->b_can_pace_control && in->b_can_rate_control );
2541
2542     /* Set record capabilities */
2543     if( demux_Control( in->p_demux, DEMUX_CAN_RECORD, &in->b_can_stream_record ) )
2544         in->b_can_stream_record = false;
2545 #ifdef ENABLE_SOUT
2546     if( !var_GetBool( p_input, "input-record-native" ) )
2547         in->b_can_stream_record = false;
2548     var_SetBool( p_input, "can-record", true );
2549 #else
2550     var_SetBool( p_input, "can-record", in->b_can_stream_record );
2551 #endif
2552
2553     /* get attachment
2554      * FIXME improve for b_preparsing: move it after GET_META and check psz_arturl */
2555     if( !input_priv(p_input)->b_preparsing )
2556     {
2557         if( demux_Control( in->p_demux, DEMUX_GET_TITLE_INFO,
2558                            &in->title, &in->i_title,
2559                            &in->i_title_offset, &in->i_seekpoint_offset ))
2560         {
2561             TAB_INIT( in->i_title, in->title );
2562         }
2563         else
2564         {
2565             in->b_title_demux = true;
2566         }
2567
2568         int i_attachment;
2569         input_attachment_t **attachment;
2570         if( !demux_Control( in->p_demux, DEMUX_GET_ATTACHMENTS,
2571                              &attachment, &i_attachment ) )
2572         {
2573             vlc_mutex_lock( &input_priv(p_input)->p_item->lock );
2574             AppendAttachment( &input_priv(p_input)->i_attachment, &input_priv(p_input)->attachment, &input_priv(p_input)->attachment_demux,
2575                               i_attachment, attachment, in->p_demux );
2576             vlc_mutex_unlock( &input_priv(p_input)->p_item->lock );
2577         }
2578
2579         demux_Control( in->p_demux, DEMUX_GET_PTS_DELAY, &in->i_pts_delay );
2580         if( in->i_pts_delay > INPUT_PTS_DELAY_MAX )
2581             in->i_pts_delay = INPUT_PTS_DELAY_MAX;
2582         else if( in->i_pts_delay < 0 )
2583             in->i_pts_delay = 0;
2584     }
2585
2586     if( demux_Control( in->p_demux, DEMUX_GET_FPS, &in->f_fps ) )
2587         in->f_fps = 0.f;
2588
2589     if( var_GetInteger( p_input, "clock-synchro" ) != -1 )
2590         in->b_can_pace_control = !var_GetInteger( p_input, "clock-synchro" );
2591
2592     return in;
2593 }
2594
2595 /*****************************************************************************
2596  * InputSourceDestroy:
2597  *****************************************************************************/
2598 static void InputSourceDestroy( input_source_t *in )
2599 {
2600     int i;
2601
2602     if( in->p_demux )
2603         demux_Delete( in->p_demux );
2604
2605     if( in->i_title > 0 )
2606     {
2607         for( i = 0; i < in->i_title; i++ )
2608             vlc_input_title_Delete( in->title[i] );
2609         TAB_CLEAN( in->i_title, in->title );
2610     }
2611
2612     vlc_object_release( in );
2613 }
2614
2615 /*****************************************************************************
2616  * InputSourceMeta:
2617  *****************************************************************************/
2618 static void InputSourceMeta( input_thread_t *p_input,
2619                              input_source_t *p_source, vlc_meta_t *p_meta )
2620 {
2621     demux_t *p_demux = p_source->p_demux;
2622
2623     /* XXX Remember that checking against p_item->p_meta->i_status & ITEM_PREPARSED
2624      * is a bad idea */
2625
2626     bool has_meta = false;
2627
2628     /* Read demux meta */
2629     if( !demux_Control( p_demux, DEMUX_GET_META, p_meta ) )
2630         has_meta = true;
2631
2632     bool has_unsupported;
2633     if( demux_Control( p_demux, DEMUX_HAS_UNSUPPORTED_META, &has_unsupported ) )
2634         has_unsupported = true;
2635
2636     /* If the demux report unsupported meta data, or if we don't have meta data
2637      * try an external "meta reader" */
2638     if( has_meta && !has_unsupported )
2639         return;
2640
2641     demux_meta_t *p_demux_meta =
2642         vlc_custom_create( p_source, sizeof( *p_demux_meta ), "demux meta" );
2643     if( unlikely(p_demux_meta == NULL) )
2644         return;
2645     p_demux_meta->p_item = input_priv(p_input)->p_item;
2646
2647     module_t *p_id3 = module_need( p_demux_meta, "meta reader", NULL, false );
2648     if( p_id3 )
2649     {
2650         if( p_demux_meta->p_meta )
2651         {
2652             vlc_meta_Merge( p_meta, p_demux_meta->p_meta );
2653             vlc_meta_Delete( p_demux_meta->p_meta );
2654         }
2655
2656         if( p_demux_meta->i_attachments > 0 )
2657         {
2658             vlc_mutex_lock( &input_priv(p_input)->p_item->lock );
2659             AppendAttachment( &input_priv(p_input)->i_attachment, &input_priv(p_input)->attachment, &input_priv(p_input)->attachment_demux,
2660                               p_demux_meta->i_attachments, p_demux_meta->attachments, p_demux);
2661             vlc_mutex_unlock( &input_priv(p_input)->p_item->lock );
2662         }
2663         module_unneed( p_demux, p_id3 );
2664     }
2665     vlc_object_release( p_demux_meta );
2666 }
2667
2668
2669 static void SlaveDemux( input_thread_t *p_input )
2670 {
2671     int64_t i_time;
2672     int i;
2673
2674     if( demux_Control( input_priv(p_input)->master->p_demux, DEMUX_GET_TIME, &i_time ) )
2675     {
2676         msg_Err( p_input, "demux doesn't like DEMUX_GET_TIME" );
2677         return;
2678     }
2679
2680     for( i = 0; i < input_priv(p_input)->i_slave; i++ )
2681     {
2682         input_source_t *in = input_priv(p_input)->slave[i];
2683         int i_ret;
2684
2685         if( in->b_eof )
2686             continue;
2687
2688         /* Call demux_Demux until we have read enough data */
2689         if( demux_Control( in->p_demux, DEMUX_SET_NEXT_DEMUX_TIME, i_time ) )
2690         {
2691             for( ;; )
2692             {
2693                 int64_t i_stime;
2694                 if( demux_Control( in->p_demux, DEMUX_GET_TIME, &i_stime ) )
2695                 {
2696                     msg_Err( p_input, "slave[%d] doesn't like "
2697                              "DEMUX_GET_TIME -> EOF", i );
2698                     i_ret = 0;
2699                     break;
2700                 }
2701
2702                 if( i_stime >= i_time )
2703                 {
2704                     i_ret = 1;
2705                     break;
2706                 }
2707
2708                 if( ( i_ret = demux_Demux( in->p_demux ) ) <= 0 )
2709                     break;
2710             }
2711         }
2712         else
2713         {
2714             i_ret = demux_Demux( in->p_demux );
2715         }
2716
2717         if( i_ret <= 0 )
2718         {
2719             msg_Dbg( p_input, "slave %d EOF", i );
2720             in->b_eof = true;
2721         }
2722     }
2723 }
2724
2725 static void SlaveSeek( input_thread_t *p_input )
2726 {
2727     int64_t i_time;
2728     int i;
2729
2730     if( demux_Control( input_priv(p_input)->master->p_demux, DEMUX_GET_TIME, &i_time ) )
2731     {
2732         msg_Err( p_input, "demux doesn't like DEMUX_GET_TIME" );
2733         return;
2734     }
2735
2736     for( i = 0; i < input_priv(p_input)->i_slave; i++ )
2737     {
2738         input_source_t *in = input_priv(p_input)->slave[i];
2739
2740         if( demux_Control( in->p_demux, DEMUX_SET_TIME, i_time, true ) )
2741         {
2742             if( !in->b_eof )
2743                 msg_Err( p_input, "seek failed for slave %d -> EOF", i );
2744             in->b_eof = true;
2745         }
2746         else
2747         {
2748             in->b_eof = false;
2749         }
2750     }
2751 }
2752
2753 /*****************************************************************************
2754  * InputMetaUser:
2755  *****************************************************************************/
2756 static void InputMetaUser( input_thread_t *p_input, vlc_meta_t *p_meta )
2757 {
2758     static const struct { int i_meta; const char *psz_name; } p_list[] = {
2759         { vlc_meta_Title,       "meta-title" },
2760         { vlc_meta_Artist,      "meta-artist" },
2761         { vlc_meta_Genre,       "meta-genre" },
2762         { vlc_meta_Copyright,   "meta-copyright" },
2763         { vlc_meta_Description, "meta-description" },
2764         { vlc_meta_Date,        "meta-date" },
2765         { vlc_meta_URL,         "meta-url" },
2766         { 0, NULL }
2767     };
2768
2769     /* Get meta information from user */
2770     for( int i = 0; p_list[i].psz_name; i++ )
2771     {
2772         char *psz_string = var_GetNonEmptyString( p_input, p_list[i].psz_name );
2773         if( !psz_string )
2774             continue;
2775
2776         EnsureUTF8( psz_string );
2777         vlc_meta_Set( p_meta, p_list[i].i_meta, psz_string );
2778         free( psz_string );
2779     }
2780 }
2781
2782 static void AppendAttachment( int *pi_attachment, input_attachment_t ***ppp_attachment,
2783                               const demux_t ***ppp_attachment_demux,
2784                               int i_new, input_attachment_t **pp_new, const demux_t *p_demux )
2785 {
2786     int i_attachment = *pi_attachment;
2787     int i;
2788
2789     input_attachment_t **pp_att = realloc( *ppp_attachment,
2790                     sizeof(*pp_att) * ( i_attachment + i_new ) );
2791     if( likely(pp_att) )
2792     {
2793         *ppp_attachment = pp_att;
2794         const demux_t **pp_attdmx = realloc( *ppp_attachment_demux,
2795                         sizeof(*pp_attdmx) * ( i_attachment + i_new ) );
2796         if( likely(pp_attdmx) )
2797         {
2798             *ppp_attachment_demux = pp_attdmx;
2799
2800             for( i = 0; i < i_new; i++ )
2801             {
2802                 pp_att[i_attachment] = pp_new[i];
2803                 pp_attdmx[i_attachment++] = p_demux;
2804             }
2805             /* */
2806             *pi_attachment = i_attachment;
2807             free( pp_new );
2808             return;
2809         }
2810     }
2811
2812     /* on alloc errors */
2813     for( i = 0; i < i_new; i++ )
2814         vlc_input_attachment_Delete( pp_new[i] );
2815     free( pp_new );
2816 }
2817
2818 /*****************************************************************************
2819  * InputUpdateMeta: merge p_item meta data with p_meta taking care of
2820  * arturl and locking issue.
2821  *****************************************************************************/
2822 static void InputUpdateMeta( input_thread_t *p_input, demux_t *p_demux )
2823 {
2824     vlc_meta_t *p_meta = vlc_meta_New();
2825     if( unlikely(p_meta == NULL) )
2826         return;
2827
2828     demux_Control( p_demux, DEMUX_GET_META, p_meta );
2829
2830     /* If metadata changed, then the attachments might have changed.
2831        We need to update them in case they contain album art. */
2832     input_attachment_t **attachment;
2833     int i_attachment;
2834
2835     if( !demux_Control( p_demux, DEMUX_GET_ATTACHMENTS,
2836                         &attachment, &i_attachment ) )
2837     {
2838         vlc_mutex_lock( &input_priv(p_input)->p_item->lock );
2839         if( input_priv(p_input)->i_attachment > 0 )
2840         {
2841             int j = 0;
2842             for( int i = 0; i < input_priv(p_input)->i_attachment; i++ )
2843             {
2844                 if( input_priv(p_input)->attachment_demux[i] == p_demux )
2845                     vlc_input_attachment_Delete( input_priv(p_input)->attachment[i] );
2846                 else
2847                 {
2848                     input_priv(p_input)->attachment[j] = input_priv(p_input)->attachment[i];
2849                     input_priv(p_input)->attachment_demux[j] = input_priv(p_input)->attachment_demux[i];
2850                     j++;
2851                 }
2852             }
2853             input_priv(p_input)->i_attachment = j;
2854         }
2855         AppendAttachment( &input_priv(p_input)->i_attachment, &input_priv(p_input)->attachment, &input_priv(p_input)->attachment_demux,
2856                           i_attachment, attachment, p_demux );
2857         vlc_mutex_unlock( &input_priv(p_input)->p_item->lock );
2858     }
2859
2860     es_out_ControlSetMeta( input_priv(p_input)->p_es_out, p_meta );
2861     vlc_meta_Delete( p_meta );
2862 }
2863
2864 /*****************************************************************************
2865  * InputGetExtraFiles
2866  *  Autodetect extra input list
2867  *****************************************************************************/
2868 static void InputGetExtraFilesPattern( input_thread_t *p_input,
2869                                        int *pi_list, char ***pppsz_list,
2870                                        const char *psz_path,
2871                                        const char *psz_match,
2872                                        const char *psz_format,
2873                                        int i_start, int i_stop )
2874 {
2875     int i_list;
2876     char **ppsz_list;
2877     TAB_INIT( i_list, ppsz_list );
2878
2879     char *psz_base = strdup( psz_path );
2880     if( !psz_base )
2881         goto exit;
2882
2883     /* Remove the extension */
2884     char *psz_end = &psz_base[strlen(psz_base)-strlen(psz_match)];
2885     assert( psz_end >= psz_base);
2886     *psz_end = '\0';
2887
2888     /* Try to list files */
2889     for( int i = i_start; i <= i_stop; i++ )
2890     {
2891         char *psz_probe;
2892         if( asprintf( &psz_probe, psz_format, psz_base, i ) < 0 )
2893             break;
2894
2895         char *filepath = get_path( psz_probe );
2896
2897         struct stat st;
2898         if( filepath == NULL ||
2899             vlc_stat( filepath, &st ) || !S_ISREG( st.st_mode ) || !st.st_size )
2900         {
2901             free( filepath );
2902             free( psz_probe );
2903             break;
2904         }
2905
2906         msg_Dbg( p_input, "Detected extra file `%s'", filepath );
2907
2908         char* psz_uri = vlc_path2uri( filepath, NULL );
2909         if( psz_uri )
2910             TAB_APPEND( i_list, ppsz_list, psz_uri );
2911
2912         free( filepath );
2913         free( psz_probe );
2914     }
2915     free( psz_base );
2916 exit:
2917     *pi_list = i_list;
2918     *pppsz_list = ppsz_list;
2919 }
2920
2921 static void InputGetExtraFiles( input_thread_t *p_input,
2922                                 int *pi_list, char ***pppsz_list,
2923                                 const char **ppsz_access, const char *psz_path )
2924 {
2925     static const struct pattern
2926     {
2927         const char *psz_access_force;
2928         const char *psz_match;
2929         const char *psz_format;
2930         int i_start;
2931         int i_stop;
2932     } patterns[] = {
2933         /* XXX the order is important */
2934         { "concat", ".001", "%s.%.3d", 2, 999 },
2935         { NULL, ".part1.rar","%s.part%.1d.rar", 2, 9 },
2936         { NULL, ".part01.rar","%s.part%.2d.rar", 2, 99, },
2937         { NULL, ".part001.rar", "%s.part%.3d.rar", 2, 999 },
2938         { NULL, ".rar", "%s.r%.2d", 0, 99 },
2939     };
2940
2941     TAB_INIT( *pi_list, *pppsz_list );
2942
2943     if( ( **ppsz_access && strcmp( *ppsz_access, "file" ) ) || !psz_path )
2944         return;
2945
2946     const size_t i_path = strlen(psz_path);
2947
2948     for( size_t i = 0; i < ARRAY_SIZE( patterns ); ++i )
2949     {
2950         const struct pattern* pat = &patterns[i];
2951         const size_t i_ext = strlen( pat->psz_match );
2952
2953         if( i_path < i_ext )
2954             continue;
2955
2956         if( !strcmp( &psz_path[i_path-i_ext], pat->psz_match ) )
2957         {
2958             InputGetExtraFilesPattern( p_input, pi_list, pppsz_list, psz_path,
2959                 pat->psz_match, pat->psz_format, pat->i_start, pat->i_stop );
2960
2961             if( *pi_list > 0 && pat->psz_access_force )
2962                 *ppsz_access = pat->psz_access_force;
2963             return;
2964         }
2965     }
2966 }
2967
2968 /* */
2969 static void input_ChangeState( input_thread_t *p_input, int i_state )
2970 {
2971     if( input_priv(p_input)->i_state == i_state )
2972         return;
2973
2974     input_priv(p_input)->i_state = i_state;
2975     if( i_state == ERROR_S )
2976         input_item_SetErrorWhenReading( input_priv(p_input)->p_item, true );
2977     input_SendEventState( p_input, i_state );
2978 }
2979
2980
2981 /*****************************************************************************
2982  * MRLSplit: parse the access, demux and url part of the
2983  *           Media Resource Locator.
2984  *****************************************************************************/
2985 void input_SplitMRL( const char **access, const char **demux,
2986                      const char **path, const char **anchor, char *buf )
2987 {
2988     char *p;
2989
2990     /* Separate <path> from <access>[/<demux>]:// */
2991     p = strstr( buf, "://" );
2992     if( p != NULL )
2993     {
2994         *p = '\0';
2995         p += 3; /* skips "://" */
2996         *path = p;
2997
2998         /* Remove HTML anchor if present (not supported).
2999          * The hash symbol itself should be URI-encoded. */
3000         p = strchr( p, '#' );
3001         if( p != NULL )
3002         {
3003             *(p++) = '\0';
3004             *anchor = p;
3005         }
3006         else
3007             *anchor = "";
3008     }
3009     else
3010     {
3011 #ifndef NDEBUG
3012         fprintf( stderr, "%s(\"%s\") probably not a valid URI!\n", __func__,
3013                  buf );
3014 #endif
3015         /* Note: this is a valid non const pointer to "": */
3016         *path = buf + strlen( buf );
3017     }
3018
3019     /* Separate access from demux */
3020     p = strchr( buf, '/' );
3021     if( p != NULL )
3022     {
3023         *(p++) = '\0';
3024         if( p[0] == '$' )
3025             p++;
3026         *demux = p;
3027     }
3028     else
3029         *demux = "";
3030
3031     /* We really don't want module name substitution here! */
3032     p = buf;
3033     if( p[0] == '$' )
3034         p++;
3035     *access = p;
3036 }
3037
3038 static const char *MRLSeekPoint( const char *str, int *title, int *chapter )
3039 {
3040     char *end;
3041     unsigned long u;
3042
3043     /* Look for the title */
3044     u = strtoul( str, &end, 0 );
3045     *title = (str == end || u > (unsigned long)INT_MAX) ? -1 : (int)u;
3046     str = end;
3047
3048     /* Look for the chapter */
3049     if( *str == ':' )
3050     {
3051         str++;
3052         u = strtoul( str, &end, 0 );
3053         *chapter = (str == end || u > (unsigned long)INT_MAX) ? -1 : (int)u;
3054         str = end;
3055     }
3056     else
3057         *chapter = -1;
3058
3059     return str;
3060 }
3061
3062
3063 /*****************************************************************************
3064  * MRLSections: parse title and seekpoint info from the Media Resource Locator.
3065  *
3066  * Syntax:
3067  * [url][@[title_start][:chapter_start][-[title_end][:chapter_end]]]
3068  *****************************************************************************/
3069 static void MRLSections( const char *p,
3070                          int *pi_title_start, int *pi_title_end,
3071                          int *pi_chapter_start, int *pi_chapter_end )
3072 {
3073     *pi_title_start = *pi_title_end = *pi_chapter_start = *pi_chapter_end = -1;
3074
3075     int title_start, chapter_start, title_end, chapter_end;
3076
3077     if( !p )
3078         return;
3079
3080     if( *p != '-' )
3081         p = MRLSeekPoint( p, &title_start, &chapter_start );
3082     else
3083         title_start = chapter_start = -1;
3084
3085     if( *p == '-' )
3086         p = MRLSeekPoint( p + 1, &title_end, &chapter_end );
3087     else
3088         title_end = chapter_end = -1;
3089
3090     if( *p ) /* syntax error */
3091         return;
3092
3093     *pi_title_start = title_start;
3094     *pi_title_end = title_end;
3095     *pi_chapter_start = chapter_start;
3096     *pi_chapter_end = chapter_end;
3097 }
3098
3099 static int input_SlaveSourceAdd( input_thread_t *p_input,
3100                                  enum slave_type i_type, const char *psz_uri,
3101                                  unsigned i_flags )
3102 {
3103     vlc_value_t count;
3104     const char *psz_es;
3105     const char *psz_forced_demux;
3106     const bool b_can_fail = i_flags & SLAVE_ADD_CANFAIL;
3107     const bool b_forced = i_flags & SLAVE_ADD_FORCED;
3108     const bool b_set_time = i_flags & SLAVE_ADD_SET_TIME;
3109
3110     switch( i_type )
3111     {
3112     case SLAVE_TYPE_SPU:
3113         psz_es = "spu-es";
3114         psz_forced_demux = "subtitle";
3115         break;
3116     case SLAVE_TYPE_AUDIO:
3117         psz_es = "audio-es";
3118         psz_forced_demux = NULL;
3119         break;
3120     default:
3121         vlc_assert_unreachable();
3122     }
3123
3124     if( b_forced )
3125         var_Change( p_input, psz_es, VLC_VAR_CHOICESCOUNT, &count, NULL );
3126
3127     msg_Dbg( p_input, "loading %s slave: %s (forced: %d)", psz_es, psz_uri,
3128              b_forced );
3129
3130     input_source_t *p_source = InputSourceNew( p_input, psz_uri,
3131                                                psz_forced_demux, b_can_fail );
3132     if( p_source == NULL )
3133     {
3134         msg_Warn( p_input, "failed to add %s as slave", psz_uri );
3135         return VLC_EGENERIC;
3136     }
3137
3138     if( i_type == SLAVE_TYPE_AUDIO )
3139     {
3140         if( b_set_time )
3141         {
3142             int64_t i_time;
3143
3144             /* Set position */
3145             if( demux_Control( input_priv(p_input)->master->p_demux,
3146                                DEMUX_GET_TIME, &i_time ) )
3147             {
3148                 msg_Err( p_input, "demux doesn't like DEMUX_GET_TIME" );
3149                 InputSourceDestroy( p_source );
3150                 return VLC_EGENERIC;
3151             }
3152
3153             if( demux_Control( p_source->p_demux,
3154                                DEMUX_SET_TIME, i_time, true ) )
3155             {
3156                 msg_Err( p_input, "seek failed for new slave" );
3157                 InputSourceDestroy( p_source );
3158                 return VLC_EGENERIC;
3159             }
3160         }
3161
3162         /* Get meta (access and demux) */
3163         InputUpdateMeta( p_input, p_source->p_demux );
3164     }
3165
3166     TAB_APPEND( input_priv(p_input)->i_slave, input_priv(p_input)->slave, p_source );
3167
3168     if( !b_forced )
3169         return VLC_SUCCESS;
3170
3171     /* Select the ES */
3172     vlc_value_t list;
3173
3174     if( var_Change( p_input, psz_es, VLC_VAR_GETCHOICES, &list, NULL ) )
3175         return VLC_SUCCESS;
3176
3177     if( count.i_int == 0 )
3178         count.i_int++;
3179     /* if it was first one, there is disable too */
3180
3181     if( count.i_int < list.p_list->i_count )
3182     {
3183         const int i_id = list.p_list->p_values[count.i_int].i_int;
3184
3185         es_out_Control( input_priv(p_input)->p_es_out_display, ES_OUT_SET_ES_DEFAULT_BY_ID, i_id );
3186         es_out_Control( input_priv(p_input)->p_es_out_display, ES_OUT_SET_ES_BY_ID, i_id );
3187     }
3188     var_FreeList( &list, NULL );
3189
3190     return VLC_SUCCESS;
3191 }
3192
3193 static char *input_SubtitleFile2Uri( input_thread_t *p_input,
3194                                      const char *psz_subtitle )
3195 {
3196     /* if we are provided a subtitle.sub file,
3197      * see if we don't have a subtitle.idx and use it instead */
3198     char *psz_idxpath = NULL;
3199     char *psz_extension = strrchr( psz_subtitle, '.');
3200     if( psz_extension && strcmp( psz_extension, ".sub" ) == 0 )
3201     {
3202         psz_idxpath = strdup( psz_subtitle );
3203         if( psz_idxpath )
3204         {
3205             struct stat st;
3206
3207             psz_extension = psz_extension - psz_subtitle + psz_idxpath;
3208             strcpy( psz_extension, ".idx" );
3209
3210             if( !vlc_stat( psz_idxpath, &st ) && S_ISREG( st.st_mode ) )
3211             {
3212                 msg_Dbg( p_input, "using %s as subtitle file instead of %s",
3213                          psz_idxpath, psz_subtitle );
3214                 psz_subtitle = psz_idxpath;
3215             }
3216         }
3217     }
3218
3219     char *psz_uri = vlc_path2uri( psz_subtitle, NULL );
3220     free( psz_idxpath );
3221     return psz_uri;
3222 }
3223
3224 /*****************************************************************************
3225  * Statistics
3226  *****************************************************************************/
3227 void input_UpdateStatistic( input_thread_t *p_input,
3228                             input_statistic_t i_type, int i_delta )
3229 {
3230     assert( input_priv(p_input)->i_state != INIT_S );
3231
3232     vlc_mutex_lock( &input_priv(p_input)->counters.counters_lock);
3233     switch( i_type )
3234     {
3235 #define I(c) stats_Update( input_priv(p_input)->counters.c, i_delta, NULL )
3236     case INPUT_STATISTIC_DECODED_VIDEO:
3237         I(p_decoded_video);
3238         break;
3239     case INPUT_STATISTIC_DECODED_AUDIO:
3240         I(p_decoded_audio);
3241         break;
3242     case INPUT_STATISTIC_DECODED_SUBTITLE:
3243         I(p_decoded_sub);
3244         break;
3245     case INPUT_STATISTIC_SENT_PACKET:
3246         I(p_sout_sent_packets);
3247         break;
3248 #undef I
3249     case INPUT_STATISTIC_SENT_BYTE:
3250     {
3251         uint64_t bytes;
3252
3253         stats_Update( input_priv(p_input)->counters.p_sout_sent_bytes, i_delta, &bytes );
3254         stats_Update( input_priv(p_input)->counters.p_sout_send_bitrate, bytes, NULL );
3255         break;
3256     }
3257     default:
3258         msg_Err( p_input, "Invalid statistic type %d (internal error)", i_type );
3259         break;
3260     }
3261     vlc_mutex_unlock( &input_priv(p_input)->counters.counters_lock);
3262 }
3263
3264 /**/
3265 /* TODO FIXME nearly the same logic that snapshot code */
3266 char *input_CreateFilename(input_thread_t *input, const char *dir,
3267                            const char *filenamefmt, const char *ext)
3268 {
3269     char *path;
3270     char *filename = str_format(input, filenamefmt);
3271     if (unlikely(filename == NULL))
3272         return NULL;
3273
3274     filename_sanitize(filename);
3275
3276     if (((ext != NULL)
3277             ? asprintf(&path, "%s"DIR_SEP"%s.%s", dir, filename, ext)
3278             : asprintf(&path, "%s"DIR_SEP"%s", dir, filename)) < 0)
3279         path = NULL;
3280
3281     free(filename);
3282     return path;
3283 }