dvb_stream/resync.rs
1//! TS byte-stream resynchronisation helpers for `dvb-stream`.
2//!
3//! Thin wrappers over [`mpeg_ts::resync::TsResync`] — the shared stateful
4//! resynchroniser lives in `mpeg-ts` (feature `ts`). This module keeps
5//! the public surface that `section_stream` and `t2mi_stream` use (the
6//! stateless `resync` + `aligned_packets` pair and the size/sync constants).
7
8pub use mpeg_ts::ts::{TS_PACKET_SIZE, TS_SYNC_BYTE};
9
10/// Find the byte offset of the first confirmed 0x47 sync byte in `buf`.
11///
12/// "Confirmed" means either `buf[offset + 188] == 0x47` (two-packet
13/// confirmation), or the buffer is too small for two packets (best-effort
14/// single-sync-byte alignment).
15///
16/// Returns `None` when `buf` contains no `0x47` byte at all.
17///
18/// This is a stateless best-effort helper. For a full stateful resynchroniser
19/// with 204-byte detection and per-call carry-over buffering, use
20/// [`mpeg_ts::resync::TsResync`].
21#[must_use]
22pub fn resync(buf: &[u8]) -> Option<usize> {
23 let mut i = 0;
24 while i < buf.len() {
25 if buf[i] == TS_SYNC_BYTE {
26 let next = i + TS_PACKET_SIZE;
27 if next < buf.len() {
28 if buf[next] == TS_SYNC_BYTE {
29 return Some(i);
30 }
31 // False sync: keep scanning.
32 i += 1;
33 continue;
34 }
35 // Buffer too small for two-packet confirmation; best-effort.
36 return Some(i);
37 }
38 i += 1;
39 }
40 None
41}
42
43/// Return an iterator over aligned 188-byte TS packet slices in `buf`.
44///
45/// Requires that `buf` is already aligned (i.e. `buf[0] == 0x47`). Each
46/// yielded slice is exactly [`TS_PACKET_SIZE`] bytes. Trailing bytes that do
47/// not form a complete packet are ignored.
48pub fn aligned_packets(buf: &[u8]) -> impl Iterator<Item = &[u8]> {
49 buf.chunks_exact(TS_PACKET_SIZE)
50 .filter(|pkt| pkt[0] == TS_SYNC_BYTE)
51}