caprica / picam

Unofficial Java API library for the Raspberry Pi camera.
GNU General Public License v3.0
49 stars 11 forks source link

Unsatisfied Link Error #21

Closed dajma00 closed 4 years ago

dajma00 commented 4 years ago

Any idea why I am getting the following error when I run my jar with version 1.1.0 of picam. I am running Ubuntu Server 64 bit on Raspberry Pi.

Exception in thread "AWT-EventQueue-0" java.lang.UnsatisfiedLinkError: uk.co.caprica.picam.Camera.create(Luk/co/caprica/picam/CameraConfiguration;)Z at uk.co.caprica.picam.Camera.create(Native Method) at uk.co.caprica.picam.Camera.open(Camera.java:106) at uk.co.caprica.picam.Camera.(Camera.java:91)

pom.xml:

uk.co.caprica picam 1.1.0
caprica commented 4 years ago

So picam 1.x uses JNA rather than it's own JNI native library. JNA is used to load the native mmal library.

Are you using a 64-bit JVM or a 32-bit JVM?

Are the MMAL libraries 64-bit or 32-bit on your OS?

Since AFAIK there is no official support for any 64-bit OS on RPi (yet).

dajma00 commented 4 years ago

JVM is 64 bit. libmmal.so is also 64 bit.

caprica commented 4 years ago

Are there no more log messages?

Because that error means it failed to load a native library, the reasons for this type of error are usually:

  1. shared libraries exist, but mismatch between JVM architecture (32-bit vs 64-bit) and the shared libraries
  2. the shared libraries do not exist or can not be found
  3. you have multiple JVM installed but the "wrong" one is found on the executable search $PATH

Is your Ubuntu OS image specially designed for a Pi, because I am surprised the MMAL libraries would be there by default.

How do you know that libmmal is 64-bit, what did you check?

Without some more information it's impossible for me to specifically what's wrong, the above pointers are the best I can offer based on what you've told me.

caprica commented 4 years ago

What does "java -version" report?

dajma00 commented 4 years ago
ubuntu@ubuntu:~$ java -version
java version "1.8.0_241"
Java(TM) SE Runtime Environment (build 1.8.0_241-b07)
Java HotSpot(TM) 64-Bit Server VM (build 25.241-b07, mixed mode)
ubuntu@ubuntu:~$

The Ubuntu version is the one placed on the Raspberry site. It is like you said, not fully supported, meaning many userland programs etc. are missing.

About the libmmal.so, yes it was not there by default. But I compiled userland with the -aarch64 flag and that gave me 64 bit version of these binaries.

Where do I get the other log messages you mention?

dajma00 commented 4 years ago

On version 2.0.1 of picam, if I compile picam library for 64 bit and then use on the same system I get this error:

Exception in thread "AWT-EventQueue-0" java.lang.UnsatisfiedLinkError: /home/ubuntu/picam-2.0.1.so: libmmal.so: cannot open shared object file: No such file or directory (Possible cause: architecture word width mismatch)
        at java.lang.ClassLoader$NativeLibrary.load(Native Method)
        at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1934)
        at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1817)
        at java.lang.Runtime.load0(Runtime.java:809)
        at java.lang.System.load(System.java:1086)

Looks like some kind of issue within the libmmal.so that I have on my system. What would "architecture word mismatch" mean?

caprica commented 4 years ago

"architecture word mismatch" is exactly the 32-bit vs 64-bit issue I was talking about.

From your last message, I would suspect that you have a 32-bit version of the picam JNI shared library - how exactly did you build that library?

Maybe try writing a trivial Java program that uses JNA to try and load libmmal by doing System.loadLibrary("mmal") - I suspect this is what is failing.

It's not possible to say any more from what you've posted.

dajma00 commented 4 years ago

hmm... this is getting tough. Raspberry just announced 64 bit beta Debian for the Pi 4. Let me check that and see if that works.

caprica commented 4 years ago

Please run this and report results...

public class LibTest {

    public static void main(String[] args) {
        System.loadLibrary("mmal");
    }
}

Until that works, there's no point trying anything else.

dajma00 commented 4 years ago

Ok, let me check that.

dajma00 commented 4 years ago

Ok, here is the result with the new Raspberry OS, 64 bit beta version running on Raspberry Pi 3b. The call

System.loadLibrary("mmal");

Succeeds without generating an exception.

caprica commented 4 years ago

That at least means whatever JVM you are using can load the MMAL shared library, so word sizes as discussed previously match.

So next the question is why, using 1.x of this library, can JNA seemingly not load the library.

Or is something else going wrong, likely related to running a 64-bit OS?

Does JNA provide a libdispatch.so for 64-bit ARM architecture, I don't know.

I suppose it's possible, but unlikely, that some method signatures in libmmal have been changed on your OS. It's doubtful, but not impossible.

TL;DR; there simply isn't enough information provided to be able to say why this is not working. Unfortunately I can't add anything else, other than to say it works on the Pi's supported OS (which doesn't help you of course).

caprica commented 4 years ago

I just did a random search and found this that may or may not be related:

https://www.filebot.net/forums/viewtopic.php?t=6059

If you read through that thread it does suggest that a similar problem related to JNA - JNA provides a libdispatch.so for multiple architectures, x86, x86_64 or whatever the AMD equivalent is, and also various architecture strings for ARM which the Pi will use.

I presume that in this case JNA can not detect/match the run-time OS/hardware architecture to one of the libdispatch.so files contained inside the JNA jar file (JNA extracts this file at runtime).

That probably is the problem with picam-1.x that uses JNA.

For picam-2.x that does NOT use JNA, the problem is likely something else, and probably that the picam JNI shared object file is not built correctly for your 64-bit OS, or you have failed to configure the java.library.path to find this picam shared object.

Probably for picam-2.x this is fixable if you can properly build a 64-bit shared library from the picam JNI sources.

I can't add anything more.

dajma00 commented 4 years ago

Version 1.1.0 works! Set the LD_LIBRARY_PATH to /usr/lib/aarch64-linux-org (this location contains libmmal.so and related dependencies) and run. Version 1.1.0 of picam runs on this Raspberry Pi OS 64 bit. I will checkout version 2 as well and see if that runs as well or not.

caprica commented 4 years ago

Well, that's good, but I don't understand how the System.loadLibrary("mmal") test worked without LD_LIBRARY_PATH, but it's moot if you have something working.

Although I suppose it could be any of the dependent libraries causing the failure.

dajma00 commented 4 years ago

Yes, the LD_LIBRARY_PATH was required to load mmal. I just didn't mention that in my post. Any ideas why is this required, because that forces me to put my other .so files also in that folder. Not a big deal, but just wondering.

caprica commented 4 years ago

Well, OK, but that piece of information was kinda important :-)

It's perfectly acceptable to use LD_LIBRARY_PATH to augment the search path for the native runtime linker to find the shared objects. There are many ways to use this, setting the environment variable as you have found, adding configuration files to the /etc/ld.so.conf folder are two different options.

Presumably it's not needed on Raspbian because the runtime linker already knows how/where to find those libraries. IIRC you had to build libmmal yourself, so things may not be quite in the expected place.

You are not forced to put your other .so files in the same folder, you can add multiple different folders to the LD_LIBRARY_PATH and they can point wherever you want.

Anyway, it's a Linux thing rather than a Java/vlcj thing of course.

I'll close this now you have things working.