[vlc-commits] avcodec video decoder: returns delayed frames at end of stream

Rafaël Carré git at videolan.org
Mon Jan 13 16:10:55 CET 2014


vlc | branch: master | Rafaël Carré <funman at videolan.org> | Mon Jan 13 16:10:29 2014 +0100| [1e335d5e5e5baf1a5425b56edab27b07713fe7c3] | committer: Rafaël Carré

avcodec video decoder: returns delayed frames at end of stream

Closes: #10331

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=1e335d5e5e5baf1a5425b56edab27b07713fe7c3
---

 modules/codec/avcodec/video.c |  126 +++++++++++++++++++++++++----------------
 1 file changed, 76 insertions(+), 50 deletions(-)

diff --git a/modules/codec/avcodec/video.c b/modules/codec/avcodec/video.c
index 03435fb..83c5954 100644
--- a/modules/codec/avcodec/video.c
+++ b/modules/codec/avcodec/video.c
@@ -430,7 +430,7 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
     int b_null_size = false;
     block_t *p_block;
 
-    if( !pp_block || !*pp_block )
+    if( !pp_block )
         return NULL;
 
     if( !p_context->extradata_size && p_dec->fmt_in.i_extra )
@@ -444,33 +444,40 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
     }
 
     p_block = *pp_block;
+    if(!p_block && !(p_sys->p_codec->capabilities & CODEC_CAP_DELAY) )
+        return NULL;
+
     if( p_sys->b_delayed_open )
     {
-        block_Release( p_block );
+        if( p_block )
+            block_Release( p_block );
         return NULL;
     }
 
-    if( p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )
+    if( p_block)
     {
-        p_sys->i_pts = VLC_TS_INVALID; /* To make sure we recover properly */
+        if( p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )
+        {
+            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;
 
-        post_mt( p_sys );
-        if( p_block->i_flags & BLOCK_FLAG_DISCONTINUITY )
-            avcodec_flush_buffers( p_context );
-        wait_mt( p_sys );
+            post_mt( p_sys );
+            if( p_block->i_flags & BLOCK_FLAG_DISCONTINUITY )
+                avcodec_flush_buffers( p_context );
+            wait_mt( p_sys );
 
-        block_Release( p_block );
-        return NULL;
-    }
+            block_Release( p_block );
+            return NULL;
+        }
 
-    if( p_block->i_flags & BLOCK_FLAG_PREROLL )
-    {
-        /* Do not care about late frames when prerolling
-         * TODO avoid decoding of non reference frame
-         * (ie all B except for H264 where it depends only on nal_ref_idc) */
-        p_sys->i_late_frames = 0;
+        if( p_block->i_flags & BLOCK_FLAG_PREROLL )
+        {
+            /* Do not care about late frames when prerolling
+             * TODO avoid decoding of non reference frame
+             * (ie all B except for H264 where it depends only on nal_ref_idc) */
+            p_sys->i_late_frames = 0;
+        }
     }
 
     if( !p_dec->b_pace_control && (p_sys->i_late_frames > 0) &&
@@ -482,7 +489,8 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
                      "dropping frame (computer too slow ?)" );
             p_sys->i_pts = VLC_TS_INVALID; /* To make sure we recover properly */
         }
-        block_Release( p_block );
+        if( p_block )
+            block_Release( p_block );
         p_sys->i_late_frames--;
         return NULL;
     }
@@ -504,7 +512,8 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
             /* picture too late, won't decode
              * but break picture until a new I, and for mpeg4 ...*/
             p_sys->i_late_frames--; /* needed else it will never be decrease */
-            block_Release( p_block );
+            if( p_block )
+                block_Release( p_block );
             return NULL;
         }
     }
@@ -512,7 +521,7 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
     {
         if( p_sys->b_hurry_up )
             p_context->skip_frame = p_sys->i_skip_frame;
-        if( !(p_block->i_flags & BLOCK_FLAG_PREROLL) )
+        if( !p_block || !(p_block->i_flags & BLOCK_FLAG_PREROLL) )
             b_drawpicture = 1;
         else
             b_drawpicture = 0;
@@ -540,7 +549,7 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
 
     /* Don't forget that libavcodec requires a little more bytes
      * that the real frame size */
-    if( p_block->i_buffer > 0 )
+    if( p_block && p_block->i_buffer > 0 )
     {
         p_sys->b_flush = ( p_block->i_flags & BLOCK_FLAG_END_OF_SEQUENCE ) != 0;
 
@@ -554,7 +563,7 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
                 FF_INPUT_BUFFER_PADDING_SIZE );
     }
 
