Added options for SAT>IP Multicast Playout and building a date-ordered TS list to CSV.

This commit is contained in:
Fey 2026-04-06 16:42:27 +02:00
parent 8de4b56c6f
commit 03f194bd34
7 changed files with 1419 additions and 1272 deletions

View File

@ -89,7 +89,7 @@ namespace skyscraper5
logger.DebugFormat("I'm a {0}-bit Process.", Environment.Is64BitProcess ? 64 : 32); logger.DebugFormat("I'm a {0}-bit Process.", Environment.Is64BitProcess ? 64 : 32);
PluginManager.GetInstance(); PluginManager.GetInstance();
SoftcamKeyset.GetInstance().AutoInitalize(); //SoftcamKeyset.GetInstance().AutoInitalize();
if (args.Length != 0) if (args.Length != 0)
{ {
@ -386,6 +386,14 @@ namespace skyscraper5
catalogueGenerator.Dispose(); catalogueGenerator.Dispose();
return; return;
} }
if (args[0].ToLowerInvariant().Equals("rotation-catalogue"))
{
TsRotationToCsv rotator = new TsRotationToCsv();
rotator.SourceDir = new DirectoryInfo(args[1]);
rotator.DestinationCsv = new FileInfo(args[2]);
rotator.Run();
return;
}
} }
/*Passing passing = new Passing(); /*Passing passing = new Passing();

View File

@ -2,7 +2,7 @@
"profiles": { "profiles": {
"skyscraper8": { "skyscraper8": {
"commandName": "Project", "commandName": "Project",
"commandLineArgs": "satip-playout auto 1 V 12597 S2 45000 6970", "commandLineArgs": "rotation-catalogue F:\\\\ F:\\\\rotate-us.csv",
"remoteDebugEnabled": false "remoteDebugEnabled": false
}, },
"Container (Dockerfile)": { "Container (Dockerfile)": {

View File

@ -83,6 +83,19 @@ namespace skyscraper8
} }
destinationPort = int.Parse(args[7]); destinationPort = int.Parse(args[7]);
playoutMode = true; playoutMode = true;
if (args.Length == 10)
{
if (args[8].ToLowerInvariant().Equals("multicast"))
{
destinationIp = IPAddress.Parse(args[9]);
multicastMode = true;
}
else
{
logger.FatalFormat("Don't know what {0} means.", args[8]);
return;
}
}
} }
private IPAddress AutodetectIPAddress() private IPAddress AutodetectIPAddress()
@ -116,7 +129,7 @@ namespace skyscraper8
SessionDescriptionProtocol sessionDescriptionProtocol = describe.GetSessionDescriptionProtocol(); SessionDescriptionProtocol sessionDescriptionProtocol = describe.GetSessionDescriptionProtocol();
packetQueue = new Queue<byte[]>(); packetQueue = new Queue<byte[]>();
RtspSetupResponse setup = rtspClient.GetSetup(url, destinationPort); RtspSetupResponse setup = rtspClient.GetSetup(url, destinationPort, multicastMode, destinationIp);
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.");
@ -236,6 +249,7 @@ namespace skyscraper8
private IPAddress destinationIp; private IPAddress destinationIp;
private int destinationPort; private int destinationPort;
private bool playoutMode; private bool playoutMode;
private bool multicastMode;
private void Setup_OnRtcpPacket(byte[] data, int length) private void Setup_OnRtcpPacket(byte[] data, int length)
{ {

View File

@ -99,7 +99,7 @@ namespace skyscraper8.SatIp
return result; return result;
} }
public RtspSetupResponse GetSetup(string url, int destinationPort = 0) public RtspSetupResponse GetSetup(string url, int destinationPort = 0, bool multicastMode = false, IPAddress multicastIp = null)
{ {
RtspSetupRequest request = new RtspSetupRequest(); RtspSetupRequest request = new RtspSetupRequest();
request.RequestPath = url; request.RequestPath = url;
@ -123,7 +123,14 @@ namespace skyscraper8.SatIp
rtcpSocket.Bind(new IPEndPoint(ListenIp, 0)); rtcpSocket.Bind(new IPEndPoint(ListenIp, 0));
int rtcpPort = GetPortFromEndPoint(rtcpSocket.LocalEndPoint); int rtcpPort = GetPortFromEndPoint(rtcpSocket.LocalEndPoint);
if (multicastMode && multicastIp != null)
{
request.SetRtpAvpMulticast(multicastIp, rtpPort, rtcpPort);
}
else
{
request.SetRtpAvpUnicast(rtpPort, rtcpPort); request.SetRtpAvpUnicast(rtpPort, rtcpPort);
}
RtspResponseHeader response = GetResponse(request.ListHeaders(RootPath)); RtspResponseHeader response = GetResponse(request.ListHeaders(RootPath));
RtspSetupResponse setupResponse = new RtspSetupResponse(response); RtspSetupResponse setupResponse = new RtspSetupResponse(response);

View File

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -52,6 +53,11 @@ namespace skyscraper8.SatIp.RtspRequests
{ {
Transport = String.Format("RTP/AVP;unicast;client_port={0}-{1}", rtpPort, rtcpPort); Transport = String.Format("RTP/AVP;unicast;client_port={0}-{1}", rtpPort, rtcpPort);
} }
public void SetRtpAvpMulticast(IPAddress targetIp, int rtpPort, int rtcpPort)
{
Transport = String.Format("RTP/AVP;multicast;destination={2};port={0}-{1}", rtpPort, rtcpPort, targetIp.ToString());
}
} }
} }

View File

@ -6,7 +6,7 @@ namespace skyscraper5.Skyscraper.IO.TunerInterface
{ {
[SkyscraperPlugin] [SkyscraperPlugin]
[TunerFactoryId(2,"skyscraper5 Remote Stream Reader")] [TunerFactoryId(2,"skyscraper5 Remote Stream Reader")]
internal class RemoteStreamReaderTunerFactory : ITunerFactory public class RemoteStreamReaderTunerFactory : ITunerFactory
{ {
public string Hostname { get; set; } public string Hostname { get; set; }

View File

@ -0,0 +1,112 @@
using log4net;
using log4net.Repository.Hierarchy;
using skyscraper5.Docsis.MacManagement;
using skyscraper5.Skyscraper;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace skyscraper8.Skyscraper
{
internal class TsRotationToCsv
{
public DirectoryInfo SourceDir { get; set; }
public FileInfo DestinationCsv { get; set; }
private List<FileInfo> files;
private ILog logger;
public void Run()
{
logger = LogManager.GetLogger(typeof(TsRotationToCsv));
files = new List<FileInfo>();
ScrapeDirectory(SourceDir);
files.Sort(new FileInfoComparerByDate(logger));
DumpCsv();
}
private void DumpCsv()
{
StreamWriter sw = new StreamWriter(DestinationCsv.FullName);
foreach (FileInfo file in files)
{
sw.WriteLine(String.Format("\"{0}\";{1};{2}", file.FullName, file.Length, file.LastWriteTime));
}
sw.Flush();
sw.Close();
}
private void ScrapeDirectory(DirectoryInfo di)
{
try
{
foreach (FileSystemInfo fsi in di.GetFileSystemInfos())
{
switch (fsi)
{
case FileInfo fi:
if (fi.Extension.ToLowerInvariant().Equals(".ts"))
{
files.Add(fi);
if (files.Count % 100 == 0)
logger.InfoFormat("Listed {0} files.", files.Count);
}
break;
case DirectoryInfo subdirectory:
ScrapeDirectory(subdirectory);
break;
default:
throw new NotImplementedException(di.GetType().Name);
}
}
}
catch (Exception e)
{
logger.WarnFormat(e.Message);
}
}
private class FileInfoComparerByDate : Comparer<FileInfo>
{
private ILog logger;
private int ups, downs, stands;
public FileInfoComparerByDate(ILog logger)
{
this.logger = logger;
}
public override int Compare(FileInfo? x, FileInfo? y)
{
long xTime = x.LastWriteTime.ToUnixTime();
long yTime = y.LastWriteTime.ToUnixTime();
int ops;
int v = xTime.CompareTo(yTime);
switch(v)
{
case -1:
ups++;
ops = ups;
break;
case 0:
stands++;
ops = stands;
break;
case 1:
downs++;
ops = downs;
break;
default:
throw new NotImplementedException(v.ToString());
}
if (ops % 1000 == 0)
{
logger.InfoFormat("Sort progress: {0} up, {1} down, {2} stand.", ups, downs, stands);
}
return v;
}
}
}
}