// // $Id: SIsections.cpp,v 1.61 2009/09/04 18:37:00 dbt Exp $ // // classes for SI sections (dbox-II-project) // // Homepage: http://dbox2.elxsi.de // // Copyright (C) 2001 fnbrd (fnbrd@gmx.de) // // 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. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // // #include #include #include #include #include // fuer poll() #include #include #include #include "SIutils.hpp" #include "SIservices.hpp" #include "SIevents.hpp" #ifdef UPDATE_NETWORKS #include "SIbouquets.hpp" #include "SInetworks.hpp" #endif #include "SIsections.hpp" #include #include #include #ifdef ENABLE_FREESATEPG #include "FreesatTables.hpp" #endif #define NOVA 0x3ffe #define CANALDIGITAAL 0x3fff //#define DEBUG struct descr_generic_header { unsigned descriptor_tag : 8; unsigned descriptor_length : 8; } __attribute__ ((packed)) ; struct descr_short_event_header { unsigned descriptor_tag : 8; unsigned descriptor_length : 8; unsigned language_code_hi : 8; unsigned language_code_mid : 8; unsigned language_code_lo : 8; unsigned event_name_length : 8; } __attribute__ ((packed)) ; struct descr_service_header { unsigned descriptor_tag : 8; unsigned descriptor_length : 8; unsigned service_typ : 8; unsigned service_provider_name_length : 8; } __attribute__ ((packed)) ; struct descr_extended_event_header { unsigned descriptor_tag : 8; unsigned descriptor_length : 8; unsigned descriptor_number : 4; unsigned last_descriptor_number : 4; unsigned iso_639_2_language_code_hi : 8; unsigned iso_639_2_language_code_mid : 8; unsigned iso_639_2_language_code_lo : 8; unsigned length_of_items : 8; } __attribute__ ((packed)) ; struct service_list_entry { unsigned service_id_hi : 8; unsigned service_id_lo : 8; unsigned service_type : 8; } __attribute__ ((packed)) ; struct digplus_order_entry { unsigned service_id_hi : 8; unsigned service_id_lo : 8; unsigned channel_number_hi : 8; unsigned channel_number_lo : 8; } __attribute__ ((packed)) ; struct bskyb_order_entry { unsigned service_id_hi : 8; unsigned service_id_lo : 8; unsigned service_type : 8; unsigned unknown1 : 8; unsigned unknown2 : 8; unsigned channel_number_hi : 8; unsigned channel_number_lo : 8; unsigned unknown3 : 8; unsigned unknown4 : 8; } __attribute__ ((packed)) ; struct bskyb_bid { unsigned unknown1 : 8; unsigned unknown2 : 8; } __attribute__ ((packed)) ; struct private_data_specifier { unsigned byte1 : 8; unsigned byte2 : 8; unsigned byte3 : 8; unsigned byte4 : 8; } __attribute__ ((packed)) ; inline unsigned min(unsigned a, unsigned b) { return b < a ? b : a; } static int get_table(unsigned char hi, unsigned char mid, unsigned char lo) { char lang[4]; lang[0] = hi; lang[1] = mid; lang[2] = lo; lang[3] = 0; if(!strcmp(lang, "pol")) return 2; else if(!strcmp(lang, "tur")) return 9; else if(!strcmp(lang, "gre")) return 7; else if(!strcmp(lang, "rus")) return 5; else if(!strcmp(lang, "bul")) return 5; else if(!strcmp(lang, "ara")) return 6; return 0; } bool check_blacklisted(const t_original_network_id onid, const t_transport_stream_id tsid) { if ( (onid == 0x0001) && ((tsid == 0x03F0) || (tsid == 0x0408) || (tsid == 0x040E) || (tsid == 0x0412) || (tsid == 0x0416) || (tsid == 0x041E) || (tsid == 0x0420) || (tsid == 0x0422) || (tsid == 0x0424) || (tsid == 0x0444) )) return true; else return false; } //----------------------------------------------------------------------- // Da es vorkommen kann das defekte Packete empfangen werden // sollte hier alles ueberprueft werden. // Leider ist das noch nicht bei allen Descriptoren so. //----------------------------------------------------------------------- void SIsectionEIT::parseLinkageDescriptor(const char *buf, SIevent &e, unsigned maxlen) { if(maxlen>=sizeof(struct descr_linkage_header)) { SIlinkage l((const struct descr_linkage_header *)buf); e.linkage_descs.insert(e.linkage_descs.end(), l); //printf("LinkName: %s\n", l.name.c_str()); } } void SIsectionEIT::parseComponentDescriptor(const char *buf, SIevent &e, unsigned maxlen) { if(maxlen>=sizeof(struct descr_component_header)) e.components.insert(SIcomponent((const struct descr_component_header *)buf)); } void SIsectionEIT::parseContentDescriptor(const char *buf, SIevent &e, unsigned maxlen) { struct descr_generic_header *cont=(struct descr_generic_header *)buf; if(cont->descriptor_length+sizeof(struct descr_generic_header)>maxlen) return; // defekt const char *classification=buf+sizeof(struct descr_generic_header); while(classification<=buf+sizeof(struct descr_generic_header)+cont->descriptor_length-2) { e.contentClassification+=std::string(classification, 1); // printf("Content: 0x%02hhx\n", *classification); e.userClassification+=std::string(classification+1, 1); // printf("User: 0x%02hhx\n", *(classification+1)); classification+=2; } } void SIsectionEIT::parseParentalRatingDescriptor(const char *buf, SIevent &e, unsigned maxlen) { struct descr_generic_header *cont=(struct descr_generic_header *)buf; if(cont->descriptor_length+sizeof(struct descr_generic_header)>maxlen) return; // defekt const char *s=buf+sizeof(struct descr_generic_header); while(sdescriptor_length-4) { e.ratings.insert(SIparentalRating(std::string(s, 3), *(s+3))); s+=4; } } void SIsectionEIT::parseExtendedEventDescriptor(const char *buf, SIevent &e, unsigned maxlen) { struct descr_extended_event_header *evt=(struct descr_extended_event_header *)buf; if((evt->descriptor_length+sizeof(descr_generic_header)>maxlen) || (evt->descriptor_lengthiso_639_2_language_code_hi, evt->iso_639_2_language_code_mid, evt->iso_639_2_language_code_lo); char lang[] = {tolower(evt->iso_639_2_language_code_hi), tolower(evt->iso_639_2_language_code_mid), tolower(evt->iso_639_2_language_code_lo), '\0'}; std::string language(lang); while(items < (unsigned char *)(buf + sizeof(struct descr_extended_event_header) + evt->length_of_items)) { // TODO What info should be in item & itemDescription? // Should I make language filter those as well? Arzka if(*items) { #if 0 if(*(items+1) < 0x06) { // other code table // 21.07.2005 - collect all extended events in one // string, delimit multiple entries with a newline e.itemDescription.append(std::string((const char *)(items+2), min(maxlen-((const char *)items+2-buf), (*items)-1))); e.itemDescription.append("\n"); } else #endif { // 21.07.2005 - collect all extended events in one // string, delimit multiple entries with a newline //e.itemDescription.append(std::string((const char *)(items+1), min(maxlen-((const char *)items+1-buf), *items))); e.itemDescription.append(convertDVBUTF8((const char *)(items+1), min(maxlen-((const char *)items+1-buf), *items), table, tsidonid)); e.itemDescription.append("\n"); } } items+=1+*items; if(*items) { // 21.07.2005 - collect all extended events in one // string, delimit multiple entries with a newline //e.item.append(std::string((const char *)(items+0), min(maxlen-((const char *)items+1-buf), *items))); e.item.append(convertDVBUTF8((const char *)(items+1), min(maxlen-((const char *)items+1-buf), *items), table, tsidonid)); e.item.append("\n"); } items+=1+*items; } // if (0 != e.itemDescription.length()) { // printf("Item Description: %s\n", e.itemDescription.c_str()); // printf("Item: %s\n", e.item.c_str()); // } if(*items) { #if 0 if(*(items+1) < 0x06) { // other code table e.appendExtendedText(language, std::string((const char *)(items+2), min(maxlen-((const char *)items+2-buf), (*items)-1))); } else #endif { //e.appendExtendedText(language, std::string((const char *)(items+1), min(maxlen-((const char *)items+1-buf), *items))); e.appendExtendedText(language, convertDVBUTF8((const char *)(items+1), min(maxlen-((const char *)items+1-buf), (*items)), table, tsidonid)); // printf("Extended Text: %s\n", e.extendedText.c_str()); } } } #ifdef ENABLE_FREESATEPG std::string SIsectionEIT::freesatHuffmanDecode(std::string input) { const char *src = input.c_str(); uint size = input.length(); if (src[1] == 1 || src[1] == 2) { std::string uncompressed(size * 3, ' '); uint p = 0; struct hufftab *table; unsigned table_length; if (src[1] == 1) { table = fsat_huffman1; table_length = sizeof(fsat_huffman1) / sizeof(fsat_huffman1[0]); } else { table = fsat_huffman2; table_length = sizeof(fsat_huffman2) / sizeof(fsat_huffman2[0]); } unsigned value = 0, byte = 2, bit = 0; while (byte < 6 && byte < size) { value |= src[byte] << ((5-byte) * 8); byte++; } char lastch = START; do { bool found = false; unsigned bitShift = 0; if (lastch == ESCAPE) { found = true; // Encoded in the next 8 bits. // Terminated by the first ASCII character. char nextCh = (value >> 24) & 0xff; bitShift = 8; if ((nextCh & 0x80) == 0) lastch = nextCh; if (p >= uncompressed.length()) uncompressed.resize(p+10); uncompressed[p++] = nextCh; } else { for (unsigned j = 0; j < table_length; j++) { if (table[j].last == lastch) { unsigned mask = 0, maskbit = 0x80000000; for (short kk = 0; kk < table[j].bits; kk++) { mask |= maskbit; maskbit >>= 1; } if ((value & mask) == table[j].value) { char nextCh = table[j].next; bitShift = table[j].bits; if (nextCh != STOP && nextCh != ESCAPE) { if (p >= uncompressed.length()) uncompressed.resize(p+10); uncompressed[p++] = nextCh; } found = true; lastch = nextCh; break; } } } } if (found) { // Shift up by the number of bits. for (unsigned b = 0; b < bitShift; b++) { value = (value << 1) & 0xfffffffe; if (byte < size) value |= (src[byte] >> (7-bit)) & 1; if (bit == 7) { bit = 0; byte++; } else bit++; } } else { // Entry missing in table. uncompressed.resize(p); uncompressed.append("..."); return uncompressed; } } while (lastch != STOP && value != 0); uncompressed.resize(p); return uncompressed; } else return input; } #endif void SIsectionEIT::parseShortEventDescriptor(const char *buf, SIevent &e, unsigned maxlen) { struct descr_short_event_header *evt=(struct descr_short_event_header *)buf; if((evt->descriptor_length+sizeof(descr_generic_header)>maxlen) || (evt->descriptor_lengthlanguage_code_hi, evt->language_code_mid, evt->language_code_lo); char lang[] = {tolower(evt->language_code_hi), tolower(evt->language_code_mid), tolower(evt->language_code_lo), '\0'}; std::string language(lang); buf+=sizeof(struct descr_short_event_header); if(evt->event_name_length) { #if 0 if(*buf < 0x06) { // other code table #ifdef ENABLE_FREESATEPG e.setName(language, buf[1] == 0x1f ? freesatHuffmanDecode(std::string(buf+1, evt->event_name_length-1)) : std::string(buf+1, evt->event_name_length-1)); #else e.setName(language, std::string(buf+1, evt->event_name_length-1)); #endif } else #endif // 0 { #ifdef ENABLE_FREESATEPG // FIXME convertDVBUTF8 e.setName(language, buf[0] == 0x1f ? freesatHuffmanDecode(std::string(buf, evt->event_name_length)) : std::string(buf, evt->event_name_length)); #else //e.setName(language, std::string(buf, evt->event_name_length)); e.setName(language, convertDVBUTF8(buf, evt->event_name_length, table, tsidonid)); #endif } } buf+=evt->event_name_length; unsigned char textlength=*((unsigned char *)buf); if(textlength > 2) { #if 0 if(*(buf+1) < 0x06) {// other code table #ifdef ENABLE_FREESATEPG e.setText(language, buf[2] == 0x1f ? freesatHuffmanDecode(std::string((++buf)+1, textlength-1)) : std::string((++buf)+1, textlength-1)); #else e.setText(language, std::string((++buf)+1, textlength-1)); #endif } else #endif // 0 { #ifdef ENABLE_FREESATEPG e.setText(language, buf[1] == 0x1f ? freesatHuffmanDecode(std::string(++buf, textlength)) : std::string(++buf, textlength)); #else //e.setText(language, std::string(++buf, textlength)); e.setText(language, convertDVBUTF8((++buf), textlength, table, tsidonid)); #endif } } // printf("Name: %s\n", e.name.c_str()); // printf("Text: %s\n", e.text.c_str()); } void SIsectionEIT::parseDescriptors(const char *des, unsigned len, SIevent &e) { struct descr_generic_header *desc; /* we pass the buffer including the eit_event header, so we have to skip it here... */ des += sizeof(struct eit_event); len -= sizeof(struct eit_event); while(len>=sizeof(struct descr_generic_header)) { desc=(struct descr_generic_header *)des; // printf("Type: %s\n", decode_descr(desc->descriptor_tag)); if(desc->descriptor_tag==0x4D) parseShortEventDescriptor((const char *)desc, e, len); else if(desc->descriptor_tag==0x4E) parseExtendedEventDescriptor((const char *)desc, e, len); else if(desc->descriptor_tag==0x54) parseContentDescriptor((const char *)desc, e, len); else if(desc->descriptor_tag==0x50) parseComponentDescriptor((const char *)desc, e, len); else if(desc->descriptor_tag==0x55) parseParentalRatingDescriptor((const char *)desc, e, len); else if(desc->descriptor_tag==0x4A) parseLinkageDescriptor((const char *)desc, e, len); if((unsigned)(desc->descriptor_length+2)>len) break; len-=desc->descriptor_length+2; des+=desc->descriptor_length+2; } } // Die infos aus dem Puffer holen void SIsectionEIT::parse(void) { const char *actPos; const char *bufEnd; struct eit_event *evt; unsigned short descriptors_loop_length; if (!buffer || parsed) return; if (bufferLength < sizeof(SI_section_EIT_header) + sizeof(struct eit_event)) { bufferLength=0; return; } actPos = buffer + sizeof(SI_section_EIT_header); bufEnd = buffer + bufferLength; while (actPos < bufEnd - sizeof(struct eit_event)) { evt = (struct eit_event *) actPos; SIevent e(evt); e.service_id = service_id(); e.original_network_id = original_network_id(); e.transport_stream_id = transport_stream_id(); descriptors_loop_length = sizeof(struct eit_event) + ((evt->descriptors_loop_length_hi << 8) | evt->descriptors_loop_length_lo); parseDescriptors(actPos, min((unsigned)(bufEnd - actPos), descriptors_loop_length), e); evts.insert(e); actPos += descriptors_loop_length; } parsed = 1; } //----------------------------------------------------------------------- // Da es vorkommen kann das defekte Packete empfangen werden // sollte hier alles ueberprueft werden. // Leider ist das noch nicht bei allen Descriptoren so. //----------------------------------------------------------------------- #ifdef ENABLE_PPT void SIsectionPPT::parseLinkageDescriptor(const char *buf, SIevent &e, unsigned maxlen) { if(maxlen>=sizeof(struct descr_linkage_header)) { SIlinkage l((const struct descr_linkage_header *)buf); e.linkage_descs.insert(e.linkage_descs.end(), l); // printf("LinkName: %s\n", l.name.c_str()); } } void SIsectionPPT::parseComponentDescriptor(const char *buf, SIevent &e, unsigned maxlen) { if(maxlen>=sizeof(struct descr_component_header)) e.components.insert(SIcomponent((const struct descr_component_header *)buf)); } void SIsectionPPT::parseContentDescriptor(const char *buf, SIevent &e, unsigned maxlen) { struct descr_generic_header *cont=(struct descr_generic_header *)buf; if(cont->descriptor_length+sizeof(struct descr_generic_header)>maxlen) return; // defekt const char *classification=buf+sizeof(struct descr_generic_header); while(classification<=buf+sizeof(struct descr_generic_header)+cont->descriptor_length-2) { e.contentClassification+=std::string(classification, 1); // printf("Content: 0x%02hhx\n", *classification); e.userClassification+=std::string(classification+1, 1); // printf("User: 0x%02hhx\n", *(classification+1)); classification+=2; } } void SIsectionPPT::parseParentalRatingDescriptor(const char *buf, SIevent &e, unsigned maxlen) { struct descr_generic_header *cont=(struct descr_generic_header *)buf; if(cont->descriptor_length+sizeof(struct descr_generic_header)>maxlen) return; // defekt const char *s=buf+sizeof(struct descr_generic_header); while(sdescriptor_length-4) { e.ratings.insert(SIparentalRating(std::string(s, 3), *(s+3))); s+=4; } } void SIsectionPPT::parseExtendedEventDescriptor(const char *buf, SIevent &e, unsigned maxlen) { struct descr_extended_event_header *evt=(struct descr_extended_event_header *)buf; if((evt->descriptor_length+sizeof(descr_generic_header)>maxlen) || (evt->descriptor_lengthiso_639_2_language_code_hi + evt->iso_639_2_language_code_mid + evt->iso_639_2_language_code_lo; unsigned char *items=(unsigned char *)(buf+sizeof(struct descr_extended_event_header)); while(items<(unsigned char *)(buf+sizeof(struct descr_extended_event_header)+evt->length_of_items)) { if(*items) { if(*(items+1) < 0x06) // other code table e.itemDescription=std::string((const char *)(items+2), min(maxlen-((const char *)items+2-buf), (*items)-1)); else e.itemDescription=std::string((const char *)(items+1), min(maxlen-((const char *)items+1-buf), *items)); // printf("Item Description: %s\n", e.itemDescription.c_str()); } items+=1+*items; if(*items) { e.item=std::string((const char *)(items+1), min(maxlen-((const char *)items+1-buf), *items)); // printf("Item: %s\n", e.item.c_str()); } items+=1+*items; } if(*items) { if(*(items+1) < 0x06) // other code table e.appendExtendedText(language, std::string((const char *)(items+2),min(maxlen-((const char *)items+2-buf), (*items)-1))); else e.appendExtendedText(language, std::string((const char *)(items+1), min(maxlen-((const char *)items+1-buf), *items))); // printf("Extended Text: %s\n", e.extendedText.c_str()); } } void SIsectionPPT::parseShortEventDescriptor(const char *buf, SIevent &e, unsigned maxlen) { struct descr_short_event_header *evt=(struct descr_short_event_header *)buf; if((evt->descriptor_length+sizeof(descr_generic_header)>maxlen) || (evt->descriptor_lengthlanguage_code_hi + evt->language_code_mid + evt->language_code_lo; buf+=sizeof(struct descr_short_event_header); if(evt->event_name_length) { if(*buf < 0x06) // other code table e.setName(language, std::string(buf+1, evt->event_name_length-1)); else e.setName(language, std::string(buf, evt->event_name_length)); } buf+=evt->event_name_length; unsigned char textlength=*((unsigned char *)buf); if(textlength > 2) { if(*(buf+1) < 0x06) // other code table e.setText(language, std::string((++buf)+1, textlength-1)); else e.setText(language, std::string(++buf, textlength)); } // printf("Name: %s\n", e.name.c_str()); // printf("Text: %s\n", e.text.c_str()); } void SIsectionPPT::parsePrivateContentOrderDescriptor(const char *buf, SIevent &e, unsigned maxlen) { struct descr_short_event_header *evt=(struct descr_short_event_header *)buf; if((evt->descriptor_length+sizeof(descr_generic_header)>maxlen) || (evt->descriptor_lengthdescriptor_length+sizeof(descr_generic_header)>maxlen) || (evt->descriptor_lengthdescriptor_length) { e.ratings.insert(SIparentalRating(std::string("", 0), *(buf))); } #if 0 unsigned char rating; unsigned char Controll_time_t1[3]; // BCD coded unsigned char Controll_time_t2[3]; // BCD coded unsigned char Parental_information_length; unsigned char Parental_information[Parental_information_length]; #endif } void SIsectionPPT::parsePrivateContentTransmissionDescriptor(const char *buf, SIevent &e, unsigned maxlen) { unsigned short starttime_loop_length = 0; unsigned char tm_buf[6]; int i; struct descr_short_event_header *evt=(struct descr_short_event_header *)buf; if((evt->descriptor_length+sizeof(descr_generic_header)>maxlen) || (evt->descriptor_lengthdescriptor_length + sizeof(struct descr_generic_header)) {// at least one startdate/looplength/time entry tm_buf[0] = *(p); tm_buf[1] = *(p+1); starttime_loop_length = (*(p+2))/3; for (i=0;i=sizeof(struct descr_generic_header)) { desc=(struct descr_generic_header *)des; // printf("Type: %s\n", decode_descr(desc->descriptor_tag)); if(desc->descriptor_tag==0x4D) parseShortEventDescriptor((const char *)desc, e, len); else if(desc->descriptor_tag==0x4E) parseExtendedEventDescriptor((const char *)desc, e, len); else if(desc->descriptor_tag==0x54) parseContentDescriptor((const char *)desc, e, len); else if(desc->descriptor_tag==0x50) parseComponentDescriptor((const char *)desc, e, len); else if(desc->descriptor_tag==0x55) parseParentalRatingDescriptor((const char *)desc, e, len); else if(desc->descriptor_tag==0x4A) parseLinkageDescriptor((const char *)desc, e, len); else if(desc->descriptor_tag==0xF0) parsePrivateContentOrderDescriptor((const char *)desc, e, len); else if(desc->descriptor_tag==0xF1) parsePrivateParentalInformationDescriptor((const char *)desc, e, len); else if(desc->descriptor_tag==0xF2) { if (linkage_alreadyseen) { // Private EPG can have two linkage descriptors with their own date/time parameters for one event // not sure if current event system supports it therefore: // Generate additional Event(s) if there are more than one linkage descriptor (for repeated transmission) SIevent e2(e); e2.linkage_descs.clear(); e2.times.clear(); parsePrivateContentTransmissionDescriptor((const char *)desc, e2, len); evts.insert(e2); } else { parsePrivateContentTransmissionDescriptor((const char *)desc, e, len); linkage_alreadyseen = true; } } if((unsigned)(desc->descriptor_length+2)>len) break; len-=desc->descriptor_length+2; des+=desc->descriptor_length+2; } } // Die infos aus dem Puffer holen void SIsectionPPT::parse(void) { const char *actPos; unsigned short descriptors_loop_length; if (!buffer || parsed) return; if (bufferLength < sizeof(SI_section_PPT_header)) { bufferLength=0; return; } actPos = &buffer[sizeof(SI_section_PPT_header)]; /*while (actPos < &buffer[bufferLength])*/ { SIevent e; descriptors_loop_length = (((SI_section_PPT_header*)buffer)->descriptor_section_length_hi << 8) | ((SI_section_PPT_header*)buffer)->descriptor_section_length_lo; e.eventID = (unsigned short)(content_id()); // ?? parseDescriptors(actPos, min((unsigned)(buffer + bufferLength - actPos), descriptors_loop_length), e); evts.insert(e); actPos += descriptors_loop_length; } parsed = 1; } #endif /********************/ void SIsectionSDT::parseNVODreferenceDescriptor(const char *buf, SIservice &s) { struct descr_generic_header *hdr=(struct descr_generic_header *)buf; unsigned short *spointer=(unsigned short *)(buf+sizeof(struct descr_generic_header)); while((const char *)spointer<=buf+sizeof(struct descr_generic_header)+hdr->descriptor_length-2) { unsigned short transportStreamID=*spointer++; unsigned short originalNetworkID=*spointer++; unsigned short sID=*spointer++; s.nvods.insert(SInvodReference(transportStreamID, originalNetworkID, sID)); } } void SIsectionSDT::parseServiceDescriptor(const char *buf, SIservice &s) { bool is_blacklisted; struct descr_service_header *sv=(struct descr_service_header *)buf; buf+=sizeof(struct descr_service_header); s.serviceTyp=sv->service_typ; is_blacklisted = check_blacklisted(s.original_network_id, s.transport_stream_id); if(sv->service_provider_name_length) { //if(*buf < 0x06) // other code table // s.providerName=std::string(buf+1, sv->service_provider_name_length-1); // else // s.providerName=std::string(buf, sv->service_provider_name_length); if ((*buf > 0x05) && (is_blacklisted)) s.providerName = CDVBString(("\x05" + std::string((const char *)(buf))).c_str(), sv->service_provider_name_length+1).getContent(); else s.providerName = CDVBString((const char *)(buf), sv->service_provider_name_length).getContent(); } buf+=sv->service_provider_name_length; unsigned char servicenamelength=*((unsigned char *)buf); if(servicenamelength) { if ((*buf+1 > 0x05) && (is_blacklisted)) s.serviceName = CDVBString(("\x05" + std::string((const char *)(++buf))).c_str(), servicenamelength+1).getContent(); else s.serviceName = CDVBString((const char *)(++buf), servicenamelength).getContent(); } // printf("Provider-Name: %s\n", s.providerName.c_str()); // printf("Service-Name: %s\n", s.serviceName.c_str()); } void SIsectionSDT::parsePrivateDataDescriptor(const char *buf, SIservice &s) { buf+=sizeof(struct descr_generic_header); struct private_data_specifier *pds=(struct private_data_specifier *)buf; if ((((((pds->byte1 << 24) | (pds->byte2 << 16)) | (pds->byte3 << 8)) | pds->byte4) == 0x000000c0) && (s.serviceTyp == 0xc3)) s.serviceTyp = 0x01; } void SIsectionSDT::parseDescriptors(const char *des, unsigned len, SIservice &s) { struct descr_generic_header *desc; des += sizeof(struct sdt_service); len -= sizeof(struct sdt_service); while(len>=sizeof(struct descr_generic_header)) { desc=(struct descr_generic_header *)des; // printf("Type: %s\n", decode_descr(desc->descriptor_tag)); // printf("Length: %hhu\n", desc->descriptor_length); if(desc->descriptor_tag==0x48) { // printf("Found service descriptor\n"); parseServiceDescriptor((const char *)desc, s); } else if(desc->descriptor_tag==0x4b) { // printf("Found NVOD reference descriptor\n"); parseNVODreferenceDescriptor((const char *)desc, s); } else if(desc->descriptor_tag==0x5f) { // printf("Found Private Data Specifier\n"); parsePrivateDataDescriptor((const char *)desc, s); } // hotfix for ARD crash if ((int) lendescriptor_length+2) break; len-=desc->descriptor_length+2; des+=desc->descriptor_length+2; } } // Die infos aus dem Puffer holen void SIsectionSDT::parse(void) { const char *actPos; const char *bufEnd; struct sdt_service *sv; unsigned short descriptors_loop_length; if (!buffer || parsed) return; if (bufferLength < sizeof(SI_section_SDT_header) + sizeof(struct sdt_service)) { bufferLength=0; return; } actPos = buffer + sizeof(SI_section_SDT_header); bufEnd = buffer + bufferLength; while (actPos <= bufEnd - sizeof(struct sdt_service)) { sv = (struct sdt_service *)actPos; SIservice s(sv); s.original_network_id = original_network_id(); s.transport_stream_id = transport_stream_id(); descriptors_loop_length = sizeof(struct sdt_service) + ((sv->descriptors_loop_length_hi << 8) | sv->descriptors_loop_length_lo); //printf("actpos: %p buf+bl: %p sid: %hu desclen: %hu\n", actPos, buffer+bufferLength, sv->service_id, sv->descriptors_loop_length); parseDescriptors(actPos, min((unsigned)(bufEnd - actPos), descriptors_loop_length), s); svs.insert(s); actPos += descriptors_loop_length; } parsed = 1; } #ifdef UPDATE_NETWORKS /************************************/ /* //Within the Service List all Channels of a bouquet are specified int SIsectionBAT::parseServiceListDescriptor(const char *buf, SIbouquet &s, int section_no, int count) { struct descr_generic_header *sv=(struct descr_generic_header *)buf; buf+=sizeof(struct descr_generic_header); unsigned short len = sv->descriptor_length; while(len >= sizeof(struct service_list_entry)) { struct service_list_entry *sl=(struct service_list_entry *)buf; buf+=sizeof(struct service_list_entry); SIbouquet bs(s); bs.service_id=(sl->service_id_hi << 8) | sl->service_id_lo; bs.serviceTyp=sl->service_type; bs.position = (uint16_t) (((section_no & 0x1f) << 11) + (count & 0x7ff)); // printf("Section Number: %d Count: %d position: %04x\n", section_no, count, bs.position); bsv.insert(bs); len -= sizeof(struct service_list_entry); count++; } return count; } void SIsectionBAT::parseBouquetNameDescriptor(const char *buf, SIbouquet &s) { struct descr_generic_header *sv=(struct descr_generic_header *)buf; buf+=sizeof(struct descr_generic_header); if(sv->descriptor_length) { // if(*buf < 0x06) // other code table // s.bouquetName=std::string(buf+1, sv->descriptor_length-1); //else //s.bouquetName=std::string(buf, sv->descriptor_length); s.bouquetName = CDVBString((const char *)(buf), sv->descriptor_length).getContent(); } //printf("Bouquet-Name: %s\n", s.bouquetName.c_str()); } int SIsectionBAT::parseDescriptors(const char *des, unsigned len, SIbouquet &s, int section_no, int count, const char *bouquetName) { struct descr_generic_header *desc; while(len>=sizeof(struct descr_generic_header)) { desc=(struct descr_generic_header *)des; // printf("Type: %s\n", decode_descr(desc->descriptor_tag)); // printf("Length: %hhu\n", desc->descriptor_length); if(desc->descriptor_tag==0x41) { // printf("Found service list descriptor\n"); count = parseServiceListDescriptor((const char *)desc, s, section_no, count); } // else if(desc->descriptor_tag==0x47) { // printf("Found bouquet name descriptor\n"); // parseBouquetNameDescriptor((const char *)desc, s); // } len-=desc->descriptor_length+2; des+=desc->descriptor_length+2; } return count; } */ // Die infos aus dem Puffer holen void SIsectionBAT::parse(void) { const char *actPos; struct bat_service *sv; // struct bouquet_ident bi; struct SI_section_BAT_header *bh; unsigned short descriptors_loop_length; unsigned short descriptors_length; uint32_t current_private_data_specifier; struct loop_len *ll; // std::string bouquetName = ""; if (!buffer || parsed) return; if (bufferLength < sizeof(SI_section_BAT_header) + sizeof(struct bat_service)) { printf("BAT fix?\n"); //No Services possible - length too short bufferLength=0; return; } actPos = &buffer[0]; // We need Bouquet ID and bouquet descriptor length from header bh = (struct SI_section_BAT_header *)actPos; // Header t_bouquet_id bouquet_id = (bh->bouquet_id_hi << 8) | bh->bouquet_id_lo; // printf("hi: %hu lo: %hu\n", bh->bouquet_descriptors_length_hi, bh->bouquet_descriptors_length_lo); descriptors_loop_length = (bh->bouquet_descriptors_length_hi << 8) | bh->bouquet_descriptors_length_lo; // SIbouquet s((bh->bouquet_id_hi << 8) | bh->bouquet_id_lo); //Create a new Bouquet entry // printf("ident: %hu actpos: %p buf+bl: %p desclen: %hu\n", bi.bouquet_id, actPos, buffer+bufferLength, descriptors_loop_length); int count = 0; //Fill out Bouquet Name //count = parseDescriptors(((const char *)bh) + sizeof(SI_section_BAT_header), descriptors_loop_length, s, bh->section_number, count); const char *des = ((const char *)bh) + sizeof(SI_section_BAT_header); unsigned len = descriptors_loop_length; struct descr_generic_header *desc; struct descr_generic_header *privdesc = NULL; std::string bouquetName = ""; current_private_data_specifier = 0; while(len>=sizeof(struct descr_generic_header)) { desc=(struct descr_generic_header *)des; if(desc->descriptor_tag==0x47) { // printf("Found bouquet name descriptor\n"); //parseBouquetNameDescriptor((const char *)desc, s); const char *buf = (const char *) desc; //struct descr_generic_header *sv=(struct descr_generic_header *)buf; buf+=sizeof(struct descr_generic_header); if(desc->descriptor_length) { /* if(*buf < 0x06) // other code table s.bouquetName=std::string(buf+1, sv->descriptor_length-1); else s.bouquetName=std::string(buf, sv->descriptor_length); */ //Mega stupid providers do not reserve their own bouquet_id //So we do it for them... f*ck that's stupid too, but what else can we do... if (bouquet_id == 0x0001) { if (!strncmp((const char *) buf, "NOVA", 4)) bouquet_id = NOVA; if (!strncmp((const char *) buf, "CanalDigitaal", 13)) bouquet_id = CANALDIGITAAL; } bouquetName = CDVBString((const char *)(buf), desc->descriptor_length).getContent(); } } if (desc->descriptor_tag == 0x5f) { const char *buf = (const char *) desc; //struct descr_generic_header *sv=(struct descr_generic_header *)buf; buf+=sizeof(struct descr_generic_header); struct private_data_specifier *pds=(struct private_data_specifier *)buf; buf+=sizeof(struct private_data_specifier); current_private_data_specifier=(((pds->byte1 << 24) | (pds->byte2 << 16)) | (pds->byte3 << 8)) | pds->byte4; //printf("Private Data Specifier: %08x\n", current_private_data_specifier); } len-=desc->descriptor_length+2; des+=desc->descriptor_length+2; } //s.bouquetName = bouquetName; actPos += sizeof(SI_section_BAT_header) + descriptors_loop_length; ll = (struct loop_len *)actPos; descriptors_loop_length = (ll->descriptors_loop_length_hi << 8) | ll->descriptors_loop_length_lo; //len is not used at the moment // printf("desclen: %hu\n", descriptors_loop_length); actPos += sizeof(loop_len); if (bouquet_id != 0x0001) { while (actPos <= &buffer[bufferLength - sizeof(struct bat_service)]) { sv = (struct bat_service *)actPos; //s.transport_stream_id = (sv->transport_stream_id_hi << 8) | sv->transport_stream_id_lo; //s.original_network_id = (sv->original_network_id_hi << 8) | sv->original_network_id_lo; // s.position = (uint16_t) (((bh->section_number & 0x1f) << 11) + (count & 0x7ff)); // printf("Section Number: %d Count: %d position: %04x\n", bh->section_number, count, s.position); descriptors_length = (sv->descriptors_loop_length_hi << 8) | sv->descriptors_loop_length_lo; // Transport Stream Loop //count = parseDescriptors(((const char *)sv) + sizeof(struct bat_service), descriptors_length, s, bh->section_number, count, //(const char *) bouquetName[0]); bool found = false; int loop_count = 1; while (loop_count >= 0) { const char *des_ = ((const char *)sv) + sizeof(struct bat_service); len = descriptors_length; while(len>=sizeof(struct descr_generic_header)) { desc=(struct descr_generic_header *)des_; // printf("Type: %s\n", decode_descr(desc->descriptor_tag)); // printf("Length: %hhu\n", desc->descriptor_length); const char *buf = (const char *) desc; buf+=sizeof(struct descr_generic_header); unsigned short dlen = desc->descriptor_length; if ((desc->descriptor_tag==0x41) && (loop_count == 0) && (current_private_data_specifier != 0x00000002)) { // printf("Found service list descriptor\n"); //count = parseServiceListDescriptor((const char *)desc, s, section_no, count); //struct descr_generic_header *sv=(struct descr_generic_header *)buf; while(dlen >= sizeof(struct service_list_entry)) { struct service_list_entry *sl=(struct service_list_entry *)buf; buf+=sizeof(struct service_list_entry); SIbouquet bs(bouquet_id); bs.bouquetName = bouquetName; bs.transport_stream_id = (sv->transport_stream_id_hi << 8) | sv->transport_stream_id_lo; bs.original_network_id = (sv->original_network_id_hi << 8) | sv->original_network_id_lo; bs.service_id=(sl->service_id_hi << 8) | sl->service_id_lo; bs.serviceTyp=sl->service_type; bs.position = (uint16_t) (((bh->section_number & 0x1f) << 11) + (count & 0x7ff)); if (found) { const char *privbuf = (const char *) privdesc; privbuf+=sizeof(struct descr_generic_header); unsigned short privdlen = privdesc->descriptor_length; bool found_posi = false; int order_entry_size; order_entry_size = sizeof(struct digplus_order_entry); while ((privdlen >= order_entry_size) && (!found_posi)) { struct digplus_order_entry *oe = (struct digplus_order_entry *)privbuf; privbuf+=order_entry_size; /* printf("Search: %04x Service_id: %04x Posi:%04x\n", (sl->service_id_hi << 8) | sl->service_id_lo, (oe->service_id_hi << 8) | oe->service_id_lo, (oe->channel_number_hi << 8) | oe->channel_number_lo); */ if ( ((sl->service_id_hi << 8) | sl->service_id_lo) == ((oe->service_id_hi << 8) | oe->service_id_lo)) { bs.position = (oe->channel_number_hi << 8) | oe->channel_number_lo; /* printf("Found Search: %04x Service_id: %04x Posi:%04x\n", (sl->service_id_hi << 8) | sl->service_id_lo, current_service_id, current_channel_number); */ found_posi=true; } privdlen -= order_entry_size; } if (!found_posi) bs.position = 0xffff; } // printf("Section Number: %d Count: %d position: %04x\n", section_no, count, bs.position); //printf("Set Position: %04x\n",bs.position); bsv.insert(bs); dlen -= sizeof(struct service_list_entry); count++; } } if (desc->descriptor_tag == 0x5f) { struct private_data_specifier *pds=(struct private_data_specifier *)buf; buf+=sizeof(struct private_data_specifier); if ((pds->byte1 != 0) || (pds->byte2 != 0) || (pds->byte3 != 0) || (pds->byte4 != 0)) current_private_data_specifier=(((pds->byte1 << 24) | (pds->byte2 << 16)) | (pds->byte3 << 8)) | pds->byte4; //printf("Private Data Specifier: %08x\n", current_private_data_specifier); } if (desc->descriptor_tag == 0x81) { if (current_private_data_specifier == 0x55504300) { //printf("UPC Bouquet ordering descriptor found!\n"); privdesc = (struct descr_generic_header *)desc; found = true; } } if (desc->descriptor_tag == 0x82) { if ((current_private_data_specifier == 0x00000010) || (bouquet_id == 0x0021)) { //printf("TPS Bouquet ordering descriptor found!\n"); privdesc = (struct descr_generic_header *)desc; found = true; } } if (desc->descriptor_tag == 0x83) { if ((current_private_data_specifier == 0x000000c0) || (current_private_data_specifier == 0x0000003a)) { //printf("Canal+ Bouquet ordering descriptor found!\n"); privdesc = (struct descr_generic_header *)desc; found = true; } } if (desc->descriptor_tag == 0x93) { if ((current_private_data_specifier == 0x00362275) || (bouquet_id == CANALDIGITAAL)) { //printf("Irdeto Bouquet ordering descriptor found!\n"); privdesc = (struct descr_generic_header *)desc; found = true; } } if ((desc->descriptor_tag == 0xb1) && (loop_count == 0)) { if (current_private_data_specifier == 0x00000002) { //printf("BSkyB Bouquet ordering descriptor found!\n"); const char *privbuf = (const char *) desc; privbuf+=sizeof(struct descr_generic_header); unsigned short privdlen = desc->descriptor_length - 2; //Nirvana 27.4.06: first 2 bytes still unknown: always 0xffff on sky italia? //check if resulting bouquets on 28.2E look more sensible... struct bskyb_bid *bid = (struct bskyb_bid *)privbuf; if ((bid->unknown1 == 0xff) && (bid->unknown2 == 0xff)) { privbuf+=2; //first 2 bytes of each 0xb1 desc unknown while (privdlen >= sizeof(struct bskyb_order_entry)) { struct bskyb_order_entry *oe = (struct bskyb_order_entry *)privbuf; privbuf+=sizeof(struct bskyb_order_entry); SIbouquet bs(bouquet_id); bs.bouquetName = bouquetName; bs.transport_stream_id = (sv->transport_stream_id_hi << 8) | sv->transport_stream_id_lo; bs.original_network_id = (sv->original_network_id_hi << 8) | sv->original_network_id_lo; bs.service_id = (oe->service_id_hi << 8) | oe->service_id_lo; bs.serviceTyp = oe->service_type; bs.position = (oe->channel_number_hi << 8) | oe->channel_number_lo; bsv.insert(bs); privdlen -= sizeof(struct bskyb_order_entry); } } } } len-=desc->descriptor_length+2; des_+=desc->descriptor_length+2; } loop_count--; } actPos += sizeof(struct bat_service) + descriptors_length; // count++; } } parsed = 1; } void SIsectionNIT::copyDeliveryDescriptor(const char *buf, SInetwork &s) { //struct descr_generic_header *sv=(struct descr_generic_header *)buf; buf+=sizeof(struct descr_generic_header); memcpy(s.delivery_descriptor, buf, sizeof(struct satellite_delivery_descriptor)); //same size as cable... //printf("Bouquet-Name: %s\n", s.bouquetName.c_str()); } void SIsectionNIT::parseDescriptors(const char *des, unsigned len, SInetwork &s) { // struct satellite_delivery_descriptor *sdd; // const char *ddp; // t_transport_stream_id tsid; // t_original_network_id onid; // unsigned short orbital_pos; struct descr_generic_header *desc; des += sizeof(struct nit_transponder); len -= sizeof(struct nit_transponder); while(len>=sizeof(struct descr_generic_header)) { desc=(struct descr_generic_header *)des; // printf("Type: %s\n", decode_descr(desc->descriptor_tag)); // printf("Length: %hhu\n", desc->descriptor_length); if ( (desc->descriptor_tag==0x43) || (desc->descriptor_tag==0x44) ) { s.delivery_type = desc->descriptor_tag; // printf("Found satellite_delivery_system_descriptor\n"); copyDeliveryDescriptor((const char *)desc, s); // ddp = &s.delivery_descriptor[0]; // sdd = (struct satellite_delivery_descriptor *)ddp; // tsid = s.transport_stream_id; // onid = s.original_network_id; // orbital_pos = (sdd->orbital_pos_hi << 8) | sdd->orbital_pos_lo; // printf("ONID: %04x TSID: %04x Orbital Position: %d\n", onid, tsid, orbital_pos); } len-=desc->descriptor_length+2; des+=desc->descriptor_length+2; } } // Die infos aus dem Puffer holen void SIsectionNIT::parse(void) { const char *actPos; const char *bufEnd; struct nit_transponder *tp; struct SI_section_NIT_header *nh; unsigned short descriptors_loop_length; unsigned short descriptors_length; struct loop_len *ll; //t_network_id network_id; if (!buffer || parsed) return; if (bufferLength < sizeof(SI_section_NIT_header) + sizeof(struct nit_transponder)) { printf("NIT fix?\n"); //No Services possible - length too short bufferLength=0; return; } actPos = buffer; // We need Bouquet ID and bouquet descriptor length from header bufEnd = buffer + bufferLength; nh = (struct SI_section_NIT_header *)actPos; // Header // printf("hi: %hu lo: %hu\n", bh->bouquet_descriptors_length_hi, bh->bouquet_descriptors_length_lo); descriptors_loop_length = (nh->network_descriptors_length_hi << 8) | nh->network_descriptors_length_lo; // SIbouquet s((bh->bouquet_id_hi << 8) | bh->bouquet_id_lo); //Create a new Bouquet entry // printf("ident: %hu actpos: %p buf+bl: %p desclen: %hu\n", bi.bouquet_id, actPos, buffer+bufferLength, descriptors_loop_length); // parseDescriptors(((const char *)bh) + sizeof(SI_section_BAT_header), descriptors_loop_length, s); //Fill out Bouquet Name actPos += sizeof(SI_section_NIT_header) + descriptors_loop_length; ll = (struct loop_len *)actPos; descriptors_loop_length = (ll->descriptors_loop_length_hi << 8) | ll->descriptors_loop_length_lo; //len is not used at the moment // printf("desclen: %hu\n", descriptors_loop_length); actPos += sizeof(loop_len); while (actPos <= bufEnd - sizeof(struct nit_transponder)) { tp = (struct nit_transponder *)actPos; SInetwork s(tp); s.network_id = (nh->network_id_hi << 8) | nh->network_id_lo; s.transport_stream_id = (tp->transport_stream_id_hi << 8) | tp->transport_stream_id_lo; s.original_network_id = (tp->original_network_id_hi << 8) | tp->original_network_id_lo; descriptors_length = sizeof(struct nit_transponder) + ((tp->descriptors_loop_length_hi << 8) | tp->descriptors_loop_length_lo); parseDescriptors(actPos, min((unsigned)(bufEnd - actPos), descriptors_length), s); // Transport Stream Loop ntw.insert(s); actPos += descriptors_length; } parsed = 1; } #endif #ifndef DO_NOT_INCLUDE_STUFF_NOT_NEEDED_FOR_SECTIONSD // Liest n Bytes aus einem Socket per read // Liefert 0 bei timeout // und -1 bei Fehler // ansonsten die Anzahl gelesener Bytes inline int readNbytes(int fd, char *buf, int n, unsigned timeoutInSeconds) { int j; for(j=0; j szeit + (long)timeoutInSeconds) { close(fd); return 0; // timeout -> kein EPG } int rc = readNbytes(fd, (char *)&header, sizeof(header), timeoutInSeconds); if(!rc) { close(fd); return 0; // timeout -> kein EPG } else if(rc<0) { close(fd); //perror ("read header"); return 3; } section_length = (header.section_length_hi << 8) | header.section_length_lo; buf = new char[sizeof(header) + section_length - 5]; if (!buf) { close(fd); fprintf(stderr, "Not enough memory!\n"); return 4; } // Den Header kopieren memcpy(buf, &header, sizeof(header)); rc = readNbytes(fd, &buf[sizeof(header)], section_length - 5, timeoutInSeconds); if (!rc) { close(fd); delete[] buf; return 0; // timeout -> kein EPG } else if (rc<0) { close(fd); //perror ("read section"); delete[] buf; return 5; } if ((readNext) || (header.current_next_indicator)) { // Wir wollen nur aktuelle sections insert(SIsection(sizeof(header) + section_length - 5, buf)); firstKey = SIsection::key(&header); // Sonderfall: Nur eine Section // d.h. wir sind fertig if ((!header.section_number) && (!header.last_section_number)) { close(fd); return 0; } } else { delete[] buf; } } while (firstKey == (uint64_t) -1); // Die restlichen Segmente lesen szeit = time(NULL); for (;;) { if (time(NULL) > szeit + (long)timeoutInSeconds) break; // timeout int rc = readNbytes(fd, (char *)&header, sizeof(header), timeoutInSeconds); if(!rc) break; // timeout else if(rc<0) { close(fd); //perror ("read header"); return 6; } if (firstKey==SIsection::key(&header)) // Wir haben die 1. section wieder gefunden break; section_length = (header.section_length_hi << 8) | header.section_length_lo; buf = new char[sizeof(header) + section_length - 5]; if (!buf) { close(fd); fprintf(stderr, "Not enough memory!\n"); return 7; } // Den Header kopieren (evtl. malloc und realloc nehmen) memcpy(buf, &header, sizeof(header)); // den Rest der Section einlesen rc = readNbytes(fd, &buf[sizeof(header)], section_length - 5, timeoutInSeconds); if (!rc) { delete[] buf; break; // timeout } else if (rc < 0) { close(fd); delete[] buf; //perror ("read section"); return 8; } if ((readNext) || (header.current_next_indicator)) insert(SIsection(sizeof(header) + section_length - 5, buf)); else delete[] buf; } close(fd); #ifdef DEBUG // Die Sections ausgeben printf("----------------Found sections-----------------------\n"); // for_each(begin(), end(), printSIsection()); for_each(begin(), end(), printSIsectionEIT()); printf("-----------------------------------------------------\n"); #endif // DEBUG // Jetzt erstellen wir eine Liste der fehlenden Sections unsigned short actualTableIDextension = (unsigned short) -1; unsigned char actualTableID = (unsigned char) -1; unsigned char maxNr = 0; unsigned char lastNr = 0; for (SIsections::iterator k = begin(); k != end(); k++) { if ((k->tableIDextension() != actualTableIDextension) || (k->tableID() != actualTableID)) { // Neue Table-ID-Extension maxNr = k->lastSectionNumber(); actualTableIDextension = k->tableIDextension(); actualTableID = k->tableID(); } else if (k->sectionNumber() != (unsigned char)(lastNr + 1)) { // Es fehlen Sections for (unsigned l = lastNr + 1; l < k->sectionNumber(); l++) { //printf("Debug: t: 0x%02x s: %u nr: %u last: %u max: %u l: %u\n", actualTableID, actualTableIDextension, k->sectionNumber(), lastNr, maxNr, l); struct SI_section_header h; memcpy(&h, k->header(), sizeof(struct SI_section_header)); h.section_number = l; missingSections.insert(SIsection(&h)); } } lastNr = k->sectionNumber(); } #ifdef DEBUG printf("Sections read: %d\n\n", size()); #endif // DEBUG if (!missingSections.size()) return 0; #ifdef DEBUG printf("----------------Missing sections---------------------\n"); for_each(missingSections.begin(), missingSections.end(), printSmallSIsectionHeader()); printf("-----------------------------------------------------\n"); printf("Sections read: %d\n\n", size()); printf("Sections misssing: %d\n", missingSections.size()); printf("Searching missing sections\n"); #endif // DEBUG szeit = time(NULL); if ((fd = open(DEMUX_DEVICE, O_RDWR)) == -1) { perror(DEMUX_DEVICE); return 9; } if (!setfilter(fd, pid, filter, mask, DMX_IMMEDIATE_START | DMX_CHECK_CRC)) { close(fd); return 10; } // Jetzt lesen wir die fehlenden Sections ein for(;;) { if (time(NULL) > szeit + (long)timeoutInSeconds) break; // Timeout int rc = readNbytes(fd, (char *)&header, sizeof(header), timeoutInSeconds); if(!rc) break; // timeout else if (rc < 0) { close(fd); //perror ("read header"); return 11; } section_length = (header.section_length_hi << 8) | header.section_length_lo; buf = new char[sizeof(header) + section_length - 5]; if (!buf) { close(fd); fprintf(stderr, "Not enough memory!\n"); return 12; } // Den Header kopieren (evtl. malloc und realloc nehmen) memcpy(buf, &header, sizeof(header)); // den Rest der Section einlesen rc = readNbytes(fd, &buf[sizeof(header)], section_length - 5, timeoutInSeconds); if (!rc) { delete[] buf; break; // timeout } else if (rc < 0) { close(fd); delete[] buf; //perror ("read section"); return 13; } if (missingSections.find(SIsection(&header)) != missingSections.end()) { #ifdef DEBUG printf("Find missing section:"); SIsection::dumpSmallSectionHeader(&header); #endif // DEBUG // War bisher vermisst // In die Menge einfuegen insert(SIsection(sizeof(header) + section_length - 5, buf)); // Und aus der vermissten Menge entfernen missingSections.erase(SIsection(&header)); #ifdef DEBUG printf("Sections misssing: %d\n", missingSections.size()); #endif // DEBUG } else { // Puffer wieder loeschen delete[] buf; } } close(fd); return 0; } #endif