/// <summary> /// Called when an SdesPacket arrives with an ID (CNAME) that no other session Participant has /// </summary> /// <param name="rtcp">SdesData containing the information for the participant</param> /// <param name="ipAddress">IpAddress this participant originates from</param> internal RtpParticipant(SdesData data, IPAddress ipAddress) : base(data) { this.ipAddress = ipAddress; this.ssrcs = new List<uint>(); this.stale = 0; SetPrivateExtension(Rtcp.PEP_SOURCE, Rtcp.PED_PARTICIPANT); }
/// <summary> /// Constructs an SdesData instance by reading its properties from another instance /// </summary> /// <param name="data"></param> public SdesData(SdesData sdes) { // Skip the first index - see comments for member variable 'data' for (int i = 1; i < sdes.data.Length; i++) { byte[] data = sdes.data[i]; if (data != null) { byte[] copy = new byte[data.Length]; data.CopyTo(copy, 0); data = copy; } this.data[i] = data; } foreach (DictionaryEntry de in sdes.privs) { SetPrivateExtension((byte[])de.Key, (byte[])de.Value); } }
internal SdesReport(uint ssrc, SdesData sdes) { this.ssrc = ssrc; this.sdes = sdes; }
/// <summary> /// This method is called to update the local data from another SdesData /// </summary> /// <param name="data">what we want to update our data to</param> /// <returns>true if the local data was updated, otherwise false</returns> internal bool UpdateData(SdesData sdes) { bool ret = false; // Well-known properties // CName can never be updated, so start with Name for (int id = (int)SDESType.NAME; id <= (int)SDESType.NOTE; id++) { if (!data[id].Compare(sdes.data[id])) { data[id] = sdes.data[id].Copy(); ret = true; } } // Write private properties foreach (DictionaryEntry de in sdes.privs) { byte[] key = (byte[])de.Key; byte[] data = (byte[])de.Value; if (!privs.Contains(key) || !data.Compare(privs[key])) { privs[key.Copy()] = data.Copy(); ret = true; } } return ret; }
internal RtpStreamFec(RtpListener rtpListener, uint ssrc, SdesData sdes, PayloadType pt) : base(rtpListener.ReturnBufferCallback, ssrc, sdes, pt) { this.getBufferHandler = rtpListener.GetBufferCallback; }
internal RtpStreamFFec(RtpListener rtpListener, uint ssrc, SdesData sdes, PayloadType pt, ushort fecPxExp) : base(rtpListener, ssrc, sdes, pt) { fecPercent = fecPxExp; pcFecType = 2; }
internal RtpStreamCFec(RtpListener rtpListener, uint ssrc, SdesData sdes, PayloadType pt, ushort dataPxExp, ushort fecPxExp) : base(rtpListener, ssrc, sdes, pt) { pcFecType = 1; this.dataPxExp = dataPxExp; this.fecPxExp = fecPxExp; SetDecoder(); InitializeDCRStorage(); }
private void AddSdes(uint ssrc, SdesData sdes) { cpb.Add_SDESReport(ssrc, sdes); }
/// <summary> /// AddOrUpdateParticipant is called by the RtpSession ctor for adding the local participant and /// by ProcessSdesPacket when an SDES packet arrives on the RtcpListener thread /// /// If the participant does not exist in the session, we add them /// If the participant does exist in the session, we make sure there is no CName conflict /// </summary> /// <param name="ssrc">Unique identifier of the stream</param> /// <param name="sdes">CName, Name, Email, etc from which to create the Participant</param> /// <param name="ip">Originating IP address of the ssrc and SdesData</param> private void AddOrUpdateParticipant(uint ssrc, SdesData sdes, IPAddress ip) { lock(participants) { string cName = sdes.CName; RtpParticipant participant = null; if (participants.ContainsKey(cName)) participant = participants[cName]; // Participant does not exist if(null == participant) { // Create a new participant AddParticipant(ssrc, new RtpParticipant(sdes, ip)); } else // Participant exists { CheckForCNameConflict(cName, new IPAddress[]{participant.IPAddress, ip}); participant.Stale = 0; participant.UpdateData(sdes); } } }
/// <summary> /// Called to create a stream via Rtcp and have all the "links" created /// /// CXP always stores the Participant ssrc/SdesData first in the SdesPacket. So a /// participant should always exist before the stream is created in this code. /// /// AddStream is called by the RtcpListener thread via ProcessSdesPacket /// </summary> private void AddOrUpdateStream(uint ssrc, SdesData sdes) { lock(participants) { lock(streamsAndIPs) { RtpParticipant participant = participants[sdes.CName]; if(participants[sdes.CName] == null) { Debug.Assert(false); throw new InvalidOperationException(Strings.CantCreateAStreamNoParticipant); } IPStreamPair ipsp = streamsAndIPs[ssrc]; Debug.Assert(ipsp != null); if(ipsp.stream == null) { ipsp.stream = RtpStream.CreateStream(rtpListener, ssrc, sdes); ssrcToParticipant[ssrc] = participant; participant.AddSSRC(ssrc); RaiseRtpStreamAddedEvent(ipsp.stream); } else // Update { ipsp.stream.Stale = 0; ipsp.stream.Properties.UpdateData(sdes); } } } }
void RtpSender.IRtpSession.AddSdes(uint ssrc, SdesData sdes) { AddSdes(ssrc, sdes); }
/// <summary> /// Raises the ParticipantStatusChanged event if the data changed /// </summary> /// <param name="data"></param> internal new void UpdateData(SdesData data) { if(base.UpdateData(data)) { object[] args = {this, new RtpEvents.RtpParticipantEventArgs(this)}; EventThrower.QueueUserWorkItem(new RtpEvents.RaiseEvent(RtpEvents.RaiseRtpParticipantDataChangedEvent), args); } }