11#include <QCoreApplication>
20 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
21 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
22 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
23 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
24 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
25 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
26 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
27 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
28 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
29 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
30 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
31 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
32 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
33 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
34 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
35 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
36 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
37 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
38 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
39 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
40 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
41 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
42 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
43 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
44 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
45 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
46 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
47 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
48 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
49 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
50 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
51 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
54static const std::array<const std::string, 8>
formats
56 "Full format 4:3, 576 lines",
57 "Letterbox 14:9 centre, 504 lines",
58 "Letterbox 14:9 top, 504 lines",
59 "Letterbox 16:9 centre, 430 lines",
60 "Letterbox 16:9 top, 430 lines",
61 "Letterbox > 16:9 centre",
62 "Full format 14:9 centre, 576 lines",
63 "Anamorphic 16:9, 576 lines"
66static const std::array<const std::string,4>
subtitles
69 "in active image area",
70 "out of active image area",
78 m_rbuf(new unsigned char[sizeof(
ccsubtitle)+255])
81 for (
uint i = 0; i < 128; i++)
110 auto then = SystemClock::now() - seconds;
111 for (
uint i = 0; i < 4; i++)
115static const std::array<const int,16>
rowdata =
117 11, -1, 1, 2, 3, 4, 12, 13,
118 14, 15, 5, 6, 7, 8, 9, 10
123 QLatin1Char(0xAE), QLatin1Char(0xB0), QLatin1Char(0xBD), QLatin1Char(0xBF),
124 QChar(0x2122), QLatin1Char(0xA2), QLatin1Char(0xA3), QChar(0x266A),
125 QLatin1Char(0xE0), QLatin1Char(
' '), QLatin1Char(0xE8), QLatin1Char(0xE2),
126 QLatin1Char(0xEA), QLatin1Char(0xEE), QLatin1Char(0xF4), QLatin1Char(0xFB)
131 QLatin1Char(0xC1), QLatin1Char(0xC9), QLatin1Char(0xD3), QLatin1Char(0xDA),
132 QLatin1Char(0xDC), QLatin1Char(0xFC), QLatin1Char(
'`'), QLatin1Char(0xA1),
133 QLatin1Char(
'*'), QLatin1Char(
'\''), QChar(0x2014), QLatin1Char(0xA9),
134 QChar(0x2120), QLatin1Char(0xB7), QChar(0x201C), QChar(0x201D),
135 QLatin1Char(0xC0), QLatin1Char(0xC2), QLatin1Char(0xC7), QLatin1Char(0xC8),
136 QLatin1Char(0xCA), QLatin1Char(0xCB), QLatin1Char(0xEB), QLatin1Char(0xCE),
137 QLatin1Char(0xCF), QLatin1Char(0xEF), QLatin1Char(0xD4), QLatin1Char(0xD9),
138 QLatin1Char(0xF9), QLatin1Char(0xDB), QLatin1Char(0xAB), QLatin1Char(0xBB)
143 QLatin1Char(0xC3), QLatin1Char(0xE3), QLatin1Char(0xCD), QLatin1Char(0xCC),
144 QLatin1Char(0xEC), QLatin1Char(0xD2), QLatin1Char(0xF2), QLatin1Char(0xD5),
145 QLatin1Char(0xF5), QLatin1Char(
'{'), QLatin1Char(
'}'), QLatin1Char(
'\\'),
146 QLatin1Char(
'^'), QLatin1Char(
'_'), QLatin1Char(0xA6), QLatin1Char(
'~'),
147 QLatin1Char(0xC4), QLatin1Char(0xE4), QLatin1Char(0xD6), QLatin1Char(0xF6),
148 QLatin1Char(0xDF), QLatin1Char(0xA5), QLatin1Char(0xA4), QLatin1Char(
'|'),
149 QLatin1Char(0xC5), QLatin1Char(0xE5), QLatin1Char(0xD8), QLatin1Char(0xF8),
150 QChar(0x250C), QChar(0x2510), QChar(0x2514), QChar(0x2518)
155 if (mode == std::numeric_limits<std::size_t>::max())
179 int newccmode = (b1 >> 3) & 1;
180 int newtxtmode =
m_txtMode[(field*2) + newccmode];
181 if ((b1 & 0x06) == 0x04)
203 m_txtMode[(field*2) + newccmode] = newtxtmode;
204 size_t mode = (field << 2) | (newtxtmode << 1) |
m_ccMode[field];
207 size_t len =
m_ccBuf[mode].length();
226 LOG(VB_VBI, LOG_INFO,
227 QString(
"cc608 preamble indent, b2=%1")
236 LOG(VB_VBI, LOG_INFO,
237 QString(
"cc608 preamble color change, b2=%1")
250 LOG(VB_VBI, LOG_DEBUG,
251 QString(
"<ATTRIBUTE %1 %2>").arg(b1).arg(b2));
261 LOG(VB_VBI, LOG_INFO,
262 QString(
"cc608 mid-row color change, b2=%1")
267 m_ccBuf[mode] += QChar(0x7000 + (b2 & 0xf));
284 m_ccBuf[mode].remove(len - 1, 1);
297 m_ccBuf[mode].remove(len - 1, 1);
305 LOG(VB_VBI, LOG_DEBUG,
306 QString(
"ccmode %1 cmd %2").arg(
m_ccMode)
307 .arg(b2, 2, 16,
'0'));
317 m_ccBuf[mode].startsWith(
"\b"))
324 m_ccBuf[mode].remove(len - 1, 1);
357 (!newtxtmode ||
m_row[mode] >= 16)))
364 if (
m_row[mode] < 16)
398 if (
m_row[mode] == 0)
489 for (
int x = 0; x < (b2 & 0x03); x++)
509 for (mode = field*4; mode < ((field*4) + 4); mode++)
523 LOG(VB_VBI, LOG_DEBUG,
"Format CC -- Duplicate");
530 int b1 = data & 0x7f;
531 int b2 = (data >> 8) & 0x7f;
533 LOG(VB_VBI, LOG_DEBUG,
534 QString(
"Format CC @%1/%2 = %3 %4, %5/%6 = '%7' '%8'")
535 .arg(tc.count()).arg(field)
536 .arg((data&0xff), 2, 16)
537 .arg((data&0xff00)>>8, 2, 16)
538 .arg(b1, 2, 16, QChar(
'0'))
539 .arg(b2, 2, 16, QChar(
'0'))
540 .arg(QChar((b1 & 0x60) ? b1 :
'_'))
541 .arg(QChar((b2 & 0x60) ? b2 :
'_')));
548 if (mode != std::numeric_limits<std::size_t>::max())
555 mode = std::numeric_limits<std::size_t>::max();
574 else if ((b1 & 0x10) && (b2 > 0x1F))
581 for (
size_t mode2 = field*4; mode2 < ((field*4) + 4); mode2++)
583 size_t len2 =
m_ccBuf[mode2].length();
607 int b1 = data & 0x7f;
608 int b2 = (data >> 8) & 0x7f;
616 ((b1 & 0x70) == 0x10))
628 std::chrono::milliseconds dup_text_fudge = 0ms;
629 std::chrono::milliseconds dup_ctrl_fudge = 0ms;
630 if (
m_badVbi[field] < 100 && b1 != 0 && b2 != 0)
632 std::chrono::milliseconds
d = tc -
m_lastTc[field];
633 if (d < 25ms || d > 42ms)
641 dup_text_fudge = -2ms;
643 dup_ctrl_fudge = 33ms - 4ms;
647 dup_text_fudge = 4ms;
648 dup_ctrl_fudge = 33ms - 4ms;
653 if ((b1 & 0x70) == 0x10)
691 for (
const auto& cp : std::as_const(cc608str))
693 int cpu = cp.unicode();
698 case 0x2120 : ret +=
"(SM)";
break;
699 case 0x2122 : ret +=
"(TM)";
break;
700 case 0x2014 : ret +=
"(--)";
break;
701 case 0x201C : ret +=
"``";
break;
702 case 0x201D : ret +=
"''";
break;
703 case 0x250C : ret +=
"|-";
break;
704 case 0x2510 : ret +=
"-|";
break;
705 case 0x2514 : ret +=
"|_";
break;
706 case 0x2518 : ret +=
"_|";
break;
707 case 0x2588 : ret +=
"[]";
break;
708 case 0x266A : ret +=
"o/~";
break;
709 case '\b' : ret +=
"\\b";
break;
711 if (cpu >= 0x7000 && cpu < 0x7000 + 0x30)
713 if (!suppress_unknown)
714 ret += QString(
"[%1]").arg(cpu, 2, 16);
716 else if (cpu <= 0x80)
718 ret += QString(cp.toLatin1());
720 else if (!suppress_unknown)
722 ret += QString(
"{%1}").arg(cpu, 2, 16);
736 tmpbuf =
m_ccBuf[mode].toUtf8();
737#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
738 len = std::min(tmpbuf.length(), 255);
740 len = std::min(tmpbuf.length(),
static_cast<qsizetype
>(255));
744 unsigned char *bp =
m_rbuf;
745 *(bp++) =
m_row[mode];
770 LOG(VB_VBI, LOG_INFO, QString(
"### %1 %2 %3 %4 %5 %6 %7 - '%8'")
773 .arg(
m_style[mode]).arg(f, 2, 16)
774 .arg(clr).arg(len, 3)
775 .arg(
ToASCII(QString::fromUtf8(tmpbuf.constData(), len),
false)));
783 case CC_CC1: stream = 0;
break;
784 case CC_CC2: stream = 1;
break;
785 case CC_CC3: stream = 2;
break;
786 case CC_CC4: stream = 3;
break;
789 m_lastSeen[stream] = std::chrono::system_clock::now();
817 if (
m_row[mode] == 0)
827 if (
m_row[mode] == 0)
880 for (
int x = 0; x < limit; x++)
902 return ((c) & 0x7F) >= 0x20 && ((c) & 0x7F) <= 0x7E;
911static int OddParity(
unsigned char c)
913 c ^= (c >> 4); c ^= (c >> 2); c ^= (c >> 1);
922static constexpr int PIL_TIME(
int day,
int mon,
int hour,
int min)
923{
return (day << 15) + (mon << 11) + (hour << 6) + min; }
927 int day = (pil >> 15);
928 int mon = (pil >> 11) & 0xF;
929 int hour = (pil >> 6 ) & 0x1F;
930 int min = (pil ) & 0x3F;
933 LOG(VB_VBI, LOG_INFO,
" PDC: Timer-control (no PDC)");
934 else if (pil ==
PIL_TIME(0, 15, 30, 63))
935 LOG(VB_VBI, LOG_INFO,
" PDC: Recording inhibit/terminate");
936 else if (pil ==
PIL_TIME(0, 15, 29, 63))
937 LOG(VB_VBI, LOG_INFO,
" PDC: Interruption");
938 else if (pil ==
PIL_TIME(0, 15, 28, 63))
939 LOG(VB_VBI, LOG_INFO,
" PDC: Continue");
940 else if (pil ==
PIL_TIME(31, 15, 31, 63))
941 LOG(VB_VBI, LOG_INFO,
" PDC: No time");
943 LOG(VB_VBI, LOG_INFO, QString(
" PDC: %1, 200X-%2-%3 %4:%5")
944 .arg(pil).arg(mon).arg(day).arg(hour).arg(min));
962 LOG(VB_VBI, LOG_INFO, QString(
"VPS: 3-10: %1 %2 %3 %4 %5 %6 %7 %8 (\"%9\")")
963 .arg(buf[0]).arg(buf[1]).arg(buf[2]).arg(buf[3]).arg(buf[4])
964 .arg(buf[5]).arg(buf[6]).arg(buf[7]).arg(
m_vpsPrLabel.data()));
966 int pcs = buf[2] >> 6;
967 int cni = + ((buf[10] & 3) << 10)
968 + ((buf[11] & 0xC0) << 2)
969 + ((buf[8] & 0xC0) << 0)
971 int pil = ((buf[8] & 0x3F) << 14) + (buf[9] << 6) + (buf[10] >> 2);
974 LOG(VB_VBI, LOG_INFO, QString(
"CNI: %1 PCS: %2 PTY: %3 ")
975 .arg(cni).arg(pcs).arg(pty));
988 static const std::array<const int,8> kWssBits { 0, 0, 0, 1, 0, 1, 1, 1 };
991 for (
uint i = 0; i < 16; i++)
993 uint b1 = kWssBits[buf[i] & 7];
994 uint b2 = kWssBits[(buf[i] >> 3) & 7];
1000 unsigned char parity = wss & 0xf;
1001 parity ^= parity >> 2;
1002 parity ^= parity >> 1;
1004 LOG(VB_VBI, LOG_INFO,
1005 QString(
"WSS: %1; %2 mode; %3 color coding;\n\t\t\t"
1006 " %4 helper; reserved b7=%5; %6\n\t\t\t"
1007 " open subtitles: %7; %scopyright %8; copying %9")
1008 .arg(QString::fromStdString(
formats[wss & 7]),
1009 (wss & 0x0010) ?
"film" :
"camera",
1010 (wss & 0x0020) ?
"MA/CP" :
"standard",
1011 (wss & 0x0040) ?
"modulated" :
"no",
1012 (wss & 0x0080) ?
"1" :
"0",
1013 (wss & 0x0100) ?
"have TTX subtitles; " :
"",
1014 QString::fromStdString(
subtitles[(wss >> 9) & 3]),
1015 (wss & 0x0800) ?
"surround sound; " :
"",
1016 (wss & 0x1000) ?
"asserted" :
"unknown")
1018 .arg((wss & 0x2000) ?
"restricted" :
"not restricted"));
1031 for (
uint i = start; (i < buf.size()) && (i < end); i++)
1033 LOG(VB_VBI, LOG_INFO, QString(
"%1: 0x%2 -> 0x%3 %4")
1035 .arg(buf[i],2,16,QChar(
'0'))
1042 for (
uint i = start; (i < buf.size()) && (i < end); i++)
1049 LOG(VB_VBI, LOG_INFO, QString(
"XDSDecodeString: '%1'").arg(
tmp));
1052 return tmp.trimmed();
1055static bool is_better(
const QString &newStr,
const QString &oldStr)
1057 if (!newStr.isEmpty() && newStr != oldStr &&
1058 (newStr != oldStr.left(newStr.length())))
1060 if (oldStr.isEmpty())
1064 return std::all_of(newStr.cbegin(), newStr.cend(),
1065 [](
auto ch){ return ch.toLatin1() >= 0x20; } );
1079 return m_xdsRating[(future) ? 1 : 0][i & 0x3] & 0x7;
1086 const std::array<const QString,4>
prefix {
"MPAA-",
"TV-",
"CE-",
"CF-" };
1087 const std::array<const std::array<const QString,8>,4> mainStr
1089 {
"NR",
"G",
"PG",
"PG-13",
"R",
"NC-17",
"X",
"NR" },
1090 {
"NR",
"Y",
"Y7",
"G",
"PG",
"14",
"MA",
"NR" },
1091 {
"E",
"C",
"C8+",
"G",
"PG",
"14+",
"18+",
"NR" },
1092 {
"E",
"G",
"8+",
"13+",
"16+",
"18+",
"NR",
"NR" },
1099 uint cf = (future) ? 1 : 0;
1127 const std::vector<uint> &program_type =
m_xdsProgramType[(future) ? 1 : 0];
1130 for (
size_t i = 0; i < program_type.size(); i++)
1144 if (key ==
"ratings")
1146 if (key.startsWith(
"has_rating_"))
1148 if (key.startsWith(
"rating_"))
1151 if (key ==
"future_ratings")
1153 if (key.startsWith(
"has_future_rating_"))
1155 if (key.startsWith(
"future_rating_"))
1158 if (key ==
"programname")
1160 if (key ==
"future_programname")
1163 if (key ==
"programtype")
1165 if (key ==
"future_programtype")
1168 if (key ==
"callsign")
1170 if (key ==
"channame")
1196 LOG(VB_VBI, LOG_INFO,
1197 QString(
"XDSDecode: 0x%1 0x%2 '%3%4' xds[%5]=%6 in XDS %7")
1198 .arg(b1,2,16,QChar(
'0')).arg(b2,2,16,QChar(
'0'))
1201 .arg(field).arg(
m_xds[field])
1223 else if ((0x0 < b1) && (b1 < 0x0f))
1247 else if ((0x10 <= b1) && (b1 <= 0x1f))
1250 LOG(VB_VBI, LOG_INFO, QString(
"XDSDecode: Suspending XDS %1 on 0x%2")
1263 bool handled =
false;
1264 int xds_class = xds_buf[0];
1269 if ((xds_class == 0x01) || (xds_class == 0x03))
1271 else if (xds_class == 0x05)
1273 else if ((xds_class == 0x07) ||
1274 (xds_class == 0x09) ||
1275 (xds_class == 0x0b))
1277 else if (xds_class == 0x0d)
1283 LOG(VB_VBI, LOG_INFO, QString(
"XDS: ") +
1284 QString(
"Unhandled packet (0x%1 0x%2) sz(%3) '%4'")
1285 .arg(xds_buf[0],0,16).arg(xds_buf[1],0,16)
1286 .arg(xds_buf.size())
1296 for (
size_t i = 0; i < xds_buf.size() - 1; i++)
1299 if ((((~sum) & 0x7f) + 1) != xds_buf[xds_buf.size() - 1])
1303 LOG(VB_VBI, LOG_ERR, QString(
"XDS: failed CRC %1 of %2")
1314 const std::vector<unsigned char> &xds_buf,
bool future)
1316 bool handled =
true;
1317 int b2 = xds_buf[1];
1318 int cf = (future) ? 1 : 0;
1319 QString loc = (future) ?
"XDS: Future " :
"XDS: Current ";
1321 if ((b2 == 0x01) && (xds_buf.size() >= 6))
1323 uint min = xds_buf[2] & 0x3f;
1324 uint hour = xds_buf[3] & 0x0f;
1325 uint day = xds_buf[4] & 0x1f;
1326 uint month = xds_buf[5] & 0x0f;
1327 month = (month < 1 || month > 12) ? 0 : month;
1329 LOG(VB_VBI, LOG_INFO, loc +
1330 QString(
"Start Time %1/%2 %3:%4%5")
1331 .arg(month).arg(day).arg(hour).arg(min / 10).arg(min % 10));
1333 else if ((b2 == 0x02) && (xds_buf.size() >= 4))
1335 uint length_min = xds_buf[2] & 0x3f;
1336 uint length_hour = xds_buf[3] & 0x3f;
1337 uint length_elapsed_min = 0;
1338 uint length_elapsed_hour = 0;
1339 uint length_elapsed_secs = 0;
1340 if (xds_buf.size() > 6)
1342 length_elapsed_min = xds_buf[4] & 0x3f;
1343 length_elapsed_hour = xds_buf[5] & 0x3f;
1345 if (xds_buf.size() > 8 && xds_buf[7] == 0x40)
1346 length_elapsed_secs = xds_buf[6] & 0x3f;
1348 QString msg = QString(
"Program Length %1:%2%3 "
1349 "Time in Show %4:%5%6.%7%8")
1350 .arg(length_hour).arg(length_min / 10).arg(length_min % 10)
1351 .arg(length_elapsed_hour)
1352 .arg(length_elapsed_min / 10).arg(length_elapsed_min % 10)
1353 .arg(length_elapsed_secs / 10).arg(length_elapsed_secs % 10);
1355 LOG(VB_VBI, LOG_INFO, loc + msg);
1357 else if ((b2 == 0x03) && (xds_buf.size() >= 6))
1363 LOG(VB_VBI, LOG_INFO, loc + QString(
"Program Name: '%1'")
1367 else if ((b2 == 0x04) && (xds_buf.size() >= 6))
1369 std::vector<uint> program_type;
1370 for (
size_t i = 2; i < xds_buf.size() - 2; i++)
1372 int cur = xds_buf[i] - 0x20;
1373 if (cur >= 0 && cur < 96)
1374 program_type.push_back(cur);
1378 for (
uint i = 0; (i < program_type.size()) && unchanged; i++)
1384 LOG(VB_VBI, LOG_INFO, loc + QString(
"Program Type '%1'")
1388 else if ((b2 == 0x05) && (xds_buf.size() >= 4))
1390 uint movie_rating = xds_buf[2] & 0x7;
1391 uint rating_system = (xds_buf[2] >> 3) & 0x7;
1392 uint tv_rating = xds_buf[3] & 0x7;
1393 uint VSL = xds_buf[3] & (0x7 << 3);
1394 uint sel = VSL | rating_system;
1402 LOG(VB_VBI, LOG_INFO, loc + QString(
"VChip %1")
1413 LOG(VB_VBI, LOG_INFO, loc + QString(
"VChip %1")
1417 else if (sel == 0x13 || sel == 0x1f)
1421 else if ((rating_system & 0x3) == 1)
1426 uint f = ((xds_buf[0]<<3) & 0x80) | ((xds_buf[1]<<1) & 0x70);
1429 LOG(VB_VBI, LOG_INFO, loc + QString(
"VChip %1")
1433 else if (rating_system == 0)
1440 LOG(VB_VBI, LOG_INFO, loc + QString(
"VChip %1")
1446 LOG(VB_VBI, LOG_ERR, loc +
1447 QString(
"VChip Unhandled -- rs(%1) rating(%2:%3)")
1448 .arg(rating_system).arg(tv_rating).arg(movie_rating));
1452 else if (b2 == 0x07)
1454 else if (b2 == 0x08)
1456 else if (b2 == 0x09)
1458 else if (b2 == 0x0c)
1460 else if (b2 == 0x10 || b2 == 0x13 || b2 == 0x15 || b2 == 0x16 ||
1461 b2 == 0x91 || b2 == 0x92 || b2 == 0x94 || b2 == 0x97)
1463 else if (b2 == 0x86)
1465 else if (b2 == 0x89)
1467 else if (b2 == 0x8c)
1480 bool handled =
true;
1482 int b2 = xds_buf[1];
1483 if ((b2 == 0x01) && (xds_buf.size() >= 6))
1488 LOG(VB_VBI, LOG_INFO, QString(
"XDS: Network Name '%1'").arg(
tmp));
1492 else if ((b2 == 0x02) && (xds_buf.size() >= 6))
1497 LOG(VB_VBI, LOG_INFO, QString(
"XDS: Network Call '%1'").arg(
tmp));
1501 else if ((b2 == 0x04) && (xds_buf.size() >= 6))
1503 uint tsid = (xds_buf[2] << 24 | xds_buf[3] << 16 |
1504 xds_buf[4] << 8 | xds_buf[5]);
1507 LOG(VB_VBI, LOG_INFO, QString(
"XDS: TSID 0x%1").arg(tsid,0,16));
1521 xds_program_type[0] = QCoreApplication::translate(
"(Categories)",
1523 xds_program_type[1] = QCoreApplication::translate(
"(Categories)",
1525 xds_program_type[2] = QCoreApplication::translate(
"(Categories)",
1527 xds_program_type[3] = QCoreApplication::translate(
"(Categories)",
1529 xds_program_type[4] = QCoreApplication::translate(
"(Categories)",
1531 xds_program_type[5] = QCoreApplication::translate(
"(Categories)",
1533 xds_program_type[6] = QCoreApplication::translate(
"(Categories)",
1535 xds_program_type[7] = QCoreApplication::translate(
"(Categories)",
1537 xds_program_type[8] = QCoreApplication::translate(
"(Categories)",
1539 xds_program_type[9] = QCoreApplication::translate(
"(Categories)",
1541 xds_program_type[10] = QCoreApplication::translate(
"(Categories)",
1543 xds_program_type[11] = QCoreApplication::translate(
"(Categories)",
1545 xds_program_type[12] = QCoreApplication::translate(
"(Categories)",
1547 xds_program_type[13] = QCoreApplication::translate(
"(Categories)",
1549 xds_program_type[14] = QCoreApplication::translate(
"(Categories)",
1551 xds_program_type[15] = QCoreApplication::translate(
"(Categories)",
1553 xds_program_type[16] = QCoreApplication::translate(
"(Categories)",
1555 xds_program_type[17] = QCoreApplication::translate(
"(Categories)",
1557 xds_program_type[18] = QCoreApplication::translate(
"(Categories)",
1559 xds_program_type[19] = QCoreApplication::translate(
"(Categories)",
1561 xds_program_type[20] = QCoreApplication::translate(
"(Categories)",
1563 xds_program_type[21] = QCoreApplication::translate(
"(Categories)",
1565 xds_program_type[22] = QCoreApplication::translate(
"(Categories)",
1567 xds_program_type[23] = QCoreApplication::translate(
"(Categories)",
1569 xds_program_type[24] = QCoreApplication::translate(
"(Categories)",
1571 xds_program_type[25] = QCoreApplication::translate(
"(Categories)",
1573 xds_program_type[26] = QCoreApplication::translate(
"(Categories)",
1575 xds_program_type[27] = QCoreApplication::translate(
"(Categories)",
1577 xds_program_type[28] = QCoreApplication::translate(
"(Categories)",
1579 xds_program_type[29] = QCoreApplication::translate(
"(Categories)",
1581 xds_program_type[30] = QCoreApplication::translate(
"(Categories)",
1583 xds_program_type[31] = QCoreApplication::translate(
"(Categories)",
1585 xds_program_type[32] = QCoreApplication::translate(
"(Categories)",
1587 xds_program_type[33] = QCoreApplication::translate(
"(Categories)",
1589 xds_program_type[34] = QCoreApplication::translate(
"(Categories)",
1591 xds_program_type[35] = QCoreApplication::translate(
"(Categories)",
1593 xds_program_type[36] = QCoreApplication::translate(
"(Categories)",
1595 xds_program_type[37] = QCoreApplication::translate(
"(Categories)",
1597 xds_program_type[38] = QCoreApplication::translate(
"(Categories)",
1599 xds_program_type[39] = QCoreApplication::translate(
"(Categories)",
1601 xds_program_type[40] = QCoreApplication::translate(
"(Categories)",
1603 xds_program_type[41] = QCoreApplication::translate(
"(Categories)",
1605 xds_program_type[42] = QCoreApplication::translate(
"(Categories)",
1607 xds_program_type[43] = QCoreApplication::translate(
"(Categories)",
1609 xds_program_type[44] = QCoreApplication::translate(
"(Categories)",
1611 xds_program_type[45] = QCoreApplication::translate(
"(Categories)",
1613 xds_program_type[46] = QCoreApplication::translate(
"(Categories)",
1615 xds_program_type[47] = QCoreApplication::translate(
"(Categories)",
1617 xds_program_type[48] = QCoreApplication::translate(
"(Categories)",
1619 xds_program_type[49] = QCoreApplication::translate(
"(Categories)",
1621 xds_program_type[50] = QCoreApplication::translate(
"(Categories)",
1623 xds_program_type[51] = QCoreApplication::translate(
"(Categories)",
1625 xds_program_type[52] = QCoreApplication::translate(
"(Categories)",
1627 xds_program_type[53] = QCoreApplication::translate(
"(Categories)",
1629 xds_program_type[54] = QCoreApplication::translate(
"(Categories)",
1631 xds_program_type[55] = QCoreApplication::translate(
"(Categories)",
1633 xds_program_type[56] = QCoreApplication::translate(
"(Categories)",
1635 xds_program_type[57] = QCoreApplication::translate(
"(Categories)",
1637 xds_program_type[58] = QCoreApplication::translate(
"(Categories)",
1639 xds_program_type[59] = QCoreApplication::translate(
"(Categories)",
1641 xds_program_type[60] = QCoreApplication::translate(
"(Categories)",
1643 xds_program_type[61] = QCoreApplication::translate(
"(Categories)",
1645 xds_program_type[62] = QCoreApplication::translate(
"(Categories)",
1647 xds_program_type[63] = QCoreApplication::translate(
"(Categories)",
1649 xds_program_type[64] = QCoreApplication::translate(
"(Categories)",
1651 xds_program_type[65] = QCoreApplication::translate(
"(Categories)",
1653 xds_program_type[66] = QCoreApplication::translate(
"(Categories)",
1655 xds_program_type[67] = QCoreApplication::translate(
"(Categories)",
1657 xds_program_type[68] = QCoreApplication::translate(
"(Categories)",
1659 xds_program_type[69] = QCoreApplication::translate(
"(Categories)",
1661 xds_program_type[70] = QCoreApplication::translate(
"(Categories)",
1663 xds_program_type[71] = QCoreApplication::translate(
"(Categories)",
1665 xds_program_type[72] = QCoreApplication::translate(
"(Categories)",
1667 xds_program_type[73] = QCoreApplication::translate(
"(Categories)",
1669 xds_program_type[74] = QCoreApplication::translate(
"(Categories)",
1671 xds_program_type[75] = QCoreApplication::translate(
"(Categories)",
1673 xds_program_type[76] = QCoreApplication::translate(
"(Categories)",
1675 xds_program_type[77] = QCoreApplication::translate(
"(Categories)",
1677 xds_program_type[78] = QCoreApplication::translate(
"(Categories)",
1679 xds_program_type[79] = QCoreApplication::translate(
"(Categories)",
1681 xds_program_type[80] = QCoreApplication::translate(
"(Categories)",
1683 xds_program_type[81] = QCoreApplication::translate(
"(Categories)",
1685 xds_program_type[82] = QCoreApplication::translate(
"(Categories)",
1687 xds_program_type[83] = QCoreApplication::translate(
"(Categories)",
1689 xds_program_type[84] = QCoreApplication::translate(
"(Categories)",
1691 xds_program_type[85] = QCoreApplication::translate(
"(Categories)",
1693 xds_program_type[86] = QCoreApplication::translate(
"(Categories)",
1695 xds_program_type[87] = QCoreApplication::translate(
"(Categories)",
1697 xds_program_type[88] = QCoreApplication::translate(
"(Categories)",
1699 xds_program_type[89] = QCoreApplication::translate(
"(Categories)",
1701 xds_program_type[90] = QCoreApplication::translate(
"(Categories)",
1703 xds_program_type[91] = QCoreApplication::translate(
"(Categories)",
1705 xds_program_type[92] = QCoreApplication::translate(
"(Categories)",
1707 xds_program_type[93] = QCoreApplication::translate(
"(Categories)",
1709 xds_program_type[94] = QCoreApplication::translate(
"(Categories)",
1711 xds_program_type[95] = QCoreApplication::translate(
"(Categories)",
static const std::array< const uint8_t, 256 > vbi_bit_reverse
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 bool IsPrintable(char c)
static void init_xds_program_type(CC608ProgramType &xds_program_type)
static char Printable(char c)
static const std::array< const std::string, 8 > formats
static constexpr int PIL_TIME(int day, int mon, int hour, int min)
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
QString GetRatingString(uint i, bool future) const
void XDSPacketParse(const std::vector< unsigned char > &xds_buf)
QString GetProgramType(bool future) const
bool XDSDecode(int field, int b1, int b2)
static QString ToASCII(const QString &cc608, bool suppress_unknown)
std::array< uint, 2 > m_xdsRatingSystems
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 XDSPacketParseProgram(const std::vector< unsigned char > &xds_buf, bool future)
void DecodeVPS(const unsigned char *buf)
QChar CharCC(int code) const
bool FalseDup(std::chrono::milliseconds tc, int field, int data)
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
void BufferCC(size_t mode, int len, int clr)
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
int NewRowCC(size_t mode, int len)
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_)