[FFmpeg-cvslog] lavf: flush decoders in avformat_find_stream_info().

Anton Khirnov git at videolan.org
Wed Jan 4 01:39:32 CET 2012


ffmpeg | branch: master | Anton Khirnov <anton at khirnov.net> | Mon Jan  2 09:01:02 2012 +0100| [212fd3a1f1121a9db20c478f1fccf15e8bb53c94] | committer: Anton Khirnov

lavf: flush decoders in avformat_find_stream_info().

This means that avformat_find_stream_info() now works properly with
multiple threads, so there's no need to force thread count to 1.

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=212fd3a1f1121a9db20c478f1fccf15e8bb53c94
---

 libavformat/utils.c |   38 +++++++++++++++++++-------------------
 1 files changed, 19 insertions(+), 19 deletions(-)

diff --git a/libavformat/utils.c b/libavformat/utils.c
index 163d602..db02878 100644
--- a/libavformat/utils.c
+++ b/libavformat/utils.c
@@ -2126,7 +2126,7 @@ static int has_decode_delay_been_guessed(AVStream *st)
 static int try_decode_frame(AVStream *st, AVPacket *avpkt, AVDictionary **options)
 {
     AVCodec *codec;
-    int got_picture, ret = 0;
+    int got_picture = 1, ret = 0;
     AVFrame picture;
     AVPacket pkt = *avpkt;
 
@@ -2139,7 +2139,8 @@ static int try_decode_frame(AVStream *st, AVPacket *avpkt, AVDictionary **option
             return ret;
     }
 
-    while (pkt.size > 0 && ret >= 0 &&
+    while ((pkt.size > 0 || (!pkt.data && got_picture)) &&
+           ret >= 0 &&
            (!has_codec_parameters(st->codec)  ||
            !has_decode_delay_been_guessed(st) ||
            (!st->codec_info_nb_frames && st->codec->codec->capabilities & CODEC_CAP_CHANNEL_CONF))) {
@@ -2268,14 +2269,9 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
     int i, count, ret, read_size, j;
     AVStream *st;
     AVPacket pkt1, *pkt;
-    AVDictionary *one_thread_opt = NULL;
     int64_t old_offset = avio_tell(ic->pb);
     int orig_nb_streams = ic->nb_streams;        // new streams might appear, no options for those
 
-    /* this function doesn't flush the decoders, so force thread count
-     * to 1 to fix behavior when thread count > number of frames in the file */
-    av_dict_set(&one_thread_opt, "threads", "1", 0);
-
     for(i=0;i<ic->nb_streams;i++) {
         AVCodec *codec;
         st = ic->streams[i];
@@ -2297,21 +2293,15 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
         assert(!st->codec->codec);
         codec = avcodec_find_decoder(st->codec->codec_id);
 
-        /* this function doesn't flush the decoders, so force thread count
-         * to 1 to fix behavior when thread count > number of frames in the file */
-        if (options)
-            av_dict_set(&options[i], "threads", "1", 0);
-
         /* Ensure that subtitle_header is properly set. */
         if (st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE
             && codec && !st->codec->codec)
-            avcodec_open2(st->codec, codec, options ? &options[i] : &one_thread_opt);
+            avcodec_open2(st->codec, codec, options ? &options[i] : NULL);
 
         //try to just open decoders, in case this is enough to get parameters
         if(!has_codec_parameters(st->codec)){
             if (codec && !st->codec->codec)
-                avcodec_open2(st->codec, codec, options ? &options[i]
-                              : &one_thread_opt);
+                avcodec_open2(st->codec, codec, options ? &options[i] : NULL);
         }
     }
 
@@ -2377,10 +2367,22 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
             continue;
 
         if (ret < 0) {
-            /* EOF or error */
+            /* EOF or error*/
+            AVPacket empty_pkt = { 0 };
+            int err;
+            av_init_packet(&empty_pkt);
+
             ret = -1; /* we could not have all the codec parameters before EOF */
             for(i=0;i<ic->nb_streams;i++) {
                 st = ic->streams[i];
+
+                /* flush the decoders */
+                while ((err = try_decode_frame(st, &empty_pkt,
+                                               (options && i < orig_nb_streams) ?
+                                                &options[i] : NULL)) >= 0)
+                    if (has_codec_parameters(st->codec))
+                        break;
+
                 if (!has_codec_parameters(st->codec)){
                     char buf[256];
                     avcodec_string(buf, sizeof(buf), st->codec, 0);
@@ -2450,8 +2452,7 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
            least one frame of codec data, this makes sure the codec initializes
            the channel configuration and does not only trust the values from the container.
         */
-        try_decode_frame(st, pkt, (options && i < orig_nb_streams )? &options[i]
-                         : &one_thread_opt);
+        try_decode_frame(st, pkt, (options && i < orig_nb_streams ) ? &options[i] : NULL);
 
         st->codec_info_nb_frames++;
         count++;
@@ -2561,7 +2562,6 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
             ic->streams[i]->codec->thread_count = 0;
         av_freep(&ic->streams[i]->info);
     }
-    av_dict_free(&one_thread_opt);
     return ret;
 }
 



More information about the ffmpeg-cvslog mailing list