This makes the FPS filter duplicate the last frame to take its duration into account, exactly like the other ones.
Fix trac ticket #2674. Signed-off-by: Nicolas George <geo...@nsup.org> --- libavfilter/vf_fps.c | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) Aded a ref to the trac ticket and fixed a corner case raised by it. Note that the whole logic of vf_fps is overly complex, but this is for another patch. diff --git a/libavfilter/vf_fps.c b/libavfilter/vf_fps.c index a3ad1bb..5bf5bda 100644 --- a/libavfilter/vf_fps.c +++ b/libavfilter/vf_fps.c @@ -28,6 +28,7 @@ #include <float.h> #include <stdint.h> +#include "libavutil/avassert.h" #include "libavutil/common.h" #include "libavutil/fifo.h" #include "libavutil/mathematics.h" @@ -150,10 +151,8 @@ static int request_frame(AVFilterLink *outlink) while (ret >= 0 && s->frames_out == frames_out) ret = ff_request_frame(ctx->inputs[0]); - - /* flush the fifo */ - if (ret == AVERROR_EOF && av_fifo_size(s->fifo)) - return flush_fifo_to_out(ctx); + if (ret == AVERROR_EOF) + av_assert1(!av_fifo_size(s->fifo)); return ret; } @@ -161,6 +160,7 @@ static int write_to_fifo(AVFifoBuffer *fifo, AVFrame *buf) { int ret; + av_assert1(buf->format >= 0); if (!av_fifo_space(fifo) && (ret = av_fifo_realloc2(fifo, 2*av_fifo_size(fifo)))) { av_frame_free(&buf); @@ -198,6 +198,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *buf) } else { s->first_pts = buf->pts; } + } else if (buf->format < 0) { + return 0; } else { av_log(ctx, AV_LOG_WARNING, "Discarding initial frame(s) with no " "timestamp.\n"); @@ -207,8 +209,18 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *buf) return 0; } + if (buf->format < 0) { + if (buf->format != FF_METAFRAME_EOF) + return 0; + if (buf->pts == AV_NOPTS_VALUE) + return flush_fifo_to_out(ctx); + if (!av_fifo_size(s->fifo)) + return 0; + } + /* now wait for the next timestamp */ if (buf->pts == AV_NOPTS_VALUE || av_fifo_size(s->fifo) <= 0) { + av_assert1(buf->format >= 0); return write_to_fifo(s->fifo, buf); } @@ -226,10 +238,14 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *buf) av_fifo_generic_read(s->fifo, &tmp, sizeof(tmp), NULL); flush_fifo(s->fifo); - ret = write_to_fifo(s->fifo, tmp); - av_frame_free(&buf); - return ret; + if (buf->format >= 0) { + /* requeue last frame if not EOF */ + ret = write_to_fifo(s->fifo, tmp); + av_frame_free(&buf); + return ret; + } + return 0; } /* can output >= 1 frames */ @@ -268,7 +284,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *buf) } flush_fifo(s->fifo); - ret = write_to_fifo(s->fifo, buf); + ret = buf->format < 0 ? 0 : write_to_fifo(s->fifo, buf); return ret; } @@ -299,6 +315,7 @@ AVFilter ff_vf_fps = { .uninit = uninit, .priv_size = sizeof(FPSContext), .priv_class = &fps_class, + .flags = FF_FILTER_FLAG_SUPPORT_METAFRAMES, .inputs = avfilter_vf_fps_inputs, .outputs = avfilter_vf_fps_outputs, }; -- 2.0.1 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel