fey 73aca11936
All checks were successful
🚀 Pack skyscraper8 / make-zip (push) Successful in 48s
Prepared ISDB Table parsing.
2026-08-19 22:29:32 +02:00

279 lines
12 KiB
C#

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using skyscraper5.Dvb.Descriptors;
using skyscraper5.Dvb.Psi.Model;
using skyscraper5.Mpeg2;
using skyscraper5.Mpeg2.Descriptors;
using skyscraper5.Skyscraper.IO;
using skyscraper5.Skyscraper.IO.CrazycatStreamReader;
using skyscraper5.Skyscraper.Plugins;
using skyscraper8.Dvb.Descriptors.Extension;
using skyscraper8.Skyscraper;
namespace skyscraper5.Dvb.Psi
{
public class EitParser : IPsiProcessor, IMultistandardTable
{
public EitParser(IEitEventHandler eventHandler)
{
this.EventHandler = eventHandler;
}
public IEitEventHandler EventHandler { get; private set; }
public void GatherPsi(PsiSection section, int sourcePid)
{
byte[] buffer = section.GetDataCopy();
MemoryStream ms = new MemoryStream(buffer, false);
byte tableId = ms.ReadUInt8();
ushort readUInt16Be = ms.ReadUInt16BE();
bool sectionSyntaxIndicator = (readUInt16Be & 0x8000) != 0;
if (!sectionSyntaxIndicator)
{
//According to en_300468v011601p.pdf, page 34 this shall be set to true
return;
}
int sectionLength = (readUInt16Be & 0x0fff);
bool isActualTs = false;
if (tableId == 0x4e)
isActualTs = true;
else if (tableId == 0x4f)
isActualTs = false;
else if (tableId >= 0x50 && tableId <= 0x5f)
isActualTs = true;
else if (tableId >= 0x60 && tableId <= 0x6f)
isActualTs = false;
else if (tableId < 0x4e)
return;
else if (tableId >= 0x70)
return;
else
throw new NotImplementedException("wait, what?");
if (ms.Length <= 14)
return;
ushort serviceId = ms.ReadUInt16BE();
byte readUInt8 = ms.ReadUInt8();
int versionNumber = (readUInt8 & 0x3e);
bool currentNextIndicator = (readUInt8 & 0x01) != 0;
byte sectionNumber = ms.ReadUInt8();
byte lastSectionNumber = ms.ReadUInt8();
ushort transportStreamId = ms.ReadUInt16BE();
ushort originalNetworkId = ms.ReadUInt16BE();
if (isActualTs)
{
EventHandler.SetTransportStreamId(transportStreamId);
EventHandler.SetNetworkId(originalNetworkId);
}
byte segmentLastSectionNumber = ms.ReadUInt8();
byte lastTableId = ms.ReadUInt8();
while ((ms.Length - ms.Position) > 7)
{
EitEvent eitEvent = new EitEvent(serviceId, transportStreamId, originalNetworkId);
eitEvent.EventId = ms.ReadUInt16BE();
DateTime? tmp = ms.ReadEtsiEn300468AnnexCDateTime();
if (tmp == null)
{
return;
}
eitEvent.StartTime = tmp.Value;
eitEvent.Duration = ReadEitDuration(ms);
readUInt16Be = ms.ReadUInt16BE();
eitEvent.RunningStatus = (RunningStatus)((readUInt16Be & 0xe000) >> 13);
eitEvent.FreeCa = (readUInt16Be & 0x1000) != 0;
int descriptorsLoopLength = readUInt16Be & 0x0fff;
if (ms.GetAvailableBytes() < descriptorsLoopLength)
break;
byte[] readBytes = ms.ReadBytes(descriptorsLoopLength);
UnpackDescriptors(readBytes, eitEvent);
if (!string.IsNullOrEmpty(eitEvent.EventName))
EventHandler.OnEitEvent(eitEvent);
else
return;
}
uint crc32 = ms.ReadUInt32BE();
}
private static TimeSpan ReadEitDuration(MemoryStream ms)
{
long hours = ms.ReadUInt8().UnpackBcd();
long minutes = ms.ReadUInt8().UnpackBcd();
long seconds = ms.ReadUInt8().UnpackBcd();
return new TimeSpan((int)hours, (int)minutes, (int)seconds);
}
private void UnpackDescriptors(byte[] input, EitEvent output)
{
IEnumerable<TsDescriptor> dvbDescriptors = TsDescriptorUnpacker.GetInstance().UnpackDescriptors(input, GetTableType());
foreach (TsDescriptor dvbDescriptor in dvbDescriptors)
{
string name = dvbDescriptor.GetType().Name;
switch (name)
{
case nameof(ShortEventDescriptor):
ShortEventDescriptor shortEventDescriptor = (ShortEventDescriptor)dvbDescriptor;
if (string.IsNullOrEmpty(shortEventDescriptor.Text) && string.IsNullOrEmpty(shortEventDescriptor.EventName))
return;
output.Iso639LanguageCode = shortEventDescriptor.Iso639LanguageCode;
output.EventName = shortEventDescriptor.EventName;
output.Text = shortEventDescriptor.Text;
break;
case nameof(ExtendedEventDescriptor):
ExtendedEventDescriptor extendedEventDescriptor = (ExtendedEventDescriptor)dvbDescriptor;
if (extendedEventDescriptor.Text == null)
break;
if (!string.IsNullOrEmpty(output.Iso639LanguageCode))
{
if (!output.Iso639LanguageCode.Equals(extendedEventDescriptor.Iso639LanguageCode))
break;
}
else
{
output.Iso639LanguageCode = extendedEventDescriptor.Iso639LanguageCode;
}
extendedEventDescriptor.Items?.ForEach(output.AddItem);
if (output.ExtendedText == null)
output.ExtendedText = new string[extendedEventDescriptor.LastDescriptorNumber + 1];
if (extendedEventDescriptor.DescriptorNumber == output.ExtendedText.Length)
{
string[] resized = new string[output.ExtendedText.Length + 1];
Array.Copy(output.ExtendedText, 0, resized, 0, output.ExtendedText.Length);
output.ExtendedText = resized;
}
output.ExtendedText[extendedEventDescriptor.DescriptorNumber] = extendedEventDescriptor.Text;
break;
case nameof(PdcDescriptor):
PdcDescriptor pdcDescriptor = (PdcDescriptor)dvbDescriptor;
if (pdcDescriptor.Valid)
{
output.Pdc = new DateTime(output.StartTime.Year, pdcDescriptor.Month, pdcDescriptor.Day,
pdcDescriptor.Hour, pdcDescriptor.Minute, 0);
}
break;
case nameof(ComponentDescriptor):
ComponentDescriptor componentDescriptor = (ComponentDescriptor)dvbDescriptor;
if (!componentDescriptor.Valid)
break;
if (output.Components == null)
output.Components = new HashSet<ComponentDescriptor>();
output.Components.Add(componentDescriptor);
break;
case nameof(ContentDescriptor):
ContentDescriptor cd = (ContentDescriptor)dvbDescriptor;
output.Content = cd.Content;
break;
case nameof(PrivateDataSpecifierDescriptor):
output.PrivateDataSpecifier = ((PrivateDataSpecifierDescriptor)dvbDescriptor).PrivateDataSpecifier;
break;
case nameof(UserDefinedDescriptor):
if (!output.PrivateDataSpecifier.HasValue)
break;
TsDescriptor unpacked = UserDefinedDescriptorUnpacker.GetInstance().UnpackUserDefinedDescriptor((UserDefinedDescriptor)dvbDescriptor, output.PrivateDataSpecifier.Value, "EIT");
if (unpacked == null)
break;
HandleUserDefinedDescriptor(unpacked, output);
break;
case nameof(ParentalRatingDescriptor):
ParentalRatingDescriptor ratingDescriptor = (ParentalRatingDescriptor)dvbDescriptor;
output.ParentalRatings = ratingDescriptor.ParentalRatings;
break;
case nameof(LinkageDescriptor):
LinkageDescriptor ld = (LinkageDescriptor)dvbDescriptor;
output.Linkages.Add(ld);
break;
case nameof(CaIdentifierDescriptor):
CaIdentifierDescriptor cid = (CaIdentifierDescriptor)dvbDescriptor;
output.CaSystems = cid.CaSystemIds;
break;
case nameof(TimeShiftedEventDescriptor):
TimeShiftedEventDescriptor tsed = (TimeShiftedEventDescriptor)dvbDescriptor;
output.ReferenceServiceId = tsed.ReferenceServiceId;
output.ReferenceEventId = tsed.ReferenceEventId;
break;
case nameof(ContentIdentifierDescriptor):
ContentIdentifierDescriptor coid = (ContentIdentifierDescriptor)dvbDescriptor;
output.Crids = coid.Crids;
break;
case nameof(FtaContentManagementDescriptor):
FtaContentManagementDescriptor fsnd = (FtaContentManagementDescriptor)dvbDescriptor;
output.ControlRemoteAccessOverInternet = fsnd.ControlRemoteAccessOverInternet;
output.DoNotApplyRevocation = fsnd.DoNotApplyRevocation;
output.DoNotScramble = fsnd.DoNotScramble;
break;
case nameof(_0x00_ImageIconDescriptor):
_0x00_ImageIconDescriptor iid = (_0x00_ImageIconDescriptor)dvbDescriptor;
if (iid.LastDescriptorNumber != 0)
{
if (output.IconComponents == null)
{
output.IconComponents = new _0x00_ImageIconDescriptor[iid.LastDescriptorNumber];
}
output.IconComponents[iid.DescriptiorNumber] = iid;
}
else
{
output.IconUrl = iid.Url;
output.IconData = iid.IconData;
output.IconType = iid.IconType;
output.IconVerticalOrigin = iid.IconVerticalOrigin;
output.IconHorizontalOrigin = iid.IconHorizontalOrigin;
output.IconCoordinateSystem = iid.CoordinateSystem;
output.IconTransportMode = iid.IconTransportMode;
}
break;
default:
throw new NotImplementedException(name);
}
}
}
private void HandleUserDefinedDescriptor(TsDescriptor unpacked, EitEvent output)
{
Attribute customAttribute = unpacked.GetType().GetCustomAttribute(typeof(DescriptorPluginEitHandlerAttribute));
if (customAttribute == null)
{
throw new NotImplementedException(String.Format("{0} has no {1} defined.", unpacked.GetType().Name, nameof(DescriptorPluginEitHandlerAttribute)));
}
DescriptorPluginEitHandlerAttribute handlerAttribute = (DescriptorPluginEitHandlerAttribute)customAttribute;
handlerAttribute.Handler.HandleEit(output, unpacked);
}
private STD_TYPE standard;
public void SetStandard(STD_TYPE standard)
{
this.standard = standard;
}
private string GetTableType()
{
if (IMultistandardTable.IsIsdb(standard))
{
return "ISDB EIT";
}
else
{
return "EIT";
}
}
}
}