FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavfilter/buffersink.c
Date: 2025-01-20 09:27:23
Exec Total Coverage
Lines: 111 214 51.9%
Functions: 22 27 81.5%
Branches: 73 212 34.4%

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 809235 static int return_or_keep_frame(BufferSinkContext *buf, AVFrame *out, AVFrame *in, int flags)
95 {
96
2/2
✓ Branch 0 taken 414021 times.
✓ Branch 1 taken 395214 times.
809235 if ((flags & AV_BUFFERSINK_FLAG_PEEK)) {
97 414021 buf->peeked_frame = in;
98
2/2
✓ Branch 0 taken 10679 times.
✓ Branch 1 taken 403342 times.
414021 return out ? av_frame_ref(out, in) : 0;
99 } else {
100 av_assert1(out);
101 395214 buf->peeked_frame = NULL;
102 395214 av_frame_move_ref(out, in);
103 395214 av_frame_free(&in);
104 395214 return 0;
105 }
106 }
107
108 1563595 static int get_frame_internal(AVFilterContext *ctx, AVFrame *frame, int flags, int samples)
109 {
110 1563595 BufferSinkContext *buf = ctx->priv;
111 1563595 AVFilterLink *inlink = ctx->inputs[0];
112 1563595 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 1149574 times.
✓ Branch 1 taken 414021 times.
1563595 if (buf->peeked_frame)
118 414021 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 3182853 times.
3182853 ret = samples ? ff_inlink_consume_samples(inlink, samples, samples, &cur_frame) :
122 3182853 ff_inlink_consume_frame(inlink, &cur_frame);
123
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3182853 times.
3182853 if (ret < 0) {
124 return ret;
125
2/2
✓ Branch 0 taken 395214 times.
✓ Branch 1 taken 2787639 times.
3182853 } else if (ret) {
126 /* TODO return the frame instead of copying it */
127 395214 return return_or_keep_frame(buf, frame, cur_frame, flags);
128
2/2
✓ Branch 1 taken 5201 times.
✓ Branch 2 taken 2782438 times.
2787639 } else if (ff_inlink_acknowledge_status(inlink, &status, &pts)) {
129 5201 return status;
130
2/2
✓ Branch 0 taken 388333 times.
✓ Branch 1 taken 2394105 times.
2782438 } else if ((flags & AV_BUFFERSINK_FLAG_NO_REQUEST)) {
131 388333 return AVERROR(EAGAIN);
132
2/2
✓ Branch 0 taken 2002074 times.
✓ Branch 1 taken 392031 times.
2394105 } else if (li->frame_wanted_out) {
133 2002074 ret = ff_filter_graph_run_once(ctx->graph);
134
2/2
✓ Branch 0 taken 360826 times.
✓ Branch 1 taken 1641248 times.
2002074 if (ret < 0)
135 360826 return ret;
136 } else {
137 392031 ff_inlink_request_frame(inlink);
138 }
139 }
140 }
141
142 1563595 int attribute_align_arg av_buffersink_get_frame_flags(AVFilterContext *ctx, AVFrame *frame, int flags)
143 {
144 1563595 return get_frame_internal(ctx, frame, flags,
145 1563595 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 7762 static av_cold int common_init(AVFilterContext *ctx)
155 {
156 7762 BufferSinkContext *buf = ctx->priv;
157 7762 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 1356 times.
7762 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 1332 times.
✓ Branch 1 taken 24 times.
✓ Branch 2 taken 1332 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1332 times.
1356 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 1356 times.
1356 CHECK_LIST_SIZE(sample_fmts)
187
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1356 times.
1356 CHECK_LIST_SIZE(sample_rates)
188
189
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1356 times.
1356 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 7762 buf->warning_limit = 100;
234 7762 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 1356 static int init_audio(AVFilterContext *ctx)
258 {
259 1356 BufferSinkContext *s = ctx->priv;
260
261
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1356 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1356 TERMINATE_ARRAY(sample_formats, AV_SAMPLE_FMT_NONE);
262
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1356 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1356 TERMINATE_ARRAY(samplerates, -1);
263
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1356 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1356 TERMINATE_ARRAY(channel_layouts, (AVChannelLayout){ .nb_channels = 0 });
264
265 1356 return common_init(ctx);
266 }
267
268 #undef TERMINATE_ARRAY
269
270 7762 static void uninit(AVFilterContext *ctx)
271 {
272 7762 BufferSinkContext *buf = ctx->priv;
273
274 7762 av_frame_free(&buf->peeked_frame);
275 7762 }
276
277 398416 static int activate(AVFilterContext *ctx)
278 {
279 398416 BufferSinkContext *buf = ctx->priv;
280 398416 FilterLinkInternal * const li = ff_link_internal(ctx->inputs[0]);
281
282
1/2
✓ Branch 0 taken 398416 times.
✗ Branch 1 not taken.
398416 if (buf->warning_limit &&
283
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 398416 times.
398416 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 398416 return 0;
293 }
294
295 1356 static int config_input_audio(AVFilterLink *inlink)
296 {
297 1356 BufferSinkContext *buf = inlink->dst->priv;
298 1356 FilterLink *l = ff_filter_link(inlink);
299
300 1356 l->min_samples = l->max_samples = buf->frame_size;
301
302 1356 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 402997 times.
402997 MAKE_AVFILTERLINK_ACCESSOR(AVRational , time_base )
324
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7762 times.
7762 MAKE_AVFILTERLINK_ACCESSOR(int , format )
325
326
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7738 times.
7738 MAKE_AVFILTERLINK_ACCESSOR(int , w )
327
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7738 times.
7738 MAKE_AVFILTERLINK_ACCESSOR(int , h )
328
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7738 times.
7738 MAKE_AVFILTERLINK_ACCESSOR(AVRational , sample_aspect_ratio)
329
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7717 times.
7717 MAKE_AVFILTERLINK_ACCESSOR(enum AVColorSpace, colorspace)
330
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7717 times.
7717 MAKE_AVFILTERLINK_ACCESSOR(enum AVColorRange, color_range)
331
332
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7741 times.
7741 MAKE_AVFILTERLINK_ACCESSOR(int , sample_rate )
333
334 10149 AVRational av_buffersink_get_frame_rate(const AVFilterContext *ctx)
335 {
336 10149 FilterLink *l = ff_filter_link(ctx->inputs[0]);
337
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 10149 times.
10149 av_assert0(fffilter(ctx->filter)->activate == activate);
338 10149 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 7741 int av_buffersink_get_ch_layout(const AVFilterContext *ctx, AVChannelLayout *out)
355 {
356 7741 AVChannelLayout ch_layout = { 0 };
357 int ret;
358
359
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7741 times.
7741 av_assert0(fffilter(ctx->filter)->activate == activate);
360 7741 ret = av_channel_layout_copy(&ch_layout, &ctx->inputs[0]->ch_layout);
361
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7741 times.
7741 if (ret < 0)
362 return ret;
363 7741 *out = ch_layout;
364 7741 return 0;
365 }
366
367 #if FF_API_BUFFERSINK_OPTS
368 #define NB_ITEMS(list) (list ## _size / sizeof(*list))
369 #endif
370
371 6406 static int vsink_query_formats(const AVFilterContext *ctx,
372 AVFilterFormatsConfig **cfg_in,
373 AVFilterFormatsConfig **cfg_out)
374 {
375 6406 const BufferSinkContext *buf = ctx->priv;
376 int ret;
377
378 #if FF_API_BUFFERSINK_OPTS
379
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) {
380 #endif
381 if (buf->nb_pixel_formats) {
382 ret = ff_set_common_formats_from_list2(ctx, cfg_in, cfg_out, buf->pixel_formats);
383 if (ret < 0)
384 return ret;
385 }
386 if (buf->nb_colorspaces) {
387 ret = ff_set_common_color_spaces_from_list2(ctx, cfg_in, cfg_out, buf->colorspaces);
388 if (ret < 0)
389 return ret;
390 }
391 if (buf->nb_colorranges) {
392 ret = ff_set_common_color_ranges_from_list2(ctx, cfg_in, cfg_out, buf->colorranges);
393 if (ret < 0)
394 return ret;
395 }
396 #if FF_API_BUFFERSINK_OPTS
397 } else {
398 unsigned i;
399
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6406 times.
6406 if (buf->pixel_fmts_size) {
400 AVFilterFormats *formats = NULL;
401 for (i = 0; i < NB_ITEMS(buf->pixel_fmts); i++)
402 if ((ret = ff_add_format(&formats, buf->pixel_fmts[i])) < 0)
403 return ret;
404 if ((ret = ff_set_common_formats2(ctx, cfg_in, cfg_out, formats)) < 0)
405 return ret;
406 }
407
408
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6406 times.
6406 if (buf->color_spaces_size) {
409 AVFilterFormats *formats = NULL;
410 for (i = 0; i < NB_ITEMS(buf->color_spaces); i++)
411 if ((ret = ff_add_format(&formats, buf->color_spaces[i])) < 0)
412 return ret;
413 if ((ret = ff_set_common_color_spaces2(ctx, cfg_in, cfg_out, formats)) < 0)
414 return ret;
415 }
416
417
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6406 times.
6406 if (buf->color_ranges_size) {
418 AVFilterFormats *formats = NULL;
419 for (i = 0; i < NB_ITEMS(buf->color_ranges); i++)
420 if ((ret = ff_add_format(&formats, buf->color_ranges[i])) < 0)
421 return ret;
422 if ((ret = ff_set_common_color_ranges2(ctx, cfg_in, cfg_out, formats)) < 0)
423 return ret;
424 }
425 }
426 #endif
427
428 6406 return 0;
429 }
430
431 1356 static int asink_query_formats(const AVFilterContext *ctx,
432 AVFilterFormatsConfig **cfg_in,
433 AVFilterFormatsConfig **cfg_out)
434 {
435 1356 const BufferSinkContext *buf = ctx->priv;
436 int ret;
437
438 #if FF_API_BUFFERSINK_OPTS
439
3/6
✓ Branch 0 taken 1356 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1356 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1356 times.
1356 if (buf->nb_sample_formats || buf->nb_samplerates || buf->nb_channel_layouts) {
440 #endif
441 if (buf->nb_sample_formats) {
442 ret = ff_set_common_formats_from_list2(ctx, cfg_in, cfg_out, buf->sample_formats);
443 if (ret < 0)
444 return ret;
445 }
446 if (buf->nb_samplerates) {
447 ret = ff_set_common_samplerates_from_list2(ctx, cfg_in, cfg_out, buf->samplerates);
448 if (ret < 0)
449 return ret;
450 }
451 if (buf->nb_channel_layouts) {
452 ret = ff_set_common_channel_layouts_from_list2(ctx, cfg_in, cfg_out, buf->channel_layouts);
453 if (ret < 0)
454 return ret;
455 }
456 #if FF_API_BUFFERSINK_OPTS
457 } else {
458 1356 AVFilterFormats *formats = NULL;
459 unsigned i;
460
461
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 1332 times.
1356 if (buf->sample_fmts_size) {
462
2/2
✓ Branch 0 taken 120 times.
✓ Branch 1 taken 24 times.
144 for (i = 0; i < NB_ITEMS(buf->sample_fmts); i++)
463
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 120 times.
120 if ((ret = ff_add_format(&formats, buf->sample_fmts[i])) < 0)
464 return ret;
465
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)
466 return ret;
467 }
468
469
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1356 times.
1356 if (buf->nb_channel_layouts) {
470 ret = ff_set_common_channel_layouts_from_list2(ctx, cfg_in, cfg_out, buf->channel_layouts);
471 if (ret < 0)
472 return ret;
473 }
474
475
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1356 times.
1356 if (buf->sample_rates_size) {
476 formats = NULL;
477 for (i = 0; i < NB_ITEMS(buf->sample_rates); i++)
478 if ((ret = ff_add_format(&formats, buf->sample_rates[i])) < 0)
479 return ret;
480 if ((ret = ff_set_common_samplerates2(ctx, cfg_in, cfg_out, formats)) < 0)
481 return ret;
482 }
483 }
484 #endif
485
486 1356 return 0;
487 }
488
489 #define OFFSET(x) offsetof(BufferSinkContext, x)
490 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
491 static const AVOption buffersink_options[] = {
492 #if FF_API_BUFFERSINK_OPTS
493 { "pix_fmts", "set the supported pixel formats", OFFSET(pixel_fmts), AV_OPT_TYPE_BINARY, .flags = FLAGS | AV_OPT_FLAG_DEPRECATED },
494 { "color_spaces", "set the supported color spaces", OFFSET(color_spaces), AV_OPT_TYPE_BINARY, .flags = FLAGS | AV_OPT_FLAG_DEPRECATED },
495 { "color_ranges", "set the supported color ranges", OFFSET(color_ranges), AV_OPT_TYPE_BINARY, .flags = FLAGS | AV_OPT_FLAG_DEPRECATED },
496 #endif
497
498 { "pixel_formats", "array of supported pixel formats", OFFSET(pixel_formats),
499 AV_OPT_TYPE_PIXEL_FMT | AV_OPT_TYPE_FLAG_ARRAY, .max = INT_MAX, .flags = FLAGS },
500 { "colorspaces", "array of supported color spaces", OFFSET(colorspaces),
501 AV_OPT_TYPE_INT | AV_OPT_TYPE_FLAG_ARRAY, .max = INT_MAX, .flags = FLAGS },
502 { "colorranges", "array of supported color ranges", OFFSET(colorranges),
503 AV_OPT_TYPE_INT | AV_OPT_TYPE_FLAG_ARRAY, .max = INT_MAX, .flags = FLAGS },
504
505 { NULL },
506 };
507 #undef FLAGS
508 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_AUDIO_PARAM
509 static const AVOption abuffersink_options[] = {
510 #if FF_API_BUFFERSINK_OPTS
511 { "sample_fmts", "set the supported sample formats", OFFSET(sample_fmts), AV_OPT_TYPE_BINARY, .flags = FLAGS | AV_OPT_FLAG_DEPRECATED },
512 { "sample_rates", "set the supported sample rates", OFFSET(sample_rates), AV_OPT_TYPE_BINARY, .flags = FLAGS | AV_OPT_FLAG_DEPRECATED },
513 { "ch_layouts", "set a '|'-separated list of supported channel layouts",
514 OFFSET(channel_layouts_str), AV_OPT_TYPE_STRING, .flags = FLAGS | AV_OPT_FLAG_DEPRECATED },
515 { "all_channel_counts", "accept all channel counts", OFFSET(all_channel_counts), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, FLAGS | AV_OPT_FLAG_DEPRECATED },
516 #endif
517
518 { "sample_formats", "array of supported sample formats", OFFSET(sample_formats),
519 AV_OPT_TYPE_SAMPLE_FMT | AV_OPT_TYPE_FLAG_ARRAY, .max = INT_MAX, .flags = FLAGS },
520 { "samplerates", "array of supported sample formats", OFFSET(samplerates),
521 AV_OPT_TYPE_INT | AV_OPT_TYPE_FLAG_ARRAY, .max = INT_MAX, .flags = FLAGS },
522 { "channel_layouts", "array of supported channel layouts", OFFSET(channel_layouts),
523 AV_OPT_TYPE_CHLAYOUT | AV_OPT_TYPE_FLAG_ARRAY, .flags = FLAGS },
524 { NULL },
525 };
526 #undef FLAGS
527
528 AVFILTER_DEFINE_CLASS(buffersink);
529 AVFILTER_DEFINE_CLASS(abuffersink);
530
531 const FFFilter ff_vsink_buffer = {
532 .p.name = "buffersink",
533 .p.description = NULL_IF_CONFIG_SMALL("Buffer video frames, and make them available to the end of the filter graph."),
534 .p.priv_class = &buffersink_class,
535 .p.outputs = NULL,
536 .priv_size = sizeof(BufferSinkContext),
537 .init = init_video,
538 .uninit = uninit,
539 .activate = activate,
540 FILTER_INPUTS(ff_video_default_filterpad),
541 FILTER_QUERY_FUNC2(vsink_query_formats),
542 };
543
544 static const AVFilterPad inputs_audio[] = {
545 {
546 .name = "default",
547 .type = AVMEDIA_TYPE_AUDIO,
548 .config_props = config_input_audio,
549 },
550 };
551
552 const FFFilter ff_asink_abuffer = {
553 .p.name = "abuffersink",
554 .p.description = NULL_IF_CONFIG_SMALL("Buffer audio frames, and make them available to the end of the filter graph."),
555 .p.priv_class = &abuffersink_class,
556 .p.outputs = NULL,
557 .priv_size = sizeof(BufferSinkContext),
558 .init = init_audio,
559 .uninit = uninit,
560 .activate = activate,
561 FILTER_INPUTS(inputs_audio),
562 FILTER_QUERY_FUNC2(asink_query_formats),
563 };
564