blob: 71da8f31659fc0bf7465abc870f067b0d4cca72d [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
library fuchsia.hardware.audio;
using zx;
// For an overview see //zircon/driver_interfaces/audio_streaming.md
table RingBufferProperties {
/// The driver's best estimate of the external delay (in nanoseconds) present in the
/// presentation pipeline for the chosen format. When precisely synchronizing presentation
/// across multiple entities (e.g. devices), the external delay should be taken into account.
1: zx.duration external_delay;
/// Size (in bytes) representing a temporary buffer used by the driver in order to consume or
/// generate the ring buffer contents. The ring buffer contents must be produced and consumed
/// at the rate specified with the `CreateRingBuffer` command, however some amount of buffering
/// is required when the data is written into and read from the ring buffer. For playback the
/// data is consumed by the driver by reading ahead up to `fifo_depth` bytes. For capture the
/// data is produced by the driver holding up to `fifo_depth` bytes at the time before
/// committing it to main system memory. Hence `fifo_depth` must be taken into account by the
/// client when determining either the minimum lead time requirement (for playback) or the
/// maximum capture delay (for capture).
///
/// To convert `fifo_depth` to the corresponding number of audio frames, use the frame size
/// returned by `CreateRingBuffer` in the `StreamConfig` protocol, note that the `fifo_depth`
/// is not necessarily a multiple size of an audio frame.
///
/// The ring buffer data may be directly consumed/generated by hardware, in this case
/// `fifo_depth` maps directly to the size of a hardware FIFO block, since the hardware FIFO
/// block determines the amount of data read ahead or held back.
///
/// The ring buffer data may instead be consumed/generated by audio driver software that is
/// conceptually situated between the ring buffer and the audio hardware. In this case, for
/// playback the `fifo_depth` read ahead amount is set large enough such that the driver
/// guarantees no undetected underruns, this assuming the client is generating the data as
/// determined by the `CreateRingBuffer` and `Start` commands. For capture, the
/// `fifo_depth` held back amount is set large enough such that the driver guarantees no
/// undetected underruns when generating the data as determined by the `CreateRingBuffer` and
/// `Start` commands. The driver must set `fifo_depth` big enough such that the potential
/// delays added by any software interfacing with the audio hardware do not occur under most
/// scenarios, and must detect and report underruns. How an underrun is reported is not defined
/// in this API.
2: uint32 fifo_depth;
/// When set to true, indicates that clients need to make sure that their data has been flushed
/// all the way to physical memory (in the case of playback) or that their view of the ring
/// buffer will need to be invalidated before read (in the case of capture).
3: bool needs_cache_flush_or_invalidate;
};
struct RingBufferPositionInfo {
/// The driver's best estimate of the time at which the playback/capture pointer reached the
/// position indicated by `position`.
zx.time timestamp;
/// The playback/capture pointer position (in bytes) in the ring buffer at time
/// `timestamp` as estimated by the driver.
uint32 position;
};
enum GetVmoError {
/// The ring buffer setup failed due to an invalid argument, e.g. min_frames is too big.
INVALID_ARGS = 1;
/// The ring buffer setup failed due to an internal error.
INTERNAL_ERROR = 2;
};
protocol RingBuffer {
/// Accessor for top level static properties.
GetProperties() -> (RingBufferProperties properties);
/// Gets the ring buffer current position via a hanging get. The driver must immediately
/// respond to a client's first `WatchClockRecoveryPositionInfo` call, but will not respond to
/// subsequent client calls until the position information has changed from what was most
/// recently provided to that client. If `clock_recovery_notifications_per_ring` is not zero,
/// the driver will reply with its estimated position to be used for clock recovery at most at
/// `clock_recovery_notifications_per_ring` frequency.
/// Must be delivered with timestamps that are monotonically increasing.
WatchClockRecoveryPositionInfo() -> (RingBufferPositionInfo position_info);
/// Requests a shared buffer to be used for moving bulk audio data. Requests the buffer size to
/// fit at least `min_frames`, and returns the actual `num_frames` allocated in
/// `ring_buffer`.
///
/// If `clock_recovery_notifications_per_ring` is non-zero, the driver will send replies to
/// `WatchClockRecoveryPositionInfo` client requests at most at
/// `clock_recovery_notifications_per_ring` frequency. These notifications are meant to be used
/// for clock recovery.
///
GetVmo(uint32 min_frames, uint32 clock_recovery_notifications_per_ring)
-> (uint32 num_frames, zx.handle:VMO ring_buffer)
error GetVmoError;
/// Start the ring buffer. The `start_time` value (in the CLOCK_MONOTONIC timeline) indicates
/// when position began moving, starting at the beginning of the ring buffer.
Start() -> (zx.time start_time);
/// Stop the ring buffer. Once this call's response is received, no further position
/// notifications will be sent until Start() is called again. TODO(39494): Add timestamp
/// parameter.
Stop() -> ();
};