moq-wg / moq-transport

draft-ietf-moq-transport
Other
72 stars 16 forks source link

Redundant object_id with stream per group #422

Open kixelated opened 3 months ago

kixelated commented 3 months ago

When sending a stream per group, the object_id MUST increment by 1 based on my interpretation of the draft:

Object ID: The order of the object within the group. The IDs starts at 0, increasing sequentially for each object within the group.

and

A relay MUST not reorder or drop objects received on a multi-object stream when forwarding to subscribers, unless it has application specific information.

Technically, the broadcaster could produce a stream that doesn't increment by one, but that doesn't make any sense and feels like a loophole to close. I much prefer things to be sequential and I don't want the application stuffing context into these relay-specific headers anyway.

If this makes sense, then we can optimize the wire encoding. Proposed:

STREAM_HEADER_GROUP Message {
  Subscribe ID (i),
  Track Alias (i),
  Group ID (i)
  + First Object ID (i)
  Object Send Order (i)
}

{
  - Object ID (i),
  Object Payload Length (i),
  Object Payload (..),
}

We need to know the ID of the first object to handle subscriptions that start at a non-zero object. Otherwise, the receiver does +1 to compute the next object's ID. We'll save some bytes for larger groups but IMO more importantly, rule out some illegal encodings.

fluffy commented 3 months ago

I think sending object ID out of order may end up being common for scalable video codecs. We should talk about what the case is her before deciding what to do with this.

kixelated commented 3 months ago

I think sending object ID out of order may end up being common for scalable video codecs. We should talk about what the case is her before deciding what to do with this.

That implies multiple streams per group, which I thought we ruled out. Otherwise you can't prioritize them separately, and all layers on the same priority is pretty pointless.

I think SVC layers should be separate tracks. That way you can also subscribe to them independently.

afrind commented 3 months ago

Individual Comment:

Is there a problem with this optimization if the publisher makes an object but doesn't send it for some reason? I think I recall Jordi's implementation does that.

kixelated commented 3 months ago

Individual Comment:

Is there a problem with this optimization if the publisher makes an object but doesn't send it for some reason? I think I recall Jordi's implementation does that.

I think it comes down to the layering of object_id and the intended usage.

In my opinion, object_id is for reassembly and gap detection when there's an object per stream/datagram. It's much like QUIC's STREAM offset in that regard, auto incrementing as each object is sent/received. It's also why my original warp draft didn't have a concept of object ID; everything was based on stream offsets.

With a sequential object_id, the MoQ transport library could feasibly implement a next() function to return objects in the original order. A relay could also use this to detect holes in the cache, for example issuing a FETCH based on a gap in object_ids. Both of these are automatic when using a group per stream so it's not necessary to encode object_id.

Those are not possible if the application is allowed to choose object_id arbitrarily. I understand the desire to encode stuff like timestamps in group/object IDs, skipping them if the encoder falls behind, but I'm worried that we're mixing layers here.

fluffy commented 3 months ago

I'm not a fan of multiple strea per group but even with one stream, if a relay had two objects, I would expect it to send the most important one first even if that was reversed the object id order. Of course that is wrapped up in object priority discussion about what object does the relay send next.

kixelated commented 3 months ago

I'm not a fan of multiple strea per group but even with one stream, if a relay had two objects, I would expect it to send the most important one first even if that was reversed the object id order. Of course that is wrapped up in object priority discussion about what object does the relay send next.

QUIC priorities work at the stream level so you can't really specify different priorities for objects within a stream. Technically you can, but the impact will be limited thanks to head-of-line blocking (akin to TCP prioritization). The current draft puts the priority in the stream header for this reason.

With a stream per group, all of the objects share the same priority and are delivered in order. The application explicitly uses this mode because it removes the need for a reassembly buffer within a group. You would use a stream/datagram per object if you want to deliver objects out of order and are willing to deal with the increased unreliability.

Christian and I have talked about a possible 5th mode: a stream per group+layer for SVC. However, I think a track per layer is just a better abstraction. The catalog would contain the SVC layer details.

fluffy commented 3 months ago

Every conversation seems to come back to priorities with deep confusions about how they work. Yes quick priorities are per stream, however moq priorities are about a relay must decide what object to forward next when the congestion window opens. I don't think this has much to do with priorities, it is simply about if a producer has to send all the objects in order and I think there are lots of cases where we do not want to mandate that at the transport level, sure for lots of types of video it will me mandated at the application layer.