コード例 #1
0
ファイル: UDPReceive.cs プロジェクト: CristianCosta/Kinect
    public static void sendData(byte[] data, IPEndPoint remoteEndPoint)
    {
        try{

            if (client == null){
                client = new UdpClient();
            }

            //remoteEndPoint = new IPEndPoint(IPAddress.Parse(LobbyGUI.serverIP), port);
            byte[] bytes = BitConverter.GetBytes(data.Length);

            byte[] mensaje = new byte[data.Length + 4];
            mensaje[0] = bytes[0];
            mensaje[1] = bytes[1];
            mensaje[2] = bytes[2];
            mensaje[3] = bytes[3];

            for (int i = 0 ; i < data.Length ; i++){
                mensaje[i+4] = data[i];
            }

            RtpPacket rtpPacket = new RtpPacket();
            rtpPacket.setData(mensaje);

            DateTime aux = System.DateTime.Now;
            Int16 hour = (Int16)aux.Hour;
            Int16 minute = (Int16)aux.Minute;
            Int16 second = (Int16)aux.Second;
            Int16 milisecond = (Int16)aux.Millisecond;
            UInt32 timestamp = (UInt32)(hour*10000000+minute*100000+second*1000+milisecond);
            rtpPacket.setTimestamp(timestamp);

            lock(receiveLock) {
                client.Send(rtpPacket.encode(), rtpPacket.encode().Length, remoteEndPoint);
            }

        }catch (Exception err){
            Console.WriteLine(err.ToString());
        }
    }
コード例 #2
0
ファイル: RtpClient.cs プロジェクト: qinpengit/net7mma-111212
        /// <summary>
        /// Adds a packet to the queue of outgoing RtpPackets
        /// </summary>
        /// <param name="packet">The packet to enqueue</param> (used to take the RtpCLient too but we can just check the packet payload type
        public void EnquePacket(RtpPacket packet)
        {
            if (IsDisposed || m_StopRequested || packet == null || packet.IsDisposed) return;

            //Add a the packet to the outgoing
            m_OutgoingRtpPackets.Add(packet);
        }
コード例 #3
0
ファイル: RtpClient.cs プロジェクト: qinpengit/net7mma-111212
            /// <summary>
            /// Performs checks on the packet which can be overriden in a derrived implementation
            /// </summary>
            /// <param name="packet"></param>
            /// <returns></returns>
            public virtual bool ValidatePacketAndUpdateSequenceNumber(RtpPacket packet)
            {
                /*NOTE :
                 * http://www.ietf.org/rfc/rfc3551.txt
                 *
                  Static payload type 13 was assigned to the Comfort Noise (CN) payload format defined in RFC 3389.
                  Payload type 19 was marked reserved because it had been temporarily allocated to an earlier version of Comfort Noise
                  present in some draft revisions of this document.
                 */

                int payloadLength = packet.Payload.Count;

                //If there is no Payload return, this prevents injection by utilizing just a RtpHeader which happens to be valid.
                //I can think of no good reason to allow this in this implementation, if required dervive and ensure that RTCP is not better suited for whatever is being done.
                //The underlying goto CheckSequenceNumber is what is used to performed this check currently.
                //if (payloadLength == 0 && packet.PayloadType != 13) return false;
                //else if (packet.PayloadType == 13  || packet.PayloadType == 19) goto CheckSequenceNumber;

                if (packet.Header.IsCompressed || packet.PayloadType == 13) goto CheckSequenceNumber;

                // RFC 3550 A.1. Notes: Each TransportContext instance may be better suited to have a structure which defines this logic.

                //o  RTP version field must equal 2.

                if (packet.Version != Version) return false;

                //o  The payload type must be known, and in particular it must not be equal to SR or RR.

                if (packet.PayloadType == Rtcp.SendersReport.PayloadType || packet.PayloadType == Rtcp.ReceiversReport.PayloadType) return false;

                //o  If the P bit is set, Padding must be less than the total packet length minus the header size.
                if (packet.Padding && payloadLength > 0 && packet.PaddingOctets > payloadLength) return false;

                ///  o  The length of the packet must be consistent with CC and payload type (if payloads have a known length this is checked with the IsComplete property).
                if (packet.ContributingSourceCount > 0 && payloadLength < packet.ContributingSourceCount * 4) return false;

                //Only performed to ensure validity
                if (packet.Extension)
                {
                    //o  The X bit must be zero if the profile does not specify that the
                    //   header extension mechanism may be used.
                    //   Otherwise, the extension
                    //   length field must be less than the total packet size minus the
                    //   fixed header length and padding.
                    if (packet.ExtensionOctets > payloadLength) return false;
                }

                #region Notes on RFC3550 Implementation

                /*
                  The validity check can be made stronger requiring more than two
                    packets in sequence.  The disadvantages are that a larger number of
                    initial packets will be discarded (or delayed in a queue) and that
                    high packet loss rates could prevent validation.  However, because
                    the RTCP header validation is relatively strong, if an RTCP packet is
                    received from a source before the data packets, the count could be
                    adjusted so that only two packets are required in sequence.  If
                    initial data loss for a few seconds can be tolerated, an application
                    MAY choose to discard all data packets from a source until a valid
                    RTCP packet has been received from that source.
                 *
                 * Please Note: This is why packets are stored in the CurrentFrame of the TransportContext. (To avoid loss where possible)
                 * A property exists for disabling the handling of RtpPackets which are incoming or outgoing.
                 *
                 * Derived implementations may want to perform additional checks noted below inter alia.
                 *
                 Depending on the application and encoding, algorithms may exploit
                   additional knowledge about the payload format for further validation.
                   For payload types where the timestamp increment is the same for all
                   packets,
                 * the timestamp values can be predicted from the previous                  ------ Note:
                   packet received from the same source using the sequence number           ------ The source is not valid until MIN_SEQUENTIAL have been received.
                   difference (assuming no change in payload type).                         ------ This implementation maskes no assumptions about the Timestamp property.

                   A strong "fast-path" check is possible since with high probability       ------ Note:
                   the first four octets in the header of a newly received RTP data         ------  This implementation is engineered with the state of mind that certain profiles
                   packet will be just the same as that of the previous packet from the     ------  may REQUIRE that Padding or Extensions only be present in RtpPacket N of a RtpFrame X
                   same SSRC except that the sequence number will have increased by one.    ------  Thus this check is NOT performed. The SequenceNumber of the TransportContext is assigned in the HandleIncomingRtpPacket function AFTER the sender is valid.

                 * Similarly, a single-entry cache may be used for faster SSRC lookups      ------ Note: This implementation utilizes the single-entry cache once MIN_SEQUENTIAL have been received.
                   in applications where data is typically received from one source at a    ------ In scenarios with more then 1 participant is required a Conference class is used.
                   time.
                 */

                #endregion

                CheckSequenceNumber:
                //Return the result of processing the verification of the sequence number according the RFC3550 A.1
                if (UpdateSequenceNumber(packet.SequenceNumber))
                {
                    SequenceNumber = packet.SequenceNumber;
                    return true;
                }

                return false;
            }
コード例 #4
0
ファイル: RedundantRtpFrame.cs プロジェクト: acinep/net7mma-1
        //Should return an Enumerable<RtpPacket> and should ask for bytesPerPayload.
        /// <summary>
        /// Given many packets a single packet is made in accordance with RFC2198
        /// </summary>
        /// <param name="packets"></param>
        /// <returns></returns>
        public static RtpPacket Packetize(RtpPacket[] packets) //todo needs a timestamp of the packet created...
        {
            //Make one packet with the data of all packets
            //Must also include headers which is 4 * packets.Length + 1

            int packetsLength;

            if (Common.Extensions.Array.ArrayExtensions.IsNullOrEmpty(packets, out packetsLength))
            {
                return(null);
            }

            //4 byte headers are only needed if there are more than 1 packet.
            int headersNeeded = packetsLength - 1;

            //Calulcate the size of the single packet we will need.
            int size = RtpHeader.Length + ((4 * headersNeeded) + 1);

            //Create the packet with the known length
            RtpPacket result = new RtpPacket(new byte[size], 0); //RtpHeader.Length + 4 * packetsLength - (packetsLength * RtpHeader.Length) + 1

            int bitOffset = 0;

            int packetIndex = 0;

            bool marker = false;

            RtpPacket packet;

            int payloadDataOffset = (4 * headersNeeded) + 1;

            int blockLen;

            //For all but the last packet write a full header
            for (int e = headersNeeded; packetIndex < e; ++packetIndex)
            {
                packet = packets[packetIndex];

                //csrc Extensions and padding included...
                blockLen = packet.Payload.Count;

                //Write the payloadType
                Common.Binary.WriteBitsMSB(result.Payload.Array, ref bitOffset, (ulong)packet.PayloadType, 7);

                //Should be offset from timestamp
                Common.Binary.WriteBitsMSB(result.Payload.Array, ref bitOffset, (ulong)packet.Timestamp, 14);

                //Write the BlockLength
                Common.Binary.WriteBitsMSB(result.Payload.Array, ref bitOffset, (ulong)blockLen, 10);

                //Copy the data
                System.Array.Copy(packet.Payload.Array, packet.Payload.Offset, result.Payload.Array, payloadDataOffset, blockLen);

                //Move the payloadDataOffset for the block of data just copied.
                payloadDataOffset += blockLen;

                //If the marker was not already found check for it
                if (false == marker && packet.Marker)
                {
                    marker = true;
                }
            }

            //Write the last header (1 byte with (F)irst bit set and PayloadType

            //Get the packet
            packet = packets[packetIndex];

            //Could just write 0x80 | PayloadType at payloadStart - 1
            //result.Payload.Array[payloadStart - 1] = (byte)(0x80 | packet.PayloadType);

            //Set the (F)irst bit
            Common.Binary.WriteBitsMSB(result.Payload.Array, ref bitOffset, (ulong)1, 1);

            //Write the payloadType
            Common.Binary.WriteBitsMSB(result.Payload.Array, ref bitOffset, (ulong)packets[packetIndex].PayloadType, 7);

            //Copy the data
            System.Array.Copy(packet.Payload.Array, packet.Payload.Offset, result.Payload.Array, payloadDataOffset, packet.Payload.Count);

            //Set the Timestamp
            result.Timestamp = packet.Timestamp;

            //Set the SequenceNumber
            result.Timestamp = packet.SequenceNumber;

            //Set the marker bit if it needs to be set.
            result.Marker = marker || packet.Marker;

            //Return the single packet created.
            return(result);
        }
コード例 #5
0
ファイル: RtpListener.cs プロジェクト: kthompson/RtpLib
 protected virtual void OnMarkerReceived(RtpPacket packet)
 {
     var handler = MarkerReceived;
     if (handler != null)
         handler(this, new EventArgs<RtpPacket>(packet));
 }
コード例 #6
0
        /// <summary>
        /// Called for each RtpPacket received in the source RtpClient
        /// </summary>
        /// <param name="client">The RtpClient from which the packet arrived</param>
        /// <param name="packet">The packet which arrived</param>
        internal void OnSourceRtpPacketRecieved(object client, RtpPacket packet)
        {
            //If the packet is null or not allowed then return
            if (packet == null || packet.IsDisposed || m_RtpClient == null) return;

            //Get a source context
            RtpClient.TransportContext context = null, sourceContext = GetSourceContext(packet);

            //Get the sourceContext incase the same payload type was used more then once otherwise fallback to the context for the Payloadtype
            if (sourceContext != null)
            {
                context = m_RtpClient.GetContextForMediaDescription(sourceContext.MediaDescription);
            }
            else
            {
                sourceContext = context = m_RtpClient.GetContextByPayloadType(packet.PayloadType);
            }

            //If there is no context then don't send.
            //OR
            //If the context already sent the packet don't send                       //(make sure the sequence number didn't wrap)
            if (context == null || context.SequenceNumber >= packet.SequenceNumber && sourceContext.SequenceNumber != packet.SequenceNumber) return;

            if (PacketBuffer.ContainsKey(sourceContext.SynchronizationSourceIdentifier))
            {
                PacketBuffer.Add(sourceContext.SynchronizationSourceIdentifier, packet);
            }
            else if (m_RtpClient != null)
            {
                //Send packet on Client Thread
                m_RtpClient.EnquePacket(packet);
            }
        }
コード例 #7
0
        void m_RtpClient_RecievedRtp(object sender, RtpPacket packet)
        {
            if (packet == null || packet.IsDisposed) return;
            else m_Server.Logger.LogException(new Exception("Recieved Rtp PacketType: " + packet.PayloadType + " - " + " Packet Ssrc = " + packet.SynchronizationSourceIdentifier));

            var context = m_RtpClient.GetContextForPacket(packet);

            if (context == null) m_Server.Logger.LogException(new Exception("Unknown Rtp Packet Ssrc = " + packet.SynchronizationSourceIdentifier));
            else m_Server.Logger.LogException(new Exception("Rtp Packet Ssrc = " + packet.SynchronizationSourceIdentifier + " RemoteId = " + context.RemoteSynchronizationSourceIdentifier + " LocalId = " + context.SynchronizationSourceIdentifier));

            //Crash... check bugs in compiler.. emited wrong instruction...
            //m_Server.Logger.LogException(new Exception("Recieved PacketType: " + packet.PayloadType + " - " + implementation != null ? implementation.Name : string.Empty));
        }
コード例 #8
0
ファイル: UDPReceive.cs プロジェクト: CristianCosta/Kinect
    private static void ReceiveData()
    {
        while (isSuscribed()) {
            try {

           			Security.PrefetchSocketPolicy(LobbyGUI.serverIP, 9933);
                IPEndPoint anyIP = new IPEndPoint(IPAddress.Any, 0);
                if (client == null){
                    client = new UdpClient();
                }

                lock(receiveLock) {
                    mensajeCrudo = client.Receive(ref anyIP);
                }

                RtpPacket rtpPacket = new RtpPacket(mensajeCrudo);
                mensaje = rtpPacket.getData();

                byte[] bytes = new byte[4];
                bytes[0] = mensaje[0];
                bytes[1] = mensaje[1];
                bytes[2] = mensaje[2];
                bytes[3] = mensaje[3];

                Int16 largo = BitConverter.ToInt16(bytes,0);

                data = new byte[largo];
                for ( int i = 0 ; i < data.Length ; i++){
                    data[i] = 	mensaje[i+4];
                }

                Debug.Log("<<< Se recibe " + data.Length + " Bytes");
                FrameDispatcher.enqueueFrame(new ShowImages(data));
            }
            catch (Exception err)  {
                Console.WriteLine(err.ToString());
            }
        }
    }
コード例 #9
0
ファイル: RtpClient.cs プロジェクト: qinpengit/net7mma-111212
        /// <summary>
        /// Updates counters and fires a FrameChanged event if required.
        /// </summary>
        /// <param name="sender">The object which raised the event</param>
        /// <param name="packet">The RtpPacket to handle</param>
        protected internal virtual void HandleIncomingRtpPacket(object/*RtpClient*/ sender, RtpPacket packet)
        {
            //Determine if the incoming packet should be handled
            if (false == HandleIncomingRtpPackets || false == RtpEnabled || IsDisposed || packet == null || packet.IsDisposed) return;

            //Fire an event now to let subscribers know a packet has arrived
            OnRtpPacketReceieved(packet);

            //Not supported at the moment
            if (packet.Header.IsCompressed)
            {
                Media.Common.ILoggingExtensions.Log(Logger, InternalId + "HandleIncomingRtpPacket Compressed Packet");

                return;
            }

            //Get the transportContext for the packet by the sourceId then by the payload type of the RtpPacket, not the SSRC alone because it may have not yet been defined.
            //Noting that this is not per RFC3550
            //This is because this implementation allows for the value 0 to be used as a discovery mechanism.
            TransportContext transportContext = GetContextForPacket(packet);

            //If the context is still null
            if (transportContext == null)
            {
                Media.Common.ILoggingExtensions.Log(Logger, InternalId + "HandleIncomingRtpPacket Unaddressed RTP Packet " + packet.SynchronizationSourceIdentifier + " PT =" + packet.PayloadType + " len =" + packet.Length);

                //Do nothing else.
                return;
            }

            //Cache the payload type of the packet being handled
            int payloadType = packet.PayloadType;

            //If the packet payload type has not been
            if (false == transportContext.MediaDescription.PayloadTypes.Contains(payloadType))
            {
                Media.Common.ILoggingExtensions.Log(Logger, InternalId + "HandleIncomingRtpPacket RTP Packet PT =" + packet.PayloadType + " is not in Media Description. (" + transportContext.MediaDescription.MediaDescriptionLine + ") ");

                //Do nothing else.
                return;
            }

            //Cache the ssrc
            int partyId = packet.SynchronizationSourceIdentifier;

            //Check for a collision
            if (partyId == transportContext.SynchronizationSourceIdentifier)
            {
                //Handle it
                HandleCollision(transportContext);
            }

            #region Unused [Handles Client InDiscovery When IsValid is false]

            //////If the context is NOT valid AND the context is in discovery mode of the remote party
            ////if (false == transportContext.IsValid && transportContext.InDiscovery)
            ////{
            ////    //Assign an id at this time
            ////    transportContext.RemoteSynchronizationSourceIdentifier = partyId;
            ////}

            #endregion

            //If the packet was not addressed to the context but the context is valid AND the context is NOT in discovery mode.
            if (partyId != transportContext.RemoteSynchronizationSourceIdentifier
                &&
                transportContext.IsValid)
            {

                //Reset the state if not discovering
                if (false == transportContext.InDiscovery)
                {
                    Media.Common.ILoggingExtensions.Log(Logger, InternalId + "HandleIncomingRtpPacket SSRC Mismatch @ " + transportContext.SynchronizationSourceIdentifier + "<->" + transportContext.RemoteSynchronizationSourceIdentifier + "||" + partyId + ". ResetState");

                    transportContext.ResetState();
                }

                //Assign the id of the remote party.
                transportContext.RemoteSynchronizationSourceIdentifier = partyId;

                Media.Common.ILoggingExtensions.Log(Logger, InternalId + "HandleIncomingRtpPacket Set RemoteSynchronizationSourceIdentifier @ " + transportContext.SynchronizationSourceIdentifier + " to=" + transportContext.RemoteSynchronizationSourceIdentifier);
            }

            //Don't worry about overflow.
            unchecked
            {
                int packetLength = packet.Length;

                //If the packet is not valid then
                if (false == transportContext.ValidatePacketAndUpdateSequenceNumber(packet) ||
                    packetLength > transportContext.MaximumPacketSize ||
                    packetLength < transportContext.MinimumPacketSize)
                {
                    //Increment for a failed reception
                    ++transportContext.m_FailedRtpReceptions;

                    Media.Common.ILoggingExtensions.Log(Logger, InternalId + "HandleIncomingRtpPacket Failed Reception " +
                             "(= " + transportContext.m_FailedRtpReceptions + ") @" + transportContext.SynchronizationSourceIdentifier +
                             " Context seq=" + transportContext.SequenceNumber +
                             " Packet pt=" + packet.PayloadType +
                            " seq=" + packet.SequenceNumber +
                            " len= " + packet.Length);

                    //Only proceeed further in the context is valid
                    //if(false == transportContext.IsValid) return;
                }

                //Increment RtpPacketsReceived for the context relating to the packet.
                ++transportContext.RtpPacketsReceived;

                //If InDiscovery and IsValid then stop InDiscovery by setting the remote id
                if (transportContext.InDiscovery && transportContext.IsValid) transportContext.RemoteSynchronizationSourceIdentifier = partyId;

                //The counters for the bytes will now be be updated (without the 12 octets of the header)
                //increment the counters (Only use the Payload.Count per the RFC) (new Erratta Submitted)
                //http://www.rfc-editor.org/errata_search.php?rfc=3550
                transportContext.RtpBytesRecieved += packet.Payload.Count;

                //Please note due to the 'consensus' achieved for this standard (RFC 1889 / RFC3550 / RFC3551)
                //The counters for the rtp bytes sent are specifically counted only to reveal average data rate...
                //A Senders report may only indicate the values which are allowed in the rfc. (Probably so middle boxes can't be detected)
                //Otherwise it's not complaint but no one will figure out how or why since its not supposed to effect annex calulcations...
                //Additionally the jitter caluclations would be messed up in most cases where a sourcelist or padding is used because it doesn't take those values into account
                //This implemenation doesn't suffer from this non-sense.

                transportContext.RfcRtpBytesRecieved += packet.Length - (packet.Header.Size + packet.HeaderOctets + packet.PaddingOctets);

                //Set the time when the first RtpPacket was received if required
                if (transportContext.m_FirstPacketReceived == DateTime.MinValue) transportContext.m_FirstPacketReceived = packet.Created;

                //Update the SequenceNumber and Timestamp and calulcate Inter-Arrival (Mark the context as active)
                transportContext.UpdateJitterAndTimestamp(packet);

                //Set the last rtp in after inter-arrival has been calculated.
                transportContext.m_LastRtpIn = packet.Created;

                //If the instance does not handle frame changed events then return
                if (false == HandleFrameChanges) return;

                //Take local variable of frame if multiple threads may access this logic
                //ThreadLocal<RtpFrame> currentFrame = new ThreadLocal<RtpFrame>(()=>transportContext.CurrentFrame, false), lastFrame = new ThreadLocal<RtpFrame>(()=>transportContext.LastFrame, false)

                //Note ALSO
                //If the ssrc changed mid stream but the data is still somehow relevent to the lastFrame or currentFrame
                //Then the ssrc of the packet must be changed or the ssrc of the frame must be changed before adding the packet.

                //If we have not allocated a currentFrame
                if (transportContext.CurrentFrame == null)
                {
                    //make a frame
                    transportContext.CurrentFrame = new RtpFrame(payloadType, packet.Timestamp, packet.SynchronizationSourceIdentifier);
                }//Check to see if the frame belongs to the last frame
                else if (transportContext.LastFrame != null && packet.Timestamp == transportContext.LastFrame.Timestamp && transportContext.MediaDescription.PayloadTypes.Contains(payloadType))
                {
                    //Create a new packet from the localPacket so it will not be disposed when the packet is disposed.
                    if (false == transportContext.LastFrame.IsComplete)
                    {
                        //17333

                        //Handle existing frame
                        transportContext.LastFrame.TryAdd(new RtpPacket(packet.Prepare().ToArray(), 0));
                    }

                    //If the frame is complete then fire an event and make a new frame
                    if (transportContext.LastFrame.IsComplete)
                    {
                        //The LastFrame changed
                        OnRtpFrameChanged(transportContext.LastFrame);

                        //Remove
                        transportContext.LastFrame.Dispose();
                        transportContext.LastFrame = null;
                    }
                    else if (transportContext.LastFrame.Count > transportContext.LastFrame.MaxPackets)
                    {
                        //Backup of frames
                        transportContext.LastFrame.Dispose();
                        transportContext.LastFrame = null;
                    }

                    return;
                }//Check to see if the frame belongs to a new frame
                else if (transportContext.CurrentFrame != null && packet.Timestamp != transportContext.CurrentFrame.Timestamp && transportContext.MediaDescription.PayloadTypes.Contains(payloadType))
                {
                    //Dispose the last frame if available
                    if (transportContext.LastFrame != null)
                    {
                        transportContext.LastFrame.Dispose();
                        transportContext.LastFrame = null;
                    }

                    //Move the current frame to the LastFrame
                    transportContext.LastFrame = transportContext.CurrentFrame;

                    //Make a new frame in the transportChannel's CurrentFrame
                    transportContext.CurrentFrame = new RtpFrame(packet.PayloadType, packet.Timestamp, packet.SynchronizationSourceIdentifier);

                    //The LastFrame changed
                    OnRtpFrameChanged(transportContext.LastFrame);
                }

                //If there is a current frame
                if (transportContext.CurrentFrame != null)
                {
                    //If the payload of the localPacket matched the media description then create a new packet from the localPacket so it will not be disposed when the packet is disposed.
                    if (transportContext.MediaDescription.PayloadTypes.Contains(payloadType))
                    {
                        //17333

                        //Handle existing frame
                        transportContext.CurrentFrame.TryAdd(new RtpPacket(packet.Prepare().ToArray(), 0));
                    }

                    //If the frame is complete then fire an event and make a new frame
                    if (transportContext.CurrentFrame.IsComplete)
                    {
                        //Dispose the last frame
                        if (transportContext.LastFrame != null)
                        {
                            transportContext.LastFrame.Dispose();

                            transportContext.LastFrame = null;
                        }

                        //Move the current frame to the LastFrame
                        transportContext.LastFrame = transportContext.CurrentFrame;

                        //Allow for a new frame to be allocated
                        transportContext.CurrentFrame = null;

                        //The LastFrame changed
                        OnRtpFrameChanged(transportContext.LastFrame);
                    }
                    else if (transportContext.CurrentFrame.Count > transportContext.CurrentFrame.MaxPackets)
                    {
                        //Backup of frames
                        transportContext.CurrentFrame.Dispose();
                        transportContext.CurrentFrame = null;
                    }
                }
            }
        }
コード例 #10
0
ファイル: RtpClient.cs プロジェクト: qinpengit/net7mma-111212
 public int SendRtpPacket(RtpPacket packet, int? ssrc = null)
 {
     SocketError error;
     return SendRtpPacket(packet, out error, ssrc);
 }
コード例 #11
0
ファイル: RtpClient.cs プロジェクト: qinpengit/net7mma-111212
        public int SendRtpPacket(RtpPacket packet, out SocketError error, int? ssrc = null)
        {
            error = SocketError.SocketError;

            if (packet == null || packet.IsDisposed || m_StopRequested) return 0;

            TransportContext transportContext = GetContextForPacket(packet);

            //If we don't have an transportContext to send on or the transportContext has not been identified
            if (transportContext == null) return 0;

            //Ensure not sending too large of a packet
            if (packet.Length > transportContext.MaximumPacketSize) Media.Common.Extensions.Exception.ExceptionExtensions.TryRaiseTaggedException(transportContext, "See Tag. The given packet must be smaller than the value in the transportContext.MaximumPacketSize.");

            //If the mediaDescription of the context does not specify the packets payload type AND
            //if (transportContext.SynchronizationSourceIdentifier == (ssrc ?? packet.SynchronizationSourceIdentifier))
            //{
            //    //Throw an exception
            //    Media.Common.Extensions.Exceptions.ExceptionExtensions.RaiseTaggedException<RtpClient>(this, "Packet from '" + ssrc + "' PayloadType is different then the expected MediaDescription.MediaFormat Expected: '" + transportContext.MediaDescription.MediaFormat + "' Found: '" + packet.PayloadType + "'");
            //}

            //How many bytes were sent
            int sent = 0;

            #region Unused [Sends a SendersReport if one was not already]

            //Send a SendersReport before any data is sent.
            //if (transportContext.SendersReport == null && transportContext.IsRtcpEnabled) SendSendersReport(transportContext);

            #endregion

            //If the transportContext is changed to automatically update the timestamp by frequency then use transportContext.RtpTimestamp
            sent += SendData(packet.Prepare(null, ssrc, null, null).ToArray(), transportContext.DataChannel, transportContext.RtpSocket, transportContext.RemoteRtp, out error);

            if (error == SocketError.Success && sent >= packet.Length)
            {
                packet.Transferred = DateTime.UtcNow;

                OnRtpPacketSent(packet);
            }
            else
            {
                ++transportContext.m_FailedRtpTransmissions;
            }

            return sent;
        }
