es_out.c
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:86k
源码类别:

midi

开发平台:

Unix_Linux

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