aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias P. Braendli <matthias.braendli@mpb.li>2019-10-01 14:49:56 +0200
committerMatthias P. Braendli <matthias.braendli@mpb.li>2019-10-01 14:49:56 +0200
commit705cf1bcd4428fc5f0f5630624412e48bf6fc50a (patch)
tree8184352ae6abab291890100acf95fa9e60c1ad6d
parent15972d6445758f7b36c7b86ecbc5fb7e4ec3742f (diff)
downloadodr-edilib-705cf1bcd4428fc5f0f5630624412e48bf6fc50a.tar.gz
odr-edilib-705cf1bcd4428fc5f0f5630624412e48bf6fc50a.tar.bz2
odr-edilib-705cf1bcd4428fc5f0f5630624412e48bf6fc50a.zip
Rework ETIWriter and STIWriter APIs to add callback on frame completion
-rw-r--r--decoder/ETIWriter.cpp46
-rw-r--r--decoder/ETIWriter.hpp19
-rw-r--r--decoder/STIWriter.cpp42
-rw-r--r--decoder/STIWriter.hpp12
-rw-r--r--test/main.cpp179
5 files changed, 104 insertions, 194 deletions
diff --git a/decoder/ETIWriter.cpp b/decoder/ETIWriter.cpp
index aabd191..5f6737d 100644
--- a/decoder/ETIWriter.cpp
+++ b/decoder/ETIWriter.cpp
@@ -34,6 +34,11 @@ namespace EdiDecoder {
using namespace std;
+ETIWriter::ETIWriter(std::function<void(eti_frame_t&&)>&& frame_callback) :
+ m_frame_callback(move(frame_callback))
+{
+}
+
void ETIWriter::update_protocol(
const std::string& proto,
uint16_t major,
@@ -46,15 +51,6 @@ void ETIWriter::update_protocol(
}
}
-void ETIWriter::reinit()
-{
- m_proto_valid = false;
- m_fc_valid = false;
- m_fic.clear();
- m_etiFrame.frame.clear();
- m_subchannels.clear();
-}
-
void ETIWriter::update_err(uint8_t err)
{
if (not m_proto_valid) {
@@ -284,28 +280,20 @@ void ETIWriter::assemble()
eti.resize(6144, 0x55);
- m_etiFrame.frame = move(eti);
- m_etiFrame.timestamp.seconds = m_seconds;
- m_etiFrame.timestamp.utco = m_utco;
-}
-
-eti_frame_t ETIWriter::getEtiFrame()
-{
- if (m_etiFrame.frame.empty()) {
- return {};
- }
-
- eti_frame_t eti;
- swap(eti, m_etiFrame);
-
- reinit();
+ eti_frame_t etiFrame;
+ etiFrame.frame = move(eti);
+ etiFrame.timestamp.seconds = m_seconds;
+ etiFrame.timestamp.utco = m_utco;
+ etiFrame.mnsc = m_mnsc;
+ etiFrame.frame_characterisation = move(m_fc);
- return eti;
-}
+ m_frame_callback(move(etiFrame));
-uint16_t ETIWriter::get_mnsc() const
-{
- return m_mnsc;
+ m_mnsc = 0xFFFF;
+ m_proto_valid = false;
+ m_fc_valid = false;
+ m_fic.clear();
+ m_subchannels.clear();
}
}
diff --git a/decoder/ETIWriter.hpp b/decoder/ETIWriter.hpp
index 4b2acd7..b990942 100644
--- a/decoder/ETIWriter.hpp
+++ b/decoder/ETIWriter.hpp
@@ -23,6 +23,7 @@
#include <stdint.h>
#include <string>
#include <vector>
+#include <functional>
#include <list>
#include "eti.hpp"
#include "ETIDecoder.hpp"
@@ -31,11 +32,16 @@ namespace EdiDecoder {
struct eti_frame_t {
std::vector<uint8_t> frame;
+ uint16_t mnsc;
frame_timestamp_t timestamp;
+ eti_fc_data frame_characterisation;
};
class ETIWriter : public ETIDataCollector {
public:
+ // The callback gets called for every STI frame that gets assembled
+ ETIWriter(std::function<void(eti_frame_t&&)>&& frame_callback);
+
// Tell the ETIWriter what EDI protocol we receive in *ptr.
// This is not part of the ETI data, but is used as check
virtual void update_protocol(
@@ -65,17 +71,8 @@ class ETIWriter : public ETIDataCollector {
// Tell the ETIWriter that the AFPacket is complete
virtual void assemble(void);
- // Return the assembled ETI frame or an empty frame if not ready
- eti_frame_t getEtiFrame(void);
-
- uint16_t get_mnsc() const;
-
- uint32_t get_timestamp() const { return m_fc.tsta; }
-
- uint8_t get_framephase() const { return m_fc.fp; }
-
private:
- void reinit(void);
+ std::function<void(eti_frame_t&&)> m_frame_callback;
bool m_proto_valid = false;
@@ -87,8 +84,6 @@ class ETIWriter : public ETIDataCollector {
// m_fic is valid if non-empty
std::vector<uint8_t> m_fic;
- eti_frame_t m_etiFrame;
-
std::list<eti_stc_data> m_subchannels;
bool m_time_valid = false;
diff --git a/decoder/STIWriter.cpp b/decoder/STIWriter.cpp
index 8f527b0..82cdd06 100644
--- a/decoder/STIWriter.cpp
+++ b/decoder/STIWriter.cpp
@@ -34,6 +34,11 @@ namespace EdiDecoder {
using namespace std;
+STIWriter::STIWriter(std::function<void(sti_frame_t&&)>&& frame_callback) :
+ m_frame_callback(move(frame_callback))
+{
+}
+
void STIWriter::update_protocol(
const std::string& proto,
uint16_t major,
@@ -46,15 +51,6 @@ void STIWriter::update_protocol(
}
}
-void STIWriter::reinit()
-{
- m_proto_valid = false;
- m_management_data_valid = false;
- m_stat_valid = false;
- m_time_valid = false;
- m_payload_valid = false;
- m_stiFrame.frame.clear();
-}
void STIWriter::update_stat(uint8_t stat, uint16_t spid)
{
@@ -118,25 +114,19 @@ void STIWriter::assemble()
// TODO check time validity
- // Do copies so as to preserve existing payload data
- m_stiFrame.frame = m_payload.istd;
- m_stiFrame.timestamp.seconds = m_seconds;
- m_stiFrame.timestamp.utco = m_utco;
- m_stiFrame.timestamp.tsta = m_management_data.tsta;
-}
+ sti_frame_t stiFrame;
+ stiFrame.frame = move(m_payload.istd);
+ stiFrame.timestamp.seconds = m_seconds;
+ stiFrame.timestamp.utco = m_utco;
+ stiFrame.timestamp.tsta = m_management_data.tsta;
-sti_frame_t STIWriter::getFrame()
-{
- if (m_stiFrame.frame.empty()) {
- return {};
- }
- fprintf(stderr, "STIWriter::getframe DFLC=%d\n", m_management_data.dflc);
+ m_frame_callback(move(stiFrame));
- sti_frame_t sti;
- swap(sti, m_stiFrame);
- reinit();
- return sti;
+ m_proto_valid = false;
+ m_management_data_valid = false;
+ m_stat_valid = false;
+ m_time_valid = false;
+ m_payload_valid = false;
}
}
-
diff --git a/decoder/STIWriter.hpp b/decoder/STIWriter.hpp
index a75cb69..4728131 100644
--- a/decoder/STIWriter.hpp
+++ b/decoder/STIWriter.hpp
@@ -23,6 +23,7 @@
#include "common.hpp"
#include "STIDecoder.hpp"
#include <cstdint>
+#include <functional>
#include <string>
#include <vector>
#include <list>
@@ -36,6 +37,9 @@ struct sti_frame_t {
class STIWriter : public STIDataCollector {
public:
+ // The callback gets called for every STI frame that gets assembled
+ STIWriter(std::function<void(sti_frame_t&&)>&& frame_callback);
+
// Tell the ETIWriter what EDI protocol we receive in *ptr.
// This is not part of the ETI data, but is used as check
virtual void update_protocol(
@@ -54,12 +58,8 @@ class STIWriter : public STIDataCollector {
virtual void add_payload(sti_payload_data&& payload);
virtual void assemble(void);
-
- // Return the assembled frame or an empty frame if not ready
- sti_frame_t getFrame();
-
private:
- void reinit(void);
+ std::function<void(sti_frame_t&&)> m_frame_callback;
bool m_proto_valid = false;
@@ -76,8 +76,6 @@ class STIWriter : public STIDataCollector {
bool m_payload_valid = false;
sti_payload_data m_payload;
-
- sti_frame_t m_stiFrame;
};
}
diff --git a/test/main.cpp b/test/main.cpp
index 537f162..7042e8c 100644
--- a/test/main.cpp
+++ b/test/main.cpp
@@ -117,80 +117,6 @@ static options_t parseargs(int argc, char **argv)
return options;
}
-static void analyse_timestamp(
- TimestampDecoder& ts_dec,
- EdiDecoder::ETIWriter& writer,
- const EdiDecoder::eti_frame_t& eti
- )
-{
- const uint8_t fct = eti.frame[4];
- const std::time_t now = std::time(nullptr);
-
- ts_dec.updateTimestampEti(writer.get_framephase(), writer.get_mnsc(), writer.get_timestamp(), fct);
-
- const auto ts = ts_dec.getTimestamp();
-
- fprintf(stderr, "%ld: Got ETI Frame with FCT %d at %s: seconds=%d, utco=%d, now-EDI=%ld, MNSC: %d, now-MNSC=%ld, MNSC-EDI=%ld, TSTA=%fms (%d)\n",
- now,
- fct,
- eti.timestamp.to_string().c_str(),
- eti.timestamp.seconds, eti.timestamp.utco,
- now - eti.timestamp.to_unix_epoch(),
- ts->timestamp_sec,
- now - ts->timestamp_sec,
- ts->timestamp_sec - eti.timestamp.to_unix_epoch(),
- ts->timestamp_pps / 16384.0,
- ts->timestamp_pps
- );
-}
-
-static void dump_buf(const uint8_t *data, size_t len)
-{
- static FILE* adler_fd = nullptr;
- if (adler_fd == nullptr) {
- adler_fd = fopen("/home/bram/dab/dabmux/adler32.edilib.txt", "w");
- if (adler_fd == nullptr) {
- abort();
- }
- }
- constexpr uint32_t MOD_ADLER = 65521;
- uint32_t a = 1, b = 0;
- // Process each byte of the data in order
- for (size_t index = 0; index < len; ++index) {
- a = (a + data[index]) % MOD_ADLER;
- b = (b + a) % MOD_ADLER;
- }
- uint32_t adler32 = (b << 16) | a;
- fprintf(adler_fd, "Frame %zu %08X\n", len, adler32);
- fflush(adler_fd);
-}
-
-static void write_outputs(
- const options_t& options,
- vector<uint8_t>&& frame,
- deque<vector<uint8_t> >& aac_frames,
- FILE* fd_out,
- AACDecoder& aac_decoder)
-{
- fwrite(frame.data(), frame.size(), 1, fd_out);
-
- if (options.decode_aac) {
- aac_frames.emplace_back(move(frame));
-
- // Collect five frames to build one superframe
- if (aac_frames.size() == 5) {
- vector<uint8_t> superframe;
- for (const auto& f : aac_frames) {
- superframe.insert(superframe.end(), f.cbegin(), f.cend());
- }
-#warning "debug this"
- aac_decoder.decode_frame(superframe.data(), superframe.size());
- aac_frames.clear();
- }
- }
-
-}
-
int main(int argc, char **argv)
{
if (argc == 1) {
@@ -215,12 +141,69 @@ int main(int argc, char **argv)
double offset = 0;
TimestampDecoder ts_dec(offset);
- EdiDecoder::ETIWriter eti_writer;
+
+ auto eti_cb = [&](EdiDecoder::eti_frame_t&& eti) {
+ fprintf(stderr, "ETI %s\n", eti.timestamp.to_string().c_str());
+ if (fd_out) {
+ fwrite(eti.frame.data(), eti.frame.size(), 1, fd_out);
+ }
+
+ if (not eti.frame.empty() and options.verbose > 0) {
+ ts_dec.updateTimestampEti(eti.frame_characterisation.fp, eti.mnsc,
+ eti.frame_characterisation.tsta,
+ eti.frame_characterisation.fct());
+
+ const auto ts = ts_dec.getTimestamp();
+
+ const std::time_t now = std::time(nullptr);
+
+ fprintf(stderr, "%ld: Got ETI Frame with FCT %d at %s:"
+ " seconds=%d, utco=%d, now-EDI=%ld, MNSC: %d, now-MNSC=%ld, MNSC-EDI=%ld,"
+ " TSTA=%fms (%d)\n",
+ now,
+ eti.frame_characterisation.fct(),
+ eti.timestamp.to_string().c_str(),
+ eti.timestamp.seconds, eti.timestamp.utco,
+ now - eti.timestamp.to_unix_epoch(),
+ ts->timestamp_sec,
+ now - ts->timestamp_sec,
+ ts->timestamp_sec - eti.timestamp.to_unix_epoch(),
+ ts->timestamp_pps / 16384.0,
+ ts->timestamp_pps
+ );
+ }
+ };
+
+ EdiDecoder::ETIWriter eti_writer(eti_cb);
EdiDecoder::ETIDecoder eti_decoder(eti_writer, options.verbose > 1);
deque<vector<uint8_t> > aac_frames;
AACDecoder aac_decoder("edilib-aac.wav");
- EdiDecoder::STIWriter sti_writer;
+
+ auto sti_cb = [&](EdiDecoder::sti_frame_t&& sti) {
+ fprintf(stderr, "STI %s\n", sti.timestamp.to_string().c_str());
+
+ if (fd_out) {
+ fwrite(sti.frame.data(), sti.frame.size(), 1, fd_out);
+ }
+
+ if (options.decode_aac) {
+ aac_frames.emplace_back(move(sti.frame));
+
+ // Collect five frames to build one superframe
+ if (aac_frames.size() == 5) {
+ vector<uint8_t> superframe;
+ for (const auto& f : aac_frames) {
+ superframe.insert(superframe.end(), f.cbegin(), f.cend());
+ }
+#warning "debug this"
+ aac_decoder.decode_frame(superframe.data(), superframe.size());
+ aac_frames.clear();
+ }
+ }
+ };
+
+ EdiDecoder::STIWriter sti_writer(sti_cb);
EdiDecoder::STIDecoder sti_decoder(sti_writer, options.verbose > 1);
if (options.max_delay) {
@@ -262,25 +245,6 @@ int main(int argc, char **argv)
eti_decoder.push_packet(buf);
}
}
-
- std::vector<uint8_t> frame;
- if (options.decode_sti) {
- const auto sti = sti_writer.getFrame();
- frame = move(sti.frame);
- fprintf(stderr, "STI %s\n", sti.timestamp.to_string().c_str());
- }
- else {
- const auto eti = eti_writer.getEtiFrame();
- if (not eti.frame.empty() and options.verbose > 0) {
- analyse_timestamp(ts_dec, eti_writer, eti);
- }
- frame = move(eti.frame);
- }
-
- if (fd_out and not frame.empty()) {
- write_outputs(options, move(frame), aac_frames, fd_out,
- aac_decoder);
- }
}
}
else if (std::regex_match(options.edi_source, m, re_tcp) /* TCP client */ ) {
@@ -310,27 +274,12 @@ int main(int argc, char **argv)
std::vector<uint8_t> frame;
if (options.decode_sti) {
sti_decoder.push_bytes(buf);
- const auto sti = sti_writer.getFrame();
- frame = move(sti.frame);
- dump_buf(frame.data(), frame.size());
}
else {
eti_decoder.push_bytes(buf);
-
- const auto eti = eti_writer.getEtiFrame();
- if (not eti.frame.empty() and options.verbose > 0) {
- analyse_timestamp(ts_dec, eti_writer, eti);
- }
- frame = move(eti.frame);
- }
-
- if (fd_out and not frame.empty()) {
- write_outputs(options, move(frame), aac_frames, fd_out,
- aac_decoder);
}
}
} while (ret > 0);
-
}
else {
FILE* fd = fopen(options.edi_source.c_str(), "r");
@@ -351,19 +300,9 @@ int main(int argc, char **argv)
std::vector<uint8_t> frame;
if (options.decode_sti) {
sti_decoder.push_bytes(buf);
- const auto sti = sti_writer.getFrame();
- frame = move(sti.frame);
}
else {
eti_decoder.push_bytes(buf);
-
- const auto eti = eti_writer.getEtiFrame();
- frame = move(eti.frame);
- }
-
- if (fd_out and not frame.empty()) {
- write_outputs(options, move(frame), aac_frames, fd_out,
- aac_decoder);
}
}
else {