How to set stream timecodes to absolute time

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

Comments are closed.