]> git.sesse.net Git - vlc/commitdiff
transcode: keep in track of input pts drift for video
authorIlkka Ollakka <ileoo@videolan.org>
Fri, 23 May 2014 12:04:55 +0000 (15:04 +0300)
committerIlkka Ollakka <ileoo@videolan.org>
Fri, 23 May 2014 12:07:13 +0000 (15:07 +0300)
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.

modules/stream_out/transcode/audio.c
modules/stream_out/transcode/transcode.h
modules/stream_out/transcode/video.c

index ab9dfec18cc62b9fee10dbfe3665a3484ff66553..60124202114cffcafc6cf60f0a6f025a3a6cce4a 100644 (file)
@@ -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;
index 50c3d7531548ee1a87bced7e91358e761351554c..66daca0520f67a643bba7322e79f9d3787726c8d 100644 (file)
@@ -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 */
index 6f775ddfda8ed4277059f9a62f0bc5922c71c11c..60b66bbbac14620fc0da0fefdd344cd61ffd83c2 100644 (file)
@@ -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