pub struct TeletextCueExtractor { /* private fields */ }teletext only.Expand description
Extracts Cues from an EBU Teletext (ETSI EN 300 706) subtitle page,
feature teletext, layered on dvb-vbi’s carriage-only
dvb_vbi::TeletextDataField (ETSI EN 301 775 §4.5).
dvb-vbi deliberately does not decode EN 300 706 (a large, separate spec
covering FEC, character sets, and page composition — not carriage; see its
own module docs). This crate owns that decode
(crate::webvtt::teletext): Hamming-8/4 + odd-parity FEC, the English
Latin G0 national option table, and basic Level-1 page composition
(header + rows 1-24). See crate::webvtt::teletext module docs for the
full list of documented losses (no enhancement packets, no styling, no
sub-code-based multi-page selection, only the English national option’s
character substitutions).
Tracks a single (magazine, page) — the caller supplies these (typically
known from the carrying service’s SI, e.g. a DVB VBI/teletext descriptor’s
page association). Feed every dvb_vbi::TeletextDataField carried by
one access unit at a time via push_frame, tagged with that access
unit’s raw (non-unrolled) 33-bit PTS; call finalize at end of stream.
Cue boundaries are derived the same way as the CEA extractors (see
crate::webvtt module docs): a diff on the currently-displayed text
(rows 1-24, non-empty, joined with \n) after each fed frame. A page’s
C4 (erase page) control bit clears the row buffer, which — combined with
the diff — naturally produces a cue boundary when a subtitle disappears.
use timed_metadata::webvtt::TeletextCueExtractor;
use dvb_vbi::{TeletextDataField, LineHeader, FRAMING_CODE_EBU};
// Build one page-header packet (magazine 8, page 0x88, subtitle+erase
// set) and one row-1 packet ("HI"), using the crate's own verified
// Hamming-8/4 / odd-parity encoders (see `webvtt::teletext` tests).
let mut header = [0u8; 42];
header[0] = hamming(0); // magazine field 0 -> magazine 8, row 0
header[1] = hamming(0);
header[2] = hamming(8); // page units
header[3] = hamming(8); // page tens -> page 0x88
header[5] = hamming(0b1000); // C4 erase_page
header[7] = hamming(0b1000); // C6 subtitle
for b in header.iter_mut().skip(10) { *b = parity(0x20); }
let mut row1 = [0u8; 42];
row1[0] = hamming(0 | (1 << 3)); // magazine 8, Y bit0 = 1 (row 1)
row1[1] = hamming(0); // Y bits 1..4 = 0
row1[2] = parity(b'H');
row1[3] = parity(b'I');
for b in row1.iter_mut().skip(4) { *b = parity(0x20); }
let field = |block| TeletextDataField {
header: LineHeader::new(true, 0),
framing_code: FRAMING_CODE_EBU,
txt_data_block: block,
};
let mut ex = TeletextCueExtractor::new(8, 0x88);
ex.push_frame(0, &[field(header)]);
ex.push_frame(1, &[field(row1)]);
ex.finalize(2);
assert_eq!(ex.cues().len(), 1);
assert_eq!(ex.cues()[0].text, "HI");Implementations§
Source§impl TeletextCueExtractor
impl TeletextCueExtractor
Sourcepub fn new(magazine: u8, page: u8) -> Self
pub fn new(magazine: u8, page: u8) -> Self
A new extractor tracking the given (magazine, page) (magazine
1..=8; page Pt << 4 | Pu, e.g. 0x88 for the common “page 888”
subtitle convention).
Sourcepub fn push_frame(&mut self, pts33: u64, fields: &[TeletextDataField])
pub fn push_frame(&mut self, pts33: u64, fields: &[TeletextDataField])
Feed every dvb_vbi::TeletextDataField carried by one access unit,
tagged with that access unit’s raw 33-bit PTS. Fields for other
magazines/pages are ignored.