use orbbec_sdk_sys::*;
use std::ffi::CStr;
use std::process;
use std::ptr;
use std::sync::mpsc;
use std::thread;
use std::time::Instant;
unsafe fn from_c_str(ptr: *const std::os::raw::c_char) -> String {
if ptr.is_null() {
return String::from("(null)");
}
unsafe { CStr::from_ptr(ptr) }
.to_string_lossy()
.into_owned()
}
unsafe fn check_ob_error(err: *mut *mut ob_error) {
unsafe {
if !(*err).is_null() {
let msg_ptr = ob_error_get_message(*err);
let error_message = from_c_str(msg_ptr);
eprintln!("Error: {}", error_message);
ob_delete_error(*err);
process::exit(-1);
}
*err = ptr::null_mut();
}
}
struct StreamTracker {
count: u64,
last_timestamp: Instant,
}
impl StreamTracker {
fn new() -> Self {
Self {
count: 0,
last_timestamp: Instant::now(),
}
}
fn update_and_print(&mut self, frame: *mut ob_frame, name: &str, error: &mut *mut ob_error) {
unsafe {
if frame.is_null() {
return;
}
self.count += 1;
let now = Instant::now();
let duration = now.duration_since(self.last_timestamp);
if duration.as_secs_f64() >= 1.0 {
let index = ob_frame_get_index(frame, error);
check_ob_error(error);
let width = ob_video_frame_get_width(frame, error);
check_ob_error(error);
let height = ob_video_frame_get_height(frame, error);
check_ob_error(error);
let frame_rate = self.count as f64 / duration.as_secs_f64();
println!(
"{} frame index: {}, width: {}, height: {}, frame rate: {:.2}",
name, index, width, height, frame_rate
);
self.count = 0;
self.last_timestamp = now;
}
ob_delete_frame(frame, error);
check_ob_error(error);
}
}
}
unsafe fn calculate_and_print_frame_rate(
frameset: *mut ob_frame,
color_tracker: &mut StreamTracker,
depth_tracker: &mut StreamTracker,
) {
unsafe {
let mut error: *mut ob_error = ptr::null_mut();
let color_frame = ob_frameset_get_frame(frameset, OBFrameType_OB_FRAME_COLOR, &mut error);
check_ob_error(&mut error);
if !color_frame.is_null() {
color_tracker.update_and_print(color_frame, "Color", &mut error);
}
let depth_frame = ob_frameset_get_frame(frameset, OBFrameType_OB_FRAME_DEPTH, &mut error);
check_ob_error(&mut error);
if !depth_frame.is_null() {
depth_tracker.update_and_print(depth_frame, "Depth", &mut error);
}
}
}
fn main() {
unsafe {
let mut error: *mut ob_error = ptr::null_mut();
let pipe = ob_create_pipeline(&mut error);
check_ob_error(&mut error);
ob_pipeline_start(pipe, &mut error);
check_ob_error(&mut error);
println!("Streams have been started.");
println!("Press 'Enter' to stop the pipeline and exit the program.");
let (tx, rx) = mpsc::channel();
thread::spawn(move || {
let mut input = String::new();
let _ = std::io::stdin().read_line(&mut input);
let _ = tx.send(());
});
let mut color_tracker = StreamTracker::new();
let mut depth_tracker = StreamTracker::new();
loop {
if rx.try_recv().is_ok() {
println!("Stop requested...");
break;
}
let frameset = ob_pipeline_wait_for_frameset(pipe, 100, &mut error);
check_ob_error(&mut error);
if frameset.is_null() {
continue;
}
calculate_and_print_frame_rate(frameset, &mut color_tracker, &mut depth_tracker);
ob_delete_frame(frameset, &mut error);
check_ob_error(&mut error);
}
ob_delete_pipeline(pipe, &mut error);
check_ob_error(&mut error);
println!("Program exited successfully.");
}
}