Preparations for BFBS Navy TV.
Some checks failed
🚀 Pack skyscraper8 / make-zip (push) Failing after 2m18s
Some checks failed
🚀 Pack skyscraper8 / make-zip (push) Failing after 2m18s
This commit is contained in:
parent
124bf9eb49
commit
8f2c31f10d
@ -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:
|
||||
|
||||
|
||||
@ -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"><SessionState ContinuousTestingMode="0" IsActive="True" Name="All tests from &lt;skyscraper8.Tests&gt;" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session">
|
||||
<Project Location="/home/schiemas/RiderProjects/skyscraper8/skyscraper8.Tests" Presentation="&lt;skyscraper8.Tests&gt;" />
|
||||
<s:String x:Key="/Default/Environment/UnitTesting/UnitTestSessionStore/Sessions/=94eea68c_002Dcaa0_002D4657_002Da521_002D7b96c8ead0ec/@EntryIndexedValue"><SessionState ContinuousTestingMode="0" IsActive="True" Name="All tests from &lt;skyscraper8.Tests&gt;" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session">
|
||||
<Project Location="\home\schiemas\RiderProjects\skyscraper8\skyscraper8.Tests" Presentation="&lt;skyscraper8.Tests&gt;" />
|
||||
</SessionState></s:String>
|
||||
|
||||
|
||||
|
||||
@ -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));
|
||||
|
||||
@ -1,28 +1,29 @@
|
||||
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)
|
||||
@ -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);
|
||||
gsePacket.GseDataBytes = span.ReadBytes(gseLength);
|
||||
|
||||
uint? crc32 = null;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
31
skyscraper8/GS/GSE-BFBS/GseL2SHandler.cs
Normal file
31
skyscraper8/GS/GSE-BFBS/GseL2SHandler.cs
Normal 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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;
|
||||
}
|
||||
@ -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)
|
||||
|
||||
53
skyscraper8/GS/GsContextDto.cs
Normal file
53
skyscraper8/GS/GsContextDto.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
23
skyscraper8/GS/GsException.cs
Normal file
23
skyscraper8/GS/GsException.cs
Normal 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)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
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);
|
||||
|
||||
@ -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);
|
||||
}
|
||||
@ -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);
|
||||
|
||||
@ -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());
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
38
skyscraper8/InteractionChannel/GseTableStructure.cs
Normal file
38
skyscraper8/InteractionChannel/GseTableStructure.cs
Normal 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; }
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
"profiles": {
|
||||
"skyscraper8": {
|
||||
"commandName": "Project",
|
||||
"commandLineArgs": "E:\\638951188146456482.ts",
|
||||
"commandLineArgs": "\"E:\\638951188146456482.ts\"",
|
||||
"remoteDebugEnabled": false
|
||||
},
|
||||
"Container (Dockerfile)": {
|
||||
|
||||
@ -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; }
|
||||
}
|
||||
@ -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;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user