Based on code by Stefano Sabatini.tags/n0.9
| @@ -13,6 +13,10 @@ libavutil: 2011-04-18 | |||
| API changes, most recent first: | |||
| 2011-xx-xx - xxxxxxx - lavu 51.18.0 | |||
| Add av_samples_get_buffer_size(), av_samples_fill_arrays(), and | |||
| av_samples_alloc(), to samplefmt.h. | |||
| 2011-xx-xx - xxxxxxx - lavu 51.17.0 | |||
| Add planar sample formats and av_sample_fmt_is_planar() to samplefmt.h. | |||
| @@ -153,7 +153,7 @@ | |||
| */ | |||
| #define LIBAVUTIL_VERSION_MAJOR 51 | |||
| #define LIBAVUTIL_VERSION_MINOR 17 | |||
| #define LIBAVUTIL_VERSION_MINOR 18 | |||
| #define LIBAVUTIL_VERSION_MICRO 0 | |||
| #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ | |||
| @@ -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; | |||
| } | |||
| @@ -92,4 +92,57 @@ int av_get_bytes_per_sample(enum AVSampleFormat sample_fmt); | |||
| */ | |||
| 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 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 channel's data | |||
| * buffer for planar layout, or the aligned size of the buffer for all channels | |||
| * for packed layout. | |||
| * | |||
| * @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 **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 data pointers and | |||
| * linesize accordingly. | |||
| * The allocated samples buffer can be freed by using av_freep(&audio_data[0]) | |||
| * | |||
| * @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 **audio_data, int *linesize, int nb_channels, | |||
| int nb_samples, enum AVSampleFormat sample_fmt, int align); | |||
| #endif /* AVUTIL_SAMPLEFMT_H */ | |||