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
|
use anyhow::{anyhow, Result};
use jellymatroska::{
block::Block,
unflatten::{Unflat, Unflatten},
MatroskaTag,
};
use log::{debug, trace, warn};
use std::collections::VecDeque;
pub struct AbsoluteBlock {
pub pts_base: u64,
pub inner: Block,
}
pub struct SegmentExtractIter<'a> {
segment: Unflatten<'a>,
extract: u64,
emission_queue: VecDeque<AbsoluteBlock>,
}
impl AbsoluteBlock {
pub fn pts(&self) -> u64 {
self.inner.timestamp_off as u64 + self.pts_base
}
}
impl<'a> SegmentExtractIter<'a> {
pub fn new(segment: Unflatten<'a>, extract: u64) -> Self {
Self {
segment,
extract,
emission_queue: Default::default(),
}
}
pub fn next(&mut self) -> Result<AbsoluteBlock> {
loop {
if let Some(b) = self.emission_queue.pop_front() {
break Ok(b);
}
self.read()?;
}
}
pub fn read(&mut self) -> Result<()> {
let Unflat { children, item } = self.segment.n().ok_or(anyhow!("eof"))??;
let mut pts_base = 0;
match item {
MatroskaTag::SeekHead(_) => {}
MatroskaTag::Info(_) => {}
MatroskaTag::Cluster(_) => {
let mut children = children.unwrap();
while let Some(Ok(Unflat { children, item })) = children.n() {
match item {
MatroskaTag::Crc32(_) => (),
MatroskaTag::Timestamp(ts) => {
trace!("read pts={ts}");
pts_base = ts;
}
MatroskaTag::BlockGroup(_) => {
trace!("group");
let mut children = children.unwrap();
// let mut duration = None;
let mut block = None;
while let Some(Ok(Unflat { children: _, item })) = children.n() {
match item {
MatroskaTag::Block(buf) => block = Some(buf),
// MatroskaTag::BlockDuration(v) => duration = Some(v),
_ => debug!("ignored {item:?}"),
}
}
// TODO duration
let block = Block::parse(&block.unwrap())?;
if block.track == self.extract {
trace!("block: track={} tso={}", block.track, block.timestamp_off);
self.emission_queue.push_back(AbsoluteBlock {
pts_base,
inner: block,
});
}
}
MatroskaTag::SimpleBlock(buf) => {
let block = Block::parse(&buf)?;
if block.track == self.extract {
trace!("block: track={} tso={}", block.track, block.timestamp_off);
self.emission_queue.push_back(AbsoluteBlock {
pts_base,
inner: block,
});
}
}
_ => warn!("(rsc) tag ignored: {item:?}"),
}
}
}
MatroskaTag::Tags(_) => {}
MatroskaTag::Cues(_) => {}
MatroskaTag::Chapters(_) => {}
MatroskaTag::Tracks(_) => {}
MatroskaTag::Void(_) => {}
_ => debug!("(rs) tag ignored: {item:?}"),
}
Ok(())
}
}
|