mirror of
https://github.com/VDR4Arch/vdr.git
synced 2023-10-10 13:36:52 +02:00
Added 'libsi'
This commit is contained in:
parent
b8034ba390
commit
161927f9fc
57
libsi/Makefile
Normal file
57
libsi/Makefile
Normal 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
742
libsi/descriptor.c
Normal 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
492
libsi/descriptor.h
Normal 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
82
libsi/gendescr.pl
Executable 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
1802
libsi/headers.h
Normal file
File diff suppressed because it is too large
Load Diff
346
libsi/section.c
Normal file
346
libsi/section.c
Normal 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
259
libsi/section.h
Normal 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
431
libsi/si.c
Normal 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
405
libsi/si.h
Normal 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
290
libsi/util.c
Normal 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
160
libsi/util.h
Normal 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
|
||||||
|
|
Loading…
Reference in New Issue
Block a user