int parse_nit(const t_satellite_position satellite_position, const unsigned char DiSEqC) { CDemux dmx; unsigned char buffer[NIT_SIZE]; /* position in buffer */ unsigned short pos; unsigned short pos2; /* network_information_section elements */ unsigned short section_length; unsigned short network_descriptors_length; unsigned short transport_descriptors_length; unsigned short transport_stream_loop_length; t_transport_stream_id transport_stream_id; t_original_network_id original_network_id; // unsigned short network_id; transponder_id_t transponder_id; unsigned char filter[DMX_FILTER_SIZE]; unsigned char mask[DMX_FILTER_SIZE]; memset(filter, 0x00, DMX_FILTER_SIZE); memset(mask, 0x00, DMX_FILTER_SIZE); filter[0] = 0x40; filter[4] = 0x00; mask[0] = 0xFF; mask[4] = 0xFF; do { if ((dmx.sectionFilter(0x10, filter, mask) < 0) || (dmx.read(buffer, NIT_SIZE) < 0)) return -1; section_length = ((buffer[1] & 0x0F) << 8) + buffer[2]; // network_id = ((buffer[3] << 8)| buffer [4]); network_descriptors_length = ((buffer[8] & 0x0F) << 8) | buffer[9]; for (pos = 10; pos < network_descriptors_length + 10; pos += buffer[pos + 1] + 2) { switch (buffer[pos]) { /* case 0x0F: Private_data_indicator_descriptor(buffer + pos); break; */ case 0x40: network_name_descriptor(buffer + pos); break; case 0x4A: linkage_descriptor(buffer + pos); break; case 0x5B: multilingual_network_name_descriptor(buffer + pos); break; /* case 0x5F: private_data_specifier_descriptor(buffer + pos); break; */ case 0x80: /* unknown, Eutelsat 13.0E */ break; case 0x90: /* unknown, Eutelsat 13.0E */ break; default: DBG("first_descriptor_tag: %02x", buffer[pos]); break; } } transport_stream_loop_length = ((buffer[pos] & 0x0F) << 8) | buffer[pos + 1]; if (!transport_stream_loop_length) continue; for (pos += 2; pos < section_length - 3; pos += transport_descriptors_length + 6) { transport_stream_id = (buffer[pos] << 8) | buffer[pos + 1]; original_network_id = (buffer[pos + 2] << 8) | buffer[pos + 3]; transport_descriptors_length = ((buffer[pos + 4] & 0x0F) << 8) | buffer[pos + 5]; // frequency will be inserted in satellite/cable_delivery_system_descriptor() transponder_id = CREATE_TRANSPONDER_ID_FROM_FREQUENCY_SATELLITEPOSITION_ORIGINALNETWORK_TRANSPORTSTREAM_ID(0, satellite_position,original_network_id,transport_stream_id); if (transponders.find(transponder_id) == transponders.end()) { for (pos2 = pos + 6; pos2 < pos + transport_descriptors_length + 6; pos2 += buffer[pos2 + 1] + 2) { switch (buffer[pos2]) { case 0x41: service_list_descriptor(buffer + pos2, transport_stream_id, original_network_id); break; case 0x42: stuffing_descriptor(buffer + pos2); break; case 0x43: if (satellite_delivery_system_descriptor(buffer + pos2, transponder_id, DiSEqC) < 0) return -2; break; case 0x44: if (cable_delivery_system_descriptor(buffer + pos2, transponder_id) < 0) return -2; break; case 0x5A: if (terrestrial_delivery_system_descriptor(buffer + pos2) < 0) return -2; break; case 0x5F: private_data_specifier_descriptor(buffer + pos2); break; case 0x62: frequency_list_descriptor(buffer + pos2); break; case 0x82: /* unknown, Eutelsat 13.0E */ break; default: DBG("second_descriptor_tag: %02x", buffer[pos2]); break; } } } } } while (filter[4]++ != buffer[7]); return 0; }
int parse_nit(t_satellite_position satellitePosition, freq_id_t freq) { int ret = 0; int secdone[255]; int sectotal = -1; for(int i = 0; i < 255; i++) secdone[i] = 0; cDemux * dmx = new cDemux();; dmx->Open(DMX_PSI_CHANNEL); unsigned char buffer[NIT_SIZE]; /* position in buffer */ unsigned short pos; unsigned short pos2; /* network_information_section elements */ unsigned short section_length; unsigned short network_descriptors_length; unsigned short transport_descriptors_length; unsigned short transport_stream_loop_length; t_transport_stream_id transport_stream_id; t_original_network_id original_network_id; unsigned short network_id; unsigned char filter[DMX_FILTER_SIZE]; unsigned char mask[DMX_FILTER_SIZE]; memset(filter, 0x00, DMX_FILTER_SIZE); memset(mask, 0x00, DMX_FILTER_SIZE); filter[0] = 0x40; //filter[4] = 0x00; mask[0] = 0xFF; //mask[4] = 0xFF; //unsigned char sec = 0x00; if (dmx->sectionFilter(0x10, filter, mask, 5) < 0) { delete dmx; return -1; } do { if (dmx->Read(buffer, NIT_SIZE) < 0) { delete dmx; return -1; } if(buffer[0] != 0x40) printf("[NIT] ******************************************* Bogus section received: 0x%x\n", buffer[0]); section_length = ((buffer[1] & 0x0F) << 8) + buffer[2]; network_id = ((buffer[3] << 8)| buffer [4]); network_descriptors_length = ((buffer[8] & 0x0F) << 8) | buffer[9]; unsigned char secnum = buffer[6]; printf("[NIT] section %X last %X network_id 0x%x -> %s\n", secnum, buffer[7], network_id, secdone[secnum] ? "skip" : "use"); if(secdone[secnum]) // mark sec XX done continue; secdone[secnum] = 1; sectotal++; for (pos = 10; pos < network_descriptors_length + 10; pos += buffer[pos + 1] + 2) { switch (buffer[pos]) { /* case 0x0F: Private_data_indicator_descriptor(buffer + pos); break; */ case 0x40: network_name_descriptor(buffer + pos); break; case 0x4A: linkage_descriptor(buffer + pos); break; case 0x5B: multilingual_network_name_descriptor(buffer + pos); break; /* case 0x5F: private_data_specifier_descriptor(buffer + pos); break; */ case 0x80: /* unknown, Eutelsat 13.0E */ break; case 0x90: /* unknown, Eutelsat 13.0E */ break; default: DBG("first_descriptor_tag: %02x\n", buffer[pos]); break; } } transport_stream_loop_length = ((buffer[pos] & 0x0F) << 8) | buffer[pos + 1]; if (!transport_stream_loop_length) continue; for (pos += 2; pos < section_length - 3; pos += transport_descriptors_length + 6) { transport_stream_id = (buffer[pos] << 8) | buffer[pos + 1]; original_network_id = (buffer[pos + 2] << 8) | buffer[pos + 3]; transport_descriptors_length = ((buffer[pos + 4] & 0x0F) << 8) | buffer[pos + 5]; //if (transponders.find((transport_stream_id << 16) | original_network_id) == transponders.end()) //if (scantransponders.find(CREATE_TRANSPONDER_ID_FROM_SATELLITEPOSITION_ORIGINALNETWORK_TRANSPORTSTREAM_ID(freq, satellitePosition, original_network_id, transport_stream_id)) == scantransponders.end()) { for (pos2 = pos + 6; pos2 < pos + transport_descriptors_length + 6; pos2 += buffer[pos2 + 1] + 2) { switch (buffer[pos2]) { case 0x41: service_list_descriptor(buffer + pos2, transport_stream_id, original_network_id, satellitePosition, freq); break; case 0x42: stuffing_descriptor(buffer + pos2); break; case 0x43: if (satellite_delivery_system_descriptor(buffer + pos2, transport_stream_id, original_network_id, satellitePosition, freq) < 0) { ret = -2; goto _return; } break; case 0x44: if (cable_delivery_system_descriptor(buffer + pos2, transport_stream_id, original_network_id, satellitePosition, freq) < 0) { ret = -2; goto _return; } break; case 0x5A: if (terrestrial_delivery_system_descriptor(buffer + pos2) < 0) { ret = -2; goto _return; } break; case 0x5F: private_data_specifier_descriptor(buffer + pos2); break; case 0x62: frequency_list_descriptor(buffer + pos2); break; case 0x82: /* unknown, Eutelsat 13.0E */ break; default: DBG("second_descriptor_tag: %02x\n", buffer[pos2]); break; } } } } } while(sectotal < buffer[7]); //} while (filter[4]++ != buffer[7]); _return: dmx->Stop(); delete dmx; return ret; }
unsigned short parse_ES_info(const unsigned char * const buffer, CZapitChannel * const channel, CCaPmt * const caPmt) { unsigned short ES_info_length; unsigned short pos; unsigned char descriptor_tag; unsigned char descriptor_length; unsigned char i; bool isAC3 = false; bool isDTS = false; bool isAAC = false; bool isDTSHD = false; bool isEAC3 = false; bool isAACPLUS = false; bool isLPCM = false; bool descramble = false; std::string description = ""; unsigned char componentTag = 0xFF; /* elementary stream info for ca pmt */ CEsInfo * esInfo = new CEsInfo(); esInfo->stream_type = buffer[0]; esInfo->reserved1 = buffer[1] >> 5; esInfo->elementary_PID = ((buffer[1] & 0x1F) << 8) | buffer[2]; esInfo->reserved2 = buffer[3] >> 4; ES_info_length = ((buffer[3] & 0x0F) << 8) | buffer[4]; for (pos = 5; pos < ES_info_length + 5; pos += descriptor_length + 2) { descriptor_tag = buffer[pos]; descriptor_length = buffer[pos + 1]; unsigned char fieldCount = descriptor_length / 5; switch (descriptor_tag) { case VIDEO_STREAM_DESCRIPTOR: video_stream_descriptor(buffer + pos); break; case AUDIO_STREAM_DESCRIPTOR: audio_stream_descriptor(buffer + pos); break; case REGISTRATION_DESCRIPTOR: if (descriptor_length >= 3) if (!strncmp((const char*)&buffer[pos + 2], "DTS", 3)) isDTS = true; break; case CA_DESCRIPTOR: esInfo->addCaDescriptor(buffer + pos); break; case ISO_639_LANGUAGE_DESCRIPTOR: for (i = 0; i < 3; i++) description += buffer[pos + i + 2]; break; case MAXIMUM_BITRATE_DESCRIPTOR: Maximum_bitrate_descriptor(buffer + pos); break; case PRIVATE_DATA_INDICATOR_DESCRIPTOR: Private_data_indicator_descriptor(buffer + pos); break; case STD_DESCRIPTOR: STD_descriptor(buffer + pos); break; case 0x1C: isAACPLUS = true; break; case 0x2B: isAAC = true; break; case CAROUSEL_IDENTIFIER_DESCRIPTOR: break; case VBI_DATA_DESCRIPTOR: VBI_data_descriptor(buffer + pos); break; case STREAM_IDENTIFIER_DESCRIPTOR: componentTag = buffer[pos + 2]; break; case TELETEXT_DESCRIPTOR: for (unsigned char fIdx = 0; fIdx < fieldCount; fIdx++) { char tmpLang[4]; memcpy(tmpLang, &buffer[pos + 5*fIdx + 2], 3); tmpLang[3] = '\0'; unsigned char teletext_type = buffer[pos + 5*fIdx + 5]>> 3; unsigned char teletext_magazine_number = buffer[pos + 5*fIdx + 5] & 7; unsigned char teletext_page_number = buffer[pos + 5*fIdx + 6]; if (teletext_type == 0x02) { channel->addTTXSubtitle(esInfo->elementary_PID, tmpLang, teletext_magazine_number, teletext_page_number); } else { if (teletext_type == 0x05) { channel->addTTXSubtitle(esInfo->elementary_PID, tmpLang, teletext_magazine_number, teletext_page_number, true); } } } channel->setTeletextPid(esInfo->elementary_PID); descramble = true;//FIXME ORF HD scramble txt ? break; case SUBTITLING_DESCRIPTOR: if (esInfo->stream_type == 0x06) { unsigned char fieldCount1 = descriptor_length/8; for (unsigned char fIdx = 0; fIdx < fieldCount1; fIdx++) { char tmpLang[4]; memcpy(tmpLang, &buffer[pos + 8*fIdx + 2], 3); tmpLang[3] = '\0'; unsigned char subtitling_type = buffer[pos + 8*fIdx + 5]; unsigned short composition_page_id = *((unsigned short*)(&buffer[pos + 8*fIdx + 6])); unsigned short ancillary_page_id = *((unsigned short*)(&buffer[pos + 8*fIdx + 8])); /*dvbsub */ channel->addDVBSubtitle(esInfo->elementary_PID, tmpLang, subtitling_type, composition_page_id, ancillary_page_id); } descramble = true;//FIXME MGM / 10E scrambling subtitles ? } subtitling_descriptor(buffer + pos); break; case PRIVATE_DATA_SPECIFIER_DESCRIPTOR: private_data_specifier_descriptor(buffer + pos); break; case DATA_BROADCAST_ID_DESCRIPTOR: data_broadcast_id_descriptor(buffer + pos); break; case AC3_DESCRIPTOR: isAC3 = true; break; case APPLICATION_SIGNALLING_DESCRIPTOR: channel->setaitPid(esInfo->elementary_PID); dprintf(DEBUG_NORMAL, "[pmt]parse_ES_info: channel->setaitPid(0x%x)\n", esInfo->elementary_PID); break; case ENHANCED_AC3_DESCRIPTOR: isEAC3 = true; break; case DTS_DESCRIPTOR: isDTS = true; break; case AAC_DESCRIPTOR: isAACPLUS = true; break; case 0xC5: for (i = 0; i < 24; i++) description += buffer[pos + i + 3]; break; default: dprintf(DEBUG_INFO, "[pmt]parse_ES_info: descriptor_tag: 0x%02x\n", descriptor_tag); break; } } switch (esInfo->stream_type) { case 0x01: // MPEG 1 video case 0x02: // MPEG 2 video case 0x1b: // AVC Video Stream (MPEG4 H264) case 0x10: // MPEG 4 Part 2 case 0x24: // H265 HEVC case 0x27: // H265 HEVC case 0x42: // CAVS channel->setVideoPid(esInfo->elementary_PID); descramble = true; if(esInfo->stream_type == 0x1b || esInfo->stream_type == 0x10) channel->videoType = CHANNEL_VIDEO_MPEG4; else if(esInfo->stream_type == 0x24 || esInfo->stream_type == 0x27) channel->videoType = CHANNEL_VIDEO_HEVC; else if(esInfo->stream_type == 0x42) channel->videoType = CHANNEL_VIDEO_CAVS; dprintf(DEBUG_NORMAL, "[pmt]parse_ES_info: vpid 0x%x stream 0x%02x type 0x%02x\n", esInfo->elementary_PID, esInfo->stream_type, channel->videoType); break; case 0x03: case 0x04: /* audio es_pids */ if (description == "") description = esInfo->elementary_PID; if(scan_runs) { if(channel->getPreAudioPid() == 0) channel->setAudioPid(esInfo->elementary_PID); } else channel->addAudioChannel(esInfo->elementary_PID, CZapitAudioChannel::MPEG, description, componentTag); descramble = true; dprintf(DEBUG_NORMAL, "[pmt]parse_ES_info: apid 0x%x %s\n", esInfo->elementary_PID, description.c_str()); break; case 0x05:// private section { int tmp = 0; // Houdini: shameless stolen from enigma dvbservices.cpp for (pos = 5; pos < ES_info_length + 5; pos += descriptor_length + 2) { descriptor_tag = buffer[pos]; descriptor_length = buffer[pos + 1]; switch (descriptor_tag) { case 0x5F: //DESCR_PRIV_DATA_SPEC: if ( ((buffer[pos + 2]<<24) | (buffer[pos + 3]<<16) | (buffer[pos + 4]<<8) | (buffer[pos + 5])) == 190 ) tmp |= 1; break; case 0x90: { if ( descriptor_length == 4 && !buffer[pos + 2] && !buffer[pos + 3] && buffer[pos + 4] == 0xFF && buffer[pos + 5] == 0xFF ) tmp |= 2; } //break;?? case APPLICATION_SIGNALLING_DESCRIPTOR: channel->setaitPid(esInfo->elementary_PID); dprintf(DEBUG_NORMAL, "[pmt]0x05:parse_ES_info: channel->setaitPid(0x%x)\n", esInfo->elementary_PID); break; default: break; } } if ( tmp == 3 ) { channel->setPrivatePid(esInfo->elementary_PID); dprintf(DEBUG_NORMAL, "[pmt]parse_ES_info: channel->setPrivatePid(0x%x)\n", esInfo->elementary_PID); } descramble = true; break; } case 0x81: // AC3 case 0xA1: // bluray secondary AC3 esInfo->stream_type = 0x6; if (description == "") description = esInfo->elementary_PID; description += " (AC3)"; isAC3 = true; descramble = true; if(!scan_runs) channel->addAudioChannel(esInfo->elementary_PID, CZapitAudioChannel::AC3, description, componentTag); dprintf(DEBUG_NORMAL, "[pmt]parse_ES_info: apid 0x%x %s\n", esInfo->elementary_PID, description.c_str()); break; case 0x06: if ( (isAC3) || (isDTS) || (isAAC) || (isAACPLUS) || (isEAC3)) { if (description == "") { description = esInfo->elementary_PID; if (isAC3) description += " (AC3)"; else if (isDTS) description += " (DTS)"; else if (isAAC) description += " (AAC)"; else if (isAACPLUS) description += " (AACPLUS)"; else if (isEAC3) description += " (EAC3)"; } if(!scan_runs) { CZapitAudioChannel::ZapitAudioChannelType Type; if (isAC3) Type = CZapitAudioChannel::AC3; else if (isDTS) Type = CZapitAudioChannel::DTS; else if (isAAC) Type = CZapitAudioChannel::AAC; else if (isAACPLUS) Type = CZapitAudioChannel::AACPLUS; else if (isEAC3) Type = CZapitAudioChannel::EAC3; else Type = CZapitAudioChannel::UNKNOWN; channel->addAudioChannel(esInfo->elementary_PID, Type, description, componentTag); } descramble = true; dprintf(DEBUG_NORMAL, "[pmt]parse_ES_info: apid 0x%x %s\n", esInfo->elementary_PID, description.c_str()); } break; case 0x0F: // AAC if (description == "") description = esInfo->elementary_PID; description += " (AAC)"; isAAC = true; descramble = true; if(!scan_runs) channel->addAudioChannel(esInfo->elementary_PID, CZapitAudioChannel::AAC, description, componentTag); dprintf(DEBUG_NORMAL, "[pmt]parse_ES_info: apid 0x%x %s\n", esInfo->elementary_PID, description.c_str()); break; case 0x11: // AACPLUS if (description == "") description = esInfo->elementary_PID; description += " (AACPLUS)"; isAACPLUS = true; descramble = true; if(!scan_runs) channel->addAudioChannel(esInfo->elementary_PID, CZapitAudioChannel::AACPLUS, description, componentTag); dprintf(DEBUG_NORMAL, "[pmt]parse_ES_info: apid 0x%x %s\n", esInfo->elementary_PID, description.c_str()); break; case 0x80: // user private ... but bluray LPCM case 0xA0: // bluray secondary LPCM if (description == "") description = esInfo->elementary_PID; description += " (LPCM)"; isLPCM = true; descramble = true; if(!scan_runs) channel->addAudioChannel(esInfo->elementary_PID, CZapitAudioChannel::LPCM, description, componentTag); dprintf(DEBUG_NORMAL, "[pmt]parse_ES_info: apid 0x%x %s\n", esInfo->elementary_PID, description.c_str()); break; case 0x82: // bluray DTS (dvb user private...) case 0xA2: // bluray secondary DTS if (description == "") description = esInfo->elementary_PID; description += " (DTS)"; isDTS = true; descramble = true; if(!scan_runs) channel->addAudioChannel(esInfo->elementary_PID, CZapitAudioChannel::DTS, description, componentTag); dprintf(DEBUG_NORMAL, "[pmt]parse_ES_info: apid 0x%x %s\n", esInfo->elementary_PID, description.c_str()); break; case 0x85: // bluray DTS-HD HRA(dvb user private...) case 0x86: // bluray DTS-HD MA(dvb user private...) case 0xA6: // bluray secondary DTS-HD if (description == "") description = esInfo->elementary_PID; description += " (DTSHD)"; isDTSHD = true; descramble = true; if(!scan_runs) channel->addAudioChannel(esInfo->elementary_PID, CZapitAudioChannel::DTSHD, description, componentTag); dprintf(DEBUG_NORMAL, "[pmt]parse_ES_info: apid 0x%x %s\n", esInfo->elementary_PID, description.c_str()); break; default: dprintf(DEBUG_NORMAL, "[pmt]parse_ES_info: stream_type: 0x%02x\n", esInfo->stream_type); break; } if (descramble) caPmt->es_info.insert(caPmt->es_info.end(), esInfo); else delete esInfo; return ES_info_length; }