androidmedia plugin doesn't register with gstreamer 1.8.3

Martin Vachovski Martin.Vachovski at skytek.com
Wed Sep 21 17:00:16 UTC 2016


Hi All,

I managed to register the androidmedia plugin.
Seems that there are some ingredients which are missing in the pre built binaries...
I managed to collect and put them together from different sources on the net (people
have been working on it)

I am going to explain how I managed to start it, so somebody else can use it or
even patch up the prebuilt library...

1) Add the the necessary compiler and linker flags to the ndk section of build.gradle of your app.
Mine currently looks something like this:
ndk {
            moduleName = 'hello-jni'
            toolchain = 'clang'
            cppFlags.addAll(['-Wall'])
            cppFlags.addAll(['-v'])
            cppFlags.addAll(["-I${lib_gst_root}/include/gstreamer-1.0".toString(),
                           "-I${lib_gst_root}/include/glib-2.0".toString(),
                           "-I${lib_gst_root}/lib/glib-2.0/include".toString(),
                           "-I${lib_gst_root}/lib/gstreamer-1.0/include".toString()])

            ldFlags.add("-v")
            ldFlags.addAll(["-L${lib_gst_root}/lib".toString(),
                            "-L${lib_gst_root}/lib/gstreamer-1.0/static".toString()])
            // gstreamer plugin libraries
            ldLibs.addAll(["EGL",  "gstandroidmedia", "gstbadvideo-1.0",
                           "gstaudio-1.0", "gstcoreelements", "gstbase-1.0", ])

            // general dependencies
            ldLibs.addAll(["log",  "gstphotography-1.0",  "gstgl-1.0",
                           "gstopengl",  "gstvideo-1.0",  "gstreamer-1.0",
                           "gmodule-2.0", "gobject-2.0", "glib-2.0",
                           "iconv", "intl", "orc-0.4", "ffi"])
        }

Note that the order of the libs matters!

2) GST_PLUGIN_STATIC_DECLARE / GST_PLUGIN_STATIC_REGISTER

in your .c or .cpp file outside of any code block
#ifdef __cplusplus
extern "C" {
#endif
GST_PLUGIN_STATIC_DECLARE(coreelements);
GST_PLUGIN_STATIC_DECLARE(androidmedia);
#ifdef __cplusplus
}
#endif

in your .c or .cpp file right after the call to gst_init():

GST_PLUGIN_STATIC_REGISTER(coreelements);
GST_PLUGIN_STATIC_REGISTER(androidmedia);

So far everything is as it is expected, now comes the not so obvious part...

3) JNI callback class
After looking into the course code of gstahcsrc.c code I read a comment
which says that a JNI callback class named 
org.freedesktop.gstreamer.androidmedia.GstAhcCallback
is required.

Seems this java class is not supplied with the gstreamer-1.0-android-arm-1.8.3.tar.bz2

I managed to find it online at:
https://github.com/alessandrod/gst-plugins-bad/tree/master/sys/androidmedia/org/freedesktop/gstreamer/androidmedia
(thanks to the people who contributed to it!)

I simply imported the file in the java part in the project.
It compiles and I can even access it via the JNI with:
jclass k = env->FindClass ("org/freedesktop/gstreamer/androidmedia/GstAhcCallback");

But at that stage the androidmedia plugin still won't register!

4) After redirecting the gstreamer log system via logcat, I saw that there is a runtime error
at file gstjniutils.c line 577:

if (!g_module_symbol (module, "gst_android_get_application_class_loader",
          (gpointer *) & get_class_loader)) {
    ret = FALSE;
  }

So, the reason androidmedia plugin won't register is that in its code there are some "manual"
checks for the availability of a class loader, and this checks rely on
a dynamic call to the function gst_android_get_application_class_loader
(and this function is also missing)

So I found that patch by Matthieu Bouron
https://lists.freedesktop.org/archives/gstreamer-commits/2015-May/086820.html

