Skip to main content

WasapiCaptureSource

Struct WasapiCaptureSource 

Source
pub struct WasapiCaptureSource { /* private fields */ }
Available on Windows and crate feature wasapi-capture and (crate features dxgi-capture or wasapi-capture) only.
Expand description

Captures audio via WASAPI (IAudioClient/IAudioCaptureClient) — GStreamer’s wasapi2src equivalent. One src pad, pushing MediaBuffer::Audio frames in the captured device’s own native mix format/rate/channel count — no resampling. Same division of labor as crate::elements::DxgiCaptureSource emitting raw Pixel::BGRA and leaving conversion to a downstream crate::elements::Scaler: if something downstream needs a fixed sample rate/format, use crate::elements::AudioResampler rather than hiding conversion in this element.

Polls IAudioCaptureClient::GetNextPacketSize on a short fixed interval (POLL_INTERVAL) rather than waiting on a WASAPI-signaled event — see that constant’s own docs on why event-driven mode isn’t used here.

Emits continuously from the moment run starts, pts always in lockstep with wall-clock time — backed by real WASAPI data when it’s available and synthesized silence otherwise (see WasapiCaptureSource::fill_silence_gap), since WASAPI itself delivers literally nothing whenever the render engine has no active session at all (e.g. nothing currently playing, for WasapiDeviceKind::Render). Without this, a quiet period would be a real gap in the audio timeline rather than silence, which would leave a downstream muxer/encoder with no way to keep audio and video in sync across it.

Every WASAPI object here is created by WasapiCaptureSource::open on its caller’s thread, then actually driven by SourceElement::run on whichever thread crate::pipeline::Pipeline spawns for this source — a different thread in the normal case. COM requires every thread that touches an interface to have joined an apartment itself (even though the interfaces here are free-threaded/agile and can be handed across threads freely), so run makes its own CoInitializeEx call before touching anything, paired with CoUninitialize when it returns — the same two-CoInitializeEx-calls-per-object-lifetime pattern cpal’s own WASAPI backend uses. open also joins its caller’s COM apartment while it creates the agile WASAPI interfaces, then balances that call before returning; the pipeline worker joins its own apartment independently in run.

Deliberately does not retry internally on AUDCLNT_E_DEVICE_INVALIDATED (default device changed, unplugged, format changed) — same “fail fast, caller rebuilds” contract as DxgiCaptureSource/RtspSource; watch for WasapiCaptureSourceError::DeviceInvalidated and call WasapiCaptureSource::open again.

Runs until Stop — never reaches Eos on its own, same as every other live source in this crate.

Implementations§

Source§

impl WasapiCaptureSource

Source

pub fn list_devices() -> Result<Vec<WasapiDevice>, WasapiCaptureSourceError>

Enumerates every currently-active audio endpoint — both Render (playback) and Capture (recording) — as an WasapiDevice list a caller can show in a picker UI and index/search into, then hand the chosen entry straight to WasapiCaptureOptions::device. No concept of “mode” to reason about beforehand: the picked device’s own WasapiDeviceKind is what tells open whether to use loopback.

Source

pub fn open( name: impl Into<String>, options: WasapiCaptureOptions, ) -> Result<(Self, u32, u16), WasapiCaptureSourceError>

Opens options.device and starts a shared-mode WASAPI capture session. Returns the element alongside the captured stream’s actual (sample_rate, channels) — what a caller needs to build a matching downstream encoder/muxer, same pattern as crate::elements::DxgiCaptureSource::open returning (width, height).

Source

pub fn time_base(&self) -> Rational

The unit each emitted frame’s pts is expressed in.

Trait Implementations§

Source§

impl Element for WasapiCaptureSource

Source§

fn name(&self) -> Arc<str>

Returns a cheap clone (refcount bump, not a deep copy) of this element’s name — crate::bus::BusEvent stores names as Arc<str> for exactly this reason: a hot path like crate::queue::Queue posting BusEvent::Dropped once per overflowed buffer shouldn’t pay for a fresh heap allocation every time it wants to report which element it is.
Source§

fn element_type(&self) -> ElementType

Source§

fn pp_log(&self) -> &PpLog

This element’s identity for crate::bus::Bus::post — same id/name as Element::name, just already wrapped as the crate::pp_log::PpLog its pp_info!/pp_warn!/pp_error! macros need. A stored private field, not built fresh per call, for the same reason name() returns a cheap Arc<str> clone instead of a fresh String — see its own docs.
Source§

fn pp_log_mut(&mut self) -> &mut PpLog

Mutable access to the same field Element::pp_log reads — used by crate::pipeline::ChainBuilder to stamp the owning crate::pipeline::Pipeline’s id onto every element that passes through it, via element_pp_log. Not meant to be called from anywhere else.
Source§

fn graph_id(&self) -> Option<ElementId>

A pre-reserved graph identity for elements that expose dynamic attachment handles. Most elements receive an ID from ChainBuilder and keep the default None implementation.
Source§

impl Send for WasapiCaptureSource

Source§

impl Source for WasapiCaptureSource

Source§

fn src_pads(&mut self) -> &mut [SrcPad]

Source§

impl SourceElement for WasapiCaptureSource

Source§

fn run(&mut self, control: &ControlReceiver, bus: &Bus) -> Result<()>

Drives this source until Eos (normal completion), crate::pipeline::Pipeline::finish, or Stop (see ControlMsg::Stop) — call crate::control::drain_control once per loop iteration to make control responsive between blocking reads. Read more
Source§

fn seek(&mut self, _target: Duration) -> Result<Duration>

Repositions this source to target, an absolute position from the start of the media (e.g. av_seek_frame for crate::elements::FileDemuxer). Called by crate::control::drain_control as part of handling ControlMsg::Seek, before that message is forwarded to the source’s own pads — so whatever’s read next comes from the new position by the time downstream elements are told to flush for it. 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<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

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> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
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<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

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