<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE rfc [
  <!ENTITY nbsp    "&#160;">
  <!ENTITY zwsp   "&#8203;">
  <!ENTITY nbhy   "&#8209;">
  <!ENTITY wj     "&#8288;">
]>
<?xml-stylesheet type="text/xsl" href="rfc2629.xslt" ?>
<!-- generated by https://github.com/cabo/kramdown-rfc version 1.7.11 (Ruby 2.6.10) -->
<rfc xmlns:xi="http://www.w3.org/2001/XInclude" ipr="trust200902" docName="draft-lcurley-moq-transfork-01" category="info" submissionType="IETF" tocInclude="true" sortRefs="true" symRefs="true" version="3">
  <!-- xml2rfc v2v3 conversion 3.21.0 -->
  <front>
    <title abbrev="moqtf">Media over QUIC - Transfork</title>
    <seriesInfo name="Internet-Draft" value="draft-lcurley-moq-transfork-01"/>
    <author fullname="Luke Curley">
      <organization>Discord</organization>
      <address>
        <email>kixelated@gmail.com</email>
      </address>
    </author>
    <date year="2024" month="September" day="23"/>
    <area>wit</area>
    <workgroup>moq</workgroup>
    <abstract>
      <?line 25?>

<t>MoqTransfork is designed to serve a broadcast to an unbounded number of viewers with different latency and quality targets: the entire spectrum between real-time and VOD.
MoqTransfork itself is a media agnostic transport, allowing relays and CDNs to forward the most important content under degraded networks without knowledge of codecs, containers, or even if the content is fully encrypted.
Higher level protocols specify how to use MoqTransfork to encode and deliver video, audio, messages, or any form of live content.</t>
    </abstract>
    <note removeInRFC="true">
      <name>Discussion Venues</name>
      <t>Discussion of this document takes place on the
    Media Over QUIC Working Group mailing list (moq@ietf.org),
    which is archived at <eref target="https://mailarchive.ietf.org/arch/browse/moq/"/>.</t>
      <t>Source for this draft and an issue tracker can be found at
    <eref target="https://github.com/kixelated/moq-transfork"/>.</t>
    </note>
  </front>
  <middle>
    <?line 31?>

<section anchor="conventions-and-definitions">
      <name>Conventions and Definitions</name>
      <t>The key words "<bcp14>MUST</bcp14>", "<bcp14>MUST NOT</bcp14>", "<bcp14>REQUIRED</bcp14>", "<bcp14>SHALL</bcp14>", "<bcp14>SHALL
NOT</bcp14>", "<bcp14>SHOULD</bcp14>", "<bcp14>SHOULD NOT</bcp14>", "<bcp14>RECOMMENDED</bcp14>", "<bcp14>NOT RECOMMENDED</bcp14>",
"<bcp14>MAY</bcp14>", and "<bcp14>OPTIONAL</bcp14>" in this document are to be interpreted as
described in BCP 14 <xref target="RFC2119"/> <xref target="RFC8174"/> when, and only when, they
appear in all capitals, as shown here.</t>
      <?line -18?>

</section>
    <section anchor="fork">
      <name>Fork</name>
      <t>This draft is based on moq-transport-03 <xref target="moqt"/>.
The concepts, motivations, and terminology are very similar on purpose.
When in doubt, refer to the upstream draft.</t>
      <t>I absolutely believe in the motivation and potential of Media over QUIC.
The layering is phenomenal and addresses many of the problems with current live media protocols.
I fully support the goals of the working group and the IETF process.</t>
      <t>But there are practical and conceptual flaws with MoqTransport that need to be addressed.
However it's been difficult to design such an experimental protocol via committee.
Despite years of arguments in person and on GitHub, we've yet to align on even the most critical property of the transport... how to utilize QUIC.
The result is inevitably an unwieldy "compromise", consisting of a modes for each party that make everything more difficult to support or explain.</t>
      <t>In our RUSH to standardize a protocol, the QUICR solutions have led to WARP in ideals.</t>
      <t>This fork is meant to be a constructive, alternative vision.
I would like to lead by example, demonstrating that you can support real media use-cases while simplifying the protocol.
The working group will keep making progress and hopefully many of these ideas will be incorporated.</t>
      <t>The appendix contains a list of high level differences between MoqTransport and MoqTransfork.</t>
    </section>
    <section anchor="concepts">
      <name>Concepts</name>
      <t>MoqTransfork consists of:</t>
      <ul spacing="normal">
        <li>
          <t><strong>Session</strong>: An established connection between a client and server used to transmit any number of Broadcasts.</t>
        </li>
        <li>
          <t><strong>Broadcast</strong>: A collection of Tracks from a single producer (client). This is primarily used for routing, but Tracks within a Broadcast may be correlated.</t>
        </li>
        <li>
          <t><strong>Track</strong>: An append-only series of Groups, each of which can be delivered and decoded independently.</t>
        </li>
        <li>
          <t><strong>Group</strong>: An append-only series of Frames, each of which are delivered and decoded in order</t>
        </li>
        <li>
          <t><strong>Frame</strong>: A sized payload of bytes, intended to represent a single moment in time.</t>
        </li>
      </ul>
      <t>The application determines how to split data into broadcasts, tracks, groups, and frames.
MoqTransfork only is responsible for the networking and deduplication by utilizing rules encoded in headers.
This provides robust and generic one-to-many transmission, even for latency sensitive applications.</t>
      <section anchor="session">
        <name>Session</name>
        <t>A Session consists of a connection between a QUIC client and server.</t>
        <t>A session is established after the necessary QUIC, WebTransport, and MoqTransfork handshakes.
The MoqTransfork handshake consists of version information and an optional ROLE extension, signaling if the endpoint supports only supports publishing or subscribing.</t>
        <t>The intent is that sessions are chained together via relays.
A broadcaster could establish a session with an CDN ingest edge while the viewers establish separate sessions to CDN distribution edges.
A MoqTransfork session is hop-by-hop, but the application should be designed end-to-end.</t>
      </section>
      <section anchor="broadcast">
        <name>Broadcast</name>
        <t>A Broadcast is a collection of tracks from a single producer, identified by a unique name within the session.
A MoqTransfork session may be used to publish and subscribe to multiple, potentially unrelated, broadcasts.</t>
        <t>The application determines if tracks within a broadcast are correlated.
For example, a "video" track and "audio" track could share timestamp domains.
This is possible as a broadcast is created by a single publisher, avoiding the need for clock synchronization.</t>
        <t>A publisher can advertise available broadcasts via an ANNOUNCE message.
This allows a subscriber to dynamically discover available broadcasts.
Alternatively, the application can discover broadcasts via an out-of-band mechanism.</t>
      </section>
      <section anchor="track">
        <name>Track</name>
        <t>A Track is a series of Groups within a Broadcast, identified by a unique name within the Broadcast.</t>
        <t>Each subscription is scoped to a single Track.
A subscription will always start at a Group boundary, either the latest group or a specified sequence number.
A subscriber chooses the ordering and priority of each subscription, hinting to the publisher which Track should arrive first during congestion.
This is critical for a decent user experience during network degradation and the core reason why QUIC can offer real-time latency.</t>
        <t>There is currently no way to discover tracks within a broadcast; it must be negotiated out-of-band.
