Repository navigation
Expand file tree
/
Copy pathlib.rs
More file actions
121 lines (113 loc) · 3.79 KB
/
Copy pathlib.rs
File metadata and controls
121 lines (113 loc) · 3.79 KB
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
//! Clean-room AV1 decoder, implemented from the AV1 Bitstream & Decoding Process Specification
//! v1.0.0 with Errata 1 (AOMediaCodec/av1-spec).
//!
//! See the crate README for the conformance status of each decoding stage.
// Items used only by stages still being written (inter prediction, post filters).
#![allow(dead_code)]
#![cfg_attr(not(test), deny(clippy::unwrap_used, clippy::expect_used, clippy::panic, clippy::unimplemented, clippy::todo, clippy::unreachable))]
mod bits;
mod cdef;
mod cdf;
mod decoder;
mod frame;
mod grain;
pub mod header;
mod inter;
mod inter_info;
mod intra;
mod mvpred;
mod par;
mod postfilter;
mod restoration;
mod spec_tables;
mod state;
mod stats;
mod symbol;
mod tile;
mod transform;
pub use decoder::Decoder;
pub use header::{ColorConfig, FrameHeader, SequenceHeader};
pub use stats::{DecodeStats, Stage};
/// Decoder errors.
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
pub enum Error {
#[error("truncated AV1 data")]
Truncated,
#[error("invalid AV1 data: {0}")]
Invalid(&'static str),
#[error("unsupported AV1 feature: {0}")]
Unsupported(&'static str),
}
pub type Result<T> = std::result::Result<T, Error>;
/// A decoded (shown) frame: planar samples without row padding, `bit_depth` significant bits in
/// `u16`. Chroma planes are `((width + ssx) >> ssx) x ((height + ssy) >> ssy)`; they are empty
/// for monochrome streams.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Picture {
pub width: u32,
pub height: u32,
pub bit_depth: u8,
pub subsampling_x: u8,
pub subsampling_y: u8,
pub mono_chrome: bool,
pub planes: [Vec<u16>; 3],
pub color_primaries: u8,
pub transfer_characteristics: u8,
pub matrix_coefficients: u8,
pub full_range: bool,
/// Timestamp of the temporal unit that showed the picture ([`Decoder::decode_pts`]).
pub pts: i64,
/// Decoded in draft mode without deblocking / CDEF / loop restoration
/// ([`Decoder::set_draft`]): approximate, for reduced-resolution playback only.
pub draft: bool,
}
impl Picture {
pub fn plane_width(&self, plane: usize) -> u32 {
if plane == 0 { self.width } else { (self.width + self.subsampling_x as u32) >> self.subsampling_x }
}
pub fn plane_height(&self, plane: usize) -> u32 {
if plane == 0 { self.height } else { (self.height + self.subsampling_y as u32) >> self.subsampling_y }
}
}
/// Whether a temporal unit starts a random access point: its first frame is a shown key frame
/// (used for keyframe detection: containers may flag samples as sync that are not).
pub fn is_key_frame_unit(data: &[u8]) -> bool {
let mut pos = 0;
let mut seq_seen = false;
while pos < data.len() {
let h = data[pos];
let obu_type = (h >> 3) & 0xf;
let ext = h & 4 != 0;
let has_size = h & 2 != 0;
let mut p = pos + 1 + ext as usize;
let size = if has_size {
match bits::leb128(data.get(p..).unwrap_or(&[])) {
Ok((v, n)) => {
p += n;
v as usize
}
Err(_) => return false,
}
} else {
data.len().saturating_sub(p)
};
if p > data.len() {
return false;
}
match obu_type {
1 => seq_seen = true,
3 | 6 => {
let b = data.get(p).copied().unwrap_or(0);
// show_existing_frame = 0, frame_type = KEY_FRAME (0), show_frame = 1
let show_existing = b >> 7;
let frame_type = (b >> 5) & 3;
let show_frame = (b >> 4) & 1;
let _ = seq_seen;
return show_existing == 0 && frame_type == 0 && show_frame == 1;
}
_ => {}
}
pos = p.saturating_add(size);
}
false
}