[pulseaudio-commits] [SCM] PulseAudio Sound Server branch, master, updated. v0.9.16-test7-53-g557c429

Lennart Poettering gitmailer-noreply at 0pointer.de
Tue Sep 8 19:30:50 PDT 2009


This is an automated email from the git hooks/post-receive script. It was
generated because of a push to the "PulseAudio Sound Server" repository.

The master branch has been updated
      from  c2f1994968e71f0f0a6c1f44bd8ec40edf1b6434 (commit)

- Log -----------------------------------------------------------------
557c429 alsa: rework buffer/period configuration
71e066c simd: be more precise which SIMD optimizations we activate
1f0904b sample-util: add pa_convert_size() call for converting sizes between two sample specs
-----------------------------------------------------------------------

Summary of changes:
 src/modules/alsa/alsa-sink.c   |   44 ++++----
 src/modules/alsa/alsa-source.c |   45 ++++----
 src/modules/alsa/alsa-util.c   |  248 ++++++++++++++++++++++++++--------------
 src/modules/alsa/alsa-util.h   |   10 +-
 src/pulsecore/remap_mmx.c      |    8 +-
 src/pulsecore/remap_sse.c      |    8 +-
 src/pulsecore/sample-util.c    |   10 ++
 src/pulsecore/sample-util.h    |    2 +
 src/pulsecore/sconv_sse.c      |   12 +-
 src/pulsecore/svolume_mmx.c    |    9 +-
 src/pulsecore/svolume_sse.c    |    7 +-
 11 files changed, 257 insertions(+), 146 deletions(-)

-----------------------------------------------------------------------

commit 1f0904b800d9d69698e79ce0435a2777d5f7ec27
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Sep 9 04:27:16 2009 +0200

    sample-util: add pa_convert_size() call for converting sizes between two sample specs

diff --git a/src/pulsecore/sample-util.c b/src/pulsecore/sample-util.c
index 5fae192..a26dc87 100644
--- a/src/pulsecore/sample-util.c
+++ b/src/pulsecore/sample-util.c
@@ -1056,3 +1056,13 @@ void pa_memchunk_sine(pa_memchunk *c, pa_mempool *pool, unsigned rate, unsigned
     calc_sine(p, c->length, freq * l / rate);
     pa_memblock_release(c->memblock);
 }
+
+size_t pa_convert_size(size_t size, const pa_sample_spec *from, const pa_sample_spec *to) {
+    pa_usec_t usec;
+
+    pa_assert(from);
+    pa_assert(to);
+
+    usec = pa_bytes_to_usec_round_up(size, from);
+    return pa_usec_to_bytes_round_up(usec, to);
+}
diff --git a/src/pulsecore/sample-util.h b/src/pulsecore/sample-util.h
index 34df5cf..d0235d6 100644
--- a/src/pulsecore/sample-util.h
+++ b/src/pulsecore/sample-util.h
@@ -91,6 +91,8 @@ typedef void (*pa_do_volume_func_t) (void *samples, void *volumes, unsigned chan
 pa_do_volume_func_t pa_get_volume_func(pa_sample_format_t f);
 void pa_set_volume_func(pa_sample_format_t f, pa_do_volume_func_t func);
 
+size_t pa_convert_size(size_t size, const pa_sample_spec *from, const pa_sample_spec *to);
+
 #define PA_CHANNEL_POSITION_MASK_LEFT                                   \
     (PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_FRONT_LEFT)           \
      | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_REAR_LEFT)          \

commit 71e066c873e5bd31bd446ac0f8d0e97cc0b12ace
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Sep 9 04:28:22 2009 +0200

    simd: be more precise which SIMD optimizations we activate

diff --git a/src/pulsecore/remap_mmx.c b/src/pulsecore/remap_mmx.c
index 79e4f1f..d358a58 100644
--- a/src/pulsecore/remap_mmx.c
+++ b/src/pulsecore/remap_mmx.c
@@ -150,8 +150,12 @@ static void init_remap_mmx (pa_remap_t *m) {
 
 void pa_remap_func_init_mmx (pa_cpu_x86_flag_t flags) {
 #if defined (__i386__) || defined (__amd64__)
-    pa_log_info("Initialising MMX optimized remappers.");
 
-    pa_set_init_remap_func ((pa_init_remap_func_t) init_remap_mmx);
+    if (flags & PA_CPU_X86_MMX) {
+        pa_log_info("Initialising MMX optimized remappers.");
+
+        pa_set_init_remap_func ((pa_init_remap_func_t) init_remap_mmx);
+    }
+
 #endif /* defined (__i386__) || defined (__amd64__) */
 }
diff --git a/src/pulsecore/remap_sse.c b/src/pulsecore/remap_sse.c
index dac072e..0ccf316 100644
--- a/src/pulsecore/remap_sse.c
+++ b/src/pulsecore/remap_sse.c
@@ -149,9 +149,11 @@ static void init_remap_sse2 (pa_remap_t *m) {
 
 void pa_remap_func_init_sse (pa_cpu_x86_flag_t flags) {
 #if defined (__i386__) || defined (__amd64__)
-    pa_log_info("Initialising SSE optimized remappers.");
 
-    if (flags & PA_CPU_X86_SSE2)
-      pa_set_init_remap_func ((pa_init_remap_func_t) init_remap_sse2);
+    if (flags & PA_CPU_X86_SSE2) {
+        pa_log_info("Initialising SSE2 optimized remappers.");
+        pa_set_init_remap_func ((pa_init_remap_func_t) init_remap_sse2);
+    }
+
 #endif /* defined (__i386__) || defined (__amd64__) */
 }
diff --git a/src/pulsecore/sconv_sse.c b/src/pulsecore/sconv_sse.c
index 7c3aa19..3737af2 100644
--- a/src/pulsecore/sconv_sse.c
+++ b/src/pulsecore/sconv_sse.c
@@ -218,16 +218,18 @@ static void run_test (void) {
 
 void pa_convert_func_init_sse (pa_cpu_x86_flag_t flags) {
 #if defined (__i386__) || defined (__amd64__)
-    pa_log_info("Initialising SSE optimized conversions.");
 
 #ifdef RUN_TEST
     run_test ();
 #endif
 
-    if (flags & PA_CPU_X86_SSE2)
-      pa_set_convert_from_float32ne_function (PA_SAMPLE_S16LE, (pa_convert_func_t) pa_sconv_s16le_from_f32ne_sse2);
-    else
-      pa_set_convert_from_float32ne_function (PA_SAMPLE_S16LE, (pa_convert_func_t) pa_sconv_s16le_from_f32ne_sse);
+    if (flags & PA_CPU_X86_SSE2) {
+        pa_log_info("Initialising SSE2 optimized conversions.");
+        pa_set_convert_from_float32ne_function (PA_SAMPLE_S16LE, (pa_convert_func_t) pa_sconv_s16le_from_f32ne_sse2);
+    } else {
+        pa_log_info("Initialising SSE optimized conversions.");
+        pa_set_convert_from_float32ne_function (PA_SAMPLE_S16LE, (pa_convert_func_t) pa_sconv_s16le_from_f32ne_sse);
+    }
 
 #endif /* defined (__i386__) || defined (__amd64__) */
 }
diff --git a/src/pulsecore/svolume_mmx.c b/src/pulsecore/svolume_mmx.c
index 8510b0c..74918e7 100644
--- a/src/pulsecore/svolume_mmx.c
+++ b/src/pulsecore/svolume_mmx.c
@@ -301,13 +301,16 @@ static void run_test (void) {
 
 void pa_volume_func_init_mmx (pa_cpu_x86_flag_t flags) {
 #if defined (__i386__) || defined (__amd64__)
-    pa_log_info("Initialising MMX optimized functions.");
 
 #ifdef RUN_TEST
     run_test ();
 #endif
 
-    pa_set_volume_func (PA_SAMPLE_S16NE,     (pa_do_volume_func_t) pa_volume_s16ne_mmx);
-    pa_set_volume_func (PA_SAMPLE_S16RE,     (pa_do_volume_func_t) pa_volume_s16re_mmx);
+    if (flags & PA_CPU_X86_MMX) {
+        pa_log_info("Initialising MMX optimized functions.");
+
+        pa_set_volume_func (PA_SAMPLE_S16NE, (pa_do_volume_func_t) pa_volume_s16ne_mmx);
+        pa_set_volume_func (PA_SAMPLE_S16RE, (pa_do_volume_func_t) pa_volume_s16re_mmx);
+    }
 #endif /* defined (__i386__) || defined (__amd64__) */
 }
diff --git a/src/pulsecore/svolume_sse.c b/src/pulsecore/svolume_sse.c
index d9dcf47..bbd73a9 100644
--- a/src/pulsecore/svolume_sse.c
+++ b/src/pulsecore/svolume_sse.c
@@ -302,15 +302,16 @@ static void run_test (void) {
 
 void pa_volume_func_init_sse (pa_cpu_x86_flag_t flags) {
 #if defined (__i386__) || defined (__amd64__)
-    pa_log_info("Initialising SSE optimized functions.");
 
 #ifdef RUN_TEST
     run_test ();
 #endif
 
     if (flags & PA_CPU_X86_SSE2) {
-      pa_set_volume_func (PA_SAMPLE_S16NE,     (pa_do_volume_func_t) pa_volume_s16ne_sse2);
-      pa_set_volume_func (PA_SAMPLE_S16RE,     (pa_do_volume_func_t) pa_volume_s16re_sse2);
+        pa_log_info("Initialising SSE2 optimized functions.");
+
+        pa_set_volume_func (PA_SAMPLE_S16NE, (pa_do_volume_func_t) pa_volume_s16ne_sse2);
+        pa_set_volume_func (PA_SAMPLE_S16RE, (pa_do_volume_func_t) pa_volume_s16re_sse2);
     }
 #endif /* defined (__i386__) || defined (__amd64__) */
 }

commit 557c4295107dc7374c850b0bd5331dd35e8fdd0f
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Sep 9 04:28:52 2009 +0200

    alsa: rework buffer/period configuration
    
    - As discussed on alsa-devel it's probably better to initialize the
      buffer size first, followed by the period size. If that fails try the
      other way round. If that fails try to configure only buffer size. If
      that fails try to configure only period size. Finally, try to
      configure neither.
    
    - Don't require integral periods anymore.
    
    Both of these changes should help improving compatibility with various
    weirder sound devices, such as TV cards.

diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c
index 883b32a..c4ff10d 100644
--- a/src/modules/alsa/alsa-sink.c
+++ b/src/modules/alsa/alsa-sink.c
@@ -116,7 +116,6 @@ struct userdata {
 
     pa_usec_t watermark_dec_not_before;
 
-    unsigned nfragments;
     pa_memchunk memchunk;
 
     char *device_name;  /* name of the PCM device */
@@ -943,8 +942,7 @@ static int unsuspend(struct userdata *u) {
     pa_sample_spec ss;
     int err;
     pa_bool_t b, d;
-    unsigned nfrags;
-    snd_pcm_uframes_t period_size;
+    snd_pcm_uframes_t period_size, buffer_size;
 
     pa_assert(u);
     pa_assert(!u->pcm_handle);
@@ -961,12 +959,12 @@ static int unsuspend(struct userdata *u) {
     }
 
     ss = u->sink->sample_spec;
-    nfrags = u->nfragments;
     period_size = u->fragment_size / u->frame_size;
+    buffer_size = u->hwbuf_size / u->frame_size;
     b = u->use_mmap;
     d = u->use_tsched;
 
-    if ((err = pa_alsa_set_hw_params(u->pcm_handle, &ss, &nfrags, &period_size, u->hwbuf_size / u->frame_size, &b, &d, TRUE)) < 0) {
+    if ((err = pa_alsa_set_hw_params(u->pcm_handle, &ss, &period_size, &buffer_size, 0, &b, &d, TRUE)) < 0) {
         pa_log("Failed to set hardware parameters: %s", pa_alsa_strerror(err));
         goto fail;
     }
@@ -981,10 +979,11 @@ static int unsuspend(struct userdata *u) {
         goto fail;
     }
 
-    if (nfrags != u->nfragments || period_size*u->frame_size != u->fragment_size) {
-        pa_log_warn("Resume failed, couldn't restore original fragment settings. (Old: %lu*%lu, New %lu*%lu)",
-                    (unsigned long) u->nfragments, (unsigned long) u->fragment_size,
-                    (unsigned long) nfrags, period_size * u->frame_size);
+    if (period_size*u->frame_size != u->fragment_size ||
+        buffer_size*u->frame_size != u->hwbuf_size) {
+        pa_log_warn("Resume failed, couldn't restore original fragment settings. (Old: %lu/%lu, New %lu/%lu)",
+                    (unsigned long) u->hwbuf_size, (unsigned long) u->fragment_size,
+                    (unsigned long) (buffer_size*u->fragment_size), (unsigned long) (period_size*u->frame_size));
         goto fail;
     }
 
@@ -1638,8 +1637,8 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
     const char *dev_id = NULL;
     pa_sample_spec ss, requested_ss;
     pa_channel_map map;
-    uint32_t nfrags, frag_size, tsched_size, tsched_watermark;
-    snd_pcm_uframes_t period_frames, tsched_frames;
+    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;
     pa_sink_new_data data;
@@ -1673,7 +1672,10 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
         goto fail;
     }
 
+    buffer_size = nfrags * frag_size;
+
     period_frames = frag_size/frame_size;
+    buffer_frames = buffer_size/frame_size;
     tsched_frames = tsched_size/frame_size;
 
     if (pa_modargs_get_value_boolean(ma, "mmap", &use_mmap) < 0) {
@@ -1740,7 +1742,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
                       &u->device_name,
                       &ss, &map,
                       SND_PCM_STREAM_PLAYBACK,
-                      &nfrags, &period_frames, tsched_frames,
+                      &period_frames, &buffer_frames, tsched_frames,
                       &b, &d, mapping)))
 
             goto fail;
@@ -1755,7 +1757,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
                       &u->device_name,
                       &ss, &map,
                       SND_PCM_STREAM_PLAYBACK,
-                      &nfrags, &period_frames, tsched_frames,
+                      &period_frames, &buffer_frames, tsched_frames,
                       &b, &d, profile_set, &mapping)))
 
             goto fail;
@@ -1767,7 +1769,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
                       &u->device_name,
                       &ss, &map,
                       SND_PCM_STREAM_PLAYBACK,
-                      &nfrags, &period_frames, tsched_frames,
+                      &period_frames, &buffer_frames, tsched_frames,
                       &b, &d, FALSE)))
             goto fail;
     }
@@ -1819,7 +1821,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
 
     pa_alsa_init_proplist_pcm(m->core, data.proplist, u->pcm_handle);
     pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, u->device_name);
-    pa_proplist_setf(data.proplist, PA_PROP_DEVICE_BUFFERING_BUFFER_SIZE, "%lu", (unsigned long) (period_frames * frame_size * nfrags));
+    pa_proplist_setf(data.proplist, PA_PROP_DEVICE_BUFFERING_BUFFER_SIZE, "%lu", (unsigned long) (buffer_frames * frame_size));
     pa_proplist_setf(data.proplist, PA_PROP_DEVICE_BUFFERING_FRAGMENT_SIZE, "%lu", (unsigned long) (period_frames * frame_size));
     pa_proplist_sets(data.proplist, PA_PROP_DEVICE_ACCESS_MODE, u->use_tsched ? "mmap+timer" : (u->use_mmap ? "mmap" : "serial"));
 
@@ -1860,13 +1862,15 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
     pa_sink_set_rtpoll(u->sink, u->rtpoll);
 
     u->frame_size = frame_size;
-    u->fragment_size = frag_size = (uint32_t) (period_frames * frame_size);
-    u->nfragments = nfrags;
-    u->hwbuf_size = u->fragment_size * nfrags;
+    u->fragment_size = frag_size = (size_t) (period_frames * frame_size);
+    u->hwbuf_size = buffer_size = (size_t) (buffer_frames * frame_size);
     pa_cvolume_mute(&u->hardware_volume, u->sink->sample_spec.channels);
 
-    pa_log_info("Using %u fragments of size %lu bytes, buffer time is %0.2fms",
-                nfrags, (long unsigned) u->fragment_size,
+    pa_log_info("Using %0.1f fragments of size %lu bytes (%0.2fms), buffer size is %lu bytes (%0.2fms)",
+                (double) u->hwbuf_size / (double) u->fragment_size,
+                (long unsigned) u->fragment_size,
+                (double) pa_bytes_to_usec(u->fragment_size, &ss) / PA_USEC_PER_MSEC,
+                (long unsigned) u->hwbuf_size,
                 (double) pa_bytes_to_usec(u->hwbuf_size, &ss) / PA_USEC_PER_MSEC);
 
     pa_sink_set_max_request(u->sink, u->hwbuf_size);
diff --git a/src/modules/alsa/alsa-source.c b/src/modules/alsa/alsa-source.c
index 64f8980..5f89d88 100644
--- a/src/modules/alsa/alsa-source.c
+++ b/src/modules/alsa/alsa-source.c
@@ -111,8 +111,6 @@ struct userdata {
 
     pa_usec_t watermark_dec_not_before;
 
-    unsigned nfragments;
-
     char *device_name;
     char *control_device;
 
@@ -891,8 +889,7 @@ static int unsuspend(struct userdata *u) {
     pa_sample_spec ss;
     int err;
     pa_bool_t b, d;
-    unsigned nfrags;
-    snd_pcm_uframes_t period_size;
+    snd_pcm_uframes_t period_size, buffer_size;
 
     pa_assert(u);
     pa_assert(!u->pcm_handle);
@@ -909,12 +906,12 @@ static int unsuspend(struct userdata *u) {
     }
 
     ss = u->source->sample_spec;
-    nfrags = u->nfragments;
     period_size = u->fragment_size / u->frame_size;
+    buffer_size = u->hwbuf_size / u->frame_size;
     b = u->use_mmap;
     d = u->use_tsched;
 
-    if ((err = pa_alsa_set_hw_params(u->pcm_handle, &ss, &nfrags, &period_size, u->hwbuf_size / u->frame_size, &b, &d, TRUE)) < 0) {
+    if ((err = pa_alsa_set_hw_params(u->pcm_handle, &ss, &period_size, &buffer_size, 0, &b, &d, TRUE)) < 0) {
         pa_log("Failed to set hardware parameters: %s", pa_alsa_strerror(err));
         goto fail;
     }
@@ -929,10 +926,11 @@ static int unsuspend(struct userdata *u) {
         goto fail;
     }
 
-    if (nfrags != u->nfragments || period_size*u->frame_size != u->fragment_size) {
-        pa_log_warn("Resume failed, couldn't restore original fragment settings. (Old: %lu*%lu, New %lu*%lu)",
-                    (unsigned long) u->nfragments, (unsigned long) u->fragment_size,
-                    (unsigned long) nfrags, period_size * u->frame_size);
+    if (period_size*u->frame_size != u->fragment_size ||
+        buffer_size*u->frame_size != u->hwbuf_size) {
+        pa_log_warn("Resume failed, couldn't restore original fragment settings. (Old: %lu/%lu, New %lu/%lu)",
+                    (unsigned long) u->hwbuf_size, (unsigned long) u->fragment_size,
+                    (unsigned long) (buffer_size*u->fragment_size), (unsigned long) (period_size*u->frame_size));
         goto fail;
     }
 
@@ -1483,8 +1481,8 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
     const char *dev_id = NULL;
     pa_sample_spec ss, requested_ss;
     pa_channel_map map;
-    uint32_t nfrags, frag_size, tsched_size, tsched_watermark;
-    snd_pcm_uframes_t period_frames, tsched_frames;
+    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;
     pa_source_new_data data;
@@ -1518,7 +1516,10 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
         goto fail;
     }
 
+    buffer_size = nfrags * frag_size;
+
     period_frames = frag_size/frame_size;
+    buffer_frames = buffer_size/frame_size;
     tsched_frames = tsched_size/frame_size;
 
     if (pa_modargs_get_value_boolean(ma, "mmap", &use_mmap) < 0) {
@@ -1584,7 +1585,7 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
                       &u->device_name,
                       &ss, &map,
                       SND_PCM_STREAM_CAPTURE,
-                      &nfrags, &period_frames, tsched_frames,
+                      &period_frames, &buffer_frames, tsched_frames,
                       &b, &d, mapping)))
             goto fail;
 
@@ -1598,7 +1599,7 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
                       &u->device_name,
                       &ss, &map,
                       SND_PCM_STREAM_CAPTURE,
-                      &nfrags, &period_frames, tsched_frames,
+                      &period_frames, &buffer_frames, tsched_frames,
                       &b, &d, profile_set, &mapping)))
             goto fail;
 
@@ -1609,7 +1610,7 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
                       &u->device_name,
                       &ss, &map,
                       SND_PCM_STREAM_CAPTURE,
-                      &nfrags, &period_frames, tsched_frames,
+                      &period_frames, &buffer_frames, tsched_frames,
                       &b, &d, FALSE)))
             goto fail;
     }
@@ -1661,7 +1662,7 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
 
     pa_alsa_init_proplist_pcm(m->core, data.proplist, u->pcm_handle);
     pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, u->device_name);
-    pa_proplist_setf(data.proplist, PA_PROP_DEVICE_BUFFERING_BUFFER_SIZE, "%lu", (unsigned long) (period_frames * frame_size * nfrags));
+    pa_proplist_setf(data.proplist, PA_PROP_DEVICE_BUFFERING_BUFFER_SIZE, "%lu", (unsigned long) (buffer_frames * frame_size));
     pa_proplist_setf(data.proplist, PA_PROP_DEVICE_BUFFERING_FRAGMENT_SIZE, "%lu", (unsigned long) (period_frames * frame_size));
     pa_proplist_sets(data.proplist, PA_PROP_DEVICE_ACCESS_MODE, u->use_tsched ? "mmap+timer" : (u->use_mmap ? "mmap" : "serial"));
 
@@ -1702,13 +1703,15 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
     pa_source_set_rtpoll(u->source, u->rtpoll);
 
     u->frame_size = frame_size;
-    u->fragment_size = frag_size = (uint32_t) (period_frames * frame_size);
-    u->nfragments = nfrags;
-    u->hwbuf_size = u->fragment_size * nfrags;
+    u->fragment_size = frag_size = (size_t) (period_frames * frame_size);
+    u->hwbuf_size = buffer_size = (size_t) (buffer_frames * frame_size);
     pa_cvolume_mute(&u->hardware_volume, u->source->sample_spec.channels);
 
