History

lavfi: rename vsrc_buffer.c into src_buffer.c.

Nicolas George committed 14 years ago

Commit 2ae5af81 parent 7ad0d982 files · +1 −1Browse files

Showing the changes to libavfilter/src_buffer.c (1 of 2 files). Show all

Unified · Split

libavfilter/src_buffer.c+625−0
@@ -0,0 +1,625 @@
1+/*
2+ * Copyright (c) 2008 Vitor Sessak
3+ * Copyright (c) 2010 S.N. Hemanth Meenakshisundaram
4+ * Copyright (c) 2011 Mina Nagy Zaki
5+ *
6+ * This file is part of FFmpeg.
7+ *
8+ * FFmpeg is free software; you can redistribute it and/or
9+ * modify it under the terms of the GNU Lesser General Public
10+ * License as published by the Free Software Foundation; either
11+ * version 2.1 of the License, or (at your option) any later version.
12+ *
13+ * FFmpeg is distributed in the hope that it will be useful,
14+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16+ * Lesser General Public License for more details.
17+ *
18+ * You should have received a copy of the GNU Lesser General Public
19+ * License along with FFmpeg; if not, write to the Free Software
20+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21+ */
22+
23+/**
24+ * @file
25+ * memory buffer source filter
26+ */
27+
28+#include "avfilter.h"
29+#include "internal.h"
30+#include "avcodec.h"
31+#include "buffersrc.h"
32+#include "vsrc_buffer.h"
33+#include "asrc_abuffer.h"
34+#include "libavutil/audioconvert.h"
35+#include "libavutil/avstring.h"
36+#include "libavutil/fifo.h"
37+#include "libavutil/imgutils.h"
38+
39+typedef struct {
40+ AVFifoBuffer *fifo;
41+ AVRational time_base; ///< time_base to set in the output link
42+ int eof;
43+ unsigned nb_failed_requests;
44+
45+ /* Video only */
46+ AVFilterContext *scale;
47+ int h, w;
48+ enum PixelFormat pix_fmt;
49+ AVRational sample_aspect_ratio;
50+ char sws_param[256];
51+
52+ /* Audio only */
53+ // Audio format of incoming buffers
54+ int sample_rate;
55+ unsigned int sample_format;
56+ int64_t channel_layout;
57+ int packing_format;
58+
59+ // Normalization filters
60+ AVFilterContext *aconvert;
61+ AVFilterContext *aresample;
62+} BufferSourceContext;
63+
64+#define FIFO_SIZE 8
65+
66+#define CHECK_PARAM_CHANGE(s, c, width, height, format)\
67+ if (c->w != width || c->h != height || c->pix_fmt != format) {\
68+ av_log(s, AV_LOG_ERROR, "Changing frame properties on the fly is not supported.\n");\
69+ return AVERROR(EINVAL);\
70+ }
71+
72+int av_vsrc_buffer_add_video_buffer_ref(AVFilterContext *buffer_filter,
73+ AVFilterBufferRef *picref, int flags)
74+{
75+ BufferSourceContext *c = buffer_filter->priv;
76+ AVFilterLink *outlink = buffer_filter->outputs[0];
77+ AVFilterBufferRef *buf;
78+ int ret;
79+
80+ if (!picref) {
81+ c->eof = 1;
82+ return 0;
83+ } else if (c->eof)
84+ return AVERROR(EINVAL);
85+
86+ if (!av_fifo_space(c->fifo) &&
87+ (ret = av_fifo_realloc2(c->fifo, av_fifo_size(c->fifo) +
88+ sizeof(buf))) < 0)
89+ return ret;
90+
91+ if (picref->video->w != c->w || picref->video->h != c->h || picref->format != c->pix_fmt) {
92+ AVFilterContext *scale = buffer_filter->outputs[0]->dst;
93+ AVFilterLink *link;
94+ char scale_param[1024];
95+
96+ av_log(buffer_filter, AV_LOG_INFO,
97+ "Buffer video input changed from size:%dx%d fmt:%s to size:%dx%d fmt:%s\n",
98+ c->w, c->h, av_pix_fmt_descriptors[c->pix_fmt].name,
99+ picref->video->w, picref->video->h, av_pix_fmt_descriptors[picref->format].name);
100+
101+ if (!scale || strcmp(scale->filter->name, "scale")) {
102+ AVFilter *f = avfilter_get_by_name("scale");
103+
104+ av_log(buffer_filter, AV_LOG_INFO, "Inserting scaler filter\n");
105+ if ((ret = avfilter_open(&scale, f, "Input equalizer")) < 0)
106+ return ret;
107+
108+ c->scale = scale;
109+
110+ snprintf(scale_param, sizeof(scale_param)-1, "%d:%d:%s", c->w, c->h, c->sws_param);
111+ if ((ret = avfilter_init_filter(scale, scale_param, NULL)) < 0) {
112+ return ret;
113+ }
114+
115+ if ((ret = avfilter_insert_filter(buffer_filter->outputs[0], scale, 0, 0)) < 0) {
116+ return ret;
117+ }
118+ scale->outputs[0]->time_base = scale->inputs[0]->time_base;
119+
120+ scale->outputs[0]->format= c->pix_fmt;
121+ } else if (!strcmp(scale->filter->name, "scale")) {
122+ snprintf(scale_param, sizeof(scale_param)-1, "%d:%d:%s",
123+ scale->outputs[0]->w, scale->outputs[0]->h, c->sws_param);
124+ scale->filter->init(scale, scale_param, NULL);
125+ }
126+
127+ c->pix_fmt = scale->inputs[0]->format = picref->format;
128+ c->w = scale->inputs[0]->w = picref->video->w;
129+ c->h = scale->inputs[0]->h = picref->video->h;
130+
131+ link = scale->outputs[0];
132+ if ((ret = link->srcpad->config_props(link)) < 0)
133+ return ret;
134+ }
135+
136+ buf = avfilter_get_video_buffer(outlink, AV_PERM_WRITE,
137+ picref->video->w, picref->video->h);
138+ av_image_copy(buf->data, buf->linesize,
139+ (void*)picref->data, picref->linesize,
140+ picref->format, picref->video->w, picref->video->h);
141+ avfilter_copy_buffer_ref_props(buf, picref);
142+
143+ if ((ret = av_fifo_generic_write(c->fifo, &buf, sizeof(buf), NULL)) < 0) {
144+ avfilter_unref_buffer(buf);
145+ return ret;
146+ }
147+ c->nb_failed_requests = 0;
148+
149+ return 0;
150+}
151+
152+int av_buffersrc_buffer(AVFilterContext *s, AVFilterBufferRef *buf)
153+{
154+ BufferSourceContext *c = s->priv;
155+ int ret;
156+
157+ if (!buf) {
158+ c->eof = 1;
159+ return 0;
160+ } else if (c->eof)
161+ return AVERROR(EINVAL);
162+
163+ if (!av_fifo_space(c->fifo) &&
164+ (ret = av_fifo_realloc2(c->fifo, av_fifo_size(c->fifo) +
165+ sizeof(buf))) < 0)
166+ return ret;
167+
168+// CHECK_PARAM_CHANGE(s, c, buf->video->w, buf->video->h, buf->format);
169+
170+ if ((ret = av_fifo_generic_write(c->fifo, &buf, sizeof(buf), NULL)) < 0)
171+ return ret;
172+ c->nb_failed_requests = 0;
173+
174+ return 0;
175+}
176+
177+#if CONFIG_AVCODEC
178+#include "avcodec.h"
179+
180+int av_vsrc_buffer_add_frame(AVFilterContext *buffer_src,
181+ const AVFrame *frame, int flags)
182+{
183+ BufferSourceContext *c = buffer_src->priv;
184+ AVFilterBufferRef *picref;
185+ int ret;
186+
187+ if (!frame) {
188+ c->eof = 1;
189+ return 0;
190+ } else if (c->eof)
191+ return AVERROR(EINVAL);
192+
193+ picref = avfilter_get_video_buffer_ref_from_frame(frame, AV_PERM_WRITE);
194+ if (!picref)
195+ return AVERROR(ENOMEM);
196+ ret = av_vsrc_buffer_add_video_buffer_ref(buffer_src, picref, flags);
197+ picref->buf->data[0] = NULL;
198+ avfilter_unref_buffer(picref);
199+
200+ return ret;
201+}
202+#endif
203+
204+unsigned av_vsrc_buffer_get_nb_failed_requests(AVFilterContext *buffer_src)
205+{
206+ return ((BufferSourceContext *)buffer_src->priv)->nb_failed_requests;
207+}
208+
209+static av_cold int init_video(AVFilterContext *ctx, const char *args, void *opaque)
210+{
211+ BufferSourceContext *c = ctx->priv;
212+ char pix_fmt_str[128];
213+ int ret, n = 0;
214+ *c->sws_param = 0;
215+
216+ if (!args ||
217+ (n = sscanf(args, "%d:%d:%127[^:]:%d:%d:%d:%d:%255c", &c->w, &c->h, pix_fmt_str,
218+ &c->time_base.num, &c->time_base.den,
219+ &c->sample_aspect_ratio.num, &c->sample_aspect_ratio.den, c->sws_param)) < 7) {
220+ av_log(ctx, AV_LOG_ERROR, "Expected at least 7 arguments, but only %d found in '%s'\n", n, args);
221+ return AVERROR(EINVAL);
222+ }
223+
224+ if ((ret = ff_parse_pixel_format(&c->pix_fmt, pix_fmt_str, ctx)) < 0)
225+ return ret;
226+
227+ if (!(c->fifo = av_fifo_alloc(sizeof(AVFilterBufferRef*))))
228+ return AVERROR(ENOMEM);
229+
230+ av_log(ctx, AV_LOG_INFO, "w:%d h:%d pixfmt:%s tb:%d/%d sar:%d/%d sws_param:%s\n",
231+ c->w, c->h, av_pix_fmt_descriptors[c->pix_fmt].name,
232+ c->time_base.num, c->time_base.den,
233+ c->sample_aspect_ratio.num, c->sample_aspect_ratio.den, c->sws_param);
234+ return 0;
235+}
236+
237+static av_cold int init_audio(AVFilterContext *ctx, const char *args0, void *opaque)
238+{
239+ BufferSourceContext *abuffer = ctx->priv;
240+ char *arg = NULL, *ptr, chlayout_str[16];
241+ char *args = av_strdup(args0);
242+ int ret;
243+
244+ arg = av_strtok(args, ":", &ptr);
245+
246+#define ADD_FORMAT(fmt_name) \
247+ if (!arg) \
248+ goto arg_fail; \
249+ if ((ret = ff_parse_##fmt_name(&abuffer->fmt_name, arg, ctx)) < 0) { \
250+ av_freep(&args); \
251+ return ret; \
252+ } \
253+ if (*args) \
254+ arg = av_strtok(NULL, ":", &ptr)
255+
256+ ADD_FORMAT(sample_rate);
257+ ADD_FORMAT(sample_format);
258+ ADD_FORMAT(channel_layout);
259+ ADD_FORMAT(packing_format);
260+
261+ abuffer->fifo = av_fifo_alloc(FIFO_SIZE*sizeof(AVFilterBufferRef*));
262+ if (!abuffer->fifo) {
263+ av_log(ctx, AV_LOG_ERROR, "Failed to allocate fifo, filter init failed.\n");
264+ return AVERROR(ENOMEM);
265+ }
266+
267+ av_get_channel_layout_string(chlayout_str, sizeof(chlayout_str),
268+ -1, abuffer->channel_layout);
269+ av_log(ctx, AV_LOG_INFO, "format:%s layout:%s rate:%d\n",
270+ av_get_sample_fmt_name(abuffer->sample_format), chlayout_str,
271+ abuffer->sample_rate);
272+ av_freep(&args);
273+
274+ return 0;
275+
276+arg_fail:
277+ av_log(ctx, AV_LOG_ERROR, "Invalid arguments, must be of the form "
278+ "sample_rate:sample_fmt:channel_layout:packing\n");
279+ av_freep(&args);
280+ return AVERROR(EINVAL);
281+}
282+
283+static av_cold void uninit(AVFilterContext *ctx)
284+{
285+ BufferSourceContext *s = ctx->priv;
286+ while (s->fifo && av_fifo_size(s->fifo)) {
287+ AVFilterBufferRef *buf;
288+ av_fifo_generic_read(s->fifo, &buf, sizeof(buf), NULL);
289+ avfilter_unref_buffer(buf);
290+ }
291+ av_fifo_free(s->fifo);
292+ s->fifo = NULL;
293+ avfilter_free(s->scale);
294+ s->scale = NULL;
295+}
296+
297+static int query_formats_video(AVFilterContext *ctx)
298+{
299+ BufferSourceContext *c = ctx->priv;
300+ enum PixelFormat pix_fmts[] = { c->pix_fmt, PIX_FMT_NONE };
301+
302+ avfilter_set_common_pixel_formats(ctx, avfilter_make_format_list(pix_fmts));
303+ return 0;
304+}
305+
306+static int query_formats_audio(AVFilterContext *ctx)
307+{
308+ BufferSourceContext *abuffer = ctx->priv;
309+ AVFilterFormats *formats;
310+
311+ formats = NULL;
312+ avfilter_add_format(&formats, abuffer->sample_format);
313+ avfilter_set_common_sample_formats(ctx, formats);
314+
315+ formats = NULL;
316+ avfilter_add_format(&formats, abuffer->channel_layout);
317+ avfilter_set_common_channel_layouts(ctx, formats);
318+
319+ formats = NULL;
320+ avfilter_add_format(&formats, abuffer->packing_format);
321+ avfilter_set_common_packing_formats(ctx, formats);
322+
323+ return 0;
324+}
325+
326+static int config_output_video(AVFilterLink *link)
327+{
328+ BufferSourceContext *c = link->src->priv;
329+
330+ link->w = c->w;
331+ link->h = c->h;
332+ link->sample_aspect_ratio = c->sample_aspect_ratio;
333+ link->time_base = c->time_base;
334+
335+ return 0;
336+}
337+
338+static int config_output_audio(AVFilterLink *outlink)
339+{
340+ BufferSourceContext *abuffer = outlink->src->priv;
341+ outlink->sample_rate = abuffer->sample_rate;
342+ return 0;
343+}
344+
345+static int request_frame(AVFilterLink *link)
346+{
347+ BufferSourceContext *c = link->src->priv;
348+ AVFilterBufferRef *buf;
349+
350+ if (!av_fifo_size(c->fifo)) {
351+ if (c->eof)
352+ return AVERROR_EOF;
353+ c->nb_failed_requests++;
354+ return AVERROR(EAGAIN);
355+ }
356+ av_fifo_generic_read(c->fifo, &buf, sizeof(buf), NULL);
357+
358+ switch (link->type) {
359+ case AVMEDIA_TYPE_VIDEO:
360+ /* TODO reindent */
361+ avfilter_start_frame(link, avfilter_ref_buffer(buf, ~0));
362+ avfilter_draw_slice(link, 0, link->h, 1);
363+ avfilter_end_frame(link);
364+ avfilter_unref_buffer(buf);
365+ break;
366+ case AVMEDIA_TYPE_AUDIO:
367+ avfilter_filter_samples(link, avfilter_ref_buffer(buf, ~0));
368+ break;
369+ default:
370+ return AVERROR(ENOSYS);
371+ }
372+ return 0;
373+}
374+
375+static int poll_frame(AVFilterLink *link)
376+{
377+ BufferSourceContext *c = link->src->priv;
378+ int size = av_fifo_size(c->fifo);
379+ if (!size && c->eof)
380+ return AVERROR_EOF;
381+ return size/sizeof(AVFilterBufferRef*);
382+}
383+
384+static void buf_free(AVFilterBuffer *ptr)
385+{
386+ av_free(ptr);
387+ return;
388+}
389+
390+static void set_link_source(AVFilterContext *src, AVFilterLink *link)
391+{
392+ link->src = src;
393+ link->srcpad = &(src->output_pads[0]);
394+ src->outputs[0] = link;
395+}
396+
397+static int reconfigure_filter(BufferSourceContext *abuffer, AVFilterContext *filt_ctx)
398+{
399+ int ret;
400+ AVFilterLink * const inlink = filt_ctx->inputs[0];
401+ AVFilterLink * const outlink = filt_ctx->outputs[0];
402+
403+ inlink->format = abuffer->sample_format;
404+ inlink->channel_layout = abuffer->channel_layout;
405+ inlink->planar = abuffer->packing_format;
406+ inlink->sample_rate = abuffer->sample_rate;
407+
408+ filt_ctx->filter->uninit(filt_ctx);
409+ memset(filt_ctx->priv, 0, filt_ctx->filter->priv_size);
410+ if ((ret = filt_ctx->filter->init(filt_ctx, NULL , NULL)) < 0)
411+ return ret;
412+ if ((ret = inlink->srcpad->config_props(inlink)) < 0)
413+ return ret;
414+ return outlink->srcpad->config_props(outlink);
415+}
416+
417+static int insert_filter(BufferSourceContext *abuffer,
418+ AVFilterLink *link, AVFilterContext **filt_ctx,
419+ const char *filt_name)
420+{
421+ int ret;
422+
423+ if ((ret = avfilter_open(filt_ctx, avfilter_get_by_name(filt_name), NULL)) < 0)
424+ return ret;
425+
426+ link->src->outputs[0] = NULL;
427+ if ((ret = avfilter_link(link->src, 0, *filt_ctx, 0)) < 0) {
428+ link->src->outputs[0] = link;
429+ return ret;
430+ }
431+
432+ set_link_source(*filt_ctx, link);
433+
434+ if ((ret = reconfigure_filter(abuffer, *filt_ctx)) < 0) {
435+ avfilter_free(*filt_ctx);
436+ return ret;
437+ }
438+
439+ return 0;
440+}
441+
442+static void remove_filter(AVFilterContext **filt_ctx)
443+{
444+ AVFilterLink *outlink = (*filt_ctx)->outputs[0];
445+ AVFilterContext *src = (*filt_ctx)->inputs[0]->src;
446+
447+ (*filt_ctx)->outputs[0] = NULL;
448+ avfilter_free(*filt_ctx);
449+ *filt_ctx = NULL;
450+
451+ set_link_source(src, outlink);
452+}
453+
454+static inline void log_input_change(void *ctx, AVFilterLink *link, AVFilterBufferRef *ref)
455+{
456+ char old_layout_str[16], new_layout_str[16];
457+ av_get_channel_layout_string(old_layout_str, sizeof(old_layout_str),
458+ -1, link->channel_layout);
459+ av_get_channel_layout_string(new_layout_str, sizeof(new_layout_str),
460+ -1, ref->audio->channel_layout);
461+ av_log(ctx, AV_LOG_INFO,
462+ "Audio input format changed: "
463+ "%s:%s:%d -> %s:%s:%d, normalizing\n",
464+ av_get_sample_fmt_name(link->format),
465+ old_layout_str, (int)link->sample_rate,
466+ av_get_sample_fmt_name(ref->format),
467+ new_layout_str, ref->audio->sample_rate);
468+}
469+
470+int av_asrc_buffer_add_audio_buffer_ref(AVFilterContext *ctx,
471+ AVFilterBufferRef *samplesref,
472+ int av_unused flags)
473+{
474+ BufferSourceContext *abuffer = ctx->priv;
475+ AVFilterLink *link;
476+ int ret, logged = 0;
477+
478+ if (av_fifo_space(abuffer->fifo) < sizeof(samplesref)) {
479+ av_log(ctx, AV_LOG_ERROR,
480+ "Buffering limit reached. Please consume some available frames "
481+ "before adding new ones.\n");
482+ return AVERROR(EINVAL);
483+ }
484+
485+ // Normalize input
486+
487+ link = ctx->outputs[0];
488+ if (samplesref->audio->sample_rate != link->sample_rate) {
489+
490+ log_input_change(ctx, link, samplesref);
491+ logged = 1;
492+
493+ abuffer->sample_rate = samplesref->audio->sample_rate;
494+
495+ if (!abuffer->aresample) {
496+ ret = insert_filter(abuffer, link, &abuffer->aresample, "aresample");
497+ if (ret < 0) return ret;
498+ } else {
499+ link = abuffer->aresample->outputs[0];
500+ if (samplesref->audio->sample_rate == link->sample_rate)
501+ remove_filter(&abuffer->aresample);
502+ else
503+ if ((ret = reconfigure_filter(abuffer, abuffer->aresample)) < 0)
504+ return ret;
505+ }
506+ }
507+
508+ link = ctx->outputs[0];
509+ if (samplesref->format != link->format ||
510+ samplesref->audio->channel_layout != link->channel_layout ||
511+ samplesref->audio->planar != link->planar) {
512+
513+ if (!logged) log_input_change(ctx, link, samplesref);
514+
515+ abuffer->sample_format = samplesref->format;
516+ abuffer->channel_layout = samplesref->audio->channel_layout;
517+ abuffer->packing_format = samplesref->audio->planar;
518+
519+ if (!abuffer->aconvert) {
520+ ret = insert_filter(abuffer, link, &abuffer->aconvert, "aconvert");
521+ if (ret < 0) return ret;
522+ } else {
523+ link = abuffer->aconvert->outputs[0];
524+ if (samplesref->format == link->format &&
525+ samplesref->audio->channel_layout == link->channel_layout &&
526+ samplesref->audio->planar == link->planar
527+ )
528+ remove_filter(&abuffer->aconvert);
529+ else
530+ if ((ret = reconfigure_filter(abuffer, abuffer->aconvert)) < 0)
531+ return ret;
532+ }
533+ }
534+
535+ if (sizeof(samplesref) != av_fifo_generic_write(abuffer->fifo, &samplesref,
536+ sizeof(samplesref), NULL)) {
537+ av_log(ctx, AV_LOG_ERROR, "Error while writing to FIFO\n");
538+ return AVERROR(EINVAL);
539+ }
540+
541+ return 0;
542+}
543+
544+int av_asrc_buffer_add_samples(AVFilterContext *ctx,
545+ uint8_t *data[8], int linesize[8],
546+ int nb_samples, int sample_rate,
547+ int sample_fmt, int64_t channel_layout, int planar,
548+ int64_t pts, int av_unused flags)
549+{
550+ AVFilterBufferRef *samplesref;
551+
552+ samplesref = avfilter_get_audio_buffer_ref_from_arrays(
553+ data, linesize, AV_PERM_WRITE,
554+ nb_samples,
555+ sample_fmt, channel_layout, planar);
556+ if (!samplesref)
557+ return AVERROR(ENOMEM);
558+
559+ samplesref->buf->free = buf_free;
560+ samplesref->pts = pts;
561+ samplesref->audio->sample_rate = sample_rate;
562+
563+ return av_asrc_buffer_add_audio_buffer_ref(ctx, samplesref, 0);
564+}
565+
566+int av_asrc_buffer_add_buffer(AVFilterContext *ctx,
567+ uint8_t *buf, int buf_size, int sample_rate,
568+ int sample_fmt, int64_t channel_layout, int planar,
569+ int64_t pts, int av_unused flags)
570+{
571+ uint8_t *data[8] = {0};
572+ int linesize[8];
573+ int nb_channels = av_get_channel_layout_nb_channels(channel_layout),
574+ nb_samples = buf_size / nb_channels / av_get_bytes_per_sample(sample_fmt);
575+
576+ av_samples_fill_arrays(data, linesize,
577+ buf, nb_channels, nb_samples,
578+ sample_fmt, 16);
579+
580+ return av_asrc_buffer_add_samples(ctx,
581+ data, linesize, nb_samples,
582+ sample_rate,
583+ sample_fmt, channel_layout, planar,
584+ pts, flags);
585+}
586+
587+AVFilter avfilter_vsrc_buffer = {
588+ .name = "buffer",
589+ .description = NULL_IF_CONFIG_SMALL("Buffer video frames, and make them accessible to the filterchain."),
590+ .priv_size = sizeof(BufferSourceContext),
591+ .query_formats = query_formats_video,
592+
593+ .init = init_video,
594+ .uninit = uninit,
595+
596+ .inputs = (const AVFilterPad[]) {{ .name = NULL }},
597+ .outputs = (const AVFilterPad[]) {{ .name = "default",
598+ .type = AVMEDIA_TYPE_VIDEO,
599+ .request_frame = request_frame,
600+ .poll_frame = poll_frame,
601+ .config_props = config_output_video, },
602+ { .name = NULL}},
603+};
604+
605+#ifdef CONFIG_ABUFFER_FILTER
606+
607+AVFilter avfilter_asrc_abuffer = {
608+ .name = "abuffer",
609+ .description = NULL_IF_CONFIG_SMALL("Buffer audio frames, and make them accessible to the filterchain."),
610+ .priv_size = sizeof(BufferSourceContext),
611+ .query_formats = query_formats_audio,
612+
613+ .init = init_audio,
614+ .uninit = uninit,
615+
616+ .inputs = (const AVFilterPad[]) {{ .name = NULL }},
617+ .outputs = (const AVFilterPad[]) {{ .name = "default",
618+ .type = AVMEDIA_TYPE_AUDIO,
619+ .request_frame = request_frame,
620+ .poll_frame = poll_frame,
621+ .config_props = config_output_audio, },
622+ { .name = NULL}},
623+};
624+
625+#endif

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