diff --git a/openvidu-server/src/main/java/io/openvidu/server/cdr/CDREventWebrtcConnection.java b/openvidu-server/src/main/java/io/openvidu/server/cdr/CDREventWebrtcConnection.java index ff58122b..20fafc61 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/cdr/CDREventWebrtcConnection.java +++ b/openvidu-server/src/main/java/io/openvidu/server/cdr/CDREventWebrtcConnection.java @@ -12,8 +12,8 @@ public class CDREventWebrtcConnection extends CDREventEnd implements Comparable< // webrtcConnectionCreated public CDREventWebrtcConnection(String sessionId, String participantId, MediaOptions mediaOptions, - String receivingFrom) { - super(CDREventName.webrtcConnectionCreated, sessionId, System.currentTimeMillis()); + String receivingFrom, Long timestamp) { + super(CDREventName.webrtcConnectionCreated, sessionId, timestamp); this.participantId = participantId; this.mediaOptions = mediaOptions; this.receivingFrom = receivingFrom; diff --git a/openvidu-server/src/main/java/io/openvidu/server/cdr/CallDetailRecord.java b/openvidu-server/src/main/java/io/openvidu/server/cdr/CallDetailRecord.java index 0357d3c1..b60d15dd 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/cdr/CallDetailRecord.java +++ b/openvidu-server/src/main/java/io/openvidu/server/cdr/CallDetailRecord.java @@ -124,9 +124,9 @@ public class CallDetailRecord { this.logger.log(new CDREventParticipant(e, reason)); } - public void recordNewPublisher(Participant participant, String sessionId, MediaOptions mediaOptions) { + public void recordNewPublisher(Participant participant, String sessionId, MediaOptions mediaOptions, Long timestamp) { CDREventWebrtcConnection publisher = new CDREventWebrtcConnection(sessionId, - participant.getParticipantPublicId(), mediaOptions, null); + participant.getParticipantPublicId(), mediaOptions, null, timestamp); this.publications.put(participant.getParticipantPublicId(), publisher); if (openviduConfig.isCdrEnabled()) this.logger.log(publisher); @@ -143,10 +143,10 @@ public class CallDetailRecord { return false; } - public void recordNewSubscriber(Participant participant, String sessionId, String senderPublicId) { + public void recordNewSubscriber(Participant participant, String sessionId, String senderPublicId, Long timestamp) { CDREventWebrtcConnection publisher = this.publications.get(senderPublicId); CDREventWebrtcConnection subscriber = new CDREventWebrtcConnection(sessionId, - participant.getParticipantPublicId(), publisher.mediaOptions, senderPublicId); + participant.getParticipantPublicId(), publisher.mediaOptions, senderPublicId, timestamp); this.subscriptions.putIfAbsent(participant.getParticipantPublicId(), new ConcurrentSkipListSet<>()); this.subscriptions.get(participant.getParticipantPublicId()).add(subscriber); if (openviduConfig.isCdrEnabled()) diff --git a/openvidu-server/src/main/java/io/openvidu/server/config/OpenviduConfig.java b/openvidu-server/src/main/java/io/openvidu/server/config/OpenviduConfig.java index d4ed154c..04d049ae 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/config/OpenviduConfig.java +++ b/openvidu-server/src/main/java/io/openvidu/server/config/OpenviduConfig.java @@ -175,6 +175,10 @@ public class OpenviduConfig { public boolean isKmsStatsEnabled() { return this.kmsStatsEnabled; } + + public String getOpenViduRecordingNotification() { + return this.openviduRecordingNotification; + } public ParticipantRole[] getRolesFromRecordingNotification() { ParticipantRole[] roles; diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java b/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java index cad6d39b..65c8e817 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java @@ -36,10 +36,14 @@ public class Participant { private final String METADATA_SEPARATOR = "%/%"; public Participant(String participantPrivatetId, String participantPublicId, Token token, String clientMetadata, - String location, String platform) { + String location, String platform, Long createdAt) { this.participantPrivatetId = participantPrivatetId; this.participantPublicId = participantPublicId; - this.createdAt = System.currentTimeMillis(); + if (createdAt != null) { + this.createdAt = createdAt; + } else { + this.createdAt = System.currentTimeMillis(); + } this.token = token; this.clientMetadata = clientMetadata; if (!token.getServerMetadata().isEmpty()) diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java b/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java index 7323084c..11bb7e24 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java @@ -339,7 +339,7 @@ public abstract class SessionManager { if (this.sessionidParticipantpublicidParticipant.get(sessionId) != null) { String participantPublicId = this.generateRandomChain(); Participant p = new Participant(participantPrivatetId, participantPublicId, token, clientMetadata, location, - platform); + platform, null); while (this.sessionidParticipantpublicidParticipant.get(sessionId).putIfAbsent(participantPublicId, p) != null) { participantPublicId = this.generateRandomChain(); @@ -355,7 +355,7 @@ public abstract class SessionManager { String clientMetadata) { if (this.sessionidParticipantpublicidParticipant.get(sessionId) != null) { Participant p = new Participant(participantPrivatetId, ProtocolElements.RECORDER_PARTICIPANT_PUBLICID, - token, clientMetadata, null, null); + token, clientMetadata, null, null, null); this.sessionidParticipantpublicidParticipant.get(sessionId) .put(ProtocolElements.RECORDER_PARTICIPANT_PUBLICID, p); return p; diff --git a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoParticipant.java b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoParticipant.java index 3cd75b0c..90a8b343 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoParticipant.java +++ b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoParticipant.java @@ -80,7 +80,8 @@ public class KurentoParticipant extends Participant { public KurentoParticipant(Participant participant, KurentoSession kurentoSession, MediaPipeline pipeline, InfoHandler infoHandler, CallDetailRecord CDR, OpenviduConfig openviduConfig) { super(participant.getParticipantPrivateId(), participant.getParticipantPublicId(), participant.getToken(), - participant.getClientMetadata(), participant.getLocation(), participant.getPlatform()); + participant.getClientMetadata(), participant.getLocation(), participant.getPlatform(), + participant.getCreatedAt()); this.openviduConfig = openviduConfig; this.session = kurentoSession; this.pipeline = pipeline; @@ -113,8 +114,6 @@ public class KurentoParticipant extends Participant { // Remove streamId from publisher's map this.session.publishedStreamIds.putIfAbsent(this.getPublisherStreamId(), this.getParticipantPrivateId()); - CDR.recordNewPublisher(this, this.session.getSessionId(), mediaOptions); - } public void shapePublisherMedia(GenericMediaElement element, MediaType type) { @@ -233,6 +232,9 @@ public class KurentoParticipant extends Participant { log.info("PARTICIPANT {}: Is now publishing video in room {}", this.getParticipantPublicId(), this.session.getSessionId()); + CDR.recordNewPublisher(this, this.session.getSessionId(), this.publisher.getMediaOptions(), + this.publisher.createdAt()); + return sdpResponse; } @@ -313,7 +315,8 @@ public class KurentoParticipant extends Participant { senderName, this.session.getSessionId()); if (!ProtocolElements.RECORDER_PARTICIPANT_PUBLICID.equals(this.getParticipantPublicId())) { - CDR.recordNewSubscriber(this, this.session.getSessionId(), sender.getParticipantPublicId()); + CDR.recordNewSubscriber(this, this.session.getSessionId(), sender.getParticipantPublicId(), + subscriber.createdAt()); } return sdpAnswer; @@ -601,14 +604,17 @@ public class KurentoParticipant extends Participant { + event.getState() + " | SOURCE: " + event.getSource().getName() + " | PAD: " + event.getPadName() + " | MEDIATYPE: " + event.getMediaType() + " | TIMESTAMP: " + System.currentTimeMillis(); - endpoint.flowInMedia.put(event.getSource().getName(), event.getMediaType()); - if (endpoint.getPublisher().getMediaOptions().hasAudio() - && endpoint.getPublisher().getMediaOptions().hasVideo() - && endpoint.flowInMedia.values().size() == 2) { - endpoint.kmsEvents.add(new KmsEvent(event)); - } else if (endpoint.flowInMedia.values().size() == 1) { - endpoint.kmsEvents.add(new KmsEvent(event)); - } + /* + * endpoint.flowInMedia.put(event.getSource().getName(), event.getMediaType()); + * if (endpoint.getPublisher().getMediaOptions().hasAudio() && + * endpoint.getPublisher().getMediaOptions().hasVideo() && + * endpoint.flowInMedia.values().size() == 2) { + */ + endpoint.kmsEvents.add(new KmsEvent(event, endpoint.createdAt())); + /* + * } else if (endpoint.flowInMedia.values().size() == 1) { + * endpoint.kmsEvents.add(new KmsEvent(event, endpoint.createdAt())); } + */ log.info(msg1); this.infoHandler.sendInfo(msg1); @@ -619,37 +625,48 @@ public class KurentoParticipant extends Participant { + event.getState() + " | SOURCE: " + event.getSource().getName() + " | PAD: " + event.getPadName() + " | MEDIATYPE: " + event.getMediaType() + " | TIMESTAMP: " + System.currentTimeMillis(); - endpoint.flowOutMedia.put(event.getSource().getName(), event.getMediaType()); - if (endpoint.getPublisher().getMediaOptions().hasAudio() - && endpoint.getPublisher().getMediaOptions().hasVideo() - && endpoint.flowOutMedia.values().size() == 2) { - endpoint.kmsEvents.add(new KmsEvent(event)); - } else if (endpoint.flowOutMedia.values().size() == 1) { - endpoint.kmsEvents.add(new KmsEvent(event)); - } + /* + * endpoint.flowOutMedia.put(event.getSource().getName(), event.getMediaType()); + * if (endpoint.getPublisher().getMediaOptions().hasAudio() && + * endpoint.getPublisher().getMediaOptions().hasVideo() && + * endpoint.flowOutMedia.values().size() == 2) { + */ + endpoint.kmsEvents.add(new KmsEvent(event, endpoint.createdAt())); + /* + * } else if (endpoint.flowOutMedia.values().size() == 1) { + * endpoint.kmsEvents.add(new KmsEvent(event)); } + */ log.info(msg1); this.infoHandler.sendInfo(msg1); }); endpoint.getWebEndpoint().addIceGatheringDoneListener(event -> { - endpoint.kmsEvents.add(new KmsEvent(event)); + endpoint.kmsEvents.add(new KmsEvent(event, endpoint.createdAt())); }); endpoint.getWebEndpoint().addConnectionStateChangedListener(event -> { - endpoint.kmsEvents.add(new KmsEvent(event)); + endpoint.kmsEvents.add(new KmsEvent(event, endpoint.createdAt())); }); endpoint.getWebEndpoint().addNewCandidatePairSelectedListener(event -> { endpoint.selectedLocalIceCandidate = event.getCandidatePair().getLocalCandidate(); endpoint.selectedRemoteIceCandidate = event.getCandidatePair().getRemoteCandidate(); - endpoint.kmsEvents.add(new KmsEvent(event)); + endpoint.kmsEvents.add(new KmsEvent(event, endpoint.createdAt())); String msg = "ICE CANDIDATE SELECTED (" + endpoint.getEndpoint().getTag("name") + "): LOCAL CANDIDATE: " + endpoint.selectedLocalIceCandidate + " | REMOTE CANDIDATE: " + endpoint.selectedRemoteIceCandidate + " | TIMESTAMP: " + System.currentTimeMillis(); log.warn(msg); this.infoHandler.sendInfo(msg); }); + + endpoint.getEndpoint().addMediaTranscodingStateChangeListener(event -> { + endpoint.kmsEvents.add(new KmsEvent(event, endpoint.createdAt())); + }); + + endpoint.getWebEndpoint().addIceComponentStateChangeListener(event -> { + endpoint.kmsEvents.add(new KmsEvent(event, endpoint.createdAt())); + }); } public MediaPipeline getPipeline() { diff --git a/openvidu-server/src/main/java/io/openvidu/server/kurento/endpoint/KmsEvent.java b/openvidu-server/src/main/java/io/openvidu/server/kurento/endpoint/KmsEvent.java index c1d12e1b..b59cd955 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/kurento/endpoint/KmsEvent.java +++ b/openvidu-server/src/main/java/io/openvidu/server/kurento/endpoint/KmsEvent.java @@ -5,10 +5,15 @@ import org.kurento.client.MediaEvent; public class KmsEvent { long timestamp; + long msSinceCreation; + String endpoint; MediaEvent event; - public KmsEvent(MediaEvent event) { + public KmsEvent(MediaEvent event, long createdAt) { this.event = event; + this.endpoint = event.getSource().getTag("name"); + this.event.setSource(null); this.timestamp = System.currentTimeMillis(); + this.msSinceCreation = this.timestamp - createdAt; } } \ No newline at end of file diff --git a/openvidu-server/src/main/java/io/openvidu/server/kurento/endpoint/MediaEndpoint.java b/openvidu-server/src/main/java/io/openvidu/server/kurento/endpoint/MediaEndpoint.java index 9854f624..abb7183d 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/kurento/endpoint/MediaEndpoint.java +++ b/openvidu-server/src/main/java/io/openvidu/server/kurento/endpoint/MediaEndpoint.java @@ -31,12 +31,14 @@ import org.kurento.client.EventListener; import org.kurento.client.IceCandidate; import org.kurento.client.ListenerSubscription; import org.kurento.client.MediaElement; +import org.kurento.client.MediaEvent; import org.kurento.client.MediaPipeline; import org.kurento.client.MediaType; import org.kurento.client.OnIceCandidateEvent; import org.kurento.client.RtpEndpoint; import org.kurento.client.SdpEndpoint; import org.kurento.client.WebRtcEndpoint; +import org.kurento.jsonrpc.JsonUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -76,6 +78,7 @@ public abstract class MediaEndpoint { private KurentoParticipant owner; private String endpointName; + protected Long createdAt; // Timestamp when this [publisher / subscriber] started [publishing / receiving] private MediaPipeline pipeline = null; private ListenerSubscription endpointSubscription = null; @@ -157,6 +160,10 @@ public abstract class MediaEndpoint { } } + public long createdAt() { + return this.createdAt; + } + public WebRtcEndpoint getWebEndpoint() { return webEndpoint; } @@ -492,6 +499,7 @@ public abstract class MediaEndpoint { public JsonObject withStatsToJson() { JsonObject json = new JsonObject(); + json.addProperty("createdAt", this.createdAt); json.addProperty("webrtcTagName", this.getEndpoint().getTag("name")); json.add("receivedCandidates", new GsonBuilder().create().toJsonTree(this.receivedCandidateList)); json.addProperty("localCandidate", this.selectedLocalIceCandidate); @@ -502,8 +510,13 @@ public abstract class MediaEndpoint { JsonArray jsonArray = new JsonArray(); for (KmsEvent event : this.kmsEvents) { - JsonObject jsonKmsEvent = new JsonObject(); - jsonKmsEvent.addProperty(event.event.getType(), event.timestamp); + JsonObject jsonKmsEvent = JsonUtils.toJsonObject(event.event); + // Set source name + jsonKmsEvent.addProperty("source", event.endpoint); + // Set custom more precise timestamp + jsonKmsEvent.addProperty("timestamp", event.timestamp); + // Set milliseconds since the Publisher or Subscriber started transmitting media + jsonKmsEvent.addProperty("msSinceCreation", event.msSinceCreation); jsonArray.add(jsonKmsEvent); } json.add("events", jsonArray); diff --git a/openvidu-server/src/main/java/io/openvidu/server/kurento/endpoint/PublisherEndpoint.java b/openvidu-server/src/main/java/io/openvidu/server/kurento/endpoint/PublisherEndpoint.java index fba20d74..ec1d935a 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/kurento/endpoint/PublisherEndpoint.java +++ b/openvidu-server/src/main/java/io/openvidu/server/kurento/endpoint/PublisherEndpoint.java @@ -201,6 +201,7 @@ public class PublisherEndpoint extends MediaEndpoint { throw new OpenViduException(Code.MEDIA_SDP_ERROR_CODE, "Sdp type not supported: " + sdpType); } gatherCandidates(); + this.createdAt = System.currentTimeMillis(); return sdpResponse; } @@ -580,7 +581,7 @@ public class PublisherEndpoint extends MediaEndpoint { } public String filterCollectionsToString() { - return "{filter: " + ((this.filter != null) ? this.filter.getName() : "null") + ", listener: " + this.filterListeners.toString() - + ", subscribers: " + this.subscribersToFilterEvents.toString() + "}"; + return "{filter: " + ((this.filter != null) ? this.filter.getName() : "null") + ", listener: " + + this.filterListeners.toString() + ", subscribers: " + this.subscribersToFilterEvents.toString() + "}"; } } diff --git a/openvidu-server/src/main/java/io/openvidu/server/kurento/endpoint/SubscriberEndpoint.java b/openvidu-server/src/main/java/io/openvidu/server/kurento/endpoint/SubscriberEndpoint.java index 49b3201e..e4610ad2 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/kurento/endpoint/SubscriberEndpoint.java +++ b/openvidu-server/src/main/java/io/openvidu/server/kurento/endpoint/SubscriberEndpoint.java @@ -53,6 +53,7 @@ public class SubscriberEndpoint extends MediaEndpoint { publisher.connect(this.getEndpoint()); setConnectedToPublisher(true); setPublisher(publisher); + this.createdAt = System.currentTimeMillis(); return sdpAnswer; } diff --git a/openvidu-server/src/main/java/io/openvidu/server/rest/ConfigRestController.java b/openvidu-server/src/main/java/io/openvidu/server/rest/ConfigRestController.java index ec529a2d..1316302f 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/rest/ConfigRestController.java +++ b/openvidu-server/src/main/java/io/openvidu/server/rest/ConfigRestController.java @@ -35,7 +35,7 @@ import io.openvidu.server.config.OpenviduConfig; public class ConfigRestController { @Autowired - OpenviduConfig openviduConfig; + protected OpenviduConfig openviduConfig; @RequestMapping(value = "/openvidu-publicurl", method = RequestMethod.GET) public String getOpenViduPublicUrl() {