[vlc-devel] [PATCH 1/2] scaletempo: fix pts/length

Thomas Guillem thomas at gllm.fr
Thu Feb 28 15:45:52 CET 2019


The output block PTS/length was wrongly set to the PTS/length of the last input
block. This could cause a PTS delay when the filter needed more than one input
block to return an output one. Example: with a rate of 4, the filter
(approximately) returned 3 time a NULL buffer, and used the PTS/length of the
4th one. This caused a PTS delay of 4 * block->i_length.

The returned PTS/length correspond now exactly to what the filer module wrote.
---
 modules/audio_filter/scaletempo.c | 28 +++++++++++++++++++++++++---
 1 file changed, 25 insertions(+), 3 deletions(-)

diff --git a/modules/audio_filter/scaletempo.c b/modules/audio_filter/scaletempo.c
index 3f47a76ae7..c7fc621796 100644
--- a/modules/audio_filter/scaletempo.c
+++ b/modules/audio_filter/scaletempo.c
@@ -43,6 +43,7 @@
 static int  Open( vlc_object_t * );
 static void Close( vlc_object_t * );
 static block_t *DoWork( filter_t *, block_t * );
+static void Flush( filter_t * );
 
 #ifdef PITCH_SHIFTER
 static int  OpenPitch( vlc_object_t * );
@@ -129,6 +130,8 @@ typedef struct
     void     *buf_pre_corr;
     void     *table_window;
     unsigned(*best_overlap_offset)( filter_t *p_filter );
+
+    date_t pts;
 #ifdef PITCH_SHIFTER
     /* pitch */
     filter_t * resampler;
@@ -434,6 +437,7 @@ static int Open( vlc_object_t *p_this )
     p_sys->bytes_queued   = 0;
     p_sys->bytes_to_slide = 0;
     p_sys->frames_stride_error = 0;
+    date_Init( &p_sys->pts, p_sys->sample_rate, 1 );
 
     if( reinit_buffers( p_filter ) != VLC_SUCCESS )
     {
@@ -445,6 +449,7 @@ static int Open( vlc_object_t *p_this )
     aout_FormatPrepare(&p_filter->fmt_in.audio);
     p_filter->fmt_out.audio = p_filter->fmt_in.audio;
     p_filter->pf_audio_filter = DoWork;
+    p_filter->pf_flush = Flush;
 
     return VLC_SUCCESS;
 }
@@ -552,7 +557,11 @@ static block_t *DoWork( filter_t * p_filter, block_t * p_in_buf )
     filter_sys_t *p = p_filter->p_sys;
 
     if( p_filter->fmt_in.audio.i_rate == p->sample_rate )
+    {
+        if( date_Get( &p->pts) != VLC_TICK_INVALID )
+            date_Set( &p->pts, VLC_TICK_INVALID );
         return p_in_buf;
+    }
 
     double scale = p_filter->fmt_in.audio.i_rate / (double)p->sample_rate;
     if( scale != p->scale ) {
@@ -565,6 +574,9 @@ static block_t *DoWork( filter_t * p_filter, block_t * p_in_buf )
                  (int)( p->bytes_stride / p->bytes_per_frame ), p->sample_rate );
     }
 
+    if( date_Get( &p->pts) == VLC_TICK_INVALID )
+        date_Set( &p->pts, p_in_buf->i_pts );
+
     block_t *p_out_buf = NULL;
     size_t i_outsize = calculate_output_buffer_size ( p_filter, p_in_buf->i_buffer );
 
@@ -587,11 +599,14 @@ static block_t *DoWork( filter_t * p_filter, block_t * p_in_buf )
             offset_in += fill_queue( p_filter, p_in_buf->p_buffer,
                                      p_in_buf->i_buffer, offset_in );
         }
+
         p_out_buf->i_buffer     = bytes_out;
         p_out_buf->i_nb_samples = bytes_out / p->bytes_per_frame;
-        p_out_buf->i_dts        = p_in_buf->i_dts;
-        p_out_buf->i_pts        = p_in_buf->i_pts;
-        p_out_buf->i_length     = p_in_buf->i_length;
+        p_out_buf->i_length =
+            vlc_tick_from_samples(p_out_buf->i_nb_samples, p->sample_rate);
+        p_out_buf->i_dts = p_out_buf->i_pts = date_Get( &p->pts );
+        date_Increment( &p->pts, p_out_buf->i_nb_samples );
+        assert( p_out_buf->i_pts + p_out_buf->i_length == date_Get( &p->pts ) );
     }
 
     block_Release( p_in_buf );
@@ -616,3 +631,10 @@ static block_t *DoPitchWork( filter_t * p_filter, block_t * p_in_buf )
     return DoWork( p_filter, p_in_buf );
 }
 #endif
+
+static void Flush( filter_t * p_filter )
+{
+    filter_sys_t *p = p_filter->p_sys;
+
+    date_Set( &p->pts, VLC_TICK_INVALID );
+}
-- 
2.20.1



More information about the vlc-devel mailing list