Rtp Rtcp fix Discovery #2116

This commit is contained in:
Luke Pulverenti 2016-09-01 21:54:16 -04:00
parent 2f67a007cd
commit fb251448c9
16 changed files with 1222 additions and 16 deletions

View file

@ -0,0 +1,79 @@
/*
Copyright (C) <2007-2016> <Kay Diefenthal>
SatIp.RtspSample is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
SatIp.RtspSample is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with SatIp.RtspSample. If not, see <http://www.gnu.org/licenses/>.
*/
namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtcp
{
public class ReportBlock
{
/// <summary>
/// Get the length of the block.
/// </summary>
public int BlockLength { get { return (24); } }
/// <summary>
/// Get the synchronization source.
/// </summary>
public string SynchronizationSource { get; private set; }
/// <summary>
/// Get the fraction lost.
/// </summary>
public int FractionLost { get; private set; }
/// <summary>
/// Get the cumulative packets lost.
/// </summary>
public int CumulativePacketsLost { get; private set; }
/// <summary>
/// Get the highest number received.
/// </summary>
public int HighestNumberReceived { get; private set; }
/// <summary>
/// Get the inter arrival jitter.
/// </summary>
public int InterArrivalJitter { get; private set; }
/// <summary>
/// Get the timestamp of the last report.
/// </summary>
public int LastReportTimeStamp { get; private set; }
/// <summary>
/// Get the delay since the last report.
/// </summary>
public int DelaySinceLastReport { get; private set; }
/// <summary>
/// Initialize a new instance of the ReportBlock class.
/// </summary>
public ReportBlock() { }
/// <summary>
/// Unpack the data in a packet.
/// </summary>
/// <param name="buffer">The buffer containing the packet.</param>
/// <param name="offset">The offset to the first byte of the packet within the buffer.</param>
/// <returns>An ErrorSpec instance if an error occurs; null otherwise.</returns>
public void Process(byte[] buffer, int offset)
{
SynchronizationSource = Utils.ConvertBytesToString(buffer, offset, 4);
FractionLost = buffer[offset + 4];
CumulativePacketsLost = Utils.Convert3BytesToInt(buffer, offset + 5);
HighestNumberReceived = Utils.Convert4BytesToInt(buffer, offset + 8);
InterArrivalJitter = Utils.Convert4BytesToInt(buffer, offset + 12);
LastReportTimeStamp = Utils.Convert4BytesToInt(buffer, offset + 16);
DelaySinceLastReport = Utils.Convert4BytesToInt(buffer, offset + 20);
}
}
}

View file

@ -0,0 +1,68 @@
/*
Copyright (C) <2007-2016> <Kay Diefenthal>
SatIp.RtspSample is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
SatIp.RtspSample is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with SatIp.RtspSample. If not, see <http://www.gnu.org/licenses/>.
*/
using System.Text;
namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtcp
{
class RtcpAppPacket : RtcpPacket
{
/// <summary>
/// Get the synchronization source.
/// </summary>
public int SynchronizationSource { get; private set; }
/// <summary>
/// Get the name.
/// </summary>
public string Name { get; private set; }
/// <summary>
/// Get the identity.
/// </summary>
public int Identity { get; private set; }
/// <summary>
/// Get the variable data portion.
/// </summary>
public string Data { get; private set; }
public override void Parse(byte[] buffer, int offset)
{
base.Parse(buffer, offset);
SynchronizationSource = Utils.Convert4BytesToInt(buffer, offset + 4);
Name = Utils.ConvertBytesToString(buffer, offset + 8, 4);
Identity = Utils.Convert2BytesToInt(buffer, offset + 12);
int dataLength = Utils.Convert2BytesToInt(buffer, offset + 14);
if (dataLength != 0)
Data = Utils.ConvertBytesToString(buffer, offset + 16, dataLength);
}
public override string ToString()
{
StringBuilder sb = new StringBuilder();
sb.AppendFormat("Application Specific.\n");
sb.AppendFormat("Version : {0} .\n", Version);
sb.AppendFormat("Padding : {0} .\n", Padding);
sb.AppendFormat("Report Count : {0} .\n", ReportCount);
sb.AppendFormat("PacketType: {0} .\n", Type);
sb.AppendFormat("Length : {0} .\n", Length);
sb.AppendFormat("SynchronizationSource : {0} .\n", SynchronizationSource);
sb.AppendFormat("Name : {0} .\n", Name);
sb.AppendFormat("Identity : {0} .\n", Identity);
sb.AppendFormat("Data : {0} .\n", Data);
sb.AppendFormat(".\n");
return sb.ToString();
}
}
}

View file

@ -0,0 +1,59 @@
using System.Collections.ObjectModel;
/*
Copyright (C) <2007-2016> <Kay Diefenthal>
SatIp.RtspSample is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
SatIp.RtspSample is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with SatIp.RtspSample. If not, see <http://www.gnu.org/licenses/>.
*/
using System.Text;
namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtcp
{
public class RtcpByePacket :RtcpPacket
{
public Collection<string> SynchronizationSources { get; private set; }
public string ReasonForLeaving { get; private set; }
public override void Parse(byte[] buffer, int offset)
{
base.Parse(buffer, offset);
SynchronizationSources = new Collection<string>();
int index = 4;
while (SynchronizationSources.Count < ReportCount)
{
SynchronizationSources.Add(Utils.ConvertBytesToString(buffer, offset + index, 4));
index += 4;
}
if (index < Length)
{
int reasonLength = buffer[offset + index];
ReasonForLeaving = Utils.ConvertBytesToString(buffer, offset + index + 1, reasonLength);
}
}
public override string ToString()
{
StringBuilder sb = new StringBuilder();
sb.AppendFormat("ByeBye .\n");
sb.AppendFormat("Version : {0} .\n", Version);
sb.AppendFormat("Padding : {0} .\n", Padding);
sb.AppendFormat("Report Count : {0} .\n", ReportCount);
sb.AppendFormat("PacketType: {0} .\n", Type);
sb.AppendFormat("Length : {0} .\n", Length);
sb.AppendFormat("SynchronizationSources : {0} .\n", SynchronizationSources);
sb.AppendFormat("ReasonForLeaving : {0} .\n", ReasonForLeaving);
sb.AppendFormat(".\n");
return sb.ToString();
}
}
}

View file

@ -0,0 +1,203 @@
/*
Copyright (C) <2007-2016> <Kay Diefenthal>
SatIp.RtspSample is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
SatIp.RtspSample is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with SatIp.RtspSample. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using MediaBrowser.Model.Logging;
namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtcp
{
public class RtcpListener
{
private readonly ILogger _logger;
private Thread _rtcpListenerThread;
private AutoResetEvent _rtcpListenerThreadStopEvent = null;
private UdpClient _udpClient;
private IPEndPoint _multicastEndPoint;
private IPEndPoint _serverEndPoint;
private TransmissionMode _transmissionMode;
public RtcpListener(String address, int port, TransmissionMode mode,ILogger logger)
{
_logger = logger;
_transmissionMode = mode;
switch (mode)
{
case TransmissionMode.Unicast:
_udpClient = new UdpClient(new IPEndPoint(IPAddress.Parse(address), port));
_serverEndPoint = new IPEndPoint(IPAddress.Any, 0);
break;
case TransmissionMode.Multicast:
_multicastEndPoint = new IPEndPoint(IPAddress.Parse(address), port);
_serverEndPoint = new IPEndPoint(IPAddress.Any, 0);
_udpClient = new UdpClient();
_udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1);
_udpClient.ExclusiveAddressUse = false;
_udpClient.Client.Bind(new IPEndPoint(IPAddress.Any, port));
_udpClient.JoinMulticastGroup(_multicastEndPoint.Address);
break;
}
//StartRtcpListenerThread();
}
public void StartRtcpListenerThread()
{
// Kill the existing thread if it is in "zombie" state.
if (_rtcpListenerThread != null && !_rtcpListenerThread.IsAlive)
{
StopRtcpListenerThread();
}
if (_rtcpListenerThread == null)
{
_logger.Info("SAT>IP : starting new RTCP listener thread");
_rtcpListenerThreadStopEvent = new AutoResetEvent(false);
_rtcpListenerThread = new Thread(new ThreadStart(RtcpListenerThread));
_rtcpListenerThread.Name = string.Format("SAT>IP tuner RTCP listener");
_rtcpListenerThread.IsBackground = true;
_rtcpListenerThread.Priority = ThreadPriority.Lowest;
_rtcpListenerThread.Start();
}
}
public void StopRtcpListenerThread()
{
if (_rtcpListenerThread != null)
{
if (!_rtcpListenerThread.IsAlive)
{
_logger.Info("SAT>IP : aborting old RTCP listener thread");
_rtcpListenerThread.Abort();
}
else
{
_rtcpListenerThreadStopEvent.Set();
if (!_rtcpListenerThread.Join(400 * 2))
{
_logger.Info("SAT>IP : failed to join RTCP listener thread, aborting thread");
_rtcpListenerThread.Abort();
}
}
_rtcpListenerThread = null;
if (_rtcpListenerThreadStopEvent != null)
{
_rtcpListenerThreadStopEvent.Close();
_rtcpListenerThreadStopEvent = null;
}
}
}
private void RtcpListenerThread()
{
try
{
bool receivedGoodBye = false;
try
{
_udpClient.Client.ReceiveTimeout = 400;
IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Any, 0);
while (!receivedGoodBye && !_rtcpListenerThreadStopEvent.WaitOne(1))
{
byte[] packets = _udpClient.Receive(ref serverEndPoint);
if (packets == null)
{
continue;
}
int offset = 0;
while (offset < packets.Length)
{
switch (packets[offset + 1])
{
case 200: //sr
var sr = new RtcpSenderReportPacket();
sr.Parse(packets, offset);
offset += sr.Length;
break;
case 201: //rr
var rr = new RtcpReceiverReportPacket();
rr.Parse(packets, offset);
offset += rr.Length;
break;
case 202: //sd
var sd = new RtcpSourceDescriptionPacket();
sd.Parse(packets, offset);
offset += sd.Length;
break;
case 203: // bye
var bye = new RtcpByePacket();
bye.Parse(packets, offset);
receivedGoodBye = true;
OnPacketReceived(new RtcpPacketReceivedArgs(bye));
offset += bye.Length;
break;
case 204: // app
var app = new RtcpAppPacket();
app.Parse(packets, offset);
OnPacketReceived(new RtcpPacketReceivedArgs(app));
offset += app.Length;
break;
}
}
}
}
finally
{
switch (_transmissionMode)
{
case TransmissionMode.Multicast:
_udpClient.DropMulticastGroup(_multicastEndPoint.Address);
_udpClient.Close();
break;
case TransmissionMode.Unicast:
_udpClient.Close();
break;
}
}
}
catch (ThreadAbortException)
{
}
catch (Exception ex)
{
_logger.Info(string.Format("SAT>IP : RTCP listener thread exception"), ex);
return;
}
_logger.Info("SAT>IP : RTCP listener thread stopping");
}
public delegate void PacketReceivedHandler(object sender, RtcpPacketReceivedArgs e);
public event PacketReceivedHandler PacketReceived;
public class RtcpPacketReceivedArgs : EventArgs
{
public Object Packet { get; private set; }
public RtcpPacketReceivedArgs(Object packet)
{
Packet = packet;
}
}
protected void OnPacketReceived(RtcpPacketReceivedArgs args)
{
if (PacketReceived != null)
{
PacketReceived(this, args);
}
}
}
}

View file

@ -0,0 +1,37 @@
/*
Copyright (C) <2007-2016> <Kay Diefenthal>
SatIp.RtspSample is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
SatIp.RtspSample is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with SatIp.RtspSample. If not, see <http://www.gnu.org/licenses/>.
*/
namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtcp
{
public abstract class RtcpPacket
{
public int Version { get; private set; }
public bool Padding { get; private set; }
public int ReportCount { get; private set; }
public int Type { get; private set; }
public int Length { get; private set; }
public virtual void Parse(byte[] buffer, int offset)
{
Version = buffer[offset] >> 6;
Padding = (buffer[offset] & 0x20) != 0;
ReportCount = buffer[offset] & 0x1f;
Type = buffer[offset + 1];
Length = (Utils.Convert2BytesToInt(buffer, offset + 2) * 4) + 4;
}
}
}

View file

@ -0,0 +1,68 @@
using System.Collections.ObjectModel;
/*
Copyright (C) <2007-2016> <Kay Diefenthal>
SatIp.RtspSample is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
SatIp.RtspSample is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with SatIp.RtspSample. If not, see <http://www.gnu.org/licenses/>.
*/
using System.Text;
namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtcp
{
public class RtcpReceiverReportPacket :RtcpPacket
{
public string SynchronizationSource { get; private set; }
public Collection<ReportBlock> ReportBlocks { get; private set; }
public byte[] ProfileExtension { get; private set; }
public override void Parse(byte[] buffer, int offset)
{
base.Parse(buffer, offset);
SynchronizationSource = Utils.ConvertBytesToString(buffer, offset + 4, 4);
ReportBlocks = new Collection<ReportBlock>();
int index = 8;
while (ReportBlocks.Count < ReportCount)
{
ReportBlock reportBlock = new ReportBlock();
reportBlock.Process(buffer, offset + index);
ReportBlocks.Add(reportBlock);
index += reportBlock.BlockLength;
}
if (index < Length)
{
ProfileExtension = new byte[Length - index];
for (int extensionIndex = 0; index < Length; index++)
{
ProfileExtension[extensionIndex] = buffer[offset + index];
extensionIndex++;
}
}
}
public override string ToString()
{
StringBuilder sb = new StringBuilder();
sb.AppendFormat("Receiver Report.\n");
sb.AppendFormat("Version : {0} .\n", Version);
sb.AppendFormat("Padding : {0} .\n", Padding);
sb.AppendFormat("Report Count : {0} .\n", ReportCount);
sb.AppendFormat("PacketType: {0} .\n", Type);
sb.AppendFormat("Length : {0} .\n", Length);
sb.AppendFormat("SynchronizationSource : {0} .\n", SynchronizationSource);
sb.AppendFormat(".\n");
return sb.ToString();
}
}
}

View file

@ -0,0 +1,105 @@
using System.Collections.ObjectModel;
/*
Copyright (C) <2007-2016> <Kay Diefenthal>
SatIp.RtspSample is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
SatIp.RtspSample is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with SatIp.RtspSample. If not, see <http://www.gnu.org/licenses/>.
*/
using System.Text;
namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtcp
{
public class RtcpSenderReportPacket : RtcpPacket
{
#region Properties
/// <summary>
/// Get the synchronization source.
/// </summary>
public int SynchronizationSource { get; private set; }
/// <summary>
/// Get the NPT timestamp.
/// </summary>
public long NPTTimeStamp { get; private set; }
/// <summary>
/// Get the RTP timestamp.
/// </summary>
public int RTPTimeStamp { get; private set; }
/// <summary>
/// Get the packet count.
/// </summary>
public int SenderPacketCount { get; private set; }
/// <summary>
/// Get the octet count.
/// </summary>
public int SenderOctetCount { get; private set; }
/// <summary>
/// Get the list of report blocks.
/// </summary>
public Collection<ReportBlock> ReportBlocks { get; private set; }
/// <summary>
/// Get the profile extension data.
/// </summary>
public byte[] ProfileExtension { get; private set; }
#endregion
public override void Parse(byte[] buffer, int offset)
{
base.Parse(buffer, offset);
SynchronizationSource = Utils.Convert4BytesToInt(buffer, offset + 4);
NPTTimeStamp = Utils.Convert8BytesToLong(buffer, offset + 8);
RTPTimeStamp = Utils.Convert4BytesToInt(buffer, offset + 16);
SenderPacketCount = Utils.Convert4BytesToInt(buffer, offset + 20);
SenderOctetCount = Utils.Convert4BytesToInt(buffer, offset + 24);
ReportBlocks = new Collection<ReportBlock>();
int index = 28;
while (ReportBlocks.Count < ReportCount)
{
ReportBlock reportBlock = new ReportBlock();
reportBlock.Process(buffer, offset + index);
ReportBlocks.Add(reportBlock);
index += reportBlock.BlockLength;
}
if (index < Length)
{
ProfileExtension = new byte[Length - index];
for (int extensionIndex = 0; index < Length; index++)
{
ProfileExtension[extensionIndex] = buffer[offset + index];
extensionIndex++;
}
}
}
public override string ToString()
{
StringBuilder sb = new StringBuilder();
sb.AppendFormat("Sender Report.\n");
sb.AppendFormat("Version : {0} .\n", Version);
sb.AppendFormat("Padding : {0} .\n", Padding);
sb.AppendFormat("Report Count : {0} .\n", ReportCount);
sb.AppendFormat("PacketType: {0} .\n", Type);
sb.AppendFormat("Length : {0} .\n", Length);
sb.AppendFormat("SynchronizationSource : {0} .\n", SynchronizationSource);
sb.AppendFormat("NTP Timestamp : {0} .\n", Utils.NptTimestampToDateTime(NPTTimeStamp));
sb.AppendFormat("RTP Timestamp : {0} .\n", RTPTimeStamp);
sb.AppendFormat("Sender PacketCount : {0} .\n", SenderPacketCount);
sb.AppendFormat("Sender Octet Count : {0} .\n", SenderOctetCount);
sb.AppendFormat(".\n");
return sb.ToString();
}
}
}

View file

@ -0,0 +1,57 @@
using System.Collections.ObjectModel;
/*
Copyright (C) <2007-2016> <Kay Diefenthal>
SatIp.RtspSample is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
SatIp.RtspSample is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with SatIp.RtspSample. If not, see <http://www.gnu.org/licenses/>.
*/
using System.Text;
namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtcp
{
class RtcpSourceDescriptionPacket :RtcpPacket
{ /// <summary>
/// Get the list of source descriptions.
/// </summary>
public Collection<SourceDescriptionBlock> Descriptions;
public override void Parse(byte[] buffer, int offset)
{
base.Parse(buffer, offset);
Descriptions = new Collection<SourceDescriptionBlock>();
int index = 4;
while (Descriptions.Count < ReportCount)
{
SourceDescriptionBlock descriptionBlock = new SourceDescriptionBlock();
descriptionBlock.Process(buffer, offset + index);
Descriptions.Add(descriptionBlock);
index += descriptionBlock.BlockLength;
}
}
public override string ToString()
{
StringBuilder sb = new StringBuilder();
sb.AppendFormat("Source Description.\n");
sb.AppendFormat("Version : {0} .\n", Version);
sb.AppendFormat("Padding : {0} .\n", Padding);
sb.AppendFormat("Report Count : {0} .\n", ReportCount);
sb.AppendFormat("PacketType: {0} .\n", Type);
sb.AppendFormat("Length : {0} .\n", Length);
sb.AppendFormat("Descriptions : {0} .\n", Descriptions);
sb.AppendFormat(".\n");
return sb.ToString();
}
}
}

View file

@ -0,0 +1,65 @@
/*
Copyright (C) <2007-2016> <Kay Diefenthal>
SatIp.RtspSample is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
SatIp.RtspSample is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with SatIp.RtspSample. If not, see <http://www.gnu.org/licenses/>.
*/
using System.Collections.ObjectModel;
namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtcp
{
class SourceDescriptionBlock
{
/// <summary>
/// Get the length of the block.
/// </summary>
public int BlockLength { get { return (blockLength + (blockLength % 4)); } }
/// <summary>
/// Get the synchronization source.
/// </summary>
public string SynchronizationSource { get; private set; }
/// <summary>
/// Get the list of source descriptioni items.
/// </summary>
public Collection<SourceDescriptionItem> Items;
private int blockLength;
public void Process(byte[] buffer, int offset)
{
SynchronizationSource = Utils.ConvertBytesToString(buffer, offset, 4);
Items = new Collection<SourceDescriptionItem>();
int index = 4;
bool done = false;
do
{
SourceDescriptionItem item = new SourceDescriptionItem();
item.Process(buffer, offset + index);
if (item.Type != 0)
{
Items.Add(item);
index += item.ItemLength;
blockLength += item.ItemLength;
}
else
{
blockLength++;
done = true;
}
}
while (!done);
}
}
}

View file

@ -0,0 +1,60 @@
/*
Copyright (C) <2007-2016> <Kay Diefenthal>
SatIp.RtspSample is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
SatIp.RtspSample is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with SatIp.RtspSample. If not, see <http://www.gnu.org/licenses/>.
*/
namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtcp
{
/// <summary>
/// The class that describes a source description item.
/// </summary>
public class SourceDescriptionItem
{
/// <summary>
/// Get the type.
/// </summary>
public int Type { get; private set; }
/// <summary>
/// Get the text.
/// </summary>
public string Text { get; private set; }
/// <summary>
/// Get the length of the item.
/// </summary>
public int ItemLength { get { return (Text.Length + 2); } }
/// <summary>
/// Initialize a new instance of the SourceDescriptionItem class.
/// </summary>
public SourceDescriptionItem() { }
/// <summary>
/// Unpack the data in a packet.
/// </summary>
/// <param name="buffer">The buffer containing the packet.</param>
/// <param name="offset">The offset to the first byte of the packet within the buffer.</param>
/// <returns>An ErrorSpec instance if an error occurs; null otherwise.</returns>
public void Process(byte[] buffer, int offset)
{
Type = buffer[offset];
if (Type != 0)
{
int length = buffer[offset + 1];
Text = Utils.ConvertBytesToString(buffer, offset + 2, length);
}
}
}
}

View file

@ -0,0 +1,160 @@
/*
Copyright (C) <2007-2016> <Kay Diefenthal>
SatIp.RtspSample is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
SatIp.RtspSample is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with SatIp.RtspSample. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using MediaBrowser.Model.Logging;
namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtp
{
public class RtpListener
{
private readonly ILogger _logger;
private AutoResetEvent _rtpListenerThreadStopEvent;
private Thread _rtpListenerThread;
private UdpClient _udpClient;
private IPEndPoint _multicastEndPoint;
private IPEndPoint _serverEndPoint;
private TransmissionMode _transmissionMode;
public RtpListener(String address, int port,TransmissionMode mode,ILogger logger)
{
_logger = logger;
_transmissionMode = mode;
switch (mode)
{
case TransmissionMode.Unicast:
_udpClient = new UdpClient(new IPEndPoint(IPAddress.Parse(address), port));
_serverEndPoint = new IPEndPoint(IPAddress.Any, 0);
break;
case TransmissionMode.Multicast:
_multicastEndPoint = new IPEndPoint(IPAddress.Parse(address), port);
_serverEndPoint = null;
_udpClient = new UdpClient();
_udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1);
_udpClient.ExclusiveAddressUse = false;
_udpClient.Client.Bind(new IPEndPoint(IPAddress.Any, _multicastEndPoint.Port));
_udpClient.JoinMulticastGroup(_multicastEndPoint.Address);
break;
}
//StartRtpListenerThread();
}
public void StartRtpListenerThread()
{
// Kill the existing thread if it is in "zombie" state.
if (_rtpListenerThread != null && !_rtpListenerThread.IsAlive)
{
StopRtpListenerThread();
}
if (_rtpListenerThread == null)
{
_logger.Info("SAT>IP : starting new RTP listener thread");
_rtpListenerThreadStopEvent = new AutoResetEvent(false);
_rtpListenerThread = new Thread(new ThreadStart(RtpListenerThread));
_rtpListenerThread.Name = string.Format("SAT>IP tuner RTP listener");
_rtpListenerThread.IsBackground = true;
_rtpListenerThread.Priority = ThreadPriority.Lowest;
_rtpListenerThread.Start();
}
}
public void StopRtpListenerThread()
{
if (_rtpListenerThread != null)
{
if (!_rtpListenerThread.IsAlive)
{
_logger.Info("SAT>IP : aborting old RTP listener thread");
_rtpListenerThread.Abort();
}
else
{
_rtpListenerThreadStopEvent.Set();
if (!_rtpListenerThread.Join(400 * 2))
{
_logger.Info("SAT>IP : failed to join RTP listener thread, aborting thread");
_rtpListenerThread.Abort();
}
}
_rtpListenerThread = null;
if (_rtpListenerThreadStopEvent != null)
{
_rtpListenerThreadStopEvent.Close();
_rtpListenerThreadStopEvent = null;
}
}
}
private void RtpListenerThread()
{
try
{
try
{
while (!_rtpListenerThreadStopEvent.WaitOne(1))
{
byte[] receivedbytes = _udpClient.Receive(ref _serverEndPoint);
RtpPacket packet = RtpPacket.Decode(receivedbytes);
OnPacketReceived(new RtpPacketReceivedArgs(packet));
}
}
finally
{
switch (_transmissionMode)
{
case TransmissionMode.Multicast:
_udpClient.DropMulticastGroup(_multicastEndPoint.Address);
_udpClient.Close();
break;
case TransmissionMode.Unicast:
_udpClient.Close();
break;
}
}
}
catch (ThreadAbortException)
{
}
catch (Exception ex)
{
_logger.Info(string.Format("SAT>IP : RTP listener thread exception"), ex);
return;
}
_logger.Info("SAT>IP : RTP listener thread stopping");
}
public delegate void PacketReceivedHandler(object sender, RtpPacketReceivedArgs e);
public event PacketReceivedHandler PacketReceived;
public class RtpPacketReceivedArgs : EventArgs
{
public RtpPacket Packet { get; private set; }
public RtpPacketReceivedArgs(RtpPacket packet)
{
Packet = packet;
}
}
protected void OnPacketReceived(RtpPacketReceivedArgs args)
{
if (PacketReceived != null)
{
PacketReceived(this, args);
}
}
}
}

View file

@ -0,0 +1,116 @@
/*
Copyright (C) <2007-2016> <Kay Diefenthal>
SatIp.RtspSample is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
SatIp.RtspSample is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with SatIp.RtspSample. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.ObjectModel;
using System.Text;
namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtp
{
public class RtpPacket
{
private static int MinHeaderLength = 12;
public int HeaderSize = MinHeaderLength;
public int Version { get; set; }
public Boolean Padding { get; set; }
public Boolean Extension { get; set; }
public int ContributingSourceCount { get; set; }
public Boolean Marker { get; set; }
public int PayloadType { get; set; }
public int SequenceNumber { get; set; }
public long TimeStamp { get; set; }
public long SynchronizationSource { get; set; }
public Collection<string> ContributingSources { get; private set; }
public int ExtensionHeaderId = 0;
public int ExtensionHeaderLength = 0;
public bool HasPayload { get; set; }
public byte[] Payload { get; set; }
public RtpPacket()
{
}
public static RtpPacket Decode(byte[] buffer)
{
var packet = new RtpPacket();
packet.Version = buffer[0] >> 6;
packet.Padding = (buffer[0] & 0x20) != 0;
packet.Extension = (buffer[0] & 0x10) != 0;
packet.ContributingSourceCount = buffer[0] & 0x0f;
packet.Marker = (buffer[1] & 0x80) != 0;
packet.PayloadType = buffer[1] & 0x7f;
packet.SequenceNumber = Utils.Convert2BytesToInt(buffer, 2);
packet.TimeStamp = Utils.Convert4BytesToLong(buffer, 4);
packet.SynchronizationSource = Utils.Convert4BytesToLong(buffer, 8);
int index = 12;
if (packet.ContributingSourceCount != 0)
{
packet.ContributingSources = new Collection<string>();
while (packet.ContributingSources.Count < packet.ContributingSourceCount)
{
packet.ContributingSources.Add(Utils.ConvertBytesToString(buffer, index, 4));
index += 4;
}
}
var dataoffset = 0;
if (!packet.Extension)
dataoffset = index;
else
{
packet.ExtensionHeaderId = Utils.Convert2BytesToInt(buffer, index);
packet.ExtensionHeaderLength = Utils.Convert2BytesToInt(buffer, index + 2);
dataoffset = index + packet.ExtensionHeaderLength + 4;
}
var dataLength = buffer.Length - dataoffset;
if (dataLength > dataoffset)
{
packet.HasPayload = true;
packet.Payload = new byte[dataLength];
Array.Copy(buffer, dataoffset, packet.Payload, 0, dataLength);
}
else
{
packet.HasPayload = false;
}
return packet;
}
public override string ToString()
{
StringBuilder sb = new StringBuilder();
sb.AppendFormat("RTP Packet");
sb.AppendFormat("Version: {0} \n", Version);
sb.AppendFormat("Padding: {0} \n", Padding);
sb.AppendFormat("Extension: {0} \n", Extension);
sb.AppendFormat("Contributing Source Identifiers Count: {0} \n", ContributingSourceCount);
sb.AppendFormat("Marker: {0} \n", Marker);
sb.AppendFormat("Payload Type: {0} \n", PayloadType);
sb.AppendFormat("Sequence Number: {0} \n", SequenceNumber);
sb.AppendFormat("Timestamp: {0} .\n", TimeStamp);
sb.AppendFormat("Synchronization Source Identifier: {0} \n", SynchronizationSource);
sb.AppendFormat("\n");
return sb.ToString();
}
}
}

View file

@ -237,7 +237,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp
string modelurl = "";
string serialnumber = "";
string presentationurl = "";
string capabilities = "";
//string capabilities = "";
string m3u = "";
var document = XDocument.Load(locationUri.AbsoluteUri);
var xnm = new XmlNamespaceManager(new NameTable());
@ -284,20 +284,20 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp
var capabilitiesElement = deviceElement.Element(n1 + "X_SATIPCAP");
if (capabilitiesElement != null)
{
//_capabilities = capabilitiesElement.Value;
//if (capabilitiesElement.Value.Contains(','))
//{
// string[] capabilities = capabilitiesElement.Value.Split(',');
// foreach (var capability in capabilities)
// {
// ReadCapability(capability);
// }
//}
//else
//{
// ReadCapability(capabilitiesElement.Value);
//}
//_capabilities = capabilitiesElement.Value;
if (capabilitiesElement.Value.Contains(','))
{
string[] capabilities = capabilitiesElement.Value.Split(',');
foreach (var capability in capabilities)
{
ReadCapability(capability);
}
}
else
{
ReadCapability(capabilitiesElement.Value);
}
}
else
{
_supportsDVBS = true;
@ -314,8 +314,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp
Id = uniquedevicename,
IsEnabled = true,
Type = SatIpHost.DeviceType,
Tuners = 1,
TunersAvailable = 1,
Tuners = _tunerCountDVBS,
TunersAvailable = _tunerCountDVBS,
M3UUrl = m3u
};

View file

@ -0,0 +1,25 @@
/*
Copyright (C) <2007-2016> <Kay Diefenthal>
SatIp.RtspSample is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
SatIp.RtspSample is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with SatIp.RtspSample. If not, see <http://www.gnu.org/licenses/>.
*/
namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp
{
public enum TransmissionMode
{
Unicast,
Multicast
}
}

View file

@ -0,0 +1,90 @@
/*
Copyright (C) <2007-2016> <Kay Diefenthal>
SatIp.RtspSample is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
SatIp.RtspSample is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with SatIp.RtspSample. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Text;
namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp
{
public class Utils
{
public static int Convert2BytesToInt(byte[] buffer, int offset)
{
int temp = (int)buffer[offset];
temp = (temp * 256) + buffer[offset + 1];
return (temp);
}
public static int Convert3BytesToInt(byte[] buffer, int offset)
{
int temp = (int)buffer[offset];
temp = (temp * 256) + buffer[offset + 1];
temp = (temp * 256) + buffer[offset + 2];
return (temp);
}
public static int Convert4BytesToInt(byte[] buffer, int offset)
{
int temp =(int)buffer[offset];
temp = (temp * 256) + buffer[offset + 1];
temp = (temp * 256) + buffer[offset + 2];
temp = (temp * 256) + buffer[offset + 3];
return (temp);
}
public static long Convert4BytesToLong(byte[] buffer, int offset)
{
long temp = 0;
for (int index = 0; index < 4; index++)
temp = (temp * 256) + buffer[offset + index];
return (temp);
}
public static long Convert8BytesToLong(byte[] buffer, int offset)
{
long temp = 0;
for (int index = 0; index < 8; index++)
temp = (temp * 256) + buffer[offset + index];
return (temp);
}
public static string ConvertBytesToString(byte[] buffer, int offset, int length)
{
StringBuilder reply = new StringBuilder(4);
for (int index = 0; index < length; index++)
reply.Append((char)buffer[offset + index]);
return (reply.ToString());
}
public static DateTime NptTimestampToDateTime(long nptTimestamp) { return NptTimestampToDateTime((uint)((nptTimestamp >> 32) & 0xFFFFFFFF), (uint)(nptTimestamp & 0xFFFFFFFF),null); }
public static DateTime NptTimestampToDateTime(uint seconds, uint fractions, DateTime? epoch )
{
ulong ticks =(ulong)((seconds * TimeSpan.TicksPerSecond) + ((fractions * TimeSpan.TicksPerSecond) / 0x100000000L));
if (epoch.HasValue) return epoch.Value + TimeSpan.FromTicks((Int64)ticks);
return (seconds & 0x80000000L) == 0 ? UtcEpoch2036 + TimeSpan.FromTicks((Int64)ticks) : UtcEpoch1900 + TimeSpan.FromTicks((Int64)ticks);
}
//When the First Epoch will wrap (The real Y2k)
public static DateTime UtcEpoch2036 = new DateTime(2036, 2, 7, 6, 28, 16, DateTimeKind.Utc);
public static DateTime UtcEpoch1900 = new DateTime(1900, 1, 1, 0, 0, 0, DateTimeKind.Utc);
public static DateTime UtcEpoch1970 = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
}
}

View file

@ -251,6 +251,18 @@
<Compile Include="LiveTv\RecordingImageProvider.cs" />
<Compile Include="LiveTv\RefreshChannelsScheduledTask.cs" />
<Compile Include="LiveTv\TunerHosts\SatIp\ChannelScan.cs" />
<Compile Include="LiveTv\TunerHosts\SatIp\Rtcp\ReportBlock.cs" />
<Compile Include="LiveTv\TunerHosts\SatIp\Rtcp\RtcpAppPacket.cs" />
<Compile Include="LiveTv\TunerHosts\SatIp\Rtcp\RtcpByePacket.cs" />
<Compile Include="LiveTv\TunerHosts\SatIp\Rtcp\RtcpListener.cs" />
<Compile Include="LiveTv\TunerHosts\SatIp\Rtcp\RtcpPacket.cs" />
<Compile Include="LiveTv\TunerHosts\SatIp\Rtcp\RtcpReceiverReportPacket.cs" />
<Compile Include="LiveTv\TunerHosts\SatIp\Rtcp\RtcpSenderReportPacket.cs" />
<Compile Include="LiveTv\TunerHosts\SatIp\Rtcp\RtcpSourceDescriptionPacket.cs" />
<Compile Include="LiveTv\TunerHosts\SatIp\Rtcp\SourceDescriptionBlock.cs" />
<Compile Include="LiveTv\TunerHosts\SatIp\Rtcp\SourceDescriptionItem.cs" />
<Compile Include="LiveTv\TunerHosts\SatIp\Rtp\RtpListener.cs" />
<Compile Include="LiveTv\TunerHosts\SatIp\Rtp\RtpPacket.cs" />
<Compile Include="LiveTv\TunerHosts\SatIp\Rtsp\RtspMethod.cs" />
<Compile Include="LiveTv\TunerHosts\SatIp\Rtsp\RtspRequest.cs" />
<Compile Include="LiveTv\TunerHosts\SatIp\Rtsp\RtspResponse.cs" />
@ -258,6 +270,8 @@
<Compile Include="LiveTv\TunerHosts\SatIp\Rtsp\RtspStatusCode.cs" />
<Compile Include="LiveTv\TunerHosts\SatIp\SatIpHost.cs" />
<Compile Include="LiveTv\TunerHosts\SatIp\SatIpDiscovery.cs" />
<Compile Include="LiveTv\TunerHosts\SatIp\TransmissionMode.cs" />
<Compile Include="LiveTv\TunerHosts\SatIp\Utils.cs" />
<Compile Include="Localization\LocalizationManager.cs" />
<Compile Include="Logging\PatternsLogger.cs" />
<Compile Include="MediaEncoder\EncodingManager.cs" />