Developing Saraswati: Getting started with GStreamer bindings for Rust

Introduction

This describes a variant of GitHub - hiveeyes/saraswati: Saraswati is a robust, multi-channel audio recording, transmission and storage system using the GStreamer bindings for Rust by Sebastian ‘slomo’ Dröge, see also Oxidising GStreamer. Enjoy the ride ;].

Update

This has been paused in favor of the GStreamer Python bindings, so the development will continue at the description of an audio recorder with timestamping and chunking in Python again.

We have been able to produce working examples of gstreamer-rs-device-monitor.rs and gstreamer-rs-launch.rs the other day. They are working flawlessly on a Mac OS X desktop machine, so Linux shouldn’t be a problem either ;] (on Intel).

Now, we want to get a feeling if this would also work on a MIPS24K CPU of a LinkIt Smart 7688 SoC machine.

Platzhalter für die “rust-cross” Anleitung von Saraswati

Todo.

Hi @weef,

Exzellent, das kommt wie gerufen!

Könntest Du mal in einer freien Minute ausprobieren, ob diese Programme [1] auf Deinem MIPS Linux laufen? Vermutlich wird es noch nicht out of the box funktionieren, aber manchmal hat man ja Glück ;].

Damit Ihr wisst, was Ihr Euch da auf die Maschinen spielt, gibt es unter [2] die Quelltexte.

Merci schon im Voraus und viele Grüße!

[1] Index of /hiveeyes/rust/saraswati/stripped/
[2] https://github.com/hiveeyes/saraswati/tree/master/rust/src

Update

  • "qemu-mips gstreamer-rs-launch fakesrc ! fakesink" läuft jetzt bei mir im Qemu für MIPS - sehr schön! Es erzeugt zwar keine Ausgabe, dafür war es aber auch noch nicht vorgesehen. Die Tatsache, dass es sich nicht zerlegt, ist schonmal keine schlechte - ich bleibe vorsichtig optimistisch ;].
  • "qemu-mips gstreamer-rs-device-monitor" stürzt zwar ab, allerdings gibt Qemu wahrscheinlich auch wirklich kein sinnvolles Audiodevice her… ;]. Ich bin darauf gespannt, ob es auf echter Hardware läuft.
# Enumerate devices
$ qemu-mips gstreamer-rs-device-monitor
thread 'main' panicked at 'assertion failed: result.is_ok()', src/gstreamer-rs-device-monitor.rs:43:5

# Launch pipeline
$ qemu-mips gstreamer-rs-launch fakesrc ! fakesink
<LÄUFT>

# Nothing to see, move along
$ qemu-mips saraswati
Hello world

Ausblick

Die Adressierung ungültiger Geräte wie audiotestsrc oder audiotestsink führt auch hier zur Panikattacke (obviously):

$ qemu-mips gstreamer-rs-launch audiotestsrc ! autoaudiosink
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Error(Boxed { inner: ForeignOwned(0x760524d0) })', libcore/result.rs:945:5

Das Ziel wäre, diesen Zustand ordentlich abzufangen, um im Fehlerfall genauso eloquent wie das Original antworten zu können:

$ qemu-mips /usr/bin/gst-launch-1.0 audiotestsrc ! autoaudiosink
WARNING: erroneous pipeline: no element "autoaudiosink"

Auch im Erfolgsfall wäre noch Luft nach oben:

$ qemu-mips /usr/bin/gst-launch-1.0 fakesrc ! fakesink

Setting pipeline to PAUSED ...
Pipeline is PREROLLING ...
Pipeline is PREROLLED ...
Setting pipeline to PLAYING ...
New clock: GstSystemClock
^C
handling interrupt.
Interrupt: Stopping pipeline ...
Execution ended after 0:00:05.111362507
Setting pipeline to PAUSED ...
Setting pipeline to READY ...
Setting pipeline to NULL ...
Freeing pipeline ...

hm… tut noch nicht:

root@OpenWrt:/mnt/saraswati# ./gstreamer-rs-launch fakesrc ! fakesink
/bin/ash: ./gstreamer-rs-launch: not found
root@OpenWrt:/mnt/saraswati# file ./gstreamer-rs-launch
./gstreamer-rs-launch: ELF 32-bit MSB pie executable MIPS, MIPS32 rel2 version 1 (SYSV), dynamically linked, interpreter /lib/ld.so.1, for GNU/Linux 3.2.0, BuildID[sha1]=c92ac1ecfb7d575133da903814e0c107df06ac46, stripped
root@OpenWrt:/mnt/saraswati# ls -la /lib/ld*
lrwxrwxrwx    1 root     root             7 Jul 11 19:55 /lib/ld-musl-mips-sf.so.1 -> libc.so

Schade!

Ausführung von normalen Programmen unter OpenWrt

Ja, so will er das bei mir auch machen: Mit der "ash" wird die Ausführung nicht klappen! ;] Ähnliche Probleme hatte ich auch bei der Entwickung des procd-scripts für BERadio: "procd" wollte das Python Programm ebenfalls ständig mit der "ash" ausführen, "busybox" spielt dabei anscheinend auch eine Rolle.

Analyse

Derzeit sieht es bei mir folgendermaßen aus.

Ausführung

root@he_7688:~# /tmp/gstreamer-rs-launch fakesrc ! fakesink
/tmp/gstreamer-rs-launch: line 1: syntax error: unexpected "("

Scheinbar gibt es da ein Geheimnis bei OpenWrt, wie man normale Programme ausführen kann?

