mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-04 13:30:12 -05:00
impl-node: handle node <-> driver links with node_peer
Also handle the relation between a node and the driver with pw_node_peer, like we do with the links. Because these are refcounted, we only make one peer for a node that is linked to another node that is also the driver (pw-play -> sink) and we save some fds as well as some admin stuff and overhead for the refcounts. This in return then results in less problems getting all the refcounts right when adding/removing nodes.
This commit is contained in:
parent
1466d0ae78
commit
c89a68b0b4
5 changed files with 30 additions and 31 deletions
|
|
@ -1210,8 +1210,8 @@ static struct pw_proxy *node_export(struct pw_core *core, void *object, bool do_
|
||||||
/* the node might have been registered and added to a driver. When we export,
|
/* the node might have been registered and added to a driver. When we export,
|
||||||
* we will be assigned a new driver target from the server and we can forget our
|
* we will be assigned a new driver target from the server and we can forget our
|
||||||
* local ones. */
|
* local ones. */
|
||||||
pw_impl_node_remove_target(node, &node->rt.driver_target);
|
pw_node_peer_unref(spa_steal_ptr(node->from_driver_peer));
|
||||||
pw_impl_node_remove_target(node->driver_node, &node->rt.target);
|
pw_node_peer_unref(spa_steal_ptr(node->to_driver_peer));
|
||||||
|
|
||||||
data->allow_mlock = pw_properties_get_bool(node->properties, "mem.allow-mlock",
|
data->allow_mlock = pw_properties_get_bool(node->properties, "mem.allow-mlock",
|
||||||
data->context->settings.mem_allow_mlock);
|
data->context->settings.mem_allow_mlock);
|
||||||
|
|
|
||||||
|
|
@ -225,7 +225,7 @@ static void context_do_profile(void *data)
|
||||||
struct pw_node_activation *na;
|
struct pw_node_activation *na;
|
||||||
struct spa_fraction latency;
|
struct spa_fraction latency;
|
||||||
|
|
||||||
if (t->id == id || t->flags & PW_NODE_TARGET_PEER)
|
if (t->id == id)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (n != NULL) {
|
if (n != NULL) {
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,8 @@ struct impl {
|
||||||
|
|
||||||
/** \endcond */
|
/** \endcond */
|
||||||
|
|
||||||
static struct pw_node_peer *pw_node_peer_ref(struct pw_impl_node *onode, struct pw_impl_node *inode)
|
SPA_EXPORT
|
||||||
|
struct pw_node_peer *pw_node_peer_ref(struct pw_impl_node *onode, struct pw_impl_node *inode)
|
||||||
{
|
{
|
||||||
struct pw_node_peer *peer;
|
struct pw_node_peer *peer;
|
||||||
|
|
||||||
|
|
@ -70,7 +71,6 @@ static struct pw_node_peer *pw_node_peer_ref(struct pw_impl_node *onode, struct
|
||||||
peer->ref = 1;
|
peer->ref = 1;
|
||||||
peer->output = onode;
|
peer->output = onode;
|
||||||
copy_target(&peer->target, &inode->rt.target);
|
copy_target(&peer->target, &inode->rt.target);
|
||||||
peer->target.flags = PW_NODE_TARGET_PEER;
|
|
||||||
|
|
||||||
spa_list_append(&onode->peer_list, &peer->link);
|
spa_list_append(&onode->peer_list, &peer->link);
|
||||||
pw_log_debug("new peer %p from %p to %p", peer, onode, inode);
|
pw_log_debug("new peer %p from %p to %p", peer, onode, inode);
|
||||||
|
|
@ -79,9 +79,10 @@ static struct pw_node_peer *pw_node_peer_ref(struct pw_impl_node *onode, struct
|
||||||
return peer;
|
return peer;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pw_node_peer_unref(struct pw_node_peer *peer)
|
SPA_EXPORT
|
||||||
|
void pw_node_peer_unref(struct pw_node_peer *peer)
|
||||||
{
|
{
|
||||||
if (--peer->ref > 0)
|
if (peer == NULL || --peer->ref > 0)
|
||||||
return;
|
return;
|
||||||
spa_list_remove(&peer->link);
|
spa_list_remove(&peer->link);
|
||||||
pw_log_debug("remove peer %p from %p to %p", peer, peer->output, peer->target.node);
|
pw_log_debug("remove peer %p from %p to %p", peer, peer->output, peer->target.node);
|
||||||
|
|
|
||||||
|
|
@ -899,9 +899,8 @@ int pw_impl_node_register(struct pw_impl_node *this,
|
||||||
this->rt.target.id = this->info.id;
|
this->rt.target.id = this->info.id;
|
||||||
this->rt.target.activation->position.clock.id = this->global->id;
|
this->rt.target.activation->position.clock.id = this->global->id;
|
||||||
|
|
||||||
copy_target(&this->rt.driver_target, &this->rt.target);
|
this->from_driver_peer = pw_node_peer_ref(this, this);
|
||||||
pw_impl_node_add_target(this, &this->rt.driver_target);
|
this->to_driver_peer = pw_node_peer_ref(this, this);
|
||||||
pw_impl_node_add_target(this, &this->rt.target);
|
|
||||||
|
|
||||||
pw_properties_setf(this->properties, PW_KEY_OBJECT_ID, "%d", this->global->id);
|
pw_properties_setf(this->properties, PW_KEY_OBJECT_ID, "%d", this->global->id);
|
||||||
pw_properties_setf(this->properties, PW_KEY_OBJECT_SERIAL, "%"PRIu64,
|
pw_properties_setf(this->properties, PW_KEY_OBJECT_SERIAL, "%"PRIu64,
|
||||||
|
|
@ -983,18 +982,16 @@ int pw_impl_node_set_driver(struct pw_impl_node *node, struct pw_impl_node *driv
|
||||||
old->name, old->info.id, driver->name, driver->info.id);
|
old->name, old->info.id, driver->name, driver->info.id);
|
||||||
|
|
||||||
/* make sure the old driver doesn't trigger the node anymore */
|
/* make sure the old driver doesn't trigger the node anymore */
|
||||||
pw_impl_node_remove_target(old, &node->rt.target);
|
pw_node_peer_unref(spa_steal_ptr(node->from_driver_peer));
|
||||||
/* make sure the node doesn't trigger the old driver anymore */
|
/* make sure the node doesn't trigger the old driver anymore */
|
||||||
pw_impl_node_remove_target(node, &node->rt.driver_target);
|
pw_node_peer_unref(spa_steal_ptr(node->to_driver_peer));
|
||||||
spa_zero(node->rt.driver_target);
|
|
||||||
|
|
||||||
node->driver_node = driver;
|
node->driver_node = driver;
|
||||||
node->moved = true;
|
node->moved = true;
|
||||||
|
|
||||||
/* first send new driver target to node, the node is not yet being
|
/* first send new driver target to node, the node is not yet being
|
||||||
* scheduled so it won't trigger yet */
|
* scheduled so it won't trigger yet */
|
||||||
copy_target(&node->rt.driver_target, &driver->rt.target);
|
node->to_driver_peer = pw_node_peer_ref(node, driver);
|
||||||
pw_impl_node_add_target(node, &node->rt.driver_target);
|
|
||||||
|
|
||||||
/* then set the new driver node activation */
|
/* then set the new driver node activation */
|
||||||
pw_impl_node_set_io(node, SPA_IO_Position,
|
pw_impl_node_set_io(node, SPA_IO_Position,
|
||||||
|
|
@ -1002,7 +999,7 @@ int pw_impl_node_set_driver(struct pw_impl_node *node, struct pw_impl_node *driv
|
||||||
sizeof(struct spa_io_position));
|
sizeof(struct spa_io_position));
|
||||||
|
|
||||||
/* and then make the driver trigger the node */
|
/* and then make the driver trigger the node */
|
||||||
pw_impl_node_add_target(driver, &node->rt.target);
|
node->from_driver_peer = pw_node_peer_ref(driver, node);
|
||||||
|
|
||||||
pw_impl_node_emit_driver_changed(node, old, driver);
|
pw_impl_node_emit_driver_changed(node, old, driver);
|
||||||
|
|
||||||
|
|
@ -2117,7 +2114,6 @@ static int node_xrun(void *data, uint64_t trigger, uint64_t delay, struct spa_po
|
||||||
{
|
{
|
||||||
struct pw_impl_node *this = data;
|
struct pw_impl_node *this = data;
|
||||||
struct pw_node_activation *a = this->rt.target.activation;
|
struct pw_node_activation *a = this->rt.target.activation;
|
||||||
struct pw_node_activation *da = this->rt.driver_target.activation;
|
|
||||||
struct spa_system *data_system = this->rt.target.system;
|
struct spa_system *data_system = this->rt.target.system;
|
||||||
uint64_t nsec = get_time_ns(data_system);
|
uint64_t nsec = get_time_ns(data_system);
|
||||||
int suppressed;
|
int suppressed;
|
||||||
|
|
@ -2126,8 +2122,8 @@ static int node_xrun(void *data, uint64_t trigger, uint64_t delay, struct spa_po
|
||||||
|
|
||||||
if ((suppressed = spa_ratelimit_test(&this->rt.rate_limit, nsec)) >= 0) {
|
if ((suppressed = spa_ratelimit_test(&this->rt.rate_limit, nsec)) >= 0) {
|
||||||
struct spa_fraction rate;
|
struct spa_fraction rate;
|
||||||
if (da) {
|
if (a) {
|
||||||
struct spa_io_clock *cl = &da->position.clock;
|
struct spa_io_clock *cl = &a->position.clock;
|
||||||
rate.num = cl->rate.num * cl->duration;
|
rate.num = cl->rate.num * cl->duration;
|
||||||
rate.denom = cl->rate.denom;
|
rate.denom = cl->rate.denom;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -2303,8 +2299,8 @@ void pw_impl_node_destroy(struct pw_impl_node *node)
|
||||||
|
|
||||||
/* remove ourself as a follower from the driver node */
|
/* remove ourself as a follower from the driver node */
|
||||||
spa_list_remove(&node->follower_link);
|
spa_list_remove(&node->follower_link);
|
||||||
pw_impl_node_remove_target(node, &node->rt.driver_target);
|
pw_node_peer_unref(spa_steal_ptr(node->from_driver_peer));
|
||||||
pw_impl_node_remove_target(node->driver_node, &node->rt.target);
|
pw_node_peer_unref(spa_steal_ptr(node->to_driver_peer));
|
||||||
remove_segment_owner(node->driver_node, node->info.id);
|
remove_segment_owner(node->driver_node, node->info.id);
|
||||||
|
|
||||||
spa_list_consume(follower, &node->follower_list, follower_link) {
|
spa_list_consume(follower, &node->follower_list, follower_link) {
|
||||||
|
|
|
||||||
|
|
@ -532,8 +532,6 @@ static inline void pw_node_activation_state_reset(struct pw_node_activation_stat
|
||||||
|
|
||||||
struct pw_node_target {
|
struct pw_node_target {
|
||||||
struct spa_list link;
|
struct spa_list link;
|
||||||
#define PW_NODE_TARGET_NONE 0
|
|
||||||
#define PW_NODE_TARGET_PEER 1
|
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
char name[128];
|
char name[128];
|
||||||
|
|
@ -661,6 +659,16 @@ static inline void trigger_target(struct pw_node_target *t, uint64_t nsec)
|
||||||
wake_target(t, nsec);
|
wake_target(t, nsec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct pw_node_peer {
|
||||||
|
int ref;
|
||||||
|
struct spa_list link; /**< link in peer list */
|
||||||
|
struct pw_impl_node *output; /**< the output node */
|
||||||
|
struct pw_node_target target; /**< target of the input node */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct pw_node_peer *pw_node_peer_ref(struct pw_impl_node *onode, struct pw_impl_node *inode);
|
||||||
|
void pw_node_peer_unref(struct pw_node_peer *peer);
|
||||||
|
|
||||||
#define pw_impl_node_emit(o,m,v,...) spa_hook_list_call(&o->listener_list, struct pw_impl_node_events, m, v, ##__VA_ARGS__)
|
#define pw_impl_node_emit(o,m,v,...) spa_hook_list_call(&o->listener_list, struct pw_impl_node_events, m, v, ##__VA_ARGS__)
|
||||||
#define pw_impl_node_emit_destroy(n) pw_impl_node_emit(n, destroy, 0)
|
#define pw_impl_node_emit_destroy(n) pw_impl_node_emit(n, destroy, 0)
|
||||||
#define pw_impl_node_emit_free(n) pw_impl_node_emit(n, free, 0)
|
#define pw_impl_node_emit_free(n) pw_impl_node_emit(n, free, 0)
|
||||||
|
|
@ -779,7 +787,6 @@ struct pw_impl_node {
|
||||||
|
|
||||||
struct spa_list target_list; /* list of targets to signal after
|
struct spa_list target_list; /* list of targets to signal after
|
||||||
* this node */
|
* this node */
|
||||||
struct pw_node_target driver_target; /* driver target that we signal */
|
|
||||||
struct spa_list input_mix; /* our input ports (and mixers) */
|
struct spa_list input_mix; /* our input ports (and mixers) */
|
||||||
struct spa_list output_mix; /* output ports (and mixers) */
|
struct spa_list output_mix; /* output ports (and mixers) */
|
||||||
|
|
||||||
|
|
@ -791,6 +798,8 @@ struct pw_impl_node {
|
||||||
|
|
||||||
bool prepared; /**< the node was added to loop */
|
bool prepared; /**< the node was added to loop */
|
||||||
} rt;
|
} rt;
|
||||||
|
struct pw_node_peer *to_driver_peer; /* node -> driver */
|
||||||
|
struct pw_node_peer *from_driver_peer; /* driver -> node */
|
||||||
struct spa_fraction target_rate;
|
struct spa_fraction target_rate;
|
||||||
uint64_t target_quantum;
|
uint64_t target_quantum;
|
||||||
|
|
||||||
|
|
@ -936,13 +945,6 @@ struct pw_control_link {
|
||||||
unsigned int valid:1;
|
unsigned int valid:1;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct pw_node_peer {
|
|
||||||
int ref;
|
|
||||||
struct spa_list link; /**< link in peer list */
|
|
||||||
struct pw_impl_node *output; /**< the output node */
|
|
||||||
struct pw_node_target target; /**< target of the input node */
|
|
||||||
};
|
|
||||||
|
|
||||||
#define pw_impl_link_emit(o,m,v,...) spa_hook_list_call(&o->listener_list, struct pw_impl_link_events, m, v, ##__VA_ARGS__)
|
#define pw_impl_link_emit(o,m,v,...) spa_hook_list_call(&o->listener_list, struct pw_impl_link_events, m, v, ##__VA_ARGS__)
|
||||||
#define pw_impl_link_emit_destroy(l) pw_impl_link_emit(l, destroy, 0)
|
#define pw_impl_link_emit_destroy(l) pw_impl_link_emit(l, destroy, 0)
|
||||||
#define pw_impl_link_emit_free(l) pw_impl_link_emit(l, free, 0)
|
#define pw_impl_link_emit_free(l) pw_impl_link_emit(l, free, 0)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue