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}