On Tue, 21 Aug 2012 21:58:42 -0700, Alex Converse <alex.conve...@gmail.com> wrote: > --- > Changelog | 1 + > doc/filters.texi | 33 ++++++++++ > libavfilter/Makefile | 1 + > libavfilter/af_alength.c | 161 > ++++++++++++++++++++++++++++++++++++++++++++++ > libavfilter/allfilters.c | 1 + > 5 files changed, 197 insertions(+), 0 deletions(-) > create mode 100644 libavfilter/af_alength.c > > diff --git a/Changelog b/Changelog > index 4326c68..c94b28a 100644 > --- a/Changelog > +++ b/Changelog > @@ -44,6 +44,7 @@ version <next>: > - Canopus Lossless Codec decoder > - avconv -shortest option is now per-output file > - Ut Video encoder > +- alength audio filter > > > version 0.8: > diff --git a/doc/filters.texi b/doc/filters.texi > index e77256e..0932516 100644 > --- a/doc/filters.texi > +++ b/doc/filters.texi > @@ -133,6 +133,39 @@ For example to force the output to either unsigned 8-bit > or signed 16-bit stereo > aformat=sample_fmts\=u8\,s16:channel_layouts\=stereo > @end example > > +@section alength > + > +Shorten or optionally pad input audio to a target length. > + > +The filter accepts the following named parameters: > +@table @option > + > +@item length > +The target length in samples > + > +@item pad > +A boolean that controls whether or not to pad output with silence to reach > +the target length. > + > +@item frame_size > +The size of silent frames to be generated. > + > +@end table > + > +For example to limit output audio to at most 480000 samples > +@example > +alength=length=480000 > +@end example > + > +To force output audio to be 480000 samples > +@example > +alength=length=480000\,pad=1 > +@end example > + > +To pad or trim audio to match video length > +@example > +avconv -i INPUT -af alength=pad=1 -shortest OUTPUT > +@end example > @section amix > > Mixes multiple audio inputs into a single output. > diff --git a/libavfilter/Makefile b/libavfilter/Makefile > index 530aa57..74d57c9 100644 > --- a/libavfilter/Makefile > +++ b/libavfilter/Makefile > @@ -26,6 +26,7 @@ OBJS = allfilters.o > \ > > OBJS-$(CONFIG_AFIFO_FILTER) += fifo.o > OBJS-$(CONFIG_AFORMAT_FILTER) += af_aformat.o > +OBJS-$(CONFIG_ALENGTH_FILTER) += af_alength.o > OBJS-$(CONFIG_AMIX_FILTER) += af_amix.o > OBJS-$(CONFIG_ANULL_FILTER) += af_anull.o > OBJS-$(CONFIG_ASPLIT_FILTER) += split.o > diff --git a/libavfilter/af_alength.c b/libavfilter/af_alength.c > new file mode 100644 > index 0000000..a06bb07 > --- /dev/null > +++ b/libavfilter/af_alength.c > @@ -0,0 +1,161 @@ > +/* > + * Copyright (c) 2012 Google, Inc. > + * > + * This file is part of Libav. > + * > + * Libav 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, > + * 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 > + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 > USA > + */ > + > +/** > + * @file > + * Filter that shortens or lengths and audio stream > + */ > + > +#include "libavutil/audioconvert.h" > +#include "libavutil/common.h" > +#include "libavutil/opt.h" > +#include "avfilter.h" > +#include "audio.h" > +#include "internal.h" > +#include "formats.h" > + > +typedef struct { > + const AVClass *class; > + int64_t next_pts; > + int64_t length; > + int got_output; > + int pad; > + int frame_size; > +} ALengthContext; > + > +#define OFFSET(x) offsetof(ALengthContext, x) > +#define A AV_OPT_FLAG_AUDIO_PARAM > + > +static const AVOption alength_options[] = { > +{ "length", "Target length in samples", OFFSET(length), AV_OPT_TYPE_INT64, { > INT64_MAX }, 0, INT64_MAX, A }, ^^^^^^^^^ As we discussed on IRC, this doesn't work currently, and after it's fixed it should be .i64 = INT64_MAX
> +{ "pad", "Pad to length if too short", OFFSET(pad), AV_OPT_TYPE_INT, { 0 }, > 0, 1, A }, > +{ "frame_size", "frame_size", OFFSET(frame_size), AV_OPT_TYPE_INT, { 1024 }, > 0, INT_MAX, A }, > +{ NULL } > +}; > + > +static const AVClass alength_class = { > + .class_name = "alength filter", > + .item_name = av_default_item_name, > + .option = alength_options, > + .version = LIBAVUTIL_VERSION_INT, > +}; > + > +static av_cold int alength_init(AVFilterContext *ctx, const char *args) > +{ > + ALengthContext *s = ctx->priv; > + int err; > + > + s->class = &alength_class; > + av_opt_set_defaults(s); > + > + if ((err = av_set_options_string(s, args, "=", ":")) < 0) > + return err; > + > + s->next_pts = AV_NOPTS_VALUE; > + av_log(ctx, AV_LOG_VERBOSE, "length:%"PRId64" pad:%d frame_size:%d\n", > s->length, s->pad, s->frame_size); > + > + return 0; > +} > + > +static int alength_filter_samples(AVFilterLink *inlink, AVFilterBufferRef > *buf) > +{ > + AVFilterContext *ctx = inlink->dst; > + ALengthContext *s = ctx->priv; > + AVFilterLink *outlink = ctx->outputs[0]; > + int nb_samples = buf->audio->nb_samples; > + > + if (buf->pts != AV_NOPTS_VALUE) { > + s->next_pts = buf->pts; > + } > + > + if (s->next_pts == AV_NOPTS_VALUE) { > + s->got_output = 1; > + return ff_filter_samples(outlink, buf); > + } else if (s->next_pts >= s->length) { > + avfilter_unref_buffer(buf); > + return AVERROR_EOF; > + } else if (s->next_pts + nb_samples <= s->length) { > + s->next_pts += nb_samples; > + s->got_output = 1; > + return ff_filter_samples(outlink, buf); > + } else { > + nb_samples = s->length - s->next_pts; > + buf->audio->nb_samples = nb_samples; > + s->next_pts += nb_samples; > + s->got_output = 1; > + return ff_filter_samples(outlink, buf); > + } This assumes the timestamps start at 0, which might not always be true. It also won't work correctly when a timestamps at the beginning are missing. I think it'd be better to track the first timestamp and assume it to be 0 when it's not present. -- Anton Khirnov _______________________________________________ libav-devel mailing list libav-devel@libav.org https://lists.libav.org/mailman/listinfo/libav-devel