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
4The last version increases were:4The last version increases were:
5libavcodec: 2012-01-275libavcodec: 2012-01-27
6libavdevice: 2011-04-186libavdevice: 2011-04-18
7libavfilter: 2011-04-187libavfilter: 2012-06-22
8libavformat: 2012-01-278libavformat: 2012-01-27
9libavresample: 2012-04-249libavresample: 2012-04-24
10libswscale: 2011-06-2010libswscale: 2011-06-20
libavfilter/avfilter.h+8−0
@@ -363,6 +363,14 @@ struct AVFilterPad { · 362 unmodified lines
363 * and another value on error.363 * and another value on error.
364 */364 */
365 int (*config_props)(AVFilterLink *link);365 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;
366};374};
367#endif375#endif
368 376
libavfilter/avfiltergraph.c+40−0
@@ -591,12 +591,52 @@ static int graph_config_formats(AVFilterGraph *graph, AVClass *log_ctx) · 590 unmodified lines
591 return 0;591 return 0;
592}592}
593 593
594static 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
594int avfilter_graph_config(AVFilterGraph *graphctx, void *log_ctx)632int avfilter_graph_config(AVFilterGraph *graphctx, void *log_ctx)
595{633{
596 int ret;634 int ret;
597 635
598 if ((ret = graph_check_validity(graphctx, log_ctx)))636 if ((ret = graph_check_validity(graphctx, log_ctx)))
599 return ret;637 return ret;
638 if ((ret = graph_insert_fifos(graphctx, log_ctx)) < 0)
639 return ret;
600 if ((ret = graph_config_formats(graphctx, log_ctx)))640 if ((ret = graph_config_formats(graphctx, log_ctx)))
601 return ret;641 return ret;
602 if ((ret = graph_config_links(graphctx, log_ctx)))642 if ((ret = graph_config_links(graphctx, log_ctx)))
libavfilter/buffersink.c+20−61
@@ -25,7 +25,7 @@ · 24 unmodified lines
25 25
26#include "libavutil/audio_fifo.h"26#include "libavutil/audio_fifo.h"
27#include "libavutil/audioconvert.h"27#include "libavutil/audioconvert.h"
28#include "libavutil/fifo.h"28#include "libavutil/avassert.h"
29#include "libavutil/mathematics.h"29#include "libavutil/mathematics.h"
30 30
31#include "audio.h"31#include "audio.h"
@@ -34,86 +34,45 @@ · 2 unmodified lines
34#include "internal.h"34#include "internal.h"
35 35
36typedef struct {36typedef struct {
37 AVFifoBuffer *fifo; ///< FIFO buffer of frame references37 AVFilterBufferRef *cur_buf; ///< last buffer delivered on the sink
38
39 AVAudioFifo *audio_fifo; ///< FIFO for audio samples38 AVAudioFifo *audio_fifo; ///< FIFO for audio samples
40 int64_t next_pts; ///< interpolating audio pts39 int64_t next_pts; ///< interpolating audio pts
41} BufferSinkContext;40} BufferSinkContext;
42 41
43#define FIFO_INIT_SIZE 8
44
45static av_cold void uninit(AVFilterContext *ctx)42static av_cold void uninit(AVFilterContext *ctx)
46{43{
47 BufferSinkContext *sink = ctx->priv;44 BufferSinkContext *sink = ctx->priv;
48 45
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
56 if (sink->audio_fifo)46 if (sink->audio_fifo)
57 av_audio_fifo_free(sink->audio_fifo);47 av_audio_fifo_free(sink->audio_fifo);
58}48}
59 49
60static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)50static void start_frame(AVFilterLink *link, AVFilterBufferRef *buf)
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
72static void write_buf(AVFilterContext *ctx, AVFilterBufferRef *buf)
73{51{
74 BufferSinkContext *sink = ctx->priv;52 BufferSinkContext *s = link->dst->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 }
81 53
82 av_fifo_generic_write(sink->fifo, &buf, sizeof(buf), NULL);54 av_assert0(!s->cur_buf);
83}55 s->cur_buf = buf;
84
85static void end_frame(AVFilterLink *link)
86{
87 write_buf(link->dst, link->cur_buf);
88 link->cur_buf = NULL;56 link->cur_buf = NULL;
89}57};
90
91static void filter_samples(AVFilterLink *link, AVFilterBufferRef *buf)
92{
93 write_buf(link->dst, buf);
94}
95 58
96int av_buffersink_read(AVFilterContext *ctx, AVFilterBufferRef **buf)59int av_buffersink_read(AVFilterContext *ctx, AVFilterBufferRef **buf)
97{60{
98 BufferSinkContext *sink = ctx->priv;61 BufferSinkContext *s = ctx->priv;
99 AVFilterLink *link = ctx->inputs[0];62 AVFilterLink *link = ctx->inputs[0];
100 int ret;63 int ret;
101 64
102 if (!buf) {65 if (!buf)
103 if (av_fifo_size(sink->fifo))66 return ff_poll_frame(ctx->inputs[0]);
104 return av_fifo_size(sink->fifo)/sizeof(*buf);
105 else
106 return ff_poll_frame(ctx->inputs[0]);
107 }
108 67
109 if (!av_fifo_size(sink->fifo) &&68 if ((ret = ff_request_frame(link)) < 0)
110 (ret = ff_request_frame(link)) < 0)
111 return ret;69 return ret;
112 70
113 if (!av_fifo_size(sink->fifo))71 if (!s->cur_buf)
114 return AVERROR(EINVAL);72 return AVERROR(EINVAL);
115 73
116 av_fifo_generic_read(sink->fifo, buf, sizeof(*buf), NULL);74 *buf = s->cur_buf;
75 s->cur_buf = NULL;
117 76
118 return 0;77 return 0;
119}78}
@@ -182,13 +141,13 @@ AVFilter avfilter_vsink_buffer = { · 62 unmodified lines
182 .name = "buffersink",141 .name = "buffersink",
183 .description = NULL_IF_CONFIG_SMALL("Buffer video frames, and make them available to the end of the filter graph."),142 .description = NULL_IF_CONFIG_SMALL("Buffer video frames, and make them available to the end of the filter graph."),
184 .priv_size = sizeof(BufferSinkContext),143 .priv_size = sizeof(BufferSinkContext),
185 .init = init,
186 .uninit = uninit,144 .uninit = uninit,
187 145
188 .inputs = (AVFilterPad[]) {{ .name = "default",146 .inputs = (AVFilterPad[]) {{ .name = "default",
189 .type = AVMEDIA_TYPE_VIDEO,147 .type = AVMEDIA_TYPE_VIDEO,
190 .end_frame = end_frame,148 .start_frame = start_frame,
191 .min_perms = AV_PERM_READ, },149 .min_perms = AV_PERM_READ,
150 .needs_fifo = 1 },
192 { .name = NULL }},151 { .name = NULL }},
193 .outputs = (AVFilterPad[]) {{ .name = NULL }},152 .outputs = (AVFilterPad[]) {{ .name = NULL }},
194};153};
@@ -197,13 +156,13 @@ AVFilter avfilter_asink_abuffer = { · 2 unmodified lines
197 .name = "abuffersink",156 .name = "abuffersink",
198 .description = NULL_IF_CONFIG_SMALL("Buffer audio frames, and make them available to the end of the filter graph."),157 .description = NULL_IF_CONFIG_SMALL("Buffer audio frames, and make them available to the end of the filter graph."),
199 .priv_size = sizeof(BufferSinkContext),158 .priv_size = sizeof(BufferSinkContext),
200 .init = init,
201 .uninit = uninit,159 .uninit = uninit,
202 160
203 .inputs = (AVFilterPad[]) {{ .name = "default",161 .inputs = (AVFilterPad[]) {{ .name = "default",
204 .type = AVMEDIA_TYPE_AUDIO,162 .type = AVMEDIA_TYPE_AUDIO,
205 .filter_samples = filter_samples,163 .filter_samples = start_frame,
206 .min_perms = AV_PERM_READ, },164 .min_perms = AV_PERM_READ,
165 .needs_fifo = 1 },
207 { .name = NULL }},166 { .name = NULL }},
208 .outputs = (AVFilterPad[]) {{ .name = NULL }},167 .outputs = (AVFilterPad[]) {{ .name = NULL }},
209};168};
libavfilter/internal.h+8−0
@@ -149,6 +149,14 @@ struct AVFilterPad { · 148 unmodified lines
149 * and another value on error.149 * and another value on error.
150 */150 */
151 int (*config_props)(AVFilterLink *link);151 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;
152};160};
153#endif161#endif
154 162
libavfilter/version.h+2−2
@@ -28,8 +28,8 @@ · 27 unmodified lines
28 28
29#include "libavutil/avutil.h"29#include "libavutil/avutil.h"
30 30
31#define LIBAVFILTER_VERSION_MAJOR 231#define LIBAVFILTER_VERSION_MAJOR 3
32#define LIBAVFILTER_VERSION_MINOR 2332#define LIBAVFILTER_VERSION_MINOR 0
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