* [FFmpeg-devel] [PATCH] avfilter: enhance command processing with chain propagation and direction control. (PR #20731)
@ 2025-10-21  9:40 cenzhanquan1 via ffmpeg-devel
  2025-10-30 19:12 ` [FFmpeg-devel] " Nicolas George via ffmpeg-devel
  0 siblings, 1 reply; 4+ messages in thread
From: cenzhanquan1 via ffmpeg-devel @ 2025-10-21  9:40 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: cenzhanquan1
PR #20731 opened by cenzhanquan1
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20731
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20731.patch
The existing avfilter_process_command and avfilter_graph_send_command havelimitations in
command propagation: they only handle commands for individualfilters and lack the ability
to propagate commands through the entire filterchain, nor do they support directional
traversal of the filter graph. Thismakes it difficult to control multiple filters in a chain
(e.g., adjustingvolume for all related filters or enabling/disabling a series of filters)with
a single command.
This patch enhances the command processing logic to address these issues:
Add two new flags to control command propagation:
AVFILTER_CMD_FLAG_CHAIN: Enables command propagation through the entire
filter chain. After processing the current filter, it traverses all
associated links (inputs/outputs based on direction) and recursively
forwards the command to subsequent filters, covering the full filter
topology.
AVFILTER_CMD_FLAG_REVERSE: Works with AVFILTER_CMD_FLAG_CHAIN to control
traversal direction. Default (forward) follows data flow (source →
destination filters), while reverse traversal goes against data flow
(destination → source filters).
Refactor avfilter_process_command to integrate chain propagation logic:
Process the command for the current filter first, then check if chain
propagation is enabled.
Traverse all relevant links (inputs for reverse, outputs for forward) and
recursively forward the command to next-level filters.
Track processing status (processed) to determine if any filter in the
chain handled the command.
Respect AVFILTER_CMD_FLAG_ONE to stop propagation once a filter processes
the command, and propagate critical errors.
Improve command handling for built-in commands ("ping" and "enable") to
workseamlessly with the new propagation logic, ensuring consistent behavioracross the chain.
These changes enable flexible command control over entire filter chains,supporting use cases
like batch adjustment of filters, topology-wide statuschecks (via "ping"), and coordinated
enable/disable operations, whilemaintaining compatibility with existing filter command
implementations.
Signed-off-by: cenzhanquan1 <cenzhanquan1@xiaomi.com>
From 9dba682222bd55c952e14e71789a7084529a74f7 Mon Sep 17 00:00:00 2001
From: cenzhanquan1 <cenzhanquan1@xiaomi.com>
Date: Tue, 21 Oct 2025 17:34:22 +0800
Subject: [PATCH] avfilter: enhance command processing with chain propagation
 and direction control.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The existing avfilter_process_command and avfilter_graph_send_command havelimitations in
command propagation: they only handle commands for individualfilters and lack the ability
to propagate commands through the entire filterchain, nor do they support directional
traversal of the filter graph. Thismakes it difficult to control multiple filters in a chain
(e.g., adjustingvolume for all related filters or enabling/disabling a series of filters)with
a single command.
This patch enhances the command processing logic to address these issues:
Add two new flags to control command propagation:
AVFILTER_CMD_FLAG_CHAIN: Enables command propagation through the entire
filter chain. After processing the current filter, it traverses all
associated links (inputs/outputs based on direction) and recursively
forwards the command to subsequent filters, covering the full filter
topology.
AVFILTER_CMD_FLAG_REVERSE: Works with AVFILTER_CMD_FLAG_CHAIN to control
traversal direction. Default (forward) follows data flow (source →
destination filters), while reverse traversal goes against data flow
(destination → source filters).
Refactor avfilter_process_command to integrate chain propagation logic:
Process the command for the current filter first, then check if chain
propagation is enabled.
Traverse all relevant links (inputs for reverse, outputs for forward) and
recursively forward the command to next-level filters.
Track processing status (processed) to determine if any filter in the
chain handled the command.
Respect AVFILTER_CMD_FLAG_ONE to stop propagation once a filter processes
the command, and propagate critical errors.
Improve command handling for built-in commands ("ping" and "enable") to
workseamlessly with the new propagation logic, ensuring consistent behavioracross the chain.
These changes enable flexible command control over entire filter chains,supporting use cases
like batch adjustment of filters, topology-wide statuschecks (via "ping"), and coordinated
enable/disable operations, whilemaintaining compatibility with existing filter command
implementations.
Signed-off-by: cenzhanquan1 <cenzhanquan1@xiaomi.com>
---
 libavfilter/avfilter.c | 75 +++++++++++++++++++++++++++++++++---------
 libavfilter/avfilter.h | 10 ++++--
 2 files changed, 67 insertions(+), 18 deletions(-)
diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c
index 169c2baa42..68ec9f6f6a 100644
--- a/libavfilter/avfilter.c
+++ b/libavfilter/avfilter.c
@@ -607,25 +607,68 @@ static int set_enable_expr(FFFilterContext *ctxi, const char *expr)
     return 0;
 }
 
-int avfilter_process_command(AVFilterContext *filter, const char *cmd, const char *arg, char *res, int res_len, int flags)
+int avfilter_process_command(AVFilterContext *filter, const char *cmd, const char *arg,
+                            char *res, int res_len, int flags)
 {
-    if(!strcmp(cmd, "ping")){
-        char local_res[256] = {0};
+    int direction = flags & AVFILTER_CMD_FLAG_REVERSE;
+    int ret = AVERROR(ENOSYS);
+    int processed = 0;
 
-        if (!res) {
-            res = local_res;
-            res_len = sizeof(local_res);
-        }
-        av_strlcatf(res, res_len, "pong from:%s %s\n", filter->filter->name, filter->name);
-        if (res == local_res)
-            av_log(filter, AV_LOG_INFO, "%s", res);
-        return 0;
-    }else if(!strcmp(cmd, "enable")) {
-        return set_enable_expr(fffilterctx(filter), arg);
-    }else if (fffilter(filter->filter)->process_command) {
-        return fffilter(filter->filter)->process_command(filter, cmd, arg, res, res_len, flags);
+    int process_flags = flags & ~AVFILTER_CMD_FLAG_CHAIN;
+    if (!strcmp(cmd, "ping")) {
+        char local_res[256] = {0};
+        char *res_buf = res ? res : local_res;
+        size_t buf_len = res ? res_len : sizeof(local_res);
+        av_strlcatf(res_buf, buf_len, "pong from:%s %s\n",
+                   filter->filter->name, filter->name ? filter->name : "unknown");
+        if (!res)
+            av_log(filter, AV_LOG_INFO, "%s", res_buf);
+        ret = 0;
+    } else if (!strcmp(cmd, "enable")) {
+        ret = set_enable_expr(fffilterctx(filter), arg);
+    } else if (fffilter(filter->filter)->process_command) {
+        ret = fffilter(filter->filter)->process_command(filter, cmd, arg, res, res_len, process_flags);
+    } else {
+        ret = AVERROR(ENOSYS);
     }
-    return AVERROR(ENOSYS);
+
+    if (ret != AVERROR(ENOSYS)) {
+        processed = 1;
+        if ((flags & AVFILTER_CMD_FLAG_ONE) || ret < 0) {
+            return ret;
+        }
+    }
+
+    if (!(flags & AVFILTER_CMD_FLAG_CHAIN)) {
+        return processed ? 0 : AVERROR(ENOSYS);
+    }
+
+    av_log(filter, AV_LOG_DEBUG,
+           "cmd_chain: [%s] dir:%s -> '%s' '%s' (forwarding)\n",
+           filter->name ? filter->name : "unknown",
+           direction ? "reverse" : "forward",
+           cmd, arg ? arg : "");
+
+    unsigned nb_links = direction ? filter->nb_inputs : filter->nb_outputs;
+    for (int i = 0; i < nb_links; i++) {
+        AVFilterLink *link = direction ? filter->inputs[i] : filter->outputs[i];
+        AVFilterContext *next_filter = direction ? (link ? link->src : NULL) : (link ? link->dst : NULL);
+
+        if (!link || !next_filter) {
+            av_log(filter, AV_LOG_DEBUG, "Invalid %s link at pad %d\n",
+                   direction ? "input" : "output", i);
+            continue;
+        }
+
+        ret = avfilter_process_command(next_filter, cmd, arg, res, res_len, flags);
+        if (ret >= 0) {
+            processed = 1;
+        } else if (ret != AVERROR(ENOSYS)) {
+            return ret;
+        }
+    }
+
+    return processed ? 0 : AVERROR(ENOSYS);
 }
 
 unsigned avfilter_filter_pad_count(const AVFilter *filter, int is_output)
diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h
index 02b58c42c2..fde3811dc3 100644
--- a/libavfilter/avfilter.h
+++ b/libavfilter/avfilter.h
@@ -466,8 +466,14 @@ struct AVFilterLink {
 int avfilter_link(AVFilterContext *src, unsigned srcpad,
                   AVFilterContext *dst, unsigned dstpad);
 
-#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_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_CHAIN   4 ///< Propagate the command through the entire filter chain. After processing the current filter,
+                                    /// traverse all its associated links (inputs or outputs, based on direction) and recursively
+                                    /// forward the command to subsequent filters, covering the full filter topology.
+#define AVFILTER_CMD_FLAG_REVERSE 8 ///< Only effective when paired with AVFILTER_CMD_FLAG_CHAIN. Changes the command's traversal
+                                    /// direction in the chain: default (forward) follows data flow (source → destination filters),
+                                    /// while reverse traversal opposes data flow (destination → source filters).
 
 /**
  * Make the filter instance process a command.
-- 
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] 4+ messages in thread
* [FFmpeg-devel] Re: [PATCH] avfilter: enhance command processing with chain propagation and direction control. (PR #20731)
  2025-10-21  9:40 [FFmpeg-devel] [PATCH] avfilter: enhance command processing with chain propagation and direction control. (PR #20731) cenzhanquan1 via ffmpeg-devel
@ 2025-10-30 19:12 ` Nicolas George via ffmpeg-devel
  2025-10-31  9:14   ` Zhao Zhili via ffmpeg-devel
  0 siblings, 1 reply; 4+ messages in thread
From: Nicolas George via ffmpeg-devel @ 2025-10-30 19:12 UTC (permalink / raw)
  To: FFmpeg development discussions and patches; +Cc: cenzhanquan1, Nicolas George
cenzhanquan1 via ffmpeg-devel (HE12025-10-21):
> PR #20731 opened by cenzhanquan1
> URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20731
> Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20731.patch
> 
> The existing avfilter_process_command and avfilter_graph_send_command havelimitations in
> command propagation: they only handle commands for individualfilters and lack the ability
> to propagate commands through the entire filterchain, nor do they support directional
> traversal of the filter graph. Thismakes it difficult to control multiple filters in a chain
> (e.g., adjustingvolume for all related filters or enabling/disabling a series of filters)with
> a single command.
You are proposing to add an API without adding any code that uses that
API, let alone user-oriented examples. That makes it impossible to guess
if the feature is useful or if there are better ways to achieve what you
want it to do.
Regards,
-- 
  Nicolas George
_______________________________________________
ffmpeg-devel mailing list -- ffmpeg-devel@ffmpeg.org
To unsubscribe send an email to ffmpeg-devel-leave@ffmpeg.org
^ permalink raw reply	[flat|nested] 4+ messages in thread
* [FFmpeg-devel] Re: [PATCH] avfilter: enhance command processing with chain propagation and direction control. (PR #20731)
  2025-10-30 19:12 ` [FFmpeg-devel] " Nicolas George via ffmpeg-devel
@ 2025-10-31  9:14   ` Zhao Zhili via ffmpeg-devel
  2025-10-31  9:58     ` Nicolas George via ffmpeg-devel
  0 siblings, 1 reply; 4+ messages in thread
From: Zhao Zhili via ffmpeg-devel @ 2025-10-31  9:14 UTC (permalink / raw)
  To: FFmpeg development discussions and patches
  Cc: cenzhanquan1, Nicolas George, Zhao Zhili
> On Oct 31, 2025, at 03:12, Nicolas George via ffmpeg-devel <ffmpeg-devel@ffmpeg.org> wrote:
> 
> cenzhanquan1 via ffmpeg-devel (HE12025-10-21):
>> PR #20731 opened by cenzhanquan1
>> URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20731
>> Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20731.patch
>> 
>> The existing avfilter_process_command and avfilter_graph_send_command havelimitations in
>> command propagation: they only handle commands for individualfilters and lack the ability
>> to propagate commands through the entire filterchain, nor do they support directional
>> traversal of the filter graph. Thismakes it difficult to control multiple filters in a chain
>> (e.g., adjustingvolume for all related filters or enabling/disabling a series of filters)with
>> a single command.
> 
> You are proposing to add an API without adding any code that uses that
> API, let alone user-oriented examples. That makes it impossible to guess
> if the feature is useful or if there are better ways to achieve what you
> want it to do.
Current implementation isn’t a new API, but new flags. It extends the ways to
traverse a graph. 
The existing API has the capability to send commands to a specific filter, a certain
type of filter, or all filters, but it lacks the ability to send commands to a subgraph,
unless the user manually filters out all filters belonging to the subgraph, which is
possible but complex.
The newly added flags provide subgraph traversal capability.
A common use case is when a graph contains multiple sources; I want to send
commands, such as volume control, to a subgraph with a specific source as the
root node, without affecting other sources. While controlling via volume instance
names is also feasible, using the source for control offers additional flexibility.
> 
> Regards,
> 
> -- 
>  Nicolas George
> _______________________________________________
> ffmpeg-devel mailing list -- ffmpeg-devel@ffmpeg.org
> To unsubscribe send an email to ffmpeg-devel-leave@ffmpeg.org
_______________________________________________
ffmpeg-devel mailing list -- ffmpeg-devel@ffmpeg.org
To unsubscribe send an email to ffmpeg-devel-leave@ffmpeg.org
^ permalink raw reply	[flat|nested] 4+ messages in thread
* [FFmpeg-devel] Re: [PATCH] avfilter: enhance command processing with chain propagation and direction control. (PR #20731)
  2025-10-31  9:14   ` Zhao Zhili via ffmpeg-devel
@ 2025-10-31  9:58     ` Nicolas George via ffmpeg-devel
  0 siblings, 0 replies; 4+ messages in thread
From: Nicolas George via ffmpeg-devel @ 2025-10-31  9:58 UTC (permalink / raw)
  To: FFmpeg development discussions and patches; +Cc: Nicolas George
Zhao Zhili via ffmpeg-devel (HE12025-10-31):
> Current implementation isn’t a new API, but new flags. It extends the ways to
> traverse a graph. 
A new flag is a new API.
> The existing API has the capability to send commands to a specific filter, a certain
> type of filter, or all filters, but it lacks the ability to send commands to a subgraph,
> unless the user manually filters out all filters belonging to the subgraph, which is
> possible but complex.
> 
> The newly added flags provide subgraph traversal capability.
> 
> A common use case is when a graph contains multiple sources; I want to send
> commands, such as volume control, to a subgraph with a specific source as the
> root node, without affecting other sources. While controlling via volume instance
> names is also feasible, using the source for control offers additional flexibility.
Then we need a patch series that really allows to do that, including
examples.
Regards,
-- 
  Nicolas George
_______________________________________________
ffmpeg-devel mailing list -- ffmpeg-devel@ffmpeg.org
To unsubscribe send an email to ffmpeg-devel-leave@ffmpeg.org
^ permalink raw reply	[flat|nested] 4+ messages in thread
end of thread, other threads:[~2025-10-31  9:59 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-10-21  9:40 [FFmpeg-devel] [PATCH] avfilter: enhance command processing with chain propagation and direction control. (PR #20731) cenzhanquan1 via ffmpeg-devel
2025-10-30 19:12 ` [FFmpeg-devel] " Nicolas George via ffmpeg-devel
2025-10-31  9:14   ` Zhao Zhili via ffmpeg-devel
2025-10-31  9:58     ` 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 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