Example #1
0
        internal static RtpStream CreateStream(RtpListener rtpListener, uint ssrc, string ipaddress, SdesData sdes)
        {
            string sPT = sdes.GetPrivateExtension(Rtcp.PEP_PAYLOADTYPE);
            PayloadType pt = (PayloadType)Enum.Parse(typeof(PayloadType), sPT);

            // RtpStreamFec
            string fecData = sdes.GetPrivateExtension(Rtcp.PEP_FEC);
            if(fecData != null)
            {
                string[] args = fecData.Split(new char[]{':'});
                ushort dataPxExp = ushort.Parse(args[0]);
                ushort fecPxExp = ushort.Parse(args[1]);

                if(fecPxExp == 0)
                {
                    throw new ArgumentOutOfRangeException("fecPxExp", fecPxExp, "Must be >= 1");
                }
                
                // Frame based Fec
                if(dataPxExp == 0)
                {
                    return new RtpStreamFFec(rtpListener, ssrc, ipaddress, sdes, pt, fecPxExp);
                }
                else // Constant Fec
                {
                    return new RtpStreamCFec(rtpListener, ssrc, ipaddress, sdes, pt, dataPxExp, fecPxExp);
                }
            }

            // RtpStream
            return new RtpStream(rtpListener, ssrc, ipaddress,sdes, pt);
        }
Example #2
0
        /// <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)Rtcp.SDESType.NAME; id <= (int)Rtcp.SDESType.NOTE; id++)
            {
                if (!BufferChunk.Compare(data[id], sdes.data[id]))
                {
                    data[id] = BufferChunk.Copy(sdes.data[id]);
                    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) || !BufferChunk.Compare(data, privs[key]))
                {
                    privs[BufferChunk.Copy(key)] = BufferChunk.Copy(data);
                    ret = true;
                }
            }

            return(ret);
        }
Example #3
0
        internal static RtpStream CreateStream(RtpListener rtpListener, uint ssrc, SdesData sdes)
        {
            string      sPT = sdes.GetPrivateExtension(Rtcp.PEP_PAYLOADTYPE);
            PayloadType pt  = (PayloadType)Enum.Parse(typeof(PayloadType), sPT);

            // RtpStreamFec
            string fecData = sdes.GetPrivateExtension(Rtcp.PEP_FEC);

            if (fecData != null)
            {
                string[] args      = fecData.Split(new char[] { ':' });
                ushort   dataPxExp = ushort.Parse(args[0]);
                ushort   fecPxExp  = ushort.Parse(args[1]);

                if (fecPxExp == 0)
                {
                    throw new ArgumentOutOfRangeException("fecPxExp", fecPxExp, "Must be >= 1");
                }

                // Frame based Fec
                if (dataPxExp == 0)
                {
                    return(new RtpStreamFFec(rtpListener, ssrc, sdes, pt, fecPxExp));
                }
                else // Constant Fec
                {
                    return(new RtpStreamCFec(rtpListener, ssrc, sdes, pt, dataPxExp, fecPxExp));
                }
            }

            // RtpStream
            return(new RtpStream(rtpListener, ssrc, sdes, pt));
        }
Example #4
0
        internal static RtpStream CreateStream2(RtpListener rtpListener, uint ssrc, string ipaddress, SdesData sdes)
        {
            string sPT = sdes.GetPrivateExtension(Rtcp.PEP_PAYLOADTYPE);
            PayloadType pt = PayloadType.JPEG;

            // RtpStream
            return new RtpStream(rtpListener, ssrc, ipaddress, sdes, pt);
        }
Example #5
0
 /// <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);
     }
 }
Example #6
0
        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();
        }
Example #7
0
        internal RtpStream(RtpListener rtpListener, uint ssrc, SdesData sdes, PayloadType pt)
        {
            Debug.Assert(rtpListener != null);
            Debug.Assert(ssrc != 0);
            Debug.Assert(sdes != null);

            this.returnBufferHandler = rtpListener.ReturnBufferCallback;
            this.ssrc = ssrc;
            this.pt   = pt;

            properties = new SdesData(sdes);

            InitializePerformanceCounters();
        }
        internal RtpSender(IRtpSession rtpSession, string name, PayloadType payloadType, Hashtable priExns, uint ssrc)
        {
            if (Thread.CurrentThread.Name == null)
            {
                Thread.CurrentThread.Name = "RtpSender - " + name;
            }

            this.ssrc = ssrc; // 0 indicates that a random value should be chosen...

            this.rtpSession  = rtpSession;
            this.payloadType = payloadType;

            // Leave everything but CName and Name blank in order to reduce Rtcp bandwidth
            sdes = new SdesData(rtpSession.Sdes.CName, name);

            // Add private extensions
            sdes.SetPrivateExtension(Rtcp.PEP_SOURCE, Rtcp.PED_STREAM);
            sdes.SetPrivateExtension(Rtcp.PEP_PAYLOADTYPE, ((int)payloadType).ToString(CultureInfo.InvariantCulture));

            InitializeNetwork();
            InitializeFrame();
            InitializePerformanceCounters();

            // This needs to be called after InitializeNetwork
            if (priExns != null)
            {
                foreach (DictionaryEntry de in priExns)
                {
                    sdes.SetPrivateExtension((string)de.Key, (string)de.Value);
                }

                string dbpString = (string)priExns[Rtcp.PEP_DBP];
                if (dbpString != null)
                {
                    DelayBetweenPackets = short.Parse(dbpString, CultureInfo.InvariantCulture);
                }
            }

            ResetState();
        }
Example #9
0
        /// <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);
            }
        }
Example #10
0
 public void Add_SDESReport(uint ssrc, SdesData sdes)
 {
     sdesReports.Push(new SdesReport(ssrc, sdes));
 }
Example #11
0
        internal static RtpStream CreateStream2(RtpListener rtpListener, uint ssrc, string ipaddress, SdesData sdes)
        {
            string      sPT = sdes.GetPrivateExtension(Rtcp.PEP_PAYLOADTYPE);
            PayloadType pt  = PayloadType.JPEG;

            // RtpStream
            return(new RtpStream(rtpListener, ssrc, ipaddress, sdes, pt));
        }
Example #12
0
 internal RtpStreamFec(RtpListener rtpListener, uint ssrc, SdesData sdes, PayloadType pt)
     : base(rtpListener, ssrc, sdes, pt)
 {
     this.getBufferHandler = rtpListener.GetBufferCallback;
 }
Example #13
0
 public void Add(uint ssrc, SdesData props)
 {
     Dictionary.Add(ssrc, props);
 }
Example #14
0
 internal RtpStreamFFec(RtpListener rtpListener, uint ssrc, string ipaddress, SdesData sdes, PayloadType pt, ushort fecPxExp)
     : base(rtpListener, ssrc, ipaddress, sdes, pt)
 {
     fecPercent = fecPxExp;
     pcFecType = 2;
 }
Example #15
0
        internal RtpStreamCFec(RtpListener rtpListener, uint ssrc, string ipaddress, SdesData sdes, PayloadType pt, ushort dataPxExp, ushort fecPxExp) 
            : base(rtpListener, ssrc, ipaddress, sdes, pt)
        {
            pcFecType = 1;

            this.dataPxExp = dataPxExp;
            this.fecPxExp = fecPxExp;

            SetDecoder();
            InitializeDCRStorage();
        }
Example #16
0
        /// <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)Rtcp.SDESType.NAME; id <= (int)Rtcp.SDESType.NOTE; id++)
            {
                if(!BufferChunk.Compare(data[id], sdes.data[id]))
                {
                    data[id] = BufferChunk.Copy(sdes.data[id]);
                    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) || !BufferChunk.Compare(data, privs[key]))
                {
                    privs[BufferChunk.Copy(key)] = BufferChunk.Copy(data);
                    ret = true;
                }
            }

            return ret;
        }
Example #17
0
        /// <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("Can't create a stream if there is " +
                            "no participant to associate it with!");
                    }

                    IPStreamPairHashtable.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);
                    }
                }
            }
        }
Example #18
0
 public SdesReport(uint ssrc, SdesData sdes)
 {
     this.ssrc = ssrc;
     this.sdes = sdes;
 }
Example #19
0
        /// <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);
            }
        }
Example #20
0
 public void Add(uint ssrc, SdesData props)
 {
     Dictionary.Add(ssrc, props);
 }
Example #21
0
 /// <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;
     SetPrivateExtension(Rtcp.PEP_SOURCE, Rtcp.PED_PARTICIPANT);
 }
Example #22
0
 internal RtpStreamFec(RtpListener rtpListener, uint ssrc, string ipaddress, SdesData sdes, PayloadType pt) 
     : base(rtpListener, ssrc, ipaddress, sdes, pt)
 {
     this.getBufferHandler = rtpListener.GetBufferCallback;
 }
Example #23
0
 void RtpSender.IRtpSession.AddSdes(uint ssrc, SdesData sdes)
 {
     AddSdes(ssrc, sdes);
 }
Example #24
0
        internal RtpStream(RtpListener rtpListener, uint ssrc, string ipaddress, SdesData sdes, PayloadType pt)
        {
            Debug.Assert(rtpListener != null);
            Debug.Assert(ssrc != 0);
            Debug.Assert(sdes != null);
            Debug.Assert(ipaddress != null);

            this.returnBufferHandler = rtpListener.ReturnBufferCallback;
            this.ssrc = ssrc;
            this.pt = pt;
            this.ipaddress = ipaddress;

            properties = new SdesData(sdes);

            InitializePerformanceCounters();
        }
Example #25
0
        /// <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 = participants[cName];

                // Participant does not exist
                if(participant == null)
                {
                    // 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);
                }
            }
        }
Example #26
0
 /// <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);
     }
 }
