[vlc-devel] [PATCH 1/5] Subtitle delay : fixed sync problem that breaks audio under linux

Pascal Thomet pthomet at gmail.com
Mon Jun 9 21:00:23 CEST 2014


    This is a follow-up to a patch I made last year
    (f7211d5efa4cd9ef392230d85fdf3470edefab39)
    When developping it I stumbled upon a prexisting bug that I could
    not correct at that time.

     Bug reproduction steps :
     ************************
     *under linux* (will not happen under OSX)
    - launch a video together with an *external* subtitle file
      (.srt file for example),
    - press Shift-H ("bookmark audio time"),
    - wait 5 seconds
    - press Shift-J ("bookmark subtitle time")
    - press Shift-K ("sync bookmarks")
    ==> the audio is broken...
    (AFAIK this bug seems not to be mentioned on trac.videolan.org)

    Correction details :
    ********************
    * Beware, there were two preexisting ways of dealing with subtitles :
	- File subtitles are handled by vlc/modules/demux/subtitle.c
        - Other subtitles are handled by vlc/modules/codec/avcodec/subtitle.c
    * A new variable was added : "sub-isfilesub".
         - equal to 1 when the subtitle is read from a file
           (for example a .srt file),
         - equal to 0 otherwise (for example dvd subtitles)
    * The subtitle delay is still stored inside "spu-delay".

    * In the case of non file subtitles, the subtitle delay
      is implemented as before: a change of "spu-delay"
      will ultimately lead to a call to UpdatePtsDelay().
    * In the case of file subtitles, the subtitle delay is implemented
      inside vlc/modules/demux/subtitles.c by the function
      adjust_subtitle_time()
      For file subtitles, the situation is different : all subtitles
      are already in memory, so that applying a delay is simpler.
    * no more delay calculations inside hotkeys.c, everything is
      handled inside vlc/modules/demux/subtitle.c through callbacks.
     This provides a better encapsulation a prepares the addition of a
     gui in the track synchronization window (patch to come later)

Note :
* this patch corrects the aforementioned bug
* however the subtitles sync hotkeys which I introduced one year ago
(Shift-H, Shift-J and Shift-K) now only work with *file subtitles*.
This should not be a problem, as I do not think this feature is of any use for DVD / DVB subtitles.
In the case of non file subtitles, they will simply not be linked to any callback.
---
 modules/control/hotkeys.c | 113 +++++++++----------------
 modules/demux/subtitle.c  | 209 ++++++++++++++++++++++++++++++++++++++++------
 src/input/input.c         |   9 +-
 src/input/var.c           |  12 ++-
 4 files changed, 241 insertions(+), 102 deletions(-)

diff --git a/modules/control/hotkeys.c b/modules/control/hotkeys.c
index 1e7fcdf..e32c389 100644
--- a/modules/control/hotkeys.c
+++ b/modules/control/hotkeys.c
@@ -48,13 +48,6 @@ struct intf_sys_t
 {
     vout_thread_t      *p_last_vout;
     int slider_chan;
-
-    /*subtitle_delaybookmarks: placeholder for storing subtitle sync timestamps*/
-    struct
-    {
-        int64_t i_time_subtitle;
-        int64_t i_time_audio;
-    } subtitle_delaybookmarks;
 };
 
 /*****************************************************************************
@@ -108,10 +101,14 @@ static int Open( vlc_object_t *p_this )
     p_intf->p_sys = p_sys;
 
     p_sys->p_last_vout = NULL;
-    p_sys->subtitle_delaybookmarks.i_time_audio = 0;
-    p_sys->subtitle_delaybookmarks.i_time_subtitle = 0;
 
+    /* key-osdmessage : variable to be used from external modules
+     * in order to display an osd message
+     * as an informative response after a hotkey press */
+    var_Create (p_intf->p_libvlc, "key-osdmessage", VLC_VAR_STRING);    
+    var_AddCallback( p_intf->p_libvlc, "key-osdmessage", ActionEvent, p_intf );
     var_AddCallback( p_intf->p_libvlc, "key-action", ActionEvent, p_intf );
