From 0a15e1f80481259a76461132f135455e3c716cf0 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Wed, 28 Aug 2019 10:28:06 +0200 Subject: [PATCH] io: add offset for clock times Add an offset to apply to the clock time before we can compare to the segment values. This way we can keep the segment start independent of the clock values and we only need to adjust the offset when paused. It's like the base_time in GStreamer to calculate the running time. --- pipewire-jack | 2 +- spa/include/spa/node/io.h | 34 ++++++++++++++++++++-------------- src/pipewire/node.c | 10 +++++++--- src/pipewire/private.h | 4 +++- 4 files changed, 31 insertions(+), 19 deletions(-) diff --git a/pipewire-jack b/pipewire-jack index 796278b20..a52ad27a1 160000 --- a/pipewire-jack +++ b/pipewire-jack @@ -1 +1 @@ -Subproject commit 796278b207e686403638d1c850ce01fa0a0fee48 +Subproject commit a52ad27a169ffd6abb4090e1d77385bd879a1d43 diff --git a/spa/include/spa/node/io.h b/spa/include/spa/node/io.h index 3e7f1b77a..116c30ea6 100644 --- a/spa/include/spa/node/io.h +++ b/spa/include/spa/node/io.h @@ -136,20 +136,20 @@ struct spa_io_segment_video { }; /** - * A segment converts a raw clock time to a segment (stream) position. + * A segment converts a running time to a segment (stream) position. * - * The segment position is valid when the current clock position is between + * The segment position is valid when the current running time is between * start and start + duration. The position is then * calculated as: * - * (start - clock.position) * rate + position; + * (running time - start) * rate + position; * - * Support for looping is done by specifying a non-zero duration. When the - * clock reaches start + duration, duration is added to start and the - * loop repeats. + * Support for looping is done by specifying the LOOPING flags with a + * non-zero duration. When the running time reaches start + duration, + * duration is added to start and the loop repeats. * - * Care has to be taken when the clock.duration extends past the - * start + duration from the segment; the user should correctly + * Care has to be taken when the running time + clock.duration extends + * past the start + duration from the segment; the user should correctly * wrap around and partially repeat the loop in the current cycle. * * Extra information can be placed in the segment by setting the valid flags @@ -162,15 +162,16 @@ struct spa_io_segment { #define SPA_IO_SEGMENT_VALID_BAR (1<<1) #define SPA_IO_SEGMENT_VALID_VIDEO (1<<2) uint32_t valid; /**< indicates what fields are valid below */ - uint64_t start; /**< position against clock position when this + uint64_t start; /**< value of running time when this * info is active. Can be in the future for * pending changes. It does not have to be in * exact multiples of the clock duration. */ - uint64_t duration; /**< duration when this info becomes invalid. If - * the duration is 0, this segment extends to the - * next segment. If the segment becomes invalid and - * the looping flag is set, the segment is repeats. */ - uint64_t position; /**< The position when the clock == start. */ + uint64_t duration; /**< duration when this info becomes invalid expressed + * in running time. If the duration is 0, this + * segment extends to the next segment. If the + * segment becomes invalid and the looping flag is + * set, the segment repeats. */ + uint64_t position; /**< The position when the running time == start. */ double rate; /**< overal rate of the graph, can be negative for * backwards time reporting. */ @@ -202,6 +203,11 @@ enum spa_io_position_state { struct spa_io_position { struct spa_io_clock clock; /**< clock position of driver, always valid and * read only */ + int64_t offset; /**< an offset to subtract from the clock position + * to get a running time. This is the time that + * the state has been in the RUNNING state and the + * time that should be used to compare the segment + * start values against. */ uint32_t state; /**< one of enum spa_io_position_state */ uint32_t n_segments; /**< number of segments */ diff --git a/src/pipewire/node.c b/src/pipewire/node.c index 9d96110df..46968feba 100644 --- a/src/pipewire/node.c +++ b/src/pipewire/node.c @@ -963,6 +963,7 @@ 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.offset = INT64_MIN; this->rt.activation->position.n_segments = 1; this->rt.activation->position.segments[0].flags = 0; this->rt.activation->position.segments[0].valid = SPA_IO_SEGMENT_VALID_POSITION; @@ -1174,6 +1175,9 @@ static void update_position(struct pw_node *node) uint32_t seq1, seq2, change_mask; enum spa_io_position_state state; + if (a->position.offset == INT64_MIN) + a->position.offset = a->position.clock.position; + seq1 = SEQ_READ(&a->pending.seq); change_mask = a->pending.change_mask; state = a->pending.state; @@ -1207,6 +1211,8 @@ static void update_position(struct pw_node *node) seg->duration = segment.duration; seg->position = segment.position; seg->rate = segment.rate; + if (seg->start == 0) + seg->start = a->position.clock.position - a->position.offset; } if (change_mask & PW_NODE_ACTIVATION_UPDATE_STATE) { switch (state) { @@ -1219,11 +1225,9 @@ static void update_position(struct pw_node *node) break; } } - if (seg->start == 0) - seg->start = a->position.clock.position; if (a->position.state == SPA_IO_POSITION_STATE_STOPPED) - seg->start += a->position.clock.duration; + a->position.offset += a->position.clock.duration; } static int node_ready(void *data, int status) diff --git a/src/pipewire/private.h b/src/pipewire/private.h index 42dbd88e6..0583437bd 100644 --- a/src/pipewire/private.h +++ b/src/pipewire/private.h @@ -381,8 +381,10 @@ struct pw_node_activation { #define PW_NODE_ACTIVATION_UPDATE_STATE (1<<0) #define PW_NODE_ACTIVATION_UPDATE_SEGMENT (1<<1) #define PW_NODE_ACTIVATION_UPDATE_REPOSITION (1<<2) +#define PW_NODE_ACTIVATION_UPDATE_FLUSH (1<<3) /* flush out current segments and immediately + * start the new one */ uint32_t change_mask; - enum spa_io_position_state state; + enum spa_io_position_state state; /* when change_mask & PW_NODE_ACTIVATION_UPDATE_STATE */ struct spa_io_segment segment; /* update for the extra segment info * fields. When REPOSITION update, the segment * position field will contain the desired