Code:Server bandwidthdetection updated

From Red5Tutorials

Jump to: navigation, search

After trying the original code written by Dan Rossi (see here), I shortened the code and also added upload speed dectection. (9th September 2009)

Red5

Calling example

public boolean appConnect(IConnection conn) {
	BandwidthDetection detect = new BandwidthDetection();
	detect.checkBandwidth(conn);
}

Class IBandwidthDetection.java

import org.red5.server.api.IConnection;

public interface IBandwidthDetection {
       
	public void checkBandwidth(IConnection p_client);
	public void calculateClientBw(IConnection p_client);
}

Class BandwidthDetection.java:

import org.red5.server.adapter.MultiThreadedApplicationAdapter;
import org.red5.server.api.IConnection;
import org.red5.server.api.service.IPendingServiceCall;
import org.red5.server.api.service.IPendingServiceCallback;
import org.red5.server.api.service.IServiceCapableConnection;
import org.apache.log4j.Logger;

public class BandwidthDetection implements IPendingServiceCallback, IBandwidthDetection {
	//---------------------------------------------------------
	protected IConnection conn;
	protected Logger log = Logger.getLogger(MultiThreadedApplicationAdapter.class);
	protected boolean checkLatency = false;
	protected double latency = 0;
	protected Long writtenOffset;
	protected Long readOffset;
	protected Long bwStart;
	//---------------------------------------------------------
	
	public BandwidthDetection(){
		//...
	}
	   
	public void checkBandwidth(IConnection conn){
		// Start checking
		this.conn = conn;
		
		// Reset
		this.checkLatency = false;
		this.latency = 0;
		
		// Calc latency
		this.getLatency();	    
	}
	
	protected void getLatency(){
		// Update flag
		this.checkLatency = true;
		
		// Update start
		this.bwStart = System.currentTimeMillis();
		
		// Send packet
		this.sendPacket(1);
	}
	
	protected void sendPacket(int numBytes){
		try{
			// Send
			this.callBWCheck(new byte[numBytes]);	
		}catch (Exception e){
			// Error
			log.error(e.getMessage());
		}
	}
	   
	public void calculateClientBw(IConnection conn){
		try{
			// Update
			this.writtenOffset = this.conn.getWrittenBytes();
			this.readOffset = this.conn.getReadBytes();
			
		    	// Update start
			this.bwStart = System.currentTimeMillis();
			
			// Send packet
			this.sendPacket(1024);
		}catch (Exception e){
			// Error
			log.error(e.getMessage());
		}
	}
	   
	/**
	 * Handle callback from service call. 
	 */
	public void resultReceived(IPendingServiceCall call) { 
		try{
			// Check flag
			if(this.checkLatency){
				// Update flag
				this.checkLatency = false;
				
				// Store latency
				this.latency = ((double)(System.currentTimeMillis() - this.bwStart)) / 1000.00;
				
				// Start BW check
				this.calculateClientBw(this.conn);
			}
			
			// Check time
			if((System.currentTimeMillis() - this.bwStart) < 1000){
				
				// Send another packet
				this.sendPacket(1024);
			}else{
				
				// Get total time
				double totalTime = (System.currentTimeMillis() - this.bwStart);

				// Work out bandwidth
				this.callBWDone(Math.round(((this.conn.getWrittenBytes() - this.writtenOffset) * 8) / totalTime), Math.round(((this.conn.getReadBytes() - this.readOffset) * 8) / totalTime), this.latency);
			}
		}catch (Exception e){
			// Error
			log.error(e.getMessage());
		}
	}
	   
	private void callBWCheck(Object params){   
		try{
			if(this.conn instanceof IServiceCapableConnection) {
				((IServiceCapableConnection) this.conn).invoke("onBWCheck", new Object[]{params}, this);
			}
		}catch (Exception e){
			// Error
			log.error(e.getMessage());
		}
	}
	   
	private void callBWDone(double kbpsDown, double kbpsUp, double latency){    
	    try{
	    	if(this.conn instanceof IServiceCapableConnection) {
	    		((IServiceCapableConnection) this.conn).invoke("onBWDone", new Object[]{kbpsDown, kbpsUp, latency});
	    	}
	    }catch (Exception e){
			// Error
			log.error(e.getMessage());
		}
	}
}

Flex / AS3

Client Side:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="onAppComplete()" width="602" height="211">
	<mx:Script>
		<![CDATA[
			import flash.utils.ByteArray;
			import flash.net.Responder;
			import flash.net.NetConnection;
	 		//-----------------------------------------------------------------------
			protected var nc:NetConnection;
			protected var serverURL:String = "rtmp://www.YourRed5Server.org/bwcheck";
			//-----------------------------------------------------------------------
			protected var uploading:Boolean = false;
			protected var uploadPacket:ByteArray;
			//-----------------------------------------------------------------------

			protected function onAppComplete():void{
				// Create upload packet
				this.uploadPacket = new ByteArray();
				this.uploadPacket.length = 1024;
				
				// Create connection
				this.nc = new NetConnection();
				this.nc.client = this;
				this.nc.connect(serverURL);	
			}

			protected function onUploadResponse(event:Object):void{
				try{
					// Check flag
					if(this.uploading){
						// Write
						this.nc.call("uploadTest", new Responder(this.onUploadResponse), this.uploadPacket);
					}
				}catch(e:Error){
					// Error
				}
			}
           
			public function onBWCheck(obj:Object):void{
				// Check upload
				if(!this.uploading){
				
					// Update flag
					this.uploading = true;
				
					// Write
					this.nc.call("uploadTest", new Responder(this.onUploadResponse), this.uploadPacket);
				}
			}
		
			public function onBWDone(kbpsDown:Number, kbpsUp:Number, latency:Number):void{
				// Update flag
				this.uploading = false;
			
				// Log
				this.txtLog.text = "kbpsDown: " + kbpsDown + "\n";
				this.txtLog.text += "kbpsUp: " + kbpsUp + "\n";
				this.txtLog.text += "Latency: " + latency;
			}
		]]>
	</mx:Script>
	<mx:TextArea x="0" y="0" width="602" height="211" id="txtLog"/>
</mx:Application>
Personal tools