Added basic ISDB-T SDT parsing.
All checks were successful
🚀 Pack skyscraper8 / make-zip (push) Successful in 50s
All checks were successful
🚀 Pack skyscraper8 / make-zip (push) Successful in 50s
This commit is contained in:
parent
ddd4181dc3
commit
1e13c556ba
@ -12,7 +12,7 @@ using skyscraper5.Skyscraper.Text;
|
||||
namespace skyscraper5.Dvb.Descriptors
|
||||
{
|
||||
[SkyscraperPlugin]
|
||||
[TsDescriptor(0x48,"SDT","Astra SGT")]
|
||||
[TsDescriptor(0x48,"SDT","Astra SGT", "ISDB SDT")]
|
||||
[BannedTable("TSDT","PMT")]
|
||||
public class ServiceDescriptor : TsDescriptor
|
||||
{
|
||||
|
||||
@ -9,7 +9,7 @@ using skyscraper8.Skyscraper;
|
||||
|
||||
namespace skyscraper5.Dvb.Psi
|
||||
{
|
||||
class Pid0x11Decoder : IPsiProcessor, IMultistandardTable
|
||||
class Pid0x11Decoder : IPsiProcessor
|
||||
{
|
||||
|
||||
public Pid0x11Decoder(IBatEventHandler batEventHandler, ISdtEventHandler sdtEventHandler)
|
||||
@ -38,11 +38,5 @@ namespace skyscraper5.Dvb.Psi
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetStandard(STD_TYPE standard)
|
||||
{
|
||||
SdtParser.SetStandard(standard);
|
||||
BatParser.SetStandard(standard);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -15,7 +15,7 @@ using skyscraper8.Skyscraper;
|
||||
|
||||
namespace skyscraper5.Dvb.Psi
|
||||
{
|
||||
class SdtParser : IPsiProcessor, IMultistandardTable
|
||||
class SdtParser : IPsiProcessor
|
||||
{
|
||||
public ISdtEventHandler EventHandler { get; }
|
||||
|
||||
@ -83,7 +83,7 @@ namespace skyscraper5.Dvb.Psi
|
||||
SdtService child = new SdtService(serviceId, eitScheduleFlag, eitPresentFollowingFlag, runningStatus, freeCaMode);
|
||||
|
||||
byte[] descriptorsData = ms.ReadBytes(descriptorsLoopLength);
|
||||
IEnumerable<TsDescriptor> unpackDescriptors = TsDescriptorUnpacker.GetInstance().UnpackDescriptors(descriptorsData, GetTableType());
|
||||
IEnumerable<TsDescriptor> unpackDescriptors = TsDescriptorUnpacker.GetInstance().UnpackDescriptors(descriptorsData, "SDT");
|
||||
foreach (TsDescriptor dvbDescriptor in unpackDescriptors)
|
||||
{
|
||||
string name = dvbDescriptor.GetType().Name;
|
||||
@ -214,23 +214,5 @@ namespace skyscraper5.Dvb.Psi
|
||||
throw new NotImplementedException(name);
|
||||
}
|
||||
}
|
||||
|
||||
private STD_TYPE standard;
|
||||
public void SetStandard(STD_TYPE standard)
|
||||
{
|
||||
this.standard = standard;
|
||||
}
|
||||
|
||||
private string GetTableType()
|
||||
{
|
||||
if (IMultistandardTable.IsIsdb(standard))
|
||||
{
|
||||
return "ISDB SDT";
|
||||
}
|
||||
else
|
||||
{
|
||||
return "SDT";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
10
skyscraper8/Isdb/EventHandlers/IIsdbSdtEventHandler.cs
Normal file
10
skyscraper8/Isdb/EventHandlers/IIsdbSdtEventHandler.cs
Normal file
@ -0,0 +1,10 @@
|
||||
using skyscraper8.Isdb.Tables;
|
||||
|
||||
namespace skyscraper8.Isdb.EventHandlers;
|
||||
|
||||
public interface IIsdbSdtEventHandler
|
||||
{
|
||||
void SetNetworkId(ushort originalNetworkId);
|
||||
void SetTransportStreamId(ushort transportStreamId);
|
||||
void OnSdtService(ushort transportStreamId, ushort originalNetworkId, IsdbSdtService child);
|
||||
}
|
||||
@ -1,3 +1,4 @@
|
||||
using System.Reflection.Metadata;
|
||||
using log4net;
|
||||
using log4net.Repository.Hierarchy;
|
||||
using skyscraper5.Dvb.Descriptors;
|
||||
@ -18,7 +19,7 @@ using skyscraper8.Skyscraper.Scraper.Storage;
|
||||
|
||||
namespace skyscraper8.Isdb;
|
||||
|
||||
public class Matenro : IPatEventHandler, ICatEventHandler, IBatEventHandler, ISdtEventHandler, IEitEventHandler, IRstEventHandler, ITdtEventHandler, ITotEventHandler, IIsdbPmtEventHandler, IBitEventHandler, IIsdbSubtitleHandler, IAutodetectionEventHandler
|
||||
public class Matenro : IPatEventHandler, ICatEventHandler, IBatEventHandler, IEitEventHandler, IRstEventHandler, ITdtEventHandler, ITotEventHandler, IIsdbPmtEventHandler, IBitEventHandler, IIsdbSubtitleHandler, IAutodetectionEventHandler, IIsdbSdtEventHandler
|
||||
{
|
||||
public TsContext DvbContext { get; }
|
||||
public DataStorage DataStorage { get; }
|
||||
@ -43,10 +44,6 @@ public class Matenro : IPatEventHandler, ICatEventHandler, IBatEventHandler, ISd
|
||||
|
||||
logger = LogManager.GetLogger(this.GetType().Name);
|
||||
|
||||
|
||||
Pid0x11Decoder pid0X11Decoder = new Pid0x11Decoder(this, this);
|
||||
pid0X11Decoder.SetStandard(STD_TYPE.STD_ISDBT);
|
||||
|
||||
EitParser eitParser = new EitParser(this);
|
||||
eitParser.SetStandard(STD_TYPE.STD_ISDBT);
|
||||
|
||||
@ -62,7 +59,7 @@ public class Matenro : IPatEventHandler, ICatEventHandler, IBatEventHandler, ISd
|
||||
|
||||
dvbContext.RegisterPacketProcessor(0x0000, new PsiDecoder(0x0000, new PatParser(this)));
|
||||
dvbContext.RegisterPacketProcessor(0x0001, new PsiDecoder(0x0001, new CatParser(this)));
|
||||
dvbContext.RegisterPacketProcessor(0x0011, new PsiDecoder(0x0011, pid0X11Decoder));
|
||||
dvbContext.RegisterPacketProcessor(0x0011, new PsiDecoder(0x0011, new IsdbSdtParser(this)));
|
||||
dvbContext.RegisterPacketProcessor(0x0012, new PsiDecoder(0x0012, eitParser));
|
||||
dvbContext.RegisterPacketProcessor(0x0013, new PsiDecoder(0x0013, rstParser));
|
||||
dvbContext.RegisterPacketProcessor(0x0014, new PsiDecoder(0x0014, tdtParser));
|
||||
@ -110,14 +107,35 @@ public class Matenro : IPatEventHandler, ICatEventHandler, IBatEventHandler, ISd
|
||||
}
|
||||
}
|
||||
|
||||
public void OnSdtService(ushort transportStreamId, ushort originalNetworkId, SdtService sdtService)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private ushort? competingNetworkId;
|
||||
public void SetNetworkId(ushort networkId)
|
||||
{
|
||||
this._networkId = networkId;
|
||||
if (_networkId.HasValue)
|
||||
{
|
||||
if (_networkId.Value == networkId)
|
||||
{
|
||||
//Die neue Network ID ist die selbe, wie die, die wir kennen, also alles ok.
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Die neue Network ID konkurriert!
|
||||
if (competingNetworkId.HasValue)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.WarnFormat("Multiple network IDs are announced for this stream: {0} <-> {1}", networkId, _networkId.Value);
|
||||
competingNetworkId = networkId;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//Network ID noch nicht bekannt, kann also gefahrlos gesetzt werden.
|
||||
this._networkId = networkId;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetTransportStreamId(ushort transportStreamId)
|
||||
@ -137,6 +155,25 @@ public class Matenro : IPatEventHandler, ICatEventHandler, IBatEventHandler, ISd
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private List<long> _knownSdts;
|
||||
public void OnSdtService(ushort transportStreamId, ushort originalNetworkId, IsdbSdtService child)
|
||||
{
|
||||
long key = originalNetworkId;
|
||||
key <<= 16;
|
||||
key += transportStreamId;
|
||||
key <<= 16;
|
||||
key += child.ServiceId;
|
||||
if (_knownSdts == null)
|
||||
_knownSdts = new List<long>();
|
||||
if (!_knownSdts.Contains(key))
|
||||
{
|
||||
logger.InfoFormat("SDT Service {0},{1}: {2}", originalNetworkId, transportStreamId, child.TryGetName());
|
||||
DataStorage.UpsertIsdbSdt(transportStreamId, originalNetworkId, child);
|
||||
_knownSdts.Add(key);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void OnEitEvent(EitEvent eitEvent)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
|
||||
96
skyscraper8/Isdb/Parsers/IsdbSdtParser.cs
Normal file
96
skyscraper8/Isdb/Parsers/IsdbSdtParser.cs
Normal file
@ -0,0 +1,96 @@
|
||||
using skyscraper5.Dvb.Descriptors;
|
||||
using skyscraper5.Dvb.Psi.Model;
|
||||
using skyscraper5.Mpeg2;
|
||||
using skyscraper5.Skyscraper.IO;
|
||||
using skyscraper8.Isdb.EventHandlers;
|
||||
using skyscraper8.Isdb.Tables;
|
||||
|
||||
namespace skyscraper8.Isdb.Psi;
|
||||
|
||||
public class IsdbSdtParser : IPsiProcessor
|
||||
{
|
||||
public IsdbSdtParser(IIsdbSdtEventHandler handler)
|
||||
{
|
||||
this.EventHandler = handler;
|
||||
}
|
||||
|
||||
public IIsdbSdtEventHandler EventHandler { get; set; }
|
||||
|
||||
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)
|
||||
{
|
||||
ReadIsdbService(ms, transportStreamId, originalNetworkId);
|
||||
}
|
||||
|
||||
uint crc32 = ms.ReadUInt32BE();
|
||||
}
|
||||
|
||||
private void ReadIsdbService(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;
|
||||
|
||||
IsdbSdtService child = new IsdbSdtService(serviceId, eitScheduleFlag, eitPresentFollowingFlag, runningStatus, freeCaMode);
|
||||
|
||||
byte[] descriptorsData = ms.ReadBytes(descriptorsLoopLength);
|
||||
IEnumerable<TsDescriptor> unpackDescriptors = TsDescriptorUnpacker.GetInstance().UnpackDescriptors(descriptorsData, "ISDB SDT");
|
||||
foreach (TsDescriptor dvbDescriptor in unpackDescriptors)
|
||||
{
|
||||
switch (dvbDescriptor)
|
||||
{
|
||||
case ServiceDescriptor sd:
|
||||
if (child.ServiceDescriptor == null)
|
||||
child.ServiceDescriptor = sd;
|
||||
else
|
||||
throw new NotImplementedException("Multiple service descriptors are not yet implemented.");
|
||||
break;
|
||||
default:
|
||||
throw new NotImplementedException("Unknown ISDB SDTdescriptor type: " + dvbDescriptor.GetType().Name);
|
||||
}
|
||||
}
|
||||
EventHandler.OnSdtService(transportStreamId, originalNetworkId, child);
|
||||
|
||||
}
|
||||
}
|
||||
33
skyscraper8/Isdb/Tables/IsdbSdtService.cs
Normal file
33
skyscraper8/Isdb/Tables/IsdbSdtService.cs
Normal file
@ -0,0 +1,33 @@
|
||||
using skyscraper5.Dvb.Descriptors;
|
||||
using skyscraper5.Dvb.Psi.Model;
|
||||
|
||||
namespace skyscraper8.Isdb.Tables;
|
||||
|
||||
public class IsdbSdtService
|
||||
{
|
||||
public ushort ServiceId { get; }
|
||||
public bool EitScheduleFlag { get; }
|
||||
public bool EitPresentFollowingFlag { get; }
|
||||
public RunningStatus RunningStatus { get; }
|
||||
public bool FreeCaMode { get; }
|
||||
public ServiceDescriptor ServiceDescriptor { get; set; }
|
||||
|
||||
public IsdbSdtService(ushort serviceId, bool eitScheduleFlag, bool eitPresentFollowingFlag, RunningStatus runningStatus, bool freeCaMode)
|
||||
{
|
||||
ServiceId = serviceId;
|
||||
EitScheduleFlag = eitScheduleFlag;
|
||||
EitPresentFollowingFlag = eitPresentFollowingFlag;
|
||||
RunningStatus = runningStatus;
|
||||
FreeCaMode = freeCaMode;
|
||||
}
|
||||
|
||||
public string TryGetName()
|
||||
{
|
||||
if (ServiceDescriptor != null)
|
||||
{
|
||||
return ServiceDescriptor.ServiceName;
|
||||
}
|
||||
|
||||
return "???";
|
||||
}
|
||||
}
|
||||
@ -221,5 +221,7 @@ namespace skyscraper8.Skyscraper.Scraper.Storage
|
||||
/// </summary>
|
||||
/// <param name="bit"></param>
|
||||
void UpsertBit(Bit bit);
|
||||
|
||||
void UpsertIsdbSdt(ushort transportStreamId, ushort originalNetworkId, IsdbSdtService child);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1828,6 +1828,14 @@ namespace skyscraper5.Skyscraper.Scraper.Storage.Filesystem
|
||||
File.WriteAllText(fi.FullName, JsonConvert.SerializeObject(bit, jsonSerializerSettings));
|
||||
}
|
||||
|
||||
public void UpsertIsdbSdt(ushort transportStreamId, ushort originalNetworkId, IsdbSdtService child)
|
||||
{
|
||||
string combine = Path.Combine(rootDirectory.FullName, "SDT", "ISDB", originalNetworkId.ToString(), transportStreamId.ToString() , child.ServiceId + ".json");
|
||||
FileInfo fi = new FileInfo(combine);
|
||||
fi.Directory.EnsureExists();
|
||||
File.WriteAllText(fi.FullName, JsonConvert.SerializeObject(child, jsonSerializerSettings));
|
||||
}
|
||||
|
||||
public RfSpectrumData GetRfSpectrum(Guid jobGuid)
|
||||
{
|
||||
string filename = Path.Combine(rootDirectory.FullName, "rf", jobGuid.ToString() + ".rf");
|
||||
|
||||
@ -1959,5 +1959,19 @@ namespace skyscraper5.Skyscraper.Scraper.Storage.InMemory
|
||||
_bits = new Bit[ushort.MaxValue];
|
||||
_bits[bit.OriginalNetworkId] = bit;
|
||||
}
|
||||
|
||||
private Dictionary<long, IsdbSdtService> _isdbSdtServices;
|
||||
public void UpsertIsdbSdt(ushort transportStreamId, ushort originalNetworkId, IsdbSdtService child)
|
||||
{
|
||||
long key = originalNetworkId;
|
||||
key <<= 16;
|
||||
key += transportStreamId;
|
||||
key <<= 16;
|
||||
key += child.ServiceId;
|
||||
|
||||
if (_isdbSdtServices == null)
|
||||
_isdbSdtServices = new Dictionary<long, IsdbSdtService>();
|
||||
_isdbSdtServices[key] = child;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user