oxideav_mpegts/lib.rs
1//! # oxideav-mpegts
2//!
3//! Pure-Rust, clean-room **MPEG-TS** (Transport Stream) demuxer per
4//! ISO/IEC 13818-1, scoped at the bytes Blu-ray Disc ships inside a
5//! `.m2ts` file once the BDAV TP_extra_header has been stripped (see
6//! `oxideav_bluray::iter_source_packets`).
7//!
8//! ## Surface (Phase 1)
9//!
10//! - 188-byte TS packet parser ([`packet::TsPacket`]) — sync byte,
11//! `transport_error_indicator`, `payload_unit_start_indicator`,
12//! `transport_priority`, 13-bit PID, scrambling / adaptation /
13//! payload flags, continuity counter, optional adaptation field,
14//! payload slice.
15//! - PAT (Program Association Table) parser
16//! ([`psi::ProgramAssociationTable`]) — discovers the PMT PID for
17//! each program.
18//! - PMT (Program Map Table) parser ([`psi::ProgramMapTable`]) —
19//! discovers each elementary stream's PID + `stream_type` +
20//! per-stream `descriptor` payloads.
21//! - PES packet reassembler ([`pes::PesReassembler`]) — joins TS
22//! payloads across packets per-PID, yields complete PES packets
23//! once the next start-indicator arrives or the stream ends. The
24//! resulting [`pes::PesPacket`] decodes every Table 2-17 optional
25//! header field — `PES_scrambling_control` / `PES_priority` /
26//! `data_alignment_indicator` / `copyright` / `original_or_copy` on
27//! flags1, plus the flag-gated bodies ESCR (27 MHz tick), `ES_rate`
28//! (50 bytes/s units), `DSM_trick_mode` (raw 8-bit byte),
29//! `additional_copy_info`, `previous_PES_packet_CRC`, and the full
30//! `PES_extension` body ([`pes::PesExtension`] — private data, pack
31//! header bytes, program_packet_sequence_counter, P-STD buffer,
32//! PES_extension_field_2).
33//! - Stream-type → ESID helpers in [`stream_type`] mapping the BD-
34//! relevant constants (`0x1B AVC`, `0x24 HEVC`, `0x81 AC-3`,
35//! `0x82 DTS`, `0x90 PGS`, etc.) to a richer enum.
36//! - PCR jitter and discontinuity tracking
37//! ([`clock::PcrTracker`], [`clock::ContinuityTracker`]) —
38//! per-PCR-PID 27 MHz clock recovery, instantaneous bitrate
39//! estimate, time-base discontinuity classification (signalled vs.
40//! tolerance-exceeded), plus per-PID continuity-counter
41//! classification (continuous / duplicate / no-payload /
42//! dropped / discontinuity).
43//!
44//! The crate ships **no decoders** — every payload byte stays as a
45//! `&[u8]` slice. A downstream pipeline (e.g. `oxideav-cli`'s
46//! `remux bluray:// …` path) iterates packets, drives a reassembler
47//! per PID, and hands the resulting PES payloads to a muxer.
48//!
49//! ## What's NOT in scope
50//!
51//! - PSIP / DVB SI tables beyond PAT + PMT + CAT + TSDT + SDT + EIT
52//! (no NIT, BAT, TDT/TOT yet). The SDT
53//! ([`psi::ServiceDescriptionTable`], ETSI EN 300 468 §5.2.3) is
54//! parsed including its per-service `service_descriptor` (tag `0x48`)
55//! for human-readable service / provider names. The EIT
56//! ([`psi::EventInformationTable`], §5.2.4) is parsed across all four
57//! `table_id` classifications, decoding each event's MJD/BCD
58//! `start_time`, BCD `duration`, and per-event descriptor loop — the
59//! `short_event_descriptor` (tag `0x4D`) names the event.
60//! - Conditional Access (CA) descriptors / scrambling.
61//! - Re-multiplexing — this is a demux-only crate. The MKV writer
62//! in `oxideav-mkv` owns the output side.
63
64#![deny(unsafe_code)]
65#![warn(missing_debug_implementations)]
66
67pub mod clock;
68pub mod descriptor;
69pub mod error;
70pub mod packet;
71pub mod pes;
72pub mod psi;
73pub mod stream_type;
74
75#[cfg(feature = "registry")]
76pub mod demuxer;
77#[cfg(feature = "registry")]
78pub mod muxer;
79#[cfg(feature = "registry")]
80pub mod registry;
81
82pub use clock::{
83 ContinuityEvent, ContinuityTracker, DiscontinuityReason, Pcr, PcrEvent, PcrTracker,
84 PCR_MODULUS_27MHZ, PCR_TOLERANCE_27MHZ,
85};
86pub use descriptor::{
87 iter_descriptors, parse_descriptors, AudioStreamDescriptor, AvcVideoDescriptor, CaDescriptor,
88 DataStreamAlignmentDescriptor, Descriptor, DescriptorBody, DescriptorIter, HevcVideoDescriptor,
89 Iso639Language, MaximumBitrateDescriptor, ServiceDescriptor, ShortEventDescriptor,
90 SmoothingBufferDescriptor, StdDescriptor, SystemClockDescriptor, VideoStreamDescriptor,
91};
92pub use error::TsError;
93pub use packet::{
94 iter_packets, AdaptationField, AdaptationFieldExtension, TsPacket, TsPacketIter, TS_PACKET_LEN,
95 TS_SYNC_BYTE,
96};
97pub use pes::{PStdBuffer, PesExtension, PesPacket, PesReassembler, ProgramPacketSequenceCounter};
98pub use psi::{
99 iter_sections, mpeg2_crc32, ConditionalAccessTable, EitDateTime, EitDuration, EitEvent,
100 EventInformationTable, PmtStream, ProgramAssociationTable, ProgramMapTable,
101 PsiSectionAssembler, RunningStatus, SdtService, SectionIter, ServiceDescriptionTable,
102 TransportStreamDescriptionTable, CAT_PID, CAT_TABLE_ID, EIT_ACTUAL_PF_TABLE_ID,
103 EIT_ACTUAL_SCHEDULE_FIRST, EIT_ACTUAL_SCHEDULE_LAST, EIT_OTHER_PF_TABLE_ID,
104 EIT_OTHER_SCHEDULE_FIRST, EIT_OTHER_SCHEDULE_LAST, EIT_PID, MAX_PSI_SECTION_LEN, PAT_PID,
105 PAT_TABLE_ID, PMT_TABLE_ID, SDT_ACTUAL_TABLE_ID, SDT_OTHER_TABLE_ID, SDT_PID, TSDT_PID,
106 TSDT_TABLE_ID,
107};
108pub use stream_type::StreamType;
109
110#[cfg(feature = "registry")]
111pub use demuxer::{open as open_demuxer, probe as probe_mpegts, MpegTsDemuxer};
112
113#[cfg(feature = "registry")]
114pub use muxer::{open as open_muxer, MpegTsMuxer};
115
116#[cfg(feature = "registry")]
117pub use registry::{register, register_containers};
118
119#[cfg(feature = "registry")]
120oxideav_core::register!("mpegts", register);