[FFmpeg-devel] [PATCH 2/4] lavfi: add audioframe helper functions.
Nicolas George
nicolas.george at normalesup.org
Fri Jun 29 14:41:07 CEST 2012
Signed-off-by: Nicolas George <nicolas.george at normalesup.org>
---
libavfilter/audioframe.h | 145 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 145 insertions(+)
create mode 100644 libavfilter/audioframe.h
diff --git a/libavfilter/audioframe.h b/libavfilter/audioframe.h
new file mode 100644
index 0000000..f66cc6b
--- /dev/null
+++ b/libavfilter/audioframe.h
@@ -0,0 +1,145 @@
+/*
+ * Helpers to get fixed-size audio frames
+ * Copyright (c) 2012 Nicolas George
+ *
+ * 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_AUDIOFRAME_H
+#define AVFILTER_AUDIOFRAME_H
+
+#include "avfilter.h"
+#include "audio.h"
+
+/**
+ * This file implements helpers for filters that require a fixed amount of
+ * samples as their input.
+ *
+ * Here is the basic template to use it:
+ *
+ * Declare somewhere, probably in the private context of the filter:
+ * AVFilterBufferRef *partial_buf = NULL;
+ *
+ * In filter_samples(inlink, insamples), do:
+ *
+ * int insamples_pos = 0;
+ * while (!ff_audioframe_feed(frame_size, inlink, NULL, AV_PERM_READ,
+ * insamples, &priv->partial_buf, &insamples_pos)) {
+ * do_something_with(priv->partial_buf);
+ * priv->partial_buf = NULL; (or avfilter_unref_bufferp)
+ * }
+ * avfilter_unref_buffer(insamples);
+ *
+ * As a reaction to a call to request_frame() on the input:
+ *
+ * if (ret == AVERROR_EOF && priv->partial_buf) {
+ * ff_audioframe_pad(frame_size, inlink, priv->partial_buf);
+ * do_something_with(priv->partial_buf);
+ * priv->partial_buf = NULL; (or avfilter_unref_bufferp)
+ * return 0;
+ * }
+ *
+ * In uninit():
+ *
+ * avfilter_unref_bufferp(&priv->partial_buf);
+ */
+
+/**
+ * Add samples to a buffer until a fixed size is reached.
+ *
+ * @param frame_size number of samples to accumulate
+ * @param inlink link where the samples come from; used to determine
+ * the format of the samples
+ * @param outlink link to request the buffer on; must have exactly
+ * the same format as inlink; if NULL, use
+ * ff_default_get_audio_buffer on inlink to get a
+ * fresh memory buffer
+ * @param perms permissions to request on the buffer; AV_PERM_WRITE
+ * is automatically added
+ * @param insamples input samples
+ * @param outsamples pointer to the buffer being filled; if set to NULL,
+ * a new buffer will be allocated as necessary
+ * @param insamples_pos pointer to an integer used to keep the position in
+ * the input samples; the integer must be initialized
+ * to 0 for each new input buffer
+ * @return 0 if the buffer is full;
+ * AVERROR(EAGAIN) if the buffer is not yet full;
+ * or any AVERROR code if an error happened
+ * If the function returns 0, the caller must set outsamples to NULL before
+ * the next call.
+ */
+static inline int ff_audioframe_feed(int frame_size,
+ AVFilterLink *inlink,
+ AVFilterLink *outlink,
+ int perms,
+ AVFilterBufferRef *insamples,
+ AVFilterBufferRef **outsamples,
+ int *insamples_pos)
+{
+ int nb_samples = insamples->audio->nb_samples - *insamples_pos;
+
+ if (!nb_samples)
+ return AVERROR(EAGAIN);
+ if (!*outsamples) {
+ AVRational samples_tb = { 1, inlink->sample_rate };
+ perms |= AV_PERM_WRITE;
+ *outsamples = outlink ? ff_get_audio_buffer(outlink, perms, frame_size):
+ ff_default_get_audio_buffer(inlink, perms, frame_size);
+ if (!*outsamples)
+ return AVERROR(ENOMEM);
+ avfilter_copy_buffer_ref_props(*outsamples, insamples);
+ (*outsamples)->pts = insamples->pts +
+ av_rescale_q(*insamples_pos,
+ samples_tb, inlink->time_base);
+ (*outsamples)->audio->nb_samples = 0;
+ }
+ nb_samples = FFMIN(nb_samples,
+ frame_size - (*outsamples)->audio->nb_samples);
+ av_samples_copy((*outsamples)->extended_data,
+ insamples->extended_data,
+ (*outsamples)->audio->nb_samples,
+ *insamples_pos,
+ nb_samples,
+ av_get_channel_layout_nb_channels(inlink->channel_layout),
+ inlink->format);
+ *insamples_pos += nb_samples;
+ (*outsamples)->audio->nb_samples += nb_samples;
+ return (*outsamples)->audio->nb_samples == frame_size ? 0 : AVERROR(EAGAIN);
+}
+
+/**
+ * Pad a buffer to a fixed size with silence.
+
+ * @param frame_size number of samples to accumulate
+ * @param inlink link where the samples come from; used to determine
+ * the format of the samples
+ * @param outsamples buffer being filled
+ */
+static inline void ff_audioframe_pad(int frame_size,
+ AVFilterLink *inlink,
+ AVFilterBufferRef *outsamples)
+{
+ int nb_channels = av_get_channel_layout_nb_channels(inlink->channel_layout);
+ av_samples_set_silence(outsamples->extended_data,
+ outsamples->audio->nb_samples,
+ frame_size - outsamples->audio->nb_samples,
+ nb_channels,
+ inlink->format);
+ outsamples->audio->nb_samples = frame_size;
+}
+
+#endif /* AVFILTER_AUDIOFRAME_H */
--
1.7.10
More information about the ffmpeg-devel
mailing list