From: cenzhanquan1 via ffmpeg-devel <ffmpeg-devel@ffmpeg.org>
To: ffmpeg-devel@ffmpeg.org
Cc: cenzhanquan1 <code@ffmpeg.org>
Subject: [FFmpeg-devel] [PATCH] avfilter: add avfilter_forward_command API for recursive command processing. (PR #20621)
Date: Sun, 28 Sep 2025 06:42:28 -0000
Message-ID: <175904174886.25.9550971653392209023@bf249f23a2c8> (raw)
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
next reply other threads:[~2025-09-28 6:43 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-09-28 6:42 cenzhanquan1 via ffmpeg-devel [this message]
2025-09-28 11:18 ` [FFmpeg-devel] " Nicolas George via ffmpeg-devel
2025-10-13 14:18 ` 岑湛权 via ffmpeg-devel
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=175904174886.25.9550971653392209023@bf249f23a2c8 \
--to=ffmpeg-devel@ffmpeg.org \
--cc=code@ffmpeg.org \
/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