[pulseaudio-discuss] Rendering data from sink with 0.9.7

Jyri Sarha lepbtetfmvbz at spammotel.com
Wed Oct 24 00:20:15 PDT 2007


Hi,
	I have been playing around with "lennart"-branch, or should I
say 0.9.7, for a while now. I am implementing a prototype audio system
on top of pulseaudio. For most part the new version has worked
pretty well for me. However there are couple of problems I have found
so far.

	To ensure minimal latencies I have configure alsa sink and
source to use only two 10ms fragments. While running the daemon with
real-time priority the sound plays without a glitch (without
RT-priority mouse movement etc. activity causes buffer under
runs). However every now and then alsa-sink or -source unloads just
out of the blue. This seems to happen more often when fragment size is
smaller, but not often enough to really bother me at the moment. I just
wonder if this is a known problem.

	I am currently working on an effect module that should links
against an algorithm library. The module looks pretty much the same as
ladspa-module, but the used algorithm requires the samples in 10 ms
chunks. For this I have written peek and drop call backs like this:

<code>
static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) {
  struct userdata *u;
  pa_sink_input_assert_ref(i);
  u = i->userdata;
  pa_assert(chunk && u);

  if (u->sink_memchunk.memblock == NULL) {
    pa_memchunk lchunk;
    while (pa_memblockq_get_length(u->sink_memblockq) < u->window_size) {
      pa_sink_render(u->sink, u->window_size - pa_memblockq_get_length(u->sink_memblockq), &lchunk);
      if (pa_memblockq_push(u->sink_memblockq, &lchunk) < 0) {
	pa_log("Failed to push chunk into memblockq.");
	pa_memblock_unref(lchunk.memblock);
	return -1;
      }
      pa_memblock_unref(lchunk.memblock);
      lchunk.memblock = NULL;
    }

    if (!memblockq_to_chunk(u->core, u->sink_memblockq, &lchunk, u->window_size))  {
	    pa_log("memblock_to_chunk failed unexpectedly");
	    return -1;
    }
    // The algorithm should be run here...

    u->sink_memchunk = lchunk;
  }

  *chunk = u->sink_memchunk;
    
  return 0;
}    

static void sink_input_drop_cb(pa_sink_input *i, size_t length) {
  struct userdata *u;
  pa_sink_input_assert_ref(i);
  pa_assert_se(u = i->userdata);

  pa_assert(u->sink_memchunk.length >= length);
    
  u->sink_memchunk.length -= length;
  u->sink_memchunk.index += length;

  if (u->sink_memchunk.length == 0) {
    pa_memblock_unref(u->sink_memchunk.memblock);
    u->sink_memchunk.memblock = NULL;
  }
}
<\code>

	The memblockq_to_chunk() just copies and drops specified amount
of data to chunk. The function allocates a new memblock and does the
actual copying only if necessary. I have tested the function quite
thoroughly and there should be no problem there (maybe the function
could be added to memblockq API).

	When the module with the code above is loaded the daemon
crashes almost immediately in memblock refcount assertion failure under
pa_sink_input_peek. I have been debugging this for a few days now
but I can not find an error in my code. Is forcibly rendering 10ms
from sink evil? Or have I just overlooked something?

Here is the failure:
pulseaudio: pulsecore/memblock.c:439: pa_memblock_get_length: Assertion `pa_atomic_load(&(b)->_ref) > 0' failed.

and here is a back trace from the crash:
#6  0xb7c6c43b in __assert_fail () from /lib/tls/i686/cmov/libc.so.6
#7  0xb7f00112 in pa_memblock_get_length (b=0xb7a0f008)
    at pulsecore/memblock.c:439
#8  0xb7f123ba in pa_sink_render (s=0x8078c38, length=960, result=0xb7925e10)
    at pulsecore/sink.c:443
#9  0xb68a8749 in aep_sink_input_peek_cb (i=0x8078600, length=960, 
    chunk=0xb7925e58) at module-AEP.c:357
#10 0xb7f167a3 in pa_sink_input_peek (i=0x8078600, length=1920, 
    chunk=0xb7925ef8, volume=0xb7925f04) at pulsecore/sink-input.c:466
#11 0xb7f11e97 in fill_mix_info (s=0x8060160, length=1920, info=0xb7925ef8, 
    maxinfo=32) at pulsecore/sink.c:339
#12 0xb7f12870 in pa_sink_render_into (s=0x8060160, target=0xb79272c0)
    at pulsecore/sink.c:504
#13 0xb7f12c76 in pa_sink_render_into_full (s=0x8060160, target=0xb792730c)
    at pulsecore/sink.c:578
#14 0xb79fe64c in mmap_write (u=0x8056b38) at modules/module-alsa-sink.c:180
#15 0xb79fff49 in thread_func (userdata=0x8056b38)
    at modules/module-alsa-sink.c:620


	One other minor issues, if I have correctly understood what
this piece of code is trying to do, alsa-util.c. I have not seen any
run-time problems related to this, the code just does not make too much
sense.  Anyway I think this patch should fix it:
<patch>
===================================================================
--- src/modules/alsa-util.c     (revision 6372)
+++ src/modules/alsa-util.c     (working copy)
@@ -301,11 +301,10 @@
         if ((ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_MMAP_INTERLEAVED)) < 0)
             if ((ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
                 goto finish;
-
+           else
+             *use_mmap = 0;
     } else if ((ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) 
         goto finish;
-    else if (*use_mmap)
-        *use_mmap = 0;
     
     if ((ret = set_format(pcm_handle, hwparams, &f)) < 0)
         goto finish;
<\patch>


Best regards,
     Jyri

// Jyri Sarha - okuAtikiDotfi



More information about the pulseaudio-discuss mailing list