bool CBat::Parse() { printf("[scan] trying to parse BAT\n"); if(!Read()) return false; sections.sort(compare_section_num); BouquetAssociationSectionConstIterator sit; for (sit = sections.begin(); sit != sections.end(); ++sit) { BouquetAssociationSection * bat = *sit; uint16_t bouquet_id = bat->getTableIdExtension(); if (CServiceScan::getInstance()->Aborted()) return false; const DescriptorList * dlist = bat->getDescriptors(); DescriptorConstIterator dit; #ifdef DEBUG_BAT printf("BAT: section %d, %d descriptors\n", bat->getSectionNumber(), (int)dlist->size()); #endif unsigned int pdsd = 0; for (dit = dlist->begin(); dit != dlist->end(); ++dit) { Descriptor * d = *dit; //printf("BAT: parse descriptor %02x len %d\n", d->getTag(), d->getLength()); switch(d->getTag()) { case BOUQUET_NAME_DESCRIPTOR: { BouquetNameDescriptor * nd = (BouquetNameDescriptor *) d; /*std::string*/ bouquetName = stringDVBUTF8(nd->getBouquetName()); printf("BAT: bouquet name [%s]\n", bouquetName.c_str()); } break; case LINKAGE_DESCRIPTOR: { #ifdef DEBUG_BAT LinkageDescriptor * ld = (LinkageDescriptor*) d; printf("BAT: linkage, tsid %04x onid %04x sid %04x type %02x\n", ld->getTransportStreamId(), ld->getOriginalNetworkId(), ld->getServiceId(), ld->getLinkageType()); #endif } break; case PRIVATE_DATA_SPECIFIER_DESCRIPTOR: { PrivateDataSpecifierDescriptor * pd = (PrivateDataSpecifierDescriptor *)d; pdsd = pd->getPrivateDataSpecifier(); #ifdef DEBUG_BAT printf("BAT: private data specifier %08x\n", pdsd); #endif } break; case COUNTRY_AVAILABILITY_DESCRIPTOR: default: { #ifdef DEBUG_BAT_UNUSED printf("BAT: descriptor %02x: ", d->getTag()); uint8_t len = 2+d->getLength(); uint8_t *buf = new uint8_t[len]; if(buf){ d->writeToBuffer(buf); for(uint8_t i = 0; i < len; i++) printf("%02x ", buf[i]); printf("\n"); delete []buf; } #endif } break; } } const BouquetAssociationList &blist = *bat->getBouquets(); BouquetAssociationConstIterator it; for(it = blist.begin(); it != blist.end(); ++it) { BouquetAssociation * b = *it; dlist = b->getDescriptors(); #if 1 printf("BAT: bouquet_id %04x tsid %04x onid %04x %d descriptors\n", bouquet_id, b->getTransportStreamId(), b->getOriginalNetworkId(), (int)dlist->size()); #endif for (dit = dlist->begin(); dit != dlist->end(); ++dit) { Descriptor * d = *dit; switch(d->getTag()) { case SERVICE_LIST_DESCRIPTOR: ParseServiceList((ServiceListDescriptor *) d, b); break; #if 1 case LOGICAL_CHANNEL_DESCRIPTOR: ParseLogicalChannels((LogicalChannelDescriptor *) d, b); break; #endif case PRIVATE_DATA_SPECIFIER_DESCRIPTOR: { PrivateDataSpecifierDescriptor * pd = (PrivateDataSpecifierDescriptor *)d; pdsd = pd->getPrivateDataSpecifier(); #ifdef DEBUG_BAT printf("BAT: private data specifier %08x\n", pdsd); #endif } break; default: { #ifdef DEBUG_BAT_UNUSED printf("BAT: descriptor %02x: ", d->getTag()); uint8_t len = 2+d->getLength(); uint8_t *buf = new uint8_t[len]; if(buf){ d->writeToBuffer(buf); for(uint8_t i = 0; i < len; i++) printf("%02x ", buf[i]); printf("\n"); delete []buf; } #endif } break; } switch(pdsd) { case 0x00000010: if(d->getTag() == 0x82) { uint8_t *buf = new uint8_t[2 + d->getLength()]; if(buf){ d->writeToBuffer(buf); LogicalChannelDescriptor ld(buf); ParseLogicalChannels(&ld, b); delete []buf; } } break; default: break; } } } } return true; }
bool CPmt::ParseEsInfo(ElementaryStreamInfo *esinfo, CZapitChannel * const channel) { std::string description = ""; unsigned char componentTag = 0xFF; CZapitAudioChannel::ZapitAudioChannelType audio_type = CZapitAudioChannel::UNKNOWN; uint8_t stream_type = esinfo->getType(); bool audio = false; const DescriptorList * dlist = esinfo->getDescriptors(); DescriptorConstIterator dit; for (dit = dlist->begin(); dit != dlist->end(); ++dit) { Descriptor * d = *dit; switch (d->getTag()) { case REGISTRATION_DESCRIPTOR: { RegistrationDescriptor *sd = (RegistrationDescriptor*) d; switch (sd->getFormatIdentifier()) { case 0x44545331: case 0x44545332: case 0x44545333: audio_type = CZapitAudioChannel::DTS; break; case 0x41432d33: audio_type = CZapitAudioChannel::AC3; break; default: #ifdef DEBUG_PMT printf("PMT: REGISTRATION_DESCRIPTOR: %x\n", sd->getFormatIdentifier()); #endif break; } } break; case ISO_639_LANGUAGE_DESCRIPTOR: { Iso639LanguageDescriptor * sd = (Iso639LanguageDescriptor*) d; const Iso639LanguageList *languages = sd->getIso639Languages(); Iso639LanguageConstIterator it; for (it = languages->begin(); it != languages->end(); ++it) { description = (*it)->getIso639LanguageCode(); break; } } break; case STREAM_IDENTIFIER_DESCRIPTOR: { StreamIdentifierDescriptor *sd = (StreamIdentifierDescriptor*) d; componentTag = sd->getComponentTag(); } break; case TELETEXT_DESCRIPTOR: { TeletextDescriptor *td = (TeletextDescriptor*)d; const VbiTeletextList *vbilist = td->getVbiTeletexts(); VbiTeletextConstIterator it; DBG("teletext pid %04x\n", esinfo->getPid()); for (it = vbilist->begin(); it != vbilist->end(); ++it) { VbiTeletext * vbi = *it; std::string lang = vbi->getIso639LanguageCode(); uint8_t page = vbi->getTeletextPageNumber(); uint8_t magazine = vbi->getTeletextMagazineNumber(); DBG("teletext type %d mag %d page %d lang [%s]\n", vbi->getTeletextType(), magazine, page, lang.c_str()); if (vbi->getTeletextType() == 0x01) channel->setTeletextLang(lang); else if (vbi->getTeletextType() == 0x02) channel->addTTXSubtitle(esinfo->getPid(), lang, magazine, page); else if (vbi->getTeletextType() == 0x05) channel->addTTXSubtitle(esinfo->getPid(), lang, magazine, page, true); } channel->setTeletextPid(esinfo->getPid()); } break; case SUBTITLING_DESCRIPTOR: if(stream_type == 0x06) { SubtitlingDescriptor *sd = (SubtitlingDescriptor*) d; const SubtitlingList *sublist = sd->getSubtitlings(); SubtitlingConstIterator it; for (it = sublist->begin(); it != sublist->end(); ++it) { Subtitling * sub = *it; uint16_t composition_page_id = sub->getCompositionPageId(); uint16_t ancillary_page_id = sub->getAncillaryPageId(); std::string lang = sub->getIso639LanguageCode(); channel->addDVBSubtitle(esinfo->getPid(), lang, sub->getSubtitlingType(), composition_page_id, ancillary_page_id); } } break; case AC3_DESCRIPTOR: audio_type = CZapitAudioChannel::AC3; break; case ENHANCED_AC3_DESCRIPTOR: audio_type = CZapitAudioChannel::EAC3; break; case DTS_DESCRIPTOR: audio_type = CZapitAudioChannel::DTS; break; case AAC_DESCRIPTOR: audio_type = CZapitAudioChannel::AAC; break; case 0xC5: /* User Private descriptor - Canal+ Radio */ if(d->getLength() >= 25) { uint8_t *buf = new uint8_t[2 + d->getLength()]; if(buf){ d->writeToBuffer(buf); int tsidonid = channel->getTransportStreamId() << 16 | channel->getOriginalNetworkId(); description = convertDVBUTF8((const char*)&buf[3], 24, 2, tsidonid); delete []buf; } } break; case AUDIO_STREAM_DESCRIPTOR: break; case VIDEO_STREAM_DESCRIPTOR: break; case CA_DESCRIPTOR: break; default: { #ifdef DEBUG_PMT_UNUSED printf("PMT: descriptor %02x: ", d->getTag()); uint8_t len = 2+d->getLength(); uint8_t buf[len]; d->writeToBuffer(buf); for(uint8_t i = 0; i < len; i++) printf("%02x ", buf[i]); printf("\n"); #endif } break; } } switch (stream_type) { case 0x01: case 0x02: case 0x1b: // AVC Video Stream (MPEG4 H264) channel->setVideoPid(esinfo->getPid()); channel->type = (stream_type == 0x1b); //FIXME DBG("vpid %04x stream %d type %d\n", esinfo->getPid(), stream_type, channel->type); break; case 0x03: case 0x04: audio_type = CZapitAudioChannel::MPEG; audio = true; break; case 0x06: if(audio_type != CZapitAudioChannel::UNKNOWN) audio = true; break; case 0x0F: // AAC ADTS case 0x11: // AAC LATM audio_type = CZapitAudioChannel::AAC; audio = true; break; case 0x81: audio_type = CZapitAudioChannel::AC3; audio = true; break; default: #ifdef DEBUG_PMT_UNUSED printf("PMT: pid %04x stream_type: %02x\n", esinfo->getPid(), stream_type); #endif break; } if(audio) { if(description.empty()) { char str[DESC_MAX_LEN]; // snprintf(str, DESC_MAX_LEN, "Unknown 0x%04x", esinfo->getPid()); snprintf(str, DESC_MAX_LEN, "Unknown"); description = str; } DBG("apid %04x stream %02x type %d [%s]\n", esinfo->getPid(), stream_type, (int) audio_type, description.c_str()); if(CServiceScan::getInstance()->Scanning()) { if(channel->getPreAudioPid() == 0) channel->setAudioPid(esinfo->getPid()); } else channel->addAudioChannel(esinfo->getPid(), audio_type, description, componentTag); } return true; }