mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2026-02-04 04:06:29 -05:00
filter-graph: allow 0 input and output ports
There is no reason to fail when there is no input or output port. We can simply run the graph with what there is. Even if there is no input or output at all, running one instance of the plugins is possible. Add a busy builtin plugin that has no ports and keeps the CPU IDLE or busy for the give percent.
This commit is contained in:
parent
ba3e564e34
commit
a97c4d10af
3 changed files with 144 additions and 18 deletions
|
|
@ -1030,11 +1030,6 @@ static struct descriptor *descriptor_load(struct impl *impl, const char *type,
|
|||
}
|
||||
}
|
||||
}
|
||||
if (desc->n_input == 0 && desc->n_output == 0 && desc->n_control == 0 && desc->n_notify == 0) {
|
||||
spa_log_error(impl->log, "plugin has no input and no output ports");
|
||||
res = -ENOTSUP;
|
||||
goto exit;
|
||||
}
|
||||
for (i = 0; i < desc->n_control; i++) {
|
||||
p = desc->control[i];
|
||||
desc->default_control[i] = get_default(impl, desc, p);
|
||||
|
|
@ -1794,7 +1789,7 @@ static int setup_graph(struct graph *graph)
|
|||
struct port *port;
|
||||
struct graph_port *gp;
|
||||
struct graph_hndl *gh;
|
||||
uint32_t i, j, n, n_input, n_output, n_hndl = 0;
|
||||
uint32_t i, j, n, n_input, n_output, n_hndl = 0, n_out_hndl;
|
||||
int res;
|
||||
struct descriptor *desc;
|
||||
const struct spa_fga_descriptor *d;
|
||||
|
|
@ -1815,16 +1810,11 @@ static int setup_graph(struct graph *graph)
|
|||
SPA_FLAG_IS_SET(first->desc->desc->flags, SPA_FGA_DESCRIPTOR_SUPPORTS_NULL_DATA) &&
|
||||
SPA_FLAG_IS_SET(last->desc->desc->flags, SPA_FGA_DESCRIPTOR_SUPPORTS_NULL_DATA);
|
||||
|
||||
if (n_input == 0) {
|
||||
spa_log_error(impl->log, "no inputs");
|
||||
res = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
if (n_output == 0) {
|
||||
spa_log_error(impl->log, "no outputs");
|
||||
res = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
if (n_input == 0)
|
||||
n_input = n_output;
|
||||
if (n_output == 0)
|
||||
n_output = n_input;
|
||||
|
||||
if (graph->n_inputs == 0)
|
||||
graph->n_inputs = impl->info.n_inputs;
|
||||
if (graph->n_inputs == 0)
|
||||
|
|
@ -1835,12 +1825,14 @@ static int setup_graph(struct graph *graph)
|
|||
|
||||
/* compare to the requested number of inputs and duplicate the
|
||||
* graph n_hndl times when needed. */
|
||||
n_hndl = graph->n_inputs / n_input;
|
||||
n_hndl = n_input ? graph->n_inputs / n_input : 1;
|
||||
|
||||
if (graph->n_outputs == 0)
|
||||
graph->n_outputs = n_output * n_hndl;
|
||||
|
||||
if (n_hndl != graph->n_outputs / n_output) {
|
||||
n_out_hndl = n_output ? graph->n_outputs / n_output : 1;
|
||||
|
||||
if (n_hndl != n_out_hndl) {
|
||||
spa_log_error(impl->log, "invalid ports. The input stream has %1$d ports and "
|
||||
"the filter has %2$d inputs. The output stream has %3$d ports "
|
||||
"and the filter has %4$d outputs. input:%1$d / input:%2$d != "
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
#include <sys/wait.h>
|
||||
#include <sys/socket.h>
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <spa/utils/json.h>
|
||||
#include <spa/utils/result.h>
|
||||
|
|
@ -3115,6 +3116,107 @@ static const struct spa_fga_descriptor noisegate_desc = {
|
|||
.cleanup = builtin_cleanup,
|
||||
};
|
||||
|
||||
/* busy */
|
||||
struct busy_impl {
|
||||
struct plugin *plugin;
|
||||
|
||||
struct spa_fga_dsp *dsp;
|
||||
struct spa_log *log;
|
||||
|
||||
unsigned long rate;
|
||||
|
||||
float wait_scale;
|
||||
float cpu_scale;
|
||||
};
|
||||
|
||||
static void *busy_instantiate(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor * Descriptor,
|
||||
unsigned long SampleRate, int index, const char *config)
|
||||
{
|
||||
struct plugin *pl = SPA_CONTAINER_OF(plugin, struct plugin, plugin);
|
||||
struct busy_impl *impl;
|
||||
struct spa_json it[1];
|
||||
const char *val;
|
||||
char key[256];
|
||||
float wait_percent = 0.0f, cpu_percent = 0.0f;
|
||||
int len;
|
||||
|
||||
if (config != NULL) {
|
||||
if (spa_json_begin_object(&it[0], config, strlen(config)) <= 0) {
|
||||
spa_log_error(pl->log, "busy:config must be an object");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while ((len = spa_json_object_next(&it[0], key, sizeof(key), &val)) > 0) {
|
||||
if (spa_streq(key, "wait-percent")) {
|
||||
if (spa_json_parse_float(val, len, &wait_percent) <= 0) {
|
||||
spa_log_error(pl->log, "busy:wait-percent requires a number");
|
||||
return NULL;
|
||||
}
|
||||
} else if (spa_streq(key, "cpu-percent")) {
|
||||
if (spa_json_parse_float(val, len, &cpu_percent) <= 0) {
|
||||
spa_log_error(pl->log, "busy:cpu-percent requires a number");
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
spa_log_warn(pl->log, "busy: ignoring config key: '%s'", key);
|
||||
}
|
||||
}
|
||||
if (wait_percent <= 0.0f)
|
||||
wait_percent = 0.0f;
|
||||
if (cpu_percent <= 0.0f)
|
||||
cpu_percent = 0.0f;
|
||||
}
|
||||
|
||||
impl = calloc(1, sizeof(*impl));
|
||||
if (impl == NULL)
|
||||
return NULL;
|
||||
|
||||
impl->plugin = pl;
|
||||
impl->dsp = pl->dsp;
|
||||
impl->log = pl->log;
|
||||
impl->rate = SampleRate;
|
||||
impl->wait_scale = wait_percent * SPA_NSEC_PER_SEC / (100.0f * SampleRate);
|
||||
impl->cpu_scale = cpu_percent * SPA_NSEC_PER_SEC / (100.0f * SampleRate);
|
||||
spa_log_info(impl->log, "wait-percent:%f cpu-percent:%f", wait_percent, cpu_percent);
|
||||
|
||||
return impl;
|
||||
}
|
||||
|
||||
static void busy_run(void * Instance, unsigned long SampleCount)
|
||||
{
|
||||
struct busy_impl *impl = Instance;
|
||||
struct timespec ts;
|
||||
uint64_t busy_nsec;
|
||||
|
||||
if (impl->wait_scale > 0.0f) {
|
||||
busy_nsec = (uint64_t)(impl->wait_scale * SampleCount);
|
||||
ts.tv_sec = busy_nsec / SPA_NSEC_PER_SEC;
|
||||
ts.tv_nsec = busy_nsec % SPA_NSEC_PER_SEC;
|
||||
clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL);
|
||||
}
|
||||
if (impl->cpu_scale > 0.0f) {
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
busy_nsec = SPA_TIMESPEC_TO_NSEC(&ts);
|
||||
busy_nsec += (uint64_t)(impl->cpu_scale * SampleCount);
|
||||
do {
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
} while ((uint64_t)SPA_TIMESPEC_TO_NSEC(&ts) < busy_nsec);
|
||||
}
|
||||
}
|
||||
|
||||
static const struct spa_fga_descriptor busy_desc = {
|
||||
.name = "busy",
|
||||
.flags = SPA_FGA_DESCRIPTOR_SUPPORTS_NULL_DATA,
|
||||
|
||||
.n_ports = 0,
|
||||
.ports = NULL,
|
||||
|
||||
.instantiate = busy_instantiate,
|
||||
.connect_port = builtin_connect_port,
|
||||
.run = busy_run,
|
||||
.cleanup = builtin_cleanup,
|
||||
};
|
||||
|
||||
static const struct spa_fga_descriptor * builtin_descriptor(unsigned long Index)
|
||||
{
|
||||
switch(Index) {
|
||||
|
|
@ -3180,6 +3282,8 @@ static const struct spa_fga_descriptor * builtin_descriptor(unsigned long Index)
|
|||
return &zeroramp_desc;
|
||||
case 30:
|
||||
return &noisegate_desc;
|
||||
case 31:
|
||||
return &busy_desc;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -652,6 +652,36 @@ extern struct spa_handle_factory spa_filter_graph_factory;
|
|||
* of "Attack (s)" seconds. The noise gate stays open for at least "Hold (s)"
|
||||
* seconds before it can close again.
|
||||
*
|
||||
* ### Busy
|
||||
*
|
||||
* The `busy` plugin has no input or output ports and it can be used to keep the
|
||||
* CPU or graph busy for the given percent of time.
|
||||
*
|
||||
* The node requires a `config` section with extra configuration:
|
||||
*
|
||||
*\code{.unparsed}
|
||||
* filter.graph = {
|
||||
* nodes = [
|
||||
* {
|
||||
* type = builtin
|
||||
* name = ...
|
||||
* label = busy
|
||||
* config = {
|
||||
* wait-percent = 0.0
|
||||
* cpu-percent = 50.0
|
||||
* }
|
||||
* ...
|
||||
* }
|
||||
* }
|
||||
* ...
|
||||
* }
|
||||
*\endcode
|
||||
*
|
||||
* - `wait-percent` the percentage of time to wait. This keeps the graph busy but
|
||||
* not the CPU. Default 0.0
|
||||
* - `cpu-percent` the percentage of time to keep the CPU busy. This keeps both the
|
||||
* graph and CPU busy. Default 0.0
|
||||
*
|
||||
*
|
||||
* ## SOFA filters
|
||||
*
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue