summaryrefslogtreecommitdiff
path: root/libavutil
diff options
context:
space:
mode:
Diffstat (limited to 'libavutil')
-rw-r--r--libavutil/avutil.h2
-rw-r--r--libavutil/samplefmt.c103
-rw-r--r--libavutil/samplefmt.h87
3 files changed, 122 insertions, 70 deletions
diff --git a/libavutil/avutil.h b/libavutil/avutil.h
index a654f8b332..5697684906 100644
--- a/libavutil/avutil.h
+++ b/libavutil/avutil.h
@@ -153,7 +153,7 @@
*/
#define LIBAVUTIL_VERSION_MAJOR 51
-#define LIBAVUTIL_VERSION_MINOR 26
+#define LIBAVUTIL_VERSION_MINOR 27
#define LIBAVUTIL_VERSION_MICRO 0
#define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \
diff --git a/libavutil/samplefmt.c b/libavutil/samplefmt.c
index bdbbf0a37d..fb9c46cab2 100644
--- a/libavutil/samplefmt.c
+++ b/libavutil/samplefmt.c
@@ -25,15 +25,21 @@
typedef struct SampleFmtInfo {
char name[4];
int bits;
+ int planar;
} SampleFmtInfo;
/** this table gives more information about formats */
static const SampleFmtInfo sample_fmt_info[AV_SAMPLE_FMT_NB] = {
- [AV_SAMPLE_FMT_U8] = { .name = "u8", .bits = 8 },
- [AV_SAMPLE_FMT_S16] = { .name = "s16", .bits = 16 },
- [AV_SAMPLE_FMT_S32] = { .name = "s32", .bits = 32 },
- [AV_SAMPLE_FMT_FLT] = { .name = "flt", .bits = 32 },
- [AV_SAMPLE_FMT_DBL] = { .name = "dbl", .bits = 64 },
+ [AV_SAMPLE_FMT_U8] = { .name = "u8", .bits = 8, .planar = 0 },
+ [AV_SAMPLE_FMT_S16] = { .name = "s16", .bits = 16, .planar = 0 },
+ [AV_SAMPLE_FMT_S32] = { .name = "s32", .bits = 32, .planar = 0 },
+ [AV_SAMPLE_FMT_FLT] = { .name = "flt", .bits = 32, .planar = 0 },
+ [AV_SAMPLE_FMT_DBL] = { .name = "dbl", .bits = 64, .planar = 0 },
+ [AV_SAMPLE_FMT_U8P] = { .name = "u8p", .bits = 8, .planar = 1 },
+ [AV_SAMPLE_FMT_S16P] = { .name = "s16p", .bits = 16, .planar = 1 },
+ [AV_SAMPLE_FMT_S32P] = { .name = "s32p", .bits = 32, .planar = 1 },
+ [AV_SAMPLE_FMT_FLTP] = { .name = "fltp", .bits = 32, .planar = 1 },
+ [AV_SAMPLE_FMT_DBLP] = { .name = "dblp", .bits = 64, .planar = 1 },
};
const char *av_get_sample_fmt_name(enum AVSampleFormat sample_fmt)
@@ -80,51 +86,74 @@ int av_get_bits_per_sample_fmt(enum AVSampleFormat sample_fmt)
}
#endif
-int av_samples_fill_arrays(uint8_t *pointers[8], int linesizes[8],
- uint8_t *buf, int nb_channels, int nb_samples,
- enum AVSampleFormat sample_fmt, int planar, int align)
+int av_sample_fmt_is_planar(enum AVSampleFormat sample_fmt)
+{
+ if (sample_fmt < 0 || sample_fmt >= AV_SAMPLE_FMT_NB)
+ 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 i, linesize;
+ int line_size;
int sample_size = av_get_bytes_per_sample(sample_fmt);
+ int planar = av_sample_fmt_is_planar(sample_fmt);
- if (nb_channels * (uint64_t)nb_samples * sample_size >= INT_MAX - align*(uint64_t)nb_channels)
+ /* validate parameter ranges */
+ if (!sample_size || nb_samples <= 0 || nb_channels <= 0)
return AVERROR(EINVAL);
- linesize = planar ? FFALIGN(nb_samples*sample_size, align) :
- FFALIGN(nb_samples*sample_size*nb_channels, align);
-
- if (pointers) {
- pointers[0] = buf;
- for (i = 1; planar && i < nb_channels; i++) {
- pointers[i] = pointers[i-1] + linesize;
- }
- memset(&pointers[i], 0, (8-i) * sizeof(pointers[0]));
- }
- if (linesizes) {
- linesizes[0] = linesize;
- for (i = 1; planar && i < nb_channels; i++)
- linesizes[i] = linesizes[0];
- memset(&linesizes[i], 0, (8-i) * sizeof(linesizes[0]));
- }
+ /* 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 ? linesize * nb_channels : linesize;
+ return planar ? line_size * nb_channels : line_size;
}
-int av_samples_alloc(uint8_t *pointers[8], int linesizes[8],
- int nb_channels, int nb_samples,
- enum AVSampleFormat sample_fmt, int planar,
- int align)
+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_fill_arrays(NULL, NULL,
- NULL, nb_channels, nb_samples,
- sample_fmt, planar, align);
+ 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);
- return av_samples_fill_arrays(pointers, linesizes,
- buf, nb_channels, nb_samples,
- sample_fmt, planar, align);
+ 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;
}
diff --git a/libavutil/samplefmt.h b/libavutil/samplefmt.h
index b06755d2ce..92c006d6f0 100644
--- a/libavutil/samplefmt.h
+++ b/libavutil/samplefmt.h
@@ -31,6 +31,13 @@ enum AVSampleFormat {
AV_SAMPLE_FMT_S32, ///< signed 32 bits
AV_SAMPLE_FMT_FLT, ///< float
AV_SAMPLE_FMT_DBL, ///< double
+
+ AV_SAMPLE_FMT_U8P, ///< unsigned 8 bits, planar
+ AV_SAMPLE_FMT_S16P, ///< signed 16 bits, planar
+ AV_SAMPLE_FMT_S32P, ///< signed 32 bits, planar
+ AV_SAMPLE_FMT_FLTP, ///< float, planar
+ AV_SAMPLE_FMT_DBLP, ///< double, planar
+
AV_SAMPLE_FMT_NB ///< Number of sample formats. DO NOT USE if linking dynamically
};
@@ -78,48 +85,64 @@ int av_get_bits_per_sample_fmt(enum AVSampleFormat sample_fmt);
int av_get_bytes_per_sample(enum AVSampleFormat sample_fmt);
/**
- * Fill channel data pointers and linesizes for samples with sample
+ * Check if the sample format is planar.
+ *
+ * @param sample_fmt the sample format to inspect
+ * @return 1 if the sample format is planar, 0 if it is interleaved
+ */
+int av_sample_fmt_is_planar(enum AVSampleFormat sample_fmt);
+
+/**
+ * Get the required buffer size for the given audio parameters.
+ *
+ * @param[out] linesize calculated linesize, may be NULL
+ * @param nb_channels the number of channels
+ * @param nb_samples the number of samples in a single channel
+ * @param sample_fmt the sample format
+ * @return required buffer size, or negative error code on failure
+ */
+int av_samples_get_buffer_size(int *linesize, int nb_channels, int nb_samples,
+ enum AVSampleFormat sample_fmt, int align);
+
+/**
+ * Fill channel data pointers and linesize for samples with sample
* format sample_fmt.
*
* The pointers array is filled with the pointers to the samples data:
- * for planar, set the start point of each plane's data within the buffer,
+ * for planar, set the start point of each channel's data within the buffer,
* for packed, set the start point of the entire buffer only.
*
- * The linesize array is filled with the aligned size of each samples
- * plane, that is linesize[i] will contain the linesize of the plane i,
- * and will be zero for all the unused planes. All linesize values are
- * equal.
+ * The linesize array is filled with the aligned size of each channel's data
+ * buffer for planar layout, or the aligned size of the buffer for all channels
+ * for packed layout.
*
- * @param pointers array to be filled with the pointer for each plane, may be NULL
- * @param linesizes array to be filled with the linesize, may be NULL
- * @param buf the pointer to a buffer containing the samples
- * @param nb_samples the number of samples in a single channel
- * @param planar 1 if the samples layout is planar, 0 if it is packed
- * @param nb_channels the number of channels
- * @return the total size of the buffer, a negative
- * error code in case of failure
+ * @param[out] audio_data array to be filled with the pointer for each channel
+ * @param[out] linesize calculated linesize
+ * @param buf the pointer to a buffer containing the samples
+ * @param nb_channels the number of channels
+ * @param nb_samples the number of samples in a single channel
+ * @param sample_fmt the sample format
+ * @param align buffer size alignment (1 = no alignment required)
+ * @return 0 on success or a negative error code on failure
*/
-int av_samples_fill_arrays(uint8_t *pointers[8], int linesizes[8],
- uint8_t *buf, int nb_channels, int nb_samples,
- enum AVSampleFormat sample_fmt, int planar, int align);
+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);
/**
- * Allocate a samples buffer for nb_samples samples, and
- * fill pointers and linesizes accordingly.
- * The allocated samples buffer has to be freed by using
- * av_freep(&pointers[0]).
+ * Allocate a samples buffer for nb_samples samples, and fill data pointers and
+ * linesize accordingly.
+ * The allocated samples buffer can be freed by using av_freep(&audio_data[0])
*
- * @param nb_channels number of audio channels
- * @param nb_samples number of samples per channel
- * @param planar 1 if the samples layout is planar, 0 if packed,
- * @param align the value to use for buffer size alignment
- * @return the size in bytes required for the samples buffer, a negative
- * error code in case of failure
+ * @param[out] audio_data array to be filled with the pointer for each channel
+ * @param[out] linesize aligned size for audio buffer(s)
+ * @param nb_channels number of audio channels
+ * @param nb_samples number of samples per channel
+ * @param align buffer size alignment (1 = no alignment required)
+ * @return 0 on success or a negative error code on failure
* @see av_samples_fill_arrays()
*/
-int av_samples_alloc(uint8_t *pointers[8], int linesizes[8],
- int nb_channels, int nb_samples,
- enum AVSampleFormat sample_fmt, int planar,
- int align);
+int av_samples_alloc(uint8_t **audio_data, int *linesize, int nb_channels,
+ int nb_samples, enum AVSampleFormat sample_fmt, int align);
-#endif /* AVCORE_SAMPLEFMT_H */
+#endif /* AVUTIL_SAMPLEFMT_H */