Skip to content
December 22, 2017 / ftth

Gstreamer “delayed linking failed” with rtspsrc video and audio

Trying to use decodebin with a network camera, i was getting some “Delayed linking failed” errors, misled by some old mailing list responses like this one.

$ gst-launch-1.0 rtspsrc location=rtsp:// name=src src. ! decodebin ! audioconvert ! fakesink silent=false src. ! decodebin ! videoconvert ! fakesink silent=false
WARNING: from element /GstPipeline:pipeline0/GstDecodeBin:decodebin1: Delayed linking failed.
WARNING: from element /GstPipeline:pipeline0/GstDecodeBin:decodebin0: Delayed linking failed.

As ndufresnes pointed out, decodebin may just receive audio or video without regards to downstream caps, which means that linking may or may not work depending on how rtspsrc created it’s caps.

The solution is to filter out by rtp caps, which will ensure that the correct type will get correctly linked:

gst-launch-1.0 rtspsrc location=rtsp:// name=src src. ! "application/x-rtp, media=(string)audio" ! decodebin ! audioconvert ! fakesink silent=false src. ! "application/x-rtp, media=(string)video" ! decodebin ! videoconvert ! fakesink silent=false

This will however obviously fail if the network source doesn’t provide any audio at all.

December 21, 2017 / ftth

terminator-compatible tmux quick pane switching

I was trying to use tmux from within terminator with improved keyboard shortcuts. Using tips from some useful resources, i added the following to ~/.tmux.conf, which was supposed to let me switch panes with a simple Alt+arrow

# switch panes using Alt-arrow without prefix
bind -n M-Left select-pane -L
bind -n M-Right select-pane -R
bind -n M-Up select-pane -U
bind -n M-Down select-pane -D

This didn’t work out as expected (nothing was happening), and the culprit was terminator itself which was already binding these for the same task (i.e. switching between panes). After fiddling a bit, i found that the Windows key + Alt combination was pretty much left available on Gnome / terminator:

# switch panes using Win-Alt arrow without prefix
bind -n M-115-Left select-pane -L
bind -n M-115-Right select-pane -R
bind -n M-115-Up select-pane -U
bind -n M-115-Down select-pane -D
December 17, 2017 / ftth

Purging librelec databases

My Pi2 powered Librelec had a music library with ~2000 albums, which was making the Yastse android kodi remote take litterally 60 minutes to refresh in the background (happily draining the battery along the way).

I needed to purge the complete audio database, and rely on directory browsing instead to launch music.

To do this, log into your librelect device, and remove the culprit db file(s):

# ls -l ~/.kodi/userdata/Database
# ls -lh
total 47309
-rw-r--r-- 1 root root 28.0K May 14 2017 ADSP0.db
-rw-r--r-- 1 root root 1.3M Dec 17 09:31 Addons27.db
drwxr-xr-x 2 root root 1.0K May 14 2017 CDDB
-rw-r--r-- 1 root root 28.0K May 14 2017 Epg11.db
-rw-r--r-- 1 root root 43.9M Dec 17 09:23 MyMusic60.db
-rw-r--r-- 1 root root 424.0K Dec 14 23:02 MyVideos107.db
-rw-r--r-- 1 root root 32.0K May 14 2017 TV29.db
-rw-r--r-- 1 root root 432.0K Dec 17 08:42 Textures13.db
-rw-r--r-- 1 root root 20.0K May 14 2017 ViewModes6.db
# rm ~/.kodi/userdata/Database/MyMusic60.db

I guess these 43 Mb of data were just too much for this little Pi2.

After a reboot, the library should have been emptied.

November 14, 2017 / ftth

Setting up a gst_uninstalled environment with gst-build

I used to follow Arun’s QuickStart guide to setup gst-uninstalled environments easily, but this left quite a lot of manual tasks. It is now possible to make it much faster and easier thanks to gst-build, which

  1. uses meson/ninja instead of autotools (much faster)
  2. replaces both and scripts
  3. includes built-in support for python and newer projects like gstreamer-vaapi

After installing the required dependencies (meson, ninja), it’s a few lines of commands to have a complete environment usable (not to mention that it is much, much faster and automated):

Updating and rebuilding is a simple (from the main gst-build directory, not from build/):

ninja -C build/ update

To use the gst-uninstalled environment to run any program:

/home/myuser/gst-build/ gst-launch-1.0 videotestsrc ! fakesink

To build without debug options enabled (may improve performance in some cases):

meson --buildtype=debugoptimized -Denable_python=true -Ddisable_gstreamer_sharp=true -Ddisable_rtsp_server=true -Ddisable_gst_editing_services=true build

If you are using Ubuntu 16.04, you will need the following packages:

apt-get install python3-pip ninja-build pkg-config gobject-introspection gnome-devel bison flex libgirepository1.0-dev liborc-0.4-dev
pip install meson
November 10, 2017 / ftth

Software raid check killing Ubuntu 16.04 servers

While investigating why our automated on-site Q&A tests would fail once per month (http timeouts, etc…), indicating heavy load, i eventually discovered that it happened while the monthly raid array check was running, and found out that Ubuntu 16.04 ships

  • with the deadline i/o scheduler by default (cat /sys/block/sda/queue/scheduler)
  • a monthly software raid check (launched by /etc/cron.d/mdadm) which runs /usr/share/mdadm/checkarray with the –idle argument (which uses ionice)

From /usr/share/mdadm/checkarray:

# queue request for the array. The kernel will make sure that these requests
# are properly queued so as to not kill one of the array.
echo $action > $MDBASE/sync_action
[ $quiet -lt 1 ] && echo "$PROGNAME: I: check queued for array $array." >&2

case "$ionice" in
 idle) ioarg='-c3'; renice=15;;
 low) ioarg='-c2 -n7'; renice=5;;
 high) ioarg='-c2 -n0'; renice=0;;
 realtime) ioarg='-c1 -n4'; renice=-5;;
 *) break;;

resync_pid= wait=5
while [ $wait -gt 0 ]; do
 wait=$((wait - 1))
 resync_pid=$(ps -ef | awk -v dev=$array 'BEGIN { pattern = "^\\[" dev "_resync]$" } $8 ~ pattern { print $2 }')
 if [ -n "$resync_pid" ]; then
 [ $quiet -lt 1 ] && echo "$PROGNAME: I: selecting $ionice I/O scheduling class and $renice niceness for resync of $array." >&2
 ionice -p "$resync_pid" $ioarg || :
 renice -n $renice -p "$resync_pid" 1>/dev/null || :
 sleep 1

However, since the deadline i/o scheduler does ignore ionice, even though the –idle argument is passed, the raid check (which is very long) will just not run with a low i/o priority…

The most incredible part is how undocumented this all is…

October 6, 2017 / ftth

Generating multichannel audio samples from gstreamer using AudioChannelPosition in Python

For test purposes it can be useful to generate samples with multiple audio channels, with a different sound per channel to identify it easily. This is something that can be achieved with the audiointerleave plugin, but defining the channel-positions property cannot be done on the command-line.

My goal was to generate a tone of specific frequency for each channel (for a given target channel count), then feed it to a target channel encoded with aac (using fdkaacenc) and save it as m4a file.

The supported channel configuration were found in the fdkaacenc source code. Note that 8 channels does not seem to be supported with the current version of fdk-aac included in gstreamer (8 channels seems to require v0.1.4).

I didn’t find any available example program explaining how to achieve this in python, so i’m sharing it:

Opening one of the m4a file with audacity shows that each channel got a different sound:

Capture d'écran de 2017-10-06 18-29-19

Interestingly, one can see that LFE channel is filtering the input (applying a low pass filter), which makes sense since LFE is for the subwoofer.

September 26, 2017 / ftth

Gstreamer/python: ‘Iterator’ object is not iterable error

While working on a python gstreamer program (through gobject introspection bindings), i encountered the following error (which was a bit confusing) when trying to iterate over all elements inside a pipeline :

python /tmp/ 
Traceback (most recent call last):
 File "/tmp/", line 14, in iterate
 for e in p.iterate_elements():
TypeError: 'Iterator' object is not iterable

The reason is that the bindings generated by gobject-introspection do not map the Gst.Iterator object returned by the method iterate_elements() to a python iterator.

Here is  a test program:

import gi
gi.require_version("Gst", "1.0")
from gi.repository import GObject, Gst, GLib

pipeline = "videotestsrc is-live=true ! queue ! fakesink"

p = Gst.parse_launch(pipeline)

def iterate():
    for e in p.iterate_elements():

ml = GObject.MainLoop()

This can be fixed by installing gst-python which overrides the auto-generated bindings, among other things adding the __iter__ method on top of the Gst.Iterator object to fix native python iteration.