All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.antmedia.statistic.HlsViewerStats Maven / Gradle / Ivy

Go to download

Ant Media Server supports RTMP, RTSP, MP4, HLS, WebRTC, Adaptive Streaming, etc.

There is a newer version: 2.10.0
Show newest version
package io.antmedia.statistic;

import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;

import org.red5.server.api.scheduling.ISchedulingService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import io.antmedia.datastore.db.DataStoreFactory;
import io.antmedia.datastore.db.IDataStoreFactory;
import io.antmedia.AppSettings;
import io.antmedia.datastore.db.DataStore;

public class HlsViewerStats implements IStreamStats, ApplicationContextAware{

	protected static Logger logger = LoggerFactory.getLogger(HlsViewerStats.class);
	
	public static final String BEAN_NAME = "hls.viewerstats";

	private DataStore dataStore;
	
	
	private DataStoreFactory dataStoreFactory;

	public static final int DEFAULT_TIME_PERIOD_FOR_VIEWER_COUNT = 10000;
	/**
	 * Time period in milliseconds to check if viewer is dropped
	 */
	private int timePeriodMS = DEFAULT_TIME_PERIOD_FOR_VIEWER_COUNT;

	Map> streamsViewerMap = new ConcurrentHashMap<>();

	/**
	 * Time out value in milliseconds, it is regarded as user is not watching stream 
	 * if last request time is older than timeout value
	 */
	private int timeoutMS = 20000;

	@Override
	public void registerNewViewer(String streamId, String sessionId) 
	{
		Map viewerMap = streamsViewerMap.get(streamId);
		if (viewerMap == null) {
			viewerMap = new ConcurrentHashMap<>();
		}
		if (!viewerMap.containsKey(sessionId)) {
			//if sessionId is not in the map, this is the first time for getting stream,
			//increment viewer count
			getDataStore().updateHLSViewerCount(streamId, 1);
		}
		viewerMap.put(sessionId, System.currentTimeMillis());

		streamsViewerMap.put(streamId, viewerMap);
	}

	@Override
	public int getViewerCount(String streamId) {
		Map viewerMap = streamsViewerMap.get(streamId);
		int viewerCount = 0;
		if (viewerMap != null) 
		{
			viewerCount = viewerMap.size();
		}
		return viewerCount;
	}
	
	public int getTotalViewerCount() {
		int viewerCount = 0;
		for (Map map : streamsViewerMap.values()) {
			viewerCount += map.size();
		}
		return viewerCount;
	}

	@Override
	public void setApplicationContext(ApplicationContext applicationContext)  {
		dataStoreFactory = (DataStoreFactory) applicationContext.getBean(IDataStoreFactory.BEAN_NAME);

		
		ISchedulingService scheduler = (ISchedulingService) applicationContext.getBean(ISchedulingService.BEAN_NAME);
		
		if (applicationContext.containsBean(AppSettings.BEAN_NAME)) {
			AppSettings settings = (AppSettings)applicationContext.getBean(AppSettings.BEAN_NAME);
			timeoutMS = getTimeoutMSFromSettings(settings, timeoutMS);
		}

		scheduler.addScheduledJobAfterDelay(timePeriodMS, 
				(ISchedulingService service) -> {
					
					Iterator>> streamIterator = streamsViewerMap.entrySet().iterator();
					Iterator> viewerIterator;
					Entry> streamViewerEntry;
					Map viewerMapEnty;
					
					long now = System.currentTimeMillis();
					while (streamIterator.hasNext()) 
					{
						streamViewerEntry = streamIterator.next();
						viewerMapEnty = streamViewerEntry.getValue();
						viewerIterator = viewerMapEnty.entrySet().iterator();
						int numberOfDecrement = 0;
						while (viewerIterator.hasNext()) 
						{
							Entry viewer = viewerIterator.next();
							if (viewer.getValue() < (now - getTimeoutMS())) 
							{
								// regard it as not a viewer
								viewerIterator.remove();
								numberOfDecrement++;
							}
						}
						
						numberOfDecrement = -1 * numberOfDecrement;
						
						getDataStore().updateHLSViewerCount(streamViewerEntry.getKey(), numberOfDecrement);
						
					}
					
				}, timePeriodMS);
	}

	public static int getTimeoutMSFromSettings(AppSettings settings, int defaultValue) {
		int newTimePeriodMS = defaultValue;
		String hlsTime = settings.getHlsTime();
		if (hlsTime != null && !hlsTime.isEmpty()) {
			try {
				newTimePeriodMS = Integer.valueOf(hlsTime) * 10 * 1000;
			}
			catch (Exception e) {
				logger.error(e.getMessage());
			}
		}
		return newTimePeriodMS;
	}

	public void setTimePeriodMS(int timePeriodMS) {
		this.timePeriodMS = timePeriodMS;
	}
	public int getTimePeriodMS() {
		return timePeriodMS;
	}

	public int getTimeoutMS() {
		return timeoutMS;
	}

	public DataStore getDataStore() {
		if (dataStore == null) {
			dataStore = getDataStoreFactory().getDataStore();
		}
		return dataStore;
	}
	
	public void setDataStore(DataStore dataStore) {
		this.dataStore = dataStore;
	}
	
	
	public DataStoreFactory getDataStoreFactory() {
		return dataStoreFactory;
	}
	
	public void setDataStoreFactory(DataStoreFactory dataStoreFactory) {
		this.dataStoreFactory = dataStoreFactory;
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy