History

lavfi: add query_func2()

It differs from query_func() in accepting arrays of input/output format configurations to be filled as callback parameters. This allows to mark the filter context as const, ensuring it is not modified by this function, as it is not supposed to have any side effects beyond returning the supported formats.

Anton Khirnov committed 2 years ago

Commit eddffbe1 parent 01f2d956 files · +347 −36Browse files

Showing the changes to libavfilter (6 of 6 files). Show all

Unified · Split

6 files
  1. libavfilter/avfilter.h +50 −35
  2. libavfilter/avfiltergraph.c +43 −0
  3. libavfilter/filters.h +4 −0
  4. libavfilter/formats.c +148 −0
  5. libavfilter/formats.h +84 −0
  6. libavfilter/tests/filtfmts.c +18 −1
libavfilter/avfilter.h+50−35
@@ -98,6 +98,41 @@ const char *avfilter_pad_get_name(const AVFilterPad *pads, int pad_idx); · 97 unmodified lines
98 */98 */
99enum AVMediaType avfilter_pad_get_type(const AVFilterPad *pads, int pad_idx);99enum AVMediaType avfilter_pad_get_type(const AVFilterPad *pads, int pad_idx);
100 100
101/**
102 * Lists of formats / etc. supported by an end of a link.
103 *
104 * This structure is directly part of AVFilterLink, in two copies:
105 * one for the source filter, one for the destination filter.
106
107 * These lists are used for negotiating the format to actually be used,
108 * which will be loaded into the format and channel_layout members of
109 * AVFilterLink, when chosen.
110 */
111typedef struct AVFilterFormatsConfig {
112
113 /**
114 * List of supported formats (pixel or sample).
115 */
116 AVFilterFormats *formats;
117
118 /**
119 * Lists of supported sample rates, only for audio.
120 */
121 AVFilterFormats *samplerates;
122
123 /**
124 * Lists of supported channel layouts, only for audio.
125 */
126 AVFilterChannelLayouts *channel_layouts;
127
128 /**
129 * Lists of supported YUV color metadata, only for YUV video.
130 */
131 AVFilterFormats *color_spaces; ///< AVColorSpace
132 AVFilterFormats *color_ranges; ///< AVColorRange
133
134} AVFilterFormatsConfig;
135
101/**136/**
102 * The number of the filter inputs is not determined just by AVFilter.inputs.137 * The number of the filter inputs is not determined just by AVFilter.inputs.
103 * The filter might add additional inputs during initialization depending on the138 * The filter might add additional inputs during initialization depending on the
@@ -324,6 +359,21 @@ typedef struct AVFilter { · 220 unmodified lines
324 * AVERROR code otherwise359 * AVERROR code otherwise
325 */360 */
326 int (*query_func)(AVFilterContext *);361 int (*query_func)(AVFilterContext *);
362
363 /**
364 * Same as query_func(), except this function writes the results into
365 * provided arrays.
366 *
367 * @param cfg_in array of input format configurations with as many
368 * members as the filters has inputs (NULL when there are
369 * no inputs);
370 * @param cfg_out array of output format configurations with as many
371 * members as the filters has outputs (NULL when there
372 * are no outputs);
373 */
374 int (*query_func2)(const AVFilterContext *,
375 struct AVFilterFormatsConfig **cfg_in,
376 struct AVFilterFormatsConfig **cfg_out);
327 /**377 /**
328 * A pointer to an array of admissible pixel formats delimited378 * A pointer to an array of admissible pixel formats delimited
329 * by AV_PIX_FMT_NONE. The generic code will use this list379 * by AV_PIX_FMT_NONE. The generic code will use this list
@@ -492,41 +542,6 @@ struct AVFilterContext { · 162 unmodified lines
492 int extra_hw_frames;542 int extra_hw_frames;
493};543};
494 544
495/**
496 * Lists of formats / etc. supported by an end of a link.
497 *
498 * This structure is directly part of AVFilterLink, in two copies:
499 * one for the source filter, one for the destination filter.
500
501 * These lists are used for negotiating the format to actually be used,
502 * which will be loaded into the format and channel_layout members of
503 * AVFilterLink, when chosen.
504 */
505typedef struct AVFilterFormatsConfig {
506
507 /**
508 * List of supported formats (pixel or sample).
509 */
510 AVFilterFormats *formats;
511
512 /**
513 * Lists of supported sample rates, only for audio.
514 */
515 AVFilterFormats *samplerates;
516
517 /**
518 * Lists of supported channel layouts, only for audio.
519 */
520 AVFilterChannelLayouts *channel_layouts;
521
522 /**
523 * Lists of supported YUV color metadata, only for YUV video.
524 */
525 AVFilterFormats *color_spaces; ///< AVColorSpace
526 AVFilterFormats *color_ranges; ///< AVColorRange
527
528} AVFilterFormatsConfig;
529
530/**545/**
531 * A link between two filters. This contains pointers to the source and546 * A link between two filters. This contains pointers to the source and
532 * destination filters between which this link exists, and the indexes of547 * destination filters between which this link exists, and the indexes of
libavfilter/avfiltergraph.c+43−0
@@ -352,7 +352,50 @@ static int filter_query_formats(AVFilterContext *ctx) · 351 unmodified lines
352 ctx->name, av_err2str(ret));352 ctx->name, av_err2str(ret));
353 return ret;353 return ret;
354 }354 }
355 } else if (ctx->filter->formats_state == FF_FILTER_FORMATS_QUERY_FUNC2) {
356 AVFilterFormatsConfig *cfg_in_stack[64], *cfg_out_stack[64];
357 AVFilterFormatsConfig **cfg_in_dyn = NULL, **cfg_out_dyn = NULL;
358 AVFilterFormatsConfig **cfg_in, **cfg_out;
359
360 if (ctx->nb_inputs > FF_ARRAY_ELEMS(cfg_in_stack)) {
361 cfg_in_dyn = av_malloc_array(ctx->nb_inputs, sizeof(*cfg_in_dyn));
362 if (!cfg_in_dyn)
363 return AVERROR(ENOMEM);
364 cfg_in = cfg_in_dyn;
365 } else
366 cfg_in = ctx->nb_inputs ? cfg_in_stack : NULL;
367
368 for (unsigned i = 0; i < ctx->nb_inputs; i++) {
369 AVFilterLink *l = ctx->inputs[i];
370 cfg_in[i] = &l->outcfg;
371 }
372
373 if (ctx->nb_outputs > FF_ARRAY_ELEMS(cfg_out_stack)) {
374 cfg_out_dyn = av_malloc_array(ctx->nb_outputs, sizeof(*cfg_out_dyn));
375 if (!cfg_out_dyn)
376 return AVERROR(ENOMEM);
377 cfg_out = cfg_out_dyn;
378 } else
379 cfg_out = ctx->nb_outputs ? cfg_out_stack : NULL;
380
381 for (unsigned i = 0; i < ctx->nb_outputs; i++) {
382 AVFilterLink *l = ctx->outputs[i];
383 cfg_out[i] = &l->incfg;
384 }
385
386 ret = ctx->filter->formats.query_func2(ctx, cfg_in, cfg_out);
387 av_freep(&cfg_in_dyn);
388 av_freep(&cfg_out_dyn);
389 if (ret < 0) {
390 if (ret != AVERROR(EAGAIN))
391 av_log(ctx, AV_LOG_ERROR, "Query format failed for '%s': %s\n",
392 ctx->name, av_err2str(ret));
393 return ret;
394 }
395 }
355 396
397 if (ctx->filter->formats_state == FF_FILTER_FORMATS_QUERY_FUNC ||
398 ctx->filter->formats_state == FF_FILTER_FORMATS_QUERY_FUNC2) {
356 ret = filter_check_formats(ctx);399 ret = filter_check_formats(ctx);
357 if (ret < 0)400 if (ret < 0)
358 return ret;401 return ret;
libavfilter/filters.h+4−0
@@ -226,6 +226,7 @@ enum FilterFormatsState { · 225 unmodified lines
226 */226 */
227 FF_FILTER_FORMATS_PASSTHROUGH = 0,227 FF_FILTER_FORMATS_PASSTHROUGH = 0,
228 FF_FILTER_FORMATS_QUERY_FUNC, ///< formats.query active.228 FF_FILTER_FORMATS_QUERY_FUNC, ///< formats.query active.
229 FF_FILTER_FORMATS_QUERY_FUNC2, ///< formats.query_func2 active.
229 FF_FILTER_FORMATS_PIXFMT_LIST, ///< formats.pixels_list active.230 FF_FILTER_FORMATS_PIXFMT_LIST, ///< formats.pixels_list active.
230 FF_FILTER_FORMATS_SAMPLEFMTS_LIST, ///< formats.samples_list active.231 FF_FILTER_FORMATS_SAMPLEFMTS_LIST, ///< formats.samples_list active.
231 FF_FILTER_FORMATS_SINGLE_PIXFMT, ///< formats.pix_fmt active232 FF_FILTER_FORMATS_SINGLE_PIXFMT, ///< formats.pix_fmt active
@@ -235,6 +236,9 @@ enum FilterFormatsState { · 3 unmodified lines
235#define FILTER_QUERY_FUNC(func) \236#define FILTER_QUERY_FUNC(func) \
236 .formats.query_func = func, \237 .formats.query_func = func, \
237 .formats_state = FF_FILTER_FORMATS_QUERY_FUNC238 .formats_state = FF_FILTER_FORMATS_QUERY_FUNC
239#define FILTER_QUERY_FUNC2(func) \
240 .formats.query_func2 = func, \
241 .formats_state = FF_FILTER_FORMATS_QUERY_FUNC2
238#define FILTER_PIXFMTS_ARRAY(array) \242#define FILTER_PIXFMTS_ARRAY(array) \
239 .formats.pixels_list = array, \243 .formats.pixels_list = array, \
240 .formats_state = FF_FILTER_FORMATS_PIXFMT_LIST244 .formats_state = FF_FILTER_FORMATS_PIXFMT_LIST
libavfilter/formats.c+148−0
@@ -876,6 +876,153 @@ int ff_set_common_formats_from_list(AVFilterContext *ctx, const int *fmts) · 875 unmodified lines
876 return ff_set_common_formats(ctx, ff_make_format_list(fmts));876 return ff_set_common_formats(ctx, ff_make_format_list(fmts));
877}877}
878 878
879#define SET_COMMON_FORMATS2(ctx, cfg_in, cfg_out, fmts, media_type, \
880 ref_fn, unref_fn) \
881 if (!fmts) \
882 return AVERROR(ENOMEM); \
883 \
884 for (unsigned i = 0; i < ctx->nb_inputs; i++) { \
885 const AVFilterLink *const link = ctx->inputs[i]; \
886 if (!cfg_in[i]->fmts && \
887 (media_type == AVMEDIA_TYPE_UNKNOWN || \
888 link->type == media_type)) { \
889 int ret = ref_fn(fmts, &cfg_in[i]->fmts); \
890 if (ret < 0) { \
891 return ret; \
892 } \
893 } \
894 } \
895 for (unsigned i = 0; i < ctx->nb_outputs; i++) { \
896 const AVFilterLink *const link = ctx->outputs[i]; \
897 if (!cfg_out[i]->fmts && \
898 (media_type == AVMEDIA_TYPE_UNKNOWN || \
899 link->type == media_type)) { \
900 int ret = ref_fn(fmts, &cfg_out[i]->fmts); \
901 if (ret < 0) { \
902 return ret; \
903 } \
904 } \
905 } \
906 \
907 if (!fmts->refcount) \
908 unref_fn(&fmts); \
909 \
910 return 0;
911
912int ff_set_common_channel_layouts2(const AVFilterContext *ctx,
913 AVFilterFormatsConfig **cfg_in,
914 AVFilterFormatsConfig **cfg_out,
915 AVFilterChannelLayouts *channel_layouts)
916{
917 SET_COMMON_FORMATS2(ctx, cfg_in, cfg_out, channel_layouts, AVMEDIA_TYPE_AUDIO,
918 ff_channel_layouts_ref, ff_channel_layouts_unref);
919}
920
921int ff_set_common_channel_layouts_from_list2(const AVFilterContext *ctx,
922 AVFilterFormatsConfig **cfg_in,
923 AVFilterFormatsConfig **cfg_out,
924 const AVChannelLayout *fmts)
925{
926 return ff_set_common_channel_layouts2(ctx, cfg_in, cfg_out, ff_make_channel_layout_list(fmts));
927}
928
929int ff_set_common_all_channel_counts2(const AVFilterContext *ctx,
930 AVFilterFormatsConfig **cfg_in,
931 AVFilterFormatsConfig **cfg_out)
932{
933 return ff_set_common_channel_layouts2(ctx, cfg_in, cfg_out, ff_all_channel_counts());
934}
935
936int ff_set_common_samplerates2(const AVFilterContext *ctx,
937 AVFilterFormatsConfig **cfg_in,
938 AVFilterFormatsConfig **cfg_out,
939 AVFilterFormats *samplerates)
940{
941 SET_COMMON_FORMATS2(ctx, cfg_in, cfg_out, samplerates, AVMEDIA_TYPE_AUDIO,
942 ff_formats_ref, ff_formats_unref);
943}
944
945int ff_set_common_samplerates_from_list2(const AVFilterContext *ctx,
946 AVFilterFormatsConfig **cfg_in,
947 AVFilterFormatsConfig **cfg_out,
948 const int *samplerates)
949{
950 return ff_set_common_samplerates2(ctx, cfg_in, cfg_out, ff_make_format_list(samplerates));
951}
952
953int ff_set_common_all_samplerates2(const AVFilterContext *ctx,
954 AVFilterFormatsConfig **cfg_in,
955 AVFilterFormatsConfig **cfg_out)
956{
957 return ff_set_common_samplerates2(ctx, cfg_in, cfg_out, ff_all_samplerates());
958}
959
960int ff_set_common_color_spaces2(const AVFilterContext *ctx,
961 AVFilterFormatsConfig **cfg_in,
962 AVFilterFormatsConfig **cfg_out,
963 AVFilterFormats *color_spaces)
964{
965 SET_COMMON_FORMATS2(ctx, cfg_in, cfg_out, color_spaces, AVMEDIA_TYPE_VIDEO,
966 ff_formats_ref, ff_formats_unref);
967}
968
969int ff_set_common_color_spaces_from_list2(const AVFilterContext *ctx,
970 AVFilterFormatsConfig **cfg_in,
971 AVFilterFormatsConfig **cfg_out,
972 const int *color_ranges)
973{
974 return ff_set_common_color_spaces2(ctx, cfg_in, cfg_out, ff_make_format_list(color_ranges));
975}
976
977int ff_set_common_all_color_spaces2(const AVFilterContext *ctx,
978 AVFilterFormatsConfig **cfg_in,
979 AVFilterFormatsConfig **cfg_out)
980{
981 return ff_set_common_color_spaces2(ctx, cfg_in, cfg_out, ff_all_color_spaces());
982}
983
984int ff_set_common_color_ranges2(const AVFilterContext *ctx,
985 AVFilterFormatsConfig **cfg_in,
986 AVFilterFormatsConfig **cfg_out,
987 AVFilterFormats *color_ranges)
988{
989 SET_COMMON_FORMATS2(ctx, cfg_in, cfg_out, color_ranges, AVMEDIA_TYPE_VIDEO,
990 ff_formats_ref, ff_formats_unref);
991}
992
993int ff_set_common_color_ranges_from_list2(const AVFilterContext *ctx,
994 AVFilterFormatsConfig **cfg_in,
995 AVFilterFormatsConfig **cfg_out,
996 const int *color_ranges)
997{
998 return ff_set_common_color_ranges2(ctx, cfg_in, cfg_out, ff_make_format_list(color_ranges));
999}
1000
1001int ff_set_common_all_color_ranges2(const AVFilterContext *ctx,
1002 AVFilterFormatsConfig **cfg_in,
1003 AVFilterFormatsConfig **cfg_out)
1004{
1005 return ff_set_common_color_ranges2(ctx, cfg_in, cfg_out, ff_all_color_ranges());
1006}
1007
1008int ff_set_common_formats2(const AVFilterContext *ctx,
1009 AVFilterFormatsConfig **cfg_in,
1010 AVFilterFormatsConfig **cfg_out,
1011 AVFilterFormats *formats)
1012{
1013 SET_COMMON_FORMATS2(ctx, cfg_in, cfg_out, formats, AVMEDIA_TYPE_UNKNOWN,
1014 ff_formats_ref, ff_formats_unref);
1015}
1016
1017int ff_set_common_formats_from_list2(const AVFilterContext *ctx,
1018 AVFilterFormatsConfig **cfg_in,
1019 AVFilterFormatsConfig **cfg_out,
1020 const int *fmts)
1021{
1022 return ff_set_common_formats2(ctx, cfg_in, cfg_out, ff_make_format_list(fmts));
1023}
1024
1025
879int ff_default_query_formats(AVFilterContext *ctx)1026int ff_default_query_formats(AVFilterContext *ctx)
880{1027{
881 const AVFilter *const f = ctx->filter;1028 const AVFilter *const f = ctx->filter;
@@ -905,6 +1052,7 @@ int ff_default_query_formats(AVFilterContext *ctx) · 23 unmodified lines
905 /* Intended fallthrough */1052 /* Intended fallthrough */
906 case FF_FILTER_FORMATS_PASSTHROUGH:1053 case FF_FILTER_FORMATS_PASSTHROUGH:
907 case FF_FILTER_FORMATS_QUERY_FUNC:1054 case FF_FILTER_FORMATS_QUERY_FUNC:
1055 case FF_FILTER_FORMATS_QUERY_FUNC2:
908 type = AVMEDIA_TYPE_UNKNOWN;1056 type = AVMEDIA_TYPE_UNKNOWN;
909 formats = ff_all_formats(ctx->nb_inputs ? ctx->inputs [0]->type :1057 formats = ff_all_formats(ctx->nb_inputs ? ctx->inputs [0]->type :
910 ctx->nb_outputs ? ctx->outputs[0]->type :1058 ctx->nb_outputs ? ctx->outputs[0]->type :
libavfilter/formats.h+84−0
@@ -225,6 +225,90 @@ int ff_set_common_formats(AVFilterContext *ctx, AVFilterFormats *formats); · 224 unmodified lines
225av_warn_unused_result225av_warn_unused_result
226int ff_set_common_formats_from_list(AVFilterContext *ctx, const int *fmts);226int ff_set_common_formats_from_list(AVFilterContext *ctx, const int *fmts);
227 227
228/**
229 * Helpers for query_formats2() which set all free audio links to the same list
230 * of channel layouts/sample rates. If there are no links hooked to this list,
231 * the list is freed.
232 */
233av_warn_unused_result
234int ff_set_common_channel_layouts2(const AVFilterContext *ctx,
235 AVFilterFormatsConfig **cfg_in,
236 AVFilterFormatsConfig **cfg_out,
237 AVFilterChannelLayouts *channel_layouts);
238
239av_warn_unused_result
240int ff_set_common_channel_layouts_from_list2(const AVFilterContext *ctx,
241 AVFilterFormatsConfig **cfg_in,
242 AVFilterFormatsConfig **cfg_out,
243 const AVChannelLayout *fmts);
244av_warn_unused_result
245int ff_set_common_all_channel_counts2(const AVFilterContext *ctx,
246 AVFilterFormatsConfig **cfg_in,
247 AVFilterFormatsConfig **cfg_out);
248
249av_warn_unused_result
250int ff_set_common_samplerates2(const AVFilterContext *ctx,
251 AVFilterFormatsConfig **cfg_in,
252 AVFilterFormatsConfig **cfg_out,
253 AVFilterFormats *samplerates);
254
255av_warn_unused_result
256int ff_set_common_samplerates_from_list2(const AVFilterContext *ctx,
257 AVFilterFormatsConfig **cfg_in,
258 AVFilterFormatsConfig **cfg_out,
259 const int *samplerates);
260
261av_warn_unused_result
262int ff_set_common_all_samplerates2(const AVFilterContext *ctx,
263 AVFilterFormatsConfig **cfg_in,
264 AVFilterFormatsConfig **cfg_out);
265
266av_warn_unused_result
267int ff_set_common_color_spaces2(const AVFilterContext *ctx,
268 AVFilterFormatsConfig **cfg_in,
269 AVFilterFormatsConfig **cfg_out,
270 AVFilterFormats *color_spaces);
271
272av_warn_unused_result
273int ff_set_common_color_spaces_from_list2(const AVFilterContext *ctx,
274 AVFilterFormatsConfig **cfg_in,
275 AVFilterFormatsConfig **cfg_out,
276 const int *color_ranges);
277
278av_warn_unused_result
279int ff_set_common_all_color_spaces2(const AVFilterContext *ctx,
280 AVFilterFormatsConfig **cfg_in,
281 AVFilterFormatsConfig **cfg_out);
282
283av_warn_unused_result
284int ff_set_common_color_ranges2(const AVFilterContext *ctx,
285 AVFilterFormatsConfig **cfg_in,
286 AVFilterFormatsConfig **cfg_out,
287 AVFilterFormats *color_ranges);
288
289av_warn_unused_result
290int ff_set_common_color_ranges_from_list2(const AVFilterContext *ctx,
291 AVFilterFormatsConfig **cfg_in,
292 AVFilterFormatsConfig **cfg_out,
293 const int *color_ranges);
294
295av_warn_unused_result
296int ff_set_common_all_color_ranges2(const AVFilterContext *ctx,
297 AVFilterFormatsConfig **cfg_in,
298 AVFilterFormatsConfig **cfg_out);
299
300av_warn_unused_result
301int ff_set_common_formats2(const AVFilterContext *ctx,
302 AVFilterFormatsConfig **cfg_in,
303 AVFilterFormatsConfig **cfg_out,
304 AVFilterFormats *formats);
305
306av_warn_unused_result
307int ff_set_common_formats_from_list2(const AVFilterContext *ctx,
308 AVFilterFormatsConfig **cfg_in,
309 AVFilterFormatsConfig **cfg_out,
310 const int *fmts);
311
228av_warn_unused_result312av_warn_unused_result
229int ff_add_channel_layout(AVFilterChannelLayouts **l,313int ff_add_channel_layout(AVFilterChannelLayouts **l,
230 const AVChannelLayout *channel_layout);314 const AVChannelLayout *channel_layout);
libavfilter/tests/filtfmts.c+18−1
@@ -143,7 +143,24 @@ int main(int argc, char **argv) · 142 unmodified lines
143 143
144 if (filter->formats_state == FF_FILTER_FORMATS_QUERY_FUNC)144 if (filter->formats_state == FF_FILTER_FORMATS_QUERY_FUNC)
145 ret = filter->formats.query_func(filter_ctx);145 ret = filter->formats.query_func(filter_ctx);
146 else146 else if (filter->formats_state == FF_FILTER_FORMATS_QUERY_FUNC2) {
147 AVFilterFormatsConfig **cfg_in = NULL, **cfg_out = NULL;
148
149 if (filter_ctx->nb_inputs) {
150 cfg_in = av_malloc_array(filter_ctx->nb_inputs, sizeof(*cfg_in));
151 for (unsigned i = 0; i < filter_ctx->nb_inputs; i++)
152 cfg_in[i] = &filter_ctx->inputs[i]->outcfg;
153 }
154 if (filter_ctx->nb_outputs) {
155 cfg_out = av_malloc_array(filter_ctx->nb_outputs, sizeof(*cfg_out));
156 for (unsigned i = 0; i < filter_ctx->nb_outputs; i++)
157 cfg_out[i] = &filter_ctx->outputs[i]->incfg;
158 }
159
160 ret = filter->formats.query_func2(filter_ctx, cfg_in, cfg_out);
161 av_freep(&cfg_in);
162 av_freep(&cfg_out);
163 } else
147 ret = ff_default_query_formats(filter_ctx);164 ret = ff_default_query_formats(filter_ctx);
148 165
149 print_formats(filter_ctx);166 print_formats(filter_ctx);

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t