[FFmpeg-devel] [PATCH 4/4] lavfi/vf_fps: accept EOF timestamp.
Nicolas George
george at nsup.org
Thu Jul 24 15:39:45 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 | 59 +++++++++++++++++++++++++++++++++++-----------------
1 file changed, 40 insertions(+), 19 deletions(-)
Note: this will not work if there are filters before vf_fps, unless they
are converted to accept messages and forward the end timestamp.
When more filters are adapted, a warning could be added.
diff --git a/libavfilter/vf_fps.c b/libavfilter/vf_fps.c
index a38633d..7028f28 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,11 +89,13 @@ 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)) {
AVFrame *tmp;
av_fifo_generic_read(fifo, &tmp, sizeof(tmp), NULL);
+ av_log(0, 16, "discard frame %d %ld\n", tmp->format, tmp->pts);
av_frame_free(&tmp);
}
}
@@ -131,25 +134,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 +145,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 +156,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 +202,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 +213,18 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *buf)
return 0;
}
+ if (buf->format < 0) {
+ if (buf->format != FF_FRAME_MSG_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 +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;
}
@@ -295,6 +315,7 @@ AVFilter ff_vf_fps = {
.uninit = uninit,
.priv_size = sizeof(FPSContext),
.priv_class = &fps_class,
+ .flags = FF_FILTER_FLAG_SUPPORT_MESSAGES,
.inputs = avfilter_vf_fps_inputs,
.outputs = avfilter_vf_fps_outputs,
};
--
2.0.1
More information about the ffmpeg-devel
mailing list