Can now parse ATSC3 PLPs.
All checks were successful
🚀 Pack skyscraper8 / make-zip (push) Successful in 56s

This commit is contained in:
feyris-tan 2026-06-03 22:59:24 +02:00
parent 885763f3e9
commit 3c6b5cf98e
6 changed files with 151 additions and 10 deletions

View File

@ -1,4 +1,5 @@
using skyscraper5.Ietf.Rfc971;
using log4net;
using skyscraper5.Ietf.Rfc971;
using skyscraper5.Skyscraper.IO;
using skyscraper8.Atsc.A330;
using skyscraper8.GSE.GSE_HEM;
@ -14,6 +15,16 @@ namespace skyscraper8.Atsc.A322
{
internal class AtscPlpBasebandParser
{
private readonly ushort _plpId;
private readonly IAtscPlpEventHandler _eventHandler;
public AtscPlpBasebandParser(ushort plpId, IAtscPlpEventHandler eventHandler)
{
_plpId = plpId;
_eventHandler = eventHandler;
}
private static readonly ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name);
private RayBuffer rayBuffer;
private const int MINIMUM_REQUIRED_RAY_LENGTH = 65535 * 2;
private const int MINIMUM_REQUIRED_RAY_PACKETS = 2;
@ -80,14 +91,14 @@ namespace skyscraper8.Atsc.A322
rayBuffer.Enqueue(new MemoryStream(bbHeaderStripped.ToArray(), false), pointer);
delivered_bbframes_total++;
if (pointer + 4 > bbHeaderStripped.Length)
/*if (pointer + 4 > bbHeaderStripped.Length)
{
Console.WriteLine("BBFRame, offset: {0}, less than four bytes left.", pointer);
}
else
{
Console.WriteLine("BBFRame, offset: {0}, first bytes: 0x{1:X2}{2:X2}{3:X2}{4:X2}", pointer, bbHeaderStripped[pointer], bbHeaderStripped[pointer + 1], bbHeaderStripped[pointer + 2], bbHeaderStripped[pointer + 3]);
}
}*/
while (rayBuffer.AvailableBytes >= MINIMUM_REQUIRED_RAY_LENGTH && rayBuffer.QueuedItems >= MINIMUM_REQUIRED_RAY_PACKETS)
{
@ -128,11 +139,45 @@ namespace skyscraper8.Atsc.A322
private List<AlpPacket> packets;
private void DeliverPacket(AlpPacket newPacket)
{
Console.WriteLine(newPacket.ToString());
//Console.WriteLine(newPacket.ToString());
delivered_alp_total++;
if (packets == null)
packets = new List<AlpPacket>();
packets.Add(newPacket);
switch (newPacket.PacketType)
{
case AlpPacketType.Ipv4:
HandleIpv4(newPacket.Payload);
break;
case AlpPacketType.LinkLayerSignalling:
HandleLinkLayerSignalling(newPacket.AdditionalHeaderForSignalingInformation, newPacket.Payload);
break;
default:
throw new NotImplementedException(String.Format("ALP Packet Type {0}", newPacket.PacketType));
}
}
private void HandleIpv4(byte[] newPacketPayload)
{
_eventHandler?.OnIpDatagram(0x1ffd, newPacketPayload);
}
private void HandleLinkLayerSignalling(AdditionalHeaderForSignalingInformation signalingInformation, byte[] payload)
{
if (signalingInformation.SignalingType == 1 && signalingInformation.SignalingTypeExtension == 0xffff &&
signalingInformation.SignalingFormat == 0 && signalingInformation.SignalingEncoding == 0)
{
LinkMappingTable lmt = new LinkMappingTable(payload);
if (lmt.ShouldRaiseEvent())
{
_eventHandler?.OnAtsc3LinkMappingTable(_plpId, signalingInformation, lmt);
}
}
else
{
logger.WarnFormat(
"Encountered unknown Link-Layer Signaling: Type = 0x{0:X2}, Type Extension = 0x{1:X4}, Format = 0x{2:X2}, Encoding = 0x{3:X2}",
signalingInformation.SignalingType, signalingInformation.SignalingTypeExtension,
signalingInformation.SignalingFormat, signalingInformation.SignalingEncoding);
}
}
private void HandleExtension(bool isLongExtension, int extType, Span<byte> extensionField)

View File

@ -0,0 +1,16 @@
using skyscraper5.Ietf.Rfc971;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using skyscraper8.Atsc.A330;
namespace skyscraper8.Atsc.A322
{
internal interface IAtscPlpEventHandler
{
void OnIpDatagram(int pid, byte[] payload);
void OnAtsc3LinkMappingTable(ushort plp, AdditionalHeaderForSignalingInformation signalingInformation, LinkMappingTable lmt);
}
}

View File

@ -158,7 +158,7 @@ namespace skyscraper8.Atsc.A324
}
if (plps[plp] == null)
{
plps[plp] = new AtscPlpBasebandParser();
plps[plp] = new AtscPlpBasebandParser(plp, context);
}
plps[plp].PushBbframe(rtpPayload);
}

View File

@ -8,7 +8,7 @@ using skyscraper5.Skyscraper.IO;
namespace skyscraper8.Atsc.A330
{
internal class AdditionalHeaderForSignalingInformation : Validatable
public class AdditionalHeaderForSignalingInformation : Validatable
{
public AdditionalHeaderForSignalingInformation(byte[] readBytes)
{

View File

@ -0,0 +1,72 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using skyscraper5.Skyscraper;
using skyscraper5.Skyscraper.IO;
namespace skyscraper8.Atsc.A330
{
public class LinkMappingTable : Validatable
{
public LinkMappingTable(byte[] buffer)
{
MemoryStream ms = new MemoryStream(buffer, false);
byte firstByte = ms.ReadUInt8();
int numPlps = (firstByte & 0xfc) >> 2;
numPlps++;
int reserved = (firstByte & 0x03);
LinkMappings = new LinkMappingTableEntry[numPlps];
for (int i = 0; i < numPlps; i++)
{
LinkMappings[i] = new LinkMappingTableEntry();
byte secondByte = ms.ReadUInt8();
LinkMappings[i].PlpId = (secondByte & 0xfc) >> 2;
reserved = (secondByte & 0x03);
byte numMulticasts = ms.ReadUInt8();
LinkMappings[i].Multicasts = new LinkMappingTableEntryMulticast[numMulticasts];
for (int j = 0; j < numMulticasts; j++)
{
throw new NotImplementedException("Link Mapping Table Multicast not supported yet.");
}
}
Valid = true;
}
public LinkMappingTableEntry[] LinkMappings;
public bool ShouldRaiseEvent()
{
foreach (LinkMappingTableEntry entry in LinkMappings)
{
foreach (LinkMappingTableEntryMulticast multicast in entry.Multicasts)
{
return true;
}
}
return false;
}
}
public class LinkMappingTableEntry
{
public int PlpId { get; set; }
public LinkMappingTableEntryMulticast[] Multicasts { get; set; }
}
public class LinkMappingTableEntryMulticast
{
}
}

View File

@ -88,6 +88,8 @@ using System.Net.NetworkInformation;
using System.Reflection;
using System.Text;
using System.Threading;
using skyscraper8.Atsc.A322;
using skyscraper8.Atsc.A330;
using Tsubasa.IO;
using Platform = skyscraper5.Dvb.SystemSoftwareUpdate.Model.Platform;
using RntParser = skyscraper5.Dvb.TvAnytime.RntParser;
@ -100,7 +102,7 @@ namespace skyscraper5.Skyscraper.Scraper
UpdateNotificationEventHandler, DataCarouselEventHandler, RdsEventHandler, IScte35EventHandler,
IAutodetectionEventHandler, IRstEventHandler, IRntEventHandler, IMultiprotocolEncapsulationEventHandler, ObjectCarouselEventHandler, T2MIEventHandler,
IDisposable, IFrameGrabberEventHandler, IntEventHandler, IRctEventHandler, ISkyscraperContext, IDocsisEventHandler, AbertisDecoderEventHandler, Id3Handler,
InteractionChannelHandler, SgtEventHandler, IDvbNipEventHandler, UleEventHandler, OtvSsuHandler, NdsSsuHandler, ISubTsHandler, ILldpFrameHandler, SisHandler, IWneHandler
InteractionChannelHandler, SgtEventHandler, IDvbNipEventHandler, UleEventHandler, OtvSsuHandler, NdsSsuHandler, ISubTsHandler, ILldpFrameHandler, SisHandler, IWneHandler, IAtscPlpEventHandler
{
public const bool ALLOW_STREAM_TYPE_AUTODETECTION = true;
public const bool ALLOW_FFMPEG_FRAMEGRABBER = true;
@ -1811,6 +1813,12 @@ namespace skyscraper5.Skyscraper.Scraper
}
}
public void OnAtsc3LinkMappingTable(ushort plp, AdditionalHeaderForSignalingInformation signalingInformation,
LinkMappingTable lmt)
{
throw new NotImplementedException();
}
public void GsIpTrafficDetected()
{
LogEvent(SkyscraperContextEvent.SpecialTsMode, "Valid IP Traffic detected");