+    
     return VLC_SUCCESS;
 }
 
@@ -123,6 +120,8 @@ static void Close( vlc_object_t *p_this )
     intf_thread_t *p_intf = (intf_thread_t *)p_this;
     intf_sys_t *p_sys = p_intf->p_sys;
 
+    var_Destroy( p_intf->p_libvlc, "key-osdmessage" );
+    var_DelCallback( p_intf->p_libvlc, "key-osdmessage", ActionEvent, p_intf );
     var_DelCallback( p_intf->p_libvlc, "key-action", ActionEvent, p_intf );
 
     /* Destroy structure */
@@ -404,76 +403,21 @@ static int PutAction( intf_thread_t *p_intf, int i_action )
             break;
 
         case ACTIONID_SUBSYNC_MARKAUDIO:
-        {
-            p_sys->subtitle_delaybookmarks.i_time_audio = mdate();
-            DisplayMessage( p_vout, _("Sub sync: bookmarked audio time"));
+            /* trigger callback in module subtitle.c */
+            var_SetInteger(p_input, "sub-bookmarkaudio", 0);
             break;
-        }
         case ACTIONID_SUBSYNC_MARKSUB:
-            if( p_input )
-            {
-                vlc_value_t val, list, list2;
-                int i_count;
-                var_Get( p_input, "spu-es", &val );
-
-                var_Change( p_input, "spu-es", VLC_VAR_GETCHOICES,
-                            &list, &list2 );
-                i_count = list.p_list->i_count;
-                if( i_count < 1 || val.i_int < 0 )
-                {
-                    DisplayMessage( p_vout, _("No active subtitle") );
-                    var_FreeList( &list, &list2 );
-                    break;
-                }
-                p_sys->subtitle_delaybookmarks.i_time_subtitle = mdate();
-                DisplayMessage( p_vout,
-                                _("Sub sync: bookmarked subtitle time"));
-                var_FreeList( &list, &list2 );
-            }
+            /* trigger callback in module subtitle.c */
+            var_SetInteger(p_input, "sub-bookmarksubtitle", 0);
             break;
         case ACTIONID_SUBSYNC_APPLY:
-        {
-            /* Warning! Can yield a pause in the playback.
-             * For example, the following succession of actions will yield a 5 second delay :
-             * - Pressing Shift-H (ACTIONID_SUBSYNC_MARKAUDIO)
-             * - wait 5 second
-             * - Press Shift-J (ACTIONID_SUBSYNC_MARKSUB)
-             * - Press Shift-K (ACTIONID_SUBSYNC_APPLY)
-             * --> 5 seconds pause
-             * This is due to var_SetTime() (and ultimately UpdatePtsDelay())
-             * which causes the video to pause for an equivalent duration
-             * (This problem is also present in the "Track synchronization" window) */
-            if ( p_input )
-            {
-                if ( (p_sys->subtitle_delaybookmarks.i_time_audio == 0) || (p_sys->subtitle_delaybookmarks.i_time_subtitle == 0) )
-                {
-                    DisplayMessage( p_vout, _( "Sub sync: set bookmarks first!" ) );
-                }
-                else
-                {
-                    int64_t i_current_subdelay = var_GetTime( p_input, "spu-delay" );
-                    int64_t i_additional_subdelay = p_sys->subtitle_delaybookmarks.i_time_audio - p_sys->subtitle_delaybookmarks.i_time_subtitle;
-                    int64_t i_total_subdelay = i_current_subdelay + i_additional_subdelay;
-                    var_SetTime( p_input, "spu-delay", i_total_subdelay);
-                    ClearChannels( p_intf, p_vout );
-                    DisplayMessage( p_vout, _( "Sub sync: corrected %i ms (total delay = %i ms)" ),
-                                            (int)(i_additional_subdelay / 1000),
-                                            (int)(i_total_subdelay / 1000) );
-                    p_sys->subtitle_delaybookmarks.i_time_audio = 0;
-                    p_sys->subtitle_delaybookmarks.i_time_subtitle = 0;
-                }
-            }
+            /* trigger callback in module subtitle.c */
+            var_SetInteger(p_input, "sub-syncbookmarks", 0);
             break;
-        }
         case ACTIONID_SUBSYNC_RESET:
-        {
-            var_SetTime( p_input, "spu-delay", 0);
-            ClearChannels( p_intf, p_vout );
-            DisplayMessage( p_vout, _( "Sub sync: delay reset" ) );
-            p_sys->subtitle_delaybookmarks.i_time_audio = 0;
-            p_sys->subtitle_delaybookmarks.i_time_subtitle = 0;
+            /* trigger callback in module subtitle.c */
+            var_SetInteger(p_input, "sub-syncreset", 0);
             break;
-        }
 
         case ACTIONID_SUBDELAY_DOWN:
         case ACTIONID_SUBDELAY_UP:
@@ -1067,7 +1011,30 @@ static int ActionEvent( vlc_object_t *libvlc, char const *psz_var,
     (void)psz_var;
     (void)oldval;
 
-    return PutAction( p_intf, newval.i_int );
+    if ( strcmp( psz_var, "key-osdmessage") == 0)
+    {
+        if ( strlen(newval.psz_string) > 0 )
+        {
+            playlist_t *p_playlist = pl_Get( p_intf );
+            input_thread_t *p_input = playlist_CurrentInput( p_playlist );
+            if (p_input)
+            {
+                vout_thread_t *p_vout = p_input ? input_GetVout( p_input ) : NULL;// XXXXDZFEEGVDS
+                if( p_vout )
+                {
+                    DisplayMessage(p_vout, "%s", newval.psz_string);
+                    vlc_object_release( p_vout );
+                }
+                vlc_object_release(p_input);
+            }
+
+        }
+        return VLC_SUCCESS;        
+    }
+    else
+    {
+        return PutAction( p_intf, newval.i_int );
+    }
 }
 
 static void PlayBookmark( intf_thread_t *p_intf, int i_num )
diff --git a/modules/demux/subtitle.c b/modules/demux/subtitle.c
index 29922cc..81d0a76 100644
--- a/modules/demux/subtitle.c
+++ b/modules/demux/subtitle.c
@@ -35,6 +35,7 @@
 #include <vlc_plugin.h>
 #include <vlc_input.h>
 #include <vlc_memory.h>
+#include <vlc_interface.h>
 
 #include <ctype.h>
 
@@ -127,6 +128,16 @@ static void TextUnload( text_t * );
 
 typedef struct
 {
+    /* 
+     * i_start and i_stop are the original subtitle timestamps.
+     * 
+     * In order to take into account the subtitle delay (spu-delay), 
+     * please use 
+     *   adjust_subtitle_time(p_demux, my_subtitle_t.i_start)
+     * instead of 
+     *   my_subtitle_t.i_start 
+     * (same goes for i_stop)
+     */
     int64_t i_start;
     int64_t i_stop;
 
@@ -141,6 +152,7 @@ struct demux_sys_t
     es_out_id_t *es;
 
     int64_t     i_next_demux_date;
+    int64_t     i_last_demux_date;
     int64_t     i_microsecperframe;
 
     char        *psz_header;
@@ -166,6 +178,14 @@ struct demux_sys_t
         float f_total;
         float f_factor;
     } mpsub;
+    
+    /*subtitle_delaybookmarks: placeholder for storing subtitle sync timestamps*/
+    struct
+    {
+        int64_t i_time_subtitle;
+        int64_t i_time_audio;
+    } subtitle_delaybookmarks;
+
 };
 
 static int  ParseMicroDvd   ( demux_t *, subtitle_t *, int );
@@ -224,6 +244,76 @@ static int Control( demux_t *, int, va_list );
 
 static void Fix( demux_t * );
 static char * get_language_from_filename( const char * );
