Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OpenSL ES driver. Changing the queue processing strategy. #813

Open
wants to merge 31 commits into
base: develop
Choose a base branch
from
Open

OpenSL ES driver. Changing the queue processing strategy. #813

wants to merge 31 commits into from

Conversation

PavelAtr
Copy link

Queue handling has been moved to Callback functions. The write / read functions only fill the audio data buffers. This allows for continuous flow of data to / from queues.
That provides continuous sound without clicks and distortion. The driver was tested on Android phone Xiaomi Redmi 8 Note with DAW Ardor and showed good sound quality.

falkTX and others added 30 commits July 15, 2021 07:29
Signed-off-by: falkTX <[email protected]>
Signed-off-by: falkTX <[email protected]>
It uses c++ sources and runtime therefore its best to use c++ compiler
to build it so it can find the correct runtime, cross compiling with
clang fails

x86_64-yoe-linux-ld: example-clients/simdtests.cpp.28.o: undefined reference to symbol '__cxa_call_unexpected@@CXXABI_1.3'

Signed-off-by: Khem Raj <[email protected]>
Signed-off-by: falkTX <[email protected]>
Signed-off-by: falkTX <[email protected]>
Signed-off-by: falkTX <[email protected]>
Signed-off-by: falkTX <[email protected]>
Signed-off-by: falkTX <[email protected]>
* macOS: Pass JackMachSemaphore send right via mach_msg IPC

Previously, JackMachSemaphore would communicate the send right for the
semaphore object from the server to a client via a named service
registered via `bootstrap_register`. However, to do this, it would
register the semaphore's port as the service port directly.

In theory this ought to be fine, however in practice, macOS `launchd`,
which provides the `bootstrap_register` interface, does not correctly
detect when such a port becomes dead, and incorrectly believes that the
service that it provides is forever alive, even past the end of the
`jackd` process' (and therefore the semaphore's) existence. This seems
to be *specific* to semaphore ports, as `launchd` is expecting a
standard IPC port, owned by the task, not the kernel. This prevents
`jackd` from later registering another service with the same name, as
`launchd` rejects the registration as conflicting with an active service.

To get around this, `jackd` previously added a counter to the end of the
named service registrations, allowing old services to remain in the
system until the end of the session. To prevent things getting out of
hand, this was capped at 98 service registrations for a given semaphore
name. This led to #784, in which running a client for the 99th time
resulted in the semaphore creation failing and the client failing to
connect.

As `launchd` outlives multiple runs of `jackd`, this situation persisted
across restarts of `jackd`, requiring a restart of the user's session
(i.e. a reboot) to fix.

An initial attempt at fixing this (see #785) tried passing the port
rights directly via shared memory, however mach is too clever for us and
foils that plan by having port names be looked up in a per-task table
(sensible when you think about it).

In this commit, we use mach IPC messages to transfer the send right for
the semaphore from the server to the client. By registering a standard
IPC port with the bootstrap server, the service registrations are
correctly torn down when the ports are destroyed.

It works something like this:

* Server creates IPC port and registers it globally via `bootstrap_register`
* Server listens on IPC port for messages
* Client looks up IPC port via `bootstrap_look_up`
* Client sends it a message
* Server replies with a message containing a send right to the
semaphore's port
* Client is then free to use the semaphore port as before.

This resolves #784.

* Improve error handling

* Add myself to Authors
@@ -414,39 +435,66 @@ double android_GetTimestamp(OPENSL_STREAM *p){
void bqRecorderCallback(SLAndroidSimpleBufferQueueItf bq, void *context)
{
OPENSL_STREAM *p = (OPENSL_STREAM *) context;

while ((p->inputBufferSize[0] > 0) && (p->inputBufferSize[1] > 0))
usleep(1000);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this really the best way? couldnt a semaphore or similar be used to keep things in sync?
sleeping until the buffers are empty does not seem like a good idea...

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be honest, I don't know if it could be done better. I was not satisfied with the initial sound quality of the driver, and my version is as follows. In any case, in the examples I've seen, the callback function itself replenishes the queue, and not the handler from the outside.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

usleep (1000) only happens when there is no sound playing, it does not happen during playback. The examples I've seen use silence buffer playback instead. What is more beautiful I do not know.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the absence of sound, usleep allows you to reduce the load on the cpu up to 1-2%, if you do not do this, then a fast cycle will load the cpu.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants