217 lines
10 KiB
C#
217 lines
10 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
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;
|
|
|
|
namespace skyscraper5.Dvb.Psi
|
|
{
|
|
class SdtParser : IPsiProcessor
|
|
{
|
|
public ISdtEventHandler EventHandler { get; }
|
|
|
|
public SdtParser(ISdtEventHandler eventHandler)
|
|
{
|
|
EventHandler = eventHandler;
|
|
}
|
|
|
|
public void GatherPsi(PsiSection section, int sourcePid)
|
|
{
|
|
MemoryStream ms = new MemoryStream(section.GetDataCopy(),false);
|
|
|
|
byte tableId = ms.ReadUInt8();
|
|
if (tableId != 0x42 && tableId != 0x46)
|
|
return;
|
|
|
|
ushort readUInt16Be = ms.ReadUInt16BE();
|
|
bool sectionSyntaxIndicator = (readUInt16Be & 0x8000) != 0;
|
|
if (!sectionSyntaxIndicator)
|
|
return;
|
|
int sectionLength = (readUInt16Be & 0x0fff);
|
|
|
|
ushort transportStreamId = ms.ReadUInt16BE();
|
|
|
|
byte readUInt8 = ms.ReadUInt8();
|
|
int versionNumber = (readUInt8 & 0x3e);
|
|
bool currentNextIndicator = (readUInt8 & 0x01) != 0;
|
|
|
|
byte sectionNumber = ms.ReadUInt8();
|
|
|
|
byte lastSectionNumber = ms.ReadUInt8();
|
|
|
|
ushort originalNetworkId = ms.ReadUInt16BE();
|
|
ms.ReadUInt8(); //reserved future use
|
|
|
|
if (tableId == 0x42)
|
|
{
|
|
//0x42 meaning current mux
|
|
EventHandler.SetNetworkId(originalNetworkId);
|
|
EventHandler.SetTransportStreamId(transportStreamId);
|
|
}
|
|
|
|
while (ms.GetAvailableBytes() > 4)
|
|
{
|
|
ReadService(ms, transportStreamId, originalNetworkId);
|
|
}
|
|
|
|
uint crc32 = ms.ReadUInt32BE();
|
|
}
|
|
|
|
private void ReadService(MemoryStream ms, ushort transportStreamId, ushort originalNetworkId)
|
|
{
|
|
ushort serviceId = ms.ReadUInt16BE();
|
|
|
|
byte readUInt8 = ms.ReadUInt8();
|
|
bool eitScheduleFlag = (readUInt8 & 0x02) != 0;
|
|
bool eitPresentFollowingFlag = (readUInt8 & 0x01) != 0;
|
|
|
|
ushort readUInt16Be = ms.ReadUInt16BE();
|
|
int rs = (readUInt16Be & 0xe000) >> 13;
|
|
RunningStatus runningStatus = (RunningStatus)rs;
|
|
bool freeCaMode = (readUInt16Be & 0x1000) != 0;
|
|
int descriptorsLoopLength = readUInt16Be & 0xfff;
|
|
|
|
SdtService child = new SdtService(serviceId, eitScheduleFlag, eitPresentFollowingFlag, runningStatus, freeCaMode);
|
|
|
|
byte[] descriptorsData = ms.ReadBytes(descriptorsLoopLength);
|
|
IEnumerable<TsDescriptor> unpackDescriptors = TsDescriptorUnpacker.GetInstance().UnpackDescriptors(descriptorsData, "SDT");
|
|
foreach (TsDescriptor dvbDescriptor in unpackDescriptors)
|
|
{
|
|
string name = dvbDescriptor.GetType().Name;
|
|
switch (name)
|
|
{
|
|
case nameof(ServiceDescriptor):
|
|
ServiceDescriptor serviceDescriptor = (ServiceDescriptor)dvbDescriptor;
|
|
child.ServiceName = serviceDescriptor.ServiceName;
|
|
child.ServiceProviderName = serviceDescriptor.ServiceProviderName;
|
|
child.ServiceType = serviceDescriptor.ServiceType;
|
|
break;
|
|
case nameof(UserDefinedDescriptor):
|
|
if (!child.PrivateDataSpecifier.HasValue)
|
|
break;
|
|
TsDescriptor tsDescriptor = UserDefinedDescriptorUnpacker.GetInstance().UnpackUserDefinedDescriptor((UserDefinedDescriptor)dvbDescriptor, child.PrivateDataSpecifier.Value, "SDT");
|
|
if (tsDescriptor == null)
|
|
break;
|
|
ParseUserDefinedDescriptor(tsDescriptor, child);
|
|
break;
|
|
case nameof(PrivateDataSpecifierDescriptor):
|
|
child.PrivateDataSpecifier = ((PrivateDataSpecifierDescriptor)dvbDescriptor).PrivateDataSpecifier;
|
|
break;
|
|
case nameof(CaIdentifierDescriptor):
|
|
child.CaIdentifiers = ((CaIdentifierDescriptor)dvbDescriptor).CaSystemIds;
|
|
if (child.CaIdentifiers.Length > 1)
|
|
Array.Sort(child.CaIdentifiers);
|
|
break;
|
|
case nameof(ComponentDescriptor):
|
|
ComponentDescriptor cd = (ComponentDescriptor)dvbDescriptor;
|
|
if (child.Components == null)
|
|
child.Components = new List<ComponentDescriptor>();
|
|
child.Components.Add(cd);
|
|
break;
|
|
case nameof(DataBroadcastDescriptor):
|
|
DataBroadcastDescriptor dbd = (DataBroadcastDescriptor)dvbDescriptor;
|
|
child.ComponentTag = dbd.ComponentTag;
|
|
child.DataBroadcastId = dbd.DataBroadcastId;
|
|
child.Selector = dbd.Selector;
|
|
child.Iso639LanguageCode = dbd.Iso639LanguageCode;
|
|
child.Text = dbd.Text;
|
|
break;
|
|
case nameof(CountryAvailabilityDescriptor):
|
|
CountryAvailabilityDescriptor cad = (CountryAvailabilityDescriptor)dvbDescriptor;
|
|
foreach (string cadCountryCode in cad.CountryCodes)
|
|
{
|
|
if (child.CountryAvailability == null)
|
|
child.CountryAvailability = new Dictionary<string, bool>();
|
|
child.CountryAvailability.Add(cadCountryCode, cad.CountryAvailabilityFlag);
|
|
}
|
|
break;
|
|
case nameof(LinkageDescriptor):
|
|
LinkageDescriptor ld = (LinkageDescriptor)dvbDescriptor;
|
|
if (child.Linkages == null)
|
|
child.Linkages = new HashSet<LinkageDescriptor>();
|
|
child.Linkages.Add(ld);
|
|
break;
|
|
case nameof(TimeShiftedServiceDescriptor):
|
|
child.ReferenceServiceId = ((TimeShiftedServiceDescriptor)dvbDescriptor).ReferenceServiceId;
|
|
break;
|
|
case nameof(NvodReferenceDescriptor):
|
|
child.NvodReferences = ((NvodReferenceDescriptor)dvbDescriptor).NvodReferences;
|
|
break;
|
|
case nameof(ExtensionUserDefinedDescriptor):
|
|
if (!child.PrivateDataSpecifier.HasValue)
|
|
break;
|
|
TsDescriptor extTsDescriptor = UserDefinedDescriptorUnpacker.GetInstance().UnpackUserDefinedDescriptor((UserDefinedDescriptor)dvbDescriptor, child.PrivateDataSpecifier.Value, "SDT");
|
|
if (extTsDescriptor == null)
|
|
break;
|
|
ParseUserDefinedDescriptor(extTsDescriptor, child);
|
|
break;
|
|
case nameof(DefaultAuthorityDescriptor):
|
|
DefaultAuthorityDescriptor defaultAuthorityDescriptor = (DefaultAuthorityDescriptor)dvbDescriptor;
|
|
child.DefaultAuthority = defaultAuthorityDescriptor.DefaultAuthority;
|
|
break;
|
|
case nameof(MultilingualServiceNameDescriptor):
|
|
MultilingualServiceNameDescriptor msnd = (MultilingualServiceNameDescriptor)dvbDescriptor;
|
|
child.MultilingualServiceName = msnd.ServiceNames;
|
|
break;
|
|
case nameof(FtaContentManagementDescriptor):
|
|
FtaContentManagementDescriptor fsnd = (FtaContentManagementDescriptor)dvbDescriptor;
|
|
child.ControlRemoteAccessOverInternet = fsnd.ControlRemoteAccessOverInternet;
|
|
child.DoNotApplyRevocation = fsnd.DoNotApplyRevocation;
|
|
child.DoNotScramble = fsnd.DoNotScramble;
|
|
break;
|
|
case nameof(ServiceRelocatedDescriptor):
|
|
ServiceRelocatedDescriptor serviceRelocatedDescriptor = (ServiceRelocatedDescriptor)dvbDescriptor;
|
|
child.OldOriginalNetworkId = serviceRelocatedDescriptor.OldOriginalNetworkId;
|
|
child.OldServiceId = serviceRelocatedDescriptor.OldServiceId;
|
|
child.OldTransportStreamId = serviceRelocatedDescriptor.OldTransportStreamId;
|
|
break;
|
|
case nameof(MessageDescriptor):
|
|
if (child.Messages == null)
|
|
child.Messages = new List<MessageDescriptor>();
|
|
|
|
MessageDescriptor message = (MessageDescriptor)dvbDescriptor;
|
|
child.Messages.Add(message);
|
|
break;
|
|
default:
|
|
throw new NotImplementedException(name);
|
|
}
|
|
}
|
|
|
|
EventHandler.OnSdtService(transportStreamId, originalNetworkId, child);
|
|
}
|
|
|
|
private void ParseUserDefinedDescriptor(TsDescriptor input, SdtService output)
|
|
{
|
|
if (input == null)
|
|
return;
|
|
|
|
string name = input.ToString();
|
|
switch (name)
|
|
{
|
|
default:
|
|
throw new NotImplementedException(name);
|
|
}
|
|
}
|
|
|
|
private void ParseUserDefinedExtensionDescriptor(TsDescriptor input, SdtService output)
|
|
{
|
|
if (input == null)
|
|
return;
|
|
|
|
string name = input.ToString();
|
|
switch (name)
|
|
{
|
|
default:
|
|
throw new NotImplementedException(name);
|
|
}
|
|
}
|
|
}
|
|
}
|