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