aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt8
-rw-r--r--cmake/Modules/FindFec.cmake34
-rw-r--r--dabplussnoop.cpp19
-rw-r--r--etisnoop.cpp2
-rw-r--r--rsdecoder.cpp83
-rw-r--r--rsdecoder.h43
6 files changed, 181 insertions, 8 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8fbe524..8a0c139 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -25,7 +25,7 @@ set(VERSION_INFO_MAINT_VERSION git)
# Compiler specific setup
########################################################################
-set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -W -Wall")
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -W -Wall -std=c++11")
########################################################################
@@ -36,6 +36,9 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -W -Wall")
find_package(Faad REQUIRED)
include_directories(${FAAD_INCLUDE_DIRS})
+# libfec
+find_package(Fec REQUIRED)
+include_directories(${FEC_INCLUDE_DIRS})
########################################################################
# Setup apps
@@ -49,11 +52,12 @@ list(APPEND etisnoop_sources
wavfile.c
etiinput.cpp
etisnoop.cpp
+ rsdecoder.cpp
)
set_source_files_properties(${etisnoop_sources} PROPERTIES LANGUAGE "CXX")
add_executable(etisnoop ${etisnoop_sources})
-target_link_libraries(etisnoop ${FAAD_LIBRARIES})
+target_link_libraries(etisnoop ${FAAD_LIBRARIES} ${FEC_LIBRARIES})
install(TARGETS etisnoop DESTINATION bin)
diff --git a/cmake/Modules/FindFec.cmake b/cmake/Modules/FindFec.cmake
new file mode 100644
index 0000000..59dc525
--- /dev/null
+++ b/cmake/Modules/FindFec.cmake
@@ -0,0 +1,34 @@
+# Try to find FEC library and include path.
+# Once done this will define
+#
+# FEC_INCLUDE_DIRS - where to find fec.h, etc.
+# FEC_LIBRARIES - List of libraries when using libFEC.
+# FEC_FOUND - True if libFEC found.
+
+find_path(FEC_INCLUDE_DIR fec.h DOC "The directory where fec.h resides")
+find_library(FEC_LIBRARY NAMES fec DOC "The libFEC library")
+
+if(FEC_INCLUDE_DIR AND FEC_LIBRARY)
+ set(FEC_FOUND 1)
+ set(FEC_LIBRARIES ${FEC_LIBRARY})
+ set(FEC_INCLUDE_DIRS ${FEC_INCLUDE_DIR})
+else(FEC_INCLUDE_DIR AND FEC_LIBRARY)
+ set(FEC_FOUND 0)
+ set(FEC_LIBRARIES)
+ set(FEC_INCLUDE_DIRS)
+endif(FEC_INCLUDE_DIR AND FEC_LIBRARY)
+
+mark_as_advanced(FEC_INCLUDE_DIR)
+mark_as_advanced(FEC_LIBRARY)
+mark_as_advanced(FEC_FOUND)
+
+if(NOT FEC_FOUND)
+ set(FEC_DIR_MESSAGE "libfec was not found. Make sure FEC_LIBRARY and FEC_INCLUDE_DIR are set.")
+ if(NOT FEC_FIND_QUIETLY)
+ message(STATUS "${FEC_DIR_MESSAGE}")
+ else(NOT FEC_FIND_QUIETLY)
+ if(FEC_FIND_REQUIRED)
+ message(FATAL_ERROR "${FEC_DIR_MESSAGE}")
+ endif(FEC_FIND_REQUIRED)
+ endif(NOT FEC_FIND_QUIETLY)
+endif(NOT FEC_FOUND)
diff --git a/dabplussnoop.cpp b/dabplussnoop.cpp
index 2728a21..7073e7f 100644
--- a/dabplussnoop.cpp
+++ b/dabplussnoop.cpp
@@ -34,6 +34,7 @@
#include "firecode.h"
#include "lib_crc.h"
#include "faad_decoder.h"
+#include "rsdecoder.h"
#define DPS_INDENT "\t\t"
#define DPS_PREFIX "DAB+ decode:"
@@ -124,9 +125,17 @@ bool DabPlusSnoop::decode()
printf(DPS_PREFIX " We have %zu bytes of data\n", m_data.size());
#endif
- if (m_subchannel_index && m_data.size() >= m_subchannel_index * 120) {
+ const size_t sf_len = m_subchannel_index * 120;
+ if (m_subchannel_index && m_data.size() >= sf_len) {
+ std::vector<uint8_t> b(sf_len);
+ std::copy(m_data.begin(), m_data.begin() + sf_len, b.begin());
- uint8_t* b = &m_data[0];
+ RSDecoder rs_dec;
+ int rs_errors = rs_dec.DecodeSuperframe(b, m_subchannel_index);
+
+ if (rs_errors == -1) {
+ return false;
+ }
// -- Parse he_aac_super_frame
// ---- Parse he_aac_super_frame_header
@@ -171,7 +180,7 @@ bool DabPlusSnoop::decode()
// ------ Parse au_start
- b += 3;
+ auto au_starts = b.begin() + 3;
vector<uint8_t> au_start_nibbles(0);
@@ -179,12 +188,12 @@ bool DabPlusSnoop::decode()
* When we have n AUs, we have n-1 au_start values. */
for (int i = 0; i < (num_aus-1)*3; i++) {
if (i % 2 == 0) {
- char nibble = b[i/2] >> 4;
+ char nibble = au_starts[i/2] >> 4;
au_start_nibbles.push_back( nibble );
}
else {
- char nibble = b[i/2] & 0x0F;
+ char nibble = au_starts[i/2] & 0x0F;
au_start_nibbles.push_back( nibble );
}
diff --git a/etisnoop.cpp b/etisnoop.cpp
index 8f95455..9503e6f 100644
--- a/etisnoop.cpp
+++ b/etisnoop.cpp
@@ -596,7 +596,7 @@ int main(int argc, char *argv[])
switch (ch) {
case 'd':
{
- int subchix = atoi(optarg);
+ int subchix = atoi(optarg);
DabPlusSnoop dps;
streams_to_decode[subchix] = dps;
}
diff --git a/rsdecoder.cpp b/rsdecoder.cpp
new file mode 100644
index 0000000..f225bf6
--- /dev/null
+++ b/rsdecoder.cpp
@@ -0,0 +1,83 @@
+/*
+ Copyright (C) 2015 Stefan Pöschel
+
+ Copyright (C) 2015 Matthias P. Braendli (http://www.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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdexcept>
+#include "rsdecoder.h"
+
+RSDecoder::RSDecoder()
+{
+ rs_handle = init_rs_char(8, 0x11D, 0, 1, 10, 135);
+ if(!rs_handle)
+ throw std::runtime_error("RSDecoder: error while init_rs_char");
+}
+
+RSDecoder::~RSDecoder()
+{
+ free_rs_char(rs_handle);
+}
+
+int RSDecoder::DecodeSuperframe(std::vector<uint8_t> &sf, int subch_index)
+{
+ int total_corr_count = 0;
+ bool uncorr_errors = false;
+
+ std::vector<int> errors_per_index(subch_index);
+
+ // process all RS packets
+ for(int i = 0; i < subch_index; i++) {
+ for(int pos = 0; pos < 120; pos++)
+ rs_packet[pos] = sf[pos * subch_index + i];
+
+ // detect errors
+ int corr_count = decode_rs_char(rs_handle, rs_packet, corr_pos, 0);
+ errors_per_index[i] = corr_count;
+
+ if(corr_count == -1) {
+ uncorr_errors = true;
+ }
+ else {
+ total_corr_count += corr_count;
+ }
+
+ // correct errors
+ for(int j = 0; j < corr_count; j++) {
+
+ int pos = corr_pos[j] - 135;
+ if(pos < 0)
+ continue;
+
+ // fprintf(stderr, "j: %d, pos: %d, sf-index: %d\n", j, pos, pos * subch_index + i);
+ sf[pos * subch_index + i] = rs_packet[pos];
+ }
+ }
+
+ // output statistics
+ if (total_corr_count || uncorr_errors) {
+ printf("RS uncorrected errors:\n");
+ for (size_t i = 0; i < errors_per_index.size(); i++) {
+ int e = errors_per_index[i];
+ printf(" (%zu: %d)", i, e);
+ }
+ printf("\n");
+ }
+
+ return uncorr_errors ? -1 : total_corr_count;
+}
+
+
diff --git a/rsdecoder.h b/rsdecoder.h
new file mode 100644
index 0000000..ca97c91
--- /dev/null
+++ b/rsdecoder.h
@@ -0,0 +1,43 @@
+/*
+ Copyright (C) 2015 Stefan Pöschel
+
+ Copyright (C) 2015 Matthias P. Braendli (http://www.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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdint.h>
+#include <vector>
+
+extern "C" {
+#include <fec.h>
+}
+
+class RSDecoder {
+ private:
+ void *rs_handle;
+ uint8_t rs_packet[120];
+ int corr_pos[10];
+ public:
+ RSDecoder();
+ ~RSDecoder();
+
+ /* Correct errors using reed-solomon decoder.
+ * Returns number of errors corrected, or -1 if some errors could not
+ * be corrected
+ */
+ int DecodeSuperframe(std::vector<uint8_t> &sf, int subch_index);
+};
+
+