[vlc-devel] [NOTAPATCH, RFC] codec: avcodec: discard currently decoded frames on seek

Francois Cartegnie fcvlcdev at free.fr
Tue Apr 4 14:36:16 CEST 2017


On seek, avcodec (and probably most decoders) still process their buffers
and output those pre seek frames when decoding resumes after seek.
This causes a few frames time offset (when decoder does compute dts/pts),
can confuse sout if original dts/pts is kept (no discontinuity signaled),
produces visual glitch after seek.

As we should not drop those frames on regular discontinuity, which
could happen on corrupted data, one way to detect the seek is to
test both PREROLL flag (set by core on buffering) and DISCONTINUITY (should
have been set by demux or packetizer). The patch belows relies on those.

But, preroll also happens on rebuffering, and in that case, any regular
discontinuity within that period would flush the decoder, and that's
unwanted.

We probably might want the core to flag first block after seek 
with an existing unused/new flag.
Other ideas ?

Francois

---
 modules/codec/avcodec/audio.c |  5 ++++-
 modules/codec/avcodec/video.c | 16 ++++++++++++----
 2 files changed, 16 insertions(+), 5 deletions(-)

diff --git a/modules/codec/avcodec/audio.c b/modules/codec/avcodec/audio.c
index dc79c38..c8261dd 100644
--- a/modules/codec/avcodec/audio.c
+++ b/modules/codec/avcodec/audio.c
@@ -346,7 +346,10 @@ static block_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block, bool *error )
 
         if( p_block->i_flags & BLOCK_FLAG_DISCONTINUITY )
         {
-            date_Set( &p_sys->end_date, VLC_TS_INVALID );
+            if( p_block->i_flags & BLOCK_FLAG_PREROLL ) /* On seek we discard current session */
+                Flush( p_dec );
+            else
+                date_Set( &p_sys->end_date, VLC_TS_INVALID );
         }
 
         /* We've just started the stream, wait for the first PTS. */
diff --git a/modules/codec/avcodec/video.c b/modules/codec/avcodec/video.c
index 6d2cb5d..b38ac85 100644
--- a/modules/codec/avcodec/video.c
+++ b/modules/codec/avcodec/video.c
@@ -600,16 +600,24 @@ static void Flush( decoder_t *p_dec )
     decoder_AbortPictures( p_dec, false );
 }
 
-static bool check_block_validity( decoder_sys_t *p_sys, block_t *block )
+static bool check_block_validity( decoder_t *p_dec, block_t *block )
 {
+    decoder_sys_t *p_sys = p_dec->p_sys;
     if( !block)
         return true;
 
     if( block->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )
     {
-        p_sys->i_pts = VLC_TS_INVALID; /* To make sure we recover properly */
+        if( block->i_flags & BLOCK_FLAG_PREROLL ) /* On seek we need to discard current session */
+        {
+            Flush( p_dec );
+        }
+        else
+        {
+            p_sys->i_pts = VLC_TS_INVALID; /* To make sure we recover properly */
+            p_sys->i_late_frames = 0;
+        }
 
-        p_sys->i_late_frames = 0;
         if( block->i_flags & BLOCK_FLAG_CORRUPTED )
         {
             block_Release( block );
@@ -768,7 +776,7 @@ static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block, bool *error
         return NULL;
     }
 
-    if( !check_block_validity( p_sys, p_block ) )
+    if( !check_block_validity( p_dec, p_block ) )
         return NULL;
 
     current_time = mdate();
-- 
2.9.3



More information about the vlc-devel mailing list