Skip to main content

rusty_h264_common/
types.rs

1//! Shared codec types: profiles, chroma format, and the raw YUV frame container.
2
3/// H.264 profile. The encoder targets Constrained Baseline; the rest are named
4/// for parsing/identification only.
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
6pub enum Profile {
7    /// Constrained Baseline (`profile_idc = 66` with `constraint_set1_flag`).
8    ConstrainedBaseline,
9    /// Baseline (`profile_idc = 66`).
10    Baseline,
11    /// Main (`profile_idc = 77`).
12    Main,
13    /// High (`profile_idc = 100`).
14    High,
15    /// Any other `profile_idc`.
16    Other(u8),
17}
18
19impl Profile {
20    /// The `profile_idc` byte written into the SPS.
21    pub fn profile_idc(self) -> u8 {
22        match self {
23            Profile::ConstrainedBaseline | Profile::Baseline => 66,
24            Profile::Main => 77,
25            Profile::High => 100,
26            Profile::Other(v) => v,
27        }
28    }
29}
30
31/// Chroma subsampling. The encoder supports 4:2:0 only for now.
32#[derive(Debug, Clone, Copy, PartialEq, Eq)]
33pub enum ChromaFormat {
34    /// Monochrome (`chroma_format_idc = 0`).
35    Monochrome,
36    /// 4:2:0 (`chroma_format_idc = 1`).
37    Yuv420,
38}
39
40impl ChromaFormat {
41    /// `chroma_format_idc`.
42    pub fn idc(self) -> u8 {
43        match self {
44            ChromaFormat::Monochrome => 0,
45            ChromaFormat::Yuv420 => 1,
46        }
47    }
48}
49
50/// A raw planar YUV 4:2:0 frame (8-bit). Plane strides equal their widths;
51/// chroma planes are half-resolution in each dimension.
52#[derive(Debug, Clone, PartialEq, Eq)]
53pub struct YuvFrame {
54    /// Luma width in pixels.
55    pub width: usize,
56    /// Luma height in pixels.
57    pub height: usize,
58    /// Y plane, `width * height` bytes.
59    pub y: Vec<u8>,
60    /// Cb plane, `(width/2) * (height/2)` bytes.
61    pub u: Vec<u8>,
62    /// Cr plane, `(width/2) * (height/2)` bytes.
63    pub v: Vec<u8>,
64}
65
66impl YuvFrame {
67    /// Allocates a black (Y=0, U=V=128) frame. Dimensions must be even.
68    pub fn black(width: usize, height: usize) -> Self {
69        assert!(width % 2 == 0 && height % 2 == 0, "dimensions must be even");
70        let cw = width / 2;
71        let ch = height / 2;
72        Self {
73            width,
74            height,
75            y: vec![0; width * height],
76            u: vec![128; cw * ch],
77            v: vec![128; cw * ch],
78        }
79    }
80
81    /// Chroma plane width.
82    pub fn chroma_width(&self) -> usize {
83        self.width / 2
84    }
85
86    /// Chroma plane height.
87    pub fn chroma_height(&self) -> usize {
88        self.height / 2
89    }
90
91    /// Validates plane sizes against the dimensions.
92    pub fn is_valid(&self) -> bool {
93        self.y.len() == self.width * self.height
94            && self.u.len() == self.chroma_width() * self.chroma_height()
95            && self.v.len() == self.chroma_width() * self.chroma_height()
96    }
97}