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
use std::fmt;
use crate::surface::RTFormat;
/// A FourCC code identifying a pixel format.
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
#[repr(transparent)]
pub struct PixelFormat(u32);
impl PixelFormat {
/// Planar YUV 4:2:0 standard pixel format.
///
/// All samples are 8 bits in size. The plane containing Y samples comes first, followed by a
/// plane storing packed U and V samples (with U samples in the first byte and V samples in the
/// second byte).
///
/// This format is widely supported by hardware codecs (and often the *only* supported format),
/// so it should be supported by all software, and may be used as the default format.
pub const NV12: Self = f(b"NV12");
/// Planar YUV 4:2:0 pixel format, with U and V swapped compared to `NV12`.
pub const NV21: Self = f(b"NV21");
/// Interleaved YUV 4:2:2, stored in memory as `yyyyyyyy uuuuuuuu YYYYYYYY vvvvvvvv`.
///
/// `uuuuuuuu` and `vvvvvvvv` are shared by 2 horizontally neighboring pixels.
///
/// Also known as [`YUYV`](Self::YUYV).
pub const YUY2: Self = f(b"YUY2");
/// Identical to [`YUY2`](Self::YUY2).
pub const YUYV: Self = f(b"YUYV");
/// Interleaved YUV 4:2:2, stored in memory as `uuuuuuuu yyyyyyyy vvvvvvvv YYYYYYYY`.
///
/// `uuuuuuuu` and `vvvvvvvv` are shared by 2 neighboring pixels.
pub const UYVY: Self = f(b"UVYV");
/// `RGBA`: Packed 8-bit RGBA, stored in memory as `aaaaaaaa bbbbbbbb gggggggg rrrrrrrr`.
pub const RGBA: Self = f(b"RGBA");
/// `ARGB`: Packed 8-bit RGBA, stored in memory as `bbbbbbbb gggggggg rrrrrrrr aaaaaaaa`.
pub const ARGB: Self = f(b"ARGB");
/// Packed 8-bit RGBX.
///
/// The X channel has unspecified values.
pub const RGBX: Self = f(b"RGBX");
/// Packed 8-bit BGRA.
pub const BGRA: Self = f(b"BGRA");
/// Packed 8-bit BGRX.
///
/// The X channel has unspecified values.
pub const BGRX: Self = f(b"BGRX");
pub const fn from_bytes(fourcc: [u8; 4]) -> Self {
Self(u32::from_le_bytes(fourcc))
}
pub const fn from_u32_le(fourcc: u32) -> Self {
Self(fourcc)
}
pub const fn to_bytes(self) -> [u8; 4] {
self.0.to_le_bytes()
}
pub const fn to_u32_le(self) -> u32 {
self.0
}
/// Returns a surface [`RTFormat`] compatible with this [`PixelFormat`].
///
/// Returns [`None`] when `self` is an unknown or unhandled [`PixelFormat`].
pub fn to_rtformat(self) -> Option<RTFormat> {
Some(match self {
Self::NV12 | Self::NV21 => RTFormat::YUV420,
Self::YUY2 | Self::YUYV | Self::UYVY => RTFormat::YUV422,
Self::RGBA | Self::RGBX | Self::ARGB | Self::BGRA | Self::BGRX => RTFormat::RGB32,
_ => return None,
})
}
}
const fn f(fourcc: &[u8; 4]) -> PixelFormat {
PixelFormat::from_bytes(*fourcc)
}
impl fmt::Display for PixelFormat {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let bytes = self.0.to_le_bytes();
let [a, b, c, d] = bytes.map(|b| (b as char).escape_default());
write!(f, "{}{}{}{}", a, b, c, d)
}
}
impl fmt::Debug for PixelFormat {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
<Self as fmt::Display>::fmt(self, f)
}
}