Skip to content

Commit eddffbe

Browse files
committed
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.
1 parent 01f2d95 commit eddffbe

File tree

6 files changed

+347
-36
lines changed

6 files changed

+347
-36
lines changed

libavfilter/avfilter.h

Lines changed: 50 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,41 @@ const char *avfilter_pad_get_name(const AVFilterPad *pads, int pad_idx);
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 {
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 {
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

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,50 @@ static int filter_query_formats(AVFilterContext *ctx)
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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,7 @@ enum FilterFormatsState {
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 {
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

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -876,6 +876,153 @@ int ff_set_common_formats_from_list(AVFilterContext *ctx, const int *fmts)
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)
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 :

0 commit comments

Comments
 (0)