RESULT eDVBScan::nextChannel() { ePtr<iDVBFrontend> fe; m_SDT = 0; m_PAT = 0; m_BAT = 0; m_NIT = 0, m_PMT = 0; m_ready = 0; m_pat_tsid = eTransportStreamID(); /* check what we need */ m_ready_all = readySDT; if (m_flags & scanNetworkSearch) m_ready_all |= readyNIT; if (m_flags & scanSearchBAT) m_ready_all |= readyBAT; if (m_usePAT) m_ready_all |= readyPAT; if (!m_ch_blindscan.empty()) { /* keep iterating with the same 'channel' till we get a tune failure */ SCAN_eDebug("[eDVBScan] blindscan channel iteration"); m_ch_current = m_ch_blindscan.front(); } else { m_ch_blindscan_result = NULL; if (m_ch_toScan.empty()) { SCAN_eDebug("[eDVBScan] no channels left: %zd scanned, %zd unavailable, %zd database.", m_ch_scanned.size(), m_ch_unavailable.size(), m_new_channels.size()); m_event(evtFinish); return -ENOENT; } m_ch_current = m_ch_toScan.front(); m_ch_toScan.pop_front(); } if (m_channel->getFrontend(fe)) { m_event(evtFail); return -ENOTSUP; } m_chid_current = eDVBChannelID(); m_channel_state = iDVBChannel::state_idle; if (fe->tune(*m_ch_current, !m_ch_blindscan.empty())) return nextChannel(); m_event(evtUpdate); return 0; }
RESULT eDVBScan::nextChannel() { ePtr<iDVBFrontend> fe; m_SDT = 0; m_PAT = 0; m_BAT = 0; m_NIT = 0, m_PMT = 0; m_ready = 0; m_pat_tsid = eTransportStreamID(); /* check what we need */ m_ready_all = readySDT; if (m_flags & scanNetworkSearch) m_ready_all |= readyNIT; if (m_flags & scanSearchBAT) m_ready_all |= readyBAT; if (m_usePAT) m_ready_all |= readyPAT; if (m_ch_toScan.empty()) { SCAN_eDebug("[eDVBScan] no channels left to scan."); SCAN_eDebug("[eDVBScan] %zd channels scanned, %zd were unavailable.", m_ch_scanned.size(), m_ch_unavailable.size()); SCAN_eDebug("[eDVBScan] %zd channels in database.", m_new_channels.size()); m_event(evtFinish); return -ENOENT; } m_ch_current = m_ch_toScan.front(); m_ch_toScan.pop_front(); if (m_channel->getFrontend(fe)) { m_event(evtFail); return -ENOTSUP; } m_chid_current = eDVBChannelID(); m_channel_state = iDVBChannel::state_idle; if (fe->tune(*m_ch_current)) return nextChannel(); m_event(evtUpdate); return 0; }
void eDVBScan::VCTready(int err) { SCAN_eDebug("[eDVBScan] got vct %d", err); m_ready |= readySDT; if (!err) m_ready |= validVCT; channelDone(); }
void eDVBScan::PATready(int err) { SCAN_eDebug("[eDVBScan] got pat, err %d", err); m_ready |= readyPAT; if (!err) m_ready |= validPAT; startFilter(); // for starting the SDT filter }
void eDVBScan::BATready(int err) { SCAN_eDebug("[eDVBScan] got bat, err %d", err); m_ready |= readyBAT; if (!err) m_ready |= validBAT; channelDone(); }
void eDVBScan::NITready(int err) { SCAN_eDebug("[eDVBScan] got nit, err %d", err); m_ready |= readyNIT; if (!err) m_ready |= validNIT; channelDone(); }
eDVBScan::eDVBScan(iDVBChannel *channel, bool usePAT, bool debug) :m_channel(channel) ,m_channel_state(iDVBChannel::state_idle) ,m_ready(0) ,m_ready_all(usePAT ? (readySDT|readyPAT) : readySDT) ,m_pmt_running(false) ,m_abort_current_pmt(false) ,m_flags(0) ,m_usePAT(usePAT) ,m_scan_debug(debug) { if (m_channel->getDemux(m_demux)) SCAN_eDebug("[eDVBScan] failed to allocate demux!"); m_channel->connectStateChange(sigc::mem_fun(*this, &eDVBScan::stateChange), m_stateChanged_connection); }
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; }
void eDVBScan::stateChange(iDVBChannel *ch) { int state; if (ch->getState(state)) return; if (m_channel_state == state) return; if (state == iDVBChannel::state_ok) { if (m_ch_current && m_channel) { int type; m_ch_current->getSystem(type); if (type == iDVBFrontend::feTerrestrial) { eDVBFrontendParametersTerrestrial parm; m_ch_current->getDVBT(parm); if (parm.system == eDVBFrontendParametersTerrestrial::System_DVB_T_T2) { /* we have a lock, this is a valid DVB-T transponder, set our system parameter */ parm.system = eDVBFrontendParametersTerrestrial::System_DVB_T; m_ch_current->setDVBT(parm); } } } if (!m_ch_blindscan.empty()) { /* update current blindscan iteration channel with scanned parameters */ if (m_ch_current && m_channel) { ePtr<iDVBFrontend> fe; m_channel->getFrontend(fe); if (fe) { ePtr<iDVBTransponderData> tp; fe->getTransponderData(tp, false); if (tp) { ePtr<eDVBFrontendParameters> feparm = new eDVBFrontendParameters; int type; m_ch_current->getSystem(type); switch (type) { case iDVBFrontend::feSatellite: { eDVBFrontendParametersSatellite parm; m_ch_current->getDVBS(parm); parm.system = tp->getSystem(); parm.frequency = tp->getFrequency(); parm.symbol_rate = tp->getSymbolRate(); parm.modulation = tp->getModulation(); feparm->setDVBS(parm); break; } case iDVBFrontend::feCable: { eDVBFrontendParametersCable parm; m_ch_current->getDVBC(parm); parm.system = tp->getSystem(); parm.frequency = tp->getFrequency(); parm.symbol_rate = tp->getSymbolRate(); parm.modulation = tp->getModulation(); feparm->setDVBC(parm); break; } case iDVBFrontend::feTerrestrial: { eDVBFrontendParametersTerrestrial parm; m_ch_current->getDVBT(parm); parm.system = tp->getSystem(); parm.frequency = tp->getFrequency(); parm.bandwidth = tp->getBandwidth(); parm.modulation = tp->getConstellation(); feparm->setDVBT(parm); break; } case iDVBFrontend::feATSC: { eDVBFrontendParametersATSC parm; m_ch_current->getATSC(parm); parm.system = tp->getSystem(); parm.frequency = tp->getFrequency(); feparm->setATSC(parm); break; } } m_ch_current = m_ch_blindscan_result = feparm; } } } } startFilter(); m_channel_state = state; } else if (state == iDVBChannel::state_failed) { if (m_ch_current && m_channel) { int type; m_ch_current->getSystem(type); m_ch_unavailable.push_back(m_ch_current); if (type == iDVBFrontend::feTerrestrial) { eDVBFrontendParametersTerrestrial parm; m_ch_current->getDVBT(parm); if (parm.system == eDVBFrontendParametersTerrestrial::System_DVB_T_T2) { /* we have to scan T2 as well as T */ ePtr<iDVBFrontend> fe; eDVBFrontendParameters eparm; parm.system = eDVBFrontendParametersTerrestrial::System_DVB_T2; eparm.setDVBT(parm); m_channel->getFrontend(fe); if (fe) { ePtr<iDVBFrontendParameters> feparm = new eDVBFrontendParameters(eparm); /* but only if the frontend supports T2 */ if (fe->isCompatibleWith(feparm)) { addChannelToScan(feparm); } } } } } if (!m_ch_blindscan.empty()) { /* tune failure, this means the blindscan channel iteration run has completed */ SCAN_eDebug("[eDVBScan] blindscan channel completed"); m_ch_blindscan.pop_front(); } nextChannel(); } /* unavailable will timeout, anyway. */ }