History

lavfi: add asrc_abuffer - audio buffer source

Originally based on code by Stefano Sabatini and S. N. Hemanth.

Mina Nagy Zaki committed 15 years ago

Commit 587c8ab1 parent f138c7f7 files · +495 −1Browse files

Unified · Split

7 files
  1. configure +1 −0
  2. doc/filters.texi +45 −0
  3. libavfilter/Makefile +1 −0
  4. libavfilter/allfilters.c +1 −0
  5. libavfilter/asrc_abuffer.c +366 −0
  6. libavfilter/asrc_abuffer.h +80 −0
  7. libavfilter/avfilter.h +1 −1
configure+1−0
@@ -1501,6 +1501,7 @@ tcp_protocol_deps="network" · 1500 unmodified lines
1501udp_protocol_deps="network"1501udp_protocol_deps="network"
1502 1502
1503# filters1503# filters
1504abuffer="strtok_r"
1504aformat_filter_deps="strtok_r"1505aformat_filter_deps="strtok_r"
1505blackframe_filter_deps="gpl"1506blackframe_filter_deps="gpl"
1506boxblur_filter_deps="gpl"1507boxblur_filter_deps="gpl"
doc/filters.texi+45−0
@@ -194,6 +194,51 @@ Adler-32 checksum for each input frame plane, expressed in the form · 193 unmodified lines
194 194
195Below is a description of the currently available audio sources.195Below is a description of the currently available audio sources.
196 196
197@section abuffer
198
199Buffer audio frames, and make them available to the filter chain.
200
201This source is mainly intended for a programmatic use, in particular
202through the interface defined in @file{libavfilter/asrc_abuffer.h}.
203
204It accepts the following mandatory parameters:
205@var{sample_rate}:@var{sample_fmt}:@var{channel_layout}:@var{packing}
206
207@table @option
208
209@item sample_rate
210The sample rate of the incoming audio buffers.
211
212@item sample_fmt
213The sample format of the incoming audio buffers.
214Either a sample format name or its corresponging integer representation from
215the enum AVSampleFormat in @file{libavutil/samplefmt.h}
216
217@item channel_layout
218The channel layout of the incoming audio buffers.
219Either a channel layout name from channel_layout_map in
220@file{libavutil/audioconvert.c} or its corresponding integer representation
221from the AV_CH_LAYOUT_* macros in @file{libavutil/audioconvert.h}
222
223@item packing
224Either "packed" or "planar", or their integer representation: 0 or 1
225respectively.
226
227@end table
228
229For example:
230@example
231abuffer=44100:s16:stereo:planar
232@end example
233
234will instruct the source to accept planar 16bit signed stereo at 44100Hz.
235Since the sample format with name "s16" corresponds to the number
2361 and the "stereo" channel layout corresponds to the value 3, this is
237equivalent to:
238@example
239abuffer=44100:1:3:1
240@end example
241
197@section anullsrc242@section anullsrc
198 243
199Null audio source, never return audio frames. It is mainly useful as a244Null audio source, never return audio frames. It is mainly useful as a
libavfilter/Makefile+1−0
@@ -24,6 +24,7 @@ OBJS-$(CONFIG_ANULL_FILTER) += af_anull.o · 23 unmodified lines
24OBJS-$(CONFIG_ARESAMPLE_FILTER) += af_aresample.o24OBJS-$(CONFIG_ARESAMPLE_FILTER) += af_aresample.o
25OBJS-$(CONFIG_ASHOWINFO_FILTER) += af_ashowinfo.o25OBJS-$(CONFIG_ASHOWINFO_FILTER) += af_ashowinfo.o
26 26
27OBJS-$(CONFIG_ABUFFER_FILTER) += asrc_abuffer.o
27OBJS-$(CONFIG_ANULLSRC_FILTER) += asrc_anullsrc.o28OBJS-$(CONFIG_ANULLSRC_FILTER) += asrc_anullsrc.o
28 29
29OBJS-$(CONFIG_ABUFFERSINK_FILTER) += asink_abuffer.o30OBJS-$(CONFIG_ABUFFERSINK_FILTER) += asink_abuffer.o
libavfilter/allfilters.c+1−0
@@ -39,6 +39,7 @@ void avfilter_register_all(void) · 38 unmodified lines
39 REGISTER_FILTER (ARESAMPLE, aresample, af);39 REGISTER_FILTER (ARESAMPLE, aresample, af);
40 REGISTER_FILTER (ASHOWINFO, ashowinfo, af);40 REGISTER_FILTER (ASHOWINFO, ashowinfo, af);
41 41
42 REGISTER_FILTER (ABUFFER, abuffer, asrc);
42 REGISTER_FILTER (ANULLSRC, anullsrc, asrc);43 REGISTER_FILTER (ANULLSRC, anullsrc, asrc);
43 44
44 REGISTER_FILTER (ABUFFERSINK, abuffersink, asink);45 REGISTER_FILTER (ABUFFERSINK, abuffersink, asink);
libavfilter/asrc_abuffer.c+366−0
@@ -0,0 +1,366 @@
1/*
2 * Copyright (c) 2010 S.N. Hemanth Meenakshisundaram
3 * Copyright (c) 2011 Mina Nagy Zaki
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22/**
23 * @file
24 * memory buffer source for audio
25 */
26
27#include "libavutil/audioconvert.h"
28#include "libavutil/fifo.h"
29#include "asrc_abuffer.h"
30#include "internal.h"
31
32typedef struct {
33 // Audio format of incoming buffers
34 int sample_rate;
35 unsigned int sample_format;
36 int64_t channel_layout;
37 int packing_format;
38
39 // FIFO buffer of audio buffer ref pointers
40 AVFifoBuffer *fifo;
41
42 // Normalization filters
43 AVFilterContext *aconvert;
44 AVFilterContext *aresample;
45} ABufferSourceContext;
46
47#define FIFO_SIZE 8
48
49static void buf_free(AVFilterBuffer *ptr)
50{
51 av_free(ptr);
52 return;
53}
54
55static void set_link_source(AVFilterContext *src, AVFilterLink *link)
56{
57 link->src = src;
58 link->srcpad = &(src->output_pads[0]);
59 src->outputs[0] = link;
60}
61
62static int reconfigure_filter(ABufferSourceContext *abuffer, AVFilterContext *filt_ctx)
63{
64 int ret;
65 AVFilterLink * const inlink = filt_ctx->inputs[0];
66 AVFilterLink * const outlink = filt_ctx->outputs[0];
67
68 inlink->format = abuffer->sample_format;
69 inlink->channel_layout = abuffer->channel_layout;
70 inlink->planar = abuffer->packing_format;
71 inlink->sample_rate = abuffer->sample_rate;
72
73 filt_ctx->filter->uninit(filt_ctx);
74 memset(filt_ctx->priv, 0, filt_ctx->filter->priv_size);
75 if ((ret = filt_ctx->filter->init(filt_ctx, NULL , NULL)) < 0)
76 return ret;
77 if ((ret = inlink->srcpad->config_props(inlink)) < 0)
78 return ret;
79 return outlink->srcpad->config_props(outlink);
80}
81
82static int insert_filter(ABufferSourceContext *abuffer,
83 AVFilterLink *link, AVFilterContext **filt_ctx,
84 const char *filt_name)
85{
86 int ret;
87
88 if ((ret = avfilter_open(filt_ctx, avfilter_get_by_name(filt_name), NULL)) < 0)
89 return ret;
90
91 link->src->outputs[0] = NULL;
92 if ((ret = avfilter_link(link->src, 0, *filt_ctx, 0)) < 0) {
93 link->src->outputs[0] = link;
94 return ret;
95 }
96
97 set_link_source(*filt_ctx, link);
98
99 if ((ret = reconfigure_filter(abuffer, *filt_ctx)) < 0) {
100 avfilter_free(*filt_ctx);
101 return ret;
102 }
103
104 return 0;
105}
106
107static void remove_filter(AVFilterContext **filt_ctx)
108{
109 AVFilterLink *outlink = (*filt_ctx)->outputs[0];
110 AVFilterContext *src = (*filt_ctx)->inputs[0]->src;
111
112 (*filt_ctx)->outputs[0] = NULL;
113 avfilter_free(*filt_ctx);
114 *filt_ctx = NULL;
115
116 set_link_source(src, outlink);
117}
118
119static inline void log_input_change(void *ctx, AVFilterLink *link, AVFilterBufferRef *ref)
120{
121 char old_layout_str[16], new_layout_str[16];
122 av_get_channel_layout_string(old_layout_str, sizeof(old_layout_str),
123 -1, link->channel_layout);
124 av_get_channel_layout_string(new_layout_str, sizeof(new_layout_str),
125 -1, ref->audio->channel_layout);
126 av_log(ctx, AV_LOG_INFO,
127 "Audio input format changed: "
128 "%s:%s:%"PRId64" -> %s:%s:%u, normalizing\n",
129 av_get_sample_fmt_name(link->format),
130 old_layout_str, link->sample_rate,
131 av_get_sample_fmt_name(ref->format),
132 new_layout_str, ref->audio->sample_rate);
133}
134
135int av_asrc_buffer_add_audio_buffer_ref(AVFilterContext *ctx,
136 AVFilterBufferRef *samplesref,
137 int av_unused flags)
138{
139 ABufferSourceContext *abuffer = ctx->priv;
140 AVFilterLink *link;
141 int ret, logged = 0;
142
143 if (av_fifo_space(abuffer->fifo) < sizeof(samplesref)) {
144 av_log(ctx, AV_LOG_ERROR,
145 "Buffering limit reached. Please consume some available frames "
146 "before adding new ones.\n");
147 return AVERROR(EINVAL);
148 }
149
150 // Normalize input
151
152 link = ctx->outputs[0];
153 if (samplesref->audio->sample_rate != link->sample_rate) {
154
155 log_input_change(ctx, link, samplesref);
156 logged = 1;
157
158 abuffer->sample_rate = samplesref->audio->sample_rate;
159
160 if (!abuffer->aresample) {
161 ret = insert_filter(abuffer, link, &abuffer->aresample, "aresample");
162 if (ret < 0) return ret;
163 } else {
164 link = abuffer->aresample->outputs[0];
165 if (samplesref->audio->sample_rate == link->sample_rate)
166 remove_filter(&abuffer->aresample);
167 else
168 if ((ret = reconfigure_filter(abuffer, abuffer->aresample)) < 0)
169 return ret;
170 }
171 }
172
173 link = ctx->outputs[0];
174 if (samplesref->format != link->format ||
175 samplesref->audio->channel_layout != link->channel_layout ||
176 samplesref->audio->planar != link->planar) {
177
178 if (!logged) log_input_change(ctx, link, samplesref);
179
180 abuffer->sample_format = samplesref->format;
181 abuffer->channel_layout = samplesref->audio->channel_layout;
182 abuffer->packing_format = samplesref->audio->planar;
183
184 if (!abuffer->aconvert) {
185 ret = insert_filter(abuffer, link, &abuffer->aconvert, "aconvert");
186 if (ret < 0) return ret;
187 } else {
188 link = abuffer->aconvert->outputs[0];
189 if (samplesref->format == link->format &&
190 samplesref->audio->channel_layout == link->channel_layout &&
191 samplesref->audio->planar == link->planar
192 )
193 remove_filter(&abuffer->aconvert);
194 else
195 if ((ret = reconfigure_filter(abuffer, abuffer->aconvert)) < 0)
196 return ret;
197 }
198 }
199
200 if (sizeof(samplesref) != av_fifo_generic_write(abuffer->fifo, &samplesref,
201 sizeof(samplesref), NULL)) {
202 av_log(ctx, AV_LOG_ERROR, "Error while writing to FIFO\n");
203 return AVERROR(EINVAL);
204 }
205
206 return 0;
207}
208
209int av_asrc_buffer_add_samples(AVFilterContext *ctx,
210 uint8_t *data[8], int linesize[8],
211 int nb_samples, int sample_rate,
212 int sample_fmt, int64_t channel_layout, int planar,
213 int64_t pts, int av_unused flags)
214{
215 AVFilterBufferRef *samplesref;
216
217 samplesref = avfilter_get_audio_buffer_ref_from_arrays(
218 data, linesize, AV_PERM_WRITE,
219 nb_samples,
220 sample_fmt, channel_layout, planar);
221 if (!samplesref)
222 return AVERROR(ENOMEM);
223
224 samplesref->buf->free = buf_free;
225 samplesref->pts = pts;
226 samplesref->audio->sample_rate = sample_rate;
227
228 return av_asrc_buffer_add_audio_buffer_ref(ctx, samplesref, 0);
229}
230
231int av_asrc_buffer_add_buffer(AVFilterContext *ctx,
232 uint8_t *buf, int buf_size, int sample_rate,
233 int sample_fmt, int64_t channel_layout, int planar,
234 int64_t pts, int av_unused flags)
235{
236 uint8_t *data[8];
237 int linesize[8];
238 int nb_channels = av_get_channel_layout_nb_channels(channel_layout),
239 nb_samples = buf_size / nb_channels / av_get_bytes_per_sample(sample_fmt);
240
241 av_samples_fill_arrays(data, linesize,
242 buf, nb_channels, nb_samples,
243 sample_fmt, planar, 16);
244
245 return av_asrc_buffer_add_samples(ctx,
246 data, linesize, nb_samples,
247 sample_rate,
248 sample_fmt, channel_layout, planar,
249 pts, flags);
250}
251
252static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
253{
254 ABufferSourceContext *abuffer = ctx->priv;
255 char *arg = NULL, *ptr, chlayout_str[16];
256 int ret;
257
258 arg = strtok_r(args, ":", &ptr);
259
260#define ADD_FORMAT(fmt_name) \
261 if (!arg) \
262 goto arg_fail; \
263 if ((ret = ff_parse_##fmt_name(&abuffer->fmt_name, arg, ctx)) < 0) \
264 return ret; \
265 if (*args) \
266 arg = strtok_r(NULL, ":", &ptr)
267
268 ADD_FORMAT(sample_rate);
269 ADD_FORMAT(sample_format);
270 ADD_FORMAT(channel_layout);
271 ADD_FORMAT(packing_format);
272
273 abuffer->fifo = av_fifo_alloc(FIFO_SIZE*sizeof(AVFilterBufferRef*));
274 if (!abuffer->fifo) {
275 av_log(ctx, AV_LOG_ERROR, "Failed to allocate fifo, filter init failed.\n");
276 return AVERROR(ENOMEM);
277 }
278
279 av_get_channel_layout_string(chlayout_str, sizeof(chlayout_str),
280 -1, abuffer->channel_layout);
281 av_log(ctx, AV_LOG_INFO, "format:%s layout:%s rate:%d\n",
282 av_get_sample_fmt_name(abuffer->sample_format), chlayout_str,
283 abuffer->sample_rate);
284
285 return 0;
286
287arg_fail:
288 av_log(ctx, AV_LOG_ERROR, "Invalid arguments, must be of the form "
289 "sample_rate:sample_fmt:channel_layout:packing\n");
290 return AVERROR(EINVAL);
291}
292
293static av_cold void uninit(AVFilterContext *ctx)
294{
295 ABufferSourceContext *abuffer = ctx->priv;
296 av_fifo_free(abuffer->fifo);
297}
298
299static int query_formats(AVFilterContext *ctx)
300{
301 ABufferSourceContext *abuffer = ctx->priv;
302 AVFilterFormats *formats;
303
304 formats = NULL;
305 avfilter_add_format(&formats, abuffer->sample_format);
306 avfilter_set_common_sample_formats(ctx, formats);
307
308 formats = NULL;
309 avfilter_add_format(&formats, abuffer->channel_layout);
310 avfilter_set_common_channel_layouts(ctx, formats);
311
312 formats = NULL;
313 avfilter_add_format(&formats, abuffer->packing_format);
314 avfilter_set_common_packing_formats(ctx, formats);
315
316 return 0;
317}
318
319static int config_output(AVFilterLink *outlink)
320{
321 ABufferSourceContext *abuffer = outlink->src->priv;
322 outlink->sample_rate = abuffer->sample_rate;
323 return 0;
324}
325
326static int request_frame(AVFilterLink *outlink)
327{
328 ABufferSourceContext *abuffer = outlink->src->priv;
329 AVFilterBufferRef *samplesref;
330
331 if (!av_fifo_size(abuffer->fifo)) {
332 av_log(outlink->src, AV_LOG_ERROR,
333 "request_frame() called with no available frames!\n");
334 return AVERROR(EINVAL);
335 }
336
337 av_fifo_generic_read(abuffer->fifo, &samplesref, sizeof(samplesref), NULL);
338 avfilter_filter_samples(outlink, avfilter_ref_buffer(samplesref, ~0));
339 avfilter_unref_buffer(samplesref);
340
341 return 0;
342}
343
344static int poll_frame(AVFilterLink *outlink)
345{
346 ABufferSourceContext *abuffer = outlink->src->priv;
347 return av_fifo_size(abuffer->fifo)/sizeof(AVFilterBufferRef*);
348}
349
350AVFilter avfilter_asrc_abuffer = {
351 .name = "abuffer",
352 .description = NULL_IF_CONFIG_SMALL("Buffer audio frames, and make them accessible to the filterchain."),
353 .priv_size = sizeof(ABufferSourceContext),
354 .query_formats = query_formats,
355
356 .init = init,
357 .uninit = uninit,
358
359 .inputs = (AVFilterPad[]) {{ .name = NULL }},
360 .outputs = (AVFilterPad[]) {{ .name = "default",
361 .type = AVMEDIA_TYPE_AUDIO,
362 .request_frame = request_frame,
363 .poll_frame = poll_frame,
364 .config_props = config_output, },
365 { .name = NULL}},
366};
libavfilter/asrc_abuffer.h+80−0
@@ -0,0 +1,80 @@
1/*
2 * This file is part of FFmpeg.
3 *
4 * FFmpeg is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * FFmpeg is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with FFmpeg; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19#ifndef AVFILTER_ASRC_ABUFFER_H
20#define AVFILTER_ASRC_ABUFFER_H
21
22#include "avfilter.h"
23
24/**
25 * @file
26 * memory buffer source for audio
27 */
28
29/**
30 * Queue an audio buffer to the audio buffer source.
31 *
32 * @param abuffersrc audio source buffer context
33 * @param data pointers to the samples planes
34 * @param linesize linesizes of each audio buffer plane
35 * @param nb_samples number of samples per channel
36 * @param sample_fmt sample format of the audio data
37 * @param ch_layout channel layout of the audio data
38 * @param planar flag to indicate if audio data is planar or packed
39 * @param pts presentation timestamp of the audio buffer
40 * @param flags unused
41 */
42int av_asrc_buffer_add_samples(AVFilterContext *abuffersrc,
43 uint8_t *data[8], int linesize[8],
44 int nb_samples, int sample_rate,
45 int sample_fmt, int64_t ch_layout, int planar,
46 int64_t pts, int av_unused flags);
47
48/**
49 * Queue an audio buffer to the audio buffer source.
50 *
51 * This is similar to av_asrc_buffer_add_samples(), but the samples
52 * are stored in a buffer with known size.
53 *
54 * @param abuffersrc audio source buffer context
55 * @param buf pointer to the samples data, packed is assumed
56 * @param size the size in bytes of the buffer, it must contain an
57 * integer number of samples
58 * @param sample_fmt sample format of the audio data
59 * @param ch_layout channel layout of the audio data
60 * @param pts presentation timestamp of the audio buffer
61 * @param flags unused
62 */
63int av_asrc_buffer_add_buffer(AVFilterContext *abuffersrc,
64 uint8_t *buf, int buf_size,
65 int sample_rate,
66 int sample_fmt, int64_t ch_layout, int planar,
67 int64_t pts, int av_unused flags);
68
69/**
70 * Queue an audio buffer to the audio buffer source.
71 *
72 * @param abuffersrc audio source buffer context
73 * @param samplesref buffer ref to queue
74 * @param flags unused
75 */
76int av_asrc_buffer_add_audio_buffer_ref(AVFilterContext *abuffersrc,
77 AVFilterBufferRef *samplesref,
78 int av_unused flags);
79
80#endif /* AVFILTER_ASRC_ABUFFER_H */
libavfilter/avfilter.h+1−1
@@ -29,7 +29,7 @@ · 28 unmodified lines
29#include "libavutil/rational.h"29#include "libavutil/rational.h"
30 30
31#define LIBAVFILTER_VERSION_MAJOR 231#define LIBAVFILTER_VERSION_MAJOR 2
32#define LIBAVFILTER_VERSION_MINOR 3332#define LIBAVFILTER_VERSION_MINOR 34
33#define LIBAVFILTER_VERSION_MICRO 033#define LIBAVFILTER_VERSION_MICRO 0
34 34
35#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \35#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t