[FFmpeg-devel] [PATCH 4/4] lavfi/vf_fps: accept EOF timestamp.
Nicolas George
george at nsup.org
Wed Jul 30 23:44:49 CEST 2014
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 <george at 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
More information about the ffmpeg-devel
mailing list