Commit 991d2ebf authored by Ilkka Ollakka's avatar Ilkka Ollakka

transcode: keep in track of input pts drift for video

Also name it to be next_input_pts instead of interpolated_pts

If input drift is more than 100ms that we estimate, we have most
likely dropped some packet and we should reset timers. Otherwise
it can cause lipsync issues if we for example just transcode video
track and audio track keeps original (jumped) pts.
parent a90263be
......@@ -250,8 +250,8 @@ int transcode_audio_process( sout_stream_t *p_stream,
if( unlikely( transcode_audio_initialize_filters( p_stream, id, p_sys,
&id->p_decoder->fmt_out.audio ) != VLC_SUCCESS ) )
return VLC_EGENERIC;
date_Init( &id->interpolated_pts, id->p_decoder->fmt_out.audio.i_rate, 1 );
date_Set( &id->interpolated_pts, p_audio_buf->i_pts );
date_Init( &id->next_input_pts, id->p_decoder->fmt_out.audio.i_rate, 1 );
date_Set( &id->next_input_pts, p_audio_buf->i_pts );
}
/* Check if audio format has changed, and filters need reinit */
......@@ -270,14 +270,14 @@ int transcode_audio_process( sout_stream_t *p_stream,
&id->p_decoder->fmt_out.audio ) != VLC_SUCCESS )
return VLC_EGENERIC;
/* Set interpolated_pts to run with new samplerate */
date_Init( &id->interpolated_pts, p_sys->fmt_audio.i_rate, 1 );
date_Set( &id->interpolated_pts, p_audio_buf->i_pts );
/* Set next_input_pts to run with new samplerate */
date_Init( &id->next_input_pts, id->fmt_audio.i_rate, 1 );
date_Set( &id->next_input_pts, p_audio_buf->i_pts );
}
if( p_sys->b_master_sync )
{
mtime_t i_pts = date_Get( &id->interpolated_pts );
mtime_t i_pts = date_Get( &id->next_input_pts );
mtime_t i_drift = 0;
if( likely( p_audio_buf->i_pts != VLC_TS_INVALID ) )
......@@ -289,13 +289,13 @@ int transcode_audio_process( sout_stream_t *p_stream,
msg_Dbg( p_stream,
"audio drift is too high (%"PRId64"), resetting master sync",
i_drift );
date_Set( &id->interpolated_pts, p_audio_buf->i_pts );
i_pts = date_Get( &id->interpolated_pts );
date_Set( &id->next_input_pts, p_audio_buf->i_pts );
i_pts = date_Get( &id->next_input_pts );
if( likely(p_audio_buf->i_pts != VLC_TS_INVALID ) )
i_drift = p_audio_buf->i_pts - i_pts;
}
p_sys->i_master_drift = i_drift;
date_Increment( &id->interpolated_pts, p_audio_buf->i_nb_samples );
date_Increment( &id->next_input_pts, p_audio_buf->i_nb_samples );
}
p_audio_buf->i_dts = p_audio_buf->i_pts;
......
......@@ -105,10 +105,10 @@ struct sout_stream_id_sys_t
encoder_t *p_encoder;
/* Sync */
date_t interpolated_pts; /**< Incoming calculated PTS */
date_t next_input_pts; /**< Incoming calculated PTS */
date_t next_output_pts; /**< output calculated PTS */
int i_output_frame_interval;
int i_input_frame_interval;
int i_output_frame_interval;
};
/* OSD */
......
......@@ -548,10 +548,18 @@ static void transcode_video_encoder_init( sout_stream_t *p_stream,
id->p_encoder->fmt_in.video.i_frame_rate,
id->p_encoder->fmt_in.video.i_frame_rate_base );
id->i_output_frame_interval = id->p_encoder->fmt_out.video.i_frame_rate_base * CLOCK_FREQ / id->p_encoder->fmt_out.video.i_frame_rate;
id->i_input_frame_interval = id->p_decoder->fmt_out.video.i_frame_rate_base * CLOCK_FREQ / id->p_decoder->fmt_out.video.i_frame_rate;
msg_Info( p_stream, "input interval %d (base %d)",
id->i_input_frame_interval, id->p_decoder->fmt_out.video.i_frame_rate_base );
id->i_output_frame_interval = id->p_encoder->fmt_in.video.i_frame_rate_base * CLOCK_FREQ / id->p_encoder->fmt_in.video.i_frame_rate;
msg_Info( p_stream, "output interval %d (base %d)",
id->i_output_frame_interval, id->p_encoder->fmt_in.video.i_frame_rate_base );
date_Init( &id->next_input_pts,
id->p_decoder->fmt_out.video.i_frame_rate,
1 );
date_Init( &id->next_output_pts,
id->p_encoder->fmt_in.video.i_frame_rate,
1 );
......@@ -885,6 +893,7 @@ int transcode_video_process( sout_stream_t *p_stream, sout_stream_id_sys_t *id,
return VLC_EGENERIC;
}
date_Set( &id->next_output_pts, p_pic->date );
date_Set( &id->next_input_pts, p_pic->date );
}
/*Input lipsync and drop check */
......@@ -912,6 +921,21 @@ int transcode_video_process( sout_stream_t *p_stream, sout_stream_id_sys_t *id,
#endif
}
/* Check input drift regardless, if it's more than 100ms from our approximation, we most likely have lost pictures
* and are in danger to become out of sync, so better reset timestamps then */
if( likely( p_pic->date != VLC_TS_INVALID ) )
{
mtime_t input_drift = p_pic->date - date_Get( &id->next_input_pts );
if( unlikely( (input_drift > (CLOCK_FREQ/10)) ||
(input_drift < -(CLOCK_FREQ/10))
) )
{
msg_Warn( p_stream, "Reseting video sync" );
date_Set( &id->next_output_pts, p_pic->date );
date_Set( &id->next_input_pts, p_pic->date );
}
}
date_Increment( &id->next_input_pts, id->p_decoder->fmt_out.video.i_frame_rate_base );
/* Run the filter and output chains; first with the picture,
* and then with NULL as many times as we need until they
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment