From 4a99ea5fe85b29adfd0e816b32e5e3be5ed993e7 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Tue, 3 Jul 2018 15:43:37 +0200 Subject: [PATCH] openvidu-server: StreamPropertyChangedEvent --- .../client/internal/ProtocolElements.java | 187 ++++++++++-------- .../java/io/openvidu/server/cdr/CDREvent.java | 10 +- .../io/openvidu/server/core/MediaOptions.java | 68 ++++++- .../server/core/SessionEventsHandler.java | 41 +++- .../openvidu/server/core/SessionManager.java | 27 ++- .../kurento/core/KurentoMediaOptions.java | 7 +- .../kurento/core/KurentoParticipant.java | 32 ++- .../kurento/core/KurentoSessionManager.java | 77 +++++++- .../io/openvidu/server/rpc/RpcHandler.java | 25 +++ 9 files changed, 347 insertions(+), 127 deletions(-) diff --git a/openvidu-client/src/main/java/io/openvidu/client/internal/ProtocolElements.java b/openvidu-client/src/main/java/io/openvidu/client/internal/ProtocolElements.java index 2f819127..7a218a48 100644 --- a/openvidu-client/src/main/java/io/openvidu/client/internal/ProtocolElements.java +++ b/openvidu-client/src/main/java/io/openvidu/client/internal/ProtocolElements.java @@ -17,113 +17,130 @@ package io.openvidu.client.internal; /** - * This class defines constant values of client-server messages and their parameters. + * This class defines constant values of client-server messages and their + * parameters. * * @author Radu Tom Vlad */ public class ProtocolElements { - // ---------------------------- CLIENT REQUESTS ----------------------- + // ---------------------------- CLIENT REQUESTS ----------------------- - public static final String SENDMESSAGE_ROOM_METHOD = "sendMessage"; - public static final String SENDMESSAGE_MESSAGE_PARAM = "message"; + public static final String SENDMESSAGE_ROOM_METHOD = "sendMessage"; + public static final String SENDMESSAGE_MESSAGE_PARAM = "message"; - public static final String LEAVEROOM_METHOD = "leaveRoom"; + public static final String LEAVEROOM_METHOD = "leaveRoom"; - public static final String JOINROOM_METHOD = "joinRoom"; - public static final String JOINROOM_USER_PARAM = "user"; - public static final String JOINROOM_TOKEN_PARAM = "token"; - public static final String JOINROOM_ROOM_PARAM = "session"; - public static final String JOINROOM_METADATA_PARAM = "metadata"; - public static final String JOINROOM_SECRET_PARAM = "secret"; - public static final String JOINROOM_RECORDER_PARAM = "recorder"; - - public static final String JOINROOM_PEERID_PARAM = "id"; - public static final String JOINROOM_PEERSTREAMS_PARAM = "streams"; - public static final String JOINROOM_PEERSTREAMID_PARAM = "id"; - public static final String JOINROOM_PEERSTREAMAUDIOACTIVE_PARAM = "audioActive"; - public static final String JOINROOM_PEERSTREAMVIDEOACTIVE_PARAM = "videoActive"; - public static final String JOINROOM_PEERSTREAMTYPEOFVIDEO_PARAM = "typeOfVideo"; - public static final String JOINROOM_PEERSTREAMFRAMERATE_PARAM = "frameRate"; + public static final String JOINROOM_METHOD = "joinRoom"; + public static final String JOINROOM_USER_PARAM = "user"; + public static final String JOINROOM_TOKEN_PARAM = "token"; + public static final String JOINROOM_ROOM_PARAM = "session"; + public static final String JOINROOM_METADATA_PARAM = "metadata"; + public static final String JOINROOM_SECRET_PARAM = "secret"; + public static final String JOINROOM_RECORDER_PARAM = "recorder"; - public static final String PUBLISHVIDEO_METHOD = "publishVideo"; - public static final String PUBLISHVIDEO_SDPOFFER_PARAM = "sdpOffer"; - public static final String PUBLISHVIDEO_DOLOOPBACK_PARAM = "doLoopback"; - public static final String PUBLISHVIDEO_SDPANSWER_PARAM = "sdpAnswer"; - public static final String PUBLISHVIDEO_STREAMID_PARAM = "id"; - public static final String PUBLISHVIDEO_AUDIOACTIVE_PARAM = "audioActive"; - public static final String PUBLISHVIDEO_VIDEOACTIVE_PARAM = "videoActive"; - public static final String PUBLISHVIDEO_TYPEOFVIDEO_PARAM = "typeOfVideo"; - public static final String PUBLISHVIDEO_FRAMERATE_PARAM = "frameRate"; + public static final String JOINROOM_PEERID_PARAM = "id"; + public static final String JOINROOM_PEERSTREAMS_PARAM = "streams"; + public static final String JOINROOM_PEERSTREAMID_PARAM = "id"; + public static final String JOINROOM_PEERSTREAMHASAUDIO_PARAM = "hasAudio"; + public static final String JOINROOM_PEERSTREAMHASVIDEO_PARAM = "hasVideo"; + public static final String JOINROOM_PEERSTREAMAUDIOACTIVE_PARAM = "audioActive"; + public static final String JOINROOM_PEERSTREAMVIDEOACTIVE_PARAM = "videoActive"; + public static final String JOINROOM_PEERSTREAMTYPEOFVIDEO_PARAM = "typeOfVideo"; + public static final String JOINROOM_PEERSTREAMFRAMERATE_PARAM = "frameRate"; + public static final String JOINROOM_PEERSTREAMVIDEODIMENSIONS_PARAM = "videoDimensions"; - public static final String UNPUBLISHVIDEO_METHOD = "unpublishVideo"; + public static final String PUBLISHVIDEO_METHOD = "publishVideo"; + public static final String PUBLISHVIDEO_SDPOFFER_PARAM = "sdpOffer"; + public static final String PUBLISHVIDEO_DOLOOPBACK_PARAM = "doLoopback"; + public static final String PUBLISHVIDEO_SDPANSWER_PARAM = "sdpAnswer"; + public static final String PUBLISHVIDEO_STREAMID_PARAM = "id"; + public static final String PUBLISHVIDEO_HASAUDIO_PARAM = "hasAudio"; + public static final String PUBLISHVIDEO_HASVIDEO_PARAM = "hasVideo"; + public static final String PUBLISHVIDEO_AUDIOACTIVE_PARAM = "audioActive"; + public static final String PUBLISHVIDEO_VIDEOACTIVE_PARAM = "videoActive"; + public static final String PUBLISHVIDEO_TYPEOFVIDEO_PARAM = "typeOfVideo"; + public static final String PUBLISHVIDEO_FRAMERATE_PARAM = "frameRate"; + public static final String PUBLISHVIDEO_VIDEODIMENSIONS_PARAM = "videoDimensions"; - public static final String RECEIVEVIDEO_METHOD = "receiveVideoFrom"; - public static final String RECEIVEVIDEO_SDPOFFER_PARAM = "sdpOffer"; - public static final String RECEIVEVIDEO_SENDER_PARAM = "sender"; - public static final String RECEIVEVIDEO_SDPANSWER_PARAM = "sdpAnswer"; + public static final String UNPUBLISHVIDEO_METHOD = "unpublishVideo"; - public static final String UNSUBSCRIBEFROMVIDEO_METHOD = "unsubscribeFromVideo"; - public static final String UNSUBSCRIBEFROMVIDEO_SENDER_PARAM = "sender"; + public static final String RECEIVEVIDEO_METHOD = "receiveVideoFrom"; + public static final String RECEIVEVIDEO_SDPOFFER_PARAM = "sdpOffer"; + public static final String RECEIVEVIDEO_SENDER_PARAM = "sender"; + public static final String RECEIVEVIDEO_SDPANSWER_PARAM = "sdpAnswer"; - public static final String ONICECANDIDATE_METHOD = "onIceCandidate"; - public static final String ONICECANDIDATE_EPNAME_PARAM = "endpointName"; - public static final String ONICECANDIDATE_CANDIDATE_PARAM = "candidate"; - public static final String ONICECANDIDATE_SDPMIDPARAM = "sdpMid"; - public static final String ONICECANDIDATE_SDPMLINEINDEX_PARAM = "sdpMLineIndex"; + public static final String UNSUBSCRIBEFROMVIDEO_METHOD = "unsubscribeFromVideo"; + public static final String UNSUBSCRIBEFROMVIDEO_SENDER_PARAM = "sender"; - public static final String CUSTOMREQUEST_METHOD = "customRequest"; + public static final String ONICECANDIDATE_METHOD = "onIceCandidate"; + public static final String ONICECANDIDATE_EPNAME_PARAM = "endpointName"; + public static final String ONICECANDIDATE_CANDIDATE_PARAM = "candidate"; + public static final String ONICECANDIDATE_SDPMIDPARAM = "sdpMid"; + public static final String ONICECANDIDATE_SDPMLINEINDEX_PARAM = "sdpMLineIndex"; - // ---------------------------- SERVER RESPONSES & EVENTS ----------------- + public static final String CUSTOMREQUEST_METHOD = "customRequest"; - public static final String PARTICIPANTJOINED_METHOD = "participantJoined"; - public static final String PARTICIPANTJOINED_USER_PARAM = "id"; - public static final String PARTICIPANTJOINED_METADATA_PARAM = "metadata"; + public static final String STREAMPROPERTYCHANGED_METHOD = "streamPropertyChanged"; + public static final String STREAMPROPERTYCHANGED_CONNECTIONID_PARAM = "connectionId"; + public static final String STREAMPROPERTYCHANGED_STREAMID_PARAM = "streamId"; + public static final String STREAMPROPERTYCHANGED_PROPERTY_PARAM = "property"; + public static final String STREAMPROPERTYCHANGED_NEWVALUE_PARAM = "newValue"; + public static final String STREAMPROPERTYCHANGED_REASON_PARAM = "reason"; - public static final String PARTICIPANTLEFT_METHOD = "participantLeft"; - public static final String PARTICIPANTLEFT_NAME_PARAM = "name"; - public static final String PARTICIPANTLEFT_REASON_PARAM = "reason"; + // ---------------------------- SERVER RESPONSES & EVENTS ----------------- - public static final String PARTICIPANTEVICTED_METHOD = "participantEvicted"; + public static final String PARTICIPANTJOINED_METHOD = "participantJoined"; + public static final String PARTICIPANTJOINED_USER_PARAM = "id"; + public static final String PARTICIPANTJOINED_METADATA_PARAM = "metadata"; - public static final String PARTICIPANTPUBLISHED_METHOD = "participantPublished"; - public static final String PARTICIPANTPUBLISHED_USER_PARAM = "id"; - public static final String PARTICIPANTPUBLISHED_STREAMS_PARAM = "streams"; - public static final String PARTICIPANTPUBLISHED_STREAMID_PARAM = "id"; - public static final String PARTICIPANTPUBLISHED_AUDIOACTIVE_PARAM = "audioActive"; - public static final String PARTICIPANTPUBLISHED_VIDEOACTIVE_PARAM = "videoActive"; - public static final String PARTICIPANTPUBLISHED_TYPEOFVIDEO_PARAM = "typeOfVideo"; - public static final String PARTICIPANTPUBLISHED_FRAMERATE_PARAM = "frameRate"; - - public static final String PARTICIPANTUNPUBLISHED_METHOD = "participantUnpublished"; - public static final String PARTICIPANTUNPUBLISHED_NAME_PARAM = "name"; - public static final String PARTICIPANTUNPUBLISHED_REASON_PARAM = "reason"; + public static final String PARTICIPANTLEFT_METHOD = "participantLeft"; + public static final String PARTICIPANTLEFT_NAME_PARAM = "name"; + public static final String PARTICIPANTLEFT_REASON_PARAM = "reason"; - public static final String PARTICIPANTSENDMESSAGE_METHOD = "sendMessage"; - public static final String PARTICIPANTSENDMESSAGE_DATA_PARAM = "data"; - public static final String PARTICIPANTSENDMESSAGE_FROM_PARAM = "from"; - public static final String PARTICIPANTSENDMESSAGE_TYPE_PARAM = "type"; + public static final String PARTICIPANTEVICTED_METHOD = "participantEvicted"; - public static final String ROOMCLOSED_METHOD = "roomClosed"; - public static final String ROOMCLOSED_ROOM_PARAM = "room"; + public static final String PARTICIPANTPUBLISHED_METHOD = "participantPublished"; + public static final String PARTICIPANTPUBLISHED_USER_PARAM = "id"; + public static final String PARTICIPANTPUBLISHED_STREAMS_PARAM = "streams"; + public static final String PARTICIPANTPUBLISHED_STREAMID_PARAM = "id"; + public static final String PARTICIPANTPUBLISHED_HASAUDIO_PARAM = "hasAudio"; + public static final String PARTICIPANTPUBLISHED_HASVIDEO_PARAM = "hasVideo"; + public static final String PARTICIPANTPUBLISHED_AUDIOACTIVE_PARAM = "audioActive"; + public static final String PARTICIPANTPUBLISHED_VIDEOACTIVE_PARAM = "videoActive"; + public static final String PARTICIPANTPUBLISHED_TYPEOFVIDEO_PARAM = "typeOfVideo"; + public static final String PARTICIPANTPUBLISHED_FRAMERATE_PARAM = "frameRate"; + public static final String PARTICIPANTPUBLISHED_VIDEODIMENSIONS_PARAM = "videoDimensions"; - public static final String MEDIAERROR_METHOD = "mediaError"; - public static final String MEDIAERROR_ERROR_PARAM = "error"; + public static final String PARTICIPANTUNPUBLISHED_METHOD = "participantUnpublished"; + public static final String PARTICIPANTUNPUBLISHED_NAME_PARAM = "name"; + public static final String PARTICIPANTUNPUBLISHED_REASON_PARAM = "reason"; - public static final String ICECANDIDATE_METHOD = "iceCandidate"; - public static final String ICECANDIDATE_EPNAME_PARAM = "endpointName"; - public static final String ICECANDIDATE_CANDIDATE_PARAM = "candidate"; - public static final String ICECANDIDATE_SDPMID_PARAM = "sdpMid"; - public static final String ICECANDIDATE_SDPMLINEINDEX_PARAM = "sdpMLineIndex"; - - public static final String RECORDINGSTARTED_METHOD = "recordingStarted"; - public static final String RECORDINGSTARTED_ID_PARAM = "id"; - public static final String RECORDINGSTARTED_NAME_PARAM = "name"; - - public static final String RECORDINGSTOPPED_METHOD = "recordingStopped"; - public static final String RECORDINGSTOPPED_ID_PARAM = "id"; + public static final String PARTICIPANTSENDMESSAGE_METHOD = "sendMessage"; + public static final String PARTICIPANTSENDMESSAGE_DATA_PARAM = "data"; + public static final String PARTICIPANTSENDMESSAGE_FROM_PARAM = "from"; + public static final String PARTICIPANTSENDMESSAGE_TYPE_PARAM = "type"; - public static final String CUSTOM_NOTIFICATION = "custonNotification"; - - public static final String RECORDER_PARTICIPANT_PUBLICID = "RECORDER"; + public static final String ROOMCLOSED_METHOD = "roomClosed"; + public static final String ROOMCLOSED_ROOM_PARAM = "room"; + + public static final String MEDIAERROR_METHOD = "mediaError"; + public static final String MEDIAERROR_ERROR_PARAM = "error"; + + public static final String ICECANDIDATE_METHOD = "iceCandidate"; + public static final String ICECANDIDATE_EPNAME_PARAM = "endpointName"; + public static final String ICECANDIDATE_CANDIDATE_PARAM = "candidate"; + public static final String ICECANDIDATE_SDPMID_PARAM = "sdpMid"; + public static final String ICECANDIDATE_SDPMLINEINDEX_PARAM = "sdpMLineIndex"; + + public static final String RECORDINGSTARTED_METHOD = "recordingStarted"; + public static final String RECORDINGSTARTED_ID_PARAM = "id"; + public static final String RECORDINGSTARTED_NAME_PARAM = "name"; + + public static final String RECORDINGSTOPPED_METHOD = "recordingStopped"; + public static final String RECORDINGSTOPPED_ID_PARAM = "id"; + + public static final String CUSTOM_NOTIFICATION = "custonNotification"; + + public static final String RECORDER_PARTICIPANT_PUBLICID = "RECORDER"; } diff --git a/openvidu-server/src/main/java/io/openvidu/server/cdr/CDREvent.java b/openvidu-server/src/main/java/io/openvidu/server/cdr/CDREvent.java index 348edde5..430c9f7d 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/cdr/CDREvent.java +++ b/openvidu-server/src/main/java/io/openvidu/server/cdr/CDREvent.java @@ -122,11 +122,11 @@ public class CDREvent implements Comparable { } if (this.mediaOptions != null) { json.put("connection", this.receivingFrom != null ? "INBOUND" : "OUTBOUND"); - json.put("audioEnabled", this.mediaOptions.audioActive); - json.put("videoEnabled", this.mediaOptions.videoActive); - if (this.mediaOptions.videoActive) { - json.put("videoSource", this.mediaOptions.typeOfVideo); - json.put("videoFramerate", this.mediaOptions.frameRate); + json.put("audioEnabled", this.mediaOptions.hasAudio()); + json.put("videoEnabled", this.mediaOptions.hasVideo()); + if (this.mediaOptions.hasVideo()) { + json.put("videoSource", this.mediaOptions.getTypeOfVideo()); + json.put("videoFramerate", this.mediaOptions.getFrameRate()); } if (this.receivingFrom != null) { json.put("receivingFrom", this.receivingFrom); diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/MediaOptions.java b/openvidu-server/src/main/java/io/openvidu/server/core/MediaOptions.java index 066775c8..2376e938 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/MediaOptions.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/MediaOptions.java @@ -17,18 +17,72 @@ package io.openvidu.server.core; +import org.json.simple.JSONObject; + public class MediaOptions { - - public boolean audioActive; - public boolean videoActive; - public String typeOfVideo; - public int frameRate; - - public MediaOptions(boolean audioActive, boolean videoActive, String typeOfVideo, int frameRate) { + + protected Boolean hasAudio; + protected Boolean hasVideo; + protected Boolean audioActive; + protected Boolean videoActive; + protected String typeOfVideo; + protected Integer frameRate; + protected String videoDimensions; + + public MediaOptions(Boolean hasAudio, Boolean hasVideo, Boolean audioActive, Boolean videoActive, + String typeOfVideo, Integer frameRate, String videoDimensions) { + this.hasAudio = hasAudio; + this.hasVideo = hasVideo; this.audioActive = audioActive; this.videoActive = videoActive; this.typeOfVideo = typeOfVideo; this.frameRate = frameRate; + this.videoDimensions = videoDimensions; + } + + @SuppressWarnings("unchecked") + public JSONObject toJson() { + JSONObject json = new JSONObject(); + json.put("hasAudio", this.hasAudio); + if (hasAudio) + json.put("audioActive", this.audioActive); + json.put("hasVideo", this.hasVideo); + if (hasVideo) + json.put("videoActive", this.videoActive); + if (this.hasVideo && this.videoActive) { + json.put("typeOfVideo", this.typeOfVideo); + json.put("frameRate", this.frameRate); + json.put("videoDimensions", this.videoDimensions); + } + return json; + } + + public boolean hasAudio() { + return this.hasAudio; + } + + public boolean hasVideo() { + return this.hasVideo; + } + + public boolean isAudioActive() { + return this.hasAudio && this.audioActive; + } + + public boolean isVideoActive() { + return this.hasVideo && this.videoActive; + } + + public String getTypeOfVideo() { + return this.typeOfVideo; + } + + public Integer getFrameRate() { + return this.frameRate; + } + + public String getVideoDimensions() { + return this.videoDimensions; } } diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/SessionEventsHandler.java b/openvidu-server/src/main/java/io/openvidu/server/core/SessionEventsHandler.java index 8a58b844..c60859f7 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/SessionEventsHandler.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/SessionEventsHandler.java @@ -91,12 +91,18 @@ public class SessionEventsHandler { existingParticipant.getFullMetadata()); if (existingParticipant.isStreaming()) { - + KurentoParticipant kParticipant = (KurentoParticipant) existingParticipant; - + JsonObject stream = new JsonObject(); stream.addProperty(ProtocolElements.JOINROOM_PEERSTREAMID_PARAM, existingParticipant.getPublisherStremId()); + stream.addProperty(ProtocolElements.JOINROOM_PEERSTREAMHASAUDIO_PARAM, + kParticipant.getPublisherMediaOptions().hasAudio); + stream.addProperty(ProtocolElements.JOINROOM_PEERSTREAMHASVIDEO_PARAM, + kParticipant.getPublisherMediaOptions().hasVideo); + stream.addProperty(ProtocolElements.JOINROOM_PEERSTREAMVIDEOACTIVE_PARAM, + kParticipant.getPublisherMediaOptions().videoActive); stream.addProperty(ProtocolElements.JOINROOM_PEERSTREAMAUDIOACTIVE_PARAM, kParticipant.getPublisherMediaOptions().audioActive); stream.addProperty(ProtocolElements.JOINROOM_PEERSTREAMVIDEOACTIVE_PARAM, @@ -105,6 +111,8 @@ public class SessionEventsHandler { kParticipant.getPublisherMediaOptions().typeOfVideo); stream.addProperty(ProtocolElements.JOINROOM_PEERSTREAMFRAMERATE_PARAM, kParticipant.getPublisherMediaOptions().frameRate); + stream.addProperty(ProtocolElements.JOINROOM_PEERSTREAMVIDEODIMENSIONS_PARAM, + kParticipant.getPublisherMediaOptions().videoDimensions); JsonArray streamsArray = new JsonArray(); streamsArray.add(stream); @@ -168,8 +176,8 @@ public class SessionEventsHandler { } } - public void onPublishMedia(Participant participant, String streamId, String sessionId, MediaOptions mediaOptions, String sdpAnswer, - Set participants, Integer transactionId, OpenViduException error) { + public void onPublishMedia(Participant participant, String streamId, String sessionId, MediaOptions mediaOptions, + String sdpAnswer, Set participants, Integer transactionId, OpenViduException error) { if (error != null) { rpcNotificationService.sendErrorResponse(participant.getParticipantPrivateId(), transactionId, null, error); return; @@ -184,10 +192,13 @@ public class SessionEventsHandler { JsonObject stream = new JsonObject(); stream.addProperty(ProtocolElements.PARTICIPANTPUBLISHED_STREAMID_PARAM, streamId); + stream.addProperty(ProtocolElements.PARTICIPANTPUBLISHED_HASAUDIO_PARAM, mediaOptions.hasAudio); + stream.addProperty(ProtocolElements.PARTICIPANTPUBLISHED_HASVIDEO_PARAM, mediaOptions.hasVideo); stream.addProperty(ProtocolElements.PARTICIPANTPUBLISHED_AUDIOACTIVE_PARAM, mediaOptions.audioActive); stream.addProperty(ProtocolElements.PARTICIPANTPUBLISHED_VIDEOACTIVE_PARAM, mediaOptions.videoActive); stream.addProperty(ProtocolElements.PARTICIPANTPUBLISHED_TYPEOFVIDEO_PARAM, mediaOptions.typeOfVideo); stream.addProperty(ProtocolElements.PARTICIPANTPUBLISHED_FRAMERATE_PARAM, mediaOptions.frameRate); + stream.addProperty(ProtocolElements.PARTICIPANTPUBLISHED_VIDEODIMENSIONS_PARAM, mediaOptions.videoDimensions); JsonArray streamsArray = new JsonArray(); streamsArray.add(stream); @@ -308,6 +319,28 @@ public class SessionEventsHandler { rpcNotificationService.sendResponse(participant.getParticipantPrivateId(), transactionId, new JsonObject()); } + public void onStreamPropertyChanged(Participant participant, Integer transactionId, Set participants, + String streamId, String property, JsonElement newValue, String reason) { + + JsonObject params = new JsonObject(); + params.addProperty(ProtocolElements.STREAMPROPERTYCHANGED_CONNECTIONID_PARAM, + participant.getParticipantPublicId()); + params.addProperty(ProtocolElements.STREAMPROPERTYCHANGED_STREAMID_PARAM, streamId); + params.addProperty(ProtocolElements.STREAMPROPERTYCHANGED_PROPERTY_PARAM, property); + params.addProperty(ProtocolElements.STREAMPROPERTYCHANGED_NEWVALUE_PARAM, newValue.toString()); + params.addProperty(ProtocolElements.STREAMPROPERTYCHANGED_REASON_PARAM, reason); + + for (Participant p : participants) { + if (p.getParticipantPrivateId().equals(participant.getParticipantPrivateId())) { + rpcNotificationService.sendResponse(participant.getParticipantPrivateId(), transactionId, + new JsonObject()); + } else { + rpcNotificationService.sendNotification(p.getParticipantPrivateId(), + ProtocolElements.STREAMPROPERTYCHANGED_METHOD, params); + } + } + } + public void onRecvIceCandidate(Participant participant, Integer transactionId, OpenViduException error) { if (error != null) { rpcNotificationService.sendErrorResponse(participant.getParticipantPrivateId(), transactionId, null, error); 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 d3996ab2..e5c3ad33 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 @@ -32,6 +32,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import com.google.gson.JsonElement; import com.google.gson.JsonObject; import io.openvidu.client.OpenViduException; @@ -86,6 +87,9 @@ public abstract class SessionManager { public abstract void sendMessage(Participant participant, String message, Integer transactionId); + public abstract void streamPropertyChanged(Participant participant, Integer transactionId, String streamId, + String property, JsonElement newValue, String reason); + public abstract void onIceCandidate(Participant participant, String endpointName, String candidate, int sdpMLineIndex, String sdpMid, Integer transactionId); @@ -203,15 +207,16 @@ public abstract class SessionManager { public String newToken(String sessionId, ParticipantRole role, String serverMetadata) throws OpenViduException { - ConcurrentHashMap map = this.sessionidTokenTokenobj.putIfAbsent(sessionId, new ConcurrentHashMap<>()); + ConcurrentHashMap map = this.sessionidTokenTokenobj.putIfAbsent(sessionId, + new ConcurrentHashMap<>()); if (map != null) { - + if (!isMetadataFormatCorrect(serverMetadata)) { log.error("Data invalid format. Max length allowed is 10000 chars"); throw new OpenViduException(Code.GENERIC_ERROR_CODE, "Data invalid format. Max length allowed is 10000 chars"); } - + String token = OpenViduServer.publicUrl; token += "?sessionId=" + sessionId; token += "&token=" + this.generateRandomChain(); @@ -225,11 +230,11 @@ public abstract class SessionManager { } } Token t = new Token(token, role, serverMetadata, turnCredentials); - + map.putIfAbsent(token, t); showTokens(); return token; - + } else { this.sessionidTokenTokenobj.remove(sessionId); log.error("sessionId [" + sessionId + "] is not valid"); @@ -249,8 +254,10 @@ public abstract class SessionManager { this.sessionidParticipantpublicidParticipant.putIfAbsent(sessionId, new ConcurrentHashMap<>()); this.sessionidTokenTokenobj.putIfAbsent(sessionId, new ConcurrentHashMap<>()); this.sessionidTokenTokenobj.get(sessionId).putIfAbsent(token, - new Token(token, ParticipantRole.PUBLISHER, "", - this.coturnCredentialsService.isCoturnAvailable() ? this.coturnCredentialsService.createUser() : null)); + new Token(token, ParticipantRole.PUBLISHER, "", + this.coturnCredentialsService.isCoturnAvailable() + ? this.coturnCredentialsService.createUser() + : null)); return true; } } @@ -313,8 +320,10 @@ public abstract class SessionManager { public Participant newRecorderParticipant(String sessionId, String participantPrivatetId, Token token, String clientMetadata) { if (this.sessionidParticipantpublicidParticipant.get(sessionId) != null) { - Participant p = new Participant(participantPrivatetId, ProtocolElements.RECORDER_PARTICIPANT_PUBLICID, token, clientMetadata); - this.sessionidParticipantpublicidParticipant.get(sessionId).put(ProtocolElements.RECORDER_PARTICIPANT_PUBLICID, p); + Participant p = new Participant(participantPrivatetId, ProtocolElements.RECORDER_PARTICIPANT_PUBLICID, + token, clientMetadata); + this.sessionidParticipantpublicidParticipant.get(sessionId) + .put(ProtocolElements.RECORDER_PARTICIPANT_PUBLICID, p); return p; } else { throw new OpenViduException(Code.ROOM_NOT_FOUND_ERROR_CODE, sessionId); diff --git a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoMediaOptions.java b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoMediaOptions.java index 422d4366..5c2486e0 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoMediaOptions.java +++ b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoMediaOptions.java @@ -32,9 +32,10 @@ public class KurentoMediaOptions extends MediaOptions { public MediaElement[] mediaElements; public KurentoMediaOptions(boolean isOffer, String sdpOffer, MediaElement loopbackAlternativeSrc, - MediaType loopbackConnectionType, boolean audioActive, boolean videoActive, String typeOfVideo, - int frameRate, boolean doLoopback, MediaElement... mediaElements) { - super(audioActive, videoActive, typeOfVideo, frameRate); + MediaType loopbackConnectionType, Boolean hasAudio, Boolean hasVideo, Boolean audioActive, + Boolean videoActive, String typeOfVideo, Integer frameRate, String videoDimensions, boolean doLoopback, + MediaElement... mediaElements) { + super(hasAudio, hasVideo, audioActive, videoActive, typeOfVideo, frameRate, videoDimensions); this.isOffer = isOffer; this.sdpOffer = sdpOffer; this.loopbackAlternativeSrc = loopbackAlternativeSrc; 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 2ac2ace5..dfccf2d5 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 @@ -58,7 +58,7 @@ import io.openvidu.server.kurento.endpoint.SubscriberEndpoint; public class KurentoParticipant extends Participant { private static final Logger log = LoggerFactory.getLogger(KurentoParticipant.class); - + @Autowired protected OpenviduConfig openviduConfig; @@ -102,7 +102,7 @@ public class KurentoParticipant extends Participant { publisher.setMediaOptions(mediaOptions); String publisherStreamId = this.getParticipantPublicId() + "_" - + (mediaOptions.videoActive ? mediaOptions.typeOfVideo : "MICRO") + "_" + + (mediaOptions.hasVideo() ? mediaOptions.getTypeOfVideo() : "MICRO") + "_" + RandomStringUtils.random(5, true, false).toUpperCase(); this.publisher.getEndpoint().addTag("name", publisherStreamId); addEndpointListeners(this.publisher); @@ -180,11 +180,15 @@ public class KurentoParticipant extends Participant { } return this.publisher; } - + public MediaOptions getPublisherMediaOptions() { return this.publisher.getMediaOptions(); } + public void setPublisherMediaOptions(MediaOptions mediaOptions) { + this.publisher.setMediaOptions(mediaOptions); + } + public KurentoSession getSession() { return session; } @@ -641,7 +645,7 @@ public class KurentoParticipant extends Participant { + " | MEDIATYPE: " + event.getMediaType() + " | TIMESTAMP: " + System.currentTimeMillis(); endpoint.flowInMedia.put(event.getSource().getName(), event.getMediaType()); - if (endpoint.getMediaOptions().audioActive && endpoint.getMediaOptions().videoActive + if (endpoint.getMediaOptions().hasAudio() && endpoint.getMediaOptions().hasVideo() && endpoint.flowInMedia.values().size() == 2) { endpoint.kmsEvents.add(new KmsEvent(event)); } else if (endpoint.flowInMedia.values().size() == 1) { @@ -658,7 +662,7 @@ public class KurentoParticipant extends Participant { + " | MEDIATYPE: " + event.getMediaType() + " | TIMESTAMP: " + System.currentTimeMillis(); endpoint.flowOutMedia.put(event.getSource().getName(), event.getMediaType()); - if (endpoint.getMediaOptions().audioActive && endpoint.getMediaOptions().videoActive + if (endpoint.getMediaOptions().hasAudio() && endpoint.getMediaOptions().hasVideo() && endpoint.flowOutMedia.values().size() == 2) { endpoint.kmsEvents.add(new KmsEvent(event)); } else if (endpoint.flowOutMedia.values().size() == 1) { @@ -708,6 +712,24 @@ public class KurentoParticipant extends Participant { return json; } + @SuppressWarnings("unchecked") + public JSONObject withStatsToJSON() { + JSONObject json = super.toJSON(); + JSONArray publisherEnpoints = new JSONArray(); + if (this.streaming && this.publisher.getEndpoint() != null) { + publisherEnpoints.add(this.publisher.withStatsToJSON()); + } + JSONArray subscriberEndpoints = new JSONArray(); + for (MediaEndpoint sub : this.subscribers.values()) { + if (sub.getEndpoint() != null) { + subscriberEndpoints.add(sub.withStatsToJSON()); + } + } + json.put("publishers", publisherEnpoints); + json.put("subscribers", subscriberEndpoints); + return json; + } + @Override public String getPublisherStremId() { return this.publisher.getEndpoint().getTag("name"); diff --git a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSessionManager.java b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSessionManager.java index 719abbaf..d862f707 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSessionManager.java +++ b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSessionManager.java @@ -28,6 +28,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import com.google.gson.JsonSyntaxException; @@ -124,7 +125,7 @@ public class KurentoSessionManager extends SessionManager { if (sessionidParticipantpublicidParticipant.get(sessionId) != null) { Participant p = sessionidParticipantpublicidParticipant.get(sessionId) .remove(participant.getParticipantPublicId()); - + if (this.coturnCredentialsService.isCoturnAvailable()) { this.coturnCredentialsService.deleteUser(p.getToken().getTurnCredentials().getUsername()); } @@ -271,8 +272,8 @@ public class KurentoSessionManager extends SessionManager { participants = kurentoParticipant.getSession().getParticipants(); if (sdpAnswer != null) { - sessionEventsHandler.onPublishMedia(participant, participant.getPublisherStremId(), session.getSessionId(), mediaOptions, sdpAnswer, - participants, transactionId, null); + sessionEventsHandler.onPublishMedia(participant, participant.getPublisherStremId(), session.getSessionId(), + mediaOptions, sdpAnswer, participants, transactionId, null); } } @@ -379,6 +380,40 @@ public class KurentoSessionManager extends SessionManager { } } + @Override + public void streamPropertyChanged(Participant participant, Integer transactionId, String streamId, String property, + JsonElement newValue, String reason) { + KurentoParticipant kParticipant = (KurentoParticipant) participant; + streamId = kParticipant.getPublisherStremId(); + MediaOptions streamProperties = kParticipant.getPublisherMediaOptions(); + + Boolean hasAudio = streamProperties.hasAudio(); + Boolean hasVideo = streamProperties.hasVideo(); + Boolean audioActive = streamProperties.isAudioActive(); + Boolean videoActive = streamProperties.isVideoActive(); + String typeOfVideo = streamProperties.getTypeOfVideo(); + Integer frameRate = streamProperties.getFrameRate(); + String videoDimensions = streamProperties.getVideoDimensions(); + + switch (property) { + case "audioActive": + audioActive = newValue.getAsBoolean(); + break; + case "videoActive": + videoActive = newValue.getAsBoolean(); + break; + case "videoDimensions": + videoDimensions = newValue.getAsString(); + break; + } + + kParticipant.setPublisherMediaOptions(new MediaOptions(hasAudio, hasVideo, audioActive, videoActive, + typeOfVideo, frameRate, videoDimensions)); + + sessionEventsHandler.onStreamPropertyChanged(participant, transactionId, + kParticipant.getSession().getParticipants(), streamId, property, newValue, reason); + } + @Override public void onIceCandidate(Participant participant, String endpointName, String candidate, int sdpMLineIndex, String sdpMid, Integer transactionId) { @@ -450,14 +485,38 @@ public class KurentoSessionManager extends SessionManager { public MediaOptions generateMediaOptions(Request request) { String sdpOffer = RpcHandler.getStringParam(request, ProtocolElements.PUBLISHVIDEO_SDPOFFER_PARAM); - boolean audioActive = RpcHandler.getBooleanParam(request, ProtocolElements.PUBLISHVIDEO_AUDIOACTIVE_PARAM); - boolean videoActive = RpcHandler.getBooleanParam(request, ProtocolElements.PUBLISHVIDEO_VIDEOACTIVE_PARAM); - String typeOfVideo = RpcHandler.getStringParam(request, ProtocolElements.PUBLISHVIDEO_TYPEOFVIDEO_PARAM); - int frameRate = RpcHandler.getIntParam(request, ProtocolElements.PUBLISHVIDEO_FRAMERATE_PARAM); + boolean hasAudio = RpcHandler.getBooleanParam(request, ProtocolElements.PUBLISHVIDEO_HASAUDIO_PARAM); + boolean hasVideo = RpcHandler.getBooleanParam(request, ProtocolElements.PUBLISHVIDEO_HASVIDEO_PARAM); + + Boolean audioActive = null, videoActive = null; + String typeOfVideo = null, videoDimensions = null; + Integer frameRate = null; + + try { + audioActive = RpcHandler.getBooleanParam(request, ProtocolElements.PUBLISHVIDEO_AUDIOACTIVE_PARAM); + } catch (RuntimeException noParameterFound) { + } + try { + videoActive = RpcHandler.getBooleanParam(request, ProtocolElements.PUBLISHVIDEO_VIDEOACTIVE_PARAM); + } catch (RuntimeException noParameterFound) { + } + try { + typeOfVideo = RpcHandler.getStringParam(request, ProtocolElements.PUBLISHVIDEO_TYPEOFVIDEO_PARAM); + } catch (RuntimeException noParameterFound) { + } + try { + videoDimensions = RpcHandler.getStringParam(request, ProtocolElements.PUBLISHVIDEO_VIDEODIMENSIONS_PARAM); + } catch (RuntimeException noParameterFound) { + } + try { + frameRate = RpcHandler.getIntParam(request, ProtocolElements.PUBLISHVIDEO_FRAMERATE_PARAM); + } catch (RuntimeException noParameterFound) { + } + boolean doLoopback = RpcHandler.getBooleanParam(request, ProtocolElements.PUBLISHVIDEO_DOLOOPBACK_PARAM); - return new KurentoMediaOptions(true, sdpOffer, null, null, audioActive, videoActive, typeOfVideo, frameRate, - doLoopback); + return new KurentoMediaOptions(true, sdpOffer, null, null, hasAudio, hasVideo, audioActive, videoActive, + typeOfVideo, frameRate, videoDimensions, doLoopback); } } diff --git a/openvidu-server/src/main/java/io/openvidu/server/rpc/RpcHandler.java b/openvidu-server/src/main/java/io/openvidu/server/rpc/RpcHandler.java index 87eb95f8..59a5bd8f 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/rpc/RpcHandler.java +++ b/openvidu-server/src/main/java/io/openvidu/server/rpc/RpcHandler.java @@ -30,6 +30,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import com.google.gson.JsonElement; import com.google.gson.JsonObject; import io.openvidu.client.OpenViduException; @@ -122,6 +123,9 @@ public class RpcHandler extends DefaultJsonRpcHandler { case ProtocolElements.UNPUBLISHVIDEO_METHOD: unpublishVideo(rpcConnection, request); break; + case ProtocolElements.STREAMPROPERTYCHANGED_METHOD: + streamPropertyChanged(rpcConnection, request); + break; default: log.error("Unrecognized request {}", request); break; @@ -282,6 +286,19 @@ public class RpcHandler extends DefaultJsonRpcHandler { sessionManager.unpublishVideo(participant, request.getId(), "unpublish"); } + + public void streamPropertyChanged(RpcConnection rpcConnection, Request request) { + String participantPrivateId = rpcConnection.getParticipantPrivateId(); + String sessionId = rpcConnection.getSessionId(); + Participant participant = sessionManager.getParticipant(sessionId, participantPrivateId); + + String streamId = getStringParam(request, ProtocolElements.STREAMPROPERTYCHANGED_STREAMID_PARAM); + String property = getStringParam(request, ProtocolElements.STREAMPROPERTYCHANGED_PROPERTY_PARAM); + JsonElement newValue = getParam(request, ProtocolElements.STREAMPROPERTYCHANGED_NEWVALUE_PARAM); + String reason = getStringParam(request, ProtocolElements.STREAMPROPERTYCHANGED_REASON_PARAM); + + sessionManager.streamPropertyChanged(participant, request.getId(), streamId, property, newValue, reason); + } public void leaveRoomAfterConnClosed(String participantPrivateId, String reason) { try { @@ -385,5 +402,13 @@ public class RpcHandler extends DefaultJsonRpcHandler { } return request.getParams().get(key).getAsBoolean(); } + + public static JsonElement getParam(Request request, String key) { + if (request.getParams() == null || request.getParams().get(key) == null) { + throw new RuntimeException("Request element '" + key + "' is missing in method '" + request.getMethod() + + "'. CHECK THAT 'openvidu-server' AND 'openvidu-browser' SHARE THE SAME VERSION NUMBER"); + } + return request.getParams().get(key); + } }