From ae60615f58fcf5f09e74a910ef8aa94fc9ae0155 Mon Sep 17 00:00:00 2001 From: Arnaud de Turckheim Date: Fri, 4 Apr 2025 17:33:40 +0200 Subject: [PATCH] upipe_avfilter: support avfilter_graph_send_command --- include/upipe-av/upipe_avfilter.h | 46 ++++++++++++++++++++++++++++++- lib/upipe-av/upipe_avfilter.c | 35 ++++++++++++++++++++++- 2 files changed, 79 insertions(+), 2 deletions(-) diff --git a/include/upipe-av/upipe_avfilter.h b/include/upipe-av/upipe_avfilter.h index 8cad3fd4b..293a239fd 100644 --- a/include/upipe-av/upipe_avfilter.h +++ b/include/upipe-av/upipe_avfilter.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2018 OpenHeadend S.A.R.L. - * Copyright (C) 2019-2020 EasyTools + * Copyright (C) 2019-2025 EasyTools * * Authors: Clément Vasseur * Arnaud de Turckheim @@ -49,6 +49,9 @@ enum upipe_avfilt_command { UPIPE_AVFILT_SET_FILTERS_DESC, /** set the hardware config (const char *, const char *) */ UPIPE_AVFILT_SET_HW_CONFIG, + /** sends a command to one or more filter instances + (const char *, const char *, const char *) */ + UPIPE_AVFILT_SEND_COMMAND, }; /** @This converts @ref upipe_avfilt_command to a string. @@ -61,6 +64,7 @@ static inline const char *upipe_avfilt_command_str(int command) switch ((enum upipe_avfilt_command)command) { UBASE_CASE_TO_STR(UPIPE_AVFILT_SET_FILTERS_DESC); UBASE_CASE_TO_STR(UPIPE_AVFILT_SET_HW_CONFIG); + UBASE_CASE_TO_STR(UPIPE_AVFILT_SEND_COMMAND); case UPIPE_AVFILT_SENTINEL: break; } return NULL; @@ -95,6 +99,46 @@ static inline int upipe_avfilt_set_hw_config(struct upipe *upipe, hw_type, hw_device); } +/** @This sends a command to one or more filter instances + * + * @param upipe description structure of the pipe + * @param target the filter(s) to which the command should be sent "all" sends + * to all filters otherwise it can be a filter or filter instance name which + * will send the command to all matching filters. + * @param command the command to send + * @param arg the arguments of the command + * @return an error code + */ +static inline int upipe_avfilt_send_command(struct upipe *upipe, + const char *target, + const char *command, + const char *arg) +{ + return upipe_control(upipe, UPIPE_AVFILT_SEND_COMMAND, + UPIPE_AVFILT_SIGNATURE, + target, command, arg); +} + +/** @This sends a command to one or more filter instances + * + * @param upipe description structure of the pipe + * @param target the filter(s) to which the command should be sent "all" sends + * to all filters otherwise it can be a filter or filter instance name which + * will send the command to all matching filters. + * @param command the command to send + * @param format the arguments format string of the command + * @return an error code + */ +UBASE_FMT_PRINTF(4, 5) +static inline int upipe_avfilt_send_command_va(struct upipe *upipe, + const char *target, + const char *command, + const char *format, ...) +{ + UBASE_VARARG(upipe_avfilt_send_command(upipe, target, command, string), + UBASE_ERR_INVALID); +} + /** @This returns the management structure for all avfilter pipes. * * @return pointer to manager diff --git a/lib/upipe-av/upipe_avfilter.c b/lib/upipe-av/upipe_avfilter.c index 39d00d316..6c75af5bc 100644 --- a/lib/upipe-av/upipe_avfilter.c +++ b/lib/upipe-av/upipe_avfilter.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2018 OpenHeadend S.A.R.L. - * Copyright (C) 2019-2020 EasyTools + * Copyright (C) 2019-2025 EasyTools * * Authors: Clément Vasseur * Arnaud de Turckheim @@ -1867,6 +1867,32 @@ static int _upipe_avfilt_set_hw_config(struct upipe *upipe, return UBASE_ERR_NONE; } +/** @This sends a command to one or more filter instances + * + * @param upipe description structure of the pipe + * @param target the filter(s) to which the command should be sent "all" sends + * to all filters otherwise it can be a filter or filter instance name which + * will send the command to all matching filters. + * @param command the command to send + * @param arg the arguments of the command + * @return an error code + */ +static int _upipe_avfilt_send_command(struct upipe *upipe, const char *target, + const char *command, const char *arg) +{ + struct upipe_avfilt *upipe_avfilt = upipe_avfilt_from_upipe(upipe); + + if (unlikely(!upipe_avfilt->configured)) + return UBASE_ERR_INVALID; + + int err = avfilter_graph_send_command(upipe_avfilt->filter_graph, target, + command, arg, NULL, 0, 0); + if (err < 0) + return UBASE_ERR_EXTERNAL; + + return UBASE_ERR_NONE; +} + /** @internal @This sets the input pipe flow definition for video. * * @param upipe description structure of the pipe @@ -2488,6 +2514,13 @@ static int upipe_avfilt_control(struct upipe *upipe, const char *hw_device = va_arg(args, const char *); return _upipe_avfilt_set_hw_config(upipe, hw_type, hw_device); } + case UPIPE_AVFILT_SEND_COMMAND: { + UBASE_SIGNATURE_CHECK(args, UPIPE_AVFILT_SIGNATURE) + const char *target = va_arg(args, const char *); + const char *command = va_arg(args, const char *); + const char *arg = va_arg(args, const char *); + return _upipe_avfilt_send_command(upipe, target, command, arg); + } default: return UBASE_ERR_UNHANDLED; }