/// <summary> /// Creates a <see cref="ParticipantModel"/> and <see cref="RTPMessageReceiver"/> /// whenever a new stream is connected to the venue. The <see cref="ParticipantModel"/> /// is added to the current <see cref="ClassroomModel"/>. /// </summary> private void HandleStreamAdded(object sender, RtpEvents.RtpStreamEventArgs args) { using (Synchronizer.Lock(this.m_Sender.m_Classroom.SyncRoot)) { using (Synchronizer.Lock(this)) { if (this.m_Disposed) { throw new ObjectDisposedException("RTPMessageSender"); } RtpStream stream = args.RtpStream; // Ignore streams that are not part of our session. if (this.m_Sender.m_RtpSession.ContainsStream(stream)) { // Ignore streams that are not DynamicPresentations. if (stream.PayloadType == PayloadType.dynamicPresentation) { // Ignore our own stream, but create a listener for all others. if (stream.SSRC != this.m_Sender.m_RtpSender.SSRC) { // If we've not seen this client before, create a new ParticipantModel, // identified by the participant's CName, which, if the participant // is running Classroom Presenter, is a Guid string. string cname = stream.Properties.CName; // It's possible for a participant to generate more than one Rtp stream, // so we need to keep a different table for m_Participants than m_Receivers. ParticipantModel participant = ((ParticipantModel)this.m_Participants[cname]); if (participant == null) { // Also get the remote client's HumanName from the participant data. RtpParticipant client = this.m_Sender.m_RtpSession.Participants[cname]; participant = new ParticipantModel(new Guid(cname), client.Name); // Add the participant to our table. this.m_Participants.Add(cname, participant); } // Add the participant to the classroom if it is not already a member. if (!this.m_Sender.m_Classroom.Participants.Contains(participant)) { this.m_Sender.m_Classroom.Participants.Add(participant); } // Create a receiver for this specific stream (there may be more than one stream per participant) // and add it to the table of receivers so it can be disposed when the stream is removed. RTPMessageReceiver receiver = new RTPMessageReceiver(this.m_Sender, stream, this.m_Sender.m_Model, this.m_Sender.m_Classroom, participant); this.m_Receivers.Add(stream, receiver); } } } } } }
private void HandleStreamRemoved(object sender, MSR.LST.Net.Rtp.RtpEvents.RtpStreamEventArgs args) { using (Synchronizer.Lock(this.m_Sender.m_Classroom.SyncRoot)) { using (Synchronizer.Lock(this)) { // Do not check (or care) whether the RTPMessageSender has been disposed, // because we will get lots of RtpStreamRemoved events when the RtpSession is closed. RtpStream stream = args.RtpStream; RTPMessageReceiver receiver = ((RTPMessageReceiver)this.m_Receivers[stream]); if (receiver != null) { receiver.Dispose(); this.m_Receivers.Remove(stream); } // Discard all pending Nacks so the NackManager doesn't keep nacking them forever. this.m_Sender.NackManager.Discard(stream.SSRC, Range.UNIVERSE); // If this was the last stream for the participant, unregister the ParticipantModel // and remove it from the classroom. string cname = stream.Properties.CName; RtpParticipant client = this.m_Sender.m_RtpSession.Participants[cname]; if (client == null || client.SSRCs.Count <= 0) { ParticipantModel participant = ((ParticipantModel)this.m_Participants[cname]); if (participant != null) { // Remove the participant from the classroom. if (this.m_Sender.m_Classroom.Participants.Contains(participant)) { this.m_Sender.m_Classroom.Participants.Remove(participant); } } // Remove the participant from the table. this.m_Participants.Remove(cname); } } } }
/// <summary> /// Creates a <see cref="ParticipantModel"/> and <see cref="RTPMessageReceiver"/> /// whenever a new stream is connected to the venue. The <see cref="ParticipantModel"/> /// is added to the current <see cref="ClassroomModel"/>. /// </summary> private void HandleStreamAdded(object sender, RtpEvents.RtpStreamEventArgs args) { using(Synchronizer.Lock(this.m_Sender.m_Classroom.SyncRoot)) { using(Synchronizer.Lock(this)) { if(this.m_Disposed) throw new ObjectDisposedException("RTPMessageSender"); RtpStream stream = args.RtpStream; // Ignore streams that are not part of our session. if(this.m_Sender.m_RtpSession.ContainsStream(stream)) { // Ignore streams that are not DynamicPresentations. if(stream.PayloadType == PayloadType.dynamicPresentation) { // Ignore our own stream, but create a listener for all others. if(stream.SSRC != this.m_Sender.m_RtpSender.SSRC) { // If we've not seen this client before, create a new ParticipantModel, // identified by the participant's CName, which, if the participant // is running Classroom Presenter, is a Guid string. string cname = stream.Properties.CName; // It's possible for a participant to generate more than one Rtp stream, // so we need to keep a different table for m_Participants than m_Receivers. ParticipantModel participant = ((ParticipantModel) this.m_Participants[cname]); if(participant == null) { // Also get the remote client's HumanName from the participant data. RtpParticipant client = this.m_Sender.m_RtpSession.Participants[cname]; participant = new ParticipantModel(new Guid(cname), client.Name); // Add the participant to our table. this.m_Participants.Add(cname, participant); } // Add the participant to the classroom if it is not already a member. if(!this.m_Sender.m_Classroom.Participants.Contains(participant)) this.m_Sender.m_Classroom.Participants.Add(participant); // Create a receiver for this specific stream (there may be more than one stream per participant) // and add it to the table of receivers so it can be disposed when the stream is removed. RTPMessageReceiver receiver = new RTPMessageReceiver(this.m_Sender, stream, this.m_Sender.m_Model, this.m_Sender.m_Classroom, participant); this.m_Receivers.Add(stream, receiver); } } } } } }
public MessageProcessingQueue(RTPMessageReceiver receiver) { this.m_Receiver = receiver; }