mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-10-29 05:40:27 -04:00
node: add target_rate and target_duration in io_clock
Place the target rate and duration in the io clock area. The driver is meant to read these new values at the start of the cycle and update the position rate and duration. This used to be done by the pipewire server when it received the ready callback from the driver but this is in fact too late. Most driver would start processing and set the next timeout based on the old rate/duration instead of the new pending ones. There is still a fallback for the old behaviour (with a warning) when the driver doesn't yet update the position.
This commit is contained in:
parent
87d64f5cad
commit
2adf8d38d5
4 changed files with 35 additions and 23 deletions
|
|
@ -124,7 +124,13 @@ struct spa_io_clock {
|
|||
* positive for capture, negative for playback */
|
||||
double rate_diff; /**< rate difference between clock and monotonic time */
|
||||
uint64_t next_nsec; /**< estimated next wakeup time in nanoseconds */
|
||||
uint32_t padding[8];
|
||||
|
||||
struct spa_fraction target_rate; /**< target rate of next cycle */
|
||||
uint64_t target_duration; /**< target duration of next cycle */
|
||||
uint32_t target_seq; /**< seq counter. must be equal at start and
|
||||
* end of read and lower bit must be 0 */
|
||||
|
||||
uint32_t padding[3];
|
||||
};
|
||||
|
||||
/* the size of the video in this cycle */
|
||||
|
|
|
|||
|
|
@ -2466,6 +2466,8 @@ static void alsa_on_timeout_event(struct spa_source *source)
|
|||
return;
|
||||
}
|
||||
}
|
||||
state->position->clock.duration = state->position->clock.target_duration;
|
||||
state->position->clock.rate = state->position->clock.target_rate;
|
||||
|
||||
check_position_config(state);
|
||||
|
||||
|
|
@ -2550,6 +2552,8 @@ int spa_alsa_start(struct state *state)
|
|||
return 0;
|
||||
|
||||
if (state->position) {
|
||||
state->position->clock.duration = state->position->clock.target_duration;
|
||||
state->position->clock.rate = state->position->clock.target_rate;
|
||||
state->duration = state->position->clock.duration;
|
||||
state->rate_denom = state->position->clock.rate.denom;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1375,16 +1375,17 @@ again:
|
|||
n->target_pending = true;
|
||||
}
|
||||
|
||||
if (n->info.state < PW_NODE_STATE_RUNNING && n->target_pending) {
|
||||
/* the driver node is not actually running and we have a
|
||||
* pending change. Apply the change to the position now so
|
||||
* that we have the right values when we change the node
|
||||
* states of the driver and followers to RUNNING below */
|
||||
if (n->target_pending) {
|
||||
/* we have a pending change. We place the new values in the
|
||||
* pending fields so that they are picked up by the driver in
|
||||
* the next cycle */
|
||||
pw_log_debug("%p: apply duration:%"PRIu64" rate:%u/%u", context,
|
||||
n->target_quantum, n->target_rate.num,
|
||||
n->target_rate.denom);
|
||||
n->rt.position->clock.duration = n->target_quantum;
|
||||
n->rt.position->clock.rate = n->target_rate;
|
||||
SEQ_WRITE(n->rt.position->clock.target_seq);
|
||||
n->rt.position->clock.target_duration = n->target_quantum;
|
||||
n->rt.position->clock.target_rate = n->target_rate;
|
||||
SEQ_WRITE(n->rt.position->clock.target_seq);
|
||||
n->target_pending = false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -688,8 +688,9 @@ static void update_io(struct pw_impl_node *node)
|
|||
pw_log_debug("%p: set position %p", node, &node->rt.activation->position);
|
||||
node->rt.position = &node->rt.activation->position;
|
||||
|
||||
node->target_rate = node->rt.position->clock.rate;
|
||||
node->target_quantum = node->rt.position->clock.duration;
|
||||
node->target_rate = node->rt.position->clock.target_rate;
|
||||
node->target_quantum = node->rt.position->clock.target_duration;
|
||||
node->target_pending = false;
|
||||
} else if (node->driver) {
|
||||
pw_log_warn("%p: can't set position on driver", node);
|
||||
}
|
||||
|
|
@ -804,8 +805,8 @@ do_move_nodes(struct spa_loop *loop,
|
|||
pw_log_trace("%p: set position %p", node, &driver->rt.activation->position);
|
||||
node->rt.position = &driver->rt.activation->position;
|
||||
|
||||
node->target_rate = node->rt.position->clock.rate;
|
||||
node->target_quantum = node->rt.position->clock.duration;
|
||||
node->target_rate = node->rt.position->clock.target_rate;
|
||||
node->target_quantum = node->rt.position->clock.target_duration;
|
||||
|
||||
if (node->source.loop != NULL) {
|
||||
remove_node(node);
|
||||
|
|
@ -1223,8 +1224,8 @@ static void reset_position(struct pw_impl_node *this, struct spa_io_position *po
|
|||
this->target_rate = SPA_FRACTION(1, rate);
|
||||
this->target_quantum = quantum;
|
||||
|
||||
pos->clock.rate = this->target_rate;
|
||||
pos->clock.duration = this->target_quantum;
|
||||
pos->clock.rate = pos->clock.target_rate = this->target_rate;
|
||||
pos->clock.duration = pos->clock.target_duration = this->target_quantum;
|
||||
pos->video.flags = SPA_IO_VIDEO_SIZE_VALID;
|
||||
pos->video.size = s->video_size;
|
||||
pos->video.stride = pos->video.size.width * 16;
|
||||
|
|
@ -1683,15 +1684,15 @@ static int node_ready(void *data, int status)
|
|||
node->rt.target.signal_func(node->rt.target.data);
|
||||
}
|
||||
|
||||
if (node->target_pending) {
|
||||
pw_log_debug("apply quantum %"PRIu64"->%"PRIu64" %d->%d",
|
||||
node->rt.position->clock.duration,
|
||||
node->target_quantum,
|
||||
node->rt.position->clock.rate.denom,
|
||||
node->target_rate.denom);
|
||||
node->rt.position->clock.duration = node->target_quantum;
|
||||
node->rt.position->clock.rate = node->target_rate;
|
||||
node->target_pending = false;
|
||||
/* This update is done too late, the driver should do this
|
||||
* before calling the ready callback so that it can use the new target
|
||||
* duration and rate to schedule the next update. We do this here to
|
||||
* help drivers that don't support this yet */
|
||||
if (node->rt.position->clock.duration != node->rt.position->clock.target_duration ||
|
||||
node->rt.position->clock.rate.denom != node->rt.position->clock.target_rate.denom) {
|
||||
pw_log_warn("driver %s did not update duration/rate", node->name);
|
||||
node->rt.position->clock.duration = node->rt.position->clock.target_duration;
|
||||
node->rt.position->clock.rate = node->rt.position->clock.target_rate;
|
||||
}
|
||||
|
||||
sync_type = check_updates(node, &reposition_owner);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue