@@ -1071,6 +1071,38 @@ Type `Largest Object` followed by a Joining FETCH (see {{joining-fetches}}) for
10711071the intended start Group, which can be relative. To join a Track at the next
10721072Group, the subscriber sends a SUBSCRIBE with Filter Type `Next Group Start`.
10731073
1074+ When a subscriber is already receiving one Track and intends to join another
1075+ Track that carries equivalent content, such as a higher or lower bitrate
1076+ variant, the subscriber uses a coordinated switching procedure. The subscriber
1077+ identifies the current Track and the target Track and requests a transition at
1078+ a suitable Group boundary. This allows the subscriber to join the new Track
1079+ without gaps or duplication in the delivered object sequence.
1080+
1081+ # ### Coordinated Track Switching for Adaptive Bitrate Streaming
1082+ Client-side Adaptive bitrate (ABR) streaming requires a subscriber to
1083+ transition between two Tracks that represent alternative formats of the same
1084+ content. Only the subscriber knows which Tracks are alternatives, based on
1085+ information such as catalog metadata or an out-of-band manifest. A Relay cannot
1086+ infer the relationship between Tracks and does not know which Track represents
1087+ a higher or lower quality.
1088+
1089+ To request a switch, the subscriber sends a SWITCH (see {{message-switch}})
1090+ identifying the Track it is currently receiving and the Track it intends to
1091+ receive next. The subscriber determines both Tracks locally and
1092+ does not rely on the Relay or publisher to infer ABR intent from subscription
1093+ patterns.
1094+
1095+ When a Relay receives a SWITCH message, it SHOULD NOT forward it upstream.
1096+ Instead, the Relay SHOULD performs the transition locally, preparing the
1097+ subscription for the new Track and determining the point at which to stop
1098+ forwarding objects from the old Track and begin forwarding objects from the
1099+ new one (see {{relay-switch}}).
1100+
1101+ Using SWITCH, the subscriber triggers an atomic transition that preserves a
1102+ continuous sequence of Groups and Objects across Tracks. This avoids the
1103+ coordination difficulties that arise when attempting to combine SUBSCRIBE,
1104+ SUBSCRIBE_UPDATE, and UNSUBSCRIBE messages to perform a Track switch.
1105+
10741106# ### Dynamically Starting New Groups
10751107
10761108While some publishers will deterministically create new Groups, other
@@ -1546,6 +1578,46 @@ A relay MUST treat the object payload as opaque. A relay MUST NOT
15461578combine, split, or otherwise modify object payloads. A relay SHOULD
15471579prioritize sending Objects based on {{priorities}}.
15481580
1581+ # # Relay Processing of SWITCH {#relay-switch}
1582+
1583+ A Relay that receives SWITCH is responsible for carrying out the transition
1584+ locally and SHOULD NOT forward the SWITCH message upstream. The Relay uses
1585+ the information supplied by the subscriber to prepare the subscription for
1586+ the new Track and to determine the appropriate transition point.
1587+
1588+ Upon receiving a SWITCH message, the Relay MUST first validate that the Old
1589+ Request ID identifies an Established subscription. If no such subscription
1590+ exists, the Relay MUST send a REQUEST_ERROR for the New Request ID and MUST
1591+ NOT modify any existing subscription state.
1592+
1593+ If the New Request ID corresponds to an existing Established subscription for
1594+ the target Track, the Relay reuses that subscription. Otherwise, the Relay
1595+ creates a new subscription by issuing an upstream SUBSCRIBE using the Track
1596+ Namespace, Track Name, authorization information, and parameters provided in
1597+ the SWITCH message. The Relay performs this upstream action independently of
1598+ the subscriber.
1599+
1600+ The Relay selects a transition point, denoted G_switch, at which objects from
1601+ the old and new Tracks MUST NOT overlap. The transition point MUST occur at a
1602+ Group boundary. All objects with Group ID less than G_switch are forwarded
1603+ from the old Track, and all objects with Group ID greater than G_switch are
1604+ forwarded from the new Track. For Group ID equal to G_switch, the Relay MUST
1605+ forward objects from at most one of the two Tracks. The Relay MUST NOT
1606+ introduce gaps or deliver the same object from both Tracks.
1607+
1608+ A Relay may determine G_switch using any strategy that satisfies these
1609+ invariants. The Relay may consider its cache state, upstream latency, local
1610+ policy, and subscriber parameters when selecting a transition strategy.
1611+ Possible approaches include waiting for the end of the current Group on the
1612+ old Track and beginning the next Group on the new Track, restarting the
1613+ current Group on the new Track, or issuing FETCH requests upstream to
1614+ obtain missing objects before switching. Relays SHOULD avoid to delay the
1615+ transition point, particularly when switching to lower bitrate Tracks.
1616+
1617+ When the transition completes, the Relay MUST send an appropriate terminal
1618+ status for the Old Request ID with a PUBLISH_DONE response and an appropriate
1619+ opening status for the New Request ID with a SUBSCRIBE_OK response.
1620+
15491621# Control Messages {#message}
15501622
15511623MOQT uses a single bidirectional stream to exchange control messages, as
@@ -1605,6 +1677,8 @@ The following Message Types are defined:
16051677| 0x18 | FETCH_OK ({{message-fetch-ok}}) |
16061678|-------|-----------------------------------------------------|
16071679| 0x17 | FETCH_CANCEL ({{message-fetch-cancel}}) |
1680+ |-------|-----------------------------------------------------|
1681+ | 0x12 | SWITCH ({{message-switch}}) |
16081682|-------|-----------------------------------------------------|
16091683| 0xD | TRACK_STATUS ({{message-track-status}}) |
16101684|-------|-----------------------------------------------------|
@@ -2879,6 +2953,79 @@ FETCH_CANCEL Message {
28792953* Request ID: The Request ID of the FETCH ({{message-fetch}}) this message is
28802954 cancelling.
28812955
2956+ # # SWITCH {#message-switch}
2957+
2958+ The SWITCH message allows a subscriber to request a coordinated transition
2959+ from one Track to another Track. A SWITCH operation is an atomic transition
2960+ that avoids gaps or duplicated objects across the two Tracks. The subscriber
2961+ identifies the Track it is currently receiving and the Track it intends to
2962+ receive next, and the Relay performs the transition as described in
2963+ {{relay-switch}}.
2964+
2965+ SWITCH Message {
2966+ Type (i) = 0x12,
2967+ Length (16),
2968+
2969+ Old Request ID (i),
2970+ New Request ID (i),
2971+
2972+ Track Namespace (...),
2973+ Track Name Length (i),
2974+ Track Name (...),
2975+
2976+ Auth Info Length (i),
2977+ Auth Info (...),
2978+
2979+ Number of Parameters (i),
2980+ Parameters (...) ...,
2981+ }
2982+
2983+ The fields of the SWITCH message are as follows :
2984+
2985+ * Old Request ID:
2986+ Identifies the Established subscription that is the source of objects
2987+ before the transition. If no such subscription exists, the receiver MUST
2988+ send a REQUEST_ERROR for New Request ID and MUST NOT modify any
2989+ subscription state.
2990+
2991+ * New Request ID:
2992+ Identifies the subscription that will deliver objects after the transition.
2993+ This Request ID MUST either refer to an existing Established subscription
2994+ for the target Track or be unused, in which case the receiver creates a
2995+ new subscription for the Track.
2996+
2997+ * Track Namespace and Track Name:
2998+ Identify the target Track and are encoded as in SUBSCRIBE. These fields
2999+ determine the Track that will be used after the transition.
3000+
3001+ * Auth Info Length and Auth Info:
3002+ Optional authorization information for the target Track. If Auth Info
3003+ Length is zero, the receiver MAY reuse any authorization information
3004+ associated with Old Request ID.
3005+
3006+ * Parameters:
3007+ Version-specific subscription parameters encoded as in SUBSCRIBE. Any
3008+ parameter omitted in SWITCH MUST cause the receiver to reuse the
3009+ corresponding parameter value from the subscription associated with Old
3010+ Request ID.
3011+
3012+ Upon receiving SWITCH, the receiver prepares the subscription associated with
3013+ New Request ID and performs the Track transition at a suitable Group
3014+ boundary (see {{relay-switch}}).
3015+
3016+ If the SWITCH request is accepted and the subscription for New Request ID
3017+ becomes ready to deliver objects, the receiver MUST send SUBSCRIBE_OK for
3018+ New Request ID. After the transition completes, the receiver MUST send a
3019+ terminal status for Old Request ID using a PUBLISH_DONE response.
3020+
3021+ If the SWITCH request cannot be honored, the receiver MUST send a
3022+ REQUEST_ERROR for New Request ID and MUST NOT alter the behavior of the
3023+ subscription associated with Old Request ID.
3024+
3025+ A Relay that receives SWITCH performs the transition locally and SHOULD
3026+ NOT forward the SWITCH message upstream.
3027+
3028+
28823029# # TRACK_STATUS {#message-track-status}
28833030
28843031A potential subscriber sends a `TRACK_STATUS` message on the control
0 commit comments