|
| 1 | +# C5 4K Latency + Aurora v1.1.4 Implementation Plan |
| 2 | + |
| 3 | +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. |
| 4 | +
|
| 5 | +**Goal:** Ship Aurora 1.1.4 with community PRs #41–#50, contributor credits, and Phase A Starfish instrumentation (`pauseAtDecodeTime` toggle + render-queue `RQ` overlay) for the C5 4K growing-delay bug. |
| 6 | + |
| 7 | +**Architecture:** Integration branch `release/v1.1.4` merges PRs in order, then wires a separate settings/env flag into SMP `MakeLoadPayload`, ports `getVideoRenderQueueLength` through the weak-symbol wrapper into SS4S + overlay. Publish only after Build (webOS) is green; Release workflow attaches IPK on tag publish. |
| 8 | + |
| 9 | +**Tech Stack:** C/CMake, ss4s SMP/Starfish (submodule fork), LVGL UI, GitHub Actions (`build-webos.yml`, `release.yml`). |
| 10 | + |
| 11 | +## Global Constraints |
| 12 | + |
| 13 | +- Version string: `1.1.4` in `CMakeLists.txt` (`MOONLIGHT_VERSION`). |
| 14 | +- Do not change default Smooth PTS behavior (`smooth_frame_pacing` stays independent). |
| 15 | +- `pause_at_decode_time` default **true**. |
| 16 | +- No NDL flush+IDR watchdog reintroduction. |
| 17 | +- No commit of unrelated dirty `third_party/Unity` / `third_party/lvgl` working-tree noise. |
| 18 | +- Release notes and PR/merge messages for the release: **English**. |
| 19 | +- Credits: [@KrisEnigma](https://github.com/KrisEnigma) (#41–#49), [@danbrun](https://github.com/danbrun) (#50). |
| 20 | +- Spec: `docs/superpowers/specs/2026-07-19-c5-4k-latency-and-v1.1.4-design.md`. |
| 21 | + |
| 22 | +--- |
| 23 | + |
| 24 | +### Task 1: Create release branch and merge PRs #41–#50 |
| 25 | + |
| 26 | +**Files:** |
| 27 | +- Modify: git history on `release/v1.1.4` only |
| 28 | + |
| 29 | +**Interfaces:** |
| 30 | +- Consumes: open PRs against `main` (#41–#50), all MERGEABLE |
| 31 | +- Produces: branch containing all PR commits in order 41→50 |
| 32 | + |
| 33 | +- [ ] **Step 1: Ensure clean base and create branch** |
| 34 | + |
| 35 | +```powershell |
| 36 | +# From repo root; leave Unity/lvgl dirty paths unstaged |
| 37 | +git fetch origin |
| 38 | +git checkout main |
| 39 | +git pull origin main |
| 40 | +git checkout -b release/v1.1.4 |
| 41 | +``` |
| 42 | + |
| 43 | +- [ ] **Step 2: Merge each PR head in order** |
| 44 | + |
| 45 | +```powershell |
| 46 | +$cred = (echo "protocol=https`nhost=github.com`n" | git credential fill 2>$null) |
| 47 | +$env:GH_TOKEN = ($cred | Where-Object { $_ -match '^password=' }) -replace '^password=','' |
| 48 | +
|
| 49 | +foreach ($n in 41..50) { |
| 50 | + gh pr checkout $n --repo GuiDev1994/aurora-tv |
| 51 | + git checkout release/v1.1.4 |
| 52 | + $head = gh pr view $n --repo GuiDev1994/aurora-tv --json headRefOid -q .headRefOid |
| 53 | + git merge --no-ff $head -m "Merge PR #$n into release/v1.1.4" |
| 54 | +} |
| 55 | +``` |
| 56 | + |
| 57 | +If a merge conflicts, resolve preserving both intents; prefer newer cover-art/UI changes from higher PR numbers when overlapping. |
| 58 | + |
| 59 | +- [ ] **Step 3: Verify log contains all PR authors** |
| 60 | + |
| 61 | +```powershell |
| 62 | +git log main..HEAD --oneline |
| 63 | +``` |
| 64 | + |
| 65 | +Expected: commits from KrisEnigma PRs and danbrun surround fix present. |
| 66 | + |
| 67 | +- [ ] **Step 4: Commit only if conflict resolutions needed** (otherwise merges already committed) |
| 68 | + |
| 69 | +--- |
| 70 | + |
| 71 | +### Task 2: Version bump + Contributors README |
| 72 | + |
| 73 | +**Files:** |
| 74 | +- Modify: `CMakeLists.txt` (line with `MOONLIGHT_VERSION`) |
| 75 | +- Modify: `README.md` (after Credits or new Contributors section) |
| 76 | + |
| 77 | +- [ ] **Step 1: Bump version** |
| 78 | + |
| 79 | +In `CMakeLists.txt` set: |
| 80 | + |
| 81 | +```cmake |
| 82 | +set(MOONLIGHT_VERSION "1.1.4") |
| 83 | +``` |
| 84 | + |
| 85 | +- [ ] **Step 2: Add Contributors section to README.md** |
| 86 | + |
| 87 | +Insert before `## License`: |
| 88 | + |
| 89 | +```markdown |
| 90 | +## Contributors |
| 91 | + |
| 92 | +Thanks to everyone helping improve Aurora: |
| 93 | + |
| 94 | +- [KrisEnigma](https://github.com/KrisEnigma) — UI polish and launcher fixes ([#41](https://github.com/GuiDev1994/aurora-tv/pull/41)–[#49](https://github.com/GuiDev1994/aurora-tv/pull/49)) |
| 95 | +- [danbrun](https://github.com/danbrun) — 5.1 surround channel mapping ([#50](https://github.com/GuiDev1994/aurora-tv/pull/50)) |
| 96 | +``` |
| 97 | + |
| 98 | +Keep existing `## Credits` for upstream project attribution. |
| 99 | + |
| 100 | +- [ ] **Step 3: Commit** |
| 101 | + |
| 102 | +```powershell |
| 103 | +git add CMakeLists.txt README.md |
| 104 | +git commit -m "chore: bump version to 1.1.4 and credit contributors" |
| 105 | +``` |
| 106 | + |
| 107 | +--- |
| 108 | + |
| 109 | +### Task 3: Wire `pause_at_decode_time` setting → SMP Load payload |
| 110 | + |
| 111 | +**Files:** |
| 112 | +- Modify: `src/app/app_settings.h` |
| 113 | +- Modify: `src/app/app_settings.c` |
| 114 | +- Modify: `src/app/ui/settings/panes/video.pane.c` |
| 115 | +- Modify: `src/app/stream/session_worker.c` |
| 116 | +- Modify: `third_party/ss4s/modules/webos/smp/src/smp_player.c` (`MakeLoadPayload`) |
| 117 | +- Modify: `tests/app/test_settings.c` (default/load/save if other bools are covered) |
| 118 | + |
| 119 | +**Interfaces:** |
| 120 | +- Consumes: existing `setenv` pattern in `session_apply_smooth_pacing_env` |
| 121 | +- Produces: env `SS4S_PAUSE_AT_DECODE_TIME` (`1`/`0`); SMP reads it in `MakeLoadPayload` |
| 122 | + |
| 123 | +- [ ] **Step 1: Add field next to `smooth_frame_pacing` in `app_settings.h`** |
| 124 | + |
| 125 | +```c |
| 126 | +/** |
| 127 | + * webOS SMP/Starfish: pass pauseAtDecodeTime in Load payload (default true). |
| 128 | + * Independent of smooth_frame_pacing (PTS grid). Set false only for latency experiments. |
| 129 | + */ |
| 130 | +bool pause_at_decode_time; |
| 131 | +``` |
| 132 | + |
| 133 | +- [ ] **Step 2: Default true; ini read/write `pause_at_decode_time`** in `app_settings.c` mirroring `smooth_frame_pacing`. |
| 134 | + |
| 135 | +- [ ] **Step 3: Checkbox in `video.pane.c`** (webOS only if smooth pacing is gated the same way): |
| 136 | + |
| 137 | +```c |
| 138 | +pref_checkbox(view, locstr("Pause at decode time (Starfish)"), &app_configuration->pause_at_decode_time, false); |
| 139 | +``` |
| 140 | +
|
| 141 | +- [ ] **Step 4: Env in `session_worker.c`** |
| 142 | +
|
| 143 | +```c |
| 144 | +static void session_apply_starfish_load_env(void) { |
| 145 | +#if TARGET_WEBOS |
| 146 | + const app_settings_t *cfg = app_configuration; |
| 147 | + bool pause = cfg == NULL || cfg->pause_at_decode_time; |
| 148 | + setenv("SS4S_PAUSE_AT_DECODE_TIME", pause ? "1" : "0", 1); |
| 149 | +#endif |
| 150 | +} |
| 151 | +``` |
| 152 | + |
| 153 | +Call before `SS4S_PlayerOpen` / with smooth pacing apply. |
| 154 | + |
| 155 | +- [ ] **Step 5: SMP `MakeLoadPayload`** |
| 156 | + |
| 157 | +```c |
| 158 | +static bool PauseAtDecodeTimeEnvEnabled(void) { |
| 159 | + const char *env = getenv("SS4S_PAUSE_AT_DECODE_TIME"); |
| 160 | + if (env == NULL || env[0] == '\0') { |
| 161 | + return true; |
| 162 | + } |
| 163 | + if (env[0] == '0' || strcmp(env, "false") == 0 || strcmp(env, "off") == 0) { |
| 164 | + return false; |
| 165 | + } |
| 166 | + return true; |
| 167 | +} |
| 168 | + |
| 169 | +/* in esInfo object: */ |
| 170 | +jkeyval(J_CSTR_TO_JVAL("pauseAtDecodeTime"), jboolean_create(PauseAtDecodeTimeEnvEnabled())), |
| 171 | +``` |
| 172 | +
|
| 173 | +Log once at load: `SMP: pauseAtDecodeTime=%s`. |
| 174 | +
|
| 175 | +- [ ] **Step 6: Extend `tests/app/test_settings.c` for default true + round-trip.** |
| 176 | +
|
| 177 | +- [ ] **Step 7: Commit app + note ss4s dirty; ss4s commit on fork in Task 4** |
| 178 | +
|
| 179 | +```powershell |
| 180 | +git add src/app/app_settings.h src/app/app_settings.c src/app/ui/settings/panes/video.pane.c src/app/stream/session_worker.c tests/app/test_settings.c |
| 181 | +git commit -m "feat: expose Starfish pauseAtDecodeTime as a settings toggle" |
| 182 | +``` |
| 183 | + |
| 184 | +--- |
| 185 | + |
| 186 | +### Task 4: Port `getVideoRenderQueueLength` + SS4S API + overlay `RQ` |
| 187 | + |
| 188 | +**Files:** |
| 189 | +- Modify: `third_party/ss4s/modules/webos/smp/wrapper/StarfishMediaAPIs_C.h` |
| 190 | +- Modify: `third_party/ss4s/modules/webos/smp/wrapper/StarfishMediaAPIs_C.cpp` |
| 191 | +- Modify: `third_party/ss4s/modules/webos/smp/src/smp_video.c` (or player get-latency path) |
| 192 | +- Modify: `third_party/ss4s/modules/interface/include/ss4s/modapi.h` |
| 193 | +- Modify: `third_party/ss4s/include/ss4s.h` (or public header where `SS4S_PlayerGetVideoLatency` is declared) |
| 194 | +- Modify: `third_party/ss4s/src/player.c` / `src/video.c` as needed for public API |
| 195 | +- Modify: `src/app/stream/video/session_video.c` / `session.h` stats fields |
| 196 | +- Modify: `src/app/ui/streaming/streaming.controller.c` overlay formatting |
| 197 | + |
| 198 | +**Interfaces:** |
| 199 | +- Produces: `bool SS4S_PlayerGetVideoRenderQueueLength(SS4S_Player *player, int *length);` |
| 200 | +- Overlay shows `RQ %d` or `RQ -` |
| 201 | + |
| 202 | +- [ ] **Step 1: Wrapper (weak symbol)** in `StarfishMediaAPIs_C.cpp`: |
| 203 | + |
| 204 | +```cpp |
| 205 | +extern "C" bool |
| 206 | +_ZN17StarfishMediaAPIs26getVideoRenderQueueLengthERi(StarfishMediaAPIs *api, int *length) __attribute__((weak)); |
| 207 | + |
| 208 | +bool StarfishMediaAPIs_getVideoRenderQueueLength(StarfishMediaAPIs_C *api, int *length) { |
| 209 | + if (_ZN17StarfishMediaAPIs26getVideoRenderQueueLengthERi == nullptr || length == nullptr) { |
| 210 | + return false; |
| 211 | + } |
| 212 | + return _ZN17StarfishMediaAPIs26getVideoRenderQueueLengthERi(&api->inner, length); |
| 213 | +} |
| 214 | +``` |
| 215 | +
|
| 216 | +Declare in `StarfishMediaAPIs_C.h`. |
| 217 | +
|
| 218 | +- [ ] **Step 2: Module optional op** — add `GetVideoRenderQueueLength` to video driver ops (nullable). SMP implements via wrapper; others leave NULL. |
| 219 | +
|
| 220 | +- [ ] **Step 3: Public API** mirroring `SS4S_PlayerGetVideoLatency`: |
| 221 | +
|
| 222 | +```c |
| 223 | +bool SS4S_PlayerGetVideoRenderQueueLength(SS4S_Player *player, int *length); |
| 224 | +``` |
| 225 | + |
| 226 | +- [ ] **Step 4: Session stats** — sample each frame or with latency sample; store `int video_render_queue = -1` when unavailable. |
| 227 | + |
| 228 | +- [ ] **Step 5: Overlay** — append `RQ %d` or `RQ -` next to decode stats in compact + full panel. |
| 229 | + |
| 230 | +- [ ] **Step 6: Commit ss4s on fork branch, bump submodule pin, commit app** |
| 231 | + |
| 232 | +```powershell |
| 233 | +# in third_party/ss4s |
| 234 | +git checkout -B aurora-v1.1.4 |
| 235 | +git add -A |
| 236 | +git commit -m "feat(webos): pauseAtDecodeTime env and getVideoRenderQueueLength" |
| 237 | +git push -u aurora HEAD |
| 238 | +
|
| 239 | +# parent repo |
| 240 | +git add third_party/ss4s src/app/stream src/app/ui/streaming |
| 241 | +git commit -m "feat: show Starfish render queue depth (RQ) in stats overlay" |
| 242 | +``` |
| 243 | + |
| 244 | +--- |
| 245 | + |
| 246 | +### Task 5: Push branch, wait for Build (webOS), merge + release |
| 247 | + |
| 248 | +**Files:** |
| 249 | +- GitHub: branch, PRs, release |
| 250 | + |
| 251 | +- [ ] **Step 1: Push release branch** |
| 252 | + |
| 253 | +```powershell |
| 254 | +git push -u origin release/v1.1.4 |
| 255 | +``` |
| 256 | + |
| 257 | +- [ ] **Step 2: Watch CI** |
| 258 | + |
| 259 | +```powershell |
| 260 | +gh run watch --repo GuiDev1994/aurora-tv $(gh run list --repo GuiDev1994/aurora-tv --branch release/v1.1.4 --workflow "Build (webOS)" --limit 1 --json databaseId -q .[0].databaseId) |
| 261 | +``` |
| 262 | + |
| 263 | +Expected: success. If fail, fix and re-push; do not merge/release. |
| 264 | + |
| 265 | +- [ ] **Step 3: Open PR release → main (English body with credits), merge when green** |
| 266 | + |
| 267 | +```powershell |
| 268 | +gh pr create --repo GuiDev1994/aurora-tv --base main --head release/v1.1.4 --title "Release v1.1.4" --body "..." |
| 269 | +gh pr merge --merge |
| 270 | +``` |
| 271 | + |
| 272 | +Also merge/close community PRs #41–#50 if still open (or they close as superseded once commits are on main — prefer merging each PR if GitHub still shows them open after cherry-picks, or close with comment pointing at release PR). |
| 273 | + |
| 274 | +- [ ] **Step 4: Publish GitHub Release `v1.1.4` (English)** |
| 275 | + |
| 276 | +```powershell |
| 277 | +gh release create v1.1.4 --repo GuiDev1994/aurora-tv --title "Aurora v1.1.4" --notes-file release-notes-v1.1.4.md |
| 278 | +``` |
| 279 | + |
| 280 | +Notes must credit KrisEnigma and danbrun and list Phase A instrumentation. Publishing triggers `.github/workflows/release.yml`. |
| 281 | + |
| 282 | +- [ ] **Step 5: Confirm Release Action success and artifacts attached** |
| 283 | + |
| 284 | +```powershell |
| 285 | +gh run list --repo GuiDev1994/aurora-tv --workflow Release --limit 1 |
| 286 | +``` |
| 287 | + |
| 288 | +--- |
| 289 | + |
| 290 | +## Out of scope for this plan (Phase B) |
| 291 | + |
| 292 | +Soft ABR/throttle recovery when `RQ` grows — implement only after C5 device confirms `RQ` tracks the growing delay. |
0 commit comments