]> git.sesse.net Git - vlc/blobdiff - src/input/es_out.c
es_out: use input_DecoderDrain()
[vlc] / src / input / es_out.c
index de186e54eb0d86de7bd1b10321f5edfb85005a0d..ec7d6556ccd2ae830aeaf7f58969bcc79c3a8721 100644 (file)
@@ -193,7 +193,7 @@ static void EsOutDecodersStopBuffering( es_out_t *out, bool b_forced );
 static char *LanguageGetName( const char *psz_code );
 static char *LanguageGetCode( const char *psz_lang );
 static char **LanguageSplit( const char *psz_langs, bool b_default_any );
-static int LanguageArrayIndex( char **ppsz_langs, char *psz_lang );
+static int LanguageArrayIndex( char **ppsz_langs, const char *psz_lang );
 
 static char *EsOutProgramGetMetaName( es_out_pgrm_t *p_pgrm );
 
@@ -227,7 +227,7 @@ es_out_t *input_EsOutNew( input_thread_t *p_input, int i_rate )
     if( !out )
         return NULL;
 
-    es_out_sys_t *p_sys = malloc( sizeof( *p_sys ) );
+    es_out_sys_t *p_sys = calloc( 1, sizeof( *p_sys ) );
     if( !p_sys )
     {
         free( out );
@@ -249,21 +249,12 @@ es_out_t *input_EsOutNew( input_thread_t *p_input, int i_rate )
 
 
     TAB_INIT( p_sys->i_pgrm, p_sys->pgrm );
-    p_sys->p_pgrm   = NULL;
-
-    p_sys->i_id    = 0;
 
     TAB_INIT( p_sys->i_es, p_sys->es );
 
-    p_sys->i_audio = 0;
-    p_sys->i_video = 0;
-    p_sys->i_sub   = 0;
-
     /* */
     p_sys->i_group_id = var_GetInteger( p_input, "program" );
-
     p_sys->i_audio_last = var_GetInteger( p_input, "audio-track" );
-
     p_sys->i_sub_last = var_GetInteger( p_input, "sub-track" );
 
     p_sys->i_default_sub_id   = -1;
@@ -292,39 +283,18 @@ es_out_t *input_EsOutNew( input_thread_t *p_input, int i_rate )
         }
         free( psz_string );
     }
-    else
-    {
-        p_sys->ppsz_sub_language = NULL;
-        p_sys->ppsz_audio_language = NULL;
-    }
 
     p_sys->i_audio_id = var_GetInteger( p_input, "audio-track-id" );
 
     p_sys->i_sub_id = var_GetInteger( p_input, "sub-track-id" );
 
-    p_sys->p_es_audio = NULL;
-    p_sys->p_es_video = NULL;
-    p_sys->p_es_sub   = NULL;
-
-    p_sys->i_audio_delay= 0;
-    p_sys->i_spu_delay  = 0;
-
-    p_sys->b_paused = false;
     p_sys->i_pause_date = -1;
 
     p_sys->i_rate = i_rate;
-    p_sys->i_pts_delay = 0;
-    p_sys->i_pts_jitter = 0;
-    p_sys->i_cr_average = 0;
 
     p_sys->b_buffering = true;
-    p_sys->i_buffering_extra_initial = 0;
-    p_sys->i_buffering_extra_stream = 0;
-    p_sys->i_buffering_extra_system = 0;
     p_sys->i_preroll_end = -1;
 
-    p_sys->p_sout_record = NULL;
-
     return out;
 }
 
@@ -491,7 +461,7 @@ static int EsOutSetRecord(  es_out_t *out, bool b_record )
 
         if( !psz_sout && psz_path )
         {
-            char *psz_file = input_CreateFilename( VLC_OBJECT(p_input), psz_path, INPUT_RECORD_PREFIX, NULL );
+            char *psz_file = input_CreateFilename( p_input, psz_path, INPUT_RECORD_PREFIX, NULL );
             if( psz_file )
             {
                 if( asprintf( &psz_sout, "#record{dst-prefix='%s'}", psz_file ) < 0 )
@@ -521,7 +491,7 @@ static int EsOutSetRecord(  es_out_t *out, bool b_record )
 
             p_es->p_dec_record = input_DecoderNew( p_input, &p_es->fmt, p_es->p_pgrm->p_clock, p_sys->p_sout_record );
             if( p_es->p_dec_record && p_sys->b_buffering )
-                input_DecoderStartBuffering( p_es->p_dec_record );
+                input_DecoderStartWait( p_es->p_dec_record );
         }
     }
     else
@@ -603,13 +573,16 @@ static void EsOutChangePosition( es_out_t *out )
     {
         es_out_id_t *p_es = p_sys->es[i];
 
-        if( !p_es->p_dec )
-            continue;
-
-        input_DecoderStartBuffering( p_es->p_dec );
-
-        if( p_es->p_dec_record )
-            input_DecoderStartBuffering( p_es->p_dec_record );
+        if( p_es->p_dec != NULL )
+        {
+            input_DecoderFlush( p_es->p_dec );
+            if( !p_sys->b_buffering )
+            {
+                input_DecoderStartWait( p_es->p_dec );
+                if( p_es->p_dec_record != NULL )
+                    input_DecoderStartWait( p_es->p_dec_record );
+            }
+        }
     }
 
     for( int i = 0; i < p_sys->i_pgrm; i++ )
@@ -627,17 +600,14 @@ static void EsOutChangePosition( es_out_t *out )
 static void EsOutDecodersStopBuffering( es_out_t *out, bool b_forced )
 {
     es_out_sys_t *p_sys = out->p_sys;
-    int i_ret;
 
     mtime_t i_stream_start;
     mtime_t i_system_start;
     mtime_t i_stream_duration;
     mtime_t i_system_duration;
-    i_ret = input_clock_GetState( p_sys->p_pgrm->p_clock,
+    if (input_clock_GetState( p_sys->p_pgrm->p_clock,
                                   &i_stream_start, &i_system_start,
-                                  &i_stream_duration, &i_system_duration );
-    assert( !i_ret || b_forced );
-    if( i_ret )
+                                  &i_stream_duration, &i_system_duration ))
         return;
 
     mtime_t i_preroll_duration = 0;
@@ -650,7 +620,11 @@ static void EsOutDecodersStopBuffering( es_out_t *out, bool b_forced )
 
     if( i_stream_duration <= i_buffering_duration && !b_forced )
     {
-        const double f_level = __MAX( (double)i_stream_duration / i_buffering_duration, 0 );
+        double f_level;
+        if (i_buffering_duration == 0)
+            f_level = 0;
+        else
+            f_level = __MAX( (double)i_stream_duration / i_buffering_duration, 0 );
         input_SendEventCache( p_sys->p_input, f_level );
 
         msg_Dbg( p_sys->p_input, "Buffering %d%%", (int)(100 * f_level) );
@@ -676,12 +650,12 @@ static void EsOutDecodersStopBuffering( es_out_t *out, bool b_forced )
 
         if( !p_es->p_dec || p_es->fmt.i_cat == SPU_ES )
             continue;
-        input_DecoderWaitBuffering( p_es->p_dec );
+        input_DecoderWait( p_es->p_dec );
         if( p_es->p_dec_record )
-            input_DecoderWaitBuffering( p_es->p_dec_record );
+            input_DecoderWait( p_es->p_dec_record );
     }
 
-    msg_Dbg( p_sys->p_input, "Decoder buffering done in %d ms",
+    msg_Dbg( p_sys->p_input, "Decoder wait done in %d ms",
               (int)(mdate() - i_decoder_buffering_start)/1000 );
 
     /* Here is a good place to destroy unused vout with every demuxer */
@@ -701,9 +675,9 @@ static void EsOutDecodersStopBuffering( es_out_t *out, bool b_forced )
         if( !p_es->p_dec )
             continue;
 
-        input_DecoderStopBuffering( p_es->p_dec );
+        input_DecoderStopWait( p_es->p_dec );
         if( p_es->p_dec_record )
-            input_DecoderStopBuffering( p_es->p_dec_record );
+            input_DecoderStopWait( p_es->p_dec_record );
     }
 }
 static void EsOutDecodersChangePause( es_out_t *out, bool b_paused, mtime_t i_date )
