Example #1
0
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;
}
Example #2
0
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;
}