Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
 help / color / mirror / Atom feed
* [FFmpeg-devel] [PATCH] avfilter: add avfilter_forward_command API for recursive command processing. (PR #20621)
@ 2025-09-28  6:42 cenzhanquan1 via ffmpeg-devel
  2025-09-28 11:18 ` [FFmpeg-devel] " Nicolas George via ffmpeg-devel
  0 siblings, 1 reply; 2+ messages in thread
From: cenzhanquan1 via ffmpeg-devel @ 2025-09-28  6:42 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: cenzhanquan1

PR #20621 opened by cenzhanquan1
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20621
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20621.patch

This commit introduces a new API that allows commands to be recursively
forwarded through filter graphs, enabling dynamic control of filters
at runtime.

Key changes:

1. Added avfilter_forward_command() function in avfilter.c:
   - Supports both forward and reverse command propagation via
     AVFILTER_CMD_FLAG_REVERSE flag
   - Recursively traverses filter links to find target filters
   - Falls back to filter-specific forward_command callback when available
   - Properly handles "all" target for broadcasting commands

2. Extended AVFilter struct in filters.h:
   - Added forward_command callback for filter-specific implementations
   - Maintains backward compatibility with existing filters

3. New API documentation in avfilter.h:
   - Detailed parameter descriptions including pad_idx and flags
   - Clear explanation of AVFILTER_CMD_FLAG_REVERSE behavior
   - Usage examples for common scenarios

4. Added AVFILTER_CMD_FLAG_REVERSE flag:
   - Enables reverse traversal from sink to source filters
   - Useful for targeting specific filters in complex graphs

Signed-off-by: cenzhanquan1 <cenzhanquan1@xiaomi.com>


>From d43417d9d3ebfcbbd71905cce648b44b30e458d9 Mon Sep 17 00:00:00 2001
From: cenzhanquan1 <cenzhanquan1@xiaomi.com>
Date: Sun, 28 Sep 2025 14:37:21 +0800
Subject: [PATCH] avfilter: add avfilter_forward_command API for recursive
 command processing.

This commit introduces a new API that allows commands to be recursively
forwarded through filter graphs, enabling dynamic control of filters
at runtime.

Key changes:

1. Added avfilter_forward_command() function in avfilter.c:
   - Supports both forward and reverse command propagation via
     AVFILTER_CMD_FLAG_REVERSE flag
   - Recursively traverses filter links to find target filters
   - Falls back to filter-specific forward_command callback when available
   - Properly handles "all" target for broadcasting commands

2. Extended AVFilter struct in filters.h:
   - Added forward_command callback for filter-specific implementations
   - Maintains backward compatibility with existing filters

3. New API documentation in avfilter.h:
   - Detailed parameter descriptions including pad_idx and flags
   - Clear explanation of AVFILTER_CMD_FLAG_REVERSE behavior
   - Usage examples for common scenarios

4. Added AVFILTER_CMD_FLAG_REVERSE flag:
   - Enables reverse traversal from sink to source filters
   - Useful for targeting specific filters in complex graphs

Signed-off-by: cenzhanquan1 <cenzhanquan1@xiaomi.com>
---
 libavfilter/avfilter.c | 53 ++++++++++++++++++++++++++++++++++++++++++
 libavfilter/avfilter.h | 15 ++++++++++++
 libavfilter/filters.h  | 10 ++++++++
 3 files changed, 78 insertions(+)

diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c
index 169c2baa42..c661556774 100644
--- a/libavfilter/avfilter.c
+++ b/libavfilter/avfilter.c
@@ -628,6 +628,59 @@ int avfilter_process_command(AVFilterContext *filter, const char *cmd, const cha
     return AVERROR(ENOSYS);
 }
 
+int avfilter_forward_command(AVFilterContext *filter, int pad_idx, const char *target, const char *cmd,
+                             const char *arg, char *res, int res_len, int flags)
+{
+    AVFilterLink* link;
+    AVFilterLink** prev_links;
+    unsigned    nb_prev_links;
+    unsigned    nb_next_links;
+    int i, ret = AVERROR(ENOSYS);
+
+    if (flags & AVFILTER_CMD_FLAG_REVERSE) {
+        link          = filter->inputs[pad_idx];
+        filter        = link->src;
+        prev_links    = filter->outputs;
+        nb_prev_links = filter->nb_outputs;
+        nb_next_links = filter->nb_inputs;
+    } else {
+        link          = filter->outputs[pad_idx];
+        filter        = link->dst;
+        prev_links    = filter->inputs;
+        nb_prev_links = filter->nb_inputs;
+        nb_next_links = filter->nb_outputs;
+    }
+
+    if (!strcmp(target, "all") || (filter->name && !strcmp(target, filter->name)) || !strcmp(target, filter->filter->name)) {
+        ret = avfilter_process_command(filter, cmd, arg, res, res_len, flags);
+        if (ret != AVERROR(ENOSYS)) {
+            if (ret == AVERROR_OPTION_NOT_FOUND)
+                ret = AVERROR(ENOSYS);
+            else if ((flags & AVFILTER_CMD_FLAG_ONE) || ret < 0)
+                return ret;
+        }
+    }
+
+    for (i = 0; i < nb_prev_links; i++) {
+        if (prev_links[i] == link) {
+            pad_idx = i;
+            break;
+        }
+    }
+
+    if (fffilter(filter->filter)->forward_command) {
+        return fffilter(filter->filter)->forward_command(filter, pad_idx, target, cmd, arg, res, res_len, flags);
+    }
+
+    for (i = 0; i < nb_next_links; i++) {
+        ret = avfilter_forward_command(filter, i, target, cmd, arg, res, res_len, flags);
+        if (ret < 0 && ret != AVERROR(ENOSYS))
+            return ret;
+    }
+
+    return ret;
+}
+
 unsigned avfilter_filter_pad_count(const AVFilter *filter, int is_output)
 {
     return is_output ? fffilter(filter)->nb_outputs : fffilter(filter)->nb_inputs;
diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h
index 02b58c42c2..0d8a3410ab 100644
--- a/libavfilter/avfilter.h
+++ b/libavfilter/avfilter.h
@@ -468,6 +468,7 @@ int avfilter_link(AVFilterContext *src, unsigned srcpad,
 
 #define AVFILTER_CMD_FLAG_ONE   1 ///< Stop once a filter understood the command (for target=all for example), fast filters are favored automatically
 #define AVFILTER_CMD_FLAG_FAST  2 ///< Only execute command when its fast (like a video out that supports contrast adjustment in hw)
+#define AVFILTER_CMD_FLAG_REVERSE 4 ///< Reverse forward command to source filter (default to sink filter)
 
 /**
  * Make the filter instance process a command.
@@ -475,6 +476,20 @@ int avfilter_link(AVFilterContext *src, unsigned srcpad,
  */
 int avfilter_process_command(AVFilterContext *filter, const char *cmd, const char *arg, char *res, int res_len, int flags);
 
+/**
+ * Recursively make the filter instance process a command.
+ * @see avfilter_process_command
+ *
+ * @param filter    the filter to forward command.
+ * @param pad_id    the pad index that filter forward command to.
+ * @param flags         @see AVFILTER_CMD_FLAG_REVERSE.
+ *
+ * @return the number of filters that successfully processed the command.
+ */
+int avfilter_forward_command(AVFilterContext *filter, int pad_idx, const char *target, const char *cmd,
+                             const char *arg, char *res, int res_len, int flags);
+
+
 /**
  * Iterate over all registered filters.
  *
diff --git a/libavfilter/filters.h b/libavfilter/filters.h
index bc79527b87..fee57fe815 100644
--- a/libavfilter/filters.h
+++ b/libavfilter/filters.h
@@ -445,6 +445,16 @@ typedef struct FFFilter {
      */
     int (*process_command)(AVFilterContext *, const char *cmd, const char *arg, char *res, int res_len, int flags);
 
+    /**
+     * Forward command to neighbor links.
+     *
+     * @param pad_idx   indicates the pad index that command is from.
+     * @return >=0 on successfully forwarding to some filters.
+     *         AVERROR(ENOSYS) on unsupported commands, or didn't forward.
+     */
+    int (*forward_command)(AVFilterContext *, int pad_idx, const char *target, const char *cmd,
+                           const char *arg, char *res, int res_len, int flags);
+
     /**
      * Filter activation function.
      *
-- 
2.49.1

_______________________________________________
ffmpeg-devel mailing list -- ffmpeg-devel@ffmpeg.org
To unsubscribe send an email to ffmpeg-devel-leave@ffmpeg.org

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2025-09-28 11:19 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-09-28  6:42 [FFmpeg-devel] [PATCH] avfilter: add avfilter_forward_command API for recursive command processing. (PR #20621) cenzhanquan1 via ffmpeg-devel
2025-09-28 11:18 ` [FFmpeg-devel] " Nicolas George via ffmpeg-devel

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 http://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/ http://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