1
- use nokhwa:: { Camera , utils:: { CameraInfo , CameraIndex , CameraFormat , FrameFormat , RequestedFormat , RequestedFormatType , ApiBackend } , pixel_format:: RgbFormat } ;
2
- use rustface:: { ImageData , Detector , FaceInfo } ;
3
- use std:: sync:: { Arc , Mutex } ;
4
- use tokio:: time:: { interval, Duration } ;
1
+ use nokhwa:: { Camera , utils:: { CameraInfo , ApiBackend } } ;
2
+ use std:: sync:: { Arc } ;
5
3
use crate :: commands:: log_message;
6
-
7
- pub struct ThreadSafeCamera ( Arc < Mutex < Camera > > ) ;
8
-
9
- impl ThreadSafeCamera {
10
- pub fn new ( index : CameraIndex , format : RequestedFormat ) -> Result < Self , nokhwa:: NokhwaError > {
11
- let camera = Camera :: new ( index, format) ?;
12
- Ok ( ThreadSafeCamera ( Arc :: new ( Mutex :: new ( camera) ) ) )
13
- }
14
-
15
- pub fn frame ( & self ) -> Result < nokhwa:: Buffer , nokhwa:: NokhwaError > {
16
- let mut camera = self . 0 . lock ( ) . unwrap ( ) ;
17
- camera. frame ( )
18
- }
19
-
20
- pub fn open_stream ( & self ) -> Result < ( ) , nokhwa:: NokhwaError > {
21
- let mut camera = self . 0 . lock ( ) . unwrap ( ) ;
22
- camera. open_stream ( )
23
- }
24
- }
25
-
26
- unsafe impl Send for ThreadSafeCamera { }
27
- unsafe impl Sync for ThreadSafeCamera { }
28
-
29
- pub struct ThreadSafeDetector ( Arc < Mutex < Box < dyn Detector + Send > > > ) ;
30
-
31
- impl ThreadSafeDetector {
32
- pub fn new ( detector : Box < dyn Detector + Send > ) -> Self {
33
- ThreadSafeDetector ( Arc :: new ( Mutex :: new ( detector) ) )
34
- }
35
-
36
- pub fn detect ( & self , image : & ImageData ) -> Vec < FaceInfo > {
37
- let mut detector = self . 0 . lock ( ) . unwrap ( ) ;
38
- detector. detect ( image)
39
- }
40
- }
41
-
42
- unsafe impl Send for ThreadSafeDetector { }
43
- unsafe impl Sync for ThreadSafeDetector { }
4
+ use parking_lot:: Mutex as PLMutex ;
44
5
45
6
pub struct CameraController {
46
- camera : ThreadSafeCamera ,
47
- camera_active : Arc < Mutex < bool > > ,
48
- face_position : Arc < Mutex < Option < ( f64 , f64 ) > > > ,
49
- selected_camera_index : Arc < Mutex < Option < usize > > > ,
50
- detector : ThreadSafeDetector ,
7
+ camera : Arc < PLMutex < Option < Camera > > > ,
8
+ selected_camera_index : Arc < PLMutex < Option < usize > > > ,
51
9
}
52
10
11
+ // 实现 Send 和 Sync
12
+ unsafe impl Send for CameraController { }
13
+ unsafe impl Sync for CameraController { }
14
+
53
15
impl CameraController {
54
- pub fn new ( ) -> Result < Self , Box < dyn std:: error:: Error > > {
55
- log_message ( "Creating new CameraController instance" . to_string ( ) , "INFO" . to_string ( ) , "CameraController" . to_string ( ) ) ;
56
-
57
- let detector = rustface:: create_detector ( "model/seeta_fd_frontal_v1.0.bin" )
58
- . map_err ( |e| Box :: new ( e) as Box < dyn std:: error:: Error > ) ?;
59
-
60
- let detector = ThreadSafeDetector :: new ( Box :: new ( SendableDetector ( detector) ) ) ;
61
-
62
- let camera = ThreadSafeCamera :: new (
63
- CameraIndex :: Index ( 0 ) ,
64
- RequestedFormat :: new :: < RgbFormat > ( RequestedFormatType :: Exact (
65
- CameraFormat :: new_from ( 640 , 480 , FrameFormat :: MJPEG , 30 )
66
- ) )
67
- ) ?;
68
-
69
- Ok ( CameraController {
70
- camera,
71
- camera_active : Arc :: new ( Mutex :: new ( false ) ) ,
72
- face_position : Arc :: new ( Mutex :: new ( None ) ) ,
73
- selected_camera_index : Arc :: new ( Mutex :: new ( Some ( 0 ) ) ) ,
74
- detector,
75
- } )
16
+ pub fn new ( ) -> Self {
17
+ log_message ( "Creating new CameraController instance" . to_string ( ) , "INFO" . to_string ( ) , "CameraController" . to_string ( ) ) ;
18
+
19
+ CameraController {
20
+ camera : Arc :: new ( PLMutex :: new ( None ) ) ,
21
+ selected_camera_index : Arc :: new ( PLMutex :: new ( None ) ) ,
76
22
}
77
-
23
+ }
78
24
79
25
pub fn get_available_cameras ( ) -> Vec < CameraInfo > {
80
- log_message ( "Querying available cameras..." . to_string ( ) , "INFO" . to_string ( ) , "CameraController. get_available_cameras" . to_string ( ) ) ;
81
-
26
+ log_message ( "Querying available cameras..." . to_string ( ) , "INFO" . to_string ( ) , "get_available_cameras" . to_string ( ) ) ;
27
+
82
28
let backends = vec ! [ ApiBackend :: AVFoundation , ApiBackend :: Auto ] ;
83
-
84
29
for backend in backends {
85
- log_message ( format ! ( "Trying backend: {:?}" , backend) , "INFO" . to_string ( ) , "CameraController.get_available_cameras" . to_string ( ) ) ;
86
- match nokhwa:: query ( backend) {
87
- Ok ( cameras) => {
88
- log_message ( format ! ( "Found {} cameras using {:?} backend" , cameras. len( ) , backend) , "INFO" . to_string ( ) , "CameraController.get_available_cameras" . to_string ( ) ) ;
89
- for ( i, camera) in cameras. iter ( ) . enumerate ( ) {
90
- log_message ( format ! ( "Camera {}: {:?}" , i, camera) , "INFO" . to_string ( ) , "CameraController.get_available_cameras" . to_string ( ) ) ;
91
- }
92
- return cameras;
93
- } ,
94
- Err ( e) => {
95
- log_message ( format ! ( "Failed to query cameras with {:?} backend: {}" , backend, e) , "WARN" . to_string ( ) , "CameraController.get_available_cameras" . to_string ( ) ) ;
96
- }
30
+ if let Ok ( cameras) = nokhwa:: query ( backend) {
31
+ return cameras;
97
32
}
98
33
}
99
-
100
- log_message ( "No cameras found with any backend" . to_string ( ) , "ERROR" . to_string ( ) , "CameraController" . to_string ( ) ) ;
101
34
Vec :: new ( )
102
35
}
103
-
104
- pub fn select_camera ( & mut self , index : usize ) -> Result < ( ) , nokhwa:: NokhwaError > {
105
- let mut selected_camera = self . selected_camera_index . lock ( ) . unwrap ( ) ;
106
- * selected_camera = Some ( index) ;
107
- log_message ( format ! ( "Selected camera with index: {}" , index) , "INFO" . to_string ( ) , "CameraController" . to_string ( ) ) ;
108
-
109
- // Reinitialize the camera with the new index
110
- self . camera = ThreadSafeCamera :: new (
111
- CameraIndex :: Index ( index as u32 ) ,
112
- RequestedFormat :: new :: < RgbFormat > ( RequestedFormatType :: Exact (
113
- CameraFormat :: new_from ( 640 , 480 , FrameFormat :: MJPEG , 30 )
114
- ) )
115
- ) ?;
116
-
117
- Ok ( ( ) )
118
- }
119
-
120
- pub async fn toggle_camera ( & mut self , active : bool ) -> Result < ( ) > {
121
- {
122
- let mut camera_active = self . camera_active . lock ( ) . unwrap ( ) ;
123
- * camera_active = active;
124
- }
125
- log_message ( format ! ( "Camera toggled to {}" , active) , "INFO" . to_string ( ) , "CameraController.toggle_camera" . to_string ( ) ) ;
126
-
127
- if active {
128
- self . run ( ) . await ;
129
- }
130
- }
131
-
132
- pub fn get_face_position ( & self ) -> Option < ( f64 , f64 ) > {
133
- let face_position = self . face_position . lock ( ) . unwrap ( ) ;
134
- * face_position
135
- }
136
-
137
- pub async fn run ( & self ) {
138
- log_message ( "Starting camera controller" . to_string ( ) , "INFO" . to_string ( ) , "CameraController.run" . to_string ( ) ) ;
139
-
140
- if let Err ( e) = self . camera . open_stream ( ) {
141
- log_message ( format ! ( "Failed to open camera stream: {}" , e) , "ERROR" . to_string ( ) , "CameraController.run" . to_string ( ) ) ;
142
- return ;
143
- }
144
-
145
- let mut interval = interval ( Duration :: from_millis ( 33 ) ) ; // ~30 fps
146
-
147
- loop {
148
- interval. tick ( ) . await ;
149
-
150
- if !* self . camera_active . lock ( ) . unwrap ( ) {
151
- continue ;
152
- }
153
-
154
- let frame = match self . camera . frame ( ) {
155
- Ok ( f) => f,
156
- Err ( e) => {
157
- log_message ( format ! ( "Failed to capture frame: {}" , e) , "ERROR" . to_string ( ) , "CameraController.run" . to_string ( ) ) ;
158
- continue ;
159
- }
160
- } ;
161
-
162
- let image = frame. buffer ( ) ;
163
- let width = frame. resolution ( ) . width ( ) as i32 ;
164
- let height = frame. resolution ( ) . height ( ) as i32 ;
165
- let image_data = ImageData :: new ( image, width as u32 , height as u32 ) ;
166
-
167
- if let Some ( face) = self . detector . detect ( & image_data) . into_iter ( ) . next ( ) {
168
- let center_x = ( face. bbox ( ) . x ( ) + face. bbox ( ) . width ( ) as i32 / 2 ) as f64 / width as f64 ;
169
- let center_y = ( face. bbox ( ) . y ( ) + face. bbox ( ) . height ( ) as i32 / 2 ) as f64 / height as f64 ;
170
-
171
- let mut face_position = self . face_position . lock ( ) . unwrap ( ) ;
172
- * face_position = Some ( ( center_x, center_y) ) ;
173
- log_message ( format ! ( "Face detected at position: ({:.2}, {:.2})" , center_x, center_y) , "INFO" . to_string ( ) , "CameraController.run" . to_string ( ) ) ;
174
- } else {
175
- let mut face_position = self . face_position . lock ( ) . unwrap ( ) ;
176
- if face_position. is_some ( ) {
177
- * face_position = None ;
178
- log_message ( "Face lost" . to_string ( ) , "INFO" . to_string ( ) , "CameraController.run" . to_string ( ) ) ;
179
- }
180
- }
181
- }
182
- }
183
- }
184
-
185
- impl Clone for CameraController {
186
- fn clone ( & self ) -> Self {
187
- CameraController {
188
- camera : ThreadSafeCamera ( Arc :: clone ( & self . camera . 0 ) ) ,
189
- camera_active : Arc :: clone ( & self . camera_active ) ,
190
- face_position : Arc :: clone ( & self . face_position ) ,
191
- selected_camera_index : Arc :: clone ( & self . selected_camera_index ) ,
192
- detector : ThreadSafeDetector ( Arc :: clone ( & self . detector . 0 ) ) ,
193
- }
194
- }
195
- }
196
-
197
-
198
- struct SendableDetector ( Box < dyn Detector > ) ;
199
-
200
- impl Detector for SendableDetector {
201
- fn detect ( & mut self , image : & ImageData ) -> Vec < FaceInfo > {
202
- self . 0 . detect ( image)
203
- }
204
-
205
- fn set_window_size ( & mut self , size : u32 ) {
206
- self . 0 . set_window_size ( size)
207
- }
208
-
209
- fn set_slide_window_step ( & mut self , step_x : u32 , step_y : u32 ) {
210
- self . 0 . set_slide_window_step ( step_x, step_y)
211
- }
212
-
213
- fn set_min_face_size ( & mut self , size : u32 ) {
214
- self . 0 . set_min_face_size ( size)
215
- }
216
-
217
- fn set_max_face_size ( & mut self , size : u32 ) {
218
- self . 0 . set_max_face_size ( size)
219
- }
220
-
221
- fn set_pyramid_scale_factor ( & mut self , factor : f32 ) {
222
- self . 0 . set_pyramid_scale_factor ( factor)
223
- }
224
-
225
- fn set_score_thresh ( & mut self , thresh : f64 ) {
226
- self . 0 . set_score_thresh ( thresh)
227
- }
228
- }
229
-
230
- unsafe impl Send for SendableDetector { }
36
+ }
0 commit comments