use std::{os::fd::AsRawFd, time::Duration};
use libc::{poll, pollfd, POLLIN};
use libcamera::{
camera_manager::CameraManager,
fence::Fence,
framebuffer::AsFrameBuffer,
framebuffer_allocator::{FrameBuffer, FrameBufferAllocator},
framebuffer_map::MemoryMappedFrameBuffer,
logging::LoggingLevel,
request::ReuseFlag,
stream::StreamRole,
};
fn main() {
let mgr = CameraManager::new().expect("manager");
let cameras = mgr.cameras();
let mut cam = cameras.iter().next().expect("no cameras").acquire().unwrap();
mgr.log_set_level("Camera", LoggingLevel::Error);
let roles_to_try = [
StreamRole::VideoRecording,
StreamRole::ViewFinder,
StreamRole::StillCapture,
];
let (mut cfgs, _role) = cam
.generate_first_supported_configuration(&roles_to_try)
.unwrap_or_else(|| {
eprintln!("No usable stream found for any role; exiting.");
std::process::exit(1);
});
cfgs.validate();
cam.configure(&mut cfgs).expect("configure");
let mut alloc = FrameBufferAllocator::new(&cam);
let stream = cfgs.get(0).and_then(|cfg| cfg.stream()).expect("stream");
let buffers = alloc.alloc(&stream).expect("alloc buffers");
println!("Allocated {} buffers", buffers.len());
let buffers = buffers
.into_iter()
.map(|buf| MemoryMappedFrameBuffer::new(buf).unwrap())
.collect::<Vec<_>>();
let mut reqs = buffers
.into_iter()
.enumerate()
.map(|(i, buf)| {
let mut req = cam.create_request(Some(i as u64)).unwrap();
req.add_buffer_with_fence(&stream, buf, None::<Fence>).unwrap();
req
})
.collect::<Vec<_>>();
let (tx, rx) = std::sync::mpsc::channel();
cam.on_request_completed(move |req| {
tx.send(req).unwrap();
});
cam.start(None).unwrap();
for req in reqs.drain(..) {
cam.queue_request(req).map_err(|(_, e)| e).unwrap();
}
for _ in 0..5 {
println!("Waiting for camera request execution");
let mut req = match rx.recv_timeout(Duration::from_secs(5)) {
Ok(r) => r,
Err(_) => {
eprintln!("Timed out waiting for a request; camera may not be delivering frames.");
break;
}
};
println!("Request {} completed", req.sequence());
let fb: &MemoryMappedFrameBuffer<FrameBuffer> = req.buffer(&stream).unwrap();
println!("Metadata: {:#?}", fb.metadata());
if let Some(fence) = fb.release_fence() {
let fence_fd = fence.into_owned_fd().expect("dup release fence");
let fd = fence_fd.as_raw_fd();
let mut pfd = [pollfd {
fd,
events: POLLIN,
revents: 0,
}];
println!("Waiting on release fence fd {}", fd);
unsafe {
let _ = poll(pfd.as_mut_ptr(), 1, 2000);
}
} else {
println!("No release fence for this buffer");
}
req.reuse(ReuseFlag::REUSE_BUFFERS);
cam.queue_request(req).map_err(|(_, e)| e).unwrap();
}
}