}
/* Called from IO context */
-static int update_sw_params(struct userdata *u) {
+static int update_sw_params(struct userdata *u, bool may_need_rewind) {
+ size_t old_unused;
snd_pcm_uframes_t avail_min;
int err;
pa_assert(u);
/* Use the full buffer if no one asked us for anything specific */
+ old_unused = u->hwbuf_unused;
u->hwbuf_unused = 0;
if (u->use_tsched) {
return err;
}
+ /* If we're lowering the latency, we need to do a rewind, because otherwise
+ * we might end up in a situation where the hw buffer contains more data
+ * than the new configured latency. The rewind has to be requested before
+ * updating max_rewind, because the rewind amount is limited to max_rewind.
+ *
+ * If may_need_rewind is false, it means that we're just starting playback,
+ * and rewinding is never needed in that situation. */
+ if (may_need_rewind && u->hwbuf_unused > old_unused) {
+ pa_log_debug("Requesting rewind due to latency change.");
+ pa_sink_request_rewind(u->sink, (size_t) -1);
+ }
+
pa_sink_set_max_request_within_thread(u->sink, u->hwbuf_size - u->hwbuf_unused);
- if (pa_alsa_pcm_is_hw(u->pcm_handle))
- pa_sink_set_max_rewind_within_thread(u->sink, u->hwbuf_size);
+ if (pa_alsa_pcm_is_hw(u->pcm_handle))
+ pa_sink_set_max_rewind_within_thread(u->sink, u->hwbuf_size - u->hwbuf_unused);
else {
pa_log_info("Disabling rewind_within_thread for device %s", u->device_name);
pa_sink_set_max_rewind_within_thread(u->sink, 0);
goto fail;
}
- if (update_sw_params(u) < 0)
+ if (update_sw_params(u, false) < 0)
goto fail;
if (build_pollfd(u) < 0)
static void sink_update_requested_latency_cb(pa_sink *s) {
struct userdata *u = s->userdata;
- size_t before;
pa_assert(u);
pa_assert(u->use_tsched); /* only when timer scheduling is used
* we can dynamically adjust the
if (!u->pcm_handle)
return;
- before = u->hwbuf_unused;
- update_sw_params(u);
-
- /* Let's check whether we now use only a smaller part of the
- buffer then before. If so, we need to make sure that subsequent
- rewinds are relative to the new maximum fill level and not to the
- current fill level. Thus, let's do a full rewind once, to clear
- things up. */
-
- if (u->hwbuf_unused > before) {
- pa_log_debug("Requesting rewind due to latency change.");
- pa_sink_request_rewind(s, (size_t) -1);
- }
+ update_sw_params(u, true);
}
static pa_idxset* sink_get_formats(pa_sink *s) {
reserve_update(u);
- if (update_sw_params(u) < 0)
+ if (update_sw_params(u, false) < 0)
goto fail;
if (u->ucm_context) {