Skip to content

Commit

Permalink
experiment: camera on thread
Browse files Browse the repository at this point in the history
  • Loading branch information
payload committed Aug 20, 2023
1 parent dcae88e commit 21bffcf
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 30 deletions.
37 changes: 7 additions & 30 deletions examples/iced.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,21 @@
use std::iter::repeat;
use std::sync::mpsc::{channel, Receiver, Sender, TryRecvError};
use std::sync::mpsc::{channel, Receiver, Sender};

Check warning on line 2 in examples/iced.rs

View workflow job for this annotation

GitHub Actions / linux (stable)

unused imports: `Receiver`, `Sender`, `channel`
use std::time::Instant;

use iced::widget::{column, container, image, text};
use iced::{
executor, window, Alignment, Application, Command, Element, Length, Settings, Subscription,
Theme,
};
use kamera::{Camera, CameraInfo};
use kamera::{Camera, CameraInfo, CameraOnThread};

Check warning on line 10 in examples/iced.rs

View workflow job for this annotation

GitHub Actions / linux (stable)

unused import: `Camera`

Check warning on line 10 in examples/iced.rs

View workflow job for this annotation

GitHub Actions / macos (stable)

unused import: `Camera`

Check warning on line 10 in examples/iced.rs

View workflow job for this annotation

GitHub Actions / windows (stable)

unused import: `Camera`

pub fn main() -> iced::Result {
Example::run(Settings::default())
}

struct Example {
camera: Camera,
camera: CameraOnThread,
cameras: Vec<CameraInfo>,
#[allow(unused)]
end_camera: Sender<()>,
send_frame: Sender<((u32, u32), Vec<u8>)>,
camera_frame: Receiver<((u32, u32), Vec<u8>)>,
current_frame: image::Handle,
}

