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:
feyris-tan 2025-09-03 23:50:11 +02:00
parent 887d983594
commit 8e57830409
15 changed files with 827 additions and 5 deletions

View 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--;
}
}
}

View 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
}
}

View 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);
}
}
}
}

View 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();
}
}
}

View 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
}
}

View 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;
}
}
}
}

View 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.");
}
}
}

View 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)
{
}
}
}

View File

@ -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);

View File

@ -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)": {

View File

@ -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));
}
}
}

View File

@ -81,6 +81,9 @@
DvbNipService,
DvbNipMulticastSession,
DvbNipMulticastGatewayConfigurationTransportSession,
FluteFileAnnouncement
FluteFileAnnouncement,
OtvSsuFileDetected,
OtvSsuComplete,
NdsSsuFileAnnounced
}
}

View File

@ -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;

View File

@ -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();
}
}
}

View File

@ -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);
}
}