+static int64_t adjust_subtitle_time( demux_t *, int64_t);
+static int set_current_subtitle_by_time(demux_t *p_demux, int64_t i64_when);
+
+
+/*****************************************************************************
+ * external callbacks
+ *****************************************************************************/
+int subtitle_external_callback ( vlc_object_t * ,char const *, vlc_value_t old_value, vlc_value_t new_value, void * callback_data);
+int subtitle_external_callback ( 
+        vlc_object_t * object,
+        char const * variable_name,
+        vlc_value_t old_value,
+        vlc_value_t new_value,
+        void * callback_data_p_demux)
+{
+    demux_t *p_demux = (demux_t*)callback_data_p_demux;
+    (void)object;
+    (void)old_value;
+    (void)new_value;
+    
+    demux_sys_t *p_sys = p_demux->p_sys;
+    
+    if ( ! strcmp(variable_name, "sub-bookmarkaudio") )
+    {
+        p_sys->subtitle_delaybookmarks.i_time_audio = p_sys->i_last_demux_date;
+        var_SetString(p_demux->p_libvlc, "key-osdmessage", _("Sub sync: bookmarked audio time"));
+    }
+    if ( ! strcmp(variable_name, "sub-bookmarksubtitle") )
+    {
+        p_sys->subtitle_delaybookmarks.i_time_subtitle = p_sys->i_last_demux_date;
+        var_SetString(p_demux->p_libvlc, "key-osdmessage", _("Sub sync: bookmarked subtitle time"));
+    }
+    if ( ! strcmp(variable_name, "sub-syncbookmarks") )
+    {
+        if ( (p_sys->subtitle_delaybookmarks.i_time_audio == 0) || (p_sys->subtitle_delaybookmarks.i_time_subtitle == 0) )
+        {
+            var_SetString(p_demux->p_libvlc, "key-osdmessage", _("Sub sync: set bookmarks first!"));
+        }
+        else
+        {
+            int64_t i_current_subdelay = var_GetTime( p_demux->p_parent, "spu-delay" );
+            int64_t i_additional_subdelay = p_sys->subtitle_delaybookmarks.i_time_audio - p_sys->subtitle_delaybookmarks.i_time_subtitle;
+            int64_t i_total_subdelay = i_current_subdelay + i_additional_subdelay;
+            var_SetTime( p_demux->p_parent, "spu-delay", i_total_subdelay);
+            char message[150];
+            snprintf(message, 150, 
+                    _( "Sub sync: corrected %i ms (total delay = %i ms)" ),
+                                    (int)(i_additional_subdelay / 1000),
+                                    (int)(i_total_subdelay / 1000) );
+            var_SetString(p_demux->p_libvlc, "key-osdmessage", message);
+            p_sys->subtitle_delaybookmarks.i_time_audio = 0;
+            p_sys->subtitle_delaybookmarks.i_time_subtitle = 0;
+        }
+    }
+    if ( ! strcmp(variable_name, "sub-syncreset") )
+    {
+        var_SetTime( p_demux->p_parent, "spu-delay", 0);
+        p_sys->subtitle_delaybookmarks.i_time_audio = 0;
+        p_sys->subtitle_delaybookmarks.i_time_subtitle = 0;
+        var_SetString(p_demux->p_libvlc, "key-osdmessage", _("Sub sync: delay reset"));
+        return VLC_SUCCESS;
+    }    
+    if ( ! strcmp(variable_name, "spu-delau") )
+    {
+        set_current_subtitle_by_time(p_demux, p_sys->i_last_demux_date);
+    }
+    return VLC_SUCCESS;
+}
+
+
 
 /*****************************************************************************
  * Module initializer
@@ -249,7 +339,29 @@ static int Open ( vlc_object_t *p_this )
     p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) );
     if( p_sys == NULL )
         return VLC_ENOMEM;
-
+    
+    /* reset spu-delay at Open*/
+    var_SetTime( p_demux->p_parent, "spu-delay", 0 );
+    /* this is a file subtitle*/
+    var_SetInteger(p_demux->p_parent, "sub-isfilesub", 1);
+    
+    
+    p_sys->subtitle_delaybookmarks.i_time_audio = 0;
+    p_sys->subtitle_delaybookmarks.i_time_subtitle = 0;
+
+    
+    /* Add callbacks*/
+    var_Create(p_demux->p_parent, "sub-bookmarkaudio", VLC_VAR_INTEGER);
+    var_Create(p_demux->p_parent, "sub-bookmarksubtitle", VLC_VAR_INTEGER);
+    var_Create(p_demux->p_parent, "sub-syncbookmarks", VLC_VAR_INTEGER);
+    var_Create(p_demux->p_parent, "sub-syncreset", VLC_VAR_INTEGER);
+    var_AddCallback( p_demux->p_parent, "sub-bookmarkaudio", &subtitle_external_callback, p_this );
+    var_AddCallback( p_demux->p_parent, "sub-bookmarksubtitle", &subtitle_external_callback, p_this );
+    var_AddCallback( p_demux->p_parent, "sub-syncbookmarks", &subtitle_external_callback, p_this );
+    var_AddCallback( p_demux->p_parent, "sub-syncreset", &subtitle_external_callback, p_this );
+    var_AddCallback( p_demux->p_parent, "spu-delay", &subtitle_external_callback, p_this );
+
+    
     p_sys->psz_header         = NULL;
     p_sys->i_subtitle         = 0;
     p_sys->i_subtitles        = 0;
