1. AVTransport protocol
The AVTransport protocol is a standardized mechanism for multimedia transport and storage. This protocol aims to be robust, reliable and low-overhead. Rather than being specialized, the protocol is scalable, from archival to chip to chip interconnect, Ethernet links to satellite links, post-production intermediates to final cinematic deliverables.
The protocol addresses shortcomings of other formats, such as timestamp rounding, lack of DTS, fragile parsing, inflexible metadata, inconvenient index positions and layout, inextensible formats, and rigid overseeing organizations.
1.1. Overview
On a high-level, AVTransport is a packetized wrapper around codec, metadata and user packets and provides context and error resilience, as well as defining a standardized way to transmit such data between clients.
AVTransport is based on individual packets, for which a demuxer interprets and maintains a structure. There is no higher-level structure to the data stored or transmitted.
As a simple example, a possible structure of packets in a general AVTransport session could be:
| Packet type | Description |
|---|---|
| § 2.1 Session start | Starts the session with a signature. May be used to identify the stream as an AVTransport session. |
| § 2.3 Stream registration | Register a new stream. |
| § 2.5 Stream configuration | Configuration data for the new stream. |
| § 2.15 Video information | Information about a video stream. |
| § 2.12 Metadata | Stream or session metadata. |
| § 2.11 Index | Optional index packets to enable fast seeking. |
| § 2.6 Stream Data | Stream data packets. |
| § 2.6.3 Stream data segmentation | Segmented stream data packets. |
| § 2.18 User data | Optional user data packets. |
| § 2.20 End of stream | Finalizes a stream or session. |
1.2. Packet descriptor
Each packet must be prefixed with a 2-bytes descriptor to identify it. Below is a table of how they’re allocated:
| Descriptor values | Packet |
|---|---|
| 0x4156 | § 2.1 Session start |
| 0x0002 | § 2.3 Stream registration |
| [0x0003:0x0005] | § 2.5 Stream configuration |
| 0x0008 | § 2.15 Video information |
| 0x0009 | § 2.10 Hash packets |
| [0x00A:0x000C] | § 2.12 Metadata |
| 0x0051 | § 2.11 Index |
| [0x0010:0x0012] | § 2.13 LUT/ICC profile |
| [0x0020:0x0023] | § 2.14 Font data |
| [0x0030:0x0031] | § 2.8 FEC grouping |
| 0x0040 | § 2.16 Video orientation |
| 0x0041 | § 2.17 Stereo video |
| 0x0050 | § 2.19 Stream duration |
| 0x00FE | § 2.9 Stream data parity |
| 0x00FF | § 2.6.3 Stream data segmentation |
| [0x0100:0x01FF] | § 2.6 Stream Data |
| [0x0200:0x02FF] | § 2.7 Extended stream data |
| 0x0300 | § 2.2 Time synchronization |
| [0x0600:0x0602] | § 2.18 User data |
| 0x0FFF | § 2.20 End of stream |
| 0xF001 | § 3.3.1 Session control data |
| 0xF002 | § 3.3.3 Feedback |
| 0xF003 | § 3.3.4 Resend |
| 0xF004 | § 3.3.5 Stream control |
Note: Range 0x8000 to 0x80FF is reserved for § 3.3 Reverse signalling.
Note: The 16-bit descriptor may be split into two sections, a constant upper 8-bits and variable bottom 8-bits, hence some descriptors are considered a range.
Anything not specified in the table is reserved and must not be used. Demuxers must ignore unknown packets. Future additions will require a version bump of the protocol, but are expected to be backwards compatible.
1.3. Specification conventions
Throughout all of this document, bit sequences are always big-endian, and numbers are always two’s complement.
A special notation is used to describe sequences of bits:
-
u(N): specifies the data that follows is an unsigned integer of N bits. -
i(N): the same, but the data describes a signed integer is signed. -
b(N): the data is an opaque sequence of N bits that clients must not interpret. -
R(N): the data is a rational number, with a numerator (num) ofi(N/2)and following that, a denominator (den) ofi(N/2). The denominator must be greater than 0.
All packets are at least 36 bytes long (288 bits), and always have an 8 byte (64 bits) § 1.4 LDPC code after the first 28 bytes to verify and correct their data.
Identification of the packet is always possible via the first two bytes (the descriptor).
All floating point samples and pixels are always normalized to fit within the
interval [-1.0, 1.0].
Padding may be present in some packets (padding). Unless otherwise indicated, the data in padding must be 0x0.
Note: This document is machine-parseable. Each symbol of a packet or enum has an assigned ID of the form descriptor in hex+index, where index is a number starting from 0, incremented for each element in a structure.
1.4. LDPC
To improve reliability, and make the protocol general-purpose, a small amount of parity data is added to each header, in the form of [LDPC].
Their main purpose is to correct bitflips which may occur during transmission or
storage of packets.
In situations where bitflips are less likely, they eliminate corrupt packets
which may break demuxer state.
Being able to quickly determine whether any 36 or more byte buffer contains a valid packet
makes AVTransport streams self-synchronizing.
This makes AVTransport suitable for not only switched networks, but also raw radio frequency links, optical links, or plain serial links. Details for each are available in the § 3.2 Streaming section.
Their theory of operation and specifications are detailed in § 4.3 Annex W: LDPC.
To simplify implementations, two different lengths are used:
-
ldpc_288_224: specified in LDPC(288, 224)
-
ldpc_2784_2016: specified in LDPC(2784, 2016)
Note: Applying LDPC error correction is optional for receiver implementations.
Senders must implement it. This document provides example routines in § 4.3 Annex W: LDPC.
1.5. Global sequence
The global_seq is a 32-bit unsigned integer, incremented by 1 each time after a packet has been sent. Once at 0xffffffff, it MUST overflow back to 0x0. This overflow MUST be handled by the receiver.
Note: global_seq should start at 0x0, but receivers MUST be prepared for any starting offset.
1.6. Stream ID
stream_id is a 16-bit unsigned integer, uniquely identifying each stream contained within an AVTransport stream.
Note: Senders should never reuse stream_id indices, but receivers should be prepared to deal with this scenario.
1.7. Timestamps
AVTransport supports high resolution timestamps, with a maximum resolution of 465.66129 picoseconds. Furthermore, the reliability of the timestamps can be assured through optional § 1.8.1 Jitter compensation.
All time-related fields (pts, dts, duration, and skip_preroll) have a corresponding timebase field with which to interpret them.
The mathematical expression to calculate the time t, in seconds, of a timestamp
or duration v and a rational timebase b is the following:
t = v * b.num / b.den
Note: All mathematical operations on timestamps should be done in the integer domain, as floating-point operations may be inaccurate and inconsistent.
The timebase of § 2.6 Stream Data, § 2.19 Stream duration, or any other packets with an explicit stream_id field is given in the § 2.3 Stream registration packets for the appropriate stream.
The time t of a pts field corresponds to the exact time when a packet must be
instantaneously released from a decoding buffer, and instantaneously presented.
The time t of a dts field corresponds to the exact time when a packet must be
input into a synchronous 1-in-1-out decoder. The dts field is defined as part
of the payload when necessary (§ 3.1 Codec encapsulation).
The time t of a duration field corresponds to the exact time difference between
two consecutive frames of audio or video. If the field is non-zero, this assertion
MUST hold. If this condition is violated, the behavior is unspecified.
1.8. Subtitle timestamps
For subtitle frames, the duration field’s definition is different. It specifies the time during which the contents of the current packet must be presented.
Unlike video or audio, subtitle packets are allowed to have overlapping timestamps. This means that players should be simultaneously presenting all subtitles on screen whose duration indicates that they should be on screen.
For exact information on how this should be done, implementors are invited to view the specifications of each encapsulated subtitle format.
Additionally, for subtitles, duration has two special values:
-
duration equal to zero has the special meaning of clearing all currently presented subtitles, even if their duration value overlaps with the current pts.
-
duration of exactly INT64_MIN (-9223372036854775808) has the special meaning of presenting this subtitle until another subtitle packet appears.
Implementations are welcome to normalize subtitle timestamps and remove any occurrences of the two special values.
1.8.1. Jitter compensation
Implementations should use the derived ts_clock_freq field from § 2.2 Time synchronization packets to perform jitter compensation of stream timestamps.
The ts_clock_id is a unique 8-bit identifier for the clock. It allows to associate a clock with a given stream. A value of zero indicates the stream has no associated clock.
The ts_clock_id of the § 2.3 Stream registration packets is matched up to the ts_clock_id of § 2.2 Time synchronization packets. If a match is not found, then no processing must be done.
Note: The only valid targets to perform timestamp jitter compensation are streams with the same timebase, which must be equal to the inverse of ts_clock_freq. Jitter compensation is otherwise undefined.
As the ts_clock_freq field defines a strictly monotonic clock signal with a rate of ts_clock_freq, which atomically increments a counter, ts_clock_seq on the rising edge of the waveform, this can be used to compensate the pts, dts and duration values of stream packets.
The following is a suggestion for implementations:
-
Initialize a phase-locked loop, with a frequency equal to ts_clock_freq.
-
Initialize a counter, local_ts_clock_seq, to be equal to ts_clock_seq.
-
Increment the local_ts_clock_seq on the rising edge of the local oscillator’s waveform.
On every received packet:
-
Measure the difference Δ between pts and local_ts_clock_seq.
-
If Δ is small, assume pts has jitter, and replace it with local_ts_clock_seq
-
Otherwise, add Δ to local_ts_clock_seq.
This is a very simple example which depends on the local receiver oscillator simply being more precise than the transmitter’s oscillator.
Note: The way receivers handle jitter is intentionally left undefined. As a recommendation, implementations should resampple the audio and adjust video frame duration such that synchronization is maintained. Otherwise, implementations can drop or duplicate frames.
1.8.2. Negative times
The time t of a pts may be negative. Packets with a negative timestamps
must be decoded, but not presented.
For audio packets, this corresponds to the internal algorithmic delay between
the first output sample and the correct sample being available.
For audio, the time between t and 0 may not be a multiple of the
audio data’s duration of a packet. Implementations must nevertheless remove any
decoded samples with a negative time.
Negative pts values are allowed, and implementations must decode such frames,
however must not present any such frames unless pts + duration
is greater than 0, in which case they must present the data required for that duration.
This enables removal of extra samples added during audio compression, as well
as permitting video segments taken out of context from a stream to bundle
all dependencies (other frames) required for their presentation.
1.8.3. Epoch definition
The epoch field of § 2.2 Time synchronization packets is an optional field.
If non-zero, it MUST signal the exact time, in nanoseconds, since 00:00:00 UTC on 1 January 1970, according to the transmitter’s wall clock time, of the stream starting. If a start time is not known, it MUST be zero. Once a stream has started, it MUST NOT be changed.
The user is allowed to handle the field in the following ways:
| Action | Description |
|---|---|
| Use as metadata | The epoch field is used to override § 2.12 Metadata packet’s date field.
|
| Ignore | The field is completely ignored. |
| Stream duration | The field is used to measure the total time the stream has been operational. |
| Stream latency | The field is used to measure latency. |
| Synchronization | The field is used to synchronize several unconnected receivers. |
By default, implementations must use the field as metadata, if present. Otherwise, they should ignore it.
Users are free to use the field to measure the stream duration by converting the t of the pts
field of any stream’s packet to nanoseconds (multiply by 1000000000), rounding it, and subtracting
it from the epoch time (t - epoch).
Users are also free to measure the latency in a similar way, by measuring their current wallclock time
t, and using Δ = t' - t - epoch. Δ will be the delay in nanoseconds.
Finally, if explicitly requested, implementations are allowed to delay presentation by interpreting a negative latency value of Δ as a delay.
Note: Packets which had a negative timestamp before must still be dropped to permit for correct decoding and presentation.
Note: The stream latency and synchronization actions depend on all devices having accurately synchronized clocks. This protocol does not guarantee, nor specify this, as this is outside its scope. Users can use the Network Time Protocol (NTP), specified in [RFC5905], or any other protocol to synchronize clocks, or simply assume all device are already synchronized.
1.9. URI scheme
The recommended URI scheme is:
avt://[<transport>[:<mode>]@]<address>[:<port>][/[<sender_uuid>][#<params>]]
-
<transport> may be either missing (default: udp) or:
-
udp: for § 3.2.1 UDP streams
-
quic: for § 3.2.2 QUIC streams
-
file: for local files
-
-
<mode> is an optional setting which has different meanings for senders and receivers:
-
Sender:
-
active: the default value. Means to start continuously sending packets to the given address without attempting bidirectional communication.
-
passive means to wait for receivers to send packets on the given address to begin transmitting back to them.
-
-
Receiver:
-
passive: the default value. means to listen on the given address for any packets received without attempting to connect and requesting for data.
-
active:means that receivers will actively connect and try to request a stream from the target address.
-
-
-
<address> of the remote host, or local host, multicast group, or local file.
-
<port> on which to listen on/transmit to. Only valid for udp, and quic protocols. If not specified, port 8212 shall be the default port.
-
<sender_uuid> is an optional, unique, pre-shared 128-bit UUID ([RFC9562]) value.
-
<params> are a <key>=<value> pair of settings for the connection, separated by an
&sign:-
default=<stream_id1>,<stream_id2>: Specifies streams to assign as being the default
-
The syntax complies with [RFC8820] and can be parsed by existing code. Implementations are free to extend the syntax.
Note: Alternatively, for UDP-only, the udp://<address>:<port> URI scheme may be used,
at the risk of conflict with other protocols (MPEG-TS or Matroska).
Note: When handling AVTransport files, it is recommended to use the .avt file extension. Alternatively, for image-only files, .ati is recommended, and for subtitles, the recommendation is .avs.
1.9.1. MIME type
AVTransport shall use the following MIME types:
-
video/avt for video-only AVTransport files
-
audio/avt for audio-only AVTransport files
-
application/avt for all other AVTransport files
2. Packet structure
This section lists the syntax of each individual packet type and specifies its purpose, and rules about its usage.
Special considerations and suggestions which need to be taken into account in a streaming scenario are described in the § 3.2 Streaming section.
2.1. Session start
Session start packets allow receivers to plausibly identify a stream of bytes as an AVTransport session. The syntax is as follows:
| Type | Name | Data | Description |
|---|---|---|---|
b(16)
| session_start_descriptor | 0x4156 | Indicates this is a AVTransport session (`AV`). |
b(16)
| session_version | 0x5430 | Indicates the session version. This document describes version `21552` (`T0`). |
u(32)
| global_seq | Monotonically incrementing per-packet global sequence number. | |
16*b(8)
| session_uuid | UUID | Lasting session UUID. |
u(32)
| session_seq | 32-bit current session sequence number. | |
b(64)
| ldpc_288_224 | LDPC(288, 224) | 64-bits of LDPC parity data to correct the previous 224 bits of the packet. |
u(16)
| session_flags | enum SessionFlags
| Session flags. |
16*b(8)
| producer_name | fixed-length string | 16-byte UTF-8 string, containing the name of the producer. |
u(16)
| producer_major | Major version of the producer. | |
u(16)
| producer_minor | Minor version of the producer. | |
u(16)
| producer_micro | Micro version of the producer. | |
b(32)
| padding | Padding, reserved for future use. Must be 0x0. | |
b(64)
| ldpc_288_224 | LDPC(288, 224) | 64-bits of LDPC parity data to correct the previous 224 bits of the packet. |
Multiple session packets may be present in a session, but must remain bytewise-identical.
The producer_name field is a fixed-length string, meaning that the field is always 16 bytes. If the name is less than 16 bytes, it must be zero-padded.
session_uuid is a long-term pre-agreed token between the sender and receiver. It is meant to represent a user ID, or a generic access token. If no pre-agreed token is required, it must contain random data.
session_seq is an ephemeral ID that is supposed to change each time a transmission is initiated. It is meant to help with longer duration disconnections.
2.1.1. Stream Session Flags Enumeration (enum SessionFlags)
The session_flags field must be interpreted in the following way:
SESSION_REVERSE_SIGNAL_READY= 0x1-
Indicates session is capable and ready to receive § 3.3 Reverse signalling packets.
Implementations can test the first 4 bytes to detect a AVTransport stream.
The LDPC data is, like for all packets, allowed to be ignored by receivers.
2.2. Time synchronization
Time synchronization packets are optional dual-purpose packets which signal:
-
A context for all timestamps in all streams, using a field called epoch, which denotes an absolute basis in time, to allow for optional receiver synchronization.
-
A device clock counter (ts_clock_seq) and clock frequency (ts_clock_freq), to allow for accurate clock cycle synchronization of packet timestamps, stream synchronization, and to enable clock drift and jitter compensation.
The structure of the data in a § 2.2 Time synchronization packet is as follows:
| Type | Name | Data | Description |
|---|---|---|---|
b(8)
| time_sync_descriptor | 0x03 | Indicates this is a time synchronization packet. |
b(8)
| ts_clock_id | Signals the clock ID for this clock. A value of 0 indicates this packet only carries epoch data. | |
u(16)
| ts_clock_hz2 | Value, in multiples of 1/65536 Hz, to be added to ts_clock_hz to make ts_clock_freq. | |
u(32)
| global_seq | Monotonically incrementing per-packet global sequence number. | |
u(64)
| epoch | Indicates absolute time, in nanoseconds since 00:00:00 UTC on 1 January 1970. [UNIX-time] | |
u(64)
| ts_clock_seq | Monotonically incrementing counter, incremented once for each cycle of the device clock, at a rate of ts_clock_freq per second. | |
u(32)
| ts_clock_hz | Hertz value of the device clock. | |
b(64)
| ldpc_288_224 | LDPC(288, 224) | 64-bits of LDPC parity data to correct the previous 224 bits of the packet. |
The ts_clock_freq field is equal to ts_clock_freq = ts_clock_hz + ts_clock_hz2/65536.
Implementations should prefer to use integer math, and instead have the ts_clock_freq in increments of 1/65536 Hz.
Note: If ts_clock_freq is 0, then the sender should be assumed to be relying entirely on its real-time clock.
The field defines a strictly monotonic clock signal with a rate of ts_clock_freq, which atomically increments a counter, ts_clock_seq on the rising edge of the waveform.
To interpret the clock, read the § 1.8.1 Jitter compensation section. Senders should send time synchronization packets as often as necessary to prevent clock drift and jitter.
In case of a zero ts_clock_hz, the sender must be assumed to not provide a clock signal reference, and the timestamps MUST be interpreted as being, in the receiver’s understanding, realtime.
The epoch is a global, optional field that receivers may interpret.
The epoch value must not change between packets.
The epoch is an absolute starting point, for all timestamps in
all streams, in nanoseconds since 00:00:00 UTC on 1 January 1970 ([UNIX-time]).
The possible applications of the epoch field are described in the § 1.8.3 Epoch definition section.
2.3. Stream registration
This packet is used to signal stream registration.
The layout of the data is as follows:
| Type | Name | Data | Description |
|---|---|---|---|
b(16)
| stream_registration_descriptor | 0x0002 | Indicates this is a Indicates this is a stream registration packet. |
b(16)
| stream_id | Indicates the stream ID for the new stream to be registered. | |
u(32)
| global_seq | Monotonically incrementing per-packet global sequence number. | |
b(16)
| related_stream_id | Indicates the stream ID for which this stream is related to. Relations are defined by StreamFlags set in stream_flags. Must be 0xFFFF if this stream has no relations.
| |
b(16)
| derived_stream_id | Indicates the stream ID for which this stream is derived from. Derivation is defined by StreamFlags set in stream_flags. Must be 0xFFFF if this stream is not derived from any other stream.
| |
u(64)
| bandwidth | Average bitrate in bits per second. MAY be 0 to indicate VBR or unknown. | |
b(64)
| stream_flags | enum StreamFlags
| Flags to indicate the type of stream. |
b(64)
| ldpc_288_224 | LDPC(288, 224) | 64-bits of LDPC parity data to correct the previous 224 bits of the packet. |
b(32)
| codec_id | Indicates the codec ID for the data packets in this stream. | |
R(64)
| timebase | Signals the timebase of the timestamps present in the § 2.6 Stream Data packets. | |
b(8)
| ts_clock_id | An 8-bit non-zero clock ID identifier to associate a stream with a given clock. | |
i(64)
| skip_preroll | Amount of time in `timebase` units to skip immediately after seeking or reinitializing. | |
u(32)
| init_packets | enum StreamInitPackets
| Flags to indicate which packets should be received before decoding or presenting any stream data packets. |
b(24)
| padding | Padding, reserved for future use. Must be 0x0. | |
b(64)
| ldpc_288_224 | LDPC(288, 224) | 64-bits of LDPC parity data to correct the previous 224 bits of the packet. |
This packet may be sent for an already-initialized stream. The bandwidth field and the stream_flags fields may change, however the codec_id, timebase AND related_stream_id fields must remain the same. If the latter are to change an § 2.20 End of stream packet must be sent first.
The skip_preroll field is a duration in timebase units to signal how much to skip after reinitializing or seeking. The duration of negative timestamps at the start of streams must be at least as long as the skip_preroll.
2.3.1. Stream Init Packets Enumeration (enum StreamInitPackets)
The init_packets field indicates which packets are required, and will be transmitted, for the stream to be correctly decoded and presented. It MUST be interpreted as follows:
STREAM_INIT_PKT_METADATA= 0x1-
Stream requires a § 2.12 Metadata packet in order to be fully initialized.
STREAM_INIT_PKT_STREAM_DURATION= 0x2-
Stream requires a § 2.19 Stream duration packet in order to be fully initialized.
STREAM_INIT_PKT_CONFIG_DATA= 0x4-
Stream requires a § 2.5 Stream configuration packet in order to be fully initialized.
STREAM_INIT_PKT_VIDEO_INFO= 0x8-
Stream requires a § 2.15 Video information packet in order to be fully initialized.
STREAM_INIT_PKT_LUT_ICC= 0x10-
Stream requires a § 2.13 LUT/ICC profile packet in order to be fully initialized.
STREAM_INIT_PKT_FONT_DATA= 0x20-
Stream requires a § 2.14 Font data packet in order to be fully initialized.
Implementations MUST wait to parse the packets signalled before exposing the new stream and decoding/presenting packets from it.
2.3.2. Stream Flags Enumeration (enum StreamFlags)
The stream_flag field provides context for the stream. It MUST be interpreted in the following manner:
STREAM_SUBTITLES= 0x1-
Stream contains timed text.
STREAM_DEFAULT= 0x2-
Stream should be chosen by default amongst other streams of the same type, unless the user has specified otherwise.
STREAM_STILL_PICTURE= 0x4-
Stream is a still picture and only a single decodable frame will be sent.
STREAM_COVER_ART= 0x8-
Stream is a cover art picture for the stream signalled in related_stream_id.
STREAM_LOW_QUALITY= 0x10-
Stream is a lower quality version of the stream signalled in derived_stream_id.
STREAM_DUB= 0x20-
Stream is a dubbed version of the stream signalled in related_stream_id.
STREAM_COMMENTARY= 0x40-
Stream is a commentary track to the stream signalled in related_stream_id.
STREAM_LYRICS= 0x80-
Stream is a lyrics track to the stream signalled in related_stream_id.
STREAM_KARAOKE= 0x100-
Stream is a karaoke track to the stream signalled in related_stream_id.
STREAM_HEARING_IMPAIRED= 0x200-
Stream is intended for hearing impaired audiences.
Note: If related_stream_id is not equal to stream_id, both should be mixed in.
STREAM_VISUALLY_IMPAIRED= 0x400-
Stream is intended for visually impaired audiences.
Note: If related_stream_id is not equal to stream_id, both should be mixed in.
STREAM_NO_DIALOGUE= 0x800-
Stream contains music and sound effects without voice.
STREAM_NON_DIEGETIC= 0x1000-
Stream contains non-diegetic audio.
Note: If related_stream_id is not equal to stream_id, both should be mixed in.
STREAM_DESCRIPTIONS= 0x2000-
Stream contains textual or spoken descriptions to the stream signalled in related_stream_id.
STREAM_TIMING_METADATA= 0x4000-
Stream contains timed metadata and is not intended to be directly presented to the user.
STREAM_THUMBNAILS= 0x8000-
Stream contains temporally sparse thumbnails to the stream signalled in related_stream_id.
STREAM_BINAURAL= 0x10000-
Stream contains binaural audio. If set, pre-processing for headphones should be disabled.
STREAM_MULTILAYER= 0x20000-
Stream contains multiple layers in the codec bitstream. For example, alternative views.
Several streams can be chained with the STREAM_LOW_QUALITY bit set to indicate
progressively lower quality/bitrate versions of the same stream. The very first
stream in the chain MUST NOT have bit STREAM_LOW_QUALITY set.
Sparse thumbnail streams may exactly match chapters from related_stream_id, but could be sparser or more frequent.
If bits STREAM_COVER_ART, STREAM_DUB, STREAM_COMMENTARY, STREAM_LYRICS,
STREAM_KARAOKE, STREAM_HEARING_IMPAIRED are all unset, then
related_stream_id must match stream_id, otherwise the stream with a
related different ID must exist.
2.4. Generic data
To ease parsing, the specification defines a common template for data that requires no special treatment, but only differ by descriptor.
This way, any generic data can share a common code path, have parity data and be a part of an § 2.8 FEC grouping packet.
The following template shall be used for generic data packets:
| Type | Name | Data | Description |
|---|---|---|---|
b(16)
| generic_data_descriptor | as specified | Indicates the data packet type. Defined in later sections. |
b(16)
| stream_id | Indicates the stream ID for which this packet is applicable. | |
u(32)
| global_seq | Monotonically incrementing per-packet global sequence number. | |
u(32)
| total_payload_length | The total size of all data needed to receive the payload correctly. Must be either 0 if unknown, or the total size of the payload across all segments. | |
i(64)
| pts | Indicates the presentation timestamp for when this data becomes valid at. To interpret the value, read the § 1.7 Timestamps section. | |
u(32)
| payload_length | The size of the data in this packet. | |
u(8)
| generic_data_compression | enum DataCompression
| Type of data compression used. |
b(24)
| padding | Padding, reserved for future use. MUST be 0x0. | |
b(64)
| ldpc_288_224 | LDPC(288, 224) | 64-bits of LDPC parity data to correct the previous 224 bits of the packet. |
payload_length*b(8)
| generic_payload | payload | The packet data itself. |
2.4.1. Generic data segmentation
In case the data needs to be segmented, the following template has to be used for segments that follow the above:
| Type | Name | Data | Description |
|---|---|---|---|
b(16)
| generic_segment_descriptor | as specified | Indicates the segment type. Defined in later sections along with generic_data_descriptor. |
b(16)
| stream_id | Indicates the stream ID for which this packet is applicable. | |
u(32)
| global_seq | Monotonically incrementing per-packet global sequence number. | |
b(32)
| target_seq | The sequence number of the starting § 2.4 Generic data packet. | |
u(32)
| pkt_total_data | Total number of data bytes, including the first data packet’s, and ending segment’s. | |
u(32)
| seg_offset | The offset since the start of the data where the segment starts. | |
u(32)
| seg_length | The size of the data segment. | |
4*b(8)
| header_7 | A seventh of the starting § 2.4 Generic data header. The part taken is determined by global_seq % 7.
| |
b(64)
| ldpc_288_224 | LDPC(288, 224) | 64-bits of LDPC parity data to correct the previous 224 bits of the packet. |
seg_length*b(8)
| generic_segment_payload | payload | The data for the segment. |
If the data in a § 2.4 Generic data packet is to be segmented, it will have a different descriptor. The generic_segment_descriptor shall be different for segments that finalize the data.
The header_7 field can be used to reconstruct the header of the very first packet in order to determine the timestamps and data type.
Note: Segments are forbidden from partially overlapping. Each segment’s offset and size must either completely overlap with another segment (such as when retransmitting lost packets), or must fit in between two segments perfectly.
2.4.2. Generic data parity
Finally, in case the data requires parity data (FEC, but only on the current packet), the following § 2.4 Generic data structure is to be used:
| Type | Name | Data | Description |
|---|---|---|---|
b(16)
| generic_parity_descriptor | as specified | Indicates this packet carries parity. Defined in later sections along with generic_data_descriptor. |
b(16)
| stream_id | Indicates the stream ID for which this packet is applicable. | |
u(32)
| global_seq | Monotonically incrementing per-packet global sequence number. | |
b(32)
| target_seq | The sequence number of the starting § 2.4 Generic data packet. | |
u(32)
| parity_data_offset | The byte offset for the RaptorQ parity data for this parity data packet protects. | |
u(32)
| parity_data_length | The length of the RaptorQ data in this packet. | |
u(32)
| parity_total | The total amount of payload bytes across all parity data packets. | |
4*b(8)
| header_7 | A seventh of the starting § 2.4 Generic data header. The part taken is determined by global_seq % 7.
| |
b(64)
| ldpc_288_224 | LDPC(288, 224) | 64-bits of LDPC parity data to correct the previous 224 bits of the packet. |
parity_data_length*b(8)
| parity_data_payload | payload | The RaptorQ parity data that can be used to check or correct the previous data packet’s payload. |
The data in an parity packet MUST be systematic RaptorQ, as per [RFC6330].
Common FEC Object Transmission Information (OTI) format and Scheme-Specific FEC
Object Transmission Information as described in the document are never used.
The FEC symbol size MUST be 128 bytes.
The header_7 field can be used to reconstruct the header of the very first packet in order to determine the timestamps and data type.
2.5. Stream configuration
Codecs generally require a one-off special piece of data needed to initialize them.
To provide this data to receivers, the templates defined in the MUST be used, with the following descriptors:
| Descriptor value | Name | Structure | Description |
|---|---|---|---|
| 0x0003 | stream_config_descriptor | § 2.4 Generic data | Codec initialization data. |
| 0x0004 | stream_config_segment_descriptor | § 2.4.1 Generic data segmentation | Non-final segment for segmented codec configuration. |
| 0x0005 | stream_config_parity_descriptor | § 2.4.2 Generic data parity | Parity data for codec configuration data. |
For more information on the layout of the specific data, consult the § 3.1 Codec encapsulation addendum.
However, in general, the data follows the same layout as what [FFmpeg]’s libavcodec produces and requires.
An implementation may error out in case it cannot handle the data in the payload. If so, when reading a file, it must stop, otherwise in a live scenario, it must send an unsupported § 3.3.1 Session control data packet, if such a connection is open.
2.6. Stream Data
The data packets indicate the start of a stream packet, which may be fragmented into more § 2.6.3 Stream data segmentation. It is laid out as follows:
| Type | Name | Data | Description | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
b(16)
| stream_data_descriptor_structure |
| |||||||||||||||||||
b(16)
| stream_id | Indicates the stream ID for which this packet is applicable. | |||||||||||||||||||
u(32)
| global_seq | Monotonically incrementing per-packet global sequence number. | |||||||||||||||||||
i(64)
| pts | Indicates the presentation timestamp for when this frame should be presented at. To interpret the value, read the § 1.7 Timestamps section. | |||||||||||||||||||
i(64)
| duration | The duration of this packet in stream timebase unis. | |||||||||||||||||||
u(32)
| data_length | The size of the data in this packet. | |||||||||||||||||||
b(64)
| ldpc_288_224 | LDPC(288, 224) | 64-bits of LDPC parity data to correct the previous 224 bits of the packet. | ||||||||||||||||||
data_length*b(8)
| packet_data | payload | The packet data itself. |
For information on the layout of the specific codec-specific packet data, consult the § 3.1 Codec encapsulation addenda.
2.6.1. Frame Type Enumeration (enum FrameType)
FRAME_TYPE_KEY= 0x0-
Packet data contains a keyframe, able to be decoded standalone.
FRAME_TYPE_S= 0x1-
Packet data contains a scalable/switch frame, able to be decoded standalone, with acceptable degradation.
FRAME_TYPE_P= 0x2-
Packet data contains an inter frame, requiring additional reference frames in order to be validly decoded.
2.6.2. Data Compression Enumeration (enum DataCompression)
DATA_COMPRESSION_NONE= 0x0-
Packet data is uncompressed
DATA_COMPRESSION_ZSTD= 0x1-
Packet data is compressed with Zstandard, defined in IETF [RFC8878].
Note: Zstandard is a general purpose format, suitable for images, audio, and binary data such as TTF, OTF, ICC, or CUBE packets. Therefore, it should be the preferred format for such payloads.
DATA_COMPRESSION_BROTLI= 0x2-
Packet data is compressed with Zstandard, defined in IETF [RFC7932].
Note: Brotli is more optimized for text rather than generic data, and should be the preferred format for subtitles. Presently, it is also more supported on the web.
Any undefined values are hereby reserved and must not be present in a compliant AVTransport stream with this version.
2.6.3. Stream data segmentation
Packets can be split up into separate chunks that may be received out of order and assembled. This allows transmission over switched networks with a limited MTU, or prevents very large packets from one stream interfering with another stream. The packet structure used for segments is the § 2.4.1 Generic data segmentation from § 2.4 Generic data, with the following descriptors:
| Descriptor value | Name | Structure | Description |
|---|---|---|---|
| 0x00FF | stream_data_segment_descriptor | § 2.4.1 Generic data segmentation | Non-final segment for segmented codec configuration. |
The size of the final assembled packet is the sum of all seg_length fields, plus the data_length field from the § 2.6 Stream Data.
Data segments and packets may arrive out of order and be duplicated. Implementations must reorder them, deduplicate them and assemble them into complete packets.
Implementations may try to decode incomplete data packets with missing segments due to latency concerns.
Senders may send duplicate segments to compensate for packet loss, but should use § 2.8 FEC grouping or § 2.9 Stream data parity instead.
Implementations should discard any packets and segments that arrive after their presentation time. Implementations should drop any packets and segments that arrive with unrealistically far away presentation times.
2.7. Extended stream data
Depending upon the codec, using an extended stream data header may be required. It is laid out in the following way:
| Type | Name | Data | Description | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
b(16)
| extended_stream_data_descriptor_structure |
| |||||||||||||||||||
b(16)
| stream_id | Indicates the stream ID for which this packet is applicable. | |||||||||||||||||||
u(32)
| global_seq | Monotonically incrementing per-packet global sequence number. | |||||||||||||||||||
i(64)
| pts | Indicates the presentation timestamp for when this frame should be presented at. To interpret the value, read the § 1.7 Timestamps section. | |||||||||||||||||||
i(64)
| dts | Indicates the timestamp for when to input this frame should be input into the decoder. To interpret the value, read the § 1.7 Timestamps section. | |||||||||||||||||||
u(32)
| data_length | The size of the data in this packet. | |||||||||||||||||||
b(64)
| ldpc_288_224 | LDPC(288, 224) | 64-bits of LDPC parity data to correct the previous 224 bits of the packet. | ||||||||||||||||||
i(64)
| duration | The duration of this packet in stream timebase unis. | |||||||||||||||||||
u(32)
| total_data_length | The total size of all data needed to receive the payload correctly. Must be either 0 if unknown, or the total size of the payload across all segments. | |||||||||||||||||||
u(16)
| side_data_desc_1 | If not equal to 0xFFFF, it means this packet depends on another packet with the given descriptor for correct decoding or presentation. | |||||||||||||||||||
u(32)
| side_data_seq_1 | If side_data_desc_1 is non-0xFFFF, a valid sequence ID for the side data packet. | |||||||||||||||||||
u(16)
| side_data_desc_2 | If not equal to 0xFFFF, it means this packet depends on another packet with the given descriptor for correct decoding or presentation. | |||||||||||||||||||
u(32)
| side_data_seq_2 | If side_data_desc_2 is non-0xFFFF, a valid sequence ID for the side data packet. | |||||||||||||||||||
b(32)
| padding | Padding, reserved for future use. MUST be 0x0. | |||||||||||||||||||
b(64)
| ldpc_288_224 | LDPC(288, 224) | 64-bits of LDPC parity data to correct the previous 224 bits of the packet. | ||||||||||||||||||
data_length*b(8)
| packet_data | payload | The packet data itself. |
Extended stream data packets should only be used if there’s a need to use them. Regular stream data packets have a much lower overhead.
2.8. FEC grouping
Whilst it’s possible to send uncontextualized FEC data backing individual packets, for most applications, this is only feasible for very high bitrate single streams, as modern FEC algorithms are highly optimized for packet erasure recovery.
FEC grouping allows for multiple buffered packets and segments from multiple streams to be FEC corrected in order to ensure no stream is starved of data.
FEC grouped streams must be registered first via a special packet:
| Type | Name | Data | Description |
|---|---|---|---|
b(16)
| fec_grouping_descriptor | 0x0030 | Indicates this is an FEC grouping packet. |
b(16)
| group_id |
Indicates the ID for this FEC grouping. Note: Must not overlap with stream_id. | |
u(32)
| global_seq | Monotonically incrementing per-packet global sequence number. | |
u(8)
| fec_grouping_streams | Number of streams in the FEC group. Must be less than or equal to 16. | |
b(64)
| fec_common_oti | RaptorQ Forward Error Correction Scheme for Object Delivery § section-3.3.2 | [RFC6330], RaptorQ Common FEC Object Transmission Information. |
b(32)
| fec_scheme_oti | RaptorQ Forward Error Correction Scheme for Object Delivery § section-3.3.3 | [RFC6330], RaptorQ Scheme-Specific FEC Object Transmission Information. |
u(32)
| fec_start_global_seq | The global sequence number of the very first packet in the FEC group. | |
b(24)
| padding | Padding, reserved for future use. MUST be 0x0. | |
b(64)
| ldpc_288_224 | LDPC(288, 224) | 64-bits of LDPC parity data to correct the previous 224 bits of the packet. |
16*u(32)
| fec_nb_packets | Total number of packets for each stream in the FEC group. | |
16*u(32)
| fec_seq_number | The sequence number of the first packet for the stream to be included in the group. | |
b(992)
| padding | Padding, reserved for future use. MUST be 0x0. | |
b(768)
| ldpc_2784_2016 | LDPC(2784, 2016) | 768-bits of LDPC parity data to correct the previous 2016 bits of the packet. |
It is hightly recommended that the common OTI parameters never change once transmitted. This lets implementations attempt to apply FEC if they miss a § 2.8 FEC grouping packet.
The fec_scheme_oti field must be interpreted as the following, given in RaptorQ Forward Error Correction Scheme for Object Delivery § section-3.3.3:
All streams in an FEC group must have timestamps that cover the same period of time.
A stream may only be part of a single FEC group at any one time. Sending a new grouping that includes an already grouped stream will destroy the previous grouping.
To end a grouping prematurely, one can send an end of stream packet with the group’s ID.
FEC groups use a different packet for the FEC data.
| Type | Name | Data | Description |
|---|---|---|---|
b(16)
| fec_group_data_descriptor | 0x0031 | Indicates this is an FEC group data packet. |
b(16)
| group_id | Indicates the FEC grouping for which this packet has data for. | |
u(32)
| global_seq | Monotonically incrementing per-packet global sequence number. | |
u(32)
| fec_data_offset | The byte offset for the FEC data for this FEC packet protects. | |
u(32)
| fec_data_length | The length of the FEC data in this packet. | |
u(32)
| fec_total_data_length | The total amount of bytes in the FEC grouping data. | |
b(64)
| fec_source_1 | § 2.8.1 FEC Group Source | Provides a single source packet which contains data to be forward error corrected. |
b(64)
| ldpc_288_224 | LDPC(288, 224) | 64-bits of LDPC parity data to correct the previous 224 bits of the packet. |
3*b(64)
| fec_source_234 | § 2.8.1 FEC Group Source | Provides another three source packet which contains data to be forward error corrected. |
b(32)
| padding | Padding, reserved for future use. MUST be 0x0. | |
b(64)
| ldpc_288_224 | LDPC(288, 224) | 64-bits of LDPC parity data to correct the previous 224 bits of the packet. |
fec_data_length*b(8)
| fec_data | payload | The FEC data that can be used to check or correct the previous data packet’s payload. |
The fec_source data is defined as follows:
2.8.1. FEC Group Source
| Type | Name | Value | Description |
|---|---|---|---|
u(32)
| fec_source_seq | Indicates a single packet’s global_seq which is to be backed by this FEC group. | |
u(16)
| fec_source_blk | Indicates the FEC source block to which the signaled packet belongs to. | |
u(16)
| fec_symbol_id | Indicates the symbol ID of the packet for the source block. |
Each § 2.8.1 FEC Group Source structure MUST reference a valid packet, in transmission order. If there are no more valid packets to reference, the sender must start repeating from the very first FEC source.
To perform FEC, first, concatenate each packet (header and payload) referenced into each source block, in order of the source symbol ID. Then, perform the procedure to apply FEC as described by RaptorQ Forward Error Correction Scheme for Object Delivery § section-4.4.1.
2.9. Stream data parity
Stream data packets and segments may individually be backed by data packets. The structure used for segments follows the § 2.4.2 Generic data parity template from the § 2.4 Generic data section, with the following descriptor:
| Descriptor value | Name | Structure | Description |
|---|---|---|---|
| 0x00FE | stream_data_parity_descriptor | § 2.4.2 Generic data parity | Parity data segment for individual stream data packets. |
Implementations may discard the FEC data, or may delay the previous packet’s decoding to correct it with the FEC data, or may attempt to decode the uncorrected packet data, and if failed, retry with the corrected data packet.
The data in an FEC packet must be RaptorQ, as per [RFC6330]. The symbol size must be 128 bytes.
The same lifetime and duplication rules apply for parity packets as they do for regular data segments.
2.10. Hash packets
For some niche cases, AVTransport provides the ability to signal a hash for the packet. This is purely optional for both senders and receivers to signal and interpret.
Note: Most filesystems, interfaces and protocols provide a CRC. While this hash is much more resistant to bitflips and secure, it is recommended to use this in cases like long-term archival, or raw RF links (to avoid retransmissions for corrupt packets).
The hash cover exactly one payload-carrying packet’s payload.
| Type | Name | Data | Description |
|---|---|---|---|
b(16)
| hash_data_descriptor | 0x0009 | Indicates this is a hash packet. |
b(16)
| stream_id | Indicates the stream ID of the target packet. May be 0xFFFF, in which case, it applies to all streams. | |
u(32)
| global_seq | Monotonically incrementing per-packet global sequence number. | |
u(32)
| hash_target | Indicates the sequence number of the packet for which this hash applies for. | |
16*b(8)
| hash_data | XXH128 of the target packet’s payload. | |
b(64)
| ldpc_288_224 | LDPC(288, 224) | 64-bits of LDPC parity data to correct the previous 224 bits of the packet. |
The hashing algorithm used is [XXHASH], with a length of 128-bits (referred to as XXH128 by the authors).
If present in an AVTransport stream, this packet should be sent before the hash_target packet is transmitted.
Demuxers are not required to process this packet or verify that the target packet’s data is received correctly, but they should.
2.11. Index
The index packet contains available byte offsets of nearby keyframes, reconfiguration packets or metadata changes, and the distance to the next index packet.
| Type | Name | Data | Description |
|---|---|---|---|
b(16)
| stream_index_descriptor | 0x0051 | Indicates this is an index packet. |
b(16)
| stream_id | Indicates the stream ID for the index. May be 0xFFFF, in which case, it applies to all streams. | |
u(32)
| global_seq | Monotonically incrementing per-packet global sequence number. | |
u(32)
| prev_idx | Negative offset of the previous index packet, if any, in bytes, relative to the current position. If exactly 0, indicates no such index is available, or is out of scope. | |
u(32)
| next_idx | Positive offset of the next index packet, if any, in bytes, relative to the current position. May be inexact, specifying the minimum distance to one. Users may search for it. | |
u(32)
| nb_indices | The total number of indices present in this packet. | |
b(64)
| padding | Padding, reserved for future use. MUST be 0x0. | |
b(64)
| ldpc_288_224 | LDPC(288, 224) | 64-bits of LDPC parity data to correct the previous 224 bits of the packet. |
nb_indices*b(144)
| index_entry_list | struct IndexEntry | Descriptor of the packet that each index points to. |
If index packets are present, an index packet must be sent for any stream reconfiguration packets, or metadata changes. No future index packets must be signalled or sent, until all the packets needed to correctly reinitialize streams have been sent. The exception to this is if a newer reinitialization has begun.
If valid, prev_idx, next_idx and pkt_offset offsets must point to the start of a packet. In other words, the byte pointed to by the offsets must contain the first, most significant byte of the descriptor of the pointed packet.
If stream_id is 0xFFFF, the timebase used for pts must be assumed to be 1 nanosecond, numerator of 1, denominator of 1000000000.
When streaming, prev_idx and next_idx must be 0.
2.11.1. Index entry (struct IndexEntry)
The structure of the data for each index entry is as follows:
| Type | Name | Data | Description |
|---|---|---|---|
b(16)
| index_entry_descriptor | Descriptor of the packet that each index points to. | |
i(64)
| pts | Timestamp of the packet that the index entry points to. | |
u(32)
| target_seq | Sequence number of the packet pointed to by this index entry. | |
i(32)
| pkt_offset | The offset of the index entry relative to the current position in bytes. May be 0 if unavailable or not applicable. |
Note: If a packet starts before the value of pts but has a duration that matches or exceeds the PTS, then it must be included. This is to permit correct subtitle presentation, or long duration still pictures like slideshows.
2.12. Metadata
The metadata packets can be sent for the overall session, or for a specific `stream_id` substream. The data is contained in structures templated in the § 2.4 Generic data structures, with the following descriptors:
| Descriptor value | Name | Structure | Description |
|---|---|---|---|
| 0x000A | metadata_descriptor | § 2.4 Generic data | First metadata segment. |
| 0x000B | metadata_segment_descriptor | § 2.4.1 Generic data segmentation | Final segment of segmented metadata. |
| 0x000C | metadata_parity_descriptor | § 2.4.2 Generic data parity | Parity data for metadata. |
The actual metadata must be stored using CBOR, as standardized in [RFC8949], as a key and value pair.
Implementations are free to use any key or value names. But, to maintain interoperability, implementations are required to either follow the tags given by § 4.1 Annex A: Metadata tags, or use custom tags if the format of the values differ.
Each key may be present multiple times. Implementations must discard the old value associated with the key and update the metadata.
If stream_id is equal to 0xFFFF, the metadata applies for the session as a whole.
If stream_id is not 0xFFFF, the metadata is a separate set of values that just describe a single stream. Tags from other streams, or the general file metadata must not overwrite each other.
Metadata can be updated by sending new metadata packets with new values. The entire metadata must be replaced with the contents of a new metadata packet, incremental updates are not possible.
Metadata may be padded by appending zeroed bytes to the end. This must be accounted by the payload value. Implementations may do this to write metadata after starting and outputting a packet.
2.13. LUT/ICC profile
Embedding of color lookup tables (LUTs) and ICC profiles for accurate color reproduction is supported.
The following structure MUST be followed:
| Type | Name | Data | Description |
|---|---|---|---|
b(16)
| lut_icc_descriptor | 0x0010 | Indicates this packet contains a complete LUT or ICC profile or the start of one. |
b(16)
| stream_id | The stream ID for which to apply the LUT/ICC profile. | |
u(32)
| global_seq | Monotonically incrementing per-packet global sequence number. | |
i(64)
| pts | Timestamp (in stream timebase units) at which this orientation packet has to be applied at. | |
u(8)
| lut_type | enum LutType
| The data type contained in the lut_data. |
b(8)
| lut_major_ver | Major version of the file. Currently only applies to ICC profiles. | |
b(8)
| lut_minor_ver | Minor version of the file. Currently only applies to ICC profiles. | |
u(8)
| lut_compression | enum DataCompression
| LUT/ICC data compression. |
b(32)
| lut_data_length | The length of the LUT/ICC profile. | |
b(32)
| lut_pl_length | The length of the LUT/ICC profile in this packet. | |
b(64)
| ldpc_288_224 | LDPC(288, 224) | 64-bits of LDPC parity data to correct the previous 224 bits of the packet. |
252*b(8)
| lut_name | fixed-length string | 252-byte UTF-8 string, containing the original file name of the LUT/ICC profile. |
b(768)
| ldpc_2784_2016 | LDPC(2784, 2016) | 768-bit LDPC parity data to correct the previous 2016 bits of the packet. |
lut_pl_length*b(8)
| lut_data | payload | The LUT/ICC profile data |
Often, LUT/ICC profiles may be too large to fit, hence they can be segmented in the same way as data packets, as well as have parity data. Segmentation happens only when lut_data_length is less than lut_pl_length. The syntax for segmentation and parity packets is via the following § 2.4 Generic data templates:
| Descriptor value | Name | Structure | Description |
|---|---|---|---|
| 0x0011 | lut_icc_segment_descriptor | § 2.4.1 Generic data segmentation | Non-final segment for segmented LUT/ICC profile. |
| 0x0012 | lut_icc_parity_descriptor | § 2.4.1 Generic data segmentation | Final segment of a segmented LUT/ICC profile. |
2.13.1. LUT/ICC Profile Type Enumeration (enum LutType)
The lut_type field must be interpreted in the following way:
CLUT_TYPE_ICC_PROFILE= 0x1-
Indicates that the data contains a regular ICC profile, with version
lut_major_ver.lut_minor_ver. CLUT_TYPE_ADOBE_CUBE= 0x2-
Indicates that the data contains an Adobe [CUBE] file.
Note: Lookup tables and ICC profiles must take precedence over the primaries and transfer characteristics values in § 2.15 Video information. The matrix coefficients are still required for RGB conversion.
Note: Both an ICC profile and a color lookup table may be applied for a single stream.
2.14. Font data
Subtitles may often require custom fonts. AVTransport supports embedding of fonts
for use by subtitles.
Currently, this only applies for ASS streams (§ 3.1.18 ASS encapsulation). Once parsed, these fonts must be made available for the ASS stream.
The following structure MUST be followed:
| Type | Name | Data | Description |
|---|---|---|---|
b(16)
| font_data_descriptor | 0x0020 | Indicates the payload contains a font. |
b(16)
| stream_id |
The stream ID for which to make the font available. Note: May be set to 0xffff to make the font available for all streams. | |
u(32)
| global_seq | Monotonically incrementing per-packet global sequence number. | |
u(8)
| font_type | enum FontType
| The data type contained in the font_data. |
u(8)
| font_compression | enum DataCompression
| Font data compression. |
u(32)
| font_data_length | The length in bytes of the font file data. | |
u(32)
| font_pl_length | The length in bytes of the current packet’s font data. | |
b(80)
| padding | Padding, reserved for future use. MUST be 0x0. | |
b(64)
| ldpc_288_224 | LDPC(288, 224) | 64-bits of LDPC parity data to correct the previous 224 bits of the packet. |
252*b(8)
| font_name | fixed-length string | 252-byte UTF-8 string, containing the original file name of the font. |
b(768)
| ldpc_2784_2016 | LDPC(2784, 2016) | 768-bit LDPC parity data to correct the previous 2016 bits of the packet. |
font_pl_length*b(8)
| font_data | payload | The font data. |
Font data can too be segmented in the same way as data packets, as well as have parity data. Segmentation happens only when font_data_length is less than font_pl_length. The syntax for segmentation and parity packets is via the following § 2.4 Generic data templates:
| Descriptor value | Structure | Name | Description |
|---|---|---|---|
| 0x0021 | font_data_segment_descriptor | § 2.4.1 Generic data segmentation | Non-final segment for segmented font file. |
| 0x0022 | font_data_parity_descriptor | § 2.4.2 Generic data parity | Parity data for a font file. |
2.14.1. Font Type Enumeration (enum FontType)
The font_type field must be interpreted in the following way:
FONT_TYPE_OTF= 0x0-
Indicates that the font data contained is an [OpenType] font.
FONT_TYPE_TTF= 0x1-
Indicates that tata contains a [TrueType] font.
FONT_TYPE_WOFF2= 0x2-
Indicates that tata contains a [WOFF2] (Web Open Font Format 2) font.
Note: FONT_TYPE_WOFF2 fonts should not be compressed, as they’re already compressed.
2.15. Video information
Video info packets contain everything needed to correctly interpret a video stream after decoding.
| Type | Name | Data | Description |
|---|---|---|---|
b(16)
| video_info_descriptor | 0x0008 | Indicates this packet contains video information. |
b(16)
| stream_id | The stream ID for which to apply the video information to. | |
u(32)
| global_seq | Monotonically incrementing per-packet global sequence number. | |
i(64)
| pts | Timestamp (in stream timebase units) at which this orientation packet has to be applied at. | |
u(32)
| width | Indicates the video width in pixels, before any cropping. | |
u(32)
| height | Indicates the video height in pixels, before any cropping | |
u(8)
| chroma_subsampling | enum ChromaSubsampling
| Indicates the chroma subsampling being used. |
u(8)
| colorspace | enum Colorspace
| Indicates the kind of colorspace the video is in. |
u(8)
| bit_depth | Number of bits per output video sample. | |
u(8)
| interlaced | enum Interlacing
| Indicates the video interleaving. |
b(64)
| ldpc_288_224 | LDPC(288, 224) | 64-bits of LDPC parity data to correct the previous 224 bits of the packet. |
R(64)
| signal_aspect | Indicates the sample aspect ratio of the image. | |
R(64)
| gamma | Indicates the gamma power curve for the video sample values. | |
R(64)
| framerate | Indicates the framerate of the video. If it’s variable, may be used to indicate the average bitrate. If the video is interlaced, indicates the field rate. | |
u(8)
| output_range | enum ColorRange
| Indicates the range for the output video samples. |
u(8)
| chroma_pos | enum ChromaPosition
| Chroma sample alignment for subsampled chroma. |
u(8)
| primaries | enum Primaries
| Video color primaries. Must be interpreted according to ITU Standard [H.273], ColourPrimaries field. |
u(8)
| transfer | enum Transfer
| Video transfer characteristics. Must be interpreted according to ITU Standard [H.273], TransferCharacteristics field. |
u(8)
| matrix | enum Matrix
| Video matrix coefficients. Must be interpreted according to ITU Standard [H.273], MatrixCoefficients field. |
u(8)
| has_mastering_primaries | If 1, indicates that the following mastering_primaries and mastering_white_point contain valid data. Other values are reserved. | |
u(8)
| has_luminance | If 1, indicates that the following min_luminance and max_luminance contain valid data. Other values are reseved. | |
16*R(64)
| custom_matrix | If the color matrix value is equal to 0xFF, use this custom matrix instead. Top left to bottom right, in "raster-order". Otherwise, must be set to 0. | |
6*R(64)
| mastering_primaries | [CIE1931] X/Y chromacity coordinates of the color primaries, x value, then y value, for each r, g, b, in order.
| |
2*R(64)
| mastering_white_point | [CIE1931] X/Y chromacity coordinates of the white point, x value, then y value.
| |
R(64)
| min_luminance | Minimal luminance of the mastering display, in cd/m2. | |
R(64)
| max_luminance | Maximum luminance of the mastering display, in cd/m2. | |
u(32)
| cropped_width | Indicates the presentable video width in samples. | |
u(32)
| cropped_height | Indicates the presentable video height in samples. | |
u(16)
| crop_x_offset | X offset for the location of the final presentation box. | |
u(16)
| crop_y_offset | Y offset for the location of the final presentation box. | |
b(8)
| padding | Padding, reserved for future use. Must be 0x0. | |
b(768)
| ldpc_2784_2016 | LDPC(2784, 2016) | 768-bit LDPC parity data to correct the previous 2016 bits of the packet. |
2.15.1. Colorspace Enumeration (enum Colorspace)
The colorspace field must be interpreted in the following way:
CSP_MONO= 0x0-
Video contains no chroma data.
CSP_RGB= 0x1-
Video data contains a form of RGB.
CSP_YUV= 0x2-
Video contains a form of YUV (YCbCr).
CSP_YCOCGR= 0x3-
Video contains a reversible form of YCoCg, as defined by [H.273], equations 47-50.
CSP_YCGCOR= 0x4-
Video contains a reversible form of YCgCo (same as above, with swapped chroma planes).
CSP_XYZ= 0x5-
Video contains [CIE1931] XYZ color data.
CSP_XYB= 0x6-
Video contains XYB color data, as defined by [ISO18181].
Note: matrix must be equal to 0xFF and the custom_matrix must be a valid matrix to transform XYB into RGB.
CSP_ICTCP= 0x5-
Video contains [BT2100] ICtCp color data.
CSP_BAYER_BGGR= 0x6-
Video contains raw CMOS voltages, from 4x4 cells with a pattern Blue, Green, Green, Red, in raster-order.
CSP_BAYER_RGGB= 0x7CSP_BAYER_GBRG= 0x8CSP_BAYER_GRBG= 0x9
2.15.2. Color Range Enumeration (enum ColorRange)
COLOR_RANGE_FULL= 0x0-
Video sample values contains the full range of the bit_depth.
COLOR_RANGE_LIMITED= 0x1-
Video sample values contains the limited range of the bit_depth.
Note: This describes the cannonical limited range representation:
(219 * E + 16) * 2(bit_depth-8), whereE, the input range, is 0.0 to 1.0 for luma planes and -0.5 to 0.5 for chroma planes. This means, for 8-bits, the luma range is 16-235 and the chroma range is 16-240.
2.15.3. Chroma Subsampling Enumeration (enum ChromaSubsampling)
CHROMA_444= 0x0-
Chromatic data is not subsampled, or subsampling does not apply.
CHROMA_420= 0x1-
Chromatic data is subsampled at half the horizontal and vertical resolution of the luminance data.
CHROMA_422= 0x2-
Chromatic data is subsampled at half the horizontal resolution of the luminance data.
CHROMA_440= 0x3-
Chromatic data is subsampled at half the vertical resolution of the luminance data.
CHROMA_411= 0x4-
Chromatic data is subsampled at a quarter of the horizontal resolution of the luminance data.
CHROMA_311= 0x5-
Luma data is subsampled at 3/4 of the output horizontal resolution, chromatic data is subsampled at 1/4 of the output horizontal resolution.
2.15.4. Interlacing Enumeration (enum Interlacing)
The value of interlaced determines whether the video is interlaced, as well as how to interpret the value of field_id in stream data packet headers.
ILACE_PROG= 0x0-
Video contains progressive data, or interlacing does not apply.
Note: In this mode, the field_id bit is free to use by users. Implementations must ignore it, and preserve it.
ILACE_TFF= 0x1-
Video is interlaced. One § 2.6 Stream Data packet per field. If the data packet’s field_id bit is unset, indicates the field contained is the top field, otherwise it’s the bottom field.
ILACE_BFF= 0x2-
Same as above, with reversed polarity, such that packets with field_id bit set contain the top field, otherwise it’s the bottom.
ILACE_TW= 0x3-
Video is interlaced. The § 2.6 Stream Data packet contains both fields, weaved together, with the top field being on every even line.
ILACE_BW= 0x4-
Same as above, but with reversed polarity, such that the bottom field is encountered first.
The ILACE_TFF and ILACE_TW, as well as the ILACE_BFF and ILACE_BW values
may be interchanged if it’s possible to output one or the other, depending on
the setting used, if the codec supports this.
2.15.5. Chroma Position Enumeration (enum ChromaPosition)
CHROMA_POS_UNSPEC= 0x0-
Chroma position not specified or does not apply.
CHROMA_POS_LEFT= 0x1-
Chroma position is between 2 luma samples on different lines.
Note: This is the default chroma position for MPEG-2, H.263 with
CHROMA_422, and H.264 withCHROMA_420. CHROMA_POS_CENTER= 0x2-
Chroma position is in the middle between all neighbouring luma samples on 2 lines.
Note: This is the default chroma position for JPEG with
CHROMA_420, and H.263 withCHROMA_420. CHROMA_POS_TOPLEFT= 0x3-
Chroma position coincides with top left’s luma sample position.
Note: This is the default chroma position for MPEG-2 with
CHROMA_422. CHROMA_POS_TOP= 0x4-
Chroma position is between 2 luma samples on the same top line.
CHROMA_POS_BOTTOMLEFT= 0x5-
Chroma position coincides with bottom left’s luma sample position.
CHROMA_POS_BOTTOM= 0x6-
Chroma position is between 2 luma samples on the same bottom line.
To illustrate:
| Luma line number | Luma row 1 | Between rows | Luma row 3 |
|---|---|---|---|
| 1 | Luma pixel 0x3
| 0x4
| Luma pixel |
| Between lines | 0x1
| 0x2
| |
| 2 | Luma pixel 0x5
| 0x6
| Luma pixel |
2.15.6. Primaries Enumeration (enum Primaries)
These values are copied verbatim from [H.273].
PRIM_RESERVED_0= 0x0-
For future use by ITU-T | ISO/IEC
PRIM_BT709= 0x1-
Rec. ITU-R BT.709-6
IEC 61966-2-1 sRGB or sYCC
PRIM_UNSPEC= 0x2-
Image characteristics are unknown or are determined by the application.
PRIM_RESERVED_3= 0x0-
For future use by ITU-T | ISO/IEC
PRIM_BT470= 0x4-
United States Federal Communications Commission (2003) Title 47 Code of Federal Regulations 73.682 (a) (20)
PRIM_BT601_625= 0x5-
Rec. ITU-R BT.1700-0 625 PAL and 625 SECAM
PRIM_BT601_525= 0x6-
Rec. ITU-R BT.1700-0 NTSC
PRIM_ST240= 0x7-
SMPTE ST 240 (1999) (functionally the same as the value 6)
PRIM_FILM= 0x8-
Generic film (colour filters using Illuminant C)
PRIM_BT2020= 0x9-
Rec. ITU-R BT.2100-2
PRIM_ST428= 0xA-
SMPTE ST 428-1 (2019) (CIE 1931 XYZ as in ISO 11664-1)
PRIM_ST431= 0xB-
SMPTE RP 431-2 (2011)
PRIM_ST432= 0xC-
SMPTE EG 432-2 (2010)
Note: This list may not be up to date in this version of the AVTransport specifications. Users should consult the latest [H.273] spec for up-to-date values and how to interpret them.
2.15.7. Transfer Function Enumeration (enum Transfer)
These values are copied verbatim from [H.273]. The same note applies.
TRANSFER_RESERVED_0= 0x0-
For future use by ITU-T | ISO/IEC
TRANSFER_BT709= 0x1-
Rec. ITU-R BT.709-6
TRANSFER_UNSPEC= 0x2-
Image characteristics are unknown or are determined by the application.
TRANSFER_FCC= 0x4-
United States Federal Communications Commission (2003) Title 47 Code of Federal Regulations 73.682 (a) (20)
TRANSFER_BT470= 0x5-
Rec. ITU-R BT.470-6 System B, G (historical)
TRANSFER_BT601= 0x6-
Rec. ITU-R BT.601-7 525 or 625
TRANSFER_ST240= 0x7-
SMPTE ST 240 (1999)
TRANSFER_LINEAR= 0x8-
Linear transfer characteristics
TRANSFER_LOG= 0x9-
Logarithmic transfer characteristic (100:1 range)
TRANSFER_LOG_SQ= 0xA-
Logarithmic transfer characteristic (100 * Sqrt( 10 ) : 1 range)
TRANSFER_IEC61966_2_4= 0xB-
IEC 61966-2-4
TRANSFER_BT1361= 0xC-
Rec. ITU-R BT.1361-0 extended colour gamut system (historical)
TRANSFER_IEC61966_2_1= 0xD-
IEC 61966-2-1 sRGB (with MatrixCoefficients equal to 0) or IEC 61966-2-1 sYCC (with MatrixCoefficients equal to 5)
TRANSFER_BT2020_10= 0xE-
Rec. ITU-R BT.2020-2 (10-bit system) (functionally the same as the values 1, 6 and 15)
TRANSFER_BT2020_12= 0xF-
Rec. ITU-R BT.2020-2 (12-bit system) (functionally the same as the values 1, 6 and 15)
TRANSFER_BT2048= 0x10-
Rec. ITU-R BT.2100-2 perceptual quantization (PQ) system
TRANSFER_ST428= 0x11-
SMPTE ST 428-1 (2019)
TRANSFER_HLG= 0x12-
Rec. ITU-R BT.2100-2 hybrid log- gamma (HLG) system
2.15.8. Matrix Enumeration (enum Matrix)
These values are copied verbatim from [H.273]. The same note applies.
MATRIX_IDENT= 0x0-
The identity matrix. Typically used for GBR (often referred to as RGB); however, may also be used for YZX (often referred to as XYZ);
MATRIX_BT709= 0x1-
Rec. ITU-R BT.709-6
MATRIX_UNSPEC= 0x2-
Image characteristics are unknown or are determined by the application
MATRIX_RESERVED_3= 0x3-
For future use by ITU-T | ISO/IEC
MATRIX_FCC= 0x4-
United States Federal Communications Commission (2003) Title 47 Code of Federal Regulations 73.682 (a) (20)
MATRIX_BT470= 0x5-
Rec. ITU-R BT.470-6 System B, G (historical) (functionally the same as the value 6)
MATRIX_BT601= 0x6-
Rec. ITU-R BT.601-7 525
MATRIX_ST240= 0x7-
SMPTE ST 240 (1999)
MATRIX_YCGCO= 0x8-
See [H.273], equations 38 to 40
MATRIX_BT2020_NCL= 0x9-
Rec. ITU-R BT.2100-2 Y′CbCr
MATRIX_BT2020_CL= 0xA-
Rec. ITU-R BT.2020-2 (constant luminance)
MATRIX_ST2085= 0xB-
SMPTE ST 2085 (2015)
MATRIX_ST2100= 0xE-
Rec. ITU-R BT.2100-2 ICTCP
MATRIX_IPT_C2= 0xF-
SMPTE ST 2128 (202x), equations 85 to 87
MATRIX_YCGCO_RE= 0x10-
[H.273], equations 58 to 65
MATRIX_YCGCO_RO= 0x11-
[H.273], equations 58 to 65
2.16. Video orientation
A standardized way to transmit orientation information is as follows:
| Type | Name | Data | Description |
|---|---|---|---|
b(16)
| video_orientation_descriptor | 0x0040 | Indicates this is a video orientation packet. |
b(16)
| stream_id | The stream ID for which to associate the video information with. | |
u(32)
| global_seq | Monotonically incrementing per-packet global sequence number. | |
i(64)
| pts | Timestamp (in stream timebase units) at which this orientation packet has to be applied at. | |
u(8)
| reflection | enum VideoReflection
| A fixed transposition that must occur before any arbitrary rotation. |
R(64)
| rotation | A fixed-point rational number to indicate rotation in radians once multiplied by π. | |
b(24)
| padding | Padding, reserved for future use. MUST be 0x0. | |
b(64)
| ldpc_288_224 | LDPC(288, 224) | 64-bits of LDPC parity data to correct the previous 224 bits of the packet. |
The effects of video orientation packets MUST persist from the pts value given, until a new orientation packet is sent, or the stream is reinitialized.
2.16.1. Video Reflection Enumeration (enum VideoReflection)
VIDEO_REFLECT_NONE= 0x0-
Video is not flipped.
VIDEO_REFLECT_MIRROR= 0x1-
Video must be mirrored for correct presentation (flipped horizontally).
VIDEO_REFLECT_FLIP= 0x2>-
Video must be flipped upside-down for correct presentation.
reflection must be applied first, before rotation.
The actual rotation in radians is given by π * (rotation.num/rotation.den).
Rotation should be applied after all other transformations have been performed on the image, including cropping via the cropped_width/cropped_height fields in § 2.15 Video information packets.
2.17. Stereo video
A stereoscopic video file consists in multiple views embedded in a single frame, usually describing two views of a scene.
Interlacing and stereoscopic video are explicitly unsupported. Implementations
must ignore any stereoscopic information if the value of interlaced is anything
except ILACE_PROG.
A standardized way to transmit stereoscopic video information is as follows:
| Type | Name | Data | Description |
|---|---|---|---|
b(16)
| stereo_video_descriptor | 0x0041 | Indicates this is a stereo video information packet. |
b(16)
| stream_id | The stream ID for which to associate the stereo information with. | |
u(32)
| global_seq | Monotonically incrementing per-packet global sequence number. | |
i(64)
| pts | Timestamp (in stream timebase units) at which this stereo packet has to be applied at. | |
u(8)
| type | enum StereoVideoType
| Indicates how views are packed within the video. |
u(8)
| flags | enum StereoVideoFlags
| Additional flags. |
u(8)
| primary_eye | enum StereoVideoPrimaryEye
| Determines which eye is the primary eye when rendering in 2D. |
u(32)
| baseline | The distance between the centres of the lenses of the camera system, in micrometers. | |
b(40)
| padding | Padding, reserved for future use. MUST be 0x0. | |
b(64)
| ldpc_288_224 | LDPC(288, 224) | 64-bits of LDPC parity data to correct the previous 224 bits of the packet. |
R(64)
| horizontal_disparity_adjustment | Relative shift of the left and right images, which changes the zero parallax plane. Range is -1.0 to 1.0. | |
R(64)
| horizontal_field_of_view | Horizontal field of view, in degrees. | |
b(96)
| padding | Padding, reserved for future use. MUST be 0x0. | |
b(64)
| ldpc_288_224 | LDPC(288, 224) | 64-bits of LDPC parity data to correct the previous 224 bits of the packet. |
The effects of stereo video packets must persist from the pts value given, until a new stereo video packet is sent, or the stream is reinitialized.
2.17.1. Stereo Video Type Enumeration (enum StereoVideoType)
By convention, the first view is the left eye’s view, and the second view is the right eye’s view.
The two are swapped if STEREO_VIDEO_FLAG_INVERTED is set.
STEREO_VIDEO_TYPE_2D= 0x0-
Video is not stereoscopic. Only a single view exists. The metadata has to be ignored.
STEREO_VIDEO_TYPE_SIDE_BY_SIDE= 0x1-
Views are next to each other, horizontally.
STEREO_VIDEO_TYPE_TOP_AND_BOTTOM= 0x2-
Views are on top of each other.
STEREO_VIDEO_TYPE_INDIVIDUAL= 0x3-
Views are separate, one in each frame. Indicated by the field_id, if set to 1, then view is the primary_eye.
STEREO_VIDEO_TYPE_CHECKERBOARD= 0x4-
Pixels from each view are interleaved in a checkerboard structure.
STEREO_VIDEO_TYPE_SIDE_BY_SIDE_QUINCUNX= 0x5-
Views are next to each other, horizontally. But are spatially sampled using a Quincunx pattern.
STEREO_VIDEO_TYPE_LINES= 0x6-
Views are interleaved on a line-basis, as if interlaced.
STEREO_VIDEO_TYPE_COLUMNS= 0x7-
Views are interleaved on a column basis.
2.17.2. Stereo Video Flags Enumeration (enum StereoVideoFlags)
STEREO_VIDEO_FLAG_INVERTED= 0x0-
Views must be swapped during presentation (left->right, right->left).
2.17.3. Stereo Video Primary Eye Enumeration (enum StereoVideoPrimaryEye)
STEREO_VIDEO_PRIMARY_EYE_NONE= 0x0-
Neither eye is primary.
STEREO_VIDEO_PRIMARY_EYE_LEFT= 0x1-
The left eye is the primary.
STEREO_VIDEO_PRIMARY_EYE_RIGHT= 0x2-
The right eye is the primary.
2.18. User data
The user-specific data packet is laid out as follows:
| Type | Name | Data | Description |
|---|---|---|---|
b(16)
| user_data_descriptor | 0x0600 | Indicates this is an opaque user-specific data. |
b(16)
| user_field | A free to use field for user data. | |
u(32)
| global_seq | Monotonically incrementing per-packet global sequence number. | |
u(32)
| userdata_length | The total length of the user data. | |
u(32)
| userdata_pl_length | The length of the user data in this packet. | |
b(64)
| opaque | Opaque data, available to users to set. | |
u(8)
| userdata_compression | enum DataCompression
| User data compression. |
b(24)
| padding | Padding, reserved for future use. MUST be 0x0. | |
b(64)
| ldpc_288_224 | LDPC(288, 224) | 64-bits of LDPC parity data to correct the previous 224 bits of the packet. |
userdata_pl_length*b(8)
| userdata | payload | The user data itself. |
User data may be segmented:
| Descriptor value | Name | Structure | Description |
|---|---|---|---|
| 0x0601 | user_data_segment_descriptor | § 2.4.1 Generic data segmentation | Non-final segment for segmented user data. |
| 0x0602 | user_data_parity_descriptor | § 2.4.2 Generic data parity | Parity data for user data. |
2.19. Stream duration
If the session length is well-known, implementations can reserve space up-front at the start of files to notify implementations of stream lengths.
| Type | Name | Data | Description |
|---|---|---|---|
b(16)
| stream_duration_descriptor | 0x0050 | Indicates this is a stream duration packet. |
b(16)
| stream_id | Indicates the stream ID for the index. May be 0xFFFF, in which case, it applies to all streams. | |
u(32)
| global_seq | Monotonically incrementing per-packet global sequence number. | |
i(64)
| total_duration | The total duration of the stream(s). | |
b(96)
| padding | Padding, reserved for future use. Must be 0x0. | |
b(64)
| ldpc_288_224 | LDPC(288, 224) | 64-bits of LDPC parity data to correct the previous 224 bits of the packet. |
If stream_id is 0xFFFF, the timebase used for total_duration must be assumed to be 1 nanosecond, numerator of 1, denominator of 1000000000.
If the value of total_duration is 0, the entire packet must be ignored.
In such cases, implementations are free to attempt to measure stream duration
via other methods.
This makes it possible to write stream duration packets at the start of
streams, and amend them later.
The duration must be the total amount of time the stream will be presented.
Any negative duration MUST be excluded.
The duration must be treated as metadata rather than a hard limit.
2.20. End of stream
The EOS packet is laid out as follows:
| Type | Name | Data | Description |
|---|---|---|---|
b(16)
| stream_end_descriptor | 0x0FFF | Indicates this is a stream duration packet. |
b(16)
| stream_id | Indicates the stream ID for the index. May be 0xFFFF, in which case, it applies to all streams. | |
u(32)
| global_seq | Monotonically incrementing per-packet global sequence number. | |
b(160)
| padding | Padding, reserved for future use. Must be 0x0. | |
b(64)
| ldpc_288_224 | LDPC(288, 224) | 64-bits of LDPC parity data to correct the previous 224 bits of the packet. |
The stream_id field may be used to indicate that a specific stream will no longer receive any packets, and implementations are free to unload decoding and free up any used resources.
The stream_id may be reused afterwards, but this is not recommended.
If not encountered in a stream, and the connection was cut, then the receiver is allowed to gracefully wait for a reconnection.
If encountered in a file, the implementation may regard any data present afterwards as padding and ignore it. AVTransport files should not be concatenated.
3. Addendum
This section expands on certain aspects of the specification.
3.1. Codec encapsulation
The following section lists the supported codecs, along with their encapsulation definitions. Below, a mapping between codec_id and encapsulation is listed:
| codec_id | codec_id (ASCII) | Encapsulation | Name |
|---|---|---|---|
| 0x4F707573 | Opus | CODEC_ID_OPUS | § 3.1.1 Opus encapsulation |
| 0x41414300 | AAC\0 | CODEC_ID_AAC | § 3.1.2 AAC encapsulation |
| 0x41432d33 | AC-3 | CODEC_ID_AC3 | § 3.1.3 AC-3 encapsulation |
| 0x41545231 | ATR1 | CODEC_ID_ATRAC1 | § 3.1.4 ATRAC-1 encapsulation |
| 0x41545239 | ATR9 | CODEC_ID_ATRAC9 | § 3.1.5 ATRAC-9 encapsulation |
| 0x4154414b | ATAK | CODEC_ID_TAK | § 3.1.6 TAK encapsulation |
| 0x664c6143 | fLaC | CODEC_ID_FLAC | § 3.1.6 TAK encapsulation |
| 0x56503332 | VP23 | CODEC_ID_THEORA | § 3.1.8 Theora encapsulation |
| 0x56503039 | VP09 | CODEC_ID_VP9 | § 3.1.9 VP9 encapsulation |
| 0x41563031 | AV01 | CODEC_ID_AV1 | § 3.1.10 AV1 encapsulation |
| 0x48323634 | H264 | CODEC_ID_H264 | § 3.1.11 H264 encapsulation |
| 0x48323635 | H265 | CODEC_ID_H265 | § 3.1.12 H265 encapsulation |
| 0x42424344 | BBCD | CODEC_ID_DIRAC | § 3.1.15 Dirac/VC-2 encapsulation |
| 0x46467631 | FFv1 | CODEC_ID_FFV1 | § 3.1.16 FFv1 encapsulation |
| 0x6170636e | apcn | CODEC_ID_PRORES_SD | § 3.1.17 ProRes encapsulation |
| 0x61706368 | apch | CODEC_ID_PRORES_HQ | § 3.1.17 ProRes encapsulation |
| 0x61706373 | apcs | CODEC_ID_PRORES_LT | § 3.1.17 ProRes encapsulation |
| 0x6170636f | apco | CODEC_ID_PRORES_PROXY | § 3.1.17 ProRes encapsulation |
| 0x61703468 | ap4h | CODEC_ID_PRORES_4444 | § 3.1.17 ProRes encapsulation |
| 0x61703478 | ap4x | CODEC_ID_PRORES_4444_XQ | § 3.1.17 ProRes encapsulation |
| 0x61707268 | aprh | CODEC_ID_PRORES_RAW_HQ | § 3.1.17 ProRes encapsulation |
| 0x6170726e | aprn | CODEC_ID_PRORES_RAW_SD | § 3.1.17 ProRes encapsulation |
| 0x54494646 | TIFF | CODEC_ID_TIFF | § 3.1.21 DNG/TIFF encapsulation |
| 0x4a504547 | JPEG | CODEC_ID_JPEG | § 3.1.22 JPEG encapsulation |
| 0x4a50324b | JP2K | CODEC_ID_JPEG2000 | § 3.1.23 JPEG-2000 encapsulation |
| 0x48544a32 | HTJ2 | CODEC_ID_JPEG2000_HT | § 3.1.23 JPEG-2000 encapsulation |
| 0x504e4700 | PNG\0 | CODEC_ID_PNG | § 3.1.24 PNG encapsulation |
| 0x53564732 | SVG2 | CODEC_ID_SVG | § 3.1.25 SVG encapsulation |
| 0x52414141 | RAAA | CODEC_ID_RAW_AUDIO | § 3.1.26 Raw audio encapsulation |
| 0x52415656 | RAVV | CODEC_ID_RAW_VIDEO | § 3.1.27 Raw video encapsulation |
| 0x41535334 | ASS4 | CODEC_ID_ASS | § 3.1.18 ASS encapsulation |
| 0x53554252 | SUBR | CODEC_ID_SRT | § 3.1.19 SubRip encapsulation |
| 0x57565454 | WVTT | CODEC_ID_WEBVTT | § 3.1.20 WebVTT encapsulation |
| 0x56433031 | VC01 | CODEC_ID_VC1 | § 3.1.13 VC1 encapsulation |
| 0x61507631 | aPv1 | CODEC_ID_APV | § 3.1.14 APV encapsulation |
3.1.1. Opus encapsulation
For Opus encapsulation, the codec_id in § 2.3 Stream registration must be 0x4F707573 (`Opus`).
The payload of the § 2.5 Stream configuration packets MUST be laid out in the following way:
| Type | Name | Value | Description |
|---|---|---|---|
b(64)
| opus_id | 0x4F70757348656164 (OpusHead) | Opus magic string. |
b(8)
| opus_init_ver | Version of the config data. Must be 0x1. | |
u(8)
| opus_channels | Number of audio channels. | |
u(16)
| opus_prepad | Number of samples to discard from the start of decoding (encoder delay). | |
u(32)
| opus_rate | Samplerate of the data. Must be 48000. | |
i(16)
| opus_gain | Volume adjustment of the stream. May be 0 to preserve the volume. | |
u(32)
| opus_ch_family | Opus channel mapping family. Consult [RFC7845] and [RFC8486]. | |
u(8)
| opus_stream_count | Optional, only available if opus_ch_family is not 0. | |
u(8)
| opus_coupled_count | Optional, only available if opus_ch_family is not 0. | |
opus_channels*u(8)
| opus_channel_mapping | Optional, only available if opus_ch_family is not 0. |
The meaning of each field is defined by [RFC7845].
Implementations must not use the opus_prepad field, but must set the first stream packet’s pts value to a negative value as defined in § 1.8.2 Negative times to remove the required number of prepended samples.
The packet_data MUST contain regular Opus packets with their front uncompressed header intact.
In case of multiple channels, the packets MUST contain the concatenated contents in coding order of all channels' packets.
In case the Opus bitstream contains native Opus FEC data, the FEC data must be appended to the packet as-is, and no § 2.9 Stream data parity packets must be present for this stream.
3.1.2. AAC encapsulation
For AAC encapsulation, the codec_id in § 2.3 Stream registration MUST be 0x41414300 (AAC0).
The § 2.5 Stream configuration packet payload must be the codec’s AudioSpecificConfig, as defined in MPEG-4.
The packet_data MUST contain regular AAC ADTS packtes. Note that LATM is explicitly unsupported.
Implementations must set the first stream packet’s pts value to a negative value as defined in § 2.6 Stream Data to remove the required number of prepended samples.
3.1.3. AC-3 encapsulation
For AAC encapsulation, the codec_id in § 2.3 Stream registration must be 0x41432d33 (AC-3).
AC-3 streams require no § 2.5 Stream configuration packets.
THe `packet_data` must contain regular AC-3 or E-AC-3 frames, starting from the `syncinfo` header defined in the specifications.
3.1.4. ATRAC-1 encapsulation
For ATRAC1, the codec_id in the § 2.3 Stream registration must be 0x41545231 (ATR1).
ATRAC-1 streams require no § 2.5 Stream configuration packets.
The `packet_data` must contain regular ATRAC-1 frames, as contained in RIFF.
3.1.5. ATRAC-9 encapsulation
For ATRAC9, the codec_id in the § 2.3 Stream registration must be 0x41545239 (ATR9).
The payload in § 2.5 Stream configuration packets must be laid out in the following way:
| Type | Name | Value | Description |
|---|---|---|---|
b(32)
| atrac9_version | 0x01000000 | The version of ATRAC-9 contained. Must be 0x01000000. |
u(8)
| atrac9_magic | 0xFE | ATRAC-9 magic byte |
u(4)
| atrac9_samplerate_idx | Samplerate index for the stream. | |
u(3)
| atrac9_block_config | Block configuration for the stream. | |
b(1)
| atrac9_verification_bit | 0 | Constant bit. |
u(11)
| atrac9_avg_frame_size | Average frame size in bits, minus one | |
u(2)
| atrac9_superframe_idx | Superframe index. Must be even. | |
u(32)
| atrac9_block_align | ATRAC-9 block alignment value for each frame. Must be larger than the largest frame in the stream. |
Note: atrac9_block_align is a value carried over from RIFF encapsulation, and is normally given to decoders via a separate mechanism. The configuration data length should omit it (so that it’s 12 bytes long).
The packet_data must contain raw ATRAC-9 frames, with no RIFF headers or encapsulation.
3.1.6. TAK encapsulation
For TAK (Tom’s lossless Audio Kompressor) encapsulation, the codec_id in § 2.3 Stream registration must be 0x4154414b (ATAK).
TAK streams require no § 2.5 Stream configuration packets.
The packet_data must contain raw TAK frames, starting with the frame header.
3.1.7. FLAC encapsulation
For FLAC encapsulation, the codec_id in § 2.3 Stream registration must be 0x664c6143 (fLaC).FLAC streams require § 2.5 Stream configuration packets, to contain the stream info header, which is defined as follows:
| Type | Name | Value | Description |
|---|---|---|---|
u(16)
| flac_min_blocksize | Minimum block size in samples. | |
u(16)
| flac_max_blocksize | Maximum number of samples in a block. Must be larger than flac_min_blocksize. | |
u(24)
| flac_min_framesize | Minimum framesize in bytes. | |
u(24)
| flac_max_framesize | Maximum framesize in bytes. Must be larger than flac_min_framesize. | |
u(20)
| flac_samplerate | Samplerate of the signal. | |
u(3)
| flac_channels | Number of channels. | |
u(5)
| flac_bitdepth | Bit depth of the signal. | |
u(24)
| flac_nb_samples_1 | Top 24 bits of the total number of samples in the stream, if known. | |
u(12)
| flac_nb_samples_2 | Bottom 12 bits of the number of samples in the stream, if known. | |
b(16)
| flac_streaminfo_md5 | MD5 ([RFC1321]) checksum of the previous 34 bytes. |
The `packet_data` must contain raw FLAC frames, with their frame header untouched.
3.1.8. Theora encapsulation
For Xiph Theora encapsulation, the codec_id in § 2.3 Stream registration must be 0x56503332 (VP32).
Stream configuration data is required for Theora. § 2.5 Stream configuration packets must contain an "Identification Header" (defined in Section 6.2), "Comment Header" (defined in Section 6.3), and a "Setup Header" (defined in Section 6.4), concatenated together, as defined in Section 3.2.1, "Decoder Setup".
The packet_data must contain raw Theora packets.
3.1.9. VP9 encapsulation
For VP9 encapsulation, the codec_id in § 2.3 Stream registration must be 0x56503039 (VP09).
The § 2.5 Stream configuration packet payload must be the codec’s so-called uncompressed header. For information on its syntax, consult the specifications, section 6.2 Uncompressed header syntax.
The packet_data must contain raw superframe packets, as defined in Annex B of the VP9 specifications.
3.1.10. AV1 encapsulation
For [AV1] encapsulation, the codec_id in § 2.3 Stream registration must be 0x41563031 (AV01).
The § 2.5 Stream configuration packet payload must be the codec’s so-called uncompressed header. For information on its syntax, consult the specifications, section 5.9.2. Uncompressed header syntax.
The packet_data MUST contain raw, separated OBUs.
3.1.11. H264 encapsulation
For H264 encapsulation, the codec_id in § 2.3 Stream registration must be 0x48323634 (H264).
§ 2.7 Extended stream data must be used, as H264 requires a dts.
The packet_data must contain Annex-B formatted NAL units, with startcode emulation bits included.
A § 2.5 Stream configuration packet may be sent, to speed up stream initialization. If they are present, they must contain an AVCDecoderConfigurationRecord structure, as defined in [ISO14496-15].
In-band parameters are always required to be present, even if an AVCDecoderConfigurationRecord structure is present in a § 2.5 Stream configuration packet.
Note: On some decoder implementations, giving an AVCDecoderConfigurationRecord structure upon initialization will result in the decoder mistaking the packets in the payload as AVCC rather than Annex-B. Implementations should consider whether the decoder being used will accept configuration data without assuming Annex-B, and only input such data if it is safe to do so.
3.1.12. H265 encapsulation
For H265 encapsulation, the codec_id in § 2.3 Stream registration must be 0x48323635 (H265).
§ 2.7 Extended stream data must be used, as H265 requires a dts.
The packet_data must contain Annex-B formatted NAL units, with startcode emulation bits included.
Annex-B formatted packets must be used, with startcode emulation bits included.
A § 2.5 Stream configuration packet may be sent, to speed up stream initialization. If they are present, they must contain an HEVCDecoderConfigurationRecord structure, as defined in [ISO23008].
3.1.13. VC1 encapsulation
For VC-1 encapsulation, the codec_id in § 2.3 Stream registration must be 0x56433031 (VC01).
This codec ID covers the following profiles of VC-1: (WMVA, WVC1).
Users may use the sequence layer data to determine the correct profile of the stream.
§ 2.7 Extended stream data must be used, as VC-1 requires a dts.
A § 2.5 Stream configuration packet may be sent, to speed up stream initialization. If they are present, they must contain a Setup Data/Sequence Layer structure.
3.1.14. APV encapsulation
For APV encapsulation, the codec_id in § 2.3 Stream registration MUST be 0x61507631 (aPv1).
APV is intra-frame only, so § 2.7 Extended stream data are not required.
APV streams require no § 2.5 Stream configuration packets. All decoder initialization data is contained within each access unit’s frame header.
The packet_data MUST contain a single APV access_unit() (as defined in Section 5.3.1 of [RFC9924]) per § 2.6 Stream Data packet, starting with the 4-byte signature (0x61507631, aPv1) and followed by its constituent PBUs. The leading au_size field from the raw bitstream format (Appendix A of [RFC9924]) MUST NOT be present, as the packet size is already conveyed by the AVTransport packet header.
3.1.15. Dirac/VC-2 encapsulation
For Dirac or VC-2 encapsulation, the codec_id in § 2.3 Stream registration MUST be 0x42424344 (BBCD).
§ 2.7 Extended stream data must be used, as Dirac packets require a dts.
Dirac streams require no § 2.5 Stream configuration packets.
The packet_data must contain raw sequences, with one sequence being a picture.
3.1.16. FFv1 encapsulation
For FFv1 encapsulation, the codec_id in § 2.3 Stream registration MUST be 0x46467631 (FFv1).
Stream configuration data is required for FFv1. § 2.5 Stream configuration packets must contain a "Parameters" structure, as defined in FFV1 Video Coding Format Versions 0, 1, and 3 § name-parameters.
The packet_data must contain raw FFv1 packets.
3.1.17. ProRes encapsulation
Apple ProRes is a collection of different profiles, each having its own codec ID:
| codec ID | codec ID (text) | Profile |
|---|---|---|
| 0x6170636e | apcn | Apple ProRes 422 Standard Definition |
| 0x61706368 | apch | Apple ProRes 422 High Quality |
| 0x61706373 | apcs | Apple ProRes 422 LT |
| 0x6170636f | apco | Apple ProRes 422 Proxy |
| 0x61703468 | ap4h | Apple ProRes 4444 |
| 0x61703478 | ap4x | Apple ProRes 4444 XQ |
| 0x61707268 | aprh | Apple ProRes RAW High Quality |
| 0x6170726e | aprn | Apple ProRes RAW Standard Definition |
All Apple ProRes streams require no § 2.5 Stream configuration packets.
The packet_data must contain raw ProRes packets.
3.1.18. ASS encapsulation
For ASS encapsulation, the codec_id in § 2.3 Stream registration MUST be 0x41535334 (ASS4).
ASS is a popular subtitle format with great presentation capabilities. Although it was not designed to be streamed or packetized, doing so is possible with the following specifications. These match to how Matroska handles [MATROSKA-ASS] encapsulation.
ASS contains 3 important sections:
-
Script information, in
[Script Info] -
Styles, in
[V4 Styles] -
Events, in
[Events] -
All other sections MUST be stripped.
First, all data MUST be converted to UTF-8.
The § 2.5 Stream configuration packet payload MUST contain
the [Script Info] and [V4 Styles] sections as a string, unmodified.
Events listed in ASS files MUST be modified in the following way:
-
Start and end timestamps, stored in the
Markedfield, must be mapped to the packet’s pts, dts and duration fields, and must be ommitted from the data. -
All other fields MUST be stored in the packet_data field as a string, in the followin order:
ReadOrder, Layer, Style, Name, MarginL, MarginR, MarginV, Effect, Text. -
Comments MAY be left as-is after all the fields.
The ReadOrder field is a monotonically incrementing field to identify the correct
order in which to reconstruct the original ASS file.
Multiple packets with the same pts are permitted.
3.1.19. SubRip encapsulation
For SubRip encapsulation, the codec_id in § 2.3 Stream registration MUST be 0x53554252 (SUBR).
SubRip are a simple method of subtitle packaging that are de-facto standardized by the following syntax:
1 00:02:17,440 --> 00:02:20,375 Senator, we're making our final approach into Coruscant. 2 00:02:20,476 --> 00:02:22,501 Very good, Lieutenant.
Each line starts with the sequence number (1), a start timestamp (2), an ending timestamp (3), the line(s) themselves, separated by newlines (4), and finally a blank like to indicate the end of the current line (5).
To encapsulate SubRip subtitles into AVTransport, simply use the subtitle body (3) as the packet_data. The start time is the packet’s pts field, while the duration field is the difference between the ending timestamp (3) and the starting timestamp (2).
SubRip streams require no § 2.5 Stream configuration packets.
Note: Extensions to SubRip files exist, with adding HTML-like tags to serve as markup. Dealing with them, however, is the users’s responsibility. It is recommended to convert such subtitles to § 3.1.18 ASS encapsulation.
Note: All kinds of encodings and line endings are used in SubRip files. They must be converted to UTF-8, with \n line endings.
3.1.20. WebVTT encapsulation
For SubRip encapsulation, the codec_id in § 2.3 Stream registration MUST be 0x57565454 (WVTT).
[WEBVTT] is a patent-free subtitle codec developed by the World Wide Web Consortium (W3C). It is essentially a standardized extension of SRT subtitles.
Unlike SRT, WebVTT supports styling. This is done via WebVTT styling blocks, inserted just before the first subtitle line.
The syling data, starting from and including the WEBVTT identifier, and ending at just before the first subtitle cue, must be put into § 2.5 Stream configuration packets. Any NOTE comments present before the first cue must be included alongside, in the way they appear, into the § 2.5 Stream configuration data.
The packet_data must contain the following structure:
| Type | Name | Value | Description |
|---|---|---|---|
u(32)
| cue_components_len | Length of the cue components. | |
cue_components_len*b(8)
| cue_comenents | A string with all cue components | |
(data_length - cue_components_len - 1)*u(8)
| cue_data | The actual line of text to present. |
After the timestamp for each cue (line), WebVTT allows a number of cue components to style the line, terminated by a newline. As they are not part of the line, they are separated, and provided upfront as cue_comenents. The line ending may be retained for the cue_data, allowing for direct copy of the cue data.
The timestamps for each cue are translated into a pts and duration, as with SubRip.
3.1.21. DNG/TIFF encapsulation
For DNG/TIFF encapsulation, the codec_id in § 2.3 Stream registration must be 0x54494646 (TIFF).
DNG/TIFF streams require no § 2.5 Stream configuration packets
The packet_data must contain a raw TIFF file, with one packet being a single picture.
3.1.22. JPEG encapsulation
For JPEG and Motion JPEG, the codec_id in the § 2.3 Stream registration must be 0x4a504547 (JPEG).
JPEG and Motion JPEG streams require no § 2.5 Stream configuration packets.
The packet_data must contain a raw JPEG file, with one packet being a single picture.
3.1.23. JPEG-2000 encapsulation
For JPEG-2000 streams, as defined by [ISO15444], the codec_id in the § 2.3 Stream registration must be 0x4a50324b (JP2K).
JPEG-2000 streams require no § 2.5 Stream configuration packets.
The packet_data must contain a raw JPEG-2000 frame.
The packet_data must not contain JP2 data (better known as the JPEG-2000 standalone container), but rather the raw, individual JPEG-2000 frames (known as J2K, or HTJ2K).
High-throughput JPEG-2000, as defined by [ISO15444-15], is supported and recommended. The same considerations as regular JPEG-2000 apply, but the codec_id in the § 2.3 Stream registration must be 0x48544a32 (HTJ2) instead.
3.1.24. PNG encapsulation
For PNG, the codec_id in the § 2.3 Stream registration must be 0x504e4730 (PNG0).
PNG streams require no § 2.5 Stream configuration packets.
The packet_data must contain a raw PNG file. No support for Animated PNG is defined, but simply not flagging the still picture flag (`stream_flags & 0x04`) and sending a single picture per frame is sufficient to animate PNG, as this is allowed for any codec.
3.1.25. SVG encapsulation
For [SVG2] (Scalable Vector Graphics), the codec_id in the § 2.3 Stream registration must be 0x53564732 (SVG2).
SVG streams require no § 2.5 Stream configuration packets.
The packet_data must contain a raw SVG file. Compressed SVGZ are explicitly not supported. Instead, the pkt_compression field must be used if compression is to be used. This is due to DEFLATE ([RFC1951]) being potentially a bottleneck in decompression.
No support for animated SVG (SVG 2 § 2.2.3 Animated mode) is available, or any SVG variant with Javascript embedded. Each SVG packet must be a raw and standalone. Embedded images are, however, permitted.
The width and height dimensions of § 2.15 Video information shall be a suggested dimension, generally set upon creation time.
Note: SVG streams may be either video streams or used as subtitles.
The STREAM_SUBTITLES flags must be set if the SVG stream is to be used as
subtitles.
3.1.26. Raw audio encapsulation
For raw audio encapsulation, the codec_id in § 2.3 Stream registration MUST be 0x52414141 (RAAA).
§ 2.5 Stream configuration packets are required, and must be laid out in the following way:
| Type | Name | Value | Description |
|---|---|---|---|
u(32)
| ra_channels | The number of channels contained. | |
b(8)
| ra_bits | The number of bits for each sample. | |
u(8)
| ra_float | If non-zero, data is floating-point. |
The packet_data must contain the concatenated stream of interleaved samples for all channels.
The samples must be normalized between [-1.0, 1.0] if they’re float, and full-range signed if they’re integers.
The size of each sample must be ra_bits, and must be aligned to the nearest power of two, with the padding in the least significant bits. That means that 24-bit samples are coded as 32-bits, with the data contained in the topmost 24 bits.
3.1.27. Raw video encapsulation
For raw video encapsulation, the codec_id in § 2.3 Stream registration MUST be 0x52415656 (RAVV).
Note: § 2.15 Video information packets must be present. The information in this structure is only sufficient to parse data, not enough to present it.
§ 2.5 Stream configuration packets are required, and must be laid out in the following way:
| Type | Name | Value | Description |
|---|---|---|---|
u(8)
| rv_components | The number of components the video stream contains. | |
u(8)
| rv_planes | The number of planes the video components are placed in. | |
u(8)
| rv_bpp | The number of bits for each individual component pixel. | |
u(32)
| rv_flags | enum RawVideoFlags
| Flags for the video stream. |
rv_planes*u(32)
| rv_plane_stride | For each plane, the total number of bytes per horizontal line, including any padding. | |
rv_components*u(8)
| rc_plane | Specifies the plane index that each component belongs in. | |
rv_components*u(8)
| rc_stride | Specifies the distance between 2 horizontally consequtive pixels for each component, in bits for bitpacked video, otherwise bytes. | |
rv_components*u(8)
| rc_offset | Specifies the number of elements before each component, in bits for bitpacked video, otherwise bytes. | |
rv_components*i(8)
| rc_shift | Specifies the number of bits to shift right (if negative) or shift left (is positive) to get the final value. | |
rv_components*u(8)
| rc_bits | Specifies the total number of bits the component’s value will contain. |
The purpose of the rc_offset field is to allow differentiation between
different orderings of pixels in an RGB video, e.g. RGB’s rc_offsets will
be [0, 1, 2], whilst BGR’s will be [2, 1, 0].
The components MUST be given in the order they appear in the stream.
The packet_data field must contain rv_planes, with each plane having rv_plane_stride bytes per line.
The number of horizontal lines is height, whicl will be modified by the value of chroma_subsampling for each individual plane as specified.
The actual data within the lines must be filled in according to rc_offset and rc_stride.
3.1.28. Raw Video Flags Enumeration (enum RawVideoFlags)
The rv_flags field must be interpreted in the following way:
RAW_VIDEO_FLOAT= 0x1-
Video contains [IEEE-754] normalized floating point values. Size is determined by the rv_bpp value.
RAW_VIDEO_ALPHA= 0x2-
Video contains a stright, non-premultiplied alpha. Alpha is always the last component.
RAW_VIDEO_ALPHA_PREMULTIPLIED= 0x4-
Video contains a premultiplied alpha channel. Alpha is always the last component.
RAW_VIDEO_PLANAR= 0x8-
At least one pixel component is not sharing a plane, e.g. video is planar.
RAW_VIDEO_BITPACKED= 0x10-
Video’s components are tightly packed, e.g. video is bitpacked.
RAW_VIDEO_BIG_ENDIAN= 0x20-
Video’s values are big-endian. If unset, values are little-endian. Does not apply for bitpacked video.
Note: rv_flags must not signal both RAW_VIDEO_ALPHA and RAW_VIDEO_ALPHA_PREMULTIPLIED.
Such a combination of flags is undefined.
This structure is flexible enough to permit zero-copy or one-copy streaming of video from most sources.
3.1.29. Custom codec encapsulation
A special section is dedicated for custom codec storage. While potentially useful for experimentation and for specialized usecases, users of such are invited to submit an addendum to this document to formalize such containerization. This field MUST NOT be used if the codec being contained already has a formal definition in this spec.
For custom encapsulation, the codec_id in § 2.3 Stream registration must be
0x433f**** (C?**), where the bottom 2 bytes can be any value between
0x30 to 0x39 (0 to 9 in ASCII) and
0x61 to 0x7a (a to z in ASCII).
The § 2.5 Stream configuration payload can be any length and contain any sequence of data.
The packet_data field can be any length and contain any sequence of data.
3.2. Streaming
This section describes and suggests behavior for realtime AVTransport streams.
The protocol supports four different streaming arrangements:
-
Unidirectional (Sender to Receiver)
-
Bidirectional (Sender to Receiver and Receiver to Sender)
-
Multidirectional prompted (Sender to Multiple Active Receivers)
-
Multicast (Sender to Multiple Receivers)
In the first case (Unidirectional), the sender initializes the session by sending a § 2.1 Session start to the receiver, and proceeds with sending more packets.
In the second case (Bidirectional), the sender initializes the session by sending a § 2.1 Session start
packet with a SESSION_REVERSE_SIGNAL_READY flag, and on the same connection, the receiver sends another
§ 2.1 Session start packet to initialize reverse connectivity.
In the third case (Multidirectional prompted) case, the sender listens for any § 2.1 Session start sent by clients on a given port. If received, the server begins to send information back to the client address on the same connection it received the session start packet.
In the fourth case (Multicast), the server binds to a multicast UDP address and begins to send data.
Users are strongly recommended to follow the recommendations given in § 4.2.2 Streaming recommendations.
3.2.1. UDP
To adapt AVTransport for streaming over UDP is trivial - simply send the data packets as-is specified, with no changes required. The sender implementation should resent packets at the frequencies listed in § 2.1 Session start to permit for implementations that didn’t catch on the start of the stream begin decoding.
UDP mode is unidirectional, but the implementations are free to use the
§ 3.3 Reverse signalling data if they negotiate it themselves.
Reverse signalling should not be used if the connection is public.
Implementations must segment the data such that the network MTU is never
exceeded and no packet fragmentation occurs.
The minimum network MTU required for the protocol is 384 bytes,
as to allow § 2.15 Video information or any future large
packets to be sent without fragmentation.
Jumbograms may be used where supported to reduce overhead and increase efficiency.
Note: Data packets may be padded by appending zeroed bytes after the packet_data field up to the maximum MTU size. This permits constant bitrate operation, as well as preventing metadata leakage in the form of a packet size.
Note: When operating at higher MTUs, implementations should consider adding FEC or parity, as the 16-bit UDP datagram CRC may be inadequate to detect errors.
If § 3.3 Reverse signalling is used, the receiver must send packets over to the sender using the same port number that the receiver is listening on.
3.2.2. QUIC
AVTransport tries to use as much of the modern conveniences of QUIC: A UDP-Based Multiplexed and Secure Transport § QUIC# as possible. As such, it uses both reliable and unreliable streams, as well as bidirectionality features of the transport mechanism.
All data packets with descriptors 0x01**, 0x02**, 0xFF, 0xFE, 0xFD and 0xFC must be sent over in an unreliable QUIC datagram stream, as per [RFC9221]. Each stream must map to a different QUIC stream, though their AVTransport and QUIC stream IDs do not have to match.
All other packets must be sent over a reliable steam. FEC data for those packets should not be signalled.
Implementations must segment the data such that the network MTU is never exceeded and no packet fragmentation occurs.
The minimum network MTU required for the protocol is 384 bytes, as to allow § 2.15 Video information or any future large packets to be sent without fragmentation.
The ALPN must contain the extension 0x61, 0x76, 0x74, 0x30 (avt0).
Jumbograms may be used where supported to reduce overhead and increase efficiency.
§ 3.3 Reverse signalling is natively supported on QUIC.
3.2.3. Packetized networks
AVTransport is a series of individual packets with no overarching data structure. This allows for it to be contained over any protocol or transmitted over any packetized network.
The built-in resilience in each data structure makes the protocol suitable even over connections with a high bit error rate.
Poor connection reliability can be largely overcome by using § 2.8 FEC grouping.
This specification does not specify how linking or transmission is performed - only that the AVTransport packets remain compliant with their definition here, and the stream as a whole remains compliant.
3.2.4. Serial
AVTransport explicitly carries the size of the contained data. This makes it suitable for not only packetized networks, but also serial links.
Users must track the start of each AVTransport packet themselves, using the packet headers and, optionally, LDPC data to synchronize with the source.
The specification contains no recommendation on how the data is transported. Users should, if necessary, use FEC and other reliability features.
3.3. Reverse signalling
AVTransport supports bidirectional connections. Implementing this part of the specification is fully optional.
All packets send back from a receiver to the transmitter must have bit 0x8000 set in their descriptors. This means that the receiver can send back the same type of packets that the transmitter can, with a number of extra packets for control.
Receivers must receive a § 2.1 Session start packet
from a transmitter, with bit SESSION_REVERSE_SIGNAL_READY set in the session_flags
bitmask before they are allowed to send packets back.
3.3.1. Session control data
The receiver can use this type to return errors and more to the sender in a one-to-one transmission. The following syntax is used:
| Type | Name | Data | Description |
|---|---|---|---|
b(16)
| session_control_descriptor | 0x8001 | Indicates this is a control data packet. |
b(8)
| cease | If not equal to 0x0, indicates a fatal error, and senders MUST NOT sent any more data. | |
u(8)
| resend_init | If nonzero, asks the sender to resend all § 2.2 Time synchronization, all § 2.3 Stream registration and all required packets for them. | |
u(32)
| error | enum ErrorCode
| Indicates an error code, if not equal to 0x0. |
b(128)
| uplink_ip | Reports the upstream address to stream to. | |
u(16)
| uplink_port | Reports the upstream port to stream on to the uplink_ip. | |
b(8)
| seek | If 1, Asks the sender to seek to the position given by seek_pts and/or seek_seq. | |
i(64)
| seek_pts | The pts value to seek to. | |
u(32)
| seek_seq | The sequence number of the packet to seek to. |
If the sender gets such a packet, and either its uplink_ip or its uplink_port do not match, the sender must cease this connection, reopen a new connection with the given uplink_ip, and resend all packets needed to begin decoding to the new destination.
The seek request asks the sender to begin sending old data that is still available. The sender may not comply if that data suddenly becomes unavailable. If the value of seek is equal to 0, then the receiver must comply and always start sending the newest data.
If the resend_init flag is set to a non-zero value, senders should flush all encoders such that the receiver can begin decoding as soon as possible.
If operating over QUIC, then any old data must be served over a reliable stream, as latency isn’t critical. If the receiver asks again for the newsest available data, that data’s payload is once again sent over an *unreliable* stream.
The following error values are allowed:
3.3.2. Error Code Enumeration (enum ErrorCode)
ERROR_CODE_GENERIC= 0x1-
Signals a generic error.
ERROR_CODE_UNSUPPORTED= 0x2-
Unsupported data. May be sent after the sender sends a § 2.3 Stream registration to indicate that the receiver does not support this codec. The sender may send another packet of this type with the same stream_id to attempt reinitialization with different parameters.
3.3.3. Feedback
The following packet MAY be sent from the receiver to the sender.
| Type | Name | Data | Description |
|---|---|---|---|
b(16)
| stream_feedback_descriptor | 0x8002 | Indicates this is a statistics packet. |
b(16)
| stream_id | Indicates the stream ID for which this packet is relevant to. May be 0xFFFF to indicate all streams. | |
u(64)
| epoch_offset | Time since epoch. May be 0. Can be used to estimate the latency. | |
u(64)
| bandwidth | Hint that indicates the available receiver bandwith, in bits per second. May be 0, in which case infinite must be assumed. Senders should respect it. The figure should include all headers and associated overhead. | |
u(64)
| fec_corrections | A counter that indicates the total amount of repaired packets (packets with errors that FEC was able to correct). | |
u(64)
| corrupt_packets | Indicates the total number of corrupt packets. This also counts corrupt packets FEC was not able to correct. | |
u(64)
| dropped_packets | Indicates the total number of dropped packets. |
Receivers should send out a new statistics packet every time a count was updated. Additionally, receivers should send new feedback packets often enough to prevent UDP NAT from timing out.
3.3.4. Resend
The following packet MAY be sent to ask the client to resend a recent packet that was likely dropped.
| Type | Name | Data | Description |
|---|---|---|---|
b(16)
| packet_resend_descriptor | 0x8003 | Indicates this is a stream data resend packet. |
b(16)
| padding | Padding, reserved for future use. Must be 0x0. | |
u(32)
| global_seq | The sequence number of the packet that is missing. |
3.3.5. Stream control
The receiver can use this type to subscribe or unsubscribe from streams.
| Type | Name | Data | Description |
|---|---|---|---|
b(16)
| stream_control_descriptor | 0x8004 | Indicates this is a stream control data packet. |
b(16)
| stream_id | The stream ID for which this packet applies to. MUST NOT be 0xFFFF. | |
u(32)
| global_seq | If `1`, asks the sender to not send any packets relating to stream_id streams. |
This can be used to save bandwidth. If previously disabled and then enabled, all packets necessary to initialize the stream MUST be resent.
3.4. Informative muxer behaviour
This annex covers recommended practices for muxers, particularly with regards to avoiding stream starvation.
3.5. Informative demuxer behaviour
This annex covers recommended practices for demuxers, mainly with packet lifetime, buffering, and reordering.
4. Annex
Additional data or recommendations for the AVTransport specification is listed here.
4.1. Annex A: Metadata tags
The following string keys should be used, instead of any others:
title— text string-
Full name of the stream.
language— text string-
Language name subtag, as per [bcp47].
language_tag— text string-
More concise language information, including regional variants, as defined by Tags for Identifying Languages § section-2.1.
date— text string-
Date of release. MUST be formatted according to [RFC3339].
track— unsigned integer-
Track number, if the stream is part of an album.
tracks— unsigned integer-
Total number of tracks, if stream is part of an album.
artist— text string-
Full name of the performing artist on this track.
album_artist— text string-
Full name of the album’s artist.
album— text string-
Full name of the album.
comment— text string-
Arbitrary release details.
disc— unsigned integer-
Disc number, in case of multi-disc releases.
discs— unsigned integer-
Total number of discs, in case of multi-disc releases.
media_type— text string-
Original media type of the release.
isrc— text string-
International Standard Recording Code of the given track.
mcn— text string-
Media Catalog Number for the album, if available.
REPLAYGAIN_TRACK_GAIN— floating point number-
ReplayGain 2.0 track gain, in dB.
REPLAYGAIN_TRACK_RANGE— floating point number-
ReplayGain 2.0 track range, in dB.
REPLAYGAIN_TRACK_PEAK— floating point number-
ReplayGain 2.0 track peak, in dB.
REPLAYGAIN_REFERENCE_LOUDNESS— floating point number-
ReplayGain 2.0 reference loudness, in LUFS.
encoder— list of properties-
A list of settings used for encoding.
The language field must be formatted as a subtag, according to the [bcp47].
The language_tag field must be formatted as described in Tags for Identifying Languages § section-2.1.
It provides more detailed information than the language field,
including regional variation and script.
The date field must be formatted according to [RFC3339].
If the value type differs, or is formatted in a different way outside of these specifications, then the metadata field is considered invalid.
4.2. Annex B: Recommended practices
This section covers recommended practices for AVTransport streams in common circumstances.
4.2.1. Archival recommendations
For archival, it is recommended to limit the packet size to the maximum packet size that the storage medium natively operates at. This ensures that the native error correction capabilities work to enhance the capabilities of AVTransport.
It is recommended to use FEC groups encapsulating every stream, with a fec_nb_packets of sufficient length to eliminate any remaining packet errors that slip by.
4.2.2. Streaming recommendations
In general, implementations should emit the following packet types at the given frequencies.
| Packet type | Suggested frequency | Description |
|---|---|---|
| § 2.1 Session start | Target startup delay | To identify a stream as AVTransport without ambiguity. |
| § 2.2 Time synchronization | Target startup delay | Optional time synchronization field to establish an epoch and do timestamp jitter compensation. |
| § 2.3 Stream registration | Target startup delay | Register streams to permit packet processing. |
| § 2.5 Stream configuration | Target startup delay | To initialize decoding of stream packets. |
| § 2.15 Video information | Target startup delay | To correctly present any video packets. |
| § 2.13 LUT/ICC profile | Target startup delay | Optional LUT/ICC profile for correct video presentation. |
| § 2.16 Video orientation | Target startup delay | Video orientation packets, when needed. |
| § 2.12 Metadata | Target startup delay | Session metadata. |
| § 2.6 Stream Data | Always | Stream data packets. |
| § 2.8 FEC grouping | Appropriate for the packet loss | Optional FEC data. |
| § 2.18 User data | As often as necessary | Optional user data packets. |
| § 2.20 End of stream | Once | Finalizes a stream or session. |
In particular, § 2.2 Time synchronization packets should be sent as often as necessary if timestamp jitter avoidance is a requirement.
4.3. Annex W: LDPC
This normative annex shall cover the usage and operation of [LDPC] within AVTransport.
The LDPC variant to be used is irregular (each row of each matrix has a non-constant amount of bits set to 1), systematic (parity data is separate from message data), with no subblocks. The full block, along with the check data, shall be sent to an LDPC decoder.
To ease implementations, only two different lengths are used:
-
LDPC(288, 224)
-
224-bit message, 64-bit parity, rate of
7/9, H₆₄ₓ₂₈₈-matrix
-
-
LDPC(2784, 2016)
-
2016-bit message, 768-bit parity, rate of
21/29, H₇₆₈ₓ₂₇₈₄-matrix
-
For reference, the following code may be used to compute the LDPC parity data:
void ldpc_encode ( uint8_t * pkt , const uint64_t * W , int message_bits , int parity_bits ) { int j , k , w ; int words = parity_bits / 64 ; uint64_t parity , data , bits [ 8 ]; /* Parity data goes last */ uint8_t * dst = pkt + ( message_bits / 8 ); /* Compute one 64-row slice of the parity vector at a time */ for ( w = 0 ; w < words ; w ++ ) { parity = 0x0 ; /* Start with zero parity */ /* Process 8 message bits at a time */ for ( j = 0 ; j < ( message_bits / 8 ); j ++ ) { data = pkt [ j ]; /* Duplicate each bit 64 times (reversed, bytestream order) */ for ( k = 0 ; k < 8 ; k ++ ) bits [ k ] = (( data >> ( 7 - k )) & 1 ) * UINT64_MAX ; /* XOR in the generator column of every message bit set to 1 */ for ( k = 0 ; k < 8 ; k ++ ) parity ^= bits [ k ] & W [( j * 8 + k ) * words + w ]; } /* Write this slice of parity data, in bytestream order */ for ( k = 56 ; k >= 0 ; k -= 8 ) * dst ++ = ( parity >> k ) & 0xFF ; } }
This code is provided as a reference, and although more efficient algorithms exist, embedded devices and microcontrollers are able to perform millions of LDPC(288, 224) encodings per second with it.
Implementations should consider using more advanced encoding algorithms, such as the Richardson-Urbanke method to reduce the overhead further.
4.3.1. LDPC matrices
Each code is defined by a parity-check matrix H of size (n - k) ⨉ n —thus 64 ⨉ 288 and 768 ⨉ 2784.
Note: In mathematical notation, matrix sizes are specified as height ⨉ width, not width ⨉ height. This specification uses mathematical nomenclature for this definition.
The matrices are irregular, systematic, and optimized for AWGN channels (though
they perform nearly as well in other circumstances). The first k columns of H
hold the message bits and the last n - k columns the parity bits; the parity
columns do not form an identity matrix.
Because of that, encoding does not use H directly — it uses the systematic generator matrix
W, the (n - k) ⨉ k matrix Hp-1·Hd,
where Hd and Hp are the message- and parity-bit column
blocks of H. The parity bits of a message u are then p = W·u
over GF(2). This is what the reference routine above consumes; H itself is used for
decoding.
As each matrix value is purely boolean, columns are stored as 64-bit unsigned integers in big
endian format: the most significant bit holds the topmost row. A column taller than 64 rows is
stored as (n - k) / 64 consecutive integers, the topmost 64 rows first, and
columns are stored one after another.
The H-matrices are provided alongside this specification as standard MacKay alist files,
ldpc_288_224.alist and ldpc_2784_2016.alist, directly usable for
analysis and simulation. The reference implementation embeds both H and the derived generator
matrices W as uint64_t arrays.