Skip to main content

RunState

Struct RunState 

Source
pub(crate) struct RunState<'a> {
Show 26 fields pub(crate) inner: &'a Inner, pub(crate) ring: &'a DeliveryRing, pub(crate) encoder: PcmEncoder, pub(crate) frame_size_per_channel: usize, pub(crate) channels: usize, pub(crate) accum: Vec<i16>, pub(crate) silence_ref: Vec<i16>, pub(crate) pcm_fill_bytes: usize, pub(crate) pool: PoolTaker, pub(crate) red_history: VecDeque<(Vec<u8>, u64)>, pub(crate) red_spare: Vec<Vec<u8>>, pub(crate) red_distance: usize, pub(crate) sounding: bool, pub(crate) tail_sounding: bool, pub(crate) lookahead: usize, pub(crate) companion: Option<(PcmEncoder, Vec<i16>)>, pub(crate) companion_bitrate: i32, pub(crate) total_samples_processed: u64, pub(crate) ogg: Option<OggSink>, pub(crate) ogg_scale: u64, pub(crate) first_sound_detected: bool, pub(crate) current_applied_bitrate: i32, pub(crate) chunks_read: u64, pub(crate) chunks_silent: u64, pub(crate) chunks_encoded: u64, pub(crate) bytes_encoded: u64,
}
Expand description

Per-run encode/deliver state, living on the capture thread’s stack for the lifetime of one capture. Holds the encoder, the frame-reassembly buffers, the outgoing buffer recycler, the RED redundancy history, and the running debug-log counters.

Fields§

§inner: &'a Inner§ring: &'a DeliveryRing§encoder: PcmEncoder§frame_size_per_channel: usize§channels: usize§accum: Vec<i16>

Reassembly buffer for exactly one Opus frame (i16 samples, filled byte-wise from the incoming PulseAudio fragments).

§silence_ref: Vec<i16>

A zeroed reference of the same length as accum; comparing accum == silence_ref lowers to a single vectorized memcmp for the silence gate, versus a scalar per-sample scan.

§pcm_fill_bytes: usize§pool: PoolTaker

Outgoing-buffer recycler, shared with delivered AudioFrames whose drop refills it.

§red_history: VecDeque<(Vec<u8>, u64)>

RFC 2198 redundancy history: the last red_distance emitted (opus, pts) frames, oldest-first. Per-run — reset on start, and the frame size is fixed for a run.

§red_spare: Vec<Vec<u8>>

Retired red_history buffers, reused for the next entry so the steady state (a silence gap included) allocates nothing. Bounded by red_distance: every buffer is either in the history or here.

§red_distance: usize§sounding: bool

Whether the last frame was emitted as sound, so the gate lets the silent frame after it through when that frame carries the end of the sound (always on a header capture, behind the bare WS_QUIET mark and marked itself; on a raw capture when tail_sounding), and a session that drops after it sends the bare mark once.

§tail_sounding: bool

Whether that frame of sound held sound in its last lookahead samples, the part the encoder holds back until the next frame.

§lookahead: usize

The encoder’s lookahead in samples per channel (PcmEncoder::lookahead).

§companion: Option<(PcmEncoder, Vec<i16>)>

A surround capture’s stereo encoder and its downmix scratch, for Inner::stereo_companion; None for mono and stereo captures.

§companion_bitrate: i32

The bitrate the companion encoder was last given; follows the capture’s.

§total_samples_processed: u64§ogg: Option<OggSink>

The Ogg Opus stream on the output socket, and the 48 kHz samples one input sample is worth for its granule positions.

§ogg_scale: u64§first_sound_detected: bool§current_applied_bitrate: i32§chunks_read: u64§chunks_silent: u64§chunks_encoded: u64§bytes_encoded: u64

Implementations§

Source§

impl<'a> RunState<'a>

Source

pub(crate) fn feed(&mut self, src: &[u8])

Feed one PulseAudio PCM fragment into the reassembly buffer, emitting a frame each time accum fills to exactly one Opus frame.

Fragments arrive at arbitrary byte boundaries, so this copies from src into accum at pcm_fill_bytes, calling emit_frame (and resetting the fill cursor) whenever a full frame_size_per_channel * channels * 2-byte chunk accumulates, and loops until src is drained. Any partial remainder is carried into the next fragment.

Source

pub(crate) fn emit_frame(&mut self)

Encode one reassembled frame and hand it to the delivery thread. The heart of the capture encode path.

  1. Dynamic bitrate: re-reads the opus_bitrate mirror and reconfigures the encoder only when it changed, so a live bitrate update costs nothing on unchanged frames.
  2. Timestamp: pts is the running 48 kHz-domain sample count (total_samples_processed) before this frame, then advanced by frame_size_per_channel — a monotonic per-frame timestamp used for RED offsets and client-side ordering.
  3. Silence gate: when enabled, a frame equal to the zeroed silence_ref is counted and dropped (no Opus is sent), so pure silence costs no bandwidth. The first one after sound can carry the end of that sound, the part the encoder held back (its lookahead). A header capture always sends it: the bare WS_QUIET mark goes first, then that frame with WS_QUIET set. A raw Opus capture sends it only when the sound reached into that lookahead (tail_sounding): a WebRTC receiver’s jitter buffer fades the sound after a pause in from what it concealed, and concealing from a frame of silence faded more short sounds than concealing from the sound itself, while a frame that ends a sound loses nothing of it. The first non-silent frame logs once.
  4. Encode in place: write_ws_prefix_into writes the RFC 2198 RED framing prefix (which depends only on pts + history) into a pooled buffer, and the Opus packet is encoded DIRECTLY after it — no assembly copy, and the buffer recycles through the pool, so the steady state allocates nothing. An encode error or a zero-length packet returns the buffer to the pool and drops the frame.
  5. Retain redundancy: with red_distance > 0, the just-encoded primary is copied onto red_history (bounded, oldest-first) to serve as a future redundant copy, into the buffer the retiring entry hands back.
  6. Hand off: the truncated buffer is pushed to the DeliveryRing; the capture thread itself never touches the GIL.
Source

pub(crate) fn emit_quiet(&mut self, pts: u64)

Tell the delivery thread the stream pauses when the session drops after a frame of sound: a header capture pushes the bare [0x01, WS_QUIET] (stamped with the pts the pause starts at), since no frame is left to carry the mark, so a player plays out what it holds rather than waiting for more. A raw Opus capture has nothing to frame it with, and its RTP timestamps carry the pause already.

Source

pub(crate) fn push_mark(&mut self, pts: u64)

Push the bare [0x01, WS_QUIET] stamped pts.

Source

pub(crate) fn emit_companion( &mut self, pts: u64, emit_header: bool, ending: bool, )

Emit the stereo companion of the frame just emitted: the frame downmixed (downmix_stereo), encoded with the companion’s own stereo encoder at the capture’s bitrate, and handed to the delivery thread right after it with the same pts and channels == 2. On the wire it carries the plain two-byte header, never RED, which the surround stream’s history serves, with WS_QUIET set when ending (the companion of the silent frame that ends a sound).

Auto Trait Implementations§

§

impl<'a> !Sync for RunState<'a>

§

impl<'a> Freeze for RunState<'a>

§

impl<'a> RefUnwindSafe for RunState<'a>

§

impl<'a> Send for RunState<'a>

§

impl<'a> Unpin for RunState<'a>

§

impl<'a> UnsafeUnpin for RunState<'a>

§

impl<'a> UnwindSafe for RunState<'a>

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

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

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.

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> Ungil for T
where T: Send,