@@ -853,21 +827,19 @@ static void EsOutFrameNext( es_out_t *out )
 static mtime_t EsOutGetBuffering( es_out_t *out )
 {
     es_out_sys_t *p_sys = out->p_sys;
+    mtime_t i_stream_duration, i_system_start;
 
     if( !p_sys->p_pgrm )
         return 0;
+    else
+    {
+        mtime_t i_stream_start, i_system_duration;
 
-    int i_ret;
-    mtime_t i_stream_start;
-    mtime_t i_system_start;
-    mtime_t i_stream_duration;
-    mtime_t i_system_duration;
-    i_ret = input_clock_GetState( p_sys->p_pgrm->p_clock,
+        if( input_clock_GetState( p_sys->p_pgrm->p_clock,
                                   &i_stream_start, &i_system_start,
-                                  &i_stream_duration, &i_system_duration );
-
-    if( i_ret )
-        return 0;
+                                  &i_stream_duration, &i_system_duration ) )
+            return 0;
+    }
 
     mtime_t i_delay;
 
@@ -878,6 +850,7 @@ static mtime_t EsOutGetBuffering( es_out_t *out )
     else
     {
         mtime_t i_system_duration;
+
         if( p_sys->b_paused )
         {
             i_system_duration = p_sys->i_pause_date  - i_system_start;
@@ -1042,7 +1015,7 @@ static void EsOutProgramSelect( es_out_t *out, es_out_pgrm_t *p_pgrm )
     }
 
     /* Update now playing */
-    input_item_SetNowPlaying( p_input->p->p_item, p_pgrm->psz_now_playing );
+    input_item_SetESNowPlaying( p_input->p->p_item, p_pgrm->psz_now_playing );
     input_item_SetPublisher( p_input->p->p_item, p_pgrm->psz_publisher );
 
     input_SendEventMeta( p_input );
@@ -1184,7 +1157,7 @@ static void EsOutProgramMeta( es_out_t *out, int i_group, const vlc_meta_t *p_me
 
     /* Check against empty meta data (empty for what we handle) */
     if( !vlc_meta_Get( p_meta, vlc_meta_Title) &&
-        !vlc_meta_Get( p_meta, vlc_meta_NowPlaying) &&
+        !vlc_meta_Get( p_meta, vlc_meta_ESNowPlaying) &&
         !vlc_meta_Get( p_meta, vlc_meta_Publisher) &&
         vlc_meta_GetExtraCount( p_meta ) <= 0 )
     {
@@ -1323,20 +1296,20 @@ static void EsOutProgramEpg( es_out_t *out, int i_group, const vlc_epg_t *p_epg
 
     if( p_pgrm == p_sys->p_pgrm )
     {
-        input_item_SetNowPlaying( p_input->p->p_item, p_pgrm->psz_now_playing );
+        input_item_SetESNowPlaying( p_input->p->p_item, p_pgrm->psz_now_playing );
         input_SendEventMeta( p_input );
     }
 
     if( p_pgrm->psz_now_playing )
     {
         input_Control( p_input, INPUT_ADD_INFO, psz_cat,
-            vlc_meta_TypeToLocalizedString(vlc_meta_NowPlaying),
+            vlc_meta_TypeToLocalizedString(vlc_meta_ESNowPlaying), "%s",
             p_pgrm->psz_now_playing );
     }
     else
     {
         input_Control( p_input, INPUT_DEL_INFO, psz_cat,
-            vlc_meta_TypeToLocalizedString(vlc_meta_NowPlaying) );
+            vlc_meta_TypeToLocalizedString(vlc_meta_ESNowPlaying) );
     }
 
     free( psz_cat );
@@ -1374,48 +1347,34 @@ static void EsOutMeta( es_out_t *p_out, const vlc_meta_t *p_meta )
 {
     es_out_sys_t    *p_sys = p_out->p_sys;
     input_thread_t  *p_input = p_sys->p_input;
-
     input_item_t *p_item = input_GetItem( p_input );
 
-    char *psz_title = NULL;
-    char *psz_arturl = input_item_GetArtURL( p_item );
-
-    vlc_mutex_lock( &p_item->lock );
+    if( vlc_meta_Get( p_meta, vlc_meta_Title ) != NULL )
+        input_item_SetName( p_item, vlc_meta_Get( p_meta, vlc_meta_Title ) );
 
-    if( vlc_meta_Get( p_meta, vlc_meta_Title ) && !p_item->b_fixed_name )
-        psz_title = strdup( vlc_meta_Get( p_meta, vlc_meta_Title ) );
+    char *psz_arturl = NULL;
+    if( vlc_meta_Get( p_item->p_meta, vlc_meta_ArtworkURL ) != NULL )
+        psz_arturl = input_item_GetArtURL( p_item ); /* save value */
 
+    vlc_mutex_lock( &p_item->lock );
     vlc_meta_Merge( p_item->p_meta, p_meta );
-
-    if( !psz_arturl || *psz_arturl == '\0' )
-    {
-        const char *psz_tmp = vlc_meta_Get( p_item->p_meta, vlc_meta_ArtworkURL );
-        if( psz_tmp )
-            psz_arturl = strdup( psz_tmp );
-    }
     vlc_mutex_unlock( &p_item->lock );
 
-    if( psz_arturl && *psz_arturl )
-    {
+    if( psz_arturl != NULL ) /* restore/favor previously set item art URL */
         input_item_SetArtURL( p_item, psz_arturl );
+    else
+        psz_arturl = input_item_GetArtURL( p_item );
 
-        if( !strncmp( psz_arturl, "attachment://", strlen("attachment") ) )
-        {
-            /* Don't look for art cover if sout
-             * XXX It can change when sout has meta data support */
-            if( p_input->p->p_sout && !p_input->b_preparsing )
-                input_item_SetArtURL( p_item, "" );
-            else
-                input_ExtractAttachmentAndCacheArt( p_input );
-        }
+    if( psz_arturl != NULL && !strncmp( psz_arturl, "attachment://", 13 ) )
+    {   /* Clear art cover if streaming out.
+         * FIXME: Why? Remove this when sout gets meta data support. */
+        if( p_input->p->p_sout && !p_input->b_preparsing )
+            input_item_SetArtURL( p_item, NULL );
+        else
+            input_ExtractAttachmentAndCacheArt( p_input, psz_arturl + 13 );
     }
     free( psz_arturl );
 
-    if( psz_title )
-    {
-        input_item_SetName( p_item, psz_title );
-        free( psz_title );
-    }
     input_item_SetPreparsed( p_item, true );
 
     input_SendEventMeta( p_input );
@@ -1588,13 +1547,13 @@ static void EsCreateDecoder( es_out_t *out, es_out_id_t *p_es )
     if( p_es->p_dec )
     {
         if( p_sys->b_buffering )
-            input_DecoderStartBuffering( p_es->p_dec );
+            input_DecoderStartWait( p_es->p_dec );
 
         if( !p_es->p_master && p_sys->p_sout_record )
         {
             p_es->p_dec_record = input_DecoderNew( p_input, &p_es->fmt, p_es->p_pgrm->p_clock, p_sys->p_sout_record );
             if( p_es->p_dec_record && p_sys->b_buffering )
-                input_DecoderStartBuffering( p_es->p_dec_record );
+                input_DecoderStartWait( p_es->p_dec_record );
         }
     }
 
@@ -1746,7 +1705,7 @@ static void EsOutSelect( es_out_t *out, es_out_id_t *es, bool b_force )
     int i_cat = es->fmt.i_cat;
 
     if( !p_sys->b_active ||
-        ( !b_force && es->fmt.i_priority < 0 ) )
+        ( !b_force && es->fmt.i_priority < ES_PRIORITY_SELECTABLE_MIN ) )
     {
         return;
     }
@@ -1786,28 +1745,34 @@ static void EsOutSelect( es_out_t *out, es_out_id_t *es, bool b_force )
 
         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 )
+            if( p_sys->ppsz_audio_language )
             {
-                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;
+                int es_idx = LanguageArrayIndex( p_sys->ppsz_audio_language,
+                                                 es->psz_language_code );
+                if( !p_sys->p_es_audio )
+                {
+                    /* Only select the language if it's in the list */
+                    if( es_idx >= 0 )
+                        i_wanted = es->i_channel;
+                }
+                else
+                {
+                    int selected_es_idx =
+                        LanguageArrayIndex( p_sys->ppsz_audio_language,
+                                            p_sys->p_es_audio->psz_language_code );
+                    if( es_idx >= 0 &&
+                        ( selected_es_idx < 0 || es_idx < selected_es_idx ||
+                          ( es_idx == selected_es_idx &&
+                            p_sys->p_es_audio->fmt.i_priority < es->fmt.i_priority ) ) )
+                        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 )
+                /* Select the first one if there is no selected audio yet 
+                 * then choose by ES priority */
+                if( !p_sys->p_es_audio ||
+                    p_sys->p_es_audio->fmt.i_priority < es->fmt.i_priority )
                     i_wanted = es->i_channel;
             }
 
@@ -1824,35 +1789,58 @@ static void EsOutSelect( es_out_t *out, es_out_id_t *es, bool b_force )
         }
         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 )
+            if( p_sys->ppsz_sub_language )
             {
-                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;
+                int es_idx = LanguageArrayIndex( p_sys->ppsz_sub_language,
+                                     es->psz_language_code );
+                if( !p_sys->p_es_sub )
+                {
+                    /* Select the language if it's in the list */
+                    if( es_idx >= 0 ||
+                        /*FIXME: Should default subtitle not in the list be 
+                         * displayed if not forbidden by none? */
+                        ( p_sys->i_default_sub_id >= 0 &&
+                          /* check if the subtitle isn't forbidden by none */
+                          LanguageArrayIndex( p_sys->ppsz_sub_language, "none" ) < 0 &&
+                          es->i_id == p_sys->i_default_sub_id ) )
+                        i_wanted = es->i_channel;
+                }
+                else
+                {
+                    int selected_es_idx =
+                        LanguageArrayIndex( p_sys->ppsz_sub_language,
+                                            p_sys->p_es_sub->psz_language_code );
+
+                    if( es_idx >= 0 &&
+                        ( selected_es_idx < 0 || es_idx < selected_es_idx ||
+                          ( es_idx == selected_es_idx &&
+                            p_sys->p_es_sub->fmt.i_priority < es->fmt.i_priority ) ) )
+                        i_wanted = es->i_channel;
+                }
             }
-            else if( idx1 >= 0 )
+            else if ( es->fmt.i_codec == EsOutFourccClosedCaptions[0] ||
+                      es->fmt.i_codec == EsOutFourccClosedCaptions[1] ||
+                      es->fmt.i_codec == EsOutFourccClosedCaptions[2] ||
+                      es->fmt.i_codec == EsOutFourccClosedCaptions[3])
             {
-                msg_Dbg( p_sys->p_input, "idx1=%d(%s)",
-                        idx1, es->psz_language_code );
-
-                i_wanted  = es->i_channel;
+                    /* We don't want to enable on initial create since p_master
+                       isn't set yet (otherwise we will think it's a standard
+                       ES_SUB stream and cause a resource leak) */
+                    return;
             }
-            else if( p_sys->i_default_sub_id >= 0 )
+            else
             {
-                if( es->i_id == p_sys->i_default_sub_id )
+                /* If there is no user preference, select the default subtitle 
+                 * or adapt by ES priority */
+                if( ( !p_sys->p_es_sub &&
+                      ( p_sys->i_default_sub_id >= 0 &&
+                        es->i_id == p_sys->i_default_sub_id ) ) ||
+                    ( p_sys->p_es_sub && 
+                      p_sys->p_es_sub->fmt.i_priority < es->fmt.i_priority ) )
                     i_wanted = es->i_channel;
+                else if( p_sys->p_es_sub &&
+                         p_sys->p_es_sub->fmt.i_priority >= es->fmt.i_priority )
+                    i_wanted = p_sys->p_es_sub->i_channel;
             }
 
             if( p_sys->i_sub_last >= 0 )
@@ -2024,6 +2012,10 @@ static int EsOutSend( es_out_t *out, es_out_id_t *es, block_t *p_block )
 
         /* */
         es->pb_cc_present[i] = true;
+
+        /* Enable if user specified on command line */
+        if (p_sys->i_sub_last == i)
+            EsOutSelect(out, es->pp_cc_es[i], true);
     }
 
     vlc_mutex_unlock( &p_sys->lock );
@@ -2045,7 +2037,7 @@ static void EsOutDel( es_out_t *out, es_out_id_t *es )
     /* We don't try to reselect */
     if( es->p_dec )
     {
-        while( !p_sys->p_input->b_die && !p_sys->b_buffering && es->p_dec )
+        while( vlc_object_alive(p_sys->p_input) && !p_sys->b_buffering )
         {
             if( input_DecoderIsEmpty( es->p_dec ) &&
                 ( !es->p_dec_record || input_DecoderIsEmpty( es->p_dec_record ) ))
@@ -2323,14 +2315,17 @@ static int EsOutControlLocked( es_out_t *out, int i_query, va_list args )
                             EsOutIsExtraBufferingAllowed( out ),
                             i_pcr, mdate() );
 
-        if( p_pgrm == p_sys->p_pgrm )
+        if( !p_sys->p_pgrm )
+            return VLC_SUCCESS;
+
+        if( p_sys->b_buffering )
         {
-            if( p_sys->b_buffering )
-            {
-                /* Check buffering state on master clock update */
-                EsOutDecodersStopBuffering( out, false );
-            }
-            else if( b_late && ( !p_sys->p_input->p->p_sout ||
+            /* Check buffering state on master clock update */
+            EsOutDecodersStopBuffering( out, false );
+        }
+        else if( p_pgrm == p_sys->p_pgrm )
+        {
+            if( b_late && ( !p_sys->p_input->p->p_sout ||
                                  !p_sys->p_input->p->b_out_pace_control ) )
             {
                 const mtime_t i_pts_delay_base = p_sys->i_pts_delay - p_sys->i_pts_jitter;
@@ -2344,19 +2339,23 @@ static int EsOutControlLocked( es_out_t *out, int i_query, va_list args )
                              "ES_OUT_SET_(GROUP_)PCR  is called too late (jitter of %d ms ignored)",
                              (int)(i_pts_delay - i_pts_delay_base) / 1000 );
                     i_pts_delay = p_sys->i_pts_delay;
+
+                    /* reset clock */
+                    for( int i = 0; i < p_sys->i_pgrm; i++ )
+                      input_clock_Reset( p_sys->pgrm[i]->p_clock );
                 }
                 else
                 {
                     msg_Err( p_sys->p_input,
                              "ES_OUT_SET_(GROUP_)PCR  is called too late (pts_delay increased to %d ms)",
                              (int)(i_pts_delay/1000) );
-                }
 
-                /* Force a rebufferization when we are too late */
+                    /* Force a rebufferization when we are too late */
 
-                /* It is not really good, as we throw away already buffered data
-                 * TODO have a mean to correctly reenter bufferization */
-                es_out_Control( out, ES_OUT_RESET_PCR );
+                    /* It is not really good, as we throw away already buffered data
+                     * TODO have a mean to correctly reenter bufferization */
+                    es_out_Control( out, ES_OUT_RESET_PCR );
+                }
 
                 es_out_SetJitter( out, i_pts_delay_base, i_pts_delay - i_pts_delay_base, p_sys->i_cr_average );
             }
@@ -2486,7 +2485,7 @@ static int EsOutControlLocked( es_out_t *out, int i_query, va_list args )
     {
         const int i_id = (int)va_arg( args, int );
         es_out_id_t *p_es = EsOutGetFromID( out, i_id );
-        int i_new_query;
+        int i_new_query = 0;
 
         switch( i_query )
         {
@@ -2494,7 +2493,7 @@ static int EsOutControlLocked( es_out_t *out, int i_query, va_list args )
         case ES_OUT_RESTART_ES_BY_ID:     i_new_query = ES_OUT_RESTART_ES; break;
         case ES_OUT_SET_ES_DEFAULT_BY_ID: i_new_query = ES_OUT_SET_ES_DEFAULT; break;
         default:
-          assert(0);
+          vlc_assert_unreachable();
         }
         /* TODO if the lock is made non recursive it should be changed */
         int i_ret = es_out_Control( out, i_new_query, p_es );
@@ -2685,15 +2684,8 @@ static int EsOutControlLocked( es_out_t *out, int i_query, va_list args )
     {
         for (int i = 0; i < p_sys->i_es; i++) {
             es_out_id_t *id = p_sys->es[i];
-            decoder_t *p_dec = id->p_dec;
-            if (!p_dec)
-                continue;
-            block_t *p_block = block_Alloc(0);
-            if( !p_block )
-                break;
-
-            p_block->i_flags |= BLOCK_FLAG_CORE_EOS;
-            input_DecoderDecode(p_dec, p_block, false);
+            if (id->p_dec != NULL)
+                input_DecoderDrain(id->p_dec);
         }
         return VLC_SUCCESS;
     }
@@ -2750,11 +2742,7 @@ static char *LanguageGetName( const char *psz_code )
     }
     else
     {
-        if( *pl->psz_native_name )
-        {
-            return strdup( pl->psz_native_name );
-        }
-        return strdup( pl->psz_eng_name );
+        return strdup( vlc_gettext(pl->psz_eng_name) );
     }
 }
 
@@ -2769,16 +2757,12 @@ static char *LanguageGetCode( const char *psz_lang )
     for( pl = p_languages; pl->psz_eng_name != NULL; pl++ )
     {
         if( !strcasecmp( pl->psz_eng_name, psz_lang ) ||
-            !strcasecmp( pl->psz_native_name, psz_lang ) ||
             !strcasecmp( pl->psz_iso639_1, psz_lang ) ||
             !strcasecmp( pl->psz_iso639_2T, psz_lang ) ||
             !strcasecmp( pl->psz_iso639_2B, psz_lang ) )
-            break;
+            return strdup( pl->psz_iso639_1 );
     }
 
-    if( pl->psz_eng_name != NULL )
-        return strdup( pl->psz_iso639_1 );
-
     return strdup("??");
 }
 
