Chapter 18. Red5 Demo Applications

This document explains how to add and maintain Red5 demo applications which are downloaded on demand using the installer application located at http://localhost:5080/installer.

18.1. Getting Red5 Demo Applications Server-Side and Client-Side Source

  1. With your favourite SVN client check out the source code from svn at this address http://red5.googlecode.com/svn/java/example/trunk/ or https://red5.googlecode.com/svn/java/example/trunk/ if you have a google code login.

  1. With your favourite SVN client check out the source code from svn at this address http://red5.googlecode.com/svn/flash/trunk/ or https://red5.googlecode.com/svn/flash/trunk/ if you have a google code login.

18.2. List Of Available Demo Applications (Server Side)

  • SOSample - A simple shared ball demo that makes use of Shared Objects.

  • admin - The Red5 administration panel.

  • echo - A test application that runs RTMP/AMF datatype tests.

  • oflaDemo - Simple video player as shown on the Online Open Source Flash conference.

  • bwcheck - Demo application that detects the client bandwidth.

  • fitcDemo - Video conference with chat.

18.3. List Of Available Demo Applications (Client Side)

  • admin - The admin panel client application

  • bwcheck - Demo to interface with the bandwidth check application, tests both download and upload rates.

  • echo - Simple echo test AMF client

  • loadtest - Simple loading testing tool, requesting a file multiple times.

  • port-tester - Open port tester application.

  • publisher - Simple broadcaster application

18.4. Environment Build Setup

To build the demo applications and add WAR snapshots to the subversion repository, the ant environment requires a SvnAnt task library added to the ant common library directory:

  1. Go here: http://subclipse.tigris.org/svnant.html

  2. Download the latest SvnAnt

ex: http://subclipse.tigris.org/files/documents/906/43359/svnant-1.2.0-RC1.zip

  1. Unzip the archive and place the jar files in your Ant lib directory


ex: C:\dev\ant\lib

4. Using your svn client or subclipse svn client in eclipse checkout or update the snapshots repository https://red5.googlecode.com/svn/snapshots. It will keep the registry.xml file up to date for modifying later.

  1. Add these variables to a build.properties file into user home directory

svn.url=http://red5.googlecode.com/svn/snapshots/ svn.login=youruser svn.password=the google code password snapshot.path=/www/red5_snapshots/ Where snapshot.path is the path to the checked out snapshots directory.

18.5. Building The Demo Application

To build the application and upload the created WAR file to the snapshots repository run the following ant target.


ant upload-snapshot

18.6. Updating The Applications Registry

Once the updated WAR has been uploaded to the snapshots repository, the registry.xml file requires to be updated so the demo applications installer will collect the update.

  1. Locate in the console output after uploading snapshot something like Destination: /www/red5_snapshots/admin- r3197-java6.war the file of the new war will be admin- r3197-java6.war.

  2. Edit the registry.xml in the snapshots checkout update the webapp entry with the new filename and commit the change

ie



<application name="admin">
			<author>Martin M, Dan Rossi</author>
			<desc>Administration console</desc>
			<filename>admin-r3197-java6.war</filename>
</application>

[Note]Note

Subclipse version for committing changes also made by svnant in the snapshots repository, needs to be version 1.4 which is bound to subversion version 1.5 using this update site http://subclipse.tigris.org/update_1.4.x. Other svn clients also need to be bound to subversion 1.5 or you will get client too old errors.

18.7. Bandwidth Check Application

This section explains the bandwidth check application and how to use it. The bandwidth check application handles two service method calls to trigger a download or upload rate check and return information to the flash client to determine what video bitrate to use.

18.7.2. Bandwidth Check Service Methods

The service method is enabled in the bean with a name bwCheckService.service.



<bean id="bwCheckService.service" class="org.red5.demos.bwcheck.BandwidthDetection" />

Inside the BandwidthDetection class there are two service methods:

  • Trigger a server to client rate check



 public void onServerClientBWCheck(Object[] params) {
		IConnection conn = Red5.getConnectionLocal();
		ServerClientDetection serverClient = new ServerClientDetection();
		serverClient.checkBandwidth(conn);
 }

  • Trigger a client to server rate check



 public Map<String, Object> onClientBWCheck(Object[] params) {
		ClientServerDetection clientServer = new ClientServerDetection();
		return clientServer.onClientBWCheck(params);
 }

18.7.3. ServerClientDetection

The ServerClientDetection class detects server to client bandwidth. 3 set of payload data arrays are intialized, the first with 1200 keys, and the next two with 12000 keys ie



for (int i = 0; i < 12000; i++) {
  payload_1[i] = Math.random();
}

  p_client.setAttribute("payload_1", payload_1);

The start microtime is recorded, along with an initial number of bytes sent to the client.

To initiate the handshake with the client method onBWCheck is called with parameters

  • count - the number of times a result has been received from the client

  • sent - the number of times the client method onBWCheck has been called

  • timePassed - The interval time in milliseconds since the beginning of the bandwidth checking has occured.

  • latency -

  • cumLatency - the value of the increased passes from server to client.



private void callBWCheck(Object payload)
	{
		IConnection conn = Red5.getConnectionLocal();
		

		Map<String, Object> statsValues = new HashMap<String, Object>();
		statsValues.put("count", this.count);
		statsValues.put("sent", this.sent);
		statsValues.put("timePassed", this.timePassed);
		statsValues.put("latency", this.latency);
		statsValues.put("cumLatency", this.cumLatency);
		statsValues.put("payload", payload);
		
		if (conn instanceof IServiceCapableConnection) {
			((IServiceCapableConnection) conn).invoke("onBWCheck", new Object[]{statsValues}, this);
		}
	}

An initial payload is sent with a size of 1200 keys, of the second pass, if the pass count is less than 3 and the time interval passed is less than 1 second progressively increase the payload packet sent with a size of 12000 keys.

On the next pass if its between 3 and less than 6 times and less than 1 second, send the 3rd payload packet.

On the next pass if its greater than 6 times and less than 1 second, send the 4th payload packet.

Once the times passed reaches the amount of times sent, send the client the calculated rate, calculated by the following



this.deltaDown = (endStats.getWrittenBytes() - beginningValues.get("b_down")) * 8 / 1000; // bytes to kbits
            this.deltaTime = ((now - beginningValues.get("time")) - (latency * cumLatency)) / 1000; // total dl time - latency for each packet sent in secs
            
            if (Math.round(deltaTime) <= 0) {
				this.deltaTime = (now - beginningValues.get("time") + latency) / 1000;
			}
			this.kbitDown = Math.round(deltaDown / deltaTime); // kbits / sec
			
            if (kbitDown < 100) this.kbitDown = 100;
            
            log.info("onBWDone: kbitDown: {} deltaDown: {} deltaTime: {} latency: {} ", new Object[]{kbitDown, deltaDown, deltaTime, this.latency});
            
            this.callBWDone();                                 

This will call a client method onBWDone

  • kbitDown - the kbits down value

  • deltaDown -

  • deltaTime -

  • latency - The latency delay calculated between server and client



private void callBWDone()
	{
		IConnection conn = Red5.getConnectionLocal();
		
		Map<String, Object> statsValues = new HashMap<String, Object>();
		statsValues.put("kbitDown", this.kbitDown);
		statsValues.put("deltaDown", this.deltaDown);
		statsValues.put("deltaTime", this.deltaTime);
		statsValues.put("latency", this.latency);
		
		if (conn instanceof IServiceCapableConnection) {
			((IServiceCapableConnection) conn).invoke("onBWDone", new Object[]{statsValues});
		}
	}

18.7.3.1. Client Side Download Detection

Client side callback methods are setup to enable the detection.


public function onBWCheck(obj:Object):void
{
dispatchStatus(obj);
}

public function onBWDone(obj:Object):void 

dispatchComplete(obj);


And then the information is obtainable on the Object argument


public function onServerClientComplete(event:BandwidthDetectEvent):void
{
txtLog.data += "\n\n kbit Down: " + event.info.kbitDown + " Delta Down: " + event.info.deltaDown + " Delta Time: " + event.info.deltaTime + " Latency: " + event.info.latency;
txtLog.data += "\n\n Server Client Bandwidth Detect Complete";
txtLog.data += "\n\n Detecting Client Server Bandwidth\n\n";
ClientServer();
}

18.7.4. ClientServerDetection

The ClientServerDetection class helps detect client to server bandwidth. The server side method onClientBWCheck is called with some information to help the client to determine the bandwidth.

  • cOutBytes - The bytes read from the client

  • cInBytes - The bytes sent to the client

  • time -



public Map<String, Object> onClientBWCheck(Object[] params) {
		final IStreamCapableConnection stats = this.getStats();

		Map<String, Object> statsValues = new HashMap<String, Object>();
		Integer time = (Integer) (params.length > 0 ? params[0] : 0);
		statsValues.put("cOutBytes", stats.getReadBytes());
		statsValues.put("cInBytes", stats.getWrittenBytes());
		statsValues.put("time", time);
		
		log.info("cOutBytes: {} cInBytes: {} time: {}", new Object[]{stats.getReadBytes(), stats.getWrittenBytes(), time});

		return statsValues;

	}