1#![allow(clippy::needless_range_loop, clippy::too_many_arguments)]
2
3pub(crate) mod bits;
4pub(crate) mod boolcoder;
5pub(crate) mod decoder;
6pub mod enc;
7pub(crate) mod error;
8pub(crate) mod frame;
9pub(crate) mod header;
10pub(crate) mod inter;
11pub(crate) mod intra;
12pub(crate) mod loopfilter;
13pub(crate) mod probs;
14#[rustfmt::skip]
15#[allow(dead_code)]
16pub(crate) mod spec_tables;
17pub(crate) mod tables;
18#[cfg(test)]
19mod tests;
20pub(crate) mod tile;
21pub(crate) mod transform;
22#[rustfmt::skip]
23#[allow(dead_code, clippy::all)]
24pub(crate) mod transform_gen;
25
26pub use error::{Error, Result};
27
28#[derive(Clone, Copy, Debug, PartialEq, Eq)]
29pub struct KeyframeInfo {
30 pub profile: u8,
31 pub width: u32,
32 pub height: u32,
33 pub render_width: u32,
34 pub render_height: u32,
35 pub bit_depth: u32,
36 pub subsampling_x: bool,
37 pub subsampling_y: bool,
38 pub color: ColorInfo,
39}
40
41pub fn keyframe_info(chunk: &[u8]) -> Option<KeyframeInfo> {
42 let first = header::split_superframe(chunk)
43 .into_iter()
44 .find(|f| !f.is_empty())?;
45 let mut st = header::HeaderState::default();
46 let h = header::parse_uncompressed(first, &mut st, &[None; 8]).ok()?;
47 if h.show_existing_frame || h.frame_type != header::KEY_FRAME {
48 return None;
49 }
50 Some(KeyframeInfo {
51 profile: h.profile,
52 width: h.width,
53 height: h.height,
54 render_width: h.render_width,
55 render_height: h.render_height,
56 bit_depth: h.color.bit_depth as u32,
57 subsampling_x: h.color.subsampling_x,
58 subsampling_y: h.color.subsampling_y,
59 color: ColorInfo {
60 color_space: h.color.color_space,
61 full_range: h.color.color_range,
62 },
63 })
64}
65
66pub fn is_keyframe(chunk: &[u8]) -> bool {
67 keyframe_info(chunk).is_some()
68}
69
70#[derive(Clone, Copy, Debug, PartialEq, Eq)]
71pub struct ColorInfo {
72 pub color_space: u8,
73 pub full_range: bool,
74}
75
76#[derive(Clone, Debug, PartialEq, Eq)]
77pub enum Plane {
78 U8(Vec<u8>),
79 U16(Vec<u16>),
80}
81
82impl Plane {
83 pub fn len(&self) -> usize {
84 match self {
85 Plane::U8(v) => v.len(),
86 Plane::U16(v) => v.len(),
87 }
88 }
89 pub fn is_empty(&self) -> bool {
90 self.len() == 0
91 }
92 pub fn as_u8(&self) -> Option<&[u8]> {
93 match self {
94 Plane::U8(v) => Some(v),
95 Plane::U16(_) => None,
96 }
97 }
98 pub fn as_u16(&self) -> Option<&[u16]> {
99 match self {
100 Plane::U8(_) => None,
101 Plane::U16(v) => Some(v),
102 }
103 }
104 pub fn get(&self, i: usize) -> u16 {
105 match self {
106 Plane::U8(v) => v[i] as u16,
107 Plane::U16(v) => v[i],
108 }
109 }
110 pub fn to_le_bytes(&self) -> Vec<u8> {
111 match self {
112 Plane::U8(v) => v.clone(),
113 Plane::U16(v) => v.iter().flat_map(|s| s.to_le_bytes()).collect(),
114 }
115 }
116}
117
118#[derive(Clone, Debug)]
119pub struct Picture {
120 pub width: u32,
121 pub height: u32,
122 pub chroma_width: u32,
123 pub chroma_height: u32,
124 pub bit_depth: u32,
125 pub subsampling_x: bool,
126 pub subsampling_y: bool,
127 pub y: Plane,
128 pub u: Plane,
129 pub v: Plane,
130 pub y_stride: usize,
131 pub uv_stride: usize,
132 pub pts: i64,
133 pub key: bool,
134 pub intra_only: bool,
135 pub color: ColorInfo,
136 pub render_width: u32,
137 pub render_height: u32,
138 pub draft: bool,
139}
140
141pub use decoder::{DecodeStats, Decoder};
142pub use enc::{Encoder, EncoderConfig, Rate};