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.
Showing the changes to libavfilter/avfiltergraph.c (1 of 6 files). Show all
Unified · Split
| @@ -352,7 +352,50 @@ static int filter_query_formats(AVFilterContext *ctx) · 351 unmodified lines | ||
| 352 | 352 | ctx->name, av_err2str(ret)); |
| 353 | 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 | 399 | ret = filter_check_formats(ctx); |
| 357 | 400 | if (ret < 0) |
| 358 | 401 | return ret; |