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

Julian Scheel julian at jusst.de
Sun Jun 1 10:47:36 CEST 2014


Am 30/05/14 22:04, schrieb Pascal Thomet:
> 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.
>
> I now propose a correction for this bug, as well as tooltip that better
> explain the use of the hotkeys introduced by f7211d5efa4cd9ef392230d85fdf3470edefab39
>
> tests passed / compile and runs correctly in debug & release modes
> under linux & OSX
>
> 1) Bug correction info :
> *  *  *  *  *  *  *  *  *
>
> Bug reproduction step : *under linux* (will not happen under OSX)
> - launch a video that has a subtitle,
> - 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)
>
> The subtitle delay ("spu-delay") was previously implemented by
>    i) setting a variable spu-delay
>       (var_SetTime(... , "spu-delay", ... ))
>    ii) this change raised a callback that finaly lead to calling
>      UpdatePtsDelay().
>
> The reason UpdatePtsDelay() was called is that the subtitle delay
> was programed the same way as the audio delay (for which it is required
> to wait until the audio is actually demuxed)
>
> *However* the situation for subtitles is quite different, as they are all in memory
> (no need to wait until they are demuxed !)

This really depends on the subtitle source. In case of dvb subtitles in 
mpeg ts they are not all in memory but come muxed into the stream.

> The code is now more simple (and the bug is fixed !) :
> - no more delay calculations inside hotkeys.c, everything is handled
>    inside subtitle.c through callbacks
> - inside subtitle.c :
>      * adjust_subtitle_time() receives a subtitle timestamp as input and returns
>        that timestamp corrected by spu-delay
>      * set_current_subtitle_by_time() is called when spu-delay is changed
>
> 2) Tooltip
> *  *  *  *

imho this should be split into a separate patch.

> This adds a tooltip in the "Track Synchronization" window
> on the "subtitle track sycnhronization" label and widget.
> It explains better the use of the subtitle sync hotkeys
> (Shift H/J/K)
>
> Also tested under Linux & OSX.
> ---
>   include/vlc_input.h                            |   2 -
>   modules/control/hotkeys.c                      | 113 +++++---------
>   modules/demux/subtitle.c                       | 205 +++++++++++++++++++++----
>   modules/gui/macosx/TrackSynchronization.m      |  17 +-
>   modules/gui/macosx/intf.m                      |   1 -
>   modules/gui/qt4/components/extended_panels.cpp |  16 +-
>   modules/gui/qt4/input_manager.cpp              |   1 -
>   src/input/event.c                              |  10 --
>   src/input/event.h                              |   1 -
>   src/input/input.c                              |  10 +-
>   src/input/input_internal.h                     |   1 -
>   src/input/var.c                                |   5 -
>   12 files changed, 250 insertions(+), 132 deletions(-)
>
> diff --git a/include/vlc_input.h b/include/vlc_input.h
> index 88bfe65..043414e 100644
> --- a/include/vlc_input.h
> +++ b/include/vlc_input.h
> @@ -380,8 +380,6 @@ typedef enum input_event_type_e
>
>       /* "audio-delay" has changed */
>       INPUT_EVENT_AUDIO_DELAY,
> -    /* "spu-delay" has changed */
> -    INPUT_EVENT_SUBTITLE_DELAY,
>
>       /* "bookmark" has changed */
>       INPUT_EVENT_BOOKMARK,
> diff --git a/modules/control/hotkeys.c b/modules/control/hotkeys.c
> index 1e7fcdf..eb00c57 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, "spu-bookmarkaudio", mdate());
>               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, "spu-bookmarksubtitle", mdate());
>               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, "spu-syncbookmarks", mdate());
>               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, "spu-syncreset", mdate());
>               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..3ed2040 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, "spu-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, "spu-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, "spu-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, "spu-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,26 @@ 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 );
> +
> +    p_sys->subtitle_delaybookmarks.i_time_audio = 0;
> +    p_sys->subtitle_delaybookmarks.i_time_subtitle = 0;
> +
> +
> +    /* Add callbacks*/
> +    var_Create(p_demux->p_parent, "spu-bookmarkaudio", VLC_VAR_INTEGER);
> +    var_Create(p_demux->p_parent, "spu-bookmarksubtitle", VLC_VAR_INTEGER);
> +    var_Create(p_demux->p_parent, "spu-syncbookmarks", VLC_VAR_INTEGER);
> +    var_Create(p_demux->p_parent, "spu-syncreset", VLC_VAR_INTEGER);
> +    var_AddCallback( p_demux->p_parent, "spu-bookmarkaudio", &subtitle_external_callback, p_this );
> +    var_AddCallback( p_demux->p_parent, "spu-bookmarksubtitle", &subtitle_external_callback, p_this );
> +    var_AddCallback( p_demux->p_parent, "spu-syncbookmarks", &subtitle_external_callback, p_this );
> +    var_AddCallback( p_demux->p_parent, "spu-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 +688,21 @@ 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;
>
> +    /* Remove callbacks*/
> +    var_DelCallback( p_demux->p_parent, "spu-bookmarkaudio", &subtitle_external_callback, p_this );
> +    var_DelCallback( p_demux->p_parent, "spu-bookmarksubtitle", &subtitle_external_callback, p_this );
> +    var_DelCallback( p_demux->p_parent, "spu-syncbookmarks", &subtitle_external_callback, p_this );
> +    var_DelCallback( p_demux->p_parent, "spu-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, "spu-bookmarkaudio");
> +    var_Destroy(p_demux->p_parent, "spu-bookmarksubtitle");
> +    var_Destroy(p_demux->p_parent, "spu-syncbookmarks");
> +    var_Destroy(p_demux->p_parent, "spu-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 +713,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 +755,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 +772,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 +788,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++;
>               }
> @@ -682,6 +815,7 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
>       }
>   }
>
> +
>   /*****************************************************************************
>    * Demux: Send subtitle to decoder
>    *****************************************************************************/
> @@ -693,15 +827,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 +855,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 +867,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/modules/gui/macosx/TrackSynchronization.m b/modules/gui/macosx/TrackSynchronization.m
> index c0b8f3c..a5ddce3 100644
> --- a/modules/gui/macosx/TrackSynchronization.m
> +++ b/modules/gui/macosx/TrackSynchronization.m
> @@ -65,7 +65,22 @@ static VLCTrackSynchronization *_o_sharedInstance = nil;
>       [o_sv_lbl setStringValue: _NS("Subtitles/Video")];
>       [o_sv_advance_lbl setStringValue: _NS("Subtitle track synchronization:")];
>       [[o_sv_advance_value_fld formatter] setFormat:[NSString stringWithFormat:@"#,##0.000 %@", _NS("s")]];
> -    [o_sv_advance_value_fld setToolTip: _NS("A positive value means that the subtitles are ahead of the video")];
> +    [o_sv_advance_value_fld setToolTip:
> +        _NS(
> +            "A positive value means that the subtitles are ahead of the video\n"
> +            "\n"\
> +            "In order to set the subtitle track synchronization delay easily, \n"\
> +            "you can use the hotkeys :\n"\
> +            "\n"\
> +            "* Shift-H (audio bookmark)\n"\
> +            "* Shift-J (subtitle bookmark) \n"\
> +            "* Shift-K (sync bookmarks)\n"\
> +            "\n"\
> +            "(Command-Shift-K resets the delay)\n"\
> +            "\n"\
> +            "(Use these hotkeys directly on the video)\n"
> +            )
> +    ];
>       [o_sv_speed_lbl setStringValue: _NS("Subtitle speed:")];
>       [[o_sv_speed_value_fld formatter] setFormat:[NSString stringWithFormat:@"#,##0.000 %@", _NS("fps")]];
>       [o_sv_dur_lbl setStringValue: _NS("Subtitle duration factor:")];
> diff --git a/modules/gui/macosx/intf.m b/modules/gui/macosx/intf.m
> index 8f46abb..26b6675 100644
> --- a/modules/gui/macosx/intf.m
> +++ b/modules/gui/macosx/intf.m
> @@ -358,7 +358,6 @@ static int InputEvent(vlc_object_t *p_this, const char *psz_var,
>               break;
>
>           case INPUT_EVENT_AUDIO_DELAY:
> -        case INPUT_EVENT_SUBTITLE_DELAY:
>               [[VLCMain sharedInstance] performSelectorOnMainThread:@selector(updateDelays) withObject:nil waitUntilDone:NO];
>               break;
>
> diff --git a/modules/gui/qt4/components/extended_panels.cpp b/modules/gui/qt4/components/extended_panels.cpp
> index 84d16ae..4dd0f7d 100644
> --- a/modules/gui/qt4/components/extended_panels.cpp
> +++ b/modules/gui/qt4/components/extended_panels.cpp
> @@ -1475,7 +1475,21 @@ SyncControls::SyncControls( intf_thread_t *_p_intf, QWidget *_parent ) :
>
>       subsSpin = new SyncWidget( this );
>       subsLayout->addWidget( subsSpin, 0, 2, 1, 1 );
> -
> +    QString subsSpin_Tooltip = qtr(
> +        "In order to set the subtitle track synchronization delay easily, \n"\
> +        "you can use the hotkeys :\n"\
> +        "\n"\
> +        "* Shift-H (audio bookmark)\n"\
> +        "* Shift-J (subtitle bookmark) \n"\
> +        "* Shift-K (sync bookmarks)\n"\
> +        "\n"\
> +        "(Ctrl-Shift-K resets the delay)\n"\
> +        "\n"\
> +        "(Use these hotkeys directly on the video)\n"
> +    );
> +    subsSpin->setToolTip(subsSpin_Tooltip);
> +    subsLabel->setToolTip(subsSpin_Tooltip);
> +
>       QLabel *subSpeedLabel = new QLabel;
>       subSpeedLabel->setText( qtr( "Subtitle speed:" ) );
>       subsLayout->addWidget( subSpeedLabel, 1, 0, 1, 1 );
> diff --git a/modules/gui/qt4/input_manager.cpp b/modules/gui/qt4/input_manager.cpp
> index c07f712..ef9ec66 100644
> --- a/modules/gui/qt4/input_manager.cpp
> +++ b/modules/gui/qt4/input_manager.cpp
> @@ -377,7 +377,6 @@ static int InputEvent( vlc_object_t *p_this, const char *,
>           break;
>
>       case INPUT_EVENT_AUDIO_DELAY:
> -    case INPUT_EVENT_SUBTITLE_DELAY:
>           event = new IMEvent( IMEvent::SynchroChanged );
>           break;
>
> diff --git a/src/input/event.c b/src/input/event.c
> index 453e04b..f4ca0d6 100644
> --- a/src/input/event.c
> +++ b/src/input/event.c
> @@ -112,16 +112,6 @@ void input_SendEventAudioDelay( input_thread_t *p_input, mtime_t i_delay )
>       Trigger( p_input, INPUT_EVENT_AUDIO_DELAY );
>   }
>
> -void input_SendEventSubtitleDelay( input_thread_t *p_input, mtime_t i_delay )
> -{
> -    vlc_value_t val;
> -
> -    val.i_time = i_delay;
> -    var_Change( p_input, "spu-delay", VLC_VAR_SETVALUE, &val, NULL );
> -
> -    Trigger( p_input, INPUT_EVENT_SUBTITLE_DELAY );
> -}
> -
>   /* TODO and file name ? */
>   void input_SendEventRecord( input_thread_t *p_input, bool b_recording )
>   {
> diff --git a/src/input/event.h b/src/input/event.h
> index c8f1071..b3c4b56 100644
> --- a/src/input/event.h
> +++ b/src/input/event.h
> @@ -36,7 +36,6 @@ void input_SendEventLength( input_thread_t *p_input, mtime_t i_length );
>   void input_SendEventStatistics( input_thread_t *p_input );
>   void input_SendEventRate( input_thread_t *p_input, int i_rate );
>   void input_SendEventAudioDelay( input_thread_t *p_input, mtime_t i_delay );
> -void input_SendEventSubtitleDelay( input_thread_t *p_input, mtime_t i_delay );
>   void input_SendEventRecord( input_thread_t *p_input, bool b_recording );
>   void input_SendEventTitle( input_thread_t *p_input, int i_title );
>   void input_SendEventSeekpoint( input_thread_t *p_input, int i_title, int i_seekpoint );
> diff --git a/src/input/input.c b/src/input/input.c
> index 7e71d4e..6d4bc4a 100644
> --- a/src/input/input.c
> +++ b/src/input/input.c
> @@ -1102,8 +1102,7 @@ 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 );
> +    const mtime_t i_extra_delay = i_audio_delay;
>       if( i_extra_delay < 0 )
>           i_pts_delay -= i_extra_delay;
>
> @@ -1112,7 +1111,6 @@ static void UpdatePtsDelay( input_thread_t *p_input )
>
>       /* */
>       es_out_SetDelay( p_input->p->p_es_out_display, AUDIO_ES, i_audio_delay );
> -    es_out_SetDelay( p_input->p->p_es_out_display, SPU_ES, i_spu_delay );
>       es_out_SetJitter( p_input->p->p_es_out, i_pts_delay, 0, i_cr_average );
>   }
>
> @@ -1871,12 +1869,6 @@ static bool Control( input_thread_t *p_input,
>               input_SendEventAudioDelay( p_input, val.i_time );
>               UpdatePtsDelay( p_input );
>               break;
> -
> -        case INPUT_CONTROL_SET_SPU_DELAY:
> -            input_SendEventSubtitleDelay( p_input, val.i_time );
> -            UpdatePtsDelay( p_input );
> -            break;
> -
>           case INPUT_CONTROL_SET_TITLE:
>           case INPUT_CONTROL_SET_TITLE_NEXT:
>           case INPUT_CONTROL_SET_TITLE_PREV:
> diff --git a/src/input/input_internal.h b/src/input/input_internal.h
> index 9f71294..9e534d9 100644
> --- a/src/input/input_internal.h
> +++ b/src/input/input_internal.h
> @@ -202,7 +202,6 @@ enum input_control_e
>       INPUT_CONTROL_RESTART_ES,
>
>       INPUT_CONTROL_SET_AUDIO_DELAY,
> -    INPUT_CONTROL_SET_SPU_DELAY,
>
>       INPUT_CONTROL_ADD_SLAVE,
>
> diff --git a/src/input/var.c b/src/input/var.c
> index 3e722f4..293babd 100644
> --- a/src/input/var.c
> +++ b/src/input/var.c
> @@ -97,7 +97,6 @@ static const vlc_input_callback_t p_input_callbacks[] =
>       CALLBACK( "title", TitleCallback ),
>       CALLBACK( "chapter", SeekpointCallback ),
>       CALLBACK( "audio-delay", EsDelayCallback ),
> -    CALLBACK( "spu-delay", EsDelayCallback ),
>       CALLBACK( "video-es", ESCallback ),
>       CALLBACK( "audio-es", ESCallback ),
>       CALLBACK( "spu-es", ESCallback ),
> @@ -787,10 +786,6 @@ static int EsDelayCallback ( vlc_object_t *p_this, char const *psz_cmd,
>       {
>           input_ControlPush( p_input, INPUT_CONTROL_SET_AUDIO_DELAY, &newval );
>       }
> -    else if( !strcmp( psz_cmd, "spu-delay" ) )
> -    {
> -        input_ControlPush( p_input, INPUT_CONTROL_SET_SPU_DELAY, &newval );
> -    }
>       return VLC_SUCCESS;
>   }
>
>




More information about the vlc-devel mailing list