diff options
author | Matthias P. Braendli <matthias.braendli@mpb.li> | 2019-02-18 11:46:12 +0100 |
---|---|---|
committer | Matthias P. Braendli <matthias.braendli@mpb.li> | 2019-02-18 11:46:12 +0100 |
commit | fd33dd4329b591cc72ef30f1cefd9eb05cb1e560 (patch) | |
tree | de8a74b43ac93de31c0b3f1fd3bc434efc0ffa09 /src | |
parent | eb15f7fc5e461c71a8d397d8fb34c27976876946 (diff) | |
download | dabmux-fd33dd4329b591cc72ef30f1cefd9eb05cb1e560.tar.gz dabmux-fd33dd4329b591cc72ef30f1cefd9eb05cb1e560.tar.bz2 dabmux-fd33dd4329b591cc72ef30f1cefd9eb05cb1e560.zip |
Rework timestamping
* Ensure MNSC and EDI carry the same timestamp
* Rename `edi_tistoffset` to `tist_offset`
* Remove conditional compilation of EDI output
* Reset PPS so as to align ETI frames across mux restarts
Diffstat (limited to 'src')
-rw-r--r-- | src/DabMultiplexer.cpp | 98 | ||||
-rw-r--r-- | src/DabMultiplexer.h | 20 | ||||
-rw-r--r-- | src/DabMux.cpp | 6 | ||||
-rw-r--r-- | src/dabOutput/edi/TagItems.cpp | 4 | ||||
-rw-r--r-- | src/dabOutput/edi/TagItems.h | 2 |
5 files changed, 55 insertions, 75 deletions
diff --git a/src/DabMultiplexer.cpp b/src/DabMultiplexer.cpp index e157523..3a7f31f 100644 --- a/src/DabMultiplexer.cpp +++ b/src/DabMultiplexer.cpp @@ -3,7 +3,7 @@ 2011, 2012 Her Majesty the Queen in Right of Canada (Communications Research Center Canada) - Copyright (C) 2017 + Copyright (C) 2019 Matthias P. Braendli, matthias.braendli@mpb.li */ /* @@ -83,19 +83,12 @@ DabMultiplexer::DabMultiplexer( boost::property_tree::ptree pt) : RemoteControllable("mux"), m_pt(pt), - timestamp(0), - MNSC_increment_time(false), - sync(0x49C5F8), - currentFrame(0), ensemble(std::make_shared<dabEnsemble>()), - m_tai_clock_required(false), m_clock_tai(split_pipe_separated_string(pt.get("general.tai_clock_bulletins", ""))), fig_carousel(ensemble) { - gettimeofday(&mnsc_time, nullptr); - RC_ADD_PARAMETER(frames, "Show number of frames generated [read-only]"); - RC_ADD_PARAMETER(tist_edioffset, "EDI Time offset in seconds"); + RC_ADD_PARAMETER(tist_offset, "Timestamp offset in integral number of seconds"); rcs.enrol(&m_clock_tai); } @@ -109,7 +102,6 @@ void DabMultiplexer::set_edi_config(const edi_configuration_t& new_edi_conf) { edi_conf = new_edi_conf; -#if HAVE_OUTPUT_EDI if (edi_conf.verbose) { etiLog.log(info, "Setup EDI"); } @@ -146,7 +138,6 @@ void DabMultiplexer::set_edi_config(const edi_configuration_t& new_edi_conf) // The AF Packet will be protected with reed-solomon and split in fragments edi::PFT pft(edi_conf); edi_pft = pft; -#endif } @@ -185,15 +176,24 @@ void DabMultiplexer::prepare(bool require_tai_clock) * Ideally, we must be able to restart transmission s.t. the receiver * synchronisation is preserved. */ - gettimeofday(&mnsc_time, nullptr); + using Sec = chrono::seconds; + const auto now = chrono::time_point_cast<Sec>(chrono::system_clock::now()); -#if HAVE_OUTPUT_EDI - edi_time = chrono::system_clock::now(); + edi_time = chrono::system_clock::to_time_t(now); + + // We define that when the time is multiple of six seconds, the timestamp + // (PPS offset) is 0. This ensures consistency of TIST even across a + // mux restart + timestamp = 0; + edi_time -= (edi_time % 6); + while (edi_time < chrono::system_clock::to_time_t(now)) { + increment_timestamp(); + } // Try to load offset once bool tist_enabled = m_pt.get("general.tist", false); - m_tist_edioffset = m_pt.get<int>("general.tist_edioffset", 0); + m_tist_offset = m_pt.get<int>("general.tist_offset", 0); m_tai_clock_required = (tist_enabled and edi_conf.enabled()) or require_tai_clock; @@ -204,7 +204,9 @@ void DabMultiplexer::prepare(bool require_tai_clock) catch (const std::runtime_error& e) { etiLog.level(error) << "Could not initialise TAI clock properly. " - "Do you have a working internet connection?"; + "TAI clock is required when TIST is enabled with an EDI output, " + "or when a ZMQ output with metadata is used. " + "Error: " << e.what(); throw; } } @@ -212,10 +214,7 @@ void DabMultiplexer::prepare(bool require_tai_clock) if (edi_conf.interleaver_enabled()) { edi_interleaver.SetLatency(edi_conf.latency_frames); } -#endif - // Shift ms by 14 to Timestamp level 2, see below in Section TIST - timestamp = (mnsc_time.tv_usec / 1000) << 14; } @@ -396,6 +395,15 @@ void DabMultiplexer::prepare_data_inputs() } } +void DabMultiplexer::increment_timestamp() +{ + timestamp += 24 << 14; // Shift 24ms by 14 to Timestamp level 2 + if (timestamp > 0xf9FFff) { + timestamp -= 0xfa0000; // Substract 16384000, corresponding to one second + edi_time += 1; + } +} + /* Each call creates one ETI frame */ void DabMultiplexer::mux_frame(std::vector<std::shared_ptr<DabOutput> >& outputs) { @@ -545,18 +553,17 @@ void DabMultiplexer::mux_frame(std::vector<std::shared_ptr<DabOutput> >& outputs eoh->MNSC = 0; + if (fc->FP == 0) { + // update the latched time only when FP==0 to ensure MNSC encodes + // a consistent time + edi_time_latched_for_mnsc = edi_time + m_tist_offset; + } + struct tm time_tm; - gmtime_r(&mnsc_time.tv_sec, &time_tm); - switch (fc->FP & 0x3) - { + gmtime_r(&edi_time_latched_for_mnsc, &time_tm); + switch (fc->FP & 0x3) { case 0: - if (MNSC_increment_time) { - MNSC_increment_time = false; - mnsc_time.tv_sec += 1; - } - { - eti_MNSC_TIME_0 *mnsc = (eti_MNSC_TIME_0 *) &eoh->MNSC; // Set fields according to ETS 300 799 -- 5.5.1 and A.2.2 mnsc->type = 0; @@ -670,17 +677,12 @@ void DabMultiplexer::mux_frame(std::vector<std::shared_ptr<DabOutput> >& outputs edi_tagDETI.tsta = 0xffffff; } -#if HAVE_OUTPUT_EDI const bool tist_enabled = m_pt.get("general.tist", false); if (tist_enabled and m_tai_clock_required) { try { const auto tai_utc_offset = m_clock_tai.get_offset(); - - edi_tagDETI.set_edi_time(edi_time + - std::chrono::seconds(m_tist_edioffset), - tai_utc_offset); - + edi_tagDETI.set_edi_time(edi_time + m_tist_offset, tai_utc_offset); edi_tagDETI.atstf = true; for (auto output : outputs) { @@ -701,7 +703,6 @@ void DabMultiplexer::mux_frame(std::vector<std::shared_ptr<DabOutput> >& outputs etiLog.level(error) << "Could not get UTC-TAI offset for EDI timestamp"; } } -#endif /* Coding of the TIST, according to ETS 300 799 Annex C @@ -716,17 +717,7 @@ void DabMultiplexer::mux_frame(std::vector<std::shared_ptr<DabOutput> >& outputs time resolution */ - timestamp += 24 << 14; // Shift 24ms by 14 to Timestamp level 2 - if (timestamp > 0xf9FFff) - { - timestamp -= 0xfa0000; // Substract 16384000, corresponding to one second - - // Also update MNSC time for next time FP==0 - MNSC_increment_time = true; - - // Immediately update edi time - edi_time += chrono::seconds(1); - } + increment_timestamp(); /********************************************************************** *********** Section FRPD ***************************************** @@ -755,11 +746,9 @@ void DabMultiplexer::mux_frame(std::vector<std::shared_ptr<DabOutput> >& outputs } } -#if HAVE_OUTPUT_EDI /********************************************************************** *********** Finalise and send EDI ******************************** **********************************************************************/ - if (edi_conf.enabled()) { // put tags *ptr, DETI and all subchannels into one TagPacket edi_tagpacket.tag_items.push_back(&edi_tagStarPtr); @@ -822,7 +811,6 @@ void DabMultiplexer::mux_frame(std::vector<std::shared_ptr<DabOutput> >& outputs } } } -#endif // HAVE_OUTPUT_EDI #if _DEBUG /********************************************************************** @@ -831,12 +819,12 @@ void DabMultiplexer::mux_frame(std::vector<std::shared_ptr<DabOutput> >& outputs if (currentFrame % 100 == 0) { if (enableTist) { etiLog.log(info, "ETI frame number %i Timestamp: %d + %f", - currentFrame, mnsc_time.tv_sec, + currentFrame, edi_time, (timestamp & 0xFFFFFF) / 16384000.0); } else { etiLog.log(info, "ETI frame number %i Time: %d, no TIST", - currentFrame, mnsc_time.tv_sec); + currentFrame, edi_time); } } #endif @@ -871,8 +859,8 @@ void DabMultiplexer::set_parameter(const std::string& parameter, " is read-only"; throw ParameterError(ss.str()); } - else if (parameter == "tist_edioffset") { - m_tist_edioffset = std::stoi(value); + else if (parameter == "tist_offset") { + m_tist_offset = std::stoi(value); } else { stringstream ss; @@ -889,8 +877,8 @@ const std::string DabMultiplexer::get_parameter(const std::string& parameter) co if (parameter == "frames") { ss << currentFrame; } - else if (parameter == "tist_edioffset") { - ss << m_tist_edioffset; + else if (parameter == "tist_offset") { + ss << m_tist_offset; } else { ss << "Parameter '" << parameter << diff --git a/src/DabMultiplexer.h b/src/DabMultiplexer.h index 127ecfb..7090be7 100644 --- a/src/DabMultiplexer.h +++ b/src/DabMultiplexer.h @@ -3,7 +3,7 @@ 2011, 2012 Her Majesty the Queen in Right of Canada (Communications Research Center Canada) - Copyright (C) 2016 + Copyright (C) 2019 Matthias P. Braendli, matthias.braendli@mpb.li */ /* @@ -80,26 +80,25 @@ class DabMultiplexer : public RemoteControllable { void prepare_subchannels(void); void prepare_services_components(void); void prepare_data_inputs(void); + void increment_timestamp(void); boost::property_tree::ptree m_pt; - unsigned timestamp; - bool MNSC_increment_time; - struct timeval mnsc_time; - std::chrono::system_clock::time_point edi_time; + unsigned timestamp = 0; + std::time_t edi_time; + std::time_t edi_time_latched_for_mnsc; edi_configuration_t edi_conf; - uint32_t sync; - unsigned long currentFrame; + uint32_t sync = 0x49C5F8; + unsigned long currentFrame = 0; std::shared_ptr<dabEnsemble> ensemble; - int m_tist_edioffset = 0; - bool m_tai_clock_required; + int m_tist_offset = 0; + bool m_tai_clock_required = false; ClockTAI m_clock_tai; -#if HAVE_OUTPUT_EDI std::ofstream edi_debug_file; // The TagPacket will then be placed into an AFPacket @@ -110,7 +109,6 @@ class DabMultiplexer : public RemoteControllable { // To mitigate for burst packet loss, PFT fragments can be sent out-of-order edi::Interleaver edi_interleaver; -#endif // HAVE_OUTPUT_EDI /* New FIG Carousel */ FIC::FIGCarousel fig_carousel; diff --git a/src/DabMux.cpp b/src/DabMux.cpp index 3185fb3..4b06eb4 100644 --- a/src/DabMux.cpp +++ b/src/DabMux.cpp @@ -291,7 +291,6 @@ int main(int argc, char *argv[]) } if (outputuid == "edi") { -#if HAVE_OUTPUT_EDI ptree pt_edi = pt_outputs.get_child("edi"); for (auto pt_edi_dest : pt_edi.get_child("destinations")) { edi_destination_t dest; @@ -330,9 +329,6 @@ int main(int argc, char *argv[]) edi_conf.tagpacket_alignment = pt_edi.get<unsigned int>("tagpacket_alignment", 8); mux.set_edi_config(edi_conf); -#else - throw runtime_error("EDI output not compiled in"); -#endif } else if (outputuid == "zeromq") { #if defined(HAVE_OUTPUT_ZEROMQ) @@ -463,7 +459,6 @@ int main(int argc, char *argv[]) etiLog.log(info, "--- Output list ---"); printOutputs(outputs); -#if HAVE_OUTPUT_EDI if (edi_conf.enabled()) { etiLog.level(info) << "EDI"; etiLog.level(info) << " verbose " << edi_conf.verbose; @@ -479,7 +474,6 @@ int main(int argc, char *argv[]) etiLog.level(info) << " interleave " << edi_conf.latency_frames * 24 << " ms"; } } -#endif size_t limit = pt.get("general.nbframes", 0); diff --git a/src/dabOutput/edi/TagItems.cpp b/src/dabOutput/edi/TagItems.cpp index 631b88d..5511efb 100644 --- a/src/dabOutput/edi/TagItems.cpp +++ b/src/dabOutput/edi/TagItems.cpp @@ -132,13 +132,13 @@ std::vector<uint8_t> TagDETI::Assemble() return packet; } -void TagDETI::set_edi_time(const std::chrono::system_clock::time_point& t, int tai_utc_offset) +void TagDETI::set_edi_time(const std::time_t t, int tai_utc_offset) { utco = tai_utc_offset - 32; const std::time_t posix_timestamp_1_jan_2000 = 946684800; - seconds = std::chrono::system_clock::to_time_t(t) - posix_timestamp_1_jan_2000 + utco; + seconds = t - posix_timestamp_1_jan_2000 + utco; } std::vector<uint8_t> TagESTn::Assemble() diff --git a/src/dabOutput/edi/TagItems.h b/src/dabOutput/edi/TagItems.h index 8666053..0559bf3 100644 --- a/src/dabOutput/edi/TagItems.h +++ b/src/dabOutput/edi/TagItems.h @@ -86,7 +86,7 @@ class TagDETI : public TagItem uint8_t utco = 0; /* Update the EDI time. t is in UTC */ - void set_edi_time(const std::chrono::system_clock::time_point &t, int tai_utc_offset); + void set_edi_time(const std::time_t t, int tai_utc_offset); /* The number of SI seconds since 2000-01-01 T 00:00:00 UTC as an * unsigned 32-bit quantity. Contrary to POSIX, this value also |