/// Commands sent from the WebRTC thread to the SW encoder when the /// bandwidth estimate changes significantly. pub enum BitrateCommand { UpdateBitrate { target_bps: u64, }, UpdateResolution { width: u32, height: u32, }, /// Force the next encoded frame to be an IDR. Sent by the WebRTC thread /// in response to str0m `Event::KeyframeRequest` or a resolution change. ForceKeyframe, } #[derive(Clone, Copy, Debug)] pub struct ResolutionChange { pub width: u32, pub height: u32, } /// Per-frame timing snapshot for the software encoder, consumed by the stats /// thread. `sws_us` measures NV12->YUV420P conversion, `encode_us` measures /// `avcodec_send_frame` + drain, and `output_bytes` counts encoded bytes /// produced by libavcodec (even if downstream delivery later drops them). #[derive(Default, Clone, Copy, Debug)] pub struct SwEncodeTiming { pub sws_us: u64, pub encode_us: u64, pub output_bytes: usize, } /// Outcome of a single `encode_cpu_frame` call. Used by the encode thread /// to decide whether to report timing stats (only real encodes tick encoded_fps). #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum EncodeOutcome { /// Frame was actually encoded and produced output bytes. Encoded, /// Frame was dropped because WebRTC is paused (no client connected). SkippedPaused, /// Frame was dropped because the encoder is in disconnected state. SkippedDisconnected, /// Frame was dropped because its Y-plane hash matched the previous frame. SkippedDuplicate, } /// Per-stage timing breakdown for one encode cycle on the hardware path. /// Returned by `EncState::encode_frame` so callers can fold the numbers /// into `crate::stats::FrameTimings`. `transfer_us` is always 0 on the HW /// path because the frame stays on the GPU; the SW path's struct (if added /// later) would carry a real readback measurement. #[derive(Debug, Default, Clone, Copy)] pub struct EncodeStages { pub scale_us: u64, pub transfer_us: u64, pub encode_us: u64, } /// Encoded H.264 frame with timing metadata for WebRTC output. /// /// MP4 file output (FrameOutput::Muxer) does NOT use this - it writes via /// avformat which preserves PTS internally. WebRTC output (FrameOutput::Channel) /// requires explicit PTS propagation so RTP timestamps reflect real capture time. /// Without this, WebRTC clients' jitter buffers grow to seconds under /// damage-driven variable frame rate. See issue #24. #[derive(Debug)] pub struct EncodedH264Frame { /// H.264 NAL byte stream (Annex B or AVCC depending on encoder configuration) pub data: Vec, /// PTS in encoder time_base units (1/fps seconds), normalized so first frame = 0. /// Derived from real capture time, NOT frame counter. pub pts_ticks: i64, /// Wall-clock capture time, propagated from CpuNv12Frame for frame_age stat. pub capture_time: std::time::Instant, } /// Owned CPU NV12 frame data for cross-thread transfer. /// Produced by main thread (VAAPI import + GPU scale + transfer), consumed by encode thread. pub struct CpuNv12Frame { pub y_data: Vec, pub uv_data: Vec, pub y_stride: usize, pub uv_stride: usize, pub pts: i64, /// Wall-clock time when this frame was captured (PipeWire delivery). /// Used for frame_age stat: time from capture to WebRTC send. pub capture_time: std::time::Instant, }