DVB.NET 4.0 Konzepte: Arbeiten mit Quellen

Nach den ganzen Einführungen hier einmal etwas Praktisches am Beispiel: es ist die Aufgabe, eine Aufzeichnung eines Senders (sagen wir mal ZDF) in eine TS (Transport Stream) Datei zu starten und gleichzeitig an einen anderen Rechner im Netzwerk zu versenden (der die Aufzeichnung dann Live mit VLC oder dem DVB.NET / VCR.NET Viewer betrachten kann).

Erst einmal zu der schlechten Nachricht: DVB.NET 3.5.1 wird im Kern keine direkte Namensauflösung von Sendern anbieten! Was genau ich da zur Verfügung stelle, weiß ich noch nicht. Aber ganz trivial wird es nicht, Sender mit identischem Namen zu unterscheiden – etwa die vielen Channel 4 Varianten auf Astra 2. Meiner Ansicht nach ist das ein eigenständiges Problem, dass auch gesondert gelöst werden muss, aber im Moment noch nicht Thema ist.

Um einen Sender in DVB.NET zu adressieren, benötigt man dessen eindeutige DVB Kennung (Ursprungsnetzwerk, Transportstrom, Dienst) – für das ZDF wäre das (1, 1079, 28006). Mit Hilfe der neuen statischen .NET Klasse ProfileManager ermittelt sich daraus eine Liste von SourceSelection Instanzen. Hat man mehrere aktive Geräteprofile, so kann es dann auch mehrere Auswahlinstanzen geben – konkret auch von verschiedener Empfangsart wie DVB-S und DVB-C. Jede Auswahlinstanz enthält weitere Details wie den Namen des Geräteprofils, über das die gewünschte Quelle erreicht werden kann. Jede Instanz kann über die .NET Eigenschaft SelectionKey in eine Zeichenkette serialisiert und später daraus rekonstruiert werden – genau dies wird dann etwa von VCR.NET 3.5.1 zur eindeutigen Identifikation einer Quelle verwendet, ohne die ganzen Probleme mit dem Umbennen von Sendern, die einige Anbieter das eine oder andere Mal machen.

Eine SourceSelection ist eigentlich auch die Verbindung zwischen der Auswahl des Anwenders und der eindeutigen Erkennung einer Quelle samt Geräteprofil, DVB.NET Ursprung, Quellgruppe (Transponder) etc. Eine Anwendung wie VCR.NET wird dem Anwender eine geeignete Namensrepräsentation zur Auswahl anbieten, selbst aber die eindeutige Repräsentation via SelectionKey speichern.

Hat man einmal eine Auswahlinstanz, so kann man diese mit der Methode SelectGroup aktivieren – nachdem man sich für die Benutzung einer DVB.NET Geräteabstraktion über den HardwareManager angemeldet hat. SelectGroup entspricht einem Tune Vorgang und wählt eine Quellgruppe (Transponder) an, so dass die darauf übertragenen Datenströme zum Empfang bereit stehen.

Der letzte Schritt es es dann nur noch, über eine StreamSelection Instanz den Empfang der Quelle zu aktivieren. Sollen mehrere Quellen der gleichen Gruppe ausgewertet werden (im Beispiel etwa zusätzlich zum ZDF auch noch KiKa und DLF Radio), so ist der Vorgang mit entsprechenden Auswahlinstanzen zu wiederholen. SelectGroup kann aufgerufen werden, ist aber optional: DVB.NET 3.5.1 erkennt automatisch, dass die selbe Quellgruppe aktiviert werden soll und macht dann einfach nichts.

In einer StreamSelection kann angegeben werden, welche Aspekte der Quelle mit in den Empfang aufzunehmen sind – etwa welche Tonspuren welcher Art und Sprache. DVB.NET 3.5.1 ermittelt automatisch die aktuell angebotenen Aspekte und erfüllt diese Wünsche soweit als möglich.

Aus der Aktivierung wird eine SourceStreamManager Instanz geliefert. Diese kann nun einfach verwendet werden, um den Empfang in eine Datei zu lenken und / oder den Netzwerkversand zu aktivieren. Hier nun das volle Beispiel:


