There is a bug in the OSS cubeb code which use the previous number of
frames as input for the next data-exchange, when full-duplex is
activated. This causes noticable jitter, because the wrong number of
audio frames is exchanged.
The solution is to check both input and output audio DSP buffers and
select the minimum number of audio frames which can be transferred when
full duplex is activated.
On some device (namely, a Samsung Galaxy A30 running Android 10, see
https://bugzilla.mozilla.org/show_bug.cgi?id=1679932), the state is
"STARTED" for quite some time, so we don't go into the `if` statement.
It's best to fallback.
We then need to ensure the monotonicity of this clock (since now we use
two distinct ways of reporting the time, it can end up being
non-monotonic for some calls), using the same technique we use on other
backends.
Reduce the code complexity of non-blocking IO all together. Besides, we
should let recording direction driving the playback direction if we are
working with duplex stream.
- Fix misuse of SNDCTL_DSP_GETOSPACE ioctl on record.fd as well
- Add more comments regarding buffer initialization
- Address comments about which direction driving another direction
This removes the constant checking for state changes with
5ms of sleep in between for the state thread.
We need a new thread to wakeup the state thread reliably
without blocking in the audio thread. For a more detailed
and theoretical explanation of the problem and solution (specifically
written for this commit), see:
https://nyorain.github.io/lock-free-wakeup.html
Now, will only do this time-based sleeping when actively waiting
for a state change. We can't implement that with a blocking call to
AAudioStream_waitForStateChange since that can't be woken up
and we furthermore might have to wait for multiple streams at once.
This also fixes some issues and race conditions with stream destruction
and adds some more documentation.