From 203b42f0b5a7ed53442b9e0a0072dec48b7f5eb6 Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Tue, 31 Jul 2018 11:51:23 +0200 Subject: Add support for services with different ECC in FIG0/9 --- src/ConfigParser.cpp | 1 + src/MuxElements.h | 6 +++ src/fig/FIG0_9.cpp | 108 ++++++++++++++++++++++++++++++++++++++++++++++++--- src/fig/FIG0_9.h | 20 ++++++++-- 4 files changed, 127 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/ConfigParser.cpp b/src/ConfigParser.cpp index 544f89c..d484787 100644 --- a/src/ConfigParser.cpp +++ b/src/ConfigParser.cpp @@ -581,6 +581,7 @@ void parse_ptree( } service->id = new_service_id; + service->ecc = hexparse(pt_service.get("ecc", "0")); service->pty_settings.pty = hexparse(pt_service.get("pty", "0")); // Default to dynamic for backward compatibility const string dynamic_no_static_str = pt_service.get("pty-sd", "dynamic"); diff --git a/src/MuxElements.h b/src/MuxElements.h index 259d5d9..09bf072 100644 --- a/src/MuxElements.h +++ b/src/MuxElements.h @@ -407,6 +407,12 @@ class DabService : public RemoteControllable std::string uid; uint32_t id = 0; + + /* Services with different ECC than the ensemble must be signalled in FIG0/9. + * here, leave at 0 if they have the same as the ensemble + */ + uint8_t ecc = 0; + struct pty_settings_t { uint8_t pty = 0; // 0 means disabled bool dynamic_no_static = false; diff --git a/src/fig/FIG0_9.cpp b/src/fig/FIG0_9.cpp index 06f2125..cf73625 100644 --- a/src/fig/FIG0_9.cpp +++ b/src/fig/FIG0_9.cpp @@ -3,7 +3,7 @@ 2011, 2012 Her Majesty the Queen in Right of Canada (Communications Research Center Canada) - Copyright (C) 2016 + Copyright (C) 2018 Matthias P. Braendli, matthias.braendli@mpb.li */ /* @@ -26,6 +26,9 @@ #include "fig/FIG0structs.h" #include "fig/FIG0_9.h" #include "utils.h" +#include + +using namespace std; namespace FIC { @@ -44,6 +47,14 @@ struct FIGtype0_9 { uint8_t tableId; } PACKED; +struct FIGtype0_9_Subfield { + uint8_t Rfa2:6; + uint8_t NumServices:2; + + uint8_t ecc; + // Followed by list of NumServices uint16_t SIDs +} PACKED; + FIG0_9::FIG0_9(FIGRuntimeInformation *rti) : m_rti(rti) {} @@ -53,7 +64,64 @@ FillStatus FIG0_9::fill(uint8_t *buf, size_t max_size) auto ensemble = m_rti->ensemble; size_t remaining = max_size; - if (remaining < 5) { + if (m_extended_fields.empty()) { + map > ecc_to_services; + for (const auto& srv : ensemble->services) { + if (srv->ecc != 0 and srv->ecc != ensemble->ecc and + srv->isProgramme(ensemble)) { + if (srv->id > 0xFFFF) { + throw std::logic_error( + "Service ID for programme service > 0xFFFF"); + } + ecc_to_services[srv->ecc].push_back(srv->id); + } + } + + // Reorganise the data so that it fits into the + // extended field. Max 3 SIds per sub-field. + for (auto& ecc_sids_pair : ecc_to_services) { + FIG0_9_Extended_Field ef; + ef.ecc = ecc_sids_pair.first; + + size_t i = 0; + for (auto& sid : ecc_sids_pair.second) { + if (i == 3) { + m_extended_fields.push_back(ef); + ef.sids.clear(); + i = 0; + } + + ef.sids.push_back(sid); + i++; + } + + if (not ef.sids.empty()) { + m_extended_fields.push_back(ef); + } + } + m_current_extended_field = m_extended_fields.begin(); + + for (const auto& ef : m_extended_fields) { + stringstream ss; + ss << "FIG0_9 Ext ECC 0x" << hex << (int)ef.ecc << dec << ":"; + + for (auto& sid : ef.sids) { + ss << " " << hex << (int)sid << dec; + } + ss << "."; + etiLog.level(debug) << ss.str(); + } + } + + size_t required = 5; + + // If we have services with different ECC, avoid transmitting a + // FIG0/9 without any extended field. + if (m_current_extended_field != m_extended_fields.end()) { + required += 2 + 2 * m_current_extended_field->sids.size(); + } + + if (remaining < required) { fs.num_bytes_written = 0; return fs; } @@ -66,7 +134,7 @@ FillStatus FIG0_9::fill(uint8_t *buf, size_t max_size) fig0_9->PD = 0; fig0_9->Extension = 9; - fig0_9->ext = 0; + fig0_9->ext = m_extended_fields.empty() ? 0 : 1; fig0_9->rfa1 = 0; // Had a different meaning in EN 300 401 V1.4.1 if (ensemble->lto_auto) { @@ -89,10 +157,40 @@ FillStatus FIG0_9::fill(uint8_t *buf, size_t max_size) buf += 5; remaining -= 5; - /* No extended field, no support for services with different ECC */ + while (m_current_extended_field != m_extended_fields.end() and + remaining > m_current_extended_field->required_bytes()) { + if (m_current_extended_field->sids.size() > 3) { + throw logic_error("Wrong FIG0/9 subfield generation"); + } + + auto subfield = (FIGtype0_9_Subfield*)buf; + subfield->NumServices = m_current_extended_field->sids.size(); + subfield->Rfa2 = 0; + subfield->ecc = m_current_extended_field->ecc; + buf += 2; + fig0_9->Length += 2; + remaining -= 2; + + for (uint16_t sid : m_current_extended_field->sids) { + uint16_t *sid_field = (uint16_t*)buf; + *sid_field = htons(sid); + buf += 2; + fig0_9->Length += 2; + remaining -= 2; + } + + ++m_current_extended_field; + } fs.num_bytes_written = max_size - remaining; - fs.complete_fig_transmitted = true; + + if (m_current_extended_field == m_extended_fields.end()) { + fs.complete_fig_transmitted = true; + m_current_extended_field = m_extended_fields.begin(); + } + else { + fs.complete_fig_transmitted = false; + } return fs; } diff --git a/src/fig/FIG0_9.h b/src/fig/FIG0_9.h index 0a71fa0..ebbf81f 100644 --- a/src/fig/FIG0_9.h +++ b/src/fig/FIG0_9.h @@ -3,7 +3,7 @@ 2011, 2012 Her Majesty the Queen in Right of Canada (Communications Research Center Canada) - Copyright (C) 2016 + Copyright (C) 2018 Matthias P. Braendli, matthias.braendli@mpb.li */ /* @@ -26,13 +26,15 @@ #pragma once #include -#include +#include +#include namespace FIC { // FIG type 0/9 // The Country, LTO and International table feature defines the local time -// offset, the International Table and the Extended Country Code (ECC) +// offset, the International Table and the Extended Country Code (ECC) for +// the ensemble. Also, the ECC for services with differing ECC. class FIG0_9 : public IFIG { public: @@ -45,6 +47,18 @@ class FIG0_9 : public IFIG private: FIGRuntimeInformation *m_rti; + + struct FIG0_9_Extended_Field { + uint8_t ecc; + std::list sids; + + size_t required_bytes() const { + return 2 + 2 * sids.size(); + } + }; + std::list m_extended_fields; + std::list::iterator m_current_extended_field; + }; } -- cgit v1.2.3