@@ -579,8 +691,23 @@ static void Close( vlc_object_t *p_this )
 {
     demux_t *p_demux = (demux_t*)p_this;
     demux_sys_t *p_sys = p_demux->p_sys;
-    int i;
 
+    var_SetInteger(p_demux->p_parent, "sub-isfilesub", 0);
+
+    /* Remove callbacks*/
+    var_DelCallback( p_demux->p_parent, "sub-bookmarkaudio", &subtitle_external_callback, p_this );
+    var_DelCallback( p_demux->p_parent, "sub-bookmarksubtitle", &subtitle_external_callback, p_this );
+    var_DelCallback( p_demux->p_parent, "sub-syncbookmarks", &subtitle_external_callback, p_this );
+    var_DelCallback( p_demux->p_parent, "sub-syncreset", &subtitle_external_callback, p_this );
+
+    var_DelCallback( p_demux->p_parent, "spu-delay", &subtitle_external_callback, p_this );
+    var_Destroy(p_demux->p_parent, "sub-bookmarkaudio");
+    var_Destroy(p_demux->p_parent, "sub-bookmarksubtitle");
+    var_Destroy(p_demux->p_parent, "sub-syncbookmarks");
+    var_Destroy(p_demux->p_parent, "sub-syncreset");
+
+
+    int i;
     for( i = 0; i < p_sys->i_subtitles; i++ )
         free( p_sys->subtitle[i].psz_text );
     free( p_sys->subtitle );
@@ -591,6 +718,31 @@ static void Close( vlc_object_t *p_this )
 /*****************************************************************************
  * Control:
  *****************************************************************************/
+
+/* Utlity function : sets the current subtitle index (p_sys->i_subtitle)
+ * based on the time 
+ */
+static int set_current_subtitle_by_time(demux_t *p_demux, int64_t i64_when)
+{
+    demux_sys_t *p_sys = p_demux->p_sys;
+
+    p_sys->i_subtitle = 0;
+    while( p_sys->i_subtitle < p_sys->i_subtitles )
+    {
+        const subtitle_t *p_subtitle = &p_sys->subtitle[p_sys->i_subtitle];
+        if( adjust_subtitle_time(p_demux, p_subtitle->i_start) > i64_when )
+            break;
+        if( p_subtitle->i_stop > p_subtitle->i_start && adjust_subtitle_time(p_demux, p_subtitle->i_stop) > i64_when )
+            break;
+
+        p_sys->i_subtitle++;
+    }
+
+    if( p_sys->i_subtitle >= p_sys->i_subtitles )
+        return VLC_EGENERIC;
+    return VLC_SUCCESS;
+}
+
 static int Control( demux_t *p_demux, int i_query, va_list args )
 {
     demux_sys_t *p_sys = p_demux->p_sys;
@@ -608,29 +760,14 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
             pi64 = (int64_t*)va_arg( args, int64_t * );
             if( p_sys->i_subtitle < p_sys->i_subtitles )
             {
-                *pi64 = p_sys->subtitle[p_sys->i_subtitle].i_start;
+                *pi64 = adjust_subtitle_time(p_demux, p_sys->subtitle[p_sys->i_subtitle].i_start);
                 return VLC_SUCCESS;
             }
             return VLC_EGENERIC;
 
         case DEMUX_SET_TIME:
             i64 = (int64_t)va_arg( args, int64_t );
-            p_sys->i_subtitle = 0;
-            while( p_sys->i_subtitle < p_sys->i_subtitles )
-            {
-                const subtitle_t *p_subtitle = &p_sys->subtitle[p_sys->i_subtitle];
-
-                if( p_subtitle->i_start > i64 )
-                    break;
-                if( p_subtitle->i_stop > p_subtitle->i_start && p_subtitle->i_stop > i64 )
-                    break;
-
-                p_sys->i_subtitle++;
-            }
-
-            if( p_sys->i_subtitle >= p_sys->i_subtitles )
-                return VLC_EGENERIC;
-            return VLC_SUCCESS;
+            return set_current_subtitle_by_time(p_demux, i64);
 
         case DEMUX_GET_POSITION:
             pf = (double*)va_arg( args, double * );
@@ -640,7 +777,8 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
             }
             else if( p_sys->i_subtitles > 0 )
             {
-                *pf = (double)p_sys->subtitle[p_sys->i_subtitle].i_start /
+                int64_t i_start_adjust = adjust_subtitle_time(p_demux, p_sys->subtitle[p_sys->i_subtitle].i_start);
+                *pf = (double) ( i_start_adjust ) /
                       (double)p_sys->i_length;
             }
             else
@@ -655,7 +793,7 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
 
             p_sys->i_subtitle = 0;
             while( p_sys->i_subtitle < p_sys->i_subtitles &&
-                   p_sys->subtitle[p_sys->i_subtitle].i_start < i64 )
+                   adjust_subtitle_time(p_demux, p_sys->subtitle[p_sys->i_subtitle].i_start) < i64 )
             {
                 p_sys->i_subtitle++;
             }
