Files
One-KVM/src/video/pipeline/delivery.rs
mofeng-git 318b58b26a perf(video): 优化视频流水线并统一使用 vendored OpenSSL
使用固定采集、解码和编码线程及同步最新帧槽,减少同步异步跨界和无效 MJPEG 解码。

编码前预留消费者容量,以完整批次投递编码结果并隔离慢客户端,避免丢失 H.264 参考帧;保留 PTS 修正,不增加 IDR 节流。

复用 Annex-B 缓冲并增加低频发送分项统计,默认启用 vendored OpenSSL SRTP AES-CM 后端。

HTTP 客户端、HTTPS 服务端和本地 DTLS 证书验证迁移至 OpenSSL,移除 rustls TLS 引擎依赖,保留证书验证、媒体加密和原有协议协商。
2026-10-01 18:34:40 +08:00

101 lines
2.7 KiB
Rust

use std::collections::VecDeque;
use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
use std::sync::Arc;
use std::time::Duration;
use parking_lot::Mutex;
use tokio::sync::mpsc;
use super::frame_mailbox::FrameMailbox;
use super::EncodedVideoFrame;
use crate::video::frame::VideoFrame;
pub(super) type EncodedBatch = Arc<[Arc<EncodedVideoFrame>]>;
pub(super) type FrameMailboxHandle = Arc<Mutex<Option<Arc<FrameMailbox<Arc<VideoFrame>>>>>>;
#[derive(Default)]
pub(super) struct DeliveryStats {
pub sent_frames: AtomicU64,
pub send_time_ns: AtomicU64,
pub send_errors: AtomicU64,
}
pub(super) struct VideoSubscriber {
pub sender: mpsc::Sender<EncodedBatch>,
pub needs_keyframe: AtomicBool,
pub recovery_requested: AtomicBool,
}
pub(super) struct VideoFrameReservation {
pub subscriber: Arc<VideoSubscriber>,
pub permit: mpsc::OwnedPermit<EncodedBatch>,
}
pub struct EncodedVideoFrameReceiver {
receiver: mpsc::Receiver<EncodedBatch>,
pending: VecDeque<Arc<EncodedVideoFrame>>,
mailbox: FrameMailboxHandle,
stats: Arc<DeliveryStats>,
}
impl EncodedVideoFrameReceiver {
pub(super) fn new(
receiver: mpsc::Receiver<EncodedBatch>,
mailbox: FrameMailboxHandle,
stats: Arc<DeliveryStats>,
) -> Self {
Self {
receiver,
pending: VecDeque::new(),
mailbox,
stats,
}
}
fn notify_capacity(&self) {
if let Some(mailbox) = self.mailbox.lock().as_ref() {
mailbox.notify();
}
}
pub async fn recv(&mut self) -> Option<Arc<EncodedVideoFrame>> {
loop {
if let Some(frame) = self.pending.pop_front() {
return Some(frame);
}
let batch = self.receiver.recv().await?;
self.pending.extend(batch.iter().cloned());
self.notify_capacity();
}
}
pub fn try_recv(&mut self) -> Result<Arc<EncodedVideoFrame>, mpsc::error::TryRecvError> {
loop {
if let Some(frame) = self.pending.pop_front() {
return Ok(frame);
}
let batch = self.receiver.try_recv()?;
self.pending.extend(batch.iter().cloned());
self.notify_capacity();
}
}
pub(crate) fn record_send(&self, elapsed: Duration, succeeded: bool) {
self.stats
.send_time_ns
.fetch_add(elapsed.as_nanos() as u64, Ordering::Relaxed);
if succeeded {
self.stats.sent_frames.fetch_add(1, Ordering::Relaxed);
} else {
self.stats.send_errors.fetch_add(1, Ordering::Relaxed);
}
}
}
impl Drop for EncodedVideoFrameReceiver {
fn drop(&mut self) {
self.receiver.close();
self.notify_capacity();
}
}