How to use Java API calls to resolve SMIL file requests (AMLST)

SMIL files are used in Wowza Media Server to describe multi-bitrate streams (both live and video on demand). There is also an API to intercept requests for multi-bitrate streams and provide the stream grouping through Java API calls. To use this new feature, you must use the stream name prefix amlst: (which stands for API based MediaList). A MediaList is a set of Java objects that describe a multi-bitrate stream. When the Wowza media server reads a SMIL file it creates a MediaList and passes it back to the streaming provider. This API provides a means to intercept these requests and create the MediaList dynamically in a Wowa Media Server module.

Each ApplicationInstance has a IMediaListProvider provider interface. This interface is used to resolve stream names that are prefixed with the amlst: prefix to MediaList objects. In a module you can create your own IMediaListProvider implementation and replace the default implementation.

MediaList object structure


A MediaList has the following object structure:

MediaList
|
--MediaListSegment
  |
  --MediaListRendition
    [...]

For now a MediaList has a single MediaListSegment (in the future we will add support for multiple MediaList segements or playlists). The MediaListSegement can have multiple MediaListRenditions each representing a single multi-bitrate rendition.

Live streaming sample module, configuration, and playback


Here is a sample module that implements this interface for live streaming:

package com.wowza.wms.plugin.test.module;

import com.wowza.wms.medialist.*;
import com.wowza.wms.module.*;
import com.wowza.wms.stream.*;
import com.wowza.wms.application.*;

public class ModuleAMLSTTestLive extends ModuleBase 
{
	class MyMediaListProvider implements IMediaListProvider
	{
		public MediaList resolveMediaList(IMediaListReader mediaListReader, IMediaStream stream, String streamName)
		{
			MediaList mediaList = new MediaList();

			MediaListSegment segment = new MediaListSegment();
			mediaList.addSegment(segment);

			MediaListRendition rendition1 = new MediaListRendition();
			segment.addRendition(rendition1);

			rendition1.setName(streamName+"_400");
			rendition1.setBitrateAudio(128000);
			rendition1.setBitrateVideo(400000);
			rendition1.setWidth(320);
			rendition1.setHeight(240);
			rendition1.setAudioCodecId("mp4a.40.2");
			rendition1.setVideoCodecId("avc1.66.12");

			MediaListRendition rendition2 = new MediaListRendition();
			segment.addRendition(rendition2);

			rendition2.setName(streamName+"_800");
			rendition2.setBitrateAudio(128000);
			rendition2.setBitrateVideo(800000);
			rendition2.setWidth(640);
			rendition2.setHeight(480);
			rendition2.setAudioCodecId("mp4a.40.2");
			rendition2.setVideoCodecId("avc1.77.31");

			return mediaList;
		}
	}

	public void onAppStart(IApplicationInstance appInstance)
	{
		appInstance.setMediaListProvider(new MyMediaListProvider());
	}

}

Add this module as the last entry in the <Modules> list in [install-dir]/conf/[application]/Application.xml:

<Module>
	<Name>ModuleAMLSTTestLive</Name>
	<Description>ModuleAMLSTTestLive</Description>
	<Class>com.wowza.wms.plugin.test.module.ModuleAMLSTTestLive</Class>
</Module>

Quickly looking at the components of this module:

  • Module extends the ModuleBase
  • Internal class MyMediaListProvider implements the IMediaListProvider interface and returns a new MediaList based on the stream name.
  • The onAppStart method is used to replace the application instance level IMediaListProvider with our implementation.

This module will intercept any request for stream names that start with amlst: such as

Apple iOS device (Cupertino/Apple HTTP Live Streaming):

http://[wowza-ip-address]:1935/live/amlst:myStream/playlist.m3u8

Microsoft Silverlight (Smooth Streaming):

http://[wowza-ip-address]:1935/live/amlst:myStream/Manifest

Adobe Flash player (San Jose/Flash HTTP):

http://[wowza-ip-address]:1935/live/amlst:myStream/manifest.f4m

It will return a multi-bitrate description with two renditions using the stream name as the base name for the filename. This is equivelent to the SMIL file:

<smil>
	<head>
	</head>
	<body>
		<switch>
			<video src="myStream_400" width="320" height="240" system-bitrate="528000">
				<param name="audioCodecId" value="mp4a.40.2" valuetype="data"/>
				<param name="videoCodecId" value="avc1.66.12" valuetype="data"/>
				<param name="audioBitrate" value="128000" valuetype="data"/>
				<param name="videoBitrate" value="400000" valuetype="data"/>
			</video>
			<video src="myStream_800" width="640" height="480" system-bitrate="928000">
				<param name="audioCodecId" value="mp4a.40.2" valuetype="data"/>
				<param name="videoCodecId" value="avc1.77.31" valuetype="data"/>
				<param name="audioBitrate" value="128000" valuetype="data"/>
				<param name="videoBitrate" value="800000" valuetype="data"/>
			</video>
		</switch>
	</body>
