Move validation from init to query_formats().
Accept the formats lists as binary options.
Signed-off-by: Nicolas George <nicolas.george@normalesup.org>
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
... | ... |
@@ -1768,9 +1768,10 @@ Below is a description of the currently available audio sinks. |
1768 | 1768 |
Buffer audio frames, and make them available to the end of filter chain. |
1769 | 1769 |
|
1770 | 1770 |
This sink is mainly intended for programmatic use, in particular |
1771 |
-through the interface defined in @file{libavfilter/buffersink.h}. |
|
1771 |
+through the interface defined in @file{libavfilter/buffersink.h} |
|
1772 |
+or the options system. |
|
1772 | 1773 |
|
1773 |
-It requires a pointer to an AVABufferSinkContext structure, which |
|
1774 |
+It accepts a pointer to an AVABufferSinkContext structure, which |
|
1774 | 1775 |
defines the incoming buffers' formats, to be passed as the opaque |
1775 | 1776 |
parameter to @code{avfilter_init_filter} for initialization. |
1776 | 1777 |
|
... | ... |
@@ -1780,13 +1781,6 @@ Null audio sink, do absolutely nothing with the input audio. It is |
1780 | 1780 |
mainly useful as a template and to be employed in analysis / debugging |
1781 | 1781 |
tools. |
1782 | 1782 |
|
1783 |
-@section abuffersink |
|
1784 |
-This sink is intended for programmatic use. Frames that arrive on this sink can |
|
1785 |
-be retrieved by the calling program using the interface defined in |
|
1786 |
-@file{libavfilter/buffersink.h}. |
|
1787 |
- |
|
1788 |
-This filter accepts no parameters. |
|
1789 |
- |
|
1790 | 1783 |
@c man end AUDIO SINKS |
1791 | 1784 |
|
1792 | 1785 |
@chapter Video Filters |
... | ... |
@@ -6298,12 +6292,12 @@ Buffer video frames, and make them available to the end of the filter |
6298 | 6298 |
graph. |
6299 | 6299 |
|
6300 | 6300 |
This sink is mainly intended for a programmatic use, in particular |
6301 |
-through the interface defined in @file{libavfilter/buffersink.h}. |
|
6301 |
+through the interface defined in @file{libavfilter/buffersink.h} |
|
6302 |
+or the options system. |
|
6302 | 6303 |
|
6303 |
-It does not require a string parameter in input, but you need to |
|
6304 |
-specify a pointer to a list of supported pixel formats terminated by |
|
6305 |
--1 in the opaque parameter provided to @code{avfilter_init_filter} |
|
6306 |
-when initializing this sink. |
|
6304 |
+It accepts a pointer to an AVBufferSinkContext structure, which |
|
6305 |
+defines the incoming buffers' formats, to be passed as the opaque |
|
6306 |
+parameter to @code{avfilter_init_filter} for initialization. |
|
6307 | 6307 |
|
6308 | 6308 |
@section nullsink |
6309 | 6309 |
|
... | ... |
@@ -28,6 +28,7 @@ |
28 | 28 |
#include "libavutil/channel_layout.h" |
29 | 29 |
#include "libavutil/common.h" |
30 | 30 |
#include "libavutil/mathematics.h" |
31 |
+#include "libavutil/opt.h" |
|
31 | 32 |
|
32 | 33 |
#include "audio.h" |
33 | 34 |
#include "avfilter.h" |
... | ... |
@@ -35,23 +36,32 @@ |
35 | 35 |
#include "internal.h" |
36 | 36 |
|
37 | 37 |
typedef struct { |
38 |
+ const AVClass *class; |
|
38 | 39 |
AVFifoBuffer *fifo; ///< FIFO buffer of video frame references |
39 | 40 |
unsigned warning_limit; |
40 | 41 |
|
41 | 42 |
/* only used for video */ |
42 | 43 |
enum AVPixelFormat *pixel_fmts; ///< list of accepted pixel formats, must be terminated with -1 |
44 |
+ int pixel_fmts_size; |
|
43 | 45 |
|
44 | 46 |
/* only used for audio */ |
45 | 47 |
enum AVSampleFormat *sample_fmts; ///< list of accepted sample formats, terminated by AV_SAMPLE_FMT_NONE |
48 |
+ int sample_fmts_size; |
|
46 | 49 |
int64_t *channel_layouts; ///< list of accepted channel layouts, terminated by -1 |
50 |
+ int channel_layouts_size; |
|
51 |
+ int *channel_counts; ///< list of accepted channel counts, terminated by -1 |
|
52 |
+ int channel_counts_size; |
|
47 | 53 |
int all_channel_counts; |
48 | 54 |
int *sample_rates; ///< list of accepted sample rates, terminated by -1 |
55 |
+ int sample_rates_size; |
|
49 | 56 |
|
50 | 57 |
/* only used for compat API */ |
51 | 58 |
AVAudioFifo *audio_fifo; ///< FIFO for audio samples |
52 | 59 |
int64_t next_pts; ///< interpolating audio pts |
53 | 60 |
} BufferSinkContext; |
54 | 61 |
|
62 |
+#define NB_ITEMS(list) (list ## _size / sizeof(*list)) |
|
63 |
+ |
|
55 | 64 |
static av_cold void uninit(AVFilterContext *ctx) |
56 | 65 |
{ |
57 | 66 |
BufferSinkContext *sink = ctx->priv; |
... | ... |
@@ -68,10 +78,6 @@ static av_cold void uninit(AVFilterContext *ctx) |
68 | 68 |
av_fifo_free(sink->fifo); |
69 | 69 |
sink->fifo = NULL; |
70 | 70 |
} |
71 |
- av_freep(&sink->pixel_fmts); |
|
72 |
- av_freep(&sink->sample_fmts); |
|
73 |
- av_freep(&sink->sample_rates); |
|
74 |
- av_freep(&sink->channel_layouts); |
|
75 | 71 |
} |
76 | 72 |
|
77 | 73 |
static int add_buffer_ref(AVFilterContext *ctx, AVFrame *ref) |
... | ... |
@@ -286,6 +292,7 @@ static int attribute_align_arg compat_read(AVFilterContext *ctx, AVFilterBufferR |
286 | 286 |
if (ret < 0) |
287 | 287 |
goto fail; |
288 | 288 |
|
289 |
+ AV_NOWARN_DEPRECATED( |
|
289 | 290 |
if (ctx->inputs[0]->type == AVMEDIA_TYPE_VIDEO) { |
290 | 291 |
buf = avfilter_get_video_buffer_ref_from_arrays(frame->data, frame->linesize, |
291 | 292 |
AV_PERM_READ, |
... | ... |
@@ -304,6 +311,7 @@ static int attribute_align_arg compat_read(AVFilterContext *ctx, AVFilterBufferR |
304 | 304 |
} |
305 | 305 |
|
306 | 306 |
avfilter_copy_frame_props(buf, frame); |
307 |
+ ) |
|
307 | 308 |
|
308 | 309 |
buf->buf->priv = frame; |
309 | 310 |
buf->buf->free = compat_free_buffer; |
... | ... |
@@ -366,13 +374,11 @@ static av_cold int vsink_init(AVFilterContext *ctx, void *opaque) |
366 | 366 |
{ |
367 | 367 |
BufferSinkContext *buf = ctx->priv; |
368 | 368 |
AVBufferSinkParams *params = opaque; |
369 |
+ int ret; |
|
369 | 370 |
|
370 |
- if (params && params->pixel_fmts) { |
|
371 |
- const int *pixel_fmts = params->pixel_fmts; |
|
372 |
- |
|
373 |
- buf->pixel_fmts = ff_copy_int_list(pixel_fmts); |
|
374 |
- if (!buf->pixel_fmts) |
|
375 |
- return AVERROR(ENOMEM); |
|
371 |
+ if (params) { |
|
372 |
+ if ((ret = av_opt_set_int_list(buf, "pix_fmts", params->pixel_fmts, AV_PIX_FMT_NONE, 0)) < 0) |
|
373 |
+ return ret; |
|
376 | 374 |
} |
377 | 375 |
|
378 | 376 |
return common_init(ctx); |
... | ... |
@@ -381,64 +387,41 @@ static av_cold int vsink_init(AVFilterContext *ctx, void *opaque) |
381 | 381 |
static int vsink_query_formats(AVFilterContext *ctx) |
382 | 382 |
{ |
383 | 383 |
BufferSinkContext *buf = ctx->priv; |
384 |
+ AVFilterFormats *formats = NULL; |
|
385 |
+ unsigned i; |
|
386 |
+ int ret; |
|
384 | 387 |
|
385 |
- if (buf->pixel_fmts) |
|
386 |
- ff_set_common_formats(ctx, ff_make_format_list(buf->pixel_fmts)); |
|
387 |
- else |
|
388 |
+ if (buf->pixel_fmts_size % sizeof(*buf->pixel_fmts)) { |
|
389 |
+ av_log(ctx, AV_LOG_ERROR, "Invalid size for format list\n"); |
|
390 |
+ return AVERROR(EINVAL); |
|
391 |
+ } |
|
392 |
+ |
|
393 |
+ if (buf->pixel_fmts_size) { |
|
394 |
+ for (i = 0; i < NB_ITEMS(buf->pixel_fmts); i++) |
|
395 |
+ if ((ret = ff_add_format(&formats, buf->pixel_fmts[i])) < 0) |
|
396 |
+ return ret; |
|
397 |
+ ff_set_common_formats(ctx, formats); |
|
398 |
+ } else { |
|
388 | 399 |
ff_default_query_formats(ctx); |
400 |
+ } |
|
389 | 401 |
|
390 | 402 |
return 0; |
391 | 403 |
} |
392 | 404 |
|
393 |
-static int64_t *concat_channels_lists(const int64_t *layouts, const int *counts) |
|
394 |
-{ |
|
395 |
- int nb_layouts = 0, nb_counts = 0, i; |
|
396 |
- int64_t *list; |
|
397 |
- |
|
398 |
- if (layouts) |
|
399 |
- for (; layouts[nb_layouts] != -1; nb_layouts++); |
|
400 |
- if (counts) |
|
401 |
- for (; counts[nb_counts] != -1; nb_counts++); |
|
402 |
- if (nb_counts > INT_MAX - 1 - nb_layouts) |
|
403 |
- return NULL; |
|
404 |
- if (!(list = av_calloc(nb_layouts + nb_counts + 1, sizeof(*list)))) |
|
405 |
- return NULL; |
|
406 |
- for (i = 0; i < nb_layouts; i++) |
|
407 |
- list[i] = layouts[i]; |
|
408 |
- for (i = 0; i < nb_counts; i++) |
|
409 |
- list[nb_layouts + i] = FF_COUNT2LAYOUT(counts[i]); |
|
410 |
- list[nb_layouts + nb_counts] = -1; |
|
411 |
- return list; |
|
412 |
-} |
|
413 |
- |
|
414 | 405 |
static av_cold int asink_init(AVFilterContext *ctx, void *opaque) |
415 | 406 |
{ |
416 | 407 |
BufferSinkContext *buf = ctx->priv; |
417 | 408 |
AVABufferSinkParams *params = opaque; |
409 |
+ int ret; |
|
418 | 410 |
|
419 |
- if (params && params->sample_fmts) { |
|
420 |
- buf->sample_fmts = ff_copy_int_list(params->sample_fmts); |
|
421 |
- if (!buf->sample_fmts) |
|
422 |
- return AVERROR(ENOMEM); |
|
423 |
- } |
|
424 |
- if (params && params->sample_rates) { |
|
425 |
- buf->sample_rates = ff_copy_int_list(params->sample_rates); |
|
426 |
- if (!buf->sample_rates) |
|
427 |
- return AVERROR(ENOMEM); |
|
428 |
- } |
|
429 |
- if (params && (params->channel_layouts || params->channel_counts)) { |
|
430 |
- if (params->all_channel_counts) { |
|
431 |
- av_log(ctx, AV_LOG_ERROR, |
|
432 |
- "Conflicting all_channel_counts and list in parameters\n"); |
|
433 |
- return AVERROR(EINVAL); |
|
434 |
- } |
|
435 |
- buf->channel_layouts = concat_channels_lists(params->channel_layouts, |
|
436 |
- params->channel_counts); |
|
437 |
- if (!buf->channel_layouts) |
|
438 |
- return AVERROR(ENOMEM); |
|
411 |
+ if (params) { |
|
412 |
+ if ((ret = av_opt_set_int_list(buf, "sample_fmts", params->sample_fmts, AV_SAMPLE_FMT_NONE, 0)) < 0 || |
|
413 |
+ (ret = av_opt_set_int_list(buf, "sample_rates", params->sample_rates, -1, 0)) < 0 || |
|
414 |
+ (ret = av_opt_set_int_list(buf, "channel_layouts", params->channel_layouts, -1, 0)) < 0 || |
|
415 |
+ (ret = av_opt_set_int_list(buf, "channel_counts", params->channel_counts, -1, 0)) < 0 || |
|
416 |
+ (ret = av_opt_set_int(buf, "all_channel_counts", params->all_channel_counts, 0)) < 0) |
|
417 |
+ return ret; |
|
439 | 418 |
} |
440 |
- if (params) |
|
441 |
- buf->all_channel_counts = params->all_channel_counts; |
|
442 | 419 |
return common_init(ctx); |
443 | 420 |
} |
444 | 421 |
|
... | ... |
@@ -447,32 +430,92 @@ static int asink_query_formats(AVFilterContext *ctx) |
447 | 447 |
BufferSinkContext *buf = ctx->priv; |
448 | 448 |
AVFilterFormats *formats = NULL; |
449 | 449 |
AVFilterChannelLayouts *layouts = NULL; |
450 |
+ unsigned i; |
|
451 |
+ int ret; |
|
450 | 452 |
|
451 |
- if (buf->sample_fmts) { |
|
452 |
- if (!(formats = ff_make_format_list(buf->sample_fmts))) |
|
453 |
- return AVERROR(ENOMEM); |
|
453 |
+ if (buf->sample_fmts_size % sizeof(*buf->sample_fmts) || |
|
454 |
+ buf->sample_rates_size % sizeof(*buf->sample_rates) || |
|
455 |
+ buf->channel_layouts_size % sizeof(*buf->channel_layouts) || |
|
456 |
+ buf->channel_counts_size % sizeof(*buf->channel_counts)) { |
|
457 |
+ av_log(ctx, AV_LOG_ERROR, "Invalid size for format lists\n"); |
|
458 |
+#define LOG_ERROR(field) \ |
|
459 |
+ if (buf->field ## _size % sizeof(*buf->field)) \ |
|
460 |
+ av_log(ctx, AV_LOG_ERROR, " " #field " is %d, should be " \ |
|
461 |
+ "multiple of %d\n", \ |
|
462 |
+ buf->field ## _size, (int)sizeof(*buf->field)); |
|
463 |
+ LOG_ERROR(sample_fmts); |
|
464 |
+ LOG_ERROR(sample_rates); |
|
465 |
+ LOG_ERROR(channel_layouts); |
|
466 |
+ LOG_ERROR(channel_counts); |
|
467 |
+#undef LOG_ERROR |
|
468 |
+ return AVERROR(EINVAL); |
|
469 |
+ } |
|
470 |
+ |
|
471 |
+ if (buf->sample_fmts_size) { |
|
472 |
+ for (i = 0; i < NB_ITEMS(buf->sample_fmts); i++) |
|
473 |
+ if ((ret = ff_add_format(&formats, buf->sample_fmts[i])) < 0) |
|
474 |
+ return ret; |
|
454 | 475 |
ff_set_common_formats(ctx, formats); |
455 | 476 |
} |
456 | 477 |
|
457 |
- if (buf->channel_layouts || buf->all_channel_counts) { |
|
458 |
- layouts = buf->all_channel_counts ? ff_all_channel_counts() : |
|
459 |
- avfilter_make_format64_list(buf->channel_layouts); |
|
460 |
- if (!layouts) |
|
461 |
- return AVERROR(ENOMEM); |
|
478 |
+ if (buf->channel_layouts_size || buf->channel_counts_size || |
|
479 |
+ buf->all_channel_counts) { |
|
480 |
+ for (i = 0; i < NB_ITEMS(buf->channel_layouts); i++) |
|
481 |
+ if ((ret = ff_add_channel_layout(&layouts, buf->channel_layouts[i])) < 0) |
|
482 |
+ return ret; |
|
483 |
+ for (i = 0; i < NB_ITEMS(buf->channel_counts); i++) |
|
484 |
+ if ((ret = ff_add_channel_layout(&layouts, FF_COUNT2LAYOUT(buf->channel_counts[i]))) < 0) |
|
485 |
+ return ret; |
|
486 |
+ if (buf->all_channel_counts) { |
|
487 |
+ if (layouts) |
|
488 |
+ av_log(ctx, AV_LOG_WARNING, |
|
489 |
+ "Conflicting all_channel_counts and list in options\n"); |
|
490 |
+ else if (!(layouts = ff_all_channel_counts())) |
|
491 |
+ return AVERROR(ENOMEM); |
|
492 |
+ } |
|
462 | 493 |
ff_set_common_channel_layouts(ctx, layouts); |
463 | 494 |
} |
464 | 495 |
|
465 |
- if (buf->sample_rates) { |
|
466 |
- formats = ff_make_format_list(buf->sample_rates); |
|
467 |
- if (!formats) |
|
468 |
- return AVERROR(ENOMEM); |
|
496 |
+ if (buf->sample_rates_size) { |
|
497 |
+ formats = NULL; |
|
498 |
+ for (i = 0; i < NB_ITEMS(buf->sample_rates); i++) |
|
499 |
+ if ((ret = ff_add_format(&formats, buf->sample_rates[i])) < 0) |
|
500 |
+ return ret; |
|
469 | 501 |
ff_set_common_samplerates(ctx, formats); |
470 | 502 |
} |
471 | 503 |
|
472 | 504 |
return 0; |
473 | 505 |
} |
474 | 506 |
|
507 |
+#define OFFSET(x) offsetof(BufferSinkContext, x) |
|
508 |
+#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM |
|
509 |
+static const AVOption buffersink_options[] = { |
|
510 |
+ { "pix_fmts", "set the supported pixel formats", OFFSET(pixel_fmts), AV_OPT_TYPE_BINARY, .flags = FLAGS }, |
|
511 |
+ { NULL }, |
|
512 |
+}; |
|
513 |
+#undef FLAGS |
|
514 |
+#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM |
|
515 |
+static const AVOption abuffersink_options[] = { |
|
516 |
+ { "sample_fmts", "set the supported sample formats", OFFSET(sample_fmts), AV_OPT_TYPE_BINARY, .flags = FLAGS }, |
|
517 |
+ { "sample_rates", "set the supported sample rates", OFFSET(sample_rates), AV_OPT_TYPE_BINARY, .flags = FLAGS }, |
|
518 |
+ { "channel_layouts", "set the supported channel layouts", OFFSET(channel_layouts), AV_OPT_TYPE_BINARY, .flags = FLAGS }, |
|
519 |
+ { "channel_counts", "set the supported channel counts", OFFSET(channel_counts), AV_OPT_TYPE_BINARY, .flags = FLAGS }, |
|
520 |
+ { "all_channel_counts", "accept all channel counts", OFFSET(all_channel_counts), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, FLAGS }, |
|
521 |
+ { NULL }, |
|
522 |
+}; |
|
523 |
+#undef FLAGS |
|
524 |
+static const char *const shorthand[] = { NULL }; |
|
525 |
+ |
|
526 |
+AVFILTER_DEFINE_CLASS(buffersink); |
|
527 |
+AVFILTER_DEFINE_CLASS(abuffersink); |
|
528 |
+ |
|
475 | 529 |
#if FF_API_AVFILTERBUFFER |
530 |
+ |
|
531 |
+#define ffbuffersink_options buffersink_options |
|
532 |
+#define ffabuffersink_options abuffersink_options |
|
533 |
+AVFILTER_DEFINE_CLASS(ffbuffersink); |
|
534 |
+AVFILTER_DEFINE_CLASS(ffabuffersink); |
|
535 |
+ |
|
476 | 536 |
static const AVFilterPad ffbuffersink_inputs[] = { |
477 | 537 |
{ |
478 | 538 |
.name = "default", |
... | ... |
@@ -486,6 +529,8 @@ AVFilter avfilter_vsink_ffbuffersink = { |
486 | 486 |
.name = "ffbuffersink", |
487 | 487 |
.description = NULL_IF_CONFIG_SMALL("Buffer video frames, and make them available to the end of the filter graph."), |
488 | 488 |
.priv_size = sizeof(BufferSinkContext), |
489 |
+ .priv_class = &ffbuffersink_class, |
|
490 |
+ .shorthand = shorthand, |
|
489 | 491 |
.init_opaque = vsink_init, |
490 | 492 |
.uninit = uninit, |
491 | 493 |
|
... | ... |
@@ -509,6 +554,8 @@ AVFilter avfilter_asink_ffabuffersink = { |
509 | 509 |
.init_opaque = asink_init, |
510 | 510 |
.uninit = uninit, |
511 | 511 |
.priv_size = sizeof(BufferSinkContext), |
512 |
+ .priv_class = &ffabuffersink_class, |
|
513 |
+ .shorthand = shorthand, |
|
512 | 514 |
.query_formats = asink_query_formats, |
513 | 515 |
.inputs = ffabuffersink_inputs, |
514 | 516 |
.outputs = NULL, |
... | ... |
@@ -528,6 +575,8 @@ AVFilter avfilter_vsink_buffer = { |
528 | 528 |
.name = "buffersink", |
529 | 529 |
.description = NULL_IF_CONFIG_SMALL("Buffer video frames, and make them available to the end of the filter graph."), |
530 | 530 |
.priv_size = sizeof(BufferSinkContext), |
531 |
+ .priv_class = &buffersink_class, |
|
532 |
+ .shorthand = shorthand, |
|
531 | 533 |
.init_opaque = vsink_init, |
532 | 534 |
.uninit = uninit, |
533 | 535 |
|
... | ... |
@@ -548,6 +597,8 @@ static const AVFilterPad avfilter_asink_abuffer_inputs[] = { |
548 | 548 |
AVFilter avfilter_asink_abuffer = { |
549 | 549 |
.name = "abuffersink", |
550 | 550 |
.description = NULL_IF_CONFIG_SMALL("Buffer audio frames, and make them available to the end of the filter graph."), |
551 |
+ .priv_class = &abuffersink_class, |
|
552 |
+ .shorthand = shorthand, |
|
551 | 553 |
.priv_size = sizeof(BufferSinkContext), |
552 | 554 |
.init_opaque = asink_init, |
553 | 555 |
.uninit = uninit, |