Config aliasmap.stream.txt for edge transcode

Firstly, I always set the following config to approach the re-streaming.

in edge server - aliasmap.stream.txt

origin1/*=wowz://[origin1 ip]/${Application.Name}/${AppInstance.Name}/${Stream.Name.Part2}

in edge server - Application.xml, I set transcoder on edge server rather than origin server

		<Streams>
			<StreamType>liverepeater-edge</StreamType>
                         .....
		</Streams>
		<Transcoder>
			<LiveStreamTranscoder>transcoder</LiveStreamTranscoder>
			<Templates>${SourceStreamName}.xml,transrate.xml</Templates>
			<ProfileDir>${com.wowza.wms.context.VHostConfigHome}/transcoder/profiles</ProfileDir>
			<TemplateDir>${com.wowza.wms.context.VHostConfigHome}/transcoder/templates</TemplateDir>
			<Properties>
			</Properties>
		</Transcoder>
                .....
                </Modules>
                        .....
			<Module>
				<Name>ModuleStreamNameAlias</Name>
				<Description>ModuleStreamNameAlias</Description>
				<Class>com.wowza.wms.plugin.streamnamealias.ModuleStreamNameAlias</Class>
			</Module> 
		</Modules>

It works fine to re-stream the unchanged-resolution stream from origin server by requesting rtmp://[edge-ip]/[app-name]/definst/origin1/mystream. But I’m trying to do the transcode on edge and access the transcoded steam of mystream. I already configure the transcoder/templates/transrate.xml of edge server to generate an 240p video, How could I get the mystream_240p?

p.s. if necessary, I can change to use IMediaStreamNameAliasProvider2 to do the remapping

andy_c

The aliased stream named is “origin1” according to your rule, so the transcoded stream name will be origin1_240p, or origin1_360p, as defined in the Encode blocks of the default templates. However, note that the _240p Encode’s /Enable attribute is set to “false”, so to use origin1_240p you have to set that to “true” and restart Wowza. Then use Wowza Flash RTMP player:

Server: rtmp://[edge-ip]:1935/[app-name]

Stream: origin1_240p

Richard

Hi Andy,

I think the reason you are getting the results you are seeing is because you have the stream type on the edge server set to liverepeater-edge.

With liverepeater-edge stream type, the player will always try to trigger a mediaCaster to start up if there is not one already running for the name that is requested. If the stream is already being published to the edge server (from the transcoder for example) this will be ignored by the player.

What you need to do is set the edge stream type to live and manually start the origin stream somehow. If transcoding, the source should be connected persistently anyway and you can start it either with the Stream Manager, StartupStreams.xml or the api methods.

If you do need to start it dynamically, the best approach is to use the IMediaStreamNameAliasProvider2 interface and trigger the mediaCaster startup for the source stream in the resolvePlayAlias methods. In the resolveStreamAlias methods, you then set the wowz address for the origin stream. You will also have to add extra code to detect when the players have all disconnected and shutdown the mediaCaster.

Note: This method is not reliable for http players as there is a long delay between when the stream is started and when the http renditions are ready for playback.

Roger.

Hi Andy,

It looks like from your output, you still have the application stream type set to liverepeater-edge or you are not detecting the stream name properly.

In your resolvePlayAlias methods, you need to detect the name the player is requesting and only start the connection to the origin if the origin stream is not already running.

Example: stream name requested is myStream_240p.

rtmp player will call resolvePlayAlias(IApplicationInstance appInstance, String name, IClient client).

  • Extract the origin stream name from name. this should be myStream.

  • Test if origin stream is already running.

    if (appInstance.getStreams().getStream(originName)) 
    
  • If not running, start the mediaCaster with the name as myStream and the type as liverepeater.

  • This will then make a call to resolvePlayAlias(IApplicationInstance appInstance, String name) with the name as myStream. Just return the same name here.

  • resolveStreamAlias(IApplicationInstance appInstance, String name, IMediaCaster mediaCaster) will then be called with with the name as myStream.

  • Back in your original method, return the name that was provided by the player.

    Each time a stream stops, it will call onStreamDestroy. This is the same for player streams, the stream from the origin and for the streams created by the transcoder. You will need to detect if the stream is a player stream and the name.

    if (!stream.isPlay())
        return;
    String name = stream.getName();
    //  See if any renditions are currently being played and if not then it is safe to shut down the origin stream.
    //  Extract the origin name from the current stream name and get a list of streams where the name starts with the origin name.
    //  for each rendition, use appInstance.getPlayStreamCount(String streamName), getHTTPStreamerSessionCount(String streamName) & getRTPSessionCount(String streamName)
    
    

    When shutting down the origin stream, you should probably use a timer to shut it down incase a player reconnects quickly. If the timer is running and the player reconnects, you can cancel the timer which will stop the shutdown. Store the timer in the origin stream properties so you can check if it exists in the resolvePlayAlias method.

    I hope this makes sense.

    Roger.

Hi Andy,

That is most likely a timing issue between when the mediaCaster starts from the origin and when the transcoded stream that the player has actually requested starts up.

The resolvePlayAlias method will return as soon as the startMediaCasterStream method returns but there are small delay before the transcoder stream is available.

The stream not found message is the player reacting to the fact that the requested stream is not ready.

Roger.

Hi Andy,

Different players handle the stream not found response form Wowza in different ways. The Wowza example player just prints a message and then when the stream does eventually start, it will play it back.

JW Player and most other commercial players will shut down the connection automatically.

The reason you get the message straight away is because the stream name you are requesting (transcoder stream) doesn’t exist by the time the play command has completed executing. When using liverepeater-edge stream type, the play command waits for the mediaCaster to fully start and then returns the stream.

What you could possibly do is start a loop once you have started the mediaCaster and wait for the transcoder to start. You can test appInstance.getStreams().getStream(transcoderStreamName). In your loop, you should have a short sleep period and a breakout if the stream never starts.

If using this then you should also start the mediaCaster in its own thread as I think the transcoder will be started on the same thread that starts the mediaCaster so if you put that thread to sleep waiting for the transcoder to start, it will never happen.

Use something like this, (not tested!!!)

	class MediaCasterStarter implements Runnable
	{
		final IApplicationInstance appInstance;
		final String name;
		final String type;
		
		MediaCasterStarter(IApplicationInstance appInstance, String name, String type)
		{
			this.appInstance = appInstance;
			this.name = name;
			this.type = type;
		}
		@Override
		public void run()
		{
			appInstance.startMediaCasterStream(name, type);
		}
	}
	
	public String resolvePlayAlias(IApplicationInstance appInstance, String name, IClient client)
	{
		if (appInstance.getStreams().getStream(name) != null)
			return name;
		// extract origin name somehow...
		String originName = name.split("_")[0];
		
		appInstance.getVHost().getHandlerThreadPool().execute(new MediaCasterStarter(appInstance, originName, "liverepeater"));
		
		long start = System.currentTimeMillis();
		
		while (appInstance.getStreams().getStream(name) == null)
		{
			if(System.currentTimeMillis() - start > 2000)
				break;
			
			try
			{
				Thread.currentThread().sleep(10);
			}
			catch (InterruptedException e)
			{
			}
		}
		
		return name;
	}

With this, it should wait a maximum of 2 seconds for the transcoder to start up. That should be plenty of time.

Roger.

Hi Andy,

As I said, the code example was not tested so I was erring on the side of caution.

Looking at the transcoder process in detail, it looks like it is initialised when the first packets arrive which will be in a separate thread so you should be fine.

What I was getting at is that there may be some other process that needs to complete once your play command completes so if putting the current thread to sleep for any reason, it is good practice to do the preceding bit in a separate thread.

Roger.

Hi,

Thank your reply.

If I use Wowza Flash RTMP player and fill the Stream to “origin1_240p” as your prompt, it would loss the source stream name mystream and fail to get the stream from origin (because downstream naming rule of above example is “[origin #]/[source stream name]”

I guess I should change the delimiter from ‘/’ to ‘-’ to avoid the result of origin1_240p (it misses the important source stream name - mystream), so I tried to modify to :

edge server - aliasmap.stream.txt

origin1-*=wowz://[origin1 ip]/${Application.Name}/${AppInstance.Name}/${Wildcard.Match1}

use Wowza Flash RTMP player:

Server: rtmp://[edge-ip]:1935/[app-name]
Stream: origin1-mystream_240p

But it would try to get the mystream_240p from origin-1 and get nothing.

What I need is someway to keep {[origin #], [source stream name], [transcode type]} on downstream name, the Media Caster catchs {[origin #], [source stream name]} and ignores [transcode type], and finally player gets the edge transcoded stream according to the [transcode type].

Any idea?

andy_c

Hi Roger:

Thanks, it’s good support. I follow you suggestion and mediaCaster startup to catch source stream successfully. But I still has problem to get the edge-transcoded stream. for example, use Wowza Flash RTMP player:

Server: rtmp://[edge-ip]:1935/[app-name]
Stream: origin1-mystream_240p

it means player wants to get the edge-transcoded 240p stream that generated from mystream on origin1, but I got the following logs:

INFO session connect 192.168.2.198 -
INFO server comment - onStreamCreate: 1
INFO stream create - -
INFO server comment - Resolve Play Flash: origin1-mystream_240p
INFO server comment - onStreamCreate: 1
INFO stream create - -
INFO server comment - Resolve Stream Mediacaster: origin1-mystream_240p
INFO server comment - LiveMediaStreamReceiver.connect: wowza://[origin ip]/[applic]/_definst_/mystream:wowza://[origin ip]/[app]/_definst_[mystream]
INFO server comment - ApplicationInstance.startMediaCasterStream[live-edge-transc/_definst_]: Stream started: flv:origin1-mystream_240p
AMFDataList:
[0] _result
[1] 1.0
[2] object
{Obj[]: fmsVer: "FMS/3,5,7,7009", capabilities: 31.0, mode: 1.0}
[3] object
{Obj[]: level: "status", code: "NetConnection.Connect.Success", description: "Connection succeeded.", data: {MixedArray: version: "3,5,7,7009"}, clientid: 1.978703004E9, objectEncoding: 0.0, liveRepeaterCapabilities: 1.0}
AMFDataList:
[0] _result
[1] 2.0
[2] null
[3] 1.0
INFO server comment - onStreamCreate: 1
INFO server comment - TranscoderSessionNative.loadLibrary: Load transcoder list: C:/Program Files (x86)/Wowza Media Systems/Wowza Media Server 3.6.2/lib-native/win64/transcoder.list
INFO server comment - LiveStreamTranscoder.init[live-edge-transc/_definst_/origin1-mystream_240p]: Load transcoder template: file:///C:/Program Files (x86)/Wowza Media Systems/Wowza Media Server 3.6.2/transcoder/templates/transrate.xml
INFO server comment - JNI:TranscoderSession.isCUDAAvailable[_defaultVHost_:live-edge-transc/_definst_/origin1-mystream_240p]: NVidia hardware acceleration is NOT available
INFO server comment - JNI:TranscoderSession.isQuickSyncAvailable[_defaultVHost_:live-edge-transc/_definst_/origin1-mystream_240p]: Intel Quick Sync hardware acceleration is NOT available.
INFO server comment - onStreamCreate: 2
INFO stream create - -
INFO stream publish origin1-mystream_240p_source -
INFO server comment - onStreamCreate: 3
INFO stream create - -
INFO stream publish [B]origin1-mystream_240p_240p[/B] -
INFO server comment - JNI:TranscoderSession.videoDecoderCreate[_defaultVHost_:live-edge-transc/_definst_/origin1-mystream_240p]: Create video decoder: H.264: default
INFO transcoder decoder-video-start origin1-mystream_240p {codec:H264, profile:Baseline, level:3.1, frameSize:640x360, displaySize:640x360, frameRate:15.0}
INFO server comment - JNI:VideoDecoderH264.updateDecodeInfo[_defaultVHost_:live-edge-transc/_definst_/origin1-mystream_240p]: aspect:16x9 frame:640x360 display:640x360 frameRate:15
INFO server comment - JNI:TranscoderSession.videoEncoderAdd[_defaultVHost_:live-edge-transc/_definst_/origin1-mystream_240p:240p]: Create video encoder: H.264: default
INFO transcoder encoder-video-start origin1-mystream_240p {name:"240p", bitrate:350000, codec:H264, profile:Baseline, level:2.1, frameSize:426x240, displaySize:426x240, frameRate:15.0}
[B]INFO stream play origin1-mystream_240p[/B] -
....

The transcoded stream name is origin1-mystream_240p_240p, so I still can’t get it to play.

Other question is, does secure origin still work on it?

Hi Roger:

With your detail flow, it successes to display the edge-transcoded stream on Wowza Flash RTMP player (it needs to wait a moment to display, that’s ok). However the problem is, it also shows the error message on the Wowza Flash RTMP player’s status field ( and it showed faster than the stream display)

Failed to play mystream1_160p; stream not found.

If I use a second Wowza Flash RTMP player to play the same stream, it would not show the error status. Do you know why it shows error status on 1st player?

andy_c

Hi Roger:

I observe some player’s behavior and think maybe it’s not just a minor warning message on player side. I try to use JW player to subscribe edge-transcoded stream and it could not display the stream. JW player shows “Error loading stream: ID not found on server”, similar as error message on Wowza Flash RTMP player.

I guess wms will response some info to player so there is error message on both JW player and Wowza Flash RTMP player, is it possible to implement some customer methods on wms to avoid the error message?

Thank your help.

andy_c

Hi Roger:

It solves my problem. Thank your great help, your post not only prompts the right way, but so tell requester why it should work.

Here I have a little doubt about “Thread of startMediaCasterStream == Thread of transcoder”. If it’s true, then this example

public String resolvePlayAlias(IApplicationInstance appInstance, String name, IClient client)
{
...
     appInstance.startMediaCasterStream(name, type);
...
}

“Thread of startMediaCasterStream == Thread of transcoder == current Thread”. The transcoded stream should exist once resolvePlayAlias is done because they are on the same thread. But something must be wrong to cause different result, could you point it out?

andy_c

Hi Roger,

Understood. Your code had no error, the previous example is not from yours.

Thank your great effort on this issue.

andy_c