[pulseaudio-commits] r2443 - /branches/glitch-free/src/modules/module-alsa-source.c

svnmailer-noreply at 0pointer.de svnmailer-noreply at 0pointer.de
Thu May 15 16:19:39 PDT 2008


Author: lennart
Date: Fri May 16 01:19:37 2008
New Revision: 2443

URL: http://0pointer.de/cgi-bin/viewcvs.cgi?rev=2443&root=pulseaudio&view=rev
Log:
follow recent alsa sink changes in the alsa source

Modified:
    branches/glitch-free/src/modules/module-alsa-source.c

Modified: branches/glitch-free/src/modules/module-alsa-source.c
URL: http://0pointer.de/cgi-bin/viewcvs.cgi/branches/glitch-free/src/modules/module-alsa-source.c?rev=2443&root=pulseaudio&r1=2442&r2=2443&view=diff
==============================================================================
--- branches/glitch-free/src/modules/module-alsa-source.c (original)
+++ branches/glitch-free/src/modules/module-alsa-source.c Fri May 16 01:19:37 2008
@@ -3,7 +3,7 @@
 /***
   This file is part of PulseAudio.
 
-  Copyright 2004-2006 Lennart Poettering
+  Copyright 2004-2008 Lennart Poettering
   Copyright 2006 Pierre Ossman <ossman at cendio.se> for Cendio AB
 
   PulseAudio is free software; you can redistribute it and/or modify
@@ -93,10 +93,10 @@
 };
 
 #define DEFAULT_DEVICE "default"
-#define DEFAULT_TSCHED_BUFFER_USEC (5*PA_USEC_PER_SEC)
-#define DEFAULT_TSCHED_WATERMARK_USEC (20*PA_USEC_PER_MSEC)
-#define TSCHED_MIN_SLEEP_USEC (3*PA_USEC_PER_MSEC)        /* 3ms */
-#define TSCHED_MIN_WAKEUP_USEC (3*PA_USEC_PER_MSEC)        /* 3ms */
+#define DEFAULT_TSCHED_BUFFER_USEC (2*PA_USEC_PER_SEC)       /* 2s */
+#define DEFAULT_TSCHED_WATERMARK_USEC (20*PA_USEC_PER_MSEC)  /* 20ms */
+#define TSCHED_MIN_SLEEP_USEC (3*PA_USEC_PER_MSEC)           /* 3ms */
+#define TSCHED_MIN_WAKEUP_USEC (3*PA_USEC_PER_MSEC)          /* 3ms */
 
 struct userdata {
     pa_core *core;
@@ -160,6 +160,31 @@
         u->tsched_watermark = min_wakeup;
 }
 
+static pa_usec_t hw_sleep_time(struct userdata *u, pa_usec_t *sleep_usec, pa_usec_t*process_usec) {
+    pa_usec_t wm, usec;
+
+    pa_assert(u);
+
+    usec = pa_source_get_requested_latency_within_thread(u->source);
+
+    if (usec == (pa_usec_t) -1)
+        usec = pa_bytes_to_usec(u->hwbuf_size, &u->source->sample_spec);
+
+/*     pa_log_debug("hw buffer time: %u ms", (unsigned) (usec / PA_USEC_PER_MSEC)); */
+
+    wm = pa_bytes_to_usec(u->tsched_watermark, &u->source->sample_spec);
+
+    if (usec >= wm) {
+        *sleep_usec = usec - wm;
+        *process_usec = wm;
+    } else
+        *process_usec = *sleep_usec = usec /= 2;
+
+/*     pa_log_debug("after watermark: %u ms", (unsigned) (*sleep_usec / PA_USEC_PER_MSEC)); */
+
+    return usec;
+}
+
 static int try_recover(struct userdata *u, const char *call, int err) {
     pa_assert(u);
     pa_assert(call);
@@ -167,10 +192,7 @@
 
     pa_log_debug("%s: %s", call, snd_strerror(err));
 
-    if (err == -EAGAIN) {
-        pa_log_debug("%s: EAGAIN", call);
-        return 1;
-    }
+    pa_assert(err != -EAGAIN);
 
     if (err == -EPIPE)
         pa_log_debug("%s: Buffer overrun!", call);
@@ -184,7 +206,7 @@
     return -1;
 }
 
-static void check_left_to_record(struct userdata *u, snd_pcm_sframes_t n) {
+static size_t check_left_to_record(struct userdata *u, snd_pcm_sframes_t n) {
     size_t left_to_record;
 
     if (n*u->frame_size < u->hwbuf_size)
@@ -192,9 +214,9 @@
     else
         left_to_record = 0;
 
-    if (left_to_record > 0)
-        pa_log_debug("%0.2f ms left to record", (double) pa_bytes_to_usec(left_to_record, &u->source->sample_spec) / PA_USEC_PER_MSEC);
-    else {
+    if (left_to_record > 0) {
+/*         pa_log_debug("%0.2f ms left to record", (double) pa_bytes_to_usec(left_to_record, &u->source->sample_spec) / PA_USEC_PER_MSEC); */
+    } else {
         pa_log_info("Overrun!");
 
         if (u->use_tsched) {
@@ -208,173 +230,191 @@
                               (double) pa_bytes_to_usec(u->tsched_watermark, &u->source->sample_spec) / PA_USEC_PER_MSEC);
         }
     }
-}
-
-static int mmap_read(struct userdata *u) {
+
+    return left_to_record;
+}
+
+static int mmap_read(struct userdata *u, pa_usec_t *sleep_usec) {
     int work_done = 0;
-    pa_bool_t checked_left_to_record = FALSE;
+    pa_usec_t max_sleep_usec, process_usec;
+    size_t left_to_record;
 
     pa_assert(u);
     pa_source_assert_ref(u->source);
+
+    if (u->use_tsched)
+        hw_sleep_time(u, &max_sleep_usec, &process_usec);
 
     for (;;) {
         snd_pcm_sframes_t n;
-        int err, r;
-        const snd_pcm_channel_area_t *areas;
-        snd_pcm_uframes_t offset, frames;
-        pa_memchunk chunk;
-        void *p;
+        int r;
 
         snd_pcm_hwsync(u->pcm_handle);
 
         if (PA_UNLIKELY((n = snd_pcm_avail_update(u->pcm_handle)) < 0)) {
 
-            if ((r = try_recover(u, "snd_pcm_avail_update", err)) == 0)
+            if ((r = try_recover(u, "snd_pcm_avail_update", n)) == 0)
                 continue;
-            else if (r > 0)
-                return work_done;
 
             return r;
         }
 
-        if (checked_left_to_record) {
-            check_left_to_record(u, n);
-            checked_left_to_record = TRUE;
+        left_to_record = check_left_to_record(u, n);
+
+        if (u->use_tsched)
+            if (pa_bytes_to_usec(left_to_record, &u->source->sample_spec) > max_sleep_usec/2)
+                break;
+
+        if (PA_UNLIKELY(n <= 0))
+            break;
+
+        for (;;) {
+            int err;
+            const snd_pcm_channel_area_t *areas;
+            snd_pcm_uframes_t offset, frames = (snd_pcm_uframes_t) n;
+            pa_memchunk chunk;
+            void *p;
+
+/*             pa_log_debug("%lu frames to read", (unsigned long) frames); */
+
+            if (PA_UNLIKELY((err = snd_pcm_mmap_begin(u->pcm_handle, &areas, &offset, &frames)) < 0)) {
+
+                if ((r = try_recover(u, "snd_pcm_mmap_begin", err)) == 0)
+                    continue;
+
+                return r;
+            }
+
+            /* Make sure that if these memblocks need to be copied they will fit into one slot */
+            if (frames > pa_mempool_block_size_max(u->source->core->mempool)/u->frame_size)
+                frames = pa_mempool_block_size_max(u->source->core->mempool)/u->frame_size;
+
+            /* Check these are multiples of 8 bit */
+            pa_assert((areas[0].first & 7) == 0);
+            pa_assert((areas[0].step & 7)== 0);
+
+            /* We assume a single interleaved memory buffer */
+            pa_assert((areas[0].first >> 3) == 0);
+            pa_assert((areas[0].step >> 3) == u->frame_size);
+
+            p = (uint8_t*) areas[0].addr + (offset * u->frame_size);
+
+            chunk.memblock = pa_memblock_new_fixed(u->core->mempool, p, frames * u->frame_size, TRUE);
+            chunk.length = pa_memblock_get_length(chunk.memblock);
+            chunk.index = 0;
+
+            pa_source_post(u->source, &chunk);
+            pa_memblock_unref_fixed(chunk.memblock);
+
+            if (PA_UNLIKELY((err = snd_pcm_mmap_commit(u->pcm_handle, offset, frames)) < 0)) {
+
+                if ((r = try_recover(u, "snd_pcm_mmap_commit", err)) == 0)
+                    continue;
+
+                return r;
+            }
+
+            work_done = 1;
+
+            u->frame_index += frames;
+
+/*             pa_log_debug("read %lu frames", (unsigned long) frames); */
+
+            if (frames >= (snd_pcm_uframes_t) n)
+                break;
+
+            n -= frames;
         }
+    }
+
+    *sleep_usec = pa_bytes_to_usec(left_to_record, &u->source->sample_spec) - process_usec;
+    return work_done;
+}
+
+static int unix_read(struct userdata *u, pa_usec_t *sleep_usec) {
+    int work_done = 0;
+    pa_usec_t max_sleep_usec, process_usec;
+    size_t left_to_record;
+
+    pa_assert(u);
+    pa_source_assert_ref(u->source);
+
+    if (u->use_tsched)
+        hw_sleep_time(u, &max_sleep_usec, &process_usec);
+
+    for (;;) {
+        snd_pcm_sframes_t n;
+        int r;
+
+        snd_pcm_hwsync(u->pcm_handle);
+
+        if (PA_UNLIKELY((n = snd_pcm_avail_update(u->pcm_handle)) < 0)) {
+
+            if ((r = try_recover(u, "snd_pcm_avail_update", n)) == 0)
+                continue;
+
+            return r;
+        }
+
+        left_to_record = check_left_to_record(u, n);
+
+        if (u->use_tsched)
+            if (pa_bytes_to_usec(left_to_record, &u->source->sample_spec) > max_sleep_usec/2)
+                break;
 
         if (PA_UNLIKELY(n <= 0))
             return work_done;
 
-        frames = n;
-
-        pa_log_debug("%lu frames to read", (unsigned long) frames);
-
-        if (PA_UNLIKELY((err = snd_pcm_mmap_begin(u->pcm_handle, &areas, &offset, &frames)) < 0)) {
-
-            if ((r = try_recover(u, "snd_pcm_mmap_begin", err)) == 0)
-                continue;
-            else if (r > 0)
-                return work_done;
-
-            return r;
+        for (;;) {
+            void *p;
+            snd_pcm_sframes_t frames;
+            pa_memchunk chunk;
+
+            chunk.memblock = pa_memblock_new(u->core->mempool, (size_t) -1);
+
+            frames = pa_memblock_get_length(chunk.memblock) / u->frame_size;
+
+            if (frames > n)
+                frames = n;
+
+/*             pa_log_debug("%lu frames to read", (unsigned long) n); */
+
+            p = pa_memblock_acquire(chunk.memblock);
+            frames = snd_pcm_readi(u->pcm_handle, (uint8_t*) p, frames);
+            pa_memblock_release(chunk.memblock);
+
+            pa_assert(frames != 0);
+
+            if (PA_UNLIKELY(frames < 0)) {
+                pa_memblock_unref(chunk.memblock);
+
+                if ((r = try_recover(u, "snd_pcm_readi", n)) == 0)
+                    continue;
+
+                return r;
+            }
+
+            chunk.index = 0;
+            chunk.length = frames * u->frame_size;
+
+            pa_source_post(u->source, &chunk);
+            pa_memblock_unref(chunk.memblock);
+
+            work_done = 1;
+
+            u->frame_index += frames;
+
+/*             pa_log_debug("read %lu frames", (unsigned long) frames); */
+
+            if (frames >= n)
+                break;
+
+            n -= frames;
         }
-
-        /* Make sure that if these memblocks need to be copied they will fit into one slot */
-        if (frames > pa_mempool_block_size_max(u->source->core->mempool)/u->frame_size)
-            frames = pa_mempool_block_size_max(u->source->core->mempool)/u->frame_size;
-
-        /* Check these are multiples of 8 bit */
-        pa_assert((areas[0].first & 7) == 0);
-        pa_assert((areas[0].step & 7)== 0);
-
-        /* We assume a single interleaved memory buffer */
-        pa_assert((areas[0].first >> 3) == 0);
-        pa_assert((areas[0].step >> 3) == u->frame_size);
-
-        p = (uint8_t*) areas[0].addr + (offset * u->frame_size);
-
-        chunk.memblock = pa_memblock_new_fixed(u->core->mempool, p, frames * u->frame_size, TRUE);
-        chunk.length = pa_memblock_get_length(chunk.memblock);
-        chunk.index = 0;
-
-        pa_source_post(u->source, &chunk);
-        pa_memblock_unref_fixed(chunk.memblock);
-
-        if (PA_UNLIKELY((err = snd_pcm_mmap_commit(u->pcm_handle, offset, frames)) < 0)) {
-
-            if ((r = try_recover(u, "snd_pcm_mmap_commit", err)) == 0)
-                continue;
-            else if (r > 0)
-                return work_done;
-
-            return r;
-        }
-
-        work_done = 1;
-
-        u->frame_index += frames;
-
-        pa_log_debug("read %lu frames", (unsigned long) frames);
-
-        if (PA_LIKELY(frames >= (snd_pcm_uframes_t) n))
-            return work_done;
-    }
-}
-
-static int unix_read(struct userdata *u) {
-    int work_done = 0;
-    pa_bool_t checked_left_to_record = FALSE;
-
-    pa_assert(u);
-    pa_source_assert_ref(u->source);
-
-    for (;;) {
-        void *p;
-        snd_pcm_sframes_t n, frames;
-        int r;
-        pa_memchunk chunk;
-
-        snd_pcm_hwsync(u->pcm_handle);
-
-        if (PA_UNLIKELY((n = snd_pcm_avail_update(u->pcm_handle)) < 0)) {
-
-            if ((r = try_recover(u, "snd_pcm_avail_update", n)) == 0)
-                continue;
-            else if (r > 0)
-                return work_done;
-
-            return r;
-        }
-
-        if (checked_left_to_record) {
-            check_left_to_record(u, n);
-            checked_left_to_record = TRUE;
-        }
-
-        if (PA_UNLIKELY(n <= 0))
-            return work_done;
-
-        chunk.memblock = pa_memblock_new(u->core->mempool, (size_t) -1);
-
-        frames = pa_memblock_get_length(chunk.memblock) / u->frame_size;
-
-        if (frames > n)
-            frames = n;
-
-        pa_log_debug("%lu frames to read", (unsigned long) n);
-
-        p = pa_memblock_acquire(chunk.memblock);
-        frames = snd_pcm_readi(u->pcm_handle, (uint8_t*) p, frames);
-        pa_memblock_release(chunk.memblock);
-
-        pa_assert(frames != 0);
-
-        if (PA_UNLIKELY(frames < 0)) {
-            pa_memblock_unref(chunk.memblock);
-
-            if ((r = try_recover(u, "snd_pcm_readi", n)) == 0)
-                continue;
-            else if (r > 0)
-                return work_done;
-
-            return r;
-        }
-
-        chunk.index = 0;
-        chunk.length = frames * u->frame_size;
-
-        pa_source_post(u->source, &chunk);
-        pa_memblock_unref(chunk.memblock);
-
-        work_done = 1;
-
-        u->frame_index += frames;
-
-        pa_log_debug("read %lu frames", (unsigned long) frames);
-
-        if (PA_LIKELY(frames >= n))
-            return work_done;
-    }
+    }
+
+    *sleep_usec = pa_bytes_to_usec(left_to_record, &u->source->sample_spec) - process_usec;
+    return work_done;
 }
 
 static void update_smoother(struct userdata *u) {
@@ -455,30 +495,6 @@
     return 0;
 }
 
-static pa_usec_t hw_sleep_time(struct userdata *u) {
-    pa_usec_t wm, usec;
-
-    pa_assert(u);
-
-    usec = pa_source_get_requested_latency_within_thread(u->source);
-
-    if (usec == (pa_usec_t) -1)
-        usec = pa_bytes_to_usec(u->hwbuf_size, &u->source->sample_spec);
-
-/*     pa_log_debug("hw buffer time: %u ms", (unsigned) (usec / PA_USEC_PER_MSEC)); */
-
-    wm = pa_bytes_to_usec(u->tsched_watermark, &u->source->sample_spec);
-
-    if (usec >= wm)
-        usec -= wm;
-    else
-        usec /= 2;
-
-/*     pa_log_debug("after watermark: %u ms", (unsigned) (usec / PA_USEC_PER_MSEC)); */
-
-    return usec;
-}
-
 static int update_sw_params(struct userdata *u) {
     snd_pcm_uframes_t avail_min;
     int err;
@@ -516,10 +532,10 @@
     avail_min = 1;
 
     if (u->use_tsched) {
-        pa_usec_t usec;
-
-        usec = hw_sleep_time(u);
-        avail_min += pa_usec_to_bytes(usec, &u->source->sample_spec);
+        pa_usec_t sleep_usec, process_usec;
+
+        hw_sleep_time(u, &sleep_usec, &process_usec);
+        avail_min += pa_usec_to_bytes(sleep_usec, &u->source->sample_spec);
     }
 
     pa_log_debug("setting avail_min=%lu", (unsigned long) avail_min);
@@ -794,8 +810,10 @@
 
 static void source_update_requested_latency_cb(pa_source *s) {
     struct userdata *u = s->userdata;
-
-    pa_assert(u);
+    pa_assert(u);
+
+    if (!u->pcm_handle)
+        return;
 
     update_sw_params(u);
 }
@@ -816,43 +834,42 @@
     for (;;) {
         int ret;
 
-        pa_log_debug("loop");
+/*         pa_log_debug("loop"); */
 
         /* Read some data and pass it to the sources */
         if (PA_SOURCE_IS_OPENED(u->source->thread_info.state)) {
             int work_done = 0;
+            pa_usec_t sleep_usec;
 
             if (u->use_mmap)
-                work_done = mmap_read(u);
+                work_done = mmap_read(u, &sleep_usec);
             else
-                work_done = unix_read(u);
+                work_done = unix_read(u, &sleep_usec);
 
             if (work_done < 0)
                 goto fail;
 
-            pa_log_debug("work_done = %i", work_done);
+/*             pa_log_debug("work_done = %i", work_done); */
 
             if (work_done)
                 update_smoother(u);
 
             if (u->use_tsched) {
-                pa_usec_t usec, cusec;
+                pa_usec_t cusec;
 
                 /* OK, the capture buffer is now empty, let's
                  * calculate when to wake up next */
 
-                usec = hw_sleep_time(u);
-
-                pa_log_debug("Waking up in %0.2fms (sound card clock).", (double) usec / PA_USEC_PER_MSEC);
+/*                 pa_log_debug("Waking up in %0.2fms (sound card clock).", (double) sleep_usec / PA_USEC_PER_MSEC); */
 
                 /* Convert from the sound card time domain to the
                  * system time domain */
-                cusec = pa_smoother_translate(u->smoother, pa_rtclock_usec(), usec);
-
-                pa_log_debug("Waking up in %0.2fms (system clock).", (double) cusec / PA_USEC_PER_MSEC);
+                cusec = pa_smoother_translate(u->smoother, pa_rtclock_usec(), sleep_usec);
+
+/*                 pa_log_debug("Waking up in %0.2fms (system clock).", (double) cusec / PA_USEC_PER_MSEC); */
 
                 /* We don't trust the conversion, so we wake up whatever comes first */
-                pa_rtpoll_set_timer_relative(u->rtpoll, PA_MIN(usec, cusec));
+                pa_rtpoll_set_timer_relative(u->rtpoll, PA_MIN(sleep_usec, cusec));
             }
         } else if (u->use_tsched)
 
@@ -887,7 +904,7 @@
                 snd_pcm_start(u->pcm_handle);
             }
 
-            if (revents)
+            if (revents && u->use_tsched)
                 pa_log_debug("Wakeup from ALSA! (%i)", revents);
         }
     }




More information about the pulseaudio-commits mailing list