A track is a sequence of groups (Section 2.3). It is the entity against which a subscriber issues a subscription request. A subscriber can request to receive individual tracks starting at a group boundary, including any new objects pushed by the publisher while the track is active.
2.4.1. Track Naming
In MOQT, every track is identified by a Full Track Name, consisting of a Track Namespace and a Track Name.
Track Namespace is an ordered set of between 1 and 32 Track Namespace Fields, encoded as follows:
Track Namespace {
Number of Track Namespace Fields (i),
Track Namespace Field (..) ...
}
-
Number of Track Namespace Fields: A variable-length integer specifying the number of Track Namespace Fields in the Track Namespace.
Each Track Namespace Field is encoded as follows:
Track Namespace Field {
Track Namespace Field Length (i),
Track Namespace Field Value (..)
}
-
Track Namespace Field Length: A variable-length integer specifying the length of the Track Namespace Field in bytes.
-
Track Namespace Field Value: A sequence of bytes that forms a Track Namespace Field.
Each Track Namespace Field Value MUST contain at least one byte. If an endpoint
receives a Track Namespace Field with a Track Namespace Field Length of 0, it
MUST close the session with a PROTOCOL_VIOLATION.
The structured nature of Track Namespace allows relays and applications to
manipulate prefixes of a namespace. If an endpoint receives a Track Namespace
consisting of 0 or greater than 32 Track Namespace Fields, it MUST close the
session with a PROTOCOL_VIOLATION.
Track Name is a sequence of bytes, possibly empty, that identifies an individual track within the namespace.
The maximum total length of a Full Track Name is 4,096 bytes. The length of a
Full Track Name is computed as the sum of the Track Namespace Field Length
fields and the Track Name Length field. The length of a Track Namespace is the
sum of the Track Namespace Field Length fields. If an endpoint receives a Track
Namespace or a Full Track Name exceeding 4,096 bytes, it MUST close the session
with a PROTOCOL_VIOLATION.
In this specification, both the Track Namespace Fields and the Track Name are not constrained to a specific encoding. They carry a sequence of bytes and comparison between two Track Namespace Fields or Track Names is done by exact comparison of the bytes. Specifications that use MOQT may constrain the information in these fields, for example by restricting them to UTF-8. Any such specification needs to specify the canonicalization into the bytes in the Track Namespace Fields or Track Name such that exact comparison works.
2.4.2. Malformed Tracks
There are multiple ways a publisher can transmit a Track that does not conform to MOQT constraints. Such a Track is considered malformed. Some example conditions that constitute a malformed track when detected by a receiver include:
-
An Object is received in a FETCH response with the same Group ID as the previous Object, but whose Object ID is not strictly larger than the previous object.
-
In a FETCH response, an Object with a particular Subgroup ID is received, but its Publisher Priority is different from that of the previous Object with the same Subgroup ID.
-
An Object is received in an Ascending FETCH response whose Group ID is smaller than the previous Object in the response.
-
An Object is received in a Descending FETCH response whose Group ID is larger than the previous Object in the resopnse.
-
An Object is received whose Object ID is larger than the final Object in the Subgroup. The final Object in a Subgroup is the last Object received on a Subgroup stream before a FIN.
-
A Subgroup is received over multiple transport streams terminated by FIN with different final Objects.
-
An Object is received in a Group whose Object ID is larger than the final Object in the Group. The final Object in a Group is the Object with Status END_OF_GROUP or the last Object sent in a FETCH that requested the entire Group.
-
An Object is received on a Track whose Group and Object ID are larger than the final Object in the Track. The final Object in a Track is the Object with Status END_OF_TRACK or the last Object sent in a FETCH whose response indicated End of Track.
-
The same Object is received more than once with different Payload or other immutable properties.
-
An Object is received with a different Forwarding Preference than previously observed.
The above list of conditions is not considered exhaustive.
When a subscriber detects a Malformed Track, it MUST UNSUBSCRIBE any
subscription and FETCH_CANCEL any fetch for that Track from that publisher, and
SHOULD deliver an error to the application. If a relay detects a Malformed
Track, it MUST immediately terminate downstream subscriptions with PUBLISH_DONE
and reset any fetch streams with Status Code MALFORMED_TRACK. Object(s)
triggering Malformed Track status MUST NOT be cached.
2.4.3. Scope
An MOQT scope is a set of servers (as identified by their connection URIs) for which a Full Track Name is guaranteed to be unique and identify a specific track. It is up to the application using MOQT to define how broad or narrow the scope is. An application that deals with connections between devices on a local network may limit the scope to a single connection; by contrast, an application that uses multiple CDNs to serve media may require the scope to include all of those CDNs.
Because each Full Track Name is unique within an MOQT scope, they can be used as a cache key for the track. If, at a given moment in time, two tracks within the same scope contain different data, they MUST have different names and/or namespaces. MOQT provides subscribers with the ability to alter the specific manner in which tracks are delivered via Parameters, but the actual content of the tracks does not depend on those parameters; this is in contrast to protocols like HTTP, where request headers can alter the server response.
A publisher that loses state (e.g. crashes) and intends to resume publishing on the same Track risks colliding with previously published Objects and violating the above requirements. A publisher can handle this in application specific ways, for example:
-
Select a unique Track Name or Track Namespace whenever it resumes publishing. For example, it can base one of the Namespace Fields on the current time, or select a sufficiently large random value.
-
Resume publishing under a previous Track Name and Namespace and set the initial Group ID to a unique value guaranteed to be larger than all previously used groups. This can be done by choosing a Group ID based on the current time.
-
Use TRACK_STATUS or similar mechanism to query the previous state to determine the largest published Group ID.