Skip to content

feat(moq-net)!: remove per-frame duration from Frame and the lite-05 wire#1753

Merged
kixelated merged 5 commits into
devfrom
claude/frosty-cerf-b14aa1
Jun 16, 2026
Merged

feat(moq-net)!: remove per-frame duration from Frame and the lite-05 wire#1753
kixelated merged 5 commits into
devfrom
claude/frosty-cerf-b14aa1

Conversation

@kixelated

@kixelated kixelated commented Jun 16, 2026

Copy link
Copy Markdown
Collaborator

Summary

Removes the duration field from moq_net::Frame and the matching slot from the moq-lite-05 wire format.

The field was effectively dead: the fMP4 importer was its only real producer, the JS subscriber decoded and discarded it, no relay or consumer ever read it, and hang's container always left it None. The only plausible future consumer (a media-agnostic relay reading frame spans off the wire) was never built, so this drops it rather than carrying unvalidated surface. The spec is being updated to match.

Changes

  • Wire (lite-05 FRAME): the per-frame timing prefix is now [zigzag-delta timestamp] instead of [zigzag-delta timestamp][zigzag-delta duration], in lockstep across Rust and JS.
    • rs/moq-net/src/lite/publisher.rs: dropped the duration encode and the prev_dur baseline threaded through encode_frame_timing / write_fetch_frame / serve_frame / serve_group / the fetch loop.
    • rs/moq-net/src/lite/subscriber.rs: decodes one varint per frame instead of two.
    • js/net/src/lite/subscriber.ts: reads/discards one varint instead of two. (The JS publisher always sends timescale: 0 and never encoded timing, so no publish-side change.)
  • Model: removed the duration field from Frame and the duration validation + its two dedicated tests from GroupProducer::append_frame.
  • Producers: updated the IETF subscriber, hang container frame.rs, and the fMP4 importer (which dropped the dts - base_media_decode_time span computation). The mux container's own Frame type (fMP4 sample durations) is a separate type and is untouched.
  • Tests: reworked the two native lite-05 round-trip tests to assert timestamps only, keeping the negative-delta (B-frame) coverage.

Public API / breaking changes

  • Breaking: moq_net::Frame::duration field removed.
  • Breaking: moq-lite-05 wire format changed (one fewer varint per timed frame). Both peers must upgrade together; lite-05 is still WIP.

Targets dev per the branch-targeting rules (wire-protocol + breaking API change).

Test plan

  • cargo check / cargo test on moq-net (378 pass), moq-mux, hang, moq-native
  • Native lite-05 wire round-trip tests pass (timestamps, fetch, fetch-during-subscribe, no-timescale)
  • cargo fmt + cargo clippy clean via nix

(Written by Claude)

…wire

The `duration` field on `moq_net::Frame` was write-mostly-None and read by
nobody: the fMP4 importer was its only real producer, the JS subscriber decoded
and discarded it, no relay or consumer ever read it, and hang's container always
left it `None`. Drop it everywhere along with the lite-05 wire slot.

The lite-05 FRAME timing prefix is now `[zigzag-delta timestamp]` instead of
`[zigzag-delta timestamp][zigzag-delta duration]`, in lockstep across Rust and
JS. Removed the duration encode/decode plumbing (`prev_dur` baselines), the model
field and its `append_frame` validation, the fMP4 importer's span computation, and
the now-unused duration assertions in the native round-trip tests.

BREAKING CHANGE: removes the `duration` field from `moq_net::Frame` and changes
the moq-lite-05 wire format. Targets dev.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@kixelated kixelated enabled auto-merge (squash) June 16, 2026 03:29
kixelated and others added 4 commits June 15, 2026 20:38
subscribe_catalog/subscribe_media are async but this test called .unwrap()
without .await, breaking the build on dev. Unrelated to the Frame change;
folded in to unblock CI.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…publish_media

This test never compiled on dev (it called the async subscribe_* without
.await), so it never ran. Beyond the await fix, it also deadlocked: subscribing
to an unpublished track blocks until the dynamic producer accepts the request via
requested_track(), so both sides must run concurrently. Restructured with
tokio::join! to match the sibling dynamic_track_request tests.

It then surfaces a separate product bug: a dynamically-requested track is
subscribed with no timescale, so publish_media_on_track stamps per-frame
timestamps that append_frame rejects as TimestampMismatch. Quarantined with
#[ignore] until that is fixed; the deadlock fix is already correct so the fix is
just removing the attribute. Unrelated to the Frame.duration change; folded in to
unblock dev CI.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
# Conflicts:
#	rs/hang/src/container/frame.rs
#	rs/moq-ffi/src/test.rs
@kixelated kixelated merged commit adb1003 into dev Jun 16, 2026
1 check failed
@kixelated kixelated deleted the claude/frosty-cerf-b14aa1 branch June 16, 2026 06:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant