Browse Source

avutil: add audio fifo buffer

The functions operate on the sample level rather than the byte level and work
with all audio sample formats.
Justin Ruggles 13 years ago
parent
commit
0c0d1bce7c
5 changed files with 355 additions and 2 deletions
  1. 12 0
      doc/APIchanges
  2. 2 0
      libavutil/Makefile
  3. 193 0
      libavutil/audio_fifo.c
  4. 146 0
      libavutil/audio_fifo.h
  5. 2 2
      libavutil/avutil.h

+ 12 - 0
doc/APIchanges

@@ -12,6 +12,18 @@ libavutil:   2011-04-18
 
 API changes, most recent first:
 
+2012-xx-xx - xxxxxxx - lavu 51.28.0 - audio_fifo.h
+  Add audio FIFO functions:
+    av_audio_fifo_free()
+    av_audio_fifo_alloc()
+    av_audio_fifo_realloc()
+    av_audio_fifo_write()
+    av_audio_fifo_read()
+    av_audio_fifo_drain()
+    av_audio_fifo_reset()
+    av_audio_fifo_size()
+    av_audio_fifo_space()
+
 2012-xx-xx - xxxxxxx - lavfi 2.16.0 - avfiltergraph.h
   Add avfilter_graph_parse2(), avfilter_inout_alloc() and
   avfilter_inout_free() functions.

+ 2 - 0
libavutil/Makefile

@@ -3,6 +3,7 @@ NAME = avutil
 HEADERS = adler32.h                                                     \
           aes.h                                                         \
           attributes.h                                                  \
+          audio_fifo.h                                                  \
           audioconvert.h                                                \
           avassert.h                                                    \
           avstring.h                                                    \
@@ -40,6 +41,7 @@ BUILT_HEADERS = avconfig.h
 
 OBJS = adler32.o                                                        \
        aes.o                                                            \
+       audio_fifo.o                                                     \
        audioconvert.o                                                   \
        avstring.o                                                       \
        base64.o                                                         \

+ 193 - 0
libavutil/audio_fifo.c

