\documentclass{article} \usepackage[T1]{fontenc} \usepackage{fontspec} \usepackage{lmodern} \usepackage{amsmath} \usepackage[margin=1.5cm]{geometry} \usepackage{graphicx} \begin{document} \title{Dokumentation VanadiumCast} \author{Silas Della Contrada} \date{12/18/2020} \maketitle \section{Hinweis zur Formatierung}\label{sec:hinweis-zur-formatierung} Verweise zu Quellen und weiterführender Literatur sind mit einer dreistelligen Buchstabenkombination in eckigen Klammern dargestellt: \begin{quote} Bla bla bla\ldots{} {[}ExW{]} bla bla bla\ldots{} {[}ExB{]} \end{quote} Die Einträge im Literaturverzeichnis lauten dann wie folgt: \begin{quote} {[} ExW{]} \emph{Example website}: https://example.com/examplesite.html {[}2020-12-18{]} {[}ExB{]} Max Mustermann (2020), \emph{Example book}, Beispielverlag, ISBN: 1234567890 \end{quote} \section{Vorwort}\label{sec:vorwort} Google Chromecast ist weit verbreitet, allerdings ist es kein Open-Source und man ist gezwungen ein Google Chromecast oder ein Android TV als Ziel und entweder Chrome oder ein Android-Gerät als Quelle zu benutzen. Außerdem gibt es keine Möglichkeit den Desktop zu übertragen, wodurch eine potenziell gute Lösung eine große Nutzergruppe nicht anspricht. In diese Lücke fügt sich nun VanadiumCast ein. \newpage \section{Projektidee}\label{sec:projektidee} Mit VanadiumCast kann man Videos und (in Zukunft) seinen Desktop an ein beliebiges Gerät übertragen, auf dem das Programm installiert ist. Es ist ähnlich einfach zu bedienen wie Chromecast, sodass es auch für technisch unbedarfte Personen nutzbar ist. Lediglich die Installation der Endgeräte ist deutlich schwieriger, da diese aber nur einmalig erfolgen muss, gibt es dort keine Probleme. Zudem ist geplant, dass VanadiumCast auf allen Desktop- und Mobilgeräten installiert und benutzt werden kann, sodass auch Handy\textrightarrow Handy oder Desktop\textrightarrow Handy Übertragungen möglich sind. Als Zielgerät eignet sich aktuell nur Laptops / PCs / Mini-PCs / SBCs mit Intel-CPUs mit iGPUs ab der 3. Generation oder Nvidia-GPUs ab der GTX 8xx, als Quellgerät die gleichen Gerätetypen, jedoch werden hier Intel-CPUs ab der 4. Generation vorausgesetzt, da auf der Quelle mehr Leistung benötigt wird als auf dem Ziel. Es ist aber geplant beide Seiten zu optimieren und zu erweitern, sodass auch kleine SBCs wie ein Raspberry Pi oder Pine A64 als Ziel und/oder Quelle geeignet sind. Damit ist es dann auch möglich, ganze Schulen mit günstigen SBCs auszustatten, um Schülerinnen und Schülern sowie Lehrkräften Bildschirmübertragungen zu ermöglichen, ohne den komplizierten Weg über Miracast zu gehen, der nur an Fernsehern und in Kombination mit Android oder Windows 10 möglich ist. Da die Software nur im LAN kommuniziert, ist auch der Datenschutz gewährleistet, bei Google Chromecast werden hingegen Daten in die Google Cloud gesendet. Zudem lässt sich bei VanadiumCast die Übertragungsqualität einstellen, sodass man nicht darauf angewiesen ist, dass die Software die richtige auswählt. \section{Motivation}\label{sec:motivation} Weil ich persönlich keinen Google Chromecast kaufen wollte und man damit auch keine Videos von Linux aus streamen könnte, habe ich mir am Ende der Sommerferien 2020 überlegt, ob man nicht auch selbst eine Lösung dafür entwickeln könnte. Also habe ich mich im Internet über mögliche C++-Bibliotheken informiert und es wurde schnell klar, dass die sehr einfache Idee recht schwierig umzusetzen ist. Da ich zu diesem Zeitpunkt aber an keinen anderen Projekte gearbeitet habe, nahm ich die Herausforderung an. Das gesamte Projekt ist ein ``learning-by-doing''-Projekt, das heißt, dass ich mich dann über Dinge informiere, wenn ich sie konkret benötige. Zum Beispiel habe ich mich zuerst mit FFmpeg bzw. den Libav-Bibliotheken auseinandergesetzt, um zu verstehen, wie man ein Video in C++ transkodieren kann. \newpage \section{Eine kurze Einführung in AV-Verarbeitung}\label{sec:eine-kurze-einführung-in-av-verarbeitung} \subsection{Videocodecs}\label{subsec:videocodecs} Videos werden nicht im Rohformat abgespeichert, da sie unkomprimiert sehr viel Platz verbrauchen. Für einen Spielfilm auf Bluray, d.h. 120 min. Full HD mit 1 Byte pro Farbe und 24 Bildern pro Sekunde, sind das bereits: \[1920\ *\ 1080\ *\ 3B\ *\ 24\ *\ 120\ *\ 60s\ =\ 1,074,954,240,000\ B\ \approx\ 1,1\ TB\] Diese Menge an Speicherplatz möchte niemand für einen Film auf seiner Festplatte bereitstellen. Daher wurde 1988 der Kompressionsstandard H.261 festgelegt, dessen Nachfolger zum Veröffentlichungszeitpunkt immer den aktuellen Stand der Technik darstellten, aktuell sind das H.264/AVC und H.265/HEVC, welche auch in VanadiumCast zum Einsatz kommen. In GPUs stecken seit ca. 10 Jahren Videoprozessoren, die die CPU beim En-/Dekodieren von Videos entlasten, sodass weniger Energie verbraucht wird. Erst dadurch wird es möglich, auf Handys, Tablets etc. Video abzuspielen, da die Akkulaufzeit sonst zu gering wäre. \subsection{Audiocodecs}\label{subsec:audiocodecs} Bei Audiodaten ist das Problem recht ähnlich, und auch wenn man auf aktuellen SD-Karten mehrere Stunden unkomprimiertes Audio speichern kann, ist es meistens ausreichend und teilweise besser, Audio zu komprimieren, z.B. bei Streaming-Diensten wie Spotify, da mobile Daten meist teuer und limitiert sind. Ursprünglich gab es das Problem, dass man auf Walkmans nicht ausreichend Platz hatte, um mehrere Stunden Musik zu speichern, weswegen eine Arbeitsgruppe des Frauenhofer IIS in Zusammenarbeit mit einer anderen Universität, AT\&T Bell Labs und Thomson die MP3-Kodierung entwickelte. Dabei wird Platz gespart, indem durch die Anwendung von Psychoakustik gezielt Teile der Daten weggelassen oder verkleinert werden, die der Mensch normalerweise nicht wahrnimmt. Dadurch wird bei einer Bitrate von 192 kBit/s eine Kompressionsrate von 85\% gegenüber einer Audio-CD erzielt. Aktuellere Codecs wie AAC und Opus unterscheiden sich von MP3 im Kompressionsalgorithmus und der Qualität bei bestimmten Bitraten, sodass sie unterschiedlich gut für das Streaming geeignet sind. In VanadiumCast wird aktuell AAC verwendet, da es die gleiche Qualität wie MP3 bei geringerer Bitrate gewährleistet. \subsection{Containerformate}\label{subsec:containerformate} Ein Video- oder Audiocodec alleine reicht nicht aus, um eine Video mit Ton und eventuellen Untertiteln etc. abzuspeichern, daher gibt es Containerformate, durch die mehrere Video-/Audiospuren teilweise mit Untertiteln in einer Datei vereint werden. Die Auswahl des Containerformat nachezu keinen Unterschied bei der Dateigröße, sondern nur in den Möglichkeiten, welche Art von Daten enthalten sein können. Bekannte Beispiele sind das von Apple entwickelte und weit verbreitete MP4 oder das offene Matroska-Format, ersteres unterstützt nur Video- und Audiospuren, letzteres alle möglichen Spuren inklusive 3D-Inhalte und Menüs wie auf DVDs. \newpage \section{Umsetzung}\label{sec:umsetzung} \subsection{Bibliotheken und Frameworks}\label{subsec:bibliotheken-und-frameworks} Ursprünglich habe ich mich direkt mit FFmpeg und den Libav-Bibliotheken auseinandergesetzt, um den Transcoder umzusetzen, aber der Code des Transcoders wurde mit steigender Komplexität des Projekts nicht mehr verständlich, weswegen ich mich nach einer Alternative umgeschaut habe. Dabei bin ich auf das Qt-Plugin QtAV gestoßen, welche exakt die Funktionalität bietet, die ich benötige, und eine bessere API als ich sie jemals hätte schreiben können. Der Umstieg war recht einfach, da der Transcoder von QtAV lediglich ein Ein- und ein Ausgabegerät benötigt, in diesem Falle eine Datei und eine Netzwerkverbindung, und konfiguriert werden muss. Bei der Konfiguration bin ich auf einige Probleme gestoßen, da das Programm abstürzt oder sich aufhängt, wenn man die Konfiguration nicht auf die richtige Art und in der exakt richtigen Reihenfolge macht. Da QtAV aber einige Beispiele auf GitHub zur Verfügung stellt, konnte ich das Problem in relativ kurzer Zeit lösen. Aktuell bestehen noch Probleme mit der Audio-Übertragung, aber ich denke, dass auch die mit etwas Zeit lösbar sind. \newpage \subsubsection{Qt}\label{subsubsec:qt} Qt ist ein Anwendungsframework für C++ und Python, welches nahezu alle Funktionen für die Anwendungsentwicklung bereitstellt, z.B. Datenbank-Anbindung, Netzwerkkommunikation und GUIs. Darüber hinaus gibt es noch diverse Plugins von The Qt Company, also der Firma, die Qt entwickelt und vertreibt, z.B. für 3D-Darstellung, Diagramme etc., sodass man in fast allen Fällen die benötigten Funktionen direkt in Qt findet. Sollte das wie bei mir nicht der Fall sein, existieren zahlreiche Plugins der Community, die häufig Open-Source und gut dokumentiert sind, die man sich dann herunterladen und installieren kann. In Qt gibt es zwei Möglichkeiten der prozessinternen Kommunikation, zum einen mit Signals und Slots und zum anderen mit Events. Diese beiden sollen im Folgenden kurz erläutert werden, sie in Gänze zu erklären, würde den Rahmen dieser Dokumentation bei weitem sprengen. Wer sich weiter mit Qt beschäftigen möchte, dem empfehle ich die Seite ``Qt for Beginners'' im Qt Wiki {[}QfB{]}. \paragraph{Signal-Slot-Prinzip} In Qt gibt es die Möglichkeit, in einer Klasse spezielle Methoden zu deklarieren, die Signale und Slots. Signale muss man nur deklarieren, d.h., sie erhalten keine Funktionalität vom Programmierer. Beim Kompilieren des Codes geht ein Programm namens Meta-Object-Compiler (MOC) durch alle Klassen, die Signale und/oder Slots enthalten oder benutzen und stattet diese entsprechend der spezifizierten Verbindungen mit Funktionalität aus, wodurch die Signale und Slots erst nutzbar werden. Diese Funktionalität ist ebenfalls sehr nützlich, wenn man mehrere parallel laufende Funktionen hat, die miteinander Daten austauschen müssen. Außerdem muss im Programm eine Event-Loop gestartet werden, d.h., es wird eine parallel laufende Funktion gestartet, die nichts anderes tut, als alle in die Event-Queue eingereihten Signale abzuarbeiten und die verbundenen Slots aufzurufen. \paragraph{Event-Prinzip} Auch Events werden von der Event-Loop bearbeitet, daher hat sie auch ihren Namen erhalten. Events werden \textbf{nur} bei Oberflächen benutzt, und arbeiten auf einer Ebene unter den Signalen und Slots. Sie werden ausgelöst, wenn der Benutzer im Fenster die Maus bewegt, mit ihr klickt, das Fenster vergrößert oder verkleinert, wenn das Fenster minimiert, maximiert oder in Vollbildmodus gesetzt wird. Es gibt viele weitere Eventtypen, siehe die API-Referenz zu Qt-Events {[}QER{]}. Da es nur vordefinierte Events gibt, kann man auch nur vordefininierte Event-Handler überschreiben. \paragraph{Oberflächen mit QML} Für Qt existieren zwei Möglichkeiten eine Oberfläche zu erstellen, eine davon ist die Qt Markup Language (QML). Mit QML kann man sehr schnell Oberflächen erstellen, da es vordefinierte Elemente, wie Knöpfe oder Text-Eingaben, gibt, die nur miteinander kombiniert werden müssen. Außerdem stehen drei Themes zur Auswahl: Material, das Standard Design unter Android 5 - 8, Universal, das Windows App Design, und Fusion, das Standard Qt Design. Direkte Funktionalität lässt sich per Javascript in QML einbetten, zudem ist es möglich, bestimmte, aus C++ zur Verfügung gestellte, Methoden aus QML aufzurufen, sodass Anwendungen mit QML meistens aus zwei Teilen bestehen, dem GUI und der eigentlichen Funktionalität der Anwendung, da C++ deutlich effizienter ist als Javascript. Zwischen QML und C++, wie auch zwischen einzelnen Elementen in QML, erfolgt die Kommunikation meist per Signal-Slot-Prinzip. Die Events werden bei QML-Oberflächen zwar auch generiert, aber von der QML-Engine ausgewertet, sodass in QML keine Events ankommen. \newpage \subsubsection{QtAV}\label{subsubsec:qtav} QtAV ist ein Plugin für Qt, das Funktionen wie A/V-Wiedergabe/-Transkodierung hinzufügt. Es gibt zwar ein Qt Multimedia Modul von The Qt Company, welches auf den GStreamer Bibliotheken basiert, aber nur die A/V-Wiedergabe und nicht Transkodieren oder Hardwarebeschleunigung unterstützt. Außerdem hat das QtAV-Plugin viel mehr Optionen als das Multimedia Modul, z.B. fehlt im Multimedia Modul die Möglichkeit, festzulegen, auf welche Art man das Video anzeigen möchte, ob in einem separaten Fenster oder so, dass es sich in die bestehende Oberfläche integriert. \subsection{Entwicklungsverlauf}\label{subsec:entwicklungsverlauf} \includegraphics[width=\textwidth]{Progress.pdf} \subsubsection{Phase 1: Anforderungen festlegen}\label{subsubsec:phase-1:-anforderungen-festlegen} Zunächst müssen die Anforderungen an die Anwendung festgelegt werden, d.h. es wird festgelegt, was der Benutzer mit der Anwendung machen können soll. Dazu legt man sogenannte User Stories an, die beschreiben, was der Nutzer tun möchte. Die User Stories entsprechen hier den in der Abbildung erwähnten Meilensteinen. \paragraph{User Stories} \begin{enumerate} \item {Geräte im Netzwerk auflisten lassen} \item {Ein Gerät auswählen} \item {Datei als Quelle auswählen} \item {Ein Profil auswählen} \item {Stream starten} \item {Stream beenden} \item {Stream kontrollieren (Play/Pause, Vor-/Zurückspulen)} \item {Profile auf Kompatibilität testen lassen} \item {Desktop als Quelle auswählen} \end{enumerate} \subsubsection{Phase 2: Entwicklung}\label{subsubsec:phase-2:-entwicklung} Bei der Entwicklung arbeite ich die Meilensteine der Reihenfolge ab, da Meilensteine immer auf den vorhergehenden basieren. Wenn sich die Anforderungen ändern, z.B. die Möglichkeit den Desktop zu übertragen, werden diese abhängig von deren Voraussetzungen in die Liste Meilensteine eingereiht. Sollte die Anforderung neu sein, dann wird sie an die Liste der Meilensteine angehängt, sollte sich jedoch nur ein bestehender Meilenstein geändert haben, wird dieser zunächst bearbeitet, da es sein kann, dass dadurch die Implementationen der nachfolgenden Meilensteine geändert werden müssen. \subsubsection{Phase 3: Optimierungen und Tests}\label{subsubsec:phase-3:-optimierungen-und-tests} In dieser Phase ist geplant, die aktuell leistungsaufwändige Transkodierung effizienter zu machen und andere ineffiziente Anwendungsteile durch Tests ausfindig zu machen und zu beheben. Außerdem werden sowohl die gesamte Anwendung als auch die einzelnen Komponenten separat getestet, um Bugs zu finden und zu beheben. Das heißt zum einen, dass ich die gesamte Anwendung, in allen Varianten und Fehlermöglichkeiten testen werden, z.B. dass man während des Streams ein Seite per Taskmanager abbricht. Außerdem werden die einzelnen Komponenten durch Unit-Tests geprüft. Ein Unit-Test ist eine Sammlung von Methoden, die alle eine Komponente der Anwendung, aber verschiedene Szenarien, prüfen. Man muss so lange Fehler suchen und beheben, bis alle Tests erfolgreich durchlaufen werden. \subsubsection {Veröffentlichung}\label{subsubsec:veröffentlichung} Zunächst muss ich mich über die verschiedenen Open-Source Lizenzen informieren und eine auswählen. Danach werde ich das Projekt vermutlich auf GitHub veröffentlichen, sodass jeder Zugriff darauf hat und es benutzen kann. Da GitHub auch Features wie Issues bietet, können anderen Fehler oder auch Verbesserungsvorschläge dort einreichen, damit ich diese bearbeiten und gegebenenfalls Rückfragen stellen kann. Außerdem können dann Schulen VanadiumCast nutzen, sobald die Desktop-Übertragung implementiert ist, um den Schülerinnen, Schülern und Lehrkräften eine komfortable Möglichkeit zu bieten, im Unterricht den eigenen Bildschirm zu teilen. \section{Architektur}\label{sec:architektur} \subsection{Komponenten}\label{subsec:komponenten} \includegraphics[width=\textwidth]{Components.transparent.png} \subsubsection{GUI (QML)}\label{subsubsec:gui-(qml)} Die Oberfläche der Anwendung ist in QML geschrieben \end{document}