This is often done with a named "catalog" track that lists all available tracks and their properties.
An application may choose to use static and/or dynamic track names.</t>
      </section>
      <section anchor="group">
        <name>Group</name>
        <t>A Group is an ordered stream of Frames within a Track.</t>
        <t>A group is served by a dedicated QUIC stream which may be closed on completion, reset by the publisher, or cancelled by the subscriber.
An active subscription involves delivering multiple potential concurrent groups.
The Frames within a Group will arrive reliably and in order thanks to the QUIC stream.
However, Groups within a Track can arrive in any order or not at all, and which the application should be prepared to handle.</t>
        <t>A subscriber may FETCH a specific group starting at a given byte offset.
This is similar to a HTTP request and may be used to recover from partial failures among other things.</t>
      </section>
      <section anchor="frame">
        <name>Frame</name>
        <t>A Frame is a payload of bytes within a Group.</t>
        <t>A frame is used to represent a chunk of data with a known size.
A frame should represent a single moment in time and avoid any buffering that would increase latency.</t>
      </section>
      <section anchor="liveliness">
        <name>Liveliness</name>
        <t>A media protocol can only be considered "live" if it can handle degraded network congestion.
MoqTransfork handles this by prioritizing the most important media while the remainder is starved.</t>
        <t>The importance of each broadcast/track/group/frame is signaled by the subscriber and the publisher will attempt to obey it.
This is done via the Track Priority and the Group Order.
Any data that is excessively starved may be dropped (by either endpoint) rather than block the live stream.</t>
        <t>A publisher that serves multiple sessions, commonly a relay, should prioritize on a per-session basis.
Alice may want real-time latency with a preference for audio, while Bob may want reliable playback while audio is muted.
A relay <bcp14>MAY</bcp14> forward subscriber preferences upstream, but when there is a conflict (like the above example), the publisher's preference should be used as a tiebreaker.</t>
      </section>
    </section>
    <section anchor="workflow">
      <name>Workflow</name>
      <t>This section outlines the flow of messages within a MoqTransfork session.
See the section for Messages section for the specific encoding.</t>
      <section anchor="connection">
        <name>Connection</name>
        <t>MoqTransfork runs on top of WebTransport.
WebTransport is a layer on top of QUIC and HTTP/3, required for web support.
The API is nearly identical to QUIC, however notably lacks stream IDs and has fewer available error codes.</t>
        <t>How the WebTransport connection is established is out-of-scope for this draft.
For example, a service <bcp14>MAY</bcp14> use the WebTransport handshake to perform authentication via the URL.</t>
      </section>
      <section anchor="termination">
        <name>Termination</name>
        <t>QUIC bidirectional streams have an independent send and receive direction.
Rather than deal with half-open states, MoqTransfork combines both sides.
If an endpoint closes the send direction of a stream, the peer <bcp14>MUST</bcp14> also close the send direction.</t>
        <t>MoqTransfork contains many long-lived transactions, such as subscriptions and announcements.
These are terminated when the underlying QUIC stream is terminated.</t>
        <t>To terminate a stream, an endpoint may:
- close the send direction (STREAM with FIN) to gracefully terminate (all messages are flushed).
- reset the send direction (RESET_STREAM) to immediately terminate.</t>
        <t>After resetting the send direction, an endpoint <bcp14>MAY</bcp14> close the recv direction (STOP_SENDING).
However, it is ultimately the other peer's responsibility to close their send direction.</t>
      </section>
      <section anchor="handshake">
        <name>Handshake</name>
        <t>After a connection is established, the client opens a Session Stream and sends a SESSION_CLIENT message, to which the server replies with a SESSION_SERVER message.
The session is active until either endpoint closes or resets the Session Stream.</t>
        <t>This session handshake is used to negotiate the MoqTransfork version and any extensions.
See the Extension section for more information.</t>
      </section>
      <section anchor="bidirectional-streams">
        <name>Bidirectional Streams</name>
        <t>Bidirectional streams are primarily used for control streams.</t>
        <t>The first byte of each stream indicates the Stream Type.
A Stream Type is created by an endpoint with the associated Role and <bcp14>MUST</bcp14> be enforced when the ROLE extension is negotiated.</t>
        <table>
          <thead>
            <tr>
              <th align="right">ID</th>
              <th align="left">Type</th>
              <th align="left">Role</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td align="right">0x0</td>
              <td align="left">Session</td>
              <td align="left">Client</td>
            </tr>
            <tr>
              <td align="right">0x1</td>
              <td align="left">Announce</td>
              <td align="left">Publisher</td>
            </tr>
            <tr>
              <td align="right">0x2</td>
              <td align="left">Subscribe</td>
              <td align="left">Subscriber</td>
            </tr>
            <tr>
              <td align="right">0x3</td>
              <td align="left">Fetch</td>
              <td align="left">Subscriber</td>
            </tr>
            <tr>
              <td align="right">0x4</td>
              <td align="left">Info</td>
              <td align="left">Subscriber</td>
            </tr>
          </tbody>
        </table>
        <section anchor="session-1">
          <name>Session</name>
          <t>The Session stream contains all messages that are session level.</t>
          <t>The client <bcp14>MUST</bcp14> open a single Session Stream immediately after establishing the QUIC/WebTransport session.
The client sends a SESSION_CLIENT message and the server replies with a SESSION_SERVER message.</t>
          <t>Afterwards, both endpoints <bcp14>SHOULD</bcp14> send SESSION_UPDATE messages, such as after a significant change in the session bitrate.</t>
          <t>The session remains active until the Session Stream is closed or reset by either endpoint.</t>
        </section>
        <section anchor="announce">
          <name>Announce</name>
          <t>A publisher can open an Announce Stream to advertise a broadcast.
This is <bcp14>OPTIONAL</bcp14> and the application can determine the broadcast name out-of-band.</t>
          <t>The publisher <bcp14>MUST</bcp14> start the stream with an ANNOUNCE message.
The subscriber <bcp14>MUST</bcp14> reply with an ANNOUNCE_OK message or reset the stream.
The announcement is active until the stream is closed or reset by either endpoint.</t>
          <t>There is currently no expectation that a relay will forward an ANNOUNCE message downstream.
A future draft may introduce a mechanism to discover broadcasts matching a prefix.</t>
        </section>
        <section anchor="subscribe">
          <name>Subscribe</name>
          <t>A subscriber can open a Subscribe Stream to request a named track within a broadcast.</t>
          <t>The subscriber <bcp14>MUST</bcp14> start a Info Stream with a SUBSCRIBE message followed by any number SUBSCRIBE_UPDATE messages.
The publisher <bcp14>MUST</bcp14> reply with an INFO message followed by any number of GROUP_DROPPED messages.
A publisher <bcp14>MAY</bcp14> reset the stream at any point if it is unable to serve the subscription.</t>
          <t>The publisher <bcp14>MUST</bcp14> transmit a complete Group Stream or a GROUP_DROPPED message for each Group within the subscription range.
This means the publisher <bcp14>MUST</bcp14> transmit a GROUP_DROPPED if a Group Stream is reset.
The subscriber <bcp14>SHOULD</bcp14> close the subscription when all GROUP and GROUP_DROP messages have been received, and the publisher <bcp14>MAY</bcp14> close the subscription after all messages have been acknowledged.</t>
        </section>
        <section anchor="fetch">
          <name>Fetch</name>
          <t>A subscriber can open a Fetch Stream to receive a single Group at a specified offset.
This is primarily used to recover from an abrupt stream termination, causing the truncation of a Group.</t>
          <t>The subscriber <bcp14>MUST</bcp14> start a Fetch Stream with a FETCH message followed by any number of FETCH_UPDATE messages.
The publisher <bcp14>MUST</bcp14> reply with the contents of a Group Stream, except starting at the specified offset <em>after</em> the GROUP message.
Note that this includes any FRAME messages.</t>
          <t>The fetch is active until both endpoints close the stream, or either endpoint resets the stream.</t>
        </section>
        <section anchor="info">
          <name>Info</name>
          <t>A subscriber can open an Info Stream to request information about a track.
This is not often necessary as SUBSCRIBE will trigger an INFO reply.</t>
          <t>The subscriber <bcp14>MUST</bcp14> start the stream with a INFO_REQUEST message.
The publisher <bcp14>MUST</bcp14> reply with an INFO message or reset the stream.
Both endpoints <bcp14>MUST</bcp14> close the stream afterwards.</t>
        </section>
      </section>
      <section anchor="unidirectional">
        <name>Unidirectional</name>
        <t>Unidirectional streams are used for subscription data.</t>
        <table>
          <thead>
            <tr>
              <th align="right">ID</th>
              <th align="left">Stream</th>
              <th align="left">Role</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td align="right">0x0</td>
              <td align="left">Group</td>
              <td align="left">Publisher</td>
            </tr>
          </tbody>
        </table>
        <section anchor="group-1">
          <name>Group</name>
          <t>A publisher creates Group Streams in response to a Subscribe Stream.</t>
          <t>A Group Stream <bcp14>MUST</bcp14> start with a GROUP message and <bcp14>MAY</bcp14> be followed by any number of FRAME messages.
An application <bcp14>MAY</bcp14> use an empty GROUP and/or FRAME to signal gaps.</t>
          <t>Both the publisher and subscriber <bcp14>MAY</bcp14> reset the stream at any time.
When a Group stream is reset, the publisher <bcp14>MUST</bcp14> send a GROUP_DROP message on the corresponding Subscribe stream.
A future version of this draft may utilize reliable reset instead.</t>
        </section>
      </section>
    </section>
    <section anchor="encoding">
      <name>Encoding</name>
      <t>This section covers the encoding of each message.</t>
      <t>Note that these message do not contain a type identifier.
The message type is determined by the stream type and the current state.</t>
      <section anchor="sessionclient">
        <name>SESSION_CLIENT</name>
        <t>The client advertises supported versions and any extensions.</t>
        <artwork><![CDATA[
SESSION_CLIENT Message {
  Supported Versions Count (i)
  Supported Version (i)
  Extension Count (i)
  [
    Extension ID (i)
    Extension Payload (b)
  ]...
}
]]></artwork>
      </section>
      <section anchor="sessionserver">
        <name>SESSION_SERVER</name>
        <t>The server responds with the selected version and any extensions.</t>
        <artwork><![CDATA[
SESSION_SERVER Message {
  Selected Version (i)
  Extension Count (i)
  [
    Extension ID (i)
    Extension Payload (b)
  ]...
}
]]></artwork>
      </section>
      <section anchor="sessionupdate">
        <name>SESSION_UPDATE</name>
        <artwork><![CDATA[
SESSION_UPDATE Message {
  Session Bitrate (i)
}
]]></artwork>
        <t><strong>Session Bitrate</strong>:
The estimated bitrate of the QUIC connection in bits per second.
This <bcp14>SHOULD</bcp14> be sourced directly from the QUIC congestion controller.
A value of 0 indicates that this information is not available.</t>
      </section>
      <section anchor="announce-1">
        <name>ANNOUNCE</name>
        <t>A publisher sends an ANNOUNCE message to advertise a broadcast.</t>
        <artwork><![CDATA[
ANNOUNCE Message {
  Broadcast Name (b),
}
]]></artwork>
        <t><strong>Broadcast Name</strong>:
The name of the broadcast.
A zero-sized name is valid but not recommended.</t>
      </section>
      <section anchor="announceok">
        <name>ANNOUNCE_OK</name>
        <t>A subscriber replies to an ANNOUNCE with an ANNOUNCE_OK message.</t>
        <artwork><![CDATA[
ANNOUNCE_OK Message {
  Cool = 0x1
}
]]></artwork>
        <t>This message is a single byte long (😎).</t>
      </section>
      <section anchor="subscribe-1">
        <name>SUBSCRIBE</name>
        <t>SUBSCRIBE is sent by a subscriber to start a subscription.</t>
        <artwork><![CDATA[
SUBSCRIBE Message {
  Subscribe ID (i)
  Broadcast Name (b)
  Track Name (b)
  Track Priority (i)
  Group Order (i)
  Group Expires (i)
  Group Min (i)
  Group Max (i)
}
]]></artwork>
        <t><strong>Subscribe ID</strong>:
A unique idenfier chosen by the subscriber.
A Subscribe ID <bcp14>MUST NOT</bcp14> be reused within the same session, even if the prior subscription has been closed.</t>
        <t><strong>Broadcast Name</strong>:
The name of the broadcast.
A zero-sized name is valid but not recommended.</t>
        <t><strong>Track Name</strong>:
The name of the track.
A zero-sized name is valid but not recommended.</t>
        <t><strong>Track Priority</strong>:
The transmission priority of the subscription relative to all other active subscriptions within the session.
The publisher <bcp14>SHOULD</bcp14> transmit <em>higher</em> values first during congestion.</t>
        <t><strong>Group Order</strong>:
The transmission order of the Groups within the subscription.
The publisher <bcp14>SHOULD</bcp14> transmit groups based on their sequence number in default (0), ascending (1), or descending (2) order.</t>
        <t><strong>Group Expires</strong>:
A duration in milliseconds that applies to all Groups within the subscription.
The group <bcp14>SHOULD</bcp14> be dropped if this duration has elapsed after group has finished, including any time spent cached.
The publisher's Group Expires value (via INFO) <bcp14>SHOULD</bcp14> be used instead when smaller.</t>
        <t><strong>Group Min</strong>:
The minimum group sequence number plus 1.
A value of 0 indicates the latest Group Sequence as determined by the publisher.</t>
        <t><strong>Group Max</strong>:
The maximum group sequence number plus 1.
A value of 0 indicates there is no maximum and the subscription continues indefinitely.</t>
      </section>
      <section anchor="subscribeupdate">
        <name>SUBSCRIBE_UPDATE</name>
        <t>A subscriber can modify a subscription with a SUBSCRIBE_UPDATE message.</t>
        <artwork><![CDATA[
SUBSCRIBE_UPDATE Message {
  Track Priority (i)
  Group Order (i)
  Group Expires (i)
  Group Min (i)
  Group Max (i)
}
]]></artwork>
        <t><strong>Track Priority</strong>:
The new track priority; see SUBSCRIBE.
The publisher <bcp14>SHOULD</bcp14> use the new priority for any blocked streams.</t>
        <t><strong>Group Order</strong>:
The new group order; see SUBSCRIBE.
The publisher <bcp14>SHOULD</bcp14> use the new order for any blocked streams.</t>
        <t><strong>Group Min</strong>:
The new minimum group sequence, or 0 if there is no update.
This value <bcp14>MUST NOT</bcp14> be smaller than prior SUBSCRIBE and SUBSCRIBE_UPDATE messages.</t>
        <t><strong>Group Max</strong>:
The new maximum group sequence, or 0 if there is no update.
This value <bcp14>MUST NOT</bcp14> be larger than prior SUBSCRIBE or SUBSCRIBE_UPDATE messages.</t>
        <t>If the Min and Max are updated, the publisher <bcp14>SHOULD</bcp14> reset any blocked streams that are outside the new range.</t>
      </section>
      <section anchor="info-1">
        <name>INFO</name>
        <t>The INFO message contains the current information about a track.</t>
        <artwork><![CDATA[
INFO Message {
  Track Priority (i)
  Group Latest (i)
  Group Order (i)
  Group Expires (i)
}
]]></artwork>
        <t><strong>Track Priority</strong>:
The priority of this track within the <em>broadcast</em>.
Note that this is slightly different than SUBSCRIBE, which is scoped to a session not broadcast.
The publisher <bcp14>SHOULD</bcp14> transmit subscriptions with <em>higher</em> values first during congestion.</t>
        <t><strong>Group Latest</strong>:
The latest group as currently known by the publisher.
A relay without an active subscription <bcp14>SHOULD</bcp14> forward this request upstream</t>
        <t><strong>Group Order</strong>:
The publisher's intended order of the groups within the subscription: none (0), ascending (1), or descending (2).</t>
        <t><strong>Group Expires</strong>:
A duration in milliseconds.
The group <bcp14>SHOULD</bcp14> be dropped if this duration has elapsed after group has finished, including any time spent cached.
The Subscriber's Group Expires value <bcp14>SHOULD</bcp14> be used instead when smaller.</t>
      </section>
      <section anchor="inforequest">
        <name>INFO_REQUEST</name>
        <t>The INFO_REQUEST message is used to request an INFO response.</t>
        <artwork><![CDATA[
INFO_REQUEST Message {
  Broadcast Name (b)
  Track Name (b)
}
]]></artwork>
      </section>
      <section anchor="fetch-1">
        <name>FETCH</name>
        <t>A subscriber can request a byte offset within a Group with a FETCH message.</t>
        <artwork><![CDATA[
FETCH Message {
  Broadcast Name (b)
  Track Name (b)
  Track Priority (i)
  Group Sequence (i)
  Group Offset (i)
}
]]></artwork>
        <t><strong>Track Priority</strong>:
The priority of the group relative to all other FETCH and SUBSCRIBE requests within the session.
The publisher should transmit <em>higher</em> values first during congestion.</t>
        <t><strong>Group Offset</strong>:
The requested offset in bytes <em>after</em> the GROUP message.</t>
      </section>
      <section anchor="fetchupdate">
        <name>FETCH_UPDATE</name>
        <t>A subscriber can modify a FETCH request with a FETCH_UPDATE message.</t>
        <artwork><![CDATA[
FETCH_UPDATE Message {
  Track Priority (i)
}
]]></artwork>
        <t><strong>Track Priority</strong>:
The priority of the group relative to all other FETCH and SUBSCRIBE requests within the session.
The publisher should transmit <em>higher</em> values first during congestion.</t>
      </section>
      <section anchor="group-2">
        <name>GROUP</name>
        <t>The GROUP message contains information about a Group, as well as a reference to the subscription being served.</t>
        <artwork><![CDATA[
GROUP Message {
  Subscribe ID (i)
  Group Sequence (i)
}
]]></artwork>
        <t><strong>Subscribe ID</strong>:
The corresponding Subscribe ID.
This ID is used to distinguish between multiple subscriptions for the same track.</t>
        <t><strong>Group Sequence</strong>:
The sequence number of the group.</t>
      </section>
      <section anchor="groupdrop">
        <name>GROUP_DROP</name>
        <t>A publisher transmits a GROUP_DROP message when it is unable to serve a group for a SUBSCRIBE.</t>
        <artwork><![CDATA[
GROUP_DROP {
  Group Start (i)
  Group Count (i)
  Group Error Code (i)
}
]]></artwork>
        <t><strong>Group Start</strong>:
The sequence number for the first group within the dropped range.</t>
        <t><strong>Group Count</strong>:
The number of additional groups after the first.
This value is 0 when only one group is dropped.</t>
        <t><strong>Error Code</strong>:
An error code indicated by the application.</t>
      </section>
      <section anchor="frame-1">
        <name>FRAME</name>
        <t>The FRAME message consists of a length followed by that many bytes.</t>
        <artwork><![CDATA[
FRAME Message {
  Payload (b)
}
]]></artwork>
        <t><strong>Payload</strong>:
An application specific payload.
A generic library or relay <bcp14>MUST NOT</bcp14> inspect or modify the contents unless otherwise negotiated.</t>
      </section>
    </section>
    <section anchor="extensions">
      <name>Extensions</name>
      <t>SESSION_CLIENT and SESSION_SERVER have a flexible encoding to facilitate extension negotiation without causing breaking changes.</t>
      <t>This draft registers some extensions and reserves any IDs smaller than 64 for future drafts.
Other documents <bcp14>MAY</bcp14> introduce additional extensions.</t>
      <table>
        <thead>
          <tr>
            <th align="right">ID</th>
            <th align="left">Extension</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td align="right">0x0</td>
            <td align="left">Role</td>
          </tr>
        </tbody>
      </table>
      <section anchor="role">
        <name>Role</name>
        <t>The Role Extension indicates the desired role for the endpoint.
This is useful for indicating intent, such as a client indicating that it will not publish any tracks.</t>
        <t>The Role payload is a single varint indicating the functionality of the sender:</t>
        <table>
          <thead>
            <tr>
              <th align="right">ID</th>
              <th align="left">Role</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td align="right">0x0</td>
              <td align="left">Publisher</td>
            </tr>
            <tr>
              <td align="right">0x1</td>
              <td align="left">Subscriber</td>
            </tr>
            <tr>
              <td align="right">0x2</td>
              <td align="left">Both</td>
            </tr>
            <tr>
              <td align="right">0x3</td>
              <td align="left">Any</td>
            </tr>
          </tbody>
        </table>
        <t>If the extension is not present, the default value is Both.
An endpoint <bcp14>MAY</bcp14> close the session with a RequiredExtension error (TODO) if the extension is missing and this default role is incompatible.</t>
      </section>
    </section>
    <section anchor="appendix-changelog">
      <name>Appendix: Changelog</name>
      <t>Notable changes between versions of this draft.</t>
      <section anchor="moq-transfork-01">
        <name>moq-transfork-01</name>
        <ul spacing="normal">
          <li>
            <t>Removed datagram support</t>
          </li>
          <li>
            <t>Removed native QUIC support</t>
          </li>
          <li>
            <t>Moved Expires from GROUP to SUBSCRIBE</t>
          </li>
          <li>
            <t>Added FETCH_UPDATE</t>
          </li>
          <li>
            <t>Added ROLE=Any</t>
          </li>
          <li>
            <t>Track Priority is now descending.</t>
          </li>
        </ul>
        <t>Datagram and native QUIC support may be re-added in a future draft.</t>
      </section>
      <section anchor="moq-transfork-00">
        <name>moq-transfork-00</name>
        <t>Based on moq-transport-03.
The significant changes have been broken into sections.</t>
        <section anchor="bikeshedding">
          <name>Bikeshedding</name>
          <ul spacing="normal">
            <li>
              <t>Renamed Track Namespace to Broadcast</t>
            </li>
            <li>
              <t>Renamed Object to Frame</t>
            </li>
          </ul>
        </section>
        <section anchor="stream-per-group">
          <name>Stream per Group</name>
          <t>The MoQ WG couldn't agree on how to utilize QUIC streams, so the compromise was to support multiple modes and let the application choose.
This is a headache for too many reasons to list.
MoqTransfork only "supports" a stream per group.</t>
        </section>
        <section anchor="subscribers-choice">
          <name>Subscriber's Choice</name>
          <t>MoqTransfork moves most decision making to the subscriber, so a single publisher can support multiple diverse subscribers.
The publisher provides a default value to resolve conflicts when deduplicating.</t>
        </section>
        <section anchor="control-streams">
          <name>Control Streams</name>
          <t>Transactions like Announce and Subscribe use their own control stream, inheriting the stream state machine for error handling.</t>
          <t>This replaces excessive message types in MoqTransport:
- Removed ANNOUNCE_ERROR
- Removed ANNOUNCE_DONE
- Removed UNANNOUNCE
- Removed SUBSCRIBE_OK
- Removed SUBSCRIBE_ERROR
- Removed SUBSCRIBE_DONE
- Removed UNSUBSCRIBE</t>
        </section>
        <section anchor="unambiguous-delivery">
          <name>Unambiguous Delivery</name>
          <t>With MoqTransfork, the subscriber knows if a group/frame will be delivered or was dropped.</t>
          <ul spacing="normal">
            <li>
              <t>Group Sequences are sequential</t>
            </li>
            <li>
              <t>All sequences within the SUBSCRIBE range are delivered or dropped.</t>
            </li>
            <li>
              <t>GROUP_DROP when a group is dropped.</t>
            </li>
          </ul>
        </section>
        <section anchor="fetch-via-offset">
          <name>Fetch via Offset</name>
          <t>A reconnecting subscriber can request the retransmission of a group/stream at a given byte offset.
Resumption in MoqTransport is more complicated and can only occur at object/group boundaries.</t>
        </section>
        <section anchor="track-info">
          <name>Track INFO</name>
          <t>Added a mechanism to request information about the current track state.</t>
          <ul spacing="normal">
            <li>
              <t>Added INFO_REQUEST and INFO</t>
            </li>
            <li>
              <t>Replaced SUBSCRIBE_OK with INFO</t>
            </li>
          </ul>
        </section>
      </section>
    </section>
    <section anchor="appendix-media-use-cases">
      <name>Appendix: Media Use-Cases</name>
      <t>These are some recommended ways to use MoqTransfork for media delivery.</t>
      <section anchor="video">
        <name>Video</name>
        <t>Video encoding involves complex dependencies between frames/slices.
The terminology in this section stems from H.264 but is applicable to most modern codecs.</t>
        <t>Each frame of video is encoded as one or more slices but to simplify the discussion, we'll refer to a slice as a frame.
There are three types of frames:</t>
        <ul spacing="normal">
          <li>
            <t><strong>I-Frame</strong>: A frame that can be decoded independently.</t>
          </li>
          <li>
            <t><strong>P-Frame</strong>: A frame that depends on previous frames.</t>
          </li>
          <li>
            <t><strong>B-Frame</strong>: A frame that depends on previous or future frames.</t>
          </li>
        </ul>
        <section anchor="group-of-pictures">
          <name>Group of Pictures</name>
          <t>A simple application can ignore the complexity of P/B frames and focus on I-Frames.
This is the optimal approach for many encoding configurations.</t>
          <t>Each I-Frame begins a Group of Pictures (GoP).
A GoP is a set of frames that <bcp14>MAY</bcp14> depend on each other and <bcp14>MUST NOT</bcp14> depend on other GoPs.
Each frame has a decode order (DTS) and a frame <bcp14>MUST NOT</bcp14> depend on frames with a higher DTS.</t>
          <t>This perfectly maps to a QUIC stream, as they too are independent and ordered.
The easiest way to use MoqTransfork is to send each GoP as a GROUP with each frame as a FRAME, hence the names.</t>
          <t>Each SUBSCRIBE starts at a Group to ensure that it starts with an I-Frame.
Each Group is delivered in decode order ensuring that all frames are decodable (no artifacts).</t>
          <t>A subscriber can choose the Group Order based on the desired user experience:</t>
          <ul spacing="normal">
            <li>
              <t><tt>SUBSCRIBE order=DESC</tt>: Transmits new Groups first to allow skipping, intended for low-latency live streams.</t>
            </li>
            <li>
              <t><tt>SUBSCRIBE order=ASC</tt>: Transmits old Groups first to avoid skipping, intended for VOD and reliable live streams.</t>
            </li>
          </ul>
          <t>A publisher or subscriber can skip the remainder of a Group by resetting a Group Stream or by issuing a SUBSCRIBE_UPDATE.
A FETCH can be used to recover any partial groups.</t>
        </section>
        <section anchor="layers">
          <name>Layers</name>
          <t>An advanced application can subdivide a GoP into layers.</t>
          <t>The most comprehensive way to do this is with Scalable Video Coding (SVC).
There is a base layer and one or more enhancement layers that depend on lower layers.
For example, a 4K stream could be broken into 4K, 1080p, and 360p (base) layers.
However, SVC has limited support and is complex to encode.</t>
          <t>Another approach is to use temporal scalability via something like B-pyramids.
The frames within a GoP are sub-divided based on their dependencies, intentionally creating a hierarchy.
For example, even frames could be prevented from referencing odd frames, creating a base 30fps layer and an enhancement 60fps layer.
This is effectively a custom SVC scheme however it's limited to time and doesn't require special decoder support.</t>
          <t>The purpose of these layers is to support degrading the quality of the broadcast.
A subscriber could limit bandwidth usage by choose to only receive the base layer or a subset of the enhancements layers.
During congestion, the base layer can be prioritized while the enhancement layers can be deprioritized or dropped.
However, the cost is a small increase in bitrate (10%) as limiting potential references can only hurt the compression ratio.</t>
          <t>When using MoqTransfork, each layer is delivered as a separate Track.
This allows the subscriber to choose which layers to receive and how to prioritize them in SUBSCRIBE.
It also enables layers to be prioritized within the layer application, for example Alice's base layer is more important than Bob's enhancement layer.</t>
          <t>The application is responsible for determining the relationship between layers, since they're unrelated tracks as MoqTransport is concerned.
The application could use a catalog to advertise the layers and how to synchronize them, for example based on the Group Sequence.</t>
        </section>
        <section anchor="non-reference-frames">
          <name>Non-Reference Frames</name>
          <t>While not explicitly stated, I believe the complexity in MoqTransport stems almost entirely from a single use-case: the ability to drop individual non-reference frames in the middle of a group.</t>
          <t>In theory, transmitting enhancement layers as tracks like mentioned above could introduce head-of-line blocking depending on the encoding.
This would occur when enhancement layers are not self-referential, a rare configuration which also hurts the compression ratio.
And in practice, there's no discernable user impact given the disproportionate size difference between base and enhancement layers.</t>
          <t>The ability to drop individual non-reference frames in the middle of a group is an explicit non-goal for MoqTransfork.</t>
        </section>
      </section>
      <section anchor="audio">
        <name>Audio</name>
        <t>Unlike video, audio is simple and yet has perhaps more potential for optimization.</t>
        <section anchor="frames">
          <name>Frames</name>
          <t>Audio samples are very small and for the sake of compression, are grouped into a frame.
This depends on the codec and the sample rate but each frame is typically 10-50ms of audio.</t>
          <t>Audio frames are independent, which means they map nicely to MoqTransfork Groups.
Each audio frame can be transmitted as a GROUP with a single FRAME.</t>
        </section>
        <section anchor="groups">
          <name>Groups</name>
          <t>Audio FRAMEs can also be combined into periodic GROUPs to reduce overhead at the cost of some introducing head-of-line blocking.
This won't increase latency except under significant congestion as each FRAME is still streamed.</t>
          <t>For example, an application could then subscribe to video and audio starting at group X for both tracks, instead of trying to maintain a mapping between the two based on timestamp.
This is quite common in HLS/DASH as there's no reason to subdivide audio segments at frame boundaries.</t>
        </section>
        <section anchor="fec">
          <name>FEC</name>
          <t>Real-time audio applications often use Forward Error Correction (FEC) to conceal packet loss.
Audio frames are a good candidate for FEC given that they are small and independent.</t>
          <t>In an ideal world, FEC would be performed by QUIC based on the properties of the hop.
However this is not currently not supported and FEC is left to the application.</t>
          <t>In MoqTransfork, each FEC packet is transmitted as a separate GROUP with a single FRAME.
A real-time subscriber issues a <tt>SUBSCRIBE</tt> with an aggressive <tt>Group Expires</tt> value in the milliseconds range.
The publisher will drop any Groups that have not been transmitted or acknowledged within this time frame, potentially causing them to be lost.</t>
          <t>Normally, FEC is performed by transmitting individual packets once as datagrams.
However, QUIC streams are useful as they allow retransmissions when <tt>Group Expires</tt> is smaller than the RTT.
If the RTT is too high, then the RESET_STREAM frame adds some overhead but it's inconsequential (~10 more bytes).
This enables retransmitting lost packets on short hops and otherwise relying on FEC for long hops.</t>
        </section>
      </section>
      <section anchor="metadata">
        <name>Metadata</name>
        <t>There's a number of non-media use cases that can be served by MoqTransfork.</t>
        <section anchor="catalog">
          <name>Catalog</name>
          <t>Originally part of the transport itself, the catalog is a list of all tracks within a broadcast.
It's since been delegated to the application and is now just another track with a well-known name.</t>
          <t>The proposed MoQ catalog format supports live updates.
It does this by encoding a base JSON blob and then applying JSON patches over time.
If the number of deltas becomes too large, the producer can start over with a new base JSON blob.</t>
          <t>In MoqTransfork, the base and all deltas are a single GROUP.
The base is the first FRAME and all deltas are subsequent FRAMEs.
The producer can create a new GROUP to start over, repeating the process.</t>
        </section>
        <section anchor="timeline">
          <name>Timeline</name>
          <t>Another track that is commonly pitched is a timeline track.
This records the presentation timestamp of each Group, giving a VOD viewer to seek to a specific time.</t>
          <t>The <tt>timeline</tt> track is a single Group containing a Frame for each timestamp.
The live nature of the timeline track is great for DVR applications while being concise enough for VOD.
Timed metadata would use a similar approach or perhaps leverage this track.</t>
        </section>
        <section anchor="interaction">
          <name>Interaction</name>
          <t>Another common use-case is to transmit user interactions, such as controller inputs or chat messages.
It's up to the application to determine the format and encoding of these messages.</t>
          <t>Let's take controller input as an example.
The application needs to determine its loss vs latency tolerance, as reordering or dropping inputs will lead to a poor user experience.</t>
          <ul spacing="normal">
            <li>
              <t>If you don't want loss, then use a single GROUP with a FRAME per input.</t>
            </li>
            <li>
              <t>If you don't want latency, then use a GROUP per input with a single FRAME.</t>
            </li>
            <li>
              <t>If you want a hybrid, then use form of clustering inputs into GROUPs and FRAMEs based on time.</t>
            </li>
          </ul>
          <t>A publisher could monitor the session RTT or stream acknowledgements to get a sense of the latency and create Groups accordingly.
However, this only applies to the first hop and won't be applicable when relays are involved.</t>
        </section>
      </section>
      <section anchor="latency">
        <name>Latency</name>
        <t>One explicit goal of MoqTransfork is to support multiple latency targets.</t>
        <t>This is accomplished by using the same Tracks and Group for all viewers, but slightly changing the behavior based on the subscription.
This is driven by the subscriber, allowing them to choose the trade-off between latency and reliability.
This may be done on the fly via SUBSCRIBE_UPDATE, for example if a high-latency viewer wishes to join the stage and suddenly needs real-time latency.</t>
        <t>The below examples assume one audio and one video track.
See the next section for more complicated broadcasts.</t>
        <section anchor="real-time">
          <name>Real-Time</name>
          <t>Real-time latency is accomplished by prioritizing the most important media during congestion and skipping the rest.</t>
          <t>This is slightly different from other media protocols which instead opt to drop packets.
The end result is similar, but prioritization means utilizing all available bandwidth as determined by the congestion controller.
A subscriber or publisher can reset groups to avoid wasting bandwidth on old data.</t>
          <t>A real-time viewer could issue:</t>
          <artwork><![CDATA[
SUBSCRIBE track=audio priority=1 order=DESC group_expires=100ms
SUBSCRIBE track=video priority=0 order=DESC group_expires=100ms
]]></artwork>
          <t>In this example, audio is higher priority than video, and newer groups are higher priority than older groups.
Suppose a viewer fell behind after a burst of congestion and has to decide which groups to deliver next.
This configuration would result in the transmission order:</t>
          <artwork><![CDATA[
GROUP track=audio sequence=102
GROUP track=audio sequence=101
GROUP track=audio sequence=100
GROUP track=video sequence=5
GROUP track=video sequence=4
]]></artwork>
          <t>The user experience depends on the amount of congestion:</t>
          <ul spacing="normal">
            <li>
              <t>If there's no congestion, all audio and video is delivered.</t>
            </li>
            <li>
              <t>If there's moderate congestion, the tail of the old video group is dropped.</t>
            </li>
            <li>
              <t>If there's severe congestion, all video will be late/dropped and some audio groups/frames will be dropped.</t>
            </li>
          </ul>
          <t>The value of <tt>group_expires</tt> is optional.
In this example it means that the publisher automatically resets each group 100ms after they are no longer the latest.
It's recommended to use the maximum jitter buffer size.</t>
        </section>
        <section anchor="unreliable-live">
          <name>Unreliable Live</name>
          <t>Unreliable live is a term I made up.
Basically we want low latency, but we don't need it at all costs and we're willing to skip some video to achieve it.
This is useful for broadcasts where latency is important but so is picture quality.</t>
          <t>An unreliable live viewer could issue:</t>
          <artwork><![CDATA[
SUBSCRIBE track=audio priority=1 order=ASC
SUBSCRIBE track=video priority=0 order=DESC group_expires=3s
]]></artwork>
          <t>This example is different from the real-time one in that audio is fully reliable and delivered in order.
Of course this is optional and up to the application, as it will result in buffering during significant congestion.
If the viewer goes through a tunnel and then comes back online, they won't miss any audio.</t>
          <t>A key difference is that our jitter buffer is much larger for video, 3s in this example.
The player will tolerate up to 3s of latency before it starts skipping past video frames.
Note that the <tt>group_expires</tt> value can be increased during buffering by issuing a SUBSCRIBE_UPDATE.</t>
        </section>
        <section anchor="reliable-live">
          <name>Reliable Live</name>
          <t>Reliable live is another term I made up.
This is when we have a live stream but primarily care about picture quality.
A good example is a sports game where you want to see every frame.</t>
          <t>A reliable live viewer could issue:</t>
          <artwork><![CDATA[
SUBSCRIBE track=audio priority=0 order=ASC
SUBSCRIBE track=video priority=0 order=ASC
]]></artwork>
          <t>This will deliver both audio and video in order, and with the same priority.
The viewer won't miss any content unless the publisher resets a group.
However, this can result in buffering during congestion and provides a similar user experience to HLS/DASH.</t>
        </section>
        <section anchor="vod-dvr">
          <name>VOD / DVR</name>
          <t>Video on Demand (VOD) and Digital Video Recorder (DVR) both involve seeking backwards in a live stream.
MoqTransfork can serve this use-case too, don't worry.</t>
          <t>A VOD viewer could issue:</t>
          <artwork><![CDATA[
SUBSCRIBE track=audio priority=0 order=ASC start=345 end=396
SUBSCRIBE track=video priority=0 order=ASC start=123 end=134
]]></artwork>
          <t>The application is responsible for determining the group sequence numbers based on the desired timestamp.
This could be done via a <tt>timeline</tt> track or out-of-band.</t>
          <t>A subscriber will need a specific <tt>end</tt> or else it will download too much data at once, as old media is transmitted at network speed and not encode speed.
It will need to issue an updated SUBSCRIBE to expand the range as playback continues and the buffer depletes.
A subscriber could use SUBSCRIBE_UPDATE, however there are race conditions involved.</t>
          <t>A DVR player does the same thing but can automatically support joining the live stream.
It's perfectly valid to specify a <tt>end</tt> in the future and it will behave like reliable live viewer once it reaches the live playhead.</t>
          <t>Alternatively, a DVR player could prefetch the live playhead by issuing a parallel SUBSCRIBE at a lower priority.
This would allow playback to immediately continue after clicking the "Go Live" button, canceling or deprioritizing the VOD subscription.</t>
          <artwork><![CDATA[
SUBSCRIBE track=video priority=1 order=ASC start=123 end=134
SUBSCRIBE track=video priority=0 order=DESC
]]></artwork>
        </section>
        <section anchor="upstream">
          <name>Upstream</name>
          <t>All of these separate viewers could be watching the same broadcast.
How is a relay supposed to fetch the content from upstream?</t>
          <t>MoqTransfork addresses this by providing the publisher's Track Priority and Group Order in the INFO message.
This is the intended behavior for the first hop and dictates which viewers are preferred.</t>
          <t>For example, suppose the producer chooses:</t>
          <artwork><![CDATA[
INFO track=audio priority=1 order=DESC
INFO track=video priority=0 order=DESC
]]></artwork>
          <t>If Alice is watching a VOD and issues:</t>
          <artwork><![CDATA[
SUBSCRIBE track=audio priority=0 order=ASC
SUBSCRIBE track=video priority=0 order=ASC
]]></artwork>
          <t>If Bob is watching real-time and issues:</t>
          <artwork><![CDATA[
SUBSCRIBE track=audio priority=1 order=DESC
SUBSCRIBE track=video priority=0 order=DESC
]]></artwork>
          <t>For any congestion on the first mile, then the relay will improve Bob's experience by following the producer's preference.
However any congestion on the last mile will always use the viewer's preference.</t>
          <t>A relay should use the publisher's priority/order only when there's a conflict.
If viewers have the same priority/order, then the relay should use the viewer's preference and it can always issue a SUBSCRIBE_UPDATE when this changes.</t>
        </section>
      </section>
      <section anchor="broadcast-1">
        <name>Broadcast</name>
        <t>A broadcast is a collection of tracks from a single producer.
This usually includes an audio track and/or a video track, but there are reasons to have more than that.</t>
        <section anchor="abr">
          <name>ABR</name>
          <t>Virtually all mass fan-out use-cases rely on Adaptive Bitrate (ABR) streaming.
The idea is to encode the same content at multiple bitrates and resolutions, allowing the viewer to choose based on their unique situation.</t>
          <t>MoqTransfork unsurprisingly supports this via multiple Tracks, but relies on the application to determine the relationship between them.
This is often done via a <tt>catalog</tt> track that details each track's name, bitrate, resolution, and codec.
This includes how a group in one track corresponds to a group in another track.
A common approach is to use the same Group Sequence number for all tracks, or perhaps utilize a <tt>timeline</tt> track to map between Group Sequences and presentation timestamps.</t>
          <t>The viewer may limit the available tracks based on capabilities or preferences.
For example, the device may not support the 4K track since it uses AV1, or the screen size may be too small to justify the bandwidth.
This is easy enough to support; just ignore these tracks in the catalog.</t>
          <t>The primary reason to use ABR is to adapt to changing network conditions.
The viewer learns about the estimated bandwidth via the SESSION_UPDATE message, or by measuring network traffic and can then choose the appropriate track based on bitrate.</t>
          <t>Transitioning between tracks can be done seamlessly by utilizing prioritization.
For example, suppose a viewer is watching the 360p track and wants to switch to 1080p at group 69.</t>
          <t>A real-time or unreliable live viewer could issue:</t>
          <artwork><![CDATA[
SUBSCRIBE_UPDATE track=360p  priority=0 order=DESC end=69
SUBSCRIBE        track=1080p priority=1 order=DESC start=69
]]></artwork>
          <t>A reliable live or VOD viewer could issue:</t>
          <artwork><![CDATA[
SUBSCRIBE_UPDATE track=360p  priority=1 order=ASC end=69
SUBSCRIBE        track=1080p priority=0 order=ASC start=69
]]></artwork>
          <t>The difference between them is whether to prioritize the old track or the new track.
In both scenarios, the subscription will seamlessly switch at group 69 even if it's seconds in the future.
The same behavior can be used to switch down.</t>
        </section>
        <section anchor="svc">
          <name>SVC</name>
          <t>We touched on SVC before, but it's worth mentioning as an alternative to ABR.
I want to see it used more often but I doubt it will be.</t>
          <t>Instead of choosing the track based on the bitrate, the viewer subscribes to them all:</t>
          <artwork><![CDATA[
SUBSCRIBE track=360p  priority=2 order=DESC
SUBSCRIBE track=1080p priority=1 order=DESC
SUBSCRIBE track=4k    priority=0 order=DESC
]]></artwork>
          <t>During congestion, the 4k enhancement layer will be deprioritized followed by the 1080p enhancement layer.
