Page 1 of 2 12 LastLast
Results 1 to 10 of 11

Thread: Get Framerate for Live Stream

  1. #1

    Question Get Framerate for Live Stream

    I searched the forums and server-api. All I could find was how to grab the bitrate for a stream. I'm looking for the framerate AKA "FPS" for a live stream.

    I'm setting a task that logs that publisher's FPS every 5 minutes.

    Currently looked at:

    StreamUtils.getStreamBitrate(stream) which gives me 0.0
    stream.getReceiveVideoFPS() which gives me -1

    Any help would be much appreciated.

  2. #2
    Join Date
    Dec 2007
    Posts
    22,013

    Default

    Take a look at the IOPerformanceCounter API. You can attach this to stream or session to get much info:

    Also, you can get metadata from live stream with IMediaStreamActionNotify3.onCodecInfoVideo() and IMediaStreamActionNotify3.onVideoInfoVideo()

    Richard

  3. #3

    Default

    I looked at IOPerformanceCounter API and it look like at on 3.6 there isn't a framerate property, bitrate yes but don't see the FPS. Am I missing something?

    As far as IMediaStreamActionNotify codecInfoVideo.getFrameRate() returns 0.0. Any reason this value is 0 all the time?

  4. #4
    Join Date
    Dec 2007
    Posts
    22,013

    Default

    You will usually find FPS in the metadata actually, and there is IMediaStreamActionNotify3.onMetadata() that I forgot to mention, sorry. This is just what the encoder is reporting in the stream's metadata, but should be accurate for the source. Frame rate at the client can be variable.

    Richard

  5. #5

    Default

    I guess the problem is that the client sets the metadata to a specific FPS. So I was trying to find the actual FPS on the server side and not something that the client can manipulate. That metadata framerate property looks at the camera settings. Because of possible network congestion etc the FPS actually goes lower yet the metadata still says 15. We've seen it go down to 3. I want to set-up a task that detects if the FPS gets below 10.

    Looks like in the Server API Doc
    getReceiveVideoFPS()
    Set frame per seconds for video (not currently implemented)

    Do you know when that might be implemented?

  6. #6
    Join Date
    Dec 2007
    Posts
    22,013

    Default

    I tried IMediaStream.getReceiveVideoFPS(), and it does seem to be not implemented. It sounds like it would provide what you want, but I am not sure and I don't have a time frame for when it might be implemented

    Meanwhile, I think IOPerformanceCounter.getMessagesInBytesRate() is the best metric available for your needs. You can monitor with an Application module (From the Wowza Collection) like this:

    /**
     * Wowza server software and all components Copyright 2006 - 2014, Wowza Media Systems, LLC, licensed pursuant to the Wowza Media Software End User License Agreement.
     */
    package com.wowza.wms.plugin.collection.module;
    
    import java.util.Date;
    import java.util.Timer;
    import java.util.TimerTask;
    
    import com.wowza.util.IOPerformanceCounter;
    import com.wowza.wms.amf.AMFPacket;
    import com.wowza.wms.application.IApplicationInstance;
    import com.wowza.wms.application.WMSProperties;
    import com.wowza.wms.logging.WMSLogger;
    import com.wowza.wms.logging.WMSLoggerFactory;
    import com.wowza.wms.logging.WMSLoggerIDs;
    import com.wowza.wms.module.ModuleBase;
    import com.wowza.wms.stream.IMediaStream;
    import com.wowza.wms.stream.IMediaStreamActionNotify;
    import com.wowza.wms.stream.IMediaStreamActionNotify2;
    
    public class ModuleLimitPublishedStreamBandwidth extends ModuleBase implements IMediaStreamActionNotify
    {
    	private class MonitorStream
    	{
    		public Timer mTimer;
    		public TimerTask mTask;
    		public IMediaStream stream;
    	
    		public MonitorStream(IMediaStream s)
    		{
    			stream = s;
    			mTask = new TimerTask()
    			{
    				public void run()
    				{
    	
    					if (stream == null)
    						stop();
    	
    					IOPerformanceCounter perf = stream.getMediaIOPerformance();
    					Double bitrate = perf.getMessagesInBytesRate() * 8 * .001;
    	
    					if (debugLog)
    						logger.info(MODULE_NAME + ".MonitorStream.run '" + stream.getName() + "' BitRate: " + Math.round(Math.floor(bitrate)) + "kbs, MaxBitrate:" + maxBitrate, WMSLoggerIDs.CAT_application, WMSLoggerIDs.EVT_comment);
    	
    					if (bitrate > maxBitrate && maxBitrate > 0)
    					{
    						logger.info(MODULE_NAME + ".MonitorStream.run Sent NetStream.Publish.Rejected to " + stream.getClientId() + " stream name: " + stream.getName() + ", BitRate: " + Math.round(Math.floor(bitrate)) + "kbs", WMSLoggerIDs.CAT_application, WMSLoggerIDs.EVT_comment);
    						sendStreamOnStatusError(stream, "NetStream.Publish.Rejected", "bitrate too high: " + Math.round(Math.floor(bitrate)) + "kbs");
    	
    						stream.getClient().setShutdownClient(true);
    					}
    				}
    			};
    			mTimer = new Timer();
    		}
    	
    		public void start()
    		{
    			if (mTimer == null)
    				mTimer = new Timer();
    			mTimer.scheduleAtFixedRate(mTask, new Date(), interval);
    		}
    	
    		public void stop()
    		{
    			if (mTimer != null)
    			{
    				mTimer.cancel();
    				mTimer = null;
    			}
    		}
    	}
    
    	public static final String MODULE_NAME = "ModuleLimitPublishedStreamBandwidth";
    	public static final String PROP_NAME_PREFIX = "limitPublishedStreamBandwidth";
    	
    	int maxBitrate = 800; // 0 = no limit
    	int sustained = 10;
    	int interval = 5000;
    	boolean debugLog = false;
    	
    	WMSLogger logger = null;
    
    	public void onAppStart(IApplicationInstance appInstance)
    	{
    		this.logger = WMSLoggerFactory.getLoggerObj(appInstance);
    		
    		// old prop name
    		maxBitrate = appInstance.getProperties().getPropertyInt("MaxBitrate", maxBitrate);
    		// new prop name
    		maxBitrate = appInstance.getProperties().getPropertyInt(PROP_NAME_PREFIX + "MaxBitrate", maxBitrate);
    		
    		// old prop name
    		debugLog = appInstance.getProperties().getPropertyBoolean("StreamMonitorLogging", debugLog);
    		// new prop name
    		debugLog = appInstance.getProperties().getPropertyBoolean(PROP_NAME_PREFIX + "DebugLog", debugLog);
    		if(logger.isDebugEnabled())
    			debugLog = true;
    		
    		sustained = appInstance.getProperties().getPropertyInt(PROP_NAME_PREFIX + "Sustained", sustained); // not used
    		
    		logger.info(MODULE_NAME + " MaxBitrate: " + maxBitrate, WMSLoggerIDs.CAT_application, WMSLoggerIDs.EVT_comment);
    	}
    
    	public void onStreamCreate(IMediaStream stream)
    	{
    		stream.addClientListener(this);
    	}
    
    	public void onStreamDestroy(IMediaStream stream)
    	{
    		stream.removeClientListener(this);
    	}
    
    	public void onUnPublish(IMediaStream stream, String streamName, boolean isRecord, boolean isAppend)
    	{
    		logger.info(MODULE_NAME + ".onUnPublish: " + stream.getName());
    		WMSProperties props = stream.getProperties();
    
    		MonitorStream monitor;
    
    		synchronized(props)
    		{
    			monitor = (MonitorStream)props.get("monitor");
    		}
    		if (monitor != null)
    			monitor.stop();
    	}
    
    	public void onPublish(IMediaStream stream, String streamName, boolean isRecord, boolean isAppend)
    	{
    		MonitorStream monitor = new MonitorStream(stream);
    		WMSProperties props = stream.getProperties();
    		synchronized(props)
    		{
    			props.put("monitor", monitor);
    		}
    		monitor.start();
    	}
    
    	public void onPlay(IMediaStream stream, String streamName, double playStart, double playLen, int playReset)
    	{
    	}
    
    	public void onSeek(IMediaStream stream, double location)
    	{
    	}
    
    	public void onStop(IMediaStream stream)
    	{
    	}
    
    	public void onPause(IMediaStream stream, boolean isPause, double location)
    	{
    	}
    }
    Richard

  7. #7

    Default

    Thanks Richard. We currently already implement IOPerformanceCounter.getMessagesInBytesRate(). We have a very specific need for FPS. Should I enter a support ticket in so we can track when this method will be available?

    Quote Originally Posted by rrlanham View Post
    I tried IMediaStream.getReceiveVideoFPS(), and it does seem to be not implemented. It sounds like it would provide what you want, but I am not sure and I don't have a time frame for when it might be implemented

    Meanwhile, I think IOPerformanceCounter.getMessagesInBytesRate() is the best metric available for your needs. You can monitor with an Application module (From the Wowza Collection) like this:

    /**
     * Wowza server software and all components Copyright 2006 - 2014, Wowza Media Systems, LLC, licensed pursuant to the Wowza Media Software End User License Agreement.
     */
    package com.wowza.wms.plugin.collection.module;
    
    import java.util.Date;
    import java.util.Timer;
    import java.util.TimerTask;
    
    import com.wowza.util.IOPerformanceCounter;
    import com.wowza.wms.amf.AMFPacket;
    import com.wowza.wms.application.IApplicationInstance;
    import com.wowza.wms.application.WMSProperties;
    import com.wowza.wms.logging.WMSLogger;
    import com.wowza.wms.logging.WMSLoggerFactory;
    import com.wowza.wms.logging.WMSLoggerIDs;
    import com.wowza.wms.module.ModuleBase;
    import com.wowza.wms.stream.IMediaStream;
    import com.wowza.wms.stream.IMediaStreamActionNotify;
    import com.wowza.wms.stream.IMediaStreamActionNotify2;
    
    public class ModuleLimitPublishedStreamBandwidth extends ModuleBase implements IMediaStreamActionNotify
    {
    	private class MonitorStream
    	{
    		public Timer mTimer;
    		public TimerTask mTask;
    		public IMediaStream stream;
    	
    		public MonitorStream(IMediaStream s)
    		{
    			stream = s;
    			mTask = new TimerTask()
    			{
    				public void run()
    				{
    	
    					if (stream == null)
    						stop();
    	
    					IOPerformanceCounter perf = stream.getMediaIOPerformance();
    					Double bitrate = perf.getMessagesInBytesRate() * 8 * .001;
    	
    					if (debugLog)
    						logger.info(MODULE_NAME + ".MonitorStream.run '" + stream.getName() + "' BitRate: " + Math.round(Math.floor(bitrate)) + "kbs, MaxBitrate:" + maxBitrate, WMSLoggerIDs.CAT_application, WMSLoggerIDs.EVT_comment);
    	
    					if (bitrate > maxBitrate && maxBitrate > 0)
    					{
    						logger.info(MODULE_NAME + ".MonitorStream.run Sent NetStream.Publish.Rejected to " + stream.getClientId() + " stream name: " + stream.getName() + ", BitRate: " + Math.round(Math.floor(bitrate)) + "kbs", WMSLoggerIDs.CAT_application, WMSLoggerIDs.EVT_comment);
    						sendStreamOnStatusError(stream, "NetStream.Publish.Rejected", "bitrate too high: " + Math.round(Math.floor(bitrate)) + "kbs");
    	
    						stream.getClient().setShutdownClient(true);
    					}
    				}
    			};
    			mTimer = new Timer();
    		}
    	
    		public void start()
    		{
    			if (mTimer == null)
    				mTimer = new Timer();
    			mTimer.scheduleAtFixedRate(mTask, new Date(), interval);
    		}
    	
    		public void stop()
    		{
    			if (mTimer != null)
    			{
    				mTimer.cancel();
    				mTimer = null;
    			}
    		}
    	}
    
    	public static final String MODULE_NAME = "ModuleLimitPublishedStreamBandwidth";
    	public static final String PROP_NAME_PREFIX = "limitPublishedStreamBandwidth";
    	
    	int maxBitrate = 800; // 0 = no limit
    	int sustained = 10;
    	int interval = 5000;
    	boolean debugLog = false;
    	
    	WMSLogger logger = null;
    
    	public void onAppStart(IApplicationInstance appInstance)
    	{
    		this.logger = WMSLoggerFactory.getLoggerObj(appInstance);
    		
    		// old prop name
    		maxBitrate = appInstance.getProperties().getPropertyInt("MaxBitrate", maxBitrate);
    		// new prop name
    		maxBitrate = appInstance.getProperties().getPropertyInt(PROP_NAME_PREFIX + "MaxBitrate", maxBitrate);
    		
    		// old prop name
    		debugLog = appInstance.getProperties().getPropertyBoolean("StreamMonitorLogging", debugLog);
    		// new prop name
    		debugLog = appInstance.getProperties().getPropertyBoolean(PROP_NAME_PREFIX + "DebugLog", debugLog);
    		if(logger.isDebugEnabled())
    			debugLog = true;
    		
    		sustained = appInstance.getProperties().getPropertyInt(PROP_NAME_PREFIX + "Sustained", sustained); // not used
    		
    		logger.info(MODULE_NAME + " MaxBitrate: " + maxBitrate, WMSLoggerIDs.CAT_application, WMSLoggerIDs.EVT_comment);
    	}
    
    	public void onStreamCreate(IMediaStream stream)
    	{
    		stream.addClientListener(this);
    	}
    
    	public void onStreamDestroy(IMediaStream stream)
    	{
    		stream.removeClientListener(this);
    	}
    
    	public void onUnPublish(IMediaStream stream, String streamName, boolean isRecord, boolean isAppend)
    	{
    		logger.info(MODULE_NAME + ".onUnPublish: " + stream.getName());
    		WMSProperties props = stream.getProperties();
    
    		MonitorStream monitor;
    
    		synchronized(props)
    		{
    			monitor = (MonitorStream)props.get("monitor");
    		}
    		if (monitor != null)
    			monitor.stop();
    	}
    
    	public void onPublish(IMediaStream stream, String streamName, boolean isRecord, boolean isAppend)
    	{
    		MonitorStream monitor = new MonitorStream(stream);
    		WMSProperties props = stream.getProperties();
    		synchronized(props)
    		{
    			props.put("monitor", monitor);
    		}
    		monitor.start();
    	}
    
    	public void onPlay(IMediaStream stream, String streamName, double playStart, double playLen, int playReset)
    	{
    	}
    
    	public void onSeek(IMediaStream stream, double location)
    	{
    	}
    
    	public void onStop(IMediaStream stream)
    	{
    	}
    
    	public void onPause(IMediaStream stream, boolean isPause, double location)
    	{
    	}
    }
    Richard

  8. #8
    Join Date
    Dec 2007
    Posts
    22,013

    Default

    Actually, I think there is a better way. I will get back to you on this today.

    Richard

  9. #9
    Join Date
    Dec 2007
    Posts
    22,013

    Default

    Take a look at this example (from soon to be published article:

    package test;
    
    import com.wowza.wms.amf.AMFDataList;
    import com.wowza.wms.amf.AMFPacket;
    import com.wowza.wms.application.IApplicationInstance;
    import com.wowza.wms.client.IClient;
    import com.wowza.wms.module.ModuleBase;
    import com.wowza.wms.request.RequestFunction;
    import com.wowza.wms.stream.IMediaStream;
    import com.wowza.wms.stream.IMediaStreamLivePacketNotify;
    
    public class ModuleLiveFrameRate extends ModuleBase
    {
    	class PacketListener implements IMediaStreamLivePacketNotify
    	{
    		/**
    		* onLivePacket is called for every packet that is received for the live stream before the packet is processed for playback.
    		* It is very important that this method returns quickly and is not delayed in any way.
    		*/
    		@Override
    		public void onLivePacket(IMediaStream stream, AMFPacket packet)
    		{
    			if (packet.isVideo())
    			{
    				// packet.getTimecode(); returns the elapsed time, in milliseconds, between this packet and the last packet of the same type.
    				double fps = (double)1000 / packet.getTimecode();
    				stream.getProperties().setProperty("currentFPS", new Double(fps));
    				getLogger().info("FPS: " + fps); // this makes a lot of logging.
    			}
    		}
    
    	}
    
    	private PacketListener packetListener = new PacketListener();
    	private IApplicationInstance appInstance;
    
    	public void onAppStart(IApplicationInstance appInstance)
    	{
    		this.appInstance = appInstance;
    	}
    
    	public void onStreamCreate(IMediaStream stream)
    	{
    		stream.addLivePacketListener(packetListener);
    	}
    
    	public void onStreamDestroy(IMediaStream stream)
    	{
    		stream.removeLivePacketListener(packetListener);
    	}
    
    	public void getCurrentFPS(IClient client, RequestFunction function, AMFDataList params)
    	{
    		double fps = 0;
    		String streamName = getParamString(params, PARAM1);
    		if (streamName != null)
    		{
    			fps = getCurrentFPS(streamName);
    		}
    
    		sendResult(client, params, fps);
    	}
    
    	public double getCurrentFPS(String streamName)
    	{
    		double fps = 0;
    		IMediaStream stream = appInstance.getStreams().getStream(streamName);
    		if (stream != null)
    		{
    			fps = stream.getProperties().getPropertyDouble("currentFPS", fps);
    		}
    		return fps;
    	}
    }
    Richard

  10. #10

    Default

    Thanks I tested this over the weekend and it works great. Thank you again!


    Quote Originally Posted by rrlanham View Post
    Take a look at this example (from soon to be published article:

    package test;
    
    import com.wowza.wms.amf.AMFDataList;
    import com.wowza.wms.amf.AMFPacket;
    import com.wowza.wms.application.IApplicationInstance;
    import com.wowza.wms.client.IClient;
    import com.wowza.wms.module.ModuleBase;
    import com.wowza.wms.request.RequestFunction;
    import com.wowza.wms.stream.IMediaStream;
    import com.wowza.wms.stream.IMediaStreamLivePacketNotify;
    
    public class ModuleLiveFrameRate extends ModuleBase
    {
    	class PacketListener implements IMediaStreamLivePacketNotify
    	{
    		/**
    		* onLivePacket is called for every packet that is received for the live stream before the packet is processed for playback.
    		* It is very important that this method returns quickly and is not delayed in any way.
    		*/
    		@Override
    		public void onLivePacket(IMediaStream stream, AMFPacket packet)
    		{
    			if (packet.isVideo())
    			{
    				// packet.getTimecode(); returns the elapsed time, in milliseconds, between this packet and the last packet of the same type.
    				double fps = (double)1000 / packet.getTimecode();
    				stream.getProperties().setProperty("currentFPS", new Double(fps));
    				getLogger().info("FPS: " + fps); // this makes a lot of logging.
    			}
    		}
    
    	}
    
    	private PacketListener packetListener = new PacketListener();
    	private IApplicationInstance appInstance;
    
    	public void onAppStart(IApplicationInstance appInstance)
    	{
    		this.appInstance = appInstance;
    	}
    
    	public void onStreamCreate(IMediaStream stream)
    	{
    		stream.addLivePacketListener(packetListener);
    	}
    
    	public void onStreamDestroy(IMediaStream stream)
    	{
    		stream.removeLivePacketListener(packetListener);
    	}
    
    	public void getCurrentFPS(IClient client, RequestFunction function, AMFDataList params)
    	{
    		double fps = 0;
    		String streamName = getParamString(params, PARAM1);
    		if (streamName != null)
    		{
    			fps = getCurrentFPS(streamName);
    		}
    
    		sendResult(client, params, fps);
    	}
    
    	public double getCurrentFPS(String streamName)
    	{
    		double fps = 0;
    		IMediaStream stream = appInstance.getStreams().getStream(streamName);
    		if (stream != null)
    		{
    			fps = stream.getProperties().getPropertyDouble("currentFPS", fps);
    		}
    		return fps;
    	}
    }
    Richard

Page 1 of 2 12 LastLast

Similar Threads

  1. Framerate
    By esso74 in forum GoCoder iOS app
    Replies: 1
    Last Post: 08-01-2013, 06:30 AM
  2. Unstable framerate
    By sebastiancocis in forum Live Streaming and Encoder Discussion
    Replies: 3
    Last Post: 05-25-2012, 09:09 AM
  3. Please, Help me with bitrate and framerate!!!
    By tunglq87 in forum AddOn: Transcoder
    Replies: 8
    Last Post: 10-31-2011, 10:29 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •