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