Wowza Community

Problem using GoCoder with custom server module

Good Day,

I am using GoCoder on iPhone and iPad with WowzaStreamingEngine 4.0.3 and have been successfully streaming to a live dvr application instance with recording enabled for later VoD viewing. I now want to rename the the recorded file when GoCoder disconnects so I have written a server side module that implements the IMediaWriterActionNotifier interface as shown below. I have added the following module definition to the Application.xml Modules section:

<Module>
	<Name>ModuleWriteListener</Name>
	<Description>YGCRecordRename</Description>
	<Class>com.ygc.wms.plugin.module.ModuleWriteListener</Class>
</Module>

In my development server running WowzaStreamingEngine 4.0.3 on Linux, everything is working well and the recorded file gets renamed successfully.

However, in the production environment running on Mac OS X 10.8.5 with the module installed and added to the Application.xml, GoCoder no longer connects to Wowza. Unfortunately, neither GoCoder or Wowza are displaying any messages whatsoever so I have no idea what is wrong. Using netstat I can see that GoCoder is connecting to port 1935.

If I comment out the Module definition in Application.xml, GoCoder connects and publishes just fine, so I know that GoCoder is configured correctly.

If I modify the Module definition in Application.xml such that the class name is incorrect, I do get an error in the wowza error and access log saying that it could not load the module, as expected!

Its seems Wowza on Mac has a problem loading the jar file for my module, but doesn’t log any error.

Any ideas on how to debug this?

Heres the module source:

package com.ygc.wms.plugin.module;
import java.io.*;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
 
import java.util.*;
import com.wowza.wms.application.*;
import com.wowza.wms.module.*;
import com.wowza.wms.stream.*;
public class ModuleWriteListener extends ModuleBase {
	class WriteListener implements IMediaWriterActionNotify
	{
		public void onFLVAddMetadata(IMediaStream stream, Map<String, Object> extraMetadata)
		{
			getLogger().info("ModuleWriteListener.WriteListener.onFLVAddMetadata["+stream.getContextStr()+"]");
		}
		public void onWriteComplete(IMediaStream stream, File file)
		{
			String name;
			DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
			Date date = new Date();
			String filePath = file.getParent();
			String fileName = file.getName();
			String fileExt = "";
			
			int fileExtIndex = fileName.lastIndexOf(".mp4");
			if (fileExtIndex >= 0)
			{
				fileExt = fileName.substring(fileExtIndex);
				fileName = fileName.substring(0, fileExtIndex);
			}
			
			int fileStreamIndex = fileName.lastIndexOf(".stream");
			if (fileStreamIndex >=0)
			{
				fileName = fileName.substring(0, fileStreamIndex);
			}
			
			File newFile;
			for (int segmentNumber = 0; ;segmentNumber++)
			{
				name = filePath+"/"+fileName+"-"+dateFormat.format(date)+"-"+segmentNumber+fileExt;
				newFile = new File(name);
				if (!newFile.exists())
				{
					break;
				}
				getLogger().info("ModuleWriteListener.WriteListener.onWriteComplete: new file "+newFile+" already exists");
			}
			getLogger().info("ModuleWriteListener.WriteListener.onWriteComplete: new file is "+newFile);
			if (!file.renameTo(newFile))
			{
				getLogger().info("ModuleWriteListener.WriteListener.onWriteComplete: failed to rename "+file+" to "+newFile);
			}
		}
	}
	public void onAppStart(IApplicationInstance appInstance) {
		String fullname = appInstance.getApplication().getName() + "/"
				+ appInstance.getName();
		getLogger().info("ModuleWriteListener.onAppStart: " + fullname);
		appInstance.addMediaWriterListener(new WriteListener());
	}
}

Ok, I’ve narrowed it down to something to do with the file.renameTo method call I make in onWriteComplete method.

If I comment out that one call the module loads and everything works except the rename doesn’t happen (of course!).

What I’m trying to do is rename the recording from fileName.mp4 to fileName-YYYY-MM-DD-C.mp4

where C is what I’m calling the clip number. This is so that when a mobile user publishes several segments, after each one completes I rename the file. So I end up with files like:

file-2014-05-06-0.mp4

file-2014-05-06-1.mp4

file-2014-05-06-2.mp4

My research leads to the fact that renameTo may fail if the file being renamed is open or the new path for the name is on a different filesystem.

In my case I’m renaming it in the same directory as the original file.

What I dont understand is that with the renameTo method left in the code, The module doesn’t appear to even load since the onAppStart log message I print doesn’t happen and the GoCoder app doesn’t start publishing.

Can anyone explain what is happening and how I can achieve what I’m trying to do?

Thanks,

Jo

Hi Jo,

If all works in development but not production, which seems to be the critical problem you are having, the first thing I would check is versions of Java. They should be the same on both, or higher on the production server.

Richard

Great! Glad that worked. Thanks for the update, Jo

Richard

Hi Richard,

that was it!

Java versions on my ubuntu dev box are:

java version “1.8.0_05”

Java™ SE Runtime Environment (build 1.8.0_05-b13)

Java HotSpot™ 64-Bit Server VM (build 25.5-b02, mixed mode)

On the production Mac minis, it is:

java version “1.6.0_65”

Java™ SE Runtime Environment (build 1.6.0_65-b14-462-11M4609)

Java HotSpot™ 64-Bit Server VM (build 20.65-b04-462, mixed mode)

I upgraded one of production macs to latest JDK from Oracle:

java version “1.8.0_05”

Java™ SE Runtime Environment (build 1.8.0_05-b13)

Java HotSpot™ 64-Bit Server VM (build 25.5-b02, mixed mode)

Now everything works like a charm!

Thanks for pointing me in the right direction!

Cheers,

Jo