feyris-tan 26beed9606
Some checks failed
🚀 Pack skyscraper8 / make-zip (push) Failing after 42s
Modernized the architecture for BAT and NIT.
2026-02-13 22:06:10 +01:00

307 lines
16 KiB
C#

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Reflection;
using skyscraper5.Dvb.Descriptors;
using skyscraper5.Dvb.Descriptors.Extension;
using skyscraper5.Dvb.Psi.Model;
using skyscraper5.Mpeg2;
using skyscraper5.Mpeg2.Descriptors;
using skyscraper5.Skyscraper.IO;
using skyscraper5.Skyscraper.Plugins;
namespace skyscraper5.Dvb.Psi
{
public class NitParser : IPsiProcessor
{
public INitEventHandler EventHandler { get; }
public NitParser(INitEventHandler eventHandler)
{
EventHandler = eventHandler;
}
public void GatherPsi(PsiSection section, int sourcePid)
{
MemoryStream ms = new MemoryStream(section.GetDataCopy());
byte tableId = ms.ReadUInt8();
bool actualNetwork;
switch (tableId)
{
case 0x40:
actualNetwork = true;
break;
case 0x41:
actualNetwork = false;
break;
case 0x72:
//stuffing area
return;
default:
return;
}
ushort readUInt16Be = ms.ReadUInt16BE();
bool sectionSyntaxSelector = (readUInt16Be & 0x8000) != 0;
if (!sectionSyntaxSelector)
return;
int sectionLength = readUInt16Be & 0x0fff;
ushort networkId = ms.ReadUInt16BE();
NitNetwork nitNetwork = new NitNetwork(networkId);
if (actualNetwork)
{
//I'd trust the NIT more than the EIT.
EventHandler.SetNetworkId(networkId,true);
}
byte readUInt8 = ms.ReadUInt8();
int versionNumber = (readUInt8 & 0x3e) >> 1;
bool currentNextIndicator = (readUInt8 & 0x01) != 0;
byte sectionNumber = ms.ReadUInt8();
byte lastSectionNumber = ms.ReadUInt8();
readUInt16Be = ms.ReadUInt16BE();
int networkDescriptorsLength = readUInt16Be & 0x0fff;
byte[] networkDescriptorsBuffer = ms.ReadBytes(networkDescriptorsLength);
IEnumerable<TsDescriptor> networkDescriptors = TsDescriptorUnpacker.GetInstance().UnpackDescriptors(networkDescriptorsBuffer, "NIT");
foreach (TsDescriptor dvbDescriptor in networkDescriptors)
{
switch (dvbDescriptor.GetType().Name)
{
case nameof(NetworkNameDescriptor):
NetworkNameDescriptor networkNameDescriptor = (NetworkNameDescriptor)dvbDescriptor;
nitNetwork.Name = networkNameDescriptor.NetworkName;
break;
case nameof(LinkageDescriptor):
LinkageDescriptor linkageDescriptor = (LinkageDescriptor)dvbDescriptor;
nitNetwork.Linkages.Add(linkageDescriptor);
break;
case nameof(PrivateDataSpecifierDescriptor):
nitNetwork.PrivateDataSpecifierId = ((PrivateDataSpecifierDescriptor)dvbDescriptor).PrivateDataSpecifier;
break;
case nameof(UserDefinedDescriptor):
if (!nitNetwork.PrivateDataSpecifierId.HasValue)
break;
TsDescriptor descriptor = UserDefinedDescriptorUnpacker.GetInstance().UnpackUserDefinedDescriptor((UserDefinedDescriptor)dvbDescriptor, nitNetwork.PrivateDataSpecifierId.Value, "NIT");
if (descriptor == null)
break;
switch (descriptor)
{
default:
throw new NotImplementedException(descriptor.GetType().Name);
}
break;
case nameof(CellListDescriptor):
nitNetwork.Cells = ((CellListDescriptor)dvbDescriptor).Cells;
break;
case nameof(XaitPidDescriptor):
XaitPidDescriptor xpd = (XaitPidDescriptor)dvbDescriptor;
nitNetwork.XaitPid = xpd.XaitPid;
break;
case nameof(MultilingualNetworkNameDescriptor):
MultilingualNetworkNameDescriptor mnnd = (MultilingualNetworkNameDescriptor)dvbDescriptor;
nitNetwork.MultilingualNetworkName = mnnd.MultilingualNetworkName;
break;
case nameof(TargetRegionNameDescriptor):
TargetRegionNameDescriptor trnd = (TargetRegionNameDescriptor)dvbDescriptor;
nitNetwork.RegionNames = trnd.Regions;
nitNetwork.RegionNameCountryCode = trnd.CountryCode;
nitNetwork.RegionNameLanguageCode = trnd.Iso639LanguageCode;
break;
case nameof(TargetRegionDescriptor):
TargetRegionDescriptor trd = (TargetRegionDescriptor)dvbDescriptor;
nitNetwork.Regions = trd.TargetRegions;
nitNetwork.RegionCountryCode = trd.CountryCode;
break;
case nameof(MessageDescriptor):
MessageDescriptor message = (MessageDescriptor)dvbDescriptor;
if (nitNetwork.Messages == null)
nitNetwork.Messages = new HashSet<MessageDescriptor>();
nitNetwork.Messages.Add(message);
break;
case nameof(UriLinkageDescriptor):
UriLinkageDescriptor uriLinkage = (UriLinkageDescriptor)dvbDescriptor;
nitNetwork.MinPollingInterval = uriLinkage.MinPollingInterval;
nitNetwork.Uri = uriLinkage.Uri;
nitNetwork.UriLinkageType = uriLinkage.UriLinkageType;
break;
case nameof(ServiceListDescriptor):
ServiceListDescriptor serviceList = (ServiceListDescriptor)dvbDescriptor;
nitNetwork.ServiceList = serviceList.Services;
break;
case nameof(ExtensionUserDefinedDescriptor):
ExtensionUserDefinedDescriptor eudd = (ExtensionUserDefinedDescriptor)dvbDescriptor;
//might be everything... idk...
break;
default:
throw new NotImplementedException(dvbDescriptor.GetType().Name);
}
}
readUInt16Be = ms.ReadUInt16BE();
int transportStreamLoopLength = readUInt16Be & 0x0fff;
byte[] transportStreamsBuffer = ms.ReadBytes(transportStreamLoopLength);
uint crc32 = ms.ReadUInt32BE();
ReadOnlyCollection<NitTransportStream> nitTransportStreams = UnpackTransportStreams(networkId, transportStreamsBuffer).ToList().AsReadOnly();
nitNetwork.Streams = nitTransportStreams;
EventHandler.OnNitNetwork(nitNetwork);
foreach (NitTransportStream stream in nitTransportStreams)
{
EventHandler.OnNitTransportStream(networkId, stream);
}
}
private IEnumerable<NitTransportStream> UnpackTransportStreams(ushort networkId, byte[] buffer)
{
MemoryStream ms = new MemoryStream(buffer, false);
while ((ms.Length - ms.Position) > 6)
{
ushort transportStreamId = ms.ReadUInt16BE();
ushort originalNetworkId = ms.ReadUInt16BE();
NitTransportStream child = new NitTransportStream(originalNetworkId, transportStreamId);
ushort readUInt16Be = ms.ReadUInt16BE();
int transportDescriptorsLength = readUInt16Be & 0x0fff;
if (transportDescriptorsLength > ms.GetAvailableBytes())
yield break;
byte[] transportDescriptorBuffer = ms.ReadBytes(transportDescriptorsLength);
IEnumerable<TsDescriptor> descriptors = TsDescriptorUnpacker.GetInstance().UnpackDescriptors(transportDescriptorBuffer, "NIT");
foreach (TsDescriptor dvbDescriptor in descriptors)
{
switch (dvbDescriptor.GetType().Name)
{
case nameof(SatelliteDeliverySystemDescriptor):
SatelliteDeliverySystemDescriptor satelliteDeliverySystemDescriptor = (SatelliteDeliverySystemDescriptor)dvbDescriptor;
child.East = satelliteDeliverySystemDescriptor.East;
child.FecInner = satelliteDeliverySystemDescriptor.FecInner;
child.Frequency = satelliteDeliverySystemDescriptor.Frequency;
child.ModulationType = satelliteDeliverySystemDescriptor.ModulationType;
child.OrbitalPosition = satelliteDeliverySystemDescriptor.OrbitalPosition;
child.Polarization = satelliteDeliverySystemDescriptor.Polarization;
child.RollOff = satelliteDeliverySystemDescriptor.RollOff;
child.S2 = satelliteDeliverySystemDescriptor.S2;
child.SymbolRate = satelliteDeliverySystemDescriptor.SymbolRate;
child.DeliveryMethod = NitTransportStream.TransportMedium.DVB_S;
break;
case nameof(ServiceListDescriptor):
ServiceListDescriptor sld = (ServiceListDescriptor)dvbDescriptor;
child.Services = sld;
break;
case nameof(S2SatelliteDeliverySystemDescriptor):
S2SatelliteDeliverySystemDescriptor s2sdsd = (S2SatelliteDeliverySystemDescriptor)dvbDescriptor;
child.ScramblingSequenceIndex = s2sdsd.ScramblingSequenceIndex;
child.InputStreamIdentifier = s2sdsd.InputStreamIdentifier;
child.TimesliceNumber = s2sdsd.TimesliceNumber;
child.TsGsMode = s2sdsd.TsGsMode;
if (child.East.HasValue)
{
child.S2 = true;
child.DeliveryMethod = NitTransportStream.TransportMedium.DVB_S2;
}
break;
case nameof(PrivateDataSpecifierDescriptor):
child.PrivateDataSpecifierId = ((PrivateDataSpecifierDescriptor)dvbDescriptor).PrivateDataSpecifier;
break;
case nameof(UserDefinedDescriptor):
if (!child.PrivateDataSpecifierId.HasValue)
break;
TsDescriptor unpacked = UserDefinedDescriptorUnpacker.GetInstance().UnpackUserDefinedDescriptor((UserDefinedDescriptor)dvbDescriptor, child.PrivateDataSpecifierId.Value, "NIT");
if (unpacked == null)
break;
HandleUserDefinedDescriptor(unpacked, child);
break;
case nameof(LinkageDescriptor):
child.Linkages.Add((LinkageDescriptor)dvbDescriptor);
break;
case nameof(T2DeliverySystemDescriptor):
child.DeliveryMethod = NitTransportStream.TransportMedium.DVB_T2;
T2DeliverySystemDescriptor t2dsd = (T2DeliverySystemDescriptor)dvbDescriptor;
child.TfsFlag = t2dsd.TfsFlag;
child.Bandwidth = t2dsd.Bandwidth;
child.CellInfos = t2dsd.CellInfos;
child.GuardInterval = t2dsd.GuardInterval;
child.OtherFrequencyFlag = t2dsd.OtherFrequencyFlag;
child.PlpId = t2dsd.PlpId;
child.SisoMiso = t2dsd.SisoMiso;
child.T2SystemId = t2dsd.T2SystemId;
child.TransmissionMode = t2dsd.TransmissionMode;
break;
case nameof(FrequencyListDescriptor):
FrequencyListDescriptor fld = (FrequencyListDescriptor)dvbDescriptor;
child.CodingType = fld.CodingType;
child.CentreFrequencies = fld.CentreFrequencies;
break;
case nameof(CellListDescriptor):
CellListDescriptor cld = (CellListDescriptor)dvbDescriptor;
child.Cells = cld.Cells;
break;
case nameof(CableDeliverySystemDescriptor):
CableDeliverySystemDescriptor cdsd = (CableDeliverySystemDescriptor)dvbDescriptor;
child.Frequency = cdsd.Frequency;
child.SymbolRate = cdsd.SymbolRate;
child.FecInner = cdsd.FecInner;
child.FecOuter = cdsd.FecOuter;
child.ModulationType = cdsd.Modulation;
child.DeliveryMethod = NitTransportStream.TransportMedium.DVB_C;
break;
case nameof(TerristialDeliverySystemDescriptor):
TerristialDeliverySystemDescriptor tdsd = (TerristialDeliverySystemDescriptor)dvbDescriptor;
child.Bandwidth = tdsd.Bandwidth;
child.Frequency = tdsd.CentreFrequency;
child.CodeRateHpStream = tdsd.CodeRateHpStream;
child.CodeRateLpStream = tdsd.CodeRateLpStream;
child.ModulationType = tdsd.Constellation;
child.GuardInterval = tdsd.GuardInterval;
child.HierarchyInformation = tdsd.HierarchyInformation;
child.MpeFecIndicator = tdsd.MpeFecIndicator;
child.OtherFrequencyFlag = tdsd.OtherFrequencyFlag;
child.Priority = tdsd.Priority;
child.TimeSlicingIndicator = tdsd.TimeSlicingIndicator ? 1 : 0;
child.TransmissionMode = tdsd.TransmissionMode;
break;
case nameof(NetworkNameDescriptor):
NetworkNameDescriptor nnd = (NetworkNameDescriptor)dvbDescriptor;
child.NetworkName = nnd.NetworkName;
break;
case nameof(TargetRegionDescriptor):
TargetRegionDescriptor trd = (TargetRegionDescriptor)dvbDescriptor;
child.TargetRegions = trd.TargetRegions;
child.TargetRegionCountryCode = trd.CountryCode;
break;
case nameof(CellFrequencyLinkDescriptor):
CellFrequencyLinkDescriptor cfld = (CellFrequencyLinkDescriptor)dvbDescriptor;
child.CellFrequencies = cfld.Cells;
break;
default:
throw new NotImplementedException(dvbDescriptor.GetType().Name);
}
}
yield return child;
//EventHandler.OnNitTransportStream(networkId, child);
}
}
private void HandleUserDefinedDescriptor(TsDescriptor unpacked, NitTransportStream outputTs)
{
Attribute customAttribute = unpacked.GetType().GetCustomAttribute(typeof(DescriptorPluginNitHandlerAttribute));
if (customAttribute == null)
{
throw new NotImplementedException(String.Format("{0} has no {1} defined.", unpacked.GetType().Name, nameof(DescriptorPluginNitHandlerAttribute)));
}
DescriptorPluginNitHandlerAttribute handlerAttribute = (DescriptorPluginNitHandlerAttribute)customAttribute;
handlerAttribute.Handler.HandleNit(outputTs, unpacked);
}
}
}