mirror of
git://f0xx.org/android_cast
synced 2026-07-29 07:20:00 +03:00
101 lines
4.7 KiB
Markdown
101 lines
4.7 KiB
Markdown
# Android Cast (POC)
|
||
|
||
**Roadmap & alpha scope:** [docs/ROADMAP.md](docs/ROADMAP.md) · **LAN demo QA:** [docs/ALPHA_SOAK.md](docs/ALPHA_SOAK.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 **UDP or TCP** 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 (alpha demo)
|
||
|
||
1. Install the same APK on two devices on the **same Wi‑Fi**.
|
||
2. **Receiver:** **Receive** → transport **UDP** → stream protection **None** → **Start listening**.
|
||
3. **Sender:** **Send** → **UDP** → pick **one** receiver → PIN → approve screen capture.
|
||
4. Sender resolution: **Original**, **720p**, **480p**, or **Auto** (settings drawer).
|
||
5. Watch **notifications** on both devices for status (not only toasts).
|
||
6. Stop from the sender notification **Stop** action.
|
||
|
||
Full soak script: [docs/ALPHA_SOAK.md](docs/ALPHA_SOAK.md).
|
||
|
||
### 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 UDP** | Default; lower latency |
|
||
| **Transport TCP** | Reliable fallback |
|
||
| **Sender resolution** | **Original** (native), **720p** / **480p** (long-edge cap), **Auto** (adaptive from peer stats) |
|
||
| **Bitrate** | Estimated / quality / speed modes in settings |
|
||
| **Stream protection** | FEC/NACK optional on UDP — use **None** for alpha demo |
|
||
| **Audio** | `AudioPlaybackCapture` + AAC (Android 10+) |
|
||
| **Camera capture** | Rear/front Camera2 (Android 10+); requires camera permission |
|
||
|
||
## 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**: ~100–300 kb/s — fine for control/metadata only
|
||
- **Bluetooth Classic (SPP)**: often ~1–3 Mb/s theoretical — still far below 720p H.264 (~2–8 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 **Wi‑Fi** 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
|
||
|
||
## Development (git flow)
|
||
|
||
We use a **green `master`** plus integration branch **`next`**: features merge to `next` first; releases merge `next` → `master` and are tagged there; production hotfixes branch from `master` and sync back into `next`.
|
||
|
||
- Narrative: [docs/GIT_FLOW.md](docs/GIT_FLOW.md)
|
||
- PDF: [docs/GIT_FLOW.pdf](docs/GIT_FLOW.pdf) — `pip install -r docs/_pdf_build/requirements-pdf.txt`, then `python3 docs/_pdf_build/build_git_flow_pdf.py`
|