92 lines
4.1 KiB
Markdown
92 lines
4.1 KiB
Markdown
# Screen Cast – Bildschirm auf jeden Smart TV
|
||
|
||
Für Android-Geräte, denen der Hersteller kein Screen Mirroring spendiert hat.
|
||
Die App nimmt den Bildschirm auf, encodiert ihn hardwarebeschleunigt in H.264
|
||
und streamt ihn ins WLAN. Am Fernseher wird nur der Browser gebraucht.
|
||
|
||
## Zwei Wege zum Fernseher
|
||
|
||
### 1. Fernseher wartet schon auf eine Verbindung
|
||
|
||
Für Geräte im Screen-Mirroring-Modus – etwa Hotelfernseher, an denen sich
|
||
nichts eintippen lässt. In der App auf **Zum Fernseher verbinden** tippen; die
|
||
Liste zeigt, was gefunden wurde:
|
||
|
||
* **Über den Übertragungsdienst von Android** – vielen Handys fehlt nur die
|
||
Bedienkachel („Smart View“), nicht die Technik. Steht der Fernseher hier,
|
||
übernimmt Android die Übertragung selbst, in voller Qualität. Das ist der
|
||
beste Fall.
|
||
* **Direktverbindung über Wi-Fi Direct** – die App baut die Verbindung selbst
|
||
auf und schickt das Bild im Miracast-Format hinüber. Läuft komplett am WLAN
|
||
vorbei, also auch in Gästenetzen, die Geräte voneinander abschotten.
|
||
|
||
Darunter liegt ein Protokoll, das jeden Schritt mitschreibt – falls ein
|
||
bestimmter Fernseher zickt, steht dort, an welcher Stelle.
|
||
|
||
### 2. Fernseher mit Browser
|
||
|
||
|
||
|
||
1. App öffnen, **Übertragung starten**, Systemabfrage bestätigen
|
||
2. Am Fernseher den Browser öffnen
|
||
3. Die angezeigte Adresse eintippen, z. B. `http://192.168.1.42:8080`
|
||
4. Das Bild läuft im Vollbild. `F` (oder die farbige Taste der Fernbedienung,
|
||
die als F wirkt) schaltet zwischen *ganzes Bild* und *randlos füllend* um.
|
||
|
||
Handy und Fernseher müssen im selben WLAN sein. Die App darf in den
|
||
Hintergrund – die Übertragung läuft als Vordergrunddienst weiter und lässt sich
|
||
über die Benachrichtigung beenden.
|
||
|
||
## Zweiter Ausgang für Player
|
||
|
||
`http://<adresse>:8080/stream.ts` liefert denselben Stream als MPEG-TS – für
|
||
VLC, mpv oder Kodi („Netzwerkstream öffnen“), falls der Fernseher-Browser
|
||
streikt oder ein Laptop am Beamer hängt.
|
||
|
||
## Was beim Direktweg möglich ist – und was nicht
|
||
|
||
Der Miracast-Handshake (M1–M7 nach Wi-Fi-Display-Standard) und der RTP-Versand
|
||
sind vollständig umgesetzt und gegen einen nachgebauten Fernseher getestet.
|
||
|
||
Die Steuerverbindung baut **der Fernseher zu uns** auf, nicht umgekehrt – so
|
||
sieht es der Standard vor, und so macht es Android intern auch
|
||
(`RemoteDisplay.listen`). Die App hört deshalb auf Port 7236 und 8554 zu,
|
||
sobald die Bildschirmfreigabe erteilt ist, und zwar *bevor* die
|
||
Wi-Fi-Direct-Verbindung aufgebaut wird – der Fernseher meldet sich nämlich
|
||
sofort, wenn die Gruppe steht. Zusätzlich wird die Gegenrichtung versucht,
|
||
falls ein Gerät es andersherum erwartet.
|
||
Eine Einschränkung bleibt: Sich per `setWfdInfo` als Wi-Fi-Display-Quelle
|
||
anzukündigen, verlangt `CONFIGURE_WIFI_DISPLAY` – eine Signaturberechtigung,
|
||
die nur Systemapps bekommen. Die App verbindet sich deshalb als gewöhnliches
|
||
Wi-Fi-Direct-Gerät. Fernseher, die auf dieses Kennzeichen bestehen, lehnen
|
||
dann ab; tolerante Geräte nehmen die Verbindung an.
|
||
|
||
Deshalb steht der Weg über den systemeigenen Übertragungsdienst in der Liste
|
||
oben: Er nutzt genau den Stack, den auch die Cast-Kachel des Systems benutzt,
|
||
und hat keine solche Hürde.
|
||
|
||
## Technik
|
||
|
||
| Baustein | Aufgabe |
|
||
|---|---|
|
||
| `ScreenEncoder` | MediaProjection → MediaCodec H.264, auf niedrige Latenz getrimmt |
|
||
| `Fmp4Muxer` | baut fragmentiertes MP4, das Browser über Media Source Extensions direkt abspielen |
|
||
| `TsMuxer` | MPEG-TS für VLC/Kodi/mpv |
|
||
| `WebServer` | HTTP + WebSocket, ohne Fremdbibliothek |
|
||
| `StreamHub` | verteilt an alle Zuschauer, wirft bei langsamen Geräten Rückstand weg statt zu stauen |
|
||
|
||
Ein Fragment pro Bild, Keyframe auf Anforderung bei jedem neuen Zuschauer,
|
||
Puffer im Player wird aktiv kleingehalten – dadurch liegt die Verzögerung im
|
||
WLAN typischerweise bei einer knappen halben Sekunde.
|
||
|
||
## Bauen
|
||
|
||
```bash
|
||
gradle assembleRelease # Gradle 8.9, JDK 17+, Android SDK 35
|
||
gradle testDebugUnitTest -DsampleH264=<datei.h264> -DmuxOutDir=<ordner>
|
||
```
|
||
|
||
Die Tests schleusen einen echten H.264-Bitstream durch beide Muxer und holen
|
||
ihn über echte Sockets wieder ab; das Ergebnis lässt sich anschließend mit
|
||
`ffprobe` prüfen.
|