Expand All @@ -36,25 +32,14 @@ impl Application for Example {
type Flags = ();

fn new(_flags: Self::Flags) -> (Self, Command<Message>) {
let (end_camera, end) = channel::<()>();
let (send_frame, camera_frame) = channel::<((u32, u32), Vec<u8>)>();
let (send_cameras, cameras) = channel::<Vec<CameraInfo>>();
// std::thread::spawn(move || {
let _ = send_cameras.send(Camera::enumerate_cameras());
let camera = Camera::new_default_device();
camera.start();

// });

let cameras = cameras.recv().expect("enumerate cameras");
let camera = CameraOnThread::new_default_device();
let cameras = CameraOnThread::enumerate_cameras();
camera.start();

(
Self {
camera,
cameras,
end_camera,
send_frame,
camera_frame,
current_frame: image::Handle::from_pixels(
16,
16,
Expand All @@ -76,15 +61,7 @@ impl Application for Example {
fn update(&mut self, message: Message) -> Command<Message> {
match message {
Message::Tick(_instant) => {
if let Some(frame) = self.camera.wait_for_frame() {
let size = frame.size_u32();
let pixels = frame.data().data_u8().to_vec();
if self.send_frame.send((size, pixels)).is_err() {

}
}

while let Ok(((w, h), pixels)) = self.camera_frame.try_recv() {
if let Some(((w, h), pixels)) = self.camera.wait_for_frame() {
self.current_frame = image::Handle::from_pixels(w, h, pixels);
}
}
Expand Down
100 changes: 100 additions & 0 deletions src/camera_on_thread.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
use std::{
sync::mpsc::{channel, Receiver, Sender},
thread::JoinHandle,
};

use crate::{Camera, CameraInfo};

enum Message {
NewDefaultDevice,
EnumerateCameras,

Check failure on line 10 in src/camera_on_thread.rs

View workflow job for this annotation

GitHub Actions / linux (stable)

variant `EnumerateCameras` is never constructed

Check warning on line 10 in src/camera_on_thread.rs

View workflow job for this annotation

GitHub Actions / linux (stable)

variant `EnumerateCameras` is never constructed

Check warning on line 10 in src/camera_on_thread.rs

View workflow job for this annotation

GitHub Actions / linux (stable)

variant `EnumerateCameras` is never constructed

Check warning on line 10 in src/camera_on_thread.rs

View workflow job for this annotation

GitHub Actions / macos (stable)

variant `EnumerateCameras` is never constructed

Check failure on line 10 in src/camera_on_thread.rs

View workflow job for this annotation

GitHub Actions / macos (stable)

variant `EnumerateCameras` is never constructed

Check warning on line 10 in src/camera_on_thread.rs

View workflow job for this annotation

GitHub Actions / macos (stable)

variant `EnumerateCameras` is never constructed

Check warning on line 10 in src/camera_on_thread.rs

View workflow job for this annotation

GitHub Actions / windows (stable)

variant `EnumerateCameras` is never constructed

Check failure on line 10 in src/camera_on_thread.rs

View workflow job for this annotation

GitHub Actions / windows (stable)

variant `EnumerateCameras` is never constructed

Check warning on line 10 in src/camera_on_thread.rs

View workflow job for this annotation

GitHub Actions / windows (stable)

variant `EnumerateCameras` is never constructed
Start,
Stop,
WaitForFrame,
ChangeDevice,
}

enum Response {
EnumerateCameras(Vec<CameraInfo>),
WaitForFrame(((u32, u32), Vec<u8>)),
}

pub struct CameraOnThread {
messages: Sender<Message>,
responses: Receiver<Response>,
thread_join: JoinHandle<()>,

Check failure on line 25 in src/camera_on_thread.rs

View workflow job for this annotation

GitHub Actions / linux (stable)

field `thread_join` is never read

Check warning on line 25 in src/camera_on_thread.rs

View workflow job for this annotation

GitHub Actions / linux (stable)

field `thread_join` is never read

Check warning on line 25 in src/camera_on_thread.rs

View workflow job for this annotation

GitHub Actions / linux (stable)

field `thread_join` is never read

Check warning on line 25 in src/camera_on_thread.rs

View workflow job for this annotation

GitHub Actions / macos (stable)

field `thread_join` is never read

Check failure on line 25 in src/camera_on_thread.rs

View workflow job for this annotation

GitHub Actions / macos (stable)

field `thread_join` is never read

Check warning on line 25 in src/camera_on_thread.rs

View workflow job for this annotation

GitHub Actions / macos (stable)

field `thread_join` is never read

Check warning on line 25 in src/camera_on_thread.rs

View workflow job for this annotation

GitHub Actions / windows (stable)

field `thread_join` is never read

Check failure on line 25 in src/camera_on_thread.rs

View workflow job for this annotation

GitHub Actions / windows (stable)

field `thread_join` is never read

Check warning on line 25 in src/camera_on_thread.rs

View workflow job for this annotation

GitHub Actions / windows (stable)

field `thread_join` is never read
}

impl CameraOnThread {
pub fn new_default_device() -> Self {
let (messages, message_rx) = channel::<Message>();
let (response_tx, responses) = channel::<Response>();
let thread_join = std::thread::spawn(move || {
use Message::*;
let mut camera = None;
let mut send_result = Ok(());
while let (Ok(message), Ok(())) = (message_rx.recv(), &send_result) {
match message {
NewDefaultDevice => {
camera = Some(Camera::new_default_device());
}
EnumerateCameras => {
send_result = response_tx
.send(Response::EnumerateCameras(Camera::enumerate_cameras()));
}
Start => {
camera.as_ref().map(|c| c.start());

Check failure on line 46 in src/camera_on_thread.rs

View workflow job for this annotation

GitHub Actions / linux (stable)

called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()`

Check failure on line 46 in src/camera_on_thread.rs

View workflow job for this annotation

GitHub Actions / macos (stable)

called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()`

Check failure on line 46 in src/camera_on_thread.rs

View workflow job for this annotation

GitHub Actions / windows (stable)

called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()`
}
Stop => {
camera.as_ref().map(|c| c.stop());

Check failure on line 49 in src/camera_on_thread.rs

View workflow job for this annotation

GitHub Actions / linux (stable)

called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()`

Check failure on line 49 in src/camera_on_thread.rs

View workflow job for this annotation

GitHub Actions / macos (stable)

called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()`

Check failure on line 49 in src/camera_on_thread.rs

View workflow job for this annotation

GitHub Actions / windows (stable)

called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()`
}
WaitForFrame => {
if let Some(ref camera) = camera {
if let Some(frame) = camera.wait_for_frame() {
let size = frame.size_u32();
let pixels = frame.data().data_u8().to_vec();
let response = Response::WaitForFrame((size, pixels));
send_result = response_tx.send(response);
}
}
}
ChangeDevice => {
camera.as_mut().map(|c| c.change_device());

Check failure on line 62 in src/camera_on_thread.rs

View workflow job for this annotation

GitHub Actions / linux (stable)

called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()`

Check failure on line 62 in src/camera_on_thread.rs

View workflow job for this annotation

GitHub Actions / macos (stable)

called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()`

Check failure on line 62 in src/camera_on_thread.rs

View workflow job for this annotation

GitHub Actions / windows (stable)

called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()`
}
}
}
if let Some(camera) = camera {
camera.stop();
}
});

messages.send(Message::NewDefaultDevice).unwrap();

CameraOnThread { messages, responses, thread_join }
}

pub fn enumerate_cameras() -> Vec<CameraInfo> {
std::thread::spawn(|| Camera::enumerate_cameras()).join().unwrap()

Check failure on line 77 in src/camera_on_thread.rs

View workflow job for this annotation

GitHub Actions / linux (stable)

redundant closure

Check failure on line 77 in src/camera_on_thread.rs

View workflow job for this annotation

GitHub Actions / macos (stable)

redundant closure

Check failure on line 77 in src/camera_on_thread.rs

View workflow job for this annotation

GitHub Actions / windows (stable)

redundant closure
}

pub fn start(&self) {
self.messages.send(Message::Start).unwrap();
}

pub fn stop(&self) {
self.messages.send(Message::Stop).unwrap();
}

pub fn change_device(&mut self) {
self.messages.send(Message::ChangeDevice).unwrap();
}

pub fn wait_for_frame(&self) -> Option<((u32, u32), Vec<u8>)> {
self.messages.send(Message::WaitForFrame).unwrap();
if let Response::WaitForFrame((size, pixels)) = self.responses.recv().unwrap() {
return Some((size, pixels));

Check failure on line 95 in src/camera_on_thread.rs

View workflow job for this annotation

GitHub Actions / linux (stable)

unneeded `return` statement

Check failure on line 95 in src/camera_on_thread.rs

View workflow job for this annotation

GitHub Actions / macos (stable)

unneeded `return` statement

Check failure on line 95 in src/camera_on_thread.rs

View workflow job for this annotation

GitHub Actions / windows (stable)

unneeded `return` statement
} else {
todo!();
}
}
}
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
mod camera;
pub use camera::*;

mod camera_on_thread;
pub use camera_on_thread::*;

#[cfg(target_os = "macos")]
pub(crate) mod mac_avf;

Expand Down

0 comments on commit 21bffcf

Please sign in to comment.