summaryrefslogtreecommitdiffstats
path: root/src/pulsecore/sink.c
diff options
context:
space:
mode:
authorJyri Sarha <jyri.sarha@nokia.com>2009-05-07 19:55:56 +0300
committerLennart Poettering <lennart@poettering.net>2009-05-08 23:59:16 +0200
commitd7b8947a5e428857ff96f5deead3dea180f69130 (patch)
tree8273a692c55822bea748697daf9570d71891bf6f /src/pulsecore/sink.c
parenta714861cc1fa2e06c5f5509880fcbfbc334c2812 (diff)
core: optimize pa_sink_render_full()
I have used this fix for quite a while and I am pretty confident about it. However, the performance gain was not what I expected.
Diffstat (limited to 'src/pulsecore/sink.c')
-rw-r--r--src/pulsecore/sink.c78
1 files changed, 73 insertions, 5 deletions
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 67bdbb68..a7e95293 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -932,22 +932,90 @@ void pa_sink_render_into_full(pa_sink *s, pa_memchunk *target) {
/* Called from IO thread context */
void pa_sink_render_full(pa_sink *s, size_t length, pa_memchunk *result) {
+ pa_mix_info info[MAX_MIX_CHANNELS];
+ size_t length1st = length;
+ unsigned n;
+
pa_sink_assert_ref(s);
pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
pa_assert(length > 0);
pa_assert(pa_frame_aligned(length, &s->sample_spec));
pa_assert(result);
+ pa_sink_ref(s);
+
pa_assert(!s->thread_info.rewind_requested);
pa_assert(s->thread_info.rewind_nbytes == 0);
- /*** This needs optimization ***/
+ pa_assert(length > 0);
+
+ n = fill_mix_info(s, &length1st, info, MAX_MIX_CHANNELS);
+
+ if (n == 0) {
+ pa_silence_memchunk_get(&s->core->silence_cache,
+ s->core->mempool,
+ result,
+ &s->sample_spec,
+ length1st);
+ } else if (n == 1) {
+ pa_cvolume volume;
+
+ *result = info[0].chunk;
+ pa_memblock_ref(result->memblock);
+
+ if (result->length > length)
+ result->length = length;
+
+ pa_sw_cvolume_multiply(&volume, &s->thread_info.soft_volume, &info[0].volume);
+
+ if (s->thread_info.soft_muted || !pa_cvolume_is_norm(&volume)) {
+ pa_memchunk_make_writable(result, length);
+ if (s->thread_info.soft_muted || pa_cvolume_is_muted(&volume))
+ pa_silence_memchunk(result, &s->sample_spec);
+ else
+ pa_volume_memchunk(result, &s->sample_spec, &volume);
+ }
+ } else {
+ void *ptr;
+
+ result->index = 0;
+ result->memblock = pa_memblock_new(s->core->mempool, length);
+
+ ptr = pa_memblock_acquire(result->memblock);
- result->index = 0;
- result->length = length;
- result->memblock = pa_memblock_new(s->core->mempool, length);
+ result->length = pa_mix(info, n,
+ (uint8_t*) ptr + result->index, length1st,
+ &s->sample_spec,
+ &s->thread_info.soft_volume,
+ s->thread_info.soft_muted);
- pa_sink_render_into_full(s, result);
+ pa_memblock_release(result->memblock);
+ }
+
+ inputs_drop(s, info, n, result);
+
+ if (result->length < length) {
+ pa_memchunk chunk;
+ size_t l, d;
+ pa_memchunk_make_writable(result, length);
+ result->length = length;
+
+ l = length - result->length;
+ d = result->index + result->length;
+ while (l > 0) {
+ chunk = *result;
+ chunk.index += d;
+ chunk.length -= d - result->index;
+
+ pa_sink_render_into(s, &chunk);
+
+ d += chunk.length;
+ l -= chunk.length;
+ }
+ result->length = length;
+ }
+
+ pa_sink_unref(s);
}
/* Called from main thread */