diff options
author | Wim Taymans <wtaymans@redhat.com> | 2019-08-27 21:36:15 +0200 |
---|---|---|
committer | Wim Taymans <wtaymans@redhat.com> | 2019-08-27 21:36:15 +0200 |
commit | 7c865f5db0469842b853bd1438fb0fc97caee10c (patch) | |
tree | ed06af77c4a045bfeb1162d39b124df01fbe085b /src | |
parent | b356c83d32516dd929adeb29eac975c84e4d1dfc (diff) |
io: add support for segment
Move fields from the io_position to io_segment. The segment contains
the mapping between raw clock time and stream time in various
formats. We keep an array of pending segments available in the
io_position field so clients can anticipate changes.
Make looping a flag in the segment instead of a state.
Prepare for segment masters. These will be registered clients that
are responsible for updating parts of the extended segment info.
Add namespace to some defines.
Diffstat (limited to 'src')
-rw-r--r-- | src/modules/module-client-node/client-node.c | 2 | ||||
-rw-r--r-- | src/modules/module-client-node/remote-node.c | 4 | ||||
-rw-r--r-- | src/pipewire/node.c | 59 | ||||
-rw-r--r-- | src/pipewire/private.h | 27 |
4 files changed, 59 insertions, 33 deletions
diff --git a/src/modules/module-client-node/client-node.c b/src/modules/module-client-node/client-node.c index fabe1495..61960a3a 100644 --- a/src/modules/module-client-node/client-node.c +++ b/src/modules/module-client-node/client-node.c @@ -880,7 +880,7 @@ static int impl_node_process(void *object) spa_log_trace_fp(this->log, "%p: send process driver:%p", this, impl->this.node->driver_node); spa_system_clock_gettime(this->data_system, CLOCK_MONOTONIC, &ts); - n->rt.activation->status = TRIGGERED; + n->rt.activation->status = PW_NODE_ACTIVATION_TRIGGERED; n->rt.activation->signal_time = SPA_TIMESPEC_TO_NSEC(&ts); if (spa_system_eventfd_write(this->data_system, this->writefd, 1) < 0) diff --git a/src/modules/module-client-node/remote-node.c b/src/modules/module-client-node/remote-node.c index 45e38835..cbaa6c7e 100644 --- a/src/modules/module-client-node/remote-node.c +++ b/src/modules/module-client-node/remote-node.c @@ -774,7 +774,7 @@ static int link_signal_func(void *user_data) pw_log_trace("link %p: signal", link); clock_gettime(CLOCK_MONOTONIC, &ts); - link->target.activation->status = TRIGGERED; + link->target.activation->status = PW_NODE_ACTIVATION_TRIGGERED; link->target.activation->signal_time = SPA_TIMESPEC_TO_NSEC(&ts); if (write(link->signalfd, &cmd, sizeof(cmd)) != sizeof(cmd)) @@ -1050,7 +1050,7 @@ static int node_ready(void *d, int status) } clock_gettime(CLOCK_MONOTONIC, &ts); - a->status = TRIGGERED; + a->status = PW_NODE_ACTIVATION_TRIGGERED; a->signal_time = SPA_TIMESPEC_TO_NSEC(&ts); if (write(data->rtwritefd, &cmd, sizeof(cmd)) != sizeof(cmd)) diff --git a/src/pipewire/node.c b/src/pipewire/node.c index 5cab8568..c1721259 100644 --- a/src/pipewire/node.c +++ b/src/pipewire/node.c @@ -768,7 +768,7 @@ static inline int resume_node(struct pw_node *this, int status) spa_system_clock_gettime(data_system, CLOCK_MONOTONIC, &ts); nsec = SPA_TIMESPEC_TO_NSEC(&ts); - activation->status = FINISHED; + activation->status = PW_NODE_ACTIVATION_FINISHED; activation->finish_time = nsec; pw_log_trace_fp(NAME" %p: trigger peers %"PRIu64, this, nsec); @@ -782,7 +782,7 @@ static inline int resume_node(struct pw_node *this, int status) state->pending, state->required); if (pw_node_activation_state_dec(state, 1)) { - t->activation->status = TRIGGERED; + t->activation->status = PW_NODE_ACTIVATION_TRIGGERED; t->activation->signal_time = nsec; t->signal(t->data); } @@ -812,7 +812,7 @@ static inline int process_node(void *data) int status; spa_system_clock_gettime(data_system, CLOCK_MONOTONIC, &ts); - a->status = AWAKE; + a->status = PW_NODE_ACTIVATION_AWAKE; a->awake_time = SPA_TIMESPEC_TO_NSEC(&ts); pw_log_trace_fp(NAME" %p: process %"PRIu64, this, a->awake_time); @@ -830,7 +830,7 @@ static inline int process_node(void *data) if (this == this->driver_node && !this->exported) { spa_system_clock_gettime(data_system, CLOCK_MONOTONIC, &ts); - a->status = FINISHED; + a->status = PW_NODE_ACTIVATION_FINISHED; a->signal_time = a->finish_time; a->finish_time = SPA_TIMESPEC_TO_NSEC(&ts); @@ -963,7 +963,6 @@ struct pw_node *pw_node_new(struct pw_core *core, this->rt.activation->position.clock.rate = SPA_FRACTION(1, 48000); this->rt.activation->position.clock.duration = DEFAULT_QUANTUM; - this->rt.activation->position.rate = 1.0; check_properties(this); @@ -1164,47 +1163,63 @@ static const struct spa_node_events node_events = { static void update_position(struct pw_node *node) { struct pw_node_activation *a = node->rt.activation; - struct spa_io_position position; + struct spa_io_segment segment, *seg; uint32_t seq1, seq2, change_mask; enum spa_io_position_state state; seq1 = SEQ_READ(&a->pending.seq); change_mask = a->pending.change_mask; state = a->pending.state; - position = a->pending.position; + segment = a->pending.segment; seq2 = SEQ_READ(&a->pending.seq); + /* if we can't read a stable update, just ignore it and process it + * in the next cycle. */ if (SEQ_READ_SUCCESS(seq1, seq2)) a->pending.change_mask = 0; else change_mask = 0; - if (change_mask & UPDATE_POSITION) { - pw_log_debug("update position:%lu", position.position); - a->position.position = position.position; - a->position.clock_start = position.clock_start; - a->position.clock_duration = position.clock_duration; - a->position.rate = position.rate; + seg = &a->position.segments[0]; + + if (change_mask & PW_NODE_ACTIVATION_UPDATE_SEGMENT) { + pw_log_debug("update segment"); + if (segment.valid & SPA_IO_SEGMENT_VALID_BAR) { + seg->bar = segment.bar; + seg->valid |= SPA_IO_SEGMENT_VALID_BAR; + } + if (segment.valid & SPA_IO_SEGMENT_VALID_VIDEO) { + seg->video = segment.video; + seg->valid |= SPA_IO_SEGMENT_VALID_BAR; + } } - if (change_mask & UPDATE_STATE) { + if (change_mask & PW_NODE_ACTIVATION_UPDATE_REPOSITION) { + pw_log_debug("update position:%lu", segment.position); + seg->flags = segment.flags; + seg->clock_start = segment.clock_start; + seg->clock_duration = segment.clock_duration; + seg->position = segment.position; + seg->rate = segment.rate; + } + if (change_mask & PW_NODE_ACTIVATION_UPDATE_STATE) { switch (state) { case SPA_IO_POSITION_STATE_STOPPED: + case SPA_IO_POSITION_STATE_RUNNING: a->position.state = state; break; case SPA_IO_POSITION_STATE_STARTING: a->position.state = SPA_IO_POSITION_STATE_RUNNING; break; - case SPA_IO_POSITION_STATE_RUNNING: - case SPA_IO_POSITION_STATE_LOOPING: - a->position.state = state; - break; } } - if (a->position.clock_start == 0) - a->position.clock_start = a->position.clock.position; + if (seg->rate == 0.0) + seg->rate = 1.0; + + if (seg->clock_start == 0) + seg->clock_start = a->position.clock.position; if (a->position.state == SPA_IO_POSITION_STATE_STOPPED) - a->position.clock_start += a->position.clock.duration; + seg->clock_start += a->position.clock.duration; } static int node_ready(void *data, int status) @@ -1227,7 +1242,7 @@ static int node_ready(void *data, int status) } spa_list_for_each(t, &driver->rt.target_list, link) { pw_node_activation_state_reset(&t->activation->state[0]); - t->activation->status = NOT_TRIGGERED; + t->activation->status = PW_NODE_ACTIVATION_NOT_TRIGGERED; } a->prev_signal_time = a->signal_time; diff --git a/src/pipewire/private.h b/src/pipewire/private.h index 2a59fa62..42dbd88e 100644 --- a/src/pipewire/private.h +++ b/src/pipewire/private.h @@ -349,10 +349,10 @@ struct pw_node_target { }; struct pw_node_activation { -#define NOT_TRIGGERED 0 -#define TRIGGERED 1 -#define AWAKE 2 -#define FINISHED 3 +#define PW_NODE_ACTIVATION_NOT_TRIGGERED 0 +#define PW_NODE_ACTIVATION_TRIGGERED 1 +#define PW_NODE_ACTIVATION_AWAKE 2 +#define PW_NODE_ACTIVATION_FINISHED 3 int status; uint64_t signal_time; @@ -361,21 +361,32 @@ struct pw_node_activation { uint64_t prev_signal_time; struct spa_io_position position; + uint32_t segment_master[32]; /* unique id (client id usually) of client + * that will update extra segment info, There + * can be one master for each segment + * bitfield */ + + uint32_t version; struct pw_node_activation_state state[2]; /* one current state and one next state, - * as low bit of version in position */ + * as low bit of version */ float cpu_load[3]; /* averaged over short, medium, long time */ uint32_t xrun_count; /* number of xruns */ uint64_t xrun_time; /* time of last xrun in microseconds */ uint64_t xrun_delay; /* delay of last xrun in microseconds */ uint64_t max_delay; /* max of all xruns in microseconds */ + struct { uint32_t seq; -#define UPDATE_STATE (1<<0) -#define UPDATE_POSITION (1<<1) +#define PW_NODE_ACTIVATION_UPDATE_STATE (1<<0) +#define PW_NODE_ACTIVATION_UPDATE_SEGMENT (1<<1) +#define PW_NODE_ACTIVATION_UPDATE_REPOSITION (1<<2) uint32_t change_mask; enum spa_io_position_state state; - struct spa_io_position position; + struct spa_io_segment segment; /* update for the extra segment info + * fields. When REPOSITION update, the segment + * position field will contain the desired + * new position. */ } pending; }; |