| Internet-Draft | MoQ FEC | October 2026 |
| Ramadan | Expires 29 April 2027 | [Page] |
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 needs no in-session messages. It also defines conventions for repair track naming, the format of repair objects, and two block profiles that fix how source symbols and FEC blocks are formed and identified: an ISO/IEC 23008-1 profile for tracks packaged as MPEG Media Transport Protocol (MMTP) packets, and an object profile for tracks packaged as Low Overhead Media Container (LOC) or Common Media Application Format (CMAF) objects. It fully specifies two FEC schemes: the systematic Reed-Solomon code over GF(2^8) of ISO/IEC 23008-10, which is mandatory to implement, and RaptorQ (RFC 6330), which is optional. An algorithm registry provides extension points for additional schemes. FEC enables receivers to recover from packet loss without retransmission latency. The MMTP profile is designed for compatibility with ATSC 3.0 (A/331) and ARIB STD-B60 broadcast systems.¶
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 29 April 2027.¶
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.¶
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:¶
iso-ssbg1-v1, which forms source symbols and FEC blocks
from MPEG Media Transport Protocol (MMTP) packets as Annex C of
[ISO.23008-1] does, and
moq-object-v1, which forms them from whole MoQ objects¶
The mechanism protects tracks whose packaging a block profile admits.
Under iso-ssbg1-v1 it protects MMTP-packaged tracks [MOQ-MMT], and
Section 7.3 specifies the protected source symbol. Under
moq-object-v1 it protects tracks packaged as Low Overhead Media
Container (LOC) [I-D.ietf-moq-loc] or Common Media Application
Format (CMAF) [I-D.ietf-moq-cmsf], and Section 7.6
specifies the protected source symbols. Section 13 compares the two
ways to protect CMAF content.¶
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, in repair objects whose form the source
track's block profile fixes (Section 7.1): MMTP FEC repair packets
([ISO.23008-1] Section C.4.3) under iso-ssbg1-v1, and a Repair FEC
Payload ID with one symbol under moq-object-v1 (Section 7.6.3).
Under iso-ssbg1-v1, 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); under iso-ssbg1-v1, the ISO
source symbol block
(3.1.34), generated from a source packet block (3.1.32). Under
raptorq, 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 iso-ssbg1-v1, one FEC source packet framed as
Section 7.3 specifies, and under moq-object-v1, one T-byte slice of
a Protected Object Unit (Section 7.6.1).¶
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. It is defined only under iso-ssbg1-v1.¶
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 is not a millisecond span: under iso-ssbg1-v1 it selects the
ISO packet-count alternative, and under moq-object-v1 it is
equivalent to an absent field (Section 5.1).¶
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. Under
iso-ssbg1-v1 it is carried in the Source FEC Payload ID of its FEC
source packet ([ISO.23008-1] Section C.5.2) and advances by one per
FEC source packet. Under moq-object-v1 the FEC Source Info Property
of a source object (Section 5.3) carries the SS_ID of its first source
symbol, and the SS_ID advances by the object's symbol count
(Section 7.6.2). It 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 source symbols are formed
from a source packet or a source object and how FEC blocks are sized,
delimited and identified, named per FEC-protected source track by
fec.blockProfile (Section 5.1).¶
Protected Object Unit: Under moq-object-v1, the bytes that one
source object contributes to its FEC block: its Location, its
Immutable Properties and its payload, framed as Section 7.6.1
specifies.¶
The protocol operates as follows (Appendix A.1 shows the exchange):¶
fec
object (Section 5), which carries the complete FEC configuration¶
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 they are delivered on QUIC streams, QUIC retransmission recovers lost packets, and receivers MAY skip FEC decoding. Stream delivery is reliable only until a delivery timeout or a stream reset abandons an object ([I-D.ietf-moq-transport] Section 5.2); a receiver that holds repair symbols for the object's block can still recover it by FEC.¶
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, and for Reed-Solomon, Section 4.4 fixes the code and its parameters are derived in the same way (Section 4.5).¶
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 SSB_length symbols (source or repair), plus a small decoding overhead (Section 6.3.2), are received. It is OPTIONAL (Section 4.3).¶
Reed-Solomon (0x02): The systematic Reed-Solomon erasure code over GF(2^8) of [ISO.23008-10] Clause 6, restated in Section 4.4. It recovers a block from any SSB_length of its distinct source and repair symbols. An FEC instance under it holds at most 255 source and repair symbols per block (Section 4.5). It is the mandatory-to-implement scheme (Section 4.3).¶
Both codes are systematic: the source symbols of a block are among its
encoding symbols, so a receiver uses the source symbols it receives as
they arrive. The two values correspond to the FEC code points 3 (the
"6330 code") and 1 (the RS code) of [ISO.23008-10] Table 1, which an
AL-FEC message carries in fec_code_id_for_repair_flow ([MOQ-MMT]
Section 8.3).¶
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 the track's block profile (Sections 7.3 and 7.6.1), as
follows:¶
symbolSize,
exact because every source symbol of either block profile 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 from
sourceSymbols, 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).¶
symbolSize.¶
symbolSize MUST 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.¶
Reed-Solomon is the mandatory-to-implement FEC scheme: an implementation that performs FEC decoding under this specification MUST support "reed-solomon", which Sections 4.4 and 4.5 fully specify. "raptorq" is OPTIONAL.¶
The MMT AL-FEC framework on which the MMTP profile of this document rests ([ISO.23008-1] Annex C) requires no FEC code: it carries whichever code the AL-FEC message names by its [ISO.23008-10] code point, and ATSC 3.0, which applies AL-FEC to an MMTP session through that framework, requires none either ([ATSC-A331] Section 8.1.2.5; Section 12). This document therefore specifies the codes it uses. Reed-Solomon is the mandatory scheme because it is small to implement, recovers a block from exactly SSB_length of its symbols, and is a code of that framework ([ISO.23008-10] code point 1). RaptorQ stays specified, code point 3, for its block size: it serves every block size this document allows. A RaptorQ block holds up to 56403 source symbols (Section 6.3.4, rule 6), while a Reed-Solomon block holds at most 255 source and repair symbols (Section 4.5). At 8 Mb/s with symbols of 1200 bytes, such a block spans at most about 300 ms of media, so the multi-second interleave windows of Section 9 need RaptorQ at that rate. A code of [ISO.23008-10] other than these two is outside this document until the registry below lists it.¶
The algorithm registry (Section 15.2) provides an extension point for additional schemes. A registered value other than "none", "raptorq" and "reed-solomon" needs a specification of its own, giving its symbol construction, parameter derivation and repair object semantics, 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. A
track under "raptorq" is therefore protected only for the receivers
that implement it.¶
The "reed-solomon" algorithm is the systematic Reed-Solomon erasure code over GF(2^8) of [ISO.23008-10] Clause 6, to which that document assigns FEC code point 1 (its Table 1). This section restates the code, because [ISO.23008-10] is not freely available. If this restatement and [ISO.23008-10] Clause 6 differ, [ISO.23008-10] governs. Appendix C gives test vectors.¶
Field. The code works in GF(2^8) defined by the primitive polynomial x^8 + x^4 + x^3 + x^2 + 1 (0x11D), the polynomial that [RFC5510] Section 8.1 gives for m = 8. alpha is a root of that polynomial and is represented by the byte 0x02. A byte with bits b_7 (the most significant) down to b_0 represents the element b_7 alpha^7 + b_6 alpha^6 + ... + b_1 alpha + b_0. Addition is the bitwise exclusive OR of bytes, and multiplication is the product of polynomials modulo 0x11D, so alpha^8 is 0x1D. This document defines the code over GF(2^8) only.¶
Generator matrix. The code is generated by G = [I | A], where I is an identity matrix and A is a Cauchy matrix ([ISO.23008-10] Clause 6.2 writes G = [I; A]). Row i of A belongs to the source symbol at ESI i, and column j to the repair symbol whose RS_ID is j. The entries of A are:¶
A_{i,j} = 1 / (x_i + y_j)
x_i = alpha^(254 - i)
y_j = alpha^j
¶
A block that holds SSB_length source symbols and RSB_length repair symbols uses rows 0 to SSB_length - 1 and columns 0 to RSB_length - 1 of A. x_i and y_j differ whenever i + j < 254, so every entry the block uses is defined when SSB_length + RSB_length is at most 255, the bound of [ISO.23008-10] Clause 6.2. An entry depends on i and j alone: not on K, not on SSB_length and not on P.¶
Encoding. Every symbol of a block is T bytes long. Let s_i be the source symbol at ESI i (Section 8.3), for i from 0 to SSB_length - 1. The repair symbol r_j whose RS_ID is j is computed one byte position at a time, as [RFC5510] Section 8.4 applies its code to symbols: for each byte position u from 0 to T - 1,¶
r_j[u] = sum over i < SSB_length of A_{i,j} * s_i[u]
¶
where the sum and the products are computed in GF(2^8). The source symbols themselves are sent unchanged.¶
Short blocks. A block whose SSB_length is less than K uses only the first SSB_length rows of A. Its repair symbols equal those of a block of K source symbols whose symbols at ESIs SSB_length to K - 1 are all zero, because a zero symbol adds nothing to any sum. No zero symbol is sent or counted in SSB_length (Section 7.4).¶
Decoding. Every square submatrix of a Cauchy matrix is invertible ([ISO.23008-10] Clause 6.2), so the code is maximum distance separable: a receiver that holds any SSB_length distinct symbols of a block, source and repair in any mix, recovers every source symbol of the block. Let M be the set of ESIs of the source symbols it lacks, and R a set of |M| RS_IDs of repair symbols that it holds. For each byte position u and each j in R:¶
sum over i in M of A_{i,j} * s_i[u]
= r_j[u] + sum over i < SSB_length, i not in M,
of A_{i,j} * s_i[u]
¶
The square matrix of the entries A_{i,j} with i in M and j in R is a submatrix of A and is therefore invertible. The receiver inverts it once per block and applies the result at every byte position. Any decoding method that yields the same source symbols is acceptable.¶
The field is that of [RFC5510], but the generator matrix is not the Vandermonde-derived matrix of [RFC5510] Section 8.2, and this document uses neither the FEC Payload IDs nor the source block partitioning of [RFC5510]. Several systematic Reed-Solomon constructions over GF(2^8) are in use, and they produce different repair symbols from the same source symbols. Appendix C gives test vectors that tell this construction apart from the others.¶
As for RaptorQ (Section 4.2), no decoder configuration is carried on
the wire, and the code has no OTI to carry. When a track's catalog
fec.algorithm is "reed-solomon", receivers MUST configure the decoder
of each FEC block from the catalog fields (Section 5.1) and the
block's Repair FEC Payload ID (Section 7.1), under the source symbol
construction of the track's block profile (Sections 7.3 and 7.6.1), as
follows:¶
symbolSize. Every source and repair symbol
is exactly T bytes. The RaptorQ rule that T is a multiple of 8
(Section 4.2) does not apply.¶
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). As under RaptorQ, its per-block
inputs travel in the Repair FEC Payload ID of every repair packet of
the block.¶
The catalog keeps every FEC instance under "reed-solomon" within the
bound of Section 4.4: K + P is at most 255, where K is the instance's
sourceSymbols and P its total repair count over all its repair
layers (Section 6.3.4, rule 12). SSB_length + RSB_length is then at
most 255 in every block. In addition to the checks of Section 7.4, a
receiver MUST discard a repair packet of such a track whose
SSB_length + RSB_length exceeds 255, or whose RS_ID is not less than
RSB_length, leaving the state of every block unchanged. Neither
packet is a symbol of a code that Section 4.4 defines. A repair
packet whose RSB_length is less than O_i + P_i for a layer i that the
receiver holds, of that layer's own track where i is above 0 or of a
block to which the check of Section 6.3.9 applies, is handled by
that section, which fails closed, and not by this rule; on any other
packet this rule applies to it, one of a block generated before an
append, carrying no symbol of layer i, or one of layer 0's track
generated under a previous total (Section 6.3.9).¶
Repair layers (Section 6.3) carry disjoint ranges of columns: layer i carries columns O_i to O_i + P_i - 1 (Section 6.3.2). A column depends on its RS_ID alone, so a repair symbol is the same whichever layer carries it and whatever other layers exist, and symbols from any subset of layers combine in one decode. A keyframe overlay (Section 6.4) is a separate FEC instance, with its own rows, numbered from its overlay SS_IDs, its own columns and its own bound: K_overlay + P_overlay is at most 255, whatever the base instance uses.¶
For example, this catalog protects an mmtp track under "reed-solomon":¶
{
"version": "draft-01",
"tracks": [
{
"name": "video",
"packaging": "mmtp",
"isLive": true,
"mmtpMode": "mfu",
"timescale": 90000,
"presentationAnchorTicks": 0,
"groupDurationMs": 1000,
"codec": "avc1.64001f",
"width": 1280,
"height": 720,
"framerate": 30,
"bitrate": 2500000,
"fec": {
"algorithm": "reed-solomon",
"blockProfile": "iso-ssbg1-v1",
"sourceSymbols": 32,
"repairSymbols": 8,
"symbolSize": 1320,
"interleaveDepthMs": 200,
"reorderToleranceMs": 40,
"repairTrack": "video/repair"
}
},
{
"name": "video/repair",
"packaging": "fec-repair",
"isLive": true,
"depends": ["video"],
"repairSymbols": 8,
"priority": 240
}
]
}
¶
K + P is 32 + 8 = 40, within the bound. A full block uses rows 0 to 31 and columns 0 to 7 of A, and its repair packets carry SSB_length 32 and RSB_length 8. A short block of 20 source symbols uses rows 0 to 19 and the same columns, and its repair packets carry SSB_length 20. The repair symbol with RS_ID 3 is column 3 in both blocks, at ESI 35 in the first and ESI 23 in the second. The full block recovers once the receiver holds any 32 of its 40 symbols, and the short block once it holds any 20 of its 28. Rule 12 leaves room for repair layers (Section 6.3.9) of at most 215 more repair symbols in all, since 32 + 8 + 215 = 255, and Section 14.3 recommends far fewer.¶
The catalog (Section 5.2) is an MSF catalog
[I-D.ietf-moq-msf], delivered on the track named catalog
([I-D.ietf-moq-msf] Section 5); for mmtp tracks it is extended by
the documents of this suite as described in [MOQ-MMT] Section 12.
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:¶
{
"version": "draft-01",
"tracks": [
{
"name": "video",
"packaging": "mmtp",
"isLive": true,
"mmtpMode": "mfu",
"timescale": 90000,
"presentationAnchorTicks": 0,
"groupDurationMs": 1000,
"codec": "avc1.640028",
"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",
"isLive": true,
"depends": ["video"],
"repairSymbols": 125,
"priority": 240
}
]
}
¶
(Appendix B works this parameter set through in full. Section 7.6.7
shows a loc track under moq-object-v1, and Section 4.5 a track under
"reed-solomon".)¶
Field definitions:¶
algorithm (string, REQUIRED if fec present): FEC scheme identifier.¶
blockProfile (string, REQUIRED when algorithm is not "none"):
The block profile of the track's
FEC: the rules that fix how source symbols are formed from a source
packet or a source object, 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 two values, which Section 15.4 registers. Each
admits only the source track packaging values named with it:¶
"iso-ssbg1-v1": the ISO/IEC 23008-1 Annex C profile of this
document, all of whose rules a receiver applies together. It
admits mmtp. A source symbol is the ssbg_mode1 framing of one
FEC source packet (Section 7.3). A block holds SSB_length source
symbols, with sourceSymbols as 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).¶
"moq-object-v1": the object profile of this document
(Section 7.6), all of whose rules a receiver applies together. It
admits loc and cmaf. The Protected Object Unit of a source
object spans s(o) consecutive source symbols (Section 7.6.1). A
block holds whole units, SSB_length source symbols in all, with
sourceSymbols as the upper bound on SSB_length (Section 7.6.2).
SS_IDs advance by s(o) per source object, blocks are consecutive,
and a source symbol is placed in its block by range membership
(Section 8.3). SS_ID arithmetic and repair Group IDs are those of
Section 7.5. A repair object carries no MMTP header
(Section 7.6.3). The profile defines no in-band signaling and no
keyframe overlay (Section 7.6.6).¶
A receiver MUST NOT apply FEC to a track whose blockProfile is
absent, names a profile the receiver does not implement, or names a
profile that does not admit the track's packaging. 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). Under iso-ssbg1-v1 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. K counts
source symbols, not objects: under moq-object-v1 a source object
contributes s(o) of them (Section 7.6.1). Under "reed-solomon", K plus
the instance's total repair count is at most 255 (Section 6.3.4,
rule 12).¶
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. T
MUST be at least 1 under every block profile: a zero-length symbol
carries nothing, and the symbol count of Section 7.6.1 divides by T.
All symbols in a block have the same size; the byte layout of each
source symbol is fixed by the track's blockProfile and is not
otherwise carried in the catalog. Under "iso-ssbg1-v1" it is the
ssbg_mode1 construction of Section 7.3, under which a source packet
of up to T - 2 bytes is protected; under it T MUST be at least 14: a
shorter symbol carries no protected packet of the 12-octet MMTP
packet header ([MOQ-MMT] Section 3.1). Under "moq-object-v1" it is
the construction of Section 7.6.1, under which an object whose
Protected Object Unit is at most K x T bytes long is protected. For
"raptorq", T is a multiple of 8, the fixed Symbol Alignment of the
derived OTI (Section 4.2), so the least T is 8 under "moq-object-v1"
and 16 under "iso-ssbg1-v1". For "reed-solomon", no such alignment
applies (Section 4.5).¶
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 under iso-ssbg1-v1; this catalog
profile carries no packet-count window. Under moq-object-v1, which
has no in-band signaling (Section 5.2), a value of zero is equivalent
to an absent field. 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).¶
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): The Track Name of the layer-0 repair track, which is in the source track's Track Namespace (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.¶
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 that carries an fec object whose
blockProfile admits the track's packaging (Section 5.1).¶
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.repairSymbols is the
authoritative P_0 (Section 6.3.4, rule 11).¶
priority (integer, OPTIONAL): The Publisher Priority ([I-D.ietf-moq-transport] Section 5.1.1) of this track's objects, in the range 192 to 255 (Section 10). A publisher that declares it MUST give every object of the track this Publisher Priority, for example through the track's DEFAULT_PUBLISHER_PRIORITY Track Property ([I-D.ietf-moq-transport] Section 10.4). Subscriber priority is applied before publisher priority ([I-D.ietf-moq-transport] Section 5.1.2), so a subscriber SHOULD NOT subscribe to the track with a SUBSCRIBER_PRIORITY numerically lower than that of its subscription to the source track. It MAY use this value as that SUBSCRIBER_PRIORITY.¶
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. An
overlay is defined only for a source track under iso-ssbg1-v1
(Section 6.3.4, rule 10).¶
sourceSymbols (integer, REQUIRED on an overlay, MUST NOT appear otherwise; MUST be >= 1): 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 whose
blockProfile names a profile it does not implement (Section 5.1).¶
Three repair layers and one keyframe overlay on one mmtp source track:¶
{
"version": "draft-01",
"tracks": [
{
"name": "video",
"packaging": "mmtp",
"isLive": true,
"mmtpMode": "mfu",
"timescale": 90000,
"presentationAnchorTicks": 0,
"groupDurationMs": 1000,
"codec": "avc1.640028",
"width": 1920,
"height": 1080,
"framerate": 30,
"bitrate": 4990000,
"fec": {
"algorithm": "raptorq",
"blockProfile": "iso-ssbg1-v1",
"sourceSymbols": 64,
"repairSymbols": 8,
"symbolSize": 1200,
"interleaveDepthMs": 200,
"repairTrack": "video/repair"
}
},
{
"name": "video/repair",
"packaging": "fec-repair",
"isLive": true,
"depends": ["video"],
"repairLayer": 0,
"repairSymbols": 8,
"priority": 240
},
{
"name": "video/repair/1",
"packaging": "fec-repair",
"isLive": true,
"depends": ["video"],
"repairLayer": 1,
"repairSymbols": 16,
"priority": 244
},
{
"name": "video/repair/2",
"packaging": "fec-repair",
"isLive": true,
"depends": ["video"],
"repairLayer": 2,
"repairSymbols": 32,
"priority": 248
},
{
"name": "video/repair/kf",
"packaging": "fec-repair",
"isLive": true,
"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.¶
This catalog uses raptorq. Under reed-solomon its base instance
would be valid, since 64 + 56 = 120 is at most 255, but its overlay
would not, since 256 + 32 = 288 exceeds 255 (Section 6.4.1).¶
The layer arithmetic is the same under moq-object-v1, which defines
no overlay.¶
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 from the derived parameters (Sections 4.2 and
4.5); 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).
The loc and cmaf packagings define none, so for a track under
moq-object-v1 the catalog is the only FEC signaling.
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.¶
A publisher that carries FEC source symbols as MoQ objects MUST tag
each object that carries one or more source symbols with a FEC Source
Info Object Property, whose type is the odd value 0x11 (Section 15.1).
Under moq-object-v1 that is every source object (Section 7.6.2).¶
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 can take a 2-byte Delta Type ([I-D.ietf-moq-transport] Section 8.3), so adopting it can change the length of an object's Properties 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. A relay that does not implement this document forwards the Property unmodified and caches it with the object, as [I-D.ietf-moq-transport] Section 8.4 requires of any Property that a relay does not support.¶
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 may be desynchronized
from that point on. Depending on the bytes, the parse ends in a
session closure ([I-D.ietf-moq-transport] Section 8.3), in a
malformed track ([I-D.ietf-moq-transport] Sections 10.7 and 12.1),
or in silently wrong Property values. 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. A
receiver cannot reject a 0x10 Property and carry on either, because by
the time it has mis-parsed the value the sequence may already be
desynchronized.¶
The Property value is:¶
FEC Source Info {
SS_ID (32),
}
¶
SS_ID is an unsigned integer in network byte order. Under
iso-ssbg1-v1 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.
Under moq-object-v1 it is the SS_ID of the first of the s(o) source
symbols that the object's Protected Object Unit occupies
(Section 7.6.2), and the Property is the only carrier of that value:
the profile has no trailer.¶
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). Under moq-object-v1 a Property carried inside
Immutable Properties is part of the Protected Object Unit and is
recovered with the object, but a receiver still takes a recovered
object's SS_ID from the block coordinate at which it found the unit,
and checks the Property against it (Section 7.6.4).¶
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.¶
FEC Source Info is single-valued. An object carries at most one FEC Source Info Property, counting its mutable Properties and its Immutable Properties together ([I-D.ietf-moq-transport] Section 10.7). A receiver treats an object that carries more than one as an object that carries none (below).¶
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 does not recover its mutable Properties, and
under iso-ssbg1-v1 it recovers no Properties at all, so a length
carried here could be absent in exactly the case a recovered length is
wanted. The recoverable length is inside the source symbols
themselves, and is recovered with them: the Length field of
Section 7.3, or the Immutable Properties Length and Payload Length of
the Protected Object Unit (Section 7.6.1). Under both source symbol
constructions 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.¶
A repair track MUST be in the Track Namespace of the source track it
repairs. The fec.repairTrack and depends fields carry only a
Track Name ([I-D.ietf-moq-transport] Section 2.4.1), and a receiver
resolves each in that namespace, as [I-D.ietf-moq-msf]
Section 5.2.14 does for depends.¶
By convention, the layer-0 repair track's Track Name is the source track's Track Name followed by the seven bytes "/repair":¶
| Track Namespace | Source Track Name | Repair Track Name |
|---|---|---|
| ("live") | "video" | "video/repair" |
| ("broadcast", "video") | "1080p" | "1080p/repair" |
| ("stream") | "audio/en" | "audio/en/repair" |
The name is a convention and not a resolution mechanism: a
receiver resolves every repair track from fec.repairTrack,
depends, repairLayer and scope (Section 5.1.1), so the name
serves only human readers, in logs and configuration.
Enhancement layers (Section 6.3) and a keyframe overlay (Section 6.4)
have no conventional name. 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.¶
Subscribers SHOULD subscribe to the source track first, then subscribe to the repair track if:¶
fec object naming a
repairTrack, Section 5.1), AND¶
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.¶
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.¶
Under iso-ssbg1-v1, 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. An entity that republishes a
subset of a catalog MUST NOT list a fec-repair track whose source
track it omits (Section 6.3.4, rule 9).¶
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.¶
Under either code of this document, a repair symbol is fixed by its block and its RS_ID alone, whichever layer carries it, and any set of distinct encoding symbols of a block decodes together ([RFC6330]; Section 4.4). Symbols received from any subset of layers, over any mix of paths, therefore 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 decoding overhead of the track's algorithm: 0 under
reed-solomon, which is maximum distance separable (Section 4.4), and
under raptorq a small number of symbols (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.¶
Repair layers and the overlay are defined only for raptorq and
reed-solomon: a publisher MUST NOT signal either under any other
algorithm, and a receiver rejects such a catalog (Section 6.3.4,
rule 7).¶
Layering needs a code whose repair symbols are identified by ESI alone and whose repair symbol for a given ESI does not depend on how many repair symbols the block generates in total. Only then do repair symbols from disjoint ESI ranges on separate tracks remain symbols of one code, and only then can a receiver add a layer without the publisher re-encoding. RaptorQ has this property by construction, through its open Encoding Symbol ID space ([RFC6330]). The property is not particular to fountain codes. A systematic Reed-Solomon code whose generator matrix is Vandermonde-derived ([RFC5510] Section 8.2.1) or Cauchy-derived has it too, provided the field element that defines each repair column is fixed by the symbol's index in the code and never by P. [RFC5510] fixes it as alpha^j for the Encoding Symbol ID j, so a repair column is fixed by SSB_length and RS_ID together, through ESI = SSB_length + RS_ID. The Cauchy construction of Section 4.4 fixes y_j as alpha^j for RS_ID j, so a repair column is fixed by RS_ID alone. Each repair symbol is then one fixed column of that matrix, independent of the code length n = K + totalP, and the field size is the only bound: K + totalP is at most 2^m - 1 over GF(2^m) for the [RFC5510] construction, and at most 2^m for a Cauchy construction in general. The construction of Section 4.4, whose x_i and y_j are nonzero powers of alpha, allows 2^m - 1, that is 255. A Reed-Solomon code in generator-polynomial form lacks the property: its parity is the remainder modulo a polynomial of degree n - K, so its symbols for one P are not valid for another.¶
An algorithm admits repair layers and the overlay only if its specification (a) establishes this property for the construction it specifies, including that each repair column's field element is fixed by the symbol's index in the code alone, (b) states how each layer's RS_ID range maps to that code's symbol index (for [RFC5510], the Encoding Symbol ID, whose Max-Number-of-Encoding-Symbols then covers K + totalP over all layers), (c) bounds K + totalP by that construction's limit, alongside rules 4 and 5 of Section 6.3.4, and (d) updates rule 7 of Section 6.3.4, since a receiver of this document otherwise rejects such a catalog. Rule 6 is particular to RaptorQ.¶
The reed-solomon code of Section 4.4 meets all four conditions:
(a) column j of A depends on RS_ID j alone, through y_j = alpha^j,
and not on P or on SSB_length; (b) layer i carries columns O_i to
O_i + P_i - 1 (Section 4.5); (c) rule 12 of Section 6.3.4 bounds
K + totalP by 255 for each FEC instance; and (d) rule 7 admits it. A
specification of another algorithm can admit repair layers and the
overlay on the same terms.¶
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.¶
depends names exactly one track in the same catalog, which
carries an fec object whose blockProfile admits that track's
packaging (Section 5.1).¶
repairLayer values 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's fec.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,
and the publisher MUST give the layer-0 track's objects Publisher
Priority 240.¶
repairSymbols across all its
layers is at most 2^24 - 1, the range of RSB_length.¶
fec.algorithm is raptorq, K is at most 56403 for each FEC
instance. [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.¶
fec.algorithm is
raptorq or reed-solomon (Section 6.3.3 above).¶
packaging is fec-repair carries no geometry
field, whether as a flat field or inside an fec object of its
own: algorithm, blockProfile, mmtpMode, timescale, any
groupDuration field, symbolSize, interleaveDepthMs,
reorderToleranceMs, and sourceSymbols except on an overlay
(Section 6.4).¶
packaging is
fec-repair is reachable from a source track, either by being
named in that source's fec.repairTrack or by naming that source
in depends. This rule binds once the catalog declares any FEC
source, that is any track whose fec.algorithm is not none; a
catalog that declares no FEC source at all MAY carry an
unreferenced fec-repair track 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.¶
"scope": "keyframe"
(Section 6.4), and none when its fec.blockProfile is
moq-object-v1 (Section 7.6.6). A track with
"scope": "keyframe" carries no repairLayer.¶
repairSymbols, where declared, equals
the source track's fec.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, 5 and 12 have a single well defined totalP to
bound.¶
fec.algorithm is reed-solomon, K + totalP is at most 255
for each FEC instance: for the base instance, fec.sourceSymbols
plus the repairSymbols of all its layers, and for an overlay,
its own sourceSymbols plus its own repairSymbols (Sections 4.5
and 6.4.1). Every entry of A that a block of the instance uses is
then defined (Section 4.4).¶
fec object meets the range rules of Section 5.1:
sourceSymbols is at least 1, repairSymbols is at least 1 when
a repair track is published, symbolSize is at least 1 and,
under iso-ssbg1-v1, at least 14, and symbolSize is a multiple
of 8 when fec.algorithm is raptorq; and each repair track
meets those
of Section 5.1.1: its repairSymbols, where declared, is at
least 1, and an overlay's sourceSymbols is at least 1. A
symbol shorter than 14 octets carries no protected MMTP packet
(Section 7.3), a RaptorQ symbol size off the Symbol Alignment
fits no derived OTI (Section 4.2), and a block of no source or no
repair symbols recovers nothing, in the base instance or in an
overlay (Section 6.4.1), so a receiver that started FEC on such a
catalog would join repair tracks whose symbols recover no packet.¶
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.¶
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).¶
Multicast endpoints carry only mmtp tracks and their repair tracks
([MOQ-MULTICAST] Section 4.1), so this subsection concerns tracks
under iso-ssbg1-v1.¶
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. A layer whose endpoint the receiver has left is carried on no endpoint it holds, reachable over MoQ unicast as above; under the bc-provenance profile of [MOQ-MULTICAST] Section 7.2 a receiver holds an endpoint while joined to its group, reading its manifest track or receiving the broadcast that carries the flow (its Section 7.2.9), and a consumer is protected under that endpoint's flow only while the receiver holds it (step 2 of [MOQ-MULTICAST] Section 7.2.7).¶
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.¶
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).¶
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 a bound:
RS_ID < RSB_length, and under reed-solomon also
SSB_length + RSB_length <= 255 (Section 4.5). 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).¶
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; under reed-solomon the
new total MUST keep the instance within rule 12 of Section 6.3.4. 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 a
bound, RS_ID < RSB_length and under reed-solomon also
SSB_length + RSB_length <= 255, 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 apply the raised total
from a block onward in the serial order of Section 7.5, generating
the repair symbols of that block and of every block after it under
the raised total or one raised later and those of every block
before it under a smaller one, whatever order its encoder generates
the repair symbols of blocks in, so that RSB_length is
non-decreasing in that order. The other order needs care: a block's
RSB_length is the total in force when its repair symbols were
generated (Section 7.1), so the repair packets of a block generated
under the previous total carry that total, which is O_n for the
appended layer n and below O_n + P_n, and a receiver that joins layer
n can take such a packet after the catalog that lists the layer: the
packets of a block are sent over the span of Section 5.1
(interleaveDepthMs), a relay delivers from its cache, and a unicast
repair (Section 11.4) returns the repair objects of an older block.
The check below therefore applies, for a held layer above 0, to a
repair packet of that layer's own track, which carries a symbol
generated under a total at or above its O_i + P_i whatever block it
belongs to, and, for every held layer, to a block at or after, in
the serial order of their SS_Start (Section 7.5), in which the total
never falls (above), one of which the receiver has received a
repair packet carrying at least that layer's O_i + P_i; for a layer
above 0, a block before it whose packets of other layers carry less
was generated before the append, carries no symbol of the layer, and
those packets are the symbols of the layers the receiver holds
below it, under the coordinates of Section 6.3.2 unchanged; for
layer 0, no block carries less than its P_0 where the catalog gives
the flow's own count, and under a block total read from an AL-FEC
message (below) a block before it whose packets carry less was
generated under a previous total, which every packet of it carries,
those of layer 0's own track included. Layer 0 has no clause of
its own track: its O_0 is 0 and its symbols' coordinates depend on
no published count, so a catalog whose layer 0 carries a block
total read from an AL-FEC message rather than the flow's own count
([MOQ-MMT] Section 12.2), or that message held in place of a
catalog (Section 12), under which a packet of that track generated
under a previous total carries less, fails a receiver closed on no
conforming packet.
Within a consumer protected under a flow of the
bc-provenance profile of [MOQ-MULTICAST] Section 7.2, whether or
not that profile governs it for its blocks (Section 7.4), the packet
that anchors the check and the packet it tests are both repair
packets that profile has admitted (step 2 of its Section 7.2.7): a
symbol of an unlisted track reaches the consumer under the
integrity protection of a MoQ unicast path, which vouches for the
relay and not for the publisher, so the total it carries attests to
no coordinate the publisher is using; it anchors nothing, and one
whose RSB_length is below the O_i + P_i of a layer the receiver
holds is discarded, leaving the state of every block unchanged, so
that a relay on that path cannot stop FEC for the source track with
one packet.¶
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. Neither code of this document detects 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 but for the check below, which fails closed those of them that hold a layer below it, on the smaller total the packets of that layer carry, they would learn of the withdrawal only at the next catalog refresh, which this document does not bound, as one holding the withdrawn layer alone, which no packet reaches after the withdrawal, does.¶
Append-only, applied from a block onward, is what makes the check below sound. RSB_length is monotonically non-decreasing over the lifetime of a source encoding in the serial order of Section 7.5, as the append rule above requires, and a symbol of a layer above 0 is generated only under a total at or above that layer's O_i + P_i, so a wire RSB_length below a held layer's O_i + P_i on a packet of that layer's track, the layer being above 0, or on a block at or after one that carried that 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 a repair packet of that layer's track, i being above 0, or on a repair packet of the same FEC instance of a block at or after, in the serial order of Section 7.5, one of which it has received a repair packet carrying at least O_i + P_i, is less than the O_i + P_i derived from its own catalog, or from the AL-FEC message for a receiver that holds layer 0 under that message alone (Section 12): 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 on the first packet of layer 2 it receives after the change, whenever it joined.¶
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. Nor does it catch, for a receiver that joins a
withdrawn highest layer under a catalog that still lists it, the
withdrawal itself unless a block generated while the layer was
published, after its append and before the withdrawal, reaches it:
no packet of that layer is generated after the withdrawal, the
packets of the layers below carry, on every block generated after
it, a total below O_i + P_i, which anchors the check on none of
them, and their coordinates are unchanged by the withdrawal, so a
receiver that takes no such block decodes from the layers below and
learns of the withdrawal only at the next catalog refresh, while
one that takes a packet of such a block, by the routes of the
append paragraph above, whose packets carry that O_i + P_i, has the
check anchored and, where it holds a layer below the withdrawn
one, fails closed on the first block that reaches it carrying the
smaller total at or after, in the serial order of Section 7.5, a
block of which it has received a repair packet carrying that
O_i + P_i, as a receiver that had joined the layer and holds one
below it does, while one holding the withdrawn layer
alone, which no repair packet reaches after the withdrawal, learns
of it at that refresh as well. The first case is silent on the
wire, and the second where no such block arrives or the receiver
holds the withdrawn layer alone, 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.¶
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. The overlay
is defined only for a source track under iso-ssbg1-v1, because its
membership and its overlay SS_ID rely on the MMTP RAP_flag and
header extension (Sections 6.4.2 and 8.5.1).¶
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.¶
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).¶
Under reed-solomon the overlay has its own bound:
K_overlay + P_overlay is at most 255 (Section 6.3.4, rule 12),
whatever the base instance uses, and its rows and columns of A are
numbered within the overlay instance (Section 4.5). The overlay of
the worked catalog of Section 5.1.2, with K_overlay 256 and P_overlay
32, is valid only under raptorq. Under reed-solomon, an overlay
whose track declares sourceSymbols 192 and repairSymbols 32 is
valid, since 192 + 32 = 224.¶
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.¶
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.¶
Under iso-ssbg1-v1, 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. Under moq-object-v1 a repair object
is the Repair FEC Payload ID and the repair symbol alone, with no MMTP
header (Section 7.6.3); every field below except the MMTP Packet
Header applies under both profiles:¶
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 when the block's repair symbols are generated, identical on every repair packet of the block. A layer does not carry its own P_i. The value rises when a layer is appended, from a block onward in the serial order of Section 7.5 (Section 6.3.9).¶
RS_ID (24 bits): The zero-based index of this repair symbol
among the block's P repair symbols. The Encoding Symbol ID is
derived as ESI = SSB_length + RS_ID (Section 7.2): under raptorq it
is the RFC 6330 Encoding Symbol ID, and under reed-solomon the code
takes the symbol's column of A from RS_ID alone (Section 4.5). Layer i
of the base instance carries RS_ID in [O_i, O_i + P_i) (Section 6.3.2).¶
Every repair symbol of a block, on whichever layer it travels, is a symbol of the one code over that block: the symbol at RS_ID r is the repair symbol that the instance's algorithm defines for r (Section 7.2). The encoder generates the instance's total repair count for each source block and assigns the disjoint RS_ID ranges to the layer tracks according to O_i. It MUST NOT encode a layer as if it were the block's only repair, for example by generating the first P_i repair symbols of the block and labeling them from O_i: those are not the block's symbols at the RS_IDs they carry, so a receiver holding more than one layer could not combine them, 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: its repair ESIs
start at SSB_length (Section 7.2). Under raptorq the block is a
RaptorQ source block of SSB_length source symbols, whose decoder is
configured with F = SSB_length x T (Section 4.2), and under
reed-solomon it is the number of rows of A that the block uses
(Section 4.5). 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.¶
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.¶
For Reed-Solomon, repair symbols are generated per Section 4.4. Source and repair symbols carry the same ESIs as under RaptorQ, so ESI = SSB_length + RS_ID still identifies a repair symbol within its block, but the code takes the symbol's column of A from its RS_ID alone (Section 4.5).¶
Repair symbol generation for other registered algorithms (Section 4.3) is not specified by this document.¶
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).
This subsection specifies the source symbols of iso-ssbg1-v1;
Section 7.6 specifies those of moq-object-v1.¶
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 source block is too large to decode in the
decoder's working memory, 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; the AL-FEC message of [ISO.23008-1] carries no OTI,
and the split source blocks of its Clause C.2.2 are the two-stage
coding structure, which this document does not use. A publisher
using MMTP packaging under iso-ssbg1-v1 therefore uses ssbg_mode1
without sub-blocks, and never ssbg_mode2.¶
A publisher MUST close a source block when it has assigned K source
symbols to it. Under moq-object-v1 a block holds whole objects, so
the publisher also closes it before an object that does not fit
(Section 7.6.2). 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 under
iso-ssbg1-v1 -- 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 block of its SSB_length
source symbols, at ESIs 0 to SSB_length - 1 in SS_ID order: under
raptorq a RaptorQ source block with F = SSB_length x T
(Section 4.2), and under reed-solomon the first SSB_length rows
of A (Section 4.4). It 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, which
is zero under reed-solomon.¶
Recovery yields the SSB_length source symbols, SSB_length x T bytes, each consumed per the track's block profile (Sections 7.3 and 7.6.4).¶
Source packets and source objects 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 or objects 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 or objects 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. Under reed-solomon it also discards a repair
packet that fails the checks of Section 4.5.¶
Within a consumer that the bc-provenance profile of [MOQ-MULTICAST] Section 7.2 governs for its blocks, one protected under a flow whose endpoint lists its source track (step 2 of its Section 7.2.7; a consumer protected under no such flow, as one a repair-only endpoint feeds while the receiver takes the source track over MoQ unicast alone, is for this paragraph, Section 9 and Section 11.4 a consumer outside that profile, while the scoping of the check of Section 6.3.9 to admitted packets reaches it where it is protected under any flow of the profile, as it reaches every consumer so protected), a block that only symbols of an unlisted track have delimited (a track that no endpoint of a flow the consumer is protected under lists, as that step defines it: one no multicast endpoint the receiver holds lists, holding being joined to its group, reading its manifest track or receiving the broadcast that carries the flow, or one a held endpoint lists while the consumer is not yet protected under its flow; Section 6.3.6) is provisional: it yields to a repair packet the profile has admitted whose (SS_Start, SSB_length) conflicts with it, as that step specifies, and the rules of the previous paragraph then apply among admitted packets. A provisional block is held for decoding only: it has no ts and no FEC deadline (Section 9), and the SS_IDs in its range that the receiver lacks belong, for Section 11.4, to blocks the receiver holds no repair packet of, as if the block were not delimited; such a symbol reveals no run of lost SS_IDs, which a packet the profile admits above them alone reveals.¶
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.¶
The groups of a track are ordered by Group ID [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 62-bit 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.¶
MoQ Transport Group IDs range up to 2^64 - 1 ([I-D.ietf-moq-transport] Section 8.1). This document deliberately uses only [0, 2^62), the Group ID range of the MoQ Transport versions before draft-17, whose variable-length integers were those of QUIC (Section 5.3), so that a repair Group ID is representable in the Group ID encoding of every MoQ Transport version. The bound is not reached in practice: at one million source symbols per second, an FEC instance takes more than 100,000 years to use 2^62 SS_IDs.¶
Sparse Group IDs depart from the recommendation of [I-D.ietf-moq-msf] Section 6.1 that each subsequent Group ID of a track increase by 1. The departure is deliberate: a Group ID that names its block's first SS_ID is what lets a receiver that has lost source packets request the block's repair by Group (below) before it knows the block partition. Within one source encoding the Group IDs still increase monotonically, as that section requires. A publisher MAY carry the PRIOR_GROUP_ID_GAP Object Property ([I-D.ietf-moq-transport] Section 10.8) on the repair objects of a block, set to the SSB_length of the preceding block of the instance minus 1. Relays and receivers that do not parse repair objects can then tell the Group IDs that will never exist from groups that have not arrived.¶
That section also requires a track's Group IDs to keep increasing
across a publisher restart. A publisher that keeps its FEC state
across a restart, for example after a loss of connectivity, continues
the source encoding, with the SS_ID sequence and wrap_epoch of each
FEC instance, so its repair Group IDs keep increasing. A publisher
that starts a new source encoding of a track, including after a
restart that loses its FEC state, retires the previous encoding and
publishes a separate rendition, as Section 6.3.9 requires for retiring
a layer. It MUST publish the source track and every repair track of
its FEC instances under Full Track Names that it has not used before in
the scope ([I-D.ietf-moq-transport] Section 2.5), and MUST NOT
resume a previously used repair Track Name with wrap_epoch reset to
0. A resumed name would reissue Group IDs below 2^32. Repair objects
of the new encoding could then take the Locations of repair objects
already published, which [I-D.ietf-moq-transport] Section 2.1 does
not allow, and a receiver could feed a cached repair object of the old
encoding to the decoder of a block of the new one.¶
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 Object of way 2: the modulo 2^32 test above screens out an object to discard, and does not verify the epoch.¶
From the Largest Object ([I-D.ietf-moq-transport] Section 3.1.4) 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.17). 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_epoch is 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, 2^62).¶
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 symbol 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:¶
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;¶
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.¶
Each such FETCH carries a LOCATION_FILTER parameter ([I-D.ietf-moq-transport] Section 9.20.9). For the range [lo, hi] above, it has type 0x03 (Absolute Start, Group End), StartGroup lo, StartObject 0 and EndGroupDelta hi - lo. For the one Group ext(SS_Start), it has type 0x03 with StartGroup ext(SS_Start), StartObject 0 and EndGroupDelta 0, or, when it requests only some of the Group's objects (Section 11.4.2), type 0x04 (Absolute Range) with StartGroup ext(SS_Start), StartObject the first and EndObject the last Object ID that it requests (an inclusive range, [I-D.ietf-moq-transport] Section 3.3.1), and EndGroupDelta 0.¶
Either form is answered only by a relay that caches the repair objects it receives, datagram-delivered ones included, and serves them by FETCH. At the time of writing not every relay does: some decline a FETCH of objects delivered as datagrams, and some serve no FETCH at all. A block's repair objects share one Group (above), so a hop that carries no Object IDs for datagram-delivered objects delivers only the first repair object of each Group, one repair symbol per block, however many the publisher sent. A publisher whose receivers sit behind such a hop can send repair objects on streams, which carry every object's Object ID.¶
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].¶
The moq-object-v1 block profile (Section 5.1) protects source tracks
whose packaging is loc [I-D.ietf-moq-loc] or cmaf
[I-D.ietf-moq-cmsf]. Its unit of protection is a whole MoQ object,
not an MMTP packet. Each source object becomes one Protected Object
Unit, which occupies one or more consecutive source symbols. The
construction follows the application data unit framing of
[RFC6681] Section 5, with fields sized for MoQ objects.¶
This section defines what differs from iso-ssbg1-v1: how source
symbols are formed from objects, how SS_IDs are assigned to them, how
blocks are delimited around them, the form of a repair object, and how
a receiver rebuilds objects from recovered symbols. The rest applies
unchanged: the catalog fields (Section 5.1), the FEC Source Info
Property (Section 5.3), repair layers (Section 6.3), the Repair FEC
Payload ID (Section 7.1), repair symbol generation (Section 7.2),
short blocks (Section 7.4), SS_ID wrap, repair Group IDs and repair
FETCH (Section 7.5), and source symbol location and deduplication
(Section 8.3). The profile fixes only the source symbols and their
identifiers, so it does not depend on fec.algorithm: the algorithm
encodes a block of this profile as it encodes any other block of
SSB_length T-byte source symbols.¶
A source object of a track under this profile is an object of the track whose Object Status is Normal ([I-D.ietf-moq-transport] Section 11.1.1). An object of any other status carries no Properties ([I-D.ietf-moq-transport] Section 11.1.2) and no source symbol, and is not counted in K or in any block.¶
The Protected Object Unit of a source object o is:¶
Protected Object Unit {
Group ID (64),
Object ID (64),
Immutable Properties Length (16),
Immutable Properties (..),
Payload Length (32),
Payload (..),
}
¶
All integers are unsigned and in network byte order.¶
The fields are fixed-width for the reason Section 5.3 gives for SS_ID: a variable-length integer has several valid encodings, so using one here would make the unit depend on the encoding that a session chose. The unit is 22 bytes longer than the Immutable Properties value and the payload together.¶
Let len(o) be the length of the unit in bytes and T the track's
symbolSize. The unit occupies¶
s(o) = ceil(len(o) / T)¶
source symbols. They are the unit followed by s(o) x T - len(o) zero octets, cut into s(o) consecutive T-byte symbols, so every source symbol is exactly T bytes, as Sections 4.2 and 4.5 require. Neither the fixed-width fields nor the padding is transmitted: the object travels in its usual MoQ form, and the publisher and each receiver build the unit from the object's fields. The mutable Properties, Subgroup ID, Publisher Priority and Delivery Mode of the object are not in the unit.¶
The publisher assigns SS_IDs to source symbols in the order in which it emits source objects. Let SS_ID(o) be the SS_ID of the first source symbol of o. The unit of o occupies the s(o) SS_IDs from SS_ID(o) on, and the next source object o' that the publisher emits starts where o ends:¶
SS_ID(o') = (SS_ID(o) + s(o)) mod 2^32¶
The publisher MUST carry SS_ID(o) in a FEC Source Info Property (Section 5.3) on every source object o. The Property SHOULD be inside the object's Immutable Properties, where no node may change it ([I-D.ietf-moq-transport] Section 10.7) and where end-to-end authentication can cover it (Section 14.6). There it is also part of the unit, so it is recovered with the object (Section 7.6.4). SS_ID(o) depends only on the objects emitted before o, and the Property's value has a fixed length, so the publisher can place the Property inside the unit that it numbers.¶
A block holds whole units: every SS_ID of a source object lies in the
block that holds its first SS_ID, so SSB_length is the sum of s(o)
over the objects of the block. A publisher MUST NOT publish a source
object whose s(o) exceeds K, the track's sourceSymbols. It chooses
sourceSymbols and symbolSize so that the unit of its largest
object fits in K x T bytes; an algorithm that allows only small blocks,
such as reed-solomon with K + totalP at most 255 (Section 4.5),
therefore limits the largest object a track can protect. When the open
block already holds more than K - s(o) source symbols, the publisher
MUST close it before it assigns SS_IDs to o, and o starts the next
block (Section 7.4). The publisher MAY also close a block at any
object boundary, for example at a Group boundary.¶
Under this profile a repair object is the Repair FEC Payload ID followed by exactly one repair symbol, with no MMTP header:¶
Repair Object {
Repair FEC Payload ID {
SS_Start (32),
RSB_length (24),
RS_ID (24),
SSB_length (24),
},
Repair Symbol Data (..), # exactly one symbol, T bytes
}
¶
The object payload is therefore 13 + T bytes long, and the Repair FEC Payload ID begins at byte offset 0. Its fields have the meanings and validity rules of Section 7.1, and the repair Group ID, Object ID and layer rules of Sections 6.3.2 and 7.5 apply unchanged. A receiver routes a repair object to the decoder of the source track that the catalog relates to the repair track it arrived on (Section 5.1.1). It MUST discard a repair object whose payload is not 13 + T bytes long.¶
A receiver builds the unit of each source object it holds and places the unit's s(o) source symbols at the SS_IDs from SS_ID(o) on (Section 8.3). An object o in a block occupies ESIs ESI(o) to ESI(o) + s(o) - 1, where ESI(o) is the ESI of SS_ID(o). The receiver MUST NOT feed the decoder a source object whose s(o) exceeds K, one whose SS_IDs do not all lie in the block that holds SS_ID(o), or either of two different objects whose SS_ID ranges overlap. Each means that the object or the block signaling is not what the publisher sent. The receiver MAY still deliver such an object as media.¶
Decoding yields the block's source data, SSB_length x T bytes in ESI order. The receiver rebuilds the objects it lacks from each run of ESIs that no object it fed to the decoder covers. It walks each run from its first ESI, one unit at a time:¶
It reads Group ID, Object ID, Immutable Properties Length, Immutable Properties, Payload Length and Payload, in that order. Every byte read MUST lie inside the run.¶
With len the number of bytes read and s = ceil(len / T), every octet from the end of the unit to the end of its s-th symbol MUST be zero.¶
The next unit starts s symbols after the start of this one. The walk MUST end exactly at the end of the run.¶
If any of these checks fails, the receiver MUST NOT deliver any object from the run, because the run is not what the publisher encoded. It also MUST NOT deliver a rebuilt object:¶
A failed check concerns bytes that the receiver computed, not an object that it received. The receiver discards the rebuilt data, and the failure is not a protocol error of the session.¶
A rebuilt object that passes these checks is the object at its Location, with the rebuilt Immutable Properties as its only Properties and the rebuilt payload as its payload. The receiver delivers it to the track's consumer and takes its SS_ID from the block coordinate (Section 5.3). The mutable Properties, Subgroup ID, Publisher Priority and Delivery Mode of the object are not recovered. MoQ Transport sends an object according to those fields ([I-D.ietf-moq-transport] Section 2.1.1), so an entity that rebuilds an object delivers it to its own consumer only, and MUST NOT forward it as an object of the source track.¶
A rebuilt object has no mutable Properties (Section 7.6.4). On a loc track the LOC Public Properties are Object Properties ([I-D.ietf-moq-loc] Section 2.2), so a LOC Property is recovered only if it is inside Immutable Properties. A publisher of a loc track under this profile MUST carry inside Immutable Properties every LOC Public Property that it sets on a source object and that a receiver needs to decode or present the object. These include Timestamp and Timescale ([I-D.ietf-moq-loc] Section 2.3.1) and, where the track uses them, Video Config, Video Frame Marking and Audio Config ([I-D.ietf-moq-loc] Sections 2.3.2 and 2.3.3). [I-D.ietf-moq-loc] Section 3.1.2 already recommends Immutable Properties for such Properties. LOC Private Properties travel in the object payload and are recovered with it.¶
On a cmaf track each object holds one or more successive CMAF chunks ([I-D.ietf-moq-cmsf] Section 3.3), and no chunk or CMAF Fragment spans a Group ([I-D.ietf-moq-cmsf] Section 3.4). The publisher chooses K and T so that K x T covers the largest such object (Section 7.6.2). The sample timing a receiver needs is in each chunk's movie fragment, inside the payload, so a rebuilt cmaf object is complete without Properties. The CMAF header that initializes decoding comes from the catalog ([I-D.ietf-moq-cmsf] Section 3.1), not from the objects.¶
An object-protection scheme can authenticate the Publisher Priority of each object, as MoQ Secure Objects does ([I-D.ietf-moq-secure-objects] Section 3.5), and the unit does not carry it. A publisher that protects a track under this profile with such a scheme SHOULD give every object of the track the track's DEFAULT_PUBLISHER_PRIORITY ([I-D.ietf-moq-transport] Section 10.4), so that a receiver can form the authenticated data of a rebuilt object and verify it.¶
The keyframe overlay (Section 6.4) is not defined for this profile.
Its membership and its overlay SS_ID rely on the MMTP RAP_flag and
header extension (Sections 6.4.2 and 8.5.1), which a loc or cmaf
object does not have. A catalog that declares an overlay for a source
track under this profile violates rule 10 of Section 6.3.4, and a
receiver fails closed on it. Repair layers (Section 6.3) apply.¶
This profile is defined for MoQ paths only. A multicast endpoint
lists only mmtp tracks, and a loc or cmaf track reaches multicast
through an mmtp rendition track, which is a separate FEC instance
under iso-ssbg1-v1 ([MOQ-MULTICAST] Sections 4.1 and 5). Symbols
of the two tracks never combine. The receiver repair policy of
Section 11.4, which serves multicast and AMT legs, does not apply to a
track under this profile.¶
On a MoQ path the erasure unit is a whole object, not a symbol. An object sent as a datagram is dropped whole when it exceeds the maximum datagram size of a session on its path ([I-D.ietf-moq-transport] Section 11.2). A delivery timeout drops a datagram, or resets the subgroup stream that carries an object ([I-D.ietf-moq-transport] Section 5.2). A lost object erases all s(o) of its source symbols, so a block recovers its lost objects only when the repair symbols the receiver holds number at least the source symbols those objects span, plus the decoding overhead (Section 6.3.2). The profile therefore helps most with small objects, such as audio frames sent as datagrams, and with objects that a delivery timeout drops. In-band recovery of a keyframe object needs a total repair count of at least its s(o). Otherwise a receiver recovers it from a further repair layer or by a FETCH of the object, or resumes at the next Group. FEC pays off most on multicast, where one lost packet erases one symbol (Section 11.3); for a loc or cmaf track that leg is the mmtp rendition.¶
All source objects of a track share one SS_ID sequence. Objects that a receiver does not receive by design, such as the subgroups of a temporal layer that a relay drops under congestion, count as erasures and consume repair symbols. A layer that receivers may skip is therefore better published as a separate track with its own FEC instance, as [I-D.ietf-moq-loc] Section 4.4 does for spatial layers.¶
The catalog below declares a LOC video track under this profile. Each one-second Group holds one Group of Pictures (GOP): an Instantaneous Decoder Refresh (IDR) frame as Object 0 and 29 P-frames as Objects 1 to 29 ([I-D.ietf-moq-loc] Section 4.2). The publisher sends the parameter sets in the IDR payload ([I-D.ietf-moq-loc] Section 2.1.1), so the track needs no Video Config.¶
{
"version": "draft-01",
"tracks": [
{
"name": "video",
"packaging": "loc",
"isLive": true,
"role": "video",
"codec": "avc3.640028",
"width": 1920,
"height": 1080,
"framerate": 30,
"bitrate": 2500000,
"fec": {
"algorithm": "raptorq",
"blockProfile": "moq-object-v1",
"sourceSymbols": 256,
"repairSymbols": 32,
"symbolSize": 1200,
"interleaveDepthMs": 1200,
"reorderToleranceMs": 40,
"repairTrack": "video/repair"
}
},
{
"name": "video/repair",
"packaging": "fec-repair",
"isLive": true,
"depends": ["video"],
"repairSymbols": 32,
"priority": 240
}
]
}
¶
Each object carries 15 bytes of Immutable Properties: Timescale in 4 bytes (Delta Type 0x08 and the value 90000 in 3 bytes), Timestamp in 5 bytes (a 4-byte value) and FEC Source Info in 6 bytes. Each unit is therefore 37 bytes longer than its payload. With T = 1200:¶
Suppose the first source object of the FEC instance, {0, 0}, has SS_ID 0, every Group so far has this shape, and the publisher closes a block at each Group boundary. Group g then starts at SS_ID 225 x g, and its block has SS_Start 225 x g and SSB_length 225. For Group 5:¶
| Object | len(o) | s(o) | SS_IDs | ESIs |
|---|---|---|---|---|
| {5, 0} (IDR) | 60,037 | 51 | 1125 to 1175 | 0 to 50 |
| {5, 1} | 7,037 | 6 | 1176 to 1181 | 51 to 56 |
| {5, 2} | 7,037 | 6 | 1182 to 1187 | 57 to 62 |
| {5, 3} | 7,037 | 6 | 1188 to 1193 | 63 to 68 |
| {5, 4} | 7,037 | 6 | 1194 to 1199 | 69 to 74 |
| {5, 5} | 7,037 | 6 | 1200 to 1205 | 75 to 80 |
| {5, 29} | 7,037 | 6 | 1344 to 1349 | 219 to 224 |
Objects {5, 6} to {5, 28}, which the table omits, follow the same pattern.¶
Object {6, 0} starts at SS_ID 1350. The block's repair objects form
Group 1125 of video/repair (Section 7.5): Objects 0 to 31, with
RS_IDs 0 to 31 and ESIs 225 to 256, each 13 + 1200 = 1,213 bytes long.
The block's source objects are sent over 967 ms, and its repair
objects follow the last of them, so the catalog's interleaveDepthMs
of 1200 covers the block's send span (Section 5.1).¶
Suppose a delivery timeout drops {5, 3} and {5, 4}. The receiver holds {5, 2}, which ends at SS_ID 1187, and {5, 5}, which starts at SS_ID 1200, so ESIs 63 to 74 form a run of 12 missing source symbols. With the other 213 source symbols and the 32 repair symbols it holds 245 symbols, 20 more than SSB_length, and decodes. It walks the run from ESI 63. The unit there has Group ID 5, Object ID 3, Immutable Properties Length 15 and Payload Length 7,000, so len = 7,037 and s = 6, and bytes 7,037 to 7,199 from the start of the unit must be zero. The next unit, at ESI 69, is {5, 4} with s = 6, so the walk ends at ESI 75, where {5, 5} starts, as required. The FEC Source Info values in the two units are 1188 and 1194, their first SS_IDs. The receiver delivers both objects with their Timescale, Timestamp and FEC Source Info Properties.¶
This block recovers the loss of up to five P-frame objects, 30 symbols, with 2 symbols of decoding overhead (Section 6.3.2). The IDR object spans 51 symbols, more than the block's 32 repair symbols, so its loss is not recovered in band: the receiver needs a further repair layer or a FETCH of the object, or resumes at the next Group.¶
This example uses raptorq. Its catalog is not valid under
reed-solomon, since 256 + 32 exceeds 255 (Section 6.3.4, rule 12).¶
FEC blocks are partitions of the source symbol sequence, independent
of MoQ Group boundaries. The publisher assigns consecutive SS_ID
values to source symbols 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.¶
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
...
¶
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.¶
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).¶
Under moq-object-v1, a source object carries no Source FEC Payload
ID. On every MoQ path its FEC Source Info Property is the only carrier
of its SS_ID, which is the SS_ID of the first source symbol of its
Protected Object Unit. The SS_ID advances by s(o) per source object,
modulo 2^32, in the order the publisher emits the objects
(Section 7.6.2), and blocks are consecutive as under iso-ssbg1-v1.¶
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¶
Under moq-object-v1, an object o whose first SS_ID has ESI ESI(o)
occupies ESIs ESI(o) to ESI(o) + s(o) - 1 of the same block
(Section 7.6.2).¶
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 SS_IDs are consecutive, a lost source packet or object is visible as missing SS_IDs 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. Under moq-object-v1 the objects that
carry no source symbol are those whose Object Status is not Normal
(Section 7.6.1). This document defines no derivation
of a source symbol's position from MoQ Group or Object IDs, under
either profile: 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).¶
Under iso-ssbg1-v1, 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. Under moq-object-v1, every MoQ path delivers the same
object with the same FEC Source Info Property, so receivers MAY
likewise combine symbols received over any MoQ path, FETCH included.
A loc or cmaf track reaches multicast only through a separate mmtp
rendition track ([MOQ-MULTICAST] Section 4.1), whose symbols belong
to another FEC instance. Within one FEC instance (Section 6.4.1), a receiver
deduplicates source symbols by SS_ID and repair symbols by
(SS_Start, RS_ID).¶
For FEC block alignment and timing to be deterministic, encoders MUST:¶
Assign consecutive SS_ID values in the order the publisher emits
source packets, or under moq-object-v1 source objects
(Section 7.6.2), 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.¶
For mmtp-packaged tracks, signal the catalog-authored group
duration and frame rate in the MoQ catalog: publish a positive
duration as
groupDurationMs when its integer-millisecond form is exact, or as
the exact positive groupDurationTicks; when both are present,
groupDurationTicks wins and groupDurationMs is informational.
Signal the keyframe cadence in keyframeIntervalMs (or
keyframeIntervalTicks), and the frame rate in the framerate field
([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 interleaveDepthMs is 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. Under
iso-ssbg1-v1, a zero value
is usable only with the ISO protection_window_size alternative
described in Section 5.1; under moq-object-v1 it is equivalent to
an absent field. The value is not derived from a group
count, frame count, or per-symbol interval.¶
This subsection and Section 8.5.1 apply under iso-ssbg1-v1. A
source object under moq-object-v1 carries no trailer, and its FEC
Source Info Property is the only carrier of its SS_ID (Section 7.6.2);
Section 14.6 covers how that Property can be authenticated.¶
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-A360] Section 5.2.2.5, the ATSC 3.0 signing mechanism, whose certificates the ATSC 3.0 Security Authority (A3SA) administers, 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. Version 2 of the
bc-provenance profile ([MOQ-MULTICAST] Section 7.2) is such a
mechanism: its digest covers the whole UDP payload as transmitted,
the Source FEC Payload ID included.¶
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.¶
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.¶
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
recovery condition of the track's algorithm (Section 6.3.2) 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. Within a consumer that the
bc-provenance profile of [MOQ-MULTICAST] Section 7.2 governs for
its blocks (Section 7.4), the packet whose receipt anchors ts is
the first packet of the block, in the order received, that the
profile admits, whenever it admits it (a datagram held on a miss
and admitted later keeps its receipt time), and a symbol of an
unlisted track (Section 7.4) is neither that packet nor such a
signal, whether or not a repair packet the profile admits later
delimits the same block; a block that only such symbols have
delimited is held for decoding only: it has no ts and no FEC
deadline,
whatever packets the profile admits into or above its range, and the
SS_IDs in its range that the receiver lacks are runs of Section
11.4, each with the ts the packet admitted above it gives, as step
2 of [MOQ-MULTICAST] Section 7.2.7 specifies.
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. Under iso-ssbg1-v1, 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. Under moq-object-v1 a zero value is equivalent to an absent
one.¶
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. Within a consumer that the
bc-provenance profile governs for its blocks (Section 7.4), the
policy discards a block that has no ts, one that only symbols of
an unlisted track have delimited, before any block that has a ts,
on a track that derives no FEC deadline as on one that does, and
such a discard is neither a reached deadline nor a
signal: it gives the block no deadline and no class, drops its repair
symbols and returns its source symbols to the undelimited state of
Section 7.4 (step 2 of [MOQ-MULTICAST] Section 7.2.7). 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. They use iso-ssbg1-v1, under which one source packet is
one source symbol; Section 7.6.7 works an example under
moq-object-v1.¶
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
}
¶
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 have SSB_length = 10
<= K = 16 as 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]]
}
¶
SSB_length = 2, F = 2 x T,
and no padding or skipped SS_ID. There is no following block.¶
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. A repair track's catalog
priority is the Publisher Priority of its objects, and Section 5.1.1
states how a subscriber chooses its subscriber priority for the
track.¶
Not every MoQ Transport implementation applies these priorities to objects delivered as datagrams. At the time of writing, some stacks send every datagram ahead of all stream data whatever its Publisher Priority, and others give the datagrams of a connection one priority, so on such a hop a repair track delivered as datagrams can precede the source track it protects, whatever priorities the two carry. A publisher keeps repair from delaying its source on such a hop by sending a block's repair objects only after it has sent the block's source objects.¶
Under congestion, this priority separation ensures:¶
On a multicast or AMT leg, the priorities of on-demand unicast repair requests are set by Section 11.4.5.¶
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 (Sections 1 and 3) are defined in [MOQ-MULTICAST]; this section covers FEC-specific considerations for hybrid 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:¶
For an mmtp track, 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. A multicast endpoint carries only mmtp tracks, so a loc or
cmaf track under moq-object-v1 reaches multicast through an mmtp
rendition track, which is a separate FEC instance ([MOQ-MULTICAST]
Section 4.1).¶
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
¶
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.¶
A track under moq-object-v1 travels on MoQ paths only, where the
erasure unit is a whole object; Section 7.6.6 states where that
profile helps.¶
This subsection is informative.¶
[QUIC-MULTICAST] lets a server send QUIC packets on one-way multicast channels. A channel is an alternate path of the unicast QUIC connections whose clients have joined it, and its packets can carry STREAM and DATAGRAM frames. Clients acknowledge channel packets with MC_ACK frames on their unicast connections ([QUIC-MULTICAST] Section 4.4). The server of each connection remains responsible for any necessary frame data that a channel loses, and Section 8 of [QUIC-MULTICAST] recommends that it send FEC repair packets on the channel instead of retransmitting the lost frames. That repair is a transport mechanism below this scheme, and this document does not depend on it. This scheme can serve as the application-layer FEC on such a channel, and suits broadcast-scale audiences better than unicast repair, because 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]) is best 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 defeats symbol-aligned recovery of FEC-protected media on a multicast channel: a lost packet then spans a byte range crossing symbol boundaries.¶
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 MC_INTEGRITY frames of [QUIC-MULTICAST] carry hashes of channel packets, and a client decodes a channel packet only after a matching hash has arrived over another integrity-protected path ([QUIC-MULTICAST] Section 4.5). 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 can additionally apply a scheme that authenticates every multicast symbol before it enters the decoder, repair symbols included, and, whenever a symbol of its decode was not so authenticated, checks a recovered packet against its own digest or, where it can derive no coordinate to hash with, withholds it (for example version 2 of the manifest-based bc-provenance profile of [MOQ-MULTICAST] Section 7.2, whose receiver procedure is its Section 7.2.7).¶
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 have no need to drive unicast repair for losses the FEC recovers, which preserves the O(1) sender cost that motivates broadcast FEC. Unicast repair remains a last resort for losses exceeding the repair budget, and Section 11.4 specifies it.¶
Item 1 assumes iso-ssbg1-v1, under which one MMTP packet is one
source symbol. This document defines no multicast carriage for
moq-object-v1 (Section 7.6.6).¶
A receiver deduplicates the symbols it receives on a multicast QUIC channel as on any other path, within one FEC instance: source symbols by SS_ID and repair symbols by (SS_Start, RS_ID). Section 8.3 states that requirement; [QUIC-MULTICAST] states none for application symbols. Section 8.3 also permits combining them with symbols received from other paths.¶
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. Multicast and AMT legs carry only mmtp tracks
([MOQ-MULTICAST] Section 5), so this section, which classifies
blocks from MMTP fields, concerns tracks under iso-ssbg1-v1.¶
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. Within a consumer that the bc-provenance profile of [MOQ-MULTICAST] Section 7.2 governs for its blocks (Section 7.4), a symbol of an unlisted track (Section 7.4) enters a decode only as step 2 of [MOQ-MULTICAST] Section 7.2.7 allows, which takes none into a decode of a block that two decodes with such symbols' help have left unrecovered; the attempt continues from the symbols the profile admits. 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. Within such a consumer, a source symbol the profile has not admitted, received or recovered, is not held for this purpose (step 2 of [MOQ-MULTICAST] Section 7.2.7).¶
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 (within a consumer that the bc-provenance profile of [MOQ-MULTICAST] Section 7.2 governs for its blocks, Section 7.4, a block only symbols of an unlisted track have delimited being no block the receiver has delimited, and the run one only once a packet the profile has admitted lies above it, step 2 of [MOQ-MULTICAST] Section 7.2.7): 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).¶
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, or
keyframeIntervalMs converted to the track timescale where that
conversion is exact; an inexact keyframeIntervalMs gives 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
interleaveDepthMs or 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.¶
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, unless the block lies below a RAP the receiver has already admitted complete (the repair would be moot on completion, below); within a consumer that the bc-provenance profile of [MOQ-MULTICAST] Section 7.2 governs for its blocks (Section 7.4), a block only symbols of an unlisted track (Section 7.4) have delimited reaches no deadline and is never requested, the SS_IDs it covers that the receiver lacks being runs of this section (step 2 of [MOQ-MULTICAST] Section 7.2.7). The request is a 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. The receiver sends it on layer 0, and on further layers in layer order where it needs more symbols than layer 0 carries (Sections 6.3.2 and 6.3.5). Section 7.5 gives the LOCATION_FILTER of either form, and the receiver establishes the wrap epoch as Section 7.5 specifies, for instance by a TRACK_STATUS request when it has received no repair-track Group ID over MoQ. 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. A relay answers it only where it caches the repair track's objects, datagram-delivered ones included (Section 7.5); where it does not, the FETCH fails by those events.¶
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; a block that reaches its deadline already below such a RAP is not requested at all.¶
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.¶
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.¶
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 it requests the repair of a keyframe-bearing block that reaches its FEC deadline unrecovered; a block whose repair Section 11.4.2 does not request cancels nothing.¶
Priorities follow the ranges of Section 10. A keyframe repair FETCH MUST carry a SUBSCRIBER_PRIORITY ([I-D.ietf-moq-transport] Section 9.20.7) in the Source Media range, numerically at most 191. It MUST also be numerically no greater than the SUBSCRIBER_PRIORITY of the receiver's subscription to the source track, where the receiver holds one on the session, and numerically lower than the SUBSCRIBER_PRIORITY of every repair-track subscription that the receiver holds on the session. Subscriber priority is compared first ([I-D.ietf-moq-transport] Section 5.1.2), so the FETCH is then delivered ahead of the receiver's repair tracks 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.¶
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.¶
This specification is designed for interoperability with the Application-Layer FEC of ATSC A/331 [ATSC-A331] MMTP sessions. [ATSC-A331] applies AL-FEC to an MMTP session, when it applies it at all, through the AL-FEC framework of [ISO.23008-1] Annex C and requires no FEC code of its own (its Section 8.1.2.5): the framework carries whichever code the AL-FEC message names by its [ISO.23008-10] code point. The codes are this document's to specify, and it specifies two, "reed-solomon" (code point 1, mandatory to implement) and "raptorq" (code point 3, OPTIONAL) (Sections 4.1 and 4.3); [MOQ-MMT] Section 8.3 gives the AL-FEC message a publisher sends for a track of either, and an MMTP session whose AL-FEC message names any other code is outside this document until the registry of Section 15.2 lists that code. A publisher that ingests an A/331 MMTP session takes the FEC parameters of its tracks from that message and the asset locations of the MP table ([MOQ-MMT] Section 12.2), and a receiver that consumes the session without the catalog takes them from the message alone, holding the one repair flow as layer 0 under the block total the message bounds, which stands for its O_0 + P_0 in the check of Section 6.3.9, applied to layer 0 by its anchored clause alone, so that a packet of the flow generated under the previous total, which the message can precede ([MOQ-MMT] Section 8.3), fails it closed on nothing. An MMTP session carries no [RFC6330] OTI: the derived OTI of Section 4.2 fixes N = 1, and sub-blocks are never used (Section 7.3). ROUTE delivery, whose repair protocol (Annex A.4 of [ATSC-A331]) is RaptorQ-based, is outside the scope of this document.¶
This section is informative.¶
A track carrying CMAF content can be protected in two ways.¶
Under moq-object-v1 (Section 7.6), a repair track protects a cmaf
track [I-D.ietf-moq-cmsf] directly. Each object of the cmaf track
holds one or more CMAF chunks ([I-D.ietf-moq-cmsf] Section 3.3) and
forms one Protected Object Unit, and each Group begins with an object
that contains a Stream Access Point (SAP) ([I-D.ietf-moq-cmsf]
Section 3.4):¶
+-------------------------------------------------+
| MoQ Track Namespace |
+-------------------------------------------------+
| |
| Source Track (packaging "cmaf") |
| +-----------------------------------------+ |
| | Object {G, 0}: CMAF chunk with a SAP | |
| | Object {G, 1}: CMAF chunk | |
| | ... | |
| +-----------------------------------------+ |
| |
| Repair Track (packaging "fec-repair") |
| +-----------------------------------------+ |
| | Group ext(S0): repair for block at S0 | |
| | Group ext(S1): repair for block at S1 | |
| | ... | |
| +-----------------------------------------+ |
| |
+-------------------------------------------------+
¶
Alternatively, the publisher carries the media as an mmtp track under
iso-ssbg1-v1, where an MPU corresponds to a CMAF Fragment (see
[MOQ-MMT]). Such a track is also how CMAF content reaches
multicast, because a multicast endpoint carries only mmtp tracks
([MOQ-MULTICAST] Section 4.1). The cmaf track and its mmtp
rendition are separate FEC instances, and symbols of one never repair
the other.¶
A publisher can 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.¶
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.¶
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).¶
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), and for the base instance to P_0/K, the repair that a receiver gets by default: further repair layers are added on demand (Sections 6.3.5 and 6.3.6), and the next paragraph covers them.¶
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.¶
When FEC is used over multicast (SSM/AMT), which carries only mmtp
tracks under iso-ssbg1-v1 ([MOQ-MULTICAST] Section 4.1),
additional considerations
apply:¶
No QUIC Protection: Multicast UDP has neither the confidentiality nor the integrity of QUIC. A publisher that needs confidentiality SHOULD encrypt the media samples, for example with Common Encryption [ISO.23001-7] and its 'cbcs' scheme, as [MOQ-MMT] Section 13 describes for mmtp tracks. All receivers of the flow share the content keys, which reach each receiver over its unicast MoQ session or from a Digital Rights Management (DRM) system. Sample encryption leaves the MMTP headers and the Source FEC Payload ID in the clear and leaves every packet identical across paths, so FEC encodes the ciphertext (Section 14.1) and symbols still combine across paths (Section 8.3). Encrypting each MoQ object payload instead, as MoQ Secure Objects [I-D.ietf-moq-secure-objects] does, would make the MoQ copy of a packet differ from its multicast copy. A keying handshake per receiver, such as DTLS-SRTP, needs a return path and cannot key a one-to-many flow. A key that every receiver holds does not authenticate the publisher; item 3 covers authentication.¶
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: SSM limits which sources reach a receiver ([MOQ-MULTICAST] Section 7.1), and version 2 of the bc-provenance profile ([MOQ-MULTICAST] Section 7.2) authenticates the datagrams themselves, repair symbols included, with a digest that covers the whole UDP payload, the Source FEC Payload ID included (Section 8.5).¶
Block Integrity: Receivers MAY implement block-level checksums to detect corrupted recovery. A block whose decoded source data fails such a check, or, within a consumer that the bc-provenance profile of [MOQ-MULTICAST] Section 7.2 governs for its blocks (Section 7.4), whose recovered packets step 2 of its Section 7.2.7 does not admit, is unrecovered: Section 11.4 governs it from its FEC deadline, and the receiver requests unicast repair for it only as that section directs, never by the multicast-to-unicast failover of [MOQ-MULTICAST], which replaces the multicast path.¶
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 with an integrity mechanism whose coverage includes the complete packet, the Source FEC Payload ID and the Repair FEC Payload ID included (Section 8.5). Version 2 of the bc-provenance profile ([MOQ-MULTICAST] Section 7.2) is such a mechanism: its digest covers the whole UDP payload of source and repair packets, both Payload IDs included.¶
Under iso-ssbg1-v1, 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).¶
Under moq-object-v1 a receiver takes the lengths of a rebuilt object
from decoded bytes (Section 7.6.4). A corrupt decode, from damaged or
injected repair symbols, can put any value there. A receiver MUST NOT
read, copy or allocate beyond the end of the run it walks on the
strength of the Immutable Properties Length or the Payload Length.
The checks of Section 7.6.4 discard a run whose units do not tile it
exactly or whose padding is not zero. They detect many corrupt
decodes, but not all.¶
A block of this profile holds K x T bytes of source data at most, and
no unit is longer (Section 7.6.2), so sourceSymbols and symbolSize
bound the memory one open block needs. A receiver MAY decline FEC for
a track whose K x T exceeds its local limits, and it bounds the number
of open blocks by the policy of Section 9.¶
A unit includes the object's Immutable Properties exactly as serialized. A relay that alters them, which [I-D.ietf-moq-transport] Section 10.7 forbids, changes the unit a receiver builds from the object, and silently corrupts the recovery of the other objects of its block. A relay that adds, changes or removes mutable Properties does not affect FEC, because they are not in the unit.¶
MoQ Secure Objects authenticates the Group ID, Object ID, Publisher Priority and serialized Immutable Properties of an object, along with its payload ([I-D.ietf-moq-secure-objects] Section 3.5). The unit carries all of these except the Publisher Priority, which Section 7.6.5 asks publishers to make known. A receiver can then verify a rebuilt object as it verifies a received one, and discards one that fails. With the FEC Source Info Property inside Immutable Properties, the same verification authenticates the SS_ID of each object it accepts.¶
The catalog bounds the cost of reed-solomon decoding. A block has
at most 255 source and repair symbols (Section 4.5), so the number of
source symbols a receiver recovers in it, E, is at most
min(SSB_length, RSB_length), which is at most 127. The receiver
inverts one E x E matrix per block and performs about
E x SSB_length x T multiplications in GF(2^8) to form and apply the
result (Section 4.4). One open block holds at most 255 x T bytes of
symbols.¶
The code provides no integrity protection, as RaptorQ provides none (Section 14.2). A decoder that is given a corrupted or injected symbol yields wrong source symbols and reports no error, and when it decodes from exactly SSB_length symbols the code itself cannot reveal the error. The checks of Sections 7.3 and 7.6.4 reject some wrong results. A receiver that holds more than SSB_length symbols of a block can also re-encode the recovered block and compare the result with the symbols it did not use: a mismatch shows that some symbol it holds is not what the publisher encoded.¶
This document requests one registration in the "MOQ Properties" registry of [I-D.ietf-moq-transport] (Section 8.4 of that document):¶
| 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 at most one additional byte per tagged object, because Property types are delta-coded ([I-D.ietf-moq-transport] Section 8.3) and the extra byte appears only when the encoded Delta Type exceeds 127. It 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.¶
This document requests creation of a "MoQ FEC Algorithms" registry, in a new "Media over QUIC (MoQ) Forward Error Correction" registry group, with the following initial values:¶
| Value | Identifier | Algorithm | Reference |
|---|---|---|---|
| 0x00 | "none" | None | This document |
| 0x01 | "raptorq" | RaptorQ | [RFC6330]; this document, Section 4.2 |
| 0x02 | "reed-solomon" | Reed-Solomon | [ISO.23008-10] Clause 6; this document, Sections 4.4 and 4.5 |
| 0x03-0xFF | Unassigned |
The Identifier is the string that the catalog fec.algorithm field
carries (Section 5.1). The Value is a one-byte code for the same
algorithm; no message or field that this document defines carries it.
New registrations require Specification Required policy
([RFC8126] Section 4.6). A registration supplies an unassigned
Value, an Identifier that no other entry uses, the algorithm's name,
and a reference to its specification. The designated expert checks
that the specification gives the algorithm's symbol construction, the
derivation of its decoder parameters from the catalog and the Repair
FEC Payload ID, and the semantics of its repair objects (Section 4.3),
and that it states whether the algorithm admits repair layers and the
keyframe overlay (Section 6.3.3).¶
This document specifies "None" (0x00), RaptorQ (0x01) and Reed-Solomon (0x02) for interoperation. Other registered values are extension points whose interoperable use requires their own specifications (Section 4.3).¶
This document defines the catalog packaging value "fec-repair"
(Section 5.1) for repair tracks, extending the allowed packaging
values of the MOQT 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 |
This document requests creation of a "MoQ FEC Block Profiles" registry, in the registry group of Section 15.2, with the following initial values:¶
| Block Profile | Admitted Packaging | Reference |
|---|---|---|
| "iso-ssbg1-v1" | mmtp | This document, Sections 5.1 and 7.3 |
| "moq-object-v1" | loc, cmaf | This document, Sections 5.1 and 7.6 |
The Block Profile is the string that the catalog fec.blockProfile
field carries (Section 5.1). New registrations require Specification
Required policy ([RFC8126] Section 4.6). A registration supplies a
Block Profile string that no other entry uses, the source track
packaging values that it admits, and a reference to its
specification. The designated expert checks that the specification
fixes what Section 5.1 requires of a block profile: how source symbols
are formed from a source packet or a source object, how many source
symbols a block holds, how a block and the source symbols in it are
identified, and how those identifiers wrap.¶
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 by SUBSCRIBE with |
| request_id=0; fec field read) |
| |
| SUBSCRIBE(request_id=2, track=video, |
| LOCATION_FILTER=0x05 (Next Object), |
| FILL_PARAMETERS(LOCATION_FILTER= |
| 0x01, StartGroup=1)) |
|<-----------------------------------------|
| |
| SUBSCRIBE_OK(LARGEST_OBJECT={G, n}) |
|----------------------------------------->|
| |
| SUBSCRIBE(request_id=4, |
| track=video/repair, |
| LOCATION_FILTER=0x05 (Next Object)) |
|<-----------------------------------------|
| |
| SUBSCRIBE_OK |
|----------------------------------------->|
| |
| [Fill fetch stream: source objects |
| {G, 0} to {G, n}] |
|----------------------------------------->|
| |
| [Source objects from {G, n+1} on] |
|----------------------------------------->|
| |
| [Repair objects, group=ext(SS_Start), |
| obj=0..7] |
|----------------------------------------->|
| |
¶
Each SUBSCRIBE carries a Request ID ([I-D.ietf-moq-transport] Section 6.4.2.1). A client uses even Request IDs, starting at 0 and rising by 2 per request, so the catalog SUBSCRIBE ([I-D.ietf-moq-msf] Section 5) takes 0 and the source and repair SUBSCRIBEs take 2 and 4. Each response travels on the bidirectional stream of its request, so SUBSCRIBE_OK carries no Request ID. The source subscription joins at the start of the current Group G ([I-D.ietf-moq-transport] Section 3.5; [MOQ-MMT] Section 6.1). Its Next Object filter starts subscription delivery at {G, n+1}, where {G, n} is the Largest Object that SUBSCRIBE_OK reports, and its fill range, from {G, 0} to that Largest Object, arrives on a fill fetch stream. The repair subscription starts at the Next Object; repair objects published before it can be requested by FETCH (Section 7.5).¶
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).¶
A loc or cmaf track under moq-object-v1 follows the same flow. Its
source objects carry the FEC Source Info Property as Section 7.6.2
specifies, and its repair objects are those of Section 7.6.3.¶
Complete catalog with FEC and multicast configuration:¶
{
"version": "draft-01",
"tracks": [
{
"name": "video",
"packaging": "mmtp",
"isLive": true,
"mmtpMode": "mfu",
"timescale": 90000,
"presentationAnchorTicks": 0,
"groupDurationMs": 1000,
"codec": "avc1.640028",
"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",
"isLive": true,
"depends": ["video"],
"repairSymbols": 125,
"priority": 240
},
{
"name": "audio",
"packaging": "mmtp",
"isLive": true,
"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",
"isLive": true,
"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:¶
K x (T - 22) = 625 x 978 = 611,250 bytes is
an upper bound on the media capacity of one full block. The media
therefore needs at least
ceil(623,750 / 978) = 638 source packets and at least two K=625
blocks; MMTP metadata, fragmentation, and authored packet boundaries
can require more. Repair overhead is P / K = 125 / 625 = 20%.¶
K x (T - 22) = 32 x 490 = 15,680 bytes. The media therefore
needs at least ceil(16,000 / 490) = 33 source packets and at least
two K=32 blocks; packetization and metadata can require more. Repair
overhead is P / 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] Sections 4.1 and 5, a multicast endpoint lists only
mmtp tracks and their repair tracks, and a loc or cmaf track reaches
multicast through an mmtp rendition track. Each track listed on the
endpoint carries a packetId that routes its MMTP packets on the
multicast UDP path. Section 7.6.7 gives a loc track under
moq-object-v1, whose capacity is counted in Protected Object Units
rather than MMTP packets.¶
This appendix is informative. It gives values of the reed-solomon
code of Section 4.4, so that an implementation can check its field
arithmetic, its matrix A and the order of its symbols. Bytes are in
hexadecimal, and a symbol is written as its T bytes in order. Two
separate implementations of Section 4.4 computed these values. They
have not been checked against an implementation of [ISO.23008-10].¶
The field. The powers of alpha fix the polynomial (alpha^8 = 1d) and the representation of elements as bytes (alpha^7 = 80):¶
{
"vector": "field",
"polynomial": "11d",
"alphaPowers": {"0": "01", "1": "02", "7": "80", "8": "1d",
"9": "3a", "254": "8e", "255": "01"},
"inverses": {"02": "8e", "03": "f4", "1d": "83"}
}
¶
Entries of A, with the x_i and y_j that define them. A_{253,0} and A_{0,253} lie at the edge of the bound: a block that uses either has SSB_length + RSB_length = 255.¶
{
"vector": "matrix",
"entries": [
{"i": 0, "j": 0, "x": "8e", "y": "01", "A": "f5"},
{"i": 0, "j": 1, "x": "8e", "y": "02", "A": "53"},
{"i": 1, "j": 0, "x": "47", "y": "01", "A": "a6"},
{"i": 1, "j": 1, "x": "47", "y": "02", "A": "4e"},
{"i": 3, "j": 2, "x": "d8", "y": "04", "A": "99"},
{"i": 31, "j": 7, "x": "09", "y": "80", "A": "31"},
{"i": 253, "j": 0, "x": "02", "y": "01", "A": "f4"},
{"i": 0, "j": 253, "x": "8e", "y": "47", "A": "f7"}
]
}
¶
A block of four one-byte source symbols, and its repair symbols at RS_IDs 0 to 2:¶
{
"vector": "encode",
"T": 1,
"SSB_length": 4,
"source": ["01", "02", "03", "04"],
"RS_ID": [0, 1, 2],
"repair": ["cc", "ce", "83"]
}
¶
A short block. K is 8, and the block holds three two-byte source symbols. Its repair symbols are also those of a full block of eight source symbols whose last five are zero. A receiver that holds the source symbol at ESI 0 and both repair symbols recovers the source symbols at ESIs 1 and 2:¶
{
"vector": "short-block",
"T": 2,
"K": 8,
"SSB_length": 3,
"source": ["0102", "0304", "0506"],
"RS_ID": [0, 1],
"repair": ["d43a", "d016"],
"received": {"ESI": [ 0 ], "RS_ID": [0, 1]},
"recovered": ["0304", "0506"]
}
¶
Two repair layers over the block of the third vector, with K = 4. Layer 0 carries RS_IDs 0 and 1 (P_0 = 2, O_0 = 0), and layer 1 carries RS_IDs 2 and 3 (P_1 = 2, O_1 = 2), so RSB_length is 4. The symbols at RS_IDs 0 to 2 equal those of the third vector, whose block has a total repair count of 3: a column does not depend on P. A receiver that holds layer 1 alone, with the source symbols at ESIs 0 and 3, recovers the source symbols at ESIs 1 and 2:¶
{
"vector": "layers",
"T": 1,
"K": 4,
"SSB_length": 4,
"RSB_length": 4,
"source": ["01", "02", "03", "04"],
"layers": [
{"repairLayer": 0, "RS_ID": [0, 1], "repair": ["cc", "ce"]},
{"repairLayer": 1, "RS_ID": [2, 3], "repair": ["83", "20"]}
],
"received": {"ESI": [0, 3], "RS_ID": [2, 3]},
"recovered": ["02", "03"]
}
¶
This appendix is informative and is to be removed before publication as an RFC.¶
iso-ssbg1-v1 profile.¶
repairTrack is a Track Name in the source track's
Track Namespace.¶
priority is the Publisher Priority of the repair
track's objects, and a subscriber should not subscribe to a repair
track with a numerically lower subscriber priority than its source
subscription. Section 10 refers to this.¶
moq-object-v1 protects tracks
packaged as loc or cmaf. A source object's Protected Object Unit
(Group ID, Object ID, Immutable Properties and payload, with
fixed-width lengths) spans s(o) zero-padded source symbols, and its
FEC Source Info Property carries the SS_ID of the first one. Blocks
hold whole units, and repair objects carry no MMTP header. The
section specifies the receiver's recovery walk and checks, requires
loc publishers to carry presentation Properties inside Immutable
Properties, asks publishers that use Secure Objects to give every
object the track's default Publisher Priority, states the profile's
applicability, and works an example.¶
blockProfile defines moq-object-v1 next to
iso-ssbg1-v1, and each value names the packaging values it
admits. A receiver does not apply FEC under a profile that does not
admit the track's packaging. sourceSymbols counts symbols,
symbolSize states the object profile's capacity, and a zero
interleaveDepthMs under moq-object-v1 equals an absent field.¶
depends names a track
whose blockProfile admits its packaging, instead of requiring
mmtp.¶
iso-ssbg1-v1, and a catalog that declares one
for a track under moq-object-v1 fails closed. Section 6.4 states
why.¶
sourceSymbols MUST be >= 1, a floor
that -00 did not state. Section 6.3.4, rule 13 makes it a catalog
rule a receiver fails closed on.¶
moq-object-v1, where it is the
only SS_ID carrier, and the recoverable length rule covers both
profiles.¶
iso-ssbg1-v1.¶
iso-ssbg1-v1, and the Repair FEC Payload ID fields apply under
both profiles.¶
interleaveDepthMs
and the conformance cases are stated per profile.¶
moq-object-v1, or carried as an mmtp track, which is also its route
to multicast.¶
moq-object-v1:
length validation, padding checks, memory bounds, relay tampering
and Secure Objects.¶
symbolSize
need not be a multiple of 8 under Reed-Solomon, is at least 1 under
every profile and at least 14 under iso-ssbg1-v1, and Section 4.5
gives a catalog example.¶
reed-solomon, new rule 12 bounds
K + totalP by 255 for each Reed-Solomon FEC instance, and new rule
13 makes the range rules of Sections 5.1 and 5.1.1 (sourceSymbols
at least 1, repairSymbols at least 1 when a repair track is
published and on each repair track where declared, an overlay's
sourceSymbols at least 1, now stated in Section 5.1.1,
symbolSize at least 1 and, under iso-ssbg1-v1, at least 14,
and a multiple of 8 under raptorq) catalog rules a receiver
fails closed on.¶
fecOTI, RepairFlow and
overhead rules) and the sub-block guidance are removed, and the
section states that [ATSC-A331] requires no particular code for
an MMTP session and that the codes are this document's to specify.¶
priority binds the publisher
to Publisher Priority 240 (rule 3), and the 56403 bound applies
under raptorq only (rule 6).¶
blockProfile values.¶
version, isLive
and bitrate. In Section 7.6.7 interleaveDepthMs is 1200, which
covers the block's send span.¶
Marc E. Fiuczynski reviewed this revision and reported how relays and MoQ Transport stacks of the time handle datagram-delivered repair objects (Sections 7.5, 10 and 11.4.2).¶