Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions doc/APIchanges
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ libavutil: 2021-04-27

API changes, most recent first:

2022-10-11 - xxxxxxxxxx - lavf 59.50.100 - avfilter.h
Add add avfilter_print_config_formats().

2022-10-11 - xxxxxxxxxx - lavu 57.39.101 - pixfmt.h
Add AV_PIX_FMT_RGBF32 and AV_PIX_FMT_RGBAF32.

Expand Down
37 changes: 26 additions & 11 deletions fftools/opt_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,7 @@ static void show_help_filter(const char *name)
{
#if CONFIG_AVFILTER
const AVFilter *f = avfilter_get_by_name(name);
AVBPrint bp;
int i, count;

if (!name) {
Expand All @@ -514,40 +515,54 @@ static void show_help_filter(const char *name)
return;
}

printf("Filter %s\n", f->name);
av_bprint_init(&bp, 0, AV_BPRINT_SIZE_UNLIMITED);
av_log_set_callback(NULL);

av_bprintf(&bp, "Filter %s\n", f->name);
if (f->description)
printf(" %s\n", f->description);
av_bprintf(&bp, " %s\n", f->description);

if (f->flags & AVFILTER_FLAG_SLICE_THREADS)
printf(" slice threading supported\n");
av_bprintf(&bp, " slice threading supported\n");

printf(" Inputs:\n");
av_bprintf(&bp, " Inputs:\n");
count = avfilter_filter_pad_count(f, 0);
for (i = 0; i < count; i++) {
printf(" #%d: %s (%s)\n", i, avfilter_pad_get_name(f->inputs, i),
av_bprintf(&bp, " #%d: %s (%s), Formats: ", i, avfilter_pad_get_name(f->inputs, i),
av_get_media_type_string(avfilter_pad_get_type(f->inputs, i)));

avfilter_print_config_formats(&bp, f, 0, i);
av_bprintf(&bp, "\n");
}
if (f->flags & AVFILTER_FLAG_DYNAMIC_INPUTS)
printf(" dynamic (depending on the options)\n");
av_bprintf(&bp, " dynamic (depending on the options)\n");
else if (!count)
printf(" none (source filter)\n");
av_bprintf(&bp, " none (source filter)\n");

printf(" Outputs:\n");
av_bprintf(&bp, " Outputs:\n");
count = avfilter_filter_pad_count(f, 1);
for (i = 0; i < count; i++) {
printf(" #%d: %s (%s)\n", i, avfilter_pad_get_name(f->outputs, i),
av_bprintf(&bp, " #%d: %s (%s), Formats: ", i, avfilter_pad_get_name(f->outputs, i),
av_get_media_type_string(avfilter_pad_get_type(f->outputs, i)));

avfilter_print_config_formats(&bp, f, 1, i);
av_bprintf(&bp, "\n");
}
if (f->flags & AVFILTER_FLAG_DYNAMIC_OUTPUTS)
printf(" dynamic (depending on the options)\n");
av_bprintf(&bp, " dynamic (depending on the options)\n");
else if (!count)
printf(" none (sink filter)\n");
av_bprintf(&bp, " none (sink filter)\n");

av_log_set_callback(log_callback_help);
printf("%s\n", bp.str);

if (f->priv_class)
show_help_children(f->priv_class, AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM |
AV_OPT_FLAG_AUDIO_PARAM);
if (f->flags & AVFILTER_FLAG_SUPPORT_TIMELINE)
printf("This filter has support for timeline through the 'enable' option.\n");

av_bprint_finalize(&bp, NULL);
#else
av_log(NULL, AV_LOG_ERROR, "Build without libavfilter; "
"can not to satisfy request\n");
Expand Down
102 changes: 100 additions & 2 deletions libavfilter/avfilter.c
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,104 @@ void avfilter_link_free(AVFilterLink **link)
av_freep(link);
}

static unsigned get_nb_pix_fmts(void)
{
unsigned i = 0;
while (av_pix_fmt_desc_get(i++)) {}
return i - 1;
}

static unsigned get_nb_sample_fmts(void)
{
unsigned i = 0;
while (av_get_sample_fmt_name(i++)) {}
return i - 1;
}

int avfilter_print_config_formats(AVBPrint *bp, const struct AVFilter *filter, int for_output, unsigned pad_index)
{
AVFilterGraph *graph;
AVFilterContext *filter_context;
AVFilterFormatsConfig *config;
enum AVMediaType media_type;
int ret = 0;

if (filter->formats_state == FF_FILTER_FORMATS_PASSTHROUGH) {
av_bprintf(bp, "All (passthrough)");
return 0;
}

graph = avfilter_graph_alloc();
if (!graph) {
av_log(NULL, AV_LOG_ERROR, "Failed to create filtergraph\n");
ret = AVERROR(ENOMEM);
goto cleanup;
}

filter_context = avfilter_graph_alloc_filter(graph, filter, "filter");
if (!filter_context) {
av_log(NULL, AV_LOG_ERROR, "Failed to create filter\n");
ret = AVERROR(ENOMEM);
goto cleanup;
}

avfilter_init_str(filter_context, NULL);

if (filter->formats_state == FF_FILTER_FORMATS_QUERY_FUNC)
av_bprintf(bp, "Dynamic");

if (!for_output && pad_index >= filter_context->nb_inputs
|| for_output && pad_index >= filter_context->nb_outputs)
goto cleanup;

avfilter_graph_config(graph, graph);

for (unsigned i = 0; i < filter_context->nb_inputs; i++)
filter_context->inputs[i] = (AVFilterLink *)av_mallocz(sizeof(AVFilterLink));

for (unsigned i = 0; i < filter_context->nb_outputs; i++)
filter_context->outputs[i] = (AVFilterLink *)av_mallocz(sizeof(AVFilterLink));

ff_filter_query_formats(filter_context);

config = for_output ? &filter_context->outputs[pad_index]->incfg : &filter_context->inputs[pad_index]->outcfg;

if (!config || !config->formats)
goto cleanup;

media_type= for_output ? filter->outputs[pad_index].type : filter->inputs[pad_index].type;

if (filter->formats_state == FF_FILTER_FORMATS_QUERY_FUNC) {
if (config->formats && config->formats->nb_formats)
av_bprintf(bp, ", Default: ");
}

if (config->formats == NULL)
av_bprintf(bp, "unknown");
else if (media_type == AVMEDIA_TYPE_VIDEO && config->formats->nb_formats == get_nb_pix_fmts() ||
media_type == AVMEDIA_TYPE_AUDIO && config->formats->nb_formats == get_nb_sample_fmts())
av_bprintf(bp, "All");
else {
for (unsigned i = 0; i < config->formats->nb_formats; i++) {
if (i == 0)
av_bprintf(bp, "[");

if (media_type == AVMEDIA_TYPE_VIDEO)
av_bprintf(bp, "%s", av_get_pix_fmt_name(config->formats->formats[i]));
else if (media_type == AVMEDIA_TYPE_AUDIO)
av_bprintf(bp, "%s", av_get_sample_fmt_name(config->formats->formats[i]));

if (i < config->formats->nb_formats - 1)
av_bprintf(bp, ", ");
else
av_bprintf(bp, "]"); }
}

cleanup:
avfilter_graph_free(&graph);
return ret;
}

void ff_filter_set_ready(AVFilterContext *filter, unsigned priority)
{
filter->ready = FFMAX(filter->ready, priority);
Expand Down Expand Up @@ -759,12 +857,12 @@ void avfilter_free(AVFilterContext *filter)

for (i = 0; i < filter->nb_inputs; i++) {
free_link(filter->inputs[i]);
if (filter->input_pads[i].flags & AVFILTERPAD_FLAG_FREE_NAME)
if (filter->input_pads && filter->input_pads[i].flags & AVFILTERPAD_FLAG_FREE_NAME)
av_freep(&filter->input_pads[i].name);
}
for (i = 0; i < filter->nb_outputs; i++) {
free_link(filter->outputs[i]);
if (filter->output_pads[i].flags & AVFILTERPAD_FLAG_FREE_NAME)
if (filter->output_pads && filter->output_pads[i].flags & AVFILTERPAD_FLAG_FREE_NAME)
av_freep(&filter->output_pads[i].name);
}

Expand Down
12 changes: 12 additions & 0 deletions libavfilter/avfilter.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
#include "libavutil/avutil.h"
#include "libavutil/buffer.h"
#include "libavutil/dict.h"
#include "libavutil/bprint.h"
#include "libavutil/frame.h"
#include "libavutil/log.h"
#include "libavutil/samplefmt.h"
Expand Down Expand Up @@ -745,6 +746,17 @@ int avfilter_link(AVFilterContext *src, unsigned srcpad,
*/
void avfilter_link_free(AVFilterLink **link);

/**
* Gets the formats from an AVFilterFormatsConfig.
*
* @param bp an instance of AVBPrint
* @param filter the AVFilter
* @param for_output set to 1 for filter outputs
* @param pad_index the index of the input or output
* @return zero on success
*/
int avfilter_print_config_formats(AVBPrint *bp, const AVFilter *filter, int for_output, unsigned pad_index);

/**
* Negotiate the media format, dimensions, etc of all inputs to a filter.
*
Expand Down
15 changes: 11 additions & 4 deletions libavfilter/avfiltergraph.c
Original file line number Diff line number Diff line change
Expand Up @@ -416,10 +416,8 @@ static int query_formats(AVFilterGraph *graph, void *log_ctx)
AVFilterContext *f = graph->filters[i];
if (formats_declared(f))
continue;
if (f->filter->formats_state == FF_FILTER_FORMATS_QUERY_FUNC)
ret = filter_query_formats(f);
else
ret = ff_default_query_formats(f);

ret = ff_filter_query_formats(f);
if (ret < 0 && ret != AVERROR(EAGAIN))
return ret;
/* note: EAGAIN could indicate a partial success, not counted yet */
Expand Down Expand Up @@ -1351,3 +1349,12 @@ int ff_filter_graph_run_once(AVFilterGraph *graph)
return AVERROR(EAGAIN);
return ff_filter_activate(filter);
}

int ff_filter_query_formats(AVFilterContext *filter)
{
if (filter->filter->formats_state == FF_FILTER_FORMATS_QUERY_FUNC)
return filter_query_formats(filter);

return ff_default_query_formats(filter);
}

9 changes: 9 additions & 0 deletions libavfilter/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,15 @@ void ff_filter_graph_remove_filter(AVFilterGraph *graph, AVFilterContext *filter
*/
int ff_filter_graph_run_once(AVFilterGraph *graph);

/**
* Query the formats of a filter.
*
* @param filter the filter context
*
* @return 0 on success
*/
int ff_filter_query_formats(AVFilterContext *filter);

/**
* Get number of threads for current filter instance.
* This number is always same or less than graph->nb_threads.
Expand Down
4 changes: 2 additions & 2 deletions libavfilter/version.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@

#include "version_major.h"

#define LIBAVFILTER_VERSION_MINOR 49
#define LIBAVFILTER_VERSION_MICRO 101
#define LIBAVFILTER_VERSION_MINOR 50
#define LIBAVFILTER_VERSION_MICRO 100


#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
Expand Down