Skip to content

BLO-4020 M.1: MMTP publisher on IETF moq-transport (draft-14+) - #1

Closed
kkroo wants to merge 13 commits into
mainfrom
blo-4020-m1
Closed

BLO-4020 M.1: MMTP publisher on IETF moq-transport (draft-14+)#1
kkroo wants to merge 13 commits into
mainfrom
blo-4020-m1

Conversation

@kkroo

@kkroo kkroo commented May 28, 2026

Copy link
Copy Markdown

Summary

  • moq-catalog: adds Container enum (isobmff/mmtp/mfu/fec-repair) per draft-ramadan-moq-mmt §11.1 and an optional multicast: MulticastConfig extension per draft-ramadan-moq-multicast §4.1+§4.2.3. Both fields are opt-in (skip_serializing_if = "Option::is_none") so existing catalogs round-trip without diff.
  • moq-pub-mmtp (new sibling crate): publishes raw MMTP packets as MoQ object payloads. Reads from stdin (4-byte BE length-prefix framing) or UDP (one datagram = one packet). Per-track state keyed by MMTP packet_id from the catalog's multicast.endpoints[].tracks[]. Auto-creates <source>/repair sibling tracks for AL-FEC routing at priority 7. Posts the catalog JSON on the .catalog track at startup (priority 127, group 0).
  • mmt-core vendored under moq-pub-mmtp/vendor/mmt-core/ at libmmt commit 929e5b0c so the crate builds without a sibling libmmt checkout.

Why

BLO-4020 umbrella: replace cast's libmoq C-ABI hop with native Rust talking IETF moq-transport draft-14+. M.0 (baseline + scope-mismatch finding) and M.1 ADR are captured under .planning/. Option A locked: new sibling crate rather than patching upstream moq-pub or rewriting cast's bridge.

What's enforced (publisher invariants)

