mirror of
https://github.com/mofeng-git/One-KVM.git
synced 2026-07-29 07:31:45 +08:00
feat: v4l2 buffer 由2改为4
This commit is contained in:
@@ -3,6 +3,8 @@
|
|||||||
pub(crate) mod runtime;
|
pub(crate) mod runtime;
|
||||||
pub(crate) mod status;
|
pub(crate) mod status;
|
||||||
|
|
||||||
|
pub const DEFAULT_CAPTURE_BUFFER_COUNT: u32 = 4;
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
mod linux;
|
mod linux;
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
|
|||||||
@@ -38,7 +38,6 @@ const CSI_BRIDGE_NOSIGNAL_INTERVAL_MS: u64 = 500;
|
|||||||
const NOSIGNAL_POLL_MAX: Duration = Duration::from_secs(20);
|
const NOSIGNAL_POLL_MAX: Duration = Duration::from_secs(20);
|
||||||
/// Throttle repeated encoding errors to avoid log flooding
|
/// Throttle repeated encoding errors to avoid log flooding
|
||||||
const ENCODE_ERROR_THROTTLE_SECS: u64 = 5;
|
const ENCODE_ERROR_THROTTLE_SECS: u64 = 5;
|
||||||
const INVALID_MJPEG_LOG_THROTTLE_SECS: u64 = 5;
|
|
||||||
|
|
||||||
static PROCESS_START: std::sync::OnceLock<Instant> = std::sync::OnceLock::new();
|
static PROCESS_START: std::sync::OnceLock<Instant> = std::sync::OnceLock::new();
|
||||||
|
|
||||||
@@ -61,6 +60,7 @@ use crate::video::frame::{FrameBuffer, FrameBufferPool, VideoFrame};
|
|||||||
use crate::video::signal::SignalStatus;
|
use crate::video::signal::SignalStatus;
|
||||||
|
|
||||||
const MIN_CAPTURE_FRAME_SIZE: usize = 128;
|
const MIN_CAPTURE_FRAME_SIZE: usize = 128;
|
||||||
|
|
||||||
#[cfg(all(
|
#[cfg(all(
|
||||||
any(target_arch = "aarch64", target_arch = "arm"),
|
any(target_arch = "aarch64", target_arch = "arm"),
|
||||||
not(target_os = "android")
|
not(target_os = "android")
|
||||||
@@ -870,8 +870,6 @@ impl SharedVideoPipeline {
|
|||||||
let mut sequence: u64 = 0;
|
let mut sequence: u64 = 0;
|
||||||
let mut consecutive_timeouts: u32 = 0;
|
let mut consecutive_timeouts: u32 = 0;
|
||||||
let capture_error_throttler = LogThrottler::with_secs(5);
|
let capture_error_throttler = LogThrottler::with_secs(5);
|
||||||
let invalid_mjpeg_throttler =
|
|
||||||
LogThrottler::with_secs(INVALID_MJPEG_LOG_THROTTLE_SECS);
|
|
||||||
let mut suppressed_capture_errors: HashMap<String, u64> = HashMap::new();
|
let mut suppressed_capture_errors: HashMap<String, u64> = HashMap::new();
|
||||||
|
|
||||||
while pipeline.running_flag.load(Ordering::Acquire) {
|
while pipeline.running_flag.load(Ordering::Acquire) {
|
||||||
@@ -1232,24 +1230,8 @@ impl SharedVideoPipeline {
|
|||||||
}
|
}
|
||||||
|
|
||||||
owned.truncate(frame_size);
|
owned.truncate(frame_size);
|
||||||
if pixel_format.is_compressed() && !VideoFrame::is_valid_jpeg_bytes(&owned) {
|
|
||||||
if invalid_mjpeg_throttler.should_log("invalid_mjpeg_capture_frame") {
|
|
||||||
let b0 = owned.first().copied().unwrap_or_default();
|
|
||||||
let b1 = owned.get(1).copied().unwrap_or_default();
|
|
||||||
warn!(
|
|
||||||
"Dropping invalid MJPEG capture frame: size={}, starts with 0x{:02x} 0x{:02x}",
|
|
||||||
owned.len(),
|
|
||||||
b0,
|
|
||||||
b1
|
|
||||||
);
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Notify streaming only after frame validation passes —
|
// Notify streaming only after the short-frame guard passes.
|
||||||
// stale/warm-up frames from V4L2 kernel queues can cause
|
|
||||||
// DQBUF Ok with invalid data, which would prematurely
|
|
||||||
// clear the frontend error overlay.
|
|
||||||
pipeline.notify_state(PipelineStateNotification::streaming());
|
pipeline.notify_state(PipelineStateNotification::streaming());
|
||||||
let frame = Arc::new(VideoFrame::from_pooled(
|
let frame = Arc::new(VideoFrame::from_pooled(
|
||||||
Arc::new(FrameBuffer::new(owned, Some(buffer_pool.clone()))),
|
Arc::new(FrameBuffer::new(owned, Some(buffer_pool.clone()))),
|
||||||
|
|||||||
@@ -27,7 +27,9 @@ use crate::video::capture::status::{
|
|||||||
capture_error_log_key, classify_capture_io_error, signal_status_from_capture_kind,
|
capture_error_log_key, classify_capture_io_error, signal_status_from_capture_kind,
|
||||||
CaptureIoErrorKind,
|
CaptureIoErrorKind,
|
||||||
};
|
};
|
||||||
use crate::video::capture::{is_source_changed_error, BridgeContext, CaptureStream};
|
use crate::video::capture::{
|
||||||
|
is_source_changed_error, BridgeContext, CaptureStream, DEFAULT_CAPTURE_BUFFER_COUNT,
|
||||||
|
};
|
||||||
|
|
||||||
const MIN_CAPTURE_FRAME_SIZE: usize = 128;
|
const MIN_CAPTURE_FRAME_SIZE: usize = 128;
|
||||||
|
|
||||||
@@ -769,7 +771,7 @@ impl Streamer {
|
|||||||
const MAX_RETRIES: u32 = 5;
|
const MAX_RETRIES: u32 = 5;
|
||||||
const RETRY_DELAY_MS: u64 = 200;
|
const RETRY_DELAY_MS: u64 = 200;
|
||||||
const IDLE_STOP_DELAY_SECS: u64 = 5;
|
const IDLE_STOP_DELAY_SECS: u64 = 5;
|
||||||
const BUFFER_COUNT: u32 = 2;
|
const BUFFER_COUNT: u32 = DEFAULT_CAPTURE_BUFFER_COUNT;
|
||||||
/// Initial back-off after signal loss before the first soft restart.
|
/// Initial back-off after signal loss before the first soft restart.
|
||||||
///
|
///
|
||||||
/// PiKVM/ustreamer drops to sub-second recovery because it subscribes to
|
/// PiKVM/ustreamer drops to sub-second recovery because it subscribes to
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ use crate::audio::{AudioController, OpusFrame};
|
|||||||
use crate::error::{AppError, Result};
|
use crate::error::{AppError, Result};
|
||||||
use crate::events::{EventBus, StreamDeviceLostKind, SystemEvent};
|
use crate::events::{EventBus, StreamDeviceLostKind, SystemEvent};
|
||||||
use crate::hid::HidController;
|
use crate::hid::HidController;
|
||||||
|
use crate::video::capture::DEFAULT_CAPTURE_BUFFER_COUNT;
|
||||||
use crate::video::codec::h264_bitstream;
|
use crate::video::codec::h264_bitstream;
|
||||||
use crate::video::device::{
|
use crate::video::device::{
|
||||||
enumerate_devices, select_recovery_device, VideoDevice, VideoDeviceRecoveryHint,
|
enumerate_devices, select_recovery_device, VideoDevice, VideoDeviceRecoveryHint,
|
||||||
@@ -319,7 +320,7 @@ impl WebRtcStreamer {
|
|||||||
current_capture
|
current_capture
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|capture| capture.buffer_count)
|
.map(|capture| capture.buffer_count)
|
||||||
.unwrap_or(2),
|
.unwrap_or(DEFAULT_CAPTURE_BUFFER_COUNT),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -745,7 +746,7 @@ impl WebRtcStreamer {
|
|||||||
});
|
});
|
||||||
*self.capture_device.write().await = Some(CaptureDeviceConfig {
|
*self.capture_device.write().await = Some(CaptureDeviceConfig {
|
||||||
device_path,
|
device_path,
|
||||||
buffer_count: 2,
|
buffer_count: DEFAULT_CAPTURE_BUFFER_COUNT,
|
||||||
jpeg_quality,
|
jpeg_quality,
|
||||||
subdev_path,
|
subdev_path,
|
||||||
bridge_kind,
|
bridge_kind,
|
||||||
|
|||||||
Reference in New Issue
Block a user