Outils pour utilisateurs

Outils du site

Panneau latéral




Ham Radio






XPiMC (Collected pointers on running XBMC on a Raspberry PI)

Flint's the name.

  • Board: Model B rev 2 (rev 1 is a bit tight on memory with real libraries)
  • Base image: RaspBian (2012-09-18)

Initial setup

Disable overscan

Overscan seems enabled by default to accomodate analog video. With an HDMI screen, it mostly creates black bars, and needs to be disabled (this can be done through raspi-config too).


Use Analog Output with HDMI Video

With an HDMI-to-DVI adapter, we cannot get the sound along the same path, so it needs to be taken out of the analog output. Fortunately, this is easily done.

$ sudo amixer cset numid=3 1 # 0=auto, 1=analog, 2=hdmi

This goes nicely in /etc/rc.local to be enabled on every boot.


Choosing the right version

Though most XBMC packages are available in the native repository, xbmc-bin is crucially missing, as it is not packaged for ARM by Debian yet. The deb-multimedia repo has some binaries, but these require an accelerated X11 driver which while in development is not quite there yet.

Fortunately, there is an official XBMC port (xbmc-rbp) which supports VideoCore (which drivers are otherwise available as a large blob).

:!: For the latest, non rbp, revisions of the XBMC source code, some dependencies need to be upgraded which are not available in Raspbian yet. This is notably the case for taglib and libshairport (that link also have a ready-to-use XBMC package).

Building xbmc-rbp

We follow the documentation to build it for RaspBian. However, we avoid duplicating headers files by symlinking them instead of copying them.

pi@raspberrypi ~ $ for file in /opt/vc/include/*; do sudo ln -s $file /usr/include; done
pi@raspberrypi ~ $ for file in /opt/vc/include/interface/vcos/pthreads/*; do sudo ln -s $file /usr/include/interface/vcos; done

We also –enable-nfs for good measure (this requires the libnfs-dev package to be installed, and change the –prefix to /opt/xbmc to avoid conflicts with APT-managed packages.

Building XBMC successfully might require dropping back to console and killing unnecessary services to free up as much RAM as possible, and remove some standard MESA headers so the proprietary ones are picked up.

pi@raspberrypi ~/xbmc-rbp $ sudo apt-get remove libegl1-mesa-dev libgl1-mesa-dev libgles2-mesa-dev

This also uninstalled libsdl1.2-dev, and libsdl-image1.2-dev, which is needed for later steps of the compilation (reinstalling libgl1-mesa-dev and libglu1-mesa-dev). :?: It is not clear whether this is actually necessary, or whether I botched my installation, as I somehow managed to temporarily lose my headers in /opt/vc/include, which might have been the real cause. The real solution was to restore these. :!: Yep, after having reinstalled the SDL headers, and its dependencies, it still builds successfully.

Compilation also tends to fail when building libsquish. It is due to the Makefile not being selective enough with respect to which platform to compile with SSE2 support. ARM do not support SSE, and the -DSQUISH_USE_SSE=2 -msse2 should simply be removed from lib/libsquish/Makefile.in in the non osx part of the conditional invoking g++.

Eventually, the compilation succeeds, and a make install puts everything where it needs to be. The binary to start is /opt/xbmc/lib/xbmc/xbmc.bin. For simplicity's, we symlink it into /usr/bin.

pi@raspberrypi ~ $ sudo ln -s /opt/xbmc/lib/xbmc/xbmc.bin /usr/bin/xbmc

Starting XBMC

In the compilation-mode memory layout (224 MiB for the system), XBMC does not seem to start properly (the binary starts fine, but it only creates a black screen.) Using the most memory (128 MiB) for the GPU solves this problem, and XBMC does not even need to be started as root. It can play fullscreen and without stutter a DivX loaded from an NFS mount over the 100MBps ethernet interface.

The final touch resides in creating and enabling an init script to start XBMC on boot!

#! /bin/sh
# Provides:          xbmc
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Start the XBMC Media Centre
# Description:       Start the non-X11 dependent XBMC Media Centre
# Author: Olivier Mehani <shtrom-xbmc@ssji.net>
# Do NOT "set -e"
# PATH should only include /usr/* if it runs after the mountnfs.sh script
DESC="XBMC Media Centre"
DAEMON=/usr/bin/$NAME # This assume /opt/lib/xbmc/xbmc.bin is symlinked to /usr/bin/xbmc
# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0
# Read configuration variable file if it is present
[ -r /etc/default/$NAME ] && . /etc/default/$NAME
# Load the VERBOSE setting and other rcS variables
. /lib/init/vars.sh
# Define LSB log_* functions.
# Depend on lsb-base (>= 3.2-14) to ensure that this file is present
# and status_of_proc is working.
. /lib/lsb/init-functions
# Function that starts the daemon/service
        # Return
        #   0 if daemon has been started
        #   1 if daemon was already running
        #   2 if daemon could not be started
        start-stop-daemon --start --quiet --pidfile $PIDFILE ${USER:+-c $USER} --exec $DAEMON --test > /dev/null \
                || return 1
        start-stop-daemon --start --quiet --pidfile $PIDFILE ${USER:+-c $USER} --make-pidfile --background --exec $DAEMON -- \
                $DAEMON_ARGS \
                || return 2
# Function that stops the daemon/service
        # Return
        #   0 if daemon has been stopped
        #   1 if daemon was already stopped
        #   2 if daemon could not be stopped
        #   other if a failure occurred
        start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME
        [ "$RETVAL" = 2 ] && return 2
        start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
        [ "$?" = 2 ] && return 2
        rm -f $PIDFILE
        return "$RETVAL"
case "$1" in
        [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
        case "$?" in
                0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
                2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
        [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
        case "$?" in
                0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
                2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
        status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
        log_daemon_msg "Restarting $DESC" "$NAME"
        case "$?" in
                case "$?" in
                        0) log_end_msg 0 ;;
                        1) log_end_msg 1 ;; # Old process is still running
                        *) log_end_msg 1 ;; # Failed to start
                # Failed to stop
                log_end_msg 1
        echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2
        exit 3

Note the USER variable, which should be set, if needed, in /etc/default/xbmc if the start-stop-daemon(8) is to change user (and group if specified after a colon) before starting XBMC.

pi@raspberrypi ~ $ sudo update-rc.d xbmc defaults


When starting XBMC, it sometimes happens taht the screen is blanked, and nothing more happens. Inspecting the logs might show the following.

pi@raspberrypi $ tail -n 5 ~/.xbmc/temp/xbmc.log
16:41:41 T:1102987824   ERROR: EGL failed to initialize
16:41:41 T:1102987824  NOTICE: EGL not configured correctly. Let's try to do that now...
16:41:41 T:1102987824   ERROR: EGL failed to initialize
16:41:41 T:1102987824   ERROR: EGL not configured correctly to create a surface
16:41:41 T:1102987824   FATAL: CApplication::Create: Unable to create window

This problem seems to be due to the standard GL and EGL libraries being picked up by the linker rather than the specific VideoCore-related ones. Parst of the build process consisted in symlinking the latter over the former but, for same reason (quite probably various apt-get-related things), some of the links get overwritten back. This can be checked as follows.

pi@raspberrypi ~ $ ls -l /usr/lib/arm-linux-gnueabihf/lib{E,}GL{ESv2,}.so*
ls: cannot access /usr/lib/arm-linux-gnueabihf/libEGLESv2.so*: No such file or directory
lrwxrwxrwx 1 root root     21 Nov 11 16:49 /usr/lib/arm-linux-gnueabihf/libEGL.so -> /opt/vc/lib/libEGL.so
lrwxrwxrwx 1 root root     21 Nov 11 16:49 /usr/lib/arm-linux-gnueabihf/libEGL.so.1 -> libEGL.so.1.0
-rw-r--r-- 1 root root 101944 Aug 27 07:04 /usr/lib/arm-linux-gnueabihf/libEGL.so.1.0
lrwxrwxrwx 1 root root     24 Nov  9 22:49 /usr/lib/arm-linux-gnueabihf/libGLESv2.so -> /opt/vc/lib/libGLESv2.so
lrwxrwxrwx 1 root root     18 Nov  9 23:27 /usr/lib/arm-linux-gnueabihf/libGLESv2.so.2 -> libGLESv2.so.2.0.0
-rw-r--r-- 1 root root  18536 Aug 27 07:05 /usr/lib/arm-linux-gnueabihf/libGLESv2.so.2.0.0
lrwxrwxrwx 1 root root     10 Aug 27 07:04 /usr/lib/arm-linux-gnueabihf/libGL.so -> libGL.so.1
lrwxrwxrwx 1 root root     12 Aug 27 07:04 /usr/lib/arm-linux-gnueabihf/libGL.so.1 -> libGL.so.1.2
-rw-r--r-- 1 root root 359656 Aug 27 07:05 /usr/lib/arm-linux-gnueabihf/libGL.so.1.2

If some of the libEGL or libGLESv2 symlinks point to a relative path, as above for libEGL.so.1 and libGLESv2.so.2, the VC libraries won't be picked up.

To fix the issue, rather than overwriting these links all the time, the actual binaries can be moved away, and replaced by links.

pi@raspberrypi ~ $ sudo mv /usr/lib/arm-linux-gnueabihf/libGLESv2.so.2.0.0 /usr/lib/arm-linux-gnueabihf/libGLESv2.so.2.0.0.orig
pi@raspberrypi ~ $ sudo ln -sf /opt/vc/lib/libGLESv2.so /usr/lib/arm-linux-gnueabihf/libGLESv2.so.2.0.0
pi@raspberrypi ~ $ sudo mv /usr/lib/arm-linux-gnueabihf/libEGL.so.1.0 /usr/lib/arm-linux-gnueabihf/libEGL.so.1.0.orig
pi@raspberrypi ~ $ sudo ln -sf /opt/vc/lib/libEGL.so /usr/lib/arm-linux-gnueabihf/libEGL.so.1.0

This makes XBMC happier accross calls to apt-get FIXME: to be confirmed.


Building the Module

The DViCO LIRC receiver will need to be adapted. There is a LIRC/GPIO driver for the Raspberry which might help.

As of 3.2.27, the driver is already available in the staging section. We just want to compile a module for the running kernel, so we can easily load it.

$ git clone --depth=1 git://github.com/raspberrypi/linux.git
$ cd linux
$ BRANCH=rpi-3.2.27 # or rpi-3.6.y
$ git fetch git://github.com/raspberrypi/linux.git $BRANCH:refs/remotes/origin/$BRANCH
$ git checkout $BRANCH
$ gunzip -c /proc/config.gz > .config
$ patch .config < EOF 
--- .config.old 2012-12-30 19:18:21.647246935 +1100
+++ .config     2012-12-30 19:20:44.072116258 +1100
@@ -2663,7 +2663,18 @@
 # CONFIG_SPEAKUP is not set
+# CONFIG_DVB_AS102 is not set
+# CONFIG_EASYCAP is not set
+# CONFIG_LIRC_IMON is not set
+# CONFIG_LIRC_SASEM is not set
+# CONFIG_LIRC_SERIAL is not set
+# CONFIG_LIRC_SIR is not set
+# CONFIG_LIRC_ZILOG is not set

$ make modules
$ sudo make modules_install

Building and Installing a Compatible Kernel

Building the module the above way worked once, but after a reinstall of the entire system (>=1000Mhz is known to corrupt SD cards, and that did mine), the same steps didn't work anymore, with module loading generating the following error messages.

$ sudo modprobe  lirc_rpi
ERROR: could not insert 'lirc_rpi': Exec format error
$ dmesg | tail -n 1
[1299758.299548] lirc_dev: no symbol version for module_layout

This appears to be due to a missing Module.symvers (which probably was co-located with the Github sources at the time of my first check-out), and the newly built modules do not agree with the kernel about which symbol is where. The easiest at this stage is therefore to simply rebuild the kernel, and install it for the Pi to boot on it. The latter phase will require specific tools.

$ make # Build a new kernel binary
$ cd .. && git clone --depth 1 git://github.com/raspberrypi/tools.git
$ cd tools/mkimage
$ python ./imagetool-uncompressed.py ../../linux/arch/arm/boot/Image # Create the kernel.img image for the Pi

The thus created kernel.img can then be placed in /boot (/dev/mmcblk0p1), and the Pi rebooted. We use the OpenBSD method to make sure we always have a valid kernel in place, adapted to a VFAT filesystem.

$ sudo cp /boot/kernel.img /boot/kernel.img.old
$ sudo cp kernel.img /boot/kernel.img.new
$ sudo mv /boot/kernel.img.new /boot/kernel.img

Building the Hardware

The circuitry is rather simple. It consists in directly plugin the receiver to the GPIO pins available on connector P1. There is some weirdness in P1's layout, not having a 3.3V pin directly next a GND one for convenient powering, but fortunately, there is a GND next to GPIO18 (P1-21), which is the default signal pin used by lirc_rpi.

Unfortunately, it appears that the DViCO receiver is a 5V module which, like the TSOP17xx is unstable at the 3.3V of the RPi GPIO (the receiver stops working for a bit after a burst of IR signals; something looking like a capacitor that needs recharging).

Installing and Configuring lircd

Finally, lircd can be installed and configured to use the default driver on /dev/lirc0.

$ sudo apt-get install lirc
# usually /dev/lirc0 is the correct setting for systems using udev

XBMC can then be configured as before.

A Nice Case

Apple ludicrously overpackages their products. Their wireless swipey mousey thing, for example, comes in a nice transparent plexiglass case. I expect the life-time of that thing to be less than five minutes once the brainwashedhappy user gets home.

Anyway, it so happens that this box can have a second life as a cute case for the Raspberry Pi. It has exactly the right size so the Pi fits snuggly in there, SD card included. A few incisions (with a swiss army knife!) later, all cables can be fed through, and we get all the well known Californian design for our home-made set-top box, without the pollution.

Switching to OpenELEC

The above solution works, but is heavy maintainance for every XBMC upgrade. Things that the good guys at OpenELEC already do, so I gave it a go. Apart from newer XBMCs and automatic updates, the entire GUI is also much smoother, even on the 256 MB Pi.

There is also OTT support for lirc for OpenELEC.

Other pointers

projets/xpimc.txt · Dernière modification: 2014-07-20 07:44 par oliviermehani