SASC
DVBSoftCAM

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 1.16 2006/04/14 10:53:44 kls Exp $
00010  *                                                                         *
00011  ***************************************************************************/
00012 
00013 #include <string.h>
00014 #include "si.h"
00015 #include "descriptor.h"
00016 
00017 namespace SI {
00018 
00019 Object::Object() {
00020 }
00021 
00022 Object::Object(CharArray &d) : data(d) {
00023 }
00024 
00025 void Object::setData(const unsigned char*d, int size, bool doCopy) {
00026    data.assign(d, size, doCopy);
00027 }
00028 
00029 void Object::setData(CharArray &d) {
00030    data=d;
00031 }
00032 
00033 bool Object::checkSize(int offset) {
00034    return data.checkSize(offset);
00035 }
00036 
00037 Section::Section(const unsigned char *data, bool doCopy) {
00038    setData(data, getLength(data), doCopy);
00039 }
00040 
00041 TableId Section::getTableId() const {
00042    return getTableId(data.getData());
00043 }
00044 
00045 int Section::getLength() {
00046    return getLength(data.getData());
00047 }
00048 
00049 TableId Section::getTableId(const unsigned char *d) {
00050    return (TableId)((const SectionHeader *)d)->table_id;
00051 }
00052 
00053 int Section::getLength(const unsigned char *d) {
00054    return HILO(((const SectionHeader *)d)->section_length)+sizeof(SectionHeader);
00055 }
00056 
00057 bool CRCSection::isCRCValid() {
00058    return CRC32::isValid((const char *)data.getData(), getLength()/*, data.FourBytes(getLength()-4)*/);
00059 }
00060 
00061 bool CRCSection::CheckCRCAndParse() {
00062    if (!isCRCValid())
00063       return false;
00064    CheckParse();
00065    return isValid();
00066 }
00067 
00068 int NumberedSection::getTableIdExtension() const {
00069    return getTableIdExtension(data.getData());
00070 }
00071 
00072 int NumberedSection::getTableIdExtension(const unsigned char *d) {
00073    return HILO(((const ExtendedSectionHeader *)d)->table_id_extension);
00074 }
00075 
00076 bool NumberedSection::getCurrentNextIndicator() const {
00077    return data.getData<ExtendedSectionHeader>()->current_next_indicator;
00078 }
00079 
00080 int NumberedSection::getVersionNumber() const {
00081    return data.getData<ExtendedSectionHeader>()->version_number;
00082 }
00083 
00084 int NumberedSection::getSectionNumber() const {
00085    return data.getData<ExtendedSectionHeader>()->section_number;
00086 }
00087 
00088 int NumberedSection::getLastSectionNumber() const {
00089    return data.getData<ExtendedSectionHeader>()->last_section_number;
00090 }
00091 
00092 int Descriptor::getLength() {
00093    return getLength(data.getData());
00094 }
00095 
00096 DescriptorTag Descriptor::getDescriptorTag() const {
00097    return getDescriptorTag(data.getData());
00098 }
00099 
00100 int Descriptor::getLength(const unsigned char *d) {
00101    return ((const DescriptorHeader*)d)->descriptor_length+sizeof(DescriptorHeader);
00102 }
00103 
00104 DescriptorTag Descriptor::getDescriptorTag(const unsigned char *d) {
00105    return (DescriptorTag)((const DescriptorHeader*)d)->descriptor_tag;
00106 }
00107 
00108 Descriptor *DescriptorLoop::getNext(Iterator &it) {
00109    if (isValid() && it.i<getLength()) {
00110       return createDescriptor(it.i, true);
00111    }
00112    return 0;
00113 }
00114 
00115 Descriptor *DescriptorLoop::getNext(Iterator &it, DescriptorTag tag, bool returnUnimplemetedDescriptor) {
00116    Descriptor *d=0;
00117    int len;
00118    if (isValid() && it.i<(len=getLength())) {
00119       const unsigned char *p=data.getData(it.i);
00120       const unsigned char *end=p+len-it.i;
00121       while (p < end) {
00122          if (Descriptor::getDescriptorTag(p) == tag) {
00123             d=createDescriptor(it.i, returnUnimplemetedDescriptor);
00124             if (d)
00125                break;
00126          }
00127          it.i+=Descriptor::getLength(p);
00128          p+=Descriptor::getLength(p);
00129       }
00130    }
00131    return d;
00132 }
00133 
00134 Descriptor *DescriptorLoop::getNext(Iterator &it, DescriptorTag *tags, int arrayLength, bool returnUnimplementedDescriptor) {
00135    Descriptor *d=0;
00136    int len;
00137    if (isValid() && it.i<(len=getLength())) {
00138       const unsigned char *p=data.getData(it.i);
00139       const unsigned char *end=p+len-it.i;
00140       while (p < end) {
00141          for (int u=0; u<arrayLength;u++)
00142             if (Descriptor::getDescriptorTag(p) == tags[u]) {
00143                d=createDescriptor(it.i, returnUnimplementedDescriptor);
00144                break;
00145             }
00146          if (d)
00147             break; //length is added to it.i by createDescriptor, break here
00148          it.i+=Descriptor::getLength(p);
00149          p+=Descriptor::getLength(p);
00150       }
00151    }
00152    return d;
00153 }
00154 
00155 Descriptor *DescriptorLoop::createDescriptor(int &i, bool returnUnimplemetedDescriptor) {
00156    if (!checkSize(Descriptor::getLength(data.getData(i))))
00157       return 0;
00158    Descriptor *d=Descriptor::getDescriptor(data+i, domain, returnUnimplemetedDescriptor);
00159    if (!d)
00160       return 0;
00161    i+=d->getLength();
00162    d->CheckParse();
00163    return d;
00164 }
00165 
00166 int DescriptorLoop::getNumberOfDescriptors() {
00167    const unsigned char *p=data.getData();
00168    const unsigned char *end=p+getLength();
00169    int count=0;
00170    while (p < end) {
00171       count++;
00172       p+=Descriptor::getLength(p);
00173    }
00174    return count;
00175 }
00176 
00177 DescriptorGroup::DescriptorGroup(bool del) {
00178    array=0;
00179    length=0;
00180    deleteOnDesctruction=del;
00181 }
00182 
00183 DescriptorGroup::~DescriptorGroup() {
00184    if (deleteOnDesctruction)
00185       Delete();
00186    delete[] array;
00187 }
00188 
00189 void DescriptorGroup::Delete() {
00190    for (int i=0;i<length;i++)
00191       if (array[i]!=0) {
00192          delete array[i];
00193          array[i]=0;
00194       }
00195 }
00196 
00197 void DescriptorGroup::Add(GroupDescriptor *d) {
00198    if (!array) {
00199       length=d->getLastDescriptorNumber()+1;
00200       array=new GroupDescriptor*[length]; //numbering is zero-based
00201       for (int i=0;i<length;i++)
00202          array[i]=0;
00203    } else if (length != d->getLastDescriptorNumber()+1)
00204       return; //avoid crash in case of misuse
00205    array[d->getDescriptorNumber()]=d;
00206 }
00207 
00208 bool DescriptorGroup::isComplete() {
00209    for (int i=0;i<length;i++)
00210       if (array[i]==0)
00211          return false;
00212    return true;
00213 }
00214 
00215 char *String::getText() {
00216    int len=getLength();
00217    if (len < 0 || len > 4095)
00218       return strdup("text error"); // caller will delete it!
00219    char *data=new char(len+1);
00220    decodeText(data, len+1);
00221    return data;
00222 }
00223 
00224 char *String::getText(char *buffer, int size) {
00225    int len=getLength();
00226    if (len < 0 || len >= size) {
00227       strncpy(buffer, "text error", size);
00228       buffer[size-1] = 0;
00229       return buffer;
00230    }
00231    decodeText(buffer, size);
00232    return buffer;
00233 }
00234 
00235 //taken from VDR, Copyright Klaus Schmidinger <kls@cadsoft.de>
00236 char *String::getText(char *buffer, char *shortVersion, int sizeBuffer, int sizeShortVersion) {
00237    int len=getLength();
00238    if (len < 0 || len >= sizeBuffer) {
00239       strncpy(buffer, "text error", sizeBuffer);
00240       buffer[sizeBuffer-1] = 0;
00241       *shortVersion = 0;
00242       return buffer;
00243    }
00244    decodeText(buffer, shortVersion, sizeBuffer, sizeShortVersion);
00245    return buffer;
00246 }
00247 
00248 //taken from libdtv, Copyright Rolf Hakenes <hakenes@hippomi.de>
00249 void String::decodeText(char *buffer, int size) {
00250    const unsigned char *from=data.getData(0);
00251    char *to=buffer;
00252 
00253    /* Disable detection of coding tables - libdtv doesn't do it either
00254    if ( (0x01 <= *from) && (*from <= 0x1f) ) {
00255       codeTable=*from
00256    }
00257    */
00258 
00259    if (*from == 0x10)
00260       from += 3; // skips code table info
00261 
00262    int len=getLength();
00263    for (int i = 0; i < len; i++) {
00264       if (*from == 0)
00265          break;
00266       if (    ((' ' <= *from) && (*from <= '~'))
00267            || (*from == '\n')
00268            || (0xA0 <= *from)
00269            || (*from == 0x86 || *from == 0x87)
00270          )
00271          *to++ = *from;
00272       else if (*from == 0x8A)
00273          *to++ = '\n';
00274       from++;
00275       if (to - buffer >= size - 1)
00276          break;
00277    }
00278    *to = '\0';
00279 }
00280 
00281 void String::decodeText(char *buffer, char *shortVersion, int sizeBuffer, int sizeShortVersion) {
00282    const unsigned char *from=data.getData(0);
00283    char *to=buffer;
00284    char *toShort=shortVersion;
00285    int IsShortName=0;
00286 
00287    if (*from == 0x10)
00288       from += 3; // skips code table info
00289 
00290    int len=getLength();
00291    for (int i = 0; i < len; i++) {
00292       if (    ((' ' <= *from) && (*from <= '~'))
00293            || (*from == '\n')
00294            || (0xA0 <= *from)
00295          )
00296       {
00297          *to++ = *from;
00298          if (IsShortName)
00299             *toShort++ = *from;
00300       }
00301       else if (*from == 0x8A)
00302          *to++ = '\n';
00303       else if (*from == 0x86)
00304          IsShortName++;
00305       else if (*from == 0x87)
00306          IsShortName--;
00307       else if (*from == 0)
00308          break;
00309       from++;
00310       if (to - buffer >= sizeBuffer - 1 || toShort - shortVersion >= sizeShortVersion - 1)
00311          break;
00312    }
00313    *to = '\0';
00314    *toShort = '\0';
00315 }
00316 
00317 Descriptor *Descriptor::getDescriptor(CharArray da, DescriptorTagDomain domain, bool returnUnimplemetedDescriptor) {
00318    Descriptor *d=0;
00319    switch (domain) {
00320    case SI:
00321       switch ((DescriptorTag)da.getData<DescriptorHeader>()->descriptor_tag) {
00322          case CaDescriptorTag:
00323             d=new CaDescriptor();
00324             break;
00325          case CarouselIdentifierDescriptorTag:
00326             d=new CarouselIdentifierDescriptor();
00327             break;
00328          case NetworkNameDescriptorTag:
00329             d=new NetworkNameDescriptor();
00330             break;
00331          case ServiceListDescriptorTag:
00332             d=new ServiceListDescriptor();
00333             break;
00334          case SatelliteDeliverySystemDescriptorTag:
00335             d=new SatelliteDeliverySystemDescriptor();
00336             break;
00337          case CableDeliverySystemDescriptorTag:
00338             d=new CableDeliverySystemDescriptor();
00339             break;
00340          case TerrestrialDeliverySystemDescriptorTag:
00341             d=new TerrestrialDeliverySystemDescriptor();
00342             break;
00343          case BouquetNameDescriptorTag:
00344             d=new BouquetNameDescriptor();
00345             break;
00346          case ServiceDescriptorTag:
00347             d=new ServiceDescriptor();
00348             break;
00349          case NVODReferenceDescriptorTag:
00350             d=new NVODReferenceDescriptor();
00351             break;
00352          case TimeShiftedServiceDescriptorTag:
00353             d=new TimeShiftedServiceDescriptor();
00354             break;
00355          case ComponentDescriptorTag:
00356             d=new ComponentDescriptor();
00357             break;
00358          case StreamIdentifierDescriptorTag:
00359             d=new StreamIdentifierDescriptor();
00360             break;
00361          case SubtitlingDescriptorTag:
00362             d=new SubtitlingDescriptor();
00363             break;
00364          case MultilingualNetworkNameDescriptorTag:
00365             d=new MultilingualNetworkNameDescriptor();
00366             break;
00367          case MultilingualBouquetNameDescriptorTag:
00368             d=new MultilingualBouquetNameDescriptor();
00369             break;
00370          case MultilingualServiceNameDescriptorTag:
00371             d=new MultilingualServiceNameDescriptor();
00372             break;
00373          case MultilingualComponentDescriptorTag:
00374             d=new MultilingualComponentDescriptor();
00375             break;
00376          case PrivateDataSpecifierDescriptorTag:
00377             d=new PrivateDataSpecifierDescriptor();
00378             break;
00379          case ServiceMoveDescriptorTag:
00380             d=new ServiceMoveDescriptor();
00381             break;
00382          case FrequencyListDescriptorTag:
00383             d=new FrequencyListDescriptor();
00384             break;
00385          case ServiceIdentifierDescriptorTag:
00386             d=new ServiceIdentifierDescriptor();
00387             break;
00388          case CaIdentifierDescriptorTag:
00389             d=new CaIdentifierDescriptor();
00390             break;
00391          case ShortEventDescriptorTag:
00392             d=new ShortEventDescriptor();
00393             break;
00394          case ExtendedEventDescriptorTag:
00395             d=new ExtendedEventDescriptor();
00396             break;
00397          case TimeShiftedEventDescriptorTag:
00398             d=new TimeShiftedEventDescriptor();
00399             break;
00400          case ContentDescriptorTag:
00401             d=new ContentDescriptor();
00402             break;
00403          case ParentalRatingDescriptorTag:
00404             d=new ParentalRatingDescriptor();
00405             break;
00406          case TeletextDescriptorTag:
00407          case VBITeletextDescriptorTag:
00408             d=new TeletextDescriptor();
00409             break;
00410          case ApplicationSignallingDescriptorTag:
00411             d=new ApplicationSignallingDescriptor();
00412             break;
00413          case LocalTimeOffsetDescriptorTag:
00414             d=new LocalTimeOffsetDescriptor();
00415             break;
00416          case LinkageDescriptorTag:
00417             d=new LinkageDescriptor();
00418             break;
00419          case ISO639LanguageDescriptorTag:
00420             d=new ISO639LanguageDescriptor();
00421             break;
00422          case PDCDescriptorTag:
00423             d=new PDCDescriptor();
00424             break;
00425          case AncillaryDataDescriptorTag:
00426             d=new AncillaryDataDescriptor();
00427             break;
00428 
00429          //note that it is no problem to implement one
00430          //of the unimplemented descriptors.
00431 
00432          //defined in ISO-13818-1
00433          case VideoStreamDescriptorTag:
00434          case AudioStreamDescriptorTag:
00435          case HierarchyDescriptorTag:
00436          case RegistrationDescriptorTag:
00437          case DataStreamAlignmentDescriptorTag:
00438          case TargetBackgroundGridDescriptorTag:
00439          case VideoWindowDescriptorTag:
00440          case SystemClockDescriptorTag:
00441          case MultiplexBufferUtilizationDescriptorTag:
00442          case CopyrightDescriptorTag:
00443          case MaximumBitrateDescriptorTag:
00444          case PrivateDataIndicatorDescriptorTag:
00445          case SmoothingBufferDescriptorTag:
00446          case STDDescriptorTag:
00447          case IBPDescriptorTag:
00448 
00449          //defined in ETSI EN 300 468
00450          case StuffingDescriptorTag:
00451          case VBIDataDescriptorTag:
00452          case CountryAvailabilityDescriptorTag:
00453          case MocaicDescriptorTag:
00454          case TelephoneDescriptorTag:
00455          case CellListDescriptorTag:
00456          case CellFrequencyLinkDescriptorTag:
00457          case ServiceAvailabilityDescriptorTag:
00458          case ShortSmoothingBufferDescriptorTag:
00459          case PartialTransportStreamDescriptorTag:
00460          case DataBroadcastDescriptorTag:
00461          case DataBroadcastIdDescriptorTag:
00462          case CaSystemDescriptorTag:
00463          case AC3DescriptorTag:
00464          case DSNGDescriptorTag:
00465          case AnnouncementSupportDescriptorTag:
00466          case AdaptationFieldDataDescriptorTag:
00467          case TransportStreamDescriptorTag:
00468          default:
00469             if (!returnUnimplemetedDescriptor)
00470                return 0;
00471             d=new UnimplementedDescriptor();
00472             break;
00473       }
00474       break;
00475    case MHP:
00476       switch ((DescriptorTag)da.getData<DescriptorHeader>()->descriptor_tag) {
00477       // They once again start with 0x00 (see page 234, MHP specification)
00478          case MHP_ApplicationDescriptorTag:
00479             d=new MHP_ApplicationDescriptor();
00480             break;
00481          case MHP_ApplicationNameDescriptorTag:
00482             d=new MHP_ApplicationNameDescriptor();
00483             break;
00484          case MHP_TransportProtocolDescriptorTag:
00485             d=new MHP_TransportProtocolDescriptor();
00486             break;
00487          case MHP_DVBJApplicationDescriptorTag:
00488             d=new MHP_DVBJApplicationDescriptor();
00489             break;
00490          case MHP_DVBJApplicationLocationDescriptorTag:
00491             d=new MHP_DVBJApplicationLocationDescriptor();
00492             break;
00493       // 0x05 - 0x0A is unimplemented this library
00494          case MHP_ExternalApplicationAuthorisationDescriptorTag:
00495          case MHP_IPv4RoutingDescriptorTag:
00496          case MHP_IPv6RoutingDescriptorTag:
00497          case MHP_DVBHTMLApplicationDescriptorTag:
00498          case MHP_DVBHTMLApplicationLocationDescriptorTag:
00499          case MHP_DVBHTMLApplicationBoundaryDescriptorTag:
00500          case MHP_ApplicationIconsDescriptorTag:
00501          case MHP_PrefetchDescriptorTag:
00502          case MHP_DelegatedApplicationDescriptorTag:
00503          case MHP_ApplicationStorageDescriptorTag:
00504          default:
00505             if (!returnUnimplemetedDescriptor)
00506                return 0;
00507             d=new UnimplementedDescriptor();
00508             break;
00509       }
00510       break;
00511    case PCIT:
00512       switch ((DescriptorTag)da.getData<DescriptorHeader>()->descriptor_tag) {
00513          case ContentDescriptorTag:
00514             d=new ContentDescriptor();
00515             break;
00516          case ShortEventDescriptorTag:
00517             d=new ShortEventDescriptor();
00518             break;
00519          case ExtendedEventDescriptorTag:
00520             d=new ExtendedEventDescriptor();
00521             break;
00522          case PremiereContentTransmissionDescriptorTag:
00523             d=new PremiereContentTransmissionDescriptor();
00524             break;
00525          default:
00526             if (!returnUnimplemetedDescriptor)
00527                return 0;
00528             d=new UnimplementedDescriptor();
00529             break;
00530       }
00531       break;
00532    }
00533    d->setData(da);
00534    return d;
00535 }
00536 
00537 } //end of namespace
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines