mirror of
https://github.com/mofeng-git/One-KVM.git
synced 2026-10-27 16:00:49 +08:00
使用固定采集、解码和编码线程及同步最新帧槽,减少同步异步跨界和无效 MJPEG 解码。 编码前预留消费者容量,以完整批次投递编码结果并隔离慢客户端,避免丢失 H.264 参考帧;保留 PTS 修正,不增加 IDR 节流。 复用 Annex-B 缓冲并增加低频发送分项统计,默认启用 vendored OpenSSL SRTP AES-CM 后端。 HTTP 客户端、HTTPS 服务端和本地 DTLS 证书验证迁移至 OpenSSL,移除 rustls TLS 引擎依赖,保留证书验证、媒体加密和原有协议协商。
101 lines
2.7 KiB
Rust
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();
|
|
}
|
|
}
|