freya_camera/
use_camera.rs1use std::{
4 cell::RefCell,
5 rc::Rc,
6};
7
8use freya_core::{
9 elements::image::ImageHolder,
10 prelude::*,
11};
12use freya_engine::prelude::{
13 AlphaType,
14 ColorType,
15 Data,
16 ISize,
17 ImageInfo,
18 raster_from_data,
19};
20
21use crate::{
22 camera::{
23 CameraConfig,
24 CameraError,
25 StreamInfo,
26 },
27 capture::{
28 CameraFrame,
29 CaptureHandle,
30 CaptureState,
31 spawn_capture,
32 },
33};
34
35#[derive(Clone, Copy, PartialEq)]
37pub struct Camera {
38 pub frame: State<Option<ImageHolder>>,
40 pub info: State<Option<StreamInfo>>,
42 pub error: State<Option<CameraError>>,
44}
45
46impl Camera {
47 pub fn create(config: CameraConfig) -> Self {
49 let mut frame: State<Option<ImageHolder>> = State::create(None);
50 let mut info: State<Option<StreamInfo>> = State::create(None);
51 let mut error: State<Option<CameraError>> = State::create(None);
52
53 let CaptureHandle { state, wake } = spawn_capture(config);
54
55 spawn(async move {
56 loop {
57 wake.notified().await;
58
59 let CaptureState {
60 frame: latest_frame,
61 info: latest_info,
62 error: latest_error,
63 } = std::mem::take(&mut *state.lock().unwrap());
64
65 if let Some(stream_info) = latest_info {
66 *info.write() = Some(stream_info);
67 }
68 if let Some(capture_error) = latest_error {
69 tracing::warn!("freya-camera: {capture_error}");
70 *error.write() = Some(capture_error);
71 }
72 if let Some(camera_frame) = latest_frame {
73 match build_holder(camera_frame) {
74 Ok(holder) => *frame.write() = Some(holder),
75 Err(build_error) => {
76 tracing::warn!("freya-camera: {build_error}");
77 *error.write() = Some(build_error);
78 }
79 }
80 }
81 }
82 });
83
84 Self { frame, info, error }
85 }
86}
87
88pub fn use_camera(init: impl FnOnce() -> CameraConfig) -> Camera {
105 use_hook(|| Camera::create(init()))
106}
107
108fn build_holder(frame: CameraFrame) -> Result<ImageHolder, CameraError> {
110 let CameraFrame {
111 width,
112 height,
113 data,
114 } = frame;
115
116 let info = ImageInfo::new(
117 ISize::new(width as i32, height as i32),
118 ColorType::RGBA8888,
119 AlphaType::Opaque,
120 None,
121 );
122 let row_bytes = (width as usize) * 4;
123 let sk_data = unsafe { Data::new_bytes(&data) };
125 let image = raster_from_data(&info, sk_data, row_bytes)
126 .ok_or_else(|| CameraError::GeneralError("failed to create raster image".to_string()))?;
127
128 Ok(ImageHolder {
129 image: Rc::new(RefCell::new(image)),
130 bytes: data,
131 })
132}