msgbartop
MAC OS X, Linux, Windows and other IT Tips and Tricks
msgbarbottom

25 Sep 12 Compiling and Installing Darwin Streaming Server on Debian Squeeze

I used to run Darwin Streaming Server Version 5.5.5 and ran quite well.
In order to be able to take advantage of the new features and stability of the 6.0.3
I tried to compile it in Debian Squeeze Linux and it didn’t work at all.
I got many compiling warnings and errors which at the end didn’t allow me to compile it.
I looked in Internet for some solutions and found some that were offering patches before compiling
but that also didn’t work well. I got either errors during the patching or error during the compiling.
Then I came across this great page:
http://www.codeproject.com/Articles/41874/Darwin-Streaming-Server-6-0-3-setup-customization
which offered more patches, replacement for Install script and an authentication module.
Thanks to the person who posted this page, and provided the patches etc. finally it did work and is now running.
So based on the information in this page I adapted it to fit to Debian Squeeze 64bit here below.

Note 1: I have stored the full source of the StreamingServer 6.0.3 as well as the patches needed on my own server just to make sure it is always available at least to me when I need it.

Note 2: I’m working here as root to avoid having to use sudo for every command.

Making sure you have the needed packages ready
apt-get install build-essential wget unzip
Adding a new user and group (qtss:qtss)for running the server
addgroup --system qtss
adduser --system --no-create-home --ingroup qtss qtss

Choose a directory where you’re going to compile the Darwin Streaming Server (DSS)
mkdir /usr/local/src/DSS
cd /usr/local/src/DSS

Getting the DSS source:
wget http://static.macosforge.org/dss/downloads/DarwinStreamingSrvr6.0.3-Source.tar
If the source is no more found there, then get it from my server:
wget http://public.itmatrix.eu/Darwin_Streamer_6.0.3/DarwinStreamingSrvr6.0.3-Source.tar
Get the patches etc. needed.
wget http://public.itmatrix.eu/Darwin_Streamer_6.0.3/Darwin_6.0.3_patches.zip
Uncompress the server source
tar -xvf DarwinStreamingSrvr6.0.3-Source.tar
Uncompress the extra patches etc.
unzip Darwin_6.0.3_patches.zip
Run the patches (makes it 64 bit compatible)
patch -p0 < Patches/dss-6.0.3.patch patch -p0 < Patches/dss-hh-20080728-1.patch
Build the server binaries (Ignore the many warnings)
It should build quite well, just verify that it does not end with an error.
cd DarwinStreamingSrvr6.0.3-Source
./Buildit

Replace the install script wit the one extra provided
mv Install Install.orig
cp ../Patches/Install .
chmod 755 Install

Install and start the server. Provide the administrator name and password(2x)
./Install
Check that the server is running:
The server should run one process as root and 2 processes as qtss user.
ps aux | grep treaming | grep -v grep
Example of results:
root 22080 0.0 0.0 19500 592 ? Ss 16:26 0:00 /usr/local/sbin/DarwinStreamingServer
qtss 22081 0.0 0.1 48352 5756 ? Ss 16:26 0:00 /usr/bin/perl /usr/local/sbin/streamingadminserver.pl
qtss 22082 0.1 0.0 133508 3004 ? Sl 16:26 0:13 /usr/local/sbin/DarwinStreamingServer

If all above is as mentioned then your server is running and you can connect with the web administration with URL:
http://www.myserver.com:1220(Use the name and password of the administrator you gave previously)
This will go through a one-time sequence of a few setting screens.
Important: make sure you don't activate the port 80 if you have a web server running on port 80 in the same host. It would create a port conflict and DSS might not want to start at all.

START/STOP init Script
In order to start and srop the server comfortably and with a reboot I suggest the following init script that you would save as /etc/init.d/DarwinStreamingServer:

#! /bin/sh
### BEGIN INIT INFO
# Provides: DarwinStreaming_server
# Required-Start: $remote_fs
# Required-Stop: $remote_fs
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Apple Audio/Video(quictime) DarwinStreamingServer
# Description: Start/Stop of DarwinStreamingServer
### END INIT INFO
#
# Author: Michel Bisson
#
# Do NOT "set -e"
#
# PATH should only include /usr/* if it runs after the mountnfs.sh script
PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC="Description of the service"
NAME="DarwinStreamingServer"
DAEMON="/usr/local/sbin/streamingadminserver.pl"
DAEMON_ARGS=""
PIDFILE=/var/run/$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME
#
# 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.0-6) to ensure that this file is present.
. /lib/lsb/init-functions
#
#
# Function that starts the daemon/service
#
do_start()
{
# 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 --exec $DAEMON --test > /dev/null \
|| return 1
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \
$DAEMON_ARGS \
|| return 2
if (ps ax | egrep -v 'grep|sh' | grep -iq streaming); then
echo "DarwinStreamingServer started"
else
echo "ERROR: DarwinStreamingServer NOT started"
fi
# Add code here, if necessary, that waits for the process to be ready
# to handle requests from services started subsequently which depend
# on this one. As a last resort, sleep for some time.
}
#
# Function that stops the daemon/service
#
do_stop()
{
# 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 2>/dev/null
kill $(pidof DarwinStreamingServer)
RETVAL="$?"
[ "$RETVAL" = 2 ] && return 2
# Wait for children to finish too if this is a daemon that forks
# and if the daemon is only ever run from this initscript.
# If the above conditions are not satisfied then add some other code
# that waits for the process to drop all resources that could be
# needed by services started subsequently. A last resort is to
# sleep for some time.
start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
if (ps ax | egrep -v 'grep|/bin/sh' | grep -iq streamingadminserver.pl); then
kill $(ps ax | grep "/usr/bin/perl /usr/local/sbin/streamingadminserver.pl" 2>/dev/null| grep -v grep| awk '{print $1}')
fi
[ "$?" = 2 ] && return 2
# Many daemons don't delete their pidfiles when they exit.
rm -f $PIDFILE
sleep 2
if (ps aux | egrep -v 'grep|/bin/sh' | grep -iq streamingadminserver); then
if (ps aux | egrep -v 'grep|/bin/sh' | grep -iq DarwinStreamingServer); then
echo "ERROR: DarwinStreamingServer still running"
ps aux | egrep -v 'grep|/bin/sh' | grep -i DarwinStreamingServer
else
echo "DarwinStreamingServer stopped"
fi
else
echo "DarwinStreamingServer stopped"
fi
return "$RETVAL"
}
#
# Function that sends a SIGHUP to the daemon/service
#
do_reload() {
#
# If the daemon can reload its configuration without
# restarting (for example, when it is sent a SIGHUP),
# then implement that here.
#
start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
return 0
}
# Start|stop|restart|reload|status
case "$1" in
start)
[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
do_start
case "$?" in
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
esac
;;
stop)
[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
do_stop
case "$?" in
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
esac
;;
#reload|force-reload)
#
# If do_reload() is not implemented then leave this commented out
# and leave 'force-reload' as an alias for 'restart'.
#
#log_daemon_msg "Reloading $DESC" "$NAME"
#do_reload
#log_end_msg $?
#;;
restart|force-reload)
#
# If the "reload" option is implemented then remove the
# 'force-reload' alias
#
log_daemon_msg "Restarting $DESC" "$NAME"
do_stop
case "$?" in
0|1)
do_start
case "$?" in
0) log_end_msg 0 ;;
1) log_end_msg 1 ;; # Old process is still running
*) log_end_msg 1 ;; # Failed to start
esac
;;
*)
# Failed to stop
log_end_msg 1
;;
esac
;;
status)
ps ax | egrep -v 'grep|/bin/sh' | grep -i streaming && echo "DarwinStreamingServer not running" || echo "DarwinStreamingServer not running"
;;
#
*)
#echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload|status}" >&2
echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload|status}" >&2
exit 3
;;
esac

Note: If you had the Darwin Streaming Server version 5.x.x installed before, it is possible that some modules of that version are still in the directory:/usr/local/sbin/StreamingServerModules.
Make sure they are deleted before you start the server.
If they are not deleted, no big deal. You're simply going to get some errors in the streaming server error logs when starting the server. Eg.
"WARNING: The module QTSSRefMovieModule is not a compatible QTSS API module."
"WARNING: The module QTSSHomeDirectoryModule is not a compatible QTSS API module."

For more information on how to create and install new Dynamic modules a good start is at:
http://www.codeproject.com/Articles/41874/Darwin-Streaming-Server-6-0-3-setup-customization


So here are some extra important info:
/usr/local/sbin/: server executable (DarwinStreamingServer) and admin server (streamingadminserver.pl)
/usr/local/sbin/StreamingServerModules/: Dynamically loadable modules.
/usr/local/movies: default content directory (where streams are served from, already contains sample hinted streams)
/usr/local/bin/: some other binaries, including "StreamingLoadTool" - a load test tool
/etc/streaming/streamingserver.xml: Configuration file for DSS
/etc/streaming/streamingloadtool.conf: Configuration file for the load test tool StreamingLoadTool),
/etc/streaming/qtusers: Authentication users file for DSS
/etc/streaming/qtgroups: Authentication groups file for DSS
(at this point only the admin user and group created during installation will be present)
/var/streaming/logs/: DSS logs folder
(StreamingServer.log, Error.log are the most important, also has streamingadminserver.log and mp3_access.log)

