Added parser for OpenTV's file delivery mechanism. Also began to work on an a parser for NDS'S file delivery mechanism.
This commit is contained in:
parent
887d983594
commit
8e57830409
117
skyscraper8/Experimentals/NdsSsu/NdsSsuDetector.cs
Normal file
117
skyscraper8/Experimentals/NdsSsu/NdsSsuDetector.cs
Normal file
@ -0,0 +1,117 @@
|
||||
using skyscraper5.Mpeg2;
|
||||
using skyscraper5.Skyscraper.Plugins;
|
||||
using skyscraper5.Skyscraper.Scraper;
|
||||
using skyscraper5.Skyscraper.Scraper.StreamAutodetection;
|
||||
using skyscraper8.Mpeg2.Psi;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace skyscraper8.Experimentals.NdsSsu
|
||||
{
|
||||
[SkyscraperPlugin]
|
||||
internal class NdsSsuDetector : Contestant, NdsSsuHandler
|
||||
{
|
||||
public NdsSsuDetector(int pid) : base("NDS France SSU", pid)
|
||||
{
|
||||
PacketProcessor = new PsiDecoder(pid, new NdsSsuDetectorWorker(this, pid));
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
PacketProcessor = null;
|
||||
}
|
||||
|
||||
public override void DeclareWinner(SkyscraperContext skyscraperContext, int pid, ProgramContext programContext)
|
||||
{
|
||||
skyscraperContext.DvbContext.RegisterPacketProcessor(pid, new PsiDecoder(pid,new NdsSsuParser(skyscraperContext,pid)));
|
||||
}
|
||||
|
||||
public override void Introduce(ProgramContext programContext)
|
||||
{
|
||||
}
|
||||
|
||||
class NdsSsuDetectorWorker : PrivateSectionParser
|
||||
{
|
||||
private readonly NdsSsuHandler _handler;
|
||||
private readonly int _pid;
|
||||
private bool[] tidExtensions;
|
||||
|
||||
public NdsSsuDetectorWorker(NdsSsuHandler handler, int pid)
|
||||
{
|
||||
_handler = handler;
|
||||
_pid = pid;
|
||||
}
|
||||
|
||||
protected override void HandleTable(byte tableId, int sourcePid, byte sectionNumber, byte lastSectionNumber, ushort tableIdExtension,
|
||||
byte[] payload)
|
||||
{
|
||||
if (tableId != 0x9e)
|
||||
{
|
||||
_handler.OnNdsSsuError(_pid,NdsSsuError.WrongTable);
|
||||
return;
|
||||
}
|
||||
|
||||
if (payload[0] != 0x01)
|
||||
{
|
||||
_handler.OnNdsSsuError(_pid, NdsSsuError.InvalidMagic);
|
||||
return;
|
||||
}
|
||||
|
||||
if (payload[1] != 0xff)
|
||||
{
|
||||
_handler.OnNdsSsuError(_pid, NdsSsuError.InvalidMagic);
|
||||
return;
|
||||
}
|
||||
|
||||
if (payload[2] != 0x00)
|
||||
{
|
||||
_handler.OnNdsSsuError(_pid, NdsSsuError.InvalidMagic);
|
||||
return;
|
||||
}
|
||||
|
||||
if (payload[3] > 0x10)
|
||||
{
|
||||
_handler.OnNdsSsuError(_pid,NdsSsuError.InvalidMagic);
|
||||
return;
|
||||
}
|
||||
|
||||
if (tidExtensions == null)
|
||||
tidExtensions = new bool[ushort.MaxValue];
|
||||
|
||||
if (tidExtensions[tableIdExtension])
|
||||
{
|
||||
_handler.OnNdsSsuProgress(_pid,tableIdExtension, sectionNumber, lastSectionNumber, payload[3]);
|
||||
}
|
||||
else
|
||||
{
|
||||
_handler.OnNdsFileAccouncement(_pid,tableIdExtension);
|
||||
tidExtensions[tableIdExtension] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void OnNdsSsuError(NdsSsuError error)
|
||||
{
|
||||
Score--;
|
||||
}
|
||||
|
||||
public void OnNdsSsuError(int pid, NdsSsuError error)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void OnNdsSsuProgress(int pid, ushort tableIdExtension, byte sectionNumber, byte lastSectionNumber, byte b)
|
||||
{
|
||||
Score++;
|
||||
}
|
||||
|
||||
public void OnNdsFileAccouncement(int pid, ushort tableIdExtension)
|
||||
{
|
||||
Score--;
|
||||
}
|
||||
}
|
||||
}
|
||||
21
skyscraper8/Experimentals/NdsSsu/NdsSsuHandler.cs
Normal file
21
skyscraper8/Experimentals/NdsSsu/NdsSsuHandler.cs
Normal file
@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace skyscraper8.Experimentals.NdsSsu
|
||||
{
|
||||
interface NdsSsuHandler
|
||||
{
|
||||
void OnNdsSsuError(int pid, NdsSsuError error);
|
||||
void OnNdsSsuProgress(int pid, ushort tableIdExtension, byte sectionNumber, byte lastSectionNumber, byte b);
|
||||
void OnNdsFileAccouncement(int pid, ushort tableIdExtension);
|
||||
}
|
||||
|
||||
public enum NdsSsuError
|
||||
{
|
||||
WrongTable,
|
||||
InvalidMagic
|
||||
}
|
||||
}
|
||||
140
skyscraper8/Experimentals/NdsSsu/NdsSsuParser.cs
Normal file
140
skyscraper8/Experimentals/NdsSsu/NdsSsuParser.cs
Normal file
@ -0,0 +1,140 @@
|
||||
using skyscraper8.Mpeg2.Psi;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection.Metadata;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace skyscraper8.Experimentals.NdsSsu
|
||||
{
|
||||
internal class NdsSsuParser : PrivateSectionParser
|
||||
{
|
||||
private readonly NdsSsuHandler _handler;
|
||||
private readonly int _pid;
|
||||
|
||||
public NdsSsuParser(NdsSsuHandler handler, int pid)
|
||||
{
|
||||
_handler = handler;
|
||||
_pid = pid;
|
||||
}
|
||||
|
||||
protected override void HandleTable(byte tableId, int sourcePid, byte sectionNumber, byte lastSectionNumber, ushort tableIdExtension, byte[] payload)
|
||||
{
|
||||
if (tableId != 0x9e)
|
||||
{
|
||||
_handler.OnNdsSsuError(_pid, NdsSsuError.WrongTable);
|
||||
return;
|
||||
}
|
||||
|
||||
if (payload[0] == 0x00 && payload[1] == 0xff && payload[2] == 0x00 && payload[3] == 0x00)
|
||||
{
|
||||
//TODO: payload name
|
||||
return;
|
||||
}
|
||||
|
||||
if (payload[0] != 0x01)
|
||||
{
|
||||
_handler.OnNdsSsuError(_pid, NdsSsuError.InvalidMagic);
|
||||
return;
|
||||
}
|
||||
|
||||
if (payload[1] != 0xff)
|
||||
{
|
||||
_handler.OnNdsSsuError(_pid, NdsSsuError.InvalidMagic);
|
||||
return;
|
||||
}
|
||||
|
||||
if (payload[2] != 0x00)
|
||||
{
|
||||
_handler.OnNdsSsuError(_pid, NdsSsuError.InvalidMagic);
|
||||
return;
|
||||
}
|
||||
|
||||
if (payload[3] > 0x10)
|
||||
{
|
||||
_handler.OnNdsSsuError(_pid, NdsSsuError.InvalidMagic);
|
||||
return;
|
||||
}
|
||||
|
||||
if (dataMaps == null)
|
||||
dataMaps = new DataMap[ushort.MaxValue];
|
||||
if (dataMaps[tableIdExtension] == null)
|
||||
{
|
||||
dataMaps[tableIdExtension] = new DataMap();
|
||||
_handler.OnNdsFileAccouncement(_pid, tableIdExtension);
|
||||
}
|
||||
|
||||
if (dataMaps[tableIdExtension].WasAlreadyPushed(payload, sectionNumber, lastSectionNumber))
|
||||
{
|
||||
throw new NotImplementedException("the file is completed!");
|
||||
}
|
||||
dataMaps[tableIdExtension].PushPacket(payload,sectionNumber,lastSectionNumber);
|
||||
}
|
||||
|
||||
private DataMap[] dataMaps;
|
||||
class DataMap
|
||||
{
|
||||
|
||||
private Superblock[] superblocks;
|
||||
public void PushPacket(byte[] payload,byte currentSection, byte lastSection)
|
||||
{
|
||||
byte maxNumSuperblocks = payload[3];
|
||||
maxNumSuperblocks++;
|
||||
if (superblocks == null)
|
||||
superblocks = new Superblock[maxNumSuperblocks];
|
||||
if (superblocks.Length < maxNumSuperblocks)
|
||||
Array.Resize(ref superblocks, maxNumSuperblocks);
|
||||
if (superblocks[payload[3]] == null)
|
||||
{
|
||||
superblocks[payload[3]] = new Superblock(lastSection);
|
||||
}
|
||||
superblocks[payload[3]].PushPacket(payload,currentSection,lastSection);
|
||||
}
|
||||
|
||||
class Superblock
|
||||
{
|
||||
private byte[][] blocks;
|
||||
public Superblock(byte lastSection)
|
||||
{
|
||||
int maxNumBlocks = lastSection;
|
||||
maxNumBlocks++;
|
||||
blocks = new byte[maxNumBlocks][];
|
||||
}
|
||||
|
||||
public void PushPacket(byte[] payload, byte currentSection, byte lastSection)
|
||||
{
|
||||
int maxNumBlocks = lastSection;
|
||||
maxNumBlocks++;
|
||||
if (blocks.Length > maxNumBlocks)
|
||||
Array.Resize(ref blocks, maxNumBlocks);
|
||||
blocks[currentSection] = payload;
|
||||
}
|
||||
|
||||
public bool WasAlreadyPushed(byte currentSection)
|
||||
{
|
||||
byte maxNumBlocks = currentSection;
|
||||
maxNumBlocks++;
|
||||
|
||||
if (blocks.Length < currentSection)
|
||||
return false;
|
||||
|
||||
return blocks[currentSection] != null;
|
||||
}
|
||||
}
|
||||
|
||||
public bool WasAlreadyPushed(byte[] payload, byte sectionNumber, byte lastSectionNumber)
|
||||
{
|
||||
if (superblocks == null)
|
||||
return false;
|
||||
|
||||
byte maxNumSuperblocks = payload[3];
|
||||
maxNumSuperblocks++;
|
||||
if (superblocks.Length < maxNumSuperblocks)
|
||||
return false;
|
||||
|
||||
return superblocks[payload[3]].WasAlreadyPushed(sectionNumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
144
skyscraper8/Experimentals/OtvSsu/OtvSsuDetector.cs
Normal file
144
skyscraper8/Experimentals/OtvSsu/OtvSsuDetector.cs
Normal file
@ -0,0 +1,144 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using skyscraper5.Mpeg2;
|
||||
using skyscraper5.Skyscraper.IO;
|
||||
using skyscraper5.Skyscraper.Plugins;
|
||||
using skyscraper5.Skyscraper.Scraper;
|
||||
using skyscraper5.Skyscraper.Scraper.StreamAutodetection;
|
||||
using skyscraper8.Mpeg2.Psi;
|
||||
|
||||
namespace skyscraper8.Experimentals.OtvSsu
|
||||
{
|
||||
[SkyscraperPlugin]
|
||||
internal class OtvSsuDetector : Contestant, OtvSsuHandler
|
||||
{
|
||||
private OtvSsuDetectorParser parser;
|
||||
public OtvSsuDetector(int pid) : base("OpenTV SSU", pid)
|
||||
{
|
||||
parser = new OtvSsuDetectorParser(this, pid);
|
||||
PacketProcessor = new PsiDecoder(pid, parser);
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
parser = null;
|
||||
PacketProcessor = null;
|
||||
}
|
||||
|
||||
public override void DeclareWinner(SkyscraperContext skyscraperContext, int pid, ProgramContext programContext)
|
||||
{
|
||||
skyscraperContext.DvbContext.RegisterPacketProcessor(pid, new PsiDecoder(pid,new OtvSsuParser(skyscraperContext)));
|
||||
}
|
||||
|
||||
public override void Introduce(ProgramContext programContext)
|
||||
{
|
||||
}
|
||||
|
||||
class OtvSsuDetectorParser : PrivateSectionParser
|
||||
{
|
||||
private readonly OtvSsuHandler _handler;
|
||||
private readonly int _pid;
|
||||
private List<Coordinate> _coordinates;
|
||||
|
||||
public OtvSsuDetectorParser(OtvSsuHandler handler, int pid)
|
||||
{
|
||||
_handler = handler;
|
||||
_pid = pid;
|
||||
_coordinates = new List<Coordinate>();
|
||||
}
|
||||
|
||||
class Coordinate
|
||||
{
|
||||
public ushort tableIdExtension;
|
||||
public uint fileId;
|
||||
public uint unknown1;
|
||||
public uint length;
|
||||
|
||||
public Coordinate(ushort tableIdExtension1, uint u, uint unknown2, uint length1)
|
||||
{
|
||||
this.tableIdExtension = tableIdExtension1;
|
||||
this.fileId = u;
|
||||
this.unknown1 = unknown2;
|
||||
this.length = length1;
|
||||
}
|
||||
|
||||
public long hits;
|
||||
}
|
||||
|
||||
protected override void HandleTable(byte tableId, int sourcePid, byte sectionNumber, byte lastSectionNumber, ushort tableIdExtension,
|
||||
byte[] payload)
|
||||
{
|
||||
MemoryStream ms = new MemoryStream(payload, false);
|
||||
uint fileId = ms.ReadUInt32BE();
|
||||
uint unknown1 = ms.ReadUInt32BE();
|
||||
uint offset = ms.ReadUInt32BE();
|
||||
uint length = ms.ReadUInt32BE();
|
||||
if (length > Int32.MaxValue)
|
||||
{
|
||||
_handler.OnOtvSsuError(_pid, OtvSsuError.FileTooLarge);
|
||||
return;
|
||||
}
|
||||
if (offset > length)
|
||||
{
|
||||
_handler.OnOtvSsuError(_pid,OtvSsuError.OffsetOutOfRange);
|
||||
return;
|
||||
}
|
||||
|
||||
if (tableIdExtension == 1 && (fileId & 0x00ff0000) == 0x00ff0000)
|
||||
{
|
||||
_handler.OnOtvSsuError(_pid, OtvSsuError.NdsOverlap);
|
||||
return;
|
||||
}
|
||||
|
||||
Coordinate coordinate = _coordinates.Find(x =>
|
||||
x.tableIdExtension == tableIdExtension && x.fileId == fileId && x.unknown1 == unknown1 &&
|
||||
x.length == length);
|
||||
if (coordinate == null)
|
||||
{
|
||||
coordinate = new Coordinate(tableIdExtension, fileId, unknown1, length);
|
||||
_handler.OnOtvSsuFileAnnouncement(_pid,tableIdExtension, fileId, unknown1, length);
|
||||
_coordinates.Add(coordinate);
|
||||
}
|
||||
else
|
||||
{
|
||||
coordinate.hits++;
|
||||
_handler.OnOtvSsuBlock(_pid, tableIdExtension, fileId, unknown1, length);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void HandleTable(byte tableId, int sourcePid, byte[] payload)
|
||||
{
|
||||
_handler.OnOtvSsuError(_pid, OtvSsuError.SectionSyntaxIndicatorMissing);
|
||||
}
|
||||
}
|
||||
|
||||
public void OnOtvSsuError(int pid, OtvSsuError offsetOutOfRange)
|
||||
{
|
||||
Score--;
|
||||
}
|
||||
|
||||
public void OnOtvSsuFileAnnouncement(int pid, ushort tableIdExtension, uint fileId, uint unknown1, uint length)
|
||||
{
|
||||
Score--;
|
||||
}
|
||||
|
||||
public void OnOtvSsuBlock(int pid, ushort tableIdExtension, uint fileId, uint unknown1, uint length)
|
||||
{
|
||||
Score++;
|
||||
}
|
||||
|
||||
public void OnOtvSsuComplete(int sourcePid, Stream getStream, ushort tableIdExtension, uint fileId, uint unknown1,
|
||||
uint length)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool OnOtvCheckFileAlreadyKnown(int sourcePid, ushort tableIdExtension, uint fileId, uint unknown1, uint length)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
26
skyscraper8/Experimentals/OtvSsu/OtvSsuHandler.cs
Normal file
26
skyscraper8/Experimentals/OtvSsu/OtvSsuHandler.cs
Normal file
@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace skyscraper8.Experimentals.OtvSsu
|
||||
{
|
||||
internal interface OtvSsuHandler
|
||||
{
|
||||
void OnOtvSsuError(int pid, OtvSsuError offsetOutOfRange);
|
||||
void OnOtvSsuFileAnnouncement(int pid, ushort tableIdExtension, uint fileId, uint unknown1, uint length);
|
||||
void OnOtvSsuBlock(int pid, ushort tableIdExtension, uint fileId, uint unknown1, uint length);
|
||||
void OnOtvSsuComplete(int sourcePid, Stream getStream, ushort tableIdExtension, uint fileId, uint unknown1, uint length);
|
||||
bool OnOtvCheckFileAlreadyKnown(int sourcePid, ushort tableIdExtension, uint fileId, uint unknown1, uint length);
|
||||
}
|
||||
|
||||
public enum OtvSsuError
|
||||
{
|
||||
OffsetOutOfRange,
|
||||
PacketDeliveredTooMuchData,
|
||||
SectionSyntaxIndicatorMissing,
|
||||
NdsOverlap,
|
||||
FileTooLarge
|
||||
}
|
||||
}
|
||||
202
skyscraper8/Experimentals/OtvSsu/OtvSsuParser.cs
Normal file
202
skyscraper8/Experimentals/OtvSsu/OtvSsuParser.cs
Normal file
@ -0,0 +1,202 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using skyscraper5.Skyscraper.IO;
|
||||
using skyscraper8.Mpeg2.Psi;
|
||||
|
||||
namespace skyscraper8.Experimentals.OtvSsu
|
||||
{
|
||||
internal class OtvSsuParser : PrivateSectionParser
|
||||
{
|
||||
private readonly OtvSsuHandler _handler;
|
||||
|
||||
public OtvSsuParser(OtvSsuHandler handler)
|
||||
{
|
||||
_handler = handler;
|
||||
}
|
||||
|
||||
private Dictionary<Coordinate, DataMap> _dataMaps;
|
||||
protected override void HandleTable(byte tableId, int sourcePid, byte sectionNumber, byte lastSectionNumber, ushort tableIdExtension, byte[] payload)
|
||||
{
|
||||
MemoryStream ms = new MemoryStream(payload, false);
|
||||
uint fileId = ms.ReadUInt32BE();
|
||||
uint unknown1 = ms.ReadUInt32BE();
|
||||
uint offset = ms.ReadUInt32BE();
|
||||
uint length = ms.ReadUInt32BE();
|
||||
if (offset > length)
|
||||
{
|
||||
_handler.OnOtvSsuError(sourcePid, OtvSsuError.OffsetOutOfRange);
|
||||
return;
|
||||
}
|
||||
|
||||
if (length > Int32.MaxValue)
|
||||
{
|
||||
_handler.OnOtvSsuError(sourcePid, OtvSsuError.FileTooLarge);
|
||||
return;
|
||||
}
|
||||
if (tableIdExtension < 10 && (fileId & 0x00ff0000) == 0x00ff0000)
|
||||
{
|
||||
_handler.OnOtvSsuError(sourcePid, OtvSsuError.NdsOverlap);
|
||||
return;
|
||||
}
|
||||
|
||||
Coordinate coords = new Coordinate(tableIdExtension, fileId, unknown1, length);
|
||||
if (_dataMaps == null)
|
||||
_dataMaps = new Dictionary<Coordinate, DataMap>();
|
||||
DataMap map;
|
||||
if (_dataMaps.ContainsKey(coords))
|
||||
{
|
||||
map = _dataMaps[coords];
|
||||
_handler.OnOtvSsuBlock(sourcePid, tableIdExtension, fileId, unknown1, length);
|
||||
}
|
||||
else
|
||||
{
|
||||
map = new DataMap(length);
|
||||
if (_handler.OnOtvCheckFileAlreadyKnown(sourcePid, tableIdExtension, fileId, unknown1, length))
|
||||
{
|
||||
map.Dispose();
|
||||
_dataMaps.Add(coords, map);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
_handler.OnOtvSsuFileAnnouncement(sourcePid, tableIdExtension, fileId, unknown1, length);
|
||||
_dataMaps.Add(coords, map);
|
||||
}
|
||||
}
|
||||
|
||||
if (map.IsComplete)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (map.WasWrittenBefore(offset))
|
||||
{
|
||||
return;
|
||||
}
|
||||
map.PushPacket(payload,offset);
|
||||
if (map.IsErronous)
|
||||
{
|
||||
_handler.OnOtvSsuError(sourcePid, OtvSsuError.PacketDeliveredTooMuchData);
|
||||
_dataMaps.Remove(coords);
|
||||
map.Dispose();
|
||||
return;
|
||||
}
|
||||
if (map.IsComplete)
|
||||
{
|
||||
_handler.OnOtvSsuComplete(sourcePid, map.GetStream(), tableIdExtension, fileId, unknown1, length);
|
||||
map.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
class Coordinate
|
||||
{
|
||||
private readonly ushort _tableIdExtension;
|
||||
private readonly uint _fileId;
|
||||
private readonly uint _unknown1;
|
||||
private readonly uint _length;
|
||||
|
||||
public Coordinate(ushort tableIdExtension, uint fileId, uint unknown1, uint length)
|
||||
{
|
||||
_tableIdExtension = tableIdExtension;
|
||||
_fileId = fileId;
|
||||
_unknown1 = unknown1;
|
||||
_length = length;
|
||||
}
|
||||
|
||||
protected bool Equals(Coordinate other)
|
||||
{
|
||||
return _tableIdExtension == other._tableIdExtension && _fileId == other._fileId && _unknown1 == other._unknown1 && _length == other._length;
|
||||
}
|
||||
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
if (ReferenceEquals(null, obj))
|
||||
return false;
|
||||
if (ReferenceEquals(this, obj))
|
||||
return true;
|
||||
if (obj.GetType() != this.GetType())
|
||||
return false;
|
||||
return Equals((Coordinate)obj);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return HashCode.Combine(_tableIdExtension, _fileId, _unknown1, _length);
|
||||
}
|
||||
}
|
||||
|
||||
class DataMap : IDisposable
|
||||
{
|
||||
private MemoryStream ms;
|
||||
private uint length;
|
||||
private uint needed;
|
||||
private List<uint> knownOffsets;
|
||||
private bool disposed;
|
||||
|
||||
public DataMap(uint length)
|
||||
{
|
||||
ms = new MemoryStream((int)length);
|
||||
this.length = length;
|
||||
this.needed = length;
|
||||
this.knownOffsets = new List<uint>();
|
||||
}
|
||||
|
||||
public void PushPacket(byte[] payload, uint offset)
|
||||
{
|
||||
if (disposed)
|
||||
throw new ObjectDisposedException(this.ToString());
|
||||
ms.Position = offset;
|
||||
ms.Write(payload, 16, payload.Length - 16);
|
||||
needed -= (uint)(payload.Length - 16);
|
||||
knownOffsets.Add(offset);
|
||||
}
|
||||
|
||||
public bool WasWrittenBefore(uint offset)
|
||||
{
|
||||
if (disposed)
|
||||
return true;
|
||||
if (knownOffsets == null)
|
||||
return false;
|
||||
|
||||
return knownOffsets.Contains(offset);
|
||||
}
|
||||
|
||||
public bool IsComplete
|
||||
{
|
||||
get
|
||||
{
|
||||
if (disposed)
|
||||
return false;
|
||||
return needed == 0;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsErronous
|
||||
{
|
||||
get
|
||||
{
|
||||
if (disposed)
|
||||
throw new ObjectDisposedException(this.ToString());
|
||||
return length < needed;
|
||||
}
|
||||
}
|
||||
|
||||
public Stream GetStream()
|
||||
{
|
||||
if (disposed)
|
||||
throw new ObjectDisposedException(this.ToString());
|
||||
return ms;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
ms = null;
|
||||
needed = 0;
|
||||
knownOffsets = null;
|
||||
disposed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
59
skyscraper8/Mpeg2/Psi/PrivateSectionParser.cs
Normal file
59
skyscraper8/Mpeg2/Psi/PrivateSectionParser.cs
Normal file
@ -0,0 +1,59 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using skyscraper5.Mpeg2;
|
||||
using skyscraper5.Skyscraper.IO;
|
||||
|
||||
namespace skyscraper8.Mpeg2.Psi
|
||||
{
|
||||
internal abstract class PrivateSectionParser : IPsiProcessor
|
||||
{
|
||||
public void GatherPsi(PsiSection section, int sourcePid)
|
||||
{
|
||||
byte[] bytes = section.GetData();
|
||||
MemoryStream ms = new MemoryStream(bytes, false);
|
||||
byte tableId = ms.ReadUInt8();
|
||||
|
||||
byte byteA = ms.ReadUInt8();
|
||||
bool sectionSyntaxIndicator = (byteA & 0x80) != 0;
|
||||
bool privateIndicator = (byteA & 0x40) != 0;
|
||||
int reserved = (byteA & 0x30) >> 4;
|
||||
int privateSectionLength = (byteA & 0xf);
|
||||
privateSectionLength <<= 8;
|
||||
privateSectionLength += ms.ReadUInt8();
|
||||
if (!sectionSyntaxIndicator)
|
||||
{
|
||||
byte[] payload = ms.ReadBytes(ms.GetAvailableBytes());
|
||||
HandleTable(tableId, sourcePid, payload);
|
||||
}
|
||||
else
|
||||
{
|
||||
ushort tableIdExtension = ms.ReadUInt16BE();
|
||||
|
||||
byte byteB = ms.ReadUInt8();
|
||||
reserved = (byteB & 0xc0) >> 6;
|
||||
int versionNumber = (byteB & 0x3e) >> 1;
|
||||
bool currentNextIndicator = (byteB & 0x01) != 0;
|
||||
|
||||
byte sectionNumber = ms.ReadUInt8();
|
||||
byte lastSectionNumber = ms.ReadUInt8();
|
||||
int blockLength = privateSectionLength - 9;
|
||||
byte[] payload = ms.ReadBytes(blockLength);
|
||||
uint crc32 = ms.ReadUInt32BE();
|
||||
HandleTable(tableId, sourcePid, sectionNumber, lastSectionNumber, tableIdExtension, payload);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void HandleTable(byte tableId, int sourcePid, byte sectionNumber, byte lastSectionNumber, ushort tableIdExtension, byte[] payload)
|
||||
{
|
||||
throw new PsiException("You should implement the override for no section syntax indicator.");
|
||||
}
|
||||
|
||||
protected virtual void HandleTable(byte tableId, int sourcePid, byte[] payload)
|
||||
{
|
||||
throw new PsiException("You should implement the override for the section syntax indicator.");
|
||||
}
|
||||
}
|
||||
}
|
||||
25
skyscraper8/Mpeg2/Psi/PsiException.cs
Normal file
25
skyscraper8/Mpeg2/Psi/PsiException.cs
Normal file
@ -0,0 +1,25 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using skyscraper5.Mpeg2;
|
||||
|
||||
namespace skyscraper8.Mpeg2.Psi
|
||||
{
|
||||
class PsiException : Mpeg2Exception
|
||||
{
|
||||
public PsiException()
|
||||
: base("PSI Error")
|
||||
{
|
||||
}
|
||||
|
||||
public PsiException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
|
||||
public PsiException(string message, Exception inner) : base(message, inner)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -39,11 +39,11 @@ namespace skyscraper5
|
||||
private static readonly ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name);
|
||||
private static void IntegrationTest()
|
||||
{
|
||||
List<SsdpDevice> ssdpDevices = SsdpClient.GetSsdpDevices(1000).ToList();
|
||||
/*List<SsdpDevice> ssdpDevices = SsdpClient.GetSsdpDevices(1000).ToList();
|
||||
foreach (SsdpDevice ssdpDevice in ssdpDevices)
|
||||
{
|
||||
Console.WriteLine("SSDP device: {0}", ssdpDevice.Server);
|
||||
}
|
||||
}*/
|
||||
|
||||
Console.WriteLine("yeet!");
|
||||
/*RtspClient rtspClient = new RtspClient("172.20.20.121", 554);
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
"profiles": {
|
||||
"skyscraper8": {
|
||||
"commandName": "Project",
|
||||
"commandLineArgs": "\"C:\\devel\\skyscraper8\\skyscraper8\\bin\\Debug\\net8.0\\36E-12226L.ts\"",
|
||||
"commandLineArgs": "\"C:\\Temp\\bem-service-a01.ts\"",
|
||||
"remoteDebugEnabled": false
|
||||
},
|
||||
"Container (Dockerfile)": {
|
||||
|
||||
@ -76,6 +76,8 @@ using System.Net;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Security.Policy;
|
||||
using System.Text;
|
||||
using skyscraper8.Experimentals.NdsSsu;
|
||||
using skyscraper8.Experimentals.OtvSsu;
|
||||
using Tsubasa.IO;
|
||||
using Platform = skyscraper5.Dvb.SystemSoftwareUpdate.Model.Platform;
|
||||
using RntParser = skyscraper5.Dvb.TvAnytime.RntParser;
|
||||
@ -88,7 +90,7 @@ namespace skyscraper5.Skyscraper.Scraper
|
||||
UpdateNotificationEventHandler, DataCarouselEventHandler, RdsEventHandler, IScte35EventHandler,
|
||||
IAutodetectionEventHandler, IRstEventHandler, IRntEventHandler, IMultiprotocolEncapsulationEventHandler, ObjectCarouselEventHandler, T2MIEventHandler,
|
||||
IDisposable, IFrameGrabberEventHandler, IntEventHandler, IRctEventHandler, IGsEventHandler, ISkyscraperContext, IDocsisEventHandler, AbertisDecoderEventHandler, Id3Handler,
|
||||
InteractionChannelHandler, SgtEventHandler, IDvbNipEventHandler, UleEventHandler
|
||||
InteractionChannelHandler, SgtEventHandler, IDvbNipEventHandler, UleEventHandler, OtvSsuHandler, NdsSsuHandler
|
||||
{
|
||||
public const bool ALLOW_STREAM_TYPE_AUTODETECTION = true;
|
||||
public const bool ALLOW_FFMPEG_FRAMEGRABBER = true;
|
||||
@ -2910,5 +2912,46 @@ namespace skyscraper5.Skyscraper.Scraper
|
||||
}
|
||||
throw new NotImplementedException("LLC/SNAP");
|
||||
}
|
||||
|
||||
public void OnOtvSsuError(int pid, OtvSsuError offsetOutOfRange)
|
||||
{
|
||||
DvbContext.RegisterPacketProcessor(pid, new PacketDiscarder());
|
||||
}
|
||||
|
||||
public void OnOtvSsuFileAnnouncement(int pid, ushort tableIdExtension, uint fileId, uint unknown1, uint length)
|
||||
{
|
||||
LogEvent(SkyscraperContextEvent.OtvSsuFileDetected, String.Format("TID = {0}, FID = {1:X8}, Length = {2}", tableIdExtension, fileId, length));
|
||||
}
|
||||
|
||||
public void OnOtvSsuBlock(int pid, ushort tableIdExtension, uint fileId, uint unknown1, uint length)
|
||||
{
|
||||
}
|
||||
|
||||
public void OnOtvSsuComplete(int sourcePid, Stream getStream, ushort tableIdExtension, uint fileId, uint unknown1,
|
||||
uint length)
|
||||
{
|
||||
LogEvent(SkyscraperContextEvent.OtvSsuComplete, String.Format("TID = {0}, FID = {1:X8}, Length = {2}", tableIdExtension, fileId, length));
|
||||
ObjectStorage.OnOtvSsuComplete(CurrentNetworkId, CurrentTransportStreamId, sourcePid, getStream, tableIdExtension, fileId, unknown1, length);
|
||||
}
|
||||
|
||||
public bool OnOtvCheckFileAlreadyKnown(int sourcePid, ushort tableIdExtension, uint fileId, uint unknown1, uint length)
|
||||
{
|
||||
return ObjectStorage.OtvSsuTestFile(CurrentNetworkId, CurrentTransportStreamId, sourcePid, tableIdExtension, fileId, unknown1, length);
|
||||
}
|
||||
|
||||
public void OnNdsSsuError(int pid, NdsSsuError error)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void OnNdsSsuProgress(int pid, ushort tableIdExtension, byte sectionNumber, byte lastSectionNumber, byte b)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void OnNdsFileAccouncement(int pid, ushort tableIdExtension)
|
||||
{
|
||||
LogEvent(SkyscraperContextEvent.NdsSsuFileAnnounced, String.Format("PID = 0x{1:X4}, Table ID Extension = {0}", tableIdExtension, pid));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -81,6 +81,9 @@
|
||||
DvbNipService,
|
||||
DvbNipMulticastSession,
|
||||
DvbNipMulticastGatewayConfigurationTransportSession,
|
||||
FluteFileAnnouncement
|
||||
FluteFileAnnouncement,
|
||||
OtvSsuFileDetected,
|
||||
OtvSsuComplete,
|
||||
NdsSsuFileAnnounced
|
||||
}
|
||||
}
|
||||
|
||||
@ -1524,6 +1524,34 @@ namespace skyscraper5.Skyscraper.Scraper.Storage.Filesystem
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool OtvSsuTestFile(int? currentNetworkId, int? currentTransportStreamId, int sourcePid, ushort tableIdExtension,
|
||||
uint fileId, uint unknown1, uint length)
|
||||
{
|
||||
string cnid = currentNetworkId.HasValue ? currentNetworkId.Value.ToString() : "unknown";
|
||||
string ctsid = currentTransportStreamId.HasValue ? currentTransportStreamId.Value.ToString() : "unknown";
|
||||
string fname = String.Format("{0}_{1:X8}_{2:X8}.bin", tableIdExtension,fileId,unknown1);
|
||||
string path = Path.Combine(rootDirectory.FullName, "OTV-SSU", cnid, ctsid, sourcePid.ToString(), fname);
|
||||
FileInfo fi = new FileInfo(path);
|
||||
return fi.Exists;
|
||||
}
|
||||
|
||||
public void OnOtvSsuComplete(int? currentNetworkId, int? currentTransportStreamId, int sourcePid, Stream getStream,
|
||||
ushort tableIdExtension, uint fileId, uint unknown1, uint length)
|
||||
{
|
||||
string cnid = currentNetworkId.HasValue ? currentNetworkId.Value.ToString() : "unknown";
|
||||
string ctsid = currentTransportStreamId.HasValue ? currentTransportStreamId.Value.ToString() : "unknown";
|
||||
string fname = String.Format("{0}_{1:X8}_{2:X8}.bin", tableIdExtension, fileId, unknown1);
|
||||
string path = Path.Combine(rootDirectory.FullName, "OTV-SSU", cnid, ctsid, sourcePid.ToString(), fname);
|
||||
FileInfo fi = new FileInfo(path);
|
||||
fi.Directory.EnsureExists();
|
||||
FileStream fileStream = fi.OpenWrite();
|
||||
getStream.Position = 0;
|
||||
getStream.CopyTo(fileStream);
|
||||
fileStream.Flush(true);
|
||||
fileStream.Close();
|
||||
getStream.Dispose();
|
||||
}
|
||||
|
||||
class NipPds
|
||||
{
|
||||
public DateTime VersionUpdate;
|
||||
|
||||
@ -99,5 +99,17 @@ namespace skyscraper8.Skyscraper.Scraper.Storage
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool OtvSsuTestFile(int? currentNetworkId, int? currentTransportStreamId, int sourcePid, ushort tableIdExtension,
|
||||
uint fileId, uint unknown1, uint length)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void OnOtvSsuComplete(int? currentNetworkId, int? currentTransportStreamId, int sourcePid, Stream getStream,
|
||||
ushort tableIdExtension, uint fileId, uint unknown1, uint length)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -31,5 +31,7 @@ namespace skyscraper8.Skyscraper.Scraper.Storage
|
||||
void StoreRfSpectrum(Guid jobGuid, RfSpectrumData rfSpectrum);
|
||||
void DeleteIqGraph(Guid selectedGuid, int frequencyItem1, SatelliteDeliverySystemDescriptor.PolarizationEnum frequencyItem2);
|
||||
void DeleteRfSpectrum(Guid selectedGuid);
|
||||
bool OtvSsuTestFile(int? currentNetworkId, int? currentTransportStreamId, int sourcePid, ushort tableIdExtension, uint fileId, uint unknown1, uint length);
|
||||
void OnOtvSsuComplete(int? currentNetworkId, int? currentTransportStreamId, int sourcePid, Stream getStream, ushort tableIdExtension, uint fileId, uint unknown1, uint length);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user