Skip to main content

dvb_stream/
lib.rs

1//! Async/tokio stream adapters for DVB SI and T2-MI processing.
2//!
3//! This crate wraps the synchronous [`dvb_si::demux::SiDemux`] and
4//! [`dvb_t2mi::pump::T2miPump`] as [`futures_core::Stream`] implementations,
5//! quarantining `tokio` and `futures-core` away from the parser crates.
6//!
7//! # Streams
8//!
9//! - [`SectionStream`] — wraps [`dvb_si::demux::SiDemux`] over any
10//!   [`tokio::io::AsyncRead`] byte source (file, TCP socket). Each item is an
11//!   owned [`dvb_si::demux::SectionEvent`] (`'static`, no borrow of the read
12//!   buffer).
13//!
14//! - [`T2miEventStream`] — wraps [`dvb_t2mi::pump::T2miPump`] over any
15//!   [`tokio::io::AsyncRead`]. Each item is an owned
16//!   [`dvb_t2mi::pump::T2miEvent`].
17//!
18//! Both streams are also constructable from a UDP multicast socket (the dominant
19//! real-world DVB transport) via the `bind_multicast` constructor when the `udp`
20//! feature is enabled.
21//!
22//! # Ownership and cancellation
23//!
24//! The adapter **owns** the read buffer and feeds bytes into the synchronous pump
25//! on each `poll_next` call. Events are buffered in a small per-packet queue and
26//! drained before the next read is attempted. There are no internal tasks or
27//! spawning; cancellation is simply dropping the stream.
28//!
29//! # 188-byte TS framing and resync
30//!
31//! The adapter reads raw bytes from the `AsyncRead` source and performs 188-byte
32//! TS packet alignment via a sync-byte (`0x47`) resync on the read buffer. The
33//! resync logic is implemented once in [`resync`] and shared by both streams.
34//!
35//! # Feature flags
36//!
37//! | Feature | Default | Description |
38//! |---------|---------|-------------|
39//! | `udp`   | on      | UDP/multicast constructors (`bind_multicast`) via `tokio::net::UdpSocket`. |
40//!
41//! # MSRV
42//!
43//! `dvb-stream` **1.86** (mirrors the workspace). This crate is versioned and
44//! released **independently** from the `dvb-si` / `dvb-t2mi` lockstep because
45//! tokio's own MSRV moves faster.
46
47// Runnable examples, embedded so they render on docs.rs and stay in sync with
48// the actual `examples/*.rs` files (shown, not compiled).
49#![doc = "\n# Examples\n"]
50#![doc = "Two runnable examples ship with this crate (`cargo run -p dvb-stream --example <name>`).\n"]
51#![doc = "\n## `count_sections`\n\n```rust,ignore"]
52#![doc = include_str!("../examples/count_sections.rs")]
53#![doc = "```\n\n## `stream_stats`\n\n```rust,ignore"]
54#![doc = include_str!("../examples/stream_stats.rs")]
55#![doc = "```"]
56
57// Drift-guard exemption (issue #806): this crate defines no `pub enum` at
58// all (only stream adapter structs and `ResyncStats` below), so neither the
59// `tests/label_coverage.rs` (#204 Display convention) nor the
60// `tests/non_exhaustive_coverage.rs` (`#[non_exhaustive]`) drift guard has
61// anything to police. Recorded in `broadcast-common`'s
62// `tests/workspace_drift_guard_coverage.rs` exemption lists.
63
64pub mod resync;
65pub mod section_stream;
66pub mod t2mi_stream;
67
68pub use section_stream::SectionStream;
69pub use t2mi_stream::T2miEventStream;
70
71/// Statistics tracking resynchronisation events and discarded bytes in a TS
72/// byte stream.
73///
74/// Returned by [`SectionStream::resync_stats`] and
75/// [`T2miEventStream::resync_stats`].
76#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
77pub struct ResyncStats {
78    /// Number of times the stream re-aligned on a new sync byte.
79    pub resyncs: u64,
80    /// Total bytes discarded due to resync alignment or mid-stream desync.
81    pub bytes_discarded: u64,
82    /// Number of mid-stream alignment losses detected (a packet whose first
83    /// byte was not `0x47`).
84    pub desyncs: u64,
85}