FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavfilter/buffersink.c
Date: 2025-07-11 09:13:03
Exec Total Coverage
Lines: 121 225 53.8%
Functions: 23 28 82.1%
Branches: 79 220 35.9%

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