1use std::num::NonZero;
2
3use crate::{
4 base::VInt64,
5 functional::{Decode, Encode},
6 lacer::Lacer,
7 leaf::SimpleBlock,
8 master::{BlockGroup, Cluster},
9};
10
11#[derive(Debug, Clone, PartialEq, Eq)]
14pub enum FrameData<'a> {
15 Single(&'a [u8]),
17 Multiple(Vec<&'a [u8]>),
19}
20
21impl<'a> FrameData<'a> {
22 fn single(data: &'a [u8]) -> Self {
23 FrameData::Single(data)
24 }
25 fn multiple(data: Vec<&'a [u8]>) -> Self {
26 FrameData::Multiple(data)
27 }
28}
29#[derive(Debug, Clone, PartialEq, Eq)]
31pub struct Frame<'a> {
32 pub data: FrameData<'a>,
34 pub is_keyframe: bool,
36 pub is_invisible: bool,
38 pub is_discardable: bool,
40 pub track_number: u64,
42 pub timestamp: i64,
44 pub duration: Option<NonZero<u64>>,
46}
47
48#[derive(Debug, Clone, PartialEq, Eq)]
54pub enum ClusterBlock {
55 Simple(SimpleBlock),
57 Group(BlockGroup),
59}
60impl ClusterBlock {
61 fn block_ref(&self) -> BlockRef<'_> {
62 match self {
63 ClusterBlock::Simple(b) => BlockRef::Simple(b),
64 ClusterBlock::Group(b) => BlockRef::Group(b),
65 }
66 }
67}
68impl From<SimpleBlock> for ClusterBlock {
69 fn from(b: SimpleBlock) -> Self {
70 ClusterBlock::Simple(b)
71 }
72}
73impl From<BlockGroup> for ClusterBlock {
74 fn from(b: BlockGroup) -> Self {
75 ClusterBlock::Group(b)
76 }
77}
78
79impl Encode for ClusterBlock {
80 fn encode<B: crate::functional::BufMut>(&self, buf: &mut B) -> crate::Result<()> {
81 match self {
82 ClusterBlock::Simple(b) => b.encode(buf),
83 ClusterBlock::Group(b) => b.encode(buf),
84 }
85 }
86}
87
88enum BlockRef<'a> {
89 Simple(&'a crate::leaf::SimpleBlock),
90 Group(&'a crate::master::BlockGroup),
91}
92
93impl<'a> BlockRef<'a> {
94 fn into_frame(self, cluster_ts: u64) -> crate::Result<Frame<'a>> {
96 match self {
97 BlockRef::Simple(block) => {
98 let body_buf = &mut &block[..];
99 let track_number = VInt64::decode(body_buf)?;
100 let relative_timestamp = i16::decode(body_buf)?;
101 let flag = u8::decode(body_buf)?;
102 let data = *body_buf;
103 let lacing = (flag >> 1) & 0x03;
104 Ok(Frame {
105 data: match lacing {
106 0 => FrameData::single(data),
107 0b01 => FrameData::multiple(Lacer::Xiph.delace(data)?),
108 0b11 => FrameData::multiple(Lacer::Ebml.delace(data)?),
109 _ => FrameData::multiple(Lacer::FixedSize.delace(data)?),
110 },
111 is_keyframe: (flag & 0x80) != 0,
112 is_invisible: (flag & 0x08) != 0,
113 is_discardable: (flag & 0x01) != 0,
114 track_number: *track_number,
115 timestamp: cluster_ts as i64 + relative_timestamp as i64,
116 duration: None,
117 })
118 }
119 BlockRef::Group(g) => {
120 let block = &g.block;
121 let body_buf = &mut &block[..];
122 let track_number = VInt64::decode(body_buf)?;
123 let relative_timestamp = i16::decode(body_buf)?;
124 let flag = u8::decode(body_buf)?;
125 let data = *body_buf;
126 let lacing = (flag >> 1) & 0x03;
127
128 Ok(Frame {
129 data: match lacing {
130 0 => FrameData::single(data),
131 0b01 => FrameData::multiple(Lacer::Xiph.delace(data)?),
132 0b11 => FrameData::multiple(Lacer::Ebml.delace(data)?),
133 _ => FrameData::multiple(Lacer::FixedSize.delace(data)?),
134 },
135 is_keyframe: g.reference_block.is_empty(),
136 is_invisible: flag & 0x08 != 0,
137 is_discardable: false,
138 track_number: *track_number,
139 timestamp: cluster_ts as i64 + relative_timestamp as i64,
140 duration: g.block_duration.and_then(|d| NonZero::new(*d)),
141 })
142 }
143 }
144 }
145}
146
147impl<'a> From<&'a crate::leaf::SimpleBlock> for BlockRef<'a> {
148 fn from(b: &'a crate::leaf::SimpleBlock) -> Self {
149 BlockRef::Simple(b)
150 }
151}
152impl<'a> From<&'a crate::master::BlockGroup> for BlockRef<'a> {
153 fn from(b: &'a crate::master::BlockGroup) -> Self {
154 BlockRef::Group(b)
155 }
156}
157
158impl Cluster {
159 pub fn frames(&self) -> impl Iterator<Item = crate::Result<Frame<'_>>> + '_ {
161 self.blocks
162 .iter()
163 .map(|b| b.block_ref().into_frame(*self.timestamp))
164 }
165}