pub enum AudioCapturerRequest {
Show 15 variants AddPayloadBuffer { id: u32, payload_buffer: Vmo, control_handle: AudioCapturerControlHandle, }, RemovePayloadBuffer { id: u32, control_handle: AudioCapturerControlHandle, }, ReleasePacket { packet: StreamPacket, control_handle: AudioCapturerControlHandle, }, DiscardAllPackets { responder: AudioCapturerDiscardAllPacketsResponder, }, DiscardAllPacketsNoReply { control_handle: AudioCapturerControlHandle, }, SetPcmStreamType { stream_type: AudioStreamType, control_handle: AudioCapturerControlHandle, }, CaptureAt { payload_buffer_id: u32, payload_offset: u32, frames: u32, responder: AudioCapturerCaptureAtResponder, }, StartAsyncCapture { frames_per_packet: u32, control_handle: AudioCapturerControlHandle, }, StopAsyncCapture { responder: AudioCapturerStopAsyncCaptureResponder, }, StopAsyncCaptureNoReply { control_handle: AudioCapturerControlHandle, }, BindGainControl { gain_control_request: ServerEnd<GainControlMarker>, control_handle: AudioCapturerControlHandle, }, GetReferenceClock { responder: AudioCapturerGetReferenceClockResponder, }, SetReferenceClock { reference_clock: Option<Clock>, control_handle: AudioCapturerControlHandle, }, SetUsage { usage: AudioCaptureUsage, control_handle: AudioCapturerControlHandle, }, GetStreamType { responder: AudioCapturerGetStreamTypeResponder, },
}
Expand description

AudioCapturer

An AudioCapturer is an interface returned from an fuchsia.media.Audio’s CreateAudioCapturer method, which may be used by clients to capture audio from either the current default audio input device, or the current default audio output device depending on the flags passed during creation.

Format support

See (Get|Set)StreamType below. By default, the captured stream type will be initially determined by the currently configured stream type of the source that the AudioCapturer was bound to at creation time. Users may either fetch this type using GetStreamType, or they may choose to have the media resampled or converted to a type of their choosing by calling SetStreamType. Note: the stream type may only be set while the system is not running, meaning that there are no pending capture regions (specified using CaptureAt) and that the system is not currently running in ‘async’ capture mode.

Buffers and memory management

Audio data is captured into a shared memory buffer (a VMO) supplied by the user to the AudioCapturer during the AddPayloadBuffer call. Please note the following requirements related to the management of the payload buffer.

  • The payload buffer must be supplied before any capture operation may start. Any attempt to start capture (via either CaptureAt or StartAsyncCapture) before a payload buffer has been established is an error.
  • The payload buffer may not be changed while there are any capture operations pending.
  • The stream type may not be changed after the payload buffer has been set.
  • The payload buffer must be an integral number of audio frame sizes (in bytes)
  • When running in ‘async’ mode (see below), the payload buffer must be at least as large as twice the frames_per_packet size specified during StartAsyncCapture.
  • The handle to the payload buffer supplied by the user must be readable, writable, mappable and transferable.
  • Users should always treat the payload buffer as read-only.

Synchronous vs. Asynchronous capture mode

The AudioCapturer interface can be used in one of two mutually exclusive modes: Synchronous and Asynchronous. A description of each mode and their tradeoffs is given below.

Synchronous mode

By default, AudioCapturer instances are running in ‘sync’ mode. They will only capture data when a user supplies at least one region to capture into using the CaptureAt method. Regions supplied in this way will be filled in the order that they are received and returned to the client as StreamPackets via the return value of the CaptureAt method. If an AudioCapturer instance has data to capture, but no place to put it (because there are no more pending regions to fill), the next payload generated will indicate that their has been an overflow by setting the Discontinuity flag on the next produced StreamPacket. Synchronous mode may not be used in conjunction with Asynchronous mode. It is an error to attempt to call StartAsyncCapture while the system still regions supplied by CaptureAt waiting to be filled.

If a user has supplied regions to be filled by the AudioCapturer instance in the past, but wishes to reclaim those regions, they may do so using the DiscardAllPackets method. Calling the DiscardAllPackets method will cause all pending regions to be returned, but with NO_TIMESTAMP as their StreamPacket’s PTS. See “Timing and Overflows”, below, for a discussion of timestamps and discontinuity flags. After a DiscardAllPackets operation, an OnEndOfStream event will be produced. While an AudioCapturer will never overwrite any region of the payload buffer after a completed region is returned, it may overwrite the unfilled portions of a partially filled buffer which has been returned as a result of a DiscardAllPackets operation.

Asynchronous mode

While running in ‘async’ mode, clients do not need to explicitly supply shared buffer regions to be filled by the AudioCapturer instance. Instead, a client enters into ‘async’ mode by calling StartAsyncCapture and supplying a callback interface and the number of frames to capture per-callback. Once running in async mode, the AudioCapturer instance will identify which payload buffer regions to capture into, capture the specified number of frames, then deliver those frames as StreamPackets using the OnPacketCapture FIDL event. Users may stop capturing and return the AudioCapturer instance to ‘sync’ mode using the StopAsyncCapture method.

It is considered an error to attempt any of the following operations.

  • To attempt to enter ‘async’ capture mode when no payload buffer has been established.
  • To specify a number of frames to capture per payload which does not permit at least two contiguous capture payloads to exist in the established shared payload buffer simultaneously.
  • To send a region to capture into using the CaptureAt method while the AudioCapturer instance is running in ‘async’ mode.
  • To attempt to call DiscardAllPackets while the AudioCapturer instance is running in ‘async’ mode.
  • To attempt to re-start ‘async’ mode capturing without having first stopped.
  • To attempt any operation except for SetGain while in the process of stopping.

Synchronizing with a StopAsyncCapture operation

Stopping asynchronous capture mode and returning to synchronous capture mode is an operation which takes time. Aside from SetGain, users may not call any other methods on the AudioCapturer interface after calling StopAsyncCapture (including calling StopAsyncCapture again) until after the stop operation has completed. Because of this, it is important for users to be able to synchronize with the stop operation. Two mechanisms are provided for doing so.

The first is to use StopAsyncCapture (not the NoReply variant). When the user’s callback has been called, they can be certain that stop operation is complete and that the AudioCapturer instance has returned to synchronous operation mode.

The second way to determine that a stop operation has completed is to use the flags on the packets which get delivered via the user-supplied AudioCapturerCallback interface after calling StopAsyncCapture. When asked to stop, any partially filled packet will be returned to the user, and the final packet returned will always have the end-of-stream flag (kFlagsEos) set on it to indicate that this is the final frame in the sequence. If there is no partially filled packet to return, the AudioCapturer will synthesize an empty packet with no timestamp, and offset/length set to zero, in order to deliver a packet with the end-of-stream flag set on it. Once users have seen the end-of-stream flag after calling stop, the AudioCapturer has finished the stop operation and returned to synchronous operating mode.

Timing and Overflows

All media packets produced by an AudioCapturer instance will have their PTS field filled out with the capture time of the audio expressed as a timestamp given by the reference clock timeline. Note: this timestamp is actually a capture timestamp, not a presentation timestamp (it is more of a CTS than a PTS) and is meant to represent the underlying system’s best estimate of the capture time of the first frame of audio, including all outboard and hardware introduced buffering delay. As a result, all timestamps produced by an AudioCapturer should be expected to be in the past relative to ‘now’ on the stream’s reference clock timeline.

The one exception to the “everything has an explicit timestamp” rule is when discarding submitted regions while operating in synchronous mode. Discarded packets have no data in them, but FIDL demands that all pending method-return-value callbacks be executed. Because of this, the regions will be returned to the user, but their timestamps will be set to NO_TIMESTAMP, and their payload sizes will be set to zero. Any partially filled payload will have a valid timestamp, but a payload size smaller than originally requested. The final discarded payload (if there were any to discard) will be followed by an OnEndOfStream event.

Two StreamPackets delivered by an AudioCapturer instance are ‘continuous’ if the first frame of audio contained in the second packet was captured exactly one nominal frame time after the final frame of audio in the first packet. If this relationship does not hold, the second StreamPacket will have the STREAM_PACKET_FLAG_DISCONTINUITY bit set in its flags field.

