/// <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 VideoFrameReady(RTPFrame frame) { if (OnRemoteVideoSampleReady != null) { //System.Diagnostics.Debug.WriteLine("Remote video frame received " + frame.FramePayload.Length + " bytes."); OnRemoteVideoSampleReady(frame.FramePayload, frame.FramePayload.Length); } }
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) { System.Diagnostics.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); System.Diagnostics.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.LogDebug("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()) { System.Diagnostics.Debug.WriteLine("Discarding old frame for timestamp " + oldFrame.Timestamp + "."); logger.LogWarning("Discarding old frame for timestamp " + oldFrame.Timestamp + "."); _frames.Remove(oldFrame); } if (OnFrameReady != null) { try { //if (frame.FramePackets.Count == 1) //{ // // REMOVE. // logger.LogWarning("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.LogError("Exception RTSPClient.ProcessRTPPackets OnFrameReady. " + frameReadyExcp); } } } } } } if (DateTime.Now.Subtract(_lastRTPReceivedAt).TotalSeconds > RTP_TIMEOUT_SECONDS) { logger.LogWarning("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.LogError("Exception RTSPClient.ProcessRTPPackets. " + excp); } }
/// <summary> /// Event handler for receiving an RTP frmae from the remote end of the VoIP call. /// </summary> /// <param name="rtpFrame">The RTP frame received.</param> private void RTPChannelSampleReceived(RTPFrame rtpFrame) { if (rtpFrame != null) { var framePayload = rtpFrame.GetFramePayload(); if (framePayload != null) { for (int index = 0; index < framePayload.Length; index++) { short pcm = MuLawDecoder.MuLawToLinearSample(framePayload[index]); byte[] pcmSample = new byte[] { (byte)(pcm & 0xFF), (byte)(pcm >> 8) }; m_waveProvider.AddSamples(pcmSample, 0, 2); } } } }
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) { System.Diagnostics.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); System.Diagnostics.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(_rtspSession.RTPPayloadHeaderLength); _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()) { System.Diagnostics.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); } }
private void ProcessRTPPackets() { try { Thread.CurrentThread.Name = "rtpchanproc-" + _rtpPort; _lastRTPReceivedAt = DateTime.Now; _lastBWCalcAt = DateTime.Now; while (!_isClosed) { while (_packets.Count() > 0) { RTPPacket rtpPacket = null; lock (_packets) { try { rtpPacket = _packets.Dequeue(); } catch { } } 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) { System.Diagnostics.Debug.WriteLine("Ignoring RTP packet with timestamp " + rtpPacket.Header.Timestamp + " as it's earlier than the last complete frame."); } else if(_frameType == FrameTypesEnum.Audio) { var frame = RTPFrame.MakeSinglePacketFrame(rtpPacket); if (OnFrameReady != null) { try { //System.Diagnostics.Debug.WriteLine("RTP audio frame ready for timestamp " + frame.Timestamp + "."); OnFrameReady(frame); } catch (Exception frameReadyExcp) { logger.Error("Exception RTPChannel.ProcessRTPPackets OnFrameReady Audio. " + frameReadyExcp); } } } else { while (_frames.Count > MAX_FRAMES_QUEUE_LENGTH) { var oldestFrame = _frames.OrderBy(x => x.Timestamp).First(); _frames.Remove(oldestFrame); System.Diagnostics.Debug.WriteLine("Receive queue full, dropping oldest frame with timestamp " + oldestFrame.Timestamp + "."); } int frameHeaderLength = 0; if (_frameType == FrameTypesEnum.VP8) { var vp8Header = RTPVP8Header.GetVP8Header(rtpPacket.Payload); // For a VP8 packet only the Payload descriptor part of the header is not part of the encoded bit stream. frameHeaderLength = vp8Header.PayloadDescriptorLength; } 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(frameHeaderLength); _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 + "."); _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()) { System.Diagnostics.Debug.WriteLine("Discarding old frame for timestamp " + oldFrame.Timestamp + "."); _frames.Remove(oldFrame); } if (OnFrameReady != null) { try { //System.Diagnostics.Debug.WriteLine("RTP frame ready for timestamp " + frame.Timestamp + "."); OnFrameReady(frame); } catch (Exception frameReadyExcp) { logger.Error("Exception RTPChannel.ProcessRTPPackets OnFrameReady. " + frameReadyExcp); } } } } } } if (DateTime.Now.Subtract(_lastRTPReceivedAt).TotalSeconds > RTP_TIMEOUT_SECONDS) { logger.Warn("No RTP packets were receoved on local port " + _rtpPort + " for " + RTP_TIMEOUT_SECONDS + ". The session will now be closed."); Close(); } else { Thread.Sleep(1); } } } catch (Exception excp) { logger.Error("Exception RTPChannel.ProcessRTPPackets. " + excp); } }
/// <summary> /// Audio frames are generally contained within a single RTP packet. This method is a shortcut /// to construct a frame from a single RTP pakcet. /// </summary> public static RTPFrame MakeSinglePacketFrame(RTPPacket rtpPacket) { RTPFrame frame = new RTPFrame(); //frame.FramePayload = rtpPacket.Payload; frame.Timestamp = rtpPacket.Header.Timestamp; return frame; }
/// <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; }