msgbartop
Various ramblings-on, mostly about Red5
msgbarbottom

25 Aug 10 Building the latest Xuggler for Windows

I recently had reason to build the latest cutting-edge version of Xuggler for my Windows environment and I want to share the experience. Mind you, I have had to do this a few times before including when the project was still named AAFFMPEG and was “unreleased”. The process has been
made a lot simpler due to the hard work of Xuggle and its community (Special thanks to Jonathan Ben). BTW if you want to skip all the steps and get the build I created, you can find it here: xuggle-xuggler.4.0.1049-win32-setup.exe

Get all of the following applications / tools if you don’t already have them; they are all FREE.
Get the 1.6 JDK
– Install it
Get 7zip (due to MinGW file compression)
– Install it
Get the zlib dll
– Copy into Windows\System32 directory
Get the preconfigured MinGW
– Unzip into C:\MinGW
– Add C:\MinGW\bin path to the PATH environmental variable
Get the Msys installer
– Install to C:\msys (not C:\msys\1.0)
– Create a directory under C:\msys name “local”
– Add C:\msys\bin path to the PATH environmental variable
Get Ant
– Unzip into C:\ant
– Create a new environment variable named “ANT_HOME” with a value of C:\ant
– Add C:\ant\bin path to the PATH environmental variable
Get SilkSVN (good command line tool, otherwise I suggest TortoiseSVN)
– Install it
Get NSIS (if you want to build the installer)
– Install it
– Add C:\Program Files\NSIS path to the PATH environmental variable
Get Visual C++ 2010 Express
– Select your language on the form
– Install it (a reboot will usually be required)
Now for the fun! Be aware that this takes awhile to complete, on my system it took 76 minutes.
1. Enter the Visual Studio command environment by selecting the “Visual Studio Command Prompt (2010)” link in the start menu
2. Change directory to C:\MinGW
3. Execute “msys.bat”
4. Check out the project source from subversion
svn co http://xuggle.googlecode.com/svn/trunk/
6. Navigate to the xuggler directory
cd trunk/java/xuggle-xuggler
7. For the heck of it run this first
ant clobber
8. Now build while also running tests and producing installers
ant run-tests dist

Et voila! (if everything works, as it did for me)

If you run into an issue where “libraries can’t be found”, you are probably missing the zlib library. I have posted a defect for this here.

Tags: , , , , , ,

31 Mar 10 Stop complaining about Flash

If people aren’t complaining about Flash and HTML5 they are falling back to NoSQL vs RDBMS. There is a time and a place for everything, just remember that tidbit. So to get on with it, I would like to state that I am mostly a Windows user and I love Windows 7.. It f#@king rocks! I also use Google Chrome as my primary browser on both OSX and Windows. I recently loaded the latest dev build of Chrome that contains a streamlined Flash Player and I can say that it is awesome.
To test, I started up a Red5 instance with some mp4 and vp6 videos to see what the CPU usage would be and here is the result: Red5 = 0% to 7% and Chrome = 3% to 6% (average 3%)
The playback was smooth as silk and the audio was perfect. Next up for comparison, I tried IE and FF:
IE 8 with FP10.1 = 5% to 11% (average 5%)
Firefox 3.6 with FP 10.1 = 14% to 66% (average 40%)

Tags: , , , , , , ,

08 Aug 09 Large if block vs list lookup

In Java, something which has always caught my eye or bugs me to no end is a large “if” block. Normally I refactor these into a “switch” to make it cleaner and easier to read, but in the case of String comparison it becomes more difficult. To diverge for a moment, I would point out that you can use a string’s hash code for a switch but you must know it ahead of final compilation (pita). So to get back to the point of this post, I want to show a little code I used today to remove an unruly looking if statement. This is the original code from Red5 (code shortened for brevity):

if (action.equals(ACTION_CREATE_STREAM)
		|| action.equals(ACTION_DELETE_STREAM)
		|| action.equals(ACTION_RELEASE_STREAM)
		|| action.equals(ACTION_PUBLISH)
		|| action.equals(ACTION_PLAY)
		|| action.equals(ACTION_SEEK)
		|| action.equals(ACTION_PAUSE)
		|| action.equals(ACTION_PAUSE_RAW)
		|| action.equals(ACTION_CLOSE_STREAM)
		|| action.equals(ACTION_RECEIVE_VIDEO)
		|| action.equals(ACTION_RECEIVE_AUDIO)) {
	//do something
}

This section has always bugged me, so I decided to make a collection containing all these strings. There may be 11 calls to String.equals in this block alone! Our “optimization” has a problem and it is that the “Constants” class containing the actions is an interface and as we all know you cant execute methods in an interface, or can we?

