[FFmpeg-devel] [PATCH 1/4] lavfi: add asrc_abuffer - audio source buffer filter
Mina Nagy Zaki
mnzaki at gmail.com
Wed Jul 27 00:05:17 CEST 2011
From: S.N. Hemanth Meenakshisundaram <smeenaks at ucsd.edu>
With many modifications by Stefano.
---
doc/filters.texi | 50 ++++++++++
libavfilter/Makefile | 2 +
libavfilter/allfilters.c | 1 +
libavfilter/asrc_abuffer.c | 225 ++++++++++++++++++++++++++++++++++++++++++++
libavfilter/asrc_abuffer.h | 79 +++++++++++++++
5 files changed, 357 insertions(+), 0 deletions(-)
create mode 100644 libavfilter/asrc_abuffer.c
create mode 100644 libavfilter/asrc_abuffer.h
diff --git a/doc/filters.texi b/doc/filters.texi
index 8054bff..92bde6e 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -1846,6 +1846,56 @@ Default value is 0.
@c man end VIDEO FILTERS
+ at chapter Audio Sources
+ at c man begin AUDIO SOURCES
+
+Below is a description of the currently available audio sources.
+
+ at section abuffer
+
+Buffer audio frames, and make them available to the filter chain.
+
+This source is mainly intended for a programmatic use, in particular
+through the interface defined in @file{libavfilter/asrc_abuffer.h}.
+
+It accepts the following mandatory parameters:
+ at var{sample_fmt_string}:@var{channel_layout_string}
+
+Follows the list of the accepted parameters.
+
+ at table @option
+
+ at item sample_fmt_string
+
+A string representing the sample format of the buffered audio frames.
+It may be a number corresponding to a sample format, or a sample format
+name.
+
+ at item channel_layout_string
+
+A string representing the channel layout of the buffered audio frames.
+It may be a number corresponding to a channel layout, or a channel
+layout name.
+
+ at end table
+
+For example:
+ at example
+abuffer=s16:stereo
+ at end example
+
+will instruct the source to accept audio frames with format "s16" and
+stereo channel layout.
+Since the sample format with name "s16" corresponds to the number
+1 and the "stereo" channel layout corresponds to the value 3
+(check the enum SampleFormatInfo definition and the channel_layout_map
+structure, this example is equivalent to:
+ at example
+abuffer=1:3
+ at end example
+
+ at c man end AUDIO SOURCES
+
@chapter Video Sources
@c man begin VIDEO SOURCES
diff --git a/libavfilter/Makefile b/libavfilter/Makefile
index 865ba1e..686fd30 100644
--- a/libavfilter/Makefile
+++ b/libavfilter/Makefile
@@ -65,6 +65,8 @@ OBJS-$(CONFIG_UNSHARP_FILTER) += vf_unsharp.o
OBJS-$(CONFIG_VFLIP_FILTER) += vf_vflip.o
OBJS-$(CONFIG_YADIF_FILTER) += vf_yadif.o
+OBJS-$(CONFIG_ABUFFER_FILTER) += asrc_abuffer.o
+
OBJS-$(CONFIG_BUFFER_FILTER) += vsrc_buffer.o
OBJS-$(CONFIG_COLOR_FILTER) += vsrc_color.o
OBJS-$(CONFIG_FREI0R_SRC_FILTER) += vf_frei0r.o
diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c
index 56baa50..49be7b7 100644
--- a/libavfilter/allfilters.c
+++ b/libavfilter/allfilters.c
@@ -37,6 +37,7 @@ void avfilter_register_all(void)
REGISTER_FILTER (AFORMAT, aformat, af);
REGISTER_FILTER (ANULL, anull, af);
+ REGISTER_FILTER (ABUFFER, abuffer, asrc);
REGISTER_FILTER (ANULLSRC, anullsrc, asrc);
REGISTER_FILTER (ANULLSINK, anullsink, asink);
diff --git a/libavfilter/asrc_abuffer.c b/libavfilter/asrc_abuffer.c
new file mode 100644
index 0000000..6341e36
--- /dev/null
+++ b/libavfilter/asrc_abuffer.c
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2010 S.N. Hemanth Meenakshisundaram
+ *
+ * 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
+ * Memory buffer source filter for audio
+ */
+
+#include "libavutil/eval.h"
+#include "libavutil/audioconvert.h"
+#include "asrc_abuffer.h"
+
+#define FIFO_SIZE 8
+
+static void buf_free(AVFilterBuffer *ptr)
+{
+ av_free(ptr);
+ return;
+}
+
+int av_asrc_buffer_add_samples(AVFilterContext *ctx,
+ uint8_t *data[8], int linesize[8], int nb_samples,
+ int sample_fmt, int64_t channel_layout, int planar,
+ int64_t pts)
+{
+ ABufferSourceContext *abuffer = ctx->priv;
+ AVFilterBufferRef *samplesref;
+
+ if (av_fifo_space(abuffer->fifo) < sizeof(samplesref)) {
+ av_log(ctx, AV_LOG_ERROR,
+ "Buffering limit reached. Please consume some available frames "
+ "before adding new ones.\n");
+ return AVERROR(ENOMEM);
+ }
+
+ samplesref = avfilter_get_audio_buffer_ref_from_arrays(data, linesize, AV_PERM_WRITE,
+ nb_samples, sample_fmt,
+ channel_layout, planar);
+ if (!samplesref)
+ return AVERROR(ENOMEM);
+ samplesref->buf->free = buf_free;
+ samplesref->pts = pts;
+
+ av_fifo_generic_write(abuffer->fifo, &samplesref, sizeof(samplesref), NULL);
+
+ return 0;
+}
+
+int av_asrc_buffer_add_buffer(AVFilterContext *ctx,
+ uint8_t *buf, int buf_size,
+ int sample_fmt, int64_t channel_layout,
+ int64_t pts)
+{
+ /* compute pointers from buffer */
+ uint8_t *data[8];
+ int linesize[8];
+ int nb_channels = av_get_channel_layout_nb_channels(channel_layout),
+ sample_size = av_get_bytes_per_sample(sample_fmt),
+ nb_samples = buf_size / sample_size / nb_channels;
+
+ memset(data, 0, 8 * sizeof(data[0]));
+ memset(linesize, 0, 8 * sizeof(linesize[0]));
+
+ data[0] = buf;
+ linesize[0] = nb_samples * sample_size * nb_channels;
+
+ return av_asrc_buffer_add_samples(ctx,
+ data, linesize, nb_samples,
+ sample_fmt, channel_layout, 0, pts);
+}
+
+static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
+{
+ ABufferSourceContext *abuffer = ctx->priv;
+ char sample_fmt_str[8], chlayout_str[16], sample_rate_str[16];
+ int n = 0;
+ char *tail;
+ double sample_rate;
+
+ n = sscanf(args, "%7[^:]:%15[^:]:%15s",
+ sample_fmt_str, chlayout_str, sample_rate_str);
+ if (!args || n != 3) {
+ av_log(ctx, AV_LOG_ERROR,
+ "Expected 3 arguments, but only %d found in '%s'\n", n, args);
+ return AVERROR(EINVAL);
+ }
+
+ abuffer->sample_fmt = av_get_sample_fmt(sample_fmt_str);
+ if (abuffer->sample_fmt == AV_SAMPLE_FMT_NONE) {
+ char *tail;
+ abuffer->sample_fmt = strtol(sample_fmt_str, &tail, 0);
+ if (*tail || (unsigned)abuffer->sample_fmt >= AV_SAMPLE_FMT_NB) {
+ av_log(ctx, AV_LOG_ERROR, "Invalid sample format '%s'\n",
+ sample_fmt_str);
+ return AVERROR(EINVAL);
+ }
+ }
+
+ abuffer->channel_layout = av_get_channel_layout(chlayout_str);
+ if (abuffer->channel_layout < AV_CH_LAYOUT_STEREO) {
+ char *tail;
+ abuffer->channel_layout = strtol(chlayout_str, &tail, 0);
+ if (*tail || abuffer->channel_layout < AV_CH_LAYOUT_STEREO) {
+ av_log(ctx, AV_LOG_ERROR, "Invalid channel layout '%s'\n",
+ chlayout_str);
+ return AVERROR(EINVAL);
+ }
+ }
+
+ sample_rate = av_strtod(sample_rate_str, &tail);
+ if (*tail || sample_rate < 0 || (int)sample_rate != sample_rate) {
+ av_log(ctx, AV_LOG_ERROR, "Invalid value '%s' for rate",
+ sample_rate_str);
+ return AVERROR(EINVAL);
+ }
+ abuffer->sample_rate = sample_rate;
+
+ abuffer->fifo = av_fifo_alloc(FIFO_SIZE*sizeof(AVFilterBufferRef*));
+ if (!abuffer->fifo) {
+ av_log(ctx, AV_LOG_ERROR, "Failed to allocate fifo, filter init failed.\n");
+ return AVERROR(ENOMEM);
+ }
+
+ av_get_channel_layout_string(chlayout_str, sizeof(chlayout_str),
+ -1, abuffer->channel_layout);
+ av_log(ctx, AV_LOG_INFO, "fmt:%s channel_layout:%s sr:%d\n",
+ av_get_sample_fmt_name(abuffer->sample_fmt), chlayout_str,
+ abuffer->sample_rate);
+
+ return 0;
+}
+
+static av_cold void uninit(AVFilterContext *ctx)
+{
+ ABufferSourceContext *abuffer = ctx->priv;
+ av_fifo_free(abuffer->fifo);
+}
+
+static int query_formats(AVFilterContext *ctx)
+{
+ ABufferSourceContext *abuffer = ctx->priv;
+ AVFilterFormats *formats;
+
+ formats = NULL;
+ avfilter_add_format(&formats, abuffer->sample_fmt);
+ avfilter_set_common_sample_formats(ctx, formats);
+
+ formats = NULL;
+ avfilter_add_format(&formats, abuffer->channel_layout);
+ avfilter_set_common_channel_layouts(ctx, formats);
+
+ formats = NULL;
+ avfilter_add_format(&formats, AVFILTER_PACKED); //FIXME: Assuming packed
+ avfilter_set_common_packing_formats(ctx, formats);
+
+ return 0;
+}
+
+static int config_props(AVFilterLink *inlink)
+{
+ ABufferSourceContext *abuffer = inlink->src->priv;
+ inlink->format = abuffer->sample_fmt;
+ inlink->channel_layout = abuffer->channel_layout;
+ inlink->sample_rate = abuffer->sample_rate;
+ return 0;
+}
+
+static int request_frame(AVFilterLink *inlink)
+{
+ ABufferSourceContext *abuffer = inlink->src->priv;
+ AVFilterBufferRef *samplesref;
+
+ if (!av_fifo_size(abuffer->fifo)) {
+ av_log(inlink->src, AV_LOG_ERROR,
+ "request_frame() called with no available frames!\n");
+ }
+
+ av_fifo_generic_read(abuffer->fifo, &samplesref, sizeof(samplesref), NULL);
+ avfilter_filter_samples(inlink, avfilter_ref_buffer(samplesref, ~0));
+ avfilter_unref_buffer(samplesref);
+
+ return 0;
+}
+
+static int poll_frame(AVFilterLink *link)
+{
+ ABufferSourceContext *abuffer = link->src->priv;
+ return av_fifo_size(abuffer->fifo)/sizeof(AVFilterBufferRef*);
+}
+
+AVFilter avfilter_asrc_abuffer =
+{
+ .name = "abuffer",
+ .description = NULL_IF_CONFIG_SMALL("Buffer audio frames, and make them accessible to the filterchain."),
+ .priv_size = sizeof(ABufferSourceContext),
+ .query_formats = query_formats,
+
+ .init = init,
+ .uninit = uninit,
+
+ .inputs = (AVFilterPad[]) {{ .name = NULL }},
+ .outputs = (AVFilterPad[]) {{ .name = "default",
+ .type = AVMEDIA_TYPE_AUDIO,
+ .request_frame = request_frame,
+ .poll_frame = poll_frame,
+ .config_props = config_props, },
+ { .name = NULL}},
+};
diff --git a/libavfilter/asrc_abuffer.h b/libavfilter/asrc_abuffer.h
new file mode 100644
index 0000000..de34a80
--- /dev/null
+++ b/libavfilter/asrc_abuffer.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2010 by S.N. Hemanth Meenakshisundaram
+ *
+ * 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
+ */
+
+#ifndef AVFILTER_ASRC_ABUFFER_H
+#define AVFILTER_ASRC_ABUFFER_H
+
+#include "avfilter.h"
+#include "libavutil/fifo.h"
+
+/**
+ * @file
+ * memory buffer source filter for audio
+ */
+
+/**
+ * The Buffer Source Context
+ */
+typedef struct {
+ unsigned int sample_fmt; ///< initial sample format indicated by client
+ int64_t channel_layout; ///< initial channel layout indicated by client
+ int sample_rate;
+ AVFifoBuffer *fifo; ///< FIFO buffer of audio frame pointers
+} ABufferSourceContext;
+
+/**
+ * Queue an audio buffer to the audio buffer source.
+ *
+ * @param abufsrc audio source buffer context
+ * @param data pointers to the samples planes
+ * @param linesize linesizes of each audio buffer plane
+ * @param nb_samples number of samples per channel
+ * @param sample_fmt sample format of the audio data
+ * @param ch_layout channel layout of the audio data
+ * @param planar flag to indicate if audio data is planar or packed
+ * @param pts presentation timestamp of the audio buffer
+ */
+int av_asrc_buffer_add_samples(AVFilterContext *abufsrc,
+ uint8_t *data[8], int linesize[8],
+ int nb_samples,
+ int sample_fmt, int64_t ch_layout, int planar,
+ int64_t pts);
+
+/**
+ * Queue an audio buffer to the audio buffer source.
+ *
+ * This is similar to av_asrc_buffer_add_samples(), but the samples
+ * are stored in a buffer with known size.
+ *
+ * @param abufsrc audio source buffer context
+ * @param buf pointer to the samples data, packed is assumed
+ * @param size the size in bytes of the buffer, it must contain an
+ * integer number of samples
+ * @param sample_fmt sample format of the audio data
+ * @param ch_layout channel layout of the audio data
+ * @param pts presentation timestamp of the audio buffer
+ */
+int av_asrc_buffer_add_buffer(AVFilterContext *abufsrc,
+ uint8_t *buf, int buf_size,
+ int sample_fmt, int64_t ch_layout,
+ int64_t pts);
+
+#endif /* AVFILTER_ASRC_ABUFFER_H */
--
1.7.4.4
More information about the ffmpeg-devel
mailing list