Skip to main content

moq_v4l/
framesize.rs

1use std::convert::TryFrom;
2use std::fmt;
3
4use crate::format::FourCC;
5use crate::sys::*;
6
7#[derive(Debug)]
8/// Format description as returned by [`crate::v4l2::vidioc::VIDIOC_ENUM_FRAMESIZES`]
9pub struct FrameSize {
10	pub index: u32,
11	pub fourcc: FourCC,
12	pub typ: u32,
13	pub size: FrameSizeEnum,
14}
15
16impl fmt::Display for FrameSize {
17	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
18		self.size.fmt(f)
19	}
20}
21
22#[derive(Debug)]
23pub enum FrameSizeEnum {
24	Discrete(Discrete),
25	Stepwise(Stepwise),
26}
27
28impl FrameSizeEnum {
29	pub fn to_discrete(self) -> impl IntoIterator<Item = Discrete> {
30		match self {
31			Self::Discrete(discrete) => vec![discrete],
32			Self::Stepwise(stepwise) => {
33				let mut discrete = Vec::new();
34
35				for width in (stepwise.min_width..=stepwise.max_width).step_by(stepwise.step_width as usize) {
36					for height in (stepwise.min_height..=stepwise.max_height).step_by(stepwise.step_height as usize) {
37						discrete.push(Discrete { width, height });
38					}
39				}
40
41				discrete
42			}
43		}
44	}
45}
46
47impl fmt::Display for FrameSizeEnum {
48	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
49		match self {
50			FrameSizeEnum::Discrete(val) => write!(f, "Discrete({})", val)?,
51			FrameSizeEnum::Stepwise(val) => write!(f, "Stepwise({})", val)?,
52		}
53
54		Ok(())
55	}
56}
57
58impl TryFrom<v4l2_frmsizeenum> for FrameSizeEnum {
59	type Error = String;
60
61	fn try_from(desc: v4l2_frmsizeenum) -> Result<Self, Self::Error> {
62		unsafe {
63			// Unsafe because of access to union __bindgen_anon_1
64			#[allow(non_upper_case_globals)]
65			match desc.type_ {
66				v4l2_frmsizetypes_V4L2_FRMSIZE_TYPE_DISCRETE => Ok({
67					FrameSizeEnum::Discrete(Discrete {
68						width: desc.__bindgen_anon_1.discrete.width,
69						height: desc.__bindgen_anon_1.discrete.height,
70					})
71				}),
72				v4l2_frmsizetypes_V4L2_FRMSIZE_TYPE_STEPWISE | v4l2_frmsizetypes_V4L2_FRMSIZE_TYPE_CONTINUOUS => Ok({
73					FrameSizeEnum::Stepwise(Stepwise {
74						min_width: desc.__bindgen_anon_1.stepwise.min_width,
75						max_width: desc.__bindgen_anon_1.stepwise.max_width,
76						step_width: desc.__bindgen_anon_1.stepwise.step_width,
77						min_height: desc.__bindgen_anon_1.stepwise.min_height,
78						max_height: desc.__bindgen_anon_1.stepwise.max_height,
79						step_height: desc.__bindgen_anon_1.stepwise.step_height,
80					})
81				}),
82				typ => Err(format!("Unknown frame size type: {}", typ)),
83			}
84		}
85	}
86}
87
88#[derive(Debug)]
89pub struct Discrete {
90	/// Width of the frame (in pixels).
91	pub width: u32,
92	/// Height of the frame (in pixels).
93	pub height: u32,
94}
95
96impl fmt::Display for Discrete {
97	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
98		write!(f, "{}x{}", self.width, self.height)?;
99		Ok(())
100	}
101}
102
103#[derive(Debug)]
104pub struct Stepwise {
105	/// Minimum frame width (in pixels).
106	pub min_width: u32,
107	/// Maximum frame width (in pixels).
108	pub max_width: u32,
109	/// Frame width step size (in pixels).
110	pub step_width: u32,
111	/// Minimum frame height (in pixels).
112	pub min_height: u32,
113	/// Maximum frame height (in pixels).
114	pub max_height: u32,
115	/// Frame height step size (in pixels).
116	pub step_height: u32,
117}
118
119impl fmt::Display for Stepwise {
120	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
121		write!(
122			f,
123			"{}x{} - {}x{} with step {}/{}",
124			self.min_width, self.min_height, self.max_width, self.max_height, self.step_width, self.step_height,
125		)?;
126		Ok(())
127	}
128}
129
130impl TryFrom<v4l2_frmsizeenum> for FrameSize {
131	type Error = String;
132
133	fn try_from(desc: v4l2_frmsizeenum) -> Result<Self, Self::Error> {
134		Ok(FrameSize {
135			index: desc.index,
136			typ: desc.type_,
137			fourcc: FourCC::from(desc.pixel_format),
138			size: FrameSizeEnum::try_from(desc)?,
139		})
140	}
141}