示例#1
0
        /// <summary>
        /// Audio frames are generally contained within a single RTP packet. This method is a shortcut
        /// to construct a frame from a single RTP packet.
        /// </summary>
        public static RTPFrame MakeSinglePacketFrame(RTPPacket rtpPacket)
        {
            RTPFrame frame = new RTPFrame();

            frame.AddRTPPacket(rtpPacket);
            frame.Timestamp = rtpPacket.Header.Timestamp;

            return(frame);
        }
        private void ProcessRTPPackets()
        {
            try
            {
                Thread.CurrentThread.Name = "rtspclient-rtp";

                _lastRTPReceivedAt = DateTime.Now;
                _lastBWCalcAt      = DateTime.Now;

                while (!_isClosed)
                {
                    while (_rtspSession.HasRTPPacket())
                    {
                        RTPPacket rtpPacket = _rtspSession.GetNextRTPPacket();

                        if (rtpPacket != null)
                        {
                            _lastRTPReceivedAt     = DateTime.Now;
                            _bytesSinceLastBWCalc += RTPHeader.MIN_HEADER_LEN + rtpPacket.Payload.Length;

                            if (_rtpTrackingAction != null)
                            {
                                double bwCalcSeconds = DateTime.Now.Subtract(_lastBWCalcAt).TotalSeconds;
                                if (bwCalcSeconds > BANDWIDTH_CALCULATION_SECONDS)
                                {
                                    _lastBWCalc           = _bytesSinceLastBWCalc * 8 / bwCalcSeconds;
                                    _lastFrameRate        = _framesSinceLastCalc / bwCalcSeconds;
                                    _bytesSinceLastBWCalc = 0;
                                    _framesSinceLastCalc  = 0;
                                    _lastBWCalcAt         = DateTime.Now;
                                }

                                var    abbrevURL       = (_url.Length <= 50) ? _url : _url.Substring(0, 50);
                                string rtpTrackingText = String.Format(
                                    "Url: {0}\r\nRcvd At: {1}\r\nSeq Num: {2}\r\nTS: {3}\r\nPayoad: {4}\r\nFrame Size: {5}\r\nBW: {6}\r\nFrame Rate: {7}",
                                    abbrevURL, DateTime.Now.ToString("HH:mm:ss:fff"), rtpPacket.Header.SequenceNumber,
                                    rtpPacket.Header.Timestamp,
                                    ((SDPMediaFormatsEnum)rtpPacket.Header.PayloadType).ToString(),
                                    _lastFrameSize + " bytes", _lastBWCalc.ToString("0.#") + "bps",
                                    _lastFrameRate.ToString("0.##") + "fps");
                                _rtpTrackingAction(rtpTrackingText);
                            }

                            if (rtpPacket.Header.Timestamp < _lastCompleteFrameTimestamp)
                            {
                                Debug.WriteLine(
                                    "Ignoring RTP packet with timestamp " + rtpPacket.Header.Timestamp +
                                    " as it's earlier than the last complete frame.");
                            }
                            else
                            {
                                while (_frames.Count > MAX_FRAMES_QUEUE_LENGTH)
                                {
                                    var oldestFrame = _frames.OrderBy(x => x.Timestamp).First();
                                    _frames.Remove(oldestFrame);
                                    Debug.WriteLine(
                                        "Receive queue full, dropping oldest frame with timestamp " +
                                        oldestFrame.Timestamp + ".");
                                }

                                var frame = _frames.Where(x => x.Timestamp == rtpPacket.Header.Timestamp)
                                            .SingleOrDefault();

                                if (frame == null)
                                {
                                    frame = new RTPFrame()
                                    {
                                        Timestamp = rtpPacket.Header.Timestamp,
                                        HasMarker = rtpPacket.Header.MarkerBit == 1
                                    };
                                    frame.AddRTPPacket(rtpPacket);
                                    _frames.Add(frame);
                                }
                                else
                                {
                                    frame.HasMarker = (rtpPacket.Header.MarkerBit == 1);
                                    frame.AddRTPPacket(rtpPacket);
                                }

                                if (frame.IsComplete)
                                {
                                    // The frame is ready for handing over to the UI.
                                    byte[] imageBytes = frame.GetFramePayload();

                                    _lastFrameSize = imageBytes.Length;
                                    _framesSinceLastCalc++;

                                    _lastCompleteFrameTimestamp = rtpPacket.Header.Timestamp;
                                    //System.Diagnostics.Debug.WriteLine("Frame ready " + frame.Timestamp + ", sequence numbers " + frame.StartSequenceNumber + " to " + frame.EndSequenceNumber + ",  payload length " + imageBytes.Length + ".");
                                    //logger.Debug("Frame ready " + frame.Timestamp + ", sequence numbers " + frame.StartSequenceNumber + " to " + frame.EndSequenceNumber + ",  payload length " + imageBytes.Length + ".");
                                    _frames.Remove(frame);

                                    // Also remove any earlier frames as we don't care about anything that's earlier than the current complete frame.
                                    foreach (var oldFrame in _frames
                                             .Where(x => x.Timestamp <= rtpPacket.Header.Timestamp).ToList())
                                    {
                                        Debug.WriteLine(
                                            "Discarding old frame for timestamp " + oldFrame.Timestamp + ".");
                                        logger.Warn("Discarding old frame for timestamp " + oldFrame.Timestamp + ".");
                                        _frames.Remove(oldFrame);
                                    }

                                    if (OnFrameReady != null)
                                    {
                                        try
                                        {
                                            //if (frame.FramePackets.Count == 1)
                                            //{
                                            //    // REMOVE.
                                            //    logger.Warn("Discarding frame as there should have been more than 1 RTP packets.");
                                            //}
                                            //else
                                            //{
                                            //System.Diagnostics.Debug.WriteLine("RTP frame ready for timestamp " + frame.Timestamp + ".");
                                            OnFrameReady(this, frame);
                                            //}
                                        }
                                        catch (Exception frameReadyExcp)
                                        {
                                            logger.Error("Exception RTSPClient.ProcessRTPPackets OnFrameReady. " +
                                                         frameReadyExcp);
                                        }
                                    }
                                }
                            }
                        }
                    }

                    if (DateTime.Now.Subtract(_lastRTPReceivedAt).TotalSeconds > RTP_TIMEOUT_SECONDS)
                    {
                        logger.Warn("No RTP packets were received on RTSP session " + _rtspSession.SessionID + " for " +
                                    RTP_TIMEOUT_SECONDS + ". The session will now be closed.");
                        Close();
                    }
                    else
                    {
                        Thread.Sleep(1);
                    }
                }
            }
            catch (Exception excp)
            {
                logger.Error("Exception RTSPClient.ProcessRTPPackets. " + excp);
            }
        }