Stéphane Cerveau
September 16, 2021
Reading time:
Note: In September 2021, the GStreamer project merged all its git repositories into a single, unified repository, often called monorepo
. The build system referred in this post as "gst-build" is now in the root of this combined/mono repository.
GStreamer is a powerful multimedia framework with over 30 libraries and more than 1600 elements in 230 plugins providing a wide variety of functionality. This makes it possible to build a huge variety of applications, however it also makes it tricky to ship in a constrained device. Luckily, most applications only use a subset of this functionality, and up until now there wasn't an easy way to generate a build with just enough GStreamer for a specific application.
Thanks to a partnership with Huawei, you can now use gst-build to generate a minimal GStreamer build, tailored to a specific application, or set of applications. In this blog post, we'll look at the major changes that have been introduced in GStreamer to make this possible, and provide a small example of what can be achieved with minimal, custom builds.
gst-build is the build system that GStreamer developers use. In previous posts, we described how to get started on Linux or Windows and how to use it as a daily development tool.
Since GStreamer 1.18, it is possible to build all of GStreamer into a single shared library called gstreamer-full. This library can include not only GStreamer's numerous libraries, but also all the plugins and other GStreamer dependencies such as a GLib. Applications can then either dynamically or statically link with gstreamer-full.
By providing -Ddefault_library=static -Dintrospection=disabled
to the Meson configure command line, it will generate a static build of all the GStreamer libraries which support the static scheme. This will also produce a shared library called gstreamer-full containing all of GStreamer. For now the GObject introspection needs to be disabled as the static build is not ready to support it (see gst-build-167).
Generating a combined library doesn't by itself reduce the total size. To achieve this goal, we need to select which libraries and plugins are included.
gst-build is a highly configurable build system that already provides options to select which plugins are built. But using the gstreamer-full mechanism, one can select exactly which libraries are included in the final gstreamer-full library by passing the -Dgst-full-libraries=
argument to meson. The plugins are then automatically included according to the configuration and the dependencies available.
Lets have an example:
$ meson build-gst-full \ --buildtype=release \ --strip \ --default-library=static \ --wrap-mode=forcefallback \ -Dauto_features=disabled \ -Dgst-full-libraries=app,video,player \ -Dbase=enabled \ -Dgood=enabled \ -Dbad=enabled \ -Dgst-plugins-base:typefind=enabled \ -Dgst-plugins-base:app=enabled \ -Dgst-plugins-base:playback=enabled \ -Dgst-plugins-base:volume=enabled \ -Dgst-plugins-base:videoconvert=enabled \ -Dgst-plugins-base:audioconvert=enabled \ -Dgst-plugins-good:audioparsers=enabled \ -Dgst-plugins-good:isomp4=enabled \ -Dgst-plugins-good:deinterlace=enabled \ -Dgst-plugins-good:audiofx=enabled \ -Dgst-plugins-bad:videoparsers=enabled
In this example, we generate a gstreamer-full library using only the feature we explicitly specify. The first step to do that is to disable the automatic selection of features based on which dependencies are already installed (-Dauto_features=disabled
). Then we explictly enable the features of each subpackage that we want (ie -Dgst-plugins-base:typefind=enabled -Dgst-plugins-base:app=enabled
) and we use -Dgst-full-libraries=app,video,player
to tell gst-build to bundle and expose only those specific libraries (app, video, player) in gstreamer-full. We also force meson to build as many dependencies itself by using the fallback with (--wrap-mode=forcefallback
), this way, those dependencies will be included in the gstreamer-full library.
In our collaboration with Huawei, we decided to push further the idea of tailoring GStreamer to increase the granuality beyond the plugin to be able to select individual element or other features inside each plugin.
GStreamer plugins contain different kind of features. The most common type of plugin features are elements, but you can select other type of loadable features such as device provider, typefind and dynamic-type. For example, the ALSA plugin includes a device provider and various elements such as alsasrc
and alsasink
.
One key goal of the project was to be able to build only the features needed, reducing the binary file size. For example if the user selects only one element such as flacparse
from the audioparsers
plugin, the code used by the other parsers should not be included in the final binary.
Note that for now, this project has been focused on Linux platforms and has not been tested on other platforms such as Windows or macOS.
We first experimented with the linker option to garbage collect sections (--gc-sections
). This option removes code sections which are not used by any part of the final program, except the public library methods. With the standard compiler options, there is normally a section per C source file, but using the -ffunction-sections
and -fdata-sections
compiler options, the compiler will generate one section per function and per data symbol.
But according to the documention, this feature must be used with care as it can bring an overhead of code if no sections can be garbage-collected and also because of incompatibility with debugger and slowness ( See -fdata-sections
comment in gcc man page).
As GStreamer is a very widely used project, we decided to avoid this solution as it could possibly lead to inconsistent results.
Instead of creating new sections automatically, we decided to play with linker rules. The linker (ld) already only pulls in object files if they are called by other objects. So this has the effect of entirely omitting any code that isn't used by the current program.
Up until now, every plugin had a function that would call the registration function for each feature present in the plugin. This function is called when the plugin is loaded. This plugin initialization function was the only one in each plugin with a predictable name. To be able to select plugins, we needed to expose a registration function for each feature. We were very careful to put these in the same file where the feature is implemented.
The plugin initialization function is now in its own file that can be ignored when linking features one by one. This work required modifying every single GStreamer plugin. A registration method has been declared through a set of macro for each of feature available in GStreamer official repositories.
To declare an element, you should use the macro GST_ELEMENT_REGISTER_DEFINE(element, "name", TANK, GST_TYPE)
. From any plugin you can register the element calling GST_ELEMENT_REGISTER(element, plugin)
.
The final part of this work was to create a "static" plugin in gstreamer-full which will contain all the features (element etc.) selected by the gst-build configure with -Dgst-full-elements=
.
With these in place, all the features which are not selected don't get included.
Five new options have been added to gst-build:
plugin1:elt1,elt2;plugin2:elt1
formatplugin1:tf1,tf2;plugin2:tf1
formatplugin1:dp1,;dp2;plugin2:dp1
formatplugin1:dt1,;dt2;plugin2:dt1
formatYou can find more information about the work achieved in the gst-build-199 merge request.
Let's start with a default build with all features and get some metrics to see the benefits. The gstreamer-full library will embed as much as possible its external dependencies such as glib
. Plugin dependencies will be kept dynamic but as soon as we'll select one or another plugin/feature, the dependency will be removed.
The build has been performed using an official GStreamer Fedora Docker image.
$ docker pull registry.freedesktop.org/gstreamer/gst-plugins-bad/amd64/fedora:2021-03-30.0-master
$ meson build-gst-full \ -Ddefault_library=static \ -Dintrospection=disabled \ --buildtype=release \ --strip \ --wrap-mode=forcefallback $ ninja -C build-gst-full
After a successful build, we can reconfigure the last gstreamer-full by providing new options to the meson comamnd line through --reconfigure
. In this use-case, we'll enable only 3 elements from the coreelements plugin in GStreamer.
$ meson build-gst-full --reconfigure -Dgst-full-plugins=coreelements '-Dgst-full-elements=coreelements:filesrc,fakesink,identity' '-Dgst-full-libraries=[]' $ ninja -C build-gst-full
In this example we are first passing the plugin(s) you'd like to enable, coreelements
and then passing the elements we'd like to include filesrc
, etc. We remove all additional GST libraries except the core library.
lib (stripped) | default | tailored |
---|---|---|
ligstreamer-full.so | 49208656 (49.2 M) | 3250256 (3.2M) |
This library can now be used through its pkg-config as gstreamer-full file to build a custom GST application.
As a final touch, we have also added an option to provide gst-build with a linker script to select exactly what gets included in the final gstreamer-full library. With this linker script you are now able to drop all the public code which is not used by your application and keep only the necessary code. See gst-build-195
The option is: gst-full-version-script=path_to_version_script
Some interesting merge requests:
All this work is now available upstream (1.19.1) and should be available in the next 1.20 release of GStreamer.
As usual, if you would like to learn more about meson, gst-build or any other parts of GStreamer, please contact us!
20/12/2024
The Rockchip RK3588 upstream support has progressed a lot over the last few years. As 2024 comes to a close, it is a great time to have…
09/12/2024
Collabora will be at NeurIPs this week to dive into the latest academic findings in machine learning and research advancements that are…
05/12/2024
Now based on Debian Bookworm, Apertis is a collaborative OS platform that includes an operating system, but also tools and cloud services…
Comments (4)
Akshay Pratap Singh:
Oct 18, 2021 at 12:53 PM
not able to build the complete pipeline , there are errors in webrtc. And even when building glib2.0. Can you point me to a stable commit / release ?
Reply to this comment
Reply to this comment
Stephane:
Oct 19, 2021 at 09:11 AM
Dear Akshay,
I think it would be better to discuss this topic on https://gitlab.freedesktop.org/gstreamer and see if we can improve the gstreamer-full build process. Please do not forget to describe your issue with your host/target, the command line and the logs. It will help to understand your problem.
Please feel free to post the issue URL here.
Regards.
Stéphane
Reply to this comment
Reply to this comment
Javad:
Sep 20, 2022 at 04:33 AM
Thanks a lot for this great help.
I successfully compiled and built the gstreamer.
I build the Helloword application with these instructions:
gcc basic-tutorial-1.c -o basic-tutorial-1 `pkg-config --cflags --libs gstreamer-1.0`
gcc basic-tutorial-1.c -o basic-tutorial-1 `pkg-config --cflags --libs gstreamer-1.0 --static`
However, when I try to run the binary application, it shows the following error:
0:00:00.012510410 119 0xc4bf00 ERROR GST_PIPELINE subprojects/gstreamer/gst/parse/grammar.y:850:priv_gst_parse_yyparse: no element "playbin"
Reply to this comment
Reply to this comment
XavierClaessens:
Sep 20, 2022 at 04:44 PM
Hi,
You should link your application against gstreamer-full-1.0. gstreamer-1.0 is only the core library with not plugins.
Reply to this comment
Reply to this comment
Add a Comment