FFmpeg
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 FFmpeg.
5  *
6  * FFmpeg 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  * FFmpeg 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 FFmpeg; 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)
54  return 1;
55  else
56  return av_sample_fmt_is_planar(sample_fmt);
57 }
58 
60 {
62  channels > a->allocated_channels)
63  return AVERROR(EINVAL);
64 
65  a->channels = channels;
66  a->planes = a->is_planar ? channels : 1;
67 
69 
70  return 0;
71 }
72 
73 int ff_audio_data_init(AudioData *a, uint8_t * const *src, int plane_size,
74  int channels, int nb_samples,
75  enum AVSampleFormat sample_fmt, int read_only,
76  const char *name)
77 {
78  int p;
79 
80  memset(a, 0, sizeof(*a));
81  a->class = &audio_data_class;
82 
84  av_log(a, AV_LOG_ERROR, "invalid channel count: %d\n", channels);
85  return AVERROR(EINVAL);
86  }
87 
88  a->sample_size = av_get_bytes_per_sample(sample_fmt);
89  if (!a->sample_size) {
90  av_log(a, AV_LOG_ERROR, "invalid sample format\n");
91  return AVERROR(EINVAL);
92  }
93  a->is_planar = ff_sample_fmt_is_planar(sample_fmt, channels);
94  a->planes = a->is_planar ? channels : 1;
95  a->stride = a->sample_size * (a->is_planar ? 1 : channels);
96 
97  for (p = 0; p < (a->is_planar ? channels : 1); p++) {
98  if (!src[p]) {
99  av_log(a, AV_LOG_ERROR, "invalid NULL pointer for src[%d]\n", p);
100  return AVERROR(EINVAL);
101  }
102  a->data[p] = src[p];
103  }
104  a->allocated_samples = nb_samples * !read_only;
105  a->nb_samples = nb_samples;
106  a->sample_fmt = sample_fmt;
107  a->channels = channels;
108  a->allocated_channels = channels;
109  a->read_only = read_only;
110  a->allow_realloc = 0;
111  a->name = name ? name : "{no name}";
112 
114  a->samples_align = plane_size / a->stride;
115 
116  return 0;
117 }
118 
120  enum AVSampleFormat sample_fmt, const char *name)
121 {
122  AudioData *a;
123  int ret;
124 
126  return NULL;
127 
128  a = av_mallocz(sizeof(*a));
129  if (!a)
130  return NULL;
131 
132  a->sample_size = av_get_bytes_per_sample(sample_fmt);
133  if (!a->sample_size) {
134  av_free(a);
135  return NULL;
136  }
137  a->is_planar = ff_sample_fmt_is_planar(sample_fmt, channels);
138  a->planes = a->is_planar ? channels : 1;
139  a->stride = a->sample_size * (a->is_planar ? 1 : channels);
140 
141  a->class = &audio_data_class;
142  a->sample_fmt = sample_fmt;
143  a->channels = channels;
144  a->allocated_channels = channels;
145  a->read_only = 0;
146  a->allow_realloc = 1;
147  a->name = name ? name : "{no name}";
148 
149  if (nb_samples > 0) {
150  ret = ff_audio_data_realloc(a, nb_samples);
151  if (ret < 0) {
152  av_free(a);
153  return NULL;
154  }
155  return a;
156  } else {
158  return a;
159  }
160 }
161 
162 int ff_audio_data_realloc(AudioData *a, int nb_samples)
163 {
164  int ret, new_buf_size, plane_size, p;
165 
166  /* check if buffer is already large enough */
167  if (a->allocated_samples >= nb_samples)
168  return 0;
169 
170  /* validate that the output is not read-only and realloc is allowed */
171  if (a->read_only || !a->allow_realloc)
172  return AVERROR(EINVAL);
173 
174  new_buf_size = av_samples_get_buffer_size(&plane_size,
175  a->allocated_channels, nb_samples,
176  a->sample_fmt, 0);
177  if (new_buf_size < 0)
178  return new_buf_size;
179 
180  /* if there is already data in the buffer and the sample format is planar,
181  allocate a new buffer and copy the data, otherwise just realloc the
182  internal buffer and set new data pointers */
183  if (a->nb_samples > 0 && a->is_planar) {
184  uint8_t *new_data[AVRESAMPLE_MAX_CHANNELS] = { NULL };
185 
186  ret = av_samples_alloc(new_data, &plane_size, a->allocated_channels,
187  nb_samples, a->sample_fmt, 0);
188  if (ret < 0)
189  return ret;
190 
191  for (p = 0; p < a->planes; p++)
192  memcpy(new_data[p], a->data[p], a->nb_samples * a->stride);
193 
194  av_freep(&a->buffer);
195  memcpy(a->data, new_data, sizeof(new_data));
196  a->buffer = a->data[0];
197  } else {
198  av_freep(&a->buffer);
199  a->buffer = av_malloc(new_buf_size);
200  if (!a->buffer)
201  return AVERROR(ENOMEM);
202  ret = av_samples_fill_arrays(a->data, &plane_size, a->buffer,
203  a->allocated_channels, nb_samples,
204  a->sample_fmt, 0);
205  if (ret < 0)
206  return ret;
207  }
208  a->buffer_size = new_buf_size;
209  a->allocated_samples = nb_samples;
210 
212  a->samples_align = plane_size / a->stride;
213 
214  return 0;
215 }
216 
218 {
219  if (!*a)
220  return;
221  av_free((*a)->buffer);
222  av_freep(a);
223 }
224 
226 {
227  int ret, p;
228 
229  /* validate input/output compatibility */
230  if (dst->sample_fmt != src->sample_fmt || dst->channels < src->channels)
231  return AVERROR(EINVAL);
232 
233  if (map && !src->is_planar) {
234  av_log(src, AV_LOG_ERROR, "cannot remap packed format during copy\n");
235  return AVERROR(EINVAL);
236  }
237 
238  /* if the input is empty, just empty the output */
239  if (!src->nb_samples) {
240  dst->nb_samples = 0;
241  return 0;
242  }
243 
244  /* reallocate output if necessary */
245  ret = ff_audio_data_realloc(dst, src->nb_samples);
246  if (ret < 0)
247  return ret;
248 
249  /* copy data */
250  if (map) {
251  if (map->do_remap) {
252  for (p = 0; p < src->planes; p++) {
253  if (map->channel_map[p] >= 0)
254  memcpy(dst->data[p], src->data[map->channel_map[p]],
255  src->nb_samples * src->stride);
256  }
257  }
258  if (map->do_copy || map->do_zero) {
259  for (p = 0; p < src->planes; p++) {
260  if (map->channel_copy[p])
261  memcpy(dst->data[p], dst->data[map->channel_copy[p]],
262  src->nb_samples * src->stride);
263  else if (map->channel_zero[p])
264  av_samples_set_silence(&dst->data[p], 0, src->nb_samples,
265  1, dst->sample_fmt);
266  }
267  }
268  } else {
269  for (p = 0; p < src->planes; p++)
270  memcpy(dst->data[p], src->data[p], src->nb_samples * src->stride);
271  }
272 
273  dst->nb_samples = src->nb_samples;
274 
275  return 0;
276 }
277 
278 int ff_audio_data_combine(AudioData *dst, int dst_offset, AudioData *src,
279  int src_offset, int nb_samples)
280 {
281  int ret, p, dst_offset2, dst_move_size;
282 
283  /* validate input/output compatibility */
284  if (dst->sample_fmt != src->sample_fmt || dst->channels != src->channels) {
285  av_log(src, AV_LOG_ERROR, "sample format mismatch\n");
286  return AVERROR(EINVAL);
287  }
288 
289  /* validate offsets are within the buffer bounds */
290  if (dst_offset < 0 || dst_offset > dst->nb_samples ||
291  src_offset < 0 || src_offset > src->nb_samples) {
292  av_log(src, AV_LOG_ERROR, "offset out-of-bounds: src=%d dst=%d\n",
293  src_offset, dst_offset);
294  return AVERROR(EINVAL);
295  }
296 
297  /* check offsets and sizes to see if we can just do nothing and return */
298  if (nb_samples > src->nb_samples - src_offset)
299  nb_samples = src->nb_samples - src_offset;
300  if (nb_samples <= 0)
301  return 0;
302 
303  /* validate that the output is not read-only */
304  if (dst->read_only) {
305  av_log(dst, AV_LOG_ERROR, "dst is read-only\n");
306  return AVERROR(EINVAL);
307  }
308 
309  /* reallocate output if necessary */
310  ret = ff_audio_data_realloc(dst, dst->nb_samples + nb_samples);
311  if (ret < 0) {
312  av_log(dst, AV_LOG_ERROR, "error reallocating dst\n");
313  return ret;
314  }
315 
316  dst_offset2 = dst_offset + nb_samples;
317  dst_move_size = dst->nb_samples - dst_offset;
318 
319  for (p = 0; p < src->planes; p++) {
320  if (dst_move_size > 0) {
321  memmove(dst->data[p] + dst_offset2 * dst->stride,
322  dst->data[p] + dst_offset * dst->stride,
323  dst_move_size * dst->stride);
324  }
325  memcpy(dst->data[p] + dst_offset * dst->stride,
326  src->data[p] + src_offset * src->stride,
327  nb_samples * src->stride);
328  }
329  dst->nb_samples += nb_samples;
330 
331  return 0;
332 }
333 
334 void ff_audio_data_drain(AudioData *a, int nb_samples)
335 {
336  if (a->nb_samples <= nb_samples) {
337  /* drain the whole buffer */
338  a->nb_samples = 0;
339  } else {
340  int p;
341  int move_offset = a->stride * nb_samples;
342  int move_size = a->stride * (a->nb_samples - nb_samples);
343 
344  for (p = 0; p < a->planes; p++)
345  memmove(a->data[p], a->data[p] + move_offset, move_size);
346 
347  a->nb_samples -= nb_samples;
348  }
349 }
350 
352  int nb_samples)
353 {
354  uint8_t *offset_data[AVRESAMPLE_MAX_CHANNELS];
355  int offset_size, p;
356 
357  if (offset >= a->nb_samples)
358  return 0;
359  offset_size = offset * a->stride;
360  for (p = 0; p < a->planes; p++)
361  offset_data[p] = a->data[p] + offset_size;
362 
363  return av_audio_fifo_write(af, (void **)offset_data, nb_samples);
364 }
365 
367 {
368  int ret;
369 
370  if (a->read_only)
371  return AVERROR(EINVAL);
372 
373  ret = ff_audio_data_realloc(a, nb_samples);
374  if (ret < 0)
375  return ret;
376 
377  ret = av_audio_fifo_read(af, (void **)a->data, nb_samples);
378  if (ret >= 0)
379  a->nb_samples = ret;
380  return ret;
381 }
name
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf default minimum maximum flags name is the option name
Definition: writing_filters.txt:88
ff_sample_fmt_is_planar
int ff_sample_fmt_is_planar(enum AVSampleFormat sample_fmt, int channels)
Definition: audio_data.c:51
calc_ptr_alignment
static void calc_ptr_alignment(AudioData *a)
Definition: audio_data.c:36
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame 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. Frame references ownership and permissions
ff_audio_data_alloc
AudioData * ff_audio_data_alloc(int channels, int nb_samples, enum AVSampleFormat sample_fmt, const char *name)
Allocate AudioData.
Definition: audio_data.c:119
av_samples_fill_arrays
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:151
ff_audio_data_set_channels
int ff_audio_data_set_channels(AudioData *a, int channels)
Definition: audio_data.c:59
AVRESAMPLE_MAX_CHANNELS
#define AVRESAMPLE_MAX_CHANNELS
Definition: avresample.h:104
ff_audio_data_add_to_fifo
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:351
AudioData::data
uint8_t * data[AVRESAMPLE_MAX_CHANNELS]
data plane pointers
Definition: audio_data.h:39
ff_audio_data_free
void ff_audio_data_free(AudioData **a)
Free AudioData.
Definition: audio_data.c:217
ff_audio_data_read_from_fifo
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:366
av_malloc
#define av_malloc(s)
Definition: tableprint_vlc.h:31
audio_data_class
static const AVClass audio_data_class
Definition: audio_data.c:27
AudioData
Audio buffer used for intermediate storage between conversion phases.
Definition: audio_data.h:37
AVAudioFifo
Context for an Audio FIFO Buffer.
Definition: audio_fifo.c:34
ChannelMapInfo
Definition: internal.h:43
av_samples_alloc
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:173
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:194
av_audio_fifo_write
int av_audio_fifo_write(AVAudioFifo *af, void **data, int nb_samples)
Write data to an AVAudioFifo.
Definition: audio_fifo.c:112
av_sample_fmt_is_planar
int av_sample_fmt_is_planar(enum AVSampleFormat sample_fmt)
Check if the sample format is planar.
Definition: samplefmt.c:112
channels
channels
Definition: aptx.h:33
LIBAVUTIL_VERSION_INT
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:67
NULL
#define NULL
Definition: coverity.c:32
AudioData::sample_fmt
enum AVSampleFormat sample_fmt
sample format
Definition: audio_data.h:44
av_default_item_name
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:235
src
#define src
Definition: vp8dsp.c:255
audio_data.h
a
The reader does not expect b to be semantically here and if the code is changed by maybe adding a a division or other the signedness will almost certainly be mistaken To avoid this confusion a new type was SUINT is the C unsigned type but it holds a signed int to use the same example SUINT a
Definition: undefined.txt:41
offset
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf offset
Definition: writing_filters.txt:86
av_audio_fifo_read
int av_audio_fifo_read(AVAudioFifo *af, void **data, int nb_samples)
Read data from an AVAudioFifo.
Definition: audio_fifo.c:181
av_get_bytes_per_sample
int av_get_bytes_per_sample(enum AVSampleFormat sample_fmt)
Return number of bytes per sample.
Definition: samplefmt.c:106
AVSampleFormat
AVSampleFormat
Audio sample formats.
Definition: samplefmt.h:58
uint8_t
uint8_t
Definition: audio_convert.c:194
av_mallocz
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:237
av_samples_get_buffer_size
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:119
AudioData::read_only
int read_only
data is read-only
Definition: audio_data.h:51
av_samples_set_silence
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:237
AudioData::nb_samples
int nb_samples
current number of samples
Definition: audio_data.h:43
ret
ret
Definition: filter_design.txt:187
AVClass::class_name
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:72
ff_audio_data_realloc
int ff_audio_data_realloc(AudioData *a, int nb_samples)
Reallocate AudioData.
Definition: audio_data.c:162
ff_audio_data_combine
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:278
mem.h
map
const VDPAUPixFmtMap * map
Definition: hwcontext_vdpau.c:71
av_free
#define av_free(p)
Definition: tableprint_vlc.h:34
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:28
AudioData::channels
int channels
channel count
Definition: audio_data.h:45
AudioData::stride
int stride
sample byte offset within a plane
Definition: audio_data.h:50
ff_audio_data_init
int ff_audio_data_init(AudioData *a, uint8_t *const *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:73
ff_audio_data_copy
int ff_audio_data_copy(AudioData *dst, AudioData *src, ChannelMapInfo *map)
Copy data from one AudioData to another.
Definition: audio_data.c:225
ff_audio_data_drain
void ff_audio_data_drain(AudioData *a, int nb_samples)
Drain samples from the start of the AudioData.
Definition: audio_data.c:334