From c97b43fc819e1e0e963183579d1b50f26f8c6f7f Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Sun, 2 Oct 2016 15:36:21 +0200 Subject: Regroup linkagesets into subsets of same type --- src/fig/FIG0_6.h | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) (limited to 'src/fig/FIG0_6.h') diff --git a/src/fig/FIG0_6.h b/src/fig/FIG0_6.h index db55c06..1af396f 100644 --- a/src/fig/FIG0_6.h +++ b/src/fig/FIG0_6.h @@ -26,7 +26,7 @@ #pragma once #include -#include +#include #include #include "fig/FIG0structs.h" @@ -58,7 +58,20 @@ class FIG0_6 : public IFIG private: FIGRuntimeInformation *m_rti; bool m_initialised; - std::list >::iterator linkageSetFIG0_6; + + /* Update the linkageSubsets */ + void update(void); + + /* A LinkageSet can contain links of different types + * (DAB, FM, DRM, AMSS), but the FIG needs to send + * different FIGs for each of those, because the IdLQ flag + * is common to a list. + * + * We reorganise all LinkageSets into subsets that have + * the same type. + */ + std::list linkageSubsets; + std::list::iterator linkageSetFIG0_6; }; // FIG0/6 needs a change indicator, which is a short-form FIG (i.e. without the list) @@ -79,7 +92,7 @@ class FIG0_6_CEI : public IFIG private: FIGRuntimeInformation *m_rti; bool m_initialised; - std::list >::iterator linkageSetFIG0_6; + std::vector >::iterator linkageSetFIG0_6; }; } -- cgit v1.2.3 From 5c3c6d734ff0c57fd3d45746df23b96e0e7fc99e Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Mon, 10 Oct 2016 12:06:45 +0200 Subject: Add FIG0/6 CEI --- src/MuxElements.h | 4 ++- src/fig/FIG0_6.cpp | 87 +++++++++++++++++++++++++++++++++++++++++++++++-- src/fig/FIG0_6.h | 8 ++--- src/fig/FIGCarousel.cpp | 2 ++ src/fig/FIGCarousel.h | 1 + 5 files changed, 95 insertions(+), 7 deletions(-) (limited to 'src/fig/FIG0_6.h') diff --git a/src/MuxElements.h b/src/MuxElements.h index 8efc2cb..79100a9 100644 --- a/src/MuxElements.h +++ b/src/MuxElements.h @@ -229,7 +229,7 @@ class dabEnsemble : public RemoteControllable { std::vector subchannels; std::vector > clusters; - std::list > linkagesets; + std::vector > linkagesets; }; @@ -463,6 +463,8 @@ class LinkageSet : public RemoteControllable { LinkageSet(std::string name, uint16_t lsn, bool hard, bool international); LinkageSetData data; + + bool is_active(void) const { return data.active; } private: /* Remote control */ virtual void set_parameter(const std::string& parameter, diff --git a/src/fig/FIG0_6.cpp b/src/fig/FIG0_6.cpp index 401606e..411d47c 100644 --- a/src/fig/FIG0_6.cpp +++ b/src/fig/FIG0_6.cpp @@ -57,9 +57,9 @@ FillStatus FIG0_6::fill(uint8_t *buf, size_t max_size) const size_t num_ids = 1 + linkageSetFIG0_6->id_list.size(); const size_t headersize = sizeof(struct FIGtype0_6_header); - const int required_size = sizeof(struct FIGtype0_6) + + const int required_size = sizeof(struct FIGtype0_6) + headersize + (num_ids > 0 ? - headersize + (PD == 0 ? (ILS == 0 ? 2*num_ids : 3*num_ids) : 4*num_ids) : + (PD == 0 ? (ILS == 0 ? 2*num_ids : 3*num_ids) : 4*num_ids) : 0); if (fig0 == NULL) { @@ -266,5 +266,88 @@ void FIG0_6::update() #endif } + +FIG0_6_CEI::FIG0_6_CEI(FIGRuntimeInformation *rti) : + m_rti(rti) +{ +} + +FillStatus FIG0_6_CEI::fill(uint8_t *buf, size_t max_size) +{ + using namespace std; + + auto ensemble = m_rti->ensemble; + + // We are called every 24ms, and must timeout after 5s + const int timeout = 5000/24; + + m_transition.update_state(timeout, ensemble->linkagesets); + + FillStatus fs; + ssize_t remaining = max_size; + + FIGtype0* fig0 = NULL; + + // Combine all links into one list + set alllinks; + for (const auto& l : m_transition.new_entries) { + alllinks.insert(l.first.get()); + } + for (const auto& l : m_transition.repeated_entries) { + alllinks.insert(l.get()); + } + for (const auto& l : m_transition.disabled_entries) { + alllinks.insert(l.first.get()); + } + + for (auto& link : alllinks) { + const bool PD = false; + const bool ILS = link->data.international; + + // The CEI does not send list contents + const size_t num_ids = 0; + + const size_t headersize = sizeof(struct FIGtype0_6_header); + const int required_size = sizeof(struct FIGtype0_6) + headersize + + (num_ids > 0 ? + (PD == 0 ? (ILS == 0 ? 2*num_ids : 3*num_ids) : 4*num_ids) : + 0); + + if (fig0 == NULL) { + if (remaining < 2 + required_size) { + break; + } + fig0 = (FIGtype0*)buf; + fig0->FIGtypeNumber = 0; + fig0->Length = 1; + fig0->CN = 1; // This is a CEI + fig0->OE = 0; + fig0->PD = PD; + fig0->Extension = 6; + + buf += 2; + remaining -= 2; + } + else if (remaining < required_size) { + break; + } + + FIGtype0_6 *fig0_6 = (FIGtype0_6*)buf; + + fig0_6->IdListFlag = (num_ids > 0); + fig0_6->LA = link->data.active; + fig0_6->SH = link->data.hard; + fig0_6->ILS = ILS; + fig0_6->setLSN(link->data.lsn); + + fig0->Length += sizeof(struct FIGtype0_6); + buf += sizeof(struct FIGtype0_6); + remaining -= sizeof(struct FIGtype0_6); + } + + fs.complete_fig_transmitted = true; + return fs; +} + } diff --git a/src/fig/FIG0_6.h b/src/fig/FIG0_6.h index 1af396f..e970102 100644 --- a/src/fig/FIG0_6.h +++ b/src/fig/FIG0_6.h @@ -70,8 +70,8 @@ class FIG0_6 : public IFIG * We reorganise all LinkageSets into subsets that have * the same type. */ - std::list linkageSubsets; - std::list::iterator linkageSetFIG0_6; + std::vector linkageSubsets; + std::vector::iterator linkageSetFIG0_6; }; // FIG0/6 needs a change indicator, which is a short-form FIG (i.e. without the list) @@ -91,8 +91,8 @@ class FIG0_6_CEI : public IFIG private: FIGRuntimeInformation *m_rti; - bool m_initialised; - std::vector >::iterator linkageSetFIG0_6; + + TransitionHandler m_transition; }; } diff --git a/src/fig/FIGCarousel.cpp b/src/fig/FIGCarousel.cpp index ac2a80b..2fc6718 100644 --- a/src/fig/FIGCarousel.cpp +++ b/src/fig/FIGCarousel.cpp @@ -65,6 +65,7 @@ FIGCarousel::FIGCarousel(std::shared_ptr ensemble) : m_fig0_3(&m_rti), m_fig0_5(&m_rti), m_fig0_6(&m_rti), + m_fig0_6_cei(&m_rti), m_fig0_17(&m_rti), m_fig0_8(&m_rti), m_fig1_0(&m_rti), @@ -96,6 +97,7 @@ FIGCarousel::FIGCarousel(std::shared_ptr ensemble) : load_and_allocate(m_fig0_3, FIBAllocation::FIB_ANY); load_and_allocate(m_fig0_5, FIBAllocation::FIB_ANY); load_and_allocate(m_fig0_6, FIBAllocation::FIB_ANY); + load_and_allocate(m_fig0_6_cei, FIBAllocation::FIB_ANY); load_and_allocate(m_fig0_8, FIBAllocation::FIB_ANY); load_and_allocate(m_fig0_13, FIBAllocation::FIB_ANY); diff --git a/src/fig/FIGCarousel.h b/src/fig/FIGCarousel.h index f52f266..209fe19 100644 --- a/src/fig/FIGCarousel.h +++ b/src/fig/FIGCarousel.h @@ -90,6 +90,7 @@ class FIGCarousel { FIG0_3 m_fig0_3; FIG0_5 m_fig0_5; FIG0_6 m_fig0_6; + FIG0_6_CEI m_fig0_6_cei; FIG0_17 m_fig0_17; FIG0_8 m_fig0_8; FIG1_0 m_fig1_0; -- cgit v1.2.3 From 6800fb66282525542366bc58df3095b93e3bf8ca Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Mon, 28 Nov 2016 20:08:56 +0100 Subject: Remove service linking active from RC This can be added later if the need arises, and when proper testing validates the implementation. --- TODO | 9 ++--- doc/servicelinking.mux | 8 ++--- src/ConfigParser.cpp | 6 ++-- src/MuxElements.cpp | 57 +++++++------------------------ src/MuxElements.h | 58 ++++++++++++++----------------- src/fig/FIG0_6.cpp | 91 +++---------------------------------------------- src/fig/FIG0_6.h | 32 +++++------------ src/fig/FIGCarousel.cpp | 2 -- src/fig/FIGCarousel.h | 1 - src/utils.cpp | 19 +++++------ 10 files changed, 69 insertions(+), 214 deletions(-) (limited to 'src/fig/FIG0_6.h') diff --git a/TODO b/TODO index 50fc9b8..fb56034 100644 --- a/TODO +++ b/TODO @@ -18,11 +18,12 @@ Initial work started in http://git.mpb.li/git/odr-edilib/ Explicit Service Linking ------------------------ -At the moment there is no support to signal explicit service linking. -Implementing this needs a definition of how it should look like in the -configuration file and in the remote control, and adding new FIGs to signal the -necessary information. +It is impossible to activate/deactive linkage sets. Commit 5c3c6d7 added +some code to transmit a FIG0/6 CEI, but this was subsequently reverted +because it was not tested enough. +Announcement of other frequencies on which to find programmes using FIG 0/21 is +also missing. Inputs for packet data ---------------------- diff --git a/doc/servicelinking.mux b/doc/servicelinking.mux index 38c59ee..f50b3fa 100644 --- a/doc/servicelinking.mux +++ b/doc/servicelinking.mux @@ -7,7 +7,7 @@ ; general { dabmode 1 - nbframes 10000 + nbframes 0 syslog false tist false @@ -29,10 +29,6 @@ linking { ; (mandatory) lsn 0xabc - ; whether this link is active or a "potential future link or de-activated link" - ; This field is also part of the remote control. (default false) - active true - ; Hard link means that all services carry the same programme, soft links means ; that the programmes are related in some way. (default true) hard true @@ -78,7 +74,6 @@ linking { ; And now an international true to test more options set-ri { lsn 0xdef - active false hard soft international true keyservice srv-ri @@ -162,5 +157,6 @@ components { outputs { file "file://./test.eti?type=raw" + throttle "simul://" } diff --git a/src/ConfigParser.cpp b/src/ConfigParser.cpp index 1b6093e..7219663 100644 --- a/src/ConfigParser.cpp +++ b/src/ConfigParser.cpp @@ -137,7 +137,6 @@ static void parse_linkage(boost::property_tree::ptree& pt, throw runtime_error("Invalid service linking definition"); } - bool active = pt_set.get("active", false); bool hard = pt_set.get("hard", true); bool international = pt_set.get("international", false); @@ -149,8 +148,7 @@ static void parse_linkage(boost::property_tree::ptree& pt, } auto linkageset = make_shared(setuid, lsn, hard, international); - linkageset->data.active = active; - linkageset->data.keyservice = service_uid; // TODO check if it exists + linkageset->keyservice = service_uid; // TODO check if it exists auto pt_list = pt_set.get_child_optional("list"); if (not pt_list) { @@ -195,7 +193,7 @@ static void parse_linkage(boost::property_tree::ptree& pt, link.ecc = 0; } - linkageset->data.id_list.push_back(link); + linkageset->id_list.push_back(link); } ensemble->linkagesets.push_back(linkageset); } diff --git a/src/MuxElements.cpp b/src/MuxElements.cpp index 7f92652..9dbe5fc 100644 --- a/src/MuxElements.cpp +++ b/src/MuxElements.cpp @@ -662,53 +662,22 @@ unsigned short DabSubchannel::getSizeDWord() const return (bitrate * 3) >> 3; } -LinkageSet::LinkageSet(string name, uint16_t lsn, bool hard, bool international) : - RemoteControllable(name) +LinkageSet::LinkageSet(const std::string& name, + uint16_t lsn, + bool hard, + bool international) : + lsn(lsn), + active(true), + hard(hard), + international(international) +{} + + +LinkageSet LinkageSet::filter_type(const ServiceLinkType type) { - data.lsn = lsn; - data.active = false; - data.hard = hard; - data.international = international; - RC_ADD_PARAMETER(active, "Activate this linkage set [0 or 1]"); -} - -void LinkageSet::set_parameter(const string& parameter, const string& value) -{ - if (parameter == "active") { - stringstream ss; - ss << value; - ss >> data.active; - } - else { - stringstream ss; - ss << "Parameter '" << parameter << - "' is not exported by controllable " << get_rc_name(); - throw ParameterError(ss.str()); - } -} - -const string LinkageSet::get_parameter(const string& parameter) const -{ - stringstream ss; - if (parameter == "active") { - ss << data.active; - } - else { - ss << "Parameter '" << parameter << - "' is not exported by controllable " << get_rc_name(); - throw ParameterError(ss.str()); - } - return ss.str(); -} - -LinkageSetData LinkageSetData::filter_type(ServiceLinkType type) -{ - LinkageSetData lsd; + LinkageSet lsd(m_name, lsn, hard, international); - lsd.lsn = lsn; lsd.active = active; - lsd.hard = hard; - lsd.international = international; lsd.keyservice = keyservice; for (const auto& link : id_list) { diff --git a/src/MuxElements.h b/src/MuxElements.h index 7ff23a6..968fb14 100644 --- a/src/MuxElements.h +++ b/src/MuxElements.h @@ -432,46 +432,40 @@ struct ServiceLink { uint8_t ecc; }; -/* Keep the data out of LinkageSet to make it copyable */ -struct LinkageSetData { - std::list id_list; - - /* Linkage Set Number is a 12-bit number that identifies the linkage - * set in a country (requires coordination between multiplex operators - * in a country) - */ - uint16_t lsn; - - bool active; // Remote-controllable - bool hard; - bool international; - - std::string keyservice; // TODO replace by pointer to service - - /* Return a LinkageSetData with id_list filtered to include - * only those links of a given type - */ - LinkageSetData filter_type(ServiceLinkType type); -}; - /* Represents a linkage set linkage sets according to * TS 103 176 Clause 5.2.3 "Linkage sets". This information will * be encoded in FIG 0/6. */ -class LinkageSet : public RemoteControllable { +class LinkageSet { public: - LinkageSet(std::string name, uint16_t lsn, bool hard, bool international); + LinkageSet(const std::string& name, + uint16_t lsn, + bool hard, + bool international); - LinkageSetData data; + std::string get_name(void) const { return m_name; } - bool is_active(void) const { return data.active; } - private: - /* Remote control */ - virtual void set_parameter(const std::string& parameter, - const std::string& value); + std::list id_list; - /* Getting a parameter always returns a string. */ - virtual const std::string get_parameter(const std::string& parameter) const; + /* Linkage Set Number is a 12-bit number that identifies the linkage + * set in a country (requires coordination between multiplex operators + * in a country) + */ + uint16_t lsn; + + bool active; // TODO: Remote-controllable + bool hard; + bool international; + + std::string keyservice; // TODO replace by pointer to service + + /* Return a LinkageSet with id_list filtered to include + * only those links of a given type + */ + LinkageSet filter_type(const ServiceLinkType type); + + private: + std::string m_name; }; std::vector::iterator getSubchannel( diff --git a/src/fig/FIG0_6.cpp b/src/fig/FIG0_6.cpp index 411d47c..5174ec2 100644 --- a/src/fig/FIG0_6.cpp +++ b/src/fig/FIG0_6.cpp @@ -210,21 +210,21 @@ void FIG0_6::update() // TODO check if AMSS and DRM have to be put into a single subset for (const auto& linkageset : m_rti->ensemble->linkagesets) { - const auto lsn = linkageset->data.lsn; + const auto lsn = linkageset->lsn; - for (const auto& link : linkageset->data.id_list) { + for (const auto& link : linkageset->id_list) { const auto type = link.type; const auto subset = std::find_if(linkageSubsets.begin(), linkageSubsets.end(), - [&](const LinkageSetData& l) { + [&](const LinkageSet& l) { return not l.id_list.empty() and l.lsn == lsn and l.id_list.front().type == type; }); if (subset == linkageSubsets.end()) { // A subset with that LSN and type does not exist yet - linkageSubsets.push_back( linkageset->data.filter_type(type) ); + linkageSubsets.push_back( linkageset->filter_type(type) ); } } } @@ -266,88 +266,5 @@ void FIG0_6::update() #endif } - -FIG0_6_CEI::FIG0_6_CEI(FIGRuntimeInformation *rti) : - m_rti(rti) -{ -} - -FillStatus FIG0_6_CEI::fill(uint8_t *buf, size_t max_size) -{ - using namespace std; - - auto ensemble = m_rti->ensemble; - - // We are called every 24ms, and must timeout after 5s - const int timeout = 5000/24; - - m_transition.update_state(timeout, ensemble->linkagesets); - - FillStatus fs; - ssize_t remaining = max_size; - - FIGtype0* fig0 = NULL; - - // Combine all links into one list - set alllinks; - for (const auto& l : m_transition.new_entries) { - alllinks.insert(l.first.get()); - } - for (const auto& l : m_transition.repeated_entries) { - alllinks.insert(l.get()); - } - for (const auto& l : m_transition.disabled_entries) { - alllinks.insert(l.first.get()); - } - - for (auto& link : alllinks) { - const bool PD = false; - const bool ILS = link->data.international; - - // The CEI does not send list contents - const size_t num_ids = 0; - - const size_t headersize = sizeof(struct FIGtype0_6_header); - const int required_size = sizeof(struct FIGtype0_6) + headersize + - (num_ids > 0 ? - (PD == 0 ? (ILS == 0 ? 2*num_ids : 3*num_ids) : 4*num_ids) : - 0); - - if (fig0 == NULL) { - if (remaining < 2 + required_size) { - break; - } - fig0 = (FIGtype0*)buf; - fig0->FIGtypeNumber = 0; - fig0->Length = 1; - fig0->CN = 1; // This is a CEI - fig0->OE = 0; - fig0->PD = PD; - fig0->Extension = 6; - - buf += 2; - remaining -= 2; - } - else if (remaining < required_size) { - break; - } - - FIGtype0_6 *fig0_6 = (FIGtype0_6*)buf; - - fig0_6->IdListFlag = (num_ids > 0); - fig0_6->LA = link->data.active; - fig0_6->SH = link->data.hard; - fig0_6->ILS = ILS; - fig0_6->setLSN(link->data.lsn); - - fig0->Length += sizeof(struct FIGtype0_6); - buf += sizeof(struct FIGtype0_6); - remaining -= sizeof(struct FIGtype0_6); - } - - fs.complete_fig_transmitted = true; - return fs; -} - } diff --git a/src/fig/FIG0_6.h b/src/fig/FIG0_6.h index e970102..e7c81c5 100644 --- a/src/fig/FIG0_6.h +++ b/src/fig/FIG0_6.h @@ -30,10 +30,15 @@ #include #include "fig/FIG0structs.h" -#include "fig/TransitionHandler.h" namespace FIC { +/* TODO + * This FIG code is unable to transmit the CEI to announce + * activation/deactivation of linkage sets. + * The TransitionHandler.h would be useful for that purpose + */ + // FIG type 0/6 // Service Linking // @@ -70,29 +75,8 @@ class FIG0_6 : public IFIG * We reorganise all LinkageSets into subsets that have * the same type. */ - std::vector linkageSubsets; - std::vector::iterator linkageSetFIG0_6; -}; - -// FIG0/6 needs a change indicator, which is a short-form FIG (i.e. without the list) -// and with C/N 1. Since this has another rate, it's implemented in another class. -// -// This is signalled once per second for a period of five seconds -// (TS 103 176 5.2.4.3). -class FIG0_6_CEI : public IFIG -{ - public: - FIG0_6_CEI(FIGRuntimeInformation* rti); - virtual FillStatus fill(uint8_t *buf, size_t max_size); - virtual FIG_rate repetition_rate(void) { return FIG_rate::B; } - - virtual const int figtype(void) const { return 0; } - virtual const int figextension(void) const { return 6; } - - private: - FIGRuntimeInformation *m_rti; - - TransitionHandler m_transition; + std::vector linkageSubsets; + std::vector::iterator linkageSetFIG0_6; }; } diff --git a/src/fig/FIGCarousel.cpp b/src/fig/FIGCarousel.cpp index 2fc6718..ac2a80b 100644 --- a/src/fig/FIGCarousel.cpp +++ b/src/fig/FIGCarousel.cpp @@ -65,7 +65,6 @@ FIGCarousel::FIGCarousel(std::shared_ptr ensemble) : m_fig0_3(&m_rti), m_fig0_5(&m_rti), m_fig0_6(&m_rti), - m_fig0_6_cei(&m_rti), m_fig0_17(&m_rti), m_fig0_8(&m_rti), m_fig1_0(&m_rti), @@ -97,7 +96,6 @@ FIGCarousel::FIGCarousel(std::shared_ptr ensemble) : load_and_allocate(m_fig0_3, FIBAllocation::FIB_ANY); load_and_allocate(m_fig0_5, FIBAllocation::FIB_ANY); load_and_allocate(m_fig0_6, FIBAllocation::FIB_ANY); - load_and_allocate(m_fig0_6_cei, FIBAllocation::FIB_ANY); load_and_allocate(m_fig0_8, FIBAllocation::FIB_ANY); load_and_allocate(m_fig0_13, FIBAllocation::FIB_ANY); diff --git a/src/fig/FIGCarousel.h b/src/fig/FIGCarousel.h index 209fe19..f52f266 100644 --- a/src/fig/FIGCarousel.h +++ b/src/fig/FIGCarousel.h @@ -90,7 +90,6 @@ class FIGCarousel { FIG0_3 m_fig0_3; FIG0_5 m_fig0_5; FIG0_6 m_fig0_6; - FIG0_6_CEI m_fig0_6_cei; FIG0_17 m_fig0_17; FIG0_8 m_fig0_8; FIG1_0 m_fig1_0; diff --git a/src/utils.cpp b/src/utils.cpp index 4431407..4c08e8b 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -369,18 +369,17 @@ void printSubchannels(vector& subchannels) static void printLinking(const shared_ptr ensemble) { etiLog.log(info, " Linkage Sets"); - for (const auto& linkageset : ensemble->linkagesets) { - const auto& lsd = linkageset->data; + for (const auto& ls : ensemble->linkagesets) { - etiLog.level(info) << " set " << linkageset->get_rc_name(); - etiLog.log(info, " LSN 0x%04x", lsd.lsn); - etiLog.level(info) << " active " << (lsd.active ? "true" : "false"); - etiLog.level(info) << " " << (lsd.hard ? "hard" : "soft"); - etiLog.level(info) << " international " << (lsd.international ? "true" : "false"); - etiLog.level(info) << " key service " << lsd.keyservice; + etiLog.level(info) << " set " << ls->get_name(); + etiLog.log(info, " LSN 0x%04x", ls->lsn); + etiLog.level(info) << " active " << (ls->active ? "true" : "false"); + etiLog.level(info) << " " << (ls->hard ? "hard" : "soft"); + etiLog.level(info) << " international " << (ls->international ? "true" : "false"); + etiLog.level(info) << " key service " << ls->keyservice; etiLog.level(info) << " ID list"; - for (const auto& link : lsd.id_list) { + for (const auto& link : ls->id_list) { switch (link.type) { case ServiceLinkType::DAB: etiLog.level(info) << " type DAB"; @@ -396,7 +395,7 @@ static void printLinking(const shared_ptr ensemble) break; } etiLog.log(info, " id 0x%04x", link.id); - if (lsd.international) { + if (ls->international) { etiLog.log(info, " ecc 0x%04x", link.ecc); } } -- cgit v1.2.3