Skip to main content

v4l/
framesize.rs

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