annotate ffmpeg/libavresample/audio_data.c @ 13:844d341cf643 tip

Back up before ISMIR
author Yading Song <yading.song@eecs.qmul.ac.uk>
date Thu, 31 Oct 2013 13:17:06 +0000
parents f445c3017523
children
rev   line source
yading@11 1 /*
yading@11 2 * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
yading@11 3 *
yading@11 4 * This file is part of Libav.
yading@11 5 *
yading@11 6 * Libav is free software; you can redistribute it and/or
yading@11 7 * modify it under the terms of the GNU Lesser General Public
yading@11 8 * License as published by the Free Software Foundation; either
yading@11 9 * version 2.1 of the License, or (at your option) any later version.
yading@11 10 *
yading@11 11 * Libav is distributed in the hope that it will be useful,
yading@11 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
yading@11 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
yading@11 14 * Lesser General Public License for more details.
yading@11 15 *
yading@11 16 * You should have received a copy of the GNU Lesser General Public
yading@11 17 * License along with Libav; if not, write to the Free Software
yading@11 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
yading@11 19 */
yading@11 20
yading@11 21 #include <stdint.h>
yading@11 22 #include <string.h>
yading@11 23
yading@11 24 #include "libavutil/mem.h"
yading@11 25 #include "audio_data.h"
yading@11 26
yading@11 27 static const AVClass audio_data_class = {
yading@11 28 .class_name = "AudioData",
yading@11 29 .item_name = av_default_item_name,
yading@11 30 .version = LIBAVUTIL_VERSION_INT,
yading@11 31 };
yading@11 32
yading@11 33 /*
yading@11 34 * Calculate alignment for data pointers.
yading@11 35 */
yading@11 36 static void calc_ptr_alignment(AudioData *a)
yading@11 37 {
yading@11 38 int p;
yading@11 39 int min_align = 128;
yading@11 40
yading@11 41 for (p = 0; p < a->planes; p++) {
yading@11 42 int cur_align = 128;
yading@11 43 while ((intptr_t)a->data[p] % cur_align)
yading@11 44 cur_align >>= 1;
yading@11 45 if (cur_align < min_align)
yading@11 46 min_align = cur_align;
yading@11 47 }
yading@11 48 a->ptr_align = min_align;
yading@11 49 }
yading@11 50
yading@11 51 int ff_audio_data_set_channels(AudioData *a, int channels)
yading@11 52 {
yading@11 53 if (channels < 1 || channels > AVRESAMPLE_MAX_CHANNELS ||
yading@11 54 channels > a->allocated_channels)
yading@11 55 return AVERROR(EINVAL);
yading@11 56
yading@11 57 a->channels = channels;
yading@11 58 a->planes = a->is_planar ? channels : 1;
yading@11 59
yading@11 60 calc_ptr_alignment(a);
yading@11 61
yading@11 62 return 0;
yading@11 63 }
yading@11 64
yading@11 65 int ff_audio_data_init(AudioData *a, uint8_t **src, int plane_size, int channels,
yading@11 66 int nb_samples, enum AVSampleFormat sample_fmt,
yading@11 67 int read_only, const char *name)
yading@11 68 {
yading@11 69 int p;
yading@11 70
yading@11 71 memset(a, 0, sizeof(*a));
yading@11 72 a->class = &audio_data_class;
yading@11 73
yading@11 74 if (channels < 1 || channels > AVRESAMPLE_MAX_CHANNELS) {
yading@11 75 av_log(a, AV_LOG_ERROR, "invalid channel count: %d\n", channels);
yading@11 76 return AVERROR(EINVAL);
yading@11 77 }
yading@11 78
yading@11 79 a->sample_size = av_get_bytes_per_sample(sample_fmt);
yading@11 80 if (!a->sample_size) {
yading@11 81 av_log(a, AV_LOG_ERROR, "invalid sample format\n");
yading@11 82 return AVERROR(EINVAL);
yading@11 83 }
yading@11 84 a->is_planar = av_sample_fmt_is_planar(sample_fmt);
yading@11 85 a->planes = a->is_planar ? channels : 1;
yading@11 86 a->stride = a->sample_size * (a->is_planar ? 1 : channels);
yading@11 87
yading@11 88 for (p = 0; p < (a->is_planar ? channels : 1); p++) {
yading@11 89 if (!src[p]) {
yading@11 90 av_log(a, AV_LOG_ERROR, "invalid NULL pointer for src[%d]\n", p);
yading@11 91 return AVERROR(EINVAL);
yading@11 92 }
yading@11 93 a->data[p] = src[p];
yading@11 94 }
yading@11 95 a->allocated_samples = nb_samples * !read_only;
yading@11 96 a->nb_samples = nb_samples;
yading@11 97 a->sample_fmt = sample_fmt;
yading@11 98 a->channels = channels;
yading@11 99 a->allocated_channels = channels;
yading@11 100 a->read_only = read_only;
yading@11 101 a->allow_realloc = 0;
yading@11 102 a->name = name ? name : "{no name}";
yading@11 103
yading@11 104 calc_ptr_alignment(a);
yading@11 105 a->samples_align = plane_size / a->stride;
yading@11 106
yading@11 107 return 0;
yading@11 108 }
yading@11 109
yading@11 110 AudioData *ff_audio_data_alloc(int channels, int nb_samples,
yading@11 111 enum AVSampleFormat sample_fmt, const char *name)
yading@11 112 {
yading@11 113 AudioData *a;
yading@11 114 int ret;
yading@11 115
yading@11 116 if (channels < 1 || channels > AVRESAMPLE_MAX_CHANNELS)
yading@11 117 return NULL;
yading@11 118
yading@11 119 a = av_mallocz(sizeof(*a));
yading@11 120 if (!a)
yading@11 121 return NULL;
yading@11 122
yading@11 123 a->sample_size = av_get_bytes_per_sample(sample_fmt);
yading@11 124 if (!a->sample_size) {
yading@11 125 av_free(a);
yading@11 126 return NULL;
yading@11 127 }
yading@11 128 a->is_planar = av_sample_fmt_is_planar(sample_fmt);
yading@11 129 a->planes = a->is_planar ? channels : 1;
yading@11 130 a->stride = a->sample_size * (a->is_planar ? 1 : channels);
yading@11 131
yading@11 132 a->class = &audio_data_class;
yading@11 133 a->sample_fmt = sample_fmt;
yading@11 134 a->channels = channels;
yading@11 135 a->allocated_channels = channels;
yading@11 136 a->read_only = 0;
yading@11 137 a->allow_realloc = 1;
yading@11 138 a->name = name ? name : "{no name}";
yading@11 139
yading@11 140 if (nb_samples > 0) {
yading@11 141 ret = ff_audio_data_realloc(a, nb_samples);
yading@11 142 if (ret < 0) {
yading@11 143 av_free(a);
yading@11 144 return NULL;
yading@11 145 }
yading@11 146 return a;
yading@11 147 } else {
yading@11 148 calc_ptr_alignment(a);
yading@11 149 return a;
yading@11 150 }
yading@11 151 }
yading@11 152
yading@11 153 int ff_audio_data_realloc(AudioData *a, int nb_samples)
yading@11 154 {
yading@11 155 int ret, new_buf_size, plane_size, p;
yading@11 156
yading@11 157 /* check if buffer is already large enough */
yading@11 158 if (a->allocated_samples >= nb_samples)
yading@11 159 return 0;
yading@11 160
yading@11 161 /* validate that the output is not read-only and realloc is allowed */
yading@11 162 if (a->read_only || !a->allow_realloc)
yading@11 163 return AVERROR(EINVAL);
yading@11 164
yading@11 165 new_buf_size = av_samples_get_buffer_size(&plane_size,
yading@11 166 a->allocated_channels, nb_samples,
yading@11 167 a->sample_fmt, 0);
yading@11 168 if (new_buf_size < 0)
yading@11 169 return new_buf_size;
yading@11 170
yading@11 171 /* if there is already data in the buffer and the sample format is planar,
yading@11 172 allocate a new buffer and copy the data, otherwise just realloc the
yading@11 173 internal buffer and set new data pointers */
yading@11 174 if (a->nb_samples > 0 && a->is_planar) {
yading@11 175 uint8_t *new_data[AVRESAMPLE_MAX_CHANNELS] = { NULL };
yading@11 176
yading@11 177 ret = av_samples_alloc(new_data, &plane_size, a->allocated_channels,
yading@11 178 nb_samples, a->sample_fmt, 0);
yading@11 179 if (ret < 0)
yading@11 180 return ret;
yading@11 181
yading@11 182 for (p = 0; p < a->planes; p++)
yading@11 183 memcpy(new_data[p], a->data[p], a->nb_samples * a->stride);
yading@11 184
yading@11 185 av_freep(&a->buffer);
yading@11 186 memcpy(a->data, new_data, sizeof(new_data));
yading@11 187 a->buffer = a->data[0];
yading@11 188 } else {
yading@11 189 av_freep(&a->buffer);
yading@11 190 a->buffer = av_malloc(new_buf_size);
yading@11 191 if (!a->buffer)
yading@11 192 return AVERROR(ENOMEM);
yading@11 193 ret = av_samples_fill_arrays(a->data, &plane_size, a->buffer,
yading@11 194 a->allocated_channels, nb_samples,
yading@11 195 a->sample_fmt, 0);
yading@11 196 if (ret < 0)
yading@11 197 return ret;
yading@11 198 }
yading@11 199 a->buffer_size = new_buf_size;
yading@11 200 a->allocated_samples = nb_samples;
yading@11 201
yading@11 202 calc_ptr_alignment(a);
yading@11 203 a->samples_align = plane_size / a->stride;
yading@11 204
yading@11 205 return 0;
yading@11 206 }
yading@11 207
yading@11 208 void ff_audio_data_free(AudioData **a)
yading@11 209 {
yading@11 210 if (!*a)
yading@11 211 return;
yading@11 212 av_free((*a)->buffer);
yading@11 213 av_freep(a);
yading@11 214 }
yading@11 215
yading@11 216 int ff_audio_data_copy(AudioData *dst, AudioData *src, ChannelMapInfo *map)
yading@11 217 {
yading@11 218 int ret, p;
yading@11 219
yading@11 220 /* validate input/output compatibility */
yading@11 221 if (dst->sample_fmt != src->sample_fmt || dst->channels < src->channels)
yading@11 222 return AVERROR(EINVAL);
yading@11 223
yading@11 224 if (map && !src->is_planar) {
yading@11 225 av_log(src, AV_LOG_ERROR, "cannot remap packed format during copy\n");
yading@11 226 return AVERROR(EINVAL);
yading@11 227 }
yading@11 228
yading@11 229 /* if the input is empty, just empty the output */
yading@11 230 if (!src->nb_samples) {
yading@11 231 dst->nb_samples = 0;
yading@11 232 return 0;
yading@11 233 }
yading@11 234
yading@11 235 /* reallocate output if necessary */
yading@11 236 ret = ff_audio_data_realloc(dst, src->nb_samples);
yading@11 237 if (ret < 0)
yading@11 238 return ret;
yading@11 239
yading@11 240 /* copy data */
yading@11 241 if (map) {
yading@11 242 if (map->do_remap) {
yading@11 243 for (p = 0; p < src->planes; p++) {
yading@11 244 if (map->channel_map[p] >= 0)
yading@11 245 memcpy(dst->data[p], src->data[map->channel_map[p]],
yading@11 246 src->nb_samples * src->stride);
yading@11 247 }
yading@11 248 }
yading@11 249 if (map->do_copy || map->do_zero) {
yading@11 250 for (p = 0; p < src->planes; p++) {
yading@11 251 if (map->channel_copy[p])
yading@11 252 memcpy(dst->data[p], dst->data[map->channel_copy[p]],
yading@11 253 src->nb_samples * src->stride);
yading@11 254 else if (map->channel_zero[p])
yading@11 255 av_samples_set_silence(&dst->data[p], 0, src->nb_samples,
yading@11 256 1, dst->sample_fmt);
yading@11 257 }
yading@11 258 }
yading@11 259 } else {
yading@11 260 for (p = 0; p < src->planes; p++)
yading@11 261 memcpy(dst->data[p], src->data[p], src->nb_samples * src->stride);
yading@11 262 }
yading@11 263
yading@11 264 dst->nb_samples = src->nb_samples;
yading@11 265
yading@11 266 return 0;
yading@11 267 }
yading@11 268
yading@11 269 int ff_audio_data_combine(AudioData *dst, int dst_offset, AudioData *src,
yading@11 270 int src_offset, int nb_samples)
yading@11 271 {
yading@11 272 int ret, p, dst_offset2, dst_move_size;
yading@11 273
yading@11 274 /* validate input/output compatibility */
yading@11 275 if (dst->sample_fmt != src->sample_fmt || dst->channels != src->channels) {
yading@11 276 av_log(src, AV_LOG_ERROR, "sample format mismatch\n");
yading@11 277 return AVERROR(EINVAL);
yading@11 278 }
yading@11 279
yading@11 280 /* validate offsets are within the buffer bounds */
yading@11 281 if (dst_offset < 0 || dst_offset > dst->nb_samples ||
yading@11 282 src_offset < 0 || src_offset > src->nb_samples) {
yading@11 283 av_log(src, AV_LOG_ERROR, "offset out-of-bounds: src=%d dst=%d\n",
yading@11 284 src_offset, dst_offset);
yading@11 285 return AVERROR(EINVAL);
yading@11 286 }
yading@11 287
yading@11 288 /* check offsets and sizes to see if we can just do nothing and return */
yading@11 289 if (nb_samples > src->nb_samples - src_offset)
yading@11 290 nb_samples = src->nb_samples - src_offset;
yading@11 291 if (nb_samples <= 0)
yading@11 292 return 0;
yading@11 293
yading@11 294 /* validate that the output is not read-only */
yading@11 295 if (dst->read_only) {
yading@11 296 av_log(dst, AV_LOG_ERROR, "dst is read-only\n");
yading@11 297 return AVERROR(EINVAL);
yading@11 298 }
yading@11 299
yading@11 300 /* reallocate output if necessary */
yading@11 301 ret = ff_audio_data_realloc(dst, dst->nb_samples + nb_samples);
yading@11 302 if (ret < 0) {
yading@11 303 av_log(dst, AV_LOG_ERROR, "error reallocating dst\n");
yading@11 304 return ret;
yading@11 305 }
yading@11 306
yading@11 307 dst_offset2 = dst_offset + nb_samples;
yading@11 308 dst_move_size = dst->nb_samples - dst_offset;
yading@11 309
yading@11 310 for (p = 0; p < src->planes; p++) {
yading@11 311 if (dst_move_size > 0) {
yading@11 312 memmove(dst->data[p] + dst_offset2 * dst->stride,
yading@11 313 dst->data[p] + dst_offset * dst->stride,
yading@11 314 dst_move_size * dst->stride);
yading@11 315 }
yading@11 316 memcpy(dst->data[p] + dst_offset * dst->stride,
yading@11 317 src->data[p] + src_offset * src->stride,
yading@11 318 nb_samples * src->stride);
yading@11 319 }
yading@11 320 dst->nb_samples += nb_samples;
yading@11 321
yading@11 322 return 0;
yading@11 323 }
yading@11 324
yading@11 325 void ff_audio_data_drain(AudioData *a, int nb_samples)
yading@11 326 {
yading@11 327 if (a->nb_samples <= nb_samples) {
yading@11 328 /* drain the whole buffer */
yading@11 329 a->nb_samples = 0;
yading@11 330 } else {
yading@11 331 int p;
yading@11 332 int move_offset = a->stride * nb_samples;
yading@11 333 int move_size = a->stride * (a->nb_samples - nb_samples);
yading@11 334
yading@11 335 for (p = 0; p < a->planes; p++)
yading@11 336 memmove(a->data[p], a->data[p] + move_offset, move_size);
yading@11 337
yading@11 338 a->nb_samples -= nb_samples;
yading@11 339 }
yading@11 340 }
yading@11 341
yading@11 342 int ff_audio_data_add_to_fifo(AVAudioFifo *af, AudioData *a, int offset,
yading@11 343 int nb_samples)
yading@11 344 {
yading@11 345 uint8_t *offset_data[AVRESAMPLE_MAX_CHANNELS];
yading@11 346 int offset_size, p;
yading@11 347
yading@11 348 if (offset >= a->nb_samples)
yading@11 349 return 0;
yading@11 350 offset_size = offset * a->stride;
yading@11 351 for (p = 0; p < a->planes; p++)
yading@11 352 offset_data[p] = a->data[p] + offset_size;
yading@11 353
yading@11 354 return av_audio_fifo_write(af, (void **)offset_data, nb_samples);
yading@11 355 }
yading@11 356
yading@11 357 int ff_audio_data_read_from_fifo(AVAudioFifo *af, AudioData *a, int nb_samples)
yading@11 358 {
yading@11 359 int ret;
yading@11 360
yading@11 361 if (a->read_only)
yading@11 362 return AVERROR(EINVAL);
yading@11 363
yading@11 364 ret = ff_audio_data_realloc(a, nb_samples);
yading@11 365 if (ret < 0)
yading@11 366 return ret;
yading@11 367
yading@11 368 ret = av_audio_fifo_read(af, (void **)a->data, nb_samples);
yading@11 369 if (ret >= 0)
yading@11 370 a->nb_samples = ret;
yading@11 371 return ret;
yading@11 372 }