diff options
Diffstat (limited to 'lib/edi')
-rw-r--r-- | lib/edi/STIDecoder.cpp | 33 | ||||
-rw-r--r-- | lib/edi/STIDecoder.hpp | 12 | ||||
-rw-r--r-- | lib/edi/common.cpp | 33 | ||||
-rw-r--r-- | lib/edi/common.hpp | 12 |
4 files changed, 64 insertions, 26 deletions
diff --git a/lib/edi/STIDecoder.cpp b/lib/edi/STIDecoder.cpp index d387f1e..0499c53 100644 --- a/lib/edi/STIDecoder.cpp +++ b/lib/edi/STIDecoder.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2020 + Copyright (C) 2025 Matthias P. Braendli, matthias.braendli@mpb.li http://opendigitalradio.org @@ -20,7 +20,6 @@ */ #include "STIDecoder.hpp" #include "buffer_unpack.hpp" -#include "crc.h" #include "Log.h" #include <cstdio> #include <cassert> @@ -70,6 +69,12 @@ void STIDecoder::setMaxDelay(int num_af_packets) m_dispatcher.setMaxDelay(num_af_packets); } +void STIDecoder::filter_stream_index(bool enable, uint16_t index) +{ + m_filter_stream = enable; + m_filtered_stream_index = index; +} + #define AFPACKET_HEADER_LEN 10 // includes SYNC bool STIDecoder::decode_starptr(const std::vector<uint8_t>& value, const tag_name_t& /*n*/) @@ -173,6 +178,20 @@ bool STIDecoder::decode_ssn(const std::vector<uint8_t>& value, const tag_name_t& n = (uint16_t)(name[2]) << 8; n |= (uint16_t)(name[3]); + if (n == 0) { + if (not m_ssnn_zero_warning_printed) { + etiLog.level(warn) << "EDI: Stream index SSnn tag is zero"; + } + m_ssnn_zero_warning_printed = true; + } + else { + m_ssnn_zero_warning_printed = false; + } + + if (m_filter_stream and m_filtered_stream_index != n) { + return true; + } + sti.stream_index = n - 1; // n is 1-indexed sti.rfa = value[0] >> 3; sti.tid = value[0] & 0x07; @@ -183,14 +202,20 @@ bool STIDecoder::decode_ssn(const std::vector<uint8_t>& value, const tag_name_t& sti.stid = istc & 0xFFF; if (sti.rfa != 0) { - etiLog.level(warn) << "EDI: rfa field in SSnn tag non-null"; + if (not m_rfa_nonnull_warning_printed) { + etiLog.level(warn) << "EDI: rfa field in SSnn tag non-null"; + } + m_rfa_nonnull_warning_printed = true; + } + else { + m_rfa_nonnull_warning_printed = false; } copy( value.cbegin() + 3, value.cend(), back_inserter(sti.istd)); - m_data_collector.add_payload(move(sti)); + m_data_collector.add_payload(std::move(sti)); return true; } diff --git a/lib/edi/STIDecoder.hpp b/lib/edi/STIDecoder.hpp index f85f789..81fbd82 100644 --- a/lib/edi/STIDecoder.hpp +++ b/lib/edi/STIDecoder.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2020 + Copyright (C) 2025 Matthias P. Braendli, matthias.braendli@mpb.li http://opendigitalradio.org @@ -119,6 +119,10 @@ class STIDecoder { */ void setMaxDelay(int num_af_packets); + /* Enable/disable stream-index filtering. + * index==0 is out of spec, but some encoders do it anyway. */ + void filter_stream_index(bool enable, uint16_t index); + private: bool decode_starptr(const std::vector<uint8_t>& value, const tag_name_t& n); bool decode_dsti(const std::vector<uint8_t>& value, const tag_name_t& n); @@ -132,6 +136,12 @@ class STIDecoder { STIDataCollector& m_data_collector; TagDispatcher m_dispatcher; + + bool m_filter_stream = false; + uint16_t m_filtered_stream_index = 1; + + bool m_ssnn_zero_warning_printed = false; + bool m_rfa_nonnull_warning_printed = false; }; } diff --git a/lib/edi/common.cpp b/lib/edi/common.cpp index c99997a..38eadf9 100644 --- a/lib/edi/common.cpp +++ b/lib/edi/common.cpp @@ -33,9 +33,9 @@ namespace EdiDecoder { using namespace std; -bool frame_timestamp_t::valid() const +bool frame_timestamp_t::is_valid() const { - return tsta != 0xFFFFFF; + return tsta != 0xFFFFFF and seconds != 0; } string frame_timestamp_t::to_string() const @@ -43,7 +43,7 @@ string frame_timestamp_t::to_string() const const time_t seconds_in_unix_epoch = to_unix_epoch(); stringstream ss; - if (valid()) { + if (is_valid()) { ss << "Timestamp: "; } else { @@ -129,10 +129,9 @@ std::string tag_name_to_human_readable(const tag_name_t& name) return s; } -TagDispatcher::TagDispatcher( - std::function<void()>&& af_packet_completed) : - m_af_packet_completed(move(af_packet_completed)), - m_tagpacket_handler([](const std::vector<uint8_t>& /*ignore*/){}) +TagDispatcher::TagDispatcher(std::function<void()>&& af_packet_completed) : + m_af_packet_completed(std::move(af_packet_completed)), + m_afpacket_handler([](std::vector<uint8_t>&& /*ignore*/){}) { } @@ -278,7 +277,6 @@ void TagDispatcher::setMaxDelay(int num_af_packets) } -#define AFPACKET_HEADER_LEN 10 // includes SYNC TagDispatcher::decode_result_t TagDispatcher::decode_afpacket( const std::vector<uint8_t> &input_data) { @@ -341,25 +339,30 @@ TagDispatcher::decode_result_t TagDispatcher::decode_afpacket( return {decode_state_e::Error, AFPACKET_HEADER_LEN + taglength + crclen}; } else { + vector<uint8_t> afpacket(AFPACKET_HEADER_LEN + taglength + crclen); + copy(input_data.begin(), + input_data.begin() + AFPACKET_HEADER_LEN + taglength + crclen, + afpacket.begin()); + m_afpacket_handler(std::move(afpacket)); + vector<uint8_t> payload(taglength); copy(input_data.begin() + AFPACKET_HEADER_LEN, input_data.begin() + AFPACKET_HEADER_LEN + taglength, payload.begin()); - return { - decode_tagpacket(payload) ? decode_state_e::Ok : decode_state_e::Error, - AFPACKET_HEADER_LEN + taglength + crclen}; + auto result = decode_tagpacket(payload) ? decode_state_e::Ok : decode_state_e::Error; + return {result, AFPACKET_HEADER_LEN + taglength + crclen}; } } void TagDispatcher::register_tag(const std::string& tag, tag_handler&& h) { - m_handlers[tag] = move(h); + m_handlers[tag] = std::move(h); } -void TagDispatcher::register_tagpacket_handler(tagpacket_handler&& h) +void TagDispatcher::register_afpacket_handler(afpacket_handler&& h) { - m_tagpacket_handler = move(h); + m_afpacket_handler = std::move(h); } @@ -428,8 +431,6 @@ bool TagDispatcher::decode_tagpacket(const vector<uint8_t> &payload) } } - m_tagpacket_handler(payload); - return success; } diff --git a/lib/edi/common.hpp b/lib/edi/common.hpp index c3e6c40..fdd7424 100644 --- a/lib/edi/common.hpp +++ b/lib/edi/common.hpp @@ -32,12 +32,14 @@ namespace EdiDecoder { +constexpr size_t AFPACKET_HEADER_LEN = 10; // includes SYNC + struct frame_timestamp_t { uint32_t seconds = 0; uint32_t utco = 0; uint32_t tsta = 0xFFFFFF; // According to EN 300 797 Annex B - bool valid() const; + bool is_valid() const; std::string to_string() const; std::time_t to_unix_epoch() const; std::chrono::system_clock::time_point to_system_clock() const; @@ -133,9 +135,9 @@ class TagDispatcher { */ void register_tag(const std::string& tag, tag_handler&& h); - /* The complete tagpacket can also be retrieved */ - using tagpacket_handler = std::function<void(const std::vector<uint8_t>&)>; - void register_tagpacket_handler(tagpacket_handler&& h); + /* The complete AF packet can also be retrieved */ + using afpacket_handler = std::function<void(std::vector<uint8_t>&&)>; + void register_afpacket_handler(afpacket_handler&& h); seq_info_t get_seq_info() const { return m_last_sequences; @@ -160,7 +162,7 @@ class TagDispatcher { std::vector<uint8_t> m_input_data; std::map<std::string, tag_handler> m_handlers; std::function<void()> m_af_packet_completed; - tagpacket_handler m_tagpacket_handler; + afpacket_handler m_afpacket_handler; std::vector<std::string> m_ignored_tags; }; |