diff --git a/CONTRIBUTORS b/CONTRIBUTORS index f2c3a7ed..7a872990 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -166,6 +166,7 @@ Stefan Huelswitt for reporting a problem with timers when channel IDs have a 'source' that is 0 for reporting a new/delete malloc/free mismatch in ringbuffer.c for reporting a crash in case the index file can't be accessed any more during replay + for adapting VDR to 'libdtv' version 0.0.5 Ulrich Röder for pointing out that there are channels that have a symbol rate higher than diff --git a/HISTORY b/HISTORY index 0071d33f..f8b63a68 100644 --- a/HISTORY +++ b/HISTORY @@ -2020,3 +2020,5 @@ Video Disk Recorder Revision History - Implemented a "resume ID" which allows several users to each have their own resume.vdr files (thanks to Martin Hammerschmid). This parameter can be set in the "Setup/Replay" menu (see MANUAL for details). +- Now using 'libdtv' version 0.0.5 (thanks to Rolf Hakenes for the new version + and Stefan Huelswitt for adapting VDR to it). diff --git a/eit.c b/eit.c index 42740852..ff5dd42f 100644 --- a/eit.c +++ b/eit.c @@ -16,7 +16,7 @@ * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * - * $Id: eit.c 1.67 2003/03/16 11:20:05 kls Exp $ + * $Id: eit.c 1.68 2003/04/12 11:27:31 kls Exp $ ***************************************************************************/ #include "eit.h" @@ -1011,29 +1011,37 @@ private: int length; uchar *data; public: - cCaDescriptor(int Source, int Transponder, int ServiceId, int CaSystem, int Length, uchar *Data); + cCaDescriptor(int Source, int Transponder, int ServiceId, int CaSystem, int CaPid, int Length, uchar *Data); virtual ~cCaDescriptor(); int Length(void) const { return length; } const uchar *Data(void) const { return data; } }; -cCaDescriptor::cCaDescriptor(int Source, int Transponder, int ServiceId, int CaSystem, int Length, uchar *Data) +cCaDescriptor::cCaDescriptor(int Source, int Transponder, int ServiceId, int CaSystem, int CaPid, int Length, uchar *Data) { source = Source; transponder = Transponder; serviceId = ServiceId; caSystem = CaSystem; - length = Length; + length = Length + 6; data = MALLOC(uchar, length); - memcpy(data, Data, length); - /*//XXX just while debugging... + data[0] = DESCR_CA; + data[1] = length - 2; + data[2] = (caSystem >> 8) & 0xFF; + data[3] = caSystem & 0xFF; + data[4] = ((CaPid >> 8) & 0xFF) | 0xE0; + data[5] = CaPid & 0xFF; + if (Length) + memcpy(&data[6], Data, Length); +//#define DEBUG_CA_DESCRIPTORS 1 +#ifdef DEBUG_CA_DESCRIPTORS char buffer[1024]; char *q = buffer; q += sprintf(q, "CAM: %04X %5d %4d", source, transponder, serviceId); for (int i = 0; i < length; i++) q += sprintf(q, " %02X", data[i]); dsyslog(buffer); - *///XXX +#endif } cCaDescriptor::~cCaDescriptor() @@ -1312,16 +1320,13 @@ void cSIProcessor::Action() if (pid == pmtPid && buf[0] == 0x02 && currentSource && currentTransponder) { struct Pid *pi = siParsePMT(buf); if (pi) { - for (struct LIST *d = (struct LIST *)pi->Descriptors; d; d = (struct LIST *)xSucc(d)) { - if (DescriptorTag(d) == DESCR_CA) { - uchar *Data = ((ConditionalAccessDescriptor *)d)->Data; - int CaSystem = (Data[2] << 8) | Data[3]; - if (!caDescriptors->Get(currentSource, currentTransponder, pi->ProgramID, CaSystem)) { - cMutexLock MutexLock(&caDescriptorsMutex); - caDescriptors->Add(new cCaDescriptor(currentSource, currentTransponder, pi->ProgramID, CaSystem, ((ConditionalAccessDescriptor *)d)->Amount, Data)); - } - //XXX update??? - } + struct Descriptor *d; + for (d = (struct Descriptor *)pi->Descriptors->Head; d; d = (struct Descriptor *)xSucc(d)) + NewCaDescriptor(d, pi->ProgramID); + // Also scan the PidInfo list for descriptors - some broadcasts send them only here. + for (struct PidInfo *p = (struct PidInfo *)pi->InfoList->Head; p; p = (struct PidInfo *)xSucc(p)) { + for (d = (struct Descriptor *)p->Descriptors->Head; d; d = (struct Descriptor *)xSucc(d)) + NewCaDescriptor(d, pi->ProgramID); } } xMemFreeAll(NULL); @@ -1438,6 +1443,18 @@ void cSIProcessor::TriggerDump(void) lastDump = 0; } +void cSIProcessor::NewCaDescriptor(struct Descriptor *d, int ProgramID) +{ + if (DescriptorTag(d) == DESCR_CA) { + struct CaDescriptor *cd = (struct CaDescriptor *)d; + if (!caDescriptors->Get(currentSource, currentTransponder, ProgramID, cd->CA_type)) { + cMutexLock MutexLock(&caDescriptorsMutex); + caDescriptors->Add(new cCaDescriptor(currentSource, currentTransponder, ProgramID, cd->CA_type, cd->CA_PID, cd->DataLength, cd->Data)); + } + //XXX update??? + } +} + int cSIProcessor::GetCaDescriptors(int Source, int Transponder, int ServiceId, int BufSize, uchar *Data) { if (BufSize > 0 && Data) { diff --git a/eit.h b/eit.h index 17fa9093..e956b013 100644 --- a/eit.h +++ b/eit.h @@ -16,7 +16,7 @@ * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * - * $Id: eit.h 1.24 2003/02/02 14:07:39 kls Exp $ + * $Id: eit.h 1.25 2003/04/12 10:59:26 kls Exp $ ***************************************************************************/ #ifndef __EIT_H @@ -158,6 +158,7 @@ private: bool AddFilter(unsigned short pid, u_char tid); bool DelFilter(unsigned short pid, u_char tid); bool ShutDownFilters(void); + void NewCaDescriptor(struct Descriptor *d, int ProgramID); public: cSIProcessor(const char *FileName); ~cSIProcessor(); diff --git a/libdtv/libsi/include/libsi.h b/libdtv/libsi/include/libsi.h index 8e9e2605..cd07fc6d 100644 --- a/libdtv/libsi/include/libsi.h +++ b/libdtv/libsi/include/libsi.h @@ -4,11 +4,13 @@ /// /// ////////////////////////////////////////////////////////////// -// $Revision: 1.6 $ -// $Date: 2002/01/30 17:04:13 $ +// $Revision: 1.7 $ +// $Date: 2003/04/12 11:27:31 $ // $Author: hakenes $ // -// (C) 2001 Rolf Hakenes , under the GNU GPL. +// (C) 2001-03 Rolf Hakenes , under the +// GNU GPL with contribution of Oleg Assovski, +// www.satmania.com // // libsi is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -38,9 +40,9 @@ /* Program Identifier */ #define PID_PAT 0x00 /* Program Association Table */ -#define PID_BAT 0x01 /* Bouquet Association Table */ #define PID_CAT 0x01 /* Conditional Access Table */ #define PID_NIT 0x10 /* Network Information Table */ +#define PID_BAT 0x11 /* Bouquet Association Table */ #define PID_SDT 0x11 /* Service Description Table */ #define PID_EIT 0x12 /* Event Information Table */ #define PID_RST 0x13 /* Running Status Table */ @@ -75,12 +77,13 @@ #define TID_TOT 0x73 /* Time Offset Section */ #define TID_CA_ECM_0 0x80 #define TID_CA_ECM_1 0x81 +#define TID_CA_EMM 0x82 -#define TID_BAT 0x01 /* Bouquet Association Section */ +#define TID_BAT 0x4A /* Bouquet Association Section */ #define TID_EIT 0x12 /* Event Information Section */ -#define TID_RST 0x13 /* Running Status Section */ -#define TID_ST 0x14 /* Stuffung Section */ +#define TID_RST 0x71 /* Running Status Section */ +#define TID_ST 0x72 /* Stuffing Section */ /* 0xFF */ /* Reserved for future use */ /* Descriptor Identifier */ @@ -160,6 +163,40 @@ #define MAX_SECTION_BUFFER 4096 +/* NetworkInfo structure (used to store NIT/BAT information) */ + +struct NetworkInfo { + struct NODE Node; + unsigned short ID; // NetworkID / BouquetID + struct LIST *Descriptors; + struct LIST *TransportStreams; +}; + +#define CreateNetworkInfo(ni, id) \ + do { \ + xCreateNode (ni, NULL); \ + (ni)->ID = id; \ + (ni)->Descriptors = xNewList(NULL); \ + (ni)->TransportStreams = NULL; \ + } while(0) + +/* TransportStream structure (NIT/BAT TS loop member) */ + +struct TransportStream { + struct NODE Node; + int TransportStreamID; + unsigned short OriginalNetworkID; + struct LIST *Descriptors; +}; + +#define CreateTransportStream(ts, tsid, onid) \ + do { \ + xCreateNode (ts, NULL); \ + (ts)->TransportStreamID = tsid; \ + (ts)->OriginalNetworkID = onid; \ + (ts)->Descriptors = xNewList(NULL); \ + } while(0) + /* Strukturen zur Aufnahme der SDT und EIT Informationen */ struct Service { @@ -305,6 +342,23 @@ struct PidInfo { #define STREAMTYPE_13818_D 13 #define STREAMTYPE_13818_AUX 14 + +struct Tot { + time_t UTC; + time_t Bias; + struct LIST *Descriptors; +}; + +#define CreateTot(tot, utc) \ + do \ + { \ + xMemAlloc(sizeof(struct Tot), &tot); \ + tot->UTC = utc; \ + tot->Bias = ((utc - time(NULL) + 1800)/3600)*3600; \ + tot->Descriptors = xNewList(NULL); \ + } while (0) + + /* Descriptors */ #define DescriptorTag(x) ((struct Descriptor *)(x))->Tag @@ -315,29 +369,6 @@ struct Descriptor { }; -/* ConditionalAccessDescriptor */ - -struct ConditionalAccessDescriptor { - struct NODE Node; - unsigned short Tag; - unsigned short Amount; /* Data */ - unsigned char *Data; -}; - -#define CreateConditionalAccessDescriptor(descr, amount, data) \ - do \ - { \ - unsigned char *tmpptr; \ - \ - xMemAlloc (amount, &tmpptr); \ - memcpy (tmpptr, data, amount); \ - xCreateNode (((struct ConditionalAccessDescriptor *)descr), NULL); \ - ((struct ConditionalAccessDescriptor *)descr)->Tag = DESCR_CA; \ - ((struct ConditionalAccessDescriptor *)descr)->Amount = amount; \ - ((struct ConditionalAccessDescriptor *)descr)->Data = tmpptr; \ - } while (0) - - /* Iso639LanguageDescriptor */ struct Iso639LanguageDescriptor { @@ -434,19 +465,23 @@ struct AncillaryDataDescriptor { /* BouquetNameDescriptor */ +/* + the same used instead of NetworkNameDescriptor because their structures + are identical. We pass 'tag' parameter to distinguish between them later +*/ struct BouquetNameDescriptor { struct NODE Node; /* Node enthält Namen */ unsigned short Tag; }; -#define CreateBouquetNameDescriptor(descr, text) \ +#define CreateBouquetNameDescriptor(descr, text, tag) \ do \ { \ xCreateNode (((struct BouquetNameDescriptor *)descr), NULL); \ ((struct NODE *)descr)->Name = text; \ ((struct NODE *)descr)->HashKey = xHashKey (text); \ - ((struct BouquetNameDescriptor *)descr)->Tag = DESCR_BOUQUET_NAME; \ + ((struct BouquetNameDescriptor *)descr)->Tag = tag; \ } while (0) @@ -514,6 +549,33 @@ struct CaIdentifierDescriptor { ((struct CaIdentifierDescriptor *)descr)->SystemID[num] = id #define GetCaIdentifierID(descr, num) (((struct CaIdentifierDescriptor *)descr)->SystemID[num]) +/* CaDescriptor */ + +struct CaDescriptor { + struct NODE Node; + unsigned short Tag; + unsigned short CA_type; + unsigned short CA_PID; + unsigned int ProviderID; + unsigned short DataLength; + unsigned char *Data; +}; + +#define CreateCaDescriptor(descr, typ, capid, len) \ + do \ + { \ + xCreateNode (((struct CaDescriptor *)descr), NULL); \ + ((struct CaDescriptor *)descr)->Tag = DESCR_CA; \ + ((struct CaDescriptor *)descr)->CA_type = typ; \ + ((struct CaDescriptor *)descr)->CA_PID = capid; \ + ((struct CaDescriptor *)descr)->ProviderID = 0; \ + ((struct CaDescriptor *)descr)->DataLength = len; \ + xMemAlloc (len+1, &((struct CaDescriptor *)descr)->Data); \ + } while (0) + +#define SetCaData(descr, num, id) \ + ((struct CaDescriptor *)descr)->Data[num] = id +#define GetCaData(descr, num) (((struct CaDescriptor *)descr)->Data[num]) /* StreamIdentifierDescriptor */ @@ -968,6 +1030,122 @@ struct SubtitlingItem { xAddTail (((struct SubtitlingDescriptor *)desc)->Items, item); \ } while (0) +/* SatelliteDeliverySystemDescriptor */ + +struct SatelliteDeliverySystemDescriptor { + struct NODE Node; + unsigned short Tag; + long Frequency; + short OrbitalPosition; + char Polarization; + long SymbolRate; + char FEC; +}; + +#define CreateSatelliteDeliverySystemDescriptor(descr, freq, orb, polar, sr, fec) \ + do \ + { \ + xCreateNode (((struct SatelliteDeliverySystemDescriptor *)descr), NULL); \ + ((struct SatelliteDeliverySystemDescriptor *)descr)->Tag = DESCR_SAT_DEL_SYS; \ + ((struct SatelliteDeliverySystemDescriptor *)descr)->Frequency = freq; \ + ((struct SatelliteDeliverySystemDescriptor *)descr)->OrbitalPosition = orb; \ + ((struct SatelliteDeliverySystemDescriptor *)descr)->Polarization = polar; \ + ((struct SatelliteDeliverySystemDescriptor *)descr)->SymbolRate = sr; \ + ((struct SatelliteDeliverySystemDescriptor *)descr)->FEC = fec; \ + } while (0) + +/* ServiceListDescriptor */ + +struct ServiceListDescriptor { + struct NODE Node; + unsigned short Tag; + struct LIST *ServiceList; +}; + +#define CreateServiceListDescriptor(descr) \ + do \ + { \ + xCreateNode (((struct ServiceListDescriptor *)descr), NULL); \ + ((struct ServiceListDescriptor *)descr)->Tag = DESCR_SERVICE_LIST; \ + ((struct ServiceListDescriptor *)descr)->ServiceList = xNewList(NULL); \ + } while (0) + +struct ServiceListEntry { + struct NODE Node; + int ServiceID; + unsigned short ServiceType; +}; + +#define AddServiceListEntry(descr, id, typ) \ + do \ + { \ + struct ServiceListEntry *newent; \ + \ + xCreateNode (newent, NULL); \ + newent->ServiceID = id; \ + newent->ServiceType = typ; \ + xAddTail (((struct ServiceListDescriptor *)descr)->ServiceList, newent); \ + } while (0) + +/* LocalTimeOffsetDescriptor */ + +struct LocalTimeOffsetDescriptor { + struct NODE Node; + unsigned short Tag; + struct LIST *LocalTimeOffsets; +}; + +#define CreateLocalTimeOffsetDescriptor(descr) \ + do \ + { \ + xCreateNode (((struct LocalTimeOffsetDescriptor *)descr), NULL); \ + ((struct LocalTimeOffsetDescriptor *)descr)->Tag = DESCR_LOCAL_TIME_OFF; \ + ((struct LocalTimeOffsetDescriptor *)descr)->LocalTimeOffsets = xNewList(NULL); \ + } while (0) + +struct LocalTimeOffsetEntry { + struct NODE Node; + char CountryCode[4]; + char RegionID; + time_t CurrentOffset; + time_t ChangeTime; + time_t NextOffset; +}; + +#define CreateLocalTimeOffsetEntry(newent, code1, code2, code3, reg, co, ct, no) \ + do \ + { \ + xCreateNode (newent, NULL); \ + newent->CountryCode[0] = code1; \ + newent->CountryCode[1] = code2; \ + newent->CountryCode[2] = code3; \ + newent->CountryCode[3] = '\0'; \ + newent->RegionID = reg; \ + newent->CurrentOffset = co; \ + newent->ChangeTime = ct; \ + newent->NextOffset = no; \ + } while (0) + +#define AddLocalTimeOffsetEntry(descr, code1, code2, code3, reg, co, ct, no) \ + do \ + { \ + struct LocalTimeOffsetEntry *newent; \ + \ + xCreateNode (newent, NULL); \ + newent->CountryCode[0] = code1; \ + newent->CountryCode[1] = code2; \ + newent->CountryCode[2] = code3; \ + newent->CountryCode[3] = '\0'; \ + newent->RegionID = reg; \ + newent->CurrentOffset = co; \ + newent->ChangeTime = ct; \ + newent->NextOffset = no; \ + xAddTail (((struct LocalTimeOffsetDescriptor *)descr)->LocalTimeOffsets, newent); \ + } while (0) + +#define timezonecmp(ptoe,cod,reg) \ + (strncmp(ptoe->CountryCode, cod, 3) || (ptoe->RegionID != reg)) + /* Prototypes */ @@ -979,13 +1157,17 @@ extern "C" { /* si_parser.c */ struct LIST *siParsePAT (u_char *); +struct LIST *siParseCAT (u_char *); struct Pid *siParsePMT (u_char *); struct LIST *siParseSDT (u_char *); +struct LIST *siParseNIT (u_char *); struct LIST *siParseEIT (u_char *); time_t siParseTDT (u_char *); +struct Tot *siParseTOT (u_char *); void siParseDescriptors (struct LIST *, u_char *, int, u_char); void siParseDescriptor (struct LIST *, u_char *); char *siGetDescriptorText (u_char *, int); +char *siGetDescriptorName (u_char *, int); u_long crc32 (char *data, int len); /* si_debug_services.c */ @@ -999,6 +1181,8 @@ void siDebugPids (char *, struct LIST *); void siDebugDescriptors (char *, struct LIST *); void siDebugEitServices (struct LIST *); void siDebugEitEvents (char *, struct LIST *); +void siDumpDescriptor (void *); +void siDumpSection (void *); #ifdef __cplusplus } diff --git a/libdtv/libsi/include/si_tables.h b/libdtv/libsi/include/si_tables.h index dfda3bf9..9da31a0f 100644 --- a/libdtv/libsi/include/si_tables.h +++ b/libdtv/libsi/include/si_tables.h @@ -5,11 +5,13 @@ /// /// ////////////////////////////////////////////////////////////// -// $Revision: 1.3 $ -// $Date: 2001/10/07 10:24:46 $ +// $Revision: 1.4 $ +// $Date: 2003/04/12 11:27:31 $ // $Author: hakenes $ // -// (C) 2001 Rolf Hakenes , under the GNU GPL. +// (C) 2001-03 Rolf Hakenes , under the +// GNU GPL with contribution of Oleg Assovski, +// www.satmania.com // // libsi is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -32,12 +34,22 @@ #define BcdTimeToSeconds(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))) +#define BcdTimeToMinutes(x) ((60 * ((10*((x##_h & 0xF0)>>4)) + (x##_h & 0xF))) + \ + (((10*((x##_m & 0xF0)>>4)) + (x##_m & 0xF)))) +#define BcdCharToInt(x) (10*((x & 0xF0)>>4) + (x & 0xF)) +#define CheckBcdChar(x) ((((x & 0xF0)>>4) <= 9) && \ + ((x & 0x0F) <= 9)) +#define CheckBcdSignedChar(x) ((((x & 0xF0)>>4) >= 0) && (((x & 0xF0)>>4) <= 9) && \ + ((x & 0x0F) >= 0) && ((x & 0x0F) <= 9)) #define TableHasMoreSections(x) (((pat_t *)(x))->last_section_number > ((pat_t *)(x))->section_number) #define GetTableId(x) ((pat_t *)(x))->table_id #define GetSectionNumber(x) ((pat_t *)(x))->section_number #define GetLastSectionNumber(x) ((pat_t *)(x))->last_section_number #define GetServiceId(x) (((eit_t *)(x))->service_id_hi << 8) | ((eit_t *)(x))->service_id_lo +#define GetSegmentLastSectionNumber(x) ((eit_t *)(x))->segment_last_section_number +#define GetLastTableId(x) ((eit_t *)(x))->segment_last_table_id +#define GetSectionLength(x) HILO(((pat_t *)(x))->section_length) /* * @@ -113,7 +125,37 @@ typedef struct { * applicable. * */ - /* TO BE DONE */ +#define CAT_LEN 8 + +typedef struct { + u_char table_id :8; +#if BYTE_ORDER == BIG_ENDIAN + u_char section_syntax_indicator :1; + u_char dummy :1; // has to be 0 + u_char :2; + u_char section_length_hi :4; +#else + u_char section_length_hi :4; + u_char :2; + u_char dummy :1; // has to be 0 + u_char section_syntax_indicator :1; +#endif + u_char section_length_lo :8; + u_char reserved_1 :8; + u_char reserved_2 :8; +#if BYTE_ORDER == BIG_ENDIAN + u_char :2; + u_char version_number :5; + u_char current_next_indicator :1; +#else + u_char current_next_indicator :1; + u_char version_number :5; + u_char :2; +#endif + u_char section_number :8; + u_char last_section_number :8; +} cat_t; + /* * * 3) Program Map Table (PMT): @@ -297,7 +339,7 @@ typedef struct { * bouquet. * */ - /* TO BE DONE */ +/* SEE NIT (It has the same structure but has different allowed descriptors) */ /* * * 2) Service Description Table (SDT): @@ -339,6 +381,9 @@ typedef struct { u_char :8; } sdt_t; +#define GetSDTTransportStreamId(x) (HILO(((sdt_t *) x)->transport_stream_id)) +#define GetSDTOriginalNetworkId(x) (HILO(((sdt_t *) x)->original_network_id)) + #define SDT_DESCR_LEN 5 typedef struct { @@ -483,7 +528,36 @@ typedef struct { * to the frequent updating of the time information. * */ - /* TO BE DONE */ +#define TOT_LEN 10 + +typedef struct { + u_char table_id :8; +#if BYTE_ORDER == BIG_ENDIAN + u_char section_syntax_indicator :1; + u_char :3; + u_char section_length_hi :4; +#else + u_char section_length_hi :4; + u_char :3; + u_char section_syntax_indicator :1; +#endif + u_char section_length_lo :8; + u_char utc_mjd_hi :8; + u_char utc_mjd_lo :8; + u_char utc_time_h :8; + u_char utc_time_m :8; + u_char utc_time_s :8; +#if BYTE_ORDER == BIG_ENDIAN + u_char :4; + u_char descriptors_loop_length_hi :4; +#else + u_char descriptors_loop_length_hi :4; + u_char :4; +#endif + u_char descriptors_loop_length_lo :8; +} tot_t; + + /* * * 7) Stuffing Table (ST): @@ -545,6 +619,25 @@ typedef struct descr_gen_struct { #define GetDescriptorLength(x) (((descr_gen_t *) x)->descriptor_length+DESCR_GEN_LEN) +/* 0x09 ca_descriptor */ + +#define DESCR_CA_LEN 6 +typedef struct descr_ca_struct { + u_char descriptor_tag :8; + u_char descriptor_length :8; + u_char CA_type_hi :8; + u_char CA_type_lo :8; +#if BYTE_ORDER == BIG_ENDIAN + u_char reserved :3; + u_char CA_PID_hi :5; +#else + u_char CA_PID_hi :5; + u_char reserved :3; +#endif + u_char CA_PID_lo :8; +} descr_ca_t; +#define CastCaDescriptor(x) ((descr_ca_t *)(x)) + /* 0x0A iso_639_language_descriptor */ #define DESCR_ISO_639_LANGUAGE_LEN 5 @@ -560,25 +653,31 @@ typedef struct descr_iso_639_language_struct { /* 0x40 network_name_descriptor */ -#define DESCR_NETWORK_NAME_LEN XX +#define DESCR_NETWORK_NAME_LEN 2 typedef struct descr_network_name_struct { u_char descriptor_tag :8; u_char descriptor_length :8; - /* TBD */ } descr_network_name_t; #define CastNetworkNameDescriptor(x) ((descr_network_name_t *)(x)) /* 0x41 service_list_descriptor */ -#define DESCR_SERVICE_LIST_LEN XX +#define DESCR_SERVICE_LIST_LEN 2 typedef struct descr_service_list_struct { u_char descriptor_tag :8; u_char descriptor_length :8; - /* TBD */ } descr_service_list_t; #define CastServiceListDescriptor(x) ((descr_service_list_t *)(x)) +#define DESCR_SERVICE_LIST_LOOP_LEN 3 +typedef struct descr_service_list_loop_struct { + u_char service_id_hi :8; + u_char service_id_lo :8; + u_char service_type :8; +} descr_service_list_loop_t; +#define CastServiceListDescriptorLoop(x) ((descr_service_list_loop_t *)(x)) + /* 0x42 stuffing_descriptor */ @@ -604,13 +703,13 @@ typedef struct descr_satellite_delivery_system_struct { u_char orbital_position1 :8; u_char orbital_position2 :8; #if BYTE_ORDER == BIG_ENDIAN - u_char modulation :5; - u_char polarization :2; u_char west_east_flag :1; + u_char polarization :2; + u_char modulation :5; #else - u_char west_east_flag :1; - u_char polarization :2; u_char modulation :5; + u_char polarization :2; + u_char west_east_flag :1; #endif u_char symbol_rate1 :8; u_char symbol_rate2 :8; @@ -964,14 +1063,39 @@ typedef struct descr_telephone_struct { /* 0x58 local_time_offset_descriptor */ -#define DESCR_LOCAL_TIME_OFFSET_LEN XX +#define DESCR_LOCAL_TIME_OFFSET_LEN 2 typedef struct descr_local_time_offset_struct { u_char descriptor_tag :8; u_char descriptor_length :8; - /* TBD */ } descr_local_time_offset_t; #define CastLocalTimeOffsetDescriptor(x) ((descr_local_time_offset_t *)(x)) +#define LOCAL_TIME_OFFSET_ENTRY_LEN 15 +typedef struct local_time_offset_entry_struct { + u_char country_code1 :8; + u_char country_code2 :8; + u_char country_code3 :8; +#if BYTE_ORDER == BIG_ENDIAN + u_char country_region_id :6; + u_char :1; + u_char local_time_offset_polarity :1; +#else + u_char local_time_offset_polarity :1; + u_char :1; + u_char country_region_id :6; +#endif + u_char local_time_offset_h :8; + u_char local_time_offset_m :8; + u_char time_of_change_mjd_hi :8; + u_char time_of_change_mjd_lo :8; + u_char time_of_change_time_h :8; + u_char time_of_change_time_m :8; + u_char time_of_change_time_s :8; + u_char next_time_offset_h :8; + u_char next_time_offset_m :8; +} local_time_offset_entry_t ; +#define CastLocalTimeOffsetEntry(x) ((local_time_offset_entry_t *)(x)) + /* 0x59 subtitling_descriptor */ diff --git a/libdtv/libsi/si_debug_services.c b/libdtv/libsi/si_debug_services.c index ae2a92a6..ac8de34c 100644 --- a/libdtv/libsi/si_debug_services.c +++ b/libdtv/libsi/si_debug_services.c @@ -4,11 +4,13 @@ /// /// ////////////////////////////////////////////////////////////// -// $Revision: 1.4 $ -// $Date: 2001/10/07 10:24:46 $ +// $Revision: 1.5 $ +// $Date: 2003/02/04 18:45:35 $ // $Author: hakenes $ // -// (C) 2001 Rolf Hakenes , under the GNU GPL. +// (C) 2001-03 Rolf Hakenes , under the +// GNU GPL with contribution of Oleg Assovski, +// www.satmania.com // // libsi is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -26,11 +28,13 @@ // Boston, MA 02111-1307, USA. #include +#include #include #include #include "../liblx/liblx.h" #include "libsi.h" +#include "si_tables.h" #include "si_debug_services.h" @@ -208,6 +212,8 @@ void siDebugPids (char *Prepend, struct LIST *PidList) printf ("%s ProgramID: %d\n", Prepend, Pid->ProgramID); printf ("%s PcrPid: %d\n", Prepend, Pid->PcrPID); printf ("%s PmtVersion: %d\n", Prepend, Pid->PmtVersion); + sprintf (NewPrepend, "%s ", Prepend); + siDebugDescriptors (NewPrepend, Pid->Descriptors); xForeach (Pid->InfoList, PidInfo) { @@ -256,6 +262,11 @@ void siDebugDescriptors (char *Prepend, struct LIST *Descriptors) printf ("\n"); break; + case DESCR_NW_NAME: + printf ("%sDescriptor: Network Name\n", Prepend); + printf ("%s Name: %s\n", Prepend, xName (Descriptor)); + break; + case DESCR_BOUQUET_NAME: printf ("%sDescriptor: Bouquet Name\n", Prepend); printf ("%s Name: %s\n", Prepend, xName (Descriptor)); @@ -336,12 +347,38 @@ void siDebugDescriptors (char *Prepend, struct LIST *Descriptors) case DESCR_CA_IDENT: printf ("%sDescriptor: Conditional Access Identity\n", Prepend); { - int j; + int j,k; for (j = 0; j < ((struct CaIdentifierDescriptor *)Descriptor)->Amount; j++) - printf ("%s SystemID: 0x%04x\n", Prepend, GetCaIdentifierID (Descriptor, j)); + { + printf ("%s SystemID: 0x%04x", Prepend, GetCaIdentifierID (Descriptor, j)); + k = GetCaIdentifierID (Descriptor, j) >> 8; + if (k < 0 || k > MAX_CA_IDENT) printf (" (unknown)\n"); + else printf (" (%s)\n", CaIdents[k]); + } } break; + case DESCR_CA: + { + int j,k; + + printf ("%sDescriptor: Conditional Access\n", Prepend); + printf ("%s CA type: 0x%04x", Prepend, (((struct CaDescriptor *)Descriptor)->CA_type)); + k = (((struct CaDescriptor *)Descriptor)->CA_type) >> 8; + if (k < 0 || k > MAX_CA_IDENT) printf (" (unknown)\n"); + else printf (" (%s)\n", CaIdents[k]); + printf ("%s CA PID: %d\n", Prepend, (((struct CaDescriptor *)Descriptor)->CA_PID)); + printf ("%s ProviderID: 0x%04X\n", Prepend, (((struct CaDescriptor *)Descriptor)->ProviderID)); + if (((struct CaDescriptor *)Descriptor)->DataLength > 0) + { + printf ("%s CA data:", Prepend); + for (j = 0; j < ((struct CaDescriptor *)Descriptor)->DataLength; j++) + printf (" 0x%02x", GetCaData (Descriptor, j)); + printf ("\n"); + } + } + break; + case DESCR_CONTENT: printf ("%sDescriptor: Content\n", Prepend); { @@ -489,16 +526,57 @@ void siDebugDescriptors (char *Prepend, struct LIST *Descriptors) } break; - case DESCR_NW_NAME: - case DESCR_SERVICE_LIST: - case DESCR_STUFFING: case DESCR_SAT_DEL_SYS: + { + struct SatelliteDeliverySystemDescriptor *sds = + (struct SatelliteDeliverySystemDescriptor *)Descriptor; + + printf ("%sDescriptor: Satellite Delivery System\n", Prepend); + printf ("%s Frequency: %ld\n", Prepend, sds->Frequency); + printf ("%s OrbitalPosition: %d\n", Prepend, sds->OrbitalPosition); + printf ("%s Polarization: %c\n", Prepend, sds->Polarization); + printf ("%s SymbolRate: %ld\n", Prepend, sds->SymbolRate); + printf ("%s FEC: %c\n", Prepend, sds->FEC); + } + break; + + case DESCR_SERVICE_LIST: + { + struct ServiceListEntry *Entry; + + printf ("%sDescriptor: Service List\n", Prepend); + xForeach (((struct ServiceListDescriptor *)Descriptor)->ServiceList, Entry) + { + printf ("%s Entry:\n"); + printf ("%s ServiceID: %d\n", Prepend, Entry->ServiceID); + printf ("%s ServiceType: %04x\n", Prepend, Entry->ServiceType); + } + } + break; + + case DESCR_LOCAL_TIME_OFF: + { + struct LocalTimeOffsetEntry *Offset; + + printf ("%sDescriptor: Local Time Offset\n", Prepend); + xForeach (((struct LocalTimeOffsetDescriptor *)Descriptor)->LocalTimeOffsets, Offset) + { + printf ("%s Offset:\n"); + printf ("%s CountryCode: %s\n", Offset->CountryCode); + printf ("%s RegionID: %c\n", Offset->RegionID); + printf ("%s CurrentOffset: %ld\n", Offset->CurrentOffset); + printf ("%s ChangeTime: %ld\n", Offset->ChangeTime); + printf ("%s NextOffset: %ld\n", Offset->NextOffset); + } + } + break; + + case DESCR_STUFFING: case DESCR_CABLE_DEL_SYS: case DESCR_VBI_DATA: case DESCR_VBI_TELETEXT: case DESCR_MOSAIC: case DESCR_TELEPHONE: - case DESCR_LOCAL_TIME_OFF: case DESCR_TERR_DEL_SYS: case DESCR_ML_NW_NAME: case DESCR_ML_BQ_NAME: @@ -527,3 +605,39 @@ void siDebugDescriptors (char *Prepend, struct LIST *Descriptors) return; } +void siDumpDescriptor (void * Descriptor) +{ + int Length, i; + unsigned char *ptr; + + Length = GetDescriptorLength (Descriptor); + for (i = 0, ptr = (char*) Descriptor; i < Length; i++) { + if ((i % 8) == 0) + printf ("\n"); + printf ("0x%02X ", (unsigned int) ptr[i]); + } + printf ( "\n"); +} + +void siDumpSection (void *Section) +{ + int Length, i; + unsigned char *ptr; + char str[9]; + + Length = GetSectionLength (Section) + 3; + for (i = 0, ptr = (unsigned char*) Section, memset (str, 0, 9); i < Length; i++) { + if ((i % 8) == 0) + { + printf (" %s\n", str); + memset (str, 0, 8); + } + printf ("0x%02X ", (unsigned int) ptr[i]); + if (ptr[i] < 0x20 || (ptr[i] > 'z' && ptr[i] < ((unsigned char )'Ā')) ) + str[i % 8] = '.'; + else + str[i % 8] = ptr[i]; + } + printf (" %*s\n", (8 - ((abs(i - 1) % 8) ? (abs(i - 1) % 8) : 8)) * 5, str); +} + diff --git a/libdtv/libsi/si_debug_services.h b/libdtv/libsi/si_debug_services.h index d33b0aa7..869c6d04 100644 --- a/libdtv/libsi/si_debug_services.h +++ b/libdtv/libsi/si_debug_services.h @@ -4,8 +4,8 @@ /// /// ////////////////////////////////////////////////////////////// -// $Revision: 1.1 $ -// $Date: 2001/08/15 10:00:00 $ +// $Revision: 1.2 $ +// $Date: 2003/04/12 11:27:31 $ // $Author: hakenes $ // // (C) 2001 Rolf Hakenes , under the GNU GPL. @@ -197,7 +197,7 @@ static struct content_type ContentTypes[] = { }; #define CONTENT_TYPE_NUMBER 79 -static char StreamTypes[][70] = { +static char *StreamTypes[] = { "ITU-T|ISO/IEC Reserved", "ISO/IEC Video", "13818-2 Video or 11172-2 constrained parameter video stream", @@ -215,3 +215,31 @@ static char StreamTypes[][70] = { "ITU-T Rec. H.222.0 | ISO 13818-1 Reserved", "User private" }; + +static char *CaIdents[] = { + "Standardized systems", + "Canal Plus", + "CCETT", + "Deutsche Telecom", + "Eurodec", + "France Telecom", + "Irdeto", + "Jerrold/GI", + "Matra Communication", + "News Datacom", + "Nokia", + "Norwegian Telekom", + "NTL", + "Philips", + "Scientific Atlanta", + "Sony", + "Tandberg Television", + "Thomson", + "TV/Com", + "HPT - Croatian Post and Telecommunications", + "HRT - Croatian Radio and Television", + "IBM", + "Nera", + "BetaTechnik" +}; +#define MAX_CA_IDENT 24 diff --git a/libdtv/libsi/si_parser.c b/libdtv/libsi/si_parser.c index ccca6e5e..e8cf8b21 100644 --- a/libdtv/libsi/si_parser.c +++ b/libdtv/libsi/si_parser.c @@ -4,11 +4,13 @@ /// /// ////////////////////////////////////////////////////////////// -// $Revision: 1.6 $ -// $Date: 2002/01/30 17:04:13 $ +// $Revision: 1.8 $ +// $Date: 2003/02/04 18:45:35 $ // $Author: hakenes $ // -// (C) 2001 Rolf Hakenes , under the GNU GPL. +// (C) 2001-03 Rolf Hakenes , under the +// GNU GPL with contribution of Oleg Assovski, +// www.satmania.com // // libsi is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -52,7 +54,7 @@ struct LIST *siParsePAT (u_char *Buffer) Pat = (pat_t *) Buffer; Ptr = Buffer; if (Pat->table_id != TID_PAT) { -// fprintf (stderr, "PAT: wrong TID %d\n", Pat->table_id); + // fprintf (stderr, "PAT: wrong TID %d\n", Pat->table_id); return NULL; } @@ -83,6 +85,43 @@ struct LIST *siParsePAT (u_char *Buffer) } +struct LIST *siParseCAT (u_char *Buffer) +{ + cat_t *Cat; + u_char *Ptr; + int SectionLength; + int TransportStreamID; + int CatVersion; + struct Descriptor *Descriptor; + struct LIST *DescriptorList = NULL; + + if (!Buffer) return NULL; + + Cat = (cat_t *) Buffer; Ptr = Buffer; + + if (Cat->table_id != TID_CAT) { + // fprintf (stderr, "CAT: wrong TID %d\n", Cat->table_id); + return NULL; + } + + SectionLength = HILO (Cat->section_length) + 3 - CAT_LEN - 4; + + if (crc32 (Ptr, HILO (Cat->section_length) + 3)) return (NULL); + + CatVersion = Cat->version_number; + + Ptr += CAT_LEN; + + if (SectionLength >= 0) + { + DescriptorList = xNewList (NULL); + siParseDescriptors (DescriptorList, Ptr, SectionLength, Cat->table_id); + } + + return (DescriptorList); +} + + struct Pid *siParsePMT (u_char *Buffer) { pmt_t *Pmt; @@ -101,7 +140,7 @@ struct Pid *siParsePMT (u_char *Buffer) Pmt = (pmt_t *) Buffer; Ptr = Buffer; if (Pmt->table_id != TID_PMT) { -// fprintf (stderr, "PMT: wrong TID %d\n", Pmt->table_id); + // fprintf (stderr, "PMT: wrong TID %d\n", Pmt->table_id); return NULL; } @@ -147,6 +186,89 @@ struct Pid *siParsePMT (u_char *Buffer) } +struct LIST *siParseNIT (u_char *Buffer) +{ + nit_t *Nit; + nit_mid_t *NitMid; + nit_ts_t *TSDesc; + u_char *Ptr; + int SectionLength, LoopLength, Loop2Length; + int TransportStreamID; + int NitVersion; + int NetworkID; + struct TransportStream *TransportStream; + struct LIST *TSList = NULL; + struct LIST *Networks; + struct NetworkInfo *Network; + + if (!Buffer) return NULL; + + Nit = (nit_t *) Buffer; + Ptr = Buffer; + + if (Nit->table_id != TID_NIT_ACT && Nit->table_id != TID_NIT_OTH && Nit->table_id != TID_BAT) { + return NULL; + } + + SectionLength = HILO (Nit->section_length) + 3 - NIT_LEN - 4; + + if (crc32 (Ptr, HILO (Nit->section_length) + 3)) return (NULL); + + NitVersion = Nit->version_number; + NetworkID = HILO (Nit->network_id); + if (NetworkID == 65535) + NetworkID = 0; + CreateNetworkInfo (Network, NetworkID); + Networks = xNewList (NULL); + xAddTail (Networks, Network); + + Ptr += NIT_LEN; + + LoopLength = HILO (Nit->network_descriptor_length); +// fprintf (stderr, "table 0x%X, SectionLen = %d, LoopLen = %d\n", +// Nit->table_id, SectionLength, LoopLength); + if (LoopLength > SectionLength - SDT_DESCR_LEN) + return (Networks); + + if (LoopLength <= SectionLength) { + if (SectionLength >= 0) siParseDescriptors (Network->Descriptors, Ptr, LoopLength, Nit->table_id); + SectionLength -= LoopLength; + Ptr += LoopLength; + NitMid = (nit_mid_t *) Ptr; + LoopLength = HILO (NitMid->transport_stream_loop_length); +// fprintf (stderr, "table 0x%X, TS LoopLen = %d\n", +// Nit->table_id, LoopLength); + if ((SectionLength > 0) && (LoopLength <= SectionLength)) { + SectionLength -= SIZE_NIT_MID; + Ptr += SIZE_NIT_MID; + while (LoopLength > 0) { + TSDesc = (nit_ts_t *) Ptr; + CreateTransportStream (TransportStream, HILO(TSDesc->transport_stream_id), HILO(TSDesc->original_network_id)); + if (TransportStream->TransportStreamID == 65535) + TransportStream->TransportStreamID = 0; + if (TransportStream->OriginalNetworkID == 65535) + TransportStream->OriginalNetworkID = 0; + Loop2Length = HILO (TSDesc->transport_descriptors_length); +// fprintf (stderr, "table 0x%X, TSdesc LoopLen = %d\n", +// Nit->table_id, Loop2Length); + Ptr += NIT_TS_LEN; + if (Loop2Length <= LoopLength) { + if (LoopLength >= 0) siParseDescriptors (TransportStream->Descriptors, Ptr, Loop2Length, Nit->table_id); + } + if (!Network->TransportStreams) + Network->TransportStreams = xNewList (NULL); + xAddTail (Network->TransportStreams, TransportStream); + LoopLength -= Loop2Length + NIT_TS_LEN; + SectionLength -= Loop2Length + NIT_TS_LEN; + Ptr += Loop2Length; + } + } + } + + return (Networks); +} + + struct LIST *siParseSDT (u_char *Buffer) { sdt_t *Sdt; @@ -164,7 +286,7 @@ struct LIST *siParseSDT (u_char *Buffer) Sdt = (sdt_t *) Buffer; Ptr = Buffer; if (Sdt->table_id != TID_SDT_ACT && Sdt->table_id != TID_SDT_OTH) { -// fprintf (stderr, "SDT: wrong TID %d\n", Sdt->table_id); + // fprintf (stderr, "SDT: wrong TID %d\n", Sdt->table_id); return NULL; } @@ -250,7 +372,7 @@ struct LIST *siParseEIT (u_char *Buffer) Eit->table_id <= TID_EIT_ACT_SCH + 0x0F) && !(Eit->table_id >= TID_EIT_OTH_SCH && Eit->table_id <= TID_EIT_OTH_SCH + 0x0F)) { -// fprintf (stderr, "EIT: wrong TID %d\n", Eit->table_id); + // fprintf (stderr, "EIT: wrong TID %d\n", Eit->table_id); return NULL; } @@ -331,7 +453,7 @@ time_t siParseTDT (u_char *Buffer) Tdt = (tdt_t *) Buffer; Ptr = Buffer; if (Tdt->table_id != TID_TDT) { -// fprintf (stderr, "TDT: wrong TID %d\n", Tdt->table_id); + // fprintf (stderr, "TDT: wrong TID %d\n", Tdt->table_id); return 0; } @@ -344,6 +466,44 @@ time_t siParseTDT (u_char *Buffer) } +struct Tot *siParseTOT (u_char *Buffer) +{ + tot_t *Tot; + u_char *Ptr; + int SectionLength, LoopLength; + struct Tot *table; + time_t CurrentTime; + + if (!Buffer) return NULL; + + Tot = (tot_t *) Buffer; + Ptr = Buffer; + + if (Tot->table_id != TID_TOT) { + return NULL; + } + + if (crc32 (Ptr, HILO (Tot->section_length) + 3)) return (NULL); +// SectionLength = HILO (Tot->section_length) + 3 - TOT_LEN - 4; + + CurrentTime = MjdToEpochTime (Tot->utc_mjd) + + BcdTimeToSeconds (Tot->utc_time); + LoopLength = HILO (Tot->descriptors_loop_length); + if (!LoopLength) + return NULL; + + CreateTot (table, CurrentTime); + + Ptr += TOT_LEN; + + siParseDescriptors (table->Descriptors, Ptr, LoopLength, Tot->table_id); + + // fprintf (stderr, "TOT Bias: %d\n", table->Bias); + return (table); +} + +static u_char TempTableID = 0; + void siParseDescriptors (struct LIST *Descriptors, u_char *Buffer, int Length, u_char TableID) { @@ -352,6 +512,7 @@ void siParseDescriptors (struct LIST *Descriptors, u_char *Buffer, DescriptorLength = 0; Ptr = Buffer; + TempTableID = TableID; while (DescriptorLength < Length) { @@ -362,15 +523,17 @@ void siParseDescriptors (struct LIST *Descriptors, u_char *Buffer, case TID_NIT_ACT: case TID_NIT_OTH: switch (GetDescriptorTag(Ptr)) { - case DESCR_NW_NAME: - case DESCR_SERVICE_LIST: - case DESCR_STUFFING: case DESCR_SAT_DEL_SYS: case DESCR_CABLE_DEL_SYS: + case DESCR_SERVICE_LIST: + case DESCR_PRIV_DATA_SPEC: +// fprintf (stderr, "Got descriptor with tag = 0x%X\n", GetDescriptorTag(Ptr)); +// siDumpDescriptor (Ptr); + case DESCR_NW_NAME: + case DESCR_STUFFING: case DESCR_LINKAGE: case DESCR_TERR_DEL_SYS: case DESCR_ML_NW_NAME: - case DESCR_PRIV_DATA_SPEC: case DESCR_CELL_LIST: case DESCR_CELL_FREQ_LINK: case DESCR_ANNOUNCEMENT_SUPPORT: @@ -378,8 +541,7 @@ void siParseDescriptors (struct LIST *Descriptors, u_char *Buffer, break; default: - /* fprintf (stderr, "forbidden descriptor 0x%x in NIT\n", - GetDescriptorTag(Ptr));*/ + // fprintf (stderr, "forbidden descriptor 0x%x in NIT\n", GetDescriptorTag(Ptr)); break; } break; @@ -396,12 +558,12 @@ void siParseDescriptors (struct LIST *Descriptors, u_char *Buffer, case DESCR_CA_IDENT: case DESCR_ML_BQ_NAME: case DESCR_PRIV_DATA_SPEC: + // fprintf (stderr, "Got descriptor with tag = 0x%X\n", GetDescriptorTag(Ptr)); siParseDescriptor (Descriptors, Ptr); break; default: - /*fprintf (stderr, "forbidden descriptor 0x%x in BAT\n", - GetDescriptorTag(Ptr));*/ + // fprintf (stderr, "forbidden descriptor 0x%x in BAT\n", GetDescriptorTag(Ptr)); break; } break; @@ -426,8 +588,7 @@ void siParseDescriptors (struct LIST *Descriptors, u_char *Buffer, break; default: - /* fprintf (stderr, "forbidden descriptor 0x%x in SDT\n", - GetDescriptorTag(Ptr)); */ + // fprintf (stderr, "forbidden descriptor 0x%x in SDT\n", GetDescriptorTag(Ptr)); break; } break; @@ -470,8 +631,7 @@ void siParseDescriptors (struct LIST *Descriptors, u_char *Buffer, break; default: - /*fprintf (stderr, "forbidden descriptor 0x%x in EIT\n", - GetDescriptorTag(Ptr));*/ + // fprintf (stderr, "forbidden descriptor 0x%x in EIT\n", GetDescriptorTag(Ptr)); break; } break; @@ -484,8 +644,7 @@ void siParseDescriptors (struct LIST *Descriptors, u_char *Buffer, break; default: - /*fprintf (stderr, "forbidden descriptor 0x%x in TOT\n", - GetDescriptorTag(Ptr));*/ + // fprintf (stderr, "forbidden descriptor 0x%x in TOT\n", GetDescriptorTag(Ptr)); break; } break; @@ -522,15 +681,28 @@ void siParseDescriptors (struct LIST *Descriptors, u_char *Buffer, break; default: - /* fprintf (stderr, "forbidden descriptor 0x%x in PMT\n", - GetDescriptorTag(Ptr)); */ + // fprintf (stderr, "forbidden descriptor 0x%x in PMT\n", GetDescriptorTag(Ptr)); + break; + } + break; + + case TID_CAT: + switch (GetDescriptorTag(Ptr)) + { + case DESCR_CA_SYSTEM: + case DESCR_CA: + case DESCR_CA_IDENT: + siParseDescriptor (Descriptors, Ptr); + break; + + default: + // fprintf (stderr, "forbidden descriptor 0x%x in CAT\n", GetDescriptorTag(Ptr)); break; } break; default: - fprintf (stderr, "descriptor 0x%x in unsupported table 0x%x\n", - GetDescriptorTag(Ptr), TableID); + // fprintf (stderr, "descriptor 0x%x in unsupported table 0x%x\n", GetDescriptorTag(Ptr), TableID); break; } DescriptorLength += GetDescriptorLength (Ptr); @@ -550,6 +722,7 @@ void siParseDescriptor (struct LIST *Descriptors, u_char *Buffer) if (!Descriptors || !Buffer) return; Ptr = Buffer; +// fprintf (stderr, "Got descriptor with tag = 0x%X\n", GetDescriptorTag(Buffer)); switch (GetDescriptorTag(Buffer)) { @@ -558,10 +731,12 @@ void siParseDescriptor (struct LIST *Descriptors, u_char *Buffer) CastAncillaryDataDescriptor(Buffer)->ancillary_data_identifier); break; + case DESCR_NW_NAME: case DESCR_BOUQUET_NAME: - Text = siGetDescriptorText (Buffer + DESCR_BOUQUET_NAME_LEN, + Text = siGetDescriptorName (Buffer + DESCR_BOUQUET_NAME_LEN, GetDescriptorLength (Buffer) - DESCR_BOUQUET_NAME_LEN); - CreateBouquetNameDescriptor (Descriptor, Text); +// fprintf (stderr, "Got descriptor with tag = 0x%X, text = '%s'\n", GetDescriptorTag(Buffer), Text); + CreateBouquetNameDescriptor (Descriptor, Text, GetDescriptorTag(Buffer)); break; case DESCR_COMPONENT: @@ -577,9 +752,9 @@ void siParseDescriptor (struct LIST *Descriptors, u_char *Buffer) break; case DESCR_SERVICE: - Text = siGetDescriptorText (Buffer + DESCR_SERVICE_LEN, + Text = siGetDescriptorName (Buffer + DESCR_SERVICE_LEN, CastServiceDescriptor(Buffer)->provider_name_length); - Text2 = siGetDescriptorText (Buffer + DESCR_SERVICE_LEN + + Text2 = siGetDescriptorName (Buffer + DESCR_SERVICE_LEN + CastServiceDescriptor(Buffer)->provider_name_length + 1, *((u_char *)(Buffer + DESCR_SERVICE_LEN + CastServiceDescriptor(Buffer)->provider_name_length))); @@ -598,7 +773,7 @@ void siParseDescriptor (struct LIST *Descriptors, u_char *Buffer) break; case DESCR_SHORT_EVENT: - Text = siGetDescriptorText (Buffer + DESCR_SHORT_EVENT_LEN, + Text = siGetDescriptorName (Buffer + DESCR_SHORT_EVENT_LEN, CastShortEventDescriptor(Buffer)->event_name_length); Text2 = siGetDescriptorText (Buffer + DESCR_SHORT_EVENT_LEN + CastShortEventDescriptor(Buffer)->event_name_length + 1, @@ -623,6 +798,7 @@ void siParseDescriptor (struct LIST *Descriptors, u_char *Buffer) CastExtendedEventDescriptor(Buffer)->lang_code3, Text); Length = CastExtendedEventDescriptor(Buffer)->length_of_items; Ptr += DESCR_EXTENDED_EVENT_LEN; +// printf ("EEDesc #%d, %s\n", CastExtendedEventDescriptor(Buffer)->descriptor_number, Text); while ((Length > 0) && (Length < GetDescriptorLength (Buffer))) { Text = siGetDescriptorText (Ptr + ITEM_EXTENDED_EVENT_LEN, @@ -631,6 +807,7 @@ void siParseDescriptor (struct LIST *Descriptors, u_char *Buffer) CastExtendedEventItem(Ptr)->item_description_length + 1, *((u_char *)(Ptr + ITEM_EXTENDED_EVENT_LEN + CastExtendedEventItem(Ptr)->item_description_length))); +// printf ("EEItem #%d, %s, %s\n", CastExtendedEventDescriptor(Buffer)->descriptor_number, Text, Text2); AddExtendedEventItem (Descriptor, Text2, Text); Length -= ITEM_EXTENDED_EVENT_LEN + CastExtendedEventItem(Ptr)->item_description_length + *((u_char *)(Ptr + ITEM_EXTENDED_EVENT_LEN + @@ -642,15 +819,85 @@ void siParseDescriptor (struct LIST *Descriptors, u_char *Buffer) break; case DESCR_CA_IDENT: - CreateCaIdentifierDescriptor (Descriptor, - (GetDescriptorLength(Buffer) - DESCR_CA_IDENTIFIER_LEN) / 2); Length = GetDescriptorLength (Buffer) - DESCR_CA_IDENTIFIER_LEN; + CreateCaIdentifierDescriptor (Descriptor, Length / 2); Ptr += DESCR_CA_IDENTIFIER_LEN; i = 0; while (Length > 0) - { SetCaIdentifierID(Descriptor, i, *((u_short *) Ptr)); + { SetCaIdentifierID(Descriptor, i, ((*((u_char *) Ptr)<<8) + *((u_char *) (Ptr+1)))); Length -= 2; Ptr += 2; i++; } break; + case DESCR_CA: + { + struct CaDescriptor *CD; + + Length = GetDescriptorLength (Buffer) - DESCR_CA_LEN; + CreateCaDescriptor (Descriptor, + HILO(CastCaDescriptor(Buffer)->CA_type), + HILO(CastCaDescriptor(Buffer)->CA_PID), Length); + Ptr += DESCR_CA_LEN; i = 0; + while (Length > 0) + { SetCaData(Descriptor, i, *Ptr); + Length --; Ptr ++; i++; } + + /* + * The following analyses are more or less directly copied from + * MultiDec 8.4b Sources. Thanx to Espresso for his great work !! + */ + CD = (struct CaDescriptor *) Descriptor; + + // fprintf (stderr, "TableID: %02x - CA - Type: 0x%04x, PID: %d\n", TempTableID, CD->CA_type, CD->CA_PID); + + if ((CD->CA_type >> 8) == 0x01) /* SECA */ + { + CD->ProviderID = (GetCaData (CD, 0) << 8) | GetCaData (CD, 1); + } + else if ((CD->CA_type >> 8) == 0x05) /* Viaccess ? (France Telecom) */ + { + i=0; + while (i < CD->DataLength) + { + if ((GetCaData (CD, i) == 0x14) && (GetCaData (CD, i+1) == 0x03)) + { + CD->ProviderID = (GetCaData (CD, i+2) << 16) | + (GetCaData (CD, i+3) << 8) | + (GetCaData (CD, i+4) & 0xf0); + i = CD->DataLength; + } + i++; + } + } + if (CD->CA_type==0x0100) /* SECA 1 */ + { + /* bptr=MyPtr+19; + + i=19; + while ( i+4 < ca_info->len ) { + if ( (*bptr&0xE0) == 0xE0 ) { + CA_ECM=(( *bptr&0x1f)<<8)+*(bptr+1); + Prov_Ident = ( *(bptr+2)<<8) | *(bptr+3); + j=0; + while ( j < ProgrammNeu[ProgrammNummer].CA_Anzahl ) { + if (( ProgrammNeu[ProgrammNummer].CA_System[j].CA_Typ == CA_Typ ) + && ( ProgrammNeu[ProgrammNummer].CA_System[j].ECM == CA_ECM )) break; + j++; + }; + + if ( j < MAX_CA_SYSTEMS ) { + if ( j >= ProgrammNeu[ProgrammNummer].CA_Anzahl ) + ProgrammNeu[ProgrammNummer].CA_Anzahl++; + ProgrammNeu[ProgrammNummer].CA_System[j].CA_Typ =CA_Typ; + ProgrammNeu[ProgrammNummer].CA_System[j].ECM =CA_ECM ; + ProgrammNeu[ProgrammNummer].CA_System[j].Provider_Id = Prov_Ident; + }; + } + i+=0x0f; + bptr+=0x0f; + }; */ + } + } + break; + case DESCR_CONTENT: CreateContentDescriptor (Descriptor, (GetDescriptorLength(Buffer) - DESCR_CONTENT_LEN) / 2); @@ -705,12 +952,6 @@ void siParseDescriptor (struct LIST *Descriptors, u_char *Buffer) HILO (CastTimeShiftedEventDescriptor(Ptr)->reference_event_id)); break; - case DESCR_CA: - CreateConditionalAccessDescriptor (Descriptor, - *(Ptr + 1) + 2, // we'll need the entire raw data! - Ptr); - break; - case DESCR_ISO_639_LANGUAGE: CreateIso639LanguageDescriptor (Descriptor, CastIso639LanguageDescriptor(Buffer)->lang_code1, @@ -789,6 +1030,80 @@ void siParseDescriptor (struct LIST *Descriptors, u_char *Buffer) } break; + case DESCR_SAT_DEL_SYS: +// fprintf (stderr, "got descriptor 0x%x\n", GetDescriptorTag(Buffer)); + { + descr_satellite_delivery_system_t *sds; + sds = (descr_satellite_delivery_system_t *) Ptr; + if (CheckBcdChar (sds->frequency1) && CheckBcdChar (sds->frequency2) && + CheckBcdChar (sds->frequency3) && CheckBcdChar (sds->frequency4) && + CheckBcdChar (sds->orbital_position1) && + CheckBcdChar (sds->orbital_position2) && + CheckBcdChar (sds->symbol_rate1) && CheckBcdChar (sds->symbol_rate1) && + CheckBcdChar (sds->symbol_rate3) && (sds->fec_inner != 0) && (sds->modulation == 1)) + { + CreateSatelliteDeliverySystemDescriptor (Descriptor, + BcdCharToInt (sds->frequency1) * 10 * 1000 * 1000 + + BcdCharToInt (sds->frequency2) * 100 * 1000 + + BcdCharToInt (sds->frequency3) * 1000 + + BcdCharToInt (sds->frequency4) * 10, + (sds->west_east_flag ? 1 : -1) * + (BcdCharToInt (sds->orbital_position1) * 100 + + BcdCharToInt (sds->orbital_position2)), + sds->polarization, + BcdCharToInt (sds->symbol_rate1) * 10 * 1000 + + BcdCharToInt (sds->symbol_rate2) * 100 + + BcdCharToInt (sds->symbol_rate3), + sds->fec_inner); + } + /* else + { + fprintf (stderr, "Illegal sds descriptor\n"); + siDumpDescriptor (Buffer); + } */ + } + break; + + case DESCR_SERVICE_LIST: +// fprintf (stderr, "got descriptor 0x%x\n", GetDescriptorTag(Buffer)); + CreateServiceListDescriptor (Descriptor); + Length = GetDescriptorLength (Buffer) - DESCR_SERVICE_LIST_LEN; + Ptr += DESCR_SERVICE_LIST_LEN; + while (Length > 0) + { + AddServiceListEntry (Descriptor, + HILO (CastServiceListDescriptorLoop(Ptr)->service_id), + CastServiceListDescriptorLoop(Ptr)->service_type); + Length -= DESCR_SERVICE_LIST_LEN; + Ptr += DESCR_SERVICE_LIST_LEN; + } + break; + + case DESCR_LOCAL_TIME_OFF: + CreateLocalTimeOffsetDescriptor (Descriptor); + Length = GetDescriptorLength (Buffer) - DESCR_LOCAL_TIME_OFFSET_LEN; + Ptr += DESCR_LOCAL_TIME_OFFSET_LEN; + while (Length > 0) + { + time_t ct, co, no; + ct = MjdToEpochTime (CastLocalTimeOffsetEntry(Ptr)->time_of_change_mjd) + + BcdTimeToSeconds (CastLocalTimeOffsetEntry(Ptr)->time_of_change_time); + co = (BcdCharToInt(CastLocalTimeOffsetEntry(Ptr)->local_time_offset_h) * 3600 + + BcdCharToInt(CastLocalTimeOffsetEntry(Ptr)->local_time_offset_m) * 60) * + ((CastLocalTimeOffsetEntry(Ptr)->local_time_offset_polarity) ? -1 : 1); + no = (BcdCharToInt(CastLocalTimeOffsetEntry(Ptr)->next_time_offset_h) * 3600 + + BcdCharToInt(CastLocalTimeOffsetEntry(Ptr)->next_time_offset_m) * 60) * + ((CastLocalTimeOffsetEntry(Ptr)->local_time_offset_polarity) ? -1 : 1); + AddLocalTimeOffsetEntry (Descriptor, + CastLocalTimeOffsetEntry(Ptr)->country_code1, + CastLocalTimeOffsetEntry(Ptr)->country_code2, + CastLocalTimeOffsetEntry(Ptr)->country_code3, + CastLocalTimeOffsetEntry(Ptr)->country_region_id, co, ct, no); + Length -= LOCAL_TIME_OFFSET_ENTRY_LEN; + Ptr += LOCAL_TIME_OFFSET_ENTRY_LEN; + } + break; + case DESCR_VIDEO_STREAM: case DESCR_AUDIO_STREAM: case DESCR_HIERARCHY: @@ -804,15 +1119,11 @@ void siParseDescriptor (struct LIST *Descriptors, u_char *Buffer) case DESCR_SMOOTHING_BUFFER: case DESCR_STD: case DESCR_IBP: - case DESCR_NW_NAME: - case DESCR_SERVICE_LIST: - case DESCR_SAT_DEL_SYS: case DESCR_CABLE_DEL_SYS: case DESCR_VBI_DATA: case DESCR_VBI_TELETEXT: case DESCR_MOSAIC: case DESCR_TELEPHONE: - case DESCR_LOCAL_TIME_OFF: case DESCR_TERR_DEL_SYS: case DESCR_ML_NW_NAME: case DESCR_ML_BQ_NAME: @@ -833,6 +1144,8 @@ void siParseDescriptor (struct LIST *Descriptors, u_char *Buffer) case DESCR_CELL_FREQ_LINK: case DESCR_ANNOUNCEMENT_SUPPORT: default: +// fprintf (stderr, "Unsupported descriptor with tag = 0x%02X\n", GetDescriptorTag(Ptr)); +// siDumpDescriptor (Buffer); /* fprintf (stderr, "unsupported descriptor 0x%x\n", GetDescriptorTag(Buffer)); */ break; @@ -845,14 +1158,19 @@ void siParseDescriptor (struct LIST *Descriptors, u_char *Buffer) /* * ToDo: ETSI conformal text definition */ -char *siGetDescriptorText (u_char *Buffer, int Length) +#define GDT_TEXT_DESCRIPTOR 0 +#define GDT_NAME_DESCRIPTOR 1 +char *siGetDescriptorTextHandler (u_char *, int , int ); + +char *siGetDescriptorTextHandler (u_char *Buffer, int Length, int type) { char *tmp, *result; int i; if ((Length < 0) || (Length > 4095)) return (xSetText ("text error")); - if (*Buffer == 0x05 || (*Buffer >= 0x20 && *Buffer <= 0xff)) +/* ASSENIZATION: removing coding detection - suppose they are all ANSI */ + // if (*Buffer == 0x05 || (*Buffer >= 0x20 && *Buffer <= 0xff)) { xMemAlloc (Length+1, &result); tmp = result; @@ -860,15 +1178,16 @@ char *siGetDescriptorText (u_char *Buffer, int Length) { if (*Buffer == 0) break; - if ((*Buffer >= ' ' && *Buffer <= '~') || + if ((*Buffer >= ' ' && *Buffer <= '~') || (*Buffer == '\n') || (*Buffer >= 0xa0 && *Buffer <= 0xff)) *tmp++ = *Buffer; - if (*Buffer == 0x8A || *Buffer == '\n') *tmp++ = '\n'; + if (*Buffer == 0x8A) *tmp++ = '\n'; if (*Buffer == 0x86 || *Buffer == 0x87) *tmp++ = ' '; + if ((*Buffer == 0x86 || *Buffer == 0x87) && !(GDT_NAME_DESCRIPTOR & type)) *tmp++ = ' '; Buffer++; } *tmp = '\0'; } - else + /* else { switch (*Buffer) { @@ -881,11 +1200,22 @@ char *siGetDescriptorText (u_char *Buffer, int Length) case 0x12: result = xSetText ("Coding according to KSC 5601"); break; default: result = xSetText ("Unknown coding"); break; } - } + } */ return (result); } +char *siGetDescriptorText (u_char *Buffer, int Length) +{ + return siGetDescriptorTextHandler (Buffer, Length, GDT_TEXT_DESCRIPTOR); +} + +char *siGetDescriptorName (u_char *Buffer, int Length) +{ + return siGetDescriptorTextHandler (Buffer, Length, GDT_NAME_DESCRIPTOR); +} + + // CRC32 lookup table for polynomial 0x04c11db7 static u_long crc_table[256] = {