+
+ es->i_preroll_end = -1;
+ es->p_dec = input_DecoderNew( p_input, &es->fmt, VLC_FALSE );
+ if( es->p_dec == NULL || es->p_pgrm != p_sys->p_pgrm )
+ return;
+
+ if( es->fmt.i_cat == VIDEO_ES )
+ psz_var = "video-es";
+ else if( es->fmt.i_cat == AUDIO_ES )
+ psz_var = "audio-es";
+ else if( es->fmt.i_cat == SPU_ES )
+ psz_var = "spu-es";
+ else
+ return;
+
+ /* Mark it as selected */
+ val.i_int = es->i_id;
+ var_Change( p_input, psz_var, VLC_VAR_SETVALUE, &val, NULL );
+
+
+ var_SetBool( p_sys->p_input, "intf-change", VLC_TRUE );
+}
+
+static void EsUnselect( es_out_t *out, es_out_id_t *es, vlc_bool_t b_update )
+{
+ es_out_sys_t *p_sys = out->p_sys;
+ input_thread_t *p_input = p_sys->p_input;
+ vlc_value_t val;
+ char *psz_var;
+
+ if( es->p_dec == NULL )
+ {
+ msg_Warn( p_input, "ES 0x%x is already unselected", es->i_id );
+ return;
+ }
+
+ input_DecoderDelete( es->p_dec );
+ es->p_dec = NULL;
+
+ if( !b_update )
+ return;
+
+ /* Update var */
+ if( es->p_dec == NULL )
+ return;
+ if( es->fmt.i_cat == VIDEO_ES )
+ psz_var = "video-es";
+ else if( es->fmt.i_cat == AUDIO_ES )
+ psz_var = "audio-es";
+ else if( es->fmt.i_cat == SPU_ES )
+ psz_var = "spu-es";
+ else
+ return;
+
+ /* Mark it as selected */
+ val.i_int = -1;
+ var_Change( p_input, psz_var, VLC_VAR_SETVALUE, &val, NULL );
+
+ var_SetBool( p_sys->p_input, "intf-change", VLC_TRUE );
+}
+
+/**
+ * Select an ES given the current mode
+ * XXX: you need to take a the lock before (stream.stream_lock)
+ *
+ * \param out The es_out structure
+ * \param es es_out_id structure
+ * \param b_force ...
+ * \return nothing
+ */
+static void EsOutSelect( es_out_t *out, es_out_id_t *es, vlc_bool_t b_force )
+{
+ es_out_sys_t *p_sys = out->p_sys;
+
+ int i_cat = es->fmt.i_cat;
+
+ if( !p_sys->b_active ||
+ ( !b_force && es->fmt.i_priority < 0 ) )
+ {
+ return;
+ }
+
+ if( p_sys->i_mode == ES_OUT_MODE_ALL || b_force )
+ {
+ if( !es->p_dec )
+ EsSelect( out, es );
+ }
+ else if( p_sys->i_mode == ES_OUT_MODE_PARTIAL )
+ {
+ vlc_value_t val;
+ int i;
+ var_Get( p_sys->p_input, "programs", &val );
+ for ( i = 0; i < val.p_list->i_count; i++ )
+ {
+ if ( val.p_list->p_values[i].i_int == es->p_pgrm->i_id || b_force )
+ {
+ if( !es->p_dec )
+ EsSelect( out, es );
+ break;
+ }
+ }
+ var_Change( p_sys->p_input, "programs", VLC_VAR_FREELIST, &val, NULL );
+ }
+ else if( p_sys->i_mode == ES_OUT_MODE_AUTO )
+ {
+ int i_wanted = -1;
+
+ if( es->p_pgrm != p_sys->p_pgrm )
+ return;
+
+ if( i_cat == AUDIO_ES )
+ {
+ int idx1 = LanguageArrayIndex( p_sys->ppsz_audio_language,
+ es->psz_language_code );
+
+ if( p_sys->p_es_audio &&
+ p_sys->p_es_audio->fmt.i_priority >= es->fmt.i_priority )
+ {
+ int idx2 = LanguageArrayIndex( p_sys->ppsz_audio_language,
+ p_sys->p_es_audio->psz_language_code );
+
+ if( idx1 < 0 || ( idx2 >= 0 && idx2 <= idx1 ) )
+ return;
+ i_wanted = es->i_channel;
+ }
+ else
+ {
+ /* Select audio if (no audio selected yet)
+ * - no audio-language
+ * - no audio code for the ES
+ * - audio code in the requested list */
+ if( idx1 >= 0 ||
+ !strcmp( es->psz_language_code, "??" ) ||
+ !p_sys->ppsz_audio_language )
+ i_wanted = es->i_channel;
+ }
+
+ if( p_sys->i_audio_last >= 0 )
+ i_wanted = p_sys->i_audio_last;
+
+ if( p_sys->i_audio_id >= 0 )
+ {
+ if( es->i_id == p_sys->i_audio_id )
+ i_wanted = es->i_channel;
+ else
+ return;
+ }
+ }
+ else if( i_cat == SPU_ES )
+ {
+ int idx1 = LanguageArrayIndex( p_sys->ppsz_sub_language,
+ es->psz_language_code );
+
+ if( p_sys->p_es_sub &&
+ p_sys->p_es_sub->fmt.i_priority >= es->fmt.i_priority )
+ {
+ int idx2 = LanguageArrayIndex( p_sys->ppsz_sub_language,
+ p_sys->p_es_sub->psz_language_code );
+
+ msg_Dbg( p_sys->p_input, "idx1=%d(%s) idx2=%d(%s)",
+ idx1, es->psz_language_code, idx2,
+ p_sys->p_es_sub->psz_language_code );
+
+ if( idx1 < 0 || ( idx2 >= 0 && idx2 <= idx1 ) )
+ return;
+ /* We found a SPU that matches our language request */
+ i_wanted = es->i_channel;
+ }
+ else if( idx1 >= 0 )
+ {
+ msg_Dbg( p_sys->p_input, "idx1=%d(%s)",
+ idx1, es->psz_language_code );
+
+ i_wanted = es->i_channel;
+ }
+ if( p_sys->i_sub_last >= 0 )
+ i_wanted = p_sys->i_sub_last;
+
+ if( p_sys->i_sub_id >= 0 )
+ {
+ if( es->i_id == p_sys->i_sub_id )
+ i_wanted = es->i_channel;
+ else
+ return;
+ }
+ }
+ else if( i_cat == VIDEO_ES )
+ {
+ i_wanted = es->i_channel;
+ }
+
+ if( i_wanted == es->i_channel && es->p_dec == NULL )
+ EsSelect( out, es );
+ }
+
+ /* FIXME TODO handle priority here */
+ if( es->p_dec )
+ {
+ if( i_cat == AUDIO_ES )
+ {
+ if( p_sys->i_mode == ES_OUT_MODE_AUTO &&
+ p_sys->p_es_audio &&
+ p_sys->p_es_audio != es &&
+ p_sys->p_es_audio->p_dec )
+ {
+ EsUnselect( out, p_sys->p_es_audio, VLC_FALSE );
+ }
+ p_sys->p_es_audio = es;
+ }
+ else if( i_cat == SPU_ES )
+ {
+ if( p_sys->i_mode == ES_OUT_MODE_AUTO &&
+ p_sys->p_es_sub &&
+ p_sys->p_es_sub != es &&
+ p_sys->p_es_sub->p_dec )
+ {
+ EsUnselect( out, p_sys->p_es_sub, VLC_FALSE );
+ }
+ p_sys->p_es_sub = es;
+ }
+ else if( i_cat == VIDEO_ES )
+ {
+ p_sys->p_es_video = es;
+ }
+ }
+}
+
+/**
+ * Send a block for the given es_out
+ *
+ * \param out the es_out to send from
+ * \param es the es_out_id
+ * \param p_block the data block to send
+ */
+static int EsOutSend( es_out_t *out, es_out_id_t *es, block_t *p_block )
+{
+ es_out_sys_t *p_sys = out->p_sys;
+ input_thread_t *p_input = p_sys->p_input;
+ es_out_pgrm_t *p_pgrm = es->p_pgrm;
+ int64_t i_delay;
+ int i_total=0;
+
+ if( es->fmt.i_cat == AUDIO_ES )
+ i_delay = p_sys->i_audio_delay;
+ else if( es->fmt.i_cat == SPU_ES )
+ i_delay = p_sys->i_spu_delay;
+ else
+ i_delay = 0;
+
+ if( p_input->p_libvlc->b_stats )
+ {
+ stats_UpdateInteger( p_input, STATS_DEMUX_READ, p_block->i_buffer,
+ &i_total );
+ stats_UpdateFloat( p_input , STATS_DEMUX_BITRATE, (float)i_total, NULL );
+ }
+
+ /* Mark preroll blocks */
+ if( es->i_preroll_end >= 0 )
+ {
+ int64_t i_date = p_block->i_pts;
+ if( i_date <= 0 )
+ i_date = p_block->i_dts;
+
+ if( i_date < es->i_preroll_end )
+ p_block->i_flags |= BLOCK_FLAG_PREROLL;
+ else
+ es->i_preroll_end = -1;
+ }
+
+ /* +11 -> avoid null value with non null dts/pts */
+ if( p_block->i_dts > 0 )
+ {
+ p_block->i_dts =
+ input_ClockGetTS( p_input, &p_pgrm->clock,
+ ( p_block->i_dts + 11 ) * 9 / 100 ) + i_delay;
+ }
+ if( p_block->i_pts > 0 )
+ {
+ p_block->i_pts =
+ input_ClockGetTS( p_input, &p_pgrm->clock,
+ ( p_block->i_pts + 11 ) * 9 / 100 ) + i_delay;
+ }
+ if ( es->fmt.i_codec == VLC_FOURCC( 't', 'e', 'l', 'x' ) )
+ {
+ mtime_t current_date = mdate();
+ if( !p_block->i_pts
+ || p_block->i_pts > current_date + 10000000
+ || current_date > p_block->i_pts )
+ {
+ /* ETSI EN 300 472 Annex A : do not take into account the PTS
+ * for teletext streams. */
+ p_block->i_pts = current_date + 400000
+ + p_input->i_pts_delay + i_delay;
+ }
+ }
+
+ p_block->i_rate = p_input->i_rate;
+
+ /* TODO handle mute */
+ if( es->p_dec && ( es->fmt.i_cat != AUDIO_ES ||
+ p_input->i_rate == INPUT_RATE_DEFAULT ) )
+ {
+ input_DecoderDecode( es->p_dec, p_block );
+ }
+ else