Site Network: freakymousemats | portal | smashingbloke | regenology

docs

My life, both personally and professionally, consists mainly of an ill-advised series of technical endeavours. In this section you will find documentation about some of these things. Hopefully they'll prove useful to someone one day.

Streaming DVB with VLS on Debian

Installing Debian

Boot server from Debian 3.1 Sarge NetInst CD, specifiying these boot options:

linux netcfg/disable_dhcp=true

Select the appropriate language, country and keymap.

Enter the IP address, netmask, router and DNS server as prompted. Set the server's hostname and domain name when prompted.

Select the "Erase entire disk" option when prompted for partitioning. Accept the new partition layout and the disk will be formatted.

The base system is installed automatically, when prompted, accept the default "Yes" to installing GRUB on the MBR.

Remove the CD when prompted and select OK when done to reboot the server.

Select "Yes" to the prompt asking if the hardware clock is set to GMT. Select the appropriate timezone.

Enter the root password and confirm when requested. Setup a normal user account following the on screen instructions.

When prompted, choose to source the installation from an HTTP server and choose an appropriate local mirror.

At the package selection screen, do not select any of the available options, just choose "OK".

At the Exim4 configuration screen, select "No configuration at this time" and accept "Yes" when prompted if you're sure you don't want to configure a mail system. Accept the default root mail recipient when prompted.

Finally, select OK to confirm Debian has been installed!

Optional for Debian Sarge

If you've installed Debian Sarge as suggested above and you're using the Hauppauge Nova-t card based on the Conxent chipset, your card won't be detected by the stock Debian 2.6 kernel. You can build the latest kernel version to solve this, or optionally, use my kernel for Pentium 4 or K7 processors:

Edit /etc/apt/sources.list and add:

deb http://packages.neuron1.com/ stable main

Reload the package list and install the most recent available dvbsn kernel for your architecture:

apt-get update
apt-get install kernel-image-2.6.12.4-dvbsn-p4

Once installed, reboot.

Preparing for VLS

Install some necessary packages:

apt-get install dvb-utils libdvbpsi3 libdvbpsi3-dev

Change directory to /usr/local/src and download the VLS and libdvb source tarballs:

cd /usr/local/src
wget http://downloads.videolan.org/pub/videolan/vls/0.5.6/vls-0.5.6.tar.gz
wget http://downloads.videolan.org/pub/videolan/vls/0.5.6/contrib/libdvb-0.2.2.tar.gz

