From f1832dd977078a60b343673c60092d3d5d030398 Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Mon, 5 Jun 2017 17:51:47 +0200 Subject: Add initial implementation for FIG0/24 --- doc/servicelinking.mux | 5 ++ src/ConfigParser.cpp | 24 +++++++ src/Makefile.am | 1 + src/MuxElements.h | 3 + src/fig/FIG0.h | 1 + src/fig/FIG0_24.cpp | 177 ++++++++++++++++++++++++++++++++++++++++++++++++ src/fig/FIG0_24.h | 53 +++++++++++++++ src/fig/FIGCarousel.cpp | 6 +- src/fig/FIGCarousel.h | 3 +- 9 files changed, 270 insertions(+), 3 deletions(-) create mode 100644 src/fig/FIG0_24.cpp create mode 100644 src/fig/FIG0_24.h diff --git a/doc/servicelinking.mux b/doc/servicelinking.mux index 6c491c8..03c842a 100644 --- a/doc/servicelinking.mux +++ b/doc/servicelinking.mux @@ -160,6 +160,11 @@ services { srv-fu { id 0x8daa label "Funk" + + ; If this service is present in other ensembles, it can be announced + ; through FIG0/24. other_ensembles is a comma separated list of + ; ensemble IDs (decimal or hexadecimal with 0x prefix) + other_ensembles "0x4ffe,0x4ffd" } srv-ri { id 0x8dab diff --git a/src/ConfigParser.cpp b/src/ConfigParser.cpp index 8c7e6b4..3f977ad 100644 --- a/src/ConfigParser.cpp +++ b/src/ConfigParser.cpp @@ -511,6 +511,30 @@ void parse_ptree( serviceuid; } + try { + auto oelist = pt_service.get("other_ensembles", ""); + vector oe_string_list; + boost::split(oe_string_list, oelist, boost::is_any_of(",")); + + for (const auto& oe_string : oe_string_list) { + if (oe_string == "") { + continue; + } + try { + service->other_ensembles.push_back(hexparse(oe_string)); + } + catch (std::logic_error& e) { + etiLog.level(warn) << "Cannot parse '" << oelist << + "' announcement clusters for service " << serviceuid << + ": " << e.what(); + } + } + } + catch (ptree_error& e) { + etiLog.level(info) << "No other_sensmbles information for Service " << + serviceuid; + } + int success = -5; string servicelabel = pt_service.get("label"); diff --git a/src/Makefile.am b/src/Makefile.am index 4ee8792..12934f0 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -96,6 +96,7 @@ odr_dabmux_SOURCES =DabMux.cpp DabMux.h \ fig/FIG0_18.cpp fig/FIG0_18.h \ fig/FIG0_19.cpp fig/FIG0_19.h \ fig/FIG0_21.cpp fig/FIG0_21.h \ + fig/FIG0_24.cpp fig/FIG0_24.h \ fig/FIG1.cpp fig/FIG1.h \ fig/FIGCarousel.cpp fig/FIGCarousel.h \ fig/TransitionHandler.h \ diff --git a/src/MuxElements.h b/src/MuxElements.h index 7f1b828..6a1ca74 100644 --- a/src/MuxElements.h +++ b/src/MuxElements.h @@ -406,6 +406,9 @@ class DabService : public RemoteControllable uint16_t ASu = 0; std::vector clusters; + // Ensembles in which this service is also available, used for FIG0/24 + std::vector other_ensembles; + subchannel_type_t getType(const std::shared_ptr ensemble) const; bool isProgramme(const std::shared_ptr& ensemble) const; unsigned char nbComponent(const std::vector& components) const; diff --git a/src/fig/FIG0.h b/src/fig/FIG0.h index d8de751..856b5ee 100644 --- a/src/fig/FIG0.h +++ b/src/fig/FIG0.h @@ -40,4 +40,5 @@ #include "fig/FIG0_18.h" #include "fig/FIG0_19.h" #include "fig/FIG0_21.h" +#include "fig/FIG0_24.h" diff --git a/src/fig/FIG0_24.cpp b/src/fig/FIG0_24.cpp new file mode 100644 index 0000000..af3f043 --- /dev/null +++ b/src/fig/FIG0_24.cpp @@ -0,0 +1,177 @@ +/* + Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, + 2011, 2012 Her Majesty the Queen in Right of Canada (Communications + Research Center Canada) + + Copyright (C) 2017 + Matthias P. Braendli, matthias.braendli@mpb.li + */ +/* + This file is part of ODR-DabMux. + + ODR-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + ODR-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ODR-DabMux. If not, see . +*/ + +#include "fig/FIG0structs.h" +#include "fig/FIG0_24.h" +#include "utils.h" + +#warning "fig0/24 rate" + +namespace FIC { + +struct FIGtype0_24_audioservice { + uint16_t SId; + uint8_t Length:4; + uint8_t CAId:3; + uint8_t rfa:1; +} PACKED; + +struct FIGtype0_24_dataservice { + uint32_t SId; + uint8_t Length:4; + uint8_t CAId:3; + uint8_t rfa:1; +} PACKED; + + +FIG0_24::FIG0_24(FIGRuntimeInformation *rti) : + m_rti(rti), + m_initialised(false), + m_inserting_audio_not_data(false) +{ +} + +FillStatus FIG0_24::fill(uint8_t *buf, size_t max_size) +{ +#define FIG0_24_TRACE debug + using namespace std; + + FillStatus fs; + FIGtype0* fig0 = nullptr; + ssize_t remaining = max_size; + + const auto ensemble = m_rti->ensemble; + + etiLog.level(FIG0_24_TRACE) << "FIG0_24::fill init " << (m_initialised ? 1 : 0) << + " ********************************"; + + if (not m_initialised) { + serviceFIG0_24 = ensemble->services.begin(); + m_initialised = true; + } + + const auto last_service = ensemble->services.end(); + + // Rotate through the subchannels until there is no more + // space + for (; serviceFIG0_24 != last_service; ++serviceFIG0_24) { + const auto type = (*serviceFIG0_24)->getType(ensemble); + const auto isProgramme = (*serviceFIG0_24)->isProgramme(ensemble); + + etiLog.log(FIG0_24_TRACE, "FIG0_24::fill loop SId=%04x %s/%s", + (*serviceFIG0_24)->id, + m_inserting_audio_not_data ? "AUDIO" : "DATA", + type == subchannel_type_t::Audio ? "Audio" : + type == subchannel_type_t::Packet ? "Packet" : + type == subchannel_type_t::DataDmb ? "DataDmb" : + type == subchannel_type_t::Fidc ? "Fidc" : "?"); + + // Skip services that are not in other ensembles + if ((*serviceFIG0_24)->other_ensembles.empty()) { + continue; + } + + const ssize_t required_size = + (isProgramme ? 2 : 4) + 1 + + (*serviceFIG0_24)->other_ensembles.size() * 2; + + + if (fig0 == nullptr) { + etiLog.level(FIG0_24_TRACE) << "FIG0_24::fill header"; + if (remaining < 2 + required_size) { + etiLog.level(FIG0_24_TRACE) << "FIG0_24::fill header no place" << + " rem=" << remaining << " req=" << 2 + required_size; + break; + } + fig0 = (FIGtype0*)buf; + + fig0->FIGtypeNumber = 0; + fig0->Length = 1; + fig0->CN = 0; + fig0->OE = 0; + fig0->PD = isProgramme ? 0 : 1; + fig0->Extension = 2; + buf += 2; + remaining -= 2; + } + else if (remaining < required_size) { + etiLog.level(FIG0_24_TRACE) << "FIG0_24::fill no place" << + " rem=" << remaining << " req=" << required_size; + break; + } + + if (type == subchannel_type_t::Audio) { + auto fig0_2serviceAudio = (FIGtype0_24_audioservice*)buf; + + fig0_2serviceAudio->SId = htons((*serviceFIG0_24)->id); + fig0_2serviceAudio->rfa = 0; + fig0_2serviceAudio->CAId = 0; + fig0_2serviceAudio->Length = (*serviceFIG0_24)->other_ensembles.size(); + buf += 3; + fig0->Length += 3; + remaining -= 3; + + etiLog.log(FIG0_24_TRACE, "FIG0_24::fill audio SId=%04x", + (*serviceFIG0_24)->id); + } + else { + auto fig0_2serviceData = (FIGtype0_24_dataservice*)buf; + + fig0_2serviceData->SId = htonl((*serviceFIG0_24)->id); + fig0_2serviceData->rfa = 0; + fig0_2serviceData->CAId = 0; + fig0_2serviceData->Length = (*serviceFIG0_24)->other_ensembles.size(); + buf += 4; + fig0->Length += 4; + remaining -= 4; + + etiLog.log(FIG0_24_TRACE, "FIG0_24::fill data SId=%04x", + (*serviceFIG0_24)->id); + } + + for (const uint16_t oe : (*serviceFIG0_24)->other_ensembles) { + buf[0] = oe >> 8; + buf[1] = oe & 0xFF; + + buf += 2; + fig0->Length += 2; + remaining -= 2; + } + } + + if (serviceFIG0_24 == last_service) { + etiLog.log(FIG0_24_TRACE, "FIG0_24::loop reached last"); + fs.complete_fig_transmitted = true; + m_initialised = false; + } + + etiLog.log(FIG0_24_TRACE, "FIG0_24::loop end complete=%d", + fs.complete_fig_transmitted ? 1 : 0); + + fs.num_bytes_written = max_size - remaining; + return fs; +} + +} diff --git a/src/fig/FIG0_24.h b/src/fig/FIG0_24.h new file mode 100644 index 0000000..0faa3b9 --- /dev/null +++ b/src/fig/FIG0_24.h @@ -0,0 +1,53 @@ +/* + Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, + 2011, 2012 Her Majesty the Queen in Right of Canada (Communications + Research Center Canada) + + Copyright (C) 2017 + Matthias P. Braendli, matthias.braendli@mpb.li + */ +/* + This file is part of ODR-DabMux. + + ODR-DabMux is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + ODR-DabMux is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ODR-DabMux. If not, see . +*/ + +#pragma once + +#include +#include +#include "FIG.h" + +namespace FIC { +/* The OE Services feature is used to identify the services currently carried + * in other DAB ensembles. + */ +class FIG0_24 : public IFIG +{ + public: + FIG0_24(FIGRuntimeInformation* rti); + virtual FillStatus fill(uint8_t *buf, size_t max_size); + virtual FIG_rate repetition_rate(void) { return FIG_rate::A; } + + virtual const int figtype(void) const { return 0; } + virtual const int figextension(void) const { return 24; } + + private: + FIGRuntimeInformation *m_rti; + bool m_initialised; + bool m_inserting_audio_not_data; + std::vector >::iterator serviceFIG0_24; +}; + +} diff --git a/src/fig/FIGCarousel.cpp b/src/fig/FIGCarousel.cpp index 6d89ad8..e32ea39 100644 --- a/src/fig/FIGCarousel.cpp +++ b/src/fig/FIGCarousel.cpp @@ -3,7 +3,7 @@ 2011, 2012 Her Majesty the Queen in Right of Canada (Communications Research Center Canada) - Copyright (C) 2016 + Copyright (C) 2017 Matthias P. Braendli, matthias.braendli@mpb.li Implementation of the FIG carousel to schedule the FIGs into the @@ -76,7 +76,8 @@ FIGCarousel::FIGCarousel(std::shared_ptr ensemble) : m_fig1_5(&m_rti), m_fig0_18(&m_rti), m_fig0_19(&m_rti), - m_fig0_21(&m_rti) + m_fig0_21(&m_rti), + m_fig0_24(&m_rti) { /* Complete MCI except FIG0/8 should be in FIB0. * EN 300 401 V1.4.1 Clause 6.1 @@ -111,6 +112,7 @@ FIGCarousel::FIGCarousel(std::shared_ptr ensemble) : load_and_allocate(m_fig0_18, FIBAllocation::FIB_ANY); load_and_allocate(m_fig0_19, FIBAllocation::FIB_ANY); load_and_allocate(m_fig0_21, FIBAllocation::FIB_ANY); + load_and_allocate(m_fig0_24, FIBAllocation::FIB_ANY); } void FIGCarousel::load_and_allocate(IFIG& fig, FIBAllocation fib) diff --git a/src/fig/FIGCarousel.h b/src/fig/FIGCarousel.h index ec1611d..5e102ad 100644 --- a/src/fig/FIGCarousel.h +++ b/src/fig/FIGCarousel.h @@ -3,7 +3,7 @@ 2011, 2012 Her Majesty the Queen in Right of Canada (Communications Research Center Canada) - Copyright (C) 2016 + Copyright (C) 2017 Matthias P. Braendli, matthias.braendli@mpb.li Implementation of the FIG carousel to schedule the FIGs into the @@ -102,6 +102,7 @@ class FIGCarousel { FIG0_18 m_fig0_18; FIG0_19 m_fig0_19; FIG0_21 m_fig0_21; + FIG0_24 m_fig0_24; }; } // namespace FIC -- cgit v1.2.3