00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <stdint.h>
00022
00023 #include "libavutil/mem.h"
00024 #include "audio_data.h"
00025
00026 static const AVClass audio_data_class = {
00027 .class_name = "AudioData",
00028 .item_name = av_default_item_name,
00029 .version = LIBAVUTIL_VERSION_INT,
00030 };
00031
00032
00033
00034
00035 static void calc_ptr_alignment(AudioData *a)
00036 {
00037 int p;
00038 int min_align = 128;
00039
00040 for (p = 0; p < a->planes; p++) {
00041 int cur_align = 128;
00042 while ((intptr_t)a->data[p] % cur_align)
00043 cur_align >>= 1;
00044 if (cur_align < min_align)
00045 min_align = cur_align;
00046 }
00047 a->ptr_align = min_align;
00048 }
00049
00050 int ff_audio_data_set_channels(AudioData *a, int channels)
00051 {
00052 if (channels < 1 || channels > AVRESAMPLE_MAX_CHANNELS ||
00053 channels > a->allocated_channels)
00054 return AVERROR(EINVAL);
00055
00056 a->channels = channels;
00057 a->planes = a->is_planar ? channels : 1;
00058
00059 calc_ptr_alignment(a);
00060
00061 return 0;
00062 }
00063
00064 int ff_audio_data_init(AudioData *a, void **src, int plane_size, int channels,
00065 int nb_samples, enum AVSampleFormat sample_fmt,
00066 int read_only, const char *name)
00067 {
00068 int p;
00069
00070 memset(a, 0, sizeof(*a));
00071 a->class = &audio_data_class;
00072
00073 if (channels < 1 || channels > AVRESAMPLE_MAX_CHANNELS) {
00074 av_log(a, AV_LOG_ERROR, "invalid channel count: %d\n", channels);
00075 return AVERROR(EINVAL);
00076 }
00077
00078 a->sample_size = av_get_bytes_per_sample(sample_fmt);
00079 if (!a->sample_size) {
00080 av_log(a, AV_LOG_ERROR, "invalid sample format\n");
00081 return AVERROR(EINVAL);
00082 }
00083 a->is_planar = av_sample_fmt_is_planar(sample_fmt);
00084 a->planes = a->is_planar ? channels : 1;
00085 a->stride = a->sample_size * (a->is_planar ? 1 : channels);
00086
00087 for (p = 0; p < (a->is_planar ? channels : 1); p++) {
00088 if (!src[p]) {
00089 av_log(a, AV_LOG_ERROR, "invalid NULL pointer for src[%d]\n", p);
00090 return AVERROR(EINVAL);
00091 }
00092 a->data[p] = src[p];
00093 }
00094 a->allocated_samples = nb_samples * !read_only;
00095 a->nb_samples = nb_samples;
00096 a->sample_fmt = sample_fmt;
00097 a->channels = channels;
00098 a->allocated_channels = channels;
00099 a->read_only = read_only;
00100 a->allow_realloc = 0;
00101 a->name = name ? name : "{no name}";
00102
00103 calc_ptr_alignment(a);
00104 a->samples_align = plane_size / a->stride;
00105
00106 return 0;
00107 }
00108
00109 AudioData *ff_audio_data_alloc(int channels, int nb_samples,
00110 enum AVSampleFormat sample_fmt, const char *name)
00111 {
00112 AudioData *a;
00113 int ret;
00114
00115 if (channels < 1 || channels > AVRESAMPLE_MAX_CHANNELS)
00116 return NULL;
00117
00118 a = av_mallocz(sizeof(*a));
00119 if (!a)
00120 return NULL;
00121
00122 a->sample_size = av_get_bytes_per_sample(sample_fmt);
00123 if (!a->sample_size) {
00124 av_free(a);
00125 return NULL;
00126 }
00127 a->is_planar = av_sample_fmt_is_planar(sample_fmt);
00128 a->planes = a->is_planar ? channels : 1;
00129 a->stride = a->sample_size * (a->is_planar ? 1 : channels);
00130
00131 a->class = &audio_data_class;
00132 a->sample_fmt = sample_fmt;
00133 a->channels = channels;
00134 a->allocated_channels = channels;
00135 a->read_only = 0;
00136 a->allow_realloc = 1;
00137 a->name = name ? name : "{no name}";
00138
00139 if (nb_samples > 0) {
00140 ret = ff_audio_data_realloc(a, nb_samples);
00141 if (ret < 0) {
00142 av_free(a);
00143 return NULL;
00144 }
00145 return a;
00146 } else {
00147 calc_ptr_alignment(a);
00148 return a;
00149 }
00150 }
00151
00152 int ff_audio_data_realloc(AudioData *a, int nb_samples)
00153 {
00154 int ret, new_buf_size, plane_size, p;
00155
00156
00157 if (a->allocated_samples >= nb_samples)
00158 return 0;
00159
00160
00161 if (a->read_only || !a->allow_realloc)
00162 return AVERROR(EINVAL);
00163
00164 new_buf_size = av_samples_get_buffer_size(&plane_size,
00165 a->allocated_channels, nb_samples,
00166 a->sample_fmt, 0);
00167 if (new_buf_size < 0)
00168 return new_buf_size;
00169
00170
00171
00172
00173 if (a->nb_samples > 0 && a->is_planar) {
00174 uint8_t *new_data[AVRESAMPLE_MAX_CHANNELS] = { NULL };
00175
00176 ret = av_samples_alloc(new_data, &plane_size, a->allocated_channels,
00177 nb_samples, a->sample_fmt, 0);
00178 if (ret < 0)
00179 return ret;
00180
00181 for (p = 0; p < a->planes; p++)
00182 memcpy(new_data[p], a->data[p], a->nb_samples * a->stride);
00183
00184 av_freep(&a->buffer);
00185 memcpy(a->data, new_data, sizeof(new_data));
00186 a->buffer = a->data[0];
00187 } else {
00188 av_freep(&a->buffer);
00189 a->buffer = av_malloc(new_buf_size);
00190 if (!a->buffer)
00191 return AVERROR(ENOMEM);
00192 ret = av_samples_fill_arrays(a->data, &plane_size, a->buffer,
00193 a->allocated_channels, nb_samples,
00194 a->sample_fmt, 0);
00195 if (ret < 0)
00196 return ret;
00197 }
00198 a->buffer_size = new_buf_size;
00199 a->allocated_samples = nb_samples;
00200
00201 calc_ptr_alignment(a);
00202 a->samples_align = plane_size / a->stride;
00203
00204 return 0;
00205 }
00206
00207 void ff_audio_data_free(AudioData **a)
00208 {
00209 if (!*a)
00210 return;
00211 av_free((*a)->buffer);
00212 av_freep(a);
00213 }
00214
00215 int ff_audio_data_copy(AudioData *dst, AudioData *src)
00216 {
00217 int ret, p;
00218
00219
00220 if (dst->sample_fmt != src->sample_fmt || dst->channels < src->channels)
00221 return AVERROR(EINVAL);
00222
00223
00224 if (!src->nb_samples) {
00225 dst->nb_samples = 0;
00226 return 0;
00227 }
00228
00229
00230 ret = ff_audio_data_realloc(dst, src->nb_samples);
00231 if (ret < 0)
00232 return ret;
00233
00234
00235 for (p = 0; p < src->planes; p++)
00236 memcpy(dst->data[p], src->data[p], src->nb_samples * src->stride);
00237 dst->nb_samples = src->nb_samples;
00238
00239 return 0;
00240 }
00241
00242 int ff_audio_data_combine(AudioData *dst, int dst_offset, AudioData *src,
00243 int src_offset, int nb_samples)
00244 {
00245 int ret, p, dst_offset2, dst_move_size;
00246
00247
00248 if (dst->sample_fmt != src->sample_fmt || dst->channels != src->channels) {
00249 av_log(src, AV_LOG_ERROR, "sample format mismatch\n");
00250 return AVERROR(EINVAL);
00251 }
00252
00253
00254 if (dst_offset < 0 || dst_offset > dst->nb_samples ||
00255 src_offset < 0 || src_offset > src->nb_samples) {
00256 av_log(src, AV_LOG_ERROR, "offset out-of-bounds: src=%d dst=%d\n",
00257 src_offset, dst_offset);
00258 return AVERROR(EINVAL);
00259 }
00260
00261
00262 if (nb_samples > src->nb_samples - src_offset)
00263 nb_samples = src->nb_samples - src_offset;
00264 if (nb_samples <= 0)
00265 return 0;
00266
00267
00268 if (dst->read_only) {
00269 av_log(dst, AV_LOG_ERROR, "dst is read-only\n");
00270 return AVERROR(EINVAL);
00271 }
00272
00273
00274 ret = ff_audio_data_realloc(dst, dst->nb_samples + nb_samples);
00275 if (ret < 0) {
00276 av_log(dst, AV_LOG_ERROR, "error reallocating dst\n");
00277 return ret;
00278 }
00279
00280 dst_offset2 = dst_offset + nb_samples;
00281 dst_move_size = dst->nb_samples - dst_offset;
00282
00283 for (p = 0; p < src->planes; p++) {
00284 if (dst_move_size > 0) {
00285 memmove(dst->data[p] + dst_offset2 * dst->stride,
00286 dst->data[p] + dst_offset * dst->stride,
00287 dst_move_size * dst->stride);
00288 }
00289 memcpy(dst->data[p] + dst_offset * dst->stride,
00290 src->data[p] + src_offset * src->stride,
00291 nb_samples * src->stride);
00292 }
00293 dst->nb_samples += nb_samples;
00294
00295 return 0;
00296 }
00297
00298 void ff_audio_data_drain(AudioData *a, int nb_samples)
00299 {
00300 if (a->nb_samples <= nb_samples) {
00301
00302 a->nb_samples = 0;
00303 } else {
00304 int p;
00305 int move_offset = a->stride * nb_samples;
00306 int move_size = a->stride * (a->nb_samples - nb_samples);
00307
00308 for (p = 0; p < a->planes; p++)
00309 memmove(a->data[p], a->data[p] + move_offset, move_size);
00310
00311 a->nb_samples -= nb_samples;
00312 }
00313 }
00314
00315 int ff_audio_data_add_to_fifo(AVAudioFifo *af, AudioData *a, int offset,
00316 int nb_samples)
00317 {
00318 uint8_t *offset_data[AVRESAMPLE_MAX_CHANNELS];
00319 int offset_size, p;
00320
00321 if (offset >= a->nb_samples)
00322 return 0;
00323 offset_size = offset * a->stride;
00324 for (p = 0; p < a->planes; p++)
00325 offset_data[p] = a->data[p] + offset_size;
00326
00327 return av_audio_fifo_write(af, (void **)offset_data, nb_samples);
00328 }
00329
00330 int ff_audio_data_read_from_fifo(AVAudioFifo *af, AudioData *a, int nb_samples)
00331 {
00332 int ret;
00333
00334 if (a->read_only)
00335 return AVERROR(EINVAL);
00336
00337 ret = ff_audio_data_realloc(a, nb_samples);
00338 if (ret < 0)
00339 return ret;
00340
00341 ret = av_audio_fifo_read(af, (void **)a->data, nb_samples);
00342 if (ret >= 0)
00343 a->nb_samples = ret;
00344 return ret;
00345 }