Added a command-line option to tune SAT>IP servers without actually processing the stream.

This commit is contained in:
Fey 2026-03-30 15:20:30 +02:00
parent fe672a54f9
commit 8de4b56c6f
6 changed files with 458 additions and 390 deletions

View File

@ -120,6 +120,11 @@ namespace skyscraper8.GS.GSE_BFBS
if (!startIndicator && endIndicator) if (!startIndicator && endIndicator)
gseLength -= 4; gseLength -= 4;
if (span.GetAvailableBytes() < gseLength)
{
//broken gse packet, invalid length
return;
}
gsePacket.GseDataBytes = span.ReadBytes(gseLength); gsePacket.GseDataBytes = span.ReadBytes(gseLength);
if (!startIndicator && endIndicator) if (!startIndicator && endIndicator)

View File

@ -290,6 +290,15 @@ namespace skyscraper5
return; return;
} }
if (args[0].ToLowerInvariant().Equals("satip-playout"))
{
QuickAndDirtySatIpClient qadsipc = new QuickAndDirtySatIpClient(args);
qadsipc.SetPlayoutMode(args);
qadsipc.Run();
return;
}
if (args[0].ToLowerInvariant().Equals("shannon")) if (args[0].ToLowerInvariant().Equals("shannon"))
{ {
if (args.Length != 2) if (args.Length != 2)
@ -392,6 +401,7 @@ namespace skyscraper5
Console.WriteLine(" or: .\\skyscraper8.exe \"C:\\path\\to\\file.ts\\"); Console.WriteLine(" or: .\\skyscraper8.exe \"C:\\path\\to\\file.ts\\");
Console.WriteLine(" or: .\\skyscraper8.exe \"C:\\path\\to\\my\\folder\\with\\ts\\files\\\" (for batch extraction)"); Console.WriteLine(" or: .\\skyscraper8.exe \"C:\\path\\to\\my\\folder\\with\\ts\\files\\\" (for batch extraction)");
Console.WriteLine(" or: .\\skyscraper8.exe satip IP_ADDRESS DISEQC POLARITY FREQUENCY SYSTEM SYMBOL_RATE (see README file)"); Console.WriteLine(" or: .\\skyscraper8.exe satip IP_ADDRESS DISEQC POLARITY FREQUENCY SYSTEM SYMBOL_RATE (see README file)");
Console.WriteLine(" or: .\\skyscraper8.exe satip-playout IP_ADDRESS DISEQC POLARITY FREQUENCY SYSTEM SYMBOL_RATE DESTINATION_PORT");
Console.WriteLine(" or: .\\skyscraper8.exe pcap-on - to write a configuration file that allows PCAP writing during scraping."); Console.WriteLine(" or: .\\skyscraper8.exe pcap-on - to write a configuration file that allows PCAP writing during scraping.");
Console.WriteLine(" or: .\\skyscraper8.exe pcap-off - to write a configuration file that turns off PCAP writing during scraping."); Console.WriteLine(" or: .\\skyscraper8.exe pcap-off - to write a configuration file that turns off PCAP writing during scraping.");
Console.WriteLine(" or: .\\skyscraper8.exe subts-on - to write a configuration file that allows extraction of nested TS."); Console.WriteLine(" or: .\\skyscraper8.exe subts-on - to write a configuration file that allows extraction of nested TS.");

View File

@ -2,6 +2,7 @@
"profiles": { "profiles": {
"skyscraper8": { "skyscraper8": {
"commandName": "Project", "commandName": "Project",
"commandLineArgs": "satip-playout auto 1 V 12597 S2 45000 6970",
"remoteDebugEnabled": false "remoteDebugEnabled": false
}, },
"Container (Dockerfile)": { "Container (Dockerfile)": {

View File

@ -74,6 +74,17 @@ namespace skyscraper8
symbolRate = Int32.Parse(args[6]); symbolRate = Int32.Parse(args[6]);
} }
public void SetPlayoutMode(string[] args)
{
if (args.Length == 7)
{
logger.Fatal("What's the target port?");
return;
}
destinationPort = int.Parse(args[7]);
playoutMode = true;
}
private IPAddress AutodetectIPAddress() private IPAddress AutodetectIPAddress()
{ {
SsdpDevice firstSatIpServer = SsdpClient.GetFirstSatIpServer(1000, null); SsdpDevice firstSatIpServer = SsdpClient.GetFirstSatIpServer(1000, null);
@ -105,7 +116,7 @@ namespace skyscraper8
SessionDescriptionProtocol sessionDescriptionProtocol = describe.GetSessionDescriptionProtocol(); SessionDescriptionProtocol sessionDescriptionProtocol = describe.GetSessionDescriptionProtocol();
packetQueue = new Queue<byte[]>(); packetQueue = new Queue<byte[]>();
RtspSetupResponse setup = rtspClient.GetSetup(url); RtspSetupResponse setup = rtspClient.GetSetup(url, destinationPort);
if (setup.RtspStatusCode == 404) if (setup.RtspStatusCode == 404)
{ {
logger.Fatal("Your SAT>IP server doesn't have a tuner available that can talk to the requested frequency."); logger.Fatal("Your SAT>IP server doesn't have a tuner available that can talk to the requested frequency.");
@ -118,15 +129,31 @@ namespace skyscraper8
dataStorage = new InMemoryScraperStorage(); dataStorage = new InMemoryScraperStorage();
if (objectStorage == null) if (objectStorage == null)
objectStorage = new FilesystemStorage(new DirectoryInfo(".")); objectStorage = new FilesystemStorage(new DirectoryInfo("."));
if (!playoutMode)
{
context = new SkyscraperContext(new TsContext(), dataStorage, objectStorage); context = new SkyscraperContext(new TsContext(), dataStorage, objectStorage);
context.EnableTimeout = true; context.EnableTimeout = true;
context.TimeoutSeconds = 60; context.TimeoutSeconds = 60;
context.InitalizeFilterChain(); context.InitalizeFilterChain();
}
RtspPlayResponse play = rtspClient.GetPlay(setup); RtspPlayResponse play = rtspClient.GetPlay(setup);
DateTime lastTimestamp = DateTime.Now; DateTime lastTimestamp = DateTime.Now;
bool initMessagePrinted = false;
while (true) while (true)
{
if (playoutMode)
{
Thread.Sleep(1000);
Keepalive(url);
if (!initMessagePrinted)
{
logger.InfoFormat("Began SAT>IP playout to port {0}", destinationPort);
initMessagePrinted = true;
}
}
else
{ {
if (packetQueue.Count >= 1) if (packetQueue.Count >= 1)
{ {
@ -136,6 +163,11 @@ namespace skyscraper8
buffer = packetQueue.Dequeue(); buffer = packetQueue.Dequeue();
} }
context.IngestSinglePacket(buffer); context.IngestSinglePacket(buffer);
if (!initMessagePrinted)
{
logger.InfoFormat("Began SAT>IP stream.");
initMessagePrinted = true;
}
} }
else else
{ {
@ -151,6 +183,7 @@ namespace skyscraper8
lastTimestamp = DateTime.Now; lastTimestamp = DateTime.Now;
} }
} }
}
rtspClient.GetTeardown(setup); rtspClient.GetTeardown(setup);
rtspClient.Dispose(); rtspClient.Dispose();
@ -200,6 +233,10 @@ namespace skyscraper8
} }
private int rtcps; private int rtcps;
private IPAddress destinationIp;
private int destinationPort;
private bool playoutMode;
private void Setup_OnRtcpPacket(byte[] data, int length) private void Setup_OnRtcpPacket(byte[] data, int length)
{ {
//rtcps++; //rtcps++;

View File

@ -99,16 +99,25 @@ namespace skyscraper8.SatIp
return result; return result;
} }
public RtspSetupResponse GetSetup(string url) public RtspSetupResponse GetSetup(string url, int destinationPort = 0)
{ {
RtspSetupRequest request = new RtspSetupRequest(); RtspSetupRequest request = new RtspSetupRequest();
request.RequestPath = url; request.RequestPath = url;
request.CSeq = cseqCounter++; request.CSeq = cseqCounter++;
request.UserAgent = USER_AGENT; request.UserAgent = USER_AGENT;
Socket rtpSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); int rtpPort = 0;
Socket rtpSocket = null;
if (destinationPort == 0)
{
rtpSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
rtpSocket.Bind(new IPEndPoint(ListenIp, 0)); rtpSocket.Bind(new IPEndPoint(ListenIp, 0));
int rtpPort = GetPortFromEndPoint(rtpSocket.LocalEndPoint); rtpPort = GetPortFromEndPoint(rtpSocket.LocalEndPoint);
}
else
{
rtpPort = destinationPort;
}
Socket rtcpSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); Socket rtcpSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
rtcpSocket.Bind(new IPEndPoint(ListenIp, 0)); rtcpSocket.Bind(new IPEndPoint(ListenIp, 0));

View File

@ -53,9 +53,14 @@ namespace skyscraper8.SatIp.RtspResponses
if (listenersStarted) if (listenersStarted)
throw new RtspException("Listener already started."); throw new RtspException("Listener already started.");
if (RtpSocket != null)
{
rtpCancellation = new CancellationTokenSource(); rtpCancellation = new CancellationTokenSource();
}
rtcpCancellation = new CancellationTokenSource(); rtcpCancellation = new CancellationTokenSource();
if (RtpSocket != null)
{
Task.Run(async () => Task.Run(async () =>
{ {
byte[] buffer = new byte[2048]; byte[] buffer = new byte[2048];
@ -70,6 +75,7 @@ namespace skyscraper8.SatIp.RtspResponses
exitedThread++; exitedThread++;
} }
); );
}
Task.Run(async () => Task.Run(async () =>
{ {
@ -92,8 +98,8 @@ namespace skyscraper8.SatIp.RtspResponses
internal void InvokeCancellationTokens() internal void InvokeCancellationTokens()
{ {
rtpCancellation.Cancel(); rtpCancellation?.Cancel();
rtcpCancellation.Cancel(); rtcpCancellation?.Cancel();
} }
public event OnRtpPacket OnRtpPacket; public event OnRtpPacket OnRtpPacket;