diff options
author | Matthias P. Braendli <matthias.braendli@mpb.li> | 2021-05-19 14:48:13 +0200 |
---|---|---|
committer | Matthias P. Braendli <matthias.braendli@mpb.li> | 2021-05-19 14:48:13 +0200 |
commit | 26b20a9aa0167b64e75b813aaf9b41557b4de3df (patch) | |
tree | 8ea23fc867cde052a70795159e8c122dccd763a7 /lib | |
parent | 9067a63a4dd433c6109ba0157db516c9cac398e4 (diff) | |
download | dabmux-26b20a9aa0167b64e75b813aaf9b41557b4de3df.tar.gz dabmux-26b20a9aa0167b64e75b813aaf9b41557b4de3df.tar.bz2 dabmux-26b20a9aa0167b64e75b813aaf9b41557b4de3df.zip |
Common 44ae39c: Make SEQ and PSEQ available on EDI receive and improve error handling
Diffstat (limited to 'lib')
-rw-r--r-- | lib/edi/PFT.cpp | 63 | ||||
-rw-r--r-- | lib/edi/PFT.hpp | 19 | ||||
-rw-r--r-- | lib/edi/STIDecoder.cpp | 11 | ||||
-rw-r--r-- | lib/edi/STIDecoder.hpp | 2 | ||||
-rw-r--r-- | lib/edi/STIWriter.cpp | 3 | ||||
-rw-r--r-- | lib/edi/STIWriter.hpp | 19 | ||||
-rw-r--r-- | lib/edi/common.cpp | 26 | ||||
-rw-r--r-- | lib/edi/common.hpp | 14 | ||||
-rw-r--r-- | lib/edioutput/AFPacket.cpp | 18 | ||||
-rw-r--r-- | lib/edioutput/AFPacket.h | 9 | ||||
-rw-r--r-- | lib/edioutput/EDIConfig.h | 1 | ||||
-rw-r--r-- | lib/edioutput/PFT.cpp | 8 | ||||
-rw-r--r-- | lib/edioutput/PFT.h | 5 | ||||
-rw-r--r-- | lib/edioutput/TagItems.cpp | 1 | ||||
-rw-r--r-- | lib/edioutput/TagItems.h | 1 | ||||
-rw-r--r-- | lib/edioutput/TagPacket.cpp | 1 | ||||
-rw-r--r-- | lib/edioutput/TagPacket.h | 1 | ||||
-rw-r--r-- | lib/edioutput/Transport.cpp | 15 | ||||
-rw-r--r-- | lib/edioutput/Transport.h | 15 |
19 files changed, 155 insertions, 77 deletions
diff --git a/lib/edi/PFT.cpp b/lib/edi/PFT.cpp index 85d6b63..25f2d1f 100644 --- a/lib/edi/PFT.cpp +++ b/lib/edi/PFT.cpp @@ -1,6 +1,6 @@ /* ------------------------------------------------------------------ * Copyright (C) 2017 AVT GmbH - Fabien Vercasson - * Copyright (C) 2017 Matthias P. Braendli + * Copyright (C) 2021 Matthias P. Braendli * matthias.braendli@mpb.li * * http://opendigitalradio.org @@ -126,7 +126,7 @@ size_t Fragment::loadData(const std::vector<uint8_t> &buf, int received_on_port) // Parse PFT Fragment Header (ETSI TS 102 821 V1.4.1 ch7.1) if (not (buf[0] == 'P' and buf[1] == 'F') ) { - throw invalid_argument("Invalid PFT SYNC bytes"); + throw runtime_error("Invalid PFT SYNC bytes"); } index += 2; // Psync @@ -208,15 +208,30 @@ AFBuilder::AFBuilder(pseq_t Pseq, findex_t Fcount, size_t lifetime) void AFBuilder::pushPFTFrag(const Fragment &frag) { - if (_Pseq != frag.Pseq() or _Fcount != frag.Fcount()) { - throw invalid_argument("Invalid PFT fragment Pseq or Fcount"); + if (_Pseq != frag.Pseq()) { + throw logic_error("Invalid PFT fragment Pseq"); } - const auto Findex = frag.Findex(); - const bool fragment_already_received = _fragments.count(Findex); - if (not fragment_already_received) - { - _fragments[Findex] = frag; + if (_Fcount != frag.Fcount()) { + etiLog.level(warn) << "Discarding fragment with invalid fcount"; + } + else { + const auto Findex = frag.Findex(); + const bool fragment_already_received = _fragments.count(Findex); + + if (not fragment_already_received) { + bool consistent = true; + if (_fragments.size() > 0) { + consistent = frag.checkConsistency(_fragments.cbegin()->second); + } + + if (consistent) { + _fragments[Findex] = frag; + } + else { + etiLog.level(warn) << "Discard fragment"; + } + } } } @@ -246,7 +261,7 @@ bool Fragment::checkConsistency(const Fragment& other) const } -AFBuilder::decode_attempt_result_t AFBuilder::canAttemptToDecode() const +AFBuilder::decode_attempt_result_t AFBuilder::canAttemptToDecode() { if (_fragments.empty()) { return AFBuilder::decode_attempt_result_t::no; @@ -263,7 +278,8 @@ AFBuilder::decode_attempt_result_t AFBuilder::canAttemptToDecode() const const Fragment& frag = pair.second; return first.checkConsistency(frag) and _Pseq == frag.Pseq(); }) ) { - throw invalid_argument("Inconsistent PFT fragments"); + _fragments.clear(); + throw runtime_error("Inconsistent PFT fragments"); } // Calculate the minimum number of fragments necessary to apply FEC. @@ -301,7 +317,7 @@ AFBuilder::decode_attempt_result_t AFBuilder::canAttemptToDecode() const return AFBuilder::decode_attempt_result_t::no; } -std::vector<uint8_t> AFBuilder::extractAF() const +std::vector<uint8_t> AFBuilder::extractAF() { if (not _af_packet.empty()) { return _af_packet; @@ -310,13 +326,12 @@ std::vector<uint8_t> AFBuilder::extractAF() const bool ok = false; if (canAttemptToDecode() != AFBuilder::decode_attempt_result_t::no) { - auto frag_it = _fragments.begin(); if (frag_it->second.Fcount() == _Fcount - 1) { frag_it++; if (frag_it == _fragments.end()) { - throw std::runtime_error("Invalid attempt at extracting AF"); + throw runtime_error("Invalid attempt at extracting AF"); } } @@ -343,12 +358,14 @@ std::vector<uint8_t> AFBuilder::extractAF() const const auto& fragment = _fragments.at(j).payload(); if (j != _Fcount - 1 and fragment.size() != Plen) { + _fragments.clear(); throw runtime_error("Incorrect fragment length " + to_string(fragment.size()) + " " + to_string(Plen)); } if (j == _Fcount - 1 and fragment.size() > Plen) { + _fragments.clear(); throw runtime_error("Incorrect last fragment length " + to_string(fragment.size()) + " " + to_string(Plen)); @@ -453,7 +470,7 @@ std::vector<uint8_t> AFBuilder::extractAF() const return _af_packet; } -std::string AFBuilder::visualise() const +std::string AFBuilder::visualise() { stringstream ss; ss << "|"; @@ -525,7 +542,7 @@ void PFT::pushPFTFrag(const Fragment &fragment) if (m_verbose) { etiLog.log(debug, "Got frag %u:%u, afbuilders: ", fragment.Pseq(), fragment.Findex()); - for (const auto &k : m_afbuilders) { + for (auto &k : m_afbuilders) { const bool isNextPseq = (m_next_pseq == k.first); etiLog.level(debug) << (isNextPseq ? "->" : " ") << k.first << " " << k.second.visualise(); @@ -534,15 +551,17 @@ void PFT::pushPFTFrag(const Fragment &fragment) } -std::vector<uint8_t> PFT::getNextAFPacket() +afpacket_pft_t PFT::getNextAFPacket() { + afpacket_pft_t af; + if (m_afbuilders.count(m_next_pseq) == 0) { if (m_afbuilders.size() > m_max_delay) { m_afbuilders.clear(); etiLog.level(debug) << " Reinit"; } - return {}; + return af; } auto &builder = m_afbuilders.at(m_next_pseq); @@ -555,8 +574,9 @@ std::vector<uint8_t> PFT::getNextAFPacket() if (m_verbose) { etiLog.level(debug) << "Fragment origin stats: " << builder.visualise_fragment_origins(); } + af.pseq = m_next_pseq; + af.af_packet = afpacket; incrementNextPseq(); - return afpacket; } else if (builder.canAttemptToDecode() == dar_t::maybe) { if (builder.lifeTime > 0) { @@ -573,8 +593,9 @@ std::vector<uint8_t> PFT::getNextAFPacket() if (m_verbose) { etiLog.level(debug) << "Fragment origin stats: " << builder.visualise_fragment_origins(); } + af.pseq = m_next_pseq; + af.af_packet = afpacket; incrementNextPseq(); - return afpacket; } } else { @@ -588,7 +609,7 @@ std::vector<uint8_t> PFT::getNextAFPacket() } } - return {}; + return af; } void PFT::setMaxDelay(size_t num_af_packets) diff --git a/lib/edi/PFT.hpp b/lib/edi/PFT.hpp index 08dca45..aa5b9d3 100644 --- a/lib/edi/PFT.hpp +++ b/lib/edi/PFT.hpp @@ -1,6 +1,6 @@ /* ------------------------------------------------------------------ * Copyright (C) 2017 AVT GmbH - Fabien Vercasson - * Copyright (C) 2017 Matthias P. Braendli + * Copyright (C) 2021 Matthias P. Braendli * matthias.braendli@mpb.li * * http://opendigitalradio.org @@ -101,20 +101,20 @@ class AFBuilder void pushPFTFrag(const Fragment &frag); /* Assess if it may be possible to decode this AF packet */ - decode_attempt_result_t canAttemptToDecode() const; + decode_attempt_result_t canAttemptToDecode(); /* Try to build the AF with received fragments. * Apply error correction if necessary (missing packets/CRC errors) * \return an empty vector if building the AF is not possible */ - std::vector<uint8_t> extractAF(void) const; + std::vector<uint8_t> extractAF(); std::pair<findex_t, findex_t> numberOfFragments(void) const { return {_fragments.size(), _Fcount}; } - std::string visualise() const; + std::string visualise(); std::string visualise_fragment_origins() const; @@ -135,6 +135,13 @@ class AFBuilder findex_t _Fcount; }; +struct afpacket_pft_t +{ + // validity of the struct is given by af_packet begin empty or not. + std::vector<uint8_t> af_packet; + pseq_t pseq = 0; +}; + class PFT { public: @@ -145,7 +152,7 @@ class PFT * * \return an empty vector if building the AF is not possible */ - std::vector<uint8_t> getNextAFPacket(void); + afpacket_pft_t getNextAFPacket(); /* Set the maximum delay in number of AF Packets before we * abandon decoding a given pseq. @@ -156,7 +163,7 @@ class PFT void setVerbose(bool enable); private: - void incrementNextPseq(void); + void incrementNextPseq(); pseq_t m_next_pseq; size_t m_max_delay = 10; // in AF packets diff --git a/lib/edi/STIDecoder.cpp b/lib/edi/STIDecoder.cpp index 99f7c11..d387f1e 100644 --- a/lib/edi/STIDecoder.cpp +++ b/lib/edi/STIDecoder.cpp @@ -72,7 +72,7 @@ void STIDecoder::setMaxDelay(int num_af_packets) #define AFPACKET_HEADER_LEN 10 // includes SYNC -bool STIDecoder::decode_starptr(const std::vector<uint8_t>& value, const tag_name_t& n) +bool STIDecoder::decode_starptr(const std::vector<uint8_t>& value, const tag_name_t& /*n*/) { if (value.size() != 0x40 / 8) { etiLog.log(warn, "Incorrect length %02lx for *PTR", value.size()); @@ -92,7 +92,7 @@ bool STIDecoder::decode_starptr(const std::vector<uint8_t>& value, const tag_nam return true; } -bool STIDecoder::decode_dsti(const std::vector<uint8_t>& value, const tag_name_t& n) +bool STIDecoder::decode_dsti(const std::vector<uint8_t>& value, const tag_name_t& /*n*/) { size_t offset = 0; @@ -200,7 +200,7 @@ bool STIDecoder::decode_stardmy(const std::vector<uint8_t>&, const tag_name_t&) return true; } -bool STIDecoder::decode_odraudiolevel(const std::vector<uint8_t>& value, const tag_name_t& n) +bool STIDecoder::decode_odraudiolevel(const std::vector<uint8_t>& value, const tag_name_t& /*n*/) { constexpr size_t expected_length = 2 * sizeof(int16_t); @@ -223,7 +223,7 @@ bool STIDecoder::decode_odraudiolevel(const std::vector<uint8_t>& value, const t return true; } -bool STIDecoder::decode_odrversion(const std::vector<uint8_t>& value, const tag_name_t& n) +bool STIDecoder::decode_odrversion(const std::vector<uint8_t>& value, const tag_name_t& /*n*/) { const auto vd = parse_odr_version_data(value); m_data_collector.update_odr_version(vd); @@ -233,7 +233,8 @@ bool STIDecoder::decode_odrversion(const std::vector<uint8_t>& value, const tag_ void STIDecoder::packet_completed() { - m_data_collector.assemble(); + auto seq = m_dispatcher.get_seq_info(); + m_data_collector.assemble(seq); } } diff --git a/lib/edi/STIDecoder.hpp b/lib/edi/STIDecoder.hpp index 28887f2..f85f789 100644 --- a/lib/edi/STIDecoder.hpp +++ b/lib/edi/STIDecoder.hpp @@ -87,7 +87,7 @@ class STIDataCollector { virtual void update_audio_levels(const audio_level_data& data) = 0; virtual void update_odr_version(const odr_version_data& data) = 0; - virtual void assemble() = 0; + virtual void assemble(seq_info_t sequences) = 0; }; /* The STIDecoder takes care of decoding the EDI TAGs related to the transport diff --git a/lib/edi/STIWriter.cpp b/lib/edi/STIWriter.cpp index 29f0124..1171065 100644 --- a/lib/edi/STIWriter.cpp +++ b/lib/edi/STIWriter.cpp @@ -106,7 +106,7 @@ void STIWriter::update_edi_time( } -void STIWriter::assemble() +void STIWriter::assemble(seq_info_t seq) { if (not m_proto_valid) { throw std::runtime_error("Cannot assemble STI before protocol"); @@ -130,6 +130,7 @@ void STIWriter::assemble() stiFrame.timestamp.tsta = m_management_data.tsta; stiFrame.audio_levels = m_audio_levels; stiFrame.version_data = m_version_data; + stiFrame.sequence_counters = seq; m_frame_callback(move(stiFrame)); diff --git a/lib/edi/STIWriter.hpp b/lib/edi/STIWriter.hpp index a7a5cda..2454a74 100644 --- a/lib/edi/STIWriter.hpp +++ b/lib/edi/STIWriter.hpp @@ -36,6 +36,7 @@ struct sti_frame_t { frame_timestamp_t timestamp; audio_level_data audio_levels; odr_version_data version_data; + seq_info_t sequence_counters; }; class STIWriter : public STIDataCollector { @@ -48,22 +49,22 @@ class STIWriter : public STIDataCollector { virtual void update_protocol( const std::string& proto, uint16_t major, - uint16_t minor); + uint16_t minor) override; - virtual void update_stat(uint8_t stat, uint16_t spid); + virtual void update_stat(uint8_t stat, uint16_t spid) override; virtual void update_edi_time( uint32_t utco, - uint32_t seconds); + uint32_t seconds) override; - virtual void update_rfad(std::array<uint8_t, 9> rfad); - virtual void update_sti_management(const sti_management_data& data); - virtual void add_payload(sti_payload_data&& payload); + virtual void update_rfad(std::array<uint8_t, 9> rfad) override; + virtual void update_sti_management(const sti_management_data& data) override; + virtual void add_payload(sti_payload_data&& payload) override; - virtual void update_audio_levels(const audio_level_data& data); - virtual void update_odr_version(const odr_version_data& data); + virtual void update_audio_levels(const audio_level_data& data) override; + virtual void update_odr_version(const odr_version_data& data) override; - virtual void assemble(void); + virtual void assemble(seq_info_t seq) override; private: std::function<void(sti_frame_t&&)> m_frame_callback; diff --git a/lib/edi/common.cpp b/lib/edi/common.cpp index 7907656..2f20391 100644 --- a/lib/edi/common.cpp +++ b/lib/edi/common.cpp @@ -132,7 +132,7 @@ std::string tag_name_to_human_readable(const tag_name_t& name) 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){}) + m_tagpacket_handler([](const std::vector<uint8_t>& /*ignore*/){}) { } @@ -145,7 +145,7 @@ void TagDispatcher::push_bytes(const vector<uint8_t> &buf) { if (buf.empty()) { m_input_data.clear(); - m_last_seq_valid = false; + m_last_sequences.seq_valid = false; return; } @@ -168,6 +168,7 @@ void TagDispatcher::push_bytes(const vector<uint8_t> &buf) m_input_data = remaining_data; } + m_last_sequences.pseq_valid = false; if (st.complete) { m_af_packet_completed(); } @@ -192,8 +193,10 @@ void TagDispatcher::push_bytes(const vector<uint8_t> &buf) } auto af = m_pft.getNextAFPacket(); - if (not af.empty()) { - decode_state_t st = decode_afpacket(af); + if (not af.af_packet.empty()) { + const decode_state_t st = decode_afpacket(af.af_packet); + m_last_sequences.pseq = af.pseq; + m_last_sequences.pseq_valid = true; if (st.complete) { m_af_packet_completed(); @@ -217,6 +220,7 @@ void TagDispatcher::push_packet(const Packet &packet) if (buf[0] == 'A' and buf[1] == 'F') { const decode_state_t st = decode_afpacket(buf); + m_last_sequences.pseq_valid = false; if (st.complete) { m_af_packet_completed(); @@ -232,8 +236,10 @@ void TagDispatcher::push_packet(const Packet &packet) } auto af = m_pft.getNextAFPacket(); - if (not af.empty()) { - const decode_state_t st = decode_afpacket(af); + if (not af.af_packet.empty()) { + const decode_state_t st = decode_afpacket(af.af_packet); + m_last_sequences.pseq = af.pseq; + m_last_sequences.pseq_valid = true; if (st.complete) { m_af_packet_completed(); @@ -272,8 +278,8 @@ decode_state_t TagDispatcher::decode_afpacket( } // SEQ wraps at 0xFFFF, unsigned integer overflow is intentional - if (m_last_seq_valid) { - const uint16_t expected_seq = m_last_seq + 1; + if (m_last_sequences.seq_valid) { + const uint16_t expected_seq = m_last_sequences.seq + 1; if (expected_seq != seq) { etiLog.level(warn) << "EDI AF Packet sequence error, " << seq; m_ignored_tags.clear(); @@ -281,9 +287,9 @@ decode_state_t TagDispatcher::decode_afpacket( } else { etiLog.level(info) << "EDI AF Packet initial sequence number: " << seq; - m_last_seq_valid = true; + m_last_sequences.seq_valid = true; } - m_last_seq = seq; + m_last_sequences.seq = seq; bool has_crc = (input_data[8] & 0x80) ? true : false; uint8_t major_revision = (input_data[8] & 0x70) >> 4; diff --git a/lib/edi/common.hpp b/lib/edi/common.hpp index 14b91ba..e8c57c1 100644 --- a/lib/edi/common.hpp +++ b/lib/edi/common.hpp @@ -68,6 +68,13 @@ struct Packet { Packet() {} }; +struct seq_info_t { + bool seq_valid = false; + uint16_t seq = 0; + bool pseq_valid = false; + uint16_t pseq = 0; +}; + /* The TagDispatcher takes care of decoding EDI, with or without PFT, and * will call functions when TAGs are encountered. * @@ -110,13 +117,16 @@ class TagDispatcher { using tagpacket_handler = std::function<void(const std::vector<uint8_t>&)>; void register_tagpacket_handler(tagpacket_handler&& h); + seq_info_t get_seq_info() const { + return m_last_sequences; + } + private: decode_state_t decode_afpacket(const std::vector<uint8_t> &input_data); bool decode_tagpacket(const std::vector<uint8_t> &payload); PFT::PFT m_pft; - bool m_last_seq_valid = false; - uint16_t m_last_seq = 0; + seq_info_t m_last_sequences; std::vector<uint8_t> m_input_data; std::map<std::string, tag_handler> m_handlers; std::function<void()> m_af_packet_completed; diff --git a/lib/edioutput/AFPacket.cpp b/lib/edioutput/AFPacket.cpp index b38c38b..323a3b1 100644 --- a/lib/edioutput/AFPacket.cpp +++ b/lib/edioutput/AFPacket.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2014 + Copyright (C) 2021 Matthias P. Braendli, matthias.braendli@mpb.li http://www.opendigitalradio.org @@ -25,7 +25,6 @@ You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "config.h" #include "crc.h" #include "AFPacket.h" #include "TagItems.h" @@ -50,7 +49,7 @@ AFPacket AFPacketiser::Assemble(TagPacket tag_packet) std::vector<uint8_t> payload = tag_packet.Assemble(); if (m_verbose) - std::cerr << "Assemble AFPacket " << seq << std::endl; + std::cerr << "Assemble AFPacket " << m_seq << std::endl; std::string pack_data("AF"); // SYNC std::vector<uint8_t> packet(pack_data.begin(), pack_data.end()); @@ -67,10 +66,10 @@ AFPacket AFPacketiser::Assemble(TagPacket tag_packet) packet.push_back(taglength & 0xFF); // fill rest of header - packet.push_back(seq >> 8); - packet.push_back(seq & 0xFF); - seq++; - packet.push_back((have_crc ? 0x80 : 0) | AFHEADER_VERSION); // ar_cf: CRC=1 + packet.push_back(m_seq >> 8); + packet.push_back(m_seq & 0xFF); + m_seq++; + packet.push_back((m_have_crc ? 0x80 : 0) | AFHEADER_VERSION); // ar_cf: CRC=1 packet.push_back(AFHEADER_PT_TAG); // insert payload, must have a length multiple of 8 bytes @@ -93,4 +92,9 @@ AFPacket AFPacketiser::Assemble(TagPacket tag_packet) return packet; } +void AFPacketiser::OverrideSeq(uint16_t seq) +{ + m_seq = seq; +} + } diff --git a/lib/edioutput/AFPacket.h b/lib/edioutput/AFPacket.h index f2c4e35..6e6ec47 100644 --- a/lib/edioutput/AFPacket.h +++ b/lib/edioutput/AFPacket.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2014 + Copyright (C) 2021 Matthias P. Braendli, matthias.braendli@mpb.li http://www.opendigitalradio.org @@ -28,7 +28,6 @@ #pragma once -#include "config.h" #include <vector> #include <cstdint> #include "TagItems.h" @@ -49,10 +48,12 @@ class AFPacketiser AFPacket Assemble(TagPacket tag_packet); + void OverrideSeq(uint16_t seq); + private: - static const bool have_crc = true; + static const bool m_have_crc = true; - uint16_t seq = 0; //counter that overflows at 0xFFFF + uint16_t m_seq = 0; //counter that overflows at 0xFFFF bool m_verbose; }; diff --git a/lib/edioutput/EDIConfig.h b/lib/edioutput/EDIConfig.h index be6c9c4..d57e9ce 100644 --- a/lib/edioutput/EDIConfig.h +++ b/lib/edioutput/EDIConfig.h @@ -27,7 +27,6 @@ #pragma once -#include "config.h" #include <vector> #include <string> #include <memory> diff --git a/lib/edioutput/PFT.cpp b/lib/edioutput/PFT.cpp index b2f07e0..7e0e8e9 100644 --- a/lib/edioutput/PFT.cpp +++ b/lib/edioutput/PFT.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2019 + Copyright (C) 2021 Matthias P. Braendli, matthias.braendli@mpb.li http://www.opendigitalradio.org @@ -30,7 +30,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "config.h" #include <vector> #include <list> #include <cstdio> @@ -320,5 +319,10 @@ std::vector< PFTFragment > PFT::Assemble(AFPacket af_packet) return pft_fragments; } +void PFT::OverridePSeq(uint16_t pseq) +{ + m_pseq = pseq; +} + } diff --git a/lib/edioutput/PFT.h b/lib/edioutput/PFT.h index 4d138c5..42569a0 100644 --- a/lib/edioutput/PFT.h +++ b/lib/edioutput/PFT.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2019 + Copyright (C) 2021 Matthias P. Braendli, matthias.braendli@mpb.li http://www.opendigitalradio.org @@ -32,7 +32,6 @@ #pragma once -#include "config.h" #include <vector> #include <list> #include <stdexcept> @@ -65,6 +64,8 @@ class PFT // Cut a RSBlock into several fragments that can be transmitted std::vector< std::vector<uint8_t> > ProtectAndFragment(AFPacket af_packet); + void OverridePSeq(uint16_t pseq); + private: unsigned int m_k = 207; // length of RS data word unsigned int m_m = 3; // number of fragments that can be recovered if lost diff --git a/lib/edioutput/TagItems.cpp b/lib/edioutput/TagItems.cpp index 739adfa..a47d168 100644 --- a/lib/edioutput/TagItems.cpp +++ b/lib/edioutput/TagItems.cpp @@ -26,7 +26,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "config.h" #include "TagItems.h" #include <vector> #include <iostream> diff --git a/lib/edioutput/TagItems.h b/lib/edioutput/TagItems.h index f24dc44..029681c 100644 --- a/lib/edioutput/TagItems.h +++ b/lib/edioutput/TagItems.h @@ -28,7 +28,6 @@ #pragma once -#include "config.h" #include <vector> #include <array> #include <chrono> diff --git a/lib/edioutput/TagPacket.cpp b/lib/edioutput/TagPacket.cpp index ec52ad7..d89fce7 100644 --- a/lib/edioutput/TagPacket.cpp +++ b/lib/edioutput/TagPacket.cpp @@ -24,7 +24,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "config.h" #include "TagPacket.h" #include "TagItems.h" #include <vector> diff --git a/lib/edioutput/TagPacket.h b/lib/edioutput/TagPacket.h index b53b718..ad23530 100644 --- a/lib/edioutput/TagPacket.h +++ b/lib/edioutput/TagPacket.h @@ -26,7 +26,6 @@ #pragma once -#include "config.h" #include "TagItems.h" #include <vector> #include <string> diff --git a/lib/edioutput/Transport.cpp b/lib/edioutput/Transport.cpp index 274f7ec..5d34814 100644 --- a/lib/edioutput/Transport.cpp +++ b/lib/edioutput/Transport.cpp @@ -126,6 +126,11 @@ void Sender::write(const TagPacket& tagpacket) // Assemble into one AF Packet edi::AFPacket af_packet = edi_afPacketiser.Assemble(tagpacket); + write(af_packet); +} + +void Sender::write(const AFPacket& af_packet) +{ if (m_conf.enable_pft) { // Apply PFT layer to AF Packet (Reed Solomon FEC and Fragmentation) vector<edi::PFTFragment> edi_fragments = edi_pft.Assemble(af_packet); @@ -194,6 +199,16 @@ void Sender::write(const TagPacket& tagpacket) } } +void Sender::override_af_sequence(uint16_t seq) +{ + edi_afPacketiser.OverrideSeq(seq); +} + +void Sender::override_pft_sequence(uint16_t pseq) +{ + edi_pft.OverridePSeq(pseq); +} + void Sender::run() { while (m_running) { diff --git a/lib/edioutput/Transport.h b/lib/edioutput/Transport.h index 3bcc2f4..be93297 100644 --- a/lib/edioutput/Transport.h +++ b/lib/edioutput/Transport.h @@ -27,7 +27,6 @@ #pragma once -#include "config.h" #include "EDIConfig.h" #include "AFPacket.h" #include "PFT.h" @@ -44,7 +43,7 @@ namespace edi { -/** Configuration for EDI output */ +/** STI sender for EDI output */ class Sender { public: @@ -53,8 +52,20 @@ class Sender { Sender operator=(const Sender&) = delete; ~Sender(); + // Assemble the tagpacket into an AF packet, and if needed, + // apply PFT and then schedule for transmission. void write(const TagPacket& tagpacket); + // Schedule an already assembled AF Packet for transmission, + // applying PFT if needed. + void write(const AFPacket& af_packet); + + // Set the sequence numbers to be used for the next call to write() + // seq is for the AF layer + // pseq is for the PFT layer + void override_af_sequence(uint16_t seq); + void override_pft_sequence(uint16_t pseq); + private: void run(); |