[vlc-devel] [PATCH] codec: avcodec: rework for readframe loop

Francois Cartegnie fcvlcdev at free.fr
Mon Jun 12 22:09:15 CEST 2017


Changes to support multiple output per block
or delayed multiple output.
Also fixes draining, and some flags applied
to asynchronous output.

Unsure about the post_mt / wait_mt sections
correctness.
---
 modules/codec/avcodec/video.c | 466 ++++++++++++++++++++++++------------------
 1 file changed, 262 insertions(+), 204 deletions(-)

diff --git a/modules/codec/avcodec/video.c b/modules/codec/avcodec/video.c
index 83eac59..a4fba2a 100644
--- a/modules/codec/avcodec/video.c
+++ b/modules/codec/avcodec/video.c
@@ -48,6 +48,15 @@
 
 #include "../codec/cc.h"
 
+#define PACKET_HISTORY_DEPTH 64
+
+struct pkt_prop_s
+{
+    int64_t i_reordered_opaque;
+    bool    b_preroll;
+    bool    b_end_of_sequence;
+};
+
 /*****************************************************************************
  * decoder_sys_t : decoder descriptor
  *****************************************************************************/
@@ -77,8 +86,10 @@ struct decoder_sys_t
     atomic_bool b_dr_failure;
 
     /* Hack to force display of still pictures */
-    bool b_first_frame;
+    bool b_force_display;
 
+    /* Attach some data to decoded frames */
+    struct pkt_prop_s packets[PACKET_HISTORY_DEPTH];
 
     /* */
     bool palette_sent;
@@ -111,6 +122,7 @@ static enum PixelFormat ffmpeg_GetFormat( AVCodecContext *,
                                           const enum PixelFormat * );
 static int  DecodeVideo( decoder_t *, block_t * );
 static void Flush( decoder_t * );
