* a filter enforcing given constant framerate
*/
+#include "libavutil/common.h"
#include "libavutil/fifo.h"
#include "libavutil/mathematics.h"
#include "libavutil/opt.h"
{
FPSContext *s = ctx->priv;
if (s->fifo) {
+ s->drop += av_fifo_size(s->fifo) / sizeof(AVFilterBufferRef*);
flush_fifo(s->fifo);
av_fifo_free(s->fifo);
}
buf->pts = av_rescale_q(s->first_pts, ctx->inputs[0]->time_base,
outlink->time_base) + s->frames_out;
- if ((ret = ff_start_frame(outlink, buf)) < 0 ||
- (ret = ff_draw_slice(outlink, 0, outlink->h, 1)) < 0 ||
- (ret = ff_end_frame(outlink)) < 0)
+ if ((ret = ff_filter_frame(outlink, buf)) < 0)
return ret;
s->frames_out++;
return 0;
}
-static int end_frame(AVFilterLink *inlink)
+static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *buf)
{
AVFilterContext *ctx = inlink->dst;
FPSContext *s = ctx->priv;
AVFilterLink *outlink = ctx->outputs[0];
- AVFilterBufferRef *buf = inlink->cur_buf;
int64_t delta;
int i, ret;
- inlink->cur_buf = NULL;
s->frames_in++;
/* discard frames until we get the first timestamp */
if (s->pts == AV_NOPTS_VALUE) {
if (buf->pts != AV_NOPTS_VALUE) {
- write_to_fifo(s->fifo, buf);
+ ret = write_to_fifo(s->fifo, buf);
+ if (ret < 0)
+ return ret;
+
s->first_pts = s->pts = buf->pts;
} else {
av_log(ctx, AV_LOG_WARNING, "Discarding initial frame(s) with no "
/* duplicate the frame if needed */
if (!av_fifo_size(s->fifo) && i < delta - 1) {
+ AVFilterBufferRef *dup = avfilter_ref_buffer(buf_out, AV_PERM_READ);
+
av_log(ctx, AV_LOG_DEBUG, "Duplicating frame.\n");
- write_to_fifo(s->fifo, avfilter_ref_buffer(buf_out, AV_PERM_READ));
+ if (dup)
+ ret = write_to_fifo(s->fifo, dup);
+ else
+ ret = AVERROR(ENOMEM);
+
+ if (ret < 0) {
+ avfilter_unref_bufferp(&buf_out);
+ avfilter_unref_bufferp(&buf);
+ return ret;
+ }
+
s->dup++;
}
buf_out->pts = av_rescale_q(s->first_pts, inlink->time_base,
outlink->time_base) + s->frames_out;
- if ((ret = ff_start_frame(outlink, buf_out)) < 0 ||
- (ret = ff_draw_slice(outlink, 0, outlink->h, 1)) < 0 ||
- (ret = ff_end_frame(outlink)) < 0) {
+ if ((ret = ff_filter_frame(outlink, buf_out)) < 0) {
avfilter_unref_bufferp(&buf);
return ret;
}
return ret;
}
-static int null_start_frame(AVFilterLink *link, AVFilterBufferRef *buf)
-{
- return 0;
-}
+static const AVFilterPad avfilter_vf_fps_inputs[] = {
+ {
+ .name = "default",
+ .type = AVMEDIA_TYPE_VIDEO,
+ .filter_frame = filter_frame,
+ },
+ { NULL }
+};
-static int null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir)
-{
- return 0;
-}
+static const AVFilterPad avfilter_vf_fps_outputs[] = {
+ {
+ .name = "default",
+ .type = AVMEDIA_TYPE_VIDEO,
+ .request_frame = request_frame,
+ .config_props = config_props
+ },
+ { NULL }
+};
AVFilter avfilter_vf_fps = {
.name = "fps",
.priv_size = sizeof(FPSContext),
- .inputs = (const AVFilterPad[]) {{ .name = "default",
- .type = AVMEDIA_TYPE_VIDEO,
- .start_frame = null_start_frame,
- .draw_slice = null_draw_slice,
- .end_frame = end_frame, },
- { .name = NULL}},
- .outputs = (const AVFilterPad[]) {{ .name = "default",
- .type = AVMEDIA_TYPE_VIDEO,
- .request_frame = request_frame,
- .config_props = config_props},
- { .name = NULL}},
+ .inputs = avfilter_vf_fps_inputs,
+ .outputs = avfilter_vf_fps_outputs,
};