// Station of interest
SourceIdentifier station = new SourceIdentifier
{
Network = 1,
TransportStream = 1079,
Service = 28006
};

// Find the station of interest
SourceSelection zdf = ProfileManager.FindSource( station )[0];

// Create the device instance
using (HardwareManager.Open())
{
// Tune
zdf.SelectGroup();

// Create new
StreamSelection selection = new StreamSelection();

// MP2
selection.MP2Tracks.AllLanguages = true;

// AC3
selection.AC3Tracks.AllLanguages = false;
selection.AC3Tracks.Languages.Add( "Deutsch" );

// Videotext
selection.Videotext = true;

// EPG
selection.ProgramGuide = true;

// Create access context
using (SourceStreamsManager streams = zdf.Open( selection ))
{
// Create the stream
streams.CreateStream( @"v:\videorecorder\ts\test1.ts" );
streams.StreamingTarget = "localhost:6666";

// Report
Console.WriteLine( "Recoding active" );
Console.ReadLine();
}
}

Für den Empfang werden alle MP2 Tonspuren, die deutsche AC3 Tonspur und der Videotext angefordert. Zusätzlich werden Informationen aus der Programmzeitschrift eingebettet. Die empfangenen Daten werden in eine TS Datei gebündelt und gleichzeitig an den TCP/IP UDP Port 6666 auf dem selben Rechner versendet.

Natürlich ist auch wie bisher der direkte Zugriff auf die DVB Hardware möglich, etwa der gezielte Empfang einzelner Teildatenströme (PIDs) und der direkten Auswertung im Speicher. Aber das ist hier nicht das Thema, hier ging es um die oberste Ebene des Zugriffs auf Quellen.

So long

Jochen

DVB.NET 4.0 Konzepte: Sendersuchlauf

Wie in den früheren Version werden auch DVB.NET 3.5.1ff Geräteprofile die Liste der Sender (Quellen in der neuen Notation) in sich tragen. Ebenso wird es möglich sein, gemeinsame Listen für verschiedene gleichartige Geräte zu verwenden – etwa ein DVB-S(2) Geräteprofil mit Senderliste für eine Hardware, die von anderer DVB-S(2) Hardware im gleichen Rechner mit genutzt wird. Dabei ist es jetzt auch möglich, unsinnige Quellgruppen (Transponder) aus der Referenz auszublenden – eine Hauppauge Nexus-S kann mit den DVB-S2 Quellgruppen einer TechnoTrend S2-3200 nichts anfangen.

Ebenso wie früher ist in einem Geräteprofil mit Quellen vermerkt, auf welcher Basis diese ermittelt wurden. Im Beispiel DVB-S (DVB-C und DVB-T sind diesbezüglich etwas einfacher) werden wie bisher erst einmal die einzelnen Satellitenantennen definiert, die von der jeweiligen Hardware mittels DiSEqC 1.0 angesteuert werden können (die alte Bezeichnung LNB wird durch den Begriff des Ursprungs ersetzt). Jeder Ursprung wird dann mit einer Satellitenkonfiguration verbunden, etwa Astra 1 auf 19.2° Ost. Und damit kommen wir zum eigentlichen Punkt dieses Artikels…

Für jeden Satelliten (ähnlich für DVB-C und DVB-T, hier geht es nur um das Prinzip) wird erst einmal eine Liste aller Quellgruppen (Transponder) verwendet, die bei einem Suchlauf angesteuert und nach Quellen (Fernsehen, Radio, Sonstiges) abgesucht werden sollen. Anders als bisher geht nun DVB.NET 3.5.1ff hin und ermittelt nach dem Ansteuern einer Quellgruppe die Gesamtkonfiguration des Satelliten über die so genannte SI Tabelle Network Information Table (NIT). Hier können etwa Quellgruppen vermerkt sein, die in der statischen (evtl. veralteten) Liste nicht vorhanden sind (man denke etwa an die neuen Frequenzen für Phoenix et al). Optional können Frequenzen und andere Empfangsparameter korrigiert sein – DVB.NET benutzt hier einen etwas entspannteren Vergleichsalgorithgmus, der auch Quellgruppen mit leicht veränderter Frequenz korrekt als identisch erkennt. Ein Sendersuchlauf berücksichtigt die Daten der NIT vorrangig. Da diese Informationen relativ selten gesendet werden (es kann schon mal über 10 Sekunden dauern, bis diese zur Verfügung stehen), versucht DVB.NET den Abruf so selten wie möglich vorzunehmen. Konkret wird die NIT nur für die Quellgruppen angefordert, die sich in der ursprünglichen (statischen) Liste befunden haben und nicht durch die NIT einer so ausgewerteten Quellgruppe schon bestätigt wurden.

