]> git.sesse.net Git - vlc/blob - src/input/es_out.c
Updated codec informations on decoder output change.
[vlc] / src / input / es_out.c
1 /*****************************************************************************
2  * es_out.c: Es Out handler for input.
3  *****************************************************************************
4  * Copyright (C) 2003-2004 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8  *          Jean-Paul Saman <jpsaman #_at_# m2x dot nl>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 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 General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, 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 <stdio.h>
33 #include <assert.h>
34 #include <vlc_common.h>
35
36 #include <vlc_input.h>
37 #include <vlc_es_out.h>
38 #include <vlc_block.h>
39 #include <vlc_aout.h>
40
41 #include "input_internal.h"
42 #include "clock.h"
43 #include "decoder.h"
44 #include "es_out.h"
45 #include "event.h"
46
47 #include "../stream_output/stream_output.h"
48
49 #include <vlc_iso_lang.h>
50 /* FIXME we should find a better way than including that */
51 #include "../text/iso-639_def.h"
52
53 /*****************************************************************************
54  * Local prototypes
55  *****************************************************************************/
56 typedef struct
57 {
58     /* Program ID */
59     int i_id;
60
61     /* Number of es for this pgrm */
62     int i_es;
63
64     bool b_selected;
65
66     /* Clock for this program */
67     input_clock_t *p_clock;
68
69     char    *psz_name;
70     char    *psz_now_playing;
71     char    *psz_publisher;
72
73     vlc_epg_t *p_epg;
74 } es_out_pgrm_t;
75
76 struct es_out_id_t
77 {
78     /* ES ID */
79     int       i_id;
80     es_out_pgrm_t *p_pgrm;
81
82     /* Channel in the track type */
83     int         i_channel;
84     es_format_t fmt;
85     char        *psz_language;
86     char        *psz_language_code;
87
88     decoder_t   *p_dec;
89     decoder_t   *p_dec_record;
90
91     /* Fields for Video with CC */
92     bool  pb_cc_present[4];
93     es_out_id_t  *pp_cc_es[4];
94
95     /* Field for CC track from a master video */
96     es_out_id_t *p_master;
97
98     /* ID for the meta data */
99     int         i_meta_id;
100 };
101
102 struct es_out_sys_t
103 {
104     input_thread_t *p_input;
105
106     /* */
107     vlc_mutex_t   lock;
108
109     /* all programs */
110     int           i_pgrm;
111     es_out_pgrm_t **pgrm;
112     es_out_pgrm_t **pp_selected_pgrm; /* --programs */
113     es_out_pgrm_t *p_pgrm;  /* Master program */
114
115     /* all es */
116     int         i_id;
117     int         i_es;
118     es_out_id_t **es;
119
120     /* mode gestion */
121     bool  b_active;
122     int         i_mode;
123
124     /* es count */
125     int         i_audio;
126     int         i_video;
127     int         i_sub;
128
129     /* es to select */
130     int         i_audio_last, i_audio_id;
131     int         i_sub_last, i_sub_id;
132     int         i_default_sub_id;   /* As specified in container; if applicable */
133     char        **ppsz_audio_language;
134     char        **ppsz_sub_language;
135
136     /* current main es */
137     es_out_id_t *p_es_audio;
138     es_out_id_t *p_es_video;
139     es_out_id_t *p_es_sub;
140
141     /* delay */
142     int64_t i_audio_delay;
143     int64_t i_spu_delay;
144
145     /* Rate used for clock */
146     int         i_rate;
147
148     /* */
149     bool        b_paused;
150
151     /* Current preroll */
152     mtime_t     i_preroll_end;
153
154     /* Used for buffering */
155     bool        b_buffering;
156     mtime_t     i_buffering_extra_initial;
157     mtime_t     i_buffering_extra_stream;
158     mtime_t     i_buffering_extra_system;
159
160     /* Record */
161     sout_instance_t *p_sout_record;
162 };
163
164 static es_out_id_t *EsOutAdd    ( es_out_t *, const es_format_t * );
165 static int          EsOutSend   ( es_out_t *, es_out_id_t *, block_t * );
166 static void         EsOutDel    ( es_out_t *, es_out_id_t * );
167 static int          EsOutControl( es_out_t *, int i_query, va_list );
168 static void         EsOutDelete ( es_out_t * );
169
170 static void         EsOutSelect( es_out_t *, es_out_id_t *es, bool b_force );
171 static void         EsOutUpdateInfo( es_out_t *, es_out_id_t *es, const es_format_t * );
172 static int          EsOutSetRecord(  es_out_t *, bool b_record );
173
174 static bool EsIsSelected( es_out_id_t *es );
175 static void EsSelect( es_out_t *out, es_out_id_t *es );
176 static void EsUnselect( es_out_t *out, es_out_id_t *es, bool b_update );
177 static void EsOutDecoderChangeDelay( es_out_t *out, es_out_id_t *p_es );
178 static void EsOutDecodersChangePause( es_out_t *out, bool b_paused, mtime_t i_date );
179 static void EsOutProgramChangePause( es_out_t *out, bool b_paused, mtime_t i_date );
180 static void EsOutProgramsChangeRate( es_out_t *out );
181 static void EsOutDecodersStopBuffering( es_out_t *out, bool b_forced );
182 static char *LanguageGetName( const char *psz_code );
183 static char *LanguageGetCode( const char *psz_lang );
184 static char **LanguageSplit( const char *psz_langs );
185 static int LanguageArrayIndex( char **ppsz_langs, char *psz_lang );
186
187 static char *EsOutProgramGetMetaName( es_out_pgrm_t *p_pgrm );
188
189 static const vlc_fourcc_t EsOutFourccClosedCaptions[4] = {
190     VLC_FOURCC('c', 'c', '1', ' '),
191     VLC_FOURCC('c', 'c', '2', ' '),
192     VLC_FOURCC('c', 'c', '3', ' '),
193     VLC_FOURCC('c', 'c', '4', ' '),
194 };
195 static inline int EsOutGetClosedCaptionsChannel( vlc_fourcc_t fcc )
196 {
197     int i;
198     for( i = 0; i < 4; i++ )
199     {
200         if( fcc == EsOutFourccClosedCaptions[i] )
201             return i;
202     }
203     return -1;
204 }
205
206
207 /*****************************************************************************
208  * input_EsOutNew:
209  *****************************************************************************/
210 es_out_t *input_EsOutNew( input_thread_t *p_input, int i_rate )
211 {
212     vlc_value_t  val;
213     int i;
214
215     es_out_t     *out = malloc( sizeof( *out ) );
216     if( !out )
217         return NULL;
218
219     es_out_sys_t *p_sys = malloc( sizeof( *p_sys ) );
220     if( !p_sys )
221     {
222         free( out );
223         return NULL;
224     }
225
226     out->pf_add     = EsOutAdd;
227     out->pf_send    = EsOutSend;
228     out->pf_del     = EsOutDel;
229     out->pf_control = EsOutControl;
230     out->pf_destroy = EsOutDelete;
231     out->p_sys      = p_sys;
232     out->b_sout     = p_input->p->p_sout != NULL;
233
234
235     vlc_mutex_init_recursive( &p_sys->lock );
236     p_sys->p_input = p_input;
237
238     p_sys->b_active = false;
239     p_sys->i_mode   = ES_OUT_MODE_AUTO;
240
241
242     TAB_INIT( p_sys->i_pgrm, p_sys->pgrm );
243     p_sys->p_pgrm   = NULL;
244
245     p_sys->i_id    = 0;
246
247     TAB_INIT( p_sys->i_es, p_sys->es );
248
249     p_sys->i_audio = 0;
250     p_sys->i_video = 0;
251     p_sys->i_sub   = 0;
252
253     /* */
254     var_Get( p_input, "audio-track", &val );
255     p_sys->i_audio_last = val.i_int;
256
257     var_Get( p_input, "sub-track", &val );
258     p_sys->i_sub_last = val.i_int;
259
260     p_sys->i_default_sub_id   = -1;
261
262     if( !p_input->b_preparsing )
263     {
264         var_Get( p_input, "audio-language", &val );
265         p_sys->ppsz_audio_language = LanguageSplit(val.psz_string);
266         if( p_sys->ppsz_audio_language )
267         {
268             for( i = 0; p_sys->ppsz_audio_language[i]; i++ )
269                 msg_Dbg( p_input, "selected audio language[%d] %s",
270                          i, p_sys->ppsz_audio_language[i] );
271         }
272         free( val.psz_string );
273
274         var_Get( p_input, "sub-language", &val );
275         p_sys->ppsz_sub_language = LanguageSplit(val.psz_string);
276         if( p_sys->ppsz_sub_language )
277         {
278             for( i = 0; p_sys->ppsz_sub_language[i]; i++ )
279                 msg_Dbg( p_input, "selected subtitle language[%d] %s",
280                          i, p_sys->ppsz_sub_language[i] );
281         }
282         free( val.psz_string );
283     }
284     else
285     {
286         p_sys->ppsz_sub_language = NULL;
287         p_sys->ppsz_audio_language = NULL;
288     }
289
290     var_Get( p_input, "audio-track-id", &val );
291     p_sys->i_audio_id = val.i_int;
292
293     var_Get( p_input, "sub-track-id", &val );
294     p_sys->i_sub_id = val.i_int;
295
296     p_sys->p_es_audio = NULL;
297     p_sys->p_es_video = NULL;
298     p_sys->p_es_sub   = NULL;
299
300     p_sys->i_audio_delay= 0;
301     p_sys->i_spu_delay  = 0;
302
303     p_sys->b_paused = false;
304
305     p_sys->i_rate = i_rate;
306
307     p_sys->b_buffering = true;
308     p_sys->i_buffering_extra_initial = 0;
309     p_sys->i_buffering_extra_stream = 0;
310     p_sys->i_buffering_extra_system = 0;
311     p_sys->i_preroll_end = -1;
312
313     p_sys->p_sout_record = NULL;
314
315     return out;
316 }
317
318 /*****************************************************************************
319  *
320  *****************************************************************************/
321 static void EsOutDelete( es_out_t *out )
322 {
323     es_out_sys_t *p_sys = out->p_sys;
324     int i;
325
326     if( p_sys->p_sout_record )
327         EsOutSetRecord( out, false );
328
329     for( i = 0; i < p_sys->i_es; i++ )
330     {
331         if( p_sys->es[i]->p_dec )
332             input_DecoderDelete( p_sys->es[i]->p_dec );
333
334         free( p_sys->es[i]->psz_language );
335         free( p_sys->es[i]->psz_language_code );
336         es_format_Clean( &p_sys->es[i]->fmt );
337
338         free( p_sys->es[i] );
339     }
340     if( p_sys->ppsz_audio_language )
341     {
342         for( i = 0; p_sys->ppsz_audio_language[i]; i++ )
343             free( p_sys->ppsz_audio_language[i] );
344         free( p_sys->ppsz_audio_language );
345     }
346     if( p_sys->ppsz_sub_language )
347     {
348         for( i = 0; p_sys->ppsz_sub_language[i]; i++ )
349             free( p_sys->ppsz_sub_language[i] );
350         free( p_sys->ppsz_sub_language );
351     }
352     free( p_sys->es );
353
354     /* FIXME duplicate work EsOutProgramDel (but we cannot use it) add a EsOutProgramClean ? */
355     for( i = 0; i < p_sys->i_pgrm; i++ )
356     {
357         es_out_pgrm_t *p_pgrm = p_sys->pgrm[i];
358         input_clock_Delete( p_pgrm->p_clock );
359         free( p_pgrm->psz_now_playing );
360         free( p_pgrm->psz_publisher );
361         free( p_pgrm->psz_name );
362         if( p_pgrm->p_epg )
363             vlc_epg_Delete( p_pgrm->p_epg );
364
365         free( p_pgrm );
366     }
367     TAB_CLEAN( p_sys->i_pgrm, p_sys->pgrm );
368     vlc_mutex_destroy( &p_sys->lock );
369
370     free( p_sys );
371     free( out );
372 }
373
374 static mtime_t EsOutGetWakeup( es_out_t *out )
375 {
376     es_out_sys_t   *p_sys = out->p_sys;
377     input_thread_t *p_input = p_sys->p_input;
378
379     if( !p_sys->p_pgrm )
380         return 0;
381
382     /* We do not have a wake up date if the input cannot have its speed
383      * controlled or sout is imposing its own or while buffering
384      *
385      * FIXME for !p_input->b_can_pace_control a wkeup time is still needed to avoid too strong buffering */
386     if( !p_input->b_can_pace_control ||
387         p_input->p->b_out_pace_control ||
388         p_sys->b_buffering )
389         return 0;
390
391     return input_clock_GetWakeup( p_sys->p_pgrm->p_clock );
392 }
393
394 static es_out_id_t *EsOutGetFromID( es_out_t *out, int i_id )
395 {
396     int i;
397     if( i_id < 0 )
398     {
399         /* Special HACK, -i_id is the cat of the stream */
400         return (es_out_id_t*)((uint8_t*)NULL-i_id);
401     }
402
403     for( i = 0; i < out->p_sys->i_es; i++ )
404     {
405         if( out->p_sys->es[i]->i_id == i_id )
406             return out->p_sys->es[i];
407     }
408     return NULL;
409 }
410
411 static bool EsOutDecodersIsEmpty( es_out_t *out )
412 {
413     es_out_sys_t      *p_sys = out->p_sys;
414     int i;
415
416     if( p_sys->b_buffering && p_sys->p_pgrm )
417     {
418         EsOutDecodersStopBuffering( out, true );
419         if( p_sys->b_buffering )
420             return true;
421     }
422
423     for( i = 0; i < p_sys->i_es; i++ )
424     {
425         es_out_id_t *es = p_sys->es[i];
426
427         if( es->p_dec && !input_DecoderIsEmpty( es->p_dec ) )
428             return false;
429         if( es->p_dec_record && !input_DecoderIsEmpty( es->p_dec_record ) )
430             return false;
431     }
432     return true;
433 }
434
435 static void EsOutSetDelay( es_out_t *out, int i_cat, int64_t i_delay )
436 {
437     es_out_sys_t *p_sys = out->p_sys;
438
439     if( i_cat == AUDIO_ES )
440         p_sys->i_audio_delay = i_delay;
441     else if( i_cat == SPU_ES )
442         p_sys->i_spu_delay = i_delay;
443
444     for( int i = 0; i < p_sys->i_es; i++ )
445         EsOutDecoderChangeDelay( out, p_sys->es[i] );
446 }
447
448 static int EsOutSetRecord(  es_out_t *out, bool b_record )
449 {
450     es_out_sys_t   *p_sys = out->p_sys;
451     input_thread_t *p_input = p_sys->p_input;
452
453     assert( ( b_record && !p_sys->p_sout_record ) || ( !b_record && p_sys->p_sout_record ) );
454
455     if( b_record )
456     {
457         char *psz_path = var_CreateGetString( p_input, "input-record-path" );
458         if( !psz_path || *psz_path == '\0' )
459         {
460             free( psz_path );
461             psz_path = strdup( config_GetHomeDir() );
462         }
463
464         char *psz_sout = NULL;  // TODO conf
465
466         if( !psz_sout && psz_path )
467         {
468             char *psz_file = input_CreateFilename( VLC_OBJECT(p_input), psz_path, INPUT_RECORD_PREFIX, NULL );
469             if( psz_file )
470             {
471                 if( asprintf( &psz_sout, "#record{dst-prefix='%s'}", psz_file ) < 0 )
472                     psz_sout = NULL;
473                 free( psz_file );
474             }
475         }
476         free( psz_path );
477
478         if( !psz_sout )
479             return VLC_EGENERIC;
480
481 #ifdef ENABLE_SOUT
482         p_sys->p_sout_record = sout_NewInstance( p_input, psz_sout );
483 #endif
484         free( psz_sout );
485
486         if( !p_sys->p_sout_record )
487             return VLC_EGENERIC;
488
489         for( int i = 0; i < p_sys->i_es; i++ )
490         {
491             es_out_id_t *p_es = p_sys->es[i];
492
493             if( !p_es->p_dec || p_es->p_master )
494                 continue;
495
496             p_es->p_dec_record = input_DecoderNew( p_input, &p_es->fmt, p_es->p_pgrm->p_clock, p_sys->p_sout_record );
497             if( p_es->p_dec_record && p_sys->b_buffering )
498                 input_DecoderStartBuffering( p_es->p_dec_record );
499         }
500     }
501     else
502     {
503         for( int i = 0; i < p_sys->i_es; i++ )
504         {
505             es_out_id_t *p_es = p_sys->es[i];
506
507             if( !p_es->p_dec_record )
508                 continue;
509
510             input_DecoderDelete( p_es->p_dec_record );
511             p_es->p_dec_record = NULL;
512         }
513 #ifdef ENABLE_SOUT
514         sout_DeleteInstance( p_sys->p_sout_record );
515 #endif
516         p_sys->p_sout_record = NULL;
517     }
518
519     return VLC_SUCCESS;
520 }
521 static void EsOutChangePause( es_out_t *out, bool b_paused, mtime_t i_date )
522 {
523     es_out_sys_t *p_sys = out->p_sys;
524
525     /* XXX the order is important */
526     if( b_paused )
527     {
528         EsOutDecodersChangePause( out, true, i_date );
529         EsOutProgramChangePause( out, true, i_date );
530     }
531     else
532     {
533         if( p_sys->i_buffering_extra_initial > 0 )
534         {
535             mtime_t i_stream_start;
536             mtime_t i_system_start;
537             mtime_t i_stream_duration;
538             mtime_t i_system_duration;
539             int i_ret;
540             i_ret = input_clock_GetState( p_sys->p_pgrm->p_clock,
541                                           &i_stream_start, &i_system_start,
542                                           &i_stream_duration, &i_system_duration );
543             if( !i_ret )
544             {
545                 /* FIXME pcr != exactly what wanted */
546                 const mtime_t i_used = /*(i_stream_duration - p_sys->p_input->i_pts_delay)*/ p_sys->i_buffering_extra_system - p_sys->i_buffering_extra_initial;
547                 i_date -= i_used;
548             }
549             p_sys->i_buffering_extra_initial = 0;
550             p_sys->i_buffering_extra_stream = 0;
551             p_sys->i_buffering_extra_system = 0;
552         }
553         EsOutProgramChangePause( out, false, i_date );
554         EsOutDecodersChangePause( out, false, i_date );
555
556         EsOutProgramsChangeRate( out );
557     }
558     p_sys->b_paused = b_paused;
559 }
560
561 static void EsOutChangeRate( es_out_t *out, int i_rate )
562 {
563     es_out_sys_t      *p_sys = out->p_sys;
564
565     p_sys->i_rate = i_rate;
566
567     if( !p_sys->b_paused )
568         EsOutProgramsChangeRate( out );
569 }
570
571 static void EsOutChangePosition( es_out_t *out )
572 {
573     es_out_sys_t      *p_sys = out->p_sys;
574
575     for( int i = 0; i < p_sys->i_es; i++ )
576     {
577         es_out_id_t *p_es = p_sys->es[i];
578
579         if( !p_es->p_dec )
580             continue;
581
582         input_DecoderStartBuffering( p_es->p_dec );
583
584         if( p_es->p_dec_record )
585             input_DecoderStartBuffering( p_es->p_dec );
586     }
587
588     for( int i = 0; i < p_sys->i_pgrm; i++ )
589         input_clock_Reset( p_sys->pgrm[i]->p_clock );
590
591     p_sys->b_buffering = true;
592     p_sys->i_buffering_extra_initial = 0;
593     p_sys->i_buffering_extra_stream = 0;
594     p_sys->i_buffering_extra_system = 0;
595     p_sys->i_preroll_end = -1;
596 }
597
598
599
600 static void EsOutDecodersStopBuffering( es_out_t *out, bool b_forced )
601 {
602     es_out_sys_t *p_sys = out->p_sys;
603     int i_ret;
604
605     mtime_t i_stream_start;
606     mtime_t i_system_start;
607     mtime_t i_stream_duration;
608     mtime_t i_system_duration;
609     i_ret = input_clock_GetState( p_sys->p_pgrm->p_clock,
610                                   &i_stream_start, &i_system_start,
611                                   &i_stream_duration, &i_system_duration );
612     assert( !i_ret || b_forced );
613     if( i_ret )
614         return;
615
616     mtime_t i_preroll_duration = 0;
617     if( p_sys->i_preroll_end >= 0 )
618         i_preroll_duration = __MAX( p_sys->i_preroll_end - i_stream_start, 0 );
619
620     const mtime_t i_buffering_duration = p_sys->p_input->i_pts_delay +
621                                          i_preroll_duration +
622                                          p_sys->i_buffering_extra_stream;
623
624     if( i_stream_duration <= i_buffering_duration && !b_forced )
625     {
626         msg_Dbg( p_sys->p_input, "Buffering %d%%",
627                  (int)(100 * i_stream_duration / i_buffering_duration ) );
628         return;
629     }
630
631     msg_Dbg( p_sys->p_input, "Stream buffering done (%d ms in %d ms)",
632               (int)(i_stream_duration/1000), (int)(i_system_duration/1000) );
633     p_sys->b_buffering = false;
634     p_sys->i_preroll_end = -1;
635
636     if( p_sys->i_buffering_extra_initial > 0 )
637     {
638         /* FIXME wrong ? */
639         return;
640     }
641
642     const mtime_t i_decoder_buffering_start = mdate();
643     for( int i = 0; i < p_sys->i_es; i++ )
644     {
645         es_out_id_t *p_es = p_sys->es[i];
646
647         if( !p_es->p_dec )
648             continue;
649         input_DecoderWaitBuffering( p_es->p_dec );
650         if( p_es->p_dec_record )
651             input_DecoderWaitBuffering( p_es->p_dec_record );
652     }
653
654     msg_Dbg( p_sys->p_input, "Decoder buffering done in %d ms",
655               (int)(mdate() - i_decoder_buffering_start)/1000 );
656
657     const mtime_t i_ts_delay = 10*1000 + /* FIXME CLEANUP thread wake up time*/
658                                mdate();
659     //msg_Dbg( p_sys->p_input, "==> %lld", i_ts_delay - p_sys->p_input->i_pts_delay );
660     input_clock_ChangeSystemOrigin( p_sys->p_pgrm->p_clock, i_ts_delay - i_buffering_duration );
661
662     for( int i = 0; i < p_sys->i_es; i++ )
663     {
664         es_out_id_t *p_es = p_sys->es[i];
665
666         if( !p_es->p_dec )
667             continue;
668
669         input_DecoderStopBuffering( p_es->p_dec );
670         if( p_es->p_dec_record )
671             input_DecoderStopBuffering( p_es->p_dec );
672     }
673 }
674 static void EsOutDecodersChangePause( es_out_t *out, bool b_paused, mtime_t i_date )
675 {
676     es_out_sys_t *p_sys = out->p_sys;
677
678     /* Pause decoders first */
679     for( int i = 0; i < p_sys->i_es; i++ )
680     {
681         es_out_id_t *es = p_sys->es[i];
682
683         if( es->p_dec )
684         {
685             input_DecoderChangePause( es->p_dec, b_paused, i_date );
686             if( es->p_dec_record )
687                 input_DecoderChangePause( es->p_dec_record, b_paused, i_date );
688         }
689     }
690 }
691 static void EsOutProgramChangePause( es_out_t *out, bool b_paused, mtime_t i_date )
692 {
693     es_out_sys_t *p_sys = out->p_sys;
694
695     for( int i = 0; i < p_sys->i_pgrm; i++ )
696         input_clock_ChangePause( p_sys->pgrm[i]->p_clock, b_paused, i_date );
697 }
698
699 static void EsOutDecoderChangeDelay( es_out_t *out, es_out_id_t *p_es )
700 {
701     es_out_sys_t *p_sys = out->p_sys;
702
703     mtime_t i_delay = 0;
704     if( p_es->fmt.i_cat == AUDIO_ES )
705         i_delay = p_sys->i_audio_delay;
706     else if( p_es->fmt.i_cat == SPU_ES )
707         i_delay = p_sys->i_spu_delay;
708
709     if( i_delay != 0 )
710     {
711         if( p_es->p_dec )
712             input_DecoderChangeDelay( p_es->p_dec, i_delay );
713         if( p_es->p_dec_record )
714             input_DecoderChangeDelay( p_es->p_dec_record, i_delay );
715     }
716 }
717 static void EsOutProgramsChangeRate( es_out_t *out )
718 {
719     es_out_sys_t      *p_sys = out->p_sys;
720
721     for( int i = 0; i < p_sys->i_pgrm; i++ )
722         input_clock_ChangeRate( p_sys->pgrm[i]->p_clock, p_sys->i_rate );
723 }
724
725 static void EsOutFrameNext( es_out_t *out )
726 {
727     es_out_sys_t *p_sys = out->p_sys;
728     es_out_id_t *p_es_video = NULL;
729
730     if( p_sys->b_buffering )
731     {
732         msg_Warn( p_sys->p_input, "buffering, ignoring 'frame next'" );
733         return;
734     }
735
736     assert( p_sys->b_paused );
737
738     for( int i = 0; i < p_sys->i_es; i++ )
739     {
740         es_out_id_t *p_es = p_sys->es[i];
741
742         if( p_es->fmt.i_cat == VIDEO_ES && p_es->p_dec )
743         {
744             p_es_video = p_es;
745             break;
746         }
747     }
748
749     if( !p_es_video )
750     {
751         msg_Warn( p_sys->p_input, "No video track selected, ignoring 'frame next'" );
752         return;
753     }
754
755     mtime_t i_duration;
756     input_DecoderFrameNext( p_es_video->p_dec, &i_duration );
757
758     msg_Dbg( out->p_sys->p_input, "EsOutFrameNext consummed %d ms", (int)(i_duration/1000) );
759
760     if( i_duration <= 0 )
761         i_duration = 40*1000;
762
763     /* FIXME it is not a clean way ? */
764     if( p_sys->i_buffering_extra_initial <= 0 )
765     {
766         mtime_t i_stream_start;
767         mtime_t i_system_start;
768         mtime_t i_stream_duration;
769         mtime_t i_system_duration;
770         int i_ret;
771
772         i_ret = input_clock_GetState( p_sys->p_pgrm->p_clock,
773                                       &i_stream_start, &i_system_start,
774                                       &i_stream_duration, &i_system_duration );
775         if( i_ret )
776             return;
777
778         p_sys->i_buffering_extra_initial = 1 + i_stream_duration - p_sys->p_input->i_pts_delay; /* FIXME < 0 ? */
779         p_sys->i_buffering_extra_system =
780         p_sys->i_buffering_extra_stream = p_sys->i_buffering_extra_initial;
781     }
782
783     const int i_rate = input_clock_GetRate( p_sys->p_pgrm->p_clock );
784
785     p_sys->b_buffering = true;
786     p_sys->i_buffering_extra_system += i_duration;
787     p_sys->i_buffering_extra_stream = p_sys->i_buffering_extra_initial +
788                                       ( p_sys->i_buffering_extra_system - p_sys->i_buffering_extra_initial ) *
789                                                 INPUT_RATE_DEFAULT / i_rate;
790
791     p_sys->i_preroll_end = -1;
792 }
793
794
795
796 static void EsOutESVarUpdateGeneric( es_out_t *out, int i_id, es_format_t *fmt, const char *psz_language,
797                                      bool b_delete )
798 {
799     es_out_sys_t      *p_sys = out->p_sys;
800     input_thread_t    *p_input = p_sys->p_input;
801     const  bool b_teletext = fmt->i_cat == SPU_ES && fmt->i_codec == VLC_FOURCC( 't', 'e', 'l', 'x' );
802     vlc_value_t       val, text;
803
804     if( b_delete )
805     {
806         /* TODO it should probably be a list */
807         if( b_teletext )
808             input_SendEventTeletext( p_sys->p_input, -1 );
809
810         input_SendEventEsDel( p_input, SPU_ES, i_id );
811         return;
812     }
813
814     /* Get the number of ES already added */
815     const char *psz_var;
816     if( fmt->i_cat == AUDIO_ES )
817         psz_var = "audio-es";
818     else if( fmt->i_cat == VIDEO_ES )
819         psz_var = "video-es";
820     else
821         psz_var = "spu-es";
822
823     var_Change( p_input, psz_var, VLC_VAR_CHOICESCOUNT, &val, NULL );
824     if( val.i_int == 0 )
825     {
826         vlc_value_t val2;
827
828         /* First one, we need to add the "Disable" choice */
829         val2.i_int = -1; text.psz_string = _("Disable");
830         var_Change( p_input, psz_var, VLC_VAR_ADDCHOICE, &val2, &text );
831         val.i_int++;
832     }
833
834     /* Take care of the ES description */
835     if( fmt->psz_description && *fmt->psz_description )
836     {
837         if( psz_language && *psz_language )
838         {
839             text.psz_string = malloc( strlen( fmt->psz_description) +
840                                       strlen( psz_language ) + 10 );
841             sprintf( text.psz_string, "%s - [%s]", fmt->psz_description,
842                                                    psz_language );
843         }
844         else text.psz_string = strdup( fmt->psz_description );
845     }
846     else
847     {
848         if( psz_language && *psz_language )
849         {
850             if( asprintf( &text.psz_string, "%s %i - [%s]", _( "Track" ), val.i_int, psz_language ) == -1 )
851                 text.psz_string = NULL;
852         }
853         else
854         {
855             if( asprintf( &text.psz_string, "%s %i", _( "Track" ), val.i_int ) == -1 )
856                 text.psz_string = NULL;
857         }
858     }
859
860     input_SendEventEsAdd( p_input, fmt->i_cat, i_id, text.psz_string );
861
862     free( text.psz_string );
863
864     if( b_teletext )
865     {
866         /* TODO it should probably be a list */
867         if( var_GetInteger( p_sys->p_input, "teletext-es" ) < 0 )
868             input_SendEventTeletext( p_sys->p_input, i_id );
869     }
870 }
871
872 static void EsOutESVarUpdate( es_out_t *out, es_out_id_t *es,
873                               bool b_delete )
874 {
875     EsOutESVarUpdateGeneric( out, es->i_id, &es->fmt, es->psz_language, b_delete );
876 }
877
878 /* EsOutProgramSelect:
879  *  Select a program and update the object variable
880  */
881 static void EsOutProgramSelect( es_out_t *out, es_out_pgrm_t *p_pgrm )
882 {
883     es_out_sys_t      *p_sys = out->p_sys;
884     input_thread_t    *p_input = p_sys->p_input;
885     int               i;
886
887     if( p_sys->p_pgrm == p_pgrm )
888         return; /* Nothing to do */
889
890     if( p_sys->p_pgrm )
891     {
892         es_out_pgrm_t *old = p_sys->p_pgrm;
893         msg_Dbg( p_input, "unselecting program id=%d", old->i_id );
894
895         for( i = 0; i < p_sys->i_es; i++ )
896         {
897             if( p_sys->es[i]->p_pgrm == old && EsIsSelected( p_sys->es[i] ) &&
898                 p_sys->i_mode != ES_OUT_MODE_ALL )
899                 EsUnselect( out, p_sys->es[i], true );
900         }
901
902         p_sys->p_es_audio = NULL;
903         p_sys->p_es_sub = NULL;
904         p_sys->p_es_video = NULL;
905     }
906
907     msg_Dbg( p_input, "selecting program id=%d", p_pgrm->i_id );
908
909     /* Mark it selected */
910     p_pgrm->b_selected = true;
911
912     /* Switch master stream */
913     p_sys->p_pgrm = p_pgrm;
914
915     /* Update "program" */
916     input_SendEventProgramSelect( p_input, p_pgrm->i_id );
917
918     /* Update "es-*" */
919     input_SendEventEsDel( p_input, AUDIO_ES, -1 );
920     input_SendEventEsDel( p_input, VIDEO_ES, -1 );
921     input_SendEventEsDel( p_input, SPU_ES, -1 );
922
923     /* TODO event */
924     var_SetInteger( p_input, "teletext-es", -1 );
925
926     for( i = 0; i < p_sys->i_es; i++ )
927     {
928         if( p_sys->es[i]->p_pgrm == p_sys->p_pgrm )
929             EsOutESVarUpdate( out, p_sys->es[i], false );
930         EsOutSelect( out, p_sys->es[i], false );
931     }
932
933     /* Update now playing */
934     input_item_SetNowPlaying( p_input->p->input.p_item,
935                               p_pgrm->psz_now_playing );
936     input_item_SetPublisher( p_input->p->input.p_item,
937                              p_pgrm->psz_publisher );
938
939     input_SendEventMeta( p_input );
940 }
941
942 /* EsOutAddProgram:
943  *  Add a program
944  */
945 static es_out_pgrm_t *EsOutProgramAdd( es_out_t *out, int i_group )
946 {
947     es_out_sys_t      *p_sys = out->p_sys;
948     input_thread_t    *p_input = p_sys->p_input;
949
950     es_out_pgrm_t *p_pgrm = malloc( sizeof( es_out_pgrm_t ) );
951     if( !p_pgrm )
952         return NULL;
953
954     /* Init */
955     p_pgrm->i_id = i_group;
956     p_pgrm->i_es = 0;
957     p_pgrm->b_selected = false;
958     p_pgrm->psz_name = NULL;
959     p_pgrm->psz_now_playing = NULL;
960     p_pgrm->psz_publisher = NULL;
961     p_pgrm->p_epg = NULL;
962     p_pgrm->p_clock = input_clock_New( p_input->p->input.i_cr_average, p_sys->i_rate );
963     if( !p_pgrm->p_clock )
964     {
965         free( p_pgrm );
966         return NULL;
967     }
968
969     /* Append it */
970     TAB_APPEND( p_sys->i_pgrm, p_sys->pgrm, p_pgrm );
971
972     /* Update "program" variable */
973     input_SendEventProgramAdd( p_input, i_group, NULL );
974
975     if( i_group == var_GetInteger( p_input, "program" ) )
976         EsOutProgramSelect( out, p_pgrm );
977
978     return p_pgrm;
979 }
980
981 /* EsOutDelProgram:
982  *  Delete a program
983  */
984 static int EsOutProgramDel( es_out_t *out, int i_group )
985 {
986     es_out_sys_t      *p_sys = out->p_sys;
987     input_thread_t    *p_input = p_sys->p_input;
988     es_out_pgrm_t     *p_pgrm = NULL;
989     int               i;
990
991     for( i = 0; i < p_sys->i_pgrm; i++ )
992     {
993         if( p_sys->pgrm[i]->i_id == i_group )
994         {
995             p_pgrm = p_sys->pgrm[i];
996             break;
997         }
998     }
999
1000     if( p_pgrm == NULL )
1001         return VLC_EGENERIC;
1002
1003     if( p_pgrm->i_es )
1004     {
1005         msg_Dbg( p_input, "can't delete program %d which still has %i ES",
1006                  i_group, p_pgrm->i_es );
1007         return VLC_EGENERIC;
1008     }
1009
1010     TAB_REMOVE( p_sys->i_pgrm, p_sys->pgrm, p_pgrm );
1011
1012     /* If program is selected we need to unselect it */
1013     if( p_sys->p_pgrm == p_pgrm )
1014         p_sys->p_pgrm = NULL;
1015
1016     input_clock_Delete( p_pgrm->p_clock );
1017
1018     free( p_pgrm->psz_name );
1019     free( p_pgrm->psz_now_playing );
1020     free( p_pgrm->psz_publisher );
1021     if( p_pgrm->p_epg )
1022         vlc_epg_Delete( p_pgrm->p_epg );
1023     free( p_pgrm );
1024
1025     /* Update "program" variable */
1026     input_SendEventProgramDel( p_input, i_group );
1027
1028     return VLC_SUCCESS;
1029 }
1030
1031 /* EsOutProgramMeta:
1032  */
1033 static char *EsOutProgramGetMetaName( es_out_pgrm_t *p_pgrm )
1034 {
1035     char *psz = NULL;
1036     if( p_pgrm->psz_name )
1037     {
1038         if( asprintf( &psz, _("%s [%s %d]"), p_pgrm->psz_name, _("Program"), p_pgrm->i_id ) == -1 )
1039             return NULL;
1040     }
1041     else
1042     {
1043         if( asprintf( &psz, "%s %d", _("Program"), p_pgrm->i_id ) == -1 )
1044             return NULL;
1045     }
1046     return psz;
1047 }
1048
1049 static void EsOutProgramMeta( es_out_t *out, int i_group, vlc_meta_t *p_meta )
1050 {
1051     es_out_sys_t      *p_sys = out->p_sys;
1052     es_out_pgrm_t     *p_pgrm = NULL;
1053     input_thread_t    *p_input = p_sys->p_input;
1054     char              *psz_cat;
1055     const char        *psz_title = NULL;
1056     const char        *psz_provider = NULL;
1057     int i;
1058
1059     msg_Dbg( p_input, "EsOutProgramMeta: number=%d", i_group );
1060
1061     /* Check against empty meta data (empty for what we handle) */
1062     if( !vlc_meta_Get( p_meta, vlc_meta_Title) &&
1063         !vlc_meta_Get( p_meta, vlc_meta_NowPlaying) &&
1064         !vlc_meta_Get( p_meta, vlc_meta_Publisher) &&
1065         vlc_dictionary_keys_count( &p_meta->extra_tags ) <= 0 )
1066     {
1067         return;
1068     }
1069     /* Find program */
1070     for( i = 0; i < p_sys->i_pgrm; i++ )
1071     {
1072         if( p_sys->pgrm[i]->i_id == i_group )
1073         {
1074             p_pgrm = p_sys->pgrm[i];
1075             break;
1076         }
1077     }
1078     if( p_pgrm == NULL )
1079         p_pgrm = EsOutProgramAdd( out, i_group );   /* Create it */
1080
1081     /* */
1082     psz_title = vlc_meta_Get( p_meta, vlc_meta_Title);
1083     psz_provider = vlc_meta_Get( p_meta, vlc_meta_Publisher);
1084
1085     /* Update the description text of the program */
1086     if( psz_title && *psz_title )
1087     {
1088         if( !p_pgrm->psz_name || strcmp( p_pgrm->psz_name, psz_title ) )
1089         {
1090             char *psz_cat = EsOutProgramGetMetaName( p_pgrm );
1091
1092             /* Remove old entries */
1093             input_Control( p_input, INPUT_DEL_INFO, psz_cat, NULL );
1094             /* TODO update epg name */
1095             free( psz_cat );
1096         }
1097         free( p_pgrm->psz_name );
1098         p_pgrm->psz_name = strdup( psz_title );
1099
1100         char *psz_text;
1101         if( psz_provider && *psz_provider )
1102         {
1103             if( asprintf( &psz_text, "%s [%s]", psz_title, psz_provider ) < 0 )
1104                 psz_text = NULL;
1105         }
1106         else
1107         {
1108             psz_text = strdup( psz_title );
1109         }
1110
1111         /* ugly but it works */
1112         if( psz_text )
1113         {
1114             input_SendEventProgramDel( p_input, i_group );
1115             input_SendEventProgramAdd( p_input, i_group, psz_text );
1116
1117             free( psz_text );
1118         }
1119     }
1120
1121     psz_cat = EsOutProgramGetMetaName( p_pgrm );
1122     if( psz_provider )
1123     {
1124         if( p_sys->p_pgrm == p_pgrm )
1125         {
1126             input_item_SetPublisher( p_input->p->input.p_item, psz_provider );
1127             input_SendEventMeta( p_input );
1128         }
1129         input_Control( p_input, INPUT_ADD_INFO, psz_cat, input_MetaTypeToLocalizedString(vlc_meta_Publisher), psz_provider );
1130     }
1131     char ** ppsz_all_keys = vlc_dictionary_all_keys( &p_meta->extra_tags );
1132     for( i = 0; ppsz_all_keys[i]; i++ )
1133     {
1134         input_Control( p_input, INPUT_ADD_INFO, psz_cat, _(ppsz_all_keys[i]),
1135                        vlc_dictionary_value_for_key( &p_meta->extra_tags, ppsz_all_keys[i] ) );
1136         free( ppsz_all_keys[i] );
1137     }
1138     free( ppsz_all_keys );
1139
1140     free( psz_cat );
1141 }
1142
1143 static void vlc_epg_Merge( vlc_epg_t *p_dst, const vlc_epg_t *p_src )
1144 {
1145     int i;
1146
1147     /* Add new event */
1148     for( i = 0; i < p_src->i_event; i++ )
1149     {
1150         vlc_epg_event_t *p_evt = p_src->pp_event[i];
1151         bool b_add = true;
1152         int j;
1153
1154         for( j = 0; j < p_dst->i_event; j++ )
1155         {
1156             if( p_dst->pp_event[j]->i_start == p_evt->i_start && p_dst->pp_event[j]->i_duration == p_evt->i_duration )
1157             {
1158                 b_add = false;
1159                 break;
1160             }
1161             if( p_dst->pp_event[j]->i_start > p_evt->i_start )
1162                 break;
1163         }
1164         if( b_add )
1165         {
1166             vlc_epg_event_t *p_copy = malloc( sizeof(vlc_epg_event_t) );
1167             if( !p_copy )
1168                 break;
1169             memset( p_copy, 0, sizeof(vlc_epg_event_t) );
1170             p_copy->i_start = p_evt->i_start;
1171             p_copy->i_duration = p_evt->i_duration;
1172             p_copy->psz_name = p_evt->psz_name ? strdup( p_evt->psz_name ) : NULL;
1173             p_copy->psz_short_description = p_evt->psz_short_description ? strdup( p_evt->psz_short_description ) : NULL;
1174             p_copy->psz_description = p_evt->psz_description ? strdup( p_evt->psz_description ) : NULL;
1175             TAB_INSERT( p_dst->i_event, p_dst->pp_event, p_copy, j );
1176         }
1177     }
1178     /* Update current */
1179     vlc_epg_SetCurrent( p_dst, p_src->p_current ? p_src->p_current->i_start : -1 );
1180
1181     /* Keep only 1 old event  */
1182     if( p_dst->p_current )
1183     {
1184         while( p_dst->i_event > 1 && p_dst->pp_event[0] != p_dst->p_current && p_dst->pp_event[1] != p_dst->p_current )
1185             TAB_REMOVE( p_dst->i_event, p_dst->pp_event, p_dst->pp_event[0] );
1186     }
1187 }
1188
1189 static void EsOutProgramEpg( es_out_t *out, int i_group, vlc_epg_t *p_epg )
1190 {
1191     es_out_sys_t      *p_sys = out->p_sys;
1192     input_thread_t    *p_input = p_sys->p_input;
1193     es_out_pgrm_t     *p_pgrm = NULL;
1194     char *psz_cat;
1195     int i;
1196
1197     /* Find program */
1198     for( i = 0; i < p_sys->i_pgrm; i++ )
1199     {
1200         if( p_sys->pgrm[i]->i_id == i_group )
1201         {
1202             p_pgrm = p_sys->pgrm[i];
1203             break;
1204         }
1205     }
1206     if( p_pgrm == NULL )
1207         p_pgrm = EsOutProgramAdd( out, i_group );   /* Create it */
1208
1209     /* Merge EPG */
1210     if( !p_pgrm->p_epg )
1211         p_pgrm->p_epg = vlc_epg_New( p_pgrm->psz_name );
1212     vlc_epg_Merge( p_pgrm->p_epg, p_epg );
1213
1214     /* Update info */
1215     psz_cat = EsOutProgramGetMetaName( p_pgrm );
1216 #ifdef HAVE_LOCALTIME_R
1217     char *psz_epg;
1218     if( asprintf( &psz_epg, "EPG %s", psz_cat ) == -1 )
1219         psz_epg = NULL;
1220     input_Control( p_input, INPUT_DEL_INFO, psz_epg, NULL );
1221     msg_Dbg( p_input, "EsOutProgramEpg: number=%d name=%s", i_group, p_pgrm->p_epg->psz_name );
1222     for( i = 0; i < p_pgrm->p_epg->i_event; i++ )
1223     {
1224         const vlc_epg_event_t *p_evt = p_pgrm->p_epg->pp_event[i];
1225         time_t t_start = (time_t)p_evt->i_start;
1226         struct tm tm_start;
1227         char psz_start[128];
1228
1229         localtime_r( &t_start, &tm_start );
1230
1231         snprintf( psz_start, sizeof(psz_start), "%2.2d:%2.2d:%2.2d", tm_start.tm_hour, tm_start.tm_min, tm_start.tm_sec );
1232         if( p_evt->psz_short_description || p_evt->psz_description )
1233             input_Control( p_input, INPUT_ADD_INFO, psz_epg, psz_start, "%s (%2.2d:%2.2d) - %s",
1234                            p_evt->psz_name,
1235                            p_evt->i_duration/60/60, (p_evt->i_duration/60)%60,
1236                            p_evt->psz_short_description ? p_evt->psz_short_description : p_evt->psz_description );
1237         else
1238             input_Control( p_input, INPUT_ADD_INFO, psz_epg, psz_start, "%s (%2.2d:%2.2d)",
1239                            p_evt->psz_name,
1240                            p_evt->i_duration/60/60, (p_evt->i_duration/60)%60 );
1241     }
1242     free( psz_epg );
1243 #endif
1244     /* Update now playing */
1245     free( p_pgrm->psz_now_playing );
1246     p_pgrm->psz_now_playing = NULL;
1247     if( p_epg->p_current && p_epg->p_current->psz_name && *p_epg->p_current->psz_name )
1248         p_pgrm->psz_now_playing = strdup( p_epg->p_current->psz_name );
1249
1250     if( p_pgrm == p_sys->p_pgrm )
1251     {
1252         input_item_SetNowPlaying( p_input->p->input.p_item, p_pgrm->psz_now_playing );
1253         input_SendEventMeta( p_input );
1254     }
1255
1256     if( p_pgrm->psz_now_playing )
1257     {
1258         input_Control( p_input, INPUT_ADD_INFO, psz_cat,
1259             input_MetaTypeToLocalizedString(vlc_meta_NowPlaying),
1260             p_pgrm->psz_now_playing );
1261     }
1262     else
1263     {
1264         input_Control( p_input, INPUT_DEL_INFO, psz_cat,
1265             input_MetaTypeToLocalizedString(vlc_meta_NowPlaying) );
1266     }
1267
1268     free( psz_cat );
1269 }
1270
1271 /* EsOutAdd:
1272  *  Add an es_out
1273  */
1274 static es_out_id_t *EsOutAdd( es_out_t *out, const es_format_t *fmt )
1275 {
1276     es_out_sys_t      *p_sys = out->p_sys;
1277     input_thread_t    *p_input = p_sys->p_input;
1278
1279     if( fmt->i_group < 0 )
1280     {
1281         msg_Err( p_input, "invalid group number" );
1282         return NULL;
1283     }
1284
1285     es_out_id_t       *es = malloc( sizeof( *es ) );
1286     es_out_pgrm_t     *p_pgrm = NULL;
1287     int i;
1288
1289     if( !es )
1290         return NULL;
1291
1292     vlc_mutex_lock( &p_sys->lock );
1293
1294     /* Search the program */
1295     for( i = 0; i < p_sys->i_pgrm; i++ )
1296     {
1297         if( fmt->i_group == p_sys->pgrm[i]->i_id )
1298         {
1299             p_pgrm = p_sys->pgrm[i];
1300             break;
1301         }
1302     }
1303     if( p_pgrm == NULL )
1304     {
1305         /* Create a new one */
1306         p_pgrm = EsOutProgramAdd( out, fmt->i_group );
1307     }
1308
1309     /* Increase ref count for program */
1310     p_pgrm->i_es++;
1311
1312     /* Set up ES */
1313     es->p_pgrm = p_pgrm;
1314     es_format_Copy( &es->fmt, fmt );
1315     if( es->fmt.i_id < 0 )
1316         es->fmt.i_id = out->p_sys->i_id;
1317     es->i_id = es->fmt.i_id;
1318     es->i_meta_id = out->p_sys->i_id;
1319
1320     switch( es->fmt.i_cat )
1321     {
1322     case AUDIO_ES:
1323     {
1324         audio_replay_gain_t rg;
1325
1326         es->i_channel = p_sys->i_audio;
1327
1328         memset( &rg, 0, sizeof(rg) );
1329         vlc_mutex_lock( &p_input->p->input.p_item->lock );
1330         vlc_audio_replay_gain_MergeFromMeta( &rg, p_input->p->input.p_item->p_meta );
1331         vlc_mutex_unlock( &p_input->p->input.p_item->lock );
1332
1333         for( i = 0; i < AUDIO_REPLAY_GAIN_MAX; i++ )
1334         {
1335             if( !es->fmt.audio_replay_gain.pb_peak[i] )
1336             {
1337                 es->fmt.audio_replay_gain.pb_peak[i] = rg.pb_peak[i];
1338                 es->fmt.audio_replay_gain.pf_peak[i] = rg.pf_peak[i];
1339             }
1340             if( !es->fmt.audio_replay_gain.pb_gain[i] )
1341             {
1342                 es->fmt.audio_replay_gain.pb_gain[i] = rg.pb_gain[i];
1343                 es->fmt.audio_replay_gain.pf_gain[i] = rg.pf_gain[i];
1344             }
1345         }
1346         break;
1347     }
1348
1349     case VIDEO_ES:
1350         es->i_channel = p_sys->i_video;
1351         if( es->fmt.video.i_frame_rate && es->fmt.video.i_frame_rate_base )
1352             vlc_ureduce( &es->fmt.video.i_frame_rate,
1353                          &es->fmt.video.i_frame_rate_base,
1354                          es->fmt.video.i_frame_rate,
1355                          es->fmt.video.i_frame_rate_base, 0 );
1356         break;
1357
1358     case SPU_ES:
1359         es->i_channel = p_sys->i_sub;
1360         break;
1361
1362     default:
1363         es->i_channel = 0;
1364         break;
1365     }
1366     es->psz_language = LanguageGetName( es->fmt.psz_language ); /* remember so we only need to do it once */
1367     es->psz_language_code = LanguageGetCode( es->fmt.psz_language );
1368     es->p_dec = NULL;
1369     es->p_dec_record = NULL;
1370     for( i = 0; i < 4; i++ )
1371         es->pb_cc_present[i] = false;
1372     es->p_master = NULL;
1373
1374     if( es->p_pgrm == p_sys->p_pgrm )
1375         EsOutESVarUpdate( out, es, false );
1376
1377     /* Select it if needed */
1378     EsOutSelect( out, es, false );
1379
1380
1381     TAB_APPEND( out->p_sys->i_es, out->p_sys->es, es );
1382     p_sys->i_id++;  /* always incremented */
1383     switch( es->fmt.i_cat )
1384     {
1385         case AUDIO_ES:
1386             p_sys->i_audio++;
1387             break;
1388         case SPU_ES:
1389             p_sys->i_sub++;
1390             break;
1391         case VIDEO_ES:
1392             p_sys->i_video++;
1393             break;
1394     }
1395
1396     EsOutUpdateInfo( out, es, &es->fmt );
1397
1398     vlc_mutex_unlock( &p_sys->lock );
1399
1400     return es;
1401 }
1402
1403 static bool EsIsSelected( es_out_id_t *es )
1404 {
1405     if( es->p_master )
1406     {
1407         bool b_decode = false;
1408         if( es->p_master->p_dec )
1409         {
1410             int i_channel = EsOutGetClosedCaptionsChannel( es->fmt.i_codec );
1411             if( i_channel != -1 )
1412                 input_DecoderGetCcState( es->p_master->p_dec, &b_decode, i_channel );
1413         }
1414         return b_decode;
1415     }
1416     else
1417     {
1418         return es->p_dec != NULL;
1419     }
1420 }
1421 static void EsCreateDecoder( es_out_t *out, es_out_id_t *p_es )
1422 {
1423     es_out_sys_t   *p_sys = out->p_sys;
1424     input_thread_t *p_input = p_sys->p_input;
1425
1426     p_es->p_dec = input_DecoderNew( p_input, &p_es->fmt, p_es->p_pgrm->p_clock, p_input->p->p_sout );
1427     if( p_es->p_dec )
1428     {
1429         if( p_sys->b_buffering )
1430             input_DecoderStartBuffering( p_es->p_dec );
1431
1432         if( !p_es->p_master && p_sys->p_sout_record )
1433         {
1434             p_es->p_dec_record = input_DecoderNew( p_input, &p_es->fmt, p_es->p_pgrm->p_clock, p_sys->p_sout_record );
1435             if( p_es->p_dec_record && p_sys->b_buffering )
1436                 input_DecoderStartBuffering( p_es->p_dec_record );
1437         }
1438     }
1439
1440     EsOutDecoderChangeDelay( out, p_es );
1441 }
1442 static void EsDestroyDecoder( es_out_t *out, es_out_id_t *p_es )
1443 {
1444     VLC_UNUSED(out);
1445
1446     if( !p_es->p_dec )
1447         return;
1448
1449     input_DecoderDelete( p_es->p_dec );
1450     p_es->p_dec = NULL;
1451
1452     if( p_es->p_dec_record )
1453     {
1454         input_DecoderDelete( p_es->p_dec_record );
1455         p_es->p_dec_record = NULL;
1456     }
1457 }
1458
1459 static void EsSelect( es_out_t *out, es_out_id_t *es )
1460 {
1461     es_out_sys_t   *p_sys = out->p_sys;
1462     input_thread_t *p_input = p_sys->p_input;
1463     vlc_value_t    val;
1464
1465     if( EsIsSelected( es ) )
1466     {
1467         msg_Warn( p_input, "ES 0x%x is already selected", es->i_id );
1468         return;
1469     }
1470
1471     if( es->p_master )
1472     {
1473         int i_channel;
1474         if( !es->p_master->p_dec )
1475             return;
1476
1477         i_channel = EsOutGetClosedCaptionsChannel( es->fmt.i_codec );
1478         if( i_channel == -1 || input_DecoderSetCcState( es->p_master->p_dec, true, i_channel ) )
1479             return;
1480     }
1481     else
1482     {
1483         if( es->fmt.i_cat == VIDEO_ES || es->fmt.i_cat == SPU_ES )
1484         {
1485             if( !var_GetBool( p_input, out->b_sout ? "sout-video" : "video" ) )
1486             {
1487                 msg_Dbg( p_input, "video is disabled, not selecting ES 0x%x",
1488                          es->i_id );
1489                 return;
1490             }
1491         }
1492         else if( es->fmt.i_cat == AUDIO_ES )
1493         {
1494             var_Get( p_input, "audio", &val );
1495             if( !var_GetBool( p_input, out->b_sout ? "sout-audio" : "audio" ) )
1496             {
1497                 msg_Dbg( p_input, "audio is disabled, not selecting ES 0x%x",
1498                          es->i_id );
1499                 return;
1500             }
1501         }
1502         if( es->fmt.i_cat == SPU_ES )
1503         {
1504             var_Get( p_input, "spu", &val );
1505             if( !var_GetBool( p_input, out->b_sout ? "sout-spu" : "spu" ) )
1506             {
1507                 msg_Dbg( p_input, "spu is disabled, not selecting ES 0x%x",
1508                          es->i_id );
1509                 return;
1510             }
1511         }
1512
1513         EsCreateDecoder( out, es );
1514
1515         if( es->p_dec == NULL || es->p_pgrm != p_sys->p_pgrm )
1516             return;
1517     }
1518
1519     /* Mark it as selected */
1520     input_SendEventEsSelect( p_input, es->fmt.i_cat, es->i_id );
1521 }
1522
1523 static void EsUnselect( es_out_t *out, es_out_id_t *es, bool b_update )
1524 {
1525     es_out_sys_t   *p_sys = out->p_sys;
1526     input_thread_t *p_input = p_sys->p_input;
1527
1528     if( !EsIsSelected( es ) )
1529     {
1530         msg_Warn( p_input, "ES 0x%x is already unselected", es->i_id );
1531         return;
1532     }
1533
1534     if( es->p_master )
1535     {
1536         if( es->p_master->p_dec )
1537         {
1538             int i_channel = EsOutGetClosedCaptionsChannel( es->fmt.i_codec );
1539             if( i_channel != -1 )
1540                 input_DecoderSetCcState( es->p_master->p_dec, false, i_channel );
1541         }
1542     }
1543     else
1544     {
1545         const int i_spu_id = var_GetInteger( p_input, "spu-es");
1546         int i;
1547         for( i = 0; i < 4; i++ )
1548         {
1549             if( !es->pb_cc_present[i] || !es->pp_cc_es[i] )
1550                 continue;
1551
1552             if( i_spu_id == es->pp_cc_es[i]->i_id )
1553             {
1554                 /* Force unselection of the CC */
1555                 input_SendEventEsSelect( p_input, SPU_ES, -1 );
1556             }
1557             EsOutDel( out, es->pp_cc_es[i] );
1558
1559             es->pb_cc_present[i] = false;
1560         }
1561         EsDestroyDecoder( out, es );
1562     }
1563
1564     if( !b_update )
1565         return;
1566
1567     /* Update var */
1568     if( es->p_dec == NULL )
1569         return;
1570
1571     /* Mark it as unselected */
1572     input_SendEventEsSelect( p_input, es->fmt.i_cat, -1 );
1573 }
1574
1575 /**
1576  * Select an ES given the current mode
1577  * XXX: you need to take a the lock before (stream.stream_lock)
1578  *
1579  * \param out The es_out structure
1580  * \param es es_out_id structure
1581  * \param b_force ...
1582  * \return nothing
1583  */
1584 static void EsOutSelect( es_out_t *out, es_out_id_t *es, bool b_force )
1585 {
1586     es_out_sys_t      *p_sys = out->p_sys;
1587
1588     int i_cat = es->fmt.i_cat;
1589
1590     if( !p_sys->b_active ||
1591         ( !b_force && es->fmt.i_priority < 0 ) )
1592     {
1593         return;
1594     }
1595
1596     if( p_sys->i_mode == ES_OUT_MODE_ALL || b_force )
1597     {
1598         if( !EsIsSelected( es ) )
1599             EsSelect( out, es );
1600     }
1601     else if( p_sys->i_mode == ES_OUT_MODE_PARTIAL )
1602     {
1603         vlc_value_t val;
1604         int i;
1605         var_Get( p_sys->p_input, "programs", &val );
1606         for ( i = 0; i < val.p_list->i_count; i++ )
1607         {
1608             if ( val.p_list->p_values[i].i_int == es->p_pgrm->i_id || b_force )
1609             {
1610                 if( !EsIsSelected( es ) )
1611                     EsSelect( out, es );
1612                 break;
1613             }
1614         }
1615         var_Change( p_sys->p_input, "programs", VLC_VAR_FREELIST, &val, NULL );
1616     }
1617     else if( p_sys->i_mode == ES_OUT_MODE_AUTO )
1618     {
1619         int i_wanted  = -1;
1620
1621         if( es->p_pgrm != p_sys->p_pgrm )
1622             return;
1623
1624         if( i_cat == AUDIO_ES )
1625         {
1626             int idx1 = LanguageArrayIndex( p_sys->ppsz_audio_language,
1627                                      es->psz_language_code );
1628
1629             if( p_sys->p_es_audio &&
1630                 p_sys->p_es_audio->fmt.i_priority >= es->fmt.i_priority )
1631             {
1632                 int idx2 = LanguageArrayIndex( p_sys->ppsz_audio_language,
1633                                          p_sys->p_es_audio->psz_language_code );
1634
1635                 if( idx1 < 0 || ( idx2 >= 0 && idx2 <= idx1 ) )
1636                     return;
1637                 i_wanted = es->i_channel;
1638             }
1639             else
1640             {
1641                 /* Select audio if (no audio selected yet)
1642                  * - no audio-language
1643                  * - no audio code for the ES
1644                  * - audio code in the requested list */
1645                 if( idx1 >= 0 ||
1646                     !strcmp( es->psz_language_code, "??" ) ||
1647                     !p_sys->ppsz_audio_language )
1648                     i_wanted = es->i_channel;
1649             }
1650
1651             if( p_sys->i_audio_last >= 0 )
1652                 i_wanted = p_sys->i_audio_last;
1653
1654             if( p_sys->i_audio_id >= 0 )
1655             {
1656                 if( es->i_id == p_sys->i_audio_id )
1657                     i_wanted = es->i_channel;
1658                 else
1659                     return;
1660             }
1661         }
1662         else if( i_cat == SPU_ES )
1663         {
1664             int idx1 = LanguageArrayIndex( p_sys->ppsz_sub_language,
1665                                      es->psz_language_code );
1666
1667             if( p_sys->p_es_sub &&
1668                 p_sys->p_es_sub->fmt.i_priority >= es->fmt.i_priority )
1669             {
1670                 int idx2 = LanguageArrayIndex( p_sys->ppsz_sub_language,
1671                                          p_sys->p_es_sub->psz_language_code );
1672
1673                 msg_Dbg( p_sys->p_input, "idx1=%d(%s) idx2=%d(%s)",
1674                         idx1, es->psz_language_code, idx2,
1675                         p_sys->p_es_sub->psz_language_code );
1676
1677                 if( idx1 < 0 || ( idx2 >= 0 && idx2 <= idx1 ) )
1678                     return;
1679                 /* We found a SPU that matches our language request */
1680                 i_wanted  = es->i_channel;
1681             }
1682             else if( idx1 >= 0 )
1683             {
1684                 msg_Dbg( p_sys->p_input, "idx1=%d(%s)",
1685                         idx1, es->psz_language_code );
1686
1687                 i_wanted  = es->i_channel;
1688             }
1689             else if( p_sys->i_default_sub_id >= 0 )
1690             {
1691                 if( es->i_id == p_sys->i_default_sub_id )
1692                     i_wanted = es->i_channel;
1693             }
1694
1695             if( p_sys->i_sub_last >= 0 )
1696                 i_wanted  = p_sys->i_sub_last;
1697
1698             if( p_sys->i_sub_id >= 0 )
1699             {
1700                 if( es->i_id == p_sys->i_sub_id )
1701                     i_wanted = es->i_channel;
1702                 else
1703                     return;
1704             }
1705         }
1706         else if( i_cat == VIDEO_ES )
1707         {
1708             i_wanted  = es->i_channel;
1709         }
1710
1711         if( i_wanted == es->i_channel && !EsIsSelected( es ) )
1712             EsSelect( out, es );
1713     }
1714
1715     /* FIXME TODO handle priority here */
1716     if( EsIsSelected( es ) )
1717     {
1718         if( i_cat == AUDIO_ES )
1719         {
1720             if( p_sys->i_mode == ES_OUT_MODE_AUTO &&
1721                 p_sys->p_es_audio &&
1722                 p_sys->p_es_audio != es &&
1723                 EsIsSelected( p_sys->p_es_audio ) )
1724             {
1725                 EsUnselect( out, p_sys->p_es_audio, false );
1726             }
1727             p_sys->p_es_audio = es;
1728         }
1729         else if( i_cat == SPU_ES )
1730         {
1731             if( p_sys->i_mode == ES_OUT_MODE_AUTO &&
1732                 p_sys->p_es_sub &&
1733                 p_sys->p_es_sub != es &&
1734                 EsIsSelected( p_sys->p_es_sub ) )
1735             {
1736                 EsUnselect( out, p_sys->p_es_sub, false );
1737             }
1738             p_sys->p_es_sub = es;
1739         }
1740         else if( i_cat == VIDEO_ES )
1741         {
1742             p_sys->p_es_video = es;
1743         }
1744     }
1745 }
1746
1747 /**
1748  * Send a block for the given es_out
1749  *
1750  * \param out the es_out to send from
1751  * \param es the es_out_id
1752  * \param p_block the data block to send
1753  */
1754 static int EsOutSend( es_out_t *out, es_out_id_t *es, block_t *p_block )
1755 {
1756     es_out_sys_t   *p_sys = out->p_sys;
1757     input_thread_t *p_input = p_sys->p_input;
1758     int i_total = 0;
1759
1760     if( libvlc_stats( p_input ) )
1761     {
1762         vlc_mutex_lock( &p_input->p->counters.counters_lock );
1763         stats_UpdateInteger( p_input, p_input->p->counters.p_demux_read,
1764                              p_block->i_buffer, &i_total );
1765         stats_UpdateFloat( p_input , p_input->p->counters.p_demux_bitrate,
1766                            (float)i_total, NULL );
1767         vlc_mutex_unlock( &p_input->p->counters.counters_lock );
1768     }
1769
1770     vlc_mutex_lock( &p_sys->lock );
1771
1772     /* Mark preroll blocks */
1773     if( p_sys->i_preroll_end >= 0 )
1774     {
1775         int64_t i_date = p_block->i_pts;
1776         if( i_date <= 0 )
1777             i_date = p_block->i_dts;
1778
1779         if( i_date < p_sys->i_preroll_end )
1780             p_block->i_flags |= BLOCK_FLAG_PREROLL;
1781     }
1782
1783     p_block->i_rate = 0;
1784
1785     if( !es->p_dec )
1786     {
1787         block_Release( p_block );
1788         vlc_mutex_unlock( &p_sys->lock );
1789         return VLC_SUCCESS;
1790     }
1791
1792     /* Decode */
1793     if( es->p_dec_record )
1794     {
1795         block_t *p_dup = block_Duplicate( p_block );
1796         if( p_dup )
1797             input_DecoderDecode( es->p_dec_record, p_dup );
1798     }
1799     input_DecoderDecode( es->p_dec, p_block );
1800
1801     es_format_t fmt_dsc;
1802     if( input_DecoderHasFormatChanged( es->p_dec, &fmt_dsc ) )
1803     {
1804         EsOutUpdateInfo( out, es, &fmt_dsc );
1805         es_format_Clean( &fmt_dsc );
1806     }
1807
1808     /* Check CC status */
1809     bool pb_cc[4];
1810
1811     input_DecoderIsCcPresent( es->p_dec, pb_cc );
1812     for( int i = 0; i < 4; i++ )
1813     {
1814         static const vlc_fourcc_t fcc[4] = {
1815             VLC_FOURCC('c', 'c', '1', ' '),
1816             VLC_FOURCC('c', 'c', '2', ' '),
1817             VLC_FOURCC('c', 'c', '3', ' '),
1818             VLC_FOURCC('c', 'c', '4', ' '),
1819         };
1820         es_format_t fmt;
1821
1822         if(  es->pb_cc_present[i] || !pb_cc[i] )
1823             continue;
1824         msg_Dbg( p_input, "Adding CC track %d for es[%d]", 1+i, es->i_id );
1825
1826         es_format_Init( &fmt, SPU_ES, fcc[i] );
1827         fmt.i_group = es->fmt.i_group;
1828         if( asprintf( &fmt.psz_description,
1829                       _("Closed captions %u"), 1 + i ) == -1 )
1830             fmt.psz_description = NULL;
1831         es->pp_cc_es[i] = EsOutAdd( out, &fmt );
1832         es->pp_cc_es[i]->p_master = es;
1833         es_format_Clean( &fmt );
1834
1835         /* */
1836         es->pb_cc_present[i] = true;
1837     }
1838
1839     vlc_mutex_unlock( &p_sys->lock );
1840
1841     return VLC_SUCCESS;
1842 }
1843
1844 /*****************************************************************************
1845  * EsOutDel:
1846  *****************************************************************************/
1847 static void EsOutDel( es_out_t *out, es_out_id_t *es )
1848 {
1849     es_out_sys_t *p_sys = out->p_sys;
1850     bool b_reselect = false;
1851     int i;
1852
1853     vlc_mutex_lock( &p_sys->lock );
1854
1855     /* We don't try to reselect */
1856     if( es->p_dec )
1857     {
1858         while( !p_sys->p_input->b_die && !p_sys->b_buffering && es->p_dec )
1859         {
1860             if( input_DecoderIsEmpty( es->p_dec ) &&
1861                 ( !es->p_dec_record || input_DecoderIsEmpty( es->p_dec_record ) ))
1862                 break;
1863             /* FIXME there should be a way to have auto deleted es, but there will be
1864              * a problem when another codec of the same type is created (mainly video) */
1865             msleep( 20*1000 );
1866         }
1867         EsUnselect( out, es, es->p_pgrm == p_sys->p_pgrm );
1868     }
1869
1870     if( es->p_pgrm == p_sys->p_pgrm )
1871         EsOutESVarUpdate( out, es, true );
1872
1873     TAB_REMOVE( p_sys->i_es, p_sys->es, es );
1874
1875     es->p_pgrm->i_es--;
1876     if( es->p_pgrm->i_es == 0 )
1877     {
1878         msg_Dbg( p_sys->p_input, "Program doesn't contain anymore ES" );
1879     }
1880
1881     if( p_sys->p_es_audio == es || p_sys->p_es_video == es ||
1882         p_sys->p_es_sub == es ) b_reselect = true;
1883
1884     if( p_sys->p_es_audio == es ) p_sys->p_es_audio = NULL;
1885     if( p_sys->p_es_video == es ) p_sys->p_es_video = NULL;
1886     if( p_sys->p_es_sub   == es ) p_sys->p_es_sub   = NULL;
1887
1888     switch( es->fmt.i_cat )
1889     {
1890         case AUDIO_ES:
1891             p_sys->i_audio--;
1892             break;
1893         case SPU_ES:
1894             p_sys->i_sub--;
1895             break;
1896         case VIDEO_ES:
1897             p_sys->i_video--;
1898             break;
1899     }
1900
1901     /* Re-select another track when needed */
1902     if( b_reselect )
1903     {
1904         for( i = 0; i < p_sys->i_es; i++ )
1905         {
1906             if( es->fmt.i_cat == p_sys->es[i]->fmt.i_cat )
1907                 EsOutSelect( out, p_sys->es[i], false );
1908         }
1909     }
1910
1911     free( es->psz_language );
1912     free( es->psz_language_code );
1913
1914     es_format_Clean( &es->fmt );
1915
1916     vlc_mutex_unlock( &p_sys->lock );
1917
1918     free( es );
1919 }
1920
1921 /**
1922  * Control query handler
1923  *
1924  * \param out the es_out to control
1925  * \param i_query A es_out query as defined in include/ninput.h
1926  * \param args a variable list of arguments for the query
1927  * \return VLC_SUCCESS or an error code
1928  */
1929 static int EsOutControlLocked( es_out_t *out, int i_query, va_list args )
1930 {
1931     es_out_sys_t *p_sys = out->p_sys;
1932     bool  b, *pb;
1933     int         i;
1934
1935     es_out_id_t *es;
1936
1937     switch( i_query )
1938     {
1939         case ES_OUT_SET_ES_STATE:
1940             es = (es_out_id_t*) va_arg( args, es_out_id_t * );
1941             b = (bool) va_arg( args, int );
1942             if( b && !EsIsSelected( es ) )
1943             {
1944                 EsSelect( out, es );
1945                 return EsIsSelected( es ) ? VLC_SUCCESS : VLC_EGENERIC;
1946             }
1947             else if( !b && EsIsSelected( es ) )
1948             {
1949                 EsUnselect( out, es, es->p_pgrm == p_sys->p_pgrm );
1950                 return VLC_SUCCESS;
1951             }
1952             return VLC_SUCCESS;
1953
1954         case ES_OUT_GET_ES_STATE:
1955             es = (es_out_id_t*) va_arg( args, es_out_id_t * );
1956             pb = (bool*) va_arg( args, bool * );
1957
1958             *pb = EsIsSelected( es );
1959             return VLC_SUCCESS;
1960
1961         case ES_OUT_SET_ACTIVE:
1962         {
1963             b = (bool) va_arg( args, int );
1964             p_sys->b_active = b;
1965             return VLC_SUCCESS;
1966         }
1967
1968         case ES_OUT_SET_MODE:
1969             i = (int) va_arg( args, int );
1970             if( i == ES_OUT_MODE_NONE || i == ES_OUT_MODE_ALL ||
1971                 i == ES_OUT_MODE_AUTO || i == ES_OUT_MODE_PARTIAL )
1972             {
1973                 p_sys->i_mode = i;
1974
1975                 /* Reapply policy mode */
1976                 for( i = 0; i < p_sys->i_es; i++ )
1977                 {
1978                     if( EsIsSelected( p_sys->es[i] ) )
1979                     {
1980                         EsUnselect( out, p_sys->es[i],
1981                                     p_sys->es[i]->p_pgrm == p_sys->p_pgrm );
1982                     }
1983                 }
1984                 for( i = 0; i < p_sys->i_es; i++ )
1985                 {
1986                     EsOutSelect( out, p_sys->es[i], false );
1987                 }
1988                 return VLC_SUCCESS;
1989             }
1990             return VLC_EGENERIC;
1991
1992         case ES_OUT_SET_ES:
1993         case ES_OUT_RESTART_ES:
1994         {
1995             int i_cat;
1996
1997             es = (es_out_id_t*) va_arg( args, es_out_id_t * );
1998
1999             if( es == NULL )
2000                 i_cat = UNKNOWN_ES;
2001             else if( es == (es_out_id_t*)((uint8_t*)NULL+AUDIO_ES) )
2002                 i_cat = AUDIO_ES;
2003             else if( es == (es_out_id_t*)((uint8_t*)NULL+VIDEO_ES) )
2004                 i_cat = VIDEO_ES;
2005             else if( es == (es_out_id_t*)((uint8_t*)NULL+SPU_ES) )
2006                 i_cat = SPU_ES;
2007             else
2008                 i_cat = -1;
2009
2010             for( i = 0; i < p_sys->i_es; i++ )
2011             {
2012                 if( i_cat == -1 )
2013                 {
2014                     if( es == p_sys->es[i] )
2015                     {
2016                         EsOutSelect( out, es, true );
2017                         break;
2018                     }
2019                 }
2020                 else
2021                 {
2022                     if( i_cat == UNKNOWN_ES || p_sys->es[i]->fmt.i_cat == i_cat )
2023                     {
2024                         if( EsIsSelected( p_sys->es[i] ) )
2025                         {
2026                             if( i_query == ES_OUT_RESTART_ES )
2027                             {
2028                                 if( p_sys->es[i]->p_dec )
2029                                 {
2030                                     EsDestroyDecoder( out, p_sys->es[i] );
2031                                     EsCreateDecoder( out, p_sys->es[i] );
2032                                 }
2033                             }
2034                             else
2035                             {
2036                                 EsUnselect( out, p_sys->es[i],
2037                                             p_sys->es[i]->p_pgrm == p_sys->p_pgrm );
2038                             }
2039                         }
2040                     }
2041                 }
2042             }
2043             return VLC_SUCCESS;
2044         }
2045  
2046         case ES_OUT_SET_ES_DEFAULT:
2047         {
2048             es = (es_out_id_t*) va_arg( args, es_out_id_t * );
2049
2050             if( es == NULL )
2051             {
2052                 /*p_sys->i_default_video_id = -1;*/
2053                 /*p_sys->i_default_audio_id = -1;*/
2054                 p_sys->i_default_sub_id = -1;
2055             }
2056             else if( es == (es_out_id_t*)((uint8_t*)NULL+AUDIO_ES) )
2057             {
2058                 /*p_sys->i_default_video_id = -1;*/
2059             }
2060             else if( es == (es_out_id_t*)((uint8_t*)NULL+VIDEO_ES) )
2061             {
2062                 /*p_sys->i_default_audio_id = -1;*/
2063             }
2064             else if( es == (es_out_id_t*)((uint8_t*)NULL+SPU_ES) )
2065             {
2066                 p_sys->i_default_sub_id = -1;
2067             }
2068             else
2069             {
2070                 /*if( es->fmt.i_cat == VIDEO_ES )
2071                     p_sys->i_default_video_id = es->i_id;
2072                 else
2073                 if( es->fmt.i_cat == AUDIO_ES )
2074                     p_sys->i_default_audio_id = es->i_id;
2075                 else*/
2076                 if( es->fmt.i_cat == SPU_ES )
2077                     p_sys->i_default_sub_id = es->i_id;
2078             }
2079             return VLC_SUCCESS;
2080         }
2081
2082         case ES_OUT_SET_PCR:
2083         case ES_OUT_SET_GROUP_PCR:
2084         {
2085             es_out_pgrm_t *p_pgrm = NULL;
2086             int            i_group = 0;
2087             int64_t        i_pcr;
2088
2089             if( i_query == ES_OUT_SET_PCR )
2090             {
2091                 p_pgrm = p_sys->p_pgrm;
2092             }
2093             else
2094             {
2095                 int i;
2096                 i_group = (int)va_arg( args, int );
2097                 for( i = 0; i < p_sys->i_pgrm; i++ )
2098                 {
2099                     if( p_sys->pgrm[i]->i_id == i_group )
2100                     {
2101                         p_pgrm = p_sys->pgrm[i];
2102                         break;
2103                     }
2104                 }
2105             }
2106             if( p_pgrm == NULL )
2107                 p_pgrm = EsOutProgramAdd( out, i_group );   /* Create it */
2108
2109             i_pcr = (int64_t)va_arg( args, int64_t );
2110             /* search program
2111              * TODO do not use mdate() but proper stream acquisition date */
2112             input_clock_Update( p_pgrm->p_clock, VLC_OBJECT(p_sys->p_input),
2113                                 p_sys->p_input->b_can_pace_control || p_sys->b_buffering, i_pcr, mdate() );
2114             /* Check buffering state on master clock update */
2115             if( p_sys->b_buffering && p_pgrm == p_sys->p_pgrm )
2116                 EsOutDecodersStopBuffering( out, false );
2117
2118             return VLC_SUCCESS;
2119         }
2120
2121         case ES_OUT_RESET_PCR:
2122             msg_Err( p_sys->p_input, "ES_OUT_RESET_PCR called" );
2123             EsOutChangePosition( out );
2124             return VLC_SUCCESS;
2125
2126         case ES_OUT_GET_TS:
2127             if( p_sys->p_pgrm )
2128             {
2129                 int64_t i_ts = (int64_t)va_arg( args, int64_t );
2130                 int64_t *pi_ts = (int64_t *)va_arg( args, int64_t * );
2131                 *pi_ts = input_clock_GetTS( p_sys->p_pgrm->p_clock, NULL,
2132                                             p_sys->p_input->i_pts_delay, i_ts );
2133                 return VLC_SUCCESS;
2134             }
2135             return VLC_EGENERIC;
2136
2137         case ES_OUT_SET_GROUP:
2138         {
2139             int j;
2140             i = (int) va_arg( args, int );
2141             for( j = 0; j < p_sys->i_pgrm; j++ )
2142             {
2143                 es_out_pgrm_t *p_pgrm = p_sys->pgrm[j];
2144                 if( p_pgrm->i_id == i )
2145                 {
2146                     EsOutProgramSelect( out, p_pgrm );
2147                     return VLC_SUCCESS;
2148                 }
2149             }
2150             return VLC_EGENERIC;
2151         }
2152
2153         case ES_OUT_SET_ES_FMT:
2154         {
2155             /* This ain't pretty but is need by some demuxers (eg. Ogg )
2156              * to update the p_extra data */
2157             es_format_t *p_fmt;
2158             es = (es_out_id_t*) va_arg( args, es_out_id_t * );
2159             p_fmt = (es_format_t*) va_arg( args, es_format_t * );
2160             if( es == NULL )
2161                 return VLC_EGENERIC;
2162
2163             if( p_fmt->i_extra )
2164             {
2165                 es->fmt.i_extra = p_fmt->i_extra;
2166                 es->fmt.p_extra = realloc( es->fmt.p_extra, p_fmt->i_extra );
2167                 memcpy( es->fmt.p_extra, p_fmt->p_extra, p_fmt->i_extra );
2168
2169                 if( !es->p_dec )
2170                     return VLC_SUCCESS;
2171 #if 1
2172                 EsDestroyDecoder( out, es );
2173
2174                 EsCreateDecoder( out, es );
2175 #else
2176                 es->p_dec->fmt_in.i_extra = p_fmt->i_extra;
2177                 es->p_dec->fmt_in.p_extra =
2178                     realloc( es->p_dec->fmt_in.p_extra, p_fmt->i_extra );
2179                 memcpy( es->p_dec->fmt_in.p_extra,
2180                         p_fmt->p_extra, p_fmt->i_extra );
2181 #endif
2182             }
2183
2184             return VLC_SUCCESS;
2185         }
2186
2187         case ES_OUT_SET_NEXT_DISPLAY_TIME:
2188         {
2189             const int64_t i_date = (int64_t)va_arg( args, int64_t );
2190
2191             if( i_date < 0 )
2192                 return VLC_EGENERIC;
2193
2194             p_sys->i_preroll_end = i_date;
2195
2196             return VLC_SUCCESS;
2197         }
2198         case ES_OUT_SET_GROUP_META:
2199         {
2200             int i_group = (int)va_arg( args, int );
2201             vlc_meta_t *p_meta = (vlc_meta_t*)va_arg( args, vlc_meta_t * );
2202
2203             EsOutProgramMeta( out, i_group, p_meta );
2204             return VLC_SUCCESS;
2205         }
2206         case ES_OUT_SET_GROUP_EPG:
2207         {
2208             int i_group = (int)va_arg( args, int );
2209             vlc_epg_t *p_epg = (vlc_epg_t*)va_arg( args, vlc_epg_t * );
2210
2211             EsOutProgramEpg( out, i_group, p_epg );
2212             return VLC_SUCCESS;
2213         }
2214         case ES_OUT_DEL_GROUP:
2215         {
2216             int i_group = (int)va_arg( args, int );
2217
2218             return EsOutProgramDel( out, i_group );
2219         }
2220
2221         case ES_OUT_GET_WAKE_UP:
2222         {
2223             mtime_t *pi_wakeup = (mtime_t*)va_arg( args, mtime_t* );
2224             *pi_wakeup = EsOutGetWakeup( out );
2225             return VLC_SUCCESS;
2226         }
2227
2228         case ES_OUT_SET_ES_BY_ID:
2229         case ES_OUT_RESTART_ES_BY_ID:
2230         case ES_OUT_SET_ES_DEFAULT_BY_ID:
2231         {
2232             const int i_id = (int)va_arg( args, int );
2233             es_out_id_t *p_es = EsOutGetFromID( out, i_id );
2234             int i_new_query;
2235
2236             switch( i_query )
2237             {
2238             case ES_OUT_SET_ES_BY_ID:         i_new_query = ES_OUT_SET_ES; break;
2239             case ES_OUT_RESTART_ES_BY_ID:     i_new_query = ES_OUT_RESTART_ES; break;
2240             case ES_OUT_SET_ES_DEFAULT_BY_ID: i_new_query = ES_OUT_SET_ES_DEFAULT; break;
2241             default:
2242               assert(0);
2243             }
2244             /* TODO if the lock is made non recursive it should be changed */
2245             return es_out_Control( out, i_new_query, p_es );
2246         }
2247
2248         case ES_OUT_GET_BUFFERING:
2249             pb = (bool *)va_arg( args, bool* );
2250             *pb = p_sys->b_buffering;
2251             return VLC_SUCCESS;
2252
2253         case ES_OUT_GET_EMPTY:
2254             pb = (bool *)va_arg( args, bool* );
2255             *pb = EsOutDecodersIsEmpty( out );
2256             return VLC_SUCCESS;
2257
2258         case ES_OUT_SET_DELAY:
2259         {
2260             const int i_cat = (int)va_arg( args, int );
2261             const mtime_t i_delay = (mtime_t)va_arg( args, mtime_t );
2262             EsOutSetDelay( out, i_cat, i_delay );
2263             return VLC_SUCCESS;
2264         }
2265
2266         case ES_OUT_SET_RECORD_STATE:
2267             b = (bool) va_arg( args, int );
2268             return EsOutSetRecord( out, b );
2269
2270         case ES_OUT_SET_PAUSE_STATE:
2271         {
2272             const bool b_source_paused = (bool)va_arg( args, int );
2273             const bool b_paused = (bool)va_arg( args, int );
2274             const mtime_t i_date = (mtime_t) va_arg( args, mtime_t );
2275
2276             assert( !b_source_paused == !b_paused );
2277             EsOutChangePause( out, b_paused, i_date );
2278
2279             return VLC_SUCCESS;
2280         }
2281
2282         case ES_OUT_SET_RATE:
2283         {
2284             const int i_src_rate = (int)va_arg( args, int );
2285             const int i_rate = (int)va_arg( args, int );
2286
2287             assert( i_src_rate == i_rate );
2288             EsOutChangeRate( out, i_rate );
2289
2290             return VLC_SUCCESS;
2291         }
2292
2293         case ES_OUT_SET_TIME:
2294         {
2295             const mtime_t i_date = (mtime_t)va_arg( args, mtime_t );
2296
2297             assert( i_date == -1 );
2298             EsOutChangePosition( out );
2299
2300             return VLC_SUCCESS;
2301         }
2302
2303         case ES_OUT_SET_FRAME_NEXT:
2304             EsOutFrameNext( out );
2305             return VLC_SUCCESS;
2306
2307         default:
2308             msg_Err( p_sys->p_input, "unknown query in es_out_Control" );
2309             return VLC_EGENERIC;
2310     }
2311 }
2312 static int EsOutControl( es_out_t *out, int i_query, va_list args )
2313 {
2314     es_out_sys_t *p_sys = out->p_sys;
2315     int i_ret;
2316
2317     vlc_mutex_lock( &p_sys->lock );
2318     i_ret = EsOutControlLocked( out, i_query, args );
2319     vlc_mutex_unlock( &p_sys->lock );
2320
2321     return i_ret;
2322 }
2323
2324 /****************************************************************************
2325  * LanguageGetName: try to expend iso639 into plain name
2326  ****************************************************************************/
2327 static char *LanguageGetName( const char *psz_code )
2328 {
2329     const iso639_lang_t *pl;
2330
2331     if( psz_code == NULL )
2332     {
2333         return strdup( "" );
2334     }
2335
2336     if( strlen( psz_code ) == 2 )
2337     {
2338         pl = GetLang_1( psz_code );
2339     }
2340     else if( strlen( psz_code ) == 3 )
2341     {
2342         pl = GetLang_2B( psz_code );
2343         if( !strcmp( pl->psz_iso639_1, "??" ) )
2344         {
2345             pl = GetLang_2T( psz_code );
2346         }
2347     }
2348     else
2349     {
2350         return strdup( psz_code );
2351     }
2352
2353     if( !strcmp( pl->psz_iso639_1, "??" ) )
2354     {
2355        return strdup( psz_code );
2356     }
2357     else
2358     {
2359         if( *pl->psz_native_name )
2360         {
2361             return strdup( pl->psz_native_name );
2362         }
2363         return strdup( pl->psz_eng_name );
2364     }
2365 }
2366
2367 /* Get a 2 char code */
2368 static char *LanguageGetCode( const char *psz_lang )
2369 {
2370     const iso639_lang_t *pl;
2371
2372     if( psz_lang == NULL || *psz_lang == '\0' )
2373         return strdup("??");
2374
2375     for( pl = p_languages; pl->psz_iso639_1 != NULL; pl++ )
2376     {
2377         if( !strcasecmp( pl->psz_eng_name, psz_lang ) ||
2378             !strcasecmp( pl->psz_native_name, psz_lang ) ||
2379             !strcasecmp( pl->psz_iso639_1, psz_lang ) ||
2380             !strcasecmp( pl->psz_iso639_2T, psz_lang ) ||
2381             !strcasecmp( pl->psz_iso639_2B, psz_lang ) )
2382             break;
2383     }
2384
2385     if( pl->psz_iso639_1 != NULL )
2386         return strdup( pl->psz_iso639_1 );
2387
2388     return strdup("??");
2389 }
2390
2391 static char **LanguageSplit( const char *psz_langs )
2392 {
2393     char *psz_dup;
2394     char *psz_parser;
2395     char **ppsz = NULL;
2396     int i_psz = 0;
2397
2398     if( psz_langs == NULL ) return NULL;
2399
2400     psz_parser = psz_dup = strdup(psz_langs);
2401
2402     while( psz_parser && *psz_parser )
2403     {
2404         char *psz;
2405         char *psz_code;
2406
2407         psz = strchr(psz_parser, ',' );
2408         if( psz ) *psz++ = '\0';
2409
2410         if( !strcmp( psz_parser, "any" ) )
2411         {
2412             TAB_APPEND( i_psz, ppsz, strdup("any") );
2413         }
2414         else
2415         {
2416             psz_code = LanguageGetCode( psz_parser );
2417             if( strcmp( psz_code, "??" ) )
2418             {
2419                 TAB_APPEND( i_psz, ppsz, psz_code );
2420             }
2421             else
2422             {
2423                 free( psz_code );
2424             }
2425         }
2426
2427         psz_parser = psz;
2428     }
2429
2430     if( i_psz )
2431     {
2432         TAB_APPEND( i_psz, ppsz, NULL );
2433     }
2434
2435     free( psz_dup );
2436     return ppsz;
2437 }
2438
2439 static int LanguageArrayIndex( char **ppsz_langs, char *psz_lang )
2440 {
2441     int i;
2442
2443     if( !ppsz_langs || !psz_lang ) return -1;
2444
2445     for( i = 0; ppsz_langs[i]; i++ )
2446     {
2447         if( !strcasecmp( ppsz_langs[i], psz_lang ) ||
2448             !strcasecmp( ppsz_langs[i], "any" ) )
2449         {
2450             return i;
2451         }
2452     }
2453
2454     return -1;
2455 }
2456
2457 /****************************************************************************
2458  * EsOutUpdateInfo:
2459  * - add meta info to the playlist item
2460  ****************************************************************************/
2461 static void EsOutUpdateInfo( es_out_t *out, es_out_id_t *es, const es_format_t *fmt )
2462 {
2463     es_out_sys_t   *p_sys = out->p_sys;
2464     input_thread_t *p_input = p_sys->p_input;
2465     const es_format_t *p_fmt_es = &es->fmt;
2466     char           *psz_cat;
2467     lldiv_t         div;
2468
2469     /* Create category name */
2470     if( asprintf( &psz_cat, _("Stream %d"), es->i_meta_id ) == -1 )
2471         return;
2472
2473     /* Remove previous information */
2474     input_Control( p_input, INPUT_DEL_INFO, psz_cat );
2475
2476     /* Add informations */
2477     const char *psz_type;
2478     switch( fmt->i_cat )
2479     {
2480     case AUDIO_ES:
2481         psz_type = _("Audio");
2482         break;
2483     case VIDEO_ES:
2484         psz_type = _("Video");
2485         break;
2486     case SPU_ES:
2487         psz_type = _("Subtitle");
2488         break;
2489     default:
2490         psz_type = NULL;
2491         break;
2492     }
2493
2494     if( psz_type )
2495         input_Control( p_input, INPUT_ADD_INFO, psz_cat, _("Type"), psz_type );
2496
2497     if( es->i_meta_id != es->i_id )
2498         input_Control( p_input, INPUT_ADD_INFO, psz_cat, _("Original ID"),
2499                        "%d", es->i_id );
2500
2501     input_Control( p_input, INPUT_ADD_INFO, psz_cat, _("Codec"),
2502                    "%.4s", (char*)&p_fmt_es->i_codec );
2503
2504     if( es->psz_language && *es->psz_language )
2505         input_Control( p_input, INPUT_ADD_INFO, psz_cat, _("Language"),
2506                        "%s", es->psz_language );
2507     if( fmt->psz_description && *fmt->psz_description )
2508         input_Control( p_input, INPUT_ADD_INFO, psz_cat, _("Description"),
2509                        "%s", fmt->psz_description );
2510
2511     switch( fmt->i_cat )
2512     {
2513     case AUDIO_ES:
2514         input_Control( p_input, INPUT_ADD_INFO, psz_cat,
2515                        _("Type"), _("Audio") );
2516
2517         if( fmt->audio.i_physical_channels & AOUT_CHAN_PHYSMASK )
2518             input_Control( p_input, INPUT_ADD_INFO, psz_cat, _("Channels"),
2519                            "%s", aout_FormatPrintChannels( &fmt->audio ) );
2520         else if( fmt->audio.i_channels > 0 )
2521             input_Control( p_input, INPUT_ADD_INFO, psz_cat, _("Channels"),
2522                            "%u", fmt->audio.i_channels );
2523
2524         if( fmt->audio.i_rate > 0 )
2525         {
2526             input_Control( p_input, INPUT_ADD_INFO, psz_cat, _("Sample rate"),
2527                            _("%u Hz"), fmt->audio.i_rate );
2528             /* FIXME that should be removed or improved ! (used by text/strings.c) */
2529             var_SetInteger( p_input, "sample-rate", fmt->audio.i_rate );
2530         }
2531
2532         unsigned int i_bitspersample = fmt->audio.i_bitspersample;
2533         if( i_bitspersample <= 0 )
2534             i_bitspersample = aout_BitsPerSample( p_fmt_es->i_codec );
2535         if( i_bitspersample > 0 )
2536             input_Control( p_input, INPUT_ADD_INFO, psz_cat,
2537                            _("Bits per sample"), "%u",
2538                            i_bitspersample );
2539
2540         if( fmt->i_bitrate > 0 )
2541         {
2542             input_Control( p_input, INPUT_ADD_INFO, psz_cat, _("Bitrate"),
2543                            _("%u kb/s"), fmt->i_bitrate / 1000 );
2544             /* FIXME that should be removed or improved ! (used by text/strings.c) */
2545             var_SetInteger( p_input, "bit-rate", fmt->i_bitrate );
2546         }
2547         for( int i = 0; i < AUDIO_REPLAY_GAIN_MAX; i++ )
2548         {
2549             const audio_replay_gain_t *p_rg = &fmt->audio_replay_gain;
2550             if( !p_rg->pb_gain[i] )
2551                 continue;
2552             const char *psz_name;
2553             if( i == AUDIO_REPLAY_GAIN_TRACK )
2554                 psz_name = _("Track replay gain");
2555             else
2556                 psz_name = _("Album replay gain");
2557             input_Control( p_input, INPUT_ADD_INFO, psz_cat,
2558                            psz_name, _("%.2f dB"), p_rg->pf_gain[i] );
2559         }
2560         break;
2561
2562     case VIDEO_ES:
2563         input_Control( p_input, INPUT_ADD_INFO, psz_cat,
2564                        _("Type"), _("Video") );
2565
2566         if( fmt->video.i_width > 0 && fmt->video.i_height > 0 )
2567             input_Control( p_input, INPUT_ADD_INFO, psz_cat,
2568                            _("Resolution"), "%ux%u",
2569                            fmt->video.i_width, fmt->video.i_height );
2570
2571         if( fmt->video.i_visible_width > 0 &&
2572             fmt->video.i_visible_height > 0 )
2573             input_Control( p_input, INPUT_ADD_INFO, psz_cat,
2574                            _("Display resolution"), "%ux%u",
2575                            fmt->video.i_visible_width,
2576                            fmt->video.i_visible_height);
2577        if( fmt->video.i_frame_rate > 0 &&
2578            fmt->video.i_frame_rate_base > 0 )
2579        {
2580            div = lldiv( (float)fmt->video.i_frame_rate /
2581                                fmt->video.i_frame_rate_base * 1000000,
2582                                1000000 );
2583            if( div.rem > 0 )
2584                input_Control( p_input, INPUT_ADD_INFO, psz_cat,
2585                               _("Frame rate"), "%"PRId64".%06u",
2586                               div.quot, (unsigned int )div.rem );
2587            else
2588                input_Control( p_input, INPUT_ADD_INFO, psz_cat,
2589                               _("Frame rate"), "%"PRId64, div.quot );
2590        }
2591        break;
2592
2593     case SPU_ES:
2594         input_Control( p_input, INPUT_ADD_INFO, psz_cat,
2595                        _("Type"), _("Subtitle") );
2596         break;
2597
2598     default:
2599         break;
2600     }
2601
2602     free( psz_cat );
2603 }