file

$ file busybox
busybox:             ELF 32-bit LSB executable,    MIPS, MIPS32 rel2 version 1 (SYSV), dynamically linked, interpreter /lib/ld-uClibc.so.0, corrupted section header size

$ file gstreamer-rs-launch
gstreamer-rs-launch: ELF 32-bit MSB shared object, MIPS, MIPS32 rel2 version 1 (SYSV), dynamically linked, interpreter /lib/ld.so.1, for GNU/Linux 3.2.0, BuildID[sha1]=c92ac1ecfb7d575133da903814e0c107df06ac46, with debug_info, not stripped

strace

"strace" sagt folgendes:

$ opkg install strace
$ strace /tmp/gstreamer-rs-launch
execve("/tmp/gstreamer-rs-launch", ["/tmp/gstreamer-rs-launch"], [/* 12 vars */]) = -1 ENOEXEC (Exec format error)
brk(0xa8c000)                           = 0xa8c000
write(2, "strace: exec: Exec format error\n", 32strace: exec: Exec format error
) = 32
exit_group(1)                           = ?
+++ exited with 1 +++

libc oder musl?

Ah, musl! Ich glaube ich habe gegen libc gebaut. Auf dem LinkIt von @einsiedlerkrebs scheint das aber die richtige Variante zu sein, nicht?:

root@he_7688:~# ls -l1 /lib/*musl*
ls: /lib/*musl*: No such file or directory
root@he_7688:~# ls -al /lib/*libc.*
lrwxrwxrwx  /lib/ld-uClibc.so.0 -> ld-uClibc-0.9.33.2.so
lrwxrwxrwx  /lib/libc.so.0 -> libuClibc-0.9.33.2.so

… macht mich stutzig. Da passt was nicht zusammen!

@weef kann die Anomalie bestätigen: Der MIPS24K des MediaTek MT7688 Chipsatzes läuft auf “little-endian”, also LSB. Ergo müssen wir für das “mipsel” Target kompilieren.

Leider hatte der Kernel darüber keine Auskunft gegeben, hier stand ganz klar "mips" ;]:

root@he_7688:~# uname -a
Linux he_7688 3.18.23 #5 Tue Sep 27 11:48:57 CEST 2016 mips GNU/Linux

Die per “mipsel” target erzeugte Datei

$ file saraswati
saraswati: ELF 32-bit LSB shared object, MIPS, MIPS32 rel2 version 1 (SYSV), dynamically linked, interpreter /lib/ld.so.1, for GNU/Linux 3.2.0, BuildID[sha1]=5c70eb8aca8b7d7e5c2e95f55af36cd801cf099a, with debug_info, not stripped

führt leider zu dem gleichen Ergebnis wie vorhin bei @weef, sie passt zwar nun zur Architektur, will aber trotzdem nicht ausgeführt werden

root@he_7688:~# ./tmp/saraswati
-ash: ./tmp/saraswati: not found

Vielleicht, weil sie als ELF 32-bit LSB shared object gar nicht ausführbar ist?

Vielleicht ist das auch alles in Ordnung so, da die erzeugten Binaries überhaupt nicht ausführbar sind:
https://github.com/rust-lang/cargo/issues/3670

sorry, übersehen: wir sind hier in staging, ich muß das garnicht als whisper machen… ;)

ich sehe schon wieder den Bezug zu /lib/ld.so.1 , steht die dort denn bei Dir auch bzw. gibt es einen link, der auf ne gültige (z.B. /lib/ld-uClibc.so.0 bei Rich) hinweist?
Und dann probier dochmal, wie angesprochen, das Teil testweise statisch zu linken, um herauszufinden, ob es überhaupt rennt. Könntest ja aus Platzgründen die dietlibc nehmen! 8)

Ja, Du hast völlig recht: Die Umgebung “https://github.com/japaric/cross” von Jorge Aparicio spielt vor allem im GNU libc Umfeld. Das habe ich mir auch erst erarbeiten müssen, sorry vielmals.

Rust selbst ist jedoch mit entsprechender Unterstützung z.B. für “musl” ab Werk ausgestattet:

$ rustc --print target-list | grep musl

aarch64-unknown-linux-musl
arm-unknown-linux-musleabi
arm-unknown-linux-musleabihf
armv5te-unknown-linux-musleabi
armv7-unknown-linux-musleabihf
i586-unknown-linux-musl
i686-unknown-linux-musl
mips-unknown-linux-musl
mipsel-unknown-linux-musl
x86_64-unknown-linux-musl

Ergo ist cross hier ein Holzweg und wir sollten uns an die Empfehlung halten, den Job “ganz normal” mit dem OpenWrt SDK zu erledigen. Da müssen wir dann “nur noch” die Rust Toolchain anflanschen, GitHub - japaric/rust-cross: Everything you need to know about cross compiling Rust programs! gibt ein wenig mehr darüber Auskunft (Achtung “deprecated” und leicht inkorrekte Informationen, aber vom gleichen Autor).

Leider nein, Unterstützung für die uClibc ist nirgendwo zu sehen, es ist also kein Wunder, dass die erzeugten Artefakte auf dem fraglichen Zielsystem nicht laufen ;].


Danke vielmals für Deine Nachforschungen!

Durch einen Beitrag bei
https://github.com/sdroege/gstreamer-rs/issues/130

zukünftig:

haben sich interessante Infos ergeben, u.a.