You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Remove Frame/Object Duration from moq-lite and moq-timestamp (#32)
Duration was an application-level presentation hint that the transport
never used for delivery decisions. Keeping it encourages a frame of added
latency: a publisher either has to know a frame's length before its
successor exists (impossible for live) or wait for the next frame to infer
it. A bare timestamp lets a receiver present each frame as soon as it
arrives.
moq-lite: drop the Duration field from the Frame concept, the FRAME
message (Duration Delta), the datagram body, the Publisher Timescale
omission rule, and the moq-lite-05 changelog.
moq-timestamp: remove the DURATION object property entirely, including its
0x915C4 IANA registration (never published, so the codepoint is freed),
and the relay age-refinement rationale.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: draft-lcurley-moq-lite.md
+10-29Lines changed: 10 additions & 29 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -155,10 +155,9 @@ A Frame is a payload of bytes within a Group.
155
155
A frame is used to represent a chunk of data with an upfront size.
156
156
The contents are opaque to the moq-lite layer.
157
157
158
-
Each frame carries a presentation timestamp expressed in the parent Track's `Timescale` (units per second, part of the [TRACK_INFO](#track-info)), and a duration in the same scale.
158
+
Each frame carries a presentation timestamp expressed in the parent Track's `Timescale` (units per second, part of the [TRACK_INFO](#track-info)).
159
159
The timestamp is the source-of-truth for media time and is used by the moq-lite layer for [expiration](#expiration) decisions instead of wall-clock arrival time.
160
-
The duration is a hint for the application layer (e.g. presentation scheduling) and is not used by moq-lite itself; a duration of `0` means unknown and the frame is presented until the next frame begins.
161
-
A Track with a `Timescale` of 0 (unspecified) carries no meaningful timestamps or durations and falls back to wall-clock arrival time for expiration.
160
+
A Track with a `Timescale` of 0 (unspecified) carries no meaningful timestamps and falls back to wall-clock arrival time for expiration.
162
161
163
162
# Flow
164
163
This section outlines the flow of messages within a moq-lite session.
@@ -495,13 +494,12 @@ DATAGRAM Body {
495
494
Subscribe ID (i)
496
495
Group Sequence (i)
497
496
[Timestamp (i)]
498
-
[Duration (i)]
499
497
Payload (b)
500
498
}
501
499
~~~
502
500
503
-
`Timestamp`and `Duration` are present only when the Track's `Publisher Timescale` (see [TRACK_INFO](#track-info)) is non-zero.
504
-
When `Publisher Timescale` is 0, both fields are omitted from the wire and the datagram body consists of just `Subscribe ID`, `Group Sequence`, and `Payload`.
501
+
`Timestamp`is present only when the Track's `Publisher Timescale` (see [TRACK_INFO](#track-info)) is non-zero.
502
+
When `Publisher Timescale` is 0, the field is omitted from the wire and the datagram body consists of just `Subscribe ID`, `Group Sequence`, and `Payload`.
505
503
506
504
**Subscribe ID**:
507
505
The Subscribe ID of an active subscription on the same session.
@@ -515,10 +513,6 @@ Each datagram represents a complete group containing exactly one frame.
515
513
The absolute timestamp of the single frame in the group, expressed in the Track's negotiated `Timescale`.
516
514
Any varint value (including 0) is a valid absolute timestamp.
517
515
518
-
**Duration**:
519
-
The absolute duration of the frame, expressed in the Track's negotiated `Timescale`.
520
-
A value of `0` means the duration is unknown; the frame is presented until the next frame begins (or indefinitely, since a datagram-delivered group contains exactly one frame, until the application supersedes it).
521
-
522
516
**Payload**:
523
517
The frame payload, extending to the end of the datagram.
524
518
If the Track's `Publisher Compression` is non-zero, the payload is compressed using the negotiated algorithm (see [TRACK_INFO](#track-info)).
@@ -847,7 +841,7 @@ The unit is milliseconds (independent of `Publisher Timescale`) so cache retenti
847
841
**Publisher Timescale**:
848
842
The number of timestamp units per second for frame timestamps on this Track.
849
843
A value of 0 means unspecified; the subscriber MUST treat per-frame timestamps as opaque and fall back to wall-clock arrival time for [expiration](#expiration).
850
-
When `Publisher Timescale` is 0, the per-frame `Timestamp Delta` and `Duration Delta` fields are omitted from FRAME messages and the `Timestamp` and `Duration` fields are omitted from datagram bodies (see [FRAME](#frame) and [Datagrams](#datagrams)).
844
+
When `Publisher Timescale` is 0, the per-frame `Timestamp Delta` field is omitted from FRAME messages and the `Timestamp` field is omitted from datagram bodies (see [FRAME](#frame) and [Datagrams](#datagrams)).
851
845
Common values include `1000` (milliseconds), `1000000` (microseconds), `48000` (audio sample rate), and `90000` (RTP video clock).
852
846
853
847
**Publisher Compression**:
@@ -1044,14 +1038,13 @@ The FRAME message is a payload within a group.
1044
1038
~~~
1045
1039
FRAME Message {
1046
1040
[Timestamp Delta (i)]
1047
-
[Duration Delta (i)]
1048
1041
Message Length (i)
1049
1042
Payload (b)
1050
1043
}
1051
1044
~~~
1052
1045
1053
-
`Timestamp Delta`and `Duration Delta` are present only when the Track's `Publisher Timescale` (see [TRACK_INFO](#track-info)) is non-zero.
1054
-
When `Publisher Timescale` is 0, both fields are omitted from the wire and the FRAME consists of just `Message Length` and `Payload`.
1046
+
`Timestamp Delta`is present only when the Track's `Publisher Timescale` (see [TRACK_INFO](#track-info)) is non-zero.
1047
+
When `Publisher Timescale` is 0, the field is omitted from the wire and the FRAME consists of just `Message Length` and `Payload`.
1055
1048
1056
1049
**Timestamp Delta**:
1057
1050
A signed delta from the previous frame's timestamp, in the Track's negotiated `Timescale`.
@@ -1063,18 +1056,6 @@ Encoded as a zigzag-mapped variable-length integer:
1063
1056
Zigzag interleaves non-negative and negative values (`0 → 0, -1 → 1, 1 → 2, -2 → 3, 2 → 4, ...`) so small magnitudes of either sign fit in a 1-byte varint and there is exactly one wire encoding for zero.
1064
1057
The first frame of a group is delta-encoded from `0`, so its `Timestamp Delta` is the zigzag encoding of the absolute timestamp.
1065
1058
1066
-
**Duration Delta**:
1067
-
A signed delta from the previous frame's duration, in the Track's negotiated `Timescale`, encoded using the same zigzag mapping as `Timestamp Delta`.
1068
-
A wire value of `0` means the duration is unchanged from the previous frame; this is the common case for constant-rate media and fits in one byte.
1069
-
The first frame of a group is delta-encoded from a prior duration of `0`.
1070
-
1071
-
The resolved duration value carries the following semantics for the application:
1072
-
1073
-
- A resolved duration of `0` means the duration is unknown; the frame is presented until the next frame in the group begins (or until the group ends, if it is the last frame).
1074
-
- A non-zero resolved duration is the explicit presentation duration in the Track's `Timescale`.
1075
-
1076
-
The duration is an application-level hint and is not used by the moq-lite layer for delivery decisions.
1077
-
1078
1059
**Payload**:
1079
1060
An application-specific payload.
1080
1061
If the Track's `Publisher Compression` is non-zero, the payload is compressed using the negotiated algorithm (see [TRACK_INFO](#track-info)) and the `Message Length` describes the compressed size.
@@ -1093,9 +1074,9 @@ A generic library or relay MUST NOT inspect or modify the decompressed contents
1093
1074
- Renamed `Start Group`/`End Group` to `Group Start`/`Group End` in SUBSCRIBE, SUBSCRIBE_UPDATE, and SUBSCRIBE_DROP for consistency with the entity-first naming used elsewhere (e.g. `Group Sequence`). Wire format unchanged.
1094
1075
- Allowed a duplicate `active` ANNOUNCE to atomically replace the prior advertisement (equivalent to UNANNOUNCE+ANNOUNCE). Used when only the origin or hop path changes (e.g. relay failover) without interrupting the broadcast. No new wire enum value — the existing `active` status carries the new metadata.
1095
1076
- Added ANNOUNCE_OK message, sent once at the head of the Announce Stream response. Carries the publisher's `Hop ID` (hoisted out of every ANNOUNCE's Hop ID list) and an `Active Count` so subscribers can batch the initial set instead of reporting each ANNOUNCE as it trickles in.
1096
-
- Added `Publisher Timescale` to TRACK_INFO for per-track timestamp negotiation. When `Publisher Timescale` is 0, the per-frame timestamp/duration fields are omitted entirely from FRAME and datagram bodies.
1097
-
- Added `Timestamp Delta` and `Duration Delta` to FRAME, both zigzag-encoded signed varints (present only when timescale is non-zero). `Duration Delta = 0` is the common "unchanged" case and fits in one byte; a resolved duration of `0` means "until the next frame".
1098
-
- Added `Timestamp` and `Duration` to the QUIC datagram body (absolute, present only when timescale is non-zero).
1077
+
- Added `Publisher Timescale` to TRACK_INFO for per-track timestamp negotiation. When `Publisher Timescale` is 0, the per-frame timestamp field is omitted entirely from FRAME and datagram bodies.
1078
+
- Added `Timestamp Delta` to FRAME, a zigzag-encoded signed varint (present only when timescale is non-zero).
1079
+
- Added `Timestamp` to the QUIC datagram body (absolute, present only when timescale is non-zero).
1099
1080
- Renamed `Publisher Max Latency` to `Publisher Cache` (now in TRACK_INFO), defined as a minimum retention guarantee (similar to HTTP `Cache-Control: max-age`). Groups may live longer than `Publisher Cache` and remain FETCH-able.
1100
1081
- Renamed `Subscriber Max Latency` to `Subscriber Stale` in SUBSCRIBE/SUBSCRIBE_UPDATE. It is the subscriber's delivery-time preference for dropping non-latest stale groups, separate from the publisher's retention guarantee.
1101
1082
- Timestamp-based expiration replaces wall-clock arrival time when a Track timescale is negotiated.
Copy file name to clipboardExpand all lines: draft-lcurley-moq-timestamp.md
+7-26Lines changed: 7 additions & 26 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -23,8 +23,8 @@ informative:
23
23
24
24
--- abstract
25
25
26
-
This document defines an extension for MoQ Transport {{moqt}} that attaches a media presentation timestamp and duration to each object.
27
-
A track-level Timescale property establishes the units, an object-level Timestamp property carries the presentation time of each object, and an optional Duration property carries its presentation duration.
26
+
This document defines an extension for MoQ Transport {{moqt}} that attaches a media presentation timestamp to each object.
27
+
A track-level Timescale property establishes the units, and an object-level Timestamp property carries the presentation time of each object.
28
28
Exposing media time to the transport lets relays make consistent age-based decisions (e.g. dropping stale objects) without parsing the media container, and it remains consistent across hops regardless of buffering or jitter.
29
29
30
30
--- middle
@@ -46,7 +46,7 @@ A relay frequently needs a notion of *when* an object is meant to be presented:
46
46
MoQ also demultiplexes media into many independent tracks — audio, video, captions, metadata, and more — so a timestamp is needed on nearly every track.
47
47
Re-implementing per-object timestamping inside each application's container format, for every track, is repetitive and error-prone; standardizing it at the transport lets one implementation serve every track and lets relays use it directly.
48
48
49
-
This extension exposes media time to the transport with three Key-Value-Pairs ({{moqt}} Section 2.5): a track-level **Timescale**, an object-level **Timestamp**, and an optional object-level **Duration**.
49
+
This extension exposes media time to the transport with two Key-Value-Pairs ({{moqt}} Section 2.5): a track-level **Timescale**and an object-level **Timestamp**.
50
50
The transport does not interpret the *meaning* of the timeline (it is still the application's clock); it only uses the timestamp for relative age comparisons.
51
51
52
52
@@ -67,7 +67,7 @@ A relay MAY perform timestamp-based dropping for a track only if the upstream pu
67
67
68
68
69
69
# TIMESCALE Track Property
70
-
The TIMESCALE property establishes the units for every Timestamp and Duration on a track.
70
+
The TIMESCALE property establishes the units for every Timestamp on a track.
71
71
It is a track-level Key-Value-Pair, carried with the track's properties (see {{moqt}} Section 2.5 and Section 12).
72
72
Because the value is a single integer, TIMESCALE uses an even Type so the value is a bare varint with no length prefix:
73
73
@@ -81,11 +81,11 @@ TIMESCALE Track Property {
81
81
**Value**:
82
82
The number of timestamp units per second.
83
83
Common values include `1000` (milliseconds), `1000000` (microseconds), `48000` (a typical audio sample rate), and `90000` (the RTP video clock).
84
-
A value of `0`, or the absence of the property, means the track has no media timeline: Timestamp and Duration properties, if present, MUST be ignored, and a relay MUST fall back to wall-clock arrival time for any age-based decision.
84
+
A value of `0`, or the absence of the property, means the track has no media timeline: Timestamp properties, if present, MUST be ignored, and a relay MUST fall back to wall-clock arrival time for any age-based decision.
85
85
86
86
The Timescale is fixed for the lifetime of the track and MUST NOT change.
87
87
88
-
The Timescale is required to interpret the units of every Timestamp and Duration, so a receiver cannot resolve an object's timing until it has the track's properties.
88
+
The Timescale is required to interpret the units of every Timestamp, so a receiver cannot resolve an object's timing until it has the track's properties.
89
89
Those properties are delivered in SUBSCRIBE_OK or TRACK_STATUS ({{moqt}} Section 12), so a receiver that begins receiving objects before it has them MUST buffer the timing (or treat it as unknown) until the Timescale arrives.
90
90
A relay that has not yet learned the Timescale MUST fall back to wall-clock arrival time for any age-based decision.
91
91
@@ -117,24 +117,6 @@ This decision is identical at every hop because it depends only on values embedd
117
117
A relay MUST NOT use timestamps to reorder delivery beyond what {{moqt}} already permits; this property informs *dropping*, not transmission order.
118
118
119
119
120
-
# DURATION Object Property
121
-
The DURATION property carries the presentation duration of an object, in the track's Timescale.
122
-
It is optional and is an object-level Key-Value-Pair with an even Type:
123
-
124
-
~~~
125
-
DURATION Object Property {
126
-
Type (vi64) = 0x915C4
127
-
Value (vi64) ; presentation duration, in Timescale units
128
-
}
129
-
~~~
130
-
131
-
**Value**:
132
-
The presentation duration of the object, expressed in the track's Timescale.
133
-
A value of `0`, or the absence of the property, means the duration is unknown; the object is presented until the next object begins.
134
-
135
-
Duration is primarily an application-level presentation hint, but a relay MAY also use it to refine age-based dropping: an object's Timestamp plus its Duration marks the end of its presentation interval, which is a more precise "this object is now in the past" signal than the Timestamp alone (for example, the last object of a group has no following object to bound it). A relay MUST NOT rely on Duration being present; when it is absent, the relay falls back to comparing Timestamps as in [Age-Based Dropping](#age-based-dropping).
136
-
137
-
138
120
# Security Considerations
139
121
Timestamps expose the media timeline to relays, which is the point of the extension, but a relay still treats payloads as opaque and gains no access to media content.
140
122
@@ -147,7 +129,7 @@ Because age-based dropping only affects which objects a live subscription receiv
147
129
148
130
This document requests the following registrations.
149
131
High, distinctive values are requested to avoid the low ranges reserved by {{moqt}} and to minimize collisions with provisional registrations by other extensions; they also avoid the greasing pattern (`0x7f * N + 0x9D`).
150
-
The three property Types are even so that each value is a bare varint with no length prefix (see {{moqt}} Section 2.5).
132
+
The property Types are even so that each value is a bare varint with no length prefix (see {{moqt}} Section 2.5).
151
133
152
134
## MOQT Setup Options
153
135
@@ -165,7 +147,6 @@ This document requests registrations in the "MOQT Properties" registry ({{moqt}}
0 commit comments