-    pa_log_info("Using %u fragments of size %lu bytes, buffer time is %0.2fms",
-                nfrags, (long unsigned) u->fragment_size,
+    pa_log_info("Using %0.1f fragments of size %lu bytes (%0.2fms), buffer size is %lu bytes (%0.2fms)",
+                (double) u->hwbuf_size / (double) u->fragment_size,
+                (long unsigned) u->fragment_size,
+                (double) pa_bytes_to_usec(u->fragment_size, &ss) / PA_USEC_PER_MSEC,
+                (long unsigned) u->hwbuf_size,
                 (double) pa_bytes_to_usec(u->hwbuf_size, &ss) / PA_USEC_PER_MSEC);
 
     if (u->use_tsched) {
diff --git a/src/modules/alsa/alsa-util.c b/src/modules/alsa/alsa-util.c
index 4d75c63..9147452 100644
--- a/src/modules/alsa/alsa-util.c
+++ b/src/modules/alsa/alsa-util.c
@@ -93,6 +93,7 @@ static int set_format(snd_pcm_t *pcm_handle, snd_pcm_hw_params_t *hwparams, pa_s
     int ret;
 
     pa_assert(pcm_handle);
+    pa_assert(hwparams);
     pa_assert(f);
 
     if ((ret = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format_trans[*f])) >= 0)
@@ -148,33 +149,71 @@ try_auto:
     return -1;
 }
 
+static int set_period_size(snd_pcm_t *pcm_handle, snd_pcm_hw_params_t *hwparams, snd_pcm_uframes_t size) {
+    snd_pcm_uframes_t s;
+    int d, ret;
+
+    pa_assert(pcm_handle);
+    pa_assert(hwparams);
+
+    s = size;
+    d = 0;
+    if (snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, &s, &d) < 0) {
+        s = size;
+        d = -1;
+        if (snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, &s, &d) < 0) {
+            s = size;
+            d = 1;
+            if ((ret = snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, &s, &d)) < 0) {
+                pa_log_info("snd_pcm_hw_params_set_period_size_near() failed: %s", pa_alsa_strerror(ret));
+                return ret;
+            }
+        }
+    }
+
+    return 0;
+}
+
+static int set_buffer_size(snd_pcm_t *pcm_handle, snd_pcm_hw_params_t *hwparams, snd_pcm_uframes_t size) {
+    int ret;
+
+    pa_assert(pcm_handle);
+    pa_assert(hwparams);
+
+    if ((ret = snd_pcm_hw_params_set_buffer_size_near(pcm_handle, hwparams, &size)) < 0) {
+        pa_log_info("snd_pcm_hw_params_set_buffer_size_near() failed: %s", pa_alsa_strerror(ret));
+        return ret;
+    }
+
+    return 0;
+}
+
 /* Set the hardware parameters of the given ALSA device. Returns the
  * selected fragment settings in *period and *period_size */
 int pa_alsa_set_hw_params(
         snd_pcm_t *pcm_handle,
         pa_sample_spec *ss,
-        uint32_t *periods,
         snd_pcm_uframes_t *period_size,
+        snd_pcm_uframes_t *buffer_size,
         snd_pcm_uframes_t tsched_size,
         pa_bool_t *use_mmap,
         pa_bool_t *use_tsched,
         pa_bool_t require_exact_channel_number) {
 
     int ret = -1;
+    snd_pcm_hw_params_t *hwparams, *hwparams_copy;
+    int dir;
     snd_pcm_uframes_t _period_size = period_size ? *period_size : 0;
-    unsigned int _periods = periods ? *periods : 0;
-    unsigned int r = ss->rate;
-    unsigned int c = ss->channels;
-    pa_sample_format_t f = ss->format;
-    snd_pcm_hw_params_t *hwparams;
+    snd_pcm_uframes_t _buffer_size = buffer_size ? *buffer_size : 0;
     pa_bool_t _use_mmap = use_mmap && *use_mmap;
     pa_bool_t _use_tsched = use_tsched && *use_tsched;
-    int dir;
+    pa_sample_spec _ss = *ss;
 
     pa_assert(pcm_handle);
     pa_assert(ss);
 
     snd_pcm_hw_params_alloca(&hwparams);
+    snd_pcm_hw_params_alloca(&hwparams_copy);
 
     if ((ret = snd_pcm_hw_params_any(pcm_handle, hwparams)) < 0) {
         pa_log_debug("snd_pcm_hw_params_any() failed: %s", pa_alsa_strerror(ret));
@@ -208,114 +247,140 @@ int pa_alsa_set_hw_params(
     if (!_use_mmap)
         _use_tsched = FALSE;
 
-    if ((ret = set_format(pcm_handle, hwparams, &f)) < 0)
+    if ((ret = set_format(pcm_handle, hwparams, &_ss.format)) < 0)
         goto finish;
 
-    if ((ret = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &r, NULL)) < 0) {
+    if ((ret = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &_ss.rate, NULL)) < 0) {
         pa_log_debug("snd_pcm_hw_params_set_rate_near() failed: %s", pa_alsa_strerror(ret));
         goto finish;
     }
 
     if (require_exact_channel_number) {
-        if ((ret = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, c)) < 0) {
-            pa_log_debug("snd_pcm_hw_params_set_channels(%u) failed: %s", c, pa_alsa_strerror(ret));
+        if ((ret = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, _ss.channels)) < 0) {
+            pa_log_debug("snd_pcm_hw_params_set_channels(%u) failed: %s", _ss.channels, pa_alsa_strerror(ret));
             goto finish;
         }
     } else {
+        unsigned int c = _ss.channels;
+
         if ((ret = snd_pcm_hw_params_set_channels_near(pcm_handle, hwparams, &c)) < 0) {
-            pa_log_debug("snd_pcm_hw_params_set_channels_near(%u) failed: %s", c, pa_alsa_strerror(ret));
+            pa_log_debug("snd_pcm_hw_params_set_channels_near(%u) failed: %s", _ss.channels, pa_alsa_strerror(ret));
             goto finish;
         }
-    }
 
-    if ((ret = snd_pcm_hw_params_set_periods_integer(pcm_handle, hwparams)) < 0) {
-        pa_log_debug("snd_pcm_hw_params_set_periods_integer() failed: %s", pa_alsa_strerror(ret));
-        goto finish;
+        _ss.channels = c;
     }
 
-    if (_period_size > 0 && tsched_size > 0 && _periods > 0) {
-        snd_pcm_uframes_t buffer_size;
-        unsigned int p;
+    if (_use_tsched && tsched_size > 0) {
+        _buffer_size = pa_convert_size(tsched_size, ss, &_ss);
+        _period_size = _buffer_size;
+    } else {
+        _period_size = pa_convert_size(_period_size, ss, &_ss);
+        _buffer_size = pa_convert_size(_buffer_size, ss, &_ss);
+    }
 
-        /* Adjust the buffer sizes, if we didn't get the rate we were asking for */
-        _period_size = (snd_pcm_uframes_t) (((uint64_t) _period_size * r) / ss->rate);
-        tsched_size = (snd_pcm_uframes_t) (((uint64_t) tsched_size * r) / ss->rate);
+    if (_buffer_size > 0 || _period_size > 0) {
+        snd_pcm_uframes_t max_frames = 0;
 
-        if (_use_tsched) {
-            buffer_size = 0;
+        if ((ret = snd_pcm_hw_params_get_buffer_size_max(hwparams, &max_frames)) < 0)
+            pa_log_warn("snd_pcm_hw_params_get_buffer_size_max() failed: %s", pa_alsa_strerror(ret));
+        else
+            pa_log_debug("Maximum hw buffer size is %lu ms", (long unsigned) max_frames * PA_MSEC_PER_SEC / _ss.rate);
 
-            if ((ret = snd_pcm_hw_params_get_buffer_size_max(hwparams, &buffer_size)) < 0)
-                pa_log_warn("snd_pcm_hw_params_get_buffer_size_max() failed: %s", pa_alsa_strerror(ret));
-            else
-                pa_log_debug("Maximum hw buffer size is %u ms", (unsigned) buffer_size * 1000 / r);
+        /* Some ALSA drivers really don't like if we set the buffer
+         * size first and the number of periods second. (which would
+         * make a lot more sense to me) So, try a few combinations
+         * before we give up. */
+
+        if (_buffer_size > 0 && _period_size > 0) {
+            snd_pcm_hw_params_copy(hwparams_copy, hwparams);
+
+            /* First try: set buffer size first, followed by period size */
+            if (set_buffer_size(pcm_handle, hwparams_copy, _buffer_size) >= 0 &&
+                set_period_size(pcm_handle, hwparams_copy, _period_size) >= 0 &&
+                snd_pcm_hw_params(pcm_handle, hwparams_copy) >= 0) {
+                pa_log_debug("Set buffer size first, period size second.");
+                goto success;
+            }
 
-            _period_size = tsched_size;
-            _periods = 1;
+            /* Second try: set period size first, followed by buffer size */
+            if (set_period_size(pcm_handle, hwparams_copy, _period_size) >= 0 &&
+                set_buffer_size(pcm_handle, hwparams_copy, _buffer_size) >= 0 &&
+                snd_pcm_hw_params(pcm_handle, hwparams_copy) >= 0) {
+                pa_log_debug("Set period size first, buffer size second.");
+                goto success;
+            }
         }
 
-        /* Some ALSA drivers really don't like if we set the buffer
-         * size first and the number of periods second. (which would
-         * make a lot more sense to me) So, follow this rule and
-         * adjust the periods first and the buffer size second */
-
-        /* First we pass 0 as direction to get exactly what we
-         * asked for. That this is necessary is presumably a bug
-         * in ALSA. All in all this is mostly a hint to ALSA, so
-         * we don't care if this fails. */
-
-        p = _periods;
-        dir = 0;
-        if (snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, &p, &dir) < 0) {
-            p = _periods;
-            dir = 1;
-            if (snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, &p, &dir) < 0) {
-                p = _periods;
-                dir = -1;
-                if ((ret = snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, &p, &dir)) < 0)
-                    pa_log_info("snd_pcm_hw_params_set_periods_near() failed: %s", pa_alsa_strerror(ret));
+        if (_buffer_size > 0) {
+            snd_pcm_hw_params_copy(hwparams_copy, hwparams);
+
+            /* Third try: set only buffer size */
+            if (set_buffer_size(pcm_handle, hwparams_copy, _buffer_size) >= 0 &&
+                snd_pcm_hw_params(pcm_handle, hwparams_copy) >= 0) {
+                pa_log_debug("Set only buffer size second.");
+                goto success;
             }
         }
 
-        /* Now set the buffer size */
-        buffer_size = _periods * _period_size;
-        if ((ret = snd_pcm_hw_params_set_buffer_size_near(pcm_handle, hwparams, &buffer_size)) < 0)
-            pa_log_info("snd_pcm_hw_params_set_buffer_size_near() failed: %s", pa_alsa_strerror(ret));
+        if (_period_size > 0) {
+            snd_pcm_hw_params_copy(hwparams_copy, hwparams);
+
+            /* Fourth try: set only period size */
+            if (set_period_size(pcm_handle, hwparams_copy, _period_size) >= 0 &&
+                snd_pcm_hw_params(pcm_handle, hwparams_copy) >= 0) {
+                pa_log_debug("Set only period size second.");
+                goto success;
+            }
+        }
     }
 
-    if  ((ret = snd_pcm_hw_params(pcm_handle, hwparams)) < 0)
+    pa_log_debug("Set neither period nor buffer size.");
+
+    /* Last chance, set nothing */
+    if  ((ret = snd_pcm_hw_params(pcm_handle, hwparams)) < 0) {
+        pa_log_info("snd_pcm_hw_params failed: %s", pa_alsa_strerror(ret));
         goto finish;
+    }
+
+success:
 
-    if (ss->rate != r)
-        pa_log_info("Device %s doesn't support %u Hz, changed to %u Hz.", snd_pcm_name(pcm_handle), ss->rate, r);
+    if (ss->rate != _ss.rate)
+        pa_log_info("Device %s doesn't support %u Hz, changed to %u Hz.", snd_pcm_name(pcm_handle), ss->rate, _ss.rate);
 
-    if (ss->channels != c)
-        pa_log_info("Device %s doesn't support %u channels, changed to %u.", snd_pcm_name(pcm_handle), ss->channels, c);
+    if (ss->channels != _ss.channels)
+        pa_log_info("Device %s doesn't support %u channels, changed to %u.", snd_pcm_name(pcm_handle), ss->channels, _ss.channels);
 
-    if (ss->format != f)
-        pa_log_info("Device %s doesn't support sample format %s, changed to %s.", snd_pcm_name(pcm_handle), pa_sample_format_to_string(ss->format), pa_sample_format_to_string(f));
+    if (ss->format != _ss.format)
+        pa_log_info("Device %s doesn't support sample format %s, changed to %s.", snd_pcm_name(pcm_handle), pa_sample_format_to_string(ss->format), pa_sample_format_to_string(_ss.format));
 
     if ((ret = snd_pcm_prepare(pcm_handle)) < 0) {
         pa_log_info("snd_pcm_prepare() failed: %s", pa_alsa_strerror(ret));
         goto finish;
     }
 
+    if ((ret = snd_pcm_hw_params_current(pcm_handle, hwparams)) < 0) {
+        pa_log_info("snd_pcm_hw_params_current() failed: %s", pa_alsa_strerror(ret));
+        goto finish;
+    }
+
     if ((ret = snd_pcm_hw_params_get_period_size(hwparams, &_period_size, &dir)) < 0 ||
-        (ret = snd_pcm_hw_params_get_periods(hwparams, &_periods, &dir)) < 0) {
-        pa_log_info("snd_pcm_hw_params_get_period{s|_size}() failed: %s", pa_alsa_strerror(ret));
+        (ret = snd_pcm_hw_params_get_buffer_size(hwparams, &_buffer_size)) < 0) {
+        pa_log_info("snd_pcm_hw_params_get_{period|buffer}_size() failed: %s", pa_alsa_strerror(ret));
         goto finish;
     }
 
     /* If the sample rate deviates too much, we need to resample */
-    if (r < ss->rate*.95 || r > ss->rate*1.05)
-        ss->rate = r;
-    ss->channels = (uint8_t) c;
-    ss->format = f;
+    if (_ss.rate < ss->rate*.95 || _ss.rate > ss->rate*1.05)
+        ss->rate = _ss.rate;
+    ss->channels = _ss.channels;
+    ss->format = _ss.format;
 
-    pa_assert(_periods > 0);
     pa_assert(_period_size > 0);
+    pa_assert(_buffer_size > 0);
 
-    if (periods)
-        *periods = _periods;
+    if (buffer_size)
+        *buffer_size = _buffer_size;
 
     if (period_size)
         *period_size = _period_size;
@@ -393,8 +458,8 @@ snd_pcm_t *pa_alsa_open_by_device_id_auto(
         pa_sample_spec *ss,
         pa_channel_map* map,
         int mode,
-        uint32_t *nfrags,
         snd_pcm_uframes_t *period_size,
+        snd_pcm_uframes_t *buffer_size,
         snd_pcm_uframes_t tsched_size,
         pa_bool_t *use_mmap,
         pa_bool_t *use_tsched,
@@ -410,8 +475,6 @@ snd_pcm_t *pa_alsa_open_by_device_id_auto(
     pa_assert(dev);
     pa_assert(ss);
     pa_assert(map);
-    pa_assert(nfrags);
-    pa_assert(period_size);
     pa_assert(ps);
 
     /* First we try to find a device string with a superset of the
@@ -433,8 +496,8 @@ snd_pcm_t *pa_alsa_open_by_device_id_auto(
                 ss,
                 map,
                 mode,
-                nfrags,
                 period_size,
+                buffer_size,
                 tsched_size,
                 use_mmap,
                 use_tsched,
@@ -460,8 +523,8 @@ snd_pcm_t *pa_alsa_open_by_device_id_auto(
                 ss,
                 map,
                 mode,
-                nfrags,
                 period_size,
+                buffer_size,
                 tsched_size,
                 use_mmap,
                 use_tsched,
@@ -478,7 +541,18 @@ snd_pcm_t *pa_alsa_open_by_device_id_auto(
     /* OK, we didn't find any good device, so let's try the raw hw: stuff */
     d = pa_sprintf_malloc("hw:%s", dev_id);
     pa_log_debug("Trying %s as last resort...", d);
-    pcm_handle = pa_alsa_open_by_device_string(d, dev, ss, map, mode, nfrags, period_size, tsched_size, use_mmap, use_tsched, FALSE);
+    pcm_handle = pa_alsa_open_by_device_string(
+            d,
+            dev,
+            ss,
+            map,
+            mode,
+            period_size,
+            buffer_size,
+            tsched_size,
+            use_mmap,
+            use_tsched,
+            FALSE);
     pa_xfree(d);
 
     if (pcm_handle && mapping)
@@ -493,8 +567,8 @@ snd_pcm_t *pa_alsa_open_by_device_id_mapping(
         pa_sample_spec *ss,
         pa_channel_map* map,
         int mode,
-        uint32_t *nfrags,
         snd_pcm_uframes_t *period_size,
+        snd_pcm_uframes_t *buffer_size,
         snd_pcm_uframes_t tsched_size,
         pa_bool_t *use_mmap,
         pa_bool_t *use_tsched,
@@ -508,8 +582,6 @@ snd_pcm_t *pa_alsa_open_by_device_id_mapping(
     pa_assert(dev);
     pa_assert(ss);
     pa_assert(map);
-    pa_assert(nfrags);
-    pa_assert(period_size);
     pa_assert(m);
 
     try_ss.channels = m->channel_map.channels;
@@ -524,8 +596,8 @@ snd_pcm_t *pa_alsa_open_by_device_id_mapping(
             &try_ss,
             &try_map,
             mode,
-            nfrags,
             period_size,
+            buffer_size,
             tsched_size,
             use_mmap,
             use_tsched,
@@ -547,8 +619,8 @@ snd_pcm_t *pa_alsa_open_by_device_string(
         pa_sample_spec *ss,
         pa_channel_map* map,
         int mode,
-        uint32_t *nfrags,
         snd_pcm_uframes_t *period_size,
+        snd_pcm_uframes_t *buffer_size,
         snd_pcm_uframes_t tsched_size,
         pa_bool_t *use_mmap,
         pa_bool_t *use_tsched,
@@ -579,7 +651,15 @@ snd_pcm_t *pa_alsa_open_by_device_string(
 
         pa_log_debug("Managed to open %s", d);
 
-        if ((err = pa_alsa_set_hw_params(pcm_handle, ss, nfrags, period_size, tsched_size, use_mmap, use_tsched, require_exact_channel_number)) < 0) {
+        if ((err = pa_alsa_set_hw_params(
+                     pcm_handle,
+                     ss,
+                     period_size,
+                     buffer_size,
+                     tsched_size,
+                     use_mmap,
+                     use_tsched,
+                     require_exact_channel_number)) < 0) {
 
             if (!reformat) {
                 reformat = TRUE;
@@ -632,8 +712,8 @@ snd_pcm_t *pa_alsa_open_by_template(
         pa_sample_spec *ss,
         pa_channel_map* map,
         int mode,
-        uint32_t *nfrags,
         snd_pcm_uframes_t *period_size,
+        snd_pcm_uframes_t *buffer_size,
         snd_pcm_uframes_t tsched_size,
         pa_bool_t *use_mmap,
         pa_bool_t *use_tsched,
@@ -653,8 +733,8 @@ snd_pcm_t *pa_alsa_open_by_template(
                 ss,
                 map,
                 mode,
-                nfrags,
                 period_size,
+                buffer_size,
                 tsched_size,
                 use_mmap,
                 use_tsched,
diff --git a/src/modules/alsa/alsa-util.h b/src/modules/alsa/alsa-util.h
index 830a922..265cd28 100644
--- a/src/modules/alsa/alsa-util.h
+++ b/src/modules/alsa/alsa-util.h
@@ -42,8 +42,8 @@
 int pa_alsa_set_hw_params(
         snd_pcm_t *pcm_handle,
         pa_sample_spec *ss,                /* modified at return */
-        uint32_t *periods,                 /* modified at return */
         snd_pcm_uframes_t *period_size,    /* modified at return */
+        snd_pcm_uframes_t *buffer_size,    /* modified at return */
         snd_pcm_uframes_t tsched_size,
         pa_bool_t *use_mmap,               /* modified at return */
         pa_bool_t *use_tsched,             /* modified at return */
@@ -60,8 +60,8 @@ snd_pcm_t *pa_alsa_open_by_device_id_auto(
         pa_sample_spec *ss,               /* modified at return */
         pa_channel_map* map,              /* modified at return */
         int mode,
-        uint32_t *nfrags,                 /* modified at return */
         snd_pcm_uframes_t *period_size,   /* modified at return */
+        snd_pcm_uframes_t *buffer_size,   /* modified at return */
         snd_pcm_uframes_t tsched_size,
         pa_bool_t *use_mmap,              /* modified at return */
         pa_bool_t *use_tsched,            /* modified at return */
@@ -75,8 +75,8 @@ snd_pcm_t *pa_alsa_open_by_device_id_mapping(
         pa_sample_spec *ss,               /* modified at return */
         pa_channel_map* map,              /* modified at return */
         int mode,
-        uint32_t *nfrags,                 /* modified at return */
         snd_pcm_uframes_t *period_size,   /* modified at return */
+        snd_pcm_uframes_t *buffer_size,   /* modified at return */
         snd_pcm_uframes_t tsched_size,
         pa_bool_t *use_mmap,              /* modified at return */
         pa_bool_t *use_tsched,            /* modified at return */
@@ -89,8 +89,8 @@ snd_pcm_t *pa_alsa_open_by_device_string(
         pa_sample_spec *ss,               /* modified at return */
         pa_channel_map* map,              /* modified at return */
         int mode,
-        uint32_t *nfrags,                 /* modified at return */
         snd_pcm_uframes_t *period_size,   /* modified at return */
+        snd_pcm_uframes_t *buffer_size,   /* modified at return */
         snd_pcm_uframes_t tsched_size,
         pa_bool_t *use_mmap,              /* modified at return */
         pa_bool_t *use_tsched,            /* modified at return */
@@ -104,8 +104,8 @@ snd_pcm_t *pa_alsa_open_by_template(
         pa_sample_spec *ss,               /* modified at return */
         pa_channel_map* map,              /* modified at return */
         int mode,
-        uint32_t *nfrags,                 /* modified at return */
         snd_pcm_uframes_t *period_size,   /* modified at return */
+        snd_pcm_uframes_t *buffer_size,   /* modified at return */
         snd_pcm_uframes_t tsched_size,
         pa_bool_t *use_mmap,              /* modified at return */
         pa_bool_t *use_tsched,            /* modified at return */

-- 
hooks/post-receive
PulseAudio Sound Server



More information about the pulseaudio-commits mailing list