This is a more efficient use of bandwidth than ABR, but it requires more complex encoding.</t>
        </section>
      </section>
      <section anchor="conferences">
        <name>Conferences</name>
        <t>Some applications involve multiple producers, such as a conference calls or a live events.
Even though these are separate broadcasts from potentially separate origins, MoqTransfork can still serve them over the same session.</t>
        <section anchor="discovery">
          <name>Discovery</name>
          <t>The first step to joining a conference is to discover the available broadcasts.</t>
          <t>There is currently no discovery mechanism in MoqTransfork.
However, an application can build one on top of a MoqTransfork track (of course!).</t>
          <t>For example, suppose we have a conference room called <tt>room.12345</tt>.
An index service could produce a <tt>room.12345</tt> track that lists all broadcasts within the room.
When Alice joins and ANNOUNCES <tt>room.12345.alice</tt>, the index service could update the <tt>room.12345</tt> track to add a new FRAME <tt>+alice</tt>.
The same can be done to remove her when she leaves.</t>
        </section>
        <section anchor="participants">
          <name>Participants</name>
          <t>Extending the idea that audio is more important than video, we can prioritize tracks regardless of the source.
This works because <tt>SUBSCRIBE priority</tt> is scoped to the session and not the broadcast.</t>
          <artwork><![CDATA[
SUBSCRIBE broadcast=alice track=audio priority=3
SUBSCRIBE broadcast=frank track=audio priority=3
SUBSCRIBE broadcast=alice track=video priority=1
SUBSCRIBE broadcast=frank track=video priority=1
]]></artwork>
          <t>When Alice starts talking or is focused, we can actually issue a SUBSCRIBE_UPDATE to increase her priority:</t>
          <artwork><![CDATA[
SUBSCRIBE_UPDATE broadcast=alice track=audio priority=2
SUBSCRIBE_UPDATE broadcast=frank track=video priority=0
]]></artwork>
          <t>Note that audio is still more important than video, but Alice is now more important than Frank. (poor Frank)</t>
          <t>This concept can further be extended to work with SVC or ABR:</t>
          <artwork><![CDATA[
SUBSCRIBE broadcast=alice track=360p priority=4
SUBSCRIBE broadcast=frank track=360p priority=3
SUBSCRIBE broadcast=alice track=720p priority=2
SUBSCRIBE broadcast=frank track=720p priority=1
]]></artwork>
        </section>
      </section>
    </section>
    <section anchor="security-considerations">
      <name>Security Considerations</name>
      <t>TODO Security</t>
    </section>
    <section anchor="iana-considerations">
      <name>IANA Considerations</name>
      <t>This document has no IANA actions.</t>
    </section>
  </middle>
  <back>
    <references anchor="sec-normative-references">
      <name>Normative References</name>
      <reference anchor="moqt">
        <front>
          <title>Media over QUIC Transport</title>
          <author fullname="Luke Curley" initials="L." surname="Curley">
            <organization>Discord</organization>
          </author>
          <author fullname="Kirill Pugin" initials="K." surname="Pugin">
            <organization>Meta</organization>
          </author>
          <author fullname="Suhas Nandakumar" initials="S." surname="Nandakumar">
            <organization>Cisco</organization>
          </author>
          <author fullname="Victor Vasiliev" initials="V." surname="Vasiliev">
            <organization>Google</organization>
          </author>
          <author fullname="Ian Swett" initials="I." surname="Swett">
            <organization>Google</organization>
          </author>
          <date day="19" month="September" year="2024"/>
          <abstract>
            <t>   This document defines the core behavior for Media over QUIC Transport
   (MOQT), a media transport protocol designed to operate over QUIC and
   WebTransport, which have similar functionality.  MOQT allows a
   producer of media to publish data and have it consumed via
   subscription by a multiplicity of endpoints.  It supports
   intermediate content distribution networks and is designed for high
   scale and low latency distribution.

            </t>
          </abstract>
        </front>
        <seriesInfo name="Internet-Draft" value="draft-ietf-moq-transport-06"/>
      </reference>
      <reference anchor="RFC2119">
        <front>
          <title>Key words for use in RFCs to Indicate Requirement Levels</title>
          <author fullname="S. Bradner" initials="S." surname="Bradner"/>
          <date month="March" year="1997"/>
          <abstract>
            <t>In many standards track documents several words are used to signify the requirements in the specification. These words are often capitalized. This document defines these words as they should be interpreted in IETF documents. This document specifies an Internet Best Current Practices for the Internet Community, and requests discussion and suggestions for improvements.</t>
          </abstract>
        </front>
        <seriesInfo name="BCP" value="14"/>
        <seriesInfo name="RFC" value="2119"/>
        <seriesInfo name="DOI" value="10.17487/RFC2119"/>
      </reference>
      <reference anchor="RFC8174">
        <front>
          <title>Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words</title>
          <author fullname="B. Leiba" initials="B." surname="Leiba"/>
          <date month="May" year="2017"/>
          <abstract>
            <t>RFC 2119 specifies common key words that may be used in protocol specifications. This document aims to reduce the ambiguity by clarifying that only UPPERCASE usage of the key words have the defined special meanings.</t>
          </abstract>
        </front>
        <seriesInfo name="BCP" value="14"/>
        <seriesInfo name="RFC" value="8174"/>
        <seriesInfo name="DOI" value="10.17487/RFC8174"/>
      </reference>
    </references>
    <?line 1072?>

<section numbered="false" anchor="acknowledgments">
      <name>Acknowledgments</name>
      <t>TODO acknowledge.</t>
    </section>
  </back>
  <!-- ##markdown-source:
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
+VGMDNpznAfuH6qR/Eszb3tXpfTDbj5daoqrUZJvXgtqOdEbbDdSGA3ri3B2
ZfkyYqpGexLZ6S++TXWOJJHlavCSXntzE7XBKapemrN3ivcLVZj410Wp5e0s
1FdSspVAQcjrUW1xsn/aucsRECIj0RabmoDOZ0cY+Z4/7B18/fTZL96jLR8X
X3wEdIup814wux04fjxWdEt0IGXtJw6AhrpUvCbVt+IqYNiLEmh9qC7jwfdy
fur9rnpMtpckTlSJTg2sibWfmab9Snrh+/8sQ0Y8N1YYUOrEvasyVD2gVIjt
ZUfQs6ylt1wdNC1WLPZHaEjoHUQwlNJg51BVrcbybmXuWCSJCtO467yZSQtU
7TaJe8e847C5Qbp2zvwg6mVh3Ot92rI/Tj80JzV4ce9SsDCQ/+VbQGvYN/J0
8IU5oefNl7wQz9D3PH5yhq0XwKojBNMgJynMN+oX5QA099jh8ls9gXyqFvOd
bgJ2y1rBWpwPdJfi81kA/Pq+9+7Z5b7sMgRnQ/0leOI9KMdSwjvpuIZh6NkX
PPVe9ggJvviwM/LJRyjSY6DN1w2Uqon23dT8Dmj50tGD9BEagKTTligfBg9E
u9/ls08efvr8p7Hrn7+On//6k+Onzx9Ys3+yXonVs9P3mKNgSBlCJ2LuRep/
xJNnR2+O+k9pEao29EUCGMkLPJn7tpaj8XiMYCN6mPkkYeQIj/5yKBa5m337
YJ6XrXvw15FMHqUT743+D4Bt866SqQAA

-->

</rfc>
