Browse Source

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.
tags/n0.10
Anton Khirnov 14 years ago
parent
commit
212fd3a1f1
1 changed files with 19 additions and 19 deletions
  1. +19
    -19
      libavformat/utils.c

+ 19
- 19
libavformat/utils.c View File

@@ -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
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)
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)
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]
: &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; 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)
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]
: &one_thread_opt);
try_decode_frame(st, pkt, (options && i < orig_nb_streams ) ? &options[i] : NULL);


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)
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;
} }




Loading…
Cancel
Save