From 91d6f90a3bbcdf5ec4fc788ef440328d76881efc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Laitl?= Date: Sat, 11 Mar 2023 00:14:56 +0100 Subject: [PATCH 1/3] Introduce `recv_blocking()` method on `PayloadReceiver` Allows callers to wait for a frame without using futures. --- README.md | 40 +++++++++++++++--------------------- cameleon/README.md | 41 +++++++++++++++---------------------- cameleon/examples/stream.rs | 34 +++++++++++++----------------- cameleon/src/payload.rs | 6 ++++++ 4 files changed, 54 insertions(+), 67 deletions(-) diff --git a/README.md b/README.md index d4d73cf9..d693cebf 100644 --- a/README.md +++ b/README.md @@ -62,30 +62,24 @@ camera.load_context().unwrap(); // Start streaming. Channel capacity is set to 3. let payload_rx = camera.start_streaming(3).unwrap(); -let mut payload_count = 0; -while payload_count < 10 { - match payload_rx.try_recv() { - Ok(payload) => { - println!( - "payload received! block_id: {:?}, timestamp: {:?}", - payload.id(), - payload.timestamp() - ); - if let Some(image_info) = payload.image_info() { - println!("{:?}\n", image_info); - let image = payload.image(); - // do something with the image. - // ... - } - payload_count += 1; - - // Send back payload to streaming loop to reuse the buffer. This is optional. - payload_rx.send_back(payload); - } - Err(_err) => { - continue; - } +for _ in 0..10 { + let payload = payload_rx + .recv_blocking() + .expect("should receive a payload"); + println!( + "payload received! block_id: {:?}, timestamp: {:?}", + payload.id(), + payload.timestamp() + ); + if let Some(image_info) = payload.image_info() { + println!("{:?}\n", image_info); + let image = payload.image(); + // do something with the image. + // ... } + + // Send back payload to streaming loop to reuse the buffer. This is optional. + payload_rx.send_back(payload); } // Closes the camera. diff --git a/cameleon/README.md b/cameleon/README.md index 120bfaf7..fe196e3d 100644 --- a/cameleon/README.md +++ b/cameleon/README.md @@ -62,30 +62,24 @@ camera.load_context().unwrap(); // Start streaming. Channel capacity is set to 3. let payload_rx = camera.start_streaming(3).unwrap(); -let mut payload_count = 0; -while payload_count < 10 { - match payload_rx.try_recv() { - Ok(payload) => { - println!( - "payload received! block_id: {:?}, timestamp: {:?}", - payload.id(), - payload.timestamp() - ); - if let Some(image_info) = payload.image_info() { - println!("{:?}\n", image_info); - let image = payload.image(); - // do something with the image. - // ... - } - payload_count += 1; - - // Send back payload to streaming loop to reuse the buffer. This is optional. - payload_rx.send_back(payload); - } - Err(_err) => { - continue; - } +for _ in 0..10 { + let payload = payload_rx + .recv_blocking() + .expect("should receive a payload"); + println!( + "payload received! block_id: {:?}, timestamp: {:?}", + payload.id(), + payload.timestamp() + ); + if let Some(image_info) = payload.image_info() { + println!("{:?}\n", image_info); + let image = payload.image(); + // do something with the image. + // ... } + + // Send back payload to streaming loop to reuse the buffer. This is optional. + payload_rx.send_back(payload); } // Closes the camera. @@ -188,4 +182,3 @@ To start developing, please refer to [CONTRIBUTING.md][contributing]. This project is licenced under [MPL 2.0][license]. [license]: https://github.com/cameleon-rs/cameleon/blob/main/LICENSE - diff --git a/cameleon/examples/stream.rs b/cameleon/examples/stream.rs index 6d6a89d2..913e944f 100644 --- a/cameleon/examples/stream.rs +++ b/cameleon/examples/stream.rs @@ -25,27 +25,21 @@ fn main() { // Start streaming. Channel capacity is set to 3. let payload_rx = camera.start_streaming(3).unwrap(); - let mut payload_count = 0_usize; - while payload_count < 10 { - match payload_rx.try_recv() { - Ok(payload) => { - println!( - "payload received! block_id: {:?}, timestamp: {:?}", - payload.id(), - payload.timestamp() - ); - if let Some(image_info) = payload.image_info() { - println!("{:?}\n", image_info); - } - payload_count += 1; - - // Send back payload to streaming loop to reuse the buffer. - payload_rx.send_back(payload); - } - Err(_err) => { - continue; - } + for _ in 0..10 { + let payload = payload_rx + .recv_blocking() + .expect("should receive a payload"); + println!( + "payload received! block_id: {:?}, timestamp: {:?}", + payload.id(), + payload.timestamp() + ); + if let Some(image_info) = payload.image_info() { + println!("{:?}\n", image_info); } + + // Send back payload to streaming loop to reuse the buffer. + payload_rx.send_back(payload); } camera.close().ok(); diff --git a/cameleon/src/payload.rs b/cameleon/src/payload.rs index 7cf168af..c6560bb7 100644 --- a/cameleon/src/payload.rs +++ b/cameleon/src/payload.rs @@ -122,6 +122,12 @@ impl PayloadReceiver { self.rx.try_recv()? } + /// Receives [`Payload`] sent from the device. + /// If the channel is empty, this method blocks until the device produces the payload. + pub fn recv_blocking(&self) -> StreamResult { + self.rx.recv_blocking()? + } + /// Sends back [`Payload`] to the device to reuse already allocated `payload`. /// /// Sending back `payload` may improve performance of streaming, but not required to call this From d7caba65af1c7239bf381824c30a73b4486d1425 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Laitl?= Date: Sun, 12 Mar 2023 20:48:01 +0100 Subject: [PATCH 2/3] Bump async-std dependency to 1.12 --- cameleon/Cargo.toml | 4 ++-- device/Cargo.toml | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/cameleon/Cargo.toml b/cameleon/Cargo.toml index 057eca0a..07ed97e2 100644 --- a/cameleon/Cargo.toml +++ b/cameleon/Cargo.toml @@ -10,7 +10,7 @@ repository = "https://github.com/cameleon-rs/cameleon" description = """ cameleon is a safe, fast, and flexible library for GenICam compatible cameras. """ -categories = ["computer-vision"] +categories = ["computer-vision"] keywords = ["genicam", "camera", "usb3", "gige", "uvc"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -20,7 +20,7 @@ thiserror = "1.0.24" semver = "1.0.0" zip = "0.6.0" sha-1 = "0.10.0" -async-std = { version = "1.9.0", features = ["unstable"] } +async-std = { version = "1.12.0", features = ["unstable"] } futures = "0.3.14" tracing = "0.1.26" auto_impl = "1.0.1" diff --git a/device/Cargo.toml b/device/Cargo.toml index dd14016e..f06dbd33 100644 --- a/device/Cargo.toml +++ b/device/Cargo.toml @@ -10,14 +10,14 @@ repository = "https://github.com/cameleon-rs/cameleon" description = """ cameleon-device provides device specific protocol decoders and basic I/O operations for GenICam compatible devices. """ -categories = ["computer-vision"] +categories = ["computer-vision"] keywords = ["genicam", "camera", "usb3", "gige", "uvc"] [dependencies] thiserror = "1.0.24" log = "0.4.14" semver = "1.0.0" -async-std = { version = "1.9.0", features = ["unstable"] } +async-std = { version = "1.12.0", features = ["unstable"] } const_format = "0.2.14" futures = "0.3.14" lazy_static = "1.4.0" @@ -29,7 +29,6 @@ rusb = { version = "0.9.0", optional = true } libusb1-sys = { version = "0.6.0", optional = true } libc = { version = "0.2", optional = true } - [dev-dependencies] trybuild = "1.0.42" From 72489df3ca0cc9f324bf2446dc19c346cf332630 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Mon, 13 Mar 2023 19:26:26 +0100 Subject: [PATCH 3/3] Swap the order of streaming loop operation and state modification operation --- cameleon/src/camera.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/cameleon/src/camera.rs b/cameleon/src/camera.rs index 5f1ca924..40679cca 100644 --- a/cameleon/src/camera.rs +++ b/cameleon/src/camera.rs @@ -303,16 +303,20 @@ impl Camera { return Err(StreamError::InStreaming.into()); } - // Enable streaimng. + // Lock TLParams to prevent changing parameters while streaming. + // Some camera models require this to obtain parameters for streaming. self.ctrl.enable_streaming()?; let mut ctxt = self.params_ctxt()?; expect_node!(&ctxt, "TLParamsLocked", as_integer).set_value(&mut ctxt, 1)?; - expect_node!(&ctxt, "AcquisitionStart", as_command).execute(&mut ctxt)?; // Start streaming loop. let (sender, receiver) = channel(cap, DEFAULT_BUFFER_CAP); self.strm.start_streaming_loop(sender, &mut self.ctrl)?; + // Enable streaming. + let mut ctxt = self.params_ctxt()?; + expect_node!(&ctxt, "AcquisitionStart", as_command).execute(&mut ctxt)?; + info!("start streaming successfully"); Ok(receiver) } @@ -358,14 +362,13 @@ impl Camera { return Ok(()); } - // Stop streaming loop. - self.strm.stop_streaming_loop()?; - // Disable streaming. let mut ctxt = self.params_ctxt()?; expect_node!(&ctxt, "AcquisitionStop", as_command).execute(&mut ctxt)?; expect_node!(&ctxt, "TLParamsLocked", as_integer).set_value(&mut ctxt, 0)?; self.ctrl.disable_streaming()?; + // Stop streaming loop. + self.strm.stop_streaming_loop()?; info!("stop streaming successfully"); Ok(())