summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/example.mux4
-rw-r--r--lib/edi/common.cpp13
-rw-r--r--lib/edi/common.hpp2
-rw-r--r--src/ConfigParser.cpp8
-rw-r--r--src/input/Edi.cpp14
-rw-r--r--src/input/Edi.h2
-rw-r--r--src/input/inputs.h2
7 files changed, 40 insertions, 5 deletions
diff --git a/doc/example.mux b/doc/example.mux
index 83dbfbb..cf02467 100644
--- a/doc/example.mux
+++ b/doc/example.mux
@@ -228,6 +228,10 @@ subchannels {
; avoid runaway memory usage in case of issues.
buffer 500
; 500 * 24ms = 12 seconds
+
+ ; Specify the additional delay in milliseconds to add to the TIST. Positive values
+ ; mean the content will be inserted later.
+ tist-delay 10
}
}
diff --git a/lib/edi/common.cpp b/lib/edi/common.cpp
index d6ca89c..87a15ce 100644
--- a/lib/edi/common.cpp
+++ b/lib/edi/common.cpp
@@ -73,6 +73,19 @@ double frame_timestamp_t::diff_ms(const frame_timestamp_t& other) const
return lhs - rhs;
}
+frame_timestamp_t& frame_timestamp_t::operator+=(const std::chrono::milliseconds& ms)
+{
+ tsta += (ms.count() % 1000) << 14; // Shift ms by 14 to Timestamp level 2
+ if (tsta > 0xf9FFff) {
+ tsta -= 0xfa0000; // Substract 16384000, corresponding to one second
+ seconds += 1;
+ }
+
+ seconds += (ms.count() / 1000);
+
+ return *this;
+}
+
frame_timestamp_t frame_timestamp_t::from_unix_epoch(std::time_t time, uint32_t tai_utc_offset, uint32_t tsta)
{
frame_timestamp_t ts;
diff --git a/lib/edi/common.hpp b/lib/edi/common.hpp
index 8252a7a..2a9c683 100644
--- a/lib/edi/common.hpp
+++ b/lib/edi/common.hpp
@@ -43,6 +43,8 @@ struct frame_timestamp_t {
double diff_ms(const frame_timestamp_t& other) const;
+ frame_timestamp_t& operator+=(const std::chrono::milliseconds& ms);
+
static frame_timestamp_t from_unix_epoch(std::time_t time, uint32_t tai_utc_offset, uint32_t tsta);
};
diff --git a/src/ConfigParser.cpp b/src/ConfigParser.cpp
index 063e4ec..776ddc8 100644
--- a/src/ConfigParser.cpp
+++ b/src/ConfigParser.cpp
@@ -51,11 +51,12 @@
#include <boost/algorithm/string/split.hpp>
#include <cstdint>
#include <cstring>
-#include <memory>
+#include <chrono>
#include <exception>
#include <iostream>
-#include <string>
#include <map>
+#include <memory>
+#include <string>
#include <vector>
using namespace std;
@@ -1037,6 +1038,9 @@ static void setup_subchannel_from_ptree(shared_ptr<DabSubchannel>& subchan,
throw runtime_error("Subchannel with uid " + subchanuid + " has invalid buffer-management !");
}
+ const int32_t tist_delay = pt.get("tist-delay", 0);
+ subchan->input->setTistDelay(chrono::milliseconds(tist_delay));
+
subchan->startAddress = 0;
dabProtection* protection = &subchan->protection;
diff --git a/src/input/Edi.cpp b/src/input/Edi.cpp
index f4b5e25..b5301d2 100644
--- a/src/input/Edi.cpp
+++ b/src/input/Edi.cpp
@@ -62,6 +62,8 @@ Edi::Edi(const std::string& name, const dab_input_edi_config_t& config) :
RC_ADD_PARAMETER(prebuffering,
"Min buffer level before streaming starts [24ms frames]");
+
+ RC_ADD_PARAMETER(tistdelay, "TIST delay to add [ms]");
}
Edi::~Edi() {
@@ -209,7 +211,8 @@ size_t Edi::readFrame(uint8_t *buffer, size_t size, std::time_t seconds, int utc
// difference between the input frame timestamp and the requested
// timestamp.
if (m_pending_sti_frame.timestamp.valid()) {
- const auto ts_req = EdiDecoder::frame_timestamp_t::from_unix_epoch(seconds, utco, tsta);
+ auto ts_req = EdiDecoder::frame_timestamp_t::from_unix_epoch(seconds, utco, tsta);
+ ts_req += m_tist_delay;
const double offset = m_pending_sti_frame.timestamp.diff_ms(ts_req);
if (offset < 24e-3) {
@@ -274,7 +277,8 @@ size_t Edi::readFrame(uint8_t *buffer, size_t size, std::time_t seconds, int utc
return 0;
}
else {
- const auto ts_req = EdiDecoder::frame_timestamp_t::from_unix_epoch(seconds, utco, tsta);
+ auto ts_req = EdiDecoder::frame_timestamp_t::from_unix_epoch(seconds, utco, tsta);
+ ts_req += m_tist_delay;
const double offset = m_pending_sti_frame.timestamp.diff_ms(ts_req);
if (offset > 24e-3) {
@@ -384,6 +388,9 @@ void Edi::set_parameter(const std::string& parameter, const std::string& value)
throw ParameterError("Invalid value for '" + parameter + "' in controllable " + get_rc_name());
}
}
+ else if (parameter == "tistdelay") {
+ m_tist_delay = chrono::milliseconds(stoi(value));
+ }
else {
throw ParameterError("Parameter '" + parameter + "' is not exported by controllable " + get_rc_name());
}
@@ -408,6 +415,9 @@ const std::string Edi::get_parameter(const std::string& parameter) const
break;
}
}
+ else if (parameter == "tistdelay") {
+ ss << m_tist_delay.count();
+ }
else {
throw ParameterError("Parameter '" + parameter + "' is not exported by controllable " + get_rc_name());
}
diff --git a/src/input/Edi.h b/src/input/Edi.h
index ed4d7cf..a3b1d4d 100644
--- a/src/input/Edi.h
+++ b/src/input/Edi.h
@@ -97,7 +97,7 @@ class Edi : public InputBase, public RemoteControllable {
std::atomic<bool> m_running = ATOMIC_VAR_INIT(false);
ThreadsafeQueue<EdiDecoder::sti_frame_t> m_frames;
- // InputBase defines bufferManagement
+ // InputBase defines bufferManagement and tist delay
// Used in timestamp-based buffer management
EdiDecoder::sti_frame_t m_pending_sti_frame;
diff --git a/src/input/inputs.h b/src/input/inputs.h
index 5d4fc60..83cdbf2 100644
--- a/src/input/inputs.h
+++ b/src/input/inputs.h
@@ -83,6 +83,7 @@ class InputBase {
virtual ~InputBase() {}
+ void setTistDelay(const std::chrono::milliseconds& ms) { m_tist_delay = ms; }
void setBufferManagement(BufferManagement bm) { m_bufferManagement = bm; }
BufferManagement getBufferManagement() const { return m_bufferManagement; }
@@ -90,6 +91,7 @@ class InputBase {
InputBase() {}
std::atomic<BufferManagement> m_bufferManagement = ATOMIC_VAR_INIT(BufferManagement::Prebuffering);
+ std::chrono::milliseconds m_tist_delay;
};
};