Internet-Draft MoQ FEC October 2026
Ramadan Expires 29 April 2027 [Page]
Workgroup:
moq
Internet-Draft:
draft-ramadan-moq-fec-01
Published:
Intended Status:
Standards Track
Expires:
Author:
O. Ramadan
Blockcast

Forward Error Correction for Media over QUIC

Abstract

This document specifies a mechanism for transmitting Forward Error Correction (FEC) repair data alongside source media in Media over QUIC (MoQ) sessions. It defines catalog-based signaling of FEC configuration, including a derived RaptorQ Object Transmission Information that 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.

Status of This Memo

This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.

Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is at https://datatracker.ietf.org/drafts/current/.

Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."

This Internet-Draft will expire on 29 April 2027.

▲

Table of Contents

1. Introduction

Media over QUIC (MoQ) [I-D.ietf-moq-transport] provides a publish/subscribe transport for real-time media. While QUIC provides reliable delivery through retransmission, the latency incurred by retransmission can be unacceptable for ultra-low-latency (ULL) applications such as live sports, gaming, and interactive broadcasts.

Forward Error Correction (FEC) enables receivers to recover lost packets using redundant repair data, without waiting for retransmissions. This is particularly valuable in wireless environments where burst packet loss is common.

This document defines:

  1. A catalog extension carrying the complete FEC configuration, which is authoritative for MoQ receivers
  2. A normative derivation of the parameters of the Reed-Solomon code, and of the RaptorQ Object Transmission Information (OTI), from the catalog fields and the Repair FEC Payload ID of each block, so that catalog-only receivers (including multicast and sessionless receivers) can fully configure their decoders
  3. A naming convention for repair tracks
  4. The format of repair objects containing FEC symbols, and two block profiles: 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
  5. Interleaving strategies to protect against burst loss
  6. A compatibility statement for ATSC 3.0 MMTP sessions (Section 12). ARIB STD-B60 [ARIB-B60] carriage of MMTP-packaged tracks uses the in-band AL-FEC signaling of [MOQ-MMT] Section 8.3, and its Section 10 covers ARIB STD-B60 ingest.

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.

2. Terminology

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.

Source Track: A MoQ track carrying media data (e.g., video, audio).

Repair Track: A MoQ track carrying FEC repair symbols for a corresponding source track, 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.

3. Protocol Overview

The protocol operates as follows (Appendix A.1 shows the exchange):

  1. Subscriber obtains the catalog and reads the track's fec object (Section 5), which carries the complete FEC configuration
  2. Subscriber sends SUBSCRIBE for source track
  3. Publisher responds with SUBSCRIBE_OK
  4. Subscriber sends SUBSCRIBE for the repair track if FEC protection is desired (Section 6.2)
  5. Publisher sends source objects and repair objects
  6. Subscriber configures its decoder from the catalog fields and the Repair FEC Payload ID of each block (Sections 4.2 and 4.5) and uses repair symbols to recover any lost source symbols

The catalog is the subscriber's authoritative FEC configuration; the subscriber needs no other FEC signaling (Section 5.2).

When source objects are delivered as QUIC datagrams (unreliable), FEC recovery is the primary loss mitigation mechanism. When 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.

4. FEC Configuration

This section defines the FEC algorithm identifiers and the decoder parameters that constitute a track's FEC configuration, which is signaled in the catalog (Section 5.2); for RaptorQ, the full RFC 6330 Object Transmission Information is derived from the catalog fields (Section 4.2) rather than carried on the wire, and for Reed-Solomon, Section 4.4 fixes the code and its parameters are derived in the same way (Section 4.5).

4.1. FEC Algorithms

FEC algorithm values are registered in the "MoQ FEC Algorithms" registry (Section 15.2); the catalog (Section 5.1) carries the corresponding string identifiers.

RaptorQ (0x01): RaptorQ fountain code per [RFC6330]. Can recover from loss of any symbols as long as 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).

4.2. RaptorQ Object Transmission Information

An RFC 6330 decoder is configured by the Object Transmission Information (OTI): the 8-byte Common FEC OTI (Section 3.3.2 of [RFC6330]) and the 4-byte Scheme-Specific FEC OTI (Section 3.3.3 of [RFC6330]), totaling 12 bytes:

RaptorQ OTI {
  Transfer Length (40),
  Reserved (8),
  Symbol Size (16),
  Number of Source Blocks (8),
  Number of Sub-Blocks (16),
  Symbol Alignment (8),
}

This specification does not carry the OTI on the wire. When a track's catalog fec.algorithm is "raptorq", receivers MUST construct the OTI of each FEC block from the catalog fields (Section 5.1) and the block's SSB_length, which every repair packet of the block carries (Section 7.1), under the source symbol construction of the track's block profile (Sections 7.3 and 7.6.1), as follows:

  • Transfer Length: F = SSB_length x T, where SSB_length is the block's source symbol count (Section 7.1) and T is symbolSize, exact because every source symbol of 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).
  • Symbol Size: T = symbolSize.
  • Number of Source Blocks: Z = 1. Each FEC block of this specification is decoded as an independent RFC 6330 object containing a single source block. Blocks are identified by the SS_Start of the Repair FEC Payload ID of repair objects (Section 7.1), and source symbols are placed in them by SS_ID (Section 8.3) -- not by the RFC 6330 Z partitioning.
  • Number of Sub-Blocks: N = 1. Catalog-signaled sessions do not use sub-blocking (Section 7.3).
  • Symbol Alignment: Al = 8. 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.

4.3. Algorithm Requirements

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.

4.4. Reed-Solomon Code

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.

4.5. Reed-Solomon Parameters

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:

  • Symbol size: T = 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.
  • Rows: SSB_length, the block's source symbol count. The source symbol whose SS_ID is x is row (x - SS_Start) mod 2^32 of A, which is its ESI (Section 8.3).
  • Columns: the repair symbol whose RS_ID is j is column j of A. Its ESI, SSB_length + RS_ID (Section 7.2), still identifies it within its block, but the column depends on RS_ID alone.
  • Column count: RSB_length, the instance's total repair count P (Section 7.1).

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.

5. Catalog FEC Extension

5.1. Catalog Fields

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.

  • "none": No FEC
  • "raptorq": RaptorQ per RFC 6330 (OPTIONAL, Section 4.3)
  • "reed-solomon": Reed-Solomon over GF(2^8) per Section 4.4 (mandatory to implement, Section 4.3)

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.

