Skip to content

moq-mux: pre-existing codec/container correctness findings (from #1918 review) #1923

Description

@kixelated

CodeRabbit's review of #1918 (the moq-mux backport to main) surfaced several Major-severity findings that are pre-existing in the dev moq-mux lineage — they are not regressions introduced by the backport. The two low-risk ones were fixed in #1918; the rest are tracked here because they're either risky to change blindly (could affect the byte-exact roundtrip tests), architectural, or ambiguous. They should be fixed on dev (and flow back to main) or in a focused follow-up with dedicated tests.

Deferred findings

  • codec/h264/split.rs / codec/h265/split.rs — consecutive bare IDRs can merge into one access unit. The IDR/keyframe arm reconciles SPS/PPS and sets contains_idr/contains_slice but never closes an already-open slice-bearing frame on the first slice of a new picture (unlike the non-keyframe slice path which checks first_slice…). A stream that doesn't repeat parameter sets before each keyframe, with a keyframe arriving right after a delta picture in the same decode chunk, can fold two AUs into one frame (and mis-flag it keyframe). Streaming-only; the decode+flush-per-AU tests don't surface it.

  • codec/aac/mod.rs — explicit (15) sample-rate index misparses. When freq_index == 15 the 24-bit explicit rate begins in bits already consumed from the preceding bytes; the current path reads the next three whole bytes, so both sample_rate and channel_count decode wrong. Breaks Config::encode()Config::parse() round-trips for non-standard rates. Needs a bit-reader.

  • container/consumer.rs — group read errors all treated as evictions. The poll_read error branch skips forward on any F::Error, but a malformed container payload (decode error) is not the same as a relay group eviction. Only known group-abort / old-cache errors should skip; decode errors should propagate.

  • container/fmp4/mod.rs — duration-less multi-sample fragments lose timestamps. Encoding omits the sample duration whenever Frame.duration is None, but decode() advances DTS by 0 for those, so a fragment with frames at e.g. 0ms and 33ms but no explicit durations decodes both at 0ms. Should infer adjacent durations for non-last samples or reject such multi-sample fragments. Related to the signed/duration work in Support negative / signed presentation timestamps (audio priming, pacing, B-frame reorder) #1917.

  • catalog/filter.rs / catalog/target.rs — stream never returns EOF after the final snapshot. After upstream EOF, last_input stays Some, so once the retained final snapshot is emitted the next poll parks in Pending forever. Ambiguous: the Pending may be intentional (re-filter the retained snapshot on a later target change after upstream ends). Needs a decision on whether a filter/target stream should end with upstream or stay alive for post-EOF target changes.

Fixed in #1918 (low-risk)

  • codec/av1/import.rs: av1C size gate relaxed from >= 16 to the 4-byte fixed header.
  • container/fmp4/import.rs: checked arithmetic for PTS / sample offsets / DTS advance.

(Written by Claude)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions