private RosterParticipant GetParticipantWithDominantSpeakerMsi(uint dominantSpeakerMsi) { RosterParticipant firstParticipant = null; if (_participants == null) { Log.Warning(new CallerInfo(), LogContext.FrontEnd, $"[{CallId}] Did not receive rosterupdate notification yet"); return(null); } string dominantSpeakerIdentity = string.Empty; foreach (RosterParticipant participant in _participants) { if (participant.MediaStreamId == dominantSpeakerMsi.ToString()) { //identify if (participant.MediaType == ModalityType.Audio) { dominantSpeakerIdentity = participant.Identity; continue; } } if (participant.MediaType != ModalityType.Video || !(participant.MediaStreamDirection == "sendonly" || participant.MediaStreamDirection == "sendrecv") ) { continue; } //cache the first participant.. just incase dominant speaker is not sending video if (firstParticipant == null) { firstParticipant = participant; if (dominantSpeakerMsi == MediaSession.DominantSpeaker_None) { return(firstParticipant); } } //The dominant speaker is sending video.. if (participant.Identity == dominantSpeakerIdentity) { return(participant); } } //If dominant speaker is not sending video or if dominant speaker has exited the conference, choose the first participant sending video return(firstParticipant); }
/// <summary> /// Subscribe to the video stream of a participant. This function is called when dominant speaker notification is received and when roster changes /// When invoked on dominant speaker change, look if the participant is sharing their video. If yes then subscribe else choose the first participant in the list sharing their video /// When invoked on roster change, verify if the previously subscribed-to participant is still in the roster and sending video /// </summary> /// <param name="msi">Msi of dominant speaker or previously subscribed to msi depending on where it is invoked</param> /// <param name="msiOfDominantSpeaker">Gives more detail on the above msi.. Whether it is of dominant speaker or previously subscribed to video msi</param> /// <returns></returns> internal async Task Subscribe(uint msi, bool msiOfDominantSpeaker) { try { RosterParticipant participant; Log.Info(new CallerInfo(), LogContext.FrontEnd, $"[{CallId}] Received subscribe request for Msi {msi} msiOfDominantSpeaker {msiOfDominantSpeaker}"); if (msiOfDominantSpeaker) { participant = GetParticipantWithDominantSpeakerMsi(msi); } else { participant = GetParticipantForRosterChange(msi); } if (participant == null) { _subscribedToParticipant = null; return; } //if we have already subscribed earlier, skip the subscription if (_subscribedToParticipant != null && _subscribedToParticipant.MediaStreamId == participant.MediaStreamId) { Log.Info(new CallerInfo(), LogContext.FrontEnd, $"[{CallId}] Already subscribed to {participant.Identity}. So skipping subscription"); return; } Log.Info(new CallerInfo(), LogContext.FrontEnd, $"[{CallId}] Subscribing to {participant.Identity} with msi {participant.MediaStreamId}"); //Get subscription details var videoSubscription = new VideoSubscription { ParticipantIdentity = participant.Identity, OperationId = Guid.NewGuid().ToString(), SocketId = 0, //index of the VideoSocket in MediaConfiguration which receives the incoming video stream VideoModality = ModalityType.Video, VideoResolution = ResolutionFormat.Hd1080p }; await CallService.Subscribe(videoSubscription).ConfigureAwait(false); _subscribedToParticipant = participant; } catch (Exception ex) { Log.Error(new CallerInfo(), LogContext.FrontEnd, $"[{CallId}] Subscribe threw exception {ex.ToString()}"); _subscribedToParticipant = null; } }
private RosterParticipant GetParticipantForRosterChange(uint msi) { RosterParticipant firstParticipant = null; if (_participants == null) { Log.Warning(new CallerInfo(), LogContext.FrontEnd, $"[{CallId}] Did not receive rosterupdate notification yet"); return(null); } string dominantSpeakerIdentity = string.Empty; foreach (RosterParticipant participant in _participants) { if (participant.MediaStreamId == msi.ToString()) { if (participant.MediaType == ModalityType.Video && (participant.MediaStreamDirection == "sendonly" || participant.MediaStreamDirection == "sendrecv")) { return(participant); } } if (participant.MediaType != ModalityType.Video || !(participant.MediaStreamDirection == "sendonly" || participant.MediaStreamDirection == "sendrecv") ) { continue; } if (firstParticipant == null) { firstParticipant = participant; } } //No dominant speaker or dominant speaker is not sending video or if old dominant speaker has exited the conference, choose a new oe return(firstParticipant); }