Quozl's streaming server for ABC TV via DVB-T |
| quozl@us.netrek.org
| up |
|
Looks like there are simpler ways to do it, but this way got me the underlying components individually tested. I also learned how it works, rather than treat it as a black box.
Next time I do this, I'll ask for an OEM card. The rest of the package is an annoying waste.
A Digital Video Broadcast (DVB) is a transport stream (TS) consisting of multiple audio and video streams. DVB-T is terrestrial, meaning transmitted from an antenna nearby. A "channel" as understood by a consumer is whatever streams are required to show a television programme.
# cat /dev/dvb/adaptor0/dvr0 > test.mp2 ^C # mplayer test.mp2
http {
port 8000;
};
adapter 0 {
dvb-t { frequency 226500000; bandwidth 7; transmission-mode auto;
guard-interval auto; hierarchy none; modulation auto; };
stream { name "ABC TV"; input { pid 512; pid 650; };
output-rtp { remote-address 224.0.0.1; remote-port 5000; }; };
stream { name "ABC2"; input { pid 513; pid 651; };
output-rtp { remote-address 224.0.0.2; remote-port 5000; }; };
stream { name "ABC HDTV"; input { pid 516; pid 654; };
output-rtp { remote-address 224.0.0.3; remote-port 5000; }; };
stream { name "ABC DiG Jazz"; input { pid 700; };
output-rtp { remote-address 224.0.0.4; remote-port 5000; }; };
stream { name "ABC DiG Radio"; input { pid 690; };
output-rtp { remote-address 224.0.0.5; remote-port 5000; }; };
};
mplayer -cache 2048 -vo xv -ao sdl -quiet \
-panscan 1.0 -zoom -fs rtp://224.0.0.1:5000/
#!/bin/sh
set -e
CHANNEL="${1}"
if test -z "${CHANNEL}"; then
CHANNEL='abc-1-and-2'
echo "fe: defaulting to ${CHANNEL}"
else
echo "fe: channel ${CHANNEL}"
fi
if test -f /tmp/fe.channel; then
read CHANNEL_OLD < /tmp/fe.channel
if test "${CHANNEL}" != "${CHANNEL_OLD}"; then
echo "fe: is running on wrong channel"
fe-stop
else
echo "fe: already running fine"
exit 0
fi
fi
cd
LD_LIBRARY_PATH=/usr/local/lib \
nice --adjustment=-20 /usr/local/bin/getstream -c ${CHANNEL}.conf &
FE_PID=$!
echo ${FE_PID} > /tmp/fe.pid
echo ${CHANNEL} > /tmp/fe.channel
echo "fe: started, pid is ${FE_PID}"
#!/bin/sh
set -e
if [ ! -f /tmp/fe.pid ]; then
if pkill getstream; then
echo "fe: was running without pidfile"
else
echo "fe: was not running"
fi
exit
fi
read FE_PID < /tmp/fe.pid
if kill ${FE_PID}; then
echo "fe: stopped, pid was ${FE_PID}"
rm -f /tmp/fe.pid /tmp/fe.channel
else
echo "fe: pid ${FE_PID} was not found"
rm -f /tmp/fe.pid /tmp/fe.channel
if pkill getstream; then
echo "fe: was running with different pid"
fi
fi
#!/bin/bash
set -e
STREAM=1
NAME=noname
if test -n "$1"; then
STREAM=$1
shift
if test -n "$1"; then
NAME=$1
fi
fi
FREE=`df --block-size=1k /tv|tail -1|awk '{print $4}'`
FILE=/tv/`date +%Y-%m-%d`-${NAME}.ts
if test -f ${FILE}; then
FILE=`date +%Y-%m-%d-%s`-${NAME}.ts
while test -f ${FILE}; do
sleep 0.5
FILE=`date +%Y-%m-%d-%s`-${NAME}.ts
done
fi
echo "ts: recording stream ${STREAM} into ${FILE}"
( nice --adjustment=-19 dumprtp 224.0.0.${STREAM} 5000 2> /tmp/ts.${STREAM}.log | \
pv --interval=1 --size=${FREE}k > ${FILE} ) &
TS_PID=$!
echo ${TS_PID} > /tmp/ts.${STREAM}.pid
wait ${TS_PID}
echo "ts: stopped stream ${STREAM} at `date +%H:%M:%S` file ${FILE}"
echo -en '\007' > /dev/tty1
#!/bin/bash
set -e
STREAM=1
if test -n "$1"; then
STREAM=$1
fi
if [ ! -f /tmp/ts.${STREAM}.pid ]; then
if pkill -f "dumprtp 224.0.0.${STREAM}"; then
echo "ts: was running without pidfile"
else
echo "ts: was not running"
fi
exit
fi
read TS_PID < /tmp/ts.${STREAM}.pid
if pkill -U ${TS_PID}; then
echo "ts: stopped, pid was ${TS_PID}"
rm -f /tmp/ts.${STREAM}.pid
else
echo "ts: pid ${TS_PID} was not found"
rm -f /tmp/ts.${STREAM}.pid
if pkill -f "dumprtp 224.0.0.${STREAM}"; then
echo "ts: was running with different pid"
fi
fi
#!/bin/sh
# $1 start time
# $2 end time
# $3 stream
# $4 title
# FIXME: workaround to cope with tomorrow is to schedule the call to
# pick for tomorrow, e.g. echo 'pick arg arg arg arg' | at tomorrow
at "${1}" <<EOF
exec > "/tmp/pick-${1}-${2}-${3}.log"
fe ${3}
echo ts-stop ${3} | at "${2}"
ts ${3} ${4}
EOF