[vlc-devel] [PATCH] Fix https://trac.videolan.org/vlc/ticket/10749 Video was getting stuck while using subtitle delay option when setting a negative subtitle delay.
Pascal Thomet
pthomet at gmail.com
Sat Sep 30 19:16:35 CEST 2017
Steps to reproduce the problem:
* load a video + srt sub
* open the "Track synchro" window
* enter -10s or +10s in the subtitle delay => video will be frozen for 10 seconds
Modifications:
**************
Note : you can see this patch online at https://github.com/pthom/vlc/commit/33742f3e76f7930e85506c23848975f2156427ea
modules/demux/subtitle.c:
* Added adjust_subtitle_time : adjust_subtitle_time returns a timestamp corrected by spu-delay
* Added set_current_subtitle_by_time: sets the current subtitle index, returns true if index changed,
i.e a new subtitle should be displayed
Note : the code was using var_GetInteger (add thus could not see the correct spu-delay). This was corrected by using var_InheritInteger
src/input/var.c:
* Added var "sub-isfilesub" : will be set to true if the sub is a file sub
src/input/input.c:
* UpdatePtsDelay now only applies a delay if var "sub-isfilesub" is false.
* Init resets the var "spu-delay" (when loading a new movie)
* Set var "sub-isfilesub" to false by default, then sets it to true inside input_SlaveSourceAdd
(if i_type == SLAVE_TYPE_SPU )
---
modules/control/hotkeys.c | 10 -----
modules/demux/subtitle.c | 108 +++++++++++++++++++++++++++++++---------------
src/input/input.c | 17 +++++++-
src/input/var.c | 9 +++-
4 files changed, 97 insertions(+), 47 deletions(-)
diff --git a/modules/control/hotkeys.c b/modules/control/hotkeys.c
index 690a4e5e6c..1f2f4a8a80 100644
--- a/modules/control/hotkeys.c
+++ b/modules/control/hotkeys.c
@@ -630,16 +630,6 @@ static int PutAction( intf_thread_t *p_intf, input_thread_t *p_input,
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) )
diff --git a/modules/demux/subtitle.c b/modules/demux/subtitle.c
index 89f1198114..bbf7e1bcab 100644
--- a/modules/demux/subtitle.c
+++ b/modules/demux/subtitle.c
@@ -131,6 +131,7 @@ static void TextUnload( text_t * );
typedef struct
{
+ /* subtitle timestamps : use with adjust_subtitle_time() to include spu-delay */
int64_t i_start;
int64_t i_stop;
@@ -175,6 +176,7 @@ struct demux_sys_t
bool b_first_time;
int64_t i_next_demux_date;
+ int64_t i_last_spu_delay;
struct
{
@@ -250,6 +252,8 @@ 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 bool set_current_subtitle_by_time(demux_t *p_demux, int64_t i64_when);
/*****************************************************************************
* Decoder format output function
@@ -324,6 +328,7 @@ static int Open ( vlc_object_t *p_this )
p_sys->b_slave = false;
p_sys->b_first_time = true;
p_sys->i_next_demux_date = 0;
+ p_sys->i_last_spu_delay = 0;
p_sys->pf_convert = ToTextBlock;
@@ -798,24 +803,13 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
case DEMUX_GET_TIME:
pi64 = va_arg( args, int64_t * );
- *pi64 = p_sys->i_next_demux_date - var_GetInteger( p_demux->obj.parent, "spu-delay" );
- if( *pi64 < 0 )
- *pi64 = p_sys->i_next_demux_date;
+ *pi64 = adjust_subtitle_time(p_demux, p_sys->subtitles.p_array[p_sys->subtitles.i_current].i_start);
return VLC_SUCCESS;
case DEMUX_SET_TIME:
i64 = va_arg( args, int64_t );
- for( size_t i = 0; i + 1< p_sys->subtitles.i_count; i++ )
- {
- if( p_sys->subtitles.p_array[i + 1].i_start >= i64 )
- {
- p_sys->subtitles.i_current = i;
- p_sys->i_next_demux_date = i64;
- p_sys->b_first_time = true;
- return VLC_SUCCESS;
- }
- }
- break;
+ set_current_subtitle_by_time(p_demux, i64);
+ return VLC_SUCCESS;
case DEMUX_GET_POSITION:
pf = va_arg( args, double * );
@@ -825,10 +819,8 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
}
else if( p_sys->subtitles.i_count > 0 && p_sys->i_length )
{
- *pf = p_sys->i_next_demux_date - var_GetInteger( p_demux->obj.parent, "spu-delay" );
- if( *pf < 0 )
- *pf = p_sys->i_next_demux_date;
- *pf /= p_sys->i_length;
+ int64_t i_start_adjust = adjust_subtitle_time(p_demux, p_sys->i_next_demux_date);
+ *pf = (double)i_start_adjust / (double)p_sys->i_length;
}
else
{
@@ -871,41 +863,45 @@ static int Demux( demux_t *p_demux )
{
demux_sys_t *p_sys = p_demux->p_sys;
- int64_t i_barrier = p_sys->i_next_demux_date - var_GetInteger( p_demux->obj.parent, "spu-delay" );
- if( i_barrier < 0 )
- i_barrier = p_sys->i_next_demux_date;
-
- while( p_sys->subtitles.i_current < p_sys->subtitles.i_count &&
- p_sys->subtitles.p_array[p_sys->subtitles.i_current].i_start <= i_barrier )
+ int64_t i_adjusted_next_demux_date = adjust_subtitle_time(p_demux, p_sys->i_next_demux_date);
+ if ( !p_sys->b_slave && p_sys->b_first_time )
{
- const subtitle_t *p_subtitle = &p_sys->subtitles.p_array[p_sys->subtitles.i_current];
+ es_out_SetPCR( p_demux->out, VLC_TS_0 + i_adjusted_next_demux_date );
+ p_sys->b_first_time = false;
+ }
- if ( !p_sys->b_slave && p_sys->b_first_time )
- {
- es_out_SetPCR( p_demux->out, VLC_TS_0 + i_barrier );
- p_sys->b_first_time = false;
- }
+ /* log if detected spu-delay changes */
+ int64_t spu_delay = var_InheritInteger(p_demux->obj.parent, "spu-delay");
+ if (spu_delay != p_sys->i_last_spu_delay)
+ {
+ msg_Info( p_demux->obj.parent,
+ "Detected spu-delay change from %lld to %lld",
+ p_sys->i_last_spu_delay / 1000, spu_delay / 1000);
+ p_sys->i_last_spu_delay = spu_delay;
+ }
- if( p_subtitle->i_start >= 0 )
+ bool b_is_new_subtitle = set_current_subtitle_by_time(p_demux, p_sys->i_next_demux_date);
+ if ( b_is_new_subtitle )
+ {
+ const subtitle_t *p_subtitle = &p_sys->subtitles.p_array[p_sys->subtitles.i_current];
+ if ( p_subtitle->i_start >= 0 )
{
block_t *p_block = p_sys->pf_convert( p_subtitle );
if( p_block )
{
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;
es_out_Send( p_demux->out, p_sys->es, p_block );
}
}
-
- p_sys->subtitles.i_current++;
}
if ( !p_sys->b_slave )
{
- es_out_SetPCR( p_demux->out, VLC_TS_0 + i_barrier );
+ es_out_SetPCR( p_demux->out, VLC_TS_0 + i_adjusted_next_demux_date );
p_sys->i_next_demux_date += CLOCK_FREQ / 8;
}
@@ -916,6 +912,48 @@ static int Demux( demux_t *p_demux )
}
+/*****************************************************************************
+ * adjust_subtitle_time & set_current_subtitle_by_time : handle the spu-delay
+ *
+ * - adjust_subtitle_time : return a timestamp corrected by spu-delay
+ * - set_current_subtitle_by_time : sets the current subtitle index
+ * returns true if index changed, i.e a new subtitle should be displayed
+ *****************************************************************************/
+static int64_t adjust_subtitle_time( demux_t * p_demux, int64_t i64_when)
+{
+ int64_t spu_delay = var_InheritInteger(p_demux->obj.parent, "spu-delay");
+ int64_t i64_adjust = i64_when + spu_delay;
+ if (i64_adjust < 0)
+ i64_adjust = 0;
+ return i64_adjust;
+}
+
+static bool set_current_subtitle_by_time(demux_t *p_demux, int64_t i64_when)
+{
+ demux_sys_t *p_sys = p_demux->p_sys;
+
+ size_t i_new_current_sub = 0;
+ while( i_new_current_sub < p_sys->subtitles.i_count )
+ {
+ const subtitle_t *p_subtitle = &p_sys->subtitles.p_array[i_new_current_sub];
+ 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;
+
+ i_new_current_sub++;
+ }
+ if( i_new_current_sub >= p_sys->subtitles.i_count )
+ {
+ p_sys->subtitles.i_current = p_sys->subtitles.i_count - 1;
+ }
+
+ bool b_changed = ( p_sys->subtitles.i_current != i_new_current_sub);
+ p_sys->subtitles.i_current = i_new_current_sub;
+ return b_changed;
+}
+
static int subtitle_cmp( const void *first, const void *second )
{
int64_t result = ((subtitle_t *)(first))->i_start - ((subtitle_t *)(second))->i_start;
diff --git a/src/input/input.c b/src/input/input.c
index 9d8f145777..1e7dcf8f8e 100644
--- a/src/input/input.c
+++ b/src/input/input.c
@@ -1066,6 +1066,9 @@ static void LoadSlaves( input_thread_t *p_input )
int i_slaves;
TAB_INIT( i_slaves, pp_slaves );
+ /* sub-isfilesub will be set to true inside input_SlaveSourceAdd (if needed)*/
+ var_SetBool(p_input, "sub-isfilesub", false);
+
/* Look for and add slaves */
char *psz_subtitle = var_GetNonEmptyString( p_input, "sub-file" );
@@ -1221,7 +1224,14 @@ static void UpdatePtsDelay( input_thread_t *p_input )
/* Take care of audio/spu delay */
const mtime_t i_audio_delay = var_GetInteger( p_input, "audio-delay" );
const mtime_t i_spu_delay = var_GetInteger( p_input, "spu-delay" );
- const mtime_t i_extra_delay = __MIN( i_audio_delay, i_spu_delay );
+ bool isfilesub = var_GetBool(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;
@@ -1308,6 +1318,9 @@ static int Init( input_thread_t * p_input )
var_SetBool( p_input, "sub-autodetect-file", false );
}
+ /* reset spu-delay on Init */
+ var_SetInteger(p_input, "spu-delay", 0);
+
InitStatistics( p_input );
#ifdef ENABLE_SOUT
if( InitSout( p_input ) )
@@ -3317,6 +3330,8 @@ static int input_SlaveSourceAdd( input_thread_t *p_input,
return VLC_EGENERIC;
}
+ if ( i_type == SLAVE_TYPE_SPU )
+ var_SetBool(p_input, "sub-isfilesub", true);
if( i_type == SLAVE_TYPE_AUDIO )
{
if( b_set_time )
diff --git a/src/input/var.c b/src/input/var.c
index f41dac5e9e..949190c156 100644
--- a/src/input/var.c
+++ b/src/input/var.c
@@ -188,6 +188,11 @@ void input_ControlVarInit ( input_thread_t *p_input )
1000 * var_GetInteger( p_input, "audio-desync" ) );
var_Create( p_input, "spu-delay", VLC_VAR_INTEGER );
+ /* sub-isfilesub : true for *.srt & the like, false otherwise (for example dvd subtitles) */
+ var_Create( p_input, "sub-isfilesub", VLC_VAR_BOOL );
+ val.b_bool = false;
+ var_Change( p_input, "sub-isfilesub", VLC_VAR_SETVALUE, &val, 0 );
+
val.i_int = -1;
/* Video ES */
var_Create( p_input, "video-es", VLC_VAR_INTEGER );
@@ -819,7 +824,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 );
+ bool isfilesub = var_GetBool(p_input, "sub-isfilesub");
+ if ( ! isfilesub )
+ input_ControlPush( p_input, INPUT_CONTROL_SET_SPU_DELAY, &newval );
}
return VLC_SUCCESS;
}
--
2.12.2
More information about the vlc-devel
mailing list