-    while( p_block->i_buffer > 0 || p_sys->b_flush )
+    while( !p_block || p_block->i_buffer > 0 || p_sys->b_flush )
     {
         int i_used, b_gotpicture;
         picture_t *p_pic;
@@ -563,10 +572,19 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
         post_mt( p_sys );
 
         av_init_packet( &pkt );
-        pkt.data = p_block->p_buffer;
-        pkt.size = p_block->i_buffer;
-        pkt.pts = p_block->i_pts;
-        pkt.dts = p_block->i_dts;
+        if( p_block )
+        {
+            pkt.data = p_block->p_buffer;
+            pkt.size = p_block->i_buffer;
+            pkt.pts = p_block->i_pts;
+            pkt.dts = p_block->i_dts;
+        }
+        else
+        {
+            /* Return delayed frames if codec has CODEC_CAP_DELAY */
+            pkt.data = NULL;
+            pkt.size = 0;
+        }
 
 #if LIBAVCODEC_VERSION_MAJOR >= 54
         if( !p_sys->palette_sent )
@@ -580,8 +598,11 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
 #endif
 
         /* Make sure we don't reuse the same timestamps twice */
-        p_block->i_pts =
-        p_block->i_dts = VLC_TS_INVALID;
+        if( p_block )
+        {
+            p_block->i_pts =
+            p_block->i_dts = VLC_TS_INVALID;
+        }
 
         i_used = avcodec_decode_video2( p_context, p_sys->p_ff_pic,
                                        &b_gotpicture, &pkt );
@@ -601,26 +622,29 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
         if( p_sys->b_flush )
             p_sys->b_first_frame = true;
 
-        if( p_block->i_buffer <= 0 )
-            p_sys->b_flush = false;
-
-        if( i_used < 0 )
-        {
-            if( b_drawpicture )
-                msg_Warn( p_dec, "cannot decode one frame (%zu bytes)",
-                          p_block->i_buffer );
-            block_Release( p_block );
-            return NULL;
-        }
-        else if( (unsigned)i_used > p_block->i_buffer ||
-                 p_context->thread_count > 1 )
+        if( p_block )
         {
-            i_used = p_block->i_buffer;
-        }
+            if( p_block->i_buffer <= 0 )
+                p_sys->b_flush = false;
 
-        /* Consumed bytes */
-        p_block->i_buffer -= i_used;
-        p_block->p_buffer += i_used;
+            if( i_used < 0 )
+            {
+                if( b_drawpicture )
+                    msg_Warn( p_dec, "cannot decode one frame (%zu bytes)",
+                            p_block->i_buffer );
+                block_Release( p_block );
+                return NULL;
+            }
+            else if( (unsigned)i_used > p_block->i_buffer ||
+                    p_context->thread_count > 1 )
+            {
+                i_used = p_block->i_buffer;
+            }
+
+            /* Consumed bytes */
+            p_block->i_buffer -= i_used;
+            p_block->p_buffer += i_used;
+        }
 
         /* Nothing to display */
         if( !b_gotpicture )
@@ -673,7 +697,7 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
 
         /* Update frame late count (except when doing preroll) */
         mtime_t i_display_date = 0;
-        if( !(p_block->i_flags & BLOCK_FLAG_PREROLL) )
+        if( !p_block || !(p_block->i_flags & BLOCK_FLAG_PREROLL) )
             i_display_date = decoder_GetDisplayDate( p_dec, i_pts );
 
         if( i_display_date > 0 && i_display_date <= mdate() )
@@ -696,7 +720,8 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
             p_pic = ffmpeg_NewPictBuf( p_dec, p_context );
             if( !p_pic )
             {
-                block_Release( p_block );
+                if( p_block )
+                    block_Release( p_block );
                 return NULL;
             }
 
@@ -749,7 +774,8 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
         }
     }
 
-    block_Release( p_block );
+    if( p_block )
+        block_Release( p_block );
     return NULL;
 }
 



More information about the vlc-commits mailing list