1#![forbid(unsafe_code)]
11
12use std::collections::{HashMap, VecDeque};
13
14use bytes::Bytes;
15use smallvec::SmallVec;
16
17use crate::error::Error;
18use crate::packet::{PACKET_LEN, parse_ts_packet};
19use crate::pes::parse_pes_header;
20use crate::psi::{parse_pat_section, parse_pmt_section};
21use crate::types::{AccessUnit, ElementaryStream};
22
23const PAT_PID: u16 = 0;
24
25#[derive(Debug, Default)]
26struct PesAccumulator {
27 data: Vec<u8>,
28 random_access: bool,
29}
30
31#[derive(Debug, Default)]
34pub struct Demuxer {
35 buf: Vec<u8>,
36 pmt_pid: Option<u16>,
37 streams: SmallVec<[ElementaryStream; 4]>,
38 accumulators: HashMap<u16, PesAccumulator>,
39 pending: VecDeque<AccessUnit>,
40}
41
42impl Demuxer {
43 #[must_use]
45 pub fn new() -> Self {
46 Self::default()
47 }
48
49 pub fn push_bytes(&mut self, data: &[u8]) {
51 self.buf.extend_from_slice(data);
52 }
53
54 #[must_use]
56 pub fn streams(&self) -> &[ElementaryStream] {
57 &self.streams
58 }
59
60 pub fn poll_access_unit(&mut self) -> Result<Option<AccessUnit>, Error> {
68 loop {
69 if let Some(unit) = self.pending.pop_front() {
70 return Ok(Some(unit));
71 }
72 if !self.consume_one_packet()? {
73 return Ok(None);
74 }
75 }
76 }
77
78 pub fn finish(&mut self) -> Vec<AccessUnit> {
82 let mut out = Vec::new();
83 for (pid, acc) in self.accumulators.drain() {
84 if acc.data.is_empty() {
85 continue;
86 }
87 if let Ok(unit) = finish_pes(pid, &acc) {
88 out.push(unit);
89 }
90 }
91 out
92 }
93
94 fn consume_one_packet(&mut self) -> Result<bool, Error> {
95 if self.buf.len() < PACKET_LEN {
96 return Ok(false);
97 }
98 let packet_owned = self.buf[..PACKET_LEN].to_vec();
99 let parsed = parse_ts_packet(&packet_owned)?;
100 let pid = parsed.pid;
101
102 if pid == PAT_PID {
103 if parsed.pusi {
104 let pat = parse_pat_section(parsed.payload)?;
105 self.pmt_pid = Some(pat.pmt_pid);
106 }
107 } else if Some(pid) == self.pmt_pid {
108 if parsed.pusi {
109 let pmt = parse_pmt_section(parsed.payload)?;
110 self.streams = pmt.streams;
111 }
112 } else if self.streams.iter().any(|s| s.pid == pid) {
113 self.feed_pes(pid, parsed.pusi, parsed.random_access, parsed.payload)?;
114 }
115
116 self.buf.drain(0..PACKET_LEN);
117 Ok(true)
118 }
119
120 fn feed_pes(
121 &mut self,
122 pid: u16,
123 pusi: bool,
124 random_access: bool,
125 payload: &[u8],
126 ) -> Result<(), Error> {
127 if pusi {
128 if let Some(prev) = self.accumulators.get(&pid) {
129 if !prev.data.is_empty() {
130 let unit = finish_pes(pid, prev)?;
131 self.pending.push_back(unit);
132 }
133 }
134 self.accumulators.insert(
135 pid,
136 PesAccumulator {
137 data: payload.to_vec(),
138 random_access,
139 },
140 );
141 } else if let Some(acc) = self.accumulators.get_mut(&pid) {
142 acc.data.extend_from_slice(payload);
143 }
144 Ok(())
145 }
146}
147
148fn finish_pes(pid: u16, acc: &PesAccumulator) -> Result<AccessUnit, Error> {
149 let header = parse_pes_header(&acc.data)?;
150 Ok(AccessUnit {
151 pid,
152 data: Bytes::copy_from_slice(&acc.data[header.header_len..]),
153 pts_90k: header.pts_90k,
154 dts_90k: header.dts_90k,
155 random_access: acc.random_access,
156 })
157}
158
159#[cfg(test)]
160#[path = "demux_tests.rs"]
161mod tests;