Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions doc/bin/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,14 @@ downstream sees it. A sparse stream such as SCTE-35 goes quiet between cues, so
the line reports rather than alarms; `Import::stats` carries the same counters
for a caller that sets its own limit.

A corrupt media packet, malformed PES header, or damaged codec access unit is
dropped and logged as a warning. Ingest continues on every other PID.
Video closes its group at the break and resumes at its next keyframe, as it does
after a continuity-counter gap: the pictures in between may reference the lost
one, so they are dropped rather than decoded with artefacts. Each break freezes
video for up to one GOP. Publishing, catalog, and clock errors still end the
import.

MPEG-TS import takes one program. A multi-program stream is refused before
anything is published, naming its programs, rather than merged onto one clock;
a PAT that adds a program mid-stream ends the import the same way.
Expand Down
6 changes: 4 additions & 2 deletions doc/bin/srt.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@ source (`--connect`); `moq export srt` serves SRT to players or pushes to a
remote. The payload is MPEG-TS, so the same codecs as [`import ts`](/bin/cli)
apply: H.264/H.265 video and AAC, MP2, AC-3, or E-AC-3 audio. Ingest logs the
same per-stream lines as `import ts`, under an `srt{path=...}` span: an
elementary stream that stopped delivering access units, and audio frame sync
lost.
elementary stream that stopped delivering access units, audio frame sync lost,
and damaged units refused. Damage drops that unit and keeps the session alive;
video closes its group at the break and resumes at its next keyframe, freezing
for up to one GOP.

```bash
# Accept a contribution feed and publish it
Expand Down
29 changes: 26 additions & 3 deletions rs/moq-mux/src/codec/h264/split.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ pub struct Split {
pending: Vec<crate::container::Frame>,
}

/// A snapshot of [`Split`]'s retained parameter sets.
pub(crate) struct Params {
sps: Vec<Bytes>,
pps: Vec<Bytes>,
}

#[derive(Default)]
struct Avc3Frame {
chunks: BytesMut,
Expand Down Expand Up @@ -224,14 +230,31 @@ impl Split {
Ok(())
}

/// Drop any in-flight access unit.
/// Drop any in-flight access unit, and any frame completed but not yet returned.
///
/// Pre-reset NALs would otherwise leak into a later frame with the wrong
/// timestamp. The parameter-set cache is kept so subsequent keyframes stay
/// self-contained.
/// timestamp, and a frame queued before a failed [`decode`](Self::decode) would
/// surface on the next call. The parameter-set cache is kept so subsequent
/// keyframes stay self-contained.
pub fn reset(&mut self) {
self.current = Avc3Frame::default();
self.tail.clear();
self.pending.clear();
}

/// The retained parameter sets, for [`restore`](Self::restore) to put back.
pub(crate) fn params(&self) -> Params {
Params {
sps: self.sps.clone(),
pps: self.pps.clone(),
}
}

/// Put back parameter sets a refused access unit replaced, so a later bare keyframe
/// re-injects the last good ones rather than the refused unit's.
pub(crate) fn restore(&mut self, params: Params) {
self.sps = params.sps;
self.pps = params.pps;
}

fn pts(&mut self, hint: Option<moq_net::Timestamp>) -> Result<moq_net::Timestamp> {
Expand Down
32 changes: 29 additions & 3 deletions rs/moq-mux/src/codec/h265/split.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,13 @@ pub struct Split {
pending: Vec<crate::container::Frame>,
}

/// A snapshot of [`Split`]'s retained parameter sets.
pub(crate) struct Params {
vps: Vec<Bytes>,
sps: Vec<Bytes>,
pps: Vec<Bytes>,
}

#[derive(Default)]
struct Au {
chunks: BytesMut,
Expand Down Expand Up @@ -228,14 +235,33 @@ impl Split {
Ok(())
}

/// Drop any in-flight access unit.
/// Drop any in-flight access unit, and any frame completed but not yet returned.
///
/// Pre-reset NALs would otherwise leak into a later frame with the wrong
/// timestamp. The parameter-set cache is kept so subsequent keyframes stay
/// self-contained.
/// timestamp, and a frame queued before a failed [`decode`](Self::decode) would
/// surface on the next call. The parameter-set cache is kept so subsequent
/// keyframes stay self-contained.
pub fn reset(&mut self) {
self.current = Au::default();
self.tail.clear();
self.pending.clear();
}

/// The retained parameter sets, for [`restore`](Self::restore) to put back.
pub(crate) fn params(&self) -> Params {
Params {
vps: self.vps.clone(),
sps: self.sps.clone(),
pps: self.pps.clone(),
}
}

/// Put back parameter sets a refused access unit replaced, so a later bare keyframe
/// re-injects the last good ones rather than the refused unit's.
pub(crate) fn restore(&mut self, params: Params) {
self.vps = params.vps;
self.sps = params.sps;
self.pps = params.pps;
}

fn pts(&mut self, hint: Option<moq_net::Timestamp>) -> Result<moq_net::Timestamp> {
Expand Down
Loading
Loading