fidl_fuchsia_hardware_audio

Struct RingBufferProperties

Source
pub struct RingBufferProperties {
    pub external_delay: Option<i64>,
    pub fifo_depth: Option<u32>,
    pub needs_cache_flush_or_invalidate: Option<bool>,
    pub turn_on_delay: Option<i64>,
    pub driver_transfer_bytes: Option<u32>,
    /* private fields */
}
Expand description

Properties of the ring buffer. These values don’t change once the ring buffer is created.

Fields§

§external_delay: Option<i64>

The driver’s best estimate (for the chosen format) of the delay external to the hardware it abstracts. External delay must be taken into account when precisely synchronizing presentation across multiple entities (e.g. devices). If not included external_delay is unknown.

§Deprecation

Not needed anymore since the functionality is available via WatchDelayInfo below.

§fifo_depth: Option<u32>

Size (in bytes) of the temporary buffer used by the driver when consuming or generating ring buffer contents. Required. 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.

§Deprecation

Not needed anymore since the functionality is available via driver_transfer_bytes below.

§needs_cache_flush_or_invalidate: Option<bool>

When set to true, indicates that the ring buffer runs in a different cache coherency domain, and thus clients must ensure that their data writes are flushed all the way to main memory (during playback), or that their view of the ring buffer must be invalidated before any reads (during capture). This is because there may be hardware external to the CPUs that reads/writes main memory, bypassing the CPUs.

When set to false, indicates that the ring buffer runs in the same cache coherency domain as the CPUs, hence the driver is not required to flush/invalidate the ring buffer. Note that in this case, the driver and client still must synchronize their data access, for instance by inserting the appropriate acquire fences before reading and releasing fences after writing.

Required.

§turn_on_delay: Option<i64>

The driver’s best estimate of the time needed for the hardware to emit (during playback) or accept (during capture) frames, after a channel is activated by SetActiveChannels. The driver estimates that after SetActiveChannels(channel)->(set_time) enables a channel, its data will resume flowing at approximately set_time + turn_on_delay. Hardware can take time to become fully operational (e.g. due to a power state change, or communication delays between a Bluetooth driver’s multiple hardware entities). The client must take this delay into account, if it is unacceptable to drop the actual audio frames and instead play/capture silence during this interval. If not included, turn_on_delay is unknown.

Optional.

§driver_transfer_bytes: Option<u32>

Size (in bytes) of the temporary buffer used by the driver/HW when consuming or generating the ring buffer contents.

The ring buffer contents must be produced and consumed at the rate specified with the CreateRingBuffer command, using data transfers between a temporary buffer and the ring buffer. For playback, audio frames are consumed by the driver in transfers as large as driver_transfer_bytes. For capture, audio frames are produced by the driver in transfers as large as driver_transfer_bytes. In both cases, this many frames must accumulate before they are read from or committed to the ring buffer.

These data transfers mean that there is always a section of the ring buffer that is unsafe for the client to be writing/reading. This unsafe buffer region is defined on one side by the current position ‘P’, and on the other side by the ‘safe pointer’ location ‘S’. Once the ring buffer starts, these two pointers begin moving. ‘P’ begins moving from position 0 at the start_time from Start. The region between these pointers must not be read or written by the client at that time. The diagrams below note these pointers as ‘P’ and ‘S’.

During playback, client must write data BEFORE hardware transfers occur. During capture, client can read captured data only AFTER hardware transfers occur. For this reason, during playback ‘S’ is always ahead of ‘P’, whereas during capture ‘S’ is always behind ‘P’.

§Playback

Before they start the ring buffer, clients may safely write any ring buffer location. It is recommended that they write at least driver_transfer_bytes of initial audio, since they must always stay at least that far ahead of where the driver/HW is reading, and upon Start the hardware might immediately consume that much data from the ring buffer. Otherwise, the client relies on the zeroed-out contents of the VMO to be the initial audio read by the driver/HW.

                                      Ring Buffer
 +-------------------------+-------------------------------------------------------------+
 |<---                                 safe to write                                 --->|
 |             (to pre-populate the ring buffer before starting the hardware)            |
 +-------------------------+-------------------------------------------------------------+
 0=P                       S                                                             0

Once the ring buffer is started, it is not safe for the client to write data to the ring buffer between ‘P’ and ‘S’, because this represents data already in use (potentially already consumed). The client may safely write the rest of the ring buffer (between ‘S’ and ‘0/P’).

                                      Ring Buffer
 +-------------------------+-------------------------------------------------------------+
 |<--- unsafe to write --->|<---                    safe to write                    --->|
 |< driver_transfer_bytes >|           (empty unless prewritten by the client)           |
 +-------------------------+-------------------------------------------------------------+
 0=P                       S                                                             0

As time passes, the driver/HW reads the data in chunks of driver_transfer_bytes or less, at the rate specified in CreateRingBuffer. The Position/Safe pointers move to the right at the same rate, but do so smoothly. As a result, the “unsafe for client writes” area moves gradually through the ring buffer, while maintaining a constant size equal to driver_transfer_bytes. Thus, after some period we now have:

                                      Ring Buffer
 +------------+-------------------------+------------------------------------------------+
 |<-- safe -->|<--- unsafe to write --->|<--               safe to write              -->|
 |  to write  |< driver_transfer_bytes >|       (not yet consumed by the hardware)       |
 +------------+-------------------------+------------------------------------------------+
 0            P                         S                                                0

Later, ‘S’ wraps around the ring buffer before ‘P’ does. Note that the region from 0 to ‘S’, plus the region from ‘P’ to the end of the ring buffer, adds up to driver_transfer_bytes:

                                      Ring Buffer
 +---------------+------------------------------------------------------------+----------+
 |<--- unsafe -->|<---                   safe to write                    --->|<-unsafe->|
 |< driver_transf|                                                            |er_bytes >|
 +---------------+------------------------------------------------------------+----------+
 0               S                                                            P          0

In steady state, any area outside of the pointers ‘P’ and ‘S’ is safe to write:

                                      Ring Buffer
 +--------------------------------+-------------------------+----------------------------+
 [<--       safe to write      -->|<--- unsafe to write --->|<--     safe to write    -->|
 |  (prior data already consumed) |< driver_transfer_bytes >|                            |
 +--------------------------------+-------------------------+----------------------------+
 0                                P                         S                            0

§Recording

While recording, it is only safe for the client to read that part of the ring buffer that is not simultaneously being written by the driver/HW. Before capture begins, it may read the entire ring buffer, but the driver has not yet written anything for the client to read. This is the ring buffer at the moment that the client starts the ring buffer:

                                      Ring Buffer
 +---------------------------------------------------------------------------------------+
 [<---                     empty (not yet written by the hardware)                    -->|
 +---------------------------------------------------------------------------------------+
0=S=P                                                                                    0

Once capture begins, the driver/HW acquires frames, eventually making its first data transfer to the ring buffer starting at ‘0’. These transfers are of unknown size but may be as large as driver_transfer_bytes; they occur at the rate specified in CreateRingBuffer. Before the driver/HW has written at least driver_transfer_bytes into the ring buffer, the client cannot yet safely read any of the newly captured frames:

                                      Ring Buffer
 +--------------+------------------------------------------------------------------------+
 [<-- unsafe -->|<--                           safe to read                           -->|
 |< driver_transfer_bytes >|     (but empty, not yet written by the hardware)            |
 +--------------+------------------------------------------------------------------------+
0=S             P                                                                        0

Once the driver/HW has written at least driver_transfer_bytes of data into the ring buffer, ‘S’ begins to smoothly move forward at the same rate as ‘P’ (as determined by the ring buffer’s rate and sample format). The client can safely read frames in the region between ‘0’ and ‘S’. It is unsafe for the client to read data between ‘S’ and ‘P’, because this is where the driver/HW is simultaneously writing. This region gradually progresses across the ring buffer, maintaining a constant size of driver_transfer_bytes. After some time we have:

                                      Ring Buffer
 +----------------+-------------------------+--------------------------------------------+
 [< safe to read >|<---  unsafe to read --->|<--             safe to read             -->|
 | captured audio |< driver_transfer_bytes >|      (not yet written by the hardware)     |
 +----------------+-------------------------+--------------------------------------------+
 0                S                         P                                            0

Later, ‘P’ wraps around the ring buffer before ‘S’ does. Note that the region from 0 to ‘P’, plus the region from ‘S’ to the end of the ring buffer, adds up to driver_transfer_bytes:

                                      Ring Buffer
 +-----------+------------------------------------------------------------+--------------+
 |<--unsafe->|<---                    safe to read                    --->|<---unsafe--->|
 |< driver_tr|                      (captured audio)                      |ansfer_bytes >|
 +-----------+------------------------------------------------------------+--------------+
 0           P                                                            S              0

In steady state, i.e. once the process has wrapped around the ring buffer, any area outside of pointers ‘S’ and ‘P’ is safe to read:

                                      Ring Buffer
 +--------------------------------+-------------------------+----------------------------+
 [<--       safe to read       -->|<---      unsafe     --->|<--     safe to read     -->|
 |                                |< driver_transfer_bytes >|                            |
 +--------------------------------+-------------------------+----------------------------+
 0                                S                         P                            0

§Hardware versus software

The ring buffer data may be directly consumed/generated by hardware, i.e. driver_transfer_bytes can be mapped directly to the size of a hardware FIFO block, since a hardware FIFO block determines the upper limit amount of data read ahead or held back. Note that if the FIFO buffer is not used in the traditional “high water” way (such as a “ping pong” design where only half the FIFO size is used at any time – even during the very first transfers at Start time), then driver_transfer_bytes may be set to a smaller value but must be at least equal to the largest amount of data ever stored in the FIFO buffer. Even if the transfer size never exceeds half the size of the FIFO, if the full size of the FIFO is used (for instance, upon Start when filling an initially empty hardware FIFO), then driver_transfer_bytes must be set to the entire size of the FIFO buffer.

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 driver_transfer_bytes read ahead amount must be large enough such that the driver guarantees no undetected underruns, based on the client requirement to generate data based on the CreateRingBuffer rate and the start_time from Start. For capture, driver_transfer_bytes must be large enough for the driver to guarantee no underruns when generating the data as determined by the CreateRingBuffer and Start commands.

driver_transfer_bytes must not include the impact of delays caused by hardware or software processing abstracted by the driver. Those delays are communicated by internal_delay and external_delay fields in DelayInfo; they are orthogonal to this value.

Required.

Trait Implementations§

Source§

impl Clone for RingBufferProperties

Source§

fn clone(&self) -> RingBufferProperties

Returns a copy of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for RingBufferProperties

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<D: ResourceDialect> Decode<RingBufferProperties, D> for RingBufferProperties

Source§

fn new_empty() -> Self

Creates a valid instance of Self. The specific value does not matter, since it will be overwritten by decode.
Source§

unsafe fn decode( &mut self, decoder: &mut Decoder<'_, D>, offset: usize, depth: Depth, ) -> Result<()>

Decodes an object of type T from the decoder’s buffers into self. Read more
Source§

impl Default for RingBufferProperties

Source§

fn default() -> RingBufferProperties

Returns the “default value” for a type. Read more
Source§

impl<D: ResourceDialect> Encode<RingBufferProperties, D> for &RingBufferProperties

Source§

unsafe fn encode( self, encoder: &mut Encoder<'_, D>, offset: usize, depth: Depth, ) -> Result<()>

Encodes the object into the encoder’s buffers. Any handles stored in the object are swapped for Handle::INVALID. Read more
Source§

impl PartialEq for RingBufferProperties

Source§

fn eq(&self, other: &RingBufferProperties) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl TypeMarker for RingBufferProperties

Source§

type Owned = RingBufferProperties

The owned Rust type which this FIDL type decodes into.
Source§

fn inline_align(_context: Context) -> usize

Returns the minimum required alignment of the inline portion of the encoded object. It must be a (nonzero) power of two.
Source§

fn inline_size(_context: Context) -> usize

Returns the size of the inline portion of the encoded object, including padding for alignment. Must be a multiple of inline_align.
§

fn encode_is_copy() -> bool

Returns true if the memory layout of Self::Owned matches the FIDL wire format and encoding requires no validation. When true, we can optimize encoding arrays and vectors of Self::Owned to a single memcpy. Read more
§

fn decode_is_copy() -> bool

Returns true if the memory layout of Self::Owned matches the FIDL wire format and decoding requires no validation. When true, we can optimize decoding arrays and vectors of Self::Owned to a single memcpy.
Source§

impl ValueTypeMarker for RingBufferProperties

Source§

type Borrowed<'a> = &'a RingBufferProperties

The Rust type to use for encoding. This is a particular Encode<Self> type cheaply obtainable from &Self::Owned. There are three cases: Read more
Source§

fn borrow(value: &<Self as TypeMarker>::Owned) -> Self::Borrowed<'_>

Cheaply converts from &Self::Owned to Self::Borrowed.
Source§

impl Persistable for RingBufferProperties

Source§

impl StructuralPartialEq for RingBufferProperties

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
§

impl<T> Body for T
where T: Persistable,

§

type MarkerAtTopLevel = T

The marker type to use when the body is at the top-level.
§

type MarkerInResultUnion = T

The marker type to use when the body is nested in a result union.
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
§

impl<T, D> Encode<Ambiguous1, D> for T
where D: ResourceDialect,

§

unsafe fn encode( self, _encoder: &mut Encoder<'_, D>, _offset: usize, _depth: Depth, ) -> Result<(), Error>

Encodes the object into the encoder’s buffers. Any handles stored in the object are swapped for Handle::INVALID. Read more
§

impl<T, D> Encode<Ambiguous2, D> for T
where D: ResourceDialect,

§

unsafe fn encode( self, _encoder: &mut Encoder<'_, D>, _offset: usize, _depth: Depth, ) -> Result<(), Error>

Encodes the object into the encoder’s buffers. Any handles stored in the object are swapped for Handle::INVALID. Read more
§

impl<E> ErrorType for E
where E: ValueTypeMarker<Owned = E> + Decode<E, DefaultFuchsiaResourceDialect>,

§

type Marker = E

The marker type.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

§

impl<T> Pointable for T

§

const ALIGN: usize = _

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more