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

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
9898 */
9999 enum AVMediaType avfilter_pad_get_type(const AVFilterPad *pads, int pad_idx);
100100
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+ */
111+typedef 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+
101136 /**
102137 * The number of the filter inputs is not determined just by AVFilter.inputs.
103138 * The filter might add additional inputs during initialization depending on the
@@ -324,6 +359,21 @@ typedef struct AVFilter { · 220 unmodified lines
324359 * AVERROR code otherwise
325360 */
326361 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);
327377 /**
328378 * A pointer to an array of admissible pixel formats delimited
329379 * by AV_PIX_FMT_NONE. The generic code will use this list
@@ -492,41 +542,6 @@ struct AVFilterContext { · 162 unmodified lines
492542 int extra_hw_frames;
493543 };
494544
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− */
505−typedef 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−
530545 /**
531546 * A link between two filters. This contains pointers to the source and
532547 * 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
352352 ctx->name, av_err2str(ret));
353353 return ret;
354354 }
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+ }
355396
397+ if (ctx->filter->formats_state == FF_FILTER_FORMATS_QUERY_FUNC ||
398+ ctx->filter->formats_state == FF_FILTER_FORMATS_QUERY_FUNC2) {
356399 ret = filter_check_formats(ctx);
357400 if (ret < 0)
358401 return ret;
libavfilter/filters.h+4−0
@@ -226,6 +226,7 @@ enum FilterFormatsState { · 225 unmodified lines
226226 */
227227 FF_FILTER_FORMATS_PASSTHROUGH = 0,
228228 FF_FILTER_FORMATS_QUERY_FUNC, ///< formats.query active.
229+ FF_FILTER_FORMATS_QUERY_FUNC2, ///< formats.query_func2 active.
229230 FF_FILTER_FORMATS_PIXFMT_LIST, ///< formats.pixels_list active.
230231 FF_FILTER_FORMATS_SAMPLEFMTS_LIST, ///< formats.samples_list active.
231232 FF_FILTER_FORMATS_SINGLE_PIXFMT, ///< formats.pix_fmt active
@@ -235,6 +236,9 @@ enum FilterFormatsState { · 3 unmodified lines
235236 #define FILTER_QUERY_FUNC(func) \
236237 .formats.query_func = func, \
237238 .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
238242 #define FILTER_PIXFMTS_ARRAY(array) \
239243 .formats.pixels_list = array, \
240244 .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
876876 return ff_set_common_formats(ctx, ff_make_format_list(fmts));
877877 }
878878
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+
912+int 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+
921+int 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+
929+int 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+
936+int 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+
945+int 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+
953+int 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+
960+int 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+
969+int 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+
977+int 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+
984+int 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+
993+int 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+
1001+int 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+
1008+int 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+
1017+int 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+
8791026 int ff_default_query_formats(AVFilterContext *ctx)
8801027 {
8811028 const AVFilter *const f = ctx->filter;
@@ -905,6 +1052,7 @@ int ff_default_query_formats(AVFilterContext *ctx) · 23 unmodified lines
9051052 /* Intended fallthrough */
9061053 case FF_FILTER_FORMATS_PASSTHROUGH:
9071054 case FF_FILTER_FORMATS_QUERY_FUNC:
1055+ case FF_FILTER_FORMATS_QUERY_FUNC2:
9081056 type = AVMEDIA_TYPE_UNKNOWN;
9091057 formats = ff_all_formats(ctx->nb_inputs ? ctx->inputs [0]->type :
9101058 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
225225 av_warn_unused_result
226226 int ff_set_common_formats_from_list(AVFilterContext *ctx, const int *fmts);
227227
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+ */
233+av_warn_unused_result
234+int ff_set_common_channel_layouts2(const AVFilterContext *ctx,
235+ AVFilterFormatsConfig **cfg_in,
236+ AVFilterFormatsConfig **cfg_out,
237+ AVFilterChannelLayouts *channel_layouts);
238+
239+av_warn_unused_result
240+int ff_set_common_channel_layouts_from_list2(const AVFilterContext *ctx,
241+ AVFilterFormatsConfig **cfg_in,
242+ AVFilterFormatsConfig **cfg_out,
243+ const AVChannelLayout *fmts);
244+av_warn_unused_result
245+int ff_set_common_all_channel_counts2(const AVFilterContext *ctx,
246+ AVFilterFormatsConfig **cfg_in,
247+ AVFilterFormatsConfig **cfg_out);
248+
249+av_warn_unused_result
250+int ff_set_common_samplerates2(const AVFilterContext *ctx,
251+ AVFilterFormatsConfig **cfg_in,
252+ AVFilterFormatsConfig **cfg_out,
253+ AVFilterFormats *samplerates);
254+
255+av_warn_unused_result
256+int ff_set_common_samplerates_from_list2(const AVFilterContext *ctx,
257+ AVFilterFormatsConfig **cfg_in,
258+ AVFilterFormatsConfig **cfg_out,
259+ const int *samplerates);
260+
261+av_warn_unused_result
262+int ff_set_common_all_samplerates2(const AVFilterContext *ctx,
263+ AVFilterFormatsConfig **cfg_in,
264+ AVFilterFormatsConfig **cfg_out);
265+
266+av_warn_unused_result
267+int ff_set_common_color_spaces2(const AVFilterContext *ctx,
268+ AVFilterFormatsConfig **cfg_in,
269+ AVFilterFormatsConfig **cfg_out,
270+ AVFilterFormats *color_spaces);
271+
272+av_warn_unused_result
273+int ff_set_common_color_spaces_from_list2(const AVFilterContext *ctx,
274+ AVFilterFormatsConfig **cfg_in,
275+ AVFilterFormatsConfig **cfg_out,
276+ const int *color_ranges);
277+
278+av_warn_unused_result
279+int ff_set_common_all_color_spaces2(const AVFilterContext *ctx,
280+ AVFilterFormatsConfig **cfg_in,
281+ AVFilterFormatsConfig **cfg_out);
282+
283+av_warn_unused_result
284+int ff_set_common_color_ranges2(const AVFilterContext *ctx,
285+ AVFilterFormatsConfig **cfg_in,
286+ AVFilterFormatsConfig **cfg_out,
287+ AVFilterFormats *color_ranges);
288+
289+av_warn_unused_result
290+int ff_set_common_color_ranges_from_list2(const AVFilterContext *ctx,
291+ AVFilterFormatsConfig **cfg_in,
292+ AVFilterFormatsConfig **cfg_out,
293+ const int *color_ranges);
294+
295+av_warn_unused_result
296+int ff_set_common_all_color_ranges2(const AVFilterContext *ctx,
297+ AVFilterFormatsConfig **cfg_in,
298+ AVFilterFormatsConfig **cfg_out);
299+
300+av_warn_unused_result
301+int ff_set_common_formats2(const AVFilterContext *ctx,
302+ AVFilterFormatsConfig **cfg_in,
303+ AVFilterFormatsConfig **cfg_out,
304+ AVFilterFormats *formats);
305+
306+av_warn_unused_result
307+int ff_set_common_formats_from_list2(const AVFilterContext *ctx,
308+ AVFilterFormatsConfig **cfg_in,
309+ AVFilterFormatsConfig **cfg_out,
310+ const int *fmts);
311+
228312 av_warn_unused_result
229313 int ff_add_channel_layout(AVFilterChannelLayouts **l,
230314 const AVChannelLayout *channel_layout);
libavfilter/tests/filtfmts.c+18−1
@@ -143,7 +143,24 @@ int main(int argc, char **argv) · 142 unmodified lines
143143
144144 if (filter->formats_state == FF_FILTER_FORMATS_QUERY_FUNC)
145145 ret = filter->formats.query_func(filter_ctx);
146− else
146+ 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
147164 ret = ff_default_query_formats(filter_ctx);
148165
149166 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