org.kurento.demo.Pipeline Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of kurento-crowddetector Show documentation
Show all versions of kurento-crowddetector Show documentation
A Crowd Detector Filter using RTSP conexion to the camera.
The video will be recorded.
/*
* (C) Copyright 2014 Kurento (http://kurento.org/)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.kurento.demo;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentHashMap;
import javax.annotation.PostConstruct;
import org.kurento.client.EndOfStreamEvent;
import org.kurento.client.ErrorEvent;
import org.kurento.client.EventListener;
import org.kurento.client.IceCandidate;
import org.kurento.client.KurentoClient;
import org.kurento.client.MediaPipeline;
import org.kurento.client.PlayerEndpoint;
import org.kurento.client.WebRtcEndpoint;
import org.kurento.module.crowddetector.CrowdDetectorDirectionEvent;
import org.kurento.module.crowddetector.CrowdDetectorFilter;
import org.kurento.module.crowddetector.CrowdDetectorFluidityEvent;
import org.kurento.module.crowddetector.CrowdDetectorOccupancyEvent;
import org.kurento.module.crowddetector.RegionOfInterest;
import org.kurento.module.crowddetector.RegionOfInterestConfig;
import org.kurento.module.crowddetector.RelativePoint;
import org.kurento.orion.OrionConnectorException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
public class Pipeline {
private static final Logger log = LoggerFactory.getLogger(Pipeline.class);
private static final long RECONNECTION_TIME = 30 * 1000;
@Autowired
private ConfigurationReader configuration;
@Autowired
private KurentoClient kurento;
@Autowired
private CrowdDetectorOrionPublisher orionPublisher;
private MediaPipeline pipe;
private PlayerEndpoint playerEndpoint;
private CrowdDetectorFilter crowdDetectorFilter;
private String feedUrl;
private List rois;
private final Map webRtcEndpoints = new ConcurrentHashMap<>();
private boolean playing;
private Timer timer;
@PostConstruct
public void init() {
this.pipe = this.kurento.createMediaPipeline();
this.rois = new ArrayList<>();
JsonArray loadedRois;
JsonObject config = this.configuration.getConfig();
if (config != null) {
JsonElement feedUrlJson = config.get("feedUrl");
if (feedUrlJson != null) {
this.feedUrl = feedUrlJson.getAsString();
} else {
log.debug("Url feed not defined.");
}
JsonElement loadedRoisJson = config.get("rois");
if (loadedRoisJson != null) {
loadedRois = loadedRoisJson.getAsJsonArray();
this.rois = readRoisFromJson(loadedRois);
} else {
this.rois = getDummyRois();
log.debug("Rois not defined. Using dummy rois");
}
}
if (this.feedUrl == null) {
// PlayerEndpoint will be configured later.
return;
}
try {
this.orionPublisher.registerRoisInOrion(this.rois);
} catch (OrionConnectorException e) {
log.warn("Could not register ROIs in ORION");
}
this.crowdDetectorFilter = new CrowdDetectorFilter.Builder(this.pipe, this.rois).build();
this.crowdDetectorFilter.setProcessingWidth(640);
addOrionListeners();
this.playerEndpoint = new PlayerEndpoint.Builder(this.pipe, this.feedUrl).build();
addPlayerListeners();
this.playing = true;
this.playerEndpoint.connect(this.crowdDetectorFilter);
this.playerEndpoint.play();
}
private void addPlayerListeners() {
this.playerEndpoint.addEndOfStreamListener(new EventListener() {
@Override
public void onEvent(EndOfStreamEvent event) {
log.warn("Received EOS from Player");
if (Pipeline.this.timer != null) {
try {
Pipeline.this.timer.cancel();
} catch (Exception e) {
log.debug("Empty timer");
}
}
setFeedUrl(Pipeline.this.feedUrl);
}
});
this.playerEndpoint.addErrorListener(new EventListener() {
@Override
public void onEvent(ErrorEvent event) {
synchronized (this) {
log.error("Error received from Media server: {} (code {}, type {})",
event.getDescription(), event.getErrorCode(), event.getType());
if (Pipeline.this.playing) {
Pipeline.this.playing = false;
log.error("Timer added to create the player again");
Pipeline.this.timer = new Timer();
TimerTask task = new TimerTask() {
@Override
public void run() {
setFeedUrl(Pipeline.this.feedUrl);
}
};
Pipeline.this.timer.schedule(task, RECONNECTION_TIME);
}
}
}
});
}
private static List readRoisFromJson(JsonArray loadedRois) {
List rois = new ArrayList<>();
for (int j = 0; j < loadedRois.size(); j++) {
JsonObject roi = (JsonObject) loadedRois.get(j);
JsonArray coordinates = (JsonArray) roi.get("points");
// create structure to configure crowddetector
List points = new ArrayList<>(coordinates.size());
for (int i = 0; i < coordinates.size(); i++) {
JsonObject coordinate = coordinates.get(i).getAsJsonObject();
float x = coordinate.getAsJsonPrimitive("x").getAsFloat();
float y = coordinate.getAsJsonPrimitive("y").getAsFloat();
if (x > 1) {
x = 1;
}
if (y > 1) {
y = 1;
}
points.add(new RelativePoint(x, y));
}
RegionOfInterestConfig config = new RegionOfInterestConfig();
config.setFluidityLevelMin(roi.getAsJsonPrimitive("fluidityLevelMin").getAsInt());
config.setFluidityLevelMed(roi.getAsJsonPrimitive("fluidityLevelMed").getAsInt());
config.setFluidityLevelMax(roi.getAsJsonPrimitive("fluidityLevelMax").getAsInt());
config.setFluidityNumFramesToEvent(
roi.getAsJsonPrimitive("fluidityNumFramesToEvent").getAsInt());
config.setOccupancyLevelMin(roi.getAsJsonPrimitive("occupancyLevelMin").getAsInt());
config.setOccupancyLevelMed(roi.getAsJsonPrimitive("occupancyLevelMed").getAsInt());
config.setOccupancyLevelMax(roi.getAsJsonPrimitive("occupancyLevelMax").getAsInt());
config.setOccupancyNumFramesToEvent(
roi.getAsJsonPrimitive("occupancyNumFramesToEvent").getAsInt());
config.setSendOpticalFlowEvent(roi.getAsJsonPrimitive("sendOpticalFlowEvent").getAsBoolean());
config.setOpticalFlowNumFramesToEvent(
roi.getAsJsonPrimitive("opticalFlowNumFramesToEvent").getAsInt());
config.setOpticalFlowNumFramesToReset(
roi.getAsJsonPrimitive("opticalFlowNumFramesToReset").getAsInt());
config.setOpticalFlowAngleOffset(roi.getAsJsonPrimitive("opticalFlowAngleOffset").getAsInt());
rois.add(new RegionOfInterest(points, config, roi.getAsJsonPrimitive("id").getAsString()));
}
return rois;
}
private static List getDummyRois() {
List points = new ArrayList<>();
float x = 0;
float y = 0;
points.add(new RelativePoint(x, y));
x = 1;
y = 0;
points.add(new RelativePoint(x, y));
x = 1;
y = 1;
points.add(new RelativePoint(x, y));
x = 0;
y = 1;
points.add(new RelativePoint(x, y));
RegionOfInterestConfig config = new RegionOfInterestConfig();
config.setFluidityLevelMin(10);
config.setFluidityLevelMed(35);
config.setFluidityLevelMax(65);
config.setFluidityNumFramesToEvent(5);
config.setOccupancyLevelMin(10);
config.setOccupancyLevelMed(35);
config.setOccupancyLevelMax(65);
config.setOccupancyNumFramesToEvent(5);
config.setSendOpticalFlowEvent(false);
config.setOpticalFlowNumFramesToEvent(3);
config.setOpticalFlowNumFramesToReset(3);
config.setOpticalFlowAngleOffset(0);
List rois = new ArrayList<>();
rois.add(new RegionOfInterest(points, config, "dummyRoy"));
return rois;
}
public void addOrionListeners() {
this.crowdDetectorFilter
.addCrowdDetectorDirectionListener(new EventListener() {
@Override
public void onEvent(CrowdDetectorDirectionEvent event) {
try {
Pipeline.this.orionPublisher.publishEvent(event);
} catch (OrionConnectorException e) {
log.warn("Could not publish event in ORION");
}
log.debug("Direction event detected in roi {} direction {}", event.getRoiID(),
event.getDirectionAngle());
}
});
this.crowdDetectorFilter
.addCrowdDetectorFluidityListener(new EventListener() {
@Override
public void onEvent(CrowdDetectorFluidityEvent event) {
try {
Pipeline.this.orionPublisher.publishEvent(event);
} catch (OrionConnectorException e) {
log.warn("Could not publish event in ORION");
}
log.debug("Fluidity event detected in roi {} percentage {} level {}", event.getRoiID(),
event.getFluidityPercentage(), event.getFluidityLevel());
}
});
this.crowdDetectorFilter
.addCrowdDetectorOccupancyListener(new EventListener() {
@Override
public void onEvent(CrowdDetectorOccupancyEvent event) {
try {
Pipeline.this.orionPublisher.publishEvent(event);
} catch (OrionConnectorException e) {
log.warn("Could not publish event in ORION");
}
log.debug("Occupancy event detected in roi {} percentage {} level {}", event.getRoiID(),
event.getOccupancyPercentage(), event.getOccupancyLevel());
}
});
}
public CrowdDetectorFilter getCrowdDetectorFilter() {
return this.crowdDetectorFilter;
}
public PlayerEndpoint getPlayerEndpoint() {
return this.playerEndpoint;
}
public String getFeedUrl() {
return this.feedUrl;
}
public void setFeedUrl(String feedUrl) {
this.feedUrl = feedUrl;
if (this.playerEndpoint != null) {
log.debug("Releasing previous elements");
this.crowdDetectorFilter.release();
this.playerEndpoint.release();
}
log.debug("Creating new elements");
this.crowdDetectorFilter = new CrowdDetectorFilter.Builder(this.pipe, this.rois).build();
this.crowdDetectorFilter.setProcessingWidth(640);
addOrionListeners();
this.playerEndpoint = new PlayerEndpoint.Builder(this.pipe, this.feedUrl).build();
addPlayerListeners();
this.playing = true;
this.playerEndpoint.connect(this.crowdDetectorFilter);
this.playerEndpoint.play();
log.debug("New player is now runing");
log.debug("Connecting " + this.webRtcEndpoints.size() + " webrtcendpoints");
// change the feed for all the webrtc clients connected.
for (Entry ep : this.webRtcEndpoints.entrySet()) {
this.crowdDetectorFilter.connect(ep.getValue());
}
}
public MediaPipeline getPipeline() {
return this.pipe;
}
public List getRois() {
return this.rois;
}
public void setWebRtcEndpoint(String session, WebRtcEndpoint webRtcEndpoint) {
this.webRtcEndpoints.put(session, webRtcEndpoint);
}
public void removeWebRtcEndpoint(String session) {
if (this.webRtcEndpoints.containsKey(session)) {
this.webRtcEndpoints.get(session).release();
this.webRtcEndpoints.remove(session);
log.debug("client removed");
}
}
public boolean isPlaying() {
return this.playing;
}
public void addCandidate(IceCandidate candidate, String session) {
WebRtcEndpoint endpoint = this.webRtcEndpoints.get(session);
if (endpoint != null) {
endpoint.addIceCandidate(candidate);
}
}
}