mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-10-29 05:40:23 -04:00
alsa: support fixed latency range in alsa modules
This adds a boolean module parameter to disable automatic dynamic latency readjustments on underruns, but leaves automatic dynamic watermark readjustments untouched.
This commit is contained in:
parent
6124bf8951
commit
7a387fed36
5 changed files with 47 additions and 10 deletions
|
|
@ -134,7 +134,7 @@ struct userdata {
|
|||
char *device_name; /* name of the PCM device */
|
||||
char *control_device; /* name of the control device */
|
||||
|
||||
pa_bool_t use_mmap:1, use_tsched:1, deferred_volume:1;
|
||||
pa_bool_t use_mmap:1, use_tsched:1, deferred_volume:1, fixed_latency_range:1;
|
||||
|
||||
pa_bool_t first, after_rewind;
|
||||
|
||||
|
|
@ -331,7 +331,12 @@ static void increase_watermark(struct userdata *u) {
|
|||
return;
|
||||
}
|
||||
|
||||
/* Hmm, we cannot increase the watermark any further, hence let's raise the latency */
|
||||
/* Hmm, we cannot increase the watermark any further, hence let's
|
||||
raise the latency, unless doing so was disabled in
|
||||
configuration */
|
||||
if (u->fixed_latency_range)
|
||||
return;
|
||||
|
||||
old_min_latency = u->sink->thread_info.min_latency;
|
||||
new_min_latency = PA_MIN(old_min_latency * 2, old_min_latency + TSCHED_WATERMARK_INC_STEP_USEC);
|
||||
new_min_latency = PA_MIN(new_min_latency, u->sink->thread_info.max_latency);
|
||||
|
|
@ -1969,7 +1974,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
|
|||
uint32_t nfrags, frag_size, buffer_size, tsched_size, tsched_watermark, rewind_safeguard;
|
||||
snd_pcm_uframes_t period_frames, buffer_frames, tsched_frames;
|
||||
size_t frame_size;
|
||||
pa_bool_t use_mmap = TRUE, b, use_tsched = TRUE, d, ignore_dB = FALSE, namereg_fail = FALSE, deferred_volume = FALSE, set_formats = FALSE;
|
||||
pa_bool_t use_mmap = TRUE, b, use_tsched = TRUE, d, ignore_dB = FALSE, namereg_fail = FALSE, deferred_volume = FALSE, set_formats = FALSE, fixed_latency_range = FALSE;
|
||||
pa_sink_new_data data;
|
||||
pa_alsa_profile_set *profile_set = NULL;
|
||||
|
||||
|
|
@ -2039,6 +2044,11 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
|
|||
goto fail;
|
||||
}
|
||||
|
||||
if (pa_modargs_get_value_boolean(ma, "fixed_latency_range", &fixed_latency_range) < 0) {
|
||||
pa_log("Failed to parse fixed_latency_range argument.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
use_tsched = pa_alsa_may_tsched(use_tsched);
|
||||
|
||||
u = pa_xnew0(struct userdata, 1);
|
||||
|
|
@ -2047,6 +2057,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
|
|||
u->use_mmap = use_mmap;
|
||||
u->use_tsched = use_tsched;
|
||||
u->deferred_volume = deferred_volume;
|
||||
u->fixed_latency_range = fixed_latency_range;
|
||||
u->first = TRUE;
|
||||
u->rewind_safeguard = rewind_safeguard;
|
||||
u->rtpoll = pa_rtpoll_new();
|
||||
|
|
@ -2143,9 +2154,13 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
|
|||
if (u->use_mmap)
|
||||
pa_log_info("Successfully enabled mmap() mode.");
|
||||
|
||||
if (u->use_tsched)
|
||||
if (u->use_tsched) {
|
||||
pa_log_info("Successfully enabled timer-based scheduling mode.");
|
||||
|
||||
if (u->fixed_latency_range)
|
||||
pa_log_info("Disabling latency range changes on underrun");
|
||||
}
|
||||
|
||||
if (is_iec958(u) || is_hdmi(u))
|
||||
set_formats = TRUE;
|
||||
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ struct userdata {
|
|||
char *device_name; /* name of the PCM device */
|
||||
char *control_device; /* name of the control device */
|
||||
|
||||
pa_bool_t use_mmap:1, use_tsched:1, deferred_volume:1;
|
||||
pa_bool_t use_mmap:1, use_tsched:1, deferred_volume:1, fixed_latency_range:1;
|
||||
|
||||
pa_bool_t first;
|
||||
|
||||
|
|
@ -306,7 +306,12 @@ static void increase_watermark(struct userdata *u) {
|
|||
return;
|
||||
}
|
||||
|
||||
/* Hmm, we cannot increase the watermark any further, hence let's raise the latency */
|
||||
/* Hmm, we cannot increase the watermark any further, hence let's
|
||||
raise the latency unless doing so was disabled in
|
||||
configuration */
|
||||
if (u->fixed_latency_range)
|
||||
return;
|
||||
|
||||
old_min_latency = u->source->thread_info.min_latency;
|
||||
new_min_latency = PA_MIN(old_min_latency * 2, old_min_latency + TSCHED_WATERMARK_INC_STEP_USEC);
|
||||
new_min_latency = PA_MIN(new_min_latency, u->source->thread_info.max_latency);
|
||||
|
|
@ -1710,7 +1715,7 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
|
|||
uint32_t nfrags, frag_size, buffer_size, tsched_size, tsched_watermark;
|
||||
snd_pcm_uframes_t period_frames, buffer_frames, tsched_frames;
|
||||
size_t frame_size;
|
||||
pa_bool_t use_mmap = TRUE, b, use_tsched = TRUE, d, ignore_dB = FALSE, namereg_fail = FALSE, deferred_volume = FALSE;
|
||||
pa_bool_t use_mmap = TRUE, b, use_tsched = TRUE, d, ignore_dB = FALSE, namereg_fail = FALSE, deferred_volume = FALSE, fixed_latency_range = FALSE;
|
||||
pa_source_new_data data;
|
||||
pa_alsa_profile_set *profile_set = NULL;
|
||||
|
||||
|
|
@ -1774,6 +1779,11 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
|
|||
goto fail;
|
||||
}
|
||||
|
||||
if (pa_modargs_get_value_boolean(ma, "fixed_latency_range", &fixed_latency_range) < 0) {
|
||||
pa_log("Failed to parse fixed_latency_range argument.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
use_tsched = pa_alsa_may_tsched(use_tsched);
|
||||
|
||||
u = pa_xnew0(struct userdata, 1);
|
||||
|
|
@ -1782,6 +1792,7 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
|
|||
u->use_mmap = use_mmap;
|
||||
u->use_tsched = use_tsched;
|
||||
u->deferred_volume = deferred_volume;
|
||||
u->fixed_latency_range = fixed_latency_range;
|
||||
u->first = TRUE;
|
||||
u->rtpoll = pa_rtpoll_new();
|
||||
pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
|
||||
|
|
@ -1877,8 +1888,11 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
|
|||
if (u->use_mmap)
|
||||
pa_log_info("Successfully enabled mmap() mode.");
|
||||
|
||||
if (u->use_tsched)
|
||||
if (u->use_tsched) {
|
||||
pa_log_info("Successfully enabled timer-based scheduling mode.");
|
||||
if (u->fixed_latency_range)
|
||||
pa_log_info("Disabling latency range changes on overrun");
|
||||
}
|
||||
|
||||
u->rates = pa_alsa_get_supported_rates(u->pcm_handle);
|
||||
if (!u->rates) {
|
||||
|
|
|
|||
|
|
@ -59,7 +59,8 @@ PA_MODULE_USAGE(
|
|||
"rewind_safeguard=<number of bytes that cannot be rewound> "
|
||||
"deferred_volume=<Synchronize software and hardware volume changes to avoid momentary jumps?> "
|
||||
"deferred_volume_safety_margin=<usec adjustment depending on volume direction> "
|
||||
"deferred_volume_extra_delay=<usec adjustment to HW volume changes>");
|
||||
"deferred_volume_extra_delay=<usec adjustment to HW volume changes> "
|
||||
"fixed_latency_range=<disable latency range changes on underrun?>");
|
||||
|
||||
static const char* const valid_modargs[] = {
|
||||
"name",
|
||||
|
|
@ -85,6 +86,7 @@ static const char* const valid_modargs[] = {
|
|||
"deferred_volume",
|
||||
"deferred_volume_safety_margin",
|
||||
"deferred_volume_extra_delay",
|
||||
"fixed_latency_range",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -67,7 +67,8 @@ PA_MODULE_USAGE(
|
|||
"control=<name of mixer control>"
|
||||
"deferred_volume=<Synchronize software and hardware volume changes to avoid momentary jumps?> "
|
||||
"deferred_volume_safety_margin=<usec adjustment depending on volume direction> "
|
||||
"deferred_volume_extra_delay=<usec adjustment to HW volume changes>");
|
||||
"deferred_volume_extra_delay=<usec adjustment to HW volume changes> "
|
||||
"fixed_latency_range=<disable latency range changes on overrun?>");
|
||||
|
||||
static const char* const valid_modargs[] = {
|
||||
"name",
|
||||
|
|
@ -92,6 +93,7 @@ static const char* const valid_modargs[] = {
|
|||
"deferred_volume",
|
||||
"deferred_volume_safety_margin",
|
||||
"deferred_volume_extra_delay",
|
||||
"fixed_latency_range",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1008,6 +1008,10 @@ static void fix_playback_buffer_attr(playback_stream *s) {
|
|||
tlength_usec -= s->configured_sink_latency;
|
||||
}
|
||||
|
||||
pa_log_debug("Requested latency=%0.2f ms, Received latency=%0.2f ms",
|
||||
(double) sink_usec / PA_USEC_PER_MSEC,
|
||||
(double) s->configured_sink_latency / PA_USEC_PER_MSEC);
|
||||
|
||||
/* FIXME: This is actually larger than necessary, since not all of
|
||||
* the sink latency is actually rewritable. */
|
||||
if (tlength_usec < s->configured_sink_latency + 2*minreq_usec)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue