javaandroidgstreamerjnajava-gstreamer

Using Gstreamer for Android with JNA & gst1-java-core?


Before we start allow me to just say that I know that it is possible to integrate Gstreamer into Android natively using C code as done in the Android Tutorials themselves.

This question is not related to simply just getting Gstreamer running on Android but rather running it on Android using the pre-existing native Java wrapper library gst1-java-core alongside JNA inside of Android Studio in a new Native project. However, if Native C code is the only way do let me know if you have tried and failed what I'm trying to do.

Lets begin.

System Information:

Process involved setting up a brand new project in Android Studio and choosing Native C++ as the Project Template followed by keeping everything else default including the toolchain. Once the project was built and finished it's Gradle business I did the usual git init and set it up in Git. Following that I downloaded and added the gst1-java-core-1.4.0.jar from the releases page to the "libs/" directly inside the "app/" folder.

Once I had done so I modified the build.gradle file in the app directory to match this Gradle Gist.

This was then naturally followed by a Gradle sync and when that had completed correctly I went to my MainActivity.java and added two lines of code total. First at the top:

import org.freedesktop.gstreamer.Gst;

and then inside the onCreate method:

Gst.init();

This then produced this error:

E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.rcbappnative, PID: 9644
java.lang.UnsatisfiedLinkError: Could not load library: gstreamer
    at org.freedesktop.gstreamer.lowlevel.GstNative.load(GstNative.java:56)
    at org.freedesktop.gstreamer.lowlevel.GstNative.load(GstNative.java:46)
    at org.freedesktop.gstreamer.lowlevel.GstAPI.<clinit>(GstAPI.java:37)
    at org.freedesktop.gstreamer.Gst.getVersion(Gst.java:144)
    at org.freedesktop.gstreamer.Gst.init(Gst.java:473)
    at org.freedesktop.gstreamer.Gst.init(Gst.java:419)
    at com.example.rcbappnative.MainActivity.onCreate(MainActivity.java:25)
    at android.app.Activity.performCreate(Activity.java:7963)
    at android.app.Activity.performCreate(Activity.java:7952)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1307)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3629)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3806)
    at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
    at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2267)
    at android.os.Handler.dispatchMessage(Handler.java:107)
    at android.os.Looper.loop(Looper.java:237)
    at android.app.ActivityThread.main(ActivityThread.java:8167)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:496)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1100)

I then proceeded to attempt to rectify this by following Gstreamers installation instructions for Android by downloading the binaries that matched my NDK version (gstreamer-1.0-android-universal-1.18.3.tar.xz) and then extracting them to a folder that was then pointed to by the environment variable

GSTREAMER_ROOT_ANDROID=/home/user/Android/gstreamer

I added this environment variable to ~/.project as well ~/.bashrc and sourced either of them and tried to build and run but nothing changed.

I then attempted to add it to both local.properties and gradle.properties simultaneously (and also either one at a time) and still the same error would occur.

The Java Examples provided by gstreamer-java's github works on my machine just fine so it appears that it is not a system wide error but rather an Android environment specific error where it somehow fails to load the library. Perhaps because it doesn't know to look for that environment variable.

So the question now is; has anyone gotten gst1-java-core to work with Android through JNA or can anybody point me in the right direction regarding what I am possibly doing wrong in relation to importing this library? Any help would be very much appreciated.


Solution

  • So it was my mistake not knowing enough about Android and the sub systems to know that even though Android is primarily developed in Java it does not support running Java "natively". This means that JNI is not relevant as according to Wikipedia JNI is:

    In software design, the Java Native Interface is a foreign function interface programming framework that enables Java code running in a Java virtual machine to call and be called by native applications and libraries written in other languages such as C, C++ and assembly

    So in saying that - because Android does not run a JVM but rather it runs Native C on a Linux Kernel this means that trying to integrate a "java wrapper" through the JNI is not currently possible on Android.

    Because of this - the common solution and following Gstreamers official tutorials appears to currently be the only way to use Gstreamer in Android.

    I only have myself to blame for thinking that everyone else had just "missed" JNI and gst1-java-core and that I somehow knew better than even the Gstreamer official website itself.

    I felt like answering this question though because if anyone else goes down the wrong track I can now officially suggest to following the official tutorials and create an Android App with Native support so that you can compile and integrate the C code directly from Gstreamer and then make your app work like that.

    I can currently say that following the above paragraph's advice resulted in me creating a working Android application with a Gstreamer live stream currently up and running using a custom pipeline. I'm not going to say it was easy; because it isn't; especially if you are not great at C programming. But it is definitely doable and the tutorials are good.