📄 siparser.cpp
字号:
SIPARSER("DSM-CC normal play time (NPT) reference descriptor"); break; case 0x18: // DSM-CC normal play time (NPT) endpoint descriptor SIPARSER("DSM-CC normal play time (NPT) endpoint descriptor"); break; case 0x19: // DSM-CC stream mode descriptor SIPARSER("DSM-CC stream mode descriptor"); break; case 0x1a: // DSM-CC stream event descriptor SIPARSER("DSM-CC stream event descriptor"); break; case 0x52: // stream identifier descriptor // We use this to associate PIDs in this PMT with component_tags, // which lets us know if a stream contains DDBs of intereset. // Marginally useful at best, but since it's here I bit the bullet. ParseDescriptorStreamIdentifier(descriptor, descriptor_len, e.PID); break; case 0x66: // data broadcast id descriptor // This allows us to discover auto-boot carousels. // It also denotes the presence of a carousel in the first place, // but we already know that from the carousel_id descriptor. ParseDescriptorDataBroadcastId(descriptor, descriptor_len); break; // --- END: changes by PJ --- case 0x56: // Teletext Descriptor ParseDescriptorTeletext(descriptor, descriptor_len); e.Type = ES_TYPE_TELETEXT; break; case 0x59: // Subtitling Descriptor ParseDescriptorSubtitling(descriptor, descriptor_len); e.Type = ES_TYPE_SUBTITLE; break; case 0x6A: // AC3 Descriptor SIPARSER(QString("AC3 Descriptor")); e.Type = ES_TYPE_AUDIO_AC3; break; default: SIPARSER(QString("Unknown descriptor, tag = %1").arg(descriptor_tag)); break; } } pos += descriptor_len + 2; } switch (e.Type) { case ES_TYPE_VIDEO_MPEG1: e.Description = QString("MPEG-1 Video"); p.hasVideo = true; break; case ES_TYPE_VIDEO_MPEG2: e.Description = QString("MPEG-2 Video"); p.hasVideo = true; break; case ES_TYPE_AUDIO_MPEG1: e.Description = QString("MPEG-1 Audio"); p.hasAudio = true; break; case ES_TYPE_AUDIO_MPEG2: e.Description = QString("MPEG-2 Audio"); p.hasAudio = true; break; case ES_TYPE_AUDIO_AC3: e.Description = QString("AC3 Audio"); p.hasAudio = true; break; case ES_TYPE_AUDIO_DTS: e.Description = QString("DTS Audio"); p.hasAudio = true; break; case ES_TYPE_AUDIO_AAC: e.Description = QString("AAC Audio"); p.hasAudio = true; break; case ES_TYPE_TELETEXT: e.Description = QString("Teletext"); break; case ES_TYPE_SUBTITLE: e.Description = QString("Subtitle"); break; case ES_TYPE_DATA: e.Description = QString("Data"); break; default: e.Description = QString("Unknown type: %1").arg(e.Orig_Type); break; } if (!e.Language.isEmpty()) e.Description += QString(" (%1").arg(e.Language); p.Components += e; } ((PMTHandler*) Table[PMT])->pmt[head->table_id_ext] = p;}void SIParser::ProcessUnknownDescriptor(uint8_t* buf, int len){ QString temp = "Unknown Descriptor: "; for (int x=0;x<len;x++) temp += QString("%1 ").arg(buf[x],2,16); SIPARSER(temp);}/*------------------------------------------------------------------------ * COMMON HELPER FUNCTIONS *------------------------------------------------------------------------*/// Decode a text string according to ETSI EN 300 468 Annex AQString SIParser::DecodeText(uint8_t *s, int length){ QString result; if (length <= 0) return QString(""); if ((*s < 0x10) || (*s >= 0x20)) { // Strip formatting characters for (int p = 0; p < length; p++) if ((s[p] >= 0x80) && (s[p] <= 0x9F)) memmove(s + p, s + p + 1, --length - p); if (*s >= 0x20) { result = QString::fromLatin1((const char*) s, length); } else if ((*s >= 0x01) && (*s <= 0x0B)) { QString coding = "ISO8859-" + QString::number(4 + *s); QTextCodec *codec = QTextCodec::codecForName(coding); result = codec->toUnicode((const char*) s + 1, length - 1); } else { // Unknown/invalid encoding - assume local8Bit result = QString::fromLocal8Bit((const char*) s + 1, length - 1); } } else { // TODO: Handle multi-byte encodings SIPARSER("Multi-byte coded text - not yet supported!"); result = "N/A"; } return result;}/*------------------------------------------------------------------------ * DVB HELPER FUNCTIONS *------------------------------------------------------------------------*/QDateTime SIParser::ConvertDVBDate(uint8_t* dvb_buf){// TODO: clean this up some since its sort of a mess right now // This function taken from dvbdate.c in linuxtv-apps code int i; int year, month, day, hour, min, sec; long int mjd; mjd = (dvb_buf[0] & 0xff) << 8; mjd += (dvb_buf[1] & 0xff); hour = bcdtoint(dvb_buf[2] & 0xff); min = bcdtoint(dvb_buf[3] & 0xff); sec = bcdtoint(dvb_buf[4] & 0xff);/* * Use the routine specified in ETSI EN 300 468 V1.4.1, * "Specification for Service Information in Digital Video Broadcasting" * to convert from Modified Julian Date to Year, Month, Day. */ year = (int) ((mjd - 15078.2) / 365.25); month = (int) ((mjd - 14956.1 - (int) (year * 365.25)) / 30.6001); day = mjd - 14956 - (int) (year * 365.25) - (int) (month * 30.6001); if (month == 14 || month == 15) i = 1; else i = 0; year += i; month = month - 1 - i * 12; year += 1900; QDateTime UTCTime = QDateTime(QDate(year,month,day),QTime(hour,min,sec)); // Convert to localtime return MythUTCToLocal(UTCTime);}/*------------------------------------------------------------------------ * DVB TABLE PARSERS *------------------------------------------------------------------------*/void SIParser::ParseNIT(tablehead_t* head, uint8_t* buffer, int size){ // Only process current network NITs for now if (head->table_id != 0x40) return; // Check to see if you already pulled this table section if (Table[NETWORK]->AddSection(head,0,0)) return; // TODO: Emit a table load here for scanner TransportObject t; QMap_uint16_t ChannelNumbers; uint16_t network_descriptors_length = (buffer[0] & 0x0F) << 8 | buffer[1]; uint16_t transport_stream_loop_length = 0; uint16_t transport_descriptors_length = 0; uint16_t pos = 2; // Parse Network Descriptors (Name, Linkage) if (network_descriptors_length > 0) { // Create a Network Object NetworkObject n; while ((network_descriptors_length) > (pos-2)) { switch (buffer[pos]) { case 0x40: ParseDescriptorNetworkName(&buffer[pos],buffer[pos+1],n); break; case 0x4A: ParseDescriptorLinkage(&buffer[pos],buffer[pos+1],n); break; default: ProcessUnknownDescriptor(&buffer[pos],buffer[pos+1]); break; } pos += (buffer[pos+1] + 2); } ((NetworkHandler*) Table[NETWORK])->NITList.Network += n; } transport_stream_loop_length = (buffer[pos] & 0x0F) << 8 | buffer[pos+1]; pos += 2; // transport desctiptors parser uint16_t dpos = 0; // Safe to assume that you can run until the end while (pos < size - 4) { if (PrivateTypesLoaded == false) { t.NetworkID = buffer[pos+2] << 8 | buffer[pos+3]; LoadPrivateTypes(t.NetworkID); } transport_descriptors_length = (buffer[pos+4] & 0x0F) << 8 | buffer[pos+5]; dpos=0; while ((transport_descriptors_length) > (dpos)) { switch (buffer[pos + 6 + dpos]) { // DVB-C - Descriptor Parser written by Ian Caulfield case 0x44: t = ParseDescriptorCableDeliverySystem( &buffer[pos + 6 + dpos],buffer[pos + 7 + dpos]); break; // DVB-T - Verified thanks to adante in #mythtv allowing me access to his DVB-T card case 0x5A: t = ParseDescriptorTerrestrialDeliverySystem( &buffer[pos + 6 + dpos],buffer[pos + 7 + dpos]); break; // DVB-S case 0x43: t = ParseDescriptorSatelliteDeliverySystem( &buffer[pos + 6 + dpos],buffer[pos + 7 + dpos]); break; case 0x62: ParseDescriptorFrequencyList(&buffer[pos+6+dpos],buffer[pos + 7 + dpos],t); break; case 0x83: if (PrivateTypes.ChannelNumbers == 0x83) ParseDescriptorUKChannelList(&buffer[pos+6+dpos],buffer[pos + 7 + dpos], ChannelNumbers); break; default: ProcessUnknownDescriptor(&buffer[pos + 6 + dpos],buffer[pos + 7 + dpos]); break; } dpos += (buffer[pos + 7 + dpos] + 2); } // Get TransportID and NetworkID t.TransportID = buffer[pos] << 8 | buffer[pos+1]; t.NetworkID = buffer[pos+2] << 8 | buffer[pos+3]; Table[SERVICES]->Request(t.TransportID); if (PrivateTypes.ChannelNumbers && !(ChannelNumbers.empty())) { QMap_uint16_t::Iterator c; for (c = ChannelNumbers.begin() ; c != ChannelNumbers.end() ; ++c) ((ServiceHandler*) Table[SERVICES])->Services[t.TransportID][c.key()].ChanNum = c.data(); } ((NetworkHandler*) Table[NETWORK])->NITList.Transport += t; pos += transport_descriptors_length + 6; }}void SIParser::ParseSDT(tablehead_t* head, uint8_t* buffer, int size){ /* Signal to keep scan wizard bars moving */ emit TableLoaded(); int CurrentTransport = 0; uint16_t network_id = buffer[0] << 8 | buffer[1]; // TODO: Handle Network Specifics here if they aren't set if (PrivateTypesLoaded == false) LoadPrivateTypes(network_id); if (PrivateTypes.SDTMapping) { if (PrivateTypes.CurrentTransportID == head->table_id_ext) CurrentTransport = 1; } else { if (head->table_id == 0x42) CurrentTransport = 1; } if (CurrentTransport) { if (Table[SERVICES]->AddSection(head,0,0)) return; } else { if (Table[SERVICES]->AddSection(head,head->table_id_ext,0)) return; } uint16_t len = 0; uint16_t pos = 3; uint16_t lentotal = 0; uint16_t descriptors_loop_length = 0; SDTObject s; SIPARSER(QString("SDT: NetworkID=%1 TransportID=%2").arg(network_id).arg(head->table_id_ext)); while (pos < (size-4)) { s.ServiceID = buffer[pos] << 8 | buffer[pos+1]; s.TransportID = head->table_id_ext; s.NetworkID = network_id; s.EITPresent = PrivateTypes.ForceGuidePresent ? 1 : (buffer[pos+2] & 0x02) >> 1; s.RunningStatus = (buffer[pos+3] & 0xE0) >> 5; s.CAStatus = (buffer[pos+3] & 0x10) >> 4; s.Version = head->version; if(((ServiceHandler*) Table[SERVICES])->Services[s.TransportID].contains(s.ServiceID)) s.ChanNum = ((ServiceHandler*) Table[SERVICES])->Services[s.TransportID][s.ServiceID].ChanNum; descriptors_loop_length = (buffer[pos+3] & 0x0F) << 8 | buffer[pos+4]; lentotal = 0; while ((descriptors_loop_length) > (lentotal)) { switch(buffer[pos + 5 + lentotal]) { case 0x48: ParseDescriptorService(&buffer[pos + 5 + lentotal], buffer[pos + 6 + lentotal], s); break; default: ProcessUnknownDescriptor(&buffer[pos + 5 + lentotal], buffer[pos + 6 + lentotal]); break; } len = buffer[pos + 6 + lentotal]; lentotal += (len + 2); } bool eit_requested = false;#ifdef USING_DVB_EIT if ((s.EITPresent) && (s.ServiceType == 1) && ((!PrivateTypes.GuideOnSingleTransport) || ((PrivateTypes.GuideOnSingleTransport) && (PrivateTypes.GuideTransportID == PrivateTypes.CurrentTransportID)))) { Table[EVENTS]->RequestEmit(s.ServiceID); eit_requested = true; }#endif SIPARSER(QString("SDT: sid=%1 type=%2 eit_present=%3 eit_requested=%4 name=%5") .arg(s.ServiceID).arg(s.ServiceType) .arg(s.EITPresent).arg(eit_requested) .arg(s.ServiceName.ascii()));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -