vdr  1.7.27
si.c
Go to the documentation of this file.
00001 /***************************************************************************
00002  *       Copyright (c) 2003 by Marcel Wiesweg                              *
00003  *                                                                         *
00004  *   This program is free software; you can redistribute it and/or modify  *
00005  *   it under the terms of the GNU General Public License as published by  *
00006  *   the Free Software Foundation; either version 2 of the License, or     *
00007  *   (at your option) any later version.                                   *
00008  *                                                                         *
00009  *   $Id: si.c 2.6 2011/12/10 15:47:15 kls Exp $
00010  *                                                                         *
00011  ***************************************************************************/
00012 
00013 #include "si.h"
00014 #include <errno.h>
00015 #include <iconv.h>
00016 #include <malloc.h>
00017 #include <stdlib.h> // for broadcaster stupidity workaround
00018 #include <string.h>
00019 #include "descriptor.h"
00020 
00021 namespace SI {
00022 
00023 Object::Object() {
00024 }
00025 
00026 Object::Object(CharArray &d) : data(d) {
00027 }
00028 
00029 void Object::setData(const unsigned char*d, int size, bool doCopy) {
00030    data.assign(d, size, doCopy);
00031 }
00032 
00033 void Object::setData(CharArray &d) {
00034    data=d;
00035 }
00036 
00037 bool Object::checkSize(int offset) {
00038    return data.checkSize(offset);
00039 }
00040 
00041 Section::Section(const unsigned char *data, bool doCopy) {
00042    setData(data, getLength(data), doCopy);
00043 }
00044 
00045 TableId Section::getTableId() const {
00046    return getTableId(data.getData());
00047 }
00048 
00049 int Section::getLength() {
00050    return getLength(data.getData());
00051 }
00052 
00053 TableId Section::getTableId(const unsigned char *d) {
00054    return (TableId)((const SectionHeader *)d)->table_id;
00055 }
00056 
00057 int Section::getLength(const unsigned char *d) {
00058    return HILO(((const SectionHeader *)d)->section_length)+sizeof(SectionHeader);
00059 }
00060 
00061 bool CRCSection::isCRCValid() {
00062    return CRC32::isValid((const char *)data.getData(), getLength()/*, data.FourBytes(getLength()-4)*/);
00063 }
00064 
00065 bool CRCSection::CheckCRCAndParse() {
00066    if (!isCRCValid())
00067       return false;
00068    CheckParse();
00069    return isValid();
00070 }
00071 
00072 int NumberedSection::getTableIdExtension() const {
00073    return getTableIdExtension(data.getData());
00074 }
00075 
00076 int NumberedSection::getTableIdExtension(const unsigned char *d) {
00077    return HILO(((const ExtendedSectionHeader *)d)->table_id_extension);
00078 }
00079 
00080 bool NumberedSection::getCurrentNextIndicator() const {
00081    return data.getData<ExtendedSectionHeader>()->current_next_indicator;
00082 }
00083 
00084 int NumberedSection::getVersionNumber() const {
00085    return data.getData<ExtendedSectionHeader>()->version_number;
00086 }
00087 
00088 int NumberedSection::getSectionNumber() const {
00089    return data.getData<ExtendedSectionHeader>()->section_number;
00090 }
00091 
00092 int NumberedSection::getLastSectionNumber() const {
00093    return data.getData<ExtendedSectionHeader>()->last_section_number;
00094 }
00095 
00096 int Descriptor::getLength() {
00097    return getLength(data.getData());
00098 }
00099 
00100 DescriptorTag Descriptor::getDescriptorTag() const {
00101    return getDescriptorTag(data.getData());
00102 }
00103 
00104 int Descriptor::getLength(const unsigned char *d) {
00105    return ((const DescriptorHeader*)d)->descriptor_length+sizeof(DescriptorHeader);
00106 }
00107 
00108 DescriptorTag Descriptor::getDescriptorTag(const unsigned char *d) {
00109    return (DescriptorTag)((const DescriptorHeader*)d)->descriptor_tag;
00110 }
00111 
00112 Descriptor *DescriptorLoop::getNext(Iterator &it) {
00113    if (isValid() && it.i<getLength()) {
00114       return createDescriptor(it.i, true);
00115    }
00116    return 0;
00117 }
00118 
00119 Descriptor *DescriptorLoop::getNext(Iterator &it, DescriptorTag tag, bool returnUnimplemetedDescriptor) {
00120    Descriptor *d=0;
00121    int len;
00122    if (isValid() && it.i<(len=getLength())) {
00123       const unsigned char *p=data.getData(it.i);
00124       const unsigned char *end=p+len-it.i;
00125       while (p < end) {
00126          if (Descriptor::getDescriptorTag(p) == tag) {
00127             d=createDescriptor(it.i, returnUnimplemetedDescriptor);
00128             if (d)
00129                break;
00130          }
00131          it.i+=Descriptor::getLength(p);
00132          p+=Descriptor::getLength(p);
00133       }
00134    }
00135    return d;
00136 }
00137 
00138 Descriptor *DescriptorLoop::getNext(Iterator &it, DescriptorTag *tags, int arrayLength, bool returnUnimplementedDescriptor) {
00139    Descriptor *d=0;
00140    int len;
00141    if (isValid() && it.i<(len=getLength())) {
00142       const unsigned char *p=data.getData(it.i);
00143       const unsigned char *end=p+len-it.i;
00144       while (p < end) {
00145          for (int u=0; u<arrayLength;u++)
00146             if (Descriptor::getDescriptorTag(p) == tags[u]) {
00147                d=createDescriptor(it.i, returnUnimplementedDescriptor);
00148                break;
00149             }
00150          if (d)
00151             break; //length is added to it.i by createDescriptor, break here
00152          it.i+=Descriptor::getLength(p);
00153          p+=Descriptor::getLength(p);
00154       }
00155    }
00156    return d;
00157 }
00158 
00159 Descriptor *DescriptorLoop::createDescriptor(int &i, bool returnUnimplemetedDescriptor) {
00160    if (!checkSize(Descriptor::getLength(data.getData(i))))
00161       return 0;
00162    Descriptor *d=Descriptor::getDescriptor(data+i, domain, returnUnimplemetedDescriptor);
00163    if (!d)
00164       return 0;
00165    i+=d->getLength();
00166    d->CheckParse();
00167    return d;
00168 }
00169 
00170 int DescriptorLoop::getNumberOfDescriptors() {
00171    const unsigned char *p=data.getData();
00172    const unsigned char *end=p+getLength();
00173    int count=0;
00174    while (p < end) {
00175       count++;
00176       p+=Descriptor::getLength(p);
00177    }
00178    return count;
00179 }
00180 
00181 DescriptorGroup::DescriptorGroup(bool del) {
00182    array=0;
00183    length=0;
00184    deleteOnDesctruction=del;
00185 }
00186 
00187 DescriptorGroup::~DescriptorGroup() {
00188    if (deleteOnDesctruction)
00189       Delete();
00190    delete[] array;
00191 }
00192 
00193 void DescriptorGroup::Delete() {
00194    for (int i=0;i<length;i++)
00195       if (array[i]!=0) {
00196          delete array[i];
00197          array[i]=0;
00198       }
00199 }
00200 
00201 void DescriptorGroup::Add(GroupDescriptor *d) {
00202    if (!array) {
00203       length=d->getLastDescriptorNumber()+1;
00204       array=new GroupDescriptor*[length]; //numbering is zero-based
00205       for (int i=0;i<length;i++)
00206          array[i]=0;
00207    } else if (length != d->getLastDescriptorNumber()+1)
00208       return; //avoid crash in case of misuse
00209    if (length <= d->getDescriptorNumber())
00210       return; // see http://www.vdr-portal.de/board60-linux/board14-betriebssystem/board69-c-t-vdr/p1025777-segfault-mit-vdr-1-7-21/#post1025777
00211    array[d->getDescriptorNumber()]=d;
00212 }
00213 
00214 bool DescriptorGroup::isComplete() {
00215    for (int i=0;i<length;i++)
00216       if (array[i]==0)
00217          return false;
00218    return true;
00219 }
00220 
00221 char *String::getText() {
00222    int len=getLength();
00223    if (len < 0 || len > 4095)
00224       return strdup("text error"); // caller will delete it!
00225    char *data=new char(len+1); // FIXME If this function is ever actually used, this buffer might
00226                                // need to be bigger in order to hold the string as UTF-8.
00227                                // Maybe decodeText should dynamically handle this? kls 2007-06-10
00228    decodeText(data, len+1);
00229    return data;
00230 }
00231 
00232 char *String::getText(char *buffer, int size) {
00233    int len=getLength();
00234    if (len < 0 || len >= size) {
00235       strncpy(buffer, "text error", size);
00236       buffer[size-1] = 0;
00237       return buffer;
00238    }
00239    decodeText(buffer, size);
00240    return buffer;
00241 }
00242 
00243 char *String::getText(char *buffer, char *shortVersion, int sizeBuffer, int sizeShortVersion) {
00244    int len=getLength();
00245    if (len < 0 || len >= sizeBuffer) {
00246       strncpy(buffer, "text error", sizeBuffer);
00247       buffer[sizeBuffer-1] = 0;
00248       *shortVersion = 0;
00249       return buffer;
00250    }
00251    decodeText(buffer, shortVersion, sizeBuffer, sizeShortVersion);
00252    return buffer;
00253 }
00254 
00255 static const char *CharacterTables1[] = {
00256   NULL,          // 0x00
00257   "ISO-8859-5",  // 0x01
00258   "ISO-8859-6",  // 0x02
00259   "ISO-8859-7",  // 0x03
00260   "ISO-8859-8",  // 0x04
00261   "ISO-8859-9",  // 0x05
00262   "ISO-8859-10", // 0x06
00263   "ISO-8859-11", // 0x07
00264   "ISO-8859-12", // 0x08
00265   "ISO-8859-13", // 0x09
00266   "ISO-8859-14", // 0x0A
00267   "ISO-8859-15", // 0x0B
00268   NULL,          // 0x0C
00269   NULL,          // 0x0D
00270   NULL,          // 0x0E
00271   NULL,          // 0x0F
00272   NULL,          // 0x10
00273   "UTF-16",      // 0x11
00274   "EUC-KR",      // 0x12
00275   "GB2312",      // 0x13
00276   "GBK",         // 0x14
00277   "UTF-8",       // 0x15
00278   NULL,          // 0x16
00279   NULL,          // 0x17
00280   NULL,          // 0x18
00281   NULL,          // 0x19
00282   NULL,          // 0x1A
00283   NULL,          // 0x1B
00284   NULL,          // 0x1C
00285   NULL,          // 0x1D
00286   NULL,          // 0x1E
00287   NULL,          // 0x1F
00288 };
00289 
00290 #define SingleByteLimit 0x0B
00291 
00292 static const char *CharacterTables2[] = {
00293   NULL,          // 0x00
00294   "ISO-8859-1",  // 0x01
00295   "ISO-8859-2",  // 0x02
00296   "ISO-8859-3",  // 0x03
00297   "ISO-8859-4",  // 0x04
00298   "ISO-8859-5",  // 0x05
00299   "ISO-8859-6",  // 0x06
00300   "ISO-8859-7",  // 0x07
00301   "ISO-8859-8",  // 0x08
00302   "ISO-8859-9",  // 0x09
00303   "ISO-8859-10", // 0x0A
00304   "ISO-8859-11", // 0x0B
00305   NULL,          // 0x0C
00306   "ISO-8859-13", // 0x0D
00307   "ISO-8859-14", // 0x0E
00308   "ISO-8859-15", // 0x0F
00309 };
00310 
00311 #define NumEntries(Table) (sizeof(Table) / sizeof(char *))
00312 
00313 static const char *SystemCharacterTable = NULL;
00314 bool SystemCharacterTableIsSingleByte = true;
00315 
00316 bool systemCharacterTableIsSingleByte(void)
00317 {
00318   return SystemCharacterTableIsSingleByte;
00319 }
00320 
00321 bool SetSystemCharacterTable(const char *CharacterTable) {
00322    if (CharacterTable) {
00323       for (unsigned int i = 0; i < NumEntries(CharacterTables1); i++) {
00324          if (CharacterTables1[i] && strcasecmp(CharacterTable, CharacterTables1[i]) == 0) {
00325             SystemCharacterTable = CharacterTables1[i];
00326             SystemCharacterTableIsSingleByte = i <= SingleByteLimit;
00327             return true;
00328          }
00329       }
00330       for (unsigned int i = 0; i < NumEntries(CharacterTables2); i++) {
00331          if (CharacterTables2[i] && strcasecmp(CharacterTable, CharacterTables2[i]) == 0) {
00332             SystemCharacterTable = CharacterTables2[i];
00333             SystemCharacterTableIsSingleByte = true;
00334             return true;
00335          }
00336       }
00337    } else {
00338       SystemCharacterTable = NULL;
00339       SystemCharacterTableIsSingleByte = true;
00340       return true;
00341    }
00342    return false;
00343 }
00344 
00345 const char *getCharacterTable(const unsigned char *&buffer, int &length, bool *isSingleByte) {
00346    const char *cs = "ISO6937";
00347    // Workaround for broadcaster stupidity: according to
00348    // "ETSI EN 300 468" the default character set is ISO6937. But unfortunately some
00349    // broadcasters actually use ISO-8859-9, but fail to correctly announce that.
00350    static const char *CharsetOverride = getenv("VDR_CHARSET_OVERRIDE");
00351    if (CharsetOverride)
00352       cs = CharsetOverride;
00353    if (isSingleByte)
00354       *isSingleByte = false;
00355    if (length <= 0)
00356       return cs;
00357    unsigned int tag = buffer[0];
00358    if (tag >= 0x20)
00359       return cs;
00360    if (tag == 0x10) {
00361       if (length >= 3) {
00362          tag = (buffer[1] << 8) | buffer[2];
00363          if (tag < NumEntries(CharacterTables2) && CharacterTables2[tag]) {
00364             buffer += 3;
00365             length -= 3;
00366             if (isSingleByte)
00367                *isSingleByte = true;
00368             return CharacterTables2[tag];
00369          }
00370       }
00371    } else if (tag < NumEntries(CharacterTables1) && CharacterTables1[tag]) {
00372       buffer += 1;
00373       length -= 1;
00374       if (isSingleByte)
00375          *isSingleByte = tag <= SingleByteLimit;
00376       return CharacterTables1[tag];
00377    }
00378    return cs;
00379 }
00380 
00381 bool convertCharacterTable(const char *from, size_t fromLength, char *to, size_t toLength, const char *fromCode)
00382 {
00383   if (SystemCharacterTable) {
00384      iconv_t cd = iconv_open(SystemCharacterTable, fromCode);
00385      if (cd != (iconv_t)-1) {
00386         char *fromPtr = (char *)from;
00387         while (fromLength > 0 && toLength > 1) {
00388            if (iconv(cd, &fromPtr, &fromLength, &to, &toLength) == size_t(-1)) {
00389               if (errno == EILSEQ) {
00390                  // A character can't be converted, so mark it with '?' and proceed:
00391                  fromPtr++;
00392                  fromLength--;
00393                  *to++ = '?';
00394                  toLength--;
00395               }
00396               else
00397                  break;
00398            }
00399         }
00400         *to = 0;
00401         iconv_close(cd);
00402         return true;
00403      }
00404   }
00405   return false;
00406 }
00407 
00408 // originally from libdtv, Copyright Rolf Hakenes <hakenes@hippomi.de>
00409 void String::decodeText(char *buffer, int size) {
00410    const unsigned char *from=data.getData(0);
00411    char *to=buffer;
00412    int len=getLength();
00413    if (len <= 0) {
00414       *to = '\0';
00415       return;
00416       }
00417    bool singleByte;
00418    const char *cs = getCharacterTable(from, len, &singleByte);
00419    // FIXME Need to make this UTF-8 aware (different control codes).
00420    // However, there's yet to be found a broadcaster that actually
00421    // uses UTF-8 for the SI data... (kls 2007-06-10)
00422    for (int i = 0; i < len; i++) {
00423       if (*from == 0)
00424          break;
00425       if (    ((' ' <= *from) && (*from <= '~'))
00426            || (*from == '\n')
00427            || (0xA0 <= *from)
00428          )
00429          *to++ = *from;
00430       else if (*from == 0x8A)
00431          *to++ = '\n';
00432       from++;
00433       if (to - buffer >= size - 1)
00434          break;
00435    }
00436    *to = '\0';
00437    if (!singleByte || !SystemCharacterTableIsSingleByte) {
00438       char convBuffer[size];
00439       if (convertCharacterTable(buffer, strlen(buffer), convBuffer, sizeof(convBuffer), cs))
00440          strncpy(buffer, convBuffer, strlen(convBuffer) + 1);
00441    }
00442 }
00443 
00444 void String::decodeText(char *buffer, char *shortVersion, int sizeBuffer, int sizeShortVersion) {
00445    const unsigned char *from=data.getData(0);
00446    char *to=buffer;
00447    char *toShort=shortVersion;
00448    int IsShortName=0;
00449    int len=getLength();
00450    if (len <= 0) {
00451       *to = '\0';
00452       *toShort = '\0';
00453       return;
00454       }
00455    bool singleByte;
00456    const char *cs = getCharacterTable(from, len, &singleByte);
00457    // FIXME Need to make this UTF-8 aware (different control codes).
00458    // However, there's yet to be found a broadcaster that actually
00459    // uses UTF-8 for the SI data... (kls 2007-06-10)
00460    for (int i = 0; i < len; i++) {
00461       if (    ((' ' <= *from) && (*from <= '~'))
00462            || (*from == '\n')
00463            || (0xA0 <= *from)
00464          )
00465       {
00466          *to++ = *from;
00467          if (IsShortName)
00468             *toShort++ = *from;
00469       }
00470       else if (*from == 0x8A)
00471          *to++ = '\n';
00472       else if (*from == 0x86)
00473          IsShortName++;
00474       else if (*from == 0x87)
00475          IsShortName--;
00476       else if (*from == 0)
00477          break;
00478       from++;
00479       if (to - buffer >= sizeBuffer - 1 || toShort - shortVersion >= sizeShortVersion - 1)
00480          break;
00481    }
00482    *to = '\0';
00483    *toShort = '\0';
00484    if (!singleByte || !SystemCharacterTableIsSingleByte) {
00485       char convBuffer[sizeBuffer];
00486       if (convertCharacterTable(buffer, strlen(buffer), convBuffer, sizeof(convBuffer), cs))
00487          strncpy(buffer, convBuffer, strlen(convBuffer) + 1);
00488       char convShortVersion[sizeShortVersion];
00489       if (convertCharacterTable(shortVersion, strlen(shortVersion), convShortVersion, sizeof(convShortVersion), cs))
00490          strncpy(shortVersion, convShortVersion, strlen(convShortVersion) + 1);
00491    }
00492 }
00493 
00494 Descriptor *Descriptor::getDescriptor(CharArray da, DescriptorTagDomain domain, bool returnUnimplemetedDescriptor) {
00495    Descriptor *d=0;
00496    switch (domain) {
00497    case SI:
00498       switch ((DescriptorTag)da.getData<DescriptorHeader>()->descriptor_tag) {
00499          case CaDescriptorTag:
00500             d=new CaDescriptor();
00501             break;
00502          case CarouselIdentifierDescriptorTag:
00503             d=new CarouselIdentifierDescriptor();
00504             break;
00505          case NetworkNameDescriptorTag:
00506             d=new NetworkNameDescriptor();
00507             break;
00508          case ServiceListDescriptorTag:
00509             d=new ServiceListDescriptor();
00510             break;
00511          case SatelliteDeliverySystemDescriptorTag:
00512             d=new SatelliteDeliverySystemDescriptor();
00513             break;
00514          case CableDeliverySystemDescriptorTag:
00515             d=new CableDeliverySystemDescriptor();
00516             break;
00517          case TerrestrialDeliverySystemDescriptorTag:
00518             d=new TerrestrialDeliverySystemDescriptor();
00519             break;
00520          case BouquetNameDescriptorTag:
00521             d=new BouquetNameDescriptor();
00522             break;
00523          case ServiceDescriptorTag:
00524             d=new ServiceDescriptor();
00525             break;
00526          case NVODReferenceDescriptorTag:
00527             d=new NVODReferenceDescriptor();
00528             break;
00529          case TimeShiftedServiceDescriptorTag:
00530             d=new TimeShiftedServiceDescriptor();
00531             break;
00532          case ComponentDescriptorTag:
00533             d=new ComponentDescriptor();
00534             break;
00535          case StreamIdentifierDescriptorTag:
00536             d=new StreamIdentifierDescriptor();
00537             break;
00538          case SubtitlingDescriptorTag:
00539             d=new SubtitlingDescriptor();
00540             break;
00541          case MultilingualNetworkNameDescriptorTag:
00542             d=new MultilingualNetworkNameDescriptor();
00543             break;
00544          case MultilingualBouquetNameDescriptorTag:
00545             d=new MultilingualBouquetNameDescriptor();
00546             break;
00547          case MultilingualServiceNameDescriptorTag:
00548             d=new MultilingualServiceNameDescriptor();
00549             break;
00550          case MultilingualComponentDescriptorTag:
00551             d=new MultilingualComponentDescriptor();
00552             break;
00553          case PrivateDataSpecifierDescriptorTag:
00554             d=new PrivateDataSpecifierDescriptor();
00555             break;
00556          case ServiceMoveDescriptorTag:
00557             d=new ServiceMoveDescriptor();
00558             break;
00559          case FrequencyListDescriptorTag:
00560             d=new FrequencyListDescriptor();
00561             break;
00562          case ServiceIdentifierDescriptorTag:
00563             d=new ServiceIdentifierDescriptor();
00564             break;
00565          case CaIdentifierDescriptorTag:
00566             d=new CaIdentifierDescriptor();
00567             break;
00568          case ShortEventDescriptorTag:
00569             d=new ShortEventDescriptor();
00570             break;
00571          case ExtendedEventDescriptorTag:
00572             d=new ExtendedEventDescriptor();
00573             break;
00574          case TimeShiftedEventDescriptorTag:
00575             d=new TimeShiftedEventDescriptor();
00576             break;
00577          case ContentDescriptorTag:
00578             d=new ContentDescriptor();
00579             break;
00580          case ParentalRatingDescriptorTag:
00581             d=new ParentalRatingDescriptor();
00582             break;
00583          case TeletextDescriptorTag:
00584          case VBITeletextDescriptorTag:
00585             d=new TeletextDescriptor();
00586             break;
00587          case ApplicationSignallingDescriptorTag:
00588             d=new ApplicationSignallingDescriptor();
00589             break;
00590          case LocalTimeOffsetDescriptorTag:
00591             d=new LocalTimeOffsetDescriptor();
00592             break;
00593          case LinkageDescriptorTag:
00594             d=new LinkageDescriptor();
00595             break;
00596          case ISO639LanguageDescriptorTag:
00597             d=new ISO639LanguageDescriptor();
00598             break;
00599          case PDCDescriptorTag:
00600             d=new PDCDescriptor();
00601             break;
00602          case AncillaryDataDescriptorTag:
00603             d=new AncillaryDataDescriptor();
00604             break;
00605          case S2SatelliteDeliverySystemDescriptorTag:
00606             d=new S2SatelliteDeliverySystemDescriptor();
00607             break;
00608          case ExtensionDescriptorTag:
00609             d=new ExtensionDescriptor();
00610             break;
00611          case RegistrationDescriptorTag:
00612             d=new RegistrationDescriptor();
00613             break;
00614          case ContentIdentifierDescriptorTag:
00615             d=new ContentIdentifierDescriptor();
00616             break;
00617          case DefaultAuthorityDescriptorTag:
00618             d=new DefaultAuthorityDescriptor();
00619             break;
00620 
00621          //note that it is no problem to implement one
00622          //of the unimplemented descriptors.
00623 
00624          //defined in ISO-13818-1
00625          case VideoStreamDescriptorTag:
00626          case AudioStreamDescriptorTag:
00627          case HierarchyDescriptorTag:
00628          case DataStreamAlignmentDescriptorTag:
00629          case TargetBackgroundGridDescriptorTag:
00630          case VideoWindowDescriptorTag:
00631          case SystemClockDescriptorTag:
00632          case MultiplexBufferUtilizationDescriptorTag:
00633          case CopyrightDescriptorTag:
00634          case MaximumBitrateDescriptorTag:
00635          case PrivateDataIndicatorDescriptorTag:
00636          case SmoothingBufferDescriptorTag:
00637          case STDDescriptorTag:
00638          case IBPDescriptorTag:
00639 
00640          //defined in ETSI EN 300 468
00641          case StuffingDescriptorTag:
00642          case VBIDataDescriptorTag:
00643          case CountryAvailabilityDescriptorTag:
00644          case MocaicDescriptorTag:
00645          case TelephoneDescriptorTag:
00646          case CellListDescriptorTag:
00647          case CellFrequencyLinkDescriptorTag:
00648          case ServiceAvailabilityDescriptorTag:
00649          case ShortSmoothingBufferDescriptorTag:
00650          case PartialTransportStreamDescriptorTag:
00651          case DataBroadcastDescriptorTag:
00652          case DataBroadcastIdDescriptorTag:
00653          case ScramblingDescriptorTag:
00654          case AC3DescriptorTag:
00655          case DSNGDescriptorTag:
00656          case AnnouncementSupportDescriptorTag:
00657          case AdaptationFieldDataDescriptorTag:
00658          case TransportStreamDescriptorTag:
00659 
00660          //defined in ETSI EN 300 468 v 1.7.1
00661          case RelatedContentDescriptorTag:
00662          case TVAIdDescriptorTag:
00663          case TimeSliceFecIdentifierDescriptorTag:
00664          case ECMRepetitionRateDescriptorTag:
00665          case EnhancedAC3DescriptorTag:
00666          case DTSDescriptorTag:
00667          case AACDescriptorTag:
00668          default:
00669             if (!returnUnimplemetedDescriptor)
00670                return 0;
00671             d=new UnimplementedDescriptor();
00672             break;
00673       }
00674       break;
00675    case MHP:
00676       switch ((DescriptorTag)da.getData<DescriptorHeader>()->descriptor_tag) {
00677       // They once again start with 0x00 (see page 234, MHP specification)
00678          case MHP_ApplicationDescriptorTag:
00679             d=new MHP_ApplicationDescriptor();
00680             break;
00681          case MHP_ApplicationNameDescriptorTag:
00682             d=new MHP_ApplicationNameDescriptor();
00683             break;
00684          case MHP_TransportProtocolDescriptorTag:
00685             d=new MHP_TransportProtocolDescriptor();
00686             break;
00687          case MHP_DVBJApplicationDescriptorTag:
00688             d=new MHP_DVBJApplicationDescriptor();
00689             break;
00690          case MHP_DVBJApplicationLocationDescriptorTag:
00691             d=new MHP_DVBJApplicationLocationDescriptor();
00692             break;
00693          case MHP_SimpleApplicationLocationDescriptorTag:
00694             d=new MHP_SimpleApplicationLocationDescriptor();
00695             break;
00696       // 0x05 - 0x0A is unimplemented this library
00697          case MHP_ExternalApplicationAuthorisationDescriptorTag:
00698          case MHP_IPv4RoutingDescriptorTag:
00699          case MHP_IPv6RoutingDescriptorTag:
00700          case MHP_DVBHTMLApplicationDescriptorTag:
00701          case MHP_DVBHTMLApplicationLocationDescriptorTag:
00702          case MHP_DVBHTMLApplicationBoundaryDescriptorTag:
00703          case MHP_ApplicationIconsDescriptorTag:
00704          case MHP_PrefetchDescriptorTag:
00705          case MHP_DelegatedApplicationDescriptorTag:
00706          case MHP_ApplicationStorageDescriptorTag:
00707          default:
00708             if (!returnUnimplemetedDescriptor)
00709                return 0;
00710             d=new UnimplementedDescriptor();
00711             break;
00712       }
00713       break;
00714    case PCIT:
00715       switch ((DescriptorTag)da.getData<DescriptorHeader>()->descriptor_tag) {
00716          case ContentDescriptorTag:
00717             d=new ContentDescriptor();
00718             break;
00719          case ShortEventDescriptorTag:
00720             d=new ShortEventDescriptor();
00721             break;
00722          case ExtendedEventDescriptorTag:
00723             d=new ExtendedEventDescriptor();
00724             break;
00725          case PremiereContentTransmissionDescriptorTag:
00726             d=new PremiereContentTransmissionDescriptor();
00727             break;
00728          default:
00729             if (!returnUnimplemetedDescriptor)
00730                return 0;
00731             d=new UnimplementedDescriptor();
00732             break;
00733       }
00734       break;
00735    default: ; // unknown domain, nothing to do
00736    }
00737    d->setData(da);
00738    return d;
00739 }
00740 
00741 } //end of namespace