Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
 help / color / mirror / Atom feed
From: Tong Wu <tong1.wu-at-intel.com@ffmpeg.org>
To: ffmpeg-devel@ffmpeg.org
Cc: Tong Wu <tong1.wu@intel.com>
Subject: [FFmpeg-devel] [PATCH v4 4/5] lavfi/format: wrap auto filters into structures
Date: Mon,  4 Jul 2022 16:09:56 +0800
Message-ID: <20220704080957.425-4-tong1.wu@intel.com> (raw)
In-Reply-To: <20220704080957.425-1-tong1.wu@intel.com>

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@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

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

  parent reply	other threads:[~2022-07-04  8:11 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-07-04  8:09 [FFmpeg-devel] [PATCH v4 1/5] avutil/hwcontext: add a function to get the AVHWDeviceType Tong Wu
2022-07-04  8:09 ` [FFmpeg-devel] [PATCH v4 2/5] avfilter/vf_hwmap: get the AVHWDeviceType from outlink format Tong Wu
2022-07-04  8:09 ` [FFmpeg-devel] [PATCH v4 3/5] lavfi/avfiltergraph: move convert codes into functions Tong Wu
2022-07-04  8:09 ` Tong Wu [this message]
2022-07-04  8:09 ` [FFmpeg-devel] [PATCH v4 5/5] lavfi/format: add a hwmap auto conversion filter Tong Wu
2022-07-15  5:19   ` Wu, Tong1

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220704080957.425-4-tong1.wu@intel.com \
    --to=tong1.wu-at-intel.com@ffmpeg.org \
    --cc=ffmpeg-devel@ffmpeg.org \
    --cc=tong1.wu@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

This inbox may be cloned and mirrored by anyone:

	git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
		ffmpegdev@gitmailbox.com
	public-inbox-index ffmpegdev

Example config snippet for mirrors.


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git