Skip to content
Draft
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
59 changes: 59 additions & 0 deletions draft-lcurley-moq-hang.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ Hang introduces additional terminology:
- **Participant**: A moq-lite broadcaster that may produce any number of media tracks.
- **Catalog**: A JSON document that describes each available media track, supporting live updates.
- **Container**: A tiny header in front of each media payload containing the timestamp.
- **Timeline**: An optional index mapping each media Group to the presentation timestamp of its first frame, used for seeking.


# Discovery
Expand Down Expand Up @@ -123,6 +124,7 @@ A video track contains the necessary information to decode a video stream.
~~~
type VideoSchema = {
"renditions": Map<TrackName, VideoDecoderConfig>,
"timeline": TrackName | undefined,
"priority": u8,
"display": {
"width": number,
Expand All @@ -137,6 +139,8 @@ The `renditions` field contains a map of track names to video decoder configurat
See the [WebCodecs specification](https://www.w3.org/TR/webcodecs/#video-decoder-config) for specifics and registered codecs.
Any Uint8Array fields are hex-encoded as a string.

The optional `timeline` field names a [Timeline](#timeline) track that indexes this media for seeking.

For example:

~~~
Expand All @@ -157,6 +161,7 @@ For example:
"framerate": 30.0
}
},
"timeline": "video/timeline",
"priority": 2,
"display": {
"width": 1280,
Expand All @@ -174,6 +179,7 @@ An audio track contains the necessary information to decode an audio stream.
~~~
type AudioSchema = {
"renditions": Map<TrackName, AudioDecoderConfig>,
"timeline": TrackName | undefined,
"priority": u8,
}
~~~
Expand All @@ -182,6 +188,8 @@ The `renditions` field contains a map of track names to audio decoder configurat
See the [WebCodecs specification](https://www.w3.org/TR/webcodecs/#audio-decoder-config) for specifics and registered codecs.
Any Uint8Array fields are hex-encoded as a string.

The optional `timeline` field names a [Timeline](#timeline) track that indexes this media for seeking.

For example:

~~~
Expand All @@ -200,6 +208,7 @@ For example:
"bitrate": 64000
}
},
"timeline": "audio/timeline",
"priority": 1,
}
~~~
Expand All @@ -217,6 +226,56 @@ The remainder of the payload is codec specific; see the WebCodecs specification
For example, h.264 with no `description` field would be annex.b encoded, while h.264 with a `description` field would be AVCC encoded.


# Timeline
The timeline is an optional track that indexes a media track's Groups by presentation timestamp.
It lets a subscriber seek — resolving a presentation timestamp to a Group sequence — without first downloading and parsing the start of every Group.
It carries no media payload and is typically given a lower priority than the media tracks it indexes.

A media schema references its timeline track by name via the `timeline` field (see [Catalog](#catalog)).
A timeline reflects the Group and timestamp structure of one media track.
The renditions of a single media already share that structure — matching Group sequence numbers and per-group timestamps so a subscriber can switch between them — so one timeline serves all of a media's renditions.
Audio and video do not share that structure and use separate timelines.

The timeline track is a single Group that grows over the lifetime of the broadcast.
Each frame appends one entry, in Group order, mapping a Group to the presentation timestamp of that Group's first frame.
A subscriber builds the full index by reading the Group from its first frame; because moq-lite always retains the latest Group, a subscriber that joins late still receives every prior entry.
A publisher SHOULD keep the whole timeline in this single Group rather than starting a new one: moq-lite guarantees retention only of the latest Group, so splitting the index across Groups risks the earlier entries being dropped before a late subscriber can read them.

To seek to a presentation timestamp, a subscriber selects the entry with the greatest timestamp not exceeding the target and subscribes to (or fetches) that Group, which begins with a keyframe (see [Container](#container)).

## Encoding
The timeline reuses the moq-lite `FRAME` to carry the presentation timestamp, leaving a single value in the payload:

~~~
Timeline Frame {
Group Delta (i),
}
~~~

The presentation timestamp is expressed in the track's `Publisher Timescale` ([moql]).
This is application-defined and SHOULD match the timescale of the media track being indexed so the values are directly comparable when seeking.

**Group Delta**:
The increase in Group sequence from the previous entry, encoded as an unsigned variable-length integer.
The first entry in the Group encodes the absolute Group sequence (a delta from 0).
This is normally `1`, since a publisher assigns Group sequences sequentially, but a larger value lets a timeline index Groups sparsely (for example, only every Nth Group).

**Presentation Timestamp**:
The presentation timestamp of the Group's first frame is not stored in the payload; it is carried by the moq-lite frame's `Timestamp Delta` field ([moql]), a zigzag-encoded signed delta from the previous entry in the track's timescale.
The first entry in the Group therefore carries the absolute timestamp, following the moq-lite frame rules.
A signed delta also accommodates the occasional backward step caused by frame reordering (e.g. an open GOP).

For example, a video track using a microsecond timescale with a constant two-second GOP starting at Group 100 produces these entries (the timestamp is carried by the moq-lite frame, the group delta by the payload):

~~~
entry 0: timestamp=0 group=100 # absolute anchor
entry 1: timestamp=+2000000 group=+1
entry 2: timestamp=+2000000 group=+1
~~~

Each entry occupies only a few bytes, and a regular cadence repeats identical deltas, so the index stays small even for long broadcasts.


# Security Considerations
TODO Security

Expand Down
Loading