コード例 #12
0
 public bool Check(RtpPacket packet)
 {
     return(false);
 }
コード例 #13
0
ファイル: RedundantRtpFrame.cs プロジェクト: acinep/net7mma-1
 //Don't really need to override this, especially since the interface calls may turn out different especially considering how they are implemented...
 public override bool IsValidPacket(RtpPacket packet)
 {
     return(base.IsValidPacket(packet));
 }
コード例 #14
0
ファイル: RedundantRtpFrame.cs プロジェクト: acinep/net7mma-1
 public virtual bool IsValidPacket(RtpPacket packet)
 {
     return(IRtpProfileInformationExtensions.IsValidPacket(this, packet));
 }
コード例 #15
0
ファイル: RedundantRtpFrame.cs プロジェクト: acinep/net7mma-1
        public static bool IsValidPacket(this IRtpProfileInformation profileInfomation, RtpPacket packet)
        {
            if (Common.IDisposedExtensions.IsNullOrDisposed(packet))
            {
                return(false);
            }

            Common.MemorySegment packetData = packet.PayloadDataSegment;

            return(packetData.Count > profileInfomation.MinimumHeaderSize && packetData.Count > profileInfomation.MaximumHeaderSize);
        }
コード例 #16
0
ファイル: RtpClient.cs プロジェクト: qinpengit/net7mma-111212
 /// <summary>
 /// Selects a TransportContext for a RtpPacket by matching the packet's PayloadType to the TransportContext's MediaDescription.MediaFormat
 /// </summary>
 /// <param name="packet"></param>
 /// <returns></returns>
 public TransportContext GetContextForPacket(RtpPacket packet)
 {
     if (packet == null) return null; return GetContextBySourceId(packet.SynchronizationSourceIdentifier) ?? GetContextByPayloadType(packet.PayloadType);
 }
コード例 #17
0
 public bool IsNextInSequence(RtpPacket rtpPacket)
 {
     return(SequenceNumber > rtpPacket.SequenceNumber);
 }
コード例 #18
0
ファイル: RtpClient.cs プロジェクト: qinpengit/net7mma-111212
        /// <summary>
        /// Handles the logic of updating counters for the packet sent if <see cref="OutgoingRtpPacketEventsEnabled"/> is true.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="packet"></param>
        protected internal virtual void HandleOutgoingRtpPacket(object sender, RtpPacket packet)
        {
            if (IsDisposed || packet == null || false == HandleOutgoingRtpPackets || false == packet.Transferred.HasValue) return;

            TransportContext transportContext = GetContextForPacket(packet);

            if (transportContext == null) return;

            unchecked
            {

                //This allows detection of middle boxes, make a seperate sample, default implementation should be 'compliant'...

                //increment the counters (Only use the Payload.Count per the RFC) (new Erratta Submitted)
                //http://www.rfc-editor.org/errata_search.php?rfc=3550
                transportContext.RtpBytesSent += packet.Payload.Count;

                //Please not due to the 'consensus' achieved for this standard (RFC 1889 / RFC3550 / RFC3551)
                //The counters for the rtp bytes sent are specifically counted only to reveal average data rate...
                //A Senders report may only indicate the values which are allowed in the rfc. (Probably so middle boxes can't be detected)
                //Otherwise it's not complaint but no one will figure out how or why since its not supposed to effect annex calulcations...
                //Additionally the jitter caluclations would be messed up in most cases where a sourcelist or padding is used because it doesn't take those values into account
                //This implemenation doesn't suffer from this non-sense.

                transportContext.RfcRtpBytesSent += packet.Length - (packet.Header.Size + packet.HeaderOctets + packet.PaddingOctets);

                ++transportContext.RtpPacketsSent;

                //Sample the clock for when the last rtp packet was sent
                DateTime sent = packet.Transferred.Value;

                //Set the time the first packet was sent.
                if (transportContext.m_FirstPacketSent == DateTime.MinValue) transportContext.m_FirstPacketSent = sent;

                //If the packet was in sequence
                if (transportContext.UpdateSequenceNumber(packet.SequenceNumber))
                {
                    //Calculate inter-arrival and mark the context as active
                    transportContext.UpdateJitterAndTimestamp(packet);
                }

                //Store the time the last RtpPacket was sent.
                transportContext.m_LastRtpOut = sent;

                //Common.ILoggingExtensions.Log(Logger, "Rtp Packet Sent");
            }
        }
コード例 #19
0
ファイル: RtpClient.cs プロジェクト: qinpengit/net7mma-111212
        /// <summary>
        /// Raises the RtpPacket Handler for Recieving
        /// </summary>
        /// <param name="packet">The packet to handle</param>
        protected internal void OnRtpPacketReceieved(RtpPacket packet)
        {
            if (IsDisposed || false == IncomingRtpPacketEventsEnabled) return;

            RtpPacketHandler action = RtpPacketReceieved;

            if (action == null) return;

            foreach (RtpPacketHandler handler in action.GetInvocationList())
            {
                try { handler(this, packet); }
                catch { continue; }
            }
        }
