From 79866a93cdd993b2ac46bcc6553c89a90d7f00dc Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Tue, 22 Jun 2021 16:10:13 +0200 Subject: [PATCH] Param: add process latency param and info --- spa/include/spa/param/latency-utils.h | 46 +++++++++++++++++++++++++++ spa/include/spa/param/param.h | 9 ++++++ spa/include/spa/param/type-info.h | 14 +++++++- spa/include/spa/utils/type-info.h | 1 + spa/include/spa/utils/type.h | 1 + src/examples/audio-dsp-filter.c | 15 ++++++++- src/pipewire/filter.c | 15 +++++++-- 7 files changed, 97 insertions(+), 4 deletions(-) diff --git a/spa/include/spa/param/latency-utils.h b/spa/include/spa/param/latency-utils.h index b8874a4d6..a68925d1d 100644 --- a/spa/include/spa/param/latency-utils.h +++ b/spa/include/spa/param/latency-utils.h @@ -112,6 +112,52 @@ spa_latency_build(struct spa_pod_builder *builder, uint32_t id, const struct spa SPA_PARAM_LATENCY_maxNs, SPA_POD_Long(info->max_ns)); } +struct spa_process_latency_info { + float quantum; + uint32_t rate; + uint64_t ns; +}; + +#define SPA_PROCESS_LATENCY_INFO_INIT(...) (struct spa_process_latency_info) { __VA_ARGS__ } + +static inline int +spa_process_latency_parse(const struct spa_pod *latency, struct spa_process_latency_info *info) +{ + int res; + spa_zero(*info); + if ((res = spa_pod_parse_object(latency, + SPA_TYPE_OBJECT_ParamProcessLatency, NULL, + SPA_PARAM_PROCESS_LATENCY_quantum, SPA_POD_OPT_Float(&info->quantum), + SPA_PARAM_PROCESS_LATENCY_rate, SPA_POD_OPT_Int(&info->rate), + SPA_PARAM_PROCESS_LATENCY_ns, SPA_POD_OPT_Long(&info->ns))) < 0) + return res; + return 0; +} + +static inline struct spa_pod * +spa_process_latency_build(struct spa_pod_builder *builder, uint32_t id, + const struct spa_process_latency_info *info) +{ + return (struct spa_pod *)spa_pod_builder_add_object(builder, + SPA_TYPE_OBJECT_ParamProcessLatency, id, + SPA_PARAM_PROCESS_LATENCY_quantum, SPA_POD_Float(info->quantum), + SPA_PARAM_PROCESS_LATENCY_rate, SPA_POD_Int(info->rate), + SPA_PARAM_PROCESS_LATENCY_ns, SPA_POD_Long(info->ns)); +} + +static inline int +spa_process_latency_info_add(const struct spa_process_latency_info *process, + struct spa_latency_info *info) +{ + info->min_quantum += process->quantum; + info->max_quantum += process->quantum; + info->min_rate += process->rate; + info->max_rate += process->rate; + info->min_ns += process->ns; + info->max_ns += process->ns; + return 0; +} + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/spa/include/spa/param/param.h b/spa/include/spa/param/param.h index 902663791..e2c3c5c8a 100644 --- a/spa/include/spa/param/param.h +++ b/spa/include/spa/param/param.h @@ -57,6 +57,7 @@ enum spa_param_type { SPA_PARAM_Route, /**< routing configuration as SPA_TYPE_OBJECT_ParamRoute */ SPA_PARAM_Control, /**< Control parameter, a SPA_TYPE_Sequence */ SPA_PARAM_Latency, /**< latency reporting, a SPA_TYPE_OBJECT_ParamLatency */ + SPA_PARAM_ProcessLatency, /**< processing latency, a SPA_TYPE_OBJECT_ParamProcessLatency */ }; /** information about a parameter */ @@ -185,6 +186,14 @@ enum spa_param_latency { SPA_PARAM_LATENCY_maxNs, /**< max latency (Long) in nanoseconds */ }; +/** properties for SPA_TYPE_OBJECT_ParamProcessLatency */ +enum spa_param_process_latency { + SPA_PARAM_PROCESS_LATENCY_START, + SPA_PARAM_PROCESS_LATENCY_quantum, /**< latency relative to quantum (Float) */ + SPA_PARAM_PROCESS_LATENCY_rate, /**< latency (Int) relative to rate */ + SPA_PARAM_PROCESS_LATENCY_ns, /**< latency (Long) in nanoseconds */ +}; + /** * \} */ diff --git a/spa/include/spa/param/type-info.h b/spa/include/spa/param/type-info.h index 663154fe4..705e2978a 100644 --- a/spa/include/spa/param/type-info.h +++ b/spa/include/spa/param/type-info.h @@ -60,6 +60,7 @@ static const struct spa_type_info spa_type_param[] = { { SPA_PARAM_Route, SPA_TYPE_OBJECT_ParamRoute, SPA_TYPE_INFO_PARAM_ID_BASE "Route", NULL }, { SPA_PARAM_Control, SPA_TYPE_Sequence, SPA_TYPE_INFO_PARAM_ID_BASE "Control", NULL }, { SPA_PARAM_Latency, SPA_TYPE_OBJECT_ParamLatency, SPA_TYPE_INFO_PARAM_ID_BASE "Latency", NULL }, + { SPA_PARAM_ProcessLatency, SPA_TYPE_OBJECT_ParamProcessLatency, SPA_TYPE_INFO_PARAM_ID_BASE "ProcessLatency", NULL }, { 0, 0, NULL, NULL }, }; @@ -385,7 +386,7 @@ static const struct spa_type_info spa_type_profiler[] = { }; #define SPA_TYPE_INFO_PARAM_Latency SPA_TYPE_INFO_PARAM_BASE "Latency" -#define SPA_TYPE_INFO_PARAM_LATENCY_BASE SPA_TYPE_INFO_PARAM_Latency ":" +#define SPA_TYPE_INFO_PARAM_LATENCY_BASE SPA_TYPE_INFO_PARAM_Latency ":" static const struct spa_type_info spa_type_param_latency[] = { { SPA_PARAM_LATENCY_START, SPA_TYPE_Id, SPA_TYPE_INFO_PARAM_LATENCY_BASE, spa_type_param, }, @@ -399,6 +400,17 @@ static const struct spa_type_info spa_type_param_latency[] = { { 0, 0, NULL, NULL }, }; +#define SPA_TYPE_INFO_PARAM_ProcessLatency SPA_TYPE_INFO_PARAM_BASE "ProcessLatency" +#define SPA_TYPE_INFO_PARAM_PROCESS_LATENCY_BASE SPA_TYPE_INFO_PARAM_ProcessLatency ":" + +static const struct spa_type_info spa_type_param_process_latency[] = { + { SPA_PARAM_PROCESS_LATENCY_START, SPA_TYPE_Id, SPA_TYPE_INFO_PARAM_LATENCY_BASE, spa_type_param, }, + { SPA_PARAM_PROCESS_LATENCY_quantum, SPA_TYPE_Float, SPA_TYPE_INFO_PARAM_PROCESS_LATENCY_BASE "quantum", NULL, }, + { SPA_PARAM_PROCESS_LATENCY_rate, SPA_TYPE_Int, SPA_TYPE_INFO_PARAM_PROCESS_LATENCY_BASE "rate", NULL, }, + { SPA_PARAM_PROCESS_LATENCY_ns, SPA_TYPE_Long, SPA_TYPE_INFO_PARAM_PROCESS_LATENCY_BASE "ns", NULL, }, + { 0, 0, NULL, NULL }, +}; + /** * \} */ diff --git a/spa/include/spa/utils/type-info.h b/spa/include/spa/utils/type-info.h index 9d316828a..029327871 100644 --- a/spa/include/spa/utils/type-info.h +++ b/spa/include/spa/utils/type-info.h @@ -124,6 +124,7 @@ static const struct spa_type_info spa_types[] = { { SPA_TYPE_OBJECT_ParamRoute, SPA_TYPE_Object, SPA_TYPE_INFO_PARAM_Route, spa_type_param_route }, { SPA_TYPE_OBJECT_Profiler, SPA_TYPE_Object, SPA_TYPE_INFO_Profiler, spa_type_profiler }, { SPA_TYPE_OBJECT_ParamLatency, SPA_TYPE_Object, SPA_TYPE_INFO_PARAM_Latency, spa_type_param_latency }, + { SPA_TYPE_OBJECT_ParamProcessLatency, SPA_TYPE_Object, SPA_TYPE_INFO_PARAM_ProcessLatency, spa_type_param_process_latency }, { 0, 0, NULL, NULL } }; diff --git a/spa/include/spa/utils/type.h b/spa/include/spa/utils/type.h index b4dc1f108..3682ef8ad 100644 --- a/spa/include/spa/utils/type.h +++ b/spa/include/spa/utils/type.h @@ -96,6 +96,7 @@ enum { SPA_TYPE_OBJECT_ParamRoute, SPA_TYPE_OBJECT_Profiler, SPA_TYPE_OBJECT_ParamLatency, + SPA_TYPE_OBJECT_ParamProcessLatency, _SPA_TYPE_OBJECT_LAST, /**< not part of ABI */ /* vendor extensions */ diff --git a/src/examples/audio-dsp-filter.c b/src/examples/audio-dsp-filter.c index b04fdd66b..e6eee1349 100644 --- a/src/examples/audio-dsp-filter.c +++ b/src/examples/audio-dsp-filter.c @@ -27,6 +27,9 @@ #include #include +#include +#include + #include #include @@ -87,6 +90,9 @@ static void do_quit(void *userdata, int signal_number) int main(int argc, char *argv[]) { struct data data = { 0, }; + const struct spa_pod *params[1]; + uint8_t buffer[1024]; + struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer)); pw_init(&argc, &argv); @@ -138,11 +144,18 @@ int main(int argc, char *argv[]) NULL), NULL, 0); + params[0] = spa_process_latency_build(&b, + SPA_PARAM_ProcessLatency, + &SPA_PROCESS_LATENCY_INFO_INIT( + .ns = 10 * SPA_NSEC_PER_MSEC + )); + + /* Now connect this filter. We ask that our process function is * called in a realtime thread. */ if (pw_filter_connect(data.filter, PW_FILTER_FLAG_RT_PROCESS, - NULL, 0) < 0) { + params, 1) < 0) { fprintf(stderr, "can't connect\n"); return -1; } diff --git a/src/pipewire/filter.c b/src/pipewire/filter.c index 8281955bd..82a0cb06d 100644 --- a/src/pipewire/filter.c +++ b/src/pipewire/filter.c @@ -147,10 +147,13 @@ struct filter { uint32_t change_mask_all; struct spa_node_info info; struct spa_list param_list; -#define IDX_Props 0 -#define N_NODE_PARAMS 1 +#define IDX_Props 0 +#define IDX_ProcessLatency 1 +#define N_NODE_PARAMS 2 struct spa_param_info params[N_NODE_PARAMS]; + struct spa_process_latency_info process_latency; + struct data data; uintptr_t seq; struct pw_time time; @@ -173,6 +176,8 @@ static int get_param_index(uint32_t id) switch (id) { case SPA_PARAM_Props: return IDX_Props; + case SPA_PARAM_ProcessLatency: + return IDX_ProcessLatency; default: return -1; } @@ -236,6 +241,8 @@ static struct param *add_param(struct filter *impl, struct port *port, } } } + if (id == SPA_PARAM_ProcessLatency && port == NULL) + spa_process_latency_parse(param, &impl->process_latency); p->id = id; p->flags = flags; @@ -732,6 +739,9 @@ static int default_latency(struct filter *impl, struct port *port, enum spa_dire continue; spa_latency_info_combine(&info, &p->latency[direction]); } + + spa_process_latency_info_add(&impl->process_latency, &info); + spa_list_for_each(p, &impl->port_list, link) { uint8_t buffer[4096]; struct spa_pod_builder b; @@ -1431,6 +1441,7 @@ pw_filter_connect(struct pw_filter *filter, impl->info.flags = impl->process_rt ? SPA_NODE_FLAG_RT : 0; impl->info.props = &filter->properties->dict; impl->params[IDX_Props] = SPA_PARAM_INFO(SPA_PARAM_Props, SPA_PARAM_INFO_WRITE); + impl->params[IDX_ProcessLatency] = SPA_PARAM_INFO(SPA_PARAM_ProcessLatency, SPA_PARAM_INFO_WRITE); impl->info.params = impl->params; impl->info.n_params = N_NODE_PARAMS; impl->info.change_mask = impl->change_mask_all;