Added 'libsi'

This commit is contained in:
Klaus Schmidinger 2003-11-22 17:56:45 +01:00
parent b8034ba390
commit 161927f9fc
11 changed files with 5066 additions and 0 deletions

57
libsi/Makefile Normal file
View File

@ -0,0 +1,57 @@
#
# Makefile for a Video Disk Recorder plugin
#
# $Id: Makefile 1.1 2003/11/22 17:56:12 kls Exp $
VDRDIR = ../../../..
### The C++ compiler and options:
CXX ?= g++
CXXFLAGS ?= -O2 -g -Wall -Woverloaded-virtual
AR = ar
ARFLAGS = ru
RANLIB = ranlib
### The directory environment:
INCLUDES += -I$(VDRDIR)/include -I..
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)
# $(CXX) $(CXXFLAGS) -shared $(OBJS) $(LIBS) -o $@
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

742
libsi/descriptor.c Normal file
View File

@ -0,0 +1,742 @@
/***************************************************************************
* 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. *
* *
***************************************************************************/
#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

492
libsi/descriptor.h Normal file
View File

@ -0,0 +1,492 @@
/***************************************************************************
* 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. *
* *
***************************************************************************/
#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

82
libsi/gendescr.pl Executable file
View File

@ -0,0 +1,82 @@
#!/usr/bin/perl
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;
}

1802
libsi/headers.h Normal file

File diff suppressed because it is too large Load Diff

346
libsi/section.c Normal file
View File

@ -0,0 +1,346 @@
/***************************************************************************
* 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. *
* *
***************************************************************************/
#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

259
libsi/section.h Normal file
View File

@ -0,0 +1,259 @@
/***************************************************************************
* 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. *
* *
***************************************************************************/
#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

431
libsi/si.c Normal file
View File

@ -0,0 +1,431 @@
/***************************************************************************
* 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. *
* *
***************************************************************************/
#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++;
}
*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

405
libsi/si.h Normal file
View File

@ -0,0 +1,405 @@
/***************************************************************************
* 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. *
* *
***************************************************************************/
#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;
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 (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() const { 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

290
libsi/util.c Normal file
View File

@ -0,0 +1,290 @@
/***************************************************************************
* 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. *
* *
***************************************************************************/
#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) {
unsigned short 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
unsigned long 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};
unsigned long CRC32::crc32 (const char *d, int len, unsigned long 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, unsigned long CRCvalue) {
data=d;
length=len;
value=CRCvalue;
}
} //end of namespace

160
libsi/util.h Normal file
View File

@ -0,0 +1,160 @@
/***************************************************************************
* 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. *
* *
***************************************************************************/
#ifndef LIBSI_UTIL_H
#define LIBSI_UTIL_H
#include <stdint.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; }
unsigned short TwoBytes(const unsigned int index) const { return data_->data ? data_->TwoBytes(off+index) : 0; }
unsigned long 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;
unsigned short TwoBytes(const unsigned int index) const
{ return (data[index] << 8) | data[index+1]; }
unsigned long 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, unsigned long CRCvalue=0xFFFFFFFF);
bool isValid() { return crc32(data, length, value) == 0; }
static bool isValid(const char *d, int len, unsigned long CRCvalue=0xFFFFFFFF) { return crc32(d, len, CRCvalue) == 0; }
protected:
static unsigned long crc_table[256];
static unsigned long crc32 (const char *d, int len, unsigned long CRCvalue);
const char *data;
int length;
unsigned long value;
};
} //end of namespace
#endif