5.1.1. Repair Track Fields

A track with "packaging": "fec-repair" describes its own role. It carries the flat MSF track fields plus the fields below. Layer 0 is identified by the source's fec.repairTrack; its entry MAY also carry depends, "repairLayer": 0 and repairSymbols, which MUST agree with the source's corresponding field when present (Section 6.3.4, rules 2 and 11).

depends (array of strings, REQUIRED except on layer 0): The name of the source track this track repairs. The array MUST contain exactly one name, and that name MUST identify a track in the same catalog 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).

5.1.2. Worked Catalog

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:

Table 1
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.

5.2. Signaling Model

The catalog fec object (Section 5.1) is the authoritative FEC signaling for MoQ receivers, that is for every receiver that obtains the track's catalog entry. Such a receiver has everything needed to discover and subscribe to the repair track (Section 6) and to configure its decoder 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.

5.3. FEC Source Info Object Property

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.

6. Repair Track Convention

6.1. Track Naming

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":

Table 2
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.

6.2. Subscription Model

Subscribers SHOULD subscribe to the source track first, then subscribe to the repair track if:

  1. The track's catalog entry signals FEC (a fec object naming a repairTrack, Section 5.1), AND
  2. The subscriber desires FEC protection

Repair-track subscription is selective and per-need: a subscriber chooses whether to consume repair data based on its own path conditions, and MAY start or stop its repair-track subscription at any time during the session -- for example, subscribing only after observing loss, or not subscribing at all on a reliable path.

Publishers and relays MUST NOT require subscription to repair tracks and MUST NOT condition delivery of a source track on a repair-track subscription. Repair tracks are optional; subscribers MAY choose to rely solely on QUIC retransmission or to accept unrecovered loss.

6.3. Layered Repair Tracks

A source track MAY be protected by more than one repair track. Each such track is a repair layer: an independently subscribable set of repair symbols for the same source blocks. Layer 0 is the repair track named by repairTrack, carrying the source's repairSymbols symbols per block. Layers 1..n are the tracks that name this source in depends and carry a repairLayer (Section 5.1.1), one track per layer index.

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).

6.3.1. Shared Block Geometry

All repair layers of a source track share its block geometry (algorithm, blockProfile, sourceSymbols, symbolSize, interleaveDepthMs, reorderToleranceMs) and differ only in repairSymbols. A repair layer MUST NOT carry a geometry field; rule 8 of Section 6.3.4 lists them, and a receiver rejects a catalog that violates it. Because each source packet or source object carries one base SS_ID (Sections 5.3 and 8.5), a different K or interleave window needs a separate rendition; the keyframe overlay (Section 6.4) is a separate FEC instance, not a layer.

6.3.2. Repair Symbol Identity Across Layers

Let P_i be the repairSymbols of layer i and O_i its RS_ID offset, defined below (O_0 = 0). P_0 is the source track's fec.repairSymbols (Section 6.3.4, rule 11), and P_i for i >= 1 the layer track's own repairSymbols. Layer i carries, for every source block, the repair symbols with RS_ID in [O_i, O_i + P_i). The Encoding Symbol ID follows the single-layer rule of Section 7.2:

O_i   = sum(P_j for j < i)
RS_ID = O_i + j, for the j-th symbol of layer i
ESI   = SSB_length + RS_ID

where SSB_length is the block's source symbol count (Section 7.1).

The total repair count of the block is the sum of P_i over all published layers. RSB_length on every repair packet of every layer carries this total (Section 7.1), not the layer's own P_i. That is what makes the RS_ID to ESI mapping independent of which layers a given receiver joined: a receiver holding a non-prefix subset computes the same coordinate for a symbol as a receiver holding everything, and the RS_ID < RSB_length bound holds for a symbol from any layer.

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.

6.3.3. Algorithms That Admit Layers

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.

6.3.4. Catalog Rules and Fail-Closed Validation

A receiver MUST validate all of the following for a source track before starting FEC for it. On any violation the receiver MUST fail closed: it MUST report the offending catalog path and MUST NOT start FEC for that source track. A receiver MUST NOT repair the catalog by ignoring the offending track, because every rule below distinguishes a layer set that decodes from one that silently mis-maps symbols.

  1. depends names exactly one track in the same catalog, which carries an fec object whose blockProfile admits that track's packaging (Section 5.1).
  2. The 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.
  3. 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.
  4. For each FEC instance, the total of repairSymbols across all its layers is at most 2^24 - 1, the range of RSB_length.
  5. For each FEC instance, K + totalP - 1 is at most 2^24 - 1, which bounds the largest ESI the instance can produce.
  6. When 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.
  7. Repair layers and any overlay appear only when fec.algorithm is raptorq or reed-solomon (Section 6.3.3 above).
  8. A track whose 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).
  9. No orphan repair track: every track whose 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.
  10. A source track has at most one track with "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.
  11. The layer-0 repair track's 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.
  12. When 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).
  13. The 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.

Table 3
Catalog defect Rule Why the wire cannot catch it
video/repair declares repairSymbols 16 while the source declares fec.repairSymbols 8 11 Both readings are self-consistent: one derives O_1 = 8 and total 56, the other O_1 = 16 and total 64. A repair symbol is identified by ESI alone, so a receiver that resolved P_0 the other way decodes with a shifted mapping and reports a corrupt block, not a catalog error.
Two tracks declare "repairLayer": 1 for video 2 Both claim RS_ID 8 to 23. Symbols from the two tracks are distinct on the wire but collide in ESI, so a decode fed from both sees duplicate encoding symbols and stalls short of K.
video/repair/2 is present but no track declares layer 1 2 O_2 is a function of P_1, which is absent, so the receiver has no offset for layer 2 at all.
video/repair/kf carries "repairLayer": 3 alongside "scope": "keyframe" 10 The overlay is a second FEC instance over its own K (Section 6.4). Admitting it as a layer would fold its RS_ID space into O_i and place its symbols in the base instance's ESI range.
A second track for video declares "scope": "keyframe" 10 A RAP packet carries one overlay SS_ID, in its one header extension (Section 8.5.1), so a second overlay has no SS_ID on the wire.
video/repair/1 carries symbolSize or its own fec object 8 A repair track carrying its own geometry would name itself as layer 0 and bypass rule 9's reachability check.

