1
0
mirror of git://f0xx.org/android_cast synced 2026-07-29 03:38:52 +03:00
Files
android_cast/README.md
Anton Afanasyeu 097c83dc69 initial
2026-05-15 16:49:02 +02:00

87 lines
3.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Android Cast (POC)
Minimal LAN screen-casting proof of concept in **Java**. Captures screen + playback audio, encodes **H.264 + AAC**, streams over **TCP or UDP** to a receiver that decodes and plays back.
## Features
- UDP broadcast discovery on the local network
- TCP or UDP stream transport (selectable; must match on both devices)
- PIN auth (SHA-256 hash, default `1234`)
- Screen capture → H.264 (AVC) with quality presets and scaled capture resolution
- Playback audio capture (API 29+) → AAC-LC
- Runtime notification permission (Android 13+)
## Quick start
1. Install the same APK on two devices on the **same WiFi**.
2. **Receiver** (TV): **Receive** → match transport (TCP/UDP) & options → tap **Start listening** (notification appears; service keeps running).
3. **Sender** (tablet): **Send****same transport** → pick receiver → PIN → approve screen capture.
4. Watch the **notification** on both devices for connection status (not only the toast).
5. Stop from the notification **Stop** action.
### If video never appears
- Transport must match on both sides (e.g. both TCP).
- Receiver must show *Listening* or *Ready* in the notification before you cast.
- Sender notification should reach *Casting via TCP · WxH* — if it shows *Screen capture data missing*, reinstall and try again (Android 13+ intent fix).
- Keep the receiver UI open once so the video `Surface` attaches (or return to it after rotation).
## Build
Use **JDK 17 or 21** (Gradle does not run on JDK 25 yet):
```bash
export JAVA_HOME=/usr/lib/jvm/openjdk-bin-21
cd "/home/foxx/repos/My Projects/android cast"
./gradlew assembleDebug
adb install -r app/build/outputs/apk/debug/app-debug.apk
```
## Stream options
| Option | Effect |
|--------|--------|
| **Transport TCP** | Reliable delivery; default |
| **Transport UDP** | Lower latency, may drop frames (POC) |
| **Quality Low/Med/High** | Video bitrate 0.8 / 2 / 4 Mbps and FPS 20 / 24 / 30 |
| **Resolution** | Scales VirtualDisplay before encode (full, 75%, 50%, or max 720p height) |
| **Audio** | `AudioPlaybackCapture` + AAC (Android 10+) |
## Protocol
| Step | Description |
|------|-------------|
| Discovery | UDP `41234`, JSON with `magic`, `name`, `port`, `transport` |
| Connect | TCP or UDP port `41235` |
| Auth | `HELLO``AUTH``AUTH_OK``CAST_SETTINGS` |
| Stream | `STREAM_CONFIG`, `VIDEO_FRAME`, `AUDIO_CONFIG`, `AUDIO_FRAME` |
UDP frames use `ACUD` header and fragmentation for payloads > ~1.2 KB.
## Bluetooth / BLE
**Not viable for this video stream.** Practical throughput:
- **BLE**: ~100300 kb/s — fine for control/metadata only
- **Bluetooth Classic (SPP)**: often ~13 Mb/s theoretical — still far below 720p H.264 (~28 Mb/s), with high latency
A phone cannot “passthrough” a live encoded screen stream over BLE to another device for playback without a custom high-bandwidth profile (which consumer Android does not expose for arbitrary apps). Use **WiFi** for media; BT could be added later only for discovery/pairing if needed.
## Persistent services (AIDL)
Casting runs in **foreground services** with tray notifications:
| Service | Role |
|---------|------|
| `ScreenCastService` | Sender — capture, encode, stream |
| `ReceiverCastService` | Receiver — listen, decode, play |
Activities bind via AIDL (`ICastSenderService` / `ICastReceiverService`) for status updates and (on the receiver) attaching the video `Surface`. Rotating the screen or leaving the app does **not** stop the receiver listener; the sender keeps casting until you tap **Stop** in the notification.
## Limitations
- No TLS encryption (LAN cleartext POC)
- UDP mode may glitch under load
- Audio captures **playback** routed through the system (not microphone); some apps may be silent by policy
- Single sender → single receiver