Since I’ve seen nothing which addresses the processing delays that I noticed in ffmpeg when generating thumbnail images, I figured I should share some important optimizations. I used to specify this command line when generating the images from a movie source (f4v in this case):
ffmpeg -y -i mymovie.f4v -an -ss 00:05:00 -t 00:00:00.01 -sameq -r 1 -vframes 1 -deinterlace -f mjpeg mythumbnail.jpg
This will take about one minute to generate the image of the video frame which is five seconds into the clip. This seems really extreme and is even worse when you try to increase the start location; for instance 45 seconds in, takes about an hour.
So, I knew there had to be a better way and I monkeyed around with the options:
ffmpeg -y -ss 00:05:00 -i mymovie.f4v -an -t 00:00:00.01 -sameq -r 1 -vframes 1 -deinterlace -f mjpeg mythumbnail.jpg
There is only one change between these lines, the placement of the “ss” option. This change causes the command to complete in less than a second, no matter what our start time is. Quite an increase in processing for something so simple! I hope this helps a few of you out there.
Tags: f4v, ffmpeg, jpg, thumbnail
The game my company has been working on for months is finally approved in the AppStore! Get your copy now! Click here
If you are using a desktop like I am and you dont “hibernate” your system, then you may want to turn this feature off. I have 12 Gb of RAM so this saves ~9 Gb on my C: drive. Heres how you save the space:
1. Click on Windows 7 Start Button 2. Go to All Programs-> Accessories 3. Now right on Command Prompt and select “Run as Administrator” from context menu. 4. Type "powercfg -h off" without the quotes
Thats all and hopefully it helps someone else out there…
Tags: hiberfil.sys, windows
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.
We are now worm-safe, for now. Thanks Influxis!
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>
Tags: bean, Java, parameter, PHP, Red5, servlet