The whole patch contains a few functions which obtain a jclass reference to the class loader
and also exposes the functions
gst_android_get_application_context ()
gst_android_get_application_class_loader ()
on the module level of the app so they 
can be resolved by
g_module_symbol()
( without the extern "C" { part, you'll have problems if you're trying to link from C++ )

static jobject _context = NULL;
static jobject _class_loader = NULL;

#ifdef __cplusplus
extern "C" {
#endif
jobject
gst_android_get_application_context ()
{
  return _context;
}

jobject
gst_android_get_application_class_loader ()
{
  return _class_loader;
}

static gboolean
init (JNIEnv *env, jobject context)
{
    __android_log_write(ANDROID_LOG_INFO, "gst-test", "init begin");
  jclass context_cls = NULL;
  jmethodID get_class_loader_id = 0;

  jobject class_loader = NULL;

  context_cls = env->GetObjectClass (context);
  if (!context_cls) {
    return FALSE;
  }
    __android_log_write(ANDROID_LOG_INFO, "gst-test", "init context_cls");

  get_class_loader_id = env->GetMethodID (context_cls,
                                          "getClassLoader", "()Ljava/lang/ClassLoader;");
  if (env->ExceptionCheck ()) {
    env->ExceptionDescribe ();
    env->ExceptionClear ();
    return FALSE;
  }
    __android_log_write(ANDROID_LOG_INFO, "gst-test", "get_class_loader_id");

  class_loader = env->CallObjectMethod (context, get_class_loader_id);
  if (env->ExceptionCheck ()) {
    env->ExceptionDescribe ();
    env->ExceptionClear ();
    return FALSE;
  }

  if (_context) {
    env->DeleteGlobalRef (_context);
  }
  _context = env->NewGlobalRef (context);

  if (_class_loader) {
    env->DeleteGlobalRef (_class_loader);
  }
  _class_loader = env->NewGlobalRef (class_loader);

    char str[128];
    sprintf(str, "init end _context %x", _context);
    __android_log_write(ANDROID_LOG_INFO, "gst-test", str);
  return TRUE;
}

static void
gst_android_init (JNIEnv * env, jobject context)
// gst_android_init (JNIEnv * env, jobject gstreamer, jobject context)
{
    gchar *registry;
    GError *error = NULL;

    if (!init(env, context)) {
        __android_log_print(ANDROID_LOG_INFO, "GStreamer", "GStreamer failed to initialize");
    }

    if (gst_is_initialized()) {
        __android_log_print(ANDROID_LOG_INFO, "GStreamer",
                            "GStreamer already initialized");
    }
}
#ifdef __cplusplus
}
#endif

So after that I saw for the first time the androidmedia plugin being registered.
Tomorrow I will even try to use the elements! :)

On a side comment, if I have enough time, I might provide a clean skeleton app
which contains everything. The only problem seems to be that
if I try to attach it as an archive, it gets stopped/delayed by the moderator.

Hope that long exercise helps somebody!

Best Regards
Martin

________________________________________
From: gstreamer-android <gstreamer-android-bounces at lists.freedesktop.org> on behalf of Martin Vachovski <Martin.Vachovski at skytek.com>
Sent: Tuesday, September 20, 2016 4:18 PM
To: Discussions about GStreamer on Android
Subject: Re: androidmedia plugin doesn't register with gstreamer 1.8.3

Hi Sebastian,

Please find attached the .tar file.
I have removed any intermediate binaries from it so it is small.
You should have
gstreamer-1.0-android-arm-1.8.3
in order to build it.

The only modification you need to make is to specify the path to gstreamer in
app/build.gradle
replace
def lib_gst_root = '/home/martin/AndroidStudioProjects/HelloJNI/gstreamer-1.0-android-arm-1.8.3'
with your path

After that, if you have properly set NDK, I think it should build

Let me know if you had any problems with the build?

Best regards
Martin

________________________________________
From: gstreamer-android <gstreamer-android-bounces at lists.freedesktop.org> on behalf of Sebastian Dröge <sebastian at centricular.com>
Sent: Tuesday, September 20, 2016 4:02 PM
To: Discussions about GStreamer on Android
Subject: Re: androidmedia plugin doesn't register with gstreamer 1.8.3

On Di, 2016-09-20 at 14:50 +0000, Martin Vachovski wrote:
> Hi Sebastian,
>
> Many thanks for the reply!
>
> The project is derived from the HelloJNI
> sample project of AndroidStudio- I have only added
> the necessary libraries to the app/build.gradle file.
> If it isn't against the mailing list policy I will be happy to
> provide the whole project as a .tar file
> or the two files which I have basically modified- hello-jni.c and
> app/build.gradle
> Let me know which form would be more convenient?

The whole project so that it can be just built with gradle :)

You might also want to take a look at these example applications here
to get some idea how people usually integrate GStreamer with Android
apps:

Using gradle:
  https://cgit.freedesktop.org/gstreamer/gst-examples/tree/playback/player/android

Using ndk-build/ant:
  https://cgit.freedesktop.org/~slomo/gst-sdk-tutorials/tree/gst-sdk/tutorials/

--
Sebastian Dröge, Centricular Ltd · http://www.centricular.com


More information about the gstreamer-android mailing list