summaryrefslogtreecommitdiff
path: root/libavutil/samplefmt.c
diff options
context:
space:
mode:
authorJustin Ruggles <justin.ruggles@gmail.com>2011-11-12 15:43:43 -0500
committerJustin Ruggles <justin.ruggles@gmail.com>2011-11-23 18:39:28 -0500
commitbbb46f3ec7128d8a624f2aa5b4f99ec44c0b9567 (patch)
tree5dd7a139179e4040b58f09dc0140816d72ddd9d4 /libavutil/samplefmt.c
parent8889cc4f5b767b323901115a92318a024336e2a1 (diff)
libavutil: add utility functions to simplify allocation of audio buffers.
Based on code by Stefano Sabatini.
Diffstat (limited to 'libavutil/samplefmt.c')
-rw-r--r--libavutil/samplefmt.c65
1 files changed, 65 insertions, 0 deletions
diff --git a/libavutil/samplefmt.c b/libavutil/samplefmt.c
index 6fc3b7e467..f38d05e426 100644
--- a/libavutil/samplefmt.c
+++ b/libavutil/samplefmt.c
@@ -92,3 +92,68 @@ int av_sample_fmt_is_planar(enum AVSampleFormat sample_fmt)
return 0;
return sample_fmt_info[sample_fmt].planar;
}
+
+int av_samples_get_buffer_size(int *linesize, int nb_channels, int nb_samples,
+ enum AVSampleFormat sample_fmt, int align)
+{
+ int line_size;
+ int sample_size = av_get_bytes_per_sample(sample_fmt);
+ int planar = av_sample_fmt_is_planar(sample_fmt);
+
+ /* validate parameter ranges */
+ if (!sample_size || nb_samples <= 0 || nb_channels <= 0)
+ return AVERROR(EINVAL);
+
+ /* check for integer overflow */
+ if (nb_channels > INT_MAX / align ||
+ (int64_t)nb_channels * nb_samples > (INT_MAX - (align * nb_channels)) / sample_size)
+ return AVERROR(EINVAL);
+
+ line_size = planar ? FFALIGN(nb_samples * sample_size, align) :
+ FFALIGN(nb_samples * sample_size * nb_channels, align);
+ if (linesize)
+ *linesize = line_size;
+
+ return planar ? line_size * nb_channels : line_size;
+}
+
+int av_samples_fill_arrays(uint8_t **audio_data, int *linesize,
+ uint8_t *buf, int nb_channels, int nb_samples,
+ enum AVSampleFormat sample_fmt, int align)
+{
+ int ch, planar, buf_size;
+
+ planar = av_sample_fmt_is_planar(sample_fmt);
+ buf_size = av_samples_get_buffer_size(linesize, nb_channels, nb_samples,
+ sample_fmt, align);
+ if (buf_size < 0)
+ return buf_size;
+
+ audio_data[0] = buf;
+ for (ch = 1; planar && ch < nb_channels; ch++)
+ audio_data[ch] = audio_data[ch-1] + *linesize;
+
+ return 0;
+}
+
+int av_samples_alloc(uint8_t **audio_data, int *linesize, int nb_channels,
+ int nb_samples, enum AVSampleFormat sample_fmt, int align)
+{
+ uint8_t *buf;
+ int size = av_samples_get_buffer_size(NULL, nb_channels, nb_samples,
+ sample_fmt, align);
+ if (size < 0)
+ return size;
+
+ buf = av_mallocz(size);
+ if (!buf)
+ return AVERROR(ENOMEM);
+
+ size = av_samples_fill_arrays(audio_data, linesize, buf, nb_channels,
+ nb_samples, sample_fmt, align);
+ if (size < 0) {
+ av_free(buf);
+ return size;
+ }
+ return 0;
+}