Streaming TV

… some quick notes on getting streaming digital TV working under Linux.

Kernel and driver

According to Hal, you need at least 2.6.15. On boot, a whole load of modules are loaded:

$ lsmod | grep ^cx
cx88_blackbird         21692  0
cx88_dvb               10660  0
cx8802                 12740  2 cx88_blackbird,cx88_dvb
cx8800                 34668  1 cx88_blackbird
cx88xx                 64384  4 cx88_blackbird,cx88_dvb,cx8802,cx8800

Sometimes, when the machine boots it doesn’t seem to detect the card correctly.

cx88[0]: Your board isn't known (yet) to the driver.  You can
cx88[0]: try to pick one of the existing card configs via
cx88[0]: card=n insmod option.

… however, after a reboot it was happy again.

Install stuff

We use the Debian packages dvb-utils, mplayer, and vlc.

Scanning for channels

You need a channels.conf file, which tells various apps what frequencies and tuning parameters to use for all the different logical channels. This is generated thusly:

$ scan /usr/share/doc/dvb-utils/examples/scan/dvb-t/au-sydney_north_shore | tee  channels.conf

… however for some reason at KEG we can’t get SBS on its normal frequency, only on the Wollongong one. So we have to scan that manually:

$ cat wollongong.scan
# T freq bw fec_hi fec_lo mod transmission-mode guard-interval hierarchy
T 711625000 7MHz 2/3 NONE QAM64 8k 1/8 NONE
$ scan wollongong.scan | tee  channels.conf

Now put channels.conf in the right place for different apps:

$ mkdir -p ~/.tzap ~/.mplayer
$ mv channels.conf ~/.tzap
$ ln -s ~/.tzap/channels.conf ~/.mplayer/channels.conf.ter

Here is the final channels.conf file, also including the (mostly unused) D44 channels.

Testing reception

$ mplayer dvb://SBS HD

You can edit the channel names in the channels.conf file to make them easier to use (it’s the first field on each line).

Streaming

With dvbstream

The dvbstream package contains a simple app that can dump a stream to the network. To do unicast streaming to a specific host, we used netcat. The dvbstream program has its own options for generating multicast streams, but we didn’t try this. On the host you want to view the stream do something like:

nc -u -l -p portnum | mplayer -cache 8000 -vo xv -

And then on the TV box, we first used tzap to tune the channel in, and then ran dvbstream:

$ tzap SBS HD
^C to interrupt it once it acquires a signal (FE_HAS_LOCK)
$ dvbstream -v 102 -a 103 -o | nc -u target portnum

102 and 103 are the video and audio program IDs respectively. You can find them in the relevant line of channels.conf. dvbstream also has options to specify the frequency and tuning parameters, so it may not be necessary to use tzap, however it doesn’t use channels.conf like tzap does, so you may want this script (by Bodo Bauer) to parse the channels file and invoke dvbstream for you.

With VLC

vlc is an all-singing all-dancing media streamer, but in the end we don’t use it to do much more than dvbstream does (the only real advantage it offers for multicast is generation of the SAP announcements). See the VLC streaming HOWTO for more detailed docs. Here is a script to invoke vlc with all the right arguments, you will probably want to edit it to suit your setup:

#!/bin/bash

# machines to stream to (unicast)
# each additional client multiplies the bandwidth required
# leave unset to use multicast
#clients="zarquon"

# channels.conf file to use
conf="$HOME/.tzap/channels.conf"

# work out frequency/program ID
# default to SBS, it has the soccer :)
[ $# == "0" ] && ch='SBS HD' || ch=$1
if grep -q ^"$ch" $conf; then
        chan=$(grep -i ^"$ch" $conf | head -1 | cut -d: -f1)
        freq=$(grep -i ^"$ch" $conf | head -1 | cut -d: -f2)
        prog=$(grep -i ^"$ch" $conf | head -1 | cut -d: -f13)
        echo "$chan, frequency $freq, program ID $prog"
else
        echo "Unknown channel $ch" > /dev/stderr
        exit 1
fi

# construct arguments to vlc
if [ ! -z "$clients" ]; then # unicast
  dsts=""
  for host in $clients; do
    dsts="${dsts}dst=standard{access=udp,mux=ts,url=${host}},"
  done
  sout="#duplicate{${dsts}}"
else # multicast
  dst="access=udp,mux=ts,url=239.255.42.42,sap,name=\"KEG TV: $chan\""
  sout="#standard{$dst}"
fi

# run the damn thing!
exec vlc -I dummy --ttl 1 --program=$prog dvb: \
--dvb-frequency=$freq --dvb-bandwidth=7 --sout "$sout"

Notes:

  • $prog is the program ID from channels.conf
  • all Australian DVB channels have 7MHz bandwidth (without this option, vlc can’t tune)
  • a TTL of 1 prevents the stream from crossing any routers; increase this only if you need to
  • 239.255.x.x is in the private space for multicast IPs, the .42.42 is arbitrary

To view this stream on a client, you could do:

$ vlc udp:@239.255.42.42

… or alternatively, enable the SAP Announcements discovery service (Settings-Preferences-Playlist-Services Discovery), and select KEG TV in the playlist when it pops up automatically.

Mumudvb

I haven’t tried it, but its author claims that:

  • Mumudvb is a program that can redistribute streams from DVB on a network using multicasting. It is able to multicast a whole DVB transponder by assigning each channel to a different multicast IP. It has be written to use as few CPU in order to stream a lot of channels with one small server.

… it might be worth a try.

Common problems

Stream doesn’t arrive

Check that the kernel supports multicast (CONFIG_IP_MULTICAST). Apparently the default Gentoo kernels have it disabled. Check for any firewall rules that may be blocking the UDP multicast traffic. With iptables:

iptables -A INPUT -p udp --dst 224.0.0.0/4 --dport 1025: -j ACCEPT

Stream starts playing but stops/pauses after a few minutes

This one was tricky. It turned out that the firewall rules were allowing the UDP data, but blocking the IGMP packets. After a while the switch timed out and stopped sending the stream out that port. The solution was:

iptables -A INPUT -p igmp -j ACCEPT
iptables -A OUTPUT -p igmp -j ACCEPT

Multicast across networks

To get streaming working across to other networks:

  1. Enable IGMP on the switch (not really necessary, but it did fix a problem with 10MBit devices getting saturated with unwanted traffic).
  2. Add a route on the gateway box for multicast (put this in startup scripts):
    • route add -net 224.0.0.0 netmask 240.0.0.0 dev eth1
  3. Make sure any firewall rules allow multicast out, and don’t attempt to NAT it.
  4. Install and run pimd on the gateway box.
  5. Increase the TTL in the vlc arguments from 1 to 2 (or higher if needed).

Published by

ab

Well, AB's just this guy, you know?