MythTV master
dvbdescriptors.cpp
Go to the documentation of this file.
1// For windows, force the second argument of `iconv' to non-const.
2#define WINICONV_CONST
3
4// C headers
5#include <iconv.h>
6#include <unistd.h>
7#include <algorithm>
8#include <cerrno>
9#include <cstdint>
10
11// Qt headers
12#include <QCoreApplication>
13
14// MythTV headers
15#include "dvbdescriptors.h"
16#include "iso6937tables.h"
17#include "freesat_huffman.h"
20
21// Decode a text string according to
22// Draft ETSI EN 300 468 V1.16.1 (2019-05)
23// Digital Video Broadcasting (DVB);
24// Specification for Service Information (SI) in DVB systems
25// Annex A (normative): Coding of text characters
26
27static QString decode_iso6937(const unsigned char *buf, uint length)
28{
29 // ISO/IEC 6937 to unicode (UCS2) convertor...
30 // This is a composed encoding - accent first then plain character
31 QString result = "";
32 ushort ch = 0x20;
33 for (uint i = 0; (i < length) && buf[i]; i++)
34 {
35 if (ch == 0xFFFF)
36 {
37 // Process second byte of two byte character
38 const iso6937table * foo = iso6937table_secondary[buf[i-1]];
39 ch = (*foo)[buf[i]];
40 if (ch == 0xFFFF)
41 {
42 // If no valid code found in secondary table,
43 // reprocess this second byte as first byte.
44 ch = iso6937table_base[buf[i]];
45 if (ch == 0xFFFF)
46 continue; // process second byte
47 }
48 }
49 else
50 {
51 // Process first character of two possible characters.
52 // double byte characters have a sentinel (0xffff) in this table.
53 ch = iso6937table_base[buf[i]];
54 if (ch == 0xFFFF)
55 continue; // process second byte
56
57 }
58 result += QChar(ch);
59 }
60 return result;
61}
62
63// Set up a context for iconv, and call it repeatedly until finished.
64// The iconv function stops whenever an unknown character is seen in
65// the input stream. Handle inserting a � character and continuing, so
66// that the resulting output is the same as QTextCodec::toUnicode.
67static QString iconv_helper(int which, char *buf, size_t length)
68{
69 QString codec = QString("iso-8859-%1").arg(which);
70 iconv_t conv = iconv_open("utf-16", qPrintable(codec));
71 if (conv == (iconv_t) -1) // NOLINT(performance-no-int-to-ptr)
72 return "";
73
74 // Allocate room for the output, including space for the Byte
75 // Order Mark.
76 size_t outmaxlen = (length * 2) + 2;
77 QByteArray outbytes;
78 outbytes.resize(outmaxlen);
79 char *outp = outbytes.data();
80 size_t outremain = outmaxlen;
81
82 // Conversion loop
83 while (length > 0)
84 {
85 size_t ret = iconv(conv, &buf, &length, &outp, &outremain);
86 if (ret == size_t(-1))
87 {
88 if (errno == EILSEQ)
89 {
90 buf++; length -= 1;
91 // Invalid Unicode character. Stuff a U+FFFD �
92 // replacement character into the output like Qt.
93 // Need to check the Byte Order Mark U+FEFF set by
94 // iconv and match the ordering being used. (This
95 // doesn't necessarily follow HAVE_BIGENDIAN.)
96 if (outbytes[0] == static_cast<char>(0xFE))
97 { // Big endian
98 *outp++ = 0xFF; *outp++ = 0xFD;
99 }
100 else
101 {
102 *outp++ = 0xFD; *outp++ = 0xFF;
103 }
104 outremain -= 2;
105 }
106 else
107 {
108 // Invalid or incomplete multibyte character in
109 // input. Should never happen when converting from
110 // iso-8859.
111 length = 0;
112 }
113 }
114 }
115
116 // Remove the Byte Order Mark for compatability with
117 // QTextCodec::toUnicode. Do not replace the ::fromUtf16 call with
118 // the faster QString constructor, as the latter doesn't read the
119 // BOM and convert the string to host byte order.
120 QString result =
121 QString::fromUtf16(reinterpret_cast<char16_t*>(outbytes.data()),
122 (outmaxlen-outremain)/2);
123
124 iconv_close(conv);
125 return result;
126}
127
128static QString decode_text(const unsigned char *buf, uint length);
129
130// Decode a text string according to ETSI EN 300 468 Annex A
131QString dvb_decode_text(const unsigned char *src, uint raw_length,
132 const enc_override &encoding_override)
133{
134 if (!raw_length)
135 return "";
136
137 if (src[0] == 0x1f)
138 return freesat_huffman_to_string(src, raw_length);
139
140 /* UCS-2 aka ISO/IEC 10646-1 Basic Multilingual Plane */
141 if (src[0] == 0x11)
142 {
143 QString s;
144 s.reserve((raw_length - 1) / 2);
145 for (size_t i = 1; i < raw_length - 1; i += 2)
146 {
147 s += QChar{(static_cast<uint16_t>(src[i]) << 8) + src[i + 1]};
148 }
149 return s;
150 }
151
152 if (((0x11 < src[0]) && (src[0] < 0x15)) ||
153 ((0x15 < src[0]) && (src[0] < 0x1f)))
154 {
155 // TODO: Handle multi-byte encodings
156 LOG(VB_SIPARSER, LOG_ERR,
157 "dvb_decode_text: Multi-byte coded text is not yet supported.");
158 return "";
159 }
160
161 // UTF-8 encoding of ISO/IEC 10646
162 if (src[0] == 0x15)
163 {
164 return decode_text(src, raw_length);
165 }
166
167 // if a override encoding is specified and the default ISO 6937 encoding
168 // would be used copy the override encoding in front of the text
169 auto *dst = new unsigned char[raw_length + encoding_override.size()];
170
171 uint length = 0;
172 if (!encoding_override.empty() && (src[0] >= 0x20)) {
173 std::copy(encoding_override.cbegin(), encoding_override.cend(), dst);
174 length = encoding_override.size();
175 }
176
177 // Strip formatting characters
178 for (uint i = 0; i < raw_length; i++)
179 {
180 if ((src[i] < 0x80) || (src[i] > 0x9F))
181 {
182 dst[length++] = src[i];
183 // replace CR/LF with a space
184 }
185 else if (src[i] == 0x8A)
186 {
187 dst[length++] = 0x20;
188 }
189 }
190
191 // Exit on empty string, sans formatting.
192
193 QString sStr = (!length) ? "" : decode_text(dst, length);
194
195 delete [] dst;
196
197 return sStr;
198}
199
200static QString decode_text(const unsigned char *buf, uint length)
201{
202 // Decode using the correct text codec
203 if (buf[0] >= 0x20)
204 {
205 return decode_iso6937(buf, length);
206 }
207 if ((buf[0] >= 0x01) && (buf[0] <= 0x0B))
208 {
209 return iconv_helper(4 + buf[0], (char*)(buf + 1), length - 1);
210 }
211 if ((buf[0] == 0x10) && (length >= 3))
212 {
213 // If the first byte of the text field has a value "0x10"
214 // then the following two bytes carry a 16-bit value (uimsbf) N
215 // to indicate that the remaining data of the text field is
216 // coded using the character code table specified by
217 // ISO Standard 8859, parts 1 to 9
218
219 uint code = buf[1] << 8 | buf[2];
220 if (code <= 15)
221 return iconv_helper(code, (char*)(buf + 3), length - 3);
222 return QString::fromLocal8Bit((char*)(buf + 3), length - 3);
223 }
224 if (buf[0] == 0x15) // Already Unicode
225 {
226 return QString::fromUtf8((char*)(buf + 1), length - 1);
227 }
228
229 // Unknown/invalid encoding - assume local8Bit
230 return QString::fromLocal8Bit((char*)(buf + 1), length - 1);
231}
232
233
234QString dvb_decode_short_name(const unsigned char *src, uint raw_length)
235{
236 if (raw_length > 50)
237 {
238 LOG(VB_SIPARSER, LOG_WARNING,
239 QString("dvb_decode_short_name: name is %1 chars "
240 "long. Unlikely to be a short name.")
241 .arg(raw_length));
242 return "";
243 }
244
245 if (((0x10 < src[0]) && (src[0] < 0x15)) ||
246 ((0x15 < src[0]) && (src[0] < 0x20)))
247 {
248 // TODO: Handle multi-byte encodings
249 LOG(VB_SIPARSER, LOG_ERR, "dvb_decode_short_name: "
250 "Multi-byte coded text is not yet supported.");
251 return "";
252 }
253
254 auto *dst = new unsigned char[raw_length];
255 uint length = 0;
256
257 // check for emphasis control codes
258 for (uint i = 0; i < raw_length; i++)
259 {
260 if (src[i] == 0x86)
261 {
262 for (i = i + 1; i < raw_length && (src[i] != 0x87); i++)
263 {
264 if ((src[i] < 0x80) || (src[i] > 0x9F))
265 {
266 dst[length++] = src[i];
267 }
268 // replace CR/LF with a space
269 else if (src[i] == 0x8A)
270 {
271 dst[length++] = 0x20;
272 }
273 }
274 }
275 }
276
277 QString sStr = (!length) ? dvb_decode_text(src, raw_length)
278 : decode_text(dst, length);
279
280 delete [] dst;
281
282 return sStr;
283}
284
286QMap<uint,QString> ContentDescriptor::s_categoryDesc;
287volatile bool ContentDescriptor::s_categoryDescExists = false;
288
290{
291 if (0x1 == Nibble1(i))
293 if (0x4 == Nibble1(i))
296}
297
298const std::array<const std::string,14> linkage_types
299{
300 "Reserved(0x00)",
301 "Information Service",
302 "EPG Service",
303 "CA Replacement Service",
304 "TS Containing Complete Network/Bouquet SI",
305 "Service Replacement Service",
306 "Data Broadcast Service",
307 "RCS Map",
308 "Mobile Hand-Over",
309 "System Software Update Service",
310 "TS Containing SSU, BAT or NIT",
311 "IP/MAC Notification Service",
312 "TS Containing INT, BAT or NIT",
313 "Event Linkage",
314};
315
316
318{
319 if (LinkageType() < linkage_types.size())
320 return QString::fromStdString(linkage_types[LinkageType()]);
321 if ((LinkageType() <= 0x7f) || (LinkageType() == 0xff))
322 return QString("Reserved(0x%1)").arg(LinkageType(),2,16,QChar('0'));
323 return QString("User Defined(0x%1)").arg(LinkageType(),2,16,QChar('0'));
324}
325
327{
329 return "Hand-Over to an Identical Service";
331 return "Hand-Over to a Local Variation";
333 return "Hand-over to an Associated Service";
334 return "Reserved";
335}
336
338{
340 Init();
341
342 QMutexLocker locker(&s_categoryLock);
343
344 // Try to get detailed description
345 QMap<uint,QString>::const_iterator it = s_categoryDesc.constFind(Nibble(i));
346 if (it != s_categoryDesc.constEnd())
347 return *it;
348
349 // Fall back to category description
350 it = s_categoryDesc.constFind(Nibble1(i)<<4);
351 if (it != s_categoryDesc.constEnd())
352 return *it;
353
354 // Found nothing? Just return empty string.
355 return "";
356}
357
359{
360 QString tmp("ContentDescriptor: ");
361 for (uint i = 0; i < Count(); i++)
362 tmp += myth_category_type_to_string(GetMythCategory(i)) + " : " + GetDescription(i) + ", ";
363 return tmp;
364}
365
367{
368 QMutexLocker locker(&s_categoryLock);
369
371 return;
372
373 //: %1 is the main category, %2 is the subcategory
374 QString subCatStr = QCoreApplication::translate("(Categories)",
375 "%1 - %2", "Category with subcategory display");
376
377 s_categoryDesc[0x10] = QCoreApplication::translate("(Categories)", "Movie");
378 s_categoryDesc[0x11] = subCatStr
379 .arg(QCoreApplication::translate("(Categories)", "Movie"),
380 QCoreApplication::translate("(Categories)", "Detective/Thriller"));
381 s_categoryDesc[0x12] = subCatStr
382 .arg(QCoreApplication::translate("(Categories)", "Movie"),
383 QCoreApplication::translate("(Categories)",
384 "Adventure/Western/War"));
385 s_categoryDesc[0x13] = subCatStr
386 .arg(QCoreApplication::translate("(Categories)", "Movie"),
387 QCoreApplication::translate("(Categories)",
388 "Science Fiction/Fantasy/Horror"));
389 s_categoryDesc[0x14] = subCatStr
390 .arg(QCoreApplication::translate("(Categories)", "Movie"),
391 QCoreApplication::translate("(Categories)", "Comedy"));
392 s_categoryDesc[0x15] = subCatStr
393 .arg(QCoreApplication::translate("(Categories)", "Movie"),
394 QCoreApplication::translate("(Categories)",
395 "Soap/Melodrama/Folkloric"));
396 s_categoryDesc[0x16] = subCatStr
397 .arg(QCoreApplication::translate("(Categories)", "Movie"),
398 QCoreApplication::translate("(Categories)", "Romance"));
399 s_categoryDesc[0x17] = subCatStr
400 .arg(QCoreApplication::translate("(Categories)","Movie"),
401 QCoreApplication::translate("(Categories)",
402 "Serious/Classical/Religious/Historical Movie/Drama"));
403 s_categoryDesc[0x18] = subCatStr
404 .arg(QCoreApplication::translate("(Categories)","Movie"),
405 QCoreApplication::translate("(Categories)", "Adult",
406 "Adult Movie"));
407
408 s_categoryDesc[0x20] = QCoreApplication::translate("(Categories)", "News");
409 s_categoryDesc[0x21] = QCoreApplication::translate("(Categories)",
410 "News/Weather Report");
411 s_categoryDesc[0x22] = QCoreApplication::translate("(Categories)",
412 "News Magazine");
413 s_categoryDesc[0x23] = QCoreApplication::translate("(Categories)",
414 "Documentary");
415 s_categoryDesc[0x24] = QCoreApplication::translate("(Categories)",
416 "Intelligent Programs");
417
418 s_categoryDesc[0x30] = QCoreApplication::translate("(Categories)",
419 "Entertainment");
420 s_categoryDesc[0x31] = QCoreApplication::translate("(Categories)",
421 "Game Show");
422 s_categoryDesc[0x32] = QCoreApplication::translate("(Categories)",
423 "Variety Show");
424 s_categoryDesc[0x33] = QCoreApplication::translate("(Categories)",
425 "Talk Show");
426
427 s_categoryDesc[0x40] = QCoreApplication::translate("(Categories)",
428 "Sports");
429 s_categoryDesc[0x41] = QCoreApplication::translate("(Categories)",
430 "Special Events (World Cup, World Series, etc)");
431 s_categoryDesc[0x42] = QCoreApplication::translate("(Categories)",
432 "Sports Magazines");
433 s_categoryDesc[0x43] = QCoreApplication::translate("(Categories)",
434 "Football (Soccer)");
435 s_categoryDesc[0x44] = QCoreApplication::translate("(Categories)",
436 "Tennis/Squash");
437 s_categoryDesc[0x45] = QCoreApplication::translate("(Categories)",
438 "Misc. Team Sports");
439 // not football/soccer
440 s_categoryDesc[0x46] = QCoreApplication::translate("(Categories)",
441 "Athletics");
442 s_categoryDesc[0x47] = QCoreApplication::translate("(Categories)",
443 "Motor Sport");
444 s_categoryDesc[0x48] = QCoreApplication::translate("(Categories)",
445 "Water Sport");
446 s_categoryDesc[0x49] = QCoreApplication::translate("(Categories)",
447 "Winter Sports");
448 s_categoryDesc[0x4A] = QCoreApplication::translate("(Categories)",
449 "Equestrian");
450 s_categoryDesc[0x4B] = QCoreApplication::translate("(Categories)",
451 "Martial Sports");
452
453 s_categoryDesc[0x50] = QCoreApplication::translate("(Categories)", "Kids");
454 s_categoryDesc[0x51] = QCoreApplication::translate("(Categories)",
455 "Pre-School Children's Programs");
456 s_categoryDesc[0x52] = QCoreApplication::translate("(Categories)",
457 "Entertainment Programs for 6 to 14");
458 s_categoryDesc[0x53] = QCoreApplication::translate("(Categories)",
459 "Entertainment Programs for 10 to 16");
460 s_categoryDesc[0x54] = QCoreApplication::translate("(Categories)",
461 "Informational/Educational");
462 s_categoryDesc[0x55] = QCoreApplication::translate("(Categories)",
463 "Cartoons/Puppets");
464
465 s_categoryDesc[0x60] = QCoreApplication::translate("(Categories)",
466 "Music/Ballet/Dance");
467 s_categoryDesc[0x61] = QCoreApplication::translate("(Categories)",
468 "Rock/Pop");
469 s_categoryDesc[0x62] = QCoreApplication::translate("(Categories)",
470 "Classical Music");
471 s_categoryDesc[0x63] = QCoreApplication::translate("(Categories)",
472 "Folk Music");
473 s_categoryDesc[0x64] = QCoreApplication::translate("(Categories)",
474 "Jazz");
475 s_categoryDesc[0x65] = QCoreApplication::translate("(Categories)",
476 "Musical/Opera");
477 s_categoryDesc[0x66] = QCoreApplication::translate("(Categories)",
478 "Ballet");
479
480 s_categoryDesc[0x70] = QCoreApplication::translate("(Categories)",
481 "Arts/Culture");
482 s_categoryDesc[0x71] = QCoreApplication::translate("(Categories)",
483 "Performing Arts");
484 s_categoryDesc[0x72] = QCoreApplication::translate("(Categories)",
485 "Fine Arts");
486 s_categoryDesc[0x73] = QCoreApplication::translate("(Categories)",
487 "Religion");
488 s_categoryDesc[0x74] = QCoreApplication::translate("(Categories)",
489 "Popular Culture/Traditional Arts");
490 s_categoryDesc[0x75] = QCoreApplication::translate("(Categories)",
491 "Literature");
492 s_categoryDesc[0x76] = QCoreApplication::translate("(Categories)",
493 "Film/Cinema");
494 s_categoryDesc[0x77] = QCoreApplication::translate("(Categories)",
495 "Experimental Film/Video");
496 s_categoryDesc[0x78] = QCoreApplication::translate("(Categories)",
497 "Broadcasting/Press");
498 s_categoryDesc[0x79] = QCoreApplication::translate("(Categories)",
499 "New Media");
500 s_categoryDesc[0x7A] = QCoreApplication::translate("(Categories)",
501 "Arts/Culture Magazines");
502 s_categoryDesc[0x7B] = QCoreApplication::translate("(Categories)", "Fashion");
503
504 s_categoryDesc[0x80] = QCoreApplication::translate("(Categories)",
505 "Social/Political/Economics");
506 s_categoryDesc[0x81] = QCoreApplication::translate("(Categories)",
507 "Magazines/Reports/Documentary");
508 s_categoryDesc[0x82] = QCoreApplication::translate("(Categories)",
509 "Economics/Social Advisory");
510 s_categoryDesc[0x83] = QCoreApplication::translate("(Categories)",
511 "Remarkable People");
512
513 s_categoryDesc[0x90] = QCoreApplication::translate("(Categories)",
514 "Education/Science/Factual");
515 s_categoryDesc[0x91] = QCoreApplication::translate("(Categories)",
516 "Nature/Animals/Environment");
517 s_categoryDesc[0x92] = QCoreApplication::translate("(Categories)",
518 "Technology/Natural Sciences");
519 s_categoryDesc[0x93] = QCoreApplication::translate("(Categories)",
520 "Medicine/Physiology/Psychology");
521 s_categoryDesc[0x94] = QCoreApplication::translate("(Categories)",
522 "Foreign Countries/Expeditions");
523 s_categoryDesc[0x95] = QCoreApplication::translate("(Categories)",
524 "Social/Spiritual Sciences");
525 s_categoryDesc[0x96] = QCoreApplication::translate("(Categories)",
526 "Further Education");
527 s_categoryDesc[0x97] = QCoreApplication::translate("(Categories)",
528 "Languages");
529
530 s_categoryDesc[0xA0] = QCoreApplication::translate("(Categories)",
531 "Leisure/Hobbies");
532 s_categoryDesc[0xA1] = QCoreApplication::translate("(Categories)",
533 "Tourism/Travel");
534 s_categoryDesc[0xA2] = QCoreApplication::translate("(Categories)",
535 "Handicraft");
536 s_categoryDesc[0xA3] = QCoreApplication::translate("(Categories)",
537 "Motoring");
538 s_categoryDesc[0xA4] = QCoreApplication::translate("(Categories)",
539 "Fitness & Health");
540 s_categoryDesc[0xA5] = QCoreApplication::translate("(Categories)", "Cooking");
541 s_categoryDesc[0xA6] = QCoreApplication::translate("(Categories)",
542 "Advertizement/Shopping");
543 s_categoryDesc[0xA7] = QCoreApplication::translate("(Categories)",
544 "Gardening");
545 // Special
546 s_categoryDesc[0xB0] = QCoreApplication::translate("(Categories)",
547 "Original Language");
548 s_categoryDesc[0xB1] = QCoreApplication::translate("(Categories)",
549 "Black & White");
550 s_categoryDesc[0xB2] = QCoreApplication::translate("(Categories)",
551 "\"Unpublished\" Programs");
552 s_categoryDesc[0xB3] = QCoreApplication::translate("(Categories)",
553 "Live Broadcast");
554 // UK Freeview custom id
555 s_categoryDesc[0xF0] = QCoreApplication::translate("(Categories)",
556 "Drama");
557
559}
560
562{
563 QString str = "FrequencyListDescriptor: frequencies: ";
564
565 for (uint i = 0; i < FrequencyCount(); i++)
566 {
567 str += QString("%1").arg(FrequencyHz(i));
568 if (i+1 < FrequencyCount())
569 {
570 if ((i+4)%10)
571 str += ", ";
572 else
573 str += ",\n ";
574 }
575 }
576
577 return str;
578}
579
581{
582 QString str = "";
583
584 if (IsDTV())
585 str.append(" (TV)");
586 else if (IsDigitalAudio())
587 str.append(" (Radio)");
588 else if (IsHDTV())
589 str.append(" (HDTV)");
590 else if (IsUHDTV())
591 str.append(" (UHDTV)");
592 else if (IsTeletext())
593 str.append(" (Teletext)");
594 else
595 str.append(QString(" (Unknown 0x%1)").arg(ServiceType(),2,16,QChar('0')));
596
597 return str;
598}
599
601{
602 QString ret = QString("Subtitling Descriptor ");
603 ret += QString("tag(0x%1) ").arg(DescriptorTag(),2,16,QChar('0'));
604 ret += QString("length(%1)").arg(DescriptorLength());
605
606 for (uint i = 0; i < StreamCount(); i++)
607 {
608 ret.append("\n ");
609 ret.append(QString("type(0x%1) composition_page_id(%2) ancillary_page_id(%3) lang(%4)")
610 .arg(SubtitleType(i),2,16,QChar('0'))
611 .arg(CompositionPageID(i))
612 .arg(AncillaryPageID(i))
613 .arg(LanguageString(i)));
614 }
615
616 return ret;
617}
618
620{
621 QString ret = QString("Teletext Descriptor ");
622 ret += QString("tag(0x%1) ").arg(DescriptorTag(),2,16,QChar('0'));
623 ret += QString("length(%1)").arg(DescriptorLength());
624
625 for (uint i = 0; i < StreamCount(); i++)
626 {
627 ret.append("\n ");
628 ret.append(QString("type(%1) mag(%2) page(%3) lang(%4)")
629 .arg(TeletextType(i))
630 .arg(TeletextMagazineNum(i), 0, 16)
631 .arg(TeletextPageNum(i), 2, 16, QChar('0'))
632 .arg(LanguageString(i)));
633 }
634
635 return ret;
636}
637
639{
640 QString str = QString("CableDeliverySystemDescriptor ");
641 str += QString("tag(0x%1) ").arg(DescriptorTag(),2,16,QChar('0'));
642 str += QString("length(%1)").arg(DescriptorLength());
643
644 str.append(QString("Frequency: %1\n").arg(FrequencyHz()));
645 str.append(QString(" Mod=%1, SymbR=%2, FECInner=%3, FECOuter=%4")
646 .arg(ModulationString(),
647 QString::number(SymbolRateHz()),
649 FECOuterString()));
650
651 return str;
652}
653
655{
656 QString str = QString("SatelliteDeliverySystemDescriptor ");
657 str += QString("tag(0x%1) ").arg(DescriptorTag(),2,16,QChar('0'));
658 str += QString("length(%1) ").arg(DescriptorLength());
659
660 str.append(QString("Frequency: %1, Type: %2\n").arg(FrequencykHz())
661 .arg(ModulationSystemString()));
662 str.append(QString(" Mod=%1, SymbR=%2, FECInner=%3, Orbit=%4, Pol=%5")
663 .arg(ModulationString(),
664 QString::number(SymbolRateHz()),
668
669 return str;
670}
671
673{
674 QString str = QString("TerrestrialDeliverySystemDescriptor ");
675 str += QString("tag(0x%1) ").arg(DescriptorTag(),2,16,QChar('0'));
676 str += QString("length(%1) ").arg(DescriptorLength());
677
678 str.append(QString("Frequency: %1\n").arg(FrequencyHz()));
679 str.append(QString(" BW=%1MHz C=%2 HP=%3 LP=%4 GI=%5 TransMode=%6k")
680 .arg(BandwidthString(),
686
687 return str;
688}
689
690// 0x79
692{
693 QString str = QString("S2SatelliteDeliverySystemDescriptor ");
694 str += QString("tag(0x%1) ").arg(DescriptorTag(),2,16,QChar('0'));
695 str += QString("length(%1) ").arg(DescriptorLength());
696
697 str.append(QString("\n ScramblingSequenceSelector(%1)").arg(ScramblingSequenceSelector()));
698 str.append(QString(" MultipleInputStreamFlag(%1)").arg(MultipleInputStreamFlag()));
699 str.append(QString("\n NotTimesliceFlag(%1)").arg(NotTimesliceFlag()));
700 str.append(QString(" TSGSMode(%1)").arg(TSGSMode()));
701 //
702 // TBD
703 //
704 str.append(" Dumping\n");
705 str.append(hexdump());
706 return str;
707}
708
709// 0x7F 0x00
711{
712 QString str = QString("ImageIconDescriptor ");
713 str += QString("tag(0x%1) ").arg(DescriptorTag(),2,16,QChar('0'));
714 str += QString("length(%1) ").arg(DescriptorLength());
715 str += QString("extension(0x%1) ").arg(DescriptorTagExtension(),2,16,QChar('0'));
716 str += QString("number %1/%2").arg(DescriptorNumber()).arg(LastDescriptorNumber());
717 //
718 // TBD
719 //
720 str.append(" Dumping\n");
721 str.append(hexdump());
722 return str;
723}
724
725// 0x7F 0x04
727{
728 m_cellPtrs.clear();
729 m_subCellPtrs.clear();
730
731 const unsigned char *cp = m_data + 8;
732 for (uint i=0; (cp - m_data + 4) < DescriptorLength(); i++)
733 {
734 m_cellPtrs.push_back(cp);
735 cp += TFSFlag() ? (2 + 1 + FrequencyLoopLength(i)) : (2 + 4);
736 m_subCellPtrs.push_back(cp);
737 cp += 1 + SubcellInfoLoopLength(i);
738 }
739}
740
742{
743 QString str = QString("T2DeliverySystemDescriptor ");
744 str += QString("tag(0x%1) ").arg(DescriptorTag(),2,16,QChar('0'));
745 str += QString("length(%1) ").arg(DescriptorLength());
746 str += QString("extension(0x%1) ").arg(DescriptorTagExtension(),2,16,QChar('0'));
747 str += QString("plp_id(%1) ").arg(PlpID());
748 str += QString("T2_system_id(%1)").arg(T2SystemID());
749 if (DescriptorLength() > 4)
750 {
751 str += QString("\n %1 ").arg(SisoMisoString());
752 str += QString("BW=%1MHz ").arg(BandwidthString());
753 str += QString("GI=%1 ").arg(GuardIntervalString());
754 str += QString("TransMode=%1 ").arg(TransmissionModeString());
755 str += QString("OF=%1 ").arg(OtherFrequencyFlag());
756 str += QString("TFS=%1 ").arg(TFSFlag());
757 }
758 if (DescriptorLength() > 6)
759 {
760 for (uint i=0; i < NumCells(); i++)
761 {
762 str += QString("\n ");
763 str += QString("cell_id:%1 ").arg(CellID(i));
764 str += QString("centre_frequency:");
765 if (TFSFlag())
766 {
767 for (uint j=0; j<FrequencyLoopLength(i)/4; j++)
768 {
769 str += QString(" %1").arg(CentreFrequency(i,j));
770 }
771 }
772 else
773 {
774 str += QString(" %1").arg(CentreFrequency(i));
775 }
776 for (uint j=0; j<SubcellInfoLoopLength(i)/5; j++)
777 {
778 str += QString("\n ");
779 str += QString("cell_id_extension:%1 ").arg(CellIDExtension(i,j));
780 str += QString("transposer_frequency:%1").arg(TransposerFrequency(i,j));
781 }
782 }
783 }
784 str.append(" Dumping\n");
785 str.append(hexdump());
786 return str;
787}
788
789// 0x7F 0x05
791{
792 QString str = QString("SHDeliverySystemDescriptor ");
793 str += QString("tag(0x%1 ").arg(DescriptorTag(),2,16,QChar('0'));
794 str += QString("length(%1) ").arg(DescriptorLength());
795 str += QString("0x%1) ").arg(DescriptorTagExtension(),2,16,QChar('0'));
796 //
797 // TBD
798 //
799 str.append(" Dumping\n");
800 str.append(hexdump());
801 return str;
802}
803
804// 0x7F 0x06
806{
807 QString str = QString("SupplementaryAudioDescriptor ");
808 str += QString("(0x%1 ").arg(DescriptorTag(),2,16,QChar('0'));
809 str += QString("0x%1) ").arg(DescriptorTagExtension(),2,16,QChar('0'));
810 str += QString("length(%1)").arg(DescriptorLength());
811 str += QString("\n ");
812 str += QString("mix_type(%1) ").arg(MixType());
813 str += QString("editorial_classification(%1)").arg(EditorialClassification());
814 str += QString("\n ");
815 str += QString("language_code_present(%1)").arg(LanguageCodePresent());
817 {
818 str += QString(" language_code(%1)").arg(LanguageString());
819 }
820 //
821 str.append(" Dumping\n");
822 str.append(hexdump());
823 return str;
824}
825
826// 0x7F 0x07
828{
829 QString str = QString("NetworkChangeNotiyDescriptor ");
830 str += QString("(0x%1 ").arg(DescriptorTag(),2,16,QChar('0'));
831 str += QString("0x%1) ").arg(DescriptorTagExtension(),2,16,QChar('0'));
832 //
833 str.append(" Dumping\n");
834 str.append(hexdump());
835 return str;
836}
837
838// 0x7F 0x08
840{
841 QString str = QString("MessageDescriptor ");
842 str += QString("(0x%1 ").arg(DescriptorTag(),2,16,QChar('0'));
843 str += QString("0x%1) ").arg(DescriptorTagExtension(),2,16,QChar('0'));
844 str += QString("length(%1)").arg(DescriptorLength());
845 str += QString("\n ");
846 str += QString("message_id(%1) ").arg(MessageID());
847 str += QString("language_code(%1)").arg(LanguageString());
848 str += QString("\n ");
849 str += QString("text_char(\"%1\")").arg(Message());
850 //
851 str.append(" Dumping\n");
852 str.append(hexdump());
853 return str;
854}
855
856// 0x7F 0x09
858{
859 QString str = QString("TargetRegionDescriptor ");
860 str += QString("(0x%1 ").arg(DescriptorTag(),2,16,QChar('0'));
861 str += QString("0x%1) ").arg(DescriptorTagExtension(),2,16,QChar('0'));
862 str += QString("length(%1)").arg(DescriptorLength());
863 str += QString("\n ");
864 str += QString("country_code(%1) ").arg(CountryCodeString());
865 //
866 // TBD
867 //
868 str.append(" Dumping\n");
869 str.append(hexdump());
870 return str;
871}
872
873// 0x7F 0x0A
875{
876 QString str = QString("TargetRegionNameDescriptor ");
877 str += QString("(0x%1 ").arg(DescriptorTag(),2,16,QChar('0'));
878 str += QString("0x%1) ").arg(DescriptorTagExtension(),2,16,QChar('0'));
879 str += QString("length(%1)").arg(DescriptorLength());
880 str += QString("\n ");
881 str += QString("country_code(%1) ").arg(CountryCodeString());
882 str += QString("language_code(%1)").arg(LanguageString());
883 //
884 // TBD
885 //
886 str.append(" Dumping\n");
887 str.append(hexdump());
888 return str;
889}
890
891// 0x7F 0x0B
893{
894 QString str = QString("ServiceRelocatedDescriptor ");
895 str += QString("(0x%1 ").arg(DescriptorTag(),2,16,QChar('0'));
896 str += QString("0x%1) ").arg(DescriptorTagExtension(),2,16,QChar('0'));
897 str += QString("length(%1)").arg(DescriptorLength());
898 str += QString("\n ");
899 str += QString("old_original_network_id(%1) ").arg(OldOriginalNetworkID());
900 str += QString("old_transport_id(%1) ").arg(OldTransportID());
901 str += QString("old_service_id(%1) ").arg(OldServiceID());
902 //
903 str.append(" Dumping\n");
904 str.append(hexdump());
905 return str;
906}
907
908// 0x7F 0x0D
910{
911 QString str = QString("C2DeliverySystemDescriptor ");
912 str += QString("(0x%1 ").arg(DescriptorTag(),2,16,QChar('0'));
913 str += QString("0x%1) ").arg(DescriptorTagExtension(),2,16,QChar('0'));
914 str += QString("length(%1)").arg(DescriptorLength());
915 //
916 // TBD
917 //
918 str.append(" Dumping\n");
919 str.append(hexdump());
920 return str;
921}
922
923// 0x7F 0x17
925{
926 QString str = QString("S2XSatelliteDeliverySystemDescriptor ");
927 str += QString("(0x%1 ").arg(DescriptorTag(),2,16,QChar('0'));
928 str += QString("0x%1) ").arg(DescriptorTagExtension(),2,16,QChar('0'));
929 str += QString("length(%1)").arg(DescriptorLength());
930 //
931 // TBD
932 //
933 str.append(" Dumping\n");
934 str.append(hexdump());
935 return str;
936}
937
939{
940 QString ret = "UKChannelListDescriptor sid->chan_num: ";
941 for (uint i = 0; i < ChannelCount(); i++)
942 {
943 ret += QString("%1->%2").arg(ServiceID(i)).arg(ChannelNumber(i));
944 if (i+1 < ChannelCount())
945 {
946 if ((i+4)%10)
947 ret += ", ";
948 else
949 ret += ",\n ";
950 }
951 }
952 return ret;
953}
954
956{
957 QString ret = "DVBSimulcastChannelDescriptor sid->chan_num: ";
958 for (uint i = 0; i < ChannelCount(); i++)
959 {
960 ret += QString("%1->%2").arg(ServiceID(i)).arg(ChannelNumber(i));
961 if (i+1 < ChannelCount())
962 {
963 if ((i+3)%10)
964 ret += ", ";
965 else
966 ret += ",\n ";
967 }
968 }
969 return ret;
970}
971
973{
974 QString ret = "Sky Logical Channel Number Descriptor ";
975 ret += QString("(0x%1) ").arg(DescriptorTag(),2,16,QChar('0'));
976 ret += QString("length(%1)").arg(DescriptorLength());
977
978 ret += QString("\n RegionID (%1) (0x%2) Raw (0x%3)")
979 .arg(RegionID()).arg(RegionID(),4,16,QChar('0')).arg(RegionRaw(),4,16,QChar('0'));
980
981 for (size_t i=0; i<ServiceCount(); i++)
982 {
983 ret += QString("\n ServiceID (%1) (0x%2) ").arg(ServiceID(i)).arg(ServiceID(i),4,16,QChar('0'));
984 ret += QString("ServiceType (0x%1) ").arg(ServiceType(i),2,16,QChar('0'));
985 ret += QString("LCN (%1) ").arg(LogicalChannelNumber(i));
986 ret += QString("ChannelID(0x%1) ").arg(ChannelID(i),4,16,QChar('0'));
987 ret += QString("Flags(0x%1) ").arg(Flags(i),4,16,QChar('0'));
988 }
989
990 return ret;
991}
992
994{
995 QString ret = "Freesat Logical Channel Number Descriptor ";
996 ret += QString("(0x%1)").arg(DescriptorTag(),2,16,QChar('0'));
997 ret += QString(" length(%1)").arg(DescriptorLength());
998
999 for (size_t i=0; i<ServiceCount(); i++)
1000 {
1001 ret += QString("\n ServiceID (%1) (0x%2) ").arg(ServiceID(i)).arg(ServiceID(i),4,16,QChar('0'));
1002 ret += QString("ChanID (0x%1)").arg(ChanID(i), 4, 16, QChar('0'));
1003 for (uint j=0; j<LCNCount(i); j++)
1004 {
1005 ret += QString("\n LCN: %1 Region: %2").arg(LogicalChannelNumber(i,j),3).arg(RegionID(i,j));
1006 }
1007 }
1008 return ret;
1009}
1010
1012{
1013 QString ret = "Freesat Region Descriptor ";
1014 ret += QString("(0x%1)").arg(DescriptorTag(),2,16,QChar('0'));
1015 ret += QString(" length(%1)").arg(DescriptorLength());
1016
1017 for (uint i=0; i<RegionCount(); ++i)
1018 {
1019 uint region_id = RegionID(i);
1020 QString language = Language(i);
1021 QString region_name = RegionName(i);
1022 ret += QString("\n Region (%1) (%2) '%3'")
1023 .arg(region_id,2).arg(language, region_name);
1024 }
1025 return ret;
1026}
1027
1029{
1030 QString ret = QString("Freesat Callsign Descriptor ");
1031 ret += QString("tag(0x%1) ").arg(DescriptorTag(),2,16,QChar('0'));
1032 ret += QString("length(%1)").arg(DescriptorLength());
1033 ret += QString(" (%1) '%2'").arg(Language(), Callsign());
1034 return ret;
1035}
1036
1038{
1039 QString ret = QString("OpenTV ChannelList Descriptor region: %1 sid->chan_num(id): ").arg(RegionID());
1040 for (uint i = 0; i < ChannelCount(); i++)
1041 {
1042 ret += QString("%1->%2(%3)").arg(ServiceID(i)).arg(ChannelNumber(i)).arg(ChannelID(i));
1043 ret += (i+1<ChannelCount()) ? ", " : "";
1044 }
1045 return ret;
1046}
1047
1049{
1050 QString ret = QString("ApplicationSignallingDescriptor ");
1051 ret += QString("tag(0x%1) ").arg(DescriptorTag(),2,16,QChar('0'));
1052 ret += QString("length(%1)").arg(DescriptorLength());
1053 for (uint i = 0; i < Count(); ++i)
1054 {
1055 ret += "\n ";
1056 ret += QString("application_type(%1) ").arg(ApplicationType(i));
1057 ret += QString("AIT_version_number(%1)").arg(AITVersionNumber(i));
1058 }
1059 return ret;
1060}
1061
1063{
1064 QString ret = QString("CAIdentifierDescriptor ");
1065 for (uint i = 0; i < CASystemCount(); ++i)
1066 {
1067 ret += QString("ca_system_id(0x%1) ")
1068 .arg(CASystemId(i), 0, 16);
1069 }
1070 return ret;
1071}
1072
1074{
1075 QString ret = QString("DataBroadcastDescriptor: "
1076 "data_broadcast_id(%1) "
1077 "component_tag(%1) ")
1078 .arg(DataBroadcastId(), 0, 10)
1079 .arg(DataComponentTag(), 0, 10);
1080
1081 ret += QString("selector(0x ");
1082 for (uint i = 0; i < SelectorLength(); i++)
1083 ret += QString("%1 ").arg(Selector()[i], 0, 16);
1084 ret += ") ";
1085
1086 ret += QString("ISO_639_language_code(%1) ")
1087 .arg(LanguageString());
1088
1089 ret += QString("text(%1) ") + Text();
1090
1091 return ret;
1092}
1093
1095{
1096 QString ret = QString("LocalTimeOffsetDescriptor ");
1097 uint count = Count();
1098 for (uint i = 0; i < count; ++i)
1099 {
1100 ret += QString("country_code(%1) country_region_id(0x%2) "
1101 "local_time_offset_with_polarity(%3) "
1102 "time_of_change(TODO)")
1103 .arg(CountryCodeString(i))
1104 .arg(CountryRegionId(i), 0, 16)
1106 // TODO add time of change
1107 }
1108 return ret;
1109}
1110
1112{
1113 QString ret = QString("NVODReferenceDescriptor ");
1114 for (uint i = 0; i < Count(); ++i)
1115 {
1116 ret += QString("transport_stream_id(0x%1) original_network_id(0x%2) "
1117 "service_id(0x%3) ")
1118 .arg(TransportStreamId(i), 0, 16)
1119 .arg(OriginalNetworkId(i), 0, 16)
1120 .arg(ServiceId(i), 0, 16);
1121 }
1122 return ret;
1123}
1124
1126{
1127 return QString("PartialTransportStreamDescriptor peak_rate(%1) "
1128 "min_overall_smooth_rate(%2) max_overall_smooth_buf(3)")
1129 .arg(PeakRate()).arg(SmoothRate()).arg(SmoothBuf());
1130}
1131
1132QString AC3Descriptor::toString(void) const
1133{
1134 QString ret = QString("AC-3 Descriptor ");
1135 ret += QString("tag(%1) length(%2) ").arg(DescriptorTag(), DescriptorLength());
1136 if (HasComponentType())
1137 ret += QString("type(0x%1) ").arg(ComponentType(), 2, 16, QChar('0'));
1138 if (HasBSID())
1139 ret += QString("bsid(0x%1) ").arg(BSID(), 2, 16, QChar('0'));
1140 if (HasMainID())
1141 ret += QString("mainid(0x%1) ").arg(MainID(), 2, 16, QChar('0'));
1142 if (HasASVC())
1143 ret += QString("asvc(0x%1) ").arg(ASVC(), 2, 16, QChar('0'));
1144 return ret;
1145}
1146
1147QMultiMap<QString,QString> ExtendedEventDescriptor::Items(void) const
1148{
1149 QMultiMap<QString, QString> ret;
1150
1151 uint index = 0;
1152
1153 /* handle all items
1154 * minimum item size is for 8bit length + 8bit length
1155 */
1156 while (LengthOfItems() - index >= 2)
1157 {
1158 QString item_description = dvb_decode_text (&m_data[8 + index], m_data[7 + index]);
1159 index += 1 + m_data[7 + index];
1160 QString item = dvb_decode_text (&m_data[8 + index], m_data[7 + index]);
1161 index += 1 + m_data[7 + index];
1162 ret.insert (item_description, item);
1163 }
1164
1165 return ret;
1166}
QString toString(void) const override
bool HasComponentType(void) const
bool HasBSID(void) const
bool HasMainID(void) const
uint BSID(void) const
uint ComponentType(void) const
uint MainID(void) const
uint ASVC(void) const
bool HasASVC(void) const
QString toString(void) const override
uint AITVersionNumber(uint i) const
uint ApplicationType(uint i) const
QString toString(void) const override
uint CASystemCount(void) const
QString toString(void) const override
int CASystemId(uint i) const
unsigned long long FrequencyHz(void) const
QString toString(void) const override
QString FECOuterString(void) const
QString ModulationString(void) const
QString FECInnerString(void) const
uint Count(void) const
static volatile bool s_categoryDescExists
uint Nibble(uint i) const
ProgramInfo::CategoryType GetMythCategory(uint i) const
static QMap< uint, QString > s_categoryDesc
static QMutex s_categoryLock
QString GetDescription(uint i) const
QString toString(void) const override
static void Init(void)
uint Nibble1(uint i) const
QString toString(void) const override
uint ChannelNumber(uint i) const
uint ServiceID(uint i) const
QString toString(void) const override
uint ChannelNumber(uint i) const
QString toString(void) const override
uint DataBroadcastId(void) const
QString LanguageString(void) const
const unsigned char * Selector(void) const
uint DataComponentTag(void) const
QString Text(void) const
uint SelectorLength(void) const
uint LengthOfItems(void) const
QMultiMap< QString, QString > Items(void) const
QString Callsign(void) const
QString toString(void) const override
QString Language(void) const
uint ChanID(size_t i) const
uint LCNCount(size_t i) const
uint ServiceCount(void) const
QString toString(void) const override
uint ServiceID(size_t i) const
uint LogicalChannelNumber(size_t i, size_t j) const
uint RegionID(size_t i, size_t j) const
QString Language(uint i) const
QString RegionName(uint i) const
int RegionID(uint i) const
QString toString(void) const override
uint RegionCount(void) const
QString toString(void) const override
unsigned long long FrequencyHz(uint i) const
QString toString(void) const override
uint LastDescriptorNumber(void) const
uint DescriptorNumber(void) const
uint LinkageType(void) const
QString LinkageTypeString(void) const
QString MobileHandOverTypeString(void) const
uint MobileHandOverType(void) const
int LocalTimeOffsetWithPolarity(uint i) const
QString CountryCodeString(uint i) const
QString toString(void) const override
uint CountryRegionId(uint i) const
uint DescriptorLength(void) const
QString hexdump(void) const
uint DescriptorTag(void) const
uint DescriptorTagExtension(void) const
const unsigned char * m_data
QString LanguageString(void) const
QString toString(void) const override
QString Message(void) const
uint MessageID(void) const
QString toString(void) const override
uint TransportStreamId(uint i) const
uint ServiceId(uint i) const
uint OriginalNetworkId(uint i) const
uint Count(void) const
QString toString(void) const override
QString toString(void) const override
uint ChannelID(uint i) const
uint ServiceID(uint i) const
uint ChannelNumber(uint i) const
QString toString(void) const override
QString toString(void) const override
QString toString(void) const override
QString toString(void) const override
uint64_t FrequencykHz(void) const
QString toString(void) const override
QString OrbitalPositionString(void) const
QString FECInnerString(void) const
QString ModulationString(void) const
QString ModulationSystemString(void) const
uint ServiceType(void) const
bool IsDigitalAudio(void) const
bool IsTeletext(void) const
QString toString(void) const
bool IsUHDTV(void) const
uint OldOriginalNetworkID(void) const
uint OldTransportID(void) const
uint OldServiceID(void) const
QString toString(void) const override
uint ServiceType(size_t i) const
uint RegionRaw(void) const
uint Flags(size_t i) const
uint ChannelID(size_t i) const
QString toString(void) const override
uint RegionID(void) const
uint ServiceCount(void) const
uint LogicalChannelNumber(size_t i) const
uint ServiceID(size_t i) const
QString LanguageString(uint i) const
uint AncillaryPageID(uint i) const
uint SubtitleType(uint i) const
uint CompositionPageID(uint i) const
QString toString(void) const override
uint StreamCount(void) const
QString LanguageString(void) const
uint EditorialClassification(void) const
QString toString(void) const override
uint LanguageCodePresent(void) const
QString toString(void) const override
uint TransposerFrequency(uint i, uint j) const
QString TransmissionModeString(void) const
std::vector< const unsigned char * > m_subCellPtrs
uint SubcellInfoLoopLength(uint i) const
QString GuardIntervalString(void) const
uint CellIDExtension(uint i, uint j) const
QString SisoMisoString(void) const
std::vector< const unsigned char * > m_cellPtrs
uint OtherFrequencyFlag(void) const
QString BandwidthString(void) const
uint FrequencyLoopLength(uint i) const
uint CentreFrequency(uint i) const
uint CellID(uint i) const
QString CountryCodeString(void) const
QString toString(void) const override
QString toString(void) const override
QString LanguageString(void) const
QString CountryCodeString(void) const
uint TeletextPageNum(uint i) const
uint StreamCount(void) const
uint TeletextMagazineNum(uint i) const
QString toString(void) const override
QString LanguageString(uint i) const
uint TeletextType(uint i) const
QString toString(void) const override
QString ConstellationString(void) const
QString TransmissionModeString(void) const
unsigned int uint
Definition: compat.h:60
static QString iconv_helper(int which, char *buf, size_t length)
static QString decode_text(const unsigned char *buf, uint length)
static QString decode_iso6937(const unsigned char *buf, uint length)
QString dvb_decode_short_name(const unsigned char *src, uint raw_length)
QString dvb_decode_text(const unsigned char *src, uint raw_length, const enc_override &encoding_override)
const std::array< const std::string, 14 > linkage_types
std::vector< uint8_t > enc_override
QString freesat_huffman_to_string(const unsigned char *compressed, uint size)
const iso6937table iso6937table_base
const std::array< const iso6937table *, 256 > iso6937table_secondary
unsigned short uint16_t
Definition: iso6937tables.h:3
std::array< const uint16_t, 256 > iso6937table
Definition: iso6937tables.h:4
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
MBASE_PUBLIC long long copy(QFile &dst, QFile &src, uint block_size=0)
Copies src file to dst file.
QString myth_category_type_to_string(ProgramInfo::CategoryType category_type)