[FFmpeg-devel] [PATCH 4/6] ffmpeg: flush and drain video filters.
Nicolas George
nicolas.george at normalesup.org
Sun Mar 11 00:29:48 CET 2012
When EOF is reached on the input stream, ffmpeg must
ensure that the graph input returns EOF instead of EAGAIN
and request frames once more until exhaustion.
Signed-off-by: Nicolas George <nicolas.george at normalesup.org>
---
ffmpeg.c | 38 ++++++++++++++++++++++++++++----------
1 files changed, 28 insertions(+), 10 deletions(-)
diff --git a/ffmpeg.c b/ffmpeg.c
index 4714b61..abcf328 100644
--- a/ffmpeg.c
+++ b/ffmpeg.c
@@ -2082,7 +2082,7 @@ static int transcode_audio(InputStream *ist, AVPacket *pkt, int *got_output)
return ret;
}
-static int transcode_video(InputStream *ist, AVPacket *pkt, int *got_output, int64_t *pkt_pts)
+static int transcode_video(InputStream *ist, AVPacket *pkt, int *got_output, int64_t *pkt_pts, int flush)
{
AVFrame *decoded_frame;
void *buffer_to_free = NULL;
@@ -2105,10 +2105,14 @@ static int transcode_video(InputStream *ist, AVPacket *pkt, int *got_output, int
return ret;
if (!*got_output) {
- /* no picture yet */
+#if CONFIG_AVFILTER
+ if (!flush)
+#endif
return ret;
}
+ if (*got_output) {
+ /* TODO reindent */
best_effort_timestamp= av_opt_ptr(avcodec_get_frame_class(), decoded_frame, "best_effort_timestamp");
if(*best_effort_timestamp != AV_NOPTS_VALUE)
ist->next_pts = ist->pts = decoded_frame->pts = *best_effort_timestamp;
@@ -2116,12 +2120,15 @@ static int transcode_video(InputStream *ist, AVPacket *pkt, int *got_output, int
pkt->size = 0;
pre_process_video_frame(ist, (AVPicture *)decoded_frame, &buffer_to_free);
+ }
#if CONFIG_AVFILTER
frame_sample_aspect= av_opt_ptr(avcodec_get_frame_class(), decoded_frame, "sample_aspect_ratio");
for(i=0;i<nb_output_streams;i++) {
OutputStream *ost = ost = &output_streams[i];
if(check_output_constraints(ist, ost) && ost->encoding_needed){
+ if (*got_output) {
+ /* TODO reindent */
if (!frame_sample_aspect->num)
*frame_sample_aspect = ist->st->sample_aspect_ratio;
decoded_frame->pts = ist->pts;
@@ -2144,6 +2151,9 @@ static int transcode_video(InputStream *ist, AVPacket *pkt, int *got_output, int
av_log(NULL, AV_LOG_FATAL, "Failed to inject frame into filter network\n");
exit_program(1);
}
+ } else {
+ av_vsrc_buffer_set_return_value(ost->input_video_filter, AVERROR_EOF);
+ }
}
}
#endif
@@ -2157,13 +2167,21 @@ static int transcode_video(InputStream *ist, AVPacket *pkt, int *got_output, int
continue;
#if CONFIG_AVFILTER
- while (av_buffersink_poll_frame(ost->output_video_filter)) {
+ while (1) {
AVRational ist_pts_tb = ost->output_video_filter->inputs[0]->time_base;
AVFrame *filtered_frame;
- if (av_buffersink_get_buffer_ref(ost->output_video_filter, &ost->picref, 0) < 0){
- av_log(NULL, AV_LOG_WARNING, "AV Filter told us it has a frame available but failed to output one\n");
- goto cont;
+ ret = av_buffersink_get_buffer_ref(ost->output_video_filter, &ost->picref, 0);
+ if (ret < 0){
+ if (ret != AVERROR(EAGAIN) && ret != AVERROR_EOF) {
+ char errbuf[128];
+ av_strerror(ret, errbuf, sizeof(errbuf));
+ av_log(NULL, AV_LOG_WARNING,
+ "Error filtering video frame: %s\n", errbuf);
+ } else {
+ ret = 0;
+ }
+ break;
}
if (!ist->filtered_frame && !(ist->filtered_frame = avcodec_alloc_frame())) {
ret = AVERROR(ENOMEM);
@@ -2176,7 +2194,6 @@ static int transcode_video(InputStream *ist, AVPacket *pkt, int *got_output, int
if (ost->picref->video && !ost->frame_aspect_ratio)
ost->st->codec->sample_aspect_ratio = ost->picref->video->sample_aspect_ratio;
do_video_out(output_files[ost->file_index].ctx, ost, ist, filtered_frame);
- cont:
avfilter_unref_buffer(ost->picref);
}
#else
@@ -2219,7 +2236,7 @@ static int output_packet(InputStream *ist,
OutputStream *ost_table, int nb_ostreams,
const AVPacket *pkt)
{
- int ret = 0, i;
+ int ret = 0, i, flush;
int got_output;
int64_t pkt_pts = AV_NOPTS_VALUE;
@@ -2230,7 +2247,8 @@ static int output_packet(InputStream *ist,
if (ist->next_pts == AV_NOPTS_VALUE)
ist->next_pts = ist->pts;
- if (pkt == NULL) {
+ flush = pkt == NULL;
+ if (flush) {
/* EOF handling */
av_init_packet(&avpkt);
avpkt.data = NULL;
@@ -2267,7 +2285,7 @@ static int output_packet(InputStream *ist,
ret = transcode_audio (ist, &avpkt, &got_output);
break;
case AVMEDIA_TYPE_VIDEO:
- ret = transcode_video (ist, &avpkt, &got_output, &pkt_pts);
+ ret = transcode_video (ist, &avpkt, &got_output, &pkt_pts, flush);
if (avpkt.duration) {
duration = av_rescale_q(avpkt.duration, ist->st->time_base, AV_TIME_BASE_Q);
} else if(ist->st->codec->time_base.num != 0 && ist->st->codec->time_base.den != 0) {
--
1.7.9.1
More information about the ffmpeg-devel
mailing list