From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from ffbox0-bg.ffmpeg.org (ffbox0-bg.ffmpeg.org [79.124.17.100]) by master.gitmailbox.com (Postfix) with ESMTPS id F1D344B7EB for ; Sun, 28 Sep 2025 06:43:03 +0000 (UTC) Authentication-Results: ffbox; dkim=fail (body hash mismatch (got b'ZTpqVGYQwoo0faC+KlcXJtHRUqAwBu/JiFOhoTaD4Vc=', expected b'6bh2loGh1ZXCMDqJf9MsqCEi2fg6b2Sy/5TliKn0Ua4=')) header.d=ffmpeg.org header.i=@ffmpeg.org header.a=rsa-sha256 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ffmpeg.org; i=@ffmpeg.org; q=dns/txt; s=mail; t=1759041764; h=mime-version : to : date : message-id : reply-to : subject : list-id : list-archive : list-archive : list-help : list-owner : list-post : list-subscribe : list-unsubscribe : from : cc : content-type : content-transfer-encoding : from; bh=ZTpqVGYQwoo0faC+KlcXJtHRUqAwBu/JiFOhoTaD4Vc=; b=bBHE3iggYtk68WMPz0j3REBIguOhOSsB9tNwOB4sVJEpr4E20/kGcBX7ohyI1ByEm2dAB D9y0BEe5xU0lyo31rgvf1HCHJvkUqHZbHG+RoNfTIV6hy9VSCIMyjqphMuIzlysiYjIjt/o n/10EYf/5afCkb/jnWq4bVSP923+BJG8z93pzS7eJ8yP8Gwm0q4VNhZv+LpWh/Vx9yG2HQX KrBQciN0s/u/0YAZpsdr/TcuopcATQF1DZci87vt198ScAymtJL03U9bIbZ9C+Csl2Ix/cr u1QiSGBmoqgTHJcsJ/k5Vvg37hfONcENOxS41ePUunvKLU2qySRgUr+slqOQ== Received: from [172.19.0.4] (unknown [172.19.0.4]) by ffbox0-bg.ffmpeg.org (Postfix) with ESMTP id D665F68ED54; Sun, 28 Sep 2025 09:42:44 +0300 (EEST) ARC-Seal: i=1; cv=none; a=rsa-sha256; d=ffmpeg.org; s=arc; t=1759041758; b=t3aTixyINaLnGnFfYsrtIrx8HCbKtSsnCHU/WuxVklqTz2i3iH8FdGWXMxOXmeHkgK5ha 7gIowuV9ZnKlY0yh5rHvhpORBSRqWCF/fIPlpxXtuV1SksQHVTOYnBW5w5JELd+uYI3MY6h 5xGYzQSZL8sNZ0oSRw/x2NSu6AKhJ/ViEkwxnzOVkLbnmUN6miPeNTce299TdKiT16WNNPP pyoEpvGupBpRqjcy0HyBg/Tfdf9chuoQekRRswTHqAbS9cEAKvdkkssIfSx9lgF9m2634tL IpsMsquxOcOsudWVYFudVu66kCBll3lalhCQWX4iOVcGowEi8D/WV2I5yCDg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=ffmpeg.org; s=arc; t=1759041758; h=from : sender : reply-to : subject : date : message-id : to : cc : mime-version : content-type : content-transfer-encoding : content-id : content-description : resent-date : resent-from : resent-sender : resent-to : resent-cc : resent-message-id : in-reply-to : references : list-id : list-help : list-unsubscribe : list-subscribe : list-post : list-owner : list-archive; bh=ZKsS6/acIhhGYgcIEVE3dZxhW5TMGhowt34T0gvl+sw=; b=QXXj9l0CwJjxcsPuSL/QD6ijBGRZk/aI/weoEFWKhzctfsnCJ3SzNXvD6i9VP2dbYg0il gpgmfLMO25K0XDHzJoXE5oNyOPa2G+5lRHBsWSrzrgqHLO3UW99/HreSXQ19KfzWraBmh+W uWJXF5nvB407UVC11/+M8IrwXMnU0OMcSRrHiE5IGZmURvLXNKmIDhwuXmdT8zdPe4Wf44A +oanwl3VUGZmG6CGoc81725NLeqf8cSXpjLMGhIAWG2Qet7gn/eiOuY/FShZSXYMSEh95qC DS7pmpE5UbkjcPdZGtrFfQrK/LNxqOohT+mnIKq123QXiQ6TAbB8kvdZF+lQ== ARC-Authentication-Results: i=1; ffmpeg.org; dkim=pass header.d=ffmpeg.org header.i=@ffmpeg.org; arc=none; dmarc=pass header.from=ffmpeg.org policy.dmarc=quarantine Authentication-Results: ffmpeg.org; dkim=pass header.d=ffmpeg.org header.i=@ffmpeg.org; arc=none (Message is not ARC signed); dmarc=pass (Used From Domain Record) header.from=ffmpeg.org policy.dmarc=quarantine DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ffmpeg.org; i=@ffmpeg.org; q=dns/txt; s=mail; t=1759041748; h=content-type : mime-version : content-transfer-encoding : from : to : reply-to : subject : date : from; bh=6bh2loGh1ZXCMDqJf9MsqCEi2fg6b2Sy/5TliKn0Ua4=; b=2K2hJDuRBjXYEFX9vKjeWNL2JbvUCdOoqtqqJdfeYE2udJsSLHRpMf3z7CH8TE9SfzMn9 woL8bfw7Kii3y2DKhlEDpjBCQfxGCugy5yOo8h7qryLcCHkPSR/ANaW28I3dKx34CllNnj7 JXN4EWBLdAPDMV1KNVX+dw/FKtFqP7mjFjLe/g3kxQ5ugtC6sHmyq69Hcvvdyu0zz2e+gVV iFujudZkv/GuvAdiQx3OZdZZjAm+skCRjqSV7l684Tw8HdJD8ceOLm8FfPD79WkxJVvf+hs Kyd0nEx0CYYDwD5HDmHD21PYMHafdltPDTX07/Wjx+5o8gcYnrrdVUZInSaA== Received: from 13289e625de8 (code.ffmpeg.org [188.245.149.3]) by ffbox0-bg.ffmpeg.org (Postfix) with ESMTPS id ACE8868ED48 for ; Sun, 28 Sep 2025 09:42:28 +0300 (EEST) MIME-Version: 1.0 To: ffmpeg-devel@ffmpeg.org Date: Sun, 28 Sep 2025 06:42:28 -0000 Message-ID: <175904174886.25.9550971653392209023@bf249f23a2c8> Message-ID-Hash: KC3LMI56PKGHGSOKZZ6DFKQ7K3QOKLAN X-Message-ID-Hash: KC3LMI56PKGHGSOKZZ6DFKQ7K3QOKLAN X-MailFrom: code@ffmpeg.org X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; header-match-ffmpeg-devel.ffmpeg.org-0; header-match-ffmpeg-devel.ffmpeg.org-1; header-match-ffmpeg-devel.ffmpeg.org-2; header-match-ffmpeg-devel.ffmpeg.org-3; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header X-Mailman-Version: 3.3.10 Precedence: list Reply-To: FFmpeg development discussions and patches Subject: [FFmpeg-devel] [PATCH] avfilter: add avfilter_forward_command API for recursive command processing. (PR #20621) List-Id: FFmpeg development discussions and patches Archived-At: Archived-At: List-Archive: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: cenzhanquan1 via ffmpeg-devel Cc: cenzhanquan1 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Archived-At: List-Archive: List-Post: 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 >>From d43417d9d3ebfcbbd71905cce648b44b30e458d9 Mon Sep 17 00:00:00 2001 From: cenzhanquan1 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 --- 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