Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
\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}