Configure, compile and install libdvb and VLS as follows (changing version numbers if they're different):

tar zxvf libdvb-0.2.2.tar.gz
cd libdvb-0.2.2
make
make install
install satscan /usr/local/bin
cd ..
tar zxvf vls-0.5.6.tar.gz
cd vls-0.5.6
./configure --enable-dvb --disable-dvd \
 --with-libdvb=/usr/local/src/libdvb-0.2.2 \
 --with-dvbpsi=/usr
make
make install

If you're doing this with a Debian version that's based on GCC 4 (Ubuntu's Breezy Badger for example), you might have a bit of trouble compiling VLS, install GCC v3.3 and use that instead, like this:

apt-get install gcc-3.3 g++-3.3
CC=gcc-3.3 CXX=g++-3.3 ./configure --enable-dvb --disable-dvd \
 --with-libdvb=/usr/local/src/libdvb-0.2.2 \
 --with-dvbpsi=/usr

Finding Channels

This next bit is rather tricky I'm afraid. We need to create a skeleton dvbrc file listing all the transponder details where we'll find channels to stream. If you're lucky, you'll be able to find one for your area (for DVB-T) or satellite. I'll provide the files for Sandy Heath and Crystal Palace below.

We need to use the satscan program from libdvb to generate the full dvbrc. Unfortunately it's rather out of date now, so it's starting point files aren't amazingly useful. The more up-to-date scan program from the dvb-utils will probably help you more. You can run that like this:

scan /usr/share/doc/dvb-utils/examples/scan/dvb-t/uk-SandyHeath
The starting files it provides only list one transponder, but from that it seems able to work out where to look next. It's output will be enough to help you piece together the skeleton file as I've done below. If anyone knows a better way to do this, I'd love to hear from you.

Skeleton dvbrc for Crystal Palace

LNB ID 1 TYPE 0 
  SAT ID 1 NAME "CrystalPalace" LNBID 1 FMIN 1 FMAX 2
    TRANSPONDER ID 0001 SATID 0001 TYPE 2 FREQ 505833333 BANDWIDTH 0 HP_RATE 3 LP_RATE 0 MODULATION 1 TRANSMISSION_MODE 0 GUARD_INTERVAL 0 HIERARCHY 0
    TRANSPONDER ID 0002 SATID 0001 TYPE 2 FREQ 481833000 BANDWIDTH 0 HP_RATE 2 LP_RATE 1 MODULATION 3 TRANSMISSION_MODE 0 GUARD_INTERVAL 0 HIERARCHY 0
    TRANSPONDER ID 0003 SATID 0001 TYPE 2 FREQ 561833000 BANDWIDTH 0 HP_RATE 2 LP_RATE 1 MODULATION 3 TRANSMISSION_MODE 0 GUARD_INTERVAL 0 HIERARCHY 0
    TRANSPONDER ID 0004 SATID 0001 TYPE 2 FREQ 529833333 BANDWIDTH 0 HP_RATE 3 LP_RATE 0 MODULATION 1 TRANSMISSION_MODE 0 GUARD_INTERVAL 0 HIERARCHY 0
    TRANSPONDER ID 0005 SATID 0001 TYPE 2 FREQ 578167000 BANDWIDTH 0 HP_RATE 3 LP_RATE 0 MODULATION 1 TRANSMISSION_MODE 0 GUARD_INTERVAL 0 HIERARCHY 0
    TRANSPONDER ID 0006 SATID 0001 TYPE 2 FREQ 537833333 BANDWIDTH 0 HP_RATE 3 LP_RATE 0 MODULATION 1 TRANSMISSION_MODE 0 GUARD_INTERVAL 0 HIERARCHY 0

Skeleton dvbrc for Sandy Heath

LNB ID 1 TYPE 0 
  SAT ID 1 NAME "SandyHeath" LNBID 1 FMIN 1 FMAX 2
    TRANSPONDER ID 0001 SATID 0001 TYPE 2 FREQ 641833334 BANDWIDTH 0 HP_RATE 3 LP_RATE 0 MODULATION 1 TRANSMISSION_MODE 0 GUARD_INTERVAL 0 HIERARCHY 0
    TRANSPONDER ID 0002 SATID 0001 TYPE 2 FREQ 665833330 BANDWIDTH 0 HP_RATE 2 LP_RATE 1 MODULATION 3 TRANSMISSION_MODE 0 GUARD_INTERVAL 0 HIERARCHY 0
    TRANSPONDER ID 0003 SATID 0001 TYPE 2 FREQ 650166670 BANDWIDTH 0 HP_RATE 2 LP_RATE 1 MODULATION 1 TRANSMISSION_MODE 0 GUARD_INTERVAL 0 HIERARCHY 0
    TRANSPONDER ID 0004 SATID 0001 TYPE 2 FREQ 842000000 BANDWIDTH 0 HP_RATE 3 LP_RATE 0 MODULATION 1 TRANSMISSION_MODE 0 GUARD_INTERVAL 0 HIERARCHY 0
    TRANSPONDER ID 0005 SATID 0001 TYPE 2 FREQ 626166670 BANDWIDTH 0 HP_RATE 2 LP_RATE 1 MODULATION 3 TRANSMISSION_MODE 0 GUARD_INTERVAL 0 HIERARCHY 0
    TRANSPONDER ID 0006 SATID 0001 TYPE 2 FREQ 674166670 BANDWIDTH 0 HP_RATE 2 LP_RATE 1 MODULATION 3 TRANSMISSION_MODE 0 GUARD_INTERVAL 0 HIERARCHY 0

Create a directory /etc/dvb and save the skeleton file there as dvbrc.template or similar.

Next, we need to use satscan to find out what channels are available on the transponders we've configured, and save the output to our system-wide dvbrc file:

satscan /etc/dvb/dvbrc.template > /etc/dvb/dvbrc
Be sure to answer 'y' to clearing the channel list and scanning the named satellite. After a short while you should be returned to the command prompt and if you look in /etc/dvb/dvbrc you'll hopefully find a list of the channels available. This information will come in useful later, so make note of it somewhere.

If you're running more than one source card then you'll need multiple copies of the dvbrc file available. If each card is of the same type (e.g. all terrestrial or all pointing at the same satellite), then simply symlink for as many cards as you have:

ln -s /etc/dvb/dvbrc /etc/dvb/dvbrc.1
ln -s /etc/dvb/dvbrc /etc/dvb/dvbrc.2

Configuring VLS

The next job is to create a configuration file for VLS so it knows what to do. A short, documented sample is shown below. The configuration is kept in /usr/local/etc/videolan/vls/vls.cfg by default, but you can keep elsewhere if you want.

# Sample configuration for streaming DVB with VLS

# application wide settings
BEGIN "Global"
  LogFile       = "/var/log/vls.log"	# log file
  ScreenLog     = "enable"              # log to the console
  SystemLog     = "disable"
END

# define available input devices
BEGIN "Inputs"
  dtt0          = "dvb"
END
BEGIN "dtt0"
  Type          = "Mpeg2-TS"        # Stream type (default is "Mpeg2-PS")
  DeviceNumber = "0"                # /dev/dvb/adapter(x)
  SendMethod   = "0"                # 0 - Send All Pids
  IgnoreTimeout = "1"               # lets us take out the aerial or get a bad signal
END

# define output channels
BEGIN "Channels"
  channel_01	 = "network"
  channel_02	 = "network"
  channel_03	 = "network"
  channel_04	 = "network"
  channel_05	 = "network"
END
BEGIN "channel_01"
  Type         = "multicast"
  TTL          = "5"
  DstHost      = "239.192.254.1"
  DstPort      = "5004"
  Interface    = "eth0"
END
BEGIN "channel_02"
  Type         = "multicast"
  TTL          = "5"
  DstHost      = "239.192.254.2"
  DstPort      = "5004"
  Interface    = "eth0"
END
BEGIN "channel_03"
  Type         = "multicast"
  TTL          = "5"
  DstHost      = "239.192.254.3"
  DstPort      = "5004"
  Interface    = "eth0"
END
BEGIN "channel_04"
  Type         = "multicast"
  TTL          = "5"
  DstHost      = "239.192.254.4"
  DstPort      = "5004"
  Interface    = "eth0"
END
BEGIN "channel_05"
  Type         = "multicast"
  TTL          = "5"
  DstHost      = "239.192.254.5"
  DstPort      = "5004"
  Interface    = "eth0"
END

# what to do on startup
# channel names are sourced from the dvbrc file
# (with spaces replaced by underscores)
BEGIN "LaunchOnStartup"
  # Freeview Multiplex 1
  command_101  = "start BBC_ONE channel_01 dtt0"
  command_102  = "start BBC_TWO channel_02 dtt0"
  command_103  = "start BBC_THREE channel_03 dtt0"
  command_104  = "start CBBC_Channel channel_04 dtt0"
  command_105  = "start BBC_NEWS_24 channel_05 dtt0"
END

OK, a little explanation of some of that stuff. After the global settings we define a list of available inputs, then describe each input within it's own section.

Next, we define a set of output channels, then describe each output channel. In this case we're going to be multicasting our transmissions. A quick note, we've chosen 239.192.254.x based on a little research. 239.192.x.x is for multicast what 192.168.x.x is for regular IP allocations, it's stuff that'll stay in our network. And for some reason IPs are traditionally allocated backwards, hence we chose 239.192.254.x (we couldn't bring ourselves to use 255 for superstitious reasons). We decided to work up on the final number to make them a little logical, 1 for BBC 1, etc.

The important to take away from this is not to make the mistake we did, and use numbers like 224.0.x.x because they're the first multicast addresses available. These are especially allocated for various configuration and network chatter things and your traffic will leak all over the place. It's not good.

Finally, we select which channels to stream, where they come from and where to send them. Remember, a single card can only tune to one transponder, so you must only use channels from the same transponder for each card you start streams from. I don't know what'll happen if you disregard this!

Test It

Get VLS started, hopefully without any error messages popping up:

vls -f /usr/local/etc/videolan/vls/vls.cfg

Using VLC on another machine you should be able to open a network stream and tune to something like 239.254.192.1 port 5004 and find a working TV channel. If not, something's gone wrong. Good luck fixing it!

Getting it running at bootup

If it's all working, you'll probably want to have VLS running every time you reboot the server. Below is a simple init script (taken from the Debian skeleton script). I'm using vls and backgrounding it rather than vlsd as I've had some problems with the daemonised version. Save a copy of the below to /etc/init.d/vls or similar.

#! /bin/sh
#
# vls           vls initscript
#
# Author:       Stephen Newey .
#
# Version:      @(#)vls  1.0  5-Oct-2005  spam@freakymousemats.com
#

set -e

PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DESC="vls"
NAME=vls
DAEMON=/usr/local/bin/$NAME
PIDFILE=/var/run/$NAME.pid
SCRIPTNAME=/etc/init.d/vls

# Gracefully exit if the package has been removed.
test -x $DAEMON || exit 0

# Read config file if it is present.
if [ -r /etc/default/vls ]
then
        . /etc/default/vls
fi

test "$RUN_DAEMON" = "yes" || exit 0

#
#       Function that starts the daemon/service.
#
d_start() {
        start-stop-daemon --start --quiet -b --exec $DAEMON -- $OPTIONS
}

#
#       Function that stops the daemon/service.
#
d_stop() {
        start-stop-daemon --stop --quiet --name $NAME
}

#
#       Function that sends a SIGHUP to the daemon/service.
#
d_reload() {
        start-stop-daemon --stop --quieti --name $NAME --signal 1
}

case "$1" in
  start)
        echo -n "Starting $DESC: $NAME"
        d_start
        echo "."
        ;;
  stop)
        echo -n "Stopping $DESC: $NAME"
        d_stop
        echo "."
        ;;
  #reload)
        #
        #       If the daemon can reload its configuration without
        #       restarting (for example, when it is sent a SIGHUP),
        #       then implement that here.
        #
        #       If the daemon responds to changes in its config file
        #       directly anyway, make this an "exit 0".
        #
        # echo -n "Reloading $DESC configuration..."
        # d_reload
        # echo "done."
  #;;
  restart|force-reload)
        #
        #       If the "reload" option is implemented, move the "force-reload"
        #       option to the "reload" entry above. If not, "force-reload" is
        #       just the same as "restart".
        #
        echo -n "Restarting $DESC: $NAME"
        d_stop
        sleep 1
        d_start
        echo "."
        ;;
  *)
        # echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
        echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2
        exit 1
        ;;
esac

exit 0

To support the init script you'll need the configuration file below so that VLS knows where it's configuration file is. Call it /etc/default/vls.

#Defaults for vls
RUN_DAEMON="yes"
OPTIONS="-f /usr/local/etc/videolan/vls/vls.cfg"

Finally link it into the default runlevels so it starts automatically, and make sure it's executable:

chmod 755 /etc/init.d/vls
update-rc.d vls defaults

And that's it, you should have a DVB streaming server!

Stephen Newey - 5th October 2005

Made with Django.