We were recently asked to look at how to provide absolute timecodes in a stream, regardless of if the encoder sent them or not. This can be done and is extremely simple to do.
package guru.thewowza.example.absolute; import com.wowza.wms.application.*; import com.wowza.wms.amf.*; import com.wowza.wms.module.*; import com.wowza.wms.stream.*; public class Timecode extends ModuleBase { public void onAppStart(IApplicationInstance appInstance) { String fullname = appInstance.getApplication().getName() + "/" + appInstance.getName(); getLogger().info("onAppStart: " + fullname); } public void onAppStop(IApplicationInstance appInstance) { String fullname = appInstance.getApplication().getName() + "/" + appInstance.getName(); getLogger().info("onAppStop: " + fullname); } public void onStreamCreate(IMediaStream stream) { stream.addLivePacketListener(new PacketListener()); } public void onStreamDestroy(IMediaStream stream) { } class PacketListener implements IMediaStreamLivePacketNotify { private boolean firstPacket = false; private long baseTimeCode = 0L; private long baseSystemTime = 0L; private long packetTimeCode = 0L; public PacketListener() { } public void onLivePacket(IMediaStream stream, AMFPacket thisPacket) { if ( this.firstPacket == false ) { this.firstPacket = true; this.baseTimeCode = thisPacket.getAbsTimecode(); this.baseSystemTime = System.currentTimeMillis(); } packetTimeCode = thisPacket.getAbsTimecode()-this.baseTimeCode; packetTimeCode = packetTimeCode + this.baseSystemTime; thisPacket.setAbsTimecode(packetTimeCode); } }
The code simple determines if this is the first run, sets up a base time from the first packet, gets the current system time and then all packet timecodes are a delta from the first packet with the addition of system time.
You will need to compile this code and then add a module entry in your Application.xml of the following
<Module> <Name>Timecode</Name> <Description>Timecode</Description> <Class>guru.thewowza.example.absolute.Timecode</Class> </Module>
You can see this code in action if you enable the Cupertino chunk based on timecode property
<Property> <Name>cupertinoCalculateChunkIDBasedOnTimecode</Name> <Name>true</Name> <Type>Boolean</Type> </Property>
The packetizer would then show the timecode but it appears to be divided by the chunk duration target, so as below you can see the chunk IDs
LiveStreamPacketizerCupertino.endChunkTS[live/_definst_/myStream]: Add chunk: id:1[146084065] mode:TS[H264,AAC] a/v/k:124/200/4 duration:8620 LiveStreamPacketizerCupertino.endChunkTS[live/_definst_/myStream]: Add chunk: id:2[146084066] mode:TS[H264,AAC] a/v/k:143/250/5 duration:10000 LiveStreamPacketizerCupertino.endChunkTS[live/_definst_/myStream]: Add chunk: id:3[146084067] mode:TS[H264,AAC] a/v/k:144/250/5 duration:9984 LiveStreamPacketizerCupertino.endChunkTS[live/_definst_/myStream]: Add chunk: id:4[146084068] mode:TS[H264,AAC] a/v/k:143/250/5 duration:9984 LiveStreamPacketizerCupertino.endChunkTS[live/_definst_/myStream]: Add chunk: id:5[146084069] mode:TS[H264,AAC] a/v/k:143/250/5 duration:9999 LiveStreamPacketizerCupertino.endChunkTS[live/_definst_/myStream]: Add chunk: id:6[146084070] mode:TS[H264,AAC] a/v/k:144/250/5 duration:9984