From NAME
NAME and NAME - I agree with Magnus in his email (cut and pasted in the description), where he said "what about RMTP and SRT?", but I'm thinking that since we already have a "Why QUIC?" section, we should probably have a "Why NOT other protocols" section, rather than trying to talk about that in (what was) Section 6.1. That could also conveniently map into saying why we're not looking at "Interactive Media" in this document (and, transitively, in the BOF), and why we're not looking at "On Demand" (Media) in this document (and in the BOF). Please let me know if this is a BAD idea soon (I'm typing PRs).
NAME for media ingest, Magnus has a good point about covering not just HLS and DASH, but also making (even brief) reference to non-segmented protocols like RTMP and SRT (but really, this can be expanded to RIST, ZiXi, etc etc etc). This can just be a sentence or two; I'm happy to write it.
NAME - I had a complicated day yesterday, which became less complicated last night, so I'm not coherent enough to type text. I'll see what I can do in the next couple of hours, and if I can include these NAME suggestions.
The current definition of latency targets in the draft is based on specific numeric ranges. Those do make sense (since they ultimately come from use case requirements), but I believe we should focus more on what consequences those have for the protocol design. Reflecting on our experience with QUIC used for live video vs QUIC used for video conferencing, my proposed definition of the latency target for live video would be "latency an order of magnitude higher than one RTT". Two major examples of why this is important: When the target latency is on the order of one RTT, it makes sense to use FEC and codec-level packet loss concealment. When the target latency is in the range of many, many RTTs, selectively retransmitting only lost packets is almost always better than FEC. When the target latency is on the order of one RTT, it is impossible to use congestion control schemes like BBR, since BBR has probing mechanisms that rely on temporarily inducing delay and amortizing the consequences of that over multiple RTTs. I think the first point illustrates nicely why protocols like RTP have low-level control over packetization, while the existing MoQ proposals defer it entirely to the QUIC stack.
NAME - that's super helpful. It helps us explain a few things - why we need to know this, in order to explain why we're shooting for One Protocol, and why we think the first three use cases in the draft are different (they're all RTPish), and why we're not looking at RTP in the BOF - right now, the draft just says AVTCORE is looking at RTP over QUIC, which really isn't much of a justification, engineering-wise.
Victor's points are well made, though I think picking the boundary of the number of round trips necessary to rely on standard QUIC loss detection is a challenge. 5 RTTs provides almost 5 opportunities to repair a loss, which in my experience is almost always enough. Similarly, I'd expect it's enough for BBR to complete various probing cycles. It's also important to understand what RTT we have in mind here. I think the RTT used to understand what domain you're in is approximately smoothed RTT (not min RTT), because the number of rounds for loss recovery or BBR gain cycling or Cubic packet conservation matter the most.
I agree that the numeric ranges are not useful when designing a protocol but they're useful enough as product requirements. However focusing on the RTT completely misses the point. Network latency involves fixed delays (min RTT) but most of it is caused by queuing (primarily congestion control). This includes any queues within the application, the network layer, intermediate routers, and even the receiver. You can think of latency as the "frame RTT" which is decoupled from the packet RTT. Of course the packet RTT is important, but it just doesn't factor in how much data has been queued. For example, it's just useless to talk about RTMP and HLS/DASH latency in terms of network RTTs. In my opinion, the problem with those protocols is that they impose unnecessary dependencies, making it slow to drop the bitrate to reduce queue sizes. Sending media over a single stream means that every frame depends on every previous frame regardless of the GoP structure (no frame dropping), and it also means that new GoPs are dependent on the previous GoPs (no skipping ahead). WebRTC avoids these unnecessary dependencies which is how it's able to rapidly respond to congestion to keep latency low. I've been working on a "latency theory" document if any of these ideas are resonating with people. I feel like it's too early though, and we should be focusing on the use-cases and requirements instead.
NAME - please let me know when you think it's not too early to focus on "latency theory". I'd love to know more (in particular, I'd love to know if I'd be able to contribute effectively to that important topic). Just filing this away for now, as you suggest.


I propose defining latencies less than 50 ms as near real-time latencies. These latencies can be used by musicians to play together in sync. And I guess the human ear or eye would mostly not notice any delay below 50 ms. Might be worth doing a bit of research around the topic to refine the ranges though. For instance, in this paper (URL) they conclude: In another source (URL) the following is defined: 150ms target performance 13ms > lower detectable limit
< 200 ms - comfortable latencies for conversation.
Apologies for not looking at this earlier, I've had to prioritise other work recently. Given that our draft and these values are an extension of , could you please also include the references and elaboration like you have in the PR as I think it will help quell any further bikeshedding on the subject.
The MOPS document now mentions near-realtime latencies (see URL), but does not define the exact values. Likely this PR still makes sense, but now as an attempt to define those type of latencies.


Move "considerations" to a separate draft, and do various related cleanup work (for example, removing unneeded references that supported text that has been deleted.
(but document focus is on all media categories, not just live media) (moving the considerations section to its own draft) (moving this diagram to the considerations draft)
Our diagram shows "media transport protocol" as one layer, which can be true, but the text points out that anything running over HTTP/3, or even WebTransport over HTTP/3, will have multiple media transport protocols. It would be helpful for readers if we showed this.
Sports fans of this draft may remember that this section was called Requirements, and true sports fans may remember that the contents had changed very little from when James and I thought this draft would be focused on Interactive use cases - and now it's focused on live media use cases. Rather than go into the BOF with a "Requirements" section that was a natural attraction for protocol designers, and almost completely mistargeted, I provided text for some of the considerations that I could type off the top of my head, before the I-D deadline. The existing list of considerations is not a complete list, and some of the considerations that are described in this section are "To Do", where the first thing To Do is to decide whether that consideration is a consideration for Live Media. To mention one significant example, the discussion about WebTransport doesn't mention one of the biggest advantages - the use of existing CDN infrastructure for live media streaming. But there are other examples - and I may think about this issue, and let other people also provide thoughts here, before I try to resolve the issue with PRs. (tagging the group, so you can be thinking about this as well) NAME NAME NAME NAME NAME
NAME and NAME - It is occurring to me that all the use cases we're recommending in this draft, and all the use cases that are named in , are pointing towards LIVE media. This document is even explaining why we think that's what matters first. If we renamed the document as "Live Media Over QUIC", it would be more accurate, and the BOF proponents could point to this draft and ask people with other use cases if their use cases overlap with the live media use cases, perhaps allowing the BOF to recommend doing the live media use cases in this draft, and inviting people to provide comments on this draft explaining their use cases, so the IESG would know what to do with them. Your thoughts?
I don't object to the name change but I don't feel strongly.
That name works for me too.
We should revisit after the BOF, when we know what the scope of the document will be. :sunglasses:
So, this is slightly more complicated than I had hoped. The use cases in the draft span "Media Over QUIC". The considerations (and, if we get that far, requirements) in the draft only cover "LIVE Media Over QUIC". So, let's leave this one open, until we find out the right thing to do, and then we can Do The Right Thing. :innocent:
I would propose we rename (again) to "Media over QUIC Use Cases and Requirements", for a few reasons: Scope of use cases that the WG will work on isn't yet settled, and it's likely that we may need to cover some (but not all) interactive use cases as well as hybrid interactive/live. I still think we should set the protocol requirements in the document - this frees up the charter to describe scope and milestone, and our draft (if WG adopted) to set the use cases and what we will require of the deliverables. If WG adopted, the details of what is in and out can be made via WG consensus. This follows a similar title format to and other documents like it. NAME thoughts?


NAME - I think this version is ready for submission as -03, when the submission window reopens during IETF 115. Please let me know what you think.
It would help people contribute to this document if there are blank sections in outline form, and we will be less likely to miss critical stuff.
The IETF 115 proposal to the working group is to use the approved charter as the high level outline for the Requirements section.


NAME could you take a look at this? I know everyone's thinking has changed on details, but we can capture those changes as the working group converges.
The subsections should be Publishing Media Naming or Identification Packaging Media Media Consumption Relays/Caches End to End Security This is only a starting point, of course, but , and it's easier to keep track of them if the document subsections match, at least for now.
NAME - ISTM that the contain a lot of material that might better be put in another section. I'll work through that before we talk (next week, right?), but please keep this note in mind, so we can fix what I get wrong. Also - ISTM that we really do need a "specific protocol considerations" requirement section, to capture things like streams/datagrams, WebTransport/H3/QUIC, one MOQ protocol, etc. I'll add that in the PR for this issue as well.
NAME most of the sections had some beginning text (and I can't remember who wrote it - was it you?). I'm copying the bullets from NAME slides into each section as a starting point. I'm not sure whether deleting the beginning text is the right thing to do, because it might or might not match the resulting subsections' contents, and of course the new subsections don't have beginning text because they didn't exist before, but let's talk about that, next week.


This is short, but we should say something about why we're working on this section. Comments are, of course, encouraged.
NAME is hoping that discussion of some requirements at a level that is not protocol-specific would be helpful. It's not helpful to include protocol-specific requirements in this document. This document should explain that.


NAME I could also include some other non-requirements into the section if you have some to mind.
A similar section seemed helpful during discussion of URL My first nominee (and I'll put that in the corresponding PR) is that we're assuming that we're working with existing media transport protocols like RTP and SRP, rather than inventing a new media transport protocol in the IETF, but we can talk when I have text.
We have this in place, and I think we have enough non-requirements to start with, let's keep adding as appropriate.


During the , NAME asked I answered (even though I'm not a MOQ chair), , but it's worth noting that this question has come up more than once during MOQ meetings, so it seems useful to add a short summary to the draft, in order to make sure we all have the same understanding. If I get this wrong, NAME and NAME can correct me, of course. :innocent:
Ta Hi, Lucas, I'm not a MOQ chair, but I can talk about history on one point. intentional, and (IIRC) derived from URL, which says, While writing down such things as requirements and use cases help to get a common understanding (and often common language) between participants in the working group, support documentation doesn’t always have a high archival value. Under most circumstances, the IESG encourages the community to consider alternate mechanisms for publishing this content, such as on a working group wiki, in an informational appendix of a solution document, or simply as an expired draft. My personal opinion is that we haven't spent enough time discussing use cases and requirements to have a good sense of the archival value of this documentation. If we did a good job on them, and kept them roughly up to date with solution drafts, the documentation may be worth publishing, but my understanding of the IESG statement is that no AD will ever ask the working group when these drafts will be submitted for publication as IETF-stream RFCs. And now, I'll let Alan and Ted give us the real answer. Best, Spencer >
Hi MoQ, I think this document is suitable candidate for adoption. It's not perfect and needs further development but that is sort of the point of adopting it. I note that the WG has a milestone of "WG adoption of Use Cases and Requirements document for Media Delivery over QUIC". If we dont adopt this document now, when and how would we axpext that milestone to be achieved? As a point of administration, I don't see a corresponding milestone for submission of a document to the IESG. Can I ask the chairs to clarify if the intention is to adopt and develop a draft but not seek taking it through to an RFC? Cheers Lucas This isn't as odd as it might sound. The MASQUE WG did something similar to help make progress on the protocol spec for IP tunnelling. So I would appreciate clarification here.


NAME - I am looking at , and wondering if I understand our point in our draft. Is it accurate to describe what WARP-04 is doing now, as ? If I understand the point, it's that we have to rev the specification, and implementations, in order to add a new package (because implementations that only support Container Format 0x0 for fMP4 don't know what to do with Container Format 0x1), so the distinction we are making seems (to me) to be about whether the protocol specification uses a generic method to tell a receiver how to decode media, rather than whether the protocol specification describes methods itself. Please let me know what you think, because I'm pretty sure I know what I want to say, unless I'm confused.
Starting thesis: The specification should support CMAF, in addition to CMAF, support non-contained {"RAW Elementary bitstream") media, and have agility to accommodate future container formats
A bunch of good comments get made in room but from requirement point of view, I think we need to have the ability to use something that has less overhead than CMAF particularly for audio. I don't see the need to use multiple types of containers in the same session and have them synchronized.
This issue was discussed at the MOQ interim meeting on 2023-01-31 - notes from that meeting are , and included here by reference. Anyone working on a PR for this issue should take a look at the discussion notes.
Hi, NAME would you be able to do a PR for this issue? This isn't my area of clue.
On today's authors' call, we think the starting point is now have agility to accommodate a variety of container formats support CMAF, support media formats that are not processed by relays (and relay-related MOQ capabilities) This document should also describe the requirements for additional container formats.
NAME - do you think what's in the document now (which isn't quite this ^^^^) is sufficient for an adoption call, or should we do a quick PR just retitling and rearranging the subsections?
We want agility, and we'll say that as a requirement, but we don't care what a MTI packaging would be (CMAF, fMP4, don't care), and we can defer to the protocol specification(s) (ex. WARP) to state those details, because those specifications will need to handle that anyway. It is likely that we need to handle codecs the same way (agility is the requirement, but we don't care about that, and the protocol specifications will need to handle that anyway).
What the document says now:


Matches the terminology used by W3C is generally much better. This is the order at which objects are sent, but does not guarantee delivery in this order. Doesn't preclude further conversations about prioritization.
This is just a rename so maybe merge it after fixing conflicts (you'll need another approval), or abandon? Based on the discussion today we'll be updating the priority section to indicate other possibilities for expressing priority.
Looks good to me. I would like to see this merged soon, so we can make the proper references to "send order" in the additional PRs.I do think that send order make more sense than delivery order but the parts of this that have to do with the prioritization scheme should probably be moved to a new section of the draft where we talk about the algorithms to decide what to send next.


NAME does the latest commit address your feedback? thanks
lgtm modulo addressing Luke's comment.


lgtm with the small tweaks to H3 and section heading requested by Luke/SuhasI'm biased but I thought the old motivation section was pretty good.


NAME does the updated text with OPEN ISSUE looks about right to you. I personally feel we should revisit all the terms and get to a common understaning across the documents. For -05 an OPEN ISSUE seems like OK. thoughts ?
LGTM


NAME please check the latest commit . thanks
Something is wrong, this PR appears blank
editorial nit if it can be addressed, otherwise LGTM


This PR by itself doesn't make a lot of sense but I'm ok rolling with it if it's part of the grand plan


NAME I think you added this TODO but it got removed in the editorial pass, are you good with that?
Yes, we can remove this. We will certainly revisit the issue later, because this is a thorny subject. For example, we assume that "objects MUST not depend from objects in the group that have a higher priority code or a higher object ID" -- object at P2 does not depend on another object at P3, object number 1000 cannot depend on object number 2001. That much has consensus, but it is a negative statement.


LGTMLGTM (side note for much much later, RFC editor often objects to acronyms in the title - but this is a future problem)


No real changes here (other than adding a missing period) but changes newlines for checker tools
LGTM, as it seems to just whitespaces only change.


The stuff we had to italicize the stuff in html is inserting underscores in the .txt file so I just want to remove this until for now until we figure this out. Did not change anything other than making the words not italicized
Thanks for catching this , the rendered TXT file looks different for these things. Merging it for now and we can work on figuring out the right markdown syntax.


Based on QUIC: URL
Based on call today, sounds like when running over QUIC we should also use an ALPN of "moq-13" for draft 13
When running over web transport, we need to talk to the web transport people to talk about what to do but the ALPN would be H3 (or whatever) so the answer is not ALPN
The conclusion was that we should move version negotiation out of the SETUP message and into an ALPN for native QUIC and an unspecified mechanism for WebTransport. However, I can't think of any replacement for WebTransport that would work today. Query parameters would work for passing the client supported versions but there's no mechanism for replying with the server selected version. The javascript API provides no information about connection establishment (ex. any returned headers), only that it completed. If we moved version negotiation out of SETUP, then it would not be possible to interop until new WebTransport functionality was deployed, assuming W3C agrees in the first place. Could we go ahead with this PR until there's an available alternative? I like the direction of utilizing more of the QUIC/WebTransport handshake, but I don't think we should block interop awaiting this marginally better design.
Can we add in the ALPN text as part of this PR and for now say something like "When QUIC is used, the negotiated alpn MUST match the value in the SETUP message."?
It's time to specify some version numbers so we can attempt interop. We should do something like QUIC, where draft versions are prefixed with 0xff (or something?).
+1 The QUIC guys way over engineered this so I would be fine with just doing the same thing so we don't need to bike shed on it.
For now, will go with lower bits are the draft number and upper bits are some fixed set of bits defined in the draft. Do roughly what QUIC did.
Here's what I propose we copy: URL We don't need semvar yet because each version WILL have breaking changes. I'd be totally fine with semvar for the final RFC, like one byte for the major/minor/revision. Although I also think that negotiating extensions is more flexible for a transport protocol, while semvar seems more useful for something intended for fanout like the catalog.
Per conversation, we've decided to move forward with this and do ALPN as a separate PR.I would want to consider using alpn at some point in time. Want to keep it open for URL version at some point too. This PR is fine to continue the experimentation.Looks fine to me. Sure we might do more complicated stuff later but this seems like good enough for now.


This PR moves track request params to its own section. This was messed up during huge PR merge as part of preparing for IETF117 work. Also it add track namespace length field to Announce_OK message which was omitted.
NAME good catch. updated the commit to address your comment. Thanks
It's an improvement so we should merge, but we do need to clean up how parameters are encoded.You may also want to move the actual definition of Track Request Parameter, it's currently in the SUBSCRIBE REQUEST section.


This PR adds support for subscribers to issue unsubscribe requests to express its interest in not receiving media for a given track. This reflects discussions from The high level call flow is
Thinking about it some more, an error code doesn't seem necessary. publisher -> subscriber should have an error code. subscriber -> publisher doesn't need an error code. Even with an error code, it would get lost in the deduplication process.
Individual reviewIt might be useful to have an error code, but I'm not sure. LGTM.We'll need to revisit using track name vs track ID for unsubscribe once we have an answer to , but for now, this LGTM.


Following from discussions in , this PR allows a given publishers to un-announce a track namespace to indicate that it is not longer accepting new subscribe requests. The high-level call flow for happy path is as below
Individual Review


and . if messages must be known, explicit message lengths are redundanct except for OBJECT and messages with parameters. This also eliminates a whole class of potential errors where the message length does not match the actual parsing of the message. Not checking this -- and not have any message type be potentially zero-length -- greatly simplifies the parser.
And trying to use messages without negotiating an extension/version just won't work for MoQ. We're designing a protocol explicitly for relays so you do need relay cooperation, or at the very least some information on how to forward unknown messages.
Also I love that you're using "parameter count" instead of "parameter size (bytes)". It makes it much easier to build a streaming encoder/decoder without allocating temporary buffers.
I thought we agreed to allow extensibility by allowing new message types to be created.
Like to see us agree on a extensibility strategy before deciding what to do on this. We also need to decide if messages can have optional fields
We have version negotiation, and presumably we'll have extension negotiation too. What's the use-case for adding new messages without negotiating them? The problem is that we can't relay unknown messages, so all it takes is a single uncooperative relay on the chain to shallow them. I think we need explicit negotiation as a result.
If we have extension negotiation, I agree. But if our extension negotiation mechanism relies on not getting an error on unknown messages .... PR is wrong place to discuss this but I think what I would like to see is a good way to do extension negotiation, and then like you have here, error on any message that is not part of a negotiated extension. I think I would lean that way if we had an extension negotiation mechanism. Note this is the opposite direction of HTTP which is often our model for things. HTTP just skips past unknown headers.
Fail, or pass over?
IMO fail. We have version negotiation and should add extension negotiation so it should never happen. The problem with ignoring messages is that MoqTransport is designed for relays. If an intermediate relay doesn't support a message, it then gets silently dropped. At the very least we need enough information on where to forward unknown messages.
If it's going to Fail, then most Message types don't need a length field at all (OBJECT and ANNOUNCE_OK would be the exceptions)
Individual Comment: Is there any reasonable action a relay can take on an unknown message, besides discarding it? See how HTTP recently added a "Capsule" concept which is an envelop with a default relay action of "forward", which allows for end-to-end extensions without upgrading all intermediaries. Given that MoQ handles forwarding on a per-track level, I think there probably isn't any way to generically forward a message that isn't associated with an active subscription. That said, it makes me wonder if we want to add a capsule-like extension message, or does the existing OBJECT definition give enough flexibility?
Yeah exactly. It's impossible to know the intended destination of an unknown message with the current ANNOUNCE/SUBSCRIBE mechanisms. I'm using the (as the track namespace) and instead of . This actually does let you forward unknown messages from publisher -> subscribers and subscribers -> publisher since each session is associated with only a single track namespace. Session pooling is always the issue...
I think we need extensibility. We want the protocol to be extensible so a given server might support extension A and C and another server supports extension A and B. It is very hard to do that using just a version number.
Rereading all this - II think this whole issue just need to be uplevel to what is the extensibility strategy then this detailed part of it will be easy.
There was support for not requiring a length and failing on unknown message types at the Interim, so the intent is to land PR after review.
LG. The agreement at the interim was to follow up with separate frame types for object with and without length, but do that in a separate PR.I love it. It also means you can implement streaming encoders. Prefixing each message with the length required a temporary buffer or 2nd pass to compute the length.LGTM


Can we PLEASE number editor's drafts as draft-ietf-moq-transport-latest? Currently, it says draft-00, which can result is significant confustion with respect to the last published draft and creates an unstable interop target.
+1 this shouldn't have been checked in.


and . There was consensus in Cambridge that removing the special meaning of zero length gets rid of difficult code, removes potental foot guns, saves a byte, and enables actual zero length payloads, which supposedly has use cases.
Since message (6. Messages) will be the main piece of info of MOQ I think we should try to minimize its size. Assuming most of the messages send to the wire will be objects inside a quic stream, the length should be NOT needed. Could we use 1 bit in "type" to indicate if length is present, we could save some bytes without overcomplicating the protocol
The length of a QUIC stream is only known after the FIN bit is received(ie the end of QUIC stream). Putting the length in the message header can ensure the size of stream is known at the beginning of the stream.
The size of an OBJECT is a varint so that's a single byte when 0. Even in the situation where you're sending an OBJECT per frame, that's what like 100 OBJECTs per second?. That's 100B/s while the media might average 375,000B/s (3Mb/s). But yeah, we can optimize when the draft is closer to completion and things are more concrete. I like how QUIC STREAM frames are encoded, where the frame type indicates if fields are present (ex. length).
This issue is related to the question of what types of lengths we'll support, and whether we'll support those that go to the end of a quic stream (aka infinite length). "unknown" payloads where they're a delimiter of some sort had no support, because you have to do extra parsing. This issue is about two types: Object and Object + Length, which has support from the WG. Martin to roll into PR
From Cambridge: Martin will put this in a separate PR once lands


one question is if they come on different streams can they get out order
My inclination is to send a SubscriptionEnd {} message with appropriate Reason Code set. This will help to support the case that we discussed on publisher wanting to indicate wanting to stop publishing
SUBSCRIPTIONEND and SUBSCRIPTIONEND_ERROR could be split for the graceful vs non-graceful cases.
Discussion in room seems to be rather not have an error after OK but instead use new messages or in subscribe_end message
I'd like to consolidate messages at some point, but we can revisit later.


by explicitly specifying the namespace. Also consistently changes to the (b) notation to indicate a variable length sequence of bytes.
This PR got lost when merging 289.
Assume a setup with two publishers, a single relay and one subscriber. P1 ANNOUNCE's track namespace fooba P2 ANNOUNCE's track namespace foo S1 sends a SUBSCRIBE REQUEST for Full Track Name How does the relay know whether is Track Namespace: and Track Name: , or Track Namespace: and Track Name , and hence which publisher to route the subscribe to? I see a few possibilities: 1) The relay should not allow this scenario (via namespace construction and/or authorization). If so the draft should include text explaining that this is disallowed (normatively?) or "bad things(tm)" happen. 2) Change SUBSCRIBE REQUEST to be able to disambiguate the Track Namespace from the Track Name. This could be done by sending name and namespace in separate message fields, or having stricter rules for the structure of Full Track Name such that a relay can extract the constituent parts. 3) Explicitly state that Full Track Names are matched to namespaces via "longest prefix match".
Option 3 looks interesting. P1 can use a longer track namespace to steer the sub request from P2. Like a traffic engeering for content.
I like option 2. I don't agree with treating track namespace as merely a string prefix. Even if you go with option 3, there's still a race condition where a late ANNOUNCE will cause a SUBSCRIBE to an unintended track. I want to give the track namespace more properties so it's treated more like a broadcast identifier. A few folks are headed down this path without realizing it, such as proposing that there's a single catalog per track namespace. I don't see how that would even work if ANNOUNCE is used purely for routing like a BGP announcement.
NAME : are you saying you believe that the relay resolves the described ambiguity by using 'longest prefix' matched (eg: option 3)? Another option I hadn't considered based on this comment is that the relay would send OBJECTs from BOTH publishers since they both match the Full Track Name. This will break in the current design, since each publisher has their own Object Sequence and Group Sequence and when merged the consumer will be left with garbage. It also violates the logic described that says a Full Track Name can be used as a cache key.
Yeah that seems quite problematic NAME Let's say a relay have two connected publishers who send IN ORDER: A subscriber connects and issues: What happens next? The relay forwards the SUBSCRIBE to publisher 1. The relay returns SUBSCRIBE ERROR notfound The relay forwards the SUBSCRIBE to publisher 2. The relay forwards the SUBSCRIBE to publisher 1&2. These are in the order of Alan's options. I added option 4 based on Suhas' comment. Would occur if the relay rejects publisher2's ANNOUNCE because of thr shared prefix. Would occur because the track namespace is an ID, not a prefix, and must fully match an ANNOUNCE. Would occur because publisher2 has the longer path prefix. Would occur because both publishers could_ produce the requested track. And to throw a wrench in things, a third publisher joins.
There's also the case where the relay replies to the subscribe requests on behalf of the publisher(s), so it doesn't have to make the routing decision at subscription time. But it does need to decide where to forward OBJECTs when they arrive.
Implementing this now so I have some more thoughts. We should explicitly support UNANNOUNCE and UNSUBSCRIBE, which implicitly occur when the connection is dropped. On ANNOUNCE, the relay MUST ensure that the namespace not a subset/superset of an existing ANNOUNCE. On SUBSCRIBE, the relay looks up the track based on the prefix and appends itself to a list of subscribers. If not found, it looks up the namespace and creates a track entry if valid. On UNSUBSCRIBE, the relay looks up the track based on the full name and removes itself from a list of subscribers. On UNANNOUNCE, the relay deletes any namespaces and tracks matching the prefix. A radix tree is used for both so the relay can iterate through any values that match the given prefix. This is a global radix tree, similar to how QUIC connections are identified when variable length connection IDs are supported. On ANNOUNCE, the relay inserts the upstream into the upstreams hash map and errors on a duplicate. On SUBSCRIBE, the relay looks up the namespace and then the track, creating an entry if not found. On UNSUBSCRIBE, the relay looks up the namespace and then the track, deleting an entry if found. On UNANNOUNCE, the relay deletes from the namespace and track hash map. This is a strictly better than option 1. It provides the same functionality but faster, and without the restriction on namespace prefixes. Runs into issues with ANNOUNCE. example: and are subscribed to different publishers, despite using THE SAME NAME. This invalidates the claim that the track name is the cache key. We can't migrate to the new longer prefix from unless there's a guarantee they are producing the same content. A similar issue occurs when UNANNOUNCE is fired, when happens implicitly when the connection is dropped: Each subscription needs to keep reference to the track when the SUBSCRIBE was received, instead of doing a lookup based on full track name when each OBJECT is received. This will cause havok when resubscriptions occur, for example with ABR, as switching away from and back to a track MAY result in different content. It's not viable. The subscription would intermingle objects from separate publishers that happen share a prefix, all while using the same . I really don't want to support subscribing based on wildcards or prefixes anyway. This is also the slowest option, as there needs to be a global RadixTree that maps tracks to subscriptions on receipt of each object. All other options listed above would keep an array of subscribers per track, resolved using a (shardable) HashMap.
I think this seems like the right approach. Having 2 producers with conflicting namespaces is a bad idea, unless the authz policy and application is somehow OK with the consequences. I have added to clarify the thinking further
I'm of the view of two things 1) apps should not do this if it is a problem for that app usage of relay 2) relay should use the latest "announce" to override any earlier announces that are more specific ( or the same )
Discussed at IETF 117: Support in the room for changing "Full Track Name" from a single string to a tuple of Namespace and Track Name, and matching on Namespace exactly.
IIRC, my recollection was not the same, also I don't think we concluded that the namespace match exactly. The discussion went over what the authz model defines and how that impacts the flow. I wonder how much the transport draft can mandate how a given relay application should implement the business rules. The transport draft must just indicate relay behavior and the course of actions to take for what happens when " if match succeeds vs match fails ", which is what is in the draft today already
Uh, my understanding of what we talking about what not at all removing Full Track Name - it was about we did not need to define a separator for concatenating things in a tuple. I don't agree there was support for chaning Full Track Name to Namesapce and Track Name tuple and only doing full matches. That is not going to work for many of the use cases and not what we are discussing.
I thought what came out of this discussion is 1) we do not know how duplicate ANNOUNCE work even when the names are identical ( do we keep first, last , error etc ) 2) once we figure that out, we can start to deal with the more complicated issue of partial match or overlapping Perhaps I have this recollection wrong but if so point me at right place in recording for that.
My motivation for ANNOUNCE was for the contribution case. A client like OBS will connect to the server, ANNOUNCE a new catalog track, and then the server will issue a corresponding SUBSCRIBE to get the data flowing. This is modeled after the QUICR PUBLISHINTENT message, except that data doesn't flow until the other side issues a SUBSCRIBE. However, announcing a namespace prefix subverts this behavior: The relay doesn't know if an ANNOUNCE is a prefix for routing, or a single broadcast being published. The relay effectively needs a business agreement with each client to determine. I think we should split this ANNOUNCE functionality into separate messages if just for the sake of discussion:
In the case of , a tuple makes perfect sense as it mirrors the arguments to SUBSCRIBE. This message would be primarily used for contribution to "push" a new broadcast. It also makes sense as a reconnect signal where the last message wins. In the case of , matching the longest prefix might make sense instead. I know very little about BGP but maybe there's some inspiration there. This message would primarily be used for inter-relay routing.
I assumed that full track name was a tuple already, and "full track name as a concatenation" was a notational convenience. Now that I read the draft more carefully, it does send full track name in messages, rather than a tuple of track name and track NS. As far as I'm concerned, this is a mistake -- I don't think this actually works, and I have no idea how one is supposed to implement that. I believe "error" is actually equivalent to "keep first" here. I think it's a safety vs practicality trade-off. On one hand, if two different programs announce the same track, it will not work, since they will publish conflicting objects under the same name; if we disallow re-announcing, we will prevent that. On the other hand, re-announcing makes reconnects more practical.
NAME Sorry if I misread the room and/or the author's meeting. Let's continue discussing. That is being discussed in / , let's keep this issue focused on the SUBSCRIBE REQUEST ambiguity?
Individual comment: Just to illustrate the problem further here, I wrote a short sketch of a generic relay (python syntax): So the concrete proposal I have is to change to have two fields, tracknamespace and trackname. Then the first bit would change to: This is not to say the every relay has to do matches in this way. By squishing the namespace and name together it's not possible to implement a relay that does exact matching. If we put the tuple in , a relay that wants non-exact matching rules based on full track name can always construct it by concatenating namespace and track_name together. NAME Can you say more about the use cases that would break with a change like this, or suggest an alternate way to implement an exact matching relay?
In a recent editor's call there was some discussion, which split into three separate issues - capturing it here: 1) SUBSCRIBE REQUEST should have a way to denote which part of the Full Track Name is the namespace. Either a Track Namespace Length field or just transmitting Track Namespace and Track Name in two fields. There was consensus to add this. 2) Does relay matching behavior (eg: exact match vs longest prefix vs ??) need to be negotiated in band? () 3) Is there a way to subscribe to more than one track at a time (eg: wildcard subscribe, ). I'd like to keep this issue focused on 1.