コード例 #20
0
ファイル: RtpClient.cs プロジェクト: qinpengit/net7mma-111212
        /// <summary>
        /// Raises the RtpPacket Handler for Sending
        /// </summary>
        /// <param name="packet">The packet to handle</param>
        protected internal void OnRtpPacketSent(RtpPacket packet)
        {
            if (IsDisposed) return;

            RtpPacketSent(this, packet);
        }
コード例 #21
0
 internal RtpClient.TransportContext GetSourceContext(RtpPacket packet)
 {
     try
     {
         foreach (RtpClient.TransportContext context in Attached.Keys)
             if (packet.SynchronizationSourceIdentifier == context.RemoteSynchronizationSourceIdentifier) return context;
     }
     catch (InvalidOperationException)
     {
         return GetSourceContext(packet);
     }
     catch { }
     return null;
 }
コード例 #22
0
ファイル: RtpClient.cs プロジェクト: qinpengit/net7mma-111212
        /// <summary>
        /// Parses the data in the buffer for valid Rtcp and Rtcp packet instances.
        /// </summary>
        /// <param name="memory">The memory to parse</param>
        /// <param name="from">The socket which received the data into memory and may be used for packet completion.</param>
        protected internal virtual void ParseAndCompleteData(Common.MemorySegment memory, bool parseRtcp = true, bool parseRtp = true, int? remaining = null)
        {
            if (memory == null || memory.IsDisposed || memory.Count == 0) return;

            //handle demultiplex scenarios e.g. RFC5761
            if (parseRtcp == parseRtp && memory.Count > RFC3550.CommonHeaderBits.Size)
            {
                //Double Negitive, Demux based on PayloadType? RFC5761?

                //Distinguishable RTP and RTCP Packets
                //http://tools.ietf.org/search/rfc5761#section-4

                //Observation 1) Rtp packets can only have a PayloadType from 64-95
                //However Rtcp Packets may also use PayloadTypes 72- 76.. (Reduced size...)

                //Observation 2) Rtcp Packets defined in RFC3550 Start at 200 (SR -> Goodbye) 204,
                // 209 - 223 is cited in the above as well as below
                //RTCP packet types in the ranges 1-191 and 224-254 SHOULD only be used when other values have been exhausted.

                using (Media.RFC3550.CommonHeaderBits header = new Media.RFC3550.CommonHeaderBits(memory))
                {
                    //Just use the payload type to avoid confusion, payload types for Rtcp and Rtp cannot and should not overlap
                    parseRtcp = !(parseRtp = GetContextByPayloadType(header.RtpPayloadType) != null);

                    //Could also lookup the ssrc
                }
            }

            //Cache start, count and index
            int offset = memory.Offset, count = memory.Count, index = 0,
                //Calulcate remaining
            mRemaining = remaining ?? count - index;

            //If there is nothing left to parse then return
            if (count <= 0) return;

            //If rtcp should be parsed
            if (parseRtcp && mRemaining >= RtcpHeader.Length)
            {
                //Copy valid RtcpPackets out of the buffer now, if any packet is not complete it will be completed only if required.
                foreach (RtcpPacket rtcp in RtcpPacket.GetPackets(memory.Array, offset + index, mRemaining))
                {
                    //Raise an event for each packet.
                    //OnRtcpPacketReceieved(rtcp);
                    HandleIncomingRtcpPacket(this, rtcp);

                    //Move the offset the length of the packet parsed
                    index += rtcp.Length;

                    mRemaining -= rtcp.Length;
                }
            }

            //If rtp is parsed
            if (parseRtp && mRemaining >= RtpHeader.Length)
            {
                using (var subMemory = new Common.MemorySegment(memory.Array, offset + index, mRemaining))
                {
                    using (RtpPacket rtp = new RtpPacket(subMemory))
                    {
                        Console.WriteLine(rtp.SequenceNumber+"===================");
                        //Raise the event
                        HandleIncomingRtpPacket(this, rtp);

                        //Move the index past the length of the packet
                        index += rtp.Length;

                        //Calculate the amount of octets remaining in the segment.
                        mRemaining -= rtp.Length;
                    }
                }
            }

            //If not all data was consumed
            if (mRemaining > 0)
            {
                Media.Common.ILoggingExtensions.Log(Logger, ToString() + "@ParseAndCompleteData - Remaining= " + mRemaining);

                //Only handle when not in TCP?
                //OnInterleavedData(memory.Array, offset + index, mRemaining);
            }

            return;
        }
コード例 #23
0
ファイル: RtpListener.cs プロジェクト: kthompson/RtpLib
 protected virtual void OnInvalidPacket(RtpPacket packet)
 {
     var handler = this.InvalidPacket;
     if (handler != null)
         handler(this, new EventArgs<RtpPacket>(packet));
 }
コード例 #24
0
ファイル: RtpClient.cs プロジェクト: qinpengit/net7mma-111212
            /// <summary>
            /// Calculates RTP Interarrival Jitter as specified in RFC 3550 6.4.1.
            /// </summary>
            /// <param name="packet">RTP packet.</param>
            public void UpdateJitterAndTimestamp(RtpPacket packet)
            {
                // RFC 3550 A.8.
                //Determine the time the last packet was sent or received
                TimeSpan arrivalDifference = (packet.Transferred.HasValue ? LastRtpPacketSent : LastRtpPacketReceived);

                //Calulcate the RtpJitter using the interarrival difference and set the RtpTransit
                RtpJitter += ((RtpTransit = (uint)arrivalDifference.TotalMilliseconds) - ((RtpJitter + 8) >> 4));

                //Update the RtpTimestamp on the Context
                RtpTimestamp = packet.Timestamp;

                //Update the NtpTimestamp on the Context.
                NtpTimestamp = (long)Media.Ntp.NetworkTimeProtocol.DateTimeToNptTimestamp(packet.Transferred ?? packet.Created);

                //Context is not inactive.
                m_InactiveTime = Media.Common.Extensions.TimeSpan.TimeSpanExtensions.InfiniteTimeSpan;
            }
コード例 #25
0
ファイル: RtpListener.cs プロジェクト: kthompson/RtpLib
        protected virtual void OnSequencedPacketReceived(RtpPacket packet)
        {
            var handler = SequencedPacketReceived;

            if (handler != null)
                handler(this, new EventArgs<RtpPacket>(packet));
        }
コード例 #26
0
ファイル: RedundantRtpFrame.cs プロジェクト: acinep/net7mma-1
        /// <summary>
        /// Given a packet using the redundant audio format, the expanded rtp packets are derived from the contents.
        /// </summary>
        /// <param name="packet"></param>
        /// <param name="shouldDispose"></param>
        /// <returns></returns>
        public static System.Collections.Generic.IEnumerable <RtpPacket> GetPackets(RtpPacket packet, bool shouldDispose = true)
        {
            if (Common.IDisposedExtensions.IsNullOrDisposed(packet))
            {
                yield break;
            }

            int headerOctets = packet.HeaderOctets,
                offset = packet.Payload.Offset + headerOctets, startOffset = offset,
                remaining = packet.Payload.Count - (headerOctets + packet.PaddingOctets),
                endHeaders = remaining, headersContained = 0;

            //If there are not enough bytes for the profile header break.
            if (remaining < Common.Binary.BytesPerInteger)
            {
                yield break;
            }

            byte toCheck;

            //Iterare from the offset of the end of the rtp header until the end of data in the payload
            while (remaining >= Common.Binary.BytesPerInteger)
            {
                // 0                   1                    2                   3
                // 0 1 2 3 4 5 6 7 8 9 0 1 2 3  4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
                //+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                //|F|   block PT  |  timestamp offset         |   block length    |
                //+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

                toCheck = packet.Payload.Array[offset];

                //Check for (F)irst bit
                if ((toCheck & 0x80) != 0)
                {
                    //Store the offset of the last header.
                    endHeaders = offset;

                    //This byte does not belong to the data.
                    --remaining;

                    break;
                }

                //Increment for the header contained.
                ++headersContained;

                //Decrement for the header read.
                remaining -= Common.Binary.BytesPerInteger;

                //Move by 4 bytes beause the size of the header is 4 bytes.
                offset += Common.Binary.BytesPerInteger;
            }

            //Nothing more to return
            if (remaining < 0)
            {
                yield break;
            }

            Common.MemorySegment tempPayload;

            Rtp.RtpHeader tempHeader;

            RtpPacket tempResult;

            int tempPayloadType, tempTimestamp, tempBlockLen;

            bool marker = packet.Marker;

            //Start at the offset in bits of the end of header.
            if (headersContained > 0)
            {
                for (int headOffset = startOffset, i = 0, bitOffset = Common.Binary.BytesToBits(ref headOffset); i < headersContained; ++i)
                {
                    //Read the payloadType out of the header
                    tempPayloadType = (int)Common.Binary.ReadBitsMSB(packet.Payload.Array, Common.Binary.BytesToBits(ref headOffset) + 1, 7);

                    //Read the timestamp offset  from the header
                    tempTimestamp = (int)Common.Binary.ReadBitsMSB(packet.Payload.Array, ref bitOffset, 10);

                    //Read the blockLength from the header
                    tempBlockLen = (int)Common.Binary.ReadBitsMSB(packet.Payload.Array, ref bitOffset, 14);

                    //If there are less bytes in the payload than remain in the block stop
                    //if (remaining < tempBlockLen) break;

                    //Get the payload
                    Common.MemorySegment payload = new Common.MemorySegment(packet.Payload.Array, Common.Binary.BitsToBytes(ref bitOffset), tempBlockLen, shouldDispose);

                    //Create the header
                    Rtp.RtpHeader header = new RtpHeader(packet.Version, false, false, marker, tempPayloadType, 0, packet.SynchronizationSourceIdentifier,
                                                         packet.SequenceNumber,
                                                         packet.Timestamp + tempTimestamp,
                                                         shouldDispose);

                    //Create the packet
                    RtpPacket result = new RtpPacket(header, payload, shouldDispose);

                    //Return the packet
                    yield return(result);

                    //Move the offset
                    bitOffset += Common.Binary.BytesToBits(ref tempBlockLen);

                    //Remove the blockLength from the count
                    remaining -= tempBlockLen;
                }
            }

            //If there is anymore data it's values are defined in the header of the given packet.

            //Read the payloadType out of the headers area (1 bit after the end of headers) 7 bits in size
            tempPayloadType = (int)Common.Binary.ReadBitsMSB(packet.Payload.Array, Common.Binary.BytesToBits(ref startOffset) + 1, 7);

            //Get the payload of the temp packet, the blockLen is given by the count in this packet minus the
            tempPayload = new Common.MemorySegment(packet.Payload.Array, endHeaders, remaining, shouldDispose);

            //Create the header
            tempHeader = new RtpHeader(packet.Version, false, false, marker, tempPayloadType, 0, packet.SynchronizationSourceIdentifier,
                                       packet.SequenceNumber,
                                       packet.Timestamp,
                                       shouldDispose);

            //Create the packet
            tempResult = new RtpPacket(tempHeader, tempPayload, shouldDispose);

            //Return the packet
            yield return(tempResult);
        }