Skip to main content

RunState

Struct RunState 

Source
pub(crate) struct RunState<'a> {
Show 19 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) total_samples_processed: 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§total_samples_processed: 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 (nothing is sent), so pure silence costs no bandwidth. 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.

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,