Darin stecken zwei Ideen und ein Zwang. Die primäre Idee ist es, die Liste der Quellgruppen pro Satellit auf ein Minimum zu beschränken – DVB.NET 3.5.1ff wird dazu auch ein eigenes Werkzeug anbieten, dass zu einer Liste einen minimalen Satz von Quellgruppen ermittelt, über deren NIT Informationen die Liste rekonstruiert werden kann. Astra 1 ist da ein sehr gutes Vorbild: hier reicht eine einzige (!) Quellgruppe, um alle Frequenzen zu erfassen. Zusätzlich soll es aber auch möglich sein, mehr als eine Quellgruppe für die Ermittelung der vollständigen Liste einsetzen zu können – vital für DVB-T, daher der Zwang. Die zweite Idee schließlich ist die Annahme, dass NIT Informationen für Gruppen von Quellgruppen identisch sind – i.e. wenn die NIT der Quellgruppe A B enthält, dann wird A auch in der NIT von B vorhanden sein und die NIT von B ist mit der von A identisch. Damit kann bei den langen Listen, die aus der alten DVB.NET Version übernommen wurden, das Warten auf die NIT soweit als möglich reduziert werden. Ob das so passt, werden wir sehen… Ziel ist es, für die wichtigsten Ursprünge irgendwann einmal minimierte Listen zu haben – DVB-S ebenso wie DVB-C und DVB-T.

Ansonsten ist ein Suchlauf nicht viel anders als früher. Lediglich der Umfang der Informationen im Geräteprofil ist dramatisch reduziert – es werden keinerlei Datenstromkennungen (PID) mehr fest eingetragen – dazu an anderer Stelle mehr. Nach einen Suchlauf wird die neue Liste üblicherweise mit der alten zusammengeführt, i.e. die neuen Quellen ersetzen die alten, aber gerade nicht verfügbare Quellen werden nicht entfernt (etwa bedingt durch eine zeitliche Beschränkung der Ausstrahlung). Bekannte Mechanismen wie das Ausblenden von Quellgruppen und Quellen oder das Anpassen von Quellinformationen wie dem Sendernamen werden ebenso unterstützt.

Ok, zum Schluss: der gesamte Algorithmus für den Sendersuchlauf soll weitgehend konfigurierbar als eigenständige Komponente (.NET Klasse) nutzbar (! angeboten war es immer schon, nur die Nutzung war kniffelig !) angeboten werden. Diese wird dann nicht nur im neuen DVB.NET Konfigurationswerkzeug, sondern auch in VCR.NET 3.5.1 genutzt.

Puh, das war wieder viel zu viel. Genug!

Jochen

DVB.NET 3.5.1 Suchlauf

DVB.NET 4.0 Konzepte: Dynamische Empfangsdaten

Zusätzlich zu den Grundelementen der DVB.NET 4.0 Senderliste (man siehe dazu den Artikel unmittelbar vor diesem hier) bietet jede Ebene ein zugehörige Informationsklasse an. Informationen können bei aktiver DVB Hardware über diese auf verschiedene Arten angefordert werden – das ist im Moment noch nicht mein Thema. Aktiv bedeutet dabei, dass eine Quellgruppe (zur Erinnerung: das war mal ein Transponder) auf einem Ursprung (nur für DVB-S die DiSEqC Auswahl) ausgewählt wurde.

Die SourceInformation enthalten alle Daten zu einer Quelle. Das umfasst vor allen die Details zum Empfang der Teildatenströme (Datenstromkennungen (PID) von Bild und Ton etwa) aber auch die Art des Bildsignals und so weiter. Im SI Modell entspricht eine Instanz dieser Klasse einer Program Mapping Table (PMT) eines Dienstes.

Auf nächster Ebene kann eine GroupInformation zu einer Quellgruppe angefordert werden. Diese enthält ausschließlich die Liste der auf der Gruppe verfügbaren Quelle, aber keine technischen Empfangsdaten. In der SI Architektur entspricht dies in etwa einer Kombination aus Program Association Table (PAT) und Service Description Table (SDT). Ein besondere Rolle spielen in DVB.NET die so genannten Dienste. Hier handelt es sich um Quellen (gemäß der SI PAT), zu denen aber keine Beschreibung (in der SI SDT) existiert. Diese sind gesondert gekennzeichnet. Die Gruppeninformation enthält als Liste von Quellen tatsächlich Instanzen der Station Klasse, da nur diese derartige Unterschiede bezeichnen – zukünftig vielleicht auch einmal Datendienste. Man beachte, dass die oben beschrieben Empfangsdaten der einzelnen Quellen bewußt nicht enthalten sind.

Mit der LocationInformation kann schließlich die Liste der Quellgruppen (nicht der Gruppeninformationen) eines Ursprungs ermittelt werden – entsprechend der Network Information Table (NIT) in der SI Architektur. Diese .NET Klasse liegt in spezifischen Varianten für DVB-S, DVB-C und DVB-T vor (SatelliteLocationInformation et al), was die Handhabung in Einzelfällen vereinfacht.

Für alle Informationensklassen ist zu beachten, dass die Qualität und Quantität der enthaltenen Daten vom jeweiligen Anbieter abhängt. DVB.NET 4.0 wird vermutlich analog zur bekannten Nachbearbeitung der Senderliste manuelle Korrekturmöglichkeiten anbieten – etwa um ITV HD empfangen zu können. Die Informationen zu den Quellgruppen eines Ursprungs scheinen für DVB-S und DVB-C relativ gut und symmetrisch zu sein (alle Quellgruppen melden die selben Informationen zur Verfügbarkeit anderere Quellgruppen), wo hingegen DVB-T schon konzeptionell sehr viel segmentierter angelegt ist.

Bis denmächst

Jochen

DVB.NET 4.0 Konzepte: Glossar

Bevor ich demnächst einiges zum aktuellen Stand von DVB.NET 3.5.1 erzähle (zur Erinnerung: hier werden nur erste Teile von 4.0 enthalten sein) einige Worte zur veränderten / verallgemeinerten Nomenklatur.

Eine Quelle bezeichnet eine DVB Sendeeinheit und ist im Allgemeinen entweder ein Fernseh- oder ein Radiosender, technisch sind aber auch Datendienste vorgesehen. Repräsentiert wird eine Quelle in DVB.NET durch die Klasse SourceIdentifier, in etwa dem alte Identifier entsprechend. Eine Quelle wird eindeutig durch ein Tripel (Originale Netzwerkkennung, Datenstromkennung, Dienstkennung) gekennzeichnet – ein über DVB-C empfangens ZDF hat in diesem Sinne im Allgemeinen die gleiche Quelle wie das über DVB-S empfangene.

DVB.NET selbst unterstützt allerdings keine Datendienste, sondern nur Sender, die durch die Klasse Station repräsentiert werden. Ein Sender ist nichts anderes als eine erweiterte Quelle – auch im Sinne der .NET Vererbungsachse. Zusätzlich zu den Daten der Quelle enthält ein Sender Informationen zur Auswahl durch den Anwender (Anzeigename, Name des Dienstanbieters) und zur Planung von Aufzeichnungen (Entschlüsselung notwendig). Ein Sender enthält aber keine Datenstromkennungen zum Empfang selbst (PID des Bildsignals etwa). Wie früher bereits einmal erwähnt soll DVB.NET 4.0 sehr viel dynamischer auf Änderung dieser technischen Daten reagieren können. Tatsächlich wird eine DVB.NET 4.0 Senderliste nur diese reduzierte Fassung eines Senders enthalten!

