| Internet-Draft | MoQ FEC | October 2026 |
| Ramadan | Expires 17 April 2027 | [Page] |
- Workgroup:
- moq
- Internet-Draft:
- draft-ramadan-moq-fec-00
- Published:
- Intended Status:
- Standards Track
- Expires:
Forward Error Correction for Media over QUIC
Abstract
This document specifies a mechanism for transmitting Forward Error Correction (FEC) repair data alongside source media in Media over QUIC (MoQ) sessions. It defines catalog-based signaling of FEC configuration -- including a derived RaptorQ Object Transmission Information that requires no in-session messages -- conventions for repair track naming, the format of repair objects, and the ISO/IEC 23008-1 block profile that fixes how source symbols and FEC blocks are formed and identified. RaptorQ (RFC 6330) is the mandatory-to-implement and only fully specified FEC scheme; an algorithm registry provides extension points for additional schemes. FEC enables receivers to recover from packet loss without retransmission latency. This specification is designed for compatibility with ATSC 3.0 (A/331) and ARIB STD-B60 broadcast systems.¶
Status of This Memo
This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.¶
Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is at https://datatracker.ietf.org/drafts/current/.¶
Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."¶
This Internet-Draft will expire on 17 April 2027.¶
Copyright Notice
Copyright (c) 2026 IETF Trust and the persons identified as the document authors. All rights reserved.¶
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Revised BSD License.¶
1. Introduction
Media over QUIC (MoQ) [I-D.ietf-moq-transport] provides a publish/subscribe transport for real-time media. While QUIC provides reliable delivery through retransmission, the latency incurred by retransmission can be unacceptable for ultra-low-latency (ULL) applications such as live sports, gaming, and interactive broadcasts.¶
Forward Error Correction (FEC) enables receivers to recover lost packets using redundant repair data, without waiting for retransmissions. This is particularly valuable in wireless environments where burst packet loss is common.¶
This document defines:¶
- A catalog extension carrying the complete FEC configuration, which is authoritative for MoQ receivers¶
- A normative derivation of the RaptorQ Object Transmission Information (OTI) from the catalog fields and the Repair FEC Payload ID of each block, so that catalog-only receivers (including multicast and sessionless receivers) can fully configure their decoders¶
- A naming convention for repair tracks¶
- The format of repair objects containing FEC symbols, and the block
profile
iso-ssbg1-v1, which forms source symbols and FEC blocks as Annex C of [ISO.23008-1] does¶ - Interleaving strategies to protect against burst loss¶
- Relay tolerance requirements that keep FEC signaling extensible¶
- Compatibility mappings for ATSC 3.0 and ARIB STD-B60 [ARIB-B60] broadcast systems¶
The mechanism protects MMTP-packaged tracks [MOQ-MMT]; Section 7.3 of this document specifies the protected source symbol, and Section 13 describes the relationship to CMAF packaging informatively.¶
2. Terminology
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.¶
Source Track: A MoQ track carrying media data (e.g., video, audio).¶
Repair Track: A MoQ track carrying FEC repair symbols for a corresponding source track, as MMTP FEC repair packets ([ISO.23008-1] Section C.4.3). The layer-0 repair track (Section 6.3) carries the FEC repair flow ([ISO.23008-1] 3.1.9) that an ISO AL-FEC message names for the source track's FEC encoded flow (3.1.7); further repair layers (Section 6.3) and a keyframe overlay (Section 6.4) are repair tracks that only the catalog declares ([MOQ-MMT] Section 8.3).¶
Source Block: A sequence of SSB_length source symbols,
1 <= SSB_length <= K, over which FEC encoding is performed, where
SSB_length is the block's source symbol count (Section 7.1) and K the
track's sourceSymbols (Section 5.1); the ISO source symbol block
(3.1.34), generated from a source packet block (3.1.32). A block of
SSB_length source symbols is an [RFC6330] source block whose K, in
the notation of [RFC6330], is SSB_length; this document's K is the
catalog bound instead. The extension of that source block to K'
symbols by padding ([RFC6330] Section 5.3.1) happens inside the
encoder and the decoder and is not visible on the wire, and this
document defines no K' of its own.¶
Source Symbol: A fixed-size unit of source data used for FEC encoding; under the block profile of this document, one FEC source packet framed as Section 7.3 specifies.¶
Repair Symbol: A symbol generated by the FEC encoder that can be used to recover lost source symbols.¶
FEC Block: The combination of SSB_length source symbols and P repair symbols; the ISO encoding symbol block (3.1.5).¶
Repair Layer: One of possibly several repair tracks protecting the
same source blocks of a source track, each carrying a disjoint range of
the block's repair symbols (Section 6.3). All layers of a source track
share one source block partition and differ only in how many repair
symbols they carry. Layer 0 is the track named by repairTrack.¶
Layer Index: The integer repairLayer giving a layer's position in
the ordered set of repair layers of one source track. Layer 0 is the
base layer; enhancement layers are numbered contiguously from 1.¶
RS_ID Offset: The first Repair Symbol ID a layer may use; O_i for layer i (Section 6.3.2).¶
Keyframe Overlay: A second, independent FEC instance over a source
track whose source symbols are only the fragments of Random Access
Points, with its own source symbol count, its own repair symbols, and
its own repair track, declared with "scope": "keyframe"
(Section 6.4). An overlay is not a repair layer and carries no layer
index.¶
Interleave Depth: When positive, the complete time span, in
milliseconds, of one FEC source/repair packet block, signaled as
interleaveDepthMs (Section 5.1); the catalog form of
protection_window_time in [ISO.23008-1] Sections 11.2 and C.6.3.
Zero selects the ISO packet-count alternative and is not a millisecond
span.¶
Object Transmission Information (OTI): Parameters required to configure a RaptorQ decoder, as defined in [RFC6330].¶
SS_ID: The 32-bit sequence number of a source symbol, carried in the Source FEC Payload ID of its FEC source packet ([ISO.23008-1] Section C.5.2). It advances by one per FEC source packet and wraps modulo 2^32 (Section 7.5).¶
SS_Start and SSB_length: The first SS_ID of a source block and the block's source symbol count, carried in the Repair FEC Payload ID of every repair packet of the block (Section 7.1). A block is the SS_ID range [SS_Start, SS_Start + SSB_length) and is identified by its SS_Start; this document defines no block number.¶
Block Profile: The rules that fix how a source symbol is formed
from a source packet and how FEC blocks are sized, delimited and
identified, named per FEC-protected source track by fec.blockProfile
(Section 5.1).¶
3. Protocol Overview
The protocol operates as follows (Appendix A.1 shows the exchange):¶
- Subscriber obtains the catalog and reads the track's
fecobject (Section 5), which carries the complete FEC configuration¶ - Subscriber sends SUBSCRIBE for source track¶
- Publisher responds with SUBSCRIBE_OK¶
- Subscriber sends SUBSCRIBE for the repair track if FEC protection is desired (Section 6.2)¶
- Publisher sends source objects and repair objects¶
- Subscriber configures its decoder from the catalog fields and the Repair FEC Payload ID of each block (Section 4.2) and uses repair symbols to recover any lost source symbols¶
The catalog is the subscriber's authoritative FEC configuration; the subscriber needs no other FEC signaling (Section 5.2).¶
When source objects are delivered as QUIC datagrams (unreliable), FEC recovery is the primary loss mitigation mechanism. When delivered as QUIC stream objects (reliable), QUIC retransmission handles loss and FEC is redundant -- receivers MAY skip FEC decoding in this case.¶
4. FEC Configuration
This section defines the FEC algorithm identifiers and the decoder parameters that constitute a track's FEC configuration, which is signaled in the catalog (Section 5.2); for RaptorQ, the full RFC 6330 Object Transmission Information is derived from the catalog fields (Section 4.2) rather than carried on the wire.¶
4.1. FEC Algorithms
FEC algorithm values are registered in the "MoQ FEC Algorithms" registry (Section 15.2); the catalog (Section 5.1) carries the corresponding string identifiers.¶
RaptorQ (0x01): RaptorQ fountain code per [RFC6330]. Can recover from loss of any symbols as long as K symbols (source or repair) are received. It is the mandatory-to-implement scheme (Section 4.3).¶
Reed-Solomon (0x02): Reed-Solomon erasure code over GF(2^8) per [RFC5510]; an extension point not specified by this document (Section 4.3).¶
4.2. RaptorQ Object Transmission Information
An RFC 6330 decoder is configured by the Object Transmission Information (OTI): the 8-byte Common FEC OTI (Section 3.3.2 of [RFC6330]) and the 4-byte Scheme-Specific FEC OTI (Section 3.3.3 of [RFC6330]), totaling 12 bytes:¶
RaptorQ OTI {
Transfer Length (40),
Reserved (8),
Symbol Size (16),
Number of Source Blocks (8),
Number of Sub-Blocks (16),
Symbol Alignment (8),
}
¶
This specification does not carry the OTI on the wire. When a
track's catalog fec.algorithm is "raptorq", receivers MUST
construct the OTI of each FEC block from the catalog fields
(Section 5.1) and the block's SSB_length, which every repair packet
of the block carries (Section 7.1), under the source symbol
construction of Section 7.3, as follows:¶
-
Transfer Length: F = SSB_length x T, where SSB_length is the
block's source symbol count (Section 7.1) and T is
symbolSize, exact because every source symbol of the construction of Section 7.3 is exactly T bytes. It is never computed from the cumulative size of source objects, which a receiver that has lost objects could not know, and never fromsourceSymbols, which bounds SSB_length but is not the size of any particular block (Section 7.4). From this F an [RFC6330] decoder derives that document's K as SSB_length, and from K its own K' ([RFC6330] Section 5.3.1).¶ -
Symbol Size: T =
symbolSize.¶ - Number of Source Blocks: Z = 1. Each FEC block of this specification is decoded as an independent RFC 6330 object containing a single source block. Blocks are identified by the SS_Start of the Repair FEC Payload ID of repair objects (Section 7.1), and source symbols are placed in them by SS_ID (Section 8.3) -- not by the RFC 6330 Z partitioning.¶
- Number of Sub-Blocks: N = 1. Catalog-signaled sessions do not use sub-blocking (Section 7.3).¶
-
Symbol Alignment: Al = 8.
symbolSizeMUST be a multiple of 8.¶
This derivation is normative and complete: a receiver that has a
track's catalog fec object requires no additional signaling to
configure its decoder (Section 5.2). Its one per-block input, SSB_length, travels in the Repair FEC Payload ID of every repair packet of the
block, so a receiver holding any repair symbol of a block holds the block's SSB_length.¶
4.3. Other FEC Algorithms
RaptorQ is the mandatory-to-implement FEC scheme: an implementation that performs FEC decoding under this specification MUST support "raptorq". It is also the only algorithm this document fully specifies.¶
The algorithm registry (Section 15.2) provides an extension point for additional schemes. In particular, "reed-solomon" (0x02) is allocated for a Reed-Solomon erasure code over GF(2^8) [RFC5510], but its symbol construction, parameter derivation, and repair object semantics are not specified by this document; a future companion specification is required before it can be used interoperably.¶
A receiver that does not implement a track's signaled
fec.algorithm simply forgoes FEC protection for that track: it
consumes the source track normally and does not subscribe to the
repair track. Repair-track subscription is optional (Section 6.2),
so an unrecognized or unimplemented algorithm is not an error.¶
5. Catalog FEC Extension
5.1. Catalog Fields
The catalog (Section 5.2) is an MSF catalog
[I-D.ietf-moq-msf], extended by the documents of this suite as
described in [MOQ-MMT] Section 12, and is delivered on the track
named catalog ([I-D.ietf-moq-msf] Section 5). This document
adds one track-level field -- the fec object defined below -- and
one packaging value (fec-repair, below). The FEC configuration
is carried at the track level:¶
{
"tracks": [
{
"name": "video",
"packaging": "mmtp",
"mmtpMode": "mfu",
"timescale": 90000,
"presentationAnchorTicks": 0,
"groupDurationMs": 1000,
"codec": "avc1.64001f",
"width": 1920,
"height": 1080,
"framerate": 30,
"fec": {
"algorithm": "raptorq",
"blockProfile": "iso-ssbg1-v1",
"sourceSymbols": 625,
"repairSymbols": 125,
"symbolSize": 1000,
"interleaveDepthMs": 1000,
"reorderToleranceMs": 40,
"repairTrack": "video/repair"
}
},
{
"name": "video/repair",
"packaging": "fec-repair",
"depends": ["video"],
"repairSymbols": 125,
"priority": 240
}
]
}
¶
(Appendix B works this parameter set through in full.)¶
Field definitions:¶
algorithm (string, REQUIRED if fec present): FEC scheme identifier.¶
- "none": No FEC¶
- "raptorq": RaptorQ per RFC 6330 (mandatory to implement, Section 4.3)¶
- "reed-solomon": Reserved extension point (Section 4.3); not specified by this document¶
blockProfile (string, REQUIRED when algorithm is not "none"):
The block profile of the track's
FEC: the rules that fix how a source symbol is formed from a source
packet, how many source symbols a block holds, how a block and the
source symbols in it are identified, and how those identifiers wrap.
It applies to every FEC instance of the source track, its repair
layers (Section 6.3) and any keyframe overlay (Section 6.4) included,
and a repair track carries no blockProfile of its own
(Section 6.3.4, rule 8). A publisher MUST NOT change a published
track's blockProfile; a different profile is a different rendition.
A fec object whose algorithm is "none" declares no FEC instance
and need not carry blockProfile.
This document defines exactly one value:¶
- "iso-ssbg1-v1": the ISO/IEC 23008-1 Annex C profile of this
document, all of whose rules a receiver applies together. A
source symbol is the ssbg_mode1 framing of one FEC source packet
(Section 7.3). A block holds SSB_length source symbols, with
sourceSymbolsas the upper bound on SSB_length (Section 7.4). SS_IDs advance by one per FEC source packet, blocks are consecutive, and a source symbol is placed in its block by range membership (Section 8.3). SS_ID arithmetic is modulo 2^32, and a block's repair objects are grouped under its 62-bit extended SS_Start (Section 7.5). An in-band AL-FEC message that describes such a track carries the coding byte 0x14 (Section 7.3).¶
A receiver MUST NOT apply FEC to a track whose blockProfile is
absent or names a profile the receiver does not implement. It treats
FEC as unavailable for that track, as for an unimplemented
algorithm (Section 4.3): it consumes the source track without FEC
and does not subscribe to or join the track's repair tracks, and it
MUST NOT fail the session, or FEC for any other track, on that
account. There is no default profile, and a receiver MUST NOT infer
one from the wire, whether from the fields of an in-band AL-FEC
message, from the length of the source packets it receives, or from
any other observation.¶
sourceSymbols (integer, REQUIRED): K, the largest number of source
symbols an FEC block may hold. MUST be >= 1. It is an upper bound,
not the size of each block: a block holds SSB_length source
symbols, 1 <= SSB_length <= K (Section 7.4). It is the value an in-band
AL-FEC message carries as maximum_k_for_repair_flow
([ISO.23008-1] Clause C.6.3), which is likewise a maximum.¶
repairSymbols (integer, REQUIRED): P value - repair symbols per FEC block. MUST be >= 1 when a repair track is published.¶
symbolSize (integer, REQUIRED): T value - bytes per symbol. All
symbols in a block have the same size; the byte layout of each source
symbol is fixed by the track's blockProfile -- for "iso-ssbg1-v1",
the ssbg_mode1 construction of Section 7.3, under which a source
packet of up to T - 2 bytes is protected -- and is not otherwise
carried in the catalog. For "raptorq", T is a multiple of 8, the
fixed Symbol Alignment of the derived OTI (Section 4.2).¶
interleaveDepthMs (integer, OPTIONAL): When present, its value MUST
be a non-negative integer. A value greater than zero is the complete
FEC source/repair packet send span in milliseconds. It is the catalog
form of protection_window_time in
[ISO.23008-1] Sections 11.2 and C.6.3: the actual elapsed time from
sending the first source or repair packet of a block to sending the
last source or repair packet of that block MUST NOT exceed this value.
For a positive value it is a duration, never a count of frames, groups,
samples, or symbols, and never a per-symbol interval.¶
This field does not select FEC block boundaries, the number of source
symbols in a block, the number of blocks in a MoQ Group, or the number
of groups a block spans. Those are determined by the consecutive
source SS_ID values and the (SS_Start, SSB_length) carried by the
block's repair packets (Sections 7.4 and 8.3). A block MAY contain
part of a Group, one Group, or several Groups, and a Group MAY contain
more than one block.¶
Thus interleaveDepthMs and groupDurationMs are not inputs to block
assignment; Section 8.3 specifies the source-symbol range and repair
packet fields that assign a source symbol to a block.¶
When present with a value greater than zero, a publisher chooses this
value to cover the actual source/repair send span of every block. An
absent field supplies no catalog-signaled span. A value of zero has
the ISO meaning of using protection_window_size instead of a time
window [ISO.23008-1] Clause C.6.3; this catalog profile carries no
packet-count window. A catalog-only receiver therefore MUST NOT treat
zero as a zero-duration span or use it to derive a block count, and has
no elapsed-time FEC deadline from this field. If an applicable ISO
packet-count window is accepted in-band, it governs separate
count-based processing; it does not supply a millisecond deadline, and
the receiver MUST NOT assume a media cadence to convert it. Without an
elapsed-time deadline, open-block state is bounded only by the local
policy of Section 9, and on a multicast or AMT leg the receiver
performs no block classification or unicast repair (Section 11.4) and
keeps its repair-layer selection fixed (Section 6.3.6).¶
Note: the iso-ssbg1-v1 token is unchanged from an earlier revision of
this document that derived the number D of Groups per block from this
field and read an absent or zero value as one group duration (D = 1),
so receivers implementing that derivation must change in lockstep with
producers.¶
reorderToleranceMs (number, OPTIONAL): A receiver-local allowance for packet reordering, network jitter, and local processing variance, in milliseconds. When present, the value MUST be finite and MUST be greater than or equal to zero; fractional values are permitted. An explicit value of zero means that no additional allowance is required. An omitted field means that the publisher did not signal an allowance; receivers MUST preserve that distinction from an explicit zero.¶
For a receiver that uses a positive interleaveDepthMs, the FEC block
deadline is the receiver-local timestamp of the first accepted packet
plus the complete block span. When reorderToleranceMs is present,
its catalog allowance is then added:¶
base_deadline = firstAcceptedAtMs + interleaveDepthMs deadline = base_deadline + reorderToleranceMs // when present¶
The catalog allowance is added exactly once when present. Its absence
is not equivalent to an explicitly signaled zero; a receiver that
applies an explicit local policy MUST keep that policy separate from
the catalog value. When interleaveDepthMs is absent or zero, this
formula supplies no elapsed-time FEC deadline; an applicable ISO
packet-count window, if accepted in-band, remains separate count-based
processing and is not converted to milliseconds. A receiver whose
FEC deadline API requires a signaled allowance MUST reject or disable
FEC for a track that omits reorderToleranceMs.¶
repairTrack (string, REQUIRED): Track name for repair symbols, following the convention in Section 6.1.¶
Repair tracks themselves are identified in the catalog by the
packaging value "fec-repair": a track with
"packaging": "fec-repair" carries repair objects (Section 7) for
the source track whose fec.repairTrack field names it, and
carries no directly renderable media. The value extends the
allowed packaging values of [I-D.ietf-moq-msf] Section 5.2.4 in
the same manner as the cmaf value of [I-D.ietf-moq-cmsf]; see
Section 15.3. Receivers that do not
implement this specification do not recognize the value and ignore
such tracks.¶
enhancementRepair: Not defined. Repair layers and keyframe overlays are declared on their own repair-track entries (Section 5.1.1), and a catalog carrying this member is rejected under the exceptions there.¶
5.1.1. Repair Track Fields
A track with "packaging": "fec-repair" describes its own role. It
carries the flat MSF track fields plus the fields below. Layer 0 is
identified by the source's fec.repairTrack; its entry MAY also carry
depends, "repairLayer": 0 and repairSymbols, which MUST agree
with the source's corresponding field when present (Section 6.3.4,
rules 2 and 11).¶
depends (array of strings, REQUIRED except on layer 0): The name
of the source track this track repairs. The
array MUST contain exactly one name, and that name MUST identify a
track in the same catalog whose packaging is mmtp and which
carries an fec object.¶
repairLayer (integer, REQUIRED on enhancement layers, OPTIONAL on layer 0, MUST NOT appear on an overlay): The layer index (Section 6.3).¶
repairSymbols (integer, REQUIRED except on layer 0; MUST be¶
= 1): The repair symbols per block that this track carries, P_i. For layer 0 the source track's
fec.repairSymbolsis the authoritative P_0 (Section 6.3.4, rule 11).¶
priority (integer, OPTIONAL): The MoQ Transport priority of this track (Section 10), in the range 192 to 255.¶
scope (string, OPTIONAL): When present, MUST be "keyframe", and
declares this track to be the source track's keyframe overlay
(Section 6.4). It is one of the unknown-key exceptions below.¶
sourceSymbols (integer, REQUIRED on an overlay, MUST NOT appear otherwise): The overlay instance's own K, the upper bound on the SSB_length of its blocks (Section 7.4).¶
Track names carry no meaning in any of this. A receiver MUST resolve
every relationship from fec.repairTrack, depends, repairLayer
and scope, and MUST NOT infer one by parsing a track name or a name
suffix.¶
A receiver MUST ignore a track-level or fec object key that it does
not recognize, and MUST NOT treat its presence as an error, so that
this suite can add fields without a flag day. Exactly three keys
defined by this document are exceptions, because ignoring any of them
would change how the receiver must interpret the packets it receives:¶
-
fec.enhancementRepair: a receiver MUST reject a catalog carrying it.¶ -
scope: a receiver that does not implement overlays MUST fail closed on a catalog carrying it (Section 6.4).¶ -
fec.blockProfile: a receiver MUST NOT apply FEC to a track whoseblockProfilenames a profile it does not implement (Section 5.1).¶
5.1.2. Worked Catalog
Three repair layers and one keyframe overlay on one source track:¶
{
"tracks": [
{
"name": "video",
"packaging": "mmtp",
"mmtpMode": "mfu",
"timescale": 90000,
"presentationAnchorTicks": 0,
"groupDurationMs": 1000,
"codec": "avc1.64001f",
"width": 1920,
"height": 1080,
"framerate": 30,
"fec": {
"algorithm": "raptorq",
"blockProfile": "iso-ssbg1-v1",
"sourceSymbols": 64,
"repairSymbols": 8,
"symbolSize": 1200,
"interleaveDepthMs": 200,
"repairTrack": "video/repair"
}
},
{
"name": "video/repair",
"packaging": "fec-repair",
"depends": ["video"],
"repairLayer": 0,
"repairSymbols": 8,
"priority": 240
},
{
"name": "video/repair/1",
"packaging": "fec-repair",
"depends": ["video"],
"repairLayer": 1,
"repairSymbols": 16,
"priority": 244
},
{
"name": "video/repair/2",
"packaging": "fec-repair",
"depends": ["video"],
"repairLayer": 2,
"repairSymbols": 32,
"priority": 248
},
{
"name": "video/repair/kf",
"packaging": "fec-repair",
"depends": ["video"],
"scope": "keyframe",
"sourceSymbols": 256,
"repairSymbols": 32,
"priority": 242
}
]
}
¶
A receiver derives the following from that catalog, the ESI column for a full block; none of it is carried on the wire:¶
| Layer | P_i | O_i | RS_ID range | ESI range (full block, SSB_length = 64) |
|---|---|---|---|---|
| 0 | 8 | 0 | 0 to 7 | 64 to 71 |
| 1 | 16 | 8 | 8 to 23 | 72 to 87 |
| 2 | 32 | 24 | 24 to 55 | 88 to 119 |
The RS_ID ranges are fixed by the catalog. The ESI ranges are those of a full block: a repair symbol's ESI is the block's SSB_length plus its RS_ID (Section 7.2), so in a short block every ESI range moves down by 64 - SSB_length while the RS_ID ranges do not move.¶
The total repair count is 8 + 16 + 32 = 56, so RSB_length is 56 on every repair packet of layers 0, 1 and 2 (Section 7.1). The overlay is a separate FEC instance and is not in that table: its own K is 256, its own P is 32, its RS_ID range is 0 to 31, its ESI range in a full overlay block is 256 to 287, and its packets carry RSB_length 32.¶
5.2. Signaling Model
The catalog fec object (Section 5.1) is the authoritative FEC
signaling for MoQ receivers, that is for every receiver that obtains
the track's catalog entry. Such a receiver has everything needed to
discover and subscribe to the repair track (Section 6) and to
configure its decoder via the derived OTI (Section 4.2); no
in-session signaling is required.¶
A packaging profile MAY also define in-band FEC signaling carried
with the media, which serves a receiver that consumes a flow without
the catalog. For the mmtp packaging this is the AL-FEC message of
[ISO.23008-1] Clause C.6 ([MOQ-MMT] Sections 8 and 8.3).
In-band FEC signaling MUST NOT signal FEC parameters that contradict
the track's catalog fec object. Where the two disagree the catalog
governs for a MoQ receiver, and a MoQ receiver MUST NOT require
in-band signaling in order to configure its decoder.¶
The catalog's authority holds uniformly across a MoQ receiver's delivery paths, its multicast and AMT legs included. MoQ control messages cannot reach multicast or sessionless receivers at all (Section 11), so no control-message mechanism could serve as the common signaling path; the catalog can, because it is delivered as track data or out of band.¶
5.3. FEC Source Info Object Property
A publisher that carries FEC source symbols as MoQ objects MUST tag each such object with a FEC Source Info Object Property, whose type is the odd value 0x11 (Section 15.1).¶
0x11 is the value this document requests, and the registration policy for the range it lies in is not reachable by an individual draft (Section 15.1). Until that request is resolved, 0x11 is to be read as provisional. If it is not obtainable, Section 15.1 names an odd value in the range 0x80 to 0x37FF as the fallback; that value is a 2-byte Delta Type, so adopting it changes the bytes on the wire and not only the constant in this paragraph.¶
[I-D.ietf-moq-transport] calls these Object Properties; drafts before draft-17 called them object extension headers, and the two terms name the same wire construct. It encodes a Property as a key-value pair whose type parity selects the value encoding: an even type carries a single variable-length integer, an odd type carries a length-prefixed sequence of bytes. FEC Source Info is byte-valued, so its type is odd, and a receiver or relay that knows nothing of this document still steps over the Property correctly by its length prefix.¶
Deployed implementations have used the even value 0x10 for this
purpose. That value is not available: [I-D.ietf-moq-transport]
already lists 0x10 as the TIMESTAMP Object Property of
draft-ietf-moq-loc, in the same Property Type space and at the same
Object scope. A 0x10-tagged FEC object is therefore not merely
unparseable under the parity rule; it is a semantic collision with an
unrelated Property. A receiver that implements TIMESTAMP parses the
FEC Source Info value as a variable-length integer, yields a garbage
timestamp, and then reads the next Property type out of the middle of
the FEC Source Info bytes. The key-value sequence is desynchronized
from that point on, so the exchange ends in a session closure rather
than in a quietly wrong value. Which closure depends on where the
desynchronized parse lands: a Delta Type read out of the FEC Source
Info bytes that overflows 2^64-1, or a Length that exceeds 2^16-1,
is a PROTOCOL_VIOLATION; a type that is understood but whose value
does not match its serialization is a KEY_VALUE_FORMATTING_ERROR.
This is why implementations
that use 0x10 must special-case the type ahead of the parity rule to
interoperate at all. An implementation of this document MUST NOT
send 0x10. The defence is necessarily publisher-side: a receiver
cannot detect a 0x10-tagged FEC object as such, because by
construction it is indistinguishable from a well-formed TIMESTAMP
until the following Delta Type fails. A receiver cannot reject a
0x10 Property and carry on,
because the sequence is already desynchronized by the time the value
has been mis-parsed; it MUST close the session as
[I-D.ietf-moq-transport] requires.¶
The Property value is:¶
FEC Source Info {
SS_ID (32),
}
¶
SS_ID is an unsigned integer in network byte order. It is the sequence number of the source symbol the object carries (Section 2), the same value and the same definition that the Source FEC Payload ID trailer of a FEC source packet carries on the MMTP path (Section 8.5). This Property is that trailer's MoQ-layer carrier: one identifier, one definition, whichever path the symbol travels.¶
Where the packaging also delivers the trailer, both carry the same value and a publisher MUST make them identical. On the mmtp packaging of [MOQ-MMT] that is every source object, because the object payload is the whole FEC source packet, trailer included. The Property is wanted there as well: it places the symbol at the MoQ layer, reachable by a relay and by a receiver that does not parse MMTP, whereas the trailer is the field the FEC encoder emitted and the one Section 8.3 locates the symbol by. Where the two disagree the trailer prevails (Section 8.5). A packet the decoder recovers carries neither (Section 7.3): the Property is not recovered with the object, and the trailer is appended after FEC encoding, so a receiver that recovers a packet determines its SS_ID from the block coordinate that recovered it, within that FEC instance's SS_ID space (Section 6.4.1); an overlay coordinate does not yield a base SS_ID (Section 7.3).¶
Where a keyframe overlay applies (Section 6.4), an object carrying a Random Access Point fragment is a source symbol of two FEC instances, whose SS_ID spaces are disjoint (Section 6.4.1), so "the source symbol the object carries" names two SS_IDs rather than one. This Property carries the base instance's SS_ID -- the value the Source FEC Payload ID trailer carries on the MMTP path (Section 8.5.1) -- and a publisher MUST NOT place an overlay SS_ID in it. No second Property conveys the overlay SS_ID: it travels in the 0x8B01 MMTP header extension, which lies inside the MMTP packet header and is therefore part of the protected packet of both instances (Section 8.5.1), so it rides inside the object's payload on this path as on any other. A receiver takes an overlay SS_ID from that extension and from nothing else, and in particular MUST NOT infer one from this Property (Section 8.5.1).¶
A receiver places the symbol in a block by SS_ID (Section 8.3) and
learns the block's extent from the (SS_Start, SSB_length) of a repair
object (Section 7.1), exactly as on the MMTP path. The Property
carries no block coordinate, and a receiver MUST NOT infer one from
it: the constraints of Section 7.4 on delimiting a block apply
unchanged to a MoQ receiver, so it MUST NOT infer a block boundary,
or SSB_length, from a gap in SS_IDs, from a group or MPU boundary --
which for a MoQ receiver includes a Group boundary -- from elapsed
time, or from sourceSymbols. Until it has
accepted a repair object of the block it holds the symbol without
placing it, as Section 8.3 describes.¶
An object that carries a source symbol but no FEC Source Info Property violates the publisher requirement that opens this section. A receiver that does not parse the FEC source packet has no SS_ID for it -- at the MoQ layer the Property is the only carrier -- so it MUST NOT feed such an object to the base decoder and MUST NOT count it in K or in any base block, and MAY still deliver it as media. Where the packaging delivers the trailer, a receiver that parses the packet MAY take the SS_ID from there instead (Section 8.3). An overlay SS_ID is unaffected either way: it travels in the 0x8B01 MMTP header extension (Section 8.5.1), which this Property does not carry, and Section 8.5.1 alone governs when the overlay decoder may be fed.¶
The value is exactly 4 bytes. A value of any other length does not
match the serialization defined for this type, so a receiver that
implements this document MUST close the session with
KEY_VALUE_FORMATTING_ERROR, as [I-D.ietf-moq-transport] requires
of any Property whose type is understood and whose value does not
match.¶
SS_ID is a fixed 32-bit field rather than a variable-length integer for two reasons. First, [I-D.ietf-moq-transport] does not require its variable-length integers to be encoded in the minimum number of bytes, so one numeric value has several valid encodings that differ in length; a varint field inside the Property value would therefore vary the Property's own length without varying its meaning. Second, the encoding is a property of the session: [I-D.ietf-moq-transport] replaced it at draft-17 (transport issue 1016) with a leading-1-bits scheme that is not the QUIC variable-length integer encoding of earlier drafts and does not decode the same bytes to the same values, so a varint field following the session encoding would decode differently on two drafts. A fixed width removes both. A publisher and a receiver that negotiated different session versions, and a relay that re-encodes between them, decode this field identically.¶
This Property carries no object length. A receiver that recovers an
object by FEC decoding receives no Properties with it, so a length
carried here would be absent in exactly the case a recovered length is
wanted. The recoverable length is the Length field inside the
source symbol itself (Section 7.3), which is recovered with the
symbol. Under the source symbol
construction of Section 7.3 the padding that completes a symbol is
applied by the encoder and decoder and is not transmitted, so there is
no transmitted padding for a receiver to strip.¶
5.4. Relay Extensibility Requirements
Relays conforming to this specification are subject to the following requirements:¶
-
A relay MUST NOT terminate, reset, or otherwise fail a session in response to a control message whose type it does not recognize. Such messages MUST be ignored.¶
-
A relay MUST NOT terminate, reset, or otherwise fail a session in response to an Object Property whose type it does not recognize. Such Properties MUST be forwarded unmodified to downstream subscribers; a relay MUST NOT strip them.¶
6. Repair Track Convention
6.1. Track Naming
For a source track with name components [namespace, track_name], the corresponding repair track MUST be named:¶
[namespace, track_name, "repair"]¶
Examples:¶
| Source Track | Repair Track |
|---|---|
| ["live", "video"] | ["live", "video", "repair"] |
| ["broadcast", "video", "1080p"] | ["broadcast", "video", "1080p", "repair"] |
| ["stream", "audio", "en"] | ["stream", "audio", "en", "repair"] |
These name components are commonly rendered in slash-separated form for URIs and logging (e.g., "live/video" and "live/video/repair"); the normative form is the tuple.¶
The convention covers layer 0 only, and it is a convention rather than
a resolution mechanism. Enhancement layers (Section 6.3) and a
keyframe overlay (Section 6.4) have no required name: they are
resolved from depends, repairLayer and scope on their own
catalog entries (Section 5.1.1). A receiver MUST NOT infer that a
track is a repair track, which source it repairs, or which layer it
is, by parsing a track name or a name suffix, and a publisher MUST NOT
rely on a receiver doing so. Names such as "video/repair/1" appear in
the examples of this document for readability only.¶
6.2. Subscription Model
Subscribers SHOULD subscribe to the source track first, then subscribe to the repair track if:¶
- The track's catalog entry signals FEC (a
fecobject naming arepairTrack, Section 5.1), AND¶ - The subscriber desires FEC protection¶
Repair-track subscription is selective and per-need: a subscriber chooses whether to consume repair data based on its own path conditions, and MAY start or stop its repair-track subscription at any time during the session -- for example, subscribing only after observing loss, or not subscribing at all on a reliable path.¶
Publishers and relays MUST NOT require subscription to repair tracks and MUST NOT condition delivery of a source track on a repair-track subscription. Repair tracks are optional; subscribers MAY choose to rely solely on QUIC retransmission or to accept unrecovered loss.¶
6.3. Layered Repair Tracks
A source track MAY be protected by more than one repair track. Each
such track is a repair layer: an independently subscribable set of
repair symbols for the same source blocks. Layer 0 is the repair
track named by repairTrack, carrying the source's repairSymbols
symbols per block. Layers 1..n are the tracks that name this source
in depends and carry a repairLayer (Section 5.1.1), one track per
layer index.¶
Layered repair is an extension of [ISO.23008-1] that an ISO AL-FEC
message cannot express: each FEC source flow has one FEC encoded flow,
whose one-stage coding structure carries a single repair_flow_id
([ISO.23008-1] Clause C.6.3), so only layer 0 maps to an ISO repair
flow. An in-band AL-FEC message names layer 0 and no other layer
([MOQ-MMT] Section 8.3). A repair layer is also unrelated to the
layers of ISO layer-aware FEC (LA-FEC, Clause C.2.3).¶
Layering separates the two costs of FEC: the repair count P buys
tolerance to random loss at a cost in bandwidth, and the interleave
window buys tolerance to burst loss at a cost in recovery latency
(Section 9). Layers let a receiver on a lossier path add repair
without changing the source encoding. A source track names only
layer 0; each further layer declares itself on its own tracks
entry, so the layer set is validated as a whole (Section 6.3.4) and
changed only as Section 6.3.9 allows. A relay that forwards a subset
of a catalog MUST NOT forward a fec-repair track whose source track
it does not forward (Section 6.3.4, rule 9).¶
6.3.2. Repair Symbol Identity Across Layers
Let P_i be the repairSymbols of layer i and O_i its RS_ID offset,
defined below (O_0 = 0). P_0 is the source track's
fec.repairSymbols (Section 6.3.4, rule 11), and P_i for i >= 1 the
layer track's own repairSymbols. Layer i carries, for every source
block, the repair symbols with RS_ID in [O_i, O_i + P_i). The
Encoding Symbol ID follows the single-layer rule of Section 7.2:¶
O_i = sum(P_j for j < i) RS_ID = O_i + j, for the j-th symbol of layer i ESI = SSB_length + RS_ID¶
where SSB_length is the block's source symbol count (Section 7.1).¶
The total repair count of the block is the sum of P_i over all
published layers. RSB_length on every repair packet of every layer
carries this total (Section 7.1), not the layer's own P_i. That is
what makes the RS_ID to ESI mapping independent of which layers a
given receiver joined: a receiver holding a non-prefix subset computes
the same coordinate for a symbol as a receiver holding everything, and
the RS_ID < RSB_length bound holds for a symbol from any layer.¶
Because RaptorQ repair symbols are identified by ESI alone and any set of distinct encoding symbols of a block decodes together ([RFC6330]), symbols received from any subset of layers, over any mix of paths, combine in one decode. Subsets need not be prefixes: in the worked catalog of Section 5.1.2 a receiver holding layers 0 and 2 holds, for a full block, ESIs 64 to 71 and 88 to 119, which are distinct encoding symbols of one code, and it decodes as soon as it holds enough distinct symbols in total.¶
A receiver that has subscribed a set of layers recovers a block whenever the number of lost symbols, source and repair together, does not exceed C - e, where C is the total P over the layers it holds and e is the RaptorQ decoding overhead (roughly 1e-2, 1e-4, and 1e-6 residual failure at 0, 1, and 2 symbols of overhead per [RFC6330]). This loss tolerance is derived from K and the layer counts; it MUST NOT be signaled as a separate catalog field.¶
Receivers MUST take layer membership and per-layer counts from the catalog. RSB_length carries the total and says nothing about which layers a receiver holds.¶
On layer i, the block's repair objects form the MoQ group whose Group ID is the block's extended SS_Start (Section 7.5), and that group carries P_i objects (Section 7); object j of that group carries the repair symbol with RS_ID = O_i + j.¶
6.3.3. Why RaptorQ Only
Repair layers and the overlay are defined only for raptorq: a
publisher MUST NOT signal either under any other algorithm, and a
receiver rejects such a catalog (Section 6.3.4, rule 7). Layering
relies on RaptorQ's open Encoding Symbol ID space, in which repair
symbols from disjoint ESI ranges on separate tracks remain symbols of
one code; a block code such as Reed-Solomon fixes n = K + P at
encoding time, so its symbols for one P are not valid for another.¶
6.3.4. Catalog Rules and Fail-Closed Validation
A receiver MUST validate all of the following for a source track before starting FEC for it. On any violation the receiver MUST fail closed: it MUST report the offending catalog path and MUST NOT start FEC for that source track. A receiver MUST NOT repair the catalog by ignoring the offending track, because every rule below distinguishes a layer set that decodes from one that silently mis-maps symbols.¶
-
dependsnames exactly one track in the same catalog, whosepackagingismmtpand which carries anfecobject.¶ - The
repairLayervalues for one source track are contiguous from 1 to n, with no gaps and no duplicates. Layer 0 is the track named by the source'sfec.repairTrack.¶ -
priority, where declared, is in the range 192 to 255 inclusive, and is monotonic non-decreasing with layer index. Layer 0's priority MAY be declared on its own track; when absent it is 240.¶ - For each FEC instance, the total of
repairSymbolsacross all its layers is at most 2^24 - 1, the range of RSB_length.¶ - For each FEC instance, K + totalP - 1 is at most 2^24 - 1, which bounds the largest ESI the instance can produce.¶
- For each FEC instance, K is at most 56403. [RFC6330] extends a source block of K source symbols to K' symbols, the smallest value at least K in its Table 2 ([RFC6330] Section 5.3.1), and 56403 is the largest such value, K'_max ([RFC6330] Section 5.1.2), so a RaptorQ source block holds at most 56403 source symbols.¶
- Repair layers and any overlay appear only when
fec.algorithmisraptorq(Section 6.3.3 above).¶ - A track whose
packagingisfec-repaircarries no geometry field, whether as a flat field or inside anfecobject of its own:algorithm,blockProfile,mmtpMode,timescale, anygroupDurationfield,symbolSize,interleaveDepthMs,reorderToleranceMs, andsourceSymbolsexcept on an overlay (Section 6.4).¶ - No orphan repair track: every track whose
packagingisfec-repairis reachable from a source track, either by being named in that source'sfec.repairTrackor by naming that source independs. This rule binds once the catalog declares any FEC source, that is any track whosefec.algorithmis notnone; a catalog that declares no FEC source at all MAY carry an unreferencedfec-repairtrack that nothing joins. This rule is the one exception to the per-source remedy of the preamble above: an orphan track is by definition associated with no source track, so there is no source track to stop. The receiver MUST refuse to join the orphan track and MUST report its catalog path, and MUST NOT stop FEC for any source track on account of it.¶ - A source track has at most one track with
"scope": "keyframe"(Section 6.4), and such a track carries norepairLayer.¶ - The layer-0 repair track's
repairSymbols, where declared, equals the source track'sfec.repairSymbols. The source field is the single authoritative value of P_0; the layer-0 track MAY restate it and MUST restate it identically. A receiver MUST reject a catalog declaring both with different values, and MUST NOT resolve the conflict by preferring either field, because the two readings disagree about O_1, about the block total, and therefore about the RSB_length that every layer's packets carry (Section 6.3.2). This rule is why rules 4 and 5 have a single well defined totalP to bound.¶
Section 6.3.9 adds one check that can only be made on received repair packets.¶
The following are the fail-closed cases this section introduces, written against the worked catalog of Section 5.1.2 (K = 64, P_0 = 8, P_1 = 16, P_2 = 32) so that each defect is one edit away from a valid catalog. Each row violates the rule shown, and none of them is detectable from the wire.¶
| Catalog defect | Rule | Why the wire cannot catch it |
|---|---|---|
video/repair declares repairSymbols 16 while the source declares fec.repairSymbols 8 |
11 | Both readings are self-consistent: one derives O_1 = 8 and total 56, the other O_1 = 16 and total 64. A repair symbol is identified by ESI alone, so a receiver that resolved P_0 the other way decodes with a shifted mapping and reports a corrupt block, not a catalog error. |
Two tracks declare "repairLayer": 1 for video
|
2 | Both claim RS_ID 8 to 23. Symbols from the two tracks are distinct on the wire but collide in ESI, so a decode fed from both sees duplicate encoding symbols and stalls short of K. |
video/repair/2 is present but no track declares layer 1 |
2 | O_2 is a function of P_1, which is absent, so the receiver has no offset for layer 2 at all. |
video/repair/kf carries "repairLayer": 3 alongside "scope": "keyframe"
|
10 | The overlay is a second FEC instance over its own K (Section 6.4). Admitting it as a layer would fold its RS_ID space into O_i and place its symbols in the base instance's ESI range. |
A second track for video declares "scope": "keyframe"
|
10 | A RAP packet carries one overlay SS_ID, in its one header extension (Section 8.5.1), so a second overlay has no SS_ID on the wire. |
video/repair/1 carries symbolSize or its own fec object |
8 | A repair track carrying its own geometry would name itself as layer 0 and bypass rule 9's reachability check. |
A receiver MAY report several violations at once.¶
6.3.5. Receiver Selection
The per-need model of Section 6.2 applies to each layer independently. On a lossy path a receiver SHOULD subscribe layer 0 first. When a block fails recovery with the receiver's current layer set and a higher layer exists, the receiver SHOULD subscribe the next layer; it MAY instead request only the failed block's repair objects from that layer, a request bounded to the block's repair group (Section 7.5), when the block is still inside its recovery budget (Section 9). On a multicast or AMT leg, Section 11.4 governs such per-block requests: which blocks get one, when, with what budget and priority, and what happens when one fails. A receiver MAY unsubscribe a layer after a receiver-chosen number of consecutive blocks whose loss stayed within the tolerance of the remaining layers. Hysteresis is counted in blocks, the protocol's unit, not by a fixed timer (Section 6.3.6).¶
6.3.6. Repair-Only Multicast Endpoints
On a multicast endpoint the receiver cannot choose tracks; the
operator of the endpoint chooses which tracks that path carries. Each
repair layer carried on an endpoint is listed with its own packetId
([MOQ-MULTICAST] Section 4.1), exactly as a source track is, and a
receiver MUST route every such packetId to the decoder of the source
track that layer depends on. Because every endpoint carries the same
source packets under the same block partition (Section 6.3.1), a
receiver that moves between endpoints, or that is side-fed over MoQ
unicast, mixes symbols from all of them in one decode. Layers not
carried on any endpoint the receiver holds remain reachable over MoQ
unicast (Section 6.2) for receivers that have a return path.¶
An operator MAY carry the source track and its layers together on one
endpoint, or MAY place layers on endpoints of their own. An endpoint
whose track list contains only fec-repair tracks is a repair-only
endpoint:¶
{
"multicast": {
"endpoints": [
{
"sourceAddress": "198.51.100.100",
"groupAddress": "232.1.1.50",
"port": 5000,
"tracks": [
{ "name": "video", "packetId": 1 },
{ "name": "video/repair", "packetId": 2 }
]
},
{
"sourceAddress": "198.51.100.100",
"groupAddress": "232.1.1.51",
"port": 5000,
"tracks": [
{ "name": "video/repair/1", "packetId": 3 },
{ "name": "video/repair/2", "packetId": 4 }
]
}
]
}
}
¶
The first endpoint suits a regional path with low random loss. The second is repair-only: a receiver on a lossy path holds both, and receives source packets once while adding layers 1 and 2 to the same decode.¶
A repair-only endpoint is never a media tier. A receiver MUST NOT
treat one as a rendition or quality choice, and endpoint or ladder
selection MUST exclude it on every path by which a receiver picks
what to render. A repair-only endpoint's bandwidth
([MOQ-MULTICAST] Section 4.1) is the cost of adding repair to a
stream the receiver has already selected, not the cost of an
alternative rendition, and MUST NOT be compared against a media
endpoint's bandwidth when choosing one.¶
A receiver joins a repair-only endpoint on measured loss: the rate at which its FEC blocks fail to recover, and the margin by which recovering blocks consume the repair symbols available to it. A receiver MUST NOT use goodput, throughput, or estimated available bandwidth to decide whether to add or drop a repair layer.¶
Layer changes are make-before-break. A receiver MUST join the additional layer's endpoint and begin receiving from it before leaving any endpoint it currently holds, so that no source block is left with less coverage than the receiver already had.¶
Hysteresis MUST derive from the FEC block span, that is from
interleaveDepthMs together with reorderToleranceMs, and MUST NOT
come from a fixed timer or a fixed symbol count. A receiver MUST
observe at least one full block span at the new layer set before
making a further layer change.¶
That loss measure and this hysteresis both need a block deadline,
which exists only for a positive interleaveDepthMs (Section 9). On a
multicast or AMT leg, a receiver of a track whose catalog omits that
field or sets it to zero MUST NOT add or drop a repair layer of the
track on block-recovery evidence, and keeps its repair-layer selection
for the track fixed.¶
6.3.7. Interaction with the Interleave Window
Layers never change interleaveDepthMs, the stream's single
recovery-latency lever (Section 9). A shallow window recovers bursts
only by per-block unicast repair (Sections 6.3.5 and 11.4.2), at about
one round trip; a deep window recovers them in band at that window's
latency. Serving both requires two renditions (Section 6.3.1).¶
6.3.8. Compatibility
A source track with a single repair track is the one-layer case
(O_0 = 0, RSB_length = repairSymbols). A receiver that subscribes
only layer 0 decodes correctly whatever other layers exist: layer 0
alone is a valid layer set, and it uses RSB_length only as the
RS_ID < RSB_length bound. The keyframe overlay is the exception: a
receiver has to recognize its declaration, because its repair packets
belong to another FEC instance (Section 6.4.3).¶
6.3.9. Changing the Layer Set Within a Session
Publishing a layer is adding one tracks entry and withdrawing it is
removing one, but the two directions are not symmetric, because O_i is
a function of every lower layer's P (Section 6.3.2). A change to the
set can therefore move the coordinates of a layer a receiver has
already joined. This subsection states which changes are defined.¶
Layer sets are append-only. A publisher MAY append a layer at the
next index above the highest published one. It MUST NOT withdraw a
published layer, at any index, for the lifetime of the source
encoding. An append changes O_i for no layer already published,
because no published layer's set of lower layers changes. It does
raise the total, so RSB_length on the wire rises, which is benign for
the reason Section 6.3.8 gives: a receiver uses the total only as the
RS_ID < RSB_length bound, so a receiver holding a catalog from
before an append reads a smaller bound that excludes only symbols of
layers it has not joined.¶
A publisher MUST NOT renumber the repairLayer of a published layer,
and MUST NOT change the repairSymbols of a published layer, while
any receiver may still be consuming the source track. Rule 2 of
Section 6.3.4 requires repairLayer to be contiguous from 1 to n, so
withdrawing a layer that is not the highest would force exactly such a
renumbering. A publisher that must retire any layer, including the
highest, retires the source encoding and publishes a separate
rendition. Supporting withdrawal directly would require a catalog
generation identifier carried on the wire, that is in-session
signaling, which Section 5.2 does not define.¶
The prohibition is not editorial, and the worked catalog of
Section 5.1.2 shows why. A receiver holding layers 0 and 2 holds,
for a full block, ESIs 64 to 71 and 88 to 119. Renumber layer 2 to
layer 1 and the same track's offset becomes O = 8, so the publisher
now labels those symbols ESI 72 to 103 while the receiver still maps
them to 88 to 119.
The receiver feeds correctly received symbols into the decoder under
wrong coordinates. RaptorQ does not detect this, because a repair
symbol is identified by its ESI alone: the result is not a reported
error but a decode that fails, or that resolves against coordinates
the symbols do not belong to. Changing a published repairSymbols
does the same to every layer above the one changed.¶
Withdrawing the highest layer forces no renumbering, but it is barred for a different reason: it is indistinguishable on the wire from the renumbering above. For the highest layer n, O_n + P_n is the total identically, so withdrawing it drops the wire RSB_length strictly below the bound derived by every receiver that had joined it, and the check below cannot tell that case from a genuine coordinate disagreement. Both present as nothing but a smaller total. The receivers holding the highest layer are also the lossiest ones, and they cannot recover by observation: absence of symbols is precisely the loss condition the layer was joined to repair, so they learn of the withdrawal only at the next catalog refresh, which this document does not bound.¶
Append-only is what makes the check below sound. RSB_length is monotonically non-decreasing over the lifetime of a source encoding, so a wire RSB_length below a held layer's O_i + P_i is always a genuine violation: no operation this document defines produces one.¶
A receiver MUST fail closed when, for any layer i it holds, the RSB_length carried on any repair packet of the same FEC instance is less than O_i + P_i derived from its own catalog: its own layer's RS_ID range does not fit under the bound the publisher is advertising, so the two disagree about coordinates the receiver is actively using. It MUST NOT treat such a packet as a symbol to discard. In the renumbering example above the total falls from 56 to 40 while the receiver's O_2 + P_2 is 56, so the check catches it.¶
That check is a backstop and not a substitute for the publisher
requirement. It does not catch a change that leaves the total at or
above the receiver's derived bound, for example an increase to a lower
layer's repairSymbols, which shifts every higher offset while
raising the total. That case is silent on the wire, which is why the
protection is the prohibition on the publisher rather than validation
at the receiver. A wire RSB_length larger than the receiver's derived
total is not an error in itself: that is the append case above.¶
6.4. Keyframe Overlay
A source track MAY additionally be protected by a keyframe overlay: a second, independent FEC instance whose source symbols are only the fragments of Random Access Points of that source track.¶
Losing part of a Random Access Point makes every dependent frame undecodable until the next one; the overlay protects RAP fragments across a block of its own, which can be wider than the base window, without changing the base instance's latency.¶
6.4.1. Overlay Instance
An overlay is a separate FEC instance over the same source track. It
has its own sourceSymbols (K_overlay) and its own repairSymbols,
declared on its own repair track, and it shares the source track's
algorithm, blockProfile and symbolSize. It does not share the
base instance's K, its block partition, its SS_ID space, or its RS_ID
space.¶
Every per-block quantity of this document -- K, the total repair count
P, SS_ID, ESI, RS_ID, SS_Start, RSB_length, SSB_length, the
short-block rules of Section 7.4, the wrap epoch and repair group IDs
of Section 7.5, and the bounds of Section 6.3.4 -- is defined within
one FEC instance. For the base instance, K is the
source track's fec.sourceSymbols and P is the sum of
repairSymbols over its published layers (Section 6.3.2); for an
overlay, K and P are the sourceSymbols and repairSymbols of its
own track. A repair packet belongs to the instance of the track it
arrived on (Section 6.4.2).¶
An overlay is not a repair layer. It carries no repairLayer, it is
not a member of the layer index chain, and it is excluded from the
contiguity and priority monotonicity rules of Section 6.3.4, which
order the base layer chain only. Its priority is independent within
192 to 255, and MAY be numerically lower than a base enhancement
layer's so that a keyframe repair symbol is delivered before an
ordinary one.¶
Overlay ESIs never collide with base ESIs because the two are different instances decoded by different decoders; a receiver MUST NOT feed a repair symbol of one instance to the decoder of the other, and MUST NOT reuse a source symbol's coordinate in one instance as its coordinate in the other. A RAP source packet is a source symbol of both instances, at an unrelated coordinate in each (Section 6.4.2).¶
A source track has at most one overlay (Section 6.3.4, rule 10), a wire constraint explained in Section 8.5.1. An overlay is declared only by the catalog, never in an in-band AL-FEC message, and only where no FEC source or repair packet carries FFSRP_TS (Section 8.5.1).¶
6.4.2. Overlay Membership
The overlay's source symbols are the fragments of the source track
that belong to a Random Access Point, in transmission order. A
publisher that declares an overlay MUST set RAP_flag on a source
packet of the track, MUST include the packet in the overlay instance,
and MUST carry the packet's overlay SS_ID in its 0x8B01 header
extension (Section 8.5.1), if and only if that packet's payload
belongs to a keyframe MFU covered by the overlay.¶
Overlay source symbols are numbered consecutively within the overlay
instance, in the order the publisher emits them: the overlay SS_ID is
0 at the first overlay source symbol of the stream and advances by one
per overlay source symbol, modulo 2^32 (Section 7.5). It is the value
the RAP source packet carries in its 0x8B01 header extension
(Section 8.5.1). It lives in the overlay instance's own SS_ID space,
independent of the base instance's, and the two IDs on one packet are
unrelated numbers. An overlay source block holds at most K_overlay
overlay source symbols, and overlay blocks, including short ones, are
formed, located and wrapped exactly as base blocks are (Sections 7.4,
7.5 and 8.3), with K_overlay as the upper bound on their SSB_length.
Because a RAP is a small fraction of the media, an overlay block spans
many base blocks; the overlay's recovery latency is therefore its own
block span and is unrelated to interleaveDepthMs.¶
A receiver knows that a source packet is an overlay source symbol
because the packet carries the 0x8B01 header extension
(Section 8.5.1). It knows that a repair packet belongs to the overlay
because it arrives on the repair track that the catalog declares with
"scope": "keyframe" for this source track, and that track has its
own packet_id. The instance is therefore fixed by the track the
packet arrived on; no field of the repair packet distinguishes the
two, and a receiver MUST NOT attempt to infer the instance from
SS_Start, RSB_length, or SSB_length, whose values are only
interpretable once the instance is known.¶
6.4.3. Receiver Behavior
A receiver that implements overlays and has joined the overlay repair track decodes the two instances independently and MAY use the recovered RAP fragments even when the base instance failed to recover the block that carried them.¶
The overlay is the publisher-side half of keyframe protection. The receiver-side half is the repair policy of Section 11.4, under which a receiver gives a keyframe-bearing base block that in-band decoding leaves unrecovered priority unicast repair; Section 11.4.6 states how the two combine.¶
A receiver that does not implement overlays MUST fail closed on a
catalog that declares one for a track it intends to consume, that is
on a fec-repair track carrying the unknown scope key, and MUST
NOT ignore the key and consume the source track anyway. This is one
of the unknown-key exceptions of Section 5.1.1: a receiver that
ignored the key could not tell the overlay's repair track from a
repair layer of the base instance, and would feed the base decoder
repair symbols of another FEC instance (Section 6.4.2).¶
This mechanism is not backward compatible with receivers that predate it, for the same reason. A publisher that must serve such receivers publishes the overlay on a separate source track, or does not publish it.¶
7. Repair Object Format
7.1. Repair Object Header
Each object on a repair track is one complete MMTP repair packet (packet type 0x03, FEC Type 2) carrying exactly one repair symbol. Its layout is the ISO 23008-1 AL-FEC repair packet form -- the MMTP packet header followed by the 13-byte Repair FEC Payload ID and the repair symbol data ([ISO.23008-1] Sections C.4.3 and C.5.3; ssbg_mode1, one-stage FEC with N = 1, and ffsrpts_flag = 0, so no FFSRP_TS, Section C.5.1) -- so the same repair packet is valid on MoQ, multicast UDP, and native broadcast paths without translation, and matches the repair-object depiction of [MOQ-MMT] Section 7. The layout below reproduces [ISO.23008-1] Section C.5.3 for convenience:¶
Repair Object {
MMTP Packet Header (96), # packet type 0x03, FEC Type 2
Repair FEC Payload ID {
SS_Start (32),
RSB_length (24),
RS_ID (24),
SSB_length (24),
},
Repair Symbol Data (..), # exactly one symbol, T bytes
}
¶
MMTP Packet Header: The standard 12-byte MMTP packet header
([MOQ-MMT] Section 3.1) with packet type 0x03 (repair) and
FEC Type 2; its packet_id routes the repair flow. Like every
packet of its MMTP packet flow, source and signaling packets
included, a repair packet has the packet counter flag C = 0
([MOQ-MMT] Section 3.1; [ISO.23008-1] Clause 9.2.3). A repair
packet MUST NOT carry a header extension (X = 0). Because C = 0 and
X = 0, the Repair FEC Payload ID always begins at byte offset 12.¶
SS_Start (32 bits): The SS_ID of the first source symbol of the protected source block ([ISO.23008-1] Section C.5.3). The blocks of an FEC instance are consecutive: the block after this one starts at SS_Start + SSB_length, modulo 2^32 (Section 7.4), so this block is the SS_ID range [SS_Start, SS_Start + SSB_length) and is identified by its SS_Start. Extended to 62 bits, SS_Start is also the MoQ Group ID of the block's repair objects (Section 7.5). Every field below is that of the packet's FEC instance (Section 6.4.1).¶
RSB_length (24 bits): The number of repair symbols generated for the block: the instance's total repair count P, identical on every repair packet of the instance; a layer does not carry its own P_i.¶
RS_ID (24 bits): The zero-based index of this repair symbol among the block's P repair symbols. The RFC 6330 Encoding Symbol ID is derived as ESI = SSB_length + RS_ID (Section 7.2). Layer i of the base instance carries RS_ID in [O_i, O_i + P_i) (Section 6.3.2).¶
The encoder performs one RaptorQ encoding pass per source block of each instance, producing the total repair count, and then assigns the disjoint RS_ID ranges to the layer tracks according to O_i. It MUST NOT run a separate encoding per layer: separate encodings of the same block are not symbols of a single code, so they could not be combined by a receiver holding more than one layer, which is the property Section 6.3.2 depends on.¶
SSB_length (24 bits): The number of source symbols in the
protected source block ([ISO.23008-1] Section C.5.3), from 1 to K,
where K is the instance's sourceSymbols (Section 5.1); it is K for
a full block. It is authoritative for the block: the block is a
RaptorQ source block of SSB_length source symbols, its repair ESIs
start at SSB_length (Section 7.2), and its decoder is configured with
F = SSB_length x T (Section 4.2). A value below K marks a short
source block, to which this document's framing adds no padding
symbols (Section 7.4). A publisher MUST NOT send 0
or a value above K; a receiver discards a repair packet carrying
either (Section 7.4).¶
Repair Symbol Data: Exactly one repair symbol of Symbol Size (T) bytes, generated per Section 7.2. Carrying one symbol per object aligns the loss unit with the FEC symbol (Section 11.3) and requires no symbol-count field.¶
7.2. Repair Symbols
For RaptorQ, repair symbols are generated per [RFC6330] Section 5.3. The source symbols of a block occupy ESIs 0 to SSB_length - 1 in SS_ID order, and the Encoding Symbol ID (ESI) of a repair symbol starts at SSB_length, the block's K in the notation of [RFC6330] ([RFC6330] Section 5.3.1): ESI = SSB_length + RS_ID, both fields taken from the Repair FEC Payload ID (Section 7.1). The Internal Symbol IDs of [RFC6330], which start the repair symbols at that document's K', are internal to its encoder and decoder and never appear on the wire.¶
Repair symbol generation for extension algorithms (Section 4.3) is not specified by this document.¶
7.3. Sub-Blocks and ssbg_mode
Per ISO 23008-1 [ISO.23008-1] Section C.3.3 (signalled per C.6.3,
Table C.5), the FEC block structure is described by the source symbol
block generation (SSBG) mode (ssbg_mode). The iso-ssbg1-v1 block
profile (Section 5.1) uses ssbg_mode1, with the one-stage FEC coding
structure and FEC payload ID mode 0 ([ISO.23008-1] Clause C.1).¶
ssbg_mode1: One MMTP source packet = one source symbol, which records the packet's length. Each MoQ object or multicast UDP datagram carries exactly one FEC symbol. Repair symbols are exactly T bytes on the wire; a SOURCE packet MAY be shorter than T on the wire -- the length field and the zero padding that complete its T-byte source symbol are applied by the encoder and decoder as part of the source symbol construction below and are NOT transmitted. This is the natural model for MMTP because packets are sized to fit in UDP datagrams and no fragmentation or reassembly is needed at the FEC layer. Every source symbol is exactly T bytes, so a block of SSB_length source symbols is exactly SSB_length x T bytes -- the property the derived Transfer Length of Section 4.2 relies on. This is ssbg_mode1 of [ISO.23008-1], not ssbg_mode0, which carries no length and requires every packet of the flow to be exactly one symbol long.¶
Source symbol construction: The protected packet of an FEC source packet is the complete MMTP packet -- the MMTP packet header, including any header extension, followed by the MMTP payload -- before its 4-byte Source FEC Payload ID is appended ([ISO.23008-1] Section C.4.2; Section 8.5). Its T-byte source symbol is ([ISO.23008-1] Section C.3.3):¶
Source Symbol {
Length (16), # protected packet length, octets
Protected Packet (..), # Length octets
Padding (..), # zero octets, up to T in total
}
¶
The Length field is in network byte order and every Padding octet is zero, so the largest protected packet a symbol can carry is T - 2 octets. A publisher MUST size every FEC source packet so that its protected packet does not exceed T - 2 octets. A receiver that observes a source packet whose protected packet exceeds T - 2 octets MUST NOT feed it to the decoder -- a truncated symbol would corrupt recovery for the entire block -- but MAY still deliver the packet as media. On a RAP packet under a keyframe overlay (Section 6.4), the base and the overlay instance form the symbol from the same protected packet, so the two protect one identical T-byte symbol.¶
Recovery yields the block's SSB_length source symbols. From each, the receiver takes the Length octets that follow the Length field as the recovered protected packet, and delivers that packet to the MMTP parser. A receiver MUST NOT deliver a recovered symbol whose Length is less than 12, the size in bytes of the MMTP packet header ([MOQ-MMT] Section 3.1), or points past the end of the symbol, or whose Padding octets are not all zero: each means that the symbol is not the one the publisher encoded.¶
A recovered packet carries no Source FEC Payload ID, of either instance: the trailer is appended after FEC encoding and is not part of the protected packet. A receiver MUST NOT re-append a trailer before delivering the recovered packet to the MMTP parser, and MUST NOT expect the recovered bytes to end in a block coordinate. This holds identically for a symbol recovered by a keyframe overlay, which the receiver delivers as media on the strength of the overlay recovery alone. The 0x8B01 header extension of a RAP packet under an overlay (Section 8.5.1) is part of the protected packet, by contrast, and is recovered with it.¶
The packet's base SS_ID was in the trailer, and this document defines no mapping from an overlay coordinate to a base one: a receiver MUST NOT place an overlay-recovered symbol into a base source block unless it has determined that packet's base SS_ID independently. Absent that, an overlay recovery is usable as media but MUST NOT be counted toward base block recovery, and in particular MUST NOT be treated as reducing the number of erasures the base decoder still has to solve. The other direction needs no such determination, because a RAP packet recovered by the base instance still carries its overlay SS_ID (Section 8.5.1).¶
In-band signaling: An AL-FEC message ([MOQ-MMT] Section 8.3)
that describes a track under iso-ssbg1-v1 carries the coding byte
0x14: fec_coding_structure 0001 (one-stage), ssbg_mode 01,
ffsrpts_flag 0 (no FFSRP_TS) and fec_payload_id_mode 0 (a Source
FEC Payload ID is appended to every FEC source packet), in that bit
order, per Table C.3 of [ISO.23008-1] as replaced by
[ISO.23008-1.AMD1]. A message carrying any other value for such a
track contradicts the catalog (Section 5.2).¶
Sub-blocks: When a single source block produces a large number
of source symbols, RFC 6330 permits dividing each block into N
sub-blocks (the Number of Sub-Blocks field of the OTI). The derived
OTI of Section 4.2 fixes N = 1, so catalog-signaled sessions do not
use sub-blocks; sub-block operation by broadcast systems that carry
an explicit OTI is described informatively in Section 12.2.
A publisher using MMTP packaging under iso-ssbg1-v1 therefore uses
ssbg_mode1 without sub-blocks, and never ssbg_mode2.¶
7.4. Short Source Blocks
A publisher MUST close a source block when it has assigned K source
symbols to it. It MAY close a source block earlier, for example at an
access-unit, media-unit, or MoQ Group boundary, or to keep the actual
source/repair send span within a positive interleaveDepthMs when that
field is present (Section 5.1). Such a block is a short source block, and it
is a block with a smaller source symbol count: every block holds
SSB_length source symbols,
1 <= SSB_length <= K ([ISO.23008-1] Section C.5.3), and K -- the catalog
sourceSymbols, carried in band as maximum_k_for_repair_flow -- is an upper bound on SSB_length, not the size of any particular
block. A short block differs from a full one only in SSB_length:¶
-
The publisher encodes the block as a RaptorQ source block of its SSB_length source symbols (F = SSB_length x T, Section 4.2), at ESIs 0 to SSB_length - 1 in SS_ID order, and MUST carry that count in the SSB_length field of every repair packet of the block, on every repair track of the instance. This document's framing adds no padding symbols to the block: none is transmitted, and none is counted in SSB_length or F. The padding of the block to K' symbols in the notation of [RFC6330] ([RFC6330] Section 5.3.1) is part of RaptorQ encoding and decoding, performed inside the encoder and the decoder.¶
-
The next block starts at the SS_ID that follows the block's last source symbol: its SS_Start is SS_Start + SSB_length, modulo 2^32. No SS_ID is skipped, so every SS_ID belongs to exactly one block.¶
-
The block's repair ESIs start at SSB_length: ESI = SSB_length + RS_ID (Section 7.2).¶
-
The block is complete, and needs no repair, once the receiver holds all SSB_length of its source symbols. It is recoverable once the source and repair symbols the receiver holds together number at least SSB_length, plus the decoding overhead of Section 6.3.2.¶
-
Recovery yields the SSB_length source symbols, SSB_length x T bytes, each consumed per the source symbol construction of Section 7.3.¶
Source packets carry only SS_ID, so the (SS_Start, SSB_length) of a
repair packet is the only wire signal of a block's extent. Until a
receiver has accepted a repair packet of a block it knows neither: it
holds the source packets of that block without placing them in any
block (Section 8.3), and a run of SS_IDs that it does not hold is a
run of lost source packets of one or more blocks it cannot yet
delimit. It MUST NOT infer a block boundary, or SSB_length, from a gap in
SS_IDs, from a group or MPU boundary, from elapsed time, or from
sourceSymbols. A block all of whose repair packets are lost
therefore remains undelimited until a repair packet of the block
arrives, including one obtained by unicast repair (Section 11.4),
which conveys (SS_Start, SSB_length) in the same way. When the
receiver accepts a repair packet of a block that starts after the end
of the blocks it has delimited, the SS_IDs between the two belong to
one or more blocks of which it holds no repair packet.¶
A receiver MUST fail closed on inconsistent block signaling. It MUST discard a repair packet whose SSB_length is 0 or exceeds K. It MUST discard a repair packet whose SSB_length differs from the value it has already accepted for the block with the same SS_Start, and one whose range [SS_Start, SS_Start + SSB_length) overlaps a different block that it has already accepted, in each case leaving the state of every block unchanged.¶
7.5. SS_ID Wrap and Repair Group IDs
SS_ID and SS_Start are 32-bit values that start from an arbitrary value and wrap to 0 after their maximum ([ISO.23008-1] Section C.5.2). Every comparison, distance and range test on them in this document, block membership (Section 8.3) included, uses serial number arithmetic [RFC1982] with SERIAL_BITS = 32. A block can span the wrap: a block with SS_Start 2^32 - 3 and SSB_length 4 holds the SS_IDs 2^32 - 3, 2^32 - 2, 2^32 - 1 and 0, and the next block starts at SS_ID 1.¶
A MoQ Group ID is a 62-bit integer, and the groups of a track are ordered by it [I-D.ietf-moq-transport], so the repair objects of a block are grouped not under its 32-bit SS_Start, which wraps, but under its extended SS_Start:¶
ext(SS_Start) = (wrap_epoch << 32) | SS_Start¶
wrap_epoch, from 0 to 2^30 - 1, counts the times that SS_Start has
wrapped in the FEC instance before this block: it is 0 for the first
block of the FEC instance's source encoding, and increases by one at each block
whose SS_Start is numerically below its predecessor's. Equivalently,
the ext(SS_Start) of a block is that of its predecessor plus the
predecessor's SSB_length. On every repair track of the instance, the
repair objects of a block form the MoQ Group whose Group ID is the
block's ext(SS_Start) (Section 6.3.2). Repair Group IDs are
therefore sparse, one per block at the block's first SS_ID, and
strictly increasing.¶
A repair object received over MoQ thus carries its block's start twice: in the SS_Start of its Repair FEC Payload ID and in its Group ID. The SS_Start is authoritative. A receiver MUST discard a repair object whose Group ID modulo 2^32 differs from its SS_Start and, once it has established the wrap epoch, one whose Group ID differs from ext(SS_Start) or whose SS_Start it cannot extend (below), in each case leaving the state of every block unchanged. The Group ID of a discarded repair object is not a reference value r.¶
A receiver establishes the wrap epoch of an FEC instance in one of the following ways, and MUST NOT assume a wrap epoch that it has not established in one of them:¶
-
From the Group ID of a repair object of the instance that it has received over MoQ and not discarded (above). That Group ID is the reference value r. The publisher assigns it and MoQ delivers it unaltered, so it stands on the same footing as the Largest Location of way 2: the modulo 2^32 test above screens out an object to discard, and does not verify the epoch.¶
-
From the Largest Location that a TRACK_STATUS request for a repair track of the instance reports ([I-D.ietf-moq-transport] Section 9.13). The publisher answers TRACK_STATUS with a REQUEST_OK, which that document calls TRACK_STATUS_OK, carrying the parameters that it would set in a SUBSCRIBE_OK, among them the LARGEST_OBJECT parameter ([I-D.ietf-moq-transport] Section 9.20.18). The receiver reads the Group of the Location that LARGEST_OBJECT carries, whichever name the reply bears, and that Group is the reference value r. A reply without LARGEST_OBJECT reports a repair track on which no object has been published, and establishes no epoch.¶
-
As epoch 0, when the receiver has observed the instance from its first block, whose
wrap_epochis 0 (above). The reference value r is then that block's SS_Start.¶
A reference value r is an extended SS_Start, and the epoch is r shifted right by 32 bits. The receiver relates its own SS_IDs to it with serial arithmetic: it extends a later 32-bit SS_Start or SS_ID x relative to an extended value r that it already holds -- its reference value, or a value it extended before -- to the 62-bit value congruent to x modulo 2^32 that is nearest r in serial order: r advanced by the serial distance from the low 32 bits of r to x when x follows them, r moved back by the serial distance from x to them when x precedes them, and r itself when the two are equal. A receiver MUST NOT extend an x that lies exactly 2^31 from the low 32 bits of r, a pair that [RFC1982] leaves unordered, or one whose extension falls outside [0, 262).¶
Serial arithmetic cannot detect an x that lies more than 2^31 SS_IDs from r: it extends such an x into the wrong epoch without error. A receiver therefore extends values relative to an r only while it can bound the number of SS_IDs between them below 2^31, and MUST re-establish the wrap epoch, in one of the ways above, after any gap that it cannot so bound, such as one that spans a rejoin of a multicast group or a reconnection of its MoQ session.¶
A receiver that has lost the source packet with SS_ID x, and holds no repair packet of the block that contains x, requests that block's repair by a FETCH [I-D.ietf-moq-transport] of the absolute, inclusive Group range¶
[ max(ext(S_prev) + 1, ext(x) - (K - 1)), ext(x) ]¶
on each repair track it requests from, where:¶
- K is the instance's
sourceSymbols(Section 5.1), the largest SSB_length that a block can have (Section 7.4), so the block that contains x starts at most K - 1 SS_IDs before x;¶ - S_prev is the SS_Start of the last block that the receiver has delimited that ends before x. When the receiver has delimited no such block, the first term is absent and the range is [ max(ext(x) - (K - 1), 0), ext(x) ];¶
- ext(x) is x extended relative to ext(S_prev) when S_prev exists, and otherwise relative to the reference value r of the receiver's wrap epoch.¶
Repair Group IDs sit at block starts, so the range returns the repair of every block that starts within it, up to and including the block that contains x, and the last Group it returns is that block. The range is never empty: it always contains ext(x). A receiver that has not established the wrap epoch, or that may not extend x, has no range to request until it establishes one. A receiver that holds a repair packet of the block requests the one Group ext(SS_Start) instead.¶
The 32-bit wrap of SS_ID and SS_Start is that of [ISO.23008-1]. The extended SS_Start, and its use as a MoQ Group ID, are defined by this document, outside [ISO.23008-1].¶
8. Block and Group Alignment
FEC blocks are partitions of the source-packet sequence, independent
of MoQ Group boundaries. The publisher assigns consecutive SS_ID
values to source packets and chooses each block's SSB_length subject
to 1 <= SSB_length <= K (Section 7.4). It signals the chosen
partition in the (SS_Start, SSB_length) fields of the block's repair
packets. A block MAY end at an access-unit, media-unit, or Group
boundary, MAY span Groups, and MAY end because it reaches K. K
exhaustion closes a block. A Group MAY contain more than one block.
A positive interleaveDepthMs limits the elapsed source/repair send
span; it does not change this partitioning rule.¶
8.1. Blocks Within a Group
For example, a source Group can contain two consecutive blocks:¶
Group G: SS_ID s .. s+a-1 -> block A, SS_Start = s
SS_ID s+a .. s+a+b-1 -> block B, SS_Start = s+a
Group G+1: SS_ID s+a+b .. -> next block or continuation
...
¶
8.2. Blocks Across Groups
A block can also span a Group boundary:¶
Group G: SS_ID s .. s+a-1 -> block A, still open
Group G+1: SS_ID s+a .. s+L-1 -> block A completes
SS_ID s+L .. -> next block
...
¶
A block's repair objects form the repair-track Group whose Group ID is
the block's extended SS_Start (Section 7.5), a number space unrelated
to the source track's Group IDs. No fixed number of MoQ Groups is
required for a block, and no Group boundary can be used to infer
SSB_length.¶
8.3. Source Symbol Location
Under iso-ssbg1-v1, every FEC source packet carries a Source FEC
Payload ID (Section 8.5), and a receiver that parses the packet takes
each source symbol's SS_ID from that field on every path that
delivers the packet with its trailer. The SS_ID is also carried
alongside the packet where the packaging says so: on the MoQ path
every object carrying a source symbol carries it in the FEC Source
Info Object Property (Section 5.3), under the same value and the same
definition, whether or not that object also delivers the trailer. A
receiver that does not parse the FEC source packet -- a relay, or a
MoQ receiver with no MMTP parser -- takes the SS_ID from there. The
SS_ID advances by one per
FEC source packet, modulo 2^32, in the order the publisher emits the
packets ([ISO.23008-1] Section C.5.2), and the blocks of an FEC
instance are consecutive: each starts at the SS_ID that follows the
last source symbol of its predecessor (Section 7.4).¶
A source symbol is located by range membership. It belongs to the block whose Repair FEC Payload ID (Section 7.1) carries an (SS_Start, SSB_length) such that the symbol's SS_ID lies in [SS_Start, SS_Start + SSB_length) under the serial arithmetic of Section 7.5, and its ESI is its serial distance from SS_Start:¶
ESI = (SS_ID - SS_Start) mod 2^32, 0 <= ESI < SSB_length¶
No source symbol's block can be computed from its SS_ID alone, because blocks differ in length (Section 7.4), and this document defines no block number. A receiver holds a source symbol whose block it has not yet delimited, and places it when it accepts a repair packet of that block. Because consecutive FEC source packets carry consecutive SS_IDs, a lost source packet is visible as a missing SS_ID even before its block is delimited, and a run of SS_IDs that a receiver holds in full needs no repair, whatever its block boundaries.¶
An object that a packaging profile defines as carrying no source symbol -- for example, the in-band AL-FEC signaling object of [MOQ-MMT] Section 8 -- carries no SS_ID, has no ESI, and is not counted in K or in any block. This document defines no derivation of a source symbol's position from MoQ Group or Object IDs: on the mmtp packaging of [MOQ-MMT], Object IDs are not positions in the FEC block, and a packaging profile that defines source objects carrying neither a Source FEC Payload ID nor a FEC Source Info Object Property (Section 5.3) needs a block profile of its own (Section 5.1).¶
Every transport path yields the same SS_ID for the same packet, because each path carries the same MMTP packet, so receivers MAY combine symbols from any transport path toward the same FEC block recovery. Within one FEC instance (Section 6.4.1), a receiver deduplicates source symbols by SS_ID and repair symbols by (SS_Start, RS_ID).¶
8.4. Encoder Constraints
For FEC block alignment and timing to be deterministic, encoders MUST:¶
-
Assign consecutive
SS_IDvalues in source-packet emission order, close a block at K source symbols or earlier as permitted by Section 7.4, and publish the resulting(SS_Start, SSB_length)in every repair packet for that block. A publisher MAY close at an access-unit, media-unit, or Group boundary, but MUST NOT use any boundary or elapsed-time observation as a substitute for that wire signaling.¶ -
Signal the catalog-authored group duration and frame rate in the MoQ catalog: for mmtp-packaged tracks, publish a positive duration as
groupDurationMswhen its integer-millisecond form is exact, or as the exact positivegroupDurationTicks; when both are present,groupDurationTickswins andgroupDurationMsis informational. Signal the keyframe cadence inkeyframeIntervalMs(orkeyframeIntervalTicks), and the frame rate in theframeratefield ([MOQ-MMT] Sections 4.4.2, 4.4.3 and 12.1). The ISO 23008-1 AL-FEC message has no field for either value ([ISO.23008-1] Table C.3), so an encoder signals neither there, and a receiver takes neither from it.¶ -
If frame rate or GOP size changes mid-session, update the MoQ catalog and signal a manifest discontinuity for DASH/HLS.¶
-
When
interleaveDepthMsis positive, choose it so that the actual elapsed send span from the first source or repair packet of every block to its last does not exceed the signaled value. A zero value is usable only with the ISOprotection_window_sizealternative described in Section 5.1. The value is not derived from a group count, frame count, or per-symbol interval.¶
8.5. Source FEC Payload ID and ATSC 3.0 Signed Region
Exactly one 4-byte Source FEC Payload ID (SS_ID; ffsrpts_flag = 0, so no FFSRP_TS, [ISO.23008-1] Section C.5.1) is appended at the END of each MMTP FEC source packet -- following the MMTP payload, outside the MMTP packet header -- with or without a keyframe overlay (Section 8.5.1). Per ATSC A/360 Section 5.2.2.5, the ATSC 3.0 Signed Application (A3SA) signing mechanism covers signaling messages and MA3 messages (packet type 0x2) but excludes asset packets (type 0x00 MPU and type 0x03 repair).¶
Neither [ISO.23008-1] nor [ATSC-A331] carries the SS_ID inside
the A3SA signed region. In particular the MMT hint sample does not:
neither its ISO syntax ([ISO.23008-1] Clause 8.3.2) nor the ATSC
MMTHSampleATSC3 syntax ([ATSC-A331] Section 7.2.4.2.2.3) has a
Source FEC Payload ID field, and hint samples travel as MPU-mode data
units on the Asset's own packet_id ([ATSC-A331] Section 7.2.4.2.3),
that is in asset packets, which A3SA does not sign. This document
therefore defines no A3SA-authenticated FEC block assignment: block
assignment taken from the trailing Source FEC Payload ID of an A3SA
verified packet is unauthenticated. A receiver that requires
authenticated FEC block assignment MUST obtain it from an integrity
mechanism, other than A3SA signing, whose coverage includes the
complete MMTP packet, the trailer included. The bc-provenance profile
is not such a mechanism: its authenticated bytes exclude the Source
FEC Payload ID ([MOQ-MULTICAST] Section 7.2.4).¶
For MoQ-only receivers (no A3SA verification), the trailing 4-byte Source FEC Payload ID remains the canonical identifier by which a source packet is placed in its block (Section 8.3). QUIC transport encryption provides equivalent integrity protection.¶
Whatever the receiver's verification posture, the FEC Source Info Object Property of Section 5.3 carries the same value for a receiver that does not parse the packet; where an object delivers both and they disagree, the trailer is the one that is canonical, because it is the field the FEC encoder emitted and the one Section 8.3 locates the symbol by. The Property restates it at the MoQ layer.¶
8.5.1. Overlay SS_ID Header Extension
When the catalog declares a keyframe overlay for a source track (Section 6.4), a source packet of that track carrying a Random Access Point fragment is a source symbol of two FEC instances. It carries its base SS_ID in the one Source FEC Payload ID trailer that every FEC source packet carries (Section 8.5), and its overlay SS_ID (Section 6.4.2) in an MMTP header extension ([ISO.23008-1] Clause 9.2.3) of type 0x8B01:¶
Source Packet with Overlay {
MMTP Packet Header {
..., # X = 1, RAP_flag = 1
Header Extension {
Type (16) = 0x8B01,
Length (16) = 4,
Overlay SS_ID (32),
},
},
MMTP Payload (..),
Source FEC Payload ID (32), # base instance SS_ID
}
¶
A publisher that declares an overlay MUST carry this extension as the
header extension, with X = 1, of exactly the source packets that it
includes in the overlay instance, that is the packets on which it
sets RAP_flag (Section 6.4.2), and of no other packet of the track.
An MMTP packet carries at most one header extension ([ISO.23008-1]
Clause 9.2.3), so the RAP packets of a track under an overlay carry no
other MMTP header extension, and a publisher that needs another
header extension on those packets cannot use the overlay for that
track.
[ISO.23008-1] specifies no particular header extension and no
registry of header extension types; this document uses the type
0x8B01 for the overlay SS_ID (Section 15.1).¶
The trailer is never more than one Source FEC Payload ID. On a packet with or without the extension, the last four bytes are the base SS_ID, as [ISO.23008-1] Section C.4.2 places it, so a receiver that does not implement overlays locates the trailer and the payload as on any other packet, stepping over the extension by its Length field. The extension lies inside the MMTP packet header, so it is part of the protected packet of both instances (Section 7.3), which protect one identical source symbol. The permission of [ISO.23008-1] Clause 9.2.3 to discard a header extension therefore extends only to a receiver's own processing: a node that forwards the packet MUST NOT remove or alter the extension. A RAP packet recovered by either instance carries its overlay SS_ID, so a receiver MAY place a RAP packet that the base instance recovered into the overlay block that the extension locates; Section 7.3 states why the converse requires the packet's base SS_ID.¶
A receiver that implements overlays takes a packet's overlay SS_ID
from this extension and from nothing else. It MUST NOT feed the
overlay decoder a source packet that lacks the extension, whatever its
RAP_flag, or one whose extension has a Length other than 4, and MUST
NOT infer an overlay SS_ID from RAP_flag, from the packet's
position, or from its base SS_ID.¶
A source track has at most one overlay (Section 6.3.4, rule 10) because a source packet has one header extension, and so carries one overlay SS_ID; relaxing that bound would be a revision of this document and a change to the source packet layout, not a catalog-only change.¶
The overlay is declared only by the catalog. A publisher MUST NOT describe the overlay's repair flow in an AL-FEC message ([MOQ-MMT] Section 8.3): the message identifies an FEC source flow by packet_id ([ISO.23008-1] Clause C.6.3) and cannot describe the RAP subset that the overlay protects, so a receiver that consumes the flow without the catalog uses the base instance alone. An overlay is defined only without FFSRP_TS: a publisher MUST NOT declare an overlay for a source track whose FEC source or repair packets carry FFSRP_TS (ffsrpts_flag = 1, [ISO.23008-1] Section C.5.1), and the extension carries an SS_ID alone.¶
Section 8.5 applies to the overlay SS_ID as to the base one: A3SA signing authenticates neither, and a receiver that requires authenticated block assignment treats each as Section 8.5 requires.¶
9. Interleaving
Interleaving spreads source symbols across time to protect against
burst loss. The interleave window (Interleave Depth, in
milliseconds) bounds the elapsed send span of a source block when the
field is positive. It does not define the block's membership or imply
a number of Groups. Block membership is the consecutive SS_ID range
identified by (SS_Start, SSB_length) (Sections 7.4 and 8.3).¶
Groups: M0 M1 M2
| | |
Blocks: [Block 0] [Block 1] [Block 2] [Block 3]
SS_ID: S0 S1 S2 S3 S4 S5 S6 S7 ...
| | | |
Repair Groups: ext(S0) ext(S2) ext(S4) ext(S6)
¶
A burst loss can therefore erase symbols from several adjacent blocks;
each block is recovered with the repair symbols identified by its own
SS_Start and SSB_length. With P repair symbols for a block, the
usual RaptorQ recovery condition applies independently to that block.¶
Publishers SHOULD choose the interleave window based on:¶
The receiver's block-abandonment timeout -- how long it waits for a
block's source and repair symbols before declaring the block
unrecoverable -- follows the ISO receiver-buffer model [ISO.23008-1]
Section 11.2. The timer is anchored at the timestamp ts of the
first source or repair packet of the block when the receiver received
that packet, not at block creation or the first repair receipt. A
block whose first packet the receiver did not receive is one that it
first learns of from a later signal -- a later source or repair
packet of the block, a packet of a successor block, or a FETCH
response that covers the block (Section 7.5) -- and its ts is the
arrival time of that signal. When interleaveDepthMs is positive,
the base FEC deadline is:¶
base_deadline = ts + interleaveDepthMs¶
Here a positive interleaveDepthMs is the complete first-to-last
source/repair send span of the block, which bounds source and repair
production at the media cadence and their serialization. An absent
value supplies no elapsed-time base deadline. A zero value invokes the
ISO protection_window_size alternative; this catalog profile supplies
no packet-count window, so a catalog-only receiver has no elapsed-time
base deadline from that value. If an applicable count window is
accepted in-band, it governs separate count-based processing and is not
converted to milliseconds without an independently defined time
mapping.¶
The block assignment rule in Section 8.3 means that implementations do
not derive a full-block span or an FEC deadline from K, a Group count, a
per-symbol interval, or by a multiplier. When the field is positive, a
deadline adds interleaveDepthMs and, where used,
reorderToleranceMs, each exactly once.¶
A receiver uses the catalog reorderToleranceMs allowance, when
present, for network jitter, one-way delay, reordering, and local
processing before abandoning the block. That allowance is additive to
the base span and MUST be applied exactly once. If
interleaveDepthMs is absent or zero, no elapsed-time deadline is
derived from this FEC window. An applicable ISO packet-count window
accepted in-band governs separate count-based processing; it does not
become a millisecond deadline without an independently defined time
mapping. When an elapsed-time deadline exists, the receiver moves the
block onward at that deadline and attempts FEC processing according to
its buffering model. What a receiver of a multicast or AMT leg does
with a block that is still unrecovered at that deadline -- unicast
repair, a stall, or concealment -- is specified in Section 11.4.¶
A receiver MUST bound the state it holds for open blocks by a
receiver-local policy, for example a memory cap, a local timeout, or a
later block that has itself passed its FEC deadline or local timeout.
The bound is needed even when no FEC deadline exists: a receiver that
loses every repair packet of a block never learns its SSB_length
(Section 7.4). For a block that has an FEC deadline, the policy MUST
NOT discard the block before that deadline, or while a unicast repair
FETCH for it is outstanding (Section 11.4.2), except under a memory
cap. A block so discarded is treated from then on as having reached
its FEC deadline unrecovered and, on a track whose blocks Section
11.4.1 classifies, of unknown class. The
policy is not signaled, and a receiver MUST keep it separate from the
catalog values: it does not change interleaveDepthMs,
reorderToleranceMs, or a deadline derived from them, and discarding
a block under it does not create an FEC deadline (Section 11.4).¶
The code is systematic (Section 4.1): a receiver plays source objects
on arrival, and the window adds latency only when a lossy leg forces
it to wait for recovery. The interleaveDepthMs value is the
worst-case source/repair send-span budget when it is present.¶
Typical values are deployment choices for that send-span budget:¶
| Application | interleaveDepthMs | Meaning | Recovery Latency |
|---|---|---|---|
| Interactive (gaming, WebRTC) | 33-133 | Short source/repair span | 33-133ms |
| Low-latency live | 1000-2000 | One-to-two second span | 1-2s |
| Broadcast | 4000 | Four-second burst-spreading span | 4s |
| ATSC 3.0 default | 8000 | Eight-second burst-spreading span | 8s |
Conformance cases.¶
These cases exercise the boundary rules without deriving a block from a Group count:¶
The first case uses this numeric vector:¶
{
"fps": 30,
"gopFrames": 30,
"groupDurationMs": 1000,
"accessUnitsPerBlock": 4,
"accessUnitStartMs": [0, 33.333, 66.667, 100.0],
"sourcePacketsPerAccessUnit": [2, 3, 1, 4],
"K": 16,
"SSB_length": 10,
"interleaveDepthMs": 133,
"firstSourceOrRepairMs": 0,
"lastSourceOrRepairMs": 133,
"sourceRepairSpanMs": 133
}
¶
- A 30 fps track with a 30-frame (1000 ms) GOP may close a block after
four access units (a four-frame access-unit interval). With the send
schedule in the vector,
interleaveDepthMs = 133. An access unit can produce multiple source packets, so the block is closed after those access units, not after an assumed packet count. For this concrete vector, the four access units begin at 0, 33.333, 66.667, and 100 ms, produce 2, 3, 1, and 4 source packets respectively, and therefore haveSSB_length = 10 <= K = 16as shown above:¶
The publisher sends the last source or repair packet for that block
by 133 ms; a later send would require a larger signaled window. The
one MoQ Group containing the GOP can therefore contain several such
blocks. Each repair packet still carries the actual
(SS_Start, SSB_length); the 133 ms value does not mean four MoQ
Groups per block and is not a rounded four-frame duration.
2. With K = 4, one Group containing three source packets followed by
a Group containing three source packets may be encoded as blocks of
lengths 3 and 3, or as a block of length 4 spanning the Group
boundary followed by a block of length 2. Both are valid; the
repair fields identify which partition was used.¶
{
"K": 4,
"groupPacketCounts": [3, 3],
"blockPartitions": [[3, 3], [4, 2]],
"SS_Starts": [[0, 3], [0, 4]]
}
¶
- If the stream ends with two source packets in the current block, the
publisher sends a short block with
SSB_length = 2,F = 2 x T, and no padding or skippedSS_ID. There is no following block.¶
10. Priority and Congestion
Priorities in this document are expressed in the MoQ Transport priority scale [I-D.ietf-moq-transport]: an 8-bit value (0-255) in which a numerically LOWER value is delivered with HIGHER precedence. Repair tracks SHOULD use a numerically greater (lower-precedence) priority than the source tracks they protect, so that repair data is dropped first under congestion. The RECOMMENDED assignment places a repair track's priority value at least 64 above its source track's (e.g. repair 240 against a source track at the common default of 128):¶
| Track Type | Priority (0-255, lower value = delivered first) | Notes |
|---|---|---|
| Control/Signaling (incl. catalog) | 0-63 | Delivered first |
| Source Media | 64-191 (e.g. 128) | Protected |
| Repair layer 0 | 192-255, default 240 | Dropped first |
| Repair layer 1 | 192-255, >= layer 0 | Declared on the track |
| Repair layer n | 192-255, >= layer n-1 | Monotonic by layer |
| Keyframe overlay | 192-255, independent | Outside the layer order |
Layer priorities and the layer-0 default follow Section 6.3.4, rule 3, so under congestion the highest layer is shed first and a receiver degrades through its layer set in order; a keyframe overlay's priority is independent of that order (Section 6.4.1).¶
Publishers and relays convey these priorities through the priority fields and scheduling rules of [I-D.ietf-moq-transport] (subscriber and publisher priority); QUIC itself defines no wire-visible stream priority mechanism.¶
Under congestion, this priority separation ensures:¶
- Source media is preserved as long as possible¶
- Repair overhead is gracefully shed¶
- Receivers degrade to QUIC retransmission when FEC is unavailable¶
On a multicast or AMT leg, the priorities of on-demand unicast repair requests are set by Section 11.4.5.¶
11. Hybrid Unicast and Multicast Delivery
This FEC mechanism is designed to support hybrid delivery architectures where the same media stream is delivered via multiple transport paths simultaneously. Multicast delivery paths, TreeDN integration, and the transport hierarchy (all Section 3) are defined in [MOQ-MULTICAST]; this section covers FEC-specific considerations for hybrid delivery.¶
11.1. Multicast and AMT Delivery
IP multicast (including Source-Specific Multicast per [RFC4607]) and Automatic Multicast Tunneling (AMT per [RFC7450]) provide efficient one-to-many delivery but are inherently unreliable. FEC enables receivers to recover from packet loss without retransmission:¶
- Native SSM: Receivers join multicast group directly¶
- AMT Tunneling: Receivers without native multicast connect via AMT relays discovered through DRIAD ([RFC8777])¶
- TreeDN Distribution: Hierarchical multicast trees per [RFC9706], with FEC protection at each hop¶
The same MoQ objects (source and repair) can be transmitted over both unicast (QUIC/WebTransport) and multicast (UDP/SSM/AMT) paths. Receivers on reliable unicast paths can skip FEC decoding (Section 3), while receivers on lossy multicast paths use FEC for recovery and apply the receiver repair policy of Section 11.4 to any block that FEC does not recover.¶
Publisher
|
v
+----------------+
| MoQ Relay |
| (Origin/Root) |
+-------+--------+
|
+----+----+--------------------+
| | |
v v v
Unicast SSM Multicast AMT Tunnel
(QUIC) (Native) (Encapsulated)
| | |
v v v
[Web] [Native SSM [Mobile/
Client Clients] Remote]
FEC: FEC: FEC:
Optional Expected Expected
¶
11.2. Deployment Applicability
The repair overhead this mechanism adds is justified only where the delivery path actually loses packets, and multicast loss characteristics differ by orders of magnitude across access technologies. FEC strength (P and Interleave Depth) is a per-path deployment choice, expressed by which tracks each endpoint carries, not a protocol constant.¶
-
Engineered low-loss segments. On managed PON or DOCSIS delivered over a provisioned VLAN, steady-state loss is typically far below 10^-6. Disabling FEC for such a path is signaled by omitting the repair track from the tracks that path's endpoints carry. Adding repair symbols on such a path spends bandwidth to recover losses that do not occur.¶
-
FEC-capable broadcast PHYs. ATSC 3.0, DVB-S2/S2X, and 5G broadcast already apply bit-error correction on their own radio link (e.g., LDPC/BCH in ATSC 3.0 and DVB-S2/S2X). Application-layer FEC is NOT a duplicate of that correction: it recovers packet erasures the PHY cannot address -- bursts when reception falls below the PHY threshold (rain fade, mobility, indoor reception), and losses on upstream aggregation or backbone hops that the last-hop PHY never sees. Its value on these paths comes primarily from Interleave Depth spreading a burst across the time domain, not from the code rate. On a one-way broadcast downlink with no return path, application-layer FEC is the only available erasure-recovery mechanism -- which is why ATSC 3.0 (see Section 12) specifies it above the PHY.¶
-
Public Internet and AMT tunnels. Loss is real and bursty; a non-trivial repair count with interleaving is RECOMMENDED.¶
11.3. Interaction with Multicast QUIC
[QUIC-MULTICAST] defines a one-way QUIC transport in which a multicast channel carries QUIC packets bearing STREAM or DATAGRAM frames, recovering loss via unicast repair (the MC_CHANNEL_ACK mechanism) and defining no Forward Error Correction of its own. This FEC scheme MAY be used as the recovery layer on such a channel, and is RECOMMENDED over unicast repair for broadcast-scale audiences, where per-receiver retransmission does not scale.¶
When this scheme is carried over a multicast QUIC channel:¶
-
Symbol-to-datagram mapping. Each source or repair symbol (one MMTP packet, per [MOQ-MMT]) SHOULD be carried in exactly one QUIC DATAGRAM frame. This aligns the erasure unit (a lost QUIC packet) with the FEC symbol, so one lost packet erases exactly one source symbol. STREAM framing SHOULD NOT be used for FEC-protected media on a multicast channel: a lost packet then spans a byte range crossing symbol boundaries, defeating symbol-aligned recovery.¶
-
Crypto boundary. FEC encoding operates on application-layer objects, ABOVE the QUIC packet protection of [QUIC-MULTICAST]. Unlike bare multicast UDP -- which lacks QUIC's integrity guarantees (see Section 14.4) -- the multicast QUIC binding applies a shared-key AEAD per packet. A sender computes source and repair symbols over the unencrypted objects; the channel then applies its AEAD; a receiver decrypts each surviving packet and recovers erased objects from the decrypted source and repair symbols. A lost packet cannot be decrypted, but its object is reconstructed from other verified symbols, so recovery does not depend on possessing it.¶
-
Integrity of recovered objects. The integrity frames of [QUIC-MULTICAST] authenticate the bytes of each delivered packet. A FEC-reconstructed object was never carried in a single packet and is therefore NOT individually covered by a packet hash; it inherits trust transitively from the verified surviving symbols used to reconstruct it. Deployments requiring per-object authentication of recovered data SHOULD additionally apply an object-level scheme (for example the manifest-based bc-provenance profile of [MOQ-MULTICAST] Section 7.2) computed below the FEC layer, which survives reconstruction.¶
-
Repair channel versus unicast repair. A publisher using this scheme broadcasts repair symbols on the multicast channel (the repair track) rather than relying on unicast retransmission. Receivers covered by the repair flow SHOULD NOT drive unicast repair for losses the FEC recovers, preserving the O(1) sender cost that motivates broadcast FEC. Unicast repair MAY be retained as a last resort for losses exceeding the repair budget. Section 11.4 specifies that last resort.¶
Symbols delivered over a multicast QUIC channel are deduplicated by their FEC coordinates, source symbols by SS_ID and repair symbols by (SS_Start, RS_ID); [QUIC-MULTICAST] normatively requires only this deduplication, and Section 8.3 permits combining them with symbols received from other paths.¶
11.4. Receiver Repair Policy
This section specifies what a receiver of a multicast or AMT leg does with a base-instance block of a source track that in-band FEC has not recovered by the block's FEC deadline (Section 9). A receiver on a reliable MoQ/QUIC leg relies on transport retransmission (Section 3) and does not need it, and nothing in this section adds a deadline or a timer to such a leg.¶
Every step of this section is keyed on a block's FEC deadline, which
exists only when the track's catalog carries a positive
interleaveDepthMs (Section 9). On a multicast or AMT leg, this
section therefore requires a positive interleaveDepthMs: a receiver
of a track whose catalog omits it or sets it to zero MUST disable the
block classification and unicast repair of this section for that
track. The receiver still decodes in-band FEC from the symbols that
arrive (Section 8.3), with open-block state bounded by the local
policy of Section 9. Media still missing at its presentation time is
lost: the loss of a RAP, or of a data unit that governs one, is
handled as for an unrecoverable keyframe-bearing block
(Section 11.4.2), and other loss is concealed as in Sections 11.4.3
and 11.4.4.¶
Every block receives in-band FEC processing. A receiver MUST attempt to recover every block, whatever its class, from the source and repair symbols received on its multicast and AMT paths, together with any it receives on other paths (Section 8.3), up to the block's FEC deadline. The rest of this section governs only a block that is still unrecovered at that deadline: the receiver does not hold all of its SSB_length source symbols (Section 7.4), and decoding from the symbols it holds has not recovered them.¶
A run of SS_IDs that the receiver lacks and that lies in no block it has delimited belongs to one or more blocks of which it holds no repair packet (Section 7.4). For this section the receiver treats such a run as one block of the instance: Section 11.4.1 classifies it from the source packets the receiver holds on either side of it, and its repair is requested by the Group range of Section 7.5, whose response also delimits the blocks it covers.¶
The policy distinguishes keyframe-bearing blocks, whose loss can stop video decoding until the next Random Access Point (RAP), from other blocks, whose loss damages only frames up to the next RAP. Keyframe-bearing blocks are protected by priority unicast repair and are the only blocks whose loss may stall video. Other blocks are repaired on a best-effort basis and, when repair fails, concealed. Every frame and audio sample a receiver presents MUST be presented at its authored time on the presentation clock shared by its tracks, and a receiver MUST NOT stall video or pause that clock except for a keyframe-bearing block (Section 11.4.2).¶
11.4.1. Block Classification
A base block of a video source track is keyframe-bearing if it
carries, or may carry, any part of a RAP: a fragment of a RAP MFU, or
of the FT=0 or FT=1 data unit that governs it ([MOQ-MMT]
Sections 4.3 and 5.1). The receiver classifies each block when the
block reaches its FEC deadline, from two inputs and only from them:
in-band evidence in the source packets it holds, and the
catalog-authored timing of the track, that is its group structure,
one MPU per group of the catalog group duration ([MOQ-MMT]
Sections 4.3 and 4.4.2), and its keyframe interval ([MOQ-MMT]
Section 4.4.3). The block's SS_Start and SSB_length, once known
(Section 7.4), fix which SS_IDs belong to the block, and a positive
interleaveDepthMs with reorderToleranceMs fixes the elapsed-time
deadline at which the class is taken (Section 9).¶
The receiver first bounds what the block's missing source symbols can carry. The lower bounding packet is the last source packet it holds, in SS_ID order, before the block's first missing source symbol; the upper bounding packet is the first source packet it holds after the block's last missing source symbol. Either may lie in an adjacent block. Only FEC source symbols count: the AL-FEC signaling object of [MOQ-MMT] Section 8 carries no SS_ID and is never a bounding packet. A publisher MUST assign the base SS_IDs of a track's source packets in increasing order along the authored order of [MOQ-MMT] Section 4.3, so every data unit the missing symbols can carry lies between the data units of the two bounding packets, those two included.¶
The block is keyframe-bearing if any of the following holds:¶
-
A source packet the receiver holds from the block sets
RAP_flag, carries the 0x8B01 overlay header extension (Section 8.5.1), or is an FT=0 packet, or two source packets it holds from the block carry different MPU sequence numbers.¶ -
The two bounding packets carry different MPU sequence numbers, or the lower bounding packet is the FT=0 packet or the first FT=1 packet of its MPU, or belongs to the first FT=2 sample of its MPU. The missing symbols can then carry part of a group-start RAP, or of the metadata that governs it ([MOQ-MMT] Section 4.3).¶
-
The catalog carries a usable keyframe interval, and the closed interval between the authored decode times ([MOQ-MMT] Section 5.1) of the samples of the two bounding packets contains an instant a positive whole number of keyframe intervals after the decode time of the first sample of their MPU. Where a bounding packet is an FT=1 packet, its time is the decode time of the first sample it describes. The interval is
keyframeIntervalTicks, orkeyframeIntervalMsconverted to the track timescale where that conversion is exact; an inexactkeyframeIntervalMsgives no usable interval.¶
The block is non-keyframe-bearing only when none of these holds, the catalog carries a usable keyframe interval, the receiver holds both bounding packets, and it can determine every value item 3 needs. Every other block is of unknown class, and a receiver MUST treat a block of unknown class as keyframe-bearing. In particular:¶
-
A block for which the receiver holds no lower or no upper bounding packet at its FEC deadline is of unknown class, as is one for which it cannot determine a decode time that item 3 needs. So is a block discarded before its FEC deadline under a memory cap (Section 9).¶
-
On a video track whose catalog entry carries no usable keyframe interval, the receiver cannot exclude a keyframe after the group start from any span, so every block of the track is keyframe-bearing or of unknown class.¶
-
A block's keyframe classification uses its actual source-packet range. A block MAY contain a complete Group, span a Group boundary, or close inside a Group; none of those shapes is inferred from
interleaveDepthMsor from the catalog's group duration.¶
A receiver MUST NOT classify a block from any input other than those
this section names; in particular, the absence of RAP_flag on the
packets it holds says nothing about a packet that was lost. A
publisher that wants receivers to be able to
apply the non-keyframe treatment of Section 11.4.3 publishes an exact
keyframe interval, which then binds every keyframe of the track
([MOQ-MMT] Section 4.4.3).¶
The blocks of a track that the catalog identifies as audio are treated by Section 11.4.4, not classified by this section. A track that the receiver cannot identify from its catalog entry is treated as video.¶
11.4.2. Keyframe-Bearing Blocks
When a keyframe-bearing block is still unrecovered at its FEC deadline, a receiver that holds a MoQ session with a relay serving the block's repair track MUST request on-demand unicast repair for it, with the priority of Section 11.4.5. The request is a standalone FETCH [I-D.ietf-moq-transport], over QUIC, of the block's repair-track group, whose Group ID is the block's extended SS_Start, or, for a run that the receiver has not delimited, of the Group range that Section 7.5 derives from a lost SS_ID x of the run, with the wrap epoch established as Section 7.5 specifies, for instance by a TRACK_STATUS request when the receiver has received no repair-track Group ID over MoQ (Sections 6.3.2 and 6.3.5): on layer 0, and on further layers in layer order where the receiver needs more symbols than layer 0 carries. The FETCH of a single group MAY be limited to the object range that covers the block's shortfall. The repair symbols it returns are deduplicated against the symbols already held by (SS_Start, RS_ID) (Section 8.3) and fed to the same decoder; their SS_Start and SSB_length also delimit a block the receiver had not delimited (Section 7.4). The receiver MUST NOT delay this request behind any non-keyframe or audio repair; Section 11.4.6 covers its interplay with a keyframe overlay. A FETCH completes or fails by MoQ Transport events, its last object or an error; a receiver MUST NOT declare it failed on a locally chosen timeout.¶
Only a keyframe-bearing block may stall video. While its unicast repair is outstanding, the receiver MAY hold video presentation for it. The block is unrecoverable when its unicast repair fails or completes without recovering it, or when the receiver holds no MoQ session through which to request it (for example a receiver that consumes an MMTP stream without a MoQ session, [MOQ-MULTICAST] Section 1.1). If the data of an unrecoverable block that the receiver could not recover includes, or may include, any part of a RAP (Section 11.4.1), the receiver treats the track as discontinuous, MAY stall video, and does not resume video before the next RAP ([MOQ-MMT] Section 6.1, step 6). Otherwise, as when it holds or has recovered every part of the block's RAPs (including through a keyframe overlay, Section 11.4.6), it conceals the block's remaining loss as for a non-keyframe block (Section 11.4.3).¶
If the next RAP arrives complete before a keyframe repair completes, the repair is moot: the receiver resumes from that RAP and SHOULD cancel the FETCH.¶
11.4.3. Other Video Blocks
For a non-keyframe-bearing block of a video track, in-band FEC remains the primary repair. A receiver MAY also request unicast repair for it, in the form of Section 11.4.2, but only on the terms of Section 11.4.5: never ahead of or concurrently with keyframe repair, and only within the budget that keyframe repair leaves unspent.¶
When such a block is unrecovered -- at its FEC deadline without unicast repair, or when its unicast repair has not completed by the presentation time of the first media it would repair -- the receiver MUST NOT stall. It conceals the affected frames, and every frame that depends on them, until the next RAP, and keeps presentation and audio/video synchronization running:¶
-
Concealment fills the presentation interval of the frames it replaces and ends at the authored presentation time of the next frame the receiver presents. The receiver MUST NOT drop later frames to absorb the loss. It derives no timing for the frames it replaces ([MOQ-MMT] Section 5.1).¶
-
The concealment method is an implementation choice: for example holding or replaying the last presented frame, or presenting decoder output in which missing reference data is filled (commonly visible as a solid or green fill). The receiver MUST NOT submit to the decoder a sample that the packaging's reassembly rules have invalidated ([MOQ-MMT] Section 5.2).¶
-
The next RAP ends concealment, and the receiver resumes normal decoding from it.¶
11.4.4. Audio Blocks
In-band FEC applies to the blocks of an audio track as to every block,
and a receiver MAY
request unicast repair for an audio block on the same best-effort
terms as for a non-keyframe video block (Section 11.4.5). RAP_flag
on an audio packet does not make its block keyframe-bearing; that
class applies to video tracks only.¶
When an audio block is unrecovered, the receiver MUST conceal the lost audio, for example with silence or packet-loss concealment, from the end of the last audio it presented to the authored presentation time of the next audio it presents, and MUST keep the audio clock advancing through the loss. It MUST NOT stall audio presentation waiting for a repair that has not completed by the presentation time of the lost audio.¶
11.4.5. Unicast Repair Budget and Priority
A receiver's unicast repair budget is derived from the catalog, not
from a receiver-local rate or byte constant. It is kept per MoQ
session and counted in bytes of repair symbol data, a repair symbol of
a track counting as that track's symbolSize T (Section 5.1).¶
-
Each block that Section 11.4.1 treats as keyframe-bearing, including a block of unknown class, credits the budget with P_t x T bytes when it reaches its FEC deadline, where P_t is the total repair count of its base instance (Section 6.4.1) and T is its track's
symbolSize.¶ -
A credit expires when the next keyframe-bearing block of the same source track reaches its FEC deadline, so unspent budget never accumulates beyond one block's credit per source track.¶
-
Every unicast repair FETCH debits the budget with the repair symbol bytes it requests. A FETCH of a Group range (Section 7.5) requests every Group that starts in the range, a number the receiver learns only from the response, and is debited with the repair symbol bytes of every Group it returns.¶
-
A receiver does not withhold a keyframe-bearing block's repair for lack of credit. For a block that it has delimited, it requests at most one repair-track Group per base repair layer, that is at most the P_t x T bytes that the block itself credits. For a run of blocks that it has not delimited, it issues the one Group range FETCH of Section 7.5 per base repair layer. Each Group that FETCH returns is the repair of one block of the run, and every block holds at least one SS_ID of a range that spans at most K SS_IDs (Section 7.5), so these FETCHes cost at most K x P_t x T bytes in all, which can exceed the credit. A debit that exceeds the remaining credit exhausts it: the budget never falls below zero, and no deficit carries over to a later credit. A receiver MUST NOT have more than one repair FETCH outstanding for the same block and repair layer.¶
-
Non-keyframe and audio repair MAY spend only unexpired credit that keyframe-bearing blocks left unspent, and a receiver MUST NOT issue a non-keyframe or audio repair FETCH that the remaining credit does not cover. Because the cost of a Group range FETCH is not known before it is issued, a receiver MUST NOT request non-keyframe or audio repair by a Group range.¶
-
A receiver MUST NOT issue a non-keyframe or audio repair FETCH while a keyframe repair FETCH is outstanding on the same session, and SHOULD cancel its outstanding non-keyframe and audio repair FETCHes when a keyframe-bearing block reaches its FEC deadline unrecovered.¶
Priorities follow the ranges of Section 10. A keyframe repair FETCH MUST carry a subscriber priority [I-D.ietf-moq-transport] in the Source Media range, numerically at most 191, and numerically no greater than the priority of the source track it repairs where the receiver knows that priority, so that it is delivered ahead of every repair track and is not shed with repair data under congestion. A non-keyframe or audio repair FETCH MUST carry a priority numerically no lower than that of the repair track it fetches, and so at least 192, so that it is shed first.¶
11.4.6. Relationship to the Keyframe Overlay
The keyframe overlay of Section 6.4 and this policy are complementary. The overlay is publisher-side and proactive: it protects RAP fragments across a block of its own, needs no return path, and so also serves sessionless receivers. This policy is receiver-side and reactive: it spends unicast repair only on keyframe-bearing blocks that in-band FEC actually failed to recover, and it needs a MoQ session. A receiver that holds both:¶
-
classifies blocks by Section 11.4.1 whether or not it holds the overlay;¶
-
MUST NOT defer the unicast repair of a keyframe-bearing block to wait for overlay recovery, whose latency is the overlay's own block span (Section 6.4.2), not the base deadline;¶
-
ends its wait for a RAP with whichever of base decoding, overlay decoding, or unicast repair supplies the RAP's fragments first; and¶
-
having recovered a block's RAP MFU fragments through the overlay, and holding the FT=0 and FT=1 data units that govern them, conceals the rest of that block's loss as for a non-keyframe block (Section 11.4.3) and SHOULD cancel any outstanding keyframe repair FETCH for it. The overlay covers only packets that set
RAP_flag(Section 6.4.2), so it does not by itself recover a lost FT=0 or FT=1 data unit.¶
12. ATSC 3.0 Compatibility
This specification is designed for interoperability with ATSC A/331 [ATSC-A331] Application-Layer FEC.¶
12.1. Mapping to A/331 AL-FEC
| ATSC A/331 Concept | MoQ FEC Equivalent |
|---|---|
<FECParameters>
|
Catalog fec field |
<RepairFlow>
|
Repair track subscription |
fecOTI (in S-TSID) |
Derived OTI (Section 4.2) |
| Source TOI range | Group ID range per Section 8 |
maximumDelay
|
No direct mapping to interleaveDepthMs; calculate the source-to-associated-repair delivery delay from the ROUTE schedule ([MOQ-MMT] Sections 12.2-12.3) |
overhead
|
From P and K ([MOQ-MMT] Sections 12.2-12.3) |
overhead is not carried in the catalog; it is converted to and from
repairSymbols by the informative rules of [MOQ-MMT] Sections 12.2
and 12.3.¶
Publishers ingesting ATSC 3.0 broadcasts SHOULD preserve the original
FEC parameters and pass them through in the catalog fec field.
overhead in particular is not passed through verbatim: the catalog
carries P rather than a percentage, and overhead is converted as
above.¶
12.2. Sub-Blocks in Broadcast Systems
This subsection is informative broadcast-interoperability guidance,
not an interoperability requirement of this document. Sub-block
operation (Section 7.3) remains available to broadcast systems that
carry an explicit OTI, such as the A/331 S-TSID fecOTI; the
ISO 23008-1 AL-FEC message carries no OTI, and the split source
blocks of [ISO.23008-1] are the two-stage FEC coding structure of
Clause C.2.2, which this document does not use. The number of
source symbols per sub-block (K_sub <= K) is derived from the
signaled parameters: K_sub = ceil(K / N), where K is the block's
source symbol count, at most the catalog sourceSymbols, and N is the
Number of Sub-Blocks field of the explicitly signaled OTI.¶
When sub-blocks are used:¶
-
When positive,
interleaveDepthMskeeps its Section 5.1 meaning, the span of the FULL block. A sub-block's own span can be estimated asinterleaveDepthMs * K_sub / Kfor partial-recovery scheduling; the estimate never replaces the full-block field or deadline (Section 9). A zero value uses the ISO packet-count alternative and supplies no millisecond span. This enables faster partial recovery at the cost of higher repair overhead (P repair symbols per sub-block instead of per block).¶ -
The receiver tracks source symbol arrivals per sub-block (keyed by the block's SS_Start and the sub-block index) and can emit recovered data as soon as each sub-block completes, without waiting for the full block.¶
-
The receiver uses the derived sub-block length K_sub (not K from the catalog) for per-sub-block recovery when K_sub < K.¶
Sub-blocks are primarily useful for large-K configurations (K >= 64) where full-block recovery latency exceeds acceptable limits.¶
13. Interaction with CMAF Packaging
This section is informative.¶
This specification's signaling (Section 5) is container-agnostic, and a repair track can sit alongside a source track carrying CMAF content in MMTP packaging in the same namespace:¶
+-------------------------------------------------+ | MoQ Track Namespace | +-------------------------------------------------+ | | | Source Track (CMAF content, MMTP packaged) | | +-----------------------------------------+ | | | Object 0: MMTP packet carrying FT=0 | | | | Object 1: MMTP packet carrying FT=1 | | | | Object 2: MMTP packet carrying FT=2 | | | | ... | | | +-----------------------------------------+ | | | | Repair Track (this specification) | | +-----------------------------------------+ | | | Object 0: Repair for Block 0 | | | | Object 1: Repair for Block 1 | | | | ... | | | +-----------------------------------------+ | | | +-------------------------------------------------+¶
The symbol construction, however, is not container-agnostic: the only source-symbol construction this document specifies is the MMTP-packet construction of Section 7.3. Applying FEC directly to CMAF chunk payloads ([I-D.ietf-moq-cmsf]) would require a companion specification defining the chunk-to-symbol segmentation, padding, length framing, and ESI mapping, under a block profile of its own (Section 5.1); none is defined here, and this section sketches the intended track relationship only. A CMAF deployment wanting FEC protection carries the media as mmtp-packaged tracks (an MPU corresponds to a CMAF Fragment; see [MOQ-MMT]).¶
A publisher MAY choose a segment duration equal to interleaveDepthMs
and close blocks at segment boundaries, so that a segment holds one
chosen block's source symbols and a CDN relay can perform FEC recovery
at the segment level before forwarding to FEC-unaware HLS/DASH clients.
The boundary is an explicit publisher choice; the duration alone does
not create or identify a block.¶
14. Security Considerations
14.1. FEC Does Not Provide Confidentiality
FEC repair symbols are derived from source data. If source data is encrypted, repair symbols will also be encrypted by virtue of operating on ciphertext. However, FEC itself provides no confidentiality guarantees.¶
14.2. Repair Symbol Manipulation
An attacker who can modify repair symbols could cause receivers to reconstruct incorrect source data. Integrity protection of repair tracks is RECOMMENDED, using the same mechanisms as source tracks (e.g., QUIC packet protection).¶
14.3. Amplification
FEC repair symbols represent additional bandwidth. Publishers MUST NOT generate excessive repair symbols that could be used for bandwidth amplification attacks. The repair overhead (P/K) SHOULD be limited to reasonable values (e.g., <= 50%). The bound applies per FEC instance (Section 6.4.1).¶
Layering changes the shape of the amplification exposure, because the attacker's lever is now which layers a victim can be made to receive rather than only whether it receives repair at all. Each layer i adds P_i x T bytes per source block, so a receiver induced to hold more layers receives proportionally more repair traffic. Deployments SHOULD bound the number of layers any single receiver may hold, and SHOULD apply the same join authorization to repair-layer endpoints as to media endpoints; a repair-only endpoint (Section 6.3.6) is not less sensitive than a media one merely because it carries no media.¶
A receiver MUST NOT be made to receive a repair layer it did not join. A publisher or relay MUST NOT push a repair-layer endpoint to a receiver that has not joined it, and MUST NOT add a layer to an endpoint a receiver has already joined as a way of raising that receiver's protection.¶
14.4. Multicast FEC Security
When FEC is used over multicast (SSM/AMT), additional considerations apply:¶
-
No QUIC Protection: Multicast UDP lacks QUIC's integrity guarantees. Publishers SHOULD use DTLS-SRTP or equivalent for payload encryption when confidentiality is required.¶
-
Repair Injection: Attackers could inject malicious repair symbols on multicast networks. Receivers SHOULD verify FEC block consistency by checking that decoded data matches expected patterns (e.g., valid media container structure).¶
-
Source Authentication: See [MOQ-MULTICAST] Section 7.1.¶
-
Block Integrity: Receivers MAY implement block-level checksums to detect corrupted recovery. If decoded source data fails integrity checks, receivers SHOULD request retransmission via unicast fallback.¶
-
Repair Policy Inputs: The in-band evidence that Section 11.4.1 classifies blocks from, and the SSB_length by which Section 7.4 completes a short block, are unauthenticated on bare multicast. An injected packet that marks a block keyframe-bearing costs at most the unicast repair that block's own credit covers (Section 11.4.5). An injected source packet inside a block's gap can instead narrow the bounds of Section 11.4.1 until a keyframe-bearing block is classified otherwise, and an injected repair packet carrying a false SS_Start or SSB_length, accepted before the genuine ones, can mis-delimit a block, mark it complete early, or cause its genuine repair packets to be discarded as inconsistent (Section 7.4). Deployments exposed to injection SHOULD authenticate source and repair packets ([MOQ-MULTICAST] Section 7.2).¶
14.5. ATSC 3.0 Signed Region (A3SA) Considerations
The Source FEC Payload ID falls outside the A3SA signed region, and neither [ISO.23008-1] nor [ATSC-A331] provides a carriage of the SS_ID inside it (Section 8.5). An attacker who can modify it without detection could redirect source symbols to incorrect FEC blocks, causing recovery failures or corrupted output. A receiver that requires authenticated FEC block assignment therefore treats the trailer as Section 8.5 requires. On multicast networks without A3SA verification, receivers SHOULD cross-check the SS_ID against the MMTP packet_sequence_number to detect obvious tampering (e.g., an SS_ID that advances further than the packet_sequence_number of the same packet_id, whereas SS_ID advances by one per FEC source packet, Section 8.3).¶
15. IANA Considerations
15.1. MoQ Registrations
This document requests one registration in the MOQT Properties registry of [I-D.ietf-moq-transport]:¶
| Type | Name | Scope | Specification |
|---|---|---|---|
| 0x11 | FEC_SOURCE_INFO | Object | This document, Section 5.3 |
The type is odd, so under the key-value parity rule of [I-D.ietf-moq-transport] the Property is length-prefixed and byte-valued (Section 5.3). The scope is Object: FEC Source Info describes the individual object it tags, and carries no track-wide meaning.¶
0x11 lies in the range 0x00 to 0x77, for which [I-D.ietf-moq-transport] states a registration policy of Standards Action or IESG Approval. That policy is not reachable by an individual draft, so this document asks for 0x11 as a provisional registration in the table [I-D.ietf-moq-transport] maintains for other active drafts in the MoQ working group, on the same terms as the existing entries for draft-ietf-moq-loc and draft-ietf-moq-secure-objects. That ask is contingent on this document being adopted. If 0x11 is not available on those terms, an odd value in the range 0x80 to 0x37FF, whose policy is Specification Required, is obtainable by this document on its own; it costs one additional byte per tagged object and changes nothing else in this specification.¶
The even value 0x10, used by deployed implementations for this purpose, is deliberately not requested, and this document could not reserve it in any case: [I-D.ietf-moq-transport] already lists 0x10 as the TIMESTAMP Object Property of draft-ietf-moq-loc, at Object scope in the same Property Type space. Section 5.3 gives the resulting collision and its consequences.¶
This document requests no registration in any MoQ message type registry. FEC signaling uses no MoQ control message (Section 5.2); no document in this suite requests a control-message codepoint. The header extension type 0x8B01 of Section 8.5.1 is an MMTP value, not a MoQ one; [ISO.23008-1] Clause 9.2.3 defines no registry of MMTP header extension types, so its use requires no IANA action.¶
15.2. FEC Algorithm Registry
This document requests creation of a "MoQ FEC Algorithms" registry with the following initial values:¶
| Value | Algorithm | Reference |
|---|---|---|
| 0x00 | None | This document |
| 0x01 | RaptorQ | [RFC6330] |
| 0x02 | Reed-Solomon | [RFC5510] |
| 0x03-0xFF | Unassigned |
New registrations require Specification Required policy.¶
Only "None" (0x00) and RaptorQ (0x01) are specified for interoperation by this document; other registered values, including Reed-Solomon (0x02), are extension points whose interoperable use requires their own specifications (Section 4.3).¶
15.3. Catalog Packaging Value
This document defines the catalog packaging value "fec-repair"
(Section 5.1) for repair tracks, extending the allowed packaging
values of the MoQ Streaming Format [I-D.ietf-moq-msf]
Section 5.2.4. If a registry of packaging values is established
for that format, this document requests registration of:¶
| Value | Description | Reference |
|---|---|---|
| "fec-repair" | Repair objects protecting a source track | This document |
16. References
16.1. Normative References
- [I-D.ietf-moq-msf]
- Law, W. and S. Nandakumar, "MOQT Streaming Format", Work in Progress, Internet-Draft, draft-ietf-moq-msf-01, , <https://datatracker.ietf.org/doc/html/draft-ietf-moq-msf-01>.
- [I-D.ietf-moq-transport]
- Nandakumar, S., Vasiliev, V., Swett, I., and A. Frindell, "Media over QUIC Transport", Work in Progress, Internet-Draft, draft-ietf-moq-transport-22, , <https://datatracker.ietf.org/doc/html/draft-ietf-moq-transport-22>.
- [ISO.23008-1]
- ISO/IEC, "Information technology - High efficiency coding and media delivery in heterogeneous environments - Part 1: MPEG media transport (MMT)", ISO/IEC 23008-1:2023, .
- [ISO.23008-1.AMD1]
- ISO/IEC, "Information technology - High efficiency coding and media delivery in heterogeneous environments - Part 1: MPEG media transport (MMT) - Amendment 1: Signalling of adaptive FEC scheme", ISO/IEC 23008-1:2023/Amd 1:2025, .
- [MOQ-MMT]
- Ramadan, O., "MPEG Media Transport (MMT) Packaging for Media over QUIC", Work in Progress, Internet-Draft, draft-ramadan-moq-mmt-00, , <https://datatracker.ietf.org/doc/html/draft-ramadan-moq-mmt-00>.
- [QUIC-MULTICAST]
- Holland, J., Pardue, L., Franke, M., and K. Rose, "Multicast Extension for QUIC", Work in Progress, Internet-Draft, draft-jholland-quic-multicast-09, , <https://datatracker.ietf.org/doc/draft-jholland-quic-multicast/>.
- [RFC1982]
- Elz, R. and R. Bush, "Serial Number Arithmetic", RFC 1982, DOI 10.17487/RFC1982, , <https://www.rfc-editor.org/info/rfc1982>.
- [RFC2119]
- Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, , <https://www.rfc-editor.org/info/rfc2119>.
- [RFC6330]
- Luby, M., Shokrollahi, A., Watson, M., Stockhammer, T., and L. Minder, "RaptorQ Forward Error Correction Scheme for Object Delivery", RFC 6330, DOI 10.17487/RFC6330, , <https://www.rfc-editor.org/info/rfc6330>.
- [RFC8174]
- Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, , <https://www.rfc-editor.org/info/rfc8174>.
16.2. Informative References
- [ARIB-B60]
- ARIB, "MMT-Based Media Transport Scheme in Digital Broadcasting Systems", ARIB STD-B60 Version 1.14.
- [ATSC-A331]
- ATSC, "Signaling, Delivery, Synchronization, and Error Protection", ATSC A/331:2026-02, , <https://www.atsc.org/atsc-documents/3312017-signaling-delivery-synchronization-error-protection/>.
- [I-D.ietf-moq-cmsf]
- Law, W., "CMSF- a CMAF compliant implementation of MOQT Streaming Format", Work in Progress, Internet-Draft, draft-ietf-moq-cmsf-01, , <https://datatracker.ietf.org/doc/html/draft-ietf-moq-cmsf-01>.
- [MOQ-MULTICAST]
- Ramadan, O., "Multicast Delivery and Endpoint Discovery for Media over QUIC", Work in Progress, Internet-Draft, draft-ramadan-moq-multicast-00, , <https://datatracker.ietf.org/doc/html/draft-ramadan-moq-multicast-00>.
- [RFC4607]
- Holbrook, H. and B. Cain, "Source-Specific Multicast for IP", RFC 4607, DOI 10.17487/RFC4607, , <https://www.rfc-editor.org/info/rfc4607>.
- [RFC5510]
- Lacan, J., Roca, V., Peltotalo, J., and S. Peltotalo, "Reed-Solomon Forward Error Correction (FEC) Schemes", RFC 5510, DOI 10.17487/RFC5510, , <https://www.rfc-editor.org/info/rfc5510>.
- [RFC7450]
- Bumgardner, G., "Automatic Multicast Tunneling", RFC 7450, DOI 10.17487/RFC7450, , <https://www.rfc-editor.org/info/rfc7450>.
- [RFC8777]
- Holland, J., "DNS Reverse IP Automatic Multicast Tunneling (AMT) Discovery", RFC 8777, DOI 10.17487/RFC8777, , <https://www.rfc-editor.org/info/rfc8777>.
- [RFC9706]
- Giuliano, L., Lenart, C., and R. Adam, "TreeDN: Tree-Based Content Delivery Network (CDN) for Live Streaming to Mass Audiences", RFC 9706, DOI 10.17487/RFC9706, , <https://www.rfc-editor.org/info/rfc9706>.
Appendix A. Example Message Flows
A.1. Catalog-Driven FEC
The subscriber learns the complete FEC configuration from the track's catalog entry before subscribing:¶
"fec": {
"algorithm": "raptorq",
"blockProfile": "iso-ssbg1-v1",
"sourceSymbols": 32,
"repairSymbols": 8,
"symbolSize": 1312,
"interleaveDepthMs": 1000,
"reorderToleranceMs": 40,
"repairTrack": "video/repair"
}
¶
Publisher Subscriber
| |
| (catalog obtained; fec field read) |
| |
| SUBSCRIBE(sub_id=1, track=video) |
|<--------------------------------------|
| |
| SUBSCRIBE_OK(sub_id=1) |
|-------------------------------------->|
| |
| SUBSCRIBE(sub_id=2, |
| track=video/repair) |
|<--------------------------------------|
| |
| SUBSCRIBE_OK(sub_id=2) |
|-------------------------------------->|
| |
| [Source objects of group 0] |
|-------------------------------------->|
| |
| [Repair objects, group=0, obj=0..7] |
|-------------------------------------->|
| |
¶
In this flow the track is mmtp-packaged with a one-second group
duration (one MPU per MoQ Group, [MOQ-MMT] Section 4.3). That group
duration describes the MoQ grouping; it does not derive an FEC block.
For example, if the first block starts at SS_ID 0 and is full, its
repair Group is its extended SS_Start, 0 (Section 7.5), the next block
starts at SS_ID 32, and its repair Group is 32. A publisher MAY choose
shorter blocks inside a Group or a block that crosses the Group
boundary; each repair packet carries the actual SSB_length. The
subscriber's decoder configuration is derived from the catalog fields
and each block's SSB_length (Section 4.2): for a full block
(SSB_length = K = 32), Transfer Length F = SSB_length x T = 32 x
1312 = 41,984 bytes, Symbol Size T = 1312, Z = 1, N = 1, Al = 8. No
in-session message is required, and this track carries no AL-FEC
signaling object ([MOQ-MMT] Section 8).¶
Appendix B. Catalog Example
Complete catalog with FEC and multicast configuration:¶
{
"version": "draft-01",
"tracks": [
{
"name": "video",
"packaging": "mmtp",
"mmtpMode": "mfu",
"timescale": 90000,
"presentationAnchorTicks": 0,
"groupDurationMs": 1000,
"codec": "avc1.64001f",
"width": 1920,
"height": 1080,
"framerate": 30,
"bitrate": 4990000,
"fec": {
"algorithm": "raptorq",
"blockProfile": "iso-ssbg1-v1",
"sourceSymbols": 625,
"repairSymbols": 125,
"symbolSize": 1000,
"interleaveDepthMs": 1000,
"reorderToleranceMs": 40,
"repairTrack": "video/repair"
}
},
{
"name": "video/repair",
"packaging": "fec-repair",
"depends": ["video"],
"repairSymbols": 125,
"priority": 240
},
{
"name": "audio",
"packaging": "mmtp",
"mmtpMode": "mfu",
"timescale": 48000,
"presentationAnchorTicks": 0,
"groupDurationMs": 1000,
"codec": "mp4a.40.2",
"samplerate": 48000,
"channelConfig": "2",
"bitrate": 128000,
"fec": {
"algorithm": "raptorq",
"blockProfile": "iso-ssbg1-v1",
"sourceSymbols": 32,
"repairSymbols": 8,
"symbolSize": 512,
"interleaveDepthMs": 1000,
"reorderToleranceMs": 40,
"repairTrack": "audio/repair"
}
},
{
"name": "audio/repair",
"packaging": "fec-repair",
"depends": ["audio"],
"repairSymbols": 8,
"priority": 240
}
],
"multicast": {
"endpoints": [{
"sourceAddress": "198.51.100.100",
"groupAddress": "232.1.1.50",
"port": 5000,
"tracks": [
{ "name": "video", "packetId": 1 },
{ "name": "video/repair", "packetId": 2 },
{ "name": "audio", "packetId": 3 },
{ "name": "audio/repair", "packetId": 4 }
]
}]
}
}
¶
Parameter consistency: both tracks use one-second MMTP groups (one MPU per MoQ Group), and each has a 1000 ms source/repair send-span budget. The group duration does not determine the FEC partition. A worked capacity check must include the MMTP and MPU-mode headers, not only the media bitrate. With no MMTP header extension, a timed FT=2 packet has the following media capacity, depending on whether it starts a data unit ([MOQ-MMT] Section 5.2):¶
FI=0 or FI=1: T - 2 (length) - 12 (MMTP) - 8 (MPU) - 14 (DU) = T - 36 FI=2 or FI=3: T - 2 (length) - 12 (MMTP) - 8 (MPU) = T - 22¶
The source packet also carries a 4-byte Source FEC Payload ID on the
wire, outside the protected packet and therefore outside these symbol
budgets. FT=0/FT=1 metadata consumes source packets but does not carry
sample bytes, and any MMTP extension consumes additional space. Every
protected MMTP packet still MUST fit within T - 2. Using the larger
continuation capacity gives a media ceiling, not a packetization plan:¶
- Video: 4,990,000 bit/s x 1.0 s / 8 = 623,750 bytes of media per
one-second group.
K x (T - 22) = 625 x 978 = 611,250bytes is an upper bound on the media capacity of one full block. The media therefore needs at leastceil(623,750 / 978) = 638source packets and at least two K=625 blocks; MMTP metadata, fragmentation, and authored packet boundaries can require more. Repair overhead isP / K = 125 / 625 = 20%.¶ - Audio: 128,000 bit/s x 1.0 s / 8 = 16,000 bytes of media per group;
the upper-bound capacity of one full block is
K x (T - 22) = 32 x 490 = 15,680bytes. The media therefore needs at leastceil(16,000 / 490) = 33source packets and at least two K=32 blocks; packetization and metadata can require more. Repair overhead isP / K = 8 / 32 = 25%.¶
The publisher MUST choose the actual source-packet count and block
boundaries so that every packet, including FT=0 and FT=1 metadata,
fits the selected symbol size and every block's repair fields describe
the actual (SS_Start, SSB_length) partition. These calculations are
capacity examples, not a rule that one FEC block equals one Group.¶
The catalog envelope is the MSF root ([I-D.ietf-moq-msf]
Section 5.1); track entries carry the flat base track fields of
[I-D.ietf-moq-msf] Section 5.2 (codec, width, samplerate,
...) alongside the fec object this document defines, and inherit
the namespace of the catalog track ([I-D.ietf-moq-msf]
Section 5.2.2). The multicast field uses the multicast endpoint format defined in
[MOQ-MULTICAST] Section 4.1: a one-element endpoints array. Per
[MOQ-MULTICAST] Section 5, all multicast delivery uses MMTP packets
regardless of a track's unicast packaging, so each track listed on
the endpoint carries a packetId that routes its MMTP packets on the
multicast UDP path.¶