summaryrefslogtreecommitdiff
path: root/src/modules/alsa
diff options
context:
space:
mode:
Diffstat (limited to 'src/modules/alsa')
-rw-r--r--src/modules/alsa/alsa-sink.c18
-rw-r--r--src/modules/alsa/module-alsa-sink.c4
2 files changed, 17 insertions, 5 deletions
diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c
index 687a83002..ce7970b23 100644
--- a/src/modules/alsa/alsa-sink.c
+++ b/src/modules/alsa/alsa-sink.c
@@ -83,6 +83,8 @@
#define VOLUME_ACCURACY (PA_VOLUME_NORM/100) /* don't require volume adjustments to be perfectly correct. don't necessarily extend granularity in software unless the differences get greater than this level */
+#define DEFAULT_REWIND_SAFEGUARD_BYTES (256) /* 1.33ms @48kHz, should work for most hardware */
+
struct userdata {
pa_core *core;
pa_module *module;
@@ -112,7 +114,8 @@ struct userdata {
watermark_inc_step,
watermark_dec_step,
watermark_inc_threshold,
- watermark_dec_threshold;
+ watermark_dec_threshold,
+ rewind_safeguard;
pa_usec_t watermark_dec_not_before;
@@ -1312,8 +1315,8 @@ static int process_rewind(struct userdata *u) {
unused_nbytes = (size_t) unused * u->frame_size;
- if (u->use_tsched)
- unused_nbytes += u->tsched_watermark;
+ /* make sure rewind doesn't go too far, can cause issues with DMAs */
+ unused_nbytes += u->rewind_safeguard;
if (u->hwbuf_size > unused_nbytes)
limit_nbytes = u->hwbuf_size - unused_nbytes;
@@ -1668,7 +1671,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
pa_channel_map map;
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;
+ size_t frame_size, rewind_safeguard;
pa_bool_t use_mmap = TRUE, b, use_tsched = TRUE, d, ignore_dB = FALSE;
pa_sink_new_data data;
pa_alsa_profile_set *profile_set = NULL;
@@ -1722,6 +1725,12 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
goto fail;
}
+ rewind_safeguard = DEFAULT_REWIND_SAFEGUARD_BYTES;
+ if (pa_modargs_get_value_u32(ma, "rewind_safeguard", &rewind_safeguard) < 0) {
+ pa_log("Failed to parse rewind_safeguard argument");
+ goto fail;
+ }
+
use_tsched = pa_alsa_may_tsched(use_tsched);
u = pa_xnew0(struct userdata, 1);
@@ -1730,6 +1739,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->first = TRUE;
+ u->rewind_safeguard = rewind_safeguard;
u->rtpoll = pa_rtpoll_new();
pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
diff --git a/src/modules/alsa/module-alsa-sink.c b/src/modules/alsa/module-alsa-sink.c
index 3aa89b2aa..a73274fdb 100644
--- a/src/modules/alsa/module-alsa-sink.c
+++ b/src/modules/alsa/module-alsa-sink.c
@@ -54,7 +54,8 @@ PA_MODULE_USAGE(
"tsched_buffer_size=<buffer size when using timer based scheduling> "
"tsched_buffer_watermark=<lower fill watermark> "
"ignore_dB=<ignore dB information from the device?> "
- "control=<name of mixer control>");
+ "control=<name of mixer control>"
+ "rewind_safeguard=<number of bytes that cannot be rewound");
static const char* const valid_modargs[] = {
"name",
@@ -74,6 +75,7 @@ static const char* const valid_modargs[] = {
"tsched_buffer_watermark",
"ignore_dB",
"control",
+ "rewind_safeguard",
NULL
};