2024-11-20 15:44:54 +01:00
---
title:
- Multimedia using Rust and GStreamer
author:
- Sanchayan Maity
2024-11-21 07:51:53 +01:00
aspectratio:
- 169
fontsize:
- 14pt
papersize:
- "presentation-16-9"
2024-11-20 15:44:54 +01:00
---
2024-11-21 07:51:53 +01:00
## Who?
2024-11-20 15:44:54 +01:00
- Consultant Software Engineer @ [asymptotic ](https://asymptotic.io/ )
- Open source consulting firm based out of Toronto, Bangalore & Hyderabad
- Work on low level systems software centred around multimedia
- GStreamer, PipeWire, PulseAudio
- Embedded Systems background
- C, Rust and Haskell
- Organizing Rust and Haskell meetup Bangalore since 2018
2024-11-21 07:51:53 +01:00
## Agenda
2024-11-20 15:44:54 +01:00
- Introduction to GStreamer
- Why Rust
- Rust and GStreamer
2024-11-21 07:51:53 +01:00
## GStreamer
2024-11-20 15:44:54 +01:00
- Multiplatform Pipeline based multimedia framework
- Bindings for various languages
- Supported on Linux, macOS, Android and Windows
- Allows building complex media processing workflows
- Some applications
* GstLAL (gravitational wave data analysis)
* PiTiVi (Video Editor)
* amaroK, Banshee, Clementine (audio players)
* Empathy (VOIP and video conferencing)
* Rygel (DLNA streaming server and renderer)
* Showtime, Clapper, Totem (Media players for desktop)
2024-11-21 07:51:53 +01:00
## Simple pipeline
2024-11-20 15:44:54 +01:00
2024-11-21 07:51:53 +01:00
```bash
gst-launch-1.0 videotestsrc ! autovideosink
gst-launch-1.0 audiotestsrc ! autoaudiosink
2024-11-20 15:44:54 +01:00
```
2024-11-21 07:51:53 +01:00
## Media pipeline[^1]
2024-11-20 15:44:54 +01:00
![*_Simple Player_* ](simple-player.png ){width=80%}
[^1]: [Dynamic Pipelines ](https://gstreamer.freedesktop.org/documentation/tutorials/basic/dynamic-pipelines.html?gi-language=c )
2024-11-21 07:51:53 +01:00
## Playback pipeline
2024-11-20 15:44:54 +01:00
```bash
2024-11-21 07:51:53 +01:00
gst-play-1.0 https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_ts/master.m3u8
2024-11-20 15:44:54 +01:00
```
2024-11-21 07:51:53 +01:00
## Playback pipeline graph
2024-11-20 15:44:54 +01:00
![*_playbin HLS_* ](playbin-hls.svg )
2024-11-21 07:51:53 +01:00
## Custom elements
2024-11-20 15:44:54 +01:00
2024-11-21 07:51:53 +01:00
![*_Rounded Corners_* ](roundedcorners.jpg ){width=58%}
2024-11-20 15:44:54 +01:00
```bash
2024-11-21 07:51:53 +01:00
gst-launch-1.0 filesrc location=bunny.mp4 ! decodebin ! videoconvert ! roundedcorners border-radius-px=100 ! videoconvert ! gtksink
2024-11-20 15:44:54 +01:00
```
2024-11-21 07:51:53 +01:00
## Why Rust?
2024-11-20 15:44:54 +01:00
- Codec implementations in pure Rust (Rust Audio, Xiph AV1, Symphonia)
- Things we care about
* **Low cognitive overhead**
* Immutability
* Expressive type system
* Memory safety and concurrency
* Foreign Function Interface
2024-11-21 07:51:53 +01:00
## Why Rust?
2024-11-20 15:44:54 +01:00
2024-11-21 07:51:53 +01:00
- Bindings/abstractions over GLib/GObject and for GStreamer[^2]
2024-11-20 15:44:54 +01:00
- Provides a root for the object hierarchy tree filed in by the GStreamer library
- Gives basic reference counting, parenting functionality and locking.
- GObject
- GstObject
- GstAllocator
- GstBufferPool
- GstBus
- GstClock
- GstDevice
- GstDeviceMonitor
- GstDeviceProvider
- GstElement
- GstPad
[^2]: [GstObject ](https://gstreamer.freedesktop.org/documentation/gstreamer/gstobject.html?gi-language=c )
2024-11-21 07:51:53 +01:00
## Why immutability and types matter?
2024-11-20 15:44:54 +01:00
```c
let caps: gst::Caps = gst::Caps::builder("video/x-raw")
.field("width", crop_w)
.field("height", crop_h)
.field("pixel-aspect-ratio", gst::Fraction::new(1, 1))
.build();
let s = caps.remove_structure(0);
```
2024-11-21 07:51:53 +01:00
## Why immutability and types matter?
2024-11-20 15:44:54 +01:00
```bash
warning: unused variable: `s`
--> video-bin/src/imp.rs:152:13
|
152 | let s = caps.remove_structure(0);
| ^ help: if this is intentional, prefix it with an
underscore: `_s`
|
= note: `#[warn(unused_variables)]` on by default
error[E0596]: cannot borrow data in dereference of `gstreamer::Caps`
as mutable
--> video-bin/src/imp.rs:152:17
|
152 | let s = caps.remove_structure(0);
| ^^^^^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable
|
= help: trait `DerefMut` is required to modify through a dereference,
but it is not implemented for `gstreamer::Caps`
```
2024-11-21 07:51:53 +01:00
## Why immutability and types matter?
2024-11-20 15:44:54 +01:00
```c
let mut caps: gst::Caps = gst::Caps::builder("video/x-raw")
.field("width", crop_w)
.field("height", crop_h)
.field("pixel-aspect-ratio", gst::Fraction::new(1, 1))
.build();
let _s = caps.remove_structure(0);
```
2024-11-21 07:51:53 +01:00
## Why immutability and types matter?
2024-11-20 15:44:54 +01:00
```bash
warning: variable does not need to be mutable
--> video-bin/src/imp.rs:147:13
|
147 | let mut caps: gst::Caps = gst::Caps::builder("video/x-raw")
| ----^^^^
| |
| help: remove this `mut`
|
= note: `#[warn(unused_mut)]` on by default
error[E0596]: cannot borrow data in dereference of `gstreamer::Caps`
as mutable
--> video-bin/src/imp.rs:152:18
|
152 | let _s = caps.remove_structure(0);
| ^^^^^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable
= help: trait `DerefMut` is required to modify through a dereference,
but it is not implemented for `gstreamer::Caps`
```
2024-11-21 07:51:53 +01:00
## Why immutability and types matter?
2024-11-20 15:44:54 +01:00
```c
let caps: gst::Caps = gst::Caps::builder("video/x-raw")
.field("width", crop_w)
.field("height", crop_h)
.field("pixel-aspect-ratio", gst::Fraction::new(1, 1))
.build();
let caps = caps.get_mut().unwrap();
let _s = caps.remove_structure(0);
```
2024-11-21 07:51:53 +01:00
## Why immutability and types matter?
2024-11-20 15:44:54 +01:00
```bash
error[E0596]: cannot borrow `caps` as mutable, as it is not declared
as mutable
--> video-bin/src/imp.rs:152:20
|
147 | let caps: gst::Caps = gst::Caps::builder("video/x-raw")
| ---- help: consider changing this to be mutable:
`mut caps`
...
152 | let caps = caps.get_mut().unwrap();
| ^^^^^^^^^^^^^^ cannot borrow as mutable
For more information about this error, try `rustc --explain E0596` .
```
2024-11-21 07:51:53 +01:00
## Why immutability and types matter?
2024-11-20 15:44:54 +01:00
```c
let mut caps: gst::Caps = gst::Caps::builder("video/x-raw")
.field("width", crop_w)
.field("height", crop_h)
.field("pixel-aspect-ratio", gst::Fraction::new(1, 1))
.build();
if let Some(caps) = caps.get_mut() {
let _s = caps.remove_structure(0);
}
```
2024-11-21 07:51:53 +01:00
## GStreamer & Rust
2024-11-20 15:44:54 +01:00
- Some stats[^3]
- gstreamer-rs: ~2700 commits, gst-plugins-rs: ~2600 commits
- gstreamer-rs: ~85 contributors, gst-plugins-rs: ~110 contributors
- gst-plugins-rs: ~ +180k SLOC / -37k SLOC
- gst-plugins-rs: Overall 47 plugins, 149 elements
- In relation to the GStreamer monorepo
- 1.22 cycle: ~33% commits / MRs in Rust modules
- 1.24 cycle: ~25% commits / MRs in Rust modules
[^3]: [GStreamer & Rust: What has happened over the last 5 years ](https://gstconf.ubicast.tv/videos/gstreamer-rust-what-has-happened-over-the-last-5-years_f8qxhpuzi9/ )
2024-11-21 07:51:53 +01:00
## Resources
2024-11-20 15:44:54 +01:00
- [GObject subclassing in Rust ](https://www.youtube.com/watch?v=TSf3rVyv7c8 )
- [GStreamer bindings for Rust ](https://gitlab.freedesktop.org/gstreamer/gstreamer-rs )
- [Rust GStreamer Plugins ](https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs )
- [Using GStreamer ](https://www.youtube.com/watch?v=ZphadMGufY8 )
- [How to get started with GStreamer ](https://www.youtube.com/watch?v=OkOsm9FyzdM&t=2s )
- [GStreamer for your backend services ](https://asymptotic.io/blog/gstreamer-for-your-backend-services/ )
2024-11-21 07:51:53 +01:00
## Questions?
2024-11-20 15:44:54 +01:00
- Rust Bangalore
* Meetup: https://hasgeek.com/rustbangalore
* Telegram: t.me/RustIndia
- Reach out on
* email:
- me@sanchayanmaity.net
- sanchayan@asymptotic.io
- hello@asymptotic.io
* Mastodon: [sanchayanmaity.com ](https://sanchayanmaity.com/@sanchayan )
* Blog: [sanchayanmaity.net ](https://sanchayanmaity.net/ )