Even though explicit timestamps are provided on every StreamPacket produced, users who have very precise timing requirements are encouraged to always reason about time by counting frames delivered since the last discontinuity, rather than simply using the raw capture timestamps. This is because the explicit timestamps written on continuous packets may have a small amount of rounding error based on whether or not the units of the capture timeline reference clock are divisible by the chosen audio frame rate.

Users should always expect the first StreamPacket produced by an AudioCapturer to have the discontinuous flag set on it (as there is no previous packet to be continuous with). Similarly, the first StreamPacket after a DiscardAllPackets or a Stop/Start cycle will always be discontinuous. After that, there are only two reasons that a StreamPacket will ever be discontinuous:

  1. The user is operating in synchronous mode and does not supply regions to be filled quickly enough. If the next continuous frame of data has not been captured by the time it needs to be purged from the source buffers, an overflow has occurred and the AudioCapturer will flag the next captured region as discontinuous.
  2. The user is operating in asynchronous mode and some internal error prevents the AudioCapturer instance from capturing the next frame of audio in a continuous fashion. This might be high system load or a hardware error, but in general it is something which should never normally happen. In practice, however, if it does, the next produced packet will be flagged as being discontinuous.

Synchronous vs. Asynchronous Trade-offs

The choice of operating in synchronous vs. asynchronous mode is up to the user, and depending on the user’s requirements, there are some advantages and disadvantages to each choice.

Synchronous mode requires only a single Zircon channel under the hood and can achieve some small savings because of this. In addition, the user has complete control over the buffer management. Users specify exactly where audio will be captured to and in what order. Because of this, if users do not need to always be capturing, it is simple to stop and restart the capture later (just by ceasing to supply packets, then resuming later on). Payloads do not need to be uniform in size either, clients may specify payloads of whatever granularity is appropriate.

The primary downside of operating in synchronous mode is that two messages will need to be sent for every packet to be captured. One to inform the AudioCapturer of the instance to capture into, and one to inform the user that the packet has been captured. This may end up increasing overhead and potentially complicating client designs.

Asynchronous mode has the advantage requiring only 1/2 of the messages, however, when operating in ‘async’ mode, AudioCapturer instances have no way of knowing if a user is processing the StreamPackets being sent in a timely fashion, and no way of automatically detecting an overflow condition. Users of ‘async’ mode should be careful to use a buffer large enough to ensure that they will be able to process their data before an AudioCapturer will be forced to overwrite it.

Variants§

§

AddPayloadBuffer

Adds a payload buffer to the current buffer set associated with the connection. A StreamPacket struct reference a payload buffer in the current set by ID using the StreamPacket.payload_buffer_id field.

A buffer with ID id must not be in the current set when this method is invoked, otherwise the service will close the connection.

Fields

§id: u32
§payload_buffer: Vmo
§

RemovePayloadBuffer

Removes a payload buffer from the current buffer set associated with the connection.

A buffer with ID id must exist in the current set when this method is invoked, otherwise the service will will close the connection.

Fields

§id: u32
§

ReleasePacket

Releases payload memory associated with a packet previously delivered via OnPacketProduced.

Fields

§

DiscardAllPackets

§

DiscardAllPacketsNoReply

Fields

§

SetPcmStreamType

Sets the stream type of the stream to be delivered. Causes the source material to be reformatted/resampled if needed in order to produce the requested stream type. Must be called before the payload buffer is established.

Fields

§stream_type: AudioStreamType
§

CaptureAt

Explicitly specifies a region of the shared payload buffer for the audio input to capture into.

Fields

§payload_buffer_id: u32
§payload_offset: u32
§frames: u32
§

StartAsyncCapture

Places the AudioCapturer into ‘async’ capture mode and begin to produce packets of exactly ‘frames_per_packet’ number of frames each. The OnPacketProduced event (of StreamSink) will be used to inform the client of produced packets.

Fields

§frames_per_packet: u32
§

StopAsyncCapture

Stops capturing in ‘async’ capture mode and (optionally) deliver a callback that may be used by the client if explicit synchronization is needed.

§

StopAsyncCaptureNoReply

Fields

§

BindGainControl

Binds to the gain control for this AudioCapturer.

Fields

§gain_control_request: ServerEnd<GainControlMarker>
§

GetReferenceClock

Retrieves the stream’s reference clock. The returned handle will have READ, DUPLICATE and TRANSFER rights, and will refer to a zx::clock that is MONOTONIC and CONTINUOUS.

§

SetReferenceClock

Sets the reference clock that controls this capturer’s playback rate. If the input parameter is a valid zx::clock, it must have READ, DUPLICATE, TRANSFER rights and refer to a clock that is both MONOTONIC and CONTINUOUS. If instead an invalid clock is passed (such as the uninitialized zx::clock()), this indicates that the stream will use a ‘flexible’ clock generated by AudioCore that tracks the audio device.

SetReferenceClock cannot be called after the capturer payload buffer has been added. It also cannot be called a second time (even before capture). If the client wants a reference clock that is initially CLOCK_MONOTONIC but may diverge at some later time, they should create a clone of the monotonic clock, set this as the stream’s reference clock, then rate-adjust it subsequently as needed.

Fields

§reference_clock: Option<Clock>
§

SetUsage

Sets the usage of the capture stream. This may be changed on the fly, but packets in flight may be affected by the new usage. By default the Capturer is created with the FOREGROUND usage.

§

GetStreamType

Gets the currently configured stream type. Note: for an AudioCapturer which was just created and has not yet had its stream type explicitly set, this will retrieve the stream type – at the time the AudioCapturer was created – of the source (input or looped-back output) to which the AudioCapturer is bound. Even if this matches the client’s desired format, SetPcmStreamType must still be called.

Implementations§

source§

impl AudioCapturerRequest

source

pub fn into_add_payload_buffer( self ) -> Option<(u32, Vmo, AudioCapturerControlHandle)>

source

pub fn into_remove_payload_buffer( self ) -> Option<(u32, AudioCapturerControlHandle)>

source

pub fn into_release_packet( self ) -> Option<(StreamPacket, AudioCapturerControlHandle)>

source

pub fn into_discard_all_packets( self ) -> Option<AudioCapturerDiscardAllPacketsResponder>

source

pub fn into_discard_all_packets_no_reply( self ) -> Option<AudioCapturerControlHandle>

source

pub fn into_set_pcm_stream_type( self ) -> Option<(AudioStreamType, AudioCapturerControlHandle)>

source

pub fn into_capture_at( self ) -> Option<(u32, u32, u32, AudioCapturerCaptureAtResponder)>

source

pub fn into_start_async_capture( self ) -> Option<(u32, AudioCapturerControlHandle)>

source

pub fn into_stop_async_capture( self ) -> Option<AudioCapturerStopAsyncCaptureResponder>

source

pub fn into_stop_async_capture_no_reply( self ) -> Option<AudioCapturerControlHandle>

source

pub fn into_bind_gain_control( self ) -> Option<(ServerEnd<GainControlMarker>, AudioCapturerControlHandle)>

source

pub fn into_get_reference_clock( self ) -> Option<AudioCapturerGetReferenceClockResponder>

source

pub fn into_set_reference_clock( self ) -> Option<(Option<Clock>, AudioCapturerControlHandle)>

source

pub fn into_set_usage( self ) -> Option<(AudioCaptureUsage, AudioCapturerControlHandle)>

source

pub fn into_get_stream_type(self) -> Option<AudioCapturerGetStreamTypeResponder>

source

pub fn method_name(&self) -> &'static str

Name of the method defined in FIDL

Trait Implementations§

source§

impl Debug for AudioCapturerRequest

source§

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

Formats the value using the given formatter. Read more

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
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
§

impl<T> Encode<Ambiguous1> for T

§

unsafe fn encode( self, _encoder: &mut Encoder<'_>, _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> Encode<Ambiguous2> for T

§

unsafe fn encode( self, _encoder: &mut Encoder<'_>, _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
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, U> TryFrom<U> for T
where U: Into<T>,

§

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>,

§

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