Writing GStreamer Applications in Rust

tl;dr: GStreamer bindings for Rust can be found here: https://github.com/sdroege/gstreamer-rs

In the last few months since RustFest in Kiev, I was working (as promised during Luis and my talk at the conference) on creating (mostly autogenerated) Rust bindings for GStreamer, with a nice API and properly integrating with gtk-rs and other software. But the main goal was to autogenerate as much as possible with the help of GObject-Introspection to keep the maintenance effort low, and re-use / have all kinds of infrastructure for GLib/GObject that already exists in the gtk-rs ecosystem.

There are already GStreamer bindings available, which hopefully can be replaced by this very soon.

Most of the time working on this in the last months was spent on making the code generator work well with GStreamer and add lots of missing features, and also add missing bits and pieces to the GLib/GObject bindings. That should all be in place now, and now at GUADEC, I had some time to finish the last pieces of the GStreamer core API. Every needed piece of the GStreamer core API should be covered now, and lots of pieces that are not needed very often. The code can currently be found here.

Example code

There currently is no real documentation available. The goal is the autogenerate this too, from the existing C documentation. But until then, the main GStreamer documentation like the Application Development Manual and Core API Reference should be helpful. Almost everything is mapping 1:1.

I’ve written some example applications though, which can be found in the same GIT repository.

GTK

The first example is a GTK application, using the gtkglsink (or gtksink if no GL support is available) GStreamer elements to show a test video in a GTK window and the current playback position in a GTK label below the video. It’s using the GLib event loop for handling GTK events (closing the window), timeouts (query position every few hundred ms) and handling the GStreamer messages (errors, etc.).

The code can be found here.

Tokio

The next example is using Tokio instead of the GLib event loop for handling the GStreamer messages. The same should also work with anything else working with future-rs. Tokio is a Rust library for asynchronous IO, based on Futures.

For this to work, a BusStream struct is defined that implements the Stream trait (from future-rs), and produces all messages that are available on the bus. Then this stream is passed to the Tokio Core (basically the event loop) and each message is handled from there.

The code can be found here.

Pipeline building, Pad Probes, Buffers, Events, Queries, …

Various other examples also exist.

There is one example that is dynamically building a pipeline with decodebin for decoding a file with audio and/or video.

Another example is building a minimal version (without any features other than creating a pipeline from a string and running it) of the gst-launch-1.0 tool. This is not using the GLib main loop for handling the GStreamer messages, but there is a slightly modified variant of the same example that uses the GLib main loop instead.

Yet another example is building a small pipeline with an audio test source, producing a 440Hz sine wave, and calculates the RMS of the audio. For this a pad probe is installed on the source pad of the audio source, and the samples of each buffer are analyzed.

And three last examples are showing how to work with queries and events, and a rather boring example that just uses playbin.

What next?

Overall I have to say that using the bindings is already much more convenient and fun than to write any GStreamer code in C. So if you’re thinking of writing a new GStreamer application and would consider Rust for that: I can highly recommend that 🙂

So what comes next. First of all, the next steps would be to make sure that the bindings work for everybody. So if you are using the old bindings, or if you want to use GStreamer from Rust, now is a good time to start testing and let me know of any problems, any inconveniences, anything that seems ugly, or anything that is still missing but you need it.

In the meantime I’m going to make the bindings a full replacement of the old ones. For this various non-core GStreamer libraries have to be added too: gstreamer-app, gstreamer-video, gstreamer-audio and gstreamer-pbutils. Hopefully this can all be done over the next few weeks, but at this point all API that is needed to use GStreamer is already available. Only some convenience/helper API is missing.

And of course my efforts to make it easy to write GStreamer plugins in Rust didn’t end yet. I’ll continue working on that, and will also move all that over to these bindings too to remove a lot of code duplication.