aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/DabMultiplexer.cpp35
-rw-r--r--src/DabMultiplexer.h7
-rw-r--r--src/DabMux.cpp52
-rw-r--r--src/fig/FIG.h10
-rw-r--r--src/fig/FIG0_10.cpp11
-rw-r--r--src/fig/FIGCarousel.cpp7
-rw-r--r--src/fig/FIGCarousel.h4
-rw-r--r--src/utils.cpp24
-rw-r--r--src/utils.h6
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
*