diff options
-rw-r--r-- | TODO | 6 | ||||
-rw-r--r-- | doc/advanced.mux | 21 | ||||
-rw-r--r-- | doc/example.mux | 11 | ||||
-rw-r--r-- | src/ConfigParser.cpp | 1 | ||||
-rw-r--r-- | src/MuxElements.h | 6 | ||||
-rw-r--r-- | src/fig/FIG0_9.cpp | 108 | ||||
-rw-r--r-- | src/fig/FIG0_9.h | 20 |
7 files changed, 147 insertions, 26 deletions
@@ -69,12 +69,6 @@ TIST, and the ClockTAI class can get the information from the Internet, but it is not used in FIG0/10. -Add support for services with different ECC than ensemble ---------------------------------------------------------- -FIG 0/9 can transmit an Extended field for this information. Needs change of -configuration file, internal structures and FIG 0/9. - - Implement FIG0/20 Service List ------------------------------ See ETSI TS 103 176 diff --git a/doc/advanced.mux b/doc/advanced.mux index 375bef0..f6e59fe 100644 --- a/doc/advanced.mux +++ b/doc/advanced.mux @@ -55,8 +55,9 @@ remotecontrol { ; Some ensemble parameters ensemble { + ; Example for Switzerland, with country id=4 and ECC=E1 id 0x4fff ; you can also use decimal if you want - ecc 0xec ; Extended Country Code + ecc 0xe1 ; Extended Country Code local-time-offset auto ; autmatically calculate from system local time ; or @@ -91,7 +92,7 @@ services { ; Each service has it's own unique identifier, that is ; used throughout the configuration file and for the RC. srv-fu { - id 0x8daa + id 0x4daa label "Funk" shortlabel "Fu" @@ -127,16 +128,18 @@ services { clusters "1,2" } } - srv-lu { - id 0x8dab - label "Luschtig" - ; pty, language, shortlabel and id can be omitted, and will take default values - } srv-ri { - id 0x8dac + ; If your ensemble contains a service from another country, + ; specify its ECC here. Example is for Italy, country id=5, ECC=E0 + id 0x5dab + ecc 0xe0 label "rick" } - + srv-lu { + id 0x4dac + label "Lu" + ; pty, language, shortlabel and id can be omitted, and will take default values + } } ; The subchannels are defined in the corresponding section. diff --git a/doc/example.mux b/doc/example.mux index 632772d..7bd9e3e 100644 --- a/doc/example.mux +++ b/doc/example.mux @@ -70,8 +70,10 @@ ensemble { ; A unique 16-bit id is allocated to the ensemble and allows unambiguous ; identification of the ensemble when associated with the ensemble ECC. ; The id normally starts with the coutry id. (See ETSI TS 101 756) + + ; Example for Switzerland, with country id=4 and ECC=E1 id 0x4fff ; you can also use decimal if you want - ecc 0xec ; Extended Country Code + ecc 0xe1 ; Extended Country Code local-time-offset auto ; autmatically calculate from system local time ; or @@ -99,12 +101,15 @@ services { ; Each service has it's own unique identifier, that is ; used throughout the configuration file and for the RC. srv-fu { - id 0x8daa + id 0x4daa label "Fünk" ; You can define a shortlabel too. } srv-ri { - id 0x8dab + ; If your ensemble contains a service from another country, + ; specify its ECC here. Example is for Italy, country id=5, ECC=E0 + id 0x5dab + ecc 0xe0 label "Rick" } } 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 <map> + +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<uint8_t, list<uint16_t> > 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 <cstdint> -#include <vector> +#include <map> +#include <list> 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<uint16_t> sids; + + size_t required_bytes() const { + return 2 + 2 * sids.size(); + } + }; + std::list<FIG0_9_Extended_Field> m_extended_fields; + std::list<FIG0_9_Extended_Field>::iterator m_current_extended_field; + }; } |