FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavfilter/buffersink.c
Date: 2025-02-11 20:31:05
Exec Total Coverage
Lines: 115 218 52.8%
Functions: 23 28 82.1%
Branches: 74 214 34.6%

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