1 use std::fs::File;
2
3 use nix::libc::off_t;
4
5 use nix::{
6 sys::memfd::{memfd_create, MemFdCreateFlag},
7 unistd::ftruncate,
8 };
9 use v4l2r::{memory::DmaBufHandle, Format};
10
export_dmabufs( format: &Format, nb_buffers: usize, ) -> nix::Result<Vec<Vec<DmaBufHandle<File>>>>11 pub fn export_dmabufs(
12 format: &Format,
13 nb_buffers: usize,
14 ) -> nix::Result<Vec<Vec<DmaBufHandle<File>>>> {
15 let fds: Vec<Vec<DmaBufHandle<File>>> = (0..nb_buffers)
16 .map(|_| {
17 format
18 .plane_fmt
19 .iter()
20 .map(|plane| {
21 memfd_create(c"memfd buffer", MemFdCreateFlag::MFD_ALLOW_SEALING)
22 .and_then(|fd| ftruncate(&fd, plane.sizeimage as off_t).map(|_| fd))
23 .map(|fd| DmaBufHandle::from(File::from(fd)))
24 })
25 .collect::<Result<Vec<_>, _>>()
26 })
27 .collect::<Result<Vec<_>, _>>()?;
28
29 Ok(fds)
30 }
31
32 #[cfg(test)]
33 mod tests {
34 use v4l2r::{memory::DmaBufSource, Format, PixelFormat, PlaneLayout};
35
36 use super::export_dmabufs;
37
38 #[test]
test_export_dmabufs()39 fn test_export_dmabufs() {
40 const WIDTH: u32 = 640;
41 const HEIGHT: u32 = 480;
42 const BYTES_PER_LINE: u32 = WIDTH;
43 const SIZE_IMAGE_Y: u32 = BYTES_PER_LINE * HEIGHT;
44 const SIZE_IMAGE_UV: u32 = BYTES_PER_LINE * HEIGHT / 2;
45
46 let format = Format {
47 width: WIDTH,
48 height: HEIGHT,
49 pixelformat: PixelFormat::from_fourcc(b"NV12"),
50 plane_fmt: vec![
51 PlaneLayout {
52 sizeimage: SIZE_IMAGE_Y,
53 bytesperline: BYTES_PER_LINE,
54 },
55 PlaneLayout {
56 sizeimage: SIZE_IMAGE_UV,
57 bytesperline: BYTES_PER_LINE,
58 },
59 ],
60 };
61
62 let dmabufs = export_dmabufs(&format, 4).unwrap();
63 assert_eq!(dmabufs.len(), 4);
64 for buf in dmabufs {
65 assert_eq!(buf.len(), 2);
66 assert!(buf[0].0.len() >= SIZE_IMAGE_Y as u64);
67 assert!(buf[1].0.len() >= SIZE_IMAGE_UV as u64);
68 }
69 }
70 }
71