/*
- * This file is part of Libav.
+ * Copyright 2007 Bobby Bingham
+ * Copyright 2012 Robert Nagy <ronag89 gmail com>
+ * Copyright 2012 Anton Khirnov <anton khirnov net>
*
- * Libav is free software; you can redistribute it and/or
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
- * Libav is distributed in the hope that it will be useful,
+ * FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with Libav; if not, write to the Free Software
+ * License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
* a filter enforcing given constant framerate
*/
+#include "libavutil/common.h"
#include "libavutil/fifo.h"
#include "libavutil/mathematics.h"
#include "libavutil/opt.h"
#define OFFSET(x) offsetof(FPSContext, x)
#define V AV_OPT_FLAG_VIDEO_PARAM
-static const AVOption options[] = {
- { "fps", "A string describing desired output framerate", OFFSET(fps), AV_OPT_TYPE_STRING, { .str = "25" }, .flags = V },
+#define F AV_OPT_FLAG_FILTERING_PARAM
+static const AVOption fps_options[] = {
+ { "fps", "A string describing desired output framerate", OFFSET(fps), AV_OPT_TYPE_STRING, { .str = "25" }, .flags = V|F },
{ NULL },
};
-static const AVClass class = {
- .class_name = "FPS filter",
- .item_name = av_default_item_name,
- .option = options,
- .version = LIBAVUTIL_VERSION_INT,
-};
+AVFILTER_DEFINE_CLASS(fps);
static av_cold int init(AVFilterContext *ctx, const char *args)
{
FPSContext *s = ctx->priv;
int ret;
- s->class = &class;
+ s->class = &fps_class;
av_opt_set_defaults(s);
if ((ret = av_set_options_string(s, args, "=", ":")) < 0) {
{
FPSContext *s = link->src->priv;
- link->time_base = (AVRational){ s->framerate.den, s->framerate.num };
+ link->time_base = av_inv_q(s->framerate);
+ link->frame_rate= s->framerate;
link->w = link->src->inputs[0]->w;
link->h = link->src->inputs[0]->h;
s->pts = AV_NOPTS_VALUE;
int ret;
if (!av_fifo_space(fifo) &&
- (ret = av_fifo_realloc2(fifo, 2*av_fifo_size(fifo))))
+ (ret = av_fifo_realloc2(fifo, 2*av_fifo_size(fifo)))) {
+ avfilter_unref_bufferp(&buf);
return ret;
+ }
av_fifo_generic_write(fifo, &buf, sizeof(buf), NULL);
return 0;
/* 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, ~0);
+
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++;
}
.inputs = (const AVFilterPad[]) {{ .name = "default",
.type = AVMEDIA_TYPE_VIDEO,
+ .min_perms = AV_PERM_READ | AV_PERM_PRESERVE,
.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,
+ .rej_perms = AV_PERM_WRITE,
.request_frame = request_frame,
.config_props = config_props},
{ .name = NULL}},
+ .priv_class = &fps_class,
};