Example #27
0
 private void AddSdes(uint ssrc, SdesData sdes)
 {
     cpb.Add_SDESReport(ssrc, sdes);
 }
Example #28
0
        /// <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 AddOrUpdateStream2(uint ssrc, string ipaddress, SdesData sdes)
        {
            lock (participants)
            {
                lock (streamsAndIPs)
                {
                    IPStreamPairHashtable.IPStreamPair ipsp = streamsAndIPs[ssrc];
                    Debug.Assert(ipsp != null);

                    if (ipsp.stream == null)
                    {
                        ipsp.stream = RtpStream.CreateStream2(rtpListener, ssrc, ipaddress, sdes);

                        RaiseRtpStreamAddedEvent(ipsp.stream);
                    }
                    else // Update
                    {
                        ipsp.stream.Stale = 0;
                        ipsp.stream.Properties.UpdateData(sdes);
                    }
                }
            }
        }        
Example #29
0
 internal RtpStreamFFec(RtpListener rtpListener, uint ssrc, SdesData sdes, PayloadType pt, ushort fecPxExp)
     : base(rtpListener, ssrc, sdes, pt)
 {
     fecPercent = fecPxExp;
     pcFecType  = 2;
 }
Example #30
0
 /// <summary>
 /// Write a report (ssrc + SdesData) to the buffer
 /// </summary>
 /// <param name="ssrc">uint was cast to int because that's how BufferChunk writes 32 bits</param>
 /// <param name="props"></param>
 private void WriteReportToBuffer(BufferChunk buffer, uint ssrc, SdesData props)
 {
     buffer += ssrc;
     props.WriteDataToBuffer(buffer);
 }
Example #31
0
 internal SdesReport(uint ssrc, SdesData sdes)
 {
     this.ssrc = ssrc;
     this.sdes = sdes;
 }
Example #32
0
        private void ReadReportFromBuffer(BufferChunk buffer)
        {
            uint ssrc = buffer.NextUInt32();
            SdesData props = new SdesData(buffer);

            AddReport(new SdesReport(ssrc, props));
        }
Example #33
0
 internal SdesReport(uint ssrc, SdesData sdes)
 {
     this.ssrc = ssrc;
     this.sdes = sdes;
 }
Example #34
0
        internal RtpSender(IRtpSession rtpSession, string name, PayloadType payloadType, Hashtable priExns)
        {
            if(Thread.CurrentThread.Name == null)
            {
                Thread.CurrentThread.Name = "RtpSender - " + name;
            }

            this.rtpSession = rtpSession;
            this.payloadType = payloadType;

            // Leave everything but CName and Name blank in order to reduce Rtcp bandwidth
            sdes = new SdesData(rtpSession.Sdes.CName, name);

            // Add private extensions
            sdes.SetPrivateExtension(Rtcp.PEP_SOURCE, Rtcp.PED_STREAM);
            sdes.SetPrivateExtension(Rtcp.PEP_PAYLOADTYPE, ((int)payloadType).ToString());

            InitializeNetwork();
            InitializeFrame();
            InitializePerformanceCounters();

            // This needs to be called after InitializeNetwork
            if( priExns != null )
            {
                foreach(DictionaryEntry de in priExns)
                {
                    sdes.SetPrivateExtension((string)de.Key, (string)de.Value);
                }

                string dbpString = (string)priExns[Rtcp.PEP_DBP];
                if( dbpString != null )
                    DelayBetweenPackets = short.Parse(dbpString);
            }

            ResetState();
        }
Example #35
0
 public SdesReport(uint ssrc, SdesData sdes)
 {
     this.ssrc = ssrc;
     this.sdes = sdes;
 }
Example #36
0
 /// <summary>
 /// Construct an SDES packet from existing properties
 /// </summary>
 public SdesPacket(uint ssrc, SdesData props) : base(Rtcp.PacketType.SDES)
 {
     AddReport(new SdesReport(ssrc, props));
 }
Example #37
0
 /// <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>
 public RtpParticipant(SdesData data, IPAddress ipAddress) : base(data)
 {
     this.ipAddress = ipAddress;
     SetPrivateExtension(Rtcp.PEP_SOURCE, Rtcp.PED_PARTICIPANT);
 }
Example #38
0
        /// <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);
                    }

                    IPStreamPairHashtable.IPStreamPair ipsp = streamsAndIPs[ssrc];
                    Debug.Assert(ipsp != null);

                    if(ipsp.stream == null)
                    {
                        ipsp.stream = RtpStream.CreateStream(rtpListener, ssrc, sdes);

                        ipsp.stream.PacketTransform = this.packetTransform;

                        ssrcToParticipant[ssrc] = participant;
                        participant.AddSSRC(ssrc);

                        RaiseRtpStreamAddedEvent(ipsp.stream);
                    }
                    else // Update
                    {
                        ipsp.stream.Stale = 0;
                        ipsp.stream.Properties.UpdateData(sdes);
                    }
                }
            }
        }