Preparations for BFBS Navy TV.
Some checks failed
🚀 Pack skyscraper8 / make-zip (push) Failing after 2m18s

This commit is contained in:
feyris-tan 2025-11-08 21:16:43 +01:00
parent 124bf9eb49
commit 8f2c31f10d
24 changed files with 410 additions and 88 deletions

View File

@ -7,12 +7,13 @@ the following Signalling applies:
|Stream Type|Interpretation |
|-----------|-----------------------------------|
|0x80 |TBS 6903-X GSE Packets |
|0x80 |STiD135 GS/GSE Packets |
|0x81 |AC-3 Audio |
|0x82 |PID only used for PCR |
|0x83 |AC-3 True HD Audio |
|0x84 |AC-3+ Audio |
|0x85 |ULE (RFC 4326) |
|0x85 |DTS Audio |
|0x91 |ULE (RFC 4326) |
## Descriptors:

View File

@ -13,8 +13,8 @@
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AThrowHelper_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fe1ab690537c44e02a014076312b886b7b2e200_003F4f_003F7bfc5050_003FThrowHelper_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ATuple_00602_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F57d616db882b441b8c50720b4477e03db2e200_003F9f_003F0d16f921_003FTuple_00602_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/Environment/Highlighting/HighlightingSourceSnapshotLocation/@EntryValue">/home/schiemas/.cache/JetBrains/Rider2025.1/resharper-host/temp/Rider/vAny/CoverageData/_skyscraper8.1808907683/Snapshot/snapshot.utdcvr</s:String>
<s:String x:Key="/Default/Environment/UnitTesting/UnitTestSessionStore/Sessions/=94eea68c_002Dcaa0_002D4657_002Da521_002D7b96c8ead0ec/@EntryIndexedValue">&lt;SessionState ContinuousTestingMode="0" IsActive="True" Name="All tests from &amp;lt;skyscraper8.Tests&amp;gt;" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"&gt;
&lt;Project Location="/home/schiemas/RiderProjects/skyscraper8/skyscraper8.Tests" Presentation="&amp;lt;skyscraper8.Tests&amp;gt;" /&gt;
<s:String x:Key="/Default/Environment/UnitTesting/UnitTestSessionStore/Sessions/=94eea68c_002Dcaa0_002D4657_002Da521_002D7b96c8ead0ec/@EntryIndexedValue">&lt;SessionState ContinuousTestingMode="0" IsActive="True" Name="All tests from &amp;lt;skyscraper8.Tests&amp;gt;" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"&gt;&#xD;
&lt;Project Location="\home\schiemas\RiderProjects\skyscraper8\skyscraper8.Tests" Presentation="&amp;lt;skyscraper8.Tests&amp;gt;" /&gt;&#xD;
&lt;/SessionState&gt;</s:String>

View File

@ -1,19 +1,18 @@
using log4net;
using skyscraper5.Dvb.DataBroadcasting;
using skyscraper8.GS;
using skyscraper8.Skyscraper.Scraper;
namespace skyscraper8.GSE;
public class BbframeDeencapsulator3 : IBbframeDeencapsulator
class BbframeDeencapsulator3 : IBbframeDeencapsulator
{
public BbframeDeencapsulator3(IMultiprotocolEncapsulationEventHandler mpeEventHandler, ISubTsHandler subTsHandler)
public BbframeDeencapsulator3(GsContextDto context)
{
_mpeEventHandler = mpeEventHandler;
_subTsHandler = subTsHandler;
this.context = context;
}
private readonly ISubTsHandler _subTsHandler;
private readonly IMultiprotocolEncapsulationEventHandler _mpeEventHandler;
private readonly GsContextDto context;
private static readonly ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name);
private long numPushed;
public void PushPacket(byte[] bbframe)
@ -38,11 +37,7 @@ public class BbframeDeencapsulator3 : IBbframeDeencapsulator
if (mis[bbHeader.Matype2] == null)
{
logger.InfoFormat("Found a stream on MIS {0}",bbHeader.Matype2);
mis[bbHeader.Matype2] = new GsTypeDetector(bbHeader.Matype2)
{
mpeEventHandler = this._mpeEventHandler,
subTsHandler = this._subTsHandler
};
mis[bbHeader.Matype2] = new GsTypeDetector(context.MisClone(bbHeader.Matype2));
}
mis[bbHeader.Matype2].PushFrame(bbHeader, new ReadOnlySpan<byte>(bbframe, 11, bbframe.Length - 11));

View File

@ -1,30 +1,31 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using skyscraper5.Dvb.DataBroadcasting;
using skyscraper5.Mpeg2;
using skyscraper5.Skyscraper.IO;
using skyscraper8.GSE;
using skyscraper8.GSE.GSE;
using skyscraper8.Skyscraper.IO;
using skyscraper8.Skyscraper.Scraper;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using skyscraper5.src.InteractionChannel;
namespace skyscraper8.GS.GSE_BFBS
{
internal class BfbsGseReader : IMisHandler
{
private readonly byte _misId;
private readonly ISubTsHandler _subTsHandler;
private GseLabel lastLabel;
private int frameNo;
public GsContextDto Context { get; set; }
public BfbsGseReader(byte misId, ISubTsHandler subTsHandler)
public BfbsGseReader(GsContextDto context)
{
_misId = misId;
_subTsHandler = subTsHandler;
this.Context = context;
}
public void PushFrame(BBHeader bbHeader, ReadOnlySpan<byte> readOnlySpan)
{
frameNo++;
@ -51,68 +52,171 @@ namespace skyscraper8.GS.GSE_BFBS
}
else
{
GsePacket gsePacket = new GsePacket(startIndicator, endIndicator, labelTypeIndicator);
int gseLength = (byteA & 0x0f) << 8;
gseLength += span.ReadUInt8();
byte? fragId = null;
gsePacket.FragmentId = null;
if (!startIndicator || !endIndicator)
{
fragId = span.ReadUInt8();
gsePacket.FragmentId = span.ReadUInt8();
gseLength -= 1;
}
ushort? totalLength = null;
if ((startIndicator) && !endIndicator)
{
totalLength = span.ReadUInt16BE();
gsePacket.TotalLength = span.ReadUInt16BE();
gseLength -= 2;
}
GseLabel label = null;
ushort? protocolType = null;
if (startIndicator)
{
protocolType = span.ReadUInt16BE();
gsePacket.ProtocolType = span.ReadUInt16BE();
gseLength -= 2;
if (labelTypeIndicator == 0)
{
label = new _6byteLabel(span.ReadBytes(6));
gsePacket.Label = new _6byteLabel(span.ReadBytes(6));
gseLength -= 6;
}
else if (labelTypeIndicator == 1)
{
label = new _3byteLabel(span.ReadBytes(3));
gsePacket.Label = new _3byteLabel(span.ReadBytes(3));
gseLength -= 3;
}
else if (labelTypeIndicator == 2)
{
label = BroadcastLabel.GetInstance();
gsePacket.Label = BroadcastLabel.GetInstance();
}
else if (labelTypeIndicator == 3)
{
label = lastLabel;
gsePacket.Label = lastLabel;
}
lastLabel = gsePacket.Label;
}
if (!startIndicator && endIndicator)
gseLength -= 4;
ReadOnlySpan<byte> gseDataBytes = span.ReadBytes(gseLength);
uint? crc32 = null;
gsePacket.GseDataBytes = span.ReadBytes(gseLength);
if (!startIndicator && endIndicator)
{
crc32 = span.ReadUInt32BE();
gsePacket.Crc32 = span.ReadUInt32BE();
}
HandleGseFrame(startIndicator, endIndicator, fragId, totalLength, label, protocolType, gseDataBytes, crc32);
HandleGseFrame(gsePacket);
}
}
}
private void HandleGseFrame(bool startIndicator, bool endIndicator, byte? fragId, ushort? totalLength, GseLabel label, ushort? protocolType, ReadOnlySpan<byte> gseDataBytes, uint? crc32)
private GseFragmentation[] fragmentations;
private void HandleGseFrame(GsePacket gsePacket)
{
//throw new NotImplementedException();
if (gsePacket.StartIndicator & gsePacket.EndIndicator)
{
HandleAssembledFrame(gsePacket.ProtocolType.Value, gsePacket.GseDataBytes);
return;
}
if (!gsePacket.StartIndicator && gsePacket.EndIndicator)
{
if (fragmentations == null)
{
//This stream had no fragmentations yet, so we cannot reassemble this packet.
return;
}
if (fragmentations[gsePacket.FragmentId.Value] == null)
{
//The previous fragments are missing, so we cannot reassemble this packet.
return;
}
fragmentations[gsePacket.FragmentId.Value].AddFragement(gsePacket);
if (fragmentations[gsePacket.FragmentId.Value].Validate())
{
byte[] gseDataBytes = fragmentations[gsePacket.FragmentId.Value].GetGseDataBytes();
ushort protocolType = fragmentations[gsePacket.FragmentId.Value].ProtocolType;
HandleAssembledFrame(protocolType, gseDataBytes);
fragmentations[gsePacket.FragmentId.Value] = null;
return;
}
else
{
throw new NotImplementedException();
}
}
if (gsePacket.StartIndicator && !gsePacket.EndIndicator)
{
fragmentations = new GseFragmentation[256];
fragmentations[gsePacket.FragmentId.Value] = new GseFragmentation(gsePacket);
return;
}
if (!gsePacket.StartIndicator && !gsePacket.EndIndicator)
{
if (fragmentations == null)
{
//This stream had no fragmentations yet, so we cannot reassemble this packet.
return;
}
if (fragmentations[gsePacket.FragmentId.Value] == null)
{
//The previous fragments are missing, so we cannot reassemble this packet.
return;
}
throw new NotImplementedException("Frames without start and end indicators are not supported yet. Please consider submitting a sample.");
}
throw new NotImplementedException();
}
private void HandleAssembledFrame(ushort protocolType, byte[] buffer)
{
switch (protocolType)
{
case 0x0081:
//Network clock reference
HandleNetworkClockReference(buffer);
return;
case 0x0082:
//Lower Layer Signalling, see en_30154502v010401p.pdf, page 49
HandleLowerLayerSignalling(buffer);
return;
case 0x0091:
//according to https://www.iana.org/assignments/ule-next-headers/ule-next-headers.xhtml it's private
return;
case 0x0800:
Context.IpOutput.OnIpDatagram(0x010e, buffer);
return;
default:
throw new NotImplementedException(protocolType.ToString());
}
}
private GseL2SHandler rcs2;
private void HandleLowerLayerSignalling(byte[] buffer)
{
if (rcs2 == null)
{
rcs2 = new GseL2SHandler(Context);
}
rcs2.PushPacket(buffer);
}
private void HandleNetworkClockReference(byte[] buffer)
{
MemoryStream binaryReader = new MemoryStream(buffer);
uint pcrA = binaryReader.ReadUInt32BE();
ushort pcrB = binaryReader.ReadUInt16BE();
ulong pcr_base = ((ulong)pcrA << 1) | ((ulong)pcrB >> 15);
ulong pcr_ext = (ulong)pcrB & 0x01ff;
ulong PCR = pcr_base * 300 + pcr_ext;
ulong seconds = PCR / 27000000;
}
}
}

View File

@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using skyscraper8.InteractionChannel;
namespace skyscraper8.GS.GSE_BFBS
{
internal class GseL2SHandler
{
public GsContextDto Context { get; }
public GseL2SHandler(GsContextDto context)
{
Context = context;
}
public void PushPacket(byte[] buffer)
{
GseTableStructure gseTableStructure = new GseTableStructure(buffer);
switch (gseTableStructure.TableId)
{
default:
throw new NotImplementedException(String.Format(
"Unknown DVB-RCS2 Table Id: 0x{0:X2}\nIf this is reproducible on this stream, please consider submitting me a sample.",
gseTableStructure.TableId));
}
}
}
}

View File

@ -1,24 +1,26 @@
using log4net;
using skyscraper5.Dvb.DataBroadcasting;
using skyscraper5.Skyscraper.IO;
using skyscraper8.GS;
using skyscraper8.GSE.GSE;
namespace skyscraper8.GSE.GSE_HEM;
public class GseHemReader : IMisHandler
class GseHemReader : IMisHandler
{
public GseHemReader(IMultiprotocolEncapsulationEventHandler mpeEventHandler)
public GseHemReader(GsContextDto context)
{
rayBuffer = new RayBuffer();
this.mpeEventHandler = mpeEventHandler;
this.Context = context;
}
private IMultiprotocolEncapsulationEventHandler mpeEventHandler;
private GseLabel lastLabel;
private RayBuffer rayBuffer;
private const int BUFFER_THRESHOLD = 65536 * 2; //Twice the maximum PDU size of GSE. That way we can guarantee we have one full PDU in buffer.
private static readonly ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name);
public GsContextDto Context { get; set; }
public void PushFrame(BBHeader bbHeader, ReadOnlySpan<byte> readOnlySpan)
{
MemoryStream ms = new MemoryStream(readOnlySpan.ToArray());
@ -101,7 +103,7 @@ public class GseHemReader : IMisHandler
switch (packet.ProtocolType)
{
case 0x0800:
mpeEventHandler.OnIpDatagram(0x010e,packet.GseDataBytes);
Context.IpOutput.OnIpDatagram(0x010e,packet.GseDataBytes);
return;
default:
logger.WarnFormat("This GSE-HEM stream contains traffic other than IP. IP is type 0x0800, but we got 0x{0:X4} here.", packet.ProtocolType);

View File

@ -7,10 +7,22 @@ public class GseFragmentation
this.ProtocolType = child.ProtocolType.Value;
this.Label = child.Label;
AddFragement(child);
this.TotalLength = child.TotalLength.Value;
this.Crc32 = child.Crc32;
}
public uint Crc32 { get; set; }
public ushort TotalLength { get; set; }
private List<byte[]> fragments;
public bool Validate()
{
//TODO: Implement proper CRC-32 checking here
return true;
}
public void AddFragement(GsePacket packet)
{
if (fragments == null)
@ -23,12 +35,11 @@ public class GseFragmentation
public ushort ProtocolType { get; private set; }
public bool Validate()
{
//To be implemented...
return true;
}
/// <summary>
/// Assembles the payload
/// </summary>
/// <returns>The concatenated GSE Data Bytes of each packet.</returns>
public byte[] GetGseDataBytes()
{
int totalLength = fragments.Select(x => x.Length).Sum();

View File

@ -6,6 +6,8 @@ public abstract class GseLabel
{
public abstract int Length { get; }
public abstract string ToString();
public abstract int LabelTypeIndicator { get; }
}
public class _6byteLabel : GseLabel
@ -23,6 +25,7 @@ public class _6byteLabel : GseLabel
}
public override int Length => 6;
public override int LabelTypeIndicator => 0;
}
public class _3byteLabel : GseLabel
@ -53,6 +56,8 @@ public class _3byteLabel : GseLabel
}
override public int Length => 3;
public override int LabelTypeIndicator => 1;
}
public class BroadcastLabel : GseLabel
@ -75,4 +80,6 @@ public class BroadcastLabel : GseLabel
}
return _instance;
}
public override int LabelTypeIndicator => 2;
}

View File

@ -1,14 +1,17 @@
using log4net;
using skyscraper5.Dvb.DataBroadcasting;
using skyscraper5.Skyscraper.IO;
using skyscraper8.GS;
namespace skyscraper8.GSE.GSE;
internal class GseReader : IMisHandler
{
private GseLabel lastLabel;
public IMultiprotocolEncapsulationEventHandler mpeEventHandler { get; set; }
private static readonly ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name);
public GsContextDto Context { get; set; }
public void PushFrame(BBHeader bbHeader, ReadOnlySpan<byte> readOnlySpan)
{
MemoryStream ms = new MemoryStream(readOnlySpan.ToArray());
@ -115,7 +118,7 @@ internal class GseReader : IMisHandler
currentFragmentation.AddFragement(child);
if (currentFragmentation.Validate())
{
mpeEventHandler.OnIpDatagram(0x010e,currentFragmentation.GetGseDataBytes());
Context.IpOutput.OnIpDatagram(0x010e,currentFragmentation.GetGseDataBytes());
}
fragmentations[child.FragmentId.Value] = null;
@ -150,7 +153,7 @@ internal class GseReader : IMisHandler
switch (child.ProtocolType)
{
case 0x0800:
mpeEventHandler.OnIpDatagram(0x010e, child.GseDataBytes);
Context.IpOutput.OnIpDatagram(0x010e, child.GseDataBytes);
break;
default:
if (warnedEthertypes == null)

View File

@ -0,0 +1,53 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using skyscraper5.Dvb.DataBroadcasting;
using skyscraper5.src.InteractionChannel;
using skyscraper8.Skyscraper.Scraper;
namespace skyscraper8.GS
{
internal class GsContextDto
{
public GsContextMisDto MisClone(byte mis)
{
GsContextMisDto misClone = new GsContextMisDto(mis);
Type type = this.GetType();
PropertyInfo[] propertyInfos = type.GetProperties();
foreach (PropertyInfo propertyInfo in propertyInfos)
{
object? value = propertyInfo.GetValue(this);
propertyInfo.SetValue(misClone, value);
}
return misClone;
}
public byte GetMisId()
{
GsContextMisDto misDto = this as GsContextMisDto;
if (misDto == null)
return 0;
return misDto.Mis;
}
public ISubTsHandler TsOutput { get; set; }
public IMultiprotocolEncapsulationEventHandler IpOutput { get; set; }
public InteractionChannelHandler Rcs2Output { get; set; }
}
internal class GsContextMisDto : GsContextDto
{
public byte Mis { get; }
public GsContextMisDto(byte mis)
{
Mis = mis;
}
}
}

View File

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace skyscraper8.GS
{
public class GsException : Exception
{
public GsException()
{
}
public GsException(string message) : base(message)
{
}
public GsException(string message, Exception inner) : base(message, inner)
{
}
}
}

View File

@ -1,5 +1,6 @@
using log4net;
using skyscraper5.Dvb.DataBroadcasting;
using skyscraper8.GS;
using skyscraper8.GS.GSE_BFBS;
using skyscraper8.GS.SiminnRadiomidun;
using skyscraper8.GSE.GSE_HEM;
@ -8,17 +9,16 @@ using skyscraper8.Skyscraper.Scraper;
namespace skyscraper8.GSE;
public class GsTypeDetector : IMisHandler
class GsTypeDetector : IMisHandler
{
public IMultiprotocolEncapsulationEventHandler mpeEventHandler { get; set; }
private readonly byte _misId;
private readonly ILog logger;
public GsContextDto Context { get; set; }
private readonly ILog logger;
private HashSet<Tuple<int, byte>> _postedStreamTypes;
public ISubTsHandler subTsHandler;
public GsTypeDetector(byte misId)
public GsTypeDetector(GsContextMisDto context)
{
_misId = misId;
logger = LogManager.GetLogger(String.Format("{0} MIS {1}",System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name,misId));
this.logger = LogManager.GetLogger(String.Format("{0} MIS {1}",System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name,context.Mis));
this.Context = context;
}
private GseReader gseReader;
@ -41,7 +41,7 @@ public class GsTypeDetector : IMisHandler
if (gseReader == null)
{
gseReader = new GseReader();
gseReader.mpeEventHandler = mpeEventHandler;
gseReader.Context = Context;
}
gseReader.PushFrame(bbHeader, readOnlySpan);
@ -53,7 +53,7 @@ public class GsTypeDetector : IMisHandler
//Looks like GSE-HEM
if (gseHemReader == null)
{
gseHemReader = new GseHemReader(mpeEventHandler);
gseHemReader = new GseHemReader(Context);
}
gseHemReader.PushFrame(bbHeader, readOnlySpan);
return;
@ -68,7 +68,7 @@ public class GsTypeDetector : IMisHandler
if (siminnRadiomidunReader == null)
{
//These behave similar to T2-MI. Interesting.
siminnRadiomidunReader = new SiminnRadiomidunReader(_misId,subTsHandler);
siminnRadiomidunReader = new SiminnRadiomidunReader(Context);
}
siminnRadiomidunReader.PushFrame(bbHeader, readOnlySpan);
@ -89,7 +89,7 @@ public class GsTypeDetector : IMisHandler
{
if (bfbsGseReader == null)
{
bfbsGseReader = new BfbsGseReader(_misId, subTsHandler);
bfbsGseReader = new BfbsGseReader(Context);
}
bfbsGseReader.PushFrame(bbHeader, readOnlySpan);

View File

@ -1,6 +1,10 @@
using skyscraper8.GS;
namespace skyscraper8.GSE;
public interface IMisHandler
interface IMisHandler
{
public GsContextDto Context { get; set; }
void PushFrame(BBHeader bbHeader, ReadOnlySpan<byte> readOnlySpan);
}

View File

@ -44,7 +44,7 @@ public class Pts2Bbf
FileStream fileStream = file.OpenRead();
TsContext mpeg2 = new TsContext();
mpeg2.RegisterPacketProcessor(0x010e, new Stid135BbFrameReader(null, null, dumper));
mpeg2.RegisterPacketProcessor(0x010e, new Stid135BbFrameReader(null, dumper));
DataStorage dataStorage = new InMemoryScraperStorage();
ObjectStorage objectStorage = new NullObjectStorage();
SkyscraperContext skyscraper = new SkyscraperContext(mpeg2, dataStorage, objectStorage);

View File

@ -25,7 +25,7 @@ public class Pts2Bbf2 : IBbframeDeencapsulator
public void Run()
{
TsContext mpeg2 = new TsContext();
Stid135BbFrameReader bbFrameReader = new Stid135BbFrameReader(null, null, this);
Stid135BbFrameReader bbFrameReader = new Stid135BbFrameReader(null, this);
mpeg2.RegisterPacketProcessor(0x010e, bbFrameReader);
SkyscraperContext context = new SkyscraperContext(mpeg2, new InMemoryScraperStorage(), new NullObjectStorage());

View File

@ -3,6 +3,7 @@ using skyscraper5.Mpeg2;
using skyscraper5.Skyscraper.Scraper;
using skyscraper5.Skyscraper.Scraper.Storage.Filesystem;
using skyscraper5.Skyscraper.Scraper.Storage.InMemory;
using skyscraper8.GS;
using skyscraper8.Skyscraper.Scraper.Storage;
namespace skyscraper8.GSE;
@ -19,7 +20,8 @@ public class Stid135Test
ObjectStorage objectStorage = new FilesystemStorage(new DirectoryInfo("nip"));
SkyscraperContext skyscraper = new SkyscraperContext(mpeg2, dataStorage, objectStorage);
mpeg2.RegisterPacketProcessor(0x010e, new Stid135BbFrameReader(skyscraper,skyscraper));
GsContextDto context = new GsContextDto();
mpeg2.RegisterPacketProcessor(0x010e, new Stid135BbFrameReader(context));
skyscraper.InitalizeFilterChain();
skyscraper.IngestFromStream(fileStream);

View File

@ -13,19 +13,18 @@ namespace skyscraper8.GS.SiminnRadiomidun
{
internal class SiminnRadiomidunReader : IMisHandler
{
public SiminnRadiomidunReader(byte mis, ISubTsHandler tsOutput)
public SiminnRadiomidunReader(GsContextDto context)
{
this.packetQueue = new Queue<Tuple<BBHeader,MemoryStream>>();
this.isInSync = false;
this.subTsKey = new SiminnRadiomidunSubTsIdentifier(mis);
this.tsOutput = tsOutput;
this.subTsKey = new SiminnRadiomidunSubTsIdentifier(context.GetMisId());
this.Context = context;
}
private bool isInSync;
private Queue<Tuple<BBHeader, MemoryStream>> packetQueue;
private MemoryStream currentItem;
private SiminnRadiomidunSubTsIdentifier subTsKey;
private ISubTsHandler tsOutput;
public long PacketQueueSize
{
@ -37,6 +36,9 @@ namespace skyscraper8.GS.SiminnRadiomidun
return packetQueue.Select(x => x.Item2.Length).Sum();
}
}
public GsContextDto Context { get; set; }
public void PushFrame(BBHeader bbHeader, ReadOnlySpan<byte> readOnlySpan)
{
if (packetQueue == null)
@ -87,7 +89,7 @@ namespace skyscraper8.GS.SiminnRadiomidun
private void OutputPacket(byte[] buffer)
{
buffer[0] = 0x47;
tsOutput.OnSubTsPacket(subTsKey, buffer);
Context.TsOutput.OnSubTsPacket(subTsKey, buffer);
}
}
}

View File

@ -7,6 +7,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using skyscraper5.Dvb.DataBroadcasting;
using skyscraper8.GS;
using skyscraper8.Skyscraper.Scraper;
namespace skyscraper8.GSE
@ -15,10 +16,10 @@ namespace skyscraper8.GSE
{
private IBbframeDeencapsulator deencapsulator;
public Stid135BbFrameReader(IMultiprotocolEncapsulationEventHandler mpeEventHandler, ISubTsHandler subTsHandler, IBbframeDeencapsulator deencapsulator = null)
public Stid135BbFrameReader(GsContextDto context, IBbframeDeencapsulator deencapsulator = null)
{
if (deencapsulator == null)
deencapsulator = new BbframeDeencapsulator3(mpeEventHandler, subTsHandler);
deencapsulator = new BbframeDeencapsulator3(context);
this.deencapsulator = deencapsulator;
}

View File

@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using skyscraper5.Skyscraper.IO;
namespace skyscraper8.InteractionChannel
{
/// <summary>
/// Represents the structure in ETSI EN 301 545-2 V1.4.1, clause 6.4.3.1.1
/// </summary>
internal class GseTableStructure
{
public GseTableStructure(byte[] buffer)
{
MemoryStream ms = new MemoryStream(buffer, false);
TableId = ms.ReadUInt8();
InteractiveNetworkId = ms.ReadUInt16BE();
byte byteA = ms.ReadUInt8();
VersionNumber = (byteA & 0x3e) >> 1;
CurrentNextIndicator = (byteA & 0x01) != 0;
TableContent = ms.ReadBytes(ms.GetAvailableBytes());
}
public byte[] TableContent { get; private set; }
public bool CurrentNextIndicator { get; private set; }
public int VersionNumber { get; private set; }
public ushort InteractiveNetworkId { get; private set; }
public byte TableId { get; private set; }
}
}

View File

@ -62,7 +62,12 @@ namespace skyscraper5.src.InteractionChannel
switch (buffer[0])
{
case 0x40: //NIT
//see ETSI EN 301 545-2
InteractionChannelSiSectionHeader nitHeader = new InteractionChannelSiSectionHeader(ms);
if (!nitHeader.Valid)
{
_handler.OnInteractionChannelError(InteractionChannelErrorState.HeaderInvalid);
return;
}
throw new NotImplementedException("NIT");
case 0x41: //RMT
Rmt rmt = new Rmt(ms);

View File

@ -100,5 +100,12 @@ namespace skyscraper5.Mpeg2
}
public int BytesContained => receivedBytes;
internal static PsiSection FromByteArray(byte[] alreadyGathered)
{
PsiSection child = new PsiSection();
child.data = new MemoryStream(alreadyGathered, false);
return child;
}
}
}

View File

@ -2,7 +2,7 @@
"profiles": {
"skyscraper8": {
"commandName": "Project",
"commandLineArgs": "E:\\638951188146456482.ts",
"commandLineArgs": "\"E:\\638951188146456482.ts\"",
"remoteDebugEnabled": false
},
"Container (Dockerfile)": {

View File

@ -119,6 +119,11 @@ public class MpeEject : ISkyscraperMpePlugin
byte[] packetBuffer = new byte[188];
for (int i = 0; i < userDatagram.Payload.Length; i += 188)
{
if (!session.PrintedNotice)
{
logger.InfoFormat("Found a Transport Stream in IP packets: {0} -> {1}", sourceEndpoint, targetEndpoint);
session.PrintedNotice = true;
}
Array.Copy(userDatagram.Payload, i, packetBuffer, 0, 188);
subTsHandler.OnSubTsPacket(session, packetBuffer);
lastOutputSucessful = true;
@ -134,6 +139,8 @@ public class MpeEject : ISkyscraperMpePlugin
{
return lastOutputSucessful;
}
}
public class MpeEjectSession
@ -155,4 +162,5 @@ public class MpeEjectSession
}
public int ValidDatagrams { get; set; }
public bool PrintedNotice { get; set; }
}

View File

@ -74,12 +74,14 @@ using System.IO;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Reflection;
using System.Security.Policy;
using System.Text;
using skyscraper5.src.InteractionChannel.Model2;
using skyscraper8.Abertis;
using skyscraper8.Experimentals.NdsSsu;
using skyscraper8.Experimentals.OtvSsu;
using skyscraper8.GS;
using skyscraper8.GSE;
using skyscraper8.Ieee802_1AB;
using skyscraper8.InteractionChannel.Model2;
@ -306,7 +308,7 @@ namespace skyscraper5.Skyscraper.Scraper
{
if (!DvbContext.IsPidProcessorPresent(0x010e))
{
DvbContext.RegisterPacketProcessor(0x010e, new Stid135BbFrameReader(this, this));
DvbContext.RegisterPacketProcessor(0x010e, new Stid135BbFrameReader(CreateGsContext()));
UiJunction?.SetGseMode();
LogEvent(SkyscraperContextEvent.SpecialTsMode, "STiD135 encapsulated GS detected.");
SpecialTsType = 3;
@ -322,6 +324,29 @@ namespace skyscraper5.Skyscraper.Scraper
}
}
private GsContextDto CreateGsContext()
{
//Build the object
GsContextDto child = new GsContextDto();
child.IpOutput = this;
child.TsOutput = this;
child.Rcs2Output = this;
//for futureproofing
PropertyInfo[] properties = typeof(GsContextDto).GetProperties();
foreach (PropertyInfo propertyInfo in properties)
{
object? value = propertyInfo.GetValue(child);
if (value == null)
{
throw new SkyscraperException(String.Format("While creating the {0}, the {1} was not properly set. This is a bug, tell Fey.", nameof(GsContextDto), propertyInfo.Name));
}
}
//actually return the object
return child;
}
private DocsisPacketProcessor docsisPacketProcessor;
public int SpecialTsType { get; private set; }
private void CheckSpecialTs()
@ -361,7 +386,7 @@ namespace skyscraper5.Skyscraper.Scraper
{
if (!DvbContext.IsPidProcessorPresent(0x010e))
{
DvbContext.RegisterPacketProcessor(0x010e, new Stid135BbFrameReader(this, this));
DvbContext.RegisterPacketProcessor(0x010e, new Stid135BbFrameReader(CreateGsContext()));
UiJunction?.SetGseMode();
LogEvent(SkyscraperContextEvent.SpecialTsMode, "STiD135 encapsulated GS detected.");
SpecialTsType = 3;