Skip to content
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 create-uninstalled-setup.sh and git-update.sh 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-uninstalled.py gst-launch-1.0 videotestsrc ! fakesink

 

Advertisements
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;;
esac

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 || :
 break
 fi
 sleep 1
done

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/test.py 
Traceback (most recent call last):
 File "/tmp/test.py", 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
Gst.init(None)

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

p = Gst.parse_launch(pipeline)

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

GObject.idle_add(iterate)
ml = GObject.MainLoop()
ml.run()

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.

July 21, 2017 / ftth

Chromium opening folders with Audacious on Arch

When installing audacious on Arch linux, trying to locate a downloaded file in the file manager will open the audacious music player.

This happens because the audacious.desktop file provided by the upstream source package does register the “inode/directory” mime type. The mime apps specs state that if multiple apps register the same mime type, the opener app (e.g. xdg-open, as used by Chromium or Firefox) will use the first found (in that case, audacious, probably because of the alphabetical sort).

This can be checked by running

$ xdg-mime query default inode/directory
audacious.desktop

To fix this, you can add the following to /etc/xdg/mimeapps.list (as described in the Arch wiki):

[Default Applications]
inode/directory=org.gnome.Nautilus.desktop

From now on, nautilus will open folders by default:

$ xdg-mime query default inode/directory
org.gnome.Nautilus.desktop
July 4, 2017 / ftth

Displaying a host IP pre-logon on Arch

Sometimes it’s useful to be able to determine a system’s IP address directly from the terminal, prior to logon.

To do that, you can create a dedicated systemd unit file (e.g. /lib/systemd/system/display_ip_on_logon.service):

[Unit]
Description=Update /etc/issue with ip address
After=network.target

[Service]
ExecStart=/usr/local/bin/update_etc_issue

[Install]
WantedBy=multi-user.target

The script would be pretty straightforward:

#!/bin/bash#
while true
    do IP=$(/sbin/ip route get 1 | cut -d " " -f7)
    printf "ubicast mediacoder $HOSTNAME $IP\n\n" > /etc/issue
    sleep 30
done

That way, when connecting a display to the system, just type any key on the keyboard and the logon banner will show the host IP.

Do not forget to:

systemctl daemon-reload
systemctl enable display_ip_on_logon.service
systemctl start display_ip_on_logon.service
July 1, 2017 / ftth

Running pulseaudio system-wide with pacmd on Arch

While pulseaudio is, by default, run for each user session (socket-activated, or manually started with systemctl –user start pulseaudio), some scenarios can require having an always-running, system-wide pulseaudio instance. The official documentation on freedesktop.org describes how to achieve that and the drawbacks it implies.

Below are the instructions that worked for me on Arch (July 2017).

1. Create the systemd unit file

Put this in e.g. /usr/lib/systemd/system/pulseaudio.service

[Unit]
Description=PulseAudio system server

[Service]
ExecStart=/usr/bin/pulseaudio --system --disallow-exit --log-target=journal
#ExecStart=/usr/bin/pulseaudio --system --disallow-exit --disallow-module-loading --log-target=journal
ExecReload=/bin/kill -HUP $MAINPID

[Install]
WantedBy=multi-user.target

2. Create a dbus policy file

Put this in /usr/share/dbus-1/system.d; note that a reboot is required (or you can also try systemctl restart dbus && systemctl restart polkit && systemctl restart systemd-logind) :

<?xml version="1.0"?> <!--*-nxml-*-->
<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
 "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>
    <policy group="pulse">
        <allow own="org.pulseaudio.Server"/>
    </policy>

    <policy context="default">
        <allow send_destination="org.pulseaudio.Server"/>
        <allow receive_sender="org.pulseaudio.Server"/>
    </policy>
</busconfig>

3. Create the users and groups

Since the daemon will not be run by users anymore, it needs it’s own user and groups.

groupadd --system pulse
groupadd --system pulse-access
useradd --system -g pulse -G audio -d /var/run/pulse -m pulse
usermod -G video,wheel,pulse-access myuser
echo "default-server = /var/run/pulse/native" >> /etc/pulse/client.conf
echo "autospawn = no" >> /etc/pulse/client.conf
systemctl daemon-reload
systemctl enable pulseaudio
systemctl start pulseaudio

At this point, pulseaudio should work already (try gst-launch pulsesrc ! fakesink -v to check).

4. Enable –disallow-module-loading

The official documentation states: “If the system-wide mode is enabled it is advisable to disable module loading during runtime by passing –disallow-module-loading to the daemon, to inhibit the user from loading arbitrary modules with potentially vulnerable code into the daemon. However, this might break some modules like module-hal-detect which will load a sound driver module each time HAL signals that a new sound card became available in the system.”

I first tried to run with –disallow-module-loading, and the alsa configuration was messed up; even aplay -l or arecord -l were failing. The trick seems to be to add –disallow-module-loading only after a first successful use.

5. Disable –disallow-module-loading to use pacmd

This was the hardest to figure out: if you want pacmd to work, you cannot run pulseaudio with –disallow-module-loading (which is recommended by the official documentation), or you will get:

$ sudo PULSE_RUNTIME_PATH=/var/run/pulse -u pulse pacmd
Daemon not responding.

As long as –disallow-module-loading is not in the ExecStart line of the systemd unit file, pacmd will work using:

sudo PULSE_RUNTIME_PATH=/var/run/pulse -u pulse pacmd

It is recommended, once the /etc/pulse/system.pa finalized, to re-add the –disallow-module-loading switch.