下面的Wowza扩展模块会为HLS切片列表中增加EXT-X-PROGRAM-DATE-TIME 标签。流的第一个切片将作为检索和显示后续切片的基础。
要在HLS切片列表中增加EXT-X-PROGRAM-DATE-TIME标签,你需要为Wowza应用添加cupertinoEnableProgramDateTime属性,并将它设置为true。
注意: 针对Wowza Streaming Engine™ 4.5.0 及以上版本。
package com.wowza.wms.plugin.test2.hlsprogramdatetime;
import java.util.*;
import org.apache.commons.lang.time.*;
import com.wowza.util.*;
import com.wowza.wms.amf.*;
import com.wowza.wms.application.*;
import com.wowza.wms.httpstreamer.cupertinostreaming.livestreampacketizer.*;
import com.wowza.wms.media.mp3.model.idtags.*;
import com.wowza.wms.module.*;
import com.wowza.wms.stream.*;
import com.wowza.wms.stream.livepacketizer.*;
public class ModuleCupertinoProgramDateTime extends ModuleBase
{
private static final Class<ModuleCupertinoProgramDateTime> CLASS = ModuleCupertinoProgramDateTime.class;
private static final String CLASSNAME = "ModuleCupertinoProgramDateTime";
public static final String PROPNAME_TRACKER = "ModuleCupertinoProgramDateTime.ProgramDateTimeTracker";
public static final String DATEFORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSS'+00:00'"; // The date/time representation is ISO/IEC 8601:2004 - 2010-02-19T14:54:23.031+08:00
private FastDateFormat fastDateFormat = FastDateFormat.getInstance(DATEFORMAT, SystemUtils.gmtTimeZone, Locale.US); //you can change it to Locale.CN
private IApplicationInstance appInstance = null;
class ProgramDateTimeTracker
{
long timeOffset = 0;
IMediaStream stream = null;
public ProgramDateTimeTracker(IMediaStream stream)
{
this.stream = stream;
}
}
class LiveStreamPacketizerDataHandler implements IHTTPStreamerCupertinoLivePacketizerDataHandler2
{
private LiveStreamPacketizerCupertino liveStreamPacketizer = null;
private int textId = 1;
private String streamName = null;
public LiveStreamPacketizerDataHandler(LiveStreamPacketizerCupertino liveStreamPacketizer, String streamName)
{
this.liveStreamPacketizer = liveStreamPacketizer;
this.streamName = streamName;
}
public ProgramDateTimeTracker getTracker()
{
ProgramDateTimeTracker tracker = null;
while(true)
{
IMediaStream stream = appInstance.getStreams().getStream(this.streamName);
if (stream == null)
break;
WMSProperties props = stream.getProperties();
synchronized(props)
{
tracker = (ProgramDateTimeTracker)props.getProperty(PROPNAME_TRACKER);
if (tracker == null)
{
tracker = new ProgramDateTimeTracker(stream);
props.put(PROPNAME_TRACKER, tracker);
}
}
break;
}
return tracker;
}
@Override
public void onFillChunkStart(LiveStreamPacketizerCupertinoChunk chunk)
{
ProgramDateTimeTracker tracker = getTracker();
if (tracker != null)
{
ElapsedTimer elapsedTime = tracker.stream.getElapsedTime();
long createTime = elapsedTime.getDate().getTime()+tracker.timeOffset;
String programDateTimeStr = fastDateFormat.format(new Date(createTime));
chunk.setProgramDateTime(programDateTimeStr);
ID3Frames id3Header = liveStreamPacketizer.getID3FramesHeader(chunk.getRendition());
if (id3Header != null)
{
ID3V2FrameTextInformationUserDefined comment = new ID3V2FrameTextInformationUserDefined();
comment.setDescription("programDateTime");
comment.setValue(programDateTimeStr);
id3Header.clear();
id3Header.putFrame(comment);
}
}
}
@Override
public void onFillChunkEnd(LiveStreamPacketizerCupertinoChunk chunk, long timecode)
{
ProgramDateTimeTracker tracker = getTracker();
if (tracker != null)
tracker.timeOffset += chunk.getDuration();
}
@Override
public void onFillChunkDataPacket(LiveStreamPacketizerCupertinoChunk chunk, CupertinoPacketHolder holder, AMFPacket packet, ID3Frames id3Frames)
{
}
@Override
public void onFillChunkMediaPacket(LiveStreamPacketizerCupertinoChunk chunk, CupertinoPacketHolder holder, AMFPacket packet)
{
}
}
class LiveStreamPacketizerListener extends LiveStreamPacketizerActionNotifyBase
{
public void onLiveStreamPacketizerCreate(ILiveStreamPacketizer liveStreamPacketizer, String streamName)
{
if (liveStreamPacketizer instanceof LiveStreamPacketizerCupertino)
{
getLogger().info(CLASSNAME+"#MyLiveListener.onLiveStreamPacketizerCreate["+((LiveStreamPacketizerCupertino)liveStreamPacketizer).getContextStr()+"]");
((LiveStreamPacketizerCupertino)liveStreamPacketizer).setDataHandler(new LiveStreamPacketizerDataHandler((LiveStreamPacketizerCupertino)liveStreamPacketizer, streamName));
}
}
}
public void onAppStart(IApplicationInstance appInstance)
{
this.appInstance = appInstance;
appInstance.addLiveStreamPacketizerListener(new LiveStreamPacketizerListener());
getLogger().info(CLASSNAME+".onAppStart["+appInstance.getContextStr()+"]");
}
}
- 在Wowza Streaming Engine Manager 管理界面,点击Wowza应用的名字(例如live).
- 点击应用主界面的Propertiestab页,再点击Quick Links导航条的Custom链接.
- 在Custom部分,点击Edit.
- 点击Add Custom Property,然后按下面添加cupertinoEnableProgramDateTime属性:
- Path: 选择 /Root/Application/HTTPStreamer.
- Name: 输入 cupertinoEnableProgramDateTime.
- Type: 选择 Boolean.
- Value: 输入 true.
- Path: 选择 /Root/Application/HTTPStreamer.
- 点击 Add, 再点击Save, 然后根据提示点击Restart。
