mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-02 09:01:50 -05:00
Rework transport protocol
Use a more simple tranport protocol for the realtime data. Use a piece of shared memory and a socket where we use a 1byte read/write to trigger remote actions. Also use a ringbuffer for events.
This commit is contained in:
parent
7e46f9e3ad
commit
b774b99db5
22 changed files with 797 additions and 364 deletions
|
|
@ -29,6 +29,8 @@ typedef struct _SpaRingbuffer SpaRingbuffer;
|
|||
#define SPA_RINGBUFFER_URI "http://spaplug.in/ns/ringbuffer"
|
||||
#define SPA_RINGBUFFER_PREFIX SPA_RINGBUFFER_URI "#"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <spa/defs.h>
|
||||
#include <spa/barrier.h>
|
||||
|
||||
|
|
@ -115,7 +117,7 @@ spa_ringbuffer_get_read_offset (SpaRingbuffer *rbuf,
|
|||
* Fill @areas with pointers to read from. The total amount of
|
||||
* bytes that can be read can be obtained by summing the areas len fields.
|
||||
*/
|
||||
static inline void
|
||||
static inline size_t
|
||||
spa_ringbuffer_get_read_areas (SpaRingbuffer *rbuf,
|
||||
SpaRingbufferArea areas[2])
|
||||
{
|
||||
|
|
@ -134,6 +136,22 @@ spa_ringbuffer_get_read_areas (SpaRingbuffer *rbuf,
|
|||
areas[0].len = avail;
|
||||
areas[1].len = 0;
|
||||
}
|
||||
return avail;
|
||||
}
|
||||
|
||||
static inline void
|
||||
spa_ringbuffer_read_data (SpaRingbuffer *rbuf,
|
||||
void *buffer,
|
||||
SpaRingbufferArea areas[2],
|
||||
void *data,
|
||||
size_t size)
|
||||
{
|
||||
if (SPA_LIKELY (size < areas[0].len))
|
||||
memcpy (data, buffer + areas[0].offset, size);
|
||||
else {
|
||||
memcpy (data, buffer + areas[0].offset, areas[0].len);
|
||||
memcpy (data + areas[0].len, buffer, size - areas[0].len);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -173,7 +191,7 @@ spa_ringbuffer_get_write_offset (SpaRingbuffer *rbuf,
|
|||
* Fill @areas with pointers to write to. The total amount of
|
||||
* bytes that can be written can be obtained by summing the areas len fields.
|
||||
*/
|
||||
static inline void
|
||||
static inline size_t
|
||||
spa_ringbuffer_get_write_areas (SpaRingbuffer *rbuf,
|
||||
SpaRingbufferArea areas[2])
|
||||
{
|
||||
|
|
@ -192,6 +210,22 @@ spa_ringbuffer_get_write_areas (SpaRingbuffer *rbuf,
|
|||
areas[0].len = avail;
|
||||
areas[1].len = 0;
|
||||
}
|
||||
return avail;
|
||||
}
|
||||
|
||||
static inline void
|
||||
spa_ringbuffer_write_data (SpaRingbuffer *rbuf,
|
||||
void *buffer,
|
||||
SpaRingbufferArea areas[2],
|
||||
void *data,
|
||||
size_t size)
|
||||
{
|
||||
if (SPA_LIKELY (size < areas[0].len))
|
||||
memcpy (buffer + areas[0].offset, data, size);
|
||||
else {
|
||||
memcpy (buffer + areas[0].offset, data, areas[0].len);
|
||||
memcpy (buffer, data + areas[0].len, size - areas[0].len);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -210,6 +244,7 @@ spa_ringbuffer_write_advance (SpaRingbuffer *rbuf,
|
|||
rbuf->writeindex = (rbuf->writeindex + len) & rbuf->mask2;
|
||||
}
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -698,7 +698,7 @@ spa_alsa_source_node_port_pull_output (SpaNode *node,
|
|||
|
||||
info[i].buffer_id = b->outbuf->id;
|
||||
info[i].status = SPA_RESULT_OK;
|
||||
spa_log_debug (this->log, "pull buffer %u", b->outbuf->id);
|
||||
spa_log_trace (this->log, "pull buffer %u", b->outbuf->id);
|
||||
}
|
||||
if (have_error)
|
||||
return SPA_RESULT_ERROR;
|
||||
|
|
@ -728,7 +728,7 @@ spa_alsa_source_node_port_reuse_buffer (SpaNode *node,
|
|||
if (buffer_id >= this->n_buffers)
|
||||
return SPA_RESULT_INVALID_BUFFER_ID;
|
||||
|
||||
spa_log_debug (this->log, "recycle buffer %u", buffer_id);
|
||||
spa_log_trace (this->log, "recycle buffer %u", buffer_id);
|
||||
recycle_buffer (this, buffer_id);
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
|
|
|
|||
|
|
@ -221,14 +221,20 @@ set_swparams (SpaALSAState *state)
|
|||
|
||||
CHECK (snd_pcm_sw_params_set_silence_threshold (hndl, params, 0U), "set_silence_threshold");
|
||||
|
||||
#if 1
|
||||
/* allow the transfer when at least period_size samples can be processed */
|
||||
/* or disable this mechanism when period event is enabled (aka interrupt like style processing) */
|
||||
CHECK (snd_pcm_sw_params_set_avail_min (hndl, params,
|
||||
props->period_event ? state->buffer_frames : state->period_frames), "set_avail_min");
|
||||
|
||||
/* enable period events when requested */
|
||||
if (props->period_event) {
|
||||
CHECK (snd_pcm_sw_params_set_period_event (hndl, params, 1), "set_period_event");
|
||||
}
|
||||
#else
|
||||
CHECK (snd_pcm_sw_params_set_avail_min (hndl, params, 0), "set_avail_min");
|
||||
#endif
|
||||
|
||||
/* write the parameters to the playback device */
|
||||
CHECK (snd_pcm_sw_params (hndl, params), "sw_params");
|
||||
|
||||
|
|
@ -328,8 +334,7 @@ pull_frames_ringbuffer (SpaALSAState *state,
|
|||
src = SPA_MEMBER (b->outbuf->datas[0].data, b->outbuf->datas[0].offset, void);
|
||||
dst = SPA_MEMBER (my_areas[0].addr, offset * state->frame_size, uint8_t);
|
||||
|
||||
spa_ringbuffer_get_read_areas (&b->rb->ringbuffer, areas);
|
||||
avail = areas[0].len + areas[1].len;
|
||||
avail = spa_ringbuffer_get_read_areas (&b->rb->ringbuffer, areas);
|
||||
size = SPA_MIN (avail, frames * state->frame_size);
|
||||
|
||||
spa_log_debug (state->log, "%zd %zd %zd %zd %zd %zd",
|
||||
|
|
@ -337,13 +342,11 @@ pull_frames_ringbuffer (SpaALSAState *state,
|
|||
areas[1].offset, areas[1].len, offset, size);
|
||||
|
||||
if (size > 0) {
|
||||
areas[0].len = SPA_MIN (areas[0].len, size);
|
||||
areas[1].len = SPA_MIN (areas[1].len, size - areas[0].len);
|
||||
|
||||
memcpy (dst, src + areas[0].offset, areas[0].len);
|
||||
if (areas[1].len)
|
||||
memcpy (dst + areas[0].len, src + areas[1].offset, areas[1].len);
|
||||
|
||||
spa_ringbuffer_read_data (&b->rb->ringbuffer,
|
||||
src,
|
||||
areas,
|
||||
dst,
|
||||
size);
|
||||
spa_ringbuffer_read_advance (&b->rb->ringbuffer, size);
|
||||
frames = size / state->frame_size;
|
||||
} else {
|
||||
|
|
@ -371,6 +374,7 @@ mmap_write (SpaALSAState *state)
|
|||
snd_pcm_status_t *status;
|
||||
SpaNodeEventNeedInput ni;
|
||||
|
||||
#if 0
|
||||
snd_pcm_status_alloca (&status);
|
||||
|
||||
if ((err = snd_pcm_status (hndl, status)) < 0) {
|
||||
|
|
@ -379,6 +383,12 @@ mmap_write (SpaALSAState *state)
|
|||
}
|
||||
|
||||
avail = snd_pcm_status_get_avail (status);
|
||||
#else
|
||||
if ((avail = snd_pcm_avail_update (hndl)) < 0) {
|
||||
spa_log_error (state->log, "snd_pcm_avail_update error: %s", snd_strerror (avail));
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
ni.event.type = SPA_NODE_EVENT_TYPE_NEED_INPUT;
|
||||
ni.event.size = sizeof (ni);
|
||||
|
|
@ -403,7 +413,6 @@ mmap_write (SpaALSAState *state)
|
|||
if (err != -EPIPE && err != -ESTRPIPE)
|
||||
return -1;
|
||||
}
|
||||
spa_log_debug (state->log, "write %zd/%zd/%zd %u", frames, size, avail, state->ready.length);
|
||||
size -= frames;
|
||||
}
|
||||
return 0;
|
||||
|
|
@ -552,6 +561,7 @@ spa_alsa_start (SpaALSAState *state, bool xrun_recover)
|
|||
spa_log_error (state->log, "Invalid poll descriptors count %d", state->poll.n_fds);
|
||||
return SPA_RESULT_ERROR;
|
||||
}
|
||||
|
||||
if ((err = snd_pcm_poll_descriptors (state->hndl, (struct pollfd *)state->fds, state->poll.n_fds)) < 0) {
|
||||
spa_log_error (state->log, "snd_pcm_poll_descriptors: %s", snd_strerror(err));
|
||||
return SPA_RESULT_ERROR;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue