1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
use bitflags::bitflags;
use std::{convert::TryFrom, fmt, mem};

use crate::v4l_sys::*;

pub mod colorspace;
pub use colorspace::Colorspace;

pub mod description;
pub use description::Description;

pub mod field;
pub use field::FieldOrder;

pub mod fourcc;
pub use fourcc::FourCC;

pub mod quantization;
pub use quantization::Quantization;

pub mod transfer;
pub use transfer::TransferFunction;

bitflags! {
    #[allow(clippy::unreadable_literal)]
    pub struct Flags : u32 {
        const PREMUL_ALPHA  = 0x00000001;
    }
}

impl From<u32> for Flags {
    fn from(flags: u32) -> Self {
        Self::from_bits_truncate(flags)
    }
}

impl From<Flags> for u32 {
    fn from(flags: Flags) -> Self {
        flags.bits()
    }
}

impl fmt::Display for Flags {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt::Debug::fmt(self, f)
    }
}

#[derive(Debug, Copy, Clone)]
/// Streaming format (single-planar)
pub struct Format {
    /// width in pixels
    pub width: u32,
    /// height in pixels
    pub height: u32,
    /// pixelformat code
    pub fourcc: FourCC,
    /// field order for interlacing
    pub field_order: FieldOrder,

    /// bytes per line
    pub stride: u32,
    /// maximum number of bytes required to store an image
    pub size: u32,

    /// flags set by the application or driver
    pub flags: Flags,

    /// supplements the pixelformat (fourcc) information
    pub colorspace: Colorspace,
    /// the way colors are mapped
    pub quantization: Quantization,
    /// the transfer function for the colorspace
    pub transfer: TransferFunction,
}

impl Format {
    /// Returns a capture format
    ///
    /// # Arguments
    ///
    /// * `width` - Width in pixels
    /// * `height` - Height in pixels
    /// * `fourcc` - Four character code (pixelformat)
    ///
    /// # Example
    ///
    /// ```
    /// use v4l::{Format, FourCC};
    /// let fmt = Format::new(640, 480, FourCC::new(b"YUYV"));
    /// ```
    pub const fn new(width: u32, height: u32, fourcc: FourCC) -> Self {
        Format {
            width,
            height,
            fourcc,
            field_order: FieldOrder::Any,
            stride: 0,
            size: 0,
            flags: Flags::empty(),
            colorspace: Colorspace::Default,
            quantization: Quantization::Default,
            transfer: TransferFunction::Default,
        }
    }
}

impl fmt::Display for Format {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        writeln!(f, "width          : {}", self.width)?;
        writeln!(f, "height         : {}", self.height)?;
        writeln!(f, "fourcc         : {}", self.fourcc)?;
        writeln!(f, "field          : {}", self.field_order)?;
        writeln!(f, "stride         : {}", self.stride)?;
        writeln!(f, "size           : {}", self.size)?;
        writeln!(f, "colorspace     : {}", self.colorspace)?;
        writeln!(f, "quantization   : {}", self.quantization)?;
        writeln!(f, "transfer       : {}", self.transfer)?;
        Ok(())
    }
}

impl From<v4l2_pix_format> for Format {
    fn from(fmt: v4l2_pix_format) -> Self {
        Self {
            width: fmt.width,
            height: fmt.height,
            fourcc: FourCC::from(fmt.pixelformat),
            field_order: FieldOrder::try_from(fmt.field).expect("Invalid field order"),
            stride: fmt.bytesperline,
            size: fmt.sizeimage,
            flags: Flags::from(fmt.flags),
            colorspace: Colorspace::try_from(fmt.colorspace).expect("Invalid colorspace"),
            quantization: Quantization::try_from(fmt.quantization).expect("Invalid quantization"),
            transfer: TransferFunction::try_from(fmt.xfer_func).expect("Invalid transfer function"),
        }
    }
}

impl From<Format> for v4l2_pix_format {
    fn from(format: Format) -> Self {
        Self {
            width: format.width,
            height: format.height,
            pixelformat: format.fourcc.into(),
            field: format.field_order as u32,
            bytesperline: format.stride,
            sizeimage: format.size,
            colorspace: format.colorspace as u32,
            flags: format.flags.into(),
            quantization: format.quantization as u32,
            xfer_func: format.transfer as u32,
            ..unsafe { mem::zeroed() }
        }
    }
}