[pulseaudio-commits] 7 commits - src/modules src/pulsecore

Tanu Kaskinen tanuk at kemper.freedesktop.org
Tue Oct 30 07:39:29 PDT 2012


 src/modules/module-combine-sink.c          |    8 +++-----
 src/modules/module-loopback.c              |   14 +++++---------
 src/modules/module-match.c                 |   10 +++++-----
 src/modules/module-virtual-surround-sink.c |    4 ++--
 src/pulsecore/memblockq.c                  |    2 +-
 src/pulsecore/memblockq.h                  |    4 ++--
 src/pulsecore/resampler.c                  |   12 ++++++------
 7 files changed, 24 insertions(+), 30 deletions(-)

New commits:
commit 0a8634f03e64a84f594bc8533235998e969eda66
Author: Tanu Kaskinen <tanuk at iki.fi>
Date:   Thu Sep 27 16:41:59 2012 +0300

    match: Use the SINK_INPUT_FIXATE hook instead of NEW.
    
    The callback relies on the sample spec being finalized, which is not
    true with the NEW hook.
    
    In case you're wondering about the "hook EARLY - 1, to match before
    stream-restore" comment that was not changed even though the code that
    the comment concerned was changed: the comment was apparently written
    at a time when module-stream-restore used the NEW hook too, and later
    stream-restore has been changed to use the FIXATE hook. So, the
    comment was wrong/nonsensical before this patch. Since these two
    modules now use the same hook again, the comment makes sense again.
    
    BugLink: https://bugs.freedesktop.org/show_bug.cgi?id=55135

diff --git a/src/modules/module-match.c b/src/modules/module-match.c
index c94ef79..e42f44e 100644
--- a/src/modules/module-match.c
+++ b/src/modules/module-match.c
@@ -80,7 +80,7 @@ struct rule {
 struct userdata {
     struct rule *rules;
     char *property_key;
-    pa_hook_slot *sink_input_new_hook_slot;
+    pa_hook_slot *sink_input_fixate_hook_slot;
 };
 
 static int load_rules(struct userdata *u, const char *filename) {
@@ -213,7 +213,7 @@ finish:
     return ret;
 }
 
-static pa_hook_result_t sink_input_new_hook_callback(pa_core *c, pa_sink_input_new_data *si, struct userdata *u) {
+static pa_hook_result_t sink_input_fixate_hook_callback(pa_core *c, pa_sink_input_new_data *si, struct userdata *u) {
     struct rule *r;
     const char *n;
 
@@ -264,7 +264,7 @@ int pa__init(pa_module*m) {
         goto fail;
 
     /* hook EARLY - 1, to match before stream-restore */
-    u->sink_input_new_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_NEW], PA_HOOK_EARLY - 1, (pa_hook_cb_t) sink_input_new_hook_callback, u);
+    u->sink_input_fixate_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_FIXATE], PA_HOOK_EARLY - 1, (pa_hook_cb_t) sink_input_fixate_hook_callback, u);
 
     pa_modargs_free(ma);
     return 0;
@@ -286,8 +286,8 @@ void pa__done(pa_module*m) {
     if (!(u = m->userdata))
         return;
 
-    if (u->sink_input_new_hook_slot)
-        pa_hook_slot_free(u->sink_input_new_hook_slot);
+    if (u->sink_input_fixate_hook_slot)
+        pa_hook_slot_free(u->sink_input_fixate_hook_slot);
 
     if (u->property_key)
         pa_xfree(u->property_key);

commit 0da87df4ec0e568a54f4560814e31dfdec4c5b50
Author: Tanu Kaskinen <tanuk at iki.fi>
Date:   Thu Sep 20 09:42:18 2012 +0300

    combine: Keep the timer active in the null mode only when running.
    
    Previously thread_func() used PA_SINK_IS_OPENED() to check whether
    some data should be rendered. process_render_null() used a different
    check: it would return immediately if the sink was not in the RUNNING
    state. This caused a busy loop when the sink was in the IDLE state,
    because process_render_null() didn't update the timestamp, and
    thread_func() still kept the timer active using the old timestamp.
    pa_rtpoll_run() would return immediately because of the old timestamp.
    
    This is fixed by using the same check in both thread_func() and
    process_render_null(). Since the checks are the same, it's actually
    redundant to have the check in process_render_null(), so it is now an
    assertion.
    
    BugLink: https://bugs.freedesktop.org/show_bug.cgi?id=54779

diff --git a/src/modules/module-combine-sink.c b/src/modules/module-combine-sink.c
index dec2279..1afdc12 100644
--- a/src/modules/module-combine-sink.c
+++ b/src/modules/module-combine-sink.c
@@ -257,11 +257,9 @@ static void time_callback(pa_mainloop_api *a, pa_time_event *e, const struct tim
 
 static void process_render_null(struct userdata *u, pa_usec_t now) {
     size_t ate = 0;
-    pa_assert(u);
 
-    /* If we are not running, we cannot produce any data */
-    if (!pa_atomic_load(&u->thread_info.running))
-        return;
+    pa_assert(u);
+    pa_assert(u->sink->thread_info.state == PA_SINK_RUNNING);
 
     if (u->thread_info.in_null_mode)
         u->thread_info.timestamp = now;
@@ -312,7 +310,7 @@ static void thread_func(void *userdata) {
                 pa_sink_process_rewind(u->sink, 0);
 
         /* If no outputs are connected, render some data and drop it immediately. */
-        if (PA_SINK_IS_OPENED(u->sink->thread_info.state) && !u->thread_info.active_outputs) {
+        if (u->sink->thread_info.state == PA_SINK_RUNNING && !u->thread_info.active_outputs) {
             pa_usec_t now;
 
             now = pa_rtclock_now();

commit 3adbb5ad034684ff751def0144764be8442fb15c
Author: Tanu Kaskinen <tanuk at iki.fi>
Date:   Wed Aug 22 09:00:25 2012 +0300

    virtual-surround-sink: Fix setting max_request and max_rewind.
    
    The sink has different frame size than the sink input, so
    the max_request and max_rewind values of the sink input need
    to be converted when setting the sink max_request and
    max_rewind values.
    
    The conversion is already done correctly in
    sink_input_update_max_request_cb() and
    sink_input_update_max_rewind_cb().

diff --git a/src/modules/module-virtual-surround-sink.c b/src/modules/module-virtual-surround-sink.c
index e5c5dc1..4915278 100644
--- a/src/modules/module-virtual-surround-sink.c
+++ b/src/modules/module-virtual-surround-sink.c
@@ -382,11 +382,11 @@ static void sink_input_attach_cb(pa_sink_input *i) {
 
     pa_sink_set_fixed_latency_within_thread(u->sink, i->sink->thread_info.fixed_latency);
 
-    pa_sink_set_max_request_within_thread(u->sink, pa_sink_input_get_max_request(i));
+    pa_sink_set_max_request_within_thread(u->sink, pa_sink_input_get_max_request(i) * u->sink_fs / u->fs);
 
     /* FIXME: Too small max_rewind:
      * https://bugs.freedesktop.org/show_bug.cgi?id=53709 */
-    pa_sink_set_max_rewind_within_thread(u->sink, pa_sink_input_get_max_rewind(i));
+    pa_sink_set_max_rewind_within_thread(u->sink, pa_sink_input_get_max_rewind(i) * u->sink_fs / u->fs);
 
     pa_sink_attach_within_thread(u->sink);
 }

commit 1fc2cf8425eff768e117bb4eff659204fdaf81dc
Author: Tanu Kaskinen <tanu.kaskinen at digia.com>
Date:   Tue Aug 14 17:08:35 2012 +0300

    loopback: Don't fix the source output format/rate/channels.
    
    Once the sink input has been routed in pa_sink_input_new(),
    the sample spec and channel map have already become fixed.
    The sink input and source output must use the same stream
    format, because the data is copied as-is.

diff --git a/src/modules/module-loopback.c b/src/modules/module-loopback.c
index d80494a..461c4a7 100644
--- a/src/modules/module-loopback.c
+++ b/src/modules/module-loopback.c
@@ -887,15 +887,6 @@ int pa__init(pa_module *m) {
     if (!remix)
         source_output_data.flags |= PA_SOURCE_OUTPUT_NO_REMIX;
 
-    if (!format_set)
-        source_output_data.flags |= PA_SOURCE_OUTPUT_FIX_FORMAT;
-
-    if (!rate_set)
-        source_output_data.flags |= PA_SOURCE_OUTPUT_FIX_RATE;
-
-    if (!channels_set)
-        source_output_data.flags |= PA_SOURCE_OUTPUT_FIX_CHANNELS;
-
     source_dont_move = FALSE;
     if (pa_modargs_get_value_boolean(ma, "source_dont_move", &source_dont_move) < 0) {
         pa_log("source_dont_move= expects a boolean argument.");

commit a68652a42c14e6d2136601d4a34ad1a2e7336e92
Author: Tanu Kaskinen <tanu.kaskinen at digia.com>
Date:   Tue Aug 14 17:08:34 2012 +0300

    loopback: Use the real sample spec once it's known.
    
    When module-loopback is loaded without arguments, the ss and
    map variables are initialized with dummy values. This caused
    a problem, because also pa_memblockq_new() was called with
    the dummy values, making it work incorrectly. The base was
    set to 1 instead of the real frame size, which in turn
    caused alignment related crashes.

diff --git a/src/modules/module-loopback.c b/src/modules/module-loopback.c
index 26d2e6a..d80494a 100644
--- a/src/modules/module-loopback.c
+++ b/src/modules/module-loopback.c
@@ -845,6 +845,11 @@ int pa__init(pa_module *m) {
     if (!u->sink_input)
         goto fail;
 
+    /* If format, rate or channels were originally unset, they are set now
+     * after the pa_sink_input_new() call. */
+    ss = u->sink_input->sample_spec;
+    map = u->sink_input->channel_map;
+
     u->sink_input->parent.process_msg = sink_input_process_msg_cb;
     u->sink_input->pop = sink_input_pop_cb;
     u->sink_input->process_rewind = sink_input_process_rewind_cb;

commit e4adf9c4d8a33509828b9b7658d4cccc7f5af563
Author: Tanu Kaskinen <tanuk at iki.fi>
Date:   Mon Jul 9 10:07:05 2012 +0300

    resampler: Make sure that there are no overflows when multiplying potentially big numbers.
    
    This fixes at least one crash that has been observed. The
    multiplication in trivial_resample() overflowed when
    resampling from 96 kHz to 48 kHz, causing an assertion
    error:
    
    Assertion 'o_index * fz < pa_memblock_get_length(output->memblock)' failed at pulsecore/resampler.c:1521, function trivial_resample(). Aborting.
    
    Without the assertion, the memcpy() after the assertion
    would have overwritten some random heap memory.

diff --git a/src/pulsecore/resampler.c b/src/pulsecore/resampler.c
index 17f1783..38c5202 100644
--- a/src/pulsecore/resampler.c
+++ b/src/pulsecore/resampler.c
@@ -389,7 +389,7 @@ size_t pa_resampler_request(pa_resampler *r, size_t out_length) {
      * loops. When the leftover is ignored here, such loops would eventually
      * terminate, because the leftover would grow each round, finally
      * surpassing the minimum input threshold of the resampler. */
-    return (((((out_length + r->o_fz-1) / r->o_fz) * r->i_ss.rate) + r->o_ss.rate-1) / r->o_ss.rate) * r->i_fz;
+    return ((((uint64_t) ((out_length + r->o_fz-1) / r->o_fz) * r->i_ss.rate) + r->o_ss.rate-1) / r->o_ss.rate) * r->i_fz;
 }
 
 size_t pa_resampler_result(pa_resampler *r, size_t in_length) {
@@ -405,7 +405,7 @@ size_t pa_resampler_result(pa_resampler *r, size_t in_length) {
     if (r->remap_buf_contains_leftover_data)
         frames += r->remap_buf.length / (r->w_sz * r->o_ss.channels);
 
-    return ((frames * r->o_ss.rate + r->i_ss.rate - 1) / r->i_ss.rate) * r->o_fz;
+    return (((uint64_t) frames * r->o_ss.rate + r->i_ss.rate - 1) / r->i_ss.rate) * r->o_fz;
 }
 
 size_t pa_resampler_max_block_size(pa_resampler *r) {
@@ -434,7 +434,7 @@ size_t pa_resampler_max_block_size(pa_resampler *r) {
     if (r->remap_buf_contains_leftover_data)
         frames -= r->remap_buf.length / (r->w_sz * r->o_ss.channels);
 
-    return (frames * r->i_ss.rate / max_ss.rate) * r->i_fz;
+    return ((uint64_t) frames * r->i_ss.rate / max_ss.rate) * r->i_fz;
 }
 
 void pa_resampler_reset(pa_resampler *r) {
@@ -1519,7 +1519,7 @@ static void trivial_resample(pa_resampler *r, const pa_memchunk *input, unsigned
     dst = pa_memblock_acquire_chunk(output);
 
     for (o_index = 0;; o_index++, r->trivial.o_counter++) {
-        i_index = (r->trivial.o_counter * r->i_ss.rate) / r->o_ss.rate;
+        i_index = ((uint64_t) r->trivial.o_counter * r->i_ss.rate) / r->o_ss.rate;
         i_index = i_index > r->trivial.i_counter ? i_index - r->trivial.i_counter : 0;
 
         if (i_index >= in_n_frames)
@@ -1580,11 +1580,11 @@ static void peaks_resample(pa_resampler *r, const pa_memchunk *input, unsigned i
     src = pa_memblock_acquire_chunk(input);
     dst = pa_memblock_acquire_chunk(output);
 
-    i = (r->peaks.o_counter * r->i_ss.rate) / r->o_ss.rate;
+    i = ((uint64_t) r->peaks.o_counter * r->i_ss.rate) / r->o_ss.rate;
     i = i > r->peaks.i_counter ? i - r->peaks.i_counter : 0;
 
     while (i_end < in_n_frames) {
-        i_end = ((r->peaks.o_counter+1) * r->i_ss.rate) / r->o_ss.rate;
+        i_end = ((uint64_t) (r->peaks.o_counter + 1) * r->i_ss.rate) / r->o_ss.rate;
         i_end = i_end > r->peaks.i_counter ? i_end - r->peaks.i_counter : 0;
 
         pa_assert_fp(o_index * r->w_sz * r->o_ss.channels < pa_memblock_get_length(output->memblock));

commit 9bcb9f1a62bf25a24b97fc34aef55eca10202344
Author: Tanu Kaskinen <tanuk at iki.fi>
Date:   Sat Apr 28 18:54:11 2012 +0300

    memblockq: Fix the order of setting minreq and prebuf.

diff --git a/src/pulsecore/memblockq.c b/src/pulsecore/memblockq.c
index 18066f7..23bb772 100644
--- a/src/pulsecore/memblockq.c
+++ b/src/pulsecore/memblockq.c
@@ -936,8 +936,8 @@ void pa_memblockq_apply_attr(pa_memblockq *bq, const pa_buffer_attr *a) {
 
     pa_memblockq_set_maxlength(bq, a->maxlength);
     pa_memblockq_set_tlength(bq, a->tlength);
-    pa_memblockq_set_prebuf(bq, a->prebuf);
     pa_memblockq_set_minreq(bq, a->minreq);
+    pa_memblockq_set_prebuf(bq, a->prebuf);
 }
 
 void pa_memblockq_get_attr(pa_memblockq *bq, pa_buffer_attr *a) {
diff --git a/src/pulsecore/memblockq.h b/src/pulsecore/memblockq.h
index 08c0bf0..83a5415 100644
--- a/src/pulsecore/memblockq.h
+++ b/src/pulsecore/memblockq.h
@@ -164,8 +164,8 @@ int64_t pa_memblockq_get_write_index(pa_memblockq *bq);
 /* Change metrics. Always call in order. */
 void pa_memblockq_set_maxlength(pa_memblockq *memblockq, size_t maxlength); /* might modify tlength, prebuf, minreq too */
 void pa_memblockq_set_tlength(pa_memblockq *memblockq, size_t tlength); /* might modify minreq, too */
-void pa_memblockq_set_prebuf(pa_memblockq *memblockq, size_t prebuf); /* might modify minreq, too */
-void pa_memblockq_set_minreq(pa_memblockq *memblockq, size_t minreq);
+void pa_memblockq_set_minreq(pa_memblockq *memblockq, size_t minreq); /* might modify prebuf, too */
+void pa_memblockq_set_prebuf(pa_memblockq *memblockq, size_t prebuf);
 void pa_memblockq_set_maxrewind(pa_memblockq *memblockq, size_t maxrewind); /* Set the maximum history size */
 void pa_memblockq_set_silence(pa_memblockq *memblockq, pa_memchunk *silence);
 



More information about the pulseaudio-commits mailing list