Reeimplementing GS/GSE...
All checks were successful
🚀 Pack skyscraper8 / make-zip (push) Successful in 1m32s

This commit is contained in:
feyris-tan 2025-10-15 16:05:50 +02:00
parent c324a923de
commit 6e35f26528
18 changed files with 213 additions and 696 deletions

View File

@ -0,0 +1,82 @@
using skyscraper5.Skyscraper;
namespace skyscraper8.GSE;
public class BBHeader : Validatable
{
public BBHeader(byte[] bbframe, int offset)
{
ReadOnlySpan<byte> BbHeaderSpan = new ReadOnlySpan<byte>(bbframe, offset, 10);
//byte 1, MATYPE-1
TsGs = (BbHeaderSpan[0] & 0xc0) >> 6;
SisMis = (BbHeaderSpan[0] & 0x20) != 0; //1 single, 0 multi
CcmAcm = (BbHeaderSpan[0] & 0x10) != 0; //1 ccm, 0 acm
Issyi = (BbHeaderSpan[0] & 0x08) != 0; //
Npd = (BbHeaderSpan[0] & 0x04) != 0;
Ro = (BbHeaderSpan[0] & 0x03);
Matype2 = (BbHeaderSpan[1]);
UserPacketLength = BbHeaderSpan[2] << 8 | BbHeaderSpan[3];
UserPacketLength /= 8;
DataFieldLength = BbHeaderSpan[4] << 8 | BbHeaderSpan[5];
DataFieldLength /= 8;
SyncByte = BbHeaderSpan[6];
SyncD = BbHeaderSpan[7] << 8 | BbHeaderSpan[8];
ChecksumValid = DvbCrc8.Compute(BbHeaderSpan) == 0;
Valid = ChecksumValid;
}
public bool ChecksumValid { get; private set; }
public int SyncD { get; private set; }
public byte SyncByte { get; private set; }
public int DataFieldLength { get; private set; }
public int UserPacketLength { get; private set; }
/// <summary>
/// If MIS, this is the Input Stream Identifier
/// </summary>
public byte Matype2 { get; private set; }
/// <summary>
/// Transmission Roll-off factor
/// </summary>
public int Ro { get; private set; }
/// <summary>
/// Null Packet Deletion
/// </summary>
public bool Npd { get; private set; }
/// <summary>
/// If true, the ISSY field is inserted after UP
/// </summary>
public bool Issyi { get; set; }
/// <summary>
/// True if CCM, False if ACM
/// </summary>
public bool CcmAcm { get; private set; }
/// <summary>
/// True if SIS, False if MIS
/// </summary>
public bool SisMis { get; private set; }
/// <summary>
/// 0 = GS, packetized
/// 1 = GS, continuous
/// 2 = GSE-HEM
/// 3 = Transport
/// </summary>
public int TsGs { get; private set; }
}

View File

@ -0,0 +1,40 @@
using log4net;
namespace skyscraper8.GSE;
public class BbframeDeencapsulator3 : IBbframeDeencapsulator
{
private static readonly ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name);
private long numPushed;
public void PushPacket(byte[] bbframe)
{
//byte 0, sync byte
if (bbframe[0] != 0xb8)
{
if (numPushed == 0)
{
logger.InfoFormat("The stream started in the middle of a BBFrame, let's skip to the start of the next one.");
}
return;
}
numPushed++;
BBHeader bbHeader = new BBHeader(bbframe, 1);
if (!bbHeader.ChecksumValid)
return;
if (!bbHeader.Valid)
return;
if (mis == null)
mis = new IMisHandler[256];
if (mis[bbHeader.Matype2] == null)
{
logger.InfoFormat("Found a stream on MIS {0}",bbHeader.Matype2);
mis[bbHeader.Matype2] = new GsTypeDetector();
}
mis[bbHeader.Matype2].PushFrame(bbHeader, new ReadOnlySpan<byte>(bbframe, 11, bbframe.Length - 11));
}
private IMisHandler[] mis;
}

26
skyscraper8/GS/Crc8.cs Normal file
View File

