Skip to main content

pito_codecs/vp9/
mod.rs

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};