</smil>

Video-on-demand streaming sample module, configuration, and playback


Here is a sample module that implements this interface for vod streaming::

package com.wowza.wms.plugin.test.module;

import com.wowza.wms.medialist.*;
import com.wowza.wms.module.*;
import com.wowza.wms.stream.*;
import com.wowza.wms.application.*;

public class ModuleAMLSTTest extends ModuleBase 
{
	class MyMediaListProvider implements IMediaListProvider
	{
		public MediaList resolveMediaList(IMediaListReader mediaListReader, IMediaStream stream, String streamName)
		{
			MediaList mediaList = new MediaList();

			MediaListSegment segment = new MediaListSegment();
			mediaList.addSegment(segment);

			MediaListRendition rendition1 = new MediaListRendition();
			segment.addRendition(rendition1);

			rendition1.setName("mp4:"+streamName+"_400k.mp4");
			rendition1.setBitrateAudio(128000);
			rendition1.setBitrateVideo(400000);
			rendition1.setWidth(320);
			rendition1.setHeight(240);
			rendition1.setAudioCodecId("mp4a.40.2");
			rendition1.setVideoCodecId("avc1.66.12");

			MediaListRendition rendition2 = new MediaListRendition();
			segment.addRendition(rendition2);

			rendition2.setName("mp4:"+streamName+"_800k.mp4");
			rendition2.setBitrateAudio(128000);
			rendition2.setBitrateVideo(800000);
			rendition2.setWidth(640);
			rendition2.setHeight(480);
			rendition2.setAudioCodecId("mp4a.40.2");
			rendition2.setVideoCodecId("avc1.77.31");

			return mediaList;
		}
	}

	public void onAppStart(IApplicationInstance appInstance)
	{
		appInstance.setMediaListProvider(new MyMediaListProvider());
	}

}

Add this module as the last entry in the <Modules> list in [install-dir]/conf/[application]/Application.xml:

<Module>
	<Name>ModuleAMLSTTest</Name>
	<Description>ModuleAMLSTTest</Description>
	<Class>com.wowza.wms.plugin.test.module.ModuleAMLSTTest</Class>
</Module>

Quickly looking at the components of this module:

  • Module extends the ModuleBase
  • Internal class MyMediaListProvider implements the IMediaListProvider interface and returns a new MediaList based on the stream name.
  • The onAppStart method is used to replace the application instance level IMediaListProvider with our implementation.

This module will intercept any request for stream names that start with amlst: such as:

Apple iOS device (Cupertino/Apple HTTP Live Streaming):

http://[wowza-ip-address]:1935/vod/amlst:sample/playlist.m3u8

Microsoft Silverlight (Smooth Streaming):

http://[wowza-ip-address]:1935/vod/amlst:sample/Manifest

Adobe Flash player (San Jose/Flash HTTP):

http://[wowza-ip-address]:1935/vod/amlst:sample/manifest.f4m

It will return a multi-bitrate description with two renditions using the stream name as the base name for the filename. This is equivalent to the SMIL file:

<smil>
	<head>
	</head>
	<body>
		<switch>
			<video src="mp4:sample_400.mp4" width="320" height="240" system-bitrate="528000">
				<param name="videoCodecId" value="avc1.66.12" valuetype="data"/>
				<param name="audioCodecId" value="mp4a.40.2" valuetype="data"/>
				<param name="audioBitrate" value="128000" valuetype="data"/>
				<param name="videoBitrate" value="400000" valuetype="data"/>
			</video>
			<video src="mp4:sample_800.mp4" width="640" height="480" system-bitrate="928000">
				<param name="videoCodecId" value="avc1.77.31" valuetype="data"/>
				<param name="audioCodecId" value="mp4a.40.2" valuetype="data"/>
				<param name="audioBitrate" value="128000" valuetype="data"/>
				<param name="videoBitrate" value="800000" valuetype="data"/>
			</video>
		</switch>
	</body>
</smil>
Note: The IMediaListReader interface does provide additional context information such as the IHTTPStreamerSession from which the stream is being requested.

Originally Published: 10-09-2011.

If you're having problems or want to discuss this article, post in our forum.