Detect ISDB Muxes
All checks were successful
🚀 Pack skyscraper8 / make-zip (push) Successful in 56s

This commit is contained in:
fey 2026-08-11 21:37:06 +02:00
parent 4cb32b8c8b
commit d4d1f8169d
6 changed files with 250 additions and 19 deletions

View File

@ -42,12 +42,16 @@
#### Chloe Lindberg
- **Name:** Chloe Lindberg
- **Alter:** 34 Jahre
- **Beziehungen:** Sie war vor vielen Jahren mal mit Sophia zusammen. Chloe hat nun in Paris mit ihrem aktuellen Freund eine Tochter.
- **Wohnort:** Paris, Frankreich
- **Arbeit:** Sie ist eine Freelance-IT-Beraterin in Paris
- **Beziehungen:** Sie war vor vielen Jahren mal mit Sophia zusammen. Nun lebt Chloe in Finnland und pflegt dort gute Beziehungen zu ihren Schüler*innnen.
- **Wohnort:** Helsinki, Finnland
- **Arbeit:** Sie arbeitet in einer Sprachschule in Helsinki und unterrichtet Finnisch für Einwanderer.
- **Rasse:** Mensch
- **Bildung:** Chloe hat das Gemeinschaftslernzentrum des Dorfes besucht. Einen formellen Schulabschluss hat sie deshalb nicht, kann aber vom Bildungsgrad etwa mit jemanden mithalten, der ein Schweizer Matura hat.
- Als Chloe volljährig wurde, hat sie das Dorf verlassen um in Paris ihre Glück zu suchen.
- In Paris hat sie mehrere Indie-Games entwickelt, die alle sehr gute Kritiken erhalten haben, aber ein Kassenschlager wurden diese nicht.
- In Paris hat sie sich in einen Mann verliebt, mit dem sie eine kleine Tochter hat, die ihr zum Verwechseln ähnlich sieht.
- Da sich der gewünschte Erfolg in Paris nicht gezeigt hat, hat sie beschlossen noch einmal von vorne anzufangen und zwar in Finnland.
- Das Einwanderungsverfahren empfand sie als sehr schwierig. Sobald sie fließend in Finnisch ist, entschließt sie sich dazu, Sprachlehrerin zu werden, um anderen Einwanderern bei ähnlichen Problemen zu helfen.
#### Valérie Beaumont
- **Name:** Valérie Beaumont
@ -58,17 +62,24 @@
- **Rasse:** Mensch
- **Bildung:** Valérie verfügt über ein allgemeines französisches Lycée.
#### Tennie:
- **Tennie:** Tennie
- **Alter:** Da sie eine streunende Katze ist, hat man sich nicht die Mühe gemacht, wie alt sie ist.
- **Beziehungen:**
- Alexandra ist Tennies Lieblingszweibeinerin.
- Tennie hasst Alpha aus nicht näher bekannten Gründen. Wahrscheinlich irgendsoein Katzending.
- Tennie mag Sophia (oder eher ihren Schoß) weil bequem.
- Tennie mag Espresso, weil diese am ehesten Futter spendet.
- Tennie findet die Geräusche lustig, wenn Jade wegen ihrer Katzenhaarallergie niesen muss.
- **Wohnort:** Adoptiert in der Aoki-Villa
- **Arbeit:** Hält die Villa und die Umgebung von Mäusen und anderen Schädlingen frei
- **Rasse:** Hauskatze (Felis domestica)
- **Bildung:** Was man als streunende Straßenkatze im Dorf eben so lernt.
- Tennie ist eine getigerte, europäisch-Kurzhaar Braun-Tabby.
- Als sie noch eine Streunerin war, hat ihr der Winter stark zugesetzt. Als sie nicht mehr weiter wusste, hat sie sich im Brennpunkt der großen Satellitenschüssel im Garten der Aoki-Villa versteckt, um dort Zuflucht vor dem Schnee zu suchen.
- Sie wurde Tennie genannt, weil die Antenne aus der Sophia sie gerettet hat auf Eutelsat 10 (Ten) ausgerichtet ist.
### Die Maids in der Aoki-Villa
#### Kaede
- **Name:** Kaede Teien
- **Alter:** 50 Jahre
- **Beziehungen:** Sie ist die Vorgesetzte der anderen Maids in der Aoki-Villa. Zudem hat sie ein sexuelles und romantisches Interesse an Alexandra Aoki.
- **Wohnort:** Die Aoki-Villa im Dorf
- **Arbeit:** Ober-Maid in der Aoki Villa & Leitung des Dorfarchivs
- **Rasse:** Mensch
- **Bildung:** Kaede hat (damals noch als Tsukasa) in Japan eine spezielle Schule für Archivare besucht, und dort einen guten Abschluss erzielt.
- In der Verwaltung des Dorfes gilt Kaede als "der Hausdrache" der Villa. Sie schaut definitiv streng drin, und ist auch streng zu den anderen Maids, aber ebenso hat sie "ein Herz aus Gold"
- Kaede ist transsexuell - sie ist als Mann zur Welt gekommen. Früher hieß sie "Tsukasa Teien" und ist ein Japan aufgewachsen.
### Espresso
- **Name:** Lina "Espresso" Müller
@ -137,6 +148,30 @@
- Fawn mag es, sich die Haare grün zu färben. Dabei benutzt sie die selben Mittel wie Espresso.
### Nebencharaktere
#### Kaede
- **Name:** Kaede Teien
- **Alter:** 50 Jahre
- **Beziehungen:** Sie ist zwar nach wie vor verheiratet mit Alexandra Aoki, hatte aber eine Affäre mit Leena, wobei ein Kind entstanden ist. Kaede hat beschlossen, für dieses Kind Verantwortung zu übernehmen, weshalb sie nach Finnland ausgewandert ist.
- **Wohnort:** Helsinki, Finnland
- **Arbeit:** Sie war früher die Ober-Maid in der Aoki-Villa. Nun ist sie in Finnland, aktuell arbeitslos, aber bemüht sich die Sprache zu lernen.
- **Rasse:** Mensch
- **Bildung:** Kaede hat (damals noch als Tsukasa) in Japan eine spezielle Schule für Archivare besucht, und dort einen guten Abschluss erzielt.
- In der Verwaltung des Dorfes galt Kaede früher als "der Hausdrache" der Villa. Sie schaut definitiv streng drin, und ist auch streng zu den anderen Maids, aber ebenso hat sie "ein Herz aus Gold"
- Kaede ist transsexuell - sie ist als Mann zur Welt gekommen. Früher hieß sie "Tsukasa Teien" und ist ein Japan aufgewachsen.
- Als Kaede eine Schulung in Grönland besucht hatte, hatte sie dort eine Affäre mit einer Finnin namens Leena.
### Leena
- **Name:** Leena ?
- **Alter:** 28 Jahre
- **Beziehungen:** Sie hatte eine sexuelle Affäre mit Kaede wobei ein Kind entstanden ist.
- **Wohnort:** Helsinki, Finnland
- **Arbeit:** Sie arbeitet im Archiv einer Universität in Helsinki wird aber bald in Mutterschutz gehen.
- **Rasse:** Mensch
- **Bildung:** Sie hat ein finnisches Ylioppilastutkinto, hat aber nicht weiter studiert, bevor sie angefangen hat zu arbeiten.
- Leena ist eher ruhig.
- Leena spricht nur finnisch und englisch, letzteres aber auch nur ungerne, weshalb sie Kaede tatkräftig beim lernen unterstützt.
#### Herr Moreau
- **Name:** Vorname unbekannt, alle nennen ihn nur Herr Moreau.
- **Alter:** Unbekannt, aber definitiv über 60.
@ -144,6 +179,7 @@
- **Wohnort:** Irgendwo an der französischen Grenze des Dorfes
- **Arbeit:** Er führt den einzigen Elektroladen des Dorfes, wo er allerlei verkauft. Von obskuren Ersatzteilen, alte Schreibmaschinen, moderne Flachbildfernseher, Kühlschränke, oder die neusten Videospiele - wenn es elektronisch ist, hat er es in seinem Laden oder kann es besorgen. Da es der einzige Elektroladen im Dorf ist, nimmt er auch Reperaturaufträge an.
- **Rasse:** Mensch
#### Benoît
- **Name:** Vorname unbekannt, alle nennen ihn nur Benoít.
- **Alter:** Ende 20.
@ -207,10 +243,12 @@
- Deshalb sehen Hexen immer aus wie junge, attraktive Männer.
- Die genaue Lebenserwartung ist unbekannt.
- Die Hexenmeister sind ein wandernes Volk, sie bleiben selten für zwei Tage am selben Ort.
- Wenn eine Hexe einen Hexenmeister zur Welt bringt, geht dieser normalerweise mit der nächsten Gruppe Hexenmeistern mit, sobald er sicher selbstständig laufen kann.
## Hexenbiologie
- Lässt sich eine Hexe mit einem menschlichen Mann (oder ein Hexenmeister mit einer menschlichen Frau) statt mit einem Hexenmeister ein, und beschließt ein Kind zu bekommen, so entsteht eine Menschenbrut.
- Eine Hexe oder ein Hexenmeister kann nur dann geboren werden, wenn sich eine Hexe und ein Hexenmeister aufeinander einlassen.
- Da Hexen sesshaft, Hexenmeister aber wandernd sind, ist es für Hexen völlig normal, polyamourös zu sein. Aus diesem Grund nimmt Alexandra es auch leicht, als Kaede ihr gesteht, dass sie eine Affäre und dabei ein Kind gezeugt hatte.
## Was Alexandra so in ihrem Leben erlebt hat
- Alexandra ist im Jahre 1190 im Hexenwald, als Tochter einer hoch angesehenen Hexe namens Helena zur Welt gekommen.
@ -258,4 +296,24 @@
- Sophia stimmt zu. Valérie kommt mit und wird undercover als neue Schülerin eingeschleust, damit Sophia nicht alleine dort hin muss.
- Während der Freizeit der Schülerinnen, zieht Valérie unbeabsichtigt Aufmerksamkeit auf sich, da sich herausstellt, dass sie dadurch, dass sie auf einem Hof aufgewachsen ist, einen exzellenten Umgang mit Pferden beherrscht. In einem Polo-Spiel gewinnt sie praktisch im Alleingang. Nun steht Valérie vor dem Problem, zu verbergen, dass sie in Wirklichkeit nicht reich ist, sondern eine Bauerntochter ist.
- Sophia bringt ihren Schülerinnen währenddessen Ruby bei.
- Als Sophia wieder zuhause ist, äußert Kaede den Wunsch ein Seminar in Grönland zu besuchen. Alle sind damit einverstanden.
- Während der Schulung verbringt Kaede viel Zeit mit der Finnin Leena. Dabei kommen sie sich auch körperlich näher.
- Kaede hat Schuldgefühle, Alexandra betrogen zu haben.
- Zuhause beichtet Kaede Alexandra alles, aber aufgrund ihrer hexischen Natur hat Alexandra überhaupt kein Problem damit.
- Es wird Winter im Dorf
- Ein paar Tage später hätte Alpha einen wichtigen Geschäftstermin, diesen kann sie jedoch nicht wahrnehmen, da die Internetverbindung streikt.
- Das Problem ist schnell gefunden: Eine Katze hat im Brennpunkt der Antenne für das Sattelliteninternet Zuflucht vor dem Schnee gesucht.
- Die Aoki-Familie adoptiert die Katze und nennt sie Tennie.
- Wenige wochen später: Leena kontaktiert Kaede und teilt mit, dass sie schwanger ist.
- Kaede beichtet Alexadra erneut. Zu Kaedes Überraschung ist Alexandra auch hier völlig entspannt.
- Also erklärt Alexandra Kaede wie das mit den Hexen und Hexenmeistern funktioniert.
- In Alphas Meeting-Zimmer kommt es zu einer Telefonkonferenz zwischen Alexandra, Kaede und Leena.
- Die drei entscheiden gemeinsam, dass Kaede Verantwortung für das Kind übernehmen wird. Sie wird zu Leena nach Finnland ziehen.
- Alpha lässt über Aoki Holdings Oy ein Haus in Helsinki kaufen, in das Kaede und Leena einziehen, sobald Kaede in Finnland ist.
- Um sich besser mit Leena verständigen zu können, und auch aus Liebe zu dem noch ungeborenen Kind beschließt Kaede Finnisch zu lernen. Dafür wird sie eine Sprachschule für Einwanderer besuchen.
- In der ersten Unterrichtsstunde ist Kaede überrascht, dass Chloe vor ihr als Dozentin steht.
- Chloe und Kaede erkennen sich wieder, schließlich waren sie beide sehr lange im staatenlosen Dorf.
- Die beiden freunden sich an, und Chloe sucht sie auch öfters privat auf.
- Durch Zufall kommt ein Telefongespräch zwischen Kaede und Sophia zustande. Kaede stellt auf frei sprechen, und Chloe kommt dazu. Sie und Sophia haben sich vermisst.
- Sophia möchte Chloe besuchen kommen. Aber Chloe hat eine bessere Idee. Chloe will ins Dorf kommen. Das ist logistisch auch für sie sinnvoller. So kann sie einen Zwischenstopp in Paris einlegen, und dort ihren Freund und ihre Tochter zu besuchen.
- (Ab hier geht's weiter)

View File

@ -0,0 +1,6 @@
namespace skyscraper8.Isdb;
public interface IIsdbDetectorCallback
{
void IsdbDetectionResult(bool isIsdb);
}

View File

@ -0,0 +1,100 @@
using skyscraper5.Mpeg2;
using skyscraper5.Skyscraper.IO;
namespace skyscraper8.Isdb;
public class IsdbDetector : IPsiProcessor
{
private readonly IIsdbDetectorCallback _callback;
public IsdbDetector(IIsdbDetectorCallback callback)
{
_callback = callback;
}
public void GatherPsi(PsiSection section, int sourcePid)
{
if (sourcePid != 0x0024)
{
_callback.IsdbDetectionResult(false);
return;
}
if (!section.Validate())
{
_callback.IsdbDetectionResult(false);
return;
}
byte[] bytes = section.GetDataCopy();
MemoryStream stream = new MemoryStream(bytes, false);
byte tableId = stream.ReadUInt8();
if (tableId != 0xc4)
{
_callback.IsdbDetectionResult(false);
return;
}
ushort sectionLength = stream.ReadUInt16BE();
bool sectionSyntaxIndicator = (sectionLength & 0x8000) != 0;
if (!sectionSyntaxIndicator)
{
_callback.IsdbDetectionResult(false);
return;
}
sectionLength &= 0x0fff;
long availableBytes = stream.GetAvailableBytes();
if (sectionLength != availableBytes)
{
_callback.IsdbDetectionResult(false);
return;
}
ushort originalNetworkId = stream.ReadUInt16BE();
byte byteA = stream.ReadUInt8();
byte sectionNumber = stream.ReadUInt8();
byte lastSectionNumber = stream.ReadUInt8();
if (sectionNumber > lastSectionNumber)
{
_callback.IsdbDetectionResult(false);
return;
}
ushort firstDescriptorsLength = stream.ReadUInt16BE();
firstDescriptorsLength &= 0x0fff;
if (!ValidateDescriptorLoop(stream.ReadBytes(firstDescriptorsLength)))
{
_callback.IsdbDetectionResult(false);
return;
}
while (stream.GetAvailableBytes() > 4)
{
byte broadcasterId = stream.ReadUInt8();
ushort broadcastDescriptorLength = stream.ReadUInt16BE();
broadcastDescriptorLength &= 0x0fff;
if (!ValidateDescriptorLoop(stream.ReadBytes(broadcastDescriptorLength)))
{
_callback.IsdbDetectionResult(false);
return;
}
}
uint crc32 = stream.ReadUInt32BE();
_callback.IsdbDetectionResult(true);
}
private bool ValidateDescriptorLoop(byte[] bytes)
{
MemoryStream ms = new MemoryStream(bytes);
while (ms.GetAvailableBytes() > 0)
{
byte descriptorId = ms.ReadUInt8();
byte descriptorLength = ms.ReadUInt8();
ms.Position += descriptorLength;
}
return true;
}
}

View File

@ -0,0 +1,41 @@
using skyscraper5.Mpeg2;
using skyscraper5.Mpeg2.Psi;
using skyscraper5.Skyscraper.Scraper;
using skyscraper8.Skyscraper.Scraper.Storage;
namespace skyscraper8.Isdb;
public class Matenro : IPatEventHandler
{
public TsContext DvbContext { get; }
public DataStorage DataStorage { get; }
public ObjectStorage ObjectStorage { get; }
public ISkyscraperUiJunction UiJunction { get; }
public Action<SkyscraperContextEvent, string> LogEvent { get; }
public Matenro(TsContext dvbContext, DataStorage dataStorage, ObjectStorage objectStorage, ISkyscraperUiJunction uiJunction, Action<SkyscraperContextEvent, string> logEvent)
{
DvbContext = dvbContext;
DataStorage = dataStorage;
ObjectStorage = objectStorage;
UiJunction = uiJunction;
LogEvent = logEvent;
dvbContext.RegisterPacketProcessor(0, new PsiDecoder(0, new PatParser(this)));
}
public void NetworkPidFromPat(int networkPid)
{
throw new NotImplementedException();
}
public void ProgramMapPidFromPat(int pmtPid, ushort programNumber)
{
throw new NotImplementedException();
}
public void SetTransportStreamId(ushort transportStreamId)
{
throw new NotImplementedException();
}
}

View File

@ -97,6 +97,7 @@ using Tsubasa.IO;
using Platform = skyscraper5.Dvb.SystemSoftwareUpdate.Model.Platform;
using RntParser = skyscraper5.Dvb.TvAnytime.RntParser;
using skyscraper8.Dvb.DataBroadcasting;
using skyscraper8.Isdb;
using skyscraper8.Skyscraper.Scraper.Storage.Tar;
using skyscraper8.ThreemediaOtt;
@ -109,7 +110,7 @@ namespace skyscraper5.Skyscraper.Scraper
IAutodetectionEventHandler, IRstEventHandler, IRntEventHandler, IMultiprotocolEncapsulationEventHandler, ObjectCarouselEventHandler, T2MIEventHandler,
IDisposable, IFrameGrabberEventHandler, IntEventHandler, IRctEventHandler, ISkyscraperContext, IDocsisEventHandler, AbertisDecoderEventHandler, Id3Handler,
InteractionChannelHandler, SgtEventHandler, IDvbNipEventHandler, UleEventHandler, OtvSsuHandler, NdsSsuHandler, ISubTsHandler, ILldpFrameHandler, SisHandler, IWneHandler,
IAtscPlpEventHandler, IAtsc3EventHandler, IThreeMediaEventHandler
IAtscPlpEventHandler, IAtsc3EventHandler, IThreeMediaEventHandler, IIsdbDetectorCallback
{
public const bool ALLOW_STREAM_TYPE_AUTODETECTION = true;
public const bool ALLOW_FFMPEG_FRAMEGRABBER = true;
@ -191,6 +192,10 @@ namespace skyscraper5.Skyscraper.Scraper
//PID 0x1F
//won't need these. We operate on broadcasted stuff, so we shouldn't encounter partial TS
//ISDB BIT
//PID 0x24
dvbContext.RegisterPacketProcessor(0x24, new PsiDecoder(0x24, new IsdbDetector(this)));
if (dataStorage == null)
{
throw new ArgumentNullException(nameof(dataStorage));
@ -3680,5 +3685,25 @@ namespace skyscraper5.Skyscraper.Scraper
}
ipTrafficHandler = sink;
}
private Matenro _matenro;
public void IsdbDetectionResult(bool isIsdb)
{
if (isIsdb)
{
LogEvent(SkyscraperContextEvent.IsdbTester, "Stream is ISDB, switching from Skyscraper to Matenrō");
for (int i = 0; i < 0x1fff; i++)
{
DvbContext.RegisterPacketProcessor(i, null);
}
_matenro = new Matenro(DvbContext, DataStorage, ObjectStorage, UiJunction, LogEvent);
}
else
{
LogEvent(SkyscraperContextEvent.IsdbTester,"Stream is not ISDB");
DvbContext.RegisterPacketProcessor(0x0024, null);
}
}
}
}

View File

@ -109,6 +109,7 @@
Atsc3ServiceFound,
Atsc3Segment,
Atsc3Held,
ThreeMediaOttFileDelivery
ThreeMediaOttFileDelivery,
IsdbTester
}
}