1use std::sync::Arc;
2use std::sync::atomic::{AtomicU64, Ordering};
3use std::time::Duration;
4
5use camera_stream::device::{CameraDevice, CameraManager};
6use camera_stream::frame::{Frame, Timestamp};
7use camera_stream::stream::CameraStream;
8
9fn main() {
10 #[cfg(target_os = "macos")]
11 {
12 use camera_stream::platform::macos::device::MacosCameraManager;
13
14 let manager = MacosCameraManager::default();
15
16 let devices = manager
18 .discover_devices()
19 .expect("failed to discover devices");
20 println!("Found {} camera(s):", devices.len());
21 for (i, dev) in devices.iter().enumerate() {
22 println!(" [{}] {} (id: {})", i, dev.name(), dev.id());
23 }
24
25 if devices.is_empty() {
26 println!("No cameras found.");
27 return;
28 }
29
30 let device = manager
32 .default_device()
33 .expect("failed to get default device")
34 .expect("no default camera");
35
36 println!("\nUsing: {} ({})", device.name(), device.id());
37
38 let formats = device.supported_formats().expect("failed to get formats");
40 println!("\nSupported formats ({} total):", formats.len());
41 for (i, f) in formats.iter().take(10).enumerate() {
42 println!(
43 " [{}] {:?} {}x{} ({} frame rate range(s))",
44 i,
45 f.pixel_format,
46 f.size.width,
47 f.size.height,
48 f.frame_rate_ranges.len(),
49 );
50 for rr in &f.frame_rate_ranges {
51 println!(" {:.1}-{:.1} fps", rr.min.as_f64(), rr.max.as_f64(),);
52 }
53 }
54 if formats.len() > 10 {
55 println!(" ... and {} more", formats.len() - 10);
56 }
57
58 let config =
60 if let Some(f) = formats.first() {
61 let rate = f.frame_rate_ranges.first().map(|r| r.max).unwrap_or(
62 camera_stream::FrameRate {
63 numerator: 30000,
64 denominator: 1000,
65 },
66 );
67 camera_stream::StreamConfig {
68 pixel_format: f.pixel_format,
69 size: f.size,
70 frame_rate: rate,
71 }
72 } else {
73 println!("No supported formats found.");
74 return;
75 };
76
77 println!(
78 "\nOpening with {:?} {}x{} @ {:.1} fps",
79 config.pixel_format,
80 config.size.width,
81 config.size.height,
82 config.frame_rate.as_f64(),
83 );
84
85 let mut stream = device.open(&config).expect("failed to open stream");
86
87 let frame_count = Arc::new(AtomicU64::new(0));
88 let count_clone = frame_count.clone();
89 let target_frames: u64 = 60;
90
91 stream
92 .start(move |frame| {
93 let n = count_clone.fetch_add(1, Ordering::Relaxed) + 1;
94 let planes = frame.planes();
95 let total_bytes: usize = planes.iter().map(|p| p.data.len()).sum();
96 println!(
97 "Frame {}: {:?} {}x{} ts={:.3}s planes={} bytes={}",
98 n,
99 frame.pixel_format(),
100 frame.size().width,
101 frame.size().height,
102 frame.timestamp().as_secs_f64(),
103 planes.len(),
104 total_bytes,
105 );
106 })
107 .expect("failed to start stream");
108
109 loop {
111 std::thread::sleep(Duration::from_millis(100));
112 if frame_count.load(Ordering::Relaxed) >= target_frames {
113 break;
114 }
115 }
116
117 stream.stop().expect("failed to stop stream");
118 println!(
119 "\nDone. Captured {} frames.",
120 frame_count.load(Ordering::Relaxed)
121 );
122 }
123
124 #[cfg(not(target_os = "macos"))]
125 {
126 println!("This example only works on macOS.");
127 }
128}