[FFmpeg-devel] [PATCH] lavfi: add interleave filters
Clément Bœsch
ubitux at gmail.com
Sat Apr 20 13:27:31 CEST 2013
On Thu, Apr 18, 2013 at 11:00:51PM +0200, Stefano Sabatini wrote:
[...]
> From cc0ea64d70218a80b4ae29c98e2b86c988e7994b Mon Sep 17 00:00:00 2001
> From: Stefano Sabatini <stefasab at gmail.com>
> Date: Mon, 8 Apr 2013 15:16:06 +0200
> Subject: [PATCH] lavfi: add interleave filters
>
> TODO: bump minor, add changelog entry
> ---
> doc/filters.texi | 48 ++++++++
> libavfilter/Makefile | 2 +
> libavfilter/allfilters.c | 2 +
> libavfilter/f_interleave.c | 259 ++++++++++++++++++++++++++++++++++++++++++++
> 4 files changed, 311 insertions(+)
> create mode 100644 libavfilter/f_interleave.c
>
> diff --git a/doc/filters.texi b/doc/filters.texi
> index 43d7368..b739fa0 100644
> --- a/doc/filters.texi
> +++ b/doc/filters.texi
> @@ -7246,6 +7246,54 @@ setpts='(RTCTIME - RTCSTART) / (TB * 1000000)'
> @end example
> @end itemize
>
> + at section ainterleave, interleave
> +
> +Temporally interleave frames from several inputs.
> +
> + at code{ainterleave} works with audio inputs, @code{interleave} with video.
> +
> +These filters read frames from several inputs and send the oldest
> +queued frame to the output.
> +
> +Input streams must have a well defined, monotonically increasing frame
> +timestamp value.
> +
> +In order to submit one frame to output, these filters need to enqueue
> +at least one frame for each input, so they cannot work in case one
> +input is not yet terminated and will not receive incoming frames.
> +
> +For example consider the case when one input is a @code{select} filter
> +which always drop input frames. The @code{interleave} filter will keep
> +reading from that input, but it will never be able to send new frames
> +to output until the input will send an end-of-stream signal.
> +
> +Also, depending on inputs synchronization, the filters may drop frames
> +in case one input receives more frames than the other ones, and the
> +queue is already filled.
> +
> +These filters accept the following options:
> +
> + at table @option
> + at item nb_inputs, n
> +Set the number of different inputs, it is 2 by default.
> + at end table
> +
> + at subsection Examples
> +
> + at itemize
> + at item
> +Interleave frames belonging to different streams using @command{ffmpeg}:
> + at example
> +ffmpeg -i bambi.avi -i pr0n.mkv -filter_complex "[0:v][1:v] interleave" out.avi
> + at end example
> +
> + at item
> +Add flickering blur effect:
> + at example
> +select='gt(random(0), 0.2):branch=1 [tmp], boxblur=2:2, [tmp] interleave"
Trailing or missing initial double quote, and missing simple quote in
select expression.
Also, the branch option was implemented differently so this example needs
adjustments. I tried replacing branch=1 with n=2 but got a bunch of buffer
queue overflows and no output.
[...]
> diff --git a/libavfilter/f_interleave.c b/libavfilter/f_interleave.c
> new file mode 100644
> index 0000000..c0af198
> --- /dev/null
> +++ b/libavfilter/f_interleave.c
> @@ -0,0 +1,259 @@
> +/*
> + * Copyright (c) 2013 Stefano Sabatini
> + *
> + * 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.
> + *
> + * 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 FFmpeg; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
> + */
> +
> +/**
> + * @file
> + * audio and video interleaver
> + */
> +
> +#include "libavutil/avassert.h"
> +#include "libavutil/avstring.h"
> +#include "libavutil/opt.h"
> +#include "avfilter.h"
> +#include "bufferqueue.h"
> +#include "formats.h"
> +#include "internal.h"
> +#include "audio.h"
> +#include "video.h"
> +
> +typedef struct {
> + const AVClass *class;
> + int nb_inputs;
> + struct FFBufQueue *queues;
> +} InterleaveContext;
> +
> +#define OFFSET(x) offsetof(InterleaveContext, x)
> +
> +#define DEFINE_OPTIONS(filt_name, filt_type) \
> +static const AVOption filt_name##_options[] = { \
> + { "nb_inputs", "set number of inputs", OFFSET(nb_inputs), AV_OPT_TYPE_INT, {.i64 = 2}, 1, INT_MAX, \
> + .flags = AV_OPT_FLAG_##filt_type##_PARAM|AV_OPT_FLAG_FILTERING_PARAM }, \
> + { "n", "set number of inputs", OFFSET(nb_inputs), AV_OPT_TYPE_INT, {.i64 = 2}, 1, INT_MAX, \
> + .flags = AV_OPT_FLAG_##filt_type##_PARAM|AV_OPT_FLAG_FILTERING_PARAM }, \
> + { NULL }, \
> +}
> +
nit: I prefer how it's done in select (where the
AV_OPT_FLAG_##filt_type##_PARAM|AV_OPT_FLAG_FILTERING_PARAM for each entry
is avoided)
[...]
> +static int config_output(AVFilterLink *outlink)
> +{
> + AVFilterContext *ctx = outlink->src;
> + AVFilterLink *inlink0 = ctx->inputs[0];
> + int i;
> +
> + if (outlink->type == AVMEDIA_TYPE_VIDEO) {
> + outlink->time_base = AV_TIME_BASE_Q;
> + outlink->w = inlink0->w;
> + outlink->h = inlink0->h;
> + outlink->sample_aspect_ratio = inlink0->sample_aspect_ratio;
> + outlink->format = inlink0->format;
> + outlink->frame_rate = (AVRational) {1, 0};
> + for (i = 1; i < ctx->nb_inputs; i++) {
> + AVFilterLink *inlink = ctx->inputs[i];
> +
> + if (outlink->w != inlink->w ||
> + outlink->h != inlink->h ||
> + outlink->sample_aspect_ratio.num != inlink->sample_aspect_ratio.num ||
> + outlink->sample_aspect_ratio.den != inlink->sample_aspect_ratio.den) {
> + av_log(ctx, AV_LOG_ERROR, "Parameters for input link %s "
> + "(size %dx%d, SAR %d:%d) do not match the corresponding "
> + "output link parameters (%dx%d, SAR %d:%d)\n",
> + ctx->input_pads[i].name, inlink->w, inlink->h,
> + inlink->sample_aspect_ratio.num,
> + inlink->sample_aspect_ratio.den,
> + outlink->w, outlink->h,
> + outlink->sample_aspect_ratio.num,
> + outlink->sample_aspect_ratio.den);
> + return AVERROR(EINVAL);
> + }
> + }
> + }
No consistency checks for audio required?
> +
> + outlink->flags |= FF_LINK_FLAG_REQUEST_LOOP;
> + return 0;
> +}
> +
Rest of the code looks OK.
--
Clément B.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 490 bytes
Desc: not available
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20130420/01e36914/attachment.asc>
More information about the ffmpeg-devel
mailing list