audio_data.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
3  *
4  * This file is part of Libav.
5  *
6  * Libav is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * Libav is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with Libav; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 #include <stdint.h>
22 #include <string.h>
23 
24 #include "libavutil/mem.h"
25 #include "audio_data.h"
26 
27 static const AVClass audio_data_class = {
28  .class_name = "AudioData",
29  .item_name = av_default_item_name,
30  .version = LIBAVUTIL_VERSION_INT,
31 };
32 
33 /*
34  * Calculate alignment for data pointers.
35  */
37 {
38  int p;
39  int min_align = 128;
40 
41  for (p = 0; p < a->planes; p++) {
42  int cur_align = 128;
43  while ((intptr_t)a->data[p] % cur_align)
44  cur_align >>= 1;
45  if (cur_align < min_align)
46  min_align = cur_align;
47  }
48  a->ptr_align = min_align;
49 }
50 
52 {
53  if (channels < 1 || channels > AVRESAMPLE_MAX_CHANNELS ||
54  channels > a->allocated_channels)
55  return AVERROR(EINVAL);
56 
57  a->channels = channels;
58  a->planes = a->is_planar ? channels : 1;
59 
61 
62  return 0;
63 }
64 
65 int ff_audio_data_init(AudioData *a, uint8_t **src, int plane_size, int channels,
67  int read_only, const char *name)
68 {
69  int p;
70 
71  memset(a, 0, sizeof(*a));
72  a->class = &audio_data_class;
73 
74  if (channels < 1 || channels > AVRESAMPLE_MAX_CHANNELS) {
75  av_log(a, AV_LOG_ERROR, "invalid channel count: %d\n", channels);
76  return AVERROR(EINVAL);
77  }
78 
79  a->sample_size = av_get_bytes_per_sample(sample_fmt);
80  if (!a->sample_size) {
81  av_log(a, AV_LOG_ERROR, "invalid sample format\n");
82  return AVERROR(EINVAL);
83  }
84  a->is_planar = av_sample_fmt_is_planar(sample_fmt);
85  a->planes = a->is_planar ? channels : 1;
86  a->stride = a->sample_size * (a->is_planar ? 1 : channels);
87 
88  for (p = 0; p < (a->is_planar ? channels : 1); p++) {
89  if (!src[p]) {
90  av_log(a, AV_LOG_ERROR, "invalid NULL pointer for src[%d]\n", p);
91  return AVERROR(EINVAL);
92  }
93  a->data[p] = src[p];
94  }
95  a->allocated_samples = nb_samples * !read_only;
98  a->channels = channels;
100  a->read_only = read_only;
101  a->allow_realloc = 0;
102  a->name = name ? name : "{no name}";
103 
105  a->samples_align = plane_size / a->stride;
106 
107  return 0;
108 }
109 
111  enum AVSampleFormat sample_fmt, const char *name)
112 {
113  AudioData *a;
114  int ret;
115 
116  if (channels < 1 || channels > AVRESAMPLE_MAX_CHANNELS)
117  return NULL;
118 
119  a = av_mallocz(sizeof(*a));
120  if (!a)
121  return NULL;
122 
123  a->sample_size = av_get_bytes_per_sample(sample_fmt);
124  if (!a->sample_size) {
125  av_free(a);
126  return NULL;
127  }
128  a->is_planar = av_sample_fmt_is_planar(sample_fmt);
129  a->planes = a->is_planar ? channels : 1;
130  a->stride = a->sample_size * (a->is_planar ? 1 : channels);
131 
132  a->class = &audio_data_class;
133  a->sample_fmt = sample_fmt;
134  a->channels = channels;
136  a->read_only = 0;
137  a->allow_realloc = 1;
138  a->name = name ? name : "{no name}";
139 
140  if (nb_samples > 0) {
141  ret = ff_audio_data_realloc(a, nb_samples);
142  if (ret < 0) {
143  av_free(a);
144  return NULL;
145  }
146  return a;
147  } else {
149  return a;
150  }
151 }
152 
154 {
155  int ret, new_buf_size, plane_size, p;
156 
157  /* check if buffer is already large enough */
158  if (a->allocated_samples >= nb_samples)
159  return 0;
160 
161  /* validate that the output is not read-only and realloc is allowed */
162  if (a->read_only || !a->allow_realloc)
163  return AVERROR(EINVAL);
164 
165  new_buf_size = av_samples_get_buffer_size(&plane_size,
166  a->allocated_channels, nb_samples,
167  a->sample_fmt, 0);
168  if (new_buf_size < 0)
169  return new_buf_size;
170 
171  /* if there is already data in the buffer and the sample format is planar,
172  allocate a new buffer and copy the data, otherwise just realloc the
173  internal buffer and set new data pointers */
174  if (a->nb_samples > 0 && a->is_planar) {
175  uint8_t *new_data[AVRESAMPLE_MAX_CHANNELS] = { NULL };
176 
177  ret = av_samples_alloc(new_data, &plane_size, a->allocated_channels,
178  nb_samples, a->sample_fmt, 0);
179  if (ret < 0)
180  return ret;
181 
182  for (p = 0; p < a->planes; p++)
183  memcpy(new_data[p], a->data[p], a->nb_samples * a->stride);
184 
185  av_freep(&a->buffer);
186  memcpy(a->data, new_data, sizeof(new_data));
187  a->buffer = a->data[0];
188  } else {
189  av_freep(&a->buffer);
190  a->buffer = av_malloc(new_buf_size);
191  if (!a->buffer)
192  return AVERROR(ENOMEM);
193  ret = av_samples_fill_arrays(a->data, &plane_size, a->buffer,
194  a->allocated_channels, nb_samples,
195  a->sample_fmt, 0);
196  if (ret < 0)
197  return ret;
198  }
199  a->buffer_size = new_buf_size;
201 
203  a->samples_align = plane_size / a->stride;
204 
205  return 0;
206 }
207 
209 {
210  if (!*a)
211  return;
212  av_free((*a)->buffer);
213  av_freep(a);
214 }
215 
217 {
218  int ret, p;
219 
220  /* validate input/output compatibility */
221  if (dst->sample_fmt != src->sample_fmt || dst->channels < src->channels)
222  return AVERROR(EINVAL);
223 
224  /* if the input is empty, just empty the output */
225  if (!src->nb_samples) {
226  dst->nb_samples = 0;
227  return 0;
228  }
229 
230  /* reallocate output if necessary */
231  ret = ff_audio_data_realloc(dst, src->nb_samples);
232  if (ret < 0)
233  return ret;
234 
235  /* copy data */
236  for (p = 0; p < src->planes; p++)
237  memcpy(dst->data[p], src->data[p], src->nb_samples * src->stride);
238  dst->nb_samples = src->nb_samples;
239 
240  return 0;
241 }
242 
243 int ff_audio_data_combine(AudioData *dst, int dst_offset, AudioData *src,
244  int src_offset, int nb_samples)
245 {
246  int ret, p, dst_offset2, dst_move_size;
247 
248  /* validate input/output compatibility */
249  if (dst->sample_fmt != src->sample_fmt || dst->channels != src->channels) {
250  av_log(src, AV_LOG_ERROR, "sample format mismatch\n");
251  return AVERROR(EINVAL);
252  }
253 
254  /* validate offsets are within the buffer bounds */
255  if (dst_offset < 0 || dst_offset > dst->nb_samples ||
256  src_offset < 0 || src_offset > src->nb_samples) {
257  av_log(src, AV_LOG_ERROR, "offset out-of-bounds: src=%d dst=%d\n",
258  src_offset, dst_offset);
259  return AVERROR(EINVAL);
260  }
261 
262  /* check offsets and sizes to see if we can just do nothing and return */
263  if (nb_samples > src->nb_samples - src_offset)
264  nb_samples = src->nb_samples - src_offset;
265  if (nb_samples <= 0)
266  return 0;
267 
268  /* validate that the output is not read-only */
269  if (dst->read_only) {
270  av_log(dst, AV_LOG_ERROR, "dst is read-only\n");
271  return AVERROR(EINVAL);
272  }
273 
274  /* reallocate output if necessary */
275  ret = ff_audio_data_realloc(dst, dst->nb_samples + nb_samples);
276  if (ret < 0) {
277  av_log(dst, AV_LOG_ERROR, "error reallocating dst\n");
278  return ret;
279  }
280 
281  dst_offset2 = dst_offset + nb_samples;
282  dst_move_size = dst->nb_samples - dst_offset;
283 
284  for (p = 0; p < src->planes; p++) {
285  if (dst_move_size > 0) {
286  memmove(dst->data[p] + dst_offset2 * dst->stride,
287  dst->data[p] + dst_offset * dst->stride,
288  dst_move_size * dst->stride);
289  }
290  memcpy(dst->data[p] + dst_offset * dst->stride,
291  src->data[p] + src_offset * src->stride,
292  nb_samples * src->stride);
293  }
294  dst->nb_samples += nb_samples;
295 
296  return 0;
297 }
298 
300 {
301  if (a->nb_samples <= nb_samples) {
302  /* drain the whole buffer */
303  a->nb_samples = 0;
304  } else {
305  int p;
306  int move_offset = a->stride * nb_samples;
307  int move_size = a->stride * (a->nb_samples - nb_samples);
308 
309  for (p = 0; p < a->planes; p++)
310  memmove(a->data[p], a->data[p] + move_offset, move_size);
311 
312  a->nb_samples -= nb_samples;
313  }
314 }
315 
317  int nb_samples)
318 {
319  uint8_t *offset_data[AVRESAMPLE_MAX_CHANNELS];
320  int offset_size, p;
321 
322  if (offset >= a->nb_samples)
323  return 0;
324  offset_size = offset * a->stride;
325  for (p = 0; p < a->planes; p++)
326  offset_data[p] = a->data[p] + offset_size;
327 
328  return av_audio_fifo_write(af, (void **)offset_data, nb_samples);
329 }
330 
332 {
333  int ret;
334 
335  if (a->read_only)
336  return AVERROR(EINVAL);
337 
338  ret = ff_audio_data_realloc(a, nb_samples);
339  if (ret < 0)
340  return ret;
341 
342  ret = av_audio_fifo_read(af, (void **)a->data, nb_samples);
343  if (ret >= 0)
344  a->nb_samples = ret;
345  return ret;
346 }
unsigned int buffer_size
allocated buffer size
Definition: audio_data.h:38
int av_audio_fifo_write(AVAudioFifo *af, void **data, int nb_samples)
Write data to an AVAudioFifo.
Definition: audio_fifo.c:113
void * av_malloc(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
Definition: mem.c:61
static void calc_ptr_alignment(AudioData *a)
Definition: audio_data.c:36
const char * name
name for debug logging
Definition: audio_data.h:52
int ff_audio_data_realloc(AudioData *a, int nb_samples)
Reallocate AudioData.
Definition: audio_data.c:153
int av_samples_get_buffer_size(int *linesize, int nb_channels, int nb_samples, enum AVSampleFormat sample_fmt, int align)
Get the required buffer size for the given audio parameters.
Definition: samplefmt.c:108
Audio buffer used for intermediate storage between conversion phases.
Definition: oss_audio.c:46
memory handling functions
int ff_audio_data_add_to_fifo(AVAudioFifo *af, AudioData *a, int offset, int nb_samples)
Add samples in AudioData to an AVAudioFifo.
Definition: audio_data.c:316
AudioData * ff_audio_data_alloc(int channels, int nb_samples, enum AVSampleFormat sample_fmt, const char *name)
Allocate AudioData.
Definition: audio_data.c:110
int allow_realloc
realloc is allowed
Definition: audio_data.h:49
int nb_samples
current number of samples
Definition: audio_data.h:40
static const AVClass audio_data_class
Definition: audio_data.c:27
void av_freep(void *arg)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc() and set the pointer ...
Definition: mem.c:151
int av_audio_fifo_read(AVAudioFifo *af, void **data, int nb_samples)
Read data from an AVAudioFifo.
Definition: audio_fifo.c:139
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
Definition: log.h:38
int av_samples_fill_arrays(uint8_t **audio_data, int *linesize, const uint8_t *buf, 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.
Definition: samplefmt.c:140
int sample_size
bytes per sample
Definition: audio_data.h:46
int allocated_channels
allocated channel count
Definition: audio_data.h:43
uint8_t
const char * name
int read_only
data is read-only
Definition: audio_data.h:48
int ff_audio_data_set_channels(AudioData *a, int channels)
Definition: audio_data.c:51
void av_free(void *ptr)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc(). ...
Definition: mem.c:139
int stride
sample byte offset within a plane
Definition: audio_data.h:47
int channels
channel count
Definition: oss_audio.c:50
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:146
int ff_audio_data_read_from_fifo(AVAudioFifo *af, AudioData *a, int nb_samples)
Read samples from an AVAudioFifo to AudioData.
Definition: audio_data.c:331
int is_planar
sample format is planar
Definition: audio_data.h:44
int ff_audio_data_copy(AudioData *dst, AudioData *src)
Copy data from one AudioData to another.
Definition: audio_data.c:216
int ff_audio_data_combine(AudioData *dst, int dst_offset, AudioData *src, int src_offset, int nb_samples)
Append data from one AudioData to the end of another.
Definition: audio_data.c:243
void ff_audio_data_drain(AudioData *a, int nb_samples)
Drain samples from the start of the AudioData.
Definition: audio_data.c:299
int ff_audio_data_init(AudioData *a, uint8_t **src, int plane_size, int channels, int nb_samples, enum AVSampleFormat sample_fmt, int read_only, const char *name)
Initialize AudioData using a given source.
Definition: audio_data.c:65
LIBAVUTIL_VERSION_INT
Definition: eval.c:52
int av_get_bytes_per_sample(enum AVSampleFormat sample_fmt)
Return number of bytes per sample.
Definition: samplefmt.c:95
NULL
Definition: eval.c:52
sample_fmt
Definition: avconv_filter.c:63
uint8_t buffer[AUDIO_BLOCK_SIZE]
Definition: oss_audio.c:54
int av_samples_alloc(uint8_t **audio_data, int *linesize, 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...
Definition: samplefmt.c:162
av_default_item_name
Definition: dnxhdenc.c:43
#define AVRESAMPLE_MAX_CHANNELS
Definition: avresample.h:103
out nb_samples
Describe the class of an AVClass context structure.
Definition: log.h:33
int av_sample_fmt_is_planar(enum AVSampleFormat sample_fmt)
Check if the sample format is planar.
Definition: samplefmt.c:101
AVClass * class
Definition: oss_audio.c:47
int samples_align
allocated samples alignment
Definition: audio_data.h:51
AVSampleFormat
Audio Sample Formats.
Definition: samplefmt.h:49
int allocated_samples
number of samples the buffer can hold
Definition: audio_data.h:39
enum AVSampleFormat sample_fmt
sample format
Definition: audio_data.h:41
void ff_audio_data_free(AudioData **a)
Free AudioData.
Definition: audio_data.c:208
int ptr_align
minimum data pointer alignment
Definition: audio_data.h:50
int planes
number of data planes
Definition: audio_data.h:45
void * av_mallocz(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
Definition: mem.c:158
uint8_t * data[AVRESAMPLE_MAX_CHANNELS]
data plane pointers
Definition: audio_data.h:36