| // 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; |
| |
| 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; |
| }; |
| |
| /// For an overview see |
| /// [Audio Driver Streaming Interface](//docs/concepts/drivers/driver_interfaces/audio_streaming.md) |
| protocol RingBuffer { |
| /// Accessor for top level static properties. |
| GetProperties() -> (RingBufferProperties properties); |
| |
| /// Gets the ring buffer current position via a hanging get. The driver must 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. The driver must not respond to a |
| /// `WatchClockRecoveryPositionInfo` until after it has replied to the `Start` command. 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. |
| /// `WatchClockRecoveryPositionInfo` may only be called after `GetVmo` was called, hence a |
| /// `clock_recovery_notifications_per_ring` was specified. |
| /// 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(fxbug.dev/39494): Add timestamp parameter. |
| Stop() -> (); |
| }; |