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: ant, c, ffmpeg, Java, mingw, msys, xuggle
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: chrome, firefox, flash, html5, ie8, Java, mp4, Red5
Red5 now supports “native” RTMPS in addition to RTMPT over SSL. To use this feature you will need to use the current trunk version until 0.9 RC3 or Final are released. A big shout-out goes to Kevin Green for providing the original patch. Using this communication channel, your data will be secured throughout the process from connection to shutdown using TLS/SSL and should provide the secure features you need until RTMPE is ready.

Red5NativeRTMPS
nc = new NetConnection(); nc.client = this; nc.proxyType = "best";
For this example I used a free opensource ssl cert provided by godaddy.
Step by step process:
1. Create your key
keytool -keysize 2048 -genkey -alias red5 -keyalg RSA -keystore keystore
Enter keystore password:
Re-enter new password:
What is your first and last name?
[Unknown]: ssl.red5.org
What is the name of your organizational unit?
[Unknown]: Dev
What is the name of your organization?
[Unknown]: Red5
What is the name of your City or Locality?
[Unknown]: Henderson
What is the name of your State or Province?
[Unknown]: Nevada
What is the two-letter country code for this unit?
[Unknown]: US
Is CN=ssl.red5.org, OU=Dev, O=Red5, L=Henderson, ST=Nevada, C=US correct?
[no]: yes
Enter key password for <red5>
(RETURN if same as keystore password):
2. Create a CSR
keytool -certreq -keyalg RSA -alias red5 -file red5.csr -keystore keystore Enter keystore password:
3. Submit your CSR to your SSL certificate provider. Godaddy process is described below.
4. After your receive your certificate, import the root cert into your keystore file
keytool -import -alias root -keystore keystore -trustcacerts -file valicert_class2_root.crt Enter keystore password: Certificate already exists in system-wide CA keystore under alias <valicertclass2ca> Do you still want to add it to your own keystore? [no]: yes Certificate was added to keystore
5. Import the cross certificates
keytool -import -alias cross -keystore keystore -trustcacerts -file gd_cross_intermediate.crt Enter keystore password: Certificate was added to keystore
6. Import the intermediate certificates
keytool -import -alias intermed -keystore keystore -trustcacerts -file gd_intermediate.crt Enter keystore password: Certificate was added to keystore
7. Import your certificate
keytool -import -alias red5 -keystore keystore -trustcacerts -file ssl.red5.org.crt Enter keystore password: Certificate reply was installed in keystore
8. Setup RTMPS in your red5/conf/red5-core.xml. You may notice that some of the rtmp variables are used here, that is only for ease of setup; you could set them to whatever you prefer.
<bean id="rtmpsMinaIoHandler"
class="org.red5.server.net.rtmps.RTMPSMinaIoHandler">
<property name="handler" ref="rtmpHandler" />
<property name="codecFactory" ref="rtmpCodecFactory" />
<property name="rtmpConnManager" ref="rtmpMinaConnManager" />
<property name="keyStorePassword" value="${rtmps.keystorepass}" />
<property name="keystoreFile" value="conf/keystore" />
</bean>
<bean id="rtmpsTransport" class="org.red5.server.net.rtmp.RTMPMinaTransport" init-method="start" destroy-method="stop">
<property name="ioHandler" ref="rtmpsMinaIoHandler" />
<property name="connectors">
<list>
<bean class="java.net.InetSocketAddress">
<constructor-arg index="0" type="java.lang.String" value="${rtmps.host}" />
<constructor-arg index="1" type="int" value="${rtmps.port}" />
</bean>
</list>
</property>
<property name="receiveBufferSize" value="${rtmp.receive_buffer_size}" />
<property name="sendBufferSize" value="${rtmp.send_buffer_size}" />
<property name="eventThreadsCore" value="${rtmp.event_threads_core}" />
<property name="eventThreadsMax" value="${rtmp.event_threads_max}" />
<property name="eventThreadsQueue" value="${rtmp.event_threads_queue}" />
<property name="eventThreadsKeepalive" value="${rtmp.event_threads_keepalive}" />
<property name="jmxPollInterval" value="1000" />
<property name="tcpNoDelay" value="${rtmp.tcp_nodelay}" />
</bean>
Additional security info can be found here
The testing player source can be found here

Screenshot of playing nsv stream in flash
This morning I was successful in playing a live NSV stream with FlashPlayer via Red5. I used NSVCap encoding VP62 and AAC. The code is implemented using the new Red5 plug-in system and will be released with 0.9.0 (soon). Huge thank yous go out to Andy Shaules and Wittawas Nakkasem for their help developing this feature.
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: Java, optimization, Red5
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: iofilter, Java, mina, Red5
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: Java, job, quartz, Red5, schedule, task, timer
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: bean, Java, parameter, PHP, Red5, servlet
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: ffmpeg, Java, jmf, media, xuggler
Red5 version 0.8.0 introduces the ability to bind multiple ports and hosts for HTTP access; starting at revision 3632. Previously there were other options to accomplish this feature, but now it is built-in. So I’ll get right to it. The older configuration style for the tomcat server bean was like so:
<bean id="tomcat.server" class="org.red5.server.tomcat.TomcatLoader" init-method="init" destroy-method="shutdown" depends-on="context.loader">
<property name="webappFolder" value="${red5.root}/webapps" />
<property name="connector">
<bean class="org.apache.catalina.connector.Connector">
<constructor -arg type="java.lang.String" value="org.apache.coyote.http11.Http11NioProtocol" />
<property name="port"><value>${http.port}</value></property>
<property name="redirectPort"><value>${https.port}</value></property>
<property name="enableLookups"><value>false</value></property>
</bean>
</property>
<property name="baseHost">
<bean class="org.apache.catalina.core.StandardHost">
<property name="name" value="${http.host}" />
<property name="unpackWARs" value="true" />
<property name="autoDeploy" value="true" />
<property name="xmlValidation" value="false" />
<property name="xmlNamespaceAware" value="false" />
</bean>
</property>
</bean>
This allowed for one connector (port) and one host (like www.red5.org). If http.host were set to “192.168.0.1″ and http.port was set to “5080″, then you would be able to connect to “http://192.168.0.1:5080/” in your browser.
This latest configuration still supports this configuration, but allows for much more.
<bean id="tomcat.server" class="org.red5.server.tomcat.TomcatLoader" init-method="init" destroy-method="shutdown" depends-on="context.loader">
<property name="webappFolder" value="${red5.root}/webapps" />
<property name="connectors">
<list>
<bean id="defaultHttp" class="org.apache.catalina.connector.Connector">
<constructor -arg type="java.lang.String" value="org.apache.coyote.http11.Http11NioProtocol" />
<property name="port"><value>${http.host}</value></property>
<property name="redirectPort"><value>8080</value></property>
<property name="enableLookups"><value>false</value></property>
</bean>
<bean id="defaultProxy" class="org.apache.catalina.connector.Connector">
<constructor -arg type="java.lang.String" value="org.apache.coyote.http11.Http11NioProtocol" />
<property name="port"><value>8080</value></property>
<property name="redirectPort"><value>${https.port}</value></property>
<property name="enableLookups"><value>false</value></property>
</bean>
</list>
</property>
<property name="baseHost">
<bean class="org.apache.catalina.core.StandardHost">
<property name="name" value="${http.host}" />
<property name="unpackWARs" value="true" />
<property name="autoDeploy" value="true" />
<property name="xmlValidation" value="false" />
<property name="xmlNamespaceAware" value="false" />
</bean>
</property>
<property name="hosts">
<list>
<bean id="local2" class="org.apache.catalina.core.StandardHost">
<property name="name" value="192.168.0.2" />
<property name="autoDeploy" value="false" />
<property name="xmlValidation" value="false" />
<property name="xmlNamespaceAware" value="false" />
</bean>
<bean id="local3" class="org.apache.catalina.core.StandardHost">
<property name="name" value="10.0.0.2" />
<property name="autoDeploy" value="false" />
<property name="xmlValidation" value="false" />
<property name="xmlNamespaceAware" value="false" />
</bean>
</list>
</property>
</bean>
This allows for two connector (ports on each host) and three hosts. If http.host were set to “192.168.0.1″ and http.port was set to “5080″, then you would be able to connect to “http://192.168.0.1:5080/” in your browser. In addition you would also have these urls available:
Each application (context) within your red5/webapps directory is made available on each host as well.
Lastly, the “host” name does not have to be an IP address; you can specify a valid dns host name instead.
Tags: http, port, Red5, socket, tomcat