aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore27
-rw-r--r--Makefile.am20
-rwxr-xr-xbootstrap.sh4
-rw-r--r--lib/edi/STIDecoder.cpp226
-rw-r--r--lib/edi/STIDecoder.hpp134
-rw-r--r--lib/edi/STIWriter.cpp142
-rw-r--r--lib/edi/STIWriter.hpp90
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;
-};
-
-}
-