mirror of
git://f0xx.org/android_cast
synced 2026-07-29 07:39:15 +03:00
113 lines
4.3 KiB
Markdown
113 lines
4.3 KiB
Markdown
# Android Cast (POC)
|
||
|
||
**Roadmap & alpha:** [docs/ROADMAP.md](docs/ROADMAP.md) · **Alpha QA & feature freeze:** [docs/ALPHA.md](docs/ALPHA.md) · **Production infra (agents: read first):** [docs/INFRA.md](docs/INFRA.md) · USB-C/HDMI: [docs/USB_HDMI_CAST.md](docs/USB_HDMI_CAST.md) · Commercial (dev-gated): [docs/COMMERCIAL.md](docs/COMMERCIAL.md)
|
||
|
||
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
|
||
- **UDP (default)** or TCP 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
|
||
- Camera capture modes (API 29+, rear/front) — best-effort
|
||
- Runtime notification permission (Android 13+)
|
||
|
||
## Quick start (alpha)
|
||
|
||
1. Install the same APK on two devices on the **same Wi‑Fi**.
|
||
2. **Receiver:** **Receive** → transport **UDP** → stream protection **None** → **Start listening** (notification *Listening* / *Ready*).
|
||
3. **Sender:** **Send** → **UDP** → protection **None** → discover receiver → PIN → approve screen capture.
|
||
4. Watch **notifications** on both devices for status.
|
||
5. Stop from either notification **Stop** action.
|
||
|
||
Full sign-off checklist: [docs/ALPHA.md](docs/ALPHA.md).
|
||
|
||
### If video never appears
|
||
|
||
- Transport must match on both sides (e.g. both UDP).
|
||
- Stream protection **None** on both sides for alpha.
|
||
- Receiver must show *Listening* or *Ready* before you cast.
|
||
- Sender notification should reach *Casting* with resolution — if it shows *Screen capture data missing*, reinstall (Android 13+ intent fix).
|
||
- Open receiver playback once so the video `Surface` attaches (or return after rotation).
|
||
- On rotation-sensitive senders, try **system rotation lock** during cast.
|
||
|
||
## 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 (defaults)
|
||
|
||
| Option | Default / alpha note |
|
||
|--------|----------------------|
|
||
| **Transport** | **UDP** (`CastConfig.DEFAULT_TRANSPORT`) |
|
||
| **Stream protection** | **None** |
|
||
| **Quality** | Medium — 5 Mbps, 30 fps |
|
||
| **Resolution** | Adaptive (sender) |
|
||
| **Multi-receiver** | **Off** while `CastConfig.ALPHA_FEATURE_FREEZE` |
|
||
| **Audio** | On when API 29+ (`AudioPlaybackCapture` + AAC) |
|
||
|
||
| Quality | Video bitrate | FPS |
|
||
|---------|---------------|-----|
|
||
| Low | 1.5 Mbps | 24 |
|
||
| Medium | 5 Mbps | 30 |
|
||
| High | 10 Mbps | 30 |
|
||
|
||
## Protocol
|
||
|
||
| Step | Description |
|
||
|------|-------------|
|
||
| Discovery | UDP `41234`, JSON with `magic`, `name`, `port`, `transport` |
|
||
| Connect | TCP or UDP port `41235` (QUIC `41236` when enabled post-alpha) |
|
||
| 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.** Use **Wi‑Fi** for media; BLE could be added later only for discovery/pairing.
|
||
|
||
## 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 for status and (on the receiver) attaching the video `Surface`. Leaving the app does **not** stop the receiver listener; the sender keeps casting until **Stop** in the notification.
|
||
|
||
## Limitations
|
||
|
||
- No TLS encryption (LAN cleartext POC)
|
||
- UDP mode may glitch under load (try TCP)
|
||
- Audio captures **playback** routed through the system (not microphone)
|
||
- Single receiver per session during alpha freeze
|
||
- No live sender preview while casting (stability)
|
||
|
||
## Development (git flow)
|
||
|
||
Green **`master`** plus integration branch **`next`**. See [docs/GIT_FLOW.md](docs/GIT_FLOW.md).
|
||
|
||
## PDF helpers
|
||
|
||
Generate the GraphVis decision memo PDF (from `docs/GRAFANA_vs_others_graphvis_pivot.md` source):
|
||
|
||
```bash
|
||
bash scripts/build-graphvis-pdf.sh
|
||
```
|
||
|
||
Output:
|
||
|
||
`docs/GRAFANA_vs_others_graphvis_pivot.pdf`
|