Skip to content
This repository has been archived by the owner on Nov 8, 2019. It is now read-only.

Commit

Permalink
alsa: clamp the period size to something sensible
Browse files Browse the repository at this point in the history
some clients (sweep) want to negotiate the smallest possible period
size we can support, which is expressed in bytes and independent
of samplerate, format and number of channels.

For files with high samplerate and channelcount, this results in periods
of 8 frames, which is too small to handle.

Instead round up the period size to something we can likely handle,
taking into account the samplerate and number of channels.
  • Loading branch information
wtay committed Oct 16, 2018
1 parent 7af81f8 commit 7e513ea
Showing 1 changed file with 29 additions and 15 deletions.
44 changes: 29 additions & 15 deletions alsa-plugins/pcm_pipewire.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@
#define MAX_CHANNELS 32
#define MAX_RATE (48000*8)

#define MIN_PERIOD 64

typedef struct {
snd_pcm_ioplug_t io;

Expand Down Expand Up @@ -189,9 +191,9 @@ snd_pcm_pipewire_process_playback(snd_pcm_pipewire_t *pw, struct pw_buffer *b)
nbytes = SPA_MIN(avail, maxsize - offset);

ptr = SPA_MEMBER(d[0].data, offset, void);
pw_log_trace("%d %d %d %d %p %d", nbytes, avail, filled, offset, ptr, io->state);

nframes = nbytes / bpf;
pw_log_trace("%d %d %lu %d %d %p %d", nbytes, avail, nframes, filled, offset, ptr, io->state);

for (channel = 0; channel < io->channels; channel++) {
pwareas[channel].addr = ptr;
Expand Down Expand Up @@ -317,10 +319,15 @@ static void on_stream_format_changed(void *data, const struct spa_pod *format)
uint8_t buffer[4096];
struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
uint32_t stride = (io->channels * pw->sample_bits) / 8;
uint32_t buffers = SPA_CLAMP(io->buffer_size / io->period_size, MIN_BUFFERS, MAX_BUFFERS);
uint32_t size = io->period_size * stride;
uint32_t buffers;
uint32_t size;

io->period_size = pw->min_avail;
buffers = SPA_CLAMP(io->buffer_size / io->period_size, MIN_BUFFERS, MAX_BUFFERS);
size = io->period_size * stride;

pw_log_info("buffers %lu %lu %u %u %u", io->buffer_size, io->period_size, buffers, stride, size);
pw_log_info("buffer_size:%lu period_size:%lu buffers:%u stride:%u size:%u min_avail:%lu",
io->buffer_size, io->period_size, buffers, stride, size, pw->min_avail);

params[n_params++] = spa_pod_builder_object(&b,
SPA_TYPE_OBJECT_ParamBuffers, SPA_PARAM_Buffers,
Expand Down Expand Up @@ -367,10 +374,20 @@ static int snd_pcm_pipewire_prepare(snd_pcm_ioplug_t *io)
struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
struct pw_properties *props;
int res;
uint32_t min_period;

pw_thread_loop_lock(pw->main_loop);

pw_log_debug("prepare %d %p %lu", pw->error, pw->stream, io->period_size);
snd_pcm_sw_params_alloca(&swparams);
if ((res = snd_pcm_sw_params_current(io->pcm, swparams)) == 0)
snd_pcm_sw_params_get_avail_min(swparams, &pw->min_avail);
else
pw->min_avail = io->period_size;

min_period = (MIN_PERIOD * io->rate / 48000);
pw->min_avail = SPA_MAX(pw->min_avail, min_period);

pw_log_debug("prepare %d %p %lu %ld", pw->error, pw->stream, io->period_size, pw->min_avail);
if (!pw->error && pw->stream != NULL)
goto done;

Expand All @@ -380,7 +397,8 @@ static int snd_pcm_pipewire_prepare(snd_pcm_ioplug_t *io)
}

props = pw_properties_new("client.api", "alsa", NULL);
pw_properties_setf(props, "node.latency", "%lu/%u", io->period_size, io->rate);

pw_properties_setf(props, "node.latency", "%lu/%u", pw->min_avail, io->rate);
pw_properties_set(props, PW_NODE_PROP_MEDIA, "Audio");
pw_properties_set(props, PW_NODE_PROP_CATEGORY,
io->stream == SND_PCM_STREAM_PLAYBACK ?
Expand Down Expand Up @@ -410,12 +428,6 @@ static int snd_pcm_pipewire_prepare(snd_pcm_ioplug_t *io)
done:
pw->hw_ptr = 0;

snd_pcm_sw_params_alloca(&swparams);
if ((res = snd_pcm_sw_params_current(io->pcm, swparams)) == 0)
snd_pcm_sw_params_get_avail_min(swparams, &pw->min_avail);
else
pw->min_avail = io->period_size;

pw_thread_loop_unlock(pw->main_loop);

return 0;
Expand Down Expand Up @@ -505,7 +517,7 @@ static int snd_pcm_pipewire_hw_params(snd_pcm_ioplug_t * io,
snd_pcm_pipewire_t *pw = io->private_data;
bool planar;

pw_log_debug("hw_params");
pw_log_debug("hw_params %lu %lu", io->buffer_size, io->period_size);

switch(io->access) {
case SND_PCM_ACCESS_MMAP_INTERLEAVED:
Expand Down Expand Up @@ -722,10 +734,12 @@ static int pipewire_set_hw_constraint(snd_pcm_pipewire_t *pw)
1, MAX_CHANNELS)) < 0 ||
(err = snd_pcm_ioplug_set_param_minmax(&pw->io, SND_PCM_IOPLUG_HW_RATE,
1, MAX_RATE)) < 0 ||
(err = snd_pcm_ioplug_set_param_minmax(&pw->io, SND_PCM_IOPLUG_HW_BUFFER_BYTES,
16*1024, 4*1024*1024)) < 0 ||
(err = snd_pcm_ioplug_set_param_minmax(&pw->io, SND_PCM_IOPLUG_HW_PERIOD_BYTES,
128, 64*1024)) < 0 ||
128, 2*1024*1024)) < 0 ||
(err = snd_pcm_ioplug_set_param_minmax(&pw->io, SND_PCM_IOPLUG_HW_PERIODS,
2, 64)) < 0)
3, 64)) < 0)
return err;

return 0;
Expand Down

0 comments on commit 7e513ea

Please sign in to comment.