public static final List<String> STREAM_ACTION_LIST = new ArrayList<String>(11){
	{
		//Add all the stream actions to make lookup simpler
		add(ACTION_CREATE_STREAM);
		add(ACTION_DELETE_STREAM);
		add(ACTION_RELEASE_STREAM);
		add(ACTION_PUBLISH);
		add(ACTION_PLAY);
		add(ACTION_SEEK);
		add(ACTION_PAUSE);
		add(ACTION_PAUSE_RAW);
		add(ACTION_CLOSE_STREAM);
		add(ACTION_RECEIVE_VIDEO);
		add(ACTION_RECEIVE_AUDIO);
	}
};

Using a class initializer we can accomplish what we want! If you use this, dont forget to replace the brace characters.
So now the old if block becomes this:

if (STREAM_ACTION_LIST.contains(action)) {
	//do something
}

Tags: , ,

07 Aug 09 How to add an IoFilter per Application or Server

A new feature has been added to Red5 to allow any number of Mina IoFilters to be added to a connection at the Server or Application level. The particular filter detailed here is one that simply counts the connections and rejects any that exceed the set maximum number. This post details setting the filter at the Application level, but if you want it at the server level simply add the below bean definitions to your global webapp configuration located here: red5/webapps/red5-default.xml.

To add the filter you must first edit your applications red5-web.xml and add your beans:

<!-- Limits connections on a per-session basis -->
<bean id="connectionFilter" class="org.gregoire.red5.ConnectionShapeFilter">
    <property name="maxConnections" value="2"/>
</bean>			

Next create a “config” bean to inform the server about your filter bean names:

<bean id="config" class="org.red5.server.adapter.Config">
    <!-- List of filter bean names to be loaded -->
    <property name="filterNames">
        <list>
	    <value>connectionFilter</value>
	</list>
    </property>
</bean>  	

One important thing to note is that since classes in the main server are creating the connections, your filter classes must be found by the URLClassloader. The URLClassloader created by the server uses jar files within Red5’s lib directory, so put your filter classes here (red5/lib) inside a jar. Once your classes are in-place, start your server and the filters will take effect.

An example Eclipse / FlexBuilder project can be found here.

Tags: , , ,

15 Jun 09 Quartz schedulers

When you want to schedule a particular task or job within Red5, you have at least two options available which are built into the server. We use Quartz for our scheduler, but you are not required to use it; I just wanted to get that disclaimer out of the way, this is Java so use whatever you like.  The first option is the “server-wide” scheduler which is created when the server starts up and requires no configuration from your application. This scheduler is sufficient for most of the jobs you may want to create, but you will run into problems if you attempt to access an application class from within your job. The second option resolves this issue by providing an application level scheduler, one which can access your classes. The only caveat with this scheduler is that you must provide some configuration details, your applications context name.

Accessing the “server-wide” scheduler is done in your application like so (using scope):

schedulingService = (ISchedulingService) scope.getContext().getBean(ISchedulingService.BEAN_NAME);

Accessing the application scheduler is slightly different (using app context):

schedulingService = (ApplicationSchedulingService) ((BeanFactory) applicationContext).getBean("scheduler");

I prefer to make sure the schedulingService member is setup in my “appStart” method, since this is essentially where the application is “started” within Red5.

The following entry must be made in your applications red5-web.xml file if you want to use an application scheduler:

<bean id="scheduler" class="org.red5.server.scheduling.ApplicationSchedulingService">	 	
    <property name="applicationName" value="myapp" />
</bean>

Make sure you set the correct application name / context (replace “myapp”).
Once you have the scheduling service, you can add your job amongst many other options which I don’t want to cover here.

Tags: , , , , , ,

06 Jun 09 PHP support in Red5

I’ve updated my “parameterdemo” to include a couple PHP pages. The latest trunk (0.8.1-dev) now supports PHP through the use of Quercus. To enable it simply set a context parameter in your web.xml and include the quercus and resin-utils jars in your WEB-INF/lib. See the zip file for a complete example (eclipse + ant).

Once you deploy the war, go to these urls to test (update your port to match your servers setting):

PHP example getting value from Red5 application: 

<a href="http://localhost/parameterdemo/getparam.php">http://localhost/parameterdemo/getparam.php</a>

Same example with debug output: 

<a href="http://localhost/parameterdemo/getparam.php?debug=true">http://localhost/parameterdemo/getparam.php?debug=true</a>

Java servlet example: 

<a href="http://localhost/parameterdemo/myservlet">http://localhost/parameterdemo/myservlet</a>

The web.xml entry must look like so:

	<context-param>
	   <param-name>enable-php</param-name>
	   <param-value>true</param-value>
	</context-param>

Note: You dont have to install Resin to use Quercus, simply download one of the wars on this page: http://quercus.caucho.com/ and grab the libraries from WEB-INF/lib

