libpromeki 1.0.0-alpha
PROfessional MEdia toolKIt
 
Loading...
Searching...
No Matches
cea608.h
Go to the documentation of this file.
1
8#pragma once
9
10
11#include <promeki/config.h>
12#if PROMEKI_ENABLE_PROAV
13#include <cstdint>
14#include <promeki/color.h>
15#include <promeki/namespace.h>
16
17PROMEKI_NAMESPACE_BEGIN
18
49struct Cea608 {
50 // -- Odd parity ---------------------------------------------
51
55 static constexpr uint8_t withOddParity(uint8_t c) {
56 uint8_t v = static_cast<uint8_t>(c & 0x7F);
57 unsigned ones = 0;
58 for (int i = 0; i < 7; ++i) {
59 if (v & (1u << i)) ++ones;
60 }
61 if ((ones & 1u) == 0u) v = static_cast<uint8_t>(v | 0x80);
62 return v;
63 }
64
67 static constexpr bool checkOddParity(uint8_t c) {
68 unsigned ones = 0;
69 for (int i = 0; i < 8; ++i) {
70 if (c & (1u << i)) ++ones;
71 }
72 return (ones & 1u) != 0u;
73 }
74
76 static constexpr uint8_t stripParity(uint8_t c) { return static_cast<uint8_t>(c & 0x7F); }
77
78 // -- Channel selectors (pre-parity first-byte values) -------
79
86 static constexpr uint8_t Cc1MiscFirstByte = 0x14;
87
88 // -- Misc control codes (second-byte values) ----------------
89
90 static constexpr uint8_t MiscRCL = 0x20;
91 static constexpr uint8_t MiscBS = 0x21;
92 static constexpr uint8_t MiscDER = 0x24;
93 static constexpr uint8_t MiscRU2 = 0x25;
94 static constexpr uint8_t MiscRU3 = 0x26;
95 static constexpr uint8_t MiscRU4 = 0x27;
96 static constexpr uint8_t MiscFON = 0x28;
97 static constexpr uint8_t MiscRDC = 0x29;
98 static constexpr uint8_t MiscTR = 0x2A;
99 static constexpr uint8_t MiscRTD = 0x2B;
100 static constexpr uint8_t MiscEDM = 0x2C;
101 static constexpr uint8_t MiscCR = 0x2D;
102 static constexpr uint8_t MiscENM = 0x2E;
103 static constexpr uint8_t MiscEOC = 0x2F;
104
105 // -- Convenience: pre-parity (b1, b2) for CC1 control pairs --
106
108 static constexpr uint8_t RclB1 = Cc1MiscFirstByte;
109 static constexpr uint8_t RclB2 = MiscRCL;
110
112 static constexpr uint8_t EocB1 = Cc1MiscFirstByte;
113 static constexpr uint8_t EocB2 = MiscEOC;
114
116 static constexpr uint8_t EdmB1 = Cc1MiscFirstByte;
117 static constexpr uint8_t EdmB2 = MiscEDM;
118
120 static constexpr uint8_t EnmB1 = Cc1MiscFirstByte;
121 static constexpr uint8_t EnmB2 = MiscENM;
122
123 // -- PAC (Preamble Address Code) ----------------------------
124
131 static constexpr uint8_t PacRow15Col0WhiteB1 = 0x14;
132 static constexpr uint8_t PacRow15Col0WhiteB2 = 0x70;
133
134 // -- CEA-608 colour palette ---------------------------------
135
166 enum class CaptionColor : uint8_t {
167 White = 0,
168 Green = 1,
169 Blue = 2,
170 Cyan = 3,
171 Red = 4,
172 Yellow = 5,
173 Magenta = 6,
174 Black = 7,
175 };
176
181 static constexpr size_t CaptionColorCount = 8;
182
197 static constexpr size_t FgCaptionColorCount = 7;
198
215 static Color::List palette();
216
218 struct PacAttr {
220 int row = 15;
226 int indentCol = 0;
228 CaptionColor color = CaptionColor::White;
232 bool italic = false;
234 bool underline = false;
235 };
236
255 static void encodePac(const PacAttr &attr, uint8_t &b1, uint8_t &b2);
256
266 static bool isPac(uint8_t b1, uint8_t b2);
267
274 static bool decodePac(uint8_t b1, uint8_t b2, PacAttr &out);
275
276 // -- Mid-row codes ------------------------------------------
277
292 static void encodeMidRow(CaptionColor color, bool italic, bool underline, uint8_t &b1,
293 uint8_t &b2);
294
299 static bool isMidRow(uint8_t b1, uint8_t b2);
300
306 static bool decodeMidRow(uint8_t b1, uint8_t b2, CaptionColor &outColor, bool &outItalic,
307 bool &outUnderline);
308
309 // -- Background attribute codes -----------------------------
310 //
311 // CEA-608-B background attribute codes (EIA-608-B §7.6) live
312 // at @c b1=0x10 (CC1 channel 1) with @c b2 in @c [0x20, 0x2F].
313 // They set the background colour and opacity for subsequent
314 // characters on the row. Doubled per spec like other
315 // control codes. This is a *post-EIA-608* extension —
316 // older 608 decoders that don't recognise them treat the
317 // bytes as no-ops, so emitting them is safe.
318
332 static void encodeBgAttribute(CaptionColor color, bool semiTransparent, uint8_t &b1,
333 uint8_t &b2);
334
339 static bool isBgAttribute(uint8_t b1, uint8_t b2);
340
347 static bool decodeBgAttribute(uint8_t b1, uint8_t b2, CaptionColor &outColor,
348 bool &outSemiTransparent);
349
350 // -- Tab Offset codes (EIA-608-B §7.6) ---------------------
351 //
352 // Tab Offset codes nudge the pen position 1, 2, or 3
353 // columns to the right of where a PAC just landed it.
354 // They're the fine-grained complement to PAC's
355 // multiples-of-4 indent slots: PAC indent 8 + Tab
356 // Offset T2 places a row at column 10 (8 + 2). The
357 // encoder uses them to honour @ref SubtitleAnchor's
358 // horizontal half (Center / Right) when the cue's
359 // computed start column isn't already a multiple of 4.
360
363 static constexpr uint8_t TabOffsetB1 = 0x17;
364
368 static constexpr uint8_t TabOffsetT1 = 0x21;
369 static constexpr uint8_t TabOffsetT2 = 0x22;
370 static constexpr uint8_t TabOffsetT3 = 0x23;
371
388 static void encodeTabOffset(int columns, uint8_t &b1, uint8_t &b2);
389
394 static bool isTabOffset(uint8_t b1, uint8_t b2);
395
405 static bool decodeTabOffset(uint8_t b1, uint8_t b2, int &outColumns);
406
407 // -- Null pair (no-op filler) -------------------------------
408
414 static constexpr uint8_t NullB1 = 0x00;
415 static constexpr uint8_t NullB2 = 0x00;
416
417 // -- Predicates ---------------------------------------------
418
426 static constexpr bool isBasicChar(uint8_t c) {
427 const uint8_t v = stripParity(c);
428 return v >= 0x20 && v <= 0x7F;
429 }
430
431 Cea608() = delete;
432};
433
434PROMEKI_NAMESPACE_END
435
436#endif // PROMEKI_ENABLE_PROAV