A receiver MAY report several violations at once.

6.3.5. Receiver Selection

The per-need model of Section 6.2 applies to each layer independently. On a lossy path a receiver SHOULD subscribe layer 0 first. When a block fails recovery with the receiver's current layer set and a higher layer exists, the receiver SHOULD subscribe the next layer; it MAY instead request only the failed block's repair objects from that layer, a request bounded to the block's repair group (Section 7.5), when the block is still inside its recovery budget (Section 9). On a multicast or AMT leg, Section 11.4 governs such per-block requests: which blocks get one, when, with what budget and priority, and what happens when one fails. A receiver MAY unsubscribe a layer after a receiver-chosen number of consecutive blocks whose loss stayed within the tolerance of the remaining layers. Hysteresis is counted in blocks, the protocol's unit, not by a fixed timer (Section 6.3.6).

6.3.6. Repair-Only Multicast Endpoints

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.

6.3.7. Interaction with the Interleave Window

Layers never change interleaveDepthMs, the stream's single recovery-latency lever (Section 9). A shallow window recovers bursts only by per-block unicast repair (Sections 6.3.5 and 11.4.2), at about one round trip; a deep window recovers them in band at that window's latency. Serving both requires two renditions (Section 6.3.1).

6.3.8. Compatibility

A source track with a single repair track is the one-layer case (O_0 = 0, RSB_length = repairSymbols). A receiver that subscribes only layer 0 decodes correctly whatever other layers exist: layer 0 alone is a valid layer set, and it uses RSB_length only as 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).

6.3.9. Changing the Layer Set Within a Session

Publishing a layer is adding one tracks entry and withdrawing it is removing one, but the two directions are not symmetric, because O_i is a function of every lower layer's P (Section 6.3.2). A change to the set can therefore move the coordinates of a layer a receiver has already joined. This subsection states which changes are defined.

Layer sets are append-only. A publisher MAY append a layer at the next index above the highest published one; 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.

6.4. Keyframe Overlay

A source track MAY additionally be protected by a keyframe overlay: a second, independent FEC instance whose source symbols are only the fragments of Random Access Points of that source track. 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.

6.4.1. Overlay Instance

An overlay is a separate FEC instance over the same source track. It has its own sourceSymbols (K_overlay) and its own repairSymbols, declared on its own repair track, and it shares the source track's algorithm, blockProfile and symbolSize. It does not share the base instance's K, its block partition, its SS_ID space, or its RS_ID space.

Every per-block quantity of this document -- K, the total repair count P, SS_ID, ESI, RS_ID, SS_Start, RSB_length, SSB_length, the short-block rules of Section 7.4, the wrap epoch and repair group IDs of Section 7.5, and the bounds of Section 6.3.4 -- is defined within one FEC instance. For the base instance, K is the source track's fec.sourceSymbols and P is the sum of repairSymbols over its published layers (Section 6.3.2); for an overlay, K and P are the sourceSymbols and repairSymbols of its own track. A repair packet belongs to the instance of the track it arrived on (Section 6.4.2).

An overlay is not a repair layer. It carries no repairLayer, it is not a member of the layer index chain, and it is excluded from the contiguity and priority monotonicity rules of Section 6.3.4, which order the base layer chain only. Its priority is independent within 192 to 255, and MAY be numerically lower than a base enhancement layer's so that a keyframe repair symbol is delivered before an ordinary one.

Overlay ESIs never collide with base ESIs because the two are different instances decoded by different decoders; a receiver MUST NOT feed a repair symbol of one instance to the decoder of the other, and MUST NOT reuse a source symbol's coordinate in one instance as its coordinate in the other. A RAP source packet is a source symbol of both instances, at an unrelated coordinate in each (Section 6.4.2).

A source track has at most one overlay (Section 6.3.4, rule 10), a wire constraint explained in Section 8.5.1. An overlay is declared only by the catalog, never in an in-band AL-FEC message, and only where no FEC source or repair packet carries FFSRP_TS (Section 8.5.1).

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.

6.4.2. Overlay Membership

The overlay's source symbols are the fragments of the source track that belong to a Random Access Point, in transmission order. A publisher that declares an overlay MUST set RAP_flag on a source packet of the track, MUST include the packet in the overlay instance, and MUST carry the packet's overlay SS_ID in its 0x8B01 header extension (Section 8.5.1), if and only if that packet's payload belongs to a keyframe MFU covered by the overlay.

Overlay source symbols are numbered consecutively within the overlay instance, in the order the publisher emits them: the overlay SS_ID is 0 at the first overlay source symbol of the stream and advances by one per overlay source symbol, modulo 2^32 (Section 7.5). It is the value the RAP source packet carries in its 0x8B01 header extension (Section 8.5.1). It lives in the overlay instance's own SS_ID space, independent of the base instance's, and the two IDs on one packet are unrelated numbers. An overlay source block holds at most K_overlay overlay source symbols, and overlay blocks, including short ones, are formed, located and wrapped exactly as base blocks are (Sections 7.4, 7.5 and 8.3), with K_overlay as the upper bound on their SSB_length. Because a RAP is a small fraction of the media, an overlay block spans many base blocks; the overlay's recovery latency is therefore its own block span and is unrelated to interleaveDepthMs.

A receiver knows that a source packet is an overlay source symbol because the packet carries the 0x8B01 header extension (Section 8.5.1). It knows that a repair packet belongs to the overlay because it arrives on the repair track that the catalog declares with "scope": "keyframe" for this source track, and that track has its own packet_id. The instance is therefore fixed by the track the packet arrived on; no field of the repair packet distinguishes the two, and a receiver MUST NOT attempt to infer the instance from SS_Start, RSB_length, or SSB_length, whose values are only interpretable once the instance is known.

6.4.3. Receiver Behavior

A receiver that implements overlays and has joined the overlay repair track decodes the two instances independently and MAY use the recovered RAP fragments even when the base instance failed to recover the block that carried them.

The overlay is the publisher-side half of keyframe protection. The receiver-side half is the repair policy of Section 11.4, under which a receiver gives a keyframe-bearing base block that in-band decoding leaves unrecovered priority unicast repair; Section 11.4.6 states how the two combine.

A receiver that does not implement overlays MUST fail closed on a catalog that declares one for a track it intends to consume, that is on a fec-repair track carrying the unknown scope key, and MUST NOT ignore the key and consume the source track anyway. This is one of the unknown-key exceptions of Section 5.1.1: a receiver that ignored the key could not tell the overlay's repair track from a repair layer of the base instance, and would feed the base decoder repair symbols of another FEC instance (Section 6.4.2).

This mechanism is not backward compatible with receivers that predate it, for the same reason. A publisher that must serve such receivers publishes the overlay on a separate source track, or does not publish it.

7. Repair Object Format

7.1. Repair Object Header

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.

7.2. Repair Symbols

For RaptorQ, repair symbols are generated per [RFC6330] Section 5.3. The source symbols of a block occupy ESIs 0 to SSB_length - 1 in SS_ID order, and the Encoding Symbol ID (ESI) of a repair symbol starts at SSB_length, the block's K in the notation of [RFC6330] ([RFC6330] Section 5.3.1): ESI = SSB_length + RS_ID, both fields taken from the Repair FEC Payload ID (Section 7.1). The Internal Symbol IDs of [RFC6330], which start the repair symbols at that document's K', are internal to its encoder and decoder and never appear on the wire.

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.

7.3. Sub-Blocks and ssbg_mode

Per ISO 23008-1 [ISO.23008-1] Section C.3.3 (signalled per C.6.3, Table C.5), the FEC block structure is described by the source symbol block generation (SSBG) mode (ssbg_mode). The iso-ssbg1-v1 block profile (Section 5.1) uses ssbg_mode1, with the one-stage FEC coding structure and FEC payload ID mode 0 ([ISO.23008-1] Clause C.1). 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.

7.4. Short Source Blocks

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:

  1. 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.

  2. 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.

  3. The block's repair ESIs start at SSB_length: ESI = SSB_length + RS_ID (Section 7.2).

  4. 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.

  5. 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.

7.5. SS_ID Wrap and Repair Group IDs

SS_ID and SS_Start are 32-bit values that start from an arbitrary value and wrap to 0 after their maximum ([ISO.23008-1] Section C.5.2). Every comparison, distance and range test on them in this document, block membership (Section 8.3) included, uses serial number arithmetic [RFC1982] with SERIAL_BITS = 32. A block can span the wrap: a block with SS_Start 2^32 - 3 and SSB_length 4 holds the SS_IDs 2^32 - 3, 2^32 - 2, 2^32 - 1 and 0, and the next block starts at SS_ID 1.

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:

  1. 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.

  2. 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.

  3. 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:

  • K is the instance's sourceSymbols (Section 5.1), the largest SSB_length that a block can have (Section 7.4), so the block that contains x starts at most K - 1 SS_IDs before x;
  • S_prev is the SS_Start of the last block that the receiver has delimited that ends before x. Within a consumer that the bc-provenance profile of [MOQ-MULTICAST] Section 7.2 governs for its blocks (Section 7.4), only a block that a repair packet the profile has admitted delimits counts here: a provisional block, one that only symbols of an unlisted track (Section 7.4) have delimited, is no such block, as its (SS_Start, SSB_length) is unverified and the block that contains x may start within its range. When the receiver has delimited no such block, the first term is absent and the range is [ max(ext(x) - (K - 1), 0), ext(x) ];
  • ext(x) is x extended relative to ext(S_prev) when S_prev exists, and otherwise relative to the reference value r of the receiver's wrap epoch.

Repair Group IDs sit at block starts, so the range returns the repair of every block that starts within it, up to and including the block that contains x, and the last Group it returns is that block. The range is never empty: it always contains ext(x). A receiver that has not established the wrap epoch, or that may not extend x, has no range to request until it establishes one. A receiver that holds a repair packet of the block requests the one Group ext(SS_Start) instead.

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].

7.6. Object Block Profile

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.

7.6.1. Protected Object Unit

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.

  • Group ID and Object ID: the Location of o ([I-D.ietf-moq-transport] Section 8.2).
  • Immutable Properties Length: the length in bytes of the value of o's Immutable Properties Property ([I-D.ietf-moq-transport] Section 10.7), or 0 when o has none. A Property value has at most 2^16 - 1 bytes ([I-D.ietf-moq-transport] Section 8.3).
  • Immutable Properties: that value, the Key-Value-Pairs exactly as the publisher serialized them, which no node may change ([I-D.ietf-moq-transport] Section 10.7). It is empty when the length is 0.
  • Payload Length: the length in bytes of the Object Payload of o.
  • Payload: the Object Payload of o.

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.

7.6.2. Source Objects and Blocks

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.

7.6.3. Repair Objects

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.

7.6.4. Recovery

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:

  1. 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.

  2. 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.

  3. 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:

  • whose Immutable Properties do not parse as a sequence of Key-Value-Pairs ([I-D.ietf-moq-transport] Section 8.3), or contain an Immutable Properties Property ([I-D.ietf-moq-transport] Section 10.7);
  • whose Immutable Properties carry a FEC Source Info Property with a value other than the SS_ID of the unit's first symbol, which is SS_Start plus the ESI at which the walk found the unit, modulo 2^32; or
  • whose Location is that of an object the receiver already holds.

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.

7.6.5. Packaging Requirements

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.

7.6.6. Applicability

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.

7.6.7. Example

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:

  • An IDR payload of 60,000 bytes gives len(o) = 60,037 and s(o) = 51. The unit's last symbol ends with 1,163 bytes of padding, which are not sent.
  • A P-frame payload of 7,000 bytes gives len(o) = 7,037 and s(o) = 6, with 163 bytes of padding.
  • A Group therefore spans 51 + 29 x 6 = 225 source symbols, within K = 256.

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:

Table 4
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).

8. Block and Group Alignment

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.

8.1. Blocks Within a Group

For example, a source Group can contain two consecutive blocks:

Group G:    SS_ID s   .. s+a-1      -> block A, SS_Start = s
            SS_ID s+a .. s+a+b-1    -> block B, SS_Start = s+a
Group G+1:  SS_ID s+a+b ..          -> next block or continuation
...

8.2. Blocks Across Groups

A block can also span a Group boundary:

Group G:    SS_ID s   .. s+a-1      -> block A, still open
Group G+1:  SS_ID s+a .. s+L-1     -> block A completes
            SS_ID s+L ..            -> next block
...

A block's repair objects form the repair-track Group whose Group ID is the block's extended SS_Start (Section 7.5), a number space unrelated to the source track's Group IDs. No fixed number of MoQ Groups is required for a block, and no Group boundary can be used to infer SSB_length.

8.3. Source Symbol Location

Under iso-ssbg1-v1, every FEC source packet carries a Source FEC Payload ID (Section 8.5), and a receiver that parses the packet takes each source symbol's SS_ID from that field on every path that delivers the packet with its trailer. The SS_ID is also carried alongside the packet where the packaging says so: on the MoQ path every object carrying a source symbol carries it in the FEC Source Info Object Property (Section 5.3), under the same value and the same definition, whether or not that object also delivers the trailer. A receiver that does not parse the FEC source packet -- a relay, or a MoQ receiver with no MMTP parser -- takes the SS_ID from there. The SS_ID advances by one per FEC source packet, modulo 2^32, in the order the publisher emits the packets ([ISO.23008-1] Section C.5.2), and the blocks of an FEC instance are consecutive: each starts at the SS_ID that follows the last source symbol of its predecessor (Section 7.4).

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).

8.4. Encoder Constraints

For FEC block alignment and timing to be deterministic, encoders MUST:

  1. 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.

  2. 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.

  3. If frame rate or GOP size changes mid-session, update the MoQ catalog and signal a manifest discontinuity for DASH/HLS.

  4. 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.

8.5. Source FEC Payload ID and ATSC 3.0 Signed Region

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.

8.5.1. Overlay SS_ID Header Extension

When the catalog declares a keyframe overlay for a source track (Section 6.4), a source packet of that track carrying a Random Access Point fragment is a source symbol of two FEC instances. It carries its base SS_ID in the one Source FEC Payload ID trailer that every FEC source packet carries (Section 8.5), and its overlay SS_ID (Section 6.4.2) in an MMTP header extension ([ISO.23008-1] Clause 9.2.3) of type 0x8B01:

Source Packet with Overlay {
  MMTP Packet Header {
    ...,                          # X = 1, RAP_flag = 1
    Header Extension {
      Type (16) = 0x8B01,
      Length (16) = 4,
      Overlay SS_ID (32),
    },
  },
  MMTP Payload (..),
  Source FEC Payload ID (32),     # base instance SS_ID
}

A publisher that declares an overlay MUST carry this extension as the header extension, with X = 1, of exactly the source packets that it includes in the overlay instance, that is the packets on which it sets RAP_flag (Section 6.4.2), and of no other packet of the track. An MMTP packet carries at most one header extension ([ISO.23008-1] Clause 9.2.3), so the RAP packets of a track under an overlay carry no other MMTP header extension, and a publisher that needs another header extension on those packets cannot use the overlay for that track. [ISO.23008-1] specifies no particular header extension and no registry of header extension types; this document uses the type 0x8B01 for the overlay SS_ID (Section 15.1).

The trailer is never more than one Source FEC Payload ID. On a packet with or without the extension, the last four bytes are the base SS_ID, as [ISO.23008-1] Section C.4.2 places it, so a receiver that does not implement overlays locates the trailer and the payload as on any other packet, stepping over the extension by its Length field. The extension lies inside the MMTP packet header, so it is part of the protected packet of both instances (Section 7.3), which protect one identical source symbol. The permission of [ISO.23008-1] Clause 9.2.3 to discard a header extension therefore extends only to a receiver's own processing: a node that forwards the packet MUST NOT remove or alter the extension. A RAP packet recovered by either instance carries its overlay SS_ID, so a receiver MAY place a RAP packet that the base instance recovered into the overlay block that the extension locates; Section 7.3 states why the converse requires the packet's base SS_ID.

A receiver that implements overlays takes a packet's overlay SS_ID from this extension and from nothing else. It MUST NOT feed the overlay decoder a source packet that lacks the extension, whatever its RAP_flag, or one whose extension has a Length other than 4, and MUST NOT infer an overlay SS_ID from RAP_flag, from the packet's position, or from its base SS_ID.

A source track has at most one overlay (Section 6.3.4, rule 10) because a source packet has one header extension, and so carries one overlay SS_ID; relaxing that bound would be a revision of this document and a change to the source packet layout, not a catalog-only change.

The overlay is declared only by the catalog. A publisher MUST NOT describe the overlay's repair flow in an AL-FEC message ([MOQ-MMT] Section 8.3): the message identifies an FEC source flow by packet_id ([ISO.23008-1] Clause C.6.3) and cannot describe the RAP subset that the overlay protects, so a receiver that consumes the flow without the catalog uses the base instance alone. An overlay is defined only without FFSRP_TS: a publisher MUST NOT declare an overlay for a source track whose FEC source or repair packets carry FFSRP_TS (ffsrpts_flag = 1, [ISO.23008-1] Section C.5.1), and the extension carries an SS_ID alone.

Section 8.5 applies to the overlay SS_ID as to the base one: A3SA signing authenticates neither, and a receiver that requires authenticated block assignment treats each as Section 8.5 requires.

9. Interleaving

Interleaving spreads source symbols across time to protect against burst loss. The interleave window (Interleave Depth, in milliseconds) bounds the elapsed send span of a source block when the field is positive. It does not define the block's membership or imply a number of Groups. Block membership is the consecutive SS_ID range identified by (SS_Start, SSB_length) (Sections 7.4 and 8.3).

Groups:         M0             M1             M2
                 |              |              |
Blocks:       [Block 0] [Block 1] [Block 2] [Block 3]
SS_ID:           S0  S1  S2  S3  S4  S5  S6  S7  ...
                 |       |       |       |
Repair Groups:  ext(S0) ext(S2) ext(S4) ext(S6)

A burst loss can therefore erase symbols from several adjacent blocks; each block is recovered with the repair symbols identified by its own SS_Start and SSB_length. With P repair symbols for a block, the 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:

Table 5
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
}
  1. A 30 fps track with a 30-frame (1000 ms) GOP may close a block after four access units (a four-frame access-unit interval). With the send schedule in the vector, interleaveDepthMs = 133. An access unit can produce multiple source packets, so the block is closed after those access units, not after an assumed packet count. For this concrete vector, the four access units begin at 0, 33.333, 66.667, and 100 ms, produce 2, 3, 1, and 4 source packets respectively, and therefore 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]]
   }
  1. If the stream ends with two source packets in the current block, the publisher sends a short block with SSB_length = 2, F = 2 x T, and no padding or skipped SS_ID. There is no following block.

10. Priority and Congestion

Priorities in this document are expressed in the MoQ Transport priority scale [I-D.ietf-moq-transport]: an 8-bit value (0-255) in which a numerically LOWER value is delivered with HIGHER precedence. Repair tracks SHOULD use a numerically greater (lower-precedence) priority than the source tracks they protect, so that repair data is dropped first under congestion. The RECOMMENDED assignment places a repair track's priority value at least 64 above its source track's (e.g. repair 240 against a source track at the common default of 128):

Table 6
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:

  1. Source media is preserved as long as possible
  2. Repair overhead is gracefully shed
  3. Receivers degrade to QUIC retransmission when FEC is unavailable

On a multicast or AMT leg, the priorities of on-demand unicast repair requests are set by Section 11.4.5.

11. Hybrid Unicast and Multicast Delivery

This FEC mechanism is designed to support hybrid delivery architectures where the same media stream is delivered via multiple transport paths simultaneously. Multicast delivery paths, TreeDN integration, and the transport hierarchy (Sections 1 and 3) are defined in [MOQ-MULTICAST]; this section covers FEC-specific considerations for hybrid delivery.

11.1. Multicast and AMT Delivery

IP multicast (including Source-Specific Multicast per [RFC4607]) and Automatic Multicast Tunneling (AMT per [RFC7450]) provide efficient one-to-many delivery but are inherently unreliable. FEC enables receivers to recover from packet loss without retransmission:

  • Native SSM: Receivers join multicast group directly
  • AMT Tunneling: Receivers without native multicast connect via AMT relays discovered through DRIAD ([RFC8777])
  • TreeDN ([RFC9706]): native SSM where a network supports multicast, and AMT relays, found through DRIAD, for receivers on unicast-only networks. The publisher generates FEC repair end to end, and the repair is the same on every leg.

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

11.2. Deployment Applicability

The repair overhead this mechanism adds is justified only where the delivery path actually loses packets, and multicast loss characteristics differ by orders of magnitude across access technologies. FEC strength (P and Interleave Depth) is a per-path deployment choice, expressed by which tracks each endpoint carries, not a protocol constant.

  • Engineered low-loss segments. On managed PON or DOCSIS delivered over a provisioned VLAN, steady-state loss is typically far below 10^-6. Disabling FEC for such a path is signaled by omitting the repair track from the tracks that path's endpoints carry. Adding repair symbols on such a path spends bandwidth to recover losses that do not occur.

  • FEC-capable broadcast PHYs. ATSC 3.0, DVB-S2/S2X, and 5G broadcast already apply bit-error correction on their own radio link (e.g., LDPC/BCH in ATSC 3.0 and DVB-S2/S2X). Application-layer FEC is NOT a duplicate of that correction: it recovers packet erasures the PHY cannot address -- bursts when reception falls below the PHY threshold (rain fade, mobility, indoor reception), and losses on upstream aggregation or backbone hops that the last-hop PHY never sees. Its value on these paths comes primarily from Interleave Depth spreading a burst across the time domain, not from the code rate. On a one-way broadcast downlink with no return path, application-layer FEC is the only available erasure-recovery mechanism -- which is why ATSC 3.0 (see Section 12) specifies it above the PHY.

  • Public Internet and AMT tunnels. Loss is real and bursty; a non-trivial repair count with interleaving is RECOMMENDED.

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.

11.3. Interaction with Multicast QUIC

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:

  1. 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.

  2. 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.

  3. 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).

  4. 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.

11.4. Receiver Repair Policy

This section specifies what a receiver of a multicast or AMT leg does with a base-instance block of a source track that in-band FEC has not recovered by the block's FEC deadline (Section 9). A receiver on a reliable MoQ/QUIC leg relies on transport retransmission (Section 3) and does not need it, and nothing in this section adds a deadline or a timer to such a leg. 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).

11.4.1. Block Classification

A base block of a video source track is keyframe-bearing if it carries, or may carry, any part of a RAP: a fragment of a RAP MFU, or of the FT=0 or FT=1 data unit that governs it ([MOQ-MMT] Sections 4.3 and 5.1). The receiver classifies each block when the block reaches its FEC deadline, from two inputs and only from them: in-band evidence in the source packets it holds, and the catalog-authored timing of the track, that is its group structure, one MPU per group of the catalog group duration ([MOQ-MMT] Sections 4.3 and 4.4.2), and its keyframe interval ([MOQ-MMT] Section 4.4.3). The block's SS_Start and SSB_length, once known (Section 7.4), fix which SS_IDs belong to the block, and a positive interleaveDepthMs with reorderToleranceMs fixes the elapsed-time deadline at which the class is taken (Section 9).

The receiver first bounds what the block's missing source symbols can carry. The lower bounding packet is the last source packet it holds, in SS_ID order, before the block's first missing source symbol; the upper bounding packet is the first source packet it holds after the block's last missing source symbol. Either may lie in an adjacent block. Only FEC source symbols count: the AL-FEC signaling object of [MOQ-MMT] Section 8 carries no SS_ID and is never a bounding packet. A publisher MUST assign the base SS_IDs of a track's source packets in increasing order along the authored order of [MOQ-MMT] Section 4.3, so every data unit the missing symbols can carry lies between the data units of the two bounding packets, those two included.

The block is keyframe-bearing if any of the following holds:

  1. 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.

  2. 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).

  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.

11.4.2. Keyframe-Bearing Blocks

When a keyframe-bearing block is still unrecovered at its FEC deadline, a receiver that holds a MoQ session with a relay serving the block's repair track MUST request on-demand unicast repair for it, with the priority of Section 11.4.5, 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.

11.4.3. Other Video Blocks

For a non-keyframe-bearing block of a video track, in-band FEC remains the primary repair. A receiver MAY also request unicast repair for it, in the form of Section 11.4.2, but only on the terms of Section 11.4.5: never ahead of or concurrently with keyframe repair, and only within the budget that keyframe repair leaves unspent.

When such a block is unrecovered -- at its FEC deadline without unicast repair, or when its unicast repair has not completed by the presentation time of the first media it would repair -- the receiver MUST NOT stall. It conceals the affected frames, and every frame that depends on them, until the next RAP, and keeps presentation and audio/video synchronization running:

  • Concealment fills the presentation interval of the frames it replaces and ends at the authored presentation time of the next frame the receiver presents. The receiver MUST NOT drop later frames to absorb the loss. It derives no timing for the frames it replaces ([MOQ-MMT] Section 5.1).

  • The concealment method is an implementation choice: for example holding or replaying the last presented frame, or presenting decoder output in which missing reference data is filled (commonly visible as a solid or green fill). The receiver MUST NOT submit to the decoder a sample that the packaging's reassembly rules have invalidated ([MOQ-MMT] Section 5.2).

  • The next RAP ends concealment, and the receiver resumes normal decoding from it.

11.4.4. Audio Blocks

In-band FEC applies to the blocks of an audio track as to every block, and a receiver MAY request unicast repair for an audio block on the same best-effort terms as for a non-keyframe video block (Section 11.4.5). RAP_flag on an audio packet does not make its block keyframe-bearing; that class applies to video tracks only.

When an audio block is unrecovered, the receiver MUST conceal the lost audio, for example with silence or packet-loss concealment, from the end of the last audio it presented to the authored presentation time of the next audio it presents, and MUST keep the audio clock advancing through the loss. It MUST NOT stall audio presentation waiting for a repair that has not completed by the presentation time of the lost audio.

11.4.5. Unicast Repair Budget and Priority

A receiver's unicast repair budget is derived from the catalog, not from a receiver-local rate or byte constant. It is kept per MoQ session and counted in bytes of repair symbol data, a repair symbol of a track counting as that track's symbolSize T (Section 5.1).

  • Each block that Section 11.4.1 treats as keyframe-bearing, including a block of unknown class, credits the budget with P_t x T bytes when it reaches its FEC deadline, where P_t is the total repair count of its base instance (Section 6.4.1) and T is its track's symbolSize.

  • A credit expires when the next keyframe-bearing block of the same source track reaches its FEC deadline, so unspent budget never accumulates beyond one block's credit per source track.

  • Every unicast repair FETCH debits the budget with the repair symbol bytes it requests. A FETCH of a Group range (Section 7.5) requests every Group that starts in the range, a number the receiver learns only from the response, and is debited with the repair symbol bytes of every Group it returns.

  1. 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.

  2. 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.

  3. 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.

11.4.6. Relationship to the Keyframe Overlay

The keyframe overlay of Section 6.4 and this policy are complementary. The overlay is publisher-side and proactive: it protects RAP fragments across a block of its own, needs no return path, and so also serves sessionless receivers. This policy is receiver-side and reactive: it spends unicast repair only on keyframe-bearing blocks that in-band FEC actually failed to recover, and it needs a MoQ session. A receiver that holds both:

  • classifies blocks by Section 11.4.1 whether or not it holds the overlay;

  • MUST NOT defer the unicast repair of a keyframe-bearing block to wait for overlay recovery, whose latency is the overlay's own block span (Section 6.4.2), not the base deadline;

  • ends its wait for a RAP with whichever of base decoding, overlay decoding, or unicast repair supplies the RAP's fragments first; and

  • having recovered a block's RAP MFU fragments through the overlay, and holding the FT=0 and FT=1 data units that govern them, conceals the rest of that block's loss as for a non-keyframe block (Section 11.4.3) and SHOULD cancel any outstanding keyframe repair FETCH for it. The overlay covers only packets that set RAP_flag (Section 6.4.2), so it does not by itself recover a lost FT=0 or FT=1 data unit.

12. ATSC 3.0 Compatibility

This specification is designed for interoperability with 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.

13. Interaction with CMAF Packaging

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.

14. Security Considerations

14.1. FEC Does Not Provide Confidentiality

FEC repair symbols are derived from source data. If source data is encrypted, repair symbols will also be encrypted by virtue of operating on ciphertext. However, FEC itself provides no confidentiality guarantees.

14.2. Repair Symbol Manipulation

An attacker who can modify repair symbols could cause receivers to reconstruct incorrect source data. Integrity protection of repair tracks is RECOMMENDED, using the same mechanisms as source tracks (e.g., QUIC packet protection).

14.3. Amplification

FEC repair symbols represent additional bandwidth. Publishers MUST NOT generate excessive repair symbols that could be used for bandwidth amplification attacks. The repair overhead (P/K) SHOULD be limited to reasonable values (e.g., <= 50%). The bound applies per FEC instance (Section 6.4.1), 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.

14.4. Multicast FEC Security

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:

  1. 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.

  2. 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).

  3. 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).

  4. 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.

  5. 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.

14.5. ATSC 3.0 Signed Region (A3SA) Considerations

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).

14.6. Object Block Profile Considerations

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.

14.7. Reed-Solomon Considerations

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.

15. IANA Considerations

15.1. MoQ Registrations

This document requests one registration in the "MOQ Properties" registry of [I-D.ietf-moq-transport] (Section 8.4 of that document):

Table 7
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.

15.2. FEC Algorithm Registry

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:

Table 8
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).

15.3. Catalog Packaging Value

This document defines the catalog packaging value "fec-repair" (Section 5.1) for repair tracks, extending the allowed packaging values of the 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:

Table 9
Value Description Reference
"fec-repair" Repair objects protecting a source track This document

15.4. FEC Block Profile Registry

This document requests creation of a "MoQ FEC Block Profiles" registry, in the registry group of Section 15.2, with the following initial values:

Table 10
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.

16. References

16.1. Normative References

