diff options
author | Matthias P. Braendli <matthias.braendli@mpb.li> | 2020-04-28 15:26:49 +0200 |
---|---|---|
committer | Matthias P. Braendli <matthias.braendli@mpb.li> | 2020-04-28 15:26:49 +0200 |
commit | 5849cc8696c96377506bd60337656481da6c21b4 (patch) | |
tree | 90145ad4be1343caaa88e457bcdb11c6b752b438 | |
parent | 06a429d0148c94c35f3e4e226714299dc03af5eb (diff) | |
download | ODR-EDI2EDI-5849cc8696c96377506bd60337656481da6c21b4.tar.gz ODR-EDI2EDI-5849cc8696c96377506bd60337656481da6c21b4.tar.bz2 ODR-EDI2EDI-5849cc8696c96377506bd60337656481da6c21b4.zip |
Get it to compile
-rw-r--r-- | .gitignore | 27 | ||||
-rw-r--r-- | Makefile.am | 20 | ||||
-rwxr-xr-x | bootstrap.sh | 4 | ||||
-rw-r--r-- | lib/edi/STIDecoder.cpp | 226 | ||||
-rw-r--r-- | lib/edi/STIDecoder.hpp | 134 | ||||
-rw-r--r-- | lib/edi/STIWriter.cpp | 142 | ||||
-rw-r--r-- | lib/edi/STIWriter.hpp | 90 |
7 files changed, 36 insertions, 607 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3405b86 --- /dev/null +++ b/.gitignore @@ -0,0 +1,27 @@ +*.o +*.Po + +.*.swp +.directory + +odr-edi2edi + +aclocal.m4 +build-aux +configure +Makefile.in +Makefile +autom4te.cache +config.h +config.log +config.status +stamp-h1 +config.h.in~ +config.h.in +.deps +.dirstamp +*.plist + +cscope.out +ctags +tags diff --git a/Makefile.am b/Makefile.am index 000c5c1..88b7219 100644 --- a/Makefile.am +++ b/Makefile.am @@ -8,14 +8,13 @@ endif bin_PROGRAMS=odr-edi2edi -INCLUDE=-Isrc +INCLUDE=-Ilib -common_test_CFLAGS =-Wall $(INCLUDE) $(GITVERSION_FLAGS) -common_test_CXXFLAGS =-Wall -std=c++11 $(INCLUDE) $(GITVERSION_FLAGS) -common_test_LDADD = -lpthread -common_test_SOURCES = src/main.cpp \ +odr_edi2edi_CFLAGS =-Wall $(INCLUDE) $(GITVERSION_FLAGS) +odr_edi2edi_CXXFLAGS =-Wall -std=c++11 $(INCLUDE) $(GITVERSION_FLAGS) +odr_edi2edi_LDADD = -lpthread +odr_edi2edi_SOURCES = src/main.cpp \ lib/crc.h lib/crc.c \ - lib/ClockTAI.h lib/ClockTAI.cpp \ lib/Globals.cpp \ lib/Log.h lib/Log.cpp \ lib/ReedSolomon.h lib/ReedSolomon.cpp \ @@ -23,16 +22,7 @@ common_test_SOURCES = src/main.cpp \ lib/RemoteControl.cpp \ lib/Socket.h lib/Socket.cpp \ lib/ThreadsafeQueue.h \ - lib/charset/charset.h lib/charset/charset.cpp \ - lib/charset/utf8.h \ - lib/charset/utf8/checked.h \ - lib/charset/utf8/core.h \ - lib/charset/utf8/unchecked.h \ lib/edi/PFT.hpp lib/edi/PFT.cpp \ - lib/edi/STIDecoder.hpp lib/edi/STIDecoder.cpp \ - lib/edi/STIWriter.hpp lib/edi/STIWriter.cpp \ - lib/edi/ETIDecoder.hpp lib/edi/ETIDecoder.cpp \ - lib/edi/eti.hpp lib/edi/eti.cpp \ lib/edi/buffer_unpack.hpp \ lib/edi/common.hpp lib/edi/common.cpp \ lib/edioutput/AFPacket.cpp \ diff --git a/bootstrap.sh b/bootstrap.sh new file mode 100755 index 0000000..a3394ab --- /dev/null +++ b/bootstrap.sh @@ -0,0 +1,4 @@ +#! /bin/sh + +autoreconf --install && \ + echo "You can call ./configure now" diff --git a/lib/edi/STIDecoder.cpp b/lib/edi/STIDecoder.cpp deleted file mode 100644 index d55cc12..0000000 --- a/lib/edi/STIDecoder.cpp +++ /dev/null @@ -1,226 +0,0 @@ -/* - Copyright (C) 2019 - Matthias P. Braendli, matthias.braendli@mpb.li - - http://opendigitalradio.org - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -#include "STIDecoder.hpp" -#include "buffer_unpack.hpp" -#include "crc.h" -#include "Log.h" -#include <cstdio> -#include <cassert> -#include <sstream> - -namespace EdiDecoder { - -using namespace std; - -STIDecoder::STIDecoder(STIDataCollector& data_collector, bool verbose) : - m_data_collector(data_collector), - m_dispatcher(std::bind(&STIDecoder::packet_completed, this), verbose) -{ - using std::placeholders::_1; - using std::placeholders::_2; - m_dispatcher.register_tag("*ptr", - std::bind(&STIDecoder::decode_starptr, this, _1, _2)); - m_dispatcher.register_tag("dsti", - std::bind(&STIDecoder::decode_dsti, this, _1, _2)); - m_dispatcher.register_tag("ss", - std::bind(&STIDecoder::decode_ssn, this, _1, _2)); - m_dispatcher.register_tag("*dmy", - std::bind(&STIDecoder::decode_stardmy, this, _1, _2)); - m_dispatcher.register_tag("ODRa", - std::bind(&STIDecoder::decode_odraudiolevel, this, _1, _2)); - m_dispatcher.register_tag("ODRv", - std::bind(&STIDecoder::decode_odrversion, this, _1, _2)); -} - -void STIDecoder::push_bytes(const vector<uint8_t> &buf) -{ - m_dispatcher.push_bytes(buf); -} - -void STIDecoder::push_packet(const vector<uint8_t> &buf) -{ - m_dispatcher.push_packet(buf); -} - -void STIDecoder::setMaxDelay(int num_af_packets) -{ - m_dispatcher.setMaxDelay(num_af_packets); -} - -#define AFPACKET_HEADER_LEN 10 // includes SYNC - -bool STIDecoder::decode_starptr(const vector<uint8_t> &value, uint16_t) -{ - if (value.size() != 0x40 / 8) { - etiLog.log(warn, "Incorrect length %02lx for *PTR", value.size()); - return false; - } - - char protocol_sz[5]; - protocol_sz[4] = '\0'; - copy(value.begin(), value.begin() + 4, protocol_sz); - string protocol(protocol_sz); - - uint16_t major = read_16b(value.begin() + 4); - uint16_t minor = read_16b(value.begin() + 6); - - m_data_collector.update_protocol(protocol, major, minor); - - return true; -} - -bool STIDecoder::decode_dsti(const vector<uint8_t> &value, uint16_t) -{ - size_t offset = 0; - - const uint16_t dstiHeader = read_16b(value.begin() + offset); - offset += 2; - - sti_management_data md; - - md.stihf = (dstiHeader >> 15) & 0x1; - md.atstf = (dstiHeader >> 14) & 0x1; - md.rfadf = (dstiHeader >> 13) & 0x1; - uint8_t dfcth = (dstiHeader >> 8) & 0x1F; - uint8_t dfctl = dstiHeader & 0xFF; - - md.dflc = dfcth * 250 + dfctl; // modulo 5000 counter - - const size_t expected_length = 2 + - (md.stihf ? 3 : 0) + - (md.atstf ? 1 + 4 + 3 : 0) + - (md.rfadf ? 9 : 0); - - if (value.size() != expected_length) { - throw std::runtime_error("EDI dsti: decoding error:" - "value.size() != expected_length: " + - to_string(value.size()) + " " + - to_string(expected_length)); - } - - if (md.stihf) { - const uint8_t stat = value[offset++]; - const uint16_t spid = read_16b(value.begin() + offset); - m_data_collector.update_stat(stat, spid); - offset += 2; - } - - if (md.atstf) { - uint8_t utco = value[offset]; - offset++; - - uint32_t seconds = read_32b(value.begin() + offset); - offset += 4; - - m_data_collector.update_edi_time(utco, seconds); - - md.tsta = read_24b(value.begin() + offset); - offset += 3; - } - else { - // Null timestamp, ETSI ETS 300 799, C.2.2 - md.tsta = 0xFFFFFF; - } - - - if (md.rfadf) { - std::array<uint8_t, 9> rfad; - copy(value.cbegin() + offset, - value.cbegin() + offset + 9, - rfad.begin()); - offset += 9; - - m_data_collector.update_rfad(rfad); - } - - m_data_collector.update_sti_management(md); - - return true; -} - -bool STIDecoder::decode_ssn(const vector<uint8_t> &value, uint16_t n) -{ - sti_payload_data sti; - - sti.stream_index = n - 1; // n is 1-indexed - sti.rfa = value[0] >> 3; - sti.tid = value[0] & 0x07; - - uint16_t istc = read_24b(value.begin() + 1); - sti.tidext = istc >> 13; - sti.crcstf = (istc >> 12) & 0x1; - sti.stid = istc & 0xFFF; - - if (sti.rfa != 0) { - etiLog.level(warn) << "EDI: rfa field in SSnn tag non-null"; - } - - copy( value.cbegin() + 3, - value.cend(), - back_inserter(sti.istd)); - - m_data_collector.add_payload(move(sti)); - - return true; -} - -bool STIDecoder::decode_stardmy(const vector<uint8_t>& /*value*/, uint16_t) -{ - return true; -} - -bool STIDecoder::decode_odraudiolevel(const vector<uint8_t>& value, uint16_t) -{ - constexpr size_t expected_length = 2 * sizeof(int16_t); - - audio_level_data audio_level; - - if (value.size() == expected_length) { - audio_level.left = read_16b(value.begin()); - audio_level.right = read_16b(value.begin() + 2); - } - else { - audio_level.left = 0; - audio_level.right = 0; - etiLog.level(warn) << "EDI: ODR AudioLevel TAG has wrong length!"; - } - - m_data_collector.update_audio_levels(audio_level); - - // Not being able to decode the audio level is a soft-failure, it should - // not disrupt decoding the actual audio data. - return true; -} - -bool STIDecoder::decode_odrversion(const vector<uint8_t>& value, uint16_t) -{ - const auto vd = parse_odr_version_data(value); - m_data_collector.update_odr_version(vd); - - return true; -} - -void STIDecoder::packet_completed() -{ - m_data_collector.assemble(); -} - -} diff --git a/lib/edi/STIDecoder.hpp b/lib/edi/STIDecoder.hpp deleted file mode 100644 index e2aa850..0000000 --- a/lib/edi/STIDecoder.hpp +++ /dev/null @@ -1,134 +0,0 @@ -/* - Copyright (C) 2019 - Matthias P. Braendli, matthias.braendli@mpb.li - - http://opendigitalradio.org - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -#pragma once - -#include "common.hpp" -#include <cstdint> -#include <deque> -#include <string> -#include <vector> -#include <array> - -namespace EdiDecoder { - -// Information for STI-D Management -struct sti_management_data { - bool stihf; - bool atstf; - bool rfadf; - uint16_t dflc; - - uint32_t tsta; -}; - -// Information for a subchannel available in EDI -struct sti_payload_data { - uint16_t stream_index; - uint8_t rfa; - uint8_t tid; - uint8_t tidext; - bool crcstf; - uint16_t stid; - std::vector<uint8_t> istd; - - // Return the length of ISTD in bytes - uint16_t stl(void) const { return istd.size(); } -}; - -struct audio_level_data { - int16_t left = 0; - int16_t right = 0; -}; - - -/* A class that receives STI data must implement the interface described - * in the STIDataCollector. This can be e.g. a converter to ETI, or something that - * prepares data structures for a modulator. - */ -class STIDataCollector { - public: - // 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( - const std::string& proto, - uint16_t major, - uint16_t minor) = 0; - - // STAT error field and service provider ID - virtual void update_stat(uint8_t stat, uint16_t spid) = 0; - - // In addition to TSTA in ETI, EDI also transports more time - // stamp information. - virtual void update_edi_time(uint32_t utco, uint32_t seconds) = 0; - - virtual void update_rfad(std::array<uint8_t, 9> rfad) = 0; - virtual void update_sti_management(const sti_management_data& data) = 0; - - virtual void add_payload(sti_payload_data&& payload) = 0; - - 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; -}; - -/* The STIDecoder takes care of decoding the EDI TAGs related to the transport - * of ETI(NI) data inside AF and PF packets. - * - * PF packets are handed over to the PFT decoder, which will in turn return - * AF packets. AF packets are directly handled (TAG extraction) here. - */ -class STIDecoder { - public: - STIDecoder(STIDataCollector& data_collector, bool verbose); - - /* Push bytes into the decoder. The buf can contain more - * than a single packet. This is useful when reading from streams - * (files, TCP) - */ - void push_bytes(const std::vector<uint8_t> &buf); - - /* Push a complete packet into the decoder. Useful for UDP and other - * datagram-oriented protocols. - */ - void push_packet(const std::vector<uint8_t> &buf); - - /* Set the maximum delay in number of AF Packets before we - * abandon decoding a given pseq. - */ - void setMaxDelay(int num_af_packets); - - private: - bool decode_starptr(const std::vector<uint8_t> &value, uint16_t); - bool decode_dsti(const std::vector<uint8_t> &value, uint16_t); - bool decode_ssn(const std::vector<uint8_t> &value, uint16_t n); - bool decode_stardmy(const std::vector<uint8_t> &value, uint16_t); - - bool decode_odraudiolevel(const std::vector<uint8_t> &value, uint16_t); - bool decode_odrversion(const std::vector<uint8_t> &value, uint16_t); - - void packet_completed(); - - STIDataCollector& m_data_collector; - TagDispatcher m_dispatcher; -}; - -} diff --git a/lib/edi/STIWriter.cpp b/lib/edi/STIWriter.cpp deleted file mode 100644 index a7e4f20..0000000 --- a/lib/edi/STIWriter.cpp +++ /dev/null @@ -1,142 +0,0 @@ -/* - Copyright (C) 2019 - Matthias P. Braendli, matthias.braendli@mpb.li - - http://opendigitalradio.org - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -#include "STIWriter.hpp" -#include "crc.h" -#include "Log.h" -#include <cstdio> -#include <cassert> -#include <stdexcept> -#include <sstream> -#include <ctime> -#include <iostream> -#include <iomanip> -#include <sstream> - -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, - uint16_t minor) -{ - m_proto_valid = (proto == "DSTI" and major == 0 and minor == 0); - - if (not m_proto_valid) { - throw std::invalid_argument("Wrong EDI protocol"); - } -} - - -void STIWriter::update_stat(uint8_t stat, uint16_t spid) -{ - m_stat = stat; - m_spid = spid; - m_stat_valid = true; - - if (m_stat != 0xFF) { - etiLog.log(warn, "STI errorlevel %02x", m_stat); - } -} - -void STIWriter::update_rfad(std::array<uint8_t, 9> rfad) -{ - (void)rfad; -} - -void STIWriter::update_sti_management(const sti_management_data& data) -{ - m_management_data = data; - m_management_data_valid = true; -} - -void STIWriter::add_payload(sti_payload_data&& payload) -{ - m_payload = move(payload); - m_payload_valid = true; -} - -void STIWriter::update_audio_levels(const audio_level_data& data) -{ - m_audio_levels = data; -} - -void STIWriter::update_odr_version(const odr_version_data& data) -{ - m_version_data = data; -} - -void STIWriter::update_edi_time( - uint32_t utco, - uint32_t seconds) -{ - if (not m_proto_valid) { - throw std::runtime_error("Cannot update time before protocol"); - } - - m_utco = utco; - m_seconds = seconds; - - // TODO check validity - m_time_valid = true; -} - - -void STIWriter::assemble() -{ - if (not m_proto_valid) { - throw std::runtime_error("Cannot assemble STI before protocol"); - } - - if (not m_management_data_valid) { - throw std::runtime_error("Cannot assemble STI before management data"); - } - - if (not m_payload_valid) { - throw std::runtime_error("Cannot assemble STI without frame data"); - } - - // TODO check time validity - - 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; - stiFrame.audio_levels = m_audio_levels; - stiFrame.version_data = m_version_data; - - m_frame_callback(move(stiFrame)); - - m_proto_valid = false; - m_management_data_valid = false; - m_stat_valid = false; - m_time_valid = false; - m_payload_valid = false; -} - -} diff --git a/lib/edi/STIWriter.hpp b/lib/edi/STIWriter.hpp deleted file mode 100644 index fc08e97..0000000 --- a/lib/edi/STIWriter.hpp +++ /dev/null @@ -1,90 +0,0 @@ -/* - Copyright (C) 2019 - Matthias P. Braendli, matthias.braendli@mpb.li - - http://opendigitalradio.org - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -#pragma once - -#include "common.hpp" -#include "STIDecoder.hpp" -#include <cstdint> -#include <functional> -#include <string> -#include <vector> -#include <list> - -namespace EdiDecoder { - -struct sti_frame_t { - std::vector<uint8_t> frame; - frame_timestamp_t timestamp; - audio_level_data audio_levels; - odr_version_data version_data; -}; - -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( - const std::string& proto, - uint16_t major, - uint16_t minor); - - virtual void update_stat(uint8_t stat, uint16_t spid); - - virtual void update_edi_time( - uint32_t utco, - uint32_t seconds); - - 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_audio_levels(const audio_level_data& data); - virtual void update_odr_version(const odr_version_data& data); - - virtual void assemble(void); - private: - std::function<void(sti_frame_t&&)> m_frame_callback; - - bool m_proto_valid = false; - - bool m_management_data_valid = false; - sti_management_data m_management_data; - - bool m_stat_valid = false; - uint8_t m_stat = 0; - uint16_t m_spid = 0; - - bool m_time_valid = false; - uint32_t m_utco = 0; - uint32_t m_seconds = 0; - - bool m_payload_valid = false; - sti_payload_data m_payload; - - audio_level_data m_audio_levels; - odr_version_data m_version_data; -}; - -} - |