12#include <QCoreApplication>
21 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
22 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
23 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
24 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
25 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
26 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
27 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
28 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
29 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
30 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
31 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
32 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
33 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
34 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
35 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
36 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
37 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
38 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
39 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
40 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
41 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
42 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
43 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
44 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
45 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
46 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
47 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
48 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
49 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
50 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
51 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
52 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
55static const std::array<const std::string, 8>
formats
57 "Full format 4:3, 576 lines",
58 "Letterbox 14:9 centre, 504 lines",
59 "Letterbox 14:9 top, 504 lines",
60 "Letterbox 16:9 centre, 430 lines",
61 "Letterbox 16:9 top, 430 lines",
62 "Letterbox > 16:9 centre",
63 "Full format 14:9 centre, 576 lines",
64 "Anamorphic 16:9, 576 lines"
67static const std::array<const std::string,4>
subtitles
70 "in active image area",
71 "out of active image area",
79 m_rbuf(new unsigned char[sizeof(
ccsubtitle)+255])
82 for (uint8_t i = 0; i < 128; i++)
111 auto then = SystemClock::now() - seconds;
112 for (
uint i = 0; i < 4; i++)
116static const std::array<const int,16>
rowdata =
118 11, -1, 1, 2, 3, 4, 12, 13,
119 14, 15, 5, 6, 7, 8, 9, 10
124 QChar(0xAE), QChar(0xB0), QChar(0xBD), QChar(0xBF),
125 QChar(0x2122), QChar(0xA2), QChar(0xA3), QChar(0x266A),
126 QChar(0xE0), QChar(
' '), QChar(0xE8), QChar(0xE2),
127 QChar(0xEA), QChar(0xEE), QChar(0xF4), QChar(0xFB)
132 QChar(0xC1), QChar(0xC9), QChar(0xD3), QChar(0xDA),
133 QChar(0xDC), QChar(0xFC), QChar(
'`'), QChar(0xA1),
134 QChar(
'*'), QChar(
'\''), QChar(0x2014), QChar(0xA9),
135 QChar(0x2120), QChar(0xB7), QChar(0x201C), QChar(0x201D),
136 QChar(0xC0), QChar(0xC2), QChar(0xC7), QChar(0xC8),
137 QChar(0xCA), QChar(0xCB), QChar(0xEB), QChar(0xCE),
138 QChar(0xCF), QChar(0xEF), QChar(0xD4), QChar(0xD9),
139 QChar(0xF9), QChar(0xDB), QChar(0xAB), QChar(0xBB)
144 QChar(0xC3), QChar(0xE3), QChar(0xCD), QChar(0xCC),
145 QChar(0xEC), QChar(0xD2), QChar(0xF2), QChar(0xD5),
146 QChar(0xF5), QChar(
'{'), QChar(
'}'), QChar(
'\\'),
147 QChar(
'^'), QChar(
'_'), QChar(0xA6), QChar(
'~'),
148 QChar(0xC4), QChar(0xE4), QChar(0xD6), QChar(0xF6),
149 QChar(0xDF), QChar(0xA5), QChar(0xA4), QChar(
'|'),
150 QChar(0xC5), QChar(0xE5), QChar(0xD8), QChar(0xF8),
151 QChar(0x250C), QChar(0x2510), QChar(0x2514), QChar(0x2518)
156 if (mode == std::numeric_limits<std::size_t>::max())
180 int newccmode = (b1 >> 3) & 1;
181 int newtxtmode =
m_txtMode[(field*2) + newccmode];
182 if ((b1 & 0x06) == 0x04)
204 m_txtMode[(field*2) + newccmode] = newtxtmode;
205 size_t mode = (field << 2) | (newtxtmode << 1) |
m_ccMode[field];
208 size_t len =
m_ccBuf[mode].length();
227 LOG(VB_VBI, LOG_INFO,
228 QString(
"cc608 preamble indent, b2=%1")
237 LOG(VB_VBI, LOG_INFO,
238 QString(
"cc608 preamble color change, b2=%1")
251 LOG(VB_VBI, LOG_DEBUG,
252 QString(
"<ATTRIBUTE %1 %2>").arg(b1).arg(b2));
262 LOG(VB_VBI, LOG_INFO,
263 QString(
"cc608 mid-row color change, b2=%1")
268 m_ccBuf[mode] += QChar(0x7000 + (b2 & 0xf));
285 m_ccBuf[mode].remove(len - 1, 1);
298 m_ccBuf[mode].remove(len - 1, 1);
306 LOG(VB_VBI, LOG_DEBUG,
307 QString(
"ccmode %1 cmd %2").arg(
m_ccMode)
308 .arg(b2, 2, 16,
'0'));
318 m_ccBuf[mode].startsWith(
"\b"))
325 m_ccBuf[mode].remove(len - 1, 1);
358 (!newtxtmode ||
m_row[mode] >= 16)))
365 if (
m_row[mode] < 16)
399 if (
m_row[mode] == 0)
490 for (
int x = 0; x < (b2 & 0x03); x++)
510 for (mode = field*4; mode < ((field*4) + 4); mode++)
524 LOG(VB_VBI, LOG_DEBUG,
"Format CC -- Duplicate");
531 int b1 = data & 0x7f;
532 int b2 = (data >> 8) & 0x7f;
534 LOG(VB_VBI, LOG_DEBUG,
535 QString(
"Format CC @%1/%2 = %3 %4, %5/%6 = '%7' '%8'")
536 .arg(tc.count()).arg(field)
537 .arg((data&0xff), 2, 16)
538 .arg((data&0xff00)>>8, 2, 16)
539 .arg(b1, 2, 16, QChar(
'0'))
540 .arg(b2, 2, 16, QChar(
'0'))
541 .arg(QChar((b1 & 0x60) ? b1 :
'_'))
542 .arg(QChar((b2 & 0x60) ? b2 :
'_')));
549 if (mode != std::numeric_limits<std::size_t>::max())
556 mode = std::numeric_limits<std::size_t>::max();
575 else if ((b1 & 0x10) && (b2 > 0x1F))
582 for (
size_t mode2 = field*4; mode2 < ((field*4) + 4); mode2++)
584 size_t len2 =
m_ccBuf[mode2].length();
608 int b1 = data & 0x7f;
609 int b2 = (data >> 8) & 0x7f;
617 ((b1 & 0x70) == 0x10))
629 std::chrono::milliseconds dup_text_fudge = 0ms;
630 std::chrono::milliseconds dup_ctrl_fudge = 0ms;
631 if (
m_badVbi[field] < 100 && b1 != 0 && b2 != 0)
633 std::chrono::milliseconds
d = tc -
m_lastTc[field];
634 if (d < 25ms || d > 42ms)
642 dup_text_fudge = -2ms;
644 dup_ctrl_fudge = 33ms - 4ms;
648 dup_text_fudge = 4ms;
649 dup_ctrl_fudge = 33ms - 4ms;
654 if ((b1 & 0x70) == 0x10)
692 for (
const auto& cp : std::as_const(cc608str))
694 int cpu = cp.unicode();
699 case 0x2120 : ret +=
"(SM)";
break;
700 case 0x2122 : ret +=
"(TM)";
break;
701 case 0x2014 : ret +=
"(--)";
break;
702 case 0x201C : ret +=
"``";
break;
703 case 0x201D : ret +=
"''";
break;
704 case 0x250C : ret +=
"|-";
break;
705 case 0x2510 : ret +=
"-|";
break;
706 case 0x2514 : ret +=
"|_";
break;
707 case 0x2518 : ret +=
"_|";
break;
708 case 0x2588 : ret +=
"[]";
break;
709 case 0x266A : ret +=
"o/~";
break;
710 case '\b' : ret +=
"\\b";
break;
712 if (cpu >= 0x7000 && cpu < 0x7000 + 0x30)
714 if (!suppress_unknown)
715 ret += QString(
"[%1]").arg(cpu, 2, 16);
717 else if (cpu <= 0x80)
719 ret += QString(cp.toLatin1());
721 else if (!suppress_unknown)
723 ret += QString(
"{%1}").arg(cpu, 2, 16);
737 tmpbuf =
m_ccBuf[mode].toUtf8();
738#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
739 len = std::min(tmpbuf.length(), 255);
741 len = std::min(tmpbuf.length(),
static_cast<qsizetype
>(255));
745 unsigned char *bp =
m_rbuf;
746 *(bp++) =
m_row[mode];
771 LOG(VB_VBI, LOG_INFO, QString(
"### %1 %2 %3 %4 %5 %6 %7 - '%8'")
774 .arg(
m_style[mode]).arg(f, 2, 16)
775 .arg(clr).arg(len, 3)
776 .arg(
ToASCII(QString::fromUtf8(tmpbuf.constData(), len),
false)));
784 case CC_CC1: stream = 0;
break;
785 case CC_CC2: stream = 1;
break;
786 case CC_CC3: stream = 2;
break;
787 case CC_CC4: stream = 3;
break;
790 m_lastSeen[stream] = std::chrono::system_clock::now();
818 if (
m_row[mode] == 0)
830 if (
m_row[mode] == 0)
883 for (
int x = 0; x < limit; x++)
905 return (c & 0x7F) >= 0x20 && (c & 0x7F) <= 0x7E;
914static int OddParity(
unsigned char c)
916 c ^= (c >> 4); c ^= (c >> 2); c ^= (c >> 1);
925static constexpr int PIL_TIME(
int day,
int mon,
int hour,
int min)
926{
return (day << 15) + (mon << 11) + (hour << 6) + min; }
930 int day = (pil >> 15);
931 int mon = (pil >> 11) & 0xF;
932 int hour = (pil >> 6 ) & 0x1F;
933 int min = pil & 0x3F;
936 LOG(VB_VBI, LOG_INFO,
" PDC: Timer-control (no PDC)");
937 else if (pil ==
PIL_TIME(0, 15, 30, 63))
938 LOG(VB_VBI, LOG_INFO,
" PDC: Recording inhibit/terminate");
939 else if (pil ==
PIL_TIME(0, 15, 29, 63))
940 LOG(VB_VBI, LOG_INFO,
" PDC: Interruption");
941 else if (pil ==
PIL_TIME(0, 15, 28, 63))
942 LOG(VB_VBI, LOG_INFO,
" PDC: Continue");
943 else if (pil ==
PIL_TIME(31, 15, 31, 63))
944 LOG(VB_VBI, LOG_INFO,
" PDC: No time");
946 LOG(VB_VBI, LOG_INFO, QString(
" PDC: %1, 200X-%2-%3 %4:%5")
947 .arg(pil).arg(mon).arg(day).arg(hour).arg(min));
965 LOG(VB_VBI, LOG_INFO, QString(
"VPS: 3-10: %1 %2 %3 %4 %5 %6 %7 %8 (\"%9\")")
966 .arg(buf[0]).arg(buf[1]).arg(buf[2]).arg(buf[3]).arg(buf[4])
967 .arg(buf[5]).arg(buf[6]).arg(buf[7]).arg(
m_vpsPrLabel.data()));
969 int pcs = buf[2] >> 6;
970 int cni = + ((buf[10] & 3) << 10)
971 + ((buf[11] & 0xC0) << 2)
972 + ((buf[8] & 0xC0) << 0)
974 int pil = ((buf[8] & 0x3F) << 14) + (buf[9] << 6) + (buf[10] >> 2);
977 LOG(VB_VBI, LOG_INFO, QString(
"CNI: %1 PCS: %2 PTY: %3 ")
978 .arg(cni).arg(pcs).arg(pty));
991 static const std::array<const int,8> kWssBits { 0, 0, 0, 1, 0, 1, 1, 1 };
994 for (
uint i = 0; i < 16; i++)
996 uint b1 = kWssBits[buf[i] & 7];
997 uint b2 = kWssBits[(buf[i] >> 3) & 7];
1003 unsigned char parity = wss & 0xf;
1004 parity ^= parity >> 2;
1005 parity ^= parity >> 1;
1007 LOG(VB_VBI, LOG_INFO,
1008 QString(
"WSS: %1; %2 mode; %3 color coding;\n\t\t\t"
1009 " %4 helper; reserved b7=%5; %6\n\t\t\t"
1010 " open subtitles: %7; %scopyright %8; copying %9")
1011 .arg(QString::fromStdString(
formats[wss & 7]),
1012 (wss & 0x0010) ?
"film" :
"camera",
1013 (wss & 0x0020) ?
"MA/CP" :
"standard",
1014 (wss & 0x0040) ?
"modulated" :
"no",
1015 (wss & 0x0080) ?
"1" :
"0",
1016 (wss & 0x0100) ?
"have TTX subtitles; " :
"",
1017 QString::fromStdString(
subtitles[(wss >> 9) & 3]),
1018 (wss & 0x0800) ?
"surround sound; " :
"",
1019 (wss & 0x1000) ?
"asserted" :
"unknown")
1021 .arg((wss & 0x2000) ?
"restricted" :
"not restricted"));
1034 for (
uint i = start; (i < buf.size()) && (i < end); i++)
1036 LOG(VB_VBI, LOG_INFO, QString(
"%1: 0x%2 -> 0x%3 %4")
1038 .arg(buf[i],2,16,QChar(
'0'))
1045 for (
uint i = start; (i < buf.size()) && (i < end); i++)
1052 LOG(VB_VBI, LOG_INFO, QString(
"XDSDecodeString: '%1'").arg(tmp));
1055 return tmp.trimmed();
1058static bool is_better(
const QString &newStr,
const QString &oldStr)
1060 if (!newStr.isEmpty() && newStr != oldStr &&
1061 (newStr != oldStr.left(newStr.length())))
1063 if (oldStr.isEmpty())
1067 return std::ranges::all_of(std::as_const(newStr),
1068 [](
auto ch){
return ch.toLatin1() >= 0x20; } );
1082 return m_xdsRating[future ? 1 : 0][i & 0x3] & 0x7;
1089 const std::array<const QString,4>
prefix {
"MPAA-",
"TV-",
"CE-",
"CF-" };
1090 const std::array<const std::array<const QString,8>,4> mainStr
1092 {
"NR",
"G",
"PG",
"PG-13",
"R",
"NC-17",
"X",
"NR" },
1093 {
"NR",
"Y",
"Y7",
"G",
"PG",
"14",
"MA",
"NR" },
1094 {
"E",
"C",
"C8+",
"G",
"PG",
"14+",
"18+",
"NR" },
1095 {
"E",
"G",
"8+",
"13+",
"16+",
"18+",
"NR",
"NR" },
1102 uint cf = future ? 1 : 0;
1133 for (
size_t i = 0; i < program_type.size(); i++)
1147 if (key ==
"ratings")
1149 if (key.startsWith(
"has_rating_"))
1151 if (key.startsWith(
"rating_"))
1154 if (key ==
"future_ratings")
1156 if (key.startsWith(
"has_future_rating_"))
1158 if (key.startsWith(
"future_rating_"))
1161 if (key ==
"programname")
1163 if (key ==
"future_programname")
1166 if (key ==
"programtype")
1168 if (key ==
"future_programtype")
1171 if (key ==
"callsign")
1173 if (key ==
"channame")
1199 LOG(VB_VBI, LOG_INFO,
1200 QString(
"XDSDecode: 0x%1 0x%2 '%3%4' xds[%5]=%6 in XDS %7")
1201 .arg(b1,2,16,QChar(
'0')).arg(b2,2,16,QChar(
'0'))
1204 .arg(field).arg(
m_xds[field])
1226 else if ((0x0 < b1) && (b1 < 0x0f))
1250 else if ((0x10 <= b1) && (b1 <= 0x1f))
1253 LOG(VB_VBI, LOG_INFO, QString(
"XDSDecode: Suspending XDS %1 on 0x%2")
1266 bool handled =
false;
1267 int xds_class = xds_buf[0];
1272 if ((xds_class == 0x01) || (xds_class == 0x03))
1274 else if (xds_class == 0x05)
1276 else if ((xds_class == 0x07) ||
1277 (xds_class == 0x09) ||
1278 (xds_class == 0x0b))
1280 else if (xds_class == 0x0d)
1286 LOG(VB_VBI, LOG_INFO, QString(
"XDS: ") +
1287 QString(
"Unhandled packet (0x%1 0x%2) sz(%3) '%4'")
1288 .arg(xds_buf[0],0,16).arg(xds_buf[1],0,16)
1289 .arg(xds_buf.size())
1299 for (
size_t i = 0; i < xds_buf.size() - 1; i++)
1302 if ((((~sum) & 0x7f) + 1) != xds_buf[xds_buf.size() - 1])
1306 LOG(VB_VBI, LOG_ERR, QString(
"XDS: failed CRC %1 of %2")
1317 const std::vector<unsigned char> &xds_buf,
bool future)
1319 bool handled =
true;
1320 int b2 = xds_buf[1];
1321 int cf = future ? 1 : 0;
1322 QString loc = future ?
"XDS: Future " :
"XDS: Current ";
1324 if ((b2 == 0x01) && (xds_buf.size() >= 6))
1326 uint min = xds_buf[2] & 0x3f;
1327 uint hour = xds_buf[3] & 0x0f;
1328 uint day = xds_buf[4] & 0x1f;
1329 uint month = xds_buf[5] & 0x0f;
1330 month = (month < 1 || month > 12) ? 0 : month;
1332 LOG(VB_VBI, LOG_INFO, loc +
1333 QString(
"Start Time %1/%2 %3:%4%5")
1334 .arg(month).arg(day).arg(hour).arg(min / 10).arg(min % 10));
1336 else if ((b2 == 0x02) && (xds_buf.size() >= 4))
1338 uint length_min = xds_buf[2] & 0x3f;
1339 uint length_hour = xds_buf[3] & 0x3f;
1340 uint length_elapsed_min = 0;
1341 uint length_elapsed_hour = 0;
1342 uint length_elapsed_secs = 0;
1343 if (xds_buf.size() > 6)
1345 length_elapsed_min = xds_buf[4] & 0x3f;
1346 length_elapsed_hour = xds_buf[5] & 0x3f;
1348 if (xds_buf.size() > 8 && xds_buf[7] == 0x40)
1349 length_elapsed_secs = xds_buf[6] & 0x3f;
1351 QString msg = QString(
"Program Length %1:%2%3 "
1352 "Time in Show %4:%5%6.%7%8")
1353 .arg(length_hour).arg(length_min / 10).arg(length_min % 10)
1354 .arg(length_elapsed_hour)
1355 .arg(length_elapsed_min / 10).arg(length_elapsed_min % 10)
1356 .arg(length_elapsed_secs / 10).arg(length_elapsed_secs % 10);
1358 LOG(VB_VBI, LOG_INFO, loc + msg);
1360 else if ((b2 == 0x03) && (xds_buf.size() >= 6))
1366 LOG(VB_VBI, LOG_INFO, loc + QString(
"Program Name: '%1'")
1370 else if ((b2 == 0x04) && (xds_buf.size() >= 6))
1372 std::vector<uint> program_type;
1373 for (
size_t i = 2; i < xds_buf.size() - 2; i++)
1375 int cur = xds_buf[i] - 0x20;
1376 if (cur >= 0 && cur < 96)
1377 program_type.push_back(cur);
1381 for (
uint i = 0; (i < program_type.size()) && unchanged; i++)
1387 LOG(VB_VBI, LOG_INFO, loc + QString(
"Program Type '%1'")
1391 else if ((b2 == 0x05) && (xds_buf.size() >= 4))
1393 uint movie_rating = xds_buf[2] & 0x7;
1394 uint rating_system = (xds_buf[2] >> 3) & 0x7;
1395 uint tv_rating = xds_buf[3] & 0x7;
1396 uint VSL = xds_buf[3] & (0x7 << 3);
1397 uint sel = VSL | rating_system;
1405 LOG(VB_VBI, LOG_INFO, loc + QString(
"VChip %1")
1416 LOG(VB_VBI, LOG_INFO, loc + QString(
"VChip %1")
1420 else if (sel == 0x13 || sel == 0x1f)
1424 else if ((rating_system & 0x3) == 1)
1429 uint f = ((xds_buf[0]<<3) & 0x80) | ((xds_buf[1]<<1) & 0x70);
1432 LOG(VB_VBI, LOG_INFO, loc + QString(
"VChip %1")
1436 else if (rating_system == 0)
1443 LOG(VB_VBI, LOG_INFO, loc + QString(
"VChip %1")
1449 LOG(VB_VBI, LOG_ERR, loc +
1450 QString(
"VChip Unhandled -- rs(%1) rating(%2:%3)")
1451 .arg(rating_system).arg(tv_rating).arg(movie_rating));
1455 else if (b2 == 0x07)
1457 else if (b2 == 0x08)
1459 else if (b2 == 0x09)
1461 else if (b2 == 0x0c)
1463 else if (b2 == 0x10 || b2 == 0x13 || b2 == 0x15 || b2 == 0x16 ||
1464 b2 == 0x91 || b2 == 0x92 || b2 == 0x94 || b2 == 0x97)
1466 else if (b2 == 0x86)
1468 else if (b2 == 0x89)
1470 else if (b2 == 0x8c)
1483 bool handled =
true;
1485 int b2 = xds_buf[1];
1486 if ((b2 == 0x01) && (xds_buf.size() >= 6))
1491 LOG(VB_VBI, LOG_INFO, QString(
"XDS: Network Name '%1'").arg(tmp));
1495 else if ((b2 == 0x02) && (xds_buf.size() >= 6))
1500 LOG(VB_VBI, LOG_INFO, QString(
"XDS: Network Call '%1'").arg(tmp));
1504 else if ((b2 == 0x04) && (xds_buf.size() >= 6))
1506 uint tsid = (xds_buf[2] << 24 | xds_buf[3] << 16 |
1507 xds_buf[4] << 8 | xds_buf[5]);
1510 LOG(VB_VBI, LOG_INFO, QString(
"XDS: TSID 0x%1").arg(tsid,0,16));
1524 xds_program_type[0] = QCoreApplication::translate(
"(Categories)",
1526 xds_program_type[1] = QCoreApplication::translate(
"(Categories)",
1528 xds_program_type[2] = QCoreApplication::translate(
"(Categories)",
1530 xds_program_type[3] = QCoreApplication::translate(
"(Categories)",
1532 xds_program_type[4] = QCoreApplication::translate(
"(Categories)",
1534 xds_program_type[5] = QCoreApplication::translate(
"(Categories)",
1536 xds_program_type[6] = QCoreApplication::translate(
"(Categories)",
1538 xds_program_type[7] = QCoreApplication::translate(
"(Categories)",
1540 xds_program_type[8] = QCoreApplication::translate(
"(Categories)",
1542 xds_program_type[9] = QCoreApplication::translate(
"(Categories)",
1544 xds_program_type[10] = QCoreApplication::translate(
"(Categories)",
1546 xds_program_type[11] = QCoreApplication::translate(
"(Categories)",
1548 xds_program_type[12] = QCoreApplication::translate(
"(Categories)",
1550 xds_program_type[13] = QCoreApplication::translate(
"(Categories)",
1552 xds_program_type[14] = QCoreApplication::translate(
"(Categories)",
1554 xds_program_type[15] = QCoreApplication::translate(
"(Categories)",
1556 xds_program_type[16] = QCoreApplication::translate(
"(Categories)",
1558 xds_program_type[17] = QCoreApplication::translate(
"(Categories)",
1560 xds_program_type[18] = QCoreApplication::translate(
"(Categories)",
1562 xds_program_type[19] = QCoreApplication::translate(
"(Categories)",
1564 xds_program_type[20] = QCoreApplication::translate(
"(Categories)",
1566 xds_program_type[21] = QCoreApplication::translate(
"(Categories)",
1568 xds_program_type[22] = QCoreApplication::translate(
"(Categories)",
1570 xds_program_type[23] = QCoreApplication::translate(
"(Categories)",
1572 xds_program_type[24] = QCoreApplication::translate(
"(Categories)",
1574 xds_program_type[25] = QCoreApplication::translate(
"(Categories)",
1576 xds_program_type[26] = QCoreApplication::translate(
"(Categories)",
1578 xds_program_type[27] = QCoreApplication::translate(
"(Categories)",
1580 xds_program_type[28] = QCoreApplication::translate(
"(Categories)",
1582 xds_program_type[29] = QCoreApplication::translate(
"(Categories)",
1584 xds_program_type[30] = QCoreApplication::translate(
"(Categories)",
1586 xds_program_type[31] = QCoreApplication::translate(
"(Categories)",
1588 xds_program_type[32] = QCoreApplication::translate(
"(Categories)",
1590 xds_program_type[33] = QCoreApplication::translate(
"(Categories)",
1592 xds_program_type[34] = QCoreApplication::translate(
"(Categories)",
1594 xds_program_type[35] = QCoreApplication::translate(
"(Categories)",
1596 xds_program_type[36] = QCoreApplication::translate(
"(Categories)",
1598 xds_program_type[37] = QCoreApplication::translate(
"(Categories)",
1600 xds_program_type[38] = QCoreApplication::translate(
"(Categories)",
1602 xds_program_type[39] = QCoreApplication::translate(
"(Categories)",
1604 xds_program_type[40] = QCoreApplication::translate(
"(Categories)",
1606 xds_program_type[41] = QCoreApplication::translate(
"(Categories)",
1608 xds_program_type[42] = QCoreApplication::translate(
"(Categories)",
1610 xds_program_type[43] = QCoreApplication::translate(
"(Categories)",
1612 xds_program_type[44] = QCoreApplication::translate(
"(Categories)",
1614 xds_program_type[45] = QCoreApplication::translate(
"(Categories)",
1616 xds_program_type[46] = QCoreApplication::translate(
"(Categories)",
1618 xds_program_type[47] = QCoreApplication::translate(
"(Categories)",
1620 xds_program_type[48] = QCoreApplication::translate(
"(Categories)",
1622 xds_program_type[49] = QCoreApplication::translate(
"(Categories)",
1624 xds_program_type[50] = QCoreApplication::translate(
"(Categories)",
1626 xds_program_type[51] = QCoreApplication::translate(
"(Categories)",
1628 xds_program_type[52] = QCoreApplication::translate(
"(Categories)",
1630 xds_program_type[53] = QCoreApplication::translate(
"(Categories)",
1632 xds_program_type[54] = QCoreApplication::translate(
"(Categories)",
1634 xds_program_type[55] = QCoreApplication::translate(
"(Categories)",
1636 xds_program_type[56] = QCoreApplication::translate(
"(Categories)",
1638 xds_program_type[57] = QCoreApplication::translate(
"(Categories)",
1640 xds_program_type[58] = QCoreApplication::translate(
"(Categories)",
1642 xds_program_type[59] = QCoreApplication::translate(
"(Categories)",
1644 xds_program_type[60] = QCoreApplication::translate(
"(Categories)",
1646 xds_program_type[61] = QCoreApplication::translate(
"(Categories)",
1648 xds_program_type[62] = QCoreApplication::translate(
"(Categories)",
1650 xds_program_type[63] = QCoreApplication::translate(
"(Categories)",
1652 xds_program_type[64] = QCoreApplication::translate(
"(Categories)",
1654 xds_program_type[65] = QCoreApplication::translate(
"(Categories)",
1656 xds_program_type[66] = QCoreApplication::translate(
"(Categories)",
1658 xds_program_type[67] = QCoreApplication::translate(
"(Categories)",
1660 xds_program_type[68] = QCoreApplication::translate(
"(Categories)",
1662 xds_program_type[69] = QCoreApplication::translate(
"(Categories)",
1664 xds_program_type[70] = QCoreApplication::translate(
"(Categories)",
1666 xds_program_type[71] = QCoreApplication::translate(
"(Categories)",
1668 xds_program_type[72] = QCoreApplication::translate(
"(Categories)",
1670 xds_program_type[73] = QCoreApplication::translate(
"(Categories)",
1672 xds_program_type[74] = QCoreApplication::translate(
"(Categories)",
1674 xds_program_type[75] = QCoreApplication::translate(
"(Categories)",
1676 xds_program_type[76] = QCoreApplication::translate(
"(Categories)",
1678 xds_program_type[77] = QCoreApplication::translate(
"(Categories)",
1680 xds_program_type[78] = QCoreApplication::translate(
"(Categories)",
1682 xds_program_type[79] = QCoreApplication::translate(
"(Categories)",
1684 xds_program_type[80] = QCoreApplication::translate(
"(Categories)",
1686 xds_program_type[81] = QCoreApplication::translate(
"(Categories)",
1688 xds_program_type[82] = QCoreApplication::translate(
"(Categories)",
1690 xds_program_type[83] = QCoreApplication::translate(
"(Categories)",
1692 xds_program_type[84] = QCoreApplication::translate(
"(Categories)",
1694 xds_program_type[85] = QCoreApplication::translate(
"(Categories)",
1696 xds_program_type[86] = QCoreApplication::translate(
"(Categories)",
1698 xds_program_type[87] = QCoreApplication::translate(
"(Categories)",
1700 xds_program_type[88] = QCoreApplication::translate(
"(Categories)",
1702 xds_program_type[89] = QCoreApplication::translate(
"(Categories)",
1704 xds_program_type[90] = QCoreApplication::translate(
"(Categories)",
1706 xds_program_type[91] = QCoreApplication::translate(
"(Categories)",
1708 xds_program_type[92] = QCoreApplication::translate(
"(Categories)",
1710 xds_program_type[93] = QCoreApplication::translate(
"(Categories)",
1712 xds_program_type[94] = QCoreApplication::translate(
"(Categories)",
1714 xds_program_type[95] = QCoreApplication::translate(
"(Categories)",
static const std::array< const uint8_t, 256 > vbi_bit_reverse
static int8_t Printable(uint8_t c)
static std::array< const int, 16 > b1_to_service
static const std::array< const QChar, 32 > extendedchar2
static const std::array< const std::string, 4 > subtitles
static const std::array< const int, 16 > rowdata
static const std::array< const QChar, 16 > specialchar
static void DumpPIL(int pil)
static void init_xds_program_type(CC608ProgramType &xds_program_type)
static const std::array< const std::string, 8 > formats
static constexpr int PIL_TIME(int day, int mon, int hour, int min)
static bool IsPrintable(uint8_t c)
static const std::array< const QChar, 32 > extendedchar3
static bool is_better(const QString &newStr, const QString &oldStr)
std::array< bool, 4 > CC608Seen
std::array< QString, 96 > CC608ProgramType
static constexpr uint8_t CC_LINE_CONT
static constexpr uint8_t CC_MODE_MASK
CC608PerFieldTc m_lastFormatTc
bool FalseDup(std::chrono::milliseconds tc, size_t field, int data)
QString GetRatingString(uint i, bool future) const
void XDSPacketParse(const std::vector< unsigned char > &xds_buf)
QString GetProgramType(bool future) const
void BufferCC(size_t mode, size_t len, int clr)
static QString ToASCII(const QString &cc608, bool suppress_unknown)
std::array< uint, 2 > m_xdsRatingSystems
size_t NewRowCC(size_t mode, size_t len)
QString GetXDS(const QString &key) const
QString XDSDecodeString(const std::vector< unsigned char > &buf, uint start, uint end) const
std::array< QString, 2 > m_xdsProgramName
void DecodeWSS(const unsigned char *buf)
CC608PerField m_lastFormatData
CC608PerMode m_resumeText
std::array< QChar, 128 > m_stdChar
void FormatControlCode(std::chrono::milliseconds tc, size_t field, int b1, int b2)
void FormatTextCode(std::chrono::milliseconds tc, size_t field, size_t mode, size_t len, int b1, int b2)
QRecursiveMutex m_xdsLock
std::array< std::array< uint, 4 >, 2 > m_xdsRating
void FormatCC(std::chrono::milliseconds tc, int code1, int code2)
bool XDSPacketParseChannel(const std::vector< unsigned char > &xds_buf)
bool XDSDecode(size_t field, int b1, int b2)
bool XDSPacketParseProgram(const std::vector< unsigned char > &xds_buf, bool future)
void DecodeVPS(const unsigned char *buf)
QChar CharCC(int code) const
std::array< QString, 8 > m_ccBuf
QString GetProgramName(bool future) const
CC608ProgramType m_xdsProgramTypeString
uint GetRatingSystems(bool future) const
CC608PerFieldTc m_lastCodeTc
void GetServices(std::chrono::seconds seconds, CC608Seen &seen) const
std::array< std::vector< unsigned char >, 7 > m_xdsBuf
void ResetCC(size_t mode)
bool XDSPacketCRC(const std::vector< unsigned char > &xds_buf)
std::array< std::vector< uint >, 2 > m_xdsProgramType
std::array< char, 20 > m_vpsLabel
CC608Decoder(CC608Input *ccr)
std::array< int, 4 > m_txtMode
std::array< SystemTime, 4 > m_lastSeen
uint GetRating(uint i, bool future) const
std::array< char, 20 > m_vpsPrLabel
CC608PerModeTc m_timeCode
void FormatCCField(std::chrono::milliseconds tc, size_t field, int data)
static const iso6937table * d
static bool VERBOSE_LEVEL_CHECK(uint64_t mask, LogLevel_t level)
#define LOG(_MASK_, _LEVEL_, _QSTRING_)