149 lines
4.0 KiB
C#

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 const int MAXIMUM_FILE_SIZE = 33554432; //32MB.
//Let's use a limit here to avoid detecting too many large files and false positives.
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 > MAXIMUM_FILE_SIZE)
{
_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();
}
}
}