Invariant Behavior on violation
A1 First MMTP packet of each new MPU is FragmentType::Init Hard error (caller's job to send MPU metadata)
A2 MPU sequence numbers strictly non-decreasing per track Hard error (moq-transport's SubgroupsWriter::create silently drops group_id ≤ latest at subgroup.rs:116-128 — A2 catches it)
A3 packet_id appears in the catalog's multicast map Hard error

Repair group_id mirrors source MPU group_id so receivers can correlate repair symbols with the data they protect. Per-FEC-block grouping (parsing FEC Payload ID for SBN) is deferred to M.1b.

Test plan

  • cargo test -p moq-pub-mmtp — expect 30 passed (5 dispatch invariants, 5 repair routing, 6 framing, 4 MMTP parsing, 1 priority pin, 6 build_state_map error/happy paths, 1 catalog publication pin, 1 UDP recv→dispatch, 1 short-packet rejection, 1 routing edge case).
  • cargo test -p moq-catalog — expect 19 passed (Container enum spec values, multicast spec §4.1+§4.2.3 alignment, serde round-trips, optional-extension round-trips).
  • cargo build --release -p moq-pub-mmtp — green, zero warnings.
  • ./target/release/moq-pub-mmtp --help — CLI surface includes --name, --catalog-json, --mmtp-input stdin|udp, --mmtp-udp-bind, --bind, and the flattened TLS flags from moq_native_ietf::tls::Args.

Out of scope (deferred per ADR)

  • MPU metadata synthesis from MFU (caller's responsibility — cast/ffmpeg).
  • MMTP fragmentation reassembly (M.1b).
  • Per-FEC-block grouping (M.1b).
  • Receiver decode/render (M.4).
  • End-to-end smoke + mlog framing verification (T9, P2 — depends on T5 catalog validation, T7 moq-sub-raw, T8 ffmpeg fork stdout mode).

ADR

.planning/moq-rs-m1-adr.md carries the full decision set (A1-A5/C1), 9 Implementation Tasks (T1-T9), and the GSTACK eng-review report (Codex outside-voice: 12 findings, 9 folded into T1-T9, 3 acknowledged as M.1b TODOs). This PR lands T6 + T1-T4 (Lane A: publisher path). T5/T7/T8/T9 remain.

🤖 Generated with Claude Code

kkroo and others added 10 commits May 28, 2026 17:52
T1 clock pub/sub + T2 fMP4 BBB pub/sub with --catalog both pass on
Cloudflare moq-rs v0.7.17 (commit f9f51dc) over draft-14 wire.
Establishes the working baseline for the BLO-4020 MMTP migration.

Findings captured:

- dev/pub vs dev/sub scope-mismatch: dev scripts connect to different
  URLs (root vs /<name>), landing in different multi-tenant scopes on
  moq-relay-ietf and surfacing as `namespace not found`. Not a spec
  bug — Cloudflare's tenant-scope feature layered on draft-14. Fix is
  one-line in dev/sub.

- file-coordinator state leak: /tmp/moq-coordinator.json persists
  registrations across abrupt publisher exits, causing `duplicate`
  rejection on next announce. Local-dev annoyance; production uses
  Redis-backed moq-api.

What this confirms for the migration:
- G2 (publisher container) is the main work — moq-pub is firmly
  fMP4-coupled, MMTP needs a new container module.
- G1 (catalog Container::Mmtp) is the smallest first change.
- G6 (libmoq vs moq-rs draft-14 wire diff) remains open.
- M.4 is "replace, not extend": moq-lite is a different wire and not
  worth bridging to draft-14.

Logs captured under .planning/m0-logs/ for reproducibility.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adds two optional shapes to moq_catalog::Root for the MMTP-on-MoQ
migration (BLO-4020). Both fields are
#[serde(skip_serializing_if = "Option::is_none")] so existing
catalogs without the extensions round-trip without diff.

1. Container enum (Track.container field) per
   draft-ramadan-moq-mmt-00 §11.1 — values: isobmff | mmtp | mfu |
   fec-repair. Distinguishes how media is encapsulated inside MoQ
   objects from TrackPackaging (which is the IETF draft-01 catalog's
   cmaf vs loc streaming format).

2. multicast: Option<MulticastConfig> field per
   draft-ramadan-moq-multicast-00 §4.1 + §4.2.3 — describes one or
   more multicast endpoints with the MMTP packet_id → MoQ track map
   used by the multicast send-side. NetworkSource carries AMT relay
   discovery (type=amt, discovery=driad per §4.2.1). The
   OneOrMany<T> carrier preserves the "one object OR array" input
   form per §4.2.3 (single object does NOT become a one-element
   array on re-serialize).

moq-pub/src/media.rs gets `multicast: None` to satisfy the new
field on Root.

19 unit tests:
  - 4 Container enum (spec values, optional, default, accepts/omits)
  - 5 multicast spec alignment (§4.1 protocol-optional,
    networkSource at endpoint level, no simple-form fields, §4.2.3
    OneOrMany single/array forms)
  - 5 serde round-trips
  - 4 multicast-extension parsing on Root
  - 1 TrackPackaging round-trip pin

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Captures the M.1 architecture decisions for MMTP-on-moq-transport
(draft-14+) per umbrella BLO-4020. Option A locked: new sibling
crate `moq-pub-mmtp` rather than patching upstream moq-pub or
rewriting cast's bridge (Option B / Option C). Minimal blast
radius, zero upstream-coordination latency.

Decisions:
  A1 — Object 0 of each new MPU MUST be FragmentType::Init
       (publisher errors on violation; does NOT synthesize).
  A2 — MPU sequence numbers strictly non-decreasing per track
       (moq-transport's SubgroupsWriter::create silently drops
       group_id ≤ latest — A2 monotonicity check catches this).
  A3 — Unknown packet_id hard-errors.
  A4 — Smoke test verifies per-track sha256 (not concatenated)
       and mlog framing (not qlog).
  A5 — Vendor mmt-core under moq-pub-mmtp/vendor/ at pinned
       libmmt commit so the crate builds standalone.
  C1 — Stdin (length-prefix) AND UDP (datagram) input both
       supported; UDP for the multicast path.

Implementation Tasks T1-T9 derived from the decisions; T6 + T1-T4
land Lane A (publisher path). T5 (catalog validation), T7
(moq-sub-raw), T8 (ffmpeg fork stdout mode), T9 (smoke) remain.

GSTACK REVIEW REPORT footer: /gstack-plan-eng-review CLEARED;
Codex outside-voice flagged 12 findings, 9 folded into the
Implementation Tasks, 3 acknowledged as M.1b TODOs (object_id_delta
verification, MMTP fragmentation reassembly, FEC source-block
grouping).

Handoff prompt (m1-next-session-prompt.md) captures the resume
context for picking up mid-task.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
New sibling crate to moq-pub. Reads MMTP packets (from stdin with
4-byte BE length-prefix framing, or from a bound UDP socket) and
publishes them as raw MoQ object payloads per draft-ramadan-moq-mmt
§3.1+§4.1. Catalog is loaded from --catalog-json; per-track state
keyed by MMTP packet_id from the multicast extension's
endpoints[].tracks[] map.

Implements M.1 ADR Implementation Tasks T6 + T1-T4:

  T6 — Vendor mmt-core under vendor/
       libmmt commit 929e5b0c7a14f6ffe0ecd50d792fff7cdc44ba0a
       vendored so moq-pub-mmtp builds without a sibling libmmt
       checkout. Refresh procedure in vendor/mmt-core/VENDOR.md.
       Vendored Cargo.toml uses explicit versions (no workspace
       deps). Per ADR A5.

  T1 — Publisher loop with spec-true grouping
       Dispatch fn abstracted over TrackSubgroups + SubgroupWrite
       traits so the core logic is unit-testable without a real
       moq-transport session. Enforces three hard invariants:
         A1 — first packet of a new MPU is FragmentType::Init
              (publisher errors on violation; caller's
              responsibility to send MPU metadata first)
         A2 — MPU sequence numbers strictly non-decreasing per
              track. moq-transport's SubgroupsWriter::create
              silently drops subgroups whose group_id ≤ latest
              (subgroup.rs:116-128) — A2 is what catches the bug.
         A3 — unknown packet_id hard-errors (no silent drop)
       SubgroupsWriter::create({group_id: mpu_seq, subgroup_id: 0,
       priority}) — NOT append() — per Codex #5.
       Equal MPU sequence appends to the open subgroup.

  T2 — `.catalog` track posted at startup
       Full catalog JSON as one object on group 0 at priority 127.
       Caller retains the returned SubgroupsWriter so the track
       stays alive for the session.

  T3 — FEC repair routing on `<name>/repair` siblings
       build_state_map auto-creates a `<source>/repair` track for
       every catalog source track. Repair packets land at priority
       7 (per draft-ramadan-moq-mmt §7.2). Repair group_id mirrors
       source MPU group_id so the receiver can correlate repair
       symbols with the source data they protect. Per-FEC-block
       grouping (parsing Source/Repair FEC Payload ID) is M.1b.

  T4 — UDP input mode
       tokio::net::UdpSocket::bind(--mmtp-udp-bind); each datagram
       is one MMTP packet (no length prefix — the datagram boundary
       IS the framing). recv_one_udp_packet() extracted as a
       testable helper.

CLI parity with moq-pub for session setup: positional URL (no
path), --name, --catalog-json, --mmtp-input stdin|udp,
--mmtp-udp-bind, --bind, and the flattened
moq_native_ietf::tls::Args (--tls-cert/--tls-key/--tls-root/
--tls-disable-verify).

30 unit tests:
  - 5 dispatch invariants (A1/A2/A3 + advance + equal)
  - 5 repair routing (sibling, priority 7, group correlation,
    unknown packet_id, before-source-MPU, missing-repair-sibling)
  - 6 framing (length-prefix encode/decode + EOF/partial/oversize)
  - 4 MMTP/MPU header parsing (route fn)
  - 6 build_state_map (no-multicast, no-endpoints, duplicate-
    packet_id, missing-track-reference, happy-path, repair-track-
    registration)
  - 1 priority_for_container pin
  - 1 publish_catalog_track registration pin
  - 1 UDP recv → dispatch integration
  - 1 mmtp_parse short-packet rejection

Out of scope for M.1 (deferred): MPU metadata synthesis from MFU
(caller's job), MMTP fragmentation reassembly (M.1b), per-FEC-block
grouping (M.1b), receiver decode/render (M.4),
moq-transport object_id_delta verification (Codex #6 follow-up
landing in T9 mlog).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Reflects post-rebase + post-PR state:
- T6 + T1-T4 marked complete with the four commit SHAs landed on
  blo-4020-m1 (dbf5ee1, 6ee40ff, bde975d, 3101aca on base f0a709a
  after a clean 47-commit upstream rebase).
- PR #1 link: #1.
- Remotes documented (origin = cloudflare/moq-rs untouched;
  blockcast = Blockcast/moq-rs where local main tracks
  blockcast/blo-4020-m1).
- Workflow notes added: new commits land on PR #1 automatically;
  branch off if T5/T7 want separate PRs.
- Obsolete "uncommitted on main, ask before non-test edits"
  branch warning removed (no longer applicable).
- Remaining T5/T7/T8/T9 scope carried forward unchanged.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Promotes catalog invariants from publisher-only runtime checks to
library-level validation so subscribers can reject malformed
catalogs without re-implementing the guards.

moq-catalog:
  - New `CatalogValidationError` enum (Display + std::error::Error,
    no external deps). Three variants:
      DuplicatePacketId       — T5a (draft-ramadan-moq-multicast §4.1)
      UnknownTrackReference   — T5b
      FecRepairInCatalog      — T5e (repair tracks are
                                publisher-derived per ADR T3)
  - `Root::validate()` runs all three checks (first-error-wins).
  - `Root::expand_common_fields()` promotes commonTrackFields into
    each track entry (track-level overrides win). Replaces the
    previously-dead `Track::with_common` private helper. T5c.
  - `CommonTrackFields` gains `Clone` (needed for expand).

moq-pub-mmtp:
  - `check_namespace_consistency(&Root, name)` — if
    commonTrackFields.namespace is Some(X) and X != --name, hard
    error. Catches a class of publisher misconfigurations. T5d.
  - main(): wired in order
      1. catalog.validate()              (lib-level guards)
      2. check_namespace_consistency()   (publisher CLI consistency)
      3. catalog.expand_common_fields()  (in-memory normalization;
                                          on-wire .catalog bytes
                                          remain the original
                                          authorial form)
  - `build_state_map` runtime guards (duplicate packet_id, unknown
    track ref) kept as defense in depth.

Tests:
  - moq-catalog: +5 (3 validate + 2 expand_common_fields) → 24 total
  - moq-pub-mmtp: +3 (check_namespace_consistency) → 33 total

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
New sibling crate to moq-sub. Subscribes to named tracks on a MoQ
broadcast and dumps each track's concatenated raw object payloads
to its own file. Used by the M.1 smoke test (T9) for per-track
sha256 verification — by dumping object payloads with NO separators
(no length prefix, no timestamp), the publisher's input bytes and
the subscriber's output bytes match byte-for-byte per track.

CLI: paired `--track NAME --output PATH` arguments, repeatable.

  moq-sub-raw --name BBB \
      --track v --output v.bin \
      --track a --output a.bin \
      https://localhost:4443

Implementation:
  - `drain_track_to_writer<W>` — extracted as a testable async fn
    so unit tests can drive it with in-process Tracks::produce
    pairs (no live relay required). Walks TrackReaderMode::Subgroups
    → groups.next → group.next → object.read, writing every chunk
    to W in arrival order. Returns total bytes written.
  - `validate_track_output_pairs` — surfaces CLI misconfigurations
    (empty args, mismatched counts) BEFORE opening a session.
  - main(): mirrors moq-sub's session template. Spawns one
    subscriber.subscribe task per track AND one drain task per
    track; tokio::select! over session.run + drain JoinSet.

Tests (6 new):
  - validate_track_output_pairs: empty / mismatched / matched.
  - drain_concatenates_object_payloads_in_arrival_order — single
    subgroup, 3 objects, verify concat.
  - drain_concatenates_across_multiple_groups — producer/consumer
    run concurrently via tokio::join! with a 100ms gap between
    groups (SubgroupsReader surfaces only the latest subgroup —
    documented gotcha pinned by the test).
  - drain_writes_zero_bytes_on_empty_track — subgroups mode set
    but never written; drain returns Ok(0).

Workspace entry added; Cargo.lock updated.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The Blockcast FFmpeg fork's `moqenc_mmt` muxer already emits MMTP
packets through standard AVIOContext to a `udp://group:port?multicast=1`
URL. The proper way to wire moq-pub-mmtp as the consumer is to have
its existing `--mmtp-input udp` listener auto-join when the bind
target is a multicast address — no FFmpeg changes, no new flags on
moq-pub-mmtp, just smarter UDP open.

New `udp` module:
  - `is_multicast(SocketAddr) -> bool` — IPv4 and IPv6.
  - `open_udp_socket(target) -> UdpSocket`:
      * unicast target: bind directly.
      * multicast target: bind wildcard on target.port(), join the
        group on all interfaces, enable multicast loopback so a
        single-host smoke test can both send and receive.

`run_udp_loop` swapped its raw `UdpSocket::bind` for
`udp::open_udp_socket`, so `--mmtp-udp-bind 239.255.1.1:5004`
now actually receives multicast.

T8 ADR plan ("add stdout flag to ffmpeg muxer") superseded: the
muxer's existing avio_write path through AVIOContext IS the proper
FFmpeg interface. The dirty state in the FFmpeg fork is unrelated
to this work (FEC algorithm FFI extension + IPv6 multicast egress
fix in progress on a separate workstream).

Tests (+6):
  - is_multicast: 4 (ipv4 multicast / unicast, ipv6 multicast / unicast).
  - open_unicast_binds_directly_to_target.
  - open_multicast_binds_wildcard_and_recvs_loopback — full
    end-to-end: open multicast listener, send via second socket,
    verify recv. Gracefully skips if sandboxed network lacks
    multicast loopback (treats timeout / open-error as skip).

Total moq-pub-mmtp tests: 33 → 39.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adds the M.1 ADR Definition-of-Done item: an end-to-end smoke test
proving MMTP packets flow byte-for-byte through the new draft-14+
pipeline.

Pipeline (5 processes, all out of this repo):
  synth_mmtp (Rust example, deterministic MPU sequences)
    → UDP loopback (127.0.0.1:5004)
    → moq-pub-mmtp --mmtp-input udp
    → moq-relay-ietf --dev --mlog-dir
    → moq-sub-raw (per-track payload dump)
    → per-track sha256 vs synth's expected files

Verdict: PASS. Both tracks' sha256 match between publisher input
and subscriber output; --mlog-dir captures SUBGROUP/OBJECT framing
per draft-14. Full results recorded in
.planning/moq-rs-m1-results.md.

New files:
  - moq-pub-mmtp/examples/synth_mmtp.rs — deterministic MMTP
    packet generator. Emits valid MPU Init packets for two
    packet_ids (1=video, 2=audio) with predictable payloads.
    Outputs to UDP (one datagram = one packet) OR stdin
    (length-prefixed) AND writes expected per-track files for
    sha256 comparison.
  - .planning/m1-smoke.sh — orchestrator. Builds binaries, writes
    catalog, starts relay → pub → sub → synth, compares hashes,
    shows mlog, reports pass/fail. Idempotent across reruns.
  - .planning/moq-rs-m1-results.md — verdict, evidence, repro
    instructions, and the open M.1b items (FEC source-block
    grouping, fragmentation reassembly, libmoq G6 byte-diff).

Pacing note: SubgroupsReader surfaces only the latest subgroup —
the smoke uses --packet-delay-ms so the subscriber drains each
MPU before the next supersedes. Already covered by a unit test
in moq-sub-raw; documented in the results doc as a real-world
constraint (real publishers are network-rate-limited).

T8 status: superseded. The Blockcast FFmpeg fork's moqenc_mmt
muxer already uses AVIOContext for UDP emission — no fork
changes needed. The architecture pushback (no special stdout
flag) is the correct call. T8.5 (moq-pub-mmtp multicast join,
already landed) is the matching consumer-side support.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Updates the in-tree handoff prompt to reflect the post-T9 state:
9 commits on blo-4020-m1, 69 tests + smoke green, T1-T9 all landed
(T8 N/A per ADR architecture pushback). Lists the four candidate
follow-up tracks in priority order — A (PR merge prep), B (M.1b
sub-tasks), C (M.2 cast bridge — ADR-gated), D (M.4 receiver inventory).

No code changes; the doc tracks the closed state of the milestone
and the open M.1b sub-tasks (fragmentation reassembly, per-FEC-block
grouping, object_id_delta correctness, G6 byte-diff vs libmoq).
kkroo added 2 commits May 28, 2026 21:47
…M.2/M.4 ahead

Refreshes the handoff prompt to reflect the 2026-05-28 M.1b session:
- M.1b §B1=C closed by raw-passthrough fragmentation contract (PR #2).
- M.1b §B3 forensics confirmed object_id_delta bug at
  moq-transport/src/session/subscribed.rs:281 (PR #3); upstream issue
  drafted in BLO-8047 awaiting external filing.
- M.1b §B4 confirms wire-format divergence between cast/moq_lite and
  moq-pub-mmtp/IETF (PR #4); B2 re-scoped from "high operational value"
  → "M.4 prerequisite, deferred".

Four stacked PRs on blo-4020-m1. Next session picks:
- PR review / merge prep (likely fastest)
- Upstream object_id_delta issue filing at cloudflare/moq-rs (use BLO-8047 draft)
- M.2 cast bridge port (biggest blast radius; needs ADR + plan-phase first)
- M.4 receiver migration (multi-object subgroup decoder, tier-switching fallback)

Also documents the new FRAGMENT=N smoke env knob, the four follow-up
branch names with detached upstreams, and the raw-passthrough contract
as a carry-forward constraint.

No code changes; doc tracks the post-M.1b state of the milestone.
Reflects 2026-05-28 session continuation:
- M.4 ADR drafted on branch blockcast/blo-4020-m4-adr (commits ec8e4b7,
  5ffd5e1, 1b0c577). A0-A3 locked; Q3-Q8 tactical questions still open.
- Scope discovery: moqtail already on IETF draft-16 with MMTP container
  wired; Shaka MSF speaks drafts 14+16 with ALPN negotiation; hang-mmt-fec
  is the actual migration burden but Track 3 is INCLUDED per session sign-off.
- Updates the "PICK ONE FOR NEXT SESSION" list: D becomes "M.4 ADR sign-off +
  T0 (publisher draft-16 bump)"; adds new E for "M.4 Track 1 (Shaka MMTP)
  implementation" as the post-T0 starting point.

No code changes.
Reflects 2026-05-28 session continuation:
- M.4 ADR Q3-Q8 signed off; Track 3 reshaped per Q7 (use moqtail-ts;
  skip Rust IETF subscriber fix). Total M.4 scope ~5-6 weeks.
- T0 (publisher draft-16 bump) implemented + smoke-validated on
  branch blo-4020-m4-t0 (commit 9336e4a), PR #5 opened on the fork.
  Per-track sha256 IDENTICAL to M.1 baseline at FRAGMENT=0; mlog
  confirms selected_version DRAFT_16 in both QUIC sessions.
- 113 moq-transport tests pass (+3 negotiation regression tests).

Five PRs now stacked on blo-4020-m1; one fork-only branch with M.4 ADR.

Pick list restructured:
- D = M.4 Track 1 (Shaka MMTP container) — RECOMMENDED next, smallest
- E = M.4 Track 2 (moqtail tier-switching)
- F = M.4 Track 3 (MoqWatch port onto moqtail-ts; T3.1/T3.2 SKIPPED
      per Q7)
- G/H/I = PR review, upstream issue, M.2

Track 1 start files: shaka-player/lib/msf/loc_parser.js and
lib/transmuxer/loc_transmuxer.js (templates to mirror for MMTP).
M.4 ADR §T1.1-T1.7 has the full task breakdown.

No code changes; doc tracks the post-T0 state.
kkroo added a commit that referenced this pull request May 31, 2026
Reviews the three production changes shipped inside shaka commit 4df077593
(strip 14B MFU sub-header; store Init MPU on init ref; seedFromFmp4Init).

Root finding: decision D9 ("init from in-band SPS/PPS") is contradicted by
the design doc's own §2 ground truth (MFUs carry SEI+coded NALs, not param
sets; SPS/PPS live in the Init-MPU avcC). Proposes D12: revert D9, reinstate
the avcC-seed init path. Fix #1 KEEP+harden, #2 REWORK, #3 wire-in-or-delete.

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

kkroo commented Jun 1, 2026

Copy link
Copy Markdown
Author

Audit / review request: this PR opened 2026-05-28, before the moq-rs Ally webhook wiring (first moq-rs Ally review is #7 on 05-31), so it never received an automated review. Requesting an Ally pass. @ally / cc blockcast-ci-packages.

@kkroo

kkroo commented Jun 13, 2026

Copy link
Copy Markdown
Author

Superseded by #20 (blo-4020-m4-t1main), which collapses the M.1 → M.4 T1 stack into a single main-targeted integration PR. Every commit here is contained in #20 (merge-base = main HEAD, clean fast-forwardable). Closing to consolidate review on one thread. Branch retained — not deleted — since blo-4020-m1 remains the base of #2/#3/#4/#5 and blo-4020-m4-t1 is #20's head + #7's base. Reopen if the incremental stack must be preserved.

@kkroo kkroo closed this Jun 13, 2026
kkroo added a commit that referenced this pull request Jun 13, 2026
Reflects post-rebase + post-PR state:
- T6 + T1-T4 marked complete with the four commit SHAs landed on
  blo-4020-m1 (dbf5ee1, 6ee40ff, bde975d, 3101aca on base f0a709a
  after a clean 47-commit upstream rebase).
- PR #1 link: #1.
- Remotes documented (origin = cloudflare/moq-rs untouched;
  blockcast = Blockcast/moq-rs where local main tracks
  blockcast/blo-4020-m1).
- Workflow notes added: new commits land on PR #1 automatically;
  branch off if T5/T7 want separate PRs.
- Obsolete "uncommitted on main, ask before non-test edits"
  branch warning removed (no longer applicable).
- Remaining T5/T7/T8/T9 scope carried forward unchanged.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
kkroo added a commit that referenced this pull request Jun 13, 2026
Reviews the three production changes shipped inside shaka commit 4df077593
(strip 14B MFU sub-header; store Init MPU on init ref; seedFromFmp4Init).

Root finding: decision D9 ("init from in-band SPS/PPS") is contradicted by
the design doc's own §2 ground truth (MFUs carry SEI+coded NALs, not param
sets; SPS/PPS live in the Init-MPU avcC). Proposes D12: revert D9, reinstate
the avcC-seed init path. Fix #1 KEEP+harden, #2 REWORK, #3 wire-in-or-delete.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
kkroo added a commit that referenced this pull request Jun 13, 2026
Reviews the three production changes shipped inside shaka commit 4df077593
(strip 14B MFU sub-header; store Init MPU on init ref; seedFromFmp4Init).

Root finding: decision D9 ("init from in-band SPS/PPS") is contradicted by
the design doc's own §2 ground truth (MFUs carry SEI+coded NALs, not param
sets; SPS/PPS live in the Init-MPU avcC). Proposes D12: revert D9, reinstate
the avcC-seed init path. Fix #1 KEEP+harden, #2 REWORK, #3 wire-in-or-delete.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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