mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-03 09:01:54 -05:00
alsa: clamp the period size to something sensible
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.
This commit is contained in:
parent
7af81f8080
commit
7e513ea243
1 changed files with 29 additions and 15 deletions
|
|
@ -45,6 +45,8 @@
|
|||
#define MAX_CHANNELS 32
|
||||
#define MAX_RATE (48000*8)
|
||||
|
||||
#define MIN_PERIOD 64
|
||||
|
||||
typedef struct {
|
||||
snd_pcm_ioplug_t io;
|
||||
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
||||
pw_log_info("buffers %lu %lu %u %u %u", io->buffer_size, io->period_size, buffers, stride, 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("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,
|
||||
|
|
@ -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;
|
||||
|
||||
|
|
@ -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 ?
|
||||
|
|
@ -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;
|
||||
|
|
@ -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:
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue