This makes the FPS filter duplicate the last frame to take its duration into account, exactly like the other ones.
TODO find corresponding trac ticket(s). Signed-off-by: Nicolas George <geo...@nsup.org> --- libavfilter/vf_fps.c | 58 +++++++++++++++++++++++++++++++++++----------------- 1 file changed, 39 insertions(+), 19 deletions(-) diff --git a/libavfilter/vf_fps.c b/libavfilter/vf_fps.c index a38633d..e969335 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" @@ -88,6 +89,7 @@ static av_cold int init(AVFilterContext *ctx) return 0; } +/* FIXME: misnommer, the frames are discarded, not flushed */ static void flush_fifo(AVFifoBuffer *fifo) { while (av_fifo_size(fifo)) { @@ -131,25 +133,10 @@ 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)) { - int i; - for (i = 0; av_fifo_size(s->fifo); i++) { - AVFrame *buf; - - av_fifo_generic_read(s->fifo, &buf, sizeof(buf), NULL); - buf->pts = av_rescale_q(s->first_pts, ctx->inputs[0]->time_base, - outlink->time_base) + s->frames_out; - - if ((ret = ff_filter_frame(outlink, buf)) < 0) - return ret; - - s->frames_out++; - } - return 0; + if (ret == AVERROR_EOF) { + flush_fifo(s->fifo); + av_assert1(!av_fifo_size(s->fifo)); } - return ret; } @@ -157,6 +144,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); @@ -167,6 +155,25 @@ static int write_to_fifo(AVFifoBuffer *fifo, AVFrame *buf) return 0; } +static int flush_fifo_to_out(AVFilterContext *ctx) +{ + FPSContext *s = ctx->priv; + AVFilterLink *outlink = ctx->outputs[0]; + AVFrame *frame; + int ret; + + while (av_fifo_size(s->fifo)) { + + av_fifo_generic_read(s->fifo, &frame, sizeof(frame), NULL); + frame->pts = av_rescale_q(s->first_pts, ctx->inputs[0]->time_base, + outlink->time_base) + s->frames_out; + if ((ret = ff_filter_frame(outlink, frame)) < 0) + return ret; + s->frames_out++; + } + return 0; +} + static int filter_frame(AVFilterLink *inlink, AVFrame *buf) { AVFilterContext *ctx = inlink->dst; @@ -194,6 +201,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"); @@ -203,8 +212,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); } @@ -264,7 +283,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; } @@ -295,6 +314,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