History

lavfi: support automatically inserting the fifo filter when needed.

This breaks libavfilter ABI.

Anton Khirnov committed 14 years ago

Commit 58b049f1 parent fa066236 files · +79 −64Browse files

Unified · Split

6 files
  1. doc/APIchanges +1 −1
  2. libavfilter/avfilter.h +8 −0
  3. libavfilter/avfiltergraph.c +40 −0
  4. libavfilter/buffersink.c +20 −61
  5. libavfilter/internal.h +8 −0
  6. libavfilter/version.h +2 −2
doc/APIchanges+1−1
@@ -4,7 +4,7 @@ since the last major version increase. · 3 unmodified lines
44 The last version increases were:
55 libavcodec: 2012-01-27
66 libavdevice: 2011-04-18
7−libavfilter: 2011-04-18
7+libavfilter: 2012-06-22
88 libavformat: 2012-01-27
99 libavresample: 2012-04-24
1010 libswscale: 2011-06-20
libavfilter/avfilter.h+8−0
@@ -363,6 +363,14 @@ struct AVFilterPad { · 362 unmodified lines
363363 * and another value on error.
364364 */
365365 int (*config_props)(AVFilterLink *link);
366+
367+ /**
368+ * The filter expects a fifo to be inserted on its input link,
369+ * typically because it has a delay.
370+ *
371+ * input pads only.
372+ */
373+ int needs_fifo;
366374 };
367375 #endif
368376
libavfilter/avfiltergraph.c+40−0
@@ -591,12 +591,52 @@ static int graph_config_formats(AVFilterGraph *graph, AVClass *log_ctx) · 590 unmodified lines
591591 return 0;
592592 }
593593
594+static int graph_insert_fifos(AVFilterGraph *graph, AVClass *log_ctx)
595+{
596+ AVFilterContext *f;
597+ int i, j, ret;
598+ int fifo_count = 0;
599+
600+ for (i = 0; i < graph->filter_count; i++) {
601+ f = graph->filters[i];
602+
603+ for (j = 0; j < f->nb_inputs; j++) {
604+ AVFilterLink *link = f->inputs[j];
605+ AVFilterContext *fifo_ctx;
606+ AVFilter *fifo;
607+ char name[32];
608+
609+ if (!link->dstpad->needs_fifo)
610+ continue;
611+
612+ fifo = f->inputs[j]->type == AVMEDIA_TYPE_VIDEO ?
613+ avfilter_get_by_name("fifo") :
614+ avfilter_get_by_name("afifo");
615+
616+ snprintf(name, sizeof(name), "auto-inserted fifo %d", fifo_count++);
617+
618+ ret = avfilter_graph_create_filter(&fifo_ctx, fifo, name, NULL,
619+ NULL, graph);
620+ if (ret < 0)
621+ return ret;
622+
623+ ret = avfilter_insert_filter(link, fifo_ctx, 0, 0);
624+ if (ret < 0)
625+ return ret;
626+ }
627+ }
628+
629+ return 0;
630+}
631+
594632 int avfilter_graph_config(AVFilterGraph *graphctx, void *log_ctx)
595633 {
596634 int ret;
597635
598636 if ((ret = graph_check_validity(graphctx, log_ctx)))
599637 return ret;
638+ if ((ret = graph_insert_fifos(graphctx, log_ctx)) < 0)
639+ return ret;
600640 if ((ret = graph_config_formats(graphctx, log_ctx)))
601641 return ret;
602642 if ((ret = graph_config_links(graphctx, log_ctx)))
libavfilter/buffersink.c+20−61
@@ -25,7 +25,7 @@ · 24 unmodified lines
2525
2626 #include "libavutil/audio_fifo.h"
2727 #include "libavutil/audioconvert.h"
28−#include "libavutil/fifo.h"
28+#include "libavutil/avassert.h"
2929 #include "libavutil/mathematics.h"
3030
3131 #include "audio.h"
@@ -34,86 +34,45 @@ · 2 unmodified lines
3434 #include "internal.h"
3535
3636 typedef struct {
37− AVFifoBuffer *fifo; ///< FIFO buffer of frame references
38−
37+ AVFilterBufferRef *cur_buf; ///< last buffer delivered on the sink
3938 AVAudioFifo *audio_fifo; ///< FIFO for audio samples
4039 int64_t next_pts; ///< interpolating audio pts
4140 } BufferSinkContext;
4241
43−#define FIFO_INIT_SIZE 8
44−
4542 static av_cold void uninit(AVFilterContext *ctx)
4643 {
4744 BufferSinkContext *sink = ctx->priv;
4845
49− while (sink->fifo && av_fifo_size(sink->fifo)) {
50− AVFilterBufferRef *buf;
51− av_fifo_generic_read(sink->fifo, &buf, sizeof(buf), NULL);
52− avfilter_unref_buffer(buf);
53− }
54− av_fifo_free(sink->fifo);
55−
5646 if (sink->audio_fifo)
5747 av_audio_fifo_free(sink->audio_fifo);
5848 }
5949
60−static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
61−{
62− BufferSinkContext *sink = ctx->priv;
63−
64− if (!(sink->fifo = av_fifo_alloc(FIFO_INIT_SIZE*sizeof(AVFilterBufferRef*)))) {
65− av_log(ctx, AV_LOG_ERROR, "Failed to allocate fifo\n");
66− return AVERROR(ENOMEM);
67− }
68−
69− return 0;
70−}
71−
72−static void write_buf(AVFilterContext *ctx, AVFilterBufferRef *buf)
50+static void start_frame(AVFilterLink *link, AVFilterBufferRef *buf)
7351 {
74− BufferSinkContext *sink = ctx->priv;
75−
76− if (av_fifo_space(sink->fifo) < sizeof(AVFilterBufferRef *) &&
77− (av_fifo_realloc2(sink->fifo, av_fifo_size(sink->fifo) * 2) < 0)) {
78− av_log(ctx, AV_LOG_ERROR, "Error reallocating the FIFO.\n");
79− return;
80− }
52+ BufferSinkContext *s = link->dst->priv;
8153
82− av_fifo_generic_write(sink->fifo, &buf, sizeof(buf), NULL);
83−}
84−
85−static void end_frame(AVFilterLink *link)
86−{
87− write_buf(link->dst, link->cur_buf);
54+ av_assert0(!s->cur_buf);
55+ s->cur_buf = buf;
8856 link->cur_buf = NULL;
89−}
90−
91−static void filter_samples(AVFilterLink *link, AVFilterBufferRef *buf)
92−{
93− write_buf(link->dst, buf);
94−}
57+};
9558
9659 int av_buffersink_read(AVFilterContext *ctx, AVFilterBufferRef **buf)
9760 {
98− BufferSinkContext *sink = ctx->priv;
61+ BufferSinkContext *s = ctx->priv;
9962 AVFilterLink *link = ctx->inputs[0];
10063 int ret;
10164
102− if (!buf) {
103− if (av_fifo_size(sink->fifo))
104− return av_fifo_size(sink->fifo)/sizeof(*buf);
105− else
106− return ff_poll_frame(ctx->inputs[0]);
107− }
65+ if (!buf)
66+ return ff_poll_frame(ctx->inputs[0]);
10867
109− if (!av_fifo_size(sink->fifo) &&
110− (ret = ff_request_frame(link)) < 0)
68+ if ((ret = ff_request_frame(link)) < 0)
11169 return ret;
11270
113− if (!av_fifo_size(sink->fifo))
71+ if (!s->cur_buf)
11472 return AVERROR(EINVAL);
11573
116− av_fifo_generic_read(sink->fifo, buf, sizeof(*buf), NULL);
74+ *buf = s->cur_buf;
75+ s->cur_buf = NULL;
11776
11877 return 0;
11978 }
@@ -182,13 +141,13 @@ AVFilter avfilter_vsink_buffer = { · 62 unmodified lines
182141 .name = "buffersink",
183142 .description = NULL_IF_CONFIG_SMALL("Buffer video frames, and make them available to the end of the filter graph."),
184143 .priv_size = sizeof(BufferSinkContext),
185− .init = init,
186144 .uninit = uninit,
187145
188146 .inputs = (AVFilterPad[]) {{ .name = "default",
189147 .type = AVMEDIA_TYPE_VIDEO,
190− .end_frame = end_frame,
191− .min_perms = AV_PERM_READ, },
148+ .start_frame = start_frame,
149+ .min_perms = AV_PERM_READ,
150+ .needs_fifo = 1 },
192151 { .name = NULL }},
193152 .outputs = (AVFilterPad[]) {{ .name = NULL }},
194153 };
@@ -197,13 +156,13 @@ AVFilter avfilter_asink_abuffer = { · 2 unmodified lines
197156 .name = "abuffersink",
198157 .description = NULL_IF_CONFIG_SMALL("Buffer audio frames, and make them available to the end of the filter graph."),
199158 .priv_size = sizeof(BufferSinkContext),
200− .init = init,
201159 .uninit = uninit,
202160
203161 .inputs = (AVFilterPad[]) {{ .name = "default",
204162 .type = AVMEDIA_TYPE_AUDIO,
205− .filter_samples = filter_samples,
206− .min_perms = AV_PERM_READ, },
163+ .filter_samples = start_frame,
164+ .min_perms = AV_PERM_READ,
165+ .needs_fifo = 1 },
207166 { .name = NULL }},
208167 .outputs = (AVFilterPad[]) {{ .name = NULL }},
209168 };
libavfilter/internal.h+8−0
@@ -149,6 +149,14 @@ struct AVFilterPad { · 148 unmodified lines
149149 * and another value on error.
150150 */
151151 int (*config_props)(AVFilterLink *link);
152+
153+ /**
154+ * The filter expects a fifo to be inserted on its input link,
155+ * typically because it has a delay.
156+ *
157+ * input pads only.
158+ */
159+ int needs_fifo;
152160 };
153161 #endif
154162
libavfilter/version.h+2−2
@@ -28,8 +28,8 @@ · 27 unmodified lines
2828
2929 #include "libavutil/avutil.h"
3030
31−#define LIBAVFILTER_VERSION_MAJOR 2
32−#define LIBAVFILTER_VERSION_MINOR 23
31+#define LIBAVFILTER_VERSION_MAJOR 3
32+#define LIBAVFILTER_VERSION_MINOR 0
3333 #define LIBAVFILTER_VERSION_MICRO 0
3434
3535 #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