mpeg_ps/
program_stream.rs1use alloc::vec::Vec;
10
11use dvb_common::{Parse, Serialize};
12
13use crate::pack_header::{PackHeader, PACK_START_CODE};
14use crate::system_header::{SystemHeader, SYSTEM_HEADER_START_CODE};
15use crate::Result;
16
17const PROGRAM_END_CODE: u32 = 0x0000_01B9;
19
20#[derive(Debug, Clone)]
23pub struct Pack<'a> {
24 pub pack_header: PackHeader<'a>,
26 pub system_header: Option<SystemHeader>,
28 pub pes_packets: Vec<dvb_pes::PesPacket<'a>>,
30}
31
32fn find_next_boundary(b: &[u8], from: usize) -> Option<usize> {
34 let mut i = from;
35 while i + 4 <= b.len() {
36 let word = u32::from_be_bytes([b[i], b[i + 1], b[i + 2], b[i + 3]]);
37 if word == PACK_START_CODE || word == PROGRAM_END_CODE {
38 return Some(i);
39 }
40 i += 1;
41 }
42 None
43}
44
45pub fn parse_pack(b: &[u8]) -> Result<(Option<Pack<'_>>, usize)> {
50 use crate::error::Error;
51
52 if b.len() < 4 {
53 return Err(Error::BufferTooShort {
54 need: 4,
55 have: b.len(),
56 what: "pack start_code or end_code",
57 });
58 }
59
60 let start = u32::from_be_bytes([b[0], b[1], b[2], b[3]]);
61 if start == PROGRAM_END_CODE {
62 return Ok((None, 4));
63 }
64
65 let pack_header = PackHeader::parse(b)?;
67 let hdr_len = pack_header.header_len();
68 let rest = &b[hdr_len..];
69
70 let boundary = find_next_boundary(rest, 0);
72
73 let (system_header, pes_start, _sh_len) = if rest.len() >= 4 {
75 let maybe_sh = u32::from_be_bytes([rest[0], rest[1], rest[2], rest[3]]);
76 if maybe_sh == SYSTEM_HEADER_START_CODE {
77 let sh = SystemHeader::parse(rest)?;
78 let slen = sh.serialized_len();
79 (Some(sh), slen, slen)
80 } else {
81 (None, 0, 0)
82 }
83 } else {
84 (None, 0, 0)
85 };
86
87 let pes_data = &rest[pes_start..];
88 let pes_end = boundary.map_or(pes_data.len(), |b| b - pes_start);
89
90 let (pes_packets, _pes_consumed) = parse_pes_loop(&pes_data[..pes_end])?;
92
93 let consumed = hdr_len + pes_start + _pes_consumed;
94 Ok((
95 Some(Pack {
96 pack_header,
97 system_header,
98 pes_packets,
99 }),
100 consumed,
101 ))
102}
103
104fn parse_pes_loop<'a>(data: &'a [u8]) -> Result<(Vec<dvb_pes::PesPacket<'a>>, usize)> {
105 use crate::error::Error;
106
107 let mut packets = Vec::new();
108 let mut pos = 0;
109
110 while pos + 6 <= data.len()
111 && data[pos] == 0x00
112 && data[pos + 1] == 0x00
113 && data[pos + 2] == 0x01
114 {
115 match dvb_pes::PesPacket::parse(&data[pos..]) {
116 Ok(pkt) => {
117 let pkt_len = pkt.serialized_len();
118 packets.push(pkt);
119 pos += pkt_len;
120 }
121 Err(e) => return Err(Error::Pes(e)),
122 }
123 }
124
125 Ok((packets, pos))
126}
127
128pub fn parse_all_packs(b: &[u8]) -> Result<(Vec<Pack<'_>>, &[u8])> {
132 let mut packs = Vec::new();
133 let mut remaining = b;
134 while remaining.len() >= 4 {
135 let (pack_opt, consumed) = parse_pack(remaining)?;
136 match pack_opt {
137 Some(pack) => {
138 remaining = &remaining[consumed..];
139 packs.push(pack);
140 }
141 None => {
142 remaining = &remaining[4..];
144 break;
145 }
146 }
147 }
148 Ok((packs, remaining))
149}