mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-04 13:30:12 -05:00
impl-link: handle mixer failures better
It is possible that the mixer input can't be created because of hitting the max limits of dsp mixer or client-node. Make sure we handle those errors, destroy the link and clean up properly.
This commit is contained in:
parent
a67f38f790
commit
7e387d842b
3 changed files with 38 additions and 25 deletions
|
|
@ -219,6 +219,8 @@ static struct mix *find_mix(struct port *p, uint32_t mix_id)
|
||||||
if (mix_id >= len) {
|
if (mix_id >= len) {
|
||||||
size_t need = sizeof(struct mix) * (mix_id + 1 - len);
|
size_t need = sizeof(struct mix) * (mix_id + 1 - len);
|
||||||
void *ptr = pw_array_add(&p->mix, need);
|
void *ptr = pw_array_add(&p->mix, need);
|
||||||
|
if (ptr == NULL)
|
||||||
|
return NULL;
|
||||||
memset(ptr, 0, need);
|
memset(ptr, 0, need);
|
||||||
}
|
}
|
||||||
mix = pw_array_get_unchecked(&p->mix, mix_id, struct mix);
|
mix = pw_array_get_unchecked(&p->mix, mix_id, struct mix);
|
||||||
|
|
|
||||||
|
|
@ -451,7 +451,7 @@ static int port_set_io(struct pw_impl_link *this, struct pw_impl_port *port, uin
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int select_io(struct pw_impl_link *this)
|
static void select_io(struct pw_impl_link *this)
|
||||||
{
|
{
|
||||||
struct impl *impl = SPA_CONTAINER_OF(this, struct impl, this);
|
struct impl *impl = SPA_CONTAINER_OF(this, struct impl, this);
|
||||||
struct spa_io_buffers *io;
|
struct spa_io_buffers *io;
|
||||||
|
|
@ -461,13 +461,9 @@ static int select_io(struct pw_impl_link *this)
|
||||||
io = this->rt.out_mix.io;
|
io = this->rt.out_mix.io;
|
||||||
if (io == NULL)
|
if (io == NULL)
|
||||||
io = &impl->io;
|
io = &impl->io;
|
||||||
if (io == NULL)
|
|
||||||
return -EIO;
|
|
||||||
|
|
||||||
this->io = io;
|
this->io = io;
|
||||||
*this->io = SPA_IO_BUFFERS_INIT;
|
*this->io = SPA_IO_BUFFERS_INIT;
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int do_allocation(struct pw_impl_link *this)
|
static int do_allocation(struct pw_impl_link *this)
|
||||||
|
|
@ -1229,6 +1225,16 @@ struct pw_impl_link *pw_context_create_link(struct pw_context *context,
|
||||||
spa_hook_list_init(&this->listener_list);
|
spa_hook_list_init(&this->listener_list);
|
||||||
|
|
||||||
impl->format_filter = format_filter;
|
impl->format_filter = format_filter;
|
||||||
|
this->info.format = NULL;
|
||||||
|
this->info.props = &this->properties->dict;
|
||||||
|
|
||||||
|
this->rt.out_mix.peer_id = input->global->id;
|
||||||
|
this->rt.in_mix.peer_id = output->global->id;
|
||||||
|
|
||||||
|
if ((res = pw_impl_port_init_mix(output, &this->rt.out_mix)) < 0)
|
||||||
|
goto error_output_mix;
|
||||||
|
if ((res = pw_impl_port_init_mix(input, &this->rt.in_mix)) < 0)
|
||||||
|
goto error_input_mix;
|
||||||
|
|
||||||
pw_impl_port_add_listener(input, &impl->input_port_listener, &input_port_events, impl);
|
pw_impl_port_add_listener(input, &impl->input_port_listener, &input_port_events, impl);
|
||||||
pw_impl_node_add_listener(input_node, &impl->input_node_listener, &input_node_events, impl);
|
pw_impl_node_add_listener(input_node, &impl->input_node_listener, &input_node_events, impl);
|
||||||
|
|
@ -1245,19 +1251,9 @@ struct pw_impl_link *pw_context_create_link(struct pw_context *context,
|
||||||
spa_list_append(&output->links, &this->output_link);
|
spa_list_append(&output->links, &this->output_link);
|
||||||
spa_list_append(&input->links, &this->input_link);
|
spa_list_append(&input->links, &this->input_link);
|
||||||
|
|
||||||
this->info.format = NULL;
|
|
||||||
this->info.props = &this->properties->dict;
|
|
||||||
|
|
||||||
impl->io = SPA_IO_BUFFERS_INIT;
|
impl->io = SPA_IO_BUFFERS_INIT;
|
||||||
|
|
||||||
this->rt.out_mix.peer_id = input->global->id;
|
select_io(this);
|
||||||
this->rt.in_mix.peer_id = output->global->id;
|
|
||||||
|
|
||||||
pw_impl_port_init_mix(output, &this->rt.out_mix);
|
|
||||||
pw_impl_port_init_mix(input, &this->rt.in_mix);
|
|
||||||
|
|
||||||
if ((res = select_io(this)) < 0)
|
|
||||||
goto error_no_io;
|
|
||||||
|
|
||||||
if (this->feedback) {
|
if (this->feedback) {
|
||||||
impl->inode = output_node;
|
impl->inode = output_node;
|
||||||
|
|
@ -1317,8 +1313,12 @@ error_work_queue:
|
||||||
res = -errno;
|
res = -errno;
|
||||||
pw_log_debug("work queue failed: %m");
|
pw_log_debug("work queue failed: %m");
|
||||||
goto error_free;
|
goto error_free;
|
||||||
error_no_io:
|
error_output_mix:
|
||||||
pw_log_debug("%p: can't set io %d (%s)", this, res, spa_strerror(res));
|
pw_log_error("%p: can't get output mix %d (%s)", this, res, spa_strerror(res));
|
||||||
|
goto error_free;
|
||||||
|
error_input_mix:
|
||||||
|
pw_log_error("%p: can't get input mix %d (%s)", this, res, spa_strerror(res));
|
||||||
|
pw_impl_port_release_mix(output, &this->rt.out_mix);
|
||||||
goto error_free;
|
goto error_free;
|
||||||
error_free:
|
error_free:
|
||||||
free(impl);
|
free(impl);
|
||||||
|
|
|
||||||
|
|
@ -214,16 +214,16 @@ int pw_impl_port_init_mix(struct pw_impl_port *port, struct pw_impl_port_mix *mi
|
||||||
if (port_id == SPA_ID_INVALID)
|
if (port_id == SPA_ID_INVALID)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
|
if ((res = spa_node_add_port(port->mix, port->direction, port_id, NULL)) < 0 &&
|
||||||
|
res != -ENOTSUP)
|
||||||
|
goto error_remove_map;
|
||||||
|
|
||||||
mix->port.direction = port->direction;
|
mix->port.direction = port->direction;
|
||||||
mix->port.port_id = port_id;
|
mix->port.port_id = port_id;
|
||||||
|
|
||||||
spa_list_append(&port->mix_list, &mix->link);
|
|
||||||
port->n_mix++;
|
|
||||||
mix->p = port;
|
mix->p = port;
|
||||||
|
|
||||||
spa_node_add_port(port->mix, port->direction, port_id, NULL);
|
if ((res = pw_impl_port_call_init_mix(port, mix)) < 0)
|
||||||
|
goto error_remove_port;
|
||||||
res = pw_impl_port_call_init_mix(port, mix);
|
|
||||||
|
|
||||||
/* set the same format on the mixer as on the port if any */
|
/* set the same format on the mixer as on the port if any */
|
||||||
{
|
{
|
||||||
|
|
@ -242,11 +242,20 @@ int pw_impl_port_init_mix(struct pw_impl_port *port, struct pw_impl_port_mix *mi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
spa_list_append(&port->mix_list, &mix->link);
|
||||||
|
port->n_mix++;
|
||||||
|
|
||||||
pw_log_debug("%p: init mix n_mix:%d %d.%d io:%p: (%s)", port,
|
pw_log_debug("%p: init mix n_mix:%d %d.%d io:%p: (%s)", port,
|
||||||
port->n_mix, port->port_id, mix->port.port_id,
|
port->n_mix, port->port_id, mix->port.port_id,
|
||||||
mix->io, spa_strerror(res));
|
mix->io, spa_strerror(res));
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
|
error_remove_port:
|
||||||
|
spa_node_remove_port(port->mix, port->direction, port_id);
|
||||||
|
error_remove_map:
|
||||||
|
pw_map_remove(&port->mix_port_map, port_id);
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
SPA_EXPORT
|
SPA_EXPORT
|
||||||
|
|
@ -261,7 +270,9 @@ int pw_impl_port_release_mix(struct pw_impl_port *port, struct pw_impl_port_mix
|
||||||
|
|
||||||
res = pw_impl_port_call_release_mix(port, mix);
|
res = pw_impl_port_call_release_mix(port, mix);
|
||||||
|
|
||||||
spa_node_remove_port(port->mix, port->direction, port_id);
|
if ((res = spa_node_remove_port(port->mix, port->direction, port_id)) < 0 &&
|
||||||
|
res != -ENOTSUP)
|
||||||
|
pw_log_warn("can't remove mix port %d: %s", port_id, spa_strerror(res));
|
||||||
|
|
||||||
pw_log_debug("%p: release mix %d %d.%d", port,
|
pw_log_debug("%p: release mix %d %d.%d", port,
|
||||||
port->n_mix, port->port_id, mix->port.port_id);
|
port->n_mix, port->port_id, mix->port.port_id);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue