FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
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 
51 int ff_sample_fmt_is_planar(enum AVSampleFormat sample_fmt, int channels)
52 {
53  if (channels == 1)
54  return 1;
55  else
56  return av_sample_fmt_is_planar(sample_fmt);
57 }
58 
60 {
61  if (channels < 1 || channels > AVRESAMPLE_MAX_CHANNELS ||
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 
83  if (channels < 1 || channels > AVRESAMPLE_MAX_CHANNELS) {
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 
119 AudioData *ff_audio_data_alloc(int channels, int nb_samples,
120  enum AVSampleFormat sample_fmt, const char *name)
121 {
122  AudioData *a;
123  int ret;
124 
125  if (channels < 1 || channels > AVRESAMPLE_MAX_CHANNELS)
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 }
unsigned int buffer_size
allocated buffer size
Definition: audio_data.h:41
#define NULL
Definition: coverity.c:32
static void calc_ptr_alignment(AudioData *a)
Definition: audio_data.c:36
const char * name
name for debug logging
Definition: audio_data.h:55
int av_audio_fifo_read(AVAudioFifo *af, void **data, int nb_samples)
Read data from an AVAudioFifo.
Definition: audio_fifo.c:181
int ff_audio_data_realloc(AudioData *a, int nb_samples)
Reallocate AudioData.
Definition: audio_data.c:162
Audio buffer used for intermediate storage between conversion phases.
Definition: audio_data.h:37
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
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:351
int do_zero
zeroing needed
Definition: internal.h:49
AudioData * ff_audio_data_alloc(int channels, int nb_samples, enum AVSampleFormat sample_fmt, const char *name)
Allocate AudioData.
Definition: audio_data.c:119
int allow_realloc
realloc is allowed
Definition: audio_data.h:52
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:252
int channel_zero[AVRESAMPLE_MAX_CHANNELS]
dest index to zero
Definition: internal.h:48
int nb_samples
current number of samples
Definition: audio_data.h:43
static const AVClass audio_data_class
Definition: audio_data.c:27
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
int sample_size
bytes per sample
Definition: audio_data.h:49
int allocated_channels
allocated channel count
Definition: audio_data.h:46
uint8_t
#define av_malloc(s)
int read_only
data is read-only
Definition: audio_data.h:51
int ff_sample_fmt_is_planar(enum AVSampleFormat sample_fmt, int channels)
Definition: audio_data.c:51
#define av_log(a,...)
int av_sample_fmt_is_planar(enum AVSampleFormat sample_fmt)
Check if the sample format is planar.
Definition: samplefmt.c:112
int ff_audio_data_set_channels(AudioData *a, int channels)
Definition: audio_data.c:59
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
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
int stride
sample byte offset within a plane
Definition: audio_data.h:50
av_default_item_name
#define AVERROR(e)
Definition: error.h:43
int channels
channel count
Definition: audio_data.h:45
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
static const uint8_t offset[127][2]
Definition: vf_spp.c:92
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
int is_planar
sample format is planar
Definition: audio_data.h:47
uint8_t * buffer
data buffer
Definition: audio_data.h:40
Context for an Audio FIFO Buffer.
Definition: audio_fifo.c:34
const AVClass * class
AVClass for logging.
Definition: audio_data.h:38
int channel_copy[AVRESAMPLE_MAX_CHANNELS]
dest index to copy from
Definition: internal.h:46
int do_remap
remap needed
Definition: internal.h:45
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
void ff_audio_data_drain(AudioData *a, int nb_samples)
Drain samples from the start of the AudioData.
Definition: audio_data.c:334
#define src
Definition: vp9dsp.c:530
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
AVSampleFormat
Audio sample formats.
Definition: samplefmt.h:58
uint8_t * data[AVRESAMPLE_MAX_CHANNELS]
data plane pointers
Definition: audio_data.h:39
#define AVRESAMPLE_MAX_CHANNELS
Definition: avresample.h:104
Describe the class of an AVClass context structure.
Definition: log.h:67
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
const VDPAUPixFmtMap * map
int channel_map[AVRESAMPLE_MAX_CHANNELS]
source index of each output channel, -1 if not remapped
Definition: internal.h:44
int av_audio_fifo_write(AVAudioFifo *af, void **data, int nb_samples)
Write data to an AVAudioFifo.
Definition: audio_fifo.c:112
int av_get_bytes_per_sample(enum AVSampleFormat sample_fmt)
Return number of bytes per sample.
Definition: samplefmt.c:106
int samples_align
allocated samples alignment
Definition: audio_data.h:54
int ff_audio_data_copy(AudioData *dst, AudioData *src, ChannelMapInfo *map)
Copy data from one AudioData to another.
Definition: audio_data.c:225
int do_copy
copy needed
Definition: internal.h:47
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
#define av_free(p)
int allocated_samples
number of samples the buffer can hold
Definition: audio_data.h:42
enum AVSampleFormat sample_fmt
sample format
Definition: audio_data.h:44
#define av_freep(p)
void ff_audio_data_free(AudioData **a)
Free AudioData.
Definition: audio_data.c:217
int ptr_align
minimum data pointer alignment
Definition: audio_data.h:53
int planes
number of data planes
Definition: audio_data.h:48
const char * name
Definition: opengl_enc.c:103