[FFmpeg-devel] [PATCH v4 4/5] lavfi/format: wrap auto filters into structures
Tong Wu
tong1.wu at intel.com
Mon Jul 4 11:09:56 EEST 2022
This patch wraps auto conversion filters into new structures, making it
easier to add more auto filters. And it adds a loop to automatically insert
every possible conversion filter until merge succeeds.
Signed-off-by: Tong Wu <tong1.wu at intel.com>
---
libavfilter/avfiltergraph.c | 76 +++++++++++++++++++++++++------------
libavfilter/formats.c | 22 +++++++++--
libavfilter/formats.h | 10 ++++-
3 files changed, 78 insertions(+), 30 deletions(-)
diff --git a/libavfilter/avfiltergraph.c b/libavfilter/avfiltergraph.c
index 2e6938b049..102c1f7693 100644
--- a/libavfilter/avfiltergraph.c
+++ b/libavfilter/avfiltergraph.c
@@ -395,24 +395,22 @@ static int formats_declared(AVFilterContext *f)
static int insert_auto_filter(AVFilterContext **convert, AVFilterGraph *graph,
AVFilterLink *link, const AVFilterNegotiation *neg,
- int *converter_count, void *log_ctx)
+ unsigned conv_step, int *converter_count, void *log_ctx)
{
int ret;
const AVFilter *filter;
AVFilterContext *ctx;
AVFilterLink *inlink, *outlink;
char inst_name[30];
- const char *opts;
+ const char *opts = FF_FIELD_AT(char *, neg->conversion_filters[conv_step].conversion_opts_offset, *graph);
+ const char *name = neg->conversion_filters[conv_step].conversion_filter;
- if (!(filter = avfilter_get_by_name(neg->conversion_filter))) {
+ if (!(filter = avfilter_get_by_name(name))) {
av_log(log_ctx, AV_LOG_ERROR,
- "'%s' filter not present, cannot convert formats.\n",
- neg->conversion_filter);
+ "'%s' filter not present, cannot convert formats.\n", name);
return AVERROR(EINVAL);
}
- snprintf(inst_name, sizeof(inst_name), "auto_%s_%d",
- neg->conversion_filter, (*converter_count)++);
- opts = FF_FIELD_AT(char *, neg->conversion_opts_offset, *graph);
+ snprintf(inst_name, sizeof(inst_name), "auto_%s_%d", name, (*converter_count)++);
ret = avfilter_graph_create_filter(&ctx, filter, inst_name, opts, NULL, graph);
if (ret < 0)
return ret;
@@ -501,7 +499,7 @@ static int query_formats(AVFilterGraph *graph, void *log_ctx)
for (j = 0; j < filter->nb_inputs; j++) {
AVFilterLink *link = filter->inputs[j];
const AVFilterNegotiation *neg;
- unsigned neg_step;
+ unsigned neg_step, conv_step;
int convert_needed = 0;
if (!link)
@@ -537,8 +535,6 @@ static int query_formats(AVFilterGraph *graph, void *log_ctx)
}
if (convert_needed) {
- AVFilterContext *convert;
-
if (graph->disable_auto_convert) {
av_log(log_ctx, AV_LOG_ERROR,
"The filters '%s' and '%s' do not have a common format "
@@ -548,20 +544,52 @@ static int query_formats(AVFilterGraph *graph, void *log_ctx)
}
/* couldn't merge format lists. auto-insert conversion filter */
- ret = insert_auto_filter(&convert, graph, link, neg, &converter_count, log_ctx);
- if (ret < 0) {
- av_log(log_ctx, AV_LOG_ERROR, "Failed to insert an auto filter.\n");
- return ret;
- }
+ for (conv_step = 0; conv_step < neg->nb_conversion_filters; conv_step++) {
+ AVFilterContext *convert;
+ ret = insert_auto_filter(&convert, graph, link, neg,
+ conv_step, &converter_count, log_ctx);
+ if (ret < 0) {
+ av_log(log_ctx, AV_LOG_ERROR, "Failed to insert an auto filter.\n");
+ return ret;
+ }
- ret = merge_auto_filter(convert, neg);
- if (ret < 0)
- return ret;
- else if (ret == 0) {
- av_log(log_ctx, AV_LOG_ERROR,
- "Impossible to convert between the formats supported by the filter "
- "'%s' and the filter '%s'\n", link->src->name, link->dst->name);
- return AVERROR(ENOSYS);
+ ret = merge_auto_filter(convert, neg);
+ if (ret < 0)
+ return ret;
+ else if (ret > 0)
+ break;
+ else if (conv_step < neg->nb_conversion_filters - 1) {
+ AVFilterLink *inlink = convert->inputs[0];
+ AVFilterLink *outlink = convert->outputs[0];
+ av_log(log_ctx, AV_LOG_VERBOSE,
+ "Impossible to convert between the formats supported by the filter "
+ "'%s' and the filter '%s', try another conversion filter.\n",
+ link->src->name, link->dst->name);
+ unsigned dstpad_idx = outlink->dstpad - outlink->dst->input_pads;
+ converter_count--;
+ /* re-hookup the link */
+ inlink->dst = outlink->dst;
+ inlink->dstpad = &outlink->dst->input_pads[dstpad_idx];
+ outlink->dst->inputs[dstpad_idx] = inlink;
+ if (outlink->outcfg.formats)
+ ff_formats_changeref(&outlink->outcfg.formats,
+ &inlink->outcfg.formats);
+ if (outlink->outcfg.samplerates)
+ ff_formats_changeref(&outlink->outcfg.samplerates,
+ &inlink->outcfg.samplerates);
+ if (outlink->outcfg.channel_layouts)
+ ff_channel_layouts_changeref(&outlink->outcfg.channel_layouts,
+ &inlink->outcfg.channel_layouts);
+ /* remove the previous auto filter */
+ convert->inputs[0] = NULL;
+ convert->outputs[0]->dst = NULL;
+ avfilter_free(convert);
+ } else {
+ av_log(log_ctx, AV_LOG_ERROR,
+ "Impossible to convert between the formats supported by the filter "
+ "'%s' and the filter '%s'\n", link->src->name, link->dst->name);
+ return AVERROR(ENOSYS);
+ }
}
}
}
diff --git a/libavfilter/formats.c b/libavfilter/formats.c
index e8c2888c0c..c8e20e5b20 100644
--- a/libavfilter/formats.c
+++ b/libavfilter/formats.c
@@ -326,18 +326,32 @@ static const AVFilterFormatsMerger mergers_audio[] = {
},
};
+static const AVFilterFormatsFilter filters_video[] = {
+ {
+ .conversion_filter = "scale",
+ .conversion_opts_offset = offsetof(AVFilterGraph, scale_sws_opts),
+ },
+};
+
+static const AVFilterFormatsFilter filters_audio[] = {
+ {
+ .conversion_filter = "aresample",
+ .conversion_opts_offset = offsetof(AVFilterGraph, aresample_swr_opts),
+ }
+};
+
static const AVFilterNegotiation negotiate_video = {
.nb_mergers = FF_ARRAY_ELEMS(mergers_video),
.mergers = mergers_video,
- .conversion_filter = "scale",
- .conversion_opts_offset = offsetof(AVFilterGraph, scale_sws_opts),
+ .nb_conversion_filters = FF_ARRAY_ELEMS(filters_video),
+ .conversion_filters = filters_video,
};
static const AVFilterNegotiation negotiate_audio = {
.nb_mergers = FF_ARRAY_ELEMS(mergers_audio),
.mergers = mergers_audio,
- .conversion_filter = "aresample",
- .conversion_opts_offset = offsetof(AVFilterGraph, aresample_swr_opts),
+ .nb_conversion_filters = FF_ARRAY_ELEMS(filters_audio),
+ .conversion_filters = filters_audio,
};
const AVFilterNegotiation *ff_filter_get_negotiation(AVFilterLink *link)
diff --git a/libavfilter/formats.h b/libavfilter/formats.h
index 22224dce2d..868cbe98dd 100644
--- a/libavfilter/formats.h
+++ b/libavfilter/formats.h
@@ -330,6 +330,12 @@ typedef struct AVFilterFormatMerger {
int (*can_merge)(const void *a, const void *b);
} AVFilterFormatsMerger;
+typedef struct AVFilterFormatFilter {
+ const char *conversion_filter;
+ unsigned conversion_opts_offset;
+} AVFilterFormatsFilter;
+
+
/**
* Callbacks and properties to describe the steps of a format negotiation.
*
@@ -418,8 +424,8 @@ typedef struct AVFilterFormatMerger {
typedef struct AVFilterNegotiation {
unsigned nb_mergers;
const AVFilterFormatsMerger *mergers;
- const char *conversion_filter;
- unsigned conversion_opts_offset;
+ unsigned nb_conversion_filters;
+ const AVFilterFormatsFilter *conversion_filters;
} AVFilterNegotiation;
const AVFilterNegotiation *ff_filter_get_negotiation(AVFilterLink *link);
--
2.35.1.windows.2
More information about the ffmpeg-devel
mailing list