[asterisk-bugs] [Asterisk 0017659]: [patch] Using app_jack with JACK_HOOK will result in noise rather than the channel sound.
Asterisk Bug Tracker
noreply at bugs.digium.com
Fri Nov 19 09:16:11 CST 2010
A NOTE has been added to this issue.
======================================================================
https://issues.asterisk.org/view.php?id=17659
======================================================================
Reported By: mrwho
Assigned To:
======================================================================
Project: Asterisk
Issue ID: 17659
Category: Applications/app_jack
Reproducibility: sometimes
Severity: major
Priority: normal
Status: ready for testing
Asterisk Version: SVN
JIRA: SWP-1866
Regression: No
Reviewboard Link:
SVN Branch (only for SVN checkouts, not tarball releases): trunk
SVN Revision (number only!): 274530
Request Review:
======================================================================
Date Submitted: 2010-07-16 05:50 CDT
Last Modified: 2010-11-19 09:16 CST
======================================================================
Summary: [patch] Using app_jack with JACK_HOOK will result in
noise rather than the channel sound.
Description:
Using JACK_HOOK to manipulate the sound of a channel may result in noise
rather than proper sound. It was quite hard to squash this bug, but it's
all related to the way the ringbuffers behave.
When a channel is set up app_jack will start queuing frames from jackd
to the ringbuffer to be sent to asterisk, problem being that at that point
the channel may be not yet ready - say that you're doing a Dial next - and
the buffer fills up.
Once the buffer is filled the next frames coming in may be cut. If a
float - made of 4 bytes - could be only partially written, that would end
up in a consequent succession of "wrong" samples, all off by one, in other
words: noise.
A bit of ASCII art to make the point, say that we have three samples
(A,B and C) coming from jack looking like:
<pre>
------A------ ------B------ ------C------
|A1|A2|A3|A4| |B1|B2|B3|B4| |C1|C2|C3|C4|
</pre>
Now, on the ringbuffer we have space only for 7 bytes, what will be
written in the buffer will look like:
<pre>
------A------ ----B-----
|A1|A2|A3|A4| |B1|B2|B3|
</pre>
When the next samples (D,E) come in - and say we have the space to write
them completely - our ringbuffer will look like:
<pre>
------A------ ------B------ ------D------ ----E-----
|A1|A2|A3|A4| |B1|B2|B3|D1| |D2|D3|D4|E1| |E2|E3|E4|
</pre>
When those samples will be sent to Asterisk they will only be noise,
since they're all off by one.
The same issue may happen if - for any reason - the buffer is filled by
any other reason. This will happen often expecially if - to have very low
latency - you're using very small buffers in app_jack and short periods in
jackd.
We have three possible solutions to this issue:
<ol>
<li>We free, by reading, enough bytes from the ringbuffer and then write
the
new samples. So we would drop the older frames, we just have to make
sure
to drop entire frames and not only parts of them - else we are
simply
reintroducing the same problem;</li>
<li>When we don't have space we will drop the whole buffer and start
writing
from the beginning again. With small buffers this is not really an
issue
and we avoid running into a case where we simply keep writing at the
top
of the buffer dropping each time a few frames from the bottom of
it;</li>
<li>We use (1) for a set amount of consecutive times, after which we do
(2).
In this way we have a chance to drop very few frames in case of a
momentary buffer underrun.</li>
</ol>
The patch I'm attaching at the moment for testing uses (2), it's very
well suited for small buffers. I'm working on a patch to allow (1) (2) and
(3) to
be chosen as parameters to the JACK_HOOK function. There is (1) in the
patch
as well, but it has been commented out, you may want to test drive it to
see
how it works on your environment.
======================================================================
----------------------------------------------------------------------
(0128982) rawdod (reporter) - 2010-11-19 09:16
https://issues.asterisk.org/view.php?id=17659#c128982
----------------------------------------------------------------------
I want to express that I am extremely interested in this patch. But I think
there is some additional complications that should be looked into.
Yesterday I started messing with asterisk and jack and ran into problems
with the jack output app right away. The problem was that the audio input
would go all screechy and drop out after a short time, usually less than a
minute. It did atleast initially seem to have some correlation to higher
volume and/or higher frequency, but I didn't go out of the way to prove
that. The next thing I tested was changing the jack server from 44100 to
8000hz. This actually was completely stable. (Using the app_jack and
asterisk system from ubuntu 10.10) I was happy that it was stable, but of
course I need to run jack at 44100. I switched it back to 44100, and tried
several different codecs and that did not seem to make a difference. So I
jumped into the code. (I've been around a few jacks and rings before..) I
cut out all the code dealing with jack_hook so I was left with just the
app. I found that the function that seemed to be actually report getting
mashed up from the issue was queue_voice_frame as it would report so once I
changed the debug line to a log line.. so I knew there was a ringbuffer
related issue at this point. I went down one path (not fully understanding
the code at all at this point ) of changing handle_jack_audio to not write
a ast_frame if (res < read_len). That might have been totally up the wrong
tree tho. Then after the 10 hours of messing with it I found this patch :P
This is good stuff perhaps, but its not stable for me. I've tried the
patch on the SVN revision mentioned in here, the latest SVN and 1.8. For
me, I still get the same 'tried to write bytes but couldn't' error that I
got before, however the audio won't go screechy and fail. However, the
entire asterisk server will crash sometimes when the caller hangs up from
the jack_app! I have tried running jack at various period sizes and
changing the ringbuffer size as advised in the patch, however nothing is
totally stable or glitch free. The best number I got was something like
9600, it caused only 15 or so buffer glitches on a 10 minute call but when
the call was over asterisk crashed.
At any rate, I definitely want to do whatever I can to get this working,
If I have to go study up on asterisk internals and ringbuffer logic, I'll
do it (could take a while tho...) Yesterday was really the first time I
had messed with asterisk in years, and I code Ruby mostly, so I'm not used
to as much debugging off by one pointer to pointer arrays and such things,
but I can cause some damnage ;P Hats off to anyone else working on this
problem, any patches or comments you got I'm ready to test and listen. You
can find me on freenode irc as oneman.
Cheers, David
Issue History
Date Modified Username Field Change
======================================================================
2010-11-19 09:16 rawdod Note Added: 0128982
======================================================================
More information about the asterisk-bugs
mailing list