Browse code

lavfi: rename sink_buffer.c into buffersink.c.

Nicolas George authored on 2013/03/11 00:01:12
Showing 3 changed files
... ...
@@ -33,13 +33,13 @@ OBJS = allfilters.o                                                     \
33 33
        avfilter.o                                                       \
34 34
        avfiltergraph.o                                                  \
35 35
        buffer.o                                                         \
36
+       buffersink.o                                                     \
36 37
        buffersrc.o                                                      \
37 38
        drawutils.o                                                      \
38 39
        fifo.o                                                           \
39 40
        formats.o                                                        \
40 41
        graphdump.o                                                      \
41 42
        graphparser.o                                                    \
42
-       sink_buffer.o                                                    \
43 43
        transform.o                                                      \
44 44
        video.o                                                          \
45 45
 
46 46
new file mode 100644
... ...
@@ -0,0 +1,486 @@
0
+/*
1
+ * Copyright (c) 2011 Stefano Sabatini
2
+ *
3
+ * This file is part of FFmpeg.
4
+ *
5
+ * FFmpeg is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * FFmpeg is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with FFmpeg; if not, write to the Free Software
17
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
+ */
19
+
20
+/**
21
+ * @file
22
+ * buffer sink
23
+ */
24
+
25
+#include "libavutil/fifo.h"
26
+#include "libavutil/avassert.h"
27
+#include "libavutil/channel_layout.h"
28
+#include "libavutil/common.h"
29
+#include "libavutil/mathematics.h"
30
+
31
+#include "audio.h"
32
+#include "avfilter.h"
33
+#include "buffersink.h"
34
+#include "internal.h"
35
+
36
+typedef struct {
37
+    AVFifoBuffer *fifo;                      ///< FIFO buffer of video frame references
38
+    unsigned warning_limit;
39
+
40
+    /* only used for video */
41
+    enum AVPixelFormat *pixel_fmts;           ///< list of accepted pixel formats, must be terminated with -1
42
+
43
+    /* only used for audio */
44
+    enum AVSampleFormat *sample_fmts;       ///< list of accepted sample formats, terminated by AV_SAMPLE_FMT_NONE
45
+    int64_t *channel_layouts;               ///< list of accepted channel layouts, terminated by -1
46
+    int all_channel_counts;
47
+    int *sample_rates;                      ///< list of accepted sample rates, terminated by -1
48
+} BufferSinkContext;
49
+
50
+static av_cold void uninit(AVFilterContext *ctx)
51
+{
52
+    BufferSinkContext *sink = ctx->priv;
53
+    AVFrame *frame;
54
+
55
+    if (sink->fifo) {
56
+        while (av_fifo_size(sink->fifo) >= sizeof(AVFilterBufferRef *)) {
57
+            av_fifo_generic_read(sink->fifo, &frame, sizeof(frame), NULL);
58
+            av_frame_unref(frame);
59
+        }
60
+        av_fifo_free(sink->fifo);
61
+        sink->fifo = NULL;
62
+    }
63
+    av_freep(&sink->pixel_fmts);
64
+    av_freep(&sink->sample_fmts);
65
+    av_freep(&sink->sample_rates);
66
+    av_freep(&sink->channel_layouts);
67
+}
68
+
69
+static int add_buffer_ref(AVFilterContext *ctx, AVFrame *ref)
70
+{
71
+    BufferSinkContext *buf = ctx->priv;
72
+
73
+    if (av_fifo_space(buf->fifo) < sizeof(AVFilterBufferRef *)) {
74
+        /* realloc fifo size */
75
+        if (av_fifo_realloc2(buf->fifo, av_fifo_size(buf->fifo) * 2) < 0) {
76
+            av_log(ctx, AV_LOG_ERROR,
77
+                   "Cannot buffer more frames. Consume some available frames "
78
+                   "before adding new ones.\n");
79
+            return AVERROR(ENOMEM);
80
+        }
81
+    }
82
+
83
+    /* cache frame */
84
+    av_fifo_generic_write(buf->fifo, &ref, sizeof(AVFilterBufferRef *), NULL);
85
+    return 0;
86
+}
87
+
88
+static int filter_frame(AVFilterLink *link, AVFrame *frame)
89
+{
90
+    AVFilterContext *ctx = link->dst;
91
+    BufferSinkContext *buf = link->dst->priv;
92
+    int ret;
93
+
94
+    if ((ret = add_buffer_ref(ctx, frame)) < 0)
95
+        return ret;
96
+    if (buf->warning_limit &&
97
+        av_fifo_size(buf->fifo) / sizeof(AVFilterBufferRef *) >= buf->warning_limit) {
98
+        av_log(ctx, AV_LOG_WARNING,
99
+               "%d buffers queued in %s, something may be wrong.\n",
100
+               buf->warning_limit,
101
+               (char *)av_x_if_null(ctx->name, ctx->filter->name));
102
+        buf->warning_limit *= 10;
103
+    }
104
+    return 0;
105
+}
106
+
107
+int av_buffersink_get_frame(AVFilterContext *ctx, AVFrame *frame)
108
+{
109
+    return av_buffersink_get_frame_flags(ctx, frame, 0);
110
+}
111
+
112
+int av_buffersink_get_frame_flags(AVFilterContext *ctx, AVFrame *frame, int flags)
113
+{
114
+    BufferSinkContext *buf = ctx->priv;
115
+    AVFilterLink *inlink = ctx->inputs[0];
116
+    int ret;
117
+    AVFrame *cur_frame;
118
+
119
+    /* no picref available, fetch it from the filterchain */
120
+    if (!av_fifo_size(buf->fifo)) {
121
+        if (flags & AV_BUFFERSINK_FLAG_NO_REQUEST)
122
+            return AVERROR(EAGAIN);
123
+        if ((ret = ff_request_frame(inlink)) < 0)
124
+            return ret;
125
+    }
126
+
127
+    if (!av_fifo_size(buf->fifo))
128
+        return AVERROR(EINVAL);
129
+
130
+    if (flags & AV_BUFFERSINK_FLAG_PEEK) {
131
+        cur_frame = *((AVFrame **)av_fifo_peek2(buf->fifo, 0));
132
+        av_frame_ref(frame, cur_frame); /* TODO check failure */
133
+    } else {
134
+        av_fifo_generic_read(buf->fifo, &cur_frame, sizeof(cur_frame), NULL);
135
+        av_frame_move_ref(frame, cur_frame);
136
+        av_frame_free(&cur_frame);
137
+    }
138
+
139
+    return 0;
140
+}
141
+
142
+int av_buffersink_get_samples(AVFilterContext *ctx, AVFrame *frame, int nb_samples)
143
+{
144
+    av_assert0(!"TODO");
145
+}
146
+
147
+AVBufferSinkParams *av_buffersink_params_alloc(void)
148
+{
149
+    static const int pixel_fmts[] = { AV_PIX_FMT_NONE };
150
+    AVBufferSinkParams *params = av_malloc(sizeof(AVBufferSinkParams));
151
+    if (!params)
152
+        return NULL;
153
+
154
+    params->pixel_fmts = pixel_fmts;
155
+    return params;
156
+}
157
+
158
+AVABufferSinkParams *av_abuffersink_params_alloc(void)
159
+{
160
+    AVABufferSinkParams *params = av_mallocz(sizeof(AVABufferSinkParams));
161
+
162
+    if (!params)
163
+        return NULL;
164
+    return params;
165
+}
166
+
167
+#define FIFO_INIT_SIZE 8
168
+
169
+static av_cold int common_init(AVFilterContext *ctx)
170
+{
171
+    BufferSinkContext *buf = ctx->priv;
172
+
173
+    buf->fifo = av_fifo_alloc(FIFO_INIT_SIZE*sizeof(AVFilterBufferRef *));
174
+    if (!buf->fifo) {
175
+        av_log(ctx, AV_LOG_ERROR, "Failed to allocate fifo\n");
176
+        return AVERROR(ENOMEM);
177
+    }
178
+    buf->warning_limit = 100;
179
+    return 0;
180
+}
181
+
182
+void av_buffersink_set_frame_size(AVFilterContext *ctx, unsigned frame_size)
183
+{
184
+    AVFilterLink *inlink = ctx->inputs[0];
185
+
186
+    inlink->min_samples = inlink->max_samples =
187
+    inlink->partial_buf_size = frame_size;
188
+}
189
+
190
+#if FF_API_AVFILTERBUFFER
191
+static void compat_free_buffer(AVFilterBuffer *buf)
192
+{
193
+    AVFrame *frame = buf->priv;
194
+    av_frame_free(&frame);
195
+    av_free(buf);
196
+}
197
+
198
+static int compat_read(AVFilterContext *ctx, AVFilterBufferRef **pbuf, int nb_samples, int flags)
199
+{
200
+    AVFilterBufferRef *buf;
201
+    AVFrame *frame;
202
+    int ret;
203
+
204
+    if (!pbuf)
205
+        return ff_poll_frame(ctx->inputs[0]);
206
+
207
+    frame = av_frame_alloc();
208
+    if (!frame)
209
+        return AVERROR(ENOMEM);
210
+
211
+    if (!nb_samples)
212
+        ret = av_buffersink_get_frame_flags(ctx, frame, flags);
213
+    else
214
+        ret = av_buffersink_get_samples(ctx, frame, nb_samples);
215
+
216
+    if (ret < 0)
217
+        goto fail;
218
+
219
+    if (ctx->inputs[0]->type == AVMEDIA_TYPE_VIDEO) {
220
+        buf = avfilter_get_video_buffer_ref_from_arrays(frame->data, frame->linesize,
221
+                                                        AV_PERM_READ,
222
+                                                        frame->width, frame->height,
223
+                                                        frame->format);
224
+    } else {
225
+        buf = avfilter_get_audio_buffer_ref_from_arrays(frame->extended_data,
226
+                                                        frame->linesize[0], AV_PERM_READ,
227
+                                                        frame->nb_samples,
228
+                                                        frame->format,
229
+                                                        frame->channel_layout);
230
+    }
231
+    if (!buf) {
232
+        ret = AVERROR(ENOMEM);
233
+        goto fail;
234
+    }
235
+
236
+    avfilter_copy_frame_props(buf, frame);
237
+
238
+    buf->buf->priv = frame;
239
+    buf->buf->free = compat_free_buffer;
240
+
241
+    *pbuf = buf;
242
+
243
+    return 0;
244
+fail:
245
+    av_frame_free(&frame);
246
+    return ret;
247
+}
248
+
249
+int av_buffersink_read(AVFilterContext *ctx, AVFilterBufferRef **buf)
250
+{
251
+    return compat_read(ctx, buf, 0, 0);
252
+}
253
+
254
+int av_buffersink_read_samples(AVFilterContext *ctx, AVFilterBufferRef **buf,
255
+                               int nb_samples)
256
+{
257
+    return compat_read(ctx, buf, nb_samples, 0);
258
+}
259
+
260
+int av_buffersink_get_buffer_ref(AVFilterContext *ctx,
261
+                                  AVFilterBufferRef **bufref, int flags)
262
+{
263
+    *bufref = NULL;
264
+
265
+    av_assert0(    !strcmp(ctx->filter->name, "buffersink")
266
+                || !strcmp(ctx->filter->name, "abuffersink")
267
+                || !strcmp(ctx->filter->name, "ffbuffersink")
268
+                || !strcmp(ctx->filter->name, "ffabuffersink"));
269
+
270
+    return compat_read(ctx, bufref, 0, flags);
271
+}
272
+#endif
273
+
274
+AVRational av_buffersink_get_frame_rate(AVFilterContext *ctx)
275
+{
276
+    av_assert0(   !strcmp(ctx->filter->name, "buffersink")
277
+               || !strcmp(ctx->filter->name, "ffbuffersink"));
278
+
279
+    return ctx->inputs[0]->frame_rate;
280
+}
281
+
282
+int av_buffersink_poll_frame(AVFilterContext *ctx)
283
+{
284
+    BufferSinkContext *buf = ctx->priv;
285
+    AVFilterLink *inlink = ctx->inputs[0];
286
+
287
+    av_assert0(   !strcmp(ctx->filter->name, "buffersink")
288
+               || !strcmp(ctx->filter->name, "abuffersink")
289
+               || !strcmp(ctx->filter->name, "ffbuffersink")
290
+               || !strcmp(ctx->filter->name, "ffabuffersink"));
291
+
292
+    return av_fifo_size(buf->fifo)/sizeof(AVFilterBufferRef *) + ff_poll_frame(inlink);
293
+}
294
+
295
+static av_cold int vsink_init(AVFilterContext *ctx, const char *args, void *opaque)
296
+{
297
+    BufferSinkContext *buf = ctx->priv;
298
+    AVBufferSinkParams *params = opaque;
299
+
300
+    if (params && params->pixel_fmts) {
301
+        const int *pixel_fmts = params->pixel_fmts;
302
+
303
+        buf->pixel_fmts = ff_copy_int_list(pixel_fmts);
304
+        if (!buf->pixel_fmts)
305
+            return AVERROR(ENOMEM);
306
+    }
307
+
308
+    return common_init(ctx);
309
+}
310
+
311
+static int vsink_query_formats(AVFilterContext *ctx)
312
+{
313
+    BufferSinkContext *buf = ctx->priv;
314
+
315
+    if (buf->pixel_fmts)
316
+        ff_set_common_formats(ctx, ff_make_format_list(buf->pixel_fmts));
317
+    else
318
+        ff_default_query_formats(ctx);
319
+
320
+    return 0;
321
+}
322
+
323
+static const AVFilterPad ffbuffersink_inputs[] = {
324
+    {
325
+        .name      = "default",
326
+        .type      = AVMEDIA_TYPE_VIDEO,
327
+        .filter_frame = filter_frame,
328
+    },
329
+    { NULL },
330
+};
331
+
332
+AVFilter avfilter_vsink_ffbuffersink = {
333
+    .name      = "ffbuffersink",
334
+    .description = NULL_IF_CONFIG_SMALL("Buffer video frames, and make them available to the end of the filter graph."),
335
+    .priv_size = sizeof(BufferSinkContext),
336
+    .init_opaque = vsink_init,
337
+    .uninit    = uninit,
338
+
339
+    .query_formats = vsink_query_formats,
340
+    .inputs        = ffbuffersink_inputs,
341
+    .outputs       = NULL,
342
+};
343
+
344
+static const AVFilterPad buffersink_inputs[] = {
345
+    {
346
+        .name      = "default",
347
+        .type      = AVMEDIA_TYPE_VIDEO,
348
+        .filter_frame = filter_frame,
349
+    },
350
+    { NULL },
351
+};
352
+
353
+AVFilter avfilter_vsink_buffersink = {
354
+    .name      = "buffersink",
355
+    .description = NULL_IF_CONFIG_SMALL("Buffer video frames, and make them available to the end of the filter graph."),
356
+    .priv_size = sizeof(BufferSinkContext),
357
+    .init_opaque = vsink_init,
358
+    .uninit    = uninit,
359
+
360
+    .query_formats = vsink_query_formats,
361
+    .inputs        = buffersink_inputs,
362
+    .outputs       = NULL,
363
+};
364
+
365
+static int64_t *concat_channels_lists(const int64_t *layouts, const int *counts)
366
+{
367
+    int nb_layouts = 0, nb_counts = 0, i;
368
+    int64_t *list;
369
+
370
+    if (layouts)
371
+        for (; layouts[nb_layouts] != -1; nb_layouts++);
372
+    if (counts)
373
+        for (; counts[nb_counts] != -1; nb_counts++);
374
+    if (nb_counts > INT_MAX - 1 - nb_layouts)
375
+        return NULL;
376
+    if (!(list = av_calloc(nb_layouts + nb_counts + 1, sizeof(*list))))
377
+        return NULL;
378
+    for (i = 0; i < nb_layouts; i++)
379
+        list[i] = layouts[i];
380
+    for (i = 0; i < nb_counts; i++)
381
+        list[nb_layouts + i] = FF_COUNT2LAYOUT(counts[i]);
382
+    list[nb_layouts + nb_counts] = -1;
383
+    return list;
384
+}
385
+
386
+static av_cold int asink_init(AVFilterContext *ctx, const char *args, void *opaque)
387
+{
388
+    BufferSinkContext *buf = ctx->priv;
389
+    AVABufferSinkParams *params = opaque;
390
+
391
+    if (params && params->sample_fmts) {
392
+        buf->sample_fmts = ff_copy_int_list(params->sample_fmts);
393
+        if (!buf->sample_fmts)
394
+            return AVERROR(ENOMEM);
395
+    }
396
+    if (params && params->sample_rates) {
397
+        buf->sample_rates = ff_copy_int_list(params->sample_rates);
398
+        if (!buf->sample_rates)
399
+            return AVERROR(ENOMEM);
400
+    }
401
+    if (params && (params->channel_layouts || params->channel_counts)) {
402
+        if (params->all_channel_counts) {
403
+            av_log(ctx, AV_LOG_ERROR,
404
+                   "Conflicting all_channel_counts and list in parameters\n");
405
+            return AVERROR(EINVAL);
406
+        }
407
+        buf->channel_layouts = concat_channels_lists(params->channel_layouts,
408
+                                                     params->channel_counts);
409
+        if (!buf->channel_layouts)
410
+            return AVERROR(ENOMEM);
411
+    }
412
+    if (params)
413
+        buf->all_channel_counts = params->all_channel_counts;
414
+    return common_init(ctx);
415
+}
416
+
417
+static int asink_query_formats(AVFilterContext *ctx)
418
+{
419
+    BufferSinkContext *buf = ctx->priv;
420
+    AVFilterFormats *formats = NULL;
421
+    AVFilterChannelLayouts *layouts = NULL;
422
+
423
+    if (buf->sample_fmts) {
424
+        if (!(formats = ff_make_format_list(buf->sample_fmts)))
425
+            return AVERROR(ENOMEM);
426
+        ff_set_common_formats(ctx, formats);
427
+    }
428
+
429
+    if (buf->channel_layouts || buf->all_channel_counts) {
430
+            layouts = buf->all_channel_counts ? ff_all_channel_counts() :
431
+                      avfilter_make_format64_list(buf->channel_layouts);
432
+        if (!layouts)
433
+            return AVERROR(ENOMEM);
434
+        ff_set_common_channel_layouts(ctx, layouts);
435
+    }
436
+
437
+    if (buf->sample_rates) {
438
+        formats = ff_make_format_list(buf->sample_rates);
439
+        if (!formats)
440
+            return AVERROR(ENOMEM);
441
+        ff_set_common_samplerates(ctx, formats);
442
+    }
443
+
444
+    return 0;
445
+}
446
+
447
+static const AVFilterPad ffabuffersink_inputs[] = {
448
+    {
449
+        .name           = "default",
450
+        .type           = AVMEDIA_TYPE_AUDIO,
451
+        .filter_frame   = filter_frame,
452
+    },
453
+    { NULL },
454
+};
455
+
456
+AVFilter avfilter_asink_ffabuffersink = {
457
+    .name      = "ffabuffersink",
458
+    .description = NULL_IF_CONFIG_SMALL("Buffer audio frames, and make them available to the end of the filter graph."),
459
+    .init_opaque = asink_init,
460
+    .uninit    = uninit,
461
+    .priv_size = sizeof(BufferSinkContext),
462
+    .query_formats = asink_query_formats,
463
+    .inputs        = ffabuffersink_inputs,
464
+    .outputs       = NULL,
465
+};
466
+
467
+static const AVFilterPad abuffersink_inputs[] = {
468
+    {
469
+        .name           = "default",
470
+        .type           = AVMEDIA_TYPE_AUDIO,
471
+        .filter_frame   = filter_frame,
472
+    },
473
+    { NULL },
474
+};
475
+
476
+AVFilter avfilter_asink_abuffersink = {
477
+    .name      = "abuffersink",
478
+    .description = NULL_IF_CONFIG_SMALL("Buffer audio frames, and make them available to the end of the filter graph."),
479
+    .init_opaque = asink_init,
480
+    .uninit    = uninit,
481
+    .priv_size = sizeof(BufferSinkContext),
482
+    .query_formats = asink_query_formats,
483
+    .inputs        = abuffersink_inputs,
484
+    .outputs       = NULL,
485
+};
0 486
deleted file mode 100644
... ...
@@ -1,486 +0,0 @@
1
-/*
2
- * Copyright (c) 2011 Stefano Sabatini
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
-/**
22
- * @file
23
- * buffer sink
24
- */
25
-
26
-#include "libavutil/fifo.h"
27
-#include "libavutil/avassert.h"
28
-#include "libavutil/channel_layout.h"
29
-#include "libavutil/common.h"
30
-#include "libavutil/mathematics.h"
31
-
32
-#include "audio.h"
33
-#include "avfilter.h"
34
-#include "buffersink.h"
35
-#include "internal.h"
36
-
37
-typedef struct {
38
-    AVFifoBuffer *fifo;                      ///< FIFO buffer of video frame references
39
-    unsigned warning_limit;
40
-
41
-    /* only used for video */
42
-    enum AVPixelFormat *pixel_fmts;           ///< list of accepted pixel formats, must be terminated with -1
43
-
44
-    /* only used for audio */
45
-    enum AVSampleFormat *sample_fmts;       ///< list of accepted sample formats, terminated by AV_SAMPLE_FMT_NONE
46
-    int64_t *channel_layouts;               ///< list of accepted channel layouts, terminated by -1
47
-    int all_channel_counts;
48
-    int *sample_rates;                      ///< list of accepted sample rates, terminated by -1
49
-} BufferSinkContext;
50
-
51
-static av_cold void uninit(AVFilterContext *ctx)
52
-{
53
-    BufferSinkContext *sink = ctx->priv;
54
-    AVFrame *frame;
55
-
56
-    if (sink->fifo) {
57
-        while (av_fifo_size(sink->fifo) >= sizeof(AVFilterBufferRef *)) {
58
-            av_fifo_generic_read(sink->fifo, &frame, sizeof(frame), NULL);
59
-            av_frame_unref(frame);
60
-        }
61
-        av_fifo_free(sink->fifo);
62
-        sink->fifo = NULL;
63
-    }
64
-    av_freep(&sink->pixel_fmts);
65
-    av_freep(&sink->sample_fmts);
66
-    av_freep(&sink->sample_rates);
67
-    av_freep(&sink->channel_layouts);
68
-}
69
-
70
-static int add_buffer_ref(AVFilterContext *ctx, AVFrame *ref)
71
-{
72
-    BufferSinkContext *buf = ctx->priv;
73
-
74
-    if (av_fifo_space(buf->fifo) < sizeof(AVFilterBufferRef *)) {
75
-        /* realloc fifo size */
76
-        if (av_fifo_realloc2(buf->fifo, av_fifo_size(buf->fifo) * 2) < 0) {
77
-            av_log(ctx, AV_LOG_ERROR,
78
-                   "Cannot buffer more frames. Consume some available frames "
79
-                   "before adding new ones.\n");
80
-            return AVERROR(ENOMEM);
81
-        }
82
-    }
83
-
84
-    /* cache frame */
85
-    av_fifo_generic_write(buf->fifo, &ref, sizeof(AVFilterBufferRef *), NULL);
86
-    return 0;
87
-}
88
-
89
-static int filter_frame(AVFilterLink *link, AVFrame *frame)
90
-{
91
-    AVFilterContext *ctx = link->dst;
92
-    BufferSinkContext *buf = link->dst->priv;
93
-    int ret;
94
-
95
-    if ((ret = add_buffer_ref(ctx, frame)) < 0)
96
-        return ret;
97
-    if (buf->warning_limit &&
98
-        av_fifo_size(buf->fifo) / sizeof(AVFilterBufferRef *) >= buf->warning_limit) {
99
-        av_log(ctx, AV_LOG_WARNING,
100
-               "%d buffers queued in %s, something may be wrong.\n",
101
-               buf->warning_limit,
102
-               (char *)av_x_if_null(ctx->name, ctx->filter->name));
103
-        buf->warning_limit *= 10;
104
-    }
105
-    return 0;
106
-}
107
-
108
-int av_buffersink_get_frame(AVFilterContext *ctx, AVFrame *frame)
109
-{
110
-    return av_buffersink_get_frame_flags(ctx, frame, 0);
111
-}
112
-
113
-int av_buffersink_get_frame_flags(AVFilterContext *ctx, AVFrame *frame, int flags)
114
-{
115
-    BufferSinkContext *buf = ctx->priv;
116
-    AVFilterLink *inlink = ctx->inputs[0];
117
-    int ret;
118
-    AVFrame *cur_frame;
119
-
120
-    /* no picref available, fetch it from the filterchain */
121
-    if (!av_fifo_size(buf->fifo)) {
122
-        if (flags & AV_BUFFERSINK_FLAG_NO_REQUEST)
123
-            return AVERROR(EAGAIN);
124
-        if ((ret = ff_request_frame(inlink)) < 0)
125
-            return ret;
126
-    }
127
-
128
-    if (!av_fifo_size(buf->fifo))
129
-        return AVERROR(EINVAL);
130
-
131
-    if (flags & AV_BUFFERSINK_FLAG_PEEK) {
132
-        cur_frame = *((AVFrame **)av_fifo_peek2(buf->fifo, 0));
133
-        av_frame_ref(frame, cur_frame); /* TODO check failure */
134
-    } else {
135
-        av_fifo_generic_read(buf->fifo, &cur_frame, sizeof(cur_frame), NULL);
136
-        av_frame_move_ref(frame, cur_frame);
137
-        av_frame_free(&cur_frame);
138
-    }
139
-
140
-    return 0;
141
-}
142
-
143
-int av_buffersink_get_samples(AVFilterContext *ctx, AVFrame *frame, int nb_samples)
144
-{
145
-    av_assert0(!"TODO");
146
-}
147
-
148
-AVBufferSinkParams *av_buffersink_params_alloc(void)
149
-{
150
-    static const int pixel_fmts[] = { AV_PIX_FMT_NONE };
151
-    AVBufferSinkParams *params = av_malloc(sizeof(AVBufferSinkParams));
152
-    if (!params)
153
-        return NULL;
154
-
155
-    params->pixel_fmts = pixel_fmts;
156
-    return params;
157
-}
158
-
159
-AVABufferSinkParams *av_abuffersink_params_alloc(void)
160
-{
161
-    AVABufferSinkParams *params = av_mallocz(sizeof(AVABufferSinkParams));
162
-
163
-    if (!params)
164
-        return NULL;
165
-    return params;
166
-}
167
-
168
-#define FIFO_INIT_SIZE 8
169
-
170
-static av_cold int common_init(AVFilterContext *ctx)
171
-{
172
-    BufferSinkContext *buf = ctx->priv;
173
-
174
-    buf->fifo = av_fifo_alloc(FIFO_INIT_SIZE*sizeof(AVFilterBufferRef *));
175
-    if (!buf->fifo) {
176
-        av_log(ctx, AV_LOG_ERROR, "Failed to allocate fifo\n");
177
-        return AVERROR(ENOMEM);
178
-    }
179
-    buf->warning_limit = 100;
180
-    return 0;
181
-}
182
-
183
-void av_buffersink_set_frame_size(AVFilterContext *ctx, unsigned frame_size)
184
-{
185
-    AVFilterLink *inlink = ctx->inputs[0];
186
-
187
-    inlink->min_samples = inlink->max_samples =
188
-    inlink->partial_buf_size = frame_size;
189
-}
190
-
191
-#if FF_API_AVFILTERBUFFER
192
-static void compat_free_buffer(AVFilterBuffer *buf)
193
-{
194
-    AVFrame *frame = buf->priv;
195
-    av_frame_free(&frame);
196
-    av_free(buf);
197
-}
198
-
199
-static int compat_read(AVFilterContext *ctx, AVFilterBufferRef **pbuf, int nb_samples, int flags)
200
-{
201
-    AVFilterBufferRef *buf;
202
-    AVFrame *frame;
203
-    int ret;
204
-
205
-    if (!pbuf)
206
-        return ff_poll_frame(ctx->inputs[0]);
207
-
208
-    frame = av_frame_alloc();
209
-    if (!frame)
210
-        return AVERROR(ENOMEM);
211
-
212
-    if (!nb_samples)
213
-        ret = av_buffersink_get_frame_flags(ctx, frame, flags);
214
-    else
215
-        ret = av_buffersink_get_samples(ctx, frame, nb_samples);
216
-
217
-    if (ret < 0)
218
-        goto fail;
219
-
220
-    if (ctx->inputs[0]->type == AVMEDIA_TYPE_VIDEO) {
221
-        buf = avfilter_get_video_buffer_ref_from_arrays(frame->data, frame->linesize,
222
-                                                        AV_PERM_READ,
223
-                                                        frame->width, frame->height,
224
-                                                        frame->format);
225
-    } else {
226
-        buf = avfilter_get_audio_buffer_ref_from_arrays(frame->extended_data,
227
-                                                        frame->linesize[0], AV_PERM_READ,
228
-                                                        frame->nb_samples,
229
-                                                        frame->format,
230
-                                                        frame->channel_layout);
231
-    }
232
-    if (!buf) {
233
-        ret = AVERROR(ENOMEM);
234
-        goto fail;
235
-    }
236
-
237
-    avfilter_copy_frame_props(buf, frame);
238
-
239
-    buf->buf->priv = frame;
240
-    buf->buf->free = compat_free_buffer;
241
-
242
-    *pbuf = buf;
243
-
244
-    return 0;
245
-fail:
246
-    av_frame_free(&frame);
247
-    return ret;
248
-}
249
-
250
-int av_buffersink_read(AVFilterContext *ctx, AVFilterBufferRef **buf)
251
-{
252
-    return compat_read(ctx, buf, 0, 0);
253
-}
254
-
255
-int av_buffersink_read_samples(AVFilterContext *ctx, AVFilterBufferRef **buf,
256
-                               int nb_samples)
257
-{
258
-    return compat_read(ctx, buf, nb_samples, 0);
259
-}
260
-
261
-int av_buffersink_get_buffer_ref(AVFilterContext *ctx,
262
-                                  AVFilterBufferRef **bufref, int flags)
263
-{
264
-    *bufref = NULL;
265
-
266
-    av_assert0(    !strcmp(ctx->filter->name, "buffersink")
267
-                || !strcmp(ctx->filter->name, "abuffersink")
268
-                || !strcmp(ctx->filter->name, "ffbuffersink")
269
-                || !strcmp(ctx->filter->name, "ffabuffersink"));
270
-
271
-    return compat_read(ctx, bufref, 0, flags);
272
-}
273
-#endif
274
-
275
-AVRational av_buffersink_get_frame_rate(AVFilterContext *ctx)
276
-{
277
-    av_assert0(   !strcmp(ctx->filter->name, "buffersink")
278
-               || !strcmp(ctx->filter->name, "ffbuffersink"));
279
-
280
-    return ctx->inputs[0]->frame_rate;
281
-}
282
-
283
-int av_buffersink_poll_frame(AVFilterContext *ctx)
284
-{
285
-    BufferSinkContext *buf = ctx->priv;
286
-    AVFilterLink *inlink = ctx->inputs[0];
287
-
288
-    av_assert0(   !strcmp(ctx->filter->name, "buffersink")
289
-               || !strcmp(ctx->filter->name, "abuffersink")
290
-               || !strcmp(ctx->filter->name, "ffbuffersink")
291
-               || !strcmp(ctx->filter->name, "ffabuffersink"));
292
-
293
-    return av_fifo_size(buf->fifo)/sizeof(AVFilterBufferRef *) + ff_poll_frame(inlink);
294
-}
295
-
296
-static av_cold int vsink_init(AVFilterContext *ctx, const char *args, void *opaque)
297
-{
298
-    BufferSinkContext *buf = ctx->priv;
299
-    AVBufferSinkParams *params = opaque;
300
-
301
-    if (params && params->pixel_fmts) {
302
-        const int *pixel_fmts = params->pixel_fmts;
303
-
304
-        buf->pixel_fmts = ff_copy_int_list(pixel_fmts);
305
-        if (!buf->pixel_fmts)
306
-            return AVERROR(ENOMEM);
307
-    }
308
-
309
-    return common_init(ctx);
310
-}
311
-
312
-static int vsink_query_formats(AVFilterContext *ctx)
313
-{
314
-    BufferSinkContext *buf = ctx->priv;
315
-
316
-    if (buf->pixel_fmts)
317
-        ff_set_common_formats(ctx, ff_make_format_list(buf->pixel_fmts));
318
-    else
319
-        ff_default_query_formats(ctx);
320
-
321
-    return 0;
322
-}
323
-
324
-static const AVFilterPad ffbuffersink_inputs[] = {
325
-    {
326
-        .name      = "default",
327
-        .type      = AVMEDIA_TYPE_VIDEO,
328
-        .filter_frame = filter_frame,
329
-    },
330
-    { NULL },
331
-};
332
-
333
-AVFilter avfilter_vsink_ffbuffersink = {
334
-    .name      = "ffbuffersink",
335
-    .description = NULL_IF_CONFIG_SMALL("Buffer video frames, and make them available to the end of the filter graph."),
336
-    .priv_size = sizeof(BufferSinkContext),
337
-    .init_opaque = vsink_init,
338
-    .uninit    = uninit,
339
-
340
-    .query_formats = vsink_query_formats,
341
-    .inputs        = ffbuffersink_inputs,
342
-    .outputs       = NULL,
343
-};
344
-
345
-static const AVFilterPad buffersink_inputs[] = {
346
-    {
347
-        .name      = "default",
348
-        .type      = AVMEDIA_TYPE_VIDEO,
349
-        .filter_frame = filter_frame,
350
-    },
351
-    { NULL },
352
-};
353
-
354
-AVFilter avfilter_vsink_buffersink = {
355
-    .name      = "buffersink",
356
-    .description = NULL_IF_CONFIG_SMALL("Buffer video frames, and make them available to the end of the filter graph."),
357
-    .priv_size = sizeof(BufferSinkContext),
358
-    .init_opaque = vsink_init,
359
-    .uninit    = uninit,
360
-
361
-    .query_formats = vsink_query_formats,
362
-    .inputs        = buffersink_inputs,
363
-    .outputs       = NULL,
364
-};
365
-
366
-static int64_t *concat_channels_lists(const int64_t *layouts, const int *counts)
367
-{
368
-    int nb_layouts = 0, nb_counts = 0, i;
369
-    int64_t *list;
370
-
371
-    if (layouts)
372
-        for (; layouts[nb_layouts] != -1; nb_layouts++);
373
-    if (counts)
374
-        for (; counts[nb_counts] != -1; nb_counts++);
375
-    if (nb_counts > INT_MAX - 1 - nb_layouts)
376
-        return NULL;
377
-    if (!(list = av_calloc(nb_layouts + nb_counts + 1, sizeof(*list))))
378
-        return NULL;
379
-    for (i = 0; i < nb_layouts; i++)
380
-        list[i] = layouts[i];
381
-    for (i = 0; i < nb_counts; i++)
382
-        list[nb_layouts + i] = FF_COUNT2LAYOUT(counts[i]);
383
-    list[nb_layouts + nb_counts] = -1;
384
-    return list;
385
-}
386
-
387
-static av_cold int asink_init(AVFilterContext *ctx, const char *args, void *opaque)
388
-{
389
-    BufferSinkContext *buf = ctx->priv;
390
-    AVABufferSinkParams *params = opaque;
391
-
392
-    if (params && params->sample_fmts) {
393
-        buf->sample_fmts = ff_copy_int_list(params->sample_fmts);
394
-        if (!buf->sample_fmts)
395
-            return AVERROR(ENOMEM);
396
-    }
397
-    if (params && params->sample_rates) {
398
-        buf->sample_rates = ff_copy_int_list(params->sample_rates);
399
-        if (!buf->sample_rates)
400
-            return AVERROR(ENOMEM);
401
-    }
402
-    if (params && (params->channel_layouts || params->channel_counts)) {
403
-        if (params->all_channel_counts) {
404
-            av_log(ctx, AV_LOG_ERROR,
405
-                   "Conflicting all_channel_counts and list in parameters\n");
406
-            return AVERROR(EINVAL);
407
-        }
408
-        buf->channel_layouts = concat_channels_lists(params->channel_layouts,
409
-                                                     params->channel_counts);
410
-        if (!buf->channel_layouts)
411
-            return AVERROR(ENOMEM);
412
-    }
413
-    if (params)
414
-        buf->all_channel_counts = params->all_channel_counts;
415
-    return common_init(ctx);
416
-}
417
-
418
-static int asink_query_formats(AVFilterContext *ctx)
419
-{
420
-    BufferSinkContext *buf = ctx->priv;
421
-    AVFilterFormats *formats = NULL;
422
-    AVFilterChannelLayouts *layouts = NULL;
423
-
424
-    if (buf->sample_fmts) {
425
-        if (!(formats = ff_make_format_list(buf->sample_fmts)))
426
-            return AVERROR(ENOMEM);
427
-        ff_set_common_formats(ctx, formats);
428
-    }
429
-
430
-    if (buf->channel_layouts || buf->all_channel_counts) {
431
-            layouts = buf->all_channel_counts ? ff_all_channel_counts() :
432
-                      avfilter_make_format64_list(buf->channel_layouts);
433
-        if (!layouts)
434
-            return AVERROR(ENOMEM);
435
-        ff_set_common_channel_layouts(ctx, layouts);
436
-    }
437
-
438
-    if (buf->sample_rates) {
439
-        formats = ff_make_format_list(buf->sample_rates);
440
-        if (!formats)
441
-            return AVERROR(ENOMEM);
442
-        ff_set_common_samplerates(ctx, formats);
443
-    }
444
-
445
-    return 0;
446
-}
447
-
448
-static const AVFilterPad ffabuffersink_inputs[] = {
449
-    {
450
-        .name           = "default",
451
-        .type           = AVMEDIA_TYPE_AUDIO,
452
-        .filter_frame   = filter_frame,
453
-    },
454
-    { NULL },
455
-};
456
-
457
-AVFilter avfilter_asink_ffabuffersink = {
458
-    .name      = "ffabuffersink",
459
-    .description = NULL_IF_CONFIG_SMALL("Buffer audio frames, and make them available to the end of the filter graph."),
460
-    .init_opaque = asink_init,
461
-    .uninit    = uninit,
462
-    .priv_size = sizeof(BufferSinkContext),
463
-    .query_formats = asink_query_formats,
464
-    .inputs        = ffabuffersink_inputs,
465
-    .outputs       = NULL,
466
-};
467
-
468
-static const AVFilterPad abuffersink_inputs[] = {
469
-    {
470
-        .name           = "default",
471
-        .type           = AVMEDIA_TYPE_AUDIO,
472
-        .filter_frame   = filter_frame,
473
-    },
474
-    { NULL },
475
-};
476
-
477
-AVFilter avfilter_asink_abuffersink = {
478
-    .name      = "abuffersink",
479
-    .description = NULL_IF_CONFIG_SMALL("Buffer audio frames, and make them available to the end of the filter graph."),
480
-    .init_opaque = asink_init,
481
-    .uninit    = uninit,
482
-    .priv_size = sizeof(BufferSinkContext),
483
-    .query_formats = asink_query_formats,
484
-    .inputs        = abuffersink_inputs,
485
-    .outputs       = NULL,
486
-};