@@ -2836,7 +2820,7 @@ static char **LanguageSplit( const char *psz_langs, bool b_default_any )
     return ppsz;
 }
 
-static int LanguageArrayIndex( char **ppsz_langs, char *psz_lang )
+static int LanguageArrayIndex( char **ppsz_langs, const char *psz_lang )
 {
     if( !ppsz_langs || !psz_lang )
         return -1;
@@ -2909,10 +2893,10 @@ static void EsOutUpdateInfo( es_out_t *out, es_out_id_t *es, const es_format_t *
         vlc_fourcc_GetDescription( p_fmt_es->i_cat, p_fmt_es->i_codec );
     const vlc_fourcc_t i_codec_fourcc = ( p_fmt_es->i_original_fourcc )?
                                p_fmt_es->i_original_fourcc : p_fmt_es->i_codec;
-    if( psz_codec_description )
+    if( psz_codec_description && *psz_codec_description )
         info_category_AddInfo( p_cat, _("Codec"), "%s (%.4s)",
                                psz_codec_description, (char*)&i_codec_fourcc );
-    else
+    else if ( i_codec_fourcc != VLC_FOURCC(0,0,0,0) )
         info_category_AddInfo( p_cat, _("Codec"), "%.4s",
                                (char*)&i_codec_fourcc );