From 5e7d558f9961bcf3d601bc4275be576de5d55655 Mon Sep 17 00:00:00 2001 From: Scott Lamb Date: Tue, 12 Apr 2022 14:57:16 -0700 Subject: [PATCH] upgrade to Retina v0.3.9 This alone improves interop and diagnostics, as noted in Retina's release notes. We also now give the camera name to the session group (for improved logging of TEARDOWN operations) and expose the RTSP server's "tool" attribute in debug logs and the config UI's "Test" button. Fixes #209 Fixes #213 --- CHANGELOG.md | 4 ++++ server/Cargo.lock | 4 ++-- server/Cargo.toml | 2 +- server/src/cmds/config/cameras.rs | 8 +++++--- server/src/cmds/run/mod.rs | 5 ++++- server/src/stream.rs | 13 ++++++++++++- server/src/streamer.rs | 4 ++++ 7 files changed, 32 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 13e0217..588c986 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ changes, see Git history. Each release is tagged in Git and on the Docker repository [`scottlamb/moonfire-nvr`](https://hub.docker.com/r/scottlamb/moonfire-nvr). +## unreleased + +* upgrade to Retina 0.3.9, improving camera interop and diagnostics + ## `v0.7.3` (2022-03-22) * security fix: check the `Origin` header on live stream WebSocket requests diff --git a/server/Cargo.lock b/server/Cargo.lock index 285b0cd..5cbf348 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -1640,9 +1640,9 @@ dependencies = [ [[package]] name = "retina" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3629d5f6a30d1a0ee184bd2a3e62eba8ffbb121250a8c72ed984575c9ffb0601" +checksum = "df90aca400866f8b1327902f7c9e93ab17f195c36b7e06b804e8acd3a79bbe41" dependencies = [ "base64", "bitreader", diff --git a/server/Cargo.toml b/server/Cargo.toml index 825009b..073b97d 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -46,7 +46,7 @@ parking_lot = "0.12.0" password-hash = "0.3.2" protobuf = "3.0.0-alpha.1" reffers = "0.7.0" -retina = "0.3.7" +retina = "0.3.9" ring = "0.16.2" rusqlite = "0.27.0" serde = { version = "1.0", features = ["derive"] } diff --git a/server/src/cmds/config/cameras.rs b/server/src/cmds/config/cameras.rs index f20355f..c875b76 100644 --- a/server/src/cmds/config/cameras.rs +++ b/server/src/cmds/config/cameras.rs @@ -214,7 +214,7 @@ fn press_test_inner( .enable_io() .build()?; let _guard = rt.enter(); - let (extra_data, _stream) = stream::OPENER.open( + let (extra_data, stream) = stream::OPENER.open( &rt, "test stream".to_owned(), url, @@ -227,8 +227,10 @@ fn press_test_inner( .transport(transport), )?; Ok(format!( - "{}x{} video stream", - extra_data.width, extra_data.height + "{}x{} video stream served by tool {:?}", + extra_data.width, + extra_data.height, + stream.tool(), )) } diff --git a/server/src/cmds/run/mod.rs b/server/src/cmds/run/mod.rs index 8978ce8..8ad6c8d 100644 --- a/server/src/cmds/run/mod.rs +++ b/server/src/cmds/run/mod.rs @@ -13,6 +13,7 @@ use fnv::FnvHashMap; use hyper::service::{make_service_fn, service_fn}; use log::error; use log::{info, warn}; +use retina::client::SessionGroup; use std::net::SocketAddr; use std::path::Path; use std::path::PathBuf; @@ -324,7 +325,9 @@ async fn inner( let syncer = syncers.get(&sample_file_dir_id).unwrap(); let session_group = session_groups_by_camera .entry(camera.id) - .or_default() + .or_insert_with(|| { + Arc::new(SessionGroup::default().named(camera.short_name.clone())) + }) .clone(); let mut streamer = streamer::Streamer::new( &env, diff --git a/server/src/stream.rs b/server/src/stream.rs index c225626..4f72006 100644 --- a/server/src/stream.rs +++ b/server/src/stream.rs @@ -45,6 +45,7 @@ pub struct VideoFrame { } pub trait Stream: Send { + fn tool(&self) -> Option<&retina::client::Tool>; fn next(&mut self) -> Result; } @@ -63,7 +64,7 @@ impl Opener for RealOpener { let options = options.user_agent(format!("Moonfire NVR {}", env!("CARGO_PKG_VERSION"))); let (session, video_params, first_frame) = rt.block_on(tokio::time::timeout( RETINA_TIMEOUT, - RetinaStream::play(url, options), + RetinaStream::play(&label, url, options), ))??; let extra_data = h264::parse_extra_data(video_params.extra_data())?; let stream = Box::new(RetinaStream { @@ -91,6 +92,7 @@ struct RetinaStream<'a> { impl<'a> RetinaStream<'a> { /// Plays to first frame. No timeout; that's the caller's responsibility. async fn play( + label: &str, url: Url, options: retina::client::SessionOptions, ) -> Result< @@ -102,6 +104,7 @@ impl<'a> RetinaStream<'a> { Error, > { let mut session = retina::client::Session::describe(url, options).await?; + log::debug!("connected to {:?}, tool {:?}", label, session.tool()); let (video_i, mut video_params) = session .streams() .iter() @@ -177,6 +180,10 @@ impl<'a> RetinaStream<'a> { } impl<'a> Stream for RetinaStream<'a> { + fn tool(&self) -> Option<&retina::client::Tool> { + Pin::into_inner(self.session.as_ref()).tool() + } + fn next(&mut self) -> Result { let frame = self.first_frame.take().map(Ok).unwrap_or_else(|| { self.rt @@ -247,6 +254,10 @@ pub mod testutil { } impl Stream for Mp4Stream { + fn tool(&self) -> Option<&retina::client::Tool> { + None + } + fn next(&mut self) -> Result { let sample = self .reader diff --git a/server/src/streamer.rs b/server/src/streamer.rs index 33bcc4e..c4f617b 100644 --- a/server/src/streamer.rs +++ b/server/src/streamer.rs @@ -313,6 +313,10 @@ mod tests { } impl Stream for ProxyingStream { + fn tool(&self) -> Option<&retina::client::Tool> { + self.inner.tool() + } + fn next(&mut self) -> Result { if self.pkts_left == 0 { bail!("end of stream");