Qt bindings of GStreamer on Android (failed experience)
for the ones who may read this note, unfortunately I couldn't succeed to provide a working solution. however I decided to write my findings here, hat hopefully help someone else that wants to cdo the same thing in the future. the source code related to my tries is located on this repository.
There are two things that we should consider when we want to start our journay:
- first thing is that all the fancy automated tools provided by GStreamer team for Android doesn't work here.
- he second is that the Qt bindings are not available in the official pre-built binaries and we need to create our own custom version of gstreamer library.
Build the libgstreamer_android.so
Official tutorials of Gstreamer, are based on Android NDK build system, which
automatically build and deploy the libgstreamer_android.so
library (absolutely
without Qt support!) to the target APK based on the plugins has been chosen
inside make file.
we need to replace it by custom targets in our qmake
project file. to do so we
defined two custom targets to build and cleanup the libgstreamer_android.so
file for us:
GSTREAMER_ROOT_ANDROID = $$_PRO_FILE_PWD_/gstreamer-1.0/armv7 gst.target = $$ANDROID_PACKAGE_SOURCE_DIR/libs/armeabi-v7a/libgstreamer_android.so gst.commands = cd $$ANDROID_PACKAGE_SOURCE_DIR; \ ./build_gstreamer.sh TARGET_ARCH_ABI=armeabi-v7a \ GSTREAMER_ROOT_ANDROID=$$GSTREAMER_ROOT_ANDROID \ NDK_PROJECT_PATH=$$ANDROID_PACKAGE_SOURCE_DIR extraclean.commands = rm -rv $$ANDROID_PACKAGE_SOURCE_DIR/libs $$ANDROID_PACKAGE_SOURCE_DIR/obj clean.depends += extraclean QMAKE_EXTRA_TARGETS += gst clean extraclean PRE_TARGETDEPS += $$ANDROID_PACKAGE_SOURCE_DIR/libs/armeabi-v7a/libgstreamer_android.so
since we don't have access to the environment variables during our custom
target, I wrote a custom bash script to first prepare the environment (the
Android relate paths), and then run the ndk-build
for me:
source ~/.bashrc ndk-build $@
finally we have the requirements to build the libgstreamer_android.so
based on
the make file we added to android/jni/Android.mk
.
Build the Gstreamer libraries including the Qt bindings
The approach that I followed was to use the cerbero
the build system which is
provided by GStreamer team to create custom bundles of GStreamer.
to do so, first we need to checkout the cerbero
from it's repository and
checkout the version we want to build.
$ git clone https://gitlab.freedesktop.org/gstreamer/cerbero $ cd cerbero $ git checkout 1.20.1
then we need to bootstrap the cerbero
to have all of it's requirements. we
also need identify our cross compile configuration using one of the
configurations provided inside config
folder. I used the
config/cross-android-universal.cbc
config.
Note: in my experience I faced errors about missing python pacakges (distro
), my
host OS (Manjaro) was also undefined for the bootstrap script, so I add it
manually, based on the error messages that I received.
$ ./cerbero-uninstalled -c config/cross-android-universal.cbc bootstrap
after preparing the environment, we go for building our custom GStreamer
bundle. to do so we use the package
command and add the qt5
variant to list
of it's default recipes.
export QMAKE='/path/to/Qt/5.15.2/android/bin/qmake' $ ./cerbero-uninstalled -c config/cross-android-universal.cbc -v qt5 package gstreamer-1.0
following the above steps, we have a
gstreamer-1.0-android-universal-1.20.1.tar.xz` file which including the Qt5
bindings. they will be added as ~GSTREAMER_PLUGINS_QT5
plugin to the list of
plugins.
however when I trying to create the libgstreamer_android.so
using this bundle,
we receive following linker errors, which I didn't have a chance to fix them
yet.
... ../gstqsgtexture.cc:36: error: undefined reference to 'QSGTexture::QSGTexture()' ../gstqsgtexture.cc:36: error: undefined reference to 'QOpenGLFunctions::QOpenGLFunctions()' ../gstqsgtexture.cc:40: error: undefined reference to 'QOpenGLFunctions::initializeOpenGLFunctions()' ../gstqsgtexture.cc:55: error: undefined reference to 'QSGTexture::~QSGTexture()' ../gstqsgtexture.cc:64: error: undefined reference to 'QOpenGLContext::functions() const' ../gstqsgtexture.cc:67: error: undefined reference to 'QSGTexture::~QSGTexture()' ../gstqsgtexture.cc:67: error: undefined reference to 'QSGTexture::~QSGTexture()' ../gstqsgtexture.cc:172: error: undefined reference to 'QOpenGLContext::functions() const' armeabi-v7a/moc_gstqsgtexture.cpp:88: error: undefined reference to 'QSGTexture::qt_metacast(char const*)' armeabi-v7a/moc_gstqsgtexture.cpp:93: error: undefined reference to 'QSGTexture::qt_metacall(QMetaObject::Call, int, void**)' /home/reza/QtProjects/GStreamerTest/gstreamer-1.0/armv7/lib/gstreamer-1.0/libgstqmlgl.a(moc_gstqsgtexture.o):moc_gstqsgtexture.cpp:GstQSGTexture::staticMetaObject: error: undefined reference to 'QSGTexture::staticMetaObject' /home/reza/QtProjects/GStreamerTest/gstreamer-1.0/armv7/lib/gstreamer-1.0/libgstqmlgl.a(moc_gstqsgtexture.o):moc_gstqsgtexture.cpp:vtable for GstQSGTexture: error: undefined reference to 'QSGTexture::normalizedTextureSubRect() const' /home/reza/QtProjects/GStreamerTest/gstreamer-1.0/armv7/lib/gstreamer-1.0/libgstqmlgl.a(moc_gstqsgtexture.o):moc_gstqsgtexture.cpp:vtable for GstQSGTexture: error: undefined reference to 'QSGTexture::isAtlasTexture() const' /home/reza/QtProjects/GStreamerTest/gstreamer-1.0/armv7/lib/gstreamer-1.0/libgstqmlgl.a(moc_gstqsgtexture.o):moc_gstqsgtexture.cpp:vtable for GstQSGTexture: error: undefined reference to 'QSGTexture::removedFromAtlas() const' /home/reza/QtProjects/GStreamerTest/gstreamer-1.0/armv7/lib/gstreamer-1.0/libgstqmlgl.a(moc_gstqsgtexture.o):moc_gstqsgtexture.cpp:typeinfo for GstQSGTexture: error: undefined reference to 'typeinfo for QSGTexture' clang++: error: linker command failed with exit code 1 (use -v to see invocation)
References
these are the usefull references that I found during my journay of working on this issue:
Guix: how to set package udev rules
Just read a thread on guix mailing list, about adding udev rules for a package. in order to have an fixed reference about it, I decided to post it here.
adding udev
rules for a guix package is as easy as adding it to the
<out>/lib/udev/rules.d/
directory. so we can either add it as an INSTALL
rule in our CMakefile.txt
or add it to manually install the rules as part of
our package install
phase:
(define-public package-name (package ... (arguments `(#:phases (modify-phases %standard-phases (add-after 'unpack 'patch-udev-rules (lambda* (#:key outputs #:allow-other-keys) (let ((out (assoc-ref outputs "out"))) (substitute* "CMakefile.txt" (("/ib/udev/rules.d") (string-append out "/lib/udev/rules.d"))) #t)))))) ...))
(define-public package-name (package ... (arguments `(#:phases (modify-phases %standard-phases (add-after 'install 'install-udev-rules (lambda* (#:key outputs #:allow-other-keys) (let ((out (assoc-ref outputs "out"))) (mkdir-p (string-append out "/lib/udev/rules.d")) (copy-file "123-my-custom-udev.rules" (string-append out "/lib/udev/rules.d/" "123-my-custom-udev.rules")) #t)))))) ... ))
New Start
After a while finally I decided to restore back my personal blog, writting down challenges I'm facing with, during my daily work. this time I decided to write in English, might be more useful for the ones who might face same issues.
One of the challenges that I faced was to choose a proper platform to build my blog on top of. using blog services like Blogger or Wordpress previously they seemd to be kind of over-qualified for my needs. so I decided to switch to static blog generators this time.
It's been a while that I'm using GNU Guix on my work and it was an opportunity for me to use GNU Emacs as my common text editor and IDE. working more with Emacs, I love this editor much more.

Since for each problem you face, Emacs provides you a solution, it also has a solution for my blogging Problem, Org Mode. search for Emacs blogging tools, there are a bunch of packages already available, and since I was looking for a simple tool to allow me setup my blog rapidly, I decided to use org-static-blog.
In order to setup my blog, I just need to add an initial configuration to my
init.el
file, create new post using org-static-blog-create-new-post
and run
org-static-blog-publish
to generate html files. after that the only thing that
I need to do was to publish generated files to github pages.