avconv: maintain sync on lavfi outputs.

Before this commit, poll_filters() reads all frames available on each
lavfi output. This does not work for lavfi sources that produce
an unlimited number of frames, e.g. color and similar.

With this commit, poll_filters() reads from output with the lowest
timestamp and returns to wait for more input if no frames are available
on it.
This commit is contained in:
Anton Khirnov 2012-08-03 22:09:58 +02:00
parent 5864eb427f
commit a4f5011065

View File

@ -644,20 +644,15 @@ static void do_video_stats(AVFormatContext *os, OutputStream *ost,
}
}
/* check for new output on any of the filtergraphs */
static int poll_filters(void)
/**
* Read one frame for lavfi output for ost and encode it.
*/
static int poll_filter(OutputStream *ost)
{
OutputFile *of = output_files[ost->file_index];
AVFilterBufferRef *picref;
AVFrame *filtered_frame = NULL;
int i, frame_size;
for (i = 0; i < nb_output_streams; i++) {
OutputStream *ost = output_streams[i];
OutputFile *of = output_files[ost->file_index];
int ret = 0;
if (!ost->filter)
continue;
int frame_size, ret;
if (!ost->filtered_frame && !(ost->filtered_frame = avcodec_alloc_frame())) {
return AVERROR(ENOMEM);
@ -665,7 +660,6 @@ static int poll_filters(void)
avcodec_get_frame_defaults(ost->filtered_frame);
filtered_frame = ost->filtered_frame;
while (ret >= 0 && !ost->is_past_recording_time) {
if (ost->enc->type == AVMEDIA_TYPE_AUDIO &&
!(ost->enc->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE))
ret = av_buffersink_read_samples(ost->filter->filter, &picref,
@ -673,9 +667,7 @@ static int poll_filters(void)
else
ret = av_buffersink_read(ost->filter->filter, &picref);
if (ret == AVERROR_EOF || ret == AVERROR(EAGAIN))
break;
else if (ret < 0)
if (ret < 0)
return ret;
avfilter_copy_buf_props(filtered_frame, picref);
@ -689,7 +681,7 @@ static int poll_filters(void)
if (of->start_time && filtered_frame->pts < 0) {
avfilter_unref_buffer(picref);
continue;
return 0;
}
}
@ -713,11 +705,61 @@ static int poll_filters(void)
}
avfilter_unref_buffer(picref);
}
}
return 0;
}
/**
* Read as many frames from possible from lavfi and encode them.
*
* Always read from the active stream with the lowest timestamp. If no frames
* are available for it then return EAGAIN and wait for more input. This way we
* can use lavfi sources that generate unlimited amount of frames without memory
* usage exploding.
*/
static int poll_filters(void)
{
int i, ret = 0;
while (ret >= 0 && !received_sigterm) {
OutputStream *ost = NULL;
int64_t min_pts = INT64_MAX;
/* choose output stream with the lowest timestamp */
for (i = 0; i < nb_output_streams; i++) {
int64_t pts = output_streams[i]->sync_opts;
if (!output_streams[i]->filter ||
output_streams[i]->is_past_recording_time)
continue;
pts = av_rescale_q(pts, output_streams[i]->st->codec->time_base,
AV_TIME_BASE_Q);
if (pts < min_pts) {
min_pts = pts;
ost = output_streams[i];
}
}
if (!ost)
break;
ret = poll_filter(ost);
if (ret == AVERROR_EOF) {
ost->is_past_recording_time = 1;
if (opt_shortest)
return ret;
ret = 0;
} else if (ret == AVERROR(EAGAIN))
return 0;
}
return ret;
}
static void print_report(int is_last_report, int64_t timer_start)
{
char buf[1024];