Expand description
CEA-608/708 -> WebVTT cue conversion (issue #568).
Cite: specs/rules/webvtt-rules.md (curated W3C WebVTT §4 cue syntax +
RFC 8216 §3.5 X-TIMESTAMP-MAP), and CTA-608-E / CTA-708-E for the
caption semantics (decode owned entirely by the cc-data crate, feature
cc-data).
This module is split in two independent halves:
Cue+write_document/write_segment(always available): pure WebVTT serialization from an already-extracted cue list. No dependency oncc-data.Cea608CueExtractor/Cea708CueExtractor(featurecc-data): turn a decoded CEA-608 CC1 channel / CEA-708 service into aCuesequence by feeding one access unit’scc_data()triplets at a time, tagged with that access unit’s 33-bit PTS.TeletextCueExtractor(featureteletext): turns an EBU Teletext (ETSI EN 300 706) subtitle page into aCuesequence by feeding one access unit’sdvb_vbi::TeletextDataFields at a time. Unlike the CEA extractors, the protocol decode (Hamming-8/4 FEC, character sets, page composition) is NOT owned by the carriage crate (dvb-vbiis deliberately carriage-only — see its module docs) — it lives inteletextinstead. See that module’s docs for the full design.
§Cue-boundary detection (the key design decision)
cc-data’s decoders expose only state (channel_text() /
service_text()), not a “just committed” event. This module derives cue
boundaries by diffing that displayed text before and after each fed
frame:
- Pop-on:
channel_text()/screen()reflect only the displayed memory; while composing a caption (RCL -> PAC -> characters) writes go to the non-displayed buffer and produce no diff. The buffers swap only on EOC, so a diff-detected boundary is exactly the EOC commit event, and the next diff (typically an EDM erase, or the next EOC) is exactly the “next erase/replace” the spec notes describe. - Roll-up / paint-on: characters are written directly to the
displayed buffer, so a diff can fire on every visible change (finer
grained than “one cue per committed row”). In practice a roll-up row is
usually written in one batch before the next control code, so real
streams still produce one boundary per row; pathologically slow
per-character delivery would fragment further. Documented as a known
simplification (see
webvtt-rules.md’s 608/708 mapping notes).
§Documented losses (round-trip is NOT claimed; conversion is lossy)
- Placement: no
line/position/aligncue settings are emitted —webvtt-rules.mdallows omitting them (“otherwise omit (player defaults)”); row/column/window-anchor information from 608 PACs / 708 window geometry is dropped. - Styling: italics/underline/colour (608 mid-row/PAC attributes, 708
pen attributes) are not carried into the payload as
<i>/<u>/<c>tags; only plain decoded text is emitted. - 708 scope: only a single service’s window text (
service_text) is read; multi-window overlap ordering beyond priority, and non-service-1 services, are the caller’s choice ofservice_numberbut are not auto-merged across services. - Roll-up granularity: see cue-boundary detection above.
Modules§
- teletext
teletext - EBU Teletext (ETSI EN 300 706 V1.2.1) subtitle page decode.
Structs§
- Cea608
CueExtractor cc-data - Extracts
Cues from a single CEA-608 data channel (CTA-608-E), wrapping acc-datacc_data::decode::Cea608Decoder. - Cea708
CueExtractor cc-data - Extracts
Cues from a single CEA-708 (DTVCC) service (CTA-708-E), wrapping acc-datacc_data::decode::Cea708Decoder. - Cue
- A single extracted caption cue: display text plus its media-timeline span.
- Teletext
CueExtractor teletext - Extracts
Cues from an EBU Teletext (ETSI EN 300 706) subtitle page, featureteletext, layered ondvb-vbi’s carriage-onlydvb_vbi::TeletextDataField(ETSI EN 301 775 §4.5).
Functions§
- cue_
block - Render one cue block: the timings line (
start --> end) followed by the escaped payload lines, terminated with a single trailing newline. No cue identifier and no cue settings are emitted (first-pass simplification). - escape_
payload - Escape a cue payload line per W3C WebVTT §6.4:
&->&,<-><,>->>(order is immaterial here: this is a single left-to-right character scan, not a sequence of whole-string find-and-replace passes, so an inserted&is never re-scanned and cannot be corrupted by a later</>substitution). - format_
timestamp - Format a
MediaTimeas a WebVTT timestamphh:mm:ss.ttt(W3C WebVTT §4.3.1). Hours are always emitted: the grammar(hh:)?mm:ss.tttmakes hours optional, not forbidden, and always including them keeps this function total and monotonic without a >=1h special case. - write_
document - Render a standalone WebVTT document: the
WEBVTTsignature, a blank line, then each cue block separated by a blank line (W3C WebVTT §4). - write_
segment - Render one HLS segment of WebVTT (RFC 8216 §3.5): the
WEBVTTsignature, anX-TIMESTAMP-MAP=MPEGTS:<n>,LOCAL:00:00:00.000header mapping this segment’s local WebVTT clock to the shared MPEG-2 TS (PES) timeline, then each cue rendered with times relative tosegment_start(so cue timestamps stay small and segment-local, per the RFC 8216 convention ofLOCAL:00:00:00.000).