commit
31e0c9c871
|
@ -481,6 +481,16 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (state.IsVideoRequest)
|
||||||
|
{
|
||||||
|
var encodingOptions = GetEncodingOptions();
|
||||||
|
var videoEncoder = EncodingJobFactory.GetVideoEncoder(MediaEncoder, state, encodingOptions);
|
||||||
|
if (videoEncoder.IndexOf("vaapi", StringComparison.OrdinalIgnoreCase) != -1)
|
||||||
|
{
|
||||||
|
arg = "-hwaccel vaapi -hwaccel_output_format vaapi -vaapi_device " + encodingOptions.VaapiDevice + " " + arg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return arg.Trim();
|
return arg.Trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -237,7 +237,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp
|
||||||
string modelurl = "";
|
string modelurl = "";
|
||||||
string serialnumber = "";
|
string serialnumber = "";
|
||||||
string presentationurl = "";
|
string presentationurl = "";
|
||||||
string capabilities = "";
|
//string capabilities = "";
|
||||||
string m3u = "";
|
string m3u = "";
|
||||||
var document = XDocument.Load(locationUri.AbsoluteUri);
|
var document = XDocument.Load(locationUri.AbsoluteUri);
|
||||||
var xnm = new XmlNamespaceManager(new NameTable());
|
var xnm = new XmlNamespaceManager(new NameTable());
|
||||||
|
@ -284,20 +284,20 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp
|
||||||
var capabilitiesElement = deviceElement.Element(n1 + "X_SATIPCAP");
|
var capabilitiesElement = deviceElement.Element(n1 + "X_SATIPCAP");
|
||||||
if (capabilitiesElement != null)
|
if (capabilitiesElement != null)
|
||||||
{
|
{
|
||||||
//_capabilities = capabilitiesElement.Value;
|
//_capabilities = capabilitiesElement.Value;
|
||||||
//if (capabilitiesElement.Value.Contains(','))
|
if (capabilitiesElement.Value.Contains(','))
|
||||||
//{
|
{
|
||||||
// string[] capabilities = capabilitiesElement.Value.Split(',');
|
string[] capabilities = capabilitiesElement.Value.Split(',');
|
||||||
// foreach (var capability in capabilities)
|
foreach (var capability in capabilities)
|
||||||
// {
|
{
|
||||||
// ReadCapability(capability);
|
ReadCapability(capability);
|
||||||
// }
|
}
|
||||||
//}
|
|
||||||
//else
|
|
||||||
//{
|
|
||||||
// ReadCapability(capabilitiesElement.Value);
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ReadCapability(capabilitiesElement.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_supportsDVBS = true;
|
_supportsDVBS = true;
|
||||||
|
@ -314,8 +314,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp
|
||||||
Id = uniquedevicename,
|
Id = uniquedevicename,
|
||||||
IsEnabled = true,
|
IsEnabled = true,
|
||||||
Type = SatIpHost.DeviceType,
|
Type = SatIpHost.DeviceType,
|
||||||
Tuners = 1,
|
Tuners = _tunerCountDVBS,
|
||||||
TunersAvailable = 1,
|
TunersAvailable = _tunerCountDVBS,
|
||||||
M3UUrl = m3u
|
M3UUrl = m3u
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -251,6 +251,18 @@
|
||||||
<Compile Include="LiveTv\RecordingImageProvider.cs" />
|
<Compile Include="LiveTv\RecordingImageProvider.cs" />
|
||||||
<Compile Include="LiveTv\RefreshChannelsScheduledTask.cs" />
|
<Compile Include="LiveTv\RefreshChannelsScheduledTask.cs" />
|
||||||
<Compile Include="LiveTv\TunerHosts\SatIp\ChannelScan.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\RtspMethod.cs" />
|
||||||
<Compile Include="LiveTv\TunerHosts\SatIp\Rtsp\RtspRequest.cs" />
|
<Compile Include="LiveTv\TunerHosts\SatIp\Rtsp\RtspRequest.cs" />
|
||||||
<Compile Include="LiveTv\TunerHosts\SatIp\Rtsp\RtspResponse.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\Rtsp\RtspStatusCode.cs" />
|
||||||
<Compile Include="LiveTv\TunerHosts\SatIp\SatIpHost.cs" />
|
<Compile Include="LiveTv\TunerHosts\SatIp\SatIpHost.cs" />
|
||||||
<Compile Include="LiveTv\TunerHosts\SatIp\SatIpDiscovery.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="Localization\LocalizationManager.cs" />
|
||||||
<Compile Include="Logging\PatternsLogger.cs" />
|
<Compile Include="Logging\PatternsLogger.cs" />
|
||||||
<Compile Include="MediaEncoder\EncodingManager.cs" />
|
<Compile Include="MediaEncoder\EncodingManager.cs" />
|
||||||
|
|
|
@ -346,11 +346,14 @@ namespace MediaBrowser.WebDashboard.Api
|
||||||
|
|
||||||
if (string.Equals(mode, "cordova", StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(mode, "cordova", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
sb.Append("<meta http-equiv=\"Content-Security-Policy\" content=\"default-src * 'unsafe-inline' 'unsafe-eval' data: gap://ready file: filesystem:;\">");
|
sb.Append("<meta http-equiv=\"Content-Security-Policy\" content=\"default-src * 'self' 'unsafe-inline' 'unsafe-eval' data: gap: file: filesystem:; connect-src ws: *\">");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sb.Append("<meta http-equiv=\"X-UA-Compatibility\" content=\"IE=Edge\">");
|
||||||
}
|
}
|
||||||
|
|
||||||
sb.Append("<link rel=\"manifest\" href=\"manifest.json\">");
|
sb.Append("<link rel=\"manifest\" href=\"manifest.json\">");
|
||||||
sb.Append("<meta http-equiv=\"X-UA-Compatibility\" content=\"IE=Edge\">");
|
|
||||||
sb.Append("<meta name=\"format-detection\" content=\"telephone=no\">");
|
sb.Append("<meta name=\"format-detection\" content=\"telephone=no\">");
|
||||||
sb.Append("<meta name=\"msapplication-tap-highlight\" content=\"no\">");
|
sb.Append("<meta name=\"msapplication-tap-highlight\" content=\"no\">");
|
||||||
sb.Append("<meta name=\"viewport\" content=\"user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width\">");
|
sb.Append("<meta name=\"viewport\" content=\"user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width\">");
|
||||||
|
|
Loading…
Reference in New Issue
Block a user