Table of Contents

AES67 Audio Network

AES67 ist ein offener Standard für ein Audio-Netzwerk, ähnlich zu Dante. Technisch sind AES67 und Dante sehr nahe beieinander.

In AES67 werden (bis zu?) 8 Audio-Kanäle im L24 (“24-bit Linear Sampled Audio”, https://tools.ietf.org/html/rfc3190) Format mit 48000 Samples/s via Multicast-RTP übertragen.

Parallel dazu wird eine System-Clock im PTP-Protokoll benutzt (https://en.wikipedia.org/wiki/Precision_Time_Protocol).

AES67 mit GStreamer empfangen

Für unsere Anwendungsfälle (Audio nur empfangen, keine Wiedergabe) ist es nicht unbedingt nötig, PTP zu implementieren. Man kann die Daten einfach so schnell verarbeiten, wie sie reinkommen.

Beim experimentieren habe ich festgestellt, dass sich die Hardware-AES67-Sender in diesem Fall anders verhalten als die meisten VirtualSoundcards. Die RTP-Pakete der Hardware-Sender enthalten keine Zeitstempel-Angaben. Daher ist auch die Empfangspipeline leicht anders. Ich vermute, dass dieser Unterschied verschwinden würde, wenn wir PTP korrekt implementieren würden.

Basis-Empfangspipeline für Hardware-Sender

Eine Einfache GStreamer-Pipeline zum Empfang von AES67 von Hardware-Controllern schaut so aus:

gst-launch-1.0 udpsrc multicast-iface=enp0s25.2342 address=239.192.42.42 port=5004 !\
	application/x-rtp, clock-rate=48000, channels=8 !\
	rtpL24depay !\
	audioconvert !\
	wavenc !\
	filesink location=/tmp/lala.wav

Basis-Empfangspipeline für Software-Sender

Die beiden VirtualSoundcards die ich getestet habe, übermitteln in ihren RTP-Paketen Zeitstempel mit. In der GStreamer-Pipeline muss dann ein rtpjitterbuffer-Element hinzugefügt werden, welches GStreamer erlaubt den Netzwerk-Jitter auszugleichen:

gst-launch-1.0 udpsrc multicast-iface=enp0s25.2342 address=239.192.42.42 port=5004 !\
	application/x-rtp, clock-rate=48000, channels=8 !\
	rtpjitterbuffer latency=2000 !\
	rtpL24depay !\
	audioconvert !\
	wavenc !\
	filesink location=/tmp/lala.wav

Warning: Sowohl die Lösung mit jitterbuffer als auch die ohne funktionieren nur, weil es uns eigentlich fast egal ist, mit wie viel Verzögerung das Audio-Signal bei uns ankommt. Für jeder Art von Live-Wiedergabe oder -Processing ist die Implementierung von PTP unumgänglich.

PTP

Es gibt eine fertige PTP-Implementierung für GStreamer, diese muss nur korrekt initialisiert und die Pipeline damit konfiguriert werden. Das geht nicht mit gst-launch-1.0 sondern nur mit einer Host-Applikation (z.B: in Python).

Die GStreamer PTP-Clock konnte sich nicht mit dem Nexus syncen, daher haben wir den 35C3 mit der internen Free-Running Clock gefahren.

Links:

WorkdClock

Da das Audio-Backup am Ende vor allem in Sync zum Video sein muss, wäre es vermutlich gut, es mit dem Video-Recording zu syncen.

13:52 <       MaZderMind > https://coaxion.net/blog/2014/12/improved-gstreamer-support-for-blackmagic-decklink-cards/
13:54 <       MaZderMind > man könnte voctomix über den reference-in der duo2 karten mit einer worldclock versehen
13:54 <       MaZderMind > vmtl. würde das sogar automatisch passieren, wenn wir da mal was dran stecken würden
13:55 <       MaZderMind > The clock of the hardware is now exposed to the pipeline as a GstClock and even if the pipeline chooses a different clock, the elements will slave their internal clock to the 
                           master clock of the pipeline and make sure that synchronization is even kept if the pipeline clock and the Decklink hardware clock are drifting apart. Thanks to GStreamer’s 
                           extensive synchronization model and all the 
13:55 <       MaZderMind > functionality that already exists in the GstClock class, this was much easier than it sounds.
13:56 <       MaZderMind > da die audio-backup-recorder auch eine decklink karte hatten würden die einfach die selbe clock bekommen und schon wäre alles schön in sync
13:56 <       MaZderMind > die decklink-karten können blackburst und trisync
13:57 <       MaZderMind > hhelenav Simpel ^
14:00 <       MaZderMind > jup, GstDecklinkClock ist verfügbar

AES67 Loudness-Meter

Für das Loudness-Meter in der ACR benutzen wir eine Pipeline aus drei Komponenten:

Das sieht dann ungefähr so aus:

gst-launch-1.0 -q udpsrc multicast-iface=enp0s25.2342 address=239.192.42.42 port=5004 !\
	application/x-rtp, clock-rate=48000, channels=2 !\
	rtpL24depay !\
	audioconvert !\
	wavenc !\
	fdsink |\
		/opt/ffmpeg-4.1-64bit-static/ffmpeg -y -nostdin -i - -filter_complex '
			[0] pan=2c|c0=c0|c1=c1, ebur128=video=1:target=-16:gauge=shortterm:scale=relative [v][a]
		' -map '[v]' -map '[a]' \
		-pix_fmt yuv420p -c:v rawvideo \
		-c:a pcm_s16le -f matroska - |\
			ffplay -v 0 -autoexit -exitonkeydown -exitonmousedown -window_title "ebur128 Loudness" -

Angepasst werden muss hier ebenfalls das Interface und die Multicast-Gruppe. Mit dem pan-Filter werden die beiden Kanäle aus den eingehenden 8 ausgewählt, die für die Loudness-Analyse verwendet werden. Um beispielsweise die Kanäle 4 und 5 (0123_45_67) benutzt werden, sieht der Filter so aus: pan=2c|c0=c4|c1=c5.