Repository navigation
quest: plan the 14 open issues without a quest #4388
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
94138cd
ce11215
6cab8d6
f27643f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| # [XS] Packaged relay starts | ||
|
|
||
| ## Goal | ||
|
|
||
| The `.deb` and `.rpm` relay service starts. Today | ||
| `packaging/moq-relay/moq-relay.service` runs `moq-relay --file | ||
| /etc/moq-relay/relay.toml`, but the config path is positional and the relay | ||
| rejects unknown flags, so every packaged install crash-loops. | ||
|
|
||
| ## Plan | ||
|
|
||
| `ExecStart=/usr/bin/moq-relay /etc/moq-relay/relay.toml`. Add the reporter's | ||
| unit test in the relay crate that parses the unit's `ExecStart` with the | ||
| relay's own `Cli`, so the unit and the parser can't drift again. | ||
|
|
||
| ## Closes | ||
|
|
||
| - [#4343](https://github.com/moq-dev/moq/issues/4343) - close this issue when the quest finishes |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| # [L] Cross-relay delivery under bursts | ||
|
|
||
| ## Goal | ||
|
|
||
| Bursty small-group tracks cross two relays without losing groups or stalling. | ||
| On cdn.moq.pro, publishers and a subscriber on different nodes saw groups | ||
| never arrive (FETCH for them unanswered for 2 s while the publisher stayed | ||
| connected), a subscription opened early deliver only a burst's tail, and | ||
| return tracks stall up to 31 s with `Stream(Old)`. The same workload on one | ||
| node, or one self-hosted relay, loses nothing. | ||
|
|
||
| ## Plan | ||
|
|
||
| Reproduce first, on a local two-relay cluster with the reporter's harness | ||
| (offered in the issue) and the relay build cdn.moq.pro ran. Then fix what the | ||
| repro shows. Suspects: `Old` expiry or newest-first dropping on the relay hop, | ||
| and FETCH not forwarded or answered upstream. Re-measure the stalls after | ||
| [FIN wait expiry](/quest/m1/fin-wait-expiry.md), a candidate cause. Keep the | ||
| repro as a regression test in the cluster tests. | ||
|
|
||
| The issue's stale and flapping announcements after a clean close are | ||
| cluster-routing evidence, not this quest's scope. | ||
|
|
||
| ## Required | ||
|
|
||
| - [FIN wait expiry](/quest/m1/fin-wait-expiry.md) - removes one candidate cause of the stalls before measuring | ||
|
|
||
| ## Closes | ||
|
|
||
| - [#4349](https://github.com/moq-dev/moq/issues/4349) - close this issue when the quest finishes | ||
|
|
||
| ## Related | ||
|
|
||
| - [Cluster routing](/quest/m1/cluster-routing.md) - owns the stale and flapping announcements from the same report | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| # [S] A group awaiting its FIN ack still expires | ||
|
|
||
| ## Goal | ||
|
|
||
| A group whose FIN is written but not yet acknowledged still expires with | ||
| `Old` and still follows priority updates, on lite and IETF. Today the | ||
| `Closed` arm only awaits `writer.poll_close`, so a stale group keeps its | ||
| queued bytes and its old send order, which can stall newer groups behind it. | ||
|
|
||
| ## Plan | ||
|
|
||
| The issue ships four failing tests, a `with_fin_gate` test hook, and a fix: | ||
|
|
||
| - lite: poll priority above the state match, not only in `Serve`. | ||
| - lite and IETF: in `Closed`, poll `poll_expired_while_pending` and abort with | ||
| `Old`. | ||
| - moq-tokio: `set_priority` in `Closing` fires the existing interrupt so the | ||
| new order applies, instead of only storing it. | ||
|
|
||
| Each priority update rebuilds the `closed()` watch; check the publisher | ||
| benchmarks for a regression. The flaky | ||
| `subscription_end_integrity::a_subscription_cut_by_the_publisher_disconnecting_does_not_end_clean` | ||
| the reporter hit is tracked in [More tests under load](/quest/m1/test-flakes-2.md). | ||
|
|
||
| ## Closes | ||
|
|
||
| - [#4332](https://github.com/moq-dev/moq/issues/4332) - close this issue when the quest finishes | ||
|
|
||
| ## Related | ||
|
|
||
| - [Starvation](/quest/m1/qos/starvation.md) - its frontier relies on FIN acks, which can now end in `Old` |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| # [L] Same-hop importers publish identical tracks | ||
|
|
||
| ## Goal | ||
|
|
||
| Two importers sharing a `--hop` and fed the same encoded stream publish | ||
| identical tracks, so a relay can fail over between them. Today two | ||
| `moq import ts` fed one forked stream break that contract twice: a standby | ||
| refuses every track until it has parsed its PMT, which aborts every | ||
| subscriber the moment it connects (#4352), and each numbers its groups from | ||
| its own counter, so after a failover `export ts` sees a timestamp rewind and | ||
| exits (#4354). | ||
|
|
||
| ## Plan | ||
|
|
||
| Decided: same-hop publishers MUST publish the same broadcasts and tracks. | ||
| Keep `--hop`, and make every container importer (ts, fmp4, flv, mkv, and the | ||
| SRT, RTMP, and HLS gateways that reuse them) meet the contract when fed one | ||
| encoded stream. Capture is out: two encoders never align. | ||
|
|
||
| - A group's sequence derives from its keyframe's media timestamp (PTS in TS), | ||
| not a per-process counter. Decide how both processes agree across a | ||
| timestamp wrap (TS PTS wraps every 26.5 h) when they started on opposite | ||
| sides of it. | ||
| - Frame timestamps derive from the input alone too: any re-anchor shift must | ||
| come from the stream, not process start or wall clock. | ||
| - An importer announces only once it knows its tracks, so it never refuses a | ||
| track the incumbent serves. | ||
| - Docs (`doc/bin/cli.md` "Redundant publishers", the `--hop` doc comment) | ||
| narrow the contract to one encoded stream fed to each publisher. | ||
|
|
||
| Tests: per importer, two instances started at different offsets into the same | ||
| input produce the same group sequences and timestamps. End to end: the | ||
| issues' 1+1 setup (one relay, two same-hop `import ts`, two `export ts`) | ||
| survives the standby joining and the incumbent stopping. | ||
|
|
||
| ## Closes | ||
|
|
||
| - [#4352](https://github.com/moq-dev/moq/issues/4352) - close this issue when the quest finishes | ||
| - [#4354](https://github.com/moq-dev/moq/issues/4354) - close this issue when the quest finishes | ||
|
|
||
| ## Related | ||
|
|
||
| - [Redundant ingest](/quest/m2/redundant-ingest.md) - splicing across first hops and two encoders, which this does not attempt | ||
| - [TS import shared shift](/quest/m1/ts-import-shared-shift.md) - the TS re-anchor shift that must stay input-derived | ||
| - [Broadcast epochs](/quest/m1/broadcast-epoch/README.md) - a redundant pair shares one epoch |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| # [S] moqsink drops frames on recoverable importer errors | ||
|
|
||
| ## Goal | ||
|
|
||
| A `moqsink` pad survives the importer errors moq-mux documents as | ||
| recoverable: it drops frames until the next keyframe instead of calling | ||
| `self.fail()` and losing the rendition for good. Two paths reach that | ||
| failure in `Media::write` (`rs/moq-gst/src/sink/pad.rs`) today: | ||
|
|
||
| - A new pad starts unlatched (`keyframe: false`), so a first buffer that is a | ||
| delta frame fails it. | ||
| - A `TimestampRewind` with no signalled break (an rtspsrc jitterbuffer | ||
| re-anchoring) has no guard at all. | ||
|
|
||
| ## Plan | ||
|
|
||
| The header-only buffer after a break was fixed in | ||
| https://github.com/moq-dev/moq/pull/4356: the latch stays armed after a | ||
| successful decode. Reuse that latch here. | ||
|
|
||
| Decided: a video pad starts latched. On `TimestampRewind`, set the latch and | ||
| drop until a keyframe lands above the producer's live edge, losing up to one | ||
| GOP per re-anchor. Mapping a rewound timeline forward instead belongs to | ||
| [#3021](/quest/m1/3021-moq-gst-anchor-generated-media-timelines-to-wall-clock.md). | ||
| The reporter offered the guard they run in production. | ||
|
|
||
| Regression tests beside `video_pause_drops_deltas_until_the_next_keyframe`: | ||
|
|
||
| - A new pad's first buffer is a delta: it drops. | ||
| - A rewind without a break: deltas drop until a keyframe above the edge. | ||
|
|
||
| ## Closes | ||
|
|
||
| - [#4366](https://github.com/moq-dev/moq/issues/4366) - close this issue when the quest finishes |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| # [L] moq import ts: select programs | ||
|
|
||
| ## Goal | ||
|
|
||
| A multi-program transport stream is never silently merged. Today `import ts` | ||
| keeps the first program's identity, adds every PMT's streams to one broadcast | ||
| on one clock, and loses content; `export ts` rebuilds one program. After | ||
| this quest `import ts` refuses a multi-program input by default, naming the | ||
| programs, and `--program` chooses what to import. | ||
|
|
||
| ## Plan | ||
|
|
||
| Decided: | ||
|
|
||
| - Default: error before publishing when the initial PAT lists more than one | ||
| non-zero program, naming each program and pointing at `--program`. A later | ||
| PAT that adds a program ends the import with the same error; media already | ||
| published stays. | ||
| - `--program <n>` imports program `n` only. | ||
| - `--program all` publishes one broadcast per program, each with its own clock | ||
| and catalog. The catalog suffix stays last so discovery and format detection | ||
| still see it: `--broadcast event.hang` publishes `event/1.hang` and | ||
| `event/2.hang`. | ||
| - `export ts` stays one program per broadcast. | ||
|
|
||
| Tests: a synthetic two-program input with far-apart clocks fails naming both | ||
| programs; `--program 2` publishes only program 2's streams on program 2's | ||
| clock; `--program all` publishes both broadcasts, each timed correctly. Update | ||
| `doc/bin/cli.md` and the `--help` text. | ||
|
|
||
| ## Closes | ||
|
|
||
| - [#4353](https://github.com/moq-dev/moq/issues/4353) - close this issue when the quest finishes | ||
|
|
||
| ## Related | ||
|
|
||
| - [TS import shared shift](/quest/m1/ts-import-shared-shift.md) - its per-program shift assumes the single program this settles |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| # [XS] Documented ffmpeg line flushes audio | ||
|
|
||
| ## Goal | ||
|
|
||
| The documented `ffmpeg ... -f mpegts -pes_payload_size 0 -` publish line stops | ||
| holding small audio frames in ffmpeg's muxer for up to 0.35 s. Those clumps | ||
| raise the importer's catalog `jitter` for the life of the track, and watch | ||
| adds about 230 ms of playout delay to match. | ||
|
|
||
| ## Plan | ||
|
|
||
| Decided: add `-muxdelay 0` everywhere the line appears | ||
| (`demo/pub/justfile`, `doc/bin/cli.md`, `doc/concept/standard.md`, | ||
| `rs/moq-cli/README.md`). `import ts` needs no PCR lead. The reporter's patch | ||
|
Comment on lines
+12
to
+14
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The claimed exhaustive list omits the live MPEG-TS publishing commands in AGENTS.md reference: AGENTS.md:L28-L28 Useful? React with 👍 / 👎. |
||
| is ready. Verify by re-measuring the catalog jitter on a quiet-audio source; | ||
| there is no automated test for a docs line. | ||
|
|
||
| The importer's jitter estimate keeping its maximum forever is a separate | ||
| problem; the player side is covered by the audio jitter target. | ||
|
|
||
| ## Closes | ||
|
|
||
| - [#4347](https://github.com/moq-dev/moq/issues/4347) - close this issue when the quest finishes | ||
|
|
||
| ## Related | ||
|
|
||
| - [Audio jitter target](/quest/m0/audio-jitter-target/README.md) - a decaying playout estimate softens a transient burst | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| # [M] Watch decoders recover from an error | ||
|
|
||
| ## Goal | ||
|
|
||
| One malformed packet no longer ends audio or video for the rest of a | ||
| subscription. Today a WebCodecs error closes the decoder, both audio loops | ||
| `break` (added in #2415 to stop an `InvalidStateError` loop), and video calls | ||
| `effect.close()`; nothing rebuilds the decoder, and playback silently stops. | ||
|
|
||
| ## Plan | ||
|
|
||
| Decided: rebuild inside the loop, for audio and video alike. On a decoder | ||
| error, rebuild through one shared `build()` helper, skip to the next keyframe, | ||
| and give up after three rebuilds in a row with no output. A rebuilt legacy | ||
|
Comment on lines
+12
to
+14
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Applying the keyframe wait to audio would introduce avoidable silence after a malformed packet. The audio codec importers intentionally mark only the first packet in each MoQ group as a keyframe for transport grouping, even though subsequent audio packets are independently decodable, so an error after that first packet could discard the remainder of a long or final group. Restrict the keyframe wait to video and test that audio resumes with the next valid packet. Useful? React with 👍 / 👎. |
||
| audio decoder re-runs its warmup priming. Cover the legacy and CMAF loops. | ||
|
|
||
| Tests: a corrupt packet mid-stream is followed by decoded output from the next | ||
| keyframe; a stream of only corrupt packets gives up after three rebuilds | ||
| instead of spinning. | ||
|
|
||
| ## Closes | ||
|
|
||
| - [#4324](https://github.com/moq-dev/moq/issues/4324) - close this issue when the quest finishes | ||
|
|
||
| ## Related | ||
|
|
||
| - [Audio warmup](/quest/m1/audio-warmup.md) - the same audio loops and priming | ||
| - [Watch video guards](/quest/m1/watch-video-guards.md) - keeps bad input from reaching the video codec | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The plan retains only a single local two-relay regression scenario, but this path fans out across publishers, routes, and subscribers, and the suspected fix is in relay-hop scheduling. A one-workload correctness test will not expose a table-wide cost that grows with cluster size, so include a benchmark swept over publisher and subscriber/route counts before closing this quest.
AGENTS.md reference: AGENTS.md:L36-L36
Useful? React with 👍 / 👎.