mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-02 09:01:50 -05:00
filter-graph: warn about unaligned streams
Keep track of min/max latencies and warn when streams are unaligned.
This commit is contained in:
parent
8e4c211a80
commit
46f5740604
1 changed files with 44 additions and 16 deletions
|
|
@ -116,9 +116,10 @@ struct node {
|
||||||
void *hndl[MAX_HNDL];
|
void *hndl[MAX_HNDL];
|
||||||
|
|
||||||
unsigned int n_deps;
|
unsigned int n_deps;
|
||||||
|
|
||||||
uint32_t latency_index;
|
uint32_t latency_index;
|
||||||
float latency;
|
|
||||||
|
float min_latency;
|
||||||
|
float max_latency;
|
||||||
|
|
||||||
unsigned int disabled:1;
|
unsigned int disabled:1;
|
||||||
unsigned int control_changed:1;
|
unsigned int control_changed:1;
|
||||||
|
|
@ -198,7 +199,8 @@ struct graph {
|
||||||
uint32_t outputs_position[SPA_AUDIO_MAX_CHANNELS];
|
uint32_t outputs_position[SPA_AUDIO_MAX_CHANNELS];
|
||||||
uint32_t n_outputs_position;
|
uint32_t n_outputs_position;
|
||||||
|
|
||||||
float latency;
|
float min_latency;
|
||||||
|
float max_latency;
|
||||||
|
|
||||||
unsigned activated:1;
|
unsigned activated:1;
|
||||||
unsigned setup:1;
|
unsigned setup:1;
|
||||||
|
|
@ -273,7 +275,8 @@ static void emit_filter_graph_info(struct impl *impl, bool full)
|
||||||
items[dict.n_items++] = SPA_DICT_ITEM("outputs.audio.position", out_pos);
|
items[dict.n_items++] = SPA_DICT_ITEM("outputs.audio.position", out_pos);
|
||||||
}
|
}
|
||||||
items[dict.n_items++] = SPA_DICT_ITEM("latency",
|
items[dict.n_items++] = SPA_DICT_ITEM("latency",
|
||||||
spa_dtoa(latency, sizeof(latency), graph->latency));
|
spa_dtoa(latency, sizeof(latency),
|
||||||
|
(graph->min_latency + graph->max_latency) / 2.0f));
|
||||||
impl->info.props = &dict;
|
impl->info.props = &dict;
|
||||||
spa_filter_graph_emit_info(&impl->hooks, &impl->info);
|
spa_filter_graph_emit_info(&impl->hooks, &impl->info);
|
||||||
impl->info.props = NULL;
|
impl->info.props = NULL;
|
||||||
|
|
@ -1535,7 +1538,7 @@ static int impl_activate(void *object, const struct spa_dict *props)
|
||||||
const struct spa_fga_plugin *p;
|
const struct spa_fga_plugin *p;
|
||||||
uint32_t i, j, max_samples = impl->quantum_limit, n_ports;
|
uint32_t i, j, max_samples = impl->quantum_limit, n_ports;
|
||||||
int res;
|
int res;
|
||||||
float *sd, *dd, *data, latency;
|
float *sd, *dd, *data, min_latency, max_latency;
|
||||||
const char *rate, *str;
|
const char *rate, *str;
|
||||||
|
|
||||||
if (graph->activated)
|
if (graph->activated)
|
||||||
|
|
@ -1661,30 +1664,55 @@ static int impl_activate(void *object, const struct spa_dict *props)
|
||||||
/* calculate latency */
|
/* calculate latency */
|
||||||
sort_reset(graph);
|
sort_reset(graph);
|
||||||
while ((node = sort_next_node(graph)) != NULL) {
|
while ((node = sort_next_node(graph)) != NULL) {
|
||||||
latency = 0.0f;
|
min_latency = FLT_MAX;
|
||||||
|
max_latency = 0.0f;
|
||||||
|
|
||||||
for (i = 0; i < node->desc->n_input; i++) {
|
for (i = 0; i < node->desc->n_input; i++) {
|
||||||
spa_list_for_each(link, &node->input_port[i].link_list, input_link)
|
spa_list_for_each(link, &node->input_port[i].link_list, input_link) {
|
||||||
latency = fmaxf(latency, link->output->node->latency);
|
min_latency = fminf(min_latency, link->output->node->min_latency);
|
||||||
|
max_latency = fmaxf(max_latency, link->output->node->max_latency);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
min_latency = min_latency == FLT_MAX ? 0.0f : min_latency;
|
||||||
|
|
||||||
if (node->latency_index != SPA_IDX_INVALID) {
|
if (node->latency_index != SPA_IDX_INVALID) {
|
||||||
port = &node->notify_port[node->latency_index];
|
port = &node->notify_port[node->latency_index];
|
||||||
latency += port->control_data[0];
|
min_latency += port->control_data[0];
|
||||||
|
max_latency += port->control_data[0];
|
||||||
|
|
||||||
}
|
}
|
||||||
node->latency = latency;
|
node->min_latency = min_latency;
|
||||||
spa_log_debug(impl->log, "%s latency:%f", node->name, latency);
|
node->max_latency = max_latency;
|
||||||
|
spa_log_info(impl->log, "%s latency:%f-%f", node->name, min_latency, max_latency);
|
||||||
}
|
}
|
||||||
latency = 0.0f;
|
min_latency = FLT_MAX;
|
||||||
|
max_latency = 0.0f;
|
||||||
for (i = 0; i < graph->n_outputs; i++) {
|
for (i = 0; i < graph->n_outputs; i++) {
|
||||||
struct graph_port *port = &graph->output[i];
|
struct graph_port *port = &graph->output[i];
|
||||||
latency = fmaxf(latency, port->node->latency);
|
max_latency = fmaxf(max_latency, port->node->max_latency);
|
||||||
|
min_latency = fminf(min_latency, port->node->min_latency);
|
||||||
}
|
}
|
||||||
|
min_latency = min_latency == FLT_MAX ? 0.0f : min_latency;
|
||||||
|
|
||||||
if (graph->latency != latency) {
|
spa_log_info(impl->log, "graph latency min:%f max:%f", min_latency, max_latency);
|
||||||
graph->latency = latency;
|
if (min_latency != max_latency) {
|
||||||
|
spa_log_warn(impl->log, "graph has unaligned latency min:%f max:%f, "
|
||||||
|
"consider adding delays or tweak node latency to "
|
||||||
|
"align the signals", min_latency, max_latency);
|
||||||
|
for (i = 0; i < graph->n_outputs; i++) {
|
||||||
|
struct graph_port *port = &graph->output[i];
|
||||||
|
if (min_latency != port->node->min_latency ||
|
||||||
|
max_latency != port->node->max_latency)
|
||||||
|
spa_log_warn(impl->log, "output port %d from %s min:%f max:%f",
|
||||||
|
i, port->node->name,
|
||||||
|
port->node->min_latency, port->node->max_latency);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if (graph->min_latency != min_latency || graph->max_latency != max_latency) {
|
||||||
|
graph->min_latency = min_latency;
|
||||||
|
graph->max_latency = max_latency;
|
||||||
impl->info.change_mask |= SPA_FILTER_GRAPH_CHANGE_MASK_PROPS;
|
impl->info.change_mask |= SPA_FILTER_GRAPH_CHANGE_MASK_PROPS;
|
||||||
spa_log_info(impl->log, "graph latency:%f", latency);
|
|
||||||
}
|
}
|
||||||
emit_filter_graph_info(impl, false);
|
emit_filter_graph_info(impl, false);
|
||||||
spa_filter_graph_emit_props_changed(&impl->hooks, SPA_DIRECTION_INPUT);
|
spa_filter_graph_emit_props_changed(&impl->hooks, SPA_DIRECTION_INPUT);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue