FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavfilter/buffersink.c
Date: 2026-04-20 20:24:43
Exec Total Coverage
Lines: 125 236 53.0%
Functions: 24 29 82.8%
Branches: 83 244 34.0%

Line Branch Exec Source
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/avassert.h"
27 #include "libavutil/avstring.h"
28 #include "libavutil/channel_layout.h"
29 #include "libavutil/common.h"
30 #include "libavutil/internal.h"
31 #include "libavutil/mem.h"
32 #include "libavutil/opt.h"
33
34 #include "audio.h"
35 #include "avfilter.h"
36 #include "avfilter_internal.h"
37 #include "buffersink.h"
38 #include "filters.h"
39 #include "formats.h"
40 #include "framequeue.h"
41 #include "video.h"
42
43 typedef struct BufferSinkContext {
44 const AVClass *class;
45 unsigned warning_limit;
46 unsigned frame_size;
47
48 /* only used for video */
49 #if FF_API_BUFFERSINK_OPTS
50 enum AVPixelFormat *pixel_fmts; ///< list of accepted pixel formats
51 int pixel_fmts_size;
52 enum AVColorSpace *color_spaces; ///< list of accepted color spaces
53 int color_spaces_size;
54 enum AVColorRange *color_ranges; ///< list of accepted color ranges
55 int color_ranges_size;
56 enum AVAlphaMode *alpha_modes; ///< list of accepted alpha modes
57 int alpha_modes_size;
58 #endif
59
60 enum AVPixelFormat *pixel_formats;
61 unsigned nb_pixel_formats;
62
63 int *colorspaces;
64 unsigned nb_colorspaces;
65
66 int *colorranges;
67 unsigned nb_colorranges;
68
69 int *alphamodes;
70 unsigned nb_alphamodes;
71
72 /* only used for audio */
73 #if FF_API_BUFFERSINK_OPTS
74 enum AVSampleFormat *sample_fmts; ///< list of accepted sample formats
75 int sample_fmts_size;
76 char *channel_layouts_str; ///< list of accepted channel layouts
77 int all_channel_counts;
78 int *sample_rates; ///< list of accepted sample rates
79 int sample_rates_size;
80 #endif
81
82 enum AVSampleFormat *sample_formats;
83 unsigned nb_sample_formats;
84
85 int *samplerates;
86 unsigned nb_samplerates;
87
88 AVChannelLayout *channel_layouts;
89 unsigned nb_channel_layouts;
90
91 AVFrame *peeked_frame;
92 } BufferSinkContext;
93
94 int attribute_align_arg av_buffersink_get_frame(AVFilterContext *ctx, AVFrame *frame)
95 {
96 return av_buffersink_get_frame_flags(ctx, frame, 0);
97 }
98
99 498889 static int return_or_keep_frame(BufferSinkContext *buf, AVFrame *out, AVFrame *in, int flags)
100 {
101
2/2
✓ Branch 0 taken 45173 times.
✓ Branch 1 taken 453716 times.
498889 if ((flags & AV_BUFFERSINK_FLAG_PEEK)) {
102 45173 buf->peeked_frame = in;
103
2/2
✓ Branch 0 taken 13593 times.
✓ Branch 1 taken 31580 times.
45173 return out ? av_frame_ref(out, in) : 0;
104 } else {
105 av_assert1(out);
106 453716 buf->peeked_frame = NULL;
107 453716 av_frame_move_ref(out, in);
108 453716 av_frame_free(&in);
109 453716 return 0;
110 }
111 }
112
113 1405386 static int get_frame_internal(AVFilterContext *ctx, AVFrame *frame, int flags, int samples)
114 {
115 1405386 BufferSinkContext *buf = ctx->priv;
116 1405386 AVFilterLink *inlink = ctx->inputs[0];
117 1405386 FilterLinkInternal *li = ff_link_internal(inlink);
118 int status, ret;
119 AVFrame *cur_frame;
120 int64_t pts;
121 1405386 int buffersrc_empty = 0;
122
123
2/2
✓ Branch 0 taken 1360215 times.
✓ Branch 1 taken 45171 times.
1405386 if (buf->peeked_frame)
124 45171 return return_or_keep_frame(buf, frame, buf->peeked_frame, flags);
125
126 while (1) {
127
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3833614 times.
3833614 ret = samples ? ff_inlink_consume_samples(inlink, samples, samples, &cur_frame) :
128 3833614 ff_inlink_consume_frame(inlink, &cur_frame);
129
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3833614 times.
3833614 if (ret < 0) {
130 return ret;
131
2/2
✓ Branch 0 taken 453718 times.
✓ Branch 1 taken 3379896 times.
3833614 } else if (ret) {
132 /* TODO return the frame instead of copying it */
133 453718 return return_or_keep_frame(buf, frame, cur_frame, flags);
134
2/2
✓ Branch 1 taken 9484 times.
✓ Branch 2 taken 3370412 times.
3379896 } else if (ff_inlink_acknowledge_status(inlink, &status, &pts)) {
135 9484 return status;
136
2/2
✓ Branch 0 taken 485666 times.
✓ Branch 1 taken 2884746 times.
3370412 } else if ((flags & AV_BUFFERSINK_FLAG_NO_REQUEST)) {
137 485666 return AVERROR(EAGAIN);
138
2/2
✓ Branch 0 taken 2431473 times.
✓ Branch 1 taken 453273 times.
2884746 } else if (li->frame_wanted_out) {
139 2431473 ret = ff_filter_graph_run_once(ctx->graph);
140
2/2
✓ Branch 0 taken 411787 times.
✓ Branch 1 taken 2019686 times.
2431473 if (ret == FFERROR_BUFFERSRC_EMPTY) {
141 411787 buffersrc_empty = 1;
142
2/2
✓ Branch 0 taken 416166 times.
✓ Branch 1 taken 1603520 times.
2019686 } else if (ret == AVERROR(EAGAIN)) {
143
2/2
✓ Branch 0 taken 411347 times.
✓ Branch 1 taken 4819 times.
416166 if (buffersrc_empty)
144 411347 return ret;
145 4819 ff_inlink_request_frame(inlink);
146
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1603520 times.
1603520 } else if (ret < 0) {
147 return ret;
148 }
149 } else {
150 453273 ff_inlink_request_frame(inlink);
151 }
152 }
153 }
154
155 1405386 int attribute_align_arg av_buffersink_get_frame_flags(AVFilterContext *ctx, AVFrame *frame, int flags)
156 {
157 1405386 return get_frame_internal(ctx, frame, flags,
158 1405386 ff_filter_link(ctx->inputs[0])->min_samples);
159 }
160
161 int attribute_align_arg av_buffersink_get_samples(AVFilterContext *ctx,
162 AVFrame *frame, int nb_samples)
163 {
164 return get_frame_internal(ctx, frame, 0, nb_samples);
165 }
166
167 8357 static av_cold int common_init(AVFilterContext *ctx)
168 {
169 8357 BufferSinkContext *buf = ctx->priv;
170
171 #if FF_API_BUFFERSINK_OPTS
172
173 #define CHECK_LIST_SIZE(field) \
174 if (buf->field ## _size % sizeof(*buf->field)) { \
175 av_log(ctx, AV_LOG_ERROR, "Invalid size for " #field ": %d, " \
176 "should be multiple of %d\n", \
177 buf->field ## _size, (int)sizeof(*buf->field)); \
178 return AVERROR(EINVAL); \
179 }
180
181
2/2
✓ Branch 0 taken 6958 times.
✓ Branch 1 taken 1399 times.
8357 if (ctx->input_pads[0].type == AVMEDIA_TYPE_VIDEO) {
182
4/8
✓ Branch 0 taken 6958 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6958 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6958 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 6958 times.
6958 if ((buf->pixel_fmts_size || buf->color_spaces_size || buf->color_ranges_size || buf->alpha_modes_size) &&
183 (buf->nb_pixel_formats || buf->nb_colorspaces || buf->nb_colorranges || buf->nb_alphamodes)) {
184 av_log(ctx, AV_LOG_ERROR, "Cannot combine old and new format lists\n");
185 return AVERROR(EINVAL);
186 }
187
188
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6958 times.
6958 CHECK_LIST_SIZE(pixel_fmts)
189
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6958 times.
6958 CHECK_LIST_SIZE(color_spaces)
190
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6958 times.
6958 CHECK_LIST_SIZE(color_ranges)
191
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6958 times.
6958 CHECK_LIST_SIZE(alpha_modes)
192 } else {
193
3/6
✓ Branch 0 taken 1399 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1399 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1399 times.
1399 if ((buf->sample_fmts_size || buf->channel_layouts_str || buf->sample_rates_size) &&
194 (buf->nb_sample_formats || buf->nb_samplerates || buf->nb_channel_layouts)) {
195 av_log(ctx, AV_LOG_ERROR, "Cannot combine old and new format lists\n");
196 return AVERROR(EINVAL);
197 }
198
199
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1399 times.
1399 CHECK_LIST_SIZE(sample_fmts)
200
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1399 times.
1399 CHECK_LIST_SIZE(sample_rates)
201
202
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1399 times.
1399 if (buf->channel_layouts_str) {
203 const char *cur = buf->channel_layouts_str;
204
205 if (buf->all_channel_counts)
206 av_log(ctx, AV_LOG_WARNING,
207 "Conflicting all_channel_counts and list in options\n");
208
209 while (cur) {
210 void *tmp;
211 char *next = strchr(cur, '|');
212 if (next)
213 *next++ = 0;
214
215 // +2 for the new element and terminator
216 tmp = av_realloc_array(buf->channel_layouts, buf->nb_channel_layouts + 2,
217 sizeof(*buf->channel_layouts));
218 if (!tmp)
219 return AVERROR(ENOMEM);
220
221 buf->channel_layouts = tmp;
222 memset(&buf->channel_layouts[buf->nb_channel_layouts], 0,
223 sizeof(*buf->channel_layouts) * 2);
224 buf->nb_channel_layouts++;
225
226 int ret = av_channel_layout_from_string(&buf->channel_layouts[buf->nb_channel_layouts - 1], cur);
227 if (ret < 0) {
228 av_log(ctx, AV_LOG_ERROR, "Error parsing channel layout: %s.\n", cur);
229 return ret;
230 }
231
232 cur = next;
233 }
234
235 if (buf->nb_channel_layouts)
236 buf->channel_layouts[buf->nb_channel_layouts] = (AVChannelLayout){ 0 };
237 }
238 }
239
240 #undef CHECK_LIST_SIZE
241
242 #endif
243
244 8357 buf->warning_limit = 100;
245 8357 return 0;
246 }
247
248 #define TERMINATE_ARRAY(arr, val) \
249 if (s->arr) { \
250 void *tmp = av_realloc_array(s->arr, s->nb_ ## arr + 1, sizeof(*s->arr)); \
251 if (!tmp) \
252 return AVERROR(ENOMEM); \
253 s->arr = tmp; \
254 s->arr[s->nb_ ## arr] = val; \
255 }
256
257 6958 static int init_video(AVFilterContext *ctx)
258 {
259 6958 BufferSinkContext *s = ctx->priv;
260
261
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 6958 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
6958 TERMINATE_ARRAY(pixel_formats, AV_PIX_FMT_NONE);
262
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 6958 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
6958 TERMINATE_ARRAY(colorranges, -1);
263
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 6958 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
6958 TERMINATE_ARRAY(colorspaces, -1);
264
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 6958 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
6958 TERMINATE_ARRAY(alphamodes, -1);
265
266 6958 return common_init(ctx);
267 }
268
269 1399 static int init_audio(AVFilterContext *ctx)
270 {
271 1399 BufferSinkContext *s = ctx->priv;
272
273
3/4
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 1372 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 27 times.
1399 TERMINATE_ARRAY(sample_formats, AV_SAMPLE_FMT_NONE);
274
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1399 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1399 TERMINATE_ARRAY(samplerates, -1);
275
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1399 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1399 TERMINATE_ARRAY(channel_layouts, (AVChannelLayout){ .nb_channels = 0 });
276
277 1399 return common_init(ctx);
278 }
279
280 #undef TERMINATE_ARRAY
281
282 8357 static void uninit(AVFilterContext *ctx)
283 {
284 8357 BufferSinkContext *buf = ctx->priv;
285
286 8357 av_frame_free(&buf->peeked_frame);
287 8357 }
288
289 459994 static int activate(AVFilterContext *ctx)
290 {
291 459994 BufferSinkContext *buf = ctx->priv;
292 459994 FilterLinkInternal * const li = ff_link_internal(ctx->inputs[0]);
293
294
1/2
✓ Branch 0 taken 459994 times.
✗ Branch 1 not taken.
459994 if (buf->warning_limit &&
295
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 459994 times.
459994 ff_framequeue_queued_frames(&li->fifo) >= buf->warning_limit) {
296 av_log(ctx, AV_LOG_WARNING,
297 "%d buffers queued in %s, something may be wrong.\n",
298 buf->warning_limit,
299 (char *)av_x_if_null(ctx->name, ctx->filter->name));
300 buf->warning_limit *= 10;
301 }
302
303 /* The frame is queued, the rest is up to get_frame_internal */
304 459994 return 0;
305 }
306
307 1399 static int config_input_audio(AVFilterLink *inlink)
308 {
309 1399 BufferSinkContext *buf = inlink->dst->priv;
310 1399 FilterLink *l = ff_filter_link(inlink);
311
312 1399 l->min_samples = l->max_samples = buf->frame_size;
313
314 1399 return 0;
315 }
316
317 void av_buffersink_set_frame_size(AVFilterContext *ctx, unsigned frame_size)
318 {
319 BufferSinkContext *buf = ctx->priv;
320 buf->frame_size = frame_size;
321
322 if (ctx->inputs && ctx->inputs[0]) {
323 FilterLink *l = ff_filter_link(ctx->inputs[0]);
324 l->min_samples = l->max_samples = buf->frame_size;
325 }
326 }
327
328 #define MAKE_AVFILTERLINK_ACCESSOR(type, field) \
329 type av_buffersink_get_##field(const AVFilterContext *ctx) { \
330 av_assert0(fffilter(ctx->filter)->activate == activate); \
331 return ctx->inputs[0]->field; \
332 }
333
334
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 62 times.
62 MAKE_AVFILTERLINK_ACCESSOR(enum AVMediaType , type )
335
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 462137 times.
462137 MAKE_AVFILTERLINK_ACCESSOR(AVRational , time_base )
336
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8357 times.
8357 MAKE_AVFILTERLINK_ACCESSOR(int , format )
337
338
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8330 times.
8330 MAKE_AVFILTERLINK_ACCESSOR(int , w )
339
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8330 times.
8330 MAKE_AVFILTERLINK_ACCESSOR(int , h )
340
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8330 times.
8330 MAKE_AVFILTERLINK_ACCESSOR(AVRational , sample_aspect_ratio)
341
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8295 times.
8295 MAKE_AVFILTERLINK_ACCESSOR(enum AVColorSpace, colorspace)
342
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8295 times.
8295 MAKE_AVFILTERLINK_ACCESSOR(enum AVColorRange, color_range)
343
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8295 times.
8295 MAKE_AVFILTERLINK_ACCESSOR(enum AVAlphaMode , alpha_mode)
344
345
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8322 times.
8322 MAKE_AVFILTERLINK_ACCESSOR(int , sample_rate )
346
347 10747 AVRational av_buffersink_get_frame_rate(const AVFilterContext *ctx)
348 {
349 10747 FilterLink *l = ff_filter_link(ctx->inputs[0]);
350
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 10747 times.
10747 av_assert0(fffilter(ctx->filter)->activate == activate);
351 10747 return l->frame_rate;
352 }
353
354 AVBufferRef* av_buffersink_get_hw_frames_ctx(const AVFilterContext *ctx)
355 {
356 FilterLink *l = ff_filter_link(ctx->inputs[0]);
357 av_assert0(fffilter(ctx->filter)->activate == activate);
358 return l->hw_frames_ctx;
359 }
360
361 int av_buffersink_get_channels(const AVFilterContext *ctx)
362 {
363 av_assert0(fffilter(ctx->filter)->activate == activate);
364 return ctx->inputs[0]->ch_layout.nb_channels;
365 }
366
367 8322 int av_buffersink_get_ch_layout(const AVFilterContext *ctx, AVChannelLayout *out)
368 {
369 8322 AVChannelLayout ch_layout = { 0 };
370 int ret;
371
372
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8322 times.
8322 av_assert0(fffilter(ctx->filter)->activate == activate);
373 8322 ret = av_channel_layout_copy(&ch_layout, &ctx->inputs[0]->ch_layout);
374
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8322 times.
8322 if (ret < 0)
375 return ret;
376 8322 *out = ch_layout;
377 8322 return 0;
378 }
379
380 8295 const AVFrameSideData *const *av_buffersink_get_side_data(const AVFilterContext *ctx,
381 int *nb_side_data)
382 {
383
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8295 times.
8295 av_assert0(fffilter(ctx->filter)->activate == activate);
384 8295 *nb_side_data = ctx->inputs[0]->nb_side_data;
385 8295 return (const AVFrameSideData *const *)ctx->inputs[0]->side_data;
386 }
387
388 #if FF_API_BUFFERSINK_OPTS
389 #define NB_ITEMS(list) (list ## _size / sizeof(*list))
390 #endif
391
392 6958 static int vsink_query_formats(const AVFilterContext *ctx,
393 AVFilterFormatsConfig **cfg_in,
394 AVFilterFormatsConfig **cfg_out)
395 {
396 6958 const BufferSinkContext *buf = ctx->priv;
397 int ret;
398
399 #if FF_API_BUFFERSINK_OPTS
400
4/8
✓ Branch 0 taken 6958 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6958 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6958 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 6958 times.
6958 if (buf->nb_pixel_formats || buf->nb_colorspaces || buf->nb_colorranges || buf->nb_alphamodes) {
401 #endif
402 if (buf->nb_pixel_formats) {
403 ret = ff_set_pixel_formats_from_list2(ctx, cfg_in, cfg_out, buf->pixel_formats);
404 if (ret < 0)
405 return ret;
406 }
407 if (buf->nb_colorspaces) {
408 ret = ff_set_common_color_spaces_from_list2(ctx, cfg_in, cfg_out, buf->colorspaces);
409 if (ret < 0)
410 return ret;
411 }
412 if (buf->nb_colorranges) {
413 ret = ff_set_common_color_ranges_from_list2(ctx, cfg_in, cfg_out, buf->colorranges);
414 if (ret < 0)
415 return ret;
416 }
417 if (buf->nb_alphamodes) {
418 ret = ff_set_common_alpha_modes_from_list2(ctx, cfg_in, cfg_out, buf->alphamodes);
419 if (ret < 0)
420 return ret;
421 }
422 #if FF_API_BUFFERSINK_OPTS
423 } else {
424 unsigned i;
425
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6958 times.
6958 if (buf->pixel_fmts_size) {
426 AVFilterFormats *formats = NULL;
427 for (i = 0; i < NB_ITEMS(buf->pixel_fmts); i++)
428 if ((ret = ff_add_format(&formats, buf->pixel_fmts[i])) < 0)
429 return ret;
430 if ((ret = ff_set_common_formats2(ctx, cfg_in, cfg_out, formats)) < 0)
431 return ret;
432 }
433
434
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6958 times.
6958 if (buf->color_spaces_size) {
435 AVFilterFormats *formats = NULL;
436 for (i = 0; i < NB_ITEMS(buf->color_spaces); i++)
437 if ((ret = ff_add_format(&formats, buf->color_spaces[i])) < 0)
438 return ret;
439 if ((ret = ff_set_common_color_spaces2(ctx, cfg_in, cfg_out, formats)) < 0)
440 return ret;
441 }
442
443
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6958 times.
6958 if (buf->color_ranges_size) {
444 AVFilterFormats *formats = NULL;
445 for (i = 0; i < NB_ITEMS(buf->color_ranges); i++)
446 if ((ret = ff_add_format(&formats, buf->color_ranges[i])) < 0)
447 return ret;
448 if ((ret = ff_set_common_color_ranges2(ctx, cfg_in, cfg_out, formats)) < 0)
449 return ret;
450 }
451
452
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6958 times.
6958 if (buf->alpha_modes_size) {
453 AVFilterFormats *formats = NULL;
454 for (i = 0; i < NB_ITEMS(buf->alpha_modes); i++)
455 if ((ret = ff_add_format(&formats, buf->alpha_modes[i])) < 0)
456 return ret;
457 if ((ret = ff_set_common_alpha_modes2(ctx, cfg_in, cfg_out, formats)) < 0)
458 return ret;
459 }
460 }
461 #endif
462
463 6958 return 0;
464 }
465
466 1399 static int asink_query_formats(const AVFilterContext *ctx,
467 AVFilterFormatsConfig **cfg_in,
468 AVFilterFormatsConfig **cfg_out)
469 {
470 1399 const BufferSinkContext *buf = ctx->priv;
471 int ret;
472
473 #if FF_API_BUFFERSINK_OPTS
474
4/6
✓ Branch 0 taken 1372 times.
✓ Branch 1 taken 27 times.
✓ Branch 2 taken 1372 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1372 times.
1399 if (buf->nb_sample_formats || buf->nb_samplerates || buf->nb_channel_layouts) {
475 #endif
476
1/2
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
27 if (buf->nb_sample_formats) {
477 27 ret = ff_set_sample_formats_from_list2(ctx, cfg_in, cfg_out, buf->sample_formats);
478
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
27 if (ret < 0)
479 return ret;
480 }
481
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
27 if (buf->nb_samplerates) {
482 ret = ff_set_common_samplerates_from_list2(ctx, cfg_in, cfg_out, buf->samplerates);
483 if (ret < 0)
484 return ret;
485 }
486
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
27 if (buf->nb_channel_layouts) {
487 ret = ff_set_common_channel_layouts_from_list2(ctx, cfg_in, cfg_out, buf->channel_layouts);
488 if (ret < 0)
489 return ret;
490 }
491 #if FF_API_BUFFERSINK_OPTS
492 } else {
493 1372 AVFilterFormats *formats = NULL;
494 unsigned i;
495
496
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1372 times.
1372 if (buf->sample_fmts_size) {
497 for (i = 0; i < NB_ITEMS(buf->sample_fmts); i++)
498 if ((ret = ff_add_format(&formats, buf->sample_fmts[i])) < 0)
499 return ret;
500 if ((ret = ff_set_common_formats2(ctx, cfg_in, cfg_out, formats)) < 0)
501 return ret;
502 }
503
504
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1372 times.
1372 if (buf->nb_channel_layouts) {
505 ret = ff_set_common_channel_layouts_from_list2(ctx, cfg_in, cfg_out, buf->channel_layouts);
506 if (ret < 0)
507 return ret;
508 }
509
510
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1372 times.
1372 if (buf->sample_rates_size) {
511 formats = NULL;
512 for (i = 0; i < NB_ITEMS(buf->sample_rates); i++)
513 if ((ret = ff_add_format(&formats, buf->sample_rates[i])) < 0)
514 return ret;
515 if ((ret = ff_set_common_samplerates2(ctx, cfg_in, cfg_out, formats)) < 0)
516 return ret;
517 }
518 }
519 #endif
520
521 1399 return 0;
522 }
523
524 #define OFFSET(x) offsetof(BufferSinkContext, x)
525 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
526 static const AVOption buffersink_options[] = {
527 #if FF_API_BUFFERSINK_OPTS
528 { "pix_fmts", "set the supported pixel formats", OFFSET(pixel_fmts), AV_OPT_TYPE_BINARY, .flags = FLAGS | AV_OPT_FLAG_DEPRECATED },
529 { "color_spaces", "set the supported color spaces", OFFSET(color_spaces), AV_OPT_TYPE_BINARY, .flags = FLAGS | AV_OPT_FLAG_DEPRECATED },
530 { "color_ranges", "set the supported color ranges", OFFSET(color_ranges), AV_OPT_TYPE_BINARY, .flags = FLAGS | AV_OPT_FLAG_DEPRECATED },
531 #endif
532
533 { "pixel_formats", "array of supported pixel formats", OFFSET(pixel_formats),
534 AV_OPT_TYPE_PIXEL_FMT | AV_OPT_TYPE_FLAG_ARRAY, .max = INT_MAX, .flags = FLAGS },
535 { "colorspaces", "array of supported color spaces", OFFSET(colorspaces),
536 AV_OPT_TYPE_INT | AV_OPT_TYPE_FLAG_ARRAY, .max = INT_MAX, .flags = FLAGS },
537 { "colorranges", "array of supported color ranges", OFFSET(colorranges),
538 AV_OPT_TYPE_INT | AV_OPT_TYPE_FLAG_ARRAY, .max = INT_MAX, .flags = FLAGS },
539 { "alphamodes", "array of supported color ranges", OFFSET(alphamodes),
540 AV_OPT_TYPE_INT | AV_OPT_TYPE_FLAG_ARRAY, .max = INT_MAX, .flags = FLAGS },
541
542 { NULL },
543 };
544 #undef FLAGS
545 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_AUDIO_PARAM
546 static const AVOption abuffersink_options[] = {
547 #if FF_API_BUFFERSINK_OPTS
548 { "sample_fmts", "set the supported sample formats", OFFSET(sample_fmts), AV_OPT_TYPE_BINARY, .flags = FLAGS | AV_OPT_FLAG_DEPRECATED },
549 { "sample_rates", "set the supported sample rates", OFFSET(sample_rates), AV_OPT_TYPE_BINARY, .flags = FLAGS | AV_OPT_FLAG_DEPRECATED },
550 { "ch_layouts", "set a '|'-separated list of supported channel layouts",
551 OFFSET(channel_layouts_str), AV_OPT_TYPE_STRING, .flags = FLAGS | AV_OPT_FLAG_DEPRECATED },
552 { "all_channel_counts", "accept all channel counts", OFFSET(all_channel_counts), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, FLAGS | AV_OPT_FLAG_DEPRECATED },
553 #endif
554
555 { "sample_formats", "array of supported sample formats", OFFSET(sample_formats),
556 AV_OPT_TYPE_SAMPLE_FMT | AV_OPT_TYPE_FLAG_ARRAY, .max = INT_MAX, .flags = FLAGS },
557 { "samplerates", "array of supported sample formats", OFFSET(samplerates),
558 AV_OPT_TYPE_INT | AV_OPT_TYPE_FLAG_ARRAY, .max = INT_MAX, .flags = FLAGS },
559 { "channel_layouts", "array of supported channel layouts", OFFSET(channel_layouts),
560 AV_OPT_TYPE_CHLAYOUT | AV_OPT_TYPE_FLAG_ARRAY, .flags = FLAGS },
561 { NULL },
562 };
563 #undef FLAGS
564
565 AVFILTER_DEFINE_CLASS(buffersink);
566 AVFILTER_DEFINE_CLASS(abuffersink);
567
568 const FFFilter ff_vsink_buffer = {
569 .p.name = "buffersink",
570 .p.description = NULL_IF_CONFIG_SMALL("Buffer video frames, and make them available to the end of the filter graph."),
571 .p.priv_class = &buffersink_class,
572 .p.outputs = NULL,
573 .priv_size = sizeof(BufferSinkContext),
574 .init = init_video,
575 .uninit = uninit,
576 .activate = activate,
577 FILTER_INPUTS(ff_video_default_filterpad),
578 FILTER_QUERY_FUNC2(vsink_query_formats),
579 };
580
581 static const AVFilterPad inputs_audio[] = {
582 {
583 .name = "default",
584 .type = AVMEDIA_TYPE_AUDIO,
585 .config_props = config_input_audio,
586 },
587 };
588
589 const FFFilter ff_asink_abuffer = {
590 .p.name = "abuffersink",
591 .p.description = NULL_IF_CONFIG_SMALL("Buffer audio frames, and make them available to the end of the filter graph."),
592 .p.priv_class = &abuffersink_class,
593 .p.outputs = NULL,
594 .priv_size = sizeof(BufferSinkContext),
595 .init = init_audio,
596 .uninit = uninit,
597 .activate = activate,
598 FILTER_INPUTS(inputs_audio),
599 FILTER_QUERY_FUNC2(asink_query_formats),
600 };
601