mirror of https://github.com/OpenVidu/openvidu.git
openvidu-server: KMS track muting refactoring
parent
cb59dbcc4d
commit
2571a8a33c
|
@ -17,6 +17,6 @@
|
||||||
|
|
||||||
package io.openvidu.server.kurento;
|
package io.openvidu.server.kurento;
|
||||||
|
|
||||||
public enum MutedMediaType {
|
public enum TrackType {
|
||||||
ALL, VIDEO, AUDIO;
|
ALL, VIDEO, AUDIO;
|
||||||
}
|
}
|
|
@ -49,7 +49,7 @@ import io.openvidu.server.config.InfoHandler;
|
||||||
import io.openvidu.server.config.OpenviduConfig;
|
import io.openvidu.server.config.OpenviduConfig;
|
||||||
import io.openvidu.server.core.MediaOptions;
|
import io.openvidu.server.core.MediaOptions;
|
||||||
import io.openvidu.server.core.Participant;
|
import io.openvidu.server.core.Participant;
|
||||||
import io.openvidu.server.kurento.MutedMediaType;
|
import io.openvidu.server.kurento.TrackType;
|
||||||
import io.openvidu.server.kurento.endpoint.KmsEvent;
|
import io.openvidu.server.kurento.endpoint.KmsEvent;
|
||||||
import io.openvidu.server.kurento.endpoint.MediaEndpoint;
|
import io.openvidu.server.kurento.endpoint.MediaEndpoint;
|
||||||
import io.openvidu.server.kurento.endpoint.PublisherEndpoint;
|
import io.openvidu.server.kurento.endpoint.PublisherEndpoint;
|
||||||
|
@ -353,54 +353,12 @@ public class KurentoParticipant extends Participant {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void mutePublishedMedia(MutedMediaType muteType) {
|
public void mutePublishedMedia(TrackType trackType) {
|
||||||
if (muteType == null) {
|
this.getPublisher().mute(trackType);
|
||||||
throw new OpenViduException(Code.MEDIA_MUTE_ERROR_CODE, "Mute type cannot be null");
|
|
||||||
}
|
|
||||||
this.getPublisher().mute(muteType);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void unmutePublishedMedia() {
|
public void unmutePublishedMedia(TrackType trackType) {
|
||||||
if (this.getPublisher().getMuteType() == null) {
|
this.getPublisher().unmute(trackType);
|
||||||
log.warn("PARTICIPANT {}: Trying to unmute published media. " + "But media is not muted.",
|
|
||||||
this.getParticipantPublicId());
|
|
||||||
} else {
|
|
||||||
this.getPublisher().unmute();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void muteSubscribedMedia(Participant sender, MutedMediaType muteType) {
|
|
||||||
if (muteType == null) {
|
|
||||||
throw new OpenViduException(Code.MEDIA_MUTE_ERROR_CODE, "Mute type cannot be null");
|
|
||||||
}
|
|
||||||
String senderName = sender.getParticipantPublicId();
|
|
||||||
SubscriberEndpoint subscriberEndpoint = subscribers.get(senderName);
|
|
||||||
if (subscriberEndpoint == null || subscriberEndpoint.getEndpoint() == null) {
|
|
||||||
log.warn("PARTICIPANT {}: Trying to mute incoming media from user {}. "
|
|
||||||
+ "But there is no such subscriber endpoint.", this.getParticipantPublicId(), senderName);
|
|
||||||
} else {
|
|
||||||
log.debug("PARTICIPANT {}: Mute subscriber endpoint linked to user {}", this.getParticipantPublicId(),
|
|
||||||
senderName);
|
|
||||||
subscriberEndpoint.mute(muteType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void unmuteSubscribedMedia(Participant sender) {
|
|
||||||
String senderName = sender.getParticipantPublicId();
|
|
||||||
SubscriberEndpoint subscriberEndpoint = subscribers.get(senderName);
|
|
||||||
if (subscriberEndpoint == null || subscriberEndpoint.getEndpoint() == null) {
|
|
||||||
log.warn("PARTICIPANT {}: Trying to unmute incoming media from user {}. "
|
|
||||||
+ "But there is no such subscriber endpoint.", this.getParticipantPublicId(), senderName);
|
|
||||||
} else {
|
|
||||||
if (subscriberEndpoint.getMuteType() == null) {
|
|
||||||
log.warn("PARTICIPANT {}: Trying to unmute incoming media from user {}. " + "But media is not muted.",
|
|
||||||
this.getParticipantPublicId(), senderName);
|
|
||||||
} else {
|
|
||||||
log.debug("PARTICIPANT {}: Unmute subscriber endpoint linked to user {}", this.getParticipantPublicId(),
|
|
||||||
senderName);
|
|
||||||
subscriberEndpoint.unmute();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void close(String reason) {
|
public void close(String reason) {
|
||||||
|
|
|
@ -36,20 +36,20 @@ import com.google.gson.JsonSyntaxException;
|
||||||
import io.openvidu.client.OpenViduException;
|
import io.openvidu.client.OpenViduException;
|
||||||
import io.openvidu.client.OpenViduException.Code;
|
import io.openvidu.client.OpenViduException.Code;
|
||||||
import io.openvidu.client.internal.ProtocolElements;
|
import io.openvidu.client.internal.ProtocolElements;
|
||||||
|
import io.openvidu.java.client.MediaMode;
|
||||||
import io.openvidu.java.client.RecordingLayout;
|
import io.openvidu.java.client.RecordingLayout;
|
||||||
import io.openvidu.java.client.RecordingMode;
|
import io.openvidu.java.client.RecordingMode;
|
||||||
import io.openvidu.java.client.RecordingProperties;
|
import io.openvidu.java.client.RecordingProperties;
|
||||||
import io.openvidu.java.client.MediaMode;
|
|
||||||
import io.openvidu.java.client.SessionProperties;
|
import io.openvidu.java.client.SessionProperties;
|
||||||
|
import io.openvidu.server.core.MediaOptions;
|
||||||
|
import io.openvidu.server.core.Participant;
|
||||||
|
import io.openvidu.server.core.Session;
|
||||||
import io.openvidu.server.core.SessionManager;
|
import io.openvidu.server.core.SessionManager;
|
||||||
import io.openvidu.server.kurento.KurentoClientProvider;
|
import io.openvidu.server.kurento.KurentoClientProvider;
|
||||||
import io.openvidu.server.kurento.KurentoClientSessionInfo;
|
import io.openvidu.server.kurento.KurentoClientSessionInfo;
|
||||||
import io.openvidu.server.kurento.OpenViduKurentoClientSessionInfo;
|
import io.openvidu.server.kurento.OpenViduKurentoClientSessionInfo;
|
||||||
import io.openvidu.server.kurento.endpoint.SdpType;
|
import io.openvidu.server.kurento.endpoint.SdpType;
|
||||||
import io.openvidu.server.rpc.RpcHandler;
|
import io.openvidu.server.rpc.RpcHandler;
|
||||||
import io.openvidu.server.core.MediaOptions;
|
|
||||||
import io.openvidu.server.core.Participant;
|
|
||||||
import io.openvidu.server.core.Session;
|
|
||||||
|
|
||||||
public class KurentoSessionManager extends SessionManager {
|
public class KurentoSessionManager extends SessionManager {
|
||||||
|
|
||||||
|
@ -105,7 +105,8 @@ public class KurentoSessionManager extends SessionManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void leaveRoom(Participant participant, Integer transactionId, String reason, boolean closeWebSocket) {
|
public synchronized void leaveRoom(Participant participant, Integer transactionId, String reason,
|
||||||
|
boolean closeWebSocket) {
|
||||||
log.debug("Request [LEAVE_ROOM] ({})", participant.getParticipantPublicId());
|
log.debug("Request [LEAVE_ROOM] ({})", participant.getParticipantPublicId());
|
||||||
|
|
||||||
KurentoParticipant kParticipant = (KurentoParticipant) participant;
|
KurentoParticipant kParticipant = (KurentoParticipant) participant;
|
||||||
|
|
|
@ -45,7 +45,6 @@ import org.slf4j.LoggerFactory;
|
||||||
import io.openvidu.client.OpenViduException;
|
import io.openvidu.client.OpenViduException;
|
||||||
import io.openvidu.client.OpenViduException.Code;
|
import io.openvidu.client.OpenViduException.Code;
|
||||||
import io.openvidu.server.core.Participant;
|
import io.openvidu.server.core.Participant;
|
||||||
import io.openvidu.server.kurento.MutedMediaType;
|
|
||||||
import io.openvidu.server.kurento.core.KurentoParticipant;
|
import io.openvidu.server.kurento.core.KurentoParticipant;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -73,8 +72,6 @@ public abstract class MediaEndpoint {
|
||||||
private final List<IceCandidate> receivedCandidateList = new LinkedList<IceCandidate>();
|
private final List<IceCandidate> receivedCandidateList = new LinkedList<IceCandidate>();
|
||||||
private LinkedList<IceCandidate> candidates = new LinkedList<IceCandidate>();
|
private LinkedList<IceCandidate> candidates = new LinkedList<IceCandidate>();
|
||||||
|
|
||||||
private MutedMediaType muteType;
|
|
||||||
|
|
||||||
public Map<String, MediaType> flowInMedia = new ConcurrentHashMap<>();
|
public Map<String, MediaType> flowInMedia = new ConcurrentHashMap<>();
|
||||||
public Map<String, MediaType> flowOutMedia = new ConcurrentHashMap<>();
|
public Map<String, MediaType> flowOutMedia = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
@ -204,50 +201,6 @@ public abstract class MediaEndpoint {
|
||||||
unregisterElementErrListener(endpoint, endpointSubscription);
|
unregisterElementErrListener(endpoint, endpointSubscription);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Mute the media stream.
|
|
||||||
*
|
|
||||||
* @param muteType
|
|
||||||
* which type of leg to disconnect (audio, video or both)
|
|
||||||
*/
|
|
||||||
public abstract void mute(MutedMediaType muteType);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reconnect the muted media leg(s).
|
|
||||||
*/
|
|
||||||
public abstract void unmute();
|
|
||||||
|
|
||||||
public void setMuteType(MutedMediaType muteType) {
|
|
||||||
this.muteType = muteType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MutedMediaType getMuteType() {
|
|
||||||
return this.muteType;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void resolveCurrentMuteType(MutedMediaType newMuteType) {
|
|
||||||
MutedMediaType prev = this.getMuteType();
|
|
||||||
if (prev != null) {
|
|
||||||
switch (prev) {
|
|
||||||
case AUDIO:
|
|
||||||
if (muteType.equals(MutedMediaType.VIDEO)) {
|
|
||||||
this.setMuteType(MutedMediaType.ALL);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case VIDEO:
|
|
||||||
if (muteType.equals(MutedMediaType.AUDIO)) {
|
|
||||||
this.setMuteType(MutedMediaType.ALL);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ALL:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.setMuteType(newMuteType);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates the endpoint (RTP or WebRTC) and any other additional elements (if
|
* Creates the endpoint (RTP or WebRTC) and any other additional elements (if
|
||||||
* needed).
|
* needed).
|
||||||
|
|
|
@ -37,7 +37,7 @@ import org.slf4j.LoggerFactory;
|
||||||
import io.openvidu.client.OpenViduException;
|
import io.openvidu.client.OpenViduException;
|
||||||
import io.openvidu.client.OpenViduException.Code;
|
import io.openvidu.client.OpenViduException.Code;
|
||||||
import io.openvidu.server.core.MediaOptions;
|
import io.openvidu.server.core.MediaOptions;
|
||||||
import io.openvidu.server.kurento.MutedMediaType;
|
import io.openvidu.server.kurento.TrackType;
|
||||||
import io.openvidu.server.kurento.core.KurentoParticipant;
|
import io.openvidu.server.kurento.core.KurentoParticipant;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -46,6 +46,7 @@ import io.openvidu.server.kurento.core.KurentoParticipant;
|
||||||
* @author <a href="mailto:rvlad@naevatec.com">Radu Tom Vlad</a>
|
* @author <a href="mailto:rvlad@naevatec.com">Radu Tom Vlad</a>
|
||||||
*/
|
*/
|
||||||
public class PublisherEndpoint extends MediaEndpoint {
|
public class PublisherEndpoint extends MediaEndpoint {
|
||||||
|
|
||||||
private final static Logger log = LoggerFactory.getLogger(PublisherEndpoint.class);
|
private final static Logger log = LoggerFactory.getLogger(PublisherEndpoint.class);
|
||||||
|
|
||||||
protected MediaOptions mediaOptions;
|
protected MediaOptions mediaOptions;
|
||||||
|
@ -283,8 +284,7 @@ public class PublisherEndpoint extends MediaEndpoint {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public synchronized void mute(TrackType muteType) {
|
||||||
public synchronized void mute(MutedMediaType muteType) {
|
|
||||||
MediaElement sink = passThru;
|
MediaElement sink = passThru;
|
||||||
if (!elements.isEmpty()) {
|
if (!elements.isEmpty()) {
|
||||||
String sinkId = elementIds.peekLast();
|
String sinkId = elementIds.peekLast();
|
||||||
|
@ -308,11 +308,9 @@ public class PublisherEndpoint extends MediaEndpoint {
|
||||||
internalSinkDisconnect(this.getEndpoint(), sink, MediaType.VIDEO);
|
internalSinkDisconnect(this.getEndpoint(), sink, MediaType.VIDEO);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
resolveCurrentMuteType(muteType);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public synchronized void unmute(TrackType muteType) {
|
||||||
public synchronized void unmute() {
|
|
||||||
MediaElement sink = passThru;
|
MediaElement sink = passThru;
|
||||||
if (!elements.isEmpty()) {
|
if (!elements.isEmpty()) {
|
||||||
String sinkId = elementIds.peekLast();
|
String sinkId = elementIds.peekLast();
|
||||||
|
@ -325,8 +323,17 @@ public class PublisherEndpoint extends MediaEndpoint {
|
||||||
} else {
|
} else {
|
||||||
log.debug("Will unmute connection of WebRTC and PassThrough (no other elems)");
|
log.debug("Will unmute connection of WebRTC and PassThrough (no other elems)");
|
||||||
}
|
}
|
||||||
|
switch (muteType) {
|
||||||
|
case ALL:
|
||||||
internalSinkConnect(this.getEndpoint(), sink);
|
internalSinkConnect(this.getEndpoint(), sink);
|
||||||
setMuteType(null);
|
break;
|
||||||
|
case AUDIO:
|
||||||
|
internalSinkConnect(this.getEndpoint(), sink, MediaType.AUDIO);
|
||||||
|
break;
|
||||||
|
case VIDEO:
|
||||||
|
internalSinkConnect(this.getEndpoint(), sink, MediaType.VIDEO);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getNext(String uid) {
|
private String getNext(String uid) {
|
||||||
|
|
|
@ -19,12 +19,9 @@ package io.openvidu.server.kurento.endpoint;
|
||||||
|
|
||||||
import org.json.simple.JSONObject;
|
import org.json.simple.JSONObject;
|
||||||
import org.kurento.client.MediaPipeline;
|
import org.kurento.client.MediaPipeline;
|
||||||
import org.kurento.client.MediaType;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import io.openvidu.client.OpenViduException;
|
|
||||||
import io.openvidu.client.OpenViduException.Code;
|
|
||||||
import io.openvidu.server.kurento.core.KurentoParticipant;
|
import io.openvidu.server.kurento.core.KurentoParticipant;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -70,31 +67,6 @@ public class SubscriberEndpoint extends MediaEndpoint {
|
||||||
this.publisher = publisher;
|
this.publisher = publisher;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized void mute(io.openvidu.server.kurento.MutedMediaType muteType) {
|
|
||||||
if (this.publisher == null) {
|
|
||||||
throw new OpenViduException(Code.MEDIA_MUTE_ERROR_CODE, "Publisher endpoint not found");
|
|
||||||
}
|
|
||||||
switch (muteType) {
|
|
||||||
case ALL:
|
|
||||||
this.publisher.disconnectFrom(this.getEndpoint());
|
|
||||||
break;
|
|
||||||
case AUDIO:
|
|
||||||
this.publisher.disconnectFrom(this.getEndpoint(), MediaType.AUDIO);
|
|
||||||
break;
|
|
||||||
case VIDEO:
|
|
||||||
this.publisher.disconnectFrom(this.getEndpoint(), MediaType.VIDEO);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
resolveCurrentMuteType(muteType);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized void unmute() {
|
|
||||||
this.publisher.connect(this.getEndpoint());
|
|
||||||
setMuteType(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
public JSONObject toJSON() {
|
public JSONObject toJSON() {
|
||||||
|
|
|
@ -210,6 +210,14 @@ public class SessionRestController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @RequestMapping(value = "/sessions/{sessionId}/stream/{streamId}", method =
|
||||||
|
* RequestMethod.PUT) public ResponseEntity<JSONObject>
|
||||||
|
* muteMedia(@PathVariable("sessionId") String sessionId,
|
||||||
|
*
|
||||||
|
* @PathVariable("streamId") String streamId, @RequestBody Map<?, ?> params) { }
|
||||||
|
*/
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@RequestMapping(value = "/tokens", method = RequestMethod.POST)
|
@RequestMapping(value = "/tokens", method = RequestMethod.POST)
|
||||||
public ResponseEntity<JSONObject> newToken(@RequestBody Map<?, ?> params) {
|
public ResponseEntity<JSONObject> newToken(@RequestBody Map<?, ?> params) {
|
||||||
|
|
|
@ -56,7 +56,6 @@ public class RpcHandler extends DefaultJsonRpcHandler<JsonObject> {
|
||||||
RpcNotificationService notificationService;
|
RpcNotificationService notificationService;
|
||||||
|
|
||||||
private ConcurrentMap<String, Boolean> webSocketEOFTransportError = new ConcurrentHashMap<>();
|
private ConcurrentMap<String, Boolean> webSocketEOFTransportError = new ConcurrentHashMap<>();
|
||||||
// private ConcurrentMap<String, Boolean> webSocketBrokenPipeTransportError = new ConcurrentHashMap<>();
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleRequest(Transaction transaction, Request<JsonObject> request) throws Exception {
|
public void handleRequest(Transaction transaction, Request<JsonObject> request) throws Exception {
|
||||||
|
@ -360,7 +359,6 @@ public class RpcHandler extends DefaultJsonRpcHandler<JsonObject> {
|
||||||
if ("IOException".equals(exception.getClass().getSimpleName())
|
if ("IOException".equals(exception.getClass().getSimpleName())
|
||||||
&& "Broken pipe".equals(exception.getCause().getMessage())) {
|
&& "Broken pipe".equals(exception.getCause().getMessage())) {
|
||||||
log.warn("Parcipant with private id {} unexpectedly closed the websocket", rpcSession.getSessionId());
|
log.warn("Parcipant with private id {} unexpectedly closed the websocket", rpcSession.getSessionId());
|
||||||
// this.webSocketBrokenPipeTransportError.put(rpcSession.getSessionId(), true);
|
|
||||||
}
|
}
|
||||||
if ("EOFException".equals(exception.getClass().getSimpleName())) {
|
if ("EOFException".equals(exception.getClass().getSimpleName())) {
|
||||||
// Store WebSocket connection interrupted exception for this web socket to
|
// Store WebSocket connection interrupted exception for this web socket to
|
||||||
|
|
Loading…
Reference in New Issue