]> git.sesse.net Git - vlc/blobdiff - src/input/es_out.c
Do not delay rate change after end of pause.
[vlc] / src / input / es_out.c
index 0c8c1d902ea4bf241489dc737305fc3d0f8dceac..3762e840e11f86169307bc050994a63a9096fe79 100644 (file)
@@ -37,6 +37,7 @@
 #include <vlc_es_out.h>
 #include <vlc_block.h>
 #include <vlc_aout.h>
+#include <vlc_fourcc.h>
 
 #include "input_internal.h"
 #include "clock.h"
@@ -211,7 +212,7 @@ static inline int EsOutGetClosedCaptionsChannel( vlc_fourcc_t fcc )
 }
 static inline bool EsFmtIsTeletext( const es_format_t *p_fmt )
 {
-    return p_fmt->i_cat == SPU_ES && p_fmt->i_codec == VLC_FOURCC( 't', 'e', 'l', 'x' );
+    return p_fmt->i_cat == SPU_ES && p_fmt->i_codec == VLC_CODEC_TELETEXT;
 }
 
 /*****************************************************************************
@@ -572,9 +573,7 @@ static void EsOutChangeRate( es_out_t *out, int i_rate )
     es_out_sys_t      *p_sys = out->p_sys;
 
     p_sys->i_rate = i_rate;
-
-    if( !p_sys->b_paused )
-        EsOutProgramsChangeRate( out );
+    EsOutProgramsChangeRate( out );
 }
 
 static void EsOutChangePosition( es_out_t *out )
@@ -1029,9 +1028,10 @@ static es_out_pgrm_t *EsOutProgramAdd( es_out_t *out, int i_group )
         free( p_pgrm );
         return NULL;
     }
+    if( p_sys->b_paused )
+        input_clock_ChangePause( p_pgrm->p_clock, p_sys->b_paused, p_sys->i_pause_date );
     input_clock_SetJitter( p_pgrm->p_clock, p_sys->i_pts_delay, p_sys->i_cr_average );
 
-
     /* Append it */
     TAB_APPEND( p_sys->i_pgrm, p_sys->pgrm, p_pgrm );
 
@@ -1205,8 +1205,10 @@ static void EsOutProgramMeta( es_out_t *out, int i_group, vlc_meta_t *p_meta )
     char ** ppsz_all_keys = vlc_dictionary_all_keys( &p_meta->extra_tags );
     for( i = 0; ppsz_all_keys[i]; i++ )
     {
-        input_Control( p_input, INPUT_ADD_INFO, psz_cat, _(ppsz_all_keys[i]),
-                       vlc_dictionary_value_for_key( &p_meta->extra_tags, ppsz_all_keys[i] ) );
+        input_Control( p_input, INPUT_ADD_INFO, psz_cat,
+                       vlc_gettext(ppsz_all_keys[i]),
+                       vlc_dictionary_value_for_key( &p_meta->extra_tags,
+                       ppsz_all_keys[i] ) );
         free( ppsz_all_keys[i] );
     }
     free( ppsz_all_keys );
@@ -1384,6 +1386,10 @@ static es_out_id_t *EsOutAdd( es_out_t *out, const es_format_t *fmt )
     es_format_Copy( &es->fmt, fmt );
     if( es->fmt.i_id < 0 )
         es->fmt.i_id = out->p_sys->i_id;
+    if( !es->fmt.i_original_fourcc )
+        es->fmt.i_original_fourcc = es->fmt.i_codec;
+    es->fmt.i_codec = vlc_fourcc_GetCodec( es->fmt.i_cat, es->fmt.i_codec );
+
     es->i_id = es->fmt.i_id;
     es->i_meta_id = out->p_sys->i_id;
     es->b_scrambled = false;
@@ -1682,7 +1688,7 @@ static void EsOutSelect( es_out_t *out, es_out_id_t *es, bool b_force )
                 break;
             }
         }
-        var_Change( p_sys->p_input, "programs", VLC_VAR_FREELIST, &val, NULL );
+        var_FreeList( &val, NULL );
     }
     else if( p_sys->i_mode == ES_OUT_MODE_AUTO )
     {
@@ -1872,14 +1878,34 @@ static int EsOutSend( es_out_t *out, es_out_id_t *es, block_t *p_block )
         return VLC_SUCCESS;
     }
 
+    /* Check for sout mode */
+    if( out->b_sout )
+    {
+        /* FIXME review this, proper lock may be missing */
+        if( p_input->p->p_sout->i_out_pace_nocontrol > 0 &&
+            p_input->p->b_out_pace_control )
+        {
+            msg_Dbg( p_input, "switching to sync mode" );
+            p_input->p->b_out_pace_control = false;
+        }
+        else if( p_input->p->p_sout->i_out_pace_nocontrol <= 0 &&
+                 !p_input->p->b_out_pace_control )
+        {
+            msg_Dbg( p_input, "switching to async mode" );
+            p_input->p->b_out_pace_control = true;
+        }
+    }
+
     /* Decode */
     if( es->p_dec_record )
     {
         block_t *p_dup = block_Duplicate( p_block );
         if( p_dup )
-            input_DecoderDecode( es->p_dec_record, p_dup );
+            input_DecoderDecode( es->p_dec_record, p_dup,
+                                 p_input->p->b_out_pace_control );
     }
-    input_DecoderDecode( es->p_dec, p_block );
+    input_DecoderDecode( es->p_dec, p_block,
+                         p_input->p->b_out_pace_control );
 
     es_format_t fmt_dsc;
     vlc_meta_t  *p_meta_dsc;
@@ -1898,19 +1924,13 @@ static int EsOutSend( es_out_t *out, es_out_id_t *es, block_t *p_block )
     input_DecoderIsCcPresent( es->p_dec, pb_cc );
     for( int i = 0; i < 4; i++ )
     {
-        static const vlc_fourcc_t fcc[4] = {
-            VLC_FOURCC('c', 'c', '1', ' '),
-            VLC_FOURCC('c', 'c', '2', ' '),
-            VLC_FOURCC('c', 'c', '3', ' '),
-            VLC_FOURCC('c', 'c', '4', ' '),
-        };
         es_format_t fmt;
 
         if(  es->pb_cc_present[i] || !pb_cc[i] )
             continue;
         msg_Dbg( p_input, "Adding CC track %d for es[%d]", 1+i, es->i_id );
 
-        es_format_Init( &fmt, SPU_ES, fcc[i] );
+        es_format_Init( &fmt, SPU_ES, EsOutFourccClosedCaptions[i] );
         fmt.i_group = es->fmt.i_group;
         if( asprintf( &fmt.psz_description,
                       _("Closed captions %u"), 1 + i ) == -1 )
@@ -2190,6 +2210,7 @@ static int EsOutControlLocked( es_out_t *out, int i_query, va_list args )
             int            i_group = 0;
             int64_t        i_pcr;
 
+            /* Search program */
             if( i_query == ES_OUT_SET_PCR )
             {
                 p_pgrm = p_sys->p_pgrm;
@@ -2205,14 +2226,46 @@ static int EsOutControlLocked( es_out_t *out, int i_query, va_list args )
                 return VLC_EGENERIC;
 
             i_pcr = (int64_t)va_arg( args, int64_t );
-            /* search program
-             * TODO do not use mdate() but proper stream acquisition date */
+            if( i_pcr <= VLC_TS_INVALID )
+            {
+                msg_Err( p_sys->p_input, "Invalid PCR value in ES_OUT_SET_(GROUP_)PCR !" );
+                return VLC_EGENERIC;
+            }
+
+            /* TODO do not use mdate() but proper stream acquisition date */
+            bool b_late;
             input_clock_Update( p_pgrm->p_clock, VLC_OBJECT(p_sys->p_input),
+                                &b_late,
                                 p_sys->p_input->p->b_can_pace_control || p_sys->b_buffering, i_pcr, mdate() );
-            /* Check buffering state on master clock update */
-            if( p_sys->b_buffering && p_pgrm == p_sys->p_pgrm )
-                EsOutDecodersStopBuffering( out, false );
 
+            if( p_pgrm == p_sys->p_pgrm )
+            {
+                if( p_sys->b_buffering )
+                {
+                    /* Check buffering state on master clock update */
+                    EsOutDecodersStopBuffering( out, false );
+                }
+                else if( b_late )
+                {
+                    mtime_t i_pts_delay = input_clock_GetJitter( p_pgrm->p_clock );
+
+                    /* Avoid dangerously high value */
+                    const mtime_t i_pts_delay_max = 30000000;
+                    if( i_pts_delay > i_pts_delay_max )
+                        i_pts_delay = __MAX( i_pts_delay_max, p_sys->i_pts_delay );
+
+                    /* Force a rebufferization when we are too late */
+                    msg_Err( p_sys->p_input,
+                             "ES_OUT_SET_(GROUP_)PCR  is called too late, increasing pts_delay to %d ms",
+                             (int)(i_pts_delay/1000) );
+
+                    /* 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_Control( out, ES_OUT_SET_JITTER, i_pts_delay, p_sys->i_cr_average );
+                }
+            }
             return VLC_SUCCESS;
         }
 
@@ -2417,20 +2470,24 @@ static int EsOutControlLocked( es_out_t *out, int i_query, va_list args )
             mtime_t i_time = (mtime_t)va_arg( args, mtime_t );
             mtime_t i_length = (mtime_t)va_arg( args, mtime_t );
 
-            /* Fix for buffering delay */
-            const mtime_t i_delay = EsOutGetBuffering( out );
+            input_SendEventLength( p_sys->p_input, i_length );
+
+            if( !p_sys->b_buffering )
+            {
+                /* Fix for buffering delay */
+                const mtime_t i_delay = EsOutGetBuffering( out );
 
-            i_time -= i_delay;
-            if( i_time < 0 )
-                i_time = 0;
+                i_time -= i_delay;
+                if( i_time < 0 )
+                    i_time = 0;
 
-            if( i_length > 0 )
-                f_position -= (double)i_delay / i_length;
-            if( f_position < 0 )
-                f_position = 0;
+                if( i_length > 0 )
+                    f_position -= (double)i_delay / i_length;
+                if( f_position < 0 )
+                    f_position = 0;
 
-            if( !p_sys->b_buffering )
-                input_SendEventTimes( p_sys->p_input, f_position, i_time, i_length );
+                input_SendEventPosition( p_sys->p_input, f_position, i_time );
+            }
             return VLC_SUCCESS;
         }
         case ES_OUT_SET_JITTER:
@@ -2519,7 +2576,7 @@ static char *LanguageGetCode( const char *psz_lang )
     if( psz_lang == NULL || *psz_lang == '\0' )
         return strdup("??");
 
-    for( pl = p_languages; pl->psz_iso639_1 != NULL; pl++ )
+    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 ) ||
@@ -2529,7 +2586,7 @@ static char *LanguageGetCode( const char *psz_lang )
             break;
     }
 
-    if( pl->psz_iso639_1 != NULL )
+    if( pl->psz_eng_name != NULL )
         return strdup( pl->psz_iso639_1 );
 
     return strdup("??");
@@ -2645,8 +2702,15 @@ static void EsOutUpdateInfo( es_out_t *out, es_out_id_t *es, const es_format_t *
         input_Control( p_input, INPUT_ADD_INFO, psz_cat, _("Original ID"),
                        "%d", es->i_id );
 
-    input_Control( p_input, INPUT_ADD_INFO, psz_cat, _("Codec"),
-                   "%.4s", (char*)&p_fmt_es->i_codec );
+    const char *psz_codec_description =
+        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_codec;
+    if( psz_codec_description )
+        input_Control( p_input, INPUT_ADD_INFO, psz_cat, _("Codec"),
+                       "%s (%.4s)", psz_codec_description, (char*)&i_codec_fourcc );
+    else
+        input_Control( p_input, INPUT_ADD_INFO, psz_cat, _("Codec"),
+                       "%.4s", (char*)&i_codec_fourcc );
 
     if( es->psz_language && *es->psz_language )
         input_Control( p_input, INPUT_ADD_INFO, psz_cat, _("Language"),
@@ -2756,7 +2820,8 @@ static void EsOutUpdateInfo( es_out_t *out, es_out_id_t *es, const es_format_t *
             char *psz_value = vlc_dictionary_value_for_key( &p_meta->extra_tags, psz_key );
 
             if( psz_value )
-                input_Control( p_input, INPUT_ADD_INFO, psz_cat, _(psz_key), _(psz_value) );
+                input_Control( p_input, INPUT_ADD_INFO, psz_cat,
+                               vlc_gettext(psz_key), vlc_gettext(psz_value) );
             free( psz_key );
         }
         free( ppsz_all_keys );