node: schedule upstream first

In pull mode, schedule all upstream nodes first, if any of them
produce output, push it into the current node.
Underrun streams without input on audiomixer, avoids glitch when
starting a new stream.
This commit is contained in:
Wim Taymans 2017-04-12 11:24:11 +02:00
parent 4c7b56020a
commit d9bb116d27
3 changed files with 18 additions and 17 deletions

View file

@ -258,6 +258,7 @@ do_pull (PinosNode *this)
{ {
SpaResult res = SPA_RESULT_OK; SpaResult res = SPA_RESULT_OK;
PinosPort *inport; PinosPort *inport;
bool have_output = false;
spa_list_for_each (inport, &this->input_ports, link) { spa_list_for_each (inport, &this->input_ports, link) {
PinosLink *link; PinosLink *link;
@ -288,23 +289,23 @@ do_pull (PinosNode *this)
if (res == SPA_RESULT_NEED_INPUT) { if (res == SPA_RESULT_NEED_INPUT) {
res = do_pull (outport->node); res = do_pull (outport->node);
*pi = *po;
pinos_log_trace ("node %p: pull return %d", outport->node, res); pinos_log_trace ("node %p: pull return %d", outport->node, res);
} }
else if (res == SPA_RESULT_HAVE_OUTPUT) { else if (res < 0 && res != SPA_RESULT_HAVE_OUTPUT) {
*pi = *po;
}
else
pinos_log_warn ("node %p: got process output %d", outport->node, res); pinos_log_warn ("node %p: got process output %d", outport->node, res);
} }
if (pi->buffer_id != SPA_ID_INVALID) {
pinos_log_trace ("node %p: process input %d %d", this, pi->status, pi->buffer_id); if (res == SPA_RESULT_HAVE_OUTPUT) {
res = spa_node_process_input (this->node); *pi = *po;
if (res == SPA_RESULT_HAVE_OUTPUT) pinos_log_trace ("node %p: have output %d %d", this, pi->status, pi->buffer_id);
break; have_output = true;
} }
} }
}
if (have_output) {
pinos_log_trace ("node %p: doing process input", this);
res = spa_node_process_input (this->node);
}
return res; return res;
} }

View file

@ -733,7 +733,7 @@ spa_audiomixer_node_process_input (SpaNode *node)
spa_log_trace (this->log, "audiomixer %p: queue buffer %d on port %d %zd %zd", spa_log_trace (this->log, "audiomixer %p: queue buffer %d on port %d %zd %zd",
this, b->outbuf->id, i, port->queued_bytes, min_queued); this, b->outbuf->id, i, port->queued_bytes, min_queued);
} }
if (min_queued == SIZE_MAX || port->queued_bytes < min_queued) if (port->queued_bytes > 0 && port->queued_bytes < min_queued)
min_queued = port->queued_bytes; min_queued = port->queued_bytes;
} }
@ -772,7 +772,7 @@ spa_audiomixer_node_process_output (SpaNode *node)
res = SPA_RESULT_NEED_INPUT; res = SPA_RESULT_NEED_INPUT;
/* produce more output if possible */ /* produce more output if possible */
if (this->state == STATE_OUT) { if (this->state == STATE_OUT) {
size_t min_queued = -1; size_t min_queued = SIZE_MAX;
for (i = 0; i < MAX_PORTS; i++) { for (i = 0; i < MAX_PORTS; i++) {
SpaAudioMixerPort *port = &this->in_ports[i]; SpaAudioMixerPort *port = &this->in_ports[i];
@ -780,10 +780,10 @@ spa_audiomixer_node_process_output (SpaNode *node)
if (port->io == NULL || port->n_buffers == 0) if (port->io == NULL || port->n_buffers == 0)
continue; continue;
if (min_queued == -1 || port->queued_bytes < min_queued) if (port->queued_bytes > 0 && port->queued_bytes < min_queued)
min_queued = port->queued_bytes; min_queued = port->queued_bytes;
} }
if (min_queued != -1 && min_queued > 0) { if (min_queued != SIZE_MAX && min_queued > 0) {
res = mix_output (this, min_queued); res = mix_output (this, min_queued);
} else { } else {
this->state = STATE_IN; this->state = STATE_IN;

View file

@ -311,7 +311,7 @@ make_nodes (AppData *data)
spa_pod_builder_init (&b, buffer, sizeof (buffer)); spa_pod_builder_init (&b, buffer, sizeof (buffer));
spa_pod_builder_props (&b, &f[0], data->type.props, spa_pod_builder_props (&b, &f[0], data->type.props,
SPA_POD_PROP (&f[1], data->type.props_device, 0, SPA_POD_TYPE_STRING, 1, "hw:0"), SPA_POD_PROP (&f[1], data->type.props_device, 0, SPA_POD_TYPE_STRING, 1, "hw:1"),
SPA_POD_PROP (&f[1], data->type.props_min_latency, 0, SPA_POD_TYPE_INT, 1, 256), SPA_POD_PROP (&f[1], data->type.props_min_latency, 0, SPA_POD_TYPE_INT, 1, 256),
SPA_POD_PROP (&f[1], data->type.props_live, 0, SPA_POD_TYPE_BOOL, 1, false)); SPA_POD_PROP (&f[1], data->type.props_live, 0, SPA_POD_TYPE_BOOL, 1, false));
props = SPA_POD_BUILDER_DEREF (&b, f[0].ref, SpaProps); props = SPA_POD_BUILDER_DEREF (&b, f[0].ref, SpaProps);