Quellen werden zu Quellgruppen zusammengefasst, früher als Transponder bezeichnet. Eine Quellgruppe beschreibt die technischen Empgfangsdaten wie Frequenz und Modulation in drei unterschiedlichen Basisklassen für DVB-S (SatelliteGroup), DVB-C (CableGroup) und DVB-T (TerrestrialGroup), alle von einer gemeinsamen .NET Basisklasse SourceGroup abgeleitet. Neben den technischen Daten sind alle Quellen enthalten, die von der jeweiligen Quellgruppe angeboten werden.

Speziell für DVB-S wurde zusätzlich das Konzept des Ursprungs eingeführt, am besten mit den alten DiSEqC Varianten zu vergleichen. Jede Quellgruppe hat einen Ursprung, der beschreibt, wie die Gruppe empfangen werden kann. Die .NET Klasse SatelliteLocation ist von einer Basisklasse GroupLocation abgeleitet, die auch über generische Varianten zu entsprechenden DVB-C und DVB-T Klassen führt – wobei es hier im allgemeinen nur einen einzigen Ursprung (Default Location) gibt. Jeder Ursprung enthält neben den Empfangsdaten alle Quellgruppen, die nach Auswahl empfangen werden können.

Eine DVB.NET 4.0 Senderliste ist im Wesentlichen die als XML serialisierte Form einer Liste von Ursprüngen.

Tschüss

Jochen

Spaß mit Extensionmethoden – hier: zyklische Referenzen von Assemblies

Man stelle sich eine Anwendung vor, die aus zwei Assemblies besteht. Die eine enthält ausschließlich Klassen, die zur Konfiguration dienen und etwa in die XML Repräsentation serialisiert werden. Als Beispiel eine Klasse StationInformation, die zu einem Fernsehsender alle Informationen für einen DVB Empfang beinhaltet (PIDs, um es konkret zu machen). Diese Assembly ist von nichts ausser .NET abhängig. Eine andere DLL implementiert einen DVB Zugriff über BDA und ist reichlich von diversen Bibliotheken abhängig. Natürlich auch von unserer ersten Assembly. In der zweiten Assembly gibt es etwa eine Klasse DVBHardware mit einer Methode UpdateStation, die eine StationInformation als Parameter erhält und die Empfangsdaten auf den aktuellen Stand bringt (etwa gibt es nur zeitweise einen Videotext wie bei KiKa).

Die Abhängigkeit der Assemblies zwingt nun erst einmal einen Anwender der Bibliotheken, die DVBHardware Instanzen ins Zentrum seines Denkens zu stellen: nur hier kann es Methoden geben, die beide Assemblies nutzen. Mit einer Extensionmethode läßt sich aber nun einfach eine Flexibilität erreichen, die eine natürlicher Sicht auf die Dinge erlaubt (eigentlich interessiert mich der Empfang eines Senders, die verwendete Hardware ist eigentlich zweitrangig): mit

public static void Update
(
this StationInformation station,
DVBHardware hardware
)
{
hardware.Update(station);
}

kann nun alternativ auch StationInformation.Update(hardware) aufgerufen werden. Aus Sicht des Anwenders, der beide Assemblies gleichzeitig verwendet und beim IntelliSense nicht so genau hinschaut sieht es fast aus, als würden sich die beiden Assemblies hier gegenseitig (zyklisch) referenzieren.

Wie dem auch sei und unabhängig davon, ob das Beispiel trägt: Extensionmethoden machen es beim Design von Bibliotheken einfacher, sich nicht schon früh auf eine Sichtweise festlegen zu müssen. Eine vollständig symmetrische Sicht ist zwar nicht immer notwendig und man kann es dabei auch leicht übertreiben, aber in Einzelfällen halte ich das für eine durchaus interessante Option – ausserhalb der trivialen Bedeutung, scheinbar abgeschlossene Klassen mit neuen Instanzmethoden erweitern zu können.

Happy Coding

Jochen