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,
66  int nb_samples, enum AVSampleFormat sample_fmt,
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;
96  a->nb_samples = nb_samples;
97  a->sample_fmt = sample_fmt;
98  a->channels = channels;
99  a->allocated_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 
110 AudioData *ff_audio_data_alloc(int channels, int nb_samples,
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;
135  a->allocated_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 
153 int ff_audio_data_realloc(AudioData *a, int nb_samples)
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;
200  a->allocated_samples = nb_samples;
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 (map && !src->is_planar) {
225  av_log(src, AV_LOG_ERROR, "cannot remap packed format during copy\n");
226  return AVERROR(EINVAL);
227  }
228 
229  /* if the input is empty, just empty the output */
230  if (!src->nb_samples) {
231  dst->nb_samples = 0;
232  return 0;
233  }
234 
235  /* reallocate output if necessary */
236  ret = ff_audio_data_realloc(dst, src->nb_samples);
237  if (ret < 0)
238  return ret;
239 
240  /* copy data */
241  if (map) {
242  if (map->do_remap) {
243  for (p = 0; p < src->planes; p++) {
244  if (map->channel_map[p] >= 0)
245  memcpy(dst->data[p], src->data[map->channel_map[p]],
246  src->nb_samples * src->stride);
247  }
248  }
249  if (map->do_copy || map->do_zero) {
250  for (p = 0; p < src->planes; p++) {
251  if (map->channel_copy[p])
252  memcpy(dst->data[p], dst->data[map->channel_copy[p]],
253  src->nb_samples * src->stride);
254  else if (map->channel_zero[p])
255  av_samples_set_silence(&dst->data[p], 0, src->nb_samples,
256  1, dst->sample_fmt);
257  }
258  }
259  } else {
260  for (p = 0; p < src->planes; p++)
261  memcpy(dst->data[p], src->data[p], src->nb_samples * src->stride);
262  }
263 
264  dst->nb_samples = src->nb_samples;
265 
266  return 0;
267 }
268 
270  int src_offset, int nb_samples)
271 {
272  int ret, p, dst_offset2, dst_move_size;
273 
274  /* validate input/output compatibility */
275  if (dst->sample_fmt != src->sample_fmt || dst->channels != src->channels) {
276  av_log(src, AV_LOG_ERROR, "sample format mismatch\n");
277  return AVERROR(EINVAL);
278  }
279 
280  /* validate offsets are within the buffer bounds */
281  if (dst_offset < 0 || dst_offset > dst->nb_samples ||
282  src_offset < 0 || src_offset > src->nb_samples) {
283  av_log(src, AV_LOG_ERROR, "offset out-of-bounds: src=%d dst=%d\n",
284  src_offset, dst_offset);
285  return AVERROR(EINVAL);
286  }
287 
288  /* check offsets and sizes to see if we can just do nothing and return */
289  if (nb_samples > src->nb_samples - src_offset)
290  nb_samples = src->nb_samples - src_offset;
291  if (nb_samples <= 0)
292  return 0;
293 
294  /* validate that the output is not read-only */
295  if (dst->read_only) {
296  av_log(dst, AV_LOG_ERROR, "dst is read-only\n");
297  return AVERROR(EINVAL);
298  }
299 
300  /* reallocate output if necessary */
301  ret = ff_audio_data_realloc(dst, dst->nb_samples + nb_samples);
302  if (ret < 0) {
303  av_log(dst, AV_LOG_ERROR, "error reallocating dst\n");
304  return ret;
305  }
306 
307  dst_offset2 = dst_offset + nb_samples;
308  dst_move_size = dst->nb_samples - dst_offset;
309 
310  for (p = 0; p < src->planes; p++) {
311  if (dst_move_size > 0) {
312  memmove(dst->data[p] + dst_offset2 * dst->stride,
313  dst->data[p] + dst_offset * dst->stride,
314  dst_move_size * dst->stride);
315  }
316  memcpy(dst->data[p] + dst_offset * dst->stride,
317  src->data[p] + src_offset * src->stride,
318  nb_samples * src->stride);
319  }
320  dst->nb_samples += nb_samples;
321 
322  return 0;
323 }
324 
325 void ff_audio_data_drain(AudioData *a, int nb_samples)
326 {
327  if (a->nb_samples <= nb_samples) {
328  /* drain the whole buffer */
329  a->nb_samples = 0;
330  } else {
331  int p;
332  int move_offset = a->stride * nb_samples;
333  int move_size = a->stride * (a->nb_samples - nb_samples);
334 
335  for (p = 0; p < a->planes; p++)
336  memmove(a->data[p], a->data[p] + move_offset, move_size);
337 
338  a->nb_samples -= nb_samples;
339  }
340 }
341 
343  int nb_samples)
344 {
345  uint8_t *offset_data[AVRESAMPLE_MAX_CHANNELS];
346  int offset_size, p;
347 
348  if (offset >= a->nb_samples)
349  return 0;
350  offset_size = offset * a->stride;
351  for (p = 0; p < a->planes; p++)
352  offset_data[p] = a->data[p] + offset_size;
353 
354  return av_audio_fifo_write(af, (void **)offset_data, nb_samples);
355 }
356 
358 {
359  int ret;
360 
361  if (a->read_only)
362  return AVERROR(EINVAL);
363 
364  ret = ff_audio_data_realloc(a, nb_samples);
365  if (ret < 0)
366  return ret;
367 
368  ret = av_audio_fifo_read(af, (void **)a->data, nb_samples);
369  if (ret >= 0)
370  a->nb_samples = ret;
371  return ret;
372 }
const char * name
Definition: avisynth_c.h:675
unsigned int buffer_size
allocated buffer size
Definition: audio_data.h:39
int av_audio_fifo_write(AVAudioFifo *af, void **data, int nb_samples)
Write data to an AVAudioFifo.
Definition: audio_fifo.c:113
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:205
static void calc_ptr_alignment(AudioData *a)
Definition: audio_data.c:36
const char * name
name for debug logging
Definition: audio_data.h:53
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:125
Audio buffer used for intermediate storage between conversion phases.
Definition: oss_audio.c:46
av_default_item_name
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:342
int do_zero
zeroing needed
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:50
int channel_zero[AVRESAMPLE_MAX_CHANNELS]
dest index to zero
int nb_samples
current number of samples
Definition: audio_data.h:41
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:198
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:55
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 plane data pointers and linesize for samples with sample format sample_fmt.
Definition: samplefmt.c:155
int sample_size
bytes per sample
Definition: audio_data.h:47
int allocated_channels
allocated channel count
Definition: audio_data.h:44
uint8_t
int read_only
data is read-only
Definition: audio_data.h:49
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:183
int stride
sample byte offset within a plane
Definition: audio_data.h:48
int channels
channel count
Definition: oss_audio.c:50
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:246
static const uint8_t offset[127][2]
Definition: vf_spp.c:70
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:357
int is_planar
sample format is planar
Definition: audio_data.h:45
int channel_copy[AVRESAMPLE_MAX_CHANNELS]
dest index to copy from
int do_remap
remap needed
int av_samples_set_silence(uint8_t **audio_data, int offset, int nb_samples, int nb_channels, enum AVSampleFormat sample_fmt)
Fill an audio buffer with silence.
Definition: samplefmt.c:249
ret
Definition: avfilter.c:821
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:269
void ff_audio_data_drain(AudioData *a, int nb_samples)
Drain samples from the start of the AudioData.
Definition: audio_data.c:325
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:55
int av_get_bytes_per_sample(enum AVSampleFormat sample_fmt)
Return number of bytes per sample.
Definition: samplefmt.c:104
NULL
Definition: eval.c:55
uint8_t buffer[AUDIO_BLOCK_SIZE]
Definition: oss_audio.c:54
AVS_Value src
Definition: avisynth_c.h:523
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:181
uint8_t * data[AVRESAMPLE_MAX_CHANNELS]
data plane pointers
Definition: audio_data.h:37
#define AVRESAMPLE_MAX_CHANNELS
Definition: avresample.h:103
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:148
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:73
Describe the class of an AVClass context structure.
Definition: log.h:50
int av_sample_fmt_is_planar(enum AVSampleFormat sample_fmt)
Check if the sample format is planar.
Definition: samplefmt.c:118
AVClass * class
Definition: oss_audio.c:47
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFilterBuffer structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Buffer references ownership and permissions
int channel_map[AVRESAMPLE_MAX_CHANNELS]
source index of each output channel, -1 if not remapped
int samples_align
allocated samples alignment
Definition: audio_data.h:52
int ff_audio_data_copy(AudioData *dst, AudioData *src, ChannelMapInfo *map)
Copy data from one AudioData to another.
Definition: audio_data.c:216
int do_copy
copy needed
AVSampleFormat
Audio Sample Formats.
Definition: samplefmt.h:49
else dst[i][x+y *dst_stride[i]]
Definition: vf_mcdeint.c:160
int allocated_samples
number of samples the buffer can hold
Definition: audio_data.h:40
enum AVSampleFormat sample_fmt
sample format
Definition: audio_data.h:42
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:51
int planes
number of data planes
Definition: audio_data.h:46