|
SASC-NG
DVBSoftCAM
|
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 1.15 2006/05/27 13:07:20 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 = 0x46, //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 CaSystemDescriptorTag = 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 TS 102 812 (MHP) 00126 // They once again start with 0x00 (see page 234, MHP specification) 00127 MHP_ApplicationDescriptorTag = 0x00, 00128 MHP_ApplicationNameDescriptorTag = 0x01, 00129 MHP_TransportProtocolDescriptorTag = 0x02, 00130 MHP_DVBJApplicationDescriptorTag = 0x03, 00131 MHP_DVBJApplicationLocationDescriptorTag = 0x04, 00132 // 0x05 - 0x0A is unimplemented this library 00133 MHP_ExternalApplicationAuthorisationDescriptorTag = 0x05, 00134 MHP_IPv4RoutingDescriptorTag = 0x06, 00135 MHP_IPv6RoutingDescriptorTag = 0x07, 00136 MHP_DVBHTMLApplicationDescriptorTag = 0x08, 00137 MHP_DVBHTMLApplicationLocationDescriptorTag = 0x09, 00138 MHP_DVBHTMLApplicationBoundaryDescriptorTag = 0x0A, 00139 MHP_ApplicationIconsDescriptorTag = 0x0B, 00140 MHP_PrefetchDescriptorTag = 0x0C, 00141 MHP_DelegatedApplicationDescriptorTag = 0x0E, 00142 MHP_ApplicationStorageDescriptorTag = 0x10, 00143 // Premiere private Descriptor Tags 00144 PremiereContentTransmissionDescriptorTag = 0xF2, 00145 00146 //a descriptor currently unimplemented in this library 00147 //the actual value 0xFF is "forbidden" according to the spec. 00148 UnimplementedDescriptorTag = 0xFF 00149 }; 00150 00151 enum DescriptorTagDomain { SI, MHP, PCIT }; 00152 00153 enum RunningStatus { RunningStatusUndefined = 0, 00154 RunningStatusNotRunning = 1, 00155 RunningStatusStartsInAFewSeconds = 2, 00156 RunningStatusPausing = 3, 00157 RunningStatusRunning = 4 00158 }; 00159 00160 enum LinkageType { LinkageTypeInformationService = 0x01, 00161 LinkageTypeEPGService = 0x02, 00162 LinkageTypeCaReplacementService = 0x03, 00163 LinkageTypeTSContainingCompleteNetworkBouquetSi = 0x04, 00164 LinkageTypeServiceReplacementService = 0x05, 00165 LinkageTypeDataBroadcastService = 0x06, 00166 LinkageTypeRCSMap = 0x07, 00167 LinkageTypeMobileHandover = 0x08, 00168 LinkageTypeSystemSoftwareUpdateService = 0x09, 00169 LinkageTypeTSContainingSsuBatOrNit = 0x0A 00170 }; 00171 00172 enum AudioType { AudioTypeUndefined = 0x00, 00173 AudioTypeCleanEffects = 0x01, 00174 AudioTypeHearingImpaired = 0x02, 00175 AudioTypeVisualImpairedCommentary = 0x03 00176 }; 00177 00178 /* Some principles: 00179 - Objects that return references to other objects contained in their data must make sure 00180 that the returned objects have been parsed. 00181 (the Loop subclasses take care of that.) 00182 Note that this does not apply to Loops and Strings (their are never returned by reference, BTW). 00183 */ 00184 00185 class Object : public Parsable { 00186 public: 00187 Object(); 00188 Object(CharArray &d); 00189 //can only be called once since data is immutable 00190 void setData(const unsigned char*data, int size, bool doCopy=true); 00191 CharArray getData() { return data; } 00192 //returns the valid flag which indicates if data is all right or errors have been encountered 00193 bool isValid() { return data.isValid(); } 00194 virtual int getLength() = 0; 00195 protected: 00196 CharArray data; 00197 //is protected - not used for sections 00198 template <class T> friend class StructureLoop; 00199 void setData(CharArray &d); 00200 //returns whether the given offset fits within the limits of the actual data 00201 //The valid flag will be set accordingly 00202 bool checkSize(int offset); 00203 }; 00204 00205 class Section : public Object { 00206 public: 00207 //convenience: sets data and parses if doParse 00208 Section(const unsigned char *data, bool doCopy=true); 00209 Section() {} 00210 TableId getTableId() const; 00211 virtual int getLength(); 00212 00213 static int getLength(const unsigned char *d); 00214 static TableId getTableId(const unsigned char *d); 00215 }; 00216 00217 class CRCSection : public Section { 00218 public: 00219 //convenience: sets data and parses if doParse 00220 CRCSection(const unsigned char *data, bool doCopy=true) : Section(data, doCopy) {} 00221 CRCSection() {} 00222 bool isCRCValid(); 00223 //convenience: isValid+CheckParse 00224 bool CheckCRCAndParse(); 00225 }; 00226 00227 /* A section which has the ExtendedSectionHeader 00228 (section_syntax_indicator==1) */ 00229 class NumberedSection : public CRCSection { 00230 public: 00231 NumberedSection(const unsigned char *data, bool doCopy=true) : CRCSection(data, doCopy) {} 00232 NumberedSection() {} 00233 int getTableIdExtension() const; 00234 bool getCurrentNextIndicator() const; 00235 int getVersionNumber() const; 00236 int getSectionNumber() const; 00237 int getLastSectionNumber() const; 00238 bool moreThanOneSection() const { return getLastSectionNumber()>0; } 00239 00240 static int getTableIdExtension(const unsigned char *d); 00241 }; 00242 00243 class VariableLengthPart : public Object { 00244 public: 00245 //never forget to call this 00246 void setData(CharArray d, int l) { Object::setData(d); checkSize(l); length=l; } 00247 //convenience method 00248 void setDataAndOffset(CharArray d, int l, int &offset) { Object::setData(d); checkSize(l); length=l; offset+=l; } 00249 virtual int getLength() { return length; } 00250 private: 00251 int length; 00252 }; 00253 00254 class LoopElement : public Object { 00255 }; 00256 00257 class Descriptor : public LoopElement { 00258 public: 00259 virtual int getLength(); 00260 DescriptorTag getDescriptorTag() const; 00261 00262 static int getLength(const unsigned char *d); 00263 static DescriptorTag getDescriptorTag(const unsigned char *d); 00264 protected: 00265 friend class DescriptorLoop; 00266 //returns a subclass of descriptor according to the data given. 00267 //The object is allocated with new and must be delete'd. 00268 //setData() will have been called, CheckParse() not. 00269 //if returnUnimplemetedDescriptor==true: 00270 // Never returns null - maybe the UnimplementedDescriptor. 00271 //if returnUnimplemetedDescriptor==false: 00272 // Never returns the UnimplementedDescriptor - maybe null 00273 static Descriptor *getDescriptor(CharArray d, DescriptorTagDomain domain, bool returnUnimplemetedDescriptor); 00274 }; 00275 00276 class Loop : public VariableLengthPart { 00277 public: 00278 class Iterator { 00279 public: 00280 Iterator() { i=0; } 00281 void reset() { i=0; } 00282 private: 00283 template <class T> friend class StructureLoop; 00284 friend class DescriptorLoop; 00285 template <class T> friend class TypeLoop; 00286 friend class ExtendedEventDescriptors; 00287 int i; 00288 }; 00289 protected: 00290 virtual void Parse() {} 00291 }; 00292 00293 //contains LoopElements of one type only 00294 template <class T> class StructureLoop : public Loop { 00295 public: 00296 //currently you must use a while-loop testing for hasNext() 00297 //i must be 0 to get the first descriptor (with the first call) 00298 bool getNext(T &obj, Iterator &it) 00299 { 00300 if (!isValid() || it.i >= getLength()) 00301 return false; 00302 CharArray d=data; 00303 d.addOffset(it.i); 00304 T ret; 00305 ret.setData(d); 00306 ret.CheckParse(); 00307 if (!checkSize(ret.getLength())) 00308 return false; 00309 it.i+=ret.getLength(); 00310 obj=ret; 00311 return true; 00312 } 00313 T* getNextAsPointer(Iterator &it) 00314 { 00315 if (!isValid() || it.i >= getLength()) 00316 return 0; 00317 CharArray d=data; 00318 d.addOffset(it.i); 00319 T *ret=new T(); 00320 ret->setData(d); 00321 ret->CheckParse(); 00322 if (!checkSize(ret->getLength())) 00323 return 0; 00324 it.i+=ret->getLength(); 00325 return ret; 00326 } 00327 //bool hasNext(Iterator &it) { return getLength() > it.i; } 00328 }; 00329 00330 //contains descriptors of different types 00331 class DescriptorLoop : public Loop { 00332 public: 00333 DescriptorLoop() { domain=SI; } 00334 //i must be 0 to get the first descriptor (with the first call) 00335 //All returned descriptors must be delete'd. 00336 //returns null if no more descriptors available 00337 Descriptor *getNext(Iterator &it); 00338 //return the next descriptor with given tag, or 0 if not available. 00339 //if returnUnimplemetedDescriptor==true: 00340 // an UnimplementedDescriptor may be returned if the next matching descriptor is unimplemented, 00341 // 0 will be returned if and only if no matching descriptor is found. 00342 //if returnUnimplemetedDescriptor==false: 00343 // if 0 is returned, either no descriptor with the given tag was found, 00344 // or descriptors were found, but the descriptor type is not implemented 00345 //In either case, a return value of 0 indicates that no further calls to this method 00346 //with the iterator shall be made. 00347 Descriptor *getNext(Iterator &it, DescriptorTag tag, bool returnUnimplemetedDescriptor=false); 00348 //return the next descriptor with one of the given tags, or 0 if not available. 00349 //if returnUnimplemetedDescriptor==true: 00350 // returns 0 if and only if no descriptor with one of the given tags was found. 00351 // The UnimplementedDescriptor may be returned. 00352 //if returnUnimplemetedDescriptor==false: 00353 // if 0 is returned, either no descriptor with one of the given tags was found, 00354 // or descriptors were found, but none of them are implemented. 00355 // The UnimplementedDescriptor will never be returned. 00356 //In either case, a return value of 0 indicates that no further calls to this method 00357 //with the iterator shall be made. 00358 Descriptor *getNext(Iterator &it, DescriptorTag *tags, int arrayLength, bool returnUnimplemetedDescriptor=false); 00359 //returns the number of descriptors in this loop 00360 int getNumberOfDescriptors(); 00361 //writes the tags of the descriptors in this loop in the array, 00362 // which must at least have the size getNumberOfDescriptors(). 00363 //The number of descriptors, i.e. getNumberOfDescriptors(), is returned. 00364 // You can specify the array type (Descriptor tags are 8 Bit, 00365 // you might e.g. choose a char, short, int or DescriptorTag array) 00366 template <typename T> int getDescriptorTags(T *tags) 00367 { 00368 const unsigned char *p=data.getData(); 00369 const unsigned char *end=p+getLength(); 00370 int count=0; 00371 while (p < end) { 00372 tags[count++]=(T)Descriptor::getDescriptorTag(p); 00373 p+=Descriptor::getLength(p); 00374 } 00375 return count; 00376 } 00377 protected: 00378 Descriptor *createDescriptor(int &i, bool returnUnimplemetedDescriptor); 00379 DescriptorTagDomain domain; 00380 }; 00381 00382 typedef uint8_t EightBit; 00383 typedef uint16_t SixteenBit; 00384 typedef uint32_t ThirtyTwoBit; 00385 typedef uint64_t SixtyFourBit; 00386 00387 template <typename T> class TypeLoop : public Loop { 00388 public: 00389 int getCount() { return getLength()/sizeof(T); } 00390 T operator[](const int index) const 00391 { 00392 switch (sizeof(T)) { 00393 case 1: 00394 return data[index]; 00395 case 2: 00396 return data.TwoBytes(index); 00397 case 4: 00398 return data.FourBytes(index); 00399 case 8: 00400 return (SixtyFourBit(data.FourBytes(index)) << 32) | data.FourBytes(index+4); 00401 } 00402 return 0; // just to avoid a compiler warning 00403 } 00404 T getNext(Iterator &it) const 00405 { 00406 T ret=operator[](it.i); 00407 it.i+=sizeof(T); 00408 return ret; 00409 } 00410 bool hasNext(Iterator &it) { return isValid() && (getLength() > it.i); } 00411 }; 00412 00413 class MHP_DescriptorLoop : public DescriptorLoop { 00414 public: 00415 MHP_DescriptorLoop() { domain=MHP; } 00416 }; 00417 00418 //Premiere Content Information Table 00419 class PCIT_DescriptorLoop : public DescriptorLoop { 00420 public: 00421 PCIT_DescriptorLoop() { domain=PCIT; } 00422 }; 00423 00424 //The content of the ExtendedEventDescriptor may be split over several 00425 //descriptors if the text is longer than 256 bytes. 00426 //The following classes provide base functionality to handle this case. 00427 class GroupDescriptor : public Descriptor { 00428 public: 00429 virtual int getDescriptorNumber() = 0; 00430 virtual int getLastDescriptorNumber() = 0; 00431 }; 00432 00433 class DescriptorGroup { 00434 public: 00435 DescriptorGroup(bool deleteOnDesctruction=true); 00436 ~DescriptorGroup(); 00437 void Add(GroupDescriptor *d); 00438 void Delete(); 00439 int getLength() { return length; } 00440 GroupDescriptor **getDescriptors() { return array; } 00441 bool isComplete(); //if all descriptors have been added 00442 protected: 00443 int length; 00444 GroupDescriptor **array; 00445 bool deleteOnDesctruction; 00446 }; 00447 00448 class String : public VariableLengthPart { 00449 public: 00450 //A note to the length: getLength() returns the length of the raw data. 00451 //The text may be shorter. Its length can be obtained with one of the 00452 //getText functions and strlen. 00453 00454 //returns text. Data is allocated with new and must be delete'd by the user. 00455 char *getText(); 00456 //copies text into given buffer. 00457 //a buffer of size getLength()+1 is guaranteed to be sufficiently large. 00458 //In most descriptors the string length is an 8-bit field, 00459 //so the maximum there is 256. 00460 //returns the given buffer for convenience. 00461 //The emphasis marks 0x86 and 0x87 are still available. 00462 char *getText(char *buffer, int size); 00463 //The same semantics as for getText(char*) apply. 00464 //The short version of the text according to ETSI TR 101 211 (chapter 4.6) 00465 //will be written into the shortVersion buffer (which should, therefore, have the same 00466 //length as buffer). If no shortVersion is available, shortVersion will contain 00467 //an empty string. 00468 //The emphasis marks 0x86 and 0x87 are still available in buffer, but not in shortVersion. 00469 char *getText(char *buffer, char *shortVersion, int sizeBuffer, int sizeShortVersion); 00470 protected: 00471 virtual void Parse() {} 00472 void decodeText(char *buffer, int size); 00473 void decodeText(char *buffer, char *shortVersion, int sizeBuffer, int sizeShortVersion); 00474 }; 00475 00476 } //end of namespace 00477 00478 #endif //LIBSI_SI_H