From efbc436e33e7caaba6284a698a23fe77506e46aa Mon Sep 17 00:00:00 2001 From: Mark Spieth Date: Thu, 9 Jan 2020 23:03:18 +0100 Subject: [PATCH] OpenTV logical channel numbers Support for OpenTV logical channel numbers as used by Sky (US/IT/NZ/AU), Dishnet(US) and others. The Bouquet ID and the Region ID, needed to get the correct tables, can be defined in the video source similar to how it is done for the Freesat and Sky UK channel numbers. Scanning is activated by a new "Scan OpenTV" channel scanning option. As a next step, when the applicable network ID's and private descriptor identifiers are known, the identification of a stream with OpenTV channel numbers can be done automatically. Refs #13472 Fixes #13547 Signed-off-by: Klaas de Waal --- .../libmythtv/channelscan/channelscan_sm.cpp | 84 ++++++++++++++++++- .../libmythtv/channelscan/channelscan_sm.h | 6 ++ .../channelscan/channelscanmiscsettings.h | 12 +++ .../libmythtv/channelscan/channelscanner.cpp | 7 ++ .../libmythtv/channelscan/channelscanner.h | 4 + .../channelscan/scanwizardconfig.cpp | 7 ++ .../libmythtv/channelscan/scanwizardconfig.h | 1 + mythtv/libs/libmythtv/mpeg/dvbdescriptors.cpp | 11 +++ mythtv/libs/libmythtv/mpeg/dvbdescriptors.h | 32 +++++++ mythtv/libs/libmythtv/mpeg/dvbstreamdata.cpp | 36 ++++++++ .../libs/libmythtv/mpeg/mpegdescriptors.cpp | 8 ++ mythtv/libs/libmythtv/mpeg/mpegdescriptors.h | 11 +++ mythtv/libs/libmythtv/mpeg/mpegtables.h | 12 +++ mythtv/libs/libmythtv/scanwizard.cpp | 5 +- mythtv/libs/libmythtv/scanwizard.h | 2 + mythtv/programs/mythtv-setup/main.cpp | 4 + 16 files changed, 240 insertions(+), 2 deletions(-) diff --git a/mythtv/libs/libmythtv/channelscan/channelscan_sm.cpp b/mythtv/libs/libmythtv/channelscan/channelscan_sm.cpp index e3a066caf8e..53343c871c1 100644 --- a/mythtv/libs/libmythtv/channelscan/channelscan_sm.cpp +++ b/mythtv/libs/libmythtv/channelscan/channelscan_sm.cpp @@ -118,6 +118,7 @@ class ScannedChannelInfo nit_vec_t m_nits; sdt_map_t m_sdts; bat_vec_t m_bats; + QMap m_opentv_channels; }; /** \class ChannelScanSM @@ -158,6 +159,9 @@ ChannelScanSM::ChannelScanSM(ScanMonitor *_scan_monitor, m_channelTimeout(channel_timeout), m_inputName(std::move(_inputname)), m_testDecryption(test_decryption), + m_scanOpenTVBouquet(0), + m_scanOpenTVRegion(0), + m_scanOpenTVRegionMask(0), // Misc m_analogSignalHandler(new AnalogSignalHandler(this)) { @@ -192,7 +196,7 @@ ChannelScanSM::ChannelScanSM(ScanMonitor *_scan_monitor, } LOG(VB_CHANSCAN, LOG_INFO, LOC + - QString("Freesat/BSkyB bouquet_id:%1 region_id:%2") + QString("Freesat/BSkyB/OpenTV bouquet_id:%1 region_id:%2") .arg(m_bouquetId).arg(m_regionId)); dtvSigMon->SetStreamData(data); @@ -251,6 +255,27 @@ void ChannelScanSM::SetAnalog(bool is_analog) m_signalMonitor->AddListener(m_analogSignalHandler); } +void ChannelScanSM::SetOpenTV(void) +{ + if (m_bouquetId > 0) + { + m_scanOpenTVBouquet = m_bouquetId; + m_scanOpenTVRegion = m_regionId; + if (m_regionId) + m_scanOpenTVRegionMask = 1 << m_regionId; + else + m_scanOpenTVRegionMask = (uint)-1; + LOG(VB_GENERAL, LOG_INFO, LOC + + QString("Scan for OpenTV channels on bouquet ID %1 and region ID %2") + .arg(m_scanOpenTVBouquet).arg(m_scanOpenTVRegion)); + } + else + { + LOG(VB_GENERAL, LOG_WARNING, LOC + + QString("Cannot scan for OpenTV channels, bouquet ID is 0")); + } +} + void ChannelScanSM::HandleAllGood(void) { QMutexLocker locker(&m_lock); @@ -546,6 +571,44 @@ void ChannelScanSM::HandleBAT(const BouquetAssociationTable *bat) m_defAuthorities[index] = authority.DefaultAuthority(); } } + + if (m_scanOpenTVBouquet > 0) + { + const unsigned char *otv_chan_list = + MPEGDescriptor::Find(parsed, PrivateDescriptorID::opentv_channel_list); + if (otv_chan_list) + { + OpenTVChannelListDescriptor opentvChannelList(otv_chan_list); + + uint64_t regionMask = (uint64_t)-1; + if (opentvChannelList.RegionID() > 0 && opentvChannelList.RegionID() < 32) + regionMask = ((uint64_t)1) << opentvChannelList.RegionID(); + + for (uint j = 0; j < opentvChannelList.ChannelCount(); j++) + { + uint64_t index = ((uint64_t)netid << 32) | + bat->BouquetID() << 16 | + opentvChannelList.ServiceID(j); + if (!m_currentInfo) + m_currentInfo = new ScannedChannelInfo(); + if (m_currentInfo->m_opentv_channels.contains(index)) + { + m_currentInfo->m_opentv_channels[index] |= regionMask << 32; + } + else + { + m_currentInfo->m_opentv_channels[index] = + regionMask << 32 | + (opentvChannelList.ChannelID(j) << 16); + } + if (regionMask & m_scanOpenTVRegionMask) + { + m_currentInfo->m_opentv_channels[index] |= + opentvChannelList.ChannelNumber(j); + } + } + } + } } UpdateChannelInfo(true); } @@ -1654,6 +1717,25 @@ ChannelScanSM::GetChannelList(transport_scan_items_it_t trans_info, } } + // OpenTV Logical Channel Numbers + if (info.m_chanNum.isEmpty()) + { + if (m_scanOpenTVBouquet > 0) + { + qlonglong key = + ((qlonglong)info.m_origNetId<<32) | m_scanOpenTVBouquet << 16 | info.m_serviceId; + QMap::const_iterator it = scan_info->m_opentv_channels.find(key); + if (it != scan_info->m_opentv_channels.end()) + { + uint chanNum = (*it) & 0xffff; + if (chanNum > 0) + { + info.m_chanNum = chanNum; + } + } + } + } + LOG(VB_CHANSCAN, LOG_INFO, LOC + QString("GetChannelList: service %1 (0x%2) chan_num '%3' callsign '%4'") .arg(info.m_serviceId).arg(info.m_serviceId,4,16,QChar('0')) diff --git a/mythtv/libs/libmythtv/channelscan/channelscan_sm.h b/mythtv/libs/libmythtv/channelscan/channelscan_sm.h index f0e50e65aaa..f216d6b301e 100644 --- a/mythtv/libs/libmythtv/channelscan/channelscan_sm.h +++ b/mythtv/libs/libmythtv/channelscan/channelscan_sm.h @@ -121,6 +121,7 @@ class ChannelScanSM : public MPEGStreamListener, void SetChannelTimeout(uint val) { m_channelTimeout = val; } void SetScanDTVTunerType(DTVTunerType t) { m_scanDTVTunerType = t; } void SetScanDTVTunerType(int t) { m_scanDTVTunerType = DTVTunerType(t); } + void SetOpenTV(void); uint GetSignalTimeout(void) const { return m_signalTimeout; } uint GetChannelTimeout(void) const { return m_channelTimeout; } @@ -225,6 +226,11 @@ class ChannelScanSM : public MPEGStreamListener, // Optional info DTVTunerType m_scanDTVTunerType {DTVTunerType::kTunerTypeUnknown}; + // OpenTV + uint m_scanOpenTVBouquet {0}; + uint m_scanOpenTVRegion {0}; + uint m_scanOpenTVRegionMask {0}; + /// The big lock mutable QMutex m_lock; diff --git a/mythtv/libs/libmythtv/channelscan/channelscanmiscsettings.h b/mythtv/libs/libmythtv/channelscan/channelscanmiscsettings.h index e0d395f47d3..ec774cdf3ec 100644 --- a/mythtv/libs/libmythtv/channelscan/channelscanmiscsettings.h +++ b/mythtv/libs/libmythtv/channelscan/channelscanmiscsettings.h @@ -201,6 +201,18 @@ class TrustEncSISetting : public TransMythUICheckBoxSetting } }; +class ScanOpenTV: public TransMythUICheckBoxSetting +{ + public: + ScanOpenTV() + { + setLabel(QObject::tr("Scan OpenTV")); + setHelpText(QObject::tr("Scan for OpenTV channel numbers.\n" + "Set the Bouquet ID and Region ID in the Video Source.")); + setValue(false); + }; +}; + class ScanFrequencykHz: public TransTextEditSetting { public: diff --git a/mythtv/libs/libmythtv/channelscan/channelscanner.cpp b/mythtv/libs/libmythtv/channelscan/channelscanner.cpp index f20db6b5842..e3f1b7881fc 100644 --- a/mythtv/libs/libmythtv/channelscan/channelscanner.cpp +++ b/mythtv/libs/libmythtv/channelscan/channelscanner.cpp @@ -121,6 +121,7 @@ void ChannelScanner::Scan( bool do_complete_only, bool do_full_channel_search, bool do_add_full_ts, + bool do_scanOpenTV, ServiceRequirements service_requirements, // stuff needed for particular scans uint mplexid /* TransportScan */, @@ -136,6 +137,7 @@ void ChannelScanner::Scan( m_completeOnly = do_complete_only; m_fullSearch = do_full_channel_search; m_addFullTS = do_add_full_ts; + m_scanOpenTV = do_scanOpenTV; m_serviceRequirements = service_requirements; m_sourceid = sourceid; @@ -155,6 +157,11 @@ void ChannelScanner::Scan( bool ok = false; + if (do_scanOpenTV) + { + m_sigmonScanner->SetOpenTV(); + } + if ((ScanTypeSetting::FullScan_ATSC == scantype) || (ScanTypeSetting::FullScan_DVBC == scantype) || (ScanTypeSetting::FullScan_DVBT == scantype) || diff --git a/mythtv/libs/libmythtv/channelscan/channelscanner.h b/mythtv/libs/libmythtv/channelscan/channelscanner.h index 66e0f9b7d90..c737e6dfda2 100644 --- a/mythtv/libs/libmythtv/channelscan/channelscanner.h +++ b/mythtv/libs/libmythtv/channelscan/channelscanner.h @@ -80,6 +80,7 @@ class MTV_PUBLIC ChannelScanner bool do_complete_only, bool do_full_channel_search, bool do_add_full_ts, + bool do_scanOpenTV, ServiceRequirements service_requirements, // stuff needed for particular scans uint mplexid, @@ -150,6 +151,9 @@ class MTV_PUBLIC ChannelScanner /// Add MPTS "full transport stream" channels bool m_addFullTS {false}; + /// Scan for OpenTV channel numbers + bool m_scanOpenTV {false}; + int m_sourceid {-1}; /// Services desired post scan diff --git a/mythtv/libs/libmythtv/channelscan/scanwizardconfig.cpp b/mythtv/libs/libmythtv/channelscan/scanwizardconfig.cpp index 5e4a76e4a34..7bfe4e4c234 100644 --- a/mythtv/libs/libmythtv/channelscan/scanwizardconfig.cpp +++ b/mythtv/libs/libmythtv/channelscan/scanwizardconfig.cpp @@ -37,6 +37,7 @@ void ScanWizard::SetupConfig( m_fullSearch = new FullChannelSearch(); m_addFullTS = new AddFullTS(); m_trustEncSI = new TrustEncSISetting(); + m_scanOpenTV = new ScanOpenTV(); setLabel(tr("Channel Scan")); @@ -47,6 +48,7 @@ void ScanWizard::SetupConfig( addChild(m_fullSearch); addChild(m_addFullTS); addChild(m_trustEncSI); + addChild(m_scanOpenTV); addChild(m_videoSource); addChild(m_input); @@ -110,6 +112,11 @@ bool ScanWizard::DoTestDecryption(void) const return m_trustEncSI->boolValue(); } +bool ScanWizard::DoScanOpenTV(void) const +{ + return m_scanOpenTV->boolValue(); +} + void ScanWizard::SetPaneDefaults(const QString &cardid_inputname) { const int sourceid = m_videoSource->getValue().toInt(); diff --git a/mythtv/libs/libmythtv/channelscan/scanwizardconfig.h b/mythtv/libs/libmythtv/channelscan/scanwizardconfig.h index 0b4d968d632..cecfd992e77 100644 --- a/mythtv/libs/libmythtv/channelscan/scanwizardconfig.h +++ b/mythtv/libs/libmythtv/channelscan/scanwizardconfig.h @@ -49,6 +49,7 @@ class CompleteChannelsOnly; class FullChannelSearch; class AddFullTS; class TrustEncSISetting; +class ScanOpenTV; class PaneAll; class PaneATSC; diff --git a/mythtv/libs/libmythtv/mpeg/dvbdescriptors.cpp b/mythtv/libs/libmythtv/mpeg/dvbdescriptors.cpp index 23217ff699b..89fed639509 100644 --- a/mythtv/libs/libmythtv/mpeg/dvbdescriptors.cpp +++ b/mythtv/libs/libmythtv/mpeg/dvbdescriptors.cpp @@ -682,6 +682,17 @@ QString FreesatCallsignDescriptor::toString(void) const return ret; } +QString OpenTVChannelListDescriptor::toString() const +{ + QString ret = QString("OpenTV ChannelList Descriptor region: %1 sid->chan_num(id): ").arg(RegionID()); + for (uint i = 0; i < ChannelCount(); i++) + { + ret += QString("%1->%2(%3)").arg(ServiceID(i)).arg(ChannelNumber(i)).arg(ChannelID(i)); + ret += (i+1