@@ -693,15 +831,15 @@ static int Demux( demux_t *p_demux )
     if( p_sys->i_subtitle >= p_sys->i_subtitles )
         return 0;
 
-    i_maxdate = p_sys->i_next_demux_date - var_GetTime( p_demux->p_parent, "spu-delay" );;
+    i_maxdate = p_sys->i_next_demux_date;
     if( i_maxdate <= 0 && p_sys->i_subtitle < p_sys->i_subtitles )
     {
         /* Should not happen */
-        i_maxdate = p_sys->subtitle[p_sys->i_subtitle].i_start + 1;
+        i_maxdate = adjust_subtitle_time(p_demux, p_sys->subtitle[p_sys->i_subtitle].i_start) + 1;
     }
-
+    
     while( p_sys->i_subtitle < p_sys->i_subtitles &&
-           p_sys->subtitle[p_sys->i_subtitle].i_start < i_maxdate )
+           adjust_subtitle_time(p_demux, p_sys->subtitle[p_sys->i_subtitle].i_start) < i_maxdate )
     {
         const subtitle_t *p_subtitle = &p_sys->subtitle[p_sys->i_subtitle];
 
@@ -721,9 +859,9 @@ static int Demux( demux_t *p_demux )
         }
 
         p_block->i_dts =
-        p_block->i_pts = VLC_TS_0 + p_subtitle->i_start;
+        p_block->i_pts = VLC_TS_0 + adjust_subtitle_time(p_demux, p_subtitle->i_start);
         if( p_subtitle->i_stop >= 0 && p_subtitle->i_stop >= p_subtitle->i_start )
-            p_block->i_length = p_subtitle->i_stop - p_subtitle->i_start;
+            p_block->i_length = adjust_subtitle_time(p_demux, p_subtitle->i_stop) - adjust_subtitle_time(p_demux, p_subtitle->i_start);
 
         memcpy( p_block->p_buffer, p_subtitle->psz_text, i_len );
 
@@ -733,11 +871,28 @@ static int Demux( demux_t *p_demux )
     }
 
     /* */
+    p_sys->i_last_demux_date = p_sys->i_next_demux_date;
     p_sys->i_next_demux_date = 0;
 
     return 1;
 }
 
+
+/*****************************************************************************
+ * adjust_subtitle_time : receives a subtitle timestamp as input 
+ *                     (p_subtitle->i_start or p_subtitle->i_stop) 
+ *                      and returns that timestamp corrected 
+ *                      by spu-delay
+ *****************************************************************************/
+static int64_t adjust_subtitle_time( demux_t * p_demux, int64_t i64_when)
+{
+    int64_t spu_delay = var_GetTime( p_demux->p_parent, "spu-delay" );
+    int64_t i64_adjust = i64_when + spu_delay;
+    return i64_adjust;
+}
+
+
+
 /*****************************************************************************
  * Fix: fix time stamp and order of subtitle
  *****************************************************************************/
diff --git a/src/input/input.c b/src/input/input.c
index 7e71d4e..ab34401 100644
--- a/src/input/input.c
+++ b/src/input/input.c
@@ -1103,7 +1103,14 @@ static void UpdatePtsDelay( input_thread_t *p_input )
     /* Take care of audio/spu delay */
     const mtime_t i_audio_delay = var_GetTime( p_input, "audio-delay" );
     const mtime_t i_spu_delay   = var_GetTime( p_input, "spu-delay" );
-    const mtime_t i_extra_delay = __MIN( i_audio_delay, i_spu_delay );
+    int isfilesub =var_GetInteger(p_input, "sub-isfilesub");
+    
+    mtime_t i_extra_delay;
+    if ( isfilesub )
+        i_extra_delay = i_audio_delay;
+    else
+        i_extra_delay = __MIN( i_audio_delay, i_spu_delay );
+
     if( i_extra_delay < 0 )
         i_pts_delay -= i_extra_delay;
 
diff --git a/src/input/var.c b/src/input/var.c
index 3e722f4..be3ef2a 100644
--- a/src/input/var.c
+++ b/src/input/var.c
@@ -195,6 +195,14 @@ void input_ControlVarInit ( input_thread_t *p_input )
     val.i_time = 0;
     var_Change( p_input, "spu-delay", VLC_VAR_SETVALUE, &val, NULL );
 
+    /*sub-isfilesub will be 
+     * - equal to 1 when the subtitle is read from a file (for example a .srt file), 
+     * - equal to 0 otherwise (for example dvd subtitles)*/
+    var_Create( p_input, "sub-isfilesub", VLC_VAR_INTEGER );
+    val.i_int = 0;
+    var_Change( p_input, "sub-isfilesub", VLC_VAR_SETVALUE, &val, 0 );
+
+    
     /* Video ES */
     var_Create( p_input, "video-es", VLC_VAR_INTEGER | VLC_VAR_HASCHOICE );
     text.psz_string = _("Video Track");
@@ -789,7 +797,9 @@ static int EsDelayCallback ( vlc_object_t *p_this, char const *psz_cmd,
     }
     else if( !strcmp( psz_cmd, "spu-delay" ) )
     {
-        input_ControlPush( p_input, INPUT_CONTROL_SET_SPU_DELAY, &newval );
+        int isfilesub = var_GetInteger(p_input, "sub-isfilesub");
+        if ( ! isfilesub )
+            input_ControlPush( p_input, INPUT_CONTROL_SET_SPU_DELAY, &newval );
     }
     return VLC_SUCCESS;
 }
-- 
1.9.1




More information about the vlc-devel mailing list