PORTS:
Port 554: Standard Video streaming port
Port 1220: Web Admin port (login with the administrator's name and password you gave during the Install process)

As DSS uses the RTSP protocol to stream (unless you're streaming via port 80)
you must have the following ports open on your firewall 1220, 554, 7070, 8000, 8001
then anything starting from 6970 & up depending on how many clients you want to support.

QuickTime Streaming Server and Darwin Streaming Server use the following TCP ports:
See also: http://www.soundscreen.com/streaming/firewall.html

80: HTTP - If activated(Warning:can conflict with running web server)
554: Standard RTSP port
6970 - 9999: used for dynamic (announced) UDP broadcasts
7070: Optionally used for RTSP
8000, 8001: MP3 streaming
10,000 - 20,000: buffer space
20,000 - 65,535: static SDP default range (user defined)

TCP:
tcp 0 0 0.0.0.0:554 0.0.0.0:* LISTEN 22082/DarwinStreami
tcp 0 0 0.0.0.0:1220 0.0.0.0:* LISTEN 22081/perl
tcp 0 0 0.0.0.0:7070 0.0.0.0:* LISTEN 22082/DarwinStreami
tcp 0 0 0.0.0.0:8000 0.0.0.0:* LISTEN 22082/DarwinStreami
tcp 0 0 0.0.0.0:8001 0.0.0.0:* LISTEN 22082/DarwinStreami

UDP:
udp 0 0 192.168.100.115:6970 0.0.0.0:* 22082/DarwinStreami
udp 0 0 192.168.100.115:6971 0.0.0.0:* 22082/DarwinStreami

HTML Streaming component embedding


In order to play a live stream fed by a streaming source for example: Apple Quicktime Broadcaster, here is an example of an HTML embedded Quicktime component code that upon clicking into the component start the connection to the streaming server. The live streaming source program must provide the same filename as the one provided in the component to have a successful streaming connection.

Detached video window HTML code:
<HTML><head>
<meta http-equiv="content-type" content="text/html;charset=iso-8859-1">
<title>Streaming</title>
<script src="mediaCode.js" type="text/javascript"></script>
<style type="text/css" title="text/css">
body {background: #bbb;}
p { font-family:Verdana, Arial, sans-serif; font-size:10px; padding:0;margin-top:4px;}
</style>
</head>
<body>
<CENTER><B><FONT color="green" face="verdana" size="3">L I V E</FONT></B><br>
<p>(Well, almost live... approx. 10 sec. delay)</p>
<noscript>
<p style="color:red;">You need to enable Javascript to see this content<p>
</noscript>
<TABLE border=1 cellpading=0 cellspacing=0><TR><TD>
<script language="JavaScript"type="text/javascript">
<!--
var myArray = new Array();
myArray["data"] = "Graph/Poster.mov";
myArray["title"] = "Live Streaming";
myArray["height"] = "270";
myArray["width"] = "320";
myArray["controller"] = "true";
myArray["loop"] = "false";
myArray["href"] = "rtsp://www.berlin-radio.net:554/stream1.sdp";
writeMediaCode(myArray);
//-->
</script></TD></TR>
</TABLE>
<p>Click in the above box to start viewing/listening the streaming.<BR>
<B>NOTE:</B><I> If it happens that you lose the sound,
reload this web page and click in the above box again.
<I></p>
</body>
</HTML>

Content of JavaScript File: mediaCode.js
var objectArr = new Array();
var paramArr = new Array();
var embedArr = new Array();
function writeMediaCode(myArray)
{
objectArr["data"] = myArray["data"];
objectArr["type"] = "video/quicktime";
objectArr["title"] = myArray["title"];
objectArr["classid"] = "clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B";
objectArr["height"] = myArray["height"];
objectArr["width"] = myArray["width"];
paramArr["src"] = objectArr["data"];
paramArr["autoplay"] = "true";
paramArr["controller"] = myArray["controller"];
paramArr["loop"] = myArray["loop"];
paramArr["target"] = "myself";
paramArr["href"] = myArray["href"];
paramArr["pluginspage"] = "http://www.apple.com/quicktime/download/";
//paramArr["bgcolor"] = "996633";
embedArr["src"] = objectArr["data"];
embedArr["type"] = objectArr["type"];
embedArr["classid"] = objectArr["classid"];
embedArr["title"] = objectArr["title"];
embedArr["height"] = objectArr["height"];
embedArr["width"] = objectArr["width"];
embedArr["autoplay"] = paramArr["autoplay"];
embedArr["controller"] = paramArr["controller"];
embedArr["loop"] = paramArr["loop"];
embedArr["target"] = paramArr["target"];
embedArr["href"] = paramArr["href"];
embedArr["pluginspage"] = paramArr["pluginspage"];
//embedArr["bgcolor"] = paramArr["bgcolor"];
// object tag
document.write('<object');
for(name in objectArr)
{
document.write(' '+name+'="'+objectArr[name]+'"');
}
document.write('>\n');
// params
for(name in paramArr)
{
document.write('<param name="'+name+'" value="'+paramArr[name]+'">\n');
}
// embed
document.write('<embed');
for(name in embedArr)
{
document.write(' '+name+'="'+embedArr[name]+'"');
}
document.write('</embed>\n');
// end
document.write('</object>\n');
}