MediaCasterStreamManager controls start/stop/record of RTP, MPEG-TS and SHOUTcast

Yes, definitely.

Richard

You can use the built-in StreamManger in Wowza 2:

http://community.wowza.com/t/-/82

Richard

I have installed the mediacasterstreammanager module.

But when I try to connect via the mediacasterstreammanager client with:

Server: rtmp://server-ip/live → connect

Stream: xxxx.sdp

Nothing shows up in the Active window and I get this error on the server:

INFO session connect-pending xx.xxx.xx.198 -

INFO session connect xx.xxx.xx.198 -

ERROR server comment - invoke(getMediaCasterStreamList): java.lang.NoSuchMethodError: com.wowza.wms.util.ModuleUtils.checkModulePassword(Lcom/wowza/wms/amf/AMFDataList;ILjava/lang/String;)Z: com.wowza.wms.plugin.mediacasterstreammanager.ModuleMediaCasterStreamManager.getMediaCasterStreamList(null:-1)

java.lang.NoSuchMethodError: com.wowza.wms.util.ModuleUtils.checkModulePassword(Lcom/wowza/wms/amf/AMFDataList;ILjava/lang/String;)Z

at com.wowza.wms.plugin.mediacasterstreammanager.ModuleMediaCasterStreamManager.getMediaCasterStreamList(Unknown Source)

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

at java.lang.reflect.Method.invoke(Method.java:597)

at com.wowza.wms.module.ModuleFunction.invoke(ModuleFunction.java:86)

at com.wowza.wms.module.ModuleFunctions.invoke(ModuleFunctions.java:151)

at com.wowza.wms.request.RequestProcessFunctions.processFunctions(RequestProcessFunctions.java:107)

at com.wowza.wms.client.ClientWorker.processNextReq(ClientWorker.java:102)

at com.wowza.wms.request.RTMPRequestAdapter.service(RTMPRequestAdapter.java:350)

at com.wowza.wms.server.ServerHandler.serviceRequest(ServerHandler.java:479)

at com.wowza.wms.server.ServerHandler.handleMessageReceived(ServerHandler.java:270)

at com.wowza.wms.server.ServerHandler.messageReceived(ServerHandler.java:347)

at com.wowza.wms.server.ServerHandlerThreadedSession.run(ServerHandlerThreadedSession.java:108)

at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)

at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)

at java.lang.Thread.run(Thread.java:619)

ERROR server comment - invoke(startMediaCasterStream): java.lang.NoSuchMethodError: com.wowza.wms.util.ModuleUtils.checkModulePassword(Lcom/wowza/wms/amf/AMFDataList;ILjava/lang/String;)Z: com.wowza.wms.plugin.mediacasterstreammanager.ModuleMediaCasterStreamManager.startMediaCasterStream(null:-1)

java.lang.NoSuchMethodError: com.wowza.wms.util.ModuleUtils.checkModulePassword(Lcom/wowza/wms/amf/AMFDataList;ILjava/lang/String;)Z

at com.wowza.wms.plugin.mediacasterstreammanager.ModuleMediaCasterStreamManager.startMediaCasterStream(Unknown Source)

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

at java.lang.reflect.Method.invoke(Method.java:597)

at com.wowza.wms.module.ModuleFunction.invoke(ModuleFunction.java:86)

at com.wowza.wms.module.ModuleFunctions.invoke(ModuleFunctions.java:151)

at com.wowza.wms.request.RequestProcessFunctions.processFunctions(RequestProcessFunctions.java:107)

at com.wowza.wms.client.ClientWorker.processNextReq(ClientWorker.java:102)

at com.wowza.wms.request.RTMPRequestAdapter.service(RTMPRequestAdapter.java:350)

at com.wowza.wms.server.ServerHandler.serviceRequest(ServerHandler.java:479)

at com.wowza.wms.server.ServerHandler.handleMessageReceived(ServerHandler.java:270)

at com.wowza.wms.server.ServerHandler.messageReceived(ServerHandler.java:347)

at com.wowza.wms.server.ServerHandlerThreadedSession.run(ServerHandlerThreadedSession.java:108)

at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)

at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)

at java.lang.Thread.run(Thread.java:619)

What is done wrong?

Thanks

… I thought that patch was already in place, but not…

Thanks.

When I set the Streamtype on rtp-live-record, for instance in the nativeRTP application, and I make a recording by connecting to the NativeRTP application, I am able to playback that recording, for instance in the nativeRTP of Fastplay application.

When I do a recording via the mediacasterstreammanager I am not able to playback the file in any of the WMS applications. Although when I download the file I can playback the file with VLC at good quality.

What is going different between these two ways of recording? And what can be done to get good recordings via the Mediacasterstreammanager which can be played back in standard WMS applications.

Thanks.

Has somebody a answer on this one?

Regards

You will need to rename the file after it has completed being written.

Ok, that’s what I’ve done and it works great !

Since I use this module, I noticed record starts after a long time. Looking at logs, I see this :

INFO server comment 2009-02-16 12:05:30 33.155 UDPTransport.firstPacket: /XXX.XXX.XXX.XXX:XXXX

INFO server comment 2009-02-16 12:05:30 33.167 UDPTransport.firstPacket: /XXX.XXX.XXX.XXX:XXXX

WARN server comment 2009-02-16 12:05:38 41.165 Waiting for RTCP packet. See docs for (Application.xml: RTP/AVSyncMethod and RTP/MaxRTCPWaitTime).

WARN server comment 2009-02-16 12:05:39 41.274 Waiting for RTCP packet. See docs for (Application.xml: RTP/AVSyncMethod and RTP/MaxRTCPWaitTime).

WARN server comment 2009-02-16 12:05:42 45.173 RTCPHandler.isTimeSyncReady: Hit MaxRTCPWaitTime synchronizing on system clock.

Looking at Application.xml, StreamType is “live”, AVSyncMethod is “senderreport” and MaxRTCPWaitTime is “12000”.

So I guess nothing happens before a 12 seconds delay.

Do I need to change anything to make record start faster ?

Thank you.

Try changing AVSyncMethod to one of the other two valid values. It sounds like the encoder you are using does not generate RTCP packets.

As you know, I’m using VLC :wink:

Also, be sure you modify your command line to increase the key frame rate.

Could you explain me, even quickly, why do I need to do this ?

I certainly need to recreate my SDP file then …

This will increase the frequency at which the encoder generates key frames. It will improve stream startup time since the stream needs a key frame to start.

Ok. This is only for that purpose ? It won’t change anything else ? Cuepoints, etc … ?

For now, I’ve switched to “rtptimecode” and it’s much better now so I don’t want to change anything to encoder part if it’s only to start recording 80 milliseconds earlier …

@Charlie : I just realized “duration” property in recorded FLV metadata is sometimes equal to 0.

I don’t know exactly when it happens but the file is 44 minutes long. flvtool2 says :


/usr/local/WowzaMediaServerPro-1.6.0/content/XXXXXXXXXXXXXX.flv:

rtpsessioninfo:

protocolversion: 0

name: XXXXX

timing: 0 0

attributes:

tool: vlc 0.8.6h

origin: - 10737062000 2 IN IP4 127.0.0.1

connectiondata: IN IP4 XX.XXX.XXX.XXX

videocodecid: avc1

audiosamplerate: 44100

creationdate: mer. mars 25 10:00:37

trackinfo:

sampledescription:

sampletype: mpeg4-generic

language: eng

timescale: 44100

sampledescription:

sampletype: H264

language: eng

timescale: 90000

height: 0

duration: 0

audiocodecid: mp4a

width: 0

audiochannels: 0

Could you take a look to this please ?

FlowPlayer can find the correct duration, I don’t know how because in my Flex application, duration caught by onMetaData is 0.

The code I’m using is similar to :

this.nsClient=new Object();

this.nsClient.onCuePoint=this.ns_onCuePoint;

this.nsClient.onMetaData=this.ns_onMetaData;

this.ns.client=this.nsClient;

Thank you.

Ok Charlie, I’ll pay attention to this carefully next time …

Java code is :

boolean success = mediaCasterStreamManager.stopStream(streamNameOn);
if (success == true)
{
  // rename SDP
  // move FLV
}

So it seems stopStream() has not ended when I move FLV …

You will need to use the IMediaStreamActionNotify2 interface and add a listener to get notification of the onUnPublish event.

Great ! Now I must find out how to code this and where I could use this code :wink:

Charlie, could you post sample code on how to implement IMediaStreamActionNotify2/onUnPublish ?

I just don’t know where to start and where add this in my current module ?

Thanks a lot !

Thank you Richard.

Using Java code published by Charlie at start of this topic (ModuleMediaCasterStreamManager.java), I’d like to be sure recording is stopped before moving archive (stopMediaCasterStream()) but I don’t know where to put the code you provide …

1/ It will certainly be the same : I won’t be sure stop action will be achieved when responder is called on client side,

2/ I’m sure I can do this without getting back to client …

It’s very easy - you can call the startMediaCasterStream inside java, we use it to start the mediacasters from our encoding server over a socket connection.

I can provide a example if you like, but it’s very very easy :wink:

You need to modify it a bit:

public void startMediaCasterStream(String group, String streamName, String mediaCasterType, String name, String size, int bitrate)
	{
		try
		{
			while(true)
			{
				getLogger().info("ModuleMediaCasterStreamManager.startMediaCasterStream["+mediaCasterType+"]: "+streamName);
				
				MediaCasterStreamMap mediaCasterMap = this.appInstance.getMediaCasterStreams();
				IVHost vhost = this.appInstance.getVHost();
				MediaCasterStreamManager mediaCasterStreamManager = mediaCasterMap.getStreamManager();
				
				MediaCasterList mediaCasterList = vhost.getMediaCasterList();
				MediaCasterItem mediaCasterDef = mediaCasterList.getMediaCasterDef(mediaCasterType);
				
				if (mediaCasterDef == null)
				{
					getLogger().warn("ModuleMediaCasterStreamManager.startMediaCasterStream: MediaCaster type not found: "+mediaCasterType);
					break;
				}
				
				MediaCasterStreamItem mediaCasterStream = mediaCasterMap.getMediaCaster(streamName);
				if (mediaCasterStream != null)
				{	getLogger().warn("ModuleMediaCasterStreamManager.startMediaCasterStream: MediaCaster already exists[mediacaster]: "+streamName);
					break;
				}
				
				boolean success = mediaCasterStreamManager.startStream(streamName, mediaCasterType);
				if (success)
				{		getLogger().info("ModuleMediaCasterStreamManager.startMediaCasterStream: Stream started: "+streamName);
				}
				else
				{
					getLogger().info("ModuleMediaCasterStreamManager.startMediaCasterStream: Stream failed: "+streamName);
				}
				break;
			}
		}
		catch (Exception e)
		{
			getLogger().error("ModuleMediaCasterStreamManager.startMediaCasterStream: "+e.toString());
		}
	}
	
	// NEEDED INFO: streamName (glf.sdp)
	public void stopMediaCasterStream(String streamName)
	{
		try
		{
			while(true)
			{
				getLogger().info("ModuleMediaCasterStreamManager.stopMediaCasterStream: "+streamName);
						
				MediaCasterStreamMap mediaCasterMap = this.appInstance.getMediaCasterStreams();
				MediaCasterStreamManager mediaCasterStreamManager = mediaCasterMap.getStreamManager();
				boolean success = mediaCasterStreamManager.stopStream(streamName);
				if (success)
				{
					getLogger().info("ModuleStreamStarter.stopMediaCasterStream: Stream stopped: "+streamName);
				}
				else
				{
					getLogger().warn("ModuleMediaCasterStreamManager.stopMediaCasterStream: Stream not found: "+streamName);
				}
				break;
			}
		}
		catch (Exception e)
		{
			getLogger().error("ModuleMediaCasterStreamManager.stopMediaCasterStream: "+e.toString());
		}
	}

and it’s called like this:

Main.getLiveApp().startMediaCasterStream(group, streams[i][0] + ".sdp", "rtp", streams[i][0], streams[i][1], Integer.parseInt(streams[i][2]));
Main.getLiveApp().stopMediaCasterStream(streams[i] + ".sdp");

Sorry, i’m in the middle of my exams, so i hadn’t the time to modify the code to your needs.