PROTOCOLS
DelayWatcher
Defined in fuchsia.audio/delay.fidl
Watches for a delay to change.
WatchDelay
The first call returns immediately with the current delay, if known. Subsequent calls block until the delay changes. There can be at most one outstanding call, otherwise the channel may be closed.
Request
Name | Type |
---|---|
payload |
DelayWatcherWatchDelayRequest
|
Response
Name | Type |
---|---|
payload |
DelayWatcherWatchDelayResponse
|
GainControl
Defined in fuchsia.audio/gain.fidl
Enables control and monitoring of audio gain. This interface is typically a tear-off of other interfaces.
Knobs
This interface exposes two orthogonal knobs:
-
The gain knob controls a single value in "relative decibels". A value of 0 applies no gain, positive values increase gain, and negative values decrease gain. Depending on context, gain may be applied relative to an input stream or relative to some absolute reference point, such as the maximum loudness of a speaker.
This knob has no defined maximum or minimum value. Individual implementations may clamp to an implementation-defined maximum value or treat all values below an implementation-defined minimum value equivalent to "muted", but this behavior is not required.
-
The mute knob controls a single boolean value. When
true
, the GainControl is muted and the effective gain is negative infinity. Whenfalse
, gain is controlled by the gain knob.
Scheduling
Changes to the gain and mute knobs can be scheduled for a time in the future. Scheduling happens on timestamps relative to a reference clock which must be established when this protocol is created.
TODO(https://fxbug.dev/42176154): scheduling semantics are subject to change
SetGain
Sets the gain knob.
Request
Name | Type |
---|---|
payload |
GainControlSetGainRequest
|
Response
Name | Type |
---|---|
payload |
GainControl_SetGain_Result
|
SetMute
Set the mute knob.
Request
Name | Type |
---|---|
payload |
GainControlSetMuteRequest
|
Response
Name | Type |
---|---|
payload |
GainControl_SetMute_Result
|
StreamSink
Defined in fuchsia.audio/stream_sink.fidl
A packet sink for cross-process audio stream transport, implemented by audio consumers and used by audio producers.
End
Indicates that the end of the stream has been reached. Consumers such as audio renderers
signal their clients when the last packet before end-of-stream has been rendered, so the
client knows when to, for example, change the UI state of a player to let the user know the
content is done playing. This method is logically scoped to the current segment. A
SetSegment
request and (typically) more packets may follow this request.
Request
<EMPTY>
OnWillClose
Sent immediately before the consumer closes to indicate why the consumer is closing the connection. After sending this event, the consumer must refrain from sending any more messages and close the connection promptly.
Response
Name | Type |
---|---|
payload |
StreamSinkOnWillCloseRequest
|
PutPacket
Puts a packet to the sink.
Request
Name | Type |
---|---|
payload |
StreamSinkPutPacketRequest
|
StartSegment
Starts a new segment. Packets following this request and preceding the next such request are assigned to the segment.
Request
Name | Type |
---|---|
payload |
StreamSinkStartSegmentRequest
|
WillClose
Sent immediately before the producer closes to indicate why the producer is closing the connection. After sending this request, the producer must refrain from sending any more messages and close the connection promptly.
Request
Name | Type |
---|---|
payload |
StreamSinkWillCloseRequest
|
STRUCTS
UnspecifiedBestEffort
Defined in fuchsia.audio/stream_sink.fidl
<EMPTY>
UnspecifiedContinuous
Defined in fuchsia.audio/stream_sink.fidl
<EMPTY>
ENUMS
ChannelConfig flexible
Type: uint32
Defined in fuchsia.audio/format.fidl
Spatial assignment of channels.
Name | Value | Description |
---|---|---|
MONO |
1 |
Front.C (CENTER) |
STEREO |
2 |
Front.L (LEFT) | Front.R (RIGHT) |
QUAD |
3 |
Front.L | Front.R | Back.L | Back.R, aka “Four corners” |
SURROUND_3 |
4 |
Front.L | Front.R | Back.C, aka “LRS” |
SURROUND_4 |
5 |
Front.L | Front.R | Front.C | Back.C, aka “LRCS” |
SURROUND_5_1 |
6 |
Front.L | Front.R | Front.C | LFE | Side.L | Side.R |
CompressionType flexible
Type: uint32
Defined in fuchsia.audio/compression.fidl
Name | Value | Description |
---|---|---|
NONE |
0 |
|
AAC |
1 |
|
AACLATM |
2 |
|
AMRNB |
3 |
|
AMRWB |
4 |
|
APTX |
5 |
|
FLAC |
6 |
|
GSMMS |
7 |
|
MP3 |
8 |
|
PCMALAW |
9 |
|
PCMMULAW |
10 |
|
SBC |
11 |
|
VORBIS |
12 |
|
OPUS |
13 |
GainError flexible
Type: uint32
Defined in fuchsia.audio/gain.fidl
Type of errors returned by GainControl
.
Name | Value | Description |
---|---|---|
MISSING_REQUIRED_FIELD |
1 |
A required field was not provided. |
UNSUPPORTED_OPTION |
2 |
A flexible field had an unsupported option. This can happen when a client built with API version X+1 talks to a server built with API version X. |
SampleType flexible
Type: uint32
Defined in fuchsia.audio/format.fidl
Expresses the type of individual audio samples.
Name | Value | Description |
---|---|---|
UINT_8 |
1 |
|
INT_16 |
2 |
|
INT_32 |
3 |
|
FLOAT_32 |
4 |
|
FLOAT_64 |
5 |
TABLES
Compression
Defined in fuchsia.audio/compression.fidl
Describes the compression applied to a stream.
Ordinal | Field | Type | Description |
---|---|---|---|
1 |
type |
CompressionType
|
The type of compression applied to the stream. |
2 |
oob_parameters |
vector<uint8>:32768
|
Opaque ‘out-of-band’ parameters describing the compression of the stream. The format of
this field is a function of the |
DelayWatcherWatchDelayRequest
Defined in fuchsia.audio/delay.fidl
Ordinal | Field | Type | Description |
---|
DelayWatcherWatchDelayResponse
Defined in fuchsia.audio/delay.fidl
Ordinal | Field | Type | Description |
---|---|---|---|
1 |
delay |
zx/Duration
|
Optional. If not specified, the delay is unknown. |
Format
Defined in fuchsia.audio/format.fidl
Describes a format used for audio streams without reference to compression. Where
compression is supported, this type should be combined with fuchsia.media2.Compression
.
An uncompressed audio stream uses LPCM encoding.
Ordinal | Field | Type | Description |
---|---|---|---|
1 |
sample_type |
SampleType
|
The type of individual samples. |
2 |
channel_count |
uint32
|
The number of samples per frame. |
3 |
frames_per_second |
uint32
|
The number of frames per second. |
4 |
channel_layout |
ChannelLayout
|
The spatial assignment of each channel. |
GainControlSetGainRequest
Defined in fuchsia.audio/gain.fidl
Ordinal | Field | Type | Description |
---|---|---|---|
1 |
how |
GainUpdateMethod
|
How to update the gain knob. Required. |
2 |
when |
fuchsia.media2/RealTime
|
When to apply this update. Required. |
GainControlSetMuteRequest
Defined in fuchsia.audio/gain.fidl
Ordinal | Field | Type | Description |
---|---|---|---|
1 |
muted |
bool
|
New value of the mute knob. Required. |
2 |
when |
fuchsia.media2/RealTime
|
When to apply this update. Required. |
GainControl_SetGain_Response
Defined in fuchsia.audio/gain.fidl
Ordinal | Field | Type | Description |
---|
GainControl_SetMute_Response
Defined in fuchsia.audio/gain.fidl
Ordinal | Field | Type | Description |
---|
Packet
Defined in fuchsia.audio/stream_sink.fidl
Describes a packet delivered via StreamSink
.
Ordinal | Field | Type | Description |
---|---|---|---|
1 |
payload |
fuchsia.media2/PayloadRange
|
Location of the payload for this packet. This field is required. |
2 |
timestamp |
Timestamp
|
Timestamp indicating when this packet should be presented. Omitting this field implies an
|
3 |
capture_timestamp |
zx/Time
|
Capture time for this packet as a system monotonic time value. This field is optional and may be set by capturers to indicate when this packet was captured. |
4 |
flags |
PacketFlags
|
Flags describing the packet. Omitting this field implies all flags are clear. |
5 |
front_frames_to_drop |
uint32
|
Indicates how many frames should be dropped from the front of the output packet produced by a decoder from this input packet. This value should only be provided for compressed streams. If this field is omitted, no front frames should be dropped. |
6 |
back_frames_to_drop |
uint32
|
Indicates how many frames should be dropped from the back of the output packet produced by a decoder from this input packet. This value should only be provided for compressed streams. If this field is omitted, no back frames should be dropped. |
7 |
encryption_properties |
fuchsia.drm/PacketEncryptionProperties
|
Describes the encryption applied to this packet. Omitting this field implies the packet is not encrypted. |
RampFunctionLinearSlope
Defined in fuchsia.audio/gain.fidl
Gain follows a linear slope over a linear domain.
For example, a ramp from gain -2.3dB to -1.6dB is a ramp in the linear domain from 0.1 to 0.5. If this is applied over 4ms, then the sequence of gain updates is:
- At 0ms, gain = 0.1 = -2.3dB
- At 1ms, gain = 0.2 = -2.0dB
- At 2ms, gain = 0.3 = -1.8dB
- At 3ms, gain = 0.4 = -1.7dB
- At 4ms, gain = 0.5 = -1.6dB
Note that the changes in dB follow a logarithmic (not linear) curve.
Ordinal | Field | Type | Description |
---|
RampedGain
Defined in fuchsia.audio/gain.fidl
Describes a ramped gain command. When this command is applied, gain is ramped from its current value to the target value, over the specified duration, using the specified function.
Ordinal | Field | Type | Description |
---|---|---|---|
1 |
target_gain_db |
float32
|
|
2 |
duration |
zx/Duration
|
|
3 |
function |
RampFunction
|
RingBuffer resource
Defined in fuchsia.audio/ring_buffer.fidl
A ring buffer of audio data.
Each ring buffer has a producer (who writes to the buffer) and a consumer (who reads from the buffer). Additionally, each ring buffer is associated with a reference clock that keeps time for the buffer.
PCM Data
A ring buffer of PCM audio is a window into a potentially-infinite sequence
of frames. Each frame is assigned a "frame number" where the first frame in
the infinite sequence is numbered 0. Frame X
can be found at ring buffer
offset (X % RingBufferFrames) * BytesPerFrame
, where RingBufferFrames
is
the size of the ring buffer in frames and BytesPerFrame
is the size of a
single frame.
Concurrency Protocol
Each ring buffer has a single producer and a single consumer which are synchronized by time. At each point in time T according to the ring buffer's reference clock, we define two functions:
-
SafeWritePos(T)
is the lowest (oldest) frame number the producer is allowed to write. The producer can write to this frame or to any higher-numbered frame. -
SafeReadPos(T)
is the highest (youngest) frame number the consumer is allowed to read. The consumer can read this frame or any lower-numbered frame.
To prevent conflicts, we define these to be offset by one:
SafeWritePos(T) = SafeReadPos(T) + 1
To avoid races, there must be a single producer, but there may be multiple consumers. Additionally, since the producer and consumer(s) are synchronized by time, we require explicit fences to ensure cache coherency: the producer must insert an appropriate fence after each write (to flush CPU caches and prevent compiler reordering of stores) and the consumer(s) must insert an appropriate fence before each read (to invalidate CPU caches and prevent compiler reordering of loads).
Since the buffer has finite size, the producer/consumer cannot write/read
infinitely in the future/past. We allocate P
frames to the producer and
C
frames to the consumer(s), where P + C <= RingBufferFrames
and P
and
C
are both chosen by whoever creates the ring buffer.
Deciding on P
and C
In practice, producers/consumers typically write/read batches of frames
on regular periods. For example, a producer might wake every Dp
milliseconds to write DpFrameRate
frames, where FrameRate
is the PCM
stream's frame rate. If a producer wakes at time T, it will spend up to the
next Dp
period writing those frames. This means the lowest frame number it
can safely write to is SafeWritePos(T+Dp)
, which is equivalent to
SafeWritePos(T) + DpFrameRate
. The producer writes DpFrameRate
frames
from the position onwards. This entire region, from SafeWritePos(T)
through 2DpFrameRate
must be allocated to the producer at time T. Making
a similar argument for consumers, we arrive at the following constraints:
P >= 2DpFrameRate
C >= 2Dc*FrameRate
RingBufferFrames >= P + C
Hence, in practice, P
and C
can be derived from the batch sizes used by
the producer and consumer, where the maximum batch sizes are limited by the
ring buffer size.
Defining SafeWritePos
The definition of SafeWritePos
(and, implicitly, SafeReadPos
) must be
provided out-of-band.
Non-PCM Data
Non-PCM data is handled similarly to PCM data, except positions are expressed as "byte offsets" instead of "frame numbers", where the infinite sequence starts at byte offset 0.
Ordinal | Field | Type | Description |
---|---|---|---|
1 |
buffer |
fuchsia.mem/Buffer
|
The actual ring buffer. The sum of Required. |
2 |
format |
Format
|
Encoding of audio data in the buffer. Required. |
3 |
producer_bytes |
uint64
|
The number of bytes allocated to the producer. For PCM encodings, For non-PCM encodings, there are no constraints, however individual encodings may impose stricter requirements. Required. |
4 |
consumer_bytes |
uint64
|
The number of bytes allocated to the consumer. For PCM encodings, For non-PCM encodings, there are no constraints, however individual encodings may impose stricter requirements. Required. |
5 |
reference_clock |
handle<clock>
|
Reference clock for the ring buffer. Required. |
6 |
reference_clock_domain |
uint32
|
Domain of Optional. If not specified, defaults to |
StreamSinkOnWillCloseRequest
Defined in fuchsia.audio/stream_sink.fidl
Ordinal | Field | Type | Description |
---|---|---|---|
1 |
reason |
fuchsia.media2/ConsumerClosedReason
|
Reason the connection will close. |
StreamSinkPutPacketRequest resource
Defined in fuchsia.audio/stream_sink.fidl
Ordinal | Field | Type | Description |
---|---|---|---|
1 |
packet |
Packet
|
Describes the packet. This field is required. |
2 |
release_fence |
handle<eventpair>
|
Eventpair closed when the consumer is done with the packet and the buffer region
associated with the packet may be reused. Packets may be released in any order. The
release fence may be duplicated by the service, so it must be sent with right
|
StreamSinkStartSegmentRequest
Defined in fuchsia.audio/stream_sink.fidl
Ordinal | Field | Type | Description |
---|---|---|---|
1 |
segment_id |
int64
|
Identifies the segment. New segment IDs for a given connection must always be strictly increasing. This field is required. |
StreamSinkWillCloseRequest
Defined in fuchsia.audio/stream_sink.fidl
Ordinal | Field | Type | Description |
---|---|---|---|
1 |
reason |
fuchsia.media2/ProducerClosedReason
|
Reason the connection will close. |
UNIONS
ChannelLayout flexible
Defined in fuchsia.audio/format.fidl
Expresses the intended assignment of channels in an audio elementary stream.
Ordinal | Variant | Type | Description |
---|---|---|---|
1 |
config |
ChannelConfig
|
This value describes the assignment of every channel. Channel
configuration must agree with |
GainControl_SetGain_Result strict
Defined in fuchsia.audio/gain.fidl
Ordinal | Variant | Type | Description |
---|---|---|---|
1 |
response |
GainControl_SetGain_Response
|
|
2 |
err |
GainError
|
GainControl_SetMute_Result strict
Defined in fuchsia.audio/gain.fidl
Ordinal | Variant | Type | Description |
---|---|---|---|
1 |
response |
GainControl_SetMute_Response
|
|
2 |
err |
GainError
|
GainUpdateMethod flexible
Defined in fuchsia.audio/gain.fidl
Supported types of gain updates.
Ordinal | Variant | Type | Description |
---|---|---|---|
1 |
gain_db |
float32
|
Immediately set the gain to this value. |
2 |
ramped |
RampedGain
|
Change the gain gradually using a ramp. |
RampFunction flexible
Defined in fuchsia.audio/gain.fidl
Supported types of ramping functions.
Ordinal | Variant | Type | Description |
---|---|---|---|
1 |
linear_slope |
RampFunctionLinearSlope
|
Timestamp flexible
Defined in fuchsia.audio/stream_sink.fidl
Indicates the position of an audio packet in the stream timeline.
Ordinal | Variant | Type | Description |
---|---|---|---|
1 |
specified |
int64
|
Specific time in the stream timeline. Units vary and are provided when the connection is established. |
2 |
unspecified_continuous |
UnspecifiedContinuous
|
Indicates the packet should be presented immediately after the previous packet, if there is
a previous packet. If there is no previous packet, this option is equivalent to a
This option implies that the stream timeline should not ‘slip’ even if the packet arrives late. The packet is intended to be presented immediately after the previous packet, and the resulting timing is to be maintained regardless of the arrival time of the packet. |
3 |
unspecified_best_effort |
UnspecifiedBestEffort
|
Indicates the packet should be presented as soon as possible after the previous packet, if there is one, as soon as possible if not. This option implies that the stream time should ‘slip’ if the packet arrives too late to be rendered immediately after the previous packet. This option is often used when a gap occurs in an un-timestamped stream, perhaps due to a lossy upstream source. |
BITS
PacketFlags flexible
Type: uint32
Defined in fuchsia.audio/stream_sink.fidl
Flags describing a packet.
Name | Value | Description |
---|---|---|
DROP_AFTER_DECODE |
1 | Indicates that this packet is provided only so that later packets can be interpreted. A decoder should drop the decompressed packets generated from this packet. |
CONSTANTS
Name | Value | Type | Description |
---|---|---|---|
MAX_COMPRESSION_PARAMETERS_SIZE |
32768
|
uint64 |
The maximum size of |