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:
Wim Taymans 2016-11-07 10:24:13 +01:00
parent 7e46f9e3ad
commit b774b99db5
22 changed files with 797 additions and 364 deletions

View file

@ -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

View file

@ -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;

View file

@ -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;