Wowza Community

IMediaStreamNameAliasProvider and resolvePlayAlias calls

Hi,

I’m wondering if it’s normal that the resolvePlayAlias method of my custom module implementing IMediaStreamNameAliasProvider is called every second?

Thanks.

It will run every time a stream is played by a client.

Richard

you mean every time the stream is started, or all the play duration?

because, on my test server (I’m the only one connected), when playing a video, I can see a new entry in the logs every seconds. (getLogger().info(“blah”) in the resolvePlayAlias method)

In my custom module, I simply check the real file path in the resolvePlayAlias (from a remote webservice).

Thanks

I’m doing basic lookup to webservice to find the real path.

here is my module code:

public class MyNameAlias extends ModuleBase implements IMediaStreamNameAliasProvider {
	
	private final String STREAMALIASDEBUG_PROPERTY = "myAliasMapDebug";
	private final String STREAMALIASWSURL_PROPERTY = "myAliasMapWSUrl";
	private final String STREAMALIASCONNECTIONTIMEOUT_PROPERTY = "myAliasMapConnectionTimeout";
	
	private String wsUrl = "http://api.xxx.com/wowza/?action=getMediaPath&media_id=";
	private int connectionTimeout = 1000;
	private boolean debug = false;
	
	public void onAppStart(IApplicationInstance appInstance) {		
		WMSProperties props = appInstance.getProperties();
		
		debug = props.getPropertyBoolean(STREAMALIASDEBUG_PROPERTY, debug);
		wsUrl = props.getPropertyStr(STREAMALIASWSURL_PROPERTY, wsUrl);
		connectionTimeout = props.getPropertyInt(STREAMALIASCONNECTIONTIMEOUT_PROPERTY, connectionTimeout);
		
		if(debug)
		{
			String fullname = appInstance.getApplication().getName() + "/" + appInstance.getName();
			getLogger().info("MyNameAlias.onAppStart: " + fullname);
		}
		
		// TODO: add timer to remove expired entries from cache
		
		appInstance.setStreamNameAliasProvider(this);
	}

	public void onAppStop(IApplicationInstance appInstance) {
		if(debug)
		{
			String fullname = appInstance.getApplication().getName() + "/" + appInstance.getName();
			getLogger().info("MyNameAlias.onAppStop: " + fullname);	
		}
	}

	private String nameToAlias(String aliasType, String streamName)
	{
		String ret = null;

		String urlstr = wsUrl + URLUtils.encodeValue(streamName);
		
		try {
			// Gets the real path from webservice
			URL url = new URL(urlstr);
			URLConnection connection = url.openConnection();
			connection.setConnectTimeout(connectionTimeout);
			connection.setDoInput(true);
			
			InputStream inStream = connection.getInputStream();
			BufferedReader input = new BufferedReader(new InputStreamReader(inStream));
			
			String line = input.readLine().trim();
			
			input.close();
			inStream.close();
			
			getLogger().debug(line);
			
			ret =  SystemUtils.expandEnvironmentVariables(line);
			
			if(ret.startsWith("ERROR")) {
				if(debug)
					getLogger().info("MyNameAlias.nameToAlias: " + streamName + " not found");
				
				return null;
			}
			
			if (debug)
				getLogger().info("MyNameAlias.nameToAlias["+aliasType+"]: streamName:"+streamName+" alias:"+line+" result:"+ret);
			
			return ret;
		}
		catch (Exception e)
		{
			ret = null;
		}

		return ret;
	}
	
	@Override
	public String resolvePlayAlias(IApplicationInstance appInstance, String name)
	{
		return nameToAlias("play", name);
	}
	@Override
	public String resolveStreamAlias(IApplicationInstance appInstance, String name)
	{
		return nameToAlias("stream", name);
	}
}

you are right, it’s a player problem, just trying with wowza example and work just fine!

I’m using flowplayer, I will investigate that way.

Thanks again.

resolveStreamAlias methods run when you start a stream in stream manager. resolvePlayAlias methods run when you play a stream in a client.

What exactly are you doing in the custom module?

Which resolvePlayAlias runs, the base method or one of the overloads?

Richard

As a debug step, I would comment out the call to nameToAlias, then play from Flash client with an actual stream name and an alias that will not work. See if the resolvePlayAlias is still called repeatedly

public String resolvePlayAlias(IApplicationInstance appInstance, String name)
	{
		//return nameToAlias("play", name);
		return name;
	}

If still same, is the player doing NetStream.play repeatedly for some reason? Test using the Wowza SimpleVideoStreaming example player.

Richard

Great, thanks for the update. Let us know if you find what is happening Flowplayer to do that, for future reference.

Richard

Bora,

You should pass-thru the name parameter in resolveStreamAlias, i.e., not do any transform. Only do the transform in resolvePlayAlias.

If you have a .stream file named example.stream containing a MediaCaster URL (typically rtsp or udp), then start “example.stream” in StreamManager. Your resolveStreamAlias should not transform, the file exists so the stream starts.

In your clients, play stream name “someAlias”. Your resolvePlayAlias should resolve that to “example.stream”. So the client will actually play example.stream, but the user will only see “someAlias”

You could do this with the StreamNameAlias package.

Richard

In my test, resolvePlayAlias is called before resolveStreamAlias when the stream is started in StreamManager. I suppose this is right, it is essentially playing the stream.

So if the name has a .stream extension, do not transform it in resolvePlayAlias. Only process alias names you know are from clients.

Richard

Oh, hold on, you can’t use .stream files with StreamNameAlias. That’s the problem.

Richard

The .stream files are aliases. So you can’t use them with the Stream Alias package or API, it’s not setup for aliasing an alias

Using a simple alias name the resolvePlayAlias still runs first, so you are still responsible for not transforming an alias you use in StreamManager in the play handler.

As I said before, unless you are doing something much more complicated, you could probably use the StreamNameAlias package instead of the API. The API gives you very fine control and allows you to interface with other resources like a db to resolve aliases, that kind of thing, but you are totally responsible for resolving or not resolving aliases when these events fire, as necessary for your requirements.

Richard

resolveStreamAlias methods run when you start a stream in stream manager. resolvePlayAlias methods run when you play a stream in a client.

Hi Richard,

About your above statement. I am using the IMediaStreamNameAliasProvider interface and when I start a stream via streammanager web interface (the one at port 8086) both of these methods are called even though there’s no client connected yet.

Let me explain what I am doing and perhaps you can direct me in the right way.

The requirement is simple. Hiding the clip url’s (either live or vod) from the clients (which is currently FlowPlayer and iOS will be added).

The clients receive the URL’s via another web application which provides encoded stream names. Then on the wowza side, my module which implements the resolvePlayAlias method decodes these URL’s to get the real stream name for a connected client.

The encoded URL would be like: rtmp://wowza-ip/rtplive/encoded-stream-name

Here actually the encoded-stream-name is the name of a .stream file, and I will come to that. And I want them encoded because I don’t want users to play with the file name and possibly access some other user’s stream.

The stream is for example from an Axis camera and its URL is: rtsp://camera-ip/axis-media/media.amp

So I create a camera.stream file containing the above Axis URL.

Then I log on to streammanager and start the stream using camera.stream as the name and rtp as the type.

After this point, I was expecting Wowza not to call resolvePlayAlias but call only resolveStreamAlias. In resolveStreamAlias I don’t do any decoding because I provide simply camera.stream via the streammanager. In resolveStreamAlias I just read the file camera.stream and return the RTSP URL. I tried simply returning the camera.stream as a string as well which didn’t work either.

But what happens is Wowza first calls resolvePlayAlias which creates a garbage stream name and afterwards calls resolveStreamAlias with this garbage stream name. Therefore it doesn’t work. I would have tried decoding in the resolveStreamAlias method as well but it still wouldn’t work because both methods are called which means decoding twice would still fail the process.

I also tried using the other interface IMediaStreamNameAliasProvider2 but same problems observed.

I would also be interested in knowing whether or not these calls are made during the publishing of the stream (such as when I start it via streammanager) or during the playing phase of the stream when a client is connected.

In summary, I am a bit confused about the life cycles of the methods defined in IMediaStreamNameAliasProvider and IMediaStreamNameAliasProvider2 interfaces. Not sure when and how they are called.

My scenario is always publish the stream via streammanager or programmatically using the startMediaCasterStream method. Then have some clients connected to these published streams. Is this not a usual use case of Wowza?

PS: Starting the stream via startMediaCasterStream works correctly and resolvePlayAlias is not called as you mentioned. But via streammanager it doesn’t work and I’m stuck here.

Regards,

Bora.

Hi Richard,

Thanks for the quick response.

However, I modified according to your suggestions and still the same issue. After publishing “example.stream” in StreamManager, firstly the resolvePlayAlias is called which does some decoding on “example.stream”, so it returns some invalid string. Then resolveStreamAlias is called with this invalid string and basically it doesn’t work.

I am not sure how this whole process would work if resolvePlayAlias method is called when a stream is published via StreamManager because resolvePlayAlias method expects an encoded stream name (simply Base64 encoding for the moment).

Here are my methods. Here resolveName does decoding with Base64.

	@Override
	public String resolvePlayAlias(IApplicationInstance appInstance, String name) {
		getLogger().info(
				"MyTestStreamSecurity: resolvePlayAlias " + appInstance.getName()
						+ " " + name);
		String alias = resolveName(name);
		getLogger().info("MyTestStreamSecurity: resolvePlayAlias " + alias);
		return alias;
	}
	@Override
	public String resolveStreamAlias(IApplicationInstance appInstance,
			String name) {
		getLogger().info(
				"MyTestStreamSecurity: resolveStreamAlias "
						+ appInstance.getName() + " " + name);
		getLogger().info("MyTestStreamSecurity: resolveStreamAlias");
		return name;
	}

Below is an example log created by Wowza with the latest modifications based on your suggestions.

2011-09-14	08:04:04	EEST	comment	server	INFO	200	-	MyTestStreamManager: onServerInit	-	-	-	2.707	-	-	-	-	-	-	-	-	-	
2011-09-14	08:04:04	EEST	comment	server	INFO	200	-	MyTestStreamManager: onAppStart 2254042 true	-	-	-	2.813	-	-	-	-	-	-	-	-	
2011-09-14	08:04:04	EEST	comment	server	INFO	200	-	MyTestStreamManager: onAppStart exit	-	-	-	2.815	-	-	-	-	-	-	-	-	-	
2011-09-14	08:04:04	EEST	app-start	application	INFO	200	_definst_	MyTest-stream-manager/_definst_	-	-	-	2.847	-	-	-	-	-	-	-	
2011-09-14	08:04:04	EEST	comment	server	INFO	200	-	MyTestStreamManager: onServerInit exit	-	-	-	2.847	-	-	-	-	-	-	-	-	-	
2011-09-14	08:04:15	EEST	comment	server	INFO	200	-	MyTestStreamSecurity: onAppStart	-	-	-	14.527	-	-	-	-	-	-	-	-	-	
2011-09-14	08:04:15	EEST	comment	server	INFO	200	-	MyTestStreamSecurity: onAppStart exit	-	-	-	14.528	-	-	-	-	-	-	-	-	-	
2011-09-14	08:04:15	EEST	app-start	application	INFO	200	_definst_	rtplive/_definst_	-	-	-	14.535	-	-	-	-	-	-	-	-	
2011-09-14	08:04:15	EEST	comment	server	INFO	200	-	MyTestStreamSecurity: resolvePlayAlias _definst_ 1-testH.stream	-	-	-	14.535	-	-	-	-	-	-	
2011-09-14	08:04:15	EEST	comment	server	INFO	200	-	MyTestStreamSecurity: resolveName Ö׬´{-*æ¦	-	-	-	14.54	-	-	-	-	-	-	-	-	
2011-09-14	08:04:15	EEST	comment	server	INFO	200	-	MyTestStreamSecurity: resolvePlayAlias Ö׬´{-*æ¦	-	-	-	14.54	-	-	-	-	-	-	-	
2011-09-14	08:04:15	EEST	comment	server	INFO	200	-	RTPMediaCaster.create[9249408]	-	-	-	14.547	-	-	-	-	-	-	-	-	-	-	
2011-09-14	08:04:15	EEST	comment	server	INFO	200	-	RTPMediaCaster.init[9249408]	-	-	-	14.547	-	-	-	-	-	-	-	-	-	-	
2011-09-14	08:04:16	EEST	comment	server	INFO	200	-	RTPMediaCaster.Reconnector[9249408:rtplive/_definst_:Ö׬´{-*æ¦]: start: 1	-	-	-	14.552	-	-	-	-	
2011-09-14	08:04:16	EEST	comment	server	INFO	200	-	HTTPStreamManager.onHTTPRequest: Publish stream successfully started [rtplive/_definst_]: flv:Ö׬´{-*æ¦	-	-	-	14.562	-	
2011-09-14	08:04:16	EEST	comment	server	INFO	200	-	MyTestStreamSecurity: resolveStreamAlias _definst_ Ö׬´{-*æ¦	-	-	-	14.654	-	-	-	-	-	-	
2011-09-14	08:04:16	EEST	comment	server	INFO	200	-	MyTestStreamSecurity: resolveStreamAlias	-	-	-	14.654	-	-	-	-	-	-	-	-	
2011-09-14	08:04:16	EEST	comment	server	INFO	200	-	RTPSessionDescriptionDataProviderBasic.getStreamInfo[rtplive/_definst_]: D:/programs/wowza/content/Ö׬´{-*æ¦	-	-	-	14.655	
2011-09-14	08:04:16	EEST	comment	server	WARN	200	-	RTPSessionDescriptionDataProviderBasic.getStreamInfo: SDP file missing: D:/programs/wowza/content/Ö׬´{-*æ¦	-	-	-	14.656	

Please let me know if you need more info to get to the bottom of this problem.

Thanks and Regards,

Bora.

Hi Richard,

In response to your first suggestion to not transform when it has .stream extension:

But I don’t want someone to use a URL that contains the .stream file name and be able to bypass my aliasing functionality.

In response to not being able to use .stream files when using IMediaStreamNameAliasProvider interface:

Why exactly is this? And how can I overcome that? In order to publish an RTSP stream I need to create a .stream file right?

I had actually read about it in the forums before posting this question. And this was the reason I initially thought I should read the .stream file content and return the rtsp url instead of returning the .stream file name in the alias methods. It didn’t work either.

Regards,

Bora.