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