The Raspberry Pi is great for playing videos and music from USB devices, but what if you want to use it as a wireless media client? This is the guide to creating a streaming home theater setup using XBMC on the Pi.
If your media is scattered around your home network (like mine is), the idea is to use XBMC on the Raspberry Pi as a central hub to access all that content. This involves setting up file servers (NFS, Samba, UPnP) on your local computers and configuring XBMC.
Since all media content will be streamed, it's important to make sure your Raspberry Pi is up to the task. If you plan on streaming 1080p DTS encoded content, you will most likely experience stuttering. Your Raspberry Pi will have no problem decoding the video, but it will struggle mightily with the audio codec. This is because the Pi does not have the proper licensing to perform hardware decoding, so it must rely on software (which is just plain slow).
So how do we get around this? The best solution is to employ audio passthrough (more on this later). This requires having a TV or external AV receiver capable of DTS decoding.
If you don't have hardware with this functionality, there is an alternative solution, but it's not pretty. You can use a local computer as an on-the-fly transcoder to convert DTS audio streams to AAC or stereo. If you choose to go this route, you can use Plex Media Server for transcoding. On the Raspberry Pi, you will have to configure XBMC to be compatible with Plex streams or install a Plex distribution.
There are several networking protocols we can choose for file sharing. The two most popular are Samba (SMB) and NFS. Samba is designed to work well with Windows and is very easy to use. NFS is not supported natively in Windows, but it provides almost twice the throughput of Samba because of its low overhead. Also, NFS is less CPU intensive than Samba. For these reasons, we'll be using NFS.
There are three main XBMC distros for the Raspberry Pi: Raspbmc, OpenELEC, and Xbian. I tried out each of them when I first bought my Raspberry Pi (a year ago) so I'll share my brief thoughts.
Raspbmc: By far the most all-inclusive distro with everything included out of the box. It has a powerful configuration tool, but is a little slow.
OpenELEC: A relatively minimalist distro with a decent configuration tool. The main advantage is that it's fast. Really fast.
Xbian: Bleeding edge distro that's in between Raspbmc and OpenELEC in terms of speed.
With it's incredible speed, OpenELEC provides the smoothest user experience so we'll use that as our OS. If you think there's a better distro out there, let me know in the comments.
Installing and configuring NFS
We'll be setting up an NFS server on OpenSUSE. The instructions should be similar across different Linux distributions.
As superuser, install the server package using
zypper in nfs-kernel-server. Optionally, if you would like to configure NFS through YaST, install
/etc/exports and add lines corresponding to the directories you would like to export via NFS. Each line should follow the following format:
<directory> <host1>(<options>) [<host2>(<options>)]...
The directory (and all subdirectories) to be exported is
/home/mdchaudhari/Movies. All hosts within the range
192.168.0.254 will have read only access. The
insecure option allows XBMC to run without root privileges. The
all_squash option converts requests from all users to anonymous uid and gid. To determine the uid and gid corresponding to a particular user, run
grep <username> /etc/passwd.
Hosts can be defined using,
- Single IP address (192.168.0.5)
- Hostname (mdc.mdczone)
- Fully qualified domain name (mdchaudhari.com)
- Wildcards (*.mdchaudhari.com)
- IP networks (192.168.0.0/28)
- NIS netgroup (@mdchaudhari)
To learn more about the host definitions and export options, read the man pages on
exports. After modifying
/etc/exports, we are left with an insecure setup. To further refine access,
/etc/hosts.deny should be modified. To implement additional security, consider the different
exports options and NFS mounting options (see man pages on
nfs). For our simple home network setup, we won't worry about additional security.
NFS and portmapper run on TCP and UDP ports 2049 and 111 respectively. If SuSEfirewall2, iptables, or another firewall is blocking access to these ports, we need to open them. NFS also relies on several daemons to function:
rpc.rquotad. Luckily, most Linux distros contain startup scripts for all these daemons.
Now, we're ready to start the NFS server. Run
systemctl start rpcbind.service and then
systemctl start nfsserver.service. You can check the NFS server status by running
systemctl status nfsserver.service.
nfsserver.service - LSB: Start the kernel based NFS daemon Loaded: loaded (/etc/init.d/nfsserver) Active: active (running) since Thu 2014-03-19 14:09:29 PDT; 2min 42s ago Process: 23131 ExecStop=/etc/init.d/nfsserver stop (code=exited, status=0/SUCCESS) Process: 23155 ExecStart=/etc/init.d/nfsserver start (code=exited, status=0/SUCCESS) CGroup: /system.slice/nfsserver.service ├─23176 /usr/sbin/rpc.idmapd -p /var/lib/nfs/rpc_pipefs ├─23180 /usr/sbin/rpc.mountd └─23183 /usr/sbin/rpc.statd --no-notify
Ensure all the NFS daemons are running using
program vers proto port service 100000 4 tcp 111 portmapper 100000 3 tcp 111 portmapper 100000 2 tcp 111 portmapper 100000 4 udp 111 portmapper 100000 3 udp 111 portmapper 100000 2 udp 111 portmapper 100005 1 udp 20048 mountd 100005 1 tcp 20048 mountd 100005 2 udp 20048 mountd 100005 2 tcp 20048 mountd 100005 3 udp 20048 mountd 100005 3 tcp 20048 mountd 100024 1 udp 37615 status 100024 1 tcp 43565 status 100003 2 tcp 2049 nfs 100003 3 tcp 2049 nfs 100003 4 tcp 2049 nfs 100227 2 tcp 2049 nfs_acl 100227 3 tcp 2049 nfs_acl 100003 2 udp 2049 nfs 100003 3 udp 2049 nfs 100003 4 udp 2049 nfs 100227 2 udp 2049 nfs_acl 100227 3 udp 2049 nfs_acl 100021 1 udp 49172 nlockmgr 100021 3 udp 49172 nlockmgr 100021 4 udp 49172 nlockmgr 100021 1 tcp 59170 nlockmgr 100021 3 tcp 59170 nlockmgr 100021 4 tcp 59170 nlockmgr
We won't be installing OpenELEC directly. Instead, we'll use BerryBoot because it's simpler and includes a bootloader if you want to install multiple distros. Download the BerryBoot zip file from here.
Next, pop your SD card into your computer. We'll need to delete all existing partitions and create a new FAT partition. As superuser, run
fdisk -l to determine which device corresponds to your SD card.
Disk /dev/sdc: 16.0 GB, 16039018496 bytes, 31326208 sectors Units = sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disk label type: dos Disk identifier: 0x00085c58 Device Boot Start End Blocks Id System /dev/sdc1 * 2048 258047 128000 c W95 FAT32 (LBA) /dev/sdc2 258048 31293439 15517696 83 Linux
In my case, that's
/dev/sdc. Enter command mode by running
fdisk /dev/sdc where
/dev/sdc should be adjusted to correspond to your particular device.
Delete all existing partitions (
/dev/sdc2) using the
d command. Ensure that all partitions are wiped using the
Disk /dev/sdc: 16.0 GB, 16039018496 bytes, 31326208 sectors Units = sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disk label type: dos Disk identifier: 0x00085c58 Device Boot Start End Blocks Id System
Now, we will create a new FAT partition. Using the
n command, create a primary partition. Set the partition number as 1, leave the first sector as default, and set the last sector as
+100M to create a 100MB partition. We need to change the partition type to FAT32 so run the
t command and use hex code
c. Print the partition table to make sure the changes are correct.
Partition 1 of type Linux and of size 100 MiB is set Changed type of partition 'Linux' to 'W95 FAT32 (LBA)' Disk /dev/sdc: 16.0 GB, 16039018496 bytes, 31326208 sectors Units = sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disk label type: dos Disk identifier: 0x00085c58 Device Boot Start End Blocks Id System /dev/sdc1 2048 206847 102400 83 W95 FAT32 (LBA)
We're satisfied with all the changes we've made so we'll use the
w command to write the changes to disk.
Next, we have to format the partition. Run
mkfs.vfat -F 32 -s 2 /dev/sdc1 where
/dev/sdc1 should correspond to the partition you created using
Now, we can copy all of the extracted BerryBoot files onto our newly created FAT partition. Once that's done, power up your Raspberry Pi with your inserted SD card. Follow the instructions on the BerryBoot website to install OpenELEC.
Once the installation is complete, we can boot into OpenELEC and see the Confluence home screen.
The first thing we need to do is enable SSH access. Navigate to System → OpenELEC → Services and enable 'Start SSH server at boot'. Then, reboot the Raspberry Pi and SSH into OpenELEC.
Login: root Password: openelec
/storage/.config/ directory, create an autostart script named
autostart.sh. In this file, we will mount our NFS share at bootup.
#!/bin/sh (sleep 10; \ mount -t nfs 192.168.0.12:/home/mdchaudhari/Movies /storage/Movies/ \ )&
Make the autostart script executable and run it. You can
cat /proc/mounts to make sure the mount worked.
Now we can add our mounted path as a video file directory inside XBMC. Once that's done, XBMC should start fetching our content.
Several minutes later, our entire library is synced.
If you want to tune OpenELEC to improve performance, there are several changes we can make.
The biggest performance improvement can be realized by overclocking. The default options are:
arm_freq=700 gpu_freq=250 avoid_pwm_pll=0 sdram_freq=400 over_voltage=0 (1.2 V) force_turbo=0 initial_turbo=0 arm_freq_min=700 core_freq_min=250 sdram_freq_min=400 over_voltage_min=0 (1.2 V) temp_limit=85
To change them, reboot your Raspberry Pi. From the BerryBoot menu, navigate to Edit Menu → Edit Config → config.txt. At the end of this file, we will add our modest overclock settings.
Exit the Bootmenu Editor and boot into OpenELEC. To check our CPU frequency, we can
cat our CPU devices.
cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_min_freq cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_cur_freq
To find out more about overclocking the Raspberry Pi, check out RPiconfig. It should be noted that certain settings, such as overvoltage, will void your warranty. Aggressive overclocking will require a heat sink. Finally, Class 6 & 10 SD cards may become corrupted.
We can tweak our NFS performance by changing the way we mount our NFS share in the
We can mount our directory using NFSv3 over UDP. We can also specify the timeout value as well as the maximum read data block size.
mount -t nfs 192.168.0.12:/home/mdchaudhari/Movies /storage/Movies/ -o udp,ro,timeo=600,rsize=65556,nfsvers=3,soft
Setting a static IP
Creating a static IP address for the Raspberry Pi will not improve performance, but it's useful if you plan on using the Pi as a server or using the XBMC web interface.
The first thing we need to do is identify the DHCP pool range of our router. Log into your router's administration web page and find the DHCP Server Settings.
We see that IPs ranging from 192.168.0.100 – 192.168.0.199 are automatically assigned by DHCP. That means we must choose an IP that falls outside this range.
In OpenELEC, navigate to System → OpenELEC → Network → Static IP Address. Assign a static IP outside of the DHCP pool. Also enter your default gateway and DNS server, both of which should be your router IP address. Reboot the Raspberry Pi for the changes to take effect.
At this point, you can go ahead and enjoy your Raspberry Pi. But if you would like even more speed improvements and additional XBMC functionality, read on.
If you are streaming HD content with DTS audio, you may experience audio and video stuttering. The solution is to enable audio passthrough so a DTS capable receiver can decode the audio stream.
Navigate to System → Settings → System → Audio output. Ensure that your Audio output is HDMI, and Dolby Digital (AC3) and DTS capable receivers are both selected.
Video and skin settings
We can disable several features to cut down on CPU usage.
Confluence skin settings:
- Disable autoscrolling for plot and review.
- Disable recently added videos and albums.
- Disable fanart.
- Disable now playing video and visualization.
- Disable weather info.
- Disable RSS feeds.
- Disable screensaver visualization.
- Disable subtitles.
- Disable extract thumbnails and video information.
Other methods to reduce system load include reducing resolution.
Skin choice can also drastically impact performance. The lightest skins perform the best. These include Quartz, Amber, Metropolis, and Bello. However, the default skin, Confluence, has the best overall performance.
We can also try to increase the buffer cache. In
/storage/.xbmc/userdata/ create a file named
advancedsettings.xml. We can adjust the video buffer size by specifying
cachemembuffersize as well as the rate at which the cache is filled by specifying
<advancedsettings> <network> <cachemembuffersize>268435456</cachemembuffersize> </network> </advancedsettings>
Be careful with the
cachemembuffersize you choose. Some people have reported the Raspberry Pi crashes and reboots if the buffer size is too large.
XBMC web setup
To enable the webserver, navigate to System → Settings → Webserver. Enable 'Allow control of XBMC via HTTP'. You can specify your port, username, and password of choice.
Now, we can view our XBMC library and control playback through a web browser.
If you have assigned a static IP to your Raspberry Pi, you won't have to worry about dynamic IP changes due to a reset of the router or DHCP lease expiration.
OpenELEC has built-in CEC support. On certain TVs, you may have to enable HDMI control. For LG TVs the feature is called SimpLink and for Samsung TVs it's called Anynet+.
To determine which remote keys are detected, enable XBMC debug logging. Then we can run
tail -f /storage/.xbmc/temp/xbmc.log | grep OnKey: to identify the valid keys. We can map these keys to XBMC actions by creating
Once all of the desired keys are mapped, we can navigate XBMC without the use of a keyboard or mouse.
- Investigate if increasing swap space improves performance?
- Fix SimpLink failing to reconnect when switching TV inputs.
- Use Chorus to stream media over LAN with working audio.
- Implement Google Speech API for hands-free control.
- Add a transcoder in front of Chorus/XBMC and build a proper CDN for media.