Philips TV-Remote unter Linux ============================= :author: Benjamin Franzke :lang: de :imagesdir: image // a2x: --dblatex-opts="-p thesis.xsl -s thesis.sty -b xetex" [abstract] == Aufgabe Ziel dieses Forschungsprojektes ist die Programmtechnische Umsetzung der Nutzung der Philips TV-Firmware als Netzwerkbasierter-Infoscreen. Als Plattform wird dabei GNU/Linux verwendet. Es werden im weiteren Lösungsmöglichkeiten für die Probleme der aktuellen Konfiguration mit dem Windows Client Pluggit evaluiert. == Grundlagen *DirectFB* 'DirectFB' ist eine Bibliothek, die als Hauptaufgabe Beschleunigung durch Grafik-Hardware bereitstellt. Außerdem werden auch Eingabegeräte unterstützt, und es enthält ein integriertes Fenster-System. Auf Grund der genannten Eigenschaften kann DirectFB als Hardwareabstraktionsschicht bezeichnet werden. *DirectFB Voodoo* 'DirectFB Voodoo' ist ein Aufsatz bzw Proxy-Kanal für DirectFB. Es besteht aus einer Client-Server Architektur. Der Server ist dabei das Anzeige Gerät und bietet über den Voodoo Kanal Zugriff auf den eigenen Framebuffer. Die clientseitige Implementierung leitet 'DirectFB'-API-Aufrufe per 'DirectFB-Voodoo' an den Server weiter, auf dem diese dann ausgeführt werden. 'DirectFB-Voodoo' ist demzufolge eine Remote-Rendering Infrastruktur die das Zeichnen von Primitiven wie Rechtecken und Kreisen ermöglicht, aber auch das übertragen von ganzen Bildinhalten. *JointSpace* 'JointSpace' ist ein Framework und API für Fernseher von Philips. Es ermöglicht das Fernseher über das API gesteuert werden können, und eine Bildübertragung per Netzwerkverbindung. Das API zur Steuerung der Fernseher basiert auf einem REST-Full HTTP-Protokoll. Für die Bildübertragung wird 'DirectFB Voodoo' eingesetzt. == Ist-Zustand Verwendet werden Fernseher der 7000er Serie von Philips, auf die eine, direkt vom Hersteller erweiterte Firmware geladen wird. Diese beinhaltet die 'JointSpace' Erweiterung. Als Datenquelle dient eine Windows-Installation in einer virtuellen Maschinen, welche das ebenfalls vom 'JointSpace' bereitgestellte Programm 'Pluggit' verwendet. Die einzelnen Fernseher sind alle in eigenen Netzen, da zum Verbindungsaufbau ein Netzwerk-Broadcast genutzt wird und sich so die Fernseher gegenseitig stören würden, wenn in einem Netzwerk enthalten. Der Firefox-Browser wird für die Darstellung im Vollbildmodus eingesetzt, da er unter Windows einer der stabilsten und ausgetestetsten, standardkonformer Browser ist. Die Fernseher bieten eine native Auflösung von +1920x1080+ Pixeln, die Remote-Anzeige funktioniert aber nur bis zur Auflösung von +1280x720+ Pixeln. == Problemlösung & Implementation Im ersten Schritt ist eine eins-zu-eins Umsetzung der Anzeige eines Linux-Screens auf einen Fernseher zu implementieren. Im zweiten sollen von einem Rechner mehrere Streams an verschiedene JointSpace-Fernseher gesandt werden. In diesem Fall 3 Clients. Das in Abbildung 1 aufgezeigte Schema verdeutlich die Server-Client Architektur von 'DirectFB-Voodoo'. Dabei wird deutlich, dass 'Pluggit' die Bildschirmdaten vom Xorg-Server ausliest und per Netzwerk an den Fernseher überträgt. Der Fernseher besitzt .Client-Server Interaktion image::directfb-voodoo-js.eps[] === Pluggit Als Basis für die Programmtechnische Umsetzung dient der Bestehende Windows-Client Pluggit, sodass die bereits ausgetestete Remote-Rendering Infrastruktur wiederverwendet werden kann. Pluggit wurde so verändert, dass es X11-Protokoll anstatt der WinAPI verwendet wird, um den Inhalt eines Fensters oder des ganzen Framebuffers anzuzeigen. Dazu ist eine 'SourceX11' Klasse notwendig, die das in Pluggit enthaltene Interface 'Source' implementiert. // TODO: Graph? ==== Verbindungsaufbau Die DirectFB-Voodoo Plattform nutzt als Standardmethode zum Verbindungsaufbau einen Broadcast Request, um verfügbare Anzeigegeräte zu finden. Dies ist für den Einsatz im Heimnetzwerk gedacht, bei dem der Verbindungsaufwand möglichst gering gehalten werden soll. Sind mehrere der Fernseher in einem Netzwerk, so ist nicht eindeutig definiert, welcher zuerst auf den Broadcast antwortet, und dadurch für die Verbindung ausgewählt werden wird. Aus diesem Grund ist eine sofortige Unicast-Verbindung nötig. Die Bibliothek bietet kein direktes API, um die Ziel-Addresse zu verarbeiten. Die Initialisierungsmethode +DirectFB::Init()+ erwartet einen Argumentenzähler und -vektor. Dieser Vektor bezieht sich auf die Kommandozeilen Argumente, im folgenden beispielhaft dargestellt: [source,c] ---- #include int main(int argc, char *argv[]) { DirectFB::Init(&argc, &argv); return 0; } ---- ==== Verbindungsabbruch Bricht die Verbindung ab -- z.B. durch Ausschalten des Fernsehers oder durch Auswählen einer anderen Quelle -- wird dies durch die DirectFB Bibliothek nicht an die Anwendung signalisiert. Im produktiven Einsatz ist es bei Remote-Steuerung deshalb nicht zu erkennen, ob die Verbindung besteht. Im weiteren ist auch keine automatisierte Neuverbindung möglich. //die Anwendung signalisiert. //Intern wird der Rückgabewert von +send(2)+ nicht auf einen Verbindungsabbruch //geprüft. *Lösung:* Die Bibliothek DirectFB wurde erweitert, das SIGPIPE Signal vom Kernel zu empfangen. Pluggit installiert für DirectFB eine Signal Behandlungsroutine und bricht die Programmausführung ab. Ein Shell-Script das 'Pluggit' überwacht, erkennt dies am Rückgabe-Status des Pluggit-Prozesses und startet diesen neu. //== Webbrowser-Rendering === Framebuffer Größenlimit Bei der Verwendung von 'Pluggit' unter Windows besteht das Problem, dass eine maximale Auflösung von +1280x720+ Pixeln genutzt werden kann. Dieses Limit ist kein Fehler im Programm oder eine Einschränkung des Betriebssystems, sondern das API erlaubt keine größere Auflösung. Bei Verwendung von z.B. einer +1920x1080+ Auflösung -- bei einem Fernseher, der diese Auflösung per HDMI unterstützt -- signalisiert das API einen Fehler, dass ein invalides Argument übergeben wurde. === Framebuffer Auslesen Das X11-Protokoll bietet die Möglichkeit den angezeigten Framebuffer über die Funktion +XGetSubImage(3)+ auszulesen. Darüber hinaus gibt es eine Anbindung an +shmget(2)+, sodass Unix Shared-Memory verwendet werden kann. Dies bietet den Vorteil, dass die Framebuffer-Daten nicht über den X11-Protokoll-Socket übertragen werden müssen, sondern direkt gelesen werden können. Es wird ein X11-Pixmap erzeugt, welchem ein auf XImage auf Shared-Memory Basis zugrunde liegt. Zum Auslesen wird nun +XCopyArea(3)+ mit dem X11-Pixmap als Argument aufgerufen. Der X-Server schreibt in der Folge den angefragten Bildinhalt in den Shared-Memory, === Multi-Client Teil der Anforderung ist, mehrere Fernseher gleichzeitig mit unterschiedlichen Bildern zu beliefern. Um mehrere Fenster darzustellen, wird ein großer Anzeigebereich benötigt. Mit 'XRandR' wird dies durch folgenden Aufruf erreicht: [source,sh] ---- xrandr --fb $((1280*3+10))x768 ---- .X11-Fenster Konfiguration image::framebuffer.svg[] === Browser Die Anzeige des Infoscreens erfolgt über eine HTML-Website, die auch Multimediainhalte enthält. Aus diesem Grund ist es nötig, dass das HTML von einem Web-Browser gerendert wird. In Betracht kommt auf Grund der Bekanntheit und Stabilität der Firefox-Browser. Dieser kann nur im Vollbild-Modus so konfiguriert werden, dass nur der Inhalt im X11-Fenster -- welches ausgelesen werden soll -- angezeigt wird, Menus und Scrollbars sind im normalen Floating-Modus immer vorhanden. Ein weiteres Problem stellt die eindeutige Adressierung der WindowID, bei Veränderung mehrerer Firefox-Fenster. Es gibt keine direkte Möglichkeit die WindowID zu erhalten, nur über Matching des Titels des Firefox-Fensters. Die Verwendung für mehrere Infoscreens würde es nötig machen den Titel des angezeigten Inhalts zu wissen, und in der Programmlogik zu berücksichtigen. Eine Veränderung des Inhalts würde damit auch eine Anpassung des Programms erfordern. Deshalb wird ein Web-Browser benötigt, der es ermöglicht nur den Inhalt der Website im X11-Fenster darzustellen. Der Browser 'Surf' footnote:[http://surf.suckless.org] von 'suckless.org' ist mit dem Prinzip erstellt worden, in andere Programme über das X11-XEmbed Protokoll eingebettet zu werden, z.b. um mehrere Instanzen in einem Tab-Manager zu einzubetten. Dies ermöglicht per Design zwei Vorteile: - Die WindowID wird auf +stdout+ ausgegeben. + (Kann demzufolge als Parameter an Pluggit übergeben werden.) - Keine Bedienelemente vorhanden, denn der Browser wird über X11-Properties gesteuert -- das erlaubt Scripting. == Test Getestet wurde jeweils mit der Infoscreen-Website footnote:[http://et.hs-wismar.de/~infosc/index.php?file=config16n] des Fachbereichs EuI: Da während der Entwicklung nicht dauerhaft Philips-Fernseher zur Verfügung standen, wurde der durch das 'JointSpace'-Projekt als VMWare-Virtuelle Maschine bereitgestellte Simulator mit QEMU verwendet. Das Anzeigen des Browser-Inhaltes und die korrekte Wiedergabe des Videos entscheiden über das Bestehen des Tests. == HowTo === Linux Betriebssystem Ein minimales Betriebssystem wie Gentoo Linux oder Arch Linux kann als Client genutzt werden. === System Vorraussetzungen Das System muss einen Xorg-Server mit Xrandr 1.3 Unterstützung besitzen und die dazugehörige 'libX11'. Das Utility wmctrl wird zur Positionierung und Größenfestlegung der Browser genutzt. Der Browser selbst ist 'surf'. Die Installationsroutine, beispielhaft für Gentoo Linux: [source,sh] ---- emerge -va xorg-server libX11 xrandr wmctrl surf ---- === DirectFB Für diese Arbeit wurde die, zum Zeitpunkt der Bearbeitung, neuste Version von 'DirectFB' verwendet: DirectFB141_source_1.3.1beta5.7z footnote:[http://sourceforge.net/projects/jointspace/files/remote_applications_SDK/] [source,sh] ---- 7z x DirectFB141_source_1.3.1beta5.7z ---- Die Sourcen, inklusive benötigter Patches (mit GIT-History), sind auch im beiliegenden Archiv enthalten. === Pluggit [source,make] ------------------------------------------------------------------------- .PHONY: pluggit pluggit: rm -f pluggit/pluggit # <1> $(MAKE) -C directfb-voodoo/ -f makefile.voodoo DEBUG=$(DEBUG) package # <2> $(MAKE) -C pluggit/ -f makefile.voodoo DIRECTFB_VOODOO=../directfb-voodoo/DirectFB_Voodoo all ------------------------------------------------------------------------- <1> In der Entwicklungsphase ist es notwendig, dass pluggit neu gelinkt wird, wenn directfb verändert wird. <2> Der DirectFB package baut die Bibliothek und kopiert Header an die benötigten Stellen. Für die Übersetzung von DirectFB und Pluggit muss also außschließlich folgender Befehl im Quellverzeichnis des Projekts ausgeführt werden: [source,sh] ------------ make pluggit ------------ == Bewertung & Ausblick Die Performanz ist durch das ständige Übertragen kompletter Bilder eingeschränkt auf die Übertragungsbandbreite des Kanals. Zur Optimierung könnte ein direktes Remote-Rendering des WebBrowsers, bzw dessen Backends, verwendet werden. Ein weiterführender Ansatz wäre es deshalb, das sich in Entwicklung befindende -- und deshalb zum Zeitpunkt dieser Arbeit noch nicht verwendbare -- WebKit-DirectFB footnote:[http://git.directfb.org/?p=libs/WebKitDFB.git;a=summary] backend zu diesem Zweck zu nutzen. Eine weitere Alternative wäre die Implementation eines Wayland-Compositors footnote:[http://wayland.freedesktop.org/], der direkt und ausschließlich die Framebuffer Daten per DirectFB-Voodoo überträgt. Auf diese Weise wäre ein Offscreen-Rendering möglich, und die Workarounds bezüglich nebeneinander Positionierung mehrerer Browser-Fenster und eine vergrößerte Arbeitsfläche wären nicht notwendig. Das Übertragen der Framebuffer-Daten, aber auch der Rendering-Direktiven wird stets eine Höhere Datenrate aufweisen, als die HTML Daten (+embedded Video) zu übertragen. Diese werden zwar nicht direkt von Fernsehern der Philips 7000er Generation angezeigt. Ein alternativer Ansatz wäre aber das Verwenden von Mini-Computern, z.B. Thin-Clients, die einen Web-Browser besitzen und die Anzeige mittels VGA oder HDMI an den Fernseher übertragen. // vim: set syntax=asciidoc tw=78 filetype=asciidoc: // spell spelllang=de,en: