/** \fn ScanStreamData::IsRedundant(uint,const PSIPTable&) const * \brief Returns true if table already seen. */ bool ScanStreamData::IsRedundant(uint pid, const PSIPTable &psip) const { // Treat BAT and SDTo as redundant unless they are on the FREESAT_SI_PID if (dvb_uk_freesat_si && (psip.TableID() == TableID::BAT || psip.TableID() == TableID::SDTo)) return pid != FREESAT_SI_PID; return (ATSCStreamData::IsRedundant(pid,psip) || DVBStreamData::IsRedundant(pid,psip)); }
// inserts tid&crc value into an ordered list // returns true if item is inserted static bool insert_crc(QList<uint64_t> &seen_crc, const PSIPTable &psip) { uint64_t key = (((uint64_t)psip.TableID()) << 32) | psip.CRC(); QList<uint64_t>::iterator it = lower_bound(seen_crc.begin(), seen_crc.end(), key); if ((it == seen_crc.end()) || (*it != key)) { seen_crc.insert(it, key); return true; } return false; }
/** \fn DVBStreamData::IsRedundant(uint,const PSIPTable&) const * \brief Returns true if table already seen. * \todo This is just a stub. */ bool DVBStreamData::IsRedundant(uint pid, const PSIPTable &psip) const { if (MPEGStreamData::IsRedundant(pid, psip)) return true; const int table_id = psip.TableID(); const int version = psip.Version(); if (TableID::NIT == table_id) { if (VersionNIT() != version) return false; return NITSectionSeen(psip.Section()); } if (TableID::SDT == table_id) { if (VersionSDT(psip.TableIDExtension()) != version) return false; return SDTSectionSeen(psip.TableIDExtension(), psip.Section()); } if (TableID::TDT == table_id) return false; if (TableID::BAT == table_id) { if (VersionBAT(psip.TableIDExtension()) != version) return false; return BATSectionSeen(psip.TableIDExtension(), psip.Section()); } bool is_eit = false; if (DVB_EIT_PID == pid || FREESAT_EIT_PID == pid) { // Standard Now/Next Event Information Tables for this transport is_eit |= TableID::PF_EIT == table_id; // Standard Future Event Information Tables for this transport is_eit |= (TableID::SC_EITbeg <= table_id && TableID::SC_EITend >= table_id); } if (is_eit) { uint service_id = psip.TableIDExtension(); if (VersionEIT(table_id, service_id) != version) return false; return EITSectionSeen(table_id, service_id, psip.Section()); } //////////////////////////////////////////////////////////////////////// // Other transport tables if (TableID::NITo == table_id) { if (VersionNITo() != version) return false; return NIToSectionSeen(psip.Section()); } if (TableID::SDTo == table_id) { if (VersionSDTo(psip.TableIDExtension()) != version) return false; return SDToSectionSeen(psip.TableIDExtension(), psip.Section()); } if (DVB_EIT_PID == pid || FREESAT_EIT_PID == pid || MCA_EIT_PID == pid) { // Standard Now/Next Event Information Tables for other transport is_eit |= TableID::PF_EITo == table_id; // Standard Future Event Information Tables for other transports is_eit |= (TableID::SC_EITbego <= table_id && TableID::SC_EITendo >= table_id); } if (DVB_DNLONG_EIT_PID == pid || DVB_BVLONG_EIT_PID == pid) { // Dish Network and Bev Long Term Future Event Information // for all transports is_eit |= (TableID::DN_EITbego <= table_id && TableID::DN_EITendo >= table_id); } if (is_eit) { uint service_id = psip.TableIDExtension(); if (VersionEIT(table_id, service_id) != version) return false; return EITSectionSeen(table_id, service_id, psip.Section()); } if (((PREMIERE_EIT_DIREKT_PID == pid) || (PREMIERE_EIT_SPORT_PID == pid)) && TableID::PREMIERE_CIT == table_id) { uint content_id = PremiereContentInformationTable(psip).ContentID(); if (VersionCIT(content_id) != version) return false; return CITSectionSeen(content_id, psip.Section()); } return false; }
/** \fn DVBStreamData::HandleTables(uint pid, const PSIPTable&) * \brief Assembles PSIP packets and processes them. * \todo This is just a stub. */ bool DVBStreamData::HandleTables(uint pid, const PSIPTable &psip) { if (MPEGStreamData::HandleTables(pid, psip)) return true; if (IsRedundant(pid, psip)) return true; switch (psip.TableID()) { case TableID::NIT: { if (_dvb_real_network_id >= 0 && psip.TableIDExtension() != (uint)_dvb_real_network_id) { NetworkInformationTable *nit = new NetworkInformationTable(psip); if (!nit->Mutate()) { delete nit; return true; } bool retval = HandleTables(pid, *nit); delete nit; return retval; } SetVersionNIT(psip.Version(), psip.LastSection()); SetNITSectionSeen(psip.Section()); if (_cache_tables) { NetworkInformationTable *nit = new NetworkInformationTable(psip); CacheNIT(nit); QMutexLocker locker(&_listener_lock); for (uint i = 0; i < _dvb_main_listeners.size(); i++) _dvb_main_listeners[i]->HandleNIT(nit); } else { NetworkInformationTable nit(psip); QMutexLocker locker(&_listener_lock); for (uint i = 0; i < _dvb_main_listeners.size(); i++) _dvb_main_listeners[i]->HandleNIT(&nit); } return true; } case TableID::SDT: { uint tsid = psip.TableIDExtension(); SetVersionSDT(tsid, psip.Version(), psip.LastSection()); SetSDTSectionSeen(tsid, psip.Section()); if (_cache_tables) { ServiceDescriptionTable *sdt = new ServiceDescriptionTable(psip); CacheSDT(sdt); ProcessSDT(tsid, sdt); } else { ServiceDescriptionTable sdt(psip); ProcessSDT(tsid, &sdt); } return true; } case TableID::TDT: { TimeDateTable tdt(psip); UpdateTimeOffset(tdt.UTCUnix()); QMutexLocker locker(&_listener_lock); for (uint i = 0; i < _dvb_main_listeners.size(); i++) _dvb_main_listeners[i]->HandleTDT(&tdt); return true; } case TableID::NITo: { if (_dvb_real_network_id >= 0 && psip.TableIDExtension() == (uint)_dvb_real_network_id) { NetworkInformationTable *nit = new NetworkInformationTable(psip); if (!nit->Mutate()) { delete nit; return true; } bool retval = HandleTables(pid, *nit); delete nit; return retval; } SetVersionNITo(psip.Version(), psip.LastSection()); SetNIToSectionSeen(psip.Section()); NetworkInformationTable nit(psip); QMutexLocker locker(&_listener_lock); for (uint i = 0; i < _dvb_other_listeners.size(); i++) _dvb_other_listeners[i]->HandleNITo(&nit); return true; } case TableID::SDTo: { uint tsid = psip.TableIDExtension(); SetVersionSDTo(tsid, psip.Version(), psip.LastSection()); SetSDToSectionSeen(tsid, psip.Section()); ServiceDescriptionTable sdt(psip); // some providers send the SDT for the current multiplex as SDTo // this routine changes the TableID to SDT and recalculates the CRC if (_desired_netid == sdt.OriginalNetworkID() && _desired_tsid == tsid) { ServiceDescriptionTable *sdta = new ServiceDescriptionTable(psip); if (!sdta->Mutate()) { delete sdta; return true; } if (_cache_tables) { CacheSDT(sdta); ProcessSDT(tsid, sdta); } else { ProcessSDT(tsid, sdta); delete sdta; } return true; } QMutexLocker locker(&_listener_lock); for (uint i = 0; i < _dvb_other_listeners.size(); i++) _dvb_other_listeners[i]->HandleSDTo(tsid, &sdt); return true; } case TableID::BAT: { uint bid = psip.TableIDExtension(); SetVersionBAT(bid, psip.Version(), psip.LastSection()); SetBATSectionSeen(bid, psip.Section()); BouquetAssociationTable bat(psip); QMutexLocker locker(&_listener_lock); for (uint i = 0; i < _dvb_other_listeners.size(); i++) _dvb_other_listeners[i]->HandleBAT(&bat); return true; } } if ((DVB_EIT_PID == pid || DVB_DNLONG_EIT_PID == pid || FREESAT_EIT_PID == pid || ((MCA_ONID == _desired_netid) && (MCA_EIT_TSID == _desired_tsid) && (MCA_EIT_PID == pid)) || DVB_BVLONG_EIT_PID == pid) && DVBEventInformationTable::IsEIT(psip.TableID())) { QMutexLocker locker(&_listener_lock); if (!_dvb_eit_listeners.size() && !_eit_helper) return true; uint service_id = psip.TableIDExtension(); SetVersionEIT(psip.TableID(), service_id, psip.Version(), psip.LastSection()); SetEITSectionSeen(psip.TableID(), service_id, psip.Section()); DVBEventInformationTable eit(psip); for (uint i = 0; i < _dvb_eit_listeners.size(); i++) _dvb_eit_listeners[i]->HandleEIT(&eit); if (_eit_helper) _eit_helper->AddEIT(&eit); return true; } if (_desired_netid == PREMIERE_ONID && (PREMIERE_EIT_DIREKT_PID == pid || PREMIERE_EIT_SPORT_PID == pid) && PremiereContentInformationTable::IsEIT(psip.TableID())) { QMutexLocker locker(&_listener_lock); if (!_dvb_eit_listeners.size() && !_eit_helper) return true; PremiereContentInformationTable cit(psip); SetVersionCIT(cit.ContentID(), cit.Version()); SetCITSectionSeen(cit.ContentID(), cit.Section()); for (uint i = 0; i < _dvb_eit_listeners.size(); i++) _dvb_eit_listeners[i]->HandleEIT(&cit); if (_eit_helper) _eit_helper->AddEIT(&cit); return true; } return false; }