+static int ReceiveFrame( decoder_t *p_dec, mtime_t );
 
 static uint32_t ffmpeg_CodecTag( vlc_fourcc_t fcc )
 {
@@ -515,6 +527,7 @@ int InitVideoDec( decoder_t *p_dec, AVCodecContext *p_context,
     p_context->get_buffer2 = lavc_GetFrame;
     p_context->refcounted_frames = true;
     p_context->opaque = p_dec;
+    p_context->reordered_opaque = 0;
 
     int i_thread_count = var_InheritInteger( p_dec, "avcodec-threads" );
     if( i_thread_count <= 0 )
@@ -557,7 +570,7 @@ int InitVideoDec( decoder_t *p_dec, AVCodecContext *p_context,
     /* ***** misc init ***** */
     date_Init(&p_sys->pts, 1, 30001);
     date_Set(&p_sys->pts, VLC_TS_INVALID);
-    p_sys->b_first_frame = true;
+    p_sys->b_force_display = true;
     p_sys->i_late_frames = 0;
     p_sys->b_from_preroll = false;
 
@@ -646,19 +659,10 @@ static bool check_block_validity( decoder_sys_t *p_sys, block_t *block )
 
 static bool check_block_being_late( decoder_sys_t *p_sys, block_t *block, mtime_t current_time)
 {
-    if( !block )
-        return false;
-    if( 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;
-        p_sys->b_from_preroll = true;
-        p_sys->i_last_late_delay = INT64_MAX;
-    }
-
-    if( p_sys->i_late_frames <= 0 )
+    /* 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) */
+    if( !block || (block->i_flags & BLOCK_FLAG_PREROLL) || p_sys->i_late_frames <= 0 )
         return false;
 
     if( current_time - p_sys->i_late_frames_start > (5*CLOCK_FREQ))
@@ -666,7 +670,6 @@ static bool check_block_being_late( decoder_sys_t *p_sys, block_t *block, mtime_
         date_Set( &p_sys->pts, VLC_TS_INVALID ); /* To make sure we recover properly */
         if( block )
             block_Release( block );
-        p_sys->i_late_frames--;
         return true;
     }
     return false;
@@ -711,36 +714,55 @@ static void interpolate_next_pts( decoder_t *p_dec, AVFrame *frame )
     date_Increment( &p_sys->pts, i_tick + frame->repeat_pict );
 }
 
-static void update_late_frame_count( decoder_t *p_dec, block_t *p_block, mtime_t current_time, mtime_t i_pts )
+static void update_late_frame_count( decoder_t *p_dec, mtime_t current_time, mtime_t i_pts, bool b_prerolling )
 {
     decoder_sys_t *p_sys = p_dec->p_sys;
-   /* Update frame late count (except when doing preroll) */
-   mtime_t i_display_date = VLC_TS_INVALID;
-   if( !p_block || !(p_block->i_flags & BLOCK_FLAG_PREROLL) )
-       i_display_date = decoder_GetDisplayDate( p_dec, i_pts );
-
-   if( i_display_date > VLC_TS_INVALID && i_display_date <= current_time )
-   {
-       /* Out of preroll, consider only late frames on rising delay */
-       if( p_sys->b_from_preroll )
-       {
-           if( p_sys->i_last_late_delay > current_time - i_display_date )
-           {
-               p_sys->i_last_late_delay = current_time - i_display_date;
-               return;
-           }
-           p_sys->b_from_preroll = false;
-       }
-
-       p_sys->i_late_frames++;
-       if( p_sys->i_late_frames == 1 )
-           p_sys->i_late_frames_start = current_time;
-
-   }
-   else
-   {
-       p_sys->i_late_frames = 0;
-   }
+    /* Update frame late count (except when doing preroll) */
+    if( b_prerolling )
+    {
+        p_sys->b_from_preroll = true;
+        p_sys->i_late_frames = 0;
+        p_sys->i_last_late_delay = 0;
+        p_sys->i_late_frames_start = VLC_TS_INVALID;
+        return;
+    }
+
+    const mtime_t i_display_date = decoder_GetDisplayDate( p_dec, i_pts );
+    if( i_display_date == VLC_TS_INVALID )
+        return;
+    const mtime_t i_diff = current_time - i_display_date;
+
+    if( i_diff > 0 && p_sys->pts.i_divider_num > 0 )
+    {
+        date_t pts = p_sys->pts;
+        date_Increment( &pts, __MAX(1, p_sys->p_context->ticks_per_frame) );
+        /* output can vary have varying delay by few a ms (and reject inter frame delay delta) */
+        const int64_t i_framelength = date_Get( &pts ) - date_Get( &p_sys->pts );
+        /* Out of preroll, consider only late frames on rising delay */
+        if( i_framelength > 0 && !p_sys->b_from_preroll &&
+            p_sys->i_last_late_delay / i_framelength < i_diff / i_framelength )
+        {
+            if( p_sys->i_late_frames < 12 )
+                p_sys->i_late_frames++;
+            if( p_sys->i_late_frames == 1 )
+                p_sys->i_late_frames_start = current_time;
+            p_sys->b_from_preroll = false;
+        }
+    }
+    else
+    {
+        p_sys->b_from_preroll = b_prerolling;
+        if(p_sys->i_late_frames > 0)
+            p_sys->i_late_frames--;
+    }
+
+    p_sys->i_last_late_delay = __MAX(i_diff, 0);
+
+    if(p_sys->i_late_frames == 0)
+    {
+        p_sys->i_last_late_delay = 0;
+        p_sys->i_late_frames_start = VLC_TS_INVALID;
+    }
 }
 
 
@@ -851,7 +873,7 @@ static void DecodeSidedata( decoder_t *p_dec, const AVFrame *frame, picture_t *p
 /*****************************************************************************
  * DecodeBlock: Called to decode one or more frames
  *****************************************************************************/
-static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block, bool *error )
+static int DecodeBlock( decoder_t *p_dec, block_t **pp_block, bool *error )
 {
     decoder_sys_t *p_sys = p_dec->p_sys;
     AVCodecContext *p_context = p_sys->p_context;
@@ -859,8 +881,7 @@ static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block, bool *error
     bool b_need_output_picture = true;
 
     /* Boolean for END_OF_SEQUENCE */
-    bool eos_spotted = false;
-
+    bool b_end_of_sequence = false;
 
     block_t *p_block;
     mtime_t current_time = VLC_TS_INVALID;
@@ -874,24 +895,25 @@ static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block, bool *error
 
     p_block = pp_block ? *pp_block : NULL;
     if(!p_block && !(p_sys->p_codec->capabilities & AV_CODEC_CAP_DELAY) )
-        return NULL;
+        return VLC_EGENERIC;
 
     if( p_sys->b_delayed_open )
     {
         if( p_block )
             block_Release( p_block );
-        return NULL;
+        return VLC_EGENERIC;
     }
 
     if( !check_block_validity( p_sys, p_block ) )
-        return NULL;
+        return VLC_EGENERIC;
 
     current_time = mdate();
     if( p_dec->b_frame_drop_allowed &&  check_block_being_late( p_sys, p_block, current_time) )
     {
+        p_sys->i_late_frames--;
         msg_Err( p_dec, "more than 5 seconds of late video -> "
                  "dropping frame (computer too slow ?)" );
-        return NULL;
+        return VLC_EGENERIC;
     }
 
 
@@ -899,7 +921,7 @@ static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block, bool *error
 
     /* Defaults that if we aren't in prerolling, we want output picture
        same for if we are flushing (p_block==NULL) */
-    if( !p_block || !(p_block->i_flags & BLOCK_FLAG_PREROLL) )
+    if( !p_block || !(p_block->i_flags & (BLOCK_FLAG_PREROLL|BLOCK_FLAG_END_OF_SEQUENCE)) )
         b_need_output_picture = true;
     else
         b_need_output_picture = false;
@@ -917,7 +939,7 @@ static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block, bool *error
             if( p_block )
                 block_Release( p_block );
             msg_Warn( p_dec, "More than 11 late frames, dropping frame" );
-            return NULL;
+            return VLC_EGENERIC;
         }
     }
     if( !b_need_output_picture )
@@ -933,25 +955,23 @@ static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block, bool *error
      * that the real frame size */
     if( p_block && p_block->i_buffer > 0 )
     {
-        eos_spotted = ( p_block->i_flags & BLOCK_FLAG_END_OF_SEQUENCE ) != 0;
+        b_end_of_sequence = ( p_block->i_flags & BLOCK_FLAG_END_OF_SEQUENCE ) != 0;
 
         p_block = block_Realloc( p_block, 0,
                             p_block->i_buffer + FF_INPUT_BUFFER_PADDING_SIZE );
         if( !p_block )
-            return NULL;
+            return VLC_SUCCESS;
         p_block->i_buffer -= FF_INPUT_BUFFER_PADDING_SIZE;
         *pp_block = p_block;
         memset( p_block->p_buffer + p_block->i_buffer, 0,
                 FF_INPUT_BUFFER_PADDING_SIZE );
     }
 
-    while( !p_block || p_block->i_buffer > 0 || eos_spotted )
+    while( !p_block || p_block->i_buffer > 0 )
     {
-        int i_used;
+        size_t i_used = 0;
         AVPacket pkt;
 
-        post_mt( p_sys );
-
         av_init_packet( &pkt );
         if( p_block && p_block->i_buffer > 0 )
         {
@@ -987,8 +1007,9 @@ static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block, bool *error
         if( !b_need_output_picture )
             pkt.flags |= AV_PKT_FLAG_DISCARD;
 #endif
-
+        post_mt( p_sys );
         int ret = avcodec_send_packet(p_context, &pkt);
+        wait_mt( p_sys );
         if( ret != 0 && ret != AVERROR(EAGAIN) )
         {
             if (ret == AVERROR(ENOMEM) || ret == AVERROR(EINVAL))
@@ -999,201 +1020,238 @@ static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block, bool *error
             av_packet_unref( &pkt );
             break;
         }
+
+        struct pkt_prop_s *p_prop = &p_sys->packets[p_context->reordered_opaque % PACKET_HISTORY_DEPTH];
+        p_prop->b_preroll = (p_block && (p_block->i_flags & BLOCK_FLAG_PREROLL));
+        p_prop->b_end_of_sequence = (p_block && (p_block->i_flags & BLOCK_FLAG_END_OF_SEQUENCE));
+        p_prop->i_reordered_opaque = p_context->reordered_opaque++;
+        if( p_prop->b_preroll )
+            p_sys->b_from_preroll = true;
+
         i_used = ret != AVERROR(EAGAIN) ? pkt.size : 0;
         av_packet_unref( &pkt );
 
-        AVFrame *frame = av_frame_alloc();
-        if (unlikely(frame == NULL))
+        if( p_block )
         {
-            *error = true;
-            break;
+            /* Consumed bytes */
+            p_block->p_buffer += i_used;
+            if( i_used < p_block->i_buffer )
+                p_block->i_buffer -= i_used;
+            else
+                p_block->i_buffer = 0;
         }
 
-        ret = avcodec_receive_frame(p_context, frame);
-        if( ret != 0 && ret != AVERROR(EAGAIN) )
+        do
         {
-            if (ret == AVERROR(ENOMEM) || ret == AVERROR(EINVAL))
-            {
-                msg_Err(p_dec, "avcodec_receive_frame critical error");
-                *error = true;
-            }
-            av_frame_free(&frame);
-            /* After draining, we need to reset decoder with a flush */
-            if( ret == AVERROR_EOF )
-                avcodec_flush_buffers( p_sys->p_context );
+            post_mt( p_sys );
+            ret = ReceiveFrame( p_dec, current_time );
+            wait_mt( p_sys );
+
+
+        } while ( ret == VLC_SUCCESS );
+
+        if( ret == VLC_EGENERIC )
+            *error = true;
+
+        if( ret != VLC_SUCCESS || !p_block || p_block->i_buffer == 0 )
             break;
-        }
-        bool not_received_frame = ret;
+    }
 
-        wait_mt( p_sys );
+    if( p_block )
+        block_Release( p_block );
 
-        if( eos_spotted )
-            p_sys->b_first_frame = true;
+    /* Need to drain after EOS packet */
+    if( b_end_of_sequence && !*error )
+        DecodeBlock( p_dec, NULL, error );
 
-        if( p_block )
-        {
-            if( p_block->i_buffer <= 0 )
-                eos_spotted = false;
+    return VLC_SUCCESS;
+}
 
-            /* Consumed bytes */
-            p_block->p_buffer += i_used;
-            p_block->i_buffer -= i_used;
-        }
+static int ReceiveFrame( decoder_t *p_dec, mtime_t current_time )
+{
+    decoder_sys_t *p_sys = p_dec->p_sys;
+    AVCodecContext *p_context = p_sys->p_context;
+
+    AVFrame *frame = av_frame_alloc();
+    if (unlikely(frame == NULL))
+        return VLC_EGENERIC;
 
-        /* Nothing to display */
-        if( not_received_frame )
+    int ret = avcodec_receive_frame(p_context, frame);
+    if( ret != 0 && ret != AVERROR(EAGAIN) )
+    {
+        av_frame_free(&frame);
+        /* After draining, we need to reset decoder with a flush */
+        if( ret == AVERROR_EOF )
         {
-            av_frame_free(&frame);
-            if( i_used == 0 ) break;
-            continue;
+            avcodec_flush_buffers( p_sys->p_context );
         }
+        else
+        {
+            char errbuf[AV_ERROR_MAX_STRING_SIZE];
+            av_strerror(ret, errbuf, AV_ERROR_MAX_STRING_SIZE);
+            msg_Err(p_dec, "avcodec_receive_frame %s", errbuf);
+            if (ret == AVERROR(ENOMEM) || ret == AVERROR(EINVAL))
+                return VLC_EGENERIC;
+        }
+        return VLC_ENOITEM;
+    }
+    bool not_received_frame = ret;
 
-        /* Compute the PTS */
+    /* Nothing to display */
+    if( not_received_frame )
+    {
+        av_frame_free(&frame);
+        return VLC_ENOITEM;
+    }
+
+    /* Get stored properties */
+    struct pkt_prop_s *p_prop = &p_sys->packets[frame->reordered_opaque % PACKET_HISTORY_DEPTH];
+    if( p_prop->i_reordered_opaque != frame->reordered_opaque )
+        p_prop = NULL;
+    else if( p_prop->b_end_of_sequence )
+        p_sys->b_force_display = true;
+
+    /* Compute the PTS */
 #ifdef FF_API_PKT_PTS
-        mtime_t i_pts = frame->pts;
+    mtime_t i_pts = frame->pts;
 #else
-        mtime_t i_pts = frame->pkt_pts;
+    mtime_t i_pts = frame->pkt_pts;
 #endif
-        if (i_pts == AV_NOPTS_VALUE )
-            i_pts = frame->pkt_dts;
+    if (i_pts == AV_NOPTS_VALUE )
+        i_pts = frame->pkt_dts;
 
-        if( i_pts == AV_NOPTS_VALUE )
-            i_pts = date_Get( &p_sys->pts );
+    if( i_pts == AV_NOPTS_VALUE )
+        i_pts = date_Get( &p_sys->pts );
 
-        /* Interpolate the next PTS */
-        if( i_pts > VLC_TS_INVALID )
-            date_Set( &p_sys->pts, i_pts );
+    /* Interpolate the next PTS */
+    if( i_pts > VLC_TS_INVALID )
+        date_Set( &p_sys->pts, i_pts );
 
-        interpolate_next_pts( p_dec, frame );
+    interpolate_next_pts( p_dec, frame );
+
+    update_late_frame_count( p_dec, current_time, i_pts, (p_prop && p_prop->b_preroll) );
+
+    if( ( !p_sys->p_va && !frame->linesize[0] ) ||
+       ( p_dec->b_frame_drop_allowed && (frame->flags & AV_FRAME_FLAG_CORRUPT) &&
+         !p_sys->b_show_corrupted ) )
+    {
+        av_frame_free(&frame);
+        return VLC_SUCCESS;
+    }
 
-        update_late_frame_count( p_dec, p_block, current_time, i_pts);
+#if !LIBAVCODEC_VERSION_CHECK( 57, 0, 0xFFFFFFFFU, 64, 101 )
+    if( !b_need_output_picture )
+    {
+        av_frame_free(&frame);
+        return VLC_SUCCESS;
+    }
+#endif
 
-        if( ( !p_sys->p_va && !frame->linesize[0] ) ||
-           ( p_dec->b_frame_drop_allowed && (frame->flags & AV_FRAME_FLAG_CORRUPT) &&
-             !p_sys->b_show_corrupted ) )
+    if( p_context->pix_fmt == AV_PIX_FMT_PAL8
+     && !p_dec->fmt_out.video.p_palette )
+    {
+        /* See AV_PIX_FMT_PAL8 comment in avc_GetVideoFormat(): update the
+         * fmt_out palette and change the fmt_out chroma to request a new
+         * vout */
+        assert( p_dec->fmt_out.video.i_chroma != VLC_CODEC_RGBP );
+
+        video_palette_t *p_palette;
+        p_palette = p_dec->fmt_out.video.p_palette
+                  = malloc( sizeof(video_palette_t) );
+        if( !p_palette )
         {
             av_frame_free(&frame);
-            continue;
+            return VLC_EGENERIC;
         }
-
-#if !LIBAVCODEC_VERSION_CHECK( 57, 0, 0xFFFFFFFFU, 64, 101 )
-        if( !b_need_output_picture )
+        static_assert( sizeof(p_palette->palette) == AVPALETTE_SIZE,
+                       "Palette size mismatch between vlc and libavutil" );
+        assert( frame->data[1] != NULL );
+        memcpy( p_palette->palette, frame->data[1], AVPALETTE_SIZE );
+        p_palette->i_entries = AVPALETTE_COUNT;
+        p_dec->fmt_out.video.i_chroma = VLC_CODEC_RGBP;
+        if( decoder_UpdateVideoFormat( p_dec ) )
         {
             av_frame_free(&frame);
-            continue;
+            return VLC_SUCCESS;
         }
-#endif
+    }
 
-        if( p_context->pix_fmt == AV_PIX_FMT_PAL8
-         && !p_dec->fmt_out.video.p_palette )
+    picture_t *p_pic = frame->opaque;
+    if( p_pic == NULL )
+    {   /* When direct rendering is not used, get_format() and get_buffer()
+         * might not be called. The output video format must be set here
+         * then picture buffer can be allocated. */
+        if (p_sys->p_va == NULL
+         && lavc_UpdateVideoFormat(p_dec, p_context, p_context->pix_fmt,
+                                   p_context->pix_fmt) == 0)
+            p_pic = decoder_NewPicture(p_dec);
+
+        if( !p_pic )
         {
-            /* See AV_PIX_FMT_PAL8 comment in avc_GetVideoFormat(): update the
-             * fmt_out palette and change the fmt_out chroma to request a new
-             * vout */
-            assert( p_dec->fmt_out.video.i_chroma != VLC_CODEC_RGBP );
-
-            video_palette_t *p_palette;
-            p_palette = p_dec->fmt_out.video.p_palette
-                      = malloc( sizeof(video_palette_t) );
-            if( !p_palette )
-            {
-                *error = true;
-                av_frame_free(&frame);
-                break;
-            }
-            static_assert( sizeof(p_palette->palette) == AVPALETTE_SIZE,
-                           "Palette size mismatch between vlc and libavutil" );
-            assert( frame->data[1] != NULL );
-            memcpy( p_palette->palette, frame->data[1], AVPALETTE_SIZE );
-            p_palette->i_entries = AVPALETTE_COUNT;
-            p_dec->fmt_out.video.i_chroma = VLC_CODEC_RGBP;
-            if( decoder_UpdateVideoFormat( p_dec ) )
-            {
-                av_frame_free(&frame);
-                continue;
-            }
+            av_frame_free(&frame);
+            return VLC_SUCCESS;
         }
 
-        picture_t *p_pic = frame->opaque;
-        if( p_pic == NULL )
-        {   /* When direct rendering is not used, get_format() and get_buffer()
-             * might not be called. The output video format must be set here
-             * then picture buffer can be allocated. */
-            if (p_sys->p_va == NULL
-             && lavc_UpdateVideoFormat(p_dec, p_context, p_context->pix_fmt,
-                                       p_context->pix_fmt) == 0)
-                p_pic = decoder_NewPicture(p_dec);
-
-            if( !p_pic )
-            {
-                av_frame_free(&frame);
-                break;
-            }
-
-            /* Fill picture_t from AVFrame */
-            if( lavc_CopyPicture( p_dec, p_pic, frame ) != VLC_SUCCESS )
-            {
-                *error = true;
-                av_frame_free(&frame);
-                picture_Release( p_pic );
-                break;
-            }
-        }
-        else
+        /* Fill picture_t from AVFrame */
+        if( lavc_CopyPicture( p_dec, p_pic, frame ) != VLC_SUCCESS )
         {
-            if( p_sys->p_va != NULL )
-                vlc_va_Extract( p_sys->p_va, p_pic, frame->data[3] );
-            picture_Hold( p_pic );
+            av_frame_free(&frame);
+            picture_Release( p_pic );
+            return VLC_EGENERIC;
         }
+    }
+    else
+    {
+        if( p_sys->p_va != NULL )
+            vlc_va_Extract( p_sys->p_va, p_pic, frame->data[3] );
+        picture_Hold( p_pic );
+    }
 
-        if( !p_dec->fmt_in.video.i_sar_num || !p_dec->fmt_in.video.i_sar_den )
-        {
-            /* Fetch again the aspect ratio in case it changed */
-            p_dec->fmt_out.video.i_sar_num
-                = p_context->sample_aspect_ratio.num;
-            p_dec->fmt_out.video.i_sar_den
-                = p_context->sample_aspect_ratio.den;
+    if( !p_dec->fmt_in.video.i_sar_num || !p_dec->fmt_in.video.i_sar_den )
+    {
+        /* Fetch again the aspect ratio in case it changed */
+        p_dec->fmt_out.video.i_sar_num
+            = p_context->sample_aspect_ratio.num;
+        p_dec->fmt_out.video.i_sar_den
+            = p_context->sample_aspect_ratio.den;
 
-            if( !p_dec->fmt_out.video.i_sar_num || !p_dec->fmt_out.video.i_sar_den )
-            {
-                p_dec->fmt_out.video.i_sar_num = 1;
-                p_dec->fmt_out.video.i_sar_den = 1;
-            }
+        if( !p_dec->fmt_out.video.i_sar_num || !p_dec->fmt_out.video.i_sar_den )
+        {
+            p_dec->fmt_out.video.i_sar_num = 1;
+            p_dec->fmt_out.video.i_sar_den = 1;
         }
+    }
 
-        p_pic->date = i_pts;
-        /* Hack to force display of still pictures */
-        p_pic->b_force = p_sys->b_first_frame;
-        p_pic->i_nb_fields = 2 + frame->repeat_pict;
-        p_pic->b_progressive = !frame->interlaced_frame;
-        p_pic->b_top_field_first = frame->top_field_first;
+    p_pic->date = i_pts;
+    /* Hack to force display of still pictures */
+    p_pic->b_force = p_sys->b_force_display;
+    p_pic->i_nb_fields = 2 + frame->repeat_pict;
+    p_pic->b_progressive = !frame->interlaced_frame;
+    p_pic->b_top_field_first = frame->top_field_first;
 
-        DecodeSidedata( p_dec, frame, p_pic );
+    DecodeSidedata( p_dec, frame, p_pic );
 
-        av_frame_free(&frame);
+    av_frame_free(&frame);
 
-        /* Send decoded frame to vout */
-        if (i_pts > VLC_TS_INVALID)
-        {
-            p_sys->b_first_frame = false;
-            return p_pic;
-        }
-        else
-            picture_Release( p_pic );
+    /* Send decoded frame to vout */
+    if (i_pts > VLC_TS_INVALID)
+    {
+        p_sys->b_force_display = false;
+        decoder_QueueVideo( p_dec, p_pic );
     }
+    else
+        picture_Release( p_pic );
 
-    if( p_block )
-        block_Release( p_block );
-    return NULL;
+    return VLC_SUCCESS;
 }
 
 static int DecodeVideo( decoder_t *p_dec, block_t *p_block )
 {
     block_t **pp_block = p_block ? &p_block : NULL;
-    picture_t *p_pic;
+
     bool error = false;
-    while( ( p_pic = DecodeBlock( p_dec, pp_block, &error ) ) != NULL )
-        decoder_QueueVideo( p_dec, p_pic );
+    DecodeBlock( p_dec, pp_block, &error );
+
     return error ? VLCDEC_ECRITICAL : VLCDEC_SUCCESS;
 }
 
-- 
2.9.4



More information about the vlc-devel mailing list