vdr  1.7.27
si.h
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.h 2.5 2012/01/11 11:35:17 kls Exp $
00010  *                                                                         *
00011  ***************************************************************************/
00012 
00013 #ifndef LIBSI_SI_H
00014 #define LIBSI_SI_H
00015 
00016 #include <stdint.h>
00017 
00018 #include "util.h"
00019 #include "headers.h"
00020 
00021 namespace SI {
00022 
00023 enum TableId { TableIdPAT = 0x00, //program association section
00024                TableIdCAT = 0x01, //conditional access section
00025                TableIdPMT = 0x02, //program map section
00026                TableIdTSDT = 0x03,//transport stream description section
00027                TableIdNIT = 0x40, //network information, actual network section
00028                TableIdNIT_other  = 0x41, //network information section, other network
00029                TableIdSDT = 0x42, //service description section
00030                TableIdSDT_other  = 0x46,
00031                TableIdBAT = 0x4A, //bouquet association section
00032                TableIdEIT_presentFollowing = 0x4E, //event information section
00033                TableIdEIT_presentFollowing_other = 0x4F,
00034                //range from 0x50 to 0x5F
00035                TableIdEIT_schedule_first = 0x50,
00036                TableIdEIT_schedule_last = 0x5F,
00037                //range from 0x60 to 0x6F
00038                TableIdEIT_schedule_Other_first = 0x60,
00039                TableIdEIT_schedule_Other_last = 0x6F,
00040                TableIdTDT = 0x70, //time date section
00041                TableIdRST = 0x71, //running status section
00042                TableIdST  = 0x72, //stuffing section
00043                TableIdTOT = 0x73, //time offset section
00044                TableIdDIT = 0x7E, //discontinuity information section
00045                TableIdSIT = 0x7F, //service information section
00046                TableIdAIT = 0x74, //application information section
00047                TableIdPremiereCIT = 0xA0 //premiere content information section
00048              };
00049 
00050 
00051 enum DescriptorTag {
00052   // defined by ISO/IEC 13818-1
00053                VideoStreamDescriptorTag = 0x02,
00054                AudioStreamDescriptorTag = 0x03,
00055                HierarchyDescriptorTag = 0x04,
00056                RegistrationDescriptorTag = 0x05,
00057                DataStreamAlignmentDescriptorTag = 0x06,
00058                TargetBackgroundGridDescriptorTag = 0x07,
00059                VideoWindowDescriptorTag = 0x08,
00060                CaDescriptorTag = 0x09,
00061                ISO639LanguageDescriptorTag = 0x0A,
00062                SystemClockDescriptorTag = 0x0B,
00063                MultiplexBufferUtilizationDescriptorTag = 0x0C,
00064                CopyrightDescriptorTag = 0x0D,
00065                MaximumBitrateDescriptorTag = 0x0E,
00066                PrivateDataIndicatorDescriptorTag = 0x0F,
00067                SmoothingBufferDescriptorTag = 0x10,
00068                STDDescriptorTag = 0x11,
00069                IBPDescriptorTag = 0x12,
00070   // defined by ISO-13818-6 (DSM-CC)
00071                CarouselIdentifierDescriptorTag = 0x13,
00072                // 0x14 - 0x3F  Reserved
00073   // defined by ETSI (EN 300 468)
00074                NetworkNameDescriptorTag = 0x40,
00075                ServiceListDescriptorTag = 0x41,
00076                StuffingDescriptorTag = 0x42,
00077                SatelliteDeliverySystemDescriptorTag = 0x43,
00078                CableDeliverySystemDescriptorTag = 0x44,
00079                VBIDataDescriptorTag = 0x45,
00080                VBITeletextDescriptorTag = 0x46,
00081                BouquetNameDescriptorTag = 0x47,
00082                ServiceDescriptorTag = 0x48,
00083                CountryAvailabilityDescriptorTag = 0x49,
00084                LinkageDescriptorTag = 0x4A,
00085                NVODReferenceDescriptorTag = 0x4B,
00086                TimeShiftedServiceDescriptorTag = 0x4C,
00087                ShortEventDescriptorTag = 0x4D,
00088                ExtendedEventDescriptorTag = 0x4E,
00089                TimeShiftedEventDescriptorTag = 0x4F,
00090                ComponentDescriptorTag = 0x50,
00091                MocaicDescriptorTag = 0x51,
00092                StreamIdentifierDescriptorTag = 0x52,
00093                CaIdentifierDescriptorTag = 0x53,
00094                ContentDescriptorTag = 0x54,
00095                ParentalRatingDescriptorTag = 0x55,
00096                TeletextDescriptorTag = 0x56,
00097                TelephoneDescriptorTag = 0x57,
00098                LocalTimeOffsetDescriptorTag = 0x58,
00099                SubtitlingDescriptorTag = 0x59,
00100                TerrestrialDeliverySystemDescriptorTag = 0x5A,
00101                MultilingualNetworkNameDescriptorTag = 0x5B,
00102                MultilingualBouquetNameDescriptorTag = 0x5C,
00103                MultilingualServiceNameDescriptorTag = 0x5D,
00104                MultilingualComponentDescriptorTag = 0x5E,
00105                PrivateDataSpecifierDescriptorTag = 0x5F,
00106                ServiceMoveDescriptorTag = 0x60,
00107                ShortSmoothingBufferDescriptorTag = 0x61,
00108                FrequencyListDescriptorTag = 0x62,
00109                PartialTransportStreamDescriptorTag = 0x63,
00110                DataBroadcastDescriptorTag = 0x64,
00111                ScramblingDescriptorTag = 0x65,
00112                DataBroadcastIdDescriptorTag = 0x66,
00113                TransportStreamDescriptorTag = 0x67,
00114                DSNGDescriptorTag = 0x68,
00115                PDCDescriptorTag = 0x69,
00116                AC3DescriptorTag = 0x6A,
00117                AncillaryDataDescriptorTag = 0x6B,
00118                CellListDescriptorTag = 0x6C,
00119                CellFrequencyLinkDescriptorTag = 0x6D,
00120                AnnouncementSupportDescriptorTag = 0x6E,
00121                ApplicationSignallingDescriptorTag = 0x6F,
00122                AdaptationFieldDataDescriptorTag = 0x70,
00123                ServiceIdentifierDescriptorTag = 0x71,
00124                ServiceAvailabilityDescriptorTag = 0x72,
00125   // defined by ETSI (EN 300 468) v 1.7.1
00126                DefaultAuthorityDescriptorTag = 0x73,
00127                RelatedContentDescriptorTag = 0x74,
00128                TVAIdDescriptorTag = 0x75,
00129                ContentIdentifierDescriptorTag = 0x76,
00130                TimeSliceFecIdentifierDescriptorTag = 0x77,
00131                ECMRepetitionRateDescriptorTag = 0x78,
00132                S2SatelliteDeliverySystemDescriptorTag = 0x79,
00133                EnhancedAC3DescriptorTag = 0x7A,
00134                DTSDescriptorTag = 0x7B,
00135                AACDescriptorTag = 0x7C,
00136                ExtensionDescriptorTag = 0x7F,
00137  // Extension descriptors
00138                ImageIconDescriptorTag = 0x00,
00139                CpcmDeliverySignallingDescriptor = 0x01,
00140                CPDescriptorTag = 0x02,
00141                CPIdentifierDescriptorTag = 0x03,
00142                T2DeliverySystemDescriptorTag = 0x04,
00143                SHDeliverySystemDescriptorTag = 0x05,
00144                SupplementaryAudioDescriptorTag = 0x06,
00145                NetworkChangeNotifyDescriptorTag = 0x07,
00146                MessageDescriptorTag = 0x08,
00147                TargetRegionDescriptorTag = 0x09,
00148                TargetRegionNameDescriptorTag = 0x0A,
00149                ServiceRelocatedDescriptorTag = 0x0B,
00150 
00151  // Defined by ETSI TS 102 812 (MHP)
00152                // They once again start with 0x00 (see page 234, MHP specification)
00153                MHP_ApplicationDescriptorTag = 0x00,
00154                MHP_ApplicationNameDescriptorTag = 0x01,
00155                MHP_TransportProtocolDescriptorTag = 0x02,
00156                MHP_DVBJApplicationDescriptorTag = 0x03,
00157                MHP_DVBJApplicationLocationDescriptorTag = 0x04,
00158                // 0x05 - 0x0A is unimplemented this library
00159                MHP_ExternalApplicationAuthorisationDescriptorTag = 0x05,
00160                MHP_IPv4RoutingDescriptorTag = 0x06,
00161                MHP_IPv6RoutingDescriptorTag = 0x07,
00162                MHP_DVBHTMLApplicationDescriptorTag = 0x08,
00163                MHP_DVBHTMLApplicationLocationDescriptorTag = 0x09,
00164                MHP_DVBHTMLApplicationBoundaryDescriptorTag = 0x0A,
00165                MHP_ApplicationIconsDescriptorTag = 0x0B,
00166                MHP_PrefetchDescriptorTag = 0x0C,
00167                MHP_DelegatedApplicationDescriptorTag = 0x0E,
00168                MHP_ApplicationStorageDescriptorTag = 0x10,
00169                MHP_SimpleApplicationLocationDescriptorTag = 0x15,
00170                MHP_SimpleApplicationBoundaryDescriptorTag = 0x17,
00171   // Premiere private Descriptor Tags
00172                PremiereContentTransmissionDescriptorTag = 0xF2,
00173 
00174                //a descriptor currently unimplemented in this library
00175                //the actual value 0xFF is "forbidden" according to the spec.
00176                UnimplementedDescriptorTag = 0xFF
00177 };
00178 
00179 enum DescriptorTagDomain { SI, MHP, PCIT };
00180 
00181 enum RunningStatus { RunningStatusUndefined = 0,
00182                      RunningStatusNotRunning = 1,
00183                      RunningStatusStartsInAFewSeconds = 2,
00184                      RunningStatusPausing = 3,
00185                      RunningStatusRunning = 4
00186                    };
00187 
00188 enum LinkageType { LinkageTypeInformationService = 0x01,
00189                    LinkageTypeEPGService = 0x02,
00190                    LinkageTypeCaReplacementService = 0x03,
00191                    LinkageTypeTSContainingCompleteNetworkBouquetSi = 0x04,
00192                    LinkageTypeServiceReplacementService = 0x05,
00193                    LinkageTypeDataBroadcastService = 0x06,
00194                    LinkageTypeRCSMap = 0x07,
00195                    LinkageTypeMobileHandover = 0x08,
00196                    LinkageTypeSystemSoftwareUpdateService = 0x09,
00197                    LinkageTypeTSContainingSsuBatOrNit = 0x0A
00198                  };
00199 
00200 enum AudioType { AudioTypeUndefined = 0x00,
00201                  AudioTypeCleanEffects = 0x01,
00202                  AudioTypeHearingImpaired = 0x02,
00203                  AudioTypeVisualImpairedCommentary = 0x03
00204                };
00205 
00206 /* Some principles:
00207    - Objects that return references to other objects contained in their data must make sure
00208      that the returned objects have been parsed.
00209      (the Loop subclasses take care of that.)
00210      Note that this does not apply to Loops and Strings (their are never returned by reference, BTW).
00211 */
00212 
00213 class Object : public Parsable {
00214 public:
00215    Object();
00216    Object(CharArray &d);
00217    //can only be called once since data is immutable
00218    void setData(const unsigned char*data, int size, bool doCopy=true);
00219    CharArray getData() { return data; }
00220    //returns the valid flag which indicates if data is all right or errors have been encountered
00221    bool isValid() { return data.isValid(); }
00222    virtual int getLength() = 0;
00223 protected:
00224    CharArray data;
00225    //is protected - not used for sections
00226    template <class T> friend class StructureLoop;
00227    void setData(CharArray &d);
00228    //returns whether the given offset fits within the limits of the actual data
00229    //The valid flag will be set accordingly
00230    bool checkSize(int offset);
00231 };
00232 
00233 class Section : public Object {
00234 public:
00235    //convenience: sets data and parses if doParse
00236    Section(const unsigned char *data, bool doCopy=true);
00237    Section() {}
00238    TableId getTableId() const;
00239    virtual int getLength();
00240 
00241    static int getLength(const unsigned char *d);
00242    static TableId getTableId(const unsigned char *d);
00243 };
00244 
00245 class CRCSection : public Section {
00246 public:
00247    //convenience: sets data and parses if doParse
00248    CRCSection(const unsigned char *data, bool doCopy=true) : Section(data, doCopy) {}
00249    CRCSection() {}
00250    bool isCRCValid();
00251    //convenience: isValid+CheckParse
00252    bool CheckCRCAndParse();
00253 };
00254 
00255 /* A section which has the ExtendedSectionHeader
00256    (section_syntax_indicator==1) */
00257 class NumberedSection : public CRCSection {
00258 public:
00259    NumberedSection(const unsigned char *data, bool doCopy=true) : CRCSection(data, doCopy) {}
00260    NumberedSection() {}
00261    int getTableIdExtension() const;
00262    bool getCurrentNextIndicator() const;
00263    int getVersionNumber() const;
00264    int getSectionNumber() const;
00265    int getLastSectionNumber() const;
00266    bool moreThanOneSection()  const { return getLastSectionNumber()>0; }
00267 
00268    static int getTableIdExtension(const unsigned char *d);
00269 };
00270 
00271 class VariableLengthPart : public Object {
00272 public:
00273    //never forget to call this
00274    void setData(CharArray d, int l) { Object::setData(d); checkSize(l); length=l; }
00275    //convenience method
00276    void setDataAndOffset(CharArray d, int l, int &offset) { Object::setData(d); checkSize(l); length=l; offset+=l; }
00277    virtual int getLength() { return length; }
00278 private:
00279    int length;
00280 };
00281 
00282 class LoopElement : public Object {
00283 };
00284 
00285 class Descriptor : public LoopElement {
00286 public:
00287    virtual int getLength();
00288    DescriptorTag getDescriptorTag() const;
00289 
00290    static int getLength(const unsigned char *d);
00291    static DescriptorTag getDescriptorTag(const unsigned char *d);
00292 protected:
00293    friend class DescriptorLoop;
00294    //returns a subclass of descriptor according to the data given.
00295    //The object is allocated with new and must be delete'd.
00296    //setData() will have been called, CheckParse() not.
00297    //if returnUnimplemetedDescriptor==true:
00298    //   Never returns null - maybe the UnimplementedDescriptor.
00299    //if returnUnimplemetedDescriptor==false:
00300    //   Never returns the UnimplementedDescriptor - maybe null
00301    static Descriptor *getDescriptor(CharArray d, DescriptorTagDomain domain, bool returnUnimplemetedDescriptor);
00302 };
00303 
00304 class Loop : public VariableLengthPart {
00305 public:
00306    class Iterator {
00307    public:
00308       Iterator() { i=0; }
00309       void reset() { i=0; }
00310    private:
00311       template <class T> friend class StructureLoop;
00312       friend class DescriptorLoop;
00313       template <class T> friend class TypeLoop;
00314       friend class ExtendedEventDescriptors;
00315       int i;
00316    };
00317 protected:
00318    virtual void Parse() {}
00319 };
00320 
00321 //contains LoopElements of one type only
00322 template <class T> class StructureLoop : public Loop {
00323 public:
00324    //currently you must use a while-loop testing for hasNext()
00325    //i must be 0 to get the first descriptor (with the first call)
00326    bool getNext(T &obj, Iterator &it)
00327       {
00328          if (!isValid() || it.i >= getLength())
00329             return false;
00330          CharArray d=data;
00331          d.addOffset(it.i);
00332          T ret;
00333          ret.setData(d);
00334          ret.CheckParse();
00335          if (!checkSize(ret.getLength()))
00336             return false;
00337          it.i+=ret.getLength();
00338          obj=ret;
00339          return true;
00340       }
00341    T* getNextAsPointer(Iterator &it)
00342       {
00343          if (!isValid() || it.i >= getLength())
00344             return 0;
00345          CharArray d=data;
00346          d.addOffset(it.i);
00347          T *ret=new T();
00348          ret->setData(d);
00349          ret->CheckParse();
00350          if (!checkSize(ret->getLength()))
00351             return 0;
00352          it.i+=ret->getLength();
00353          return ret;
00354       }
00355    //bool hasNext(Iterator &it) { return getLength() > it.i; }
00356 };
00357 
00358 //contains descriptors of different types
00359 class DescriptorLoop : public Loop {
00360 public:
00361    DescriptorLoop() { domain=SI; }
00362    //i must be 0 to get the first descriptor (with the first call)
00363    //All returned descriptors must be delete'd.
00364    //returns null if no more descriptors available
00365    Descriptor *getNext(Iterator &it);
00366    //return the next descriptor with given tag, or 0 if not available.
00367    //if returnUnimplemetedDescriptor==true:
00368    //   an UnimplementedDescriptor may be returned if the next matching descriptor is unimplemented,
00369    //   0 will be returned if and only if no matching descriptor is found.
00370    //if returnUnimplemetedDescriptor==false:
00371    //   if 0 is returned, either no descriptor with the given tag was found,
00372    //   or descriptors were found, but the descriptor type is not implemented
00373    //In either case, a return value of 0 indicates that no further calls to this method
00374    //with the iterator shall be made.
00375    Descriptor *getNext(Iterator &it, DescriptorTag tag, bool returnUnimplemetedDescriptor=false);
00376    //return the next descriptor with one of the given tags, or 0 if not available.
00377    //if returnUnimplemetedDescriptor==true:
00378    //   returns 0 if and only if no descriptor with one of the given tags was found.
00379    //   The UnimplementedDescriptor may be returned.
00380    //if returnUnimplemetedDescriptor==false:
00381    //   if 0 is returned, either no descriptor with one of the given tags was found,
00382    //   or descriptors were found, but none of them are implemented.
00383    //   The UnimplementedDescriptor will never be returned.
00384    //In either case, a return value of 0 indicates that no further calls to this method
00385    //with the iterator shall be made.
00386    Descriptor *getNext(Iterator &it, DescriptorTag *tags, int arrayLength, bool returnUnimplemetedDescriptor=false);
00387    //returns the number of descriptors in this loop
00388    int getNumberOfDescriptors();
00389    //writes the tags of the descriptors in this loop in the array,
00390    // which must at least have the size getNumberOfDescriptors().
00391    //The number of descriptors, i.e. getNumberOfDescriptors(), is returned.
00392    // You can specify the array type (Descriptor tags are 8 Bit,
00393    // you might e.g. choose a char, short, int or DescriptorTag array)
00394    template <typename T> int getDescriptorTags(T *tags)
00395       {
00396          const unsigned char *p=data.getData();
00397          const unsigned char *end=p+getLength();
00398          int count=0;
00399          while (p < end) {
00400             tags[count++]=(T)Descriptor::getDescriptorTag(p);
00401             p+=Descriptor::getLength(p);
00402          }
00403          return count;
00404       }
00405 protected:
00406    Descriptor *createDescriptor(int &i, bool returnUnimplemetedDescriptor);
00407    DescriptorTagDomain domain;
00408 };
00409 
00410 typedef uint8_t   EightBit;
00411 typedef uint16_t  SixteenBit;
00412 typedef uint32_t  ThirtyTwoBit;
00413 typedef uint64_t  SixtyFourBit;
00414 
00415 template <typename T> class TypeLoop : public Loop {
00416 public:
00417    int getCount() { return getLength()/sizeof(T); }
00418    T operator[](const int index) const
00419       {
00420          switch (sizeof(T)) {
00421          case 1:
00422             return data[index];
00423          case 2:
00424             return data.TwoBytes(index);
00425          case 4:
00426             return data.FourBytes(index);
00427          case 8:
00428             return (SixtyFourBit(data.FourBytes(index)) << 32) | data.FourBytes(index+4);
00429          default:
00430             return 0; // just to avoid a compiler warning
00431          }
00432          return 0; // just to avoid a compiler warning
00433       }
00434    T getNext(Iterator &it) const
00435       {
00436          T ret=operator[](it.i);
00437          it.i+=sizeof(T);
00438          return ret;
00439       }
00440    bool hasNext(Iterator &it) { return isValid() && (getLength() > it.i); }
00441 };
00442 
00443 class MHP_DescriptorLoop : public DescriptorLoop {
00444 public:
00445    MHP_DescriptorLoop() { domain=MHP; }
00446 };
00447 
00448 //Premiere Content Information Table
00449 class PCIT_DescriptorLoop : public DescriptorLoop {
00450 public:
00451    PCIT_DescriptorLoop() { domain=PCIT; }
00452 };
00453 
00454 //The content of the ExtendedEventDescriptor may be split over several
00455 //descriptors if the text is longer than 256 bytes.
00456 //The following classes provide base functionality to handle this case.
00457 class GroupDescriptor : public Descriptor {
00458 public:
00459    virtual int getDescriptorNumber() = 0;
00460    virtual int getLastDescriptorNumber() = 0;
00461 };
00462 
00463 class DescriptorGroup {
00464 public:
00465    DescriptorGroup(bool deleteOnDesctruction=true);
00466    ~DescriptorGroup();
00467    void Add(GroupDescriptor *d);
00468    void Delete();
00469    int getLength() { return length; }
00470    GroupDescriptor **getDescriptors() { return array; }
00471    bool isComplete(); //if all descriptors have been added
00472 protected:
00473    int length;
00474    GroupDescriptor **array;
00475    bool deleteOnDesctruction;
00476 };
00477 
00478 class String : public VariableLengthPart {
00479 public:
00480    //A note to the length: getLength() returns the length of the raw data.
00481    //The text may be shorter. Its length can be obtained with one of the
00482    //getText functions and strlen.
00483 
00484    //returns text. Data is allocated with new and must be delete'd by the user.
00485    char *getText();
00486    //copies text into given buffer.
00487    //a buffer of size getLength()+1 is guaranteed to be sufficiently large.
00488    //In most descriptors the string length is an 8-bit field,
00489    //so the maximum there is 256.
00490    //returns the given buffer for convenience.
00491    //The emphasis marks 0x86 and 0x87 are still available.
00492    char *getText(char *buffer, int size);
00493    //The same semantics as for getText(char*) apply.
00494    //The short version of the text according to ETSI TR 101 211 (chapter 4.6)
00495    //will be written into the shortVersion buffer (which should, therefore, have the same
00496    //length as buffer). If no shortVersion is available, shortVersion will contain
00497    //an empty string.
00498    //The emphasis marks 0x86 and 0x87 are still available in buffer, but not in shortVersion.
00499    char *getText(char *buffer, char *shortVersion, int sizeBuffer, int sizeShortVersion);
00500 protected:
00501    virtual void Parse() {}
00502    void decodeText(char *buffer, int size);
00503    void decodeText(char *buffer, char *shortVersion, int sizeBuffer, int sizeShortVersion);
00504 };
00505 
00506 // Call this function to set the system character table. CharacterTable is a string
00507 // like "iso8859-15" or "utf-8" (case insensitive).
00508 // Returns true if the character table was recognized.
00509 bool SetSystemCharacterTable(const char *CharacterTable);
00510 // Determines the character table used in the given buffer and returns
00511 // a string indicating that table. If no table can be determined, the
00512 // default ISO6937 is returned. If a table can be determined, the buffer
00513 // and length are adjusted accordingly.
00514 const char *getCharacterTable(const unsigned char *&buffer, int &length, bool *isSingleByte = NULL);
00515 bool convertCharacterTable(const char *from, size_t fromLength, char *to, size_t toLength, const char *fromCode);
00516 bool systemCharacterTableIsSingleByte(void);
00517 
00518 } //end of namespace
00519 
00520 #endif //LIBSI_SI_H