The Red5 demo applications are available for downloaded on demand using the installer application located at http://localhost:5080/installer.
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.
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.
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.
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
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:
Download the latest SvnAnt
ex: http://subclipse.tigris.org/files/documents/906/43359/svnant-1.2.0-RC1.zip
Unzip the archive and place the jar files in your Ant lib directory
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.
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.
To build the application and upload the created WAR file to the snapshots repository run the following ant target.
$ ant upload-snapshot
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.
ie
<application name="admin"> <author>Martin M, Dan Rossi</author> <desc>Administration console</desc> <filename>admin-r3197-java6.war</filename> </application>
![]() | 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. |
Following is documentation for the demo applications:
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.
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); }
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}); } }
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();
}
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; }