• Source code for HTTPProviderMediaList in Wowza Media Server

    This article provides the HTTPProviderMediaList source code that's built into Wowza Media Server.

    Note: Wowza Media Server™ 3.5 or later is required.
    package com.wowza.wms.http;
    
    import java.io.OutputStream;
    import java.util.*;
    
    import com.wowza.util.HTTPUtils;
    import com.wowza.wms.application.*;
    import com.wowza.wms.httpstreamer.cupertinostreaming.httpstreamer.CupertinoStreamingURL;
    import com.wowza.wms.httpstreamer.util.HTTPStreamerUtils;
    import com.wowza.wms.logging.WMSLoggerFactory;
    import com.wowza.wms.medialist.*;
    import com.wowza.wms.stream.IMediaReader;
    import com.wowza.wms.util.*;
    import com.wowza.wms.vhost.*;
    
    public class HTTPProviderMediaList extends HTTProvider2Base
    {
    	private HTTPCrossdomainHandler crossdomainHandler = new HTTPCrossdomainHandler();
    
    	public void onBind(IVHost vhost, HostPort hostPort)
    	{
    		super.onBind(vhost, hostPort);
    		crossdomainHandler.setVHost(vhost);
    	}
    
    	public void setProperties(WMSProperties properties)
    	{
    		super.setProperties(properties);
    		crossdomainHandler.setProperties(properties);
    	}
    
    	public void onHTTPRequest(IVHost vhost, IHTTPRequest req, IHTTPResponse resp)
    	{
    		if (!doHTTPAuthentication(vhost, req, resp))
    			return;
    		
    
    		String smilStr = null;
    		String contentTypeStr = "text/xml";
    		while(true)
    		{
    			String queryStr = req.getQueryString();
    			if (queryStr == null)
    			{
    				WMSLoggerFactory.getLogger(HTTPProviderMediaList.class).warn("HTTPProviderMediaList.onHTTPRequest: Query string missing");
    				break;
    			}
    			
    	        Map<String, String> queryMap = HTTPUtils.splitQueryStr(queryStr);
    	        
    	        String streamName = null;
    	        String comboAppStr = null;
    	        String formatStr = "smil";
    	        String domainStr = req.getHeader("host");
    	        String protocolStr = "rtmp";
    	        
                String url = req.getHeader("context");
                if (url == null)
                    break;
                
                if (url.indexOf("crossdomain.xml") >= 0)
                {
    				WMSLoggerFactory.getLogger(HTTPProviderMediaList.class).warn("HTTPProviderMediaList.onHTTPRequest: crossdomain.xml request");
                	crossdomainHandler.handleCrossdomainRequest(vhost, req, resp);
                	return;
                }
    
        		int qloc = url.indexOf("?");
                if (qloc >= 0)
                	url = url.substring(0, qloc);
    
                url = HTTPStreamerUtils.urlDecode(url);
     	        	        
    	        if (queryMap.get("streamname") != null)
    	        	streamName = queryMap.get("streamname");
    	        
    	        if (queryMap.get("format") != null)
    	        	formatStr = queryMap.get("format");
    	        
    	        if (queryMap.get("application") != null)
    	        	comboAppStr = queryMap.get("application");
    
    	        if (queryMap.get("protocol") != null)
    	        	protocolStr = queryMap.get("protocol");
    
    	        if (queryMap.get("domain") != null)
    	        	domainStr = queryMap.get("domain");
    
    	        boolean decodePath = false;
    	        	        
    	        if (url.endsWith("jwplayer.rss"))
    	        {
    	        	decodePath = true;
    	        	formatStr = "rss.jwplayer";
    	        }
    	        else if (url.endsWith("jwplayer.smil"))
    	        {
    	        	decodePath = true;
    	        	formatStr = "smil.jwplayer";
    	        }
    	        else if (url.endsWith("medialist.smil"))
    	        {
    	        	decodePath = true;
    	        	formatStr = "smil";
    	        }
    	        else if (url.endsWith("manifest-rtmp.f4m"))
    	        {
    	        	decodePath = true;
    	        	formatStr = "f4m.rtmp";
    	        }
    	        
    	        if (decodePath)
    	        {
    	        	CupertinoStreamingURL urlDecoded = new CupertinoStreamingURL(url, true);
    	        	if (urlDecoded != null)
    	        	{
    		        	streamName = urlDecoded.getStreamName();
    		        	comboAppStr = urlDecoded.getAppName()+"/"+urlDecoded.getAppInstanceName();
    	        	}
    	        }
    	        	        
    	        if (streamName == null)
    			{
    				WMSLoggerFactory.getLogger(HTTPProviderMediaList.class).warn("HTTPProviderMediaList.onHTTPRequest: Streamname not specified");
    				break;
    			}
    
    	        if (comboAppStr == null)
    			{
    				WMSLoggerFactory.getLogger(HTTPProviderMediaList.class).warn("HTTPProviderMediaList.onHTTPRequest: Application name not specified");
    				break;
    			}
    	        	        
    	        String applicationStr = comboAppStr;
    	        String appInstanceStr = IApplicationInstance.DEFAULT_APPINSTANCE_NAME;
    	        
    	        int cindex = applicationStr.indexOf("/");
    	        if (cindex > 0)
    	        {
    	        	appInstanceStr = applicationStr.substring(cindex+1);
    	        	applicationStr = applicationStr.substring(0, cindex);
    	        }
    	        
    			IApplication applicationLoc = vhost.getApplication(applicationStr);
    			if (applicationLoc == null)
    			{
    				WMSLoggerFactory.getLogger(HTTPProviderMediaList.class).warn("HTTPProviderMediaList.onHTTPRequest: Application could not be loaded: "+applicationStr);
    				break;
    			}
    			
    			IApplicationInstance appInstance = applicationLoc.getAppInstance(appInstanceStr);
    			if (appInstance == null)
    			{
    				WMSLoggerFactory.getLogger(HTTPProviderMediaList.class).warn("HTTPProviderMediaList.onHTTPRequest: Application instance could not be loaded: "+applicationStr+"/"+appInstanceStr);
    				break;
    			}
    			
    			String streamExt = "smil";
    			
    			String[] streamDecode = ModuleUtils.decodeStreamExtension(streamName, streamExt);
    			streamName = streamDecode[0];
    			streamExt = streamDecode[1];
    
    			if (appInstance.getMediaReaderContentType(streamExt) != IMediaReader.CONTENTTYPE_MEDIALIST)
    			{
    				WMSLoggerFactory.getLogger(HTTPProviderMediaList.class).warn("HTTPProviderMediaList.onHTTPRequest: Stream is not a MediaList: "+applicationStr+"/"+appInstanceStr+"/"+streamExt+":"+streamName);
    				break;
    			}
    			
    			MediaList mediaList = MediaListUtils.parseMediaList(appInstance, streamName, streamExt, null);
    			if (mediaList == null)
    			{
    				WMSLoggerFactory.getLogger(HTTPProviderMediaList.class).warn("HTTPProviderMediaList.onHTTPRequest: MediaList not found: "+applicationStr+"/"+appInstanceStr+"/"+streamExt+":"+streamName);
    				break;
    			}
    			
    			if (formatStr.equalsIgnoreCase("f4m.rtmp"))
    			{
    				//<?xml version="1.0" encoding="utf-8"?>
    				//<manifest xmlns="_http://ns.adobe.com/f4m/1.0"> 
    				//     <id>dynamicStream</id> 
    				//     <mimeType>video/mp4</mimeType> 
    				//     <streamType>live</streamType> 
    				//     <baseURL>rtmp://someURL.net/files-live</baseURL> 
    				//     <media url="file1500" bitrate="1500" /> 
    				//     <media url="file800" bitrate="800" /> 
    				//     <media url="file400" bitrate="400" /> 
    				//</manifest>
    				StringBuffer strBuf = new StringBuffer();
    				
    				strBuf.append("<?xml version="1.0" encoding="utf-8"?>
    ");
    				strBuf.append("<manifest xmlns="http://ns.adobe.com/f4m/1.0">
    ");
    				strBuf.append("	<id>"+streamName+"</id>
    ");
    				strBuf.append("	<mimeType>video/mp4</mimeType>
    ");
    				strBuf.append("	<streamType>live</streamType>
    ");
    				strBuf.append("	<deliveryType>streaming</deliveryType>
    ");
    				strBuf.append("	<baseURL>"+protocolStr+"://"+domainStr+"/"+applicationStr+"/"+appInstanceStr+"</baseURL>
    ");
    				while(true)
    				{
    					MediaListSegment segment = mediaList.getFirstSegment();
    					if (segment == null)
    						break;
    					
    					List<MediaListRendition> renditions = segment.getRenditions();
    					Iterator<MediaListRendition> iter = renditions.iterator();
    					while(iter.hasNext())
    					{
    						MediaListRendition rendtion = iter.next();
    						
    						String urlStr = "";
    						if (rendtion.getName() != null)
    							urlStr = " url=""+rendtion.getName()+""";
    						
    						String widthStr = "";
    						String heightStr = "";
    						if (rendtion.getWidth() > 0)
    							widthStr = " width=""+rendtion.getWidth()+""";
    						if (rendtion.getHeight() > 0)
    							heightStr = " height=""+rendtion.getHeight()+""";
    						
    						String bitrateStr = "";
    						if (rendtion.getBitrateTotal() > 0)
    							bitrateStr = " bitrate=""+(rendtion.getBitrateTotal()/1000)+""";
    
    						strBuf.append("	<media"+urlStr+bitrateStr+widthStr+heightStr+"/>
    ");
    					}
    					break;
    				}
    				strBuf.append("</manifest>
    ");
    				
    				smilStr = strBuf.toString();
    			}
    			else if (formatStr.equalsIgnoreCase("smil.jwplayer"))
    			{
    				//<smil>
    				//  <head>
    				//    <meta base="rtmp://example.com/vod/" />
    				//  </head>
    				//  <body>
    				//    <switch>
    				//      <video src="myVideo-high.mp4" height="720"
    				//system-bitrate="2000000" width="1280" />
    				//      <video src="myVideo-medium.mp4" height="360"
    				//system-bitrate="800000" width="640" />
    				//      <video src="myVideo-low.mp4" height="180"
    				//system-bitrate="300000" width="320" />
    				//    </switch>
    				//  </body>
    				//</smil>
    				
    				StringBuffer strBuf = new StringBuffer();
    				
    				strBuf.append("<smil>
    ");
    				strBuf.append("	<head>
    ");
    				strBuf.append("		<meta base=""+protocolStr+"://"+domainStr+"/"+applicationStr+"/"+appInstanceStr+"" />
    ");
    				strBuf.append("	</head>
    ");
    				strBuf.append("	<body>
    ");
    				strBuf.append("		<switch>
    ");
    				
    				while(true)
    				{
    					MediaListSegment segment = mediaList.getFirstSegment();
    					if (segment == null)
    						break;
    					
    					List<MediaListRendition> renditions = segment.getRenditions();
    					Iterator<MediaListRendition> iter = renditions.iterator();
    					while(iter.hasNext())
    					{
    						MediaListRendition rendtion = iter.next();
    						
    						// skip textstream
    						if (rendtion.getType() == IVHost.CONTENTTYPE_DATA)
    							continue;
    						
    						String urlStr = "";
    						if (rendtion.getName() != null)
    							urlStr = " src=""+rendtion.getName()+""";
    						
    						String widthStr = "";
    						String heightStr = "";
    						if (rendtion.getWidth() > 0)
    							widthStr = " width=""+rendtion.getWidth()+""";
    						if (rendtion.getHeight() > 0)
    							heightStr = " height=""+rendtion.getHeight()+""";
    						
    						String bitrateStr = "";
    						if (rendtion.getBitrateTotal() > 0)
    							bitrateStr = " system-bitrate=""+(rendtion.getBitrateTotal())+""";
    						
    						strBuf.append("			<video"+urlStr+bitrateStr+widthStr+heightStr+"/>
    ");
    					}
    					break;
    				}
    				
    				strBuf.append("		</switch>
    ");
    				strBuf.append("	</body>
    ");
    				strBuf.append("</smil>
    ");
    				
    				smilStr = strBuf.toString();
    			}
    			else if (formatStr.equalsIgnoreCase("rss.jwplayer"))
    			{
    				//<rss version="2.0" xmlns:media="http://search.yahoo.com/mrss/"
    				//  xmlns:jwplayer="http://developer.longtailvideo.com/">
    				//  <channel>
    				//    <item>
    				//      <title>Demos Flash Bitrate Switching</title>
    				//      <description>Demos Flash Bitrate Switching</description>
    				//      <jwplayer:streamer>rtmp://184.72.239.149/demos</jwplayer:streamer>
    				//      <media:group>
    				//        <media:content bitrate="1500" url="bigbuckbunny_1500.mp4"  width="1080" />
    				//        <media:content bitrate="1100" url="bigbuckbunny_1100.mp4" width="640"/>
    				//        <media:content bitrate="750" url="bigbuckbunny_750.mp4" width="476" />
    				//        <media:content bitrate="450" url="bigbuckbunny_450.mp4" width="320" />
    				//      </media:group>
    				//    </item>
    				//  </channel>
    				//</rss>
    				
    				StringBuffer strBuf = new StringBuffer();
    				
    				strBuf.append("<rss version="2.0" xmlns:media="http://search.yahoo.com/mrss/" xmlns:jwplayer="http://developer.longtailvideo.com/">
    ");
    				strBuf.append("	<channel>
    ");
    				strBuf.append("		<item>
    ");
    				strBuf.append("			<title>"+streamName+"</title>
    ");
    				strBuf.append("			<description>"+streamName+"</description>
    ");
    				strBuf.append("			<jwplayer:streamer>"+protocolStr+"://"+domainStr+"/"+applicationStr+"/"+appInstanceStr+"</jwplayer:streamer>
    ");
    				strBuf.append("			<media:group>
    ");
    				
    				while(true)
    				{
    					MediaListSegment segment = mediaList.getFirstSegment();
    					if (segment == null)
    						break;
    					
    					List<MediaListRendition> renditions = segment.getRenditions();
    					Iterator<MediaListRendition> iter = renditions.iterator();
    					while(iter.hasNext())
    					{
    						MediaListRendition rendtion = iter.next();
    						
    						String urlStr = "";
    						if (rendtion.getName() != null)
    							urlStr = " url=""+rendtion.getName()+""";
    						
    						String widthStr = "";
    						String heightStr = "";
    						if (rendtion.getWidth() > 0)
    							widthStr = " width=""+rendtion.getWidth()+""";
    						if (rendtion.getHeight() > 0)
    							heightStr = " height=""+rendtion.getHeight()+""";
    						
    						String bitrateStr = "";
    						if (rendtion.getBitrateTotal() > 0)
    							bitrateStr = " bitrate=""+(rendtion.getBitrateTotal()/1000)+""";
    
    						strBuf.append("				<media:content"+urlStr+bitrateStr+widthStr+heightStr+"/>
    ");
    					}
    					break;
    				}
    				
    				strBuf.append("			</media:group>
    ");
    				strBuf.append("		</item>
    ");
    				strBuf.append("	</channel>
    ");
    				strBuf.append("</rss>");
    				
    				smilStr = strBuf.toString();
    			}
    			else
    				smilStr = mediaList.toSMILString();
    			break;
    		}
    		
    		try
    		{
    			if (smilStr != null)
    			{
    				resp.setHeader("Content-Type", contentTypeStr);
    
    				OutputStream out = resp.getOutputStream();
    
    				byte[] outBytes = smilStr.getBytes();
    							
    				out.write(outBytes);
    			}
    			else
    				resp.setResponseCode(404);
    		}
    		catch (Exception e)
    		{
    			WMSLoggerFactory.getLogger(HTTPProviderMediaList.class).error("HTTPProviderMediaList.onHTTPRequest ", e);
    		}	
    	}
    }

    Originally Published: For Wowza Media Server 3.5 on 01-10-2013

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