mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-12-16 08:56:45 -05:00
avb: handle sink follower
We need to flush out the packets when we are a follower and when we get data because our timer is not running as a sink.
This commit is contained in:
parent
4d6c71bf12
commit
87053365ea
1 changed files with 54 additions and 46 deletions
|
|
@ -856,6 +856,55 @@ static void set_timeout(struct state *state, uint64_t next_time)
|
||||||
state->timer_source.fd, SPA_FD_TIMER_ABSTIME, &ts, NULL);
|
state->timer_source.fd, SPA_FD_TIMER_ABSTIME, &ts, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int flush_write(struct state *state, uint64_t current_time)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
int32_t avail, wanted;
|
||||||
|
uint32_t index;
|
||||||
|
uint64_t ptime, txtime;
|
||||||
|
int pdu_count;
|
||||||
|
struct props *p = &state->props;
|
||||||
|
struct avtp_stream_pdu *pdu = state->pdu;
|
||||||
|
ssize_t n;
|
||||||
|
|
||||||
|
avail = spa_ringbuffer_get_read_index(&state->ring, &index);
|
||||||
|
wanted = state->duration * state->stride;
|
||||||
|
if (avail < wanted) {
|
||||||
|
spa_log_warn(state->log, "underrun %d < %d", avail, wanted);
|
||||||
|
return -EPIPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
pdu_count = state->duration / p->frames_per_pdu;
|
||||||
|
|
||||||
|
txtime = current_time + p->t_uncertainty;
|
||||||
|
ptime = txtime + p->mtt;
|
||||||
|
|
||||||
|
while (pdu_count--) {
|
||||||
|
*(__u64 *)CMSG_DATA(state->cmsg) = txtime;
|
||||||
|
|
||||||
|
set_iovec(&state->ring,
|
||||||
|
state->ringbuffer_data,
|
||||||
|
state->ringbuffer_size,
|
||||||
|
index % state->ringbuffer_size,
|
||||||
|
&state->iov[1], state->payload_size);
|
||||||
|
|
||||||
|
#define PDU_SET(f,v) if ((res = avtp_aaf_pdu_set(pdu, (f), (v))) < 0) return res;
|
||||||
|
PDU_SET(AVTP_AAF_FIELD_SEQ_NUM, state->pdu_seq++);
|
||||||
|
PDU_SET(AVTP_AAF_FIELD_TIMESTAMP, ptime);
|
||||||
|
#undef PDU_SET
|
||||||
|
n = sendmsg(state->sockfd, &state->msg, 0);
|
||||||
|
if (n < 0 || n != (ssize_t)state->pdu_size) {
|
||||||
|
spa_log_error(state->log, "sendmdg() failed: %m");
|
||||||
|
return -errno;
|
||||||
|
}
|
||||||
|
txtime += state->pdu_period;
|
||||||
|
ptime += state->pdu_period;
|
||||||
|
index += state->payload_size;
|
||||||
|
}
|
||||||
|
spa_ringbuffer_read_update(&state->ring, index);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int spa_avb_write(struct state *state)
|
int spa_avb_write(struct state *state)
|
||||||
{
|
{
|
||||||
int32_t filled;
|
int32_t filled;
|
||||||
|
|
@ -910,58 +959,17 @@ int spa_avb_write(struct state *state)
|
||||||
index += n_bytes;
|
index += n_bytes;
|
||||||
}
|
}
|
||||||
spa_ringbuffer_write_update(&state->ring, index);
|
spa_ringbuffer_write_update(&state->ring, index);
|
||||||
|
|
||||||
|
if (state->following) {
|
||||||
|
flush_write(state, state->position->clock.nsec);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int handle_play(struct state *state, uint64_t current_time)
|
static int handle_play(struct state *state, uint64_t current_time)
|
||||||
{
|
{
|
||||||
int res;
|
flush_write(state, current_time);
|
||||||
int32_t avail, wanted;
|
|
||||||
uint32_t index;
|
|
||||||
uint64_t ptime, txtime;
|
|
||||||
int pdu_count;
|
|
||||||
struct props *p = &state->props;
|
|
||||||
struct avtp_stream_pdu *pdu = state->pdu;
|
|
||||||
ssize_t n;
|
|
||||||
|
|
||||||
avail = spa_ringbuffer_get_read_index(&state->ring, &index);
|
|
||||||
wanted = state->duration * state->stride;
|
|
||||||
if (avail < wanted) {
|
|
||||||
spa_log_warn(state->log, "underrun %d < %d", avail, wanted);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
pdu_count = state->duration / p->frames_per_pdu;
|
|
||||||
|
|
||||||
txtime = current_time + p->t_uncertainty;
|
|
||||||
ptime = txtime + p->mtt;
|
|
||||||
|
|
||||||
while (pdu_count--) {
|
|
||||||
*(__u64 *)CMSG_DATA(state->cmsg) = txtime;
|
|
||||||
|
|
||||||
set_iovec(&state->ring,
|
|
||||||
state->ringbuffer_data,
|
|
||||||
state->ringbuffer_size,
|
|
||||||
index % state->ringbuffer_size,
|
|
||||||
&state->iov[1], state->payload_size);
|
|
||||||
|
|
||||||
#define PDU_SET(f,v) if ((res = avtp_aaf_pdu_set(pdu, (f), (v))) < 0) return res;
|
|
||||||
PDU_SET(AVTP_AAF_FIELD_SEQ_NUM, state->pdu_seq++);
|
|
||||||
PDU_SET(AVTP_AAF_FIELD_TIMESTAMP, ptime);
|
|
||||||
#undef PDU_SET
|
|
||||||
n = sendmsg(state->sockfd, &state->msg, 0);
|
|
||||||
if (n < 0 || n != (ssize_t)state->pdu_size) {
|
|
||||||
spa_log_error(state->log, "sendmdg() failed: %m");
|
|
||||||
return -errno;
|
|
||||||
}
|
|
||||||
txtime += state->pdu_period;
|
|
||||||
ptime += state->pdu_period;
|
|
||||||
index += state->payload_size;
|
|
||||||
}
|
|
||||||
spa_ringbuffer_read_update(&state->ring, index);
|
|
||||||
done:
|
|
||||||
spa_node_call_ready(&state->callbacks, SPA_STATUS_NEED_DATA);
|
spa_node_call_ready(&state->callbacks, SPA_STATUS_NEED_DATA);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue