int eDVBPMTParser::getProgramInfo(program &program) { ePtr<eTable<ProgramMapSection> > ptr; int ret = -1; clearProgramInfo(program); if (!m_PMT.getCurrent(ptr)) { audioStream *prev_audio = 0; eDVBTableSpec table_spec; ptr->getSpec(table_spec); program.pmtPid = table_spec.pid < 0x1fff ? table_spec.pid : -1; std::vector<ProgramMapSection*>::const_iterator i; for (i = ptr->getSections().begin(); i != ptr->getSections().end(); ++i) { const ProgramMapSection &pmt = **i; int is_hdmv = 0; program.serviceId = pmt.getProgramNumber(); program.pcrPid = pmt.getPcrPid(); for (DescriptorConstIterator desc = pmt.getDescriptors()->begin(); desc != pmt.getDescriptors()->end(); ++desc) { if ((*desc)->getTag() == CA_DESCRIPTOR) { CaDescriptor *descr = (CaDescriptor*)(*desc); program::capid_pair pair; pair.caid = descr->getCaSystemId(); pair.capid = descr->getCaPid(); program.caids.push_back(pair); } else if ((*desc)->getTag() == REGISTRATION_DESCRIPTOR) { RegistrationDescriptor *d = (RegistrationDescriptor*)(*desc); if (d->getFormatIdentifier() == 0x48444d56) // HDMV is_hdmv = 1; } } ElementaryStreamInfoConstIterator es; for (es = pmt.getEsInfo()->begin(); es != pmt.getEsInfo()->end(); ++es) { int isaudio = 0, isvideo = 0, issubtitle = 0, forced_video = 0, forced_audio = 0, isteletext = 0; int streamtype = (*es)->getType(); videoStream video; audioStream audio; audio.component_tag=video.component_tag=-1; video.type = videoStream::vtMPEG2; audio.type = audioStream::atMPEG; audio.rdsPid = -1; switch (streamtype) { case 0x1b: // AVC Video Stream (MPEG4 H264) video.type = videoStream::vtMPEG4_H264; isvideo = 1; //break; fall through !!! case 0x10: // MPEG 4 Part 2 if (!isvideo) { video.type = videoStream::vtMPEG4_Part2; isvideo = 1; } //break; fall through !!! case 0x01: // MPEG 1 video if (!isvideo) video.type = videoStream::vtMPEG1; //break; fall through !!! case 0x02: // MPEG 2 video isvideo = 1; forced_video = 1; //break; fall through !!! case 0x03: // MPEG 1 audio case 0x04: // MPEG 2 audio: if (!isvideo) { isaudio = 1; forced_audio = 1; } //break; fall through !!! case 0x0f: // MPEG 2 AAC if (!isvideo && !isaudio) { isaudio = 1; audio.type = audioStream::atAAC; forced_audio = 1; } //break; fall through !!! case 0x11: // MPEG 4 AAC if (!isvideo && !isaudio) { isaudio = 1; audio.type = audioStream::atAACHE; forced_audio = 1; } case 0x80: // user private ... but bluray LPCM case 0xA0: // bluray secondary LPCM if (!isvideo && !isaudio && is_hdmv) { isaudio = 1; audio.type = audioStream::atLPCM; } case 0x81: // user private ... but bluray AC3 case 0xA1: // bluray secondary AC3 if (!isvideo && !isaudio) { isaudio = 1; audio.type = audioStream::atAC3; } case 0x82: // bluray DTS (dvb user private...) case 0xA2: // bluray secondary DTS if (!isvideo && !isaudio && is_hdmv) { isaudio = 1; audio.type = audioStream::atDTS; } case 0x86: // bluray DTS-HD (dvb user private...) case 0xA6: // bluray secondary DTS-HD if (!isvideo && !isaudio && is_hdmv) { isaudio = 1; audio.type = audioStream::atDTSHD; } case 0x06: // PES Private case 0xEA: // TS_PSI_ST_SMPTE_VC1 { int num_descriptors = 0; for (DescriptorConstIterator desc = (*es)->getDescriptors()->begin(); desc != (*es)->getDescriptors()->end(); ++desc) { uint8_t tag = (*desc)->getTag(); /* check descriptors to get the exakt stream type. */ ++num_descriptors; if (!forced_video && !forced_audio) { switch (tag) { case AUDIO_STREAM_DESCRIPTOR: isaudio = 1; break; case VIDEO_STREAM_DESCRIPTOR: { isvideo = 1; VideoStreamDescriptor *d = (VideoStreamDescriptor*)(*desc); if (d->getMpeg1OnlyFlag()) video.type = videoStream::vtMPEG1; break; } case SUBTITLING_DESCRIPTOR: { SubtitlingDescriptor *d = (SubtitlingDescriptor*)(*desc); const SubtitlingList *list = d->getSubtitlings(); subtitleStream s; s.pid = (*es)->getPid(); for (SubtitlingConstIterator it(list->begin()); it != list->end(); ++it) { s.subtitling_type = (*it)->getSubtitlingType(); switch(s.subtitling_type) { case 0x10 ... 0x13: // dvb subtitles normal case 0x20 ... 0x23: // dvb subtitles hearing impaired break; default: eDebug("dvb subtitle %s PID %04x with wrong subtitling type (%02x)... force 0x10!!", s.language_code.c_str(), s.pid, s.subtitling_type); s.subtitling_type = 0x10; break; } s.composition_page_id = (*it)->getCompositionPageId(); s.ancillary_page_id = (*it)->getAncillaryPageId(); std::string language = (*it)->getIso639LanguageCode(); s.language_code = language; // eDebug("add dvb subtitle %s PID %04x, type %d, composition page %d, ancillary_page %d", s.language_code.c_str(), s.pid, s.subtitling_type, s.composition_page_id, s.ancillary_page_id); issubtitle = 1; program.subtitleStreams.push_back(s); } break; } case TELETEXT_DESCRIPTOR: if (program.textPid == -1) { subtitleStream s; s.subtitling_type = 0x01; // EBU TELETEXT SUBTITLES s.pid = program.textPid = (*es)->getPid(); TeletextDescriptor *d = (TeletextDescriptor*)(*desc); isteletext = 1; const VbiTeletextList *list = d->getVbiTeletexts(); std::string language; for (VbiTeletextConstIterator it(list->begin()); it != list->end(); ++it) { switch((*it)->getTeletextType()) { case 0x02: // Teletext subtitle page case 0x05: // Teletext subtitle page for hearing impaired pepople language = (*it)->getIso639LanguageCode(); s.language_code = language; s.teletext_page_number = (*it)->getTeletextPageNumber(); s.teletext_magazine_number = (*it)->getTeletextMagazineNumber(); // eDebug("add teletext subtitle %s PID %04x, page number %d, magazine number %d", s.language_code.c_str(), s.pid, s.teletext_page_number, s.teletext_magazine_number); program.subtitleStreams.push_back(s); issubtitle=1; default: break; } } } break; case DTS_DESCRIPTOR: isaudio = 1; audio.type = audioStream::atDTS; break; case 0x2B: // TS_PSI_DT_MPEG2_AAC isaudio = 1; audio.type = audioStream::atAAC; // MPEG2-AAC break; case 0x1C: // TS_PSI_DT_MPEG4_Audio case AAC_DESCRIPTOR: isaudio = 1; audio.type = audioStream::atAACHE; // MPEG4-AAC break; case AC3_DESCRIPTOR: isaudio = 1; audio.type = audioStream::atAC3; break; case ENHANCED_AC3_DESCRIPTOR: isaudio = 1; audio.type = audioStream::atDDP; break; case REGISTRATION_DESCRIPTOR: /* some services don't have a separate AC3 descriptor */ { RegistrationDescriptor *d = (RegistrationDescriptor*)(*desc); switch (d->getFormatIdentifier()) { case 0x44545331 ... 0x44545333: // DTS1/DTS2/DTS3 isaudio = 1; audio.type = audioStream::atDTS; break; case 0x41432d33: // == 'AC-3' isaudio = 1; audio.type = audioStream::atAC3; break; case 0x42535344: // == 'BSSD' (LPCM) isaudio = 1; audio.type = audioStream::atLPCM; break; case 0x56432d31: // == 'VC-1' { const AdditionalIdentificationInfoVector *vec = d->getAdditionalIdentificationInfo(); if (vec->size() > 1 && (*vec)[0] == 0x01) // subdescriptor tag { if ((*vec)[1] >= 0x90) // profile_level video.type = videoStream::vtVC1; // advanced profile else video.type = videoStream::vtVC1_SM; // simple main isvideo = 1; } } default: break; } break; } case 0x28: // TS_PSI_DT_AVC isvideo = 1; video.type = videoStream::vtMPEG4_H264; break; case 0x1B: // TS_PSI_DT_MPEG4_Video isvideo = 1; video.type = videoStream::vtMPEG4_Part2; break; default: break; } } switch (tag) { case ISO_639_LANGUAGE_DESCRIPTOR: if (!isvideo) { const Iso639LanguageList *languages = ((Iso639LanguageDescriptor*)*desc)->getIso639Languages(); /* use last language code */ int cnt=0; for (Iso639LanguageConstIterator i=languages->begin(); i != languages->end(); ++i) { std::string language=(*i)->getIso639LanguageCode(); if ( cnt==0 ) audio.language_code = language; else audio.language_code += "/" + language; cnt++; } } break; case STREAM_IDENTIFIER_DESCRIPTOR: audio.component_tag = video.component_tag = ((StreamIdentifierDescriptor*)*desc)->getComponentTag(); break; case CA_DESCRIPTOR: { CaDescriptor *descr = (CaDescriptor*)(*desc); program::capid_pair pair; pair.caid = descr->getCaSystemId(); pair.capid = descr->getCaPid(); program.caids.push_back(pair); break; } default: break; } } if (!num_descriptors && streamtype == 0x06 && prev_audio) { prev_audio->rdsPid = (*es)->getPid(); eDebug("Rds PID %04x detected ? ! ?", prev_audio->rdsPid); } prev_audio = 0; break; } case 0x05: /* ITU-T Rec. H.222.0 | ISO/IEC 13818-1 private sections */ { for (DescriptorConstIterator desc = (*es)->getDescriptors()->begin(); desc != (*es)->getDescriptors()->end(); ++desc) { switch ((*desc)->getTag()) { case APPLICATION_SIGNALLING_DESCRIPTOR: program.aitPid = (*es)->getPid(); break; } } break; } case 0x0b: /* ISO/IEC 13818-6 DSM-CC U-N Messages */ { for (DescriptorConstIterator desc = (*es)->getDescriptors()->begin(); desc != (*es)->getDescriptors()->end(); ++desc) { switch ((*desc)->getTag()) { case CAROUSEL_IDENTIFIER_DESCRIPTOR: program.dsmccPid = (*es)->getPid(); break; case STREAM_IDENTIFIER_DESCRIPTOR: break; } } break; } default: break; } if (isteletext && (isaudio || isvideo)) { eDebug("ambiguous streamtype for PID %04x detected.. forced as teletext!", (*es)->getPid()); continue; // continue with next PID } else if (issubtitle && (isaudio || isvideo)) eDebug("ambiguous streamtype for PID %04x detected.. forced as subtitle!", (*es)->getPid()); else if (isaudio && isvideo) eDebug("ambiguous streamtype for PID %04x detected.. forced as video!", (*es)->getPid()); if (issubtitle) // continue with next PID continue; else if (isvideo) { video.pid = (*es)->getPid(); program.videoStreams.push_back(video); } else if (isaudio) { audio.pid = (*es)->getPid(); program.audioStreams.push_back(audio); prev_audio = &program.audioStreams.back(); } else continue; } } ret = 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; }
void eDVBScan::PMTready(int err) { SCAN_eDebug("[eDVBScan] got pmt %d", err); if (!err) { bool scrambled = false; bool have_audio = false; bool have_video = false; unsigned short pcrpid = 0xFFFF; std::vector<ProgramMapSection*>::const_iterator i; for (i = m_PMT->getSections().begin(); i != m_PMT->getSections().end(); ++i) { const ProgramMapSection &pmt = **i; if (pcrpid == 0xFFFF) pcrpid = pmt.getPcrPid(); else SCAN_eDebug("[eDVBScan] already have a pcrpid %04x %04x", pcrpid, pmt.getPcrPid()); ElementaryStreamInfoConstIterator es; for (es = pmt.getEsInfo()->begin(); es != pmt.getEsInfo()->end(); ++es) { int isaudio = 0, isvideo = 0, is_scrambled = 0, forced_audio = 0, forced_video = 0; switch ((*es)->getType()) { case 0x1b: // AVC Video Stream (MPEG4 H264) case 0x24: // H265 HEVC case 0x10: // MPEG 4 Part 2 case 0x01: // MPEG 1 video case 0x02: // MPEG 2 video isvideo = 1; forced_video = 1; //break; fall through !!! case 0x03: // MPEG 1 audio case 0x04: // MPEG 2 audio case 0x0f: // MPEG 2 AAC case 0x11: // MPEG 4 AAC if (!isvideo) { forced_audio = 1; isaudio = 1; } case 0x06: // PES Private case 0x81: // user private case 0xEA: // TS_PSI_ST_SMPTE_VC1 for (DescriptorConstIterator desc = (*es)->getDescriptors()->begin(); desc != (*es)->getDescriptors()->end(); ++desc) { uint8_t tag = (*desc)->getTag(); /* PES private can contain AC-3, DTS or lots of other stuff. check descriptors to get the exakt type. */ if (!forced_video && !forced_audio) { switch (tag) { case 0x1C: // TS_PSI_DT_MPEG4_Audio case 0x2B: // TS_PSI_DT_MPEG2_AAC case AAC_DESCRIPTOR: case AC3_DESCRIPTOR: case DTS_DESCRIPTOR: case AUDIO_STREAM_DESCRIPTOR: isaudio = 1; break; case 0x28: // TS_PSI_DT_AVC case 0x1B: // TS_PSI_DT_MPEG4_Video case VIDEO_STREAM_DESCRIPTOR: isvideo = 1; break; case REGISTRATION_DESCRIPTOR: /* some services don't have a separate AC3 descriptor */ { RegistrationDescriptor *d = (RegistrationDescriptor*)(*desc); switch (d->getFormatIdentifier()) { case 0x44545331 ... 0x44545333: // DTS1/DTS2/DTS3 case 0x41432d33: // == 'AC-3' case 0x42535344: // == 'BSSD' (LPCM) isaudio = 1; break; case 0x56432d31: // == 'VC-1' isvideo = 1; break; default: break; } } default: break; } } if (tag == CA_DESCRIPTOR) is_scrambled = 1; } default: break; } if (isvideo) have_video = true; else if (isaudio) have_audio = true; else continue; if (is_scrambled) scrambled = true; } for (DescriptorConstIterator desc = pmt.getDescriptors()->begin(); desc != pmt.getDescriptors()->end(); ++desc) { if ((*desc)->getTag() == CA_DESCRIPTOR) scrambled = true; } } m_pmt_in_progress->second.scrambled = scrambled; if ( have_video ) m_pmt_in_progress->second.serviceType = 1; else if ( have_audio ) m_pmt_in_progress->second.serviceType = 2; else m_pmt_in_progress->second.serviceType = 100; }
int eDVBServicePMTHandler::getProgramInfo(program &program) { ePtr<eTable<ProgramMapSection> > ptr; int cached_apid_ac3 = -1; int cached_apid_mpeg = -1; int cached_vpid = -1; int cached_tpid = -1; int ret = -1; if (m_have_cached_program) { program = m_cached_program; return 0; } program.videoStreams.clear(); program.audioStreams.clear(); program.subtitleStreams.clear(); program.pcrPid = -1; program.pmtPid = -1; program.textPid = -1; program.aitPid = -1; program.defaultAudioStream = 0; program.defaultSubtitleStream = -1; if ( m_service && !m_service->cacheEmpty() ) { cached_vpid = m_service->getCacheEntry(eDVBService::cVPID); cached_apid_mpeg = m_service->getCacheEntry(eDVBService::cAPID); cached_apid_ac3 = m_service->getCacheEntry(eDVBService::cAC3PID); cached_tpid = m_service->getCacheEntry(eDVBService::cTPID); } if ( ((m_service && m_service->usePMT()) || !m_service) && !m_PMT.getCurrent(ptr)) { int first_ac3 = -1; int audio_cached = -1; int autoaudio_mpeg = -1; int autoaudio_ac3 = -1; int autoaudio_level = 4; std::string configvalue; std::vector<std::string> autoaudio_languages; if (!ePythonConfigQuery::getConfigValue("config.autolanguage.audio_autoselect1", configvalue) && configvalue != "None") autoaudio_languages.push_back(configvalue); if (!ePythonConfigQuery::getConfigValue("config.autolanguage.audio_autoselect2", configvalue) && configvalue != "None") autoaudio_languages.push_back(configvalue); if (!ePythonConfigQuery::getConfigValue("config.autolanguage.audio_autoselect3", configvalue) && configvalue != "None") autoaudio_languages.push_back(configvalue); if (!ePythonConfigQuery::getConfigValue("config.autolanguage.audio_autoselect4", configvalue) && configvalue != "None") autoaudio_languages.push_back(configvalue); audioStream *prev_audio = 0; int autosub_txt_normal = -1; int autosub_txt_hearing = -1; int autosub_dvb_normal = -1; int autosub_dvb_hearing = -1; int autosub_level =4; std::vector<std::string> autosub_languages; if (!ePythonConfigQuery::getConfigValue("config.autolanguage.subtitle_autoselect1", configvalue) && configvalue != "None") autosub_languages.push_back(configvalue); if (!ePythonConfigQuery::getConfigValue("config.autolanguage.subtitle_autoselect2", configvalue) && configvalue != "None") autosub_languages.push_back(configvalue); if (!ePythonConfigQuery::getConfigValue("config.autolanguage.subtitle_autoselect3", configvalue) && configvalue != "None") autosub_languages.push_back(configvalue); if (!ePythonConfigQuery::getConfigValue("config.autolanguage.subtitle_autoselect4", configvalue) && configvalue != "None") autosub_languages.push_back(configvalue); eDVBTableSpec table_spec; ptr->getSpec(table_spec); program.pmtPid = table_spec.pid < 0x1fff ? table_spec.pid : -1; std::vector<ProgramMapSection*>::const_iterator i; for (i = ptr->getSections().begin(); i != ptr->getSections().end(); ++i) { const ProgramMapSection &pmt = **i; int is_hdmv = 0; program.pcrPid = pmt.getPcrPid(); for (DescriptorConstIterator desc = pmt.getDescriptors()->begin(); desc != pmt.getDescriptors()->end(); ++desc) { if ((*desc)->getTag() == CA_DESCRIPTOR) { CaDescriptor *descr = (CaDescriptor*)(*desc); program::capid_pair pair; pair.caid = descr->getCaSystemId(); pair.capid = descr->getCaPid(); program.caids.push_back(pair); } else if ((*desc)->getTag() == REGISTRATION_DESCRIPTOR) { RegistrationDescriptor *d = (RegistrationDescriptor*)(*desc); if (d->getFormatIdentifier() == 0x48444d56) // HDMV is_hdmv = 1; } } ElementaryStreamInfoConstIterator es; for (es = pmt.getEsInfo()->begin(); es != pmt.getEsInfo()->end(); ++es) { int isaudio = 0, isvideo = 0, issubtitle = 0, forced_video = 0, forced_audio = 0, isteletext = 0; int streamtype = (*es)->getType(); videoStream video; audioStream audio; audio.component_tag=video.component_tag=-1; video.type = videoStream::vtMPEG2; audio.type = audioStream::atMPEG; audio.rdsPid = -1; switch (streamtype) { case 0x1b: // AVC Video Stream (MPEG4 H264) video.type = videoStream::vtMPEG4_H264; isvideo = 1; //break; fall through !!! case 0x10: // MPEG 4 Part 2 if (!isvideo) { video.type = videoStream::vtMPEG4_Part2; isvideo = 1; } //break; fall through !!! case 0x01: // MPEG 1 video if (!isvideo) video.type = videoStream::vtMPEG1; //break; fall through !!! case 0x02: // MPEG 2 video isvideo = 1; forced_video = 1; //break; fall through !!! case 0x03: // MPEG 1 audio case 0x04: // MPEG 2 audio: if (!isvideo) { isaudio = 1; forced_audio = 1; } //break; fall through !!! case 0x0f: // MPEG 2 AAC if (!isvideo && !isaudio) { isaudio = 1; audio.type = audioStream::atAAC; forced_audio = 1; } //break; fall through !!! case 0x11: // MPEG 4 AAC if (!isvideo && !isaudio) { isaudio = 1; audio.type = audioStream::atAACHE; forced_audio = 1; } case 0x80: // user private ... but bluray LPCM case 0xA0: // bluray secondary LPCM if (!isvideo && !isaudio && is_hdmv) { isaudio = 1; audio.type = audioStream::atLPCM; } case 0x81: // user private ... but bluray AC3 case 0xA1: // bluray secondary AC3 if (!isvideo && !isaudio) { isaudio = 1; audio.type = audioStream::atAC3; } case 0x82: // bluray DTS (dvb user private...) case 0xA2: // bluray secondary DTS if (!isvideo && !isaudio && is_hdmv) { isaudio = 1; audio.type = audioStream::atDTS; } case 0x86: // bluray DTS-HD (dvb user private...) case 0xA6: // bluray secondary DTS-HD if (!isvideo && !isaudio && is_hdmv) { isaudio = 1; audio.type = audioStream::atDTSHD; } case 0x06: // PES Private case 0xEA: // TS_PSI_ST_SMPTE_VC1 { int num_descriptors = 0; for (DescriptorConstIterator desc = (*es)->getDescriptors()->begin(); desc != (*es)->getDescriptors()->end(); ++desc) { uint8_t tag = (*desc)->getTag(); /* check descriptors to get the exakt stream type. */ ++num_descriptors; if (!forced_video && !forced_audio) { switch (tag) { case AUDIO_STREAM_DESCRIPTOR: isaudio = 1; break; case VIDEO_STREAM_DESCRIPTOR: { isvideo = 1; VideoStreamDescriptor *d = (VideoStreamDescriptor*)(*desc); if (d->getMpeg1OnlyFlag()) video.type = videoStream::vtMPEG1; break; } case SUBTITLING_DESCRIPTOR: { SubtitlingDescriptor *d = (SubtitlingDescriptor*)(*desc); const SubtitlingList *list = d->getSubtitlings(); subtitleStream s; s.pid = (*es)->getPid(); for (SubtitlingConstIterator it(list->begin()); it != list->end(); ++it) { s.subtitling_type = (*it)->getSubtitlingType(); switch(s.subtitling_type) { case 0x10 ... 0x13: // dvb subtitles normal case 0x20 ... 0x23: // dvb subtitles hearing impaired break; default: eDebug("dvb subtitle %s PID %04x with wrong subtitling type (%02x)... force 0x10!!", s.language_code.c_str(), s.pid, s.subtitling_type); s.subtitling_type = 0x10; break; } s.composition_page_id = (*it)->getCompositionPageId(); s.ancillary_page_id = (*it)->getAncillaryPageId(); std::string language = (*it)->getIso639LanguageCode(); s.language_code = language; // eDebug("add dvb subtitle %s PID %04x, type %d, composition page %d, ancillary_page %d", s.language_code.c_str(), s.pid, s.subtitling_type, s.composition_page_id, s.ancillary_page_id); if (!language.empty()) { int x = 1; for (std::vector<std::string>::iterator it2 = autosub_languages.begin();x <= autosub_level && it2 != autosub_languages.end();x++,it2++) { if ((*it2).find(language) != std::string::npos) { autosub_level = x; if (s.subtitling_type >= 0x20) autosub_dvb_hearing = program.subtitleStreams.size(); else autosub_dvb_normal = program.subtitleStreams.size(); break; } } } issubtitle = 1; program.subtitleStreams.push_back(s); } break; } case TELETEXT_DESCRIPTOR: if ( program.textPid == -1 || (*es)->getPid() == cached_tpid ) { subtitleStream s; s.subtitling_type = 0x01; // EBU TELETEXT SUBTITLES s.pid = program.textPid = (*es)->getPid(); TeletextDescriptor *d = (TeletextDescriptor*)(*desc); isteletext = 1; const VbiTeletextList *list = d->getVbiTeletexts(); std::string language; for (VbiTeletextConstIterator it(list->begin()); it != list->end(); ++it) { switch((*it)->getTeletextType()) { case 0x02: // Teletext subtitle page case 0x05: // Teletext subtitle page for hearing impaired pepople language = (*it)->getIso639LanguageCode(); s.language_code = language; s.teletext_page_number = (*it)->getTeletextPageNumber(); s.teletext_magazine_number = (*it)->getTeletextMagazineNumber(); // eDebug("add teletext subtitle %s PID %04x, page number %d, magazine number %d", s.language_code.c_str(), s.pid, s.teletext_page_number, s.teletext_magazine_number); if (!language.empty()) { int x = 1; for (std::vector<std::string>::iterator it2 = autosub_languages.begin();x <= autosub_level && it2 != autosub_languages.end();x++,it2++) { if ((*it2).find(language) != std::string::npos) { autosub_level = x; if (s.subtitling_type == 0x05) autosub_txt_hearing = program.subtitleStreams.size(); else autosub_txt_normal = program.subtitleStreams.size(); break; } } } program.subtitleStreams.push_back(s); issubtitle=1; default: break; } } } break; case DTS_DESCRIPTOR: isaudio = 1; audio.type = audioStream::atDTS; break; case 0x2B: // TS_PSI_DT_MPEG2_AAC isaudio = 1; audio.type = audioStream::atAAC; // MPEG2-AAC break; case 0x1C: // TS_PSI_DT_MPEG4_Audio case AAC_DESCRIPTOR: isaudio = 1; audio.type = audioStream::atAACHE; // MPEG4-AAC break; case AC3_DESCRIPTOR: isaudio = 1; audio.type = audioStream::atAC3; break; case ENHANCED_AC3_DESCRIPTOR: isaudio = 1; audio.type = audioStream::atDDP; break; case REGISTRATION_DESCRIPTOR: /* some services don't have a separate AC3 descriptor */ { RegistrationDescriptor *d = (RegistrationDescriptor*)(*desc); switch (d->getFormatIdentifier()) { case 0x44545331 ... 0x44545333: // DTS1/DTS2/DTS3 isaudio = 1; audio.type = audioStream::atDTS; break; case 0x41432d33: // == 'AC-3' isaudio = 1; audio.type = audioStream::atAC3; break; case 0x42535344: // == 'BSSD' (LPCM) isaudio = 1; audio.type = audioStream::atLPCM; break; case 0x56432d31: // == 'VC-1' { const AdditionalIdentificationInfoVector *vec = d->getAdditionalIdentificationInfo(); if (vec->size() > 1 && (*vec)[0] == 0x01) // subdescriptor tag { if ((*vec)[1] >= 0x90) // profile_level video.type = videoStream::vtVC1; // advanced profile else video.type = videoStream::vtVC1_SM; // simple main isvideo = 1; } } default: break; } break; } case 0x28: // TS_PSI_DT_AVC isvideo = 1; video.type = videoStream::vtMPEG4_H264; break; case 0x1B: // TS_PSI_DT_MPEG4_Video isvideo = 1; video.type = videoStream::vtMPEG4_Part2; break; default: break; } } switch (tag) { case ISO_639_LANGUAGE_DESCRIPTOR: if (!isvideo) { const Iso639LanguageList *languages = ((Iso639LanguageDescriptor*)*desc)->getIso639Languages(); /* use last language code */ int cnt=0; for (Iso639LanguageConstIterator i=languages->begin(); i != languages->end(); ++i) { std::string language=(*i)->getIso639LanguageCode(); if ( cnt==0 ) audio.language_code = language; else audio.language_code += "/" + language; cnt++; if (!language.empty()) { int x = 1; for (std::vector<std::string>::iterator it = autoaudio_languages.begin();x <= autoaudio_level && it != autoaudio_languages.end();x++,it++) { if ((*it).find(language) != std::string::npos) { if (audio.type == audioStream::atMPEG && (autoaudio_level > x || autoaudio_mpeg == -1)) autoaudio_mpeg = program.audioStreams.size(); else if (audio.type != audioStream::atMPEG && (autoaudio_level > x || autoaudio_ac3 == -1)) autoaudio_ac3 = program.audioStreams.size(); autoaudio_level = x; break; } } } } } break; case STREAM_IDENTIFIER_DESCRIPTOR: audio.component_tag = video.component_tag = ((StreamIdentifierDescriptor*)*desc)->getComponentTag(); break; case CA_DESCRIPTOR: { CaDescriptor *descr = (CaDescriptor*)(*desc); program::capid_pair pair; pair.caid = descr->getCaSystemId(); pair.capid = descr->getCaPid(); program.caids.push_back(pair); break; } default: break; } } if (!num_descriptors && streamtype == 0x06 && prev_audio) { prev_audio->rdsPid = (*es)->getPid(); eDebug("Rds PID %04x detected ? ! ?", prev_audio->rdsPid); } prev_audio = 0; break; } case 0x05: /* ITU-T Rec. H.222.0 | ISO/IEC 13818-1 private sections */ { for (DescriptorConstIterator desc = (*es)->getDescriptors()->begin(); desc != (*es)->getDescriptors()->end(); ++desc) { switch ((*desc)->getTag()) { case APPLICATION_SIGNALLING_DESCRIPTOR: program.aitPid = (*es)->getPid(); m_AIT.begin(eApp, eDVBAITSpec(program.aitPid), m_demux); break; } } break; } case 0x0b: /* ISO/IEC 13818-6 DSM-CC U-N Messages */ { for (DescriptorConstIterator desc = (*es)->getDescriptors()->begin(); desc != (*es)->getDescriptors()->end(); ++desc) { switch ((*desc)->getTag()) { case CAROUSEL_IDENTIFIER_DESCRIPTOR: m_dsmcc_pid = (*es)->getPid(); break; case STREAM_IDENTIFIER_DESCRIPTOR: break; } } break; } default: break; } if (isteletext && (isaudio || isvideo)) { eDebug("ambiguous streamtype for PID %04x detected.. forced as teletext!", (*es)->getPid()); continue; // continue with next PID } else if (issubtitle && (isaudio || isvideo)) eDebug("ambiguous streamtype for PID %04x detected.. forced as subtitle!", (*es)->getPid()); else if (isaudio && isvideo) eDebug("ambiguous streamtype for PID %04x detected.. forced as video!", (*es)->getPid()); if (issubtitle) // continue with next PID continue; else if (isvideo) { video.pid = (*es)->getPid(); if ( !program.videoStreams.empty() && video.pid == cached_vpid ) { program.videoStreams.push_back(program.videoStreams[0]); program.videoStreams[0] = video; } else program.videoStreams.push_back(video); } else if (isaudio) { audio.pid = (*es)->getPid(); /* if we find the cached pids, this will be our default stream */ if (audio.pid == cached_apid_ac3 || audio.pid == cached_apid_mpeg) audio_cached = program.audioStreams.size(); /* also, we need to know the first non-mpeg (i.e. "ac3"/dts/...) stream */ if ((audio.type != audioStream::atMPEG) && ((first_ac3 == -1) || (audio.pid == cached_apid_ac3))) first_ac3 = program.audioStreams.size(); program.audioStreams.push_back(audio); prev_audio = &program.audioStreams.back(); } else continue; } } ret = 0; bool defaultac3 = false; bool useaudio_cache = false; if (!ePythonConfigQuery::getConfigValue("config.autolanguage.audio_defaultac3", configvalue)) defaultac3 = configvalue == "True"; if (!ePythonConfigQuery::getConfigValue("config.autolanguage.audio_usecache", configvalue)) useaudio_cache = configvalue == "True"; if (useaudio_cache && audio_cached != -1) program.defaultAudioStream = audio_cached; else if ( defaultac3 ) { if ( autoaudio_ac3 != -1 ) program.defaultAudioStream = autoaudio_ac3; else if ( autoaudio_mpeg != -1 ) program.defaultAudioStream = autoaudio_mpeg; else if ( first_ac3 != -1 ) program.defaultAudioStream = first_ac3; } else { if ( autoaudio_mpeg != -1 ) program.defaultAudioStream = autoaudio_mpeg; else if ( autoaudio_ac3 != -1 ) program.defaultAudioStream = autoaudio_ac3; } bool allow_hearingimpaired = false; bool default_hearingimpaired = false; bool defaultdvb = false; int equallanguagemask = false; if (!ePythonConfigQuery::getConfigValue("config.autolanguage.subtitle_hearingimpaired", configvalue)) allow_hearingimpaired = configvalue == "True"; if (!ePythonConfigQuery::getConfigValue("config.autolanguage.subtitle_defaultimpaired", configvalue)) default_hearingimpaired = configvalue == "True"; if (!ePythonConfigQuery::getConfigValue("config.autolanguage.subtitle_defaultdvb", configvalue)) defaultdvb = configvalue == "True"; if (!ePythonConfigQuery::getConfigValue("config.autolanguage.equal_languages", configvalue)) equallanguagemask = atoi(configvalue.c_str()); if (defaultdvb) { if (allow_hearingimpaired && default_hearingimpaired && autosub_dvb_hearing != -1) program.defaultSubtitleStream = autosub_dvb_hearing; else if (autosub_dvb_normal != -1) program.defaultSubtitleStream = autosub_dvb_normal; else if (allow_hearingimpaired && autosub_dvb_hearing != -1) program.defaultSubtitleStream = autosub_dvb_hearing; else if (allow_hearingimpaired && default_hearingimpaired && autosub_txt_hearing != -1) program.defaultSubtitleStream = autosub_txt_hearing; else if (autosub_txt_normal != -1) program.defaultSubtitleStream = autosub_txt_normal; else if (allow_hearingimpaired && autosub_dvb_hearing != -1) program.defaultSubtitleStream = autosub_txt_hearing; } else { if (allow_hearingimpaired && default_hearingimpaired && autosub_txt_hearing != -1) program.defaultSubtitleStream = autosub_txt_hearing; else if (autosub_txt_normal != -1) program.defaultSubtitleStream = autosub_txt_normal; else if (allow_hearingimpaired && autosub_txt_hearing != -1) program.defaultSubtitleStream = autosub_txt_hearing; else if (allow_hearingimpaired && default_hearingimpaired && autosub_dvb_hearing != -1) program.defaultSubtitleStream = autosub_dvb_hearing; else if (autosub_dvb_normal != -1) program.defaultSubtitleStream = autosub_dvb_normal; else if (allow_hearingimpaired && autosub_dvb_hearing != -1) program.defaultSubtitleStream = autosub_dvb_hearing; } if (program.defaultSubtitleStream != -1 && (equallanguagemask & (1<<(autosub_level-1))) == 0 && program.subtitleStreams[program.defaultSubtitleStream].language_code.compare(program.audioStreams[program.defaultAudioStream].language_code) == 0 ) program.defaultSubtitleStream = -1; }