Each stream’s media is cut into fragments that start at the same times in every track,
so a player can switch bit rate between any two. The manifest lists the fragments’
times; the player builds each fragment’s address from the stream’s Url
pattern.
The c element
Each c element in a StreamIndex describes one fragment, or a
run of fragments of equal length. Their order matters.
| Attribute | Type | Meaning |
|---|---|---|
n | 32-bit | The fragment’s number; must rise with its time. |
t | 64-bit | Start time, in the stream’s timescale. If absent: the previous fragment’s start plus its duration, or 0 for the first. |
d | 64-bit | Duration. If absent, it is worked out from the start times of the neighbouring fragments; with no neighbours, it is the presentation’s Duration. |
r | 64-bit | How many fragments of this duration follow on, counting this one: r="2" is two fragments. Needs version 2.2. |
Each c needs t or d or both. A run of
fragments is written either with start times (each t given, and only the
last d) or with durations (each d given, and only the first
t, or none when it is 0).
The f element
A c element may hold f elements, one per track, with
i (required), the track’s Index. When the stream has
ManifestOutput="TRUE", its text is that track’s sample data for the
fragment, in Base64, so a player gets it without a request. This is how short text
data, such as script commands, travels in the manifest.
Fragment addresses
The Url pattern is
QualityLevels(bit rate)/Fragments(name=start time),
relative to the address of the presentation (the .ism file’s address).
| Placeholder | Replaced by |
|---|---|
{bitrate} or {Bitrate} | The track’s Bitrate |
{CustomAttributes} | The track’s custom attributes, as Name=Value pairs separated by commas |
{start time} or {start_time} | The fragment’s t |
| Noun in the request | Response |
|---|---|
Fragments(…) | The whole fragment: moof and mdat boxes |
FragmentInfo(…) | Only the metadata |
RawFragments(…) | Only the data |
KeyFrames(…) | Only the independently decodable frames |
Adding , format=m3u8-aapl inside the brackets asks for the fragment
packaged for HLS instead. A fragment of a live stream that does not exist yet is
answered with HTTP 412 Precondition Failed and an empty body. With a fragment, the
server can also send a sparse stream pointer,
ChildTrack="name=time,…", giving the latest fragment of each related
sparse stream.
Live timing boxes
Fragments of a live presentation carry two uuid boxes in their
traf, which on-demand players ignore. Both start with the box size and the
type uuid, then the 16-byte UUID, then a version byte and three flag
bytes. In version 1 the times are 64-bit; in version 0, 32-bit.
| Box | UUID | Fields after version and flags |
|---|---|---|
tfxd | 6D1D9B05-42D5-44E6-80E2-141DAFF757B2 | The fragment’s absolute start time, then its duration |
tfrf | D4807EF2-CA39-4695-8E54-26CB9E46A79F | A fragment count, then that many pairs of absolute start time and duration, for the fragments that follow |
With tfrf, a live player learns of new fragments without reloading the
manifest. The count is one byte in the specification’s grammar and in players such as
ExoPlayer, though the specification’s field list calls it four bytes.
Worked example
<StreamIndex Type="video" Name="video" Chunks="4" QualityLevels="2" TimeScale="10000000"
Url="QualityLevels({bitrate})/Fragments(video={start time})">
<QualityLevel Index="0" Bitrate="3000000" FourCC="H264" MaxWidth="1280" MaxHeight="720" CodecPrivateData="…"/>
<QualityLevel Index="1" Bitrate="1000000" FourCC="H264" MaxWidth="640" MaxHeight="360" CodecPrivateData="…"/>
<c t="0" d="20020000" r="3"/>
<c d="10010000"/>
</StreamIndex>
…/Movie.ism/QualityLevels(3000000)/Fragments(video=40040000).