diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/DabMultiplexer.cpp | 35 | ||||
-rw-r--r-- | src/DabMultiplexer.h | 7 | ||||
-rw-r--r-- | src/DabMux.cpp | 52 | ||||
-rw-r--r-- | src/fig/FIG.h | 10 | ||||
-rw-r--r-- | src/fig/FIG0_10.cpp | 11 | ||||
-rw-r--r-- | src/fig/FIGCarousel.cpp | 7 | ||||
-rw-r--r-- | src/fig/FIGCarousel.h | 4 | ||||
-rw-r--r-- | src/utils.cpp | 24 | ||||
-rw-r--r-- | src/utils.h | 6 |
9 files changed, 88 insertions, 68 deletions
diff --git a/src/DabMultiplexer.cpp b/src/DabMultiplexer.cpp index b9575fc..e6e6782 100644 --- a/src/DabMultiplexer.cpp +++ b/src/DabMultiplexer.cpp @@ -49,6 +49,8 @@ static vector<string> split_pipe_separated_string(const std::string& s) uint64_t MuxTime::init(uint32_t tist_at_fct0_us) { + m_tist_at_fct0_us = tist_at_fct0_us; + /* At startup, derive edi_time, TIST and CIF count such that there is * a consistency across mux restarts. Ensure edi_time and TIST represent * current time. @@ -98,9 +100,11 @@ uint64_t MuxTime::init(uint32_t tist_at_fct0_us) return currentFrame; } +constexpr int TIMESTAMP_LEVEL_2_SHIFT = 14; + void MuxTime::increment_timestamp() { - m_timestamp += 24 << 14; // Shift 24ms by 14 to Timestamp level 2 + m_timestamp += 24 << TIMESTAMP_LEVEL_2_SHIFT; // Shift 24ms by 14 to Timestamp level 2 if (m_timestamp > 0xf9FFff) { m_timestamp -= 0xfa0000; // Subtract 16384000, corresponding to one second m_edi_time += 1; @@ -110,16 +114,21 @@ void MuxTime::increment_timestamp() } } -std::pair<uint32_t, std::time_t> MuxTime::get_time() +std::pair<uint32_t, std::time_t> MuxTime::get_tist_seconds() { + // The user-visible configuration tist_offset is the effective + // offset, but since we implicitly add the tist_at_fct0 to it, + // we must compensate. + double corrected_tist_offset = tist_offset - (m_tist_at_fct0_us / 1e6); + // negative tist_offset not supported, because the calculation is annoying - if (tist_offset < 0) return {m_timestamp, m_edi_time}; + if (corrected_tist_offset < 0) return {m_timestamp, m_edi_time}; - double fractional_part = tist_offset - std::floor(tist_offset); + double fractional_part = corrected_tist_offset - std::floor(corrected_tist_offset); const size_t steps = std::lround(std::floor(fractional_part / 24e-3)); - uint32_t timestamp = m_timestamp + (24 << 14) * steps; + uint32_t timestamp = m_timestamp + (24 << TIMESTAMP_LEVEL_2_SHIFT) * steps; - std::time_t edi_time = m_edi_time + std::lround(std::floor(tist_offset)); + std::time_t edi_time = m_edi_time + std::lround(std::floor(corrected_tist_offset)); if (timestamp > 0xf9FFff) { edi_time += 1; @@ -128,13 +137,20 @@ std::pair<uint32_t, std::time_t> MuxTime::get_time() return {timestamp % 0xfa0000, edi_time}; } +std::pair<uint32_t, std::time_t> MuxTime::get_milliseconds_seconds() +{ + auto tist_seconds = get_tist_seconds(); + return {tist_seconds.first >> TIMESTAMP_LEVEL_2_SHIFT, tist_seconds.second}; +} + DabMultiplexer::DabMultiplexer(boost::property_tree::ptree pt) : RemoteControllable("mux"), m_pt(pt), + m_time(), ensemble(std::make_shared<dabEnsemble>()), m_clock_tai(split_pipe_separated_string(pt.get("general.tai_clock_bulletins", ""))), - fig_carousel(ensemble) + fig_carousel(ensemble, [&]() { return m_time.get_milliseconds_seconds(); }) { RC_ADD_PARAMETER(frames, "Show number of frames generated [read-only]"); RC_ADD_PARAMETER(tist_offset, "Timestamp offset in fractional number of seconds"); @@ -190,7 +206,7 @@ void DabMultiplexer::prepare(bool require_tai_clock) bool tist_enabled = m_pt.get("general.tist", false); m_time.tist_offset = m_pt.get<double>("general.tist_offset", 0.0); - auto tist_edi_time = m_time.get_time(); + auto tist_edi_time = m_time.get_tist_seconds(); const auto timestamp = tist_edi_time.first; const auto edi_time = tist_edi_time.second; m_time.mnsc_time = edi_time; @@ -467,9 +483,8 @@ void DabMultiplexer::mux_frame(std::vector<std::shared_ptr<DabOutput> >& outputs etiLog.level(error) << "Could not get UTC-TAI offset for EDI timestamp"; } } - update_dab_time(); - auto tist_edi_time = m_time.get_time(); + auto tist_edi_time = m_time.get_tist_seconds(); const auto timestamp = tist_edi_time.first; const auto edi_time = tist_edi_time.second; diff --git a/src/DabMultiplexer.h b/src/DabMultiplexer.h index aa6adfb..5a0d906 100644 --- a/src/DabMultiplexer.h +++ b/src/DabMultiplexer.h @@ -47,9 +47,11 @@ class MuxTime { private: uint32_t m_timestamp = 0; std::time_t m_edi_time = 0; + uint32_t m_tist_at_fct0_us = 0; public: - std::pair<uint32_t, std::time_t> get_time(); + std::pair<uint32_t, std::time_t> get_tist_seconds(); + std::pair<uint32_t, std::time_t> get_milliseconds_seconds(); double tist_offset = 0; @@ -80,8 +82,6 @@ class DabMultiplexer : public RemoteControllable { void prepare(bool require_tai_clock); - uint64_t getCurrentFrame() const { return currentFrame; } - void mux_frame(std::vector<std::shared_ptr<DabOutput> >& outputs); void print_info(void); @@ -115,6 +115,5 @@ class DabMultiplexer : public RemoteControllable { bool m_tai_clock_required = false; ClockTAI m_clock_tai; - /* New FIG Carousel */ FIC::FIGCarousel fig_carousel; }; diff --git a/src/DabMux.cpp b/src/DabMux.cpp index 1a367da..bf525c1 100644 --- a/src/DabMux.cpp +++ b/src/DabMux.cpp @@ -327,6 +327,38 @@ int main(int argc, char *argv[]) if (outputuid == "edi") { ptree pt_edi = pt_outputs.get_child("edi"); + bool default_enable_pft = pt_edi.get<bool>("enable_pft", false); + edi_conf.verbose = pt_edi.get<bool>("verbose", false); + + unsigned int default_fec = pt_edi.get<unsigned int>("fec", 3); + unsigned int default_chunk_len = pt_edi.get<unsigned int>("chunk_len", 207); + + auto check_spreading_factor = [](int percent) { + if (percent < 0) { + throw std::runtime_error("EDI output: negative packet_spread value is invalid."); + } + double factor = (double)percent / 100.0; + if (factor > 30000) { + throw std::runtime_error("EDI output: interleaving set for more than 30 seconds!"); + } + return factor; + }; + + double default_spreading_factor = check_spreading_factor(pt_edi.get<int>("packet_spread", 95)); + + using pt_t = boost::property_tree::basic_ptree<std::basic_string<char>, std::basic_string<char>>; + auto handle_overrides = [&](edi::pft_settings_t& pft_settings, pt_t pt) { + pft_settings.chunk_len = pt.get<unsigned int>("chunk_len", default_chunk_len); + pft_settings.enable_pft = pt.get<bool>("enable_pft", default_enable_pft); + pft_settings.fec = pt.get<unsigned int>("fec", default_fec); + pft_settings.fragment_spreading_factor = default_spreading_factor; + auto override_spread_percent = pt.get_optional<int>("packet_spread"); + if (override_spread_percent) { + pft_settings.fragment_spreading_factor = check_spreading_factor(*override_spread_percent); + } + pft_settings.verbose = pt.get<bool>("verbose", edi_conf.verbose); + }; + for (auto pt_edi_dest : pt_edi.get_child("destinations")) { const auto proto = pt_edi_dest.second.get<string>("protocol", "udp"); if (proto == "udp") { @@ -346,6 +378,8 @@ int main(int argc, char *argv[]) dest->dest_port = pt_edi.get<unsigned int>("port"); } + handle_overrides(dest->pft_settings, pt_edi_dest.second); + edi_conf.destinations.push_back(dest); } else if (proto == "tcp") { @@ -355,6 +389,8 @@ int main(int argc, char *argv[]) double preroll = pt_edi_dest.second.get<double>("preroll-burst", 0.0); dest->tcp_server_preroll_buffers = ceil(preroll / 24e-3); + handle_overrides(dest->pft_settings, pt_edi_dest.second); + edi_conf.destinations.push_back(dest); } else { @@ -362,22 +398,6 @@ int main(int argc, char *argv[]) } } - edi_conf.dump = pt_edi.get<bool>("dump", false); - edi_conf.enable_pft = pt_edi.get<bool>("enable_pft", false); - edi_conf.verbose = pt_edi.get<bool>("verbose", false); - - edi_conf.fec = pt_edi.get<unsigned int>("fec", 3); - edi_conf.chunk_len = pt_edi.get<unsigned int>("chunk_len", 207); - - int spread_percent = pt_edi.get<int>("packet_spread", 95); - if (spread_percent < 0) { - throw std::runtime_error("EDI output: negative packet_spread value is invalid."); - } - edi_conf.fragment_spreading_factor = (double)spread_percent / 100.0; - if (edi_conf.fragment_spreading_factor > 30000) { - throw std::runtime_error("EDI output: interleaving set for more than 30 seconds!"); - } - edi_conf.tagpacket_alignment = pt_edi.get<unsigned int>("tagpacket_alignment", 8); mux.set_edi_config(edi_conf); diff --git a/src/fig/FIG.h b/src/fig/FIG.h index 9752245..eda4671 100644 --- a/src/fig/FIG.h +++ b/src/fig/FIG.h @@ -35,11 +35,19 @@ namespace FIC { class FIGRuntimeInformation { public: - FIGRuntimeInformation(std::shared_ptr<dabEnsemble>& e) : + + using dab_time_t = std::pair<uint32_t /* milliseconds */, time_t>; + using get_time_func_t = std::function<dab_time_t()>; + + FIGRuntimeInformation( + std::shared_ptr<dabEnsemble>& e, + get_time_func_t getTimeFunc) : + getTimeFunc(getTimeFunc), currentFrame(0), ensemble(e), factumAnalyzer(false) {} + get_time_func_t getTimeFunc; unsigned long currentFrame; std::shared_ptr<dabEnsemble> ensemble; bool factumAnalyzer; diff --git a/src/fig/FIG0_10.cpp b/src/fig/FIG0_10.cpp index 56ce9fb..240aa19 100644 --- a/src/fig/FIG0_10.cpp +++ b/src/fig/FIG0_10.cpp @@ -3,7 +3,7 @@ 2011, 2012 Her Majesty the Queen in Right of Canada (Communications Research Center Canada) - Copyright (C) 2016 + Copyright (C) 2025 Matthias P. Braendli, matthias.braendli@mpb.li */ /* @@ -23,7 +23,6 @@ along with ODR-DabMux. If not, see <http://www.gnu.org/licenses/>. */ -#include "fig/FIG0structs.h" #include "fig/FIG0_10.h" #include "utils.h" @@ -89,7 +88,7 @@ FillStatus FIG0_10::fill(uint8_t *buf, size_t max_size) return fs; } - //Time and country identifier + // Time and country identifier auto fig0_10 = (FIGtype0_10_LongForm*)buf; fig0_10->FIGtypeNumber = 0; @@ -102,9 +101,9 @@ FillStatus FIG0_10::fill(uint8_t *buf, size_t max_size) remaining -= 2; struct tm timeData; - time_t dab_time_seconds = 0; - uint32_t dab_time_millis = 0; - get_dab_time(&dab_time_seconds, &dab_time_millis); + const auto dab_time = m_rti->getTimeFunc(); + time_t dab_time_seconds = dab_time.second; + uint32_t dab_time_millis = dab_time.first; gmtime_r(&dab_time_seconds, &timeData); fig0_10->RFU = 0; diff --git a/src/fig/FIGCarousel.cpp b/src/fig/FIGCarousel.cpp index 9748dbf..ceda275 100644 --- a/src/fig/FIGCarousel.cpp +++ b/src/fig/FIGCarousel.cpp @@ -68,8 +68,11 @@ bool FIGCarouselElement::check_deadline() /**************** FIGCarousel *****************/ -FIGCarousel::FIGCarousel(std::shared_ptr<dabEnsemble> ensemble) : - m_rti(ensemble), +FIGCarousel::FIGCarousel( + std::shared_ptr<dabEnsemble> ensemble, + FIGRuntimeInformation::get_time_func_t getTimeFunc + ) : + m_rti(ensemble, getTimeFunc), m_fig0_0(&m_rti), m_fig0_1(&m_rti), m_fig0_2(&m_rti), diff --git a/src/fig/FIGCarousel.h b/src/fig/FIGCarousel.h index 1e33577..a2a8022 100644 --- a/src/fig/FIGCarousel.h +++ b/src/fig/FIGCarousel.h @@ -67,7 +67,9 @@ enum class FIBAllocation { class FIGCarousel { public: - FIGCarousel(std::shared_ptr<dabEnsemble> ensemble); + FIGCarousel( + std::shared_ptr<dabEnsemble> ensemble, + FIGRuntimeInformation::get_time_func_t getTimeFunc); /* Write all FIBs to the buffer, including correct padding and crc. * Returns number of bytes written. diff --git a/src/utils.cpp b/src/utils.cpp index 1a13caf..7ea6293 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -3,7 +3,7 @@ 2011, 2012 Her Majesty the Queen in Right of Canada (Communications Research Center Canada) - Copyright (C) 2021 + Copyright (C) 2025 Matthias P. Braendli, matthias.braendli@mpb.li http://www.opendigitalradio.org @@ -34,30 +34,8 @@ using namespace std; -static time_t dab_time_seconds = 0; -static int dab_time_millis = 0; - static void printServices(const vector<shared_ptr<DabService> >& services); -void update_dab_time() -{ - if (dab_time_seconds == 0) { - dab_time_seconds = time(nullptr); - } else { - dab_time_millis+= 24; - if (dab_time_millis >= 1000) { - dab_time_millis -= 1000; - ++dab_time_seconds; - } - } -} - -void get_dab_time(time_t *time, uint32_t *millis) -{ - *time = dab_time_seconds; - *millis = dab_time_millis; -} - uint32_t gregorian2mjd(int year, int month, int day) { diff --git a/src/utils.h b/src/utils.h index 331a0b2..d037bb3 100644 --- a/src/utils.h +++ b/src/utils.h @@ -3,7 +3,7 @@ 2011, 2012 Her Majesty the Queen in Right of Canada (Communications Research Center Canada) - Copyright (C) 2020 + Copyright (C) 2025 Matthias P. Braendli, matthias.braendli@mpb.li This file contains a set of utility functions that are used to show @@ -34,10 +34,6 @@ #include <memory> #include "MuxElements.h" -/* Must be called once per ETI frame to update the time */ -void update_dab_time(void); -void get_dab_time(time_t *time, uint32_t *millis); - /* Convert a date and time into the modified Julian date * used in FIG 0/10 * |