Skip to main content

dvb_subtitle/
lib.rs

1//! DVB subtitling (bitmap) segment parser — ETSI EN 300 743 V1.6.1.
2//!
3//! Parses the subtitling segments carried in a DVB subtitle PES data field:
4//! display-definition, page-composition, region-composition, CLUT-definition,
5//! object-data (incl. 2/4/8-bit pixel-data sub-blocks), disparity-signalling,
6//! alternative-CLUT and end-of-display-set segments. Feed it a reassembled PES
7//! payload (e.g. from `mpeg-pes`); it depends only on `broadcast-common` and is
8//! `#![no_std]` (+ `alloc`).
9//!
10//! ```
11//! use broadcast_common::Parse;
12//! use dvb_subtitle::{PesDataField, DataIdentifier, SyncByte, EndOfPesMarker};
13//!
14//! let bytes = [
15//!     DataIdentifier,               // 0x20
16//!     0x00,                         // subtitle_stream_id
17//!     SyncByte,                     // 0x0F
18//!     0x80, 0x00, 0x01, 0x00, 0x00, // end_of_display_set
19//!     EndOfPesMarker,               // 0xFF
20//! ];
21//! let field = PesDataField::parse(&bytes).unwrap();
22//! assert_eq!(field.segments.len(), 1);
23//! ```
24#![no_std]
25#![cfg_attr(docsrs, feature(doc_cfg))]
26#![warn(missing_docs)]
27// Runnable examples, embedded so they render on docs.rs and stay in sync with
28// the actual `examples/*.rs` files (shown, not compiled).
29#![doc = "\n# Examples\n"]
30#![doc = "Two runnable examples ship with this crate (`cargo run -p dvb-subtitle --example <name>`).\n"]
31#![doc = "\n## `parse_segment`\n\n```rust,ignore"]
32#![doc = include_str!("../examples/parse_segment.rs")]
33#![doc = "```\n\n## `parse_full_pes`\n\n```rust,ignore"]
34#![doc = include_str!("../examples/parse_full_pes.rs")]
35#![doc = "```"]
36
37extern crate alloc;
38
39mod any;
40mod error;
41mod pes_data_field;
42mod segments;
43mod traits;
44
45pub use any::AnySegment;
46pub use error::{Error, Result};
47pub use pes_data_field::PesDataField;
48pub use traits::SegmentDef;
49
50/// The `data_identifier` for DVB subtitle streams (0x20).
51pub use pes_data_field::DATA_IDENTIFIER as DataIdentifier;
52/// The `end_of_PES_data_field_marker` (0xFF).
53pub use pes_data_field::END_OF_PES_MARKER as EndOfPesMarker;
54/// The `subtitle_stream_id` identifying a DVB subtitle stream (0x00).
55pub use pes_data_field::SUBTITLE_STREAM_ID as SubtitleStreamId;
56/// The sync_byte prefixing each subtitling segmentation (0x0F).
57pub use pes_data_field::SYNC_BYTE as SyncByte;
58
59// Re-export segment types and enums for convenience.
60pub use segments::alternative_clut::{
61    AlternativeClutEntry, AlternativeClutSegment, ClutParameters, DynamicRangeColourGamut,
62    OutputBitDepth,
63};
64pub use segments::clut_definition::{ClutDefinitionSegment, ClutEntry};
65pub use segments::disparity_signalling::{
66    DisparityRegion, DisparityShiftInterval, DisparityShiftUpdateSequence,
67    DisparitySignallingSegment, Subregion,
68};
69pub use segments::display_definition::DisplayDefinitionSegment;
70pub use segments::end_of_display_set::EndOfDisplaySetSegment;
71pub use segments::object_data::{
72    DataType, InterlacedPixelsData, ObjectCodingMethod, ObjectDataPayload, ObjectDataSegment,
73    PixelDataSubBlock, ProgressivePixelBlock,
74};
75pub use segments::page_composition::{PageCompositionSegment, PageRegionEntry, PageState};
76pub use segments::region_composition::{
77    ObjectProviderFlag, ObjectType, RegionCompositionSegment, RegionDepth,
78    RegionLevelOfCompatibility, RegionObjectEntry,
79};
80pub use segments::stuffing::StuffingSegment;
81
82// Implement SegmentDef for each type
83impl SegmentDef<'_> for DisplayDefinitionSegment {
84    const SEGMENT_TYPE: u8 = segments::display_definition::SEGMENT_TYPE;
85    const NAME: &'static str = "DISPLAY_DEFINITION";
86}
87
88impl SegmentDef<'_> for PageCompositionSegment {
89    const SEGMENT_TYPE: u8 = segments::page_composition::SEGMENT_TYPE;
90    const NAME: &'static str = "PAGE_COMPOSITION";
91}
92
93impl SegmentDef<'_> for RegionCompositionSegment {
94    const SEGMENT_TYPE: u8 = segments::region_composition::SEGMENT_TYPE;
95    const NAME: &'static str = "REGION_COMPOSITION";
96}
97
98impl SegmentDef<'_> for ClutDefinitionSegment {
99    const SEGMENT_TYPE: u8 = segments::clut_definition::SEGMENT_TYPE;
100    const NAME: &'static str = "CLUT_DEFINITION";
101}
102
103impl<'a> SegmentDef<'a> for ObjectDataSegment<'a> {
104    const SEGMENT_TYPE: u8 = segments::object_data::SEGMENT_TYPE;
105    const NAME: &'static str = "OBJECT_DATA";
106}
107
108impl SegmentDef<'_> for EndOfDisplaySetSegment {
109    const SEGMENT_TYPE: u8 = segments::end_of_display_set::SEGMENT_TYPE;
110    const NAME: &'static str = "END_OF_DISPLAY_SET";
111}
112
113impl SegmentDef<'_> for DisparitySignallingSegment {
114    const SEGMENT_TYPE: u8 = segments::disparity_signalling::SEGMENT_TYPE;
115    const NAME: &'static str = "DISPARITY_SIGNALLING";
116}
117
118impl SegmentDef<'_> for AlternativeClutSegment {
119    const SEGMENT_TYPE: u8 = segments::alternative_clut::SEGMENT_TYPE;
120    const NAME: &'static str = "ALTERNATIVE_CLUT";
121}
122
123impl<'a> SegmentDef<'a> for StuffingSegment<'a> {
124    const SEGMENT_TYPE: u8 = segments::stuffing::SEGMENT_TYPE;
125    const NAME: &'static str = "STUFFING";
126}