summaryrefslogtreecommitdiff
path: root/libsi
diff options
context:
space:
mode:
Diffstat (limited to 'libsi')
-rw-r--r--libsi/Makefile52
-rw-r--r--libsi/descriptor.c635
-rw-r--r--libsi/descriptor.h477
-rwxr-xr-xlibsi/gendescr.pl83
-rw-r--r--libsi/headers.h1669
-rw-r--r--libsi/section.c328
-rw-r--r--libsi/section.h252
-rw-r--r--libsi/si.c415
-rw-r--r--libsi/si.h392
-rw-r--r--libsi/util.c281
-rw-r--r--libsi/util.h157
11 files changed, 4741 insertions, 0 deletions
diff --git a/libsi/Makefile b/libsi/Makefile
new file mode 100644
index 0000000..613fbee
--- /dev/null
+++ b/libsi/Makefile
@@ -0,0 +1,52 @@
+#
+# Makefile for a libsi
+#
+# $Id: Makefile 1.2 2003/12/13 10:41:39 kls Exp $
+
+### The C++ compiler and options:
+
+CXX ?= g++
+CXXFLAGS ?= -O2 -g -Wall -Woverloaded-virtual
+AR = ar
+ARFLAGS = ru
+RANLIB = ranlib
+
+### The directory environment:
+
+INCLUDES +=
+
+DEFINES +=
+
+LIBS +=
+
+### The object files (add further files here):
+
+OBJS = util.o si.o section.o descriptor.o
+
+### Implicit rules:
+
+%.o: %.c
+ $(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) $<
+
+# Dependencies:
+
+MAKEDEP = g++ -MM -MG
+DEPFILE = .dependencies
+$(DEPFILE): Makefile
+ @$(MAKEDEP) $(DEFINES) $(INCLUDES) $(OBJS:%.o=%.c) > $@
+
+-include $(DEPFILE)
+
+### Targets:
+
+all: libsi.a
+
+libsi.a : $(OBJS)
+ $(AR) $(ARFLAGS) $@ $(OBJS)
+
+clean:
+ @-rm -f $(OBJS) $(DEPFILE) *.a *.so *.tgz core* *~
+
+dist:
+ tar cvzf libsi.tar.gz -C .. libsi/util.c libsi/si.c libsi/section.c libsi/descriptor.c \
+ libsi/util.h libsi/si.h libsi/section.h libsi/descriptor.h libsi/headers.h libsi/Makefile libsi/gendescr.pl
diff --git a/libsi/descriptor.c b/libsi/descriptor.c
new file mode 100644
index 0000000..433d680
--- /dev/null
+++ b/libsi/descriptor.c
@@ -0,0 +1,635 @@
+/***************************************************************************
+ * 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: descriptor.c 1.2 2003/12/13 10:42:05 kls Exp $
+ * *
+ ***************************************************************************/
+
+#include <string.h>
+#include "descriptor.h"
+
+namespace SI {
+
+void ShortEventDescriptor::Parse() {
+ unsigned int offset=0;
+ const descr_short_event *s;
+ data.setPointerAndOffset<const descr_short_event>(s, offset);
+ languageCode[0]=s->lang_code1;
+ languageCode[1]=s->lang_code2;
+ languageCode[2]=s->lang_code3;
+ name.setDataAndOffset(data+offset, s->event_name_length, offset);
+ const descr_short_event_mid *mid;
+ data.setPointerAndOffset<const descr_short_event_mid>(mid, offset);
+ text.setData(data+offset, mid->text_length);
+}
+
+int ExtendedEventDescriptor::getDescriptorNumber() {
+ return s->descriptor_number;
+}
+
+int ExtendedEventDescriptor::getLastDescriptorNumber() {
+ return s->last_descriptor_number;
+}
+
+void ExtendedEventDescriptor::Parse() {
+ unsigned int offset=0;
+ data.setPointerAndOffset<const descr_extended_event>(s, offset);
+ languageCode[0]=s->lang_code1;
+ languageCode[1]=s->lang_code2;
+ languageCode[2]=s->lang_code3;
+ itemLoop.setDataAndOffset(data+offset, s->length_of_items, offset);
+ const descr_extended_event_mid *mid;
+ data.setPointerAndOffset<const descr_extended_event_mid>(mid, offset);
+ text.setData(data+offset, mid->text_length);
+}
+
+void ExtendedEventDescriptor::Item::Parse() {
+ unsigned int offset=0;
+ const item_extended_event *first;
+ data.setPointerAndOffset<const item_extended_event>(first, offset);
+ itemDescription.setDataAndOffset(data+offset, first->item_description_length, offset);
+ const item_extended_event_mid *mid;
+ data.setPointerAndOffset<const item_extended_event_mid>(mid, offset);
+ item.setData(data+offset, mid->item_length);
+}
+
+int ExtendedEventDescriptors::getTextLength() {
+ int ret=0;
+ for (int i=0;i<length;i++) {
+ ExtendedEventDescriptor *d=(ExtendedEventDescriptor *)array[i];
+ if (!d)
+ continue;
+ ret+=d->text.getLength()+1; //plus a blank
+ ExtendedEventDescriptor::Item item;
+ for (Loop::Iterator it; d->itemLoop.hasNext(it); ) {
+ item=d->itemLoop.getNext(it);
+ ret+=item.item.getLength();
+ ret+=item.itemDescription.getLength();
+ ret+=2; //the blanks
+ }
+ }
+ return ret;
+}
+
+//is there a case where this function does not return the same as getTextLength?
+int ExtendedEventDescriptors::getMaximumTextLength() {
+ int ret=0;
+ for (int i=0;i<length;i++) {
+ ExtendedEventDescriptor *d=(ExtendedEventDescriptor *)array[i];
+ if (!d)
+ continue;
+ ret+=d->text.getLength()+1; //plus a blank
+ ret+=d->itemLoop.getLength();
+ }
+ return ret;
+}
+
+char *ExtendedEventDescriptors::getText() {
+ char *text=new char[getMaximumTextLength()];
+ return getText(text);
+}
+
+//appends the Strings of every Descriptor in the group
+char *ExtendedEventDescriptors::getText(char *buffer) {
+ int index=0, len;
+ char tempbuf[256];
+ for (int i=0;i<length;i++) {
+ ExtendedEventDescriptor *d=(ExtendedEventDescriptor *)array[i];
+ if (!d)
+ continue;
+ d->text.getText(tempbuf);
+ len=strlen(tempbuf);
+ if (len) {
+ memcpy(buffer+index, tempbuf, len);
+ index+=len;
+ }
+
+ ExtendedEventDescriptor::Item item;
+ for (Loop::Iterator it; d->itemLoop.hasNext(it); ) {
+ item=d->itemLoop.getNext(it);
+
+ item.item.getText(tempbuf);
+ len=strlen(tempbuf);
+ if (len) {
+ memcpy(buffer+index, tempbuf, len);
+ index+=len;
+ }
+
+ item.itemDescription.getText(tempbuf);
+ len=strlen(tempbuf);
+ if (len) {
+ memcpy(buffer+index, tempbuf, len);
+ index+=len;
+ }
+ }
+ }
+ buffer[index]='\0';
+ return buffer;
+}
+
+int TimeShiftedEventDescriptor::getReferenceServiceId() const {
+ return HILO(s->reference_service_id);
+}
+
+int TimeShiftedEventDescriptor::getReferenceEventId() const {
+ return HILO(s->reference_event_id);
+}
+
+void TimeShiftedEventDescriptor::Parse() {
+ s=data.getData<const descr_time_shifted_event>();
+}
+
+void ContentDescriptor::Parse() {
+ //this descriptor is only a header and a loop
+ nibbleLoop.setData(data+sizeof(SectionHeader), getLength()-sizeof(SectionHeader));
+}
+
+int ContentDescriptor::Nibble::getContentNibbleLevel1() const {
+ return s->content_nibble_level_1;
+}
+
+int ContentDescriptor::Nibble::getContentNibbleLevel2() const {
+ return s->content_nibble_level_2;
+}
+
+int ContentDescriptor::Nibble::getUserNibble1() const {
+ return s->user_nibble_1;
+}
+
+int ContentDescriptor::Nibble::getUserNibble2() const {
+ return s->user_nibble_2;
+}
+
+void ContentDescriptor::Nibble::Parse() {
+ s=data.getData<const nibble_content>();
+}
+
+void ParentalRatingDescriptor::Parse() {
+ //this descriptor is only a header and a loop
+ ratingLoop.setData(data+sizeof(SectionHeader), getLength()-sizeof(SectionHeader));
+}
+
+int ParentalRatingDescriptor::Rating::getRating() const {
+ return s->rating;
+}
+
+void ParentalRatingDescriptor::Rating::Parse() {
+ s=data.getData<const parental_rating>();
+ languageCode[0]=s->lang_code1;
+ languageCode[1]=s->lang_code2;
+ languageCode[2]=s->lang_code3;
+}
+
+int CaDescriptor::getCaType() const {
+ return HILO(s->CA_type);
+}
+
+int CaDescriptor::getCaPid() const {
+ return HILO(s->CA_PID);
+}
+
+void CaDescriptor::Parse() {
+ unsigned int offset=0;
+ data.setPointerAndOffset<const descr_ca>(s, offset);
+ privateData.assign(data.getData(offset), getLength()-offset);
+}
+
+int StreamIdentifierDescriptor::getComponentTag() const {
+ return s->component_tag;
+}
+
+void StreamIdentifierDescriptor::Parse() {
+ s=data.getData<const descr_stream_identifier>();
+}
+
+void NetworkNameDescriptor::Parse() {
+ name.setData(data+sizeof(descr_network_name), getLength()-sizeof(descr_network_name));
+}
+
+void CaIdentifierDescriptor::Parse() {
+ identifiers.setData(data+sizeof(descr_ca_identifier), getLength()-sizeof(descr_ca_identifier));
+}
+
+int CarouselIdentifierDescriptor::getCarouselId() const {
+ return (HILO(s->carousel_id_hi) << 16) | HILO(s->carousel_id_lo);
+}
+
+int CarouselIdentifierDescriptor::getFormatId() const {
+ return s->FormatId;
+}
+
+void CarouselIdentifierDescriptor::Parse() {
+ s=data.getData<const descr_carousel_identifier>();
+}
+
+void ServiceListDescriptor::Parse() {
+ serviceLoop.setData(data+sizeof(descr_service_list), getLength()-sizeof(descr_service_list));
+}
+
+int ServiceListDescriptor::Service::getServiceId() const {
+ return HILO(s->service_id);
+}
+
+int ServiceListDescriptor::Service::getServiceType() const {
+ return s->service_type;
+}
+
+void ServiceListDescriptor::Service::Parse() {
+ s=data.getData<const descr_service_list_loop>();
+}
+
+int SatelliteDeliverySystemDescriptor::getFrequency() const {
+ return (HILO(s->frequency_hi) << 16) | HILO(s->frequency_lo);
+}
+
+int SatelliteDeliverySystemDescriptor::getOrbitalPosition() const {
+ return HILO(s->orbital_position);
+}
+
+int SatelliteDeliverySystemDescriptor::getWestEastFlag() const {
+ return s->west_east_flag;
+}
+
+int SatelliteDeliverySystemDescriptor::getPolarization() const {
+ return s->polarization;
+}
+
+int SatelliteDeliverySystemDescriptor::getModulation() const {
+ return s->modulation;
+}
+
+int SatelliteDeliverySystemDescriptor::getSymbolRate() const {
+ return (HILO(s->symbol_rate_hi) << 12) | (s->symbol_rate_lo_1 << 4) | s->symbol_rate_lo_2;
+}
+
+int SatelliteDeliverySystemDescriptor::getFecInner() const {
+ return s->fec_inner;
+}
+
+void SatelliteDeliverySystemDescriptor::Parse() {
+ s=data.getData<const descr_satellite_delivery_system>();
+}
+
+int CableDeliverySystemDescriptor::getFrequency() const {
+ return (HILO(s->frequency_hi) << 16) | HILO(s->frequency_lo);
+}
+
+int CableDeliverySystemDescriptor::getFecOuter() const {
+ return s->fec_outer;
+}
+
+int CableDeliverySystemDescriptor::getModulation() const {
+ return s->modulation;
+}
+
+int CableDeliverySystemDescriptor::getSymbolRate() const {
+ return (HILO(s->symbol_rate_hi) << 12) | (s->symbol_rate_lo_1 << 4) | s->symbol_rate_lo_2;
+}
+
+int CableDeliverySystemDescriptor::getFecInner() const {
+ return s->fec_inner;
+}
+
+void CableDeliverySystemDescriptor::Parse() {
+ s=data.getData<const descr_cable_delivery_system>();
+}
+
+int TerrestrialDeliverySystemDescriptor::getFrequency() const {
+ return (HILO(s->frequency_hi) << 16) | HILO(s->frequency_lo);
+}
+
+int TerrestrialDeliverySystemDescriptor::getBandwidth() const {
+ return s->bandwidth;
+}
+
+int TerrestrialDeliverySystemDescriptor::getConstellation() const {
+ return s->constellation;
+}
+
+int TerrestrialDeliverySystemDescriptor::getHierarchy() const {
+ return s->hierarchy;
+}
+
+int TerrestrialDeliverySystemDescriptor::getCodeRateHP() const {
+ return s->code_rate_HP;
+}
+
+int TerrestrialDeliverySystemDescriptor::getCodeRateLP() const {
+ return s->code_rate_LP;
+}
+
+int TerrestrialDeliverySystemDescriptor::getGuardInterval() const {
+ return s->guard_interval;
+}
+
+int TerrestrialDeliverySystemDescriptor::getTransmissionMode() const {
+ return s->transmission_mode;
+}
+
+bool TerrestrialDeliverySystemDescriptor::getOtherFrequency() const {
+ return s->other_frequency_flag;
+}
+
+void TerrestrialDeliverySystemDescriptor::Parse() {
+ s=data.getData<const descr_terrestrial_delivery>();
+}
+
+int ServiceDescriptor::getServiceType() const {
+ return s->service_type;
+}
+
+void ServiceDescriptor::Parse() {
+ unsigned int offset=0;
+ data.setPointerAndOffset<const descr_service>(s, offset);
+ providerName.setDataAndOffset(data+offset, s->provider_name_length, offset);
+ const descr_service_mid *mid;
+ data.setPointerAndOffset<const descr_service_mid>(mid, offset);
+ serviceName.setData(data+offset, mid->service_name_length);
+}
+
+void NVODReferenceDescriptor::Parse() {
+ serviceLoop.setData(data+sizeof(descr_nvod_reference), getLength()-sizeof(descr_nvod_reference));
+}
+
+int NVODReferenceDescriptor::Service::getTransportStream() const {
+ return HILO(s->transport_stream_id);
+}
+
+int NVODReferenceDescriptor::Service::getOriginalNetworkId() const {
+ return HILO(s->original_network_id);
+}
+
+int NVODReferenceDescriptor::Service::getServiceId() const {
+ return HILO(s->service_id);
+}
+
+void NVODReferenceDescriptor::Service::Parse() {
+ s=data.getData<const item_nvod_reference>();
+}
+
+int TimeShiftedServiceDescriptor::getReferenceServiceId() const {
+ return HILO(s->reference_service_id);
+}
+
+void TimeShiftedServiceDescriptor::Parse() {
+ s=data.getData<const descr_time_shifted_service>();
+}
+
+int ComponentDescriptor::getStreamContent() const {
+ return s->stream_content;
+}
+
+int ComponentDescriptor::getComponentType() const {
+ return s->component_type;
+}
+
+int ComponentDescriptor::getComponentTag() const {
+ return s->component_tag;
+}
+
+void ComponentDescriptor::Parse() {
+ unsigned int offset=0;
+ data.setPointerAndOffset<const descr_component>(s, offset);
+ languageCode[0]=s->lang_code1;
+ languageCode[1]=s->lang_code2;
+ languageCode[2]=s->lang_code3;
+ description.setData(data+offset, getLength()-offset);
+}
+
+void SubtitlingDescriptor::Parse() {
+ subtitlingLoop.setData(data+sizeof(descr_subtitling), getLength()-sizeof(descr_subtitling));
+}
+
+int SubtitlingDescriptor::Subtitling::getSubtitlingType() const {
+ return s->subtitling_type;
+}
+
+int SubtitlingDescriptor::Subtitling::getCompositionPageId() const {
+ return HILO(s->composition_page_id);
+}
+
+int SubtitlingDescriptor::Subtitling::getAncillaryPageId() const {
+ return HILO(s->ancillary_page_id);
+}
+
+void SubtitlingDescriptor::Subtitling::Parse() {
+ s=data.getData<const item_subtitling>();
+}
+
+int ServiceMoveDescriptor::getNewOriginalNetworkId() const {
+ return HILO(s->new_original_network_id);
+}
+
+int ServiceMoveDescriptor::getNewTransportStreamId() const {
+ return HILO(s->new_transport_stream_id);
+}
+
+int ServiceMoveDescriptor::getNewServiceId() const {
+ return HILO(s->new_service_id);
+}
+
+void ServiceMoveDescriptor::Parse() {
+ s=data.getData<const descr_service_move>();
+}
+
+int FrequencyListDescriptor::getCodingType() const {
+ return s->coding_type;
+}
+
+void FrequencyListDescriptor::Parse() {
+ unsigned int offset=0;
+ data.setPointerAndOffset<const descr_frequency_list>(s, offset);
+ frequencies.setData(data+offset, getLength()-offset);
+}
+
+void ServiceIdentifierDescriptor::Parse() {
+ textualServiceIdentifier.setData(data+sizeof(descr_service_identifier), getLength()-sizeof(descr_service_identifier));
+}
+
+void MultilingualNameDescriptor::Parse() {
+ nameLoop.setData(data+sizeof(descr_multilingual_network_name), getLength()-sizeof(descr_multilingual_network_name));
+}
+
+void MultilingualNameDescriptor::Name::Parse() {
+ unsigned int offset=0;
+ const entry_multilingual_name *s;
+ data.setPointerAndOffset<const entry_multilingual_name>(s, offset);
+ languageCode[0]=s->lang_code1;
+ languageCode[1]=s->lang_code2;
+ languageCode[2]=s->lang_code3;
+ name.setData(data+offset, s->text_length);
+}
+
+int MultilingualComponentDescriptor::getComponentTag() const {
+ return s->component_tag;
+}
+
+void MultilingualComponentDescriptor::Parse() {
+ unsigned int offset=0;
+ data.setPointerAndOffset<const descr_multilingual_component>(s, offset);
+ nameLoop.setData(data+sizeof(descr_multilingual_component), getLength()-sizeof(descr_multilingual_component));
+}
+
+void MultilingualServiceNameDescriptor::Parse() {
+ nameLoop.setData(data+sizeof(descr_multilingual_network_name), getLength()-sizeof(descr_multilingual_network_name));
+}
+
+void MultilingualServiceNameDescriptor::Name::Parse() {
+ unsigned int offset=0;
+ const entry_multilingual_name *s;
+ data.setPointerAndOffset<const entry_multilingual_name>(s, offset);
+ languageCode[0]=s->lang_code1;
+ languageCode[1]=s->lang_code2;
+ languageCode[2]=s->lang_code3;
+ providerName.setDataAndOffset(data+offset, s->text_length, offset);
+ const entry_multilingual_service_name_mid *mid;
+ data.setPointerAndOffset<const entry_multilingual_service_name_mid>(mid, offset);
+ name.setData(data+offset, mid->service_name_length);
+}
+
+void ApplicationSignallingDescriptor::Parse() {
+ entryLoop.setData(data+sizeof(descr_application_signalling), getLength()-sizeof(descr_application_signalling));
+}
+
+int ApplicationSignallingDescriptor::ApplicationEntryDescriptor::getApplicationType() const {
+ return HILO(s->application_type);
+}
+
+int ApplicationSignallingDescriptor::ApplicationEntryDescriptor::getAITVersionNumber() const {
+ return s->AIT_version_number;
+}
+
+void ApplicationSignallingDescriptor::ApplicationEntryDescriptor::Parse() {
+ s=data.getData<const application_signalling_entry>();
+}
+
+bool MHP_ApplicationDescriptor::isServiceBound() const {
+ return s->service_bound_flag;
+}
+
+int MHP_ApplicationDescriptor::getVisibility() const {
+ return s->visibility;
+}
+
+int MHP_ApplicationDescriptor::getApplicationPriority() const {
+ return s->application_priority;
+}
+
+void MHP_ApplicationDescriptor::Parse() {
+ unsigned int offset=0;
+ const descr_application *dapp;
+ data.setPointerAndOffset<const descr_application>(dapp, offset);
+ profileLoop.setDataAndOffset(data+offset, dapp->application_profiles_length, offset);
+ data.setPointerAndOffset<const descr_application_end>(s, offset);
+ transportProtocolLabels.setData(data+offset, getLength()-offset);
+}
+
+int MHP_ApplicationDescriptor::Profile::getApplicationProfile() const {
+ return HILO(s->application_profile);
+}
+
+int MHP_ApplicationDescriptor::Profile::getVersionMajor() const {
+ return s->version_major;
+}
+
+int MHP_ApplicationDescriptor::Profile::getVersionMinor() const {
+ return s->version_minor;
+}
+
+int MHP_ApplicationDescriptor::Profile::getVersionMicro() const {
+ return s->version_micro;
+}
+
+void MHP_ApplicationDescriptor::Profile::Parse() {
+ s=data.getData<application_profile_entry>();
+}
+
+void MHP_ApplicationNameDescriptor::Parse() {
+ nameLoop.setData(data+sizeof(descr_application_name), getLength()-sizeof(descr_application_name));
+}
+
+void MHP_ApplicationNameDescriptor::NameEntry::Parse() {
+ const descr_application_name_entry *s;
+ s=data.getData<const descr_application_name_entry>();
+ name.setData(data+sizeof(descr_application_name_entry), s->application_name_length);
+ languageCode[0]=s->lang_code1;
+ languageCode[1]=s->lang_code2;
+ languageCode[2]=s->lang_code3;
+}
+
+int MHP_TransportProtocolDescriptor::getProtocolId() const {
+ return HILO(s->protocol_id);
+}
+
+int MHP_TransportProtocolDescriptor::getProtocolLabel() const {
+ return s->transport_protocol_label;
+}
+
+bool MHP_TransportProtocolDescriptor::isRemote() const {
+ return remote;
+}
+
+int MHP_TransportProtocolDescriptor::getComponentTag() const {
+ return componentTag;
+}
+
+void MHP_TransportProtocolDescriptor::Parse() {
+ unsigned int offset=0;
+ data.setPointerAndOffset<const descr_transport_protocol>(s, offset);
+ if (getProtocolId() == ObjectCarousel) {
+ const transport_via_oc *oc;
+ data.setPointerAndOffset<const transport_via_oc>(oc, offset);
+ remote=oc->remote;
+ if (remote) {
+ const transport_via_oc_remote_end *rem;
+ data.setPointerAndOffset<const transport_via_oc_remote_end>(rem, offset);
+ componentTag=rem->component_tag;
+ } else {
+ const transport_via_oc_end *rem;
+ data.setPointerAndOffset<const transport_via_oc_end>(rem, offset);
+ componentTag=rem->component_tag;
+ }
+ } else { //unimplemented
+ remote=false;
+ componentTag=-1;
+ }
+}
+
+void MHP_DVBJApplicationDescriptor::Parse() {
+ applicationLoop.setData(data+sizeof(descr_dvbj_application), getLength()-sizeof(descr_dvbj_application));
+}
+
+void MHP_DVBJApplicationDescriptor::ApplicationEntry::Parse() {
+ const descr_dvbj_application_entry *entry=data.getData<const descr_dvbj_application_entry>();
+ parameter.setData(data+sizeof(descr_dvbj_application_entry), entry->parameter_length);
+}
+
+void MHP_DVBJApplicationLocationDescriptor::Parse() {
+ unsigned int offset=0;
+ const descr_dvbj_application_location *first;
+ data.setPointerAndOffset<const descr_dvbj_application_location>(first, offset);
+ baseDirectory.setDataAndOffset(data+offset, first->base_directory_length, offset);
+ const descr_dvbj_application_location_mid *mid;
+ data.setPointerAndOffset<const descr_dvbj_application_location_mid>(mid, offset);
+ classPath.setDataAndOffset(data+offset, mid->classpath_extension_length, offset);
+ initialClass.setData(data+offset, getLength()-offset);
+}
+
+int MHP_ApplicationIconsDescriptor::getIconFlags() const {
+ return HILO(s->icon_flags);
+}
+
+void MHP_ApplicationIconsDescriptor::Parse() {
+ unsigned int offset=0;
+ const descr_application_icons_descriptor *first;
+ data.setPointerAndOffset<const descr_application_icons_descriptor>(first, offset);
+ iconLocator.setDataAndOffset(data+offset, first->icon_locator_length, offset);
+ data.setPointerAndOffset<const descr_application_icons_descriptor_end>(s, offset);
+}
+
+} //end of namespace
diff --git a/libsi/descriptor.h b/libsi/descriptor.h
new file mode 100644
index 0000000..9abe1f0
--- /dev/null
+++ b/libsi/descriptor.h
@@ -0,0 +1,477 @@
+/***************************************************************************
+ * 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: descriptor.h 1.2 2003/12/13 10:42:08 kls Exp $
+ * *
+ ***************************************************************************/
+
+#ifndef LIBSI_DESCRIPTOR_H
+#define LIBSI_DESCRIPTOR_H
+
+#include "si.h"
+#include "headers.h"
+
+namespace SI {
+
+class ShortEventDescriptor : public Descriptor {
+public:
+ char languageCode[3];
+ String name; //name of the event
+ String text; //short description
+protected:
+ virtual void Parse();
+};
+
+class ExtendedEventDescriptor : public GroupDescriptor {
+public:
+ class Item : public LoopElement {
+ public:
+ virtual int getLength() { return sizeof(item_extended_event)+sizeof(item_extended_event_mid)+item.getLength()+itemDescription.getLength(); }
+ String item;
+ String itemDescription;
+ protected:
+ virtual void Parse();
+ };
+ char languageCode[3];
+ int getDescriptorNumber();
+ int getLastDescriptorNumber();
+ StructureLoop<Item> itemLoop;
+ String text;
+protected:
+ virtual void Parse();
+private:
+ const descr_extended_event *s;
+};
+
+class ExtendedEventDescriptors : public DescriptorGroup {
+public:
+ //don't use
+ int getTextLength();
+ //really fast
+ int getMaximumTextLength();
+ //same semantics as with SI::String
+ char *getText();
+ //buffer must at least be getTextLength(), getMaximumTextLength() is a good choice
+ char *getText(char *buffer);
+};
+
+class TimeShiftedEventDescriptor : public Descriptor {
+public:
+ int getReferenceServiceId() const;
+ int getReferenceEventId() const;
+protected:
+ virtual void Parse();
+private:
+ const descr_time_shifted_event *s;
+};
+
+class ContentDescriptor : public Descriptor {
+public:
+ class Nibble : public LoopElement {
+ public:
+ virtual int getLength() { return sizeof(nibble_content); }
+ int getContentNibbleLevel1() const;
+ int getContentNibbleLevel2() const;
+ int getUserNibble1() const;
+ int getUserNibble2() const;
+ protected:
+ virtual void Parse();
+ private:
+ const nibble_content *s;
+ };
+ StructureLoop<Nibble> nibbleLoop;
+protected:
+ virtual void Parse();
+};
+
+class ParentalRatingDescriptor : public Descriptor {
+public:
+ class Rating : public LoopElement {
+ public:
+ char languageCode[3];
+ int getRating() const;
+ virtual int getLength() { return sizeof(parental_rating); }
+ protected:
+ virtual void Parse();
+ private:
+ const parental_rating *s;
+ };
+ StructureLoop<Rating> ratingLoop;
+protected:
+ virtual void Parse();
+};
+
+class CaDescriptor : public Descriptor {
+public:
+ int getCaType() const;
+ int getCaPid() const;
+ CharArray privateData;
+protected:
+ virtual void Parse();
+private:
+ const descr_ca *s;
+};
+
+class StreamIdentifierDescriptor : public Descriptor {
+public:
+ int getComponentTag() const;
+protected:
+ virtual void Parse();
+private:
+ const descr_stream_identifier *s;
+};
+
+class NetworkNameDescriptor : public Descriptor {
+public:
+ String name;
+protected:
+ virtual void Parse();
+};
+
+class CaIdentifierDescriptor : public Descriptor {
+public:
+ TypeLoop<SixteenBit> identifiers;
+protected:
+ virtual void Parse();
+};
+
+class CarouselIdentifierDescriptor : public Descriptor {
+public:
+ int getCarouselId() const;
+ int getFormatId() const;
+protected:
+ virtual void Parse();
+private:
+ const descr_carousel_identifier *s;
+};
+
+class BouquetNameDescriptor : public NetworkNameDescriptor {
+};
+
+class ServiceListDescriptor : public Descriptor {
+public:
+ class Service : public LoopElement {
+ public:
+ int getServiceId() const;
+ int getServiceType() const;
+ virtual int getLength() { return sizeof(descr_service_list_loop); }
+ protected:
+ virtual void Parse();
+ private:
+ const descr_service_list_loop *s;
+ };
+ StructureLoop<Service> serviceLoop;
+protected:
+ virtual void Parse();
+};
+
+class SatelliteDeliverySystemDescriptor : public Descriptor {
+public:
+ int getFrequency() const;
+ int getOrbitalPosition() const;
+ int getWestEastFlag() const;
+ int getPolarization() const;
+ int getModulation() const;
+ int getSymbolRate() const;
+ int getFecInner() const;
+protected:
+ virtual void Parse();
+private:
+ const descr_satellite_delivery_system *s;
+};
+
+class CableDeliverySystemDescriptor : public Descriptor {
+public:
+ int getFrequency() const;
+ int getFecOuter() const;
+ int getModulation() const;
+ int getSymbolRate() const;
+ int getFecInner() const;
+protected:
+ virtual void Parse();
+private:
+ const descr_cable_delivery_system *s;
+};
+
+class TerrestrialDeliverySystemDescriptor : public Descriptor {
+public:
+ int getFrequency() const;
+ int getBandwidth() const;
+ int getConstellation() const;
+ int getHierarchy() const;
+ int getCodeRateHP() const;
+ int getCodeRateLP() const;
+ int getGuardInterval() const;
+ int getTransmissionMode() const;
+ bool getOtherFrequency() const;
+protected:
+ virtual void Parse();
+private:
+ const descr_terrestrial_delivery *s;
+};
+
+class ServiceDescriptor : public Descriptor {
+public:
+ int getServiceType() const;
+ String serviceName;
+ String providerName;
+protected:
+ virtual void Parse();
+private:
+ const descr_service *s;
+};
+
+class NVODReferenceDescriptor : public Descriptor {
+public:
+ class Service : public LoopElement {
+ public:
+ int getTransportStream() const;
+ int getOriginalNetworkId() const;
+ int getServiceId() const;
+ virtual int getLength() { return sizeof(item_nvod_reference); }
+ protected:
+ virtual void Parse();
+ private:
+ const item_nvod_reference *s;
+ };
+ StructureLoop<Service> serviceLoop;
+protected:
+ virtual void Parse();
+};
+
+class TimeShiftedServiceDescriptor : public Descriptor {
+public:
+ int getReferenceServiceId() const;
+protected:
+ virtual void Parse();
+private:
+ const descr_time_shifted_service *s;
+};
+
+class ComponentDescriptor : public Descriptor {
+public:
+ int getStreamContent() const;
+ int getComponentType() const;
+ int getComponentTag() const;
+ char languageCode[3];
+ String description;
+protected:
+ virtual void Parse();
+private:
+ const descr_component *s;
+};
+
+class SubtitlingDescriptor : public Descriptor {
+public:
+ class Subtitling : public Descriptor {
+ public:
+ int getSubtitlingType() const;
+ int getCompositionPageId() const;
+ int getAncillaryPageId() const;
+ virtual int getLength() { return sizeof(item_nvod_reference); }
+ protected:
+ virtual void Parse();
+ private:
+ const item_subtitling *s;
+ };
+ StructureLoop<Subtitling> subtitlingLoop;
+protected:
+ virtual void Parse();
+};
+
+class ServiceMoveDescriptor : public Descriptor {
+public:
+ int getNewOriginalNetworkId() const;
+ int getNewTransportStreamId() const;
+ int getNewServiceId() const;
+protected:
+ virtual void Parse();
+private:
+ const descr_service_move *s;
+};
+
+class FrequencyListDescriptor : public Descriptor {
+public:
+ int getCodingType() const;
+ TypeLoop<ThirtyTwoBit> frequencies;
+protected:
+ virtual void Parse();
+private:
+ const descr_frequency_list *s;
+};
+
+class ServiceIdentifierDescriptor : public Descriptor {
+public:
+ String textualServiceIdentifier;
+protected:
+ virtual void Parse();
+};
+
+//abstract base class
+class MultilingualNameDescriptor : public Descriptor {
+public:
+ class Name : public LoopElement {
+ public:
+ char languageCode[3];
+ String name;
+ virtual int getLength() { return sizeof(entry_multilingual_name)+name.getLength(); }
+ protected:
+ virtual void Parse();
+ };
+ StructureLoop<Name> nameLoop;
+protected:
+ virtual void Parse();
+};
+
+class MultilingualNetworkNameDescriptor : public MultilingualNameDescriptor {
+ //inherits nameLoop from MultilingualNameDescriptor
+};
+
+class MultilingualBouquetNameDescriptor : public MultilingualNameDescriptor {
+ //inherits nameLoop from MultilingualNameDescriptor
+};
+
+class MultilingualComponentDescriptor : public MultilingualNameDescriptor {
+public:
+ int getComponentTag() const;
+ //inherits nameLoop from MultilingualNameDescriptor
+protected:
+ virtual void Parse();
+private:
+ const descr_multilingual_component *s;
+};
+
+class MultilingualServiceNameDescriptor : public Descriptor {
+public:
+ class Name : public MultilingualNameDescriptor::Name {
+ public:
+ virtual int getLength() { return sizeof(entry_multilingual_name)+providerName.getLength()+sizeof(entry_multilingual_service_name_mid)+name.getLength(); }
+ String providerName;
+ //inherits name, meaning: service name;
+ protected:
+ virtual void Parse();
+ };
+ StructureLoop<Name> nameLoop;
+protected:
+ virtual void Parse();
+};
+
+//a descriptor currently unimplemented in this library
+class UnimplementedDescriptor : public Descriptor {
+protected:
+ virtual void Parse() {}
+};
+
+class ApplicationSignallingDescriptor : public Descriptor {
+public:
+ class ApplicationEntryDescriptor : public LoopElement {
+ public:
+ virtual int getLength() { return sizeof(application_signalling_entry); }
+ int getApplicationType() const;
+ int getAITVersionNumber() const;
+ protected:
+ virtual void Parse();
+ private:
+ const application_signalling_entry *s;
+ };
+ StructureLoop<ApplicationEntryDescriptor> entryLoop;
+protected:
+ virtual void Parse();
+};
+
+class MHP_ApplicationDescriptor : public Descriptor {
+public:
+ class Profile : public LoopElement {
+ public:
+ virtual int getLength() { return sizeof(application_profile_entry); }
+ int getApplicationProfile() const;
+ int getVersionMajor() const;
+ int getVersionMinor() const;
+ int getVersionMicro() const;
+ private:
+ const application_profile_entry *s;
+ protected:
+ virtual void Parse();
+ };
+ StructureLoop<Profile> profileLoop;
+ bool isServiceBound() const;
+ int getVisibility() const;
+ int getApplicationPriority() const;
+ TypeLoop<EightBit> transportProtocolLabels;
+private:
+ const descr_application_end *s;
+protected:
+ virtual void Parse();
+};
+
+class MHP_ApplicationNameDescriptor : public Descriptor {
+public:
+ class NameEntry : public LoopElement {
+ public:
+ virtual int getLength() { return sizeof(descr_application_name_entry)+name.getLength(); }
+ char languageCode[3];
+ String name;
+ protected:
+ virtual void Parse();
+ };
+ StructureLoop<NameEntry> nameLoop;
+protected:
+ virtual void Parse();
+};
+
+class MHP_TransportProtocolDescriptor : public Descriptor {
+public:
+ enum Protocol { ObjectCarousel = 0x01, IPviaDVB = 0x02, HTTPoverInteractionChannel = 0x03 };
+ int getProtocolId() const;
+ int getProtocolLabel() const;
+ bool isRemote() const;
+ int getComponentTag() const;
+protected:
+ virtual void Parse();
+private:
+ const descr_transport_protocol *s;
+ bool remote;
+ int componentTag;
+};
+
+class MHP_DVBJApplicationDescriptor : public Descriptor {
+public:
+ class ApplicationEntry : public LoopElement {
+ public:
+ virtual int getLength() { return sizeof(descr_dvbj_application_entry)+parameter.getLength(); }
+ String parameter;
+ protected:
+ virtual void Parse();
+ };
+ StructureLoop<ApplicationEntry> applicationLoop;
+protected:
+ virtual void Parse();
+};
+
+class MHP_DVBJApplicationLocationDescriptor : public Descriptor {
+public:
+ String baseDirectory;
+ String classPath;
+ String initialClass;
+protected:
+ virtual void Parse();
+};
+
+class MHP_ApplicationIconsDescriptor : public Descriptor {
+public:
+ String iconLocator;
+ int getIconFlags() const;
+protected:
+ virtual void Parse();
+private:
+ const descr_application_icons_descriptor_end *s;
+};
+
+} //end of namespace
+
+#endif //LIBSI_TABLE_H
diff --git a/libsi/gendescr.pl b/libsi/gendescr.pl
new file mode 100755
index 0000000..e2b206f
--- /dev/null
+++ b/libsi/gendescr.pl
@@ -0,0 +1,83 @@
+#!/usr/bin/perl
+
+# $Id: gendescr.pl 1.2 2003/12/13 10:40:53 kls Exp $
+
+print "Name (ohne ...Descriptor):";
+$name=<STDIN>;
+$name =~ s/\n$//;
+$inner = ($name =~ s/ä$//);
+$name .= "Descriptor" unless ($inner);
+
+print "Struct:";
+$struct=<STDIN>;
+$struct =~ s/\n$//;
+
+mm:
+$index=0;
+$which=1;
+print "Variablen:";
+while ( <STDIN> ) {
+ if (/ä/) {
+ goto vv;
+ } elsif (/ü/) {
+ $which=1;
+ next;
+ }
+ $eingabe=$_;
+ $eingabe =~ s/(.{75,120} )/\1\n/g;
+ $eingabe =~ s/\n$//;
+ if ($which) {
+ $members[$index]=$eingabe;
+ } else {
+ $members_comments[$index]=$eingabe;
+ $index++;
+ print "Jep!\n";
+ }
+ $which= (! $which);
+}
+
+vv:
+$filename_h="tempdescr.h";
+$filename_c="tempdescr.c";
+schreib();
+
+sub schreib {
+ print "Danke.\n";
+ open(OUTPUT_H, ">>".$filename_h) or die "Could not open file!!";
+ open(OUTPUT_C, ">>".$filename_c) or die "Could not open file!!";
+
+ if ($inner) {
+ $offset=" ";
+ } else {
+ $offset="";
+ }
+ print(OUTPUT_H $offset."class ".$name);
+ if ($inner) {
+ print(OUTPUT_H " : public LoopElement {\n".$offset."public:");
+ } else {
+ print(OUTPUT_H " : public Descriptor {\n".$offset."public:");
+ }
+ #for ($i=0; $i<=$#vars;$i++) {
+ # print (OUTPUT "/*\n".$vars_comments[$i]." */\n".$vars[$i].";\n\n\n");
+ #}
+ for ($i=0; $i<=$#members;$i++) {
+ print (OUTPUT_H "\n".$offset." int get".$members[$i]."() const;");
+ }
+ print(OUTPUT_H "\n".$offset."virtual int getLength() { return sizeof(".$struct."); }") if ($inner);
+
+ print(OUTPUT_H "\n".$offset."protected:\n".$offset." virtual void Parse();");
+ print(OUTPUT_H "\n".$offset."private:\n".$offset." const ".$struct." *s;") if ($struct ne "");
+ print(OUTPUT_H "\n".$offset."};\n\n");
+ for ($i=0; $i<=$#members_comments;$i++) {
+ print (OUTPUT_C "int ".$name."::get".$members[$i]."() const {\n");
+ if ($members_comments[$i] =~ /^(.+)_hi$/) {
+ $varbase=$1;
+ print (OUTPUT_C " return HILO(s->".$varbase.");\n}\n\n");
+ } else {
+ print (OUTPUT_C " return s->".$members_comments[$i].";\n}\n\n");
+ }
+ }
+ print (OUTPUT_C "void ".$name."::Parse() {\n}\n\n");
+ print (OUTPUT_C "\n\n\n");
+ exit;
+}
diff --git a/libsi/headers.h b/libsi/headers.h
new file mode 100644
index 0000000..d5c1199
--- /dev/null
+++ b/libsi/headers.h
@@ -0,0 +1,1669 @@
+/***************************************************************************
+ * *
+ * (C) 2001-03 Rolf Hakenes <hakenes@hippomi.de>, under the *
+ * GNU GPL with contribution of Oleg Assovski, *
+ * www.satmania.com *
+ * Adapted and extended 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: headers.h 1.2 2003/12/13 10:43:26 kls Exp $
+ * *
+ ***************************************************************************/
+
+#ifndef LIBSI_HEADERS_H
+#define LIBSI_HEADERS_H
+
+#include <endian.h>
+
+namespace SI {
+
+typedef unsigned char u_char;
+
+struct SectionHeader {
+ u_char table_id :8;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char section_syntax_indicator :1;
+ u_char :3;
+ u_char section_length_hi :4;
+#else
+ u_char section_length_hi :4;
+ u_char :3;
+ u_char section_syntax_indicator :1;
+#endif
+ u_char section_length_lo :8;
+};
+
+struct ExtendedSectionHeader {
+ u_char table_id :8;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char section_syntax_indicator :1;
+ u_char :3;
+ u_char section_length_hi :4;
+#else
+ u_char section_length_hi :4;
+ u_char :3;
+ u_char section_syntax_indicator :1;
+#endif
+ u_char section_length_lo :8;
+ u_char table_id_extension_hi :8;
+ u_char table_id_extension_lo :8;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char :2;
+ u_char version_number :5;
+ u_char current_next_indicator :1;
+#else
+ u_char current_next_indicator :1;
+ u_char version_number :5;
+ u_char :2;
+#endif
+ u_char section_number :8;
+ u_char last_section_number :8;
+};
+
+struct DescriptorHeader {
+ u_char descriptor_tag :8;
+ u_char descriptor_length :8;
+};
+
+/*
+ *
+ * ETSI ISO/IEC 13818-1 specifies SI which is referred to as PSI. The PSI
+ * data provides information to enable automatic configuration of the
+ * receiver to demultiplex and decode the various streams of programs
+ * within the multiplex. The PSI data is structured as four types of table.
+ * The tables are transmitted in sections.
+ *
+ * 1) Program Association Table (PAT):
+ *
+ * - for each service in the multiplex, the PAT indicates the location
+ * (the Packet Identifier (PID) values of the Transport Stream (TS)
+ * packets) of the corresponding Program Map Table (PMT).
+ * It also gives the location of the Network Information Table (NIT).
+ *
+ */
+
+#define PAT_LEN 8
+
+struct pat {
+ u_char table_id :8;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char section_syntax_indicator :1;
+ u_char dummy :1; // has to be 0
+ u_char :2;
+ u_char section_length_hi :4;
+#else
+ u_char section_length_hi :4;
+ u_char :2;
+ u_char dummy :1; // has to be 0
+ u_char section_syntax_indicator :1;
+#endif
+ u_char section_length_lo :8;
+ u_char transport_stream_id_hi :8;
+ u_char transport_stream_id_lo :8;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char :2;
+ u_char version_number :5;
+ u_char current_next_indicator :1;
+#else
+ u_char current_next_indicator :1;
+ u_char version_number :5;
+ u_char :2;
+#endif
+ u_char section_number :8;
+ u_char last_section_number :8;
+};
+
+#define PAT_PROG_LEN 4
+
+struct pat_prog {
+ u_char program_number_hi :8;
+ u_char program_number_lo :8;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char :3;
+ u_char network_pid_hi :5;
+#else
+ u_char network_pid_hi :5;
+ u_char :3;
+#endif
+ u_char network_pid_lo :8;
+ /* or program_map_pid (if prog_num=0)*/
+};
+
+/*
+ *
+ * 2) Conditional Access Table (CAT):
+ *
+ * - the CAT provides information on the CA systems used in the
+ * multiplex; the information is private and dependent on the CA
+ * system, but includes the location of the EMM stream, when
+ * applicable.
+ *
+ */
+#define CAT_LEN 8
+
+struct cat {
+ u_char table_id :8;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char section_syntax_indicator :1;
+ u_char dummy :1; // has to be 0
+ u_char :2;
+ u_char section_length_hi :4;
+#else
+ u_char section_length_hi :4;
+ u_char :2;
+ u_char dummy :1; // has to be 0
+ u_char section_syntax_indicator :1;
+#endif
+ u_char section_length_lo :8;
+ u_char reserved_1 :8;
+ u_char reserved_2 :8;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char :2;
+ u_char version_number :5;
+ u_char current_next_indicator :1;
+#else
+ u_char current_next_indicator :1;
+ u_char version_number :5;
+ u_char :2;
+#endif
+ u_char section_number :8;
+ u_char last_section_number :8;
+};
+
+/*
+ *
+ * 3) Program Map Table (PMT):
+ *
+ * - the PMT identifies and indicates the locations of the streams that
+ * make up each service, and the location of the Program Clock
+ * Reference fields for a service.
+ *
+ */
+
+#define PMT_LEN 12
+
+struct pmt {
+ u_char table_id :8;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char section_syntax_indicator :1;
+ u_char dummy :1; // has to be 0
+ u_char :2;
+ u_char section_length_hi :4;
+#else
+ u_char section_length_hi :4;
+ u_char :2;
+ u_char dummy :1; // has to be 0
+ u_char section_syntax_indicator :1;
+#endif
+ u_char section_length_lo :8;
+ u_char program_number_hi :8;
+ u_char program_number_lo :8;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char :2;
+ u_char version_number :5;
+ u_char current_next_indicator :1;
+#else
+ u_char current_next_indicator :1;
+ u_char version_number :5;
+ u_char :2;
+#endif
+ u_char section_number :8;
+ u_char last_section_number :8;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char :3;
+ u_char PCR_PID_hi :5;
+#else
+ u_char PCR_PID_hi :5;
+ u_char :3;
+#endif
+ u_char PCR_PID_lo :8;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char :4;
+ u_char program_info_length_hi :4;
+#else
+ u_char program_info_length_hi :4;
+ u_char :4;
+#endif
+ u_char program_info_length_lo :8;
+ //descriptors
+};
+
+#define PMT_INFO_LEN 5
+
+struct pmt_info {
+ u_char stream_type :8;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char :3;
+ u_char elementary_PID_hi :5;
+#else
+ u_char elementary_PID_hi :5;
+ u_char :3;
+#endif
+ u_char elementary_PID_lo :8;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char :4;
+ u_char ES_info_length_hi :4;
+#else
+ u_char ES_info_length_hi :4;
+ u_char :4;
+#endif
+ u_char ES_info_length_lo :8;
+ // descriptors
+};
+
+/*
+ *
+ * 4) Network Information Table (NIT):
+ *
+ * - the NIT is intended to provide information about the physical
+ * network. The syntax and semantics of the NIT are defined in
+ * ETSI EN 300 468.
+ *
+ */
+
+#define NIT_LEN 10
+
+struct nit {
+ u_char table_id :8;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char section_syntax_indicator :1;
+ u_char :3;
+ u_char section_length_hi :4;
+#else
+ u_char section_length_hi :4;
+ u_char :3;
+ u_char section_syntax_indicator :1;
+#endif
+ u_char section_length_lo :8;
+ u_char network_id_hi :8;
+ u_char network_id_lo :8;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char :2;
+ u_char version_number :5;
+ u_char current_next_indicator :1;
+#else
+ u_char current_next_indicator :1;
+ u_char version_number :5;
+ u_char :2;
+#endif
+ u_char section_number :8;
+ u_char last_section_number :8;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char :4;
+ u_char network_descriptor_length_hi :4;
+#else
+ u_char network_descriptor_length_hi :4;
+ u_char :4;
+#endif
+ u_char network_descriptor_length_lo :8;
+ /* descriptors */
+};
+
+#define SIZE_NIT_MID 2
+
+struct nit_mid { // after descriptors
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char :4;
+ u_char transport_stream_loop_length_hi :4;
+#else
+ u_char transport_stream_loop_length_hi :4;
+ u_char :4;
+#endif
+ u_char transport_stream_loop_length_lo :8;
+};
+
+#define SIZE_NIT_END 4
+
+struct nit_end {
+ long CRC;
+};
+
+#define NIT_TS_LEN 6
+
+struct ni_ts {
+ u_char transport_stream_id_hi :8;
+ u_char transport_stream_id_lo :8;
+ u_char original_network_id_hi :8;
+ u_char original_network_id_lo :8;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char :4;
+ u_char transport_descriptors_length_hi :4;
+#else
+ u_char transport_descriptors_length_hi :4;
+ u_char :4;
+#endif
+ u_char transport_descriptors_length_lo :8;
+ /* descriptors */
+};
+
+/*
+ *
+ * In addition to the PSI, data is needed to provide identification of
+ * services and events for the user. In contrast with the PAT, CAT, and
+ * PMT of the PSI, which give information only for the multiplex in which
+ * they are contained (the actual multiplex), the additional information
+ * defined within the present document can also provide information on
+ * services and events carried by different multiplexes, and even on other
+ * networks. This data is structured as nine tables:
+ *
+ * 1) Bouquet Association Table (BAT):
+ *
+ * - the BAT provides information regarding bouquets. As well as giving
+ * the name of the bouquet, it provides a list of services for each
+ * bouquet.
+ *
+ */
+/* SEE NIT (It has the same structure but has different allowed descriptors) */
+/*
+ *
+ * 2) Service Description Table (SDT):
+ *
+ * - the SDT contains data describing the services in the system e.g.
+ * names of services, the service provider, etc.
+ *
+ */
+
+#define SDT_LEN 11
+
+struct sdt {
+ u_char table_id :8;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char section_syntax_indicator :1;
+ u_char :3;
+ u_char section_length_hi :4;
+#else
+ u_char section_length_hi :4;
+ u_char :3;
+ u_char section_syntax_indicator :1;
+#endif
+ u_char section_length_lo :8;
+ u_char transport_stream_id_hi :8;
+ u_char transport_stream_id_lo :8;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char :2;
+ u_char version_number :5;
+ u_char current_next_indicator :1;
+#else
+ u_char current_next_indicator :1;
+ u_char version_number :5;
+ u_char :2;
+#endif
+ u_char section_number :8;
+ u_char last_section_number :8;
+ u_char original_network_id_hi :8;
+ u_char original_network_id_lo :8;
+ u_char :8;
+};
+
+#define GetSDTTransportStreamId(x) (HILO(((sdt_t *) x)->transport_stream_id))
+#define GetSDTOriginalNetworkId(x) (HILO(((sdt_t *) x)->original_network_id))
+
+#define SDT_DESCR_LEN 5
+
+struct sdt_descr {
+ u_char service_id_hi :8;
+ u_char service_id_lo :8;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char :6;
+ u_char eit_schedule_flag :1;
+ u_char eit_present_following_flag :1;
+ u_char running_status :3;
+ u_char free_ca_mode :1;
+ u_char descriptors_loop_length_hi :4;
+#else
+ u_char eit_present_following_flag :1;
+ u_char eit_schedule_flag :1;
+ u_char :6;
+ u_char descriptors_loop_length_hi :4;
+ u_char free_ca_mode :1;
+ u_char running_status :3;
+#endif
+ u_char descriptors_loop_length_lo :8;
+};
+
+/*
+ *
+ * 3) Event Information Table (EIT):
+ *
+ * - the EIT contains data concerning events or programmes such as event
+ * name, start time, duration, etc.; - the use of different descriptors
+ * allows the transmission of different kinds of event information e.g.
+ * for different service types.
+ *
+ */
+
+#define EIT_LEN 14
+
+struct eit {
+ u_char table_id :8;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char section_syntax_indicator :1;
+ u_char :3;
+ u_char section_length_hi :4;
+#else
+ u_char section_length_hi :4;
+ u_char :3;
+ u_char section_syntax_indicator :1;
+#endif
+ u_char section_length_lo :8;
+ u_char service_id_hi :8;
+ u_char service_id_lo :8;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char :2;
+ u_char version_number :5;
+ u_char current_next_indicator :1;
+#else
+ u_char current_next_indicator :1;
+ u_char version_number :5;
+ u_char :2;
+#endif
+ u_char section_number :8;
+ u_char last_section_number :8;
+ u_char transport_stream_id_hi :8;
+ u_char transport_stream_id_lo :8;
+ u_char original_network_id_hi :8;
+ u_char original_network_id_lo :8;
+ u_char segment_last_section_number :8;
+ u_char segment_last_table_id :8;
+};
+
+#define EIT_EVENT_LEN 12
+
+struct eit_event {
+ u_char event_id_hi :8;
+ u_char event_id_lo :8;
+ u_char mjd_hi :8;
+ u_char mjd_lo :8;
+ u_char start_time_h :8;
+ u_char start_time_m :8;
+ u_char start_time_s :8;
+ u_char duration_h :8;
+ u_char duration_m :8;
+ u_char duration_s :8;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char running_status :3;
+ u_char free_ca_mode :1;
+ u_char descriptors_loop_length_hi :4;
+#else
+ u_char descriptors_loop_length_hi :4;
+ u_char free_ca_mode :1;
+ u_char running_status :3;
+#endif
+ u_char descriptors_loop_length_lo :8;
+};
+
+/*
+ *
+ * 4) Running Status Table (RST):
+ *
+ * - the RST gives the status of an event (running/not running). The RST
+ * updates this information and allows timely automatic switching to
+ * events.
+ *
+ */
+
+struct rst {
+ u_char table_id :8;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char section_syntax_indicator :1;
+ u_char :3;
+ u_char section_length_hi :4;
+#else
+ u_char section_length_hi :4;
+ u_char :3;
+ u_char section_syntax_indicator :1;
+#endif
+ u_char section_length_lo :8;
+};
+
+struct rst_info {
+ u_char transport_stream_id_hi :8;
+ u_char transport_stream_id_lo :8;
+ u_char original_network_id_hi :8;
+ u_char original_network_id_lo :8;
+ u_char service_id_hi :8;
+ u_char service_id_lo :8;
+ u_char event_id_hi :8;
+ u_char event_id_lo :8;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char :5;
+ u_char running_status :3;
+#else
+ u_char running_status :3;
+ u_char :5;
+#endif
+};
+
+/*
+ *
+ * 5) Time and Date Table (TDT):
+ *
+ * - the TDT gives information relating to the present time and date.
+ * This information is given in a separate table due to the frequent
+ * updating of this information.
+ *
+ */
+
+#define TDT_LEN 8
+
+struct tdt {
+ u_char table_id :8;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char section_syntax_indicator :1;
+ u_char :3;
+ u_char section_length_hi :4;
+#else
+ u_char section_length_hi :4;
+ u_char :3;
+ u_char section_syntax_indicator :1;
+#endif
+ u_char section_length_lo :8;
+ u_char utc_mjd_hi :8;
+ u_char utc_mjd_lo :8;
+ u_char utc_time_h :8;
+ u_char utc_time_m :8;
+ u_char utc_time_s :8;
+};
+
+/*
+ *
+ * 6) Time Offset Table (TOT):
+ *
+ * - the TOT gives information relating to the present time and date and
+ * local time offset. This information is given in a separate table due
+ * to the frequent updating of the time information.
+ *
+ */
+#define TOT_LEN 10
+
+struct tot {
+ u_char table_id :8;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char section_syntax_indicator :1;
+ u_char :3;
+ u_char section_length_hi :4;
+#else
+ u_char section_length_hi :4;
+ u_char :3;
+ u_char section_syntax_indicator :1;
+#endif
+ u_char section_length_lo :8;
+ u_char utc_mjd_hi :8;
+ u_char utc_mjd_lo :8;
+ u_char utc_time_h :8;
+ u_char utc_time_m :8;
+ u_char utc_time_s :8;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char :4;
+ u_char descriptors_loop_length_hi :4;
+#else
+ u_char descriptors_loop_length_hi :4;
+ u_char :4;
+#endif
+ u_char descriptors_loop_length_lo :8;
+};
+
+/*
+ *
+ * 7) Stuffing Table (ST):
+ *
+ * - the ST is used to invalidate existing sections, for example at
+ * delivery system boundaries.
+ *
+ */
+ /* TO BE DONE */
+/*
+ *
+ * 8) Selection Information Table (SIT):
+ *
+ * - the SIT is used only in "partial" (i.e. recorded) bitstreams. It
+ * carries a summary of the SI information required to describe the
+ * streams in the partial bitstream.
+ *
+ */
+ /* TO BE DONE */
+/*
+ *
+ * 9) Discontinuity Information Table (DIT):
+ *
+ * - the DIT is used only in "partial" (i.e. recorded) bitstreams.
+ * It is inserted where the SI information in the partial bitstream may
+ * be discontinuous. Where applicable the use of descriptors allows a
+ * flexible approach to the organization of the tables and allows for
+ * future compatible extensions.
+ *
+ */
+ /* TO BE DONE */
+
+/*
+ *
+ * 3) Application Information Table (AIT):
+ *
+ * - the AIT contains data concerning MHP application broadcast by a service.
+ *
+ */
+
+#define AIT_LEN 10
+
+struct ait {
+ u_char table_id :8;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char section_syntax_indicator :1;
+ u_char :3;
+ u_char section_length_hi :4;
+#else
+ u_char section_length_hi :4;
+ u_char :3;
+ u_char section_syntax_indicator :1;
+#endif
+ u_char section_length_lo :8;
+ u_char application_type_hi :8;
+ u_char application_type_lo :8;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char :2;
+ u_char version_number :5;
+ u_char current_next_indicator :1;
+#else
+ u_char current_next_indicator :1;
+ u_char version_number :5;
+ u_char :2;
+#endif
+ u_char section_number :8;
+ u_char last_section_number :8;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char :4;
+ u_char common_descriptors_length_hi :4;
+#else
+ u_char common_descriptors_length_hi :4;
+ u_char :4;
+#endif
+ u_char common_descriptors_length_lo :8;
+};
+
+#define SIZE_AIT_MID 2
+
+struct ait_mid { // after descriptors
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char :4;
+ u_char application_loop_length_hi :4;
+#else
+ u_char application_loop_length_hi :4;
+ u_char :4;
+#endif
+ u_char application_loop_length_lo :8;
+};
+
+#define SIZE_AIT_END 4
+
+struct ait_end {
+ long CRC;
+};
+
+#define AIT_APP_LEN 9
+
+struct ait_app {
+ //how to deal with 32 bit fields?
+
+ u_char organisation_id_hi_hi :8;
+ u_char organisation_id_hi_lo :8;
+ u_char organisation_id_lo_hi :8;
+ u_char organisation_id_lo_lo :8;
+
+ //long organisation_id :32;
+ u_char application_id_hi :8;
+ u_char application_id_lo :8;
+ u_char application_control_code :8;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char :4;
+ u_char application_descriptors_length_hi :4;
+#else
+ u_char application_descriptors_length_hi :4;
+ u_char :4;
+#endif
+ u_char application_descriptors_length_lo :8;
+ /* descriptors */
+};
+
+/*
+ *
+ * The following describes the different descriptors that can be used within
+ * the SI.
+ *
+ * The following semantics apply to all the descriptors defined in this
+ * subclause:
+ *
+ * descriptor_tag: The descriptor tag is an 8-bit field which identifies
+ * each descriptor. Those values with MPEG-2 normative
+ * meaning are described in ISO/IEC 13818-1. The values of
+ * descriptor_tag are defined in 'libsi.h'
+ * descriptor_length: The descriptor length is an 8-bit field specifying the
+ * total number of bytes of the data portion of the
+ * descriptor following the byte defining the value of
+ * this field.
+ *
+ */
+
+#define DESCR_GEN_LEN 2
+struct descr_gen {
+ u_char descriptor_tag :8;
+ u_char descriptor_length :8;
+};
+
+#define GetDescriptorTag(x) (((descr_gen_t *) x)->descriptor_tag)
+#define GetDescriptorLength(x) (((descr_gen_t *) x)->descriptor_length+DESCR_GEN_LEN)
+
+/* 0x09 ca_descriptor */
+
+#define DESCR_CA_LEN 6
+struct descr_ca {
+ u_char descriptor_tag :8;
+ u_char descriptor_length :8;
+ u_char CA_type_hi :8;
+ u_char CA_type_lo :8;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char reserved :3;
+ u_char CA_PID_hi :5;
+#else
+ u_char CA_PID_hi :5;
+ u_char reserved :3;
+#endif
+ u_char CA_PID_lo :8;
+};
+
+/* 0x0A iso_639_language_descriptor */
+
+#define DESCR_ISO_639_LANGUAGE_LEN 5
+struct descr_iso_639_language {
+ u_char descriptor_tag :8;
+ u_char descriptor_length :8;
+ u_char lang_code1 :8;
+ u_char lang_code2 :8;
+ u_char lang_code3 :8;
+};
+
+/* 0x13 carousel_identifier_descriptor */
+
+#define DESCR_CAROUSEL_IDENTIFIER_LEN 7
+struct descr_carousel_identifier {
+ u_char descriptor_tag :8;
+ u_char descriptor_length :8;
+ u_char carousel_id_hi_hi :8;
+ u_char carousel_id_hi_lo :8;
+ u_char carousel_id_lo_hi :8;
+ u_char carousel_id_lo_lo :8;
+ u_char FormatId :8;
+ /* FormatSpecifier follows */
+};
+
+/* 0x40 network_name_descriptor */
+
+#define DESCR_NETWORK_NAME_LEN 2
+struct descr_network_name {
+ u_char descriptor_tag :8;
+ u_char descriptor_length :8;
+};
+
+/* 0x41 service_list_descriptor */
+
+#define DESCR_SERVICE_LIST_LEN 2
+struct descr_service_list {
+ u_char descriptor_tag :8;
+ u_char descriptor_length :8;
+};
+
+#define DESCR_SERVICE_LIST_LOOP_LEN 3
+struct descr_service_list_loop {
+ u_char service_id_hi :8;
+ u_char service_id_lo :8;
+ u_char service_type :8;
+};
+
+/* 0x42 stuffing_descriptor */
+
+#define DESCR_STUFFING_LEN XX
+struct descr_stuffing {
+ u_char descriptor_tag :8;
+ u_char descriptor_length :8;
+ /* TBD */
+};
+
+/* 0x43 satellite_delivery_system_descriptor */
+
+#define DESCR_SATELLITE_DELIVERY_SYSTEM_LEN 13
+struct descr_satellite_delivery_system {
+ u_char descriptor_tag :8;
+ u_char descriptor_length :8;
+ u_char frequency_hi_hi :8;
+ u_char frequency_hi_lo :8;
+ u_char frequency_lo_hi :8;
+ u_char frequency_lo_lo :8;
+ u_char orbital_position_hi :8;
+ u_char orbital_position_lo :8;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char west_east_flag :1;
+ u_char polarization :2;
+ u_char modulation :5;
+#else
+ u_char modulation :5;
+ u_char polarization :2;
+ u_char west_east_flag :1;
+#endif
+ u_char symbol_rate_hi_hi :8;
+ u_char symbol_rate_hi_lo :8;
+ u_char symbol_rate_lo_1 :8;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char symbol_rate_lo_2 :4;
+ u_char fec_inner :4;
+#else
+ u_char fec_inner :4;
+ u_char symbol_rate_lo_2 :4;
+#endif
+};
+
+/* 0x44 cable_delivery_system_descriptor */
+
+#define DESCR_CABLE_DELIVERY_SYSTEM_LEN 13
+struct descr_cable_delivery_system {
+ u_char descriptor_tag :8;
+ u_char descriptor_length :8;
+ u_char frequency_hi_hi :8;
+ u_char frequency_hi_lo :8;
+ u_char frequency_lo_hi :8;
+ u_char frequency_lo_lo :8;
+ u_char reserved1 :8;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char reserved2 :4;
+ u_char fec_outer :4;
+#else
+ u_char fec_outer :4;
+ u_char reserved2 :4;
+#endif
+ u_char modulation :8;
+ u_char symbol_rate_hi_hi :8;
+ u_char symbol_rate_hi_lo :8;
+ u_char symbol_rate_lo_1 :8;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char symbol_rate_lo_2 :4;
+ u_char fec_inner :4;
+#else
+ u_char fec_inner :4;
+ u_char symbol_rate_lo_2 :4;
+#endif
+};
+
+/* 0x45 vbi_data_descriptor */
+
+#define DESCR_VBI_DATA_LEN XX
+struct descr_vbi_data {
+ u_char descriptor_tag :8;
+ u_char descriptor_length :8;
+ /* TBD */
+};
+
+/* 0x46 vbi_teletext_descriptor */
+
+#define DESCR_VBI_TELETEXT_LEN XX
+struct descr_vbi_teletext {
+ u_char descriptor_tag :8;
+ u_char descriptor_length :8;
+ /* TBD */
+};
+
+/* 0x47 bouquet_name_descriptor */
+
+#define DESCR_BOUQUET_NAME_LEN 2
+struct descr_bouquet_name {
+ u_char descriptor_tag :8;
+ u_char descriptor_length :8;
+};
+
+/* 0x48 service_descriptor */
+
+#define DESCR_SERVICE_LEN 4
+struct descr_service {
+ u_char descriptor_tag :8;
+ u_char descriptor_length :8;
+ u_char service_type :8;
+ u_char provider_name_length :8;
+};
+
+struct descr_service_mid {
+ u_char service_name_length :8;
+};
+
+/* 0x49 country_availability_descriptor */
+
+#define DESCR_COUNTRY_AVAILABILITY_LEN 3
+struct descr_country_availability {
+ u_char descriptor_tag :8;
+ u_char descriptor_length :8;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char country_availability_flag :1;
+ u_char reserved :7;
+#else
+ u_char reserved :7;
+ u_char country_availability_flag :1;
+#endif
+};
+
+/* 0x4A linkage_descriptor */
+
+#define DESCR_LINKAGE_LEN 9
+struct descr_linkage {
+ u_char descriptor_tag :8;
+ u_char descriptor_length :8;
+ u_char transport_stream_id_hi :8;
+ u_char transport_stream_id_lo :8;
+ u_char original_network_id_hi :8;
+ u_char original_network_id_lo :8;
+ u_char service_id_hi :8;
+ u_char service_id_lo :8;
+ u_char linkage_type :8;
+};
+
+/* 0x4B nvod_reference_descriptor */
+
+#define DESCR_NVOD_REFERENCE_LEN 2
+struct descr_nvod_reference {
+ u_char descriptor_tag :8;
+ u_char descriptor_length :8;
+};
+
+#define ITEM_NVOD_REFERENCE_LEN 6
+struct item_nvod_reference {
+ u_char transport_stream_id_hi :8;
+ u_char transport_stream_id_lo :8;
+ u_char original_network_id_hi :8;
+ u_char original_network_id_lo :8;
+ u_char service_id_hi :8;
+ u_char service_id_lo :8;
+};
+
+/* 0x4C time_shifted_service_descriptor */
+
+#define DESCR_TIME_SHIFTED_SERVICE_LEN 4
+struct descr_time_shifted_service {
+ u_char descriptor_tag :8;
+ u_char descriptor_length :8;
+ u_char reference_service_id_hi :8;
+ u_char reference_service_id_lo :8;
+};
+
+/* 0x4D short_event_descriptor */
+
+#define DESCR_SHORT_EVENT_LEN 6
+struct descr_short_event {
+ u_char descriptor_tag :8;
+ u_char descriptor_length :8;
+ u_char lang_code1 :8;
+ u_char lang_code2 :8;
+ u_char lang_code3 :8;
+ u_char event_name_length :8;
+};
+
+struct descr_short_event_mid {
+ u_char text_length :8;
+};
+
+/* 0x4E extended_event_descriptor */
+
+#define DESCR_EXTENDED_EVENT_LEN 7
+struct descr_extended_event {
+ u_char descriptor_tag :8;
+ u_char descriptor_length :8;
+ /* TBD */
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char descriptor_number :4;
+ u_char last_descriptor_number :4;
+#else
+ u_char last_descriptor_number :4;
+ u_char descriptor_number :4;
+#endif
+ u_char lang_code1 :8;
+ u_char lang_code2 :8;
+ u_char lang_code3 :8;
+ u_char length_of_items :8;
+};
+
+struct descr_extended_event_mid {
+ u_char text_length :8;
+};
+
+#define ITEM_EXTENDED_EVENT_LEN 1
+struct item_extended_event {
+ u_char item_description_length :8;
+};
+
+struct item_extended_event_mid {
+ u_char item_length :8;
+};
+
+/* 0x4F time_shifted_event_descriptor */
+
+#define DESCR_TIME_SHIFTED_EVENT_LEN 6
+struct descr_time_shifted_event {
+ u_char descriptor_tag :8;
+ u_char descriptor_length :8;
+ u_char reference_service_id_hi :8;
+ u_char reference_service_id_lo :8;
+ u_char reference_event_id_hi :8;
+ u_char reference_event_id_lo :8;
+};
+
+/* 0x50 component_descriptor */
+
+#define DESCR_COMPONENT_LEN 8
+struct descr_component {
+ u_char descriptor_tag :8;
+ u_char descriptor_length :8;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char reserved :4;
+ u_char stream_content :4;
+#else
+ u_char stream_content :4;
+ u_char reserved :4;
+#endif
+ u_char component_type :8;
+ u_char component_tag :8;
+ u_char lang_code1 :8;
+ u_char lang_code2 :8;
+ u_char lang_code3 :8;
+};
+
+/* 0x51 mosaic_descriptor */
+
+#define DESCR_MOSAIC_LEN XX
+struct descr_mosaic {
+ u_char descriptor_tag :8;
+ u_char descriptor_length :8;
+ /* TBD */
+};
+
+/* 0x52 stream_identifier_descriptor */
+
+#define DESCR_STREAM_IDENTIFIER_LEN 3
+struct descr_stream_identifier {
+ u_char descriptor_tag :8;
+ u_char descriptor_length :8;
+ u_char component_tag :8;
+};
+
+/* 0x53 ca_identifier_descriptor */
+
+#define DESCR_CA_IDENTIFIER_LEN 2
+struct descr_ca_identifier {
+ u_char descriptor_tag :8;
+ u_char descriptor_length :8;
+};
+
+/* 0x54 content_descriptor */
+
+#define DESCR_CONTENT_LEN 2
+struct descr_content {
+ u_char descriptor_tag :8;
+ u_char descriptor_length :8;
+};
+
+struct nibble_content {
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char content_nibble_level_1 :4;
+ u_char content_nibble_level_2 :4;
+#else
+ u_char content_nibble_level_2 :4;
+ u_char content_nibble_level_1 :4;
+#endif
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char user_nibble_1 :4;
+ u_char user_nibble_2 :4;
+#else
+ u_char user_nibble_2 :4;
+ u_char user_nibble_1 :4;
+#endif
+};
+
+/* 0x55 parental_rating_descriptor */
+
+#define DESCR_PARENTAL_RATING_LEN 2
+struct descr_parental_rating {
+ u_char descriptor_tag :8;
+ u_char descriptor_length :8;
+};
+
+#define PARENTAL_RATING_LEN 4
+struct parental_rating {
+ u_char lang_code1 :8;
+ u_char lang_code2 :8;
+ u_char lang_code3 :8;
+ u_char rating :8;
+};
+
+/* 0x56 teletext_descriptor */
+
+#define DESCR_TELETEXT_LEN 2
+struct descr_teletext {
+ u_char descriptor_tag :8;
+ u_char descriptor_length :8;
+};
+
+#define ITEM_TELETEXT_LEN 5
+struct item_teletext {
+ u_char lang_code1 :8;
+ u_char lang_code2 :8;
+ u_char lang_code3 :8;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char type :5;
+ u_char magazine_number :3;
+#else
+ u_char magazine_number :3;
+ u_char type :5;
+#endif
+ u_char page_number :8;
+};
+
+/* 0x57 telephone_descriptor */
+
+#define DESCR_TELEPHONE_LEN XX
+struct descr_telephone {
+ u_char descriptor_tag :8;
+ u_char descriptor_length :8;
+ /* TBD */
+};
+
+/* 0x58 local_time_offset_descriptor */
+
+#define DESCR_LOCAL_TIME_OFFSET_LEN 2
+struct descr_local_time_offset {
+ u_char descriptor_tag :8;
+ u_char descriptor_length :8;
+};
+
+#define LOCAL_TIME_OFFSET_ENTRY_LEN 15
+struct local_time_offset_entry {
+ u_char country_code1 :8;
+ u_char country_code2 :8;
+ u_char country_code3 :8;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char country_region_id :6;
+ u_char :1;
+ u_char local_time_offset_polarity :1;
+#else
+ u_char local_time_offset_polarity :1;
+ u_char :1;
+ u_char country_region_id :6;
+#endif
+ u_char local_time_offset_h :8;
+ u_char local_time_offset_m :8;
+ u_char time_of_change_mjd_hi :8;
+ u_char time_of_change_mjd_lo :8;
+ u_char time_of_change_time_h :8;
+ u_char time_of_change_time_m :8;
+ u_char time_of_change_time_s :8;
+ u_char next_time_offset_h :8;
+ u_char next_time_offset_m :8;
+};
+
+/* 0x59 subtitling_descriptor */
+
+#define DESCR_SUBTITLING_LEN 2
+struct descr_subtitling {
+ u_char descriptor_tag :8;
+ u_char descriptor_length :8;
+};
+
+#define ITEM_SUBTITLING_LEN 8
+struct item_subtitling {
+ u_char lang_code1 :8;
+ u_char lang_code2 :8;
+ u_char lang_code3 :8;
+ u_char subtitling_type :8;
+ u_char composition_page_id_hi :8;
+ u_char composition_page_id_lo :8;
+ u_char ancillary_page_id_hi :8;
+ u_char ancillary_page_id_lo :8;
+};
+
+/* 0x5A terrestrial_delivery_system_descriptor */
+
+#define DESCR_TERRESTRIAL_DELIVERY_SYSTEM_LEN XX
+struct descr_terrestrial_delivery {
+ u_char descriptor_tag :8;
+ u_char descriptor_length :8;
+ u_char frequency_hi_hi :8;
+ u_char frequency_hi_lo :8;
+ u_char frequency_lo_hi :8;
+ u_char frequency_lo_lo :8;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char bandwidth :3;
+ u_char reserved1 :5;
+#else
+ u_char reserved1 :5;
+ u_char bandwidth :3;
+#endif
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char constellation :2;
+ u_char hierarchy :3;
+ u_char code_rate_HP :3;
+#else
+ u_char code_rate_HP :3;
+ u_char hierarchy :3;
+ u_char constellation :2;
+#endif
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char code_rate_LP :3;
+ u_char guard_interval :2;
+ u_char transmission_mode :2;
+ u_char other_frequency_flag :1;
+#else
+ u_char other_frequency_flag :1;
+ u_char transmission_mode :2;
+ u_char guard_interval :2;
+ u_char code_rate_LP :3;
+#endif
+ u_char reserver2 :8;
+ u_char reserver3 :8;
+ u_char reserver4 :8;
+ u_char reserver5 :8;
+};
+
+/* 0x5B multilingual_network_name_descriptor */
+
+#define DESCR_MULTILINGUAL_NETWORK_NAME_LEN XX
+struct descr_multilingual_network_name {
+ u_char descriptor_tag :8;
+ u_char descriptor_length :8;
+};
+
+struct entry_multilingual_name {
+ u_char lang_code1 :8;
+ u_char lang_code2 :8;
+ u_char lang_code3 :8;
+ u_char text_length :8;
+};
+
+/* 0x5C multilingual_bouquet_name_descriptor */
+
+#define DESCR_MULTILINGUAL_BOUQUET_NAME_LEN XX
+struct descr_multilingual_bouquet_name {
+ u_char descriptor_tag :8;
+ u_char descriptor_length :8;
+};
+
+/* 0x5D multilingual_service_name_descriptor */
+
+#define DESCR_MULTILINGUAL_SERVICE_NAME_LEN XX
+struct descr_multilingual_service_name {
+ u_char descriptor_tag :8;
+ u_char descriptor_length :8;
+};
+
+struct entry_multilingual_service_name_mid {
+ u_char service_name_length :8;
+};
+
+/* 0x5E multilingual_component_descriptor */
+
+#define DESCR_MULTILINGUAL_COMPONENT_LEN XX
+struct descr_multilingual_component {
+ u_char descriptor_tag :8;
+ u_char descriptor_length :8;
+ u_char component_tag :8;
+};
+
+/* 0x5F private_data_specifier_descriptor */
+
+#define DESCR_PRIVATE_DATA_SPECIFIER_LEN XX
+struct descr_private_data_specifier {
+ u_char descriptor_tag :8;
+ u_char descriptor_length :8;
+ /* TBD */
+};
+
+/* 0x60 service_move_descriptor */
+
+#define DESCR_SERVICE_MOVE_LEN XX
+struct descr_service_move {
+ u_char descriptor_tag :8;
+ u_char descriptor_length :8;
+ u_char new_original_network_id_hi :8;
+ u_char new_original_network_id_lo :8;
+ u_char new_transport_stream_id_hi :8;
+ u_char new_transport_stream_id_lo :8;
+ u_char new_service_id_hi :8;
+ u_char new_service_id_lo :8;
+};
+
+/* 0x61 short_smoothing_buffer_descriptor */
+
+#define DESCR_SHORT_SMOOTHING_BUFFER_LEN XX
+struct descr_short_smoothing_buffer {
+ u_char descriptor_tag :8;
+ u_char descriptor_length :8;
+ /* TBD */
+};
+
+/* 0x62 frequency_list_descriptor */
+
+#define DESCR_FREQUENCY_LIST_LEN XX
+struct descr_frequency_list {
+ u_char descriptor_tag :8;
+ u_char descriptor_length :8;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char :6;
+ u_char coding_type :2;
+#else
+ u_char coding_type :2;
+ u_char :6;
+#endif
+};
+
+/* 0x63 partial_transport_stream_descriptor */
+
+#define DESCR_PARTIAL_TRANSPORT_STREAM_LEN XX
+struct descr_partial_transport_stream {
+ u_char descriptor_tag :8;
+ u_char descriptor_length :8;
+ /* TBD */
+};
+
+/* 0x64 data_broadcast_descriptor */
+
+#define DESCR_DATA_BROADCAST_LEN XX
+struct descr_data_broadcast {
+ u_char descriptor_tag :8;
+ u_char descriptor_length :8;
+ /* TBD */
+};
+
+/* 0x65 ca_system_descriptor */
+
+#define DESCR_CA_SYSTEM_LEN XX
+struct descr_ca_system {
+ u_char descriptor_tag :8;
+ u_char descriptor_length :8;
+ /* TBD */
+};
+
+/* 0x66 data_broadcast_id_descriptor */
+
+#define DESCR_DATA_BROADCAST_ID_LEN XX
+struct descr_data_broadcast_id {
+ u_char descriptor_tag :8;
+ u_char descriptor_length :8;
+ /* TBD */
+};
+
+/* 0x67 transport_stream_descriptor */
+
+#define DESCR_TRANSPORT_STREAM_LEN XX
+struct descr_transport_stream {
+ u_char descriptor_tag :8;
+ u_char descriptor_length :8;
+ /* TBD */
+};
+
+/* 0x68 dsng_descriptor */
+
+#define DESCR_DSNG_LEN XX
+struct descr_dsng {
+ u_char descriptor_tag :8;
+ u_char descriptor_length :8;
+ /* TBD */
+};
+
+/* 0x69 pdc_descriptor */
+
+#define DESCR_PDC_LEN XX
+struct descr_pdc {
+ u_char descriptor_tag :8;
+ u_char descriptor_length :8;
+ /* TBD */
+};
+
+/* 0x6A ac3_descriptor */
+
+#define DESCR_AC3_LEN 3
+struct descr_ac3 {
+ u_char descriptor_tag :8;
+ u_char descriptor_length :8;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char ac3_type_flag :1;
+ u_char bsid_flag :1;
+ u_char mainid_flag :1;
+ u_char asvc_flag :1;
+ u_char reserved :4;
+#else
+ u_char reserved :4;
+ u_char asvc_flag :1;
+ u_char mainid_flag :1;
+ u_char bsid_flag :1;
+ u_char ac3_type_flag :1;
+#endif
+ u_char ac3_type :8;
+ u_char bsid :8;
+ u_char mainid :8;
+ u_char asvc :8;
+};
+
+/* 0x6B ancillary_data_descriptor */
+
+#define DESCR_ANCILLARY_DATA_LEN 3
+struct descr_ancillary_data {
+ u_char descriptor_tag :8;
+ u_char descriptor_length :8;
+ u_char ancillary_data_identifier :8;
+};
+
+/* 0x6C cell_list_descriptor */
+
+#define DESCR_CELL_LIST_LEN XX
+struct descr_cell_list {
+ u_char descriptor_tag :8;
+ u_char descriptor_length :8;
+ /* TBD */
+};
+
+/* 0x6D cell_frequency_link_descriptor */
+
+#define DESCR_CELL_FREQUENCY_LINK_LEN XX
+struct descr_cell_frequency_link {
+ u_char descriptor_tag :8;
+ u_char descriptor_length :8;
+ /* TBD */
+};
+
+/* 0x6E announcement_support_descriptor */
+
+#define DESCR_ANNOUNCEMENT_SUPPORT_LEN XX
+struct descr_announcement_support {
+ u_char descriptor_tag :8;
+ u_char descriptor_length :8;
+ /* TBD */
+};
+
+/* 0x6F application_signalling_descriptor */
+
+#define DESCR_APPLICATION_SIGNALLING_LEN 2
+struct descr_application_signalling {
+ u_char descriptor_tag :8;
+ u_char descriptor_length :8;
+};
+
+#define APPLICATION_SIGNALLING_ENTRY_LEN 3
+struct application_signalling_entry {
+ u_char application_type_hi :8;
+ u_char application_type_lo :8;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char :3;
+ u_char AIT_version_number :5;
+#else
+ u_char AIT_version_number :5;
+ u_char :3;
+#endif
+};
+
+/* 0x71 service_identifier_descriptor (ETSI TS 102 812, MHP) */
+
+struct descr_service_identifier {
+ u_char descriptor_tag :8;
+ u_char descriptor_length :8;
+};
+
+/* MHP 0x00 application_descriptor */
+
+#define DESCR_APPLICATION_LEN 3
+
+struct descr_application {
+ u_char descriptor_tag :8;
+ u_char descriptor_length :8;
+ u_char application_profiles_length :8;
+};
+
+#define DESCR_APPLICATION_END_LEN 2
+
+struct descr_application_end {
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char service_bound_flag :1;
+ u_char visibility :2;
+ u_char :5;
+#else
+ u_char :5;
+ u_char visibility :2;
+ u_char service_bound_flag :1;
+#endif
+ u_char application_priority :8;
+/*now follow 8bit transport_protocol_label fields to the end */
+};
+
+#define APPLICATION_PROFILE_ENTRY_LEN 5
+
+struct application_profile_entry {
+ u_char application_profile_hi :8;
+ u_char application_profile_lo :8;
+ u_char version_major :8;
+ u_char version_minor :8;
+ u_char version_micro :8;
+};
+
+/* MHP 0x01 application_name_desriptor */
+
+#define DESCR_APPLICATION_NAME_LEN 2
+
+struct descr_application_name {
+ u_char descriptor_tag :8;
+ u_char descriptor_length :8;
+};
+
+#define APPLICATION_NAME_ENTRY_LEN 4
+
+struct descr_application_name_entry {
+ u_char lang_code1 :8;
+ u_char lang_code2 :8;
+ u_char lang_code3 :8;
+ u_char application_name_length :8;
+ /* application name string */
+};
+
+/* MHP 0x02 transport_protocol_descriptor */
+
+#define DESCR_TRANSPORT_PROTOCOL_LEN 5
+
+struct descr_transport_protocol {
+ u_char descriptor_tag :8;
+ u_char descriptor_length :8;
+ u_char protocol_id_hi :8;
+ u_char protocol_id_lo :8;
+ u_char transport_protocol_label :8;
+ /* protocol_id-specific selector bytes follow */
+};
+
+#define TRANSPORT_VIA_OC_LEN 1
+
+struct transport_via_oc {
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char remote :1;
+ u_char :7;
+#else
+ u_char :7;
+ u_char remote :1;
+#endif
+};
+
+//if remote is true, transport_via_oc_remote_end_t follows,
+// else transport_via_oc_end_t.
+
+#define TRANSPORT_VIA_OC_REMOTE_END_LEN 7
+
+struct transport_via_oc_remote_end {
+ u_char original_network_id_hi :8;
+ u_char original_network_id_lo :8;
+ u_char transport_stream_id_hi :8;
+ u_char transport_stream_id_lo :8;
+ u_char service_id_hi :8;
+ u_char service_id_lo :8;
+ u_char component_tag :8;
+};
+
+#define TRANSPORT_VIA_OC_END_LEN 1
+
+struct transport_via_oc_end {
+ u_char component_tag :8;
+};
+
+/* 0x03 dvb_j_application_descriptor() */
+
+#define DESCR_DVBJ_APPLICATION_LEN 2
+
+struct descr_dvbj_application {
+ u_char descriptor_tag :8;
+ u_char descriptor_length :8;
+};
+
+#define DESCR_DVBJ_APPLICATION_ENTRY_LEN 1
+
+struct descr_dvbj_application_entry {
+ u_char parameter_length :8;
+ /* parameter string */
+};
+
+/* 0x04 dvb_j_application_location_descriptor */
+
+#define DESCR_DVBJ_APPLICATION_LOCATION_LEN 3
+
+struct descr_dvbj_application_location {
+ u_char descriptor_tag :8;
+ u_char descriptor_length :8;
+ u_char base_directory_length :8;
+ /* base directory string */
+};
+
+#define DESCR_DVBJ_APPLICATION_LOCATION_MID_LEN 1
+
+struct descr_dvbj_application_location_mid {
+ u_char classpath_extension_length :8;
+};
+
+/* 0x0B application_icons_descriptor */
+
+#define DESCR_APPLICATION_ICONS_LEN 3
+
+struct descr_application_icons_descriptor {
+ u_char descriptor_tag :8;
+ u_char descriptor_length :8;
+ u_char icon_locator_length :8;
+ /* icon locator */
+};
+
+#define DESCR_APPLICATION_ICONS_END_LEN 2
+
+struct descr_application_icons_descriptor_end {
+ u_char icon_flags_hi :8;
+ u_char icon_flags_lo :8;
+};
+
+} //end of namespace
+
+#endif //LIBSI_HEADERS_H
diff --git a/libsi/section.c b/libsi/section.c
new file mode 100644
index 0000000..0de2a57
--- /dev/null
+++ b/libsi/section.c
@@ -0,0 +1,328 @@
+/***************************************************************************
+ * 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: section.c 1.2 2003/12/13 10:42:14 kls Exp $
+ * *
+ ***************************************************************************/
+
+#include "section.h"
+#include <stdio.h>
+
+namespace SI {
+
+/*********************** PAT ***********************/
+
+void PAT::Parse() {
+ unsigned int offset=0;
+ data.setPointerAndOffset<const pat>(s, offset);
+ associationLoop.setData(data+offset, getLength()-offset-4);
+}
+
+int PAT::getTransportStreamId() const {
+ return HILO(s->transport_stream_id);
+}
+
+int PAT::Association::getServiceId() const {
+ return HILO(s->program_number);
+}
+
+int PAT::Association::getPid() const {
+ return HILO(s->network_pid);
+}
+
+void PAT::Association::Parse() {
+ s=data.getData<pat_prog>();
+}
+
+/*********************** CAT ***********************/
+
+void CAT::Parse() {
+ loop.setData(data+sizeof(cat), getLength()-sizeof(cat)-4);
+}
+
+/*********************** PMT ***********************/
+
+void PMT::Parse() {
+ unsigned int offset=0;
+ data.setPointerAndOffset<const pmt>(s, offset);
+ commonDescriptors.setDataAndOffset(data+offset, HILO(s->program_info_length), offset);
+ streamLoop.setData(data+offset, getLength()-offset-4);
+}
+
+int PMT::getServiceId() const {
+ return HILO(s->program_number);
+}
+
+int PMT::getPCRPid() const {
+ return HILO(s->PCR_PID);
+}
+
+int PMT::Stream::getPid() const {
+ return HILO(s->elementary_PID);
+}
+
+int PMT::Stream::getStreamType() const {
+ return s->stream_type;
+}
+
+void PMT::Stream::Parse() {
+ unsigned int offset=0;
+ data.setPointerAndOffset<const pmt_info>(s, offset);
+ streamDescriptors.setData(data+offset, HILO(s->ES_info_length));
+}
+
+/*********************** NIT ***********************/
+
+int NIT::getNetworkId() const {
+ return HILO(s->network_id);
+}
+
+void NIT::Parse() {
+ unsigned int offset=0;
+ data.setPointerAndOffset<const nit>(s, offset);
+ commonDescriptors.setDataAndOffset(data+offset, HILO(s->network_descriptor_length), offset);
+ const nit_mid *mid;
+ data.setPointerAndOffset<const nit_mid>(mid, offset);
+ transportStreamLoop.setData(data+offset, HILO(mid->transport_stream_loop_length));
+}
+
+int NIT::TransportStream::getTransportStreamId() const {
+ return HILO(s->transport_stream_id);
+}
+
+int NIT::TransportStream::getOriginalNetworkId() const {
+ return HILO(s->original_network_id);
+}
+
+void NIT::TransportStream::Parse() {
+ unsigned int offset=0;
+ data.setPointerAndOffset<const ni_ts>(s, offset);
+ transportStreamDescriptors.setData(data+offset, HILO(s->transport_descriptors_length));
+}
+
+/*********************** SDT ***********************/
+
+void SDT::Parse() {
+ unsigned int offset=0;
+ data.setPointerAndOffset<const sdt>(s, offset);
+ serviceLoop.setData(data+offset, getLength()-offset-4); //4 is for CRC
+}
+
+int SDT::getTransportStreamId() const {
+ return HILO(s->transport_stream_id);
+}
+
+int SDT::getOriginalNetworkId() const {
+ return HILO(s->original_network_id);
+}
+
+int SDT::Service::getServiceId() const {
+ return HILO(s->service_id);
+}
+
+int SDT::Service::getEITscheduleFlag() const {
+ return s->eit_schedule_flag;
+}
+
+int SDT::Service::getEITpresentFollowingFlag() const {
+ return s->eit_present_following_flag;
+}
+
+RunningStatus SDT::Service::getRunningStatus() const {
+ return (RunningStatus)s->running_status;
+}
+
+int SDT::Service::getFreeCaMode() const {
+ return s->free_ca_mode;
+}
+
+void SDT::Service::Parse() {
+ unsigned int offset=0;
+ data.setPointerAndOffset<const sdt_descr>(s, offset);
+ serviceDescriptors.setData(data+offset, HILO(s->descriptors_loop_length));
+}
+
+/*********************** EIT ***********************/
+
+int EIT::getServiceId() const {
+ return HILO(s->service_id);
+}
+
+int EIT::getTransportStreamId() const {
+ return HILO(s->transport_stream_id);
+}
+
+int EIT::getOriginalNetworkId() const {
+ return HILO(s->original_network_id);
+}
+
+bool EIT::isPresentFollowing() const {
+ return getTableId() == TableIdEIT_presentFollowing || getTableId() == TableIdEIT_presentFollowing_other;
+}
+
+bool EIT::isActualTS() const {
+ return
+ (getTableId() ==TableIdEIT_presentFollowing)
+ || (TableIdEIT_schedule_first <= getTableId() && getTableId() <= TableIdEIT_schedule_last);
+}
+
+void EIT::Parse() {
+ unsigned int offset=0;
+ data.setPointerAndOffset<const eit>(s, offset);
+ //printf("%d %d %d %d %d\n", getServiceId(), getTransportStreamId(), getOriginalNetworkId(), isPresentFollowing(), isActualTS());
+ eventLoop.setData(data+offset, getLength()-offset-4); //4 is for CRC
+}
+
+time_t EIT::Event::getStartTime() const {
+ return DVBTime::getTime(s->mjd_hi, s->mjd_lo, s->start_time_h, s->start_time_m, s->start_time_s);
+}
+
+time_t EIT::Event::getDuration() const {
+ return DVBTime::getDuration(s->duration_h, s->duration_m, s->duration_s);
+}
+
+int EIT::Event::getEventId() const {
+ return HILO(s->event_id);
+}
+
+int EIT::Event::getMJD() const {
+ return HILO(s->mjd);
+}
+
+int EIT::Event::getStartTimeHour() const {
+ return DVBTime::bcdToDec(s->start_time_h);
+}
+
+int EIT::Event::getStartTimeMinute() const {
+ return DVBTime::bcdToDec(s->start_time_m);
+}
+
+int EIT::Event::getStartTimeSecond() const {
+ return DVBTime::bcdToDec(s->start_time_s);
+}
+
+int EIT::Event::getDurationHour() const {
+ return DVBTime::bcdToDec(s->duration_h);
+}
+
+int EIT::Event::getDurationMinute() const {
+ return DVBTime::bcdToDec(s->duration_m);
+}
+
+int EIT::Event::getDurationSecond() const {
+ return DVBTime::bcdToDec(s->duration_s);
+}
+
+RunningStatus EIT::Event::getRunningStatus() const {
+ return (RunningStatus)s->running_status;
+}
+
+int EIT::Event::getFreeCaMode() const {
+ return s->free_ca_mode;
+}
+
+void EIT::Event::Parse() {
+ unsigned int offset=0;
+ data.setPointerAndOffset<const eit_event>(s, offset);
+ //printf("%d %d %d\n", getStartTime(), getDuration(), getRunningStatus());
+ eventDescriptors.setData(data+offset, HILO(s->descriptors_loop_length));
+}
+
+/*********************** TDT ***********************/
+
+time_t TDT::getTime() const {
+ return DVBTime::getTime(s->utc_mjd_hi, s->utc_mjd_lo, s->utc_time_h, s->utc_time_m, s->utc_time_s);
+}
+
+void TDT::Parse() {
+ s=data.getData<const tdt>();
+}
+
+/*********************** TOT ***********************/
+
+time_t TOT::getTime() const {
+ return DVBTime::getTime(s->utc_mjd_hi, s->utc_mjd_lo, s->utc_time_h, s->utc_time_m, s->utc_time_s);
+}
+
+void TOT::Parse() {
+ unsigned int offset=0;
+ data.setPointerAndOffset<const tot>(s, offset);
+ descriptorLoop.setData(data+offset, getLength()-offset-4);
+}
+
+/*********************** RST ***********************/
+
+void RST::Parse() {
+ unsigned int offset=0;
+ const rst *s;
+ data.setPointerAndOffset<const rst>(s, offset);
+ infoLoop.setData(data+offset, getLength()-offset);
+}
+
+int RST::RunningInfo::getTransportStreamId() const {
+ return HILO(s->transport_stream_id);
+}
+
+int RST::RunningInfo::getOriginalNetworkId() const {
+ return HILO(s->original_network_id);
+}
+
+int RST::RunningInfo::getServiceId() const {
+ return HILO(s->service_id);
+}
+
+int RST::RunningInfo::getEventId() const {
+ return HILO(s->event_id);
+}
+
+RunningStatus RST::RunningInfo::getRunningStatus() const {
+ return (RunningStatus)s->running_status;
+}
+
+void RST::RunningInfo::Parse() {
+ s=data.getData<const rst_info>();
+}
+
+/*********************** AIT ***********************/
+
+int AIT::getApplicationType() const {
+ return HILO(first->application_type);
+}
+
+int AIT::getAITVersion() const {
+ return first->version_number;
+}
+
+void AIT::Parse() {
+ unsigned int offset=0;
+ data.setPointerAndOffset<const ait>(first, offset);
+ commonDescriptors.setDataAndOffset(data+offset, HILO(first->common_descriptors_length), offset);
+ const ait_mid *mid;
+ data.setPointerAndOffset<const ait_mid>(mid, offset);
+ applicationLoop.setData(data+offset, HILO(mid->application_loop_length));
+}
+
+long AIT::Application::getOrganisationId() const {
+ return data.FourBytes(0);
+}
+
+int AIT::Application::getApplicationId() const {
+ return HILO(s->application_id);
+}
+
+int AIT::Application::getControlCode() const {
+ return s->application_control_code;
+}
+
+void AIT::Application::Parse() {
+ unsigned int offset=0;
+ data.setPointerAndOffset<const ait_app>(s, offset);
+ applicationDescriptors.setData(data+offset, HILO(s->application_descriptors_length));
+}
+
+} //end of namespace
diff --git a/libsi/section.h b/libsi/section.h
new file mode 100644
index 0000000..efca9bb
--- /dev/null
+++ b/libsi/section.h
@@ -0,0 +1,252 @@
+/***************************************************************************
+ * 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: section.h 1.2 2003/12/13 10:42:15 kls Exp $
+ * *
+ ***************************************************************************/
+
+#ifndef LIBSI_SECTION_H
+#define LIBSI_SECTION_H
+
+#include <time.h>
+
+#include "si.h"
+#include "headers.h"
+
+namespace SI {
+
+class PAT : public NumberedSection {
+public:
+ PAT(const unsigned char *data, bool doCopy=true) : NumberedSection(data, doCopy) {}
+ PAT() {}
+ class Association : public LoopElement {
+ public:
+ int getServiceId() const;
+ int getPid() const;
+ bool isNITPid() const { return getServiceId()==0; }
+ virtual int getLength() { return sizeof(pat_prog); }
+ protected:
+ virtual void Parse();
+ private:
+ const pat_prog *s;
+ };
+ int getTransportStreamId() const;
+ StructureLoop<Association> associationLoop;
+protected:
+ virtual void Parse();
+private:
+ const pat *s;
+};
+
+class CAT : public NumberedSection {
+public:
+ CAT(const unsigned char *data, bool doCopy=true) : NumberedSection(data, doCopy) {}
+ CAT() {}
+ DescriptorLoop loop;
+protected:
+ virtual void Parse();
+};
+
+class PMT : public NumberedSection {
+public:
+ PMT(const unsigned char *data, bool doCopy=true) : NumberedSection(data, doCopy) {}
+ PMT() {}
+ class Stream : public LoopElement {
+ public:
+ int getPid() const;
+ int getStreamType() const;
+ DescriptorLoop streamDescriptors;
+ virtual int getLength() { return sizeof(pmt_info)+streamDescriptors.getLength(); }
+ protected:
+ virtual void Parse();
+ private:
+ const pmt_info *s;
+ };
+ DescriptorLoop commonDescriptors;
+ StructureLoop<Stream> streamLoop;
+ int getServiceId() const;
+ int getPCRPid() const;
+protected:
+ virtual void Parse();
+private:
+ const pmt *s;
+};
+
+class NIT : public NumberedSection {
+public:
+ NIT(const unsigned char *data, bool doCopy=true) : NumberedSection(data, doCopy) {}
+ NIT() {}
+ class TransportStream : public LoopElement {
+ public:
+ int getTransportStreamId() const;
+ int getOriginalNetworkId() const;
+ virtual int getLength() { return sizeof(ni_ts)+transportStreamDescriptors.getLength(); }
+ DescriptorLoop transportStreamDescriptors;
+ protected:
+ virtual void Parse();
+ private:
+ const ni_ts *s;
+ };
+ DescriptorLoop commonDescriptors;
+ StructureLoop<TransportStream> transportStreamLoop;
+ int getNetworkId() const;
+protected:
+ virtual void Parse();
+private:
+ const nit *s;
+};
+
+//BAT has the same structure as NIT but different allowed descriptors
+class BAT : public NIT {
+public:
+ BAT(const unsigned char *data, bool doCopy=true) : NIT(data, doCopy) {}
+ BAT() {}
+ int getBouquetId() const { return getNetworkId(); }
+};
+
+class SDT : public NumberedSection {
+public:
+ SDT(const unsigned char *data, bool doCopy=true) : NumberedSection(data, doCopy) {}
+ SDT() {}
+ class Service : public LoopElement {
+ public:
+ int getServiceId() const;
+ int getEITscheduleFlag() const;
+ int getEITpresentFollowingFlag() const;
+ RunningStatus getRunningStatus() const;
+ int getFreeCaMode() const;
+ virtual int getLength() { return sizeof(sdt_descr)+serviceDescriptors.getLength(); }
+ DescriptorLoop serviceDescriptors;
+ protected:
+ virtual void Parse();
+ private:
+ const sdt_descr *s;
+ };
+ int getTransportStreamId() const;
+ int getOriginalNetworkId() const;
+ StructureLoop<Service> serviceLoop;
+protected:
+ virtual void Parse();
+private:
+ const sdt *s;
+};
+
+class EIT : public NumberedSection {
+public:
+ EIT(const unsigned char *data, bool doCopy=true) : NumberedSection(data, doCopy) {}
+ EIT() {}
+ class Event : public LoopElement {
+ public:
+ int getEventId() const;
+ time_t getStartTime() const; //UTC
+ time_t getDuration() const;
+
+ int getMJD() const;
+ int getStartTimeHour() const; //UTC
+ int getStartTimeMinute() const; //UTC
+ int getStartTimeSecond() const; //UTC
+ int getDurationHour() const;
+ int getDurationMinute() const;
+ int getDurationSecond() const;
+ RunningStatus getRunningStatus() const;
+ int getFreeCaMode() const;
+
+ DescriptorLoop eventDescriptors;
+ virtual int getLength() { return sizeof(eit_event)+eventDescriptors.getLength(); }
+ protected:
+ virtual void Parse();
+ private:
+ const eit_event *s;
+ };
+ int getServiceId() const;
+ int getTransportStreamId() const;
+ int getOriginalNetworkId() const;
+ StructureLoop<Event> eventLoop;
+
+ //true if table conveys present/following information, false if it conveys schedule information
+ bool isPresentFollowing() const;
+ //true if table describes TS on which it is broadcast, false if it describes other TS
+ bool isActualTS() const;
+protected:
+ virtual void Parse();
+private:
+ const eit *s;
+};
+
+class TDT : public Section {
+public:
+ TDT(const unsigned char *data, bool doCopy=true) : Section(data, doCopy) {}
+ TDT() {}
+ time_t getTime() const; //UTC
+protected:
+ virtual void Parse();
+private:
+ const tdt *s;
+};
+
+class TOT : public CRCSection {
+public:
+ TOT(const unsigned char *data, bool doCopy=true) : CRCSection(data, doCopy) {}
+ TOT() {}
+ time_t getTime() const;
+ DescriptorLoop descriptorLoop;
+protected:
+ virtual void Parse();
+private:
+ const tot *s;
+};
+
+class RST : public Section {
+public:
+ RST(const unsigned char *data, bool doCopy=true) : Section(data, doCopy) {}
+ RST() {}
+ class RunningInfo : public LoopElement {
+ public:
+ int getTransportStreamId() const;
+ int getOriginalNetworkId() const;
+ int getServiceId() const;
+ int getEventId() const;
+ RunningStatus getRunningStatus() const;
+ virtual int getLength() { return sizeof(rst_info); }
+ protected:
+ virtual void Parse();
+ private:
+ const rst_info *s;
+ };
+ StructureLoop<RunningInfo> infoLoop;
+protected:
+ virtual void Parse();
+};
+
+class AIT : public NumberedSection {
+public:
+ AIT(const unsigned char *data, bool doCopy=true) : NumberedSection(data, doCopy) {}
+ AIT() {}
+ class Application : public LoopElement {
+ public:
+ virtual int getLength() { return sizeof(ait_app)+applicationDescriptors.getLength(); }
+ long getOrganisationId() const;
+ int getApplicationId() const;
+ int getControlCode() const;
+ MHP_DescriptorLoop applicationDescriptors;
+ protected:
+ virtual void Parse();
+ const ait_app *s;
+ };
+ MHP_DescriptorLoop commonDescriptors;
+ StructureLoop<Application> applicationLoop;
+ int getApplicationType() const;
+ int getAITVersion() const;
+protected:
+ const ait *first;
+ virtual void Parse();
+};
+
+} //end of namespace
+
+#endif //LIBSI_TABLE_H
diff --git a/libsi/si.c b/libsi/si.c
new file mode 100644
index 0000000..bcf519a
--- /dev/null
+++ b/libsi/si.c
@@ -0,0 +1,415 @@
+/***************************************************************************
+ * 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.3 2004/01/04 14:26:53 kls Exp $
+ * *
+ ***************************************************************************/
+
+#include <string.h>
+#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<ExtendedSectionHeader>()->current_next_indicator;
+}
+
+int NumberedSection::getVersionNumber() const {
+ return data.getData<ExtendedSectionHeader>()->version_number;
+}
+
+int NumberedSection::getSectionNumber() const {
+ return data.getData<ExtendedSectionHeader>()->section_number;
+}
+
+int NumberedSection::getLastSectionNumber() const {
+ return data.getData<ExtendedSectionHeader>()->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.i<getLength()) {
+ return createDescriptor(it.i);
+ }
+ return 0;
+}
+
+Descriptor *DescriptorLoop::getNext(Iterator &it, DescriptorTag tag, bool returnUnimplemetedDescriptor) {
+ Descriptor *d=0;
+ if (it.i<getLength()) {
+ const unsigned char *p=data.getData(it.i);
+ const unsigned char *end=p+getLength();
+ while (p < end) {
+ if (Descriptor::getDescriptorTag(p) == tag) {
+ d=createDescriptor(it.i);
+ break;
+ }
+ it.i+=Descriptor::getLength(p);
+ p+=Descriptor::getLength(p);
+ }
+ }
+ if (d && d->getDescriptorTag()==UnimplementedDescriptorTag)
+ return returnUnimplemetedDescriptor ? d : 0;
+ return d;
+}
+
+Descriptor *DescriptorLoop::getNext(Iterator &it, DescriptorTag *tags, int arrayLength, bool returnUnimplemetedDescriptor) {
+ Descriptor *d=0;
+ if (it.i<getLength()) {
+ const unsigned char *p=data.getData(it.i);
+ const unsigned char *end=p+getLength();
+ while (p < end) {
+ for (int u=0; u<arrayLength;u++)
+ if (Descriptor::getDescriptorTag(p) == tags[u]) {
+ d=createDescriptor(it.i);
+ break;
+ }
+ if (d)
+ break;
+ it.i+=Descriptor::getLength(p);
+ p+=Descriptor::getLength(p);
+ }
+ }
+ if (d && d->getDescriptorTag()==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;i<length;i++)
+ if (array[i]!=0) {
+ delete array[i];
+ array[i]=0;
+ }
+}
+
+void DescriptorGroup::Add(GroupDescriptor *d) {
+ if (!array) {
+ length=d->getLastDescriptorNumber()+1;
+ array=new GroupDescriptor*[length]; //numbering is zero-based
+ for (int i=0;i<length;i++)
+ array[i]=0;
+ } else if (length != d->getLastDescriptorNumber()+1)
+ return; //avoid crash in case of misuse
+ array[d->getDescriptorNumber()]=d;
+}
+
+bool DescriptorGroup::isComplete() {
+ for (int i=0;i<length;i++)
+ if (array[i]==0)
+ return false;
+ return true;
+}
+
+char *String::getText() {
+ if (getLength() < 0 || getLength() >4095)
+ 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 <hakenes@hippomi.de>
+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) && (*from <= 0xFF))
+ )
+ *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<DescriptorHeader>()->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<DescriptorHeader>()->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
diff --git a/libsi/si.h b/libsi/si.h
new file mode 100644
index 0000000..31d17cb
--- /dev/null
+++ b/libsi/si.h
@@ -0,0 +1,392 @@
+/***************************************************************************
+ * 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.h 1.3 2003/12/26 14:09:30 kls Exp $
+ * *
+ ***************************************************************************/
+
+#ifndef LIBSI_SI_H
+#define LIBSI_SI_H
+
+#include <stdint.h>
+
+#include "util.h"
+#include "headers.h"
+
+namespace SI {
+
+enum TableId { TableIdPAT = 0x00, //program association section
+ TableIdCAT = 0x01, //conditional access section
+ TableIdPMT = 0x02, //program map section
+ TableIdTSDT = 0x03,//transport stream description section
+ TableIdNIT = 0x40, //network information, actual network section
+ TableIdNIT_other = 0x41, //network information section, other network
+ TableIdSDT = 0x42, //service description section
+ TableIdSDT_other = 0x46,
+ TableIdBAT = 0x46, //bouquet association section
+ TableIdEIT_presentFollowing = 0x4E, //event information section
+ TableIdEIT_presentFollowing_other = 0x4F,
+ //range from 0x50 to 0x5F
+ TableIdEIT_schedule_first = 0x50,
+ TableIdEIT_schedule_last = 0x5F,
+ //range from 0x60 to 0x6F
+ TableIdEIT_schedule_Other_first = 0x60,
+ TableIdEIT_schedule_Other_fast = 0x6F,
+ TableIdTDT = 0x70, //time date section
+ TableIdRST = 0x71, //running status section
+ TableIdST = 0x72, //stuffing section
+ TableIdTOT = 0x73, //time offset section
+ TableIdDIT = 0x7E, //discontinuity information section
+ TableIdSIT = 0x7F, //service information section
+ TableIdAIT = 0x74 //application information section
+ };
+
+
+enum DescriptorTag {
+ // defined by ISO/IEC 13818-1
+ VideoStreamDescriptorTag = 0x02,
+ AudioStreamDescriptorTag = 0x03,
+ HierarchyDescriptorTag = 0x04,
+ RegistrationDescriptorTag = 0x05,
+ DataStreamAlignmentDescriptorTag = 0x06,
+ TargetBackgroundGridDescriptorTag = 0x07,
+ VideoWindowDescriptorTag = 0x08,
+ CaDescriptorTag = 0x09,
+ ISO639LanguageDescriptorTag = 0x0A,
+ SystemClockDescriptorTag = 0x0B,
+ MultiplexBufferUtilizationDescriptorTag = 0x0C,
+ CopyrightDescriptorTag = 0x0D,
+ MaximumBitrateDescriptorTag = 0x0E,
+ PrivateDataIndicatorDescriptorTag = 0x0F,
+ SmoothingBufferDescriptorTag = 0x10,
+ STDDescriptorTag = 0x11,
+ IBPDescriptorTag = 0x12,
+ // defined by ISO-13818-6 (DSM-CC)
+ CarouselIdentifierDescriptorTag = 0x13,
+ // 0x14 - 0x3F Reserved
+ // defined by ETSI (EN 300 468)
+ NetworkNameDescriptorTag = 0x40,
+ ServiceListDescriptorTag = 0x41,
+ StuffingDescriptorTag = 0x42,
+ SatelliteDeliverySystemDescriptorTag = 0x43,
+ CableDeliverySystemDescriptorTag = 0x44,
+ VBIDataDescriptorTag = 0x45,
+ VBITeletextDescriptorTag = 0x46,
+ BouquetNameDescriptorTag = 0x47,
+ ServiceDescriptorTag = 0x48,
+ CountryAvailabilityDescriptorTag = 0x49,
+ LinkageDescriptorTag = 0x4A,
+ NVODReferenceDescriptorTag = 0x4B,
+ TimeShiftedServiceDescriptorTag = 0x4C,
+ ShortEventDescriptorTag = 0x4D,
+ ExtendedEventDescriptorTag = 0x4E,
+ TimeShiftedEventDescriptorTag = 0x4F,
+ ComponentDescriptorTag = 0x50,
+ MocaicDescriptorTag = 0x51,
+ StreamIdentifierDescriptorTag = 0x52,
+ CaIdentifierDescriptorTag = 0x53,
+ ContentDescriptorTag = 0x54,
+ ParentalRatingDescriptorTag = 0x55,
+ TeletextDescriptorTag = 0x56,
+ TelephoneDescriptorTag = 0x57,
+ LocalTimeOffsetDescriptorTag = 0x58,
+ SubtitlingDescriptorTag = 0x59,
+ TerrestrialDeliverySystemDescriptorTag = 0x5A,
+ MultilingualNetworkNameDescriptorTag = 0x5B,
+ MultilingualBouquetNameDescriptorTag = 0x5C,
+ MultilingualServiceNameDescriptorTag = 0x5D,
+ MultilingualComponentDescriptorTag = 0x5E,
+ PrivateDataSpecifierDescriptorTag = 0x5F,
+ ServiceMoveDescriptorTag = 0x60,
+ ShortSmoothingBufferDescriptorTag = 0x61,
+ FrequencyListDescriptorTag = 0x62,
+ PartialTransportStreamDescriptorTag = 0x63,
+ DataBroadcastDescriptorTag = 0x64,
+ CaSystemDescriptorTag = 0x65,
+ DataBroadcastIdDescriptorTag = 0x66,
+ TransportStreamDescriptorTag = 0x67,
+ DSNGDescriptorTag = 0x68,
+ PDCDescriptorTag = 0x69,
+ AC3DescriptorTag = 0x6A,
+ AncillaryDataDescriptorTag = 0x6B,
+ CellListDescriptorTag = 0x6C,
+ CellFrequencyLinkDescriptorTag = 0x6D,
+ AnnouncementSupportDescriptorTag = 0x6E,
+ ApplicationSignallingDescriptorTag = 0x6F,
+ AdaptationFieldDataDescriptorTag = 0x70,
+ ServiceIdentifierDescriptorTag = 0x71,
+ ServiceAvailabilityDescriptorTag = 0x72,
+ // Defined by ETSI TS 102 812 (MHP)
+ // They once again start with 0x00 (see page 234, MHP specification)
+ MHP_ApplicationDescriptorTag = 0x00,
+ MHP_ApplicationNameDescriptorTag = 0x01,
+ MHP_TransportProtocolDescriptorTag = 0x02,
+ MHP_DVBJApplicationDescriptorTag = 0x03,
+ MHP_DVBJApplicationLocationDescriptorTag = 0x04,
+ // 0x05 - 0x0A is unimplemented this library
+ MHP_ExternalApplicationAuthorisationDescriptorTag = 0x05,
+ MHP_IPv4RoutingDescriptorTag = 0x06,
+ MHP_IPv6RoutingDescriptorTag = 0x07,
+ MHP_DVBHTMLApplicationDescriptorTag = 0x08,
+ MHP_DVBHTMLApplicationLocationDescriptorTag = 0x09,
+ MHP_DVBHTMLApplicationBoundaryDescriptorTag = 0x0A,
+ MHP_ApplicationIconsDescriptorTag = 0x0B,
+ MHP_PrefetchDescriptorTag = 0x0C,
+ MHP_DelegatedApplicationDescriptorTag = 0x0E,
+ MHP_ApplicationStorageDescriptorTag = 0x10,
+
+ //a descriptor currently unimplemented in this library
+ //the actual value 0xFF is "forbidden" according to the spec.
+ UnimplementedDescriptorTag = 0xFF
+};
+
+enum DescriptorTagDomain { SI, MHP };
+
+enum RunningStatus { RunningStatusUndefined = 0,
+ RunningStatusNotRunning = 1,
+ RunningStatusStartsInAFewSeconds = 2,
+ RunningStatusPausing = 3,
+ RunningStatusRunning = 4
+ };
+
+/* Some principles:
+ - Objects that return references to other objects contained in their data must make sure
+ that the returned objects have been parsed.
+ (the Loop subclasses take care of that.)
+ Note that this does not apply to Loops and Strings (their are never returned by reference, BTW).
+*/
+
+class Object : public Parsable {
+public:
+ Object();
+ Object(CharArray &d);
+ //can only be called once since data is immutable
+ void setData(const unsigned char*data, unsigned int size, bool doCopy=true);
+ virtual int getLength() = 0;
+protected:
+ CharArray data;
+ //is protected - not used for sections
+ template <class T> friend class StructureLoop;
+ void setData(CharArray &d);
+};
+
+class Section : public Object {
+public:
+ //convenience: sets data and parses if doParse
+ Section(const unsigned char *data, bool doCopy=true);
+ Section() {}
+ TableId getTableId() const;
+ virtual int getLength();
+
+ static int getLength(const unsigned char *d);
+ static TableId getTableId(const unsigned char *d);
+};
+
+class CRCSection : public Section {
+public:
+ //convenience: sets data and parses if doParse
+ CRCSection(const unsigned char *data, bool doCopy=true) : Section(data, doCopy) {}
+ CRCSection() {}
+ bool isValid();
+ //convenience: isValid+CheckParse
+ bool CheckCRCAndParse();
+};
+
+/* A section which has the ExtendedSectionHeader
+ (section_syntax_indicator==1) */
+class NumberedSection : public CRCSection {
+public:
+ NumberedSection(const unsigned char *data, bool doCopy=true) : CRCSection(data, doCopy) {}
+ NumberedSection() {}
+ bool getCurrentNextIndicator() const;
+ int getVersionNumber() const;
+ int getSectionNumber() const;
+ int getLastSectionNumber() const;
+ bool moreThanOneSection() const { return getLastSectionNumber()>1; }
+};
+
+class VariableLengthPart : public Object {
+public:
+ //never forget to call this
+ void setData(CharArray d, int l) { Object::setData(d); length=l; }
+ //convenience method
+ void setDataAndOffset(CharArray d, int l, unsigned int &offset) { Object::setData(d); length=l; offset+=l; }
+ virtual int getLength() { return length; }
+private:
+ int length;
+};
+
+class LoopElement : public Object {
+};
+
+class SubStructure : public LoopElement {
+};
+
+class Descriptor : public LoopElement {
+public:
+ virtual int getLength();
+ DescriptorTag getDescriptorTag() const;
+
+ static int getLength(const unsigned char *d);
+ static DescriptorTag getDescriptorTag(const unsigned char *d);
+protected:
+ friend class DescriptorLoop;
+ //returns a subclass of descriptor according to the data given.
+ //The object is allocated with new and must be delete'd.
+ //setData() will have been called, CheckParse() not.
+ //Never returns null - maybe the UnimplementedDescriptor.
+ static Descriptor *getDescriptor(CharArray d, DescriptorTagDomain domain);
+};
+
+class Loop : public VariableLengthPart {
+public:
+ class Iterator {
+ public:
+ Iterator() { i=0; }
+ void reset() { i=0; }
+ private:
+ template <class T> friend class StructureLoop;
+ friend class DescriptorLoop;
+ template <class T> friend class TypeLoop;
+ int i;
+ };
+protected:
+ virtual void Parse() {}
+};
+
+//contains LoopElements of one type only
+template <class T> class StructureLoop : public Loop {
+public:
+ //currently you must use a while-loop testing for hasNext()
+ //i must be 0 to get the first descriptor (with the first call)
+ T getNext(Iterator &it)
+ {
+ CharArray d=data;
+ d.addOffset(it.i);
+ T ret;
+ ret.setData(d);
+ ret.CheckParse();
+ it.i+=ret.getLength();
+ return ret;
+ }
+ T* getNextAsPointer(Iterator &it)
+ {
+ if (getLength() <= it.i)
+ return 0;
+ CharArray d=data;
+ d.addOffset(it.i);
+ T *ret=new T();
+ ret->setData(d);
+ ret->CheckParse();
+ it.i+=ret->getLength();
+ return ret;
+ }
+ bool hasNext(Iterator &it) { return getLength() > it.i; }
+};
+
+//contains descriptors of different types
+class DescriptorLoop : public Loop {
+public:
+ DescriptorLoop() { domain=SI; }
+ //i must be 0 to get the first descriptor (with the first call)
+ //All returned descriptors must be delete'd.
+ //returns null if no more descriptors available
+ Descriptor *getNext(Iterator &it);
+ //return the next descriptor with given tag, or 0 if not available.
+ //if the descriptor found is not implemented,
+ // an UnimplementedDescriptor will be returned if returnUnimplemetedDescriptor==true,
+ // 0 will be returned if returnUnimplemetedDescriptor==false
+ Descriptor *getNext(Iterator &it, DescriptorTag tag, bool returnUnimplemetedDescriptor=false);
+ //return the next descriptor with one of the given tags, or 0 if not available.
+ Descriptor *getNext(Iterator &it, DescriptorTag *tags, int arrayLength, bool returnUnimplemetedDescriptor=false);
+protected:
+ Descriptor *createDescriptor(int &i);
+ DescriptorTagDomain domain;
+};
+
+typedef uint8_t EightBit;
+typedef uint16_t SixteenBit;
+typedef uint32_t ThirtyTwoBit;
+typedef uint64_t SixtyFourBit;
+
+template <typename T> class TypeLoop : public Loop {
+public:
+ int getCount() const { return getLength()/sizeof(T); }
+ T operator[](const unsigned int index) const
+ {
+ switch (sizeof(T)) {
+ case 1:
+ return data[index];
+ case 2:
+ return data.TwoBytes(index);
+ case 4:
+ return data.FourBytes(index);
+ case 8:
+ return (SixtyFourBit(data.FourBytes(index)) << 32) | data.FourBytes(index+4);
+ }
+ }
+ T getNext(Iterator &it) const
+ {
+ T ret=operator[](it.i);
+ it.i+=sizeof(T);
+ return ret;
+ }
+ bool hasNext(Iterator &it) { return getLength() > it.i; }
+};
+
+class MHP_DescriptorLoop : public DescriptorLoop {
+public:
+ MHP_DescriptorLoop() { domain=MHP; }
+};
+
+//The content of the ExtendedEventDescriptor may be split over several
+//descriptors if the text is longer than 256 bytes.
+//The following classes provide base functionality to handle this case.
+class GroupDescriptor : public Descriptor {
+public:
+ virtual int getDescriptorNumber() = 0;
+ virtual int getLastDescriptorNumber() = 0;
+};
+
+class DescriptorGroup {
+public:
+ DescriptorGroup(bool deleteOnDesctruction=true);
+ ~DescriptorGroup();
+ void Add(GroupDescriptor *d);
+ void Delete();
+ int getLength() { return length; }
+ GroupDescriptor **getDescriptors() { return array; }
+ bool isComplete(); //if all descriptors have been added
+protected:
+ int length;
+ GroupDescriptor **array;
+ bool deleteOnDesctruction;
+};
+
+class String : public VariableLengthPart {
+public:
+ //A note to the length: getLength() returns the length of the raw data.
+ //The text may be shorter. Its length can be obtained with one of the
+ //above functions and strlen.
+
+ //returns text. Data is allocated with new and must be delete'd by the user.
+ char *getText();
+ //copies text into given buffer.
+ //a buffer of size getLength()+1 is guaranteed to be sufficiently large.
+ //In most descriptors the string length is an 8-bit field,
+ //so the maximum there is 256.
+ //returns the given buffer for convenience.
+ char * getText(char *buffer);
+protected:
+ virtual void Parse() {}
+ void decodeText(char *buffer);
+};
+
+} //end of namespace
+
+#endif //LIBSI_SI_H
diff --git a/libsi/util.c b/libsi/util.c
new file mode 100644
index 0000000..a2a6f0d
--- /dev/null
+++ b/libsi/util.c
@@ -0,0 +1,281 @@
+/***************************************************************************
+ * Copyright (c) 2003 by Marcel Wiesweg, Rolf Hakenes *
+ * *
+ * 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: util.c 1.3 2003/12/22 14:03:03 kls Exp $
+ * *
+ ***************************************************************************/
+
+#include <string.h>
+#include "util.h"
+
+namespace SI {
+
+/*---------------------------- CharArray ----------------------------*/
+
+CharArray::CharArray() : data_(0), off(0) {
+}
+
+CharArray::~CharArray() {
+ if (!data_)
+ return;
+ if (--data_->count_ == 0)
+ delete data_;
+}
+
+CharArray::CharArray(const CharArray &f) : data_(f.data_), off(f.off) {
+ if (data_)
+ ++ data_->count_;
+}
+
+CharArray& CharArray::operator=(const CharArray &f) {
+ // DO NOT CHANGE THE ORDER OF THESE STATEMENTS!
+ // (This order properly handles self-assignment)
+ if (f.data_) {
+ ++ f.data_->count_;
+ }
+ if (data_) {
+ if (--data_->count_ == 0)
+ delete data_;
+ }
+ data_ = f.data_;
+ off = f.off;
+ return *this;
+}
+
+void CharArray::assign(const unsigned char*data, unsigned int size, bool doCopy) {
+ //immutable
+ if (!data_)
+ data_= doCopy ? (Data*)new DataOwnData() : (Data*)new DataForeignData();
+ // This method might need to change things in *data_
+ // Thus it first checks if this is the only pointer to *data_
+ if (data_->count_ > 1) {
+ Data* d = doCopy ? (Data*)new DataOwnData() : (Data*)new DataForeignData();
+ -- data_->count_;
+ data_ = d;
+ }
+ data_->assign(data, size);
+}
+
+bool CharArray::operator==(const char *string) const {
+ //here we can use strcmp, string is null-terminated.
+ if (!data_)
+ return false;
+ return data_->size ? (!strcmp((const char*)data_->data, string)) : string[0]==0;
+}
+
+bool CharArray::operator==(const CharArray &other) const {
+ if (!data_ || !other.data_)
+ return !(data_ || other.data_); //true if both empty
+
+ if (data_->size != other.data_->size)
+ return false;
+
+ //do _not_ use strcmp! Data is not necessarily null-terminated.
+ for (unsigned int i=0;i<data_->size;i++)
+ if (data_->data[i] != other.data_->data[i])
+ return false;
+ return true;
+}
+
+CharArray CharArray::operator+(const unsigned int offset) const {
+ CharArray f(*this);
+ f.off+=offset;
+ return f;
+}
+
+CharArray::Data::Data() : count_(1) {
+ size=0;
+ data=0;
+ /*
+ lockingPid = 0;
+ locked = 0;
+ pthread_mutex_init(&mutex, NULL);
+ */
+}
+
+CharArray::Data::~Data() {
+ /*
+ if (locked)
+ pthread_mutex_unlock(&mutex);
+ pthread_mutex_destroy(&mutex);
+ */
+}
+
+/*CharArray::Data::Data(const Data& d) : count_(1) {
+ size=0;
+ data=0;
+
+ lockingPid = 0;
+ locked = 0;
+ pthread_mutex_init(&mutex, NULL);
+}*/
+
+CharArray::DataOwnData::~DataOwnData() {
+ Delete();
+}
+
+void CharArray::DataOwnData::assign(const unsigned char*d, unsigned int s) {
+ Delete();
+ size=s;
+ unsigned char *newdata=new unsigned char[size];
+ memcpy(newdata, d, size);
+ data=newdata;
+}
+
+void CharArray::DataOwnData::Delete() {
+ delete[] data;
+}
+
+CharArray::DataForeignData::~DataForeignData() {
+ Delete();
+}
+
+void CharArray::DataForeignData::assign(const unsigned char*d, unsigned int s) {
+ size=s;
+ data=d;
+}
+
+void CharArray::DataForeignData::Delete() {
+ //do not delete!
+}
+
+/*
+void CharArray::Data::assign(unsigned int s) {
+ if (data)
+ delete[] data;
+ size=s;
+ if (size) { //new assignment may be zero length
+ data=new unsigned char[size];
+ memset(data, 0, size);
+ }
+}
+
+void CharArray::Data::Lock(void)
+{
+ if ( !pthread_equal(pthread_self(), lockingPid) || !locked) {
+ pthread_mutex_lock(&mutex);
+ lockingPid = pthread_self();
+ }
+ locked++;
+}
+
+void CharArray::Data::Unlock(void)
+{
+ if (!--locked) {
+ lockingPid = 0;
+ pthread_mutex_unlock(&mutex);
+ }
+}
+*/
+
+Parsable::Parsable() {
+ parsed=false;
+}
+
+void Parsable::CheckParse() {
+ if (!parsed) {
+ parsed=true;
+ Parse();
+ }
+}
+
+//taken and adapted from libdtv, (c) Rolf Hakenes and VDR, (c) Klaus Schmidinger
+time_t DVBTime::getTime(unsigned char date_hi, unsigned char date_lo, unsigned char time_hour, unsigned char time_minute, unsigned char time_second) {
+ u_int16_t mjd = date_hi << 8 | date_lo;
+ struct tm t;
+
+ t.tm_sec = bcdToDec(time_second);
+ t.tm_min = bcdToDec(time_minute);
+ t.tm_hour = bcdToDec(time_hour);
+
+ int k;
+ t.tm_year = (int) ((mjd - 15078.2) / 365.25);
+ t.tm_mon = (int) ((mjd - 14956.1 - (int)(t.tm_year * 365.25)) / 30.6001);
+ t.tm_mday = (int) (mjd - 14956 - (int)(t.tm_year * 365.25) - (int)(t.tm_mon * 30.6001));
+ k = (t.tm_mon == 14 || t.tm_mon == 15) ? 1 : 0;
+ t.tm_year = t.tm_year + k;
+ t.tm_mon = t.tm_mon - 1 - k * 12;
+ t.tm_mon--;
+
+ t.tm_isdst = -1;
+ t.tm_gmtoff = 0;
+
+ return timegm(&t);
+}
+
+time_t DVBTime::getDuration(unsigned char time_hour, unsigned char time_minute, unsigned char time_second) {
+ return
+ bcdToDec(time_second)
+ + bcdToDec(time_minute) * 60
+ + bcdToDec(time_hour) *3600;
+}
+
+//taken and adapted from libdtv, (c) Rolf Hakenes
+// CRC32 lookup table for polynomial 0x04c11db7
+u_int32_t CRC32::crc_table[256] = {
+ 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
+ 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
+ 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7,
+ 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
+ 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3,
+ 0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
+ 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef,
+ 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
+ 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb,
+ 0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
+ 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
+ 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
+ 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4,
+ 0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
+ 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08,
+ 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
+ 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc,
+ 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
+ 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050,
+ 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
+ 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
+ 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
+ 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1,
+ 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
+ 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5,
+ 0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
+ 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9,
+ 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
+ 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd,
+ 0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
+ 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
+ 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
+ 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2,
+ 0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
+ 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e,
+ 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
+ 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a,
+ 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
+ 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676,
+ 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
+ 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
+ 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
+ 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4};
+
+u_int32_t CRC32::crc32 (const char *d, int len, u_int32_t crc)
+{
+ register int i;
+
+ for (i=0; i<len; i++)
+ crc = (crc << 8) ^ crc_table[((crc >> 24) ^ *d++) & 0xff];
+
+ return crc;
+}
+
+CRC32::CRC32(const char *d, int len, u_int32_t CRCvalue) {
+ data=d;
+ length=len;
+ value=CRCvalue;
+}
+
+} //end of namespace
diff --git a/libsi/util.h b/libsi/util.h
new file mode 100644
index 0000000..db01923
--- /dev/null
+++ b/libsi/util.h
@@ -0,0 +1,157 @@
+/***************************************************************************
+ * 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: util.h 1.3 2003/12/22 14:07:41 kls Exp $
+ * *
+ ***************************************************************************/
+
+#ifndef LIBSI_UTIL_H
+#define LIBSI_UTIL_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <pthread.h>
+#include <time.h>
+
+#define HILO(x) (x##_hi << 8 | x##_lo)
+#define BCD_TIME_TO_SECONDS(x) ((3600 * ((10*((x##_h & 0xF0)>>4)) + (x##_h & 0xF))) + \
+ (60 * ((10*((x##_m & 0xF0)>>4)) + (x##_m & 0xF))) + \
+ ((10*((x##_s & 0xF0)>>4)) + (x##_s & 0xF)))
+
+namespace SI {
+
+//Holds an array of unsigned char which is deleted
+//when the last object pointing to it is deleted.
+//Optimized for use in libsi.
+class CharArray {
+public:
+ CharArray();
+
+ CharArray(const CharArray &source);
+ CharArray& operator=(const CharArray &source);
+ ~CharArray();
+
+ //can be called exactly once
+ void assign(const unsigned char*data, unsigned int size, bool doCopy=true);
+ //compares to a null-terminated string
+ bool operator==(const char *string) const;
+ //compares to another CharArray (data not necessarily null-terminated)
+ bool operator==(const CharArray &other) const;
+
+ //returns another CharArray with its offset incremented by offset
+ CharArray operator+(const unsigned int offset) const;
+
+ //access and convenience methods
+ const unsigned char* getData() const { return data_->data+off; }
+ const unsigned char* getData(int offset) const { return data_->data+offset+off; }
+ template <typename T> const T* getData() const { return (T*)(data_->data+off); }
+ template <typename T> const T* getData(int offset) const { return (T*)(data_->data+offset+off); }
+ //sets p to point to data+offset, increments offset
+ template <typename T> void setPointerAndOffset(const T* &p, unsigned int &offset) const { p=(T*)getData(offset); offset+=sizeof(T); }
+ unsigned char operator[](const unsigned int index) const { return data_->data ? data_->data[off+index] : 0; }
+ int getLength() const { return data_->size; }
+ u_int16_t TwoBytes(const unsigned int index) const { return data_->data ? data_->TwoBytes(off+index) : 0; }
+ u_int32_t FourBytes(const unsigned int index) const { return data_->data ? data_->FourBytes(off+index) : 0; }
+
+ void addOffset(unsigned int offset) { off+=offset; }
+private:
+ class Data {
+ public:
+ Data();
+ virtual ~Data();
+
+ virtual void assign(const unsigned char*data, unsigned int size) = 0;
+ virtual void Delete() = 0;
+
+ u_int16_t TwoBytes(const unsigned int index) const
+ { return (data[index] << 8) | data[index+1]; }
+ u_int32_t FourBytes(const unsigned int index) const
+ { return (data[index] << 24) | (data[index+1] << 16) | (data[index+2] << 8) | data[index+3]; }
+ /*#ifdef CHARARRAY_THREADSAFE
+ void Lock();
+ void Unlock();
+ #else
+ void Lock() {}
+ void Unlock() {}
+ #endif
+ Data(const Data& d);
+ void assign(unsigned int size);
+ */
+
+ const unsigned char*data;
+ unsigned int size;
+
+ unsigned count_;
+ // count_ is the number of CharArray objects that point at this
+ // count_ must be initialized to 1 by all constructors
+ // (it starts as 1 since it is pointed to by the CharArray object that created it)
+
+ /*
+ pthread_mutex_t mutex;
+ pid_t lockingPid;
+ pthread_t locked;
+ */
+ };
+ class DataOwnData : public Data {
+ public:
+ DataOwnData() {}
+ virtual ~DataOwnData();
+ virtual void assign(const unsigned char*data, unsigned int size);
+ virtual void Delete();
+ };
+ class DataForeignData : public Data {
+ public:
+ DataForeignData() {}
+ virtual ~DataForeignData();
+ virtual void assign(const unsigned char*data, unsigned int size);
+ virtual void Delete();
+ };
+ Data* data_;
+ unsigned int off;
+};
+
+
+
+//abstract base class
+class Parsable {
+public:
+ void CheckParse();
+protected:
+ Parsable();
+ virtual ~Parsable() {}
+ //actually parses given data.
+ virtual void Parse() = 0;
+private:
+ bool parsed;
+};
+
+//taken and adapted from libdtv, (c) Rolf Hakenes and VDR, (c) Klaus Schmidinger
+namespace DVBTime {
+time_t getTime(unsigned char date_hi, unsigned char date_lo, unsigned char timehr, unsigned char timemi, unsigned char timese);
+time_t getDuration(unsigned char timehr, unsigned char timemi, unsigned char timese);
+inline unsigned char bcdToDec(unsigned char b) { return ((b >> 4) & 0x0F) * 10 + (b & 0x0F); }
+};
+
+//taken and adapted from libdtv, (c) Rolf Hakenes
+class CRC32 {
+public:
+ CRC32(const char *d, int len, u_int32_t CRCvalue=0xFFFFFFFF);
+ bool isValid() { return crc32(data, length, value) == 0; }
+ static bool isValid(const char *d, int len, u_int32_t CRCvalue=0xFFFFFFFF) { return crc32(d, len, CRCvalue) == 0; }
+protected:
+ static u_int32_t crc_table[256];
+ static u_int32_t crc32 (const char *d, int len, u_int32_t CRCvalue);
+
+ const char *data;
+ int length;
+ u_int32_t value;
+};
+
+} //end of namespace
+
+#endif