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)
gseLength -= 4;
if (span.GetAvailableBytes() < gseLength)
{
//broken gse packet, invalid length
return;
}
gsePacket.GseDataBytes = span.ReadBytes(gseLength);
if (!startIndicator && endIndicator)

View File

@ -290,6 +290,15 @@ namespace skyscraper5
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.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\\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-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-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.");

View File

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

View File

@ -74,6 +74,17 @@ namespace skyscraper8
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()
{
SsdpDevice firstSatIpServer = SsdpClient.GetFirstSatIpServer(1000, null);
@ -105,7 +116,7 @@ namespace skyscraper8
SessionDescriptionProtocol sessionDescriptionProtocol = describe.GetSessionDescriptionProtocol();
packetQueue = new Queue<byte[]>();
RtspSetupResponse setup = rtspClient.GetSetup(url);
RtspSetupResponse setup = rtspClient.GetSetup(url, destinationPort);
if (setup.RtspStatusCode == 404)
{
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();
if (objectStorage == null)
objectStorage = new FilesystemStorage(new DirectoryInfo("."));
if (!playoutMode)
{
context = new SkyscraperContext(new TsContext(), dataStorage, objectStorage);
context.EnableTimeout = true;
context.TimeoutSeconds = 60;
context.InitalizeFilterChain();
}
RtspPlayResponse play = rtspClient.GetPlay(setup);
DateTime lastTimestamp = DateTime.Now;
bool initMessagePrinted = false;
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)
{
@ -136,6 +163,11 @@ namespace skyscraper8
buffer = packetQueue.Dequeue();
}
context.IngestSinglePacket(buffer);
if (!initMessagePrinted)
{
logger.InfoFormat("Began SAT>IP stream.");
initMessagePrinted = true;
}
}
else
{
@ -151,6 +183,7 @@ namespace skyscraper8
lastTimestamp = DateTime.Now;
}
}
}
rtspClient.GetTeardown(setup);
rtspClient.Dispose();
@ -200,6 +233,10 @@ namespace skyscraper8
}
private int rtcps;
private IPAddress destinationIp;
private int destinationPort;
private bool playoutMode;
private void Setup_OnRtcpPacket(byte[] data, int length)
{
//rtcps++;

View File

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

View File

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