[I-D.ietf-moq-loc]
Zanaty, M., Nandakumar, S., and P. Thatcher, "Low Overhead Media Container", Work in Progress, Internet-Draft, draft-ietf-moq-loc-04, , <https://datatracker.ietf.org/doc/html/draft-ietf-moq-loc-04>.
[I-D.ietf-moq-msf]
Law, W. and S. Nandakumar, "MOQT Streaming Format", Work in Progress, Internet-Draft, draft-ietf-moq-msf-01, , <https://datatracker.ietf.org/doc/html/draft-ietf-moq-msf-01>.
[I-D.ietf-moq-transport]
Nandakumar, S., Vasiliev, V., Swett, I., and A. Frindell, "Media over QUIC Transport", Work in Progress, Internet-Draft, draft-ietf-moq-transport-22, , <https://datatracker.ietf.org/doc/html/draft-ietf-moq-transport-22>.
[ISO.23008-1]
ISO/IEC, "Information technology - High efficiency coding and media delivery in heterogeneous environments - Part 1: MPEG media transport (MMT)", ISO/IEC 23008-1:2023, .
[ISO.23008-1.AMD1]
ISO/IEC, "Information technology - High efficiency coding and media delivery in heterogeneous environments - Part 1: MPEG media transport (MMT) - Amendment 1: Signalling of adaptive FEC scheme", ISO/IEC 23008-1:2023/Amd 1:2025, .
[ISO.23008-10]
ISO/IEC, "Information technology - High efficiency coding and media delivery in heterogeneous environments - Part 10: MPEG media transport forward error correction (FEC) codes", ISO/IEC 23008-10:2015, .
[MOQ-MMT]
Ramadan, O., "MPEG Media Transport (MMT) Packaging for Media over QUIC", Work in Progress, Internet-Draft, draft-ramadan-moq-mmt-01, , <https://datatracker.ietf.org/doc/html/draft-ramadan-moq-mmt-01>.
[MOQ-MULTICAST]
Ramadan, O., "Multicast Delivery and Endpoint Discovery for Media over QUIC", Work in Progress, Internet-Draft, draft-ramadan-moq-multicast-01, , <https://datatracker.ietf.org/doc/html/draft-ramadan-moq-multicast-01>.
[RFC1982]
Elz, R. and R. Bush, "Serial Number Arithmetic", RFC 1982, DOI 10.17487/RFC1982, , <https://www.rfc-editor.org/info/rfc1982>.
[RFC2119]
Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, , <https://www.rfc-editor.org/info/rfc2119>.
[RFC6330]
Luby, M., Shokrollahi, A., Watson, M., Stockhammer, T., and L. Minder, "RaptorQ Forward Error Correction Scheme for Object Delivery", RFC 6330, DOI 10.17487/RFC6330, , <https://www.rfc-editor.org/info/rfc6330>.
[RFC8126]
Cotton, M., Leiba, B., and T. Narten, "Guidelines for Writing an IANA Considerations Section in RFCs", BCP 26, RFC 8126, DOI 10.17487/RFC8126, , <https://www.rfc-editor.org/info/rfc8126>.
[RFC8174]
Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, , <https://www.rfc-editor.org/info/rfc8174>.

16.2. Informative References

[ARIB-B60]
ARIB, "MMT-Based Media Transport Scheme in Digital Broadcasting Systems", ARIB STD-B60 Version 1.14.
[ATSC-A331]
ATSC, "Signaling, Delivery, Synchronization, and Error Protection", ATSC A/331:2026-02, , <https://www.atsc.org/atsc-documents/3312017-signaling-delivery-synchronization-error-protection/>.
[ATSC-A360]
ATSC, "ATSC 3.0 Security and Service Protection", ATSC A/360:2026-08, , <https://www.atsc.org/atsc-documents/3602018-atsc-3-0-security-service-protection/>.
[I-D.ietf-moq-cmsf]
Law, W., "CMSF- a CMAF compliant implementation of MOQT Streaming Format", Work in Progress, Internet-Draft, draft-ietf-moq-cmsf-01, , <https://datatracker.ietf.org/doc/html/draft-ietf-moq-cmsf-01>.
[I-D.ietf-moq-secure-objects]
Jennings, C. F., Nandakumar, S., and R. Barnes, "End-to-End Secure Objects for Media over QUIC Transport", Work in Progress, Internet-Draft, draft-ietf-moq-secure-objects-01, , <https://datatracker.ietf.org/doc/html/draft-ietf-moq-secure-objects-01>.
[ISO.23001-7]
ISO/IEC, "Information technology - MPEG systems technologies - Part 7: Common encryption in ISO base media file format files", ISO/IEC 23001-7:2023, .
[QUIC-MULTICAST]
Holland, J., Pardue, L., Franke, M., and K. Rose, "Multicast Extension for QUIC", Work in Progress, Internet-Draft, draft-jholland-quic-multicast-09, , <https://datatracker.ietf.org/doc/draft-jholland-quic-multicast/>.
[RFC4607]
Holbrook, H. and B. Cain, "Source-Specific Multicast for IP", RFC 4607, DOI 10.17487/RFC4607, , <https://www.rfc-editor.org/info/rfc4607>.
[RFC5510]
Lacan, J., Roca, V., Peltotalo, J., and S. Peltotalo, "Reed-Solomon Forward Error Correction (FEC) Schemes", RFC 5510, DOI 10.17487/RFC5510, , <https://www.rfc-editor.org/info/rfc5510>.
[RFC6681]
Watson, M., Stockhammer, T., and M. Luby, "Raptor Forward Error Correction (FEC) Schemes for FECFRAME", RFC 6681, DOI 10.17487/RFC6681, , <https://www.rfc-editor.org/info/rfc6681>.
[RFC7450]
Bumgardner, G., "Automatic Multicast Tunneling", RFC 7450, DOI 10.17487/RFC7450, , <https://www.rfc-editor.org/info/rfc7450>.
[RFC8777]
Holland, J., "DNS Reverse IP Automatic Multicast Tunneling (AMT) Discovery", RFC 8777, DOI 10.17487/RFC8777, , <https://www.rfc-editor.org/info/rfc8777>.
[RFC9706]
Giuliano, L., Lenart, C., and R. Adam, "TreeDN: Tree-Based Content Delivery Network (CDN) for Live Streaming to Mass Audiences", RFC 9706, DOI 10.17487/RFC9706, , <https://www.rfc-editor.org/info/rfc9706>.

Appendix A. Example Message Flows

A.1. Catalog-Driven FEC

The subscriber learns the complete FEC configuration from the track's catalog entry before subscribing:

"fec": {
  "algorithm": "raptorq",
  "blockProfile": "iso-ssbg1-v1",
  "sourceSymbols": 32,
  "repairSymbols": 8,
  "symbolSize": 1312,
  "interleaveDepthMs": 1000,
  "reorderToleranceMs": 40,
  "repairTrack": "video/repair"
}
Publisher                                    Subscriber
    |                                          |
    |  (catalog obtained 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.

Appendix B. Catalog Example

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:

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.

Appendix C. Reed-Solomon Test Vectors

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"]
}

Appendix D. Changes Since draft-ramadan-moq-fec-00

This appendix is informative and is to be removed before publication as an RFC.

Acknowledgments

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).

Author's Address

Omar Ramadan
Blockcast