@ -0,0 +1,26 @@
namespace skyscraper8.GSE;
public static class DvbCrc8
{
private const byte Polynomial = 0xD5; // x^8 + x^7 + x^6 + x^4 + x^2 + 1
public static byte Compute(ReadOnlySpan<byte> data)
{
byte crc = 0x00;
foreach (byte b in data)
{
crc ^= b; // XOR byte into top of crc register
for (int i = 0; i < 8; i++)
{
if ((crc & 0x80) != 0)
crc = (byte)((crc << 1) ^ Polynomial);
else
crc <<= 1;
}
}
return crc;
}
}

View File

@ -0,0 +1,9 @@
namespace skyscraper8.GSE;
public class GsTypeDetector : IMisHandler
{
public void PushFrame(BBHeader bbHeader, ReadOnlySpan<byte> readOnlySpan)
{
throw new NotImplementedException();
}
}

View File

@ -0,0 +1,6 @@
namespace skyscraper8.GSE;
public interface IMisHandler
{
void PushFrame(BBHeader bbHeader, ReadOnlySpan<byte> readOnlySpan);
}

View File

@ -11,7 +11,7 @@ public class Pts2Bbf
{
private static readonly ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name);
public static void Run(FileInfo file, bool useUdpDecap = false)
public static void Run(FileInfo file, bool useUdpDecap = false, IPEndPoint ipEndPoint = null)
{
if (!file.Exists)
{
@ -25,9 +25,13 @@ public class Pts2Bbf
string changeExtension = Path.ChangeExtension(file.FullName, ".sdecap");
BbfUdpDecap.UdpDecapFileOutput udpDecapSink = new BbfUdpDecap.UdpDecapFileOutput(new FileInfo(changeExtension));
if (ipEndPoint == null)
{
ipEndPoint = new IPEndPoint(IPAddress.Parse("239.199.2.1"), 1234);
}
BbfUdpDecap bbfUdpDecap = new BbfUdpDecap();
bbfUdpDecap.SetTargetPort(1234);
bbfUdpDecap.SetTargetIp(IPAddress.Parse("239.199.2.1"));
bbfUdpDecap.SetTargetPort(ipEndPoint.Port);
bbfUdpDecap.SetTargetIp(ipEndPoint.Address);
bbfUdpDecap.Sink = udpDecapSink;
dumper = bbfUdpDecap;
}
@ -40,7 +44,7 @@ public class Pts2Bbf
FileStream fileStream = file.OpenRead();
TsContext mpeg2 = new TsContext();
mpeg2.RegisterPacketProcessor(0x010e, new Stid135BbFrameReader(new NullGsEventHandler(),dumper));
mpeg2.RegisterPacketProcessor(0x010e, new Stid135BbFrameReader(dumper));
DataStorage dataStorage = new InMemoryScraperStorage();
ObjectStorage objectStorage = new NullObjectStorage();
SkyscraperContext skyscraper = new SkyscraperContext(mpeg2, dataStorage, objectStorage);

View File

@ -0,0 +1,29 @@
using log4net;
using skyscraper5.Mpeg2;
using skyscraper5.Skyscraper.Scraper;
using skyscraper5.Skyscraper.Scraper.Storage.InMemory;
using skyscraper8.Skyscraper.Scraper.Storage;
namespace skyscraper8.GSE;
public class Stid135Test
{
private static readonly ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name);
public static void Run(FileInfo file)
{
FileStream fileStream = file.OpenRead();
BbframeDeencapsulator3 decap = new BbframeDeencapsulator3();
TsContext mpeg2 = new TsContext();
mpeg2.RegisterPacketProcessor(0x010e, new Stid135BbFrameReader(decap));
DataStorage dataStorage = new InMemoryScraperStorage();
ObjectStorage objectStorage = new NullObjectStorage();
SkyscraperContext skyscraper = new SkyscraperContext(mpeg2, dataStorage, objectStorage);
skyscraper.InitalizeFilterChain();
skyscraper.IngestFromStream(fileStream);
fileStream.Close();
logger.Info("STiD135 Tester exiting");
}
}

View File

