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 <[email protected]>
>From d43417d9d3ebfcbbd71905cce648b44b30e458d9 Mon Sep 17 00:00:00 2001
From: cenzhanquan1 <[email protected]>
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 <[email protected]>
---
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 -- [email protected]
To unsubscribe send an email to [email protected]