/*************************************************************************** * Copyright (c) 2003 by Marcel Wiesweg * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * $Id: si.c 1.4 2004/01/05 11:04:17 kls Exp $ * * ***************************************************************************/ #include #include "si.h" #include "descriptor.h" namespace SI { Object::Object() { } Object::Object(CharArray &d) : data(d) { } void Object::setData(const unsigned char*d, unsigned int size, bool doCopy) { data.assign(d, size, doCopy); } void Object::setData(CharArray &d) { data=d; } Section::Section(const unsigned char *data, bool doCopy) { setData(data, getLength(data), doCopy); } TableId Section::getTableId() const { return getTableId(data.getData()); } int Section::getLength() { return getLength(data.getData()); } TableId Section::getTableId(const unsigned char *d) { return (TableId)((const SectionHeader *)d)->table_id; } int Section::getLength(const unsigned char *d) { return HILO(((const SectionHeader *)d)->section_length)+sizeof(SectionHeader); } bool CRCSection::isValid() { return CRC32::isValid((const char *)data.getData(), getLength()/*, data.FourBytes(getLength()-4)*/); } bool CRCSection::CheckCRCAndParse() { if (!isValid()) return false; CheckParse(); return true; } bool NumberedSection::getCurrentNextIndicator() const { return data.getData()->current_next_indicator; } int NumberedSection::getVersionNumber() const { return data.getData()->version_number; } int NumberedSection::getSectionNumber() const { return data.getData()->section_number; } int NumberedSection::getLastSectionNumber() const { return data.getData()->last_section_number; } int Descriptor::getLength() { return getLength(data.getData()); } DescriptorTag Descriptor::getDescriptorTag() const { return getDescriptorTag(data.getData()); } int Descriptor::getLength(const unsigned char *d) { return ((const DescriptorHeader*)d)->descriptor_length+sizeof(DescriptorHeader); } DescriptorTag Descriptor::getDescriptorTag(const unsigned char *d) { return (DescriptorTag)((const DescriptorHeader*)d)->descriptor_tag; } Descriptor *DescriptorLoop::getNext(Iterator &it) { if (it.igetDescriptorTag()==UnimplementedDescriptorTag) return returnUnimplemetedDescriptor ? d : 0; return d; } Descriptor *DescriptorLoop::getNext(Iterator &it, DescriptorTag *tags, int arrayLength, bool returnUnimplemetedDescriptor) { Descriptor *d=0; if (it.igetDescriptorTag()==UnimplementedDescriptorTag) return returnUnimplemetedDescriptor ? d : 0; return d; } Descriptor *DescriptorLoop::createDescriptor(int &i) { Descriptor *d=Descriptor::getDescriptor(data+i, domain); i+=d->getLength(); d->CheckParse(); return d; } DescriptorGroup::DescriptorGroup(bool del) { array=0; length=0; deleteOnDesctruction=del; } DescriptorGroup::~DescriptorGroup() { if (deleteOnDesctruction) Delete(); delete[] array; } void DescriptorGroup::Delete() { for (int i=0;igetLastDescriptorNumber()+1; array=new GroupDescriptor*[length]; //numbering is zero-based for (int i=0;igetLastDescriptorNumber()+1) return; //avoid crash in case of misuse array[d->getDescriptorNumber()]=d; } bool DescriptorGroup::isComplete() { for (int i=0;i4095) return "text error"; char *data=new char(getLength()+1); decodeText(data); return data; } char *String::getText(char *buffer) { if (getLength() < 0 || getLength() >4095) { strncpy(buffer, "text error", getLength()+1); return buffer; } decodeText(buffer); return buffer; } //taken from libdtv, Copyright Rolf Hakenes void String::decodeText(char *buffer) { const unsigned char *from=data.getData(0); char *to=buffer; /* Disable detection of coding tables - libdtv doesn't do it either if ( (0x01 <= *from) && (*from <= 0x1f) ) { codeTable=*from } */ for (int i = 0; i < getLength(); i++) { if (*from == 0) break; if ( ((' ' <= *from) && (*from <= '~')) || (*from == '\n') || (0xA0 <= *from) ) *to++ = *from; else if (*from == 0x8A) *to++ = '\n'; else if (*from == 0x86 || *from == 0x87) //&& !(GDT_NAME_DESCRIPTOR & type)) *to++ = *from; from++; } *to = '\0'; } Descriptor *Descriptor::getDescriptor(CharArray da, DescriptorTagDomain domain) { Descriptor *d=0; switch (domain) { case SI: switch ((DescriptorTag)da.getData()->descriptor_tag) { case CaDescriptorTag: d=new CaDescriptor(); break; case CarouselIdentifierDescriptorTag: d=new CarouselIdentifierDescriptor(); break; case NetworkNameDescriptorTag: d=new NetworkNameDescriptor(); break; case ServiceListDescriptorTag: d=new ServiceListDescriptor(); break; case SatelliteDeliverySystemDescriptorTag: d=new SatelliteDeliverySystemDescriptor(); break; case CableDeliverySystemDescriptorTag: d=new CableDeliverySystemDescriptor(); break; case TerrestrialDeliverySystemDescriptorTag: d=new TerrestrialDeliverySystemDescriptor(); break; case BouquetNameDescriptorTag: d=new BouquetNameDescriptor(); break; case ServiceDescriptorTag: d=new ServiceDescriptor(); break; case NVODReferenceDescriptorTag: d=new NVODReferenceDescriptor(); break; case TimeShiftedServiceDescriptorTag: d=new TimeShiftedServiceDescriptor(); break; case ComponentDescriptorTag: d=new ComponentDescriptor(); break; case StreamIdentifierDescriptorTag: d=new StreamIdentifierDescriptor(); break; case SubtitlingDescriptorTag: d=new SubtitlingDescriptor(); break; case MultilingualNetworkNameDescriptorTag: d=new MultilingualNetworkNameDescriptor(); break; case MultilingualBouquetNameDescriptorTag: d=new MultilingualBouquetNameDescriptor(); break; case MultilingualServiceNameDescriptorTag: d=new MultilingualServiceNameDescriptor(); break; case MultilingualComponentDescriptorTag: d=new MultilingualComponentDescriptor(); break; case ServiceMoveDescriptorTag: d=new ServiceMoveDescriptor(); break; case FrequencyListDescriptorTag: d=new FrequencyListDescriptor(); break; case ServiceIdentifierDescriptorTag: d=new ServiceIdentifierDescriptor(); break; case CaIdentifierDescriptorTag: d=new CaIdentifierDescriptor(); break; case ShortEventDescriptorTag: d=new ShortEventDescriptor(); break; case ExtendedEventDescriptorTag: d=new ExtendedEventDescriptor(); break; case TimeShiftedEventDescriptorTag: d=new TimeShiftedEventDescriptor(); break; case ContentDescriptorTag: d=new ContentDescriptor(); break; case ParentalRatingDescriptorTag: d=new ParentalRatingDescriptor(); break; case ApplicationSignallingDescriptorTag: d=new ApplicationSignallingDescriptor(); break; //note that it is no problem to implement one //of the unimplemented descriptors. //defined in ISO-13818-1 case VideoStreamDescriptorTag: case AudioStreamDescriptorTag: case HierarchyDescriptorTag: case RegistrationDescriptorTag: case DataStreamAlignmentDescriptorTag: case TargetBackgroundGridDescriptorTag: case VideoWindowDescriptorTag: case ISO639LanguageDescriptorTag: case SystemClockDescriptorTag: case MultiplexBufferUtilizationDescriptorTag: case CopyrightDescriptorTag: case MaximumBitrateDescriptorTag: case PrivateDataIndicatorDescriptorTag: case SmoothingBufferDescriptorTag: case STDDescriptorTag: case IBPDescriptorTag: //defined in ETSI EN 300 468 case StuffingDescriptorTag: case VBIDataDescriptorTag: case VBITeletextDescriptorTag: case CountryAvailabilityDescriptorTag: case MocaicDescriptorTag: case LinkageDescriptorTag: case TeletextDescriptorTag: case TelephoneDescriptorTag: case LocalTimeOffsetDescriptorTag: case PrivateDataSpecifierDescriptorTag: case CellListDescriptorTag: case CellFrequencyLinkDescriptorTag: case ServiceAvailabilityDescriptorTag: case ShortSmoothingBufferDescriptorTag: case PartialTransportStreamDescriptorTag: case DataBroadcastDescriptorTag: case DataBroadcastIdDescriptorTag: case CaSystemDescriptorTag: case AC3DescriptorTag: case DSNGDescriptorTag: case PDCDescriptorTag: case AncillaryDataDescriptorTag: case AnnouncementSupportDescriptorTag: case AdaptationFieldDataDescriptorTag: case TransportStreamDescriptorTag: default: d=new UnimplementedDescriptor(); break; } break; case MHP: switch ((DescriptorTag)da.getData()->descriptor_tag) { // They once again start with 0x00 (see page 234, MHP specification) case MHP_ApplicationDescriptorTag: d=new MHP_ApplicationDescriptor(); break; case MHP_ApplicationNameDescriptorTag: d=new MHP_ApplicationNameDescriptor(); break; case MHP_TransportProtocolDescriptorTag: d=new MHP_TransportProtocolDescriptor(); break; case MHP_DVBJApplicationDescriptorTag: d=new MHP_DVBJApplicationDescriptor(); break; case MHP_DVBJApplicationLocationDescriptorTag: d=new MHP_DVBJApplicationLocationDescriptor(); break; // 0x05 - 0x0A is unimplemented this library case MHP_ExternalApplicationAuthorisationDescriptorTag: case MHP_IPv4RoutingDescriptorTag: case MHP_IPv6RoutingDescriptorTag: case MHP_DVBHTMLApplicationDescriptorTag: case MHP_DVBHTMLApplicationLocationDescriptorTag: case MHP_DVBHTMLApplicationBoundaryDescriptorTag: case MHP_ApplicationIconsDescriptorTag: case MHP_PrefetchDescriptorTag: case MHP_DelegatedApplicationDescriptorTag: case MHP_ApplicationStorageDescriptorTag: default: d=new UnimplementedDescriptor(); break; } break; } d->setData(da); return d; } } //end of namespace