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

* [FFmpeg-devel] Re: [PATCH] avfilter: add avfilter_forward_command API for recursive command processing. (PR #20621)
  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 ` Nicolas George via ffmpeg-devel
  0 siblings, 0 replies; 2+ messages in thread
From: Nicolas George via ffmpeg-devel @ 2025-09-28 11:18 UTC (permalink / raw)
  To: FFmpeg development discussions and patches; +Cc: cenzhanquan1, Nicolas George

cenzhanquan1 via ffmpeg-devel (HE12025-09-28):
> 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

Thanks for the patch.

We normally avoid introducing APIs that nothing uses. If this API is
useful, then it probably can be made use of by one of the fftools, most
likely ffmpeg itself. Please submit a patch series that also adds this
use.

Also, please explain what this makes possible that was not already
possible with existing functions, in particular simply
avfilter_process_command() and avfilter_graph_send_command().

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