@ -11,15 +11,13 @@ namespace skyscraper8.GSE
{
internal class Stid135BbFrameReader : ITsPacketProcessor
{
private IGsEventHandler mpeEventHandler;
private IBbframeDeencapsulator deencapsulator;
public Stid135BbFrameReader(IGsEventHandler mpeEventHandler, IBbframeDeencapsulator deencapsulator = null)
public Stid135BbFrameReader(IBbframeDeencapsulator deencapsulator = null)
{
if (deencapsulator == null)
deencapsulator = new BbframeDeencapsulator();
deencapsulator = new BbframeDeencapsulator3();
this.mpeEventHandler = mpeEventHandler;
this.deencapsulator = deencapsulator;
}
@ -56,21 +54,6 @@ namespace skyscraper8.GSE
{
outbuf.Write(packets, 9, packets[7] - 1);
}
/*if ((packets[8] & 0xff) == 0xb8)
{
if (outbuf != null)
{
byte[] chi = outbuf.ToArray();
deencapsulator.PushPacket(chi);
}
outbuf = new MemoryStream();
outbuf.Write(packets,9, packets[7] - 1);
}
else
{
if (outbuf != null)
outbuf.Write(packets, 9, packets[7] - 1);
}*/
}
}
}

View File

@ -1,446 +0,0 @@
using skyscraper5.Mpeg2;
using skyscraper5.Skyscraper;
using skyscraper5.Skyscraper.IO;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;
using log4net;
namespace skyscraper8.GSE
{
internal class BbframeDeencapsulator : IBbframeDeencapsulator
{
private bool interruptedGseHem;
private MemoryStream interruptedGseHemBuffer;
private bool interruptedGseHemWantsCrc32;
public IGsEventHandler MpeEventHandler { get; set; }
private static readonly ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name);
private bool shownNonGseWarning;
public void PushPacket(byte[] bbframe)
{
MemoryStream ms = new MemoryStream(bbframe, false);
//BBHeader
byte matype1 = ms.ReadUInt8();
int tsGsField = (matype1 & 0xc0) >> 6;
bool sisMisField = (matype1 & 0x20) != 0;
bool ccmAcmField = (matype1 & 0x10) != 0;
bool issyi = (matype1 & 0x08) != 0;
bool npd = (matype1 & 0x04) != 0;
int ro = matype1 & 0x03;
byte matype2 = ms.ReadUInt8();
ushort userPacketLength = ms.ReadUInt16BE();
ushort dataFieldLength = ms.ReadUInt16BE();
byte sync = ms.ReadUInt8();
ushort syncd = ms.ReadUInt16BE();
byte crc8 = ms.ReadUInt8();
if (userPacketLength == 0 && dataFieldLength == 0)
return;
switch (tsGsField)
{
case 1:
if (sync != 0)
{
if (!shownNonGseWarning)
{
logger.WarnFormat("This stream is a valid GS, but also contains packets which are not GSE (type 0), but of type {0} . Please share a sample of this stream!", sync);
shownNonGseWarning = true;
}
return;
}
int bytes = dataFieldLength / 8;
if (ms.GetAvailableBytes() < bytes)
return;
HandleContinous(ms);
break;
case 2:
int hemBytes = dataFieldLength / 8;
if (ms.GetAvailableBytes() < hemBytes)
return;
HandleGseHem(ms);
break;
default: //0 = generic packetized, 1 = generic continouus, 2 = gse, 3 = ts
logger.Warn(string.Format("Unsupported: TS/GS field says 0x{0:X2}, please share a sample of this stream.", tsGsField));
break;
}
}
private GseFragmentation[] gseFragmentations;
private void HandleContinous(MemoryStream ms)
{
ms.Position = 10;
while (ms.GetAvailableBytes() > 0)
{
GsePacket packet = GsePacket.Read(ms);
if (packet.IsPadding)
{
break;
}
if (!packet.Valid)
{
break;
}
if (packet.IsCompletePacket)
{
if (ValidateEthertype(packet.ProtocolType.Value))
{
MpeEventHandler.OnIpDatagram(PID, packet.GseData);
}
else
{
logger.WarnFormat("Unknown EtherType: 0x{0:X4}", packet.ProtocolType.Value);
}
continue;
}
if (packet.StartIndicator && !packet.EndIndicator)
{
if (gseFragmentations == null)
gseFragmentations = new GseFragmentation[256];
gseFragmentations[packet.FragmentId.Value] = new GseFragmentation();
gseFragmentations[packet.FragmentId.Value].AddPacket(packet);
continue;
}
if (!packet.StartIndicator && packet.EndIndicator)
{
if (gseFragmentations == null)
continue;
if (gseFragmentations[packet.FragmentId.Value] == null)
continue;
gseFragmentations[packet.FragmentId.Value].AddPacket(packet);
continue;
}
if (!packet.StartIndicator && !packet.EndIndicator)
{
if (gseFragmentations == null)
continue;
throw new NotImplementedException();
}
throw new NotImplementedException();
}
}
private bool gseNeedMore;
private MemoryStream gseAssembler;
public int PID;
private void HandleGseHem(MemoryStream ms)
{
ms.Position = 10;
byte syncByte = ms.ReadUInt8();
ms.Position = 10;
long availableBytes = ms.GetAvailableBytes();
byte[] readBytes = ms.ReadBytes(availableBytes);
GseAssemblyState assemblyState = ValidateGse(gseAssembler, true);
if (assemblyState == GseAssemblyState.NOT_YET_BEGUN)
{
if ((syncByte & 0xc0) == 0xc0)
{
//Aktuell ist der GSE Assembler nicht beschäftigt, aber wir haben ein Sync-Byte, also kann er loslegen.
gseAssembler = new MemoryStream();
gseAssembler.Write(readBytes, 0, readBytes.Length);
return;
}
else
{
//Aktuell ist der GSE Assembler nicht beschäftigt, und wir haben kein gültiges Sync-Byte, also weg damit.
//Console.WriteLine("gse not in sync yet. sync byte = {0}", syncByte);
return;
}
}
else if (assemblyState == GseAssemblyState.NEED_MORE_DATA)
{
gseAssembler.Write(readBytes, 0, readBytes.Length);
return;
}
else if (assemblyState == GseAssemblyState.VALID)
{
gseAssembler.Position = 0;
AssembleGse(gseAssembler);
//Console.WriteLine("assembled {0} next sync byte is {1}", sucessfulAssembles++,syncByte);
if (sucessfulAssembles == 181)
{
}
gseAssembler = null;
HandleGseHem(ms);
return;
}
else if (assemblyState == GseAssemblyState.BROKEN_SUSPECT_ETHERTYPE)
{
gseAssembler = null;
HandleGseHem(ms);
return;
}
else if (assemblyState == GseAssemblyState.BROKEN_NEGATIVE_LENGTH)
{
gseAssembler = null;
HandleGseHem(ms);
return;
}
else
{
throw new NotImplementedException(string.Format("Unknown GSE assembler state: {0}, sync byte 0x{1}", assemblyState, syncByte));
}
}
private long sucessfulAssembles;
enum GseAssemblyState
{
NOT_YET_BEGUN,
VALID,
BROKEN_NEGATIVE_LENGTH,
NEED_MORE_DATA,
BROKEN_SUSPECT_LENGTH,
BROKEN_SUSPECT_ETHERTYPE,
VALID_NULL_PACKET, //somehow these only show up on TBS6903x, not DD Max SX8?
}
private GseAssemblyState ValidateGse(MemoryStream ms, bool tryFix = false)
{
if (ms == null)
return GseAssemblyState.NOT_YET_BEGUN;
long backupPosition = ms.Position;
ms.Position = 0;
while (ms.GetAvailableBytes() > 2)
{
long fixPosition = ms.Position;
//GSE-Header
byte byteA = ms.ReadUInt8();
bool startIndicator = (byteA & 0x80) != 0;
bool endIndicator = (byteA & 0x40) != 0;
int labelIndicator = (byteA & 0x30) >> 4;
if (!startIndicator && !endIndicator && labelIndicator == 0)
{
//end of base band frame
ms.Position = backupPosition;
return GseAssemblyState.VALID;
}
else
{
byte byteB = ms.ReadUInt8();
int gseLength = byteA & 0x0f;
gseLength <<= 8;
gseLength += byteB;
//Console.WriteLine("GSE Length: {0}", gseLength);
if (gseLength > 9000)
{
if (tryFix)
{
ms.Position = fixPosition;
ms.WriteUInt8Repeat(0, (int)ms.GetAvailableBytes());
break;
}
ms.Position = backupPosition;
return GseAssemblyState.BROKEN_SUSPECT_LENGTH;
}
if (!startIndicator || !endIndicator)
{
byte fragId = ms.ReadUInt8();
gseLength--;
}
if (startIndicator && !endIndicator)
{
if (2 > ms.GetAvailableBytes())
{
ms.Position = backupPosition;
return GseAssemblyState.NEED_MORE_DATA;
}
ushort totalLength = ms.ReadUInt16BE();
gseLength -= 2;
}
if (startIndicator)
{
if (2 > ms.GetAvailableBytes())
{
ms.Position = backupPosition;
return GseAssemblyState.NEED_MORE_DATA;
}
ushort protocolType = ms.ReadUInt16BE();
if (!ValidateEthertype(protocolType))
{
if (tryFix)
{
ms.Position = fixPosition;
ms.WriteUInt8Repeat(0, (int)ms.GetAvailableBytes());
break;
}
ms.Position = backupPosition;
return GseAssemblyState.BROKEN_SUSPECT_ETHERTYPE;
}
gseLength -= 2;
if (labelIndicator == 0)
{
if (6 > ms.GetAvailableBytes())
{
ms.Position = backupPosition;
return GseAssemblyState.NEED_MORE_DATA;
}
PhysicalAddress sixByteLabel = new PhysicalAddress(ms.ReadBytes(6));
gseLength -= 6;
}
else if (labelIndicator == 1)
{
byte[] threeByteLabel = ms.ReadBytes(3);
gseLength -= 3;
}
}
if (!startIndicator && endIndicator)
gseLength -= 4;
int startCrc32 = (int)ms.Position;
if (gseLength < 0)
{
if (tryFix)
{
ms.Position = fixPosition;
ms.WriteUInt8Repeat(0, (int)ms.GetAvailableBytes());
break;
}
ms.Position = backupPosition;
return GseAssemblyState.BROKEN_NEGATIVE_LENGTH;
}
if (gseLength > ms.GetAvailableBytes())
{
ms.Position = backupPosition;
return GseAssemblyState.NEED_MORE_DATA;
}
ms.Position += gseLength;
if (!startIndicator && endIndicator)
{
if (4 > ms.GetAvailableBytes())
{
ms.Position = backupPosition;
return GseAssemblyState.NEED_MORE_DATA;
}
uint crc32 = ms.ReadUInt32BE();
int endCrc32 = (int)ms.Position;
DvbCrc32.ValidateCrc(ms, startCrc32, endCrc32);
}
}
}
ms.Position = backupPosition;
return GseAssemblyState.VALID;
}
private bool ValidateEthertype(ushort ethertype)
{
if (ethertype == 0x0800)
return true; //IPv4
if (ethertype == 0x86DD)
return true; //IPv6
else
return false; //There are many more valid values, but since we don't speak anything aside from IPv4/IPv6, we discard it.
}
private void AssembleGse(MemoryStream ms)
{
ushort protocolType = 0;
while (ms.GetAvailableBytes() > 2)
{
//GSE-Header
byte byteA = ms.ReadUInt8();
bool startIndicator = (byteA & 0x80) != 0;
bool endIndicator = (byteA & 0x40) != 0;
int labelIndicator = (byteA & 0x30) >> 4;
if (!startIndicator && !endIndicator && labelIndicator == 0)
{
//end of base band frame
return;
}
else
{
byte byteB = ms.ReadUInt8();
int gseLength = byteA & 0x0f;
gseLength <<= 8;
gseLength += byteB;
if (!startIndicator || !endIndicator)
{
byte fragId = ms.ReadUInt8();
gseLength--;
}
if (startIndicator && !endIndicator)
{
ushort totalLength = ms.ReadUInt16BE();
gseLength -= 2;
}
if (startIndicator)
{
protocolType = ms.ReadUInt16BE();
gseLength -= 2;
if (labelIndicator == 0)
{
PhysicalAddress sixByteLabel = new PhysicalAddress(ms.ReadBytes(6));
gseLength -= 6;
}
else if (labelIndicator == 1)
{
byte[] threeByteLabel = ms.ReadBytes(3);
gseLength -= 3;
}
}
if (!startIndicator && endIndicator)
gseLength -= 4;
int startCrc32 = (int)ms.Position;
byte[] payload = ms.ReadBytes(gseLength);
if (!startIndicator && endIndicator)
{
uint crc32 = ms.ReadUInt32BE();
int endCrc32 = (int)ms.Position;
DvbCrc32.ValidateCrc(ms, startCrc32, endCrc32);
}
switch (protocolType)
{
case 0x0800: //IPv4
MpeEventHandler.OnIpDatagram(PID, payload);
break;
default:
//throw new NotImplementedException(String.Format("Unknown GSE Protocol ID 0x{0:X4}", protocolType));
break;
}
}
}
}
}
}

View File

@ -1,14 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace skyscraper5.Skyscraper
{
internal interface IGsEventHandler
{
void OnIpDatagram(int pid, byte[] payload);
void GsIpTrafficDetected();
}
}

View File

@ -1,26 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace skyscraper8.GSE
{
internal class GseFragmentation
{
public void AddPacket(GsePacket packet)
{
if (spanningGsePackets == null)
{
spanningGsePackets = new List<GsePacket>();
TotalLength = packet.TotalLength.Value;
}
spanningGsePackets.Add(packet);
}
public ushort TotalLength { get; private set; }
private List<GsePacket> spanningGsePackets;
}
}

View File

@ -1,167 +0,0 @@
using skyscraper5.Skyscraper.IO;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.NetworkInformation;
using System.Text;
using System.Threading.Tasks;
using skyscraper5.Skyscraper;
namespace skyscraper8.GSE
{
internal class GsePacket : Validatable
{
public static GsePacket Read(MemoryStream ms)
{
GsePacket packet = new GsePacket();
byte byteA = ms.ReadUInt8();
packet.StartIndicator = (byteA & 0x80) != 0;
packet.EndIndicator = (byteA & 0x40) != 0;
packet.LabelIndicator = (byteA & 0x30) >> 4;
if (!packet.StartIndicator && !packet.EndIndicator && packet.LabelIndicator == 0)
{
//End of baseband frame
return packet;
}
else
{
byte byteB = ms.ReadUInt8();
int gseLength = byteA & 0x0f;
gseLength <<= 8;
gseLength += byteB;
if (!packet.StartIndicator || !packet.EndIndicator)
{
packet.FragmentId = ms.ReadUInt8();
gseLength--;
}
if (packet.StartIndicator && !packet.EndIndicator)
{
packet.TotalLength = ms.ReadUInt16BE();
gseLength -= 2;
}
if (packet.StartIndicator)
{
packet.ProtocolType = ms.ReadUInt16BE();
gseLength -= 2;
if (packet.LabelIndicator == 0)
{
packet.Label = new SixByteGseLabel(ms.ReadBytes(6));
gseLength -= 6;
}
else if (packet.LabelIndicator == 1)
{
packet.Label = new ThreeByteGseLabel(ms.ReadBytes(3));
gseLength -= 3;
}
}
if (!packet.StartIndicator && packet.EndIndicator)
gseLength -= 4;
if (gseLength < 0)
{
packet.Valid = false;
return packet;
}
if (gseLength > ms.GetAvailableBytes())
{
packet.Valid = false;
return packet;
}
packet.GseData = ms.ReadBytes(gseLength);
if (!packet.StartIndicator && packet.EndIndicator)
packet.Crc32 = ms.ReadUInt32BE();
}
packet.Valid = true;
return packet;
}
public uint? Crc32 { get; set; }
public byte[] GseData { get; set; }
public GseLabel Label { get; set; }
public ushort? ProtocolType { get; set; }
public ushort? TotalLength { get; set; }
public byte? FragmentId { get; set; }
public int LabelIndicator { get; private set; }
public bool EndIndicator { get; private set; }
public bool StartIndicator { get; private set; }
public bool IsPadding
{
get
{
return !StartIndicator && !EndIndicator && LabelIndicator == 0;
}
}
public bool IsCompletePacket
{
get
{
return StartIndicator && EndIndicator;
}
}
}
public abstract class GseLabel : Validatable
{
public abstract int LabelLength { get; }
public abstract string ToString();
}
public class ThreeByteGseLabel : GseLabel
{
public ThreeByteGseLabel(byte[] buffer)
{
if (buffer.Length != 3)
{
Valid = false;
return;
}
LabelBytes = buffer;
Valid = true;
}
public byte[] LabelBytes { get; private set; }
public override string ToString()
{
return BitConverter.ToString(LabelBytes);
}
public override int LabelLength => 3;
}
public class SixByteGseLabel : GseLabel
{
public SixByteGseLabel(byte[] buffer)
{
if (buffer.Length != 6)
{
Valid = false;
return;
}
MacAddress = new PhysicalAddress(buffer);
Valid = true;
}
public PhysicalAddress MacAddress { get; private set; }
public override string ToString()
{
return MacAddress.ToString();
}
public override int LabelLength => 6;
}
}

View File

@ -1,16 +0,0 @@
using skyscraper5.Skyscraper;
namespace skyscraper8.GSE;
public class NullGsEventHandler : IGsEventHandler
{
public void OnIpDatagram(int pid, byte[] payload)
{
}
public void GsIpTrafficDetected()
{
}
}

View File

@ -323,6 +323,13 @@ namespace skyscraper5
return;
}
}
if (args[0].ToLowerInvariant().Equals("stid135test"))
{
FileInfo fi = new FileInfo(args[1]);
Stid135Test.Run(fi);
return;
}
}
/*Passing passing = new Passing();

View File

@ -92,7 +92,7 @@ namespace skyscraper5.Skyscraper.Scraper
IEitEventHandler, IAitEventHandler, ISubtitleEventHandler,
UpdateNotificationEventHandler, DataCarouselEventHandler, RdsEventHandler, IScte35EventHandler,
IAutodetectionEventHandler, IRstEventHandler, IRntEventHandler, IMultiprotocolEncapsulationEventHandler, ObjectCarouselEventHandler, T2MIEventHandler,
IDisposable, IFrameGrabberEventHandler, IntEventHandler, IRctEventHandler, IGsEventHandler, ISkyscraperContext, IDocsisEventHandler, AbertisDecoderEventHandler, Id3Handler,
IDisposable, IFrameGrabberEventHandler, IntEventHandler, IRctEventHandler, ISkyscraperContext, IDocsisEventHandler, AbertisDecoderEventHandler, Id3Handler,
InteractionChannelHandler, SgtEventHandler, IDvbNipEventHandler, UleEventHandler, OtvSsuHandler, NdsSsuHandler
{
public const bool ALLOW_STREAM_TYPE_AUTODETECTION = true;
@ -301,7 +301,7 @@ namespace skyscraper5.Skyscraper.Scraper
{
if (!DvbContext.IsPidProcessorPresent(0x010e))
{
DvbContext.RegisterPacketProcessor(0x010e, new Stid135BbFrameReader(this));
DvbContext.RegisterPacketProcessor(0x010e, new Stid135BbFrameReader());
UiJunction?.SetGseMode();
LogEvent(SkyscraperContextEvent.SpecialTsMode, "STiD135 encapsulated GS detected.");
SpecialTsType = 3;
@ -356,7 +356,7 @@ namespace skyscraper5.Skyscraper.Scraper
{
if (!DvbContext.IsPidProcessorPresent(0x010e))
{
DvbContext.RegisterPacketProcessor(0x010e, new Stid135BbFrameReader(this));
DvbContext.RegisterPacketProcessor(0x010e, new Stid135BbFrameReader());
UiJunction?.SetGseMode();
LogEvent(SkyscraperContextEvent.SpecialTsMode, "STiD135 encapsulated GS detected.");
SpecialTsType = 3;