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