Wowza Streaming Engine™ media server software can be configured as an HTTP origin for stream delivery. When in HTTP origin mode, Wowza Streaming Engine combines all sessions with a given stream name into a single session by default. This is problematic if you're using certain features, such as wowzaplaystart and wowzaplayduration query parameters, to control playback because while these features are in use, the proper start and duration aren't tracked in the single session for viewers that are using different values. However, the IHTTPStreamerHTTPOriginSessionIdProvider API hook enables you to control the httpOriginId, which is used to combine sessions and determine if a session is unique. This article demonstrates how to create unique sessions for an Apple HLS (cupertino) stream using the IHTTPStreamerHTTPOriginSessionIdProvider API hook and the wowzaplaystart and wowzaplayduration query parameters.
Notes:
- Wowza Streaming Engine 4.4.0 or later is required to use the IHTTPStreamerHTTPOriginSessionIdProvider API hook to control HTTP origin session creation and combination.
- The IHTTPStreamerHTTPOriginSessionIdProvider API hook won't work properly if you require different behaviors based on the query parameter, such as wowzaplaystart or wowzaplayduration.
import java.util.*; import com.wowza.util.*; import com.wowza.wms.application.*; import com.wowza.wms.http.*; import com.wowza.wms.httpstreamer.cupertinostreaming.httpstreamer.*; import com.wowza.wms.httpstreamer.model.*; import com.wowza.wms.httpstreamer.util.*; import com.wowza.wms.module.*; import com.wowza.wms.vhost.*; public class ModuleTestHTTPOriginSessionIdProvider extends ModuleBase { class MyHTTPOriginSessionIdProvider implements IHTTPStreamerHTTPOriginSessionIdProvider { HTTPStreamerApplicationContextCupertinoStreamer appContextCupertino = null; HTTPStreamerAdapterCupertinoStreamer streamAdapterCupertino = null; public MyHTTPOriginSessionIdProvider(HTTPStreamerApplicationContextCupertinoStreamer appContextCupertino, HTTPStreamerAdapterCupertinoStreamer streamAdapterCupertino) { this.appContextCupertino = appContextCupertino; this.streamAdapterCupertino = streamAdapterCupertino; } public String getHTTPOriginId(String httpOriginId, IHTTPRequest req, IHTTPStreamerApplicationContext appContext, String oldSessionId, String streamDomainStr, boolean isHTTPOrigin, boolean isDvr, long currTime) { long playStart = 0; long playDuration = -1; String queryStr = req.getQueryString(); if (queryStr != null) { Map<String, String> queryMap = HTTPUtils.splitQueryStr(queryStr); String playStartStr = queryMap.get(streamAdapterCupertino.getPlayStartQueryParameter()); if (playStartStr != null) { try { playStart = Long.parseLong(playStartStr); } catch(Exception e) { } } String playDurationStr = queryMap.get(streamAdapterCupertino.getPlayDurationQueryParameter()); if (playDurationStr != null) { try { playDuration = Long.parseLong(playDurationStr); } catch(Exception e) { } } } httpOriginId = httpOriginId+"|playStart="+playStart+"|playDuration="+playDuration; getLogger().info("ModuleTestHTTPOriginSessionIdProvider#MyHTTPOriginSessionIdProvider.getHTTPOriginId:"+httpOriginId); return httpOriginId; } } public void onAppStart(IApplicationInstance appInstance) { getLogger().info("ModuleTestHTTPOriginSessionIdProvider.onAppStart["+appInstance.getContextStr()+"]"); IVHost vhost = appInstance.getVHost(); String adapterName = HTTPStreamerUtils.httpSessionProtocolToName(IHTTPStreamerSession.SESSIONPROTOCOL_CUPERTINOSTREAMING); IHTTPStreamerApplicationContext appContext = appInstance.getHTTPStreamerApplicationContext(adapterName, true); IHTTPStreamerAdapter streamerAdapter = vhost.getHTTPStreamerAdapter(adapterName); if (appContext != null && streamerAdapter != null) { MyHTTPOriginSessionIdProvider httpOriginSessionIdProvider = new MyHTTPOriginSessionIdProvider((HTTPStreamerApplicationContextCupertinoStreamer)appContext, (HTTPStreamerAdapterCupertinoStreamer)streamerAdapter); appContext.setHTTPOriginSessionIdProvider(httpOriginSessionIdProvider); } } }