[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