fix: reject MJPEG during HEVC UVC handoff

This commit is contained in:
Brad Stein 2026-05-19 13:09:08 -03:00
parent e4a4ca1c9d
commit 6b98f067c4
7 changed files with 26 additions and 7 deletions

6
Cargo.lock generated
View File

@ -1658,7 +1658,7 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2"
[[package]]
name = "lesavka_client"
version = "0.26.1"
version = "0.26.2"
dependencies = [
"anyhow",
"async-stream",
@ -1692,7 +1692,7 @@ dependencies = [
[[package]]
name = "lesavka_common"
version = "0.26.1"
version = "0.26.2"
dependencies = [
"anyhow",
"base64",
@ -1704,7 +1704,7 @@ dependencies = [
[[package]]
name = "lesavka_server"
version = "0.26.1"
version = "0.26.2"
dependencies = [
"anyhow",
"base64",

View File

@ -4,7 +4,7 @@ path = "src/main.rs"
[package]
name = "lesavka_client"
version = "0.26.1"
version = "0.26.2"
edition = "2024"
[dependencies]

View File

@ -1,6 +1,6 @@
[package]
name = "lesavka_common"
version = "0.26.1"
version = "0.26.2"
edition = "2024"
build = "build.rs"

View File

@ -16,7 +16,7 @@ bench = false
[package]
name = "lesavka_server"
version = "0.26.1"
version = "0.26.2"
edition = "2024"
autobins = false

View File

@ -47,6 +47,7 @@ pub struct WebcamSink {
uvc_width: u16,
uvc_height: u16,
direct_mjpeg_profile_mismatch_seen: AtomicBool,
unexpected_mjpeg_in_hevc_seen: AtomicBool,
last_decoded_mjpeg_bytes: AtomicU64,
direct_mjpeg_normalize_bypassed: AtomicBool,
normalized_mjpeg_miss_count: AtomicU64,

View File

@ -62,6 +62,7 @@ impl WebcamSink {
uvc_width: cfg.width.min(u32::from(u16::MAX)) as u16,
uvc_height: cfg.height.min(u32::from(u16::MAX)) as u16,
direct_mjpeg_profile_mismatch_seen: AtomicBool::new(false),
unexpected_mjpeg_in_hevc_seen: AtomicBool::new(false),
last_decoded_mjpeg_bytes: AtomicU64::new(0),
direct_mjpeg_normalize_bypassed: AtomicBool::new(false),
normalized_mjpeg_miss_count: AtomicU64::new(0),
@ -368,6 +369,7 @@ impl WebcamSink {
uvc_width: cfg.width.min(u32::from(u16::MAX)) as u16,
uvc_height: cfg.height.min(u32::from(u16::MAX)) as u16,
direct_mjpeg_profile_mismatch_seen: AtomicBool::new(false),
unexpected_mjpeg_in_hevc_seen: AtomicBool::new(false),
last_decoded_mjpeg_bytes: AtomicU64::new(0),
direct_mjpeg_normalize_bypassed: AtomicBool::new(false),
normalized_mjpeg_miss_count: AtomicU64::new(0),

View File

@ -26,8 +26,24 @@ impl WebcamSink {
#[cfg(not(coverage))]
pub fn push(&self, pkt: VideoPacket) {
let packet_is_mjpeg = looks_like_mjpeg_frame(&pkt.data);
if packet_is_mjpeg && self.decoded_mjpeg_sink.is_some() {
if !self
.unexpected_mjpeg_in_hevc_seen
.swap(true, Ordering::Relaxed)
{
warn!(
target:"lesavka_server::video",
bytes = pkt.data.len(),
pts = pkt.pts,
"dropping MJPEG packet received while HEVC UVC decoder is active; restart or update the upstream client so it emits HEVC"
);
}
return;
}
if let Some(path) = &self.mjpeg_spool_path
&& looks_like_mjpeg_frame(&pkt.data)
&& packet_is_mjpeg
{
self.spool_direct_mjpeg_frame(path, &pkt);
return;