Tags: , , , , ,

06 Jun 09 FFMPEG made super simple

Robert and Art continue to amaze me with their Xuggler project. If you are like me and have had to use FFMPEG in a project (Java in my case), you know how hard it can be to get everything working correctly. Xuggler has some how made this even more easy than with their 1.0 version. Through the use of their MediaTool you can do some incredible stuff; the stuff that should have been possible with JMF! Do yourself a favor and check out their post about the MediaTool.

As a minor side note, Xuggler has changed its license to AGPL with the 3.0 release.

Tags: , , , ,

25 May 09 Memory leak?

A poster to the Red5 list posted this today and claims that it exposes a memory leak in the server. The individual states that he doesnt know Java very well, so having been in the Java-game for 10+ years I immediately spot a potential leak in his method.

public void privMessage(String sendto, String message) {
IConnection conn = Red5.getConnectionLocal();
IClient client = conn.getClient();
IScope scope = getScope();
IContext context = getContext();
IClientRegistry reg = context.getClientRegistry();
if (reg.hasClient(sendto)) {
IClient recip = reg.lookupClient(sendto);
Set[IConnection] rcons = recip.getConnections(scope);
Iterator[IConnection] it = rcons.iterator();
while (it.hasNext()) {
IConnection rcon = it.next();
if (rcon instanceof IServiceCapableConnection)
((IServiceCapableConnection) rcon).invoke("privComm", new Object[]{client.getId(),message});
}
}
}

The big red flag for me is the use of an Iterator and the second thing is the use of an object reference within a loop. So to fix these potential leak candidates, I offer two solutions below.

Removal of the Iterator by using for-each:

IConnection conn = Red5.getConnectionLocal();
IClient client = conn.getClient();
IContext context = getContext();
IClientRegistry reg = context.getClientRegistry();
if (reg.hasClient(sendto)) {
IClient recip = reg.lookupClient(sendto);
String clientId = client.getId();
Set[IConnection] rcons = recip.getConnections(scope);
for (IConnection rcon : rcons) {
if (rcon instanceof IServiceCapableConnection)
((IServiceCapableConnection) rcon).invoke("privComm", new Object[]{clientId,message});
break;
}
}

Overall I think this is the best solution and is what I would implement:

1. In your ApplicationAdapter, create a map containing your client id to connection mappings

// map to keep track of connections by client id
private static ConcurrentMap[String, IConnection] connectionMap = new ConcurrentHashMap[String, IConnection](31);

2. In your connect method, add the incomming clients to the map

@Override
public boolean connect(final IConnection conn, IScope scope, Object[] params) {
// call original method of parent class
if (!super.connect(conn, scope, params)) {
return false;
}
// get the connections client id
IClient client = conn.getClient();
if (client != null) {
String clientId = client.getId();
// check the map for the client
if (!connectionMap.containsKey(clientId)) {
// register the connection
connectionMap.put(clientId, conn);
} else {
log.warn("Client id {} already exists in connection map",
clientId);
}
}
return true;
}

3. Simplify your method

public void privMessage(String sendto, String message) {
IConnection conn = Red5.getConnectionLocal();
IClient client = conn.getClient();
//senders client id
String clientId = client.getId();
if (connectionMap.containsKey(sendto)) {
IConnection rcon = connectionMap.get(sendto);
if (!ServiceUtils.invokeOnConnection(rcon, "privComm", new Object[]{clientId, message})) {
log.warn("Private message to client id: {} failed", sendto);
}
} else {
//notify sender that recipient is not available
ServiceUtils.invokeOnConnection(conn, "onError", new Object[]{"Client was not available"});
}
}

4. Dont forget to remove the map entries when the client disconnects

@Override
public void appDisconnect(IConnection conn) {
// get the previously stored id
String clientId = conn.getClient().getId();
// unregister user
IConnection cn = connectionMap.remove(clientId);
}

Please note that for the generic type args, I am using square braces for word press formatting reasons. Make sure you replace them with < and > before using the code

Tags: , , , , ,

08 May 09 Flash on Tap: Red5 Workshop

FOT is coming up real soon… I’m co-presenting with Dominick for the Red5 workshop and I would like to know what you guys want to see? Since its an all-day thing, I would be glad to get some input from the community. Post your ideas as comments.

Tags: , , , , ,

07 May 09 Azdroids

I wrote a new Android application today while on my “Vacation”, this one is based on one of my favorite classic games – Asteroids. I still have a lot of bugs and clean up to complete, but by looking at the screencast you can see that it is playable.

Tags: , , ,


Fatal error: Call to undefined function akismet_counter() in C:\xampp\htdocs\paulgregoireblog\wp-content\themes\googlechrome\footer.php on line 9