Also, can someone explain what the following paragraph is saying, because I'm having a difficult time parsing it.
The next paragraph is trying to say that if you receive HoL blocked stream data at a relay you should try to forward what you have. The goal is to mitigate accumulating latency at every relay hop. I think this makes sense in two cases: You receive data that you know to be within an object you have already seen the header for. Eg: the object length is 100 and you miss bytes 0-49 but get 50-99, you can forward 50-99, as long as your QUIC library supports out of order reads and writes to a stream (not many presently do). This also applies when the object has no length and occupies the entire stream. You are missing some object data for object N on a stream, but you receive the header for object N + 1. This is (potentially) less problematic since the relay might be able to open a new stream to forward it, so out-of-order stream write APIs are not required. In any case, the text probably needs clarification, and perhaps moving from SHOULD (but we know you won't) to MAY is warranted?
Should we mention that a relay should start sending object as soon as the object can be identified (after the header)? Since the draft points out latency as a big deal, it seems this is a must have if we want to cover ULL cases
+1.
It used to be in but was removed. The text was pretty simple: I think and the agreement was to put it into some non-existent latency section.
+1 We should add a recommendation text for Relays to address the request from NAME
sooner is better I do think this might be interpreted by some people in an over zealous sort of way ( like turning off nagle type things ). I do wonder about just using MAY. But happy either way. SHOULD and MAY mean the same thing.


Section 3.3 currently says: "3.3. Cancellation A QUIC stream MAY be canceled at any point with an error code. The producer does this via a RESETSTREAM frame while the consumer requests cancellation with a STOPSENDING frame. When using order, lower priority streams will be starved during congestion, perhaps indefinitely. These streams will consume resources and flow control until they are canceled. When nearing resource limits, an endpoint SHOULD cancel the lowest priority stream with error code 0. The sender MAY cancel streams in response to congestion. This can be useful when the sender does not support stream prioritization. TODO: this section actually describes stream cancellation, not session cancellation. Is this section required, or can it be deleted, or added to a new "workflow" section." [BA] While the meaning of STOPSENDING is clear for frame/stream transport (e.g. stop sending the frame whose transmission is currently in progress), it is less clear when multiple frames are transported on the same QUIC stream. In the case where multiple frames are being transmitted on a stream, the problem is that STOPSENDING does not indicate which frame the receiver has given up on. So how is the sender to interpret it? For example, after resetting the stream, does the sender open a new stream? If so, what frame(s) are to be transmitted on that new stream? To address this ambiguity, an application-layer message(s) could be defined, indicating exactly what the receiver wants the sender to do: Stop (re-)transmission of a particular (named) frame. The existing stream is reset and a new stream is opened for transmission of subsequent frames. Stop transmission of layer(s). The receiver wishes to the sender to adjust the operating point, by stopping the transmission of one or more temporal or spatial layers. Only the layers that remain will be transmitted on new stream(s). Mailing list thread: URL
I think subscribe hints solves the problem of what to start on by saying which object to start the new subscription on. It seems like the solutions to layers would be to put different layers on differenent streams. I would expect different layers to have different priorities which will then mean different streams.
Attendees think there may be valid use cases of STOPSENDING and RESET and it should not be disallowed. But typically UNSUBSCRIBE could be used to accomplish the desired behavior. STOPSENDING and RESET do not change the state of subscriptions.
Yeah the problem is when there's significant congestion, a player can fall behind on the active subscription. It needs a way of indicating that it is not waiting for group X any longer so the server should not send it, otherwise it's just a waste of bandwidth. My proposal is to use STOPSENDING to indicate you don't want something. This does mean that you can't put unrelated objects on the same stream, otherwise you might accidentally reset the wrong objects. ex. If I no longer want to receive group X, I STOPSENDING any QUIC streams containing group X. But that does prohibit sending group Y on the same QUIC stream, so it would prohibit sending the entire track on a single stream. But like you forfeited the ability to skip any content if you decided to do that. Alternatively, we could add a STOPGROUP message or UNSUBSCRIBERANGE. Possibly we could RESUBSCRIBE with a new start group.
Resubscription works fine here. Since a new subscription is supposed to override an existing subscription from the client, Relay can start sending from the new group. Also I don't think we need to forfeit track per stream use-case. If someone is using track per stream, they exactly know what properties they are signing up for. My proposal would be to Subscribe with new start_point
Resubscribe only works if the content we don't want is at the head/tail, unless SUBSCRIBE supports ranges instead of a single start/end. We don't need to forfeit the use-case; the receiver would have to know that it can't cancel streams in this mode. Franky the application has already made a huge mistake if you're encountering congestion while sending all groups over the same stream. A UNSUBSCRIBE/SUBSCRIBE message doesn't work because it will cause redelivery of any duplicates. We would have to add RESUBSCRIBE or allow augmenting an existing SUBSCRIBE.
NAME Agree that STOPSENDING and RESETSTREAM do not change the state of subscriptions. I'd say the same for CLOSE_STREAM (see: URL).
Not with Subscription hints though
Yes , its application decision to prefer such a mode. Yes in such cases cancel will cancel the entire stream. But resubscription with a new start_point will help alleviate some.
The group spent time discussing ideas around RESUBSCRIBE/SUBSCRIBE_UPDATE and multiple subscriptions. NAME brought up the fact that a relay may have to issue overlapping subscribes because it doesn't know whether a relative or absolute subscription is earlier. This needs a new issue for multiple subscriptions and updating subscriptions.
Like the change. Section 3.3 currently says: "3.3. Cancellation A QUIC stream MAY be canceled at any point with an error code. The producer does this via a RESETSTREAM frame while the consumer requests cancellation with a STOPSENDING frame. When using order, lower priority streams will be starved during congestion, perhaps indefinitely. These streams will consume resources and flow control until they are canceled. When nearing resource limits, an endpoint SHOULD cancel the lowest priority stream with error code 0. The sender MAY cancel streams in response to congestion. This can be useful when the sender does not support stream prioritization. TODO: this section actually describes stream cancellation, not session cancellation. Is this section required, or can it be deleted, or added to a new "workflow" section." [BA] While the meaning of STOPSENDING is clear for frame/stream transport (e.g. stop sending the frame whose transmission is currently in progress), it is less clear when multiple frames are transported on the same QUIC stream. In the case where multiple frames are being transmitted on a stream, the problem is that STOPSENDING does not indicate which frame the receiver has given up on. So how is the sender to interpret it? For example, after resetting the stream, does the sender open a new stream? If so, what frame(s) are to be transmitted on that new stream? To address this ambiguity, an application-layer message(s) could be defined, indicating exactly what the receiver wants the sender to do: Stop (re-)transmission of a particular (named) frame. The existing stream is reset and a new stream is opened for transmission of subsequent frames. Stop transmission of layer(s). The receiver wishes to the sender to adjust the operating point, by stopping the transmission of one or more temporal or spatial layers. Only the layers that remain will be transmitted on new stream(s).


There's an assumption in the current draft that some messages are partially reliable (OBJECT messages) while some are fully reliable (everything else, aka control messages). The ability to drop a message depend on the ability to reset the QUIC stream. However, reseting a stream containing control messages wrecks havok on the subscription state machine. There's no way within QUIC determine if a messages was received or processed prior to a reset. For example, if I send a SUBSCRIBE on stream and then a receive a STOPSENDING for that stream, then the subscription enters a limbo state: The SUBSCRIBE was processed and a SUBSCRIBEOK or SUBSCRIBEERROR is forthcoming. The SUBSCRIBE was never processed and a SUBSCRIBEOK or SUBSCRIBEERROR will never be received. The only option currently is to set a timer after a reset is received. After a few RTTs or so, we assume the SUBSCRIBE was lost and issue a new SUBSCRIBE on a new stream, introducing latency in the process. Though things get extra weird if we receive a response after this timeout expires... I think we either need to state: Control streams MUST NOT be reset (like HTTP/3) Reseting a control stream also resets all prior messages (ie. all prior SUBSCRIBEs). Reseting a control stream resets all unacknowledged messages (ie. SUBSCRIBEs without SUBSCRIBEOK). Option 3 is problematic, since the subscriber knows that the OK was received prior to the reset but the publisher doesn't. Personally, I think option 1 is the best is there's a single control stream, while option 2 is the best if there's multiple (scoped) control streams. Regardless of the approach, data messages and control messages should be split () because they have different reliability. A receiver should know if it can issue STOP_SENDING for an OBJECT without impacting control messages, especially if we take approach 1. My application uses a bidirectional stream for control messages and unidirectional streams for data messages. It makes it very easy for the application to know if a stream is resettable just based on the ID.
From , (s/channels/streams) -- snip Control and Data Channels When a endpoint client or relay begins a transaction for media delivery, a new bilateral QUIC Stream is opened. This stream will act as the "Control Channel" for the exchange of data, carrying a series of control messages in both directions. There is one "Control Channel" setup per track. Control Channels are "one way" and are setup hop-by-hop between the participating MoQ entities. If a peer both sends and receive media, there will be different control channels for sending and receiving. For exchanging media, OBJECT messages ({{message-object}}) belonging to a group are delivered over one or more unidirectional streams, called data channels, based on application's preferred mapping of the OBJECT and its group to underlying QUIC Stream(s). The control channel will remain open as long as the peers are still sending or receiving the media. If either peer closes the control stream, the other peer will close its end of the stream and discard the state associated with the media transfer. The latter resulting in termination or clean up of stream states associated with the data channels. -- snip The meta level thinking there was , OBJECT messages sent over data streams doesn't impact control stream. However closing a control stream, say for a track namespace, will end up closing all the data streams corresponding to the media transfer for the associated track namespace
Resetting the control stream should be an error, given there is only a single control stream.
The client creates a bidirectional stream and sends the SETUP message. The server replies with its own SETUP message on the same stream. Afterwards, both endpoints can create any number of unidirectional streams containing any non-SETUP messages. Messages with different priorities should not be mixed in the same stream, which means control messages should never be mixed with data messages. Messages can't be sent or have to be buffered until the receipt of the SETUP message. Control messages over separate streams arrive in an unknown order.The client creates a single bidirectional control stream. The control stream MUST start with a SETUP message, followed by any number of control messages (ex. SUBSCRIBE). The sender creates unidirectional data streams. The data streams MUST only contain OBJECT messages. Pros: Partially Control messages are no longer intermingled with with data messages, and the control stream MUST always be the highest priority. Endpoints no longer have to buffer messages, as QUIC will automatically make sure SETUP arrives before any other control messages. Data streams MUST NOT be created until receipt of SETUP. Control messages arrive in a specified, deterministic order. Cons: Head-of-line blocking between control messages, which sometimes may not be desired.
While I was reading the requirements draft, I found some use cases mentioning bidirectionality. Is it expected/supported that there can be data flowing in both directions (eg: a p2p call)?
Yeah, my intent is that there's a "sender" and a "receiver" per track. The ROLE param in the SETUP message indicates if an endpoint (client/server) intends to send tracks, receive tracks, or both. In the bidirectional case, both endpoints would say ROLE=BOTH. Then they could independently PUBLISH or SUBSCRIBE to tracks. Alternatively, we could say that tracks may be bidirectional... but I don't think that makes any sense.
We can simply say that data objects MUST NOT be sent over control streams, and remove any reference to whether data streams should be unidirectional or bidirectional. It doesn't matter and we can leave it to the end-points discretion.
The proposal above aligns pretty well with the idea in , more specifically this I like the separation of control stream and data streams, the latter being unidirectional streams.
I like the proposal for this. I view the HOL blocking of control messages a feature not a bug. More specifically, I think that some of our messages need to be delivered in order. Specifically if a client is trying to stop and high res video subscription and start a low res subscription, it would be good to ensure that the subscribe to the low res track does not happen until after the end the end subscription to the high res track has happened. Sending the un-subscribe then subscribe on one quic stream allows these to be sent and same time to server ( we don't need a round trip between them ) but still be delivered in order. I think it needs to be clear that multiple control messages can be outstanding at once. For example can send multiple subscribes before getting the response to the first subscribe.
I would like to write up a PR based on the above ( basically resurrecting ) that pertains to the control channels.
I like the idea of seperation of control stream and data stream.
WG is ok with a single stream, with no critical use cases for multiple. A single stream makes it easier to change bitrates 'atomically'. People don't want Object messages allowed on the same stream as control messages. People noted that this means the only bidi stream is used for the control stream in practice, and all unidirectional streams are used for objects, but people don't want to bake that into the spec.
The current draft specifies that control messages may be sent over separate streams. This means that control messages will arrive in an unknown order. This can create divergent behavior if messages depend on any form of ordering. The simplest example if sending a SUBSCRIBE message followed by a later UNSUBSCRIBE message on a separate stream. If the UNSUBSCRIBE arrives first for whatever reason (packet loss or poor prioritization), then it has a completely different meaning. The current draft adds some advisory text that control messages should be on the same stream if ordering is required. I think we should put all control messages on the same stream, so ordering is enforced and the behavior is deterministic.
I think life will be way easier if all control messages are reliable and in order. So +1 on single control stream. One of my arguments for this is the difficulty in even testing our of order control messages.
Will be fixed by the PR that
As mentioned in , there's currently no distinction between control streams and media streams. Should we have dedicated control streams? When should these be cached or forwarded by relays? For example, GOAWAY must NOT be forwarded by a relay, but something like TRACK (does not exist yet) should be forwarded.
This sounds like something worth thinking on and capturing more about in the spec.
QuicR supports control streams and media streams. Control Stream is for setup and other control features Media Streams for delivery media - today it supports QUIC Streams or QUIC Datagrams. More details can be seen here : URL This keeps protocol design cleanly separated and also extensible
Discussed today, there was interest in separating today's control messages from media/object streams, but not yet interest in constraining a MoQ session to a single control stream. Per track and per namespace were both mentioned as reasonable scopes, as well as 1 per session. There were follow-up questions about Setup messages and version negotiation and how you know which version is in use.
One conclusion from the chat is that QUIC streams MUST NOT contain messages with different priorities. Otherwise, a QUIC library would need the ability to reprioritize a stream at a given byte offset. If control messages are always higher priority than data messages (debated), then separate streams are required. I also mentioned that in my implementation, separate threads process control and data messages separately. Data streams are immediately sent to a media decoder thread (WebWorker) while control streams stay in the main thread. This architecture is nice but breaks if control messages and data messages can be interleaved. I think we were in pretty good alignment that there should be control streams. The primary discussion surrounds the scope and number of control streams. control stream per track. control stream per track namespace. control stream per session. I don't think option 1 is viable for ABR, as you want to coalesce the UNSUBSCRIBE / SUBSCRIBE for separate tracks. For example, (near) simultaneously unsubscribe to 480p and subscribe to 720p. If the tracks are truly independent and can not tolerate head-of-line blocking, perhaps they should use a separate namespace instead? I think option 2 is acceptable. The goal is to avoid introducing head-of-line blocking for thousands of unrelated track namespaces, but I think this bleeds into the infamous pooling discussion. If pooling is accomplished via multiple sessions like WebTransport, then option 3 also accomplishes that goal. I'm currently using option 3 since it makes the SETUP marginally handshake easier. Control messages are written immediately after the SETUP message, avoiding the need to buffer messages pending the handshake. It also means you can coordinate subscriptions when tracks are NOT within the same track namespace (ex. ABR across different producers).
Okay so I can't help but start a tiny bit of the POOLING discussion. My application uses Warp for media and Alan's protocol for chat. Let's assume that I want to use the same QUIC connection for both for efficiency reasons. I would like to design my application into two halves, so one part of the code deals with chat and one part deals with media. I don't want a situation where I have to pass control and data messages between threads. It would be really nice if there were two control streams: one to control the chat protocol and one to control the media protocol. This would also be nice for the CDN, as each control streams could be routed to a separate backend/origin. A fatal error (RESETSTREAM) on the chat control stream would not impact the media control stream and vice-versa. However, this doesn't quite work right now because the can be collisions. The chat and media system would need to coordinate to avoid collisions, otherwise IDs need to be rewritten. Any incoming data streams need to be forwarded to the correct component based on this rewrite lookup table. One way to fix this is to extend all messages to include a , where 0=media and 1=chat in this example. Each control stream gets its own ID and OBJECTs would include the ID, avoiding collisions and making it very easy to route within the application and CDN. (this is basically WebTransport session pooling) In fact, now each session could even use a different version of MoQ. This would be super useful when the chat and media backends are running different versions of the protocol. It's why I suggested at the end of the call (NAME that each control stream contains it's own SETUP handshake.
Individual comment: Do you mean the "sendOrder" field in OBJECT (section 6.2), or something else? I'm not sure normative language is required here, especially if it's based on what current QUIC implementations supports as a prioritization API. Someday a QUIC implementation could support changing priorities at different offsets for a stream. As for pooling - WebTransport has taught us that pooling is a huge headache. I suggest we defer to WebTransport or open multiple QUIC connections rather than trying to define yet another pooling layer in moqt.
I have a draft in the works to support doing this for HTTP/3, so it's not far off in my world
Well, I kinda think the normative language is justified when priority schemes are written on the wire. You're totally right that an implementation could prioritize at byte offsets... but that doesn't mean a relay can support it. Ugh, I guess we need to discuss if prioritization schemes are negotiated or not. My goal was to require a base scheme (send order) in the transport draft so we could just assume that every MoQ relay will support it, and thus normative language like this is fine. But you're right, new prioritization schemes will absolutely come along and maybe send order should be a guinea pig. So maybe: if the is negotiated, then messages on the same stream MUST use the same value. I believe the same is true for NAME prioritization scheme. Either way, point taken and it was a bad argument on my part, and barely even related to the topic of control streams. Gross but point taken. I assume the priority can only decrease?
The design doesn't currently implement that constraint, the reason being that an application using HTTP might have a need to increase the priority of some bytes relative to other streams.
Going back to the topic of control streams, we need to support both the following Control stream per track namespace One Control stream for the session - (for setup, termination) Also i feel the transport draft should have the text for it as well to explain what happens when a control stream for a track namespace is created or reset and how are they related to the data streams carrying the objects.
NAME mentioned my priority scheme. On the prioritization scheme, my personal thinking evolved as I was studying implementations and consequences. For a while, I did believe that layered encodings would be better implemented by having a single track for the whole media, and having for each object priority fields of some kind indicating the relative urgency of the object. I think now that I was wrong, because it leads to a complex mapping that makes relaying harder, and also because the exact semantic of the "priority field" is too complex to specify in a base protocol. The transport mappings get much simpler if all objects in a track are treated with the same precedence -- at least within a group. We may debate whether the next group should ever take precedence over the previous one, or never, or only some times. This simplification does force layered encodings to use separate tracks for each layer, and to explain the relation between the tracks as part of the application data. Which amounts to pushing complexity out of the transport and back into the application, which I think is a better tradeoff. The tradeoff also simplifies the tasks of the control stream, because it only has to manage precedence between streams, not precedence between objects.
Should be fixed with the PR that
I would add a note that data streams are sent on unidirectional streams, but looks gud.LGTM


Delayed LGTM.
Section 5.1 of the draft says: For the second case above, I think it would be useful to have an explicit signal from the publisher to signal the end of the track. For the third case, the text seems to hint (via a section reference) that if the subscription abruptly terminates with an error, the publisher can send SUBSCRIBE ERROR, but that section says: The draft should clarify if this is allowed following a SUBSCRIBE OK. Also +1 to adding UNSUBSCRIBE ().
+1 we should allow sending a SUBSCRIBE ERROR after a SUBSCRIBE OK.
I was assuming that the catalog change would be the way a track end was indicated then the client would unsubscribe.
As an individual: This seems like a bit of a subtle signal and something more explicit using the Track ID would be preferable for me.
I tend to incline towards Catalog indicating the status the more i think of it. Catalog is source of truth for tracks. Having a catalog update that indicates the following Full Track Name lastobjectid field Also if the catalog is ending, since the producer is going away, then include another optional field finished or something These would be sufficient and a clear way to identify the status end to end.
I think putting the FIN group/sequence in the catalog is clean. It does prohibit relays from cleanly terminating a broadcast early or rewriting group/object sequences, but I think that's fine? However, the wrinkle is that a sender MAY choose to not transmit a group/object. While I don't think this is explicitly stated in the draft, it's a requirement given that relays can only cache data for a finite amount of time. The viewer could get stuck waiting for the FIN group/sequence as signaled in the catalog, even though it is not forthcoming as the relay did not receive the object or already evicted it from the cache.
As an individual: Having an explicit signal outside the catalog will make it easier for relays to clean up track related state. If a publisher is done with a track, they can update the catalog, but it will need to propagate to all subscribers, who in turn need to issue an unsubscribe. Only when all of them unsubscribe (which we still need) can a relay discard the entry in the forwarding table. If the publisher also sends an explicit signal closing off the track, the relay can immediately clean up the state.
We need few things. Cease the announcement This is an explicit signal from the publisher that it is no longer interested in sending media for the announced tracks. This is sent to the relay to trigger subscription cancellation downstream and clean up local relay state. Terminate the Subscription On subscribe end signal, each receiving entity will forward downstream and clean up local state. If it is the consumer, it stop media pipeline and so on. Unsubscribe For subscribers to explicitly indicate that they are no longer interested in a given track , they will send I am happy to write up a small PR as proposal if we think the general direction is fine.
What is the difference between Cancel the subscription and Unsubscribe?
Unsubscribe is an explicit action from the subscriber and Cancel is the signal from the publisher. May be we should call it ` instead ? I see cancel can be misleading
Got it. Terminate is better than Cancel.
We already have for the publisher to immediately terminate a subscription with a code/reason, so we could reuse that. However, the problem is when the termination occurs. The end of a broadcast would look like: There's a race, as the can arrive before the last objects due to retransmits or congestion control, severing the subscription early. Ideally we wait for all outstanding objects to get delivered and then terminate the subscription. In QUIC terminology, we need a in addition to our existing . The difficult part is determining which objects are still outstanding.
Do we want to distinguish a normal end of subscription (due to EOF), and an unexpected end (due to, e.g., a downstream server crashing)? We do that normally in QUIC (fin vs reset), so it might make sense to do that here.
Image the case where we have A sending to R sending to B. B subscribes to R. A sends ANNOUNCE to R. R subscribes to A. At this point media is flowing from A to R to B. A temporary looses WIFI connectivity and reconnects over 5G with new IP. A sends an ANNOUNCE to R, R subscribes to the new A and perhaps tries to send an error to original ANNOUNCE and end subscribe but A will not get that as that QUIC connection is gone. Once again data is flowing from A to R to B. I think it would be bad if the new ANNOUNCE, or an error on the QUIC connection from A to R caused a termination or error of the subscribe between B and R. I'm think it is better for B to unsubscribe if it is not receiving the media it wold expect.
Having explicit messages reflecting the actions would be my inclination as well. I thought it might be beneficial to explain the role of the above proposed messages with few flow diagrams Here is the happy path flow (it ignores Subscribe_OK and response flows to keep the flow focussed)
Summary thoughts: Want to support disconnection without propagation to all subscribers (ie: If there were two publishers) Need a way to cleanly unsubscribe from a track (UNSUBSCRIBE) - Like STOPSENDING? Need a way to indicate that a relay is no longer the place to subscribe to for a track (ie: UNANNOUNCE) But UNANNOUNCE does not indicate an unsubscription. Need a way to indicate the track is FIN'd and ending, could use the catalog or put in the protocol (or both) Likely want a way to drain a relay, such as an HTTP GOAWAY style functionality. (Could be SUBSCRIBETERMINATE) Timeouts do need to be handled, even if they're not the ideal/clean case. Want to know whether the relay wants to stop publishing or the origin did, so a client can decide whether to re-sub. NOTE: Objects can be dropped, hard to know if they'll ever arrive. Cullen will summarize a proposal. Note that the relay doesn't really need to know about tracks or what its subscribing to. An open issue is how to do FIN, whether it as part of Objects, only the catalog, a separate message, etc.
Rough notes on proposal in the call: The catalog updates and says what the last message in a track is. Catalogs are a way that endpoints can say there will never be more on a track. The annouce has an equivalent un-Annouce message. It changes routing of future subscribes but does not change state of existing subscribes. The entity that send an subscribe and send an un-subscribe The entity that receives a subscribe can send a go-away which will let the entity that sent the subscribe go do something new ( like subscribe to something else ). We might need to figure out what data goes in the go away to given info that the clients enough info to do the right thing. Timeout can happen, and connections disappearing, and we need to sort out what impact that has but that is not the primary way to cause flow of media to change. Update: Key issue here is when the relays see the go away, do they drop the related forwarding state for the subscription, or do they just forward the update to the subscribers and wait for the subscribers to remove the subscription.
NAME NAME thanks for capturing the notes. I will work on set of small PRs to capture some of the items from the summary.
The point I was trying to clarify on the last call was that catalog already has a mechanism for a publisher to communicate to all subscribers that the track it has advertised as being available is no longer available. A clean FIN if you like. We can, as has been pointed out, create a control message which says the same thing. But then we have a weird asymmetry in which a publisher notifies clients of track availability through a catalog update but then uses control messages to do the reverse. For good design with clean encapsulation, we should seek symmetry in operation. We should either use control messages to advertise the availability/unavailability of tracks , or use catalogs, but not a hybrid of both. In my understanding of moq-transport, control messages have utility that is scoped to the current hop. They negotiate the format in which data will be exchanged on that hop and issue commands to subscribe/unsubscribe/announce etc. Those commands have no applicability to any other hops on the distribution chain. A catalog however is a contract between a publishers and all subscribers. Unlike control messages, it holds data that is not interpreted hop-by-hop and is intended for targets that can be many hops away. I think relays should be as simple as possible. In my conception, they should not understand whether tracks are being published or not. Their job is to move objects. Their view of the world is around objects and they do not need to understand what tracks are. While of course we can build all sorts of track intelligence in to relays, I think if we can build a base protocol which is agnostic to tracks, then it will be scalable and robust, and cleverness with tracks can evolve in the streaming formats without affecting deployed networks of relays.
Discussed in Boston: Agree we should add a SUBSCRIBE FIN message with the "final offset"


Issue raised at interim on Feb 1, 2023: Does the protocol need to define a failover if QUIC is not available on a specific path. If so, is it the same failover in all cases?
Note that WebTransport does provide a failover to HTTP/2.
We need a answer for Raw QUIC too
We discussed this in chartering and came down on a hard no. It just makes things too complicated. Yep, the webtransport version of it might work fine on TCP and we are not out to break that but it is not a design goal. This is about media over QUIC and QUIC is over UDP. The CDNs may internally do whatever they do but that is a black box.
I agree that this is out of scope, based on my reading of the charter, which says "can be used over raw QUIC or WebTransport." I would like to either close with no action or we can add editorial text that notes that all paths may not support QUIC.
It was decided that a sentence or two about this, including a note that the appropriate fallback may be something entirely different from MoQ (ie: DASH/HLS/etc) depending upon the application and deployment.


Given this also runs over WebTransport, it's best to avoid QUIC unless it's specifically referring to the transport.
Though MOQT is optimized for QUIC, it technically can go over WebTransport over HTTP/1 or HTTP/2. There are a number of cases when QUIC is used when it could be something else and in most cases, specifying QUIC is not critical to the design. For example "Consumer: A QUIC endpoint receiving media over the network." Also, the definitions in 1.2 frequently reference terms defined later in the list.
Absolutely. Stream prioritization and congestion control is better with QUIC, and thus can support lower latencies, but MoQ over TCP should still work well enough.
For what its worth, we did did say during chartering that were were not going to focus on solving any of the problems that happen with fallback to TCP. Clearly we are not going to go and brak whatever fallback WebTransport does, but they key thing is this work when then WebTransport is over QUIC, not other cases
I completely agree. This is an editorial point that there are times when 'QUIC' is used when it may not actually be QUIC. In many cases, just removing that word makes the sentence both slightly more accurate and shorter.