public RtpMediaConnection(MediaConfig config, MediaStatistics mediaStats)
 {
     _controlClient         = new NetClient(config.MediaServerHost, config.MediaServerControlPort);
     _rtpClient             = new NetClient(config.MediaServerHost, config.MediaServerStreamingPort, mediaStats);
     _rtpConnect            = new RtpPacketConnect();
     _rtpData               = new RtpPacketData();
     _rtpConnect.SsrcId     = config.LocalSsrcId;
     _dataReceiveBuffer     = new ByteStream(RtpPacketData.DataPacketMaxLength * 10);         // Leave room for at least 10 packets.
     _rtpPacketDataListPool = new ObjectPool <List <RtpPacketData> >(() => new List <RtpPacketData>(), list => list.Clear());
     _rtpPacketDataPool     = new ObjectPool <RtpPacketData>(() => new RtpPacketData());      // No reset action needed
     _packetBufferPool      = new ObjectPool <ByteStream>(() => new ByteStream(RtpPacketData.DataPacketMaxLength), bs => bs.Reset());
 }
Example #2
0
        public static List <RtpPacketData> GetPacketsFromData(ByteStream buffer, IObjectPool <List <RtpPacketData> > rtpPacketDataListPool, IObjectPool <RtpPacketData> rtpPacketDataPool)
        {
            // Retrieve the list from an object pool (rather than creating a new one each time that has to be garbage-collected).
            var packets = rtpPacketDataListPool.GetNext();

            while (buffer.CurrentOffset < buffer.EndOffset)
            {
                RtpPacketData  packet = rtpPacketDataPool.GetNext();
                RtpParseResult result = packet.ParsePacket(buffer);

                switch (result)
                {
                case RtpParseResult.Success:
                    // Add the packet to the list and continue processing.
                    packets.Add(packet);
                    break;

                case RtpParseResult.DataIncomplete:
                    // Tell the calling function that it can reuse the buffer after position <length>.
                    // Move the data to the beginning of the buffer (so that we can get it next time) and stop parsing.
                    Debug.Assert(buffer.CurrentOffset >= 0, "The current offset cannot be negative.");
                    Debug.Assert(buffer.RemainingBytes >= 0, "The remaining bytes cannot be negative.");
                    Buffer.BlockCopy(buffer.Data, buffer.CurrentOffset, buffer.Data, 0, buffer.RemainingBytes);
                    buffer.DataLength    = buffer.RemainingBytes;
                    buffer.DataOffset    = 0;
                    buffer.CurrentOffset = 0;
                    return(packets);

                case RtpParseResult.DataInvalid:
                    // Don't add the current packet to the list, but continue processing at the current position.
                    break;
                }
            }
            // If this is our exit point, tell the calling function that it can reuse the entire buffer.
            buffer.DataLength    = 0;
            buffer.CurrentOffset = 0;
            return(packets);
        }
        protected void HandleRtpData(byte[] buffer, int offset, int length)
        {
            if (_disposed)
            {
                return;
            }
            List <RtpPacketData> packets = null;

            try
            {
                // ks 8/23/11 - TODO: Investigate whether we can get rid of this memcpy().
                // I think we can do it by passing the dataReceiveBuffer to the NetClient class,
                // and just keeping better track of what's been processed and what hasn't.
                // Kind of like how we handle it in the media server.
                lock (_dataReceiveBuffer)
                {
                    // Copy the data in the network receive buffer to the packet receive buffer.
                    int dataLength = _dataReceiveBuffer.CurrentOffset + length;
                    _dataReceiveBuffer.TryWriteBytes(buffer, offset, length);
                    _dataReceiveBuffer.DataOffset    = 0;
                    _dataReceiveBuffer.CurrentOffset = 0;
                    _dataReceiveBuffer.DataLength    = dataLength;

                    // Pull the packets out of the packet receive buffer.
                    packets = RtpPacketData.GetPacketsFromData(_dataReceiveBuffer, _rtpPacketDataListPool, _rtpPacketDataPool);
                }
                #region Packet Processor
                foreach (var packet in packets)
                {
                    try
                    {
                        switch (packet.PayloadType)
                        {
                        case RtpPayloadType.Audio:
                            if (AudioPacketHandler != null)
                            {
                                AudioPacketHandler(packet);
                            }
                            break;

                        case RtpPayloadType.VideoFromServer:
                            if (VideoPacketHandler != null)
                            {
                                VideoPacketHandler(packet);
                            }
                            break;

                        default:
                            ClientLogger.Debug("Unexpected packetBuffer type {0}", packet.PayloadType);
                            break;
                        }
                    }
                    finally
                    {
                        _rtpPacketDataPool.Recycle(packet);
                    }
                }
                #endregion
            }
            catch (Exception ex)
            {
                ClientLogger.ErrorException(ex, "Error processing RTP data");
            }
            finally
            {
                _rtpPacketDataListPool.Recycle(packets);
            }
        }