@@ -0,0 +1,193 @@
+/*
+ * Audio FIFO
+ * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
+ *
+ * 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
+ * Audio FIFO
+ */
+
+#include "avutil.h"
+#include "audio_fifo.h"
+#include "fifo.h"
+#include "mem.h"
+#include "samplefmt.h"
+
+struct AVAudioFifo {
+    AVFifoBuffer **buf;             /**< single buffer for interleaved, per-channel buffers for planar */
+    int nb_buffers;                 /**< number of buffers */
+    int nb_samples;                 /**< number of samples currently in the FIFO */
+    int allocated_samples;          /**< current allocated size, in samples */
+
+    int channels;                   /**< number of channels */
+    enum AVSampleFormat sample_fmt; /**< sample format */
+    int sample_size;                /**< size, in bytes, of one sample in a buffer */
+};
+
+void av_audio_fifo_free(AVAudioFifo *af)
+{
+    if (af) {
+        if (af->buf) {
+            int i;
+            for (i = 0; i < af->nb_buffers; i++) {
+                if (af->buf[i])
+                    av_fifo_free(af->buf[i]);
+            }
+            av_free(af->buf);
+        }
+        av_free(af);
+    }
+}
+
+AVAudioFifo *av_audio_fifo_alloc(enum AVSampleFormat sample_fmt, int channels,
+                                 int nb_samples)
+{
+    AVAudioFifo *af;
+    int buf_size, i;
+
+    /* get channel buffer size (also validates parameters) */
+    if (av_samples_get_buffer_size(&buf_size, channels, nb_samples, sample_fmt, 1) < 0)
+        return NULL;
+
+    af = av_mallocz(sizeof(*af));
+    if (!af)
+        return NULL;
+
+    af->channels    = channels;
+    af->sample_fmt  = sample_fmt;
+    af->sample_size = buf_size / nb_samples;
+    af->nb_buffers  = av_sample_fmt_is_planar(sample_fmt) ? channels : 1;
+
+    af->buf = av_mallocz(af->nb_buffers * sizeof(*af->buf));
+    if (!af->buf)
+        goto error;
+
+    for (i = 0; i < af->nb_buffers; i++) {
+        af->buf[i] = av_fifo_alloc(buf_size);
+        if (!af->buf[i])
+            goto error;
+    }
+    af->allocated_samples = nb_samples;
+
+    return af;
+
+error:
+    av_audio_fifo_free(af);
+    return NULL;
+}
+
+int av_audio_fifo_realloc(AVAudioFifo *af, int nb_samples)
+{
+    int i, ret, buf_size;
+
+    if ((ret = av_samples_get_buffer_size(&buf_size, af->channels, nb_samples,
+                                          af->sample_fmt, 1)) < 0)
+        return ret;
+
+    for (i = 0; i < af->nb_buffers; i++) {
+        if ((ret = av_fifo_realloc2(af->buf[i], buf_size)) < 0)
+            return ret;
+    }
+    af->allocated_samples = nb_samples;
+    return 0;
+}
+
+int av_audio_fifo_write(AVAudioFifo *af, void **data, int nb_samples)
+{
+    int i, ret, size;
+
+    /* automatically reallocate buffers if needed */
+    if (av_audio_fifo_space(af) < nb_samples) {
+        int current_size = av_audio_fifo_size(af);
+        /* check for integer overflow in new size calculation */
+        if (INT_MAX / 2 - current_size < nb_samples)
+            return AVERROR(EINVAL);
+        /* reallocate buffers */
+        if ((ret = av_audio_fifo_realloc(af, 2 * (current_size + nb_samples))) < 0)
+            return ret;
+    }
+
+    size = nb_samples * af->sample_size;
+    for (i = 0; i < af->nb_buffers; i++) {
+        ret = av_fifo_generic_write(af->buf[i], data[i], size, NULL);
+        if (ret != size)
+            return AVERROR_BUG;
+    }
+    af->nb_samples += nb_samples;
+
+    return nb_samples;
+}
+
+int av_audio_fifo_read(AVAudioFifo *af, void **data, int nb_samples)
+{
+    int i, ret, size;
+
+    if (nb_samples < 0)
+        return AVERROR(EINVAL);
+    nb_samples = FFMIN(nb_samples, af->nb_samples);
+    if (!nb_samples)
+        return 0;
+
+    size = nb_samples * af->sample_size;
+    for (i = 0; i < af->nb_buffers; i++) {
+        if ((ret = av_fifo_generic_read(af->buf[i], data[i], size, NULL)) < 0)
+            return AVERROR_BUG;
+    }
+    af->nb_samples -= nb_samples;
+
+    return nb_samples;
+}
+
+int av_audio_fifo_drain(AVAudioFifo *af, int nb_samples)
+{
+    int i, size;
+
+    if (nb_samples < 0)
+        return AVERROR(EINVAL);
+    nb_samples = FFMIN(nb_samples, af->nb_samples);
+
+    if (nb_samples) {
+        size = nb_samples * af->sample_size;
+        for (i = 0; i < af->nb_buffers; i++)
+            av_fifo_drain(af->buf[i], size);
+        af->nb_samples -= nb_samples;
+    }
+    return 0;
+}
+
+void av_audio_fifo_reset(AVAudioFifo *af)
+{
+    int i;
+
+    for (i = 0; i < af->nb_buffers; i++)
+        av_fifo_reset(af->buf[i]);
+
+    af->nb_samples = 0;
+}
+
+int av_audio_fifo_size(AVAudioFifo *af)
+{
+    return af->nb_samples;
+}
+
+int av_audio_fifo_space(AVAudioFifo *af)
+{
+    return af->allocated_samples - af->nb_samples;
+}

+ 146 - 0
libavutil/audio_fifo.h

@@ -0,0 +1,146 @@
+/*
+ * Audio FIFO
+ * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
+ *
+ * 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
+ * Audio FIFO Buffer
+ */
+
+#ifndef AVUTIL_AUDIO_FIFO_H
+#define AVUTIL_AUDIO_FIFO_H
+
+#include "avutil.h"
+#include "fifo.h"
+#include "samplefmt.h"
+
+/**
+ * @addtogroup lavu_audio
+ * @{
+ */
+
+/**
+ * Context for an Audio FIFO Buffer.
+ *
+ * - Operates at the sample level rather than the byte level.
+ * - Supports multiple channels with either planar or packed sample format.
+ * - Automatic reallocation when writing to a full buffer.
+ */
+typedef struct AVAudioFifo AVAudioFifo;
+
+/**
+ * Free an AVAudioFifo.
+ *
+ * @param af  AVAudioFifo to free
+ */
+void av_audio_fifo_free(AVAudioFifo *af);
+
+/**
+ * Allocate an AVAudioFifo.
+ *
+ * @param sample_fmt  sample format
+ * @param channels    number of channels
+ * @param nb_samples  initial allocation size, in samples
+ * @return            newly allocated AVAudioFifo, or NULL on error
+ */
+AVAudioFifo *av_audio_fifo_alloc(enum AVSampleFormat sample_fmt, int channels,
+                                 int nb_samples);
+
+/**
+ * Reallocate an AVAudioFifo.
+ *
+ * @param af          AVAudioFifo to reallocate
+ * @param nb_samples  new allocation size, in samples
+ * @return            0 if OK, or negative AVERROR code on failure
+ */
+int av_audio_fifo_realloc(AVAudioFifo *af, int nb_samples);
+
+/**
+ * Write data to an AVAudioFifo.
+ *
+ * The AVAudioFifo will be reallocated automatically if the available space
+ * is less than nb_samples.
+ *
+ * @see enum AVSampleFormat
+ * The documentation for AVSampleFormat describes the data layout.
+ *
+ * @param af          AVAudioFifo to write to
+ * @param data        audio data plane pointers
+ * @param nb_samples  number of samples to write
+ * @return            number of samples actually written, or negative AVERROR
+ *                    code on failure.
+ */
+int av_audio_fifo_write(AVAudioFifo *af, void **data, int nb_samples);
+
+/**
+ * Read data from an AVAudioFifo.
+ *
+ * @see enum AVSampleFormat
+ * The documentation for AVSampleFormat describes the data layout.
+ *
+ * @param af          AVAudioFifo to read from
+ * @param data        audio data plane pointers
+ * @param nb_samples  number of samples to read
+ * @return            number of samples actually read, or negative AVERROR code
+ *                    on failure.
+ */
+int av_audio_fifo_read(AVAudioFifo *af, void **data, int nb_samples);
+
+/**
+ * Drain data from an AVAudioFifo.
+ *
+ * Removes the data without reading it.
+ *
+ * @param af          AVAudioFifo to drain
+ * @param nb_samples  number of samples to drain
+ * @return            0 if OK, or negative AVERROR code on failure
+ */
+int av_audio_fifo_drain(AVAudioFifo *af, int nb_samples);
+
+/**
+ * Reset the AVAudioFifo buffer.
+ *
+ * This empties all data in the buffer.
+ *
+ * @param af  AVAudioFifo to reset
+ */
+void av_audio_fifo_reset(AVAudioFifo *af);
+
+/**
+ * Get the current number of samples in the AVAudioFifo available for reading.
+ *
+ * @param af  the AVAudioFifo to query
+ * @return    number of samples available for reading
+ */
+int av_audio_fifo_size(AVAudioFifo *af);
+
+/**
+ * Get the current number of samples in the AVAudioFifo available for writing.
+ *
+ * @param af  the AVAudioFifo to query
+ * @return    number of samples available for writing
+ */
+int av_audio_fifo_space(AVAudioFifo *af);
+
+/**
+ * @}
+ */
+
+#endif /* AVUTIL_AUDIO_FIFO_H */

+ 2 - 2
libavutil/avutil.h

@@ -152,8 +152,8 @@
  */
 
 #define LIBAVUTIL_VERSION_MAJOR 51
-#define LIBAVUTIL_VERSION_MINOR 27
-#define LIBAVUTIL_VERSION_MICRO  2
+#define LIBAVUTIL_VERSION_MINOR 28
+#define LIBAVUTIL_VERSION_MICRO  0
 
 #define LIBAVUTIL_VERSION_INT   AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \
                                                LIBAVUTIL_VERSION_MINOR, \