Commit 212fd3a1 authored by Anton Khirnov's avatar 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.
parent 02e8f427
...@@ -2126,7 +2126,7 @@ static int has_decode_delay_been_guessed(AVStream *st) ...@@ -2126,7 +2126,7 @@ static int has_decode_delay_been_guessed(AVStream *st)
static int try_decode_frame(AVStream *st, AVPacket *avpkt, AVDictionary **options) static int try_decode_frame(AVStream *st, AVPacket *avpkt, AVDictionary **options)
{ {
AVCodec *codec; AVCodec *codec;
int got_picture, ret = 0; int got_picture = 1, ret = 0;
AVFrame picture; AVFrame picture;
AVPacket pkt = *avpkt; AVPacket pkt = *avpkt;
...@@ -2139,7 +2139,8 @@ static int try_decode_frame(AVStream *st, AVPacket *avpkt, AVDictionary **option ...@@ -2139,7 +2139,8 @@ static int try_decode_frame(AVStream *st, AVPacket *avpkt, AVDictionary **option
return ret; return ret;
} }
while (pkt.size > 0 && ret >= 0 && while ((pkt.size > 0 || (!pkt.data && got_picture)) &&
ret >= 0 &&
(!has_codec_parameters(st->codec) || (!has_codec_parameters(st->codec) ||
!has_decode_delay_been_guessed(st) || !has_decode_delay_been_guessed(st) ||
(!st->codec_info_nb_frames && st->codec->codec->capabilities & CODEC_CAP_CHANNEL_CONF))) { (!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) ...@@ -2268,14 +2269,9 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
int i, count, ret, read_size, j; int i, count, ret, read_size, j;
AVStream *st; AVStream *st;
AVPacket pkt1, *pkt; AVPacket pkt1, *pkt;
AVDictionary *one_thread_opt = NULL;
int64_t old_offset = avio_tell(ic->pb); int64_t old_offset = avio_tell(ic->pb);
int orig_nb_streams = ic->nb_streams; // new streams might appear, no options for those 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++) { for(i=0;i<ic->nb_streams;i++) {
AVCodec *codec; AVCodec *codec;
st = ic->streams[i]; st = ic->streams[i];
...@@ -2297,21 +2293,15 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) ...@@ -2297,21 +2293,15 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
assert(!st->codec->codec); assert(!st->codec->codec);
codec = avcodec_find_decoder(st->codec->codec_id); 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. */ /* Ensure that subtitle_header is properly set. */
if (st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE if (st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE
&& codec && !st->codec->codec) && 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 //try to just open decoders, in case this is enough to get parameters
if(!has_codec_parameters(st->codec)){ if(!has_codec_parameters(st->codec)){
if (codec && !st->codec->codec) if (codec && !st->codec->codec)
avcodec_open2(st->codec, codec, options ? &options[i] avcodec_open2(st->codec, codec, options ? &options[i] : NULL);
: &one_thread_opt);
} }
} }
...@@ -2377,10 +2367,22 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) ...@@ -2377,10 +2367,22 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
continue; continue;
if (ret < 0) { 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 */ ret = -1; /* we could not have all the codec parameters before EOF */
for(i=0;i<ic->nb_streams;i++) { for(i=0;i<ic->nb_streams;i++) {
st = ic->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)){ if (!has_codec_parameters(st->codec)){
char buf[256]; char buf[256];
avcodec_string(buf, sizeof(buf), st->codec, 0); avcodec_string(buf, sizeof(buf), st->codec, 0);
...@@ -2450,8 +2452,7 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) ...@@ -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 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. 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] try_decode_frame(st, pkt, (options && i < orig_nb_streams ) ? &options[i] : NULL);
: &one_thread_opt);
st->codec_info_nb_frames++; st->codec_info_nb_frames++;
count++; count++;
...@@ -2561,7 +2562,6 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) ...@@ -2561,7 +2562,6 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
ic->streams[i]->codec->thread_count = 0; ic->streams[i]->codec->thread_count = 0;
av_freep(&ic->streams[i]->info); av_freep(&ic->streams[i]->info);
} }
av_dict_free(&one_thread_opt);
return ret; return ret;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment