File indexing completed on 2024-05-12 04:52:19

0001 /*
0002  * dvbsi.cpp
0003  *
0004  * Copyright (C) 2008-2011 Christoph Pfister <christophpfister@gmail.com>
0005  *
0006  * This program is free software; you can redistribute it and/or modify
0007  * it under the terms of the GNU General Public License as published by
0008  * the Free Software Foundation; either version 2 of the License, or
0009  * (at your option) any later version.
0010  *
0011  * This program is distributed in the hope that it will be useful,
0012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0014  * GNU General Public License for more details.
0015  *
0016  * You should have received a copy of the GNU General Public License along
0017  * with this program; if not, write to the Free Software Foundation, Inc.,
0018  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
0019  */
0020 
0021 #include "../log.h"
0022 
0023 #include <QTextCodec>
0024 
0025 #include "dvbsi.h"
0026 
0027 void DvbSection::initSection(const char *data, int size)
0028 {
0029     if (size < 3) {
0030         initSectionData();
0031         return;
0032     }
0033 
0034     int sectionLength = ((((quint8(data[1]) & 0xf) << 8) | quint8(data[2])) + 3);
0035 
0036     if (sectionLength > size) {
0037         qCInfo(logDvbSi, "Adjusting length");
0038         sectionLength = size;
0039     }
0040 
0041     initSectionData(data, sectionLength, size);
0042 }
0043 
0044 int DvbStandardSection::verifyCrc32(const char *data, int size)
0045 {
0046     unsigned int crc32 = 0xffffffff;
0047 
0048     for (int i = 0; i < size; ++i) {
0049         crc32 = ((crc32 << 8) ^ crc32Table[(crc32 >> 24) ^ quint8(data[i])]);
0050     }
0051 
0052     return crc32;
0053 }
0054 
0055 /*
0056  * unsigned int crc32TableValue(int index)
0057  * {
0058  *  unsigned int value = 0;
0059  *
0060  *  for (int i = 8; i >= 0; --i) {
0061  *      if (((value & 0x80000000) != 0) ^ ((index & (1 << i)) != 0)) {
0062  *          value = (value << 1) ^ 0x04c11db7;
0063  *      } else {
0064  *          value <<= 1;
0065  *      }
0066  *  }
0067  *
0068  *  return value;
0069  * }
0070  */
0071 
0072 const unsigned int DvbStandardSection::crc32Table[] =
0073 {
0074     0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
0075     0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
0076     0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
0077     0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
0078     0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9,
0079     0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
0080     0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011,
0081     0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
0082     0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
0083     0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
0084     0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81,
0085     0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
0086     0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49,
0087     0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
0088     0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
0089     0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
0090     0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae,
0091     0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
0092     0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
0093     0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
0094     0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
0095     0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
0096     0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066,
0097     0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
0098     0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e,
0099     0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
0100     0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
0101     0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
0102     0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
0103     0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
0104     0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686,
0105     0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
0106     0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
0107     0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
0108     0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f,
0109     0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
0110     0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47,
0111     0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
0112     0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
0113     0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
0114     0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7,
0115     0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
0116     0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f,
0117     0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
0118     0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
0119     0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
0120     0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f,
0121     0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
0122     0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
0123     0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
0124     0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
0125     0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
0126     0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30,
0127     0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
0128     0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088,
0129     0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
0130     0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
0131     0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
0132     0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
0133     0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
0134     0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0,
0135     0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
0136     0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
0137     0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
0138 };
0139 
0140 void DvbStandardSection::initStandardSection(const char *data, int size)
0141 {
0142     if (size < 12) {
0143         initSectionData();
0144         return;
0145     }
0146 
0147     initSection(data, size);
0148 }
0149 
0150 class Iso6937Codec : public QTextCodec
0151 {
0152 public:
0153     Iso6937Codec() { }
0154     ~Iso6937Codec() { }
0155 
0156     QByteArray name() const override
0157     {
0158         return "ISO 6937"; // actually a superset of ISO 6937
0159     }
0160 
0161     int mibEnum() const override
0162     {
0163         return 14;
0164     }
0165 
0166     QByteArray convertFromUnicode(const QChar *, int, QTextCodec::ConverterState *) const override
0167     {
0168         return QByteArray();
0169     }
0170 
0171     QString convertToUnicode(const char *input, int size, QTextCodec::ConverterState *) const override
0172     {
0173         QString result;
0174         unsigned short diacriticalMark = 0;
0175 
0176         for (; size > 0; ++input, --size) {
0177             unsigned short value = table[quint8(*input)];
0178 
0179             if (value == 0xffff) {
0180                 continue;
0181             }
0182 
0183             if ((value & 0xff00) == 0x0300) {
0184                 // diacritical mark
0185                 diacriticalMark = value;
0186                 continue;
0187             }
0188 
0189             result.append(value);
0190 
0191             if (diacriticalMark != 0) {
0192                 result.append(diacriticalMark);
0193                 diacriticalMark = 0;
0194             }
0195         }
0196 
0197         return result.normalized(QString::NormalizationForm_C);
0198     }
0199 
0200 private:
0201     static const unsigned short table[];
0202 };
0203 
0204 const unsigned short Iso6937Codec::table[] = {
0205     0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
0206     0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
0207     0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
0208     0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
0209     0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
0210     0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
0211     0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
0212     0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
0213     0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
0214     0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
0215     0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
0216     0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
0217     0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
0218     0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
0219     0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
0220     0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
0221     0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0222     0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0223     0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0224     0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0225     0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x20ac, 0x00a5, 0xffff, 0x00a7,
0226     0x00a4, 0x2018, 0x201c, 0x00ab, 0x2190, 0x2191, 0x2192, 0x2193,
0227     0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00d7, 0x00b5, 0x00b6, 0x00b7,
0228     0x00f7, 0x2019, 0x201d, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
0229     0xffff, 0x0300, 0x0301, 0x0302, 0x0303, 0x0304, 0x0306, 0x0307,
0230     0x0308, 0xffff, 0x030a, 0x0327, 0xffff, 0x030b, 0x0328, 0x030c,
0231     0x2015, 0x00b9, 0x00ae, 0x00a9, 0x2122, 0x266a, 0x00ac, 0x00a6,
0232     0xffff, 0xffff, 0xffff, 0xffff, 0x215b, 0x215c, 0x215d, 0x215e,
0233     0x2126, 0x00c6, 0x0110, 0x00aa, 0x0126, 0xffff, 0x0132, 0x013f,
0234     0x0141, 0x00d8, 0x0152, 0x00ba, 0x00de, 0x0166, 0x014a, 0x0149,
0235     0x0138, 0x00e6, 0x0111, 0x00f0, 0x0127, 0x0131, 0x0133, 0x0140,
0236     0x0142, 0x00f8, 0x0153, 0x00df, 0x00fe, 0x0167, 0x014b, 0x00ad
0237 };
0238 
0239 QString DvbSiText::convertText(const char *data, int size)
0240 {
0241     TextEncoding encoding = Iso6937;
0242 
0243     if (size < 1) {
0244         return QString();
0245     }
0246 
0247     if (size >2 && data[0] == 0x0e && data[size - 1] == 0x0f ) {
0248         // Remove LS0 and LS1 codes found on some ISDB-T streams
0249         data++;
0250         size -= 2;
0251 
0252         encoding = Iso8859_1;
0253     }
0254 
0255     if (override6937)
0256         encoding = Iso8859_1;
0257 
0258     if (quint8(data[0]) < 0x20) {
0259         switch (data[0]) {
0260         case 0x00: encoding = Iso6937; break;
0261         case 0x01: encoding = Iso8859_5; break;
0262         case 0x02: encoding = Iso8859_6; break;
0263         case 0x03: encoding = Iso8859_7; break;
0264         case 0x04: encoding = Iso8859_8; break;
0265         case 0x05: encoding = Iso8859_9; break;
0266         case 0x06: encoding = Iso8859_10; break;
0267         case 0x07: encoding = Iso8859_11; break;
0268         case 0x09: encoding = Iso8859_13; break;
0269         case 0x0a: encoding = Iso8859_14; break;
0270         case 0x0b: encoding = Iso8859_15; break;
0271         case 0x11: encoding = Iso10646_ucs2; break;
0272         case 0x12: encoding = Iso2022_kr; break;
0273         case 0x13: encoding = Gb2312; break;
0274         case 0x14: encoding = Utf_16be; break;
0275         case 0x15: encoding = Utf_8; break;
0276         case 0x10: {
0277             if (size < 3) {
0278                 return QString();
0279             }
0280 
0281             if (data[1] != 0) {
0282                 return QString();
0283             }
0284 
0285             switch (data[2]) {
0286             case 0x01: encoding = Iso8859_1; break;
0287             case 0x02: encoding = Iso8859_2; break;
0288             case 0x03: encoding = Iso8859_3; break;
0289             case 0x04: encoding = Iso8859_4; break;
0290             case 0x05: encoding = Iso8859_5; break;
0291             case 0x06: encoding = Iso8859_6; break;
0292             case 0x07: encoding = Iso8859_7; break;
0293             case 0x08: encoding = Iso8859_8; break;
0294             case 0x09: encoding = Iso8859_9; break;
0295             case 0x0a: encoding = Iso8859_10; break;
0296             case 0x0b: encoding = Iso8859_11; break;
0297             case 0x0d: encoding = Iso8859_13; break;
0298             case 0x0e: encoding = Iso8859_14; break;
0299             case 0x0f: encoding = Iso8859_15; break;
0300             default:
0301                 return QString();
0302             }
0303 
0304             data += 2;
0305             size -= 2;
0306             break;
0307             }
0308         }
0309 
0310         data++;
0311         size--;
0312     }
0313 
0314     if (codecTable[encoding] == NULL) {
0315         QTextCodec *codec = NULL;
0316 
0317         switch (encoding) {
0318         case Iso6937: codec = new Iso6937Codec(); break;
0319         case Iso8859_1: codec = QTextCodec::codecForName("ISO 8859-1"); break;
0320         case Iso8859_2: codec = QTextCodec::codecForName("ISO 8859-2"); break;
0321         case Iso8859_3: codec = QTextCodec::codecForName("ISO 8859-3"); break;
0322         case Iso8859_4: codec = QTextCodec::codecForName("ISO 8859-4"); break;
0323         case Iso8859_5: codec = QTextCodec::codecForName("ISO 8859-5"); break;
0324         case Iso8859_6: codec = QTextCodec::codecForName("ISO 8859-6"); break;
0325         case Iso8859_7: codec = QTextCodec::codecForName("ISO 8859-7"); break;
0326         case Iso8859_8: codec = QTextCodec::codecForName("ISO 8859-8"); break;
0327         case Iso8859_9: codec = QTextCodec::codecForName("ISO 8859-9"); break;
0328         case Iso8859_10: codec = QTextCodec::codecForName("ISO 8859-10"); break;
0329         case Iso8859_11: codec = QTextCodec::codecForName("ISO 8859-11"); break;
0330         case Iso8859_13: codec = QTextCodec::codecForName("ISO 8859-13"); break;
0331         case Iso8859_14: codec = QTextCodec::codecForName("ISO 8859-14"); break;
0332         case Iso8859_15: codec = QTextCodec::codecForName("ISO 8859-15"); break;
0333         case Iso10646_ucs2: codec = QTextCodec::codecForName("UTF-16"); break;
0334         case Iso2022_kr: codec = QTextCodec::codecForName("ISO 2022-KR"); break;
0335         case Gb2312: codec = QTextCodec::codecForName("GB2312"); break;
0336         case Utf_16be: codec = QTextCodec::codecForName("UTF-16BE"); break;
0337         case Utf_8: codec = QTextCodec::codecForName("UTF-8"); break;
0338         }
0339 
0340         Q_ASSERT(codec != NULL);
0341         codecTable[encoding] = codec;
0342     }
0343 
0344     if (encoding <= Iso8859_15) {
0345         // only strip control codes for one-byte character tables
0346 
0347         char *dest = new char[size];
0348         char *destIt = dest;
0349 
0350         for (const char *it = data; it != (data + size); ++it) {
0351             unsigned char value = *it;
0352 
0353             if ((value < 0x80) || (value > 0x9f)) {
0354                 *(destIt++) = value;
0355             }
0356         }
0357 
0358         QString result = codecTable[encoding]->toUnicode(dest, int(destIt - dest));
0359         delete[] dest;
0360 
0361         return result;
0362     }
0363 
0364     return codecTable[encoding]->toUnicode(data, size);
0365 }
0366 
0367 void DvbSiText::setOverride6937(bool override)
0368 {
0369     override6937 = override;
0370 }
0371 
0372 QTextCodec *DvbSiText::codecTable[EncodingTypeMax + 1] = { NULL };
0373 bool DvbSiText::override6937 = false;
0374 
0375 void DvbDescriptor::initDescriptor(const char *data, int size)
0376 {
0377     if (size < 2) {
0378         if (size != 0) {
0379             qCInfo(logDvbSi, "Invalid descriptor");
0380         }
0381 
0382         initSectionData();
0383         return;
0384     }
0385 
0386     int descriptorLength = (quint8(data[1]) + 2);
0387 
0388     if (descriptorLength > size) {
0389         qCInfo(logDvbSi, "Adjusting length");
0390         descriptorLength = size;
0391     }
0392 
0393     initSectionData(data, descriptorLength, size);
0394 }
0395 
0396 QString AtscPsipText::interpretTextData(const char *data, unsigned int len,
0397                     unsigned int mode)
0398 {
0399     // Based on the "mode" values in A/65C Table 6.41, convert
0400     // the data into a string
0401     QString result;
0402 
0403     if ((mode <= 0x06) ||
0404         (mode >= 0x09 && mode <= 0x10) ||
0405         (mode >= 0x20 && mode <= 0x27) ||
0406         (mode >= 0x30 && mode <= 0x33)) {
0407         // Select UNICODE Code range based on mode as leading octet
0408         for (unsigned int i = 0; i < len; i++) {
0409             QChar val = (data[i] | (mode << 8));
0410             result += val;
0411         }
0412     } else if (mode == 0x3f) {
0413         // UTF-16
0414         for (unsigned int i = 0; i < len; i += 2) {
0415             QChar val = ((unsigned char)data[i] * 256) + (unsigned char)data[i+1];
0416             result += val;
0417         }
0418     } else {
0419         // We currently don't support the following:
0420         // 0x3e Standard Compression Scheme for UNICODE (SCSU)
0421         // 0x40/0x41 Taiwan
0422         // 0x48 South Korea
0423         qCInfo(logDvbSi, "Unsupported ATSC Text mode %d", mode);
0424     }
0425     return result;
0426 }
0427 
0428 QString AtscPsipText::convertText(const char *data, int size)
0429 {
0430     QString result;
0431 
0432     if (size < 1) {
0433         return QString();
0434     }
0435 
0436     unsigned int num_strings = quint8(data[0]);
0437 
0438     if (num_strings == 0) {
0439         return result;
0440     }
0441 
0442     // Note that for now we are only supporting the first string sent.  If
0443     // multiple languages are sent, we only grab the first one provided
0444     int offset = 1;
0445 
0446     // First three bytes are the ISO 639 language code
0447     offset += 3;
0448 
0449     if (offset > size) {
0450         qCInfo(logDvbSi, "Adjusting length");
0451         return result;
0452     }
0453 
0454     int num_segments = quint8(data[offset++]);
0455 
0456     for (int j = 0; j < num_segments; j++) {
0457         if ((offset + 3) > size) {
0458             qCInfo(logDvbSi, "Adjusting length");
0459             return result;
0460         }
0461 
0462         int comp_type = quint8(data[offset++]);
0463         int mode = quint8(data[offset++]);
0464         int num_bytes = quint8(data[offset++]);
0465 
0466         if ((offset + num_bytes) > size) {
0467             qCInfo(logDvbSi, "Adjusting length");
0468             return result;
0469         }
0470 
0471         const char *comp_string = (data + offset);
0472 
0473         if (comp_type == 0x00) {
0474             // Uncompressed
0475             result += interpretTextData(comp_string,
0476                             num_bytes, mode);
0477         } else if ((comp_type == 0x01 || comp_type == 0x02) &&
0478                mode == 0x00) {
0479             // Huffman Compression
0480             // As per the spec, only mode 0x00 supports Huffman coding
0481             result +=
0482                 AtscHuffmanString::convertText(comp_string, num_bytes, comp_type);
0483         } else {
0484             qCInfo(logDvbSi, "Unsupported compression / mode %d %d", comp_type, mode);
0485         }
0486 
0487         offset += num_bytes;
0488     }
0489 
0490     return result;
0491 }
0492 
0493 QString AtscHuffmanString::convertText(const char *data_, int length, int table)
0494 {
0495     AtscHuffmanString huffmanstring(data_, length, table);
0496     huffmanstring.decompress();
0497     return huffmanstring.result;
0498 }
0499 
0500 AtscHuffmanString::AtscHuffmanString(const char *data_, int length, int table) : data(data_),
0501     bitsLeft(8 * length)
0502 {
0503     if (table == 1) {
0504         offsets = Huffman1Offsets;
0505         tableBase = Huffman1Tables;
0506     } else {
0507         offsets = Huffman2Offsets;
0508         tableBase = Huffman2Tables;
0509     }
0510 }
0511 
0512 AtscHuffmanString::~AtscHuffmanString() { }
0513 
0514 bool AtscHuffmanString::hasBits()
0515 {
0516     return bitsLeft > 0;
0517 }
0518 
0519 unsigned char AtscHuffmanString::getBit()
0520 {
0521     if (bitsLeft >= 1) {
0522         int shift = (--bitsLeft % 8);
0523         unsigned char value = (data[0] >> shift) & 0x1;
0524 
0525         if (shift == 0) {
0526             data++;
0527         }
0528         return value;
0529     }
0530 
0531     return 0;
0532 }
0533 
0534 unsigned char AtscHuffmanString::getByte()
0535 {
0536     if (bitsLeft >= 8) {
0537         int shift = ((bitsLeft - 1) % 8);
0538         // Note this takes advantage of the fact that there is always
0539         // at least one byte remaining (to avoid a read-past end
0540         // condition)
0541         unsigned char value = ((((data[0] << 8) | quint8(data[1])) >> (shift + 1)) & 0xff);
0542 
0543         bitsLeft -= 8;
0544         data++;
0545         return value;
0546     }
0547 
0548     return 0;
0549 }
0550 
0551 void AtscHuffmanString::decompress()
0552 {
0553     const unsigned char *table = tableBase;
0554 
0555     while (hasBits()) {
0556         int index = 0;
0557 
0558         do {
0559             index = table[2 * index + getBit()];
0560         } while (index < 128);
0561 
0562         index &= 0x7f;
0563 
0564         if (index == 27) {
0565             // escape --> uncompressed character(s)
0566             while (true) {
0567                 index = getByte();
0568 
0569                 if (index < 128) {
0570                     break;
0571                 }
0572 
0573                 result += QChar(index);
0574             }
0575         }
0576 
0577         if (index == 0) {
0578             // end
0579             break;
0580         }
0581 
0582         result += QChar(index);
0583         table = tableBase + offsets[index];
0584     }
0585 }
0586 
0587 const unsigned short AtscHuffmanString::Huffman1Offsets[128] = {
0588     0x0000, 0x003a, 0x003c, 0x003e, 0x0040, 0x0042, 0x0044, 0x0046,
0589     0x0048, 0x004a, 0x004c, 0x004e, 0x0050, 0x0052, 0x0054, 0x0056,
0590     0x0058, 0x005a, 0x005c, 0x005e, 0x0060, 0x0062, 0x0064, 0x0066,
0591     0x0068, 0x006a, 0x006c, 0x006e, 0x0070, 0x0072, 0x0074, 0x0076,
0592     0x0078, 0x00ce, 0x00d2, 0x00d4, 0x00d6, 0x00d8, 0x00da, 0x00dc,
0593     0x00e6, 0x00e8, 0x00ea, 0x00f0, 0x00f2, 0x00f4, 0x0106, 0x0112,
0594     0x0114, 0x011c, 0x0128, 0x0130, 0x0134, 0x0136, 0x0138, 0x013a,
0595     0x013c, 0x013e, 0x0146, 0x0148, 0x014a, 0x014c, 0x014e, 0x0150,
0596     0x0152, 0x0154, 0x017e, 0x0192, 0x01ac, 0x01ba, 0x01d2, 0x01e4,
0597     0x01fa, 0x0206, 0x021e, 0x0226, 0x0232, 0x023e, 0x0252, 0x0264,
0598     0x027a, 0x0294, 0x0298, 0x02a4, 0x02c8, 0x02de, 0x02e6, 0x02f4,
0599     0x0304, 0x0306, 0x030c, 0x0310, 0x0312, 0x0314, 0x0316, 0x0318,
0600     0x031a, 0x031c, 0x0352, 0x036a, 0x038e, 0x03ae, 0x03ee, 0x0406,
0601     0x0428, 0x0444, 0x0472, 0x0476, 0x0490, 0x04be, 0x04d6, 0x050a,
0602     0x0544, 0x0564, 0x0566, 0x059a, 0x05d0, 0x05fc, 0x0622, 0x062c,
0603     0x0646, 0x0654, 0x067c, 0x068a, 0x068c, 0x068e, 0x0690, 0x0692 };
0604 
0605 const unsigned char AtscHuffmanString::Huffman1Tables[] = {
0606     0x1b, 0x1c, 0xb4, 0xa4, 0xb2, 0xb7, 0xda, 0x01,
0607     0xd1, 0x02, 0x03, 0x9b, 0x04, 0xd5, 0xd9, 0x05,
0608     0xcb, 0xd6, 0x06, 0xcf, 0x07, 0x08, 0xca, 0x09,
0609     0xc9, 0xc5, 0xc6, 0x0a, 0xd2, 0xc4, 0xc7, 0xcc,
0610     0xd0, 0xc8, 0xd7, 0xce, 0x0b, 0xc1, 0x0c, 0xc2,
0611     0xcd, 0xc3, 0x0d, 0x0e, 0x0f, 0x10, 0xd3, 0x11,
0612     0xd4, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
0613     0x19, 0x1a, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b,
0614     0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b,
0615     0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b,
0616     0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b,
0617     0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b,
0618     0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b,
0619     0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b,
0620     0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b,
0621     0x29, 0x2a, 0xd8, 0xe5, 0xb9, 0x01, 0xa7, 0xb1,
0622     0xec, 0xd1, 0x02, 0xad, 0xb2, 0xda, 0xe3, 0xb3,
0623     0x03, 0xe4, 0xe6, 0x04, 0x9b, 0xe2, 0x05, 0x06,
0624     0x07, 0x08, 0x09, 0xd5, 0x0a, 0xd6, 0x0b, 0xd9,
0625     0x0c, 0xa6, 0xe9, 0xcb, 0xc5, 0xcf, 0x0d, 0x0e,
0626     0xca, 0xc9, 0x0f, 0xc7, 0x10, 0x11, 0xe1, 0x12,
0627     0x13, 0xc6, 0xd2, 0xc8, 0xce, 0xc1, 0xc4, 0xd0,
0628     0xcc, 0x14, 0x15, 0xef, 0xc2, 0xd7, 0x16, 0xcd,
0629     0x17, 0xf4, 0xd4, 0x18, 0x19, 0x1a, 0xc3, 0xd3,
0630     0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22,
0631     0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x01, 0x80,
0632     0xa0, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0xb1, 0x9b,
0633     0x9b, 0x9b, 0x9b, 0xa0, 0x04, 0xf3, 0xe4, 0xb9,
0634     0x01, 0xf4, 0xa0, 0x9b, 0x02, 0x03, 0x9b, 0x9b,
0635     0x9b, 0x9b, 0x01, 0x02, 0x9b, 0xc1, 0xc8, 0xd3,
0636     0x9b, 0x9b, 0x9b, 0xa0, 0x07, 0x08, 0xb1, 0xd2,
0637     0xd3, 0xd4, 0xd5, 0xad, 0xcd, 0xc1, 0x01, 0x02,
0638     0x03, 0xa0, 0x04, 0x9b, 0x05, 0x06, 0xa0, 0x05,
0639     0xc9, 0xd7, 0xd3, 0x01, 0x02, 0x9b, 0xae, 0x80,
0640     0x03, 0x04, 0x9b, 0x9b, 0x02, 0x03, 0xad, 0x9b,
0641     0x01, 0x80, 0xa0, 0xb0, 0x04, 0x05, 0x80, 0x9b,
0642     0xb1, 0xb2, 0xa0, 0xb0, 0xb9, 0x01, 0x02, 0x03,
0643     0x02, 0x03, 0xb1, 0xba, 0x01, 0xb0, 0x9b, 0x80,
0644     0x80, 0x01, 0xb0, 0x9b, 0x9b, 0xb8, 0x9b, 0x9b,
0645     0x9b, 0x9b, 0x9b, 0xb0, 0x9b, 0xa0, 0x02, 0x03,
0646     0xb1, 0xb3, 0xb9, 0xb0, 0x01, 0x9b, 0x9b, 0xa0,
0647     0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b,
0648     0x9b, 0x80, 0x9b, 0x9b, 0x13, 0x14, 0xaa, 0xad,
0649     0xae, 0xf6, 0xe7, 0xf4, 0xe2, 0xe9, 0x01, 0x02,
0650     0xc2, 0xf0, 0x9b, 0xf3, 0xe3, 0xe6, 0xf7, 0x03,
0651     0xf5, 0x04, 0x05, 0x06, 0xf2, 0x07, 0x08, 0x09,
0652     0x0a, 0x0b, 0x0c, 0xe4, 0xa0, 0x0d, 0xec, 0xee,
0653     0x0e, 0xed, 0x0f, 0x10, 0x11, 0x12, 0x08, 0x09,
0654     0xc1, 0xd3, 0x9b, 0x01, 0xc3, 0x02, 0xe9, 0xec,
0655     0x03, 0xf2, 0xf5, 0x04, 0xef, 0xe1, 0x05, 0xe5,
0656     0x06, 0x07, 0x0b, 0x0c, 0xc1, 0xf9, 0x01, 0xc2,
0657     0xcf, 0xe5, 0xf5, 0x9b, 0xe9, 0x02, 0xa0, 0x03,
0658     0x04, 0x05, 0xf2, 0x06, 0xec, 0x07, 0xe1, 0x08,
0659     0x09, 0xe8, 0x0a, 0xef, 0x05, 0x06, 0xf9, 0x9b,
0660     0x01, 0xf5, 0x02, 0xf2, 0xe9, 0xe5, 0xef, 0x03,
0661     0xe1, 0x04, 0x0a, 0x0b, 0xf1, 0xf5, 0xf3, 0x01,
0662     0xed, 0xf9, 0xc3, 0x02, 0xec, 0xee, 0xe4, 0xf8,
0663     0x03, 0x9b, 0xf6, 0x04, 0x05, 0xe1, 0x06, 0x07,
0664     0x08, 0x09, 0x07, 0x08, 0xa0, 0x9b, 0xcc, 0x01,
0665     0xe5, 0x02, 0xec, 0xf5, 0xef, 0x03, 0xe9, 0xf2,
0666     0x04, 0x05, 0xe1, 0x06, 0x09, 0x0a, 0xae, 0xec,
0667     0xf9, 0xc1, 0xe8, 0x01, 0x9b, 0x02, 0x03, 0x04,
0668     0xe1, 0xf5, 0xe9, 0x05, 0xe5, 0x06, 0xf2, 0xef,
0669     0x07, 0x08, 0xef, 0x05, 0x80, 0x9b, 0xf5, 0x01,
0670     0x02, 0xe9, 0xe1, 0x03, 0xe5, 0x04, 0xee, 0x0b,
0671     0xba, 0xd4, 0xae, 0xf2, 0xe3, 0x01, 0xa0, 0x02,
0672     0x80, 0x9b, 0xed, 0x03, 0xc9, 0xf3, 0xf4, 0x04,
0673     0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x02, 0x03,
0674     0x9b, 0xf5, 0x01, 0xe1, 0xef, 0xe5, 0x05, 0xe9,
0675     0xe1, 0xef, 0xf5, 0xee, 0x9b, 0xe5, 0x01, 0x02,
0676     0x03, 0x04, 0x04, 0x05, 0xa0, 0x9b, 0x01, 0xf5,
0677     0x02, 0xe5, 0xef, 0x03, 0xe1, 0xe9, 0x08, 0x09,
0678     0xaa, 0xd4, 0x01, 0x9b, 0xe3, 0x02, 0xf2, 0x03,
0679     0xe5, 0x04, 0xf5, 0xf9, 0xe9, 0x05, 0xef, 0x06,
0680     0x07, 0xe1, 0xe5, 0x08, 0xce, 0xa0, 0xc6, 0xf5,
0681     0x01, 0x02, 0x9b, 0xc2, 0x03, 0xe1, 0x04, 0xef,
0682     0x05, 0xe9, 0x06, 0x07, 0x09, 0x0a, 0xe4, 0xf3,
0683     0xe6, 0xf6, 0xf7, 0xf0, 0xf2, 0x01, 0xec, 0x02,
0684     0x03, 0xa0, 0x9b, 0x04, 0x05, 0xf5, 0x06, 0x07,
0685     0xee, 0x08, 0x0b, 0x0c, 0xa0, 0xf3, 0xf9, 0xae,
0686     0xd2, 0xc7, 0x01, 0x9b, 0x02, 0xf5, 0x03, 0x04,
0687     0x05, 0xe9, 0xec, 0x06, 0xe5, 0x07, 0xef, 0x08,
0688     0xe1, 0x09, 0xf2, 0x0a, 0x01, 0xf5, 0x9b, 0xd6,
0689     0x04, 0x05, 0xe8, 0x9b, 0x01, 0xf5, 0x02, 0xe1,
0690     0xe9, 0xef, 0x03, 0xe5, 0x10, 0x11, 0xaa, 0xec,
0691     0xf1, 0xae, 0xa0, 0xf7, 0xed, 0xee, 0x01, 0x02,
0692     0x9b, 0xeb, 0x03, 0x04, 0x05, 0x06, 0xe3, 0x07,
0693     0xef, 0x08, 0xe9, 0xf5, 0x09, 0xe1, 0xe5, 0xf0,
0694     0xe8, 0x0a, 0x0b, 0x0c, 0x0d, 0xf4, 0x0e, 0x0f,
0695     0xe8, 0x0a, 0xad, 0xce, 0x9b, 0x01, 0xd6, 0x02,
0696     0xf5, 0xf7, 0x03, 0x04, 0xe1, 0xe5, 0xe9, 0x05,
0697     0xf2, 0x06, 0xef, 0x07, 0x08, 0x09, 0xee, 0x03,
0698     0xec, 0xae, 0x01, 0x9b, 0x02, 0xf0, 0x06, 0xe9,
0699     0xa0, 0xc3, 0xef, 0x9b, 0xe5, 0x01, 0x80, 0x02,
0700     0x03, 0xe1, 0x04, 0x05, 0x06, 0x07, 0xc6, 0xd7,
0701     0x01, 0x9b, 0xf2, 0x02, 0x03, 0xe8, 0xe5, 0xe1,
0702     0x04, 0xe9, 0xef, 0x05, 0x9b, 0x9b, 0x02, 0xef,
0703     0xe1, 0x9b, 0x01, 0xe5, 0x01, 0xef, 0x9b, 0xe1,
0704     0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b,
0705     0x9b, 0x9b, 0x9b, 0x9b, 0x19, 0x1a, 0x9b, 0xba,
0706     0xe5, 0xea, 0xf8, 0x01, 0x02, 0xe6, 0xa7, 0x03,
0707     0xfa, 0xe8, 0x04, 0xf7, 0x05, 0xf5, 0xe2, 0x06,
0708     0xeb, 0x07, 0xf0, 0x08, 0x80, 0xf6, 0xe7, 0x09,
0709     0xe4, 0x0a, 0xa0, 0xe9, 0x0b, 0xe3, 0xf9, 0x0c,
0710     0x0d, 0xed, 0x0e, 0x0f, 0xf3, 0x10, 0x11, 0xec,
0711     0x12, 0xf4, 0xf2, 0x13, 0xee, 0x14, 0x15, 0x16,
0712     0x17, 0x18, 0x0a, 0x0b, 0xf3, 0x9b, 0xf5, 0xe2,
0713     0x01, 0x80, 0xa0, 0x02, 0xe5, 0xf2, 0xe9, 0x03,
0714     0xec, 0x04, 0xf9, 0x05, 0xef, 0x06, 0xe1, 0x07,
0715     0x08, 0x09, 0x10, 0x11, 0xc3, 0xcc, 0xc7, 0x9b,
0716     0xe3, 0x01, 0x80, 0xec, 0xf9, 0x02, 0xf3, 0x03,
0717     0xf5, 0x04, 0x05, 0xf2, 0x06, 0xe9, 0xa0, 0x07,
0718     0x08, 0xef, 0xf4, 0x09, 0x0a, 0xe1, 0x0b, 0xe8,
0719     0xeb, 0xe5, 0x0c, 0x0d, 0x0e, 0x0f, 0x0e, 0x0f,
0720     0xae, 0xf5, 0xf7, 0x01, 0xec, 0x02, 0xe4, 0xe7,
0721     0xf2, 0x03, 0x9b, 0xef, 0x04, 0xf6, 0x05, 0x06,
0722     0xf9, 0xf3, 0x07, 0xe9, 0xe1, 0x08, 0x09, 0x80,
0723     0x0a, 0x0b, 0xe5, 0x0c, 0x0d, 0xa0, 0x1e, 0x1f,
0724     0x9b, 0xa1, 0xad, 0xe8, 0xea, 0xf1, 0xf5, 0xfa,
0725     0x01, 0x02, 0x03, 0x04, 0xba, 0xf8, 0xa7, 0xe2,
0726     0xe9, 0x05, 0x06, 0x07, 0xe6, 0xed, 0xe7, 0xeb,
0727     0x08, 0x09, 0xf6, 0xf0, 0x0a, 0xef, 0x0b, 0xe3,
0728     0x0c, 0x0d, 0x0e, 0xf9, 0x0f, 0xe4, 0xec, 0x10,
0729     0xe5, 0x11, 0xf4, 0xf7, 0x12, 0x13, 0xe1, 0x14,
0730     0x15, 0x16, 0xee, 0xf3, 0x17, 0x80, 0x18, 0x19,
0731     0xf2, 0x1a, 0x1b, 0xa0, 0x1c, 0x1d, 0xa0, 0x0b,
0732     0xf5, 0x9b, 0x01, 0xec, 0xf3, 0xf2, 0x80, 0xe1,
0733     0x02, 0x03, 0xf4, 0xe9, 0xef, 0xe6, 0x04, 0x05,
0734     0x06, 0x07, 0xe5, 0x08, 0x09, 0x0a, 0x0f, 0x10,
0735     0xba, 0xf9, 0xa7, 0xf4, 0x9b, 0x01, 0xe7, 0xec,
0736     0x02, 0xee, 0x03, 0xef, 0xf5, 0x04, 0xf2, 0x05,
0737     0x06, 0xe9, 0x07, 0xf3, 0xe1, 0x08, 0x09, 0x0a,
0738     0x0b, 0xe5, 0x80, 0x0c, 0xe8, 0xa0, 0x0d, 0x0e,
0739     0xe5, 0x0d, 0xe2, 0xf5, 0xf7, 0x9b, 0xec, 0x01,
0740     0xf9, 0xee, 0x02, 0x03, 0x04, 0xf2, 0x05, 0x80,
0741     0x06, 0xa0, 0xe1, 0xef, 0x07, 0xf4, 0xe9, 0x08,
0742     0x09, 0x0a, 0x0b, 0x0c, 0x15, 0x16, 0xa1, 0xf8,
0743     0xe9, 0xeb, 0x01, 0x80, 0x9b, 0xfa, 0xe2, 0x02,
0744     0x03, 0x04, 0xa0, 0xf0, 0x05, 0x06, 0x07, 0xe1,
0745     0x08, 0xe6, 0xf2, 0xed, 0xf6, 0x09, 0xe4, 0x0a,
0746     0xef, 0xf4, 0xec, 0xf3, 0xe7, 0xe5, 0x0b, 0xe3,
0747     0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13,
0748     0xee, 0x14, 0xef, 0x01, 0x9b, 0xe1, 0x0b, 0x0c,
0749     0xd4, 0xef, 0xe6, 0xec, 0xf7, 0xe1, 0x01, 0xba,
0750     0x02, 0x9b, 0xf9, 0x03, 0x04, 0x05, 0xf3, 0x06,
0751     0x07, 0x08, 0xe9, 0xa0, 0x09, 0x80, 0xe5, 0x0a,
0752     0x15, 0x16, 0xa7, 0xba, 0xe3, 0xf7, 0xf2, 0xad,
0753     0xe2, 0x01, 0x02, 0x9b, 0xe6, 0x03, 0xed, 0xf6,
0754     0x04, 0xeb, 0x05, 0xf4, 0x06, 0x07, 0x08, 0xf3,
0755     0x09, 0xf5, 0x0a, 0xef, 0x0b, 0x0c, 0x80, 0xf9,
0756     0xe1, 0x0d, 0xe4, 0xe9, 0xa0, 0x0e, 0x0f, 0xec,
0757     0xe5, 0x10, 0x11, 0x12, 0x13, 0x14, 0x0a, 0x0b,
0758     0xf9, 0x9b, 0xf5, 0xf3, 0x01, 0x02, 0xe2, 0xed,
0759     0x80, 0x03, 0xf0, 0xef, 0x04, 0xa0, 0x05, 0xe9,
0760     0x06, 0xe1, 0x07, 0x08, 0x09, 0xe5, 0x18, 0x19,
0761     0xe2, 0xea, 0xf2, 0xe8, 0xec, 0xed, 0xfa, 0x9b,
0762     0x01, 0xf5, 0x02, 0x03, 0xf6, 0x04, 0xba, 0xe6,
0763     0x05, 0x06, 0xeb, 0xef, 0x07, 0xa7, 0xf9, 0x08,
0764     0x09, 0x0a, 0x0b, 0xe3, 0x0c, 0xee, 0xe1, 0x0d,
0765     0xf3, 0x0e, 0xe9, 0x0f, 0x10, 0xf4, 0x80, 0xe4,
0766     0xe5, 0x11, 0x12, 0xe7, 0xa0, 0x13, 0x14, 0x15,
0767     0x16, 0x17, 0x1b, 0x1c, 0xae, 0xfa, 0xbf, 0x01,
0768     0xa7, 0x9b, 0x02, 0xe9, 0xf8, 0xf9, 0x03, 0xe5,
0769     0xe8, 0x04, 0xe1, 0xeb, 0x05, 0xe2, 0x06, 0x07,
0770     0xe3, 0x08, 0xe7, 0xf4, 0x09, 0x80, 0xf6, 0xf0,
0771     0x0a, 0xe4, 0x0b, 0xf3, 0xf7, 0x0c, 0x0d, 0xef,
0772     0xec, 0xa0, 0x0e, 0x0f, 0xed, 0xe6, 0x10, 0xf5,
0773     0x11, 0x12, 0x13, 0x14, 0x15, 0xf2, 0x16, 0xee,
0774     0x17, 0x18, 0x19, 0x1a, 0x0e, 0x0f, 0xed, 0xa7,
0775     0x9b, 0xe4, 0x01, 0xf9, 0xf3, 0xf2, 0xf4, 0x02,
0776     0xe8, 0x03, 0xec, 0xf0, 0x04, 0xe1, 0xe9, 0x05,
0777     0x06, 0x80, 0xa0, 0x07, 0x08, 0x09, 0x0a, 0xe5,
0778     0xef, 0x0b, 0x0c, 0x0d, 0x9b, 0xf5, 0x18, 0x19,
0779     0xba, 0xac, 0xf6, 0x9b, 0xf0, 0xe2, 0x01, 0xe6,
0780     0x02, 0xa7, 0xae, 0xe7, 0x03, 0xe3, 0xf5, 0x04,
0781     0xed, 0x05, 0x06, 0x07, 0xeb, 0x08, 0x09, 0xee,
0782     0xf2, 0x0a, 0xe4, 0x0b, 0xf9, 0xec, 0x0c, 0x0d,
0783     0xf4, 0x80, 0x0e, 0xef, 0xf3, 0xa0, 0xe1, 0x0f,
0784     0xe9, 0x10, 0x11, 0xe5, 0x12, 0x13, 0x14, 0x15,
0785     0x16, 0x17, 0x19, 0x1a, 0xa7, 0xac, 0xbf, 0xc3,
0786     0xc8, 0xe4, 0xe6, 0xed, 0xf2, 0xae, 0xec, 0xee,
0787     0xf9, 0x01, 0x02, 0x03, 0x04, 0xba, 0x05, 0x9b,
0788     0xf5, 0x06, 0x07, 0x08, 0x09, 0xeb, 0xf0, 0x0a,
0789     0x0b, 0x0c, 0xe1, 0xe3, 0x0d, 0xe8, 0x0e, 0x0f,
0790     0xef, 0x10, 0x11, 0xf3, 0x12, 0xe9, 0x13, 0xe5,
0791     0x14, 0x15, 0xf4, 0x16, 0x17, 0xa0, 0x18, 0x80,
0792     0x14, 0x15, 0xba, 0xbf, 0xe4, 0xf7, 0x9b, 0xa7,
0793     0x01, 0xee, 0x02, 0x03, 0x04, 0xe3, 0xe2, 0xed,
0794     0x05, 0xf9, 0x06, 0xf4, 0x07, 0xec, 0x08, 0xf5,
0795     0xf2, 0x09, 0xe1, 0xf3, 0x0a, 0xef, 0x0b, 0x0c,
0796     0x0d, 0xe9, 0x80, 0xe5, 0x0e, 0xa0, 0x0f, 0xe8,
0797     0x10, 0x11, 0x12, 0x13, 0x11, 0x12, 0xeb, 0xfa,
0798     0x80, 0xe6, 0x9b, 0x01, 0xa0, 0x02, 0x03, 0xe9,
0799     0xe1, 0x04, 0xe4, 0xf0, 0xed, 0xe2, 0xe3, 0xe7,
0800     0xec, 0x05, 0xe5, 0x06, 0x07, 0x08, 0x09, 0xf4,
0801     0x0a, 0x0b, 0x0c, 0xf3, 0xee, 0x0d, 0x0e, 0xf2,
0802     0x0f, 0x10, 0x04, 0xe5, 0xf3, 0xef, 0x9b, 0x01,
0803     0xe1, 0x02, 0x03, 0xe9, 0x0b, 0x0c, 0xa7, 0xe2,
0804     0xec, 0xe3, 0xf2, 0x01, 0x9b, 0x02, 0x03, 0x04,
0805     0xe9, 0xef, 0xee, 0xe5, 0xe1, 0x80, 0x05, 0xa0,
0806     0x06, 0x07, 0x08, 0x09, 0xf3, 0x0a, 0x05, 0x06,
0807     0x9b, 0xa0, 0xe1, 0xe5, 0xe9, 0x01, 0x80, 0xf0,
0808     0x02, 0xf4, 0x03, 0x04, 0xa0, 0x13, 0xe3, 0xad,
0809     0xe4, 0xe9, 0xee, 0xef, 0xf0, 0xf4, 0xf6, 0xa1,
0810     0xe1, 0xed, 0x01, 0xe2, 0x02, 0x03, 0x04, 0xa7,
0811     0x05, 0x06, 0xf7, 0x07, 0x9b, 0xec, 0x08, 0xe5,
0812     0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0xf3, 0x0f,
0813     0x10, 0x11, 0x80, 0x12, 0x05, 0x06, 0xe5, 0xfa,
0814     0xa0, 0xf9, 0x9b, 0x01, 0x80, 0xe9, 0x02, 0xe1,
0815     0x03, 0x04, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b,
0816     0x9b, 0x9b, 0x9b, 0x9b };
0817 
0818 const unsigned short AtscHuffmanString::Huffman2Offsets[128] = {
0819     0x0000, 0x002c, 0x002e, 0x0030, 0x0032, 0x0034, 0x0036, 0x0038,
0820     0x003a, 0x003c, 0x003e, 0x0040, 0x0042, 0x0044, 0x0046, 0x0048,
0821     0x004a, 0x004c, 0x004e, 0x0050, 0x0052, 0x0054, 0x0056, 0x0058,
0822     0x005a, 0x005c, 0x005e, 0x0060, 0x0062, 0x0064, 0x0066, 0x0068,
0823     0x006a, 0x00de, 0x00e0, 0x00ea, 0x00ec, 0x00ee, 0x00f0, 0x00f2,
0824     0x00f8, 0x00fa, 0x00fc, 0x00fe, 0x0100, 0x0104, 0x0116, 0x0120,
0825     0x0122, 0x012c, 0x0132, 0x0138, 0x013c, 0x0140, 0x0144, 0x0146,
0826     0x014a, 0x014c, 0x0154, 0x0156, 0x0158, 0x015a, 0x015c, 0x015e,
0827     0x0160, 0x0162, 0x0176, 0x0184, 0x0194, 0x01a2, 0x01b2, 0x01ba,
0828     0x01c8, 0x01d2, 0x01de, 0x01ea, 0x01f2, 0x01fc, 0x0208, 0x0210,
0829     0x021a, 0x0228, 0x022a, 0x0234, 0x024a, 0x025a, 0x025e, 0x0264,
0830     0x026e, 0x0270, 0x0272, 0x0274, 0x0276, 0x0278, 0x027a, 0x027c,
0831     0x027e, 0x0280, 0x02b4, 0x02ce, 0x02f0, 0x031a, 0x0358, 0x036e,
0832     0x038e, 0x03ac, 0x03d8, 0x03e0, 0x03f4, 0x0424, 0x0440, 0x0476,
0833     0x04ae, 0x04ce, 0x04d0, 0x0506, 0x0534, 0x0560, 0x0586, 0x0592,
0834     0x05aa, 0x05b8, 0x05dc, 0x05ec, 0x05ee, 0x05f0, 0x05f2, 0x05f4 };
0835 
0836 const unsigned char AtscHuffmanString::Huffman2Tables[] = {
0837     0x14, 0x15, 0x9b, 0xd6, 0xc9, 0xcf, 0xd7, 0xc7,
0838     0x01, 0xa2, 0xce, 0xcb, 0x02, 0x03, 0xc5, 0xcc,
0839     0xc6, 0xc8, 0x04, 0xc4, 0x05, 0xc2, 0x06, 0xc3,
0840     0xd2, 0x07, 0xd3, 0x08, 0xca, 0xd4, 0x09, 0xcd,
0841     0xd0, 0x0a, 0xc1, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0842     0x10, 0x11, 0x12, 0x13, 0x9b, 0x9b, 0x9b, 0x9b,
0843     0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b,
0844     0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b,
0845     0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b,
0846     0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b,
0847     0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b,
0848     0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b,
0849     0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b,
0850     0x9b, 0x9b, 0x38, 0x39, 0xad, 0xaf, 0xb7, 0xda,
0851     0xa8, 0xb3, 0xb5, 0x01, 0x02, 0x9b, 0xb4, 0xf1,
0852     0xa2, 0xd5, 0xd6, 0xd9, 0x03, 0x04, 0x05, 0xcf,
0853     0x06, 0xc9, 0xf9, 0xea, 0xeb, 0xf5, 0xf6, 0x07,
0854     0x08, 0x09, 0xb2, 0xc5, 0xc6, 0xb1, 0x0a, 0xee,
0855     0xcb, 0x0b, 0xd4, 0x0c, 0xc4, 0xc8, 0xd2, 0x0d,
0856     0x0e, 0x0f, 0xc7, 0xca, 0xce, 0xd0, 0xd7, 0x10,
0857     0xc2, 0x11, 0xcc, 0xec, 0xe5, 0xe7, 0x12, 0xcd,
0858     0x13, 0x14, 0xc3, 0x15, 0x16, 0x17, 0xed, 0x18,
0859     0x19, 0xf2, 0x1a, 0xd3, 0x1b, 0x1c, 0xe4, 0x1d,
0860     0xc1, 0xe3, 0x1e, 0xe9, 0xf0, 0xe2, 0xf7, 0x1f,
0861     0xf3, 0xe6, 0x20, 0x21, 0x22, 0xe8, 0xef, 0x23,
0862     0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0xf4,
0863     0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0xe1, 0x30, 0x31,
0864     0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x9b, 0x9b,
0865     0x03, 0x04, 0x80, 0xae, 0xc8, 0xd4, 0x01, 0x02,
0866     0x9b, 0xa0, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b,
0867     0x9b, 0x9b, 0x02, 0xf3, 0xa0, 0xf4, 0x9b, 0x01,
0868     0x9b, 0x9b, 0xac, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b,
0869     0x01, 0xa0, 0x9b, 0xa2, 0x07, 0x08, 0xe2, 0xe4,
0870     0xe5, 0xe6, 0xa0, 0xf2, 0xe1, 0x01, 0x02, 0xf3,
0871     0xe3, 0x03, 0x04, 0x05, 0x9b, 0x06, 0x04, 0x80,
0872     0xca, 0xd3, 0xa2, 0x01, 0x9b, 0x02, 0x03, 0xa0,
0873     0x9b, 0xa0, 0x03, 0x04, 0x9b, 0xb7, 0xf4, 0xa0,
0874     0xb0, 0xf3, 0x01, 0x02, 0xb9, 0x02, 0xb8, 0x9b,
0875     0xa0, 0x01, 0xae, 0x02, 0xb6, 0x9b, 0x01, 0xa0,
0876     0xa0, 0x01, 0x9b, 0xb0, 0xae, 0x01, 0x9b, 0xa0,
0877     0xae, 0x01, 0xa0, 0x9b, 0x9b, 0x9b, 0x9b, 0x01,
0878     0xac, 0xae, 0x9b, 0x9b, 0x02, 0x03, 0x9b, 0xa0,
0879     0xb5, 0xb6, 0xb8, 0x01, 0x9b, 0xa0, 0x9b, 0xa0,
0880     0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0xa0,
0881     0x9b, 0x9b, 0x08, 0x09, 0xe6, 0xf5, 0xf3, 0xf4,
0882     0x9b, 0xe4, 0x01, 0xed, 0x02, 0x03, 0x04, 0xf2,
0883     0x05, 0x06, 0xec, 0xee, 0x07, 0xa0, 0x05, 0x06,
0884     0x9b, 0xec, 0xf5, 0x01, 0x02, 0xe1, 0xef, 0xe5,
0885     0xe9, 0xf2, 0x03, 0x04, 0x06, 0x07, 0x9b, 0xe9,
0886     0xf9, 0xf2, 0xf5, 0x01, 0x02, 0x03, 0xec, 0xef,
0887     0xe1, 0x04, 0xe8, 0x05, 0x05, 0x06, 0xf9, 0xf2,
0888     0xf5, 0x9b, 0xe5, 0xef, 0x01, 0x02, 0xe9, 0xe1,
0889     0x03, 0x04, 0x06, 0x07, 0xe1, 0xe9, 0xee, 0xf6,
0890     0xe4, 0xec, 0xf3, 0x01, 0x02, 0xf2, 0x03, 0x04,
0891     0x9b, 0x05, 0x02, 0x03, 0xe5, 0xec, 0x9b, 0xef,
0892     0x01, 0xf2, 0x05, 0x06, 0xf5, 0xef, 0x9b, 0xec,
0893     0xe9, 0x01, 0xe1, 0xf2, 0x02, 0xe5, 0x03, 0x04,
0894     0x03, 0x04, 0x9b, 0xe5, 0xe9, 0xf5, 0xe1, 0x01,
0895     0xef, 0x02, 0x04, 0x05, 0xa0, 0xc9, 0xf3, 0x9b,
0896     0xae, 0xf2, 0x01, 0x02, 0x03, 0xee, 0xef, 0x05,
0897     0x9b, 0xae, 0xe9, 0xe5, 0x01, 0xf5, 0x02, 0xe1,
0898     0x03, 0x04, 0xe5, 0x03, 0xe1, 0xe9, 0xf2, 0x9b,
0899     0x01, 0x02, 0x03, 0x04, 0x9b, 0xe9, 0xf5, 0x01,
0900     0xe5, 0x02, 0xef, 0xe1, 0xe1, 0x05, 0x9b, 0xe3,
0901     0xef, 0x01, 0xf5, 0xe5, 0x02, 0x03, 0xe9, 0x04,
0902     0xe5, 0x03, 0x9b, 0xe9, 0x01, 0xe1, 0xef, 0x02,
0903     0x03, 0x04, 0xa7, 0xee, 0xec, 0xf2, 0xf3, 0x01,
0904     0x9b, 0x02, 0xe1, 0x06, 0x9b, 0xe8, 0xe9, 0x01,
0905     0xf2, 0xec, 0x02, 0xef, 0x03, 0xe5, 0x04, 0x05,
0906     0x9b, 0x9b, 0x03, 0x04, 0x9b, 0xae, 0x01, 0xe9,
0907     0x02, 0xe1, 0xe5, 0xef, 0x09, 0x0a, 0xf6, 0xf9,
0908     0x01, 0xae, 0xe3, 0xe9, 0xf5, 0x9b, 0xe5, 0xef,
0909     0x02, 0x03, 0xe1, 0x04, 0xe8, 0x05, 0x06, 0xf4,
0910     0x07, 0x08, 0xe8, 0x07, 0xe5, 0xf7, 0xd6, 0xe1,
0911     0x9b, 0xe9, 0xf2, 0x01, 0x02, 0x03, 0x04, 0xef,
0912     0x05, 0x06, 0xae, 0x01, 0x9b, 0xee, 0xe9, 0x02,
0913     0xe5, 0x9b, 0xa0, 0x01, 0x03, 0x04, 0x9b, 0xe8,
0914     0xe5, 0xe1, 0xef, 0x01, 0xe9, 0x02, 0x9b, 0x9b,
0915     0x9b, 0xef, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b,
0916     0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b,
0917     0x18, 0x19, 0xe8, 0xef, 0xf8, 0x9b, 0xa7, 0xf7,
0918     0xfa, 0x01, 0x02, 0x03, 0x04, 0xe5, 0xae, 0x05,
0919     0xe6, 0xe2, 0x06, 0xf6, 0xeb, 0xf5, 0xe9, 0x07,
0920     0xf0, 0xf9, 0xe7, 0x08, 0x09, 0xe4, 0x0a, 0xe3,
0921     0x0b, 0xed, 0x0c, 0xf3, 0x0d, 0x0e, 0x0f, 0xec,
0922     0x10, 0xf4, 0x11, 0x12, 0xf2, 0xa0, 0x13, 0x14,
0923     0x15, 0xee, 0x16, 0x17, 0x0b, 0x0c, 0xe4, 0xf3,
0924     0x9b, 0xae, 0xe2, 0x01, 0x02, 0x03, 0xec, 0xa0,
0925     0x04, 0xe9, 0xf2, 0xf5, 0x05, 0xf9, 0xe1, 0x06,
0926     0xef, 0x07, 0xe5, 0x08, 0x09, 0x0a, 0x0f, 0x10,
0927     0xf1, 0xae, 0xc4, 0xf9, 0xac, 0x01, 0xe3, 0x02,
0928     0x9b, 0xf2, 0x03, 0x04, 0xa0, 0xec, 0xf5, 0x05,
0929     0x06, 0xe9, 0x07, 0xeb, 0x08, 0xf4, 0x09, 0xe5,
0930     0x0a, 0xef, 0xe1, 0xe8, 0x0b, 0x0c, 0x0d, 0x0e,
0931     0x13, 0x14, 0xa7, 0xbb, 0xe6, 0xed, 0xf7, 0xe7,
0932     0xf6, 0x01, 0x02, 0x9b, 0xee, 0x03, 0x04, 0xec,
0933     0x05, 0xf5, 0x06, 0xac, 0xe4, 0xf9, 0xf2, 0x07,
0934     0x08, 0x09, 0xae, 0x0a, 0xef, 0x0b, 0xe1, 0xf3,
0935     0x0c, 0xe9, 0x0d, 0x0e, 0x0f, 0x10, 0xe5, 0x11,
0936     0x12, 0xa0, 0x1d, 0x1e, 0xa9, 0xe8, 0xf5, 0x9b,
0937     0x01, 0xad, 0xbb, 0xeb, 0xfa, 0x02, 0xa7, 0xe6,
0938     0xe2, 0xe7, 0x03, 0x04, 0x05, 0x06, 0xe9, 0xf8,
0939     0x07, 0xac, 0xef, 0xf0, 0x08, 0xed, 0xf6, 0xf9,
0940     0x09, 0xf7, 0x0a, 0x0b, 0xae, 0x0c, 0xe3, 0x0d,
0941     0xe5, 0xf4, 0x0e, 0x0f, 0xe4, 0x10, 0xec, 0x11,
0942     0xe1, 0x12, 0x13, 0x14, 0x15, 0x16, 0xee, 0xf3,
0943     0x17, 0x18, 0xf2, 0xa0, 0x19, 0x1a, 0x1b, 0x1c,
0944     0x09, 0x0a, 0xae, 0x9b, 0xec, 0x01, 0xf5, 0x02,
0945     0xf4, 0xe6, 0x03, 0xe1, 0xe5, 0xe9, 0x04, 0xf2,
0946     0xef, 0x05, 0x06, 0x07, 0xa0, 0x08, 0x0e, 0x0f,
0947     0xad, 0xe7, 0x9b, 0xa7, 0xf9, 0x01, 0xec, 0x02,
0948     0xac, 0xf2, 0x03, 0xae, 0xf3, 0xf5, 0x04, 0x05,
0949     0xef, 0x06, 0x07, 0xe9, 0xe1, 0x08, 0x09, 0xe8,
0950     0x0a, 0x0b, 0xe5, 0x0c, 0xa0, 0x0d, 0x0d, 0x0e,
0951     0xa7, 0xac, 0xf3, 0xad, 0x01, 0x02, 0x9b, 0xf9,
0952     0xf5, 0xae, 0x03, 0xee, 0x04, 0xf2, 0x05, 0x06,
0953     0xf4, 0x07, 0x08, 0x09, 0xef, 0xe1, 0xa0, 0x0a,
0954     0xe9, 0x0b, 0x0c, 0xe5, 0x14, 0x15, 0xac, 0xe2,
0955     0xf8, 0x9b, 0xae, 0xfa, 0x01, 0xeb, 0x02, 0xa0,
0956     0x03, 0x04, 0xf0, 0x05, 0x06, 0xe6, 0xf6, 0x07,
0957     0xe4, 0xed, 0xe7, 0x08, 0xe1, 0xef, 0xf2, 0x09,
0958     0x0a, 0x0b, 0xec, 0x0c, 0xe5, 0xe3, 0x0d, 0xf4,
0959     0x0e, 0xf3, 0x0f, 0x10, 0x11, 0xee, 0x12, 0x13,
0960     0x03, 0xef, 0x9b, 0xe1, 0xe5, 0xf5, 0x01, 0x02,
0961     0x08, 0x09, 0xec, 0xf9, 0xa7, 0xee, 0x01, 0xac,
0962     0x9b, 0xae, 0x02, 0x03, 0x04, 0xf3, 0x05, 0xe9,
0963     0x06, 0xa0, 0x07, 0xe5, 0x16, 0x17, 0xa7, 0xad,
0964     0xee, 0xe3, 0xeb, 0xf2, 0x9b, 0xe2, 0x01, 0x02,
0965     0xf5, 0x03, 0xf4, 0xac, 0x04, 0x05, 0xe6, 0xed,
0966     0xf6, 0x06, 0xae, 0xf0, 0x07, 0x08, 0xf3, 0x09,
0967     0x0a, 0xe4, 0x0b, 0x0c, 0xf9, 0x0d, 0xef, 0x0e,
0968     0xe1, 0x0f, 0x10, 0xe9, 0xec, 0x11, 0xa0, 0xe5,
0969     0x12, 0x13, 0x14, 0x15, 0x0c, 0x0d, 0xa7, 0xbb,
0970     0x9b, 0x01, 0xf9, 0xae, 0xe2, 0x02, 0xed, 0xf3,
0971     0x03, 0xf5, 0xef, 0xf0, 0x04, 0x05, 0xe9, 0x06,
0972     0x07, 0x08, 0x09, 0xa0, 0xe1, 0xe5, 0x0a, 0x0b,
0973     0x19, 0x1a, 0xad, 0xbb, 0xe2, 0xea, 0xed, 0xf2,
0974     0xfa, 0xe6, 0xec, 0x01, 0x02, 0x03, 0x9b, 0xf5,
0975     0x04, 0xa7, 0xf6, 0xf9, 0x05, 0x06, 0xeb, 0xef,
0976     0x07, 0x08, 0x09, 0x0a, 0xac, 0x0b, 0x0c, 0xe3,
0977     0xae, 0x0d, 0xee, 0xe9, 0x0e, 0xe1, 0x0f, 0xf3,
0978     0x10, 0x11, 0xf4, 0x12, 0xe7, 0xe5, 0x13, 0x14,
0979     0xe4, 0x15, 0x16, 0x17, 0xa0, 0x18, 0x1a, 0x1b,
0980     0xc2, 0x9b, 0xad, 0xac, 0xf8, 0x01, 0xae, 0x02,
0981     0x03, 0xe5, 0xe7, 0xe8, 0xf9, 0xe9, 0xeb, 0x04,
0982     0xe3, 0xe1, 0x05, 0xf6, 0x06, 0xe4, 0x07, 0xe2,
0983     0xf0, 0x08, 0x09, 0xf3, 0xf4, 0xf7, 0xef, 0x0a,
0984     0x0b, 0x0c, 0x0d, 0xec, 0x0e, 0x0f, 0x10, 0xf5,
0985     0xed, 0x11, 0xe6, 0xa0, 0x12, 0xf2, 0x13, 0x14,
0986     0x15, 0xee, 0x16, 0x17, 0x18, 0x19, 0x0e, 0x0f,
0987     0xad, 0xed, 0xf9, 0x9b, 0xae, 0x01, 0xf3, 0x02,
0988     0x03, 0xf5, 0xf4, 0xf0, 0x04, 0xef, 0x05, 0xe9,
0989     0x06, 0xe8, 0xa0, 0xe1, 0xec, 0x07, 0xf2, 0x08,
0990     0xe5, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x9b, 0xf5,
0991     0x19, 0x1a, 0xa9, 0xbb, 0xf6, 0xe6, 0x01, 0x9b,
0992     0xad, 0xe2, 0xf0, 0x02, 0xa7, 0x03, 0x04, 0x05,
0993     0xf5, 0xe3, 0xac, 0xe7, 0xf2, 0x06, 0xeb, 0x07,
0994     0xec, 0xed, 0xee, 0xf9, 0x08, 0xae, 0x09, 0x0a,
0995     0xe4, 0x0b, 0x0c, 0xf4, 0x0d, 0xf3, 0x0e, 0x0f,
0996     0x10, 0xe1, 0xef, 0x11, 0xe9, 0x12, 0x13, 0xe5,
0997     0x14, 0xa0, 0x15, 0x16, 0x17, 0x18, 0xa0, 0x16,
0998     0xa2, 0xa7, 0xe2, 0xeb, 0xed, 0xee, 0x9b, 0xf7,
0999     0x01, 0x02, 0x03, 0xbb, 0xf9, 0xf0, 0x04, 0x05,
1000     0xec, 0x06, 0x07, 0x08, 0xf5, 0xe1, 0x09, 0xac,
1001     0xe3, 0x0a, 0xe8, 0x0b, 0xe9, 0x0c, 0xef, 0xf3,
1002     0xae, 0x0d, 0x0e, 0xe5, 0x0f, 0x10, 0x11, 0xf4,
1003     0x12, 0x13, 0x14, 0x15, 0x14, 0x15, 0xbb, 0xe2,
1004     0xad, 0xed, 0x01, 0x9b, 0xa7, 0xe3, 0xac, 0xec,
1005     0xee, 0x02, 0xf7, 0x03, 0x04, 0xf9, 0x05, 0x06,
1006     0x07, 0x08, 0xf4, 0xae, 0xf5, 0x09, 0x0a, 0xf2,
1007     0xe1, 0xf3, 0x0b, 0x0c, 0x0d, 0xe9, 0x0e, 0x0f,
1008     0xef, 0xe5, 0x10, 0xa0, 0xe8, 0x11, 0x12, 0x13,
1009     0x11, 0x12, 0xef, 0xf6, 0x9b, 0xeb, 0xf9, 0x01,
1010     0xa0, 0xe2, 0x02, 0xe1, 0x03, 0xed, 0x04, 0xe3,
1011     0xe9, 0x05, 0xe4, 0xe5, 0xe7, 0x06, 0xec, 0xf0,
1012     0x07, 0x08, 0x09, 0x0a, 0x0b, 0xf3, 0x0c, 0xf4,
1013     0xee, 0x0d, 0xf2, 0x0e, 0x0f, 0x10, 0x05, 0xe5,
1014     0xf3, 0xf9, 0x9b, 0x01, 0xef, 0x02, 0x03, 0xe1,
1015     0x04, 0xe9, 0x0a, 0x0b, 0xae, 0x9b, 0xec, 0xed,
1016     0x01, 0x02, 0xf3, 0xee, 0xf2, 0x03, 0xe5, 0x04,
1017     0xe8, 0xa0, 0xe1, 0x05, 0xef, 0x06, 0x07, 0x08,
1018     0xe9, 0x09, 0x05, 0x06, 0xa0, 0xac, 0xad, 0xf4,
1019     0xe9, 0x01, 0x02, 0xe1, 0xe5, 0x03, 0x9b, 0x04,
1020     0x11, 0xa0, 0xbf, 0xe1, 0xe2, 0xe6, 0xed, 0xe4,
1021     0xe9, 0xf7, 0xa7, 0x01, 0x02, 0xbb, 0x03, 0x04,
1022     0xec, 0x05, 0x9b, 0xee, 0x06, 0xef, 0x07, 0xac,
1023     0xe5, 0xf3, 0x08, 0x09, 0x0a, 0xae, 0x0b, 0x0c,
1024     0x0d, 0x0e, 0x0f, 0x10, 0x06, 0x07, 0xa0, 0xae,
1025     0xe1, 0xe5, 0xec, 0xfa, 0x9b, 0xef, 0xe9, 0x01,
1026     0x02, 0x03, 0x04, 0x05, 0x9b, 0x9b, 0x9b, 0x9b,
1027     0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b };
1028 
1029 void DvbPmtFilter::processSection(const char *data, int size)
1030 {
1031     unsigned char tableId = data[0];
1032 
1033     if (tableId != 0x02) {
1034         return;
1035     }
1036 
1037     DvbPmtSection pmtSection(data, size);
1038 
1039     if (!pmtSection.isValid() || (pmtSection.programNumber() != programNumber)) {
1040         return;
1041     }
1042 
1043     if ((size == lastPmtSectionData.size()) &&
1044         (memcmp(data, lastPmtSectionData.constData(), size) == 0)) {
1045         return;
1046     }
1047 
1048     lastPmtSectionData = pmtSection.toByteArray();
1049     emit pmtSectionChanged(lastPmtSectionData);
1050 }
1051 
1052 void DvbSectionGenerator::initPat(int transportStreamId, int programNumber, int pmtPid)
1053 {
1054     Q_ASSERT((pmtPid >= 0) && (pmtPid <= 0x1fff));
1055 
1056     char *data = startSection(16);
1057     data[0] = 0x00;
1058     data[3] = char(transportStreamId >> 8);
1059     data[4] = char(transportStreamId);
1060     data[8] = char(programNumber >> 8);
1061     data[9] = char(programNumber);
1062     data[10] = 0xe0 | char(pmtPid >> 8);
1063     data[11] = char(pmtPid);
1064     endSection(16, 0x00);
1065 }
1066 
1067 void DvbSectionGenerator::initPmt(int pmtPid, const DvbPmtSection &section, const QList<int> &pids)
1068 {
1069     Q_ASSERT(section.isValid());
1070 
1071     char *data = startSection(section.getSectionLength());
1072 
1073     DvbPmtSectionEntry entry = section.entries();
1074     memcpy(data, section.getData(), entry.getData() - section.getData());
1075     int size = int(entry.getData() - section.getData());
1076 
1077     while (entry.isValid()) {
1078         if (pids.contains(entry.pid())) {
1079             memcpy(data + size, entry.getData(), entry.getLength());
1080             size += entry.getLength();
1081         }
1082 
1083         entry.advance();
1084     }
1085 
1086     endSection(size + 4, pmtPid);
1087 }
1088 
1089 QByteArray DvbSectionGenerator::generatePackets()
1090 {
1091     char *data = packets.data();
1092 
1093     for (int i = 3; i < packets.size(); i += 188) {
1094         data[i] = (data[i] & 0xf0) | char(continuityCounter);
1095         continuityCounter = (continuityCounter + 1) & 0x0f;
1096     }
1097 
1098     return packets;
1099 }
1100 
1101 char *DvbSectionGenerator::startSection(int sectionLength)
1102 {
1103     Q_ASSERT((sectionLength >= 4) && (sectionLength <= 0x1002));
1104     packets.resize(((sectionLength / 184) + 1) * 188);
1105     return packets.data() + 5;
1106 }
1107 
1108 void DvbSectionGenerator::endSection(int sectionLength, int pid)
1109 {
1110     Q_ASSERT((sectionLength >= 4) && (sectionLength <= 0x1002));
1111     Q_ASSERT((pid >= 0) && (pid <= 0x1fff));
1112 
1113     packets.resize(((sectionLength / 184) + 1) * 188);
1114     char *data = packets.data();
1115 
1116     data[0] = 0x47;
1117     data[1] = 0x40 | char(pid >> 8);
1118     data[2] = char(pid);
1119     data[3] = 0x10;
1120     data[4] = 0x00;
1121     data[6] = 0xb0 | char((sectionLength - 3) >> 8);
1122     data[7] = char(sectionLength - 3);
1123     data[10] = 0xc1 | char(versionNumber << 1);
1124     data[11] = 0x00;
1125     data[12] = 0x00;
1126 
1127     int size = sectionLength + 5;
1128     unsigned int crc32 = 0xffffffff;
1129 
1130     for (int i = 5; i < (size - 4); ++i) {
1131         unsigned char byte = data[i];
1132         crc32 = (crc32 << 8) ^ DvbStandardSection::crc32Table[(crc32 >> 24) ^ byte];
1133     }
1134 
1135     data[size - 4] = char(crc32 >> 24);
1136     data[size - 3] = char(crc32 >> 16);
1137     data[size - 2] = char(crc32 >> 8);
1138     data[size - 1] = char(crc32);
1139 
1140     for (int i = 188; i < size; i += 188) {
1141         // split the section into multiple packets if necessary
1142         memmove(data + i + 4, data + i, size - i);
1143         data[i] = 0x47;
1144         data[i + 1] = char(pid >> 8);
1145         data[i + 2] = char(pid);
1146         data[i + 3] = 0x10; // continuity counter is filled out in generatePackets()
1147         size += 4;
1148     }
1149 
1150     // pad the unused bytes
1151     memset(data + size, 0xff, packets.size() - size);
1152 
1153     // increment version number
1154     versionNumber = (versionNumber + 1) & 0x1f;
1155 }
1156 
1157 DvbPmtParser::DvbPmtParser(const DvbPmtSection &section) : videoPid(-1), teletextPid(-1)
1158 {
1159     for (DvbPmtSectionEntry entry = section.entries(); entry.isValid(); entry.advance()) {
1160         QString streamLanguage;
1161         QString subtitleLanguage;
1162         QString fourcc;
1163         bool teletextPresent = false;
1164         bool audioPresent = false;
1165         bool videoPresent = false;
1166 
1167         for (DvbDescriptor descriptor = entry.descriptors(); descriptor.isValid();
1168              descriptor.advance()) {
1169             switch (descriptor.descriptorTag()) {
1170             case 0x05: {
1171                 DvbRegistrationDescriptor registrationDescriptor(descriptor);
1172                 fourcc.clear();
1173                 fourcc.append(QChar(registrationDescriptor.formatIdentifier0()));
1174                 fourcc.append(QChar(registrationDescriptor.formatIdentifier1()));
1175                 fourcc.append(QChar(registrationDescriptor.formatIdentifier2()));
1176                 fourcc.append(QChar(registrationDescriptor.formatIdentifier3()));
1177 
1178                 /* Handle audio and video fourcc's */
1179                 if (entry.streamType() == 0x06 &&
1180                     (fourcc == "EAC3" ||
1181                      fourcc == "AC-3" ||
1182                      fourcc == "DTS1" ||
1183                      fourcc == "DTS2" ||
1184                      fourcc == "DTS3" ||
1185                      fourcc == "BSSD"))
1186                     audioPresent = true;
1187                 else if ((entry.streamType() == 0x06 && fourcc == "HEVC") ||
1188                      (entry.streamType() == 0xea && fourcc == "VC-1"))
1189                     videoPresent = true;
1190                 break;
1191                 }
1192 
1193             case 0x0a: {
1194                 DvbLanguageDescriptor languageDescriptor(descriptor);
1195 
1196                 if (!languageDescriptor.isValid()) {
1197                     break;
1198                 }
1199 
1200                 // ISO 8859-1 equals to unicode range 0x0000 - 0x00ff
1201                 streamLanguage.clear();
1202                 streamLanguage.append(QChar(languageDescriptor.languageCode1()));
1203                 streamLanguage.append(QChar(languageDescriptor.languageCode2()));
1204                 streamLanguage.append(QChar(languageDescriptor.languageCode3()));
1205                 break;
1206                 }
1207 
1208             case 0x56:
1209                 teletextPresent = true;
1210                 break;
1211 
1212             case 0x59: {
1213                 DvbSubtitleDescriptor subtitleDescriptor(descriptor);
1214 
1215                 if (!subtitleDescriptor.isValid()) {
1216                     break;
1217                 }
1218 
1219                 if ((subtitleDescriptor.subtitleType() >= 0x01) &&
1220                     (subtitleDescriptor.subtitleType() <= 0x03)) {
1221                     // FIXME how to deal with vbi and teletext subtitles?
1222                     qCInfo(logDvbSi, "Unsupported subtitle found: VBI/teletext (%d)", subtitleDescriptor.subtitleType());
1223                 }
1224 
1225                 // ISO 8859-1 equals to unicode range 0x0000 - 0x00ff
1226                 subtitleLanguage.clear();
1227                 subtitleLanguage.append(QChar(subtitleDescriptor.languageCode1()));
1228                 subtitleLanguage.append(QChar(subtitleDescriptor.languageCode2()));
1229                 subtitleLanguage.append(QChar(subtitleDescriptor.languageCode3()));
1230                 break;
1231                 }
1232 
1233             case 0x6a:
1234             case 0x7a:
1235                 audioPresent = true;
1236                 break;
1237             }
1238         }
1239 
1240         /*
1241          * The code above already checks for streamType. So,
1242          * once we add a video channel here, just rely on it,
1243          * without parsing the streamType() again.
1244          */
1245         if (videoPresent) {
1246             if (videoPid < 0) {
1247                 videoPid = entry.pid();
1248             } else {
1249                 qCInfo(logDvbSi, "More than one video PID");
1250             }
1251             continue;
1252         }
1253 
1254         // Updated with Table 2-34 of ISO/IEC 13818-1:2018 / ITU-T H.222.0 2017
1255         // and with https://www.wikiwand.com/en/Program-specific_information
1256         // (as private IDs are not at ITU/ISO/IEC specs
1257 
1258         switch (entry.streamType()) {
1259         case 0x01: // ISO/IEC 11172-2 (MPEG-1) video
1260         case 0x02: // ITU-T H.262 (MPEG2) video or ISO/IEC 11172-2
1261         case 0x10: // ISO/IEC 14496-2 (MPEG-4) video
1262         case 0x1b: // ITU-T H.264 video
1263         case 0x1e: // ISO/IEC 23002-3 (MPEG-4 auxiliary video)
1264         case 0x1f: // ITU-T H.264 Annex G (MPEG-4 SVC sub-bitstream on AVC)
1265         case 0x20: // ITU-T H.264 Annex H (MPEG-4 MVC sub-bitstream on AVC)
1266         case 0x21: // ITU-T T.800 (JPEG 2000 video)
1267         case 0x22: // ITU-T H.262 additional view for 3D
1268         case 0x23: // ITU-T H.264 additional view for 3D
1269         case 0x24: // ITU-T H.265 or HEVC sub-bitstream
1270         case 0x25: // ITU-T H.265 Annex A - HEVC video stream or subset
1271         case 0x26: // ITU-T H.264 Annex I - MVCD substream on HEVC
1272         case 0x28: // ITU-T H.265 Annex G - HEVC enhancemeng sub-partition
1273         case 0x29: // ITU-T H.265 Annex G - HEVC temporal enhancement
1274         case 0x2a: // ITU-T H.265 Annex H - HEVC enhancement
1275         case 0x2b: // ITU-T H.265 Annex H - HEVC temporal enhancement
1276         case 0x42: // CAVS video
1277         // User-private video streams
1278         case 0x80: // MPEG-2 MOTO video
1279         case 0xd1: // Dirac (Ultra HD video)
1280             if (videoPid < 0) {
1281                 videoPid = entry.pid();
1282             } else {
1283                 qCInfo(logDvbSi, "More than one video PID");
1284             }
1285 
1286             break;
1287 
1288         case 0x03: // ISO/IEC 11172-3 (MPEG1) audio
1289         case 0x04: // ISO/IEC 13818-3 (MPEG2) audio
1290         case 0x07: // ISO/IEC 13522 MHEG - DTS and DTS-HD Audio
1291         case 0x0f: // ISO/IEC 13818-7 Audio with ADTS transport syntax
1292         case 0x11: // ISO/IEC 14496-3 Audio (AAC / LATM)
1293         case 0x1c: // ISO/IEC 14496-3 Audio, without additional transport syntax
1294         case 0x2d: // ISO/IEC 23008-3 Audio with MHAS – main stream
1295         case 0x2e: // ISO/IEC 23008-3 Audio with MHAS – auxiliary stream
1296         // User-private audio streams
1297         case 0x81: // AC-3 audio (ATSC specific)
1298         case 0x83: // TrueHD lossless audio
1299         case 0x84: // SDDS
1300         case 0x85: // DTS on HDMV
1301         case 0x86: // DTS 8 channel
1302         case 0x87: // enhanced AC-3 audio (ATSC specific)
1303         case 0x8a: // DTS
1304         case 0x91: // A52 VLS
1305         case 0x94: // SDDS
1306             audioPids.append(qMakePair(entry.pid(), streamLanguage));
1307             break;
1308 
1309         case 0x06: // private data - can be teletext, subtitle, ac3 or something else
1310             if (teletextPresent) {
1311                 if (teletextPid < 0) {
1312                     teletextPid = entry.pid();
1313                 } else {
1314                     qCInfo(logDvbSi, "More than one teletext PID");
1315                 }
1316             }
1317 
1318             if (!subtitleLanguage.isEmpty()) {
1319                 subtitlePids.append(qMakePair(entry.pid(), subtitleLanguage));
1320 
1321                 if (teletextPresent) {
1322                     qCInfo(logDvbSi, "Subtitle and teletext on the same PID");
1323                 }
1324             }
1325 
1326             if (audioPresent) {
1327                 audioPids.append(qMakePair(entry.pid(), streamLanguage));
1328             }
1329 
1330             break;
1331 
1332         default:
1333             if (!subtitleLanguage.isEmpty()) {
1334                 qCInfo(logDvbSi, "Subtitle with unexpected stream type found");
1335             }
1336 
1337             if (teletextPresent) {
1338                 qCInfo(logDvbSi, "Teletext with unexpected stream type found");
1339             }
1340 
1341             break;
1342         }
1343     }
1344 }
1345 
1346 void AtscEitSectionEntry::initEitSectionEntry(const char *data, int size)
1347 {
1348     if (size < 12) {
1349         if (size != 0) {
1350             qCInfo(logDvbSi, "Invalid entry");
1351         }
1352 
1353         initSectionData();
1354         return;
1355     }
1356 
1357     titleLength = quint8(data[9]);
1358 
1359     if (titleLength > (size - 12)) {
1360         qCInfo(logDvbSi, "Adjusting length");
1361         titleLength = (size - 12);
1362     }
1363 
1364     // too ugly to be automatically generated
1365     int entryLength = ((((quint8(data[10 + titleLength]) & 0xf) << 8) |
1366         quint8(data[11 + titleLength])) + 12 + titleLength);
1367 
1368     if (entryLength > size) {
1369         qCInfo(logDvbSi, "Adjusting length");
1370         entryLength = size;
1371     }
1372 
1373     initSectionData(data, entryLength, size);
1374 }
1375 
1376 // everything below this line is automatically generated
1377 
1378 void DvbPatSectionEntry::initPatSectionEntry(const char *data, int size)
1379 {
1380     if (size < 4) {
1381         if (size != 0) {
1382         qCWarning(logDvbSi, "Invalid entry at descriptor");
1383         }
1384 
1385         initSectionData();
1386         return;
1387     }
1388 
1389     initSectionData(data, 4, size);
1390 }
1391 
1392 void DvbPmtSectionEntry::initPmtSectionEntry(const char *data, int size)
1393 {
1394     if (size < 5) {
1395         if (size != 0) {
1396         qCWarning(logDvbSi, "Invalid entry at descriptor");
1397         }
1398 
1399         initSectionData();
1400         return;
1401     }
1402 
1403     int entryLength = ((((quint8(data[3]) & 0xf) << 8) | quint8(data[4])) + 5);
1404 
1405     if (entryLength > size) {
1406         qCWarning(logDvbSi, "Adjusting length on descriptor");
1407         entryLength = size;
1408     }
1409 
1410     initSectionData(data, entryLength, size);
1411 }
1412 
1413 void DvbSdtSectionEntry::initSdtSectionEntry(const char *data, int size)
1414 {
1415     if (size < 5) {
1416         if (size != 0) {
1417         qCWarning(logDvbSi, "Invalid entry at descriptor");
1418         }
1419 
1420         initSectionData();
1421         return;
1422     }
1423 
1424     int entryLength = ((((quint8(data[3]) & 0xf) << 8) | quint8(data[4])) + 5);
1425 
1426     if (entryLength > size) {
1427         qCWarning(logDvbSi, "Adjusting length on descriptor");
1428         entryLength = size;
1429     }
1430 
1431     initSectionData(data, entryLength, size);
1432 }
1433 
1434 void DvbEitSectionEntry::initEitSectionEntry(const char *data, int size)
1435 {
1436     if (size < 12) {
1437         if (size != 0) {
1438         qCWarning(logDvbSi, "Invalid entry at descriptor");
1439         }
1440 
1441         initSectionData();
1442         return;
1443     }
1444 
1445     int entryLength = ((((quint8(data[10]) & 0xf) << 8) | quint8(data[11])) + 12);
1446 
1447     if (entryLength > size) {
1448         qCWarning(logDvbSi, "Adjusting length on descriptor");
1449         entryLength = size;
1450     }
1451 
1452     initSectionData(data, entryLength, size);
1453 }
1454 
1455 void DvbEitContentEntry::initEitContentEntry(const char *data, int size)
1456 {
1457     if (size < 2) {
1458         if (size != 0) {
1459         qCWarning(logDvbSi, "Invalid entry at descriptor");
1460         }
1461 
1462         initSectionData();
1463         return;
1464     }
1465 
1466     initSectionData(data, 2, size);
1467 }
1468 
1469 void DvbParentalRatingEntry::initParentalRatingEntry(const char *data, int size)
1470 {
1471     if (size < 4) {
1472         if (size != 0) {
1473         qCWarning(logDvbSi, "Invalid entry at descriptor");
1474         }
1475 
1476         initSectionData();
1477         return;
1478     }
1479 
1480     initSectionData(data, 4, size);
1481 }
1482 
1483 void DvbNitSectionEntry::initNitSectionEntry(const char *data, int size)
1484 {
1485     if (size < 6) {
1486         if (size != 0) {
1487         qCWarning(logDvbSi, "Invalid entry at descriptor");
1488         }
1489 
1490         initSectionData();
1491         return;
1492     }
1493 
1494     int entryLength = ((((quint8(data[4]) & 0xf) << 8) | quint8(data[5])) + 6);
1495 
1496     if (entryLength > size) {
1497         qCWarning(logDvbSi, "Adjusting length on descriptor");
1498         entryLength = size;
1499     }
1500 
1501     initSectionData(data, entryLength, size);
1502 }
1503 
1504 void AtscMgtSectionEntry::initMgtSectionEntry(const char *data, int size)
1505 {
1506     if (size < 11) {
1507         if (size != 0) {
1508         qCWarning(logDvbSi, "Invalid entry at descriptor");
1509         }
1510 
1511         initSectionData();
1512         return;
1513     }
1514 
1515     int entryLength = ((((quint8(data[9]) & 0xf) << 8) | quint8(data[10])) + 11);
1516 
1517     if (entryLength > size) {
1518         qCWarning(logDvbSi, "Adjusting length on descriptor");
1519         entryLength = size;
1520     }
1521 
1522     initSectionData(data, entryLength, size);
1523 }
1524 
1525 void AtscVctSectionEntry::initVctSectionEntry(const char *data, int size)
1526 {
1527     if (size < 32) {
1528         if (size != 0) {
1529         qCWarning(logDvbSi, "Invalid entry at descriptor");
1530         }
1531 
1532         initSectionData();
1533         return;
1534     }
1535 
1536     int entryLength = ((((quint8(data[30]) & 0x3) << 8) | quint8(data[31])) + 32);
1537 
1538     if (entryLength > size) {
1539         qCWarning(logDvbSi, "Adjusting length on descriptor");
1540         entryLength = size;
1541     }
1542 
1543     initSectionData(data, entryLength, size);
1544 }
1545 
1546 DvbRegistrationDescriptor::DvbRegistrationDescriptor(const DvbDescriptor &descriptor) : DvbDescriptor(descriptor)
1547 {
1548     if (getLength() < 6) {
1549         qCWarning(logDvbSi, "Invalid descriptor");
1550         initSectionData();
1551         return;
1552     }
1553 }
1554 
1555 DvbLanguageDescriptor::DvbLanguageDescriptor(const DvbDescriptor &descriptor) : DvbDescriptor(descriptor)
1556 {
1557     if (getLength() < 6) {
1558         qCWarning(logDvbSi, "Invalid descriptor");
1559         initSectionData();
1560         return;
1561     }
1562 }
1563 
1564 DvbSubtitleDescriptor::DvbSubtitleDescriptor(const DvbDescriptor &descriptor) : DvbDescriptor(descriptor)
1565 {
1566     if (getLength() < 10) {
1567         qCWarning(logDvbSi, "Invalid descriptor");
1568         initSectionData();
1569         return;
1570     }
1571 }
1572 
1573 DvbServiceDescriptor::DvbServiceDescriptor(const DvbDescriptor &descriptor) : DvbDescriptor(descriptor)
1574 {
1575     if (getLength() < 5) {
1576         qCWarning(logDvbSi, "Invalid descriptor");
1577         initSectionData();
1578         return;
1579     }
1580 
1581     providerNameLength = at(3);
1582 
1583     if (providerNameLength > (getLength() - 5)) {
1584         qCWarning(logDvbSi, "Adjusting length on descriptor");
1585         providerNameLength = (getLength() - 5);
1586     }
1587 
1588     serviceNameLength = at(4 + providerNameLength);
1589 
1590     if (serviceNameLength > (getLength() - (5 + providerNameLength))) {
1591         qCWarning(logDvbSi, "Adjusting length on descriptor");
1592         serviceNameLength = (getLength() - (5 + providerNameLength));
1593     }
1594 }
1595 
1596 DvbShortEventDescriptor::DvbShortEventDescriptor(const DvbDescriptor &descriptor) : DvbDescriptor(descriptor)
1597 {
1598     if (getLength() < 7) {
1599         qCWarning(logDvbSi, "Invalid descriptor");
1600         initSectionData();
1601         return;
1602     }
1603 
1604     eventNameLength = at(5);
1605 
1606     if (eventNameLength > (getLength() - 7)) {
1607         qCWarning(logDvbSi, "Adjusting length on descriptor");
1608         eventNameLength = (getLength() - 7);
1609     }
1610 
1611     textLength = at(6 + eventNameLength);
1612 
1613     if (textLength > (getLength() - (7 + eventNameLength))) {
1614         qCWarning(logDvbSi, "Adjusting length on descriptor");
1615         textLength = (getLength() - (7 + eventNameLength));
1616     }
1617 }
1618 
1619 DvbExtendedEventDescriptor::DvbExtendedEventDescriptor(const DvbDescriptor &descriptor) : DvbDescriptor(descriptor)
1620 {
1621     if (getLength() < 8) {
1622         qCWarning(logDvbSi, "Invalid descriptor");
1623         initSectionData();
1624         return;
1625     }
1626 
1627     itemsLength = at(6);
1628 
1629     if (itemsLength > (getLength() - 8)) {
1630         qCWarning(logDvbSi, "Adjusting length on descriptor");
1631         itemsLength = (getLength() - 8);
1632     }
1633 
1634     textLength = at(7 + itemsLength);
1635 
1636     if (textLength > (getLength() - (8 + itemsLength))) {
1637         qCWarning(logDvbSi, "Adjusting length on descriptor");
1638         textLength = (getLength() - (8 + itemsLength));
1639     }
1640 }
1641 
1642 DvbContentDescriptor::DvbContentDescriptor(const DvbDescriptor &descriptor) : DvbDescriptor(descriptor)
1643 {
1644     if (getLength() < 2) {
1645         qCWarning(logDvbSi, "Invalid descriptor");
1646         initSectionData();
1647         return;
1648     }
1649 }
1650 
1651 DvbParentalRatingDescriptor::DvbParentalRatingDescriptor(const DvbDescriptor &descriptor) : DvbDescriptor(descriptor)
1652 {
1653     if (getLength() < 2) {
1654         qCWarning(logDvbSi, "Invalid descriptor");
1655         initSectionData();
1656         return;
1657     }
1658 }
1659 
1660 DvbCableDescriptor::DvbCableDescriptor(const DvbDescriptor &descriptor) : DvbDescriptor(descriptor)
1661 {
1662     if (getLength() < 13) {
1663         qCWarning(logDvbSi, "Invalid descriptor");
1664         initSectionData();
1665         return;
1666     }
1667 }
1668 
1669 DvbSatelliteDescriptor::DvbSatelliteDescriptor(const DvbDescriptor &descriptor) : DvbDescriptor(descriptor)
1670 {
1671     if (getLength() < 13) {
1672         qCWarning(logDvbSi, "Invalid descriptor");
1673         initSectionData();
1674         return;
1675     }
1676 }
1677 
1678 DvbTerrestrialDescriptor::DvbTerrestrialDescriptor(const DvbDescriptor &descriptor) : DvbDescriptor(descriptor)
1679 {
1680     if (getLength() < 13) {
1681         qCWarning(logDvbSi, "Invalid descriptor");
1682         initSectionData();
1683         return;
1684     }
1685 }
1686 
1687 IsdbTerrestrialDescriptor::IsdbTerrestrialDescriptor(const DvbDescriptor &descriptor) : DvbDescriptor(descriptor)
1688 {
1689     if (getLength() < 4) {
1690         qCWarning(logDvbSi, "Invalid descriptor");
1691         initSectionData();
1692         return;
1693     }
1694 }
1695 
1696 AtscChannelNameDescriptor::AtscChannelNameDescriptor(const DvbDescriptor &descriptor) : DvbDescriptor(descriptor)
1697 {
1698     if (getLength() < 2) {
1699         qCWarning(logDvbSi, "Invalid descriptor");
1700         initSectionData();
1701         return;
1702     }
1703 }
1704 
1705 void DvbPatSection::initPatSection(const char *data, int size)
1706 {
1707     if (size < 12) {
1708         initSectionData();
1709         return;
1710     }
1711 
1712     initStandardSection(data, size);
1713 }
1714 
1715 void DvbPmtSection::initPmtSection(const char *data, int size)
1716 {
1717     if (size < 16) {
1718         initSectionData();
1719         return;
1720     }
1721 
1722     initStandardSection(data, size);
1723     descriptorsLength = ((at(10) & 0xf) << 8) | at(11);
1724 
1725     if (descriptorsLength > (getLength() - 16)) {
1726         qCWarning(logDvbSi, "Adjusting length on descriptor");
1727         descriptorsLength = (getLength() - 16);
1728     }
1729 }
1730 
1731 void DvbSdtSection::initSdtSection(const char *data, int size)
1732 {
1733     if (size < 15) {
1734         initSectionData();
1735         return;
1736     }
1737 
1738     initStandardSection(data, size);
1739 }
1740 
1741 void DvbEitSection::initEitSection(const char *data, int size)
1742 {
1743     if (size < 18) {
1744         initSectionData();
1745         return;
1746     }
1747 
1748     initStandardSection(data, size);
1749 }
1750 
1751 void DvbNitSection::initNitSection(const char *data, int size)
1752 {
1753     if (size < 16) {
1754         initSectionData();
1755         return;
1756     }
1757 
1758     initStandardSection(data, size);
1759     descriptorsLength = ((at(8) & 0xf) << 8) | at(9);
1760 
1761     if (descriptorsLength > (getLength() - 16)) {
1762         qCWarning(logDvbSi, "Adjusting length on descriptor");
1763         descriptorsLength = (getLength() - 16);
1764     }
1765 
1766     entriesLength = ((at(10 + descriptorsLength) & 0xf) << 8) | at(11 + descriptorsLength);
1767 
1768     if (entriesLength > (getLength() - (16 + descriptorsLength))) {
1769         qCWarning(logDvbSi, "Adjusting length on descriptor");
1770         entriesLength = (getLength() - (16 + descriptorsLength));
1771     }
1772 }
1773 
1774 void AtscMgtSection::initMgtSection(const char *data, int size)
1775 {
1776     if (size < 17) {
1777         initSectionData();
1778         return;
1779     }
1780 
1781     initStandardSection(data, size);
1782 }
1783 
1784 void AtscVctSection::initVctSection(const char *data, int size)
1785 {
1786     if (size < 14) {
1787         initSectionData();
1788         return;
1789     }
1790 
1791     initStandardSection(data, size);
1792 }
1793 
1794 void AtscEitSection::initEitSection(const char *data, int size)
1795 {
1796     if (size < 14) {
1797         initSectionData();
1798         return;
1799     }
1800 
1801     initStandardSection(data, size);
1802 }
1803 
1804 void AtscEttSection::initEttSection(const char *data, int size)
1805 {
1806     if (size < 17) {
1807         initSectionData();
1808         return;
1809     }
1810 
1811     initStandardSection(data, size);
1812 }
1813 
1814 #include "moc_dvbsi.cpp"