Skip to content
1 change: 0 additions & 1 deletion quest/m1/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,6 @@ removed).
- [JS FETCH timeout test](/quest/m1/js-fetch-timeout-test.md) - a JS joining FETCH still waiting on its SUBSCRIBE at the deadline is refused with TIMEOUT
- [JS joins at the current group](/quest/m1/ietf-js-join.md) - a late JS moq-transport subscriber gets the group in progress whole through a joining FETCH or fill, as Rust does
- [IETF fill timeout](/quest/m1/ietf-fill-timeout.md) - Rust honors native FILL_TIMEOUT to bound upstream waiting on drafts 18 and 22, alongside local content-age enforcement
- [Catalog estimates settle](/quest/m1/catalog-estimates.md) - hang quantizes jitter and delay rises, and MSF publishes once its estimates are made and then only for track changes
- [IETF takeover](/quest/m1/ietf-takeover.md) - carry the shared takeover contract through the negotiated IETF epoch extension
- [Identity and recovery guide](/quest/m1/identity-guide.md) - explain epochs, pinned catalogs, lazy jobs, restart and version compatibility as they exist; takeover adds its own section
- [Native rung disable](/quest/m1/simulcast-rung-disable.md) - OBS stops sending the top renditions its grant cannot fund, as the Rust/FFI publishers do, and a shaped uplink through moq-ffi proves the resume
Expand Down
59 changes: 0 additions & 59 deletions quest/m1/catalog-estimates.md

This file was deleted.

3 changes: 2 additions & 1 deletion rs/moq-c/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,8 @@ pub struct moq_video_init {
///
/// Zero the struct and set only the `has_*` flags you want. Hints fill gaps the
/// bitstream leaves (especially bitrate); a value the stream detects later wins
/// for dimensions.
/// for dimensions. The MSF catalog declares a bitrate or frame rate only when
/// it is hinted here.
#[repr(C)]
#[derive(Clone, Copy, Default)]
pub struct moq_video_hint {
Expand Down
1 change: 1 addition & 0 deletions rs/moq-ffi/src/media.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ pub struct MoqDatagram {
/// Caller-provided video catalog fields for [`MoqVideoInit`].
///
/// Every field is optional and fills only a gap the stream leaves; a value the stream detects wins.
/// The MSF catalog declares a bitrate or frame rate only when it is hinted here.
/// Publishing the catalog before the first keyframe needs at least the codec, which comes from the
/// [`MoqVideoInit`] format. Audio has no equivalent: it resolves entirely from its init bytes.
#[derive(Clone, Default, uniffi::Record)]
Expand Down
8 changes: 4 additions & 4 deletions rs/moq-mux/src/catalog/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ pub(crate) struct Listing {
trait Owned: Send + Sync {
fn name(&self) -> &str;
fn clock(&self) -> crate::Clock;
fn estimate(&mut self, estimate: super::Estimate) -> crate::Result<()>;
fn estimate(&mut self, reading: super::Reading) -> crate::Result<()>;
}

impl<E: CatalogExt, C: RenditionConfig<E>> Owned for Rendition<E, C> {
Expand All @@ -55,8 +55,8 @@ impl<E: CatalogExt, C: RenditionConfig<E>> Owned for Rendition<E, C> {
fn clock(&self) -> crate::Clock {
Rendition::clock(self)
}
fn estimate(&mut self, estimate: super::Estimate) -> crate::Result<()> {
Rendition::estimate(self, estimate)
fn estimate(&mut self, reading: super::Reading) -> crate::Result<()> {
Rendition::estimate(self, reading)
}
}

Expand Down Expand Up @@ -111,6 +111,6 @@ impl Listing {
// media track behind it by however fast it runs. It was written no later than now.
self.estimator.order(captured.min(now));
}
self.rendition.estimate(self.estimator.estimate())
self.rendition.estimate(self.estimator.reading())
}
}
30 changes: 30 additions & 0 deletions rs/moq-mux/src/catalog/estimate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,14 @@ impl Estimator {
self.jitter.max = self.jitter.max.max(duration);
}

/// Everything measured so far, with what a catalog rendition needs to decide when to publish it.
pub(crate) fn reading(&self) -> Reading {
Reading {
estimate: self.estimate(),
period: self.framerate.shortest,
}
}

/// Everything measured so far.
///
/// Catalog-owned [`container::Producer`](crate::container::Producer) handles publish this
Expand All @@ -204,6 +212,21 @@ impl Estimator {
}
}

/// An [`Estimate`] with the measurements that pace its publishing.
#[derive(Clone, Debug, Default)]
pub(crate) struct Reading {
pub estimate: Estimate,
/// The shortest advance between frames, which a published `jitter` or `delay` rises in whole
/// steps of when no framerate says the frame duration.
pub period: Option<Duration>,
}

impl From<Estimate> for Reading {
fn from(estimate: Estimate) -> Self {
Self { estimate, period: None }
}
}

/// A frame time as scale-free nanoseconds.
///
/// Timestamps reaching an estimator can carry different timescales: a track normalizes them into
Expand Down Expand Up @@ -307,10 +330,16 @@ struct Framerate {
/// Frames written since the window opened.
frames: u64,
max: Option<f64>,
/// The shortest advance of the highest timestamp: a frame's duration, or a reordered group's
/// span of them.
shortest: Option<Duration>,
}

impl Framerate {
fn write(&mut self, ts: u128) {
if let Some(advance) = self.high.and_then(|high| elapsed(high, ts)) {
self.shortest = Some(self.shortest.map_or(advance, |shortest| shortest.min(advance)));
}
self.high = Some(self.high.map_or(ts, |high| high.max(ts)));
self.frames += 1;
}
Expand Down Expand Up @@ -349,6 +378,7 @@ impl Framerate {
fn discontinuity(&mut self) {
*self = Self {
max: self.max,
shortest: self.shortest,
..Self::default()
};
}
Expand Down
1 change: 1 addition & 0 deletions rs/moq-mux/src/catalog/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ pub use consumer::Consumer;
pub use data::IntoRendition;
pub(crate) use data::Listing;
pub use entry::Entry;
pub(crate) use estimate::Reading;
pub use estimate::{Estimate, Estimator};
pub use format::*;
pub use producer::{Config, Guard, Producer};
Expand Down
Loading
Loading