#![allow(non_camel_case_types)]
#![allow(dead_code)]
use nix::{ioctl_read, ioctl_readwrite, ioctl_write_ptr};
pub const VIDEO_MAX_PLANES: usize = 8;
pub const fn fourcc(a: u8, b: u8, c: u8, d: u8) -> u32 {
(a as u32) | ((b as u32) << 8) | ((c as u32) << 16) | ((d as u32) << 24)
}
pub fn fourcc_str(v: u32) -> String {
let bytes = [v as u8, (v >> 8) as u8, (v >> 16) as u8, (v >> 24) as u8];
bytes
.iter()
.map(|&b| if b.is_ascii_graphic() { b as char } else { '?' })
.collect()
}
pub const V4L2_PIX_FMT_JPEG: u32 = fourcc(b'J', b'P', b'E', b'G');
pub const V4L2_PIX_FMT_MJPEG: u32 = fourcc(b'M', b'J', b'P', b'G');
pub const V4L2_PIX_FMT_YUV24: u32 = fourcc(b'Y', b'U', b'V', b'3');
pub const V4L2_PIX_FMT_GREY: u32 = fourcc(b'G', b'R', b'E', b'Y');
pub const V4L2_PIX_FMT_NV12: u32 = fourcc(b'N', b'V', b'1', b'2');
pub const V4L2_PIX_FMT_NV12M: u32 = fourcc(b'N', b'M', b'1', b'2');
pub const V4L2_PIX_FMT_YUYV: u32 = fourcc(b'Y', b'U', b'Y', b'V');
pub const V4L2_PIX_FMT_UYVY: u32 = fourcc(b'U', b'Y', b'V', b'Y');
pub const V4L2_PIX_FMT_YVYU: u32 = fourcc(b'Y', b'V', b'Y', b'U');
pub const V4L2_CAP_VIDEO_M2M: u32 = 0x0000_8000;
pub const V4L2_CAP_VIDEO_M2M_MPLANE: u32 = 0x0000_4000;
pub const V4L2_CAP_STREAMING: u32 = 0x0400_0000;
pub const V4L2_CAP_DEVICE_CAPS: u32 = 0x8000_0000;
pub const V4L2_BUF_TYPE_VIDEO_CAPTURE: u32 = 1;
pub const V4L2_BUF_TYPE_VIDEO_OUTPUT: u32 = 2;
pub const V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: u32 = 9;
pub const V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: u32 = 10;
pub const V4L2_MEMORY_MMAP: u32 = 1;
pub const V4L2_MEMORY_USERPTR: u32 = 2;
pub const V4L2_MEMORY_DMABUF: u32 = 4;
pub const V4L2_FIELD_NONE: u32 = 1;
pub const V4L2_COLORSPACE_JPEG: u32 = 7;
pub const V4L2_COLORSPACE_SRGB: u32 = 8;
pub const V4L2_YCBCR_ENC_601: u8 = 1;
pub const V4L2_QUANTIZATION_DEFAULT: u8 = 0;
pub const V4L2_QUANTIZATION_FULL_RANGE: u8 = 1;
pub const V4L2_EVENT_SOURCE_CHANGE: u32 = 5;
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct v4l2_capability {
pub driver: [u8; 16],
pub card: [u8; 32],
pub bus_info: [u8; 32],
pub version: u32,
pub capabilities: u32,
pub device_caps: u32,
pub reserved: [u32; 3],
}
const _: () = assert!(std::mem::size_of::<v4l2_capability>() == 104);
impl Default for v4l2_capability {
fn default() -> Self {
unsafe { std::mem::zeroed() }
}
}
impl v4l2_capability {
pub fn effective_caps(&self) -> u32 {
if self.capabilities & V4L2_CAP_DEVICE_CAPS != 0 {
self.device_caps
} else {
self.capabilities
}
}
}
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct v4l2_fmtdesc {
pub index: u32,
pub type_: u32,
pub flags: u32,
pub description: [u8; 32],
pub pixelformat: u32,
pub reserved: [u32; 4],
}
const _: () = assert!(std::mem::size_of::<v4l2_fmtdesc>() == 64);
impl Default for v4l2_fmtdesc {
fn default() -> Self {
unsafe { std::mem::zeroed() }
}
}
#[repr(C)]
#[derive(Debug, Clone, Copy, Default)]
pub struct v4l2_plane_pix_format {
pub sizeimage: u32,
pub bytesperline: u32,
pub reserved: [u16; 6],
}
const _: () = assert!(std::mem::size_of::<v4l2_plane_pix_format>() == 20);
#[repr(C)]
#[derive(Debug, Clone, Copy, Default)]
pub struct v4l2_pix_format {
pub width: u32,
pub height: u32,
pub pixelformat: u32,
pub field: u32,
pub bytesperline: u32,
pub sizeimage: u32,
pub colorspace: u32,
pub priv_: u32,
pub flags: u32,
pub ycbcr_enc: u32,
pub quantization: u32,
pub xfer_func: u32,
}
const _: () = assert!(std::mem::size_of::<v4l2_pix_format>() == 48);
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct v4l2_pix_format_mplane {
pub width: u32,
pub height: u32,
pub pixelformat: u32,
pub field: u32,
pub colorspace: u32,
pub plane_fmt: [v4l2_plane_pix_format; VIDEO_MAX_PLANES],
pub num_planes: u8,
pub flags: u8,
pub ycbcr_enc: u8,
pub quantization: u8,
pub xfer_func: u8,
pub reserved: [u8; 7],
}
const _: () = assert!(std::mem::size_of::<v4l2_pix_format_mplane>() == 192);
impl Default for v4l2_pix_format_mplane {
fn default() -> Self {
unsafe { std::mem::zeroed() }
}
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct v4l2_format {
pub type_: u32,
pub _pad: u32,
pub fmt: [u8; 200],
}
const _: () = assert!(std::mem::size_of::<v4l2_format>() == 208);
impl Default for v4l2_format {
fn default() -> Self {
Self {
type_: 0,
_pad: 0,
fmt: [0u8; 200],
}
}
}
impl v4l2_format {
pub unsafe fn pix(&mut self) -> &mut v4l2_pix_format {
&mut *(self.fmt.as_mut_ptr() as *mut v4l2_pix_format)
}
pub unsafe fn pix_mp(&mut self) -> &mut v4l2_pix_format_mplane {
&mut *(self.fmt.as_mut_ptr() as *mut v4l2_pix_format_mplane)
}
}
#[repr(C)]
#[derive(Debug, Clone, Copy, Default)]
pub struct v4l2_requestbuffers {
pub count: u32,
pub type_: u32,
pub memory: u32,
pub capabilities: u32,
pub flags: u8,
pub reserved: [u8; 3],
}
const _: () = assert!(std::mem::size_of::<v4l2_requestbuffers>() == 20);
#[repr(C)]
#[derive(Debug, Clone, Copy, Default)]
pub struct v4l2_timecode {
pub type_: u32,
pub flags: u32,
pub frames: u8,
pub seconds: u8,
pub minutes: u8,
pub hours: u8,
pub userbits: [u8; 4],
}
const _: () = assert!(std::mem::size_of::<v4l2_timecode>() == 16);
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct v4l2_plane {
pub bytesused: u32,
pub length: u32,
pub m: u64,
pub data_offset: u32,
pub reserved: [u32; 11],
}
const _: () = assert!(std::mem::size_of::<v4l2_plane>() == 64);
impl Default for v4l2_plane {
fn default() -> Self {
unsafe { std::mem::zeroed() }
}
}
impl v4l2_plane {
pub fn mem_offset(&self) -> u32 {
self.m as u32
}
pub fn set_fd(&mut self, fd: i32) {
self.m = fd as u32 as u64;
}
}
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct v4l2_buffer {
pub index: u32,
pub type_: u32,
pub bytesused: u32,
pub flags: u32,
pub field: u32,
pub timestamp: libc::timeval,
pub timecode: v4l2_timecode,
pub sequence: u32,
pub memory: u32,
pub m: u64,
pub length: u32,
pub reserved2: u32,
pub request_fd: i32,
}
const _: () = assert!(std::mem::size_of::<v4l2_buffer>() == 88);
impl Default for v4l2_buffer {
fn default() -> Self {
unsafe { std::mem::zeroed() }
}
}
impl v4l2_buffer {
pub fn set_offset(&mut self, offset: u32) {
self.m = offset as u64;
}
pub fn offset(&self) -> u32 {
self.m as u32
}
pub fn set_fd(&mut self, fd: i32) {
self.m = fd as u32 as u64;
}
pub fn set_planes(&mut self, planes: *mut v4l2_plane) {
self.m = planes as usize as u64;
}
}
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct v4l2_event {
pub type_: u32,
pub _pad: u32,
pub u: [u8; 64],
pub pending: u32,
pub sequence: u32,
pub timestamp: libc::timespec,
pub id: u32,
pub reserved: [u32; 8],
}
const _: () = assert!(std::mem::size_of::<v4l2_event>() == 136);
impl Default for v4l2_event {
fn default() -> Self {
unsafe { std::mem::zeroed() }
}
}
#[repr(C)]
#[derive(Debug, Clone, Copy, Default)]
pub struct v4l2_event_subscription {
pub type_: u32,
pub id: u32,
pub flags: u32,
pub reserved: [u32; 5],
}
const _: () = assert!(std::mem::size_of::<v4l2_event_subscription>() == 32);
ioctl_read!(
vidioc_querycap,
b'V',
0,
v4l2_capability
);
ioctl_readwrite!(
vidioc_enum_fmt,
b'V',
2,
v4l2_fmtdesc
);
ioctl_readwrite!(
vidioc_g_fmt,
b'V',
4,
v4l2_format
);
ioctl_readwrite!(
vidioc_s_fmt,
b'V',
5,
v4l2_format
);
ioctl_readwrite!(
vidioc_reqbufs,
b'V',
8,
v4l2_requestbuffers
);
ioctl_readwrite!(
vidioc_querybuf,
b'V',
9,
v4l2_buffer
);
ioctl_readwrite!(
vidioc_qbuf,
b'V',
15,
v4l2_buffer
);
ioctl_readwrite!(
vidioc_dqbuf,
b'V',
17,
v4l2_buffer
);
ioctl_write_ptr!(
vidioc_streamon,
b'V',
18,
std::os::raw::c_int
);
ioctl_write_ptr!(
vidioc_streamoff,
b'V',
19,
std::os::raw::c_int
);
ioctl_read!(
vidioc_dqevent,
b'V',
89,
v4l2_event
);
ioctl_write_ptr!(
vidioc_subscribe_event,
b'V',
90,
v4l2_event_subscription
);